mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-19 03:24:09 +00: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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101974 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -3218,6 +3218,40 @@ static uint32_t CondCode(uint32_t CondField) {
|
|||||||
return 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,
|
bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
|
||||||
uint32_t insn, unsigned short NumOpsRemaining) {
|
uint32_t insn, unsigned short NumOpsRemaining) {
|
||||||
|
|
||||||
@ -3258,10 +3292,11 @@ bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
|
|||||||
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
|
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
|
||||||
Idx += 2;
|
Idx += 2;
|
||||||
NumOpsRemaining -= 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.
|
// Next, if OptionalDefOperand exists, we check whether the 'S' bit is set.
|
||||||
if (OpInfo[Idx].isOptionalDef() && OpInfo[Idx].RegClass==ARM::CCRRegClassID) {
|
if (OpInfo[Idx].isOptionalDef() && OpInfo[Idx].RegClass==ARM::CCRRegClassID) {
|
||||||
MI.addOperand(MCOperand::CreateReg(getSBit(insn) == 1 ? ARM::CPSR : 0));
|
MI.addOperand(MCOperand::CreateReg(getSBit(insn) == 1 ? ARM::CPSR : 0));
|
||||||
|
@ -210,6 +210,12 @@ public:
|
|||||||
Err = ErrCode;
|
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
|
/// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
|
||||||
/// the possible Predicate and SBitModifier, to build the remaining MCOperand
|
/// the possible Predicate and SBitModifier, to build the remaining MCOperand
|
||||||
/// constituents.
|
/// constituents.
|
||||||
|
@ -713,13 +713,17 @@ static bool DisassembleThumb1PushPop(MCInst &MI, unsigned Opcode, uint32_t insn,
|
|||||||
unsigned &OpIdx = NumOpsAdded;
|
unsigned &OpIdx = NumOpsAdded;
|
||||||
|
|
||||||
// Handling the two predicate operands before the reglist.
|
// Handling the two predicate operands before the reglist.
|
||||||
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
|
||||||
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
|
OpIdx += 2;
|
||||||
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)
|
unsigned RegListBits = slice(insn, 8, 8) << (Opcode == ARM::tPUSH ? 14 : 15)
|
||||||
| slice(insn, 7, 0);
|
| slice(insn, 7, 0);
|
||||||
|
|
||||||
|
// Fill the variadic part of reglist.
|
||||||
for (unsigned i = 0; i < 16; ++i) {
|
for (unsigned i = 0; i < 16; ++i) {
|
||||||
if ((RegListBits >> i) & 1) {
|
if ((RegListBits >> i) & 1) {
|
||||||
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
|
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 &OpIdx = NumOpsAdded;
|
||||||
|
|
||||||
unsigned tRt = getT1tRt(insn);
|
unsigned tRt = getT1tRt(insn);
|
||||||
unsigned RegListBits = slice(insn, 7, 0);
|
|
||||||
|
|
||||||
OpIdx = 0;
|
OpIdx = 0;
|
||||||
|
|
||||||
@ -856,13 +859,19 @@ static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode,
|
|||||||
++OpIdx;
|
++OpIdx;
|
||||||
|
|
||||||
// A8.6.53 LDM / LDMIA / LDMFD - Encoding T1
|
// 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)));
|
MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)));
|
||||||
++OpIdx;
|
++OpIdx;
|
||||||
|
|
||||||
// Handling the two predicate operands before the reglist.
|
// Handling the two predicate operands before the reglist.
|
||||||
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
|
||||||
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
|
OpIdx += 2;
|
||||||
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.
|
// Fill the variadic part of reglist.
|
||||||
for (unsigned i = 0; i < 8; ++i) {
|
for (unsigned i = 0; i < 8; ++i) {
|
||||||
@ -1137,12 +1146,16 @@ static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn,
|
|||||||
++OpIdx;
|
++OpIdx;
|
||||||
|
|
||||||
// Handling the two predicate operands before the reglist.
|
// Handling the two predicate operands before the reglist.
|
||||||
MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
|
if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
|
||||||
MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
|
OpIdx += 2;
|
||||||
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.
|
// Fill the variadic part of reglist.
|
||||||
unsigned RegListBits = insn & ((1 << 16) - 1);
|
|
||||||
for (unsigned i = 0; i < 16; ++i) {
|
for (unsigned i = 0; i < 16; ++i) {
|
||||||
if ((RegListBits >> i) & 1) {
|
if ((RegListBits >> i) & 1) {
|
||||||
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
|
MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
|
||||||
|
@ -85,6 +85,9 @@
|
|||||||
# CHECK: lsleq r1, r0, #28
|
# CHECK: lsleq r1, r0, #28
|
||||||
0x01 0x07
|
0x01 0x07
|
||||||
|
|
||||||
# CHECK: rsbne r1, r2, #0
|
# CHECK: stmiane r0!, {r1, r2, r3}
|
||||||
0x51 0x42
|
0x0e 0xc0
|
||||||
|
|
||||||
# IT block end
|
# IT block end
|
||||||
|
# CHECK: rsbs r1, r2, #0
|
||||||
|
0x51 0x42
|
||||||
|
Reference in New Issue
Block a user