diff options
Diffstat (limited to 'src/compiler/codegen')
| -rw-r--r-- | src/compiler/codegen/arm/ArmLIR.h | 2 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Assemble.cc | 34 |
2 files changed, 36 insertions, 0 deletions
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h index daa13962c0..1e4022ee4b 100644 --- a/src/compiler/codegen/arm/ArmLIR.h +++ b/src/compiler/codegen/arm/ArmLIR.h @@ -693,6 +693,8 @@ typedef enum ArmOpcode { kThumb2SubsRRI12, /* setflags encoding */ kThumb2OrrRRRs, /* orrx [111010100101] rn[19..16] [0000] rd[11..8] [0000] rm[3..0] */ + kThumb2Push1, /* t3 encoding of push */ + kThumb2Pop1, /* t3 encoding of pop */ kArmLast, } ArmOpcode; diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc index bbd97b4d75..af71efe988 100644 --- a/src/compiler/codegen/arm/Assemble.cc +++ b/src/compiler/codegen/arm/Assemble.cc @@ -953,6 +953,16 @@ ArmEncodingMap EncodingMap[kArmLast] = { kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtBitBlt, 3, 0, kFmtShift, -1, -1, IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES, "orrs", "!0C, !1C, !2C!3H", 2), + ENCODING_MAP(kThumb2Push1, 0xf84d0d04, + kFmtBitBlt, 15, 12, kFmtUnused, -1, -1, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, + IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE0 + | IS_STORE, "push1", "!0C", 2), + ENCODING_MAP(kThumb2Pop1, 0xf85d0b04, + kFmtBitBlt, 15, 12, kFmtUnused, -1, -1, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, + IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF0 + | IS_LOAD, "pop1", "!0C", 2), }; @@ -1167,6 +1177,30 @@ STATIC AssemblerStatus assembleInstructions(CompilationUnit* cUnit, } else { lir->operands[1] = delta >> 1; } + } else if (lir->opcode == kThumb2Push || + lir->opcode == kThumb2Pop) { + if (__builtin_popcount(lir->operands[0]) == 1) { + /* + * The standard push/pop multiple instruction + * requires at least two registers in the list. + * If we've got just one, switch to the single-reg + * encoding. + */ + lir->opcode = (lir->opcode == kThumb2Push) + ? kThumb2Push1 : kThumb2Pop1; + int reg = 0; + while (lir->operands[0]) { + if (lir->operands[0] & 0x1) { + break; + } else { + reg++; + lir->operands[0] >>= 1; + } + } + lir->operands[0] = reg; + oatSetupResourceMasks(lir); + res = kRetryAll; + } } else if (lir->opcode == kThumbBCond || lir->opcode == kThumb2BCond) { ArmLIR *targetLIR = (ArmLIR *) lir->generic.target; |