Thumb instructions which have reglist operands at the end and predicate operands

before reglist were not properly handled with respect to IT Block.  Fix that by
creating a new method ARMBasicMCBuilder::DoPredicateOperands() used by those
instructions for disassembly.  Add a test case.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101974 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Johnny Chen 2010-04-21 01:01:19 +00:00
parent 08e322db8a
commit 52d2b0ed00
4 changed files with 73 additions and 16 deletions

View File

@ -3218,6 +3218,40 @@ static uint32_t CondCode(uint32_t CondField) {
return CondField;
}
/// DoPredicateOperands - DoPredicateOperands process the predicate operands
/// of some Thumb instructions which come before the reglist operands. It
/// returns true if the two predicate operands have been processed.
bool ARMBasicMCBuilder::DoPredicateOperands(MCInst& MI, unsigned Opcode,
uint32_t /* insn */, unsigned short NumOpsRemaining) {
assert(NumOpsRemaining > 0 && "Invalid argument");
const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
unsigned Idx = MI.getNumOperands();
// First, we check whether this instr specifies the PredicateOperand through
// a pair of TargetOperandInfos with isPredicate() property.
if (NumOpsRemaining >= 2 &&
OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() &&
OpInfo[Idx].RegClass == 0 && OpInfo[Idx+1].RegClass == ARM::CCRRegClassID)
{
// If we are inside an IT block, get the IT condition bits maintained via
// ARMBasicMCBuilder::ITState[7:0], through ARMBasicMCBuilder::GetITCond().
// See also A2.5.2.
if (InITBlock())
MI.addOperand(MCOperand::CreateImm(GetITCond()));
else
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
return true;
}
return false;
}
/// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
/// the possible Predicate and SBitModifier, to build the remaining MCOperand
/// constituents.
bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
uint32_t insn, unsigned short NumOpsRemaining) {
@ -3258,10 +3292,11 @@ bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
Idx += 2;
NumOpsRemaining -= 2;
if (NumOpsRemaining == 0)
return true;
}
if (NumOpsRemaining == 0)
return true;
// Next, if OptionalDefOperand exists, we check whether the 'S' bit is set.
if (OpInfo[Idx].isOptionalDef() && OpInfo[Idx].RegClass==ARM::CCRRegClassID) {
MI.addOperand(MCOperand::CreateReg(getSBit(insn) == 1 ? ARM::CPSR : 0));

View File

@ -210,6 +210,12 @@ public:
Err = ErrCode;
}
/// DoPredicateOperands - DoPredicateOperands process the predicate operands
/// of some Thumb instructions which come before the reglist operands. It
/// returns true if the two predicate operands have been processed.
bool DoPredicateOperands(MCInst& MI, unsigned Opcode,
uint32_t insn, unsigned short NumOpsRemaning);
/// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
/// the possible Predicate and SBitModifier, to build the remaining MCOperand
/// constituents.

View File

@ -713,13 +713,17 @@ static bool DisassembleThumb1PushPop(MCInst &MI, unsigned Opcode, uint32_t insn,
unsigned &OpIdx = NumOpsAdded;
// Handling the two predicate operands before the reglist.
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
OpIdx = 2;
if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
OpIdx += 2;
else {
DEBUG(errs() << "Expected predicate operands not found.\n");
return false;
}
// Fill the variadic part of reglist.
unsigned RegListBits = slice(insn, 8, 8) << (Opcode == ARM::tPUSH ? 14 : 15)
| slice(insn, 7, 0);
// Fill the variadic part of reglist.
for (unsigned i = 0; i < 16; ++i) {
if ((RegListBits >> i) & 1) {
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
@ -840,7 +844,6 @@ static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode,
unsigned &OpIdx = NumOpsAdded;
unsigned tRt = getT1tRt(insn);
unsigned RegListBits = slice(insn, 7, 0);
OpIdx = 0;
@ -856,13 +859,19 @@ static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode,
++OpIdx;
// A8.6.53 LDM / LDMIA / LDMFD - Encoding T1
// A8.6.53 STM / STMIA / STMEA - Encoding T1
MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)));
++OpIdx;
// Handling the two predicate operands before the reglist.
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
OpIdx += 2;
if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
OpIdx += 2;
else {
DEBUG(errs() << "Expected predicate operands not found.\n");
return false;
}
unsigned RegListBits = slice(insn, 7, 0);
// Fill the variadic part of reglist.
for (unsigned i = 0; i < 8; ++i) {
@ -1137,12 +1146,16 @@ static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn,
++OpIdx;
// Handling the two predicate operands before the reglist.
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
OpIdx += 2;
if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
OpIdx += 2;
else {
DEBUG(errs() << "Expected predicate operands not found.\n");
return false;
}
unsigned RegListBits = insn & ((1 << 16) - 1);
// Fill the variadic part of reglist.
unsigned RegListBits = insn & ((1 << 16) - 1);
for (unsigned i = 0; i < 16; ++i) {
if ((RegListBits >> i) & 1) {
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,

View File

@ -85,6 +85,9 @@
# CHECK: lsleq r1, r0, #28
0x01 0x07
# CHECK: rsbne r1, r2, #0
0x51 0x42
# CHECK: stmiane r0!, {r1, r2, r3}
0x0e 0xc0
# IT block end
# CHECK: rsbs r1, r2, #0
0x51 0x42