1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02: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:
Bill Wendling 2010-12-15 23:32:27 +00:00
parent ed6c88ead9
commit 63ebdf4786
2 changed files with 38 additions and 29 deletions

View File

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

View File

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