From: Ben Cheng Date: Mon, 24 Jan 2011 18:14:29 +0000 (-0800) Subject: Fix push/pop instruction selection and encoding. X-Git-Tag: android-x86-4.0-r1~156^2~259^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=18c990ebab4475335a5b94ac6077d3482b6875b9;p=android-x86%2Fdalvik.git Fix push/pop instruction selection and encoding. 1) Thumb 'push' can handle lr and 'pop' can handle pc, so make use of them. 2) Thumb2 push was incorrectly encoded as stmia, which should be stmdb instead. None of the above affect the code that we currently ship. Change-Id: I89ab46b032a3d562355c2cc3bc05fe308ba40957 --- diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c index 95b96c496..7a4d307b5 100644 --- a/vm/compiler/codegen/arm/ArchUtility.c +++ b/vm/compiler/codegen/arm/ArchUtility.c @@ -25,18 +25,24 @@ static char *shiftNames[4] = { "ror"}; /* Decode and print a ARM register name */ -static char * decodeRegList(int vector, char *buf) +static char * decodeRegList(ArmOpcode opcode, int vector, char *buf) { int i; bool printed = false; buf[0] = 0; - for (i = 0; i < 8; i++, vector >>= 1) { + for (i = 0; i < 16; i++, vector >>= 1) { if (vector & 0x1) { + int regId = i; + if (opcode == kThumbPush && i == 8) { + regId = rlr; + } else if (opcode == kThumbPop && i == 8) { + regId = rpc; + } if (printed) { - sprintf(buf + strlen(buf), ", r%d", i); + sprintf(buf + strlen(buf), ", r%d", regId); } else { printed = true; - sprintf(buf, "r%d", i); + sprintf(buf, "r%d", regId); } } } @@ -209,7 +215,7 @@ static void buildInsnString(char *fmt, ArmLIR *lir, char* buf, strcpy(tbuf, "see above"); break; case 'R': - decodeRegList(operand, tbuf); + decodeRegList(lir->opcode, operand, tbuf); break; default: strcpy(tbuf,"DecodeError"); diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h index 437c2ed96..0ee821d3f 100644 --- a/vm/compiler/codegen/arm/ArmLIR.h +++ b/vm/compiler/codegen/arm/ArmLIR.h @@ -515,7 +515,7 @@ typedef enum ArmOpcode { kThumb2StrbRRI12, /* strb rt,[rn,#imm12] [111110001000] rt[15..12] rn[19..16] imm12[11..0] */ kThumb2Pop, /* pop [1110100010111101] list[15-0]*/ - kThumb2Push, /* push [1110100010101101] list[15-0]*/ + kThumb2Push, /* push [1110100100101101] list[15-0]*/ kThumb2CmpRI8, /* cmp rn, # [11110] i [011011] rn[19-16] [0] imm3 [1111] imm8[7..0] */ kThumb2AdcRRR, /* adc [111010110101] rn[19..16] [0000] rd[11..8] diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c index aa6128593..577f68320 100644 --- a/vm/compiler/codegen/arm/Assemble.c +++ b/vm/compiler/codegen/arm/Assemble.c @@ -641,7 +641,7 @@ ArmEncodingMap EncodingMap[kArmLast] = { kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0 | IS_LOAD, "pop", "", 2), - ENCODING_MAP(kThumb2Push, 0xe8ad0000, + ENCODING_MAP(kThumb2Push, 0xe92d0000, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0 diff --git a/vm/compiler/codegen/arm/Thumb2/Factory.c b/vm/compiler/codegen/arm/Thumb2/Factory.c index f50edfe32..fb30292e7 100644 --- a/vm/compiler/codegen/arm/Thumb2/Factory.c +++ b/vm/compiler/codegen/arm/Thumb2/Factory.c @@ -234,12 +234,30 @@ static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value) { ArmOpcode opcode = kThumbBkpt; switch (op) { - case kOpPush: - opcode = ((value & 0xff00) != 0) ? kThumb2Push : kThumbPush; + case kOpPush: { + if ((value & 0xff00) == 0) { + opcode = kThumbPush; + } else if ((value & 0xff00) == (1 << rlr)) { + /* Thumb push can handle lr, which is encoded by bit 8 */ + opcode = kThumbPush; + value = (value & 0xff) | (1<<8); + } else { + opcode = kThumb2Push; + } break; - case kOpPop: - opcode = ((value & 0xff00) != 0) ? kThumb2Pop : kThumbPop; + } + case kOpPop: { + if ((value & 0xff00) == 0) { + opcode = kThumbPop; + } else if ((value & 0xff00) == (1 << rpc)) { + /* Thumb pop can handle pc, which is encoded by bit 8 */ + opcode = kThumbPop; + value = (value & 0xff) | (1<<8); + } else { + opcode = kThumb2Pop; + } break; + } default: assert(0); }