blob: 1873c2aa37a288de36164a3a2ac75fe99f24a84b [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
buzbee31a4a6f2012-02-28 15:36:15 -080021int encodeImmSingle(int value)
buzbee67bf8852011-08-17 17:51:35 -070022{
Bill Buzbeea114add2012-05-03 15:00:40 -070023 int res;
24 int bitA = (value & 0x80000000) >> 31;
25 int notBitB = (value & 0x40000000) >> 30;
26 int bitB = (value & 0x20000000) >> 29;
27 int bSmear = (value & 0x3e000000) >> 25;
28 int slice = (value & 0x01f80000) >> 19;
29 int zeroes = (value & 0x0007ffff);
30 if (zeroes != 0)
31 return -1;
32 if (bitB) {
33 if ((notBitB != 0) || (bSmear != 0x1f))
34 return -1;
35 } else {
36 if ((notBitB != 1) || (bSmear != 0x0))
37 return -1;
38 }
39 res = (bitA << 7) | (bitB << 6) | slice;
40 return res;
buzbee67bf8852011-08-17 17:51:35 -070041}
42
buzbee31a4a6f2012-02-28 15:36:15 -080043LIR* loadFPConstantValue(CompilationUnit* cUnit, int rDest, int value)
buzbee67bf8852011-08-17 17:51:35 -070044{
Bill Buzbeea114add2012-05-03 15:00:40 -070045 int encodedImm = encodeImmSingle(value);
buzbeef0504cd2012-11-13 16:31:10 -080046 DCHECK(ARM_SINGLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -070047 if (encodedImm >= 0) {
48 return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
49 }
50 LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
51 if (dataTarget == NULL) {
52 dataTarget = addWordData(cUnit, &cUnit->literalList, value);
53 }
54 LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrs,
55 rDest, r15pc, 0, 0, 0, dataTarget);
56 setMemRefType(loadPcRel, true, kLiteral);
buzbeecbd6d442012-11-17 14:11:25 -080057 loadPcRel->aliasInfo = reinterpret_cast<uintptr_t>(dataTarget);
58 oatAppendLIR(cUnit, loadPcRel);
Bill Buzbeea114add2012-05-03 15:00:40 -070059 return loadPcRel;
buzbee67bf8852011-08-17 17:51:35 -070060}
61
buzbeeeaf09bc2012-11-15 14:51:41 -080062int leadingZeros(uint32_t val)
buzbee67bf8852011-08-17 17:51:35 -070063{
buzbeeeaf09bc2012-11-15 14:51:41 -080064 uint32_t alt;
Bill Buzbeea114add2012-05-03 15:00:40 -070065 int n;
66 int count;
buzbee67bf8852011-08-17 17:51:35 -070067
Bill Buzbeea114add2012-05-03 15:00:40 -070068 count = 16;
69 n = 32;
70 do {
71 alt = val >> count;
72 if (alt != 0) {
73 n = n - count;
74 val = alt;
75 }
76 count >>= 1;
77 } while (count);
78 return n - val;
buzbee67bf8852011-08-17 17:51:35 -070079}
80
81/*
82 * Determine whether value can be encoded as a Thumb2 modified
83 * immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form.
84 */
buzbeeeaf09bc2012-11-15 14:51:41 -080085int modifiedImmediate(uint32_t value)
buzbee67bf8852011-08-17 17:51:35 -070086{
87 int zLeading;
88 int zTrailing;
buzbeeeaf09bc2012-11-15 14:51:41 -080089 uint32_t b0 = value & 0xff;
buzbee67bf8852011-08-17 17:51:35 -070090
91 /* Note: case of value==0 must use 0:000:0:0000000 encoding */
92 if (value <= 0xFF)
Bill Buzbeea114add2012-05-03 15:00:40 -070093 return b0; // 0:000:a:bcdefgh
buzbee67bf8852011-08-17 17:51:35 -070094 if (value == ((b0 << 16) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -070095 return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -070096 if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -070097 return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -070098 b0 = (value >> 8) & 0xff;
99 if (value == ((b0 << 24) | (b0 << 8)))
Bill Buzbeea114add2012-05-03 15:00:40 -0700100 return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700101 /* Can we do it with rotation? */
102 zLeading = leadingZeros(value);
103 zTrailing = 32 - leadingZeros(~value & (value - 1));
104 /* A run of eight or fewer active bits? */
105 if ((zLeading + zTrailing) < 24)
Bill Buzbeea114add2012-05-03 15:00:40 -0700106 return -1; /* No - bail */
buzbee67bf8852011-08-17 17:51:35 -0700107 /* left-justify the constant, discarding msb (known to be 1) */
108 value <<= zLeading + 1;
109 /* Create bcdefgh */
110 value >>= 25;
111 /* Put it all together */
112 return value | ((0x8 + zLeading) << 7); /* [01000..11111]:bcdefgh */
113}
114
115/*
116 * Load a immediate using a shortcut if possible; otherwise
117 * grab from the per-translation literal pool.
118 *
119 * No additional register clobbering operation performed. Use this version when
120 * 1) rDest is freshly returned from oatAllocTemp or
121 * 2) The codegen is under fixed register usage
122 */
buzbee31a4a6f2012-02-28 15:36:15 -0800123LIR* loadConstantNoClobber(CompilationUnit* cUnit, int rDest, int value)
buzbee67bf8852011-08-17 17:51:35 -0700124{
Bill Buzbeea114add2012-05-03 15:00:40 -0700125 LIR* res;
126 int modImm;
buzbee67bf8852011-08-17 17:51:35 -0700127
buzbeef0504cd2012-11-13 16:31:10 -0800128 if (ARM_FPREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700129 return loadFPConstantValue(cUnit, rDest, value);
130 }
buzbee67bf8852011-08-17 17:51:35 -0700131
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 /* See if the value can be constructed cheaply */
buzbeef0504cd2012-11-13 16:31:10 -0800133 if (ARM_LOWREG(rDest) && (value >= 0) && (value <= 255)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700134 return newLIR2(cUnit, kThumbMovImm, rDest, value);
135 }
136 /* Check Modified immediate special cases */
137 modImm = modifiedImmediate(value);
138 if (modImm >= 0) {
139 res = newLIR2(cUnit, kThumb2MovImmShift, rDest, modImm);
buzbee67bf8852011-08-17 17:51:35 -0700140 return res;
Bill Buzbeea114add2012-05-03 15:00:40 -0700141 }
142 modImm = modifiedImmediate(~value);
143 if (modImm >= 0) {
144 res = newLIR2(cUnit, kThumb2MvnImm12, rDest, modImm);
145 return res;
146 }
147 /* 16-bit immediate? */
148 if ((value & 0xffff) == value) {
149 res = newLIR2(cUnit, kThumb2MovImm16, rDest, value);
150 return res;
151 }
152 /* No shortcut - go ahead and use literal pool */
153 LIR* dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
154 if (dataTarget == NULL) {
155 dataTarget = addWordData(cUnit, &cUnit->literalList, value);
156 }
157 LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset,
158 kThumb2LdrPcRel12, rDest, 0, 0, 0, 0, dataTarget);
159 setMemRefType(loadPcRel, true, kLiteral);
buzbeecbd6d442012-11-17 14:11:25 -0800160 loadPcRel->aliasInfo = reinterpret_cast<uintptr_t>(dataTarget);
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 res = loadPcRel;
buzbeecbd6d442012-11-17 14:11:25 -0800162 oatAppendLIR(cUnit, loadPcRel);
Bill Buzbeea114add2012-05-03 15:00:40 -0700163
164 /*
165 * To save space in the constant pool, we use the ADD_RRI8 instruction to
166 * add up to 255 to an existing constant value.
167 */
168 if (dataTarget->operands[0] != value) {
169 opRegImm(cUnit, kOpAdd, rDest, value - dataTarget->operands[0]);
170 }
171 return res;
buzbee67bf8852011-08-17 17:51:35 -0700172}
173
Ian Rogers680b1bd2012-03-07 20:18:49 -0800174LIR* opBranchUnconditional(CompilationUnit* cUnit, OpKind op)
buzbee67bf8852011-08-17 17:51:35 -0700175{
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 DCHECK_EQ(op, kOpUncondBr);
177 return newLIR1(cUnit, kThumbBUncond, 0 /* offset to be patched */);
buzbee67bf8852011-08-17 17:51:35 -0700178}
179
buzbee82488f52012-03-02 08:20:26 -0800180LIR* opCondBranch(CompilationUnit* cUnit, ConditionCode cc, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700181{
Bill Buzbeea114add2012-05-03 15:00:40 -0700182 LIR* branch = newLIR2(cUnit, kThumb2BCond, 0 /* offset to be patched */,
183 oatArmConditionEncoding(cc));
184 branch->target = target;
185 return branch;
buzbee67bf8852011-08-17 17:51:35 -0700186}
187
buzbee31a4a6f2012-02-28 15:36:15 -0800188LIR* opReg(CompilationUnit* cUnit, OpKind op, int rDestSrc)
buzbee67bf8852011-08-17 17:51:35 -0700189{
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 ArmOpcode opcode = kThumbBkpt;
191 switch (op) {
192 case kOpBlx:
193 opcode = kThumbBlxR;
194 break;
195 default:
buzbeecbd6d442012-11-17 14:11:25 -0800196 LOG(FATAL) << "Bad opcode " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700197 }
198 return newLIR1(cUnit, opcode, rDestSrc);
buzbee67bf8852011-08-17 17:51:35 -0700199}
200
buzbee31a4a6f2012-02-28 15:36:15 -0800201LIR* opRegRegShift(CompilationUnit* cUnit, OpKind op, int rDestSrc1,
202 int rSrc2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700203{
buzbeef0504cd2012-11-13 16:31:10 -0800204 bool thumbForm = ((shift == 0) && ARM_LOWREG(rDestSrc1) && ARM_LOWREG(rSrc2));
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 ArmOpcode opcode = kThumbBkpt;
206 switch (op) {
207 case kOpAdc:
208 opcode = (thumbForm) ? kThumbAdcRR : kThumb2AdcRRR;
209 break;
210 case kOpAnd:
211 opcode = (thumbForm) ? kThumbAndRR : kThumb2AndRRR;
212 break;
213 case kOpBic:
214 opcode = (thumbForm) ? kThumbBicRR : kThumb2BicRRR;
215 break;
216 case kOpCmn:
217 DCHECK_EQ(shift, 0);
218 opcode = (thumbForm) ? kThumbCmnRR : kThumb2CmnRR;
219 break;
220 case kOpCmp:
221 if (thumbForm)
222 opcode = kThumbCmpRR;
buzbeef0504cd2012-11-13 16:31:10 -0800223 else if ((shift == 0) && !ARM_LOWREG(rDestSrc1) && !ARM_LOWREG(rSrc2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 opcode = kThumbCmpHH;
buzbeef0504cd2012-11-13 16:31:10 -0800225 else if ((shift == 0) && ARM_LOWREG(rDestSrc1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700226 opcode = kThumbCmpLH;
227 else if (shift == 0)
228 opcode = kThumbCmpHL;
229 else
230 opcode = kThumb2CmpRR;
231 break;
232 case kOpXor:
233 opcode = (thumbForm) ? kThumbEorRR : kThumb2EorRRR;
234 break;
235 case kOpMov:
236 DCHECK_EQ(shift, 0);
buzbeef0504cd2012-11-13 16:31:10 -0800237 if (ARM_LOWREG(rDestSrc1) && ARM_LOWREG(rSrc2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 opcode = kThumbMovRR;
buzbeef0504cd2012-11-13 16:31:10 -0800239 else if (!ARM_LOWREG(rDestSrc1) && !ARM_LOWREG(rSrc2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 opcode = kThumbMovRR_H2H;
buzbeef0504cd2012-11-13 16:31:10 -0800241 else if (ARM_LOWREG(rDestSrc1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700242 opcode = kThumbMovRR_H2L;
243 else
244 opcode = kThumbMovRR_L2H;
245 break;
246 case kOpMul:
247 DCHECK_EQ(shift, 0);
248 opcode = (thumbForm) ? kThumbMul : kThumb2MulRRR;
249 break;
250 case kOpMvn:
251 opcode = (thumbForm) ? kThumbMvn : kThumb2MnvRR;
252 break;
253 case kOpNeg:
254 DCHECK_EQ(shift, 0);
255 opcode = (thumbForm) ? kThumbNeg : kThumb2NegRR;
256 break;
257 case kOpOr:
258 opcode = (thumbForm) ? kThumbOrr : kThumb2OrrRRR;
259 break;
260 case kOpSbc:
261 opcode = (thumbForm) ? kThumbSbc : kThumb2SbcRRR;
262 break;
263 case kOpTst:
264 opcode = (thumbForm) ? kThumbTst : kThumb2TstRR;
265 break;
266 case kOpLsl:
267 DCHECK_EQ(shift, 0);
268 opcode = (thumbForm) ? kThumbLslRR : kThumb2LslRRR;
269 break;
270 case kOpLsr:
271 DCHECK_EQ(shift, 0);
272 opcode = (thumbForm) ? kThumbLsrRR : kThumb2LsrRRR;
273 break;
274 case kOpAsr:
275 DCHECK_EQ(shift, 0);
276 opcode = (thumbForm) ? kThumbAsrRR : kThumb2AsrRRR;
277 break;
278 case kOpRor:
279 DCHECK_EQ(shift, 0);
280 opcode = (thumbForm) ? kThumbRorRR : kThumb2RorRRR;
281 break;
282 case kOpAdd:
283 opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
284 break;
285 case kOpSub:
286 opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
287 break;
288 case kOp2Byte:
289 DCHECK_EQ(shift, 0);
290 return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 8);
291 case kOp2Short:
292 DCHECK_EQ(shift, 0);
293 return newLIR4(cUnit, kThumb2Sbfx, rDestSrc1, rSrc2, 0, 16);
294 case kOp2Char:
295 DCHECK_EQ(shift, 0);
296 return newLIR4(cUnit, kThumb2Ubfx, rDestSrc1, rSrc2, 0, 16);
297 default:
buzbeecbd6d442012-11-17 14:11:25 -0800298 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700299 break;
300 }
301 DCHECK_GE(static_cast<int>(opcode), 0);
302 if (EncodingMap[opcode].flags & IS_BINARY_OP)
303 return newLIR2(cUnit, opcode, rDestSrc1, rSrc2);
304 else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
305 if (EncodingMap[opcode].fieldLoc[2].kind == kFmtShift)
306 return newLIR3(cUnit, opcode, rDestSrc1, rSrc2, shift);
307 else
308 return newLIR3(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2);
309 } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
310 return newLIR4(cUnit, opcode, rDestSrc1, rDestSrc1, rSrc2, shift);
311 else {
312 LOG(FATAL) << "Unexpected encoding operand count";
313 return NULL;
314 }
buzbee67bf8852011-08-17 17:51:35 -0700315}
316
buzbee31a4a6f2012-02-28 15:36:15 -0800317LIR* opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2)
buzbee67bf8852011-08-17 17:51:35 -0700318{
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700320}
321
buzbee31a4a6f2012-02-28 15:36:15 -0800322LIR* opRegRegRegShift(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
Bill Buzbeea114add2012-05-03 15:00:40 -0700323 int rSrc2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700324{
Bill Buzbeea114add2012-05-03 15:00:40 -0700325 ArmOpcode opcode = kThumbBkpt;
buzbeef0504cd2012-11-13 16:31:10 -0800326 bool thumbForm = (shift == 0) && ARM_LOWREG(rDest) && ARM_LOWREG(rSrc1) &&
327 ARM_LOWREG(rSrc2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700328 switch (op) {
329 case kOpAdd:
330 opcode = (thumbForm) ? kThumbAddRRR : kThumb2AddRRR;
331 break;
332 case kOpSub:
333 opcode = (thumbForm) ? kThumbSubRRR : kThumb2SubRRR;
334 break;
335 case kOpRsub:
336 opcode = kThumb2RsubRRR;
337 break;
338 case kOpAdc:
339 opcode = kThumb2AdcRRR;
340 break;
341 case kOpAnd:
342 opcode = kThumb2AndRRR;
343 break;
344 case kOpBic:
345 opcode = kThumb2BicRRR;
346 break;
347 case kOpXor:
348 opcode = kThumb2EorRRR;
349 break;
350 case kOpMul:
351 DCHECK_EQ(shift, 0);
352 opcode = kThumb2MulRRR;
353 break;
354 case kOpOr:
355 opcode = kThumb2OrrRRR;
356 break;
357 case kOpSbc:
358 opcode = kThumb2SbcRRR;
359 break;
360 case kOpLsl:
361 DCHECK_EQ(shift, 0);
362 opcode = kThumb2LslRRR;
363 break;
364 case kOpLsr:
365 DCHECK_EQ(shift, 0);
366 opcode = kThumb2LsrRRR;
367 break;
368 case kOpAsr:
369 DCHECK_EQ(shift, 0);
370 opcode = kThumb2AsrRRR;
371 break;
372 case kOpRor:
373 DCHECK_EQ(shift, 0);
374 opcode = kThumb2RorRRR;
375 break;
376 default:
buzbeecbd6d442012-11-17 14:11:25 -0800377 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 break;
379 }
380 DCHECK_GE(static_cast<int>(opcode), 0);
381 if (EncodingMap[opcode].flags & IS_QUAD_OP)
382 return newLIR4(cUnit, opcode, rDest, rSrc1, rSrc2, shift);
383 else {
384 DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
385 return newLIR3(cUnit, opcode, rDest, rSrc1, rSrc2);
386 }
buzbee67bf8852011-08-17 17:51:35 -0700387}
388
buzbee31a4a6f2012-02-28 15:36:15 -0800389LIR* opRegRegReg(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
390 int rSrc2)
buzbee67bf8852011-08-17 17:51:35 -0700391{
Bill Buzbeea114add2012-05-03 15:00:40 -0700392 return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700393}
394
buzbee31a4a6f2012-02-28 15:36:15 -0800395LIR* opRegRegImm(CompilationUnit* cUnit, OpKind op, int rDest, int rSrc1,
396 int value)
buzbee67bf8852011-08-17 17:51:35 -0700397{
Bill Buzbeea114add2012-05-03 15:00:40 -0700398 LIR* res;
399 bool neg = (value < 0);
400 int absValue = (neg) ? -value : value;
401 ArmOpcode opcode = kThumbBkpt;
402 ArmOpcode altOpcode = kThumbBkpt;
buzbeef0504cd2012-11-13 16:31:10 -0800403 bool allLowRegs = (ARM_LOWREG(rDest) && ARM_LOWREG(rSrc1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700404 int modImm = modifiedImmediate(value);
405 int modImmNeg = modifiedImmediate(-value);
buzbee67bf8852011-08-17 17:51:35 -0700406
Bill Buzbeea114add2012-05-03 15:00:40 -0700407 switch (op) {
408 case kOpLsl:
409 if (allLowRegs)
410 return newLIR3(cUnit, kThumbLslRRI5, rDest, rSrc1, value);
411 else
412 return newLIR3(cUnit, kThumb2LslRRI5, rDest, rSrc1, value);
413 case kOpLsr:
414 if (allLowRegs)
415 return newLIR3(cUnit, kThumbLsrRRI5, rDest, rSrc1, value);
416 else
417 return newLIR3(cUnit, kThumb2LsrRRI5, rDest, rSrc1, value);
418 case kOpAsr:
419 if (allLowRegs)
420 return newLIR3(cUnit, kThumbAsrRRI5, rDest, rSrc1, value);
421 else
422 return newLIR3(cUnit, kThumb2AsrRRI5, rDest, rSrc1, value);
423 case kOpRor:
424 return newLIR3(cUnit, kThumb2RorRRI5, rDest, rSrc1, value);
425 case kOpAdd:
buzbeef0504cd2012-11-13 16:31:10 -0800426 if (ARM_LOWREG(rDest) && (rSrc1 == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 (value <= 1020) && ((value & 0x3)==0)) {
428 return newLIR3(cUnit, kThumbAddSpRel, rDest, rSrc1, value >> 2);
buzbeef0504cd2012-11-13 16:31:10 -0800429 } else if (ARM_LOWREG(rDest) && (rSrc1 == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 (value <= 1020) && ((value & 0x3)==0)) {
431 return newLIR3(cUnit, kThumbAddPcRel, rDest, rSrc1, value >> 2);
432 }
433 // Note: intentional fallthrough
434 case kOpSub:
435 if (allLowRegs && ((absValue & 0x7) == absValue)) {
436 if (op == kOpAdd)
437 opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
buzbee67bf8852011-08-17 17:51:35 -0700438 else
Bill Buzbeea114add2012-05-03 15:00:40 -0700439 opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
440 return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
441 } else if ((absValue & 0xff) == absValue) {
442 if (op == kOpAdd)
443 opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
444 else
445 opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
446 return newLIR3(cUnit, opcode, rDest, rSrc1, absValue);
447 }
448 if (modImmNeg >= 0) {
449 op = (op == kOpAdd) ? kOpSub : kOpAdd;
450 modImm = modImmNeg;
451 }
452 if (op == kOpSub) {
453 opcode = kThumb2SubRRI8;
454 altOpcode = kThumb2SubRRR;
455 } else {
456 opcode = kThumb2AddRRI8;
457 altOpcode = kThumb2AddRRR;
458 }
459 break;
460 case kOpAdc:
461 opcode = kThumb2AdcRRI8;
462 altOpcode = kThumb2AdcRRR;
463 break;
464 case kOpSbc:
465 opcode = kThumb2SbcRRI8;
466 altOpcode = kThumb2SbcRRR;
467 break;
468 case kOpOr:
469 opcode = kThumb2OrrRRI8;
470 altOpcode = kThumb2OrrRRR;
471 break;
472 case kOpAnd:
473 opcode = kThumb2AndRRI8;
474 altOpcode = kThumb2AndRRR;
475 break;
476 case kOpXor:
477 opcode = kThumb2EorRRI8;
478 altOpcode = kThumb2EorRRR;
479 break;
480 case kOpMul:
481 //TUNING: power of 2, shift & add
482 modImm = -1;
483 altOpcode = kThumb2MulRRR;
484 break;
485 case kOpCmp: {
486 int modImm = modifiedImmediate(value);
487 LIR* res;
488 if (modImm >= 0) {
489 res = newLIR2(cUnit, kThumb2CmpRI8, rSrc1, modImm);
490 } else {
491 int rTmp = oatAllocTemp(cUnit);
492 res = loadConstant(cUnit, rTmp, value);
493 opRegReg(cUnit, kOpCmp, rSrc1, rTmp);
494 oatFreeTemp(cUnit, rTmp);
495 }
496 return res;
buzbee67bf8852011-08-17 17:51:35 -0700497 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 default:
buzbeecbd6d442012-11-17 14:11:25 -0800499 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 }
501
502 if (modImm >= 0) {
503 return newLIR3(cUnit, opcode, rDest, rSrc1, modImm);
504 } else {
505 int rScratch = oatAllocTemp(cUnit);
506 loadConstant(cUnit, rScratch, value);
507 if (EncodingMap[altOpcode].flags & IS_QUAD_OP)
508 res = newLIR4(cUnit, altOpcode, rDest, rSrc1, rScratch, 0);
509 else
510 res = newLIR3(cUnit, altOpcode, rDest, rSrc1, rScratch);
511 oatFreeTemp(cUnit, rScratch);
512 return res;
513 }
buzbee67bf8852011-08-17 17:51:35 -0700514}
515
516/* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
buzbee31a4a6f2012-02-28 15:36:15 -0800517LIR* opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700518{
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 bool neg = (value < 0);
520 int absValue = (neg) ? -value : value;
buzbeef0504cd2012-11-13 16:31:10 -0800521 bool shortForm = (((absValue & 0xff) == absValue) && ARM_LOWREG(rDestSrc1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 ArmOpcode opcode = kThumbBkpt;
523 switch (op) {
524 case kOpAdd:
525 if ( !neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
526 DCHECK_EQ((value & 0x3), 0);
527 return newLIR1(cUnit, kThumbAddSpI7, value >> 2);
528 } else if (shortForm) {
529 opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
530 }
531 break;
532 case kOpSub:
533 if (!neg && (rDestSrc1 == r13sp) && (value <= 508)) { /* sp */
534 DCHECK_EQ((value & 0x3), 0);
535 return newLIR1(cUnit, kThumbSubSpI7, value >> 2);
536 } else if (shortForm) {
537 opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
538 }
539 break;
540 case kOpCmp:
buzbeef0504cd2012-11-13 16:31:10 -0800541 if (ARM_LOWREG(rDestSrc1) && shortForm)
Bill Buzbeea114add2012-05-03 15:00:40 -0700542 opcode = (shortForm) ? kThumbCmpRI8 : kThumbCmpRR;
buzbeef0504cd2012-11-13 16:31:10 -0800543 else if (ARM_LOWREG(rDestSrc1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 opcode = kThumbCmpRR;
545 else {
546 shortForm = false;
547 opcode = kThumbCmpHL;
548 }
549 break;
550 default:
551 /* Punt to opRegRegImm - if bad case catch it there */
552 shortForm = false;
553 break;
554 }
555 if (shortForm)
556 return newLIR2(cUnit, opcode, rDestSrc1, absValue);
557 else {
558 return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value);
559 }
buzbee67bf8852011-08-17 17:51:35 -0700560}
561
562/*
563 * Determine whether value can be encoded as a Thumb2 floating point
564 * immediate. If not, return -1. If so return encoded 8-bit value.
565 */
buzbee31a4a6f2012-02-28 15:36:15 -0800566int encodeImmDoubleHigh(int value)
buzbee67bf8852011-08-17 17:51:35 -0700567{
Bill Buzbeea114add2012-05-03 15:00:40 -0700568 int res;
569 int bitA = (value & 0x80000000) >> 31;
570 int notBitB = (value & 0x40000000) >> 30;
571 int bitB = (value & 0x20000000) >> 29;
572 int bSmear = (value & 0x3fc00000) >> 22;
573 int slice = (value & 0x003f0000) >> 16;
574 int zeroes = (value & 0x0000ffff);
575 if (zeroes != 0)
576 return -1;
577 if (bitB) {
578 if ((notBitB != 0) || (bSmear != 0xff))
579 return -1;
580 } else {
581 if ((notBitB != 1) || (bSmear != 0x0))
582 return -1;
583 }
584 res = (bitA << 7) | (bitB << 6) | slice;
585 return res;
buzbee67bf8852011-08-17 17:51:35 -0700586}
587
buzbee31a4a6f2012-02-28 15:36:15 -0800588int encodeImmDouble(int valLo, int valHi)
buzbee67bf8852011-08-17 17:51:35 -0700589{
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 int res = -1;
591 if (valLo == 0)
592 res = encodeImmDoubleHigh(valHi);
593 return res;
buzbee67bf8852011-08-17 17:51:35 -0700594}
595
buzbee31a4a6f2012-02-28 15:36:15 -0800596LIR* loadConstantValueWide(CompilationUnit* cUnit, int rDestLo, int rDestHi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700597 int valLo, int valHi)
buzbee67bf8852011-08-17 17:51:35 -0700598{
Bill Buzbeea114add2012-05-03 15:00:40 -0700599 int encodedImm = encodeImmDouble(valLo, valHi);
600 LIR* res;
buzbeef0504cd2012-11-13 16:31:10 -0800601 if (ARM_FPREG(rDestLo)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700602 if (encodedImm >= 0) {
buzbeef0504cd2012-11-13 16:31:10 -0800603 res = newLIR2(cUnit, kThumb2Vmovd_IMM8, s2d(rDestLo, rDestHi),
Bill Buzbeea114add2012-05-03 15:00:40 -0700604 encodedImm);
buzbee67bf8852011-08-17 17:51:35 -0700605 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 LIR* dataTarget = scanLiteralPoolWide(cUnit->literalList, valLo, valHi);
607 if (dataTarget == NULL) {
608 dataTarget = addWideData(cUnit, &cUnit->literalList, valLo, valHi);
609 }
610 LIR* loadPcRel =
611 rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrd,
buzbeef0504cd2012-11-13 16:31:10 -0800612 s2d(rDestLo, rDestHi), r15pc, 0, 0, 0, dataTarget);
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 setMemRefType(loadPcRel, true, kLiteral);
buzbeecbd6d442012-11-17 14:11:25 -0800614 loadPcRel->aliasInfo = reinterpret_cast<uintptr_t>(dataTarget);
615 oatAppendLIR(cUnit, loadPcRel);
Bill Buzbeea114add2012-05-03 15:00:40 -0700616 res = loadPcRel;
buzbee67bf8852011-08-17 17:51:35 -0700617 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 } else {
619 res = loadConstantNoClobber(cUnit, rDestLo, valLo);
620 loadConstantNoClobber(cUnit, rDestHi, valHi);
621 }
622 return res;
buzbee67bf8852011-08-17 17:51:35 -0700623}
624
buzbee31a4a6f2012-02-28 15:36:15 -0800625int encodeShift(int code, int amount) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700626 return ((amount & 0x1f) << 2) | code;
buzbee67bf8852011-08-17 17:51:35 -0700627}
628
buzbee31a4a6f2012-02-28 15:36:15 -0800629LIR* loadBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rDest,
630 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700631{
buzbeef0504cd2012-11-13 16:31:10 -0800632 bool allLowRegs = ARM_LOWREG(rBase) && ARM_LOWREG(rIndex) && ARM_LOWREG(rDest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700633 LIR* load;
634 ArmOpcode opcode = kThumbBkpt;
635 bool thumbForm = (allLowRegs && (scale == 0));
636 int regPtr;
buzbee67bf8852011-08-17 17:51:35 -0700637
buzbeef0504cd2012-11-13 16:31:10 -0800638 if (ARM_FPREG(rDest)) {
639 if (ARM_SINGLEREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700640 DCHECK((size == kWord) || (size == kSingle));
641 opcode = kThumb2Vldrs;
642 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700643 } else {
buzbeef0504cd2012-11-13 16:31:10 -0800644 DCHECK(ARM_DOUBLEREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700645 DCHECK((size == kLong) || (size == kDouble));
Elliott Hughes74847412012-06-20 18:10:21 -0700646 DCHECK_EQ((rDest & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700647 opcode = kThumb2Vldrd;
648 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700649 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700650 } else {
651 if (size == kSingle)
652 size = kWord;
653 }
buzbee67bf8852011-08-17 17:51:35 -0700654
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 switch (size) {
656 case kDouble: // fall-through
657 case kSingle:
658 regPtr = oatAllocTemp(cUnit);
659 if (scale) {
660 newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
661 encodeShift(kArmLsl, scale));
662 } else {
663 opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
664 }
665 load = newLIR3(cUnit, opcode, rDest, regPtr, 0);
666 oatFreeTemp(cUnit, regPtr);
667 return load;
668 case kWord:
669 opcode = (thumbForm) ? kThumbLdrRRR : kThumb2LdrRRR;
670 break;
671 case kUnsignedHalf:
672 opcode = (thumbForm) ? kThumbLdrhRRR : kThumb2LdrhRRR;
673 break;
674 case kSignedHalf:
675 opcode = (thumbForm) ? kThumbLdrshRRR : kThumb2LdrshRRR;
676 break;
677 case kUnsignedByte:
678 opcode = (thumbForm) ? kThumbLdrbRRR : kThumb2LdrbRRR;
679 break;
680 case kSignedByte:
681 opcode = (thumbForm) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
682 break;
683 default:
buzbeecbd6d442012-11-17 14:11:25 -0800684 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700685 }
686 if (thumbForm)
687 load = newLIR3(cUnit, opcode, rDest, rBase, rIndex);
688 else
689 load = newLIR4(cUnit, opcode, rDest, rBase, rIndex, scale);
buzbee67bf8852011-08-17 17:51:35 -0700690
Bill Buzbeea114add2012-05-03 15:00:40 -0700691 return load;
buzbee67bf8852011-08-17 17:51:35 -0700692}
693
buzbee31a4a6f2012-02-28 15:36:15 -0800694LIR* storeBaseIndexed(CompilationUnit* cUnit, int rBase, int rIndex, int rSrc,
695 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700696{
buzbeef0504cd2012-11-13 16:31:10 -0800697 bool allLowRegs = ARM_LOWREG(rBase) && ARM_LOWREG(rIndex) && ARM_LOWREG(rSrc);
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 LIR* store;
699 ArmOpcode opcode = kThumbBkpt;
700 bool thumbForm = (allLowRegs && (scale == 0));
701 int regPtr;
buzbee67bf8852011-08-17 17:51:35 -0700702
buzbeef0504cd2012-11-13 16:31:10 -0800703 if (ARM_FPREG(rSrc)) {
704 if (ARM_SINGLEREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700705 DCHECK((size == kWord) || (size == kSingle));
706 opcode = kThumb2Vstrs;
707 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700708 } else {
buzbeef0504cd2012-11-13 16:31:10 -0800709 DCHECK(ARM_DOUBLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 DCHECK((size == kLong) || (size == kDouble));
Elliott Hughes74847412012-06-20 18:10:21 -0700711 DCHECK_EQ((rSrc & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700712 opcode = kThumb2Vstrd;
713 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700714 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700715 } else {
716 if (size == kSingle)
717 size = kWord;
718 }
buzbee67bf8852011-08-17 17:51:35 -0700719
Bill Buzbeea114add2012-05-03 15:00:40 -0700720 switch (size) {
721 case kDouble: // fall-through
722 case kSingle:
723 regPtr = oatAllocTemp(cUnit);
724 if (scale) {
725 newLIR4(cUnit, kThumb2AddRRR, regPtr, rBase, rIndex,
726 encodeShift(kArmLsl, scale));
727 } else {
728 opRegRegReg(cUnit, kOpAdd, regPtr, rBase, rIndex);
729 }
730 store = newLIR3(cUnit, opcode, rSrc, regPtr, 0);
731 oatFreeTemp(cUnit, regPtr);
732 return store;
733 case kWord:
734 opcode = (thumbForm) ? kThumbStrRRR : kThumb2StrRRR;
735 break;
736 case kUnsignedHalf:
737 case kSignedHalf:
738 opcode = (thumbForm) ? kThumbStrhRRR : kThumb2StrhRRR;
739 break;
740 case kUnsignedByte:
741 case kSignedByte:
742 opcode = (thumbForm) ? kThumbStrbRRR : kThumb2StrbRRR;
743 break;
744 default:
buzbeecbd6d442012-11-17 14:11:25 -0800745 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700746 }
747 if (thumbForm)
748 store = newLIR3(cUnit, opcode, rSrc, rBase, rIndex);
749 else
750 store = newLIR4(cUnit, opcode, rSrc, rBase, rIndex, scale);
buzbee67bf8852011-08-17 17:51:35 -0700751
Bill Buzbeea114add2012-05-03 15:00:40 -0700752 return store;
buzbee67bf8852011-08-17 17:51:35 -0700753}
754
755/*
756 * Load value from base + displacement. Optionally perform null check
757 * on base (which must have an associated sReg and MIR). If not
758 * performing null check, incoming MIR can be null.
759 */
buzbee408ad162012-06-06 16:45:18 -0700760LIR* loadBaseDispBody(CompilationUnit* cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -0800761 int displacement, int rDest, int rDestHi, OpSize size,
762 int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700763{
Bill Buzbeea114add2012-05-03 15:00:40 -0700764 LIR* res;
765 LIR* load;
766 ArmOpcode opcode = kThumbBkpt;
767 bool shortForm = false;
768 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeef0504cd2012-11-13 16:31:10 -0800769 bool allLowRegs = (ARM_LOWREG(rBase) && ARM_LOWREG(rDest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700770 int encodedDisp = displacement;
771 bool is64bit = false;
772 switch (size) {
773 case kDouble:
774 case kLong:
775 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800776 if (ARM_FPREG(rDest)) {
777 if (ARM_SINGLEREG(rDest)) {
778 DCHECK(ARM_FPREG(rDestHi));
779 rDest = s2d(rDest, rDestHi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700780 }
781 opcode = kThumb2Vldrd;
782 if (displacement <= 1020) {
783 shortForm = true;
784 encodedDisp >>= 2;
785 }
786 break;
787 } else {
buzbee408ad162012-06-06 16:45:18 -0700788 res = loadBaseDispBody(cUnit, rBase, displacement, rDest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700789 -1, kWord, sReg);
buzbee408ad162012-06-06 16:45:18 -0700790 loadBaseDispBody(cUnit, rBase, displacement + 4, rDestHi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700791 -1, kWord, INVALID_SREG);
792 return res;
793 }
794 case kSingle:
795 case kWord:
buzbeef0504cd2012-11-13 16:31:10 -0800796 if (ARM_FPREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700797 opcode = kThumb2Vldrs;
798 if (displacement <= 1020) {
799 shortForm = true;
800 encodedDisp >>= 2;
801 }
802 break;
803 }
buzbeef0504cd2012-11-13 16:31:10 -0800804 if (ARM_LOWREG(rDest) && (rBase == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700805 (displacement <= 1020) && (displacement >= 0)) {
806 shortForm = true;
807 encodedDisp >>= 2;
808 opcode = kThumbLdrPcRel;
buzbeef0504cd2012-11-13 16:31:10 -0800809 } else if (ARM_LOWREG(rDest) && (rBase == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700810 (displacement <= 1020) && (displacement >= 0)) {
811 shortForm = true;
812 encodedDisp >>= 2;
813 opcode = kThumbLdrSpRel;
814 } else if (allLowRegs && displacement < 128 && displacement >= 0) {
815 DCHECK_EQ((displacement & 0x3), 0);
816 shortForm = true;
817 encodedDisp >>= 2;
818 opcode = kThumbLdrRRI5;
819 } else if (thumb2Form) {
820 shortForm = true;
821 opcode = kThumb2LdrRRI12;
822 }
823 break;
824 case kUnsignedHalf:
825 if (allLowRegs && displacement < 64 && displacement >= 0) {
826 DCHECK_EQ((displacement & 0x1), 0);
827 shortForm = true;
828 encodedDisp >>= 1;
829 opcode = kThumbLdrhRRI5;
830 } else if (displacement < 4092 && displacement >= 0) {
831 shortForm = true;
832 opcode = kThumb2LdrhRRI12;
833 }
834 break;
835 case kSignedHalf:
836 if (thumb2Form) {
837 shortForm = true;
838 opcode = kThumb2LdrshRRI12;
839 }
840 break;
841 case kUnsignedByte:
842 if (allLowRegs && displacement < 32 && displacement >= 0) {
843 shortForm = true;
844 opcode = kThumbLdrbRRI5;
845 } else if (thumb2Form) {
846 shortForm = true;
847 opcode = kThumb2LdrbRRI12;
848 }
849 break;
850 case kSignedByte:
851 if (thumb2Form) {
852 shortForm = true;
853 opcode = kThumb2LdrsbRRI12;
854 }
855 break;
856 default:
buzbeecbd6d442012-11-17 14:11:25 -0800857 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700858 }
buzbee67bf8852011-08-17 17:51:35 -0700859
Bill Buzbeea114add2012-05-03 15:00:40 -0700860 if (shortForm) {
861 load = res = newLIR3(cUnit, opcode, rDest, rBase, encodedDisp);
862 } else {
863 int regOffset = oatAllocTemp(cUnit);
864 res = loadConstant(cUnit, regOffset, encodedDisp);
865 load = loadBaseIndexed(cUnit, rBase, regOffset, rDest, 0, size);
866 oatFreeTemp(cUnit, regOffset);
867 }
buzbee67bf8852011-08-17 17:51:35 -0700868
Bill Buzbeea114add2012-05-03 15:00:40 -0700869 // TODO: in future may need to differentiate Dalvik accesses w/ spills
buzbeef0504cd2012-11-13 16:31:10 -0800870 if (rBase == rARM_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */, is64bit);
872 }
873 return load;
buzbee67bf8852011-08-17 17:51:35 -0700874}
875
buzbee408ad162012-06-06 16:45:18 -0700876LIR* loadBaseDisp(CompilationUnit* cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -0800877 int displacement, int rDest, OpSize size, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700878{
buzbee408ad162012-06-06 16:45:18 -0700879 return loadBaseDispBody(cUnit, rBase, displacement, rDest, -1, size,
Bill Buzbeea114add2012-05-03 15:00:40 -0700880 sReg);
buzbee67bf8852011-08-17 17:51:35 -0700881}
882
buzbee408ad162012-06-06 16:45:18 -0700883 LIR* loadBaseDispWide(CompilationUnit* cUnit, int rBase,
buzbee31a4a6f2012-02-28 15:36:15 -0800884 int displacement, int rDestLo, int rDestHi, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700885{
buzbee408ad162012-06-06 16:45:18 -0700886 return loadBaseDispBody(cUnit, rBase, displacement, rDestLo, rDestHi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700887 kLong, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700888}
889
890
buzbee31a4a6f2012-02-28 15:36:15 -0800891LIR* storeBaseDispBody(CompilationUnit* cUnit, int rBase, int displacement,
892 int rSrc, int rSrcHi, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700893{
Bill Buzbeea114add2012-05-03 15:00:40 -0700894 LIR* res, *store;
895 ArmOpcode opcode = kThumbBkpt;
896 bool shortForm = false;
897 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeef0504cd2012-11-13 16:31:10 -0800898 bool allLowRegs = (ARM_LOWREG(rBase) && ARM_LOWREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 int encodedDisp = displacement;
900 bool is64bit = false;
901 switch (size) {
902 case kLong:
903 case kDouble:
904 is64bit = true;
buzbeef0504cd2012-11-13 16:31:10 -0800905 if (!ARM_FPREG(rSrc)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 res = storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, kWord);
907 storeBaseDispBody(cUnit, rBase, displacement + 4, rSrcHi, -1, kWord);
908 return res;
909 }
buzbeef0504cd2012-11-13 16:31:10 -0800910 if (ARM_SINGLEREG(rSrc)) {
911 DCHECK(ARM_FPREG(rSrcHi));
912 rSrc = s2d(rSrc, rSrcHi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700913 }
914 opcode = kThumb2Vstrd;
915 if (displacement <= 1020) {
916 shortForm = true;
917 encodedDisp >>= 2;
918 }
919 break;
920 case kSingle:
921 case kWord:
buzbeef0504cd2012-11-13 16:31:10 -0800922 if (ARM_FPREG(rSrc)) {
923 DCHECK(ARM_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700924 opcode = kThumb2Vstrs;
925 if (displacement <= 1020) {
926 shortForm = true;
927 encodedDisp >>= 2;
928 }
929 break;
930 }
931 if (allLowRegs && displacement < 128 && displacement >= 0) {
932 DCHECK_EQ((displacement & 0x3), 0);
933 shortForm = true;
934 encodedDisp >>= 2;
935 opcode = kThumbStrRRI5;
936 } else if (thumb2Form) {
937 shortForm = true;
938 opcode = kThumb2StrRRI12;
939 }
940 break;
941 case kUnsignedHalf:
942 case kSignedHalf:
943 if (allLowRegs && displacement < 64 && displacement >= 0) {
944 DCHECK_EQ((displacement & 0x1), 0);
945 shortForm = true;
946 encodedDisp >>= 1;
947 opcode = kThumbStrhRRI5;
948 } else if (thumb2Form) {
949 shortForm = true;
950 opcode = kThumb2StrhRRI12;
951 }
952 break;
953 case kUnsignedByte:
954 case kSignedByte:
955 if (allLowRegs && displacement < 32 && displacement >= 0) {
956 shortForm = true;
957 opcode = kThumbStrbRRI5;
958 } else if (thumb2Form) {
959 shortForm = true;
960 opcode = kThumb2StrbRRI12;
961 }
962 break;
963 default:
buzbeecbd6d442012-11-17 14:11:25 -0800964 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700965 }
966 if (shortForm) {
967 store = res = newLIR3(cUnit, opcode, rSrc, rBase, encodedDisp);
968 } else {
969 int rScratch = oatAllocTemp(cUnit);
970 res = loadConstant(cUnit, rScratch, encodedDisp);
971 store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
972 oatFreeTemp(cUnit, rScratch);
973 }
buzbee67bf8852011-08-17 17:51:35 -0700974
Bill Buzbeea114add2012-05-03 15:00:40 -0700975 // TODO: In future, may need to differentiate Dalvik & spill accesses
buzbeef0504cd2012-11-13 16:31:10 -0800976 if (rBase == rARM_SP) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */,
978 is64bit);
979 }
980 return res;
buzbee67bf8852011-08-17 17:51:35 -0700981}
982
buzbee31a4a6f2012-02-28 15:36:15 -0800983LIR* storeBaseDisp(CompilationUnit* cUnit, int rBase, int displacement,
984 int rSrc, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700985{
Bill Buzbeea114add2012-05-03 15:00:40 -0700986 return storeBaseDispBody(cUnit, rBase, displacement, rSrc, -1, size);
buzbee67bf8852011-08-17 17:51:35 -0700987}
988
buzbee31a4a6f2012-02-28 15:36:15 -0800989LIR* storeBaseDispWide(CompilationUnit* cUnit, int rBase, int displacement,
990 int rSrcLo, int rSrcHi)
buzbee67bf8852011-08-17 17:51:35 -0700991{
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
buzbee67bf8852011-08-17 17:51:35 -0700993}
994
buzbee31a4a6f2012-02-28 15:36:15 -0800995void loadPair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
buzbee67bf8852011-08-17 17:51:35 -0700996{
buzbee408ad162012-06-06 16:45:18 -0700997 loadBaseDispWide(cUnit, base, 0, lowReg, highReg, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700998}
999
buzbee31a4a6f2012-02-28 15:36:15 -08001000LIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
buzbee67bf8852011-08-17 17:51:35 -07001001{
Bill Buzbeea114add2012-05-03 15:00:40 -07001002 int opcode;
buzbeef0504cd2012-11-13 16:31:10 -08001003 DCHECK_EQ(ARM_DOUBLEREG(rDest), ARM_DOUBLEREG(rSrc));
1004 if (ARM_DOUBLEREG(rDest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001005 opcode = kThumb2Vmovd;
1006 } else {
buzbeef0504cd2012-11-13 16:31:10 -08001007 if (ARM_SINGLEREG(rDest)) {
1008 opcode = ARM_SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr;
buzbeea2ebdd72012-03-04 14:57:06 -08001009 } else {
buzbeef0504cd2012-11-13 16:31:10 -08001010 DCHECK(ARM_SINGLEREG(rSrc));
Bill Buzbeea114add2012-05-03 15:00:40 -07001011 opcode = kThumb2Fmrs;
buzbeea2ebdd72012-03-04 14:57:06 -08001012 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001013 }
1014 LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc);
1015 if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) {
1016 res->flags.isNop = true;
1017 }
1018 return res;
buzbee67bf8852011-08-17 17:51:35 -07001019}
1020
buzbeeb046e162012-10-30 15:48:42 -07001021LIR* opThreadMem(CompilationUnit* cUnit, OpKind op, int threadOffset)
1022{
1023 LOG(FATAL) << "Unexpected use of opThreadMem for Arm";
1024 return NULL;
1025}
buzbee67bf8852011-08-17 17:51:35 -07001026
buzbeeb046e162012-10-30 15:48:42 -07001027LIR* opMem(CompilationUnit* cUnit, OpKind op, int rBase, int disp)
1028{
1029 LOG(FATAL) << "Unexpected use of opMem for Arm";
1030 return NULL;
1031}
1032
1033LIR* storeBaseIndexedDisp(CompilationUnit *cUnit,
1034 int rBase, int rIndex, int scale, int displacement,
1035 int rSrc, int rSrcHi,
1036 OpSize size, int sReg)
1037{
1038 LOG(FATAL) << "Unexpected use of storeBaseIndexedDisp for Arm";
1039 return NULL;
1040}
1041
1042LIR* opRegMem(CompilationUnit *cUnit, OpKind op, int rDest, int rBase,
1043 int offset)
1044{
1045 LOG(FATAL) << "Unexpected use of opRegMem for Arm";
1046 return NULL;
1047}
1048
1049LIR* loadBaseIndexedDisp(CompilationUnit *cUnit,
1050 int rBase, int rIndex, int scale, int displacement,
1051 int rDest, int rDestHi,
1052 OpSize size, int sReg)
1053{
1054 LOG(FATAL) << "Unexpected use of loadBaseIndexedDisp for Arm";
1055 return NULL;
1056}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001057
1058} // namespace art