OSDN Git Service

JIT: Support for Dalvik volatiles (issue 2781881)
[android-x86/dalvik.git] / vm / compiler / codegen / arm / ArchUtility.c
1 /*
2  * Copyright (C) 2009 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 "libdex/OpCodeNames.h"
19 #include "ArmLIR.h"
20
21 /* Decode and print a ARM register name */
22 static char * decodeRegList(int vector, char *buf)
23 {
24     int i;
25     bool printed = false;
26     buf[0] = 0;
27     for (i = 0; i < 8; i++, vector >>= 1) {
28         if (vector & 0x1) {
29             if (printed) {
30                 sprintf(buf + strlen(buf), ", r%d", i);
31             } else {
32                 printed = true;
33                 sprintf(buf, "r%d", i);
34             }
35         }
36     }
37     return buf;
38 }
39
40 static int expandImmediate(int value)
41 {
42     int mode = (value & 0xf00) >> 8;
43     u4 bits = value & 0xff;
44     switch(mode) {
45         case 0:
46             return bits;
47        case 1:
48             return (bits << 16) | bits;
49        case 2:
50             return (bits << 24) | (bits << 8);
51        case 3:
52             return (bits << 24) | (bits << 16) | (bits << 8) | bits;
53       default:
54             break;
55     }
56     bits = (bits | 0x80) << 24;
57     return bits >> (((value & 0xf80) >> 7) - 8);
58 }
59
60 /*
61  * Interpret a format string and build a string no longer than size
62  * See format key in Assemble.c.
63  */
64 static void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
65                             unsigned char *baseAddr, int size)
66 {
67     int i;
68     char *bufEnd = &buf[size-1];
69     char *fmtEnd = &fmt[strlen(fmt)];
70     char tbuf[256];
71     char *name;
72     char nc;
73     while (fmt < fmtEnd) {
74         int operand;
75         if (*fmt == '!') {
76             fmt++;
77             assert(fmt < fmtEnd);
78             nc = *fmt++;
79             if (nc=='!') {
80                 strcpy(tbuf, "!");
81             } else {
82                assert(fmt < fmtEnd);
83                assert((unsigned)(nc-'0') < 4);
84                operand = lir->operands[nc-'0'];
85                switch(*fmt++) {
86                    case 'B':
87                        switch (operand) {
88                            case kSY:
89                                name = "sy";
90                                break;
91                            case kST:
92                                name = "st";
93                                break;
94                            case kISH:
95                                name = "ish";
96                                break;
97                            case kISHST:
98                                name = "ishst";
99                                break;
100                            case kNSH:
101                                name = "nsh";
102                                break;
103                            case kNSHST:
104                                name = "shst";
105                                break;
106                            default:
107                                name = "DecodeError";
108                                break;
109                        }
110                        strcpy(tbuf, name);
111                        break;
112                    case 'b':
113                        strcpy(tbuf,"0000");
114                        for (i=3; i>= 0; i--) {
115                            tbuf[i] += operand & 1;
116                            operand >>= 1;
117                        }
118                        break;
119                    case 'n':
120                        operand = ~expandImmediate(operand);
121                        sprintf(tbuf,"%d [0x%x]", operand, operand);
122                        break;
123                    case 'm':
124                        operand = expandImmediate(operand);
125                        sprintf(tbuf,"%d [0x%x]", operand, operand);
126                        break;
127                    case 's':
128                        sprintf(tbuf,"s%d",operand & FP_REG_MASK);
129                        break;
130                    case 'S':
131                        sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
132                        break;
133                    case 'h':
134                        sprintf(tbuf,"%04x", operand);
135                        break;
136                    case 'M':
137                    case 'd':
138                        sprintf(tbuf,"%d", operand);
139                        break;
140                    case 'E':
141                        sprintf(tbuf,"%d", operand*4);
142                        break;
143                    case 'F':
144                        sprintf(tbuf,"%d", operand*2);
145                        break;
146                    case 'c':
147                        switch (operand) {
148                            case kArmCondEq:
149                                strcpy(tbuf, "eq");
150                                break;
151                            case kArmCondNe:
152                                strcpy(tbuf, "ne");
153                                break;
154                            case kArmCondLt:
155                                strcpy(tbuf, "lt");
156                                break;
157                            case kArmCondGe:
158                                strcpy(tbuf, "ge");
159                                break;
160                            case kArmCondGt:
161                                strcpy(tbuf, "gt");
162                                break;
163                            case kArmCondLe:
164                                strcpy(tbuf, "le");
165                                break;
166                            case kArmCondCs:
167                                strcpy(tbuf, "cs");
168                                break;
169                            case kArmCondMi:
170                                strcpy(tbuf, "mi");
171                                break;
172                            default:
173                                strcpy(tbuf, "");
174                                break;
175                        }
176                        break;
177                    case 't':
178                        sprintf(tbuf,"0x%08x",
179                                (int) baseAddr + lir->generic.offset + 4 +
180                                (operand << 1));
181                        break;
182                    case 'u': {
183                        int offset_1 = lir->operands[0];
184                        int offset_2 = NEXT_LIR(lir)->operands[0];
185                        intptr_t target =
186                            ((((intptr_t) baseAddr + lir->generic.offset + 4) &
187                             ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
188                            0xfffffffc;
189                        sprintf(tbuf, "%p", (void *) target);
190                        break;
191                     }
192
193                    /* Nothing to print for BLX_2 */
194                    case 'v':
195                        strcpy(tbuf, "see above");
196                        break;
197                    case 'R':
198                        decodeRegList(operand, tbuf);
199                        break;
200                    default:
201                        strcpy(tbuf,"DecodeError");
202                        break;
203                }
204                if (buf+strlen(tbuf) <= bufEnd) {
205                    strcpy(buf, tbuf);
206                    buf += strlen(tbuf);
207                } else {
208                    break;
209                }
210             }
211         } else {
212            *buf++ = *fmt++;
213         }
214         if (buf == bufEnd)
215             break;
216     }
217     *buf = 0;
218 }
219
220 void dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
221 {
222     char buf[256];
223     buf[0] = 0;
224     ArmLIR *armLIR = (ArmLIR *) lir;
225
226     if (mask == ENCODE_ALL) {
227         strcpy(buf, "all");
228     } else {
229         char num[8];
230         int i;
231
232         for (i = 0; i < kRegEnd; i++) {
233             if (mask & (1ULL << i)) {
234                 sprintf(num, "%d ", i);
235                 strcat(buf, num);
236             }
237         }
238
239         if (mask & ENCODE_CCODE) {
240             strcat(buf, "cc ");
241         }
242         if (mask & ENCODE_FP_STATUS) {
243             strcat(buf, "fpcc ");
244         }
245         if (armLIR && (mask & ENCODE_DALVIK_REG)) {
246             sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
247                     (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
248         }
249     }
250     if (buf[0]) {
251         LOGD("%s: %s", prefix, buf);
252     }
253 }
254
255 /*
256  * Debugging macros
257  */
258 #define DUMP_RESOURCE_MASK(X)
259 #define DUMP_SSA_REP(X)
260
261 /* Pretty-print a LIR instruction */
262 void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
263 {
264     ArmLIR *lir = (ArmLIR *) arg;
265     char buf[256];
266     char opName[256];
267     int offset = lir->generic.offset;
268     int dest = lir->operands[0];
269     const bool dumpNop = false;
270
271     /* Handle pseudo-ops individually, and all regular insns as a group */
272     switch(lir->opCode) {
273         case kArmChainingCellBottom:
274             LOGD("-------- end of chaining cells (0x%04x)\n", offset);
275             break;
276         case kArmPseudoBarrier:
277             LOGD("-------- BARRIER");
278             break;
279         case kArmPseudoExtended:
280             /* intentional fallthrough */
281         case kArmPseudoSSARep:
282             DUMP_SSA_REP(LOGD("-------- %s\n", (char *) dest));
283             break;
284         case kArmPseudoTargetLabel:
285             break;
286         case kArmPseudoChainingCellBackwardBranch:
287             LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest);
288             break;
289         case kArmPseudoChainingCellNormal:
290             LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
291             break;
292         case kArmPseudoChainingCellHot:
293             LOGD("-------- chaining cell (hot): 0x%04x\n", dest);
294             break;
295         case kArmPseudoChainingCellInvokePredicted:
296             LOGD("-------- chaining cell (predicted)\n");
297             break;
298         case kArmPseudoChainingCellInvokeSingleton:
299             LOGD("-------- chaining cell (invoke singleton): %s/%p\n",
300                  ((Method *)dest)->name,
301                  ((Method *)dest)->insns);
302             break;
303         case kArmPseudoEntryBlock:
304             LOGD("-------- entry offset: 0x%04x\n", dest);
305             break;
306         case kArmPseudoDalvikByteCodeBoundary:
307             LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
308                  (char *) lir->operands[1]);
309             break;
310         case kArmPseudoExitBlock:
311             LOGD("-------- exit offset: 0x%04x\n", dest);
312             break;
313         case kArmPseudoPseudoAlign4:
314             LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
315             break;
316         case kArmPseudoPCReconstructionCell:
317             LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest,
318                  lir->operands[1]);
319             break;
320         case kArmPseudoPCReconstructionBlockLabel:
321             /* Do nothing */
322             break;
323         case kArmPseudoEHBlockLabel:
324             LOGD("Exception_Handling:\n");
325             break;
326         case kArmPseudoNormalBlockLabel:
327             LOGD("L%#06x:\n", dest);
328             break;
329         default:
330             if (lir->isNop && !dumpNop) {
331                 break;
332             }
333             buildInsnString(EncodingMap[lir->opCode].name, lir, opName,
334                             baseAddr, 256);
335             buildInsnString(EncodingMap[lir->opCode].fmt, lir, buf, baseAddr,
336                             256);
337             LOGD("%p (%04x): %-8s%s%s\n",
338                  baseAddr + offset, offset, opName, buf,
339                  lir->isNop ? "(nop)" : "");
340             break;
341     }
342
343     if (lir->useMask && (!lir->isNop || dumpNop)) {
344         DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
345                                                lir->useMask, "use"));
346     }
347     if (lir->defMask && (!lir->isNop || dumpNop)) {
348         DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
349                                                lir->defMask, "def"));
350     }
351 }
352
353 /* Dump instructions and constant pool contents */
354 void dvmCompilerCodegenDump(CompilationUnit *cUnit)
355 {
356     LOGD("Dumping LIR insns\n");
357     LIR *lirInsn;
358     ArmLIR *armLIR;
359
360     LOGD("installed code is at %p\n", cUnit->baseAddr);
361     LOGD("total size is %d bytes\n", cUnit->totalSize);
362     for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
363         dvmDumpLIRInsn(lirInsn, cUnit->baseAddr);
364     }
365     for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
366         armLIR = (ArmLIR *) lirInsn;
367         LOGD("%p (%04x): .word (0x%x)\n",
368              (char*)cUnit->baseAddr + armLIR->generic.offset,
369              armLIR->generic.offset,
370              armLIR->operands[0]);
371     }
372 }