utility_x86.cc revision 37f05ef45e0393de812d51261dc293240c17294d
1e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee/*
2e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Copyright (C) 2012 The Android Open Source Project
3e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee *
4e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Licensed under the Apache License, Version 2.0 (the "License");
5e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * you may not use this file except in compliance with the License.
6e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * You may obtain a copy of the License at
7e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee *
8e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee *      http://www.apache.org/licenses/LICENSE-2.0
9e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee *
10e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Unless required by applicable law or agreed to in writing, software
11e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * distributed under the License is distributed on an "AS IS" BASIS,
12e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * See the License for the specific language governing permissions and
14e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * limitations under the License.
15e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee */
16e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1702031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h"
187940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "dex/quick/mir_to_lir-inl.h"
1967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell#include "dex/dataflow_iterator-inl.h"
20641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h"
217071c8d5885175a746723a3b38a347855965be08Yixin Shou#include "dex/quick/dex_file_method_inliner.h"
227071c8d5885175a746723a3b38a347855965be08Yixin Shou#include "dex/quick/dex_file_to_method_inliner_map.h"
23b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h"
241bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
25e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbeenamespace art {
26e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
27b046e16d8b8da318d6055f9308950131f1255e08buzbee/* This file contains codegen for the X86 ISA */
28e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
292700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
30a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int opcode;
31a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* must be both DOUBLE or both not DOUBLE */
32091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(r_dest.IsFloat() || r_src.IsFloat());
33091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK_EQ(r_dest.IsDouble(), r_src.IsDouble());
34091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (r_dest.IsDouble()) {
35a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    opcode = kX86MovsdRR;
36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
37091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    if (r_dest.IsSingle()) {
38091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_src.IsSingle()) {
39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kX86MovssRR;
40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {  // Fpr <- Gpr
41a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kX86MovdxrRR;
42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
43a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {  // Gpr <- Fpr
44091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      DCHECK(r_src.IsSingle()) << "Raw: 0x" << std::hex << r_src.GetRawBits();
45a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kX86MovdrxRR;
46e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
48ec13743da80a80c1817cf6660c28917fc28846bcbuzbee  DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
492700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest.GetReg(), r_src.GetReg());
50fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest == r_src) {
51fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res->flags.is_nop = true;
52a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
53a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
54e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
55e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
562ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantInt(int32_t value) {
57e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  return true;
58e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
59e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
602ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantFloat(int32_t value) {
614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return false;
624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
642ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantLong(int64_t value) {
654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return true;
664ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
682ce745c06271d5223d57dbf08117b20d5b60694aBrian Carlstrombool X86Mir2Lir::InexpensiveConstantDouble(int64_t value) {
6967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  return value == 0;
704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
714ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
72e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee/*
73e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Load a immediate using a shortcut if possible; otherwise
74e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * grab from the per-translation literal pool.  If target is
75e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * a high register, build constant into a low register and copy.
76e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee *
77e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * No additional register clobbering operation performed. Use this version when
78fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * 1) r_dest is freshly returned from AllocTemp or
79e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 2) The codegen is under fixed register usage
80e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee */
812700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
822700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  RegStorage r_dest_save = r_dest;
83091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (r_dest.IsFloat()) {
84b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    if (value == 0) {
852700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      return NewLIR2(kX86XorpsRR, r_dest.GetReg(), r_dest.GetReg());
86b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
871fd3346740dfb7f47be9922312b68a4227fada96buzbee    r_dest = AllocTemp();
886cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
89e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
90b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  LIR *res;
916cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  if (value == 0) {
922700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    res = NewLIR2(kX86Xor32RR, r_dest.GetReg(), r_dest.GetReg());
936cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  } else {
942e9f7ed8d00271cb1cf082d68b4f4bc60702d6ecIan Rogers    // Note, there is no byte immediate form of a 32 bit immediate move.
95e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    // 64-bit immediate is not supported by LIR structure
96e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    res = NewLIR2(kX86Mov32RI, r_dest.GetReg(), value);
976cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
98e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
99091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  if (r_dest_save.IsFloat()) {
1002700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    NewLIR2(kX86MovdxrRR, r_dest_save.GetReg(), r_dest.GetReg());
1011fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(r_dest);
1026cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
103e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1046cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  return res;
105e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
106e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1072ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* X86Mir2Lir::OpUnconditionalBranch(LIR* target) {
108df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom  LIR* res = NewLIR1(kX86Jmp8, 0 /* offset to be patched during assembly*/);
10902031b185b4653e6c72e21f7a51238b903f6d638buzbee  res->target = target;
11002031b185b4653e6c72e21f7a51238b903f6d638buzbee  return res;
111e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
112e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1132ce745c06271d5223d57dbf08117b20d5b60694aBrian CarlstromLIR* X86Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
1141fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch = NewLIR2(kX86Jcc8, 0 /* offset to be patched */,
11552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee                        X86ConditionEncoding(cc));
116b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  branch->target = target;
117b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return branch;
118a7678db092ac6bb79f7cad490099a1015fbbc714buzbee}
119a7678db092ac6bb79f7cad490099a1015fbbc714buzbee
1202700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
121b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Bkpt;
122b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (op) {
123e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpNeg: opcode = r_dest_src.Is64Bit() ? kX86Neg64R : kX86Neg32R; break;
124e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpNot: opcode = r_dest_src.Is64Bit() ? kX86Not64R : kX86Not32R; break;
125c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk    case kOpRev: opcode = r_dest_src.Is64Bit() ? kX86Bswap64R : kX86Bswap32R; break;
126b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpBlx: opcode = kX86CallR; break;
127b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
12852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in OpReg " << op;
129b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
1302700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  return NewLIR1(opcode, r_dest_src.GetReg());
131e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
132e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1332700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
134b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Bkpt;
135fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool byte_imm = IS_SIMM8(value);
136091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(!r_dest_src1.IsFloat());
1379ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  if (r_dest_src1.Is64Bit()) {
1389ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    switch (op) {
1399ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpAdd: opcode = byte_imm ? kX86Add64RI8 : kX86Add64RI; break;
1409ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpSub: opcode = byte_imm ? kX86Sub64RI8 : kX86Sub64RI; break;
141e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpLsl: opcode = kX86Sal64RI; break;
142e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpLsr: opcode = kX86Shr64RI; break;
143e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpAsr: opcode = kX86Sar64RI; break;
1447e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu      case kOpCmp: opcode = byte_imm ? kX86Cmp64RI8 : kX86Cmp64RI; break;
1459ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      default:
1469ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        LOG(FATAL) << "Bad case in OpRegImm (64-bit) " << op;
1479ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    }
1489ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko  } else {
1499ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    switch (op) {
1509ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpLsl: opcode = kX86Sal32RI; break;
1519ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpLsr: opcode = kX86Shr32RI; break;
1529ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpAsr: opcode = kX86Sar32RI; break;
1539ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
1549ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpOr:  opcode = byte_imm ? kX86Or32RI8  : kX86Or32RI;  break;
1559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
1569ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      // case kOpSbb: opcode = kX86Sbb32RI; break;
1579ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
1589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
1599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
1609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
1619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpMov:
1629ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        /*
1639ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko         * Moving the constant zero into register can be specialized as an xor of the register.
1649ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko         * However, that sets eflags while the move does not. For that reason here, always do
1659ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko         * the move and if caller is flexible, they should be calling LoadConstantNoClobber instead.
1669ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko         */
1679ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        opcode = kX86Mov32RI;
1689ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        break;
1699ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      case kOpMul:
1709ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
1719ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), value);
172e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell      case kOp2Byte:
173e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        opcode = kX86Mov32RI;
174e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        value = static_cast<int8_t>(value);
175e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        break;
176e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell      case kOp2Short:
177e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        opcode = kX86Mov32RI;
178e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        value = static_cast<int16_t>(value);
179e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        break;
180e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell      case kOp2Char:
181e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        opcode = kX86Mov32RI;
182e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        value = static_cast<uint16_t>(value);
183e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        break;
184e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell      case kOpNeg:
185e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        opcode = kX86Mov32RI;
186e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        value = -value;
187e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell        break;
1889ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      default:
1899ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        LOG(FATAL) << "Bad case in OpRegImm " << op;
1909ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    }
191b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
1922700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  return NewLIR2(opcode, r_dest_src1.GetReg(), value);
193e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
194e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1952700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
196e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    bool is64Bit = r_dest_src1.Is64Bit();
197a7678db092ac6bb79f7cad490099a1015fbbc714buzbee    X86OpCode opcode = kX86Nop;
198d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    bool src2_must_be_cx = false;
199e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    switch (op) {
200b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        // X86 unary opcodes
201b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpMvn:
2021fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(r_dest_src1, r_src2);
2031fd3346740dfb7f47be9922312b68a4227fada96buzbee        return OpReg(kOpNot, r_dest_src1);
204b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpNeg:
2051fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(r_dest_src1, r_src2);
2061fd3346740dfb7f47be9922312b68a4227fada96buzbee        return OpReg(kOpNeg, r_dest_src1);
207a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      case kOpRev:
208a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko        OpRegCopy(r_dest_src1, r_src2);
209a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko        return OpReg(kOpRev, r_dest_src1);
210a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko      case kOpRevsh:
211a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko        OpRegCopy(r_dest_src1, r_src2);
212a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko        OpReg(kOpRev, r_dest_src1);
213a8b4caf7526b6b66a8ae0826bd52c39c66e3c714Vladimir Marko        return OpRegImm(kOpAsr, r_dest_src1, 16);
214b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        // X86 binary opcodes
215e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpSub: opcode = is64Bit ? kX86Sub64RR : kX86Sub32RR; break;
216e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpSbc: opcode = is64Bit ? kX86Sbb64RR : kX86Sbb32RR; break;
217e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpLsl: opcode = is64Bit ? kX86Sal64RC : kX86Sal32RC; src2_must_be_cx = true; break;
218e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpLsr: opcode = is64Bit ? kX86Shr64RC : kX86Shr32RC; src2_must_be_cx = true; break;
219e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpAsr: opcode = is64Bit ? kX86Sar64RC : kX86Sar32RC; src2_must_be_cx = true; break;
220e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpMov: opcode = is64Bit ? kX86Mov64RR : kX86Mov32RR; break;
221e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpCmp: opcode = is64Bit ? kX86Cmp64RR : kX86Cmp32RR; break;
222e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpAdd: opcode = is64Bit ? kX86Add64RR : kX86Add32RR; break;
223e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpAdc: opcode = is64Bit ? kX86Adc64RR : kX86Adc32RR; break;
224e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpAnd: opcode = is64Bit ? kX86And64RR : kX86And32RR; break;
225e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpOr:  opcode = is64Bit ? kX86Or64RR : kX86Or32RR; break;
226e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpXor: opcode = is64Bit ? kX86Xor64RR : kX86Xor32RR; break;
227703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao      case kOp2Byte:
228091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        // TODO: there are several instances of this check.  A utility function perhaps?
229091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        // TODO: Similar to Arm's reg < 8 check.  Perhaps add attribute checks to RegStorage?
230703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        // Use shifts instead of a byte operand if the source can't be byte accessed.
231091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        if (r_src2.GetRegNum() >= rs_rX86_SP.GetRegNum()) {
232e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu          NewLIR2(is64Bit ? kX86Mov64RR : kX86Mov32RR, r_dest_src1.GetReg(), r_src2.GetReg());
233e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu          NewLIR2(is64Bit ? kX86Sal64RI : kX86Sal32RI, r_dest_src1.GetReg(), is64Bit ? 56 : 24);
234e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu          return NewLIR2(is64Bit ? kX86Sar64RI : kX86Sar32RI, r_dest_src1.GetReg(),
235e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu                         is64Bit ? 56 : 24);
236703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        } else {
237e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu          opcode = is64Bit ? kX86Bkpt : kX86Movsx8RR;
238703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        }
239703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        break;
240e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOp2Short: opcode = is64Bit ? kX86Bkpt : kX86Movsx16RR; break;
241e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOp2Char: opcode = is64Bit ? kX86Bkpt : kX86Movzx16RR; break;
242e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      case kOpMul: opcode = is64Bit ? kX86Bkpt : kX86Imul32RR; break;
243b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      default:
24452a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        LOG(FATAL) << "Bad case in OpRegReg " << op;
245b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        break;
246e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
247091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    CHECK(!src2_must_be_cx || r_src2.GetReg() == rs_rCX.GetReg());
2482700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg());
249e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
250e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
2512700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type) {
252091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(!r_base.IsFloat());
2532c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru  X86OpCode opcode = kX86Nop;
2542700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  int dest = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg();
2552c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru  switch (move_type) {
2562c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov8GP:
257091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(!r_dest.IsFloat());
2582c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86Mov8RM;
2592c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2602c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov16GP:
261091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(!r_dest.IsFloat());
2622c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86Mov16RM;
2632c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2642c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov32GP:
265091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(!r_dest.IsFloat());
2662c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86Mov32RM;
2672c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2682c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov32FP:
269091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_dest.IsFloat());
2702c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovssRM;
2712c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2722c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov64FP:
273091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_dest.IsFloat());
2742c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovsdRM;
2752c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2762c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovU128FP:
277091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_dest.IsFloat());
2782c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovupsRM;
2792c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2802c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovA128FP:
281091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_dest.IsFloat());
2822c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovapsRM;
2832c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2842c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovLo128FP:
285091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_dest.IsFloat());
2862c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovlpsRM;
2872c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2882c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovHi128FP:
289091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_dest.IsFloat());
2902c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovhpsRM;
2912c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2922c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov64GP:
2932c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovLo64FP:
2942c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovHi64FP:
2952c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    default:
2962c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      LOG(FATAL) << "Bad case in OpMovRegMem";
2972c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
2982c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru  }
2992c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru
3002700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  return NewLIR3(opcode, dest, r_base.GetReg(), offset);
3012c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru}
3022c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru
3032700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, MoveType move_type) {
304091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  DCHECK(!r_base.IsFloat());
3052700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  int src = r_src.IsPair() ? r_src.GetLowReg() : r_src.GetReg();
3062c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru
3072c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru  X86OpCode opcode = kX86Nop;
3082c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru  switch (move_type) {
3092c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov8GP:
310091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(!r_src.IsFloat());
3112c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86Mov8MR;
3122c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3132c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov16GP:
314091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(!r_src.IsFloat());
3152c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86Mov16MR;
3162c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3172c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov32GP:
318091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(!r_src.IsFloat());
3192c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86Mov32MR;
3202c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3212c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov32FP:
322091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_src.IsFloat());
3232c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovssMR;
3242c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3252c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov64FP:
326091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_src.IsFloat());
3272c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovsdMR;
3282c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3292c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovU128FP:
330091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_src.IsFloat());
3312c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovupsMR;
3322c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3332c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovA128FP:
334091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_src.IsFloat());
3352c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovapsMR;
3362c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3372c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovLo128FP:
338091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_src.IsFloat());
3392c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovlpsMR;
3402c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3412c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovHi128FP:
342091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      CHECK(r_src.IsFloat());
3432c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      opcode = kX86MovhpsMR;
3442c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3452c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMov64GP:
3462c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovLo64FP:
3472c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    case kMovHi64FP:
3482c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru    default:
3492c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      LOG(FATAL) << "Bad case in OpMovMemReg";
3502c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru      break;
3512c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru  }
3522c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru
3532700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  return NewLIR3(opcode, r_base.GetReg(), offset, src);
3542c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru}
3552c498d1f28e62e81fbdb477ff93ca7454e7493d7Razvan A Lupusoru
3562700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
357bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru  // The only conditional reg to reg operation supported is Cmov
358bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru  DCHECK_EQ(op, kOpCmov);
359c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  DCHECK_EQ(r_dest.Is64Bit(), r_src.Is64Bit());
360c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk  return NewLIR3(r_dest.Is64Bit() ? kX86Cmov64RRC : kX86Cmov32RRC, r_dest.GetReg(),
361c5e4ce116e4d44bfdf162f0c949e77772d7e0654nikolay serdjuk                 r_src.GetReg(), X86ConditionEncoding(cc));
362bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru}
363bd288c2c1206bc99fafebfb9120a83f13cf9723bRazvan A Lupusoru
3642700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegStorage r_base, int offset) {
365e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  bool is64Bit = r_dest.Is64Bit();
366b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Nop;
367b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (op) {
368b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      // X86 binary opcodes
369e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpSub: opcode = is64Bit ? kX86Sub64RM : kX86Sub32RM; break;
370e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpMov: opcode = is64Bit ? kX86Mov64RM : kX86Mov32RM; break;
371e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpCmp: opcode = is64Bit ? kX86Cmp64RM : kX86Cmp32RM; break;
372e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpAdd: opcode = is64Bit ? kX86Add64RM : kX86Add32RM; break;
373e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpAnd: opcode = is64Bit ? kX86And64RM : kX86And32RM; break;
374e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpOr:  opcode = is64Bit ? kX86Or64RM : kX86Or32RM; break;
375e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpXor: opcode = is64Bit ? kX86Xor64RM : kX86Xor32RM; break;
376b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOp2Byte: opcode = kX86Movsx8RM; break;
377b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOp2Short: opcode = kX86Movsx16RM; break;
378b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOp2Char: opcode = kX86Movzx16RM; break;
379b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpMul:
380b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
38152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in OpRegMem " << op;
382b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
383b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
3842700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  LIR *l = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), offset);
3858dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  if (mem_ref_type_ == ResourceMask::kDalvikReg) {
3868dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    DCHECK(r_base == rs_rX86_SP);
387feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell    AnnotateDalvikRegAccess(l, offset >> 2, true /* is_load */, false /* is_64bit */);
388feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  }
389feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  return l;
390feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell}
391feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell
392feb2b4e2d1c6538777bb80b60f3a247537b6221dMark MendellLIR* X86Mir2Lir::OpMemReg(OpKind op, RegLocation rl_dest, int r_value) {
393feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  DCHECK_NE(rl_dest.location, kLocPhysReg);
394feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  int displacement = SRegOffset(rl_dest.s_reg_low);
395e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  bool is64Bit = rl_dest.wide != 0;
396feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  X86OpCode opcode = kX86Nop;
397feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  switch (op) {
398e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpSub: opcode = is64Bit ? kX86Sub64MR : kX86Sub32MR; break;
399e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpMov: opcode = is64Bit ? kX86Mov64MR : kX86Mov32MR; break;
400e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpCmp: opcode = is64Bit ? kX86Cmp64MR : kX86Cmp32MR; break;
401e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpAdd: opcode = is64Bit ? kX86Add64MR : kX86Add32MR; break;
402e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpAnd: opcode = is64Bit ? kX86And64MR : kX86And32MR; break;
403e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpOr:  opcode = is64Bit ? kX86Or64MR : kX86Or32MR; break;
404e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpXor: opcode = is64Bit ? kX86Xor64MR : kX86Xor32MR; break;
405e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpLsl: opcode = is64Bit ? kX86Sal64MC : kX86Sal32MC; break;
406e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpLsr: opcode = is64Bit ? kX86Shr64MC : kX86Shr32MC; break;
407e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpAsr: opcode = is64Bit ? kX86Sar64MC : kX86Sar32MC; break;
408feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell    default:
409feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell      LOG(FATAL) << "Bad case in OpMemReg " << op;
410feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell      break;
411feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  }
412091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LIR *l = NewLIR3(opcode, rs_rX86_SP.GetReg(), displacement, r_value);
4138dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  if (mem_ref_type_ == ResourceMask::kDalvikReg) {
4148dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, is64Bit /* is_64bit */);
4158dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    AnnotateDalvikRegAccess(l, displacement >> 2, false /* is_load */, is64Bit /* is_64bit */);
4168dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  }
417feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  return l;
418feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell}
419feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell
4202700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegMem(OpKind op, RegStorage r_dest, RegLocation rl_value) {
421feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  DCHECK_NE(rl_value.location, kLocPhysReg);
422e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  bool is64Bit = r_dest.Is64Bit();
423feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  int displacement = SRegOffset(rl_value.s_reg_low);
424feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  X86OpCode opcode = kX86Nop;
425feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  switch (op) {
426e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpSub: opcode = is64Bit ? kX86Sub64RM : kX86Sub32RM; break;
427e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpMov: opcode = is64Bit ? kX86Mov64RM : kX86Mov32RM; break;
428e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpCmp: opcode = is64Bit ? kX86Cmp64RM : kX86Cmp32RM; break;
429e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpAdd: opcode = is64Bit ? kX86Add64RM : kX86Add32RM; break;
430e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpAnd: opcode = is64Bit ? kX86And64RM : kX86And32RM; break;
431e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpOr:  opcode = is64Bit ? kX86Or64RM : kX86Or32RM; break;
432e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpXor: opcode = is64Bit ? kX86Xor64RM : kX86Xor32RM; break;
433e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu    case kOpMul: opcode = is64Bit ? kX86Bkpt : kX86Imul32RM; break;
434feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell    default:
435feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell      LOG(FATAL) << "Bad case in OpRegMem " << op;
436feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell      break;
437feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  }
438091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  LIR *l = NewLIR3(opcode, r_dest.GetReg(), rs_rX86_SP.GetReg(), displacement);
4398dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  if (mem_ref_type_ == ResourceMask::kDalvikReg) {
4408dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    AnnotateDalvikRegAccess(l, displacement >> 2, true /* is_load */, is64Bit /* is_64bit */);
4418dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  }
442feb2b4e2d1c6538777bb80b60f3a247537b6221dMark Mendell  return l;
443b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers}
444e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
4452700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1,
4462700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee                             RegStorage r_src2) {
447e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  bool is64Bit = r_dest.Is64Bit();
448fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest != r_src1 && r_dest != r_src2) {
4497934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    if (op == kOpAdd) {  // lea special case, except can't encode rbp as base
450fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (r_src1 == r_src2) {
4511fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(r_dest, r_src1);
4521fd3346740dfb7f47be9922312b68a4227fada96buzbee        return OpRegImm(kOpLsl, r_dest, 1);
4532700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      } else if (r_src1 != rs_rBP) {
454e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        return NewLIR5(is64Bit ? kX86Lea64RA : kX86Lea32RA, r_dest.GetReg(),
455e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu                       r_src1.GetReg() /* base */, r_src2.GetReg() /* index */,
456e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu                       0 /* scale */, 0 /* disp */);
457b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      } else {
458e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        return NewLIR5(is64Bit ? kX86Lea64RA : kX86Lea32RA, r_dest.GetReg(),
459e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu                       r_src2.GetReg() /* base */, r_src1.GetReg() /* index */,
460e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu                       0 /* scale */, 0 /* disp */);
461b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
462b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    } else {
4631fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(r_dest, r_src1);
4641fd3346740dfb7f47be9922312b68a4227fada96buzbee      return OpRegReg(op, r_dest, r_src2);
465e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
466fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  } else if (r_dest == r_src1) {
4671fd3346740dfb7f47be9922312b68a4227fada96buzbee    return OpRegReg(op, r_dest, r_src2);
468fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  } else {  // r_dest == r_src2
469b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    switch (op) {
470b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSub:  // non-commutative
4711fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpReg(kOpNeg, r_dest);
472b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        op = kOpAdd;
473b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        break;
474b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSbc:
475b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
4762700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        RegStorage t_reg = AllocTemp();
4771fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(t_reg, r_src1);
4781fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegReg(op, t_reg, r_src2);
4797a11ab09f93f54b1c07c0bf38dd65ed322e86bc6buzbee        LIR* res = OpRegCopyNoInsert(r_dest, t_reg);
4807a11ab09f93f54b1c07c0bf38dd65ed322e86bc6buzbee        AppendLIR(res);
4811fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
482b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        return res;
483b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
484b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdd:  // commutative
485b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpOr:
486b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdc:
487b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAnd:
488b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpXor:
489b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        break;
490b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      default:
49152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        LOG(FATAL) << "Bad case in OpRegRegReg " << op;
492e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
4931fd3346740dfb7f47be9922312b68a4227fada96buzbee    return OpRegReg(op, r_dest, r_src1);
494b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
495e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
496e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
4972700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src, int value) {
498dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  if (op == kOpMul && !cu_->target64) {
499b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
5002700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    return NewLIR3(opcode, r_dest.GetReg(), r_src.GetReg(), value);
501dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina  } else if (op == kOpAnd && !cu_->target64) {
502091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee    if (value == 0xFF && r_src.Low4()) {
5032700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      return NewLIR2(kX86Movzx8RR, r_dest.GetReg(), r_src.GetReg());
504b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else if (value == 0xFFFF) {
5052700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      return NewLIR2(kX86Movzx16RR, r_dest.GetReg(), r_src.GetReg());
506b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
507b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
508fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest != r_src) {
5097934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    if (false && op == kOpLsl && value >= 0 && value <= 3) {  // lea shift special case
5107caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers      // TODO: fix bug in LEA encoding when disp == 0
5112700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      return NewLIR5(kX86Lea32RA, r_dest.GetReg(),  r5sib_no_base /* base */,
5122700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee                     r_src.GetReg() /* index */, value /* scale */, 0 /* disp */);
5137934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    } else if (op == kOpAdd) {  // lea add special case
5147e399fd3a99ba9c9dbfafdf14f75dd318fa7d454Chao-ying Fu      return NewLIR5(r_dest.Is64Bit() ? kX86Lea64RA : kX86Lea32RA, r_dest.GetReg(),
515e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu                     r_src.GetReg() /* base */, rs_rX86_SP.GetReg()/*r4sib_no_index*/ /* index */,
516e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu                     0 /* scale */, value /* disp */);
517e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
5181fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegCopy(r_dest, r_src);
519b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
5201fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpRegImm(op, r_dest, value);
521e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
522e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
523dd7624d2b9e599d57762d12031b10b89defc9807Ian RogersLIR* X86Mir2Lir::OpThreadMem(OpKind op, ThreadOffset<4> thread_offset) {
5242f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  DCHECK_EQ(kX86, cu_->instruction_set);
5252f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  X86OpCode opcode = kX86Bkpt;
5262f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  switch (op) {
5272f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe    case kOpBlx: opcode = kX86CallT;  break;
5282f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe    case kOpBx: opcode = kX86JmpT;  break;
5292f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe    default:
5302f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe      LOG(FATAL) << "Bad opcode: " << op;
5312f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe      break;
5322f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  }
5332f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  return NewLIR1(opcode, thread_offset.Int32Value());
5342f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe}
5352f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe
5362f244e9faccfcca68af3c5484c397a01a1c3a342Andreas GampeLIR* X86Mir2Lir::OpThreadMem(OpKind op, ThreadOffset<8> thread_offset) {
5372f244e9faccfcca68af3c5484c397a01a1c3a342Andreas Gampe  DCHECK_EQ(kX86_64, cu_->instruction_set);
5386cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  X86OpCode opcode = kX86Bkpt;
5396cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  switch (op) {
5406cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    case kOpBlx: opcode = kX86CallT;  break;
54160d7a65f7fb60f502160a2e479e86014c7787553Brian Carlstrom    case kOpBx: opcode = kX86JmpT;  break;
5426cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    default:
5436cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      LOG(FATAL) << "Bad opcode: " << op;
5446cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      break;
5456cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
546468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return NewLIR1(opcode, thread_offset.Int32Value());
5476cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers}
5486cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers
5492700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
5506cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  X86OpCode opcode = kX86Bkpt;
5516cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  switch (op) {
5526cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    case kOpBlx: opcode = kX86CallM;  break;
5536cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    default:
5546cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      LOG(FATAL) << "Bad opcode: " << op;
5556cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      break;
5566cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
5572700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  return NewLIR2(opcode, r_base.GetReg(), disp);
5586cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers}
5596cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers
5602700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
5614ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int32_t val_lo = Low32Bits(value);
5624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int32_t val_hi = High32Bits(value);
5632700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    int32_t low_reg_val = r_dest.IsPair() ? r_dest.GetLowReg() : r_dest.GetReg();
564e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    LIR *res;
565e87f9b5185379c8cf8392d65a63e7bf7e51b97e7Mark Mendell    bool is_fp = r_dest.IsFloat();
5662700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    // TODO: clean this up once we fully recognize 64-bit storage containers.
5672700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee    if (is_fp) {
5680e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov      DCHECK(r_dest.IsDouble());
5694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (value == 0) {
5702700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee        return NewLIR2(kX86XorpsRR, low_reg_val, low_reg_val);
57167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      } else if (base_of_code_ != nullptr) {
57267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        // We will load the value from the literal area.
57367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi);
57467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        if (data_target == NULL) {
57567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell          data_target = AddWideData(&literal_list_, val_lo, val_hi);
57667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        }
57767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
57867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        // Address the start of the method
57967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        RegLocation rl_method = mir_graph_->GetRegLocation(base_of_code_->s_reg_low);
580e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        if (rl_method.wide) {
581e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu          rl_method = LoadValueWide(rl_method, kCoreReg);
582e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        } else {
583e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu          rl_method = LoadValue(rl_method, kCoreReg);
584e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        }
58567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
58667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        // Load the proper value from the literal area.
58767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        // We don't know the proper offset for the value, so pick one that will force
58867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        // 4 byte offset.  We will fix this up in the assembler later to have the right
58967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        // value.
5908dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko        ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
5910c52451e9be14a6bff9ffefce89ff1d60691af60Mark Mendell        res = LoadBaseDisp(rl_method.reg, 256 /* bogus */, RegStorage::FloatSolo64(low_reg_val),
5923c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe                           kDouble, kNotVolatile);
59367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        res->target = data_target;
59467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell        res->flags.fixup = kFixupLoad;
59554659e3a2c83d3949957a10436e55e525a430a15Alexei Zavjalov        Clobber(rl_method.reg);
59655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell        store_method_addr_used_ = true;
597b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers      } else {
5980e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov        if (r_dest.IsPair()) {
5990e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov          if (val_lo == 0) {
6000e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov            res = NewLIR2(kX86XorpsRR, low_reg_val, low_reg_val);
6010e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov          } else {
6020e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov            res = LoadConstantNoClobber(RegStorage::FloatSolo32(low_reg_val), val_lo);
6030e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov          }
6040e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov          if (val_hi != 0) {
6050e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov            RegStorage r_dest_hi = AllocTempDouble();
6060e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov            LoadConstantNoClobber(r_dest_hi, val_hi);
6070e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov            NewLIR2(kX86PunpckldqRR, low_reg_val, r_dest_hi.GetReg());
6080e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov            FreeTemp(r_dest_hi);
6090e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov          }
610b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers        } else {
6110e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov          RegStorage r_temp = AllocTypedTempWide(false, kCoreReg);
6120e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov          res = LoadConstantWide(r_temp, value);
6130e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov          OpRegCopyWide(r_dest, r_temp);
6140e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov          FreeTemp(r_temp);
615b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers        }
616b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers      }
617b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else {
618e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      if (r_dest.IsPair()) {
619e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        res = LoadConstantNoClobber(r_dest.GetLow(), val_lo);
620e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        LoadConstantNoClobber(r_dest.GetHigh(), val_hi);
621e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      } else {
6225192cbb12856b12620dc346758605baaa1469cedYixin Shou        if (value == 0) {
6231c55703526827b5fc63f5d4b8477f36574649342Serguei Katkov          res = NewLIR2(kX86Xor64RR, r_dest.GetReg(), r_dest.GetReg());
6245192cbb12856b12620dc346758605baaa1469cedYixin Shou        } else if (value >= INT_MIN && value <= INT_MAX) {
6255192cbb12856b12620dc346758605baaa1469cedYixin Shou          res = NewLIR2(kX86Mov64RI32, r_dest.GetReg(), val_lo);
6265192cbb12856b12620dc346758605baaa1469cedYixin Shou        } else {
6275192cbb12856b12620dc346758605baaa1469cedYixin Shou          res = NewLIR3(kX86Mov64RI64, r_dest.GetReg(), val_hi, val_lo);
628e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        }
629e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      }
630b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
631e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    return res;
632e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
633e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
6342700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
6353bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko                                     int displacement, RegStorage r_dest, OpSize size) {
636b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR *load = NULL;
637b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR *load2 = NULL;
6382700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  bool is_array = r_index.Valid();
639091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool pair = r_dest.IsPair();
640091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool is64bit = ((size == k64) || (size == kDouble));
641b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Nop;
642b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (size) {
643695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case k64:
644b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kDouble:
645091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_dest.IsFloat()) {
646fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovsdRA : kX86MovsdRM;
647e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      } else if (!pair) {
648e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        opcode = is_array ? kX86Mov64RA  : kX86Mov64RM;
649b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      } else {
650fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86Mov32RA  : kX86Mov32RM;
651b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
652b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      // TODO: double store is to unaligned address
653b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
654b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
6559ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    case kWord:
656dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina      if (cu_->target64) {
6579ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        opcode = is_array ? kX86Mov64RA  : kX86Mov64RM;
6589ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        CHECK_EQ(is_array, false);
6599ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        CHECK_EQ(r_dest.IsFloat(), false);
6609ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        break;
6619ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      }  // else fall-through to k32 case
662695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case k32:
663b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSingle:
664695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case kReference:  // TODO: update for reference decompression on 64-bit targets.
665fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
666091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_dest.IsFloat()) {
667fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovssRA : kX86MovssRM;
668091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        DCHECK(r_dest.IsFloat());
669b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
670b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
671b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
672b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedHalf:
673fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM;
674b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x1), 0);
675b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
676b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedHalf:
677fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM;
678b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x1), 0);
679b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
680b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedByte:
681fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM;
682b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
683b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedByte:
684fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM;
685b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
686b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
68752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
688b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
689b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
690fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (!is_array) {
691b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (!pair) {
6922700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), displacement + LOWORD_OFFSET);
693e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    } else {
694091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      DCHECK(!r_dest.IsFloat());  // Make sure we're not still using a pair here.
695091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_base == r_dest.GetLow()) {
69669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison        load = NewLIR3(opcode, r_dest.GetHighReg(), r_base.GetReg(),
697fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
69869dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison        load2 = NewLIR3(opcode, r_dest.GetLowReg(), r_base.GetReg(), displacement + LOWORD_OFFSET);
699fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      } else {
700091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        load = NewLIR3(opcode, r_dest.GetLowReg(), r_base.GetReg(), displacement + LOWORD_OFFSET);
701091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        load2 = NewLIR3(opcode, r_dest.GetHighReg(), r_base.GetReg(),
702fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
703fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      }
704e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
7058dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mem_ref_type_ == ResourceMask::kDalvikReg) {
7068dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko      DCHECK(r_base == rs_rX86_SP);
7071fd3346740dfb7f47be9922312b68a4227fada96buzbee      AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
70802031b185b4653e6c72e21f7a51238b903f6d638buzbee                              true /* is_load */, is64bit);
709f7d9ad39541dd09030e26d54d3b73a076f90cc74Ian Rogers      if (pair) {
7101fd3346740dfb7f47be9922312b68a4227fada96buzbee        AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
711fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                true /* is_load */, is64bit);
712b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
713e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
714b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
715b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (!pair) {
7162700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      load = NewLIR5(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
717a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                     displacement + LOWORD_OFFSET);
718b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    } else {
719091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      DCHECK(!r_dest.IsFloat());  // Make sure we're not still using a pair here.
720091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_base == r_dest.GetLow()) {
721091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        if (r_dest.GetHigh() == r_index) {
722ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell          // We can't use either register for the first load.
7232700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee          RegStorage temp = AllocTemp();
72469dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison          load = NewLIR5(opcode, temp.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
725ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell                          displacement + HIWORD_OFFSET);
72669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison          load2 = NewLIR5(opcode, r_dest.GetLowReg(), r_base.GetReg(), r_index.GetReg(), scale,
727ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell                         displacement + LOWORD_OFFSET);
728091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee          OpRegCopy(r_dest.GetHigh(), temp);
729ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell          FreeTemp(temp);
730ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell        } else {
73169dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison          load = NewLIR5(opcode, r_dest.GetHighReg(), r_base.GetReg(), r_index.GetReg(), scale,
732ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell                          displacement + HIWORD_OFFSET);
73369dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison          load2 = NewLIR5(opcode, r_dest.GetLowReg(), r_base.GetReg(), r_index.GetReg(), scale,
734ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell                         displacement + LOWORD_OFFSET);
735ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell        }
736fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      } else {
737091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        if (r_dest.GetLow() == r_index) {
738ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell          // We can't use either register for the first load.
7392700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee          RegStorage temp = AllocTemp();
7402700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee          load = NewLIR5(opcode, temp.GetReg(), r_base.GetReg(), r_index.GetReg(), scale,
741ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell                         displacement + LOWORD_OFFSET);
742091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee          load2 = NewLIR5(opcode, r_dest.GetHighReg(), r_base.GetReg(), r_index.GetReg(), scale,
743ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell                          displacement + HIWORD_OFFSET);
744091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee          OpRegCopy(r_dest.GetLow(), temp);
745ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell          FreeTemp(temp);
746ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell        } else {
747091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee          load = NewLIR5(opcode, r_dest.GetLowReg(), r_base.GetReg(), r_index.GetReg(), scale,
748ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell                         displacement + LOWORD_OFFSET);
749091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee          load2 = NewLIR5(opcode, r_dest.GetHighReg(), r_base.GetReg(), r_index.GetReg(), scale,
750ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell                          displacement + HIWORD_OFFSET);
751ae427c3ba8d05599919c16f0c7c8983919cf7da3Mark Mendell        }
752fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      }
753b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    }
754b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
755b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
75669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison  // Always return first load generated as this might cause a fault if base is nullptr.
757b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return load;
758e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
759e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
7605772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao/* Load value from base + scaled index. */
7612700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
7622700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee                                 int scale, OpSize size) {
7633bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko  return LoadBaseIndexedDisp(r_base, r_index, scale, 0, r_dest, size);
7645772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao}
7655772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao
7663c12c512faf6837844d5465b23b9410889e5eb11Andreas GampeLIR* X86Mir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
7673c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe                              OpSize size, VolatileKind is_volatile) {
768674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  // LoadBaseDisp() will emit correct insn for atomic load on x86
769674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  // assuming r_dest is correctly prepared using RegClassForFieldLoadStore().
770674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko
7713c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  LIR* load = LoadBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_dest,
7723c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe                                  size);
7733c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
7743c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  if (UNLIKELY(is_volatile == kVolatile)) {
77548f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    GenMemBarrier(kLoadAny);  // Only a scheduling barrier.
7763c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  }
7773c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
7783c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  return load;
779e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
780e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
7812700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::StoreBaseIndexedDisp(RegStorage r_base, RegStorage r_index, int scale,
7823bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko                                      int displacement, RegStorage r_src, OpSize size) {
783b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR *store = NULL;
784e296248a124ed8287b38a9225463696c18d84cd6jeffhao  LIR *store2 = NULL;
7852700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee  bool is_array = r_index.Valid();
786091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool pair = r_src.IsPair();
787091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee  bool is64bit = (size == k64) || (size == kDouble);
788b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  X86OpCode opcode = kX86Nop;
789b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (size) {
790695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case k64:
791b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kDouble:
792091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_src.IsFloat()) {
793fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
794e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu      } else if (!pair) {
795e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        opcode = is_array ? kX86Mov64AR  : kX86Mov64MR;
796b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      } else {
797e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu        opcode = is_array ? kX86Mov32AR  : kX86Mov32MR;
798b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
799b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      // TODO: double store is to unaligned address
800b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
801b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
8029ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko    case kWord:
803dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina      if (cu_->target64) {
8049ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        opcode = is_array ? kX86Mov64AR  : kX86Mov64MR;
8059ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        CHECK_EQ(is_array, false);
8069ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        CHECK_EQ(r_src.IsFloat(), false);
8079ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko        break;
8089ee801f5308aa3c62ae3bedae2658612762ffb91Dmitry Petrochenko      }  // else fall-through to k32 case
809695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case k32:
810b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSingle:
811695d13a82d6dd801aaa57a22a9d4b3f6db0d0fdbbuzbee    case kReference:
812fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
813091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      if (r_src.IsFloat()) {
814fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovssAR : kX86MovssMR;
815091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee        DCHECK(r_src.IsSingle());
816b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
817b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
818b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
819b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedHalf:
820b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedHalf:
821fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov16AR : kX86Mov16MR;
822b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x1), 0);
823b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
824b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedByte:
825b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedByte:
826fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov8AR : kX86Mov8MR;
827b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
828b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
82900e1ec6581b5b7b46ca4c314c2854e9caa647dd2Bill Buzbee      LOG(FATAL) << "Bad case in StoreBaseIndexedDispBody";
830b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
831b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
832fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (!is_array) {
833b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    if (!pair) {
8342700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      store = NewLIR3(opcode, r_base.GetReg(), displacement + LOWORD_OFFSET, r_src.GetReg());
835b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else {
836091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      DCHECK(!r_src.IsFloat());  // Make sure we're not still using a pair here.
837091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      store = NewLIR3(opcode, r_base.GetReg(), displacement + LOWORD_OFFSET, r_src.GetLowReg());
838091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      store2 = NewLIR3(opcode, r_base.GetReg(), displacement + HIWORD_OFFSET, r_src.GetHighReg());
839e296248a124ed8287b38a9225463696c18d84cd6jeffhao    }
8408dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko    if (mem_ref_type_ == ResourceMask::kDalvikReg) {
8418dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko      DCHECK(r_base == rs_rX86_SP);
8421fd3346740dfb7f47be9922312b68a4227fada96buzbee      AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
84302031b185b4653e6c72e21f7a51238b903f6d638buzbee                              false /* is_load */, is64bit);
844e296248a124ed8287b38a9225463696c18d84cd6jeffhao      if (pair) {
8451fd3346740dfb7f47be9922312b68a4227fada96buzbee        AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
846fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                false /* is_load */, is64bit);
847e296248a124ed8287b38a9225463696c18d84cd6jeffhao      }
848b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
849b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
850b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    if (!pair) {
8512700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      store = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale,
8522700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee                      displacement + LOWORD_OFFSET, r_src.GetReg());
853b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else {
854091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee      DCHECK(!r_src.IsFloat());  // Make sure we're not still using a pair here.
8552700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      store = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale,
856091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee                      displacement + LOWORD_OFFSET, r_src.GetLowReg());
8572700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbee      store2 = NewLIR5(opcode, r_base.GetReg(), r_index.GetReg(), scale,
858091cc408e9dc87e60fb64c61e186bea568fc3d3abuzbee                       displacement + HIWORD_OFFSET, r_src.GetHighReg());
859e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
860b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
861b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  return store;
862e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
863e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
864c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers/* store value base base + scaled index. */
8652700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
8663c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe                                  int scale, OpSize size) {
8673bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko  return StoreBaseIndexedDisp(r_base, r_index, scale, 0, r_src, size);
868c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers}
869c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers
8703c12c512faf6837844d5465b23b9410889e5eb11Andreas GampeLIR* X86Mir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, OpSize size,
8713c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe                               VolatileKind is_volatile) {
8723c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  if (UNLIKELY(is_volatile == kVolatile)) {
87348f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    GenMemBarrier(kAnyStore);  // Only a scheduling barrier.
8743c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  }
8753c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
876674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  // StoreBaseDisp() will emit correct insn for atomic store on x86
877674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  // assuming r_dest is correctly prepared using RegClassForFieldLoadStore().
87837f05ef45e0393de812d51261dc293240c17294dFred Shih  // x86 only allows registers EAX-EDX to be used as byte registers, if the input src is not
87937f05ef45e0393de812d51261dc293240c17294dFred Shih  // valid, allocate a temp.
88037f05ef45e0393de812d51261dc293240c17294dFred Shih  bool allocated_temp = false;
88137f05ef45e0393de812d51261dc293240c17294dFred Shih  if (size == kUnsignedByte || size == kSignedByte) {
88237f05ef45e0393de812d51261dc293240c17294dFred Shih    if (!cu_->target64 && !r_src.Low4()) {
88337f05ef45e0393de812d51261dc293240c17294dFred Shih      RegStorage r_input = r_src;
88437f05ef45e0393de812d51261dc293240c17294dFred Shih      r_src = AllocateByteRegister();
88537f05ef45e0393de812d51261dc293240c17294dFred Shih      OpRegCopy(r_src, r_input);
88637f05ef45e0393de812d51261dc293240c17294dFred Shih      allocated_temp = true;
88737f05ef45e0393de812d51261dc293240c17294dFred Shih    }
88837f05ef45e0393de812d51261dc293240c17294dFred Shih  }
889674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko
8903c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  LIR* store = StoreBaseIndexedDisp(r_base, RegStorage::InvalidReg(), 0, displacement, r_src, size);
8913c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
8923c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  if (UNLIKELY(is_volatile == kVolatile)) {
89348f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    // A volatile load might follow the volatile store so insert a StoreLoad barrier.
89448f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    // This does require a fence, even on x86.
89548f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    GenMemBarrier(kAnyAny);
8963c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  }
8973c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
89837f05ef45e0393de812d51261dc293240c17294dFred Shih  if (allocated_temp) {
89937f05ef45e0393de812d51261dc293240c17294dFred Shih    FreeTemp(r_src);
90037f05ef45e0393de812d51261dc293240c17294dFred Shih  }
90137f05ef45e0393de812d51261dc293240c17294dFred Shih
9023c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  return store;
903e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
904e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
9052700f7e1edbcd2518f4978e4cd0e05a4149f91b6buzbeeLIR* X86Mir2Lir::OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg,
90669dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison                                   int offset, int check_value, LIR* target, LIR** compare) {
90769dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison    LIR* inst = NewLIR3(IS_SIMM8(check_value) ? kX86Cmp32MI8 : kX86Cmp32MI, base_reg.GetReg(),
90869dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison            offset, check_value);
90969dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison    if (compare != nullptr) {
91069dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison        *compare = inst;
91169dfe51b684dd9d510dbcb63295fe180f998efdeDave Allison    }
912766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell    LIR* branch = OpCondBranch(cond, target);
913766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell    return branch;
914766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell}
915766e9295d2c34cd1846d81610c9045b5d5093dddMark Mendell
91667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeMIR() {
91767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // Assume we don't need a pointer to the base of the code.
91867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  cu_->NewTimingSplit("X86 MIR Analysis");
91967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  store_method_addr_ = false;
92067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
92167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // Walk the MIR looking for interesting items.
92267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  PreOrderDfsIterator iter(mir_graph_);
92367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  BasicBlock* curr_bb = iter.Next();
92467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  while (curr_bb != NULL) {
92567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    AnalyzeBB(curr_bb);
92667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    curr_bb = iter.Next();
92767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
92867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
92967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // Did we need a pointer to the method code?
93067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  if (store_method_addr_) {
931dd64450b37776f68b9bfc47f8d9a88bc72c95727Elena Sayapina    base_of_code_ = mir_graph_->GetNewCompilerTemp(kCompilerTempVR, cu_->target64 == true);
93267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  } else {
93367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    base_of_code_ = nullptr;
93467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
93567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell}
93667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
93767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeBB(BasicBlock * bb) {
93867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  if (bb->block_type == kDead) {
93967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    // Ignore dead blocks
94067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    return;
94167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
94267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
94367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  for (MIR *mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
94467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    int opcode = mir->dalvikInsn.opcode;
9452ab40eb3c23559205ac7b9b039bd749458e8a761Jean Christophe Beyler    if (MIR::DecodedInstruction::IsPseudoMirOp(opcode)) {
94667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      AnalyzeExtendedMIR(opcode, bb, mir);
94767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    } else {
94867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      AnalyzeMIR(opcode, bb, mir);
94967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    }
95067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
95167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell}
95267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
95367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
95467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeExtendedMIR(int opcode, BasicBlock * bb, MIR *mir) {
95567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  switch (opcode) {
95667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    // Instructions referencing doubles.
95767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case kMirOpFusedCmplDouble:
95867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case kMirOpFusedCmpgDouble:
95967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      AnalyzeFPInstruction(opcode, bb, mir);
96067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      break;
961d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell    case kMirOpConstVector:
962d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      store_method_addr_ = true;
963d65c51a556e6649db4e18bd083c8fec37607a442Mark Mendell      break;
96467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    default:
96567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      // Ignore the rest.
96667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      break;
96767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
96867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell}
96967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
97067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir) {
97167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // Looking for
97267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // - Do we need a pointer to the code (used for packed switches and double lits)?
97367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
97467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  switch (opcode) {
97567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    // Instructions referencing doubles.
97667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::CMPL_DOUBLE:
97767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::CMPG_DOUBLE:
97867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::NEG_DOUBLE:
97967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::ADD_DOUBLE:
98067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::SUB_DOUBLE:
98167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::MUL_DOUBLE:
98267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::DIV_DOUBLE:
98367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::REM_DOUBLE:
98467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::ADD_DOUBLE_2ADDR:
98567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::SUB_DOUBLE_2ADDR:
98667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::MUL_DOUBLE_2ADDR:
98767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::DIV_DOUBLE_2ADDR:
98867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::REM_DOUBLE_2ADDR:
98967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      AnalyzeFPInstruction(opcode, bb, mir);
99067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      break;
99155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell
99267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    // Packed switches and array fills need a pointer to the base of the method.
99367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::FILL_ARRAY_DATA:
99467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    case Instruction::PACKED_SWITCH:
99567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      store_method_addr_ = true;
99667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      break;
9977071c8d5885175a746723a3b38a347855965be08Yixin Shou    case Instruction::INVOKE_STATIC:
9987071c8d5885175a746723a3b38a347855965be08Yixin Shou      AnalyzeInvokeStatic(opcode, bb, mir);
9997071c8d5885175a746723a3b38a347855965be08Yixin Shou      break;
100067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    default:
100167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      // Other instructions are not interesting yet.
100267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      break;
100367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
100467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell}
100567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
100667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeFPInstruction(int opcode, BasicBlock * bb, MIR *mir) {
100767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  // Look at all the uses, and see if they are double constants.
1008cc794c3dc5b45601da23fb0d7bc16f9b4ef04065Jean Christophe Beyler  uint64_t attrs = MIRGraph::GetDataFlowAttributes(static_cast<Instruction::Code>(opcode));
100967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  int next_sreg = 0;
101067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  if (attrs & DF_UA) {
101167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    if (attrs & DF_A_WIDE) {
101267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      AnalyzeDoubleUse(mir_graph_->GetSrcWide(mir, next_sreg));
101367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      next_sreg += 2;
101467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    } else {
101567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      next_sreg++;
101667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    }
101767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
101867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  if (attrs & DF_UB) {
101967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    if (attrs & DF_B_WIDE) {
102067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      AnalyzeDoubleUse(mir_graph_->GetSrcWide(mir, next_sreg));
102167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      next_sreg += 2;
102267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    } else {
102367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      next_sreg++;
102467c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    }
102567c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
102667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  if (attrs & DF_UC) {
102767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    if (attrs & DF_C_WIDE) {
102867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell      AnalyzeDoubleUse(mir_graph_->GetSrcWide(mir, next_sreg));
102967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    }
103067c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
103167c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell}
103267c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
103367c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendellvoid X86Mir2Lir::AnalyzeDoubleUse(RegLocation use) {
10340e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov  // If this is a double literal, we will want it in the literal pool on 32b platforms.
10350e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov  if (use.is_const && !cu_->target64) {
103667c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell    store_method_addr_ = true;
103767c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell  }
103867c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell}
103967c39c4aefca23cb136157b889c09ee200b3dec6Mark Mendell
104030adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbeeRegLocation X86Mir2Lir::UpdateLocTyped(RegLocation loc, int reg_class) {
104130adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee  loc = UpdateLoc(loc);
104230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee  if ((loc.location == kLocPhysReg) && (loc.fp != loc.reg.IsFloat())) {
104330adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee    if (GetRegInfo(loc.reg)->IsTemp()) {
104430adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      Clobber(loc.reg);
104530adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      FreeTemp(loc.reg);
104630adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      loc.reg = RegStorage::InvalidReg();
104730adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      loc.location = kLocDalvikFrame;
104830adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee    }
104930adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee  }
1050e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  DCHECK(CheckCorePoolSanity());
105130adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee  return loc;
105230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee}
105330adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee
105430adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbeeRegLocation X86Mir2Lir::UpdateLocWideTyped(RegLocation loc, int reg_class) {
105530adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee  loc = UpdateLocWide(loc);
105630adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee  if ((loc.location == kLocPhysReg) && (loc.fp != loc.reg.IsFloat())) {
105730adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee    if (GetRegInfo(loc.reg)->IsTemp()) {
105830adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      Clobber(loc.reg);
105930adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      FreeTemp(loc.reg);
106030adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      loc.reg = RegStorage::InvalidReg();
106130adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee      loc.location = kLocDalvikFrame;
106230adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee    }
106330adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee  }
1064e0ccdc0dd166136cd43e5f54201179a4496d33e8Chao-ying Fu  DCHECK(CheckCorePoolSanity());
106530adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee  return loc;
106630adc7383a74eb3cb6db3bf42cea3a5595055ce1buzbee}
10677071c8d5885175a746723a3b38a347855965be08Yixin Shou
10687071c8d5885175a746723a3b38a347855965be08Yixin Shouvoid X86Mir2Lir::AnalyzeInvokeStatic(int opcode, BasicBlock * bb, MIR *mir) {
10690e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov  // For now this is only actual for x86-32.
10700e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov  if (cu_->target64) {
10710e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov    return;
10720e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov  }
10730e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov
10747071c8d5885175a746723a3b38a347855965be08Yixin Shou  uint32_t index = mir->dalvikInsn.vB;
10757071c8d5885175a746723a3b38a347855965be08Yixin Shou  if (!(mir->optimization_flags & MIR_INLINED)) {
10767071c8d5885175a746723a3b38a347855965be08Yixin Shou    DCHECK(cu_->compiler_driver->GetMethodInlinerMap() != nullptr);
10770e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov    DexFileMethodInliner* method_inliner =
10780e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov      cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(cu_->dex_file);
10797071c8d5885175a746723a3b38a347855965be08Yixin Shou    InlineMethod method;
10800e63ce19bdb04d31180d7eb4a8bf6605333ade5aAlexei Zavjalov    if (method_inliner->IsIntrinsic(index, &method)) {
10817071c8d5885175a746723a3b38a347855965be08Yixin Shou      switch (method.opcode) {
10827071c8d5885175a746723a3b38a347855965be08Yixin Shou        case kIntrinsicAbsDouble:
10831222c96fafe98061cfc57d3bd115f46edb64e624Alexei Zavjalov        case kIntrinsicMinMaxDouble:
10847071c8d5885175a746723a3b38a347855965be08Yixin Shou          store_method_addr_ = true;
10857071c8d5885175a746723a3b38a347855965be08Yixin Shou          break;
10867071c8d5885175a746723a3b38a347855965be08Yixin Shou        default:
10877071c8d5885175a746723a3b38a347855965be08Yixin Shou          break;
10887071c8d5885175a746723a3b38a347855965be08Yixin Shou      }
10897071c8d5885175a746723a3b38a347855965be08Yixin Shou    }
10907071c8d5885175a746723a3b38a347855965be08Yixin Shou  }
10917071c8d5885175a746723a3b38a347855965be08Yixin Shou}
1092984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe
1093984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas GampeLIR* X86Mir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, QuickEntrypointEnum trampoline) {
1094984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe  if (cu_->target64) {
1095984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe    return OpThreadMem(op, GetThreadOffset<8>(trampoline));
1096984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe  } else {
1097984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe    return OpThreadMem(op, GetThreadOffset<4>(trampoline));
1098984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe  }
1099984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe}
1100984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe
1101e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}  // namespace art
1102