target_x86.cc revision b72c723bfb21e05cb9b0a7999db805df93fcaee8
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 176dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev#include <cstdarg> 18f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray#include <inttypes.h> 196dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev#include <string> 20f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray 218366ca0d7ba3b80a2d5be65ba436446cc32440bdElliott Hughes#include "arch/instruction_set_features.h" 2253c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe#include "backend_x86.h" 2302031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h" 247940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/compiler_internals.h" 257940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h" 26b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h" 277e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers#include "mirror/array-inl.h" 28f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko#include "mirror/art_method.h" 29e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell#include "mirror/string.h" 30b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A#include "oat.h" 31641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h" 32547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen#include "utils/dwarf_cfi.h" 33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 34efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art { 35efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 36089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_32[] = { 379ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI, 389ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 39089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_64[] = { 4076af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI, 41091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_r8, rs_r9, rs_r10, rs_r11, rs_r12, rs_r13, rs_r14, rs_r15 42efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 43089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_64q[] = { 440999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko rs_r0q, rs_r1q, rs_r2q, rs_r3q, rs_rX86_SP_64, rs_r5q, rs_r6q, rs_r7q, 45a20468c004264592f309a548fc71ba62a69b8742Dmitry Petrochenko rs_r8q, rs_r9q, rs_r10q, rs_r11q, rs_r12q, rs_r13q, rs_r14q, rs_r15q 460999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko}; 47089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_regs_arr_32[] = { 489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 50089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_regs_arr_64[] = { 51091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 52091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 53efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 54089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_regs_arr_32[] = { 559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 57089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_regs_arr_64[] = { 58091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 59091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 60efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 61c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr RegStorage xp_regs_arr_32[] = { 62c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 63c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov}; 64c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr RegStorage xp_regs_arr_64[] = { 65c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 66c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr8, rs_xr9, rs_xr10, rs_xr11, rs_xr12, rs_xr13, rs_xr14, rs_xr15 67c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov}; 68089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage reserved_regs_arr_32[] = {rs_rX86_SP_32}; 6976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenkostatic constexpr RegStorage reserved_regs_arr_64[] = {rs_rX86_SP_32}; 70089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage reserved_regs_arr_64q[] = {rs_rX86_SP_64}; 71089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_32[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX}; 72089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_64[] = { 739ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rSI, rs_rDI, 749ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_r8, rs_r9, rs_r10, rs_r11 759ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 76c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 77c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// How to add register to be available for promotion: 78c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 1) Remove register from array defining temp 79c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 2) Update ClobberCallerSave 80c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 3) Update JNI compiler ABI: 81c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 3.1) add reg in JniCallingConvention method 82c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 3.2) update CoreSpillMask/FpSpillMask 83c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4) Update entrypoints 84c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.1) Update constants in asm_support_x86_64.h for new frame size 85c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.2) Remove entry in SmashCallerSaves 86c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.3) Update jni_entrypoints to spill/unspill new callee save reg 87c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.4) Update quick_entrypoints to spill/unspill new callee save reg 88c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 5) Update runtime ABI 89c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 5.1) Update quick_method_frame_info with new required spills 90c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 5.2) Update QuickArgumentVisitor with new offsets to gprs and xmms 91c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// Note that you cannot use register corresponding to incoming args 92c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// according to ABI and QCG needs one additional XMM temp for 93c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// bulk copy in preparation to call. 94089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_64q[] = { 950999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko rs_r0q, rs_r1q, rs_r2q, rs_r6q, rs_r7q, 960999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko rs_r8q, rs_r9q, rs_r10q, rs_r11q 970999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko}; 98089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_temps_arr_32[] = { 999ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 1009ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 101089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_temps_arr_64[] = { 102091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 103c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_fr8, rs_fr9, rs_fr10, rs_fr11 104091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 105089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_temps_arr_32[] = { 1069ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 1079ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 108089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_temps_arr_64[] = { 109091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 110c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_dr8, rs_dr9, rs_dr10, rs_dr11 111091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 112091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 113089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage xp_temps_arr_32[] = { 114fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 115fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}; 116089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage xp_temps_arr_64[] = { 117fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 118c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr8, rs_xr9, rs_xr10, rs_xr11 119fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}; 120fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 121089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> empty_pool; 122089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_32(core_regs_arr_32); 123089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_64(core_regs_arr_64); 124089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_64q(core_regs_arr_64q); 125089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_regs_32(sp_regs_arr_32); 126089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_regs_64(sp_regs_arr_64); 127089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_regs_32(dp_regs_arr_32); 128089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_regs_64(dp_regs_arr_64); 129c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr ArrayRef<const RegStorage> xp_regs_32(xp_regs_arr_32); 130c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr ArrayRef<const RegStorage> xp_regs_64(xp_regs_arr_64); 131089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_32(reserved_regs_arr_32); 132089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_64(reserved_regs_arr_64); 133089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_64q(reserved_regs_arr_64q); 134089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_32(core_temps_arr_32); 135089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_64(core_temps_arr_64); 136089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_64q(core_temps_arr_64q); 137089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_temps_32(sp_temps_arr_32); 138089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_temps_64(sp_temps_arr_64); 139089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_temps_32(dp_temps_arr_32); 140089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_temps_64(dp_temps_arr_64); 141089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Marko 142089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> xp_temps_32(xp_temps_arr_32); 143089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> xp_temps_64(xp_temps_arr_64); 144fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1452ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturn() { 14600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return; 147efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 148efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 149a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbeeRegLocation X86Mir2Lir::LocCReturnRef() { 150a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu return cu_->target64 ? x86_64_loc_c_return_ref : x86_loc_c_return_ref; 151a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee} 152a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee 1532ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnWide() { 154dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina return cu_->target64 ? x86_64_loc_c_return_wide : x86_loc_c_return_wide; 155efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 156efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1572ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnFloat() { 15800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_float; 159efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 160efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1612ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnDouble() { 16200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_double; 163efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 164efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 165b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers// 32-bit reg storage locations for 32-bit targets. 166b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogersstatic const RegStorage RegStorage32FromSpecialTargetRegister_Target32[] { 167b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kSelf - Thread pointer. 168b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kSuspend - Used to reduce suspend checks for some targets. 169b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kLr - no register as the return address is pushed on entry. 170b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kPc - not exposed on X86 see kX86StartOfMethod. 171b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rX86_SP_32, // kSp 172b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rAX, // kArg0 173b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rCX, // kArg1 174b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rDX, // kArg2 175b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rBX, // kArg3 176b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kArg4 177b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kArg5 178b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kArg6 179b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kArg7 180b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rAX, // kFArg0 181b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rCX, // kFArg1 182b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rDX, // kFArg2 183b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rBX, // kFArg3 184b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg4 185b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg5 186b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg6 187b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg7 188b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg8 189b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg9 190b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg10 191b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg11 192b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg12 193b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg13 194b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg14 195b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg15 196b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rAX, // kRet0 197b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rDX, // kRet1 198b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rAX, // kInvokeTgt 199b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rAX, // kHiddenArg - used to hold the method index before copying to fr0. 200b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_fr0, // kHiddenFpArg 201b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rCX, // kCount 202b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers}; 203b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers 204b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers// 32-bit reg storage locations for 64-bit targets. 205b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogersstatic const RegStorage RegStorage32FromSpecialTargetRegister_Target64[] { 206b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kSelf - Thread pointer. 207b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kSuspend - Used to reduce suspend checks for some targets. 208b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kLr - no register as the return address is pushed on entry. 209b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kPc - TODO: RIP based addressing. 210b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rX86_SP_32, // kSp 211b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rDI, // kArg0 212b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rSI, // kArg1 213b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rDX, // kArg2 214b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rCX, // kArg3 215b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_r8, // kArg4 216b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_r9, // kArg5 217b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kArg6 218b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kArg7 219b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_fr0, // kFArg0 220b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_fr1, // kFArg1 221b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_fr2, // kFArg2 222b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_fr3, // kFArg3 223b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_fr4, // kFArg4 224b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_fr5, // kFArg5 225b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_fr6, // kFArg6 226b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_fr7, // kFArg7 227b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg8 228b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg9 229b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg10 230b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg11 231b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg12 232b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg13 233b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg14 234b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kFArg15 235b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rAX, // kRet0 236b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rDX, // kRet1 237b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rAX, // kInvokeTgt 238b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rAX, // kHiddenArg 239b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers RegStorage::InvalidReg(), // kHiddenFpArg 240b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers rs_rCX, // kCount 241b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers}; 242b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogersstatic_assert(arraysize(RegStorage32FromSpecialTargetRegister_Target32) == 243b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers arraysize(RegStorage32FromSpecialTargetRegister_Target64), 244b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers "Mismatch in RegStorage array sizes"); 245b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers 246a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu// Return a target-dependent special register for 32-bit. 247b28c1c06236751aa5c9e64dcb68b3c940341e496Ian RogersRegStorage X86Mir2Lir::TargetReg32(SpecialTargetRegister reg) const { 248b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_EQ(RegStorage32FromSpecialTargetRegister_Target32[kCount], rs_rCX); 249b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_EQ(RegStorage32FromSpecialTargetRegister_Target64[kCount], rs_rCX); 250b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_LT(reg, arraysize(RegStorage32FromSpecialTargetRegister_Target32)); 251b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers return cu_->target64 ? RegStorage32FromSpecialTargetRegister_Target64[reg] 252b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers : RegStorage32FromSpecialTargetRegister_Target32[reg]; 253efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 254efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 255a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying FuRegStorage X86Mir2Lir::TargetReg(SpecialTargetRegister reg) { 2566a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(reg); 257a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LOG(FATAL) << "Do not use this function!!!"; 2586a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 259a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu} 260a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu 261efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 262efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Decode the register id. 263efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 2648dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask X86Mir2Lir::GetRegMaskCommon(const RegStorage& reg) const { 2658dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko /* Double registers in x86 are just a single FP register. This is always just a single bit. */ 2668dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko return ResourceMask::Bit( 2678dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko /* FP register starts at bit position 16 */ 2688dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ((reg.IsFloat() || reg.StorageSize() > 8) ? kX86FPReg0 : 0) + reg.GetRegNum()); 2698dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko} 2708dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko 2718dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask X86Mir2Lir::GetPCUseDefEncoding() const { 2728dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko return kEncodeNone; 273efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 274efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 2758dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid X86Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags, 2768dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ResourceMask* use_mask, ResourceMask* def_mask) { 2776a58cb16d803c9a7b3a75ccac8be19dd9d4e520dDmitry Petrochenko DCHECK(cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64); 278b48819db07f9a0992a72173380c24249d7fc648abuzbee DCHECK(!lir->flags.use_def_invalid); 279efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 280efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // X86-specific resource map setup here. 281efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USE_SP) { 2828dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko use_mask->SetBit(kX86RegSP); 283efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 284efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 285efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEF_SP) { 2868dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko def_mask->SetBit(kX86RegSP); 287efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFA) { 2908dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(def_mask, rs_rAX.GetReg()); 291efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 292efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFD) { 2948dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(def_mask, rs_rDX.GetReg()); 295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEA) { 2978dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rAX.GetReg()); 298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEC) { 3018dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rCX.GetReg()); 302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 304efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USED) { 3058dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rDX.GetReg()); 306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 30770b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko 30870b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko if (flags & REG_USEB) { 3098dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rBX.GetReg()); 31070b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko } 3114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 3124028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Fixup hard to describe instruction: Uses rAX, rCX, rDI; sets rDI. 3134028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (lir->opcode == kX86RepneScasw) { 3148dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rAX.GetReg()); 3158dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rCX.GetReg()); 3168dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rDI.GetReg()); 3178dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(def_mask, rs_rDI.GetReg()); 3184028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 319e90501da0222717d75c126ebf89569db3976927eSerguei Katkov 320e90501da0222717d75c126ebf89569db3976927eSerguei Katkov if (flags & USE_FP_STACK) { 3218dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko use_mask->SetBit(kX86FPStack); 3228dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko def_mask->SetBit(kX86FPStack); 323e90501da0222717d75c126ebf89569db3976927eSerguei Katkov } 324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* For dumping instructions */ 327efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86RegName[] = { 328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 332efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86CondName[] = { 333efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "O", 334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NO", 335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "B/NAE/C", 336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NB/AE/NC", 337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "Z/EQ", 338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NZ/NE", 339efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "BE/NA", 340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NBE/A", 341efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "S", 342efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NS", 343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "P/PE", 344efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NP/PO", 345efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "L/NGE", 346efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NL/GE", 347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "LE/NG", 348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NLE/G" 349efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 350efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 351efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 352efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Interpret a format string and build a string no longer than size 353efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See format key in Assemble.cc. 354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 3551fd3346740dfb7f47be9922312b68a4227fada96buzbeestd::string X86Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) { 356efc6369224b036a1fb77849f7ae65b3492c832c0buzbee std::string buf; 357efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t i = 0; 358efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t fmt_len = strlen(fmt); 359efc6369224b036a1fb77849f7ae65b3492c832c0buzbee while (i < fmt_len) { 360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (fmt[i] != '!') { 361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += fmt[i]; 362efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 363efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 364efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 365efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 366efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char operand_number_ch = fmt[i]; 367efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 368efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (operand_number_ch == '!') { 369efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += "!"; 370efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 371efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand_number = operand_number_ch - '0'; 372efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(operand_number, 6); // Expect upto 6 LIR operands. 373efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 374efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand = lir->operands[operand_number]; 375efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (fmt[i]) { 376efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'c': 377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(static_cast<size_t>(operand), sizeof(x86CondName)); 378efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += x86CondName[operand]; 379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'd': 381efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("%d", operand); 382efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 3835192cbb12856b12620dc346758605baaa1469cedYixin Shou case 'q': { 3845192cbb12856b12620dc346758605baaa1469cedYixin Shou int64_t value = static_cast<int64_t>(static_cast<int64_t>(operand) << 32 | 3855192cbb12856b12620dc346758605baaa1469cedYixin Shou static_cast<uint32_t>(lir->operands[operand_number+1])); 3865192cbb12856b12620dc346758605baaa1469cedYixin Shou buf +=StringPrintf("%" PRId64, value); 387e70f179aca4f13b15be8a47a4d9e5b6c2422c69aHaitao Feng break; 3885192cbb12856b12620dc346758605baaa1469cedYixin Shou } 389efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'p': { 3900d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(operand)); 391fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee buf += StringPrintf("0x%08x", tab_rec->offset); 392efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'r': 395091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (RegStorage::IsFloat(operand)) { 396091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int fp_reg = RegStorage::RegNum(operand); 397efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("xmm%d", fp_reg); 398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 399091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int reg_num = RegStorage::RegNum(operand); 400091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK_LT(static_cast<size_t>(reg_num), sizeof(x86RegName)); 401091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee buf += x86RegName[reg_num]; 402efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 't': 405107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers buf += StringPrintf("0x%08" PRIxPTR " (L%p)", 406107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers reinterpret_cast<uintptr_t>(base_addr) + lir->offset + operand, 407107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers lir->target); 408efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 409efc6369224b036a1fb77849f7ae65b3492c832c0buzbee default: 410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("DecodeError '%c'", fmt[i]); 411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 415efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return buf; 418efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 419efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4208dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid X86Mir2Lir::DumpResourceMask(LIR *x86LIR, const ResourceMask& mask, const char *prefix) { 421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char buf[256]; 422efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf[0] = 0; 423efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4248dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.Equals(kEncodeAll)) { 425efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcpy(buf, "all"); 426efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 427efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char num[8]; 428efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int i; 429efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 430efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (i = 0; i < kX86RegEnd; i++) { 4318dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(i)) { 432988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(num, arraysize(num), "%d ", i); 433efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, num); 434efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 435efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 436efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4378dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kCCode)) { 438efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "cc "); 439efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 440efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Memory bits */ 4418dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (x86LIR && (mask.HasBit(ResourceMask::kDalvikReg))) { 442988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s", 443988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers DECODE_ALIAS_INFO_REG(x86LIR->flags.alias_info), 444988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers (DECODE_ALIAS_INFO_WIDE(x86LIR->flags.alias_info)) ? "(+1)" : ""); 445efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 4468dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kLiteral)) { 447efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "lit "); 448efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 449efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4508dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kHeapRef)) { 451efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "heap "); 452efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 4538dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kMustNotAlias)) { 454efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "noalias "); 455efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 456efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 457efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (buf[0]) { 458efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(INFO) << prefix << ": " << buf; 459efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 460efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 46102031b185b4653e6c72e21f7a51238b903f6d638buzbee 4621fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::AdjustSpillMask() { 463efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Adjustment for LR spilling, x86 has no LR so nothing to do here 464091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee core_spill_mask_ |= (1 << rs_rRET.GetRegNum()); 4651fd3346740dfb7f47be9922312b68a4227fada96buzbee num_core_spills_++; 466efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 467efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 468e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark MendellRegStorage X86Mir2Lir::AllocateByteRegister() { 4697e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu RegStorage reg = AllocTypedTemp(false, kCoreReg); 470dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 471b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_LT(reg.GetRegNum(), rs_rX86_SP_32.GetRegNum()); 4727e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu } 4737e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu return reg; 4747e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu} 4757e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu 47660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan BanerjiRegStorage X86Mir2Lir::Get128BitRegister(RegStorage reg) { 477b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return GetRegInfo(reg)->Master()->GetReg(); 47860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 47960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 480b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogersbool X86Mir2Lir::IsByteRegister(RegStorage reg) const { 481b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers return cu_->target64 || reg.GetRegNum() < rs_rX86_SP_32.GetRegNum(); 482e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell} 483e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell 484efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Clobber all regs that might be used by an external C call */ 48531c2aac7137b69d5622eea09597500731fbee2efVladimir Markovoid X86Mir2Lir::ClobberCallerSave() { 486dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 487c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rAX); 488c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rCX); 489c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rDX); 490c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rSI); 491c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rDI); 492c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 49335ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r8); 49435ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r9); 49535ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r10); 49635ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r11); 49735ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu 49835ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr8); 49935ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr9); 50035ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr10); 50135ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr11); 502c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } else { 503c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rAX); 504c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rCX); 505c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rDX); 506c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rBX); 50735ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu } 508c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 509c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr0); 510c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr1); 511c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr2); 512c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr3); 513c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr4); 514c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr5); 515c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr6); 516c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr7); 517efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 518efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5191fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation X86Mir2Lir::GetReturnWideAlt() { 52052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturnWide(); 521b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_EQ(res.reg.GetLowReg(), rs_rAX.GetReg()); 522b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_EQ(res.reg.GetHighReg(), rs_rDX.GetReg()); 523091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rAX); 524091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 525091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rAX); 526091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 527091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkWide(res.reg); 528efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 529efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 530efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5312ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::GetReturnAlt() { 53252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturn(); 533091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee res.reg.SetReg(rs_rDX.GetReg()); 534091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 535091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 536efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 537efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 538efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 539efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 5402ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::LockCallTemps() { 541b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kArg0)); 542b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kArg1)); 543b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kArg2)); 544b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kArg3)); 545dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 546b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kArg4)); 547b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kArg5)); 548b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kFArg0)); 549b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kFArg1)); 550b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kFArg2)); 551b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kFArg3)); 552b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kFArg4)); 553b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kFArg5)); 554b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kFArg6)); 555b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LockTemp(TargetReg32(kFArg7)); 55658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 557efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 558efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 559efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 5602ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::FreeCallTemps() { 561b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kArg0)); 562b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kArg1)); 563b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kArg2)); 564b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kArg3)); 565dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 566b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kArg4)); 567b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kArg5)); 568b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kFArg0)); 569b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kFArg1)); 570b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kFArg2)); 571b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kFArg3)); 572b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kFArg4)); 573b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kFArg5)); 574b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kFArg6)); 575b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers FreeTemp(TargetReg32(kFArg7)); 57658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 577efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 578efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 57999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusorubool X86Mir2Lir::ProvidesFullMemoryBarrier(X86OpCode opcode) { 58099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru switch (opcode) { 58199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgMR: 58299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgAR: 5830f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers case kX86LockCmpxchg64M: 5840f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers case kX86LockCmpxchg64A: 58599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86XchgMR: 58699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86Mfence: 58799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Atomic memory instructions provide full barrier. 58899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return true; 58999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru default: 59099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru break; 59199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 59299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 59399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Conservative if cannot prove it provides full barrier. 59499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return false; 59599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru} 59699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 597b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampebool X86Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) { 5988366ca0d7ba3b80a2d5be65ba436446cc32440bdElliott Hughes if (!cu_->GetInstructionSetFeatures()->IsSmp()) { 5998366ca0d7ba3b80a2d5be65ba436446cc32440bdElliott Hughes return false; 6008366ca0d7ba3b80a2d5be65ba436446cc32440bdElliott Hughes } 60199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Start off with using the last LIR as the barrier. If it is not enough, then we will update it. 60299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru LIR* mem_barrier = last_lir_insn_; 60399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 604b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe bool ret = false; 60599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru /* 60648f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm * According to the JSR-133 Cookbook, for x86 only StoreLoad/AnyAny barriers need memory fence. 60748f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm * All other barriers (LoadAny, AnyStore, StoreStore) are nops due to the x86 memory model. 60848f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm * For those cases, all we need to ensure is that there is a scheduling barrier in place. 60999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru */ 61048f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm if (barrier_kind == kAnyAny) { 61199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If no LIR exists already that can be used a barrier, then generate an mfence. 61299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 61399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 614b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe ret = true; 61599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 61699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 61799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If last instruction does not provide full barrier, then insert an mfence. 61899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (ProvidesFullMemoryBarrier(static_cast<X86OpCode>(mem_barrier->opcode)) == false) { 61999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 620b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe ret = true; 62199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 622b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler } else if (barrier_kind == kNTStoreStore) { 623b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler mem_barrier = NewLIR0(kX86Sfence); 624b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler ret = true; 62599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 62699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 62799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Now ensure that a scheduling barrier is in place. 62899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 62999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru GenBarrier(); 63099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } else { 63199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Mark as a scheduling barrier. 63299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru DCHECK(!mem_barrier->flags.use_def_invalid); 6338dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko mem_barrier->u.m.def_mask = &kEncodeAll; 63499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 635b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe return ret; 636efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 63700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee 6381fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::CompilerInitializeRegAlloc() { 639dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 640e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64q, sp_regs_64, 641e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko dp_regs_64, reserved_regs_64, reserved_regs_64q, 642e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko core_temps_64, core_temps_64q, 643e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko sp_temps_64, dp_temps_64)); 6449ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 645e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, sp_regs_32, 646e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko dp_regs_32, reserved_regs_32, empty_pool, 647e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko core_temps_32, empty_pool, 648e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko sp_temps_32, dp_temps_32)); 6499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 650091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 651091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Target-specific adjustments. 652091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 653fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Add in XMM registers. 654c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov const ArrayRef<const RegStorage> *xp_regs = cu_->target64 ? &xp_regs_64 : &xp_regs_32; 655c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (RegStorage reg : *xp_regs) { 656fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell RegisterInfo* info = new (arena_) RegisterInfo(reg, GetRegMaskCommon(reg)); 657e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reginfo_map_[reg.GetReg()] = info; 658c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 659c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov const ArrayRef<const RegStorage> *xp_temps = cu_->target64 ? &xp_temps_64 : &xp_temps_32; 660c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (RegStorage reg : *xp_temps) { 661c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov RegisterInfo* xp_reg_info = GetRegInfo(reg); 662c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov xp_reg_info->SetIsTemp(true); 663fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 664fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 665091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Alias single precision xmm to double xmms. 666091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: as needed, add larger vector sizes - alias all to the largest. 667e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (RegisterInfo* info : reg_pool_->sp_regs_) { 668091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int sp_reg_num = info->GetReg().GetRegNum(); 669fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell RegStorage xp_reg = RegStorage::Solo128(sp_reg_num); 670fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell RegisterInfo* xp_reg_info = GetRegInfo(xp_reg); 671fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // 128-bit xmm vector register's master storage should refer to itself. 672fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell DCHECK_EQ(xp_reg_info, xp_reg_info->Master()); 673fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 674fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Redirect 32-bit vector's master storage to 128-bit vector. 675fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell info->SetMaster(xp_reg_info); 676fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 67776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko RegStorage dp_reg = RegStorage::FloatSolo64(sp_reg_num); 678091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegisterInfo* dp_reg_info = GetRegInfo(dp_reg); 679fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Redirect 64-bit vector's master storage to 128-bit vector. 680fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell dp_reg_info->SetMaster(xp_reg_info); 68176af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // Singles should show a single 32-bit mask bit, at first referring to the low half. 68276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko DCHECK_EQ(info->StorageMask(), 0x1U); 68376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko } 68476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko 685dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 68676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // Alias 32bit W registers to corresponding 64bit X registers. 687e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (RegisterInfo* info : reg_pool_->core_regs_) { 68876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko int x_reg_num = info->GetReg().GetRegNum(); 68976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko RegStorage x_reg = RegStorage::Solo64(x_reg_num); 69076af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko RegisterInfo* x_reg_info = GetRegInfo(x_reg); 69176af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // 64bit X register's master storage should refer to itself. 69276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko DCHECK_EQ(x_reg_info, x_reg_info->Master()); 69376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // Redirect 32bit W master storage to 64bit X. 69476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko info->SetMaster(x_reg_info); 69576af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // 32bit W should show a single 32-bit mask bit, at first referring to the low half. 69676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko DCHECK_EQ(info->StorageMask(), 0x1U); 69776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko } 698efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 699091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 700091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods. 701091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: adjust for x86/hard float calling convention. 702091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_core_reg_ = 2; 703091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_sp_reg_ = 2; 704091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_dp_reg_ = 1; 705efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 706efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 70760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjiint X86Mir2Lir::VectorRegisterSize() { 70860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return 128; 70960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 71060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 711b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Aint X86Mir2Lir::NumReservableVectorRegisters(bool long_or_fp) { 712b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int num_vector_temps = cu_->target64 ? xp_temps_64.size() : xp_temps_32.size(); 713b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 714b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Leave a few temps for use by backend as scratch. 715b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return long_or_fp ? num_vector_temps - 2 : num_vector_temps - 1; 71660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 71760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 7181fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::SpillCoreRegs() { 7191fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_core_spills_ == 0) { 720efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 721efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 722efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Spill mask not including fake return address register 723091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 724b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers int offset = 725b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 726c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov OpSize size = cu_->target64 ? k64 : k32; 727b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 728efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (int reg = 0; mask; mask >>= 1, reg++) { 729efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & 0x1) { 730b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rSP, offset, 731b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg), 732c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov size, kNotVolatile); 7339ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko offset += GetInstructionSetPointerSize(cu_->instruction_set); 734efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 735efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 736efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 737efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 7381fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::UnSpillCoreRegs() { 7391fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_core_spills_ == 0) { 740efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 741efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 742efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Spill mask not including fake return address register 743091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 7449ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 745c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov OpSize size = cu_->target64 ? k64 : k32; 746b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 747efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (int reg = 0; mask; mask >>= 1, reg++) { 748efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & 0x1) { 749b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LoadBaseDisp(rs_rSP, offset, cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg), 750c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov size, kNotVolatile); 7519ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko offset += GetInstructionSetPointerSize(cu_->instruction_set); 752efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 753efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 754efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 755efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 756c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovvoid X86Mir2Lir::SpillFPRegs() { 757c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (num_fp_spills_ == 0) { 758c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov return; 759c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 760c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov uint32_t mask = fp_spill_mask_; 761b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers int offset = frame_size_ - 762b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers (GetInstructionSetPointerSize(cu_->instruction_set) * (num_fp_spills_ + num_core_spills_)); 763b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 764c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (int reg = 0; mask; mask >>= 1, reg++) { 765c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (mask & 0x1) { 766b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rSP, offset, RegStorage::FloatSolo64(reg), k64, kNotVolatile); 767c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov offset += sizeof(double); 768c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 769c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 770c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov} 771c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovvoid X86Mir2Lir::UnSpillFPRegs() { 772c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (num_fp_spills_ == 0) { 773c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov return; 774c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 775c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov uint32_t mask = fp_spill_mask_; 776b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers int offset = frame_size_ - 777b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers (GetInstructionSetPointerSize(cu_->instruction_set) * (num_fp_spills_ + num_core_spills_)); 778b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 779c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (int reg = 0; mask; mask >>= 1, reg++) { 780c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (mask & 0x1) { 781b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LoadBaseDisp(rs_rSP, offset, RegStorage::FloatSolo64(reg), 782c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov k64, kNotVolatile); 783c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov offset += sizeof(double); 784c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 785c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 786c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov} 787c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 788c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 7892ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::IsUnconditionalBranch(LIR* lir) { 790cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32); 791efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 792efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 793674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoRegisterClass X86Mir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) { 794e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu // X86_64 can handle any size. 795dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 79606839f868c9c4bb1f2f6333f9e88a560e80bcad8Chao-ying Fu return RegClassBySize(size); 797e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } 798e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu 799674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko if (UNLIKELY(is_volatile)) { 800674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // On x86, atomic 64-bit load/store requires an fp register. 801674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // Smaller aligned load/store is atomic for both core and fp registers. 802674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko if (size == k64 || size == kDouble) { 803674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return kFPReg; 804674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko } 805674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko } 806674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return RegClassBySize(size); 807674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko} 808674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 809dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena SayapinaX86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena) 81055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell : Mir2Lir(cu, mir_graph, arena), 811dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers base_of_code_(nullptr), store_method_addr_(false), store_method_addr_used_(false), 812e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko method_address_insns_(arena->Adapter()), 813e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko class_type_address_insns_(arena->Adapter()), 814e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko call_method_insns_(arena->Adapter()), 815dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina stack_decrement_(nullptr), stack_increment_(nullptr), 816d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell const_vectors_(nullptr) { 817e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko method_address_insns_.reserve(100); 818e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko class_type_address_insns_.reserve(100); 819e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko call_method_insns_.reserve(100); 820d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell store_method_addr_used_ = false; 821dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers for (int i = 0; i < kX86Last; i++) { 8226a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers DCHECK_EQ(X86Mir2Lir::EncodingMap[i].opcode, i) 8236a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name 8246a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers << " is wrong: expecting " << i << ", seeing " 8256a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode); 826efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 8271fd3346740dfb7f47be9922312b68a4227fada96buzbee} 8281fd3346740dfb7f47be9922312b68a4227fada96buzbee 829862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 830862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee ArenaAllocator* const arena) { 831dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina return new X86Mir2Lir(cu, mir_graph, arena); 832efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 833efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 834984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe// Not used in x86(-64) 835984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas GampeRegStorage X86Mir2Lir::LoadHelper(QuickEntrypointEnum trampoline) { 8366a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(trampoline); 8372f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe LOG(FATAL) << "Unexpected use of LoadHelper in x86"; 8386a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 8392f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe} 8402f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe 841b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave AllisonLIR* X86Mir2Lir::CheckSuspendUsingLoad() { 84269dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // First load the pointer in fs:[suspend-trigger] into eax 84369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // Then use a test instruction to indirect via that address. 844dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison if (cu_->target64) { 845dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison NewLIR2(kX86Mov64RT, rs_rAX.GetReg(), 846dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison Thread::ThreadSuspendTriggerOffset<8>().Int32Value()); 847dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison } else { 848dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison NewLIR2(kX86Mov32RT, rs_rAX.GetReg(), 849dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison Thread::ThreadSuspendTriggerOffset<4>().Int32Value()); 850dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison } 85169dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison return NewLIR3(kX86Test32RM, rs_rAX.GetReg(), rs_rAX.GetReg(), 0); 852b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison} 853b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison 8542ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t X86Mir2Lir::GetTargetInstFlags(int opcode) { 855409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 8561fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].flags; 8571bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 8581bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 8592ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstName(int opcode) { 860409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 8611fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].name; 8621bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 8631bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 8642ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstFmt(int opcode) { 865409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 8661fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].fmt; 8671bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 8681bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 869d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbeevoid X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) { 870d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Can we do this directly to memory? 871d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee rl_dest = UpdateLocWide(rl_dest); 872d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee if ((rl_dest.location == kLocDalvikFrame) || 873d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee (rl_dest.location == kLocCompilerTemp)) { 874d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_lo = Low32Bits(value); 875d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_hi = High32Bits(value); 876b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers int r_base = rs_rX86_SP_32.GetReg(); 877d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int displacement = SRegOffset(rl_dest.s_reg_low); 878d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 8798dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 8802700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR * store = NewLIR3(kX86Mov32MI, r_base, displacement + LOWORD_OFFSET, val_lo); 881d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2, 882d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 8832700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR3(kX86Mov32MI, r_base, displacement + HIWORD_OFFSET, val_hi); 884d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2, 885d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 886d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee return; 887d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee } 888d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 889d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Just use the standard code to do the generation. 890d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee Mir2Lir::GenConstWide(rl_dest, value); 891d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee} 892e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 893e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell// TODO: Merge with existing RegLocation dumper in vreg_analysis.cc 894e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendellvoid X86Mir2Lir::DumpRegLocation(RegLocation loc) { 895e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell LOG(INFO) << "location: " << loc.location << ',' 896e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.wide ? " w" : " ") 897e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.defined ? " D" : " ") 898e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.is_const ? " c" : " ") 899e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.fp ? " F" : " ") 900e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.core ? " C" : " ") 901e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.ref ? " r" : " ") 902e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.high_word ? " h" : " ") 903e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.home ? " H" : " ") 9042700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee << ", low: " << static_cast<int>(loc.reg.GetLowReg()) 90500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee << ", high: " << static_cast<int>(loc.reg.GetHighReg()) 906e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", s_reg: " << loc.s_reg_low 907e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", orig: " << loc.orig_sreg; 908e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell} 909e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 91067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::Materialize() { 91167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // A good place to put the analysis before starting. 91267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeMIR(); 91367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 91467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Now continue with regular code generation. 91567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell Mir2Lir::Materialize(); 91667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 91767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 91849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Haovoid X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type, 91955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell SpecialTargetRegister symbolic_reg) { 92055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 92155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 92255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 92355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 92455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 92549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 92649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 92749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 92849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 92955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 93049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the move instruction with the unique pointer and save index, dex_file, and type. 931ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, 932ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe TargetReg(symbolic_reg, kNotWide).GetReg(), 93349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<int>(target_method_id_ptr), target_method_idx, 93449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 93555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 936e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko method_address_insns_.push_back(move); 93755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 93855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 939e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shihvoid X86Mir2Lir::LoadClassType(const DexFile& dex_file, uint32_t type_idx, 940e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih SpecialTargetRegister symbolic_reg) { 94155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 94255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 94355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 94455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 94555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 946e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih const DexFile::TypeId& id = dex_file.GetTypeId(type_idx); 94755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell uintptr_t ptr = reinterpret_cast<uintptr_t>(&id); 94855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 94955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Generate the move instruction with the unique pointer and save index and type. 950ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, 951ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe TargetReg(symbolic_reg, kNotWide).GetReg(), 952e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih static_cast<int>(ptr), type_idx, 953e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih WrapPointer(const_cast<DexFile*>(&dex_file))); 95455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 955e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko class_type_address_insns_.push_back(move); 95655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 95755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 958f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir MarkoLIR* X86Mir2Lir::CallWithLinkerFixup(const MethodReference& target_method, InvokeType type) { 95955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 96055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit call relative instruction, that will be filled 961f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko * in at 'link time'. 96255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 96349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 96449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 96549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao 96649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the call instruction with the unique pointer and save index, dex_file, and type. 967f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko // NOTE: Method deduplication takes linker patches into account, so we can just pass 0 968f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko // as a placeholder for the offset. 969f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko LIR* call = RawLIR(current_dalvik_offset_, kX86CallI, 0, 97049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 97155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(call); 972e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko call_method_insns_.push_back(call); 97355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell return call; 97455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 97555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 976f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Markostatic LIR* GenInvokeNoInlineCall(Mir2Lir* mir_to_lir, InvokeType type) { 977f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko QuickEntrypointEnum trampoline; 978f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko switch (type) { 979f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kInterface: 980f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeInterfaceTrampolineWithAccessCheck; 981f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 982f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kDirect: 983f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeDirectTrampolineWithAccessCheck; 984f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 985f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kStatic: 986f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeStaticTrampolineWithAccessCheck; 987f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 988f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kSuper: 989f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeSuperTrampolineWithAccessCheck; 990f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 991f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kVirtual: 992f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeVirtualTrampolineWithAccessCheck; 993f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 994f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko default: 995f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko LOG(FATAL) << "Unexpected invoke type"; 996f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeInterfaceTrampolineWithAccessCheck; 997f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 998f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko return mir_to_lir->InvokeTrampoline(kOpBlx, RegStorage::InvalidReg(), trampoline); 999f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko} 1000f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko 1001f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir MarkoLIR* X86Mir2Lir::GenCallInsn(const MirMethodLoweringInfo& method_info) { 1002f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko LIR* call_insn; 1003f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko if (method_info.FastPath()) { 1004f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko if (method_info.DirectCode() == static_cast<uintptr_t>(-1)) { 1005f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko // We can have the linker fixup a call relative. 1006f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko call_insn = CallWithLinkerFixup(method_info.GetTargetMethod(), method_info.GetSharpType()); 1007f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } else { 1008f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko call_insn = OpMem(kOpBlx, TargetReg(kArg0, kRef), 10092d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset( 10102d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier cu_->target64 ? 8 : 4).Int32Value()); 1011f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 1012f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } else { 1013f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko call_insn = GenInvokeNoInlineCall(this, method_info.GetSharpType()); 1014f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 1015f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko return call_insn; 1016f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko} 1017f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko 101855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::InstallLiteralPools() { 101955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // These are handled differently for x86. 102055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(code_literal_list_ == nullptr); 102155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(method_literal_list_ == nullptr); 102255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(class_literal_list_ == nullptr); 102355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 1024d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1025b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (const_vectors_ != nullptr) { 1026b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Vector literals must be 16-byte aligned. The header that is placed 1027b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // in the code section causes misalignment so we take it into account. 1028b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Otherwise, we are sure that for x86 method is aligned to 16. 1029b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A DCHECK_EQ(GetInstructionSetAlignment(cu_->instruction_set), 16u); 1030b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A uint32_t bytes_to_fill = (0x10 - ((code_buffer_.size() + sizeof(OatQuickMethodHeader)) & 0xF)) & 0xF; 1031b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A while (bytes_to_fill > 0) { 1032d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell code_buffer_.push_back(0); 1033b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bytes_to_fill--; 1034d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1035b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1036d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell for (LIR *p = const_vectors_; p != nullptr; p = p->next) { 1037547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[0]); 1038547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[1]); 1039547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[2]); 1040547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[3]); 1041d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1042d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1043d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 104455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for methods. 1045e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (LIR* p : method_address_insns_) { 104655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 104749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[2]; 104849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 104949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3])); 105055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 105155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 105255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 1053f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko patches_.push_back(LinkerPatch::MethodPatch(patch_offset, 1054f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko target_dex_file, target_method_idx)); 105555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 105655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 105755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for class types. 1058e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (LIR* p : class_type_address_insns_) { 105955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 1060e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih 1061e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih const DexFile* class_dex_file = 1062e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3])); 1063f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko uint32_t target_type_idx = p->operands[2]; 106455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 106555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 106655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 1067f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko patches_.push_back(LinkerPatch::TypePatch(patch_offset, 1068f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko class_dex_file, target_type_idx)); 106955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 107055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 107155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And now the PC-relative calls to methods. 1072f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko patches_.reserve(call_method_insns_.size()); 1073e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (LIR* p : call_method_insns_) { 107455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86CallI); 107549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[1]; 107649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 107749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2])); 107855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 107955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 108055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 1081f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko patches_.push_back(LinkerPatch::RelativeCodePatch(patch_offset, 1082f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko target_dex_file, target_method_idx)); 108355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 108455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 108555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And do the normal processing. 108655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell Mir2Lir::InstallLiteralPools(); 108755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 108855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 108970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolovbool X86Mir2Lir::GenInlinedArrayCopyCharArray(CallInfo* info) { 109070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_src = info->args[0]; 109170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_srcPos = info->args[1]; 109270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_dst = info->args[2]; 109370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_dstPos = info->args[3]; 109470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_length = info->args[4]; 109570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (rl_srcPos.is_const && (mir_graph_->ConstantValue(rl_srcPos) < 0)) { 109670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov return false; 109770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 109870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (rl_dstPos.is_const && (mir_graph_->ConstantValue(rl_dstPos) < 0)) { 109970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov return false; 110070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 110170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov ClobberCallerSave(); 11025a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LockCallTemps(); // Using fixed registers. 11035a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov RegStorage tmp_reg = cu_->target64 ? rs_r11 : rs_rBX; 11045a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_src, rs_rAX); 11055a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dst, rs_rCX); 11065a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* src_dst_same = OpCmpBranch(kCondEq, rs_rAX, rs_rCX, nullptr); 11075a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* src_null_branch = OpCmpImmBranch(kCondEq, rs_rAX, 0, nullptr); 11085a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* dst_null_branch = OpCmpImmBranch(kCondEq, rs_rCX, 0, nullptr); 11095a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_length, rs_rDX); 11105a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // If the length of the copy is > 128 characters (256 bytes) or negative then go slow path. 11115a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* len_too_big = OpCmpImmBranch(kCondHi, rs_rDX, 128, nullptr); 11125a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_src, rs_rAX); 11135a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadWordDisp(rs_rAX, mirror::Array::LengthOffset().Int32Value(), rs_rAX); 111470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* src_bad_len = nullptr; 1115f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate LIR* src_bad_off = nullptr; 111670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* srcPos_negative = nullptr; 111770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (!rl_srcPos.is_const) { 11185a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_srcPos, tmp_reg); 11195a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov srcPos_negative = OpCmpImmBranch(kCondLt, tmp_reg, 0, nullptr); 1120f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // src_pos < src_len 1121f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_off = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr); 1122f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // src_len - src_pos < copy_len 1123f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate OpRegRegReg(kOpSub, tmp_reg, rs_rAX, tmp_reg); 1124f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr); 112570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 11265a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov int32_t pos_val = mir_graph_->ConstantValue(rl_srcPos.orig_sreg); 112770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (pos_val == 0) { 11285a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov src_bad_len = OpCmpBranch(kCondLt, rs_rAX, rs_rDX, nullptr); 112970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 1130f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // src_pos < src_len 1131f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_off = OpCmpImmBranch(kCondLt, rs_rAX, pos_val, nullptr); 1132f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // src_len - src_pos < copy_len 1133f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate OpRegRegImm(kOpSub, tmp_reg, rs_rAX, pos_val); 1134f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr); 113570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 113670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 113770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* dstPos_negative = nullptr; 113870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* dst_bad_len = nullptr; 1139f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate LIR* dst_bad_off = nullptr; 114070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadValueDirectFixed(rl_dst, rs_rAX); 114170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadWordDisp(rs_rAX, mirror::Array::LengthOffset().Int32Value(), rs_rAX); 114270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (!rl_dstPos.is_const) { 11435a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dstPos, tmp_reg); 11445a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov dstPos_negative = OpCmpImmBranch(kCondLt, tmp_reg, 0, nullptr); 1145f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // dst_pos < dst_len 1146f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_off = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr); 1147f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // dst_len - dst_pos < copy_len 1148f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate OpRegRegReg(kOpSub, tmp_reg, rs_rAX, tmp_reg); 1149f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr); 115070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 11515a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov int32_t pos_val = mir_graph_->ConstantValue(rl_dstPos.orig_sreg); 115270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (pos_val == 0) { 11535a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov dst_bad_len = OpCmpBranch(kCondLt, rs_rAX, rs_rDX, nullptr); 115470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 1155f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // dst_pos < dst_len 1156f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_off = OpCmpImmBranch(kCondLt, rs_rAX, pos_val, nullptr); 1157f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // dst_len - dst_pos < copy_len 1158f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate OpRegRegImm(kOpSub, tmp_reg, rs_rAX, pos_val); 1159f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr); 116070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 116170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 11625a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // Everything is checked now. 11635a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_src, rs_rAX); 11645a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dst, tmp_reg); 11655a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_srcPos, rs_rCX); 116670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov NewLIR5(kX86Lea32RA, rs_rAX.GetReg(), rs_rAX.GetReg(), 11675a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov rs_rCX.GetReg(), 1, mirror::Array::DataOffset(2).Int32Value()); 11685a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // RAX now holds the address of the first src element to be copied. 116970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 11705a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dstPos, rs_rCX); 11715a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov NewLIR5(kX86Lea32RA, tmp_reg.GetReg(), tmp_reg.GetReg(), 11725a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov rs_rCX.GetReg(), 1, mirror::Array::DataOffset(2).Int32Value() ); 11735a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // RBX now holds the address of the first dst element to be copied. 117470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 11755a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // Check if the number of elements to be copied is odd or even. If odd 117670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov // then copy the first element (so that the remaining number of elements 117770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov // is even). 11785a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_length, rs_rCX); 117970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpRegImm(kOpAnd, rs_rCX, 1); 118070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* jmp_to_begin_loop = OpCmpImmBranch(kCondEq, rs_rCX, 0, nullptr); 118170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpRegImm(kOpSub, rs_rDX, 1); 118270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadBaseIndexedDisp(rs_rAX, rs_rDX, 1, 0, rs_rCX, kSignedHalf); 11835a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov StoreBaseIndexedDisp(tmp_reg, rs_rDX, 1, 0, rs_rCX, kSignedHalf); 118470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 11855a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // Since the remaining number of elements is even, we will copy by 118670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov // two elements at a time. 11875a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* beginLoop = NewLIR0(kPseudoTargetLabel); 11885a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* jmp_to_ret = OpCmpImmBranch(kCondEq, rs_rDX, 0, nullptr); 118970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpRegImm(kOpSub, rs_rDX, 2); 119070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadBaseIndexedDisp(rs_rAX, rs_rDX, 1, 0, rs_rCX, kSingle); 11915a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov StoreBaseIndexedDisp(tmp_reg, rs_rDX, 1, 0, rs_rCX, kSingle); 119270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpUnconditionalBranch(beginLoop); 119370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR *check_failed = NewLIR0(kPseudoTargetLabel); 119470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* launchpad_branch = OpUnconditionalBranch(nullptr); 119570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR *return_point = NewLIR0(kPseudoTargetLabel); 119670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov jmp_to_ret->target = return_point; 119770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov jmp_to_begin_loop->target = beginLoop; 119870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov src_dst_same->target = check_failed; 119970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov len_too_big->target = check_failed; 120070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov src_null_branch->target = check_failed; 120170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (srcPos_negative != nullptr) 120270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov srcPos_negative ->target = check_failed; 1203f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate if (src_bad_off != nullptr) 1204f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_off->target = check_failed; 120570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (src_bad_len != nullptr) 120670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov src_bad_len->target = check_failed; 120770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov dst_null_branch->target = check_failed; 120870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (dstPos_negative != nullptr) 120970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov dstPos_negative->target = check_failed; 1210f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate if (dst_bad_off != nullptr) 1211f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_off->target = check_failed; 121270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (dst_bad_len != nullptr) 121370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov dst_bad_len->target = check_failed; 121470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov AddIntrinsicSlowPath(info, launchpad_branch, return_point); 12159863daf4fdc1a08339edac794452dbc719aef4f1Serguei Katkov ClobberCallerSave(); // We must clobber everything because slow path will return here 121670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov return true; 121770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov} 121870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 121970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 12204028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell/* 12214028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * Fast string.index_of(I) & (II). Inline check for simple case of char <= 0xffff, 12224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * otherwise bails to standard library code. 12234028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell */ 12244028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendellbool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { 12254028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_obj = info->args[0]; 12264028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_char = info->args[1]; 1227a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee RegLocation rl_start; // Note: only present in III flavor or IndexOf. 12288bd698fb785b58302be684efcbb24a0b8c6535d7nikolay serdjuk // RBX is promotable in 64-bit mode. 1229c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk RegStorage rs_tmp = cu_->target64 ? rs_r11 : rs_rBX; 1230c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk int start_value = -1; 12314028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12324028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell uint32_t char_value = 12334028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell rl_char.is_const ? mir_graph_->ConstantValue(rl_char.orig_sreg) : 0; 12344028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12354028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (char_value > 0xFFFF) { 12364028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to punt to the real String.indexOf. 12374028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return false; 12384028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 12394028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12404028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Okay, we are commited to inlining this. 1241c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EAX: 16 bit character being searched. 1242c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // ECX: count: number of words to be searched. 1243c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EDI: String being searched. 1244c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EDX: temporary during execution. 1245c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EBX or R11: temporary during execution (depending on mode). 1246c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // REP SCASW: search instruction. 1247c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 12488bd698fb785b58302be684efcbb24a0b8c6535d7nikolay serdjuk FlushAllRegs(); 1249c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1250a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee RegLocation rl_return = GetReturn(kCoreReg); 12514028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_dest = InlineTarget(info); 12524028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12534028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the string non-NULL? 12542700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_obj, rs_rDX); 12552700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee GenNullCheck(rs_rDX, info->opt_flags); 12563bc8615332b7848dec8c2297a40f7e4d176c0efbVladimir Marko info->opt_flags |= MIR_IGNORE_NULL_CHECK; // Record that we've null checked. 12574028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 1258c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk LIR *slowpath_branch = nullptr, *length_compare = nullptr; 1259c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1260c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We need the value in EAX. 12614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_char.is_const) { 12622700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rs_rAX, char_value); 12634028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1264c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Does the character fit in 16 bits? Compare it at runtime. 12652700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_char, rs_rAX); 12663a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang slowpath_branch = OpCmpImmBranch(kCondGt, rs_rAX, 0xFFFF, nullptr); 12674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 12684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12694028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // From here down, we know that we are looking for a char that fits in 16 bits. 1270e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of reference to data array within the String object. 1271e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int value_offset = mirror::String::ValueOffset().Int32Value(); 1272e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of count within the String object. 1273e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int count_offset = mirror::String::CountOffset().Int32Value(); 1274e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Starting offset within data array. 1275e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int offset_offset = mirror::String::OffsetOffset().Int32Value(); 1276e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Start of char data with array_. 1277e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); 12784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 127969dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // Compute the number of words to search in to rCX. 128069dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison Load32Disp(rs_rDX, count_offset, rs_rCX); 128169dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison 1282dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // Possible signal here due to null pointer dereference. 1283dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // Note that the signal handler will expect the top word of 1284dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // the stack to be the ArtMethod*. If the PUSH edi instruction 1285dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // below is ahead of the load above then this will not be true 1286dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // and the signal handler will not work. 1287dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison MarkPossibleNullPointerException(0); 1288c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1289dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison if (!cu_->target64) { 12908bd698fb785b58302be684efcbb24a0b8c6535d7nikolay serdjuk // EDI is promotable in 32-bit mode. 1291c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk NewLIR1(kX86Push32R, rs_rDI.GetReg()); 1292c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk } 12934028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12944028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (zero_based) { 1295c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Start index is not present. 12964028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to handle an empty string. Use special instruction JECXZ. 12974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare = NewLIR0(kX86Jecxz8); 1298c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1299c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Copy the number of words to search in a temporary register. 1300c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We will use the register at the end to calculate result. 1301c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpMov, rs_tmp, rs_rCX); 13024028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1303c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Start index is present. 1304a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee rl_start = info->args[2]; 1305c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 13064028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to offset by the start index. 13074028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_start.is_const) { 13084028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = mir_graph_->ConstantValue(rl_start.orig_sreg); 13094028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = std::max(start_value, 0); 13104028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the start > count? 13122700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee length_compare = OpCmpImmBranch(kCondLe, rs_rCX, start_value, nullptr); 1313c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegImm(kOpMov, rs_rDI, start_value); 1314c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1315c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Copy the number of words to search in a temporary register. 1316c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We will use the register at the end to calculate result. 1317c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpMov, rs_tmp, rs_rCX); 13184028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13194028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (start_value != 0) { 1320c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Decrease the number of words to search by the start index. 13212700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegImm(kOpSub, rs_rCX, start_value); 13224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13234028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1324c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Handle "start index < 0" case. 1325c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk if (!cu_->target64 && rl_start.location != kLocPhysReg) { 1326a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Load the start index from stack, remembering that we pushed EDI. 1327c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk int displacement = SRegOffset(rl_start.s_reg_low) + sizeof(uint32_t); 132874de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 1329b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers Load32Disp(rs_rX86_SP_32, displacement, rs_rDI); 133074de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko // Dalvik register annotation in LoadBaseIndexedDisp() used wrong offset. Fix it. 133174de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko DCHECK(!DECODE_ALIAS_INFO_WIDE(last_lir_insn_->flags.alias_info)); 133274de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko int reg_id = DECODE_ALIAS_INFO_REG(last_lir_insn_->flags.alias_info) - 1; 133374de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko AnnotateDalvikRegAccess(last_lir_insn_, reg_id, true, false); 1334c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk } else { 1335c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk LoadValueDirectFixed(rl_start, rs_rDI); 13364028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 1337c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpXor, rs_tmp, rs_tmp); 1338c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpCmp, rs_rDI, rs_tmp); 1339c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpCondRegReg(kOpCmov, kCondLt, rs_rDI, rs_tmp); 1340c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1341c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // The length of the string should be greater than the start index. 1342c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk length_compare = OpCmpBranch(kCondLe, rs_rCX, rs_rDI, nullptr); 1343c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1344c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Copy the number of words to search in a temporary register. 1345c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We will use the register at the end to calculate result. 1346c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpMov, rs_tmp, rs_rCX); 1347c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1348c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Decrease the number of words to search by the start index. 1349c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpSub, rs_rCX, rs_rDI); 13504028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13514028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13524028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 1353c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Load the address of the string into EDI. 1354c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // In case of start index we have to add the address to existing value in EDI. 1355e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET. 1356c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk if (zero_based || (!zero_based && rl_start.is_const && start_value == 0)) { 1357c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk Load32Disp(rs_rDX, offset_offset, rs_rDI); 13584028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1359c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegMem(kOpAdd, rs_rDI, rs_rDX, offset_offset); 13604028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 1361c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegImm(kOpLsl, rs_rDI, 1); 1362c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegMem(kOpAdd, rs_rDI, rs_rDX, value_offset); 1363c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegImm(kOpAdd, rs_rDI, data_offset); 13644028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13654028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EDI now contains the start of the string to be searched. 13664028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We are all prepared to do the search for the character. 13674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell NewLIR0(kX86RepneScasw); 13684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13694028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Did we find a match? 13704028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR* failed_branch = OpCondBranch(kCondNe, nullptr); 13714028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13724028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // yes, we matched. Compute the index of the result. 1373c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpSub, rs_tmp, rs_rCX); 1374c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rs_tmp.GetReg(), -1); 1375c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 13764028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *all_done = NewLIR1(kX86Jmp8, 0); 13774028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Failed to match; return -1. 13794028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *not_found = NewLIR0(kPseudoTargetLabel); 13804028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare->target = not_found; 13814028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell failed_branch->target = not_found; 13822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rl_return.reg, -1); 13834028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13844028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // And join up at the end. 13854028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell all_done->target = NewLIR0(kPseudoTargetLabel); 1386c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1387c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk if (!cu_->target64) 1388c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk NewLIR1(kX86Pop32R, rs_rDI.GetReg()); 13894028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Out of line code returns here. 13913a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang if (slowpath_branch != nullptr) { 13924028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *return_point = NewLIR0(kPseudoTargetLabel); 13933a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang AddIntrinsicSlowPath(info, slowpath_branch, return_point); 13949863daf4fdc1a08339edac794452dbc719aef4f1Serguei Katkov ClobberCallerSave(); // We must clobber everything because slow path will return here 13954028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13964028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell StoreValue(rl_dest, rl_return); 13984028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return true; 13994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell} 14004028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 140135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shenstatic bool ARTRegIDToDWARFRegID(bool is_x86_64, int art_reg_id, int* dwarf_reg_id) { 140235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen if (is_x86_64) { 140335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen switch (art_reg_id) { 1404bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 3 : *dwarf_reg_id = 3; return true; // %rbx 140535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // This is the only discrepancy between ART & DWARF register numbering. 1406bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 5 : *dwarf_reg_id = 6; return true; // %rbp 1407bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 12: *dwarf_reg_id = 12; return true; // %r12 1408bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 13: *dwarf_reg_id = 13; return true; // %r13 1409bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 14: *dwarf_reg_id = 14; return true; // %r14 1410bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 15: *dwarf_reg_id = 15; return true; // %r15 1411bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe default: return false; // Should not get here 141235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 141335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } else { 141435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen switch (art_reg_id) { 1415bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 5: *dwarf_reg_id = 5; return true; // %ebp 1416bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 6: *dwarf_reg_id = 6; return true; // %esi 1417bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 7: *dwarf_reg_id = 7; return true; // %edi 1418bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe default: return false; // Should not get here 141935e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 1420ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1421ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1422ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1423547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shenstd::vector<uint8_t>* X86Mir2Lir::ReturnFrameDescriptionEntry() { 1424547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen std::vector<uint8_t>* cfi_info = new std::vector<uint8_t>; 1425ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1426ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Generate the FDE for the method. 1427ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell DCHECK_NE(data_offset_, 0U); 1428ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1429e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban WriteFDEHeader(cfi_info, cu_->target64); 1430e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban WriteFDEAddressRange(cfi_info, data_offset_, cu_->target64); 143135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 1432ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // The instructions in the FDE. 1433ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_decrement_ != nullptr) { 1434ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Advance LOC to just past the stack decrement. 1435ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t pc = NEXT_LIR(stack_decrement_)->offset; 1436547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, pc); 1437ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1438ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Now update the offset to the call frame: DW_CFA_def_cfa_offset frame_size. 1439547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_def_cfa_offset(cfi_info, frame_size_); 1440ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 144135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // Handle register spills 144235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen const uint32_t kSpillInstLen = (cu_->target64) ? 5 : 4; 144335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen const int kDataAlignmentFactor = (cu_->target64) ? -8 : -4; 144435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 144535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen int offset = -(GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 144635e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen for (int reg = 0; mask; mask >>= 1, reg++) { 144735e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen if (mask & 0x1) { 144835e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen pc += kSpillInstLen; 144935e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 145035e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // Advance LOC to pass this instruction 1451547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, kSpillInstLen); 145235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 145335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen int dwarf_reg_id; 145435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen if (ARTRegIDToDWARFRegID(cu_->target64, reg, &dwarf_reg_id)) { 1455547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen // DW_CFA_offset_extended_sf reg offset 1456547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_offset_extended_sf(cfi_info, dwarf_reg_id, offset / kDataAlignmentFactor); 145735e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 145835e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 145935e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen offset += GetInstructionSetPointerSize(cu_->instruction_set); 146035e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 146135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 146235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 1463ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We continue with that stack until the epilogue. 1464ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_increment_ != nullptr) { 1465ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t new_pc = NEXT_LIR(stack_increment_)->offset; 1466547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, new_pc - pc); 1467ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1468ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We probably have code snippets after the epilogue, so save the 1469ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // current state: DW_CFA_remember_state. 1470547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_remember_state(cfi_info); 1471ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 147235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // We have now popped the stack: DW_CFA_def_cfa_offset 4/8. 147335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // There is only the return PC on the stack now. 1474547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_def_cfa_offset(cfi_info, GetInstructionSetPointerSize(cu_->instruction_set)); 1475ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1476ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Everything after that is the same as before the epilogue. 1477ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Stack bump was followed by RET instruction. 1478ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell LIR *post_ret_insn = NEXT_LIR(NEXT_LIR(stack_increment_)); 1479ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (post_ret_insn != nullptr) { 1480ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell pc = new_pc; 1481ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell new_pc = post_ret_insn->offset; 1482547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, new_pc - pc); 1483ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Restore the state: DW_CFA_restore_state. 1484547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_restore_state(cfi_info); 1485ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1486ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1487ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1488ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1489547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PadCFI(cfi_info); 1490e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban WriteCFILength(cfi_info, cu_->target64); 1491ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1492ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell return cfi_info; 1493ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1494ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1495d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) { 1496d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 149760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpReserveVectorRegisters: 149860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji ReserveVectorRegisters(mir); 149960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 150060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpReturnVectorRegisters: 1501b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A ReturnVectorRegisters(mir); 150260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 1503d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell case kMirOpConstVector: 15046a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenConst128(mir); 1505d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell break; 1506fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpMoveVector: 15076a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenMoveVector(mir); 1508fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1509fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedMultiply: 15106a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenMultiplyVector(mir); 1511fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1512fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedAddition: 15136a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenAddVector(mir); 1514fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1515fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedSubtract: 15166a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenSubtractVector(mir); 1517fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1518fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedShiftLeft: 15196a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenShiftLeftVector(mir); 1520fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1521fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedSignedShiftRight: 15226a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenSignedShiftRightVector(mir); 1523fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1524fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedUnsignedShiftRight: 15256a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenUnsignedShiftRightVector(mir); 1526fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1527fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedAnd: 15286a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenAndVector(mir); 1529fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1530fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedOr: 15316a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenOrVector(mir); 1532fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1533fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedXor: 15346a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenXorVector(mir); 1535fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1536fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedAddReduce: 15376a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenAddReduceVector(mir); 1538fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1539fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedReduce: 15406a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenReduceVector(mir); 1541fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1542fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedSet: 15436a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenSetVector(mir); 1544fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1545b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler case kMirOpMemBarrier: 1546b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler GenMemBarrier(static_cast<MemBarrierKind>(mir->dalvikInsn.vA)); 1547b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler break; 1548b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kMirOpPackedArrayGet: 1549b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenPackedArrayGet(bb, mir); 1550b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1551b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kMirOpPackedArrayPut: 1552b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenPackedArrayPut(bb, mir); 1553b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1554d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell default: 1555d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell break; 1556d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1557d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1558d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 155960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::ReserveVectorRegisters(MIR* mir) { 1560b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (uint32_t i = mir->dalvikInsn.vA; i <= mir->dalvikInsn.vB; i++) { 156160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage xp_reg = RegStorage::Solo128(i); 156260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegisterInfo *xp_reg_info = GetRegInfo(xp_reg); 156360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji Clobber(xp_reg); 156460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 156560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji for (RegisterInfo *info = xp_reg_info->GetAliasChain(); 156660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info != nullptr; 156760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info = info->GetAliasChain()) { 1568e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko ArenaVector<RegisterInfo*>* regs = 1569e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko info->GetReg().IsSingle() ? ®_pool_->sp_regs_ : ®_pool_->dp_regs_; 1570e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko auto it = std::find(regs->begin(), regs->end(), info); 1571e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko DCHECK(it != regs->end()); 1572e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko regs->erase(it); 157360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 157460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 157560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 157660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1577b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::ReturnVectorRegisters(MIR* mir) { 1578b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (uint32_t i = mir->dalvikInsn.vA; i <= mir->dalvikInsn.vB; i++) { 157960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage xp_reg = RegStorage::Solo128(i); 158060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegisterInfo *xp_reg_info = GetRegInfo(xp_reg); 158160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 158260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji for (RegisterInfo *info = xp_reg_info->GetAliasChain(); 158360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info != nullptr; 158460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info = info->GetAliasChain()) { 158560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji if (info->GetReg().IsSingle()) { 1586e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reg_pool_->sp_regs_.push_back(info); 158760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 1588e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reg_pool_->dp_regs_.push_back(info); 158960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 159060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 159160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 159260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 159360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 15946a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenConst128(MIR* mir) { 159560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA); 1596b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest); 1597b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1598d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell uint32_t *args = mir->dalvikInsn.arg; 1599fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int reg = rs_dest.GetReg(); 1600d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Check for all 0 case. 1601d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (args[0] == 0 && args[1] == 0 && args[2] == 0 && args[3] == 0) { 1602d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell NewLIR2(kX86XorpsRR, reg, reg); 1603d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return; 1604d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 160560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 160660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Append the mov const vector to reg opcode. 1607b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AppendOpcodeWithConst(kX86MovdqaRM, reg, mir); 160860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 160960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 161060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::AppendOpcodeWithConst(X86OpCode opcode, int reg, MIR* mir) { 1611b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // The literal pool needs position independent logic. 1612b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A store_method_addr_used_ = true; 1613b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1614b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // To deal with correct memory ordering, reverse order of constants. 1615b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int32_t constants[4]; 1616b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[3] = mir->dalvikInsn.arg[0]; 1617b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[2] = mir->dalvikInsn.arg[1]; 1618b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[1] = mir->dalvikInsn.arg[2]; 1619b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[0] = mir->dalvikInsn.arg[3]; 1620b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1621b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Search if there is already a constant in pool with this value. 1622b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LIR *data_target = ScanVectorLiteral(constants); 1623d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (data_target == nullptr) { 1624b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A data_target = AddVectorLiteral(constants); 1625d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1626d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1627d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Address the start of the method. 1628d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low); 1629e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu if (rl_method.wide) { 1630e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu rl_method = LoadValueWide(rl_method, kCoreReg); 1631e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } else { 1632e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu rl_method = LoadValue(rl_method, kCoreReg); 1633e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } 1634d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1635d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Load the proper value from the literal area. 1636d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // We don't know the proper offset for the value, so pick one that will force 1637d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // 4 byte offset. We will fix this up in the assembler later to have the right 1638d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // value. 16398dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral); 1640b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LIR *load = NewLIR3(opcode, reg, rl_method.reg.GetReg(), 256 /* bogus */); 1641d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell load->flags.fixup = kFixupLoad; 1642d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell load->target = data_target; 1643d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1644d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 16456a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenMoveVector(MIR* mir) { 1646fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 164760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 164860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA); 1649b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest); 165060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src = RegStorage::Solo128(mir->dalvikInsn.vB); 1651b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_dest.GetReg(), rs_src.GetReg()); 1652fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1653fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1654b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::GenMultiplyVectorSignedByte(RegStorage rs_dest_src1, RegStorage rs_src2) { 165560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji /* 165660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * Emulate the behavior of a kSignedByte by separating out the 16 values in the two XMM 165760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * and multiplying 8 at a time before recombining back into one XMM register. 165860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * 165960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * let xmm1, xmm2 be real srcs (keep low bits of 16bit lanes) 166060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm3 is tmp (operate on high bits of 16bit lanes) 166160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * 166260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm3 = xmm1 166360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm1 = xmm1 .* xmm2 166460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm1 = xmm1 & 0x00ff00ff00ff00ff00ff00ff00ff00ff // xmm1 now has low bits 166560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm3 = xmm3 .>> 8 166660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm2 = xmm2 & 0xff00ff00ff00ff00ff00ff00ff00ff00 166760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm2 = xmm2 .* xmm3 // xmm2 now has high bits 166860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm1 = xmm1 | xmm2 // combine results 166960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji */ 167060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 167160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Copy xmm1. 1672b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_src1_high_tmp = Get128BitRegister(AllocTempDouble()); 1673b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_dest_high_tmp = Get128BitRegister(AllocTempDouble()); 1674b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_src1_high_tmp.GetReg(), rs_src2.GetReg()); 1675b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_dest_high_tmp.GetReg(), rs_dest_src1.GetReg()); 167660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 167760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Multiply low bits. 1678b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // x7 *= x3 167960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji NewLIR2(kX86PmullwRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 168060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 168160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // xmm1 now has low bits. 168260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji AndMaskVectorRegister(rs_dest_src1, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF); 168360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 168460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Prepare high bits for multiplication. 1685b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlwRI, rs_src1_high_tmp.GetReg(), 0x8); 1686b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AndMaskVectorRegister(rs_dest_high_tmp, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00); 168760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 168860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Multiply high bits and xmm2 now has high bits. 1689b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmullwRR, rs_src1_high_tmp.GetReg(), rs_dest_high_tmp.GetReg()); 169060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 169160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Combine back into dest XMM register. 1692b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_src1_high_tmp.GetReg()); 1693b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A} 1694b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1695b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::GenMultiplyVectorLong(RegStorage rs_dest_src1, RegStorage rs_src2) { 1696b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 1697b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * We need to emulate the packed long multiply. 1698b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * For kMirOpPackedMultiply xmm1, xmm0: 1699b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - xmm1 is src/dest 1700b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - xmm0 is src 1701b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Get xmm2 and xmm3 as temp 1702b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Idea is to multiply the lower 32 of each operand with the higher 32 of the other. 1703b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Then add the two results. 1704b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Move it to the upper 32 of the destination 1705b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Then multiply the lower 32-bits of the operands and add the result to the destination. 1706b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1707b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * (op dest src ) 1708b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * movdqa %xmm2, %xmm1 1709b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * movdqa %xmm3, %xmm0 1710b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psrlq %xmm3, $0x20 1711b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm3, %xmm2 1712b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psrlq %xmm1, $0x20 1713b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm1, %xmm0 1714b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm3 1715b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psllq %xmm1, $0x20 1716b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm2, %xmm0 1717b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm2 1718b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1719b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * When both the operands are the same, then we need to calculate the lower-32 * higher-32 1720b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * calculation only once. Thus we don't need the xmm3 temp above. That sequence becomes: 1721b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1722b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * (op dest src ) 1723b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * movdqa %xmm2, %xmm1 1724b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psrlq %xmm1, $0x20 1725b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm1, %xmm0 1726b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm1 1727b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psllq %xmm1, $0x20 1728b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm2, %xmm0 1729b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm2 1730b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1731b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 1732b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1733b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bool both_operands_same = (rs_dest_src1.GetReg() == rs_src2.GetReg()); 1734b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1735b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector_1; 1736b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector_2; 1737b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rs_tmp_vector_1 = Get128BitRegister(AllocTempDouble()); 1738b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector_1.GetReg(), rs_dest_src1.GetReg()); 1739b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1740b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (both_operands_same == false) { 1741b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rs_tmp_vector_2 = Get128BitRegister(AllocTempDouble()); 1742b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector_2.GetReg(), rs_src2.GetReg()); 1743b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, rs_tmp_vector_2.GetReg(), 0x20); 1744b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmuludqRR, rs_tmp_vector_2.GetReg(), rs_tmp_vector_1.GetReg()); 1745b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 1746b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1747b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, rs_dest_src1.GetReg(), 0x20); 1748b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmuludqRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1749b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1750b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (both_operands_same == false) { 1751b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, rs_dest_src1.GetReg(), rs_tmp_vector_2.GetReg()); 1752b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 1753b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, rs_dest_src1.GetReg(), rs_dest_src1.GetReg()); 1754b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 1755b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1756b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsllqRI, rs_dest_src1.GetReg(), 0x20); 1757b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmuludqRR, rs_tmp_vector_1.GetReg(), rs_src2.GetReg()); 1758b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, rs_dest_src1.GetReg(), rs_tmp_vector_1.GetReg()); 175960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 176060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 17616a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenMultiplyVector(MIR* mir) { 176260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 176360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 176460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1765b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 176660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1767fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1768fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1769fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1770fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PmulldRR; 1771fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1772fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1773fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PmullwRR; 1774fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1775fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSingle: 1776fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86MulpsRR; 1777fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1778fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kDouble: 1779fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86MulpdRR; 1780fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 178160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 178260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // HW doesn't support 16x16 byte multiplication so emulate it. 1783b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenMultiplyVectorSignedByte(rs_dest_src1, rs_src2); 1784b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 1785b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1786b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenMultiplyVectorLong(rs_dest_src1, rs_src2); 178760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1788fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1789fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector multiply " << opsize; 1790fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1791fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1792fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1793fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1794fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 17956a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenAddVector(MIR* mir) { 179660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 179760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 179860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1799b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 180060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1801fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1802fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1803fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1804fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PadddRR; 1805fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1806b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1807b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A opcode = kX86PaddqRR; 1808b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1809fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1810fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1811fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PaddwRR; 1812fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1813fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedByte: 1814fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedByte: 1815fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PaddbRR; 1816fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1817fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSingle: 1818fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86AddpsRR; 1819fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1820fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kDouble: 1821fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86AddpdRR; 1822fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1823fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1824fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector addition " << opsize; 1825fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1826fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1827fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1828fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1829fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 18306a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenSubtractVector(MIR* mir) { 183160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 183260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 183360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1834b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 183560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1836fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1837fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1838fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1839fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsubdRR; 1840fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1841b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1842b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A opcode = kX86PsubqRR; 1843b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1844fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1845fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1846fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsubwRR; 1847fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1848fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedByte: 1849fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedByte: 1850fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsubbRR; 1851fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1852fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSingle: 1853fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86SubpsRR; 1854fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1855fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kDouble: 1856fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86SubpdRR; 1857fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1858fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1859fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector subtraction " << opsize; 1860fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1861fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1862fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1863fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1864fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 18656a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenShiftByteVector(MIR* mir) { 1866b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Destination does not need clobbered because it has already been as part 1867b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // of the general packed shift handler (caller of this method). 186860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 186960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 187060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int opcode = 0; 187160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 187260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpPackedShiftLeft: 187360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji opcode = kX86PsllwRI; 187460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 187560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpPackedSignedShiftRight: 187660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpPackedUnsignedShiftRight: 1877b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Add support for emulated byte shifts. 187860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji default: 187960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji LOG(FATAL) << "Unsupported shift operation on byte vector " << opcode; 188060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 188160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 188260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1883b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Clear xmm register and return if shift more than byte length. 1884b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int imm = mir->dalvikInsn.vB; 1885b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (imm >= 8) { 1886b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PxorRR, rs_dest_src1.GetReg(), rs_dest_src1.GetReg()); 1887b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 1888b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 188960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 189060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Shift lower values. 189160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 189260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1893b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 1894b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * The above shift will shift the whole word, but that means 1895b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * both the bytes will shift as well. To emulate a byte level 1896b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * shift, we can just throw away the lower (8 - N) bits of the 1897b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * upper byte, and we are done. 1898b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 1899b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A uint8_t byte_mask = 0xFF << imm; 1900b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A uint32_t int_mask = byte_mask; 1901b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int_mask = int_mask << 8 | byte_mask; 1902b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int_mask = int_mask << 8 | byte_mask; 1903b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int_mask = int_mask << 8 | byte_mask; 190460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1905b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // And the destination with the mask 1906b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AndMaskVectorRegister(rs_dest_src1, int_mask, int_mask, int_mask, int_mask); 190760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 190860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 19096a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenShiftLeftVector(MIR* mir) { 191060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 191160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 191260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1913b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 191460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int imm = mir->dalvikInsn.vB; 1915fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1916fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1917fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1918fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PslldRI; 1919fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1920fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k64: 1921fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsllqRI; 1922fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1923fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1924fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1925fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsllwRI; 1926fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 192760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 192860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 19296a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenShiftByteVector(mir); 193060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1931fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1932fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector shift left " << opsize; 1933fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1934fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1935fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1936fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1937fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 19386a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenSignedShiftRightVector(MIR* mir) { 193960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 194060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 194160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1942b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 194360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int imm = mir->dalvikInsn.vB; 1944fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1945fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1946fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1947fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsradRI; 1948fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1949fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1950fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1951fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrawRI; 1952fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 195360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 195460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 19556a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenShiftByteVector(mir); 195660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1957b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1958b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Implement emulated shift algorithm. 1959fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1960fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector signed shift right " << opsize; 19616a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 1962fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1963fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1964fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1965fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 19666a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenUnsignedShiftRightVector(MIR* mir) { 196760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 196860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 196960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1970b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 197160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int imm = mir->dalvikInsn.vB; 1972fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1973fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1974fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1975fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrldRI; 1976fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1977fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k64: 1978fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrlqRI; 1979fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1980fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1981fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1982fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrlwRI; 1983fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 198460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 198560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 19866a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenShiftByteVector(mir); 198760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1988fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1989fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector unsigned shift right " << opsize; 1990fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1991fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1992fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1993fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1994fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 19956a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenAndVector(MIR* mir) { 1996fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 199760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 199860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1999b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 200060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 2001fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(kX86PandRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 2002fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2003fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 20046a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenOrVector(MIR* mir) { 2005fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 200660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 200760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 2008b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 200960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 2010fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 2011fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2012fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 20136a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenXorVector(MIR* mir) { 2014fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 201560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 201660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 2017b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 201860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 2019fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(kX86PxorRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 2020fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2021fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 202260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::AndMaskVectorRegister(RegStorage rs_src1, uint32_t m1, uint32_t m2, uint32_t m3, uint32_t m4) { 202360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji MaskVectorRegister(kX86PandRM, rs_src1, m1, m2, m3, m4); 202460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 202560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 202660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::MaskVectorRegister(X86OpCode opcode, RegStorage rs_src1, uint32_t m0, uint32_t m1, uint32_t m2, uint32_t m3) { 202760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Create temporary MIR as container for 128-bit binary mask. 202860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji MIR const_mir; 202960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji MIR* const_mirp = &const_mir; 203060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpConstVector); 203160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[0] = m0; 203260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[1] = m1; 203360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[2] = m2; 203460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[3] = m3; 203560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 203660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Mask vector with const from literal pool. 203760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji AppendOpcodeWithConst(opcode, rs_src1.GetReg(), const_mirp); 203860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 203960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 20406a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenAddReduceVector(MIR* mir) { 204160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 2042b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage vector_src = RegStorage::Solo128(mir->dalvikInsn.vB); 2043b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bool is_wide = opsize == k64 || opsize == kDouble; 2044b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2045b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Get the location of the virtual register. Since this bytecode is overloaded 2046b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // for different types (and sizes), we need different logic for each path. 2047b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // The design of bytecode uses same VR for source and destination. 2048b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegLocation rl_src, rl_dest, rl_result; 2049b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (is_wide) { 2050b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrcWide(mir, 0); 2051b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_dest = mir_graph_->GetDestWide(mir); 2052b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2053b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrc(mir, 0); 2054b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_dest = mir_graph_->GetDest(mir); 2055b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 205660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2057b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // We need a temp for byte and short values 2058b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage temp; 205960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2060b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // There is a different path depending on type and size. 2061b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSingle) { 2062b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle float case. 2063b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Add support for fast math (not value safe) and do horizontal add in that case. 206460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2065b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = LoadValue(rl_src, kFPReg); 2066b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLoc(rl_dest, kFPReg, true); 206760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2068b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Since we are doing an add-reduce, we move the reg holding the VR 2069b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // into the result so we include it in result. 2070b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A OpRegCopy(rl_result.reg, rl_src.reg); 2071b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 207260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2073b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Since FP must keep order of operation for value safety, we shift to low 2074b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // 32-bits and add to result. 2075b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (int i = 0; i < 3; i++) { 2076b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(kX86ShufpsRRI, vector_src.GetReg(), vector_src.GetReg(), 0x39); 2077b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 2078b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 207960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2080b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreValue(rl_dest, rl_result); 2081b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == kDouble) { 2082b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle double case. 2083b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = LoadValueWide(rl_src, kFPReg); 2084b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLocWide(rl_dest, kFPReg, true); 2085b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported vector add reduce for double."; 2086b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == k64) { 2087b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 2088b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * Handle long case: 2089b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1) Reduce the vector register to lower half (with addition). 2090b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-1) Get an xmm temp and fill it with vector register. 2091b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-2) Shift the xmm temp by 8-bytes. 2092b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-3) Add the xmm temp to vector register that is being reduced. 2093b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2) Allocate temp GP / GP pair. 2094b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-1) In 64-bit case, use movq to move result to a 64-bit GP. 2095b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-2) In 32-bit case, use movd twice to move to 32-bit GP pair. 2096b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 3) Finish the add reduction by doing what add-long/2addr does, 2097b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * but instead of having a VR as one of the sources, we have our temp GP. 2098b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 2099b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector = Get128BitRegister(AllocTempDouble()); 2100b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector.GetReg(), vector_src.GetReg()); 2101b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrldqRI, rs_tmp_vector.GetReg(), 8); 2102b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, vector_src.GetReg(), rs_tmp_vector.GetReg()); 2103b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A FreeTemp(rs_tmp_vector); 2104b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2105b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // We would like to be able to reuse the add-long implementation, so set up a fake 2106b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // register location to pass it. 2107b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegLocation temp_loc = mir_graph_->GetBadLoc(); 2108b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.core = 1; 2109b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.wide = 1; 2110b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.location = kLocPhysReg; 2111b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.reg = AllocTempWide(); 2112b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2113b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (cu_->target64) { 2114b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A DCHECK(!temp_loc.reg.IsPair()); 2115b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovqrxRR, temp_loc.reg.GetReg(), vector_src.GetReg()); 2116b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2117b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, temp_loc.reg.GetLowReg(), vector_src.GetReg()); 2118b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, vector_src.GetReg(), 0x20); 2119b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, temp_loc.reg.GetHighReg(), vector_src.GetReg()); 2120b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 212160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 21225c5676b26a08454b3f0133783778991bbe5dd681Razvan A Lupusoru GenArithOpLong(Instruction::ADD_LONG_2ADDR, rl_dest, temp_loc, temp_loc, mir->optimization_flags); 2123b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == kSignedByte || opsize == kUnsignedByte) { 2124b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp = Get128BitRegister(AllocTempDouble()); 2125b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PxorRR, rs_tmp.GetReg(), rs_tmp.GetReg()); 2126b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsadbwRR, vector_src.GetReg(), rs_tmp.GetReg()); 2127b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(kX86PshufdRRI, rs_tmp.GetReg(), vector_src.GetReg(), 0x4e); 2128b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddbRR, vector_src.GetReg(), rs_tmp.GetReg()); 2129b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Move to a GPR 2130b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp = AllocTemp(); 2131b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, temp.GetReg(), vector_src.GetReg()); 2132b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2133b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle and the int and short cases together 2134b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2135b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Initialize as if we were handling int case. Below we update 2136b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // the opcode if handling byte or short. 2137b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int vec_bytes = (mir->dalvikInsn.vC & 0xFFFF) / 8; 2138b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int vec_unit_size; 2139b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int horizontal_add_opcode; 2140b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int extract_opcode; 2141b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2142b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSignedHalf || opsize == kUnsignedHalf) { 2143b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A extract_opcode = kX86PextrwRRI; 2144b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A horizontal_add_opcode = kX86PhaddwRR; 2145b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A vec_unit_size = 2; 2146b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == k32) { 2147b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A vec_unit_size = 4; 2148b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A horizontal_add_opcode = kX86PhadddRR; 2149b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A extract_opcode = kX86PextrdRRI; 2150b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2151b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported vector add reduce " << opsize; 2152b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 215360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 215460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2155b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int elems = vec_bytes / vec_unit_size; 215660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2157b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A while (elems > 1) { 2158b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(horizontal_add_opcode, vector_src.GetReg(), vector_src.GetReg()); 2159b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A elems >>= 1; 2160b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 216160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2162b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle this as arithmetic unary case. 2163b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 216460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2165b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Extract to a GP register because this is integral typed. 2166b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp = AllocTemp(); 2167b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(extract_opcode, temp.GetReg(), vector_src.GetReg(), 0); 2168b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2169b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2170b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize != k64 && opsize != kSingle && opsize != kDouble) { 2171b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // The logic below looks very similar to the handling of ADD_INT_2ADDR 2172b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // except the rhs is not a VR but a physical register allocated above. 2173b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // No load of source VR is done because it assumes that rl_result will 2174b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // share physical register / memory location. 21756a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers rl_result = UpdateLocTyped(rl_dest); 2176b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (rl_result.location == kLocPhysReg) { 2177b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Ensure res is in a core reg. 2178b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLoc(rl_dest, kCoreReg, true); 2179b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A OpRegReg(kOpAdd, rl_result.reg, temp); 2180b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreFinalValue(rl_dest, rl_result); 2181b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2182b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Do the addition directly to memory. 2183b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A OpMemReg(kOpAdd, rl_result, temp.GetReg()); 2184b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2185b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2186fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2187fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 21886a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenReduceVector(MIR* mir) { 218960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 219060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegLocation rl_dest = mir_graph_->GetDest(mir); 2191b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage vector_src = RegStorage::Solo128(mir->dalvikInsn.vB); 219260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegLocation rl_result; 219360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji bool is_wide = false; 219460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2195b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // There is a different path depending on type and size. 2196b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSingle) { 2197b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle float case. 2198b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Add support for fast math (not value safe) and do horizontal add in that case. 2199fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2200b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLoc(rl_dest, kFPReg, true); 2201b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PxorRR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 2202b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 2203b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2204b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Since FP must keep order of operation for value safety, we shift to low 2205b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // 32-bits and add to result. 2206b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (int i = 0; i < 3; i++) { 2207b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(kX86ShufpsRRI, vector_src.GetReg(), vector_src.GetReg(), 0x39); 2208b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 2209b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2210b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2211b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreValue(rl_dest, rl_result); 2212b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == kDouble) { 2213b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Handle double case. 2214b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported add reduce for double."; 2215b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == k64) { 2216b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 2217b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * Handle long case: 2218b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1) Reduce the vector register to lower half (with addition). 2219b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-1) Get an xmm temp and fill it with vector register. 2220b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-2) Shift the xmm temp by 8-bytes. 2221b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-3) Add the xmm temp to vector register that is being reduced. 2222b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2) Evaluate destination to a GP / GP pair. 2223b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-1) In 64-bit case, use movq to move result to a 64-bit GP. 2224b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-2) In 32-bit case, use movd twice to move to 32-bit GP pair. 2225b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 3) Store the result to the final destination. 2226b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 222753cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji NewLIR2(kX86PsrldqRI, vector_src.GetReg(), 8); 2228b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLocWide(rl_dest, kCoreReg, true); 2229b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (cu_->target64) { 2230b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A DCHECK(!rl_result.reg.IsPair()); 2231b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovqrxRR, rl_result.reg.GetReg(), vector_src.GetReg()); 223260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 2233b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, rl_result.reg.GetLowReg(), vector_src.GetReg()); 2234b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, vector_src.GetReg(), 0x20); 2235b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, rl_result.reg.GetHighReg(), vector_src.GetReg()); 223660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 2237b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2238b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreValueWide(rl_dest, rl_result); 223960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 224053cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji int extract_index = mir->dalvikInsn.arg[0]; 224153cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji int extr_opcode = 0; 22426a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers rl_result = UpdateLocTyped(rl_dest); 224353cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji 2244b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle the rest of integral types now. 2245b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A switch (opsize) { 2246b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k32: 224753cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrdRRI : kX86PextrdMRI; 2248b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 2249b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kSignedHalf: 2250b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kUnsignedHalf: 225153cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrwRRI : kX86PextrwMRI; 225253cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji break; 225353cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji case kSignedByte: 225453cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrbRRI : kX86PextrbMRI; 2255b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 2256b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A default: 2257b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported vector reduce " << opsize; 22586a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 2259b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2260b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2261b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (rl_result.location == kLocPhysReg) { 2262b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(extr_opcode, rl_result.reg.GetReg(), vector_src.GetReg(), extract_index); 226353cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji StoreFinalValue(rl_dest, rl_result); 2264b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2265b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int displacement = SRegOffset(rl_result.s_reg_low); 2266b72c723bfb21e05cb9b0a7999db805df93fcaee8Razvan A Lupusoru LIR *l = NewLIR4(extr_opcode, rs_rX86_SP_32.GetReg(), displacement, vector_src.GetReg(), 2267b72c723bfb21e05cb9b0a7999db805df93fcaee8Razvan A Lupusoru extract_index); 2268b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, is_wide /* is_64bit */); 2269b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AnnotateDalvikRegAccess(l, displacement >> 2, false /* is_load */, is_wide /* is_64bit */); 2270b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 227160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 2272fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2273fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 22740a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendellvoid X86Mir2Lir::LoadVectorRegister(RegStorage rs_dest, RegStorage rs_src, 22750a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell OpSize opsize, int op_mov) { 22760a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell if (!cu_->target64 && opsize == k64) { 22770a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell // Logic assumes that longs are loaded in GP register pairs. 22780a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell NewLIR2(kX86MovdxrRR, rs_dest.GetReg(), rs_src.GetLowReg()); 22790a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell RegStorage r_tmp = AllocTempDouble(); 22800a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell NewLIR2(kX86MovdxrRR, r_tmp.GetReg(), rs_src.GetHighReg()); 22810a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell NewLIR2(kX86PunpckldqRR, rs_dest.GetReg(), r_tmp.GetReg()); 22820a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell FreeTemp(r_tmp); 22830a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell } else { 22840a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell NewLIR2(op_mov, rs_dest.GetReg(), rs_src.GetReg()); 22850a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell } 22860a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell} 22870a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell 22886a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenSetVector(MIR* mir) { 228960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 229060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 229160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA); 2292b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest); 2293b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int op_shuffle = 0, op_shuffle_high = 0, op_mov = kX86MovdxrRR; 229460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegisterClass reg_type = kCoreReg; 2295b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bool is_wide = false; 229660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2297fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 2298fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 2299b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PshufdRRI; 2300fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 230160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSingle: 2302b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PshufdRRI; 2303b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_mov = kX86MovdqaRR; 230460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji reg_type = kFPReg; 230560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 230660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case k64: 2307b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PunpcklqdqRR; 230853cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji op_mov = kX86MovqxrRR; 2309b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A is_wide = true; 231060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 231160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 231260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 2313b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // We will have the source loaded up in a 2314b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // double-word before we use this shuffle 2315b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PshufdRRI; 2316b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 2317fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 2318fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 2319fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Handles low quadword. 2320b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PshuflwRRI; 2321fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Handles upper quadword. 2322b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle_high = kX86PshufdRRI; 2323fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 2324fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 2325fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector set " << opsize; 2326fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 2327fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 2328fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2329b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Load the value from the VR into a physical register. 2330b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegLocation rl_src; 2331b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (!is_wide) { 2332b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrc(mir, 0); 233360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji rl_src = LoadValue(rl_src, reg_type); 233460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 2335b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrcWide(mir, 0); 233660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji rl_src = LoadValueWide(rl_src, reg_type); 233760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 2338b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage reg_to_shuffle = rl_src.reg; 233960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2340b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Load the value into the XMM register. 23410a1174efd81fc25110ad106a84063c62af9ce7e5Mark Mendell LoadVectorRegister(rs_dest, reg_to_shuffle, opsize, op_mov); 2342fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2343b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSignedByte || opsize == kUnsignedByte) { 2344b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // In the byte case, first duplicate it to be a word 2345b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Then duplicate it to be a double-word 2346b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PunpcklbwRR, rs_dest.GetReg(), rs_dest.GetReg()); 2347b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PunpcklwdRR, rs_dest.GetReg(), rs_dest.GetReg()); 2348b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2349fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2350fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Now shuffle the value across the destination. 2351b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (op_shuffle == kX86PunpcklqdqRR) { 2352b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(op_shuffle, rs_dest.GetReg(), rs_dest.GetReg()); 2353b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2354b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(op_shuffle, rs_dest.GetReg(), rs_dest.GetReg(), 0); 2355b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2356fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2357fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // And then repeat as needed. 2358b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (op_shuffle_high != 0) { 2359b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(op_shuffle_high, rs_dest.GetReg(), rs_dest.GetReg(), 0); 2360fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 2361fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2362fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 23636a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenPackedArrayGet(BasicBlock* bb, MIR* mir) { 23646a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(bb, mir); 2365b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A UNIMPLEMENTED(FATAL) << "Extended opcode kMirOpPackedArrayGet not supported."; 2366b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A} 2367b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 23686a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenPackedArrayPut(BasicBlock* bb, MIR* mir) { 23696a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(bb, mir); 2370b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A UNIMPLEMENTED(FATAL) << "Extended opcode kMirOpPackedArrayPut not supported."; 2371b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A} 2372b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2373b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan ALIR* X86Mir2Lir::ScanVectorLiteral(int32_t* constants) { 2374d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell for (LIR *p = const_vectors_; p != nullptr; p = p->next) { 2375b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (constants[0] == p->operands[0] && constants[1] == p->operands[1] && 2376b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[2] == p->operands[2] && constants[3] == p->operands[3]) { 2377d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return p; 2378d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 2379d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 2380d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return nullptr; 2381d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 2382d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 2383b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan ALIR* X86Mir2Lir::AddVectorLiteral(int32_t* constants) { 2384d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell LIR* new_value = static_cast<LIR*>(arena_->Alloc(sizeof(LIR), kArenaAllocData)); 2385b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A new_value->operands[0] = constants[0]; 2386b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A new_value->operands[1] = constants[1]; 2387b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A new_value->operands[2] = constants[2]; 2388b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A new_value->operands[3] = constants[3]; 2389d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell new_value->next = const_vectors_; 2390d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (const_vectors_ == nullptr) { 2391b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A estimated_native_code_size_ += 12; // Maximum needed to align to 16 byte boundary. 2392d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 2393d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell estimated_native_code_size_ += 16; // Space for one vector. 2394d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell const_vectors_ = new_value; 2395d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return new_value; 2396d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 2397d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 239858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// ------------ ABI support: mapping of args to physical registers ------------- 2399ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas GampeRegStorage X86Mir2Lir::InToRegStorageX86_64Mapper::GetNextReg(bool is_double_or_float, bool is_wide, 2400ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe bool is_ref) { 2401a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu const SpecialTargetRegister coreArgMappingToPhysicalReg[] = {kArg1, kArg2, kArg3, kArg4, kArg5}; 2402ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe const int coreArgMappingToPhysicalRegSize = sizeof(coreArgMappingToPhysicalReg) / 2403ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe sizeof(SpecialTargetRegister); 2404a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu const SpecialTargetRegister fpArgMappingToPhysicalReg[] = {kFArg0, kFArg1, kFArg2, kFArg3, 2405ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe kFArg4, kFArg5, kFArg6, kFArg7}; 2406ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe const int fpArgMappingToPhysicalRegSize = sizeof(fpArgMappingToPhysicalReg) / 2407ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe sizeof(SpecialTargetRegister); 240858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 240958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (is_double_or_float) { 241058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) { 2411ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe return ml_->TargetReg(fpArgMappingToPhysicalReg[cur_fp_reg_++], is_wide ? kWide : kNotWide); 241258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 241358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 241458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) { 2415ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe return ml_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++], 2416ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe is_ref ? kRef : (is_wide ? kWide : kNotWide)); 241758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 241858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 2419a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu return RegStorage::InvalidReg(); 242058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 242158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 242258994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::InToRegStorageMapping::Get(int in_position) { 242358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko DCHECK(IsInitialized()); 242458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko auto res = mapping_.find(in_position); 242558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return res != mapping_.end() ? res->second : RegStorage::InvalidReg(); 242658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 242758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2428ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampevoid X86Mir2Lir::InToRegStorageMapping::Initialize(RegLocation* arg_locs, int count, 2429ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe InToRegStorageMapper* mapper) { 243058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko DCHECK(mapper != nullptr); 243158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko max_mapped_in_ = -1; 243258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko is_there_stack_mapped_ = false; 243358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko for (int in_position = 0; in_position < count; in_position++) { 2434407a9d2847161b843966a443b71760b1280bd396Serguei Katkov RegStorage reg = mapper->GetNextReg(arg_locs[in_position].fp, 2435407a9d2847161b843966a443b71760b1280bd396Serguei Katkov arg_locs[in_position].wide, arg_locs[in_position].ref); 243658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (reg.Valid()) { 243758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko mapping_[in_position] = reg; 243858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko max_mapped_in_ = std::max(max_mapped_in_, in_position); 2439407a9d2847161b843966a443b71760b1280bd396Serguei Katkov if (arg_locs[in_position].wide) { 244058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // We covered 2 args, so skip the next one 244158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko in_position++; 244258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 244358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 244458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko is_there_stack_mapped_ = true; 244558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 244658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 244758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko initialized_ = true; 244858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 244958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 245058994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) { 2451dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 245258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return GetCoreArgMappingToPhysicalReg(arg_num); 245358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 245458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 245558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (!in_to_reg_storage_mapping_.IsInitialized()) { 24568d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru int start_vreg = cu_->mir_graph->GetFirstInVR(); 245758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation* arg_locs = &mir_graph_->reg_location_[start_vreg]; 245858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2459a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu InToRegStorageX86_64Mapper mapper(this); 24608d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru in_to_reg_storage_mapping_.Initialize(arg_locs, mir_graph_->GetNumOfInVRs(), &mapper); 246158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 246258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return in_to_reg_storage_mapping_.Get(arg_num); 246358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 246458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2465b28c1c06236751aa5c9e64dcb68b3c940341e496Ian RogersRegStorage X86Mir2Lir::GetCoreArgMappingToPhysicalReg(int core_arg_num) const { 246658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // For the 32-bit internal ABI, the first 3 arguments are passed in registers. 246758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Not used for 64-bit, TODO: Move X86_32 to the same framework 246858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko switch (core_arg_num) { 2469b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers case 0: return TargetReg32(kArg1); 2470b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers case 1: return TargetReg32(kArg2); 2471b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers case 2: return TargetReg32(kArg3); 2472b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers default: return RegStorage::InvalidReg(); 247358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 247458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 247558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 247658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// ---------End of ABI support: mapping of args to physical registers ------------- 247758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 247858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/* 247958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If there are any ins passed in registers that have not been promoted 248058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * to a callee-save register, flush them to the frame. Perform initial 248158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * assignment of promoted arguments. 248258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 248358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * ArgLocs is an array of location records describing the incoming arguments 248458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * with one location record per word of argument. 248558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 248658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkovoid X86Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) { 2487dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) return Mir2Lir::FlushIns(ArgLocs, rl_method); 248858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 248958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Dummy up a RegLocation for the incoming Method* 249058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * It will attempt to keep kArg0 live (or copy it to home location 249158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * if promoted). 249258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 249358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 249458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation rl_src = rl_method; 249558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_src.location = kLocPhysReg; 2496ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe rl_src.reg = TargetReg(kArg0, kRef); 249758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_src.home = false; 249858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko MarkLive(rl_src); 249958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko StoreValue(rl_method, rl_src); 250058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // If Method* has been promoted, explicitly flush 250158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (rl_method.location == kLocPhysReg) { 2502b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32; 2503b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreRefDisp(rs_rSP, 0, As32BitReg(TargetReg(kArg0, kRef)), kNotVolatile); 250458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 250558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25068d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru if (mir_graph_->GetNumOfInVRs() == 0) { 250758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return; 250858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 250958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25108d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru int start_vreg = cu_->mir_graph->GetFirstInVR(); 251158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 251258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Copy incoming arguments to their proper home locations. 251358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * NOTE: an older version of dx had an issue in which 251458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * it would reuse static method argument registers. 251558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * This could result in the same Dalvik virtual register 251658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * being promoted to both core and fp regs. To account for this, 251758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * we only copy to the corresponding promoted physical register 251858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * if it matches the type of the SSA name for the incoming 251958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * argument. It is also possible that long and double arguments 252058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * end up half-promoted. In those cases, we must flush the promoted 252158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * half to memory as well. 252258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 25238dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 25248d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru for (uint32_t i = 0; i < mir_graph_->GetNumOfInVRs(); i++) { 252558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // get reg corresponding to input 25264d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko RegStorage reg = GetArgMappingToPhysicalReg(i); 252758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25284d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko RegLocation* t_loc = &ArgLocs[i]; 252958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (reg.Valid()) { 25304d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // If arriving in register. 253158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25324d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // We have already updated the arg location with promoted info 25334d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // so we can be based on it. 25344d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->location == kLocPhysReg) { 25354d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // Just copy it. 25364d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko OpRegCopy(t_loc->reg, reg); 25374d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } else { 25384d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // Needs flush. 25394d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->ref) { 2540b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreRefDisp(rs_rX86_SP_64, SRegOffset(start_vreg + i), reg, kNotVolatile); 254158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 2542b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rX86_SP_64, SRegOffset(start_vreg + i), reg, t_loc->wide ? k64 : k32, 25434d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko kNotVolatile); 254458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 254558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 254658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 25474d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // If arriving in frame & promoted. 25484d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->location == kLocPhysReg) { 25494d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->ref) { 2550b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LoadRefDisp(rs_rX86_SP_64, SRegOffset(start_vreg + i), t_loc->reg, kNotVolatile); 25514d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } else { 2552b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers LoadBaseDisp(rs_rX86_SP_64, SRegOffset(start_vreg + i), t_loc->reg, 25534d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko t_loc->wide ? k64 : k32, kNotVolatile); 25544d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } 255558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 255658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 25574d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->wide) { 25584d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // Increment i to skip the next one. 25594d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko i++; 25604d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } 256158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 256258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 256358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 256458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/* 256558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Load up to 5 arguments, the first three of which will be in 256658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * kArg1 .. kArg3. On entry kArg0 contains the current method pointer, 256758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * and as part of the load sequence, it must be replaced with 256858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * the target method pointer. Note, this may also be called 256958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * for "range" variants if the number of arguments is 5 or fewer. 257058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 257158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsNoRange(CallInfo* info, 257258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int call_state, LIR** pcrLabel, NextCallInsn next_call_insn, 257358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const MethodReference& target_method, 257458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko uint32_t vtable_idx, uintptr_t direct_code, 257558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko uintptr_t direct_method, InvokeType type, bool skip_this) { 2576dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 257758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return Mir2Lir::GenDalvikArgsNoRange(info, 2578b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers call_state, pcrLabel, next_call_insn, 2579b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers target_method, 2580b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers vtable_idx, direct_code, 2581b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers direct_method, type, skip_this); 258258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 258358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return GenDalvikArgsRange(info, 2584b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers call_state, pcrLabel, next_call_insn, 2585b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers target_method, 2586b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers vtable_idx, direct_code, 2587b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers direct_method, type, skip_this); 258858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 258958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 259058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/* 259158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * May have 0+ arguments (also used for jumbo). Note that 259258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * source virtual registers may be in physical registers, so may 259358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * need to be flushed to home location before copying. This 259458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * applies to arg3 and above (see below). 259558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 259658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Two general strategies: 259758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If < 20 arguments 259858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass args 3-18 using vldm/vstm block copy 259958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass arg0, arg1 & arg2 in kArg1-kArg3 260058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If 20+ arguments 260158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass args arg19+ using memcpy block copy 260258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass arg0, arg1 & arg2 in kArg1-kArg3 260358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 260458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 260558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state, 260658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR** pcrLabel, NextCallInsn next_call_insn, 260758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const MethodReference& target_method, 260858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko uint32_t vtable_idx, uintptr_t direct_code, uintptr_t direct_method, 260958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko InvokeType type, bool skip_this) { 2610dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 261158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return Mir2Lir::GenDalvikArgsRange(info, call_state, 261258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko pcrLabel, next_call_insn, 261358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko target_method, 261458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, direct_method, 261558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko type, skip_this); 261658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 261758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 261858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* If no arguments, just return */ 261958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (info->num_arg_words == 0) 262058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return call_state; 262158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 262258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const int start_index = skip_this ? 1 : 0; 262358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2624a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu InToRegStorageX86_64Mapper mapper(this); 262558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko InToRegStorageMapping in_to_reg_storage_mapping; 262658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko in_to_reg_storage_mapping.Initialize(info->args, info->num_arg_words, &mapper); 262758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const int last_mapped_in = in_to_reg_storage_mapping.GetMaxMappedIn(); 262858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const int size_of_the_last_mapped = last_mapped_in == -1 ? 1 : 26298e3acdd132aef1391676a5db2696804900aacd8eSerguei Katkov info->args[last_mapped_in].wide ? 2 : 1; 263058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int regs_left_to_pass_via_stack = info->num_arg_words - (last_mapped_in + size_of_the_last_mapped); 263158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 263258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Fisrt of all, check whether it make sense to use bulk copying 263358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Optimization is aplicable only for range case 263458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // TODO: make a constant instead of 2 263558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (info->is_range && regs_left_to_pass_via_stack >= 2) { 263658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Scan the rest of the args - if in phys_reg flush to memory 263758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko for (int next_arg = last_mapped_in + size_of_the_last_mapped; next_arg < info->num_arg_words;) { 263858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation loc = info->args[next_arg]; 263958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (loc.wide) { 264058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko loc = UpdateLocWide(loc); 264158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (loc.location == kLocPhysReg) { 26428dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 2643b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rX86_SP_64, SRegOffset(loc.s_reg_low), loc.reg, k64, kNotVolatile); 264458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 264558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko next_arg += 2; 264658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 264758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko loc = UpdateLoc(loc); 264858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (loc.location == kLocPhysReg) { 26498dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 2650b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rX86_SP_64, SRegOffset(loc.s_reg_low), loc.reg, k32, kNotVolatile); 265158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 265258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko next_arg++; 265358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 265458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 265558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 265658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // The rest can be copied together 265758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int start_offset = SRegOffset(info->args[last_mapped_in + size_of_the_last_mapped].s_reg_low); 2658ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe int outs_offset = StackVisitor::GetOutVROffset(last_mapped_in + size_of_the_last_mapped, 2659ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe cu_->instruction_set); 266058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 266158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int current_src_offset = start_offset; 266258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int current_dest_offset = outs_offset; 266358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 26648dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko // Only davik regs are accessed in this loop; no next_call_insn() calls. 26658dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 266658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko while (regs_left_to_pass_via_stack > 0) { 266758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // This is based on the knowledge that the stack itself is 16-byte aligned. 266858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool src_is_16b_aligned = (current_src_offset & 0xF) == 0; 266958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool dest_is_16b_aligned = (current_dest_offset & 0xF) == 0; 267058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko size_t bytes_to_move; 267158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 267258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 267358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * The amount to move defaults to 32-bit. If there are 4 registers left to move, then do a 267458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * a 128-bit move because we won't get the chance to try to aligned. If there are more than 267558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 4 registers left to move, consider doing a 128-bit only if either src or dest are aligned. 267658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * We do this because we could potentially do a smaller move to align. 267758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 267858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (regs_left_to_pass_via_stack == 4 || 267958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko (regs_left_to_pass_via_stack > 4 && (src_is_16b_aligned || dest_is_16b_aligned))) { 268058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Moving 128-bits via xmm register. 268158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bytes_to_move = sizeof(uint32_t) * 4; 268258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 268358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Allocate a free xmm temp. Since we are working through the calling sequence, 268458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // we expect to have an xmm temporary available. AllocTempDouble will abort if 268558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // there are no free registers. 268658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage temp = AllocTempDouble(); 268758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 268858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* ld1 = nullptr; 268958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* ld2 = nullptr; 269058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* st1 = nullptr; 269158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* st2 = nullptr; 269258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 269358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 269458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * The logic is similar for both loads and stores. If we have 16-byte alignment, 269558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * do an aligned move. If we have 8-byte alignment, then do the move in two 269658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * parts. This approach prevents possible cache line splits. Finally, fall back 269758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * to doing an unaligned move. In most cases we likely won't split the cache 269858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * line but we cannot prove it and thus take a conservative approach. 269958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 270058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool src_is_8b_aligned = (current_src_offset & 0x7) == 0; 270158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool dest_is_8b_aligned = (current_dest_offset & 0x7) == 0; 270258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2703277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe ScopedMemRefType mem_ref_type2(this, ResourceMask::kDalvikReg); 270458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (src_is_16b_aligned) { 2705b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers ld1 = OpMovRegMem(temp, rs_rX86_SP_64, current_src_offset, kMovA128FP); 270658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else if (src_is_8b_aligned) { 2707b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers ld1 = OpMovRegMem(temp, rs_rX86_SP_64, current_src_offset, kMovLo128FP); 2708b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers ld2 = OpMovRegMem(temp, rs_rX86_SP_64, current_src_offset + (bytes_to_move >> 1), 270958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko kMovHi128FP); 271058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 2711b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers ld1 = OpMovRegMem(temp, rs_rX86_SP_64, current_src_offset, kMovU128FP); 271258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 271358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 271458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (dest_is_16b_aligned) { 2715b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers st1 = OpMovMemReg(rs_rX86_SP_64, current_dest_offset, temp, kMovA128FP); 271658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else if (dest_is_8b_aligned) { 2717b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers st1 = OpMovMemReg(rs_rX86_SP_64, current_dest_offset, temp, kMovLo128FP); 2718b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers st2 = OpMovMemReg(rs_rX86_SP_64, current_dest_offset + (bytes_to_move >> 1), 271958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko temp, kMovHi128FP); 272058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 2721b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers st1 = OpMovMemReg(rs_rX86_SP_64, current_dest_offset, temp, kMovU128FP); 272258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 272358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 272458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // TODO If we could keep track of aliasing information for memory accesses that are wider 272558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // than 64-bit, we wouldn't need to set up a barrier. 272658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (ld1 != nullptr) { 272758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (ld2 != nullptr) { 272858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // For 64-bit load we can actually set up the aliasing information. 272958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(ld1, current_src_offset >> 2, true, true); 273058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(ld2, (current_src_offset + (bytes_to_move >> 1)) >> 2, true, true); 273158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 273258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Set barrier for 128-bit load. 27338dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ld1->u.m.def_mask = &kEncodeAll; 273458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 273558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 273658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (st1 != nullptr) { 273758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (st2 != nullptr) { 273858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // For 64-bit store we can actually set up the aliasing information. 273958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(st1, current_dest_offset >> 2, false, true); 274058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(st2, (current_dest_offset + (bytes_to_move >> 1)) >> 2, false, true); 274158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 274258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Set barrier for 128-bit store. 27438dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko st1->u.m.def_mask = &kEncodeAll; 274458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 274558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 274658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 274758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Free the temporary used for the data movement. 274858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(temp); 274958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 275058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Moving 32-bits via general purpose register. 275158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bytes_to_move = sizeof(uint32_t); 275258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 275358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Instead of allocating a new temp, simply reuse one of the registers being used 275458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // for argument passing. 2755ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe RegStorage temp = TargetReg(kArg3, kNotWide); 275658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 275758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Now load the argument VR and store to the outs. 2758b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers Load32Disp(rs_rX86_SP_64, current_src_offset, temp); 2759b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers Store32Disp(rs_rX86_SP_64, current_dest_offset, temp); 276058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 276158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 276258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko current_src_offset += bytes_to_move; 276358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko current_dest_offset += bytes_to_move; 276458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko regs_left_to_pass_via_stack -= (bytes_to_move >> 2); 276558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 276658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko DCHECK_EQ(regs_left_to_pass_via_stack, 0); 276758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 276858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 276958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Now handle rest not registers if they are 277058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (in_to_reg_storage_mapping.IsThereStackMapped()) { 2771ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe RegStorage regSingle = TargetReg(kArg2, kNotWide); 2772ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe RegStorage regWide = TargetReg(kArg3, kWide); 2773b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu for (int i = start_index; 2774b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu i < last_mapped_in + size_of_the_last_mapped + regs_left_to_pass_via_stack; i++) { 277558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation rl_arg = info->args[i]; 277658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_arg = UpdateRawLoc(rl_arg); 277758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage reg = in_to_reg_storage_mapping.Get(i); 277858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (!reg.Valid()) { 277958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int out_offset = StackVisitor::GetOutVROffset(i, cu_->instruction_set); 278058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 27818dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko { 27828dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 27838dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (rl_arg.wide) { 27848dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (rl_arg.location == kLocPhysReg) { 2785b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rX86_SP_64, out_offset, rl_arg.reg, k64, kNotVolatile); 27868dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } else { 27878dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko LoadValueDirectWideFixed(rl_arg, regWide); 2788b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rX86_SP_64, out_offset, regWide, k64, kNotVolatile); 27898dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } 279058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 27918dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (rl_arg.location == kLocPhysReg) { 2792b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rX86_SP_64, out_offset, rl_arg.reg, k32, kNotVolatile); 27938dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } else { 27948dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko LoadValueDirectFixed(rl_arg, regSingle); 2795b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers StoreBaseDisp(rs_rX86_SP_64, out_offset, regSingle, k32, kNotVolatile); 27968dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } 279758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 279858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 279958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state = next_call_insn(cu_, info, call_state, target_method, 280058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, direct_method, type); 280158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 2802b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu if (rl_arg.wide) { 2803b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu i++; 2804b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu } 280558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 280658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 280758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 280858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Finish with mapped registers 280958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko for (int i = start_index; i <= last_mapped_in; i++) { 281058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation rl_arg = info->args[i]; 281158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_arg = UpdateRawLoc(rl_arg); 281258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage reg = in_to_reg_storage_mapping.Get(i); 281358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (reg.Valid()) { 281458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (rl_arg.wide) { 281558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LoadValueDirectWideFixed(rl_arg, reg); 281658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 281758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LoadValueDirectFixed(rl_arg, reg); 281858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 281958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, 282058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_code, direct_method, type); 282158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 2822b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu if (rl_arg.wide) { 2823b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu i++; 2824b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu } 282558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 282658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 282758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, 282858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_code, direct_method, type); 282958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (pcrLabel) { 283069dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) { 2831ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe *pcrLabel = GenExplicitNullCheck(TargetReg(kArg1, kRef), info->opt_flags); 283258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 283358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *pcrLabel = nullptr; 283458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // In lieu of generating a check for kArg1 being null, we need to 283558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // perform a load when doing implicit checks. 283658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage tmp = AllocTemp(); 2837ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe Load32Disp(TargetReg(kArg1, kRef), 0, tmp); 283858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko MarkPossibleNullPointerException(info->opt_flags); 283958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(tmp); 284058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 284158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 284258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return call_state; 284358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 284458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2845984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampebool X86Mir2Lir::GenInlinedCharAt(CallInfo* info) { 2846984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Location of reference to data array 2847984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int value_offset = mirror::String::ValueOffset().Int32Value(); 2848984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Location of count 2849984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int count_offset = mirror::String::CountOffset().Int32Value(); 2850984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Starting offset within data array 2851984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int offset_offset = mirror::String::OffsetOffset().Int32Value(); 2852984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Start of char data with array_ 2853984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); 2854984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe 2855984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_obj = info->args[0]; 2856984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_idx = info->args[1]; 2857984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe rl_obj = LoadValue(rl_obj, kRefReg); 2858984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // X86 wants to avoid putting a constant index into a register. 2859984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (!rl_idx.is_const) { 2860984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe rl_idx = LoadValue(rl_idx, kCoreReg); 2861984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2862984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegStorage reg_max; 2863984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe GenNullCheck(rl_obj.reg, info->opt_flags); 2864984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe bool range_check = (!(info->opt_flags & MIR_IGNORE_RANGE_CHECK)); 2865984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LIR* range_check_branch = nullptr; 2866984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegStorage reg_off; 2867984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegStorage reg_ptr; 2868984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (range_check) { 2869984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // On x86, we can compare to memory directly 2870984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Set up a launch pad to allow retry in case of bounds violation */ 2871984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (rl_idx.is_const) { 2872984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LIR* comparison; 2873984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe range_check_branch = OpCmpMemImmBranch( 2874984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe kCondUlt, RegStorage::InvalidReg(), rl_obj.reg, count_offset, 2875984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe mir_graph_->ConstantValue(rl_idx.orig_sreg), nullptr, &comparison); 2876984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe MarkPossibleNullPointerExceptionAfter(0, comparison); 2877984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } else { 2878984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe OpRegMem(kOpCmp, rl_idx.reg, rl_obj.reg, count_offset); 2879984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe MarkPossibleNullPointerException(0); 2880984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe range_check_branch = OpCondBranch(kCondUge, nullptr); 2881984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2882984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2883984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe reg_off = AllocTemp(); 2884984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe reg_ptr = AllocTempRef(); 2885984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe Load32Disp(rl_obj.reg, offset_offset, reg_off); 2886984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LoadRefDisp(rl_obj.reg, value_offset, reg_ptr, kNotVolatile); 2887984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (rl_idx.is_const) { 2888984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe OpRegImm(kOpAdd, reg_off, mir_graph_->ConstantValue(rl_idx.orig_sreg)); 2889984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } else { 2890984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe OpRegReg(kOpAdd, reg_off, rl_idx.reg); 2891984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2892984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(rl_obj.reg); 2893984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (rl_idx.location == kLocPhysReg) { 2894984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(rl_idx.reg); 2895984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2896984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_dest = InlineTarget(info); 2897984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 2898984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LoadBaseIndexedDisp(reg_ptr, reg_off, 1, data_offset, rl_result.reg, kUnsignedHalf); 2899984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(reg_off); 2900984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(reg_ptr); 2901984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe StoreValue(rl_dest, rl_result); 2902984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (range_check) { 2903984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe DCHECK(range_check_branch != nullptr); 2904984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe info->opt_flags |= MIR_IGNORE_NULL_CHECK; // Record that we've already null checked. 2905984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe AddIntrinsicSlowPath(info, range_check_branch); 2906984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2907984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe return true; 2908984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe} 2909984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe 29106bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalovbool X86Mir2Lir::GenInlinedCurrentThread(CallInfo* info) { 29116bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov RegLocation rl_dest = InlineTarget(info); 29126bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29136bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov // Early exit if the result is unused. 29146bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov if (rl_dest.orig_sreg < 0) { 29156bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov return true; 29166bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov } 29176bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29186bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true); 29196bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29206bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov if (cu_->target64) { 29216bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov OpRegThreadMem(kOpMov, rl_result.reg, Thread::PeerOffset<8>()); 29226bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov } else { 29236bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov OpRegThreadMem(kOpMov, rl_result.reg, Thread::PeerOffset<4>()); 29246bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov } 29256bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29266bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov StoreValue(rl_dest, rl_result); 29276bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov return true; 29286bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov} 29296bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29306dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev/** 29316dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev * Lock temp registers for explicit usage. Registers will be freed in destructor. 29326dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev */ 29336dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim KazantsevX86Mir2Lir::ExplicitTempRegisterLock::ExplicitTempRegisterLock(X86Mir2Lir* mir_to_lir, 29346dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev int n_regs, ...) : 29356dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev temp_regs_(n_regs), 29366dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_(mir_to_lir) { 29376dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev va_list regs; 29386dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev va_start(regs, n_regs); 29396dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev for (int i = 0; i < n_regs; i++) { 29406dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev RegStorage reg = *(va_arg(regs, RegStorage*)); 29416dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev RegisterInfo* info = mir_to_lir_->GetRegInfo(reg); 29426dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29436dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev // Make sure we don't have promoted register here. 29446dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev DCHECK(info->IsTemp()); 29456dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29466dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev temp_regs_.push_back(reg); 29476dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->FlushReg(reg); 29486dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29496dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev if (reg.IsPair()) { 29506dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev RegStorage partner = info->Partner(); 29516dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev temp_regs_.push_back(partner); 29526dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->FlushReg(partner); 29536dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev } 29546dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29556dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->Clobber(reg); 29566dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->LockTemp(reg); 29576dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev } 29586dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29596dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev va_end(regs); 29606dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev} 29616dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29626dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev/* 29636dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev * Free all locked registers. 29646dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev */ 29656dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim KazantsevX86Mir2Lir::ExplicitTempRegisterLock::~ExplicitTempRegisterLock() { 29666dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev // Free all locked temps. 29676dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev for (auto it : temp_regs_) { 29686dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->FreeTemp(it); 29696dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev } 29706dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev} 29716dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29727934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 2973