mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-28 06:32:09 +00:00
Thumb1 ADD/SUB SP instructions are predicable in Thumb2 mode.
Add the predicate operand to the instructions. Update the back end accordingly where the instructions are used. Restrict the SP operands to actually only be SP, as otherwise these break assembly parsing for the normal instruction variants. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138445 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e234d02204
commit
5b81584f74
@ -1098,11 +1098,11 @@ materializeFrameBaseRegister(MachineBasicBlock *MBB,
|
||||
MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
|
||||
MRI.constrainRegClass(BaseReg, TII.getRegClass(MCID, 0, this));
|
||||
|
||||
MachineInstrBuilder MIB = BuildMI(*MBB, Ins, DL, MCID, BaseReg)
|
||||
.addFrameIndex(FrameIdx).addImm(Offset);
|
||||
MachineInstrBuilder MIB = AddDefaultPred(BuildMI(*MBB, Ins, DL, MCID, BaseReg)
|
||||
.addFrameIndex(FrameIdx).addImm(Offset));
|
||||
|
||||
if (!AFI->isThumb1OnlyFunction())
|
||||
AddDefaultCC(AddDefaultPred(MIB));
|
||||
AddDefaultCC(MIB);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2338,8 +2338,9 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
|
||||
int FI = cast<FrameIndexSDNode>(N)->getIndex();
|
||||
SDValue TFI = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
|
||||
if (Subtarget->isThumb1Only()) {
|
||||
return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, TFI,
|
||||
CurDAG->getTargetConstant(0, MVT::i32));
|
||||
SDValue Ops[] = { TFI, CurDAG->getTargetConstant(0, MVT::i32),
|
||||
getAL(CurDAG), CurDAG->getRegister(0, MVT::i32) };
|
||||
return CurDAG->SelectNodeTo(N, ARM::tADDrSPi, MVT::i32, Ops, 4);
|
||||
} else {
|
||||
unsigned Opc = ((Subtarget->isThumb() && Subtarget->hasThumb2()) ?
|
||||
ARM::t2ADDri : ARM::ADDri);
|
||||
|
@ -305,8 +305,8 @@ def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, "",
|
||||
// This is rematerializable, which is particularly useful for taking the
|
||||
// address of locals.
|
||||
let isReMaterializable = 1 in
|
||||
def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi,
|
||||
"add\t$dst, $sp, $rhs", []>,
|
||||
def tADDrSPi : T1pI<(outs tGPR:$dst), (ins GPRsp:$sp, t_imm_s4:$rhs), IIC_iALUi,
|
||||
"add", "\t$dst, $sp, $rhs", []>,
|
||||
T1Encoding<{1,0,1,0,1,?}> {
|
||||
// A6.2 & A8.6.8
|
||||
bits<3> dst;
|
||||
@ -317,8 +317,8 @@ def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi,
|
||||
}
|
||||
|
||||
// ADD sp, sp, #<imm7>
|
||||
def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi,
|
||||
"add\t$dst, $rhs", []>,
|
||||
def tADDspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm_s4:$rhs),
|
||||
IIC_iALUi, "add", "\t$Rdn, $rhs", []>,
|
||||
T1Misc<{0,0,0,0,0,?,?}> {
|
||||
// A6.2.5 & A8.6.8
|
||||
bits<7> rhs;
|
||||
@ -328,8 +328,8 @@ def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi,
|
||||
|
||||
// SUB sp, sp, #<imm7>
|
||||
// FIXME: The encoding and the ASM string don't match up.
|
||||
def tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi,
|
||||
"sub\t$dst, $rhs", []>,
|
||||
def tSUBspi : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, t_imm_s4:$rhs),
|
||||
IIC_iALUi, "sub", "\t$Rdn, $rhs", []>,
|
||||
T1Misc<{0,0,0,0,1,?,?}> {
|
||||
// A6.2.5 & A8.6.214
|
||||
bits<7> rhs;
|
||||
@ -338,25 +338,25 @@ def tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi,
|
||||
}
|
||||
|
||||
// ADD <Rm>, sp
|
||||
def tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
|
||||
"add\t$dst, $rhs", []>,
|
||||
def tADDrSP : T1pIt<(outs GPR:$Rdn), (ins GPR:$Rn, GPRsp:$rhs), IIC_iALUr,
|
||||
"add", "\t$Rdn, $rhs", []>,
|
||||
T1Special<{0,0,?,?}> {
|
||||
// A8.6.9 Encoding T1
|
||||
bits<4> dst;
|
||||
let Inst{7} = dst{3};
|
||||
bits<4> Rdn;
|
||||
let Inst{7} = Rdn{3};
|
||||
let Inst{6-3} = 0b1101;
|
||||
let Inst{2-0} = dst{2-0};
|
||||
let Inst{2-0} = Rdn{2-0};
|
||||
let DecoderMethod = "DecodeThumbAddSPReg";
|
||||
}
|
||||
|
||||
// ADD sp, <Rm>
|
||||
def tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr,
|
||||
"add\t$dst, $rhs", []>,
|
||||
def tADDspr : T1pIt<(outs GPRsp:$Rdn), (ins GPRsp:$Rn, GPR:$rhs), IIC_iALUr,
|
||||
"add", "\t$Rdn, $rhs", []>,
|
||||
T1Special<{0,0,?,?}> {
|
||||
// A8.6.9 Encoding T2
|
||||
bits<4> dst;
|
||||
bits<4> Rdn;
|
||||
let Inst{7} = 1;
|
||||
let Inst{6-3} = dst;
|
||||
let Inst{6-3} = Rdn;
|
||||
let Inst{2-0} = 0b101;
|
||||
let DecoderMethod = "DecodeThumbAddSPReg";
|
||||
}
|
||||
|
@ -225,6 +225,13 @@ def GPRnopc : RegisterClass<"ARM", [i32], 32, (sub GPR, PC)> {
|
||||
}];
|
||||
}
|
||||
|
||||
// GPRsp - Only the SP is legal. Used by Thumb1 instructions that want the
|
||||
// implied SP argument list.
|
||||
// FIXME: It would be better to not use this at all and refactor the
|
||||
// instructions to not have SP an an explicit argument. That makes
|
||||
// frame index resolution a bit trickier, though.
|
||||
def GPRsp : RegisterClass<"ARM", [i32], 32, (add SP)>;
|
||||
|
||||
// restricted GPR register class. Many Thumb2 instructions allow the full
|
||||
// register range for operands, but have undefined behaviours when PC
|
||||
// or SP (R13 or R15) are used. The ARM ISA refers to these operands
|
||||
|
@ -133,9 +133,9 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
|
||||
// Adjust FP so it point to the stack slot that contains the previous FP.
|
||||
if (hasFP(MF)) {
|
||||
BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr)
|
||||
AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr)
|
||||
.addFrameIndex(FramePtrSpillFI).addImm(0)
|
||||
.setMIFlags(MachineInstr::FrameSetup);
|
||||
.setMIFlags(MachineInstr::FrameSetup));
|
||||
if (NumBytes > 508)
|
||||
// If offset is > 508 then sp cannot be adjusted in a single instruction,
|
||||
// try restoring from fp instead.
|
||||
|
@ -181,7 +181,6 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
||||
int Opc = 0;
|
||||
int ExtraOpc = 0;
|
||||
bool NeedCC = false;
|
||||
bool NeedPred = false;
|
||||
|
||||
if (DestReg == BaseReg && BaseReg == ARM::SP) {
|
||||
assert(isMul4 && "Thumb sp inc / dec size must be multiple of 4!");
|
||||
@ -216,7 +215,7 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
||||
} else {
|
||||
Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
|
||||
NumBits = 8;
|
||||
NeedPred = NeedCC = true;
|
||||
NeedCC = true;
|
||||
}
|
||||
isTwoAddr = true;
|
||||
}
|
||||
@ -262,8 +261,7 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
||||
if (NeedCC)
|
||||
MIB = AddDefaultT1CC(MIB);
|
||||
MIB.addReg(DestReg).addImm(ThisVal);
|
||||
if (NeedPred)
|
||||
MIB = AddDefaultPred(MIB);
|
||||
MIB = AddDefaultPred(MIB);
|
||||
MIB.setMIFlags(MIFlags);
|
||||
} else {
|
||||
bool isKill = BaseReg != ARM::SP;
|
||||
@ -271,8 +269,7 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
||||
if (NeedCC)
|
||||
MIB = AddDefaultT1CC(MIB);
|
||||
MIB.addReg(BaseReg, getKillRegState(isKill)).addImm(ThisVal);
|
||||
if (NeedPred)
|
||||
MIB = AddDefaultPred(MIB);
|
||||
MIB = AddDefaultPred(MIB);
|
||||
MIB.setMIFlags(MIFlags);
|
||||
|
||||
BaseReg = DestReg;
|
||||
@ -284,7 +281,7 @@ void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
||||
Scale = 1;
|
||||
Chunk = ((1 << NumBits) - 1) * Scale;
|
||||
Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
|
||||
NeedPred = NeedCC = isTwoAddr = true;
|
||||
NeedCC = isTwoAddr = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -404,7 +401,6 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
|
||||
unsigned Scale = 1;
|
||||
if (FrameReg != ARM::SP) {
|
||||
Opcode = ARM::tADDi3;
|
||||
MI.setDesc(TII.get(Opcode));
|
||||
NumBits = 3;
|
||||
} else {
|
||||
NumBits = 8;
|
||||
@ -418,10 +414,9 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
|
||||
// Turn it into a move.
|
||||
MI.setDesc(TII.get(ARM::tMOVr));
|
||||
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
|
||||
// Remove offset and add predicate operands.
|
||||
// Remove offset
|
||||
MI.RemoveOperand(FrameRegIdx+1);
|
||||
MachineInstrBuilder MIB(&MI);
|
||||
AddDefaultPred(MIB);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -430,6 +425,7 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
|
||||
if (((Offset / Scale) & ~Mask) == 0) {
|
||||
// Replace the FrameIndex with sp / fp
|
||||
if (Opcode == ARM::tADDi3) {
|
||||
MI.setDesc(TII.get(Opcode));
|
||||
removeOperands(MI, FrameRegIdx);
|
||||
MachineInstrBuilder MIB(&MI);
|
||||
AddDefaultPred(AddDefaultT1CC(MIB).addReg(FrameReg)
|
||||
@ -478,10 +474,6 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
|
||||
MI.setDesc(TII.get(ARM::tADDhirr));
|
||||
MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false, false, true);
|
||||
MI.getOperand(FrameRegIdx+1).ChangeToRegister(FrameReg, false);
|
||||
if (Opcode == ARM::tADDi3) {
|
||||
MachineInstrBuilder MIB(&MI);
|
||||
AddDefaultPred(MIB);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
@ -235,9 +235,8 @@ void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
|
||||
if (DestReg == ARM::SP && (ThisVal < ((1 << 7)-1) * 4)) {
|
||||
assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?");
|
||||
Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
|
||||
// FIXME: Fix Thumb1 immediate encoding.
|
||||
BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
|
||||
.addReg(BaseReg).addImm(ThisVal/4).setMIFlags(MIFlags);
|
||||
AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
|
||||
.addReg(BaseReg).addImm(ThisVal/4).setMIFlags(MIFlags));
|
||||
NumBytes = 0;
|
||||
continue;
|
||||
}
|
||||
|
@ -507,6 +507,7 @@ Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
|
||||
.addOperand(MI->getOperand(0))
|
||||
.addOperand(MI->getOperand(1))
|
||||
.addImm(Imm / 4); // The tADDrSPi has an implied scale by four.
|
||||
AddDefaultPred(MIB);
|
||||
|
||||
// Transfer MI flags.
|
||||
MIB.setMIFlags(MI->getFlags());
|
||||
|
@ -556,6 +556,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
|
||||
REG("GPR");
|
||||
REG("rGPR");
|
||||
REG("GPRnopc");
|
||||
REG("GPRsp");
|
||||
REG("tcGPR");
|
||||
REG("cc_out");
|
||||
REG("s_cc_out");
|
||||
|
Loading…
x
Reference in New Issue
Block a user