utility_x86.cc revision 02031b185b4653e6c72e21f7a51238b903f6d638
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
171bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "x86_lir.h"
1802031b185b4653e6c72e21f7a51238b903f6d638buzbee#include "codegen_x86.h"
191bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "../codegen_util.h"
201bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "../ralloc_util.h"
211bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
22e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbeenamespace art {
23e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
24b046e16d8b8da318d6055f9308950131f1255e08buzbee/* This file contains codegen for the X86 ISA */
25e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
2602031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpFpRegCopy(CompilationUnit *cu, int r_dest, int r_src)
27e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee{
28a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int opcode;
29a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* must be both DOUBLE or both not DOUBLE */
30fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(X86_DOUBLEREG(r_dest), X86_DOUBLEREG(r_src));
31fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (X86_DOUBLEREG(r_dest)) {
32a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    opcode = kX86MovsdRR;
33a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
34fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (X86_SINGLEREG(r_dest)) {
35fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_SINGLEREG(r_src)) {
36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kX86MovssRR;
37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {  // Fpr <- Gpr
38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kX86MovdxrRR;
39a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {  // Gpr <- Fpr
41fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(X86_SINGLEREG(r_src));
42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kX86MovdrxRR;
43e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
44a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
45ec13743da80a80c1817cf6660c28917fc28846bcbuzbee  DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
46fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src);
47fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest == r_src) {
48fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res->flags.is_nop = true;
49a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
50a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
51e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
52e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
53e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee/*
54e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Load a immediate using a shortcut if possible; otherwise
55e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * grab from the per-translation literal pool.  If target is
56e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * a high register, build constant into a low register and copy.
57e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee *
58e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * No additional register clobbering operation performed. Use this version when
59fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * 1) r_dest is freshly returned from AllocTemp or
60e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 2) The codegen is under fixed register usage
61e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee */
6202031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int value)
63a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
64fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int r_dest_save = r_dest;
65fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (X86_FPREG(r_dest)) {
66b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    if (value == 0) {
67fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return NewLIR2(cu, kX86XorpsRR, r_dest, r_dest);
68b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
69fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    DCHECK(X86_SINGLEREG(r_dest));
70fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    r_dest = AllocTemp(cu);
716cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
72e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
73b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  LIR *res;
746cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  if (value == 0) {
75fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res = NewLIR2(cu, kX86Xor32RR, r_dest, r_dest);
766cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  } else {
772e9f7ed8d00271cb1cf082d68b4f4bc60702d6ecIan Rogers    // Note, there is no byte immediate form of a 32 bit immediate move.
78fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res = NewLIR2(cu, kX86Mov32RI, r_dest, value);
796cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
80e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
81fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (X86_FPREG(r_dest_save)) {
82fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    NewLIR2(cu, kX86MovdxrRR, r_dest_save, r_dest);
83fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    FreeTemp(cu, r_dest);
846cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
85e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
866cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  return res;
87e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
88e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
8902031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
90a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
9102031b185b4653e6c72e21f7a51238b903f6d638buzbee  LIR* res = NewLIR1(cu, kX86Jmp8, 0 /* offset to be patched during assembly*/ );
9202031b185b4653e6c72e21f7a51238b903f6d638buzbee  res->target = target;
9302031b185b4653e6c72e21f7a51238b903f6d638buzbee  return res;
94e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
95e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
9602031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
97a7678db092ac6bb79f7cad490099a1015fbbc714buzbee{
98fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LIR* branch = NewLIR2(cu, kX86Jcc8, 0 /* offset to be patched */,
9952a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee                        X86ConditionEncoding(cc));
100b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  branch->target = target;
101b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return branch;
102a7678db092ac6bb79f7cad490099a1015fbbc714buzbee}
103a7678db092ac6bb79f7cad490099a1015fbbc714buzbee
10402031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src)
105a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
106b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Bkpt;
107b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (op) {
108b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpNeg: opcode = kX86Neg32R; break;
1091395b1e06c1d0ff5155b0c5d113ad3bd6f163c07jeffhao    case kOpNot: opcode = kX86Not32R; break;
110b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpBlx: opcode = kX86CallR; break;
111b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
11252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in OpReg " << op;
113b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
114fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return NewLIR1(cu, opcode, r_dest_src);
115e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
116e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
11702031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1, int value)
118a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
119b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Bkpt;
120fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool byte_imm = IS_SIMM8(value);
121fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(!X86_FPREG(r_dest_src1));
122b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (op) {
123b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpLsl: opcode = kX86Sal32RI; break;
124b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpLsr: opcode = kX86Shr32RI; break;
125b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpAsr: opcode = kX86Sar32RI; break;
126fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
127fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpOr:  opcode = byte_imm ? kX86Or32RI8  : kX86Or32RI;  break;
128fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
129b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    //case kOpSbb: opcode = kX86Sbb32RI; break;
130fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
131fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
132fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
133fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
134fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpMov: return LoadConstantNoClobber(cu, r_dest_src1, value);
135b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpMul:
136fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
137fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, value);
138b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
13952a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in OpRegImm " << op;
140b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
141fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return NewLIR2(cu, opcode, r_dest_src1, value);
142e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
143e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
14402031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r_src2)
145e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee{
146a7678db092ac6bb79f7cad490099a1015fbbc714buzbee    X86OpCode opcode = kX86Nop;
147d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    bool src2_must_be_cx = false;
148e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    switch (op) {
149b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        // X86 unary opcodes
150b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpMvn:
151fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        OpRegCopy(cu, r_dest_src1, r_src2);
152fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        return OpReg(cu, kOpNot, r_dest_src1);
153b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpNeg:
154fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        OpRegCopy(cu, r_dest_src1, r_src2);
155fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        return OpReg(cu, kOpNeg, r_dest_src1);
156b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        // X86 binary opcodes
157b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSub: opcode = kX86Sub32RR; break;
158b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSbc: opcode = kX86Sbb32RR; break;
159d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers      case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
160d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers      case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
161d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers      case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
162b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpMov: opcode = kX86Mov32RR; break;
163b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpCmp: opcode = kX86Cmp32RR; break;
164b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdd: opcode = kX86Add32RR; break;
165b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdc: opcode = kX86Adc32RR; break;
166b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAnd: opcode = kX86And32RR; break;
167b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpOr:  opcode = kX86Or32RR; break;
168b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpXor: opcode = kX86Xor32RR; break;
169703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao      case kOp2Byte:
170703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        // Use shifts instead of a byte operand if the source can't be byte accessed.
171fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (r_src2 >= 4) {
172fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          NewLIR2(cu, kX86Mov32RR, r_dest_src1, r_src2);
173fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          NewLIR2(cu, kX86Sal32RI, r_dest_src1, 24);
174fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          return NewLIR2(cu, kX86Sar32RI, r_dest_src1, 24);
175703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        } else {
176703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao          opcode = kX86Movsx8RR;
177703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        }
178703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        break;
179b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOp2Short: opcode = kX86Movsx16RR; break;
180b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOp2Char: opcode = kX86Movzx16RR; break;
181b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpMul: opcode = kX86Imul32RR; break;
182b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      default:
18352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        LOG(FATAL) << "Bad case in OpRegReg " << op;
184b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        break;
185e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
186fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    CHECK(!src2_must_be_cx || r_src2 == rCX);
187fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    return NewLIR2(cu, opcode, r_dest_src1, r_src2);
188e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
189e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
19002031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase,
191a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee              int offset)
192a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
193b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Nop;
194b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (op) {
195b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      // X86 binary opcodes
196b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpSub: opcode = kX86Sub32RM; break;
197b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpMov: opcode = kX86Mov32RM; break;
198b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpCmp: opcode = kX86Cmp32RM; break;
199b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpAdd: opcode = kX86Add32RM; break;
200b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpAnd: opcode = kX86And32RM; break;
201b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpOr:  opcode = kX86Or32RM; break;
202b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpXor: opcode = kX86Xor32RM; break;
203b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOp2Byte: opcode = kX86Movsx8RM; break;
204b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOp2Short: opcode = kX86Movsx16RM; break;
205b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOp2Char: opcode = kX86Movzx16RM; break;
206b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpMul:
207b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
20852a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in OpRegMem " << op;
209b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
210b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
211fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return NewLIR3(cu, opcode, r_dest, rBase, offset);
212b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers}
213e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
21402031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_src1,
215fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                 int r_src2)
216a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
217fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest != r_src1 && r_dest != r_src2) {
218b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (op == kOpAdd) { // lea special case, except can't encode rbp as base
219fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (r_src1 == r_src2) {
220fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        OpRegCopy(cu, r_dest, r_src1);
221fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        return OpRegImm(cu, kOpLsl, r_dest, 1);
222fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if (r_src1 != rBP) {
223fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        return NewLIR5(cu, kX86Lea32RA, r_dest, r_src1 /* base */,
224fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                       r_src2 /* index */, 0 /* scale */, 0 /* disp */);
225b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      } else {
226fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        return NewLIR5(cu, kX86Lea32RA, r_dest, r_src2 /* base */,
227fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                       r_src1 /* index */, 0 /* scale */, 0 /* disp */);
228b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
229b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    } else {
230fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      OpRegCopy(cu, r_dest, r_src1);
231fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return OpRegReg(cu, op, r_dest, r_src2);
232e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
233fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  } else if (r_dest == r_src1) {
234fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    return OpRegReg(cu, op, r_dest, r_src2);
235fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  } else {  // r_dest == r_src2
236b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    switch (op) {
237b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSub:  // non-commutative
238fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        OpReg(cu, kOpNeg, r_dest);
239b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        op = kOpAdd;
240b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        break;
241b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSbc:
242b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
243fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        int t_reg = AllocTemp(cu);
244fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        OpRegCopy(cu, t_reg, r_src1);
245fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        OpRegReg(cu, op, t_reg, r_src2);
246fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        LIR* res = OpRegCopy(cu, r_dest, t_reg);
247fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        FreeTemp(cu, t_reg);
248b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        return res;
249b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
250b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdd:  // commutative
251b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpOr:
252b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdc:
253b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAnd:
254b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpXor:
255b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        break;
256b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      default:
25752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        LOG(FATAL) << "Bad case in OpRegRegReg " << op;
258e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
259fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    return OpRegReg(cu, op, r_dest, r_src1);
260b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
261e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
262e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
26302031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_src,
264a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                 int value)
265a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
266b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  if (op == kOpMul) {
267b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
268fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    return NewLIR3(cu, opcode, r_dest, r_src, value);
269b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  } else if (op == kOpAnd) {
270fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (value == 0xFF && r_src < 4) {
271fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return NewLIR2(cu, kX86Movzx8RR, r_dest, r_src);
272b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else if (value == 0xFFFF) {
273fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return NewLIR2(cu, kX86Movzx16RR, r_dest, r_src);
274b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
275b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
276fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest != r_src) {
2777caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
2787caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers      // TODO: fix bug in LEA encoding when disp == 0
279fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return NewLIR5(cu, kX86Lea32RA, r_dest,  r5sib_no_base /* base */,
280fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                     r_src /* index */, value /* scale */, 0 /* disp */);
281b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else if (op == kOpAdd) { // lea add special case
282fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      return NewLIR5(cu, kX86Lea32RA, r_dest, r_src /* base */,
283b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                     r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
284e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
285fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    OpRegCopy(cu, r_dest, r_src);
286b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
287fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return OpRegImm(cu, op, r_dest, value);
288e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
289e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
29002031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
291a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
2926cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  X86OpCode opcode = kX86Bkpt;
2936cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  switch (op) {
2946cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    case kOpBlx: opcode = kX86CallT;  break;
2956cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    default:
2966cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      LOG(FATAL) << "Bad opcode: " << op;
2976cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      break;
2986cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
299fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return NewLIR1(cu, opcode, thread_offset);
3006cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers}
3016cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers
30202031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
303a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
3046cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  X86OpCode opcode = kX86Bkpt;
3056cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  switch (op) {
3066cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    case kOpBlx: opcode = kX86CallM;  break;
3076cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    default:
3086cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      LOG(FATAL) << "Bad opcode: " << op;
3096cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      break;
3106cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
311fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return NewLIR2(cu, opcode, rBase, disp);
3126cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers}
3136cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers
31402031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::LoadConstantValueWide(CompilationUnit *cu, int r_dest_lo,
31502031b185b4653e6c72e21f7a51238b903f6d638buzbee                                       int r_dest_hi, int val_lo, int val_hi)
316e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee{
317e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    LIR *res;
318fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (X86_FPREG(r_dest_lo)) {
319fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(X86_FPREG(r_dest_hi));  // ignore r_dest_hi
320fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (val_lo == 0 && val_hi == 0) {
321fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        return NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo);
322b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers      } else {
323fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (val_lo == 0) {
324fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          res = NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo);
325b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers        } else {
326fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
327b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers        }
328fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (val_hi != 0) {
329fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          LoadConstantNoClobber(cu, r_dest_hi, val_hi);
330fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          NewLIR2(cu, kX86PsllqRI, r_dest_hi, 32);
331fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          NewLIR2(cu, kX86OrpsRR, r_dest_lo, r_dest_hi);
332b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers        }
333b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers      }
334b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else {
335fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
336fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      LoadConstantNoClobber(cu, r_dest_hi, val_hi);
337b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
338e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    return res;
339e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
340e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
34102031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
34202031b185b4653e6c72e21f7a51238b903f6d638buzbee                                     int displacement, int r_dest, int r_dest_hi, OpSize size,
34302031b185b4653e6c72e21f7a51238b903f6d638buzbee                                     int s_reg) {
344b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR *load = NULL;
345b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR *load2 = NULL;
346fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool is_array = r_index != INVALID_REG;
347b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  bool pair = false;
348b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  bool is64bit = false;
349b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Nop;
350b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (size) {
351b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kLong:
352b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kDouble:
353b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      is64bit = true;
354fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_FPREG(r_dest)) {
355fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovsdRA : kX86MovsdRM;
356fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (X86_SINGLEREG(r_dest)) {
357fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          DCHECK(X86_FPREG(r_dest_hi));
358fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          DCHECK_EQ(r_dest, (r_dest_hi - 1));
359fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          r_dest = S2d(r_dest, r_dest_hi);
360e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee        }
361fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        r_dest_hi = r_dest + 1;
362b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      } else {
363b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        pair = true;
364fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86Mov32RA  : kX86Mov32RM;
365b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
366b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      // TODO: double store is to unaligned address
367b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
368b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
369b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kWord:
370b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSingle:
371fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
372fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_FPREG(r_dest)) {
373fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovssRA : kX86MovssRM;
374fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        DCHECK(X86_SINGLEREG(r_dest));
375b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
376b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
377b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
378b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedHalf:
379fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM;
380b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x1), 0);
381b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
382b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedHalf:
383fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM;
384b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x1), 0);
385b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
386b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedByte:
387fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM;
388b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
389b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedByte:
390fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM;
391b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
392b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
39352a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
394b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
395b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
396fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (!is_array) {
397b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (!pair) {
398fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
399e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    } else {
400fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (rBase == r_dest) {
401fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        load2 = NewLIR3(cu, opcode, r_dest_hi, rBase,
402fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
403fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
404fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      } else {
405fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
406fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        load2 = NewLIR3(cu, opcode, r_dest_hi, rBase,
407fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
408fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      }
409e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
410f0504cdc5b6400edd4b39eea64ac280465042d5bbuzbee    if (rBase == rX86_SP) {
41102031b185b4653e6c72e21f7a51238b903f6d638buzbee      AnnotateDalvikRegAccess(cu, load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
41202031b185b4653e6c72e21f7a51238b903f6d638buzbee                              true /* is_load */, is64bit);
413f7d9ad39541dd09030e26d54d3b73a076f90cc74Ian Rogers      if (pair) {
41402031b185b4653e6c72e21f7a51238b903f6d638buzbee        AnnotateDalvikRegAccess(cu, load2, (displacement + HIWORD_OFFSET) >> 2,
415fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                true /* is_load */, is64bit);
416b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
417e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
418b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
419b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (!pair) {
420fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
421a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                     displacement + LOWORD_OFFSET);
422b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    } else {
423fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (rBase == r_dest) {
424fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale,
425fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
426fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
427fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                       displacement + LOWORD_OFFSET);
428fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      } else {
429fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
430fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                       displacement + LOWORD_OFFSET);
431fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale,
432fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
433fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      }
434b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    }
435b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
436b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
437b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return load;
438e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
439e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
4405772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao/* Load value from base + scaled index. */
44102031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::LoadBaseIndexed(CompilationUnit *cu, int rBase,
442fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                     int r_index, int r_dest, int scale, OpSize size) {
443fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return LoadBaseIndexedDisp(cu, rBase, r_index, scale, 0,
444fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                             r_dest, INVALID_REG, size, INVALID_SREG);
4455772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao}
4465772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao
44702031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::LoadBaseDisp(CompilationUnit *cu, int rBase, int displacement,
448fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                  int r_dest, OpSize size, int s_reg) {
449fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
450fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                             r_dest, INVALID_REG, size, s_reg);
451e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
452e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
45302031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::LoadBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
454fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                      int r_dest_lo, int r_dest_hi, int s_reg) {
455fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
456fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                             r_dest_lo, r_dest_hi, kLong, s_reg);
457e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
458e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
45902031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
46002031b185b4653e6c72e21f7a51238b903f6d638buzbee                                      int displacement, int r_src, int r_src_hi, OpSize size,
46102031b185b4653e6c72e21f7a51238b903f6d638buzbee                                      int s_reg) {
462b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR *store = NULL;
463e296248a124ed8287b38a9225463696c18d84cd6jeffhao  LIR *store2 = NULL;
464fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool is_array = r_index != INVALID_REG;
465b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  bool pair = false;
466e296248a124ed8287b38a9225463696c18d84cd6jeffhao  bool is64bit = false;
467b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  X86OpCode opcode = kX86Nop;
468b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (size) {
469b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kLong:
470b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kDouble:
471e296248a124ed8287b38a9225463696c18d84cd6jeffhao      is64bit = true;
472fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_FPREG(r_src)) {
473fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
474fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (X86_SINGLEREG(r_src)) {
475fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          DCHECK(X86_FPREG(r_src_hi));
476fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          DCHECK_EQ(r_src, (r_src_hi - 1));
477fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          r_src = S2d(r_src, r_src_hi);
478e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee        }
479fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        r_src_hi = r_src + 1;
480b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      } else {
481b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        pair = true;
482fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86Mov32AR  : kX86Mov32MR;
483b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
484b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      // TODO: double store is to unaligned address
485b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
486b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
487b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kWord:
488b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSingle:
489fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
490fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_FPREG(r_src)) {
491fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovssAR : kX86MovssMR;
492fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        DCHECK(X86_SINGLEREG(r_src));
493b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
494b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
495b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
496b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedHalf:
497b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedHalf:
498fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov16AR : kX86Mov16MR;
499b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x1), 0);
500b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
501b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedByte:
502b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedByte:
503fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov8AR : kX86Mov8MR;
504b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
505b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
50652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
507b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
508b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
509fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (!is_array) {
510b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    if (!pair) {
511fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src);
512b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else {
513fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src);
514fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      store2 = NewLIR3(cu, opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi);
515e296248a124ed8287b38a9225463696c18d84cd6jeffhao    }
516f0504cdc5b6400edd4b39eea64ac280465042d5bbuzbee    if (rBase == rX86_SP) {
51702031b185b4653e6c72e21f7a51238b903f6d638buzbee      AnnotateDalvikRegAccess(cu, store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
51802031b185b4653e6c72e21f7a51238b903f6d638buzbee                              false /* is_load */, is64bit);
519e296248a124ed8287b38a9225463696c18d84cd6jeffhao      if (pair) {
52002031b185b4653e6c72e21f7a51238b903f6d638buzbee        AnnotateDalvikRegAccess(cu, store2, (displacement + HIWORD_OFFSET) >> 2,
521fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                false /* is_load */, is64bit);
522e296248a124ed8287b38a9225463696c18d84cd6jeffhao      }
523b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
524b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
525b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    if (!pair) {
526fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      store = NewLIR5(cu, opcode, rBase, r_index, scale,
527fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                      displacement + LOWORD_OFFSET, r_src);
528b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else {
529fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      store = NewLIR5(cu, opcode, rBase, r_index, scale,
530fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                      displacement + LOWORD_OFFSET, r_src);
531fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      store2 = NewLIR5(cu, opcode, rBase, r_index, scale,
532fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                       displacement + HIWORD_OFFSET, r_src_hi);
533e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
534b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
535b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers
536b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  return store;
537e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
538e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
539c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers/* store value base base + scaled index. */
54002031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_src,
541a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                      int scale, OpSize size)
542c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers{
543fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return StoreBaseIndexedDisp(cu, rBase, r_index, scale, 0,
544fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              r_src, INVALID_REG, size, INVALID_SREG);
545c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers}
546c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers
54702031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::StoreBaseDisp(CompilationUnit *cu, int rBase, int displacement,
54802031b185b4653e6c72e21f7a51238b903f6d638buzbee                               int r_src, OpSize size)
549a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
550fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0,
551fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                displacement, r_src, INVALID_REG, size,
552a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                INVALID_SREG);
553e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
554e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
55502031b185b4653e6c72e21f7a51238b903f6d638buzbeeLIR* X86Codegen::StoreBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
55602031b185b4653e6c72e21f7a51238b903f6d638buzbee                                   int r_src_lo, int r_src_hi)
557a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
558fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
559fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              r_src_lo, r_src_hi, kLong, INVALID_SREG);
560e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
561e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
56202031b185b4653e6c72e21f7a51238b903f6d638buzbeevoid X86Codegen::LoadPair(CompilationUnit *cu, int base, int low_reg, int high_reg)
563e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee{
564fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  LoadBaseDispWide(cu, base, 0, low_reg, high_reg, INVALID_SREG);
565e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
566e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
567e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}  // namespace art
568