blob: ce55b4bf228c59487d5bb2cb04d9f4a2fd746d1a [file] [log] [blame]
buzbeee88dfbf2012-03-05 11:19:57 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
buzbee1bc37c62012-11-20 13:35:41 -080017#include "x86_lir.h"
buzbee02031b12012-11-23 09:41:35 -080018#include "codegen_x86.h"
buzbee1bc37c62012-11-20 13:35:41 -080019#include "../codegen_util.h"
20#include "../ralloc_util.h"
21
buzbeee88dfbf2012-03-05 11:19:57 -080022namespace art {
23
buzbeeb046e162012-10-30 15:48:42 -070024/* This file contains codegen for the X86 ISA */
buzbeee88dfbf2012-03-05 11:19:57 -080025
buzbee02031b12012-11-23 09:41:35 -080026LIR* X86Codegen::OpFpRegCopy(CompilationUnit *cu, int r_dest, int r_src)
buzbeee88dfbf2012-03-05 11:19:57 -080027{
Bill Buzbeea114add2012-05-03 15:00:40 -070028 int opcode;
29 /* must be both DOUBLE or both not DOUBLE */
buzbeefa57c472012-11-21 12:06:18 -080030 DCHECK_EQ(X86_DOUBLEREG(r_dest), X86_DOUBLEREG(r_src));
31 if (X86_DOUBLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070032 opcode = kX86MovsdRR;
33 } else {
buzbeefa57c472012-11-21 12:06:18 -080034 if (X86_SINGLEREG(r_dest)) {
35 if (X86_SINGLEREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070036 opcode = kX86MovssRR;
37 } else { // Fpr <- Gpr
38 opcode = kX86MovdxrRR;
39 }
40 } else { // Gpr <- Fpr
buzbeefa57c472012-11-21 12:06:18 -080041 DCHECK(X86_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -070042 opcode = kX86MovdrxRR;
buzbeee88dfbf2012-03-05 11:19:57 -080043 }
Bill Buzbeea114add2012-05-03 15:00:40 -070044 }
buzbeeec137432012-11-13 12:13:16 -080045 DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
buzbeefa57c472012-11-21 12:06:18 -080046 LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src);
47 if (r_dest == r_src) {
48 res->flags.is_nop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -070049 }
50 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080051}
52
buzbeee6285f92012-12-06 15:57:46 -080053bool X86Codegen::InexpensiveConstant(int reg, int value)
54{
55 return true;
56}
57
buzbeee88dfbf2012-03-05 11:19:57 -080058/*
59 * Load a immediate using a shortcut if possible; otherwise
60 * grab from the per-translation literal pool. If target is
61 * a high register, build constant into a low register and copy.
62 *
63 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -080064 * 1) r_dest is freshly returned from AllocTemp or
buzbeee88dfbf2012-03-05 11:19:57 -080065 * 2) The codegen is under fixed register usage
66 */
buzbee02031b12012-11-23 09:41:35 -080067LIR* X86Codegen::LoadConstantNoClobber(CompilationUnit *cu, int r_dest, int value)
Bill Buzbeea114add2012-05-03 15:00:40 -070068{
buzbeefa57c472012-11-21 12:06:18 -080069 int r_dest_save = r_dest;
70 if (X86_FPREG(r_dest)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -070071 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -080072 return NewLIR2(cu, kX86XorpsRR, r_dest, r_dest);
Ian Rogersb41b33b2012-03-20 14:22:54 -070073 }
buzbeefa57c472012-11-21 12:06:18 -080074 DCHECK(X86_SINGLEREG(r_dest));
75 r_dest = AllocTemp(cu);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070076 }
buzbeee88dfbf2012-03-05 11:19:57 -080077
Ian Rogersb41b33b2012-03-20 14:22:54 -070078 LIR *res;
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070079 if (value == 0) {
buzbeefa57c472012-11-21 12:06:18 -080080 res = NewLIR2(cu, kX86Xor32RR, r_dest, r_dest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070081 } else {
Ian Rogers2e9f7ed2012-09-26 11:30:43 -070082 // Note, there is no byte immediate form of a 32 bit immediate move.
buzbeefa57c472012-11-21 12:06:18 -080083 res = NewLIR2(cu, kX86Mov32RI, r_dest, value);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070084 }
buzbeee88dfbf2012-03-05 11:19:57 -080085
buzbeefa57c472012-11-21 12:06:18 -080086 if (X86_FPREG(r_dest_save)) {
87 NewLIR2(cu, kX86MovdxrRR, r_dest_save, r_dest);
88 FreeTemp(cu, r_dest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070089 }
buzbeee88dfbf2012-03-05 11:19:57 -080090
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070091 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080092}
93
buzbee02031b12012-11-23 09:41:35 -080094LIR* X86Codegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
Bill Buzbeea114add2012-05-03 15:00:40 -070095{
buzbee02031b12012-11-23 09:41:35 -080096 LIR* res = NewLIR1(cu, kX86Jmp8, 0 /* offset to be patched during assembly*/ );
97 res->target = target;
98 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080099}
100
buzbee02031b12012-11-23 09:41:35 -0800101LIR* X86Codegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbeea7678db2012-03-05 15:35:46 -0800102{
buzbeefa57c472012-11-21 12:06:18 -0800103 LIR* branch = NewLIR2(cu, kX86Jcc8, 0 /* offset to be patched */,
buzbee52a77fc2012-11-20 19:50:46 -0800104 X86ConditionEncoding(cc));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800105 branch->target = target;
106 return branch;
buzbeea7678db2012-03-05 15:35:46 -0800107}
108
buzbee02031b12012-11-23 09:41:35 -0800109LIR* X86Codegen::OpReg(CompilationUnit *cu, OpKind op, int r_dest_src)
Bill Buzbeea114add2012-05-03 15:00:40 -0700110{
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:
buzbee52a77fc2012-11-20 19:50:46 -0800117 LOG(FATAL) << "Bad case in OpReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800118 }
buzbeefa57c472012-11-21 12:06:18 -0800119 return NewLIR1(cu, opcode, r_dest_src);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800120}
121
buzbee02031b12012-11-23 09:41:35 -0800122LIR* X86Codegen::OpRegImm(CompilationUnit *cu, OpKind op, int r_dest_src1, int value)
Bill Buzbeea114add2012-05-03 15:00:40 -0700123{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800124 X86OpCode opcode = kX86Bkpt;
buzbeefa57c472012-11-21 12:06:18 -0800125 bool byte_imm = IS_SIMM8(value);
126 DCHECK(!X86_FPREG(r_dest_src1));
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;
buzbeefa57c472012-11-21 12:06:18 -0800131 case kOpAdd: opcode = byte_imm ? kX86Add32RI8 : kX86Add32RI; break;
132 case kOpOr: opcode = byte_imm ? kX86Or32RI8 : kX86Or32RI; break;
133 case kOpAdc: opcode = byte_imm ? kX86Adc32RI8 : kX86Adc32RI; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800134 //case kOpSbb: opcode = kX86Sbb32RI; break;
buzbeefa57c472012-11-21 12:06:18 -0800135 case kOpAnd: opcode = byte_imm ? kX86And32RI8 : kX86And32RI; break;
136 case kOpSub: opcode = byte_imm ? kX86Sub32RI8 : kX86Sub32RI; break;
137 case kOpXor: opcode = byte_imm ? kX86Xor32RI8 : kX86Xor32RI; break;
138 case kOpCmp: opcode = byte_imm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
139 case kOpMov: return LoadConstantNoClobber(cu, r_dest_src1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800140 case kOpMul:
buzbeefa57c472012-11-21 12:06:18 -0800141 opcode = byte_imm ? kX86Imul32RRI8 : kX86Imul32RRI;
142 return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800143 default:
buzbee52a77fc2012-11-20 19:50:46 -0800144 LOG(FATAL) << "Bad case in OpRegImm " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800145 }
buzbeefa57c472012-11-21 12:06:18 -0800146 return NewLIR2(cu, opcode, r_dest_src1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800147}
148
buzbee02031b12012-11-23 09:41:35 -0800149LIR* X86Codegen::OpRegReg(CompilationUnit *cu, OpKind op, int r_dest_src1, int r_src2)
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:
buzbeefa57c472012-11-21 12:06:18 -0800156 OpRegCopy(cu, r_dest_src1, r_src2);
157 return OpReg(cu, kOpNot, r_dest_src1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800158 case kOpNeg:
buzbeefa57c472012-11-21 12:06:18 -0800159 OpRegCopy(cu, r_dest_src1, r_src2);
160 return OpReg(cu, kOpNeg, r_dest_src1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800161 // 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.
buzbeefa57c472012-11-21 12:06:18 -0800176 if (r_src2 >= 4) {
177 NewLIR2(cu, kX86Mov32RR, r_dest_src1, r_src2);
178 NewLIR2(cu, kX86Sal32RI, r_dest_src1, 24);
179 return NewLIR2(cu, kX86Sar32RI, r_dest_src1, 24);
jeffhao703f2cd2012-07-13 17:25:52 -0700180 } 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:
buzbee52a77fc2012-11-20 19:50:46 -0800188 LOG(FATAL) << "Bad case in OpRegReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800189 break;
buzbeee88dfbf2012-03-05 11:19:57 -0800190 }
buzbeefa57c472012-11-21 12:06:18 -0800191 CHECK(!src2_must_be_cx || r_src2 == rCX);
192 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800193}
194
buzbee02031b12012-11-23 09:41:35 -0800195LIR* X86Codegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700196 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:
buzbee52a77fc2012-11-20 19:50:46 -0800213 LOG(FATAL) << "Bad case in OpRegMem " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800214 break;
215 }
buzbeefa57c472012-11-21 12:06:18 -0800216 return NewLIR3(cu, opcode, r_dest, rBase, offset);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800217}
218
buzbee02031b12012-11-23 09:41:35 -0800219LIR* X86Codegen::OpRegRegReg(CompilationUnit *cu, OpKind op, int r_dest, int r_src1,
buzbeefa57c472012-11-21 12:06:18 -0800220 int r_src2)
Bill Buzbeea114add2012-05-03 15:00:40 -0700221{
buzbeefa57c472012-11-21 12:06:18 -0800222 if (r_dest != r_src1 && r_dest != r_src2) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800223 if (op == kOpAdd) { // lea special case, except can't encode rbp as base
buzbeefa57c472012-11-21 12:06:18 -0800224 if (r_src1 == r_src2) {
225 OpRegCopy(cu, r_dest, r_src1);
226 return OpRegImm(cu, kOpLsl, r_dest, 1);
227 } else if (r_src1 != rBP) {
228 return NewLIR5(cu, kX86Lea32RA, r_dest, r_src1 /* base */,
229 r_src2 /* index */, 0 /* scale */, 0 /* disp */);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800230 } else {
buzbeefa57c472012-11-21 12:06:18 -0800231 return NewLIR5(cu, kX86Lea32RA, r_dest, r_src2 /* base */,
232 r_src1 /* index */, 0 /* scale */, 0 /* disp */);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800233 }
234 } else {
buzbeefa57c472012-11-21 12:06:18 -0800235 OpRegCopy(cu, r_dest, r_src1);
236 return OpRegReg(cu, op, r_dest, r_src2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800237 }
buzbeefa57c472012-11-21 12:06:18 -0800238 } else if (r_dest == r_src1) {
239 return OpRegReg(cu, op, r_dest, r_src2);
240 } else { // r_dest == r_src2
Ian Rogersb5d09b22012-03-06 22:14:17 -0800241 switch (op) {
242 case kOpSub: // non-commutative
buzbeefa57c472012-11-21 12:06:18 -0800243 OpReg(cu, kOpNeg, r_dest);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800244 op = kOpAdd;
245 break;
246 case kOpSbc:
247 case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
buzbeefa57c472012-11-21 12:06:18 -0800248 int t_reg = AllocTemp(cu);
249 OpRegCopy(cu, t_reg, r_src1);
250 OpRegReg(cu, op, t_reg, r_src2);
251 LIR* res = OpRegCopy(cu, r_dest, t_reg);
252 FreeTemp(cu, t_reg);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800253 return res;
254 }
255 case kOpAdd: // commutative
256 case kOpOr:
257 case kOpAdc:
258 case kOpAnd:
259 case kOpXor:
260 break;
261 default:
buzbee52a77fc2012-11-20 19:50:46 -0800262 LOG(FATAL) << "Bad case in OpRegRegReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800263 }
buzbeefa57c472012-11-21 12:06:18 -0800264 return OpRegReg(cu, op, r_dest, r_src1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800265 }
266}
267
buzbee02031b12012-11-23 09:41:35 -0800268LIR* X86Codegen::OpRegRegImm(CompilationUnit *cu, OpKind op, int r_dest, int r_src,
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 int value)
270{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800271 if (op == kOpMul) {
272 X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
buzbeefa57c472012-11-21 12:06:18 -0800273 return NewLIR3(cu, opcode, r_dest, r_src, value);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700274 } else if (op == kOpAnd) {
buzbeefa57c472012-11-21 12:06:18 -0800275 if (value == 0xFF && r_src < 4) {
276 return NewLIR2(cu, kX86Movzx8RR, r_dest, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700277 } else if (value == 0xFFFF) {
buzbeefa57c472012-11-21 12:06:18 -0800278 return NewLIR2(cu, kX86Movzx16RR, r_dest, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700279 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800280 }
buzbeefa57c472012-11-21 12:06:18 -0800281 if (r_dest != r_src) {
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
buzbeefa57c472012-11-21 12:06:18 -0800284 return NewLIR5(cu, kX86Lea32RA, r_dest, r5sib_no_base /* base */,
285 r_src /* index */, value /* scale */, 0 /* disp */);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700286 } else if (op == kOpAdd) { // lea add special case
buzbeefa57c472012-11-21 12:06:18 -0800287 return NewLIR5(cu, kX86Lea32RA, r_dest, r_src /* base */,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800288 r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
289 }
buzbeefa57c472012-11-21 12:06:18 -0800290 OpRegCopy(cu, r_dest, r_src);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800291 }
buzbeefa57c472012-11-21 12:06:18 -0800292 return OpRegImm(cu, op, r_dest, value);
buzbeee88dfbf2012-03-05 11:19:57 -0800293}
294
buzbee02031b12012-11-23 09:41:35 -0800295LIR* X86Codegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
Bill Buzbeea114add2012-05-03 15:00:40 -0700296{
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 }
buzbeefa57c472012-11-21 12:06:18 -0800304 return NewLIR1(cu, opcode, thread_offset);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700305}
306
buzbee02031b12012-11-23 09:41:35 -0800307LIR* X86Codegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
Bill Buzbeea114add2012-05-03 15:00:40 -0700308{
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 }
buzbeefa57c472012-11-21 12:06:18 -0800316 return NewLIR2(cu, opcode, rBase, disp);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700317}
318
buzbee02031b12012-11-23 09:41:35 -0800319LIR* X86Codegen::LoadConstantValueWide(CompilationUnit *cu, int r_dest_lo,
320 int r_dest_hi, int val_lo, int val_hi)
buzbeee88dfbf2012-03-05 11:19:57 -0800321{
322 LIR *res;
buzbeefa57c472012-11-21 12:06:18 -0800323 if (X86_FPREG(r_dest_lo)) {
324 DCHECK(X86_FPREG(r_dest_hi)); // ignore r_dest_hi
325 if (val_lo == 0 && val_hi == 0) {
326 return NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700327 } else {
buzbeefa57c472012-11-21 12:06:18 -0800328 if (val_lo == 0) {
329 res = NewLIR2(cu, kX86XorpsRR, r_dest_lo, r_dest_lo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700330 } else {
buzbeefa57c472012-11-21 12:06:18 -0800331 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700332 }
buzbeefa57c472012-11-21 12:06:18 -0800333 if (val_hi != 0) {
334 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
335 NewLIR2(cu, kX86PsllqRI, r_dest_hi, 32);
336 NewLIR2(cu, kX86OrpsRR, r_dest_lo, r_dest_hi);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700337 }
338 }
339 } else {
buzbeefa57c472012-11-21 12:06:18 -0800340 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
341 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700342 }
buzbeee88dfbf2012-03-05 11:19:57 -0800343 return res;
344}
345
buzbee02031b12012-11-23 09:41:35 -0800346LIR* X86Codegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
347 int displacement, int r_dest, int r_dest_hi, OpSize size,
348 int s_reg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800349 LIR *load = NULL;
350 LIR *load2 = NULL;
buzbeefa57c472012-11-21 12:06:18 -0800351 bool is_array = r_index != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800352 bool pair = false;
353 bool is64bit = false;
354 X86OpCode opcode = kX86Nop;
355 switch (size) {
356 case kLong:
357 case kDouble:
358 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800359 if (X86_FPREG(r_dest)) {
360 opcode = is_array ? kX86MovsdRA : kX86MovsdRM;
361 if (X86_SINGLEREG(r_dest)) {
362 DCHECK(X86_FPREG(r_dest_hi));
363 DCHECK_EQ(r_dest, (r_dest_hi - 1));
364 r_dest = S2d(r_dest, r_dest_hi);
buzbeee88dfbf2012-03-05 11:19:57 -0800365 }
buzbeefa57c472012-11-21 12:06:18 -0800366 r_dest_hi = r_dest + 1;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800367 } else {
368 pair = true;
buzbeefa57c472012-11-21 12:06:18 -0800369 opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800370 }
371 // TODO: double store is to unaligned address
372 DCHECK_EQ((displacement & 0x3), 0);
373 break;
374 case kWord:
375 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800376 opcode = is_array ? kX86Mov32RA : kX86Mov32RM;
377 if (X86_FPREG(r_dest)) {
378 opcode = is_array ? kX86MovssRA : kX86MovssRM;
379 DCHECK(X86_SINGLEREG(r_dest));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800380 }
381 DCHECK_EQ((displacement & 0x3), 0);
382 break;
383 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800384 opcode = is_array ? kX86Movzx16RA : kX86Movzx16RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800385 DCHECK_EQ((displacement & 0x1), 0);
386 break;
387 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800388 opcode = is_array ? kX86Movsx16RA : kX86Movsx16RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800389 DCHECK_EQ((displacement & 0x1), 0);
390 break;
391 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800392 opcode = is_array ? kX86Movzx8RA : kX86Movzx8RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800393 break;
394 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800395 opcode = is_array ? kX86Movsx8RA : kX86Movsx8RM;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800396 break;
397 default:
buzbee52a77fc2012-11-20 19:50:46 -0800398 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800399 }
400
buzbeefa57c472012-11-21 12:06:18 -0800401 if (!is_array) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800402 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800403 load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
buzbeee88dfbf2012-03-05 11:19:57 -0800404 } else {
buzbeefa57c472012-11-21 12:06:18 -0800405 if (rBase == r_dest) {
406 load2 = NewLIR3(cu, opcode, r_dest_hi, rBase,
jeffhaofdffdf82012-07-11 16:08:43 -0700407 displacement + HIWORD_OFFSET);
buzbeefa57c472012-11-21 12:06:18 -0800408 load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
jeffhaofdffdf82012-07-11 16:08:43 -0700409 } else {
buzbeefa57c472012-11-21 12:06:18 -0800410 load = NewLIR3(cu, opcode, r_dest, rBase, displacement + LOWORD_OFFSET);
411 load2 = NewLIR3(cu, opcode, r_dest_hi, rBase,
jeffhaofdffdf82012-07-11 16:08:43 -0700412 displacement + HIWORD_OFFSET);
413 }
buzbeee88dfbf2012-03-05 11:19:57 -0800414 }
buzbeef0504cd2012-11-13 16:31:10 -0800415 if (rBase == rX86_SP) {
buzbee02031b12012-11-23 09:41:35 -0800416 AnnotateDalvikRegAccess(cu, load, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
417 true /* is_load */, is64bit);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700418 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800419 AnnotateDalvikRegAccess(cu, load2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800420 true /* is_load */, is64bit);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800421 }
buzbeee88dfbf2012-03-05 11:19:57 -0800422 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800423 } else {
424 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800425 load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
Bill Buzbeea114add2012-05-03 15:00:40 -0700426 displacement + LOWORD_OFFSET);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800427 } else {
buzbeefa57c472012-11-21 12:06:18 -0800428 if (rBase == r_dest) {
429 load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700430 displacement + HIWORD_OFFSET);
buzbeefa57c472012-11-21 12:06:18 -0800431 load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700432 displacement + LOWORD_OFFSET);
433 } else {
buzbeefa57c472012-11-21 12:06:18 -0800434 load = NewLIR5(cu, opcode, r_dest, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700435 displacement + LOWORD_OFFSET);
buzbeefa57c472012-11-21 12:06:18 -0800436 load2 = NewLIR5(cu, opcode, r_dest_hi, rBase, r_index, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700437 displacement + HIWORD_OFFSET);
438 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800439 }
440 }
441
442 return load;
buzbeee88dfbf2012-03-05 11:19:57 -0800443}
444
jeffhao5772bab2012-05-18 11:51:26 -0700445/* Load value from base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800446LIR* X86Codegen::LoadBaseIndexed(CompilationUnit *cu, int rBase,
buzbeefa57c472012-11-21 12:06:18 -0800447 int r_index, int r_dest, int scale, OpSize size) {
448 return LoadBaseIndexedDisp(cu, rBase, r_index, scale, 0,
449 r_dest, INVALID_REG, size, INVALID_SREG);
jeffhao5772bab2012-05-18 11:51:26 -0700450}
451
buzbee02031b12012-11-23 09:41:35 -0800452LIR* X86Codegen::LoadBaseDisp(CompilationUnit *cu, int rBase, int displacement,
buzbeefa57c472012-11-21 12:06:18 -0800453 int r_dest, OpSize size, int s_reg) {
454 return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
455 r_dest, INVALID_REG, size, s_reg);
buzbeee88dfbf2012-03-05 11:19:57 -0800456}
457
buzbee02031b12012-11-23 09:41:35 -0800458LIR* X86Codegen::LoadBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
buzbeefa57c472012-11-21 12:06:18 -0800459 int r_dest_lo, int r_dest_hi, int s_reg) {
460 return LoadBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
461 r_dest_lo, r_dest_hi, kLong, s_reg);
buzbeee88dfbf2012-03-05 11:19:57 -0800462}
463
buzbee02031b12012-11-23 09:41:35 -0800464LIR* X86Codegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
465 int displacement, int r_src, int r_src_hi, OpSize size,
466 int s_reg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800467 LIR *store = NULL;
jeffhaoe2962482012-06-28 11:29:57 -0700468 LIR *store2 = NULL;
buzbeefa57c472012-11-21 12:06:18 -0800469 bool is_array = r_index != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800470 bool pair = false;
jeffhaoe2962482012-06-28 11:29:57 -0700471 bool is64bit = false;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700472 X86OpCode opcode = kX86Nop;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800473 switch (size) {
474 case kLong:
475 case kDouble:
jeffhaoe2962482012-06-28 11:29:57 -0700476 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800477 if (X86_FPREG(r_src)) {
478 opcode = is_array ? kX86MovsdAR : kX86MovsdMR;
479 if (X86_SINGLEREG(r_src)) {
480 DCHECK(X86_FPREG(r_src_hi));
481 DCHECK_EQ(r_src, (r_src_hi - 1));
482 r_src = S2d(r_src, r_src_hi);
buzbeee88dfbf2012-03-05 11:19:57 -0800483 }
buzbeefa57c472012-11-21 12:06:18 -0800484 r_src_hi = r_src + 1;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800485 } else {
486 pair = true;
buzbeefa57c472012-11-21 12:06:18 -0800487 opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800488 }
489 // TODO: double store is to unaligned address
490 DCHECK_EQ((displacement & 0x3), 0);
491 break;
492 case kWord:
493 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800494 opcode = is_array ? kX86Mov32AR : kX86Mov32MR;
495 if (X86_FPREG(r_src)) {
496 opcode = is_array ? kX86MovssAR : kX86MovssMR;
497 DCHECK(X86_SINGLEREG(r_src));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800498 }
499 DCHECK_EQ((displacement & 0x3), 0);
500 break;
501 case kUnsignedHalf:
502 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800503 opcode = is_array ? kX86Mov16AR : kX86Mov16MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800504 DCHECK_EQ((displacement & 0x1), 0);
505 break;
506 case kUnsignedByte:
507 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800508 opcode = is_array ? kX86Mov8AR : kX86Mov8MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800509 break;
510 default:
buzbee52a77fc2012-11-20 19:50:46 -0800511 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800512 }
buzbeee88dfbf2012-03-05 11:19:57 -0800513
buzbeefa57c472012-11-21 12:06:18 -0800514 if (!is_array) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700515 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800516 store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700517 } else {
buzbeefa57c472012-11-21 12:06:18 -0800518 store = NewLIR3(cu, opcode, rBase, displacement + LOWORD_OFFSET, r_src);
519 store2 = NewLIR3(cu, opcode, rBase, displacement + HIWORD_OFFSET, r_src_hi);
jeffhaoe2962482012-06-28 11:29:57 -0700520 }
buzbeef0504cd2012-11-13 16:31:10 -0800521 if (rBase == rX86_SP) {
buzbee02031b12012-11-23 09:41:35 -0800522 AnnotateDalvikRegAccess(cu, store, (displacement + (pair ? LOWORD_OFFSET : 0)) >> 2,
523 false /* is_load */, is64bit);
jeffhaoe2962482012-06-28 11:29:57 -0700524 if (pair) {
buzbee02031b12012-11-23 09:41:35 -0800525 AnnotateDalvikRegAccess(cu, store2, (displacement + HIWORD_OFFSET) >> 2,
buzbeefa57c472012-11-21 12:06:18 -0800526 false /* is_load */, is64bit);
jeffhaoe2962482012-06-28 11:29:57 -0700527 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700528 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800529 } else {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700530 if (!pair) {
buzbeefa57c472012-11-21 12:06:18 -0800531 store = NewLIR5(cu, opcode, rBase, r_index, scale,
532 displacement + LOWORD_OFFSET, r_src);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700533 } else {
buzbeefa57c472012-11-21 12:06:18 -0800534 store = NewLIR5(cu, opcode, rBase, r_index, scale,
535 displacement + LOWORD_OFFSET, r_src);
536 store2 = NewLIR5(cu, opcode, rBase, r_index, scale,
537 displacement + HIWORD_OFFSET, r_src_hi);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800538 }
539 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700540
541 return store;
buzbeee88dfbf2012-03-05 11:19:57 -0800542}
543
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700544/* store value base base + scaled index. */
buzbee02031b12012-11-23 09:41:35 -0800545LIR* X86Codegen::StoreBaseIndexed(CompilationUnit *cu, int rBase, int r_index, int r_src,
Bill Buzbeea114add2012-05-03 15:00:40 -0700546 int scale, OpSize size)
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700547{
buzbeefa57c472012-11-21 12:06:18 -0800548 return StoreBaseIndexedDisp(cu, rBase, r_index, scale, 0,
549 r_src, INVALID_REG, size, INVALID_SREG);
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700550}
551
buzbee02031b12012-11-23 09:41:35 -0800552LIR* X86Codegen::StoreBaseDisp(CompilationUnit *cu, int rBase, int displacement,
553 int r_src, OpSize size)
Bill Buzbeea114add2012-05-03 15:00:40 -0700554{
buzbeefa57c472012-11-21 12:06:18 -0800555 return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0,
556 displacement, r_src, INVALID_REG, size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800558}
559
buzbee02031b12012-11-23 09:41:35 -0800560LIR* X86Codegen::StoreBaseDispWide(CompilationUnit *cu, int rBase, int displacement,
561 int r_src_lo, int r_src_hi)
Bill Buzbeea114add2012-05-03 15:00:40 -0700562{
buzbeefa57c472012-11-21 12:06:18 -0800563 return StoreBaseIndexedDisp(cu, rBase, INVALID_REG, 0, displacement,
564 r_src_lo, r_src_hi, kLong, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800565}
566
buzbeee88dfbf2012-03-05 11:19:57 -0800567} // namespace art