blob: 8746b6866e17bfac29181549c2e251c32b75dd22 [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
buzbeeec137432012-11-13 12:13:16 -080025/*
26 * Decode the register id.
27 */
28u8 getRegMaskCommon(CompilationUnit* cUnit, int reg)
29{
30 u8 seed;
31 int shift;
32 int regId;
33
34
35 regId = reg & 0x1f;
36 /* Each double register is equal to a pair of single-precision FP registers */
37 seed = DOUBLEREG(reg) ? 3 : 1;
38 /* FP register starts at bit position 16 */
39 shift = FPREG(reg) ? kArmFPReg0 : 0;
40 /* Expand the double register id into single offset */
41 shift += regId;
42 return (seed << shift);
43}
44
45uint64_t getPCUseDefEncoding()
46{
47 return ENCODE_ARM_REG_PC;
48}
49
buzbeeb046e162012-10-30 15:48:42 -070050void setupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir)
51{
52 DCHECK_EQ(cUnit->instructionSet, kThumb2);
53
54 // Thumb2 specific setup
buzbeeec137432012-11-13 12:13:16 -080055 uint64_t flags = EncodingMap[lir->opcode].flags;
buzbeeb046e162012-10-30 15:48:42 -070056 int opcode = lir->opcode;
57
buzbeeec137432012-11-13 12:13:16 -080058 if (flags & REG_DEF_SP) {
59 lir->defMask |= ENCODE_ARM_REG_SP;
60 }
61
62 if (flags & REG_USE_SP) {
63 lir->useMask |= ENCODE_ARM_REG_SP;
64 }
65
buzbeeb046e162012-10-30 15:48:42 -070066 if (flags & REG_DEF_LIST0) {
buzbeeec137432012-11-13 12:13:16 -080067 lir->defMask |= ENCODE_ARM_REG_LIST(lir->operands[0]);
buzbeeb046e162012-10-30 15:48:42 -070068 }
69
70 if (flags & REG_DEF_LIST1) {
buzbeeec137432012-11-13 12:13:16 -080071 lir->defMask |= ENCODE_ARM_REG_LIST(lir->operands[1]);
buzbeeb046e162012-10-30 15:48:42 -070072 }
73
74 if (flags & REG_DEF_FPCS_LIST0) {
buzbeeec137432012-11-13 12:13:16 -080075 lir->defMask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]);
buzbeeb046e162012-10-30 15:48:42 -070076 }
77
78 if (flags & REG_DEF_FPCS_LIST2) {
79 for (int i = 0; i < lir->operands[2]; i++) {
80 oatSetupRegMask(cUnit, &lir->defMask, lir->operands[1] + i);
81 }
82 }
83
84 if (flags & REG_USE_PC) {
buzbeeec137432012-11-13 12:13:16 -080085 lir->useMask |= ENCODE_ARM_REG_PC;
buzbeeb046e162012-10-30 15:48:42 -070086 }
87
88 /* Conservatively treat the IT block */
89 if (flags & IS_IT) {
90 lir->defMask = ENCODE_ALL;
91 }
92
93 if (flags & REG_USE_LIST0) {
buzbeeec137432012-11-13 12:13:16 -080094 lir->useMask |= ENCODE_ARM_REG_LIST(lir->operands[0]);
buzbeeb046e162012-10-30 15:48:42 -070095 }
96
97 if (flags & REG_USE_LIST1) {
buzbeeec137432012-11-13 12:13:16 -080098 lir->useMask |= ENCODE_ARM_REG_LIST(lir->operands[1]);
buzbeeb046e162012-10-30 15:48:42 -070099 }
100
101 if (flags & REG_USE_FPCS_LIST0) {
buzbeeec137432012-11-13 12:13:16 -0800102 lir->useMask |= ENCODE_ARM_REG_FPCS_LIST(lir->operands[0]);
buzbeeb046e162012-10-30 15:48:42 -0700103 }
104
105 if (flags & REG_USE_FPCS_LIST2) {
106 for (int i = 0; i < lir->operands[2]; i++) {
107 oatSetupRegMask(cUnit, &lir->useMask, lir->operands[1] + i);
108 }
109 }
110 /* Fixup for kThumbPush/lr and kThumbPop/pc */
111 if (opcode == kThumbPush || opcode == kThumbPop) {
112 u8 r8Mask = oatGetRegMaskCommon(cUnit, r8);
113 if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
114 lir->useMask &= ~r8Mask;
buzbeeec137432012-11-13 12:13:16 -0800115 lir->useMask |= ENCODE_ARM_REG_LR;
buzbeeb046e162012-10-30 15:48:42 -0700116 } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
117 lir->defMask &= ~r8Mask;
buzbeeec137432012-11-13 12:13:16 -0800118 lir->defMask |= ENCODE_ARM_REG_PC;
buzbeeb046e162012-10-30 15:48:42 -0700119 }
120 }
121 if (flags & REG_DEF_LR) {
buzbeeec137432012-11-13 12:13:16 -0800122 lir->defMask |= ENCODE_ARM_REG_LR;
buzbeeb046e162012-10-30 15:48:42 -0700123 }
124}
125
buzbee31a4a6f2012-02-28 15:36:15 -0800126ArmConditionCode oatArmConditionEncoding(ConditionCode code)
127{
Bill Buzbeea114add2012-05-03 15:00:40 -0700128 ArmConditionCode res;
129 switch (code) {
130 case kCondEq: res = kArmCondEq; break;
131 case kCondNe: res = kArmCondNe; break;
132 case kCondCs: res = kArmCondCs; break;
133 case kCondCc: res = kArmCondCc; break;
134 case kCondMi: res = kArmCondMi; break;
135 case kCondPl: res = kArmCondPl; break;
136 case kCondVs: res = kArmCondVs; break;
137 case kCondVc: res = kArmCondVc; break;
138 case kCondHi: res = kArmCondHi; break;
139 case kCondLs: res = kArmCondLs; break;
140 case kCondGe: res = kArmCondGe; break;
141 case kCondLt: res = kArmCondLt; break;
142 case kCondGt: res = kArmCondGt; break;
143 case kCondLe: res = kArmCondLe; break;
144 case kCondAl: res = kArmCondAl; break;
145 case kCondNv: res = kArmCondNv; break;
146 default:
147 LOG(FATAL) << "Bad condition code" << (int)code;
148 res = (ArmConditionCode)0; // Quiet gcc
149 }
150 return res;
buzbee31a4a6f2012-02-28 15:36:15 -0800151}
152
buzbee67bf8852011-08-17 17:51:35 -0700153static const char* coreRegNames[16] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 "r0",
155 "r1",
156 "r2",
157 "r3",
158 "r4",
159 "r5",
160 "r6",
161 "r7",
162 "r8",
163 "rSELF",
164 "r10",
165 "r11",
166 "r12",
167 "sp",
168 "lr",
169 "pc",
buzbee67bf8852011-08-17 17:51:35 -0700170};
171
172
173static const char* shiftNames[4] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700174 "lsl",
175 "lsr",
176 "asr",
177 "ror"};
buzbee67bf8852011-08-17 17:51:35 -0700178
179/* Decode and print a ARM register name */
buzbee31a4a6f2012-02-28 15:36:15 -0800180char* decodeRegList(int opcode, int vector, char* buf)
buzbee67bf8852011-08-17 17:51:35 -0700181{
Bill Buzbeea114add2012-05-03 15:00:40 -0700182 int i;
183 bool printed = false;
184 buf[0] = 0;
185 for (i = 0; i < 16; i++, vector >>= 1) {
186 if (vector & 0x1) {
187 int regId = i;
188 if (opcode == kThumbPush && i == 8) {
189 regId = r14lr;
190 } else if (opcode == kThumbPop && i == 8) {
191 regId = r15pc;
192 }
193 if (printed) {
194 sprintf(buf + strlen(buf), ", r%d", regId);
195 } else {
196 printed = true;
197 sprintf(buf, "r%d", regId);
198 }
buzbee67bf8852011-08-17 17:51:35 -0700199 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700200 }
201 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700202}
203
buzbee31a4a6f2012-02-28 15:36:15 -0800204char* decodeFPCSRegList(int count, int base, char* buf)
buzbee67bf8852011-08-17 17:51:35 -0700205{
Bill Buzbeea114add2012-05-03 15:00:40 -0700206 sprintf(buf, "s%d", base);
207 for (int i = 1; i < count; i++) {
208 sprintf(buf + strlen(buf), ", s%d",base + i);
209 }
210 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700211}
212
buzbee31a4a6f2012-02-28 15:36:15 -0800213int expandImmediate(int value)
buzbee67bf8852011-08-17 17:51:35 -0700214{
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 int mode = (value & 0xf00) >> 8;
216 u4 bits = value & 0xff;
217 switch (mode) {
218 case 0:
219 return bits;
220 case 1:
221 return (bits << 16) | bits;
222 case 2:
223 return (bits << 24) | (bits << 8);
224 case 3:
225 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
226 default:
227 break;
228 }
229 bits = (bits | 0x80) << 24;
230 return bits >> (((value & 0xf80) >> 7) - 8);
buzbee67bf8852011-08-17 17:51:35 -0700231}
232
233const char* ccNames[] = {"eq","ne","cs","cc","mi","pl","vs","vc",
234 "hi","ls","ge","lt","gt","le","al","nv"};
235/*
236 * Interpret a format string and build a string no longer than size
237 * See format key in Assemble.c.
238 */
Bill Buzbeea114add2012-05-03 15:00:40 -0700239std::string buildInsnString(const char* fmt, LIR* lir, unsigned char* baseAddr)
buzbee67bf8852011-08-17 17:51:35 -0700240{
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 std::string buf;
242 int i;
243 const char* fmtEnd = &fmt[strlen(fmt)];
244 char tbuf[256];
245 const char* name;
246 char nc;
247 while (fmt < fmtEnd) {
248 int operand;
249 if (*fmt == '!') {
250 fmt++;
251 DCHECK_LT(fmt, fmtEnd);
252 nc = *fmt++;
253 if (nc=='!') {
254 strcpy(tbuf, "!");
255 } else {
256 DCHECK_LT(fmt, fmtEnd);
257 DCHECK_LT((unsigned)(nc-'0'), 4U);
258 operand = lir->operands[nc-'0'];
259 switch (*fmt++) {
260 case 'H':
261 if (operand != 0) {
262 sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3], operand >> 2);
263 } else {
264 strcpy(tbuf,"");
265 }
266 break;
267 case 'B':
268 switch (operand) {
269 case kSY:
270 name = "sy";
271 break;
272 case kST:
273 name = "st";
274 break;
275 case kISH:
276 name = "ish";
277 break;
278 case kISHST:
279 name = "ishst";
280 break;
281 case kNSH:
282 name = "nsh";
283 break;
284 case kNSHST:
285 name = "shst";
286 break;
287 default:
288 name = "DecodeError2";
289 break;
290 }
291 strcpy(tbuf, name);
292 break;
293 case 'b':
294 strcpy(tbuf,"0000");
295 for (i=3; i>= 0; i--) {
296 tbuf[i] += operand & 1;
297 operand >>= 1;
298 }
299 break;
300 case 'n':
301 operand = ~expandImmediate(operand);
302 sprintf(tbuf,"%d [%#x]", operand, operand);
303 break;
304 case 'm':
305 operand = expandImmediate(operand);
306 sprintf(tbuf,"%d [%#x]", operand, operand);
307 break;
308 case 's':
309 sprintf(tbuf,"s%d",operand & FP_REG_MASK);
310 break;
311 case 'S':
312 sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
313 break;
314 case 'h':
315 sprintf(tbuf,"%04x", operand);
316 break;
317 case 'M':
318 case 'd':
319 sprintf(tbuf,"%d", operand);
320 break;
321 case 'C':
buzbeef1f86362012-07-10 15:18:31 -0700322 DCHECK_LT(operand, static_cast<int>(
323 sizeof(coreRegNames)/sizeof(coreRegNames[0])));
Bill Buzbeea114add2012-05-03 15:00:40 -0700324 sprintf(tbuf,"%s",coreRegNames[operand]);
325 break;
326 case 'E':
327 sprintf(tbuf,"%d", operand*4);
328 break;
329 case 'F':
330 sprintf(tbuf,"%d", operand*2);
331 break;
332 case 'c':
333 strcpy(tbuf, ccNames[operand]);
334 break;
335 case 't':
336 sprintf(tbuf,"0x%08x (L%p)",
337 (int) baseAddr + lir->offset + 4 +
338 (operand << 1),
339 lir->target);
340 break;
341 case 'u': {
342 int offset_1 = lir->operands[0];
343 int offset_2 = NEXT_LIR(lir)->operands[0];
344 intptr_t target =
345 ((((intptr_t) baseAddr + lir->offset + 4) &
346 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
347 0xfffffffc;
348 sprintf(tbuf, "%p", (void *) target);
349 break;
350 }
buzbee67bf8852011-08-17 17:51:35 -0700351
Bill Buzbeea114add2012-05-03 15:00:40 -0700352 /* Nothing to print for BLX_2 */
353 case 'v':
354 strcpy(tbuf, "see above");
355 break;
356 case 'R':
357 decodeRegList(lir->opcode, operand, tbuf);
358 break;
359 case 'P':
360 decodeFPCSRegList(operand, 16, tbuf);
361 break;
362 case 'Q':
363 decodeFPCSRegList(operand, 0, tbuf);
364 break;
365 default:
366 strcpy(tbuf,"DecodeError1");
367 break;
buzbee67bf8852011-08-17 17:51:35 -0700368 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 buf += tbuf;
370 }
371 } else {
372 buf += *fmt++;
buzbee67bf8852011-08-17 17:51:35 -0700373 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 }
375 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700376}
377
378void oatDumpResourceMask(LIR* lir, u8 mask, const char* prefix)
379{
Bill Buzbeea114add2012-05-03 15:00:40 -0700380 char buf[256];
381 buf[0] = 0;
382 LIR* armLIR = (LIR*) lir;
buzbee67bf8852011-08-17 17:51:35 -0700383
Bill Buzbeea114add2012-05-03 15:00:40 -0700384 if (mask == ENCODE_ALL) {
385 strcpy(buf, "all");
386 } else {
387 char num[8];
388 int i;
buzbee67bf8852011-08-17 17:51:35 -0700389
buzbeeec137432012-11-13 12:13:16 -0800390 for (i = 0; i < kArmRegEnd; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700391 if (mask & (1ULL << i)) {
392 sprintf(num, "%d ", i);
393 strcat(buf, num);
394 }
buzbee67bf8852011-08-17 17:51:35 -0700395 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700396
397 if (mask & ENCODE_CCODE) {
398 strcat(buf, "cc ");
buzbee67bf8852011-08-17 17:51:35 -0700399 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700400 if (mask & ENCODE_FP_STATUS) {
401 strcat(buf, "fpcc ");
402 }
403
404 /* Memory bits */
405 if (armLIR && (mask & ENCODE_DALVIK_REG)) {
406 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
407 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
408 }
409 if (mask & ENCODE_LITERAL) {
410 strcat(buf, "lit ");
411 }
412
413 if (mask & ENCODE_HEAP_REF) {
414 strcat(buf, "heap ");
415 }
416 if (mask & ENCODE_MUST_NOT_ALIAS) {
417 strcat(buf, "noalias ");
418 }
419 }
420 if (buf[0]) {
421 LOG(INFO) << prefix << ": " << buf;
422 }
buzbee67bf8852011-08-17 17:51:35 -0700423}
424
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800425
426} // namespace art