diff options
Diffstat (limited to 'vm/compiler/codegen/arm')
-rw-r--r-- | vm/compiler/codegen/arm/ArchUtility.c | 16 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/ArmLIR.h | 2 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Assemble.c | 2 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Thumb2/Factory.c | 26 |
4 files changed, 35 insertions, 11 deletions
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, #<const> [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", "<!0R>", 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); } |