blob: b6df8e3ead72904081274f04fae32ba21effc6f7 [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
buzbee67bf8852011-08-17 17:51:35 -070019/*
20 * This file contains codegen for the Thumb ISA and is intended to be
21 * includes by:
22 *
23 * Codegen-$(TARGET_ARCH_VARIANT).c
24 *
25 */
26
buzbee68253262011-10-07 14:02:25 -070027static int coreRegs[] = {r0, r1, r2, r3, rSUSPEND, r5, r6, r7, r8, rSELF, r10,
buzbeec1f45042011-09-21 16:03:19 -070028 r11, r12, rSP, rLR, rPC};
29static int reservedRegs[] = {rSUSPEND, rSELF, rSP, rLR, rPC};
buzbee67bf8852011-08-17 17:51:35 -070030static int fpRegs[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
31 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15,
32 fr16, fr17, fr18, fr19, fr20, fr21, fr22, fr23,
33 fr24, fr25, fr26, fr27, fr28, fr29, fr30, fr31};
34static int coreTemps[] = {r0, r1, r2, r3, r12};
35static int fpTemps[] = {fr0, fr1, fr2, fr3, fr4, fr5, fr6, fr7,
36 fr8, fr9, fr10, fr11, fr12, fr13, fr14, fr15};
37
buzbee31a4a6f2012-02-28 15:36:15 -080038int encodeImmSingle(int value)
buzbee67bf8852011-08-17 17:51:35 -070039{
40 int res;
41 int bitA = (value & 0x80000000) >> 31;
42 int notBitB = (value & 0x40000000) >> 30;
43 int bitB = (value & 0x20000000) >> 29;
44 int bSmear = (value & 0x3e000000) >> 25;
45 int slice = (value & 0x01f80000) >> 19;
46 int zeroes = (value & 0x0007ffff);
47 if (zeroes != 0)
48 return -1;
49 if (bitB) {
50 if ((notBitB != 0) || (bSmear != 0x1f))
51 return -1;
52 } else {
53 if ((notBitB != 1) || (bSmear != 0x0))
54 return -1;
55 }
56 res = (bitA << 7) | (bitB << 6) | slice;
57 return res;
58}
59
buzbee31a4a6f2012-02-28 15:36:15 -080060LIR* loadFPConstantValue(CompilationUnit* cUnit, int rDest, int value)
buzbee67bf8852011-08-17 17:51:35 -070061{
62 int encodedImm = encodeImmSingle(value);
buzbeeed3e9302011-09-23 17:34:19 -070063 DCHECK(SINGLEREG(rDest));
buzbee67bf8852011-08-17 17:51:35 -070064 if (encodedImm >= 0) {
65 return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
66 }
buzbee31a4a6f2012-02-28 15:36:15 -080067 LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
buzbee67bf8852011-08-17 17:51:35 -070068 if (dataTarget == NULL) {
69 dataTarget = addWordData(cUnit, &cUnit->literalList, value);
70 }
buzbeea2ebdd72012-03-04 14:57:06 -080071 LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrs,
72 rDest, r15pc, 0, 0, dataTarget);
buzbee67bf8852011-08-17 17:51:35 -070073 setMemRefType(loadPcRel, true, kLiteral);
buzbeebbaf8942011-10-02 13:08:29 -070074 loadPcRel->aliasInfo = (intptr_t)dataTarget;
buzbee67bf8852011-08-17 17:51:35 -070075 oatAppendLIR(cUnit, (LIR* ) loadPcRel);
76 return loadPcRel;
77}
78
buzbee31a4a6f2012-02-28 15:36:15 -080079int leadingZeros(u4 val)
buzbee67bf8852011-08-17 17:51:35 -070080{
81 u4 alt;
82 int n;
83 int count;
84
85 count = 16;
86 n = 32;
87 do {
88 alt = val >> count;
89 if (alt != 0) {
90 n = n - count;
91 val = alt;
92 }
93 count >>= 1;
94 } while (count);
95 return n - val;
96}
97
98/*
99 * Determine whether value can be encoded as a Thumb2 modified
100 * immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form.
101 */
buzbee31a4a6f2012-02-28 15:36:15 -0800102int modifiedImmediate(u4 value)
buzbee67bf8852011-08-17 17:51:35 -0700103{
104 int zLeading;
105 int zTrailing;
106 u4 b0 = value & 0xff;
107
108 /* Note: case of value==0 must use 0:000:0:0000000 encoding */
109 if (value <= 0xFF)
110 return b0; // 0:000:a:bcdefgh
111 if (value == ((b0 << 16) | b0))
112 return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
113 if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
114 return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
115 b0 = (value >> 8) & 0xff;
116 if (value == ((b0 << 24) | (b0 << 8)))
117 return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
118 /* Can we do it with rotation? */
119 zLeading = leadingZeros(value);
120 zTrailing = 32 - leadingZeros(~value & (value - 1));
121 /* A run of eight or fewer active bits? */
122 if ((zLeading + zTrailing) < 24)
123 return -1; /* No - bail */
124 /* left-justify the constant, discarding msb (known to be 1) */
125 value <<= zLeading + 1;
126 /* Create bcdefgh */
127 value >>= 25;
128 /* Put it all together */
129 return value | ((0x8 + zLeading) << 7); /* [01000..11111]:bcdefgh */
130}
131
132/*
133 * Load a immediate using a shortcut if possible; otherwise
134 * grab from the per-translation literal pool.
135 *
136 * No additional register clobbering operation performed. Use this version when
137 * 1) rDest is freshly returned from oatAllocTemp or
138 * 2) The codegen is under fixed register usage
139 */
buzbee31a4a6f2012-02-28 15:36:15 -0800140LIR* loadConstantNoClobber(CompilationUnit* cUnit, int rDest, int value)
buzbee67bf8852011-08-17 17:51:35 -0700141{
buzbee31a4a6f2012-02-28 15:36:15 -0800142 LIR* res;
buzbee67bf8852011-08-17 17:51:35 -0700143 int modImm;
144
145 if (FPREG(rDest)) {
146 return loadFPConstantValue(cUnit, rDest, value);
147 }
148
149 /* See if the value can be constructed cheaply */
150 if (LOWREG(rDest) && (value >= 0) && (value <= 255)) {
151 return newLIR2(cUnit, kThumbMovImm, rDest, value);
152 }
153 /* Check Modified immediate special cases */
154 modImm = modifiedImmediate(value);
155 if (modImm >= 0) {
156 res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm);
157 return res;
158 }
159 modImm = modifiedImmediate(~value);
160 if (modImm >= 0) {
buzbee58f92742011-10-01 11:22:17 -0700161 res = newLIR2(cUnit, kThumb2MvnImm12, rDest, modImm);
buzbee67bf8852011-08-17 17:51:35 -0700162 return res;
163 }
164 /* 16-bit immediate? */
165 if ((value & 0xffff) == value) {
166 res = newLIR2(cUnit, kThumb2MovImm16, rDest, value);
167 return res;
168 }
169 /* No shortcut - go ahead and use literal pool */
buzbee31a4a6f2012-02-28 15:36:15 -0800170 LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
buzbee67bf8852011-08-17 17:51:35 -0700171 if (dataTarget == NULL) {
172 dataTarget = addWordData(cUnit, &cUnit->literalList, value);
173 }
buzbeea2ebdd72012-03-04 14:57:06 -0800174 LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
175 kThumb2LdrPcRel12, rDest, 0, 0, 0, dataTarget);
buzbee67bf8852011-08-17 17:51:35 -0700176 setMemRefType(loadPcRel, true, kLiteral);
buzbeebbaf8942011-10-02 13:08:29 -0700177 loadPcRel->aliasInfo = (intptr_t)dataTarget;
buzbee67bf8852011-08-17 17:51:35 -0700178 res = loadPcRel;
179 oatAppendLIR(cUnit, (LIR* ) loadPcRel);
180
181 /*
182 * To save space in the constant pool, we use the ADD_RRI8 instruction to
183 * add up to 255 to an existing constant value.
184 */
185 if (dataTarget->operands[0] != value) {
186 opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]);
187 }
188 return res;
189}
190
buzbee31a4a6f2012-02-28 15:36:15 -0800191LIR* opNone(CompilationUnit* cUnit, OpKind op)
buzbee67bf8852011-08-17 17:51:35 -0700192{
193 ArmOpcode opcode = kThumbBkpt;
194 switch (op) {
195 case kOpUncondBr:
196 opcode = kThumbBUncond;
197 break;
198 default:
buzbeeed3e9302011-09-23 17:34:19 -0700199 LOG(FATAL) << "Bad opcode " << (int)op;
buzbee67bf8852011-08-17 17:51:35 -0700200 }
201 return newLIR0(cUnit, opcode);
202}
203
buzbee82488f52012-03-02 08:20:26 -0800204LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700205{
buzbee82488f52012-03-02 08:20:26 -0800206 LIR* branch = newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */,
207 oatArmConditionEncoding(cc));
208 branch->target = target;
209 return branch;
buzbee67bf8852011-08-17 17:51:35 -0700210}
211
buzbee31a4a6f2012-02-28 15:36:15 -0800212LIR* opReg(CompilationUnit* cUnit, OpKind op, int rDestSrc)
buzbee67bf8852011-08-17 17:51:35 -0700213{
214 ArmOpcode opcode = kThumbBkpt;
215 switch (op) {
216 case kOpBlx:
217 opcode = kThumbBlxR;
218 break;
219 default:
buzbeeed3e9302011-09-23 17:34:19 -0700220 LOG(FATAL) << "Bad opcode " << (int)op;
buzbee67bf8852011-08-17 17:51:35 -0700221 }
222 return newLIR1(cUnit, opcode, rDestSrc);
223}
224
buzbee31a4a6f2012-02-28 15:36:15 -0800225LIR* opRegRegShift(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
226 int rSrc2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700227{
228 bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2));
229 ArmOpcode opcode = kThumbBkpt;
230 switch (op) {
231 case kOpAdc:
232 opcode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR;
233 break;
234 case kOpAnd:
235 opcode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR;
236 break;
237 case kOpBic:
238 opcode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR;
239 break;
240 case kOpCmn:
buzbeeed3e9302011-09-23 17:34:19 -0700241 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700242 opcode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR;
243 break;
244 case kOpCmp:
245 if (thumbForm)
246 opcode = kThumbCmpRR;
247 else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2))
248 opcode = kThumbCmpHH;
249 else if ((shift == 0) && LOWREG(rDestSrc1))
250 opcode = kThumbCmpLH;
251 else if (shift == 0)
252 opcode = kThumbCmpHL;
253 else
254 opcode = kThumb2CmpRR;
255 break;
256 case kOpXor:
257 opcode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR;
258 break;
259 case kOpMov:
buzbeeed3e9302011-09-23 17:34:19 -0700260 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700261 if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
262 opcode = kThumbMovRR;
263 else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
264 opcode = kThumbMovRR_H2H;
265 else if (LOWREG(rDestSrc1))
266 opcode = kThumbMovRR_H2L;
267 else
268 opcode = kThumbMovRR_L2H;
269 break;
270 case kOpMul:
buzbeeed3e9302011-09-23 17:34:19 -0700271 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700272 opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR;
273 break;
274 case kOpMvn:
275 opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR;
276 break;
277 case kOpNeg:
buzbeeed3e9302011-09-23 17:34:19 -0700278 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700279 opcode = (thumbForm) ? kThumbNeg : kThumb2NegRR;
280 break;
281 case kOpOr:
282 opcode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR;
283 break;
284 case kOpSbc:
285 opcode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR;
286 break;
287 case kOpTst:
288 opcode = (thumbForm) ? kThumbTst : kThumb2TstRR;
289 break;
290 case kOpLsl:
buzbeeed3e9302011-09-23 17:34:19 -0700291 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700292 opcode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR;
293 break;
294 case kOpLsr:
buzbeeed3e9302011-09-23 17:34:19 -0700295 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700296 opcode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR;
297 break;
298 case kOpAsr:
buzbeeed3e9302011-09-23 17:34:19 -0700299 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700300 opcode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR;
301 break;
302 case kOpRor:
buzbeeed3e9302011-09-23 17:34:19 -0700303 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700304 opcode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR;
305 break;
306 case kOpAdd:
307 opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
308 break;
309 case kOpSub:
310 opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
311 break;
312 case kOp2Byte:
buzbeeed3e9302011-09-23 17:34:19 -0700313 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700314 return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8);
315 case kOp2Short:
buzbeeed3e9302011-09-23 17:34:19 -0700316 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700317 return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16);
318 case kOp2Char:
buzbeeed3e9302011-09-23 17:34:19 -0700319 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700320 return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16);
321 default:
buzbeeed3e9302011-09-23 17:34:19 -0700322 LOG(FATAL) << "Bad opcode: " << (int)op;
buzbee67bf8852011-08-17 17:51:35 -0700323 break;
324 }
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700325 DCHECK_GE(static_cast<int>(opcode), 0);
buzbee67bf8852011-08-17 17:51:35 -0700326 if (EncodingMap[opcode].flags & IS_BINARY_OP)
327 return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
328 else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
329 if (EncodingMap[opcode].fieldLoc[2].kind == kFmtShift)
330 return newLIR3(cUnit, opcode, rDestSrc1, rSrc2, shift);
331 else
332 return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2);
333 } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
334 return newLIR4(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2, shift);
335 else {
buzbeeed3e9302011-09-23 17:34:19 -0700336 LOG(FATAL) << "Unexpected encoding operand count";
buzbee67bf8852011-08-17 17:51:35 -0700337 return NULL;
338 }
339}
340
buzbee31a4a6f2012-02-28 15:36:15 -0800341LIR* opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2)
buzbee67bf8852011-08-17 17:51:35 -0700342{
343 return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
344}
345
buzbee31a4a6f2012-02-28 15:36:15 -0800346LIR* opRegRegRegShift(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
347 int rSrc2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700348{
349 ArmOpcode opcode = kThumbBkpt;
350 bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) &&
351 LOWREG(rSrc2);
352 switch (op) {
353 case kOpAdd:
354 opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
355 break;
356 case kOpSub:
357 opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
358 break;
359 case kOpAdc:
360 opcode = kThumb2AdcRRR;
361 break;
362 case kOpAnd:
363 opcode = kThumb2AndRRR;
364 break;
365 case kOpBic:
366 opcode = kThumb2BicRRR;
367 break;
368 case kOpXor:
369 opcode = kThumb2EorRRR;
370 break;
371 case kOpMul:
buzbeeed3e9302011-09-23 17:34:19 -0700372 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700373 opcode = kThumb2MulRRR;
374 break;
375 case kOpOr:
376 opcode = kThumb2OrrRRR;
377 break;
378 case kOpSbc:
379 opcode = kThumb2SbcRRR;
380 break;
381 case kOpLsl:
buzbeeed3e9302011-09-23 17:34:19 -0700382 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700383 opcode = kThumb2LslRRR;
384 break;
385 case kOpLsr:
buzbeeed3e9302011-09-23 17:34:19 -0700386 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700387 opcode = kThumb2LsrRRR;
388 break;
389 case kOpAsr:
buzbeeed3e9302011-09-23 17:34:19 -0700390 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700391 opcode = kThumb2AsrRRR;
392 break;
393 case kOpRor:
buzbeeed3e9302011-09-23 17:34:19 -0700394 DCHECK_EQ(shift, 0);
buzbee67bf8852011-08-17 17:51:35 -0700395 opcode = kThumb2RorRRR;
396 break;
397 default:
buzbeeed3e9302011-09-23 17:34:19 -0700398 LOG(FATAL) << "Bad opcode: " << (int)op;
buzbee67bf8852011-08-17 17:51:35 -0700399 break;
400 }
Elliott Hughesf5a7a472011-10-07 14:31:02 -0700401 DCHECK_GE(static_cast<int>(opcode), 0);
buzbee67bf8852011-08-17 17:51:35 -0700402 if (EncodingMap[opcode].flags & IS_QUAD_OP)
403 return newLIR4(cUnit, opcode, rDest, rSrc1, rSrc2, shift);
404 else {
buzbeeed3e9302011-09-23 17:34:19 -0700405 DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
buzbee67bf8852011-08-17 17:51:35 -0700406 return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
407 }
408}
409
buzbee31a4a6f2012-02-28 15:36:15 -0800410LIR* opRegRegReg(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
411 int rSrc2)
buzbee67bf8852011-08-17 17:51:35 -0700412{
413 return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
414}
415
buzbee31a4a6f2012-02-28 15:36:15 -0800416LIR* opRegRegImm(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
417 int value)
buzbee67bf8852011-08-17 17:51:35 -0700418{
buzbee31a4a6f2012-02-28 15:36:15 -0800419 LIR* res;
buzbee67bf8852011-08-17 17:51:35 -0700420 bool neg = (value < 0);
421 int absValue = (neg) ? -value : value;
422 ArmOpcode opcode = kThumbBkpt;
423 ArmOpcode altOpcode = kThumbBkpt;
424 bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1));
425 int modImm = modifiedImmediate(value);
426 int modImmNeg = modifiedImmediate(-value);
427
428 switch(op) {
429 case kOpLsl:
430 if (allLowRegs)
431 return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value);
432 else
433 return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value);
434 case kOpLsr:
435 if (allLowRegs)
436 return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value);
437 else
438 return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value);
439 case kOpAsr:
440 if (allLowRegs)
441 return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value);
442 else
443 return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value);
444 case kOpRor:
445 return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value);
446 case kOpAdd:
447 if (LOWREG(rDest) && (rSrc1 == r13sp) &&
448 (value <= 1020) && ((value & 0x3)==0)) {
449 return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1,
450 value >> 2);
451 } else if (LOWREG(rDest) && (rSrc1 == r15pc) &&
452 (value <= 1020) && ((value & 0x3)==0)) {
453 return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1,
454 value >> 2);
455 }
buzbee67bf8852011-08-17 17:51:35 -0700456 // Note: intentional fallthrough
457 case kOpSub:
458 if (allLowRegs && ((absValue & 0x7) == absValue)) {
459 if (op == kOpAdd)
460 opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
461 else
462 opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
463 return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
464 } else if ((absValue & 0xff) == absValue) {
465 if (op == kOpAdd)
466 opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
467 else
468 opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
469 return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
470 }
471 if (modImmNeg >= 0) {
472 op = (op == kOpAdd) ? kOpSub : kOpAdd;
473 modImm = modImmNeg;
474 }
475 if (op == kOpSub) {
476 opcode = kThumb2SubRRI8;
477 altOpcode = kThumb2SubRRR;
buzbee3b5d3792011-09-20 11:01:40 -0700478 } else {
479 opcode = kThumb2AddRRI8;
480 altOpcode = kThumb2AddRRR;
buzbee67bf8852011-08-17 17:51:35 -0700481 }
482 break;
483 case kOpAdc:
484 opcode = kThumb2AdcRRI8;
485 altOpcode = kThumb2AdcRRR;
486 break;
487 case kOpSbc:
488 opcode = kThumb2SbcRRI8;
489 altOpcode = kThumb2SbcRRR;
490 break;
491 case kOpOr:
492 opcode = kThumb2OrrRRI8;
493 altOpcode = kThumb2OrrRRR;
494 break;
495 case kOpAnd:
496 opcode = kThumb2AndRRI8;
497 altOpcode = kThumb2AndRRR;
498 break;
499 case kOpXor:
500 opcode = kThumb2EorRRI8;
501 altOpcode = kThumb2EorRRR;
502 break;
503 case kOpMul:
504 //TUNING: power of 2, shift & add
505 modImm = -1;
506 altOpcode = kThumb2MulRRR;
507 break;
508 case kOpCmp: {
509 int modImm = modifiedImmediate(value);
buzbee31a4a6f2012-02-28 15:36:15 -0800510 LIR* res;
buzbee67bf8852011-08-17 17:51:35 -0700511 if (modImm >= 0) {
512 res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm);
513 } else {
514 int rTmp = oatAllocTemp(cUnit);
515 res = loadConstant(cUnit, rTmp, value);
516 opRegReg(cUnit, kOpCmp, rSrc1, rTmp);
517 oatFreeTemp(cUnit, rTmp);
518 }
519 return res;
520 }
521 default:
buzbeeed3e9302011-09-23 17:34:19 -0700522 LOG(FATAL) << "Bad opcode: " << (int)op;
buzbee67bf8852011-08-17 17:51:35 -0700523 }
524
525 if (modImm >= 0) {
526 return newLIR3(cUnit, opcode, rDest, rSrc1, modImm);
527 } else {
528 int rScratch = oatAllocTemp(cUnit);
529 loadConstant(cUnit, rScratch, value);
530 if (EncodingMap[altOpcode].flags & IS_QUAD_OP)
531 res = newLIR4(cUnit, altOpcode, rDest, rSrc1, rScratch, 0);
532 else
533 res = newLIR3(cUnit, altOpcode, rDest, rSrc1, rScratch);
534 oatFreeTemp(cUnit, rScratch);
535 return res;
536 }
537}
538
539/* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
buzbee31a4a6f2012-02-28 15:36:15 -0800540LIR* opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700541{
542 bool neg = (value < 0);
543 int absValue = (neg) ? -value : value;
544 bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1));
545 ArmOpcode opcode = kThumbBkpt;
546 switch (op) {
547 case kOpAdd:
548 if ( !neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
buzbeeed3e9302011-09-23 17:34:19 -0700549 DCHECK_EQ((value & 0x3), 0);
buzbee67bf8852011-08-17 17:51:35 -0700550 return newLIR1(cUnit, kThumbAddSpI7, value >> 2);
551 } else if (shortForm) {
552 opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
553 }
554 break;
555 case kOpSub:
556 if (!neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
buzbeeed3e9302011-09-23 17:34:19 -0700557 DCHECK_EQ((value & 0x3), 0);
buzbee67bf8852011-08-17 17:51:35 -0700558 return newLIR1(cUnit, kThumbSubSpI7, value >> 2);
559 } else if (shortForm) {
560 opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
561 }
562 break;
563 case kOpCmp:
564 if (LOWREG(rDestSrc1) && shortForm)
565 opcode = (shortForm) ? kThumbCmpRI8 : kThumbCmpRR;
566 else if (LOWREG(rDestSrc1))
567 opcode = kThumbCmpRR;
568 else {
569 shortForm = false;
570 opcode = kThumbCmpHL;
571 }
572 break;
573 default:
574 /* Punt to opRegRegImm - if bad case catch it there */
575 shortForm = false;
576 break;
577 }
578 if (shortForm)
579 return newLIR2(cUnit, opcode, rDestSrc1, absValue);
580 else {
581 return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
582 }
583}
584
585/*
586 * Determine whether value can be encoded as a Thumb2 floating point
587 * immediate. If not, return -1. If so return encoded 8-bit value.
588 */
buzbee31a4a6f2012-02-28 15:36:15 -0800589int encodeImmDoubleHigh(int value)
buzbee67bf8852011-08-17 17:51:35 -0700590{
591 int res;
592 int bitA = (value & 0x80000000) >> 31;
593 int notBitB = (value & 0x40000000) >> 30;
594 int bitB = (value & 0x20000000) >> 29;
595 int bSmear = (value & 0x3fc00000) >> 22;
596 int slice = (value & 0x003f0000) >> 16;
597 int zeroes = (value & 0x0000ffff);
598 if (zeroes != 0)
599 return -1;
600 if (bitB) {
buzbee03fa2632011-09-20 17:10:57 -0700601 if ((notBitB != 0) || (bSmear != 0xff))
buzbee67bf8852011-08-17 17:51:35 -0700602 return -1;
603 } else {
604 if ((notBitB != 1) || (bSmear != 0x0))
605 return -1;
606 }
607 res = (bitA << 7) | (bitB << 6) | slice;
608 return res;
609}
610
buzbee31a4a6f2012-02-28 15:36:15 -0800611int encodeImmDouble(int valLo, int valHi)
buzbee67bf8852011-08-17 17:51:35 -0700612{
613 int res = -1;
614 if (valLo == 0)
615 res = encodeImmDoubleHigh(valHi);
616 return res;
617}
618
buzbee31a4a6f2012-02-28 15:36:15 -0800619LIR* loadConstantValueWide(CompilationUnit* cUnit, int rDestLo, int rDestHi,
620 int valLo, int valHi)
buzbee67bf8852011-08-17 17:51:35 -0700621{
622 int encodedImm = encodeImmDouble(valLo, valHi);
buzbee31a4a6f2012-02-28 15:36:15 -0800623 LIR* res;
buzbee03fa2632011-09-20 17:10:57 -0700624 if (FPREG(rDestLo)) {
625 if (encodedImm >= 0) {
626 res = newLIR2(cUnit, kThumb2Vmovd_IMM8, S2D(rDestLo, rDestHi),
627 encodedImm);
628 } else {
buzbee31a4a6f2012-02-28 15:36:15 -0800629 LIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo,
buzbee03fa2632011-09-20 17:10:57 -0700630 valHi);
631 if (dataTarget == NULL) {
632 dataTarget = addWideData(cUnit, &cUnit->literalList, valLo,
633 valHi);
634 }
buzbeea2ebdd72012-03-04 14:57:06 -0800635 LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
636 kThumb2Vldrd, S2D(rDestLo, rDestHi),
637 r15pc, 0, 0, dataTarget);
buzbee03fa2632011-09-20 17:10:57 -0700638 setMemRefType(loadPcRel, true, kLiteral);
buzbeebbaf8942011-10-02 13:08:29 -0700639 loadPcRel->aliasInfo = (intptr_t)dataTarget;
buzbee03fa2632011-09-20 17:10:57 -0700640 oatAppendLIR(cUnit, (LIR* ) loadPcRel);
641 res = loadPcRel;
642 }
buzbee67bf8852011-08-17 17:51:35 -0700643 } else {
644 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
645 loadConstantNoClobber(cUnit, rDestHi, valHi);
646 }
647 return res;
648}
649
buzbee31a4a6f2012-02-28 15:36:15 -0800650int encodeShift(int code, int amount) {
buzbee67bf8852011-08-17 17:51:35 -0700651 return ((amount & 0x1f) << 2) | code;
652}
653
buzbee31a4a6f2012-02-28 15:36:15 -0800654LIR* loadBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rDest,
655 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700656{
657 bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
buzbee31a4a6f2012-02-28 15:36:15 -0800658 LIR* load;
buzbee67bf8852011-08-17 17:51:35 -0700659 ArmOpcode opcode = kThumbBkpt;
660 bool thumbForm = (allLowRegs && (scale == 0));
661 int regPtr;
662
663 if (FPREG(rDest)) {
Ian Rogers513c64a2012-02-26 15:16:23 -0800664 if (SINGLEREG(rDest)) {
665 DCHECK((size == kWord) || (size == kSingle));
666 opcode = kThumb2Vldrs;
667 size = kSingle;
668 } else {
669 DCHECK(DOUBLEREG(rDest));
670 DCHECK((size == kLong) || (size == kDouble));
671 DCHECK((rDest & 0x1) == 0);
672 opcode = kThumb2Vldrd;
673 size = kDouble;
674 }
buzbee67bf8852011-08-17 17:51:35 -0700675 } else {
676 if (size == kSingle)
677 size = kWord;
678 }
679
680 switch (size) {
Ian Rogers513c64a2012-02-26 15:16:23 -0800681 case kDouble: // fall-through
buzbee67bf8852011-08-17 17:51:35 -0700682 case kSingle:
683 regPtr = oatAllocTemp(cUnit);
684 if (scale) {
685 newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
686 encodeShift(kArmLsl, scale));
687 } else {
688 opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
689 }
690 load = newLIR3(cUnit, opcode, rDest, regPtr, 0);
691 return load;
692 case kWord:
693 opcode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR;
694 break;
695 case kUnsignedHalf:
696 opcode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR;
697 break;
698 case kSignedHalf:
699 opcode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR;
700 break;
701 case kUnsignedByte:
702 opcode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR;
703 break;
704 case kSignedByte:
705 opcode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
706 break;
707 default:
buzbeeed3e9302011-09-23 17:34:19 -0700708 LOG(FATAL) << "Bad size: " << (int)size;
buzbee67bf8852011-08-17 17:51:35 -0700709 }
710 if (thumbForm)
711 load = newLIR3(cUnit, opcode, rDest, rBase, rIndex);
712 else
713 load = newLIR4(cUnit, opcode, rDest, rBase, rIndex, scale);
714
715 return load;
716}
717
buzbee31a4a6f2012-02-28 15:36:15 -0800718LIR* storeBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rSrc,
719 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700720{
721 bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
buzbee31a4a6f2012-02-28 15:36:15 -0800722 LIR* store;
buzbee67bf8852011-08-17 17:51:35 -0700723 ArmOpcode opcode = kThumbBkpt;
724 bool thumbForm = (allLowRegs && (scale == 0));
725 int regPtr;
726
727 if (FPREG(rSrc)) {
Ian Rogers513c64a2012-02-26 15:16:23 -0800728 if (SINGLEREG(rSrc)) {
729 DCHECK((size == kWord) || (size == kSingle));
730 opcode = kThumb2Vstrs;
731 size = kSingle;
732 } else {
733 DCHECK(DOUBLEREG(rSrc));
734 DCHECK((size == kLong) || (size == kDouble));
735 DCHECK((rSrc & 0x1) == 0);
736 opcode = kThumb2Vstrd;
737 size = kDouble;
738 }
buzbee67bf8852011-08-17 17:51:35 -0700739 } else {
740 if (size == kSingle)
741 size = kWord;
742 }
743
744 switch (size) {
Ian Rogers513c64a2012-02-26 15:16:23 -0800745 case kDouble: // fall-through
buzbee67bf8852011-08-17 17:51:35 -0700746 case kSingle:
747 regPtr = oatAllocTemp(cUnit);
748 if (scale) {
749 newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
750 encodeShift(kArmLsl, scale));
751 } else {
752 opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
753 }
754 store = newLIR3(cUnit, opcode, rSrc, regPtr, 0);
755 return store;
756 case kWord:
757 opcode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR;
758 break;
759 case kUnsignedHalf:
760 case kSignedHalf:
761 opcode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR;
762 break;
763 case kUnsignedByte:
764 case kSignedByte:
765 opcode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR;
766 break;
767 default:
buzbeeed3e9302011-09-23 17:34:19 -0700768 LOG(FATAL) << "Bad size: " << (int)size;
buzbee67bf8852011-08-17 17:51:35 -0700769 }
770 if (thumbForm)
771 store = newLIR3(cUnit, opcode, rSrc, rBase, rIndex);
772 else
773 store = newLIR4(cUnit, opcode, rSrc, rBase, rIndex, scale);
774
775 return store;
776}
777
778/*
779 * Load value from base + displacement. Optionally perform null check
780 * on base (which must have an associated sReg and MIR). If not
781 * performing null check, incoming MIR can be null.
782 */
buzbee31a4a6f2012-02-28 15:36:15 -0800783LIR* loadBaseDispBody(CompilationUnit* cUnit, MIR* mir, int rBase,
784 int displacement, int rDest, int rDestHi, OpSize size,
785 int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700786{
buzbee31a4a6f2012-02-28 15:36:15 -0800787 LIR* res;
788 LIR* load;
buzbee67bf8852011-08-17 17:51:35 -0700789 ArmOpcode opcode = kThumbBkpt;
790 bool shortForm = false;
791 bool thumb2Form = (displacement < 4092 && displacement >= 0);
792 bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest));
793 int encodedDisp = displacement;
794
795 switch (size) {
796 case kDouble:
797 case kLong:
798 if (FPREG(rDest)) {
799 if (SINGLEREG(rDest)) {
buzbeeed3e9302011-09-23 17:34:19 -0700800 DCHECK(FPREG(rDestHi));
buzbee67bf8852011-08-17 17:51:35 -0700801 rDest = S2D(rDest, rDestHi);
802 }
803 opcode = kThumb2Vldrd;
804 if (displacement <= 1020) {
805 shortForm = true;
806 encodedDisp >>= 2;
807 }
808 break;
809 } else {
810 res = loadBaseDispBody(cUnit, mir, rBase, displacement, rDest,
811 -1, kWord, sReg);
812 loadBaseDispBody(cUnit, NULL, rBase, displacement + 4, rDestHi,
813 -1, kWord, INVALID_SREG);
814 return res;
815 }
816 case kSingle:
817 case kWord:
818 if (FPREG(rDest)) {
819 opcode = kThumb2Vldrs;
820 if (displacement <= 1020) {
821 shortForm = true;
822 encodedDisp >>= 2;
823 }
824 break;
825 }
826 if (LOWREG(rDest) && (rBase == r15pc) &&
827 (displacement <= 1020) && (displacement >= 0)) {
828 shortForm = true;
829 encodedDisp >>= 2;
830 opcode = kThumbLdrPcRel;
831 } else if (LOWREG(rDest) && (rBase == r13sp) &&
832 (displacement <= 1020) && (displacement >= 0)) {
833 shortForm = true;
834 encodedDisp >>= 2;
835 opcode = kThumbLdrSpRel;
836 } else if (allLowRegs && displacement < 128 && displacement >= 0) {
buzbeeed3e9302011-09-23 17:34:19 -0700837 DCHECK_EQ((displacement & 0x3), 0);
buzbee67bf8852011-08-17 17:51:35 -0700838 shortForm = true;
839 encodedDisp >>= 2;
840 opcode = kThumbLdrRRI5;
841 } else if (thumb2Form) {
842 shortForm = true;
843 opcode = kThumb2LdrRRI12;
844 }
845 break;
846 case kUnsignedHalf:
847 if (allLowRegs && displacement < 64 && displacement >= 0) {
buzbeeed3e9302011-09-23 17:34:19 -0700848 DCHECK_EQ((displacement & 0x1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700849 shortForm = true;
850 encodedDisp >>= 1;
851 opcode = kThumbLdrhRRI5;
852 } else if (displacement < 4092 && displacement >= 0) {
853 shortForm = true;
854 opcode = kThumb2LdrhRRI12;
855 }
856 break;
857 case kSignedHalf:
858 if (thumb2Form) {
859 shortForm = true;
860 opcode = kThumb2LdrshRRI12;
861 }
862 break;
863 case kUnsignedByte:
864 if (allLowRegs && displacement < 32 && displacement >= 0) {
865 shortForm = true;
866 opcode = kThumbLdrbRRI5;
867 } else if (thumb2Form) {
868 shortForm = true;
869 opcode = kThumb2LdrbRRI12;
870 }
871 break;
872 case kSignedByte:
873 if (thumb2Form) {
874 shortForm = true;
875 opcode = kThumb2LdrsbRRI12;
876 }
877 break;
878 default:
buzbeeed3e9302011-09-23 17:34:19 -0700879 LOG(FATAL) << "Bad size: " << (int)size;
buzbee67bf8852011-08-17 17:51:35 -0700880 }
881
882 if (shortForm) {
883 load = res = newLIR3(cUnit, opcode, rDest, rBase, encodedDisp);
884 } else {
885 int regOffset = oatAllocTemp(cUnit);
886 res = loadConstant(cUnit, regOffset, encodedDisp);
887 load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size);
888 oatFreeTemp(cUnit, regOffset);
889 }
890
891 // TODO: in future may need to differentiate Dalvik accesses w/ spills
892 if (rBase == rSP) {
893 annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */);
894 }
895 return load;
896}
897
buzbee31a4a6f2012-02-28 15:36:15 -0800898LIR* loadBaseDisp(CompilationUnit* cUnit, MIR* mir, int rBase,
899 int displacement, int rDest, OpSize size, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700900{
901 return loadBaseDispBody(cUnit, mir, rBase, displacement, rDest, -1,
902 size, sReg);
903}
904
buzbee31a4a6f2012-02-28 15:36:15 -0800905 LIR* loadBaseDispWide(CompilationUnit* cUnit, MIR* mir, int rBase,
906 int displacement, int rDestLo, int rDestHi, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700907{
908 return loadBaseDispBody(cUnit, mir, rBase, displacement, rDestLo, rDestHi,
909 kLong, sReg);
910}
911
912
buzbee31a4a6f2012-02-28 15:36:15 -0800913LIR* storeBaseDispBody(CompilationUnit* cUnit, int rBase, int displacement,
914 int rSrc, int rSrcHi, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700915{
buzbee31a4a6f2012-02-28 15:36:15 -0800916 LIR* res, *store;
buzbee67bf8852011-08-17 17:51:35 -0700917 ArmOpcode opcode = kThumbBkpt;
918 bool shortForm = false;
919 bool thumb2Form = (displacement < 4092 && displacement >= 0);
920 bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc));
921 int encodedDisp = displacement;
922
923 switch (size) {
924 case kLong:
925 case kDouble:
926 if (!FPREG(rSrc)) {
927 res = storeBaseDispBody(cUnit, rBase, displacement, rSrc,
928 -1, kWord);
929 storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi,
930 -1, kWord);
931 return res;
932 }
933 if (SINGLEREG(rSrc)) {
buzbeeed3e9302011-09-23 17:34:19 -0700934 DCHECK(FPREG(rSrcHi));
buzbee67bf8852011-08-17 17:51:35 -0700935 rSrc = S2D(rSrc, rSrcHi);
936 }
937 opcode = kThumb2Vstrd;
938 if (displacement <= 1020) {
939 shortForm = true;
940 encodedDisp >>= 2;
941 }
942 break;
943 case kSingle:
944 case kWord:
945 if (FPREG(rSrc)) {
buzbeeed3e9302011-09-23 17:34:19 -0700946 DCHECK(SINGLEREG(rSrc));
buzbee67bf8852011-08-17 17:51:35 -0700947 opcode = kThumb2Vstrs;
948 if (displacement <= 1020) {
949 shortForm = true;
950 encodedDisp >>= 2;
951 }
952 break;
953 }
954 if (allLowRegs && displacement < 128 && displacement >= 0) {
buzbeeed3e9302011-09-23 17:34:19 -0700955 DCHECK_EQ((displacement & 0x3), 0);
buzbee67bf8852011-08-17 17:51:35 -0700956 shortForm = true;
957 encodedDisp >>= 2;
958 opcode = kThumbStrRRI5;
959 } else if (thumb2Form) {
960 shortForm = true;
961 opcode = kThumb2StrRRI12;
962 }
963 break;
964 case kUnsignedHalf:
965 case kSignedHalf:
966 if (allLowRegs && displacement < 64 && displacement >= 0) {
buzbeeed3e9302011-09-23 17:34:19 -0700967 DCHECK_EQ((displacement & 0x1), 0);
buzbee67bf8852011-08-17 17:51:35 -0700968 shortForm = true;
969 encodedDisp >>= 1;
970 opcode = kThumbStrhRRI5;
971 } else if (thumb2Form) {
972 shortForm = true;
973 opcode = kThumb2StrhRRI12;
974 }
975 break;
976 case kUnsignedByte:
977 case kSignedByte:
978 if (allLowRegs && displacement < 32 && displacement >= 0) {
979 shortForm = true;
980 opcode = kThumbStrbRRI5;
981 } else if (thumb2Form) {
982 shortForm = true;
983 opcode = kThumb2StrbRRI12;
984 }
985 break;
986 default:
buzbeeed3e9302011-09-23 17:34:19 -0700987 LOG(FATAL) << "Bad size: " << (int)size;
buzbee67bf8852011-08-17 17:51:35 -0700988 }
989 if (shortForm) {
990 store = res = newLIR3(cUnit, opcode, rSrc, rBase, encodedDisp);
991 } else {
992 int rScratch = oatAllocTemp(cUnit);
993 res = loadConstant(cUnit, rScratch, encodedDisp);
994 store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
995 oatFreeTemp(cUnit, rScratch);
996 }
997
998 // TODO: In future, may need to differentiate Dalvik & spill accesses
999 if (rBase == rSP) {
1000 annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */);
1001 }
1002 return res;
1003}
1004
buzbee31a4a6f2012-02-28 15:36:15 -08001005LIR* storeBaseDisp(CompilationUnit* cUnit, int rBase, int displacement,
1006 int rSrc, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -07001007{
1008 return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
1009}
1010
buzbee31a4a6f2012-02-28 15:36:15 -08001011LIR* storeBaseDispWide(CompilationUnit* cUnit, int rBase, int displacement,
1012 int rSrcLo, int rSrcHi)
buzbee67bf8852011-08-17 17:51:35 -07001013{
1014 return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
1015}
1016
buzbee31a4a6f2012-02-28 15:36:15 -08001017void storePair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
buzbee67bf8852011-08-17 17:51:35 -07001018{
1019 storeBaseDispWide(cUnit, base, 0, lowReg, highReg);
1020}
1021
buzbee31a4a6f2012-02-28 15:36:15 -08001022void loadPair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
buzbee67bf8852011-08-17 17:51:35 -07001023{
1024 loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG);
1025}
1026
buzbee31a4a6f2012-02-28 15:36:15 -08001027LIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
buzbee67bf8852011-08-17 17:51:35 -07001028{
buzbeea2ebdd72012-03-04 14:57:06 -08001029 int opcode;
1030 DCHECK_EQ(DOUBLEREG(rDest), DOUBLEREG(rSrc));
1031 if (DOUBLEREG(rDest)) {
1032 opcode = kThumb2Vmovd;
1033 } else {
1034 if (SINGLEREG(rDest)) {
1035 opcode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr;
1036 } else {
1037 DCHECK(SINGLEREG(rSrc));
1038 opcode = kThumb2Fmrs;
1039 }
1040 }
1041 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
buzbee67bf8852011-08-17 17:51:35 -07001042 if (rDest == rSrc) {
1043 res->flags.isNop = true;
buzbee67bf8852011-08-17 17:51:35 -07001044 }
buzbee67bf8852011-08-17 17:51:35 -07001045 return res;
1046}
1047
buzbee67bf8852011-08-17 17:51:35 -07001048
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001049
1050} // namespace art