mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-18 12:31:26 +00:00
Add fixup for Thumb1 BL/BLX instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121072 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6033b346e2
commit
662a816e89
@ -1546,6 +1546,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
case ARM::fixup_arm_ldst_pcrel_12:
|
||||
case ARM::fixup_arm_pcrel_10:
|
||||
case ARM::fixup_arm_adr_pcrel_12:
|
||||
case ARM::fixup_arm_thumb_bl:
|
||||
assert(0 && "Unimplemented"); break;
|
||||
case ARM::fixup_arm_branch:
|
||||
return ELF::R_ARM_CALL; break;
|
||||
|
@ -103,7 +103,18 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
case ARM::fixup_arm_branch:
|
||||
// These values don't encode the low two bits since they're always zero.
|
||||
// Offset by 8 just as above.
|
||||
return 0xFFFFFF & ((Value - 8) >> 2);
|
||||
return 0xffffff & ((Value - 8) >> 2);
|
||||
case ARM::fixup_arm_thumb_bl: {
|
||||
// The value doesn't encode the low bit (always zero) and is offset by
|
||||
// four. The value is encoded into disjoint bit positions in the destination
|
||||
// opcode. x = unchanged, I = immediate value bit, S = sign extension bit
|
||||
// xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII
|
||||
// Note that the halfwords are stored high first, low second; so we need
|
||||
// to transpose the fixup value here to map properly.
|
||||
uint32_t Binary = 0x3fffff & ((Value - 4) >> 1);
|
||||
Binary = ((Binary & 0x7ff) << 16) | (Binary >> 11);
|
||||
return Binary;
|
||||
}
|
||||
case ARM::fixup_arm_pcrel_10: {
|
||||
// Offset by 8 just as above.
|
||||
Value = Value - 8;
|
||||
@ -198,12 +209,17 @@ public:
|
||||
|
||||
static unsigned getFixupKindNumBytes(unsigned Kind) {
|
||||
switch (Kind) {
|
||||
default: llvm_unreachable("Unknown fixup kind!");
|
||||
case FK_Data_4: return 4;
|
||||
case ARM::fixup_arm_ldst_pcrel_12: return 3;
|
||||
case ARM::fixup_arm_pcrel_10: return 3;
|
||||
case ARM::fixup_arm_adr_pcrel_12: return 3;
|
||||
case ARM::fixup_arm_branch: return 3;
|
||||
default:
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
case FK_Data_4:
|
||||
return 4;
|
||||
case ARM::fixup_arm_ldst_pcrel_12:
|
||||
case ARM::fixup_arm_pcrel_10:
|
||||
case ARM::fixup_arm_adr_pcrel_12:
|
||||
case ARM::fixup_arm_branch:
|
||||
return 3;
|
||||
case ARM::fixup_arm_thumb_bl:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,6 +171,8 @@ namespace {
|
||||
const { return 0; }
|
||||
unsigned getAdrLabelOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getThumbBLTargetOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
|
||||
const { return 0; }
|
||||
unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op)
|
||||
|
@ -25,9 +25,11 @@ enum Fixups {
|
||||
// fixup_arm_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
|
||||
// instruction.
|
||||
fixup_arm_adr_pcrel_12,
|
||||
// fixup_arm_brnach - 24-bit PC relative relocation for direct branch
|
||||
// fixup_arm_branch - 24-bit PC relative relocation for direct branch
|
||||
// instructions.
|
||||
fixup_arm_branch,
|
||||
// fixup_arm_thumb_bl - Fixup for Thumb BL/BLX instructions.
|
||||
fixup_arm_thumb_bl,
|
||||
|
||||
// The next two are for the movt/movw pair
|
||||
// the 16bit imm field are split into imm{15-12} and imm{11-0}
|
||||
|
@ -74,6 +74,10 @@ def t_imm_s4 : Operand<i32> {
|
||||
|
||||
// Define Thumb specific addressing modes.
|
||||
|
||||
def t_bltarget : Operand<i32> {
|
||||
let EncoderMethod = "getThumbBLTargetOpValue";
|
||||
}
|
||||
|
||||
def MemModeThumbAsmOperand : AsmOperandClass {
|
||||
let Name = "MemModeThumb";
|
||||
let SuperClasses = [];
|
||||
@ -366,22 +370,29 @@ let isCall = 1,
|
||||
Uses = [SP] in {
|
||||
// Also used for Thumb2
|
||||
def tBL : TIx2<0b11110, 0b11, 1,
|
||||
(outs), (ins i32imm:$func, variable_ops), IIC_Br,
|
||||
(outs), (ins t_bltarget:$func, variable_ops), IIC_Br,
|
||||
"bl\t$func",
|
||||
[(ARMtcall tglobaladdr:$func)]>,
|
||||
Requires<[IsThumb, IsNotDarwin]> {
|
||||
bits<21> func;
|
||||
let Inst{25-16} = func{20-11};
|
||||
let Inst{13} = 1;
|
||||
let Inst{11} = 1;
|
||||
let Inst{10-0} = func{10-0};
|
||||
}
|
||||
|
||||
// ARMv5T and above, also used for Thumb2
|
||||
def tBLXi : TIx2<0b11110, 0b11, 0,
|
||||
(outs), (ins i32imm:$func, variable_ops), IIC_Br,
|
||||
(outs), (ins t_bltarget:$func, variable_ops), IIC_Br,
|
||||
"blx\t$func",
|
||||
[(ARMcall tglobaladdr:$func)]>,
|
||||
Requires<[IsThumb, HasV5T, IsNotDarwin]> {
|
||||
bits<21> func;
|
||||
let Inst{25-16} = func{20-11};
|
||||
let Inst{13} = 1;
|
||||
let Inst{11} = 1;
|
||||
let Inst{10-1} = func{10-1};
|
||||
let Inst{0} = 0; // func{0} is assumed zero
|
||||
}
|
||||
|
||||
// Also used for Thumb2
|
||||
@ -412,23 +423,29 @@ let isCall = 1,
|
||||
Uses = [R7, SP] in {
|
||||
// Also used for Thumb2
|
||||
def tBLr9 : TIx2<0b11110, 0b11, 1,
|
||||
(outs), (ins pred:$p, i32imm:$func, variable_ops), IIC_Br,
|
||||
"bl${p}\t$func",
|
||||
(outs), (ins pred:$p, t_bltarget:$func, variable_ops),
|
||||
IIC_Br, "bl${p}\t$func",
|
||||
[(ARMtcall tglobaladdr:$func)]>,
|
||||
Requires<[IsThumb, IsDarwin]> {
|
||||
let Inst{13} = 1;
|
||||
let Inst{11} = 1;
|
||||
bits<21> func;
|
||||
let Inst{25-16} = func{20-11};
|
||||
let Inst{13} = 1;
|
||||
let Inst{11} = 1;
|
||||
let Inst{10-0} = func{10-0};
|
||||
}
|
||||
|
||||
// ARMv5T and above, also used for Thumb2
|
||||
def tBLXi_r9 : TIx2<0b11110, 0b11, 0,
|
||||
(outs), (ins pred:$p, i32imm:$func, variable_ops),
|
||||
IIC_Br,
|
||||
"blx${p}\t$func",
|
||||
(outs), (ins pred:$p, t_bltarget:$func, variable_ops),
|
||||
IIC_Br, "blx${p}\t$func",
|
||||
[(ARMcall tglobaladdr:$func)]>,
|
||||
Requires<[IsThumb, HasV5T, IsDarwin]> {
|
||||
bits<21> func;
|
||||
let Inst{25-16} = func{20-11};
|
||||
let Inst{13} = 1;
|
||||
let Inst{11} = 1;
|
||||
let Inst{10-1} = func{10-1};
|
||||
let Inst{0} = 0; // func{0} is assumed zero
|
||||
}
|
||||
|
||||
// Also used for Thumb2
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||
{ "fixup_arm_movt_hi16", 0, 16, 0 },
|
||||
{ "fixup_arm_movw_lo16", 0, 16, 0 },
|
||||
};
|
||||
@ -81,6 +82,11 @@ public:
|
||||
unsigned &Reg, unsigned &Imm,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
/// getThumbBLTargetOpValue - Return encoding info for Thumb immediate
|
||||
/// branch target.
|
||||
uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||
|
||||
/// getBranchTargetOpValue - Return encoding info for 24-bit immediate
|
||||
/// branch target.
|
||||
uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
@ -395,6 +401,24 @@ EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg,
|
||||
return isAdd;
|
||||
}
|
||||
|
||||
/// getThumbBLTargetOpValue - Return encoding info for immediate
|
||||
/// branch target.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||
const MCOperand &MO = MI.getOperand(OpIdx);
|
||||
|
||||
// If the destination is an immediate, we have nothing to do.
|
||||
if (MO.isImm()) return MO.getImm();
|
||||
assert (MO.isExpr() && "Unexpected branch target type!");
|
||||
const MCExpr *Expr = MO.getExpr();
|
||||
MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_thumb_bl);
|
||||
Fixups.push_back(MCFixup::Create(0, Expr, Kind));
|
||||
|
||||
// All of the information is in the fixup.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getBranchTargetOpValue - Return encoding info for 24-bit immediate
|
||||
/// branch target.
|
||||
uint32_t ARMMCCodeEmitter::
|
||||
|
@ -587,6 +587,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
IMM("neon_vcvt_imm32");
|
||||
|
||||
MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
|
||||
MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ?
|
||||
MISC("bltarget", "kOperandTypeARMBranchTarget"); // ?
|
||||
MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I
|
||||
MISC("shift_so_reg", "kOperandTypeARMSoReg"); // R, R, I
|
||||
|
Loading…
x
Reference in New Issue
Block a user