blob: 418a6fe0c164216b92e6e7259cae53a4e76de27f [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
buzbeeb046e162012-10-30 15:48:42 -070019/* This file contains codegen for the X86 ISA */
buzbeee88dfbf2012-03-05 11:19:57 -080020
buzbeee88dfbf2012-03-05 11:19:57 -080021void genBarrier(CompilationUnit *cUnit);
buzbeee88dfbf2012-03-05 11:19:57 -080022void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
23LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
24 int rDest);
25LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
26 int displacement, int rSrc);
27LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
28
29LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
30{
Bill Buzbeea114add2012-05-03 15:00:40 -070031 int opcode;
32 /* must be both DOUBLE or both not DOUBLE */
buzbeef0504cd2012-11-13 16:31:10 -080033 DCHECK_EQ(X86_DOUBLEREG(rDest), X86_DOUBLEREG(rSrc));
34 if (X86_DOUBLEREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070035 opcode = kX86MovsdRR;
36 } else {
buzbeef0504cd2012-11-13 16:31:10 -080037 if (X86_SINGLEREG(rDest)) {
38 if (X86_SINGLEREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070039 opcode = kX86MovssRR;
40 } else { // Fpr <- Gpr
41 opcode = kX86MovdxrRR;
42 }
43 } else { // Gpr <- Fpr
buzbeef0504cd2012-11-13 16:31:10 -080044 DCHECK(X86_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -070045 opcode = kX86MovdrxRR;
buzbeee88dfbf2012-03-05 11:19:57 -080046 }
Bill Buzbeea114add2012-05-03 15:00:40 -070047 }
buzbeeec137432012-11-13 12:13:16 -080048 DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
Bill Buzbeea114add2012-05-03 15:00:40 -070049 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
50 if (rDest == rSrc) {
51 res->flags.isNop = true;
52 }
53 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080054}
55
56/*
57 * Load a immediate using a shortcut if possible; otherwise
58 * grab from the per-translation literal pool. If target is
59 * a high register, build constant into a low register and copy.
60 *
61 * No additional register clobbering operation performed. Use this version when
62 * 1) rDest is freshly returned from oatAllocTemp or
63 * 2) The codegen is under fixed register usage
64 */
Bill Buzbeea114add2012-05-03 15:00:40 -070065LIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest, int value)
66{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070067 int rDestSave = rDest;
buzbeef0504cd2012-11-13 16:31:10 -080068 if (X86_FPREG(rDest)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -070069 if (value == 0) {
70 return newLIR2(cUnit, kX86XorpsRR, rDest, rDest);
71 }
buzbeef0504cd2012-11-13 16:31:10 -080072 DCHECK(X86_SINGLEREG(rDest));
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070073 rDest = oatAllocTemp(cUnit);
74 }
buzbeee88dfbf2012-03-05 11:19:57 -080075
Ian Rogersb41b33b2012-03-20 14:22:54 -070076 LIR *res;
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070077 if (value == 0) {
78 res = newLIR2(cUnit, kX86Xor32RR, rDest, rDest);
79 } else {
Ian Rogers2e9f7ed2012-09-26 11:30:43 -070080 // Note, there is no byte immediate form of a 32 bit immediate move.
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070081 res = newLIR2(cUnit, kX86Mov32RI, rDest, value);
82 }
buzbeee88dfbf2012-03-05 11:19:57 -080083
buzbeef0504cd2012-11-13 16:31:10 -080084 if (X86_FPREG(rDestSave)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -070085 newLIR2(cUnit, kX86MovdxrRR, rDestSave, rDest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070086 oatFreeTemp(cUnit, rDest);
87 }
buzbeee88dfbf2012-03-05 11:19:57 -080088
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070089 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080090}
91
Bill Buzbeea114add2012-05-03 15:00:40 -070092LIR* opBranchUnconditional(CompilationUnit *cUnit, OpKind op)
93{
Ian Rogersb5d09b22012-03-06 22:14:17 -080094 CHECK_EQ(op, kOpUncondBr);
Ian Rogersb41b33b2012-03-20 14:22:54 -070095 return newLIR1(cUnit, kX86Jmp8, 0 /* offset to be patched */ );
buzbeee88dfbf2012-03-05 11:19:57 -080096}
97
98LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
99
Ian Rogersb5d09b22012-03-06 22:14:17 -0800100X86ConditionCode oatX86ConditionEncoding(ConditionCode cond);
buzbeea7678db2012-03-05 15:35:46 -0800101LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
102{
Ian Rogersb41b33b2012-03-20 14:22:54 -0700103 LIR* branch = newLIR2(cUnit, kX86Jcc8, 0 /* offset to be patched */,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800104 oatX86ConditionEncoding(cc));
105 branch->target = target;
106 return branch;
buzbeea7678db2012-03-05 15:35:46 -0800107}
108
Bill Buzbeea114add2012-05-03 15:00:40 -0700109LIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
110{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800111 X86OpCode opcode = kX86Bkpt;
112 switch (op) {
113 case kOpNeg: opcode = kX86Neg32R; break;
jeffhao1395b1e2012-06-13 18:05:13 -0700114 case kOpNot: opcode = kX86Not32R; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800115 case kOpBlx: opcode = kX86CallR; break;
116 default:
117 LOG(FATAL) << "Bad case in opReg " << op;
118 }
119 return newLIR1(cUnit, opcode, rDestSrc);
120}
121
Bill Buzbeea114add2012-05-03 15:00:40 -0700122LIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int value)
123{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800124 X86OpCode opcode = kX86Bkpt;
125 bool byteImm = IS_SIMM8(value);
buzbeef0504cd2012-11-13 16:31:10 -0800126 DCHECK(!X86_FPREG(rDestSrc1));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800127 switch (op) {
128 case kOpLsl: opcode = kX86Sal32RI; break;
129 case kOpLsr: opcode = kX86Shr32RI; break;
130 case kOpAsr: opcode = kX86Sar32RI; break;
131 case kOpAdd: opcode = byteImm ? kX86Add32RI8 : kX86Add32RI; break;
132 case kOpOr: opcode = byteImm ? kX86Or32RI8 : kX86Or32RI; break;
133 case kOpAdc: opcode = byteImm ? kX86Adc32RI8 : kX86Adc32RI; break;
134 //case kOpSbb: opcode = kX86Sbb32RI; break;
135 case kOpAnd: opcode = byteImm ? kX86And32RI8 : kX86And32RI; break;
136 case kOpSub: opcode = byteImm ? kX86Sub32RI8 : kX86Sub32RI; break;
137 case kOpXor: opcode = byteImm ? kX86Xor32RI8 : kX86Xor32RI; break;
138 case kOpCmp: opcode = byteImm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700139 case kOpMov: return loadConstantNoClobber(cUnit, rDestSrc1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800140 case kOpMul:
141 opcode = byteImm ? kX86Imul32RRI8 : kX86Imul32RRI;
142 return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, value);
143 default:
144 LOG(FATAL) << "Bad case in opRegImm " << op;
145 }
146 return newLIR2(cUnit, opcode, rDestSrc1, value);
147}
148
149LIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2)
buzbeee88dfbf2012-03-05 11:19:57 -0800150{
buzbeea7678db2012-03-05 15:35:46 -0800151 X86OpCode opcode = kX86Nop;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700152 bool src2_must_be_cx = false;
buzbeee88dfbf2012-03-05 11:19:57 -0800153 switch (op) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800154 // X86 unary opcodes
155 case kOpMvn:
156 opRegCopy(cUnit, rDestSrc1, rSrc2);
157 return opReg(cUnit, kOpNot, rDestSrc1);
158 case kOpNeg:
159 opRegCopy(cUnit, rDestSrc1, rSrc2);
160 return opReg(cUnit, kOpNeg, rDestSrc1);
161 // X86 binary opcodes
162 case kOpSub: opcode = kX86Sub32RR; break;
163 case kOpSbc: opcode = kX86Sbb32RR; break;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700164 case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
165 case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
166 case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800167 case kOpMov: opcode = kX86Mov32RR; break;
168 case kOpCmp: opcode = kX86Cmp32RR; break;
169 case kOpAdd: opcode = kX86Add32RR; break;
170 case kOpAdc: opcode = kX86Adc32RR; break;
171 case kOpAnd: opcode = kX86And32RR; break;
172 case kOpOr: opcode = kX86Or32RR; break;
173 case kOpXor: opcode = kX86Xor32RR; break;
jeffhao703f2cd2012-07-13 17:25:52 -0700174 case kOp2Byte:
175 // Use shifts instead of a byte operand if the source can't be byte accessed.
176 if (rSrc2 >= 4) {
177 newLIR2(cUnit, kX86Mov32RR, rDestSrc1, rSrc2);
178 newLIR2(cUnit, kX86Sal32RI, rDestSrc1, 24);
179 return newLIR2(cUnit, kX86Sar32RI, rDestSrc1, 24);
180 } else {
181 opcode = kX86Movsx8RR;
182 }
183 break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800184 case kOp2Short: opcode = kX86Movsx16RR; break;
185 case kOp2Char: opcode = kX86Movzx16RR; break;
186 case kOpMul: opcode = kX86Imul32RR; break;
187 default:
188 LOG(FATAL) << "Bad case in opRegReg " << op;
189 break;
buzbeee88dfbf2012-03-05 11:19:57 -0800190 }
Ian Rogersd36c52e2012-04-09 16:29:25 -0700191 CHECK(!src2_must_be_cx || rSrc2 == rCX);
buzbeee88dfbf2012-03-05 11:19:57 -0800192 return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800193}
194
Bill Buzbeea114add2012-05-03 15:00:40 -0700195LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase,
196 int offset)
197{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800198 X86OpCode opcode = kX86Nop;
199 switch (op) {
200 // X86 binary opcodes
201 case kOpSub: opcode = kX86Sub32RM; break;
202 case kOpMov: opcode = kX86Mov32RM; break;
203 case kOpCmp: opcode = kX86Cmp32RM; break;
204 case kOpAdd: opcode = kX86Add32RM; break;
205 case kOpAnd: opcode = kX86And32RM; break;
206 case kOpOr: opcode = kX86Or32RM; break;
207 case kOpXor: opcode = kX86Xor32RM; break;
208 case kOp2Byte: opcode = kX86Movsx8RM; break;
209 case kOp2Short: opcode = kX86Movsx16RM; break;
210 case kOp2Char: opcode = kX86Movzx16RM; break;
211 case kOpMul:
212 default:
jeffhao703f2cd2012-07-13 17:25:52 -0700213 LOG(FATAL) << "Bad case in opRegMem " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800214 break;
215 }
216 return newLIR3(cUnit, opcode, rDest, rBase, offset);
217}
218
Bill Buzbeea114add2012-05-03 15:00:40 -0700219LIR* opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc1,
220 int rSrc2)
221{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800222 if (rDest != rSrc1 && rDest != rSrc2) {
223 if (op == kOpAdd) { // lea special case, except can't encode rbp as base
224 if (rSrc1 == rSrc2) {
Ian Rogers7caad772012-03-30 01:07:54 -0700225 opRegCopy(cUnit, rDest, rSrc1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800226 return opRegImm(cUnit, kOpLsl, rDest, 1);
227 } else if (rSrc1 != rBP) {
228 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc1 /* base */,
229 rSrc2 /* index */, 0 /* scale */, 0 /* disp */);
230 } else {
231 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc2 /* base */,
232 rSrc1 /* index */, 0 /* scale */, 0 /* disp */);
233 }
234 } else {
235 opRegCopy(cUnit, rDest, rSrc1);
236 return opRegReg(cUnit, op, rDest, rSrc2);
237 }
238 } else if (rDest == rSrc1) {
239 return opRegReg(cUnit, op, rDest, rSrc2);
240 } else { // rDest == rSrc2
241 switch (op) {
242 case kOpSub: // non-commutative
243 opReg(cUnit, kOpNeg, rDest);
244 op = kOpAdd;
245 break;
246 case kOpSbc:
247 case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
248 int tReg = oatAllocTemp(cUnit);
249 opRegCopy(cUnit, tReg, rSrc1);
250 opRegReg(cUnit, op, tReg, rSrc2);
251 LIR* res = opRegCopy(cUnit, rDest, tReg);
252 oatFreeTemp(cUnit, tReg);
253 return res;
254 }
255 case kOpAdd: // commutative
256 case kOpOr:
257 case kOpAdc:
258 case kOpAnd:
259 case kOpXor:
260 break;
261 default:
262 LOG(FATAL) << "Bad case in opRegRegReg " << op;
263 }
264 return opRegReg(cUnit, op, rDest, rSrc1);
265 }
266}
267
Bill Buzbeea114add2012-05-03 15:00:40 -0700268LIR* opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc,
269 int value)
270{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800271 if (op == kOpMul) {
272 X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
273 return newLIR3(cUnit, opcode, rDest, rSrc, value);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700274 } else if (op == kOpAnd) {
jeffhao854029c2012-07-23 17:31:30 -0700275 if (value == 0xFF && rSrc < 4) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700276 return newLIR2(cUnit, kX86Movzx8RR, rDest, rSrc);
277 } else if (value == 0xFFFF) {
278 return newLIR2(cUnit, kX86Movzx16RR, rDest, rSrc);
279 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800280 }
281 if (rDest != rSrc) {
Ian Rogers7caad772012-03-30 01:07:54 -0700282 if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
283 // TODO: fix bug in LEA encoding when disp == 0
284 return newLIR5(cUnit, kX86Lea32RA, rDest, r5sib_no_base /* base */,
285 rSrc /* index */, value /* scale */, 0 /* disp */);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700286 } else if (op == kOpAdd) { // lea add special case
Ian Rogersb5d09b22012-03-06 22:14:17 -0800287 return newLIR5(cUnit, kX86Lea32RA, rDest, rSrc /* base */,
288 r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
289 }
290 opRegCopy(cUnit, rDest, rSrc);
291 }
292 return opRegImm(cUnit, op, rDest, value);
buzbeee88dfbf2012-03-05 11:19:57 -0800293}
294
Bill Buzbeea114add2012-05-03 15:00:40 -0700295LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset)
296{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700297 X86OpCode opcode = kX86Bkpt;
298 switch (op) {
299 case kOpBlx: opcode = kX86CallT; break;
300 default:
301 LOG(FATAL) << "Bad opcode: " << op;
302 break;
303 }
304 return newLIR1(cUnit, opcode, threadOffset);
305}
306
Bill Buzbeea114add2012-05-03 15:00:40 -0700307LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp)
308{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700309 X86OpCode opcode = kX86Bkpt;
310 switch (op) {
311 case kOpBlx: opcode = kX86CallM; break;
312 default:
313 LOG(FATAL) << "Bad opcode: " << op;
314 break;
315 }
316 return newLIR2(cUnit, opcode, rBase, disp);
317}
318
buzbeee88dfbf2012-03-05 11:19:57 -0800319LIR *loadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
Bill Buzbeea114add2012-05-03 15:00:40 -0700320 int rDestHi, int valLo, int valHi)
buzbeee88dfbf2012-03-05 11:19:57 -0800321{
322 LIR *res;
buzbeef0504cd2012-11-13 16:31:10 -0800323 if (X86_FPREG(rDestLo)) {
324 DCHECK(X86_FPREG(rDestHi)); // ignore rDestHi
Ian Rogersb41b33b2012-03-20 14:22:54 -0700325 if (valLo == 0 && valHi == 0) {
326 return newLIR2(cUnit, kX86XorpsRR, rDestLo, rDestLo);
327 } else {
328 if (valLo == 0) {
329 res = newLIR2(cUnit, kX86XorpsRR, rDestLo, rDestLo);
330 } else {
331 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
332 }
333 if (valHi != 0) {
334 loadConstantNoClobber(cUnit, rDestHi, valHi);
335 newLIR2(cUnit, kX86PsllqRI, rDestHi, 32);
336 newLIR2(cUnit, kX86OrpsRR, rDestLo, rDestHi);
337 }
338 }
339 } else {
340 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
341 loadConstantNoClobber(cUnit, rDestHi, valHi);
342 }
buzbeee88dfbf2012-03-05 11:19:57 -0800343 return res;
344}
345
buzbeee88dfbf2012-03-05 11:19:57 -0800346LIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
347{
Ian Rogers474b6da2012-09-25 00:20:38 -0700348 UNIMPLEMENTED(FATAL) << "loadMultiple";
Bill Buzbeea114add2012-05-03 15:00:40 -0700349 newLIR0(cUnit, kX86Bkpt);
350 return NULL;
buzbeee88dfbf2012-03-05 11:19:57 -0800351}
352
353LIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
354{
Ian Rogers474b6da2012-09-25 00:20:38 -0700355 UNIMPLEMENTED(FATAL) << "storeMultiple";
Bill Buzbeea114add2012-05-03 15:00:40 -0700356 newLIR0(cUnit, kX86Bkpt);
357 return NULL;
buzbeee88dfbf2012-03-05 11:19:57 -0800358}
359
buzbee408ad162012-06-06 16:45:18 -0700360LIR* loadBaseIndexedDisp(CompilationUnit *cUnit,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800361 int rBase, int rIndex, int scale, int displacement,
362 int rDest, int rDestHi,
363 OpSize size, int sReg) {
364 LIR *load = NULL;
365 LIR *load2 = NULL;
366 bool isArray = rIndex != INVALID_REG;
367 bool pair = false;
368 bool is64bit = false;
369 X86OpCode opcode = kX86Nop;
370 switch (size) {
371 case kLong:
372 case kDouble:
373 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800374 if (X86_FPREG(rDest)) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800375 opcode = isArray ? kX86MovsdRA : kX86MovsdRM;
buzbeef0504cd2012-11-13 16:31:10 -0800376 if (X86_SINGLEREG(rDest)) {
377 DCHECK(X86_FPREG(rDestHi));
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700378 DCHECK_EQ(rDest, (rDestHi - 1));
buzbeef0504cd2012-11-13 16:31:10 -0800379 rDest = s2d(rDest, rDestHi);
buzbeee88dfbf2012-03-05 11:19:57 -0800380 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800381 rDestHi = rDest + 1;
382 } else {
383 pair = true;
384 opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
385 }
386 // TODO: double store is to unaligned address
387 DCHECK_EQ((displacement & 0x3), 0);
388 break;
389 case kWord:
390 case kSingle:
391 opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
buzbeef0504cd2012-11-13 16:31:10 -0800392 if (X86_FPREG(rDest)) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800393 opcode = isArray ? kX86MovssRA : kX86MovssRM;
buzbeef0504cd2012-11-13 16:31:10 -0800394 DCHECK(X86_SINGLEREG(rDest));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800395 }
396 DCHECK_EQ((displacement & 0x3), 0);
397 break;
398 case kUnsignedHalf:
399 opcode = isArray ? kX86Movzx16RA : kX86Movzx16RM;
400 DCHECK_EQ((displacement & 0x1), 0);
401 break;
402 case kSignedHalf:
403 opcode = isArray ? kX86Movsx16RA : kX86Movsx16RM;
404 DCHECK_EQ((displacement & 0x1), 0);
405 break;
406 case kUnsignedByte:
407 opcode = isArray ? kX86Movzx8RA : kX86Movzx8RM;
408 break;
409 case kSignedByte:
410 opcode = isArray ? kX86Movsx8RA : kX86Movsx8RM;
411 break;
412 default:
413 LOG(FATAL) << "Bad case in loadBaseIndexedDispBody";
414 }
415
416 if (!isArray) {
417 if (!pair) {
418 load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
buzbeee88dfbf2012-03-05 11:19:57 -0800419 } else {
jeffhaofdffdf82012-07-11 16:08:43 -0700420 if (rBase == rDest) {
421 load2 = newLIR3(cUnit, opcode, rDestHi, rBase,
422 displacement + HIWORD_OFFSET);
423 load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
424 } else {
425 load = newLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
426 load2 = newLIR3(cUnit, opcode, rDestHi, rBase,
427 displacement + HIWORD_OFFSET);
428 }
buzbeee88dfbf2012-03-05 11:19:57 -0800429 }
buzbeef0504cd2012-11-13 16:31:10 -0800430 if (rBase == rX86_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 annotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0))
432 >> 2, true /* isLoad */, is64bit);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700433 if (pair) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800434 annotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
435 true /* isLoad */, is64bit);
436 }
buzbeee88dfbf2012-03-05 11:19:57 -0800437 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800438 } else {
439 if (!pair) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale,
441 displacement + LOWORD_OFFSET);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800442 } else {
jeffhaofdffdf82012-07-11 16:08:43 -0700443 if (rBase == rDest) {
444 load2 = newLIR5(cUnit, opcode, rDestHi, rBase, rIndex, scale,
445 displacement + HIWORD_OFFSET);
446 load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale,
447 displacement + LOWORD_OFFSET);
448 } else {
449 load = newLIR5(cUnit, opcode, rDest, rBase, rIndex, scale,
450 displacement + LOWORD_OFFSET);
451 load2 = newLIR5(cUnit, opcode, rDestHi, rBase, rIndex, scale,
452 displacement + HIWORD_OFFSET);
453 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800454 }
455 }
456
457 return load;
buzbeee88dfbf2012-03-05 11:19:57 -0800458}
459
jeffhao5772bab2012-05-18 11:51:26 -0700460/* Load value from base + scaled index. */
461LIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
462 int rIndex, int rDest, int scale, OpSize size) {
buzbee408ad162012-06-06 16:45:18 -0700463 return loadBaseIndexedDisp(cUnit, rBase, rIndex, scale, 0,
jeffhao5772bab2012-05-18 11:51:26 -0700464 rDest, INVALID_REG, size, INVALID_SREG);
465}
466
buzbee408ad162012-06-06 16:45:18 -0700467LIR *loadBaseDisp(CompilationUnit *cUnit,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800468 int rBase, int displacement,
469 int rDest,
470 OpSize size, int sReg) {
buzbee408ad162012-06-06 16:45:18 -0700471 return loadBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0, displacement,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800472 rDest, INVALID_REG, size, sReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800473}
474
buzbee408ad162012-06-06 16:45:18 -0700475LIR *loadBaseDispWide(CompilationUnit *cUnit,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800476 int rBase, int displacement,
477 int rDestLo, int rDestHi,
478 int sReg) {
buzbee408ad162012-06-06 16:45:18 -0700479 return loadBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0, displacement,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800480 rDestLo, rDestHi, kLong, sReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800481}
482
buzbee408ad162012-06-06 16:45:18 -0700483LIR* storeBaseIndexedDisp(CompilationUnit *cUnit,
Ian Rogersb41b33b2012-03-20 14:22:54 -0700484 int rBase, int rIndex, int scale, int displacement,
485 int rSrc, int rSrcHi,
486 OpSize size, int sReg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800487 LIR *store = NULL;
jeffhaoe2962482012-06-28 11:29:57 -0700488 LIR *store2 = NULL;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700489 bool isArray = rIndex != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800490 bool pair = false;
jeffhaoe2962482012-06-28 11:29:57 -0700491 bool is64bit = false;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700492 X86OpCode opcode = kX86Nop;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800493 switch (size) {
494 case kLong:
495 case kDouble:
jeffhaoe2962482012-06-28 11:29:57 -0700496 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800497 if (X86_FPREG(rSrc)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700498 opcode = isArray ? kX86MovsdAR : kX86MovsdMR;
buzbeef0504cd2012-11-13 16:31:10 -0800499 if (X86_SINGLEREG(rSrc)) {
500 DCHECK(X86_FPREG(rSrcHi));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800501 DCHECK_EQ(rSrc, (rSrcHi - 1));
buzbeef0504cd2012-11-13 16:31:10 -0800502 rSrc = s2d(rSrc, rSrcHi);
buzbeee88dfbf2012-03-05 11:19:57 -0800503 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800504 rSrcHi = rSrc + 1;
505 } else {
506 pair = true;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700507 opcode = isArray ? kX86Mov32AR : kX86Mov32MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800508 }
509 // TODO: double store is to unaligned address
510 DCHECK_EQ((displacement & 0x3), 0);
511 break;
512 case kWord:
513 case kSingle:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700514 opcode = isArray ? kX86Mov32AR : kX86Mov32MR;
buzbeef0504cd2012-11-13 16:31:10 -0800515 if (X86_FPREG(rSrc)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700516 opcode = isArray ? kX86MovssAR : kX86MovssMR;
buzbeef0504cd2012-11-13 16:31:10 -0800517 DCHECK(X86_SINGLEREG(rSrc));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800518 }
519 DCHECK_EQ((displacement & 0x3), 0);
520 break;
521 case kUnsignedHalf:
522 case kSignedHalf:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700523 opcode = isArray ? kX86Mov16AR : kX86Mov16MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800524 DCHECK_EQ((displacement & 0x1), 0);
525 break;
526 case kUnsignedByte:
527 case kSignedByte:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700528 opcode = isArray ? kX86Mov8AR : kX86Mov8MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800529 break;
530 default:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700531 LOG(FATAL) << "Bad case in loadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800532 }
buzbeee88dfbf2012-03-05 11:19:57 -0800533
Ian Rogersb41b33b2012-03-20 14:22:54 -0700534 if (!isArray) {
535 if (!pair) {
536 store = newLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
537 } else {
538 store = newLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
jeffhaoe2962482012-06-28 11:29:57 -0700539 store2 = newLIR3(cUnit, opcode, rBase, displacement + HIWORD_OFFSET, rSrcHi);
540 }
buzbeef0504cd2012-11-13 16:31:10 -0800541 if (rBase == rX86_SP) {
jeffhaoe2962482012-06-28 11:29:57 -0700542 annotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0))
543 >> 2, false /* isLoad */, is64bit);
544 if (pair) {
545 annotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
546 false /* isLoad */, is64bit);
547 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700548 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800549 } else {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700550 if (!pair) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 store = newLIR5(cUnit, opcode, rBase, rIndex, scale,
552 displacement + LOWORD_OFFSET, rSrc);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700553 } else {
Elliott Hughes60234562012-06-01 12:25:59 -0700554 store = newLIR5(cUnit, opcode, rBase, rIndex, scale,
555 displacement + LOWORD_OFFSET, rSrc);
jeffhaoe2962482012-06-28 11:29:57 -0700556 store2 = newLIR5(cUnit, opcode, rBase, rIndex, scale,
557 displacement + HIWORD_OFFSET, rSrcHi);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800558 }
559 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700560
561 return store;
buzbeee88dfbf2012-03-05 11:19:57 -0800562}
563
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700564/* store value base base + scaled index. */
Bill Buzbeea114add2012-05-03 15:00:40 -0700565LIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase, int rIndex, int rSrc,
566 int scale, OpSize size)
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700567{
buzbee408ad162012-06-06 16:45:18 -0700568 return storeBaseIndexedDisp(cUnit, rBase, rIndex, scale, 0,
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700569 rSrc, INVALID_REG, size, INVALID_SREG);
570}
571
Bill Buzbeea114add2012-05-03 15:00:40 -0700572LIR *storeBaseDisp(CompilationUnit *cUnit, int rBase, int displacement,
573 int rSrc, OpSize size)
574{
buzbee408ad162012-06-06 16:45:18 -0700575 return storeBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700576 displacement, rSrc, INVALID_REG, size,
577 INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800578}
579
Ian Rogersb41b33b2012-03-20 14:22:54 -0700580LIR *storeBaseDispWide(CompilationUnit *cUnit, int rBase, int displacement,
Bill Buzbeea114add2012-05-03 15:00:40 -0700581 int rSrcLo, int rSrcHi)
582{
buzbee408ad162012-06-06 16:45:18 -0700583 return storeBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0, displacement,
Ian Rogersb41b33b2012-03-20 14:22:54 -0700584 rSrcLo, rSrcHi, kLong, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800585}
586
buzbeee88dfbf2012-03-05 11:19:57 -0800587void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
588{
jeffhaoe2962482012-06-28 11:29:57 -0700589 loadBaseDispWide(cUnit, base, 0, lowReg, highReg, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800590}
591
592} // namespace art