ArchUtility.cpp revision 13fbc2e4bfa04cce8e181ac37d7f2b13a54aa037
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 */
28ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengstatic char * decodeRegList(int vector, char *buf)
29ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
30ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int i;
31ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    bool printed = false;
32ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    buf[0] = 0;
33ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    for (i = 0; i < 8; i++, vector >>= 1) {
34ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (vector & 0x1) {
35ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            if (printed) {
36ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                sprintf(buf + strlen(buf), ", r%d", i);
37ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            } else {
38ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                printed = true;
39ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                sprintf(buf, "r%d", i);
40ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            }
41ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
42ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
43ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    return buf;
44ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
45ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
467ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbeestatic int expandImmediate(int value)
477ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee{
487ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    int mode = (value & 0xf00) >> 8;
497ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    u4 bits = value & 0xff;
507ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    switch(mode) {
517ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee        case 0:
527ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            return bits;
537ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee       case 1:
547ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            return (bits << 16) | bits;
557ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee       case 2:
567ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            return (bits << 24) | (bits << 8);
577ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee       case 3:
587ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            return (bits << 24) | (bits << 16) | (bits << 8) | bits;
597ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee      default:
607ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee            break;
617ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    }
627ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    bits = (bits | 0x80) << 24;
637ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee    return bits >> (((value & 0xf80) >> 7) - 8);
647ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee}
657ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee
66ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/*
67ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * Interpret a format string and build a string no longer than size
68ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * See format key in Assemble.c.
69ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */
7089efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbeestatic void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
71ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                            unsigned char *baseAddr, int size)
72ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
73ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int i;
74ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char *bufEnd = &buf[size-1];
75ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char *fmtEnd = &fmt[strlen(fmt)];
76ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char tbuf[256];
77ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee    char *name;
78ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char nc;
79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    while (fmt < fmtEnd) {
80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        int operand;
81ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (*fmt == '!') {
82ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            fmt++;
83ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            assert(fmt < fmtEnd);
84ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            nc = *fmt++;
85ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            if (nc=='!') {
86ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                strcpy(tbuf, "!");
87ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            } else {
88ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               assert(fmt < fmtEnd);
89270c1d64a192341be842f46734054c692bac061eBill Buzbee               assert((unsigned)(nc-'0') < 4);
90ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               operand = lir->operands[nc-'0'];
91ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               switch(*fmt++) {
9214f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                   case 'H':
9314f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                       if (operand != 0) {
9414f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                           sprintf(tbuf, ", %s %d",shiftNames[operand & 0x3],
9514f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                                   operand >> 2);
9614f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                       } else {
9714f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                           strcpy(tbuf,"");
9814f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                       }
9914f711ba6ffea52d6000e7d442d01b684bbe7f97buzbee                       break;
100ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                   case 'B':
101ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                       switch (operand) {
102ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kSY:
103ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "sy";
104ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
105ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kST:
106ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "st";
107ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
108ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kISH:
109ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "ish";
110ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
111ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kISHST:
112ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "ishst";
113ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
114ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kNSH:
115ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "nsh";
116ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
117ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           case kNSHST:
118ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "shst";
119ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
120ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                           default:
121ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               name = "DecodeError";
122ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                               break;
123ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                       }
124ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                       strcpy(tbuf, name);
125ecf8f6ede2c00350a36297dd7427afff9d9cb154buzbee                       break;
126a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                   case 'b':
127a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                       strcpy(tbuf,"0000");
128a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                       for (i=3; i>= 0; i--) {
129a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                           tbuf[i] += operand & 1;
130a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                           operand >>= 1;
131a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                       }
132a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                       break;
133270c1d64a192341be842f46734054c692bac061eBill Buzbee                   case 'n':
134270c1d64a192341be842f46734054c692bac061eBill Buzbee                       operand = ~expandImmediate(operand);
135270c1d64a192341be842f46734054c692bac061eBill Buzbee                       sprintf(tbuf,"%d [0x%x]", operand, operand);
136270c1d64a192341be842f46734054c692bac061eBill Buzbee                       break;
1377ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                   case 'm':
1387ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                       operand = expandImmediate(operand);
1397ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                       sprintf(tbuf,"%d [0x%x]", operand, operand);
1407ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                       break;
1419727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                   case 's':
1429727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                       sprintf(tbuf,"s%d",operand & FP_REG_MASK);
1439727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                       break;
1449727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                   case 'S':
1459727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                       sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
1469727c3de12ab9daed0d92f6da2f5c0b0169e698dBill Buzbee                       break;
147ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'h':
148ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"%04x", operand);
149ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
1507ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                   case 'M':
151ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'd':
152ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"%d", operand);
153ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
154ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'E':
155ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"%d", operand*4);
156ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
157ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'F':
158ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"%d", operand*2);
159ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
160ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'c':
161ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       switch (operand) {
1621465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondEq:
163a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "eq");
164ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1651465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondNe:
166a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "ne");
167ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1681465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondLt:
169a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "lt");
170ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1711465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondGe:
172a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "ge");
173ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1741465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondGt:
175a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "gt");
176ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1771465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondLe:
178a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "le");
179ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1801465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondCs:
181a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "cs");
182ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
1831465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee                           case kArmCondMi:
184a4a7f0708e75eefae8cf9fff3f9e15699f7881beBill Buzbee                               strcpy(tbuf, "mi");
1857ea0f64d067cd8a2213c2c04a3291335c34d9602Bill Buzbee                               break;
186ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                           default:
187ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               strcpy(tbuf, "");
188ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               break;
189ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       }
190ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
191ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 't':
192ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf,"0x%08x",
193ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               (int) baseAddr + lir->generic.offset + 4 +
194ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                               (operand << 1));
195ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
196ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'u': {
197ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       int offset_1 = lir->operands[0];
198ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       int offset_2 = NEXT_LIR(lir)->operands[0];
199ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       intptr_t target =
200ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                           ((((intptr_t) baseAddr + lir->generic.offset + 4) &
201ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                            ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
202ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                           0xfffffffc;
203ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       sprintf(tbuf, "%p", (void *) target);
204ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
205ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                    }
206ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
207ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   /* Nothing to print for BLX_2 */
208ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'v':
209ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       strcpy(tbuf, "see above");
210ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
211ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   case 'R':
212ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       decodeRegList(operand, tbuf);
213ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
214ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   default:
215ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       strcpy(tbuf,"DecodeError");
216ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                       break;
217ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               }
218ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               if (buf+strlen(tbuf) <= bufEnd) {
219ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   strcpy(buf, tbuf);
220ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   buf += strlen(tbuf);
221ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               } else {
222ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                   break;
223ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng               }
224ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            }
225ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        } else {
226ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng           *buf++ = *fmt++;
227ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        }
228ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        if (buf == bufEnd)
229ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
230ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
231ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    *buf = 0;
232ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
233ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
234d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Chengvoid dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
235d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng{
236d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    char buf[256];
237d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    buf[0] = 0;
238d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    ArmLIR *armLIR = (ArmLIR *) lir;
239d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
240d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    if (mask == ENCODE_ALL) {
241d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        strcpy(buf, "all");
242d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    } else {
243d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        char num[8];
244d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        int i;
245d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
246d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        for (i = 0; i < kRegEnd; i++) {
247d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            if (mask & (1ULL << i)) {
248d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                sprintf(num, "%d ", i);
249d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                strcat(buf, num);
250d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            }
251d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        }
252d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
253d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        if (mask & ENCODE_CCODE) {
254d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            strcat(buf, "cc ");
255d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        }
256d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        if (mask & ENCODE_FP_STATUS) {
257d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            strcat(buf, "fpcc ");
258d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        }
259d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        if (armLIR && (mask & ENCODE_DALVIK_REG)) {
260d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
261d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                    (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
262d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        }
263d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
264d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    if (buf[0]) {
265d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        LOGD("%s: %s", prefix, buf);
266d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
267d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng}
268d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
269d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng/*
270d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng * Debugging macros
271d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng */
272d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng#define DUMP_RESOURCE_MASK(X)
273d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng#define DUMP_SSA_REP(X)
274d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
275ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Pretty-print a LIR instruction */
276d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Chengvoid dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
277ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
27889efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee    ArmLIR *lir = (ArmLIR *) arg;
279ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char buf[256];
280ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    char opName[256];
281ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int offset = lir->generic.offset;
282ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    int dest = lir->operands[0];
283d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    const bool dumpNop = false;
284d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
285ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    /* Handle pseudo-ops individually, and all regular insns as a group */
2869a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    switch(lir->opcode) {
287cec26f6ae3347d5ab3d60de02caca2e47151c6b2Ben Cheng        case kArmChainingCellBottom:
288cec26f6ae3347d5ab3d60de02caca2e47151c6b2Ben Cheng            LOGD("-------- end of chaining cells (0x%04x)\n", offset);
289cec26f6ae3347d5ab3d60de02caca2e47151c6b2Ben Cheng            break;
2901465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoBarrier:
291d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            LOGD("-------- BARRIER");
292dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng            break;
2931465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoExtended:
2947a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            LOGD("-------- %s\n", (char *) dest);
2957a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            break;
2961465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoSSARep:
297d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            DUMP_SSA_REP(LOGD("-------- %s\n", (char *) dest));
2984238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            break;
2991465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoTargetLabel:
300ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
301a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellBackwardBranch:
3024238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest);
3034238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            break;
304a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellNormal:
3051efc9c5e4c5c4c2fccde18e5771c68d064c33bd3Ben Cheng            LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
306ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
307a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellHot:
3081efc9c5e4c5c4c2fccde18e5771c68d064c33bd3Ben Cheng            LOGD("-------- chaining cell (hot): 0x%04x\n", dest);
309ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
310a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellInvokePredicted:
31138329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng            LOGD("-------- chaining cell (predicted)\n");
31238329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng            break;
313a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoChainingCellInvokeSingleton:
31438329f5678fd7a4879528b02a0ab60322d38a897Ben Cheng            LOGD("-------- chaining cell (invoke singleton): %s/%p\n",
315ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                 ((Method *)dest)->name,
316ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                 ((Method *)dest)->insns);
317ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
318a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoEntryBlock:
3194238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            LOGD("-------- entry offset: 0x%04x\n", dest);
32097319a8a234e9fe1cf90ca39aa6eca37d729afd5Jeff Hao            break;
321a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoDalvikByteCodeBoundary:
322ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
323ccd6c0102d1f898aaea1c94761167fdd083b5275Ben Cheng                 (char *) lir->operands[1]);
324ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
325a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoExitBlock:
3264238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            LOGD("-------- exit offset: 0x%04x\n", dest);
3274238ec2ad1ace5103b2206a483f5f03d2e96c476Ben Cheng            break;
3281465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoPseudoAlign4:
329ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
330ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
331a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoPCReconstructionCell:
332ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest,
333ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                 lir->operands[1]);
334ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
335a497359afa1abe4c5780c8799c6fe0edab551c2dBen Cheng        case kArmPseudoPCReconstructionBlockLabel:
336ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            /* Do nothing */
337ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
3381465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoEHBlockLabel:
339ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("Exception_Handling:\n");
340ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
3411465db5ee2d3c4c4dcc8e017a294172e858765cbBill Buzbee        case kArmPseudoNormalBlockLabel:
342ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            LOGD("L%#06x:\n", dest);
343ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
344ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        default:
345d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            if (lir->isNop && !dumpNop) {
346e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng                break;
347e9695e5d281ad8bfbe3091e825befbedfc1b2007Ben Cheng            }
3489a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            buildInsnString(EncodingMap[lir->opcode].name, lir, opName,
349ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                            baseAddr, 256);
3509a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein            buildInsnString(EncodingMap[lir->opcode].fmt, lir, buf, baseAddr,
351ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng                            256);
352d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng            LOGD("%p (%04x): %-8s%s%s\n",
353d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                 baseAddr + offset, offset, opName, buf,
354d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                 lir->isNop ? "(nop)" : "");
355ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng            break;
356ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
357d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng
358d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    if (lir->useMask && (!lir->isNop || dumpNop)) {
359d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
360d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                                               lir->useMask, "use"));
361d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
362d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    if (lir->defMask && (!lir->isNop || dumpNop)) {
363d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng        DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
364d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng                                               lir->defMask, "def"));
365d7d426a1d746f70edeaeccf77886f3ad8298e28cBen Cheng    }
366ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
367ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
368ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng/* Dump instructions and constant pool contents */
369ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengvoid dvmCompilerCodegenDump(CompilationUnit *cUnit)
370ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng{
371ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    LOGD("Dumping LIR insns\n");
372ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    LIR *lirInsn;
37389efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee    ArmLIR *armLIR;
374ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng
375ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    LOGD("installed code is at %p\n", cUnit->baseAddr);
376ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    LOGD("total size is %d bytes\n", cUnit->totalSize);
377ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
378fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr);
379ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
380ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
38189efc3d632adfa076bd622369b1ad8e4b49cf20eBill Buzbee        armLIR = (ArmLIR *) lirInsn;
382ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng        LOGD("%p (%04x): .word (0x%x)\n",
383dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng             (char*)cUnit->baseAddr + armLIR->generic.offset,
384dcf3e5d43a1831a166f70cb9e0694cd4b0b356b0Ben Cheng             armLIR->generic.offset,
385ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng             armLIR->operands[0]);
386ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng    }
387ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng}
38813fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee
38913fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee/* Target-specific cache flushing */
39013fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbeeint dvmCompilerCacheFlush(long start, long end, long flags)
39113fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee{
39213fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee    return cacheflush(start, end, flags);
39313fbc2e4bfa04cce8e181ac37d7f2b13a54aa037buzbee}
394