mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-02 07:32:52 +00:00
Thumb2 parsing and encoding for LDMIA.
Choose 32-bit vs. 16-bit encoding when there's no .w suffix in post-processing as match classes are insufficient to handle the context-sensitiveness of the writeback operand's legality for the 16-bit encodings. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139242 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6de3c6f1a9
commit
76ecc3d35b
@ -3339,6 +3339,17 @@ static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the specified regisgter is in the register list of the inst,
|
||||
// starting at the indicated operand number.
|
||||
static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
|
||||
for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
|
||||
unsigned OpReg = Inst.getOperand(i).getReg();
|
||||
if (OpReg == Reg)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
|
||||
// the ARMInsts array) instead. Getting that here requires awkward
|
||||
// API changes, though. Better way?
|
||||
@ -3430,6 +3441,11 @@ validateInstruction(MCInst &Inst,
|
||||
return false;
|
||||
}
|
||||
case ARM::tLDMIA: {
|
||||
// If we're parsing Thumb2, the .w variant is available and handles
|
||||
// most cases that are normally illegal for a Thumb1 LDM
|
||||
// instruction. We'll make the transformation in processInstruction()
|
||||
// if necessary.
|
||||
//
|
||||
// Thumb LDM instructions are writeback iff the base register is not
|
||||
// in the register list.
|
||||
unsigned Rn = Inst.getOperand(0).getReg();
|
||||
@ -3437,14 +3453,15 @@ validateInstruction(MCInst &Inst,
|
||||
(static_cast<ARMOperand*>(Operands[3])->isToken() &&
|
||||
static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
|
||||
bool listContainsBase;
|
||||
if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase))
|
||||
if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
|
||||
return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
|
||||
"registers must be in range r0-r7");
|
||||
// If we should have writeback, then there should be a '!' token.
|
||||
if (!listContainsBase && !hasWritebackToken)
|
||||
if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
|
||||
return Error(Operands[2]->getStartLoc(),
|
||||
"writeback operator '!' expected");
|
||||
// Likewise, if we should not have writeback, there must not be a '!'
|
||||
// If we should not have writeback, there must not be a '!'. This is
|
||||
// true even for the 32-bit wide encodings.
|
||||
if (listContainsBase && hasWritebackToken)
|
||||
return Error(Operands[3]->getStartLoc(),
|
||||
"writeback operator '!' not allowed when base register "
|
||||
@ -3452,6 +3469,13 @@ validateInstruction(MCInst &Inst,
|
||||
|
||||
break;
|
||||
}
|
||||
case ARM::t2LDMIA_UPD: {
|
||||
if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
|
||||
return Error(Operands[4]->getStartLoc(),
|
||||
"writeback operator '!' not allowed when base register "
|
||||
"in register list");
|
||||
break;
|
||||
}
|
||||
case ARM::tPOP: {
|
||||
bool listContainsBase;
|
||||
if (checkLowRegisterList(Inst, 3, 0, ARM::PC, listContainsBase))
|
||||
@ -3533,6 +3557,30 @@ processInstruction(MCInst &Inst,
|
||||
if (Inst.getOperand(1).getImm() == ARMCC::AL)
|
||||
Inst.setOpcode(ARM::tB);
|
||||
break;
|
||||
case ARM::tLDMIA: {
|
||||
// If the register list contains any high registers, or if the writeback
|
||||
// doesn't match what tLDMIA can do, we need to use the 32-bit encoding
|
||||
// instead if we're in Thumb2. Otherwise, this should have generated
|
||||
// an error in validateInstruction().
|
||||
unsigned Rn = Inst.getOperand(0).getReg();
|
||||
bool hasWritebackToken =
|
||||
(static_cast<ARMOperand*>(Operands[3])->isToken() &&
|
||||
static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
|
||||
bool listContainsBase;
|
||||
if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
|
||||
(!listContainsBase && !hasWritebackToken) ||
|
||||
(listContainsBase && hasWritebackToken)) {
|
||||
// 16-bit encoding isn't sufficient. Switch to the 32-bit version.
|
||||
assert (isThumbTwo());
|
||||
Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
|
||||
// If we're switching to the updating version, we need to insert
|
||||
// the writeback tied operand.
|
||||
if (hasWritebackToken)
|
||||
Inst.insert(Inst.begin(),
|
||||
MCOperand::CreateReg(Inst.getOperand(0).getReg()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARM::t2IT: {
|
||||
// The mask bits for all but the first condition are represented as
|
||||
// the low bit of the condition code value implies 't'. We currently
|
||||
|
@ -462,6 +462,44 @@ _func:
|
||||
@ CHECK: isb sy @ encoding: [0xbf,0xf3,0x6f,0x8f]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ LDMIA
|
||||
@------------------------------------------------------------------------------
|
||||
ldmia.w r4, {r4, r5, r8, r9}
|
||||
ldmia.w r4, {r5, r6}
|
||||
ldmia.w r5!, {r3, r8}
|
||||
ldm.w r4, {r4, r5, r8, r9}
|
||||
ldm.w r4, {r5, r6}
|
||||
ldm.w r5!, {r3, r8}
|
||||
ldm.w r5!, {r1, r2}
|
||||
ldm.w r2, {r1, r2}
|
||||
|
||||
ldmia r4, {r4, r5, r8, r9}
|
||||
ldmia r4, {r5, r6}
|
||||
ldmia r5!, {r3, r8}
|
||||
ldm r4, {r4, r5, r8, r9}
|
||||
ldm r4, {r5, r6}
|
||||
ldm r5!, {r3, r8}
|
||||
ldmfd r5!, {r3, r8}
|
||||
|
||||
@ CHECK: ldm.w r4, {r4, r5, r8, r9} @ encoding: [0x94,0xe8,0x30,0x03]
|
||||
@ CHECK: ldm.w r4, {r5, r6} @ encoding: [0x94,0xe8,0x60,0x00]
|
||||
@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
|
||||
@ CHECK: ldm.w r4, {r4, r5, r8, r9} @ encoding: [0x94,0xe8,0x30,0x03]
|
||||
@ CHECK: ldm.w r4, {r5, r6} @ encoding: [0x94,0xe8,0x60,0x00]
|
||||
@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
|
||||
@ CHECK: ldm.w r5!, {r1, r2} @ encoding: [0xb5,0xe8,0x06,0x00]
|
||||
@ CHECK: ldm.w r2, {r1, r2} @ encoding: [0x92,0xe8,0x06,0x00]
|
||||
|
||||
@ CHECK: ldm.w r4, {r4, r5, r8, r9} @ encoding: [0x94,0xe8,0x30,0x03]
|
||||
@ CHECK: ldm.w r4, {r5, r6} @ encoding: [0x94,0xe8,0x60,0x00]
|
||||
@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
|
||||
@ CHECK: ldm.w r4, {r4, r5, r8, r9} @ encoding: [0x94,0xe8,0x30,0x03]
|
||||
@ CHECK: ldm.w r4, {r5, r6} @ encoding: [0x94,0xe8,0x60,0x00]
|
||||
@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
|
||||
@ CHECK: ldm.w r5!, {r3, r8} @ encoding: [0xb5,0xe8,0x08,0x01]
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ IT
|
||||
@------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user