target_x86.cc revision 091cc408e9dc87e60fb64c61e186bea568fc3d3a
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 17f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray#include <string> 18f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray#include <inttypes.h> 19f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray 2002031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h" 217940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/compiler_internals.h" 227940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h" 23e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell#include "mirror/array.h" 24e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell#include "mirror/string.h" 25641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h" 26efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 27efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art { 28efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 29091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const RegStorage core_regs_arr[] = { 30091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP, rs_rBP, rs_rSI, rs_rDI 31efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#ifdef TARGET_REX_SUPPORT 32091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_r8, rs_r9, rs_r10, rs_r11, rs_r12, rs_r13, rs_r14, rs_r15 33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 35091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const RegStorage sp_regs_arr[] = { 36091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 37efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#ifdef TARGET_REX_SUPPORT 38091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 39efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 41091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const RegStorage dp_regs_arr[] = { 42091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 43efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#ifdef TARGET_REX_SUPPORT 44091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 45efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 46efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 47091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const RegStorage reserved_regs_arr[] = {rs_rX86_SP}; 48091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const RegStorage core_temps_arr[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX}; 49091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const RegStorage sp_temps_arr[] = { 50091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 51091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee#ifdef TARGET_REX_SUPPORT 52091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 53091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee#endif 54091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 55091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const RegStorage dp_temps_arr[] = { 56091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 57091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee#ifdef TARGET_REX_SUPPORT 58091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 59091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee#endif 60091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 61091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 62091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const std::vector<RegStorage> core_regs(core_regs_arr, 63091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee core_regs_arr + sizeof(core_regs_arr) / sizeof(core_regs_arr[0])); 64091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const std::vector<RegStorage> sp_regs(sp_regs_arr, 65091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee sp_regs_arr + sizeof(sp_regs_arr) / sizeof(sp_regs_arr[0])); 66091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const std::vector<RegStorage> dp_regs(dp_regs_arr, 67091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee dp_regs_arr + sizeof(dp_regs_arr) / sizeof(dp_regs_arr[0])); 68091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const std::vector<RegStorage> reserved_regs(reserved_regs_arr, 69091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reserved_regs_arr + sizeof(reserved_regs_arr) / sizeof(reserved_regs_arr[0])); 70091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const std::vector<RegStorage> core_temps(core_temps_arr, 71091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee core_temps_arr + sizeof(core_temps_arr) / sizeof(core_temps_arr[0])); 72091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const std::vector<RegStorage> sp_temps(sp_temps_arr, 73091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee sp_temps_arr + sizeof(sp_temps_arr) / sizeof(sp_temps_arr[0])); 74091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeestatic const std::vector<RegStorage> dp_temps(dp_temps_arr, 75091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee dp_temps_arr + sizeof(dp_temps_arr) / sizeof(dp_temps_arr[0])); 76efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 772ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturn() { 7800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return; 79efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 80efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 812ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnWide() { 8200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_wide; 83efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 84efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 852ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnFloat() { 8600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_float; 87efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 88efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 892ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnDouble() { 9000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_double; 91efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 92efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 93efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Return a target-dependent special register. 942700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeRegStorage X86Mir2Lir::TargetReg(SpecialTargetRegister reg) { 95091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage res_reg = RegStorage::InvalidReg(); 96efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (reg) { 97091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSelf: res_reg = RegStorage::InvalidReg(); break; 98091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSuspend: res_reg = RegStorage::InvalidReg(); break; 99091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kLr: res_reg = RegStorage::InvalidReg(); break; 100091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kPc: res_reg = RegStorage::InvalidReg(); break; 101091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSp: res_reg = rs_rX86_SP; break; 102091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg0: res_reg = rs_rX86_ARG0; break; 103091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg1: res_reg = rs_rX86_ARG1; break; 104091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg2: res_reg = rs_rX86_ARG2; break; 105091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg3: res_reg = rs_rX86_ARG3; break; 106091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg0: res_reg = rs_rX86_FARG0; break; 107091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg1: res_reg = rs_rX86_FARG1; break; 108091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg2: res_reg = rs_rX86_FARG2; break; 109091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg3: res_reg = rs_rX86_FARG3; break; 110091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kRet0: res_reg = rs_rX86_RET0; break; 111091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kRet1: res_reg = rs_rX86_RET1; break; 112091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kInvokeTgt: res_reg = rs_rX86_INVOKE_TGT; break; 113091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kHiddenArg: res_reg = rs_rAX; break; 114091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kHiddenFpArg: res_reg = rs_fr0; break; 115091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kCount: res_reg = rs_rX86_COUNT; break; 116091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee } 117091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee return res_reg; 118efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 119efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1202700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeRegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) { 1213bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru // For the 32-bit internal ABI, the first 3 arguments are passed in registers. 1223bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru // TODO: This is not 64-bit compliant and depends on new internal ABI. 1233bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru switch (arg_num) { 1243bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru case 0: 1252700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return rs_rX86_ARG1; 1263bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru case 1: 1272700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return rs_rX86_ARG2; 1283bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru case 2: 1292700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return rs_rX86_ARG3; 1303bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru default: 1312700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return RegStorage::InvalidReg(); 1323bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru } 1333bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru} 1343bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru 135efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 136efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Decode the register id. 137efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 138091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeeuint64_t X86Mir2Lir::GetRegMaskCommon(RegStorage reg) { 139eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint64_t seed; 140efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int shift; 141fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int reg_id; 142efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 143091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_id = reg.GetRegNum(); 144efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Double registers in x86 are just a single FP register */ 145efc6369224b036a1fb77849f7ae65b3492c832c0buzbee seed = 1; 146efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* FP register starts at bit position 16 */ 147091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee shift = reg.IsFloat() ? kX86FPReg0 : 0; 148efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Expand the double register id into single offset */ 149fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee shift += reg_id; 150efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return (seed << shift); 151efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 152efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1532ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t X86Mir2Lir::GetPCUseDefEncoding() { 154efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* 155efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * FIXME: might make sense to use a virtual resource encoding bit for pc. Might be 156efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * able to clean up some of the x86/Arm_Mips differences 157efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 15852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Unexpected call to GetPCUseDefEncoding for x86"; 159efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return 0ULL; 160efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 161efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 162b48819db07f9a0992a72173380c24249d7fc648abuzbeevoid X86Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) { 1636a58cb16d803c9a7b3a75ccac8be19dd9d4e520dDmitry Petrochenko DCHECK(cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64); 164b48819db07f9a0992a72173380c24249d7fc648abuzbee DCHECK(!lir->flags.use_def_invalid); 165efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 166efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // X86-specific resource map setup here. 167efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USE_SP) { 168b48819db07f9a0992a72173380c24249d7fc648abuzbee lir->u.m.use_mask |= ENCODE_X86_REG_SP; 169efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 170efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 171efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEF_SP) { 172b48819db07f9a0992a72173380c24249d7fc648abuzbee lir->u.m.def_mask |= ENCODE_X86_REG_SP; 173efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 174efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 175efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFA) { 176091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.def_mask, rs_rAX.GetReg()); 177efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 178efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 179efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFD) { 180091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.def_mask, rs_rDX.GetReg()); 181efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 182efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEA) { 183091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rAX.GetReg()); 184efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 185efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 186efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEC) { 187091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rCX.GetReg()); 188efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 189efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 190efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USED) { 191091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rDX.GetReg()); 192efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 19370b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko 19470b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko if (flags & REG_USEB) { 195091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rBX.GetReg()); 19670b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko } 1974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 1984028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Fixup hard to describe instruction: Uses rAX, rCX, rDI; sets rDI. 1994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (lir->opcode == kX86RepneScasw) { 200091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rAX.GetReg()); 201091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rCX.GetReg()); 202091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rDI.GetReg()); 203091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.def_mask, rs_rDI.GetReg()); 2044028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 205e90501da0222717d75c126ebf89569db3976927eSerguei Katkov 206e90501da0222717d75c126ebf89569db3976927eSerguei Katkov if (flags & USE_FP_STACK) { 207e90501da0222717d75c126ebf89569db3976927eSerguei Katkov lir->u.m.use_mask |= ENCODE_X86_FP_STACK; 208e90501da0222717d75c126ebf89569db3976927eSerguei Katkov lir->u.m.def_mask |= ENCODE_X86_FP_STACK; 209e90501da0222717d75c126ebf89569db3976927eSerguei Katkov } 210efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 211efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 212efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* For dumping instructions */ 213efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86RegName[] = { 214efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 215efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 216efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 217efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 218efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86CondName[] = { 219efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "O", 220efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NO", 221efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "B/NAE/C", 222efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NB/AE/NC", 223efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "Z/EQ", 224efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NZ/NE", 225efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "BE/NA", 226efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NBE/A", 227efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "S", 228efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NS", 229efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "P/PE", 230efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NP/PO", 231efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "L/NGE", 232efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NL/GE", 233efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "LE/NG", 234efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NLE/G" 235efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 236efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 237efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 238efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Interpret a format string and build a string no longer than size 239efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See format key in Assemble.cc. 240efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 2411fd3346740dfb7f47be9922312b68a4227fada96buzbeestd::string X86Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) { 242efc6369224b036a1fb77849f7ae65b3492c832c0buzbee std::string buf; 243efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t i = 0; 244efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t fmt_len = strlen(fmt); 245efc6369224b036a1fb77849f7ae65b3492c832c0buzbee while (i < fmt_len) { 246efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (fmt[i] != '!') { 247efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += fmt[i]; 248efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 249efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 250efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 251efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 252efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char operand_number_ch = fmt[i]; 253efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 254efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (operand_number_ch == '!') { 255efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += "!"; 256efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 257efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand_number = operand_number_ch - '0'; 258efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(operand_number, 6); // Expect upto 6 LIR operands. 259efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 260efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand = lir->operands[operand_number]; 261efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (fmt[i]) { 262efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'c': 263efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(static_cast<size_t>(operand), sizeof(x86CondName)); 264efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += x86CondName[operand]; 265efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 266efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'd': 267efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("%d", operand); 268efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 269efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'p': { 2700d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(operand)); 271fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee buf += StringPrintf("0x%08x", tab_rec->offset); 272efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 273efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 274efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'r': 275091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (RegStorage::IsFloat(operand)) { 276091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int fp_reg = RegStorage::RegNum(operand); 277efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("xmm%d", fp_reg); 278efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 279091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int reg_num = RegStorage::RegNum(operand); 280091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK_LT(static_cast<size_t>(reg_num), sizeof(x86RegName)); 281091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee buf += x86RegName[reg_num]; 282efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 283efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 284efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 't': 285107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers buf += StringPrintf("0x%08" PRIxPTR " (L%p)", 286107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers reinterpret_cast<uintptr_t>(base_addr) + lir->offset + operand, 287107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers lir->target); 288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee default: 290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("DecodeError '%c'", fmt[i]); 291efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 292efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 297efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return buf; 298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3002ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::DumpResourceMask(LIR *x86LIR, uint64_t mask, const char *prefix) { 301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char buf[256]; 302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf[0] = 0; 303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 304efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask == ENCODE_ALL) { 305efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcpy(buf, "all"); 306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char num[8]; 308efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int i; 309efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (i = 0; i < kX86RegEnd; i++) { 311efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & (1ULL << i)) { 312988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(num, arraysize(num), "%d ", i); 313efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, num); 314efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 315efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 316efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 317efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & ENCODE_CCODE) { 318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "cc "); 319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 320efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Memory bits */ 321efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (x86LIR && (mask & ENCODE_DALVIK_REG)) { 322988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s", 323988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers DECODE_ALIAS_INFO_REG(x86LIR->flags.alias_info), 324988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers (DECODE_ALIAS_INFO_WIDE(x86LIR->flags.alias_info)) ? "(+1)" : ""); 325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & ENCODE_LITERAL) { 327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "lit "); 328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & ENCODE_HEAP_REF) { 331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "heap "); 332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 333efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & ENCODE_MUST_NOT_ALIAS) { 334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "noalias "); 335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (buf[0]) { 338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(INFO) << prefix << ": " << buf; 339efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 34102031b185b4653e6c72e21f7a51238b903f6d638buzbee 3421fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::AdjustSpillMask() { 343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Adjustment for LR spilling, x86 has no LR so nothing to do here 344091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee core_spill_mask_ |= (1 << rs_rRET.GetRegNum()); 3451fd3346740dfb7f47be9922312b68a4227fada96buzbee num_core_spills_++; 346efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 349efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Mark a callee-save fp register as promoted. Note that 350efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * vpush/vpop uses contiguous register lists so we must 351efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * include any holes in the mask. Associate holes with 352efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Dalvik register INVALID_VREG (0xFFFFU). 353efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 354091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeevoid X86Mir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) { 355091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee UNIMPLEMENTED(FATAL) << "MarkPreservedSingle"; 356efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 357efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 358091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeevoid X86Mir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) { 359091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee UNIMPLEMENTED(FATAL) << "MarkPreservedDouble"; 3602700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee} 3612700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee 362efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Clobber all regs that might be used by an external C call */ 36331c2aac7137b69d5622eea09597500731fbee2efVladimir Markovoid X86Mir2Lir::ClobberCallerSave() { 364091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rAX); 365091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rCX); 366091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 367091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rBX); 368efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 369efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3701fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation X86Mir2Lir::GetReturnWideAlt() { 37152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturnWide(); 372091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(res.reg.GetLowReg() == rs_rAX.GetReg()); 373091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(res.reg.GetHighReg() == rs_rDX.GetReg()); 374091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rAX); 375091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 376091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rAX); 377091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 378091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkWide(res.reg); 379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 381efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3822ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::GetReturnAlt() { 38352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturn(); 384091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee res.reg.SetReg(rs_rDX.GetReg()); 385091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 386091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 387efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 388efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 389efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 3912ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::LockCallTemps() { 392091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG0); 393091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG1); 394091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG2); 395091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG3); 396efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 397efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 3992ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::FreeCallTemps() { 400091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG0); 401091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG1); 402091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG2); 403091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG3); 404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 40699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusorubool X86Mir2Lir::ProvidesFullMemoryBarrier(X86OpCode opcode) { 40799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru switch (opcode) { 40899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgMR: 40999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgAR: 41099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchg8bM: 41199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchg8bA: 41299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86XchgMR: 41399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86Mfence: 41499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Atomic memory instructions provide full barrier. 41599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return true; 41699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru default: 41799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru break; 41899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 41999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 42099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Conservative if cannot prove it provides full barrier. 42199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return false; 42299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru} 42399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 4242ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) { 425efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0 42699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Start off with using the last LIR as the barrier. If it is not enough, then we will update it. 42799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru LIR* mem_barrier = last_lir_insn_; 42899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 42999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru /* 43099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru * According to the JSR-133 Cookbook, for x86 only StoreLoad barriers need memory fence. All other barriers 43199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru * (LoadLoad, LoadStore, StoreStore) are nops due to the x86 memory model. For those cases, all we need 43299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru * to ensure is that there is a scheduling barrier in place. 43399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru */ 43499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (barrier_kind == kStoreLoad) { 43599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If no LIR exists already that can be used a barrier, then generate an mfence. 43699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 43799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 43899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 43999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 44099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If last instruction does not provide full barrier, then insert an mfence. 44199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (ProvidesFullMemoryBarrier(static_cast<X86OpCode>(mem_barrier->opcode)) == false) { 44299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 44399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 44499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 44599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 44699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Now ensure that a scheduling barrier is in place. 44799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 44899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru GenBarrier(); 44999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } else { 45099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Mark as a scheduling barrier. 45199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru DCHECK(!mem_barrier->flags.use_def_invalid); 45299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier->u.m.def_mask = ENCODE_ALL; 45399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 454efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 455efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 45600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee 45700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee// Alloc a pair of core registers, or a double. 45800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill BuzbeeRegStorage X86Mir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) { 459fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { 4602700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return AllocTempDouble(); 461efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 4622700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage low_reg = AllocTemp(); 4632700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage high_reg = AllocTemp(); 4642700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return RegStorage::MakeRegPair(low_reg, high_reg); 465efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 466efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4672700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeRegStorage X86Mir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) { 468fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { 469091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee return AllocTempSingle(); 470efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 4711fd3346740dfb7f47be9922312b68a4227fada96buzbee return AllocTemp(); 472efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 473efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4741fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::CompilerInitializeRegAlloc() { 475091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs, sp_regs, dp_regs, reserved_regs, 476091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee core_temps, sp_temps, dp_temps); 477091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 478091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Target-specific adjustments. 479091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 480091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Alias single precision xmm to double xmms. 481091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: as needed, add larger vector sizes - alias all to the largest. 482091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee GrowableArray<RegisterInfo*>::Iterator it(®_pool_->sp_regs_); 483091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) { 484091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int sp_reg_num = info->GetReg().GetRegNum(); 485091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | sp_reg_num); 486091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegisterInfo* dp_reg_info = GetRegInfo(dp_reg); 487091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // 64-bit xmm vector register's master storage should refer to itself. 488091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK_EQ(dp_reg_info, dp_reg_info->Master()); 489091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Redirect 32-bit vector's master storage to 64-bit vector. 490091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee info->SetMaster(dp_reg_info); 491efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 492091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 493091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods. 494091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: adjust for x86/hard float calling convention. 495091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_core_reg_ = 2; 496091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_sp_reg_ = 2; 497091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_dp_reg_ = 1; 498efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 499efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5002700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeevoid X86Mir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) { 5012700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee DCHECK(rl_keep.wide); 5022700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee DCHECK(rl_free.wide); 5032700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int free_low = rl_free.reg.GetLowReg(); 5042700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int free_high = rl_free.reg.GetHighReg(); 5052700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int keep_low = rl_keep.reg.GetLowReg(); 5062700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int keep_high = rl_keep.reg.GetHighReg(); 5072700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee if ((free_low != keep_low) && (free_low != keep_high) && 5082700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee (free_high != keep_low) && (free_high != keep_high)) { 509efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // No overlap, free both 510091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rl_free.reg); 511efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 512efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 513efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5141fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::SpillCoreRegs() { 5151fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_core_spills_ == 0) { 516efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 517efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 518efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Spill mask not including fake return address register 519091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 5201fd3346740dfb7f47be9922312b68a4227fada96buzbee int offset = frame_size_ - (4 * num_core_spills_); 521efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (int reg = 0; mask; mask >>= 1, reg++) { 522efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & 0x1) { 5232700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee StoreWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg)); 524efc6369224b036a1fb77849f7ae65b3492c832c0buzbee offset += 4; 525efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 526efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 527efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 528efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5291fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::UnSpillCoreRegs() { 5301fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_core_spills_ == 0) { 531efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 532efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 533efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Spill mask not including fake return address register 534091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 5351fd3346740dfb7f47be9922312b68a4227fada96buzbee int offset = frame_size_ - (4 * num_core_spills_); 536efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (int reg = 0; mask; mask >>= 1, reg++) { 537efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & 0x1) { 5382700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg)); 539efc6369224b036a1fb77849f7ae65b3492c832c0buzbee offset += 4; 540efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 541efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 542efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 543efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5442ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::IsUnconditionalBranch(LIR* lir) { 545cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32); 546efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 547efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 548862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeX86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena) 54955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell : Mir2Lir(cu, mir_graph, arena), 550dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers base_of_code_(nullptr), store_method_addr_(false), store_method_addr_used_(false), 55155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell method_address_insns_(arena, 100, kGrowableArrayMisc), 55255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell class_type_address_insns_(arena, 100, kGrowableArrayMisc), 553ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell call_method_insns_(arena, 100, kGrowableArrayMisc), 554ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell stack_decrement_(nullptr), stack_increment_(nullptr) { 555dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (kIsDebugBuild) { 556dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers for (int i = 0; i < kX86Last; i++) { 557dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (X86Mir2Lir::EncodingMap[i].opcode != i) { 558dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers LOG(FATAL) << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name 559dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers << " is wrong: expecting " << i << ", seeing " 560dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode); 561dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers } 562efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 563efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 5641fd3346740dfb7f47be9922312b68a4227fada96buzbee} 5651fd3346740dfb7f47be9922312b68a4227fada96buzbee 566862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 567862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee ArenaAllocator* const arena) { 568862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee return new X86Mir2Lir(cu, mir_graph, arena); 569efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 570efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 571efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Not used in x86 572dd7624d2b9e599d57762d12031b10b89defc9807Ian RogersRegStorage X86Mir2Lir::LoadHelper(ThreadOffset<4> offset) { 57352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Unexpected use of LoadHelper in x86"; 5742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return RegStorage::InvalidReg(); 575efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 576efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 577b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave AllisonLIR* X86Mir2Lir::CheckSuspendUsingLoad() { 578b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison LOG(FATAL) << "Unexpected use of CheckSuspendUsingLoad in x86"; 579b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison return nullptr; 580b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison} 581b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison 5822ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t X86Mir2Lir::GetTargetInstFlags(int opcode) { 583409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 5841fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].flags; 5851bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 5861bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 5872ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstName(int opcode) { 588409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 5891fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].name; 5901bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 5911bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 5922ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstFmt(int opcode) { 593409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 5941fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].fmt; 5951bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 5961bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 597d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbeevoid X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) { 598d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Can we do this directly to memory? 599d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee rl_dest = UpdateLocWide(rl_dest); 600d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee if ((rl_dest.location == kLocDalvikFrame) || 601d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee (rl_dest.location == kLocCompilerTemp)) { 602d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_lo = Low32Bits(value); 603d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_hi = High32Bits(value); 6042700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int r_base = TargetReg(kSp).GetReg(); 605d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int displacement = SRegOffset(rl_dest.s_reg_low); 606d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 6072700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR * store = NewLIR3(kX86Mov32MI, r_base, displacement + LOWORD_OFFSET, val_lo); 608d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2, 609d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 6102700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR3(kX86Mov32MI, r_base, displacement + HIWORD_OFFSET, val_hi); 611d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2, 612d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 613d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee return; 614d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee } 615d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 616d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Just use the standard code to do the generation. 617d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee Mir2Lir::GenConstWide(rl_dest, value); 618d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee} 619e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 620e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell// TODO: Merge with existing RegLocation dumper in vreg_analysis.cc 621e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendellvoid X86Mir2Lir::DumpRegLocation(RegLocation loc) { 622e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell LOG(INFO) << "location: " << loc.location << ',' 623e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.wide ? " w" : " ") 624e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.defined ? " D" : " ") 625e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.is_const ? " c" : " ") 626e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.fp ? " F" : " ") 627e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.core ? " C" : " ") 628e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.ref ? " r" : " ") 629e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.high_word ? " h" : " ") 630e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.home ? " H" : " ") 6312700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee << ", low: " << static_cast<int>(loc.reg.GetLowReg()) 63200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee << ", high: " << static_cast<int>(loc.reg.GetHighReg()) 633e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", s_reg: " << loc.s_reg_low 634e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", orig: " << loc.orig_sreg; 635e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell} 636e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 63767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::Materialize() { 63867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // A good place to put the analysis before starting. 63967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeMIR(); 64067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 64167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Now continue with regular code generation. 64267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell Mir2Lir::Materialize(); 64367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 64467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 64549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Haovoid X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type, 64655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell SpecialTargetRegister symbolic_reg) { 64755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 64855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 64955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 65055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 65155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 65249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 65349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 65449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 65549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 65655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 65749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the move instruction with the unique pointer and save index, dex_file, and type. 6582700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg).GetReg(), 65949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<int>(target_method_id_ptr), target_method_idx, 66049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 66155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 66255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell method_address_insns_.Insert(move); 66355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 66455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 66555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg) { 66655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 66755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 66855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 66955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 67055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 67155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell const DexFile::TypeId& id = cu_->dex_file->GetTypeId(type_idx); 67255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell uintptr_t ptr = reinterpret_cast<uintptr_t>(&id); 67355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 67455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Generate the move instruction with the unique pointer and save index and type. 6752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg).GetReg(), 67655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell static_cast<int>(ptr), type_idx); 67755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 67855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell class_type_address_insns_.Insert(move); 67955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 68055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 68149161cef10a308aedada18e9aa742498d6e6c8c7Jeff HaoLIR *X86Mir2Lir::CallWithLinkerFixup(const MethodReference& target_method, InvokeType type) { 68255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 68355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit call relative instruction, that will be filled 68455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 68555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 68655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 68749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 68849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 68949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 69049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 69149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao 69249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the call instruction with the unique pointer and save index, dex_file, and type. 69349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao LIR *call = RawLIR(current_dalvik_offset_, kX86CallI, static_cast<int>(target_method_id_ptr), 69449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 69555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(call); 69655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell call_method_insns_.Insert(call); 69755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell return call; 69855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 69955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 70055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::InstallLiteralPools() { 70155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // These are handled differently for x86. 70255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(code_literal_list_ == nullptr); 70355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(method_literal_list_ == nullptr); 70455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(class_literal_list_ == nullptr); 70555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 70655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for methods. 70755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell for (uint32_t i = 0; i < method_address_insns_.Size(); i++) { 70855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell LIR* p = method_address_insns_.Get(i); 70955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 71049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[2]; 71149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 71249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3])); 71355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 71455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 71555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 71655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->compiler_driver->AddMethodPatch(cu_->dex_file, cu_->class_def_idx, 71755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->method_idx, cu_->invoke_type, 71849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, target_dex_file, 71949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<InvokeType>(p->operands[4]), 72055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell patch_offset); 72155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 72255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 72355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for class types. 72455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell for (uint32_t i = 0; i < class_type_address_insns_.Size(); i++) { 72555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell LIR* p = class_type_address_insns_.Get(i); 72655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 72749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[2]; 72855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 72955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 73055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 73155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->compiler_driver->AddClassPatch(cu_->dex_file, cu_->class_def_idx, 73249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao cu_->method_idx, target_method_idx, patch_offset); 73355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 73455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 73555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And now the PC-relative calls to methods. 73655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell for (uint32_t i = 0; i < call_method_insns_.Size(); i++) { 73755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell LIR* p = call_method_insns_.Get(i); 73855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86CallI); 73949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[1]; 74049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 74149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2])); 74255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 74355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 74455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 74555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->compiler_driver->AddRelativeCodePatch(cu_->dex_file, cu_->class_def_idx, 74649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao cu_->method_idx, cu_->invoke_type, 74749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, target_dex_file, 74849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<InvokeType>(p->operands[3]), 74955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell patch_offset, -4 /* offset */); 75055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 75155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 75255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And do the normal processing. 75355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell Mir2Lir::InstallLiteralPools(); 75455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 75555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 7564028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell/* 7574028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * Fast string.index_of(I) & (II). Inline check for simple case of char <= 0xffff, 7584028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * otherwise bails to standard library code. 7594028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell */ 7604028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendellbool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { 7614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell ClobberCallerSave(); 7624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LockCallTemps(); // Using fixed registers 7634028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 7644028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EAX: 16 bit character being searched. 7654028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // ECX: count: number of words to be searched. 7664028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EDI: String being searched. 7674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EDX: temporary during execution. 7684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EBX: temporary during execution. 7694028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 7704028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_obj = info->args[0]; 7714028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_char = info->args[1]; 772a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee RegLocation rl_start; // Note: only present in III flavor or IndexOf. 7734028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 7744028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell uint32_t char_value = 7754028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell rl_char.is_const ? mir_graph_->ConstantValue(rl_char.orig_sreg) : 0; 7764028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 7774028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (char_value > 0xFFFF) { 7784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to punt to the real String.indexOf. 7794028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return false; 7804028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 7814028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 7824028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Okay, we are commited to inlining this. 7834028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_return = GetReturn(false); 7844028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_dest = InlineTarget(info); 7854028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 7864028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the string non-NULL? 7872700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_obj, rs_rDX); 7882700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee GenNullCheck(rs_rDX, info->opt_flags); 7893bc8615332b7848dec8c2297a40f7e4d176c0efbVladimir Marko info->opt_flags |= MIR_IGNORE_NULL_CHECK; // Record that we've null checked. 7904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 7914028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Does the character fit in 16 bits? 7923a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang LIR* slowpath_branch = nullptr; 7934028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_char.is_const) { 7944028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We need the value in EAX. 7952700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rs_rAX, char_value); 7964028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 7974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Character is not a constant; compare at runtime. 7982700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_char, rs_rAX); 7993a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang slowpath_branch = OpCmpImmBranch(kCondGt, rs_rAX, 0xFFFF, nullptr); 8004028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 8014028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 8024028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // From here down, we know that we are looking for a char that fits in 16 bits. 803e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of reference to data array within the String object. 804e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int value_offset = mirror::String::ValueOffset().Int32Value(); 805e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of count within the String object. 806e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int count_offset = mirror::String::CountOffset().Int32Value(); 807e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Starting offset within data array. 808e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int offset_offset = mirror::String::OffsetOffset().Int32Value(); 809e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Start of char data with array_. 810e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); 8114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 8124028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Character is in EAX. 8134028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Object pointer is in EDX. 8144028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 8154028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We need to preserve EDI, but have no spare registers, so push it on the stack. 8164028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to remember that all stack addresses after this are offset by sizeof(EDI). 817091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Push32R, rs_rDI.GetReg()); 8184028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 8194028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Compute the number of words to search in to rCX. 820695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee Load32Disp(rs_rDX, count_offset, rs_rCX); 8214028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *length_compare = nullptr; 8224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell int start_value = 0; 823a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov bool is_index_on_stack = false; 8244028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (zero_based) { 8254028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to handle an empty string. Use special instruction JECXZ. 8264028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare = NewLIR0(kX86Jecxz8); 8274028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 828a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee rl_start = info->args[2]; 8294028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to offset by the start index. 8304028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_start.is_const) { 8314028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = mir_graph_->ConstantValue(rl_start.orig_sreg); 8324028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = std::max(start_value, 0); 8334028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 8344028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the start > count? 8352700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee length_compare = OpCmpImmBranch(kCondLe, rs_rCX, start_value, nullptr); 8364028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 8374028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (start_value != 0) { 8382700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegImm(kOpSub, rs_rCX, start_value); 8394028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 8404028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 8414028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Runtime start index. 8424028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell rl_start = UpdateLoc(rl_start); 8434028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_start.location == kLocPhysReg) { 844a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Handle "start index < 0" case. 845a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpXor, rs_rBX, rs_rBX); 846a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpCmp, rl_start.reg, rs_rBX); 847a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpCondRegReg(kOpCmov, kCondLt, rl_start.reg, rs_rBX); 848a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov 849a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // The length of the string should be greater than the start index. 8502700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee length_compare = OpCmpBranch(kCondLe, rs_rCX, rl_start.reg, nullptr); 8512700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegReg(kOpSub, rs_rCX, rl_start.reg); 852a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov if (rl_start.reg == rs_rDI) { 853a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // The special case. We will use EDI further, so lets put start index to stack. 854091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Push32R, rs_rDI.GetReg()); 855a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov is_index_on_stack = true; 856a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov } 8574028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 858a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Load the start index from stack, remembering that we pushed EDI. 8594028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell int displacement = SRegOffset(rl_start.s_reg_low) + sizeof(uint32_t); 860695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee Load32Disp(rs_rX86_SP, displacement, rs_rBX); 861a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpXor, rs_rDI, rs_rDI); 862a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpCmp, rs_rBX, rs_rDI); 863a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpCondRegReg(kOpCmov, kCondLt, rs_rBX, rs_rDI); 864a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov 865a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov length_compare = OpCmpBranch(kCondLe, rs_rCX, rs_rBX, nullptr); 866a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpSub, rs_rCX, rs_rBX); 867a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Put the start index to stack. 868091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Push32R, rs_rBX.GetReg()); 869a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov is_index_on_stack = true; 8704028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 8714028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 8724028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 8734028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell DCHECK(length_compare != nullptr); 8744028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 8754028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // ECX now contains the count in words to be searched. 8764028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 8774028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Load the address of the string into EBX. 878e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET. 879695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee Load32Disp(rs_rDX, value_offset, rs_rDI); 880695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee Load32Disp(rs_rDX, offset_offset, rs_rBX); 8812700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpLea(rs_rBX, rs_rDI, rs_rBX, 1, data_offset); 8824028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 8834028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Now compute into EDI where the search will start. 8844028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (zero_based || rl_start.is_const) { 8854028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (start_value == 0) { 8862700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegCopy(rs_rDI, rs_rBX); 8874028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 888091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR3(kX86Lea32RM, rs_rDI.GetReg(), rs_rBX.GetReg(), 2 * start_value); 8894028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 8904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 891a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov if (is_index_on_stack == true) { 892a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Load the start index from stack. 893091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Pop32R, rs_rDX.GetReg()); 8942700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpLea(rs_rDI, rs_rBX, rs_rDX, 1, 0); 895a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov } else { 896a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpLea(rs_rDI, rs_rBX, rl_start.reg, 1, 0); 8974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 8984028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 8994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9004028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EDI now contains the start of the string to be searched. 9014028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We are all prepared to do the search for the character. 9024028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell NewLIR0(kX86RepneScasw); 9034028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9044028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Did we find a match? 9054028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR* failed_branch = OpCondBranch(kCondNe, nullptr); 9064028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9074028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // yes, we matched. Compute the index of the result. 9084028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // index = ((curr_ptr - orig_ptr) / 2) - 1. 9092700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegReg(kOpSub, rs_rDI, rs_rBX); 9102700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegImm(kOpAsr, rs_rDI, 1); 911091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rs_rDI.GetReg(), -1); 9124028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *all_done = NewLIR1(kX86Jmp8, 0); 9134028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9144028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Failed to match; return -1. 9154028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *not_found = NewLIR0(kPseudoTargetLabel); 9164028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare->target = not_found; 9174028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell failed_branch->target = not_found; 9182700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rl_return.reg, -1); 9194028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9204028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // And join up at the end. 9214028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell all_done->target = NewLIR0(kPseudoTargetLabel); 9224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Restore EDI from the stack. 923091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Pop32R, rs_rDI.GetReg()); 9244028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9254028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Out of line code returns here. 9263a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang if (slowpath_branch != nullptr) { 9274028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *return_point = NewLIR0(kPseudoTargetLabel); 9283a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang AddIntrinsicSlowPath(info, slowpath_branch, return_point); 9294028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 9304028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9314028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell StoreValue(rl_dest, rl_return); 9324028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return true; 9334028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell} 9344028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 935ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell/* 936ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @brief Enter a 32 bit quantity into the FDE buffer 937ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param buf FDE buffer. 938ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param data Data value. 939ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell */ 940ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstatic void PushWord(std::vector<uint8_t>&buf, int data) { 941ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(data & 0xff); 942ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back((data >> 8) & 0xff); 943ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back((data >> 16) & 0xff); 944ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back((data >> 24) & 0xff); 945ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 946ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 947ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell/* 948ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @brief Enter an 'advance LOC' into the FDE buffer 949ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param buf FDE buffer. 950ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param increment Amount by which to increase the current location. 951ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell */ 952ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstatic void AdvanceLoc(std::vector<uint8_t>&buf, uint32_t increment) { 953ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (increment < 64) { 954ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Encoding in opcode. 955ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(0x1 << 6 | increment); 956ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } else if (increment < 256) { 957ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Single byte delta. 958ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(0x02); 959ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(increment); 960ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } else if (increment < 256 * 256) { 961ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Two byte delta. 962ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(0x03); 963ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(increment & 0xff); 964ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back((increment >> 8) & 0xff); 965ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } else { 966ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Four byte delta. 967ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(0x04); 968ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(buf, increment); 969ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 970ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 971ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 972ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 973ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86CFIInitialization() { 974ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell return X86Mir2Lir::ReturnCommonCallFrameInformation(); 975ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 976ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 977ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86Mir2Lir::ReturnCommonCallFrameInformation() { 978ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>; 979ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 980ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Length of the CIE (except for this field). 981ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 16); 982ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 983ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // CIE id. 984ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 0xFFFFFFFFU); 985ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 986ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Version: 3. 987ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x03); 988ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 989ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Augmentation: empty string. 990ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0); 991ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 992ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Code alignment: 1. 993ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x01); 994ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 995ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Data alignment: -4. 996ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x7C); 997ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 998ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Return address register (R8). 999ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x08); 1000ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1001ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Initial return PC is 4(ESP): DW_CFA_def_cfa R4 4. 1002ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0C); 1003ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x04); 1004ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x04); 1005ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1006ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Return address location: 0(SP): DW_CFA_offset R8 1 (* -4);. 1007ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x2 << 6 | 0x08); 1008ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x01); 1009ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1010ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // And 2 Noops to align to 4 byte boundary. 1011ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0); 1012ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0); 1013ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1014ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell DCHECK_EQ(cfi_info->size() & 3, 0U); 1015ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell return cfi_info; 1016ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1017ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1018ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstatic void EncodeUnsignedLeb128(std::vector<uint8_t>& buf, uint32_t value) { 1019ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint8_t buffer[12]; 1020ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint8_t *ptr = EncodeUnsignedLeb128(buffer, value); 1021ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell for (uint8_t *p = buffer; p < ptr; p++) { 1022ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(*p); 1023ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1024ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1025ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1026ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() { 1027ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>; 1028ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1029ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Generate the FDE for the method. 1030ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell DCHECK_NE(data_offset_, 0U); 1031ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1032ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Length (will be filled in later in this routine). 1033ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 0); 1034ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1035ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // CIE_pointer (can be filled in by linker); might be left at 0 if there is only 1036ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // one CIE for the whole debug_frame section. 1037ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 0); 1038ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1039ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // 'initial_location' (filled in by linker). 1040ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 0); 1041ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1042ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // 'address_range' (number of bytes in the method). 1043ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, data_offset_); 1044ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1045ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // The instructions in the FDE. 1046ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_decrement_ != nullptr) { 1047ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Advance LOC to just past the stack decrement. 1048ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t pc = NEXT_LIR(stack_decrement_)->offset; 1049ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell AdvanceLoc(*cfi_info, pc); 1050ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1051ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Now update the offset to the call frame: DW_CFA_def_cfa_offset frame_size. 1052ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0e); 1053ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell EncodeUnsignedLeb128(*cfi_info, frame_size_); 1054ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1055ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We continue with that stack until the epilogue. 1056ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_increment_ != nullptr) { 1057ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t new_pc = NEXT_LIR(stack_increment_)->offset; 1058ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell AdvanceLoc(*cfi_info, new_pc - pc); 1059ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1060ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We probably have code snippets after the epilogue, so save the 1061ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // current state: DW_CFA_remember_state. 1062ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0a); 1063ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1064ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We have now popped the stack: DW_CFA_def_cfa_offset 4. There is only the return 1065ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // PC on the stack now. 1066ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0e); 1067ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell EncodeUnsignedLeb128(*cfi_info, 4); 1068ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1069ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Everything after that is the same as before the epilogue. 1070ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Stack bump was followed by RET instruction. 1071ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell LIR *post_ret_insn = NEXT_LIR(NEXT_LIR(stack_increment_)); 1072ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (post_ret_insn != nullptr) { 1073ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell pc = new_pc; 1074ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell new_pc = post_ret_insn->offset; 1075ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell AdvanceLoc(*cfi_info, new_pc - pc); 1076ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Restore the state: DW_CFA_restore_state. 1077ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0b); 1078ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1079ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1080ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1081ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1082ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Padding to a multiple of 4 1083ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell while ((cfi_info->size() & 3) != 0) { 1084ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // DW_CFA_nop is encoded as 0. 1085ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0); 1086ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1087ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1088ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Set the length of the FDE inside the generated bytes. 1089ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t length = cfi_info->size() - 4; 1090ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[0] = length; 1091ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[1] = length >> 8; 1092ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[2] = length >> 16; 1093ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[3] = length >> 24; 1094ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell return cfi_info; 1095ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1096ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 10977934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 1098