Index: lib/Target/CellSPU/SPURegisterInfo.h
===================================================================
--- lib/Target/CellSPU/SPURegisterInfo.h	(revision 96782)
+++ lib/Target/CellSPU/SPURegisterInfo.h	(arbetskopia)
@@ -53,6 +53,10 @@
     virtual const TargetRegisterClass* const *
       getCalleeSavedRegClasses(const MachineFunction *MF) const;
 
+    //! Allow for scavenging, so we can get scratch registers when needed.
+	 virtual bool requiresRegisterScavenging(const MachineFunction &MF) const
+    { return true; }
+
     //! Return the reserved registers
     BitVector getReservedRegs(const MachineFunction &MF) const;
 
@@ -97,6 +101,18 @@
 
     //! Get DWARF debugging register number
     int getDwarfRegNum(unsigned RegNum, bool isEH) const;
+
+    /// Convert a machine instruction opcode from immediate adressing 
+    /// form (D) to two register addessing (X) form.
+    int dToXForm(int dFormOpcode) const;
+
+    /// Use the register scavenger to get a unused register, spilling
+    /// registers if needed.
+    unsigned findScratchRegister(MachineBasicBlock::iterator II,
+                                 RegScavenger *RS,
+                                 const TargetRegisterClass *RC, 
+                                 int SPAdj) const;
+    
   };
 } // end namespace llvm
 
Index: lib/Target/CellSPU/SPURegisterInfo.cpp
===================================================================
--- lib/Target/CellSPU/SPURegisterInfo.cpp	(revision 96782)
+++ lib/Target/CellSPU/SPURegisterInfo.cpp	(arbetskopia)
@@ -28,6 +28,7 @@
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineLocation.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
 #include "llvm/CodeGen/ValueTypes.h"
 #include "llvm/Target/TargetFrameInfo.h"
 #include "llvm/Target/TargetInstrInfo.h"
@@ -335,6 +336,7 @@
   MachineBasicBlock &MBB = *MI.getParent();
   MachineFunction &MF = *MBB.getParent();
   MachineFrameInfo *MFI = MF.getFrameInfo();
+  DebugLoc dl = II->getDebugLoc();
 
   while (!MI.getOperand(i).isFI()) {
     ++i;
@@ -363,11 +365,22 @@
 
   // Replace the FrameIndex with base register with $sp (aka $r1)
   SPOp.ChangeToRegister(SPU::R1, false);
-  if (Offset > SPUFrameInfo::maxFrameOffset()
-      || Offset < SPUFrameInfo::minFrameOffset()) {
-    errs() << "Large stack adjustment ("
-         << Offset
-         << ") in SPURegisterInfo::eliminateFrameIndex.";
+
+  // if 'Offset' doesn't fit to the D-form instruction's
+  // immediate, convert the instruction to X-form
+  // TODO optimize for the special case when the generated op is lqd/stqd
+  // TODO look into the possibility of not inserting the D-form in the first
+  //      place
+  if (!isS10Constant(Offset)) {
+    int newOpcode = dToXForm(MI.getOpcode());
+    unsigned tmpReg = findScratchRegister(II, RS, &SPU::R32CRegClass, SPAdj);
+    BuildMI(MBB, II, dl, TII.get(SPU::ILr32), tmpReg )
+        .addImm(Offset);
+    BuildMI(MBB, II, dl, TII.get(newOpcode), MI.getOperand(0).getReg())
+        .addReg(tmpReg)
+        .addReg(SPU::R1);
+    // remove the replaced D-form instruction
+    MBB.erase(II);
   } else {
     MO.ChangeToImmediate(Offset);
   }
@@ -474,7 +487,7 @@
         .addReg(SPU::R1);
       BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
         .addImm(FrameSize);
-      BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R1)
+      BuildMI(MBB, MBBI, dl, TII.get(SPU::STQXr32), SPU::R1)
         .addReg(SPU::R2)
         .addReg(SPU::R1);
       BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
@@ -573,7 +586,7 @@
         .addReg(SPU::R2);
       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
         .addImm(16)
-        .addReg(SPU::R2);
+        .addReg(SPU::R1);
       BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2).
         addReg(SPU::R2)
         .addImm(16);
@@ -617,4 +630,37 @@
   return SPUGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
 }
 
+int 
+SPURegisterInfo::dToXForm(int dFormOpcode) const
+{
+  int xFormOpcode;
+  switch(dFormOpcode) 
+  {
+    case SPU::AIr32:     xFormOpcode=SPU::Ar32;      break;
+    case SPU::LQDr32:    xFormOpcode=SPU::LQXr32;    break;
+    case SPU::LQDv16i8:  xFormOpcode=SPU::LQXv16i8;  break;
+    case SPU::STQDr32:   xFormOpcode=SPU::STQXr32;   break;
+    case SPU::STQDr128:  xFormOpcode=SPU::STQXr128;  break;
+    case SPU::STQDv4i32: xFormOpcode=SPU::STQXv4i32; break;
+    default: assert( false && "Unhandled D to X-form conversion");
+  }
+  return xFormOpcode;
+}
+
+// TODO this is already copied from PPC. Could this convenience function
+// be moved to the RegScavenger class?
+unsigned  
+SPURegisterInfo::findScratchRegister(MachineBasicBlock::iterator II, 
+                                     RegScavenger *RS,
+                                     const TargetRegisterClass *RC, 
+                                     int SPAdj) const
+{
+  assert(RS && "Register scavenging must be on");
+  unsigned Reg = RS->FindUnusedReg(RC);
+  if (Reg == 0)
+    Reg = RS->scavengeRegister(RC, II, SPAdj);
+  assert( Reg && "Register scavenger failed");
+  return Reg;
+}
+
 #include "SPUGenRegisterInfo.inc"
