ArchUtility.cpp revision 18c990ebab4475335a5b94ac6077d3482b6875b9
1ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
2ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Copyright (C) 2009 The Android Open Source Project
3ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
4ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Licensed under the Apache License, Version 2.0 (the "License");
5ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * you may not use this file except in compliance with the License.
6ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * You may obtain a copy of the License at
7ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
8ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *      http://www.apache.org/licenses/LICENSE-2.0
9ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng *
10ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Unless required by applicable law or agreed to in writing, software
11ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * distributed under the License is distributed on an "AS IS" BASIS,
12ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * See the License for the specific language governing permissions and
14ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * limitations under the License.
15ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
16ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
17ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "../../CompilerInternals.h"
18df4daaf8f41e3dcaa8221f54273338160dd43138Dan Bornstein#include "libdex/DexOpcodes.h"
1989efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee#include "ArmLIR.h"
20ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
2114f711ba6ffea52d6000e7d442d01b684bbe7f97buzbeestatic char *shiftNames[4] = {
2214f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee    "lsl",
2314f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee    "lsr",
2414f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee    "asr",
2514f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee    "ror"};
2614f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee
27ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Decode and print a ARM register name */
2818c990ebab4475335a5b94ac6077d3482b6875b9Ben Chengstatic char * decodeRegList(ArmOpcode opcode, int vector, char *buf)
29ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
30ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int i;
31ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    bool printed = false;
32ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    buf[0] = 0;
3318c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng    for (i = 0; i < 16; i++, vector >>= 1) {
34ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (vector & 0x1) {
3518c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            int regId = i;
3618c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            if (opcode == kThumbPush && i == 8) {
3718c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                regId = rlr;
3818c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            } else if (opcode == kThumbPop && i == 8) {
3918c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                regId = rpc;
4018c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng            }
41ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            if (printed) {
4218c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                sprintf(buf + strlen(buf), ", r%d", regId);
43ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            } else {
44ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                printed = true;
4518c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                sprintf(buf, "r%d", regId);
46ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            }
47ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
48ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
49ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return buf;
50ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
51ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
527ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbeestatic int expandImmediate(int value)
537ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee{
547ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    int mode = (value & 0xf00) >> 8;
557ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    u4 bits = value & 0xff;
567ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    switch(mode) {
577ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee        case 0:
587ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            return bits;
597ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee       case 1:
607ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            return (bits << 16) | bits;
617ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee       case 2:
627ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            return (bits << 24) | (bits << 8);
637ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee       case 3:
647ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            return (bits << 24) | (bits << 16) | (bits << 8) | bits;
657ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee      default:
667ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            break;
677ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    }
687ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    bits = (bits | 0x80) << 24;
697ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    return bits >> (((value & 0xf80) >> 7) - 8);
707ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee}
717ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee
72ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
73ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Interpret a format string and build a string no longer than size
74ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * See format key in Assemble.c.
75ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
7689efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbeestatic void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
77ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                            unsigned char *baseAddr, int size)
78ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int i;
80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char *bufEnd = &buf[size-1];
81ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char *fmtEnd = &fmt[strlen(fmt)];
82ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char tbuf[256];
83ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee    char *name;
84ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char nc;
85ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    while (fmt < fmtEnd) {
86ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        int operand;
87ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (*fmt == '!') {
88ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            fmt++;
89ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            assert(fmt < fmtEnd);
90ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            nc = *fmt++;
91ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            if (nc=='!') {
92ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                strcpy(tbuf, "!");
93ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            } else {
94ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               assert(fmt < fmtEnd);
95270c1d64a192341be842f46734054c692bac061eBill Buzbee               assert((unsigned)(nc-'0') < 4);
96ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               operand = lir->operands[nc-'0'];
97ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               switch(*fmt++) {
9814f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                   case 'H':
9914f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                       if (operand != 0) {
10014f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                           sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3],
10114f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                                   operand >> 2);
10214f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                       } else {
10314f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                           strcpy(tbuf,"");
10414f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                       }
10514f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                       break;
106ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                   case 'B':
107ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                       switch (operand) {
108ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kSY:
109ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "sy";
110ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
111ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kST:
112ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "st";
113ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
114ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kISH:
115ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "ish";
116ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
117ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kISHST:
118ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "ishst";
119ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
120ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kNSH:
121ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "nsh";
122ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
123ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kNSHST:
124ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "shst";
125ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
126ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           default:
127ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "DecodeError";
128ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
129ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                       }
130ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                       strcpy(tbuf, name);
131ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                       break;
132a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                   case 'b':
133a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                       strcpy(tbuf,"0000");
134a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                       for (i=3; i>= 0; i--) {
135a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                           tbuf[i] += operand & 1;
136a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                           operand >>= 1;
137a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                       }
138a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                       break;
139270c1d64a192341be842f46734054c692bac061eBill Buzbee                   case 'n':
140270c1d64a192341be842f46734054c692bac061eBill Buzbee                       operand = ~expandImmediate(operand);
141270c1d64a192341be842f46734054c692bac061eBill Buzbee                       sprintf(tbuf,"%d [0x%x]", operand, operand);
142270c1d64a192341be842f46734054c692bac061eBill Buzbee                       break;
1437ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                   case 'm':
1447ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                       operand = expandImmediate(operand);
1457ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                       sprintf(tbuf,"%d [0x%x]", operand, operand);
1467ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                       break;
1479727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                   case 's':
1489727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                       sprintf(tbuf,"s%d",operand & FP_REG_MASK);
1499727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                       break;
1509727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                   case 'S':
1519727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                       sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
1529727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                       break;
153ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'h':
154ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"%04x", operand);
155ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
1567ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                   case 'M':
157ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'd':
158ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"%d", operand);
159ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
160ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'E':
161ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"%d", operand*4);
162ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
163ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'F':
164ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"%d", operand*2);
165ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
166ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'c':
167ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       switch (operand) {
1681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondEq:
169a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "eq");
170ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondNe:
172a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "ne");
173ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondLt:
175a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "lt");
176ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondGe:
178a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "ge");
179ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondGt:
181a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "gt");
182ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondLe:
184a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "le");
185ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1861465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondCs:
187a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "cs");
188ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1891465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondMi:
190a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "mi");
1917ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                               break;
192ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                           default:
193ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               strcpy(tbuf, "");
194ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
195ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       }
196ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
197ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 't':
198ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"0x%08x",
199ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               (int) baseAddr + lir->generic.offset + 4 +
200ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               (operand << 1));
201ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
202ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'u': {
203ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       int offset_1 = lir->operands[0];
204ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       int offset_2 = NEXT_LIR(lir)->operands[0];
205ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       intptr_t target =
206ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                           ((((intptr_t) baseAddr + lir->generic.offset + 4) &
207ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                            ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
208ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                           0xfffffffc;
209ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf, "%p", (void *) target);
210ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
211ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                    }
212ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
213ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   /* Nothing to print for BLX_2 */
214ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'v':
215ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       strcpy(tbuf, "see above");
216ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
217ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'R':
21818c990ebab4475335a5b94ac6077d3482b6875b9Ben Cheng                       decodeRegList(lir->opcode, operand, tbuf);
219ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
220ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   default:
221ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       strcpy(tbuf,"DecodeError");
222ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
223ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               }
224ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               if (buf+strlen(tbuf) <= bufEnd) {
225ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   strcpy(buf, tbuf);
226ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   buf += strlen(tbuf);
227ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               } else {
228ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   break;
229ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               }
230ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            }
231ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        } else {
232ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng           *buf++ = *fmt++;
233ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
234ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (buf == bufEnd)
235ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
236ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
237ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    *buf = 0;
238ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
239ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
240d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Chengvoid dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
241d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng{
242d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    char buf[256];
243d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    buf[0] = 0;
244d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    ArmLIR *armLIR = (ArmLIR *) lir;
245d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
246d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    if (mask == ENCODE_ALL) {
247d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        strcpy(buf, "all");
248d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    } else {
249d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        char num[8];
250d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        int i;
251d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
252d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        for (i = 0; i < kRegEnd; i++) {
253d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            if (mask & (1ULL << i)) {
254d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                sprintf(num, "%d ", i);
255d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                strcat(buf, num);
256d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            }
257d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        }
258d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
259d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        if (mask & ENCODE_CCODE) {
260d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            strcat(buf, "cc ");
261d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        }
262d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        if (mask & ENCODE_FP_STATUS) {
263d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            strcat(buf, "fpcc ");
264d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        }
265d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        if (armLIR && (mask & ENCODE_DALVIK_REG)) {
266d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
267d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                    (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
268d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        }
269d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
270d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    if (buf[0]) {
271d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        LOGD("%s: %s", prefix, buf);
272d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
273d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng}
274d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
275d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng/*
276d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * Debugging macros
277d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng */
278d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng#define DUMP_RESOURCE_MASK(X)
279d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng#define DUMP_SSA_REP(X)
280d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
281ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Pretty-print a LIR instruction */
282d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Chengvoid dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
283ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
28489efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee    ArmLIR *lir = (ArmLIR *) arg;
285ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char buf[256];
286ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char opName[256];
287ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int offset = lir->generic.offset;
288ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int dest = lir->operands[0];
289d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    const bool dumpNop = false;
290d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
291ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Handle pseudo-ops individually, and all regular insns as a group */
2929a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch(lir->opcode) {
293cec26f6ae3347d5ab3d60de02caca2e47151c6b2Ben Cheng        case kArmChainingCellBottom:
294cec26f6ae3347d5ab3d60de02caca2e47151c6b2Ben Cheng            LOGD("-------- end of chaining cells (0x%04x)\n", offset);
295cec26f6ae3347d5ab3d60de02caca2e47151c6b2Ben Cheng            break;
2961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoBarrier:
297d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            LOGD("-------- BARRIER");
298dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng            break;
2991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoExtended:
3007a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            LOGD("-------- %s\n", (char *) dest);
3017a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            break;
3021465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoSSARep:
303d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            DUMP_SSA_REP(LOGD("-------- %s\n", (char *) dest));
3044238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            break;
3051465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoTargetLabel:
306ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
307a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellBackwardBranch:
3084238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest);
3094238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            break;
310a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellNormal:
3111efc9c5e4c5c4c2fccde18e5771c68d064c33bd3Ben Cheng            LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
312ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
313a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellHot:
3141efc9c5e4c5c4c2fccde18e5771c68d064c33bd3Ben Cheng            LOGD("-------- chaining cell (hot): 0x%04x\n", dest);
315ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
316a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellInvokePredicted:
31738329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng            LOGD("-------- chaining cell (predicted)\n");
31838329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng            break;
319a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellInvokeSingleton:
32038329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng            LOGD("-------- chaining cell (invoke singleton): %s/%p\n",
321ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                 ((Method *)dest)->name,
322ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                 ((Method *)dest)->insns);
323ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
324a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoEntryBlock:
3254238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            LOGD("-------- entry offset: 0x%04x\n", dest);
32697319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao            break;
327a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoDalvikByteCodeBoundary:
328ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
329ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng                 (char *) lir->operands[1]);
330ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
331a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoExitBlock:
3324238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            LOGD("-------- exit offset: 0x%04x\n", dest);
3334238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            break;
3341465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoPseudoAlign4:
335ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
336ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
337a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoPCReconstructionCell:
338ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest,
339ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                 lir->operands[1]);
340ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
341a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoPCReconstructionBlockLabel:
342ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            /* Do nothing */
343ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
3441465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoEHBlockLabel:
345ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("Exception_Handling:\n");
346ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
3471465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoNormalBlockLabel:
348ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("L%#06x:\n", dest);
349ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
350ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
351d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            if (lir->isNop && !dumpNop) {
352e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                break;
353e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            }
3549a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            buildInsnString(EncodingMap[lir->opcode].name, lir, opName,
355ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                            baseAddr, 256);
3569a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            buildInsnString(EncodingMap[lir->opcode].fmt, lir, buf, baseAddr,
357ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                            256);
358d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            LOGD("%p (%04x): %-8s%s%s\n",
359d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                 baseAddr + offset, offset, opName, buf,
360d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                 lir->isNop ? "(nop)" : "");
361ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
362ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
363d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
364d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    if (lir->useMask && (!lir->isNop || dumpNop)) {
365d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
366d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                                               lir->useMask, "use"));
367d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
368d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    if (lir->defMask && (!lir->isNop || dumpNop)) {
369d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
370d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                                               lir->defMask, "def"));
371d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
372ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
373ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
374ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Dump instructions and constant pool contents */
375ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerCodegenDump(CompilationUnit *cUnit)
376ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
377ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    LOGD("Dumping LIR insns\n");
378ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    LIR *lirInsn;
37989efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee    ArmLIR *armLIR;
380ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
381ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    LOGD("installed code is at %p\n", cUnit->baseAddr);
382ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    LOGD("total size is %d bytes\n", cUnit->totalSize);
383ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
384fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr);
385ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
386ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
38789efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee        armLIR = (ArmLIR *) lirInsn;
388ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        LOGD("%p (%04x): .word (0x%x)\n",
389dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng             (char*)cUnit->baseAddr + armLIR->generic.offset,
390dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng             armLIR->generic.offset,
391ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng             armLIR->operands[0]);
392ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
393ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
39413fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee
39513fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee/* Target-specific cache flushing */
39613fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbeeint dvmCompilerCacheFlush(long start, long end, long flags)
39713fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee{
39813fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee    return cacheflush(start, end, flags);
39913fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee}
400