mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-30 08:44:48 +00:00
If we're changing the frame register to a physical register other than SP, we
need to use tLDRi and tSTRi instead of tLDRspi and tSTRspi respectively. llvm-svn: 121915
This commit is contained in:
parent
ed6c88ead9
commit
63ebdf4786
@ -806,10 +806,9 @@ getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
// [SP, #imm]
|
||||
// {7-0} = imm8
|
||||
const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
|
||||
#if 0 // FIXME: This crashes2003-05-14-initialize-string.c
|
||||
assert(MI.getOperand(OpIdx).getReg() == ARM::SP &&
|
||||
"Unexpected base register!");
|
||||
#endif
|
||||
|
||||
// The immediate is already shifted for the implicit zeroes, so no change
|
||||
// here.
|
||||
return MO1.getImm() & 0xff;
|
||||
|
@ -351,6 +351,20 @@ static void removeOperands(MachineInstr &MI, unsigned i) {
|
||||
MI.RemoveOperand(Op);
|
||||
}
|
||||
|
||||
/// convertToNonSPOpcode - Change the opcode to the non-SP version, because
|
||||
/// we're replacing the frame index with a non-SP register.
|
||||
static unsigned convertToNonSPOpcode(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case ARM::tLDRspi:
|
||||
return ARM::tLDRi;
|
||||
|
||||
case ARM::tSTRspi:
|
||||
return ARM::tSTRi;
|
||||
}
|
||||
|
||||
return Opcode;
|
||||
}
|
||||
|
||||
bool Thumb1RegisterInfo::
|
||||
rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
|
||||
unsigned FrameReg, int &Offset,
|
||||
@ -452,55 +466,51 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
unsigned ImmIdx = 0;
|
||||
int InstrOffs = 0;
|
||||
unsigned NumBits = 0;
|
||||
unsigned Scale = 1;
|
||||
switch (AddrMode) {
|
||||
case ARMII::AddrModeT1_s: {
|
||||
ImmIdx = FrameRegIdx+1;
|
||||
InstrOffs = MI.getOperand(ImmIdx).getImm();
|
||||
NumBits = (FrameReg == ARM::SP) ? 8 : 5;
|
||||
Scale = 4;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (AddrMode != ARMII::AddrModeT1_s)
|
||||
llvm_unreachable("Unsupported addressing mode!");
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned ImmIdx = FrameRegIdx + 1;
|
||||
int InstrOffs = MI.getOperand(ImmIdx).getImm();
|
||||
unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5;
|
||||
unsigned Scale = 4;
|
||||
|
||||
Offset += InstrOffs * Scale;
|
||||
assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
|
||||
assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!");
|
||||
|
||||
// Common case: small offset, fits into instruction.
|
||||
MachineOperand &ImmOp = MI.getOperand(ImmIdx);
|
||||
int ImmedOffset = Offset / Scale;
|
||||
unsigned Mask = (1 << NumBits) - 1;
|
||||
|
||||
if ((unsigned)Offset <= Mask * Scale) {
|
||||
// Replace the FrameIndex with sp
|
||||
// Replace the FrameIndex with the frame register (e.g., sp).
|
||||
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
|
||||
ImmOp.ChangeToImmediate(ImmedOffset);
|
||||
|
||||
// If we're using a register where sp was stored, convert the instruction
|
||||
// to the non-SP version.
|
||||
unsigned NewOpc = convertToNonSPOpcode(Opcode);
|
||||
if (NewOpc != Opcode && FrameReg != ARM::SP)
|
||||
MI.setDesc(TII.get(NewOpc));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isThumSpillRestore = Opcode == ARM::tRestore || Opcode == ARM::tSpill;
|
||||
if (AddrMode == ARMII::AddrModeT1_s) {
|
||||
// Thumb tLDRspi, tSTRspi. These will change to instructions that use
|
||||
// a different base register.
|
||||
NumBits = 5;
|
||||
Mask = (1 << NumBits) - 1;
|
||||
}
|
||||
NumBits = 5;
|
||||
Mask = (1 << NumBits) - 1;
|
||||
|
||||
// If this is a thumb spill / restore, we will be using a constpool load to
|
||||
// materialize the offset.
|
||||
if (AddrMode == ARMII::AddrModeT1_s && isThumSpillRestore)
|
||||
if (Opcode == ARM::tRestore || Opcode == ARM::tSpill) {
|
||||
ImmOp.ChangeToImmediate(0);
|
||||
else {
|
||||
} else {
|
||||
// Otherwise, it didn't fit. Pull in what we can to simplify the immed.
|
||||
ImmedOffset = ImmedOffset & Mask;
|
||||
ImmOp.ChangeToImmediate(ImmedOffset);
|
||||
Offset &= ~(Mask*Scale);
|
||||
Offset &= ~(Mask * Scale);
|
||||
}
|
||||
}
|
||||
|
||||
return Offset == 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user