utility_x86.cc revision 1fd3346740dfb7f47be9922312b68a4227fada96
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"
18641ce0371c2f0dc95d26be02d8366124c8b66653Brian Carlstrom#include "x86_lir.h"
191bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee
20e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbeenamespace art {
21e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
22b046e16d8b8da318d6055f9308950131f1255e08buzbee/* This file contains codegen for the X86 ISA */
23e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
241fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpFpRegCopy(int r_dest, int r_src)
25e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee{
26a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  int opcode;
27a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  /* must be both DOUBLE or both not DOUBLE */
28fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK_EQ(X86_DOUBLEREG(r_dest), X86_DOUBLEREG(r_src));
29fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (X86_DOUBLEREG(r_dest)) {
30a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    opcode = kX86MovsdRR;
31a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  } else {
32fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (X86_SINGLEREG(r_dest)) {
33fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_SINGLEREG(r_src)) {
34a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kX86MovssRR;
35a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      } else {  // Fpr <- Gpr
36a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee        opcode = kX86MovdxrRR;
37a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      }
38a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee    } else {  // Gpr <- Fpr
39fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(X86_SINGLEREG(r_src));
40a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee      opcode = kX86MovdrxRR;
41e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
42a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
43ec13743da80a80c1817cf6660c28917fc28846bcbuzbee  DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
441fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
45fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest == r_src) {
46fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    res->flags.is_nop = true;
47a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  }
48a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee  return res;
49e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
50e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
511fd3346740dfb7f47be9922312b68a4227fada96buzbeebool X86Mir2Lir::InexpensiveConstantInt(int32_t value)
52e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee{
53e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee  return true;
54e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee}
55e6285f99a53a344efd6f8409ff5f43a3e80190dbbuzbee
561fd3346740dfb7f47be9922312b68a4227fada96buzbeebool X86Mir2Lir::InexpensiveConstantFloat(int32_t value)
574ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee{
584ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return false;
594ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
604ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
611fd3346740dfb7f47be9922312b68a4227fada96buzbeebool X86Mir2Lir::InexpensiveConstantLong(int64_t value)
624ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee{
634ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return true;
644ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
654ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
661fd3346740dfb7f47be9922312b68a4227fada96buzbeebool X86Mir2Lir::InexpensiveConstantDouble(int64_t value)
674ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee{
684ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee  return false; // TUNING
694ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee}
704ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee
71e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee/*
72e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * Load a immediate using a shortcut if possible; otherwise
73e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * grab from the per-translation literal pool.  If target is
74e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * a high register, build constant into a low register and copy.
75e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee *
76e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * No additional register clobbering operation performed. Use this version when
77fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee * 1) r_dest is freshly returned from AllocTemp or
78e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee * 2) The codegen is under fixed register usage
79e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee */
801fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::LoadConstantNoClobber(int r_dest, int value)
81a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
82fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  int r_dest_save = r_dest;
83fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (X86_FPREG(r_dest)) {
84b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    if (value == 0) {
851fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR2(kX86XorpsRR, r_dest, r_dest);
86b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
87fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    DCHECK(X86_SINGLEREG(r_dest));
881fd3346740dfb7f47be9922312b68a4227fada96buzbee    r_dest = AllocTemp();
896cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
90e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
91b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  LIR *res;
926cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  if (value == 0) {
931fd3346740dfb7f47be9922312b68a4227fada96buzbee    res = NewLIR2(kX86Xor32RR, r_dest, r_dest);
946cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  } else {
952e9f7ed8d00271cb1cf082d68b4f4bc60702d6ecIan Rogers    // Note, there is no byte immediate form of a 32 bit immediate move.
961fd3346740dfb7f47be9922312b68a4227fada96buzbee    res = NewLIR2(kX86Mov32RI, r_dest, value);
976cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
98e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
99fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (X86_FPREG(r_dest_save)) {
1001fd3346740dfb7f47be9922312b68a4227fada96buzbee    NewLIR2(kX86MovdxrRR, r_dest_save, r_dest);
1011fd3346740dfb7f47be9922312b68a4227fada96buzbee    FreeTemp(r_dest);
1026cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
103e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1046cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  return res;
105e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
106e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1071fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpUnconditionalBranch(LIR* target)
108a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
1091fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* res = NewLIR1(kX86Jmp8, 0 /* offset to be patched during assembly*/ );
11002031b185b4653e6c72e21f7a51238b903f6d638buzbee  res->target = target;
11102031b185b4653e6c72e21f7a51238b903f6d638buzbee  return res;
112e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
113e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1141fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target)
115a7678db092ac6bb79f7cad490099a1015fbbc714buzbee{
1161fd3346740dfb7f47be9922312b68a4227fada96buzbee  LIR* branch = NewLIR2(kX86Jcc8, 0 /* offset to be patched */,
11752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee                        X86ConditionEncoding(cc));
118b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  branch->target = target;
119b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return branch;
120a7678db092ac6bb79f7cad490099a1015fbbc714buzbee}
121a7678db092ac6bb79f7cad490099a1015fbbc714buzbee
1221fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpReg(OpKind op, int r_dest_src)
123a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
124b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Bkpt;
125b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (op) {
126b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpNeg: opcode = kX86Neg32R; break;
1271395b1e06c1d0ff5155b0c5d113ad3bd6f163c07jeffhao    case kOpNot: opcode = kX86Not32R; break;
128b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpBlx: opcode = kX86CallR; break;
129b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
13052a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in OpReg " << op;
131b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
1321fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR1(opcode, r_dest_src);
133e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
134e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1351fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value)
136a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
137b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Bkpt;
138fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool byte_imm = IS_SIMM8(value);
139fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  DCHECK(!X86_FPREG(r_dest_src1));
140b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (op) {
141b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpLsl: opcode = kX86Sal32RI; break;
142b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpLsr: opcode = kX86Shr32RI; break;
143b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpAsr: opcode = kX86Sar32RI; break;
144fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
145fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpOr:  opcode = byte_imm ? kX86Or32RI8  : kX86Or32RI;  break;
146fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
147b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    //case kOpSbb: opcode = kX86Sbb32RI; break;
148fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
149fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
150fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
151fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
1521fd3346740dfb7f47be9922312b68a4227fada96buzbee    case kOpMov: return LoadConstantNoClobber(r_dest_src1, value);
153b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpMul:
154fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
1551fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR3(opcode, r_dest_src1, r_dest_src1, value);
156b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
15752a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in OpRegImm " << op;
158b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
1591fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR2(opcode, r_dest_src1, value);
160e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
161e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
1621fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2)
163e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee{
164a7678db092ac6bb79f7cad490099a1015fbbc714buzbee    X86OpCode opcode = kX86Nop;
165d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers    bool src2_must_be_cx = false;
166e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    switch (op) {
167b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        // X86 unary opcodes
168b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpMvn:
1691fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(r_dest_src1, r_src2);
1701fd3346740dfb7f47be9922312b68a4227fada96buzbee        return OpReg(kOpNot, r_dest_src1);
171b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpNeg:
1721fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(r_dest_src1, r_src2);
1731fd3346740dfb7f47be9922312b68a4227fada96buzbee        return OpReg(kOpNeg, r_dest_src1);
174b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        // X86 binary opcodes
175b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSub: opcode = kX86Sub32RR; break;
176b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSbc: opcode = kX86Sbb32RR; break;
177d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers      case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
178d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers      case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
179d36c52ea6bc22883ef381f6da1ac05ef7524f63aIan Rogers      case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
180b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpMov: opcode = kX86Mov32RR; break;
181b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpCmp: opcode = kX86Cmp32RR; break;
182b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdd: opcode = kX86Add32RR; break;
183b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdc: opcode = kX86Adc32RR; break;
184b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAnd: opcode = kX86And32RR; break;
185b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpOr:  opcode = kX86Or32RR; break;
186b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpXor: opcode = kX86Xor32RR; break;
187703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao      case kOp2Byte:
188703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        // Use shifts instead of a byte operand if the source can't be byte accessed.
189fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (r_src2 >= 4) {
1901fd3346740dfb7f47be9922312b68a4227fada96buzbee          NewLIR2(kX86Mov32RR, r_dest_src1, r_src2);
1911fd3346740dfb7f47be9922312b68a4227fada96buzbee          NewLIR2(kX86Sal32RI, r_dest_src1, 24);
1921fd3346740dfb7f47be9922312b68a4227fada96buzbee          return NewLIR2(kX86Sar32RI, r_dest_src1, 24);
193703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        } else {
194703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao          opcode = kX86Movsx8RR;
195703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        }
196703f2cd1f4d1eb5ab5c9792ca2de9ffb39378203jeffhao        break;
197b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOp2Short: opcode = kX86Movsx16RR; break;
198b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOp2Char: opcode = kX86Movzx16RR; break;
199b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpMul: opcode = kX86Imul32RR; break;
200b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      default:
20152a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        LOG(FATAL) << "Bad case in OpRegReg " << op;
202b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        break;
203e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
204fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    CHECK(!src2_must_be_cx || r_src2 == rCX);
2051fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR2(opcode, r_dest_src1, r_src2);
206e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
207e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
2081fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpRegMem(OpKind op, int r_dest, int rBase,
209a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee              int offset)
210a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
211b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Nop;
212b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (op) {
213b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      // X86 binary opcodes
214b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpSub: opcode = kX86Sub32RM; break;
215b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpMov: opcode = kX86Mov32RM; break;
216b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpCmp: opcode = kX86Cmp32RM; break;
217b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpAdd: opcode = kX86Add32RM; break;
218b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpAnd: opcode = kX86And32RM; break;
219b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpOr:  opcode = kX86Or32RM; break;
220b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpXor: opcode = kX86Xor32RM; break;
221b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOp2Byte: opcode = kX86Movsx8RM; break;
222b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOp2Short: opcode = kX86Movsx16RM; break;
223b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOp2Char: opcode = kX86Movzx16RM; break;
224b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kOpMul:
225b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
22652a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in OpRegMem " << op;
227b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
228b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
2291fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR3(opcode, r_dest, rBase, offset);
230b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers}
231e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
2321fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1,
233fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                 int r_src2)
234a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
235fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest != r_src1 && r_dest != r_src2) {
236b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (op == kOpAdd) { // lea special case, except can't encode rbp as base
237fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (r_src1 == r_src2) {
2381fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(r_dest, r_src1);
2391fd3346740dfb7f47be9922312b68a4227fada96buzbee        return OpRegImm(kOpLsl, r_dest, 1);
240fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      } else if (r_src1 != rBP) {
2411fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR5(kX86Lea32RA, r_dest, r_src1 /* base */,
242fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                       r_src2 /* index */, 0 /* scale */, 0 /* disp */);
243b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      } else {
2441fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR5(kX86Lea32RA, r_dest, r_src2 /* base */,
245fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                       r_src1 /* index */, 0 /* scale */, 0 /* disp */);
246b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
247b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    } else {
2481fd3346740dfb7f47be9922312b68a4227fada96buzbee      OpRegCopy(r_dest, r_src1);
2491fd3346740dfb7f47be9922312b68a4227fada96buzbee      return OpRegReg(op, r_dest, r_src2);
250e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
251fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  } else if (r_dest == r_src1) {
2521fd3346740dfb7f47be9922312b68a4227fada96buzbee    return OpRegReg(op, r_dest, r_src2);
253fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  } else {  // r_dest == r_src2
254b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    switch (op) {
255b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSub:  // non-commutative
2561fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpReg(kOpNeg, r_dest);
257b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        op = kOpAdd;
258b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        break;
259b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpSbc:
260b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
2611fd3346740dfb7f47be9922312b68a4227fada96buzbee        int t_reg = AllocTemp();
2621fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegCopy(t_reg, r_src1);
2631fd3346740dfb7f47be9922312b68a4227fada96buzbee        OpRegReg(op, t_reg, r_src2);
2641fd3346740dfb7f47be9922312b68a4227fada96buzbee        LIR* res = OpRegCopy(r_dest, t_reg);
2651fd3346740dfb7f47be9922312b68a4227fada96buzbee        FreeTemp(t_reg);
266b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        return res;
267b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
268b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdd:  // commutative
269b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpOr:
270b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAdc:
271b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpAnd:
272b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      case kOpXor:
273b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        break;
274b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      default:
27552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee        LOG(FATAL) << "Bad case in OpRegRegReg " << op;
276e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
2771fd3346740dfb7f47be9922312b68a4227fada96buzbee    return OpRegReg(op, r_dest, r_src1);
278b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
279e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
280e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
2811fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src,
282a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                 int value)
283a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
284b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  if (op == kOpMul) {
285b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
2861fd3346740dfb7f47be9922312b68a4227fada96buzbee    return NewLIR3(opcode, r_dest, r_src, value);
287b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  } else if (op == kOpAnd) {
288fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (value == 0xFF && r_src < 4) {
2891fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR2(kX86Movzx8RR, r_dest, r_src);
290b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else if (value == 0xFFFF) {
2911fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR2(kX86Movzx16RR, r_dest, r_src);
292b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
293b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
294fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (r_dest != r_src) {
2957caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers    if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
2967caad77632ae121c9f64c488e3f8f710e2c4813dIan Rogers      // TODO: fix bug in LEA encoding when disp == 0
2971fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR5(kX86Lea32RA, r_dest,  r5sib_no_base /* base */,
298fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                     r_src /* index */, value /* scale */, 0 /* disp */);
299b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else if (op == kOpAdd) { // lea add special case
3001fd3346740dfb7f47be9922312b68a4227fada96buzbee      return NewLIR5(kX86Lea32RA, r_dest, r_src /* base */,
301b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                     r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
302e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
3031fd3346740dfb7f47be9922312b68a4227fada96buzbee    OpRegCopy(r_dest, r_src);
304b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
3051fd3346740dfb7f47be9922312b68a4227fada96buzbee  return OpRegImm(op, r_dest, value);
306e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
307e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
3081fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpThreadMem(OpKind op, int thread_offset)
309a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
3106cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  X86OpCode opcode = kX86Bkpt;
3116cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  switch (op) {
3126cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    case kOpBlx: opcode = kX86CallT;  break;
3136cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    default:
3146cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      LOG(FATAL) << "Bad opcode: " << op;
3156cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      break;
3166cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
3171fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR1(opcode, thread_offset);
3186cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers}
3196cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers
3201fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::OpMem(OpKind op, int rBase, int disp)
321a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
3226cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  X86OpCode opcode = kX86Bkpt;
3236cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  switch (op) {
3246cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    case kOpBlx: opcode = kX86CallM;  break;
3256cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers    default:
3266cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      LOG(FATAL) << "Bad opcode: " << op;
3276cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers      break;
3286cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers  }
3291fd3346740dfb7f47be9922312b68a4227fada96buzbee  return NewLIR2(opcode, rBase, disp);
3306cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers}
3316cbb2bd8ba9a52de7e50a5da1f4e98dd7a460f1bIan Rogers
3321fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value)
333e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee{
3344ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int32_t val_lo = Low32Bits(value);
3354ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee    int32_t val_hi = High32Bits(value);
336e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    LIR *res;
337fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee    if (X86_FPREG(r_dest_lo)) {
338fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      DCHECK(X86_FPREG(r_dest_hi));  // ignore r_dest_hi
3394ef3e45d7c6ec3c482a1a48f4df470811aa3cf0abuzbee      if (value == 0) {
3401fd3346740dfb7f47be9922312b68a4227fada96buzbee        return NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo);
341b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers      } else {
342fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (val_lo == 0) {
3431fd3346740dfb7f47be9922312b68a4227fada96buzbee          res = NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo);
344b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers        } else {
3451fd3346740dfb7f47be9922312b68a4227fada96buzbee          res = LoadConstantNoClobber(r_dest_lo, val_lo);
346b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers        }
347fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (val_hi != 0) {
3481fd3346740dfb7f47be9922312b68a4227fada96buzbee          LoadConstantNoClobber(r_dest_hi, val_hi);
3491fd3346740dfb7f47be9922312b68a4227fada96buzbee          NewLIR2(kX86PsllqRI, r_dest_hi, 32);
3501fd3346740dfb7f47be9922312b68a4227fada96buzbee          NewLIR2(kX86OrpsRR, r_dest_lo, r_dest_hi);
351b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers        }
352b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers      }
353b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else {
3541fd3346740dfb7f47be9922312b68a4227fada96buzbee      res = LoadConstantNoClobber(r_dest_lo, val_lo);
3551fd3346740dfb7f47be9922312b68a4227fada96buzbee      LoadConstantNoClobber(r_dest_hi, val_hi);
356b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
357e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    return res;
358e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
359e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
3601fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale,
36102031b185b4653e6c72e21f7a51238b903f6d638buzbee                                     int displacement, int r_dest, int r_dest_hi, OpSize size,
36202031b185b4653e6c72e21f7a51238b903f6d638buzbee                                     int s_reg) {
363b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR *load = NULL;
364b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR *load2 = NULL;
365fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool is_array = r_index != INVALID_REG;
366b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  bool pair = false;
367b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  bool is64bit = false;
368b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  X86OpCode opcode = kX86Nop;
369b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (size) {
370b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kLong:
371b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kDouble:
372b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      is64bit = true;
373fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_FPREG(r_dest)) {
374fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovsdRA : kX86MovsdRM;
375fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (X86_SINGLEREG(r_dest)) {
376fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          DCHECK(X86_FPREG(r_dest_hi));
377fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          DCHECK_EQ(r_dest, (r_dest_hi - 1));
378fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          r_dest = S2d(r_dest, r_dest_hi);
379e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee        }
380fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        r_dest_hi = r_dest + 1;
381b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      } else {
382b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        pair = true;
383fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86Mov32RA  : kX86Mov32RM;
384b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
385b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      // TODO: double store is to unaligned address
386b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
387b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
388b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kWord:
389b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSingle:
390fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
391fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_FPREG(r_dest)) {
392fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovssRA : kX86MovssRM;
393fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        DCHECK(X86_SINGLEREG(r_dest));
394b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
395b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
396b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
397b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedHalf:
398fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM;
399b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x1), 0);
400b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
401b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedHalf:
402fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM;
403b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x1), 0);
404b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
405b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedByte:
406fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM;
407b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
408b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedByte:
409fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM;
410b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
411b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
41252a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
413b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
414b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
415fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (!is_array) {
416b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (!pair) {
4171fd3346740dfb7f47be9922312b68a4227fada96buzbee      load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
418e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    } else {
419fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (rBase == r_dest) {
4201fd3346740dfb7f47be9922312b68a4227fada96buzbee        load2 = NewLIR3(opcode, r_dest_hi, rBase,
421fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
4221fd3346740dfb7f47be9922312b68a4227fada96buzbee        load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
423fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      } else {
4241fd3346740dfb7f47be9922312b68a4227fada96buzbee        load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
4251fd3346740dfb7f47be9922312b68a4227fada96buzbee        load2 = NewLIR3(opcode, r_dest_hi, rBase,
426fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
427fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      }
428e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
429f0504cdc5b6400edd4b39eea64ac280465042d5bbuzbee    if (rBase == rX86_SP) {
4301fd3346740dfb7f47be9922312b68a4227fada96buzbee      AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
43102031b185b4653e6c72e21f7a51238b903f6d638buzbee                              true /* is_load */, is64bit);
432f7d9ad39541dd09030e26d54d3b73a076f90cc74Ian Rogers      if (pair) {
4331fd3346740dfb7f47be9922312b68a4227fada96buzbee        AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
434fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                true /* is_load */, is64bit);
435b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
436e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
437b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
438b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (!pair) {
4391fd3346740dfb7f47be9922312b68a4227fada96buzbee      load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
440a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                     displacement + LOWORD_OFFSET);
441b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    } else {
442fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (rBase == r_dest) {
4431fd3346740dfb7f47be9922312b68a4227fada96buzbee        load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale,
444fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
4451fd3346740dfb7f47be9922312b68a4227fada96buzbee        load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
446fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                       displacement + LOWORD_OFFSET);
447fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      } else {
4481fd3346740dfb7f47be9922312b68a4227fada96buzbee        load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
449fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                       displacement + LOWORD_OFFSET);
4501fd3346740dfb7f47be9922312b68a4227fada96buzbee        load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale,
451fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao                        displacement + HIWORD_OFFSET);
452fdffdf898f12d91765c7dbe7bcb1ccbbcd2b72d1jeffhao      }
453b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    }
454b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
455b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
456b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  return load;
457e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
458e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
4595772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao/* Load value from base + scaled index. */
4601fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::LoadBaseIndexed(int rBase,
461fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                     int r_index, int r_dest, int scale, OpSize size) {
4621fd3346740dfb7f47be9922312b68a4227fada96buzbee  return LoadBaseIndexedDisp(rBase, r_index, scale, 0,
463fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                             r_dest, INVALID_REG, size, INVALID_SREG);
4645772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao}
4655772babbe824494ef9fe90a1b07a926d124bb7c7jeffhao
4661fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::LoadBaseDisp(int rBase, int displacement,
467fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                  int r_dest, OpSize size, int s_reg) {
4681fd3346740dfb7f47be9922312b68a4227fada96buzbee  return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
469fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                             r_dest, INVALID_REG, size, s_reg);
470e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
471e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
4721fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::LoadBaseDispWide(int rBase, int displacement,
473fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                      int r_dest_lo, int r_dest_hi, int s_reg) {
4741fd3346740dfb7f47be9922312b68a4227fada96buzbee  return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
475fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                             r_dest_lo, r_dest_hi, kLong, s_reg);
476e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
477e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
4781fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale,
47902031b185b4653e6c72e21f7a51238b903f6d638buzbee                                      int displacement, int r_src, int r_src_hi, OpSize size,
48002031b185b4653e6c72e21f7a51238b903f6d638buzbee                                      int s_reg) {
481b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  LIR *store = NULL;
482e296248a124ed8287b38a9225463696c18d84cd6jeffhao  LIR *store2 = NULL;
483fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  bool is_array = r_index != INVALID_REG;
484b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  bool pair = false;
485e296248a124ed8287b38a9225463696c18d84cd6jeffhao  bool is64bit = false;
486b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  X86OpCode opcode = kX86Nop;
487b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  switch (size) {
488b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kLong:
489b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kDouble:
490e296248a124ed8287b38a9225463696c18d84cd6jeffhao      is64bit = true;
491fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_FPREG(r_src)) {
492fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
493fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        if (X86_SINGLEREG(r_src)) {
494fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          DCHECK(X86_FPREG(r_src_hi));
495fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          DCHECK_EQ(r_src, (r_src_hi - 1));
496fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee          r_src = S2d(r_src, r_src_hi);
497e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee        }
498fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        r_src_hi = r_src + 1;
499b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      } else {
500b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers        pair = true;
501fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86Mov32AR  : kX86Mov32MR;
502b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
503b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      // TODO: double store is to unaligned address
504b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
505b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
506b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kWord:
507b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSingle:
508fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
509fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      if (X86_FPREG(r_src)) {
510fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        opcode = is_array ? kX86MovssAR : kX86MovssMR;
511fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee        DCHECK(X86_SINGLEREG(r_src));
512b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      }
513b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x3), 0);
514b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
515b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedHalf:
516b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedHalf:
517fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov16AR : kX86Mov16MR;
518b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      DCHECK_EQ((displacement & 0x1), 0);
519b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
520b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kUnsignedByte:
521b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    case kSignedByte:
522fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee      opcode = is_array ? kX86Mov8AR : kX86Mov8MR;
523b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers      break;
524b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    default:
52552a77fc135f0e0df57ee24641c3f5ae415ff7bd6buzbee      LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
526b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
527b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
528fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee  if (!is_array) {
529b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    if (!pair) {
5301fd3346740dfb7f47be9922312b68a4227fada96buzbee      store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src);
531b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else {
5321fd3346740dfb7f47be9922312b68a4227fada96buzbee      store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src);
5331fd3346740dfb7f47be9922312b68a4227fada96buzbee      store2 = NewLIR3(opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi);
534e296248a124ed8287b38a9225463696c18d84cd6jeffhao    }
535f0504cdc5b6400edd4b39eea64ac280465042d5bbuzbee    if (rBase == rX86_SP) {
5361fd3346740dfb7f47be9922312b68a4227fada96buzbee      AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
53702031b185b4653e6c72e21f7a51238b903f6d638buzbee                              false /* is_load */, is64bit);
538e296248a124ed8287b38a9225463696c18d84cd6jeffhao      if (pair) {
5391fd3346740dfb7f47be9922312b68a4227fada96buzbee        AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
540fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                false /* is_load */, is64bit);
541e296248a124ed8287b38a9225463696c18d84cd6jeffhao      }
542b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    }
543b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  } else {
544b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    if (!pair) {
5451fd3346740dfb7f47be9922312b68a4227fada96buzbee      store = NewLIR5(opcode, rBase, r_index, scale,
546fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                      displacement + LOWORD_OFFSET, r_src);
547b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers    } else {
5481fd3346740dfb7f47be9922312b68a4227fada96buzbee      store = NewLIR5(opcode, rBase, r_index, scale,
549fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                      displacement + LOWORD_OFFSET, r_src);
5501fd3346740dfb7f47be9922312b68a4227fada96buzbee      store2 = NewLIR5(opcode, rBase, r_index, scale,
551fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                       displacement + HIWORD_OFFSET, r_src_hi);
552e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    }
553b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  }
554b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers
555b41b33b5e5f08083e35f84818b4f44d26feb4a8bIan Rogers  return store;
556e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
557e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
558c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers/* store value base base + scaled index. */
5591fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src,
560a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                      int scale, OpSize size)
561c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers{
5621fd3346740dfb7f47be9922312b68a4227fada96buzbee  return StoreBaseIndexedDisp(rBase, r_index, scale, 0,
563fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              r_src, INVALID_REG, size, INVALID_SREG);
564c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers}
565c6f3bb87ffbb44d902c4a1f67a71bb108bd01560Ian Rogers
5661fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::StoreBaseDisp(int rBase, int displacement,
56702031b185b4653e6c72e21f7a51238b903f6d638buzbee                               int r_src, OpSize size)
568a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
5691fd3346740dfb7f47be9922312b68a4227fada96buzbee    return StoreBaseIndexedDisp(rBase, INVALID_REG, 0,
570fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                                displacement, r_src, INVALID_REG, size,
571a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee                                INVALID_SREG);
572e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
573e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
5741fd3346740dfb7f47be9922312b68a4227fada96buzbeeLIR* X86Mir2Lir::StoreBaseDispWide(int rBase, int displacement,
57502031b185b4653e6c72e21f7a51238b903f6d638buzbee                                   int r_src_lo, int r_src_hi)
576a114add0300b95eeaae7465493f39144e07324e8Bill Buzbee{
5771fd3346740dfb7f47be9922312b68a4227fada96buzbee  return StoreBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
578fa57c47f1b72916371a9c2d5c1389219bce655b4buzbee                              r_src_lo, r_src_hi, kLong, INVALID_SREG);
579e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}
580e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
581e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee}  // namespace art
582