blob: 2d4b314d51038e91c880efc5768363950c071524 [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
17#include "../../CompilerInternals.h"
18#include "ArmLIR.h"
buzbee67bc2362011-10-11 18:08:40 -070019#include "../Ralloc.h"
buzbee67bf8852011-08-17 17:51:35 -070020
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070021#include <string>
22
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080023namespace art {
24
buzbeef0504cd2012-11-13 16:31:10 -080025RegLocation locCReturn()
26{
27 RegLocation res = ARM_LOC_C_RETURN;
28 return res;
29}
30
31RegLocation locCReturnWide()
32{
33 RegLocation res = ARM_LOC_C_RETURN_WIDE;
34 return res;
35}
36
37RegLocation locCReturnFloat()
38{
39 RegLocation res = ARM_LOC_C_RETURN_FLOAT;
40 return res;
41}
42
43RegLocation locCReturnDouble()
44{
45 RegLocation res = ARM_LOC_C_RETURN_DOUBLE;
46 return res;
47}
48
49// Return a target-dependent special register.
50int targetReg(SpecialTargetRegister reg) {
51 int res = INVALID_REG;
52 switch (reg) {
53 case kSelf: res = rARM_SELF; break;
54 case kSuspend: res = rARM_SUSPEND; break;
55 case kLr: res = rARM_LR; break;
56 case kPc: res = rARM_PC; break;
57 case kSp: res = rARM_SP; break;
58 case kArg0: res = rARM_ARG0; break;
59 case kArg1: res = rARM_ARG1; break;
60 case kArg2: res = rARM_ARG2; break;
61 case kArg3: res = rARM_ARG3; break;
62 case kFArg0: res = rARM_FARG0; break;
63 case kFArg1: res = rARM_FARG1; break;
64 case kFArg2: res = rARM_FARG2; break;
65 case kFArg3: res = rARM_FARG3; break;
66 case kRet0: res = rARM_RET0; break;
67 case kRet1: res = rARM_RET1; break;
68 case kInvokeTgt: res = rARM_INVOKE_TGT; break;
69 case kCount: res = rARM_COUNT; break;
70 }
71 return res;
72}
73
74
75// Create a double from a pair of singles.
76int s2d(int lowReg, int highReg)
77{
78 return ARM_S2D(lowReg, highReg);
79}
80
81// Is reg a single or double?
82bool fpReg(int reg)
83{
84 return ARM_FPREG(reg);
85}
86
87// Is reg a single?
88bool singleReg(int reg)
89{
90 return ARM_SINGLEREG(reg);
91}
92
93// Is reg a double?
94bool doubleReg(int reg)
95{
96 return ARM_DOUBLEREG(reg);
97}
98
99// Return mask to strip off fp reg flags and bias.
100uint32_t fpRegMask()
101{
102 return ARM_FP_REG_MASK;
103}
104
105// True if both regs single, both core or both double.
106bool sameRegType(int reg1, int reg2)
107{
108 return (ARM_REGTYPE(reg1) == ARM_REGTYPE(reg2));
109}
110
buzbeeec137432012-11-13 12:13:16 -0800111/*
112 * Decode the register id.
113 */
114u8 getRegMaskCommon(CompilationUnit* cUnit, int reg)
115{
116 u8 seed;
117 int shift;
118 int regId;
119
120
121 regId = reg & 0x1f;
122 /* Each double register is equal to a pair of single-precision FP registers */
buzbeef0504cd2012-11-13 16:31:10 -0800123 seed = ARM_DOUBLEREG(reg) ? 3 : 1;
buzbeeec137432012-11-13 12:13:16 -0800124 /* FP register starts at bit position 16 */
buzbeef0504cd2012-11-13 16:31:10 -0800125 shift = ARM_FPREG(reg) ? kArmFPReg0 : 0;
buzbeeec137432012-11-13 12:13:16 -0800126 /* Expand the double register id into single offset */
127 shift += regId;
128 return (seed << shift);
129}
130
131uint64_t getPCUseDefEncoding()
132{
133 return ENCODE_ARM_REG_PC;
134}
135
buzbeeb046e162012-10-30 15:48:42 -0700136void setupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir)
137{
138 DCHECK_EQ(cUnit->instructionSet, kThumb2);
139
140 // Thumb2 specific setup
buzbeeec137432012-11-13 12:13:16 -0800141 uint64_t flags = EncodingMap[lir->opcode].flags;
buzbeeb046e162012-10-30 15:48:42 -0700142 int opcode = lir->opcode;
143
buzbeeec137432012-11-13 12:13:16 -0800144 if (flags & REG_DEF_SP) {
145 lir->defMask |= ENCODE_ARM_REG_SP;
146 }
147
148 if (flags & REG_USE_SP) {
149 lir->useMask |= ENCODE_ARM_REG_SP;
150 }
151
buzbeeb046e162012-10-30 15:48:42 -0700152 if (flags & REG_DEF_LIST0) {
buzbeeec137432012-11-13 12:13:16 -0800153 lir->defMask |= ENCODE_ARM_REG_LIST(lir->operands[0]);
buzbeeb046e162012-10-30 15:48:42 -0700154 }
155
156 if (flags & REG_DEF_LIST1) {
buzbeeec137432012-11-13 12:13:16 -0800157 lir->defMask |= ENCODE_ARM_REG_LIST(lir->operands[1]);
buzbeeb046e162012-10-30 15:48:42 -0700158 }
159
160 if (flags & REG_DEF_FPCS_LIST0) {
buzbeeec137432012-11-13 12:13:16 -0800161 lir->defMask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]);
buzbeeb046e162012-10-30 15:48:42 -0700162 }
163
164 if (flags & REG_DEF_FPCS_LIST2) {
165 for (int i = 0; i < lir->operands[2]; i++) {
166 oatSetupRegMask(cUnit, &lir->defMask, lir->operands[1] + i);
167 }
168 }
169
170 if (flags & REG_USE_PC) {
buzbeeec137432012-11-13 12:13:16 -0800171 lir->useMask |= ENCODE_ARM_REG_PC;
buzbeeb046e162012-10-30 15:48:42 -0700172 }
173
174 /* Conservatively treat the IT block */
175 if (flags & IS_IT) {
176 lir->defMask = ENCODE_ALL;
177 }
178
179 if (flags & REG_USE_LIST0) {
buzbeeec137432012-11-13 12:13:16 -0800180 lir->useMask |= ENCODE_ARM_REG_LIST(lir->operands[0]);
buzbeeb046e162012-10-30 15:48:42 -0700181 }
182
183 if (flags & REG_USE_LIST1) {
buzbeeec137432012-11-13 12:13:16 -0800184 lir->useMask |= ENCODE_ARM_REG_LIST(lir->operands[1]);
buzbeeb046e162012-10-30 15:48:42 -0700185 }
186
187 if (flags & REG_USE_FPCS_LIST0) {
buzbeeec137432012-11-13 12:13:16 -0800188 lir->useMask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]);
buzbeeb046e162012-10-30 15:48:42 -0700189 }
190
191 if (flags & REG_USE_FPCS_LIST2) {
192 for (int i = 0; i < lir->operands[2]; i++) {
193 oatSetupRegMask(cUnit, &lir->useMask, lir->operands[1] + i);
194 }
195 }
196 /* Fixup for kThumbPush/lr and kThumbPop/pc */
197 if (opcode == kThumbPush || opcode == kThumbPop) {
198 u8 r8Mask = oatGetRegMaskCommon(cUnit, r8);
199 if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
200 lir->useMask &= ~r8Mask;
buzbeeec137432012-11-13 12:13:16 -0800201 lir->useMask |= ENCODE_ARM_REG_LR;
buzbeeb046e162012-10-30 15:48:42 -0700202 } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
203 lir->defMask &= ~r8Mask;
buzbeeec137432012-11-13 12:13:16 -0800204 lir->defMask |= ENCODE_ARM_REG_PC;
buzbeeb046e162012-10-30 15:48:42 -0700205 }
206 }
207 if (flags & REG_DEF_LR) {
buzbeeec137432012-11-13 12:13:16 -0800208 lir->defMask |= ENCODE_ARM_REG_LR;
buzbeeb046e162012-10-30 15:48:42 -0700209 }
210}
211
buzbee31a4a6f2012-02-28 15:36:15 -0800212ArmConditionCode oatArmConditionEncoding(ConditionCode code)
213{
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 ArmConditionCode res;
215 switch (code) {
216 case kCondEq: res = kArmCondEq; break;
217 case kCondNe: res = kArmCondNe; break;
218 case kCondCs: res = kArmCondCs; break;
219 case kCondCc: res = kArmCondCc; break;
220 case kCondMi: res = kArmCondMi; break;
221 case kCondPl: res = kArmCondPl; break;
222 case kCondVs: res = kArmCondVs; break;
223 case kCondVc: res = kArmCondVc; break;
224 case kCondHi: res = kArmCondHi; break;
225 case kCondLs: res = kArmCondLs; break;
226 case kCondGe: res = kArmCondGe; break;
227 case kCondLt: res = kArmCondLt; break;
228 case kCondGt: res = kArmCondGt; break;
229 case kCondLe: res = kArmCondLe; break;
230 case kCondAl: res = kArmCondAl; break;
231 case kCondNv: res = kArmCondNv; break;
232 default:
233 LOG(FATAL) << "Bad condition code" << (int)code;
234 res = (ArmConditionCode)0; // Quiet gcc
235 }
236 return res;
buzbee31a4a6f2012-02-28 15:36:15 -0800237}
238
buzbee67bf8852011-08-17 17:51:35 -0700239static const char* coreRegNames[16] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 "r0",
241 "r1",
242 "r2",
243 "r3",
244 "r4",
245 "r5",
246 "r6",
247 "r7",
248 "r8",
249 "rSELF",
250 "r10",
251 "r11",
252 "r12",
253 "sp",
254 "lr",
255 "pc",
buzbee67bf8852011-08-17 17:51:35 -0700256};
257
258
259static const char* shiftNames[4] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 "lsl",
261 "lsr",
262 "asr",
263 "ror"};
buzbee67bf8852011-08-17 17:51:35 -0700264
265/* Decode and print a ARM register name */
buzbee31a4a6f2012-02-28 15:36:15 -0800266char* decodeRegList(int opcode, int vector, char* buf)
buzbee67bf8852011-08-17 17:51:35 -0700267{
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 int i;
269 bool printed = false;
270 buf[0] = 0;
271 for (i = 0; i < 16; i++, vector >>= 1) {
272 if (vector & 0x1) {
273 int regId = i;
274 if (opcode == kThumbPush && i == 8) {
275 regId = r14lr;
276 } else if (opcode == kThumbPop && i == 8) {
277 regId = r15pc;
278 }
279 if (printed) {
280 sprintf(buf + strlen(buf), ", r%d", regId);
281 } else {
282 printed = true;
283 sprintf(buf, "r%d", regId);
284 }
buzbee67bf8852011-08-17 17:51:35 -0700285 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700286 }
287 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700288}
289
buzbee31a4a6f2012-02-28 15:36:15 -0800290char* decodeFPCSRegList(int count, int base, char* buf)
buzbee67bf8852011-08-17 17:51:35 -0700291{
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 sprintf(buf, "s%d", base);
293 for (int i = 1; i < count; i++) {
294 sprintf(buf + strlen(buf), ", s%d",base + i);
295 }
296 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700297}
298
buzbee31a4a6f2012-02-28 15:36:15 -0800299int expandImmediate(int value)
buzbee67bf8852011-08-17 17:51:35 -0700300{
Bill Buzbeea114add2012-05-03 15:00:40 -0700301 int mode = (value & 0xf00) >> 8;
302 u4 bits = value & 0xff;
303 switch (mode) {
304 case 0:
305 return bits;
306 case 1:
307 return (bits << 16) | bits;
308 case 2:
309 return (bits << 24) | (bits << 8);
310 case 3:
311 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
312 default:
313 break;
314 }
315 bits = (bits | 0x80) << 24;
316 return bits >> (((value & 0xf80) >> 7) - 8);
buzbee67bf8852011-08-17 17:51:35 -0700317}
318
319const char* ccNames[] = {"eq","ne","cs","cc","mi","pl","vs","vc",
320 "hi","ls","ge","lt","gt","le","al","nv"};
321/*
322 * Interpret a format string and build a string no longer than size
323 * See format key in Assemble.c.
324 */
Bill Buzbeea114add2012-05-03 15:00:40 -0700325std::string buildInsnString(const char* fmt, LIR* lir, unsigned char* baseAddr)
buzbee67bf8852011-08-17 17:51:35 -0700326{
Bill Buzbeea114add2012-05-03 15:00:40 -0700327 std::string buf;
328 int i;
329 const char* fmtEnd = &fmt[strlen(fmt)];
330 char tbuf[256];
331 const char* name;
332 char nc;
333 while (fmt < fmtEnd) {
334 int operand;
335 if (*fmt == '!') {
336 fmt++;
337 DCHECK_LT(fmt, fmtEnd);
338 nc = *fmt++;
339 if (nc=='!') {
340 strcpy(tbuf, "!");
341 } else {
342 DCHECK_LT(fmt, fmtEnd);
343 DCHECK_LT((unsigned)(nc-'0'), 4U);
344 operand = lir->operands[nc-'0'];
345 switch (*fmt++) {
346 case 'H':
347 if (operand != 0) {
348 sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3], operand >> 2);
349 } else {
350 strcpy(tbuf,"");
351 }
352 break;
353 case 'B':
354 switch (operand) {
355 case kSY:
356 name = "sy";
357 break;
358 case kST:
359 name = "st";
360 break;
361 case kISH:
362 name = "ish";
363 break;
364 case kISHST:
365 name = "ishst";
366 break;
367 case kNSH:
368 name = "nsh";
369 break;
370 case kNSHST:
371 name = "shst";
372 break;
373 default:
374 name = "DecodeError2";
375 break;
376 }
377 strcpy(tbuf, name);
378 break;
379 case 'b':
380 strcpy(tbuf,"0000");
381 for (i=3; i>= 0; i--) {
382 tbuf[i] += operand & 1;
383 operand >>= 1;
384 }
385 break;
386 case 'n':
387 operand = ~expandImmediate(operand);
388 sprintf(tbuf,"%d [%#x]", operand, operand);
389 break;
390 case 'm':
391 operand = expandImmediate(operand);
392 sprintf(tbuf,"%d [%#x]", operand, operand);
393 break;
394 case 's':
buzbeef0504cd2012-11-13 16:31:10 -0800395 sprintf(tbuf,"s%d",operand & ARM_FP_REG_MASK);
Bill Buzbeea114add2012-05-03 15:00:40 -0700396 break;
397 case 'S':
buzbeef0504cd2012-11-13 16:31:10 -0800398 sprintf(tbuf,"d%d",(operand & ARM_FP_REG_MASK) >> 1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 break;
400 case 'h':
401 sprintf(tbuf,"%04x", operand);
402 break;
403 case 'M':
404 case 'd':
405 sprintf(tbuf,"%d", operand);
406 break;
407 case 'C':
buzbeef1f86362012-07-10 15:18:31 -0700408 DCHECK_LT(operand, static_cast<int>(
409 sizeof(coreRegNames)/sizeof(coreRegNames[0])));
Bill Buzbeea114add2012-05-03 15:00:40 -0700410 sprintf(tbuf,"%s",coreRegNames[operand]);
411 break;
412 case 'E':
413 sprintf(tbuf,"%d", operand*4);
414 break;
415 case 'F':
416 sprintf(tbuf,"%d", operand*2);
417 break;
418 case 'c':
419 strcpy(tbuf, ccNames[operand]);
420 break;
421 case 't':
422 sprintf(tbuf,"0x%08x (L%p)",
423 (int) baseAddr + lir->offset + 4 +
424 (operand << 1),
425 lir->target);
426 break;
427 case 'u': {
428 int offset_1 = lir->operands[0];
429 int offset_2 = NEXT_LIR(lir)->operands[0];
430 intptr_t target =
431 ((((intptr_t) baseAddr + lir->offset + 4) &
432 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
433 0xfffffffc;
434 sprintf(tbuf, "%p", (void *) target);
435 break;
436 }
buzbee67bf8852011-08-17 17:51:35 -0700437
Bill Buzbeea114add2012-05-03 15:00:40 -0700438 /* Nothing to print for BLX_2 */
439 case 'v':
440 strcpy(tbuf, "see above");
441 break;
442 case 'R':
443 decodeRegList(lir->opcode, operand, tbuf);
444 break;
445 case 'P':
446 decodeFPCSRegList(operand, 16, tbuf);
447 break;
448 case 'Q':
449 decodeFPCSRegList(operand, 0, tbuf);
450 break;
451 default:
452 strcpy(tbuf,"DecodeError1");
453 break;
buzbee67bf8852011-08-17 17:51:35 -0700454 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 buf += tbuf;
456 }
457 } else {
458 buf += *fmt++;
buzbee67bf8852011-08-17 17:51:35 -0700459 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 }
461 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700462}
463
464void oatDumpResourceMask(LIR* lir, u8 mask, const char* prefix)
465{
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 char buf[256];
467 buf[0] = 0;
468 LIR* armLIR = (LIR*) lir;
buzbee67bf8852011-08-17 17:51:35 -0700469
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 if (mask == ENCODE_ALL) {
471 strcpy(buf, "all");
472 } else {
473 char num[8];
474 int i;
buzbee67bf8852011-08-17 17:51:35 -0700475
buzbeeec137432012-11-13 12:13:16 -0800476 for (i = 0; i < kArmRegEnd; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700477 if (mask & (1ULL << i)) {
478 sprintf(num, "%d ", i);
479 strcat(buf, num);
480 }
buzbee67bf8852011-08-17 17:51:35 -0700481 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700482
483 if (mask & ENCODE_CCODE) {
484 strcat(buf, "cc ");
buzbee67bf8852011-08-17 17:51:35 -0700485 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 if (mask & ENCODE_FP_STATUS) {
487 strcat(buf, "fpcc ");
488 }
489
490 /* Memory bits */
491 if (armLIR && (mask & ENCODE_DALVIK_REG)) {
492 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
493 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
494 }
495 if (mask & ENCODE_LITERAL) {
496 strcat(buf, "lit ");
497 }
498
499 if (mask & ENCODE_HEAP_REF) {
500 strcat(buf, "heap ");
501 }
502 if (mask & ENCODE_MUST_NOT_ALIAS) {
503 strcat(buf, "noalias ");
504 }
505 }
506 if (buf[0]) {
507 LOG(INFO) << prefix << ": " << buf;
508 }
buzbee67bf8852011-08-17 17:51:35 -0700509}
510
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800511
512} // namespace art