mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
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. llvm-svn: 101974
This commit is contained in:
parent
c840cfe5c9
commit
6e4b1607ee
@ -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));
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user