summaryrefslogtreecommitdiffstats
path: root/vm/compiler/codegen/arm/ArchUtility.c
diff options
context:
space:
mode:
authorBill Buzbee <buzbee@google.com>2009-07-28 11:22:22 -0700
committerBill Buzbee <buzbee@google.com>2009-07-28 11:22:22 -0700
commit89efc3d632adfa076bd622369b1ad8e4b49cf20e (patch)
tree8fef4780be23cea9ae084e060ea0e92478c64311 /vm/compiler/codegen/arm/ArchUtility.c
parente2557513420f6be2d70c19a4d826731174c828d1 (diff)
downloadandroid_dalvik-89efc3d632adfa076bd622369b1ad8e4b49cf20e.tar.gz
android_dalvik-89efc3d632adfa076bd622369b1ad8e4b49cf20e.tar.bz2
android_dalvik-89efc3d632adfa076bd622369b1ad8e4b49cf20e.zip
Stage 2 of structural changes for support of THUMB2. No logic changes.
Diffstat (limited to 'vm/compiler/codegen/arm/ArchUtility.c')
-rw-r--r--vm/compiler/codegen/arm/ArchUtility.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c
new file mode 100644
index 000000000..6d1a261bb
--- /dev/null
+++ b/vm/compiler/codegen/arm/ArchUtility.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../../CompilerInternals.h"
+#include "dexdump/OpCodeNames.h"
+#include "ArmLIR.h"
+
+/* Decode and print a ARM register name */
+static char * decodeRegList(int vector, char *buf)
+{
+ int i;
+ bool printed = false;
+ buf[0] = 0;
+ for (i = 0; i < 8; i++, vector >>= 1) {
+ if (vector & 0x1) {
+ if (printed) {
+ sprintf(buf + strlen(buf), ", r%d", i);
+ } else {
+ printed = true;
+ sprintf(buf, "r%d", i);
+ }
+ }
+ }
+ return buf;
+}
+
+/*
+ * Interpret a format string and build a string no longer than size
+ * See format key in Assemble.c.
+ */
+static void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
+ unsigned char *baseAddr, int size)
+{
+ int i;
+ char *bufEnd = &buf[size-1];
+ char *fmtEnd = &fmt[strlen(fmt)];
+ char tbuf[256];
+ char nc;
+ while (fmt < fmtEnd) {
+ int operand;
+ if (*fmt == '!') {
+ fmt++;
+ assert(fmt < fmtEnd);
+ nc = *fmt++;
+ if (nc=='!') {
+ strcpy(tbuf, "!");
+ } else {
+ assert(fmt < fmtEnd);
+ assert((unsigned)(nc-'0') < 3);
+ operand = lir->operands[nc-'0'];
+ switch(*fmt++) {
+ case 'h':
+ sprintf(tbuf,"%04x", operand);
+ break;
+ case 'd':
+ sprintf(tbuf,"%d", operand);
+ break;
+ case 'D':
+ sprintf(tbuf,"%d", operand+8);
+ break;
+ case 'E':
+ sprintf(tbuf,"%d", operand*4);
+ break;
+ case 'F':
+ sprintf(tbuf,"%d", operand*2);
+ break;
+ case 'c':
+ switch (operand) {
+ case ARM_COND_EQ:
+ strcpy(tbuf, "beq");
+ break;
+ case ARM_COND_NE:
+ strcpy(tbuf, "bne");
+ break;
+ case ARM_COND_LT:
+ strcpy(tbuf, "blt");
+ break;
+ case ARM_COND_GE:
+ strcpy(tbuf, "bge");
+ break;
+ case ARM_COND_GT:
+ strcpy(tbuf, "bgt");
+ break;
+ case ARM_COND_LE:
+ strcpy(tbuf, "ble");
+ break;
+ case ARM_COND_CS:
+ strcpy(tbuf, "bcs");
+ break;
+ default:
+ strcpy(tbuf, "");
+ break;
+ }
+ break;
+ case 't':
+ sprintf(tbuf,"0x%08x",
+ (int) baseAddr + lir->generic.offset + 4 +
+ (operand << 1));
+ break;
+ case 'u': {
+ int offset_1 = lir->operands[0];
+ int offset_2 = NEXT_LIR(lir)->operands[0];
+ intptr_t target =
+ ((((intptr_t) baseAddr + lir->generic.offset + 4) &
+ ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
+ 0xfffffffc;
+ sprintf(tbuf, "%p", (void *) target);
+ break;
+ }
+
+ /* Nothing to print for BLX_2 */
+ case 'v':
+ strcpy(tbuf, "see above");
+ break;
+ case 'R':
+ decodeRegList(operand, tbuf);
+ break;
+ default:
+ strcpy(tbuf,"DecodeError");
+ break;
+ }
+ if (buf+strlen(tbuf) <= bufEnd) {
+ strcpy(buf, tbuf);
+ buf += strlen(tbuf);
+ } else {
+ break;
+ }
+ }
+ } else {
+ *buf++ = *fmt++;
+ }
+ if (buf == bufEnd)
+ break;
+ }
+ *buf = 0;
+}
+
+/* Pretty-print a LIR instruction */
+static void dumpLIRInsn(LIR *arg, unsigned char *baseAddr)
+{
+ ArmLIR *lir = (ArmLIR *) arg;
+ char buf[256];
+ char opName[256];
+ int offset = lir->generic.offset;
+ int dest = lir->operands[0];
+ u2 *cPtr = (u2*)baseAddr;
+ /* Handle pseudo-ops individually, and all regular insns as a group */
+ switch(lir->opCode) {
+ case ARM_PSEUDO_TARGET_LABEL:
+ break;
+ case ARM_PSEUDO_CHAINING_CELL_NORMAL:
+ LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
+ break;
+ case ARM_PSEUDO_CHAINING_CELL_HOT:
+ LOGD("-------- chaining cell (hot): 0x%04x\n", dest);
+ break;
+ case ARM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED:
+ LOGD("-------- chaining cell (predicted)\n");
+ break;
+ case ARM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON:
+ LOGD("-------- chaining cell (invoke singleton): %s/%p\n",
+ ((Method *)dest)->name,
+ ((Method *)dest)->insns);
+ break;
+ case ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY:
+ LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
+ getOpcodeName(lir->operands[1]));
+ break;
+ case ARM_PSEUDO_ALIGN4:
+ LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
+ break;
+ case ARM_PSEUDO_PC_RECONSTRUCTION_CELL:
+ LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest,
+ lir->operands[1]);
+ break;
+ case ARM_PSEUDO_PC_RECONSTRUCTION_BLOCK_LABEL:
+ /* Do nothing */
+ break;
+ case ARM_PSEUDO_EH_BLOCK_LABEL:
+ LOGD("Exception_Handling:\n");
+ break;
+ case ARM_PSEUDO_NORMAL_BLOCK_LABEL:
+ LOGD("L%#06x:\n", dest);
+ break;
+ default:
+ if (lir->isNop) {
+ break;
+ }
+ buildInsnString(EncodingMap[lir->opCode].name, lir, opName,
+ baseAddr, 256);
+ buildInsnString(EncodingMap[lir->opCode].fmt, lir, buf, baseAddr,
+ 256);
+ LOGD("%p (%04x): %-8s%s\n",
+ baseAddr + offset, offset, opName, buf);
+ break;
+ }
+}
+
+/* Dump instructions and constant pool contents */
+void dvmCompilerCodegenDump(CompilationUnit *cUnit)
+{
+ LOGD("Dumping LIR insns\n");
+ LIR *lirInsn;
+ ArmLIR *armLIR;
+
+ LOGD("installed code is at %p\n", cUnit->baseAddr);
+ LOGD("total size is %d bytes\n", cUnit->totalSize);
+ for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
+ dumpLIRInsn(lirInsn, cUnit->baseAddr);
+ }
+ for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
+ armLIR = (ArmLIR *) lirInsn;
+ LOGD("%p (%04x): .word (0x%x)\n",
+ (char*)cUnit->baseAddr + armLIR->generic.offset, armLIR->generic.offset,
+ armLIR->operands[0]);
+ }
+}