target_x86.cc revision 60bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43
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
43060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan BanerjiRegStorage X86Mir2Lir::Get128BitRegister(RegStorage reg) {
43160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  return GetRegInfo(reg)->FindMatchingView(RegisterInfo::k128SoloStorageMask)->GetReg();
43260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
43360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
4347e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fubool X86Mir2Lir::IsByteRegister(RegStorage reg) {
435dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  return cu_->target64 || reg.GetRegNum() < rs_rX86_SP.GetRegNum();
436e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell}
437e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell
438efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* Clobber all regs that might be used by an external C call */
43931c2aac7137b69d5622eea09597500731fbee2efVladimir Markovoid X86Mir2Lir::ClobberCallerSave() {
440091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rAX);
441091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rCX);
442091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rDX);
443091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rBX);
44435ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu
44535ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr0);
44635ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr1);
44735ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr2);
44835ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr3);
44935ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr4);
45035ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr5);
45135ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr6);
45235ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  Clobber(rs_fr7);
45335ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu
454dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
45535ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_r8);
45635ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_r9);
45735ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_r10);
45835ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_r11);
45935ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu
46035ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr8);
46135ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr9);
46235ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr10);
46335ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr11);
46435ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr12);
46535ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr13);
46635ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr14);
46735ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu    Clobber(rs_fr15);
46835ec2b5faf9a2dbc3c0cddb7ebc09952b8a27d2aChao-ying Fu  }
469efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
470efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4711fd3346740dfb7f47be9922312b68a4227fada96buzbeeRegLocation X86Mir2Lir::GetReturnWideAlt() {
47252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  RegLocation res = LocCReturnWide();
473091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(res.reg.GetLowReg() == rs_rAX.GetReg());
474091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(res.reg.GetHighReg() == rs_rDX.GetReg());
475091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rAX);
476091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rDX);
477091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  MarkInUse(rs_rAX);
478091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  MarkInUse(rs_rDX);
479091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  MarkWide(res.reg);
480efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
481efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
482efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
4832ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromRegLocation X86Mir2Lir::GetReturnAlt() {
48452a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  RegLocation res = LocCReturn();
485091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  res.reg.SetReg(rs_rDX.GetReg());
486091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  Clobber(rs_rDX);
487091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  MarkInUse(rs_rDX);
488efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  return res;
489efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
490efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
491efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */
4922ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::LockCallTemps() {
493091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rX86_ARG0);
494091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rX86_ARG1);
495091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rX86_ARG2);
496091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LockTemp(rs_rX86_ARG3);
497dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
49858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_ARG4);
49958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_ARG5);
50058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG0);
50158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG1);
50258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG2);
50358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG3);
50458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG4);
50558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG5);
50658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG6);
50758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    LockTemp(rs_rX86_FARG7);
50858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
509efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
510efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
511efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* To be used when explicitly managing register use */
5122ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromvoid X86Mir2Lir::FreeCallTemps() {
513091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rX86_ARG0);
514091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rX86_ARG1);
515091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rX86_ARG2);
516091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  FreeTemp(rs_rX86_ARG3);
517dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
51858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_ARG4);
51958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_ARG5);
52058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG0);
52158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG1);
52258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG2);
52358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG3);
52458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG4);
52558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG5);
52658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG6);
52758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    FreeTemp(rs_rX86_FARG7);
52858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
529efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
530efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
53199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusorubool X86Mir2Lir::ProvidesFullMemoryBarrier(X86OpCode opcode) {
53299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    switch (opcode) {
53399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      case kX86LockCmpxchgMR:
53499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      case kX86LockCmpxchgAR:
5350f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers      case kX86LockCmpxchg64M:
5360f9b9c508814a62c6e21c6a06cfe4de39b5036c0Ian Rogers      case kX86LockCmpxchg64A:
53799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      case kX86XchgMR:
53899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      case kX86Mfence:
53999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru        // Atomic memory instructions provide full barrier.
54099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru        return true;
54199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      default:
54299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru        break;
54399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    }
54499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
54599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    // Conservative if cannot prove it provides full barrier.
54699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    return false;
54799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru}
54899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
549b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampebool X86Mir2Lir::GenMemBarrier(MemBarrierKind barrier_kind) {
550efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0
55199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  // Start off with using the last LIR as the barrier. If it is not enough, then we will update it.
55299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  LIR* mem_barrier = last_lir_insn_;
55399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
554b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe  bool ret = false;
55599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  /*
55699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru   * According to the JSR-133 Cookbook, for x86 only StoreLoad barriers need memory fence. All other barriers
55799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru   * (LoadLoad, LoadStore, StoreStore) are nops due to the x86 memory model. For those cases, all we need
55899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru   * to ensure is that there is a scheduling barrier in place.
55999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru   */
56099ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  if (barrier_kind == kStoreLoad) {
56199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    // If no LIR exists already that can be used a barrier, then generate an mfence.
56299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    if (mem_barrier == nullptr) {
56399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      mem_barrier = NewLIR0(kX86Mfence);
564b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe      ret = true;
56599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    }
56699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
56799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    // If last instruction does not provide full barrier, then insert an mfence.
56899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    if (ProvidesFullMemoryBarrier(static_cast<X86OpCode>(mem_barrier->opcode)) == false) {
56999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru      mem_barrier = NewLIR0(kX86Mfence);
570b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe      ret = true;
57199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    }
57299ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  }
57399ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru
57499ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  // Now ensure that a scheduling barrier is in place.
57599ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  if (mem_barrier == nullptr) {
57699ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    GenBarrier();
57799ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  } else {
57899ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    // Mark as a scheduling barrier.
57999ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru    DCHECK(!mem_barrier->flags.use_def_invalid);
5808dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    mem_barrier->u.m.def_mask = &kEncodeAll;
58199ad7230ccaace93bf323dea9790f35fe991a4a2Razvan A Lupusoru  }
582b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe  return ret;
583b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe#else
584b14329f90f725af0f67c45dfcb94933a426d63ceAndreas Gampe  return false;
585efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif
586efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
58700e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee
5881fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::CompilerInitializeRegAlloc() {
589dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
59076af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_64, core_regs_64q, sp_regs_64,
59176af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko                                          dp_regs_64, reserved_regs_64, reserved_regs_64q,
59276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko                                          core_temps_64, core_temps_64q, sp_temps_64, dp_temps_64);
5939ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  } else {
594b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee    reg_pool_ = new (arena_) RegisterPool(this, arena_, core_regs_32, empty_pool, sp_regs_32,
595b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee                                          dp_regs_32, reserved_regs_32, empty_pool,
596b01bf15d18f9b08d77e7a3c6e2897af0e02bf8cabuzbee                                          core_temps_32, empty_pool, sp_temps_32, dp_temps_32);
5979ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  }
598091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
599091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Target-specific adjustments.
600091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
601fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Add in XMM registers.
602dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  const ArrayRef<const RegStorage> *xp_temps = cu_->target64 ? &xp_temps_64 : &xp_temps_32;
603fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  for (RegStorage reg : *xp_temps) {
604fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    RegisterInfo* info = new (arena_) RegisterInfo(reg, GetRegMaskCommon(reg));
605fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    reginfo_map_.Put(reg.GetReg(), info);
606fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    info->SetIsTemp(true);
607fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
608fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
609091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Alias single precision xmm to double xmms.
610091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // TODO: as needed, add larger vector sizes - alias all to the largest.
611091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  GrowableArray<RegisterInfo*>::Iterator it(&reg_pool_->sp_regs_);
612091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  for (RegisterInfo* info = it.Next(); info != nullptr; info = it.Next()) {
613091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    int sp_reg_num = info->GetReg().GetRegNum();
614fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    RegStorage xp_reg = RegStorage::Solo128(sp_reg_num);
615fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    RegisterInfo* xp_reg_info = GetRegInfo(xp_reg);
616fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    // 128-bit xmm vector register's master storage should refer to itself.
617fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    DCHECK_EQ(xp_reg_info, xp_reg_info->Master());
618fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
619fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    // Redirect 32-bit vector's master storage to 128-bit vector.
620fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    info->SetMaster(xp_reg_info);
621fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
62276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    RegStorage dp_reg = RegStorage::FloatSolo64(sp_reg_num);
623091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    RegisterInfo* dp_reg_info = GetRegInfo(dp_reg);
624fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    // Redirect 64-bit vector's master storage to 128-bit vector.
625fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    dp_reg_info->SetMaster(xp_reg_info);
62676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    // Singles should show a single 32-bit mask bit, at first referring to the low half.
62776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    DCHECK_EQ(info->StorageMask(), 0x1U);
62876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko  }
62976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko
630dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
63176af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    // Alias 32bit W registers to corresponding 64bit X registers.
63276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    GrowableArray<RegisterInfo*>::Iterator w_it(&reg_pool_->core_regs_);
63376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    for (RegisterInfo* info = w_it.Next(); info != nullptr; info = w_it.Next()) {
63476af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      int x_reg_num = info->GetReg().GetRegNum();
63576af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      RegStorage x_reg = RegStorage::Solo64(x_reg_num);
63676af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      RegisterInfo* x_reg_info = GetRegInfo(x_reg);
63776af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      // 64bit X register's master storage should refer to itself.
63876af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      DCHECK_EQ(x_reg_info, x_reg_info->Master());
63976af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      // Redirect 32bit W master storage to 64bit X.
64076af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      info->SetMaster(x_reg_info);
64176af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      // 32bit W should show a single 32-bit mask bit, at first referring to the low half.
64276af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko      DCHECK_EQ(info->StorageMask(), 0x1U);
64376af0d307194045ece429dbaf62e93d3e08c6c20Dmitry Petrochenko    }
644efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
645091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee
646091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // Don't start allocating temps at r0/s0/d0 or you may clobber return regs in early-exit methods.
647091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  // TODO: adjust for x86/hard float calling convention.
648091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  reg_pool_->next_core_reg_ = 2;
649091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  reg_pool_->next_sp_reg_ = 2;
650091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  reg_pool_->next_dp_reg_ = 1;
651efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
652efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
65360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjiint X86Mir2Lir::VectorRegisterSize() {
65460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  return 128;
65560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
65660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
65760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjiint X86Mir2Lir::NumReservableVectorRegisters(bool fp_used) {
65860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  return fp_used ? 5 : 7;
65960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
66060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
6611fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::SpillCoreRegs() {
6621fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (num_core_spills_ == 0) {
663efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return;
664efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
665efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Spill mask not including fake return address register
666091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum());
6679ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_);
668efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  for (int reg = 0; mask; mask >>= 1, reg++) {
669efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (mask & 0x1) {
6702700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      StoreWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg));
6719ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      offset += GetInstructionSetPointerSize(cu_->instruction_set);
672efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
673efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
674efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
675efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6761fd3346740dfb7f47be9922312b68a4227fada96buzbeevoid X86Mir2Lir::UnSpillCoreRegs() {
6771fd3346740dfb7f47be9922312b68a4227fada96buzbee  if (num_core_spills_ == 0) {
678efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    return;
679efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
680efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  // Spill mask not including fake return address register
681091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  uint32_t mask = core_spill_mask_ & ~(1 << rs_rRET.GetRegNum());
6829ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  int offset = frame_size_ - (GetInstructionSetPointerSize(cu_->instruction_set) * num_core_spills_);
683efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  for (int reg = 0; mask; mask >>= 1, reg++) {
684efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    if (mask & 0x1) {
6852700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      LoadWordDisp(rs_rX86_SP, offset, RegStorage::Solo32(reg));
6869ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      offset += GetInstructionSetPointerSize(cu_->instruction_set);
687efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
688efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
689efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
690efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
6912ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::IsUnconditionalBranch(LIR* lir) {
692cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee  return (lir->opcode == kX86Jmp8 || lir->opcode == kX86Jmp32);
693efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
694efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
695674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Markobool X86Mir2Lir::SupportsVolatileLoadStore(OpSize size) {
696674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  return true;
697674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko}
698674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko
699674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir MarkoRegisterClass X86Mir2Lir::RegClassForFieldLoadStore(OpSize size, bool is_volatile) {
700e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  // X86_64 can handle any size.
701dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
702e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    if (size == kReference) {
703e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      return kRefReg;
704e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    }
705e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    return kCoreReg;
706e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  }
707e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu
708674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  if (UNLIKELY(is_volatile)) {
709674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko    // On x86, atomic 64-bit load/store requires an fp register.
710674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko    // Smaller aligned load/store is atomic for both core and fp registers.
711674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko    if (size == k64 || size == kDouble) {
712674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko      return kFPReg;
713674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko    }
714674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  }
715674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  return RegClassBySize(size);
716674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko}
717674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko
718dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena SayapinaX86Mir2Lir::X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena)
71955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell    : Mir2Lir(cu, mir_graph, arena),
720dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      base_of_code_(nullptr), store_method_addr_(false), store_method_addr_used_(false),
72155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      method_address_insns_(arena, 100, kGrowableArrayMisc),
72255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      class_type_address_insns_(arena, 100, kGrowableArrayMisc),
723ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      call_method_insns_(arena, 100, kGrowableArrayMisc),
724dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina      stack_decrement_(nullptr), stack_increment_(nullptr),
725d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      const_vectors_(nullptr) {
726d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  store_method_addr_used_ = false;
727dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  if (kIsDebugBuild) {
728dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers    for (int i = 0; i < kX86Last; i++) {
729dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      if (X86Mir2Lir::EncodingMap[i].opcode != i) {
730dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers        LOG(FATAL) << "Encoding order for " << X86Mir2Lir::EncodingMap[i].name
731d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                   << " is wrong: expecting " << i << ", seeing "
732d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell                   << static_cast<int>(X86Mir2Lir::EncodingMap[i].opcode);
733dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers      }
734efc6369224b036a1fb77849f7ae65b3492c832c0buzbee    }
735efc6369224b036a1fb77849f7ae65b3492c832c0buzbee  }
736dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (cu_->target64) {
7379ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_SP = rs_rX86_SP_64;
7389ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko
7399ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG0 = rs_rDI;
7409ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG1 = rs_rSI;
7419ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG2 = rs_rDX;
7429ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG3 = rs_rCX;
74358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_ARG4 = rs_r8;
74458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_ARG5 = rs_r9;
74558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG0 = rs_fr0;
74658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG1 = rs_fr1;
74758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG2 = rs_fr2;
74858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG3 = rs_fr3;
74958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG4 = rs_fr4;
75058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG5 = rs_fr5;
75158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG6 = rs_fr6;
75258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG7 = rs_fr7;
7539ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG0 = rDI;
7549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG1 = rSI;
7559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG2 = rDX;
7569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG3 = rCX;
75758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_ARG4 = r8;
75858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_ARG5 = r9;
75958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG0 = fr0;
76058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG1 = fr1;
76158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG2 = fr2;
76258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG3 = fr3;
76358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG4 = fr4;
76458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG5 = fr5;
76558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG6 = fr6;
76658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG7 = fr7;
76755884bc1e2e1b324809b462455ccaf5811ffafd8Mark Mendell    rs_rX86_INVOKE_TGT = rs_rDI;
7689ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  } else {
7699ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_SP = rs_rX86_SP_32;
7709ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko
7719ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG0 = rs_rAX;
7729ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG1 = rs_rCX;
7739ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG2 = rs_rDX;
7749ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rs_rX86_ARG3 = rs_rBX;
77558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_ARG4 = RegStorage::InvalidReg();
77658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_ARG5 = RegStorage::InvalidReg();
77758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG0 = rs_rAX;
77858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG1 = rs_rCX;
77958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG2 = rs_rDX;
78058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG3 = rs_rBX;
78158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG4 = RegStorage::InvalidReg();
78258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG5 = RegStorage::InvalidReg();
78358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG6 = RegStorage::InvalidReg();
78458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rs_rX86_FARG7 = RegStorage::InvalidReg();
7859ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG0 = rAX;
7869ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG1 = rCX;
7879ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG2 = rDX;
7889ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    rX86_ARG3 = rBX;
78958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG0 = rAX;
79058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG1 = rCX;
79158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG2 = rDX;
79258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rX86_FARG3 = rBX;
79355884bc1e2e1b324809b462455ccaf5811ffafd8Mark Mendell    rs_rX86_INVOKE_TGT = rs_rAX;
79458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // TODO(64): Initialize with invalid reg
79558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko//    rX86_ARG4 = RegStorage::InvalidReg();
79658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko//    rX86_ARG5 = RegStorage::InvalidReg();
7979ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  }
7989ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rs_rX86_RET0 = rs_rAX;
7999ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rs_rX86_RET1 = rs_rDX;
8009ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rs_rX86_COUNT = rs_rCX;
8019ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rX86_RET0 = rAX;
8029ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rX86_RET1 = rDX;
8039ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rX86_INVOKE_TGT = rAX;
8049ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  rX86_COUNT = rCX;
80560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
80660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Initialize the number of reserved vector registers
80760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  num_reserved_vector_regs_ = -1;
8081fd3346740dfb7f47be9922312b68a4227fada96buzbee}
8091fd3346740dfb7f47be9922312b68a4227fada96buzbee
810862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbeeMir2Lir* X86CodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
811862a76027076c341c26aa6cd4a30a7cdd6dc2143buzbee                          ArenaAllocator* const arena) {
812dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  return new X86Mir2Lir(cu, mir_graph, arena);
813efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
814efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
815efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Not used in x86
816dd7624d2b9e599d57762d12031b10b89defc9807Ian RogersRegStorage X86Mir2Lir::LoadHelper(ThreadOffset<4> offset) {
81752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee  LOG(FATAL) << "Unexpected use of LoadHelper in x86";
8182700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  return RegStorage::InvalidReg();
819efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}
820efc6369224b036a1fb77849f7ae65b3492c832c0buzbee
8212f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe// Not used in x86
8222f244e9faccfcca68af3c5484c397a01a1c3a342Andreas GampeRegStorage X86Mir2Lir::LoadHelper(ThreadOffset<8> offset) {
8232f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  LOG(FATAL) << "Unexpected use of LoadHelper in x86";
8242f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  return RegStorage::InvalidReg();
8252f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe}
8262f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe
827b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave AllisonLIR* X86Mir2Lir::CheckSuspendUsingLoad() {
828b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison  LOG(FATAL) << "Unexpected use of CheckSuspendUsingLoad in x86";
829b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison  return nullptr;
830b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison}
831b373e091eac39b1a79c11f2dcbd610af01e9e8a9Dave Allison
8322ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromuint64_t X86Mir2Lir::GetTargetInstFlags(int opcode) {
833409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
8341fd3346740dfb7f47be9922312b68a4227fada96buzbee  return X86Mir2Lir::EncodingMap[opcode].flags;
8351bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee}
8361bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
8372ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstName(int opcode) {
838409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
8391fd3346740dfb7f47be9922312b68a4227fada96buzbee  return X86Mir2Lir::EncodingMap[opcode].name;
8401bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee}
8411bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
8422ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstromconst char* X86Mir2Lir::GetTargetInstFmt(int opcode) {
843409fe94ad529d9334587be80b9f6a3d166805508buzbee  DCHECK(!IsPseudoLirOp(opcode));
8441fd3346740dfb7f47be9922312b68a4227fada96buzbee  return X86Mir2Lir::EncodingMap[opcode].fmt;
8451bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee}
8461bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
847d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbeevoid X86Mir2Lir::GenConstWide(RegLocation rl_dest, int64_t value) {
848d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  // Can we do this directly to memory?
849d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  rl_dest = UpdateLocWide(rl_dest);
850d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  if ((rl_dest.location == kLocDalvikFrame) ||
851d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee      (rl_dest.location == kLocCompilerTemp)) {
852d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    int32_t val_lo = Low32Bits(value);
853d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    int32_t val_hi = High32Bits(value);
854a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    int r_base = rs_rX86_SP.GetReg();
855d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    int displacement = SRegOffset(rl_dest.s_reg_low);
856d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee
8578dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
8582700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LIR * store = NewLIR3(kX86Mov32MI, r_base, displacement + LOWORD_OFFSET, val_lo);
859d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    AnnotateDalvikRegAccess(store, (displacement + LOWORD_OFFSET) >> 2,
860d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee                              false /* is_load */, true /* is64bit */);
8612700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    store = NewLIR3(kX86Mov32MI, r_base, displacement + HIWORD_OFFSET, val_hi);
862d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    AnnotateDalvikRegAccess(store, (displacement + HIWORD_OFFSET) >> 2,
863d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee                              false /* is_load */, true /* is64bit */);
864d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee    return;
865d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  }
866d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee
867d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  // Just use the standard code to do the generation.
868d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee  Mir2Lir::GenConstWide(rl_dest, value);
869d61ba4ba6fcde666adb5d5c81b1c32f0534fb2c8Bill Buzbee}
870e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell
871e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell// TODO: Merge with existing RegLocation dumper in vreg_analysis.cc
872e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendellvoid X86Mir2Lir::DumpRegLocation(RegLocation loc) {
873e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell  LOG(INFO)  << "location: " << loc.location << ','
874e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.wide ? " w" : "  ")
875e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.defined ? " D" : "  ")
876e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.is_const ? " c" : "  ")
877e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.fp ? " F" : "  ")
878e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.core ? " C" : "  ")
879e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.ref ? " r" : "  ")
880e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.high_word ? " h" : "  ")
881e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << (loc.home ? " H" : "  ")
8822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee             << ", low: " << static_cast<int>(loc.reg.GetLowReg())
88300e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee             << ", high: " << static_cast<int>(loc.reg.GetHighReg())
884e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << ", s_reg: " << loc.s_reg_low
885e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell             << ", orig: " << loc.orig_sreg;
886e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell}
887e02d48fb24747f90fd893e1c3572bb3c500afcedMark Mendell
88867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::Materialize() {
88967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // A good place to put the analysis before starting.
89067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  AnalyzeMIR();
89167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
89267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // Now continue with regular code generation.
89367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  Mir2Lir::Materialize();
89467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell}
89567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
89649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Haovoid X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type,
89755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                                   SpecialTargetRegister symbolic_reg) {
89855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  /*
89955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * For x86, just generate a 32 bit move immediate instruction, that will be filled
90055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * in at 'link time'.  For now, put a unique value based on target to ensure that
90155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * code deduplication works.
90255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   */
90349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  int target_method_idx = target_method.dex_method_index;
90449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  const DexFile* target_dex_file = target_method.dex_file;
90549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
90649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id);
90755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
90849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  // Generate the move instruction with the unique pointer and save index, dex_file, and type.
909a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg, false).GetReg(),
91049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                     static_cast<int>(target_method_id_ptr), target_method_idx,
91149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                     WrapPointer(const_cast<DexFile*>(target_dex_file)), type);
91255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  AppendLIR(move);
91355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  method_address_insns_.Insert(move);
91455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell}
91555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
91655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::LoadClassType(uint32_t type_idx, SpecialTargetRegister symbolic_reg) {
91755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  /*
91855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * For x86, just generate a 32 bit move immediate instruction, that will be filled
91955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * in at 'link time'.  For now, put a unique value based on target to ensure that
92055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * code deduplication works.
92155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   */
92255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  const DexFile::TypeId& id = cu_->dex_file->GetTypeId(type_idx);
92355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  uintptr_t ptr = reinterpret_cast<uintptr_t>(&id);
92455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
92555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // Generate the move instruction with the unique pointer and save index and type.
926a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg, false).GetReg(),
92755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                     static_cast<int>(ptr), type_idx);
92855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  AppendLIR(move);
92955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  class_type_address_insns_.Insert(move);
93055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell}
93155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
93249161cef10a308aedada18e9aa742498d6e6c8c7Jeff HaoLIR *X86Mir2Lir::CallWithLinkerFixup(const MethodReference& target_method, InvokeType type) {
93355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  /*
93455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * For x86, just generate a 32 bit call relative instruction, that will be filled
93555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * in at 'link time'.  For now, put a unique value based on target to ensure that
93655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   * code deduplication works.
93755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell   */
93849161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  int target_method_idx = target_method.dex_method_index;
93949161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  const DexFile* target_dex_file = target_method.dex_file;
94049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
94149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id);
94249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao
94349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  // Generate the call instruction with the unique pointer and save index, dex_file, and type.
94449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao  LIR *call = RawLIR(current_dalvik_offset_, kX86CallI, static_cast<int>(target_method_id_ptr),
94549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                     target_method_idx, WrapPointer(const_cast<DexFile*>(target_dex_file)), type);
94655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  AppendLIR(call);
94755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  call_method_insns_.Insert(call);
94855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  return call;
94955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell}
95055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
951d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell/*
952d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell * @brief Enter a 32 bit quantity into a buffer
953d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell * @param buf buffer.
954d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell * @param data Data value.
955d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell */
956d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
957d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellstatic void PushWord(std::vector<uint8_t>&buf, int32_t data) {
958d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  buf.push_back(data & 0xff);
959d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  buf.push_back((data >> 8) & 0xff);
960d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  buf.push_back((data >> 16) & 0xff);
961d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  buf.push_back((data >> 24) & 0xff);
962d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
963d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
96455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendellvoid X86Mir2Lir::InstallLiteralPools() {
96555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // These are handled differently for x86.
96655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  DCHECK(code_literal_list_ == nullptr);
96755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  DCHECK(method_literal_list_ == nullptr);
96855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  DCHECK(class_literal_list_ == nullptr);
96955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
970d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Align to 16 byte boundary.  We have implicit knowledge that the start of the method is
971d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // on a 4 byte boundary.   How can I check this if it changes (other than aligned loads
972d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // will fail at runtime)?
973d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  if (const_vectors_ != nullptr) {
974d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    int align_size = (16-4) - (code_buffer_.size() & 0xF);
975d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    if (align_size < 0) {
976d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      align_size += 16;
977d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    }
978d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
979d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    while (align_size > 0) {
980d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      code_buffer_.push_back(0);
981d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      align_size--;
982d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    }
983d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    for (LIR *p = const_vectors_; p != nullptr; p = p->next) {
984d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      PushWord(code_buffer_, p->operands[0]);
985d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      PushWord(code_buffer_, p->operands[1]);
986d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      PushWord(code_buffer_, p->operands[2]);
987d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      PushWord(code_buffer_, p->operands[3]);
988d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    }
989d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
990d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
99155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // Handle the fixups for methods.
99255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  for (uint32_t i = 0; i < method_address_insns_.Size(); i++) {
99355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      LIR* p = method_address_insns_.Get(i);
99455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      DCHECK_EQ(p->opcode, kX86Mov32RI);
99549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      uint32_t target_method_idx = p->operands[2];
99649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      const DexFile* target_dex_file =
99749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao          reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3]));
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->AddMethodPatch(cu_->dex_file, cu_->class_def_idx,
100255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                                           cu_->method_idx, cu_->invoke_type,
100349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                           target_method_idx, target_dex_file,
100449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                           static_cast<InvokeType>(p->operands[4]),
100555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                                           patch_offset);
100655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  }
100755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
100855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // Handle the fixups for class types.
100955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  for (uint32_t i = 0; i < class_type_address_insns_.Size(); i++) {
101055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      LIR* p = class_type_address_insns_.Get(i);
101155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      DCHECK_EQ(p->opcode, kX86Mov32RI);
101249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      uint32_t target_method_idx = p->operands[2];
101355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
101455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      // The offset to patch is the last 4 bytes of the instruction.
101555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      int patch_offset = p->offset + p->flags.size - 4;
101655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      cu_->compiler_driver->AddClassPatch(cu_->dex_file, cu_->class_def_idx,
101749161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                          cu_->method_idx, target_method_idx, patch_offset);
101855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  }
101955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
102055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // And now the PC-relative calls to methods.
102155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  for (uint32_t i = 0; i < call_method_insns_.Size(); i++) {
102255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      LIR* p = call_method_insns_.Get(i);
102355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      DCHECK_EQ(p->opcode, kX86CallI);
102449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      uint32_t target_method_idx = p->operands[1];
102549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao      const DexFile* target_dex_file =
102649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao          reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2]));
102755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
102855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      // The offset to patch is the last 4 bytes of the instruction.
102955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      int patch_offset = p->offset + p->flags.size - 4;
103055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell      cu_->compiler_driver->AddRelativeCodePatch(cu_->dex_file, cu_->class_def_idx,
103149161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                                 cu_->method_idx, cu_->invoke_type,
103249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                                 target_method_idx, target_dex_file,
103349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao                                                 static_cast<InvokeType>(p->operands[3]),
103455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell                                                 patch_offset, -4 /* offset */);
103555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  }
103655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
103755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  // And do the normal processing.
103855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell  Mir2Lir::InstallLiteralPools();
103955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell}
104055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
10414028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell/*
10424028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * Fast string.index_of(I) & (II).  Inline check for simple case of char <= 0xffff,
10434028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell * otherwise bails to standard library code.
10444028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell */
10454028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendellbool X86Mir2Lir::GenInlinedIndexOf(CallInfo* info, bool zero_based) {
10464028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  ClobberCallerSave();
10474028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LockCallTemps();  // Using fixed registers
10484028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
10494028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // EAX: 16 bit character being searched.
10504028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // ECX: count: number of words to be searched.
10514028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // EDI: String being searched.
10524028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // EDX: temporary during execution.
1053c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  // EBX or R11: temporary during execution (depending on mode).
10544028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
10554028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  RegLocation rl_obj = info->args[0];
10564028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  RegLocation rl_char = info->args[1];
1057a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee  RegLocation rl_start;  // Note: only present in III flavor or IndexOf.
1058c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  RegStorage tmpReg = cu_->target64 ? rs_r11 : rs_rBX;
10594028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
10604028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  uint32_t char_value =
10614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    rl_char.is_const ? mir_graph_->ConstantValue(rl_char.orig_sreg) : 0;
10624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
10634028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  if (char_value > 0xFFFF) {
10644028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // We have to punt to the real String.indexOf.
10654028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    return false;
10664028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
10674028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
10684028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Okay, we are commited to inlining this.
1069a0cd2d701f29e0bc6275f1b13c0edfd4ec391879buzbee  RegLocation rl_return = GetReturn(kCoreReg);
10704028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  RegLocation rl_dest = InlineTarget(info);
10714028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
10724028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Is the string non-NULL?
10732700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LoadValueDirectFixed(rl_obj, rs_rDX);
10742700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  GenNullCheck(rs_rDX, info->opt_flags);
10753bc8615332b7848dec8c2297a40f7e4d176c0efbVladimir Marko  info->opt_flags |= MIR_IGNORE_NULL_CHECK;  // Record that we've null checked.
10764028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
10774028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Does the character fit in 16 bits?
10783a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang  LIR* slowpath_branch = nullptr;
10794028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  if (rl_char.is_const) {
10804028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // We need the value in EAX.
10812700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LoadConstantNoClobber(rs_rAX, char_value);
10824028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  } else {
10834028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // Character is not a constant; compare at runtime.
10842700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    LoadValueDirectFixed(rl_char, rs_rAX);
10853a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang    slowpath_branch = OpCmpImmBranch(kCondGt, rs_rAX, 0xFFFF, nullptr);
10864028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
10874028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
10884028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // From here down, we know that we are looking for a char that fits in 16 bits.
1089e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // Location of reference to data array within the String object.
1090e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  int value_offset = mirror::String::ValueOffset().Int32Value();
1091e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // Location of count within the String object.
1092e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  int count_offset = mirror::String::CountOffset().Int32Value();
1093e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // Starting offset within data array.
1094e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  int offset_offset = mirror::String::OffsetOffset().Int32Value();
1095e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // Start of char data with array_.
1096e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  int data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Int32Value();
10974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
10984028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Character is in EAX.
10994028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Object pointer is in EDX.
11004028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11014028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // We need to preserve EDI, but have no spare registers, so push it on the stack.
11024028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // We have to remember that all stack addresses after this are offset by sizeof(EDI).
1103091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR1(kX86Push32R, rs_rDI.GetReg());
11044028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11054028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Compute the number of words to search in to rCX.
1106695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  Load32Disp(rs_rDX, count_offset, rs_rCX);
11074028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LIR *length_compare = nullptr;
11084028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  int start_value = 0;
1109a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov  bool is_index_on_stack = false;
11104028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  if (zero_based) {
11114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // We have to handle an empty string.  Use special instruction JECXZ.
11124028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    length_compare = NewLIR0(kX86Jecxz8);
11134028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  } else {
1114a44d4f508fa1642294e79d3ebecd790afe75ea60buzbee    rl_start = info->args[2];
11154028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    // We have to offset by the start index.
11164028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    if (rl_start.is_const) {
11174028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      start_value = mir_graph_->ConstantValue(rl_start.orig_sreg);
11184028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      start_value = std::max(start_value, 0);
11194028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11204028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      // Is the start > count?
11212700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      length_compare = OpCmpImmBranch(kCondLe, rs_rCX, start_value, nullptr);
11224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11234028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      if (start_value != 0) {
11242700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        OpRegImm(kOpSub, rs_rCX, start_value);
11254028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      }
11264028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    } else {
11274028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      // Runtime start index.
112830adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      rl_start = UpdateLocTyped(rl_start, kCoreReg);
11294028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      if (rl_start.location == kLocPhysReg) {
1130a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        // Handle "start index < 0" case.
1131c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpRegReg(kOpXor, tmpReg, tmpReg);
1132c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpRegReg(kOpCmp, rl_start.reg, tmpReg);
1133c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpCondRegReg(kOpCmov, kCondLt, rl_start.reg, tmpReg);
1134a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov
1135a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        // The length of the string should be greater than the start index.
11362700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        length_compare = OpCmpBranch(kCondLe, rs_rCX, rl_start.reg, nullptr);
11372700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        OpRegReg(kOpSub, rs_rCX, rl_start.reg);
1138a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        if (rl_start.reg == rs_rDI) {
1139a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov          // The special case. We will use EDI further, so lets put start index to stack.
1140091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee          NewLIR1(kX86Push32R, rs_rDI.GetReg());
1141a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov          is_index_on_stack = true;
1142a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        }
11434028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      } else {
1144a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        // Load the start index from stack, remembering that we pushed EDI.
1145c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        int displacement = SRegOffset(rl_start.s_reg_low) + (cu_->target64 ? 2 : 1) * sizeof(uint32_t);
11468dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko        {
11478dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
1148c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk          Load32Disp(rs_rX86_SP, displacement, tmpReg);
11498dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko        }
1150a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        OpRegReg(kOpXor, rs_rDI, rs_rDI);
1151c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpRegReg(kOpCmp, tmpReg, rs_rDI);
1152c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpCondRegReg(kOpCmov, kCondLt, tmpReg, rs_rDI);
1153a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov
1154c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        length_compare = OpCmpBranch(kCondLe, rs_rCX, tmpReg, nullptr);
1155c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        OpRegReg(kOpSub, rs_rCX, tmpReg);
1156a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        // Put the start index to stack.
1157c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk        NewLIR1(kX86Push32R, tmpReg.GetReg());
1158a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov        is_index_on_stack = true;
11594028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell      }
11604028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    }
11614028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
11624028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  DCHECK(length_compare != nullptr);
11634028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11644028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // ECX now contains the count in words to be searched.
11654028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
1166c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  // Load the address of the string into R11 or EBX (depending on mode).
1167e19c91fdb88ff6fd4e88bc5984772dcfb1e86f80Mark Mendell  // The string starts at VALUE(String) + 2 * OFFSET(String) + DATA_OFFSET.
1168695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee  Load32Disp(rs_rDX, value_offset, rs_rDI);
1169c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  Load32Disp(rs_rDX, offset_offset, tmpReg);
1170c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  OpLea(tmpReg, rs_rDI, tmpReg, 1, data_offset);
11714028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11724028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Now compute into EDI where the search will start.
11734028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  if (zero_based || rl_start.is_const) {
11744028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    if (start_value == 0) {
1175c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk      OpRegCopy(rs_rDI, tmpReg);
11764028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    } else {
1177c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk      NewLIR3(kX86Lea32RM, rs_rDI.GetReg(), tmpReg.GetReg(), 2 * start_value);
11784028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    }
11794028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  } else {
1180a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov    if (is_index_on_stack == true) {
1181a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov      // Load the start index from stack.
1182091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      NewLIR1(kX86Pop32R, rs_rDX.GetReg());
1183c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk      OpLea(rs_rDI, tmpReg, rs_rDX, 1, 0);
1184a1758d83e298c9ee31848bcae07c2a35f6efd618Alexei Zavjalov    } else {
1185c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk      OpLea(rs_rDI, tmpReg, rl_start.reg, 1, 0);
11864028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    }
11874028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
11884028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11894028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // EDI now contains the start of the string to be searched.
11904028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // We are all prepared to do the search for the character.
11914028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  NewLIR0(kX86RepneScasw);
11924028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11934028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Did we find a match?
11944028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LIR* failed_branch = OpCondBranch(kCondNe, nullptr);
11954028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
11964028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // yes, we matched.  Compute the index of the result.
11974028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // index = ((curr_ptr - orig_ptr) / 2) - 1.
1198c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  OpRegReg(kOpSub, rs_rDI, tmpReg);
11992700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  OpRegImm(kOpAsr, rs_rDI, 1);
1200091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR3(kX86Lea32RM, rl_return.reg.GetReg(), rs_rDI.GetReg(), -1);
12014028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LIR *all_done = NewLIR1(kX86Jmp8, 0);
12024028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12034028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Failed to match; return -1.
12044028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  LIR *not_found = NewLIR0(kPseudoTargetLabel);
12054028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  length_compare->target = not_found;
12064028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  failed_branch->target = not_found;
12072700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LoadConstantNoClobber(rl_return.reg, -1);
12084028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12094028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // And join up at the end.
12104028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  all_done->target = NewLIR0(kPseudoTargetLabel);
12114028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Restore EDI from the stack.
1212091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  NewLIR1(kX86Pop32R, rs_rDI.GetReg());
12134028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12144028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  // Out of line code returns here.
12153a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang  if (slowpath_branch != nullptr) {
12164028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell    LIR *return_point = NewLIR0(kPseudoTargetLabel);
12173a74d15ccc9a902874473ac9632e568b19b91b1cMingyao Yang    AddIntrinsicSlowPath(info, slowpath_branch, return_point);
12184028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  }
12194028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
12204028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  StoreValue(rl_dest, rl_return);
12214028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell  return true;
12224028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell}
12234028a6c83a339036864999fdfd2855b012a9f1a7Mark Mendell
1224ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell/*
1225ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @brief Enter an 'advance LOC' into the FDE buffer
1226ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param buf FDE buffer.
1227ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell * @param increment Amount by which to increase the current location.
1228ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell */
1229ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstatic void AdvanceLoc(std::vector<uint8_t>&buf, uint32_t increment) {
1230ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  if (increment < 64) {
1231ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Encoding in opcode.
1232ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(0x1 << 6 | increment);
1233ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  } else if (increment < 256) {
1234ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Single byte delta.
1235ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(0x02);
1236ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(increment);
1237ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  } else if (increment < 256 * 256) {
1238ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Two byte delta.
1239ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(0x03);
1240ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(increment & 0xff);
1241ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back((increment >> 8) & 0xff);
1242ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  } else {
1243ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Four byte delta.
1244ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(0x04);
1245ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    PushWord(buf, increment);
1246ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
1247ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1248ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1249ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1250ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86CFIInitialization() {
1251ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  return X86Mir2Lir::ReturnCommonCallFrameInformation();
1252ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1253ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1254ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86Mir2Lir::ReturnCommonCallFrameInformation() {
1255ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>;
1256ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1257ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Length of the CIE (except for this field).
1258ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 16);
1259ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1260ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // CIE id.
1261ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 0xFFFFFFFFU);
1262ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1263ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Version: 3.
1264ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x03);
1265ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1266ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Augmentation: empty string.
1267ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x0);
1268ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1269ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Code alignment: 1.
1270ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x01);
1271ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1272ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Data alignment: -4.
1273ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x7C);
1274ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1275ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Return address register (R8).
1276ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x08);
1277ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1278ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Initial return PC is 4(ESP): DW_CFA_def_cfa R4 4.
1279ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x0C);
1280ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x04);
1281ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x04);
1282ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1283ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Return address location: 0(SP): DW_CFA_offset R8 1 (* -4);.
1284ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x2 << 6 | 0x08);
1285ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x01);
1286ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1287ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // And 2 Noops to align to 4 byte boundary.
1288ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x0);
1289ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  cfi_info->push_back(0x0);
1290ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1291ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  DCHECK_EQ(cfi_info->size() & 3, 0U);
1292ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  return cfi_info;
1293ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1294ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1295ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstatic void EncodeUnsignedLeb128(std::vector<uint8_t>& buf, uint32_t value) {
1296ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  uint8_t buffer[12];
1297ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  uint8_t *ptr = EncodeUnsignedLeb128(buffer, value);
1298ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  for (uint8_t *p = buffer; p < ptr; p++) {
1299ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    buf.push_back(*p);
1300ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
1301ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1302ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1303ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendellstd::vector<uint8_t>* X86Mir2Lir::ReturnCallFrameInformation() {
1304ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  std::vector<uint8_t>*cfi_info = new std::vector<uint8_t>;
1305ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1306ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Generate the FDE for the method.
1307ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  DCHECK_NE(data_offset_, 0U);
1308ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1309ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Length (will be filled in later in this routine).
1310ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 0);
1311ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1312ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // CIE_pointer (can be filled in by linker); might be left at 0 if there is only
1313ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // one CIE for the whole debug_frame section.
1314ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 0);
1315ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1316ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // 'initial_location' (filled in by linker).
1317ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, 0);
1318ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1319ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // 'address_range' (number of bytes in the method).
1320ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  PushWord(*cfi_info, data_offset_);
1321ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1322ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // The instructions in the FDE.
1323ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  if (stack_decrement_ != nullptr) {
1324ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Advance LOC to just past the stack decrement.
1325ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    uint32_t pc = NEXT_LIR(stack_decrement_)->offset;
1326ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    AdvanceLoc(*cfi_info, pc);
1327ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1328ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // Now update the offset to the call frame: DW_CFA_def_cfa_offset frame_size.
1329ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    cfi_info->push_back(0x0e);
1330ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    EncodeUnsignedLeb128(*cfi_info, frame_size_);
1331ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1332ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // We continue with that stack until the epilogue.
1333ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    if (stack_increment_ != nullptr) {
1334ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      uint32_t new_pc = NEXT_LIR(stack_increment_)->offset;
1335ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      AdvanceLoc(*cfi_info, new_pc - pc);
1336ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1337ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // We probably have code snippets after the epilogue, so save the
1338ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // current state: DW_CFA_remember_state.
1339ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      cfi_info->push_back(0x0a);
1340ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1341ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // We have now popped the stack: DW_CFA_def_cfa_offset 4.  There is only the return
1342ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // PC on the stack now.
1343ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      cfi_info->push_back(0x0e);
1344ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      EncodeUnsignedLeb128(*cfi_info, 4);
1345ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1346ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // Everything after that is the same as before the epilogue.
1347ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      // Stack bump was followed by RET instruction.
1348ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      LIR *post_ret_insn = NEXT_LIR(NEXT_LIR(stack_increment_));
1349ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      if (post_ret_insn != nullptr) {
1350ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        pc = new_pc;
1351ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        new_pc = post_ret_insn->offset;
1352ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        AdvanceLoc(*cfi_info, new_pc - pc);
1353ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        // Restore the state: DW_CFA_restore_state.
1354ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell        cfi_info->push_back(0x0b);
1355ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell      }
1356ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    }
1357ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
1358ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1359ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Padding to a multiple of 4
1360ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  while ((cfi_info->size() & 3) != 0) {
1361ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    // DW_CFA_nop is encoded as 0.
1362ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell    cfi_info->push_back(0);
1363ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  }
1364ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1365ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  // Set the length of the FDE inside the generated bytes.
1366ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  uint32_t length = cfi_info->size() - 4;
1367ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  (*cfi_info)[0] = length;
1368ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  (*cfi_info)[1] = length >> 8;
1369ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  (*cfi_info)[2] = length >> 16;
1370ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  (*cfi_info)[3] = length >> 24;
1371ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell  return cfi_info;
1372ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell}
1373ae9fd93c39a341e2dffe15c61cc7d9e841fa92c4Mark Mendell
1374d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenMachineSpecificExtendedMethodMIR(BasicBlock* bb, MIR* mir) {
1375d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
137660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kMirOpReserveVectorRegisters:
137760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      ReserveVectorRegisters(mir);
137860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
137960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kMirOpReturnVectorRegisters:
138060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      ReturnVectorRegisters();
138160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
1382d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    case kMirOpConstVector:
1383d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      GenConst128(bb, mir);
1384d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      break;
1385fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpMoveVector:
1386fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenMoveVector(bb, mir);
1387fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1388fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedMultiply:
1389fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenMultiplyVector(bb, mir);
1390fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1391fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedAddition:
1392fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenAddVector(bb, mir);
1393fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1394fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedSubtract:
1395fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenSubtractVector(bb, mir);
1396fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1397fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedShiftLeft:
1398fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenShiftLeftVector(bb, mir);
1399fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1400fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedSignedShiftRight:
1401fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenSignedShiftRightVector(bb, mir);
1402fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1403fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedUnsignedShiftRight:
1404fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenUnsignedShiftRightVector(bb, mir);
1405fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1406fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedAnd:
1407fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenAndVector(bb, mir);
1408fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1409fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedOr:
1410fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenOrVector(bb, mir);
1411fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1412fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedXor:
1413fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenXorVector(bb, mir);
1414fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1415fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedAddReduce:
1416fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenAddReduceVector(bb, mir);
1417fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1418fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedReduce:
1419fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenReduceVector(bb, mir);
1420fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1421fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kMirOpPackedSet:
1422fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      GenSetVector(bb, mir);
1423fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1424d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    default:
1425d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      break;
1426d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
1427d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
1428d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
142960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::ReserveVectorRegisters(MIR* mir) {
143060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // We should not try to reserve twice without returning the registers
143160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_NE(num_reserved_vector_regs_, -1);
143260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
143360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int num_vector_reg = mir->dalvikInsn.vA;
143460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  for (int i = 0; i < num_vector_reg; i++) {
143560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    RegStorage xp_reg = RegStorage::Solo128(i);
143660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    RegisterInfo *xp_reg_info = GetRegInfo(xp_reg);
143760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    Clobber(xp_reg);
143860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
143960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    for (RegisterInfo *info = xp_reg_info->GetAliasChain();
144060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji                       info != nullptr;
144160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji                       info = info->GetAliasChain()) {
144260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      if (info->GetReg().IsSingle()) {
144360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji        reg_pool_->sp_regs_.Delete(info);
144460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      } else {
144560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji        reg_pool_->dp_regs_.Delete(info);
144660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      }
144760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    }
144860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
144960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
145060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  num_reserved_vector_regs_ = num_vector_reg;
145160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
145260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
145360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::ReturnVectorRegisters() {
145460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Return all the reserved registers
145560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  for (int i = 0; i < num_reserved_vector_regs_; i++) {
145660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    RegStorage xp_reg = RegStorage::Solo128(i);
145760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    RegisterInfo *xp_reg_info = GetRegInfo(xp_reg);
145860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
145960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    for (RegisterInfo *info = xp_reg_info->GetAliasChain();
146060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji                       info != nullptr;
146160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji                       info = info->GetAliasChain()) {
146260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      if (info->GetReg().IsSingle()) {
146360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji        reg_pool_->sp_regs_.Insert(info);
146460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      } else {
146560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji        reg_pool_->dp_regs_.Insert(info);
146660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      }
146760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    }
146860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
146960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
147060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // We don't have anymore reserved vector registers
147160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  num_reserved_vector_regs_ = -1;
147260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
147360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
1474d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendellvoid X86Mir2Lir::GenConst128(BasicBlock* bb, MIR* mir) {
147560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  store_method_addr_used_ = true;
147660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int type_size = mir->dalvikInsn.vB;
1477d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // We support 128 bit vectors.
1478d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  DCHECK_EQ(type_size & 0xFFFF, 128);
147960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA);
1480d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  uint32_t *args = mir->dalvikInsn.arg;
1481fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int reg = rs_dest.GetReg();
1482d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Check for all 0 case.
1483d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  if (args[0] == 0 && args[1] == 0 && args[2] == 0 && args[3] == 0) {
1484d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    NewLIR2(kX86XorpsRR, reg, reg);
1485d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    return;
1486d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
148760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
148860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Append the mov const vector to reg opcode.
148960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  AppendOpcodeWithConst(kX86MovupsRM, reg, mir);
149060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
149160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
149260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::AppendOpcodeWithConst(X86OpCode opcode, int reg, MIR* mir) {
1493d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Okay, load it from the constant vector area.
1494d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  LIR *data_target = ScanVectorLiteral(mir);
1495d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  if (data_target == nullptr) {
1496d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    data_target = AddVectorLiteral(mir);
1497d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
1498d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
1499d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Address the start of the method.
1500d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low);
1501e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  if (rl_method.wide) {
1502e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    rl_method = LoadValueWide(rl_method, kCoreReg);
1503e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  } else {
1504e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    rl_method = LoadValue(rl_method, kCoreReg);
1505e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  }
1506d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
1507d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // Load the proper value from the literal area.
1508d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // We don't know the proper offset for the value, so pick one that will force
1509d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // 4 byte offset.  We will fix this up in the assembler later to have the right
1510d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  // value.
15118dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
151260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  LIR *load = NewLIR2(opcode, reg, rl_method.reg.GetReg());
1513d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  load->flags.fixup = kFixupLoad;
1514d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  load->target = data_target;
1515d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
1516d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
1517fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenMoveVector(BasicBlock *bb, MIR *mir) {
1518fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // We only support 128 bit registers.
151960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
152060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA);
152160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src = RegStorage::Solo128(mir->dalvikInsn.vB);
1522fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(kX86Mova128RR, rs_dest.GetReg(), rs_src.GetReg());
1523fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1524fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
152560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::GenMultiplyVectorSignedByte(BasicBlock *bb, MIR *mir) {
152660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  const int BYTE_SIZE = 8;
152760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
152860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB);
152960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src1_high_tmp = Get128BitRegister(AllocTempWide());
153060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
153160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  /*
153260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   * Emulate the behavior of a kSignedByte by separating out the 16 values in the two XMM
153360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   * and multiplying 8 at a time before recombining back into one XMM register.
153460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *
153560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *   let xmm1, xmm2 be real srcs (keep low bits of 16bit lanes)
153660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *       xmm3 is tmp             (operate on high bits of 16bit lanes)
153760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *
153860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *    xmm3 = xmm1
153960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *    xmm1 = xmm1 .* xmm2
154060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *    xmm1 = xmm1 & 0x00ff00ff00ff00ff00ff00ff00ff00ff  // xmm1 now has low bits
154160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *    xmm3 = xmm3 .>> 8
154260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *    xmm2 = xmm2 & 0xff00ff00ff00ff00ff00ff00ff00ff00
154360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *    xmm2 = xmm2 .* xmm3                               // xmm2 now has high bits
154460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *    xmm1 = xmm1 | xmm2                                // combine results
154560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   */
154660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
154760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Copy xmm1.
154860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(kX86Mova128RR, rs_src1_high_tmp.GetReg(), rs_dest_src1.GetReg());
154960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
155060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Multiply low bits.
155160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(kX86PmullwRR, rs_dest_src1.GetReg(), rs_src2.GetReg());
155260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
155360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // xmm1 now has low bits.
155460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  AndMaskVectorRegister(rs_dest_src1, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF);
155560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
155660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Prepare high bits for multiplication.
155760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(kX86PsrlwRI, rs_src1_high_tmp.GetReg(), BYTE_SIZE);
155860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  AndMaskVectorRegister(rs_src2, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00);
155960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
156060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Multiply high bits and xmm2 now has high bits.
156160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(kX86PmullwRR, rs_src2.GetReg(), rs_src1_high_tmp.GetReg());
156260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
156360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Combine back into dest XMM register.
156460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_src2.GetReg());
156560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
156660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
1567fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenMultiplyVector(BasicBlock *bb, MIR *mir) {
156860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
156960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16);
157060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
157160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB);
1572fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1573fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1574fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1575fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PmulldRR;
1576fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1577fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1578fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PmullwRR;
1579fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1580fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSingle:
1581fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86MulpsRR;
1582fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1583fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kDouble:
1584fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86MulpdRR;
1585fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
158660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kSignedByte:
158760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      // HW doesn't support 16x16 byte multiplication so emulate it.
158860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      GenMultiplyVectorSignedByte(bb, mir);
158960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      return;
1590fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1591fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector multiply " << opsize;
1592fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1593fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1594fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg());
1595fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1596fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1597fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenAddVector(BasicBlock *bb, MIR *mir) {
159860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
159960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16);
160060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
160160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB);
1602fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1603fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1604fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1605fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PadddRR;
1606fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1607fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1608fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1609fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PaddwRR;
1610fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1611fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedByte:
1612fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedByte:
1613fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PaddbRR;
1614fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1615fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSingle:
1616fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86AddpsRR;
1617fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1618fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kDouble:
1619fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86AddpdRR;
1620fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1621fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1622fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector addition " << opsize;
1623fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1624fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1625fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg());
1626fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1627fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1628fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenSubtractVector(BasicBlock *bb, MIR *mir) {
162960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
163060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16);
163160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
163260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB);
1633fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1634fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1635fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1636fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsubdRR;
1637fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1638fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1639fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1640fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsubwRR;
1641fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1642fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedByte:
1643fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedByte:
1644fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsubbRR;
1645fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1646fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSingle:
1647fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86SubpsRR;
1648fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1649fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kDouble:
1650fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86SubpdRR;
1651fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1652fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1653fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector subtraction " << opsize;
1654fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1655fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1656fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), rs_src2.GetReg());
1657fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1658fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
165960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::GenShiftByteVector(BasicBlock *bb, MIR *mir) {
166060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
166160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_tmp = Get128BitRegister(AllocTempWide());
166260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
166360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int opcode = 0;
166460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int imm = mir->dalvikInsn.vB;
166560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
166660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) {
166760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kMirOpPackedShiftLeft:
166860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      opcode = kX86PsllwRI;
166960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
167060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kMirOpPackedSignedShiftRight:
167160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      opcode = kX86PsrawRI;
167260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
167360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kMirOpPackedUnsignedShiftRight:
167460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      opcode = kX86PsrlwRI;
167560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
167660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    default:
167760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      LOG(FATAL) << "Unsupported shift operation on byte vector " << opcode;
167860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
167960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
168060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
168160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  /*
168260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   * xmm1 will have low bits
168360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   * xmm2 will have high bits
168460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   *
168560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   * xmm2 = xmm1
168660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   * xmm1 = xmm1 .<< N
168760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   * xmm2 = xmm2 && 0xFF00FF00FF00FF00FF00FF00FF00FF00
168860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   * xmm2 = xmm2 .<< N
168960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   * xmm1 = xmm1 | xmm2
169060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji   */
169160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
169260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Copy xmm1.
169360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(kX86Mova128RR, rs_tmp.GetReg(), rs_dest_src1.GetReg());
169460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
169560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Shift lower values.
169660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(opcode, rs_dest_src1.GetReg(), imm);
169760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
169860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Mask bottom bits.
169960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  AndMaskVectorRegister(rs_tmp, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00);
170060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
170160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Shift higher values.
170260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(opcode, rs_tmp.GetReg(), imm);
170360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
170460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Combine back into dest XMM register.
170560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_tmp.GetReg());
170660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
170760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
1708fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenShiftLeftVector(BasicBlock *bb, MIR *mir) {
170960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
171060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16);
171160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
171260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int imm = mir->dalvikInsn.vB;
1713fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1714fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1715fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1716fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PslldRI;
1717fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1718fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k64:
1719fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsllqRI;
1720fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1721fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1722fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1723fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsllwRI;
1724fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
172560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kSignedByte:
172660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kUnsignedByte:
172760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      GenShiftByteVector(bb, mir);
172860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      return;
1729fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1730fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector shift left " << opsize;
1731fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1732fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1733fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), imm);
1734fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1735fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1736fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenSignedShiftRightVector(BasicBlock *bb, MIR *mir) {
173760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
173860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16);
173960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
174060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int imm = mir->dalvikInsn.vB;
1741fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1742fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1743fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1744fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsradRI;
1745fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1746fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1747fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1748fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsrawRI;
1749fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
175060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kSignedByte:
175160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kUnsignedByte:
175260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      GenShiftByteVector(bb, mir);
175360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      return;
1754fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1755fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector signed shift right " << opsize;
1756fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1757fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1758fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), imm);
1759fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1760fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1761fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenUnsignedShiftRightVector(BasicBlock *bb, MIR *mir) {
176260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
176360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16);
176460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
176560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int imm = mir->dalvikInsn.vB;
1766fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
1767fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1768fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1769fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsrldRI;
1770fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1771fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k64:
1772fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsrlqRI;
1773fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1774fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1775fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1776fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PsrlwRI;
1777fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
177860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kSignedByte:
177960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kUnsignedByte:
178060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      GenShiftByteVector(bb, mir);
178160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      return;
1782fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1783fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector unsigned shift right " << opsize;
1784fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1785fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1786fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(opcode, rs_dest_src1.GetReg(), imm);
1787fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1788fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1789fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenAndVector(BasicBlock *bb, MIR *mir) {
1790fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // We only support 128 bit registers.
179160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
179260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
179360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB);
1794fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(kX86PandRR, rs_dest_src1.GetReg(), rs_src2.GetReg());
1795fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1796fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1797fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenOrVector(BasicBlock *bb, MIR *mir) {
1798fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // We only support 128 bit registers.
179960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
180060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
180160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB);
1802fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(kX86PorRR, rs_dest_src1.GetReg(), rs_src2.GetReg());
1803fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1804fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1805fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenXorVector(BasicBlock *bb, MIR *mir) {
1806fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // We only support 128 bit registers.
180760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
180860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest_src1 = RegStorage::Solo128(mir->dalvikInsn.vA);
180960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src2 = RegStorage::Solo128(mir->dalvikInsn.vB);
1810fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  NewLIR2(kX86PxorRR, rs_dest_src1.GetReg(), rs_src2.GetReg());
1811fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1812fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
181360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::AndMaskVectorRegister(RegStorage rs_src1, uint32_t m1, uint32_t m2, uint32_t m3, uint32_t m4) {
181460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  MaskVectorRegister(kX86PandRM, rs_src1, m1, m2, m3, m4);
181560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
181660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
181760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerjivoid X86Mir2Lir::MaskVectorRegister(X86OpCode opcode, RegStorage rs_src1, uint32_t m0, uint32_t m1, uint32_t m2, uint32_t m3) {
181860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Create temporary MIR as container for 128-bit binary mask.
181960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  MIR const_mir;
182060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  MIR* const_mirp = &const_mir;
182160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  const_mirp->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpConstVector);
182260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  const_mirp->dalvikInsn.arg[0] = m0;
182360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  const_mirp->dalvikInsn.arg[1] = m1;
182460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  const_mirp->dalvikInsn.arg[2] = m2;
182560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  const_mirp->dalvikInsn.arg[3] = m3;
182660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
182760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Mask vector with const from literal pool.
182860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  AppendOpcodeWithConst(opcode, rs_src1.GetReg(), const_mirp);
182960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji}
183060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
1831fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenAddReduceVector(BasicBlock *bb, MIR *mir) {
183260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16);
183360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
183460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegLocation rl_dest = mir_graph_->GetDest(mir);
183560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_tmp;
183660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
183760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int vec_bytes = (mir->dalvikInsn.vC & 0xFFFF) / 8;
183860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int vec_unit_size = 0;
1839fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  int opcode = 0;
184060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int extr_opcode = 0;
184160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegLocation rl_result;
184260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
1843fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1844fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
184560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      extr_opcode = kX86PextrdRRI;
1846fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PhadddRR;
184760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      vec_unit_size = 4;
184860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
184960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kSignedByte:
185060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kUnsignedByte:
185160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      extr_opcode = kX86PextrbRRI;
185260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      opcode = kX86PhaddwRR;
185360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      vec_unit_size = 2;
1854fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1855fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1856fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
185760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      extr_opcode = kX86PextrwRRI;
1858fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      opcode = kX86PhaddwRR;
185960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      vec_unit_size = 2;
1860fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
186160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kSingle:
186260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      rl_result = EvalLoc(rl_dest, kFPReg, true);
186360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      vec_unit_size = 4;
186460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      for (int i = 0; i < 3; i++) {
186560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji        NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), rs_src1.GetReg());
186660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji        NewLIR3(kX86ShufpsRRI, rs_src1.GetReg(), rs_src1.GetReg(), 0x39);
186760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      }
186860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      NewLIR2(kX86AddssRR, rl_result.reg.GetReg(), rs_src1.GetReg());
186960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      StoreValue(rl_dest, rl_result);
187060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
187160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      // For single-precision floats, we are done here
187260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      return;
1873fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
1874fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector add reduce " << opsize;
1875fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1876fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
187760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
187860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int elems = vec_bytes / vec_unit_size;
187960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
188060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Emulate horizontal add instruction by reducing 2 vectors with 8 values before adding them again
188160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // TODO is overflow handled correctly?
188260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  if (opsize == kSignedByte || opsize == kUnsignedByte) {
188360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    rs_tmp = Get128BitRegister(AllocTempWide());
188460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
188560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    // tmp = xmm1 .>> 8.
188660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    NewLIR2(kX86Mova128RR, rs_tmp.GetReg(), rs_src1.GetReg());
188760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    NewLIR2(kX86PsrlwRI, rs_tmp.GetReg(), 8);
188860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
188960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    // Zero extend low bits in xmm1.
189060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    AndMaskVectorRegister(rs_src1, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF);
189160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
189260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
189360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  while (elems > 1) {
189460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    if (opsize == kSignedByte || opsize == kUnsignedByte) {
189560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      NewLIR2(opcode, rs_tmp.GetReg(), rs_tmp.GetReg());
189660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    }
189760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    NewLIR2(opcode, rs_src1.GetReg(), rs_src1.GetReg());
189860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    elems >>= 1;
189960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
190060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
190160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Combine the results if we separated them.
190260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  if (opsize == kSignedByte || opsize == kUnsignedByte) {
190360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    NewLIR2(kX86PaddbRR, rs_src1.GetReg(), rs_tmp.GetReg());
190460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
190560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
190660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // We need to extract to a GPR.
190760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage temp = AllocTemp();
190860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR3(extr_opcode, temp.GetReg(), rs_src1.GetReg(), 0);
190960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
191060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Can we do this directly into memory?
191160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  rl_result = UpdateLocTyped(rl_dest, kCoreReg);
191260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  if (rl_result.location == kLocPhysReg) {
191360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    // Ensure res is in a core reg
191460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    rl_result = EvalLoc(rl_dest, kCoreReg, true);
191560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    OpRegReg(kOpAdd, rl_result.reg, temp);
191660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    StoreFinalValue(rl_dest, rl_result);
191760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  } else {
191860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    OpMemReg(kOpAdd, rl_result, temp.GetReg());
191960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
192060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
192160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  FreeTemp(temp);
1922fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1923fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1924fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenReduceVector(BasicBlock *bb, MIR *mir) {
192560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16);
192660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegLocation rl_dest = mir_graph_->GetDest(mir);
192760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_src1 = RegStorage::Solo128(mir->dalvikInsn.vB);
192860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int extract_index = mir->dalvikInsn.arg[0];
192960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int extr_opcode = 0;
193060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegLocation rl_result;
193160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  bool is_wide = false;
193260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
1933fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1934fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
193560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      rl_result = UpdateLocTyped(rl_dest, kCoreReg);
193660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrdMRI : kX86PextrdRRI;
1937fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1938fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1939fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
194060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      rl_result= UpdateLocTyped(rl_dest, kCoreReg);
194160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      extr_opcode = (rl_result.location == kLocPhysReg) ? kX86PextrwMRI : kX86PextrwRRI;
1942fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1943fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
194460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      LOG(FATAL) << "Unsupported vector add reduce " << opsize;
194560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      return;
1946fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
1947fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
1948fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
194960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  if (rl_result.location == kLocPhysReg) {
195060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    NewLIR3(extr_opcode, rl_result.reg.GetReg(), rs_src1.GetReg(), extract_index);
195160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    if (is_wide == true) {
195260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      StoreFinalValue(rl_dest, rl_result);
195360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    } else {
195460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      StoreFinalValueWide(rl_dest, rl_result);
195560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    }
195660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  } else {
195760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    int displacement = SRegOffset(rl_result.s_reg_low);
195860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    LIR *l = NewLIR3(extr_opcode, rs_rX86_SP.GetReg(), displacement, rs_src1.GetReg());
195960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, is_wide /* is_64bit */);
196060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    AnnotateDalvikRegAccess(l, displacement >> 2, false /* is_load */, is_wide /* is_64bit */);
196160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
1962fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
1963fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
1964fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendellvoid X86Mir2Lir::GenSetVector(BasicBlock *bb, MIR *mir) {
196560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  DCHECK_EQ(mir->dalvikInsn.vC & 0xFFFF, 128U);
196660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  OpSize opsize = static_cast<OpSize>(mir->dalvikInsn.vC >> 16);
196760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegStorage rs_dest = RegStorage::Solo128(mir->dalvikInsn.vA);
196860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  int op_low = 0, op_high = 0, imm = 0, op_mov = kX86MovdxrRR;
196960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  RegisterClass reg_type = kCoreReg;
197060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
1971fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  switch (opsize) {
1972fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case k32:
1973fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      op_low = kX86PshufdRRI;
1974fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
197560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kSingle:
197660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      op_low = kX86PshufdRRI;
197760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      op_mov = kX86Mova128RR;
197860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      reg_type = kFPReg;
197960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
198060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case k64:
198160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      op_low = kX86PshufdRRI;
198260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      imm = 0x44;
198360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
198460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kDouble:
198560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      op_low = kX86PshufdRRI;
198660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      op_mov = kX86Mova128RR;
198760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      reg_type = kFPReg;
198860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      imm = 0x44;
198960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      break;
199060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kSignedByte:
199160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    case kUnsignedByte:
199260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      // Shuffle 8 bit value into 16 bit word.
199360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji      // We set val = val + (val << 8) below and use 16 bit shuffle.
1994fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kSignedHalf:
1995fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    case kUnsignedHalf:
1996fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      // Handles low quadword.
1997fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      op_low = kX86PshuflwRRI;
1998fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      // Handles upper quadword.
1999fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      op_high = kX86PshufdRRI;
2000fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
2001fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell    default:
2002fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      LOG(FATAL) << "Unsupported vector set " << opsize;
2003fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell      break;
2004fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
2005fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
2006fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  RegLocation rl_src = mir_graph_->GetSrc(mir, 0);
200760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
200860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // Load the value from the VR into the reg.
200960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  if (rl_src.wide == 0) {
201060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    rl_src = LoadValue(rl_src, reg_type);
201160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  } else {
201260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    rl_src = LoadValueWide(rl_src, reg_type);
201360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
201460bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji
201560bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  // If opsize is 8 bits wide then double value and use 16 bit shuffle instead.
201660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  if (opsize == kSignedByte || opsize == kUnsignedByte) {
201760bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    RegStorage temp = AllocTemp();
201860bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    // val = val + (val << 8).
201960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    NewLIR2(kX86Mov32RR, temp.GetReg(), rl_src.reg.GetReg());
202060bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    NewLIR2(kX86Sal32RI, temp.GetReg(), 8);
202160bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    NewLIR2(kX86Or32RR, rl_src.reg.GetReg(), temp.GetReg());
202260bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    FreeTemp(temp);
202360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  }
2024fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
2025fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Load the value into the XMM register.
202660bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR2(op_mov, rs_dest.GetReg(), rl_src.reg.GetReg());
2027fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
2028fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // Now shuffle the value across the destination.
202960bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji  NewLIR3(op_low, rs_dest.GetReg(), rs_dest.GetReg(), imm);
2030fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
2031fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  // And then repeat as needed.
2032fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  if (op_high != 0) {
203360bfe7b3e8f00f0a8ef3f5d8716adfdf86b71f43Udayan Banerji    NewLIR3(op_high, rs_dest.GetReg(), rs_dest.GetReg(), imm);
2034fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell  }
2035fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell}
2036fe94578b63380f464c3abd5c156b7b31d068db6cMark Mendell
2037d65c51a556e6649db4e18bd083c8fec37607a442Mark MendellLIR *X86Mir2Lir::ScanVectorLiteral(MIR *mir) {
2038d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg);
2039d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  for (LIR *p = const_vectors_; p != nullptr; p = p->next) {
2040d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    if (args[0] == p->operands[0] && args[1] == p->operands[1] &&
2041d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell        args[2] == p->operands[2] && args[3] == p->operands[3]) {
2042d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      return p;
2043d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    }
2044d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
2045d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  return nullptr;
2046d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
2047d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
2048d65c51a556e6649db4e18bd083c8fec37607a442Mark MendellLIR *X86Mir2Lir::AddVectorLiteral(MIR *mir) {
2049d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  LIR* new_value = static_cast<LIR*>(arena_->Alloc(sizeof(LIR), kArenaAllocData));
2050d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  int *args = reinterpret_cast<int*>(mir->dalvikInsn.arg);
2051d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->operands[0] = args[0];
2052d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->operands[1] = args[1];
2053d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->operands[2] = args[2];
2054d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->operands[3] = args[3];
2055d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  new_value->next = const_vectors_;
2056d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  if (const_vectors_ == nullptr) {
2057d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    estimated_native_code_size_ += 12;  // Amount needed to align to 16 byte boundary.
2058d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  }
2059d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  estimated_native_code_size_ += 16;  // Space for one vector.
2060d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  const_vectors_ = new_value;
2061d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell  return new_value;
2062d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell}
2063d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell
206458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// ------------ ABI support: mapping of args to physical registers -------------
206558994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::InToRegStorageX86_64Mapper::GetNextReg(bool is_double_or_float, bool is_wide) {
2066a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  const SpecialTargetRegister coreArgMappingToPhysicalReg[] = {kArg1, kArg2, kArg3, kArg4, kArg5};
2067a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  const int coreArgMappingToPhysicalRegSize = sizeof(coreArgMappingToPhysicalReg) / sizeof(SpecialTargetRegister);
2068a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  const SpecialTargetRegister fpArgMappingToPhysicalReg[] = {kFArg0, kFArg1, kFArg2, kFArg3,
2069a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu                                                  kFArg4, kFArg5, kFArg6, kFArg7};
2070a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  const int fpArgMappingToPhysicalRegSize = sizeof(fpArgMappingToPhysicalReg) / sizeof(SpecialTargetRegister);
207158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
207258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (is_double_or_float) {
207358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    if (cur_fp_reg_ < fpArgMappingToPhysicalRegSize) {
2074a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu      return ml_->TargetReg(fpArgMappingToPhysicalReg[cur_fp_reg_++], is_wide);
207558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
207658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  } else {
207758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    if (cur_core_reg_ < coreArgMappingToPhysicalRegSize) {
2078a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu      return ml_->TargetReg(coreArgMappingToPhysicalReg[cur_core_reg_++], is_wide);
207958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
208058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
2081a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  return RegStorage::InvalidReg();
208258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
208358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
208458994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::InToRegStorageMapping::Get(int in_position) {
208558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  DCHECK(IsInitialized());
208658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  auto res = mapping_.find(in_position);
208758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  return res != mapping_.end() ? res->second : RegStorage::InvalidReg();
208858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
208958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
209058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkovoid X86Mir2Lir::InToRegStorageMapping::Initialize(RegLocation* arg_locs, int count, InToRegStorageMapper* mapper) {
209158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  DCHECK(mapper != nullptr);
209258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  max_mapped_in_ = -1;
209358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  is_there_stack_mapped_ = false;
209458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  for (int in_position = 0; in_position < count; in_position++) {
209558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko     RegStorage reg = mapper->GetNextReg(arg_locs[in_position].fp, arg_locs[in_position].wide);
209658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko     if (reg.Valid()) {
209758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       mapping_[in_position] = reg;
209858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       max_mapped_in_ = std::max(max_mapped_in_, in_position);
209958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       if (reg.Is64BitSolo()) {
210058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         // We covered 2 args, so skip the next one
210158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         in_position++;
210258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       }
210358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko     } else {
210458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       is_there_stack_mapped_ = true;
210558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko     }
210658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
210758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  initialized_ = true;
210858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
210958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
211058994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::GetArgMappingToPhysicalReg(int arg_num) {
2111dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (!cu_->target64) {
211258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return GetCoreArgMappingToPhysicalReg(arg_num);
211358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
211458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
211558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (!in_to_reg_storage_mapping_.IsInitialized()) {
211658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int start_vreg = cu_->num_dalvik_registers - cu_->num_ins;
211758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    RegLocation* arg_locs = &mir_graph_->reg_location_[start_vreg];
211858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
2119a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    InToRegStorageX86_64Mapper mapper(this);
212058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    in_to_reg_storage_mapping_.Initialize(arg_locs, cu_->num_ins, &mapper);
212158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
212258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  return in_to_reg_storage_mapping_.Get(arg_num);
212358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
212458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
212558994cdb00b323339bd83828eddc53976048006fDmitry PetrochenkoRegStorage X86Mir2Lir::GetCoreArgMappingToPhysicalReg(int core_arg_num) {
212658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // For the 32-bit internal ABI, the first 3 arguments are passed in registers.
212758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Not used for 64-bit, TODO: Move X86_32 to the same framework
212858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  switch (core_arg_num) {
212958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case 0:
213058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      return rs_rX86_ARG1;
213158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case 1:
213258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      return rs_rX86_ARG2;
213358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    case 2:
213458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      return rs_rX86_ARG3;
213558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    default:
213658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      return RegStorage::InvalidReg();
213758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
213858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
213958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
214058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko// ---------End of ABI support: mapping of args to physical registers -------------
214158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
214258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/*
214358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * If there are any ins passed in registers that have not been promoted
214458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * to a callee-save register, flush them to the frame.  Perform initial
214558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * assignment of promoted arguments.
214658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *
214758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * ArgLocs is an array of location records describing the incoming arguments
214858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * with one location record per word of argument.
214958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */
215058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkovoid X86Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) {
2151dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (!cu_->target64) return Mir2Lir::FlushIns(ArgLocs, rl_method);
215258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  /*
215358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * Dummy up a RegLocation for the incoming Method*
215458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * It will attempt to keep kArg0 live (or copy it to home location
215558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * if promoted).
215658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   */
215758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
215858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  RegLocation rl_src = rl_method;
215958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  rl_src.location = kLocPhysReg;
2160a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  rl_src.reg = TargetRefReg(kArg0);
216158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  rl_src.home = false;
216258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  MarkLive(rl_src);
216358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  StoreValue(rl_method, rl_src);
216458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // If Method* has been promoted, explicitly flush
216558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (rl_method.location == kLocPhysReg) {
2166a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    StoreRefDisp(rs_rX86_SP, 0, As32BitReg(TargetRefReg(kArg0)), kNotVolatile);
216758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
216858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
216958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (cu_->num_ins == 0) {
217058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return;
217158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
217258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
217358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  int start_vreg = cu_->num_dalvik_registers - cu_->num_ins;
217458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  /*
217558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * Copy incoming arguments to their proper home locations.
217658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * NOTE: an older version of dx had an issue in which
217758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * it would reuse static method argument registers.
217858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * This could result in the same Dalvik virtual register
217958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * being promoted to both core and fp regs. To account for this,
218058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * we only copy to the corresponding promoted physical register
218158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * if it matches the type of the SSA name for the incoming
218258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * argument.  It is also possible that long and double arguments
218358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * end up half-promoted.  In those cases, we must flush the promoted
218458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   * half to memory as well.
218558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko   */
21868dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
218758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  for (int i = 0; i < cu_->num_ins; i++) {
218858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // get reg corresponding to input
21894d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko    RegStorage reg = GetArgMappingToPhysicalReg(i);
219058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
21914d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko    RegLocation* t_loc = &ArgLocs[i];
219258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    if (reg.Valid()) {
21934d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // If arriving in register.
219458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
21954d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // We have already updated the arg location with promoted info
21964d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // so we can be based on it.
21974d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      if (t_loc->location == kLocPhysReg) {
21984d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        // Just copy it.
21994d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        OpRegCopy(t_loc->reg, reg);
22004d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      } else {
22014d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        // Needs flush.
22024d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        if (t_loc->ref) {
2203a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          StoreRefDisp(rs_rX86_SP, SRegOffset(start_vreg + i), reg, kNotVolatile);
220458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else {
2205a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          StoreBaseDisp(rs_rX86_SP, SRegOffset(start_vreg + i), reg, t_loc->wide ? k64 : k32,
22064d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko                        kNotVolatile);
220758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
220858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
220958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    } else {
22104d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // If arriving in frame & promoted.
22114d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      if (t_loc->location == kLocPhysReg) {
22124d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        if (t_loc->ref) {
2213a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          LoadRefDisp(rs_rX86_SP, SRegOffset(start_vreg + i), t_loc->reg, kNotVolatile);
22144d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        } else {
2215a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          LoadBaseDisp(rs_rX86_SP, SRegOffset(start_vreg + i), t_loc->reg,
22164d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko                       t_loc->wide ? k64 : k32, kNotVolatile);
22174d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko        }
221858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
221958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
22204d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko    if (t_loc->wide) {
22214d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      // Increment i to skip the next one.
22224d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko      i++;
22234d5d794382cd6d3a25392d17543d5987e432d314Dmitry Petrochenko    }
222458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
222558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
222658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
222758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/*
222858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Load up to 5 arguments, the first three of which will be in
222958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * kArg1 .. kArg3.  On entry kArg0 contains the current method pointer,
223058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * and as part of the load sequence, it must be replaced with
223158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * the target method pointer.  Note, this may also be called
223258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * for "range" variants if the number of arguments is 5 or fewer.
223358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */
223458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsNoRange(CallInfo* info,
223558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  int call_state, LIR** pcrLabel, NextCallInsn next_call_insn,
223658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  const MethodReference& target_method,
223758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  uint32_t vtable_idx, uintptr_t direct_code,
223858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  uintptr_t direct_method, InvokeType type, bool skip_this) {
2239dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (!cu_->target64) {
224058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return Mir2Lir::GenDalvikArgsNoRange(info,
224158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  call_state, pcrLabel, next_call_insn,
224258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  target_method,
224358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  vtable_idx, direct_code,
224458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                  direct_method, type, skip_this);
224558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
224658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  return GenDalvikArgsRange(info,
224758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                       call_state, pcrLabel, next_call_insn,
224858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                       target_method,
224958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                       vtable_idx, direct_code,
225058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                       direct_method, type, skip_this);
225158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
225258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
225358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko/*
225458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * May have 0+ arguments (also used for jumbo).  Note that
225558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * source virtual registers may be in physical registers, so may
225658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * need to be flushed to home location before copying.  This
225758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * applies to arg3 and above (see below).
225858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *
225958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko * Two general strategies:
226058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *    If < 20 arguments
226158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *       Pass args 3-18 using vldm/vstm block copy
226258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *       Pass arg0, arg1 & arg2 in kArg1-kArg3
226358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *    If 20+ arguments
226458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *       Pass args arg19+ using memcpy block copy
226558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *       Pass arg0, arg1 & arg2 in kArg1-kArg3
226658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko *
226758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko */
226858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenkoint X86Mir2Lir::GenDalvikArgsRange(CallInfo* info, int call_state,
226958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                LIR** pcrLabel, NextCallInsn next_call_insn,
227058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                const MethodReference& target_method,
227158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                uint32_t vtable_idx, uintptr_t direct_code, uintptr_t direct_method,
227258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                InvokeType type, bool skip_this) {
2273dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (!cu_->target64) {
227458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return Mir2Lir::GenDalvikArgsRange(info, call_state,
227558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                pcrLabel, next_call_insn,
227658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                target_method,
227758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                vtable_idx, direct_code, direct_method,
227858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                type, skip_this);
227958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
228058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
228158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  /* If no arguments, just return */
228258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (info->num_arg_words == 0)
228358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    return call_state;
228458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
228558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  const int start_index = skip_this ? 1 : 0;
228658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
2287a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu  InToRegStorageX86_64Mapper mapper(this);
228858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  InToRegStorageMapping in_to_reg_storage_mapping;
228958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  in_to_reg_storage_mapping.Initialize(info->args, info->num_arg_words, &mapper);
229058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  const int last_mapped_in = in_to_reg_storage_mapping.GetMaxMappedIn();
229158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  const int size_of_the_last_mapped = last_mapped_in == -1 ? 1 :
229258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          in_to_reg_storage_mapping.Get(last_mapped_in).Is64BitSolo() ? 2 : 1;
229358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  int regs_left_to_pass_via_stack = info->num_arg_words - (last_mapped_in + size_of_the_last_mapped);
229458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
229558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Fisrt of all, check whether it make sense to use bulk copying
229658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Optimization is aplicable only for range case
229758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // TODO: make a constant instead of 2
229858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (info->is_range && regs_left_to_pass_via_stack >= 2) {
229958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // Scan the rest of the args - if in phys_reg flush to memory
230058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    for (int next_arg = last_mapped_in + size_of_the_last_mapped; next_arg < info->num_arg_words;) {
230158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      RegLocation loc = info->args[next_arg];
230258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      if (loc.wide) {
230358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        loc = UpdateLocWide(loc);
230458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (loc.location == kLocPhysReg) {
23058dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
2306a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          StoreBaseDisp(rs_rX86_SP, SRegOffset(loc.s_reg_low), loc.reg, k64, kNotVolatile);
230758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
230858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        next_arg += 2;
230958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      } else {
231058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        loc = UpdateLoc(loc);
231158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (loc.location == kLocPhysReg) {
23128dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
2313a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          StoreBaseDisp(rs_rX86_SP, SRegOffset(loc.s_reg_low), loc.reg, k32, kNotVolatile);
231458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
231558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        next_arg++;
231658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
231758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
231858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
231958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // Logic below assumes that Method pointer is at offset zero from SP.
232058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    DCHECK_EQ(VRegOffset(static_cast<int>(kVRegMethodPtrBaseReg)), 0);
232158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
232258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    // The rest can be copied together
232358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int start_offset = SRegOffset(info->args[last_mapped_in + size_of_the_last_mapped].s_reg_low);
232458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int outs_offset = StackVisitor::GetOutVROffset(last_mapped_in + size_of_the_last_mapped, cu_->instruction_set);
232558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
232658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int current_src_offset = start_offset;
232758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    int current_dest_offset = outs_offset;
232858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
23298dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    // Only davik regs are accessed in this loop; no next_call_insn() calls.
23308dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
233158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    while (regs_left_to_pass_via_stack > 0) {
233258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      // This is based on the knowledge that the stack itself is 16-byte aligned.
233358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      bool src_is_16b_aligned = (current_src_offset & 0xF) == 0;
233458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      bool dest_is_16b_aligned = (current_dest_offset & 0xF) == 0;
233558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      size_t bytes_to_move;
233658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
233758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      /*
233858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       * The amount to move defaults to 32-bit. If there are 4 registers left to move, then do a
233958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       * a 128-bit move because we won't get the chance to try to aligned. If there are more than
234058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       * 4 registers left to move, consider doing a 128-bit only if either src or dest are aligned.
234158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       * We do this because we could potentially do a smaller move to align.
234258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko       */
234358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      if (regs_left_to_pass_via_stack == 4 ||
234458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          (regs_left_to_pass_via_stack > 4 && (src_is_16b_aligned || dest_is_16b_aligned))) {
234558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Moving 128-bits via xmm register.
234658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        bytes_to_move = sizeof(uint32_t) * 4;
234758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
234858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Allocate a free xmm temp. Since we are working through the calling sequence,
234958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // we expect to have an xmm temporary available.  AllocTempDouble will abort if
235058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // there are no free registers.
235158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        RegStorage temp = AllocTempDouble();
235258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
235358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LIR* ld1 = nullptr;
235458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LIR* ld2 = nullptr;
235558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LIR* st1 = nullptr;
235658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LIR* st2 = nullptr;
235758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
235858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        /*
235958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * The logic is similar for both loads and stores. If we have 16-byte alignment,
236058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * do an aligned move. If we have 8-byte alignment, then do the move in two
236158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * parts. This approach prevents possible cache line splits. Finally, fall back
236258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * to doing an unaligned move. In most cases we likely won't split the cache
236358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         * line but we cannot prove it and thus take a conservative approach.
236458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko         */
236558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        bool src_is_8b_aligned = (current_src_offset & 0x7) == 0;
236658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        bool dest_is_8b_aligned = (current_dest_offset & 0x7) == 0;
236758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
23688dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko        ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
236958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (src_is_16b_aligned) {
2370a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovA128FP);
237158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else if (src_is_8b_aligned) {
2372a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovLo128FP);
2373a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          ld2 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset + (bytes_to_move >> 1),
237458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                            kMovHi128FP);
237558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else {
2376a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          ld1 = OpMovRegMem(temp, rs_rX86_SP, current_src_offset, kMovU128FP);
237758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
237858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
237958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (dest_is_16b_aligned) {
2380a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovA128FP);
238158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else if (dest_is_8b_aligned) {
2382a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovLo128FP);
2383a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          st2 = OpMovMemReg(rs_rX86_SP, current_dest_offset + (bytes_to_move >> 1),
238458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                            temp, kMovHi128FP);
238558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        } else {
2386a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu          st1 = OpMovMemReg(rs_rX86_SP, current_dest_offset, temp, kMovU128FP);
238758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
238858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
238958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // TODO If we could keep track of aliasing information for memory accesses that are wider
239058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // than 64-bit, we wouldn't need to set up a barrier.
239158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (ld1 != nullptr) {
239258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          if (ld2 != nullptr) {
239358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            // For 64-bit load we can actually set up the aliasing information.
239458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            AnnotateDalvikRegAccess(ld1, current_src_offset >> 2, true, true);
239558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            AnnotateDalvikRegAccess(ld2, (current_src_offset + (bytes_to_move >> 1)) >> 2, true, true);
239658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          } else {
239758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            // Set barrier for 128-bit load.
23988dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            ld1->u.m.def_mask = &kEncodeAll;
239958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          }
240058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
240158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        if (st1 != nullptr) {
240258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          if (st2 != nullptr) {
240358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            // For 64-bit store we can actually set up the aliasing information.
240458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            AnnotateDalvikRegAccess(st1, current_dest_offset >> 2, false, true);
240558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            AnnotateDalvikRegAccess(st2, (current_dest_offset + (bytes_to_move >> 1)) >> 2, false, true);
240658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          } else {
240758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko            // Set barrier for 128-bit store.
24088dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            st1->u.m.def_mask = &kEncodeAll;
240958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          }
241058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
241158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
241258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Free the temporary used for the data movement.
241358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        FreeTemp(temp);
241458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      } else {
241558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Moving 32-bits via general purpose register.
241658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        bytes_to_move = sizeof(uint32_t);
241758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
241858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Instead of allocating a new temp, simply reuse one of the registers being used
241958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // for argument passing.
2420a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu        RegStorage temp = TargetReg(kArg3, false);
242158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
242258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        // Now load the argument VR and store to the outs.
2423a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu        Load32Disp(rs_rX86_SP, current_src_offset, temp);
2424a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu        Store32Disp(rs_rX86_SP, current_dest_offset, temp);
242558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
242658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
242758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      current_src_offset += bytes_to_move;
242858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      current_dest_offset += bytes_to_move;
242958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      regs_left_to_pass_via_stack -= (bytes_to_move >> 2);
243058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
243158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    DCHECK_EQ(regs_left_to_pass_via_stack, 0);
243258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
243358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
243458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Now handle rest not registers if they are
243558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (in_to_reg_storage_mapping.IsThereStackMapped()) {
2436a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    RegStorage regSingle = TargetReg(kArg2, false);
2437a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu    RegStorage regWide = TargetReg(kArg3, true);
2438b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu    for (int i = start_index;
2439b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu         i < last_mapped_in + size_of_the_last_mapped + regs_left_to_pass_via_stack; i++) {
244058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      RegLocation rl_arg = info->args[i];
244158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      rl_arg = UpdateRawLoc(rl_arg);
244258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      RegStorage reg = in_to_reg_storage_mapping.Get(i);
244358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      if (!reg.Valid()) {
244458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        int out_offset = StackVisitor::GetOutVROffset(i, cu_->instruction_set);
244558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
24468dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko        {
24478dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
24488dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko          if (rl_arg.wide) {
24498dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            if (rl_arg.location == kLocPhysReg) {
2450a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu              StoreBaseDisp(rs_rX86_SP, out_offset, rl_arg.reg, k64, kNotVolatile);
24518dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            } else {
24528dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko              LoadValueDirectWideFixed(rl_arg, regWide);
2453a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu              StoreBaseDisp(rs_rX86_SP, out_offset, regWide, k64, kNotVolatile);
24548dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            }
245558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          } else {
24568dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            if (rl_arg.location == kLocPhysReg) {
2457a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu              StoreBaseDisp(rs_rX86_SP, out_offset, rl_arg.reg, k32, kNotVolatile);
24588dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            } else {
24598dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko              LoadValueDirectFixed(rl_arg, regSingle);
2460a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu              StoreBaseDisp(rs_rX86_SP, out_offset, regSingle, k32, kNotVolatile);
24618dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko            }
246258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko          }
246358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        }
246458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        call_state = next_call_insn(cu_, info, call_state, target_method,
246558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                                    vtable_idx, direct_code, direct_method, type);
246658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
2467b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu      if (rl_arg.wide) {
2468b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu        i++;
2469b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu      }
247058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
247158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
247258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
247358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  // Finish with mapped registers
247458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  for (int i = start_index; i <= last_mapped_in; i++) {
247558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    RegLocation rl_arg = info->args[i];
247658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    rl_arg = UpdateRawLoc(rl_arg);
247758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    RegStorage reg = in_to_reg_storage_mapping.Get(i);
247858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    if (reg.Valid()) {
247958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      if (rl_arg.wide) {
248058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LoadValueDirectWideFixed(rl_arg, reg);
248158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      } else {
248258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko        LoadValueDirectFixed(rl_arg, reg);
248358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      }
248458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
248558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                               direct_code, direct_method, type);
248658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
2487b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu    if (rl_arg.wide) {
2488b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu      i++;
2489b6564c19c5e14a3caa3f8da423b0da510fda7026Chao-ying Fu    }
249058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
249158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
249258994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  call_state = next_call_insn(cu_, info, call_state, target_method, vtable_idx,
249358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko                           direct_code, direct_method, type);
249458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  if (pcrLabel) {
24955655e84e8d71697d8ef3ea901a0b853af42c559eAndreas Gampe    if (cu_->compiler_driver->GetCompilerOptions().GetExplicitNullChecks()) {
2496a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu      *pcrLabel = GenExplicitNullCheck(TargetRefReg(kArg1), info->opt_flags);
249758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    } else {
249858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      *pcrLabel = nullptr;
249958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      // In lieu of generating a check for kArg1 being null, we need to
250058994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      // perform a load when doing implicit checks.
250158994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      RegStorage tmp = AllocTemp();
2502a77ee5103532abb197f492c14a9e6fb437054e2aChao-ying Fu      Load32Disp(TargetRefReg(kArg1), 0, tmp);
250358994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      MarkPossibleNullPointerException(info->opt_flags);
250458994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko      FreeTemp(tmp);
250558994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko    }
250658994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  }
250758994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko  return call_state;
250858994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko}
250958994cdb00b323339bd83828eddc53976048006fDmitry Petrochenko
25107934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
2511