blob: 9d24dda38f4eac66fee27b1b53634757e41f1ea9 [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"
18#include "../codegen_util.h"
19#include "../ralloc_util.h"
20
buzbeee88dfbf2012-03-05 11:19:57 -080021namespace art {
22
buzbeeb046e162012-10-30 15:48:42 -070023/* This file contains codegen for the X86 ISA */
buzbeee88dfbf2012-03-05 11:19:57 -080024
buzbeee88dfbf2012-03-05 11:19:57 -080025void genBarrier(CompilationUnit *cUnit);
buzbeee88dfbf2012-03-05 11:19:57 -080026void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
27LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
28 int rDest);
29LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
30 int displacement, int rSrc);
31LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
32
33LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
34{
Bill Buzbeea114add2012-05-03 15:00:40 -070035 int opcode;
36 /* must be both DOUBLE or both not DOUBLE */
buzbeef0504cd2012-11-13 16:31:10 -080037 DCHECK_EQ(X86_DOUBLEREG(rDest), X86_DOUBLEREG(rSrc));
38 if (X86_DOUBLEREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070039 opcode = kX86MovsdRR;
40 } else {
buzbeef0504cd2012-11-13 16:31:10 -080041 if (X86_SINGLEREG(rDest)) {
42 if (X86_SINGLEREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070043 opcode = kX86MovssRR;
44 } else { // Fpr <- Gpr
45 opcode = kX86MovdxrRR;
46 }
47 } else { // Gpr <- Fpr
buzbeef0504cd2012-11-13 16:31:10 -080048 DCHECK(X86_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -070049 opcode = kX86MovdrxRR;
buzbeee88dfbf2012-03-05 11:19:57 -080050 }
Bill Buzbeea114add2012-05-03 15:00:40 -070051 }
buzbeeec137432012-11-13 12:13:16 -080052 DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
Bill Buzbeea114add2012-05-03 15:00:40 -070053 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
54 if (rDest == rSrc) {
55 res->flags.isNop = true;
56 }
57 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080058}
59
60/*
61 * Load a immediate using a shortcut if possible; otherwise
62 * grab from the per-translation literal pool. If target is
63 * a high register, build constant into a low register and copy.
64 *
65 * No additional register clobbering operation performed. Use this version when
66 * 1) rDest is freshly returned from oatAllocTemp or
67 * 2) The codegen is under fixed register usage
68 */
Bill Buzbeea114add2012-05-03 15:00:40 -070069LIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest, int value)
70{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070071 int rDestSave = rDest;
buzbeef0504cd2012-11-13 16:31:10 -080072 if (X86_FPREG(rDest)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -070073 if (value == 0) {
74 return newLIR2(cUnit, kX86XorpsRR, rDest, rDest);
75 }
buzbeef0504cd2012-11-13 16:31:10 -080076 DCHECK(X86_SINGLEREG(rDest));
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070077 rDest = oatAllocTemp(cUnit);
78 }
buzbeee88dfbf2012-03-05 11:19:57 -080079
Ian Rogersb41b33b2012-03-20 14:22:54 -070080 LIR *res;
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070081 if (value == 0) {
82 res = newLIR2(cUnit, kX86Xor32RR, rDest, rDest);
83 } else {
Ian Rogers2e9f7ed2012-09-26 11:30:43 -070084 // Note, there is no byte immediate form of a 32 bit immediate move.
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070085 res = newLIR2(cUnit, kX86Mov32RI, rDest, value);
86 }
buzbeee88dfbf2012-03-05 11:19:57 -080087
buzbeef0504cd2012-11-13 16:31:10 -080088 if (X86_FPREG(rDestSave)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -070089 newLIR2(cUnit, kX86MovdxrRR, rDestSave, rDest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070090 oatFreeTemp(cUnit, rDest);
91 }
buzbeee88dfbf2012-03-05 11:19:57 -080092
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070093 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080094}
95
Bill Buzbeea114add2012-05-03 15:00:40 -070096LIR* opBranchUnconditional(CompilationUnit *cUnit, OpKind op)
97{
Ian Rogersb5d09b22012-03-06 22:14:17 -080098 CHECK_EQ(op, kOpUncondBr);
Ian Rogersb41b33b2012-03-20 14:22:54 -070099 return newLIR1(cUnit, kX86Jmp8, 0 /* offset to be patched */ );
buzbeee88dfbf2012-03-05 11:19:57 -0800100}
101
102LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
103
Ian Rogersb5d09b22012-03-06 22:14:17 -0800104X86ConditionCode oatX86ConditionEncoding(ConditionCode cond);
buzbeea7678db2012-03-05 15:35:46 -0800105LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
106{
Ian Rogersb41b33b2012-03-20 14:22:54 -0700107 LIR* branch = newLIR2(cUnit, kX86Jcc8, 0 /* offset to be patched */,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800108 oatX86ConditionEncoding(cc));
109 branch->target = target;
110 return branch;
buzbeea7678db2012-03-05 15:35:46 -0800111}
112
Bill Buzbeea114add2012-05-03 15:00:40 -0700113LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
114{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800115 X86OpCode opcode = kX86Bkpt;
116 switch (op) {
117 case kOpNeg: opcode = kX86Neg32R; break;
jeffhao1395b1e2012-06-13 18:05:13 -0700118 case kOpNot: opcode = kX86Not32R; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800119 case kOpBlx: opcode = kX86CallR; break;
120 default:
121 LOG(FATAL) << "Bad case in opReg " << op;
122 }
123 return newLIR1(cUnit, opcode, rDestSrc);
124}
125
Bill Buzbeea114add2012-05-03 15:00:40 -0700126LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int value)
127{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800128 X86OpCode opcode = kX86Bkpt;
129 bool byteImm = IS_SIMM8(value);
buzbeef0504cd2012-11-13 16:31:10 -0800130 DCHECK(!X86_FPREG(rDestSrc1));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800131 switch (op) {
132 case kOpLsl: opcode = kX86Sal32RI; break;
133 case kOpLsr: opcode = kX86Shr32RI; break;
134 case kOpAsr: opcode = kX86Sar32RI; break;
135 case kOpAdd: opcode = byteImm ? kX86Add32RI8 : kX86Add32RI; break;
136 case kOpOr: opcode = byteImm ? kX86Or32RI8 : kX86Or32RI; break;
137 case kOpAdc: opcode = byteImm ? kX86Adc32RI8 : kX86Adc32RI; break;
138 //case kOpSbb: opcode = kX86Sbb32RI; break;
139 case kOpAnd: opcode = byteImm ? kX86And32RI8 : kX86And32RI; break;
140 case kOpSub: opcode = byteImm ? kX86Sub32RI8 : kX86Sub32RI; break;
141 case kOpXor: opcode = byteImm ? kX86Xor32RI8 : kX86Xor32RI; break;
142 case kOpCmp: opcode = byteImm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700143 case kOpMov: return loadConstantNoClobber(cUnit, rDestSrc1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800144 case kOpMul:
145 opcode = byteImm ? kX86Imul32RRI8 : kX86Imul32RRI;
146 return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, value);
147 default:
148 LOG(FATAL) << "Bad case in opRegImm " << op;
149 }
150 return newLIR2(cUnit, opcode, rDestSrc1, value);
151}
152
153LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2)
buzbeee88dfbf2012-03-05 11:19:57 -0800154{
buzbeea7678db2012-03-05 15:35:46 -0800155 X86OpCode opcode = kX86Nop;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700156 bool src2_must_be_cx = false;
buzbeee88dfbf2012-03-05 11:19:57 -0800157 switch (op) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800158 // X86 unary opcodes
159 case kOpMvn:
160 opRegCopy(cUnit, rDestSrc1, rSrc2);
161 return opReg(cUnit, kOpNot, rDestSrc1);
162 case kOpNeg:
163 opRegCopy(cUnit, rDestSrc1, rSrc2);
164 return opReg(cUnit, kOpNeg, rDestSrc1);
165 // X86 binary opcodes
166 case kOpSub: opcode = kX86Sub32RR; break;
167 case kOpSbc: opcode = kX86Sbb32RR; break;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700168 case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
169 case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
170 case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800171 case kOpMov: opcode = kX86Mov32RR; break;
172 case kOpCmp: opcode = kX86Cmp32RR; break;
173 case kOpAdd: opcode = kX86Add32RR; break;
174 case kOpAdc: opcode = kX86Adc32RR; break;
175 case kOpAnd: opcode = kX86And32RR; break;
176 case kOpOr: opcode = kX86Or32RR; break;
177 case kOpXor: opcode = kX86Xor32RR; break;
jeffhao703f2cd2012-07-13 17:25:52 -0700178 case kOp2Byte:
179 // Use shifts instead of a byte operand if the source can't be byte accessed.
180 if (rSrc2 >= 4) {
181 newLIR2(cUnit, kX86Mov32RR, rDestSrc1, rSrc2);
182 newLIR2(cUnit, kX86Sal32RI, rDestSrc1, 24);
183 return newLIR2(cUnit, kX86Sar32RI, rDestSrc1, 24);
184 } else {
185 opcode = kX86Movsx8RR;
186 }
187 break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800188 case kOp2Short: opcode = kX86Movsx16RR; break;
189 case kOp2Char: opcode = kX86Movzx16RR; break;
190 case kOpMul: opcode = kX86Imul32RR; break;
191 default:
192 LOG(FATAL) << "Bad case in opRegReg " << op;
193 break;
buzbeee88dfbf2012-03-05 11:19:57 -0800194 }
Ian Rogersd36c52e2012-04-09 16:29:25 -0700195 CHECK(!src2_must_be_cx || rSrc2 == rCX);
buzbeee88dfbf2012-03-05 11:19:57 -0800196 return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800197}
198
Bill Buzbeea114add2012-05-03 15:00:40 -0700199LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase,
200 int offset)
201{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800202 X86OpCode opcode = kX86Nop;
203 switch (op) {
204 // X86 binary opcodes
205 case kOpSub: opcode = kX86Sub32RM; break;
206 case kOpMov: opcode = kX86Mov32RM; break;
207 case kOpCmp: opcode = kX86Cmp32RM; break;
208 case kOpAdd: opcode = kX86Add32RM; break;
209 case kOpAnd: opcode = kX86And32RM; break;
210 case kOpOr: opcode = kX86Or32RM; break;
211 case kOpXor: opcode = kX86Xor32RM; break;
212 case kOp2Byte: opcode = kX86Movsx8RM; break;
213 case kOp2Short: opcode = kX86Movsx16RM; break;
214 case kOp2Char: opcode = kX86Movzx16RM; break;
215 case kOpMul:
216 default:
jeffhao703f2cd2012-07-13 17:25:52 -0700217 LOG(FATAL) << "Bad case in opRegMem " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800218 break;
219 }
220 return newLIR3(cUnit, opcode, rDest, rBase, offset);
221}
222
Bill Buzbeea114add2012-05-03 15:00:40 -0700223LIR* opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc1,
224 int rSrc2)
225{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800226 if (rDest != rSrc1 && rDest != rSrc2) {
227 if (op == kOpAdd) { // lea special case, except can't encode rbp as base
228 if (rSrc1 == rSrc2) {
Ian Rogers7caad772012-03-30 01:07:54 -0700229 opRegCopy(cUnit, rDest, rSrc1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800230 return opRegImm(cUnit, kOpLsl, rDest, 1);
231 } else if (rSrc1 != rBP) {
232 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc1 /* base */,
233 rSrc2 /* index */, 0 /* scale */, 0 /* disp */);
234 } else {
235 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc2 /* base */,
236 rSrc1 /* index */, 0 /* scale */, 0 /* disp */);
237 }
238 } else {
239 opRegCopy(cUnit, rDest, rSrc1);
240 return opRegReg(cUnit, op, rDest, rSrc2);
241 }
242 } else if (rDest == rSrc1) {
243 return opRegReg(cUnit, op, rDest, rSrc2);
244 } else { // rDest == rSrc2
245 switch (op) {
246 case kOpSub: // non-commutative
247 opReg(cUnit, kOpNeg, rDest);
248 op = kOpAdd;
249 break;
250 case kOpSbc:
251 case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
252 int tReg = oatAllocTemp(cUnit);
253 opRegCopy(cUnit, tReg, rSrc1);
254 opRegReg(cUnit, op, tReg, rSrc2);
255 LIR* res = opRegCopy(cUnit, rDest, tReg);
256 oatFreeTemp(cUnit, tReg);
257 return res;
258 }
259 case kOpAdd: // commutative
260 case kOpOr:
261 case kOpAdc:
262 case kOpAnd:
263 case kOpXor:
264 break;
265 default:
266 LOG(FATAL) << "Bad case in opRegRegReg " << op;
267 }
268 return opRegReg(cUnit, op, rDest, rSrc1);
269 }
270}
271
Bill Buzbeea114add2012-05-03 15:00:40 -0700272LIR* opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc,
273 int value)
274{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800275 if (op == kOpMul) {
276 X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
277 return newLIR3(cUnit, opcode, rDest, rSrc, value);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700278 } else if (op == kOpAnd) {
jeffhao854029c2012-07-23 17:31:30 -0700279 if (value == 0xFF && rSrc < 4) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700280 return newLIR2(cUnit, kX86Movzx8RR, rDest, rSrc);
281 } else if (value == 0xFFFF) {
282 return newLIR2(cUnit, kX86Movzx16RR, rDest, rSrc);
283 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800284 }
285 if (rDest != rSrc) {
Ian Rogers7caad772012-03-30 01:07:54 -0700286 if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
287 // TODO: fix bug in LEA encoding when disp == 0
288 return newLIR5(cUnit, kX86Lea32RA, rDest, r5sib_no_base /* base */,
289 rSrc /* index */, value /* scale */, 0 /* disp */);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700290 } else if (op == kOpAdd) { // lea add special case
Ian Rogersb5d09b22012-03-06 22:14:17 -0800291 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc /* base */,
292 r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
293 }
294 opRegCopy(cUnit, rDest, rSrc);
295 }
296 return opRegImm(cUnit, op, rDest, value);
buzbeee88dfbf2012-03-05 11:19:57 -0800297}
298
Bill Buzbeea114add2012-05-03 15:00:40 -0700299LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset)
300{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700301 X86OpCode opcode = kX86Bkpt;
302 switch (op) {
303 case kOpBlx: opcode = kX86CallT; break;
304 default:
305 LOG(FATAL) << "Bad opcode: " << op;
306 break;
307 }
308 return newLIR1(cUnit, opcode, threadOffset);
309}
310
Bill Buzbeea114add2012-05-03 15:00:40 -0700311LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp)
312{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700313 X86OpCode opcode = kX86Bkpt;
314 switch (op) {
315 case kOpBlx: opcode = kX86CallM; break;
316 default:
317 LOG(FATAL) << "Bad opcode: " << op;
318 break;
319 }
320 return newLIR2(cUnit, opcode, rBase, disp);
321}
322
buzbeee88dfbf2012-03-05 11:19:57 -0800323LIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
Bill Buzbeea114add2012-05-03 15:00:40 -0700324 int rDestHi, int valLo, int valHi)
buzbeee88dfbf2012-03-05 11:19:57 -0800325{
326 LIR *res;
buzbeef0504cd2012-11-13 16:31:10 -0800327 if (X86_FPREG(rDestLo)) {
328 DCHECK(X86_FPREG(rDestHi)); // ignore rDestHi
Ian Rogersb41b33b2012-03-20 14:22:54 -0700329 if (valLo == 0 && valHi == 0) {
330 return newLIR2(cUnit, kX86XorpsRR, rDestLo, rDestLo);
331 } else {
332 if (valLo == 0) {
333 res = newLIR2(cUnit, kX86XorpsRR, rDestLo, rDestLo);
334 } else {
335 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
336 }
337 if (valHi != 0) {
338 loadConstantNoClobber(cUnit, rDestHi, valHi);
339 newLIR2(cUnit, kX86PsllqRI, rDestHi, 32);
340 newLIR2(cUnit, kX86OrpsRR, rDestLo, rDestHi);
341 }
342 }
343 } else {
344 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
345 loadConstantNoClobber(cUnit, rDestHi, valHi);
346 }
buzbeee88dfbf2012-03-05 11:19:57 -0800347 return res;
348}
349
buzbeee88dfbf2012-03-05 11:19:57 -0800350LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
351{
Ian Rogers474b6da2012-09-25 00:20:38 -0700352 UNIMPLEMENTED(FATAL) << "loadMultiple";
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 newLIR0(cUnit, kX86Bkpt);
354 return NULL;
buzbeee88dfbf2012-03-05 11:19:57 -0800355}
356
357LIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
358{
Ian Rogers474b6da2012-09-25 00:20:38 -0700359 UNIMPLEMENTED(FATAL) << "storeMultiple";
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 newLIR0(cUnit, kX86Bkpt);
361 return NULL;
buzbeee88dfbf2012-03-05 11:19:57 -0800362}
363
buzbee408ad162012-06-06 16:45:18 -0700364LIR* loadBaseIndexedDisp(CompilationUnit *cUnit,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800365 int rBase, int rIndex, int scale, int displacement,
366 int rDest, int rDestHi,
367 OpSize size, int sReg) {
368 LIR *load = NULL;
369 LIR *load2 = NULL;
370 bool isArray = rIndex != INVALID_REG;
371 bool pair = false;
372 bool is64bit = false;
373 X86OpCode opcode = kX86Nop;
374 switch (size) {
375 case kLong:
376 case kDouble:
377 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800378 if (X86_FPREG(rDest)) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800379 opcode = isArray ? kX86MovsdRA : kX86MovsdRM;
buzbeef0504cd2012-11-13 16:31:10 -0800380 if (X86_SINGLEREG(rDest)) {
381 DCHECK(X86_FPREG(rDestHi));
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700382 DCHECK_EQ(rDest, (rDestHi - 1));
buzbeef0504cd2012-11-13 16:31:10 -0800383 rDest = s2d(rDest, rDestHi);
buzbeee88dfbf2012-03-05 11:19:57 -0800384 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800385 rDestHi = rDest + 1;
386 } else {
387 pair = true;
388 opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
389 }
390 // TODO: double store is to unaligned address
391 DCHECK_EQ((displacement & 0x3), 0);
392 break;
393 case kWord:
394 case kSingle:
395 opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
buzbeef0504cd2012-11-13 16:31:10 -0800396 if (X86_FPREG(rDest)) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800397 opcode = isArray ? kX86MovssRA : kX86MovssRM;
buzbeef0504cd2012-11-13 16:31:10 -0800398 DCHECK(X86_SINGLEREG(rDest));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800399 }
400 DCHECK_EQ((displacement & 0x3), 0);
401 break;
402 case kUnsignedHalf:
403 opcode = isArray ? kX86Movzx16RA : kX86Movzx16RM;
404 DCHECK_EQ((displacement & 0x1), 0);
405 break;
406 case kSignedHalf:
407 opcode = isArray ? kX86Movsx16RA : kX86Movsx16RM;
408 DCHECK_EQ((displacement & 0x1), 0);
409 break;
410 case kUnsignedByte:
411 opcode = isArray ? kX86Movzx8RA : kX86Movzx8RM;
412 break;
413 case kSignedByte:
414 opcode = isArray ? kX86Movsx8RA : kX86Movsx8RM;
415 break;
416 default:
417 LOG(FATAL) << "Bad case in loadBaseIndexedDispBody";
418 }
419
420 if (!isArray) {
421 if (!pair) {
422 load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
buzbeee88dfbf2012-03-05 11:19:57 -0800423 } else {
jeffhaofdffdf82012-07-11 16:08:43 -0700424 if (rBase == rDest) {
425 load2 = newLIR3(cUnit, opcode, rDestHi, rBase,
426 displacement + HIWORD_OFFSET);
427 load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
428 } else {
429 load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
430 load2 = newLIR3(cUnit, opcode, rDestHi, rBase,
431 displacement + HIWORD_OFFSET);
432 }
buzbeee88dfbf2012-03-05 11:19:57 -0800433 }
buzbeef0504cd2012-11-13 16:31:10 -0800434 if (rBase == rX86_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700435 annotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0))
436 >> 2, true /* isLoad */, is64bit);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700437 if (pair) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800438 annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
439 true /* isLoad */, is64bit);
440 }
buzbeee88dfbf2012-03-05 11:19:57 -0800441 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800442 } else {
443 if (!pair) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale,
445 displacement + LOWORD_OFFSET);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800446 } else {
jeffhaofdffdf82012-07-11 16:08:43 -0700447 if (rBase == rDest) {
448 load2 = newLIR5(cUnit, opcode, rDestHi, rBase, rIndex, scale,
449 displacement + HIWORD_OFFSET);
450 load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale,
451 displacement + LOWORD_OFFSET);
452 } else {
453 load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale,
454 displacement + LOWORD_OFFSET);
455 load2 = newLIR5(cUnit, opcode, rDestHi, rBase, rIndex, scale,
456 displacement + HIWORD_OFFSET);
457 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800458 }
459 }
460
461 return load;
buzbeee88dfbf2012-03-05 11:19:57 -0800462}
463
jeffhao5772bab2012-05-18 11:51:26 -0700464/* Load value from base + scaled index. */
465LIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
466 int rIndex, int rDest, int scale, OpSize size) {
buzbee408ad162012-06-06 16:45:18 -0700467 return loadBaseIndexedDisp(cUnit, rBase, rIndex, scale, 0,
jeffhao5772bab2012-05-18 11:51:26 -0700468 rDest, INVALID_REG, size, INVALID_SREG);
469}
470
buzbee408ad162012-06-06 16:45:18 -0700471LIR *loadBaseDisp(CompilationUnit *cUnit,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800472 int rBase, int displacement,
473 int rDest,
474 OpSize size, int sReg) {
buzbee408ad162012-06-06 16:45:18 -0700475 return loadBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0, displacement,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800476 rDest, INVALID_REG, size, sReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800477}
478
buzbee408ad162012-06-06 16:45:18 -0700479LIR *loadBaseDispWide(CompilationUnit *cUnit,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800480 int rBase, int displacement,
481 int rDestLo, int rDestHi,
482 int sReg) {
buzbee408ad162012-06-06 16:45:18 -0700483 return loadBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0, displacement,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800484 rDestLo, rDestHi, kLong, sReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800485}
486
buzbee408ad162012-06-06 16:45:18 -0700487LIR* storeBaseIndexedDisp(CompilationUnit *cUnit,
Ian Rogersb41b33b2012-03-20 14:22:54 -0700488 int rBase, int rIndex, int scale, int displacement,
489 int rSrc, int rSrcHi,
490 OpSize size, int sReg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800491 LIR *store = NULL;
jeffhaoe2962482012-06-28 11:29:57 -0700492 LIR *store2 = NULL;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700493 bool isArray = rIndex != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800494 bool pair = false;
jeffhaoe2962482012-06-28 11:29:57 -0700495 bool is64bit = false;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700496 X86OpCode opcode = kX86Nop;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800497 switch (size) {
498 case kLong:
499 case kDouble:
jeffhaoe2962482012-06-28 11:29:57 -0700500 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800501 if (X86_FPREG(rSrc)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700502 opcode = isArray ? kX86MovsdAR : kX86MovsdMR;
buzbeef0504cd2012-11-13 16:31:10 -0800503 if (X86_SINGLEREG(rSrc)) {
504 DCHECK(X86_FPREG(rSrcHi));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800505 DCHECK_EQ(rSrc, (rSrcHi - 1));
buzbeef0504cd2012-11-13 16:31:10 -0800506 rSrc = s2d(rSrc, rSrcHi);
buzbeee88dfbf2012-03-05 11:19:57 -0800507 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800508 rSrcHi = rSrc + 1;
509 } else {
510 pair = true;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700511 opcode = isArray ? kX86Mov32AR : kX86Mov32MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800512 }
513 // TODO: double store is to unaligned address
514 DCHECK_EQ((displacement & 0x3), 0);
515 break;
516 case kWord:
517 case kSingle:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700518 opcode = isArray ? kX86Mov32AR : kX86Mov32MR;
buzbeef0504cd2012-11-13 16:31:10 -0800519 if (X86_FPREG(rSrc)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700520 opcode = isArray ? kX86MovssAR : kX86MovssMR;
buzbeef0504cd2012-11-13 16:31:10 -0800521 DCHECK(X86_SINGLEREG(rSrc));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800522 }
523 DCHECK_EQ((displacement & 0x3), 0);
524 break;
525 case kUnsignedHalf:
526 case kSignedHalf:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700527 opcode = isArray ? kX86Mov16AR : kX86Mov16MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800528 DCHECK_EQ((displacement & 0x1), 0);
529 break;
530 case kUnsignedByte:
531 case kSignedByte:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700532 opcode = isArray ? kX86Mov8AR : kX86Mov8MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800533 break;
534 default:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700535 LOG(FATAL) << "Bad case in loadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800536 }
buzbeee88dfbf2012-03-05 11:19:57 -0800537
Ian Rogersb41b33b2012-03-20 14:22:54 -0700538 if (!isArray) {
539 if (!pair) {
540 store = newLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
541 } else {
542 store = newLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
jeffhaoe2962482012-06-28 11:29:57 -0700543 store2 = newLIR3(cUnit, opcode, rBase, displacement + HIWORD_OFFSET, rSrcHi);
544 }
buzbeef0504cd2012-11-13 16:31:10 -0800545 if (rBase == rX86_SP) {
jeffhaoe2962482012-06-28 11:29:57 -0700546 annotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0))
547 >> 2, false /* isLoad */, is64bit);
548 if (pair) {
549 annotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
550 false /* isLoad */, is64bit);
551 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700552 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800553 } else {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700554 if (!pair) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700555 store = newLIR5(cUnit, opcode, rBase, rIndex, scale,
556 displacement + LOWORD_OFFSET, rSrc);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700557 } else {
Elliott Hughes60234562012-06-01 12:25:59 -0700558 store = newLIR5(cUnit, opcode, rBase, rIndex, scale,
559 displacement + LOWORD_OFFSET, rSrc);
jeffhaoe2962482012-06-28 11:29:57 -0700560 store2 = newLIR5(cUnit, opcode, rBase, rIndex, scale,
561 displacement + HIWORD_OFFSET, rSrcHi);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800562 }
563 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700564
565 return store;
buzbeee88dfbf2012-03-05 11:19:57 -0800566}
567
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700568/* store value base base + scaled index. */
Bill Buzbeea114add2012-05-03 15:00:40 -0700569LIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase, int rIndex, int rSrc,
570 int scale, OpSize size)
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700571{
buzbee408ad162012-06-06 16:45:18 -0700572 return storeBaseIndexedDisp(cUnit, rBase, rIndex, scale, 0,
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700573 rSrc, INVALID_REG, size, INVALID_SREG);
574}
575
Bill Buzbeea114add2012-05-03 15:00:40 -0700576LIR *storeBaseDisp(CompilationUnit *cUnit, int rBase, int displacement,
577 int rSrc, OpSize size)
578{
buzbee408ad162012-06-06 16:45:18 -0700579 return storeBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700580 displacement, rSrc, INVALID_REG, size,
581 INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800582}
583
Ian Rogersb41b33b2012-03-20 14:22:54 -0700584LIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase, int displacement,
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 int rSrcLo, int rSrcHi)
586{
buzbee408ad162012-06-06 16:45:18 -0700587 return storeBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0, displacement,
Ian Rogersb41b33b2012-03-20 14:22:54 -0700588 rSrcLo, rSrcHi, kLong, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800589}
590
buzbeee88dfbf2012-03-05 11:19:57 -0800591void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
592{
jeffhaoe2962482012-06-28 11:29:57 -0700593 loadBaseDispWide(cUnit, base, 0, lowReg, highReg, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800594}
595
596} // namespace art