blob: 820f64e643299d8fd7a46965dcf3ce3f7f67ce46 [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
buzbeeb046e162012-10-30 15:48:42 -070025void setupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir)
26{
27 DCHECK_EQ(cUnit->instructionSet, kThumb2);
28
29 // Thumb2 specific setup
30 int flags = EncodingMap[lir->opcode].flags;
31 int opcode = lir->opcode;
32
33 if (flags & REG_DEF_LIST0) {
34 lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
35 }
36
37 if (flags & REG_DEF_LIST1) {
38 lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
39 }
40
41 if (flags & REG_DEF_FPCS_LIST0) {
42 lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
43 }
44
45 if (flags & REG_DEF_FPCS_LIST2) {
46 for (int i = 0; i < lir->operands[2]; i++) {
47 oatSetupRegMask(cUnit, &lir->defMask, lir->operands[1] + i);
48 }
49 }
50
51 if (flags & REG_USE_PC) {
52 lir->useMask |= ENCODE_REG_PC;
53 }
54
55 /* Conservatively treat the IT block */
56 if (flags & IS_IT) {
57 lir->defMask = ENCODE_ALL;
58 }
59
60 if (flags & REG_USE_LIST0) {
61 lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
62 }
63
64 if (flags & REG_USE_LIST1) {
65 lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
66 }
67
68 if (flags & REG_USE_FPCS_LIST0) {
69 lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
70 }
71
72 if (flags & REG_USE_FPCS_LIST2) {
73 for (int i = 0; i < lir->operands[2]; i++) {
74 oatSetupRegMask(cUnit, &lir->useMask, lir->operands[1] + i);
75 }
76 }
77 /* Fixup for kThumbPush/lr and kThumbPop/pc */
78 if (opcode == kThumbPush || opcode == kThumbPop) {
79 u8 r8Mask = oatGetRegMaskCommon(cUnit, r8);
80 if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
81 lir->useMask &= ~r8Mask;
82 lir->useMask |= ENCODE_REG_LR;
83 } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
84 lir->defMask &= ~r8Mask;
85 lir->defMask |= ENCODE_REG_PC;
86 }
87 }
88 if (flags & REG_DEF_LR) {
89 lir->defMask |= ENCODE_REG_LR;
90 }
91}
92
buzbee31a4a6f2012-02-28 15:36:15 -080093ArmConditionCode oatArmConditionEncoding(ConditionCode code)
94{
Bill Buzbeea114add2012-05-03 15:00:40 -070095 ArmConditionCode res;
96 switch (code) {
97 case kCondEq: res = kArmCondEq; break;
98 case kCondNe: res = kArmCondNe; break;
99 case kCondCs: res = kArmCondCs; break;
100 case kCondCc: res = kArmCondCc; break;
101 case kCondMi: res = kArmCondMi; break;
102 case kCondPl: res = kArmCondPl; break;
103 case kCondVs: res = kArmCondVs; break;
104 case kCondVc: res = kArmCondVc; break;
105 case kCondHi: res = kArmCondHi; break;
106 case kCondLs: res = kArmCondLs; break;
107 case kCondGe: res = kArmCondGe; break;
108 case kCondLt: res = kArmCondLt; break;
109 case kCondGt: res = kArmCondGt; break;
110 case kCondLe: res = kArmCondLe; break;
111 case kCondAl: res = kArmCondAl; break;
112 case kCondNv: res = kArmCondNv; break;
113 default:
114 LOG(FATAL) << "Bad condition code" << (int)code;
115 res = (ArmConditionCode)0; // Quiet gcc
116 }
117 return res;
buzbee31a4a6f2012-02-28 15:36:15 -0800118}
119
buzbee67bf8852011-08-17 17:51:35 -0700120static const char* coreRegNames[16] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700121 "r0",
122 "r1",
123 "r2",
124 "r3",
125 "r4",
126 "r5",
127 "r6",
128 "r7",
129 "r8",
130 "rSELF",
131 "r10",
132 "r11",
133 "r12",
134 "sp",
135 "lr",
136 "pc",
buzbee67bf8852011-08-17 17:51:35 -0700137};
138
139
140static const char* shiftNames[4] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700141 "lsl",
142 "lsr",
143 "asr",
144 "ror"};
buzbee67bf8852011-08-17 17:51:35 -0700145
146/* Decode and print a ARM register name */
buzbee31a4a6f2012-02-28 15:36:15 -0800147char* decodeRegList(int opcode, int vector, char* buf)
buzbee67bf8852011-08-17 17:51:35 -0700148{
Bill Buzbeea114add2012-05-03 15:00:40 -0700149 int i;
150 bool printed = false;
151 buf[0] = 0;
152 for (i = 0; i < 16; i++, vector >>= 1) {
153 if (vector & 0x1) {
154 int regId = i;
155 if (opcode == kThumbPush && i == 8) {
156 regId = r14lr;
157 } else if (opcode == kThumbPop && i == 8) {
158 regId = r15pc;
159 }
160 if (printed) {
161 sprintf(buf + strlen(buf), ", r%d", regId);
162 } else {
163 printed = true;
164 sprintf(buf, "r%d", regId);
165 }
buzbee67bf8852011-08-17 17:51:35 -0700166 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 }
168 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700169}
170
buzbee31a4a6f2012-02-28 15:36:15 -0800171char* decodeFPCSRegList(int count, int base, char* buf)
buzbee67bf8852011-08-17 17:51:35 -0700172{
Bill Buzbeea114add2012-05-03 15:00:40 -0700173 sprintf(buf, "s%d", base);
174 for (int i = 1; i < count; i++) {
175 sprintf(buf + strlen(buf), ", s%d",base + i);
176 }
177 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700178}
179
buzbee31a4a6f2012-02-28 15:36:15 -0800180int expandImmediate(int value)
buzbee67bf8852011-08-17 17:51:35 -0700181{
Bill Buzbeea114add2012-05-03 15:00:40 -0700182 int mode = (value & 0xf00) >> 8;
183 u4 bits = value & 0xff;
184 switch (mode) {
185 case 0:
186 return bits;
187 case 1:
188 return (bits << 16) | bits;
189 case 2:
190 return (bits << 24) | (bits << 8);
191 case 3:
192 return (bits << 24) | (bits << 16) | (bits << 8) | bits;
193 default:
194 break;
195 }
196 bits = (bits | 0x80) << 24;
197 return bits >> (((value & 0xf80) >> 7) - 8);
buzbee67bf8852011-08-17 17:51:35 -0700198}
199
200const char* ccNames[] = {"eq","ne","cs","cc","mi","pl","vs","vc",
201 "hi","ls","ge","lt","gt","le","al","nv"};
202/*
203 * Interpret a format string and build a string no longer than size
204 * See format key in Assemble.c.
205 */
Bill Buzbeea114add2012-05-03 15:00:40 -0700206std::string buildInsnString(const char* fmt, LIR* lir, unsigned char* baseAddr)
buzbee67bf8852011-08-17 17:51:35 -0700207{
Bill Buzbeea114add2012-05-03 15:00:40 -0700208 std::string buf;
209 int i;
210 const char* fmtEnd = &fmt[strlen(fmt)];
211 char tbuf[256];
212 const char* name;
213 char nc;
214 while (fmt < fmtEnd) {
215 int operand;
216 if (*fmt == '!') {
217 fmt++;
218 DCHECK_LT(fmt, fmtEnd);
219 nc = *fmt++;
220 if (nc=='!') {
221 strcpy(tbuf, "!");
222 } else {
223 DCHECK_LT(fmt, fmtEnd);
224 DCHECK_LT((unsigned)(nc-'0'), 4U);
225 operand = lir->operands[nc-'0'];
226 switch (*fmt++) {
227 case 'H':
228 if (operand != 0) {
229 sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3], operand >> 2);
230 } else {
231 strcpy(tbuf,"");
232 }
233 break;
234 case 'B':
235 switch (operand) {
236 case kSY:
237 name = "sy";
238 break;
239 case kST:
240 name = "st";
241 break;
242 case kISH:
243 name = "ish";
244 break;
245 case kISHST:
246 name = "ishst";
247 break;
248 case kNSH:
249 name = "nsh";
250 break;
251 case kNSHST:
252 name = "shst";
253 break;
254 default:
255 name = "DecodeError2";
256 break;
257 }
258 strcpy(tbuf, name);
259 break;
260 case 'b':
261 strcpy(tbuf,"0000");
262 for (i=3; i>= 0; i--) {
263 tbuf[i] += operand & 1;
264 operand >>= 1;
265 }
266 break;
267 case 'n':
268 operand = ~expandImmediate(operand);
269 sprintf(tbuf,"%d [%#x]", operand, operand);
270 break;
271 case 'm':
272 operand = expandImmediate(operand);
273 sprintf(tbuf,"%d [%#x]", operand, operand);
274 break;
275 case 's':
276 sprintf(tbuf,"s%d",operand & FP_REG_MASK);
277 break;
278 case 'S':
279 sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
280 break;
281 case 'h':
282 sprintf(tbuf,"%04x", operand);
283 break;
284 case 'M':
285 case 'd':
286 sprintf(tbuf,"%d", operand);
287 break;
288 case 'C':
buzbeef1f86362012-07-10 15:18:31 -0700289 DCHECK_LT(operand, static_cast<int>(
290 sizeof(coreRegNames)/sizeof(coreRegNames[0])));
Bill Buzbeea114add2012-05-03 15:00:40 -0700291 sprintf(tbuf,"%s",coreRegNames[operand]);
292 break;
293 case 'E':
294 sprintf(tbuf,"%d", operand*4);
295 break;
296 case 'F':
297 sprintf(tbuf,"%d", operand*2);
298 break;
299 case 'c':
300 strcpy(tbuf, ccNames[operand]);
301 break;
302 case 't':
303 sprintf(tbuf,"0x%08x (L%p)",
304 (int) baseAddr + lir->offset + 4 +
305 (operand << 1),
306 lir->target);
307 break;
308 case 'u': {
309 int offset_1 = lir->operands[0];
310 int offset_2 = NEXT_LIR(lir)->operands[0];
311 intptr_t target =
312 ((((intptr_t) baseAddr + lir->offset + 4) &
313 ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
314 0xfffffffc;
315 sprintf(tbuf, "%p", (void *) target);
316 break;
317 }
buzbee67bf8852011-08-17 17:51:35 -0700318
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 /* Nothing to print for BLX_2 */
320 case 'v':
321 strcpy(tbuf, "see above");
322 break;
323 case 'R':
324 decodeRegList(lir->opcode, operand, tbuf);
325 break;
326 case 'P':
327 decodeFPCSRegList(operand, 16, tbuf);
328 break;
329 case 'Q':
330 decodeFPCSRegList(operand, 0, tbuf);
331 break;
332 default:
333 strcpy(tbuf,"DecodeError1");
334 break;
buzbee67bf8852011-08-17 17:51:35 -0700335 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 buf += tbuf;
337 }
338 } else {
339 buf += *fmt++;
buzbee67bf8852011-08-17 17:51:35 -0700340 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700341 }
342 return buf;
buzbee67bf8852011-08-17 17:51:35 -0700343}
344
345void oatDumpResourceMask(LIR* lir, u8 mask, const char* prefix)
346{
Bill Buzbeea114add2012-05-03 15:00:40 -0700347 char buf[256];
348 buf[0] = 0;
349 LIR* armLIR = (LIR*) lir;
buzbee67bf8852011-08-17 17:51:35 -0700350
Bill Buzbeea114add2012-05-03 15:00:40 -0700351 if (mask == ENCODE_ALL) {
352 strcpy(buf, "all");
353 } else {
354 char num[8];
355 int i;
buzbee67bf8852011-08-17 17:51:35 -0700356
Bill Buzbeea114add2012-05-03 15:00:40 -0700357 for (i = 0; i < kRegEnd; i++) {
358 if (mask & (1ULL << i)) {
359 sprintf(num, "%d ", i);
360 strcat(buf, num);
361 }
buzbee67bf8852011-08-17 17:51:35 -0700362 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700363
364 if (mask & ENCODE_CCODE) {
365 strcat(buf, "cc ");
buzbee67bf8852011-08-17 17:51:35 -0700366 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 if (mask & ENCODE_FP_STATUS) {
368 strcat(buf, "fpcc ");
369 }
370
371 /* Memory bits */
372 if (armLIR && (mask & ENCODE_DALVIK_REG)) {
373 sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
374 (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
375 }
376 if (mask & ENCODE_LITERAL) {
377 strcat(buf, "lit ");
378 }
379
380 if (mask & ENCODE_HEAP_REF) {
381 strcat(buf, "heap ");
382 }
383 if (mask & ENCODE_MUST_NOT_ALIAS) {
384 strcat(buf, "noalias ");
385 }
386 }
387 if (buf[0]) {
388 LOG(INFO) << prefix << ": " << buf;
389 }
buzbee67bf8852011-08-17 17:51:35 -0700390}
391
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800392
393} // namespace art