target_x86.cc revision d65c51a556e6649db4e18bd083c8fec37607a442
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 299ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage core_regs_arr_32[] = { 309ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI, 319ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 329ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage core_regs_arr_64[] = { 339ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_64, rs_rBP, rs_rSI, rs_rDI, 34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#ifdef TARGET_REX_SUPPORT 35091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_r8, rs_r9, rs_r10, rs_r11, rs_r12, rs_r13, rs_r14, rs_r15 36efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 37efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 389ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage sp_regs_arr_32[] = { 399ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 409ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 419ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage sp_regs_arr_64[] = { 42091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 43efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#ifdef TARGET_REX_SUPPORT 44091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 45efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 46efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage dp_regs_arr_32[] = { 489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 509ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage dp_regs_arr_64[] = { 51091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 52efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#ifdef TARGET_REX_SUPPORT 53091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 54efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 55efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage reserved_regs_arr_32[] = {rs_rX86_SP_32}; 579ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage reserved_regs_arr_64[] = {rs_rX86_SP_64}; 589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage core_temps_arr_32[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX}; 599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage core_temps_arr_64[] = { 609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rSI, rs_rDI, 619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko#ifdef TARGET_REX_SUPPORT 629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_r8, rs_r9, rs_r10, rs_r11 639ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko#endif 649ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 659ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage sp_temps_arr_32[] = { 669ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 679ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 689ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage sp_temps_arr_64[] = { 69091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 70091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee#ifdef TARGET_REX_SUPPORT 71091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 72091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee#endif 73091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 749ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage dp_temps_arr_32[] = { 759ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 769ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 779ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const RegStorage dp_temps_arr_64[] = { 78091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 79091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee#ifdef TARGET_REX_SUPPORT 80091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 81091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee#endif 82091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 83091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 849ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> core_regs_32(core_regs_arr_32, 859ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko core_regs_arr_32 + sizeof(core_regs_arr_32) / sizeof(core_regs_arr_32[0])); 869ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> core_regs_64(core_regs_arr_64, 879ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko core_regs_arr_64 + sizeof(core_regs_arr_64) / sizeof(core_regs_arr_64[0])); 889ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> sp_regs_32(sp_regs_arr_32, 899ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko sp_regs_arr_32 + sizeof(sp_regs_arr_32) / sizeof(sp_regs_arr_32[0])); 909ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> sp_regs_64(sp_regs_arr_64, 919ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko sp_regs_arr_64 + sizeof(sp_regs_arr_64) / sizeof(sp_regs_arr_64[0])); 929ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> dp_regs_32(dp_regs_arr_32, 939ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko dp_regs_arr_32 + sizeof(dp_regs_arr_32) / sizeof(dp_regs_arr_32[0])); 949ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> dp_regs_64(dp_regs_arr_64, 959ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko dp_regs_arr_64 + sizeof(dp_regs_arr_64) / sizeof(dp_regs_arr_64[0])); 969ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> reserved_regs_32(reserved_regs_arr_32, 979ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko reserved_regs_arr_32 + sizeof(reserved_regs_arr_32) / sizeof(reserved_regs_arr_32[0])); 989ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> reserved_regs_64(reserved_regs_arr_64, 999ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko reserved_regs_arr_64 + sizeof(reserved_regs_arr_64) / sizeof(reserved_regs_arr_64[0])); 1009ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> core_temps_32(core_temps_arr_32, 1019ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko core_temps_arr_32 + sizeof(core_temps_arr_32) / sizeof(core_temps_arr_32[0])); 1029ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> core_temps_64(core_temps_arr_64, 1039ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko core_temps_arr_64 + sizeof(core_temps_arr_64) / sizeof(core_temps_arr_64[0])); 1049ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> sp_temps_32(sp_temps_arr_32, 1059ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko sp_temps_arr_32 + sizeof(sp_temps_arr_32) / sizeof(sp_temps_arr_32[0])); 1069ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> sp_temps_64(sp_temps_arr_64, 1079ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko sp_temps_arr_64 + sizeof(sp_temps_arr_64) / sizeof(sp_temps_arr_64[0])); 1089ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> dp_temps_32(dp_temps_arr_32, 1099ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko dp_temps_arr_32 + sizeof(dp_temps_arr_32) / sizeof(dp_temps_arr_32[0])); 1109ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenkostatic const std::vector<RegStorage> dp_temps_64(dp_temps_arr_64, 1119ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko dp_temps_arr_64 + sizeof(dp_temps_arr_64) / sizeof(dp_temps_arr_64[0])); 1129ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 1139ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_SP; 1149ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 1159ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG0; 1169ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG1; 1179ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG2; 1189ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG3; 1199ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG0; 1209ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG1; 1219ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG2; 1229ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG3; 1239ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_RET0; 1249ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_RET1; 1259ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_INVOKE_TGT; 1269ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_COUNT; 1279ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 1289ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG0; 1299ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG1; 1309ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG2; 1319ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG3; 1329ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG0; 1339ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG1; 1349ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG2; 1359ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG3; 1369ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_RET0; 1379ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_RET1; 1389ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_INVOKE_TGT; 1399ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_COUNT; 140efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1412ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturn() { 14200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return; 143efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 144efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1452ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnWide() { 14600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_wide; 147efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 148efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1492ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnFloat() { 15000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_float; 151efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 152efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1532ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnDouble() { 15400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_double; 155efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 156efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 157efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Return a target-dependent special register. 1582700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeRegStorage X86Mir2Lir::TargetReg(SpecialTargetRegister reg) { 159091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage res_reg = RegStorage::InvalidReg(); 160efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (reg) { 161091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSelf: res_reg = RegStorage::InvalidReg(); break; 162091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSuspend: res_reg = RegStorage::InvalidReg(); break; 163091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kLr: res_reg = RegStorage::InvalidReg(); break; 164091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kPc: res_reg = RegStorage::InvalidReg(); break; 165091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSp: res_reg = rs_rX86_SP; break; 166091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg0: res_reg = rs_rX86_ARG0; break; 167091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg1: res_reg = rs_rX86_ARG1; break; 168091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg2: res_reg = rs_rX86_ARG2; break; 169091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg3: res_reg = rs_rX86_ARG3; break; 170091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg0: res_reg = rs_rX86_FARG0; break; 171091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg1: res_reg = rs_rX86_FARG1; break; 172091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg2: res_reg = rs_rX86_FARG2; break; 173091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg3: res_reg = rs_rX86_FARG3; break; 174091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kRet0: res_reg = rs_rX86_RET0; break; 175091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kRet1: res_reg = rs_rX86_RET1; break; 176091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kInvokeTgt: res_reg = rs_rX86_INVOKE_TGT; break; 177091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kHiddenArg: res_reg = rs_rAX; break; 178091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kHiddenFpArg: res_reg = rs_fr0; break; 179091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kCount: res_reg = rs_rX86_COUNT; break; 180091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee } 181091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee return res_reg; 182efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 183efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1842700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeRegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) { 1853bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru // For the 32-bit internal ABI, the first 3 arguments are passed in registers. 1863bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru // TODO: This is not 64-bit compliant and depends on new internal ABI. 1873bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru switch (arg_num) { 1883bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru case 0: 1892700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return rs_rX86_ARG1; 1903bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru case 1: 1912700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return rs_rX86_ARG2; 1923bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru case 2: 1932700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return rs_rX86_ARG3; 1943bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru default: 1952700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return RegStorage::InvalidReg(); 1963bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru } 1973bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru} 1983bc01748ef1c3e43361bdf520947a9d656658bf8Razvan A Lupusoru 199efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 200efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Decode the register id. 201efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 202091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeeuint64_t X86Mir2Lir::GetRegMaskCommon(RegStorage reg) { 203eaf09bc65f9a10d12befcdb239156938c9bceef2buzbee uint64_t seed; 204efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int shift; 205fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee int reg_id; 206efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 207091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_id = reg.GetRegNum(); 208efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Double registers in x86 are just a single FP register */ 209efc6369224b036a1fb77849f7ae65b3492c832c0buzbee seed = 1; 210efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* FP register starts at bit position 16 */ 211091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee shift = reg.IsFloat() ? kX86FPReg0 : 0; 212efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Expand the double register id into single offset */ 213fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee shift += reg_id; 214efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return (seed << shift); 215efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 216efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 2172ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t X86Mir2Lir::GetPCUseDefEncoding() { 218efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* 219efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * FIXME: might make sense to use a virtual resource encoding bit for pc. Might be 220efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * able to clean up some of the x86/Arm_Mips differences 221efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 22252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Unexpected call to GetPCUseDefEncoding for x86"; 223efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return 0ULL; 224efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 225efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 226b48819db07f9a0992a72173380c24249d7fc648abuzbeevoid X86Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags) { 2276a58cb16d803c9a7b3a75ccac8be19dd9d4e520dDmitry Petrochenko DCHECK(cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64); 228b48819db07f9a0992a72173380c24249d7fc648abuzbee DCHECK(!lir->flags.use_def_invalid); 229efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 230efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // X86-specific resource map setup here. 231efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USE_SP) { 232b48819db07f9a0992a72173380c24249d7fc648abuzbee lir->u.m.use_mask |= ENCODE_X86_REG_SP; 233efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 234efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 235efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEF_SP) { 236b48819db07f9a0992a72173380c24249d7fc648abuzbee lir->u.m.def_mask |= ENCODE_X86_REG_SP; 237efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 238efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 239efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFA) { 240091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.def_mask, rs_rAX.GetReg()); 241efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 242efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 243efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFD) { 244091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.def_mask, rs_rDX.GetReg()); 245efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 246efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEA) { 247091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rAX.GetReg()); 248efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 249efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 250efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEC) { 251091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rCX.GetReg()); 252efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 253efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 254efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USED) { 255091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rDX.GetReg()); 256efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 25770b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko 25870b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko if (flags & REG_USEB) { 259091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rBX.GetReg()); 26070b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko } 2614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 2624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Fixup hard to describe instruction: Uses rAX, rCX, rDI; sets rDI. 2634028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (lir->opcode == kX86RepneScasw) { 264091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rAX.GetReg()); 265091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rCX.GetReg()); 266091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.use_mask, rs_rDI.GetReg()); 267091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee SetupRegMask(&lir->u.m.def_mask, rs_rDI.GetReg()); 2684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 269e90501da0222717d75c126ebf89569db3976927eSerguei Katkov 270e90501da0222717d75c126ebf89569db3976927eSerguei Katkov if (flags & USE_FP_STACK) { 271e90501da0222717d75c126ebf89569db3976927eSerguei Katkov lir->u.m.use_mask |= ENCODE_X86_FP_STACK; 272e90501da0222717d75c126ebf89569db3976927eSerguei Katkov lir->u.m.def_mask |= ENCODE_X86_FP_STACK; 273e90501da0222717d75c126ebf89569db3976927eSerguei Katkov } 274efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 275efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 276efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* For dumping instructions */ 277efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86RegName[] = { 278efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 279efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 280efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 281efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 282efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86CondName[] = { 283efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "O", 284efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NO", 285efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "B/NAE/C", 286efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NB/AE/NC", 287efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "Z/EQ", 288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NZ/NE", 289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "BE/NA", 290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NBE/A", 291efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "S", 292efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NS", 293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "P/PE", 294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NP/PO", 295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "L/NGE", 296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NL/GE", 297efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "LE/NG", 298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NLE/G" 299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Interpret a format string and build a string no longer than size 303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See format key in Assemble.cc. 304efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 3051fd3346740dfb7f47be9922312b68a4227fada96buzbeestd::string X86Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) { 306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee std::string buf; 307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t i = 0; 308efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t fmt_len = strlen(fmt); 309efc6369224b036a1fb77849f7ae65b3492c832c0buzbee while (i < fmt_len) { 310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (fmt[i] != '!') { 311efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += fmt[i]; 312efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 313efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 314efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 315efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 316efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char operand_number_ch = fmt[i]; 317efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (operand_number_ch == '!') { 319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += "!"; 320efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 321efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand_number = operand_number_ch - '0'; 322efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(operand_number, 6); // Expect upto 6 LIR operands. 323efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand = lir->operands[operand_number]; 325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (fmt[i]) { 326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'c': 327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(static_cast<size_t>(operand), sizeof(x86CondName)); 328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += x86CondName[operand]; 329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'd': 331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("%d", operand); 332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 333efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'p': { 3340d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(operand)); 335fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee buf += StringPrintf("0x%08x", tab_rec->offset); 336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'r': 339091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (RegStorage::IsFloat(operand)) { 340091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int fp_reg = RegStorage::RegNum(operand); 341efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("xmm%d", fp_reg); 342efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 343091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int reg_num = RegStorage::RegNum(operand); 344091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK_LT(static_cast<size_t>(reg_num), sizeof(x86RegName)); 345091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee buf += x86RegName[reg_num]; 346efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 't': 349107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers buf += StringPrintf("0x%08" PRIxPTR " (L%p)", 350107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers reinterpret_cast<uintptr_t>(base_addr) + lir->offset + operand, 351107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers lir->target); 352efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 353efc6369224b036a1fb77849f7ae65b3492c832c0buzbee default: 354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("DecodeError '%c'", fmt[i]); 355efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 356efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 357efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 358efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 359efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return buf; 362efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 363efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3642ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::DumpResourceMask(LIR *x86LIR, uint64_t mask, const char *prefix) { 365efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char buf[256]; 366efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf[0] = 0; 367efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 368efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask == ENCODE_ALL) { 369efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcpy(buf, "all"); 370efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 371efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char num[8]; 372efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int i; 373efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 374efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (i = 0; i < kX86RegEnd; i++) { 375efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & (1ULL << i)) { 376988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(num, arraysize(num), "%d ", i); 377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, num); 378efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 381efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & ENCODE_CCODE) { 382efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "cc "); 383efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 384efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Memory bits */ 385efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (x86LIR && (mask & ENCODE_DALVIK_REG)) { 386988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s", 387988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers DECODE_ALIAS_INFO_REG(x86LIR->flags.alias_info), 388988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers (DECODE_ALIAS_INFO_WIDE(x86LIR->flags.alias_info)) ? "(+1)" : ""); 389efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & ENCODE_LITERAL) { 391efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "lit "); 392efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & ENCODE_HEAP_REF) { 395efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "heap "); 396efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 397efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & ENCODE_MUST_NOT_ALIAS) { 398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "noalias "); 399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 400efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 401efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (buf[0]) { 402efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(INFO) << prefix << ": " << buf; 403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 40502031b185b4653e6c72e21f7a51238b903f6d638buzbee 4061fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::AdjustSpillMask() { 407efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Adjustment for LR spilling, x86 has no LR so nothing to do here 408091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee core_spill_mask_ |= (1 << rs_rRET.GetRegNum()); 4091fd3346740dfb7f47be9922312b68a4227fada96buzbee num_core_spills_++; 410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Mark a callee-save fp register as promoted. Note that 414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * vpush/vpop uses contiguous register lists so we must 415efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * include any holes in the mask. Associate holes with 416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Dalvik register INVALID_VREG (0xFFFFU). 417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 418091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeevoid X86Mir2Lir::MarkPreservedSingle(int v_reg, RegStorage reg) { 419091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee UNIMPLEMENTED(FATAL) << "MarkPreservedSingle"; 420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 422091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbeevoid X86Mir2Lir::MarkPreservedDouble(int v_reg, RegStorage reg) { 423091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee UNIMPLEMENTED(FATAL) << "MarkPreservedDouble"; 4242700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee} 4252700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee 426efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Clobber all regs that might be used by an external C call */ 42731c2aac7137b69d5622eea09597500731fbee2efVladimir Markovoid X86Mir2Lir::ClobberCallerSave() { 428091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rAX); 429091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rCX); 430091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 431091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rBX); 432efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 433efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4341fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation X86Mir2Lir::GetReturnWideAlt() { 43552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturnWide(); 436091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(res.reg.GetLowReg() == rs_rAX.GetReg()); 437091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(res.reg.GetHighReg() == rs_rDX.GetReg()); 438091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rAX); 439091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 440091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rAX); 441091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 442091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkWide(res.reg); 443efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 444efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 445efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4462ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::GetReturnAlt() { 44752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturn(); 448091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee res.reg.SetReg(rs_rDX.GetReg()); 449091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 450091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 451efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 452efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 453efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 454efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 4552ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::LockCallTemps() { 456091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG0); 457091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG1); 458091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG2); 459091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG3); 460efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 461efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 462efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 4632ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::FreeCallTemps() { 464091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG0); 465091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG1); 466091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG2); 467091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG3); 468efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 469efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 47099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusorubool X86Mir2Lir::ProvidesFullMemoryBarrier(X86OpCode opcode) { 47199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru switch (opcode) { 47299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgMR: 47399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgAR: 47499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchg8bM: 47599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchg8bA: 47699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86XchgMR: 47799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86Mfence: 47899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Atomic memory instructions provide full barrier. 47999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return true; 48099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru default: 48199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru break; 48299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 48399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 48499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Conservative if cannot prove it provides full barrier. 48599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return false; 48699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru} 48799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 488b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampebool X86Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) { 489efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0 49099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Start off with using the last LIR as the barrier. If it is not enough, then we will update it. 49199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru LIR* mem_barrier = last_lir_insn_; 49299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 493b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe bool ret = false; 49499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru /* 49599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru * According to the JSR-133 Cookbook, for x86 only StoreLoad barriers need memory fence. All other barriers 49699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru * (LoadLoad, LoadStore, StoreStore) are nops due to the x86 memory model. For those cases, all we need 49799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru * to ensure is that there is a scheduling barrier in place. 49899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru */ 49999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (barrier_kind == kStoreLoad) { 50099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If no LIR exists already that can be used a barrier, then generate an mfence. 50199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 50299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 503b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe ret = true; 50499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 50599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 50699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If last instruction does not provide full barrier, then insert an mfence. 50799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (ProvidesFullMemoryBarrier(static_cast<X86OpCode>(mem_barrier->opcode)) == false) { 50899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 509b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe ret = true; 51099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 51199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 51299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 51399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Now ensure that a scheduling barrier is in place. 51499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 51599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru GenBarrier(); 51699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } else { 51799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Mark as a scheduling barrier. 51899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru DCHECK(!mem_barrier->flags.use_def_invalid); 51999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier->u.m.def_mask = ENCODE_ALL; 52099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 521b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe return ret; 522b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe#else 523b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe return false; 524efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 525efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 52600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee 52700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee// Alloc a pair of core registers, or a double. 52800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill BuzbeeRegStorage X86Mir2Lir::AllocTypedTempWide(bool fp_hint, int reg_class) { 529fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { 5302700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return AllocTempDouble(); 531efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 5322700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage low_reg = AllocTemp(); 5332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee RegStorage high_reg = AllocTemp(); 5342700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return RegStorage::MakeRegPair(low_reg, high_reg); 535efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 536efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5372700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeRegStorage X86Mir2Lir::AllocTypedTemp(bool fp_hint, int reg_class) { 538fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee if (((reg_class == kAnyReg) && fp_hint) || (reg_class == kFPReg)) { 539091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee return AllocTempSingle(); 540efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 5411fd3346740dfb7f47be9922312b68a4227fada96buzbee return AllocTemp(); 542efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 543efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5441fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::CompilerInitializeRegAlloc() { 5459ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko if (Gen64Bit()) { 5469ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_64, sp_regs_64, dp_regs_64, reserved_regs_64, 5479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko core_temps_64, sp_temps_64, dp_temps_64); 5489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 5499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_32, sp_regs_32, dp_regs_32, reserved_regs_32, 5509ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko core_temps_32, sp_temps_32, dp_temps_32); 5519ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 552091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 553091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Target-specific adjustments. 554091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 555091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Alias single precision xmm to double xmms. 556091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: as needed, add larger vector sizes - alias all to the largest. 557091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee GrowableArray<RegisterInfo*>::Iterator it(®_pool_->sp_regs_); 558091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) { 559091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int sp_reg_num = info->GetReg().GetRegNum(); 560091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage dp_reg = RegStorage::Solo64(RegStorage::kFloatingPoint | sp_reg_num); 561091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegisterInfo* dp_reg_info = GetRegInfo(dp_reg); 562091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // 64-bit xmm vector register's master storage should refer to itself. 563091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK_EQ(dp_reg_info, dp_reg_info->Master()); 564091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Redirect 32-bit vector's master storage to 64-bit vector. 565091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee info->SetMaster(dp_reg_info); 566efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 567091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 568091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods. 569091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: adjust for x86/hard float calling convention. 570091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_core_reg_ = 2; 571091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_sp_reg_ = 2; 572091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_dp_reg_ = 1; 573efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 574efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeevoid X86Mir2Lir::FreeRegLocTemps(RegLocation rl_keep, RegLocation rl_free) { 5762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee DCHECK(rl_keep.wide); 5772700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee DCHECK(rl_free.wide); 5782700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int free_low = rl_free.reg.GetLowReg(); 5792700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int free_high = rl_free.reg.GetHighReg(); 5802700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int keep_low = rl_keep.reg.GetLowReg(); 5812700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int keep_high = rl_keep.reg.GetHighReg(); 5822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee if ((free_low != keep_low) && (free_low != keep_high) && 5832700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee (free_high != keep_low) && (free_high != keep_high)) { 584efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // No overlap, free both 585091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rl_free.reg); 586efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 587efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 588efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5891fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::SpillCoreRegs() { 5901fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_core_spills_ == 0) { 591efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 592efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 593efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Spill mask not including fake return address register 594091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 5959ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 596efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (int reg = 0; mask; mask >>= 1, reg++) { 597efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & 0x1) { 5982700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee StoreWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg)); 5999ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko offset += GetInstructionSetPointerSize(cu_->instruction_set); 600efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 601efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 602efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 603efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 6041fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::UnSpillCoreRegs() { 6051fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_core_spills_ == 0) { 606efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 607efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 608efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Spill mask not including fake return address register 609091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 6109ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 611efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (int reg = 0; mask; mask >>= 1, reg++) { 612efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & 0x1) { 6132700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg)); 6149ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko offset += GetInstructionSetPointerSize(cu_->instruction_set); 615efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 616efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 617efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 618efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 6192ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::IsUnconditionalBranch(LIR* lir) { 620cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32); 621efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 622efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 623674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Markobool X86Mir2Lir::SupportsVolatileLoadStore(OpSize size) { 624674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return true; 625674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko} 626674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 627674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoRegisterClass X86Mir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) { 628674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko if (UNLIKELY(is_volatile)) { 629674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // On x86, atomic 64-bit load/store requires an fp register. 630674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // Smaller aligned load/store is atomic for both core and fp registers. 631674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko if (size == k64 || size == kDouble) { 632674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return kFPReg; 633674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko } 634674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko } 635674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return RegClassBySize(size); 636674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko} 637674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 6389ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena, bool gen64bit) 63955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell : Mir2Lir(cu, mir_graph, arena), 640dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers base_of_code_(nullptr), store_method_addr_(false), store_method_addr_used_(false), 64155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell method_address_insns_(arena, 100, kGrowableArrayMisc), 64255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell class_type_address_insns_(arena, 100, kGrowableArrayMisc), 643ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell call_method_insns_(arena, 100, kGrowableArrayMisc), 644d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell stack_decrement_(nullptr), stack_increment_(nullptr), gen64bit_(gen64bit), 645d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell const_vectors_(nullptr) { 646d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell store_method_addr_used_ = false; 647dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (kIsDebugBuild) { 648dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers for (int i = 0; i < kX86Last; i++) { 649dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (X86Mir2Lir::EncodingMap[i].opcode != i) { 650dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers LOG(FATAL) << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name 651d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell << " is wrong: expecting " << i << ", seeing " 652d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode); 653dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers } 654efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 655efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 6569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko if (Gen64Bit()) { 6579ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_SP = rs_rX86_SP_64; 6589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 6599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG0 = rs_rDI; 6609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG1 = rs_rSI; 6619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG2 = rs_rDX; 6629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG3 = rs_rCX; 6639ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG0 = rDI; 6649ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG1 = rSI; 6659ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG2 = rDX; 6669ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG3 = rCX; 6679ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko // TODO: ARG4(r8), ARG5(r9), floating point args. 6689ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 6699ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_SP = rs_rX86_SP_32; 6709ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 6719ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG0 = rs_rAX; 6729ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG1 = rs_rCX; 6739ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG2 = rs_rDX; 6749ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG3 = rs_rBX; 6759ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG0 = rAX; 6769ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG1 = rCX; 6779ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG2 = rDX; 6789ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG3 = rBX; 6799ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 6809ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_FARG0 = rs_rAX; 6819ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_FARG1 = rs_rCX; 6829ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_FARG2 = rs_rDX; 6839ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_FARG3 = rs_rBX; 6849ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_RET0 = rs_rAX; 6859ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_RET1 = rs_rDX; 6869ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_INVOKE_TGT = rs_rAX; 6879ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_COUNT = rs_rCX; 6889ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_FARG0 = rAX; 6899ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_FARG1 = rCX; 6909ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_FARG2 = rDX; 6919ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_FARG3 = rBX; 6929ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_RET0 = rAX; 6939ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_RET1 = rDX; 6949ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_INVOKE_TGT = rAX; 6959ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_COUNT = rCX; 6961fd3346740dfb7f47be9922312b68a4227fada96buzbee} 6971fd3346740dfb7f47be9922312b68a4227fada96buzbee 698862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 699862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee ArenaAllocator* const arena) { 7009ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko return new X86Mir2Lir(cu, mir_graph, arena, false); 7019ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko} 7029ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 7039ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoMir2Lir* X86_64CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 7049ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko ArenaAllocator* const arena) { 7059ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko return new X86Mir2Lir(cu, mir_graph, arena, true); 706efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 707efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 708efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Not used in x86 709dd7624d2b9e599d57762d12031b10b89defc9807Ian RogersRegStorage X86Mir2Lir::LoadHelper(ThreadOffset<4> offset) { 71052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee LOG(FATAL) << "Unexpected use of LoadHelper in x86"; 7112700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee return RegStorage::InvalidReg(); 712efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 713efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 7142f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe// Not used in x86 7152f244e9faccfcca68af3c5484c397a01a1c3a342Andreas GampeRegStorage X86Mir2Lir::LoadHelper(ThreadOffset<8> offset) { 7162f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe LOG(FATAL) << "Unexpected use of LoadHelper in x86"; 7172f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe return RegStorage::InvalidReg(); 7182f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe} 7192f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe 720b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave AllisonLIR* X86Mir2Lir::CheckSuspendUsingLoad() { 721b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison LOG(FATAL) << "Unexpected use of CheckSuspendUsingLoad in x86"; 722b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison return nullptr; 723b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison} 724b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison 7252ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t X86Mir2Lir::GetTargetInstFlags(int opcode) { 726409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 7271fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].flags; 7281bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 7291bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 7302ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstName(int opcode) { 731409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 7321fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].name; 7331bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 7341bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 7352ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstFmt(int opcode) { 736409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 7371fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].fmt; 7381bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 7391bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 740d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbeevoid X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) { 741d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Can we do this directly to memory? 742d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee rl_dest = UpdateLocWide(rl_dest); 743d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee if ((rl_dest.location == kLocDalvikFrame) || 744d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee (rl_dest.location == kLocCompilerTemp)) { 745d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_lo = Low32Bits(value); 746d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_hi = High32Bits(value); 7472700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee int r_base = TargetReg(kSp).GetReg(); 748d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int displacement = SRegOffset(rl_dest.s_reg_low); 749d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 7502700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR * store = NewLIR3(kX86Mov32MI, r_base, displacement + LOWORD_OFFSET, val_lo); 751d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2, 752d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 7532700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR3(kX86Mov32MI, r_base, displacement + HIWORD_OFFSET, val_hi); 754d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2, 755d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 756d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee return; 757d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee } 758d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 759d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Just use the standard code to do the generation. 760d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee Mir2Lir::GenConstWide(rl_dest, value); 761d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee} 762e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 763e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell// TODO: Merge with existing RegLocation dumper in vreg_analysis.cc 764e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendellvoid X86Mir2Lir::DumpRegLocation(RegLocation loc) { 765e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell LOG(INFO) << "location: " << loc.location << ',' 766e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.wide ? " w" : " ") 767e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.defined ? " D" : " ") 768e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.is_const ? " c" : " ") 769e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.fp ? " F" : " ") 770e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.core ? " C" : " ") 771e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.ref ? " r" : " ") 772e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.high_word ? " h" : " ") 773e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.home ? " H" : " ") 7742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee << ", low: " << static_cast<int>(loc.reg.GetLowReg()) 77500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee << ", high: " << static_cast<int>(loc.reg.GetHighReg()) 776e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", s_reg: " << loc.s_reg_low 777e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", orig: " << loc.orig_sreg; 778e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell} 779e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 78067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::Materialize() { 78167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // A good place to put the analysis before starting. 78267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeMIR(); 78367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 78467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Now continue with regular code generation. 78567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell Mir2Lir::Materialize(); 78667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 78767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 78849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Haovoid X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type, 78955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell SpecialTargetRegister symbolic_reg) { 79055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 79155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 79255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 79355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 79455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 79549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 79649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 79749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 79849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 79955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 80049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the move instruction with the unique pointer and save index, dex_file, and type. 8012700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg).GetReg(), 80249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<int>(target_method_id_ptr), target_method_idx, 80349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 80455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 80555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell method_address_insns_.Insert(move); 80655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 80755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 80855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg) { 80955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 81055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 81155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 81255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 81355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 81455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell const DexFile::TypeId& id = cu_->dex_file->GetTypeId(type_idx); 81555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell uintptr_t ptr = reinterpret_cast<uintptr_t>(&id); 81655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 81755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Generate the move instruction with the unique pointer and save index and type. 8182700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg).GetReg(), 81955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell static_cast<int>(ptr), type_idx); 82055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 82155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell class_type_address_insns_.Insert(move); 82255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 82355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 82449161cef10a308aedada18e9aa742498d6e6c8c7Jeff HaoLIR *X86Mir2Lir::CallWithLinkerFixup(const MethodReference& target_method, InvokeType type) { 82555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 82655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit call relative instruction, that will be filled 82755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 82855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 82955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 83049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 83149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 83249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 83349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 83449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao 83549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the call instruction with the unique pointer and save index, dex_file, and type. 83649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao LIR *call = RawLIR(current_dalvik_offset_, kX86CallI, static_cast<int>(target_method_id_ptr), 83749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 83855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(call); 83955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell call_method_insns_.Insert(call); 84055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell return call; 84155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 84255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 843d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell/* 844d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell * @brief Enter a 32 bit quantity into a buffer 845d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell * @param buf buffer. 846d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell * @param data Data value. 847d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell */ 848d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 849d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellstatic void PushWord(std::vector<uint8_t>&buf, int32_t data) { 850d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell buf.push_back(data & 0xff); 851d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell buf.push_back((data >> 8) & 0xff); 852d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell buf.push_back((data >> 16) & 0xff); 853d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell buf.push_back((data >> 24) & 0xff); 854d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 855d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 85655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::InstallLiteralPools() { 85755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // These are handled differently for x86. 85855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(code_literal_list_ == nullptr); 85955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(method_literal_list_ == nullptr); 86055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(class_literal_list_ == nullptr); 86155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 862d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Align to 16 byte boundary. We have implicit knowledge that the start of the method is 863d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // on a 4 byte boundary. How can I check this if it changes (other than aligned loads 864d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // will fail at runtime)? 865d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (const_vectors_ != nullptr) { 866d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell int align_size = (16-4) - (code_buffer_.size() & 0xF); 867d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (align_size < 0) { 868d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell align_size += 16; 869d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 870d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 871d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell while (align_size > 0) { 872d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell code_buffer_.push_back(0); 873d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell align_size--; 874d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 875d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell for (LIR *p = const_vectors_; p != nullptr; p = p->next) { 876d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell PushWord(code_buffer_, p->operands[0]); 877d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell PushWord(code_buffer_, p->operands[1]); 878d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell PushWord(code_buffer_, p->operands[2]); 879d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell PushWord(code_buffer_, p->operands[3]); 880d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 881d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 882d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 88355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for methods. 88455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell for (uint32_t i = 0; i < method_address_insns_.Size(); i++) { 88555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell LIR* p = method_address_insns_.Get(i); 88655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 88749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[2]; 88849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 88949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3])); 89055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 89155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 89255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 89355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->compiler_driver->AddMethodPatch(cu_->dex_file, cu_->class_def_idx, 89455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->method_idx, cu_->invoke_type, 89549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, target_dex_file, 89649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<InvokeType>(p->operands[4]), 89755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell patch_offset); 89855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 89955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 90055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for class types. 90155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell for (uint32_t i = 0; i < class_type_address_insns_.Size(); i++) { 90255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell LIR* p = class_type_address_insns_.Get(i); 90355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 90449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[2]; 90555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 90655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 90755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 90855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->compiler_driver->AddClassPatch(cu_->dex_file, cu_->class_def_idx, 90949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao cu_->method_idx, target_method_idx, patch_offset); 91055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 91155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 91255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And now the PC-relative calls to methods. 91355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell for (uint32_t i = 0; i < call_method_insns_.Size(); i++) { 91455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell LIR* p = call_method_insns_.Get(i); 91555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86CallI); 91649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[1]; 91749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 91849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2])); 91955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 92055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 92155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 92255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->compiler_driver->AddRelativeCodePatch(cu_->dex_file, cu_->class_def_idx, 92349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao cu_->method_idx, cu_->invoke_type, 92449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, target_dex_file, 92549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<InvokeType>(p->operands[3]), 92655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell patch_offset, -4 /* offset */); 92755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 92855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 92955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And do the normal processing. 93055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell Mir2Lir::InstallLiteralPools(); 93155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 93255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 9334028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell/* 9344028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * Fast string.index_of(I) & (II). Inline check for simple case of char <= 0xffff, 9354028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * otherwise bails to standard library code. 9364028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell */ 9374028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendellbool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { 9384028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell ClobberCallerSave(); 9394028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LockCallTemps(); // Using fixed registers 9404028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9414028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EAX: 16 bit character being searched. 9424028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // ECX: count: number of words to be searched. 9434028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EDI: String being searched. 9444028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EDX: temporary during execution. 9454028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EBX: temporary during execution. 9464028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9474028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_obj = info->args[0]; 9484028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_char = info->args[1]; 949a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee RegLocation rl_start; // Note: only present in III flavor or IndexOf. 9504028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9514028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell uint32_t char_value = 9524028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell rl_char.is_const ? mir_graph_->ConstantValue(rl_char.orig_sreg) : 0; 9534028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9544028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (char_value > 0xFFFF) { 9554028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to punt to the real String.indexOf. 9564028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return false; 9574028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 9584028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9594028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Okay, we are commited to inlining this. 9604028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_return = GetReturn(false); 9614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_dest = InlineTarget(info); 9624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9634028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the string non-NULL? 9642700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_obj, rs_rDX); 9652700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee GenNullCheck(rs_rDX, info->opt_flags); 9663bc8615332b7848dec8c2297a40f7e4d176c0efbVladimir Marko info->opt_flags |= MIR_IGNORE_NULL_CHECK; // Record that we've null checked. 9674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Does the character fit in 16 bits? 9693a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang LIR* slowpath_branch = nullptr; 9704028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_char.is_const) { 9714028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We need the value in EAX. 9722700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rs_rAX, char_value); 9734028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 9744028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Character is not a constant; compare at runtime. 9752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_char, rs_rAX); 9763a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang slowpath_branch = OpCmpImmBranch(kCondGt, rs_rAX, 0xFFFF, nullptr); 9774028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 9784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9794028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // From here down, we know that we are looking for a char that fits in 16 bits. 980e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of reference to data array within the String object. 981e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int value_offset = mirror::String::ValueOffset().Int32Value(); 982e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of count within the String object. 983e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int count_offset = mirror::String::CountOffset().Int32Value(); 984e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Starting offset within data array. 985e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int offset_offset = mirror::String::OffsetOffset().Int32Value(); 986e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Start of char data with array_. 987e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); 9884028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9894028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Character is in EAX. 9904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Object pointer is in EDX. 9914028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9924028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We need to preserve EDI, but have no spare registers, so push it on the stack. 9934028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to remember that all stack addresses after this are offset by sizeof(EDI). 994091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Push32R, rs_rDI.GetReg()); 9954028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 9964028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Compute the number of words to search in to rCX. 997695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee Load32Disp(rs_rDX, count_offset, rs_rCX); 9984028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *length_compare = nullptr; 9994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell int start_value = 0; 1000a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov bool is_index_on_stack = false; 10014028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (zero_based) { 10024028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to handle an empty string. Use special instruction JECXZ. 10034028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare = NewLIR0(kX86Jecxz8); 10044028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1005a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee rl_start = info->args[2]; 10064028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to offset by the start index. 10074028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_start.is_const) { 10084028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = mir_graph_->ConstantValue(rl_start.orig_sreg); 10094028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = std::max(start_value, 0); 10104028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the start > count? 10122700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee length_compare = OpCmpImmBranch(kCondLe, rs_rCX, start_value, nullptr); 10134028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10144028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (start_value != 0) { 10152700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegImm(kOpSub, rs_rCX, start_value); 10164028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 10174028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 10184028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Runtime start index. 101930adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee rl_start = UpdateLocTyped(rl_start, kCoreReg); 10204028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_start.location == kLocPhysReg) { 1021a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Handle "start index < 0" case. 1022a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpXor, rs_rBX, rs_rBX); 1023a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpCmp, rl_start.reg, rs_rBX); 1024a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpCondRegReg(kOpCmov, kCondLt, rl_start.reg, rs_rBX); 1025a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov 1026a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // The length of the string should be greater than the start index. 10272700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee length_compare = OpCmpBranch(kCondLe, rs_rCX, rl_start.reg, nullptr); 10282700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegReg(kOpSub, rs_rCX, rl_start.reg); 1029a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov if (rl_start.reg == rs_rDI) { 1030a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // The special case. We will use EDI further, so lets put start index to stack. 1031091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Push32R, rs_rDI.GetReg()); 1032a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov is_index_on_stack = true; 1033a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov } 10344028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1035a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Load the start index from stack, remembering that we pushed EDI. 10364028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell int displacement = SRegOffset(rl_start.s_reg_low) + sizeof(uint32_t); 1037695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee Load32Disp(rs_rX86_SP, displacement, rs_rBX); 1038a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpXor, rs_rDI, rs_rDI); 1039a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpCmp, rs_rBX, rs_rDI); 1040a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpCondRegReg(kOpCmov, kCondLt, rs_rBX, rs_rDI); 1041a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov 1042a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov length_compare = OpCmpBranch(kCondLe, rs_rCX, rs_rBX, nullptr); 1043a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpRegReg(kOpSub, rs_rCX, rs_rBX); 1044a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Put the start index to stack. 1045091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Push32R, rs_rBX.GetReg()); 1046a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov is_index_on_stack = true; 10474028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 10484028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 10494028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 10504028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell DCHECK(length_compare != nullptr); 10514028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10524028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // ECX now contains the count in words to be searched. 10534028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10544028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Load the address of the string into EBX. 1055e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET. 1056695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee Load32Disp(rs_rDX, value_offset, rs_rDI); 1057695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee Load32Disp(rs_rDX, offset_offset, rs_rBX); 10582700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpLea(rs_rBX, rs_rDI, rs_rBX, 1, data_offset); 10594028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10604028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Now compute into EDI where the search will start. 10614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (zero_based || rl_start.is_const) { 10624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (start_value == 0) { 10632700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegCopy(rs_rDI, rs_rBX); 10644028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1065091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR3(kX86Lea32RM, rs_rDI.GetReg(), rs_rBX.GetReg(), 2 * start_value); 10664028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 10674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1068a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov if (is_index_on_stack == true) { 1069a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Load the start index from stack. 1070091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Pop32R, rs_rDX.GetReg()); 10712700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpLea(rs_rDI, rs_rBX, rs_rDX, 1, 0); 1072a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov } else { 1073a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov OpLea(rs_rDI, rs_rBX, rl_start.reg, 1, 0); 10744028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 10754028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 10764028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10774028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EDI now contains the start of the string to be searched. 10784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We are all prepared to do the search for the character. 10794028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell NewLIR0(kX86RepneScasw); 10804028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10814028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Did we find a match? 10824028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR* failed_branch = OpCondBranch(kCondNe, nullptr); 10834028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10844028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // yes, we matched. Compute the index of the result. 10854028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // index = ((curr_ptr - orig_ptr) / 2) - 1. 10862700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegReg(kOpSub, rs_rDI, rs_rBX); 10872700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegImm(kOpAsr, rs_rDI, 1); 1088091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rs_rDI.GetReg(), -1); 10894028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *all_done = NewLIR1(kX86Jmp8, 0); 10904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10914028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Failed to match; return -1. 10924028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *not_found = NewLIR0(kPseudoTargetLabel); 10934028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare->target = not_found; 10944028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell failed_branch->target = not_found; 10952700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rl_return.reg, -1); 10964028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 10974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // And join up at the end. 10984028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell all_done->target = NewLIR0(kPseudoTargetLabel); 10994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Restore EDI from the stack. 1100091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee NewLIR1(kX86Pop32R, rs_rDI.GetReg()); 11014028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 11024028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Out of line code returns here. 11033a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang if (slowpath_branch != nullptr) { 11044028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *return_point = NewLIR0(kPseudoTargetLabel); 11053a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang AddIntrinsicSlowPath(info, slowpath_branch, return_point); 11064028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 11074028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 11084028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell StoreValue(rl_dest, rl_return); 11094028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return true; 11104028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell} 11114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 1112ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell/* 1113ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @brief Enter an 'advance LOC' into the FDE buffer 1114ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param buf FDE buffer. 1115ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param increment Amount by which to increase the current location. 1116ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell */ 1117ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstatic void AdvanceLoc(std::vector<uint8_t>&buf, uint32_t increment) { 1118ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (increment < 64) { 1119ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Encoding in opcode. 1120ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(0x1 << 6 | increment); 1121ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } else if (increment < 256) { 1122ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Single byte delta. 1123ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(0x02); 1124ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(increment); 1125ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } else if (increment < 256 * 256) { 1126ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Two byte delta. 1127ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(0x03); 1128ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(increment & 0xff); 1129ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back((increment >> 8) & 0xff); 1130ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } else { 1131ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Four byte delta. 1132ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(0x04); 1133ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(buf, increment); 1134ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1135ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1136ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1137ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1138ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86CFIInitialization() { 1139ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell return X86Mir2Lir::ReturnCommonCallFrameInformation(); 1140ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1141ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1142ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86Mir2Lir::ReturnCommonCallFrameInformation() { 1143ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>; 1144ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1145ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Length of the CIE (except for this field). 1146ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 16); 1147ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1148ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // CIE id. 1149ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 0xFFFFFFFFU); 1150ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1151ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Version: 3. 1152ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x03); 1153ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1154ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Augmentation: empty string. 1155ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0); 1156ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1157ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Code alignment: 1. 1158ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x01); 1159ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1160ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Data alignment: -4. 1161ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x7C); 1162ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1163ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Return address register (R8). 1164ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x08); 1165ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1166ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Initial return PC is 4(ESP): DW_CFA_def_cfa R4 4. 1167ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0C); 1168ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x04); 1169ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x04); 1170ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1171ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Return address location: 0(SP): DW_CFA_offset R8 1 (* -4);. 1172ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x2 << 6 | 0x08); 1173ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x01); 1174ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1175ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // And 2 Noops to align to 4 byte boundary. 1176ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0); 1177ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0); 1178ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1179ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell DCHECK_EQ(cfi_info->size() & 3, 0U); 1180ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell return cfi_info; 1181ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1182ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1183ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstatic void EncodeUnsignedLeb128(std::vector<uint8_t>& buf, uint32_t value) { 1184ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint8_t buffer[12]; 1185ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint8_t *ptr = EncodeUnsignedLeb128(buffer, value); 1186ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell for (uint8_t *p = buffer; p < ptr; p++) { 1187ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell buf.push_back(*p); 1188ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1189ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1190ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1191ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() { 1192ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>; 1193ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1194ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Generate the FDE for the method. 1195ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell DCHECK_NE(data_offset_, 0U); 1196ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1197ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Length (will be filled in later in this routine). 1198ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 0); 1199ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1200ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // CIE_pointer (can be filled in by linker); might be left at 0 if there is only 1201ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // one CIE for the whole debug_frame section. 1202ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 0); 1203ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1204ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // 'initial_location' (filled in by linker). 1205ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, 0); 1206ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1207ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // 'address_range' (number of bytes in the method). 1208ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell PushWord(*cfi_info, data_offset_); 1209ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1210ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // The instructions in the FDE. 1211ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_decrement_ != nullptr) { 1212ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Advance LOC to just past the stack decrement. 1213ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t pc = NEXT_LIR(stack_decrement_)->offset; 1214ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell AdvanceLoc(*cfi_info, pc); 1215ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1216ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Now update the offset to the call frame: DW_CFA_def_cfa_offset frame_size. 1217ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0e); 1218ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell EncodeUnsignedLeb128(*cfi_info, frame_size_); 1219ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1220ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We continue with that stack until the epilogue. 1221ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_increment_ != nullptr) { 1222ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t new_pc = NEXT_LIR(stack_increment_)->offset; 1223ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell AdvanceLoc(*cfi_info, new_pc - pc); 1224ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1225ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We probably have code snippets after the epilogue, so save the 1226ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // current state: DW_CFA_remember_state. 1227ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0a); 1228ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1229ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We have now popped the stack: DW_CFA_def_cfa_offset 4. There is only the return 1230ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // PC on the stack now. 1231ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0e); 1232ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell EncodeUnsignedLeb128(*cfi_info, 4); 1233ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1234ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Everything after that is the same as before the epilogue. 1235ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Stack bump was followed by RET instruction. 1236ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell LIR *post_ret_insn = NEXT_LIR(NEXT_LIR(stack_increment_)); 1237ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (post_ret_insn != nullptr) { 1238ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell pc = new_pc; 1239ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell new_pc = post_ret_insn->offset; 1240ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell AdvanceLoc(*cfi_info, new_pc - pc); 1241ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Restore the state: DW_CFA_restore_state. 1242ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0x0b); 1243ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1244ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1245ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1246ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1247ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Padding to a multiple of 4 1248ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell while ((cfi_info->size() & 3) != 0) { 1249ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // DW_CFA_nop is encoded as 0. 1250ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell cfi_info->push_back(0); 1251ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1252ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1253ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Set the length of the FDE inside the generated bytes. 1254ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t length = cfi_info->size() - 4; 1255ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[0] = length; 1256ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[1] = length >> 8; 1257ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[2] = length >> 16; 1258ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell (*cfi_info)[3] = length >> 24; 1259ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell return cfi_info; 1260ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1261ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1262d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) { 1263d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 1264d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell case kMirOpConstVector: 1265d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell GenConst128(bb, mir); 1266d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell break; 1267d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell default: 1268d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell break; 1269d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1270d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1271d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1272d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenConst128(BasicBlock* bb, MIR* mir) { 1273d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell int type_size = mir->dalvikInsn.vA; 1274d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // We support 128 bit vectors. 1275d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell DCHECK_EQ(type_size & 0xFFFF, 128); 1276d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell int reg = mir->dalvikInsn.vB; 1277d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell DCHECK_LT(reg, 8); 1278d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell uint32_t *args = mir->dalvikInsn.arg; 1279d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Check for all 0 case. 1280d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (args[0] == 0 && args[1] == 0 && args[2] == 0 && args[3] == 0) { 1281d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell NewLIR2(kX86XorpsRR, reg, reg); 1282d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return; 1283d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1284d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Okay, load it from the constant vector area. 1285d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell LIR *data_target = ScanVectorLiteral(mir); 1286d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (data_target == nullptr) { 1287d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell data_target = AddVectorLiteral(mir); 1288d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1289d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1290d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Address the start of the method. 1291d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low); 1292d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell rl_method = LoadValue(rl_method, kCoreReg); 1293d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1294d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Load the proper value from the literal area. 1295d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // We don't know the proper offset for the value, so pick one that will force 1296d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // 4 byte offset. We will fix this up in the assembler later to have the right 1297d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // value. 1298d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell LIR *load = NewLIR3(kX86Mova128RM, reg, rl_method.reg.GetReg(), 256 /* bogus */); 1299d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell load->flags.fixup = kFixupLoad; 1300d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell load->target = data_target; 1301d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell SetMemRefType(load, true, kLiteral); 1302d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1303d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1304d65c51a556e6649db4e18bd083c8fec37607a442Mark MendellLIR *X86Mir2Lir::ScanVectorLiteral(MIR *mir) { 1305d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg); 1306d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell for (LIR *p = const_vectors_; p != nullptr; p = p->next) { 1307d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (args[0] == p->operands[0] && args[1] == p->operands[1] && 1308d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell args[2] == p->operands[2] && args[3] == p->operands[3]) { 1309d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return p; 1310d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1311d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1312d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return nullptr; 1313d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1314d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1315d65c51a556e6649db4e18bd083c8fec37607a442Mark MendellLIR *X86Mir2Lir::AddVectorLiteral(MIR *mir) { 1316d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell LIR* new_value = static_cast<LIR*>(arena_->Alloc(sizeof(LIR), kArenaAllocData)); 1317d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg); 1318d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell new_value->operands[0] = args[0]; 1319d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell new_value->operands[1] = args[1]; 1320d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell new_value->operands[2] = args[2]; 1321d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell new_value->operands[3] = args[3]; 1322d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell new_value->next = const_vectors_; 1323d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (const_vectors_ == nullptr) { 1324d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell estimated_native_code_size_ += 12; // Amount needed to align to 16 byte boundary. 1325d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1326d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell estimated_native_code_size_ += 16; // Space for one vector. 1327d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell const_vectors_ = new_value; 1328d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return new_value; 1329d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1330d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 13317934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 1332