blob: 87a794289105666cd802c572edccf6be2a2cb1c0 [file] [log] [blame]
buzbeee88dfbf2012-03-05 11:19:57 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
buzbee1bc37c62012-11-20 13:35:41 -080017#include "x86_lir.h"
18#include "../codegen_util.h"
19#include "../ralloc_util.h"
20
buzbeee88dfbf2012-03-05 11:19:57 -080021namespace art {
22
buzbeeb046e162012-10-30 15:48:42 -070023/* This file contains codegen for the X86 ISA */
buzbeee88dfbf2012-03-05 11:19:57 -080024
buzbee52a77fc2012-11-20 19:50:46 -080025void GenBarrier(CompilationUnit *cUnit);
26void LoadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
27LIR *LoadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
buzbeee88dfbf2012-03-05 11:19:57 -080028 int rDest);
buzbee52a77fc2012-11-20 19:50:46 -080029LIR *StoreWordDisp(CompilationUnit *cUnit, int rBase,
buzbeee88dfbf2012-03-05 11:19:57 -080030 int displacement, int rSrc);
buzbee52a77fc2012-11-20 19:50:46 -080031LIR *LoadConstant(CompilationUnit *cUnit, int rDest, int value);
buzbeee88dfbf2012-03-05 11:19:57 -080032
buzbee52a77fc2012-11-20 19:50:46 -080033LIR *FpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
buzbeee88dfbf2012-03-05 11:19:57 -080034{
Bill Buzbeea114add2012-05-03 15:00:40 -070035 int opcode;
36 /* must be both DOUBLE or both not DOUBLE */
buzbeef0504cd2012-11-13 16:31:10 -080037 DCHECK_EQ(X86_DOUBLEREG(rDest), X86_DOUBLEREG(rSrc));
38 if (X86_DOUBLEREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070039 opcode = kX86MovsdRR;
40 } else {
buzbeef0504cd2012-11-13 16:31:10 -080041 if (X86_SINGLEREG(rDest)) {
42 if (X86_SINGLEREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -070043 opcode = kX86MovssRR;
44 } else { // Fpr <- Gpr
45 opcode = kX86MovdxrRR;
46 }
47 } else { // Gpr <- Fpr
buzbeef0504cd2012-11-13 16:31:10 -080048 DCHECK(X86_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -070049 opcode = kX86MovdrxRR;
buzbeee88dfbf2012-03-05 11:19:57 -080050 }
Bill Buzbeea114add2012-05-03 15:00:40 -070051 }
buzbeeec137432012-11-13 12:13:16 -080052 DCHECK_NE((EncodingMap[opcode].flags & IS_BINARY_OP), 0ULL);
buzbee52a77fc2012-11-20 19:50:46 -080053 LIR* res = RawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
Bill Buzbeea114add2012-05-03 15:00:40 -070054 if (rDest == rSrc) {
55 res->flags.isNop = true;
56 }
57 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080058}
59
60/*
61 * Load a immediate using a shortcut if possible; otherwise
62 * grab from the per-translation literal pool. If target is
63 * a high register, build constant into a low register and copy.
64 *
65 * No additional register clobbering operation performed. Use this version when
buzbee52a77fc2012-11-20 19:50:46 -080066 * 1) rDest is freshly returned from AllocTemp or
buzbeee88dfbf2012-03-05 11:19:57 -080067 * 2) The codegen is under fixed register usage
68 */
buzbee52a77fc2012-11-20 19:50:46 -080069LIR *LoadConstantNoClobber(CompilationUnit *cUnit, int rDest, int value)
Bill Buzbeea114add2012-05-03 15:00:40 -070070{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070071 int rDestSave = rDest;
buzbeef0504cd2012-11-13 16:31:10 -080072 if (X86_FPREG(rDest)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -070073 if (value == 0) {
buzbee52a77fc2012-11-20 19:50:46 -080074 return NewLIR2(cUnit, kX86XorpsRR, rDest, rDest);
Ian Rogersb41b33b2012-03-20 14:22:54 -070075 }
buzbeef0504cd2012-11-13 16:31:10 -080076 DCHECK(X86_SINGLEREG(rDest));
buzbee52a77fc2012-11-20 19:50:46 -080077 rDest = AllocTemp(cUnit);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070078 }
buzbeee88dfbf2012-03-05 11:19:57 -080079
Ian Rogersb41b33b2012-03-20 14:22:54 -070080 LIR *res;
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070081 if (value == 0) {
buzbee52a77fc2012-11-20 19:50:46 -080082 res = NewLIR2(cUnit, kX86Xor32RR, rDest, rDest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070083 } else {
Ian Rogers2e9f7ed2012-09-26 11:30:43 -070084 // Note, there is no byte immediate form of a 32 bit immediate move.
buzbee52a77fc2012-11-20 19:50:46 -080085 res = NewLIR2(cUnit, kX86Mov32RI, rDest, value);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070086 }
buzbeee88dfbf2012-03-05 11:19:57 -080087
buzbeef0504cd2012-11-13 16:31:10 -080088 if (X86_FPREG(rDestSave)) {
buzbee52a77fc2012-11-20 19:50:46 -080089 NewLIR2(cUnit, kX86MovdxrRR, rDestSave, rDest);
90 FreeTemp(cUnit, rDest);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070091 }
buzbeee88dfbf2012-03-05 11:19:57 -080092
Ian Rogers6cbb2bd2012-03-16 13:45:30 -070093 return res;
buzbeee88dfbf2012-03-05 11:19:57 -080094}
95
buzbee52a77fc2012-11-20 19:50:46 -080096LIR* OpBranchUnconditional(CompilationUnit *cUnit, OpKind op)
Bill Buzbeea114add2012-05-03 15:00:40 -070097{
Ian Rogersb5d09b22012-03-06 22:14:17 -080098 CHECK_EQ(op, kOpUncondBr);
buzbee52a77fc2012-11-20 19:50:46 -080099 return NewLIR1(cUnit, kX86Jmp8, 0 /* offset to be patched */ );
buzbeee88dfbf2012-03-05 11:19:57 -0800100}
101
buzbee52a77fc2012-11-20 19:50:46 -0800102LIR *LoadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
buzbeee88dfbf2012-03-05 11:19:57 -0800103
buzbee52a77fc2012-11-20 19:50:46 -0800104X86ConditionCode X86ConditionEncoding(ConditionCode cond);
105LIR* OpCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
buzbeea7678db2012-03-05 15:35:46 -0800106{
buzbee52a77fc2012-11-20 19:50:46 -0800107 LIR* branch = NewLIR2(cUnit, kX86Jcc8, 0 /* offset to be patched */,
108 X86ConditionEncoding(cc));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800109 branch->target = target;
110 return branch;
buzbeea7678db2012-03-05 15:35:46 -0800111}
112
buzbee52a77fc2012-11-20 19:50:46 -0800113LIR *OpReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
Bill Buzbeea114add2012-05-03 15:00:40 -0700114{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800115 X86OpCode opcode = kX86Bkpt;
116 switch (op) {
117 case kOpNeg: opcode = kX86Neg32R; break;
jeffhao1395b1e2012-06-13 18:05:13 -0700118 case kOpNot: opcode = kX86Not32R; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800119 case kOpBlx: opcode = kX86CallR; break;
120 default:
buzbee52a77fc2012-11-20 19:50:46 -0800121 LOG(FATAL) << "Bad case in OpReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800122 }
buzbee52a77fc2012-11-20 19:50:46 -0800123 return NewLIR1(cUnit, opcode, rDestSrc);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800124}
125
buzbee52a77fc2012-11-20 19:50:46 -0800126LIR *OpRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int value)
Bill Buzbeea114add2012-05-03 15:00:40 -0700127{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800128 X86OpCode opcode = kX86Bkpt;
129 bool byteImm = IS_SIMM8(value);
buzbeef0504cd2012-11-13 16:31:10 -0800130 DCHECK(!X86_FPREG(rDestSrc1));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800131 switch (op) {
132 case kOpLsl: opcode = kX86Sal32RI; break;
133 case kOpLsr: opcode = kX86Shr32RI; break;
134 case kOpAsr: opcode = kX86Sar32RI; break;
135 case kOpAdd: opcode = byteImm ? kX86Add32RI8 : kX86Add32RI; break;
136 case kOpOr: opcode = byteImm ? kX86Or32RI8 : kX86Or32RI; break;
137 case kOpAdc: opcode = byteImm ? kX86Adc32RI8 : kX86Adc32RI; break;
138 //case kOpSbb: opcode = kX86Sbb32RI; break;
139 case kOpAnd: opcode = byteImm ? kX86And32RI8 : kX86And32RI; break;
140 case kOpSub: opcode = byteImm ? kX86Sub32RI8 : kX86Sub32RI; break;
141 case kOpXor: opcode = byteImm ? kX86Xor32RI8 : kX86Xor32RI; break;
142 case kOpCmp: opcode = byteImm ? kX86Cmp32RI8 : kX86Cmp32RI; break;
buzbee52a77fc2012-11-20 19:50:46 -0800143 case kOpMov: return LoadConstantNoClobber(cUnit, rDestSrc1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800144 case kOpMul:
145 opcode = byteImm ? kX86Imul32RRI8 : kX86Imul32RRI;
buzbee52a77fc2012-11-20 19:50:46 -0800146 return NewLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800147 default:
buzbee52a77fc2012-11-20 19:50:46 -0800148 LOG(FATAL) << "Bad case in OpRegImm " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800149 }
buzbee52a77fc2012-11-20 19:50:46 -0800150 return NewLIR2(cUnit, opcode, rDestSrc1, value);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800151}
152
buzbee52a77fc2012-11-20 19:50:46 -0800153LIR *OpRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1, int rSrc2)
buzbeee88dfbf2012-03-05 11:19:57 -0800154{
buzbeea7678db2012-03-05 15:35:46 -0800155 X86OpCode opcode = kX86Nop;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700156 bool src2_must_be_cx = false;
buzbeee88dfbf2012-03-05 11:19:57 -0800157 switch (op) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800158 // X86 unary opcodes
159 case kOpMvn:
buzbee52a77fc2012-11-20 19:50:46 -0800160 OpRegCopy(cUnit, rDestSrc1, rSrc2);
161 return OpReg(cUnit, kOpNot, rDestSrc1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800162 case kOpNeg:
buzbee52a77fc2012-11-20 19:50:46 -0800163 OpRegCopy(cUnit, rDestSrc1, rSrc2);
164 return OpReg(cUnit, kOpNeg, rDestSrc1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800165 // X86 binary opcodes
166 case kOpSub: opcode = kX86Sub32RR; break;
167 case kOpSbc: opcode = kX86Sbb32RR; break;
Ian Rogersd36c52e2012-04-09 16:29:25 -0700168 case kOpLsl: opcode = kX86Sal32RC; src2_must_be_cx = true; break;
169 case kOpLsr: opcode = kX86Shr32RC; src2_must_be_cx = true; break;
170 case kOpAsr: opcode = kX86Sar32RC; src2_must_be_cx = true; break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800171 case kOpMov: opcode = kX86Mov32RR; break;
172 case kOpCmp: opcode = kX86Cmp32RR; break;
173 case kOpAdd: opcode = kX86Add32RR; break;
174 case kOpAdc: opcode = kX86Adc32RR; break;
175 case kOpAnd: opcode = kX86And32RR; break;
176 case kOpOr: opcode = kX86Or32RR; break;
177 case kOpXor: opcode = kX86Xor32RR; break;
jeffhao703f2cd2012-07-13 17:25:52 -0700178 case kOp2Byte:
179 // Use shifts instead of a byte operand if the source can't be byte accessed.
180 if (rSrc2 >= 4) {
buzbee52a77fc2012-11-20 19:50:46 -0800181 NewLIR2(cUnit, kX86Mov32RR, rDestSrc1, rSrc2);
182 NewLIR2(cUnit, kX86Sal32RI, rDestSrc1, 24);
183 return NewLIR2(cUnit, kX86Sar32RI, rDestSrc1, 24);
jeffhao703f2cd2012-07-13 17:25:52 -0700184 } else {
185 opcode = kX86Movsx8RR;
186 }
187 break;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800188 case kOp2Short: opcode = kX86Movsx16RR; break;
189 case kOp2Char: opcode = kX86Movzx16RR; break;
190 case kOpMul: opcode = kX86Imul32RR; break;
191 default:
buzbee52a77fc2012-11-20 19:50:46 -0800192 LOG(FATAL) << "Bad case in OpRegReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800193 break;
buzbeee88dfbf2012-03-05 11:19:57 -0800194 }
Ian Rogersd36c52e2012-04-09 16:29:25 -0700195 CHECK(!src2_must_be_cx || rSrc2 == rCX);
buzbee52a77fc2012-11-20 19:50:46 -0800196 return NewLIR2(cUnit, opcode, rDestSrc1, rSrc2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800197}
198
buzbee52a77fc2012-11-20 19:50:46 -0800199LIR* OpRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase,
Bill Buzbeea114add2012-05-03 15:00:40 -0700200 int offset)
201{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800202 X86OpCode opcode = kX86Nop;
203 switch (op) {
204 // X86 binary opcodes
205 case kOpSub: opcode = kX86Sub32RM; break;
206 case kOpMov: opcode = kX86Mov32RM; break;
207 case kOpCmp: opcode = kX86Cmp32RM; break;
208 case kOpAdd: opcode = kX86Add32RM; break;
209 case kOpAnd: opcode = kX86And32RM; break;
210 case kOpOr: opcode = kX86Or32RM; break;
211 case kOpXor: opcode = kX86Xor32RM; break;
212 case kOp2Byte: opcode = kX86Movsx8RM; break;
213 case kOp2Short: opcode = kX86Movsx16RM; break;
214 case kOp2Char: opcode = kX86Movzx16RM; break;
215 case kOpMul:
216 default:
buzbee52a77fc2012-11-20 19:50:46 -0800217 LOG(FATAL) << "Bad case in OpRegMem " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800218 break;
219 }
buzbee52a77fc2012-11-20 19:50:46 -0800220 return NewLIR3(cUnit, opcode, rDest, rBase, offset);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800221}
222
buzbee52a77fc2012-11-20 19:50:46 -0800223LIR* OpRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 int rSrc2)
225{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800226 if (rDest != rSrc1 && rDest != rSrc2) {
227 if (op == kOpAdd) { // lea special case, except can't encode rbp as base
228 if (rSrc1 == rSrc2) {
buzbee52a77fc2012-11-20 19:50:46 -0800229 OpRegCopy(cUnit, rDest, rSrc1);
230 return OpRegImm(cUnit, kOpLsl, rDest, 1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800231 } else if (rSrc1 != rBP) {
buzbee52a77fc2012-11-20 19:50:46 -0800232 return NewLIR5(cUnit, kX86Lea32RA, rDest, rSrc1 /* base */,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800233 rSrc2 /* index */, 0 /* scale */, 0 /* disp */);
234 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800235 return NewLIR5(cUnit, kX86Lea32RA, rDest, rSrc2 /* base */,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800236 rSrc1 /* index */, 0 /* scale */, 0 /* disp */);
237 }
238 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800239 OpRegCopy(cUnit, rDest, rSrc1);
240 return OpRegReg(cUnit, op, rDest, rSrc2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800241 }
242 } else if (rDest == rSrc1) {
buzbee52a77fc2012-11-20 19:50:46 -0800243 return OpRegReg(cUnit, op, rDest, rSrc2);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800244 } else { // rDest == rSrc2
245 switch (op) {
246 case kOpSub: // non-commutative
buzbee52a77fc2012-11-20 19:50:46 -0800247 OpReg(cUnit, kOpNeg, rDest);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800248 op = kOpAdd;
249 break;
250 case kOpSbc:
251 case kOpLsl: case kOpLsr: case kOpAsr: case kOpRor: {
buzbee52a77fc2012-11-20 19:50:46 -0800252 int tReg = AllocTemp(cUnit);
253 OpRegCopy(cUnit, tReg, rSrc1);
254 OpRegReg(cUnit, op, tReg, rSrc2);
255 LIR* res = OpRegCopy(cUnit, rDest, tReg);
256 FreeTemp(cUnit, tReg);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800257 return res;
258 }
259 case kOpAdd: // commutative
260 case kOpOr:
261 case kOpAdc:
262 case kOpAnd:
263 case kOpXor:
264 break;
265 default:
buzbee52a77fc2012-11-20 19:50:46 -0800266 LOG(FATAL) << "Bad case in OpRegRegReg " << op;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800267 }
buzbee52a77fc2012-11-20 19:50:46 -0800268 return OpRegReg(cUnit, op, rDest, rSrc1);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800269 }
270}
271
buzbee52a77fc2012-11-20 19:50:46 -0800272LIR* OpRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest, int rSrc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700273 int value)
274{
Ian Rogersb5d09b22012-03-06 22:14:17 -0800275 if (op == kOpMul) {
276 X86OpCode opcode = IS_SIMM8(value) ? kX86Imul32RRI8 : kX86Imul32RRI;
buzbee52a77fc2012-11-20 19:50:46 -0800277 return NewLIR3(cUnit, opcode, rDest, rSrc, value);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700278 } else if (op == kOpAnd) {
jeffhao854029c2012-07-23 17:31:30 -0700279 if (value == 0xFF && rSrc < 4) {
buzbee52a77fc2012-11-20 19:50:46 -0800280 return NewLIR2(cUnit, kX86Movzx8RR, rDest, rSrc);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700281 } else if (value == 0xFFFF) {
buzbee52a77fc2012-11-20 19:50:46 -0800282 return NewLIR2(cUnit, kX86Movzx16RR, rDest, rSrc);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700283 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800284 }
285 if (rDest != rSrc) {
Ian Rogers7caad772012-03-30 01:07:54 -0700286 if (false && op == kOpLsl && value >= 0 && value <= 3) { // lea shift special case
287 // TODO: fix bug in LEA encoding when disp == 0
buzbee52a77fc2012-11-20 19:50:46 -0800288 return NewLIR5(cUnit, kX86Lea32RA, rDest, r5sib_no_base /* base */,
Ian Rogers7caad772012-03-30 01:07:54 -0700289 rSrc /* index */, value /* scale */, 0 /* disp */);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700290 } else if (op == kOpAdd) { // lea add special case
buzbee52a77fc2012-11-20 19:50:46 -0800291 return NewLIR5(cUnit, kX86Lea32RA, rDest, rSrc /* base */,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800292 r4sib_no_index /* index */, 0 /* scale */, value /* disp */);
293 }
buzbee52a77fc2012-11-20 19:50:46 -0800294 OpRegCopy(cUnit, rDest, rSrc);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800295 }
buzbee52a77fc2012-11-20 19:50:46 -0800296 return OpRegImm(cUnit, op, rDest, value);
buzbeee88dfbf2012-03-05 11:19:57 -0800297}
298
buzbee52a77fc2012-11-20 19:50:46 -0800299LIR* OpThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset)
Bill Buzbeea114add2012-05-03 15:00:40 -0700300{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700301 X86OpCode opcode = kX86Bkpt;
302 switch (op) {
303 case kOpBlx: opcode = kX86CallT; break;
304 default:
305 LOG(FATAL) << "Bad opcode: " << op;
306 break;
307 }
buzbee52a77fc2012-11-20 19:50:46 -0800308 return NewLIR1(cUnit, opcode, threadOffset);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700309}
310
buzbee52a77fc2012-11-20 19:50:46 -0800311LIR* OpMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp)
Bill Buzbeea114add2012-05-03 15:00:40 -0700312{
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700313 X86OpCode opcode = kX86Bkpt;
314 switch (op) {
315 case kOpBlx: opcode = kX86CallM; break;
316 default:
317 LOG(FATAL) << "Bad opcode: " << op;
318 break;
319 }
buzbee52a77fc2012-11-20 19:50:46 -0800320 return NewLIR2(cUnit, opcode, rBase, disp);
Ian Rogers6cbb2bd2012-03-16 13:45:30 -0700321}
322
buzbee52a77fc2012-11-20 19:50:46 -0800323LIR *LoadConstantValueWide(CompilationUnit *cUnit, int rDestLo,
Bill Buzbeea114add2012-05-03 15:00:40 -0700324 int rDestHi, int valLo, int valHi)
buzbeee88dfbf2012-03-05 11:19:57 -0800325{
326 LIR *res;
buzbeef0504cd2012-11-13 16:31:10 -0800327 if (X86_FPREG(rDestLo)) {
328 DCHECK(X86_FPREG(rDestHi)); // ignore rDestHi
Ian Rogersb41b33b2012-03-20 14:22:54 -0700329 if (valLo == 0 && valHi == 0) {
buzbee52a77fc2012-11-20 19:50:46 -0800330 return NewLIR2(cUnit, kX86XorpsRR, rDestLo, rDestLo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700331 } else {
332 if (valLo == 0) {
buzbee52a77fc2012-11-20 19:50:46 -0800333 res = NewLIR2(cUnit, kX86XorpsRR, rDestLo, rDestLo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700334 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800335 res = LoadConstantNoClobber(cUnit, rDestLo, valLo);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700336 }
337 if (valHi != 0) {
buzbee52a77fc2012-11-20 19:50:46 -0800338 LoadConstantNoClobber(cUnit, rDestHi, valHi);
339 NewLIR2(cUnit, kX86PsllqRI, rDestHi, 32);
340 NewLIR2(cUnit, kX86OrpsRR, rDestLo, rDestHi);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700341 }
342 }
343 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800344 res = LoadConstantNoClobber(cUnit, rDestLo, valLo);
345 LoadConstantNoClobber(cUnit, rDestHi, valHi);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700346 }
buzbeee88dfbf2012-03-05 11:19:57 -0800347 return res;
348}
349
buzbee52a77fc2012-11-20 19:50:46 -0800350LIR *LoadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
buzbeee88dfbf2012-03-05 11:19:57 -0800351{
buzbee52a77fc2012-11-20 19:50:46 -0800352 UNIMPLEMENTED(FATAL) << "LoadMultiple";
353 NewLIR0(cUnit, kX86Bkpt);
Bill Buzbeea114add2012-05-03 15:00:40 -0700354 return NULL;
buzbeee88dfbf2012-03-05 11:19:57 -0800355}
356
buzbee52a77fc2012-11-20 19:50:46 -0800357LIR *StoreMultiple(CompilationUnit *cUnit, int rBase, int rMask)
buzbeee88dfbf2012-03-05 11:19:57 -0800358{
buzbee52a77fc2012-11-20 19:50:46 -0800359 UNIMPLEMENTED(FATAL) << "StoreMultiple";
360 NewLIR0(cUnit, kX86Bkpt);
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 return NULL;
buzbeee88dfbf2012-03-05 11:19:57 -0800362}
363
buzbee52a77fc2012-11-20 19:50:46 -0800364LIR* LoadBaseIndexedDisp(CompilationUnit *cUnit,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800365 int rBase, int rIndex, int scale, int displacement,
366 int rDest, int rDestHi,
367 OpSize size, int sReg) {
368 LIR *load = NULL;
369 LIR *load2 = NULL;
370 bool isArray = rIndex != INVALID_REG;
371 bool pair = false;
372 bool is64bit = false;
373 X86OpCode opcode = kX86Nop;
374 switch (size) {
375 case kLong:
376 case kDouble:
377 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800378 if (X86_FPREG(rDest)) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800379 opcode = isArray ? kX86MovsdRA : kX86MovsdRM;
buzbeef0504cd2012-11-13 16:31:10 -0800380 if (X86_SINGLEREG(rDest)) {
381 DCHECK(X86_FPREG(rDestHi));
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700382 DCHECK_EQ(rDest, (rDestHi - 1));
buzbee52a77fc2012-11-20 19:50:46 -0800383 rDest = S2d(rDest, rDestHi);
buzbeee88dfbf2012-03-05 11:19:57 -0800384 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800385 rDestHi = rDest + 1;
386 } else {
387 pair = true;
388 opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
389 }
390 // TODO: double store is to unaligned address
391 DCHECK_EQ((displacement & 0x3), 0);
392 break;
393 case kWord:
394 case kSingle:
395 opcode = isArray ? kX86Mov32RA : kX86Mov32RM;
buzbeef0504cd2012-11-13 16:31:10 -0800396 if (X86_FPREG(rDest)) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800397 opcode = isArray ? kX86MovssRA : kX86MovssRM;
buzbeef0504cd2012-11-13 16:31:10 -0800398 DCHECK(X86_SINGLEREG(rDest));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800399 }
400 DCHECK_EQ((displacement & 0x3), 0);
401 break;
402 case kUnsignedHalf:
403 opcode = isArray ? kX86Movzx16RA : kX86Movzx16RM;
404 DCHECK_EQ((displacement & 0x1), 0);
405 break;
406 case kSignedHalf:
407 opcode = isArray ? kX86Movsx16RA : kX86Movsx16RM;
408 DCHECK_EQ((displacement & 0x1), 0);
409 break;
410 case kUnsignedByte:
411 opcode = isArray ? kX86Movzx8RA : kX86Movzx8RM;
412 break;
413 case kSignedByte:
414 opcode = isArray ? kX86Movsx8RA : kX86Movsx8RM;
415 break;
416 default:
buzbee52a77fc2012-11-20 19:50:46 -0800417 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800418 }
419
420 if (!isArray) {
421 if (!pair) {
buzbee52a77fc2012-11-20 19:50:46 -0800422 load = NewLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
buzbeee88dfbf2012-03-05 11:19:57 -0800423 } else {
jeffhaofdffdf82012-07-11 16:08:43 -0700424 if (rBase == rDest) {
buzbee52a77fc2012-11-20 19:50:46 -0800425 load2 = NewLIR3(cUnit, opcode, rDestHi, rBase,
jeffhaofdffdf82012-07-11 16:08:43 -0700426 displacement + HIWORD_OFFSET);
buzbee52a77fc2012-11-20 19:50:46 -0800427 load = NewLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
jeffhaofdffdf82012-07-11 16:08:43 -0700428 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800429 load = NewLIR3(cUnit, opcode, rDest, rBase, displacement + LOWORD_OFFSET);
430 load2 = NewLIR3(cUnit, opcode, rDestHi, rBase,
jeffhaofdffdf82012-07-11 16:08:43 -0700431 displacement + HIWORD_OFFSET);
432 }
buzbeee88dfbf2012-03-05 11:19:57 -0800433 }
buzbeef0504cd2012-11-13 16:31:10 -0800434 if (rBase == rX86_SP) {
buzbee52a77fc2012-11-20 19:50:46 -0800435 AnnotateDalvikRegAccess(load, (displacement + (pair ? LOWORD_OFFSET : 0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700436 >> 2, true /* isLoad */, is64bit);
Ian Rogersf7d9ad32012-03-13 18:45:39 -0700437 if (pair) {
buzbee52a77fc2012-11-20 19:50:46 -0800438 AnnotateDalvikRegAccess(load2, (displacement + HIWORD_OFFSET) >> 2,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800439 true /* isLoad */, is64bit);
440 }
buzbeee88dfbf2012-03-05 11:19:57 -0800441 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800442 } else {
443 if (!pair) {
buzbee52a77fc2012-11-20 19:50:46 -0800444 load = NewLIR5(cUnit, opcode, rDest, rBase, rIndex, scale,
Bill Buzbeea114add2012-05-03 15:00:40 -0700445 displacement + LOWORD_OFFSET);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800446 } else {
jeffhaofdffdf82012-07-11 16:08:43 -0700447 if (rBase == rDest) {
buzbee52a77fc2012-11-20 19:50:46 -0800448 load2 = NewLIR5(cUnit, opcode, rDestHi, rBase, rIndex, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700449 displacement + HIWORD_OFFSET);
buzbee52a77fc2012-11-20 19:50:46 -0800450 load = NewLIR5(cUnit, opcode, rDest, rBase, rIndex, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700451 displacement + LOWORD_OFFSET);
452 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800453 load = NewLIR5(cUnit, opcode, rDest, rBase, rIndex, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700454 displacement + LOWORD_OFFSET);
buzbee52a77fc2012-11-20 19:50:46 -0800455 load2 = NewLIR5(cUnit, opcode, rDestHi, rBase, rIndex, scale,
jeffhaofdffdf82012-07-11 16:08:43 -0700456 displacement + HIWORD_OFFSET);
457 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800458 }
459 }
460
461 return load;
buzbeee88dfbf2012-03-05 11:19:57 -0800462}
463
jeffhao5772bab2012-05-18 11:51:26 -0700464/* Load value from base + scaled index. */
buzbee52a77fc2012-11-20 19:50:46 -0800465LIR *LoadBaseIndexed(CompilationUnit *cUnit, int rBase,
jeffhao5772bab2012-05-18 11:51:26 -0700466 int rIndex, int rDest, int scale, OpSize size) {
buzbee52a77fc2012-11-20 19:50:46 -0800467 return LoadBaseIndexedDisp(cUnit, rBase, rIndex, scale, 0,
jeffhao5772bab2012-05-18 11:51:26 -0700468 rDest, INVALID_REG, size, INVALID_SREG);
469}
470
buzbee52a77fc2012-11-20 19:50:46 -0800471LIR *LoadBaseDisp(CompilationUnit *cUnit,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800472 int rBase, int displacement,
473 int rDest,
474 OpSize size, int sReg) {
buzbee52a77fc2012-11-20 19:50:46 -0800475 return LoadBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0, displacement,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800476 rDest, INVALID_REG, size, sReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800477}
478
buzbee52a77fc2012-11-20 19:50:46 -0800479LIR *LoadBaseDispWide(CompilationUnit *cUnit,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800480 int rBase, int displacement,
481 int rDestLo, int rDestHi,
482 int sReg) {
buzbee52a77fc2012-11-20 19:50:46 -0800483 return LoadBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0, displacement,
Ian Rogersb5d09b22012-03-06 22:14:17 -0800484 rDestLo, rDestHi, kLong, sReg);
buzbeee88dfbf2012-03-05 11:19:57 -0800485}
486
buzbee52a77fc2012-11-20 19:50:46 -0800487LIR* StoreBaseIndexedDisp(CompilationUnit *cUnit,
Ian Rogersb41b33b2012-03-20 14:22:54 -0700488 int rBase, int rIndex, int scale, int displacement,
489 int rSrc, int rSrcHi,
490 OpSize size, int sReg) {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800491 LIR *store = NULL;
jeffhaoe2962482012-06-28 11:29:57 -0700492 LIR *store2 = NULL;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700493 bool isArray = rIndex != INVALID_REG;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800494 bool pair = false;
jeffhaoe2962482012-06-28 11:29:57 -0700495 bool is64bit = false;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700496 X86OpCode opcode = kX86Nop;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800497 switch (size) {
498 case kLong:
499 case kDouble:
jeffhaoe2962482012-06-28 11:29:57 -0700500 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800501 if (X86_FPREG(rSrc)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700502 opcode = isArray ? kX86MovsdAR : kX86MovsdMR;
buzbeef0504cd2012-11-13 16:31:10 -0800503 if (X86_SINGLEREG(rSrc)) {
504 DCHECK(X86_FPREG(rSrcHi));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800505 DCHECK_EQ(rSrc, (rSrcHi - 1));
buzbee52a77fc2012-11-20 19:50:46 -0800506 rSrc = S2d(rSrc, rSrcHi);
buzbeee88dfbf2012-03-05 11:19:57 -0800507 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800508 rSrcHi = rSrc + 1;
509 } else {
510 pair = true;
Ian Rogersb41b33b2012-03-20 14:22:54 -0700511 opcode = isArray ? kX86Mov32AR : kX86Mov32MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800512 }
513 // TODO: double store is to unaligned address
514 DCHECK_EQ((displacement & 0x3), 0);
515 break;
516 case kWord:
517 case kSingle:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700518 opcode = isArray ? kX86Mov32AR : kX86Mov32MR;
buzbeef0504cd2012-11-13 16:31:10 -0800519 if (X86_FPREG(rSrc)) {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700520 opcode = isArray ? kX86MovssAR : kX86MovssMR;
buzbeef0504cd2012-11-13 16:31:10 -0800521 DCHECK(X86_SINGLEREG(rSrc));
Ian Rogersb5d09b22012-03-06 22:14:17 -0800522 }
523 DCHECK_EQ((displacement & 0x3), 0);
524 break;
525 case kUnsignedHalf:
526 case kSignedHalf:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700527 opcode = isArray ? kX86Mov16AR : kX86Mov16MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800528 DCHECK_EQ((displacement & 0x1), 0);
529 break;
530 case kUnsignedByte:
531 case kSignedByte:
Ian Rogersb41b33b2012-03-20 14:22:54 -0700532 opcode = isArray ? kX86Mov8AR : kX86Mov8MR;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800533 break;
534 default:
buzbee52a77fc2012-11-20 19:50:46 -0800535 LOG(FATAL) << "Bad case in LoadBaseIndexedDispBody";
Ian Rogersb5d09b22012-03-06 22:14:17 -0800536 }
buzbeee88dfbf2012-03-05 11:19:57 -0800537
Ian Rogersb41b33b2012-03-20 14:22:54 -0700538 if (!isArray) {
539 if (!pair) {
buzbee52a77fc2012-11-20 19:50:46 -0800540 store = NewLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700541 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800542 store = NewLIR3(cUnit, opcode, rBase, displacement + LOWORD_OFFSET, rSrc);
543 store2 = NewLIR3(cUnit, opcode, rBase, displacement + HIWORD_OFFSET, rSrcHi);
jeffhaoe2962482012-06-28 11:29:57 -0700544 }
buzbeef0504cd2012-11-13 16:31:10 -0800545 if (rBase == rX86_SP) {
buzbee52a77fc2012-11-20 19:50:46 -0800546 AnnotateDalvikRegAccess(store, (displacement + (pair ? LOWORD_OFFSET : 0))
jeffhaoe2962482012-06-28 11:29:57 -0700547 >> 2, false /* isLoad */, is64bit);
548 if (pair) {
buzbee52a77fc2012-11-20 19:50:46 -0800549 AnnotateDalvikRegAccess(store2, (displacement + HIWORD_OFFSET) >> 2,
jeffhaoe2962482012-06-28 11:29:57 -0700550 false /* isLoad */, is64bit);
551 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700552 }
Ian Rogersb5d09b22012-03-06 22:14:17 -0800553 } else {
Ian Rogersb41b33b2012-03-20 14:22:54 -0700554 if (!pair) {
buzbee52a77fc2012-11-20 19:50:46 -0800555 store = NewLIR5(cUnit, opcode, rBase, rIndex, scale,
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 displacement + LOWORD_OFFSET, rSrc);
Ian Rogersb41b33b2012-03-20 14:22:54 -0700557 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800558 store = NewLIR5(cUnit, opcode, rBase, rIndex, scale,
Elliott Hughes60234562012-06-01 12:25:59 -0700559 displacement + LOWORD_OFFSET, rSrc);
buzbee52a77fc2012-11-20 19:50:46 -0800560 store2 = NewLIR5(cUnit, opcode, rBase, rIndex, scale,
jeffhaoe2962482012-06-28 11:29:57 -0700561 displacement + HIWORD_OFFSET, rSrcHi);
Ian Rogersb5d09b22012-03-06 22:14:17 -0800562 }
563 }
Ian Rogersb41b33b2012-03-20 14:22:54 -0700564
565 return store;
buzbeee88dfbf2012-03-05 11:19:57 -0800566}
567
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700568/* store value base base + scaled index. */
buzbee52a77fc2012-11-20 19:50:46 -0800569LIR *StoreBaseIndexed(CompilationUnit *cUnit, int rBase, int rIndex, int rSrc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700570 int scale, OpSize size)
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700571{
buzbee52a77fc2012-11-20 19:50:46 -0800572 return StoreBaseIndexedDisp(cUnit, rBase, rIndex, scale, 0,
Ian Rogersc6f3bb82012-03-21 20:40:33 -0700573 rSrc, INVALID_REG, size, INVALID_SREG);
574}
575
buzbee52a77fc2012-11-20 19:50:46 -0800576LIR *StoreBaseDisp(CompilationUnit *cUnit, int rBase, int displacement,
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 int rSrc, OpSize size)
578{
buzbee52a77fc2012-11-20 19:50:46 -0800579 return StoreBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0,
Bill Buzbeea114add2012-05-03 15:00:40 -0700580 displacement, rSrc, INVALID_REG, size,
581 INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800582}
583
buzbee52a77fc2012-11-20 19:50:46 -0800584LIR *StoreBaseDispWide(CompilationUnit *cUnit, int rBase, int displacement,
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 int rSrcLo, int rSrcHi)
586{
buzbee52a77fc2012-11-20 19:50:46 -0800587 return StoreBaseIndexedDisp(cUnit, rBase, INVALID_REG, 0, displacement,
Ian Rogersb41b33b2012-03-20 14:22:54 -0700588 rSrcLo, rSrcHi, kLong, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800589}
590
buzbee52a77fc2012-11-20 19:50:46 -0800591void LoadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
buzbeee88dfbf2012-03-05 11:19:57 -0800592{
buzbee52a77fc2012-11-20 19:50:46 -0800593 LoadBaseDispWide(cUnit, base, 0, lowReg, highReg, INVALID_SREG);
buzbeee88dfbf2012-03-05 11:19:57 -0800594}
595
596} // namespace art