blob: e15995fef49bf701788c163449a5e628208d415a [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
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
17#include "codegen_x86.h"
18#include "dex/quick/mir_to_lir-inl.h"
19#include "x86_lir.h"
20
21namespace art {
22
23/* This file contains codegen for the X86 ISA */
24
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070025LIR* X86Mir2Lir::OpFpRegCopy(int r_dest, int r_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070026 int opcode;
27 /* must be both DOUBLE or both not DOUBLE */
28 DCHECK_EQ(X86_DOUBLEREG(r_dest), X86_DOUBLEREG(r_src));
29 if (X86_DOUBLEREG(r_dest)) {
30 opcode = kX86MovsdRR;
31 } else {
32 if (X86_SINGLEREG(r_dest)) {
33 if (X86_SINGLEREG(r_src)) {
34 opcode = kX86MovssRR;
35 } else { // Fpr <- Gpr
36 opcode = kX86MovdxrRR;
37 }
38 } else { // Gpr <- Fpr
39 DCHECK(X86_SINGLEREG(r_src));
40 opcode = kX86MovdrxRR;
41 }
42 }
43 DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
44 LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
45 if (r_dest == r_src) {
46 res->flags.is_nop = true;
47 }
48 return res;
49}
50
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070051bool X86Mir2Lir::InexpensiveConstantInt(int32_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070052 return true;
53}
54
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070055bool X86Mir2Lir::InexpensiveConstantFloat(int32_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070056 return false;
57}
58
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070059bool X86Mir2Lir::InexpensiveConstantLong(int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070060 return true;
61}
62
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070063bool X86Mir2Lir::InexpensiveConstantDouble(int64_t value) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -070064 return false; // TUNING
Brian Carlstrom7940e442013-07-12 13:46:57 -070065}
66
67/*
68 * Load a immediate using a shortcut if possible; otherwise
69 * grab from the per-translation literal pool. If target is
70 * a high register, build constant into a low register and copy.
71 *
72 * No additional register clobbering operation performed. Use this version when
73 * 1) r_dest is freshly returned from AllocTemp or
74 * 2) The codegen is under fixed register usage
75 */
Brian Carlstrom2ce745c2013-07-17 17:44:30 -070076LIR* X86Mir2Lir::LoadConstantNoClobber(int r_dest, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -070077 int r_dest_save = r_dest;
78 if (X86_FPREG(r_dest)) {
79 if (value == 0) {
80 return NewLIR2(kX86XorpsRR, r_dest, r_dest);
81 }
82 DCHECK(X86_SINGLEREG(r_dest));
83 r_dest = AllocTemp();
84 }
85
86 LIR *res;
87 if (value == 0) {
88 res = NewLIR2(kX86Xor32RR, r_dest, r_dest);
89 } else {
90 // Note, there is no byte immediate form of a 32 bit immediate move.
91 res = NewLIR2(kX86Mov32RI, r_dest, value);
92 }
93
94 if (X86_FPREG(r_dest_save)) {
95 NewLIR2(kX86MovdxrRR, r_dest_save, r_dest);
96 FreeTemp(r_dest);
97 }
98
99 return res;
100}
101
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700102LIR* X86Mir2Lir::OpUnconditionalBranch(LIR* target) {
Brian Carlstromdf629502013-07-17 22:39:56 -0700103 LIR* res = NewLIR1(kX86Jmp8, 0 /* offset to be patched during assembly*/);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700104 res->target = target;
105 return res;
106}
107
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700108LIR* X86Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700109 LIR* branch = NewLIR2(kX86Jcc8, 0 /* offset to be patched */,
110 X86ConditionEncoding(cc));
111 branch->target = target;
112 return branch;
113}
114
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700115LIR* X86Mir2Lir::OpReg(OpKind op, int r_dest_src) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700116 X86OpCode opcode = kX86Bkpt;
117 switch (op) {
118 case kOpNeg: opcode = kX86Neg32R; break;
119 case kOpNot: opcode = kX86Not32R; break;
120 case kOpBlx: opcode = kX86CallR; break;
121 default:
122 LOG(FATAL) << "Bad case in OpReg " << op;
123 }
124 return NewLIR1(opcode, r_dest_src);
125}
126
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700127LIR* X86Mir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700128 X86OpCode opcode = kX86Bkpt;
129 bool byte_imm = IS_SIMM8(value);
130 DCHECK(!X86_FPREG(r_dest_src1));
131 switch (op) {
132 case kOpLsl: opcode = kX86Sal32RI; break;
133 case kOpLsr: opcode = kX86Shr32RI; break;
134 case kOpAsr: opcode = kX86Sar32RI; break;
135 case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
136 case kOpOr: opcode = byte_imm ? kX86Or32RI8 : kX86Or32RI; break;
137 case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700138 // case kOpSbb: opcode = kX86Sbb32RI; break;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700139 case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
140 case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
141 case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
142 case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
143 case kOpMov: return LoadConstantNoClobber(r_dest_src1, value);
144 case kOpMul:
145 opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
146 return NewLIR3(opcode, r_dest_src1, r_dest_src1, value);
147 default:
148 LOG(FATAL) << "Bad case in OpRegImm " << op;
149 }
150 return NewLIR2(opcode, r_dest_src1, value);
151}
152
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700153LIR* X86Mir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700154 X86OpCode opcode = kX86Nop;
155 bool src2_must_be_cx = false;
156 switch (op) {
157 // X86 unary opcodes
158 case kOpMvn:
159 OpRegCopy(r_dest_src1, r_src2);
160 return OpReg(kOpNot, r_dest_src1);
161 case kOpNeg:
162 OpRegCopy(r_dest_src1, r_src2);
163 return OpReg(kOpNeg, r_dest_src1);
164 // X86 binary opcodes
165 case kOpSub: opcode = kX86Sub32RR; break;
166 case kOpSbc: opcode = kX86Sbb32RR; break;
167 case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
168 case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
169 case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
170 case kOpMov: opcode = kX86Mov32RR; break;
171 case kOpCmp: opcode = kX86Cmp32RR; break;
172 case kOpAdd: opcode = kX86Add32RR; break;
173 case kOpAdc: opcode = kX86Adc32RR; break;
174 case kOpAnd: opcode = kX86And32RR; break;
175 case kOpOr: opcode = kX86Or32RR; break;
176 case kOpXor: opcode = kX86Xor32RR; break;
177 case kOp2Byte:
178 // Use shifts instead of a byte operand if the source can't be byte accessed.
179 if (r_src2 >= 4) {
180 NewLIR2(kX86Mov32RR, r_dest_src1, r_src2);
181 NewLIR2(kX86Sal32RI, r_dest_src1, 24);
182 return NewLIR2(kX86Sar32RI, r_dest_src1, 24);
183 } else {
184 opcode = kX86Movsx8RR;
185 }
186 break;
187 case kOp2Short: opcode = kX86Movsx16RR; break;
188 case kOp2Char: opcode = kX86Movzx16RR; break;
189 case kOpMul: opcode = kX86Imul32RR; break;
190 default:
191 LOG(FATAL) << "Bad case in OpRegReg " << op;
192 break;
193 }
194 CHECK(!src2_must_be_cx || r_src2 == rCX);
195 return NewLIR2(opcode, r_dest_src1, r_src2);
196}
197
198LIR* X86Mir2Lir::OpRegMem(OpKind op, int r_dest, int rBase,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700199 int offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700200 X86OpCode opcode = kX86Nop;
201 switch (op) {
202 // X86 binary opcodes
203 case kOpSub: opcode = kX86Sub32RM; break;
204 case kOpMov: opcode = kX86Mov32RM; break;
205 case kOpCmp: opcode = kX86Cmp32RM; break;
206 case kOpAdd: opcode = kX86Add32RM; break;
207 case kOpAnd: opcode = kX86And32RM; break;
208 case kOpOr: opcode = kX86Or32RM; break;
209 case kOpXor: opcode = kX86Xor32RM; break;
210 case kOp2Byte: opcode = kX86Movsx8RM; break;
211 case kOp2Short: opcode = kX86Movsx16RM; break;
212 case kOp2Char: opcode = kX86Movzx16RM; break;
213 case kOpMul:
214 default:
215 LOG(FATAL) << "Bad case in OpRegMem " << op;
216 break;
217 }
218 return NewLIR3(opcode, r_dest, rBase, offset);
219}
220
221LIR* X86Mir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700222 int r_src2) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700223 if (r_dest != r_src1 && r_dest != r_src2) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700224 if (op == kOpAdd) { // lea special case, except can't encode rbp as base
Brian Carlstrom7940e442013-07-12 13:46:57 -0700225 if (r_src1 == r_src2) {
226 OpRegCopy(r_dest, r_src1);
227 return OpRegImm(kOpLsl, r_dest, 1);
228 } else if (r_src1 != rBP) {
229 return NewLIR5(kX86Lea32RA, r_dest, r_src1 /* base */,
230 r_src2 /* index */, 0 /* scale */, 0 /* disp */);
231 } else {
232 return NewLIR5(kX86Lea32RA, r_dest, r_src2 /* base */,
233 r_src1 /* index */, 0 /* scale */, 0 /* disp */);
234 }
235 } else {
236 OpRegCopy(r_dest, r_src1);
237 return OpRegReg(op, r_dest, r_src2);
238 }
239 } else if (r_dest == r_src1) {
240 return OpRegReg(op, r_dest, r_src2);
241 } else { // r_dest == r_src2
242 switch (op) {
243 case kOpSub: // non-commutative
244 OpReg(kOpNeg, r_dest);
245 op = kOpAdd;
246 break;
247 case kOpSbc:
248 case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
249 int t_reg = AllocTemp();
250 OpRegCopy(t_reg, r_src1);
251 OpRegReg(op, t_reg, r_src2);
252 LIR* res = OpRegCopy(r_dest, t_reg);
253 FreeTemp(t_reg);
254 return res;
255 }
256 case kOpAdd: // commutative
257 case kOpOr:
258 case kOpAdc:
259 case kOpAnd:
260 case kOpXor:
261 break;
262 default:
263 LOG(FATAL) << "Bad case in OpRegRegReg " << op;
264 }
265 return OpRegReg(op, r_dest, r_src1);
266 }
267}
268
269LIR* X86Mir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700270 int value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700271 if (op == kOpMul) {
272 X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
273 return NewLIR3(opcode, r_dest, r_src, value);
274 } else if (op == kOpAnd) {
275 if (value == 0xFF && r_src < 4) {
276 return NewLIR2(kX86Movzx8RR, r_dest, r_src);
277 } else if (value == 0xFFFF) {
278 return NewLIR2(kX86Movzx16RR, r_dest, r_src);
279 }
280 }
281 if (r_dest != r_src) {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700282 if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
Brian Carlstrom7940e442013-07-12 13:46:57 -0700283 // TODO: fix bug in LEA encoding when disp == 0
284 return NewLIR5(kX86Lea32RA, r_dest, r5sib_no_base /* base */,
285 r_src /* index */, value /* scale */, 0 /* disp */);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700286 } else if (op == kOpAdd) { // lea add special case
Brian Carlstrom7940e442013-07-12 13:46:57 -0700287 return NewLIR5(kX86Lea32RA, r_dest, r_src /* base */,
288 r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
289 }
290 OpRegCopy(r_dest, r_src);
291 }
292 return OpRegImm(op, r_dest, value);
293}
294
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700295LIR* X86Mir2Lir::OpThreadMem(OpKind op, int thread_offset) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700296 X86OpCode opcode = kX86Bkpt;
297 switch (op) {
298 case kOpBlx: opcode = kX86CallT; break;
299 default:
300 LOG(FATAL) << "Bad opcode: " << op;
301 break;
302 }
303 return NewLIR1(opcode, thread_offset);
304}
305
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700306LIR* X86Mir2Lir::OpMem(OpKind op, int rBase, int disp) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700307 X86OpCode opcode = kX86Bkpt;
308 switch (op) {
309 case kOpBlx: opcode = kX86CallM; break;
310 default:
311 LOG(FATAL) << "Bad opcode: " << op;
312 break;
313 }
314 return NewLIR2(opcode, rBase, disp);
315}
316
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700317LIR* X86Mir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700318 int32_t val_lo = Low32Bits(value);
319 int32_t val_hi = High32Bits(value);
320 LIR *res;
321 if (X86_FPREG(r_dest_lo)) {
322 DCHECK(X86_FPREG(r_dest_hi)); // ignore r_dest_hi
323 if (value == 0) {
324 return NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo);
325 } else {
326 if (val_lo == 0) {
327 res = NewLIR2(kX86XorpsRR, r_dest_lo, r_dest_lo);
328 } else {
329 res = LoadConstantNoClobber(r_dest_lo, val_lo);
330 }
331 if (val_hi != 0) {
332 LoadConstantNoClobber(r_dest_hi, val_hi);
333 NewLIR2(kX86PsllqRI, r_dest_hi, 32);
334 NewLIR2(kX86OrpsRR, r_dest_lo, r_dest_hi);
335 }
336 }
337 } else {
338 res = LoadConstantNoClobber(r_dest_lo, val_lo);
339 LoadConstantNoClobber(r_dest_hi, val_hi);
340 }
341 return res;
342}
343
344LIR* X86Mir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale,
345 int displacement, int r_dest, int r_dest_hi, OpSize size,
346 int s_reg) {
347 LIR *load = NULL;
348 LIR *load2 = NULL;
349 bool is_array = r_index != INVALID_REG;
350 bool pair = false;
351 bool is64bit = false;
352 X86OpCode opcode = kX86Nop;
353 switch (size) {
354 case kLong:
355 case kDouble:
356 is64bit = true;
357 if (X86_FPREG(r_dest)) {
358 opcode = is_array ? kX86MovsdRA : kX86MovsdRM;
359 if (X86_SINGLEREG(r_dest)) {
360 DCHECK(X86_FPREG(r_dest_hi));
361 DCHECK_EQ(r_dest, (r_dest_hi - 1));
362 r_dest = S2d(r_dest, r_dest_hi);
363 }
364 r_dest_hi = r_dest + 1;
365 } else {
366 pair = true;
367 opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
368 }
369 // TODO: double store is to unaligned address
370 DCHECK_EQ((displacement & 0x3), 0);
371 break;
372 case kWord:
373 case kSingle:
374 opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
375 if (X86_FPREG(r_dest)) {
376 opcode = is_array ? kX86MovssRA : kX86MovssRM;
377 DCHECK(X86_SINGLEREG(r_dest));
378 }
379 DCHECK_EQ((displacement & 0x3), 0);
380 break;
381 case kUnsignedHalf:
382 opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM;
383 DCHECK_EQ((displacement & 0x1), 0);
384 break;
385 case kSignedHalf:
386 opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM;
387 DCHECK_EQ((displacement & 0x1), 0);
388 break;
389 case kUnsignedByte:
390 opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM;
391 break;
392 case kSignedByte:
393 opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM;
394 break;
395 default:
396 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
397 }
398
399 if (!is_array) {
400 if (!pair) {
401 load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
402 } else {
403 if (rBase == r_dest) {
404 load2 = NewLIR3(opcode, r_dest_hi, rBase,
405 displacement + HIWORD_OFFSET);
406 load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
407 } else {
408 load = NewLIR3(opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
409 load2 = NewLIR3(opcode, r_dest_hi, rBase,
410 displacement + HIWORD_OFFSET);
411 }
412 }
413 if (rBase == rX86_SP) {
414 AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
415 true /* is_load */, is64bit);
416 if (pair) {
417 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
418 true /* is_load */, is64bit);
419 }
420 }
421 } else {
422 if (!pair) {
423 load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
424 displacement + LOWORD_OFFSET);
425 } else {
426 if (rBase == r_dest) {
427 load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale,
428 displacement + HIWORD_OFFSET);
429 load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
430 displacement + LOWORD_OFFSET);
431 } else {
432 load = NewLIR5(opcode, r_dest, rBase, r_index, scale,
433 displacement + LOWORD_OFFSET);
434 load2 = NewLIR5(opcode, r_dest_hi, rBase, r_index, scale,
435 displacement + HIWORD_OFFSET);
436 }
437 }
438 }
439
440 return load;
441}
442
443/* Load value from base + scaled index. */
444LIR* X86Mir2Lir::LoadBaseIndexed(int rBase,
445 int r_index, int r_dest, int scale, OpSize size) {
446 return LoadBaseIndexedDisp(rBase, r_index, scale, 0,
447 r_dest, INVALID_REG, size, INVALID_SREG);
448}
449
450LIR* X86Mir2Lir::LoadBaseDisp(int rBase, int displacement,
451 int r_dest, OpSize size, int s_reg) {
452 return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
453 r_dest, INVALID_REG, size, s_reg);
454}
455
456LIR* X86Mir2Lir::LoadBaseDispWide(int rBase, int displacement,
457 int r_dest_lo, int r_dest_hi, int s_reg) {
458 return LoadBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
459 r_dest_lo, r_dest_hi, kLong, s_reg);
460}
461
462LIR* X86Mir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale,
463 int displacement, int r_src, int r_src_hi, OpSize size,
464 int s_reg) {
465 LIR *store = NULL;
466 LIR *store2 = NULL;
467 bool is_array = r_index != INVALID_REG;
468 bool pair = false;
469 bool is64bit = false;
470 X86OpCode opcode = kX86Nop;
471 switch (size) {
472 case kLong:
473 case kDouble:
474 is64bit = true;
475 if (X86_FPREG(r_src)) {
476 opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
477 if (X86_SINGLEREG(r_src)) {
478 DCHECK(X86_FPREG(r_src_hi));
479 DCHECK_EQ(r_src, (r_src_hi - 1));
480 r_src = S2d(r_src, r_src_hi);
481 }
482 r_src_hi = r_src + 1;
483 } else {
484 pair = true;
485 opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
486 }
487 // TODO: double store is to unaligned address
488 DCHECK_EQ((displacement & 0x3), 0);
489 break;
490 case kWord:
491 case kSingle:
492 opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
493 if (X86_FPREG(r_src)) {
494 opcode = is_array ? kX86MovssAR : kX86MovssMR;
495 DCHECK(X86_SINGLEREG(r_src));
496 }
497 DCHECK_EQ((displacement & 0x3), 0);
498 break;
499 case kUnsignedHalf:
500 case kSignedHalf:
501 opcode = is_array ? kX86Mov16AR : kX86Mov16MR;
502 DCHECK_EQ((displacement & 0x1), 0);
503 break;
504 case kUnsignedByte:
505 case kSignedByte:
506 opcode = is_array ? kX86Mov8AR : kX86Mov8MR;
507 break;
508 default:
509 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
510 }
511
512 if (!is_array) {
513 if (!pair) {
514 store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src);
515 } else {
516 store = NewLIR3(opcode, rBase, displacement + LOWORD_OFFSET, r_src);
517 store2 = NewLIR3(opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi);
518 }
519 if (rBase == rX86_SP) {
520 AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
521 false /* is_load */, is64bit);
522 if (pair) {
523 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
524 false /* is_load */, is64bit);
525 }
526 }
527 } else {
528 if (!pair) {
529 store = NewLIR5(opcode, rBase, r_index, scale,
530 displacement + LOWORD_OFFSET, r_src);
531 } else {
532 store = NewLIR5(opcode, rBase, r_index, scale,
533 displacement + LOWORD_OFFSET, r_src);
534 store2 = NewLIR5(opcode, rBase, r_index, scale,
535 displacement + HIWORD_OFFSET, r_src_hi);
536 }
537 }
538
539 return store;
540}
541
542/* store value base base + scaled index. */
543LIR* X86Mir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700544 int scale, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700545 return StoreBaseIndexedDisp(rBase, r_index, scale, 0,
546 r_src, INVALID_REG, size, INVALID_SREG);
547}
548
549LIR* X86Mir2Lir::StoreBaseDisp(int rBase, int displacement,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700550 int r_src, OpSize size) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700551 return StoreBaseIndexedDisp(rBase, INVALID_REG, 0,
552 displacement, r_src, INVALID_REG, size,
553 INVALID_SREG);
554}
555
556LIR* X86Mir2Lir::StoreBaseDispWide(int rBase, int displacement,
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700557 int r_src_lo, int r_src_hi) {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700558 return StoreBaseIndexedDisp(rBase, INVALID_REG, 0, displacement,
559 r_src_lo, r_src_hi, kLong, INVALID_SREG);
560}
561
562} // namespace art