blob: fc3aaa0e958ef3d8bddb59e39686e89c45fe5bda [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 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
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080017namespace art {
18
buzbeeb046e162012-10-30 15:48:42 -070019/* This file contains codegen for the Thumb ISA. */
buzbee67bf8852011-08-17 17:51:35 -070020
buzbeef0504cd2012-11-13 16:31:10 -080021static int coreRegs[] = {r0, r1, r2, r3, rARM_SUSPEND, r5, r6, r7, r8, rARM_SELF, r10,
22 r11, r12, rARM_SP, rARM_LR, rARM_PC};
23static int reservedRegs[] = {rARM_SUSPEND, rARM_SELF, rARM_SP, rARM_LR, rARM_PC};
buzbee67bf8852011-08-17 17:51:35 -070024static int fpRegs[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
25 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15,
26 fr16, fr17, fr18, fr19, fr20, fr21, fr22, fr23,
27 fr24, fr25, fr26, fr27, fr28, fr29, fr30, fr31};
28static int coreTemps[] = {r0, r1, r2, r3, r12};
29static int fpTemps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
30 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15};
31
buzbee31a4a6f2012-02-28 15:36:15 -080032int encodeImmSingle(int value)
buzbee67bf8852011-08-17 17:51:35 -070033{
Bill Buzbeea114add2012-05-03 15:00:40 -070034 int res;
35 int bitA = (value & 0x80000000) >> 31;
36 int notBitB = (value & 0x40000000) >> 30;
37 int bitB = (value & 0x20000000) >> 29;
38 int bSmear = (value & 0x3e000000) >> 25;
39 int slice = (value & 0x01f80000) >> 19;
40 int zeroes = (value & 0x0007ffff);
41 if (zeroes != 0)
42 return -1;
43 if (bitB) {
44 if ((notBitB != 0) || (bSmear != 0x1f))
45 return -1;
46 } else {
47 if ((notBitB != 1) || (bSmear != 0x0))
48 return -1;
49 }
50 res = (bitA << 7) | (bitB << 6) | slice;
51 return res;
buzbee67bf8852011-08-17 17:51:35 -070052}
53
buzbee31a4a6f2012-02-28 15:36:15 -080054LIR* loadFPConstantValue(CompilationUnit* cUnit, int rDest, int value)
buzbee67bf8852011-08-17 17:51:35 -070055{
Bill Buzbeea114add2012-05-03 15:00:40 -070056 int encodedImm = encodeImmSingle(value);
buzbeef0504cd2012-11-13 16:31:10 -080057 DCHECK(ARM_SINGLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -070058 if (encodedImm >= 0) {
59 return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
60 }
61 LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
62 if (dataTarget == NULL) {
63 dataTarget = addWordData(cUnit, &cUnit->literalList, value);
64 }
65 LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrs,
66 rDest, r15pc, 0, 0, 0, dataTarget);
67 setMemRefType(loadPcRel, true, kLiteral);
68 loadPcRel->aliasInfo = (intptr_t)dataTarget;
69 oatAppendLIR(cUnit, (LIR* ) loadPcRel);
70 return loadPcRel;
buzbee67bf8852011-08-17 17:51:35 -070071}
72
buzbee31a4a6f2012-02-28 15:36:15 -080073int leadingZeros(u4 val)
buzbee67bf8852011-08-17 17:51:35 -070074{
Bill Buzbeea114add2012-05-03 15:00:40 -070075 u4 alt;
76 int n;
77 int count;
buzbee67bf8852011-08-17 17:51:35 -070078
Bill Buzbeea114add2012-05-03 15:00:40 -070079 count = 16;
80 n = 32;
81 do {
82 alt = val >> count;
83 if (alt != 0) {
84 n = n - count;
85 val = alt;
86 }
87 count >>= 1;
88 } while (count);
89 return n - val;
buzbee67bf8852011-08-17 17:51:35 -070090}
91
92/*
93 * Determine whether value can be encoded as a Thumb2 modified
94 * immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form.
95 */
buzbee31a4a6f2012-02-28 15:36:15 -080096int modifiedImmediate(u4 value)
buzbee67bf8852011-08-17 17:51:35 -070097{
98 int zLeading;
99 int zTrailing;
100 u4 b0 = value & 0xff;
101
102 /* Note: case of value==0 must use 0:000:0:0000000 encoding */
103 if (value <= 0xFF)
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 return b0; // 0:000:a:bcdefgh
buzbee67bf8852011-08-17 17:51:35 -0700105 if (value == ((b0 << 16) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700106 return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700107 if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700108 return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700109 b0 = (value >> 8) & 0xff;
110 if (value == ((b0 << 24) | (b0 << 8)))
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700112 /* Can we do it with rotation? */
113 zLeading = leadingZeros(value);
114 zTrailing = 32 - leadingZeros(~value & (value - 1));
115 /* A run of eight or fewer active bits? */
116 if ((zLeading + zTrailing) < 24)
Bill Buzbeea114add2012-05-03 15:00:40 -0700117 return -1; /* No - bail */
buzbee67bf8852011-08-17 17:51:35 -0700118 /* left-justify the constant, discarding msb (known to be 1) */
119 value <<= zLeading + 1;
120 /* Create bcdefgh */
121 value >>= 25;
122 /* Put it all together */
123 return value | ((0x8 + zLeading) << 7); /* [01000..11111]:bcdefgh */
124}
125
126/*
127 * Load a immediate using a shortcut if possible; otherwise
128 * grab from the per-translation literal pool.
129 *
130 * No additional register clobbering operation performed. Use this version when
131 * 1) rDest is freshly returned from oatAllocTemp or
132 * 2) The codegen is under fixed register usage
133 */
buzbee31a4a6f2012-02-28 15:36:15 -0800134LIR* loadConstantNoClobber(CompilationUnit* cUnit, int rDest, int value)
buzbee67bf8852011-08-17 17:51:35 -0700135{
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 LIR* res;
137 int modImm;
buzbee67bf8852011-08-17 17:51:35 -0700138
buzbeef0504cd2012-11-13 16:31:10 -0800139 if (ARM_FPREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 return loadFPConstantValue(cUnit, rDest, value);
141 }
buzbee67bf8852011-08-17 17:51:35 -0700142
Bill Buzbeea114add2012-05-03 15:00:40 -0700143 /* See if the value can be constructed cheaply */
buzbeef0504cd2012-11-13 16:31:10 -0800144 if (ARM_LOWREG(rDest) && (value >= 0) && (value <= 255)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700145 return newLIR2(cUnit, kThumbMovImm, rDest, value);
146 }
147 /* Check Modified immediate special cases */
148 modImm = modifiedImmediate(value);
149 if (modImm >= 0) {
150 res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm);
buzbee67bf8852011-08-17 17:51:35 -0700151 return res;
Bill Buzbeea114add2012-05-03 15:00:40 -0700152 }
153 modImm = modifiedImmediate(~value);
154 if (modImm >= 0) {
155 res = newLIR2(cUnit, kThumb2MvnImm12, rDest, modImm);
156 return res;
157 }
158 /* 16-bit immediate? */
159 if ((value & 0xffff) == value) {
160 res = newLIR2(cUnit, kThumb2MovImm16, rDest, value);
161 return res;
162 }
163 /* No shortcut - go ahead and use literal pool */
164 LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
165 if (dataTarget == NULL) {
166 dataTarget = addWordData(cUnit, &cUnit->literalList, value);
167 }
168 LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
169 kThumb2LdrPcRel12, rDest, 0, 0, 0, 0, dataTarget);
170 setMemRefType(loadPcRel, true, kLiteral);
171 loadPcRel->aliasInfo = (intptr_t)dataTarget;
172 res = loadPcRel;
173 oatAppendLIR(cUnit, (LIR* ) loadPcRel);
174
175 /*
176 * To save space in the constant pool, we use the ADD_RRI8 instruction to
177 * add up to 255 to an existing constant value.
178 */
179 if (dataTarget->operands[0] != value) {
180 opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]);
181 }
182 return res;
buzbee67bf8852011-08-17 17:51:35 -0700183}
184
Ian Rogers680b1bd2012-03-07 20:18:49 -0800185LIR* opBranchUnconditional(CompilationUnit* cUnit, OpKind op)
buzbee67bf8852011-08-17 17:51:35 -0700186{
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 DCHECK_EQ(op, kOpUncondBr);
188 return newLIR1(cUnit, kThumbBUncond, 0 /* offset to be patched */);
buzbee67bf8852011-08-17 17:51:35 -0700189}
190
buzbee82488f52012-03-02 08:20:26 -0800191LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700192{
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 LIR* branch = newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */,
194 oatArmConditionEncoding(cc));
195 branch->target = target;
196 return branch;
buzbee67bf8852011-08-17 17:51:35 -0700197}
198
buzbee31a4a6f2012-02-28 15:36:15 -0800199LIR* opReg(CompilationUnit* cUnit, OpKind op, int rDestSrc)
buzbee67bf8852011-08-17 17:51:35 -0700200{
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 ArmOpcode opcode = kThumbBkpt;
202 switch (op) {
203 case kOpBlx:
204 opcode = kThumbBlxR;
205 break;
206 default:
207 LOG(FATAL) << "Bad opcode " << (int)op;
208 }
209 return newLIR1(cUnit, opcode, rDestSrc);
buzbee67bf8852011-08-17 17:51:35 -0700210}
211
buzbee31a4a6f2012-02-28 15:36:15 -0800212LIR* opRegRegShift(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
213 int rSrc2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700214{
buzbeef0504cd2012-11-13 16:31:10 -0800215 bool thumbForm = ((shift == 0) && ARM_LOWREG(rDestSrc1) && ARM_LOWREG(rSrc2));
Bill Buzbeea114add2012-05-03 15:00:40 -0700216 ArmOpcode opcode = kThumbBkpt;
217 switch (op) {
218 case kOpAdc:
219 opcode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR;
220 break;
221 case kOpAnd:
222 opcode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR;
223 break;
224 case kOpBic:
225 opcode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR;
226 break;
227 case kOpCmn:
228 DCHECK_EQ(shift, 0);
229 opcode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR;
230 break;
231 case kOpCmp:
232 if (thumbForm)
233 opcode = kThumbCmpRR;
buzbeef0504cd2012-11-13 16:31:10 -0800234 else if ((shift == 0) && !ARM_LOWREG(rDestSrc1) && !ARM_LOWREG(rSrc2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700235 opcode = kThumbCmpHH;
buzbeef0504cd2012-11-13 16:31:10 -0800236 else if ((shift == 0) && ARM_LOWREG(rDestSrc1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700237 opcode = kThumbCmpLH;
238 else if (shift == 0)
239 opcode = kThumbCmpHL;
240 else
241 opcode = kThumb2CmpRR;
242 break;
243 case kOpXor:
244 opcode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR;
245 break;
246 case kOpMov:
247 DCHECK_EQ(shift, 0);
buzbeef0504cd2012-11-13 16:31:10 -0800248 if (ARM_LOWREG(rDestSrc1) && ARM_LOWREG(rSrc2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 opcode = kThumbMovRR;
buzbeef0504cd2012-11-13 16:31:10 -0800250 else if (!ARM_LOWREG(rDestSrc1) && !ARM_LOWREG(rSrc2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700251 opcode = kThumbMovRR_H2H;
buzbeef0504cd2012-11-13 16:31:10 -0800252 else if (ARM_LOWREG(rDestSrc1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700253 opcode = kThumbMovRR_H2L;
254 else
255 opcode = kThumbMovRR_L2H;
256 break;
257 case kOpMul:
258 DCHECK_EQ(shift, 0);
259 opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR;
260 break;
261 case kOpMvn:
262 opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR;
263 break;
264 case kOpNeg:
265 DCHECK_EQ(shift, 0);
266 opcode = (thumbForm) ? kThumbNeg : kThumb2NegRR;
267 break;
268 case kOpOr:
269 opcode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR;
270 break;
271 case kOpSbc:
272 opcode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR;
273 break;
274 case kOpTst:
275 opcode = (thumbForm) ? kThumbTst : kThumb2TstRR;
276 break;
277 case kOpLsl:
278 DCHECK_EQ(shift, 0);
279 opcode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR;
280 break;
281 case kOpLsr:
282 DCHECK_EQ(shift, 0);
283 opcode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR;
284 break;
285 case kOpAsr:
286 DCHECK_EQ(shift, 0);
287 opcode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR;
288 break;
289 case kOpRor:
290 DCHECK_EQ(shift, 0);
291 opcode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR;
292 break;
293 case kOpAdd:
294 opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
295 break;
296 case kOpSub:
297 opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
298 break;
299 case kOp2Byte:
300 DCHECK_EQ(shift, 0);
301 return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8);
302 case kOp2Short:
303 DCHECK_EQ(shift, 0);
304 return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16);
305 case kOp2Char:
306 DCHECK_EQ(shift, 0);
307 return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16);
308 default:
309 LOG(FATAL) << "Bad opcode: " << (int)op;
310 break;
311 }
312 DCHECK_GE(static_cast<int>(opcode), 0);
313 if (EncodingMap[opcode].flags & IS_BINARY_OP)
314 return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
315 else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
316 if (EncodingMap[opcode].fieldLoc[2].kind == kFmtShift)
317 return newLIR3(cUnit, opcode, rDestSrc1, rSrc2, shift);
318 else
319 return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2);
320 } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
321 return newLIR4(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2, shift);
322 else {
323 LOG(FATAL) << "Unexpected encoding operand count";
324 return NULL;
325 }
buzbee67bf8852011-08-17 17:51:35 -0700326}
327
buzbee31a4a6f2012-02-28 15:36:15 -0800328LIR* opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2)
buzbee67bf8852011-08-17 17:51:35 -0700329{
Bill Buzbeea114add2012-05-03 15:00:40 -0700330 return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700331}
332
buzbee31a4a6f2012-02-28 15:36:15 -0800333LIR* opRegRegRegShift(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700334 int rSrc2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700335{
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 ArmOpcode opcode = kThumbBkpt;
buzbeef0504cd2012-11-13 16:31:10 -0800337 bool thumbForm = (shift == 0) && ARM_LOWREG(rDest) && ARM_LOWREG(rSrc1) &&
338 ARM_LOWREG(rSrc2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 switch (op) {
340 case kOpAdd:
341 opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
342 break;
343 case kOpSub:
344 opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
345 break;
346 case kOpRsub:
347 opcode = kThumb2RsubRRR;
348 break;
349 case kOpAdc:
350 opcode = kThumb2AdcRRR;
351 break;
352 case kOpAnd:
353 opcode = kThumb2AndRRR;
354 break;
355 case kOpBic:
356 opcode = kThumb2BicRRR;
357 break;
358 case kOpXor:
359 opcode = kThumb2EorRRR;
360 break;
361 case kOpMul:
362 DCHECK_EQ(shift, 0);
363 opcode = kThumb2MulRRR;
364 break;
365 case kOpOr:
366 opcode = kThumb2OrrRRR;
367 break;
368 case kOpSbc:
369 opcode = kThumb2SbcRRR;
370 break;
371 case kOpLsl:
372 DCHECK_EQ(shift, 0);
373 opcode = kThumb2LslRRR;
374 break;
375 case kOpLsr:
376 DCHECK_EQ(shift, 0);
377 opcode = kThumb2LsrRRR;
378 break;
379 case kOpAsr:
380 DCHECK_EQ(shift, 0);
381 opcode = kThumb2AsrRRR;
382 break;
383 case kOpRor:
384 DCHECK_EQ(shift, 0);
385 opcode = kThumb2RorRRR;
386 break;
387 default:
388 LOG(FATAL) << "Bad opcode: " << (int)op;
389 break;
390 }
391 DCHECK_GE(static_cast<int>(opcode), 0);
392 if (EncodingMap[opcode].flags & IS_QUAD_OP)
393 return newLIR4(cUnit, opcode, rDest, rSrc1, rSrc2, shift);
394 else {
395 DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
396 return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
397 }
buzbee67bf8852011-08-17 17:51:35 -0700398}
399
buzbee31a4a6f2012-02-28 15:36:15 -0800400LIR* opRegRegReg(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
401 int rSrc2)
buzbee67bf8852011-08-17 17:51:35 -0700402{
Bill Buzbeea114add2012-05-03 15:00:40 -0700403 return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700404}
405
buzbee31a4a6f2012-02-28 15:36:15 -0800406LIR* opRegRegImm(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
407 int value)
buzbee67bf8852011-08-17 17:51:35 -0700408{
Bill Buzbeea114add2012-05-03 15:00:40 -0700409 LIR* res;
410 bool neg = (value < 0);
411 int absValue = (neg) ? -value : value;
412 ArmOpcode opcode = kThumbBkpt;
413 ArmOpcode altOpcode = kThumbBkpt;
buzbeef0504cd2012-11-13 16:31:10 -0800414 bool allLowRegs = (ARM_LOWREG(rDest) && ARM_LOWREG(rSrc1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 int modImm = modifiedImmediate(value);
416 int modImmNeg = modifiedImmediate(-value);
buzbee67bf8852011-08-17 17:51:35 -0700417
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 switch (op) {
419 case kOpLsl:
420 if (allLowRegs)
421 return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value);
422 else
423 return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value);
424 case kOpLsr:
425 if (allLowRegs)
426 return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value);
427 else
428 return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value);
429 case kOpAsr:
430 if (allLowRegs)
431 return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value);
432 else
433 return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value);
434 case kOpRor:
435 return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value);
436 case kOpAdd:
buzbeef0504cd2012-11-13 16:31:10 -0800437 if (ARM_LOWREG(rDest) && (rSrc1 == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700438 (value <= 1020) && ((value & 0x3)==0)) {
439 return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1, value >> 2);
buzbeef0504cd2012-11-13 16:31:10 -0800440 } else if (ARM_LOWREG(rDest) && (rSrc1 == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700441 (value <= 1020) && ((value & 0x3)==0)) {
442 return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1, value >> 2);
443 }
444 // Note: intentional fallthrough
445 case kOpSub:
446 if (allLowRegs && ((absValue & 0x7) == absValue)) {
447 if (op == kOpAdd)
448 opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
buzbee67bf8852011-08-17 17:51:35 -0700449 else
Bill Buzbeea114add2012-05-03 15:00:40 -0700450 opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
451 return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
452 } else if ((absValue & 0xff) == absValue) {
453 if (op == kOpAdd)
454 opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
455 else
456 opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
457 return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
458 }
459 if (modImmNeg >= 0) {
460 op = (op == kOpAdd) ? kOpSub : kOpAdd;
461 modImm = modImmNeg;
462 }
463 if (op == kOpSub) {
464 opcode = kThumb2SubRRI8;
465 altOpcode = kThumb2SubRRR;
466 } else {
467 opcode = kThumb2AddRRI8;
468 altOpcode = kThumb2AddRRR;
469 }
470 break;
471 case kOpAdc:
472 opcode = kThumb2AdcRRI8;
473 altOpcode = kThumb2AdcRRR;
474 break;
475 case kOpSbc:
476 opcode = kThumb2SbcRRI8;
477 altOpcode = kThumb2SbcRRR;
478 break;
479 case kOpOr:
480 opcode = kThumb2OrrRRI8;
481 altOpcode = kThumb2OrrRRR;
482 break;
483 case kOpAnd:
484 opcode = kThumb2AndRRI8;
485 altOpcode = kThumb2AndRRR;
486 break;
487 case kOpXor:
488 opcode = kThumb2EorRRI8;
489 altOpcode = kThumb2EorRRR;
490 break;
491 case kOpMul:
492 //TUNING: power of 2, shift & add
493 modImm = -1;
494 altOpcode = kThumb2MulRRR;
495 break;
496 case kOpCmp: {
497 int modImm = modifiedImmediate(value);
498 LIR* res;
499 if (modImm >= 0) {
500 res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm);
501 } else {
502 int rTmp = oatAllocTemp(cUnit);
503 res = loadConstant(cUnit, rTmp, value);
504 opRegReg(cUnit, kOpCmp, rSrc1, rTmp);
505 oatFreeTemp(cUnit, rTmp);
506 }
507 return res;
buzbee67bf8852011-08-17 17:51:35 -0700508 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700509 default:
510 LOG(FATAL) << "Bad opcode: " << (int)op;
511 }
512
513 if (modImm >= 0) {
514 return newLIR3(cUnit, opcode, rDest, rSrc1, modImm);
515 } else {
516 int rScratch = oatAllocTemp(cUnit);
517 loadConstant(cUnit, rScratch, value);
518 if (EncodingMap[altOpcode].flags & IS_QUAD_OP)
519 res = newLIR4(cUnit, altOpcode, rDest, rSrc1, rScratch, 0);
520 else
521 res = newLIR3(cUnit, altOpcode, rDest, rSrc1, rScratch);
522 oatFreeTemp(cUnit, rScratch);
523 return res;
524 }
buzbee67bf8852011-08-17 17:51:35 -0700525}
526
527/* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
buzbee31a4a6f2012-02-28 15:36:15 -0800528LIR* opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700529{
Bill Buzbeea114add2012-05-03 15:00:40 -0700530 bool neg = (value < 0);
531 int absValue = (neg) ? -value : value;
buzbeef0504cd2012-11-13 16:31:10 -0800532 bool shortForm = (((absValue & 0xff) == absValue) && ARM_LOWREG(rDestSrc1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 ArmOpcode opcode = kThumbBkpt;
534 switch (op) {
535 case kOpAdd:
536 if ( !neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
537 DCHECK_EQ((value & 0x3), 0);
538 return newLIR1(cUnit, kThumbAddSpI7, value >> 2);
539 } else if (shortForm) {
540 opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
541 }
542 break;
543 case kOpSub:
544 if (!neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
545 DCHECK_EQ((value & 0x3), 0);
546 return newLIR1(cUnit, kThumbSubSpI7, value >> 2);
547 } else if (shortForm) {
548 opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
549 }
550 break;
551 case kOpCmp:
buzbeef0504cd2012-11-13 16:31:10 -0800552 if (ARM_LOWREG(rDestSrc1) && shortForm)
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 opcode = (shortForm) ? kThumbCmpRI8 : kThumbCmpRR;
buzbeef0504cd2012-11-13 16:31:10 -0800554 else if (ARM_LOWREG(rDestSrc1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700555 opcode = kThumbCmpRR;
556 else {
557 shortForm = false;
558 opcode = kThumbCmpHL;
559 }
560 break;
561 default:
562 /* Punt to opRegRegImm - if bad case catch it there */
563 shortForm = false;
564 break;
565 }
566 if (shortForm)
567 return newLIR2(cUnit, opcode, rDestSrc1, absValue);
568 else {
569 return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
570 }
buzbee67bf8852011-08-17 17:51:35 -0700571}
572
573/*
574 * Determine whether value can be encoded as a Thumb2 floating point
575 * immediate. If not, return -1. If so return encoded 8-bit value.
576 */
buzbee31a4a6f2012-02-28 15:36:15 -0800577int encodeImmDoubleHigh(int value)
buzbee67bf8852011-08-17 17:51:35 -0700578{
Bill Buzbeea114add2012-05-03 15:00:40 -0700579 int res;
580 int bitA = (value & 0x80000000) >> 31;
581 int notBitB = (value & 0x40000000) >> 30;
582 int bitB = (value & 0x20000000) >> 29;
583 int bSmear = (value & 0x3fc00000) >> 22;
584 int slice = (value & 0x003f0000) >> 16;
585 int zeroes = (value & 0x0000ffff);
586 if (zeroes != 0)
587 return -1;
588 if (bitB) {
589 if ((notBitB != 0) || (bSmear != 0xff))
590 return -1;
591 } else {
592 if ((notBitB != 1) || (bSmear != 0x0))
593 return -1;
594 }
595 res = (bitA << 7) | (bitB << 6) | slice;
596 return res;
buzbee67bf8852011-08-17 17:51:35 -0700597}
598
buzbee31a4a6f2012-02-28 15:36:15 -0800599int encodeImmDouble(int valLo, int valHi)
buzbee67bf8852011-08-17 17:51:35 -0700600{
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 int res = -1;
602 if (valLo == 0)
603 res = encodeImmDoubleHigh(valHi);
604 return res;
buzbee67bf8852011-08-17 17:51:35 -0700605}
606
buzbee31a4a6f2012-02-28 15:36:15 -0800607LIR* loadConstantValueWide(CompilationUnit* cUnit, int rDestLo, int rDestHi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700608 int valLo, int valHi)
buzbee67bf8852011-08-17 17:51:35 -0700609{
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 int encodedImm = encodeImmDouble(valLo, valHi);
611 LIR* res;
buzbeef0504cd2012-11-13 16:31:10 -0800612 if (ARM_FPREG(rDestLo)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 if (encodedImm >= 0) {
buzbeef0504cd2012-11-13 16:31:10 -0800614 res = newLIR2(cUnit, kThumb2Vmovd_IMM8, s2d(rDestLo, rDestHi),
Bill Buzbeea114add2012-05-03 15:00:40 -0700615 encodedImm);
buzbee67bf8852011-08-17 17:51:35 -0700616 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700617 LIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo, valHi);
618 if (dataTarget == NULL) {
619 dataTarget = addWideData(cUnit, &cUnit->literalList, valLo, valHi);
620 }
621 LIR* loadPcRel =
622 rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrd,
buzbeef0504cd2012-11-13 16:31:10 -0800623 s2d(rDestLo, rDestHi), r15pc, 0, 0, 0, dataTarget);
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 setMemRefType(loadPcRel, true, kLiteral);
625 loadPcRel->aliasInfo = (intptr_t)dataTarget;
626 oatAppendLIR(cUnit, (LIR* ) loadPcRel);
627 res = loadPcRel;
buzbee67bf8852011-08-17 17:51:35 -0700628 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700629 } else {
630 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
631 loadConstantNoClobber(cUnit, rDestHi, valHi);
632 }
633 return res;
buzbee67bf8852011-08-17 17:51:35 -0700634}
635
buzbee31a4a6f2012-02-28 15:36:15 -0800636int encodeShift(int code, int amount) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 return ((amount & 0x1f) << 2) | code;
buzbee67bf8852011-08-17 17:51:35 -0700638}
639
buzbee31a4a6f2012-02-28 15:36:15 -0800640LIR* loadBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rDest,
641 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700642{
buzbeef0504cd2012-11-13 16:31:10 -0800643 bool allLowRegs = ARM_LOWREG(rBase) && ARM_LOWREG(rIndex) && ARM_LOWREG(rDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700644 LIR* load;
645 ArmOpcode opcode = kThumbBkpt;
646 bool thumbForm = (allLowRegs && (scale == 0));
647 int regPtr;
buzbee67bf8852011-08-17 17:51:35 -0700648
buzbeef0504cd2012-11-13 16:31:10 -0800649 if (ARM_FPREG(rDest)) {
650 if (ARM_SINGLEREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700651 DCHECK((size == kWord) || (size == kSingle));
652 opcode = kThumb2Vldrs;
653 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700654 } else {
buzbeef0504cd2012-11-13 16:31:10 -0800655 DCHECK(ARM_DOUBLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700656 DCHECK((size == kLong) || (size == kDouble));
Elliott Hughes74847412012-06-20 18:10:21 -0700657 DCHECK_EQ((rDest & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700658 opcode = kThumb2Vldrd;
659 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700660 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 } else {
662 if (size == kSingle)
663 size = kWord;
664 }
buzbee67bf8852011-08-17 17:51:35 -0700665
Bill Buzbeea114add2012-05-03 15:00:40 -0700666 switch (size) {
667 case kDouble: // fall-through
668 case kSingle:
669 regPtr = oatAllocTemp(cUnit);
670 if (scale) {
671 newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
672 encodeShift(kArmLsl, scale));
673 } else {
674 opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
675 }
676 load = newLIR3(cUnit, opcode, rDest, regPtr, 0);
677 oatFreeTemp(cUnit, regPtr);
678 return load;
679 case kWord:
680 opcode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR;
681 break;
682 case kUnsignedHalf:
683 opcode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR;
684 break;
685 case kSignedHalf:
686 opcode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR;
687 break;
688 case kUnsignedByte:
689 opcode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR;
690 break;
691 case kSignedByte:
692 opcode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
693 break;
694 default:
695 LOG(FATAL) << "Bad size: " << (int)size;
696 }
697 if (thumbForm)
698 load = newLIR3(cUnit, opcode, rDest, rBase, rIndex);
699 else
700 load = newLIR4(cUnit, opcode, rDest, rBase, rIndex, scale);
buzbee67bf8852011-08-17 17:51:35 -0700701
Bill Buzbeea114add2012-05-03 15:00:40 -0700702 return load;
buzbee67bf8852011-08-17 17:51:35 -0700703}
704
buzbee31a4a6f2012-02-28 15:36:15 -0800705LIR* storeBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rSrc,
706 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700707{
buzbeef0504cd2012-11-13 16:31:10 -0800708 bool allLowRegs = ARM_LOWREG(rBase) && ARM_LOWREG(rIndex) && ARM_LOWREG(rSrc);
Bill Buzbeea114add2012-05-03 15:00:40 -0700709 LIR* store;
710 ArmOpcode opcode = kThumbBkpt;
711 bool thumbForm = (allLowRegs && (scale == 0));
712 int regPtr;
buzbee67bf8852011-08-17 17:51:35 -0700713
buzbeef0504cd2012-11-13 16:31:10 -0800714 if (ARM_FPREG(rSrc)) {
715 if (ARM_SINGLEREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700716 DCHECK((size == kWord) || (size == kSingle));
717 opcode = kThumb2Vstrs;
718 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700719 } else {
buzbeef0504cd2012-11-13 16:31:10 -0800720 DCHECK(ARM_DOUBLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700721 DCHECK((size == kLong) || (size == kDouble));
Elliott Hughes74847412012-06-20 18:10:21 -0700722 DCHECK_EQ((rSrc & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700723 opcode = kThumb2Vstrd;
724 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700725 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700726 } else {
727 if (size == kSingle)
728 size = kWord;
729 }
buzbee67bf8852011-08-17 17:51:35 -0700730
Bill Buzbeea114add2012-05-03 15:00:40 -0700731 switch (size) {
732 case kDouble: // fall-through
733 case kSingle:
734 regPtr = oatAllocTemp(cUnit);
735 if (scale) {
736 newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
737 encodeShift(kArmLsl, scale));
738 } else {
739 opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
740 }
741 store = newLIR3(cUnit, opcode, rSrc, regPtr, 0);
742 oatFreeTemp(cUnit, regPtr);
743 return store;
744 case kWord:
745 opcode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR;
746 break;
747 case kUnsignedHalf:
748 case kSignedHalf:
749 opcode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR;
750 break;
751 case kUnsignedByte:
752 case kSignedByte:
753 opcode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR;
754 break;
755 default:
756 LOG(FATAL) << "Bad size: " << (int)size;
757 }
758 if (thumbForm)
759 store = newLIR3(cUnit, opcode, rSrc, rBase, rIndex);
760 else
761 store = newLIR4(cUnit, opcode, rSrc, rBase, rIndex, scale);
buzbee67bf8852011-08-17 17:51:35 -0700762
Bill Buzbeea114add2012-05-03 15:00:40 -0700763 return store;
buzbee67bf8852011-08-17 17:51:35 -0700764}
765
766/*
767 * Load value from base + displacement. Optionally perform null check
768 * on base (which must have an associated sReg and MIR). If not
769 * performing null check, incoming MIR can be null.
770 */
buzbee408ad162012-06-06 16:45:18 -0700771LIR* loadBaseDispBody(CompilationUnit* cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -0800772 int displacement, int rDest, int rDestHi, OpSize size,
773 int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700774{
Bill Buzbeea114add2012-05-03 15:00:40 -0700775 LIR* res;
776 LIR* load;
777 ArmOpcode opcode = kThumbBkpt;
778 bool shortForm = false;
779 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeef0504cd2012-11-13 16:31:10 -0800780 bool allLowRegs = (ARM_LOWREG(rBase) && ARM_LOWREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700781 int encodedDisp = displacement;
782 bool is64bit = false;
783 switch (size) {
784 case kDouble:
785 case kLong:
786 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800787 if (ARM_FPREG(rDest)) {
788 if (ARM_SINGLEREG(rDest)) {
789 DCHECK(ARM_FPREG(rDestHi));
790 rDest = s2d(rDest, rDestHi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700791 }
792 opcode = kThumb2Vldrd;
793 if (displacement <= 1020) {
794 shortForm = true;
795 encodedDisp >>= 2;
796 }
797 break;
798 } else {
buzbee408ad162012-06-06 16:45:18 -0700799 res = loadBaseDispBody(cUnit, rBase, displacement, rDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700800 -1, kWord, sReg);
buzbee408ad162012-06-06 16:45:18 -0700801 loadBaseDispBody(cUnit, rBase, displacement + 4, rDestHi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700802 -1, kWord, INVALID_SREG);
803 return res;
804 }
805 case kSingle:
806 case kWord:
buzbeef0504cd2012-11-13 16:31:10 -0800807 if (ARM_FPREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700808 opcode = kThumb2Vldrs;
809 if (displacement <= 1020) {
810 shortForm = true;
811 encodedDisp >>= 2;
812 }
813 break;
814 }
buzbeef0504cd2012-11-13 16:31:10 -0800815 if (ARM_LOWREG(rDest) && (rBase == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700816 (displacement <= 1020) && (displacement >= 0)) {
817 shortForm = true;
818 encodedDisp >>= 2;
819 opcode = kThumbLdrPcRel;
buzbeef0504cd2012-11-13 16:31:10 -0800820 } else if (ARM_LOWREG(rDest) && (rBase == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700821 (displacement <= 1020) && (displacement >= 0)) {
822 shortForm = true;
823 encodedDisp >>= 2;
824 opcode = kThumbLdrSpRel;
825 } else if (allLowRegs && displacement < 128 && displacement >= 0) {
826 DCHECK_EQ((displacement & 0x3), 0);
827 shortForm = true;
828 encodedDisp >>= 2;
829 opcode = kThumbLdrRRI5;
830 } else if (thumb2Form) {
831 shortForm = true;
832 opcode = kThumb2LdrRRI12;
833 }
834 break;
835 case kUnsignedHalf:
836 if (allLowRegs && displacement < 64 && displacement >= 0) {
837 DCHECK_EQ((displacement & 0x1), 0);
838 shortForm = true;
839 encodedDisp >>= 1;
840 opcode = kThumbLdrhRRI5;
841 } else if (displacement < 4092 && displacement >= 0) {
842 shortForm = true;
843 opcode = kThumb2LdrhRRI12;
844 }
845 break;
846 case kSignedHalf:
847 if (thumb2Form) {
848 shortForm = true;
849 opcode = kThumb2LdrshRRI12;
850 }
851 break;
852 case kUnsignedByte:
853 if (allLowRegs && displacement < 32 && displacement >= 0) {
854 shortForm = true;
855 opcode = kThumbLdrbRRI5;
856 } else if (thumb2Form) {
857 shortForm = true;
858 opcode = kThumb2LdrbRRI12;
859 }
860 break;
861 case kSignedByte:
862 if (thumb2Form) {
863 shortForm = true;
864 opcode = kThumb2LdrsbRRI12;
865 }
866 break;
867 default:
868 LOG(FATAL) << "Bad size: " << (int)size;
869 }
buzbee67bf8852011-08-17 17:51:35 -0700870
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 if (shortForm) {
872 load = res = newLIR3(cUnit, opcode, rDest, rBase, encodedDisp);
873 } else {
874 int regOffset = oatAllocTemp(cUnit);
875 res = loadConstant(cUnit, regOffset, encodedDisp);
876 load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size);
877 oatFreeTemp(cUnit, regOffset);
878 }
buzbee67bf8852011-08-17 17:51:35 -0700879
Bill Buzbeea114add2012-05-03 15:00:40 -0700880 // TODO: in future may need to differentiate Dalvik accesses w/ spills
buzbeef0504cd2012-11-13 16:31:10 -0800881 if (rBase == rARM_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700882 annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */, is64bit);
883 }
884 return load;
buzbee67bf8852011-08-17 17:51:35 -0700885}
886
buzbee408ad162012-06-06 16:45:18 -0700887LIR* loadBaseDisp(CompilationUnit* cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -0800888 int displacement, int rDest, OpSize size, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700889{
buzbee408ad162012-06-06 16:45:18 -0700890 return loadBaseDispBody(cUnit, rBase, displacement, rDest, -1, size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700891 sReg);
buzbee67bf8852011-08-17 17:51:35 -0700892}
893
buzbee408ad162012-06-06 16:45:18 -0700894 LIR* loadBaseDispWide(CompilationUnit* cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -0800895 int displacement, int rDestLo, int rDestHi, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700896{
buzbee408ad162012-06-06 16:45:18 -0700897 return loadBaseDispBody(cUnit, rBase, displacement, rDestLo, rDestHi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700898 kLong, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700899}
900
901
buzbee31a4a6f2012-02-28 15:36:15 -0800902LIR* storeBaseDispBody(CompilationUnit* cUnit, int rBase, int displacement,
903 int rSrc, int rSrcHi, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700904{
Bill Buzbeea114add2012-05-03 15:00:40 -0700905 LIR* res, *store;
906 ArmOpcode opcode = kThumbBkpt;
907 bool shortForm = false;
908 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeef0504cd2012-11-13 16:31:10 -0800909 bool allLowRegs = (ARM_LOWREG(rBase) && ARM_LOWREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700910 int encodedDisp = displacement;
911 bool is64bit = false;
912 switch (size) {
913 case kLong:
914 case kDouble:
915 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800916 if (!ARM_FPREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700917 res = storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, kWord);
918 storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi, -1, kWord);
919 return res;
920 }
buzbeef0504cd2012-11-13 16:31:10 -0800921 if (ARM_SINGLEREG(rSrc)) {
922 DCHECK(ARM_FPREG(rSrcHi));
923 rSrc = s2d(rSrc, rSrcHi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700924 }
925 opcode = kThumb2Vstrd;
926 if (displacement <= 1020) {
927 shortForm = true;
928 encodedDisp >>= 2;
929 }
930 break;
931 case kSingle:
932 case kWord:
buzbeef0504cd2012-11-13 16:31:10 -0800933 if (ARM_FPREG(rSrc)) {
934 DCHECK(ARM_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700935 opcode = kThumb2Vstrs;
936 if (displacement <= 1020) {
937 shortForm = true;
938 encodedDisp >>= 2;
939 }
940 break;
941 }
942 if (allLowRegs && displacement < 128 && displacement >= 0) {
943 DCHECK_EQ((displacement & 0x3), 0);
944 shortForm = true;
945 encodedDisp >>= 2;
946 opcode = kThumbStrRRI5;
947 } else if (thumb2Form) {
948 shortForm = true;
949 opcode = kThumb2StrRRI12;
950 }
951 break;
952 case kUnsignedHalf:
953 case kSignedHalf:
954 if (allLowRegs && displacement < 64 && displacement >= 0) {
955 DCHECK_EQ((displacement & 0x1), 0);
956 shortForm = true;
957 encodedDisp >>= 1;
958 opcode = kThumbStrhRRI5;
959 } else if (thumb2Form) {
960 shortForm = true;
961 opcode = kThumb2StrhRRI12;
962 }
963 break;
964 case kUnsignedByte:
965 case kSignedByte:
966 if (allLowRegs && displacement < 32 && displacement >= 0) {
967 shortForm = true;
968 opcode = kThumbStrbRRI5;
969 } else if (thumb2Form) {
970 shortForm = true;
971 opcode = kThumb2StrbRRI12;
972 }
973 break;
974 default:
975 LOG(FATAL) << "Bad size: " << (int)size;
976 }
977 if (shortForm) {
978 store = res = newLIR3(cUnit, opcode, rSrc, rBase, encodedDisp);
979 } else {
980 int rScratch = oatAllocTemp(cUnit);
981 res = loadConstant(cUnit, rScratch, encodedDisp);
982 store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
983 oatFreeTemp(cUnit, rScratch);
984 }
buzbee67bf8852011-08-17 17:51:35 -0700985
Bill Buzbeea114add2012-05-03 15:00:40 -0700986 // TODO: In future, may need to differentiate Dalvik & spill accesses
buzbeef0504cd2012-11-13 16:31:10 -0800987 if (rBase == rARM_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700988 annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */,
989 is64bit);
990 }
991 return res;
buzbee67bf8852011-08-17 17:51:35 -0700992}
993
buzbee31a4a6f2012-02-28 15:36:15 -0800994LIR* storeBaseDisp(CompilationUnit* cUnit, int rBase, int displacement,
995 int rSrc, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700996{
Bill Buzbeea114add2012-05-03 15:00:40 -0700997 return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
buzbee67bf8852011-08-17 17:51:35 -0700998}
999
buzbee31a4a6f2012-02-28 15:36:15 -08001000LIR* storeBaseDispWide(CompilationUnit* cUnit, int rBase, int displacement,
1001 int rSrcLo, int rSrcHi)
buzbee67bf8852011-08-17 17:51:35 -07001002{
Bill Buzbeea114add2012-05-03 15:00:40 -07001003 return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
buzbee67bf8852011-08-17 17:51:35 -07001004}
1005
buzbee31a4a6f2012-02-28 15:36:15 -08001006void loadPair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
buzbee67bf8852011-08-17 17:51:35 -07001007{
buzbee408ad162012-06-06 16:45:18 -07001008 loadBaseDispWide(cUnit, base, 0, lowReg, highReg, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001009}
1010
buzbee31a4a6f2012-02-28 15:36:15 -08001011LIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
buzbee67bf8852011-08-17 17:51:35 -07001012{
Bill Buzbeea114add2012-05-03 15:00:40 -07001013 int opcode;
buzbeef0504cd2012-11-13 16:31:10 -08001014 DCHECK_EQ(ARM_DOUBLEREG(rDest), ARM_DOUBLEREG(rSrc));
1015 if (ARM_DOUBLEREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001016 opcode = kThumb2Vmovd;
1017 } else {
buzbeef0504cd2012-11-13 16:31:10 -08001018 if (ARM_SINGLEREG(rDest)) {
1019 opcode = ARM_SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr;
buzbeea2ebdd72012-03-04 14:57:06 -08001020 } else {
buzbeef0504cd2012-11-13 16:31:10 -08001021 DCHECK(ARM_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -07001022 opcode = kThumb2Fmrs;
buzbeea2ebdd72012-03-04 14:57:06 -08001023 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001024 }
1025 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
1026 if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
1027 res->flags.isNop = true;
1028 }
1029 return res;
buzbee67bf8852011-08-17 17:51:35 -07001030}
1031
buzbeeb046e162012-10-30 15:48:42 -07001032LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset)
1033{
1034 LOG(FATAL) << "Unexpected use of opThreadMem for Arm";
1035 return NULL;
1036}
buzbee67bf8852011-08-17 17:51:35 -07001037
buzbeeb046e162012-10-30 15:48:42 -07001038LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp)
1039{
1040 LOG(FATAL) << "Unexpected use of opMem for Arm";
1041 return NULL;
1042}
1043
1044LIR* storeBaseIndexedDisp(CompilationUnit *cUnit,
1045 int rBase, int rIndex, int scale, int displacement,
1046 int rSrc, int rSrcHi,
1047 OpSize size, int sReg)
1048{
1049 LOG(FATAL) << "Unexpected use of storeBaseIndexedDisp for Arm";
1050 return NULL;
1051}
1052
1053LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase,
1054 int offset)
1055{
1056 LOG(FATAL) << "Unexpected use of opRegMem for Arm";
1057 return NULL;
1058}
1059
1060LIR* loadBaseIndexedDisp(CompilationUnit *cUnit,
1061 int rBase, int rIndex, int scale, int displacement,
1062 int rDest, int rDestHi,
1063 OpSize size, int sReg)
1064{
1065 LOG(FATAL) << "Unexpected use of loadBaseIndexedDisp for Arm";
1066 return NULL;
1067}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001068
1069} // namespace art