Renamed PPC32 (namespace for regs, opcodes) to PPC to include 64-bit targets
[oota-llvm.git] / lib / Target / SparcV8 / SparcV8ISelSimple.cpp
index 5cf9131b1ef284831bf481b37e38bde25ec35d5d..ac33ef574b8ff7a40efda02c0fd02e0a440ea0e2 100644 (file)
@@ -232,8 +232,8 @@ void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB,
       // Copy the value into the register pair.
       // R = top(more-significant) half, R+1 = bottom(less-significant) half
       uint64_t Val = cast<ConstantInt>(C)->getRawValue();
-      unsigned topHalf = Val & 0xffffffffU;
-      unsigned bottomHalf = Val >> 32;
+      unsigned bottomHalf = Val & 0xffffffffU;
+      unsigned topHalf = Val >> 32;
       unsigned HH = topHalf >> 10;
       unsigned HM = topHalf & 0x03ff;
       unsigned LM = bottomHalf >> 10;
@@ -288,28 +288,47 @@ void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB,
   } else if (isa<ConstantPointerNull>(C)) {
     // Copy zero (null pointer) to the register.
     BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addSImm (0);
-  } else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)) {
+  } else if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
     // Copy it with a SETHI/OR pair; the JIT + asmwriter should recognize
     // that SETHI %reg,global == SETHI %reg,%hi(global) and 
     // OR %reg,global,%reg == OR %reg,%lo(global),%reg.
     unsigned TmpReg = makeAnotherReg (C->getType ());
-    BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addGlobalAddress (CPR->getValue());
-    BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg)
-      .addGlobalAddress (CPR->getValue ());
+    BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addGlobalAddress(GV);
+    BuildMI (*MBB, IP, V8::ORri, 2, R).addReg(TmpReg).addGlobalAddress(GV);
   } else {
     std::cerr << "Offending constant: " << *C << "\n";
     assert (0 && "Can't copy this kind of constant into register yet");
   }
 }
 
