blob: 4987c2856cc5fa614aea88b2135bb75353369b6b [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
17namespace art {
18
19/*
buzbeea7678db2012-03-05 15:35:46 -080020 * This file contains codegen for the X86 ISA and is intended to be
buzbeee88dfbf2012-03-05 11:19:57 -080021 * includes by:
22 *
23 * Codegen-$(TARGET_ARCH_VARIANT).c
24 *
25 */
26
buzbeea7678db2012-03-05 15:35:46 -080027//FIXME: restore "static" when usage uncovered
Ian Rogersb5d09b22012-03-06 22:14:17 -080028/*static*/ int coreRegs[] = {
29 rAX, rCX, rDX, rBX, rSP, rBP, rSI, rDI
30#ifdef TARGET_REX_SUPPORT
31 r8, r9, r10, r11, r12, r13, r14, 15
32#endif
33};
buzbeea7678db2012-03-05 15:35:46 -080034/*static*/ int reservedRegs[] = {rSP};
Ian Rogersb41b33b2012-03-20 14:22:54 -070035/*static*/ int coreTemps[] = {rAX, rCX, rDX, rBX};
Ian Rogersb5d09b22012-03-06 22:14:17 -080036/*static*/ int fpRegs[] = {
37 fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
38#ifdef TARGET_REX_SUPPORT
39 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15
40#endif
41};
42/*static*/ int fpTemps[] = {
43 fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
44#ifdef TARGET_REX_SUPPORT
45 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15
46#endif
47};
buzbeee88dfbf2012-03-05 11:19:57 -080048
49void genBarrier(CompilationUnit *cUnit);
50void storePair(CompilationUnit *cUnit, int base, int lowReg,
51 int highReg);
52void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
53LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
54 int rDest);
55LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
56 int displacement, int rSrc);
57LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
58
59LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
60{
buzbeee88dfbf2012-03-05 11:19:57 -080061 int opcode;
62 /* must be both DOUBLE or both not DOUBLE */
63 DCHECK_EQ(DOUBLEREG(rDest),DOUBLEREG(rSrc));
64 if (DOUBLEREG(rDest)) {
Ian Rogersb5d09b22012-03-06 22:14:17 -080065 opcode = kX86MovsdRR;
buzbeee88dfbf2012-03-05 11:19:57 -080066 } else {
67 if (SINGLEREG(rDest)) {
68 if (SINGLEREG(rSrc)) {
Ian Rogersb5d09b22012-03-06 22:14:17 -080069 opcode = kX86MovssRR;
70 } else { // Fpr <- Gpr
71 opcode = kX86MovdxrRR;
buzbeee88dfbf2012-03-05 11:19:57 -080072 }
Ian Rogersb5d09b22012-03-06 22:14:17 -080073 } else { // Gpr <- Fpr
buzbeee88dfbf2012-03-05 11:19:57 -080074 DCHECK(SINGLEREG(rSrc));
Ian Rogersb5d09b22012-03-06 22:14:17 -080075 opcode = kX86MovdrxRR;
buzbeee88dfbf2012-03-05 11:19:57 -080076 }
77 }
Ian Rogersb5d09b22012-03-06 22:14:17 -080078 DCHECK((EncodingMap[opcode].flags & IS_BINARY_OP) != 0);
Ian Rogersf7d9ad32012-03-13 18:45:39 -070079 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
buzbeee88dfbf2012-03-05 11:19:57 -080080 if (rDest == rSrc) {
81 res->flags.isNop = true;
82 }
83 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080084}
85
86/*
87 * Load a immediate using a shortcut if possible; otherwise
88 * grab from the per-translation literal pool. If target is
89 * a high register, build constant into a low register and copy.
90 *
91 * No additional register clobbering operation performed. Use this version when
92 * 1) rDest is freshly returned from oatAllocTemp or
93 * 2) The codegen is under fixed register usage
94 */
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070095LIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest, int value) {
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070096 int rDestSave = rDest;
Ian Rogersb41b33b2012-03-20 14:22:54 -070097 if (FPREG(rDest)) {
98 if (value == 0) {
99 return newLIR2(cUnit, kX86XorpsRR, rDest, rDest);
100 }
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700101 DCHECK(SINGLEREG(rDest));
102 rDest = oatAllocTemp(cUnit);
103 }
buzbeee88dfbf2012-03-05 11:19:57 -0800104
Ian Rogersb41b33b2012-03-20 14:22:54 -0700105 LIR *res;
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700106 if (value == 0) {
107 res = newLIR2(cUnit, kX86Xor32RR, rDest, rDest);
108 } else {
109 res = newLIR2(cUnit, kX86Mov32RI, rDest, value);
110 }
buzbeee88dfbf2012-03-05 11:19:57 -0800111
Ian Rogersb41b33b2012-03-20 14:22:54 -0700112 if (FPREG(rDestSave)) {
113 newLIR2(cUnit, kX86MovdxrRR, rDestSave, rDest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700114 oatFreeTemp(cUnit, rDest);
115 }
buzbeee88dfbf2012-03-05 11:19:57 -0800116
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700117 return res;
buzbeee88dfbf2012-03-05 11:19:57 -0800118}
119
Ian Rogersb5d09b22012-03-06 22:14:17 -0800120LIR* opBranchUnconditional(CompilationUnit *cUnit, OpKind op) {
121 CHECK_EQ(op, kOpUncondBr);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700122 return newLIR1(cUnit, kX86Jmp8, 0 /* offset to be patched */ );
buzbeee88dfbf2012-03-05 11:19:57 -0800123}
124
125LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
126
Ian Rogersb5d09b22012-03-06 22:14:17 -0800127X86ConditionCode oatX86ConditionEncoding(ConditionCode cond);
buzbeea7678db2012-03-05 15:35:46 -0800128LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
129{
Ian Rogersb41b33b2012-03-20 14:22:54 -0700130 LIR* branch = newLIR2(cUnit, kX86Jcc8, 0 /* offset to be patched */,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800131 oatX86ConditionEncoding(cc));
132 branch->target = target;
133 return branch;
buzbeea7678db2012-03-05 15:35:46 -0800134}
135
Ian Rogersb5d09b22012-03-06 22:14:17 -0800136LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc) {
137 X86OpCode opcode = kX86Bkpt;
138 switch (op) {
139 case kOpNeg: opcode = kX86Neg32R; break;
140 case kOpBlx: opcode = kX86CallR; break;
141 default:
142 LOG(FATAL) << "Bad case in opReg " << op;
143 }
144 return newLIR1(cUnit, opcode, rDestSrc);
145}
146
147LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int value) {
148 X86OpCode opcode = kX86Bkpt;
149 bool byteImm = IS_SIMM8(value);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700150 DCHECK(!FPREG(rDestSrc1));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800151 switch (op) {
152 case kOpLsl: opcode = kX86Sal32RI; break;
153 case kOpLsr: opcode = kX86Shr32RI; break;
154 case kOpAsr: opcode = kX86Sar32RI; break;
155 case kOpAdd: opcode = byteImm ? kX86Add32RI8 : kX86Add32RI; break;
156 case kOpOr: opcode = byteImm ? kX86Or32RI8 : kX86Or32RI; break;
157 case kOpAdc: opcode = byteImm ? kX86Adc32RI8 : kX86Adc32RI; break;
158 //case kOpSbb: opcode = kX86Sbb32RI; break;
159 case kOpAnd: opcode = byteImm ? kX86And32RI8 : kX86And32RI; break;
160 case kOpSub: opcode = byteImm ? kX86Sub32RI8 : kX86Sub32RI; break;
161 case kOpXor: opcode = byteImm ? kX86Xor32RI8 : kX86Xor32RI; break;
162 case kOpCmp: opcode = byteImm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700163 case kOpMov: return loadConstantNoClobber(cUnit, rDestSrc1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800164 case kOpMul:
165 opcode = byteImm ? kX86Imul32RRI8 : kX86Imul32RRI;
166 return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, value);
167 default:
168 LOG(FATAL) << "Bad case in opRegImm " << op;
169 }
170 return newLIR2(cUnit, opcode, rDestSrc1, value);
171}
172
173LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2)
buzbeee88dfbf2012-03-05 11:19:57 -0800174{
buzbeea7678db2012-03-05 15:35:46 -0800175 X86OpCode opcode = kX86Nop;
buzbeee88dfbf2012-03-05 11:19:57 -0800176 switch (op) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800177 // X86 unary opcodes
178 case kOpMvn:
179 opRegCopy(cUnit, rDestSrc1, rSrc2);
180 return opReg(cUnit, kOpNot, rDestSrc1);
181 case kOpNeg:
182 opRegCopy(cUnit, rDestSrc1, rSrc2);
183 return opReg(cUnit, kOpNeg, rDestSrc1);
184 // X86 binary opcodes
185 case kOpSub: opcode = kX86Sub32RR; break;
186 case kOpSbc: opcode = kX86Sbb32RR; break;
187 case kOpLsl: opcode = kX86Sal32RC; break;
188 case kOpLsr: opcode = kX86Shr32RC; break;
189 case kOpAsr: opcode = kX86Sar32RC; break;
190 case kOpMov: opcode = kX86Mov32RR; break;
191 case kOpCmp: opcode = kX86Cmp32RR; break;
192 case kOpAdd: opcode = kX86Add32RR; break;
193 case kOpAdc: opcode = kX86Adc32RR; break;
194 case kOpAnd: opcode = kX86And32RR; break;
195 case kOpOr: opcode = kX86Or32RR; break;
196 case kOpXor: opcode = kX86Xor32RR; break;
197 case kOp2Byte: opcode = kX86Movsx8RR; break;
198 case kOp2Short: opcode = kX86Movsx16RR; break;
199 case kOp2Char: opcode = kX86Movzx16RR; break;
200 case kOpMul: opcode = kX86Imul32RR; break;
201 default:
202 LOG(FATAL) << "Bad case in opRegReg " << op;
203 break;
buzbeee88dfbf2012-03-05 11:19:57 -0800204 }
205 return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800206}
207
208LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase, int offset) {
209 X86OpCode opcode = kX86Nop;
210 switch (op) {
211 // X86 binary opcodes
212 case kOpSub: opcode = kX86Sub32RM; break;
213 case kOpMov: opcode = kX86Mov32RM; break;
214 case kOpCmp: opcode = kX86Cmp32RM; break;
215 case kOpAdd: opcode = kX86Add32RM; break;
216 case kOpAnd: opcode = kX86And32RM; break;
217 case kOpOr: opcode = kX86Or32RM; break;
218 case kOpXor: opcode = kX86Xor32RM; break;
219 case kOp2Byte: opcode = kX86Movsx8RM; break;
220 case kOp2Short: opcode = kX86Movsx16RM; break;
221 case kOp2Char: opcode = kX86Movzx16RM; break;
222 case kOpMul:
223 default:
224 LOG(FATAL) << "Bad case in opRegReg " << op;
225 break;
226 }
227 return newLIR3(cUnit, opcode, rDest, rBase, offset);
228}
229
230LIR* opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc1, int rSrc2) {
231 if (rDest != rSrc1 && rDest != rSrc2) {
232 if (op == kOpAdd) { // lea special case, except can't encode rbp as base
233 if (rSrc1 == rSrc2) {
234 return opRegImm(cUnit, kOpLsl, rDest, 1);
235 } else if (rSrc1 != rBP) {
236 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc1 /* base */,
237 rSrc2 /* index */, 0 /* scale */, 0 /* disp */);
238 } else {
239 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc2 /* base */,
240 rSrc1 /* index */, 0 /* scale */, 0 /* disp */);
241 }
242 } else {
243 opRegCopy(cUnit, rDest, rSrc1);
244 return opRegReg(cUnit, op, rDest, rSrc2);
245 }
246 } else if (rDest == rSrc1) {
247 return opRegReg(cUnit, op, rDest, rSrc2);
248 } else { // rDest == rSrc2
249 switch (op) {
250 case kOpSub: // non-commutative
251 opReg(cUnit, kOpNeg, rDest);
252 op = kOpAdd;
253 break;
254 case kOpSbc:
255 case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
256 int tReg = oatAllocTemp(cUnit);
257 opRegCopy(cUnit, tReg, rSrc1);
258 opRegReg(cUnit, op, tReg, rSrc2);
259 LIR* res = opRegCopy(cUnit, rDest, tReg);
260 oatFreeTemp(cUnit, tReg);
261 return res;
262 }
263 case kOpAdd: // commutative
264 case kOpOr:
265 case kOpAdc:
266 case kOpAnd:
267 case kOpXor:
268 break;
269 default:
270 LOG(FATAL) << "Bad case in opRegRegReg " << op;
271 }
272 return opRegReg(cUnit, op, rDest, rSrc1);
273 }
274}
275
276LIR* opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc, int value) {
277 if (op == kOpMul) {
278 X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
279 return newLIR3(cUnit, opcode, rDest, rSrc, value);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700280 } else if (op == kOpAnd) {
281 if (value == 0xFF) {
282 return newLIR2(cUnit, kX86Movzx8RR, rDest, rSrc);
283 } else if (value == 0xFFFF) {
284 return newLIR2(cUnit, kX86Movzx16RR, rDest, rSrc);
285 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800286 }
287 if (rDest != rSrc) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700288 if (op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
289 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc /* base */,
290 r4sib_no_index /* index */, value /* scale */, value /* disp */);
291 } else if (op == kOpAdd) { // lea add special case
Ian Rogersb5d09b22012-03-06 22:14:17 -0800292 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc /* base */,
293 r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
294 }
295 opRegCopy(cUnit, rDest, rSrc);
296 }
297 return opRegImm(cUnit, op, rDest, value);
buzbeee88dfbf2012-03-05 11:19:57 -0800298}
299
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700300LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset) {
301 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
311LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp) {
312 X86OpCode opcode = kX86Bkpt;
313 switch (op) {
314 case kOpBlx: opcode = kX86CallM; break;
315 default:
316 LOG(FATAL) << "Bad opcode: " << op;
317 break;
318 }
319 return newLIR2(cUnit, opcode, rBase, disp);
320}
321
buzbeee88dfbf2012-03-05 11:19:57 -0800322LIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
323 int rDestHi, int valLo, int valHi)
324{
325 LIR *res;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700326 if (FPREG(rDestLo)) {
327 DCHECK(FPREG(rDestHi)); // ignore rDestHi
328 if (valLo == 0 && valHi == 0) {
329 return newLIR2(cUnit, kX86XorpsRR, rDestLo, rDestLo);
330 } else {
331 if (valLo == 0) {
332 res = newLIR2(cUnit, kX86XorpsRR, rDestLo, rDestLo);
333 } else {
334 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
335 }
336 if (valHi != 0) {
337 loadConstantNoClobber(cUnit, rDestHi, valHi);
338 newLIR2(cUnit, kX86PsllqRI, rDestHi, 32);
339 newLIR2(cUnit, kX86OrpsRR, rDestLo, rDestHi);
340 }
341 }
342 } else {
343 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
344 loadConstantNoClobber(cUnit, rDestHi, valHi);
345 }
buzbeee88dfbf2012-03-05 11:19:57 -0800346 return res;
347}
348
349/* Load value from base + scaled index. */
350LIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
351 int rIndex, int rDest, int scale, OpSize size)
352{
353 UNIMPLEMENTED(WARNING) << "loadBaseIndexed";
354 return NULL;
355#if 0
356 LIR *first = NULL;
357 LIR *res;
buzbeea7678db2012-03-05 15:35:46 -0800358 X86OpCode opcode = kX86Nop;
buzbeee88dfbf2012-03-05 11:19:57 -0800359 int tReg = oatAllocTemp(cUnit);
360
361 if (FPREG(rDest)) {
362 DCHECK(SINGLEREG(rDest));
363 DCHECK((size == kWord) || (size == kSingle));
364 size = kSingle;
365 } else {
366 if (size == kSingle)
367 size = kWord;
368 }
369
370 if (!scale) {
buzbeea7678db2012-03-05 15:35:46 -0800371 first = newLIR3(cUnit, kX86Addu, tReg , rBase, rIndex);
buzbeee88dfbf2012-03-05 11:19:57 -0800372 } else {
373 first = opRegRegImm(cUnit, kOpLsl, tReg, rIndex, scale);
buzbeea7678db2012-03-05 15:35:46 -0800374 newLIR3(cUnit, kX86Addu, tReg , rBase, tReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800375 }
376
377 switch (size) {
378 case kSingle:
buzbeea7678db2012-03-05 15:35:46 -0800379 opcode = kX86Flwc1;
buzbeee88dfbf2012-03-05 11:19:57 -0800380 break;
381 case kWord:
buzbeea7678db2012-03-05 15:35:46 -0800382 opcode = kX86Lw;
buzbeee88dfbf2012-03-05 11:19:57 -0800383 break;
384 case kUnsignedHalf:
buzbeea7678db2012-03-05 15:35:46 -0800385 opcode = kX86Lhu;
buzbeee88dfbf2012-03-05 11:19:57 -0800386 break;
387 case kSignedHalf:
buzbeea7678db2012-03-05 15:35:46 -0800388 opcode = kX86Lh;
buzbeee88dfbf2012-03-05 11:19:57 -0800389 break;
390 case kUnsignedByte:
buzbeea7678db2012-03-05 15:35:46 -0800391 opcode = kX86Lbu;
buzbeee88dfbf2012-03-05 11:19:57 -0800392 break;
393 case kSignedByte:
buzbeea7678db2012-03-05 15:35:46 -0800394 opcode = kX86Lb;
buzbeee88dfbf2012-03-05 11:19:57 -0800395 break;
396 default:
397 LOG(FATAL) << "Bad case in loadBaseIndexed";
398 }
399
400 res = newLIR3(cUnit, opcode, rDest, 0, tReg);
401 oatFreeTemp(cUnit, tReg);
402 return (first) ? first : res;
403#endif
404}
405
buzbeee88dfbf2012-03-05 11:19:57 -0800406LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
407{
408 UNIMPLEMENTED(WARNING) << "loadMultiple";
409 return NULL;
410#if 0
411 int i;
412 int loadCnt = 0;
413 LIR *res = NULL ;
414 genBarrier(cUnit);
415
416 for (i = 0; i < 8; i++, rMask >>= 1) {
buzbeea7678db2012-03-05 15:35:46 -0800417 if (rMask & 0x1) {
418 newLIR3(cUnit, kX86Lw, i+r_A0, loadCnt*4, rBase);
buzbeee88dfbf2012-03-05 11:19:57 -0800419 loadCnt++;
420 }
421 }
422
423 if (loadCnt) {/* increment after */
buzbeea7678db2012-03-05 15:35:46 -0800424 newLIR3(cUnit, kX86Addiu, rBase, rBase, loadCnt*4);
buzbeee88dfbf2012-03-05 11:19:57 -0800425 }
426
427 genBarrier(cUnit);
428 return res; /* NULL always returned which should be ok since no callers use it */
429#endif
430}
431
432LIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
433{
434 UNIMPLEMENTED(WARNING) << "storeMultiple";
435 return NULL;
buzbeea7678db2012-03-05 15:35:46 -0800436#if 0
buzbeee88dfbf2012-03-05 11:19:57 -0800437 int i;
438 int storeCnt = 0;
439 LIR *res = NULL ;
440 genBarrier(cUnit);
441
442 for (i = 0; i < 8; i++, rMask >>= 1) {
buzbeea7678db2012-03-05 15:35:46 -0800443 if (rMask & 0x1) {
444 newLIR3(cUnit, kX86Sw, i+r_A0, storeCnt*4, rBase);
buzbeee88dfbf2012-03-05 11:19:57 -0800445 storeCnt++;
446 }
447 }
448
449 if (storeCnt) { /* increment after */
buzbeea7678db2012-03-05 15:35:46 -0800450 newLIR3(cUnit, kX86Addiu, rBase, rBase, storeCnt*4);
buzbeee88dfbf2012-03-05 11:19:57 -0800451 }
452
453 genBarrier(cUnit);
454 return res; /* NULL always returned which should be ok since no callers use it */
455#endif
456}
457
Ian Rogersb5d09b22012-03-06 22:14:17 -0800458LIR* loadBaseIndexedDisp(CompilationUnit *cUnit, MIR *mir,
459 int rBase, int rIndex, int scale, int displacement,
460 int rDest, int rDestHi,
461 OpSize size, int sReg) {
462 LIR *load = NULL;
463 LIR *load2 = NULL;
464 bool isArray = rIndex != INVALID_REG;
465 bool pair = false;
466 bool is64bit = false;
467 X86OpCode opcode = kX86Nop;
468 switch (size) {
469 case kLong:
470 case kDouble:
471 is64bit = true;
472 if (FPREG(rDest)) {
473 opcode = isArray ? kX86MovsdRA : kX86MovsdRM;
474 if (DOUBLEREG(rDest)) {
475 rDest = rDest - FP_DOUBLE;
buzbeee88dfbf2012-03-05 11:19:57 -0800476 } else {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800477 DCHECK(FPREG(rDestHi));
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700478 DCHECK_EQ(rDest, (rDestHi - 1));
buzbeee88dfbf2012-03-05 11:19:57 -0800479 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800480 rDestHi = rDest + 1;
481 } else {
482 pair = true;
483 opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
484 }
485 // TODO: double store is to unaligned address
486 DCHECK_EQ((displacement & 0x3), 0);
487 break;
488 case kWord:
489 case kSingle:
490 opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
491 if (FPREG(rDest)) {
492 opcode = isArray ? kX86MovssRA : kX86MovssRM;
493 DCHECK(SINGLEREG(rDest));
494 }
495 DCHECK_EQ((displacement & 0x3), 0);
496 break;
497 case kUnsignedHalf:
498 opcode = isArray ? kX86Movzx16RA : kX86Movzx16RM;
499 DCHECK_EQ((displacement & 0x1), 0);
500 break;
501 case kSignedHalf:
502 opcode = isArray ? kX86Movsx16RA : kX86Movsx16RM;
503 DCHECK_EQ((displacement & 0x1), 0);
504 break;
505 case kUnsignedByte:
506 opcode = isArray ? kX86Movzx8RA : kX86Movzx8RM;
507 break;
508 case kSignedByte:
509 opcode = isArray ? kX86Movsx8RA : kX86Movsx8RM;
510 break;
511 default:
512 LOG(FATAL) << "Bad case in loadBaseIndexedDispBody";
513 }
514
515 if (!isArray) {
516 if (!pair) {
517 load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
buzbeee88dfbf2012-03-05 11:19:57 -0800518 } else {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800519 load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
520 load2 = newLIR3(cUnit, opcode, rDestHi, rBase, displacement + HIWORD_OFFSET);
buzbeee88dfbf2012-03-05 11:19:57 -0800521 }
buzbeee88dfbf2012-03-05 11:19:57 -0800522 if (rBase == rSP) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800523 annotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
524 true /* isLoad */, is64bit);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700525 if (pair) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800526 annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
527 true /* isLoad */, is64bit);
528 }
buzbeee88dfbf2012-03-05 11:19:57 -0800529 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800530 } else {
531 if (!pair) {
532 load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale, displacement + LOWORD_OFFSET);
533 } else {
534 load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale, displacement + LOWORD_OFFSET);
535 load2 = newLIR5(cUnit, opcode, rDestHi, rBase, rIndex, scale, displacement + HIWORD_OFFSET);
536 }
537 }
538
539 return load;
buzbeee88dfbf2012-03-05 11:19:57 -0800540}
541
Ian Rogersb5d09b22012-03-06 22:14:17 -0800542LIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir,
543 int rBase, int displacement,
544 int rDest,
545 OpSize size, int sReg) {
546 return loadBaseIndexedDisp(cUnit, mir, rBase, INVALID_REG, 0, displacement,
547 rDest, INVALID_REG, size, sReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800548}
549
Ian Rogersb5d09b22012-03-06 22:14:17 -0800550LIR *loadBaseDispWide(CompilationUnit *cUnit, MIR *mir,
551 int rBase, int displacement,
552 int rDestLo, int rDestHi,
553 int sReg) {
554 return loadBaseIndexedDisp(cUnit, mir, rBase, INVALID_REG, 0, displacement,
555 rDestLo, rDestHi, kLong, sReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800556}
557
Ian Rogersb41b33b2012-03-20 14:22:54 -0700558LIR* storeBaseIndexedDisp(CompilationUnit *cUnit, MIR *mir,
559 int rBase, int rIndex, int scale, int displacement,
560 int rSrc, int rSrcHi,
561 OpSize size, int sReg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800562 LIR *store = NULL;
563 LIR *store2 = NULL;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700564 bool isArray = rIndex != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800565 bool pair = false;
566 bool is64bit = false;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700567 X86OpCode opcode = kX86Nop;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800568 switch (size) {
569 case kLong:
570 case kDouble:
571 is64bit = true;
572 if (FPREG(rSrc)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700573 opcode = isArray ? kX86MovsdAR : kX86MovsdMR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800574 if (DOUBLEREG(rSrc)) {
575 rSrc = rSrc - FP_DOUBLE;
buzbeee88dfbf2012-03-05 11:19:57 -0800576 } else {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800577 DCHECK(FPREG(rSrcHi));
578 DCHECK_EQ(rSrc, (rSrcHi - 1));
buzbeee88dfbf2012-03-05 11:19:57 -0800579 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800580 rSrcHi = rSrc + 1;
581 } else {
582 pair = true;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700583 opcode = isArray ? kX86Mov32AR : kX86Mov32MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800584 }
585 // TODO: double store is to unaligned address
586 DCHECK_EQ((displacement & 0x3), 0);
587 break;
588 case kWord:
589 case kSingle:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700590 opcode = isArray ? kX86Mov32AR : kX86Mov32MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800591 if (FPREG(rSrc)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700592 opcode = isArray ? kX86MovssAR : kX86MovssMR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800593 DCHECK(SINGLEREG(rSrc));
594 }
595 DCHECK_EQ((displacement & 0x3), 0);
596 break;
597 case kUnsignedHalf:
598 case kSignedHalf:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700599 opcode = isArray ? kX86Mov16AR : kX86Mov16MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800600 DCHECK_EQ((displacement & 0x1), 0);
601 break;
602 case kUnsignedByte:
603 case kSignedByte:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700604 opcode = isArray ? kX86Mov8AR : kX86Mov8MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800605 break;
606 default:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700607 LOG(FATAL) << "Bad case in loadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800608 }
buzbeee88dfbf2012-03-05 11:19:57 -0800609
Ian Rogersb41b33b2012-03-20 14:22:54 -0700610 if (!isArray) {
611 if (!pair) {
612 store = newLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
613 } else {
614 store = newLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
615 store2 = newLIR3(cUnit, opcode, rBase, displacement + HIWORD_OFFSET, rSrcHi);
616 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800617 } else {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700618 if (!pair) {
619 store = newLIR5(cUnit, opcode, rBase, rIndex, scale, displacement + LOWORD_OFFSET, rSrc);
620 } else {
621 store = newLIR5(cUnit, opcode, rBase, rIndex, scale, displacement + LOWORD_OFFSET, rSrc);
622 store2 = newLIR5(cUnit, opcode, rBase, rIndex, scale, displacement + HIWORD_OFFSET, rSrcHi);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800623 }
624 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700625
626 return store;
buzbeee88dfbf2012-03-05 11:19:57 -0800627}
628
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700629/* store value base base + scaled index. */
630LIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase, int rIndex, int rSrc, int scale,
631 OpSize size)
632{
633 return storeBaseIndexedDisp(cUnit, NULL, rBase, rIndex, scale, 0,
634 rSrc, INVALID_REG, size, INVALID_SREG);
635}
636
Ian Rogersb41b33b2012-03-20 14:22:54 -0700637LIR *storeBaseDisp(CompilationUnit *cUnit, int rBase, int displacement, int rSrc, OpSize size) {
638 return storeBaseIndexedDisp(cUnit, NULL, rBase, INVALID_REG, 0, displacement,
639 rSrc, INVALID_REG, size, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800640}
641
Ian Rogersb41b33b2012-03-20 14:22:54 -0700642LIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase, int displacement,
643 int rSrcLo, int rSrcHi) {
644 return storeBaseIndexedDisp(cUnit, NULL, rBase, INVALID_REG, 0, displacement,
645 rSrcLo, rSrcHi, kLong, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800646}
647
648void storePair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
649{
buzbeea7678db2012-03-05 15:35:46 -0800650 storeWordDisp(cUnit, base, 0, lowReg);
651 storeWordDisp(cUnit, base, 4, highReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800652}
653
654void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
655{
buzbeea7678db2012-03-05 15:35:46 -0800656 loadWordDisp(cUnit, base, 0, lowReg);
657 loadWordDisp(cUnit, base, 4, highReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800658}
659
660} // namespace art