mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
ARM assembly parsing and encoding support for LDRD(label).
rdar://9932658 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146921 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8787c5f24e
commit
2f196747f1
@ -880,6 +880,11 @@ public:
|
||||
return Val > -4096 && Val < 4096;
|
||||
}
|
||||
bool isAddrMode3() const {
|
||||
// If we have an immediate that's not a constant, treat it as a label
|
||||
// reference needing a fixup. If it is a constant, it's something else
|
||||
// and we reject it.
|
||||
if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
|
||||
return true;
|
||||
if (!isMemory() || Memory.Alignment != 0) return false;
|
||||
// No shifts are legal for AM3.
|
||||
if (Memory.ShiftType != ARM_AM::no_shift) return false;
|
||||
@ -992,6 +997,11 @@ public:
|
||||
return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
|
||||
}
|
||||
bool isMemImm8s4Offset() const {
|
||||
// If we have an immediate that's not a constant, treat it as a label
|
||||
// reference needing a fixup. If it is a constant, it's something else
|
||||
// and we reject it.
|
||||
if (Kind == k_Immediate && !isa<MCConstantExpr>(getImm()))
|
||||
return true;
|
||||
if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
|
||||
return false;
|
||||
// Immediate offset a multiple of 4 in range [-1020, 1020].
|
||||
@ -1488,6 +1498,16 @@ public:
|
||||
|
||||
void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 3 && "Invalid number of operands!");
|
||||
// If we have an immediate that's not a constant, treat it as a label
|
||||
// reference needing a fixup. If it is a constant, it's something else
|
||||
// and we reject it.
|
||||
if (isImm()) {
|
||||
Inst.addOperand(MCOperand::CreateExpr(getImm()));
|
||||
Inst.addOperand(MCOperand::CreateReg(0));
|
||||
Inst.addOperand(MCOperand::CreateImm(0));
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
|
||||
if (!Memory.OffsetRegNum) {
|
||||
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
|
||||
@ -1551,6 +1571,15 @@ public:
|
||||
|
||||
void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
|
||||
assert(N == 2 && "Invalid number of operands!");
|
||||
// If we have an immediate that's not a constant, treat it as a label
|
||||
// reference needing a fixup. If it is a constant, it's something else
|
||||
// and we reject it.
|
||||
if (isImm()) {
|
||||
Inst.addOperand(MCOperand::CreateExpr(getImm()));
|
||||
Inst.addOperand(MCOperand::CreateImm(0));
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
|
||||
Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
|
||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
||||
|
@ -436,6 +436,12 @@ void ARMInstPrinter::printAM3PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
|
||||
|
||||
void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
if (!MO1.isReg()) { // For label symbolic references.
|
||||
printOperand(MI, Op, O);
|
||||
return;
|
||||
}
|
||||
|
||||
const MCOperand &MO3 = MI->getOperand(Op+2);
|
||||
unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm());
|
||||
|
||||
@ -885,6 +891,11 @@ void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
if (!MO1.isReg()) { // For label symbolic references.
|
||||
printOperand(MI, OpNum, O);
|
||||
return;
|
||||
}
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
int32_t OffImm = (int32_t)MO2.getImm() / 4;
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
{ "fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
|
||||
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
|
||||
{ "fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
|
||||
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
|
||||
@ -399,6 +400,17 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
case ARM::fixup_arm_thumb_bcc:
|
||||
// Offset by 4 and don't encode the lower bit, which is always 0.
|
||||
return ((Value - 4) >> 1) & 0xff;
|
||||
case ARM::fixup_arm_pcrel_10_unscaled: {
|
||||
Value = Value - 8; // ARM fixups offset by an additional word and don't
|
||||
// need to adjust for the half-word ordering.
|
||||
bool isAdd = true;
|
||||
if ((int64_t)Value < 0) {
|
||||
Value = -Value;
|
||||
isAdd = false;
|
||||
}
|
||||
assert ((Value < 256) && "Out of range pc-relative fixup value!");
|
||||
return Value | (isAdd << 23);
|
||||
}
|
||||
case ARM::fixup_arm_pcrel_10:
|
||||
Value = Value - 4; // ARM fixups offset by an additional word and don't
|
||||
// need to adjust for the half-word ordering.
|
||||
@ -416,8 +428,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
assert ((Value < 256) && "Out of range pc-relative fixup value!");
|
||||
Value |= isAdd << 23;
|
||||
|
||||
// Same addressing mode as fixup_arm_pcrel_10,
|
||||
// but with 16-bit halfwords swapped.
|
||||
// Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords
|
||||
// swapped.
|
||||
if (Kind == ARM::fixup_t2_pcrel_10) {
|
||||
uint32_t swapped = (Value & 0xFFFF0000) >> 16;
|
||||
swapped |= (Value & 0x0000FFFF) << 16;
|
||||
@ -504,6 +516,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
|
||||
case ARM::fixup_arm_thumb_cb:
|
||||
return 2;
|
||||
|
||||
case ARM::fixup_arm_pcrel_10_unscaled:
|
||||
case ARM::fixup_arm_ldst_pcrel_12:
|
||||
case ARM::fixup_arm_pcrel_10:
|
||||
case ARM::fixup_arm_adr_pcrel_12:
|
||||
|
@ -23,6 +23,9 @@ enum Fixups {
|
||||
// the 16-bit halfwords reordered.
|
||||
fixup_t2_ldst_pcrel_12,
|
||||
|
||||
// fixup_arm_pcrel_10_unscaled - 10-bit PC relative relocation for symbol
|
||||
// addresses used in LDRD/LDRH/LDRB/etc. instructions. All bits are encoded.
|
||||
fixup_arm_pcrel_10_unscaled,
|
||||
// fixup_arm_pcrel_10 - 10-bit PC relative relocation for symbol addresses
|
||||
// used in VFP instructions where the lower 2 bits are not encoded
|
||||
// (so it's encoded as an 8-bit immediate).
|
||||
|
@ -791,7 +791,7 @@ getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
|
||||
assert(MO.isExpr() && "Unexpected machine operand type!");
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
|
||||
MCFixupKind Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
|
||||
Fixups.push_back(MCFixup::Create(0, Expr, Kind));
|
||||
|
||||
++MCNumCPRelocations;
|
||||
@ -993,6 +993,19 @@ getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
|
||||
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||
const MCOperand &MO1 = MI.getOperand(OpIdx+1);
|
||||
const MCOperand &MO2 = MI.getOperand(OpIdx+2);
|
||||
|
||||
// If The first operand isn't a register, we have a label reference.
|
||||
if (!MO.isReg()) {
|
||||
unsigned Rn = getARMRegisterNumbering(ARM::PC); // Rn is PC.
|
||||
|
||||
assert(MO.isExpr() && "Unexpected machine operand type!");
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10_unscaled);
|
||||
Fixups.push_back(MCFixup::Create(0, Expr, Kind));
|
||||
|
||||
++MCNumCPRelocations;
|
||||
return (Rn << 9) | (1 << 13);
|
||||
}
|
||||
unsigned Rn = getARMRegisterNumbering(MO.getReg());
|
||||
unsigned Imm = MO2.getImm();
|
||||
bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
|
||||
|
@ -130,8 +130,13 @@ _func:
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ FIXME: LDRD (label)
|
||||
@ LDRD (label)
|
||||
@------------------------------------------------------------------------------
|
||||
ldrd r2, r3, Lbaz
|
||||
Lbaz: .quad 0
|
||||
|
||||
@ CHECK: ldrd r2, r3, Lbaz @ encoding: [0xd0'A',0x20'A',0x4f'A',0xe1'A']
|
||||
|
||||
|
||||
@------------------------------------------------------------------------------
|
||||
@ LDRD (register)
|
||||
|
Loading…
Reference in New Issue
Block a user