target_x86.cc revision 6dccdc2511c9f22d3cc2ea83386ce9db2688fa19
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" 26e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell#include "mirror/array.h" 27e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell#include "mirror/string.h" 28b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A#include "oat.h" 29641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h" 30547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen#include "utils/dwarf_cfi.h" 31efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 32efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art { 33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 34089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_32[] = { 359ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI, 369ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 37089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_64[] = { 3876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI, 39091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_r8, rs_r9, rs_r10, rs_r11, rs_r12, rs_r13, rs_r14, rs_r15 40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 41089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_64q[] = { 420999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko rs_r0q, rs_r1q, rs_r2q, rs_r3q, rs_rX86_SP_64, rs_r5q, rs_r6q, rs_r7q, 43a20468c004264592f309a548fc71ba62a69b8742Dmitry Petrochenko rs_r8q, rs_r9q, rs_r10q, rs_r11q, rs_r12q, rs_r13q, rs_r14q, rs_r15q 440999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko}; 45089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_regs_arr_32[] = { 469ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 48089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_regs_arr_64[] = { 49091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 50091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15 51efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 52089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_regs_arr_32[] = { 539ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 55089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_regs_arr_64[] = { 56091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 57091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15 58efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 59c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr RegStorage xp_regs_arr_32[] = { 60c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 61c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov}; 62c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr RegStorage xp_regs_arr_64[] = { 63c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 64c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr8, rs_xr9, rs_xr10, rs_xr11, rs_xr12, rs_xr13, rs_xr14, rs_xr15 65c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov}; 66089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage reserved_regs_arr_32[] = {rs_rX86_SP_32}; 6776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenkostatic constexpr RegStorage reserved_regs_arr_64[] = {rs_rX86_SP_32}; 68089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage reserved_regs_arr_64q[] = {rs_rX86_SP_64}; 69089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_32[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX}; 70089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_64[] = { 719ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rAX, rs_rCX, rs_rDX, rs_rSI, rs_rDI, 729ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_r8, rs_r9, rs_r10, rs_r11 739ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 74c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 75c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// How to add register to be available for promotion: 76c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 1) Remove register from array defining temp 77c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 2) Update ClobberCallerSave 78c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 3) Update JNI compiler ABI: 79c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 3.1) add reg in JniCallingConvention method 80c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 3.2) update CoreSpillMask/FpSpillMask 81c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4) Update entrypoints 82c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.1) Update constants in asm_support_x86_64.h for new frame size 83c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.2) Remove entry in SmashCallerSaves 84c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.3) Update jni_entrypoints to spill/unspill new callee save reg 85c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 4.4) Update quick_entrypoints to spill/unspill new callee save reg 86c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 5) Update runtime ABI 87c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 5.1) Update quick_method_frame_info with new required spills 88c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// 5.2) Update QuickArgumentVisitor with new offsets to gprs and xmms 89c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// Note that you cannot use register corresponding to incoming args 90c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// according to ABI and QCG needs one additional XMM temp for 91c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov// bulk copy in preparation to call. 92089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_64q[] = { 930999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko rs_r0q, rs_r1q, rs_r2q, rs_r6q, rs_r7q, 940999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko rs_r8q, rs_r9q, rs_r10q, rs_r11q 950999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko}; 96089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_temps_arr_32[] = { 979ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 989ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 99089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_temps_arr_64[] = { 100091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7, 101c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_fr8, rs_fr9, rs_fr10, rs_fr11 102091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 103089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_temps_arr_32[] = { 1049ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 1059ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko}; 106089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_temps_arr_64[] = { 107091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7, 108c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_dr8, rs_dr9, rs_dr10, rs_dr11 109091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee}; 110091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 111089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage xp_temps_arr_32[] = { 112fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 113fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}; 114089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage xp_temps_arr_64[] = { 115fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7, 116c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov rs_xr8, rs_xr9, rs_xr10, rs_xr11 117fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}; 118fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 119089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> empty_pool; 120089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_32(core_regs_arr_32); 121089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_64(core_regs_arr_64); 122089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_64q(core_regs_arr_64q); 123089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_regs_32(sp_regs_arr_32); 124089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_regs_64(sp_regs_arr_64); 125089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_regs_32(dp_regs_arr_32); 126089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_regs_64(dp_regs_arr_64); 127c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr ArrayRef<const RegStorage> xp_regs_32(xp_regs_arr_32); 128c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovstatic constexpr ArrayRef<const RegStorage> xp_regs_64(xp_regs_arr_64); 129089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_32(reserved_regs_arr_32); 130089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_64(reserved_regs_arr_64); 131089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_64q(reserved_regs_arr_64q); 132089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_32(core_temps_arr_32); 133089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_64(core_temps_arr_64); 134089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_64q(core_temps_arr_64q); 135089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_temps_32(sp_temps_arr_32); 136089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_temps_64(sp_temps_arr_64); 137089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_temps_32(dp_temps_arr_32); 138089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_temps_64(dp_temps_arr_64); 139089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Marko 140089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> xp_temps_32(xp_temps_arr_32); 141089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> xp_temps_64(xp_temps_arr_64); 142fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1439ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_SP; 1449ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 1459ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG0; 1469ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG1; 1479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG2; 1489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG3; 14958994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_ARG4; 15058994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_ARG5; 1519ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG0; 1529ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG1; 1539ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG2; 1549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG3; 15558994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_FARG4; 15658994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_FARG5; 15758994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_FARG6; 15858994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_FARG7; 1599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_RET0; 1609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_RET1; 1619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_INVOKE_TGT; 1629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_COUNT; 1639ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 1649ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG0; 1659ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG1; 1669ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG2; 1679ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG3; 16858994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_ARG4; 16958994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_ARG5; 1709ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG0; 1719ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG1; 1729ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG2; 1739ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG3; 17458994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG4; 17558994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG5; 17658994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG6; 17758994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG7; 1789ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_RET0; 1799ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_RET1; 1809ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_INVOKE_TGT; 1819ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_COUNT; 182efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1832ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturn() { 18400e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return; 185efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 186efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 187a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbeeRegLocation X86Mir2Lir::LocCReturnRef() { 188a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu return cu_->target64 ? x86_64_loc_c_return_ref : x86_loc_c_return_ref; 189a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee} 190a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee 1912ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnWide() { 192dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina return cu_->target64 ? x86_64_loc_c_return_wide : x86_loc_c_return_wide; 193efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 194efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1952ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnFloat() { 19600e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_float; 197efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 198efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 1992ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnDouble() { 20000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee return x86_loc_c_return_double; 201efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 202efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 203a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu// Return a target-dependent special register for 32-bit. 204a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying FuRegStorage X86Mir2Lir::TargetReg32(SpecialTargetRegister reg) { 205091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegStorage res_reg = RegStorage::InvalidReg(); 206efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (reg) { 207091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSelf: res_reg = RegStorage::InvalidReg(); break; 208091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kSuspend: res_reg = RegStorage::InvalidReg(); break; 209091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kLr: res_reg = RegStorage::InvalidReg(); break; 210091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kPc: res_reg = RegStorage::InvalidReg(); break; 211ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe case kSp: res_reg = rs_rX86_SP_32; break; // This must be the concrete one, as _SP is target- 212ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe // specific size. 213091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg0: res_reg = rs_rX86_ARG0; break; 214091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg1: res_reg = rs_rX86_ARG1; break; 215091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg2: res_reg = rs_rX86_ARG2; break; 216091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kArg3: res_reg = rs_rX86_ARG3; break; 21758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kArg4: res_reg = rs_rX86_ARG4; break; 21858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kArg5: res_reg = rs_rX86_ARG5; break; 219091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg0: res_reg = rs_rX86_FARG0; break; 220091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg1: res_reg = rs_rX86_FARG1; break; 221091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg2: res_reg = rs_rX86_FARG2; break; 222091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kFArg3: res_reg = rs_rX86_FARG3; break; 22358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kFArg4: res_reg = rs_rX86_FARG4; break; 22458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kFArg5: res_reg = rs_rX86_FARG5; break; 22558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kFArg6: res_reg = rs_rX86_FARG6; break; 22658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case kFArg7: res_reg = rs_rX86_FARG7; break; 227091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kRet0: res_reg = rs_rX86_RET0; break; 228091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kRet1: res_reg = rs_rX86_RET1; break; 229091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kInvokeTgt: res_reg = rs_rX86_INVOKE_TGT; break; 230091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kHiddenArg: res_reg = rs_rAX; break; 231dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina case kHiddenFpArg: DCHECK(!cu_->target64); res_reg = rs_fr0; break; 232091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee case kCount: res_reg = rs_rX86_COUNT; break; 23358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko default: res_reg = RegStorage::InvalidReg(); 234091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee } 235091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee return res_reg; 236efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 237efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 238a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying FuRegStorage X86Mir2Lir::TargetReg(SpecialTargetRegister reg) { 239a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LOG(FATAL) << "Do not use this function!!!"; 240a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu return RegStorage::InvalidReg(); 241a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu} 242a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu 243efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 244efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Decode the register id. 245efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 2468dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask X86Mir2Lir::GetRegMaskCommon(const RegStorage& reg) const { 2478dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko /* Double registers in x86 are just a single FP register. This is always just a single bit. */ 2488dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko return ResourceMask::Bit( 2498dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko /* FP register starts at bit position 16 */ 2508dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ((reg.IsFloat() || reg.StorageSize() > 8) ? kX86FPReg0 : 0) + reg.GetRegNum()); 2518dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko} 2528dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko 2538dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask X86Mir2Lir::GetPCUseDefEncoding() const { 2548dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko return kEncodeNone; 255efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 256efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 2578dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid X86Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags, 2588dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ResourceMask* use_mask, ResourceMask* def_mask) { 2596a58cb16d803c9a7b3a75ccac8be19dd9d4e520dDmitry Petrochenko DCHECK(cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64); 260b48819db07f9a0992a72173380c24249d7fc648abuzbee DCHECK(!lir->flags.use_def_invalid); 261efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 262efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // X86-specific resource map setup here. 263efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USE_SP) { 2648dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko use_mask->SetBit(kX86RegSP); 265efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 266efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 267efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEF_SP) { 2688dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko def_mask->SetBit(kX86RegSP); 269efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 270efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 271efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFA) { 2728dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(def_mask, rs_rAX.GetReg()); 273efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 274efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 275efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_DEFD) { 2768dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(def_mask, rs_rDX.GetReg()); 277efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 278efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEA) { 2798dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rAX.GetReg()); 280efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 281efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 282efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USEC) { 2838dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rCX.GetReg()); 284efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 285efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 286efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (flags & REG_USED) { 2878dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rDX.GetReg()); 288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 28970b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko 29070b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko if (flags & REG_USEB) { 2918dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rBX.GetReg()); 29270b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko } 2934028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 2944028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Fixup hard to describe instruction: Uses rAX, rCX, rDI; sets rDI. 2954028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (lir->opcode == kX86RepneScasw) { 2968dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rAX.GetReg()); 2978dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rCX.GetReg()); 2988dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(use_mask, rs_rDI.GetReg()); 2998dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko SetupRegMask(def_mask, rs_rDI.GetReg()); 3004028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 301e90501da0222717d75c126ebf89569db3976927eSerguei Katkov 302e90501da0222717d75c126ebf89569db3976927eSerguei Katkov if (flags & USE_FP_STACK) { 3038dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko use_mask->SetBit(kX86FPStack); 3048dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko def_mask->SetBit(kX86FPStack); 305e90501da0222717d75c126ebf89569db3976927eSerguei Katkov } 306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 308efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* For dumping instructions */ 309efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86RegName[] = { 310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 311efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 312efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 313efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 314efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86CondName[] = { 315efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "O", 316efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NO", 317efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "B/NAE/C", 318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NB/AE/NC", 319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "Z/EQ", 320efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NZ/NE", 321efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "BE/NA", 322efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NBE/A", 323efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "S", 324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NS", 325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "P/PE", 326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NP/PO", 327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "L/NGE", 328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NL/GE", 329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "LE/NG", 330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee "NLE/G" 331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 333efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Interpret a format string and build a string no longer than size 335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See format key in Assemble.cc. 336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 3371fd3346740dfb7f47be9922312b68a4227fada96buzbeestd::string X86Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) { 338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee std::string buf; 339efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t i = 0; 340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee size_t fmt_len = strlen(fmt); 341efc6369224b036a1fb77849f7ae65b3492c832c0buzbee while (i < fmt_len) { 342efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (fmt[i] != '!') { 343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += fmt[i]; 344efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 345efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 346efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char operand_number_ch = fmt[i]; 349efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 350efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (operand_number_ch == '!') { 351efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += "!"; 352efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 353efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand_number = operand_number_ch - '0'; 354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(operand_number, 6); // Expect upto 6 LIR operands. 355efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(i, fmt_len); 356efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int operand = lir->operands[operand_number]; 357efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (fmt[i]) { 358efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'c': 359efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_LT(static_cast<size_t>(operand), sizeof(x86CondName)); 360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += x86CondName[operand]; 361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 362efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'd': 363efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("%d", operand); 364efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 3655192cbb12856b12620dc346758605baaa1469cedYixin Shou case 'q': { 3665192cbb12856b12620dc346758605baaa1469cedYixin Shou int64_t value = static_cast<int64_t>(static_cast<int64_t>(operand) << 32 | 3675192cbb12856b12620dc346758605baaa1469cedYixin Shou static_cast<uint32_t>(lir->operands[operand_number+1])); 3685192cbb12856b12620dc346758605baaa1469cedYixin Shou buf +=StringPrintf("%" PRId64, value); 369e70f179aca4f13b15be8a47a4d9e5b6c2422c69aHaitao Feng break; 3705192cbb12856b12620dc346758605baaa1469cedYixin Shou } 371efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'p': { 3720d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(operand)); 373fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee buf += StringPrintf("0x%08x", tab_rec->offset); 374efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 375efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 376efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 'r': 377091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee if (RegStorage::IsFloat(operand)) { 378091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int fp_reg = RegStorage::RegNum(operand); 379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("xmm%d", fp_reg); 380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 381091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int reg_num = RegStorage::RegNum(operand); 382091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK_LT(static_cast<size_t>(reg_num), sizeof(x86RegName)); 383091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee buf += x86RegName[reg_num]; 384efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 385efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 386efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 't': 387107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers buf += StringPrintf("0x%08" PRIxPTR " (L%p)", 388107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers reinterpret_cast<uintptr_t>(base_addr) + lir->offset + operand, 389107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers lir->target); 390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 391efc6369224b036a1fb77849f7ae65b3492c832c0buzbee default: 392efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf += StringPrintf("DecodeError '%c'", fmt[i]); 393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 395efc6369224b036a1fb77849f7ae65b3492c832c0buzbee i++; 396efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 397efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return buf; 400efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 401efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4028dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid X86Mir2Lir::DumpResourceMask(LIR *x86LIR, const ResourceMask& mask, const char *prefix) { 403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char buf[256]; 404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee buf[0] = 0; 405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4068dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.Equals(kEncodeAll)) { 407efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcpy(buf, "all"); 408efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 409efc6369224b036a1fb77849f7ae65b3492c832c0buzbee char num[8]; 410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int i; 411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (i = 0; i < kX86RegEnd; i++) { 4138dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(i)) { 414988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(num, arraysize(num), "%d ", i); 415efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, num); 416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 418efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4198dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kCCode)) { 420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "cc "); 421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 422efc6369224b036a1fb77849f7ae65b3492c832c0buzbee /* Memory bits */ 4238dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (x86LIR && (mask.HasBit(ResourceMask::kDalvikReg))) { 424988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s", 425988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers DECODE_ALIAS_INFO_REG(x86LIR->flags.alias_info), 426988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers (DECODE_ALIAS_INFO_WIDE(x86LIR->flags.alias_info)) ? "(+1)" : ""); 427efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 4288dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kLiteral)) { 429efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "lit "); 430efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 431efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4328dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kHeapRef)) { 433efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "heap "); 434efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 4358dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mask.HasBit(ResourceMask::kMustNotAlias)) { 436efc6369224b036a1fb77849f7ae65b3492c832c0buzbee strcat(buf, "noalias "); 437efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 438efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 439efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (buf[0]) { 440efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(INFO) << prefix << ": " << buf; 441efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 442efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 44302031b185b4653e6c72e21f7a51238b903f6d638buzbee 4441fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::AdjustSpillMask() { 445efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Adjustment for LR spilling, x86 has no LR so nothing to do here 446091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee core_spill_mask_ |= (1 << rs_rRET.GetRegNum()); 4471fd3346740dfb7f47be9922312b68a4227fada96buzbee num_core_spills_++; 448efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 449efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 450e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark MendellRegStorage X86Mir2Lir::AllocateByteRegister() { 4517e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu RegStorage reg = AllocTypedTemp(false, kCoreReg); 452dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 4537e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu DCHECK_LT(reg.GetRegNum(), rs_rX86_SP.GetRegNum()); 4547e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu } 4557e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu return reg; 4567e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu} 4577e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu 45860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan BanerjiRegStorage X86Mir2Lir::Get128BitRegister(RegStorage reg) { 459b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return GetRegInfo(reg)->Master()->GetReg(); 46060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 46160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 4627e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fubool X86Mir2Lir::IsByteRegister(RegStorage reg) { 463dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina return cu_->target64 || reg.GetRegNum() < rs_rX86_SP.GetRegNum(); 464e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell} 465e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell 466efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Clobber all regs that might be used by an external C call */ 46731c2aac7137b69d5622eea09597500731fbee2efVladimir Markovoid X86Mir2Lir::ClobberCallerSave() { 468dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 469c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rAX); 470c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rCX); 471c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rDX); 472c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rSI); 473c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rDI); 474c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 47535ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r8); 47635ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r9); 47735ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r10); 47835ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_r11); 47935ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu 48035ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr8); 48135ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr9); 48235ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr10); 48335ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu Clobber(rs_fr11); 484c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } else { 485c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rAX); 486c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rCX); 487c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rDX); 488c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_rBX); 48935ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu } 490c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 491c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr0); 492c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr1); 493c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr2); 494c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr3); 495c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr4); 496c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr5); 497c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr6); 498c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov Clobber(rs_fr7); 499efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 500efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5011fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation X86Mir2Lir::GetReturnWideAlt() { 50252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturnWide(); 503091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(res.reg.GetLowReg() == rs_rAX.GetReg()); 504091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee DCHECK(res.reg.GetHighReg() == rs_rDX.GetReg()); 505091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rAX); 506091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 507091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rAX); 508091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 509091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkWide(res.reg); 510efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 511efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 512efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 5132ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::GetReturnAlt() { 51452a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee RegLocation res = LocCReturn(); 515091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee res.reg.SetReg(rs_rDX.GetReg()); 516091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee Clobber(rs_rDX); 517091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee MarkInUse(rs_rDX); 518efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 519efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 520efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 521efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 5222ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::LockCallTemps() { 523091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG0); 524091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG1); 525091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG2); 526091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee LockTemp(rs_rX86_ARG3); 527dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 52858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_ARG4); 52958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_ARG5); 53058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG0); 53158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG1); 53258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG2); 53358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG3); 53458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG4); 53558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG5); 53658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG6); 53758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LockTemp(rs_rX86_FARG7); 53858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 539efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 540efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 541efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */ 5422ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::FreeCallTemps() { 543091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG0); 544091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG1); 545091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG2); 546091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee FreeTemp(rs_rX86_ARG3); 547dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 54858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_ARG4); 54958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_ARG5); 55058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG0); 55158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG1); 55258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG2); 55358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG3); 55458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG4); 55558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG5); 55658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG6); 55758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(rs_rX86_FARG7); 55858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 559efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 560efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 56199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusorubool X86Mir2Lir::ProvidesFullMemoryBarrier(X86OpCode opcode) { 56299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru switch (opcode) { 56399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgMR: 56499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86LockCmpxchgAR: 5650f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers case kX86LockCmpxchg64M: 5660f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers case kX86LockCmpxchg64A: 56799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86XchgMR: 56899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru case kX86Mfence: 56999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Atomic memory instructions provide full barrier. 57099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return true; 57199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru default: 57299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru break; 57399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 57499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 57599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Conservative if cannot prove it provides full barrier. 57699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru return false; 57799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru} 57899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 579b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampebool X86Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) { 580efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0 58199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Start off with using the last LIR as the barrier. If it is not enough, then we will update it. 58299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru LIR* mem_barrier = last_lir_insn_; 58399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 584b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe bool ret = false; 58599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru /* 58648f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm * According to the JSR-133 Cookbook, for x86 only StoreLoad/AnyAny barriers need memory fence. 58748f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm * All other barriers (LoadAny, AnyStore, StoreStore) are nops due to the x86 memory model. 58848f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm * For those cases, all we need to ensure is that there is a scheduling barrier in place. 58999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru */ 59048f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm if (barrier_kind == kAnyAny) { 59199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If no LIR exists already that can be used a barrier, then generate an mfence. 59299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 59399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 594b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe ret = true; 59599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 59699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 59799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // If last instruction does not provide full barrier, then insert an mfence. 59899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (ProvidesFullMemoryBarrier(static_cast<X86OpCode>(mem_barrier->opcode)) == false) { 59999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru mem_barrier = NewLIR0(kX86Mfence); 600b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe ret = true; 60199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 602b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler } else if (barrier_kind == kNTStoreStore) { 603b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler mem_barrier = NewLIR0(kX86Sfence); 604b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler ret = true; 60599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 60699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru 60799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Now ensure that a scheduling barrier is in place. 60899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru if (mem_barrier == nullptr) { 60999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru GenBarrier(); 61099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } else { 61199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru // Mark as a scheduling barrier. 61299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru DCHECK(!mem_barrier->flags.use_def_invalid); 6138dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko mem_barrier->u.m.def_mask = &kEncodeAll; 61499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru } 615b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe return ret; 616b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe#else 617b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe return false; 618efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 619efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 62000e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee 6211fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::CompilerInitializeRegAlloc() { 622dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 62376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64q, sp_regs_64, 62476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko dp_regs_64, reserved_regs_64, reserved_regs_64q, 62576af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko core_temps_64, core_temps_64q, sp_temps_64, dp_temps_64); 6269ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 627b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, sp_regs_32, 628b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee dp_regs_32, reserved_regs_32, empty_pool, 629b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee core_temps_32, empty_pool, sp_temps_32, dp_temps_32); 6309ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 631091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 632091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Target-specific adjustments. 633091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 634fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Add in XMM registers. 635c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov const ArrayRef<const RegStorage> *xp_regs = cu_->target64 ? &xp_regs_64 : &xp_regs_32; 636c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (RegStorage reg : *xp_regs) { 637fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell RegisterInfo* info = new (arena_) RegisterInfo(reg, GetRegMaskCommon(reg)); 638fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell reginfo_map_.Put(reg.GetReg(), info); 639c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 640c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov const ArrayRef<const RegStorage> *xp_temps = cu_->target64 ? &xp_temps_64 : &xp_temps_32; 641c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (RegStorage reg : *xp_temps) { 642c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov RegisterInfo* xp_reg_info = GetRegInfo(reg); 643c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov xp_reg_info->SetIsTemp(true); 644fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 645fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 646091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Alias single precision xmm to double xmms. 647091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: as needed, add larger vector sizes - alias all to the largest. 648091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee GrowableArray<RegisterInfo*>::Iterator it(®_pool_->sp_regs_); 649091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) { 650091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee int sp_reg_num = info->GetReg().GetRegNum(); 651fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell RegStorage xp_reg = RegStorage::Solo128(sp_reg_num); 652fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell RegisterInfo* xp_reg_info = GetRegInfo(xp_reg); 653fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // 128-bit xmm vector register's master storage should refer to itself. 654fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell DCHECK_EQ(xp_reg_info, xp_reg_info->Master()); 655fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 656fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Redirect 32-bit vector's master storage to 128-bit vector. 657fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell info->SetMaster(xp_reg_info); 658fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 65976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko RegStorage dp_reg = RegStorage::FloatSolo64(sp_reg_num); 660091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee RegisterInfo* dp_reg_info = GetRegInfo(dp_reg); 661fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Redirect 64-bit vector's master storage to 128-bit vector. 662fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell dp_reg_info->SetMaster(xp_reg_info); 66376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // Singles should show a single 32-bit mask bit, at first referring to the low half. 66476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko DCHECK_EQ(info->StorageMask(), 0x1U); 66576af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko } 66676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko 667dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 66876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // Alias 32bit W registers to corresponding 64bit X registers. 66976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko GrowableArray<RegisterInfo*>::Iterator w_it(®_pool_->core_regs_); 67076af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko for (RegisterInfo* info = w_it.Next(); info != nullptr; info = w_it.Next()) { 67176af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko int x_reg_num = info->GetReg().GetRegNum(); 67276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko RegStorage x_reg = RegStorage::Solo64(x_reg_num); 67376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko RegisterInfo* x_reg_info = GetRegInfo(x_reg); 67476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // 64bit X register's master storage should refer to itself. 67576af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko DCHECK_EQ(x_reg_info, x_reg_info->Master()); 67676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // Redirect 32bit W master storage to 64bit X. 67776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko info->SetMaster(x_reg_info); 67876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko // 32bit W should show a single 32-bit mask bit, at first referring to the low half. 67976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko DCHECK_EQ(info->StorageMask(), 0x1U); 68076af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko } 681efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 682091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee 683091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods. 684091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee // TODO: adjust for x86/hard float calling convention. 685091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_core_reg_ = 2; 686091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_sp_reg_ = 2; 687091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee reg_pool_->next_dp_reg_ = 1; 688efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 689efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 69060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjiint X86Mir2Lir::VectorRegisterSize() { 69160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return 128; 69260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 69360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 694b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Aint X86Mir2Lir::NumReservableVectorRegisters(bool long_or_fp) { 695b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int num_vector_temps = cu_->target64 ? xp_temps_64.size() : xp_temps_32.size(); 696b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 697b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Leave a few temps for use by backend as scratch. 698b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return long_or_fp ? num_vector_temps - 2 : num_vector_temps - 1; 69960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 70060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 7011fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::SpillCoreRegs() { 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 StoreBaseDisp(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 7181fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::UnSpillCoreRegs() { 7191fd3346740dfb7f47be9922312b68a4227fada96buzbee if (num_core_spills_ == 0) { 720efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return; 721efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 722efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Spill mask not including fake return address register 723091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 7249ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 725c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov OpSize size = cu_->target64 ? k64 : k32; 726efc6369224b036a1fb77849f7ae65b3492c832c0buzbee for (int reg = 0; mask; mask >>= 1, reg++) { 727efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (mask & 0x1) { 728c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov LoadBaseDisp(rs_rX86_SP, offset, cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg), 729c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov size, kNotVolatile); 7309ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko offset += GetInstructionSetPointerSize(cu_->instruction_set); 731efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 732efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 733efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 734efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 735c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovvoid X86Mir2Lir::SpillFPRegs() { 736c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (num_fp_spills_ == 0) { 737c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov return; 738c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 739c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov uint32_t mask = fp_spill_mask_; 740c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * (num_fp_spills_ + num_core_spills_)); 741c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (int reg = 0; mask; mask >>= 1, reg++) { 742c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (mask & 0x1) { 743c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov StoreBaseDisp(rs_rX86_SP, offset, RegStorage::FloatSolo64(reg), 744c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov k64, kNotVolatile); 745c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov offset += sizeof(double); 746c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 747c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 748c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov} 749c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkovvoid X86Mir2Lir::UnSpillFPRegs() { 750c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (num_fp_spills_ == 0) { 751c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov return; 752c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 753c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov uint32_t mask = fp_spill_mask_; 754c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * (num_fp_spills_ + num_core_spills_)); 755c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov for (int reg = 0; mask; mask >>= 1, reg++) { 756c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov if (mask & 0x1) { 757c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov LoadBaseDisp(rs_rX86_SP, offset, RegStorage::FloatSolo64(reg), 758c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov k64, kNotVolatile); 759c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov offset += sizeof(double); 760c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 761c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov } 762c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov} 763c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 764c380191f3048db2a3796d65db8e5d5a5e7b08c65Serguei Katkov 7652ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::IsUnconditionalBranch(LIR* lir) { 766cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32); 767efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 768efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 769674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoRegisterClass X86Mir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) { 770e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu // X86_64 can handle any size. 771dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 77206839f868c9c4bb1f2f6333f9e88a560e80bcad8Chao-ying Fu return RegClassBySize(size); 773e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } 774e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu 775674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko if (UNLIKELY(is_volatile)) { 776674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // On x86, atomic 64-bit load/store requires an fp register. 777674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // Smaller aligned load/store is atomic for both core and fp registers. 778674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko if (size == k64 || size == kDouble) { 779674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return kFPReg; 780674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko } 781674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko } 782674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko return RegClassBySize(size); 783674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko} 784674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 785dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena SayapinaX86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena) 78655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell : Mir2Lir(cu, mir_graph, arena), 787dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers base_of_code_(nullptr), store_method_addr_(false), store_method_addr_used_(false), 78855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell method_address_insns_(arena, 100, kGrowableArrayMisc), 78955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell class_type_address_insns_(arena, 100, kGrowableArrayMisc), 790ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell call_method_insns_(arena, 100, kGrowableArrayMisc), 791dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina stack_decrement_(nullptr), stack_increment_(nullptr), 792d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell const_vectors_(nullptr) { 793d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell store_method_addr_used_ = false; 794dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (kIsDebugBuild) { 795dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers for (int i = 0; i < kX86Last; i++) { 796dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (X86Mir2Lir::EncodingMap[i].opcode != i) { 797dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers LOG(FATAL) << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name 798d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell << " is wrong: expecting " << i << ", seeing " 799d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode); 800dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers } 801efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 802efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 803dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (cu_->target64) { 8049ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_SP = rs_rX86_SP_64; 8059ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 8069ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG0 = rs_rDI; 8079ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG1 = rs_rSI; 8089ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG2 = rs_rDX; 8099ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG3 = rs_rCX; 81058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_ARG4 = rs_r8; 81158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_ARG5 = rs_r9; 81258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG0 = rs_fr0; 81358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG1 = rs_fr1; 81458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG2 = rs_fr2; 81558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG3 = rs_fr3; 81658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG4 = rs_fr4; 81758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG5 = rs_fr5; 81858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG6 = rs_fr6; 81958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG7 = rs_fr7; 8209ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG0 = rDI; 8219ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG1 = rSI; 8229ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG2 = rDX; 8239ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG3 = rCX; 82458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_ARG4 = r8; 82558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_ARG5 = r9; 82658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG0 = fr0; 82758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG1 = fr1; 82858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG2 = fr2; 82958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG3 = fr3; 83058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG4 = fr4; 83158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG5 = fr5; 83258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG6 = fr6; 83358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG7 = fr7; 83455884bc1e2e1b324809b462455ccaf5811ffafd8Mark Mendell rs_rX86_INVOKE_TGT = rs_rDI; 8359ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } else { 8369ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_SP = rs_rX86_SP_32; 8379ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko 8389ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG0 = rs_rAX; 8399ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG1 = rs_rCX; 8409ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG2 = rs_rDX; 8419ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_ARG3 = rs_rBX; 84258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_ARG4 = RegStorage::InvalidReg(); 84358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_ARG5 = RegStorage::InvalidReg(); 84458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG0 = rs_rAX; 84558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG1 = rs_rCX; 84658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG2 = rs_rDX; 84758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG3 = rs_rBX; 84858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG4 = RegStorage::InvalidReg(); 84958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG5 = RegStorage::InvalidReg(); 85058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG6 = RegStorage::InvalidReg(); 85158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rs_rX86_FARG7 = RegStorage::InvalidReg(); 8529ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG0 = rAX; 8539ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG1 = rCX; 8549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG2 = rDX; 8559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_ARG3 = rBX; 85658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG0 = rAX; 85758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG1 = rCX; 85858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG2 = rDX; 85958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rX86_FARG3 = rBX; 86055884bc1e2e1b324809b462455ccaf5811ffafd8Mark Mendell rs_rX86_INVOKE_TGT = rs_rAX; 86158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // TODO(64): Initialize with invalid reg 86258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// rX86_ARG4 = RegStorage::InvalidReg(); 86358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// rX86_ARG5 = RegStorage::InvalidReg(); 8649ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko } 8659ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_RET0 = rs_rAX; 8669ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_RET1 = rs_rDX; 8679ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rs_rX86_COUNT = rs_rCX; 8689ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_RET0 = rAX; 8699ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_RET1 = rDX; 8709ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_INVOKE_TGT = rAX; 8719ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko rX86_COUNT = rCX; 8721fd3346740dfb7f47be9922312b68a4227fada96buzbee} 8731fd3346740dfb7f47be9922312b68a4227fada96buzbee 874862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph, 875862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee ArenaAllocator* const arena) { 876dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina return new X86Mir2Lir(cu, mir_graph, arena); 877efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 878efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 879984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe// Not used in x86(-64) 880984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas GampeRegStorage X86Mir2Lir::LoadHelper(QuickEntrypointEnum trampoline) { 8812f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe LOG(FATAL) << "Unexpected use of LoadHelper in x86"; 8822f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe return RegStorage::InvalidReg(); 8832f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe} 8842f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe 885b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave AllisonLIR* X86Mir2Lir::CheckSuspendUsingLoad() { 88669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // First load the pointer in fs:[suspend-trigger] into eax 88769dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // Then use a test instruction to indirect via that address. 888dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison if (cu_->target64) { 889dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison NewLIR2(kX86Mov64RT, rs_rAX.GetReg(), 890dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison Thread::ThreadSuspendTriggerOffset<8>().Int32Value()); 891dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison } else { 892dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison NewLIR2(kX86Mov32RT, rs_rAX.GetReg(), 893dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison Thread::ThreadSuspendTriggerOffset<4>().Int32Value()); 894dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison } 89569dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison return NewLIR3(kX86Test32RM, rs_rAX.GetReg(), rs_rAX.GetReg(), 0); 896b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison} 897b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison 8982ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t X86Mir2Lir::GetTargetInstFlags(int opcode) { 899409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 9001fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].flags; 9011bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 9021bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 9032ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstName(int opcode) { 904409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 9051fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].name; 9061bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 9071bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 9082ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstFmt(int opcode) { 909409fe94ad529d9334587be80b9f6a3d166805508buzbee DCHECK(!IsPseudoLirOp(opcode)); 9101fd3346740dfb7f47be9922312b68a4227fada96buzbee return X86Mir2Lir::EncodingMap[opcode].fmt; 9111bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee} 9121bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee 913d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbeevoid X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) { 914d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Can we do this directly to memory? 915d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee rl_dest = UpdateLocWide(rl_dest); 916d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee if ((rl_dest.location == kLocDalvikFrame) || 917d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee (rl_dest.location == kLocCompilerTemp)) { 918d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_lo = Low32Bits(value); 919d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int32_t val_hi = High32Bits(value); 920a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu int r_base = rs_rX86_SP.GetReg(); 921d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee int displacement = SRegOffset(rl_dest.s_reg_low); 922d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 9238dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 9242700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LIR * store = NewLIR3(kX86Mov32MI, r_base, displacement + LOWORD_OFFSET, val_lo); 925d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2, 926d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 9272700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee store = NewLIR3(kX86Mov32MI, r_base, displacement + HIWORD_OFFSET, val_hi); 928d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2, 929d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee false /* is_load */, true /* is64bit */); 930d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee return; 931d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee } 932d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee 933d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee // Just use the standard code to do the generation. 934d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee Mir2Lir::GenConstWide(rl_dest, value); 935d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee} 936e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 937e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell// TODO: Merge with existing RegLocation dumper in vreg_analysis.cc 938e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendellvoid X86Mir2Lir::DumpRegLocation(RegLocation loc) { 939e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell LOG(INFO) << "location: " << loc.location << ',' 940e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.wide ? " w" : " ") 941e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.defined ? " D" : " ") 942e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.is_const ? " c" : " ") 943e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.fp ? " F" : " ") 944e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.core ? " C" : " ") 945e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.ref ? " r" : " ") 946e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.high_word ? " h" : " ") 947e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << (loc.home ? " H" : " ") 9482700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee << ", low: " << static_cast<int>(loc.reg.GetLowReg()) 94900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee << ", high: " << static_cast<int>(loc.reg.GetHighReg()) 950e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", s_reg: " << loc.s_reg_low 951e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell << ", orig: " << loc.orig_sreg; 952e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell} 953e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell 95467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::Materialize() { 95567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // A good place to put the analysis before starting. 95667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell AnalyzeMIR(); 95767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 95867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell // Now continue with regular code generation. 95967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell Mir2Lir::Materialize(); 96067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell} 96167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell 96249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Haovoid X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type, 96355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell SpecialTargetRegister symbolic_reg) { 96455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 96555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 96655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 96755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 96855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 96949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 97049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 97149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 97249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 97355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 97449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the move instruction with the unique pointer and save index, dex_file, and type. 975ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, 976ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe TargetReg(symbolic_reg, kNotWide).GetReg(), 97749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<int>(target_method_id_ptr), target_method_idx, 97849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 97955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 98055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell method_address_insns_.Insert(move); 98155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 98255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 983e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shihvoid X86Mir2Lir::LoadClassType(const DexFile& dex_file, uint32_t type_idx, 984e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih SpecialTargetRegister symbolic_reg) { 98555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 98655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit move immediate instruction, that will be filled 98755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 98855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 98955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 990e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih const DexFile::TypeId& id = dex_file.GetTypeId(type_idx); 99155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell uintptr_t ptr = reinterpret_cast<uintptr_t>(&id); 99255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 99355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Generate the move instruction with the unique pointer and save index and type. 994ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, 995ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe TargetReg(symbolic_reg, kNotWide).GetReg(), 996e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih static_cast<int>(ptr), type_idx, 997e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih WrapPointer(const_cast<DexFile*>(&dex_file))); 99855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(move); 99955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell class_type_address_insns_.Insert(move); 100055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 100155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 100249161cef10a308aedada18e9aa742498d6e6c8c7Jeff HaoLIR *X86Mir2Lir::CallWithLinkerFixup(const MethodReference& target_method, InvokeType type) { 100355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell /* 100455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * For x86, just generate a 32 bit call relative instruction, that will be filled 100555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * in at 'link time'. For now, put a unique value based on target to ensure that 100655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell * code deduplication works. 100755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell */ 100849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao int target_method_idx = target_method.dex_method_index; 100949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = target_method.dex_file; 101049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx); 101149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id); 101249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao 101349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao // Generate the call instruction with the unique pointer and save index, dex_file, and type. 101449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao LIR *call = RawLIR(current_dalvik_offset_, kX86CallI, static_cast<int>(target_method_id_ptr), 101549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, WrapPointer(const_cast<DexFile*>(target_dex_file)), type); 101655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell AppendLIR(call); 101755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell call_method_insns_.Insert(call); 101855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell return call; 101955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 102055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 102155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::InstallLiteralPools() { 102255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // These are handled differently for x86. 102355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(code_literal_list_ == nullptr); 102455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(method_literal_list_ == nullptr); 102555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK(class_literal_list_ == nullptr); 102655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 1027d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1028b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (const_vectors_ != nullptr) { 1029b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Vector literals must be 16-byte aligned. The header that is placed 1030b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // in the code section causes misalignment so we take it into account. 1031b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Otherwise, we are sure that for x86 method is aligned to 16. 1032b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A DCHECK_EQ(GetInstructionSetAlignment(cu_->instruction_set), 16u); 1033b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A uint32_t bytes_to_fill = (0x10 - ((code_buffer_.size() + sizeof(OatQuickMethodHeader)) & 0xF)) & 0xF; 1034b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A while (bytes_to_fill > 0) { 1035d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell code_buffer_.push_back(0); 1036b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bytes_to_fill--; 1037d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1038b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1039d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell for (LIR *p = const_vectors_; p != nullptr; p = p->next) { 1040547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[0]); 1041547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[1]); 1042547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[2]); 1043547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PushWord(&code_buffer_, p->operands[3]); 1044d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1045d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1046d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 104755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for methods. 104855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell for (uint32_t i = 0; i < method_address_insns_.Size(); i++) { 104955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell LIR* p = method_address_insns_.Get(i); 105055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 105149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[2]; 105249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 105349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3])); 105455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 105555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 105655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 105755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->compiler_driver->AddMethodPatch(cu_->dex_file, cu_->class_def_idx, 105855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->method_idx, cu_->invoke_type, 105949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, target_dex_file, 106049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<InvokeType>(p->operands[4]), 106155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell patch_offset); 106255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 106355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 106455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // Handle the fixups for class types. 106555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell for (uint32_t i = 0; i < class_type_address_insns_.Size(); i++) { 106655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell LIR* p = class_type_address_insns_.Get(i); 106755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86Mov32RI); 1068e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih 1069e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih const DexFile* class_dex_file = 1070e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3])); 107149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[2]; 107255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 107355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 107455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 107555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->compiler_driver->AddClassPatch(cu_->dex_file, cu_->class_def_idx, 1076e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih cu_->method_idx, target_method_idx, class_dex_file, 1077e7f82e2515f47f3c3292281312d7031a34a58ffcFred Shih patch_offset); 107855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 107955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 108055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And now the PC-relative calls to methods. 108155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell for (uint32_t i = 0; i < call_method_insns_.Size(); i++) { 108255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell LIR* p = call_method_insns_.Get(i); 108355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell DCHECK_EQ(p->opcode, kX86CallI); 108449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao uint32_t target_method_idx = p->operands[1]; 108549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile* target_dex_file = 108649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2])); 108755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 108855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // The offset to patch is the last 4 bytes of the instruction. 108955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell int patch_offset = p->offset + p->flags.size - 4; 109055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell cu_->compiler_driver->AddRelativeCodePatch(cu_->dex_file, cu_->class_def_idx, 109149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao cu_->method_idx, cu_->invoke_type, 109249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao target_method_idx, target_dex_file, 109349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao static_cast<InvokeType>(p->operands[3]), 109455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell patch_offset, -4 /* offset */); 109555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 109655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 109755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // And do the normal processing. 109855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell Mir2Lir::InstallLiteralPools(); 109955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell} 110055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell 110170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolovbool X86Mir2Lir::GenInlinedArrayCopyCharArray(CallInfo* info) { 110270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_src = info->args[0]; 110370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_srcPos = info->args[1]; 110470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_dst = info->args[2]; 110570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_dstPos = info->args[3]; 110670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov RegLocation rl_length = info->args[4]; 110770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (rl_srcPos.is_const && (mir_graph_->ConstantValue(rl_srcPos) < 0)) { 110870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov return false; 110970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 111070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (rl_dstPos.is_const && (mir_graph_->ConstantValue(rl_dstPos) < 0)) { 111170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov return false; 111270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 111370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov ClobberCallerSave(); 11145a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LockCallTemps(); // Using fixed registers. 11155a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov RegStorage tmp_reg = cu_->target64 ? rs_r11 : rs_rBX; 11165a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_src, rs_rAX); 11175a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dst, rs_rCX); 11185a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* src_dst_same = OpCmpBranch(kCondEq, rs_rAX, rs_rCX, nullptr); 11195a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* src_null_branch = OpCmpImmBranch(kCondEq, rs_rAX, 0, nullptr); 11205a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* dst_null_branch = OpCmpImmBranch(kCondEq, rs_rCX, 0, nullptr); 11215a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_length, rs_rDX); 11225a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // If the length of the copy is > 128 characters (256 bytes) or negative then go slow path. 11235a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* len_too_big = OpCmpImmBranch(kCondHi, rs_rDX, 128, nullptr); 11245a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_src, rs_rAX); 11255a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadWordDisp(rs_rAX, mirror::Array::LengthOffset().Int32Value(), rs_rAX); 112670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* src_bad_len = nullptr; 112770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* srcPos_negative = nullptr; 112870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (!rl_srcPos.is_const) { 11295a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_srcPos, tmp_reg); 11305a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov srcPos_negative = OpCmpImmBranch(kCondLt, tmp_reg, 0, nullptr); 11315a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov OpRegReg(kOpAdd, tmp_reg, rs_rDX); 11325a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov src_bad_len = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr); 113370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 11345a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov int32_t pos_val = mir_graph_->ConstantValue(rl_srcPos.orig_sreg); 113570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (pos_val == 0) { 11365a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov src_bad_len = OpCmpBranch(kCondLt, rs_rAX, rs_rDX, nullptr); 113770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } else { 11385a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov OpRegRegImm(kOpAdd, tmp_reg, rs_rDX, pos_val); 11395a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov src_bad_len = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr); 114070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 114170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 114270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* dstPos_negative = nullptr; 114370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* dst_bad_len = nullptr; 114470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadValueDirectFixed(rl_dst, rs_rAX); 114570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadWordDisp(rs_rAX, mirror::Array::LengthOffset().Int32Value(), rs_rAX); 114670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (!rl_dstPos.is_const) { 11475a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dstPos, tmp_reg); 11485a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov dstPos_negative = OpCmpImmBranch(kCondLt, tmp_reg, 0, nullptr); 11495a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov OpRegRegReg(kOpAdd, tmp_reg, tmp_reg, rs_rDX); 11505a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov dst_bad_len = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, 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 { 11565a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov OpRegRegImm(kOpAdd, tmp_reg, rs_rDX, pos_val); 11575a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov dst_bad_len = OpCmpBranch(kCondLt, rs_rAX, tmp_reg, nullptr); 115870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 115970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov } 11605a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // Everything is checked now. 11615a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_src, rs_rAX); 11625a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dst, tmp_reg); 11635a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_srcPos, rs_rCX); 116470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov NewLIR5(kX86Lea32RA, rs_rAX.GetReg(), rs_rAX.GetReg(), 11655a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov rs_rCX.GetReg(), 1, mirror::Array::DataOffset(2).Int32Value()); 11665a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // RAX now holds the address of the first src element to be copied. 116770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 11685a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_dstPos, rs_rCX); 11695a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov NewLIR5(kX86Lea32RA, tmp_reg.GetReg(), tmp_reg.GetReg(), 11705a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov rs_rCX.GetReg(), 1, mirror::Array::DataOffset(2).Int32Value() ); 11715a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // RBX now holds the address of the first dst element to be copied. 117270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 11735a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // Check if the number of elements to be copied is odd or even. If odd 117470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov // then copy the first element (so that the remaining number of elements 117570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov // is even). 11765a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LoadValueDirectFixed(rl_length, rs_rCX); 117770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpRegImm(kOpAnd, rs_rCX, 1); 117870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* jmp_to_begin_loop = OpCmpImmBranch(kCondEq, rs_rCX, 0, nullptr); 117970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpRegImm(kOpSub, rs_rDX, 1); 118070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadBaseIndexedDisp(rs_rAX, rs_rDX, 1, 0, rs_rCX, kSignedHalf); 11815a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov StoreBaseIndexedDisp(tmp_reg, rs_rDX, 1, 0, rs_rCX, kSignedHalf); 118270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 11835a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov // Since the remaining number of elements is even, we will copy by 118470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov // two elements at a time. 11855a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* beginLoop = NewLIR0(kPseudoTargetLabel); 11865a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov LIR* jmp_to_ret = OpCmpImmBranch(kCondEq, rs_rDX, 0, nullptr); 118770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpRegImm(kOpSub, rs_rDX, 2); 118870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LoadBaseIndexedDisp(rs_rAX, rs_rDX, 1, 0, rs_rCX, kSingle); 11895a5e85693b1d5952d88377be5826068b67b0dcecDaniilSokolov StoreBaseIndexedDisp(tmp_reg, rs_rDX, 1, 0, rs_rCX, kSingle); 119070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov OpUnconditionalBranch(beginLoop); 119170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR *check_failed = NewLIR0(kPseudoTargetLabel); 119270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR* launchpad_branch = OpUnconditionalBranch(nullptr); 119370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov LIR *return_point = NewLIR0(kPseudoTargetLabel); 119470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov jmp_to_ret->target = return_point; 119570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov jmp_to_begin_loop->target = beginLoop; 119670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov src_dst_same->target = check_failed; 119770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov len_too_big->target = check_failed; 119870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov src_null_branch->target = check_failed; 119970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (srcPos_negative != nullptr) 120070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov srcPos_negative ->target = check_failed; 120170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (src_bad_len != nullptr) 120270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov src_bad_len->target = check_failed; 120370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov dst_null_branch->target = check_failed; 120470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (dstPos_negative != nullptr) 120570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov dstPos_negative->target = check_failed; 120670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov if (dst_bad_len != nullptr) 120770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov dst_bad_len->target = check_failed; 120870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov AddIntrinsicSlowPath(info, launchpad_branch, return_point); 120970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov return true; 121070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov} 121170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 121270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov 12134028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell/* 12144028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * Fast string.index_of(I) & (II). Inline check for simple case of char <= 0xffff, 12154028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * otherwise bails to standard library code. 12164028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell */ 12174028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendellbool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) { 12184028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_obj = info->args[0]; 12194028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_char = info->args[1]; 1220a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee RegLocation rl_start; // Note: only present in III flavor or IndexOf. 12218bd698fb785b58302be684efcbb24a0b8c6535d7nikolay serdjuk // RBX is promotable in 64-bit mode. 1222c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk RegStorage rs_tmp = cu_->target64 ? rs_r11 : rs_rBX; 1223c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk int start_value = -1; 12244028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12254028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell uint32_t char_value = 12264028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell rl_char.is_const ? mir_graph_->ConstantValue(rl_char.orig_sreg) : 0; 12274028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12284028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (char_value > 0xFFFF) { 12294028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to punt to the real String.indexOf. 12304028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return false; 12314028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 12324028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12334028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Okay, we are commited to inlining this. 1234c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EAX: 16 bit character being searched. 1235c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // ECX: count: number of words to be searched. 1236c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EDI: String being searched. 1237c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EDX: temporary during execution. 1238c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // EBX or R11: temporary during execution (depending on mode). 1239c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // REP SCASW: search instruction. 1240c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 12418bd698fb785b58302be684efcbb24a0b8c6535d7nikolay serdjuk FlushAllRegs(); 1242c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1243a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee RegLocation rl_return = GetReturn(kCoreReg); 12444028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell RegLocation rl_dest = InlineTarget(info); 12454028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12464028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the string non-NULL? 12472700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_obj, rs_rDX); 12482700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee GenNullCheck(rs_rDX, info->opt_flags); 12493bc8615332b7848dec8c2297a40f7e4d176c0efbVladimir Marko info->opt_flags |= MIR_IGNORE_NULL_CHECK; // Record that we've null checked. 12504028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 1251c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk LIR *slowpath_branch = nullptr, *length_compare = nullptr; 1252c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1253c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We need the value in EAX. 12544028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_char.is_const) { 12552700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rs_rAX, char_value); 12564028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1257c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Does the character fit in 16 bits? Compare it at runtime. 12582700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadValueDirectFixed(rl_char, rs_rAX); 12593a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang slowpath_branch = OpCmpImmBranch(kCondGt, rs_rAX, 0xFFFF, nullptr); 12604028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 12614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // From here down, we know that we are looking for a char that fits in 16 bits. 1263e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of reference to data array within the String object. 1264e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int value_offset = mirror::String::ValueOffset().Int32Value(); 1265e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Location of count within the String object. 1266e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int count_offset = mirror::String::CountOffset().Int32Value(); 1267e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Starting offset within data array. 1268e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int offset_offset = mirror::String::OffsetOffset().Int32Value(); 1269e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // Start of char data with array_. 1270e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); 12714028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 127269dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison // Compute the number of words to search in to rCX. 127369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison Load32Disp(rs_rDX, count_offset, rs_rCX); 127469dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison 1275dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // Possible signal here due to null pointer dereference. 1276dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // Note that the signal handler will expect the top word of 1277dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // the stack to be the ArtMethod*. If the PUSH edi instruction 1278dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // below is ahead of the load above then this will not be true 1279dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison // and the signal handler will not work. 1280dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison MarkPossibleNullPointerException(0); 1281c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1282dfd3b47813c14c5f1607cbe7b10a28b1b2f29cbcDave Allison if (!cu_->target64) { 12838bd698fb785b58302be684efcbb24a0b8c6535d7nikolay serdjuk // EDI is promotable in 32-bit mode. 1284c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk NewLIR1(kX86Push32R, rs_rDI.GetReg()); 1285c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk } 12864028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 12874028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (zero_based) { 1288c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Start index is not present. 12894028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to handle an empty string. Use special instruction JECXZ. 12904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare = NewLIR0(kX86Jecxz8); 1291c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1292c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Copy the number of words to search in a temporary register. 1293c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We will use the register at the end to calculate result. 1294c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpMov, rs_tmp, rs_rCX); 12954028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1296c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Start index is present. 1297a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee rl_start = info->args[2]; 1298c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 12994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We have to offset by the start index. 13004028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (rl_start.is_const) { 13014028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = mir_graph_->ConstantValue(rl_start.orig_sreg); 13024028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell start_value = std::max(start_value, 0); 13034028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13044028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Is the start > count? 13052700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee length_compare = OpCmpImmBranch(kCondLe, rs_rCX, start_value, nullptr); 1306c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegImm(kOpMov, rs_rDI, start_value); 1307c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1308c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Copy the number of words to search in a temporary register. 1309c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We will use the register at the end to calculate result. 1310c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpMov, rs_tmp, rs_rCX); 13114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13124028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell if (start_value != 0) { 1313c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Decrease the number of words to search by the start index. 13142700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee OpRegImm(kOpSub, rs_rCX, start_value); 13154028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13164028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1317c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Handle "start index < 0" case. 1318c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk if (!cu_->target64 && rl_start.location != kLocPhysReg) { 1319a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov // Load the start index from stack, remembering that we pushed EDI. 1320c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk int displacement = SRegOffset(rl_start.s_reg_low) + sizeof(uint32_t); 132174de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 132274de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko Load32Disp(rs_rX86_SP, displacement, rs_rDI); 132374de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko // Dalvik register annotation in LoadBaseIndexedDisp() used wrong offset. Fix it. 132474de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko DCHECK(!DECODE_ALIAS_INFO_WIDE(last_lir_insn_->flags.alias_info)); 132574de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko int reg_id = DECODE_ALIAS_INFO_REG(last_lir_insn_->flags.alias_info) - 1; 132674de63bb1cc275b411cae28a96f9b3a78b939bc2Vladimir Marko AnnotateDalvikRegAccess(last_lir_insn_, reg_id, true, false); 1327c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk } else { 1328c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk LoadValueDirectFixed(rl_start, rs_rDI); 13294028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 1330c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpXor, rs_tmp, rs_tmp); 1331c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpCmp, rs_rDI, rs_tmp); 1332c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpCondRegReg(kOpCmov, kCondLt, rs_rDI, rs_tmp); 1333c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1334c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // The length of the string should be greater than the start index. 1335c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk length_compare = OpCmpBranch(kCondLe, rs_rCX, rs_rDI, nullptr); 1336c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1337c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Copy the number of words to search in a temporary register. 1338c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // We will use the register at the end to calculate result. 1339c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpMov, rs_tmp, rs_rCX); 1340c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1341c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Decrease the number of words to search by the start index. 1342c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpSub, rs_rCX, rs_rDI); 13434028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13444028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13454028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 1346c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // Load the address of the string into EDI. 1347c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk // In case of start index we have to add the address to existing value in EDI. 1348e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET. 1349c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk if (zero_based || (!zero_based && rl_start.is_const && start_value == 0)) { 1350c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk Load32Disp(rs_rDX, offset_offset, rs_rDI); 13514028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } else { 1352c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegMem(kOpAdd, rs_rDI, rs_rDX, offset_offset); 13534028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 1354c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegImm(kOpLsl, rs_rDI, 1); 1355c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegMem(kOpAdd, rs_rDI, rs_rDX, value_offset); 1356c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegImm(kOpAdd, rs_rDI, data_offset); 13574028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13584028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // EDI now contains the start of the string to be searched. 13594028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // We are all prepared to do the search for the character. 13604028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell NewLIR0(kX86RepneScasw); 13614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Did we find a match? 13634028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR* failed_branch = OpCondBranch(kCondNe, nullptr); 13644028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13654028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // yes, we matched. Compute the index of the result. 1366c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk OpRegReg(kOpSub, rs_tmp, rs_rCX); 1367c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rs_tmp.GetReg(), -1); 1368c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 13694028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *all_done = NewLIR1(kX86Jmp8, 0); 13704028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13714028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Failed to match; return -1. 13724028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *not_found = NewLIR0(kPseudoTargetLabel); 13734028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell length_compare->target = not_found; 13744028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell failed_branch->target = not_found; 13752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee LoadConstantNoClobber(rl_return.reg, -1); 13764028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13774028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // And join up at the end. 13784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell all_done->target = NewLIR0(kPseudoTargetLabel); 1379c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk 1380c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk if (!cu_->target64) 1381c3561ae381960cbd52a83b7591504f158ec06920nikolay serdjuk NewLIR1(kX86Pop32R, rs_rDI.GetReg()); 13824028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13834028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell // Out of line code returns here. 13843a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang if (slowpath_branch != nullptr) { 13854028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell LIR *return_point = NewLIR0(kPseudoTargetLabel); 13863a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang AddIntrinsicSlowPath(info, slowpath_branch, return_point); 13874028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell } 13884028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 13894028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell StoreValue(rl_dest, rl_return); 13904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell return true; 13914028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell} 13924028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell 139335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shenstatic bool ARTRegIDToDWARFRegID(bool is_x86_64, int art_reg_id, int* dwarf_reg_id) { 139435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen if (is_x86_64) { 139535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen switch (art_reg_id) { 1396bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 3 : *dwarf_reg_id = 3; return true; // %rbx 139735e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // This is the only discrepancy between ART & DWARF register numbering. 1398bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 5 : *dwarf_reg_id = 6; return true; // %rbp 1399bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 12: *dwarf_reg_id = 12; return true; // %r12 1400bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 13: *dwarf_reg_id = 13; return true; // %r13 1401bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 14: *dwarf_reg_id = 14; return true; // %r14 1402bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 15: *dwarf_reg_id = 15; return true; // %r15 1403bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe default: return false; // Should not get here 140435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 140535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } else { 140635e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen switch (art_reg_id) { 1407bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 5: *dwarf_reg_id = 5; return true; // %ebp 1408bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 6: *dwarf_reg_id = 6; return true; // %esi 1409bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe case 7: *dwarf_reg_id = 7; return true; // %edi 1410bda2722ba62e5be9f9fd6a6eb0db8259bb383629Andreas Gampe default: return false; // Should not get here 141135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 1412ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1413ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1414ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1415547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shenstd::vector<uint8_t>* X86Mir2Lir::ReturnFrameDescriptionEntry() { 1416547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen std::vector<uint8_t>* cfi_info = new std::vector<uint8_t>; 1417ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1418ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Generate the FDE for the method. 1419ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell DCHECK_NE(data_offset_, 0U); 1420ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1421e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban WriteFDEHeader(cfi_info, cu_->target64); 1422e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban WriteFDEAddressRange(cfi_info, data_offset_, cu_->target64); 142335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 1424ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // The instructions in the FDE. 1425ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_decrement_ != nullptr) { 1426ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Advance LOC to just past the stack decrement. 1427ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t pc = NEXT_LIR(stack_decrement_)->offset; 1428547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, pc); 1429ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1430ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Now update the offset to the call frame: DW_CFA_def_cfa_offset frame_size. 1431547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_def_cfa_offset(cfi_info, frame_size_); 1432ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 143335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // Handle register spills 143435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen const uint32_t kSpillInstLen = (cu_->target64) ? 5 : 4; 143535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen const int kDataAlignmentFactor = (cu_->target64) ? -8 : -4; 143635e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum()); 143735e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen int offset = -(GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_); 143835e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen for (int reg = 0; mask; mask >>= 1, reg++) { 143935e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen if (mask & 0x1) { 144035e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen pc += kSpillInstLen; 144135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 144235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // Advance LOC to pass this instruction 1443547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, kSpillInstLen); 144435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 144535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen int dwarf_reg_id; 144635e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen if (ARTRegIDToDWARFRegID(cu_->target64, reg, &dwarf_reg_id)) { 1447547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen // DW_CFA_offset_extended_sf reg offset 1448547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_offset_extended_sf(cfi_info, dwarf_reg_id, offset / kDataAlignmentFactor); 144935e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 145035e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 145135e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen offset += GetInstructionSetPointerSize(cu_->instruction_set); 145235e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 145335e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen } 145435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen 1455ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We continue with that stack until the epilogue. 1456ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (stack_increment_ != nullptr) { 1457ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell uint32_t new_pc = NEXT_LIR(stack_increment_)->offset; 1458547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, new_pc - pc); 1459ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1460ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // We probably have code snippets after the epilogue, so save the 1461ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // current state: DW_CFA_remember_state. 1462547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_remember_state(cfi_info); 1463ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 146435e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // We have now popped the stack: DW_CFA_def_cfa_offset 4/8. 146535e1e6ad4b50f1adbe9f93fe467766f042491896Tong Shen // There is only the return PC on the stack now. 1466547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_def_cfa_offset(cfi_info, GetInstructionSetPointerSize(cu_->instruction_set)); 1467ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1468ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Everything after that is the same as before the epilogue. 1469ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Stack bump was followed by RET instruction. 1470ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell LIR *post_ret_insn = NEXT_LIR(NEXT_LIR(stack_increment_)); 1471ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell if (post_ret_insn != nullptr) { 1472ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell pc = new_pc; 1473ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell new_pc = post_ret_insn->offset; 1474547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_advance_loc(cfi_info, new_pc - pc); 1475ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell // Restore the state: DW_CFA_restore_state. 1476547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen DW_CFA_restore_state(cfi_info); 1477ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1478ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1479ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell } 1480ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1481547cdfd21ee21e4ab9ca8692d6ef47c62ee7ea52Tong Shen PadCFI(cfi_info); 1482e3ea83811d47152c00abea24a9b420651a33b496Yevgeny Rouban WriteCFILength(cfi_info, cu_->target64); 1483ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1484ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell return cfi_info; 1485ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell} 1486ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell 1487d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) { 1488d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 148960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpReserveVectorRegisters: 149060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji ReserveVectorRegisters(mir); 149160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 149260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpReturnVectorRegisters: 1493b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A ReturnVectorRegisters(mir); 149460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 1495d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell case kMirOpConstVector: 1496d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell GenConst128(bb, mir); 1497d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell break; 1498fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpMoveVector: 1499fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenMoveVector(bb, mir); 1500fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1501fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedMultiply: 1502fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenMultiplyVector(bb, mir); 1503fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1504fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedAddition: 1505fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenAddVector(bb, mir); 1506fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1507fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedSubtract: 1508fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenSubtractVector(bb, mir); 1509fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1510fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedShiftLeft: 1511fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenShiftLeftVector(bb, mir); 1512fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1513fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedSignedShiftRight: 1514fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenSignedShiftRightVector(bb, mir); 1515fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1516fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedUnsignedShiftRight: 1517fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenUnsignedShiftRightVector(bb, mir); 1518fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1519fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedAnd: 1520fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenAndVector(bb, mir); 1521fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1522fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedOr: 1523fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenOrVector(bb, mir); 1524fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1525fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedXor: 1526fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenXorVector(bb, mir); 1527fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1528fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedAddReduce: 1529fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenAddReduceVector(bb, mir); 1530fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1531fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedReduce: 1532fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenReduceVector(bb, mir); 1533fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1534fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kMirOpPackedSet: 1535fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell GenSetVector(bb, mir); 1536fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1537b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler case kMirOpMemBarrier: 1538b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler GenMemBarrier(static_cast<MemBarrierKind>(mir->dalvikInsn.vA)); 1539b5bce7cc9f1130ab4932ba8e6917c362bf871f24Jean Christophe Beyler break; 1540b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kMirOpPackedArrayGet: 1541b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenPackedArrayGet(bb, mir); 1542b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1543b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kMirOpPackedArrayPut: 1544b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenPackedArrayPut(bb, mir); 1545b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1546d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell default: 1547d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell break; 1548d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1549d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1550d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 155160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::ReserveVectorRegisters(MIR* mir) { 1552b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (uint32_t i = mir->dalvikInsn.vA; i <= mir->dalvikInsn.vB; i++) { 155360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage xp_reg = RegStorage::Solo128(i); 155460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegisterInfo *xp_reg_info = GetRegInfo(xp_reg); 155560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji Clobber(xp_reg); 155660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 155760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji for (RegisterInfo *info = xp_reg_info->GetAliasChain(); 155860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info != nullptr; 155960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info = info->GetAliasChain()) { 156060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji if (info->GetReg().IsSingle()) { 156160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji reg_pool_->sp_regs_.Delete(info); 156260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 156360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji reg_pool_->dp_regs_.Delete(info); 156460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 156560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 156660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 156760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 156860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1569b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::ReturnVectorRegisters(MIR* mir) { 1570b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (uint32_t i = mir->dalvikInsn.vA; i <= mir->dalvikInsn.vB; i++) { 157160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage xp_reg = RegStorage::Solo128(i); 157260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegisterInfo *xp_reg_info = GetRegInfo(xp_reg); 157360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 157460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji for (RegisterInfo *info = xp_reg_info->GetAliasChain(); 157560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info != nullptr; 157660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji info = info->GetAliasChain()) { 157760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji if (info->GetReg().IsSingle()) { 157860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji reg_pool_->sp_regs_.Insert(info); 157960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 158060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji reg_pool_->dp_regs_.Insert(info); 158160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 158260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 158360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 158460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 158560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1586d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenConst128(BasicBlock* bb, MIR* mir) { 158760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA); 1588b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest); 1589b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1590d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell uint32_t *args = mir->dalvikInsn.arg; 1591fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int reg = rs_dest.GetReg(); 1592d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Check for all 0 case. 1593d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (args[0] == 0 && args[1] == 0 && args[2] == 0 && args[3] == 0) { 1594d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell NewLIR2(kX86XorpsRR, reg, reg); 1595d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return; 1596d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 159760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 159860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Append the mov const vector to reg opcode. 1599b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AppendOpcodeWithConst(kX86MovdqaRM, reg, mir); 160060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 160160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 160260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::AppendOpcodeWithConst(X86OpCode opcode, int reg, MIR* mir) { 1603b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // The literal pool needs position independent logic. 1604b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A store_method_addr_used_ = true; 1605b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1606b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // To deal with correct memory ordering, reverse order of constants. 1607b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int32_t constants[4]; 1608b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[3] = mir->dalvikInsn.arg[0]; 1609b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[2] = mir->dalvikInsn.arg[1]; 1610b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[1] = mir->dalvikInsn.arg[2]; 1611b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[0] = mir->dalvikInsn.arg[3]; 1612b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1613b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Search if there is already a constant in pool with this value. 1614b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LIR *data_target = ScanVectorLiteral(constants); 1615d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (data_target == nullptr) { 1616b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A data_target = AddVectorLiteral(constants); 1617d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 1618d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1619d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Address the start of the method. 1620d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low); 1621e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu if (rl_method.wide) { 1622e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu rl_method = LoadValueWide(rl_method, kCoreReg); 1623e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } else { 1624e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu rl_method = LoadValue(rl_method, kCoreReg); 1625e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu } 1626d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1627d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // Load the proper value from the literal area. 1628d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // We don't know the proper offset for the value, so pick one that will force 1629d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // 4 byte offset. We will fix this up in the assembler later to have the right 1630d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell // value. 16318dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral); 1632b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LIR *load = NewLIR3(opcode, reg, rl_method.reg.GetReg(), 256 /* bogus */); 1633d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell load->flags.fixup = kFixupLoad; 1634d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell load->target = data_target; 1635d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 1636d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 1637fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenMoveVector(BasicBlock *bb, MIR *mir) { 1638fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 163960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 164060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA); 1641b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest); 164260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src = RegStorage::Solo128(mir->dalvikInsn.vB); 1643b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_dest.GetReg(), rs_src.GetReg()); 1644fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1645fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1646b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::GenMultiplyVectorSignedByte(RegStorage rs_dest_src1, RegStorage rs_src2) { 164760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji /* 164860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * Emulate the behavior of a kSignedByte by separating out the 16 values in the two XMM 164960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * and multiplying 8 at a time before recombining back into one XMM register. 165060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * 165160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * let xmm1, xmm2 be real srcs (keep low bits of 16bit lanes) 165260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm3 is tmp (operate on high bits of 16bit lanes) 165360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * 165460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm3 = xmm1 165560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm1 = xmm1 .* xmm2 165660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm1 = xmm1 & 0x00ff00ff00ff00ff00ff00ff00ff00ff // xmm1 now has low bits 165760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm3 = xmm3 .>> 8 165860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm2 = xmm2 & 0xff00ff00ff00ff00ff00ff00ff00ff00 165960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm2 = xmm2 .* xmm3 // xmm2 now has high bits 166060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji * xmm1 = xmm1 | xmm2 // combine results 166160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji */ 166260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 166360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Copy xmm1. 1664b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_src1_high_tmp = Get128BitRegister(AllocTempDouble()); 1665b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_dest_high_tmp = Get128BitRegister(AllocTempDouble()); 1666b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_src1_high_tmp.GetReg(), rs_src2.GetReg()); 1667b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_dest_high_tmp.GetReg(), rs_dest_src1.GetReg()); 166860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 166960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Multiply low bits. 1670b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // x7 *= x3 167160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji NewLIR2(kX86PmullwRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 167260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 167360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // xmm1 now has low bits. 167460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji AndMaskVectorRegister(rs_dest_src1, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF); 167560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 167660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Prepare high bits for multiplication. 1677b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlwRI, rs_src1_high_tmp.GetReg(), 0x8); 1678b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AndMaskVectorRegister(rs_dest_high_tmp, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00); 167960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 168060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Multiply high bits and xmm2 now has high bits. 1681b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmullwRR, rs_src1_high_tmp.GetReg(), rs_dest_high_tmp.GetReg()); 168260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 168360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Combine back into dest XMM register. 1684b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_src1_high_tmp.GetReg()); 1685b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A} 1686b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1687b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::GenMultiplyVectorLong(RegStorage rs_dest_src1, RegStorage rs_src2) { 1688b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 1689b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * We need to emulate the packed long multiply. 1690b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * For kMirOpPackedMultiply xmm1, xmm0: 1691b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - xmm1 is src/dest 1692b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - xmm0 is src 1693b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Get xmm2 and xmm3 as temp 1694b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Idea is to multiply the lower 32 of each operand with the higher 32 of the other. 1695b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Then add the two results. 1696b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Move it to the upper 32 of the destination 1697b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * - Then multiply the lower 32-bits of the operands and add the result to the destination. 1698b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1699b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * (op dest src ) 1700b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * movdqa %xmm2, %xmm1 1701b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * movdqa %xmm3, %xmm0 1702b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psrlq %xmm3, $0x20 1703b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm3, %xmm2 1704b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psrlq %xmm1, $0x20 1705b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm1, %xmm0 1706b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm3 1707b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psllq %xmm1, $0x20 1708b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm2, %xmm0 1709b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm2 1710b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1711b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * When both the operands are the same, then we need to calculate the lower-32 * higher-32 1712b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * calculation only once. Thus we don't need the xmm3 temp above. That sequence becomes: 1713b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1714b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * (op dest src ) 1715b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * movdqa %xmm2, %xmm1 1716b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psrlq %xmm1, $0x20 1717b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm1, %xmm0 1718b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm1 1719b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * psllq %xmm1, $0x20 1720b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * pmuludq %xmm2, %xmm0 1721b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * paddq %xmm1, %xmm2 1722b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1723b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 1724b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1725b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bool both_operands_same = (rs_dest_src1.GetReg() == rs_src2.GetReg()); 1726b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1727b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector_1; 1728b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector_2; 1729b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rs_tmp_vector_1 = Get128BitRegister(AllocTempDouble()); 1730b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector_1.GetReg(), rs_dest_src1.GetReg()); 1731b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1732b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (both_operands_same == false) { 1733b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rs_tmp_vector_2 = Get128BitRegister(AllocTempDouble()); 1734b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector_2.GetReg(), rs_src2.GetReg()); 1735b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, rs_tmp_vector_2.GetReg(), 0x20); 1736b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmuludqRR, rs_tmp_vector_2.GetReg(), rs_tmp_vector_1.GetReg()); 1737b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 1738b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1739b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, rs_dest_src1.GetReg(), 0x20); 1740b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmuludqRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1741b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1742b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (both_operands_same == false) { 1743b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, rs_dest_src1.GetReg(), rs_tmp_vector_2.GetReg()); 1744b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 1745b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, rs_dest_src1.GetReg(), rs_dest_src1.GetReg()); 1746b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 1747b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 1748b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsllqRI, rs_dest_src1.GetReg(), 0x20); 1749b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PmuludqRR, rs_tmp_vector_1.GetReg(), rs_src2.GetReg()); 1750b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, rs_dest_src1.GetReg(), rs_tmp_vector_1.GetReg()); 175160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 175260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1753fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenMultiplyVector(BasicBlock *bb, MIR *mir) { 175460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 175560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 175660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1757b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 175860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1759fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1760fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1761fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1762fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PmulldRR; 1763fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1764fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1765fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PmullwRR; 1766fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1767fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSingle: 1768fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86MulpsRR; 1769fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1770fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kDouble: 1771fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86MulpdRR; 1772fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 177360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 177460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // HW doesn't support 16x16 byte multiplication so emulate it. 1775b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenMultiplyVectorSignedByte(rs_dest_src1, rs_src2); 1776b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 1777b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1778b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenMultiplyVectorLong(rs_dest_src1, rs_src2); 177960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1780fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1781fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector multiply " << opsize; 1782fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1783fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1784fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1785fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1786fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1787fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenAddVector(BasicBlock *bb, MIR *mir) { 178860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 178960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 179060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1791b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 179260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1793fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1794fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1795fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1796fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PadddRR; 1797fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1798b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1799b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A opcode = kX86PaddqRR; 1800b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1801fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1802fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1803fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PaddwRR; 1804fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1805fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedByte: 1806fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedByte: 1807fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PaddbRR; 1808fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1809fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSingle: 1810fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86AddpsRR; 1811fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1812fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kDouble: 1813fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86AddpdRR; 1814fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1815fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1816fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector addition " << opsize; 1817fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1818fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1819fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1820fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1821fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1822fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenSubtractVector(BasicBlock *bb, MIR *mir) { 182360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 182460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 182560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1826b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 182760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1828fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1829fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1830fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1831fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsubdRR; 1832fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1833b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1834b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A opcode = kX86PsubqRR; 1835b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 1836fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1837fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1838fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsubwRR; 1839fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1840fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedByte: 1841fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedByte: 1842fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsubbRR; 1843fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1844fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSingle: 1845fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86SubpsRR; 1846fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1847fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kDouble: 1848fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86SubpdRR; 1849fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1850fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1851fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector subtraction " << opsize; 1852fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1853fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1854fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1855fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1856fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 185760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::GenShiftByteVector(BasicBlock *bb, MIR *mir) { 1858b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Destination does not need clobbered because it has already been as part 1859b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // of the general packed shift handler (caller of this method). 186060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 186160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 186260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int opcode = 0; 186360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { 186460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpPackedShiftLeft: 186560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji opcode = kX86PsllwRI; 186660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 186760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpPackedSignedShiftRight: 186860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kMirOpPackedUnsignedShiftRight: 1869b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Add support for emulated byte shifts. 187060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji default: 187160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji LOG(FATAL) << "Unsupported shift operation on byte vector " << opcode; 187260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 187360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 187460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1875b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Clear xmm register and return if shift more than byte length. 1876b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int imm = mir->dalvikInsn.vB; 1877b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (imm >= 8) { 1878b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PxorRR, rs_dest_src1.GetReg(), rs_dest_src1.GetReg()); 1879b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 1880b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 188160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 188260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Shift lower values. 188360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 188460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1885b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 1886b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * The above shift will shift the whole word, but that means 1887b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * both the bytes will shift as well. To emulate a byte level 1888b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * shift, we can just throw away the lower (8 - N) bits of the 1889b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * upper byte, and we are done. 1890b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 1891b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A uint8_t byte_mask = 0xFF << imm; 1892b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A uint32_t int_mask = byte_mask; 1893b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int_mask = int_mask << 8 | byte_mask; 1894b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int_mask = int_mask << 8 | byte_mask; 1895b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int_mask = int_mask << 8 | byte_mask; 189660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1897b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // And the destination with the mask 1898b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AndMaskVectorRegister(rs_dest_src1, int_mask, int_mask, int_mask, int_mask); 189960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 190060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 1901fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenShiftLeftVector(BasicBlock *bb, MIR *mir) { 190260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 190360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 190460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1905b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 190660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int imm = mir->dalvikInsn.vB; 1907fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1908fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1909fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1910fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PslldRI; 1911fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1912fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k64: 1913fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsllqRI; 1914fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1915fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1916fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1917fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsllwRI; 1918fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 191960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 192060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 192160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji GenShiftByteVector(bb, mir); 192260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1923fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1924fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector shift left " << opsize; 1925fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1926fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1927fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1928fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1929fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1930fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenSignedShiftRightVector(BasicBlock *bb, MIR *mir) { 193160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 193260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 193360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1934b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 193560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int imm = mir->dalvikInsn.vB; 1936fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1937fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1938fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1939fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsradRI; 1940fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1941fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1942fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1943fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrawRI; 1944fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 194560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 194660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 194760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji GenShiftByteVector(bb, mir); 194860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1949b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k64: 1950b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Implement emulated shift algorithm. 1951fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1952fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector signed shift right " << opsize; 1953fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1954fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1955fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1956fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1957fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1958fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenUnsignedShiftRightVector(BasicBlock *bb, MIR *mir) { 195960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 196060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 196160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1962b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 196360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int imm = mir->dalvikInsn.vB; 1964fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell int opcode = 0; 1965fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 1966fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 1967fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrldRI; 1968fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1969fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k64: 1970fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrlqRI; 1971fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1972fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 1973fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 1974fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell opcode = kX86PsrlwRI; 1975fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 197660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 197760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 197860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji GenShiftByteVector(bb, mir); 197960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji return; 1980fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 1981fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector unsigned shift right " << opsize; 1982fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 1983fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 1984fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(opcode, rs_dest_src1.GetReg(), imm); 1985fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1986fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1987fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenAndVector(BasicBlock *bb, MIR *mir) { 1988fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // We only support 128 bit registers. 198960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 199060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA); 1991b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest_src1); 199260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB); 1993fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell NewLIR2(kX86PandRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 1994fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 1995fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 1996fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenOrVector(BasicBlock *bb, 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(kX86PorRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 2003fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2004fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2005fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenXorVector(BasicBlock *bb, 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(kX86PxorRR, rs_dest_src1.GetReg(), rs_src2.GetReg()); 2012fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2013fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 201460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::AndMaskVectorRegister(RegStorage rs_src1, uint32_t m1, uint32_t m2, uint32_t m3, uint32_t m4) { 201560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji MaskVectorRegister(kX86PandRM, rs_src1, m1, m2, m3, m4); 201660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 201760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 201860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::MaskVectorRegister(X86OpCode opcode, RegStorage rs_src1, uint32_t m0, uint32_t m1, uint32_t m2, uint32_t m3) { 201960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Create temporary MIR as container for 128-bit binary mask. 202060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji MIR const_mir; 202160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji MIR* const_mirp = &const_mir; 202260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpConstVector); 202360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[0] = m0; 202460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[1] = m1; 202560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[2] = m2; 202660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji const_mirp->dalvikInsn.arg[3] = m3; 202760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 202860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji // Mask vector with const from literal pool. 202960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji AppendOpcodeWithConst(opcode, rs_src1.GetReg(), const_mirp); 203060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji} 203160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2032fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenAddReduceVector(BasicBlock *bb, MIR *mir) { 203360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 2034b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage vector_src = RegStorage::Solo128(mir->dalvikInsn.vB); 2035b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bool is_wide = opsize == k64 || opsize == kDouble; 2036b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2037b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Get the location of the virtual register. Since this bytecode is overloaded 2038b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // for different types (and sizes), we need different logic for each path. 2039b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // The design of bytecode uses same VR for source and destination. 2040b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegLocation rl_src, rl_dest, rl_result; 2041b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (is_wide) { 2042b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrcWide(mir, 0); 2043b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_dest = mir_graph_->GetDestWide(mir); 2044b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2045b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrc(mir, 0); 2046b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_dest = mir_graph_->GetDest(mir); 2047b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 204860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2049b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // We need a temp for byte and short values 2050b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage temp; 205160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2052b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // There is a different path depending on type and size. 2053b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSingle) { 2054b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle float case. 2055b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Add support for fast math (not value safe) and do horizontal add in that case. 205660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2057b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = LoadValue(rl_src, kFPReg); 2058b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLoc(rl_dest, kFPReg, true); 205960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2060b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Since we are doing an add-reduce, we move the reg holding the VR 2061b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // into the result so we include it in result. 2062b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A OpRegCopy(rl_result.reg, rl_src.reg); 2063b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 206460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2065b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Since FP must keep order of operation for value safety, we shift to low 2066b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // 32-bits and add to result. 2067b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (int i = 0; i < 3; i++) { 2068b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(kX86ShufpsRRI, vector_src.GetReg(), vector_src.GetReg(), 0x39); 2069b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 2070b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 207160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2072b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreValue(rl_dest, rl_result); 2073b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == kDouble) { 2074b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle double case. 2075b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = LoadValueWide(rl_src, kFPReg); 2076b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLocWide(rl_dest, kFPReg, true); 2077b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported vector add reduce for double."; 2078b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == k64) { 2079b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 2080b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * Handle long case: 2081b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1) Reduce the vector register to lower half (with addition). 2082b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-1) Get an xmm temp and fill it with vector register. 2083b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-2) Shift the xmm temp by 8-bytes. 2084b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-3) Add the xmm temp to vector register that is being reduced. 2085b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2) Allocate temp GP / GP pair. 2086b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-1) In 64-bit case, use movq to move result to a 64-bit GP. 2087b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-2) In 32-bit case, use movd twice to move to 32-bit GP pair. 2088b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 3) Finish the add reduction by doing what add-long/2addr does, 2089b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * but instead of having a VR as one of the sources, we have our temp GP. 2090b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 2091b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector = Get128BitRegister(AllocTempDouble()); 2092b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector.GetReg(), vector_src.GetReg()); 2093b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrldqRI, rs_tmp_vector.GetReg(), 8); 2094b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, vector_src.GetReg(), rs_tmp_vector.GetReg()); 2095b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A FreeTemp(rs_tmp_vector); 2096b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2097b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // We would like to be able to reuse the add-long implementation, so set up a fake 2098b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // register location to pass it. 2099b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegLocation temp_loc = mir_graph_->GetBadLoc(); 2100b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.core = 1; 2101b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.wide = 1; 2102b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.location = kLocPhysReg; 2103b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp_loc.reg = AllocTempWide(); 2104b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2105b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (cu_->target64) { 2106b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A DCHECK(!temp_loc.reg.IsPair()); 2107b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovqrxRR, temp_loc.reg.GetReg(), vector_src.GetReg()); 2108b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2109b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, temp_loc.reg.GetLowReg(), vector_src.GetReg()); 2110b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, vector_src.GetReg(), 0x20); 2111b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, temp_loc.reg.GetHighReg(), vector_src.GetReg()); 2112b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 211360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2114b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A GenArithOpLong(Instruction::ADD_LONG_2ADDR, rl_dest, temp_loc, temp_loc); 2115b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == kSignedByte || opsize == kUnsignedByte) { 2116b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp = Get128BitRegister(AllocTempDouble()); 2117b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PxorRR, rs_tmp.GetReg(), rs_tmp.GetReg()); 2118b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsadbwRR, vector_src.GetReg(), rs_tmp.GetReg()); 2119b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(kX86PshufdRRI, rs_tmp.GetReg(), vector_src.GetReg(), 0x4e); 2120b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddbRR, vector_src.GetReg(), rs_tmp.GetReg()); 2121b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Move to a GPR 2122b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp = AllocTemp(); 2123b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, temp.GetReg(), vector_src.GetReg()); 2124b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2125b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle and the int and short cases together 2126b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2127b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Initialize as if we were handling int case. Below we update 2128b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // the opcode if handling byte or short. 2129b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int vec_bytes = (mir->dalvikInsn.vC & 0xFFFF) / 8; 2130b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int vec_unit_size; 2131b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int horizontal_add_opcode; 2132b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int extract_opcode; 2133b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2134b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSignedHalf || opsize == kUnsignedHalf) { 2135b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A extract_opcode = kX86PextrwRRI; 2136b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A horizontal_add_opcode = kX86PhaddwRR; 2137b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A vec_unit_size = 2; 2138b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == k32) { 2139b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A vec_unit_size = 4; 2140b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A horizontal_add_opcode = kX86PhadddRR; 2141b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A extract_opcode = kX86PextrdRRI; 2142b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2143b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported vector add reduce " << opsize; 2144b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 214560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 214660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2147b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int elems = vec_bytes / vec_unit_size; 214860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2149b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A while (elems > 1) { 2150b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(horizontal_add_opcode, vector_src.GetReg(), vector_src.GetReg()); 2151b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A elems >>= 1; 2152b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 215360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2154b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle this as arithmetic unary case. 2155b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 215660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2157b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Extract to a GP register because this is integral typed. 2158b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A temp = AllocTemp(); 2159b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(extract_opcode, temp.GetReg(), vector_src.GetReg(), 0); 2160b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2161b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2162b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize != k64 && opsize != kSingle && opsize != kDouble) { 2163b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // The logic below looks very similar to the handling of ADD_INT_2ADDR 2164b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // except the rhs is not a VR but a physical register allocated above. 2165b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // No load of source VR is done because it assumes that rl_result will 2166b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // share physical register / memory location. 2167b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = UpdateLocTyped(rl_dest, kCoreReg); 2168b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (rl_result.location == kLocPhysReg) { 2169b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Ensure res is in a core reg. 2170b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLoc(rl_dest, kCoreReg, true); 2171b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A OpRegReg(kOpAdd, rl_result.reg, temp); 2172b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreFinalValue(rl_dest, rl_result); 2173b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2174b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Do the addition directly to memory. 2175b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A OpMemReg(kOpAdd, rl_result, temp.GetReg()); 2176b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2177b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2178fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2179fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2180fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenReduceVector(BasicBlock *bb, MIR *mir) { 218160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 218260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegLocation rl_dest = mir_graph_->GetDest(mir); 2183b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage vector_src = RegStorage::Solo128(mir->dalvikInsn.vB); 218460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int extract_index = mir->dalvikInsn.arg[0]; 218560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji int extr_opcode = 0; 218660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegLocation rl_result; 218760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji bool is_wide = false; 218860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2189b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // There is a different path depending on type and size. 2190b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSingle) { 2191b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle float case. 2192b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Add support for fast math (not value safe) and do horizontal add in that case. 2193fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2194b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLoc(rl_dest, kFPReg, true); 2195b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PxorRR, rl_result.reg.GetReg(), rl_result.reg.GetReg()); 2196b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 2197b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2198b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Since FP must keep order of operation for value safety, we shift to low 2199b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // 32-bits and add to result. 2200b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A for (int i = 0; i < 3; i++) { 2201b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(kX86ShufpsRRI, vector_src.GetReg(), vector_src.GetReg(), 0x39); 2202b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), vector_src.GetReg()); 2203b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2204b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2205b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreValue(rl_dest, rl_result); 2206b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == kDouble) { 2207b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // TODO Handle double case. 2208b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported add reduce for double."; 2209b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else if (opsize == k64) { 2210b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A /* 2211b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * Handle long case: 2212b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1) Reduce the vector register to lower half (with addition). 2213b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-1) Get an xmm temp and fill it with vector register. 2214b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-2) Shift the xmm temp by 8-bytes. 2215b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 1-3) Add the xmm temp to vector register that is being reduced. 2216b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2) Evaluate destination to a GP / GP pair. 2217b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-1) In 64-bit case, use movq to move result to a 64-bit GP. 2218b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 2-2) In 32-bit case, use movd twice to move to 32-bit GP pair. 2219b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A * 3) Store the result to the final destination. 2220b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A */ 2221b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage rs_tmp_vector = Get128BitRegister(AllocTempDouble()); 2222b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdqaRR, rs_tmp_vector.GetReg(), vector_src.GetReg()); 2223b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrldqRI, rs_tmp_vector.GetReg(), 8); 2224b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PaddqRR, vector_src.GetReg(), rs_tmp_vector.GetReg()); 2225b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A FreeTemp(rs_tmp_vector); 2226b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2227b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = EvalLocWide(rl_dest, kCoreReg, true); 2228b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (cu_->target64) { 2229b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A DCHECK(!rl_result.reg.IsPair()); 2230b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovqrxRR, rl_result.reg.GetReg(), vector_src.GetReg()); 223160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 2232b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, rl_result.reg.GetLowReg(), vector_src.GetReg()); 2233b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PsrlqRI, vector_src.GetReg(), 0x20); 2234b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdrxRR, rl_result.reg.GetHighReg(), vector_src.GetReg()); 223560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 2236b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2237b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreValueWide(rl_dest, rl_result); 223860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 2239b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Handle the rest of integral types now. 2240b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A switch (opsize) { 2241b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case k32: 2242b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result = UpdateLocTyped(rl_dest, kCoreReg); 2243b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrdMRI : kX86PextrdRRI; 2244b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 2245b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kSignedHalf: 2246b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A case kUnsignedHalf: 2247b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_result= UpdateLocTyped(rl_dest, kCoreReg); 2248b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrwMRI : kX86PextrwRRI; 2249b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 2250b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A default: 2251b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LOG(FATAL) << "Unsupported vector reduce " << opsize; 2252b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A return; 2253b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2254b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2255b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (rl_result.location == kLocPhysReg) { 2256b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(extr_opcode, rl_result.reg.GetReg(), vector_src.GetReg(), extract_index); 2257b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (is_wide == true) { 2258b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreFinalValue(rl_dest, rl_result); 2259b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2260b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A StoreFinalValueWide(rl_dest, rl_result); 2261b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2262b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2263b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int displacement = SRegOffset(rl_result.s_reg_low); 2264b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A LIR *l = NewLIR3(extr_opcode, rs_rX86_SP.GetReg(), displacement, vector_src.GetReg()); 2265b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, is_wide /* is_64bit */); 2266b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A AnnotateDalvikRegAccess(l, displacement >> 2, false /* is_load */, is_wide /* is_64bit */); 2267b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 226860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 2269fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2270fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2271fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenSetVector(BasicBlock *bb, MIR *mir) { 227260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U); 227360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16); 227460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA); 2275b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A Clobber(rs_dest); 2276b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A int op_shuffle = 0, op_shuffle_high = 0, op_mov = kX86MovdxrRR; 227760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji RegisterClass reg_type = kCoreReg; 2278b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A bool is_wide = false; 227960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2280fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell switch (opsize) { 2281fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case k32: 2282b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PshufdRRI; 2283fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 228460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSingle: 2285b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PshufdRRI; 2286b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_mov = kX86MovdqaRR; 228760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji reg_type = kFPReg; 228860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 228960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case k64: 2290b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PunpcklqdqRR; 2291b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_mov = kX86MovqrxRR; 2292b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A is_wide = true; 229360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji break; 229460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kSignedByte: 229560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji case kUnsignedByte: 2296b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // We will have the source loaded up in a 2297b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // double-word before we use this shuffle 2298b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PshufdRRI; 2299b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A break; 2300fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kSignedHalf: 2301fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell case kUnsignedHalf: 2302fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Handles low quadword. 2303b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle = kX86PshuflwRRI; 2304fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Handles upper quadword. 2305b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A op_shuffle_high = kX86PshufdRRI; 2306fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 2307fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell default: 2308fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell LOG(FATAL) << "Unsupported vector set " << opsize; 2309fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell break; 2310fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 2311fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2312b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Load the value from the VR into a physical register. 2313b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegLocation rl_src; 2314b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (!is_wide) { 2315b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrc(mir, 0); 231660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji rl_src = LoadValue(rl_src, reg_type); 231760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } else { 2318b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A rl_src = mir_graph_->GetSrcWide(mir, 0); 231960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji rl_src = LoadValueWide(rl_src, reg_type); 232060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 2321b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage reg_to_shuffle = rl_src.reg; 232260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji 2323b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Load the value into the XMM register. 2324b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (!cu_->target64 && opsize == k64) { 2325b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Logic assumes that longs are loaded in GP register pairs. 2326b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdxrRR, rs_dest.GetReg(), reg_to_shuffle.GetLowReg()); 2327b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A RegStorage r_tmp = AllocTempDouble(); 2328b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86MovdxrRR, r_tmp.GetReg(), reg_to_shuffle.GetHighReg()); 2329b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PunpckldqRR, rs_dest.GetReg(), r_tmp.GetReg()); 2330b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A FreeTemp(r_tmp); 2331b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2332b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(op_mov, rs_dest.GetReg(), reg_to_shuffle.GetReg()); 233360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji } 2334fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2335b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (opsize == kSignedByte || opsize == kUnsignedByte) { 2336b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // In the byte case, first duplicate it to be a word 2337b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A // Then duplicate it to be a double-word 2338b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PunpcklbwRR, rs_dest.GetReg(), rs_dest.GetReg()); 2339b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(kX86PunpcklwdRR, rs_dest.GetReg(), rs_dest.GetReg()); 2340b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2341fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2342fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // Now shuffle the value across the destination. 2343b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (op_shuffle == kX86PunpcklqdqRR) { 2344b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR2(op_shuffle, rs_dest.GetReg(), rs_dest.GetReg()); 2345b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } else { 2346b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(op_shuffle, rs_dest.GetReg(), rs_dest.GetReg(), 0); 2347b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A } 2348fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2349fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell // And then repeat as needed. 2350b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (op_shuffle_high != 0) { 2351b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A NewLIR3(op_shuffle_high, rs_dest.GetReg(), rs_dest.GetReg(), 0); 2352fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell } 2353fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell} 2354fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell 2355b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::GenPackedArrayGet(BasicBlock *bb, MIR *mir) { 2356b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A UNIMPLEMENTED(FATAL) << "Extended opcode kMirOpPackedArrayGet not supported."; 2357b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A} 2358b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2359b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan Avoid X86Mir2Lir::GenPackedArrayPut(BasicBlock *bb, MIR *mir) { 2360b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A UNIMPLEMENTED(FATAL) << "Extended opcode kMirOpPackedArrayPut not supported."; 2361b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A} 2362b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A 2363b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan ALIR* X86Mir2Lir::ScanVectorLiteral(int32_t* constants) { 2364d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell for (LIR *p = const_vectors_; p != nullptr; p = p->next) { 2365b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A if (constants[0] == p->operands[0] && constants[1] == p->operands[1] && 2366b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A constants[2] == p->operands[2] && constants[3] == p->operands[3]) { 2367d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return p; 2368d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 2369d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 2370d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return nullptr; 2371d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 2372d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 2373b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan ALIR* X86Mir2Lir::AddVectorLiteral(int32_t* constants) { 2374d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell LIR* new_value = static_cast<LIR*>(arena_->Alloc(sizeof(LIR), kArenaAllocData)); 2375b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A new_value->operands[0] = constants[0]; 2376b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A new_value->operands[1] = constants[1]; 2377b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A new_value->operands[2] = constants[2]; 2378b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A new_value->operands[3] = constants[3]; 2379d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell new_value->next = const_vectors_; 2380d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell if (const_vectors_ == nullptr) { 2381b3a84e2f308b3ed7d17b8e96fc7adfcac36ebe77Lupusoru, Razvan A estimated_native_code_size_ += 12; // Maximum needed to align to 16 byte boundary. 2382d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell } 2383d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell estimated_native_code_size_ += 16; // Space for one vector. 2384d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell const_vectors_ = new_value; 2385d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell return new_value; 2386d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell} 2387d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell 238858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// ------------ ABI support: mapping of args to physical registers ------------- 2389ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas GampeRegStorage X86Mir2Lir::InToRegStorageX86_64Mapper::GetNextReg(bool is_double_or_float, bool is_wide, 2390ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe bool is_ref) { 2391a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu const SpecialTargetRegister coreArgMappingToPhysicalReg[] = {kArg1, kArg2, kArg3, kArg4, kArg5}; 2392ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe const int coreArgMappingToPhysicalRegSize = sizeof(coreArgMappingToPhysicalReg) / 2393ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe sizeof(SpecialTargetRegister); 2394a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu const SpecialTargetRegister fpArgMappingToPhysicalReg[] = {kFArg0, kFArg1, kFArg2, kFArg3, 2395ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe kFArg4, kFArg5, kFArg6, kFArg7}; 2396ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe const int fpArgMappingToPhysicalRegSize = sizeof(fpArgMappingToPhysicalReg) / 2397ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe sizeof(SpecialTargetRegister); 239858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 239958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (is_double_or_float) { 240058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) { 2401ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe return ml_->TargetReg(fpArgMappingToPhysicalReg[cur_fp_reg_++], is_wide ? kWide : kNotWide); 240258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 240358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 240458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) { 2405ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe return ml_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++], 2406ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe is_ref ? kRef : (is_wide ? kWide : kNotWide)); 240758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 240858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 2409a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu return RegStorage::InvalidReg(); 241058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 241158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 241258994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::InToRegStorageMapping::Get(int in_position) { 241358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko DCHECK(IsInitialized()); 241458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko auto res = mapping_.find(in_position); 241558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return res != mapping_.end() ? res->second : RegStorage::InvalidReg(); 241658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 241758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2418ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampevoid X86Mir2Lir::InToRegStorageMapping::Initialize(RegLocation* arg_locs, int count, 2419ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe InToRegStorageMapper* mapper) { 242058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko DCHECK(mapper != nullptr); 242158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko max_mapped_in_ = -1; 242258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko is_there_stack_mapped_ = false; 242358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko for (int in_position = 0; in_position < count; in_position++) { 2424407a9d2847161b843966a443b71760b1280bd396Serguei Katkov RegStorage reg = mapper->GetNextReg(arg_locs[in_position].fp, 2425407a9d2847161b843966a443b71760b1280bd396Serguei Katkov arg_locs[in_position].wide, arg_locs[in_position].ref); 242658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (reg.Valid()) { 242758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko mapping_[in_position] = reg; 242858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko max_mapped_in_ = std::max(max_mapped_in_, in_position); 2429407a9d2847161b843966a443b71760b1280bd396Serguei Katkov if (arg_locs[in_position].wide) { 243058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // We covered 2 args, so skip the next one 243158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko in_position++; 243258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 243358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 243458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko is_there_stack_mapped_ = true; 243558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 243658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 243758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko initialized_ = true; 243858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 243958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 244058994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) { 2441dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 244258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return GetCoreArgMappingToPhysicalReg(arg_num); 244358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 244458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 244558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (!in_to_reg_storage_mapping_.IsInitialized()) { 24468d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru int start_vreg = cu_->mir_graph->GetFirstInVR(); 244758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation* arg_locs = &mir_graph_->reg_location_[start_vreg]; 244858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2449a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu InToRegStorageX86_64Mapper mapper(this); 24508d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru in_to_reg_storage_mapping_.Initialize(arg_locs, mir_graph_->GetNumOfInVRs(), &mapper); 245158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 245258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return in_to_reg_storage_mapping_.Get(arg_num); 245358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 245458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 245558994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::GetCoreArgMappingToPhysicalReg(int core_arg_num) { 245658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // For the 32-bit internal ABI, the first 3 arguments are passed in registers. 245758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Not used for 64-bit, TODO: Move X86_32 to the same framework 245858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko switch (core_arg_num) { 245958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case 0: 246058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return rs_rX86_ARG1; 246158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case 1: 246258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return rs_rX86_ARG2; 246358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko case 2: 246458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return rs_rX86_ARG3; 246558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko default: 246658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return RegStorage::InvalidReg(); 246758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 246858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 246958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 247058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// ---------End of ABI support: mapping of args to physical registers ------------- 247158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 247258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/* 247358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If there are any ins passed in registers that have not been promoted 247458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * to a callee-save register, flush them to the frame. Perform initial 247558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * assignment of promoted arguments. 247658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 247758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * ArgLocs is an array of location records describing the incoming arguments 247858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * with one location record per word of argument. 247958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 248058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkovoid X86Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) { 2481dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) return Mir2Lir::FlushIns(ArgLocs, rl_method); 248258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 248358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Dummy up a RegLocation for the incoming Method* 248458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * It will attempt to keep kArg0 live (or copy it to home location 248558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * if promoted). 248658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 248758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 248858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation rl_src = rl_method; 248958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_src.location = kLocPhysReg; 2490ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe rl_src.reg = TargetReg(kArg0, kRef); 249158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_src.home = false; 249258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko MarkLive(rl_src); 249358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko StoreValue(rl_method, rl_src); 249458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // If Method* has been promoted, explicitly flush 249558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (rl_method.location == kLocPhysReg) { 2496ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe StoreRefDisp(rs_rX86_SP, 0, As32BitReg(TargetReg(kArg0, kRef)), kNotVolatile); 249758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 249858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 24998d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru if (mir_graph_->GetNumOfInVRs() == 0) { 250058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return; 250158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 250258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25038d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru int start_vreg = cu_->mir_graph->GetFirstInVR(); 250458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 250558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Copy incoming arguments to their proper home locations. 250658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * NOTE: an older version of dx had an issue in which 250758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * it would reuse static method argument registers. 250858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * This could result in the same Dalvik virtual register 250958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * being promoted to both core and fp regs. To account for this, 251058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * we only copy to the corresponding promoted physical register 251158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * if it matches the type of the SSA name for the incoming 251258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * argument. It is also possible that long and double arguments 251358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * end up half-promoted. In those cases, we must flush the promoted 251458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * half to memory as well. 251558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 25168dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 25178d0d03e24325463f0060abfd05dba5598044e9b1Razvan A Lupusoru for (uint32_t i = 0; i < mir_graph_->GetNumOfInVRs(); i++) { 251858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // get reg corresponding to input 25194d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko RegStorage reg = GetArgMappingToPhysicalReg(i); 252058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25214d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko RegLocation* t_loc = &ArgLocs[i]; 252258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (reg.Valid()) { 25234d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // If arriving in register. 252458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 25254d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // We have already updated the arg location with promoted info 25264d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // so we can be based on it. 25274d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->location == kLocPhysReg) { 25284d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // Just copy it. 25294d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko OpRegCopy(t_loc->reg, reg); 25304d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } else { 25314d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // Needs flush. 25324d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->ref) { 2533a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreRefDisp(rs_rX86_SP, SRegOffset(start_vreg + i), reg, kNotVolatile); 253458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 2535a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, SRegOffset(start_vreg + i), reg, t_loc->wide ? k64 : k32, 25364d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko kNotVolatile); 253758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 253858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 253958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 25404d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // If arriving in frame & promoted. 25414d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->location == kLocPhysReg) { 25424d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->ref) { 2543a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LoadRefDisp(rs_rX86_SP, SRegOffset(start_vreg + i), t_loc->reg, kNotVolatile); 25444d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } else { 2545a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu LoadBaseDisp(rs_rX86_SP, SRegOffset(start_vreg + i), t_loc->reg, 25464d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko t_loc->wide ? k64 : k32, kNotVolatile); 25474d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } 254858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 254958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 25504d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko if (t_loc->wide) { 25514d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko // Increment i to skip the next one. 25524d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko i++; 25534d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko } 255458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 255558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 255658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 255758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/* 255858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Load up to 5 arguments, the first three of which will be in 255958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * kArg1 .. kArg3. On entry kArg0 contains the current method pointer, 256058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * and as part of the load sequence, it must be replaced with 256158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * the target method pointer. Note, this may also be called 256258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * for "range" variants if the number of arguments is 5 or fewer. 256358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 256458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsNoRange(CallInfo* info, 256558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int call_state, LIR** pcrLabel, NextCallInsn next_call_insn, 256658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const MethodReference& target_method, 256758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko uint32_t vtable_idx, uintptr_t direct_code, 256858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko uintptr_t direct_method, InvokeType type, bool skip_this) { 2569dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 257058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return Mir2Lir::GenDalvikArgsNoRange(info, 257158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state, pcrLabel, next_call_insn, 257258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko target_method, 257358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, 257458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_method, type, skip_this); 257558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 257658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return GenDalvikArgsRange(info, 257758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state, pcrLabel, next_call_insn, 257858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko target_method, 257958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, 258058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_method, type, skip_this); 258158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 258258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 258358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/* 258458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * May have 0+ arguments (also used for jumbo). Note that 258558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * source virtual registers may be in physical registers, so may 258658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * need to be flushed to home location before copying. This 258758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * applies to arg3 and above (see below). 258858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 258958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Two general strategies: 259058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If < 20 arguments 259158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass args 3-18 using vldm/vstm block copy 259258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass arg0, arg1 & arg2 in kArg1-kArg3 259358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If 20+ arguments 259458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass args arg19+ using memcpy block copy 259558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Pass arg0, arg1 & arg2 in kArg1-kArg3 259658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 259758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 259858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state, 259958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR** pcrLabel, NextCallInsn next_call_insn, 260058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const MethodReference& target_method, 260158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko uint32_t vtable_idx, uintptr_t direct_code, uintptr_t direct_method, 260258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko InvokeType type, bool skip_this) { 2603dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina if (!cu_->target64) { 260458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return Mir2Lir::GenDalvikArgsRange(info, call_state, 260558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko pcrLabel, next_call_insn, 260658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko target_method, 260758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, direct_method, 260858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko type, skip_this); 260958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 261058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 261158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* If no arguments, just return */ 261258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (info->num_arg_words == 0) 261358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return call_state; 261458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 261558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const int start_index = skip_this ? 1 : 0; 261658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2617a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu InToRegStorageX86_64Mapper mapper(this); 261858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko InToRegStorageMapping in_to_reg_storage_mapping; 261958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko in_to_reg_storage_mapping.Initialize(info->args, info->num_arg_words, &mapper); 262058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const int last_mapped_in = in_to_reg_storage_mapping.GetMaxMappedIn(); 262158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko const int size_of_the_last_mapped = last_mapped_in == -1 ? 1 : 26228e3acdd132aef1391676a5db2696804900aacd8eSerguei Katkov info->args[last_mapped_in].wide ? 2 : 1; 262358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int regs_left_to_pass_via_stack = info->num_arg_words - (last_mapped_in + size_of_the_last_mapped); 262458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 262558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Fisrt of all, check whether it make sense to use bulk copying 262658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Optimization is aplicable only for range case 262758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // TODO: make a constant instead of 2 262858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (info->is_range && regs_left_to_pass_via_stack >= 2) { 262958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Scan the rest of the args - if in phys_reg flush to memory 263058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko for (int next_arg = last_mapped_in + size_of_the_last_mapped; next_arg < info->num_arg_words;) { 263158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation loc = info->args[next_arg]; 263258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (loc.wide) { 263358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko loc = UpdateLocWide(loc); 263458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (loc.location == kLocPhysReg) { 26358dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 2636a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, SRegOffset(loc.s_reg_low), loc.reg, k64, kNotVolatile); 263758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 263858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko next_arg += 2; 263958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 264058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko loc = UpdateLoc(loc); 264158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (loc.location == kLocPhysReg) { 26428dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 2643a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, SRegOffset(loc.s_reg_low), loc.reg, k32, kNotVolatile); 264458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 264558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko next_arg++; 264658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 264758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 264858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 264958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // The rest can be copied together 265058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int start_offset = SRegOffset(info->args[last_mapped_in + size_of_the_last_mapped].s_reg_low); 2651ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe int outs_offset = StackVisitor::GetOutVROffset(last_mapped_in + size_of_the_last_mapped, 2652ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe cu_->instruction_set); 265358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 265458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int current_src_offset = start_offset; 265558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int current_dest_offset = outs_offset; 265658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 26578dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko // Only davik regs are accessed in this loop; no next_call_insn() calls. 26588dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 265958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko while (regs_left_to_pass_via_stack > 0) { 266058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // This is based on the knowledge that the stack itself is 16-byte aligned. 266158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool src_is_16b_aligned = (current_src_offset & 0xF) == 0; 266258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool dest_is_16b_aligned = (current_dest_offset & 0xF) == 0; 266358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko size_t bytes_to_move; 266458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 266558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 266658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * The amount to move defaults to 32-bit. If there are 4 registers left to move, then do a 266758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * a 128-bit move because we won't get the chance to try to aligned. If there are more than 266858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * 4 registers left to move, consider doing a 128-bit only if either src or dest are aligned. 266958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * We do this because we could potentially do a smaller move to align. 267058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 267158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (regs_left_to_pass_via_stack == 4 || 267258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko (regs_left_to_pass_via_stack > 4 && (src_is_16b_aligned || dest_is_16b_aligned))) { 267358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Moving 128-bits via xmm register. 267458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bytes_to_move = sizeof(uint32_t) * 4; 267558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 267658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Allocate a free xmm temp. Since we are working through the calling sequence, 267758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // we expect to have an xmm temporary available. AllocTempDouble will abort if 267858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // there are no free registers. 267958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage temp = AllocTempDouble(); 268058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 268158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* ld1 = nullptr; 268258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* ld2 = nullptr; 268358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* st1 = nullptr; 268458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LIR* st2 = nullptr; 268558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 268658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko /* 268758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * The logic is similar for both loads and stores. If we have 16-byte alignment, 268858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * do an aligned move. If we have 8-byte alignment, then do the move in two 268958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * parts. This approach prevents possible cache line splits. Finally, fall back 269058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * to doing an unaligned move. In most cases we likely won't split the cache 269158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * line but we cannot prove it and thus take a conservative approach. 269258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */ 269358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool src_is_8b_aligned = (current_src_offset & 0x7) == 0; 269458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bool dest_is_8b_aligned = (current_dest_offset & 0x7) == 0; 269558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 26968dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 269758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (src_is_16b_aligned) { 2698a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovA128FP); 269958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else if (src_is_8b_aligned) { 2700a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovLo128FP); 2701a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu ld2 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset + (bytes_to_move >> 1), 270258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko kMovHi128FP); 270358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 2704a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovU128FP); 270558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 270658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 270758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (dest_is_16b_aligned) { 2708a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovA128FP); 270958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else if (dest_is_8b_aligned) { 2710a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovLo128FP); 2711a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu st2 = OpMovMemReg(rs_rX86_SP, current_dest_offset + (bytes_to_move >> 1), 271258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko temp, kMovHi128FP); 271358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 2714a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovU128FP); 271558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 271658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 271758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // TODO If we could keep track of aliasing information for memory accesses that are wider 271858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // than 64-bit, we wouldn't need to set up a barrier. 271958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (ld1 != nullptr) { 272058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (ld2 != nullptr) { 272158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // For 64-bit load we can actually set up the aliasing information. 272258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(ld1, current_src_offset >> 2, true, true); 272358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(ld2, (current_src_offset + (bytes_to_move >> 1)) >> 2, true, true); 272458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 272558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Set barrier for 128-bit load. 27268dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ld1->u.m.def_mask = &kEncodeAll; 272758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 272858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 272958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (st1 != nullptr) { 273058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (st2 != nullptr) { 273158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // For 64-bit store we can actually set up the aliasing information. 273258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(st1, current_dest_offset >> 2, false, true); 273358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko AnnotateDalvikRegAccess(st2, (current_dest_offset + (bytes_to_move >> 1)) >> 2, false, true); 273458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 273558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Set barrier for 128-bit store. 27368dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko st1->u.m.def_mask = &kEncodeAll; 273758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 273858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 273958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 274058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Free the temporary used for the data movement. 274158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(temp); 274258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 274358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Moving 32-bits via general purpose register. 274458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko bytes_to_move = sizeof(uint32_t); 274558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 274658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Instead of allocating a new temp, simply reuse one of the registers being used 274758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // for argument passing. 2748ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe RegStorage temp = TargetReg(kArg3, kNotWide); 274958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 275058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Now load the argument VR and store to the outs. 2751a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu Load32Disp(rs_rX86_SP, current_src_offset, temp); 2752a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu Store32Disp(rs_rX86_SP, current_dest_offset, temp); 275358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 275458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 275558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko current_src_offset += bytes_to_move; 275658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko current_dest_offset += bytes_to_move; 275758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko regs_left_to_pass_via_stack -= (bytes_to_move >> 2); 275858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 275958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko DCHECK_EQ(regs_left_to_pass_via_stack, 0); 276058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 276158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 276258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Now handle rest not registers if they are 276358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (in_to_reg_storage_mapping.IsThereStackMapped()) { 2764ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe RegStorage regSingle = TargetReg(kArg2, kNotWide); 2765ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe RegStorage regWide = TargetReg(kArg3, kWide); 2766b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu for (int i = start_index; 2767b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu i < last_mapped_in + size_of_the_last_mapped + regs_left_to_pass_via_stack; i++) { 276858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation rl_arg = info->args[i]; 276958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_arg = UpdateRawLoc(rl_arg); 277058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage reg = in_to_reg_storage_mapping.Get(i); 277158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (!reg.Valid()) { 277258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko int out_offset = StackVisitor::GetOutVROffset(i, cu_->instruction_set); 277358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 27748dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko { 27758dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); 27768dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (rl_arg.wide) { 27778dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (rl_arg.location == kLocPhysReg) { 2778a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, out_offset, rl_arg.reg, k64, kNotVolatile); 27798dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } else { 27808dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko LoadValueDirectWideFixed(rl_arg, regWide); 2781a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, out_offset, regWide, k64, kNotVolatile); 27828dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } 278358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 27848dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (rl_arg.location == kLocPhysReg) { 2785a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, out_offset, rl_arg.reg, k32, kNotVolatile); 27868dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } else { 27878dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko LoadValueDirectFixed(rl_arg, regSingle); 2788a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu StoreBaseDisp(rs_rX86_SP, out_offset, regSingle, k32, kNotVolatile); 27898dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko } 279058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 279158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 279258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state = next_call_insn(cu_, info, call_state, target_method, 279358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko vtable_idx, direct_code, direct_method, type); 279458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 2795b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu if (rl_arg.wide) { 2796b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu i++; 2797b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu } 279858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 279958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 280058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 280158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // Finish with mapped registers 280258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko for (int i = start_index; i <= last_mapped_in; i++) { 280358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegLocation rl_arg = info->args[i]; 280458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko rl_arg = UpdateRawLoc(rl_arg); 280558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage reg = in_to_reg_storage_mapping.Get(i); 280658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (reg.Valid()) { 280758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (rl_arg.wide) { 280858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LoadValueDirectWideFixed(rl_arg, reg); 280958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 281058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko LoadValueDirectFixed(rl_arg, reg); 281158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 281258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, 281358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_code, direct_method, type); 281458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 2815b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu if (rl_arg.wide) { 2816b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu i++; 2817b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu } 281858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 281958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 282058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx, 282158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko direct_code, direct_method, type); 282258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko if (pcrLabel) { 282369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison if (!cu_->compiler_driver->GetCompilerOptions().GetImplicitNullChecks()) { 2824ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe *pcrLabel = GenExplicitNullCheck(TargetReg(kArg1, kRef), info->opt_flags); 282558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } else { 282658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *pcrLabel = nullptr; 282758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // In lieu of generating a check for kArg1 being null, we need to 282858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko // perform a load when doing implicit checks. 282958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko RegStorage tmp = AllocTemp(); 2830ccc60264229ac96d798528d2cb7dbbdd0deca993Andreas Gampe Load32Disp(TargetReg(kArg1, kRef), 0, tmp); 283158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko MarkPossibleNullPointerException(info->opt_flags); 283258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko FreeTemp(tmp); 283358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 283458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko } 283558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko return call_state; 283658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko} 283758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko 2838984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampebool X86Mir2Lir::GenInlinedCharAt(CallInfo* info) { 2839984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Location of reference to data array 2840984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int value_offset = mirror::String::ValueOffset().Int32Value(); 2841984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Location of count 2842984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int count_offset = mirror::String::CountOffset().Int32Value(); 2843984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Starting offset within data array 2844984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int offset_offset = mirror::String::OffsetOffset().Int32Value(); 2845984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Start of char data with array_ 2846984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value(); 2847984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe 2848984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_obj = info->args[0]; 2849984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_idx = info->args[1]; 2850984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe rl_obj = LoadValue(rl_obj, kRefReg); 2851984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // X86 wants to avoid putting a constant index into a register. 2852984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (!rl_idx.is_const) { 2853984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe rl_idx = LoadValue(rl_idx, kCoreReg); 2854984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2855984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegStorage reg_max; 2856984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe GenNullCheck(rl_obj.reg, info->opt_flags); 2857984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe bool range_check = (!(info->opt_flags & MIR_IGNORE_RANGE_CHECK)); 2858984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LIR* range_check_branch = nullptr; 2859984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegStorage reg_off; 2860984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegStorage reg_ptr; 2861984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (range_check) { 2862984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // On x86, we can compare to memory directly 2863984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe // Set up a launch pad to allow retry in case of bounds violation */ 2864984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (rl_idx.is_const) { 2865984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LIR* comparison; 2866984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe range_check_branch = OpCmpMemImmBranch( 2867984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe kCondUlt, RegStorage::InvalidReg(), rl_obj.reg, count_offset, 2868984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe mir_graph_->ConstantValue(rl_idx.orig_sreg), nullptr, &comparison); 2869984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe MarkPossibleNullPointerExceptionAfter(0, comparison); 2870984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } else { 2871984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe OpRegMem(kOpCmp, rl_idx.reg, rl_obj.reg, count_offset); 2872984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe MarkPossibleNullPointerException(0); 2873984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe range_check_branch = OpCondBranch(kCondUge, nullptr); 2874984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2875984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2876984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe reg_off = AllocTemp(); 2877984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe reg_ptr = AllocTempRef(); 2878984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe Load32Disp(rl_obj.reg, offset_offset, reg_off); 2879984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LoadRefDisp(rl_obj.reg, value_offset, reg_ptr, kNotVolatile); 2880984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (rl_idx.is_const) { 2881984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe OpRegImm(kOpAdd, reg_off, mir_graph_->ConstantValue(rl_idx.orig_sreg)); 2882984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } else { 2883984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe OpRegReg(kOpAdd, reg_off, rl_idx.reg); 2884984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2885984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(rl_obj.reg); 2886984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (rl_idx.location == kLocPhysReg) { 2887984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(rl_idx.reg); 2888984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2889984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_dest = InlineTarget(info); 2890984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); 2891984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe LoadBaseIndexedDisp(reg_ptr, reg_off, 1, data_offset, rl_result.reg, kUnsignedHalf); 2892984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(reg_off); 2893984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe FreeTemp(reg_ptr); 2894984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe StoreValue(rl_dest, rl_result); 2895984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe if (range_check) { 2896984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe DCHECK(range_check_branch != nullptr); 2897984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe info->opt_flags |= MIR_IGNORE_NULL_CHECK; // Record that we've already null checked. 2898984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe AddIntrinsicSlowPath(info, range_check_branch); 2899984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe } 2900984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe return true; 2901984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe} 2902984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe 29036bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalovbool X86Mir2Lir::GenInlinedCurrentThread(CallInfo* info) { 29046bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov RegLocation rl_dest = InlineTarget(info); 29056bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29066bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov // Early exit if the result is unused. 29076bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov if (rl_dest.orig_sreg < 0) { 29086bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov return true; 29096bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov } 29106bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29116bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true); 29126bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29136bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov if (cu_->target64) { 29146bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov OpRegThreadMem(kOpMov, rl_result.reg, Thread::PeerOffset<8>()); 29156bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov } else { 29166bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov OpRegThreadMem(kOpMov, rl_result.reg, Thread::PeerOffset<4>()); 29176bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov } 29186bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29196bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov StoreValue(rl_dest, rl_result); 29206bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov return true; 29216bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov} 29226bbf0967d217ab2b7bdbb78bfd076b8fb07a44e8Alexei Zavjalov 29236dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev/** 29246dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev * Lock temp registers for explicit usage. Registers will be freed in destructor. 29256dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev */ 29266dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim KazantsevX86Mir2Lir::ExplicitTempRegisterLock::ExplicitTempRegisterLock(X86Mir2Lir* mir_to_lir, 29276dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev int n_regs, ...) : 29286dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev temp_regs_(n_regs), 29296dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_(mir_to_lir) { 29306dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev va_list regs; 29316dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev va_start(regs, n_regs); 29326dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev for (int i = 0; i < n_regs; i++) { 29336dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev RegStorage reg = *(va_arg(regs, RegStorage*)); 29346dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev RegisterInfo* info = mir_to_lir_->GetRegInfo(reg); 29356dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29366dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev // Make sure we don't have promoted register here. 29376dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev DCHECK(info->IsTemp()); 29386dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29396dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev temp_regs_.push_back(reg); 29406dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->FlushReg(reg); 29416dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29426dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev if (reg.IsPair()) { 29436dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev RegStorage partner = info->Partner(); 29446dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev temp_regs_.push_back(partner); 29456dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->FlushReg(partner); 29466dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev } 29476dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29486dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->Clobber(reg); 29496dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->LockTemp(reg); 29506dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev } 29516dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29526dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev va_end(regs); 29536dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev} 29546dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29556dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev/* 29566dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev * Free all locked registers. 29576dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev */ 29586dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim KazantsevX86Mir2Lir::ExplicitTempRegisterLock::~ExplicitTempRegisterLock() { 29596dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev // Free all locked temps. 29606dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev for (auto it : temp_regs_) { 29616dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev mir_to_lir_->FreeTemp(it); 29626dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev } 29636dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev} 29646dccdc2511c9f22d3cc2ea83386ce9db2688fa19Maxim Kazantsev 29657934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom} // namespace art 2966