target_x86.cc revision 6a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866f
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 2153c913bb71b218714823c8c87a1f92830c336f61Andreas Gampe#include "backend_x86.h" 2202031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h" 237940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/compiler_internals.h" 247940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h" 25b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h" 267e70b002c4552347ed1af8c002a0e13f08864f20Ian Rogers#include "mirror/array-inl.h" 27f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko#include "mirror/art_method.h" 28e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell#include "mirror/string.h" 29b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A#include "oat.h" 30641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h" 31547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen#include "utils/dwarf_cfi.h" 32efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 33efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art { 34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 35089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_32[] = { 369ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI, 379ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 38089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_64[] = { 3976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI, 40091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_r8, rs_r9, rs_r10, rs_r11, rs_r12, rs_r13, rs_r14, rs_r15 41efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 42089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_64q[] = { 430999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko rs_r0q, rs_r1q, rs_r2q, rs_r3q, rs_rX86_SP_64, rs_r5q, rs_r6q, rs_r7q, 44a20468c004264592f309a548fc71ba62a69b8742Dmitry Petrochenko rs_r8q, rs_r9q, rs_r10q, rs_r11q, rs_r12q, rs_r13q, rs_r14q, rs_r15q 450999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko}; 46089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_regs_arr_32[] = { 479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 49089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_regs_arr_64[] = { 50091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 51091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 52efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 53089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_regs_arr_32[] = { 549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 56089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_regs_arr_64[] = { 57091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 58091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 59efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 60c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr RegStorage xp_regs_arr_32[] = { 61c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 62c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov}; 63c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr RegStorage xp_regs_arr_64[] = { 64c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 65c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr8, rs_xr9, rs_xr10, rs_xr11, rs_xr12, rs_xr13, rs_xr14, rs_xr15 66c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov}; 67089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage reserved_regs_arr_32[] = {rs_rX86_SP_32}; 6876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenkostatic constexpr RegStorage reserved_regs_arr_64[] = {rs_rX86_SP_32}; 69089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage reserved_regs_arr_64q[] = {rs_rX86_SP_64}; 70089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_32[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX}; 71089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_64[] = { 729ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rSI, rs_rDI, 739ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_r8, rs_r9, rs_r10, rs_r11 749ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 75c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 76c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// How to add register to be available for promotion: 77c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 1) Remove register from array defining temp 78c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 2) Update ClobberCallerSave 79c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 3) Update JNI compiler ABI: 80c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 3.1) add reg in JniCallingConvention method 81c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 3.2) update CoreSpillMask/FpSpillMask 82c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4) Update entrypoints 83c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.1) Update constants in asm_support_x86_64.h for new frame size 84c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.2) Remove entry in SmashCallerSaves 85c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.3) Update jni_entrypoints to spill/unspill new callee save reg 86c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.4) Update quick_entrypoints to spill/unspill new callee save reg 87c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 5) Update runtime ABI 88c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 5.1) Update quick_method_frame_info with new required spills 89c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 5.2) Update QuickArgumentVisitor with new offsets to gprs and xmms 90c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// Note that you cannot use register corresponding to incoming args 91c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// according to ABI and QCG needs one additional XMM temp for 92c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// bulk copy in preparation to call. 93089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_64q[] = { 940999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko rs_r0q, rs_r1q, rs_r2q, rs_r6q, rs_r7q, 950999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko rs_r8q, rs_r9q, rs_r10q, rs_r11q 960999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko}; 97089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_temps_arr_32[] = { 989ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 999ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 100089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_temps_arr_64[] = { 101091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 102c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_fr8, rs_fr9, rs_fr10, rs_fr11 103091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 104089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_temps_arr_32[] = { 1059ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 1069ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 107089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_temps_arr_64[] = { 108091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 109c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_dr8, rs_dr9, rs_dr10, rs_dr11 110091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 111091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 112089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage xp_temps_arr_32[] = { 113fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 114fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}; 115089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage xp_temps_arr_64[] = { 116fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 117c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr8, rs_xr9, rs_xr10, rs_xr11 118fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}; 119fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 120089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> empty_pool; 121089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_32(core_regs_arr_32); 122089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_64(core_regs_arr_64); 123089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_64q(core_regs_arr_64q); 124089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_regs_32(sp_regs_arr_32); 125089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_regs_64(sp_regs_arr_64); 126089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_regs_32(dp_regs_arr_32); 127089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_regs_64(dp_regs_arr_64); 128c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr ArrayRef<const RegStorage> xp_regs_32(xp_regs_arr_32); 129c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr ArrayRef<const RegStorage> xp_regs_64(xp_regs_arr_64); 130089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_32(reserved_regs_arr_32); 131089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_64(reserved_regs_arr_64); 132089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_64q(reserved_regs_arr_64q); 133089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_32(core_temps_arr_32); 134089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_64(core_temps_arr_64); 135089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_64q(core_temps_arr_64q); 136089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_temps_32(sp_temps_arr_32); 137089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_temps_64(sp_temps_arr_64); 138089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_temps_32(dp_temps_arr_32); 139089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_temps_64(dp_temps_arr_64); 140089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Marko 141089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> xp_temps_32(xp_temps_arr_32); 142089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> xp_temps_64(xp_temps_arr_64); 143fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1449ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_SP; 1459ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 1469ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG0; 1479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG1; 1489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG2; 1499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG3; 15058994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_ARG4; 15158994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_ARG5; 1529ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG0; 1539ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG1; 1549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG2; 1559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG3; 15658994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG4; 15758994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG5; 15858994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG6; 15958994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG7; 1609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_RET0; 1619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_RET1; 1629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_INVOKE_TGT; 1639ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_COUNT; 164efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1652ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturn() { 16600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return; 167efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 168efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 169a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbeeRegLocation X86Mir2Lir::LocCReturnRef() { 170a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu return cu_->target64 ? x86_64_loc_c_return_ref : x86_loc_c_return_ref; 171a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee} 172a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee 1732ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnWide() { 174dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina return cu_->target64 ? x86_64_loc_c_return_wide : x86_loc_c_return_wide; 175efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 176efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1772ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnFloat() { 17800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_float; 179efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 180efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1812ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnDouble() { 18200e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_double; 183efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 184efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 185a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu// Return a target-dependent special register for 32-bit. 186a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying FuRegStorage X86Mir2Lir::TargetReg32(SpecialTargetRegister reg) { 187091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage res_reg = RegStorage::InvalidReg(); 188efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (reg) { 189091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSelf: res_reg = RegStorage::InvalidReg(); break; 190091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSuspend: res_reg = RegStorage::InvalidReg(); break; 191091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kLr: res_reg = RegStorage::InvalidReg(); break; 192091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kPc: res_reg = RegStorage::InvalidReg(); break; 193ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe case kSp: res_reg = rs_rX86_SP_32; break; // This must be the concrete one, as _SP is target- 194ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe // specific size. 195091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg0: res_reg = rs_rX86_ARG0; break; 196091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg1: res_reg = rs_rX86_ARG1; break; 197091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg2: res_reg = rs_rX86_ARG2; break; 198091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg3: res_reg = rs_rX86_ARG3; break; 19958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kArg4: res_reg = rs_rX86_ARG4; break; 20058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kArg5: res_reg = rs_rX86_ARG5; break; 201091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg0: res_reg = rs_rX86_FARG0; break; 202091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg1: res_reg = rs_rX86_FARG1; break; 203091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg2: res_reg = rs_rX86_FARG2; break; 204091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg3: res_reg = rs_rX86_FARG3; break; 20558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kFArg4: res_reg = rs_rX86_FARG4; break; 20658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kFArg5: res_reg = rs_rX86_FARG5; break; 20758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kFArg6: res_reg = rs_rX86_FARG6; break; 20858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kFArg7: res_reg = rs_rX86_FARG7; break; 209091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kRet0: res_reg = rs_rX86_RET0; break; 210091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kRet1: res_reg = rs_rX86_RET1; break; 211091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kInvokeTgt: res_reg = rs_rX86_INVOKE_TGT; break; 212091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kHiddenArg: res_reg = rs_rAX; break; 213dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina case kHiddenFpArg: DCHECK(!cu_->target64); res_reg = rs_fr0; break; 214091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kCount: res_reg = rs_rX86_COUNT; break; 21558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko default: res_reg = RegStorage::InvalidReg(); 216091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee } 217091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee return res_reg; 218efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 219efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 220a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying FuRegStorage X86Mir2Lir::TargetReg(SpecialTargetRegister reg) { 2216a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(reg); 222a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LOG(FATAL) << "Do not use this function!!!"; 2236a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 224a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu} 225a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu 226efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 227efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Decode the register id. 228efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 2298dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask X86Mir2Lir::GetRegMaskCommon(const RegStorage& reg) const { 2308dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko /* Double registers in x86 are just a single FP register. This is always just a single bit. */ 2318dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko return ResourceMask::Bit( 2328dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko /* FP register starts at bit position 16 */ 2338dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ((reg.IsFloat() || reg.StorageSize() > 8) ? kX86FPReg0 : 0) + reg.GetRegNum()); 2348dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko} 2358dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko 2368dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask X86Mir2Lir::GetPCUseDefEncoding() const { 2378dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko return kEncodeNone; 238efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 239efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 2408dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid X86Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags, 2418dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ResourceMask* use_mask, ResourceMask* def_mask) { 2426a58cb16d803c9a7b3a75ccac8be19dd9d4e520dDmitry Petrochenko DCHECK(cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64); 243b48819db07f9a0992a72173380c24249d7fc648abuzbee DCHECK(!lir->flags.use_def_invalid); 244efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 245efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // X86-specific resource map setup here. 246efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USE_SP) { 2478dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko use_mask->SetBit(kX86RegSP); 248efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 249efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 250efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEF_SP) { 2518dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko def_mask->SetBit(kX86RegSP); 252efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 253efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 254efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFA) { 2558dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(def_mask, rs_rAX.GetReg()); 256efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 257efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 258efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFD) { 2598dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(def_mask, rs_rDX.GetReg()); 260efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 261efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEA) { 2628dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rAX.GetReg()); 263efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 264efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 265efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEC) { 2668dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rCX.GetReg()); 267efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 268efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 269efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USED) { 2708dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rDX.GetReg()); 271efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 27270b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko 27370b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko if (flags & REG_USEB) { 2748dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rBX.GetReg()); 27570b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko } 2764028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 2774028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Fixup hard to describe instruction: Uses rAX, rCX, rDI; sets rDI. 2784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (lir->opcode == kX86RepneScasw) { 2798dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rAX.GetReg()); 2808dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rCX.GetReg()); 2818dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rDI.GetReg()); 2828dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(def_mask, rs_rDI.GetReg()); 2834028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 284e90501da0222717d75c126ebf89569db3976927eSerguei Katkov 285e90501da0222717d75c126ebf89569db3976927eSerguei Katkov if (flags & USE_FP_STACK) { 2868dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko use_mask->SetBit(kX86FPStack); 2878dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko def_mask->SetBit(kX86FPStack); 288e90501da0222717d75c126ebf89569db3976927eSerguei Katkov } 289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 291efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* For dumping instructions */ 292efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86RegName[] = { 293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 297efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86CondName[] = { 298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "O", 299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NO", 300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "B/NAE/C", 301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NB/AE/NC", 302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "Z/EQ", 303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NZ/NE", 304efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "BE/NA", 305efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NBE/A", 306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "S", 307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NS", 308efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "P/PE", 309efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NP/PO", 310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "L/NGE", 311efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NL/GE", 312efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "LE/NG", 313efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NLE/G" 314efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 315efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 316efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 317efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Interpret a format string and build a string no longer than size 318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See format key in Assemble.cc. 319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 3201fd3346740dfb7f47be9922312b68a4227fada96buzbeestd::string X86Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) { 321efc6369224b036a1fb77849f7ae65b3492c832c0buzbee std::string buf; 322efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t i = 0; 323efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t fmt_len = strlen(fmt); 324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee while (i < fmt_len) { 325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (fmt[i] != '!') { 326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += fmt[i]; 327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char operand_number_ch = fmt[i]; 332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 333efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (operand_number_ch == '!') { 334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += "!"; 335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand_number = operand_number_ch - '0'; 337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(operand_number, 6); // Expect upto 6 LIR operands. 338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 339efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand = lir->operands[operand_number]; 340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (fmt[i]) { 341efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'c': 342efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(static_cast<size_t>(operand), sizeof(x86CondName)); 343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += x86CondName[operand]; 344efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 345efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'd': 346efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("%d", operand); 347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 3485192cbb12856b12620dc346758605baaa1469cedYixin Shou case 'q': { 3495192cbb12856b12620dc346758605baaa1469cedYixin Shou int64_t value = static_cast<int64_t>(static_cast<int64_t>(operand) << 32 | 3505192cbb12856b12620dc346758605baaa1469cedYixin Shou static_cast<uint32_t>(lir->operands[operand_number+1])); 3515192cbb12856b12620dc346758605baaa1469cedYixin Shou buf +=StringPrintf("%" PRId64, value); 352e70f179aca4f13b15be8a47a4d9e5b6c2422c69aHaitao Feng break; 3535192cbb12856b12620dc346758605baaa1469cedYixin Shou } 354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'p': { 3550d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(operand)); 356fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee buf += StringPrintf("0x%08x", tab_rec->offset); 357efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 358efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 359efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'r': 360091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (RegStorage::IsFloat(operand)) { 361091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int fp_reg = RegStorage::RegNum(operand); 362efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("xmm%d", fp_reg); 363efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 364091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int reg_num = RegStorage::RegNum(operand); 365091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK_LT(static_cast<size_t>(reg_num), sizeof(x86RegName)); 366091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee buf += x86RegName[reg_num]; 367efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 368efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 369efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 't': 370107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers buf += StringPrintf("0x%08" PRIxPTR " (L%p)", 371107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers reinterpret_cast<uintptr_t>(base_addr) + lir->offset + operand, 372107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers lir->target); 373efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 374efc6369224b036a1fb77849f7ae65b3492c832c0buzbee default: 375efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("DecodeError '%c'", fmt[i]); 376efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 378efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 381efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 382efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return buf; 383efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 384efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3858dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid X86Mir2Lir::DumpResourceMask(LIR *x86LIR, const ResourceMask& mask, const char *prefix) { 386efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char buf[256]; 387efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf[0] = 0; 388efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3898dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.Equals(kEncodeAll)) { 390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcpy(buf, "all"); 391efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 392efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char num[8]; 393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int i; 394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 395efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (i = 0; i < kX86RegEnd; i++) { 3968dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(i)) { 397988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(num, arraysize(num), "%d ", i); 398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, num); 399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 400efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 401efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4028dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kCCode)) { 403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "cc "); 404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Memory bits */ 4068dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (x86LIR && (mask.HasBit(ResourceMask::kDalvikReg))) { 407988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s", 408988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers DECODE_ALIAS_INFO_REG(x86LIR->flags.alias_info), 409988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers (DECODE_ALIAS_INFO_WIDE(x86LIR->flags.alias_info)) ? "(+1)" : ""); 410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 4118dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kLiteral)) { 412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "lit "); 413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4158dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kHeapRef)) { 416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "heap "); 417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 4188dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kMustNotAlias)) { 419efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "noalias "); 420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 422efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (buf[0]) { 423efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(INFO) << prefix << ": " << buf; 424efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 425efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 42602031b185b4653e6c72e21f7a51238b903f6d638buzbee 4271fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::AdjustSpillMask() { 428efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Adjustment for LR spilling, x86 has no LR so nothing to do here 429091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee core_spill_mask_ |= (1 << rs_rRET.GetRegNum()); 4301fd3346740dfb7f47be9922312b68a4227fada96buzbee num_core_spills_++; 431efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 432efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 433e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark MendellRegStorage X86Mir2Lir::AllocateByteRegister() { 4347e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu RegStorage reg = AllocTypedTemp(false, kCoreReg); 435dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 4367e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu DCHECK_LT(reg.GetRegNum(), rs_rX86_SP.GetRegNum()); 4377e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu } 4387e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu return reg; 4397e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu} 4407e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu 44160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan BanerjiRegStorage X86Mir2Lir::Get128BitRegister(RegStorage reg) { 442b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return GetRegInfo(reg)->Master()->GetReg(); 44360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 44460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 4457e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fubool X86Mir2Lir::IsByteRegister(RegStorage reg) { 446dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina return cu_->target64 || reg.GetRegNum() < rs_rX86_SP.GetRegNum(); 447e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell} 448e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell 449efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Clobber all regs that might be used by an external C call */ 45031c2aac7137b69d5622eea09597500731fbee2efVladimir Markovoid X86Mir2Lir::ClobberCallerSave() { 451dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 452c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rAX); 453c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rCX); 454c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rDX); 455c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rSI); 456c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rDI); 457c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 45835ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r8); 45935ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r9); 46035ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r10); 46135ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r11); 46235ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu 46335ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr8); 46435ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr9); 46535ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr10); 46635ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr11); 467c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } else { 468c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rAX); 469c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rCX); 470c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rDX); 471c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rBX); 47235ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu } 473c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 474c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr0); 475c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr1); 476c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr2); 477c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr3); 478c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr4); 479c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr5); 480c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr6); 481c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr7); 482efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 483efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4841fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation X86Mir2Lir::GetReturnWideAlt() { 48552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturnWide(); 486091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(res.reg.GetLowReg() == rs_rAX.GetReg()); 487091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(res.reg.GetHighReg() == rs_rDX.GetReg()); 488091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rAX); 489091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 490091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rAX); 491091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 492091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkWide(res.reg); 493efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 494efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 495efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4962ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::GetReturnAlt() { 49752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturn(); 498091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee res.reg.SetReg(rs_rDX.GetReg()); 499091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 500091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 501efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 502efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 503efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 504efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 5052ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::LockCallTemps() { 506091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG0); 507091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG1); 508091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG2); 509091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG3); 510dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 51158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_ARG4); 51258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_ARG5); 51358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG0); 51458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG1); 51558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG2); 51658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG3); 51758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG4); 51858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG5); 51958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG6); 52058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG7); 52158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 522efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 523efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 524efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 5252ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::FreeCallTemps() { 526091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG0); 527091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG1); 528091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG2); 529091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG3); 530dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 53158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_ARG4); 53258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_ARG5); 53358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG0); 53458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG1); 53558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG2); 53658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG3); 53758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG4); 53858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG5); 53958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG6); 54058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG7); 54158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 542efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 543efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 54499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusorubool X86Mir2Lir::ProvidesFullMemoryBarrier(X86OpCode opcode) { 54599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru switch (opcode) { 54699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgMR: 54799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgAR: 5480f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers case kX86LockCmpxchg64M: 5490f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers case kX86LockCmpxchg64A: 55099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86XchgMR: 55199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86Mfence: 55299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Atomic memory instructions provide full barrier. 55399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return true; 55499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru default: 55599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru break; 55699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 55799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 55899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Conservative if cannot prove it provides full barrier. 55999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return false; 56099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru} 56199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 562b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampebool X86Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) { 563efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0 56499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Start off with using the last LIR as the barrier. If it is not enough, then we will update it. 56599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru LIR* mem_barrier = last_lir_insn_; 56699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 567b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe bool ret = false; 56899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru /* 56948f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm * According to the JSR-133 Cookbook, for x86 only StoreLoad/AnyAny barriers need memory fence. 57048f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm * All other barriers (LoadAny, AnyStore, StoreStore) are nops due to the x86 memory model. 57148f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm * For those cases, all we need to ensure is that there is a scheduling barrier in place. 57299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru */ 57348f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm if (barrier_kind == kAnyAny) { 57499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If no LIR exists already that can be used a barrier, then generate an mfence. 57599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 57699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 577b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe ret = true; 57899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 57999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 58099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If last instruction does not provide full barrier, then insert an mfence. 58199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (ProvidesFullMemoryBarrier(static_cast<X86OpCode>(mem_barrier->opcode)) == false) { 58299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 583b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe ret = true; 58499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 585b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler } else if (barrier_kind == kNTStoreStore) { 586b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler mem_barrier = NewLIR0(kX86Sfence); 587b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler ret = true; 58899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 58999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 59099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Now ensure that a scheduling barrier is in place. 59199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 59299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru GenBarrier(); 59399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } else { 59499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Mark as a scheduling barrier. 59599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru DCHECK(!mem_barrier->flags.use_def_invalid); 5968dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko mem_barrier->u.m.def_mask = &kEncodeAll; 59799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 598b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe return ret; 599b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe#else 600b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe return false; 601efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 602efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 60300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee 6041fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::CompilerInitializeRegAlloc() { 605dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 606e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64q, sp_regs_64, 607e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko dp_regs_64, reserved_regs_64, reserved_regs_64q, 608e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko core_temps_64, core_temps_64q, 609e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko sp_temps_64, dp_temps_64)); 6109ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 611e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reg_pool_.reset(new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, sp_regs_32, 612e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko dp_regs_32, reserved_regs_32, empty_pool, 613e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko core_temps_32, empty_pool, 614e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko sp_temps_32, dp_temps_32)); 6159ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 616091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 617091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Target-specific adjustments. 618091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 619fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Add in XMM registers. 620c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov const ArrayRef<const RegStorage> *xp_regs = cu_->target64 ? &xp_regs_64 : &xp_regs_32; 621c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (RegStorage reg : *xp_regs) { 622fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell RegisterInfo* info = new (arena_) RegisterInfo(reg, GetRegMaskCommon(reg)); 623e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reginfo_map_[reg.GetReg()] = info; 624c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 625c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov const ArrayRef<const RegStorage> *xp_temps = cu_->target64 ? &xp_temps_64 : &xp_temps_32; 626c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (RegStorage reg : *xp_temps) { 627c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov RegisterInfo* xp_reg_info = GetRegInfo(reg); 628c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov xp_reg_info->SetIsTemp(true); 629fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 630fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 631091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Alias single precision xmm to double xmms. 632091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: as needed, add larger vector sizes - alias all to the largest. 633e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (RegisterInfo* info : reg_pool_->sp_regs_) { 634091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int sp_reg_num = info->GetReg().GetRegNum(); 635fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell RegStorage xp_reg = RegStorage::Solo128(sp_reg_num); 636fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell RegisterInfo* xp_reg_info = GetRegInfo(xp_reg); 637fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // 128-bit xmm vector register's master storage should refer to itself. 638fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell DCHECK_EQ(xp_reg_info, xp_reg_info->Master()); 639fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 640fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Redirect 32-bit vector's master storage to 128-bit vector. 641fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell info->SetMaster(xp_reg_info); 642fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 64376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko RegStorage dp_reg = RegStorage::FloatSolo64(sp_reg_num); 644091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegisterInfo* dp_reg_info = GetRegInfo(dp_reg); 645fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Redirect 64-bit vector's master storage to 128-bit vector. 646fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell dp_reg_info->SetMaster(xp_reg_info); 64776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // Singles should show a single 32-bit mask bit, at first referring to the low half. 64876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko DCHECK_EQ(info->StorageMask(), 0x1U); 64976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko } 65076af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko 651dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 65276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // Alias 32bit W registers to corresponding 64bit X registers. 653e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (RegisterInfo* info : reg_pool_->core_regs_) { 65476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko int x_reg_num = info->GetReg().GetRegNum(); 65576af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko RegStorage x_reg = RegStorage::Solo64(x_reg_num); 65676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko RegisterInfo* x_reg_info = GetRegInfo(x_reg); 65776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // 64bit X register's master storage should refer to itself. 65876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko DCHECK_EQ(x_reg_info, x_reg_info->Master()); 65976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // Redirect 32bit W master storage to 64bit X. 66076af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko info->SetMaster(x_reg_info); 66176af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // 32bit W should show a single 32-bit mask bit, at first referring to the low half. 66276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko DCHECK_EQ(info->StorageMask(), 0x1U); 66376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko } 664efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 665091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 666091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods. 667091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: adjust for x86/hard float calling convention. 668091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_core_reg_ = 2; 669091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_sp_reg_ = 2; 670091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_dp_reg_ = 1; 671efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 672efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 67360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjiint X86Mir2Lir::VectorRegisterSize() { 67460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return 128; 67560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 67660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 677b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Aint X86Mir2Lir::NumReservableVectorRegisters(bool long_or_fp) { 678b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int num_vector_temps = cu_->target64 ? xp_temps_64.size() : xp_temps_32.size(); 679b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 680b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Leave a few temps for use by backend as scratch. 681b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return long_or_fp ? num_vector_temps - 2 : num_vector_temps - 1; 68260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 68360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 6841fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::SpillCoreRegs() { 6851fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_core_spills_ == 0) { 686efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 687efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 688efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Spill mask not including fake return address register 689091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 6909ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 691c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov OpSize size = cu_->target64 ? k64 : k32; 692efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (int reg = 0; mask; mask >>= 1, reg++) { 693efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & 0x1) { 694c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov StoreBaseDisp(rs_rX86_SP, offset, cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg), 695c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov size, kNotVolatile); 6969ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko offset += GetInstructionSetPointerSize(cu_->instruction_set); 697efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 698efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 699efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 700efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 7011fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::UnSpillCoreRegs() { 7021fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_core_spills_ == 0) { 703efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 704efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 705efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Spill mask not including fake return address register 706091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 7079ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 708c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov OpSize size = cu_->target64 ? k64 : k32; 709efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (int reg = 0; mask; mask >>= 1, reg++) { 710efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & 0x1) { 711c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov LoadBaseDisp(rs_rX86_SP, offset, cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg), 712c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov size, kNotVolatile); 7139ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko offset += GetInstructionSetPointerSize(cu_->instruction_set); 714efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 715efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 716efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 717efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 718c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovvoid X86Mir2Lir::SpillFPRegs() { 719c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (num_fp_spills_ == 0) { 720c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov return; 721c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 722c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov uint32_t mask = fp_spill_mask_; 723c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * (num_fp_spills_ + num_core_spills_)); 724c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (int reg = 0; mask; mask >>= 1, reg++) { 725c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (mask & 0x1) { 726c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov StoreBaseDisp(rs_rX86_SP, offset, RegStorage::FloatSolo64(reg), 727c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov k64, kNotVolatile); 728c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov offset += sizeof(double); 729c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 730c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 731c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov} 732c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovvoid X86Mir2Lir::UnSpillFPRegs() { 733c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (num_fp_spills_ == 0) { 734c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov return; 735c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 736c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov uint32_t mask = fp_spill_mask_; 737c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * (num_fp_spills_ + num_core_spills_)); 738c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (int reg = 0; mask; mask >>= 1, reg++) { 739c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (mask & 0x1) { 740c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov LoadBaseDisp(rs_rX86_SP, offset, RegStorage::FloatSolo64(reg), 741c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov k64, kNotVolatile); 742c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov offset += sizeof(double); 743c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 744c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 745c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov} 746c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 747c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 7482ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::IsUnconditionalBranch(LIR* lir) { 749cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32); 750efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 751efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 752674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoRegisterClass X86Mir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) { 753e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu // X86_64 can handle any size. 754dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 75506839f868c9c4bb1f2f6333f9e88a560e80bcad8Chao-ying Fu return RegClassBySize(size); 756e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } 757e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu 758674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko if (UNLIKELY(is_volatile)) { 759674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // On x86, atomic 64-bit load/store requires an fp register. 760674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // Smaller aligned load/store is atomic for both core and fp registers. 761674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko if (size == k64 || size == kDouble) { 762674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return kFPReg; 763674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko } 764674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko } 765674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return RegClassBySize(size); 766674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko} 767674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 768dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena SayapinaX86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena) 76955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell : Mir2Lir(cu, mir_graph, arena), 770dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers base_of_code_(nullptr), store_method_addr_(false), store_method_addr_used_(false), 771e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko method_address_insns_(arena->Adapter()), 772e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko class_type_address_insns_(arena->Adapter()), 773e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko call_method_insns_(arena->Adapter()), 774dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina stack_decrement_(nullptr), stack_increment_(nullptr), 775d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell const_vectors_(nullptr) { 776e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko method_address_insns_.reserve(100); 777e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko class_type_address_insns_.reserve(100); 778e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko call_method_insns_.reserve(100); 779d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell store_method_addr_used_ = false; 780dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers for (int i = 0; i < kX86Last; i++) { 7816a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers DCHECK_EQ(X86Mir2Lir::EncodingMap[i].opcode, i) 7826a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name 7836a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers << " is wrong: expecting " << i << ", seeing " 7846a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode); 785efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 786dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 7879ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_SP = rs_rX86_SP_64; 7889ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 7899ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG0 = rs_rDI; 7909ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG1 = rs_rSI; 7919ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG2 = rs_rDX; 7929ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG3 = rs_rCX; 79358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_ARG4 = rs_r8; 79458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_ARG5 = rs_r9; 79558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG0 = rs_fr0; 79658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG1 = rs_fr1; 79758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG2 = rs_fr2; 79858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG3 = rs_fr3; 79958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG4 = rs_fr4; 80058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG5 = rs_fr5; 80158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG6 = rs_fr6; 80258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG7 = rs_fr7; 80355884bc1e2e1b324809b462455ccaf5811ffafd8Mark Mendell rs_rX86_INVOKE_TGT = rs_rDI; 8049ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 8059ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_SP = rs_rX86_SP_32; 8069ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 8079ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG0 = rs_rAX; 8089ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG1 = rs_rCX; 8099ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG2 = rs_rDX; 8109ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG3 = rs_rBX; 81158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_ARG4 = RegStorage::InvalidReg(); 81258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_ARG5 = RegStorage::InvalidReg(); 81358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG0 = rs_rAX; 81458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG1 = rs_rCX; 81558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG2 = rs_rDX; 81658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG3 = rs_rBX; 81758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG4 = RegStorage::InvalidReg(); 81858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG5 = RegStorage::InvalidReg(); 81958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG6 = RegStorage::InvalidReg(); 82058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG7 = RegStorage::InvalidReg(); 82155884bc1e2e1b324809b462455ccaf5811ffafd8Mark Mendell rs_rX86_INVOKE_TGT = rs_rAX; 82258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // TODO(64): Initialize with invalid reg 82358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// rX86_ARG4 = RegStorage::InvalidReg(); 82458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// rX86_ARG5 = RegStorage::InvalidReg(); 8259ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 8269ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_RET0 = rs_rAX; 8279ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_RET1 = rs_rDX; 8289ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_COUNT = rs_rCX; 8291fd3346740dfb7f47be9922312b68a4227fada96buzbee} 8301fd3346740dfb7f47be9922312b68a4227fada96buzbee 831862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 832862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee ArenaAllocator* const arena) { 833dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina return new X86Mir2Lir(cu, mir_graph, arena); 834efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 835efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 836984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe// Not used in x86(-64) 837984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas GampeRegStorage X86Mir2Lir::LoadHelper(QuickEntrypointEnum trampoline) { 8386a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(trampoline); 8392f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe LOG(FATAL) << "Unexpected use of LoadHelper in x86"; 8406a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 8412f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe} 8422f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe 843b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave AllisonLIR* X86Mir2Lir::CheckSuspendUsingLoad() { 84469dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // First load the pointer in fs:[suspend-trigger] into eax 84569dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // Then use a test instruction to indirect via that address. 846dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison if (cu_->target64) { 847dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison NewLIR2(kX86Mov64RT, rs_rAX.GetReg(), 848dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison Thread::ThreadSuspendTriggerOffset<8>().Int32Value()); 849dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison } else { 850dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison NewLIR2(kX86Mov32RT, rs_rAX.GetReg(), 851dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison Thread::ThreadSuspendTriggerOffset<4>().Int32Value()); 852dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison } 85369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison return NewLIR3(kX86Test32RM, rs_rAX.GetReg(), rs_rAX.GetReg(), 0); 854b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison} 855b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison 8562ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t X86Mir2Lir::GetTargetInstFlags(int opcode) { 857409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 8581fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].flags; 8591bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 8601bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 8612ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstName(int opcode) { 862409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 8631fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].name; 8641bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 8651bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 8662ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstFmt(int opcode) { 867409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 8681fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].fmt; 8691bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 8701bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 871d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbeevoid X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) { 872d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Can we do this directly to memory? 873d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee rl_dest = UpdateLocWide(rl_dest); 874d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee if ((rl_dest.location == kLocDalvikFrame) || 875d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee (rl_dest.location == kLocCompilerTemp)) { 876d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_lo = Low32Bits(value); 877d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_hi = High32Bits(value); 878a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu int r_base = rs_rX86_SP.GetReg(); 879d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int displacement = SRegOffset(rl_dest.s_reg_low); 880d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 8818dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 8822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR * store = NewLIR3(kX86Mov32MI, r_base, displacement + LOWORD_OFFSET, val_lo); 883d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2, 884d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 8852700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR3(kX86Mov32MI, r_base, displacement + HIWORD_OFFSET, val_hi); 886d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2, 887d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 888d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee return; 889d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee } 890d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 891d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Just use the standard code to do the generation. 892d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee Mir2Lir::GenConstWide(rl_dest, value); 893d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee} 894e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 895e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell// TODO: Merge with existing RegLocation dumper in vreg_analysis.cc 896e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendellvoid X86Mir2Lir::DumpRegLocation(RegLocation loc) { 897e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell LOG(INFO) << "location: " << loc.location << ',' 898e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.wide ? " w" : " ") 899e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.defined ? " D" : " ") 900e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.is_const ? " c" : " ") 901e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.fp ? " F" : " ") 902e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.core ? " C" : " ") 903e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.ref ? " r" : " ") 904e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.high_word ? " h" : " ") 905e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.home ? " H" : " ") 9062700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee << ", low: " << static_cast<int>(loc.reg.GetLowReg()) 90700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee << ", high: " << static_cast<int>(loc.reg.GetHighReg()) 908e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", s_reg: " << loc.s_reg_low 909e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", orig: " << loc.orig_sreg; 910e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell} 911e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 91267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::Materialize() { 91367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // A good place to put the analysis before starting. 91467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeMIR(); 91567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 91667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Now continue with regular code generation. 91767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell Mir2Lir::Materialize(); 91867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 91967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 92049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Haovoid X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type, 92155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell SpecialTargetRegister symbolic_reg) { 92255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 92355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 92455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 92555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 92655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 92749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 92849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 92949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 93049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 93155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 93249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the move instruction with the unique pointer and save index, dex_file, and type. 933ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, 934ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe TargetReg(symbolic_reg, kNotWide).GetReg(), 93549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<int>(target_method_id_ptr), target_method_idx, 93649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 93755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 938e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko method_address_insns_.push_back(move); 93955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 94055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 941e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shihvoid X86Mir2Lir::LoadClassType(const DexFile& dex_file, uint32_t type_idx, 942e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih SpecialTargetRegister symbolic_reg) { 94355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 94455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 94555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 94655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 94755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 948e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih const DexFile::TypeId& id = dex_file.GetTypeId(type_idx); 94955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell uintptr_t ptr = reinterpret_cast<uintptr_t>(&id); 95055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 95155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Generate the move instruction with the unique pointer and save index and type. 952ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, 953ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe TargetReg(symbolic_reg, kNotWide).GetReg(), 954e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih static_cast<int>(ptr), type_idx, 955e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih WrapPointer(const_cast<DexFile*>(&dex_file))); 95655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 957e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko class_type_address_insns_.push_back(move); 95855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 95955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 960f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir MarkoLIR* X86Mir2Lir::CallWithLinkerFixup(const MethodReference& target_method, InvokeType type) { 96155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 96255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit call relative instruction, that will be filled 963f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko * in at 'link time'. 96455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 96549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 96649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 96749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao 96849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the call instruction with the unique pointer and save index, dex_file, and type. 969f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko // NOTE: Method deduplication takes linker patches into account, so we can just pass 0 970f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko // as a placeholder for the offset. 971f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko LIR* call = RawLIR(current_dalvik_offset_, kX86CallI, 0, 97249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 97355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(call); 974e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko call_method_insns_.push_back(call); 97555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell return call; 97655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 97755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 978f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Markostatic LIR* GenInvokeNoInlineCall(Mir2Lir* mir_to_lir, InvokeType type) { 979f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko QuickEntrypointEnum trampoline; 980f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko switch (type) { 981f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kInterface: 982f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeInterfaceTrampolineWithAccessCheck; 983f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 984f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kDirect: 985f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeDirectTrampolineWithAccessCheck; 986f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 987f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kStatic: 988f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeStaticTrampolineWithAccessCheck; 989f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 990f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kSuper: 991f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeSuperTrampolineWithAccessCheck; 992f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 993f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko case kVirtual: 994f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeVirtualTrampolineWithAccessCheck; 995f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko break; 996f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko default: 997f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko LOG(FATAL) << "Unexpected invoke type"; 998f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko trampoline = kQuickInvokeInterfaceTrampolineWithAccessCheck; 999f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 1000f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko return mir_to_lir->InvokeTrampoline(kOpBlx, RegStorage::InvalidReg(), trampoline); 1001f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko} 1002f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko 1003f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir MarkoLIR* X86Mir2Lir::GenCallInsn(const MirMethodLoweringInfo& method_info) { 1004f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko LIR* call_insn; 1005f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko if (method_info.FastPath()) { 1006f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko if (method_info.DirectCode() == static_cast<uintptr_t>(-1)) { 1007f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko // We can have the linker fixup a call relative. 1008f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko call_insn = CallWithLinkerFixup(method_info.GetTargetMethod(), method_info.GetSharpType()); 1009f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } else { 1010f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko call_insn = OpMem(kOpBlx, TargetReg(kArg0, kRef), 1011f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value()); 1012f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 1013f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } else { 1014f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko call_insn = GenInvokeNoInlineCall(this, method_info.GetSharpType()); 1015f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko } 1016f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko return call_insn; 1017f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko} 1018f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko 101955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::InstallLiteralPools() { 102055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // These are handled differently for x86. 102155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(code_literal_list_ == nullptr); 102255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(method_literal_list_ == nullptr); 102355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(class_literal_list_ == nullptr); 102455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 1025d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1026b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (const_vectors_ != nullptr) { 1027b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Vector literals must be 16-byte aligned. The header that is placed 1028b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // in the code section causes misalignment so we take it into account. 1029b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Otherwise, we are sure that for x86 method is aligned to 16. 1030b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A DCHECK_EQ(GetInstructionSetAlignment(cu_->instruction_set), 16u); 1031b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A uint32_t bytes_to_fill = (0x10 - ((code_buffer_.size() + sizeof(OatQuickMethodHeader)) & 0xF)) & 0xF; 1032b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A while (bytes_to_fill > 0) { 1033d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell code_buffer_.push_back(0); 1034b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bytes_to_fill--; 1035d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1036b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1037d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell for (LIR *p = const_vectors_; p != nullptr; p = p->next) { 1038547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[0]); 1039547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[1]); 1040547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[2]); 1041547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[3]); 1042d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1043d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1044d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 104555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for methods. 1046e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (LIR* p : method_address_insns_) { 104755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 104849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[2]; 104949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 105049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3])); 105155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 105255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 105355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 1054f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko patches_.push_back(LinkerPatch::MethodPatch(patch_offset, 1055f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko target_dex_file, target_method_idx)); 105655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 105755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 105855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for class types. 1059e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (LIR* p : class_type_address_insns_) { 106055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 1061e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih 1062e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih const DexFile* class_dex_file = 1063e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3])); 1064f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko uint32_t target_type_idx = p->operands[2]; 106555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 106655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 106755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 1068f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko patches_.push_back(LinkerPatch::TypePatch(patch_offset, 1069f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko class_dex_file, target_type_idx)); 107055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 107155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 107255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And now the PC-relative calls to methods. 1073f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko patches_.reserve(call_method_insns_.size()); 1074e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko for (LIR* p : call_method_insns_) { 107555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86CallI); 107649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[1]; 107749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 107849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2])); 107955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 108055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 108155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 1082f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko patches_.push_back(LinkerPatch::RelativeCodePatch(patch_offset, 1083f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko target_dex_file, target_method_idx)); 108455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 108555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 108655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And do the normal processing. 108755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell Mir2Lir::InstallLiteralPools(); 108855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 108955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 109070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolovbool X86Mir2Lir::GenInlinedArrayCopyCharArray(CallInfo* info) { 109170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_src = info->args[0]; 109270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_srcPos = info->args[1]; 109370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_dst = info->args[2]; 109470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_dstPos = info->args[3]; 109570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_length = info->args[4]; 109670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (rl_srcPos.is_const && (mir_graph_->ConstantValue(rl_srcPos) < 0)) { 109770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov return false; 109870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 109970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (rl_dstPos.is_const && (mir_graph_->ConstantValue(rl_dstPos) < 0)) { 110070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov return false; 110170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 110270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov ClobberCallerSave(); 11035a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LockCallTemps(); // Using fixed registers. 11045a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov RegStorage tmp_reg = cu_->target64 ? rs_r11 : rs_rBX; 11055a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_src, rs_rAX); 11065a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dst, rs_rCX); 11075a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* src_dst_same = OpCmpBranch(kCondEq, rs_rAX, rs_rCX, nullptr); 11085a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* src_null_branch = OpCmpImmBranch(kCondEq, rs_rAX, 0, nullptr); 11095a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* dst_null_branch = OpCmpImmBranch(kCondEq, rs_rCX, 0, nullptr); 11105a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_length, rs_rDX); 11115a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // If the length of the copy is > 128 characters (256 bytes) or negative then go slow path. 11125a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* len_too_big = OpCmpImmBranch(kCondHi, rs_rDX, 128, nullptr); 11135a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_src, rs_rAX); 11145a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadWordDisp(rs_rAX, mirror::Array::LengthOffset().Int32Value(), rs_rAX); 111570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* src_bad_len = nullptr; 1116f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate LIR* src_bad_off = nullptr; 111770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* srcPos_negative = nullptr; 111870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (!rl_srcPos.is_const) { 11195a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_srcPos, tmp_reg); 11205a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov srcPos_negative = OpCmpImmBranch(kCondLt, tmp_reg, 0, nullptr); 1121f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // src_pos < src_len 1122f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_off = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr); 1123f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // src_len - src_pos < copy_len 1124f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate OpRegRegReg(kOpSub, tmp_reg, rs_rAX, tmp_reg); 1125f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr); 112670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 11275a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov int32_t pos_val = mir_graph_->ConstantValue(rl_srcPos.orig_sreg); 112870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (pos_val == 0) { 11295a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov src_bad_len = OpCmpBranch(kCondLt, rs_rAX, rs_rDX, nullptr); 113070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 1131f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // src_pos < src_len 1132f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_off = OpCmpImmBranch(kCondLt, rs_rAX, pos_val, nullptr); 1133f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // src_len - src_pos < copy_len 1134f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate OpRegRegImm(kOpSub, tmp_reg, rs_rAX, pos_val); 1135f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr); 113670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 113770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 113870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* dstPos_negative = nullptr; 113970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* dst_bad_len = nullptr; 1140f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate LIR* dst_bad_off = nullptr; 114170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadValueDirectFixed(rl_dst, rs_rAX); 114270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadWordDisp(rs_rAX, mirror::Array::LengthOffset().Int32Value(), rs_rAX); 114370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (!rl_dstPos.is_const) { 11445a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dstPos, tmp_reg); 11455a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov dstPos_negative = OpCmpImmBranch(kCondLt, tmp_reg, 0, nullptr); 1146f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // dst_pos < dst_len 1147f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_off = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr); 1148f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // dst_len - dst_pos < copy_len 1149f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate OpRegRegReg(kOpSub, tmp_reg, rs_rAX, tmp_reg); 1150f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr); 115170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 11525a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov int32_t pos_val = mir_graph_->ConstantValue(rl_dstPos.orig_sreg); 115370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (pos_val == 0) { 11545a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov dst_bad_len = OpCmpBranch(kCondLt, rs_rAX, rs_rDX, nullptr); 115570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 1156f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // dst_pos < dst_len 1157f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_off = OpCmpImmBranch(kCondLt, rs_rAX, pos_val, nullptr); 1158f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate // dst_len - dst_pos < copy_len 1159f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate OpRegRegImm(kOpSub, tmp_reg, rs_rAX, pos_val); 1160f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_len = OpCmpBranch(kCondLt, tmp_reg, rs_rDX, nullptr); 116170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 116270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 11635a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // Everything is checked now. 11645a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_src, rs_rAX); 11655a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dst, tmp_reg); 11665a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_srcPos, rs_rCX); 116770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov NewLIR5(kX86Lea32RA, rs_rAX.GetReg(), rs_rAX.GetReg(), 11685a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov rs_rCX.GetReg(), 1, mirror::Array::DataOffset(2).Int32Value()); 11695a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // RAX now holds the address of the first src element to be copied. 117070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 11715a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dstPos, rs_rCX); 11725a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov NewLIR5(kX86Lea32RA, tmp_reg.GetReg(), tmp_reg.GetReg(), 11735a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov rs_rCX.GetReg(), 1, mirror::Array::DataOffset(2).Int32Value() ); 11745a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // RBX now holds the address of the first dst element to be copied. 117570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 11765a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // Check if the number of elements to be copied is odd or even. If odd 117770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov // then copy the first element (so that the remaining number of elements 117870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov // is even). 11795a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_length, rs_rCX); 118070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpRegImm(kOpAnd, rs_rCX, 1); 118170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* jmp_to_begin_loop = OpCmpImmBranch(kCondEq, rs_rCX, 0, nullptr); 118270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpRegImm(kOpSub, rs_rDX, 1); 118370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadBaseIndexedDisp(rs_rAX, rs_rDX, 1, 0, rs_rCX, kSignedHalf); 11845a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov StoreBaseIndexedDisp(tmp_reg, rs_rDX, 1, 0, rs_rCX, kSignedHalf); 118570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 11865a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // Since the remaining number of elements is even, we will copy by 118770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov // two elements at a time. 11885a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* beginLoop = NewLIR0(kPseudoTargetLabel); 11895a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* jmp_to_ret = OpCmpImmBranch(kCondEq, rs_rDX, 0, nullptr); 119070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpRegImm(kOpSub, rs_rDX, 2); 119170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadBaseIndexedDisp(rs_rAX, rs_rDX, 1, 0, rs_rCX, kSingle); 11925a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov StoreBaseIndexedDisp(tmp_reg, rs_rDX, 1, 0, rs_rCX, kSingle); 119370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpUnconditionalBranch(beginLoop); 119470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR *check_failed = NewLIR0(kPseudoTargetLabel); 119570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* launchpad_branch = OpUnconditionalBranch(nullptr); 119670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR *return_point = NewLIR0(kPseudoTargetLabel); 119770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov jmp_to_ret->target = return_point; 119870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov jmp_to_begin_loop->target = beginLoop; 119970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov src_dst_same->target = check_failed; 120070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov len_too_big->target = check_failed; 120170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov src_null_branch->target = check_failed; 120270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (srcPos_negative != nullptr) 120370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov srcPos_negative ->target = check_failed; 1204f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate if (src_bad_off != nullptr) 1205f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate src_bad_off->target = check_failed; 120670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (src_bad_len != nullptr) 120770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov src_bad_len->target = check_failed; 120870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov dst_null_branch->target = check_failed; 120970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (dstPos_negative != nullptr) 121070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov dstPos_negative->target = check_failed; 1211f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate if (dst_bad_off != nullptr) 1212f9f0ed401f7fe4138a71b36719423b908a3b7bfbavignate dst_bad_off->target = check_failed; 121370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (dst_bad_len != nullptr) 121470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov dst_bad_len->target = check_failed; 121570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov AddIntrinsicSlowPath(info, launchpad_branch, return_point); 12169863daf4fdc1a08339edac794452dbc719aef4f1Serguei Katkov ClobberCallerSave(); // We must clobber everything because slow path will return here 121770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov return true; 121870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov} 121970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 122070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 12214028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell/* 12224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * Fast string.index_of(I) & (II). Inline check for simple case of char <= 0xffff, 12234028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * otherwise bails to standard library code. 12244028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell */ 12254028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendellbool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { 12264028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_obj = info->args[0]; 12274028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_char = info->args[1]; 1228a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee RegLocation rl_start; // Note: only present in III flavor or IndexOf. 12298bd698fb785b58302be684efcbb24a0b8c6535d7nikolay serdjuk // RBX is promotable in 64-bit mode. 1230c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk RegStorage rs_tmp = cu_->target64 ? rs_r11 : rs_rBX; 1231c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk int start_value = -1; 12324028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12334028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell uint32_t char_value = 12344028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell rl_char.is_const ? mir_graph_->ConstantValue(rl_char.orig_sreg) : 0; 12354028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12364028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (char_value > 0xFFFF) { 12374028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to punt to the real String.indexOf. 12384028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return false; 12394028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 12404028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12414028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Okay, we are commited to inlining this. 1242c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EAX: 16 bit character being searched. 1243c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // ECX: count: number of words to be searched. 1244c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EDI: String being searched. 1245c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EDX: temporary during execution. 1246c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EBX or R11: temporary during execution (depending on mode). 1247c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // REP SCASW: search instruction. 1248c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 12498bd698fb785b58302be684efcbb24a0b8c6535d7nikolay serdjuk FlushAllRegs(); 1250c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1251a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee RegLocation rl_return = GetReturn(kCoreReg); 12524028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_dest = InlineTarget(info); 12534028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12544028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the string non-NULL? 12552700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_obj, rs_rDX); 12562700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee GenNullCheck(rs_rDX, info->opt_flags); 12573bc8615332b7848dec8c2297a40f7e4d176c0efbVladimir Marko info->opt_flags |= MIR_IGNORE_NULL_CHECK; // Record that we've null checked. 12584028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 1259c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk LIR *slowpath_branch = nullptr, *length_compare = nullptr; 1260c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1261c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We need the value in EAX. 12624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_char.is_const) { 12632700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rs_rAX, char_value); 12644028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1265c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Does the character fit in 16 bits? Compare it at runtime. 12662700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_char, rs_rAX); 12673a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang slowpath_branch = OpCmpImmBranch(kCondGt, rs_rAX, 0xFFFF, nullptr); 12684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 12694028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12704028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // From here down, we know that we are looking for a char that fits in 16 bits. 1271e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of reference to data array within the String object. 1272e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int value_offset = mirror::String::ValueOffset().Int32Value(); 1273e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of count within the String object. 1274e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int count_offset = mirror::String::CountOffset().Int32Value(); 1275e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Starting offset within data array. 1276e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int offset_offset = mirror::String::OffsetOffset().Int32Value(); 1277e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Start of char data with array_. 1278e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); 12794028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 128069dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // Compute the number of words to search in to rCX. 128169dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison Load32Disp(rs_rDX, count_offset, rs_rCX); 128269dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison 1283dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // Possible signal here due to null pointer dereference. 1284dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // Note that the signal handler will expect the top word of 1285dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // the stack to be the ArtMethod*. If the PUSH edi instruction 1286dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // below is ahead of the load above then this will not be true 1287dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // and the signal handler will not work. 1288dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison MarkPossibleNullPointerException(0); 1289c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1290dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison if (!cu_->target64) { 12918bd698fb785b58302be684efcbb24a0b8c6535d7nikolay serdjuk // EDI is promotable in 32-bit mode. 1292c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk NewLIR1(kX86Push32R, rs_rDI.GetReg()); 1293c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk } 12944028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12954028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (zero_based) { 1296c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Start index is not present. 12974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to handle an empty string. Use special instruction JECXZ. 12984028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare = NewLIR0(kX86Jecxz8); 1299c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1300c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Copy the number of words to search in a temporary register. 1301c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We will use the register at the end to calculate result. 1302c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpMov, rs_tmp, rs_rCX); 13034028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1304c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Start index is present. 1305a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee rl_start = info->args[2]; 1306c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 13074028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to offset by the start index. 13084028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_start.is_const) { 13094028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = mir_graph_->ConstantValue(rl_start.orig_sreg); 13104028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = std::max(start_value, 0); 13114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13124028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the start > count? 13132700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee length_compare = OpCmpImmBranch(kCondLe, rs_rCX, start_value, nullptr); 1314c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegImm(kOpMov, rs_rDI, start_value); 1315c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1316c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Copy the number of words to search in a temporary register. 1317c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We will use the register at the end to calculate result. 1318c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpMov, rs_tmp, rs_rCX); 13194028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13204028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (start_value != 0) { 1321c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Decrease the number of words to search by the start index. 13222700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegImm(kOpSub, rs_rCX, start_value); 13234028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13244028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1325c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Handle "start index < 0" case. 1326c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk if (!cu_->target64 && rl_start.location != kLocPhysReg) { 1327a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Load the start index from stack, remembering that we pushed EDI. 1328c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk int displacement = SRegOffset(rl_start.s_reg_low) + sizeof(uint32_t); 132974de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 133074de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko Load32Disp(rs_rX86_SP, displacement, rs_rDI); 133174de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko // Dalvik register annotation in LoadBaseIndexedDisp() used wrong offset. Fix it. 133274de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko DCHECK(!DECODE_ALIAS_INFO_WIDE(last_lir_insn_->flags.alias_info)); 133374de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko int reg_id = DECODE_ALIAS_INFO_REG(last_lir_insn_->flags.alias_info) - 1; 133474de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko AnnotateDalvikRegAccess(last_lir_insn_, reg_id, true, false); 1335c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk } else { 1336c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk LoadValueDirectFixed(rl_start, rs_rDI); 13374028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 1338c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpXor, rs_tmp, rs_tmp); 1339c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpCmp, rs_rDI, rs_tmp); 1340c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpCondRegReg(kOpCmov, kCondLt, rs_rDI, rs_tmp); 1341c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1342c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // The length of the string should be greater than the start index. 1343c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk length_compare = OpCmpBranch(kCondLe, rs_rCX, rs_rDI, nullptr); 1344c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1345c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Copy the number of words to search in a temporary register. 1346c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We will use the register at the end to calculate result. 1347c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpMov, rs_tmp, rs_rCX); 1348c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1349c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Decrease the number of words to search by the start index. 1350c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpSub, rs_rCX, rs_rDI); 13514028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13524028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13534028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 1354c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Load the address of the string into EDI. 1355c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // In case of start index we have to add the address to existing value in EDI. 1356e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET. 1357c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk if (zero_based || (!zero_based && rl_start.is_const && start_value == 0)) { 1358c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk Load32Disp(rs_rDX, offset_offset, rs_rDI); 13594028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1360c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegMem(kOpAdd, rs_rDI, rs_rDX, offset_offset); 13614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 1362c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegImm(kOpLsl, rs_rDI, 1); 1363c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegMem(kOpAdd, rs_rDI, rs_rDX, value_offset); 1364c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegImm(kOpAdd, rs_rDI, data_offset); 13654028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13664028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EDI now contains the start of the string to be searched. 13674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We are all prepared to do the search for the character. 13684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell NewLIR0(kX86RepneScasw); 13694028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13704028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Did we find a match? 13714028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR* failed_branch = OpCondBranch(kCondNe, nullptr); 13724028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13734028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // yes, we matched. Compute the index of the result. 1374c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpSub, rs_tmp, rs_rCX); 1375c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rs_tmp.GetReg(), -1); 1376c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 13774028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *all_done = NewLIR1(kX86Jmp8, 0); 13784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13794028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Failed to match; return -1. 13804028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *not_found = NewLIR0(kPseudoTargetLabel); 13814028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare->target = not_found; 13824028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell failed_branch->target = not_found; 13832700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rl_return.reg, -1); 13844028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13854028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // And join up at the end. 13864028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell all_done->target = NewLIR0(kPseudoTargetLabel); 1387c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1388c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk if (!cu_->target64) 1389c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk NewLIR1(kX86Pop32R, rs_rDI.GetReg()); 13904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13914028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Out of line code returns here. 13923a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang if (slowpath_branch != nullptr) { 13934028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *return_point = NewLIR0(kPseudoTargetLabel); 13943a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang AddIntrinsicSlowPath(info, slowpath_branch, return_point); 13959863daf4fdc1a08339edac794452dbc719aef4f1Serguei Katkov ClobberCallerSave(); // We must clobber everything because slow path will return here 13964028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13984028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell StoreValue(rl_dest, rl_return); 13994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return true; 14004028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell} 14014028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 140235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shenstatic bool ARTRegIDToDWARFRegID(bool is_x86_64, int art_reg_id, int* dwarf_reg_id) { 140335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen if (is_x86_64) { 140435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen switch (art_reg_id) { 1405bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 3 : *dwarf_reg_id = 3; return true; // %rbx 140635e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // This is the only discrepancy between ART & DWARF register numbering. 1407bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 5 : *dwarf_reg_id = 6; return true; // %rbp 1408bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 12: *dwarf_reg_id = 12; return true; // %r12 1409bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 13: *dwarf_reg_id = 13; return true; // %r13 1410bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 14: *dwarf_reg_id = 14; return true; // %r14 1411bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 15: *dwarf_reg_id = 15; return true; // %r15 1412bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe default: return false; // Should not get here 141335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 141435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } else { 141535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen switch (art_reg_id) { 1416bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 5: *dwarf_reg_id = 5; return true; // %ebp 1417bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 6: *dwarf_reg_id = 6; return true; // %esi 1418bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 7: *dwarf_reg_id = 7; return true; // %edi 1419bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe default: return false; // Should not get here 142035e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 1421ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1422ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1423ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1424547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shenstd::vector<uint8_t>* X86Mir2Lir::ReturnFrameDescriptionEntry() { 1425547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen std::vector<uint8_t>* cfi_info = new std::vector<uint8_t>; 1426ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1427ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Generate the FDE for the method. 1428ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell DCHECK_NE(data_offset_, 0U); 1429ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1430e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban WriteFDEHeader(cfi_info, cu_->target64); 1431e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban WriteFDEAddressRange(cfi_info, data_offset_, cu_->target64); 143235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 1433ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // The instructions in the FDE. 1434ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_decrement_ != nullptr) { 1435ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Advance LOC to just past the stack decrement. 1436ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t pc = NEXT_LIR(stack_decrement_)->offset; 1437547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, pc); 1438ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1439ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Now update the offset to the call frame: DW_CFA_def_cfa_offset frame_size. 1440547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_def_cfa_offset(cfi_info, frame_size_); 1441ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 144235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // Handle register spills 144335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen const uint32_t kSpillInstLen = (cu_->target64) ? 5 : 4; 144435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen const int kDataAlignmentFactor = (cu_->target64) ? -8 : -4; 144535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 144635e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen int offset = -(GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 144735e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen for (int reg = 0; mask; mask >>= 1, reg++) { 144835e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen if (mask & 0x1) { 144935e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen pc += kSpillInstLen; 145035e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 145135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // Advance LOC to pass this instruction 1452547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, kSpillInstLen); 145335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 145435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen int dwarf_reg_id; 145535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen if (ARTRegIDToDWARFRegID(cu_->target64, reg, &dwarf_reg_id)) { 1456547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen // DW_CFA_offset_extended_sf reg offset 1457547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_offset_extended_sf(cfi_info, dwarf_reg_id, offset / kDataAlignmentFactor); 145835e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 145935e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 146035e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen offset += GetInstructionSetPointerSize(cu_->instruction_set); 146135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 146235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 146335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 1464ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We continue with that stack until the epilogue. 1465ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_increment_ != nullptr) { 1466ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t new_pc = NEXT_LIR(stack_increment_)->offset; 1467547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, new_pc - pc); 1468ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1469ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We probably have code snippets after the epilogue, so save the 1470ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // current state: DW_CFA_remember_state. 1471547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_remember_state(cfi_info); 1472ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 147335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // We have now popped the stack: DW_CFA_def_cfa_offset 4/8. 147435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // There is only the return PC on the stack now. 1475547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_def_cfa_offset(cfi_info, GetInstructionSetPointerSize(cu_->instruction_set)); 1476ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1477ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Everything after that is the same as before the epilogue. 1478ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Stack bump was followed by RET instruction. 1479ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell LIR *post_ret_insn = NEXT_LIR(NEXT_LIR(stack_increment_)); 1480ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (post_ret_insn != nullptr) { 1481ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell pc = new_pc; 1482ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell new_pc = post_ret_insn->offset; 1483547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, new_pc - pc); 1484ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Restore the state: DW_CFA_restore_state. 1485547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_restore_state(cfi_info); 1486ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1487ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1488ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1489ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1490547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PadCFI(cfi_info); 1491e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban WriteCFILength(cfi_info, cu_->target64); 1492ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1493ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell return cfi_info; 1494ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1495ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1496d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) { 1497d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 149860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpReserveVectorRegisters: 149960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji ReserveVectorRegisters(mir); 150060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 150160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpReturnVectorRegisters: 1502b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A ReturnVectorRegisters(mir); 150360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 1504d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell case kMirOpConstVector: 15056a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenConst128(mir); 1506d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell break; 1507fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpMoveVector: 15086a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenMoveVector(mir); 1509fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1510fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedMultiply: 15116a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenMultiplyVector(mir); 1512fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1513fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedAddition: 15146a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenAddVector(mir); 1515fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1516fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedSubtract: 15176a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenSubtractVector(mir); 1518fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1519fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedShiftLeft: 15206a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenShiftLeftVector(mir); 1521fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1522fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedSignedShiftRight: 15236a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenSignedShiftRightVector(mir); 1524fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1525fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedUnsignedShiftRight: 15266a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenUnsignedShiftRightVector(mir); 1527fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1528fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedAnd: 15296a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenAndVector(mir); 1530fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1531fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedOr: 15326a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenOrVector(mir); 1533fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1534fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedXor: 15356a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenXorVector(mir); 1536fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1537fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedAddReduce: 15386a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenAddReduceVector(mir); 1539fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1540fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedReduce: 15416a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenReduceVector(mir); 1542fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1543fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedSet: 15446a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenSetVector(mir); 1545fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1546b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler case kMirOpMemBarrier: 1547b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler GenMemBarrier(static_cast<MemBarrierKind>(mir->dalvikInsn.vA)); 1548b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler break; 1549b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kMirOpPackedArrayGet: 1550b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenPackedArrayGet(bb, mir); 1551b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1552b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kMirOpPackedArrayPut: 1553b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenPackedArrayPut(bb, mir); 1554b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1555d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell default: 1556d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell break; 1557d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1558d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1559d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 156060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::ReserveVectorRegisters(MIR* mir) { 1561b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (uint32_t i = mir->dalvikInsn.vA; i <= mir->dalvikInsn.vB; i++) { 156260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage xp_reg = RegStorage::Solo128(i); 156360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegisterInfo *xp_reg_info = GetRegInfo(xp_reg); 156460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji Clobber(xp_reg); 156560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 156660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji for (RegisterInfo *info = xp_reg_info->GetAliasChain(); 156760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info != nullptr; 156860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info = info->GetAliasChain()) { 1569e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko ArenaVector<RegisterInfo*>* regs = 1570e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko info->GetReg().IsSingle() ? ®_pool_->sp_regs_ : ®_pool_->dp_regs_; 1571e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko auto it = std::find(regs->begin(), regs->end(), info); 1572e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko DCHECK(it != regs->end()); 1573e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko regs->erase(it); 157460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 157560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 157660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 157760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1578b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::ReturnVectorRegisters(MIR* mir) { 1579b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (uint32_t i = mir->dalvikInsn.vA; i <= mir->dalvikInsn.vB; i++) { 158060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage xp_reg = RegStorage::Solo128(i); 158160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegisterInfo *xp_reg_info = GetRegInfo(xp_reg); 158260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 158360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji for (RegisterInfo *info = xp_reg_info->GetAliasChain(); 158460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info != nullptr; 158560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info = info->GetAliasChain()) { 158660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji if (info->GetReg().IsSingle()) { 1587e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reg_pool_->sp_regs_.push_back(info); 158860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 1589e39c54ea575ec710d5e84277fcdcc049f8acb3c9Vladimir Marko reg_pool_->dp_regs_.push_back(info); 159060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 159160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 159260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 159360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 159460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 15956a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenConst128(MIR* mir) { 159660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA); 1597b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest); 1598b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1599d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell uint32_t *args = mir->dalvikInsn.arg; 1600fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int reg = rs_dest.GetReg(); 1601d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Check for all 0 case. 1602d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (args[0] == 0 && args[1] == 0 && args[2] == 0 && args[3] == 0) { 1603d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell NewLIR2(kX86XorpsRR, reg, reg); 1604d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return; 1605d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 160660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 160760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Append the mov const vector to reg opcode. 1608b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AppendOpcodeWithConst(kX86MovdqaRM, reg, mir); 160960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 161060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 161160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::AppendOpcodeWithConst(X86OpCode opcode, int reg, MIR* mir) { 1612b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // The literal pool needs position independent logic. 1613b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A store_method_addr_used_ = true; 1614b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1615b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // To deal with correct memory ordering, reverse order of constants. 1616b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int32_t constants[4]; 1617b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[3] = mir->dalvikInsn.arg[0]; 1618b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[2] = mir->dalvikInsn.arg[1]; 1619b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[1] = mir->dalvikInsn.arg[2]; 1620b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[0] = mir->dalvikInsn.arg[3]; 1621b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1622b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Search if there is already a constant in pool with this value. 1623b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LIR *data_target = ScanVectorLiteral(constants); 1624d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (data_target == nullptr) { 1625b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A data_target = AddVectorLiteral(constants); 1626d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1627d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1628d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Address the start of the method. 1629d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low); 1630e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu if (rl_method.wide) { 1631e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu rl_method = LoadValueWide(rl_method, kCoreReg); 1632e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } else { 1633e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu rl_method = LoadValue(rl_method, kCoreReg); 1634e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } 1635d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1636d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Load the proper value from the literal area. 1637d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // We don't know the proper offset for the value, so pick one that will force 1638d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // 4 byte offset. We will fix this up in the assembler later to have the right 1639d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // value. 16408dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral); 1641b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LIR *load = NewLIR3(opcode, reg, rl_method.reg.GetReg(), 256 /* bogus */); 1642d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell load->flags.fixup = kFixupLoad; 1643d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell load->target = data_target; 1644d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1645d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 16466a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenMoveVector(MIR* mir) { 1647fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 164860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 164960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA); 1650b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest); 165160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src = RegStorage::Solo128(mir->dalvikInsn.vB); 1652b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_dest.GetReg(), rs_src.GetReg()); 1653fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1654fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1655b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::GenMultiplyVectorSignedByte(RegStorage rs_dest_src1, RegStorage rs_src2) { 165660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji /* 165760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * Emulate the behavior of a kSignedByte by separating out the 16 values in the two XMM 165860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * and multiplying 8 at a time before recombining back into one XMM register. 165960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * 166060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * let xmm1, xmm2 be real srcs (keep low bits of 16bit lanes) 166160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm3 is tmp (operate on high bits of 16bit lanes) 166260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * 166360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm3 = xmm1 166460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm1 = xmm1 .* xmm2 166560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm1 = xmm1 & 0x00ff00ff00ff00ff00ff00ff00ff00ff // xmm1 now has low bits 166660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm3 = xmm3 .>> 8 166760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm2 = xmm2 & 0xff00ff00ff00ff00ff00ff00ff00ff00 166860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm2 = xmm2 .* xmm3 // xmm2 now has high bits 166960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm1 = xmm1 | xmm2 // combine results 167060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji */ 167160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 167260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Copy xmm1. 1673b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_src1_high_tmp = Get128BitRegister(AllocTempDouble()); 1674b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_dest_high_tmp = Get128BitRegister(AllocTempDouble()); 1675b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_src1_high_tmp.GetReg(), rs_src2.GetReg()); 1676b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_dest_high_tmp.GetReg(), rs_dest_src1.GetReg()); 167760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 167860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Multiply low bits. 1679b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // x7 *= x3 168060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji NewLIR2(kX86PmullwRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 168160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 168260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // xmm1 now has low bits. 168360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji AndMaskVectorRegister(rs_dest_src1, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF); 168460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 168560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Prepare high bits for multiplication. 1686b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlwRI, rs_src1_high_tmp.GetReg(), 0x8); 1687b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AndMaskVectorRegister(rs_dest_high_tmp, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00); 168860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 168960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Multiply high bits and xmm2 now has high bits. 1690b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmullwRR, rs_src1_high_tmp.GetReg(), rs_dest_high_tmp.GetReg()); 169160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 169260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Combine back into dest XMM register. 1693b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_src1_high_tmp.GetReg()); 1694b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A} 1695b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1696b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::GenMultiplyVectorLong(RegStorage rs_dest_src1, RegStorage rs_src2) { 1697b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 1698b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * We need to emulate the packed long multiply. 1699b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * For kMirOpPackedMultiply xmm1, xmm0: 1700b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - xmm1 is src/dest 1701b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - xmm0 is src 1702b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Get xmm2 and xmm3 as temp 1703b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Idea is to multiply the lower 32 of each operand with the higher 32 of the other. 1704b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Then add the two results. 1705b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Move it to the upper 32 of the destination 1706b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Then multiply the lower 32-bits of the operands and add the result to the destination. 1707b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1708b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * (op dest src ) 1709b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * movdqa %xmm2, %xmm1 1710b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * movdqa %xmm3, %xmm0 1711b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psrlq %xmm3, $0x20 1712b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm3, %xmm2 1713b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psrlq %xmm1, $0x20 1714b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm1, %xmm0 1715b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm3 1716b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psllq %xmm1, $0x20 1717b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm2, %xmm0 1718b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm2 1719b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1720b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * When both the operands are the same, then we need to calculate the lower-32 * higher-32 1721b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * calculation only once. Thus we don't need the xmm3 temp above. That sequence becomes: 1722b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1723b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * (op dest src ) 1724b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * movdqa %xmm2, %xmm1 1725b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psrlq %xmm1, $0x20 1726b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm1, %xmm0 1727b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm1 1728b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psllq %xmm1, $0x20 1729b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm2, %xmm0 1730b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm2 1731b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1732b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 1733b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1734b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bool both_operands_same = (rs_dest_src1.GetReg() == rs_src2.GetReg()); 1735b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1736b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector_1; 1737b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector_2; 1738b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rs_tmp_vector_1 = Get128BitRegister(AllocTempDouble()); 1739b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector_1.GetReg(), rs_dest_src1.GetReg()); 1740b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1741b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (both_operands_same == false) { 1742b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rs_tmp_vector_2 = Get128BitRegister(AllocTempDouble()); 1743b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector_2.GetReg(), rs_src2.GetReg()); 1744b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, rs_tmp_vector_2.GetReg(), 0x20); 1745b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmuludqRR, rs_tmp_vector_2.GetReg(), rs_tmp_vector_1.GetReg()); 1746b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 1747b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1748b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, rs_dest_src1.GetReg(), 0x20); 1749b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmuludqRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1750b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1751b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (both_operands_same == false) { 1752b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, rs_dest_src1.GetReg(), rs_tmp_vector_2.GetReg()); 1753b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 1754b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, rs_dest_src1.GetReg(), rs_dest_src1.GetReg()); 1755b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 1756b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1757b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsllqRI, rs_dest_src1.GetReg(), 0x20); 1758b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmuludqRR, rs_tmp_vector_1.GetReg(), rs_src2.GetReg()); 1759b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, rs_dest_src1.GetReg(), rs_tmp_vector_1.GetReg()); 176060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 176160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 17626a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenMultiplyVector(MIR* mir) { 176360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 176460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 176560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1766b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 176760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1768fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1769fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1770fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1771fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PmulldRR; 1772fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1773fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1774fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PmullwRR; 1775fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1776fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSingle: 1777fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86MulpsRR; 1778fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1779fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kDouble: 1780fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86MulpdRR; 1781fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 178260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 178360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // HW doesn't support 16x16 byte multiplication so emulate it. 1784b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenMultiplyVectorSignedByte(rs_dest_src1, rs_src2); 1785b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 1786b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1787b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenMultiplyVectorLong(rs_dest_src1, rs_src2); 178860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1789fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1790fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector multiply " << opsize; 1791fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1792fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1793fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1794fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1795fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 17966a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenAddVector(MIR* mir) { 179760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 179860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 179960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1800b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 180160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1802fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1803fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1804fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1805fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PadddRR; 1806fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1807b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1808b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A opcode = kX86PaddqRR; 1809b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1810fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1811fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1812fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PaddwRR; 1813fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1814fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedByte: 1815fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedByte: 1816fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PaddbRR; 1817fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1818fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSingle: 1819fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86AddpsRR; 1820fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1821fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kDouble: 1822fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86AddpdRR; 1823fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1824fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1825fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector addition " << opsize; 1826fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1827fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1828fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1829fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1830fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 18316a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenSubtractVector(MIR* mir) { 183260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 183360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 183460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1835b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 183660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1837fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1838fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1839fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1840fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsubdRR; 1841fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1842b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1843b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A opcode = kX86PsubqRR; 1844b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1845fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1846fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1847fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsubwRR; 1848fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1849fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedByte: 1850fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedByte: 1851fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsubbRR; 1852fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1853fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSingle: 1854fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86SubpsRR; 1855fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1856fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kDouble: 1857fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86SubpdRR; 1858fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1859fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1860fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector subtraction " << opsize; 1861fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1862fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1863fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1864fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1865fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 18666a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenShiftByteVector(MIR* mir) { 1867b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Destination does not need clobbered because it has already been as part 1868b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // of the general packed shift handler (caller of this method). 186960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 187060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 187160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int opcode = 0; 187260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 187360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpPackedShiftLeft: 187460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji opcode = kX86PsllwRI; 187560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 187660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpPackedSignedShiftRight: 187760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpPackedUnsignedShiftRight: 1878b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Add support for emulated byte shifts. 187960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji default: 188060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji LOG(FATAL) << "Unsupported shift operation on byte vector " << opcode; 188160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 188260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 188360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1884b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Clear xmm register and return if shift more than byte length. 1885b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int imm = mir->dalvikInsn.vB; 1886b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (imm >= 8) { 1887b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PxorRR, rs_dest_src1.GetReg(), rs_dest_src1.GetReg()); 1888b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 1889b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 189060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 189160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Shift lower values. 189260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 189360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1894b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 1895b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * The above shift will shift the whole word, but that means 1896b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * both the bytes will shift as well. To emulate a byte level 1897b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * shift, we can just throw away the lower (8 - N) bits of the 1898b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * upper byte, and we are done. 1899b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 1900b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A uint8_t byte_mask = 0xFF << imm; 1901b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A uint32_t int_mask = byte_mask; 1902b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int_mask = int_mask << 8 | byte_mask; 1903b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int_mask = int_mask << 8 | byte_mask; 1904b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int_mask = int_mask << 8 | byte_mask; 190560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1906b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // And the destination with the mask 1907b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AndMaskVectorRegister(rs_dest_src1, int_mask, int_mask, int_mask, int_mask); 190860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 190960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 19106a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenShiftLeftVector(MIR* mir) { 191160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 191260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 191360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1914b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 191560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int imm = mir->dalvikInsn.vB; 1916fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1917fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1918fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1919fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PslldRI; 1920fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1921fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k64: 1922fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsllqRI; 1923fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1924fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1925fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1926fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsllwRI; 1927fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 192860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 192960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 19306a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenShiftByteVector(mir); 193160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1932fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1933fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector shift left " << opsize; 1934fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1935fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1936fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1937fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1938fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 19396a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenSignedShiftRightVector(MIR* mir) { 194060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 194160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 194260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1943b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 194460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int imm = mir->dalvikInsn.vB; 1945fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1946fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1947fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1948fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsradRI; 1949fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1950fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1951fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1952fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrawRI; 1953fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 195460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 195560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 19566a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenShiftByteVector(mir); 195760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1958b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1959b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Implement emulated shift algorithm. 1960fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1961fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector signed shift right " << opsize; 19626a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 1963fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1964fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1965fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1966fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 19676a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenUnsignedShiftRightVector(MIR* mir) { 196860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 196960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 197060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1971b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 197260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int imm = mir->dalvikInsn.vB; 1973fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1974fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1975fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1976fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrldRI; 1977fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1978fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k64: 1979fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrlqRI; 1980fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1981fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1982fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1983fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrlwRI; 1984fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 198560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 198660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 19876a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers GenShiftByteVector(mir); 198860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1989fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1990fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector unsigned shift right " << opsize; 1991fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1992fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1993fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1994fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1995fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 19966a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenAndVector(MIR* mir) { 1997fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 199860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 199960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 2000b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 200160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 2002fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(kX86PandRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 2003fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2004fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 20056a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenOrVector(MIR* mir) { 2006fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 200760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 200860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 2009b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 201060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 2011fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 2012fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2013fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 20146a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenXorVector(MIR* mir) { 2015fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 201660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 201760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 2018b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 201960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 2020fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(kX86PxorRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 2021fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2022fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 202360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::AndMaskVectorRegister(RegStorage rs_src1, uint32_t m1, uint32_t m2, uint32_t m3, uint32_t m4) { 202460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji MaskVectorRegister(kX86PandRM, rs_src1, m1, m2, m3, m4); 202560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 202660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 202760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::MaskVectorRegister(X86OpCode opcode, RegStorage rs_src1, uint32_t m0, uint32_t m1, uint32_t m2, uint32_t m3) { 202860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Create temporary MIR as container for 128-bit binary mask. 202960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji MIR const_mir; 203060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji MIR* const_mirp = &const_mir; 203160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpConstVector); 203260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[0] = m0; 203360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[1] = m1; 203460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[2] = m2; 203560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[3] = m3; 203660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 203760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Mask vector with const from literal pool. 203860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji AppendOpcodeWithConst(opcode, rs_src1.GetReg(), const_mirp); 203960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 204060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 20416a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenAddReduceVector(MIR* mir) { 204260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 2043b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage vector_src = RegStorage::Solo128(mir->dalvikInsn.vB); 2044b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bool is_wide = opsize == k64 || opsize == kDouble; 2045b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2046b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Get the location of the virtual register. Since this bytecode is overloaded 2047b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // for different types (and sizes), we need different logic for each path. 2048b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // The design of bytecode uses same VR for source and destination. 2049b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegLocation rl_src, rl_dest, rl_result; 2050b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (is_wide) { 2051b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrcWide(mir, 0); 2052b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_dest = mir_graph_->GetDestWide(mir); 2053b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2054b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrc(mir, 0); 2055b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_dest = mir_graph_->GetDest(mir); 2056b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 205760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2058b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // We need a temp for byte and short values 2059b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage temp; 206060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2061b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // There is a different path depending on type and size. 2062b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSingle) { 2063b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle float case. 2064b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Add support for fast math (not value safe) and do horizontal add in that case. 206560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2066b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = LoadValue(rl_src, kFPReg); 2067b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLoc(rl_dest, kFPReg, true); 206860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2069b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Since we are doing an add-reduce, we move the reg holding the VR 2070b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // into the result so we include it in result. 2071b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A OpRegCopy(rl_result.reg, rl_src.reg); 2072b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 207360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2074b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Since FP must keep order of operation for value safety, we shift to low 2075b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // 32-bits and add to result. 2076b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (int i = 0; i < 3; i++) { 2077b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(kX86ShufpsRRI, vector_src.GetReg(), vector_src.GetReg(), 0x39); 2078b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 2079b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 208060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2081b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreValue(rl_dest, rl_result); 2082b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == kDouble) { 2083b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle double case. 2084b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = LoadValueWide(rl_src, kFPReg); 2085b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLocWide(rl_dest, kFPReg, true); 2086b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported vector add reduce for double."; 2087b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == k64) { 2088b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 2089b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * Handle long case: 2090b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1) Reduce the vector register to lower half (with addition). 2091b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-1) Get an xmm temp and fill it with vector register. 2092b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-2) Shift the xmm temp by 8-bytes. 2093b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-3) Add the xmm temp to vector register that is being reduced. 2094b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2) Allocate temp GP / GP pair. 2095b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-1) In 64-bit case, use movq to move result to a 64-bit GP. 2096b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-2) In 32-bit case, use movd twice to move to 32-bit GP pair. 2097b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 3) Finish the add reduction by doing what add-long/2addr does, 2098b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * but instead of having a VR as one of the sources, we have our temp GP. 2099b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 2100b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector = Get128BitRegister(AllocTempDouble()); 2101b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector.GetReg(), vector_src.GetReg()); 2102b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrldqRI, rs_tmp_vector.GetReg(), 8); 2103b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, vector_src.GetReg(), rs_tmp_vector.GetReg()); 2104b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A FreeTemp(rs_tmp_vector); 2105b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2106b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // We would like to be able to reuse the add-long implementation, so set up a fake 2107b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // register location to pass it. 2108b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegLocation temp_loc = mir_graph_->GetBadLoc(); 2109b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.core = 1; 2110b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.wide = 1; 2111b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.location = kLocPhysReg; 2112b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.reg = AllocTempWide(); 2113b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2114b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (cu_->target64) { 2115b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A DCHECK(!temp_loc.reg.IsPair()); 2116b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovqrxRR, temp_loc.reg.GetReg(), vector_src.GetReg()); 2117b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2118b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, temp_loc.reg.GetLowReg(), vector_src.GetReg()); 2119b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, vector_src.GetReg(), 0x20); 2120b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, temp_loc.reg.GetHighReg(), vector_src.GetReg()); 2121b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 212260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 21235c5676b26a08454b3f0133783778991bbe5dd681Razvan A Lupusoru GenArithOpLong(Instruction::ADD_LONG_2ADDR, rl_dest, temp_loc, temp_loc, mir->optimization_flags); 2124b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == kSignedByte || opsize == kUnsignedByte) { 2125b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp = Get128BitRegister(AllocTempDouble()); 2126b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PxorRR, rs_tmp.GetReg(), rs_tmp.GetReg()); 2127b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsadbwRR, vector_src.GetReg(), rs_tmp.GetReg()); 2128b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(kX86PshufdRRI, rs_tmp.GetReg(), vector_src.GetReg(), 0x4e); 2129b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddbRR, vector_src.GetReg(), rs_tmp.GetReg()); 2130b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Move to a GPR 2131b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp = AllocTemp(); 2132b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, temp.GetReg(), vector_src.GetReg()); 2133b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2134b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle and the int and short cases together 2135b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2136b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Initialize as if we were handling int case. Below we update 2137b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // the opcode if handling byte or short. 2138b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int vec_bytes = (mir->dalvikInsn.vC & 0xFFFF) / 8; 2139b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int vec_unit_size; 2140b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int horizontal_add_opcode; 2141b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int extract_opcode; 2142b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2143b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSignedHalf || opsize == kUnsignedHalf) { 2144b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A extract_opcode = kX86PextrwRRI; 2145b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A horizontal_add_opcode = kX86PhaddwRR; 2146b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A vec_unit_size = 2; 2147b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == k32) { 2148b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A vec_unit_size = 4; 2149b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A horizontal_add_opcode = kX86PhadddRR; 2150b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A extract_opcode = kX86PextrdRRI; 2151b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2152b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported vector add reduce " << opsize; 2153b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 215460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 215560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2156b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int elems = vec_bytes / vec_unit_size; 215760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2158b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A while (elems > 1) { 2159b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(horizontal_add_opcode, vector_src.GetReg(), vector_src.GetReg()); 2160b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A elems >>= 1; 2161b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 216260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2163b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle this as arithmetic unary case. 2164b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 216560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2166b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Extract to a GP register because this is integral typed. 2167b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp = AllocTemp(); 2168b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(extract_opcode, temp.GetReg(), vector_src.GetReg(), 0); 2169b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2170b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2171b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize != k64 && opsize != kSingle && opsize != kDouble) { 2172b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // The logic below looks very similar to the handling of ADD_INT_2ADDR 2173b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // except the rhs is not a VR but a physical register allocated above. 2174b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // No load of source VR is done because it assumes that rl_result will 2175b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // share physical register / memory location. 21766a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers rl_result = UpdateLocTyped(rl_dest); 2177b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (rl_result.location == kLocPhysReg) { 2178b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Ensure res is in a core reg. 2179b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLoc(rl_dest, kCoreReg, true); 2180b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A OpRegReg(kOpAdd, rl_result.reg, temp); 2181b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreFinalValue(rl_dest, rl_result); 2182b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2183b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Do the addition directly to memory. 2184b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A OpMemReg(kOpAdd, rl_result, temp.GetReg()); 2185b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2186b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2187fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2188fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 21896a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid X86Mir2Lir::GenReduceVector(MIR* mir) { 219060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 219160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegLocation rl_dest = mir_graph_->GetDest(mir); 2192b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage vector_src = RegStorage::Solo128(mir->dalvikInsn.vB); 219360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegLocation rl_result; 219460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji bool is_wide = false; 219560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2196b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // There is a different path depending on type and size. 2197b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSingle) { 2198b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle float case. 2199b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Add support for fast math (not value safe) and do horizontal add in that case. 2200fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2201b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLoc(rl_dest, kFPReg, true); 2202b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PxorRR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 2203b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 2204b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2205b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Since FP must keep order of operation for value safety, we shift to low 2206b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // 32-bits and add to result. 2207b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (int i = 0; i < 3; i++) { 2208b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(kX86ShufpsRRI, vector_src.GetReg(), vector_src.GetReg(), 0x39); 2209b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 2210b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2211b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2212b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreValue(rl_dest, rl_result); 2213b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == kDouble) { 2214b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Handle double case. 2215b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported add reduce for double."; 2216b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == k64) { 2217b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 2218b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * Handle long case: 2219b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1) Reduce the vector register to lower half (with addition). 2220b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-1) Get an xmm temp and fill it with vector register. 2221b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-2) Shift the xmm temp by 8-bytes. 2222b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-3) Add the xmm temp to vector register that is being reduced. 2223b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2) Evaluate destination to a GP / GP pair. 2224b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-1) In 64-bit case, use movq to move result to a 64-bit GP. 2225b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-2) In 32-bit case, use movd twice to move to 32-bit GP pair. 2226b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 3) Store the result to the final destination. 2227b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 222853cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji NewLIR2(kX86PsrldqRI, vector_src.GetReg(), 8); 2229b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLocWide(rl_dest, kCoreReg, true); 2230b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (cu_->target64) { 2231b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A DCHECK(!rl_result.reg.IsPair()); 2232b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovqrxRR, rl_result.reg.GetReg(), vector_src.GetReg()); 223360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 2234b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, rl_result.reg.GetLowReg(), vector_src.GetReg()); 2235b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, vector_src.GetReg(), 0x20); 2236b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, rl_result.reg.GetHighReg(), vector_src.GetReg()); 223760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 2238b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2239b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreValueWide(rl_dest, rl_result); 224060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 224153cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji int extract_index = mir->dalvikInsn.arg[0]; 224253cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji int extr_opcode = 0; 22436a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers rl_result = UpdateLocTyped(rl_dest); 224453cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji 2245b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle the rest of integral types now. 2246b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A switch (opsize) { 2247b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k32: 224853cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrdRRI : kX86PextrdMRI; 2249b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 2250b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kSignedHalf: 2251b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kUnsignedHalf: 225253cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrwRRI : kX86PextrwMRI; 225353cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji break; 225453cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji case kSignedByte: 225553cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrbRRI : kX86PextrbMRI; 2256b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 2257b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A default: 2258b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported vector reduce " << opsize; 22596a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 2260b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2261b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2262b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (rl_result.location == kLocPhysReg) { 2263b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(extr_opcode, rl_result.reg.GetReg(), vector_src.GetReg(), extract_index); 226453cec00aa6789382621a53b33b13f45bd27148caUdayan Banerji StoreFinalValue(rl_dest, rl_result); 2265b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2266b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int displacement = SRegOffset(rl_result.s_reg_low); 2267b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LIR *l = NewLIR3(extr_opcode, rs_rX86_SP.GetReg(), displacement, vector_src.GetReg()); 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 246558994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::GetCoreArgMappingToPhysicalReg(int core_arg_num) { 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) { 246958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case 0: 247058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return rs_rX86_ARG1; 247158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case 1: 247258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return rs_rX86_ARG2; 247358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case 2: 247458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return rs_rX86_ARG3; 247558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko default: 247658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return RegStorage::InvalidReg(); 247758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 247858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 247958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 248058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// ---------End of ABI support: mapping of args to physical registers ------------- 248158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 248258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/* 248358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If there are any ins passed in registers that have not been promoted 248458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * to a callee-save register, flush them to the frame. Perform initial 248558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * assignment of promoted arguments. 248658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 248758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * ArgLocs is an array of location records describing the incoming arguments 248858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * with one location record per word of argument. 248958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 249058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkovoid X86Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) { 2491dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) return Mir2Lir::FlushIns(ArgLocs, rl_method); 249258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 249358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Dummy up a RegLocation for the incoming Method* 249458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * It will attempt to keep kArg0 live (or copy it to home location 249558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * if promoted). 249658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 249758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 249858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation rl_src = rl_method; 249958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_src.location = kLocPhysReg; 2500ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe rl_src.reg = TargetReg(kArg0, kRef); 250158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_src.home = false; 250258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko MarkLive(rl_src); 250358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko StoreValue(rl_method, rl_src); 250458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // If Method* has been promoted, explicitly flush 250558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (rl_method.location == kLocPhysReg) { 2506ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe StoreRefDisp(rs_rX86_SP, 0, As32BitReg(TargetReg(kArg0, kRef)), kNotVolatile); 250758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 250858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25098d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru if (mir_graph_->GetNumOfInVRs() == 0) { 251058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return; 251158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 251258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25138d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru int start_vreg = cu_->mir_graph->GetFirstInVR(); 251458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 251558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Copy incoming arguments to their proper home locations. 251658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * NOTE: an older version of dx had an issue in which 251758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * it would reuse static method argument registers. 251858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * This could result in the same Dalvik virtual register 251958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * being promoted to both core and fp regs. To account for this, 252058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * we only copy to the corresponding promoted physical register 252158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * if it matches the type of the SSA name for the incoming 252258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * argument. It is also possible that long and double arguments 252358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * end up half-promoted. In those cases, we must flush the promoted 252458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * half to memory as well. 252558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 25268dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 25278d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru for (uint32_t i = 0; i < mir_graph_->GetNumOfInVRs(); i++) { 252858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // get reg corresponding to input 25294d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko RegStorage reg = GetArgMappingToPhysicalReg(i); 253058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25314d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko RegLocation* t_loc = &ArgLocs[i]; 253258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (reg.Valid()) { 25334d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // If arriving in register. 253458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25354d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // We have already updated the arg location with promoted info 25364d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // so we can be based on it. 25374d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->location == kLocPhysReg) { 25384d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // Just copy it. 25394d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko OpRegCopy(t_loc->reg, reg); 25404d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } else { 25414d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // Needs flush. 25424d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->ref) { 2543a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreRefDisp(rs_rX86_SP, SRegOffset(start_vreg + i), reg, kNotVolatile); 254458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 2545a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, SRegOffset(start_vreg + i), reg, t_loc->wide ? k64 : k32, 25464d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko kNotVolatile); 254758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 254858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 254958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 25504d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // If arriving in frame & promoted. 25514d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->location == kLocPhysReg) { 25524d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->ref) { 2553a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LoadRefDisp(rs_rX86_SP, SRegOffset(start_vreg + i), t_loc->reg, kNotVolatile); 25544d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } else { 2555a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LoadBaseDisp(rs_rX86_SP, SRegOffset(start_vreg + i), t_loc->reg, 25564d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko t_loc->wide ? k64 : k32, kNotVolatile); 25574d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } 255858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 255958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 25604d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->wide) { 25614d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // Increment i to skip the next one. 25624d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko i++; 25634d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } 256458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 256558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 256658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 256758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/* 256858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Load up to 5 arguments, the first three of which will be in 256958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * kArg1 .. kArg3. On entry kArg0 contains the current method pointer, 257058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * and as part of the load sequence, it must be replaced with 257158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * the target method pointer. Note, this may also be called 257258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * for "range" variants if the number of arguments is 5 or fewer. 257358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 257458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsNoRange(CallInfo* info, 257558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int call_state, LIR** pcrLabel, NextCallInsn next_call_insn, 257658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const MethodReference& target_method, 257758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko uint32_t vtable_idx, uintptr_t direct_code, 257858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko uintptr_t direct_method, InvokeType type, bool skip_this) { 2579dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 258058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return Mir2Lir::GenDalvikArgsNoRange(info, 258158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state, pcrLabel, next_call_insn, 258258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko target_method, 258358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, 258458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_method, type, skip_this); 258558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 258658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return GenDalvikArgsRange(info, 258758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state, pcrLabel, next_call_insn, 258858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko target_method, 258958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, 259058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_method, type, skip_this); 259158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 259258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 259358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/* 259458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * May have 0+ arguments (also used for jumbo). Note that 259558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * source virtual registers may be in physical registers, so may 259658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * need to be flushed to home location before copying. This 259758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * applies to arg3 and above (see below). 259858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 259958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Two general strategies: 260058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If < 20 arguments 260158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass args 3-18 using vldm/vstm block copy 260258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass arg0, arg1 & arg2 in kArg1-kArg3 260358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If 20+ arguments 260458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass args arg19+ using memcpy block copy 260558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass arg0, arg1 & arg2 in kArg1-kArg3 260658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 260758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 260858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state, 260958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR** pcrLabel, NextCallInsn next_call_insn, 261058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const MethodReference& target_method, 261158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko uint32_t vtable_idx, uintptr_t direct_code, uintptr_t direct_method, 261258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko InvokeType type, bool skip_this) { 2613dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 261458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return Mir2Lir::GenDalvikArgsRange(info, call_state, 261558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko pcrLabel, next_call_insn, 261658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko target_method, 261758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, direct_method, 261858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko type, skip_this); 261958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 262058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 262158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* If no arguments, just return */ 262258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (info->num_arg_words == 0) 262358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return call_state; 262458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 262558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const int start_index = skip_this ? 1 : 0; 262658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2627a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu InToRegStorageX86_64Mapper mapper(this); 262858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko InToRegStorageMapping in_to_reg_storage_mapping; 262958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko in_to_reg_storage_mapping.Initialize(info->args, info->num_arg_words, &mapper); 263058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const int last_mapped_in = in_to_reg_storage_mapping.GetMaxMappedIn(); 263158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const int size_of_the_last_mapped = last_mapped_in == -1 ? 1 : 26328e3acdd132aef1391676a5db2696804900aacd8eSerguei Katkov info->args[last_mapped_in].wide ? 2 : 1; 263358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int regs_left_to_pass_via_stack = info->num_arg_words - (last_mapped_in + size_of_the_last_mapped); 263458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 263558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Fisrt of all, check whether it make sense to use bulk copying 263658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Optimization is aplicable only for range case 263758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // TODO: make a constant instead of 2 263858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (info->is_range && regs_left_to_pass_via_stack >= 2) { 263958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Scan the rest of the args - if in phys_reg flush to memory 264058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko for (int next_arg = last_mapped_in + size_of_the_last_mapped; next_arg < info->num_arg_words;) { 264158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation loc = info->args[next_arg]; 264258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (loc.wide) { 264358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko loc = UpdateLocWide(loc); 264458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (loc.location == kLocPhysReg) { 26458dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 2646a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, SRegOffset(loc.s_reg_low), loc.reg, k64, kNotVolatile); 264758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 264858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko next_arg += 2; 264958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 265058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko loc = UpdateLoc(loc); 265158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (loc.location == kLocPhysReg) { 26528dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 2653a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, SRegOffset(loc.s_reg_low), loc.reg, k32, kNotVolatile); 265458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 265558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko next_arg++; 265658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 265758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 265858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 265958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // The rest can be copied together 266058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int start_offset = SRegOffset(info->args[last_mapped_in + size_of_the_last_mapped].s_reg_low); 2661ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe int outs_offset = StackVisitor::GetOutVROffset(last_mapped_in + size_of_the_last_mapped, 2662ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe cu_->instruction_set); 266358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 266458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int current_src_offset = start_offset; 266558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int current_dest_offset = outs_offset; 266658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 26678dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko // Only davik regs are accessed in this loop; no next_call_insn() calls. 26688dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 266958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko while (regs_left_to_pass_via_stack > 0) { 267058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // This is based on the knowledge that the stack itself is 16-byte aligned. 267158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool src_is_16b_aligned = (current_src_offset & 0xF) == 0; 267258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool dest_is_16b_aligned = (current_dest_offset & 0xF) == 0; 267358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko size_t bytes_to_move; 267458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 267558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 267658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * The amount to move defaults to 32-bit. If there are 4 registers left to move, then do a 267758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * a 128-bit move because we won't get the chance to try to aligned. If there are more than 267858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 4 registers left to move, consider doing a 128-bit only if either src or dest are aligned. 267958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * We do this because we could potentially do a smaller move to align. 268058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 268158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (regs_left_to_pass_via_stack == 4 || 268258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko (regs_left_to_pass_via_stack > 4 && (src_is_16b_aligned || dest_is_16b_aligned))) { 268358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Moving 128-bits via xmm register. 268458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bytes_to_move = sizeof(uint32_t) * 4; 268558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 268658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Allocate a free xmm temp. Since we are working through the calling sequence, 268758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // we expect to have an xmm temporary available. AllocTempDouble will abort if 268858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // there are no free registers. 268958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage temp = AllocTempDouble(); 269058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 269158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* ld1 = nullptr; 269258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* ld2 = nullptr; 269358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* st1 = nullptr; 269458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* st2 = nullptr; 269558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 269658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 269758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * The logic is similar for both loads and stores. If we have 16-byte alignment, 269858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * do an aligned move. If we have 8-byte alignment, then do the move in two 269958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * parts. This approach prevents possible cache line splits. Finally, fall back 270058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * to doing an unaligned move. In most cases we likely won't split the cache 270158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * line but we cannot prove it and thus take a conservative approach. 270258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 270358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool src_is_8b_aligned = (current_src_offset & 0x7) == 0; 270458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool dest_is_8b_aligned = (current_dest_offset & 0x7) == 0; 270558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 27068dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 270758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (src_is_16b_aligned) { 2708a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovA128FP); 270958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else if (src_is_8b_aligned) { 2710a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovLo128FP); 2711a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu ld2 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset + (bytes_to_move >> 1), 271258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko kMovHi128FP); 271358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 2714a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovU128FP); 271558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 271658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 271758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (dest_is_16b_aligned) { 2718a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovA128FP); 271958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else if (dest_is_8b_aligned) { 2720a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovLo128FP); 2721a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu st2 = OpMovMemReg(rs_rX86_SP, current_dest_offset + (bytes_to_move >> 1), 272258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko temp, kMovHi128FP); 272358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 2724a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovU128FP); 272558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 272658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 272758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // TODO If we could keep track of aliasing information for memory accesses that are wider 272858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // than 64-bit, we wouldn't need to set up a barrier. 272958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (ld1 != nullptr) { 273058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (ld2 != nullptr) { 273158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // For 64-bit load we can actually set up the aliasing information. 273258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(ld1, current_src_offset >> 2, true, true); 273358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(ld2, (current_src_offset + (bytes_to_move >> 1)) >> 2, true, true); 273458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 273558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Set barrier for 128-bit load. 27368dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ld1->u.m.def_mask = &kEncodeAll; 273758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 273858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 273958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (st1 != nullptr) { 274058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (st2 != nullptr) { 274158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // For 64-bit store we can actually set up the aliasing information. 274258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(st1, current_dest_offset >> 2, false, true); 274358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(st2, (current_dest_offset + (bytes_to_move >> 1)) >> 2, false, true); 274458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 274558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Set barrier for 128-bit store. 27468dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko st1->u.m.def_mask = &kEncodeAll; 274758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 274858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 274958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 275058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Free the temporary used for the data movement. 275158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(temp); 275258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 275358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Moving 32-bits via general purpose register. 275458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bytes_to_move = sizeof(uint32_t); 275558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 275658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Instead of allocating a new temp, simply reuse one of the registers being used 275758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // for argument passing. 2758ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe RegStorage temp = TargetReg(kArg3, kNotWide); 275958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 276058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Now load the argument VR and store to the outs. 2761a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu Load32Disp(rs_rX86_SP, current_src_offset, temp); 2762a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu Store32Disp(rs_rX86_SP, current_dest_offset, temp); 276358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 276458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 276558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko current_src_offset += bytes_to_move; 276658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko current_dest_offset += bytes_to_move; 276758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko regs_left_to_pass_via_stack -= (bytes_to_move >> 2); 276858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 276958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko DCHECK_EQ(regs_left_to_pass_via_stack, 0); 277058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 277158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 277258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Now handle rest not registers if they are 277358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (in_to_reg_storage_mapping.IsThereStackMapped()) { 2774ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe RegStorage regSingle = TargetReg(kArg2, kNotWide); 2775ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe RegStorage regWide = TargetReg(kArg3, kWide); 2776b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu for (int i = start_index; 2777b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu i < last_mapped_in + size_of_the_last_mapped + regs_left_to_pass_via_stack; i++) { 277858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation rl_arg = info->args[i]; 277958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_arg = UpdateRawLoc(rl_arg); 278058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage reg = in_to_reg_storage_mapping.Get(i); 278158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (!reg.Valid()) { 278258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int out_offset = StackVisitor::GetOutVROffset(i, cu_->instruction_set); 278358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 27848dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko { 27858dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 27868dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (rl_arg.wide) { 27878dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (rl_arg.location == kLocPhysReg) { 2788a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, out_offset, rl_arg.reg, k64, kNotVolatile); 27898dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } else { 27908dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko LoadValueDirectWideFixed(rl_arg, regWide); 2791a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, out_offset, regWide, k64, kNotVolatile); 27928dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } 279358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 27948dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (rl_arg.location == kLocPhysReg) { 2795a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, out_offset, rl_arg.reg, k32, kNotVolatile); 27968dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } else { 27978dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko LoadValueDirectFixed(rl_arg, regSingle); 2798a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, out_offset, regSingle, k32, kNotVolatile); 27998dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } 280058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 280158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 280258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state = next_call_insn(cu_, info, call_state, target_method, 280358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, direct_method, type); 280458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 2805b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu if (rl_arg.wide) { 2806b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu i++; 2807b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu } 280858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 280958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 281058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 281158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Finish with mapped registers 281258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko for (int i = start_index; i <= last_mapped_in; i++) { 281358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation rl_arg = info->args[i]; 281458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_arg = UpdateRawLoc(rl_arg); 281558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage reg = in_to_reg_storage_mapping.Get(i); 281658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (reg.Valid()) { 281758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (rl_arg.wide) { 281858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LoadValueDirectWideFixed(rl_arg, reg); 281958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 282058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LoadValueDirectFixed(rl_arg, reg); 282158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 282258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, 282358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_code, direct_method, type); 282458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 2825b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu if (rl_arg.wide) { 2826b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu i++; 2827b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu } 282858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 282958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 283058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, 283158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_code, direct_method, type); 283258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (pcrLabel) { 283369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) { 2834ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe *pcrLabel = GenExplicitNullCheck(TargetReg(kArg1, kRef), info->opt_flags); 283558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 283658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *pcrLabel = nullptr; 283758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // In lieu of generating a check for kArg1 being null, we need to 283858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // perform a load when doing implicit checks. 283958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage tmp = AllocTemp(); 2840ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe Load32Disp(TargetReg(kArg1, kRef), 0, tmp); 284158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko MarkPossibleNullPointerException(info->opt_flags); 284258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(tmp); 284358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 284458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 284558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return call_state; 284658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 284758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2848984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampebool X86Mir2Lir::GenInlinedCharAt(CallInfo* info) { 2849984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Location of reference to data array 2850984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int value_offset = mirror::String::ValueOffset().Int32Value(); 2851984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Location of count 2852984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int count_offset = mirror::String::CountOffset().Int32Value(); 2853984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Starting offset within data array 2854984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int offset_offset = mirror::String::OffsetOffset().Int32Value(); 2855984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Start of char data with array_ 2856984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); 2857984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe 2858984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_obj = info->args[0]; 2859984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_idx = info->args[1]; 2860984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe rl_obj = LoadValue(rl_obj, kRefReg); 2861984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // X86 wants to avoid putting a constant index into a register. 2862984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (!rl_idx.is_const) { 2863984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe rl_idx = LoadValue(rl_idx, kCoreReg); 2864984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2865984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegStorage reg_max; 2866984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe GenNullCheck(rl_obj.reg, info->opt_flags); 2867984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe bool range_check = (!(info->opt_flags & MIR_IGNORE_RANGE_CHECK)); 2868984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LIR* range_check_branch = nullptr; 2869984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegStorage reg_off; 2870984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegStorage reg_ptr; 2871984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (range_check) { 2872984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // On x86, we can compare to memory directly 2873984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Set up a launch pad to allow retry in case of bounds violation */ 2874984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (rl_idx.is_const) { 2875984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LIR* comparison; 2876984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe range_check_branch = OpCmpMemImmBranch( 2877984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe kCondUlt, RegStorage::InvalidReg(), rl_obj.reg, count_offset, 2878984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe mir_graph_->ConstantValue(rl_idx.orig_sreg), nullptr, &comparison); 2879984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe MarkPossibleNullPointerExceptionAfter(0, comparison); 2880984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } else { 2881984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe OpRegMem(kOpCmp, rl_idx.reg, rl_obj.reg, count_offset); 2882984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe MarkPossibleNullPointerException(0); 2883984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe range_check_branch = OpCondBranch(kCondUge, nullptr); 2884984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2885984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2886984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe reg_off = AllocTemp(); 2887984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe reg_ptr = AllocTempRef(); 2888984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe Load32Disp(rl_obj.reg, offset_offset, reg_off); 2889984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LoadRefDisp(rl_obj.reg, value_offset, reg_ptr, kNotVolatile); 2890984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (rl_idx.is_const) { 2891984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe OpRegImm(kOpAdd, reg_off, mir_graph_->ConstantValue(rl_idx.orig_sreg)); 2892984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } else { 2893984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe OpRegReg(kOpAdd, reg_off, rl_idx.reg); 2894984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2895984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(rl_obj.reg); 2896984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (rl_idx.location == kLocPhysReg) { 2897984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(rl_idx.reg); 2898984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2899984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_dest = InlineTarget(info); 2900984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 2901984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LoadBaseIndexedDisp(reg_ptr, reg_off, 1, data_offset, rl_result.reg, kUnsignedHalf); 2902984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(reg_off); 2903984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(reg_ptr); 2904984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe StoreValue(rl_dest, rl_result); 2905984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (range_check) { 2906984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe DCHECK(range_check_branch != nullptr); 2907984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe info->opt_flags |= MIR_IGNORE_NULL_CHECK; // Record that we've already null checked. 2908984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe AddIntrinsicSlowPath(info, range_check_branch); 2909984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2910984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe return true; 2911984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe} 2912984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe 29136bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalovbool X86Mir2Lir::GenInlinedCurrentThread(CallInfo* info) { 29146bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov RegLocation rl_dest = InlineTarget(info); 29156bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29166bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov // Early exit if the result is unused. 29176bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov if (rl_dest.orig_sreg < 0) { 29186bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov return true; 29196bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov } 29206bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29216bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true); 29226bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29236bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov if (cu_->target64) { 29246bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov OpRegThreadMem(kOpMov, rl_result.reg, Thread::PeerOffset<8>()); 29256bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov } else { 29266bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov OpRegThreadMem(kOpMov, rl_result.reg, Thread::PeerOffset<4>()); 29276bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov } 29286bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29296bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov StoreValue(rl_dest, rl_result); 29306bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov return true; 29316bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov} 29326bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29336dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev/** 29346dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev * Lock temp registers for explicit usage. Registers will be freed in destructor. 29356dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev */ 29366dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim KazantsevX86Mir2Lir::ExplicitTempRegisterLock::ExplicitTempRegisterLock(X86Mir2Lir* mir_to_lir, 29376dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev int n_regs, ...) : 29386dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev temp_regs_(n_regs), 29396dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_(mir_to_lir) { 29406dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev va_list regs; 29416dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev va_start(regs, n_regs); 29426dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev for (int i = 0; i < n_regs; i++) { 29436dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev RegStorage reg = *(va_arg(regs, RegStorage*)); 29446dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev RegisterInfo* info = mir_to_lir_->GetRegInfo(reg); 29456dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29466dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev // Make sure we don't have promoted register here. 29476dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev DCHECK(info->IsTemp()); 29486dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29496dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev temp_regs_.push_back(reg); 29506dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->FlushReg(reg); 29516dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29526dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev if (reg.IsPair()) { 29536dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev RegStorage partner = info->Partner(); 29546dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev temp_regs_.push_back(partner); 29556dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->FlushReg(partner); 29566dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev } 29576dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29586dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->Clobber(reg); 29596dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->LockTemp(reg); 29606dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev } 29616dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29626dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev va_end(regs); 29636dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev} 29646dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29656dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev/* 29666dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev * Free all locked registers. 29676dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev */ 29686dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim KazantsevX86Mir2Lir::ExplicitTempRegisterLock::~ExplicitTempRegisterLock() { 29696dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev // Free all locked temps. 29706dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev for (auto it : temp_regs_) { 29716dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->FreeTemp(it); 29726dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev } 29736dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev} 29746dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29757934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 2976