diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 15ab4557dea..e3a9742bc76 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -369,6 +369,15 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1 in { let Inst{2-0} = 0b000; } + def tBX_Rm : TI<(outs), (ins pred:$p, GPR:$Rm), IIC_Br, "bx${p}\t$Rm", + [/* for disassembly only */]>, + T1Special<{1,1,0,?}> { + // A6.2.3 & A8.6.25 + bits<4> Rm; + let Inst{6-3} = Rm; + let Inst{2-0} = 0b000; + } + // Alternative return instruction used by vararg functions. def tBX_RET_vararg : TI<(outs), (ins tGPR:$Rm), IIC_Br, "bx\t$Rm", diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index 727fc1332ad..85816e02fef 100644 --- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -485,10 +485,13 @@ static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, return true; // BX/BLX has 1 reg operand: Rm. - if (NumOps == 1) { + if (Opcode == ARM::tBLXr_r9 || Opcode == ARM::tBX_Rm) { + // Handling the two predicate operands before the reg operand. + if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps)) + return false; MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, getT1Rm(insn)))); - NumOpsAdded = 1; + NumOpsAdded = 3; return true; } diff --git a/test/MC/Disassembler/ARM/thumb-tests.txt b/test/MC/Disassembler/ARM/thumb-tests.txt index 03a1451d1da..c3a15d012fd 100644 --- a/test/MC/Disassembler/ARM/thumb-tests.txt +++ b/test/MC/Disassembler/ARM/thumb-tests.txt @@ -214,3 +214,12 @@ # CHECK: lsr.w r10, r0, #32 0x4f 0xea 0x10 0x0a + +# CHECK: blx sp +0xe8 0x47 + +# CHECK: bx lr +0x70 0x47 + +# CHECK: bx pc +0x78 0x47 diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index e48ac1e6788..07ff213bed9 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1624,6 +1624,10 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr") return false; + // A8.6.25 BX. Use the generic tBX_Rm, ignore tBX_RET and tBX_RET_vararg. + if (Name == "tBX_RET" || Name == "tBX_RET_vararg") + return false; + // Ignore the TPsoft (TLS) instructions, which conflict with tBLr9. if (Name == "tTPsoft" || Name == "t2TPsoft") return false;