blob: 4cc2c182cb6890ee8b565f1e3b3d586677dfffc9 [file] [log] [blame]
buzbeee88dfbf2012-03-05 11:19:57 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
buzbee02031b12012-11-23 09:41:35 -080017#include "codegen_x86.h"
Brian Carlstrom641ce032013-01-31 15:21:37 -080018#include "compiler/codegen/codegen_util.h"
19#include "compiler/codegen/ralloc_util.h"
20#include "x86_lir.h"
buzbee1bc37c62012-11-20 13:35:41 -080021
buzbeee88dfbf2012-03-05 11:19:57 -080022namespace art {
23
buzbeeb046e162012-10-30 15:48:42 -070024/* This file contains codegen for the X86 ISA */
buzbeee88dfbf2012-03-05 11:19:57 -080025
buzbee02031b12012-11-23 09:41:35 -080026LIR* X86Codegen::OpFpRegCopy(CompilationUnit *cu, int r_dest, int r_src)
buzbeee88dfbf2012-03-05 11:19:57 -080027{
Bill Buzbeea114add2012-05-03 15:00:40 -070028 int opcode;
29 /* must be both DOUBLE or both not DOUBLE */
buzbeefa57c472012-11-21 12:06:18 -080030 DCHECK_EQ(X86_DOUBLEREG(r_dest), X86_DOUBLEREG(r_src));
31 if (X86_DOUBLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070032 opcode = kX86MovsdRR;
33 } else {
buzbeefa57c472012-11-21 12:06:18 -080034 if (X86_SINGLEREG(r_dest)) {
35 if (X86_SINGLEREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070036 opcode = kX86MovssRR;
37 } else { // Fpr <- Gpr
38 opcode = kX86MovdxrRR;
39 }
40 } else { // Gpr <- Fpr
buzbeefa57c472012-11-21 12:06:18 -080041 DCHECK(X86_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -070042 opcode = kX86MovdrxRR;
buzbeee88dfbf2012-03-05 11:19:57 -080043 }
Bill Buzbeea114add2012-05-03 15:00:40 -070044 }
buzbeeec137432012-11-13 12:13:16 -080045 DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
buzbeefa57c472012-11-21 12:06:18 -080046 LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src);
47 if (r_dest == r_src) {
48 res->flags.is_nop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -070049 }
50 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080051}
52
buzbee4ef3e452012-12-14 13:35:28 -080053bool X86Codegen::InexpensiveConstantInt(int32_t value)
buzbeee6285f92012-12-06 15:57:46 -080054{
55 return true;
56}
57
buzbee4ef3e452012-12-14 13:35:28 -080058bool X86Codegen::InexpensiveConstantFloat(int32_t value)
59{
60 return false;
61}
62
63bool X86Codegen::InexpensiveConstantLong(int64_t value)
64{
65 return true;
66}
67
68bool X86Codegen::InexpensiveConstantDouble(int64_t value)
69{
70 return false; // TUNING
71}
72
buzbeee88dfbf2012-03-05 11:19:57 -080073/*
74 * Load a immediate using a shortcut if possible; otherwise
75 * grab from the per-translation literal pool. If target is
76 * a high register, build constant into a low register and copy.
77 *
78 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -080079 * 1) r_dest is freshly returned from AllocTemp or
buzbeee88dfbf2012-03-05 11:19:57 -080080 * 2) The codegen is under fixed register usage
81 */
buzbee02031b12012-11-23 09:41:35 -080082LIR* X86Codegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int value)
Bill Buzbeea114add2012-05-03 15:00:40 -070083{
buzbeefa57c472012-11-21 12:06:18 -080084 int r_dest_save = r_dest;
85 if (X86_FPREG(r_dest)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -070086 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -080087 return NewLIR2(cu, kX86XorpsRR, r_dest, r_dest);
Ian Rogersb41b33b2012-03-20 14:22:54 -070088 }
buzbeefa57c472012-11-21 12:06:18 -080089 DCHECK(X86_SINGLEREG(r_dest));
90 r_dest = AllocTemp(cu);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070091 }
buzbeee88dfbf2012-03-05 11:19:57 -080092
Ian Rogersb41b33b2012-03-20 14:22:54 -070093 LIR *res;
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070094 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -080095 res = NewLIR2(cu, kX86Xor32RR, r_dest, r_dest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070096 } else {
Ian Rogers2e9f7ed2012-09-26 11:30:43 -070097 // Note, there is no byte immediate form of a 32 bit immediate move.
buzbeefa57c472012-11-21 12:06:18 -080098 res = NewLIR2(cu, kX86Mov32RI, r_dest, value);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070099 }
buzbeee88dfbf2012-03-05 11:19:57 -0800100
buzbeefa57c472012-11-21 12:06:18 -0800101 if (X86_FPREG(r_dest_save)) {
102 NewLIR2(cu, kX86MovdxrRR, r_dest_save, r_dest);
103 FreeTemp(cu, r_dest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700104 }
buzbeee88dfbf2012-03-05 11:19:57 -0800105
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700106 return res;
buzbeee88dfbf2012-03-05 11:19:57 -0800107}
108
buzbee02031b12012-11-23 09:41:35 -0800109LIR* X86Codegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
Bill Buzbeea114add2012-05-03 15:00:40 -0700110{
buzbee02031b12012-11-23 09:41:35 -0800111 LIR* res = NewLIR1(cu, kX86Jmp8, 0 /* offset to be patched during assembly*/ );
112 res->target = target;
113 return res;
buzbeee88dfbf2012-03-05 11:19:57 -0800114}
115
buzbee02031b12012-11-23 09:41:35 -0800116LIR* X86Codegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbeea7678db2012-03-05 15:35:46 -0800117{
buzbeefa57c472012-11-21 12:06:18 -0800118 LIR* branch = NewLIR2(cu, kX86Jcc8, 0 /* offset to be patched */,
buzbee52a77fc2012-11-20 19:50:46 -0800119 X86ConditionEncoding(cc));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800120 branch->target = target;
121 return branch;
buzbeea7678db2012-03-05 15:35:46 -0800122}
123
buzbee02031b12012-11-23 09:41:35 -0800124LIR* X86Codegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src)
Bill Buzbeea114add2012-05-03 15:00:40 -0700125{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800126 X86OpCode opcode = kX86Bkpt;
127 switch (op) {
128 case kOpNeg: opcode = kX86Neg32R; break;
jeffhao1395b1e2012-06-13 18:05:13 -0700129 case kOpNot: opcode = kX86Not32R; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800130 case kOpBlx: opcode = kX86CallR; break;
131 default:
buzbee52a77fc2012-11-20 19:50:46 -0800132 LOG(FATAL) << "Bad case in OpReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800133 }
buzbeefa57c472012-11-21 12:06:18 -0800134 return NewLIR1(cu, opcode, r_dest_src);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800135}
136
buzbee02031b12012-11-23 09:41:35 -0800137LIR* X86Codegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1, int value)
Bill Buzbeea114add2012-05-03 15:00:40 -0700138{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800139 X86OpCode opcode = kX86Bkpt;
buzbeefa57c472012-11-21 12:06:18 -0800140 bool byte_imm = IS_SIMM8(value);
141 DCHECK(!X86_FPREG(r_dest_src1));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800142 switch (op) {
143 case kOpLsl: opcode = kX86Sal32RI; break;
144 case kOpLsr: opcode = kX86Shr32RI; break;
145 case kOpAsr: opcode = kX86Sar32RI; break;
buzbeefa57c472012-11-21 12:06:18 -0800146 case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
147 case kOpOr: opcode = byte_imm ? kX86Or32RI8 : kX86Or32RI; break;
148 case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800149 //case kOpSbb: opcode = kX86Sbb32RI; break;
buzbeefa57c472012-11-21 12:06:18 -0800150 case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
151 case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
152 case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
153 case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
154 case kOpMov: return LoadConstantNoClobber(cu, r_dest_src1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800155 case kOpMul:
buzbeefa57c472012-11-21 12:06:18 -0800156 opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
157 return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800158 default:
buzbee52a77fc2012-11-20 19:50:46 -0800159 LOG(FATAL) << "Bad case in OpRegImm " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800160 }
buzbeefa57c472012-11-21 12:06:18 -0800161 return NewLIR2(cu, opcode, r_dest_src1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800162}
163
buzbee02031b12012-11-23 09:41:35 -0800164LIR* X86Codegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r_src2)
buzbeee88dfbf2012-03-05 11:19:57 -0800165{
buzbeea7678db2012-03-05 15:35:46 -0800166 X86OpCode opcode = kX86Nop;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700167 bool src2_must_be_cx = false;
buzbeee88dfbf2012-03-05 11:19:57 -0800168 switch (op) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800169 // X86 unary opcodes
170 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800171 OpRegCopy(cu, r_dest_src1, r_src2);
172 return OpReg(cu, kOpNot, r_dest_src1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800173 case kOpNeg:
buzbeefa57c472012-11-21 12:06:18 -0800174 OpRegCopy(cu, r_dest_src1, r_src2);
175 return OpReg(cu, kOpNeg, r_dest_src1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800176 // X86 binary opcodes
177 case kOpSub: opcode = kX86Sub32RR; break;
178 case kOpSbc: opcode = kX86Sbb32RR; break;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700179 case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
180 case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
181 case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800182 case kOpMov: opcode = kX86Mov32RR; break;
183 case kOpCmp: opcode = kX86Cmp32RR; break;
184 case kOpAdd: opcode = kX86Add32RR; break;
185 case kOpAdc: opcode = kX86Adc32RR; break;
186 case kOpAnd: opcode = kX86And32RR; break;
187 case kOpOr: opcode = kX86Or32RR; break;
188 case kOpXor: opcode = kX86Xor32RR; break;
jeffhao703f2cd2012-07-13 17:25:52 -0700189 case kOp2Byte:
190 // Use shifts instead of a byte operand if the source can't be byte accessed.
buzbeefa57c472012-11-21 12:06:18 -0800191 if (r_src2 >= 4) {
192 NewLIR2(cu, kX86Mov32RR, r_dest_src1, r_src2);
193 NewLIR2(cu, kX86Sal32RI, r_dest_src1, 24);
194 return NewLIR2(cu, kX86Sar32RI, r_dest_src1, 24);
jeffhao703f2cd2012-07-13 17:25:52 -0700195 } else {
196 opcode = kX86Movsx8RR;
197 }
198 break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800199 case kOp2Short: opcode = kX86Movsx16RR; break;
200 case kOp2Char: opcode = kX86Movzx16RR; break;
201 case kOpMul: opcode = kX86Imul32RR; break;
202 default:
buzbee52a77fc2012-11-20 19:50:46 -0800203 LOG(FATAL) << "Bad case in OpRegReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800204 break;
buzbeee88dfbf2012-03-05 11:19:57 -0800205 }
buzbeefa57c472012-11-21 12:06:18 -0800206 CHECK(!src2_must_be_cx || r_src2 == rCX);
207 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800208}
209
buzbee02031b12012-11-23 09:41:35 -0800210LIR* X86Codegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700211 int offset)
212{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800213 X86OpCode opcode = kX86Nop;
214 switch (op) {
215 // X86 binary opcodes
216 case kOpSub: opcode = kX86Sub32RM; break;
217 case kOpMov: opcode = kX86Mov32RM; break;
218 case kOpCmp: opcode = kX86Cmp32RM; break;
219 case kOpAdd: opcode = kX86Add32RM; break;
220 case kOpAnd: opcode = kX86And32RM; break;
221 case kOpOr: opcode = kX86Or32RM; break;
222 case kOpXor: opcode = kX86Xor32RM; break;
223 case kOp2Byte: opcode = kX86Movsx8RM; break;
224 case kOp2Short: opcode = kX86Movsx16RM; break;
225 case kOp2Char: opcode = kX86Movzx16RM; break;
226 case kOpMul:
227 default:
buzbee52a77fc2012-11-20 19:50:46 -0800228 LOG(FATAL) << "Bad case in OpRegMem " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800229 break;
230 }
buzbeefa57c472012-11-21 12:06:18 -0800231 return NewLIR3(cu, opcode, r_dest, rBase, offset);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800232}
233
buzbee02031b12012-11-23 09:41:35 -0800234LIR* X86Codegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_src1,
buzbeefa57c472012-11-21 12:06:18 -0800235 int r_src2)
Bill Buzbeea114add2012-05-03 15:00:40 -0700236{
buzbeefa57c472012-11-21 12:06:18 -0800237 if (r_dest != r_src1 && r_dest != r_src2) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800238 if (op == kOpAdd) { // lea special case, except can't encode rbp as base
buzbeefa57c472012-11-21 12:06:18 -0800239 if (r_src1 == r_src2) {
240 OpRegCopy(cu, r_dest, r_src1);
241 return OpRegImm(cu, kOpLsl, r_dest, 1);
242 } else if (r_src1 != rBP) {
243 return NewLIR5(cu, kX86Lea32RA, r_dest, r_src1 /* base */,
244 r_src2 /* index */, 0 /* scale */, 0 /* disp */);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800245 } else {
buzbeefa57c472012-11-21 12:06:18 -0800246 return NewLIR5(cu, kX86Lea32RA, r_dest, r_src2 /* base */,
247 r_src1 /* index */, 0 /* scale */, 0 /* disp */);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800248 }
249 } else {
buzbeefa57c472012-11-21 12:06:18 -0800250 OpRegCopy(cu, r_dest, r_src1);
251 return OpRegReg(cu, op, r_dest, r_src2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800252 }
buzbeefa57c472012-11-21 12:06:18 -0800253 } else if (r_dest == r_src1) {
254 return OpRegReg(cu, op, r_dest, r_src2);
255 } else { // r_dest == r_src2
Ian Rogersb5d09b22012-03-06 22:14:17 -0800256 switch (op) {
257 case kOpSub: // non-commutative
buzbeefa57c472012-11-21 12:06:18 -0800258 OpReg(cu, kOpNeg, r_dest);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800259 op = kOpAdd;
260 break;
261 case kOpSbc:
262 case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
buzbeefa57c472012-11-21 12:06:18 -0800263 int t_reg = AllocTemp(cu);
264 OpRegCopy(cu, t_reg, r_src1);
265 OpRegReg(cu, op, t_reg, r_src2);
266 LIR* res = OpRegCopy(cu, r_dest, t_reg);
267 FreeTemp(cu, t_reg);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800268 return res;
269 }
270 case kOpAdd: // commutative
271 case kOpOr:
272 case kOpAdc:
273 case kOpAnd:
274 case kOpXor:
275 break;
276 default:
buzbee52a77fc2012-11-20 19:50:46 -0800277 LOG(FATAL) << "Bad case in OpRegRegReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800278 }
buzbeefa57c472012-11-21 12:06:18 -0800279 return OpRegReg(cu, op, r_dest, r_src1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800280 }
281}
282
buzbee02031b12012-11-23 09:41:35 -0800283LIR* X86Codegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_src,
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 int value)
285{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800286 if (op == kOpMul) {
287 X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
buzbeefa57c472012-11-21 12:06:18 -0800288 return NewLIR3(cu, opcode, r_dest, r_src, value);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700289 } else if (op == kOpAnd) {
buzbeefa57c472012-11-21 12:06:18 -0800290 if (value == 0xFF && r_src < 4) {
291 return NewLIR2(cu, kX86Movzx8RR, r_dest, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700292 } else if (value == 0xFFFF) {
buzbeefa57c472012-11-21 12:06:18 -0800293 return NewLIR2(cu, kX86Movzx16RR, r_dest, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700294 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800295 }
buzbeefa57c472012-11-21 12:06:18 -0800296 if (r_dest != r_src) {
Ian Rogers7caad772012-03-30 01:07:54 -0700297 if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
298 // TODO: fix bug in LEA encoding when disp == 0
buzbeefa57c472012-11-21 12:06:18 -0800299 return NewLIR5(cu, kX86Lea32RA, r_dest, r5sib_no_base /* base */,
300 r_src /* index */, value /* scale */, 0 /* disp */);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700301 } else if (op == kOpAdd) { // lea add special case
buzbeefa57c472012-11-21 12:06:18 -0800302 return NewLIR5(cu, kX86Lea32RA, r_dest, r_src /* base */,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800303 r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
304 }
buzbeefa57c472012-11-21 12:06:18 -0800305 OpRegCopy(cu, r_dest, r_src);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800306 }
buzbeefa57c472012-11-21 12:06:18 -0800307 return OpRegImm(cu, op, r_dest, value);
buzbeee88dfbf2012-03-05 11:19:57 -0800308}
309
buzbee02031b12012-11-23 09:41:35 -0800310LIR* X86Codegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
Bill Buzbeea114add2012-05-03 15:00:40 -0700311{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700312 X86OpCode opcode = kX86Bkpt;
313 switch (op) {
314 case kOpBlx: opcode = kX86CallT; break;
315 default:
316 LOG(FATAL) << "Bad opcode: " << op;
317 break;
318 }
buzbeefa57c472012-11-21 12:06:18 -0800319 return NewLIR1(cu, opcode, thread_offset);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700320}
321
buzbee02031b12012-11-23 09:41:35 -0800322LIR* X86Codegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
Bill Buzbeea114add2012-05-03 15:00:40 -0700323{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700324 X86OpCode opcode = kX86Bkpt;
325 switch (op) {
326 case kOpBlx: opcode = kX86CallM; break;
327 default:
328 LOG(FATAL) << "Bad opcode: " << op;
329 break;
330 }
buzbeefa57c472012-11-21 12:06:18 -0800331 return NewLIR2(cu, opcode, rBase, disp);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700332}
333
buzbee4ef3e452012-12-14 13:35:28 -0800334LIR* X86Codegen::LoadConstantWide(CompilationUnit *cu, int r_dest_lo, int r_dest_hi, int64_t value)
buzbeee88dfbf2012-03-05 11:19:57 -0800335{
buzbee4ef3e452012-12-14 13:35:28 -0800336 int32_t val_lo = Low32Bits(value);
337 int32_t val_hi = High32Bits(value);
buzbeee88dfbf2012-03-05 11:19:57 -0800338 LIR *res;
buzbeefa57c472012-11-21 12:06:18 -0800339 if (X86_FPREG(r_dest_lo)) {
340 DCHECK(X86_FPREG(r_dest_hi)); // ignore r_dest_hi
buzbee4ef3e452012-12-14 13:35:28 -0800341 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -0800342 return NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700343 } else {
buzbeefa57c472012-11-21 12:06:18 -0800344 if (val_lo == 0) {
345 res = NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700346 } else {
buzbeefa57c472012-11-21 12:06:18 -0800347 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700348 }
buzbeefa57c472012-11-21 12:06:18 -0800349 if (val_hi != 0) {
350 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
351 NewLIR2(cu, kX86PsllqRI, r_dest_hi, 32);
352 NewLIR2(cu, kX86OrpsRR, r_dest_lo, r_dest_hi);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700353 }
354 }
355 } else {
buzbeefa57c472012-11-21 12:06:18 -0800356 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
357 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700358 }
buzbeee88dfbf2012-03-05 11:19:57 -0800359 return res;
360}
361
buzbee02031b12012-11-23 09:41:35 -0800362LIR* X86Codegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
363 int displacement, int r_dest, int r_dest_hi, OpSize size,
364 int s_reg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800365 LIR *load = NULL;
366 LIR *load2 = NULL;
buzbeefa57c472012-11-21 12:06:18 -0800367 bool is_array = r_index != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800368 bool pair = false;
369 bool is64bit = false;
370 X86OpCode opcode = kX86Nop;
371 switch (size) {
372 case kLong:
373 case kDouble:
374 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800375 if (X86_FPREG(r_dest)) {
376 opcode = is_array ? kX86MovsdRA : kX86MovsdRM;
377 if (X86_SINGLEREG(r_dest)) {
378 DCHECK(X86_FPREG(r_dest_hi));
379 DCHECK_EQ(r_dest, (r_dest_hi - 1));
380 r_dest = S2d(r_dest, r_dest_hi);
buzbeee88dfbf2012-03-05 11:19:57 -0800381 }
buzbeefa57c472012-11-21 12:06:18 -0800382 r_dest_hi = r_dest + 1;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800383 } else {
384 pair = true;
buzbeefa57c472012-11-21 12:06:18 -0800385 opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800386 }
387 // TODO: double store is to unaligned address
388 DCHECK_EQ((displacement & 0x3), 0);
389 break;
390 case kWord:
391 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800392 opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
393 if (X86_FPREG(r_dest)) {
394 opcode = is_array ? kX86MovssRA : kX86MovssRM;
395 DCHECK(X86_SINGLEREG(r_dest));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800396 }
397 DCHECK_EQ((displacement & 0x3), 0);
398 break;
399 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800400 opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800401 DCHECK_EQ((displacement & 0x1), 0);
402 break;
403 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800404 opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800405 DCHECK_EQ((displacement & 0x1), 0);
406 break;
407 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800408 opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800409 break;
410 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800411 opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800412 break;
413 default:
buzbee52a77fc2012-11-20 19:50:46 -0800414 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800415 }
416
buzbeefa57c472012-11-21 12:06:18 -0800417 if (!is_array) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800418 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800419 load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
buzbeee88dfbf2012-03-05 11:19:57 -0800420 } else {
buzbeefa57c472012-11-21 12:06:18 -0800421 if (rBase == r_dest) {
422 load2 = NewLIR3(cu, opcode, r_dest_hi, rBase,
jeffhaofdffdf82012-07-11 16:08:43 -0700423 displacement + HIWORD_OFFSET);
buzbeefa57c472012-11-21 12:06:18 -0800424 load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
jeffhaofdffdf82012-07-11 16:08:43 -0700425 } else {
buzbeefa57c472012-11-21 12:06:18 -0800426 load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
427 load2 = NewLIR3(cu, opcode, r_dest_hi, rBase,
jeffhaofdffdf82012-07-11 16:08:43 -0700428 displacement + HIWORD_OFFSET);
429 }
buzbeee88dfbf2012-03-05 11:19:57 -0800430 }
buzbeef0504cd2012-11-13 16:31:10 -0800431 if (rBase == rX86_SP) {
buzbee02031b12012-11-23 09:41:35 -0800432 AnnotateDalvikRegAccess(cu, load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
433 true /* is_load */, is64bit);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700434 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800435 AnnotateDalvikRegAccess(cu, load2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800436 true /* is_load */, is64bit);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800437 }
buzbeee88dfbf2012-03-05 11:19:57 -0800438 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800439 } else {
440 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800441 load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 displacement + LOWORD_OFFSET);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800443 } else {
buzbeefa57c472012-11-21 12:06:18 -0800444 if (rBase == r_dest) {
445 load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700446 displacement + HIWORD_OFFSET);
buzbeefa57c472012-11-21 12:06:18 -0800447 load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700448 displacement + LOWORD_OFFSET);
449 } else {
buzbeefa57c472012-11-21 12:06:18 -0800450 load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700451 displacement + LOWORD_OFFSET);
buzbeefa57c472012-11-21 12:06:18 -0800452 load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700453 displacement + HIWORD_OFFSET);
454 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800455 }
456 }
457
458 return load;
buzbeee88dfbf2012-03-05 11:19:57 -0800459}
460
jeffhao5772bab2012-05-18 11:51:26 -0700461/* Load value from base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800462LIR* X86Codegen::LoadBaseIndexed(CompilationUnit *cu, int rBase,
buzbeefa57c472012-11-21 12:06:18 -0800463 int r_index, int r_dest, int scale, OpSize size) {
464 return LoadBaseIndexedDisp(cu, rBase, r_index, scale, 0,
465 r_dest, INVALID_REG, size, INVALID_SREG);
jeffhao5772bab2012-05-18 11:51:26 -0700466}
467
buzbee02031b12012-11-23 09:41:35 -0800468LIR* X86Codegen::LoadBaseDisp(CompilationUnit *cu, int rBase, int displacement,
buzbeefa57c472012-11-21 12:06:18 -0800469 int r_dest, OpSize size, int s_reg) {
470 return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
471 r_dest, INVALID_REG, size, s_reg);
buzbeee88dfbf2012-03-05 11:19:57 -0800472}
473
buzbee02031b12012-11-23 09:41:35 -0800474LIR* X86Codegen::LoadBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
buzbeefa57c472012-11-21 12:06:18 -0800475 int r_dest_lo, int r_dest_hi, int s_reg) {
476 return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
477 r_dest_lo, r_dest_hi, kLong, s_reg);
buzbeee88dfbf2012-03-05 11:19:57 -0800478}
479
buzbee02031b12012-11-23 09:41:35 -0800480LIR* X86Codegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
481 int displacement, int r_src, int r_src_hi, OpSize size,
482 int s_reg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800483 LIR *store = NULL;
jeffhaoe2962482012-06-28 11:29:57 -0700484 LIR *store2 = NULL;
buzbeefa57c472012-11-21 12:06:18 -0800485 bool is_array = r_index != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800486 bool pair = false;
jeffhaoe2962482012-06-28 11:29:57 -0700487 bool is64bit = false;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700488 X86OpCode opcode = kX86Nop;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800489 switch (size) {
490 case kLong:
491 case kDouble:
jeffhaoe2962482012-06-28 11:29:57 -0700492 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800493 if (X86_FPREG(r_src)) {
494 opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
495 if (X86_SINGLEREG(r_src)) {
496 DCHECK(X86_FPREG(r_src_hi));
497 DCHECK_EQ(r_src, (r_src_hi - 1));
498 r_src = S2d(r_src, r_src_hi);
buzbeee88dfbf2012-03-05 11:19:57 -0800499 }
buzbeefa57c472012-11-21 12:06:18 -0800500 r_src_hi = r_src + 1;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800501 } else {
502 pair = true;
buzbeefa57c472012-11-21 12:06:18 -0800503 opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800504 }
505 // TODO: double store is to unaligned address
506 DCHECK_EQ((displacement & 0x3), 0);
507 break;
508 case kWord:
509 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800510 opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
511 if (X86_FPREG(r_src)) {
512 opcode = is_array ? kX86MovssAR : kX86MovssMR;
513 DCHECK(X86_SINGLEREG(r_src));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800514 }
515 DCHECK_EQ((displacement & 0x3), 0);
516 break;
517 case kUnsignedHalf:
518 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800519 opcode = is_array ? kX86Mov16AR : kX86Mov16MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800520 DCHECK_EQ((displacement & 0x1), 0);
521 break;
522 case kUnsignedByte:
523 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800524 opcode = is_array ? kX86Mov8AR : kX86Mov8MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800525 break;
526 default:
buzbee52a77fc2012-11-20 19:50:46 -0800527 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800528 }
buzbeee88dfbf2012-03-05 11:19:57 -0800529
buzbeefa57c472012-11-21 12:06:18 -0800530 if (!is_array) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700531 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800532 store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700533 } else {
buzbeefa57c472012-11-21 12:06:18 -0800534 store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src);
535 store2 = NewLIR3(cu, opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi);
jeffhaoe2962482012-06-28 11:29:57 -0700536 }
buzbeef0504cd2012-11-13 16:31:10 -0800537 if (rBase == rX86_SP) {
buzbee02031b12012-11-23 09:41:35 -0800538 AnnotateDalvikRegAccess(cu, store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
539 false /* is_load */, is64bit);
jeffhaoe2962482012-06-28 11:29:57 -0700540 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800541 AnnotateDalvikRegAccess(cu, store2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800542 false /* is_load */, is64bit);
jeffhaoe2962482012-06-28 11:29:57 -0700543 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700544 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800545 } else {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700546 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800547 store = NewLIR5(cu, opcode, rBase, r_index, scale,
548 displacement + LOWORD_OFFSET, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700549 } else {
buzbeefa57c472012-11-21 12:06:18 -0800550 store = NewLIR5(cu, opcode, rBase, r_index, scale,
551 displacement + LOWORD_OFFSET, r_src);
552 store2 = NewLIR5(cu, opcode, rBase, r_index, scale,
553 displacement + HIWORD_OFFSET, r_src_hi);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800554 }
555 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700556
557 return store;
buzbeee88dfbf2012-03-05 11:19:57 -0800558}
559
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700560/* store value base base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800561LIR* X86Codegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_src,
Bill Buzbeea114add2012-05-03 15:00:40 -0700562 int scale, OpSize size)
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700563{
buzbeefa57c472012-11-21 12:06:18 -0800564 return StoreBaseIndexedDisp(cu, rBase, r_index, scale, 0,
565 r_src, INVALID_REG, size, INVALID_SREG);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700566}
567
buzbee02031b12012-11-23 09:41:35 -0800568LIR* X86Codegen::StoreBaseDisp(CompilationUnit *cu, int rBase, int displacement,
569 int r_src, OpSize size)
Bill Buzbeea114add2012-05-03 15:00:40 -0700570{
buzbeefa57c472012-11-21 12:06:18 -0800571 return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0,
572 displacement, r_src, INVALID_REG, size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700573 INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800574}
575
buzbee02031b12012-11-23 09:41:35 -0800576LIR* X86Codegen::StoreBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
577 int r_src_lo, int r_src_hi)
Bill Buzbeea114add2012-05-03 15:00:40 -0700578{
buzbeefa57c472012-11-21 12:06:18 -0800579 return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
580 r_src_lo, r_src_hi, kLong, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800581}
582
buzbeee88dfbf2012-03-05 11:19:57 -0800583} // namespace art