mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-18 22:38:56 +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;
|
return Val > -4096 && Val < 4096;
|
||||||
}
|
}
|
||||||
bool isAddrMode3() const {
|
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;
|
if (!isMemory() || Memory.Alignment != 0) return false;
|
||||||
// No shifts are legal for AM3.
|
// No shifts are legal for AM3.
|
||||||
if (Memory.ShiftType != ARM_AM::no_shift) return false;
|
if (Memory.ShiftType != ARM_AM::no_shift) return false;
|
||||||
@ -992,6 +997,11 @@ public:
|
|||||||
return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
|
return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
|
||||||
}
|
}
|
||||||
bool isMemImm8s4Offset() const {
|
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)
|
if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
|
||||||
return false;
|
return false;
|
||||||
// Immediate offset a multiple of 4 in range [-1020, 1020].
|
// Immediate offset a multiple of 4 in range [-1020, 1020].
|
||||||
@ -1488,6 +1498,16 @@ public:
|
|||||||
|
|
||||||
void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
|
void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
|
||||||
assert(N == 3 && "Invalid number of operands!");
|
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;
|
int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
|
||||||
if (!Memory.OffsetRegNum) {
|
if (!Memory.OffsetRegNum) {
|
||||||
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
|
ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
|
||||||
@ -1551,6 +1571,15 @@ public:
|
|||||||
|
|
||||||
void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
|
void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
|
||||||
assert(N == 2 && "Invalid number of operands!");
|
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;
|
int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
|
||||||
Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
|
Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
|
||||||
Inst.addOperand(MCOperand::CreateImm(Val));
|
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,
|
void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned Op,
|
||||||
raw_ostream &O) {
|
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);
|
const MCOperand &MO3 = MI->getOperand(Op+2);
|
||||||
unsigned IdxMode = ARM_AM::getAM3IdxMode(MO3.getImm());
|
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 &MO1 = MI->getOperand(OpNum);
|
||||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||||
|
|
||||||
|
if (!MO1.isReg()) { // For label symbolic references.
|
||||||
|
printOperand(MI, OpNum, O);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
O << "[" << getRegisterName(MO1.getReg());
|
O << "[" << getRegisterName(MO1.getReg());
|
||||||
|
|
||||||
int32_t OffImm = (int32_t)MO2.getImm() / 4;
|
int32_t OffImm = (int32_t)MO2.getImm() / 4;
|
||||||
|
@ -63,6 +63,7 @@ public:
|
|||||||
{ "fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
|
{ "fixup_t2_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
|
||||||
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
|
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
|
||||||
|
{ "fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
|
{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
|
||||||
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
|
MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
|
||||||
@ -399,6 +400,17 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
|||||||
case ARM::fixup_arm_thumb_bcc:
|
case ARM::fixup_arm_thumb_bcc:
|
||||||
// Offset by 4 and don't encode the lower bit, which is always 0.
|
// Offset by 4 and don't encode the lower bit, which is always 0.
|
||||||
return ((Value - 4) >> 1) & 0xff;
|
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:
|
case ARM::fixup_arm_pcrel_10:
|
||||||
Value = Value - 4; // ARM fixups offset by an additional word and don't
|
Value = Value - 4; // ARM fixups offset by an additional word and don't
|
||||||
// need to adjust for the half-word ordering.
|
// 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!");
|
assert ((Value < 256) && "Out of range pc-relative fixup value!");
|
||||||
Value |= isAdd << 23;
|
Value |= isAdd << 23;
|
||||||
|
|
||||||
// Same addressing mode as fixup_arm_pcrel_10,
|
// Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords
|
||||||
// but with 16-bit halfwords swapped.
|
// swapped.
|
||||||
if (Kind == ARM::fixup_t2_pcrel_10) {
|
if (Kind == ARM::fixup_t2_pcrel_10) {
|
||||||
uint32_t swapped = (Value & 0xFFFF0000) >> 16;
|
uint32_t swapped = (Value & 0xFFFF0000) >> 16;
|
||||||
swapped |= (Value & 0x0000FFFF) << 16;
|
swapped |= (Value & 0x0000FFFF) << 16;
|
||||||
@ -504,6 +516,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
|
|||||||
case ARM::fixup_arm_thumb_cb:
|
case ARM::fixup_arm_thumb_cb:
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
|
case ARM::fixup_arm_pcrel_10_unscaled:
|
||||||
case ARM::fixup_arm_ldst_pcrel_12:
|
case ARM::fixup_arm_ldst_pcrel_12:
|
||||||
case ARM::fixup_arm_pcrel_10:
|
case ARM::fixup_arm_pcrel_10:
|
||||||
case ARM::fixup_arm_adr_pcrel_12:
|
case ARM::fixup_arm_adr_pcrel_12:
|
||||||
|
@ -23,6 +23,9 @@ enum Fixups {
|
|||||||
// the 16-bit halfwords reordered.
|
// the 16-bit halfwords reordered.
|
||||||
fixup_t2_ldst_pcrel_12,
|
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
|
// fixup_arm_pcrel_10 - 10-bit PC relative relocation for symbol addresses
|
||||||
// used in VFP instructions where the lower 2 bits are not encoded
|
// used in VFP instructions where the lower 2 bits are not encoded
|
||||||
// (so it's encoded as an 8-bit immediate).
|
// (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!");
|
assert(MO.isExpr() && "Unexpected machine operand type!");
|
||||||
const MCExpr *Expr = MO.getExpr();
|
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));
|
Fixups.push_back(MCFixup::Create(0, Expr, Kind));
|
||||||
|
|
||||||
++MCNumCPRelocations;
|
++MCNumCPRelocations;
|
||||||
@ -993,6 +993,19 @@ getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
|
|||||||
const MCOperand &MO = MI.getOperand(OpIdx);
|
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||||
const MCOperand &MO1 = MI.getOperand(OpIdx+1);
|
const MCOperand &MO1 = MI.getOperand(OpIdx+1);
|
||||||
const MCOperand &MO2 = MI.getOperand(OpIdx+2);
|
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 Rn = getARMRegisterNumbering(MO.getReg());
|
||||||
unsigned Imm = MO2.getImm();
|
unsigned Imm = MO2.getImm();
|
||||||
bool isAdd = ARM_AM::getAM3Op(Imm) == ARM_AM::add;
|
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)
|
@ LDRD (register)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user