call_x86.cc revision 60d7a65f7fb60f502160a2e479e86014c7787553
1efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
2efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Copyright (C) 2012 The Android Open Source Project
3efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
4efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Licensed under the Apache License, Version 2.0 (the "License");
5efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * you may not use this file except in compliance with the License.
6efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * You may obtain a copy of the License at
7efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
8efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *      http://www.apache.org/licenses/LICENSE-2.0
9efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
10efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Unless required by applicable law or agreed to in writing, software
11efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * distributed under the License is distributed on an "AS IS" BASIS,
12efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See the License for the specific language governing permissions and
14efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * limitations under the License.
15efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
16efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
17efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* This file contains codegen for the X86 ISA */
18efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1902031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h"
207940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
21641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h"
221bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
23efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art {
24efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
25efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
26efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * The sparse table in the literal pool is an array of <key,displacement>
27efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * pairs.
28efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
290d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeevoid X86Mir2Lir::GenSparseSwitch(MIR* mir, DexOffset table_offset,
302ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                 RegLocation rl_src) {
311fd3346740dfb7f47be9922312b68a4227fada96buzbee  const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset;
321fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (cu_->verbose) {
3352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee    DumpSparseSwitchTable(table);
34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
35efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int entries = table[1];
360d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  const int32_t* keys = reinterpret_cast<const int32_t*>(&table[2]);
370d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  const int32_t* targets = &keys[entries];
381fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
39efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  for (int i = 0; i < entries; i++) {
40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    int key = keys[i];
41311ca169f4727d46a55bdc8dfa0059719fa72b65buzbee    BasicBlock* case_block =
421fd3346740dfb7f47be9922312b68a4227fada96buzbee        mir_graph_->FindBlock(current_dalvik_offset_ + targets[i]);
4300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    OpCmpImmBranch(kCondEq, rl_src.reg.GetReg(), key,
441fd3346740dfb7f47be9922312b68a4227fada96buzbee                   &block_label_list_[case_block->id]);
45efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
46efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
47efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
48efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
49efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Code pattern will look something like:
50efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
51fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * mov  r_val, ..
52efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * call 0
53fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * pop  r_start_of_method
54fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * sub  r_start_of_method, ..
55fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * mov  r_key_reg, r_val
56fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * sub  r_key_reg, low_key
57fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * cmp  r_key_reg, size-1  ; bound check
58efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * ja   done
59fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * mov  r_disp, [r_start_of_method + r_key_reg * 4 + table_offset]
60fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * add  r_start_of_method, r_disp
61fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * jmp  r_start_of_method
62efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * done:
63efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
640d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeevoid X86Mir2Lir::GenPackedSwitch(MIR* mir, DexOffset table_offset,
652ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrom                                 RegLocation rl_src) {
661fd3346740dfb7f47be9922312b68a4227fada96buzbee  const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset;
671fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (cu_->verbose) {
6852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee    DumpPackedSwitchTable(table);
69efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
70efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Add the table to the list - we'll process it later
710d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  SwitchTable* tab_rec =
7283cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko      static_cast<SwitchTable*>(arena_->Alloc(sizeof(SwitchTable), kArenaAllocData));
73fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  tab_rec->table = table;
741fd3346740dfb7f47be9922312b68a4227fada96buzbee  tab_rec->vaddr = current_dalvik_offset_;
75efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int size = table[1];
76f6c4b3ba3825de1dbb3e747a68b809c6cc8eb4dbMathieu Chartier  tab_rec->targets = static_cast<LIR**>(arena_->Alloc(size * sizeof(LIR*),
7783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko                                                      kArenaAllocLIR));
78862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  switch_tables_.Insert(tab_rec);
79efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
80efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Get the switch value
811fd3346740dfb7f47be9922312b68a4227fada96buzbee  rl_src = LoadValue(rl_src, kCoreReg);
827934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom  // NewLIR0(kX86Bkpt);
8367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
8467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // Materialize a pointer to the switch table
8567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  int start_of_method_reg;
8667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  if (base_of_code_ != nullptr) {
8767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    // We can use the saved value.
8867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low);
8967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    rl_method = LoadValue(rl_method, kCoreReg);
9000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    start_of_method_reg = rl_method.reg.GetReg();
9155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell    store_method_addr_used_ = true;
9267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  } else {
9367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    start_of_method_reg = AllocTemp();
9467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    NewLIR1(kX86StartOfMethod, start_of_method_reg);
9567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
96fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int low_key = s4FromSwitchData(&table[2]);
97efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  int keyReg;
98efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Remove the bias, if necessary
99fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (low_key == 0) {
10000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    keyReg = rl_src.reg.GetReg();
101efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
1021fd3346740dfb7f47be9922312b68a4227fada96buzbee    keyReg = AllocTemp();
10300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee    OpRegRegImm(kOpSub, keyReg, rl_src.reg.GetReg(), low_key);
104efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
105efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Bounds check - if < 0 or >= size continue following switch
1061fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegImm(kOpCmp, keyReg, size-1);
1071fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch_over = OpCondBranch(kCondHi, NULL);
108efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
109efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Load the displacement from the switch table
1101fd3346740dfb7f47be9922312b68a4227fada96buzbee  int disp_reg = AllocTemp();
1110d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  NewLIR5(kX86PcRelLoadRA, disp_reg, start_of_method_reg, keyReg, 2, WrapPointer(tab_rec));
112efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Add displacement to start of method
1131fd3346740dfb7f47be9922312b68a4227fada96buzbee  OpRegReg(kOpAdd, start_of_method_reg, disp_reg);
114efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // ..and go!
1151fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* switch_branch = NewLIR1(kX86JmpR, start_of_method_reg);
116fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  tab_rec->anchor = switch_branch;
117efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
118fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  /* branch_over target here */
1191fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* target = NewLIR0(kPseudoTargetLabel);
120fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  branch_over->target = target;
121efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
122efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
123efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
124efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Array data table format:
125efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *  ushort ident = 0x0300   magic value
126efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *  ushort width            width of each element in the table
127efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *  uint   size             number of elements in the table
128efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *  ubyte  data[size*width] table of data values (may contain a single-byte
129efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *                          padding at the end)
130efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
131efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Total size is 4+(width * size + 1)/2 16-bit code units.
132efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
1330d82948094d9a198e01aa95f64012bdedd5b6fc9buzbeevoid X86Mir2Lir::GenFillArrayData(DexOffset table_offset, RegLocation rl_src) {
1341fd3346740dfb7f47be9922312b68a4227fada96buzbee  const uint16_t* table = cu_->insns + current_dalvik_offset_ + table_offset;
135efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Add the table to the list - we'll process it later
1360d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  FillArrayData* tab_rec =
13783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko      static_cast<FillArrayData*>(arena_->Alloc(sizeof(FillArrayData), kArenaAllocData));
138fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  tab_rec->table = table;
1391fd3346740dfb7f47be9922312b68a4227fada96buzbee  tab_rec->vaddr = current_dalvik_offset_;
140fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  uint16_t width = tab_rec->table[1];
141fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  uint32_t size = tab_rec->table[2] | ((static_cast<uint32_t>(tab_rec->table[3])) << 16);
142fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  tab_rec->size = (size * width) + 8;
143efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
144862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee  fill_array_data_.Insert(tab_rec);
145efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
146efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Making a call - use explicit registers
1471fd3346740dfb7f47be9922312b68a4227fada96buzbee  FlushAllRegs();   /* Everything to home location */
1481fd3346740dfb7f47be9922312b68a4227fada96buzbee  LoadValueDirectFixed(rl_src, rX86_ARG0);
149efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Materialize a pointer to the fill data image
15067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  if (base_of_code_ != nullptr) {
15167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    // We can use the saved value.
15267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low);
15367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    LoadValueDirect(rl_method, rX86_ARG2);
15455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell    store_method_addr_used_ = true;
15567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  } else {
15667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    NewLIR1(kX86StartOfMethod, rX86_ARG2);
15767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
1580d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee  NewLIR2(kX86PcRelAdr, rX86_ARG1, WrapPointer(tab_rec));
1591fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kX86Add32RR, rX86_ARG1, rX86_ARG2);
160468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CallRuntimeHelperRegReg(QUICK_ENTRYPOINT_OFFSET(pHandleFillArrayData), rX86_ARG0,
161cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee                          rX86_ARG1, true);
162efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
163efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1642ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenMoveException(RegLocation rl_dest) {
1651eab958cde39a7e2f0e5ce01730f4e2e75c72519jeffhao  int ex_offset = Thread::ExceptionOffset().Int32Value();
1661fd3346740dfb7f47be9922312b68a4227fada96buzbee  RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true);
16700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  NewLIR2(kX86Mov32RT, rl_result.reg.GetReg(), ex_offset);
1681fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kX86Mov32TI, ex_offset, 0);
1691fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreValue(rl_dest, rl_result);
1701eab958cde39a7e2f0e5ce01730f4e2e75c72519jeffhao}
1711eab958cde39a7e2f0e5ce01730f4e2e75c72519jeffhao
172efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
173efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Mark garbage collection card. Skip if the value we're storing is null.
174efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
1752ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::MarkGCCard(int val_reg, int tgt_addr_reg) {
1761fd3346740dfb7f47be9922312b68a4227fada96buzbee  int reg_card_base = AllocTemp();
1771fd3346740dfb7f47be9922312b68a4227fada96buzbee  int reg_card_no = AllocTemp();
1781fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, NULL);
1791fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR2(kX86Mov32RT, reg_card_base, Thread::CardTableOffset().Int32Value());
1801d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  OpRegRegImm(kOpLsr, reg_card_no, tgt_addr_reg, gc::accounting::CardTable::kCardShift);
1811fd3346740dfb7f47be9922312b68a4227fada96buzbee  StoreBaseIndexed(reg_card_base, reg_card_no, reg_card_base, 0,
182efc6369224b036a1fb77849f7ae65b3492c832c0buzbee                   kUnsignedByte);
1831fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* target = NewLIR0(kPseudoTargetLabel);
184fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  branch_over->target = target;
1851fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(reg_card_base);
1861fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(reg_card_no);
187efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
188efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1892ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenEntrySequence(RegLocation* ArgLocs, RegLocation rl_method) {
190efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  /*
191efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * On entry, rX86_ARG0, rX86_ARG1, rX86_ARG2 are live.  Let the register
192efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * allocation mechanism know so it doesn't try to use any of them when
193efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * expanding the frame or flushing.  This leaves the utility
194efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * code with no spare temps.
195efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   */
1961fd3346740dfb7f47be9922312b68a4227fada96buzbee  LockTemp(rX86_ARG0);
1971fd3346740dfb7f47be9922312b68a4227fada96buzbee  LockTemp(rX86_ARG1);
1981fd3346740dfb7f47be9922312b68a4227fada96buzbee  LockTemp(rX86_ARG2);
199efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
200efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  /* Build frame, return address already on stack */
20160d7a65f7fb60f502160a2e479e86014c7787553Brian Carlstrom  // TODO: 64 bit.
202ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  stack_decrement_ = OpRegImm(kOpSub, rX86_SP, frame_size_ - 4);
203efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
204efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  /*
205efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * We can safely skip the stack overflow check if we're
206efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * a leaf *and* our frame size < fudge factor.
207efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   */
20860d7a65f7fb60f502160a2e479e86014c7787553Brian Carlstrom  const bool skip_overflow_check = (mir_graph_->MethodIsLeaf() &&
20960d7a65f7fb60f502160a2e479e86014c7787553Brian Carlstrom      (static_cast<size_t>(frame_size_) < Thread::kStackOverflowReservedBytes));
2101fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kPseudoMethodEntry);
211efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  /* Spill core callee saves */
2121fd3346740dfb7f47be9922312b68a4227fada96buzbee  SpillCoreRegs();
213efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  /* NOTE: promotion of FP regs currently unsupported, thus no FP spill */
2141fd3346740dfb7f47be9922312b68a4227fada96buzbee  DCHECK_EQ(num_fp_spills_, 0);
215fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (!skip_overflow_check) {
216efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    // cmp rX86_SP, fs:[stack_end_]; jcc throw_launchpad
2171fd3346740dfb7f47be9922312b68a4227fada96buzbee    LIR* tgt = RawLIR(0, kPseudoThrowTarget, kThrowStackOverflow, 0, 0, 0, 0);
218468532ea115657709bc32ee498e701a4c71762d4Ian Rogers    OpRegThreadMem(kOpCmp, rX86_SP, Thread::StackEndOffset());
2191fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpCondBranch(kCondUlt, tgt);
220efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    // Remember branch target - will process later
221862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee    throw_launchpads_.Insert(tgt);
222efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
223efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
2241fd3346740dfb7f47be9922312b68a4227fada96buzbee  FlushIns(ArgLocs, rl_method);
225efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
22667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  if (base_of_code_ != nullptr) {
22767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    // We have been asked to save the address of the method start for later use.
22855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell    setup_method_address_[0] = NewLIR1(kX86StartOfMethod, rX86_ARG0);
22967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    int displacement = SRegOffset(base_of_code_->s_reg_low);
23055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell    setup_method_address_[1] = StoreBaseDisp(rX86_SP, displacement, rX86_ARG0, kWord);
23167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
23267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
2331fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(rX86_ARG0);
2341fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(rX86_ARG1);
2351fd3346740dfb7f47be9922312b68a4227fada96buzbee  FreeTemp(rX86_ARG2);
236efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
237efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
2381fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::GenExitSequence() {
239efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  /*
240efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * In the exit path, rX86_RET0/rX86_RET1 are live - make sure they aren't
241efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * allocated by the register utilities as temps.
242efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   */
2431fd3346740dfb7f47be9922312b68a4227fada96buzbee  LockTemp(rX86_RET0);
2441fd3346740dfb7f47be9922312b68a4227fada96buzbee  LockTemp(rX86_RET1);
245efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
2461fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kPseudoMethodExit);
2471fd3346740dfb7f47be9922312b68a4227fada96buzbee  UnSpillCoreRegs();
248efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  /* Remove frame except for return address */
249ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  stack_increment_ = OpRegImm(kOpAdd, rX86_SP, frame_size_ - 4);
2501fd3346740dfb7f47be9922312b68a4227fada96buzbee  NewLIR0(kX86Ret);
251efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
252efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
2533bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoruvoid X86Mir2Lir::GenSpecialExitSequence() {
2543bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru  NewLIR0(kX86Ret);
2553bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru}
2563bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru
257efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}  // namespace art
258