target_x86.cc revision 407a9d2847161b843966a443b71760b1280bd396
1efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
2efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Copyright (C) 2012 The Android Open Source Project
3efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
4efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Licensed under the Apache License, Version 2.0 (the "License");
5efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * you may not use this file except in compliance with the License.
6efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * You may obtain a copy of the License at
7efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
8efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *      http://www.apache.org/licenses/LICENSE-2.0
9efc6369224b036a1fb77849f7ae65b3492c832c0buzbee *
10efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Unless required by applicable law or agreed to in writing, software
11efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * distributed under the License is distributed on an "AS IS" BASIS,
12efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See the License for the specific language governing permissions and
14efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * limitations under the License.
15efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
16efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
17f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray#include <string>
18f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray#include <inttypes.h>
19f3e2cc4a38389aa75eb8ee3973a535254bf1c8d2Nicolas Geoffray
2002031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h"
217940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/compiler_internals.h"
227940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
23b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h"
24e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell#include "mirror/array.h"
25e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell#include "mirror/string.h"
26641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h"
27efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
28efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art {
29efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
30089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_32[] = {
319ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI,
329ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko};
33089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_64[] = {
3476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    rs_rAX, rs_rCX, rs_rDX, rs_rBX, rs_rX86_SP_32, rs_rBP, rs_rSI, rs_rDI,
35091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rs_r8, rs_r9, rs_r10, rs_r11, rs_r12, rs_r13, rs_r14, rs_r15
36efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
37089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_regs_arr_64q[] = {
380999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko    rs_r0q, rs_r1q, rs_r2q, rs_r3q, rs_rX86_SP_64, rs_r5q, rs_r6q, rs_r7q,
39a20468c004264592f309a548fc71ba62a69b8742Dmitry Petrochenko    rs_r8q, rs_r9q, rs_r10q, rs_r11q, rs_r12q, rs_r13q, rs_r14q, rs_r15q
400999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko};
41089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_regs_arr_32[] = {
429ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
439ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko};
44089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_regs_arr_64[] = {
45091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
46091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15
47efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
48089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_regs_arr_32[] = {
499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7,
509ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko};
51089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_regs_arr_64[] = {
52091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7,
53091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15
54efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
55089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage reserved_regs_arr_32[] = {rs_rX86_SP_32};
5676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenkostatic constexpr RegStorage reserved_regs_arr_64[] = {rs_rX86_SP_32};
57089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage reserved_regs_arr_64q[] = {rs_rX86_SP_64};
58089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_32[] = {rs_rAX, rs_rCX, rs_rDX, rs_rBX};
59089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_64[] = {
609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rAX, rs_rCX, rs_rDX, rs_rSI, rs_rDI,
619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_r8, rs_r9, rs_r10, rs_r11
629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko};
63089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage core_temps_arr_64q[] = {
640999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko    rs_r0q, rs_r1q, rs_r2q, rs_r6q, rs_r7q,
650999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko    rs_r8q, rs_r9q, rs_r10q, rs_r11q
660999a6f7c83d10aa59b75f079f0d2fdbac982cf7Dmitry Petrochenko};
67089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_temps_arr_32[] = {
689ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
699ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko};
70089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage sp_temps_arr_64[] = {
71091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rs_fr0, rs_fr1, rs_fr2, rs_fr3, rs_fr4, rs_fr5, rs_fr6, rs_fr7,
72091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rs_fr8, rs_fr9, rs_fr10, rs_fr11, rs_fr12, rs_fr13, rs_fr14, rs_fr15
73091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee};
74089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_temps_arr_32[] = {
759ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7,
769ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko};
77089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage dp_temps_arr_64[] = {
78091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rs_dr0, rs_dr1, rs_dr2, rs_dr3, rs_dr4, rs_dr5, rs_dr6, rs_dr7,
79091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    rs_dr8, rs_dr9, rs_dr10, rs_dr11, rs_dr12, rs_dr13, rs_dr14, rs_dr15
80091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee};
81091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
82089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage xp_temps_arr_32[] = {
83fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7,
84fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell};
85089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr RegStorage xp_temps_arr_64[] = {
86fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    rs_xr0, rs_xr1, rs_xr2, rs_xr3, rs_xr4, rs_xr5, rs_xr6, rs_xr7,
87fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    rs_xr8, rs_xr9, rs_xr10, rs_xr11, rs_xr12, rs_xr13, rs_xr14, rs_xr15
88fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell};
89fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
90089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> empty_pool;
91089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_32(core_regs_arr_32);
92089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_64(core_regs_arr_64);
93089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_regs_64q(core_regs_arr_64q);
94089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_regs_32(sp_regs_arr_32);
95089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_regs_64(sp_regs_arr_64);
96089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_regs_32(dp_regs_arr_32);
97089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_regs_64(dp_regs_arr_64);
98089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_32(reserved_regs_arr_32);
99089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_64(reserved_regs_arr_64);
100089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> reserved_regs_64q(reserved_regs_arr_64q);
101089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_32(core_temps_arr_32);
102089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_64(core_temps_arr_64);
103089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> core_temps_64q(core_temps_arr_64q);
104089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_temps_32(sp_temps_arr_32);
105089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> sp_temps_64(sp_temps_arr_64);
106089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_temps_32(dp_temps_arr_32);
107089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> dp_temps_64(dp_temps_arr_64);
108089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Marko
109089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> xp_temps_32(xp_temps_arr_32);
110089142cf1d0c028b5a7c703baf0b97f4a4ada3f7Vladimir Markostatic constexpr ArrayRef<const RegStorage> xp_temps_64(xp_temps_arr_64);
111fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1129ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_SP;
1139ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko
1149ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG0;
1159ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG1;
1169ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG2;
1179ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_ARG3;
11858994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_ARG4;
11958994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_ARG5;
1209ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG0;
1219ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG1;
1229ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG2;
1239ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_FARG3;
12458994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_FARG4;
12558994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_FARG5;
12658994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_FARG6;
12758994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoX86NativeRegisterPool rX86_FARG7;
1289ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_RET0;
1299ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_RET1;
1309ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_INVOKE_TGT;
1319ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoX86NativeRegisterPool rX86_COUNT;
1329ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko
1339ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG0;
1349ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG1;
1359ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG2;
1369ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_ARG3;
13758994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_ARG4;
13858994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_ARG5;
1399ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG0;
1409ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG1;
1419ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG2;
1429ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_FARG3;
14358994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG4;
14458994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG5;
14558994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG6;
14658994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage rs_rX86_FARG7;
1479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_RET0;
1489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_RET1;
1499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_INVOKE_TGT;
1509ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry PetrochenkoRegStorage rs_rX86_COUNT;
151efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1522ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturn() {
15300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  return x86_loc_c_return;
154efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
155efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
156a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbeeRegLocation X86Mir2Lir::LocCReturnRef() {
157a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  return cu_->target64 ? x86_64_loc_c_return_ref : x86_loc_c_return_ref;
158a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee}
159a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee
1602ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnWide() {
161dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  return cu_->target64 ? x86_64_loc_c_return_wide : x86_loc_c_return_wide;
162efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
163efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1642ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnFloat() {
16500e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  return x86_loc_c_return_float;
166efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
167efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
1682ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::LocCReturnDouble() {
16900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee  return x86_loc_c_return_double;
170efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
171efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
172a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu// Return a target-dependent special register for 32-bit.
173a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying FuRegStorage X86Mir2Lir::TargetReg32(SpecialTargetRegister reg) {
174091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  RegStorage res_reg = RegStorage::InvalidReg();
175efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  switch (reg) {
176091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kSelf: res_reg = RegStorage::InvalidReg(); break;
177091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kSuspend: res_reg =  RegStorage::InvalidReg(); break;
178091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kLr: res_reg =  RegStorage::InvalidReg(); break;
179091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kPc: res_reg =  RegStorage::InvalidReg(); break;
180091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kSp: res_reg =  rs_rX86_SP; break;
181091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kArg0: res_reg = rs_rX86_ARG0; break;
182091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kArg1: res_reg = rs_rX86_ARG1; break;
183091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kArg2: res_reg = rs_rX86_ARG2; break;
184091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kArg3: res_reg = rs_rX86_ARG3; break;
18558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case kArg4: res_reg = rs_rX86_ARG4; break;
18658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case kArg5: res_reg = rs_rX86_ARG5; break;
187091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kFArg0: res_reg = rs_rX86_FARG0; break;
188091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kFArg1: res_reg = rs_rX86_FARG1; break;
189091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kFArg2: res_reg = rs_rX86_FARG2; break;
190091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kFArg3: res_reg = rs_rX86_FARG3; break;
19158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case kFArg4: res_reg = rs_rX86_FARG4; break;
19258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case kFArg5: res_reg = rs_rX86_FARG5; break;
19358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case kFArg6: res_reg = rs_rX86_FARG6; break;
19458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case kFArg7: res_reg = rs_rX86_FARG7; break;
195091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kRet0: res_reg = rs_rX86_RET0; break;
196091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kRet1: res_reg = rs_rX86_RET1; break;
197091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kInvokeTgt: res_reg = rs_rX86_INVOKE_TGT; break;
198091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kHiddenArg: res_reg = rs_rAX; break;
199dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina    case kHiddenFpArg: DCHECK(!cu_->target64); res_reg = rs_fr0; break;
200091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    case kCount: res_reg = rs_rX86_COUNT; break;
20158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    default: res_reg = RegStorage::InvalidReg();
202091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  }
203091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  return res_reg;
204efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
205efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
206a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying FuRegStorage X86Mir2Lir::TargetReg(SpecialTargetRegister reg) {
207a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  LOG(FATAL) << "Do not use this function!!!";
208a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  return RegStorage::InvalidReg();
209a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu}
210a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu
211efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
212efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Decode the register id.
213efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
2148dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask X86Mir2Lir::GetRegMaskCommon(const RegStorage& reg) const {
2158dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  /* Double registers in x86 are just a single FP register. This is always just a single bit. */
2168dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  return ResourceMask::Bit(
2178dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko      /* FP register starts at bit position 16 */
2188dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko      ((reg.IsFloat() || reg.StorageSize() > 8) ? kX86FPReg0 : 0) + reg.GetRegNum());
2198dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko}
2208dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko
2218dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir MarkoResourceMask X86Mir2Lir::GetPCUseDefEncoding() const {
222efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  /*
223efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * FIXME: might make sense to use a virtual resource encoding bit for pc.  Might be
224efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   * able to clean up some of the x86/Arm_Mips differences
225efc6369224b036a1fb77849f7ae65b3492c832c0buzbee   */
22652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected call to GetPCUseDefEncoding for x86";
2278dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  return kEncodeNone;
228efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
229efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
2308dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid X86Mir2Lir::SetupTargetResourceMasks(LIR* lir, uint64_t flags,
2318dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko                                          ResourceMask* use_mask, ResourceMask* def_mask) {
2326a58cb16d803c9a7b3a75ccac8be19dd9d4e520dDmitry Petrochenko  DCHECK(cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64);
233b48819db07f9a0992a72173380c24249d7fc648abuzbee  DCHECK(!lir->flags.use_def_invalid);
234efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
235efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // X86-specific resource map setup here.
236efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_USE_SP) {
2378dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    use_mask->SetBit(kX86RegSP);
238efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
239efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
240efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_DEF_SP) {
2418dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    def_mask->SetBit(kX86RegSP);
242efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
243efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
244efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_DEFA) {
2458dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(def_mask, rs_rAX.GetReg());
246efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
247efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
248efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_DEFD) {
2498dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(def_mask, rs_rDX.GetReg());
250efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
251efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_USEA) {
2528dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(use_mask, rs_rAX.GetReg());
253efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
254efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
255efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_USEC) {
2568dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(use_mask, rs_rCX.GetReg());
257efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
258efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
259efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (flags & REG_USED) {
2608dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(use_mask, rs_rDX.GetReg());
261efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
26270b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko
26370b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko  if (flags & REG_USEB) {
2648dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(use_mask, rs_rBX.GetReg());
26570b797d998f2a28e39f7d6ffc8a07c9cbc47da14Vladimir Marko  }
2664028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
2674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Fixup hard to describe instruction: Uses rAX, rCX, rDI; sets rDI.
2684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  if (lir->opcode == kX86RepneScasw) {
2698dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(use_mask, rs_rAX.GetReg());
2708dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(use_mask, rs_rCX.GetReg());
2718dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(use_mask, rs_rDI.GetReg());
2728dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    SetupRegMask(def_mask, rs_rDI.GetReg());
2734028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
274e90501da0222717d75c126ebf89569db3976927eSerguei Katkov
275e90501da0222717d75c126ebf89569db3976927eSerguei Katkov  if (flags & USE_FP_STACK) {
2768dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    use_mask->SetBit(kX86FPStack);
2778dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    def_mask->SetBit(kX86FPStack);
278e90501da0222717d75c126ebf89569db3976927eSerguei Katkov  }
279efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
280efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
281efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* For dumping instructions */
282efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86RegName[] = {
283efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
284efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
285efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
286efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
287efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const char* x86CondName[] = {
288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "O",
289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "NO",
290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "B/NAE/C",
291efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "NB/AE/NC",
292efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "Z/EQ",
293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "NZ/NE",
294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "BE/NA",
295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "NBE/A",
296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "S",
297efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "NS",
298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "P/PE",
299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "NP/PO",
300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "L/NGE",
301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "NL/GE",
302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "LE/NG",
303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  "NLE/G"
304efc6369224b036a1fb77849f7ae65b3492c832c0buzbee};
305efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/*
307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Interpret a format string and build a string no longer than size
308efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See format key in Assemble.cc.
309efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */
3101fd3346740dfb7f47be9922312b68a4227fada96buzbeestd::string X86Mir2Lir::BuildInsnString(const char *fmt, LIR *lir, unsigned char* base_addr) {
311efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  std::string buf;
312efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  size_t i = 0;
313efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  size_t fmt_len = strlen(fmt);
314efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  while (i < fmt_len) {
315efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (fmt[i] != '!') {
316efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      buf += fmt[i];
317efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      i++;
318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    } else {
319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      i++;
320efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      DCHECK_LT(i, fmt_len);
321efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      char operand_number_ch = fmt[i];
322efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      i++;
323efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      if (operand_number_ch == '!') {
324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        buf += "!";
325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      } else {
326efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        int operand_number = operand_number_ch - '0';
327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        DCHECK_LT(operand_number, 6);  // Expect upto 6 LIR operands.
328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        DCHECK_LT(i, fmt_len);
329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        int operand = lir->operands[operand_number];
330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        switch (fmt[i]) {
331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee          case 'c':
332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            DCHECK_LT(static_cast<size_t>(operand), sizeof(x86CondName));
333efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            buf += x86CondName[operand];
334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            break;
335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee          case 'd':
336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            buf += StringPrintf("%d", operand);
337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            break;
3385192cbb12856b12620dc346758605baaa1469cedYixin Shou          case 'q': {
3395192cbb12856b12620dc346758605baaa1469cedYixin Shou             int64_t value = static_cast<int64_t>(static_cast<int64_t>(operand) << 32 |
3405192cbb12856b12620dc346758605baaa1469cedYixin Shou                             static_cast<uint32_t>(lir->operands[operand_number+1]));
3415192cbb12856b12620dc346758605baaa1469cedYixin Shou             buf +=StringPrintf("%" PRId64, value);
3425192cbb12856b12620dc346758605baaa1469cedYixin Shou          }
343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee          case 'p': {
3440d82948094d9a198e01aa95f64012bdedd5b6fc9buzbee            EmbeddedData *tab_rec = reinterpret_cast<EmbeddedData*>(UnwrapPointer(operand));
345fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee            buf += StringPrintf("0x%08x", tab_rec->offset);
346efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            break;
347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee          }
348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee          case 'r':
349091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee            if (RegStorage::IsFloat(operand)) {
350091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee              int fp_reg = RegStorage::RegNum(operand);
351efc6369224b036a1fb77849f7ae65b3492c832c0buzbee              buf += StringPrintf("xmm%d", fp_reg);
352efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            } else {
353091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee              int reg_num = RegStorage::RegNum(operand);
354091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee              DCHECK_LT(static_cast<size_t>(reg_num), sizeof(x86RegName));
355091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee              buf += x86RegName[reg_num];
356efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            }
357efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            break;
358efc6369224b036a1fb77849f7ae65b3492c832c0buzbee          case 't':
359107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers            buf += StringPrintf("0x%08" PRIxPTR " (L%p)",
360107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers                                reinterpret_cast<uintptr_t>(base_addr) + lir->offset + operand,
361107c31e598b649a8bb8d959d6a0377937e63e624Ian Rogers                                lir->target);
362efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            break;
363efc6369224b036a1fb77849f7ae65b3492c832c0buzbee          default:
364efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            buf += StringPrintf("DecodeError '%c'", fmt[i]);
365efc6369224b036a1fb77849f7ae65b3492c832c0buzbee            break;
366efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        }
367efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        i++;
368efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      }
369efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
370efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
371efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return buf;
372efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
373efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3748dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Markovoid X86Mir2Lir::DumpResourceMask(LIR *x86LIR, const ResourceMask& mask, const char *prefix) {
375efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  char buf[256];
376efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  buf[0] = 0;
377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3788dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  if (mask.Equals(kEncodeAll)) {
379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    strcpy(buf, "all");
380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  } else {
381efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    char num[8];
382efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    int i;
383efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
384efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    for (i = 0; i < kX86RegEnd; i++) {
3858dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko      if (mask.HasBit(i)) {
386988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers        snprintf(num, arraysize(num), "%d ", i);
387efc6369224b036a1fb77849f7ae65b3492c832c0buzbee        strcat(buf, num);
388efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      }
389efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
3918dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mask.HasBit(ResourceMask::kCCode)) {
392efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      strcat(buf, "cc ");
393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    /* Memory bits */
3958dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (x86LIR && (mask.HasBit(ResourceMask::kDalvikReg))) {
396988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers      snprintf(buf + strlen(buf), arraysize(buf) - strlen(buf), "dr%d%s",
397988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers               DECODE_ALIAS_INFO_REG(x86LIR->flags.alias_info),
398988e6ea9ac66edf1e205851df9bb53de3f3763f3Ian Rogers               (DECODE_ALIAS_INFO_WIDE(x86LIR->flags.alias_info)) ? "(+1)" : "");
399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
4008dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mask.HasBit(ResourceMask::kLiteral)) {
401efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      strcat(buf, "lit ");
402efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4048dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mask.HasBit(ResourceMask::kHeapRef)) {
405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      strcat(buf, "heap ");
406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
4078dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mask.HasBit(ResourceMask::kMustNotAlias)) {
408efc6369224b036a1fb77849f7ae65b3492c832c0buzbee      strcat(buf, "noalias ");
409efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  if (buf[0]) {
412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    LOG(INFO) << prefix << ": " <<  buf;
413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
41502031b185b4653e6c72e21f7a51238b903f6d638buzbee
4161fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::AdjustSpillMask() {
417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Adjustment for LR spilling, x86 has no LR so nothing to do here
418091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  core_spill_mask_ |= (1 << rs_rRET.GetRegNum());
4191fd3346740dfb7f47be9922312b68a4227fada96buzbee  num_core_spills_++;
420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
422e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark MendellRegStorage X86Mir2Lir::AllocateByteRegister() {
4237e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu  RegStorage reg = AllocTypedTemp(false, kCoreReg);
424dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (!cu_->target64) {
4257e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu    DCHECK_LT(reg.GetRegNum(), rs_rX86_SP.GetRegNum());
4267e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu  }
4277e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu  return reg;
4287e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu}
4297e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu
4307e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fubool X86Mir2Lir::IsByteRegister(RegStorage reg) {
431dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  return cu_->target64 || reg.GetRegNum() < rs_rX86_SP.GetRegNum();
432e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell}
433e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell
434efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Clobber all regs that might be used by an external C call */
43531c2aac7137b69d5622eea09597500731fbee2efVladimir Markovoid X86Mir2Lir::ClobberCallerSave() {
436091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rAX);
437091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rCX);
438091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rDX);
439091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rBX);
44035ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu
44135ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr0);
44235ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr1);
44335ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr2);
44435ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr3);
44535ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr4);
44635ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr5);
44735ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr6);
44835ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr7);
44935ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu
450dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
45135ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_r8);
45235ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_r9);
45335ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_r10);
45435ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_r11);
45535ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu
45635ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr8);
45735ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr9);
45835ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr10);
45935ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr11);
46035ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr12);
46135ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr13);
46235ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr14);
46335ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr15);
46435ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  }
465efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
466efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4671fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation X86Mir2Lir::GetReturnWideAlt() {
46852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  RegLocation res = LocCReturnWide();
469091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(res.reg.GetLowReg() == rs_rAX.GetReg());
470091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(res.reg.GetHighReg() == rs_rDX.GetReg());
471091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rAX);
472091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rDX);
473091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  MarkInUse(rs_rAX);
474091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  MarkInUse(rs_rDX);
475091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  MarkWide(res.reg);
476efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
477efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
478efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4792ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::GetReturnAlt() {
48052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  RegLocation res = LocCReturn();
481091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  res.reg.SetReg(rs_rDX.GetReg());
482091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rDX);
483091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  MarkInUse(rs_rDX);
484efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
485efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
486efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
487efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */
4882ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::LockCallTemps() {
489091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rX86_ARG0);
490091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rX86_ARG1);
491091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rX86_ARG2);
492091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rX86_ARG3);
493dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
49458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_ARG4);
49558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_ARG5);
49658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG0);
49758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG1);
49858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG2);
49958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG3);
50058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG4);
50158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG5);
50258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG6);
50358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG7);
50458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
505efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
506efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
507efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */
5082ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::FreeCallTemps() {
509091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rX86_ARG0);
510091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rX86_ARG1);
511091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rX86_ARG2);
512091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rX86_ARG3);
513dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
51458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_ARG4);
51558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_ARG5);
51658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG0);
51758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG1);
51858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG2);
51958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG3);
52058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG4);
52158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG5);
52258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG6);
52358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG7);
52458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
525efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
526efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
52799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusorubool X86Mir2Lir::ProvidesFullMemoryBarrier(X86OpCode opcode) {
52899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    switch (opcode) {
52999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      case kX86LockCmpxchgMR:
53099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      case kX86LockCmpxchgAR:
5310f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers      case kX86LockCmpxchg64M:
5320f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers      case kX86LockCmpxchg64A:
53399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      case kX86XchgMR:
53499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      case kX86Mfence:
53599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru        // Atomic memory instructions provide full barrier.
53699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru        return true;
53799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      default:
53899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru        break;
53999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    }
54099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
54199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    // Conservative if cannot prove it provides full barrier.
54299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    return false;
54399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru}
54499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
545b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampebool X86Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
546efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0
54799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  // Start off with using the last LIR as the barrier. If it is not enough, then we will update it.
54899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  LIR* mem_barrier = last_lir_insn_;
54999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
550b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe  bool ret = false;
55199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  /*
55299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru   * According to the JSR-133 Cookbook, for x86 only StoreLoad barriers need memory fence. All other barriers
55399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru   * (LoadLoad, LoadStore, StoreStore) are nops due to the x86 memory model. For those cases, all we need
55499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru   * to ensure is that there is a scheduling barrier in place.
55599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru   */
55699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  if (barrier_kind == kStoreLoad) {
55799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    // If no LIR exists already that can be used a barrier, then generate an mfence.
55899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    if (mem_barrier == nullptr) {
55999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      mem_barrier = NewLIR0(kX86Mfence);
560b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe      ret = true;
56199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    }
56299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
56399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    // If last instruction does not provide full barrier, then insert an mfence.
56499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    if (ProvidesFullMemoryBarrier(static_cast<X86OpCode>(mem_barrier->opcode)) == false) {
56599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      mem_barrier = NewLIR0(kX86Mfence);
566b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe      ret = true;
56799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    }
56899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  }
56999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
57099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  // Now ensure that a scheduling barrier is in place.
57199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  if (mem_barrier == nullptr) {
57299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    GenBarrier();
57399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  } else {
57499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    // Mark as a scheduling barrier.
57599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    DCHECK(!mem_barrier->flags.use_def_invalid);
5768dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    mem_barrier->u.m.def_mask = &kEncodeAll;
57799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  }
578b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe  return ret;
579b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe#else
580b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe  return false;
581efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif
582efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
58300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
5841fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::CompilerInitializeRegAlloc() {
585dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
58676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64q, sp_regs_64,
58776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko                                          dp_regs_64, reserved_regs_64, reserved_regs_64q,
58876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko                                          core_temps_64, core_temps_64q, sp_temps_64, dp_temps_64);
5899ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  } else {
590b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee    reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, sp_regs_32,
591b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee                                          dp_regs_32, reserved_regs_32, empty_pool,
592b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee                                          core_temps_32, empty_pool, sp_temps_32, dp_temps_32);
5939ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  }
594091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
595091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Target-specific adjustments.
596091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
597fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Add in XMM registers.
598dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  const ArrayRef<const RegStorage> *xp_temps = cu_->target64 ? &xp_temps_64 : &xp_temps_32;
599fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  for (RegStorage reg : *xp_temps) {
600fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    RegisterInfo* info = new (arena_) RegisterInfo(reg, GetRegMaskCommon(reg));
601fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    reginfo_map_.Put(reg.GetReg(), info);
602fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    info->SetIsTemp(true);
603fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
604fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
605091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Alias single precision xmm to double xmms.
606091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // TODO: as needed, add larger vector sizes - alias all to the largest.
607091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
608091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
609091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    int sp_reg_num = info->GetReg().GetRegNum();
610fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    RegStorage xp_reg = RegStorage::Solo128(sp_reg_num);
611fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    RegisterInfo* xp_reg_info = GetRegInfo(xp_reg);
612fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    // 128-bit xmm vector register's master storage should refer to itself.
613fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    DCHECK_EQ(xp_reg_info, xp_reg_info->Master());
614fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
615fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    // Redirect 32-bit vector's master storage to 128-bit vector.
616fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    info->SetMaster(xp_reg_info);
617fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
61876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    RegStorage dp_reg = RegStorage::FloatSolo64(sp_reg_num);
619091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
620fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    // Redirect 64-bit vector's master storage to 128-bit vector.
621fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    dp_reg_info->SetMaster(xp_reg_info);
62276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    // Singles should show a single 32-bit mask bit, at first referring to the low half.
62376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    DCHECK_EQ(info->StorageMask(), 0x1U);
62476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko  }
62576af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko
626dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
62776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    // Alias 32bit W registers to corresponding 64bit X registers.
62876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    GrowableArray<RegisterInfo*>::Iterator w_it(&reg_pool_->core_regs_);
62976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    for (RegisterInfo* info = w_it.Next(); info != nullptr; info = w_it.Next()) {
63076af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      int x_reg_num = info->GetReg().GetRegNum();
63176af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      RegStorage x_reg = RegStorage::Solo64(x_reg_num);
63276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      RegisterInfo* x_reg_info = GetRegInfo(x_reg);
63376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      // 64bit X register's master storage should refer to itself.
63476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      DCHECK_EQ(x_reg_info, x_reg_info->Master());
63576af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      // Redirect 32bit W master storage to 64bit X.
63676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      info->SetMaster(x_reg_info);
63776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      // 32bit W should show a single 32-bit mask bit, at first referring to the low half.
63876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      DCHECK_EQ(info->StorageMask(), 0x1U);
63976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    }
640efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
641091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
642091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
643091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // TODO: adjust for x86/hard float calling convention.
644091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  reg_pool_->next_core_reg_ = 2;
645091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  reg_pool_->next_sp_reg_ = 2;
646091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  reg_pool_->next_dp_reg_ = 1;
647efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
648efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6491fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::SpillCoreRegs() {
6501fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (num_core_spills_ == 0) {
651efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return;
652efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
653efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Spill mask not including fake return address register
654091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum());
6559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_);
656efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  for (int reg = 0; mask; mask >>= 1, reg++) {
657efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (mask & 0x1) {
6582700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      StoreWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg));
6599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      offset += GetInstructionSetPointerSize(cu_->instruction_set);
660efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
661efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
662efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
663efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6641fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::UnSpillCoreRegs() {
6651fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (num_core_spills_ == 0) {
666efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return;
667efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
668efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Spill mask not including fake return address register
669091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum());
6709ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_);
671efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  for (int reg = 0; mask; mask >>= 1, reg++) {
672efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (mask & 0x1) {
6732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      LoadWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg));
6749ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      offset += GetInstructionSetPointerSize(cu_->instruction_set);
675efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
676efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
677efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
678efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6792ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::IsUnconditionalBranch(LIR* lir) {
680cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32);
681efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
682efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
683674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Markobool X86Mir2Lir::SupportsVolatileLoadStore(OpSize size) {
684674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  return true;
685674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko}
686674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko
687674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoRegisterClass X86Mir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
688e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  // X86_64 can handle any size.
689dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
690e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    if (size == kReference) {
691e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      return kRefReg;
692e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    }
693e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    return kCoreReg;
694e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  }
695e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu
696674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  if (UNLIKELY(is_volatile)) {
697674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko    // On x86, atomic 64-bit load/store requires an fp register.
698674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko    // Smaller aligned load/store is atomic for both core and fp registers.
699674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko    if (size == k64 || size == kDouble) {
700674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko      return kFPReg;
701674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko    }
702674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  }
703674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  return RegClassBySize(size);
704674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko}
705674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko
706dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena SayapinaX86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
70755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell    : Mir2Lir(cu, mir_graph, arena),
708dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      base_of_code_(nullptr), store_method_addr_(false), store_method_addr_used_(false),
70955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      method_address_insns_(arena, 100, kGrowableArrayMisc),
71055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      class_type_address_insns_(arena, 100, kGrowableArrayMisc),
711ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      call_method_insns_(arena, 100, kGrowableArrayMisc),
712dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina      stack_decrement_(nullptr), stack_increment_(nullptr),
713d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      const_vectors_(nullptr) {
714d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  store_method_addr_used_ = false;
715dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  if (kIsDebugBuild) {
716dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers    for (int i = 0; i < kX86Last; i++) {
717dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      if (X86Mir2Lir::EncodingMap[i].opcode != i) {
718dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers        LOG(FATAL) << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name
719d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                   << " is wrong: expecting " << i << ", seeing "
720d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                   << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode);
721dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      }
722efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
723efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
724dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
7259ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_SP = rs_rX86_SP_64;
7269ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko
7279ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG0 = rs_rDI;
7289ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG1 = rs_rSI;
7299ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG2 = rs_rDX;
7309ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG3 = rs_rCX;
73158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_ARG4 = rs_r8;
73258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_ARG5 = rs_r9;
73358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG0 = rs_fr0;
73458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG1 = rs_fr1;
73558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG2 = rs_fr2;
73658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG3 = rs_fr3;
73758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG4 = rs_fr4;
73858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG5 = rs_fr5;
73958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG6 = rs_fr6;
74058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG7 = rs_fr7;
7419ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG0 = rDI;
7429ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG1 = rSI;
7439ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG2 = rDX;
7449ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG3 = rCX;
74558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_ARG4 = r8;
74658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_ARG5 = r9;
74758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG0 = fr0;
74858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG1 = fr1;
74958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG2 = fr2;
75058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG3 = fr3;
75158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG4 = fr4;
75258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG5 = fr5;
75358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG6 = fr6;
75458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG7 = fr7;
75555884bc1e2e1b324809b462455ccaf5811ffafd8Mark Mendell    rs_rX86_INVOKE_TGT = rs_rDI;
7569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  } else {
7579ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_SP = rs_rX86_SP_32;
7589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko
7599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG0 = rs_rAX;
7609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG1 = rs_rCX;
7619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG2 = rs_rDX;
7629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG3 = rs_rBX;
76358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_ARG4 = RegStorage::InvalidReg();
76458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_ARG5 = RegStorage::InvalidReg();
76558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG0 = rs_rAX;
76658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG1 = rs_rCX;
76758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG2 = rs_rDX;
76858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG3 = rs_rBX;
76958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG4 = RegStorage::InvalidReg();
77058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG5 = RegStorage::InvalidReg();
77158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG6 = RegStorage::InvalidReg();
77258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG7 = RegStorage::InvalidReg();
7739ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG0 = rAX;
7749ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG1 = rCX;
7759ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG2 = rDX;
7769ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG3 = rBX;
77758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG0 = rAX;
77858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG1 = rCX;
77958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG2 = rDX;
78058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG3 = rBX;
78155884bc1e2e1b324809b462455ccaf5811ffafd8Mark Mendell    rs_rX86_INVOKE_TGT = rs_rAX;
78258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // TODO(64): Initialize with invalid reg
78358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko//    rX86_ARG4 = RegStorage::InvalidReg();
78458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko//    rX86_ARG5 = RegStorage::InvalidReg();
7859ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  }
7869ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rs_rX86_RET0 = rs_rAX;
7879ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rs_rX86_RET1 = rs_rDX;
7889ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rs_rX86_COUNT = rs_rCX;
7899ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rX86_RET0 = rAX;
7909ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rX86_RET1 = rDX;
7919ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rX86_INVOKE_TGT = rAX;
7929ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rX86_COUNT = rCX;
7931fd3346740dfb7f47be9922312b68a4227fada96buzbee}
7941fd3346740dfb7f47be9922312b68a4227fada96buzbee
795862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
796862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee                          ArenaAllocator* const arena) {
797dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  return new X86Mir2Lir(cu, mir_graph, arena);
798efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
799efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
800efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Not used in x86
801dd7624d2b9e599d57762d12031b10b89defc9807Ian RogersRegStorage X86Mir2Lir::LoadHelper(ThreadOffset<4> offset) {
80252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of LoadHelper in x86";
8032700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  return RegStorage::InvalidReg();
804efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
805efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
8062f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe// Not used in x86
8072f244e9faccfcca68af3c5484c397a01a1c3a342Andreas GampeRegStorage X86Mir2Lir::LoadHelper(ThreadOffset<8> offset) {
8082f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  LOG(FATAL) << "Unexpected use of LoadHelper in x86";
8092f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  return RegStorage::InvalidReg();
8102f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe}
8112f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe
812b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave AllisonLIR* X86Mir2Lir::CheckSuspendUsingLoad() {
813b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison  LOG(FATAL) << "Unexpected use of CheckSuspendUsingLoad in x86";
814b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison  return nullptr;
815b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison}
816b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison
8172ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t X86Mir2Lir::GetTargetInstFlags(int opcode) {
818409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
8191fd3346740dfb7f47be9922312b68a4227fada96buzbee  return X86Mir2Lir::EncodingMap[opcode].flags;
8201bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee}
8211bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
8222ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstName(int opcode) {
823409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
8241fd3346740dfb7f47be9922312b68a4227fada96buzbee  return X86Mir2Lir::EncodingMap[opcode].name;
8251bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee}
8261bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
8272ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstFmt(int opcode) {
828409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
8291fd3346740dfb7f47be9922312b68a4227fada96buzbee  return X86Mir2Lir::EncodingMap[opcode].fmt;
8301bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee}
8311bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
832d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbeevoid X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) {
833d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  // Can we do this directly to memory?
834d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  rl_dest = UpdateLocWide(rl_dest);
835d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  if ((rl_dest.location == kLocDalvikFrame) ||
836d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee      (rl_dest.location == kLocCompilerTemp)) {
837d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    int32_t val_lo = Low32Bits(value);
838d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    int32_t val_hi = High32Bits(value);
839a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    int r_base = rs_rX86_SP.GetReg();
840d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    int displacement = SRegOffset(rl_dest.s_reg_low);
841d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee
8428dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
8432700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LIR * store = NewLIR3(kX86Mov32MI, r_base, displacement + LOWORD_OFFSET, val_lo);
844d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2,
845d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee                              false /* is_load */, true /* is64bit */);
8462700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    store = NewLIR3(kX86Mov32MI, r_base, displacement + HIWORD_OFFSET, val_hi);
847d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2,
848d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee                              false /* is_load */, true /* is64bit */);
849d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    return;
850d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  }
851d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee
852d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  // Just use the standard code to do the generation.
853d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  Mir2Lir::GenConstWide(rl_dest, value);
854d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee}
855e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell
856e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell// TODO: Merge with existing RegLocation dumper in vreg_analysis.cc
857e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendellvoid X86Mir2Lir::DumpRegLocation(RegLocation loc) {
858e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell  LOG(INFO)  << "location: " << loc.location << ','
859e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.wide ? " w" : "  ")
860e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.defined ? " D" : "  ")
861e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.is_const ? " c" : "  ")
862e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.fp ? " F" : "  ")
863e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.core ? " C" : "  ")
864e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.ref ? " r" : "  ")
865e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.high_word ? " h" : "  ")
866e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.home ? " H" : "  ")
8672700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee             << ", low: " << static_cast<int>(loc.reg.GetLowReg())
86800e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee             << ", high: " << static_cast<int>(loc.reg.GetHighReg())
869e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << ", s_reg: " << loc.s_reg_low
870e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << ", orig: " << loc.orig_sreg;
871e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell}
872e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell
87367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::Materialize() {
87467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // A good place to put the analysis before starting.
87567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  AnalyzeMIR();
87667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
87767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // Now continue with regular code generation.
87867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  Mir2Lir::Materialize();
87967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell}
88067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
88149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Haovoid X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type,
88255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                                   SpecialTargetRegister symbolic_reg) {
88355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  /*
88455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * For x86, just generate a 32 bit move immediate instruction, that will be filled
88555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * in at 'link time'.  For now, put a unique value based on target to ensure that
88655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * code deduplication works.
88755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   */
88849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  int target_method_idx = target_method.dex_method_index;
88949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  const DexFile* target_dex_file = target_method.dex_file;
89049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
89149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id);
89255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
89349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  // Generate the move instruction with the unique pointer and save index, dex_file, and type.
894a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg, false).GetReg(),
89549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                     static_cast<int>(target_method_id_ptr), target_method_idx,
89649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                     WrapPointer(const_cast<DexFile*>(target_dex_file)), type);
89755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  AppendLIR(move);
89855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  method_address_insns_.Insert(move);
89955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell}
90055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
90155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg) {
90255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  /*
90355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * For x86, just generate a 32 bit move immediate instruction, that will be filled
90455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * in at 'link time'.  For now, put a unique value based on target to ensure that
90555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * code deduplication works.
90655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   */
90755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  const DexFile::TypeId& id = cu_->dex_file->GetTypeId(type_idx);
90855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  uintptr_t ptr = reinterpret_cast<uintptr_t>(&id);
90955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
91055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // Generate the move instruction with the unique pointer and save index and type.
911a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg, false).GetReg(),
91255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                     static_cast<int>(ptr), type_idx);
91355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  AppendLIR(move);
91455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  class_type_address_insns_.Insert(move);
91555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell}
91655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
91749161cef10a308aedada18e9aa742498d6e6c8c7Jeff HaoLIR *X86Mir2Lir::CallWithLinkerFixup(const MethodReference& target_method, InvokeType type) {
91855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  /*
91955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * For x86, just generate a 32 bit call relative instruction, that will be filled
92055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * in at 'link time'.  For now, put a unique value based on target to ensure that
92155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * code deduplication works.
92255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   */
92349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  int target_method_idx = target_method.dex_method_index;
92449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  const DexFile* target_dex_file = target_method.dex_file;
92549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
92649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id);
92749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao
92849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  // Generate the call instruction with the unique pointer and save index, dex_file, and type.
92949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  LIR *call = RawLIR(current_dalvik_offset_, kX86CallI, static_cast<int>(target_method_id_ptr),
93049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                     target_method_idx, WrapPointer(const_cast<DexFile*>(target_dex_file)), type);
93155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  AppendLIR(call);
93255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  call_method_insns_.Insert(call);
93355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  return call;
93455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell}
93555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
936d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell/*
937d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell * @brief Enter a 32 bit quantity into a buffer
938d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell * @param buf buffer.
939d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell * @param data Data value.
940d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell */
941d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
942d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellstatic void PushWord(std::vector<uint8_t>&buf, int32_t data) {
943d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  buf.push_back(data & 0xff);
944d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  buf.push_back((data >> 8) & 0xff);
945d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  buf.push_back((data >> 16) & 0xff);
946d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  buf.push_back((data >> 24) & 0xff);
947d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
948d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
94955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::InstallLiteralPools() {
95055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // These are handled differently for x86.
95155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  DCHECK(code_literal_list_ == nullptr);
95255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  DCHECK(method_literal_list_ == nullptr);
95355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  DCHECK(class_literal_list_ == nullptr);
95455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
955d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Align to 16 byte boundary.  We have implicit knowledge that the start of the method is
956d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // on a 4 byte boundary.   How can I check this if it changes (other than aligned loads
957d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // will fail at runtime)?
958d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  if (const_vectors_ != nullptr) {
959d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    int align_size = (16-4) - (code_buffer_.size() & 0xF);
960d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    if (align_size < 0) {
961d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      align_size += 16;
962d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    }
963d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
964d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    while (align_size > 0) {
965d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      code_buffer_.push_back(0);
966d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      align_size--;
967d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    }
968d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    for (LIR *p = const_vectors_; p != nullptr; p = p->next) {
969d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      PushWord(code_buffer_, p->operands[0]);
970d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      PushWord(code_buffer_, p->operands[1]);
971d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      PushWord(code_buffer_, p->operands[2]);
972d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      PushWord(code_buffer_, p->operands[3]);
973d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    }
974d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
975d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
97655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // Handle the fixups for methods.
97755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  for (uint32_t i = 0; i < method_address_insns_.Size(); i++) {
97855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      LIR* p = method_address_insns_.Get(i);
97955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      DCHECK_EQ(p->opcode, kX86Mov32RI);
98049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      uint32_t target_method_idx = p->operands[2];
98149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      const DexFile* target_dex_file =
98249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao          reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3]));
98355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
98455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      // The offset to patch is the last 4 bytes of the instruction.
98555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      int patch_offset = p->offset + p->flags.size - 4;
98655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      cu_->compiler_driver->AddMethodPatch(cu_->dex_file, cu_->class_def_idx,
98755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                                           cu_->method_idx, cu_->invoke_type,
98849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                           target_method_idx, target_dex_file,
98949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                           static_cast<InvokeType>(p->operands[4]),
99055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                                           patch_offset);
99155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  }
99255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
99355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // Handle the fixups for class types.
99455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  for (uint32_t i = 0; i < class_type_address_insns_.Size(); i++) {
99555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      LIR* p = class_type_address_insns_.Get(i);
99655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      DCHECK_EQ(p->opcode, kX86Mov32RI);
99749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      uint32_t target_method_idx = p->operands[2];
99855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
99955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      // The offset to patch is the last 4 bytes of the instruction.
100055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      int patch_offset = p->offset + p->flags.size - 4;
100155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      cu_->compiler_driver->AddClassPatch(cu_->dex_file, cu_->class_def_idx,
100249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                          cu_->method_idx, target_method_idx, patch_offset);
100355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  }
100455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
100555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // And now the PC-relative calls to methods.
100655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  for (uint32_t i = 0; i < call_method_insns_.Size(); i++) {
100755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      LIR* p = call_method_insns_.Get(i);
100855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      DCHECK_EQ(p->opcode, kX86CallI);
100949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      uint32_t target_method_idx = p->operands[1];
101049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      const DexFile* target_dex_file =
101149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao          reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2]));
101255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
101355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      // The offset to patch is the last 4 bytes of the instruction.
101455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      int patch_offset = p->offset + p->flags.size - 4;
101555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      cu_->compiler_driver->AddRelativeCodePatch(cu_->dex_file, cu_->class_def_idx,
101649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                                 cu_->method_idx, cu_->invoke_type,
101749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                                 target_method_idx, target_dex_file,
101849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                                 static_cast<InvokeType>(p->operands[3]),
101955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                                                 patch_offset, -4 /* offset */);
102055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  }
102155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
102255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // And do the normal processing.
102355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  Mir2Lir::InstallLiteralPools();
102455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell}
102555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
102670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolovbool X86Mir2Lir::GenInlinedArrayCopyCharArray(CallInfo* info) {
102770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  if (cu_->target64) {
102870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    // TODO: Implement ArrayCOpy intrinsic for x86_64
102970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    return false;
103070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  }
103170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov
103270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  RegLocation rl_src = info->args[0];
103370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  RegLocation rl_srcPos = info->args[1];
103470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  RegLocation rl_dst = info->args[2];
103570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  RegLocation rl_dstPos = info->args[3];
103670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  RegLocation rl_length = info->args[4];
103770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  if (rl_srcPos.is_const && (mir_graph_->ConstantValue(rl_srcPos) < 0)) {
103870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    return false;
103970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  }
104070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  if (rl_dstPos.is_const && (mir_graph_->ConstantValue(rl_dstPos) < 0)) {
104170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    return false;
104270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  }
104370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  ClobberCallerSave();
104470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LockCallTemps();  // Using fixed registers
104570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_src , rs_rAX);
104670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_dst , rs_rCX);
104770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* src_dst_same  = OpCmpBranch(kCondEq, rs_rAX , rs_rCX, nullptr);
104870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* src_null_branch = OpCmpImmBranch(kCondEq, rs_rAX , 0, nullptr);
104970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* dst_null_branch = OpCmpImmBranch(kCondEq, rs_rCX , 0, nullptr);
105070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_length , rs_rDX);
105170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* len_negative  = OpCmpImmBranch(kCondLt, rs_rDX , 0, nullptr);
105270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* len_too_big  = OpCmpImmBranch(kCondGt, rs_rDX , 128, nullptr);
105370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_src , rs_rAX);
105470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadWordDisp(rs_rAX , mirror::Array::LengthOffset().Int32Value(), rs_rAX);
105570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* src_bad_len  = nullptr;
105670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* srcPos_negative  = nullptr;
105770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  if (!rl_srcPos.is_const) {
105870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    LoadValueDirectFixed(rl_srcPos , rs_rBX);
105970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    srcPos_negative  = OpCmpImmBranch(kCondLt, rs_rBX , 0, nullptr);
106070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    OpRegReg(kOpAdd, rs_rBX, rs_rDX);
106170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    src_bad_len  = OpCmpBranch(kCondLt, rs_rAX , rs_rBX, nullptr);
106270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  } else {
106370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    int pos_val = mir_graph_->ConstantValue(rl_srcPos.orig_sreg);
106470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    if (pos_val == 0) {
106570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov      src_bad_len  = OpCmpBranch(kCondLt, rs_rAX , rs_rDX, nullptr);
106670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    } else {
106770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov      OpRegRegImm(kOpAdd, rs_rBX,  rs_rDX, pos_val);
106870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov      src_bad_len  = OpCmpBranch(kCondLt, rs_rAX , rs_rBX, nullptr);
106970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    }
107070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  }
107170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* dstPos_negative = nullptr;
107270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* dst_bad_len = nullptr;
107370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_dst, rs_rAX);
107470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadWordDisp(rs_rAX, mirror::Array::LengthOffset().Int32Value(), rs_rAX);
107570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  if (!rl_dstPos.is_const) {
107670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    LoadValueDirectFixed(rl_dstPos , rs_rBX);
107770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    dstPos_negative = OpCmpImmBranch(kCondLt, rs_rBX , 0, nullptr);
107870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    OpRegRegReg(kOpAdd, rs_rBX, rs_rBX, rs_rDX);
107970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    dst_bad_len = OpCmpBranch(kCondLt, rs_rAX , rs_rBX, nullptr);
108070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  } else {
108170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    int pos_val = mir_graph_->ConstantValue(rl_dstPos.orig_sreg);
108270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    if (pos_val == 0) {
108370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov      dst_bad_len = OpCmpBranch(kCondLt, rs_rAX , rs_rDX, nullptr);
108470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    } else {
108570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov      OpRegRegImm(kOpAdd, rs_rBX,  rs_rDX, pos_val);
108670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov      dst_bad_len = OpCmpBranch(kCondLt, rs_rAX , rs_rBX, nullptr);
108770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    }
108870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  }
108970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  // everything is checked now
109070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_src , rs_rAX);
109170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_dst , rs_rBX);
109270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_srcPos , rs_rCX);
109370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  NewLIR5(kX86Lea32RA, rs_rAX.GetReg(), rs_rAX.GetReg(),
109470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov       rs_rCX.GetReg() , 1, mirror::Array::DataOffset(2).Int32Value());
109570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  // RAX now holds the address of the first src element to be copied
109670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov
109770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_dstPos , rs_rCX);
109870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  NewLIR5(kX86Lea32RA, rs_rBX.GetReg(), rs_rBX.GetReg(),
109970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov       rs_rCX.GetReg() , 1, mirror::Array::DataOffset(2).Int32Value() );
110070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  // RBX now holds the address of the first dst element to be copied
110170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov
110270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  // check if the number of elements to be copied is odd or even. If odd
110370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  // then copy the first element (so that the remaining number of elements
110470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  // is even).
110570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadValueDirectFixed(rl_length , rs_rCX);
110670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  OpRegImm(kOpAnd, rs_rCX, 1);
110770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* jmp_to_begin_loop  = OpCmpImmBranch(kCondEq, rs_rCX, 0, nullptr);
110870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  OpRegImm(kOpSub, rs_rDX, 1);
110970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadBaseIndexedDisp(rs_rAX, rs_rDX, 1, 0, rs_rCX, kSignedHalf);
111070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  StoreBaseIndexedDisp(rs_rBX, rs_rDX, 1, 0, rs_rCX, kSignedHalf);
111170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov
111270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  // since the remaining number of elements is even, we will copy by
111370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  // two elements at a time.
111470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR *beginLoop = NewLIR0(kPseudoTargetLabel);
111570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* jmp_to_ret  = OpCmpImmBranch(kCondEq, rs_rDX , 0, nullptr);
111670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  OpRegImm(kOpSub, rs_rDX, 2);
111770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LoadBaseIndexedDisp(rs_rAX, rs_rDX, 1, 0, rs_rCX, kSingle);
111870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  StoreBaseIndexedDisp(rs_rBX, rs_rDX, 1, 0, rs_rCX, kSingle);
111970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  OpUnconditionalBranch(beginLoop);
112070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR *check_failed = NewLIR0(kPseudoTargetLabel);
112170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR* launchpad_branch  = OpUnconditionalBranch(nullptr);
112270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  LIR *return_point = NewLIR0(kPseudoTargetLabel);
112370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  jmp_to_ret->target = return_point;
112470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  jmp_to_begin_loop->target = beginLoop;
112570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  src_dst_same->target = check_failed;
112670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  len_negative->target = check_failed;
112770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  len_too_big->target = check_failed;
112870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  src_null_branch->target = check_failed;
112970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  if (srcPos_negative != nullptr)
113070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    srcPos_negative ->target = check_failed;
113170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  if (src_bad_len != nullptr)
113270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    src_bad_len->target = check_failed;
113370c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  dst_null_branch->target = check_failed;
113470c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  if (dstPos_negative != nullptr)
113570c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    dstPos_negative->target = check_failed;
113670c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  if (dst_bad_len != nullptr)
113770c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov    dst_bad_len->target = check_failed;
113870c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  AddIntrinsicSlowPath(info, launchpad_branch, return_point);
113970c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov  return true;
114070c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov}
114170c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov
114270c4f06f9965cdb9319a2c85f65acda20086d765DaniilSokolov
11434028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell/*
11444028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * Fast string.index_of(I) & (II).  Inline check for simple case of char <= 0xffff,
11454028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * otherwise bails to standard library code.
11464028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell */
11474028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendellbool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) {
11484028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  ClobberCallerSave();
11494028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LockCallTemps();  // Using fixed registers
11504028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11514028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // EAX: 16 bit character being searched.
11524028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // ECX: count: number of words to be searched.
11534028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // EDI: String being searched.
11544028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // EDX: temporary during execution.
1155c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  // EBX or R11: temporary during execution (depending on mode).
11564028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11574028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  RegLocation rl_obj = info->args[0];
11584028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  RegLocation rl_char = info->args[1];
1159a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee  RegLocation rl_start;  // Note: only present in III flavor or IndexOf.
1160c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  RegStorage tmpReg = cu_->target64 ? rs_r11 : rs_rBX;
11614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  uint32_t char_value =
11634028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    rl_char.is_const ? mir_graph_->ConstantValue(rl_char.orig_sreg) : 0;
11644028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11654028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  if (char_value > 0xFFFF) {
11664028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // We have to punt to the real String.indexOf.
11674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    return false;
11684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
11694028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11704028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Okay, we are commited to inlining this.
1171a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee  RegLocation rl_return = GetReturn(kCoreReg);
11724028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  RegLocation rl_dest = InlineTarget(info);
11734028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11744028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Is the string non-NULL?
11752700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LoadValueDirectFixed(rl_obj, rs_rDX);
11762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  GenNullCheck(rs_rDX, info->opt_flags);
11773bc8615332b7848dec8c2297a40f7e4d176c0efbVladimir Marko  info->opt_flags |= MIR_IGNORE_NULL_CHECK;  // Record that we've null checked.
11784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11794028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Does the character fit in 16 bits?
11803a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang  LIR* slowpath_branch = nullptr;
11814028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  if (rl_char.is_const) {
11824028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // We need the value in EAX.
11832700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LoadConstantNoClobber(rs_rAX, char_value);
11844028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  } else {
11854028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // Character is not a constant; compare at runtime.
11862700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LoadValueDirectFixed(rl_char, rs_rAX);
11873a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang    slowpath_branch = OpCmpImmBranch(kCondGt, rs_rAX, 0xFFFF, nullptr);
11884028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
11894028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // From here down, we know that we are looking for a char that fits in 16 bits.
1191e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // Location of reference to data array within the String object.
1192e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  int value_offset = mirror::String::ValueOffset().Int32Value();
1193e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // Location of count within the String object.
1194e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  int count_offset = mirror::String::CountOffset().Int32Value();
1195e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // Starting offset within data array.
1196e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  int offset_offset = mirror::String::OffsetOffset().Int32Value();
1197e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // Start of char data with array_.
1198e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value();
11994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12004028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Character is in EAX.
12014028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Object pointer is in EDX.
12024028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12034028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // We need to preserve EDI, but have no spare registers, so push it on the stack.
12044028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // We have to remember that all stack addresses after this are offset by sizeof(EDI).
1205091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR1(kX86Push32R, rs_rDI.GetReg());
12064028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12074028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Compute the number of words to search in to rCX.
1208695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  Load32Disp(rs_rDX, count_offset, rs_rCX);
12094028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LIR *length_compare = nullptr;
12104028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  int start_value = 0;
1211a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov  bool is_index_on_stack = false;
12124028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  if (zero_based) {
12134028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // We have to handle an empty string.  Use special instruction JECXZ.
12144028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    length_compare = NewLIR0(kX86Jecxz8);
12154028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  } else {
1216a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee    rl_start = info->args[2];
12174028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // We have to offset by the start index.
12184028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    if (rl_start.is_const) {
12194028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      start_value = mir_graph_->ConstantValue(rl_start.orig_sreg);
12204028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      start_value = std::max(start_value, 0);
12214028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      // Is the start > count?
12232700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      length_compare = OpCmpImmBranch(kCondLe, rs_rCX, start_value, nullptr);
12244028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12254028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      if (start_value != 0) {
12262700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        OpRegImm(kOpSub, rs_rCX, start_value);
12274028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      }
12284028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    } else {
12294028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      // Runtime start index.
123030adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      rl_start = UpdateLocTyped(rl_start, kCoreReg);
12314028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      if (rl_start.location == kLocPhysReg) {
1232a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        // Handle "start index < 0" case.
1233c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpRegReg(kOpXor, tmpReg, tmpReg);
1234c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpRegReg(kOpCmp, rl_start.reg, tmpReg);
1235c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpCondRegReg(kOpCmov, kCondLt, rl_start.reg, tmpReg);
1236a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov
1237a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        // The length of the string should be greater than the start index.
12382700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        length_compare = OpCmpBranch(kCondLe, rs_rCX, rl_start.reg, nullptr);
12392700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        OpRegReg(kOpSub, rs_rCX, rl_start.reg);
1240a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        if (rl_start.reg == rs_rDI) {
1241a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov          // The special case. We will use EDI further, so lets put start index to stack.
1242091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee          NewLIR1(kX86Push32R, rs_rDI.GetReg());
1243a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov          is_index_on_stack = true;
1244a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        }
12454028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      } else {
1246a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        // Load the start index from stack, remembering that we pushed EDI.
1247c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        int displacement = SRegOffset(rl_start.s_reg_low) + (cu_->target64 ? 2 : 1) * sizeof(uint32_t);
12488dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko        {
12498dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
1250c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk          Load32Disp(rs_rX86_SP, displacement, tmpReg);
12518dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko        }
1252a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        OpRegReg(kOpXor, rs_rDI, rs_rDI);
1253c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpRegReg(kOpCmp, tmpReg, rs_rDI);
1254c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpCondRegReg(kOpCmov, kCondLt, tmpReg, rs_rDI);
1255a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov
1256c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        length_compare = OpCmpBranch(kCondLe, rs_rCX, tmpReg, nullptr);
1257c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpRegReg(kOpSub, rs_rCX, tmpReg);
1258a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        // Put the start index to stack.
1259c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        NewLIR1(kX86Push32R, tmpReg.GetReg());
1260a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        is_index_on_stack = true;
12614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      }
12624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    }
12634028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
12644028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  DCHECK(length_compare != nullptr);
12654028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12664028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // ECX now contains the count in words to be searched.
12674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
1268c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  // Load the address of the string into R11 or EBX (depending on mode).
1269e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET.
1270695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  Load32Disp(rs_rDX, value_offset, rs_rDI);
1271c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  Load32Disp(rs_rDX, offset_offset, tmpReg);
1272c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  OpLea(tmpReg, rs_rDI, tmpReg, 1, data_offset);
12734028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12744028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Now compute into EDI where the search will start.
12754028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  if (zero_based || rl_start.is_const) {
12764028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    if (start_value == 0) {
1277c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk      OpRegCopy(rs_rDI, tmpReg);
12784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    } else {
1279c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk      NewLIR3(kX86Lea32RM, rs_rDI.GetReg(), tmpReg.GetReg(), 2 * start_value);
12804028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    }
12814028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  } else {
1282a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov    if (is_index_on_stack == true) {
1283a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov      // Load the start index from stack.
1284091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR1(kX86Pop32R, rs_rDX.GetReg());
1285c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk      OpLea(rs_rDI, tmpReg, rs_rDX, 1, 0);
1286a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov    } else {
1287c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk      OpLea(rs_rDI, tmpReg, rl_start.reg, 1, 0);
12884028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    }
12894028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
12904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12914028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // EDI now contains the start of the string to be searched.
12924028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // We are all prepared to do the search for the character.
12934028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  NewLIR0(kX86RepneScasw);
12944028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12954028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Did we find a match?
12964028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LIR* failed_branch = OpCondBranch(kCondNe, nullptr);
12974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12984028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // yes, we matched.  Compute the index of the result.
12994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // index = ((curr_ptr - orig_ptr) / 2) - 1.
1300c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  OpRegReg(kOpSub, rs_rDI, tmpReg);
13012700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  OpRegImm(kOpAsr, rs_rDI, 1);
1302091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rs_rDI.GetReg(), -1);
13034028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LIR *all_done = NewLIR1(kX86Jmp8, 0);
13044028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
13054028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Failed to match; return -1.
13064028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LIR *not_found = NewLIR0(kPseudoTargetLabel);
13074028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  length_compare->target = not_found;
13084028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  failed_branch->target = not_found;
13092700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LoadConstantNoClobber(rl_return.reg, -1);
13104028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
13114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // And join up at the end.
13124028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  all_done->target = NewLIR0(kPseudoTargetLabel);
13134028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Restore EDI from the stack.
1314091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR1(kX86Pop32R, rs_rDI.GetReg());
13154028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
13164028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Out of line code returns here.
13173a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang  if (slowpath_branch != nullptr) {
13184028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    LIR *return_point = NewLIR0(kPseudoTargetLabel);
13193a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang    AddIntrinsicSlowPath(info, slowpath_branch, return_point);
13204028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
13214028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
13224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  StoreValue(rl_dest, rl_return);
13234028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  return true;
13244028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell}
13254028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
1326ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell/*
1327ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @brief Enter an 'advance LOC' into the FDE buffer
1328ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param buf FDE buffer.
1329ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param increment Amount by which to increase the current location.
1330ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell */
1331ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstatic void AdvanceLoc(std::vector<uint8_t>&buf, uint32_t increment) {
1332ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  if (increment < 64) {
1333ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Encoding in opcode.
1334ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(0x1 << 6 | increment);
1335ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  } else if (increment < 256) {
1336ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Single byte delta.
1337ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(0x02);
1338ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(increment);
1339ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  } else if (increment < 256 * 256) {
1340ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Two byte delta.
1341ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(0x03);
1342ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(increment & 0xff);
1343ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back((increment >> 8) & 0xff);
1344ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  } else {
1345ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Four byte delta.
1346ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(0x04);
1347ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    PushWord(buf, increment);
1348ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
1349ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1350ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1351ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1352ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86CFIInitialization() {
1353ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  return X86Mir2Lir::ReturnCommonCallFrameInformation();
1354ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1355ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1356ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86Mir2Lir::ReturnCommonCallFrameInformation() {
1357ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>;
1358ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1359ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Length of the CIE (except for this field).
1360ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 16);
1361ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1362ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // CIE id.
1363ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 0xFFFFFFFFU);
1364ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1365ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Version: 3.
1366ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x03);
1367ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1368ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Augmentation: empty string.
1369ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x0);
1370ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1371ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Code alignment: 1.
1372ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x01);
1373ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1374ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Data alignment: -4.
1375ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x7C);
1376ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1377ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Return address register (R8).
1378ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x08);
1379ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1380ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Initial return PC is 4(ESP): DW_CFA_def_cfa R4 4.
1381ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x0C);
1382ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x04);
1383ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x04);
1384ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1385ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Return address location: 0(SP): DW_CFA_offset R8 1 (* -4);.
1386ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x2 << 6 | 0x08);
1387ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x01);
1388ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1389ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // And 2 Noops to align to 4 byte boundary.
1390ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x0);
1391ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x0);
1392ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1393ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  DCHECK_EQ(cfi_info->size() & 3, 0U);
1394ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  return cfi_info;
1395ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1396ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1397ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstatic void EncodeUnsignedLeb128(std::vector<uint8_t>& buf, uint32_t value) {
1398ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  uint8_t buffer[12];
1399ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  uint8_t *ptr = EncodeUnsignedLeb128(buffer, value);
1400ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  for (uint8_t *p = buffer; p < ptr; p++) {
1401ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(*p);
1402ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
1403ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1404ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1405ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() {
1406ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>;
1407ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1408ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Generate the FDE for the method.
1409ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  DCHECK_NE(data_offset_, 0U);
1410ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1411ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Length (will be filled in later in this routine).
1412ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 0);
1413ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1414ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // CIE_pointer (can be filled in by linker); might be left at 0 if there is only
1415ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // one CIE for the whole debug_frame section.
1416ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 0);
1417ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1418ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // 'initial_location' (filled in by linker).
1419ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 0);
1420ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1421ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // 'address_range' (number of bytes in the method).
1422ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, data_offset_);
1423ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
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;
1428ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    AdvanceLoc(*cfi_info, pc);
1429ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1430ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Now update the offset to the call frame: DW_CFA_def_cfa_offset frame_size.
1431ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    cfi_info->push_back(0x0e);
1432ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    EncodeUnsignedLeb128(*cfi_info, frame_size_);
1433ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1434ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // We continue with that stack until the epilogue.
1435ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    if (stack_increment_ != nullptr) {
1436ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      uint32_t new_pc = NEXT_LIR(stack_increment_)->offset;
1437ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      AdvanceLoc(*cfi_info, new_pc - pc);
1438ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1439ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // We probably have code snippets after the epilogue, so save the
1440ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // current state: DW_CFA_remember_state.
1441ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      cfi_info->push_back(0x0a);
1442ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1443ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // We have now popped the stack: DW_CFA_def_cfa_offset 4.  There is only the return
1444ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // PC on the stack now.
1445ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      cfi_info->push_back(0x0e);
1446ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      EncodeUnsignedLeb128(*cfi_info, 4);
1447ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1448ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // Everything after that is the same as before the epilogue.
1449ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // Stack bump was followed by RET instruction.
1450ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      LIR *post_ret_insn = NEXT_LIR(NEXT_LIR(stack_increment_));
1451ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      if (post_ret_insn != nullptr) {
1452ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        pc = new_pc;
1453ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        new_pc = post_ret_insn->offset;
1454ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        AdvanceLoc(*cfi_info, new_pc - pc);
1455ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        // Restore the state: DW_CFA_restore_state.
1456ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        cfi_info->push_back(0x0b);
1457ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      }
1458ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
1459ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
1460ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1461ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Padding to a multiple of 4
1462ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  while ((cfi_info->size() & 3) != 0) {
1463ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // DW_CFA_nop is encoded as 0.
1464ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    cfi_info->push_back(0);
1465ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
1466ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1467ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Set the length of the FDE inside the generated bytes.
1468ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  uint32_t length = cfi_info->size() - 4;
1469ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  (*cfi_info)[0] = length;
1470ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  (*cfi_info)[1] = length >> 8;
1471ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  (*cfi_info)[2] = length >> 16;
1472ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  (*cfi_info)[3] = length >> 24;
1473ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  return cfi_info;
1474ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1475ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1476d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
1477d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
1478d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    case kMirOpConstVector:
1479d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      GenConst128(bb, mir);
1480d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      break;
1481fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpMoveVector:
1482fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenMoveVector(bb, mir);
1483fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1484fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedMultiply:
1485fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenMultiplyVector(bb, mir);
1486fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1487fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedAddition:
1488fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenAddVector(bb, mir);
1489fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1490fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedSubtract:
1491fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenSubtractVector(bb, mir);
1492fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1493fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedShiftLeft:
1494fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenShiftLeftVector(bb, mir);
1495fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1496fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedSignedShiftRight:
1497fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenSignedShiftRightVector(bb, mir);
1498fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1499fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedUnsignedShiftRight:
1500fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenUnsignedShiftRightVector(bb, mir);
1501fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1502fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedAnd:
1503fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenAndVector(bb, mir);
1504fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1505fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedOr:
1506fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenOrVector(bb, mir);
1507fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1508fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedXor:
1509fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenXorVector(bb, mir);
1510fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1511fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedAddReduce:
1512fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenAddReduceVector(bb, mir);
1513fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1514fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedReduce:
1515fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenReduceVector(bb, mir);
1516fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1517fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedSet:
1518fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenSetVector(bb, mir);
1519fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1520d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    default:
1521d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      break;
1522d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
1523d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
1524d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
1525d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenConst128(BasicBlock* bb, MIR* mir) {
1526d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  int type_size = mir->dalvikInsn.vA;
1527d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // We support 128 bit vectors.
1528d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  DCHECK_EQ(type_size & 0xFFFF, 128);
1529fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vB);
1530d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  uint32_t *args = mir->dalvikInsn.arg;
1531fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int reg = rs_dest.GetReg();
1532d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Check for all 0 case.
1533d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  if (args[0] == 0 && args[1] == 0 && args[2] == 0 && args[3] == 0) {
1534d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    NewLIR2(kX86XorpsRR, reg, reg);
1535d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    return;
1536d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
1537d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Okay, load it from the constant vector area.
1538d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  LIR *data_target = ScanVectorLiteral(mir);
1539d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  if (data_target == nullptr) {
1540d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    data_target = AddVectorLiteral(mir);
1541d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
1542d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
1543d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Address the start of the method.
1544d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low);
1545e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  if (rl_method.wide) {
1546e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    rl_method = LoadValueWide(rl_method, kCoreReg);
1547e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  } else {
1548e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    rl_method = LoadValue(rl_method, kCoreReg);
1549e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  }
1550d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
1551d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Load the proper value from the literal area.
1552d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // We don't know the proper offset for the value, so pick one that will force
1553d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // 4 byte offset.  We will fix this up in the assembler later to have the right
1554d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // value.
15558dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
1556d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  LIR *load = NewLIR3(kX86Mova128RM, reg, rl_method.reg.GetReg(),  256 /* bogus */);
1557d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  load->flags.fixup = kFixupLoad;
1558d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  load->target = data_target;
1559d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
1560d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
1561fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenMoveVector(BasicBlock *bb, MIR *mir) {
1562fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // We only support 128 bit registers.
1563fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1564fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vB);
1565fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_src = RegStorage::Solo128(mir->dalvikInsn.vC);
1566fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(kX86Mova128RR, rs_dest.GetReg(), rs_src.GetReg());
1567fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1568fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1569fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenMultiplyVector(BasicBlock *bb, MIR *mir) {
1570fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1571fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16);
1572fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1573fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC);
1574fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1575fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1576fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1577fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PmulldRR;
1578fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1579fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1580fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PmullwRR;
1581fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1582fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSingle:
1583fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86MulpsRR;
1584fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1585fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kDouble:
1586fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86MulpdRR;
1587fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1588fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1589fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector multiply " << opsize;
1590fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1591fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1592fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg());
1593fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1594fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1595fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenAddVector(BasicBlock *bb, MIR *mir) {
1596fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1597fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16);
1598fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1599fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC);
1600fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1601fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1602fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1603fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PadddRR;
1604fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1605fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1606fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1607fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PaddwRR;
1608fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1609fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedByte:
1610fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedByte:
1611fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PaddbRR;
1612fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1613fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSingle:
1614fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86AddpsRR;
1615fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1616fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kDouble:
1617fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86AddpdRR;
1618fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1619fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1620fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector addition " << opsize;
1621fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1622fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1623fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg());
1624fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1625fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1626fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenSubtractVector(BasicBlock *bb, MIR *mir) {
1627fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1628fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16);
1629fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1630fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC);
1631fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1632fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1633fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1634fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsubdRR;
1635fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1636fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1637fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1638fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsubwRR;
1639fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1640fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedByte:
1641fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedByte:
1642fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsubbRR;
1643fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1644fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSingle:
1645fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86SubpsRR;
1646fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1647fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kDouble:
1648fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86SubpdRR;
1649fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1650fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1651fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector subtraction " << opsize;
1652fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1653fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1654fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg());
1655fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1656fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1657fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenShiftLeftVector(BasicBlock *bb, MIR *mir) {
1658fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1659fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16);
1660fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1661fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int imm = mir->dalvikInsn.vC;
1662fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1663fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1664fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1665fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PslldRI;
1666fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1667fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k64:
1668fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsllqRI;
1669fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1670fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1671fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1672fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsllwRI;
1673fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1674fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1675fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector shift left " << opsize;
1676fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1677fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1678fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), imm);
1679fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1680fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1681fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenSignedShiftRightVector(BasicBlock *bb, MIR *mir) {
1682fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1683fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16);
1684fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1685fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int imm = mir->dalvikInsn.vC;
1686fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1687fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1688fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1689fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsradRI;
1690fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1691fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1692fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1693fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsrawRI;
1694fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1695fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1696fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector signed shift right " << opsize;
1697fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1698fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1699fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), imm);
1700fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1701fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1702fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenUnsignedShiftRightVector(BasicBlock *bb, MIR *mir) {
1703fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1704fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16);
1705fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1706fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int imm = mir->dalvikInsn.vC;
1707fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1708fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1709fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1710fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsrldRI;
1711fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1712fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k64:
1713fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsrlqRI;
1714fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1715fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1716fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1717fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsrlwRI;
1718fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1719fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1720fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector unsigned shift right " << opsize;
1721fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1722fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1723fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), imm);
1724fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1725fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1726fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenAndVector(BasicBlock *bb, MIR *mir) {
1727fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // We only support 128 bit registers.
1728fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1729fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1730fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC);
1731fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(kX86PandRR, rs_dest_src1.GetReg(), rs_src2.GetReg());
1732fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1733fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1734fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenOrVector(BasicBlock *bb, MIR *mir) {
1735fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // We only support 128 bit registers.
1736fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1737fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1738fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC);
1739fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_src2.GetReg());
1740fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1741fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1742fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenXorVector(BasicBlock *bb, MIR *mir) {
1743fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // We only support 128 bit registers.
1744fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1745fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1746fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vC);
1747fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(kX86PxorRR, rs_dest_src1.GetReg(), rs_src2.GetReg());
1748fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1749fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1750fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenAddReduceVector(BasicBlock *bb, MIR *mir) {
1751fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1752fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16);
1753fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
1754fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int imm = mir->dalvikInsn.vC;
1755fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1756fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1757fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1758fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PhadddRR;
1759fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1760fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1761fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1762fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PhaddwRR;
1763fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1764fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1765fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector add reduce " << opsize;
1766fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1767fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1768fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), imm);
1769fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1770fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1771fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenReduceVector(BasicBlock *bb, MIR *mir) {
1772fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1773fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16);
1774fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_src = RegStorage::Solo128(mir->dalvikInsn.vB);
1775fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int index = mir->dalvikInsn.arg[0];
1776fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1777fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1778fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1779fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PextrdRRI;
1780fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1781fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1782fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1783fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PextrwRRI;
1784fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1785fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedByte:
1786fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedByte:
1787fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PextrbRRI;
1788fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1789fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1790fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector reduce " << opsize;
1791fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1792fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1793fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // We need to extract to a GPR.
1794fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage temp = AllocTemp();
1795fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR3(opcode, temp.GetReg(), rs_src.GetReg(), index);
1796fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1797fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Assume that the destination VR is in the def for the mir.
1798fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegLocation rl_dest = mir_graph_->GetDest(mir);
1799fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegLocation rl_temp =
1800fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, temp, INVALID_SREG, INVALID_SREG};
1801fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  StoreValue(rl_dest, rl_temp);
1802fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1803fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1804fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenSetVector(BasicBlock *bb, MIR *mir) {
1805fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  DCHECK_EQ(mir->dalvikInsn.vA & 0xFFFF, 128U);
1806fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vA >> 16);
1807fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vB);
1808fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int op_low = 0, op_high = 0;
1809fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1810fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1811fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      op_low = kX86PshufdRRI;
1812fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1813fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1814fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1815fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      // Handles low quadword.
1816fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      op_low = kX86PshuflwRRI;
1817fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      // Handles upper quadword.
1818fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      op_high = kX86PshufdRRI;
1819fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1820fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1821fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector set " << opsize;
1822fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1823fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1824fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1825fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Load the value from the VR into a GPR.
1826fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
1827fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  rl_src = LoadValue(rl_src, kCoreReg);
1828fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1829fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Load the value into the XMM register.
1830fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(kX86MovdxrRR, rs_dest.GetReg(), rl_src.reg.GetReg());
1831fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1832fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Now shuffle the value across the destination.
1833fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR3(op_low, rs_dest.GetReg(), rs_dest.GetReg(), 0);
1834fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1835fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // And then repeat as needed.
1836fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  if (op_high != 0) {
1837fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    NewLIR3(op_high, rs_dest.GetReg(), rs_dest.GetReg(), 0);
1838fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1839fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1840fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1841fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1842d65c51a556e6649db4e18bd083c8fec37607a442Mark MendellLIR *X86Mir2Lir::ScanVectorLiteral(MIR *mir) {
1843d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg);
1844d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  for (LIR *p = const_vectors_; p != nullptr; p = p->next) {
1845d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    if (args[0] == p->operands[0] && args[1] == p->operands[1] &&
1846d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell        args[2] == p->operands[2] && args[3] == p->operands[3]) {
1847d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      return p;
1848d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    }
1849d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
1850d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  return nullptr;
1851d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
1852d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
1853d65c51a556e6649db4e18bd083c8fec37607a442Mark MendellLIR *X86Mir2Lir::AddVectorLiteral(MIR *mir) {
1854d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  LIR* new_value = static_cast<LIR*>(arena_->Alloc(sizeof(LIR), kArenaAllocData));
1855d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg);
1856d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->operands[0] = args[0];
1857d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->operands[1] = args[1];
1858d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->operands[2] = args[2];
1859d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->operands[3] = args[3];
1860d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->next = const_vectors_;
1861d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  if (const_vectors_ == nullptr) {
1862d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    estimated_native_code_size_ += 12;  // Amount needed to align to 16 byte boundary.
1863d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
1864d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  estimated_native_code_size_ += 16;  // Space for one vector.
1865d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  const_vectors_ = new_value;
1866d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  return new_value;
1867d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
1868d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
186958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// ------------ ABI support: mapping of args to physical registers -------------
1870407a9d2847161b843966a443b71760b1280bd396Serguei KatkovRegStorage X86Mir2Lir::InToRegStorageX86_64Mapper::GetNextReg(bool is_double_or_float, bool is_wide, bool is_ref) {
1871a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  const SpecialTargetRegister coreArgMappingToPhysicalReg[] = {kArg1, kArg2, kArg3, kArg4, kArg5};
1872a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  const int coreArgMappingToPhysicalRegSize = sizeof(coreArgMappingToPhysicalReg) / sizeof(SpecialTargetRegister);
1873a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  const SpecialTargetRegister fpArgMappingToPhysicalReg[] = {kFArg0, kFArg1, kFArg2, kFArg3,
1874a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu                                                  kFArg4, kFArg5, kFArg6, kFArg7};
1875a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  const int fpArgMappingToPhysicalRegSize = sizeof(fpArgMappingToPhysicalReg) / sizeof(SpecialTargetRegister);
187658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
187758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (is_double_or_float) {
187858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) {
1879a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu      return ml_->TargetReg(fpArgMappingToPhysicalReg[cur_fp_reg_++], is_wide);
188058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
188158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  } else {
188258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
1883407a9d2847161b843966a443b71760b1280bd396Serguei Katkov      return is_ref ? ml_->TargetRefReg(coreArgMappingToPhysicalReg[cur_core_reg_++]) :
1884407a9d2847161b843966a443b71760b1280bd396Serguei Katkov                      ml_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++], is_wide);
188558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
188658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
1887a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  return RegStorage::InvalidReg();
188858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
188958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
189058994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::InToRegStorageMapping::Get(int in_position) {
189158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  DCHECK(IsInitialized());
189258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  auto res = mapping_.find(in_position);
189358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  return res != mapping_.end() ? res->second : RegStorage::InvalidReg();
189458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
189558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
189658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkovoid X86Mir2Lir::InToRegStorageMapping::Initialize(RegLocation* arg_locs, int count, InToRegStorageMapper* mapper) {
189758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  DCHECK(mapper != nullptr);
189858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  max_mapped_in_ = -1;
189958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  is_there_stack_mapped_ = false;
190058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  for (int in_position = 0; in_position < count; in_position++) {
1901407a9d2847161b843966a443b71760b1280bd396Serguei Katkov     RegStorage reg = mapper->GetNextReg(arg_locs[in_position].fp,
1902407a9d2847161b843966a443b71760b1280bd396Serguei Katkov             arg_locs[in_position].wide, arg_locs[in_position].ref);
190358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko     if (reg.Valid()) {
190458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       mapping_[in_position] = reg;
190558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       max_mapped_in_ = std::max(max_mapped_in_, in_position);
1906407a9d2847161b843966a443b71760b1280bd396Serguei Katkov       if (arg_locs[in_position].wide) {
190758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         // We covered 2 args, so skip the next one
190858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         in_position++;
190958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       }
191058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko     } else {
191158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       is_there_stack_mapped_ = true;
191258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko     }
191358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
191458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  initialized_ = true;
191558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
191658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
191758994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
1918dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (!cu_->target64) {
191958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return GetCoreArgMappingToPhysicalReg(arg_num);
192058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
192158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
192258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (!in_to_reg_storage_mapping_.IsInitialized()) {
192358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int start_vreg = cu_->num_dalvik_registers - cu_->num_ins;
192458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    RegLocation* arg_locs = &mir_graph_->reg_location_[start_vreg];
192558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
1926a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    InToRegStorageX86_64Mapper mapper(this);
192758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    in_to_reg_storage_mapping_.Initialize(arg_locs, cu_->num_ins, &mapper);
192858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
192958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  return in_to_reg_storage_mapping_.Get(arg_num);
193058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
193158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
193258994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::GetCoreArgMappingToPhysicalReg(int core_arg_num) {
193358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
193458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Not used for 64-bit, TODO: Move X86_32 to the same framework
193558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  switch (core_arg_num) {
193658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case 0:
193758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      return rs_rX86_ARG1;
193858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case 1:
193958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      return rs_rX86_ARG2;
194058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case 2:
194158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      return rs_rX86_ARG3;
194258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    default:
194358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      return RegStorage::InvalidReg();
194458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
194558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
194658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
194758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// ---------End of ABI support: mapping of args to physical registers -------------
194858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
194958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/*
195058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If there are any ins passed in registers that have not been promoted
195158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * to a callee-save register, flush them to the frame.  Perform initial
195258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * assignment of promoted arguments.
195358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *
195458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * ArgLocs is an array of location records describing the incoming arguments
195558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * with one location record per word of argument.
195658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */
195758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkovoid X86Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) {
1958dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (!cu_->target64) return Mir2Lir::FlushIns(ArgLocs, rl_method);
195958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  /*
196058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * Dummy up a RegLocation for the incoming Method*
196158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * It will attempt to keep kArg0 live (or copy it to home location
196258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * if promoted).
196358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   */
196458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
196558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  RegLocation rl_src = rl_method;
196658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  rl_src.location = kLocPhysReg;
1967a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  rl_src.reg = TargetRefReg(kArg0);
196858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  rl_src.home = false;
196958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  MarkLive(rl_src);
197058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  StoreValue(rl_method, rl_src);
197158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // If Method* has been promoted, explicitly flush
197258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (rl_method.location == kLocPhysReg) {
1973a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    StoreRefDisp(rs_rX86_SP, 0, As32BitReg(TargetRefReg(kArg0)), kNotVolatile);
197458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
197558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
197658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (cu_->num_ins == 0) {
197758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return;
197858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
197958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
198058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  int start_vreg = cu_->num_dalvik_registers - cu_->num_ins;
198158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  /*
198258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * Copy incoming arguments to their proper home locations.
198358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * NOTE: an older version of dx had an issue in which
198458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * it would reuse static method argument registers.
198558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * This could result in the same Dalvik virtual register
198658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * being promoted to both core and fp regs. To account for this,
198758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * we only copy to the corresponding promoted physical register
198858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * if it matches the type of the SSA name for the incoming
198958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * argument.  It is also possible that long and double arguments
199058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * end up half-promoted.  In those cases, we must flush the promoted
199158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * half to memory as well.
199258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   */
19938dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
199458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  for (int i = 0; i < cu_->num_ins; i++) {
199558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // get reg corresponding to input
19964d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko    RegStorage reg = GetArgMappingToPhysicalReg(i);
199758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
19984d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko    RegLocation* t_loc = &ArgLocs[i];
199958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    if (reg.Valid()) {
20004d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // If arriving in register.
200158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
20024d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // We have already updated the arg location with promoted info
20034d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // so we can be based on it.
20044d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      if (t_loc->location == kLocPhysReg) {
20054d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        // Just copy it.
20064d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        OpRegCopy(t_loc->reg, reg);
20074d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      } else {
20084d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        // Needs flush.
20094d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        if (t_loc->ref) {
2010a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          StoreRefDisp(rs_rX86_SP, SRegOffset(start_vreg + i), reg, kNotVolatile);
201158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else {
2012a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          StoreBaseDisp(rs_rX86_SP, SRegOffset(start_vreg + i), reg, t_loc->wide ? k64 : k32,
20134d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko                        kNotVolatile);
201458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
201558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
201658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    } else {
20174d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // If arriving in frame & promoted.
20184d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      if (t_loc->location == kLocPhysReg) {
20194d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        if (t_loc->ref) {
2020a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          LoadRefDisp(rs_rX86_SP, SRegOffset(start_vreg + i), t_loc->reg, kNotVolatile);
20214d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        } else {
2022a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          LoadBaseDisp(rs_rX86_SP, SRegOffset(start_vreg + i), t_loc->reg,
20234d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko                       t_loc->wide ? k64 : k32, kNotVolatile);
20244d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        }
202558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
202658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
20274d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko    if (t_loc->wide) {
20284d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // Increment i to skip the next one.
20294d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      i++;
20304d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko    }
203158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
203258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
203358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
203458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/*
203558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Load up to 5 arguments, the first three of which will be in
203658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * kArg1 .. kArg3.  On entry kArg0 contains the current method pointer,
203758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * and as part of the load sequence, it must be replaced with
203858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * the target method pointer.  Note, this may also be called
203958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * for "range" variants if the number of arguments is 5 or fewer.
204058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */
204158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsNoRange(CallInfo* info,
204258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  int call_state, LIR** pcrLabel, NextCallInsn next_call_insn,
204358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  const MethodReference& target_method,
204458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  uint32_t vtable_idx, uintptr_t direct_code,
204558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  uintptr_t direct_method, InvokeType type, bool skip_this) {
2046dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (!cu_->target64) {
204758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return Mir2Lir::GenDalvikArgsNoRange(info,
204858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  call_state, pcrLabel, next_call_insn,
204958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  target_method,
205058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  vtable_idx, direct_code,
205158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  direct_method, type, skip_this);
205258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
205358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  return GenDalvikArgsRange(info,
205458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                       call_state, pcrLabel, next_call_insn,
205558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                       target_method,
205658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                       vtable_idx, direct_code,
205758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                       direct_method, type, skip_this);
205858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
205958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
206058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/*
206158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * May have 0+ arguments (also used for jumbo).  Note that
206258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * source virtual registers may be in physical registers, so may
206358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * need to be flushed to home location before copying.  This
206458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * applies to arg3 and above (see below).
206558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *
206658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Two general strategies:
206758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *    If < 20 arguments
206858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *       Pass args 3-18 using vldm/vstm block copy
206958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *       Pass arg0, arg1 & arg2 in kArg1-kArg3
207058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *    If 20+ arguments
207158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *       Pass args arg19+ using memcpy block copy
207258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *       Pass arg0, arg1 & arg2 in kArg1-kArg3
207358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *
207458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */
207558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state,
207658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                LIR** pcrLabel, NextCallInsn next_call_insn,
207758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                const MethodReference& target_method,
207858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                uint32_t vtable_idx, uintptr_t direct_code, uintptr_t direct_method,
207958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                InvokeType type, bool skip_this) {
2080dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (!cu_->target64) {
208158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return Mir2Lir::GenDalvikArgsRange(info, call_state,
208258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                pcrLabel, next_call_insn,
208358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                target_method,
208458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                vtable_idx, direct_code, direct_method,
208558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                type, skip_this);
208658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
208758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
208858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  /* If no arguments, just return */
208958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (info->num_arg_words == 0)
209058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return call_state;
209158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
209258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  const int start_index = skip_this ? 1 : 0;
209358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
2094a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  InToRegStorageX86_64Mapper mapper(this);
209558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  InToRegStorageMapping in_to_reg_storage_mapping;
209658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  in_to_reg_storage_mapping.Initialize(info->args, info->num_arg_words, &mapper);
209758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  const int last_mapped_in = in_to_reg_storage_mapping.GetMaxMappedIn();
209858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  const int size_of_the_last_mapped = last_mapped_in == -1 ? 1 :
209958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          in_to_reg_storage_mapping.Get(last_mapped_in).Is64BitSolo() ? 2 : 1;
210058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  int regs_left_to_pass_via_stack = info->num_arg_words - (last_mapped_in + size_of_the_last_mapped);
210158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
210258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Fisrt of all, check whether it make sense to use bulk copying
210358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Optimization is aplicable only for range case
210458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // TODO: make a constant instead of 2
210558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (info->is_range && regs_left_to_pass_via_stack >= 2) {
210658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // Scan the rest of the args - if in phys_reg flush to memory
210758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    for (int next_arg = last_mapped_in + size_of_the_last_mapped; next_arg < info->num_arg_words;) {
210858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      RegLocation loc = info->args[next_arg];
210958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      if (loc.wide) {
211058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        loc = UpdateLocWide(loc);
211158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (loc.location == kLocPhysReg) {
21128dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
2113a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          StoreBaseDisp(rs_rX86_SP, SRegOffset(loc.s_reg_low), loc.reg, k64, kNotVolatile);
211458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
211558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        next_arg += 2;
211658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      } else {
211758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        loc = UpdateLoc(loc);
211858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (loc.location == kLocPhysReg) {
21198dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
2120a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          StoreBaseDisp(rs_rX86_SP, SRegOffset(loc.s_reg_low), loc.reg, k32, kNotVolatile);
212158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
212258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        next_arg++;
212358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
212458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
212558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
212658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // Logic below assumes that Method pointer is at offset zero from SP.
212758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    DCHECK_EQ(VRegOffset(static_cast<int>(kVRegMethodPtrBaseReg)), 0);
212858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
212958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // The rest can be copied together
213058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int start_offset = SRegOffset(info->args[last_mapped_in + size_of_the_last_mapped].s_reg_low);
213158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int outs_offset = StackVisitor::GetOutVROffset(last_mapped_in + size_of_the_last_mapped, cu_->instruction_set);
213258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
213358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int current_src_offset = start_offset;
213458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int current_dest_offset = outs_offset;
213558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
21368dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    // Only davik regs are accessed in this loop; no next_call_insn() calls.
21378dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
213858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    while (regs_left_to_pass_via_stack > 0) {
213958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      // This is based on the knowledge that the stack itself is 16-byte aligned.
214058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      bool src_is_16b_aligned = (current_src_offset & 0xF) == 0;
214158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      bool dest_is_16b_aligned = (current_dest_offset & 0xF) == 0;
214258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      size_t bytes_to_move;
214358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
214458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      /*
214558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       * The amount to move defaults to 32-bit. If there are 4 registers left to move, then do a
214658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       * a 128-bit move because we won't get the chance to try to aligned. If there are more than
214758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       * 4 registers left to move, consider doing a 128-bit only if either src or dest are aligned.
214858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       * We do this because we could potentially do a smaller move to align.
214958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       */
215058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      if (regs_left_to_pass_via_stack == 4 ||
215158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          (regs_left_to_pass_via_stack > 4 && (src_is_16b_aligned || dest_is_16b_aligned))) {
215258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Moving 128-bits via xmm register.
215358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        bytes_to_move = sizeof(uint32_t) * 4;
215458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
215558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Allocate a free xmm temp. Since we are working through the calling sequence,
215658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // we expect to have an xmm temporary available.  AllocTempDouble will abort if
215758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // there are no free registers.
215858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        RegStorage temp = AllocTempDouble();
215958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
216058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LIR* ld1 = nullptr;
216158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LIR* ld2 = nullptr;
216258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LIR* st1 = nullptr;
216358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LIR* st2 = nullptr;
216458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
216558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        /*
216658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * The logic is similar for both loads and stores. If we have 16-byte alignment,
216758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * do an aligned move. If we have 8-byte alignment, then do the move in two
216858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * parts. This approach prevents possible cache line splits. Finally, fall back
216958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * to doing an unaligned move. In most cases we likely won't split the cache
217058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * line but we cannot prove it and thus take a conservative approach.
217158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         */
217258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        bool src_is_8b_aligned = (current_src_offset & 0x7) == 0;
217358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        bool dest_is_8b_aligned = (current_dest_offset & 0x7) == 0;
217458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
21758dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko        ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
217658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (src_is_16b_aligned) {
2177a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovA128FP);
217858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else if (src_is_8b_aligned) {
2179a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovLo128FP);
2180a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          ld2 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset + (bytes_to_move >> 1),
218158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                            kMovHi128FP);
218258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else {
2183a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovU128FP);
218458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
218558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
218658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (dest_is_16b_aligned) {
2187a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovA128FP);
218858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else if (dest_is_8b_aligned) {
2189a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovLo128FP);
2190a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          st2 = OpMovMemReg(rs_rX86_SP, current_dest_offset + (bytes_to_move >> 1),
219158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                            temp, kMovHi128FP);
219258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else {
2193a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovU128FP);
219458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
219558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
219658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // TODO If we could keep track of aliasing information for memory accesses that are wider
219758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // than 64-bit, we wouldn't need to set up a barrier.
219858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (ld1 != nullptr) {
219958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          if (ld2 != nullptr) {
220058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            // For 64-bit load we can actually set up the aliasing information.
220158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            AnnotateDalvikRegAccess(ld1, current_src_offset >> 2, true, true);
220258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            AnnotateDalvikRegAccess(ld2, (current_src_offset + (bytes_to_move >> 1)) >> 2, true, true);
220358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          } else {
220458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            // Set barrier for 128-bit load.
22058dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            ld1->u.m.def_mask = &kEncodeAll;
220658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          }
220758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
220858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (st1 != nullptr) {
220958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          if (st2 != nullptr) {
221058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            // For 64-bit store we can actually set up the aliasing information.
221158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            AnnotateDalvikRegAccess(st1, current_dest_offset >> 2, false, true);
221258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            AnnotateDalvikRegAccess(st2, (current_dest_offset + (bytes_to_move >> 1)) >> 2, false, true);
221358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          } else {
221458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            // Set barrier for 128-bit store.
22158dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            st1->u.m.def_mask = &kEncodeAll;
221658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          }
221758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
221858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
221958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Free the temporary used for the data movement.
222058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        FreeTemp(temp);
222158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      } else {
222258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Moving 32-bits via general purpose register.
222358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        bytes_to_move = sizeof(uint32_t);
222458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
222558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Instead of allocating a new temp, simply reuse one of the registers being used
222658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // for argument passing.
2227a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu        RegStorage temp = TargetReg(kArg3, false);
222858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
222958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Now load the argument VR and store to the outs.
2230a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu        Load32Disp(rs_rX86_SP, current_src_offset, temp);
2231a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu        Store32Disp(rs_rX86_SP, current_dest_offset, temp);
223258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
223358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
223458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      current_src_offset += bytes_to_move;
223558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      current_dest_offset += bytes_to_move;
223658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      regs_left_to_pass_via_stack -= (bytes_to_move >> 2);
223758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
223858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    DCHECK_EQ(regs_left_to_pass_via_stack, 0);
223958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
224058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
224158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Now handle rest not registers if they are
224258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (in_to_reg_storage_mapping.IsThereStackMapped()) {
2243a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    RegStorage regSingle = TargetReg(kArg2, false);
2244a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    RegStorage regWide = TargetReg(kArg3, true);
2245b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu    for (int i = start_index;
2246b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu         i < last_mapped_in + size_of_the_last_mapped + regs_left_to_pass_via_stack; i++) {
224758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      RegLocation rl_arg = info->args[i];
224858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      rl_arg = UpdateRawLoc(rl_arg);
224958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      RegStorage reg = in_to_reg_storage_mapping.Get(i);
225058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      if (!reg.Valid()) {
225158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        int out_offset = StackVisitor::GetOutVROffset(i, cu_->instruction_set);
225258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
22538dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko        {
22548dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
22558dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          if (rl_arg.wide) {
22568dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            if (rl_arg.location == kLocPhysReg) {
2257a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu              StoreBaseDisp(rs_rX86_SP, out_offset, rl_arg.reg, k64, kNotVolatile);
22588dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            } else {
22598dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko              LoadValueDirectWideFixed(rl_arg, regWide);
2260a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu              StoreBaseDisp(rs_rX86_SP, out_offset, regWide, k64, kNotVolatile);
22618dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            }
226258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          } else {
22638dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            if (rl_arg.location == kLocPhysReg) {
2264a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu              StoreBaseDisp(rs_rX86_SP, out_offset, rl_arg.reg, k32, kNotVolatile);
22658dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            } else {
22668dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko              LoadValueDirectFixed(rl_arg, regSingle);
2267a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu              StoreBaseDisp(rs_rX86_SP, out_offset, regSingle, k32, kNotVolatile);
22688dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            }
226958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          }
227058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
227158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        call_state = next_call_insn(cu_, info, call_state, target_method,
227258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                    vtable_idx, direct_code, direct_method, type);
227358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
2274b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu      if (rl_arg.wide) {
2275b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu        i++;
2276b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu      }
227758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
227858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
227958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
228058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Finish with mapped registers
228158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  for (int i = start_index; i <= last_mapped_in; i++) {
228258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    RegLocation rl_arg = info->args[i];
228358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rl_arg = UpdateRawLoc(rl_arg);
228458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    RegStorage reg = in_to_reg_storage_mapping.Get(i);
228558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    if (reg.Valid()) {
228658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      if (rl_arg.wide) {
228758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LoadValueDirectWideFixed(rl_arg, reg);
228858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      } else {
228958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LoadValueDirectFixed(rl_arg, reg);
229058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
229158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
229258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                               direct_code, direct_method, type);
229358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
2294b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu    if (rl_arg.wide) {
2295b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu      i++;
2296b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu    }
229758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
229858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
229958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
230058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                           direct_code, direct_method, type);
230158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (pcrLabel) {
23025655e84e8d71697d8ef3ea901a0b853af42c559eAndreas Gampe    if (cu_->compiler_driver->GetCompilerOptions().GetExplicitNullChecks()) {
2303a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu      *pcrLabel = GenExplicitNullCheck(TargetRefReg(kArg1), info->opt_flags);
230458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    } else {
230558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      *pcrLabel = nullptr;
230658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      // In lieu of generating a check for kArg1 being null, we need to
230758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      // perform a load when doing implicit checks.
230858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      RegStorage tmp = AllocTemp();
2309a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu      Load32Disp(TargetRefReg(kArg1), 0, tmp);
231058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      MarkPossibleNullPointerException(info->opt_flags);
231158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      FreeTemp(tmp);
231258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
231358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
231458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  return call_state;
231558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
231658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
23177934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
2318