-void V8ISel::LoadArgumentsToVirtualRegs (Function *F) {
-  unsigned ArgOffset = 0;
+void V8ISel::LoadArgumentsToVirtualRegs (Function *LF) {
+  unsigned ArgOffset;
   static const unsigned IncomingArgRegs[] = { V8::I0, V8::I1, V8::I2,
     V8::I3, V8::I4, V8::I5 };
-  assert (F->asize () < 7
+  assert (LF->asize () < 7
           && "Can't handle loading excess call args off the stack yet");
 
-  for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I) {
+  // Add IMPLICIT_DEFs of input regs.
+  ArgOffset = 0;
+  for (Function::aiterator I = LF->abegin(), E = LF->aend(); I != E; ++I) {
+    unsigned Reg = getReg(*I);
+    switch (getClassB(I->getType())) {
+    case cByte:
+    case cShort:
+    case cInt:
+    case cFloat:
+      BuildMI(BB, V8::IMPLICIT_DEF, 0, IncomingArgRegs[ArgOffset]);
+      break;
+    default:
+      // FIXME: handle cDouble, cLong
+      assert (0 && "64-bit (double, long, etc.) function args not handled");
+      return;
+    }
+    ++ArgOffset;
+  }
+
+  ArgOffset = 0;
+  for (Function::aiterator I = LF->abegin(), E = LF->aend(); I != E; ++I) {
     unsigned Reg = getReg(*I);
     switch (getClassB(I->getType())) {
     case cByte:
@@ -318,12 +337,24 @@ void V8ISel::LoadArgumentsToVirtualRegs (Function *F) {
       BuildMI(BB, V8::ORrr, 2, Reg).addReg (V8::G0)
         .addReg (IncomingArgRegs[ArgOffset]);
       break;
+    case cFloat: {
+      // Single-fp args are passed in integer registers; go through
+      // memory to get them into FP registers. (Bleh!)
+      unsigned FltAlign = TM.getTargetData().getFloatAlignment();
+      int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign);
+      BuildMI (BB, V8::ST, 3).addFrameIndex (FI).addSImm (0)
+        .addReg (IncomingArgRegs[ArgOffset]);
+      BuildMI (BB, V8::LDFri, 2, Reg).addFrameIndex (FI).addSImm (0);
+      break;
+    }
     default:
-      assert (0 && "Only <=32-bit, integral arguments currently handled");
+      // FIXME: handle cDouble, cLong
+      assert (0 && "64-bit (double, long, etc.) function args not handled");
       return;
     }
     ++ArgOffset;
   }
+
 }
 
 void V8ISel::SelectPHINodes() {
@@ -565,6 +596,17 @@ void V8ISel::emitCastOperation(MachineBasicBlock *BB,
         break;
       }
       }
+    } else if (newTyClass == cLong) {
+      if (oldTyClass == cLong) {
+        // Just copy it
+        BuildMI (*BB, IP, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (SrcReg);
+        BuildMI (*BB, IP, V8::ORrr, 2, DestReg+1).addReg (V8::G0)
+          .addReg (SrcReg+1);
+      } else {
+        std::cerr << "Cast still unsupported: SrcTy = "
+                  << *SrcTy << ", DestTy = " << *DestTy << "\n";
+        abort ();
+      }
     } else {
       std::cerr << "Cast still unsupported: SrcTy = "
                 << *SrcTy << ", DestTy = " << *DestTy << "\n";
@@ -657,12 +699,23 @@ void V8ISel::visitCallInst(CallInst &I) {
     V8::O4, V8::O5 };
   for (unsigned i = 1; i < 7; ++i)
     if (i < I.getNumOperands ()) {
-      assert (getClassB (I.getOperand (i)->getType ()) < cLong
-              && "Can't handle long or fp function call arguments yet");
       unsigned ArgReg = getReg (I.getOperand (i));
-      // Schlep it over into the incoming arg register
-      BuildMI (BB, V8::ORrr, 2, OutgoingArgRegs[i - 1]).addReg (V8::G0)
-        .addReg (ArgReg);
+      if (getClassB (I.getOperand (i)->getType ()) < cLong) {
+        // Schlep it over into the incoming arg register
+        BuildMI (BB, V8::ORrr, 2, OutgoingArgRegs[i - 1]).addReg (V8::G0)
+          .addReg (ArgReg);
+      } else if (getClassB (I.getOperand (i)->getType ()) == cFloat) {
+        // Single-fp args are passed in integer registers; go through
+        // memory to get them out of FP registers. (Bleh!)
+        unsigned FltAlign = TM.getTargetData().getFloatAlignment();
+        int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign);
+        BuildMI (BB, V8::STFri, 3).addFrameIndex (FI).addSImm (0)
+          .addReg (ArgReg);
+        BuildMI (BB, V8::LD, 2, OutgoingArgRegs[i - 1]).addFrameIndex (FI)
+          .addSImm (0);
+      } else {
+        assert (0 && "64-bit (double, long, etc.) 'call' opnds not handled");
+      }
     }
 
   // Emit call instruction
@@ -702,6 +755,21 @@ void V8ISel::visitReturnInst(ReturnInst &I) {
         // Schlep it over into i0 (where it will become o0 after restore).
         BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
         break;
+      case cFloat:
+        BuildMI (BB, V8::FMOVS, 2, V8::F0).addReg(RetValReg);
+        break;
+      case cDouble: {
+        unsigned DoubleAlignment = TM.getTargetData().getDoubleAlignment();
+        int FI = F->getFrameInfo()->CreateStackObject(8, DoubleAlignment);
+        BuildMI (BB, V8::STDFri, 3).addFrameIndex (FI).addSImm (0)
+          .addReg (RetValReg);
+        BuildMI (BB, V8::LDDFri, 2, V8::F0).addFrameIndex (FI).addSImm (0);
+        break;
+      }
+      case cLong:
+        BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
+        BuildMI (BB, V8::ORrr, 2, V8::I1).addReg(V8::G0).addReg(RetValReg+1);
+        break;
       default:
         std::cerr << "Return instruction of this type not handled: " << I;
         abort ();
@@ -886,7 +954,7 @@ void V8ISel::visitBinaryOperator (Instruction &I) {
     BuildMI (BB, Opcodes[OpCase], 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
   }
 
-  switch (getClass (I.getType ())) {
+  switch (getClassB (I.getType ())) {
     case cByte: 
       if (I.getType ()->isSigned ()) { // add byte
         BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff);
@@ -908,7 +976,7 @@ void V8ISel::visitBinaryOperator (Instruction &I) {
       }
       break;
     case cInt:
-      // Nothing todo here.
+      // Nothing to do here.
       break;
     case cLong:
       // Only support and, or, xor.
@@ -931,9 +999,15 @@ void V8ISel::visitSetCondInst(SetCondInst &I) {
   unsigned DestReg = getReg (I);
   const Type *Ty = I.getOperand (0)->getType ();
   
-  assert (getClass (Ty) < cLong && "can't setcc on longs or fp yet");
   // Compare the two values.
-  BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
+  assert (getClass (Ty) != cLong && "can't setcc on longs yet");
+  if (getClass (Ty) < cLong) {
+    BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
+  } else if (getClass (Ty) == cFloat) {
+    BuildMI(BB, V8::FCMPS, 2).addReg(Op0Reg).addReg(Op1Reg);
+  } else if (getClass (Ty) == cDouble) {
+    BuildMI(BB, V8::FCMPD, 2).addReg(Op0Reg).addReg(Op1Reg);
+  }
 
   unsigned BranchIdx;
   switch (I.getOpcode()) {
@@ -945,17 +1019,20 @@ void V8ISel::visitSetCondInst(SetCondInst &I) {
   case Instruction::SetLE: BranchIdx = 4; break;
   case Instruction::SetGE: BranchIdx = 5; break;
   }
-  static unsigned OpcodeTab[12] = {
-                              // LLVM       SparcV8
-                              //        unsigned signed
-    V8::BE,   V8::BE,         // seteq = be      be
-    V8::BNE,  V8::BNE,        // setne = bne     bne
-    V8::BCS,  V8::BL,         // setlt = bcs     bl
-    V8::BGU,  V8::BG,         // setgt = bgu     bg
-    V8::BLEU, V8::BLE,        // setle = bleu    ble
-    V8::BCC,  V8::BGE         // setge = bcc     bge
+  unsigned Column = 0;
+  if (Ty->isSigned()) ++Column;
+  if (Ty->isFloatingPoint()) ++Column;
+  static unsigned OpcodeTab[3*6] = {
+                                 // LLVM            SparcV8
+                                 //        unsigned signed  fp
+    V8::BE,   V8::BE,  V8::FBE,  // seteq = be      be      fbe
+    V8::BNE,  V8::BNE, V8::FBNE, // setne = bne     bne     fbne
+    V8::BCS,  V8::BL,  V8::FBL,  // setlt = bcs     bl      fbl
+    V8::BGU,  V8::BG,  V8::FBG,  // setgt = bgu     bg      fbg
+    V8::BLEU, V8::BLE, V8::FBLE, // setle = bleu    ble     fble
+    V8::BCC,  V8::BGE, V8::FBGE  // setge = bcc     bge     fbge
   };
-  unsigned Opcode = OpcodeTab[2*BranchIdx + (Ty->isSigned() ? 1 : 0)];
+  unsigned Opcode = OpcodeTab[3*BranchIdx + Column];
 
   MachineBasicBlock *thisMBB = BB;
   const BasicBlock *LLVM_BB = BB->getBasicBlock ();