blob: bdbc54767fbd890fc93d5305aca28ea09e20f20a [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
buzbee1bc37c62012-11-20 13:35:41 -080017#include "x86_lir.h"
buzbee02031b12012-11-23 09:41:35 -080018#include "codegen_x86.h"
buzbee1bc37c62012-11-20 13:35:41 -080019#include "../codegen_util.h"
20#include "../ralloc_util.h"
21
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
53/*
54 * Load a immediate using a shortcut if possible; otherwise
55 * grab from the per-translation literal pool. If target is
56 * a high register, build constant into a low register and copy.
57 *
58 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -080059 * 1) r_dest is freshly returned from AllocTemp or
buzbeee88dfbf2012-03-05 11:19:57 -080060 * 2) The codegen is under fixed register usage
61 */
buzbee02031b12012-11-23 09:41:35 -080062LIR* X86Codegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int value)
Bill Buzbeea114add2012-05-03 15:00:40 -070063{
buzbeefa57c472012-11-21 12:06:18 -080064 int r_dest_save = r_dest;
65 if (X86_FPREG(r_dest)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -070066 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -080067 return NewLIR2(cu, kX86XorpsRR, r_dest, r_dest);
Ian Rogersb41b33b2012-03-20 14:22:54 -070068 }
buzbeefa57c472012-11-21 12:06:18 -080069 DCHECK(X86_SINGLEREG(r_dest));
70 r_dest = AllocTemp(cu);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070071 }
buzbeee88dfbf2012-03-05 11:19:57 -080072
Ian Rogersb41b33b2012-03-20 14:22:54 -070073 LIR *res;
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070074 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -080075 res = NewLIR2(cu, kX86Xor32RR, r_dest, r_dest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070076 } else {
Ian Rogers2e9f7ed2012-09-26 11:30:43 -070077 // Note, there is no byte immediate form of a 32 bit immediate move.
buzbeefa57c472012-11-21 12:06:18 -080078 res = NewLIR2(cu, kX86Mov32RI, r_dest, value);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070079 }
buzbeee88dfbf2012-03-05 11:19:57 -080080
buzbeefa57c472012-11-21 12:06:18 -080081 if (X86_FPREG(r_dest_save)) {
82 NewLIR2(cu, kX86MovdxrRR, r_dest_save, r_dest);
83 FreeTemp(cu, r_dest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070084 }
buzbeee88dfbf2012-03-05 11:19:57 -080085
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070086 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080087}
88
buzbee02031b12012-11-23 09:41:35 -080089LIR* X86Codegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
Bill Buzbeea114add2012-05-03 15:00:40 -070090{
buzbee02031b12012-11-23 09:41:35 -080091 LIR* res = NewLIR1(cu, kX86Jmp8, 0 /* offset to be patched during assembly*/ );
92 res->target = target;
93 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080094}
95
buzbee02031b12012-11-23 09:41:35 -080096LIR* X86Codegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbeea7678db2012-03-05 15:35:46 -080097{
buzbeefa57c472012-11-21 12:06:18 -080098 LIR* branch = NewLIR2(cu, kX86Jcc8, 0 /* offset to be patched */,
buzbee52a77fc2012-11-20 19:50:46 -080099 X86ConditionEncoding(cc));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800100 branch->target = target;
101 return branch;
buzbeea7678db2012-03-05 15:35:46 -0800102}
103
buzbee02031b12012-11-23 09:41:35 -0800104LIR* X86Codegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src)
Bill Buzbeea114add2012-05-03 15:00:40 -0700105{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800106 X86OpCode opcode = kX86Bkpt;
107 switch (op) {
108 case kOpNeg: opcode = kX86Neg32R; break;
jeffhao1395b1e2012-06-13 18:05:13 -0700109 case kOpNot: opcode = kX86Not32R; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800110 case kOpBlx: opcode = kX86CallR; break;
111 default:
buzbee52a77fc2012-11-20 19:50:46 -0800112 LOG(FATAL) << "Bad case in OpReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800113 }
buzbeefa57c472012-11-21 12:06:18 -0800114 return NewLIR1(cu, opcode, r_dest_src);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800115}
116
buzbee02031b12012-11-23 09:41:35 -0800117LIR* X86Codegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1, int value)
Bill Buzbeea114add2012-05-03 15:00:40 -0700118{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800119 X86OpCode opcode = kX86Bkpt;
buzbeefa57c472012-11-21 12:06:18 -0800120 bool byte_imm = IS_SIMM8(value);
121 DCHECK(!X86_FPREG(r_dest_src1));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800122 switch (op) {
123 case kOpLsl: opcode = kX86Sal32RI; break;
124 case kOpLsr: opcode = kX86Shr32RI; break;
125 case kOpAsr: opcode = kX86Sar32RI; break;
buzbeefa57c472012-11-21 12:06:18 -0800126 case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
127 case kOpOr: opcode = byte_imm ? kX86Or32RI8 : kX86Or32RI; break;
128 case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800129 //case kOpSbb: opcode = kX86Sbb32RI; break;
buzbeefa57c472012-11-21 12:06:18 -0800130 case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
131 case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
132 case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
133 case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
134 case kOpMov: return LoadConstantNoClobber(cu, r_dest_src1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800135 case kOpMul:
buzbeefa57c472012-11-21 12:06:18 -0800136 opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
137 return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800138 default:
buzbee52a77fc2012-11-20 19:50:46 -0800139 LOG(FATAL) << "Bad case in OpRegImm " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800140 }
buzbeefa57c472012-11-21 12:06:18 -0800141 return NewLIR2(cu, opcode, r_dest_src1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800142}
143
buzbee02031b12012-11-23 09:41:35 -0800144LIR* X86Codegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r_src2)
buzbeee88dfbf2012-03-05 11:19:57 -0800145{
buzbeea7678db2012-03-05 15:35:46 -0800146 X86OpCode opcode = kX86Nop;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700147 bool src2_must_be_cx = false;
buzbeee88dfbf2012-03-05 11:19:57 -0800148 switch (op) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800149 // X86 unary opcodes
150 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800151 OpRegCopy(cu, r_dest_src1, r_src2);
152 return OpReg(cu, kOpNot, r_dest_src1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800153 case kOpNeg:
buzbeefa57c472012-11-21 12:06:18 -0800154 OpRegCopy(cu, r_dest_src1, r_src2);
155 return OpReg(cu, kOpNeg, r_dest_src1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800156 // X86 binary opcodes
157 case kOpSub: opcode = kX86Sub32RR; break;
158 case kOpSbc: opcode = kX86Sbb32RR; break;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700159 case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
160 case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
161 case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800162 case kOpMov: opcode = kX86Mov32RR; break;
163 case kOpCmp: opcode = kX86Cmp32RR; break;
164 case kOpAdd: opcode = kX86Add32RR; break;
165 case kOpAdc: opcode = kX86Adc32RR; break;
166 case kOpAnd: opcode = kX86And32RR; break;
167 case kOpOr: opcode = kX86Or32RR; break;
168 case kOpXor: opcode = kX86Xor32RR; break;
jeffhao703f2cd2012-07-13 17:25:52 -0700169 case kOp2Byte:
170 // Use shifts instead of a byte operand if the source can't be byte accessed.
buzbeefa57c472012-11-21 12:06:18 -0800171 if (r_src2 >= 4) {
172 NewLIR2(cu, kX86Mov32RR, r_dest_src1, r_src2);
173 NewLIR2(cu, kX86Sal32RI, r_dest_src1, 24);
174 return NewLIR2(cu, kX86Sar32RI, r_dest_src1, 24);
jeffhao703f2cd2012-07-13 17:25:52 -0700175 } else {
176 opcode = kX86Movsx8RR;
177 }
178 break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800179 case kOp2Short: opcode = kX86Movsx16RR; break;
180 case kOp2Char: opcode = kX86Movzx16RR; break;
181 case kOpMul: opcode = kX86Imul32RR; break;
182 default:
buzbee52a77fc2012-11-20 19:50:46 -0800183 LOG(FATAL) << "Bad case in OpRegReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800184 break;
buzbeee88dfbf2012-03-05 11:19:57 -0800185 }
buzbeefa57c472012-11-21 12:06:18 -0800186 CHECK(!src2_must_be_cx || r_src2 == rCX);
187 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800188}
189
buzbee02031b12012-11-23 09:41:35 -0800190LIR* X86Codegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700191 int offset)
192{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800193 X86OpCode opcode = kX86Nop;
194 switch (op) {
195 // X86 binary opcodes
196 case kOpSub: opcode = kX86Sub32RM; break;
197 case kOpMov: opcode = kX86Mov32RM; break;
198 case kOpCmp: opcode = kX86Cmp32RM; break;
199 case kOpAdd: opcode = kX86Add32RM; break;
200 case kOpAnd: opcode = kX86And32RM; break;
201 case kOpOr: opcode = kX86Or32RM; break;
202 case kOpXor: opcode = kX86Xor32RM; break;
203 case kOp2Byte: opcode = kX86Movsx8RM; break;
204 case kOp2Short: opcode = kX86Movsx16RM; break;
205 case kOp2Char: opcode = kX86Movzx16RM; break;
206 case kOpMul:
207 default:
buzbee52a77fc2012-11-20 19:50:46 -0800208 LOG(FATAL) << "Bad case in OpRegMem " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800209 break;
210 }
buzbeefa57c472012-11-21 12:06:18 -0800211 return NewLIR3(cu, opcode, r_dest, rBase, offset);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800212}
213
buzbee02031b12012-11-23 09:41:35 -0800214LIR* X86Codegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_src1,
buzbeefa57c472012-11-21 12:06:18 -0800215 int r_src2)
Bill Buzbeea114add2012-05-03 15:00:40 -0700216{
buzbeefa57c472012-11-21 12:06:18 -0800217 if (r_dest != r_src1 && r_dest != r_src2) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800218 if (op == kOpAdd) { // lea special case, except can't encode rbp as base
buzbeefa57c472012-11-21 12:06:18 -0800219 if (r_src1 == r_src2) {
220 OpRegCopy(cu, r_dest, r_src1);
221 return OpRegImm(cu, kOpLsl, r_dest, 1);
222 } else if (r_src1 != rBP) {
223 return NewLIR5(cu, kX86Lea32RA, r_dest, r_src1 /* base */,
224 r_src2 /* index */, 0 /* scale */, 0 /* disp */);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800225 } else {
buzbeefa57c472012-11-21 12:06:18 -0800226 return NewLIR5(cu, kX86Lea32RA, r_dest, r_src2 /* base */,
227 r_src1 /* index */, 0 /* scale */, 0 /* disp */);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800228 }
229 } else {
buzbeefa57c472012-11-21 12:06:18 -0800230 OpRegCopy(cu, r_dest, r_src1);
231 return OpRegReg(cu, op, r_dest, r_src2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800232 }
buzbeefa57c472012-11-21 12:06:18 -0800233 } else if (r_dest == r_src1) {
234 return OpRegReg(cu, op, r_dest, r_src2);
235 } else { // r_dest == r_src2
Ian Rogersb5d09b22012-03-06 22:14:17 -0800236 switch (op) {
237 case kOpSub: // non-commutative
buzbeefa57c472012-11-21 12:06:18 -0800238 OpReg(cu, kOpNeg, r_dest);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800239 op = kOpAdd;
240 break;
241 case kOpSbc:
242 case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
buzbeefa57c472012-11-21 12:06:18 -0800243 int t_reg = AllocTemp(cu);
244 OpRegCopy(cu, t_reg, r_src1);
245 OpRegReg(cu, op, t_reg, r_src2);
246 LIR* res = OpRegCopy(cu, r_dest, t_reg);
247 FreeTemp(cu, t_reg);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800248 return res;
249 }
250 case kOpAdd: // commutative
251 case kOpOr:
252 case kOpAdc:
253 case kOpAnd:
254 case kOpXor:
255 break;
256 default:
buzbee52a77fc2012-11-20 19:50:46 -0800257 LOG(FATAL) << "Bad case in OpRegRegReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800258 }
buzbeefa57c472012-11-21 12:06:18 -0800259 return OpRegReg(cu, op, r_dest, r_src1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800260 }
261}
262
buzbee02031b12012-11-23 09:41:35 -0800263LIR* X86Codegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_src,
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 int value)
265{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800266 if (op == kOpMul) {
267 X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
buzbeefa57c472012-11-21 12:06:18 -0800268 return NewLIR3(cu, opcode, r_dest, r_src, value);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700269 } else if (op == kOpAnd) {
buzbeefa57c472012-11-21 12:06:18 -0800270 if (value == 0xFF && r_src < 4) {
271 return NewLIR2(cu, kX86Movzx8RR, r_dest, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700272 } else if (value == 0xFFFF) {
buzbeefa57c472012-11-21 12:06:18 -0800273 return NewLIR2(cu, kX86Movzx16RR, r_dest, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700274 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800275 }
buzbeefa57c472012-11-21 12:06:18 -0800276 if (r_dest != r_src) {
Ian Rogers7caad772012-03-30 01:07:54 -0700277 if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
278 // TODO: fix bug in LEA encoding when disp == 0
buzbeefa57c472012-11-21 12:06:18 -0800279 return NewLIR5(cu, kX86Lea32RA, r_dest, r5sib_no_base /* base */,
280 r_src /* index */, value /* scale */, 0 /* disp */);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700281 } else if (op == kOpAdd) { // lea add special case
buzbeefa57c472012-11-21 12:06:18 -0800282 return NewLIR5(cu, kX86Lea32RA, r_dest, r_src /* base */,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800283 r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
284 }
buzbeefa57c472012-11-21 12:06:18 -0800285 OpRegCopy(cu, r_dest, r_src);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800286 }
buzbeefa57c472012-11-21 12:06:18 -0800287 return OpRegImm(cu, op, r_dest, value);
buzbeee88dfbf2012-03-05 11:19:57 -0800288}
289
buzbee02031b12012-11-23 09:41:35 -0800290LIR* X86Codegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
Bill Buzbeea114add2012-05-03 15:00:40 -0700291{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700292 X86OpCode opcode = kX86Bkpt;
293 switch (op) {
294 case kOpBlx: opcode = kX86CallT; break;
295 default:
296 LOG(FATAL) << "Bad opcode: " << op;
297 break;
298 }
buzbeefa57c472012-11-21 12:06:18 -0800299 return NewLIR1(cu, opcode, thread_offset);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700300}
301
buzbee02031b12012-11-23 09:41:35 -0800302LIR* X86Codegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
Bill Buzbeea114add2012-05-03 15:00:40 -0700303{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700304 X86OpCode opcode = kX86Bkpt;
305 switch (op) {
306 case kOpBlx: opcode = kX86CallM; break;
307 default:
308 LOG(FATAL) << "Bad opcode: " << op;
309 break;
310 }
buzbeefa57c472012-11-21 12:06:18 -0800311 return NewLIR2(cu, opcode, rBase, disp);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700312}
313
buzbee02031b12012-11-23 09:41:35 -0800314LIR* X86Codegen::LoadConstantValueWide(CompilationUnit *cu, int r_dest_lo,
315 int r_dest_hi, int val_lo, int val_hi)
buzbeee88dfbf2012-03-05 11:19:57 -0800316{
317 LIR *res;
buzbeefa57c472012-11-21 12:06:18 -0800318 if (X86_FPREG(r_dest_lo)) {
319 DCHECK(X86_FPREG(r_dest_hi)); // ignore r_dest_hi
320 if (val_lo == 0 && val_hi == 0) {
321 return NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700322 } else {
buzbeefa57c472012-11-21 12:06:18 -0800323 if (val_lo == 0) {
324 res = NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700325 } else {
buzbeefa57c472012-11-21 12:06:18 -0800326 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700327 }
buzbeefa57c472012-11-21 12:06:18 -0800328 if (val_hi != 0) {
329 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
330 NewLIR2(cu, kX86PsllqRI, r_dest_hi, 32);
331 NewLIR2(cu, kX86OrpsRR, r_dest_lo, r_dest_hi);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700332 }
333 }
334 } else {
buzbeefa57c472012-11-21 12:06:18 -0800335 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
336 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700337 }
buzbeee88dfbf2012-03-05 11:19:57 -0800338 return res;
339}
340
buzbee02031b12012-11-23 09:41:35 -0800341LIR* X86Codegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
342 int displacement, int r_dest, int r_dest_hi, OpSize size,
343 int s_reg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800344 LIR *load = NULL;
345 LIR *load2 = NULL;
buzbeefa57c472012-11-21 12:06:18 -0800346 bool is_array = r_index != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800347 bool pair = false;
348 bool is64bit = false;
349 X86OpCode opcode = kX86Nop;
350 switch (size) {
351 case kLong:
352 case kDouble:
353 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800354 if (X86_FPREG(r_dest)) {
355 opcode = is_array ? kX86MovsdRA : kX86MovsdRM;
356 if (X86_SINGLEREG(r_dest)) {
357 DCHECK(X86_FPREG(r_dest_hi));
358 DCHECK_EQ(r_dest, (r_dest_hi - 1));
359 r_dest = S2d(r_dest, r_dest_hi);
buzbeee88dfbf2012-03-05 11:19:57 -0800360 }
buzbeefa57c472012-11-21 12:06:18 -0800361 r_dest_hi = r_dest + 1;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800362 } else {
363 pair = true;
buzbeefa57c472012-11-21 12:06:18 -0800364 opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800365 }
366 // TODO: double store is to unaligned address
367 DCHECK_EQ((displacement & 0x3), 0);
368 break;
369 case kWord:
370 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800371 opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
372 if (X86_FPREG(r_dest)) {
373 opcode = is_array ? kX86MovssRA : kX86MovssRM;
374 DCHECK(X86_SINGLEREG(r_dest));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800375 }
376 DCHECK_EQ((displacement & 0x3), 0);
377 break;
378 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800379 opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800380 DCHECK_EQ((displacement & 0x1), 0);
381 break;
382 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800383 opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800384 DCHECK_EQ((displacement & 0x1), 0);
385 break;
386 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800387 opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800388 break;
389 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800390 opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800391 break;
392 default:
buzbee52a77fc2012-11-20 19:50:46 -0800393 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800394 }
395
buzbeefa57c472012-11-21 12:06:18 -0800396 if (!is_array) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800397 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800398 load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
buzbeee88dfbf2012-03-05 11:19:57 -0800399 } else {
buzbeefa57c472012-11-21 12:06:18 -0800400 if (rBase == r_dest) {
401 load2 = NewLIR3(cu, opcode, r_dest_hi, rBase,
jeffhaofdffdf82012-07-11 16:08:43 -0700402 displacement + HIWORD_OFFSET);
buzbeefa57c472012-11-21 12:06:18 -0800403 load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
jeffhaofdffdf82012-07-11 16:08:43 -0700404 } else {
buzbeefa57c472012-11-21 12:06:18 -0800405 load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
406 load2 = NewLIR3(cu, opcode, r_dest_hi, rBase,
jeffhaofdffdf82012-07-11 16:08:43 -0700407 displacement + HIWORD_OFFSET);
408 }
buzbeee88dfbf2012-03-05 11:19:57 -0800409 }
buzbeef0504cd2012-11-13 16:31:10 -0800410 if (rBase == rX86_SP) {
buzbee02031b12012-11-23 09:41:35 -0800411 AnnotateDalvikRegAccess(cu, load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
412 true /* is_load */, is64bit);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700413 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800414 AnnotateDalvikRegAccess(cu, load2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800415 true /* is_load */, is64bit);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800416 }
buzbeee88dfbf2012-03-05 11:19:57 -0800417 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800418 } else {
419 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800420 load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
Bill Buzbeea114add2012-05-03 15:00:40 -0700421 displacement + LOWORD_OFFSET);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800422 } else {
buzbeefa57c472012-11-21 12:06:18 -0800423 if (rBase == r_dest) {
424 load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700425 displacement + HIWORD_OFFSET);
buzbeefa57c472012-11-21 12:06:18 -0800426 load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700427 displacement + LOWORD_OFFSET);
428 } else {
buzbeefa57c472012-11-21 12:06:18 -0800429 load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700430 displacement + LOWORD_OFFSET);
buzbeefa57c472012-11-21 12:06:18 -0800431 load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700432 displacement + HIWORD_OFFSET);
433 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800434 }
435 }
436
437 return load;
buzbeee88dfbf2012-03-05 11:19:57 -0800438}
439
jeffhao5772bab2012-05-18 11:51:26 -0700440/* Load value from base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800441LIR* X86Codegen::LoadBaseIndexed(CompilationUnit *cu, int rBase,
buzbeefa57c472012-11-21 12:06:18 -0800442 int r_index, int r_dest, int scale, OpSize size) {
443 return LoadBaseIndexedDisp(cu, rBase, r_index, scale, 0,
444 r_dest, INVALID_REG, size, INVALID_SREG);
jeffhao5772bab2012-05-18 11:51:26 -0700445}
446
buzbee02031b12012-11-23 09:41:35 -0800447LIR* X86Codegen::LoadBaseDisp(CompilationUnit *cu, int rBase, int displacement,
buzbeefa57c472012-11-21 12:06:18 -0800448 int r_dest, OpSize size, int s_reg) {
449 return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
450 r_dest, INVALID_REG, size, s_reg);
buzbeee88dfbf2012-03-05 11:19:57 -0800451}
452
buzbee02031b12012-11-23 09:41:35 -0800453LIR* X86Codegen::LoadBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
buzbeefa57c472012-11-21 12:06:18 -0800454 int r_dest_lo, int r_dest_hi, int s_reg) {
455 return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
456 r_dest_lo, r_dest_hi, kLong, s_reg);
buzbeee88dfbf2012-03-05 11:19:57 -0800457}
458
buzbee02031b12012-11-23 09:41:35 -0800459LIR* X86Codegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
460 int displacement, int r_src, int r_src_hi, OpSize size,
461 int s_reg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800462 LIR *store = NULL;
jeffhaoe2962482012-06-28 11:29:57 -0700463 LIR *store2 = NULL;
buzbeefa57c472012-11-21 12:06:18 -0800464 bool is_array = r_index != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800465 bool pair = false;
jeffhaoe2962482012-06-28 11:29:57 -0700466 bool is64bit = false;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700467 X86OpCode opcode = kX86Nop;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800468 switch (size) {
469 case kLong:
470 case kDouble:
jeffhaoe2962482012-06-28 11:29:57 -0700471 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800472 if (X86_FPREG(r_src)) {
473 opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
474 if (X86_SINGLEREG(r_src)) {
475 DCHECK(X86_FPREG(r_src_hi));
476 DCHECK_EQ(r_src, (r_src_hi - 1));
477 r_src = S2d(r_src, r_src_hi);
buzbeee88dfbf2012-03-05 11:19:57 -0800478 }
buzbeefa57c472012-11-21 12:06:18 -0800479 r_src_hi = r_src + 1;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800480 } else {
481 pair = true;
buzbeefa57c472012-11-21 12:06:18 -0800482 opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800483 }
484 // TODO: double store is to unaligned address
485 DCHECK_EQ((displacement & 0x3), 0);
486 break;
487 case kWord:
488 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800489 opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
490 if (X86_FPREG(r_src)) {
491 opcode = is_array ? kX86MovssAR : kX86MovssMR;
492 DCHECK(X86_SINGLEREG(r_src));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800493 }
494 DCHECK_EQ((displacement & 0x3), 0);
495 break;
496 case kUnsignedHalf:
497 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800498 opcode = is_array ? kX86Mov16AR : kX86Mov16MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800499 DCHECK_EQ((displacement & 0x1), 0);
500 break;
501 case kUnsignedByte:
502 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800503 opcode = is_array ? kX86Mov8AR : kX86Mov8MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800504 break;
505 default:
buzbee52a77fc2012-11-20 19:50:46 -0800506 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800507 }
buzbeee88dfbf2012-03-05 11:19:57 -0800508
buzbeefa57c472012-11-21 12:06:18 -0800509 if (!is_array) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700510 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800511 store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700512 } else {
buzbeefa57c472012-11-21 12:06:18 -0800513 store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src);
514 store2 = NewLIR3(cu, opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi);
jeffhaoe2962482012-06-28 11:29:57 -0700515 }
buzbeef0504cd2012-11-13 16:31:10 -0800516 if (rBase == rX86_SP) {
buzbee02031b12012-11-23 09:41:35 -0800517 AnnotateDalvikRegAccess(cu, store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
518 false /* is_load */, is64bit);
jeffhaoe2962482012-06-28 11:29:57 -0700519 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800520 AnnotateDalvikRegAccess(cu, store2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800521 false /* is_load */, is64bit);
jeffhaoe2962482012-06-28 11:29:57 -0700522 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700523 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800524 } else {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700525 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800526 store = NewLIR5(cu, opcode, rBase, r_index, scale,
527 displacement + LOWORD_OFFSET, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700528 } else {
buzbeefa57c472012-11-21 12:06:18 -0800529 store = NewLIR5(cu, opcode, rBase, r_index, scale,
530 displacement + LOWORD_OFFSET, r_src);
531 store2 = NewLIR5(cu, opcode, rBase, r_index, scale,
532 displacement + HIWORD_OFFSET, r_src_hi);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800533 }
534 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700535
536 return store;
buzbeee88dfbf2012-03-05 11:19:57 -0800537}
538
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700539/* store value base base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800540LIR* X86Codegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_src,
Bill Buzbeea114add2012-05-03 15:00:40 -0700541 int scale, OpSize size)
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700542{
buzbeefa57c472012-11-21 12:06:18 -0800543 return StoreBaseIndexedDisp(cu, rBase, r_index, scale, 0,
544 r_src, INVALID_REG, size, INVALID_SREG);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700545}
546
buzbee02031b12012-11-23 09:41:35 -0800547LIR* X86Codegen::StoreBaseDisp(CompilationUnit *cu, int rBase, int displacement,
548 int r_src, OpSize size)
Bill Buzbeea114add2012-05-03 15:00:40 -0700549{
buzbeefa57c472012-11-21 12:06:18 -0800550 return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0,
551 displacement, r_src, INVALID_REG, size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700552 INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800553}
554
buzbee02031b12012-11-23 09:41:35 -0800555LIR* X86Codegen::StoreBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
556 int r_src_lo, int r_src_hi)
Bill Buzbeea114add2012-05-03 15:00:40 -0700557{
buzbeefa57c472012-11-21 12:06:18 -0800558 return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
559 r_src_lo, r_src_hi, kLong, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800560}
561
buzbee02031b12012-11-23 09:41:35 -0800562void X86Codegen::LoadPair(CompilationUnit *cu, int base, int low_reg, int high_reg)
buzbeee88dfbf2012-03-05 11:19:57 -0800563{
buzbeefa57c472012-11-21 12:06:18 -0800564 LoadBaseDispWide(cu, base, 0, low_reg, high_reg, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800565}
566
567} // namespace art