mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 05:24:01 +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:
@ -1546,6 +1546,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
|
|||||||
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:
|
||||||
|
case ARM::fixup_arm_thumb_bl:
|
||||||
assert(0 && "Unimplemented"); break;
|
assert(0 && "Unimplemented"); break;
|
||||||
case ARM::fixup_arm_branch:
|
case ARM::fixup_arm_branch:
|
||||||
return ELF::R_ARM_CALL; break;
|
return ELF::R_ARM_CALL; break;
|
||||||
|
@ -103,7 +103,18 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
|||||||
case ARM::fixup_arm_branch:
|
case ARM::fixup_arm_branch:
|
||||||
// These values don't encode the low two bits since they're always zero.
|
// These values don't encode the low two bits since they're always zero.
|
||||||
// Offset by 8 just as above.
|
// 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: {
|
case ARM::fixup_arm_pcrel_10: {
|
||||||
// Offset by 8 just as above.
|
// Offset by 8 just as above.
|
||||||
Value = Value - 8;
|
Value = Value - 8;
|
||||||
@ -198,12 +209,17 @@ public:
|
|||||||
|
|
||||||
static unsigned getFixupKindNumBytes(unsigned Kind) {
|
static unsigned getFixupKindNumBytes(unsigned Kind) {
|
||||||
switch (Kind) {
|
switch (Kind) {
|
||||||
default: llvm_unreachable("Unknown fixup kind!");
|
default:
|
||||||
case FK_Data_4: return 4;
|
llvm_unreachable("Unknown fixup kind!");
|
||||||
case ARM::fixup_arm_ldst_pcrel_12: return 3;
|
case FK_Data_4:
|
||||||
case ARM::fixup_arm_pcrel_10: return 3;
|
return 4;
|
||||||
case ARM::fixup_arm_adr_pcrel_12: return 3;
|
case ARM::fixup_arm_ldst_pcrel_12:
|
||||||
case ARM::fixup_arm_branch: return 3;
|
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; }
|
const { return 0; }
|
||||||
unsigned getAdrLabelOpValue(const MachineInstr &MI, unsigned Op)
|
unsigned getAdrLabelOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
const { return 0; }
|
const { return 0; }
|
||||||
|
unsigned getThumbBLTargetOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
|
const { return 0; }
|
||||||
unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
|
unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
const { return 0; }
|
const { return 0; }
|
||||||
unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op)
|
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
|
// fixup_arm_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
|
||||||
// instruction.
|
// instruction.
|
||||||
fixup_arm_adr_pcrel_12,
|
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.
|
// instructions.
|
||||||
fixup_arm_branch,
|
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 next two are for the movt/movw pair
|
||||||
// the 16bit imm field are split into imm{15-12} and imm{11-0}
|
// 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.
|
// Define Thumb specific addressing modes.
|
||||||
|
|
||||||
|
def t_bltarget : Operand<i32> {
|
||||||
|
let EncoderMethod = "getThumbBLTargetOpValue";
|
||||||
|
}
|
||||||
|
|
||||||
def MemModeThumbAsmOperand : AsmOperandClass {
|
def MemModeThumbAsmOperand : AsmOperandClass {
|
||||||
let Name = "MemModeThumb";
|
let Name = "MemModeThumb";
|
||||||
let SuperClasses = [];
|
let SuperClasses = [];
|
||||||
@ -366,22 +370,29 @@ let isCall = 1,
|
|||||||
Uses = [SP] in {
|
Uses = [SP] in {
|
||||||
// Also used for Thumb2
|
// Also used for Thumb2
|
||||||
def tBL : TIx2<0b11110, 0b11, 1,
|
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",
|
"bl\t$func",
|
||||||
[(ARMtcall tglobaladdr:$func)]>,
|
[(ARMtcall tglobaladdr:$func)]>,
|
||||||
Requires<[IsThumb, IsNotDarwin]> {
|
Requires<[IsThumb, IsNotDarwin]> {
|
||||||
|
bits<21> func;
|
||||||
|
let Inst{25-16} = func{20-11};
|
||||||
let Inst{13} = 1;
|
let Inst{13} = 1;
|
||||||
let Inst{11} = 1;
|
let Inst{11} = 1;
|
||||||
|
let Inst{10-0} = func{10-0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ARMv5T and above, also used for Thumb2
|
// ARMv5T and above, also used for Thumb2
|
||||||
def tBLXi : TIx2<0b11110, 0b11, 0,
|
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",
|
"blx\t$func",
|
||||||
[(ARMcall tglobaladdr:$func)]>,
|
[(ARMcall tglobaladdr:$func)]>,
|
||||||
Requires<[IsThumb, HasV5T, IsNotDarwin]> {
|
Requires<[IsThumb, HasV5T, IsNotDarwin]> {
|
||||||
|
bits<21> func;
|
||||||
|
let Inst{25-16} = func{20-11};
|
||||||
let Inst{13} = 1;
|
let Inst{13} = 1;
|
||||||
let Inst{11} = 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
|
// Also used for Thumb2
|
||||||
@ -412,23 +423,29 @@ let isCall = 1,
|
|||||||
Uses = [R7, SP] in {
|
Uses = [R7, SP] in {
|
||||||
// Also used for Thumb2
|
// Also used for Thumb2
|
||||||
def tBLr9 : TIx2<0b11110, 0b11, 1,
|
def tBLr9 : TIx2<0b11110, 0b11, 1,
|
||||||
(outs), (ins pred:$p, i32imm:$func, variable_ops), IIC_Br,
|
(outs), (ins pred:$p, t_bltarget:$func, variable_ops),
|
||||||
"bl${p}\t$func",
|
IIC_Br, "bl${p}\t$func",
|
||||||
[(ARMtcall tglobaladdr:$func)]>,
|
[(ARMtcall tglobaladdr:$func)]>,
|
||||||
Requires<[IsThumb, IsDarwin]> {
|
Requires<[IsThumb, IsDarwin]> {
|
||||||
let Inst{13} = 1;
|
bits<21> func;
|
||||||
let Inst{11} = 1;
|
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
|
// ARMv5T and above, also used for Thumb2
|
||||||
def tBLXi_r9 : TIx2<0b11110, 0b11, 0,
|
def tBLXi_r9 : TIx2<0b11110, 0b11, 0,
|
||||||
(outs), (ins pred:$p, i32imm:$func, variable_ops),
|
(outs), (ins pred:$p, t_bltarget:$func, variable_ops),
|
||||||
IIC_Br,
|
IIC_Br, "blx${p}\t$func",
|
||||||
"blx${p}\t$func",
|
|
||||||
[(ARMcall tglobaladdr:$func)]>,
|
[(ARMcall tglobaladdr:$func)]>,
|
||||||
Requires<[IsThumb, HasV5T, IsDarwin]> {
|
Requires<[IsThumb, HasV5T, IsDarwin]> {
|
||||||
|
bits<21> func;
|
||||||
|
let Inst{25-16} = func{20-11};
|
||||||
let Inst{13} = 1;
|
let Inst{13} = 1;
|
||||||
let Inst{11} = 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
|
// Also used for Thumb2
|
||||||
|
@ -50,6 +50,7 @@ public:
|
|||||||
{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_arm_adr_pcrel_12", 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_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
|
{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_arm_movt_hi16", 0, 16, 0 },
|
{ "fixup_arm_movt_hi16", 0, 16, 0 },
|
||||||
{ "fixup_arm_movw_lo16", 0, 16, 0 },
|
{ "fixup_arm_movw_lo16", 0, 16, 0 },
|
||||||
};
|
};
|
||||||
@ -81,6 +82,11 @@ public:
|
|||||||
unsigned &Reg, unsigned &Imm,
|
unsigned &Reg, unsigned &Imm,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
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
|
/// getBranchTargetOpValue - Return encoding info for 24-bit immediate
|
||||||
/// branch target.
|
/// branch target.
|
||||||
uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
|
uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
@ -395,6 +401,24 @@ EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg,
|
|||||||
return isAdd;
|
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
|
/// getBranchTargetOpValue - Return encoding info for 24-bit immediate
|
||||||
/// branch target.
|
/// branch target.
|
||||||
uint32_t ARMMCCodeEmitter::
|
uint32_t ARMMCCodeEmitter::
|
||||||
|
@ -587,6 +587,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
|||||||
IMM("neon_vcvt_imm32");
|
IMM("neon_vcvt_imm32");
|
||||||
|
|
||||||
MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
|
MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
|
||||||
|
MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ?
|
||||||
MISC("bltarget", "kOperandTypeARMBranchTarget"); // ?
|
MISC("bltarget", "kOperandTypeARMBranchTarget"); // ?
|
||||||
MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I
|
MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I
|
||||||
MISC("shift_so_reg", "kOperandTypeARMSoReg"); // R, R, I
|
MISC("shift_so_reg", "kOperandTypeARMSoReg"); // R, R, I
|
||||||
|
Reference in New Issue
Block a user