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