mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-03-06 20:33:54 +00:00
Make Thumb2 LEA-like instruction into pseudos, which map down to ADR. Provide correct fixups for Thumb2 ADR,
which is _of course_ different from ARM ADR fixups, or any other Thumb2 fixup. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121721 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4dedddce93
commit
e8d02539d7
@ -136,6 +136,25 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
|||||||
// Encode the immediate and shift the opcode into place.
|
// Encode the immediate and shift the opcode into place.
|
||||||
return ARM_AM::getSOImmVal(Value) | (opc << 21);
|
return ARM_AM::getSOImmVal(Value) | (opc << 21);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ARM::fixup_t2_adr_pcrel_12: {
|
||||||
|
Value -= 4;
|
||||||
|
unsigned opc = 0;
|
||||||
|
if ((int64_t)Value < 0) {
|
||||||
|
Value = -Value;
|
||||||
|
opc = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t out = (opc << 21);
|
||||||
|
out |= (Value & 0x800) << 14;
|
||||||
|
out |= (Value & 0x700) << 4;
|
||||||
|
out |= (Value & 0x0FF);
|
||||||
|
|
||||||
|
uint64_t swapped = (out & 0xFFFF0000) >> 16;
|
||||||
|
swapped |= (out & 0x0000FFFF) << 16;
|
||||||
|
return swapped;
|
||||||
|
}
|
||||||
|
|
||||||
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.
|
||||||
@ -356,6 +375,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
|
|||||||
case ARM::fixup_t2_condbranch:
|
case ARM::fixup_t2_condbranch:
|
||||||
case ARM::fixup_t2_uncondbranch:
|
case ARM::fixup_t2_uncondbranch:
|
||||||
case ARM::fixup_t2_pcrel_10:
|
case ARM::fixup_t2_pcrel_10:
|
||||||
|
case ARM::fixup_t2_adr_pcrel_12:
|
||||||
case ARM::fixup_arm_thumb_bl:
|
case ARM::fixup_arm_thumb_bl:
|
||||||
case ARM::fixup_arm_thumb_blx:
|
case ARM::fixup_arm_thumb_blx:
|
||||||
return 4;
|
return 4;
|
||||||
|
@ -213,6 +213,8 @@ namespace {
|
|||||||
const { return 0; }
|
const { return 0; }
|
||||||
unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op)
|
unsigned getImmMinusOneOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
const { return 0; }
|
const { return 0; }
|
||||||
|
unsigned getT2AdrLabelOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
|
const { return 0; }
|
||||||
unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op)
|
unsigned getAddrMode6AddressOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
const { return 0; }
|
const { return 0; }
|
||||||
unsigned getAddrMode6DupAddressOpValue(const MachineInstr &MI, unsigned Op)
|
unsigned getAddrMode6DupAddressOpValue(const MachineInstr &MI, unsigned Op)
|
||||||
|
@ -594,7 +594,7 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &MF,
|
|||||||
NegOk = true;
|
NegOk = true;
|
||||||
IsSoImm = true;
|
IsSoImm = true;
|
||||||
break;
|
break;
|
||||||
case ARM::t2LEApcrel:
|
case ARM::t2ADR:
|
||||||
Bits = 12;
|
Bits = 12;
|
||||||
NegOk = true;
|
NegOk = true;
|
||||||
break;
|
break;
|
||||||
@ -1555,7 +1555,7 @@ bool ARMConstantIslands::OptimizeThumb2Instructions(MachineFunction &MF) {
|
|||||||
unsigned Bits = 0;
|
unsigned Bits = 0;
|
||||||
switch (Opcode) {
|
switch (Opcode) {
|
||||||
default: break;
|
default: break;
|
||||||
case ARM::t2LEApcrel:
|
case ARM::t2ADR:
|
||||||
if (isARMLowRegister(U.MI->getOperand(0).getReg())) {
|
if (isARMLowRegister(U.MI->getOperand(0).getReg())) {
|
||||||
NewOpc = ARM::tLEApcrel;
|
NewOpc = ARM::tLEApcrel;
|
||||||
Bits = 8;
|
Bits = 8;
|
||||||
@ -1754,16 +1754,16 @@ bool ARMConstantIslands::OptimizeThumb2JumpTables(MachineFunction &MF) {
|
|||||||
if (!OptOk)
|
if (!OptOk)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Now scan back again to find the tLEApcrel or t2LEApcrelJT instruction
|
// Now scan back again to find the tLEApcrel or t2ADR instruction
|
||||||
// that gave us the initial base register definition.
|
// that gave us the initial base register definition.
|
||||||
for (--PrevI; PrevI != B && !PrevI->definesRegister(BaseReg); --PrevI)
|
for (--PrevI; PrevI != B && !PrevI->definesRegister(BaseReg); --PrevI)
|
||||||
;
|
;
|
||||||
|
|
||||||
// The instruction should be a tLEApcrel or t2LEApcrelJT; we want
|
// The instruction should be a tLEApcrel or t2ADR; we want
|
||||||
// to delete it as well.
|
// to delete it as well.
|
||||||
MachineInstr *LeaMI = PrevI;
|
MachineInstr *LeaMI = PrevI;
|
||||||
if ((LeaMI->getOpcode() != ARM::tLEApcrelJT &&
|
if ((LeaMI->getOpcode() != ARM::tLEApcrelJT &&
|
||||||
LeaMI->getOpcode() != ARM::t2LEApcrelJT) ||
|
LeaMI->getOpcode() != ARM::t2ADR) ||
|
||||||
LeaMI->getOperand(0).getReg() != BaseReg)
|
LeaMI->getOperand(0).getReg() != BaseReg)
|
||||||
OptOk = false;
|
OptOk = false;
|
||||||
|
|
||||||
|
@ -763,6 +763,21 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ARM::t2LEApcrel:
|
||||||
|
case ARM::t2LEApcrelJT: {
|
||||||
|
bool DstIsDead = MI.getOperand(0).isDead();
|
||||||
|
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
|
||||||
|
TII->get(ARM::t2ADR))
|
||||||
|
.addReg(MI.getOperand(0).getReg(),
|
||||||
|
RegState::Define | getDeadRegState(DstIsDead)) // Dst reg
|
||||||
|
.addOperand(MI.getOperand(1)) // Label
|
||||||
|
.addOperand(MI.getOperand(2)) // Pred
|
||||||
|
.addOperand(MI.getOperand(3));
|
||||||
|
TransferImpOps(MI, MIB, MIB);
|
||||||
|
MI.eraseFromParent();
|
||||||
|
return MIB;
|
||||||
|
}
|
||||||
|
|
||||||
case ARM::MOVi32imm:
|
case ARM::MOVi32imm:
|
||||||
case ARM::MOVCCi32imm:
|
case ARM::MOVCCi32imm:
|
||||||
case ARM::t2MOVi32imm:
|
case ARM::t2MOVi32imm:
|
||||||
|
@ -33,6 +33,9 @@ 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_t2_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
|
||||||
|
// instruction.
|
||||||
|
fixup_t2_adr_pcrel_12,
|
||||||
// fixup_arm_branch - 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,
|
||||||
|
@ -131,6 +131,12 @@ def t2addrmode_imm12 : Operand<i32>,
|
|||||||
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
|
let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ADR instruction labels.
|
||||||
|
def t2adrlabel : Operand<i32> {
|
||||||
|
let EncoderMethod = "getT2AdrLabelOpValue";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// t2addrmode_imm8 := reg +/- imm8
|
// t2addrmode_imm8 := reg +/- imm8
|
||||||
def t2addrmode_imm8 : Operand<i32>,
|
def t2addrmode_imm8 : Operand<i32>,
|
||||||
ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
|
ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> {
|
||||||
@ -1128,10 +1134,11 @@ class T2PCOneRegImm<dag oops, dag iops, InstrItinClass itin,
|
|||||||
|
|
||||||
// LEApcrel - Load a pc-relative address into a register without offending the
|
// LEApcrel - Load a pc-relative address into a register without offending the
|
||||||
// assembler.
|
// assembler.
|
||||||
let neverHasSideEffects = 1 in {
|
let neverHasSideEffects = 1, isReMaterializable = 1 in {
|
||||||
let isReMaterializable = 1 in
|
|
||||||
def t2LEApcrel : T2PCOneRegImm<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p), IIC_iALUi,
|
def t2ADR : T2PCOneRegImm<(outs rGPR:$Rd),
|
||||||
"adr${p}.w\t$Rd, #$label", []> {
|
(ins t2adrlabel:$addr, pred:$p),
|
||||||
|
IIC_iALUi, "adr{$p}.w\t$Rd, #$addr", []> {
|
||||||
let Inst{31-27} = 0b11110;
|
let Inst{31-27} = 0b11110;
|
||||||
let Inst{25-24} = 0b10;
|
let Inst{25-24} = 0b10;
|
||||||
// Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE)
|
// Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE)
|
||||||
@ -1140,19 +1147,21 @@ def t2LEApcrel : T2PCOneRegImm<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p), II
|
|||||||
let Inst{19-16} = 0b1111; // Rn
|
let Inst{19-16} = 0b1111; // Rn
|
||||||
let Inst{15} = 0;
|
let Inst{15} = 0;
|
||||||
|
|
||||||
|
bits<4> Rd;
|
||||||
|
bits<13> addr;
|
||||||
|
let Inst{11-8} = Rd;
|
||||||
|
let Inst{23} = addr{12};
|
||||||
|
let Inst{21} = addr{12};
|
||||||
|
let Inst{26} = addr{11};
|
||||||
|
let Inst{14-12} = addr{10-8};
|
||||||
|
let Inst{7-0} = addr{7-0};
|
||||||
}
|
}
|
||||||
} // neverHasSideEffects
|
|
||||||
def t2LEApcrelJT : T2PCOneRegImm<(outs rGPR:$Rd),
|
def t2LEApcrel : PseudoInst<(outs rGPR:$Rd), (ins i32imm:$label, pred:$p),
|
||||||
|
IIC_iALUi, []>;
|
||||||
|
def t2LEApcrelJT : PseudoInst<(outs rGPR:$Rd),
|
||||||
(ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi,
|
(ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi,
|
||||||
"adr${p}.w\t$Rd, #${label}_${id}", []> {
|
[]>;
|
||||||
let Inst{31-27} = 0b11110;
|
|
||||||
let Inst{25-24} = 0b10;
|
|
||||||
// Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE)
|
|
||||||
let Inst{22} = 0;
|
|
||||||
let Inst{20} = 0;
|
|
||||||
let Inst{19-16} = 0b1111; // Rn
|
|
||||||
let Inst{15} = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,6 +56,8 @@ public:
|
|||||||
{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
|
{ "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
|
||||||
MCFixupKindInfo::FKF_IsAligned},
|
MCFixupKindInfo::FKF_IsAligned},
|
||||||
{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
|
{ "fixup_t2_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel |
|
||||||
|
MCFixupKindInfo::FKF_IsAligned},
|
||||||
{ "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
|
||||||
@ -133,6 +135,9 @@ public:
|
|||||||
/// ADR label target.
|
/// ADR label target.
|
||||||
uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
SmallVectorImpl<MCFixup> &Fixups) const;
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
uint32_t getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups) const;
|
||||||
|
|
||||||
|
|
||||||
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
|
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
|
||||||
/// operand.
|
/// operand.
|
||||||
@ -544,6 +549,16 @@ getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
|||||||
Fixups);
|
Fixups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
|
||||||
|
/// target.
|
||||||
|
uint32_t ARMMCCodeEmitter::
|
||||||
|
getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups) const {
|
||||||
|
assert(MI.getOperand(OpIdx).isExpr() && "Unexpected adr target type!");
|
||||||
|
return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_adr_pcrel_12,
|
||||||
|
Fixups);
|
||||||
|
}
|
||||||
|
|
||||||
/// getTAddrModeRegRegOpValue - Return encoding info for 'reg + reg' operand.
|
/// getTAddrModeRegRegOpValue - Return encoding info for 'reg + reg' operand.
|
||||||
uint32_t ARMMCCodeEmitter::
|
uint32_t ARMMCCodeEmitter::
|
||||||
getTAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
|
getTAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
@ -584,6 +584,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
|||||||
IMM("t_imm_s4");
|
IMM("t_imm_s4");
|
||||||
IMM("pclabel");
|
IMM("pclabel");
|
||||||
IMM("adrlabel");
|
IMM("adrlabel");
|
||||||
|
IMM("t2adrlabel");
|
||||||
IMM("shift_imm");
|
IMM("shift_imm");
|
||||||
IMM("neon_vcvt_imm32");
|
IMM("neon_vcvt_imm32");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user