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:
Jim Grosbach 2010-12-06 23:57:07 +00:00
parent 6033b346e2
commit 662a816e89
7 changed files with 80 additions and 17 deletions

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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}

View File

@ -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

View File

@ -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::

View File

@ -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