Initial Mips support, here we go! =)
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Wed, 6 Jun 2007 07:42:06 +0000 (07:42 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Wed, 6 Jun 2007 07:42:06 +0000 (07:42 +0000)
- Modifications from the last patch included
  (issues pointed by Evan Cheng are now fixed).
- Added more MipsI instructions.
- Added more patterns to match branch instructions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37461 91177308-0d34-0410-b5e6-96231b3b80d8

21 files changed:
lib/Target/Mips/Makefile [new file with mode: 0644]
lib/Target/Mips/Mips.h [new file with mode: 0644]
lib/Target/Mips/Mips.td [new file with mode: 0644]
lib/Target/Mips/MipsAsmPrinter.cpp [new file with mode: 0644]
lib/Target/Mips/MipsCallingConv.td [new file with mode: 0644]
lib/Target/Mips/MipsISelDAGToDAG.cpp [new file with mode: 0644]
lib/Target/Mips/MipsISelLowering.cpp [new file with mode: 0644]
lib/Target/Mips/MipsISelLowering.h [new file with mode: 0644]
lib/Target/Mips/MipsInstrFormats.td [new file with mode: 0644]
lib/Target/Mips/MipsInstrInfo.cpp [new file with mode: 0644]
lib/Target/Mips/MipsInstrInfo.h [new file with mode: 0644]
lib/Target/Mips/MipsInstrInfo.td [new file with mode: 0644]
lib/Target/Mips/MipsRegisterInfo.cpp [new file with mode: 0644]
lib/Target/Mips/MipsRegisterInfo.h [new file with mode: 0644]
lib/Target/Mips/MipsRegisterInfo.td [new file with mode: 0644]
lib/Target/Mips/MipsSubtarget.cpp [new file with mode: 0644]
lib/Target/Mips/MipsSubtarget.h [new file with mode: 0644]
lib/Target/Mips/MipsTargetAsmInfo.cpp [new file with mode: 0644]
lib/Target/Mips/MipsTargetAsmInfo.h [new file with mode: 0644]
lib/Target/Mips/MipsTargetMachine.cpp [new file with mode: 0644]
lib/Target/Mips/MipsTargetMachine.h [new file with mode: 0644]

diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile
new file mode 100644 (file)
index 0000000..6ebffc7
--- /dev/null
@@ -0,0 +1,21 @@
+##===- lib/Target/Mips/Makefile ----------------------------*- Makefile -*-===##
+# 
+#                     The LLVM Compiler Infrastructure
+#
+# This file was developed by Bruno Cardoso Lopes and is distributed under the 
+# University of Illinois Open Source License. See LICENSE.TXT for details.
+# 
+##===----------------------------------------------------------------------===##
+LEVEL = ../../..
+LIBRARYNAME = LLVMMips
+TARGET = Mips
+
+# Make sure that tblgen is run, first thing.
+BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \
+                                                               MipsGenRegisterInfo.inc MipsGenInstrNames.inc \
+                                                               MipsGenInstrInfo.inc MipsGenAsmWriter.inc \
+                                                               MipsGenDAGISel.inc MipsGenCallingConv.inc \
+                                                               MipsGenSubtarget.inc
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h
new file mode 100644 (file)
index 0000000..48b08ea
--- /dev/null
@@ -0,0 +1,38 @@
+//===-- Mips.h - Top-level interface for Mips representation ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the entry points for global functions defined in 
+// the LLVM Mips back-end.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TARGET_MIPS_H
+#define TARGET_MIPS_H
+
+#include <iosfwd>
+
+namespace llvm {
+  class MipsTargetMachine;
+  class FunctionPassManager;
+  class FunctionPass;
+  class MachineCodeEmitter;
+
+  FunctionPass *createMipsCodePrinterPass(std::ostream &OS, 
+                                          MipsTargetMachine &TM);
+  FunctionPass *createMipsISelDag(MipsTargetMachine &TM);
+} // end namespace llvm;
+
+// Defines symbolic names for Mips registers.  This defines a mapping from
+// register name to register number.
+#include "MipsGenRegisterNames.inc"
+
+// Defines symbolic names for the Mips instructions.
+#include "MipsGenInstrNames.inc"
+
+#endif
diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td
new file mode 100644 (file)
index 0000000..662bc3b
--- /dev/null
@@ -0,0 +1,63 @@
+//===- Mips.td - Describe the Mips Target Machine ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Target-independent interfaces which we are implementing
+//===----------------------------------------------------------------------===//
+
+include "../Target.td"
+
+//===----------------------------------------------------------------------===//
+// Register File Description
+//===----------------------------------------------------------------------===//
+
+include "MipsRegisterInfo.td"
+
+//===----------------------------------------------------------------------===//
+// Subtarget features
+//===----------------------------------------------------------------------===//
+
+// TODO: dummy, needed to compile
+def FeatureCIX : SubtargetFeature<"r3000", "isR3000", "true",
+                                  "Enable r3000 extentions">;
+
+//===----------------------------------------------------------------------===//
+// Instruction Description
+//===----------------------------------------------------------------------===//
+
+include "MipsInstrInfo.td"
+
+def MipsInstrInfo : InstrInfo {
+  // Define how we want to layout our target-specific information field.
+  let TSFlagsFields = [];
+  let TSFlagsShifts = [];
+}
+//===----------------------------------------------------------------------===//
+// Calling Conventions
+//===----------------------------------------------------------------------===//
+
+include "MipsCallingConv.td"
+
+//===----------------------------------------------------------------------===//
+// Mips processors supported.
+//===----------------------------------------------------------------------===//
+
+class Proc<string Name, list<SubtargetFeature> Features>
+ : Processor<Name, NoItineraries, Features>;
+
+def : Proc<"generic", []>;
+
+//===----------------------------------------------------------------------===//
+// Declare the target which we are implementing
+//===----------------------------------------------------------------------===//
+
+def Mips : Target {
+  // Pull in Instruction Info:
+  let InstructionSet = MipsInstrInfo;
+}
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
new file mode 100644 (file)
index 0000000..fdf60d9
--- /dev/null
@@ -0,0 +1,294 @@
+//===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to GAS-format MIPS assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mips-asm-printer"
+
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "MipsTargetMachine.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/Mangler.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MathExtras.h"
+#include <cctype>
+
+using namespace llvm;
+
+STATISTIC(EmittedInsts, "Number of machine instrs printed");
+
+namespace {
+  struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter {
+    MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM, 
+                   const TargetAsmInfo *T): 
+                   AsmPrinter(O, TM, T) {}
+
+    virtual const char *getPassName() const {
+      return "Mips Assembly Printer";
+    }
+
+    void printOperand(const MachineInstr *MI, int opNum);
+    void printMemOperand(const MachineInstr *MI, int opNum, 
+                         const char *Modifier = 0);
+
+    bool printInstruction(const MachineInstr *MI);  // autogenerated.
+    bool runOnMachineFunction(MachineFunction &F);
+    bool doInitialization(Module &M);
+    bool doFinalization(Module &M);
+  };
+} // end of anonymous namespace
+
+#include "MipsGenAsmWriter.inc"
+
+/// createMipsCodePrinterPass - Returns a pass that prints the MIPS
+/// assembly code for a MachineFunction to the given output stream,
+/// using the given target machine description.  This should work
+/// regardless of whether the function is in SSA form.
+FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o,
+                                              MipsTargetMachine &tm) 
+{
+  return new MipsAsmPrinter(o, tm, tm.getTargetAsmInfo());
+}
+
+/// runOnMachineFunction - This uses the printMachineInstruction()
+/// method to print assembly for each instruction.
+bool MipsAsmPrinter::
+runOnMachineFunction(MachineFunction &MF) 
+{
+  SetupMachineFunction(MF);
+
+  // Print out constants referenced by the function
+  EmitConstantPool(MF.getConstantPool());
+
+  O << "\n\n";
+
+  // What's my mangled name?
+  CurrentFnName = Mang->getValueName(MF.getFunction());
+
+  // Print out the label for the function.
+  const Function *F = MF.getFunction();
+  SwitchToTextSection(getSectionForFunction(*F).c_str(), F);
+
+  // On Mips GAS if .align #n is present, #n means the number of bits 
+  // to be cleared to align. So, if we want 4 byte alignment, we must 
+  // have .align 2
+  // TODO:
+  //  add gas ".mask" and ".fmask"
+  EmitAlignment(1, F);
+  O << "\t.globl\t" << CurrentFnName << "\n";
+  O << "\t.ent\t" << CurrentFnName << "\n";
+  O << "\t.type\t"  << CurrentFnName << ", @function\n";
+  O << CurrentFnName << ":\n";
+
+  // Print out code for the function.
+  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
+       I != E; ++I) {
+
+    // Print a label for the basic block.
+    if (I != MF.begin()) {
+      printBasicBlockLabel(I, true);
+      O << '\n';
+    }
+
+    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
+         II != E; ++II) {
+      // Print the assembly for the instruction.
+      O << "\t";
+      printInstruction(II);
+      ++EmittedInsts;
+    }
+  }
+
+  // close function with asm directive
+  O << "\t.end\t" << CurrentFnName << "\n";
+
+  // We didn't modify anything.
+  return false;
+}
+
+void MipsAsmPrinter::
+printOperand(const MachineInstr *MI, int opNum) 
+{
+  const MachineOperand &MO = MI->getOperand(opNum);
+  const MRegisterInfo  &RI = *TM.getRegisterInfo();
+  bool  closeP=false;
+
+  // %hi and %lo used on mips gas to break large constants
+  if (MI->getOpcode() == Mips::LUi && !MO.isRegister() 
+      && !MO.isImmediate()) {
+    O << "%hi(";
+    closeP = true;
+  } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister() 
+             && !MO.isImmediate()) {
+    O << "%lo(";
+    closeP = true;
+  }
+  switch (MO.getType()) 
+  {
+    case MachineOperand::MO_Register:
+      if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
+        O << "$" << LowercaseString (RI.get(MO.getReg()).Name);
+      else
+        O << "$" << MO.getReg();
+      break;
+
+    case MachineOperand::MO_Immediate:
+      if ((MI->getOpcode() == Mips::SLTiu) || (MI->getOpcode() == Mips::ORi) || 
+          (MI->getOpcode() == Mips::LUi) || (MI->getOpcode() == Mips::ANDi))
+        O << (unsigned int)MO.getImmedValue();
+      else
+        O << (int)MO.getImmedValue();
+      break;
+
+    case MachineOperand::MO_MachineBasicBlock:
+      printBasicBlockLabel(MO.getMachineBasicBlock());
+      return;
+
+    case MachineOperand::MO_GlobalAddress:
+      O << Mang->getValueName(MO.getGlobal());
+      break;
+
+    case MachineOperand::MO_ExternalSymbol:
+      O << MO.getSymbolName();
+      break;
+
+    case MachineOperand::MO_ConstantPoolIndex:
+      O << TAI->getPrivateGlobalPrefix() << "CPI"
+        << getFunctionNumber() << "_" << MO.getConstantPoolIndex();
+      break;
+  
+    default:
+      O << "<unknown operand type>"; abort (); break;
+  }
+
+  if (closeP) O << ")";
+}
+
+void MipsAsmPrinter::
+printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) 
+{
+  // lw/sw $reg, MemOperand
+  // will turn into :
+  // lw/sw $reg, imm($reg)
+  printOperand(MI, opNum);
+  O << "(";
+  printOperand(MI, opNum+1);
+  O << ")";
+}
+
+bool MipsAsmPrinter::
+doInitialization(Module &M) 
+{
+  Mang = new Mangler(M);
+  return false; // success
+}
+
+bool MipsAsmPrinter::
+doFinalization(Module &M) 
+{
+  const TargetData *TD = TM.getTargetData();
+
+  // Print out module-level global variables here.
+  for (Module::const_global_iterator I = M.global_begin(),
+         E = M.global_end(); I != E; ++I)
+
+    // External global require no code
+    if (I->hasInitializer()) {
+
+      // Check to see if this is a special global 
+      // used by LLVM, if so, emit it.
+      if (EmitSpecialLLVMGlobal(I))
+        continue;
+      
+      O << "\n\n";
+      std::string name = Mang->getValueName(I);
+      Constant *C      = I->getInitializer();
+      unsigned Size    = TD->getTypeSize(C->getType());
+      unsigned Align   = TD->getPrefTypeAlignment(C->getType());
+
+      if (C->isNullValue() && (I->hasLinkOnceLinkage() || 
+        I->hasInternalLinkage() || I->hasWeakLinkage() 
+        /* FIXME: Verify correct */)) {
+
+        SwitchToDataSection(".data", I);
+        if (I->hasInternalLinkage())
+          O << "\t.local " << name << "\n";
+
+        O << "\t.comm " << name << "," 
+          << TD->getTypeSize(C->getType()) 
+          << "," << Align << "\n";
+
+      } else {
+
+        switch (I->getLinkage()) 
+        {
+          case GlobalValue::LinkOnceLinkage:
+          case GlobalValue::WeakLinkage:   
+            // FIXME: Verify correct for weak.
+            // Nonnull linkonce -> weak
+            O << "\t.weak " << name << "\n";
+            SwitchToDataSection("", I);
+            O << "\t.section\t\".llvm.linkonce.d." << name
+                          << "\",\"aw\",@progbits\n";
+            break;
+          case GlobalValue::AppendingLinkage:
+            // FIXME: appending linkage variables 
+            // should go into a section of  their name or 
+            // something.  For now, just emit them as external.
+          case GlobalValue::ExternalLinkage:
+            // If external or appending, declare as a global symbol
+            O << "\t.globl " << name << "\n";
+          case GlobalValue::InternalLinkage:
+            if (C->isNullValue())
+              SwitchToDataSection(".bss", I);
+            else
+              SwitchToDataSection(".data", I);
+            break;
+          case GlobalValue::GhostLinkage:
+            cerr << "Should not have any" 
+                 << "unmaterialized functions!\n";
+            abort();
+          case GlobalValue::DLLImportLinkage:
+            cerr << "DLLImport linkage is" 
+                 << "not supported by this target!\n";
+            abort();
+          case GlobalValue::DLLExportLinkage:
+            cerr << "DLLExport linkage is" 
+                 << "not supported by this target!\n";
+            abort();
+          default:
+            assert(0 && "Unknown linkage type!");          
+        }
+        O << "\t.align " << Align << "\n";
+        O << "\t.type " << name << ",@object\n";
+        O << "\t.size " << name << "," << Size << "\n";
+        O << name << ":\n";
+        EmitGlobalConstant(C);
+    }
+  }
+
+  AsmPrinter::doFinalization(M);
+  return false; // success
+}
diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td
new file mode 100644 (file)
index 0000000..23ef850
--- /dev/null
@@ -0,0 +1,39 @@
+//===- MipsCallingConv.td - Calling Conventions for Mips --------*- C++ -*-===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+// This describes the calling conventions for Mips architecture.
+//===----------------------------------------------------------------------===//
+
+/// CCIfSubtarget - Match if the current subtarget has a feature F.
+class CCIfSubtarget<string F, CCAction A>: 
+  CCIf<!strconcat("State.getTarget().getSubtarget<MipsSubtarget>().", F), A>;
+
+//===----------------------------------------------------------------------===//
+// Mips Return Value Calling Convention
+//===----------------------------------------------------------------------===//
+def RetCC_Mips : CallingConv<[
+  // i32 are returned in registers V0, V1
+  CCIfType<[i32], CCAssignToReg<[V0, V1]>>
+]>;
+
+
+//===----------------------------------------------------------------------===//
+// Mips Argument Calling Conventions
+//===----------------------------------------------------------------------===//
+def CC_Mips : CallingConv<[
+  // Promote i8/i16 arguments to i32.
+  CCIfType<[i8, i16], CCPromoteToType<i32>>,
+
+  // The first 4 integer arguments are passed in integer registers.
+  CCIfType<[i32], CCAssignToReg<[A0, A1, A2, A3]>>,
+
+  // Integer values get stored in stack slots that are 4 bytes in
+  // size and 4-byte aligned.
+  CCIfType<[i32], CCAssignToStack<4, 4>>
+]>;
+
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
new file mode 100644 (file)
index 0000000..e660f9c
--- /dev/null
@@ -0,0 +1,272 @@
+//===-- MipsISelDAGToDAG.cpp - A dag to dag inst selector for Mips --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an instruction selector for the MIPS target.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mips-isel"
+
+#include "Mips.h"
+#include "MipsISelLowering.h"
+#include "MipsRegisterInfo.h"
+#include "MipsSubtarget.h"
+#include "MipsTargetMachine.h"
+#include "llvm/GlobalValue.h"
+#include "llvm/Instructions.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Type.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include <queue>
+#include <set>
+
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Instruction Selector Implementation
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// MipsDAGToDAGISel - MIPS specific code to select MIPS machine
+// instructions for SelectionDAG operations.
+//===----------------------------------------------------------------------===//
+namespace {
+
+class VISIBILITY_HIDDEN MipsDAGToDAGISel : public SelectionDAGISel {
+
+  /// TM - Keep a reference to MipsTargetMachine.
+  MipsTargetMachine &TM;
+
+  /// MipsLowering - This object fully describes how to lower LLVM code to an
+  /// Mips-specific SelectionDAG.
+  MipsTargetLowering MipsLowering;
+
+  /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
+  /// make the right decision when generating code for different targets.
+  //TODO: add initialization on constructor
+  //const MipsSubtarget *Subtarget;
+public:
+  MipsDAGToDAGISel(MipsTargetMachine &tm) : 
+        SelectionDAGISel(MipsLowering),
+        TM(tm), MipsLowering(*TM.getTargetLowering()) {}
+  
+  virtual void InstructionSelectBasicBlock(SelectionDAG &SD);
+
+  // Pass Name
+  virtual const char *getPassName() const {
+    return "MIPS DAG->DAG Pattern Instruction Selection";
+  } 
+  
+
+private:  
+  // Include the pieces autogenerated from the target description.
+  #include "MipsGenDAGISel.inc"
+
+  SDNode *Select(SDOperand N);
+
+  // Complex Pattern.
+  bool SelectAddr(SDOperand Op, SDOperand N, 
+                  SDOperand &Base, SDOperand &Offset);
+
+
+  // getI32Imm - Return a target constant with the specified
+  // value, of type i32.
+  inline SDOperand getI32Imm(unsigned Imm) {
+    return CurDAG->getTargetConstant(Imm, MVT::i32);
+  }
+
+
+  #ifndef NDEBUG
+  unsigned Indent;
+  #endif
+};
+
+}
+
+/// InstructionSelectBasicBlock - This callback is invoked by
+/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
+void MipsDAGToDAGISel::
+InstructionSelectBasicBlock(SelectionDAG &SD) 
+{
+  DEBUG(BB->dump());
+  // Codegen the basic block.
+  #ifndef NDEBUG
+  DOUT << "===== Instruction selection begins:\n";
+  Indent = 0;
+  #endif
+
+  // Select target instructions for the DAG.
+  SD.setRoot(SelectRoot(SD.getRoot()));
+
+  #ifndef NDEBUG
+  DOUT << "===== Instruction selection ends:\n";
+  #endif
+
+  SD.RemoveDeadNodes();
+  
+  // Emit machine code to BB. 
+  ScheduleAndEmitDAG(SD);
+}
+
+/// ComplexPattern used on MipsInstrInfo
+/// Used on Mips Load/Store instructions
+bool MipsDAGToDAGISel::
+SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base)
+{
+  // if Address is FI, get the TargetFrameIndex.
+  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
+    Base   = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
+    Offset = CurDAG->getTargetConstant(0, MVT::i32);
+    return true;
+  }
+    
+  // TargetExternalSymbol and TargetGlobalAddress are
+  // lowered and their addresses go into registers, so
+  // they should not be touched here.
+  if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
+       Addr.getOpcode() == ISD::TargetGlobalAddress))
+    return false;
+  
+  // Operand is an result from an ADD.
+  if (Addr.getOpcode() == ISD::ADD) 
+  {
+    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 
+    {
+      if (Predicate_immSExt16(CN)) 
+      {
+        // If the first operand is a FI, get the TargetFI Node
+        if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
+                                    (Addr.getOperand(0))) {
+          Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
+        } else {
+          Base = Addr.getOperand(0);
+        }
+
+        Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32);
+        return true;
+      }
+    }
+  }
+
+  Base = Addr;
+  Offset = CurDAG->getTargetConstant(0, MVT::i32);
+  return true;
+}
+
+/// Select instructions not customized! Used for
+/// expanded, promoted and normal instructions
+SDNode* MipsDAGToDAGISel::
+Select(SDOperand N) 
+{
+  SDNode *Node = N.Val;
+  unsigned Opcode = Node->getOpcode();
+
+  // Dump information about the Node being selected
+  #ifndef NDEBUG
+  DOUT << std::string(Indent, ' ') << "Selecting: ";
+  DEBUG(Node->dump(CurDAG));
+  DOUT << "\n";
+  Indent += 2;
+  #endif
+
+  // If we have a custom node, we already have selected!
+  if (Opcode >= ISD::BUILTIN_OP_END && Opcode < MipsISD::FIRST_NUMBER) {
+    #ifndef NDEBUG
+    DOUT << std::string(Indent-2, ' ') << "== ";
+    DEBUG(Node->dump(CurDAG));
+    DOUT << "\n";
+    Indent -= 2;
+    #endif
+    return NULL;
+  }
+
+  ///
+  // Instruction Selection not handled by custom or by the 
+  // auto-generated tablegen selection should be handled here
+  /// 
+  switch(Opcode) {
+
+    default: break;
+
+    /// Special Mul operations
+    case ISD::MULHS:
+    case ISD::MULHU: {
+      SDOperand MulOp1 = Node->getOperand(0);
+      SDOperand MulOp2 = Node->getOperand(1);
+      AddToISelQueue(MulOp1);
+      AddToISelQueue(MulOp2);
+
+      unsigned MulOp  = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
+      SDNode *MulNode = CurDAG->getTargetNode(MulOp, MVT::Flag, MulOp1, MulOp2);
+
+      SDOperand MFInFlag = SDOperand(MulNode, 0);
+      return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
+    }
+
+    /// Div operations
+    case ISD::SDIV: 
+    case ISD::UDIV: {
+      SDOperand DivOp1 = Node->getOperand(0);
+      SDOperand DivOp2 = Node->getOperand(1);
+      AddToISelQueue(DivOp1);
+      AddToISelQueue(DivOp2);
+
+      unsigned DivOp  = (Opcode == ISD::SDIV ? Mips::DIV : Mips::DIVu);
+      SDNode *DivNode = CurDAG->getTargetNode(DivOp, MVT::Flag, DivOp1, DivOp2);
+
+      SDOperand MFInFlag = SDOperand(DivNode, 0);
+      return CurDAG->getTargetNode(Mips::MFLO, MVT::i32, MFInFlag);
+    }
+
+    /// Rem operations
+    case ISD::SREM: 
+    case ISD::UREM: {
+      SDOperand RemOp1 = Node->getOperand(0);
+      SDOperand RemOp2 = Node->getOperand(1);
+      AddToISelQueue(RemOp1);
+      AddToISelQueue(RemOp2);
+      
+      unsigned RemOp  = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu);
+      SDNode *RemNode = CurDAG->getTargetNode(RemOp, MVT::Flag, RemOp1, RemOp2);
+
+      SDOperand MFInFlag = SDOperand(RemNode, 0);
+      return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
+    }
+  }
+
+  // Select the default instruction
+  SDNode *ResNode = SelectCode(N);
+
+  #ifndef NDEBUG
+  DOUT << std::string(Indent-2, ' ') << "=> ";
+  if (ResNode == NULL || ResNode == N.Val)
+    DEBUG(N.Val->dump(CurDAG));
+  else
+    DEBUG(ResNode->dump(CurDAG));
+  DOUT << "\n";
+  Indent -= 2;
+  #endif
+
+  return ResNode;
+}
+
+/// createMipsISelDag - This pass converts a legalized DAG into a 
+/// MIPS-specific DAG, ready for instruction scheduling.
+FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) {
+  return new MipsDAGToDAGISel(TM);
+}
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
new file mode 100644 (file)
index 0000000..98da575
--- /dev/null
@@ -0,0 +1,519 @@
+//===-- MipsISelLowering.cpp - Mips DAG Lowering Implementation -----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that Mips uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mips-lower"
+
+#include "MipsISelLowering.h"
+#include "MipsTargetMachine.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/CallingConv.h"
+#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/Support/Debug.h"
+#include <queue>
+#include <set>
+
+using namespace llvm;
+
+const char *MipsTargetLowering::
+getTargetNodeName(unsigned Opcode) const 
+{
+  switch (Opcode) 
+  {
+    case MipsISD::JmpLink   : return "MipsISD::JmpLink";
+    case MipsISD::Hi        : return "MipsISD::Hi";
+    case MipsISD::Lo        : return "MipsISD::Lo";
+    case MipsISD::Ret       : return "MipsISD::Ret";
+    default                 : return NULL;
+  }
+}
+
+MipsTargetLowering::
+MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM) 
+{
+  // Mips does not have i1 type, so use i32 for
+  // setcc operations results (slt, sgt, ...). 
+  setSetCCResultType(MVT::i32);
+  setSetCCResultContents(ZeroOrOneSetCCResult);
+
+  // Set up the register classes
+  addRegisterClass(MVT::i32, Mips::CPURegsRegisterClass);
+
+  // Custom
+  setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
+  setOperationAction(ISD::RET, MVT::Other, Custom);
+
+  // Load extented operations for i1 types must be promoted 
+  setLoadXAction(ISD::EXTLOAD,  MVT::i1,  Promote);
+  setLoadXAction(ISD::ZEXTLOAD, MVT::i1,  Promote);
+  setLoadXAction(ISD::SEXTLOAD, MVT::i1,  Promote);
+
+  // Store operations for i1 types must be promoted
+  setStoreXAction(MVT::i1, Promote);
+
+  // Mips does not have these NodeTypes below.
+  setOperationAction(ISD::BR_JT,     MVT::Other, Expand);
+  setOperationAction(ISD::BR_CC,     MVT::Other, Expand);
+  setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
+  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
+  setOperationAction(ISD::SELECT, MVT::i32, Expand);
+
+  // Mips not supported intrinsics.
+  setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
+  setOperationAction(ISD::MEMSET, MVT::Other, Expand);
+  setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
+
+  setOperationAction(ISD::CTPOP, MVT::i32, Expand);
+  setOperationAction(ISD::CTTZ , MVT::i32, Expand);
+  setOperationAction(ISD::CTLZ , MVT::i32, Expand);
+  setOperationAction(ISD::ROTL , MVT::i32, Expand);
+  setOperationAction(ISD::ROTR , MVT::i32, Expand);
+  setOperationAction(ISD::BSWAP, MVT::i32, Expand);
+
+  setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
+  setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
+  setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
+
+  // We don't have line number support yet.
+  setOperationAction(ISD::LOCATION, MVT::Other, Expand);
+  setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
+  setOperationAction(ISD::LABEL, MVT::Other, Expand);
+
+  // Use the default for now
+  setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
+  setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
+
+  setStackPointerRegisterToSaveRestore(Mips::SP);
+  computeRegisterProperties();
+}
+
+
+SDOperand MipsTargetLowering::
+LowerOperation(SDOperand Op, SelectionDAG &DAG) 
+{
+  switch (Op.getOpcode()) 
+  {
+    case ISD::CALL:             return LowerCALL(Op, DAG);
+    case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
+    case ISD::RET:              return LowerRET(Op, DAG);
+    case ISD::GlobalAddress:    return LowerGlobalAddress(Op, DAG);
+    case ISD::RETURNADDR:       return LowerRETURNADDR(Op, DAG);
+  }
+  return SDOperand();
+}
+
+//===----------------------------------------------------------------------===//
+//  Lower helper functions
+//===----------------------------------------------------------------------===//
+
+// AddLiveIn - This helper function adds the specified physical register to the
+// MachineFunction as a live in value.  It also creates a corresponding
+// virtual register for it.
+static unsigned
+AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC) 
+{
+  assert(RC->contains(PReg) && "Not the correct regclass!");
+  unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC);
+  MF.addLiveIn(PReg, VReg);
+  return VReg;
+}
+
+// Set up a frame object for the return address.
+SDOperand MipsTargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) {
+  if (ReturnAddrIndex == 0) {
+    MachineFunction &MF = DAG.getMachineFunction();
+    ReturnAddrIndex = MF.getFrameInfo()->CreateFixedObject(4, 0);
+  }
+
+  return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy());
+}
+
+
+//===----------------------------------------------------------------------===//
+//  Misc Lower Operation implementation
+//===----------------------------------------------------------------------===//
+SDOperand MipsTargetLowering::
+LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) 
+{
+  GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
+
+  SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
+  SDOperand Hi = DAG.getNode(MipsISD::Hi, MVT::i32, GA);
+  SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
+
+  return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi);
+}
+
+SDOperand MipsTargetLowering::
+LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG) {
+  // Depths > 0 not supported yet!
+  if (cast<ConstantSDNode>(Op.getOperand(0))->getValue() > 0)
+    return SDOperand();
+  
+  // Just load the return address
+  SDOperand RetAddrFI = getReturnAddressFrameIndex(DAG);
+  return DAG.getLoad(getPointerTy(), DAG.getEntryNode(), RetAddrFI, NULL, 0);
+}
+
+//===----------------------------------------------------------------------===//
+//                      Calling Convention Implementation
+//
+//  The lower operations present on calling convention works on this order:
+//      LowerCALL (virt regs --> phys regs, virt regs --> stack) 
+//      LowerFORMAL_ARGUMENTS (phys --> virt regs, stack --> virt regs)
+//      LowerRET (virt regs --> phys regs)
+//      LowerCALL (phys regs --> virt regs)
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsGenCallingConv.inc"
+
+//===----------------------------------------------------------------------===//
+//                  CALL Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+/// Mips custom CALL implementation
+SDOperand MipsTargetLowering::
+LowerCALL(SDOperand Op, SelectionDAG &DAG)
+{
+  unsigned CallingConv= cast<ConstantSDNode>(Op.getOperand(1))->getValue();
+
+  // By now, only CallingConv::C implemented
+  switch (CallingConv) 
+  {
+    default:
+      assert(0 && "Unsupported calling convention");
+    case CallingConv::Fast:
+    case CallingConv::C:
+      return LowerCCCCallTo(Op, DAG, CallingConv);
+  }
+}
+
+/// LowerCCCCallTo - functions arguments are copied from virtual
+/// regs to (physical regs)/(stack frame), CALLSEQ_START and
+/// CALLSEQ_END are emitted.
+/// TODO: isVarArg, isTailCall, sret, GOT, linkage types.
+SDOperand MipsTargetLowering::
+LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) 
+{
+  SDOperand Chain  = Op.getOperand(0);
+  SDOperand Callee = Op.getOperand(4);
+
+  // Analyze operands of the call, assigning locations to each operand.
+  SmallVector<CCValAssign, 16> ArgLocs;
+  CCState CCInfo(CC, getTargetMachine(), ArgLocs);
+  CCInfo.AnalyzeCallOperands(Op.Val, CC_Mips);
+  
+  // Get a count of how many bytes are to be pushed on the stack.
+  unsigned NumBytes = CCInfo.getNextStackOffset();
+
+  Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, 
+                                 getPointerTy()));
+
+  SmallVector<std::pair<unsigned, SDOperand>, 8> RegsToPass;
+  SmallVector<SDOperand, 8> MemOpChains;
+
+  SDOperand StackPtr;
+
+  // Walk the register/memloc assignments, inserting copies/loads.
+  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+    CCValAssign &VA = ArgLocs[i];
+
+    // Arguments start after the 5 first operands of ISD::CALL
+    SDOperand Arg = Op.getOperand(5+2*VA.getValNo());
+    
+    // Promote the value if needed.
+    switch (VA.getLocInfo()) {
+      default: assert(0 && "Unknown loc info!");
+      case CCValAssign::Full: break;
+      case CCValAssign::SExt:
+        Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg);
+        break;
+      case CCValAssign::ZExt:
+        Arg = DAG.getNode(ISD::ZERO_EXTEND, VA.getLocVT(), Arg);
+        break;
+      case CCValAssign::AExt:
+        Arg = DAG.getNode(ISD::ANY_EXTEND, VA.getLocVT(), Arg);
+        break;
+    }
+    
+    // Arguments that can be passed on register, 
+    // must be kept at RegsToPass vector
+    if (VA.isRegLoc()) {
+      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
+    } else {
+      assert(VA.isMemLoc());
+      // Mips::SP holds our stack pointer
+      if (StackPtr.Val == 0)
+        StackPtr = DAG.getRegister(Mips::SP, getPointerTy());
+     
+      SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), 
+                                         getPointerTy());
+      
+      // emit a ISD::ADD which emits the final 
+      // stack location to place the parameter
+      PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff);
+
+      // emit ISD::STORE whichs stores the 
+      // parameter value to a stack Location
+      MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
+    }
+  }
+
+  // Transform all store nodes into one single node because
+  // all store nodes ar independent of each other.
+  if (!MemOpChains.empty())     
+    Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, 
+                        &MemOpChains[0], MemOpChains.size());
+
+  // Build a sequence of copy-to-reg nodes chained together with token 
+  // chain and flag operands which copy the outgoing args into registers.
+  // The InFlag in necessary since all emited instructions must be
+  // stuck together.
+  SDOperand InFlag;
+  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
+    Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, 
+                             RegsToPass[i].second, InFlag);
+    InFlag = Chain.getValue(1);
+  }
+
+  // If the callee is a GlobalAddress node (quite common, every direct 
+  // call is) turn it into a TargetGlobalAddress node so that legalize 
+  // doesn't hack it.
+  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
+  } else 
+  if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
+    Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
+
+  // MipsJmpLink = #chain, #target_address, #opt_in_flags...
+  //             = Chain, Callee, Reg#1, Reg#2, ...  
+  //
+  // Returns a chain & a flag for retval copy to use.
+  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
+  SmallVector<SDOperand, 8> Ops;
+  Ops.push_back(Chain);
+  Ops.push_back(Callee);
+
+  // Add argument registers to the end of the list so that they are 
+  // known live into the call.
+  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
+    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
+                                  RegsToPass[i].second.getValueType()));
+
+  if (InFlag.Val)
+    Ops.push_back(InFlag);
+
+  Chain  = DAG.getNode(MipsISD::JmpLink, NodeTys, &Ops[0], Ops.size());
+  InFlag = Chain.getValue(1);
+
+  // Create the CALLSEQ_END node.
+  NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
+  Ops.clear();
+  Ops.push_back(Chain);
+  Ops.push_back(DAG.getConstant(NumBytes, getPointerTy()));
+  Ops.push_back(InFlag);
+  Chain  = DAG.getNode(ISD::CALLSEQ_END, NodeTys, &Ops[0], Ops.size());
+  InFlag = Chain.getValue(1);
+
+  // Handle result values, copying them out of physregs into vregs that we
+  // return.
+  return SDOperand(LowerCallResult(Chain, InFlag, Op.Val, CC, DAG), Op.ResNo);
+}
+
+/// LowerCallResult - Lower the result values of an ISD::CALL into the
+/// appropriate copies out of appropriate physical registers.  This assumes that
+/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
+/// being lowered. Returns a SDNode with the same number of values as the 
+/// ISD::CALL.
+SDNode *MipsTargetLowering::
+LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall, 
+        unsigned CallingConv, SelectionDAG &DAG) {
+  
+  // Assign locations to each value returned by this call.
+  SmallVector<CCValAssign, 16> RVLocs;
+  CCState CCInfo(CallingConv, getTargetMachine(), RVLocs);
+  CCInfo.AnalyzeCallResult(TheCall, RetCC_Mips);
+  SmallVector<SDOperand, 8> ResultVals;
+
+  // returns void
+  if (!RVLocs.size())
+    return Chain.Val;
+
+  // Copy all of the result registers out of their specified physreg.
+  for (unsigned i = 0; i != RVLocs.size(); ++i) {
+    Chain = DAG.getCopyFromReg(Chain, RVLocs[i].getLocReg(),
+                                 RVLocs[i].getValVT(), InFlag).getValue(1);
+    InFlag = Chain.getValue(2);
+    ResultVals.push_back(Chain.getValue(0));
+  }
+  
+  // Merge everything together with a MERGE_VALUES node.
+  ResultVals.push_back(Chain);
+  return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(),
+                       &ResultVals[0], ResultVals.size()).Val;
+}
+
+//===----------------------------------------------------------------------===//
+//             FORMAL_ARGUMENTS Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+/// Mips custom FORMAL_ARGUMENTS implementation
+SDOperand MipsTargetLowering::
+LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) 
+{
+  unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getValue();
+  switch(CC) 
+  {
+    default:
+      assert(0 && "Unsupported calling convention");
+    case CallingConv::C:
+      return LowerCCCArguments(Op, DAG);
+  }
+}
+
+/// LowerCCCArguments - transform physical registers into
+/// virtual registers and generate load operations for
+/// arguments places on the stack.
+/// TODO: isVarArg, sret
+SDOperand MipsTargetLowering::
+LowerCCCArguments(SDOperand Op, SelectionDAG &DAG) 
+{
+  MachineFunction &MF   = DAG.getMachineFunction();
+  MachineFrameInfo *MFI = MF.getFrameInfo();
+  SDOperand Root        = Op.getOperand(0);
+
+  // Assign locations to all of the incoming arguments.
+  SmallVector<CCValAssign, 16> ArgLocs;
+  CCState CCInfo(MF.getFunction()->getCallingConv(), 
+                 getTargetMachine(), ArgLocs);
+  CCInfo.AnalyzeFormalArguments(Op.Val, CC_Mips);
+  SmallVector<SDOperand, 8> ArgValues;
+
+  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+
+    CCValAssign &VA = ArgLocs[i];
+
+    // Arguments stored on registers
+    if (VA.isRegLoc()) {
+      MVT::ValueType RegVT = VA.getLocVT();
+      TargetRegisterClass *RC;
+            
+      if (RegVT == MVT::i32)
+        RC = Mips::CPURegsRegisterClass;
+      else
+        assert(0 && "support only Mips::CPURegsRegisterClass");
+      
+      unsigned Reg = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC);
+
+      // Transform the arguments stored on 
+      // physical registers into virtual ones
+      SDOperand ArgValue = DAG.getCopyFromReg(Root, Reg, RegVT);
+      
+      // If this is an 8 or 16-bit value, it is really passed promoted 
+      // to 32 bits.  Insert an assert[sz]ext to capture this, then 
+      // truncate to the right size.
+      if (VA.getLocInfo() == CCValAssign::SExt)
+        ArgValue = DAG.getNode(ISD::AssertSext, RegVT, ArgValue,
+                               DAG.getValueType(VA.getValVT()));
+      else if (VA.getLocInfo() == CCValAssign::ZExt)
+        ArgValue = DAG.getNode(ISD::AssertZext, RegVT, ArgValue,
+                               DAG.getValueType(VA.getValVT()));
+      
+      if (VA.getLocInfo() != CCValAssign::Full)
+        ArgValue = DAG.getNode(ISD::TRUNCATE, VA.getValVT(), ArgValue);
+
+      ArgValues.push_back(ArgValue);
+
+    } else {
+      // sanity check
+      assert(VA.isMemLoc());
+      
+      // Create the frame index object for this incoming parameter...
+      int FI = MFI->CreateFixedObject(MVT::getSizeInBits(VA.getValVT())/8,
+                                      VA.getLocMemOffset());
+
+      // Create load nodes to retrieve arguments from the stack
+      SDOperand FIN = DAG.getFrameIndex(FI, getPointerTy());
+      ArgValues.push_back(DAG.getLoad(VA.getValVT(), Root, FIN, NULL, 0));
+    }
+  }
+  ArgValues.push_back(Root);
+
+  ReturnAddrIndex = 0;
+
+  // Return the new list of results.
+  return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(),
+                     &ArgValues[0], ArgValues.size()).getValue(Op.ResNo);
+}
+
+//===----------------------------------------------------------------------===//
+//               Return Value Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+SDOperand MipsTargetLowering::
+LowerRET(SDOperand Op, SelectionDAG &DAG)
+{
+  // CCValAssign - represent the assignment of
+  // the return value to a location
+  SmallVector<CCValAssign, 16> RVLocs;
+  unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
+
+  // CCState - Info about the registers and stack slot.
+  CCState CCInfo(CC, getTargetMachine(), RVLocs);
+
+  // Analize return values of ISD::RET
+  CCInfo.AnalyzeReturn(Op.Val, RetCC_Mips);
+
+  // If this is the first return lowered for this function, add 
+  // the regs to the liveout set for the function.
+  if (DAG.getMachineFunction().liveout_empty()) {
+    for (unsigned i = 0; i != RVLocs.size(); ++i)
+      DAG.getMachineFunction().addLiveOut(RVLocs[i].getLocReg());
+  }
+
+  // The chain is always operand #0
+  SDOperand Chain = Op.getOperand(0);
+  SDOperand Flag;
+
+  // Copy the result values into the output registers.
+  for (unsigned i = 0; i != RVLocs.size(); ++i) {
+    CCValAssign &VA = RVLocs[i];
+    assert(VA.isRegLoc() && "Can only return in registers!");
+
+    // ISD::RET => ret chain, (regnum1,val1), ...
+    // So i*2+1 index only the regnums
+    Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), 
+                                 Op.getOperand(i*2+1), Flag);
+
+    // guarantee that all emitted copies are
+    // stuck together, avoiding something bad
+    Flag = Chain.getValue(1);
+  }
+
+  // Return on Mips is always a "jr $ra"
+  if (Flag.Val)
+    return DAG.getNode(MipsISD::Ret, MVT::Other, 
+                           Chain, DAG.getRegister(Mips::RA, MVT::i32), Flag);
+  else // Return Void
+    return DAG.getNode(MipsISD::Ret, MVT::Other, 
+                           Chain, DAG.getRegister(Mips::RA, MVT::i32));
+}
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
new file mode 100644 (file)
index 0000000..3300f40
--- /dev/null
@@ -0,0 +1,83 @@
+//===-- MipsISelLowering.h - Mips DAG Lowering Interface --------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that Mips uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MipsISELLOWERING_H
+#define MipsISELLOWERING_H
+
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/Target/TargetLowering.h"
+#include "Mips.h"
+#include "MipsSubtarget.h"
+
+namespace llvm {
+  namespace MipsISD {
+    enum NodeType {
+      // Start the numbering from where ISD NodeType finishes.
+      FIRST_NUMBER = ISD::BUILTIN_OP_END+Mips::INSTRUCTION_LIST_END,
+
+      // Jump and link (call)
+      JmpLink,
+
+      // Get the Higher 16 bits from a 32-bit immediate
+      // No relation with Mips Hi register
+      Hi, 
+
+      // Get the Lower 16 bits from a 32-bit immediate
+      // No relation with Mips Lo register
+      Lo, 
+
+      // Return 
+      Ret
+    };
+  }
+
+  //===--------------------------------------------------------------------===//
+  // TargetLowering Implementation
+  //===--------------------------------------------------------------------===//
+  class MipsTargetLowering : public TargetLowering 
+  {
+    // FrameIndex for return slot.
+    int ReturnAddrIndex;
+
+    // const MipsSubtarget &MipsSubTarget;
+  public:
+
+    MipsTargetLowering(MipsTargetMachine &TM);
+
+    /// LowerOperation - Provide custom lowering hooks for some operations.
+    virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
+
+    /// getTargetNodeName - This method returns the name of a target specific 
+    //  DAG node.
+    virtual const char *getTargetNodeName(unsigned Opcode) const;
+
+  private:
+    // Lower Operand helpers
+    SDOperand LowerCCCArguments(SDOperand Op, SelectionDAG &DAG);
+    SDOperand LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC);
+    SDNode *LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode*TheCall,
+                            unsigned CallingConv, SelectionDAG &DAG);
+    SDOperand getReturnAddressFrameIndex(SelectionDAG &DAG);
+
+    // Lower Operand specifics
+    SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG);
+    SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG);
+    SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
+    SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
+    SDOperand LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG);
+
+  };
+}
+
+#endif // MipsISELLOWERING_H
diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td
new file mode 100644 (file)
index 0000000..b88fa90
--- /dev/null
@@ -0,0 +1,96 @@
+//===- MipsRegisterInfo.td - Mips Register defs -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//  Describe MIPS instructions format
+//
+//  All the possible Mips fields are:
+//
+//  opcode  - operation code.
+//  rs      - src reg.
+//  rt      - dst reg (on a 2 regs instr) or src reg (on a 3 reg instr).
+//  rd      - dst reg, only used on 3 regs instr.
+//  shamt   - only used on shift instructions, contains the shift amount.
+//  funct   - combined with opcode field give us an operation code.
+//
+//===----------------------------------------------------------------------===//
+
+// Generic Mips Format
+class MipsInst<dag ops, string asmstr, list<dag> pattern>: 
+      Instruction 
+{
+  field bits<32> Inst;
+
+  let Namespace = "Mips";
+
+  bits<6> opcode;
+
+  // Top 5 bits are the 'opcode' field
+  let Inst{31-26} = opcode;   
+  
+  dag OperandList = ops;
+  let AsmString   = asmstr;
+  let Pattern     = pattern;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Format R instruction class in Mips : <|opcode|rs|rt|rd|shamt|funct|>
+//===----------------------------------------------------------------------===//
+
+class FR<bits<6> op, bits<6> _funct, dag ops, string asmstr, list<dag> pattern>:
+      MipsInst<ops, asmstr, pattern> 
+{
+  bits<5>  rd;
+  bits<5>  rs;
+  bits<5>  rt;
+  bits<5>  shamt;
+  bits<6>  funct;
+
+  let opcode = op;
+  let funct  = _funct;
+
+  let Inst{25-21} = rs;
+  let Inst{20-16} = rt; 
+  let Inst{15-11} = rd;
+  let Inst{10-6}  = shamt;
+  let Inst{5-0}   = funct;
+}
+
+//===----------------------------------------------------------------------===//
+// Format I instruction class in Mips : <|opcode|rs|rt|immediate|>
+//===----------------------------------------------------------------------===//
+
+class FI<bits<6> op, dag ops, string asmstr, list<dag> pattern>: 
+      MipsInst<ops, asmstr, pattern> 
+{
+  bits<5>  rt;
+  bits<5>  rs;
+  bits<16> imm16;
+
+  let opcode = op;
+
+  let Inst{25-21} = rs;
+  let Inst{20-16} = rt; 
+  let Inst{15-0}  = imm16;
+}
+
+//===----------------------------------------------------------------------===//
+// Format J instruction class in Mips : <|opcode|address|>
+//===----------------------------------------------------------------------===//
+
+class FJ<bits<6> op, dag ops, string asmstr, list<dag> pattern>: 
+      MipsInst<ops, asmstr, pattern> 
+{
+  bits<26> addr;
+
+  let opcode = op;
+  
+  let Inst{25-0} = addr;
+}
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
new file mode 100644 (file)
index 0000000..8084030
--- /dev/null
@@ -0,0 +1,114 @@
+//===- MipsInstrInfo.cpp - Mips Instruction Information ---------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the Mips implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "MipsGenInstrInfo.inc"
+
+using namespace llvm;
+
+// TODO: Add the subtarget support on this constructor
+MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm)
+  : TargetInstrInfo(MipsInsts, sizeof(MipsInsts)/sizeof(MipsInsts[0])),
+    TM(tm), RI(*this) {}
+
+static bool isZeroImm(const MachineOperand &op) {
+  return op.isImmediate() && op.getImmedValue() == 0;
+}
+
+/// Return true if the instruction is a register to register move and
+/// leave the source and dest operands in the passed parameters.
+bool MipsInstrInfo::
+isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg) const 
+{
+  //  addu  $dst, $src, $zero || addu  $dst, $zero, $src
+  //  or    $dst, $src, $zero || or    $dst, $zero, $src
+  if ((MI.getOpcode() == Mips::ADDu) || (MI.getOpcode() == Mips::OR))
+  {
+    if (MI.getOperand(1).getReg() == Mips::ZERO) {
+      DstReg = MI.getOperand(0).getReg();
+      SrcReg = MI.getOperand(2).getReg();
+      return true;
+    } else if (MI.getOperand(2).getReg() == Mips::ZERO) {
+      DstReg = MI.getOperand(0).getReg();
+      SrcReg = MI.getOperand(1).getReg();
+      return true;
+    }
+  }
+
+  //  addiu $dst, $src, 0
+  if (MI.getOpcode() == Mips::ADDiu) 
+  {
+    if ((MI.getOperand(1).isRegister()) && (isZeroImm(MI.getOperand(2)))) {
+      DstReg = MI.getOperand(0).getReg();
+      SrcReg = MI.getOperand(1).getReg();
+      return true;
+    }
+  }
+  return false;
+}
+
+/// isLoadFromStackSlot - If the specified machine instruction is a direct
+/// load from a stack slot, return the virtual or physical register number of
+/// the destination along with the FrameIndex of the loaded stack slot.  If
+/// not, return 0.  This predicate must return 0 if the instruction has
+/// any side effects other than loading from the stack slot.
+unsigned MipsInstrInfo::
+isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const 
+{
+  // TODO: add lhu, lbu ???
+  if (MI->getOpcode() == Mips::LW) 
+  {
+    if ((MI->getOperand(2).isFrameIndex()) && // is a stack slot
+        (MI->getOperand(1).isImmediate()) &&  // the imm is zero
+        (isZeroImm(MI->getOperand(1)))) 
+    {
+      FrameIndex = MI->getOperand(2).getFrameIndex();
+      return MI->getOperand(0).getReg();
+    }
+  }
+
+  return 0;
+}
+
+/// isStoreToStackSlot - If the specified machine instruction is a direct
+/// store to a stack slot, return the virtual or physical register number of
+/// the source reg along with the FrameIndex of the loaded stack slot.  If
+/// not, return 0.  This predicate must return 0 if the instruction has
+/// any side effects other than storing to the stack slot.
+unsigned MipsInstrInfo::
+isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const 
+{
+  // TODO: add sb, sh ???
+  if (MI->getOpcode() == Mips::SW) {
+    if ((MI->getOperand(0).isFrameIndex()) && // is a stack slot
+        (MI->getOperand(1).isImmediate()) &&  // the imm is zero
+        (isZeroImm(MI->getOperand(1)))) 
+    {
+      FrameIndex = MI->getOperand(0).getFrameIndex();
+      return MI->getOperand(2).getReg();
+    }
+  }
+  return 0;
+}
+
+unsigned MipsInstrInfo::
+InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 
+             MachineBasicBlock *FBB, const std::vector<MachineOperand> &Cond)
+             const
+{
+  // TODO: add Mips::J here.
+  assert(0 && "Cant handle any kind of branches!");
+  return 1;
+}
diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h
new file mode 100644 (file)
index 0000000..356cf3d
--- /dev/null
@@ -0,0 +1,63 @@
+//===- MipsInstrInfo.h - Mips Instruction Information -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the Mips implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSINSTRUCTIONINFO_H
+#define MIPSINSTRUCTIONINFO_H
+
+#include "Mips.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "MipsRegisterInfo.h"
+
+namespace llvm {
+
+class MipsInstrInfo : public TargetInstrInfo 
+{
+  MipsTargetMachine &TM;
+  const MipsRegisterInfo RI;
+public:
+  MipsInstrInfo(MipsTargetMachine &TM);
+
+  /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info.  As
+  /// such, whenever a client has an instance of instruction info, it should
+  /// always be able to get register info as well (through this method).
+  ///
+  virtual const MRegisterInfo &getRegisterInfo() const { return RI; }
+
+  /// Return true if the instruction is a register to register move and
+  /// leave the source and dest operands in the passed parameters.
+  ///
+  virtual bool isMoveInstr(const MachineInstr &MI,
+                           unsigned &SrcReg, unsigned &DstReg) const;
+  
+  /// isLoadFromStackSlot - If the specified machine instruction is a direct
+  /// load from a stack slot, return the virtual or physical register number of
+  /// the destination along with the FrameIndex of the loaded stack slot.  If
+  /// not, return 0.  This predicate must return 0 if the instruction has
+  /// any side effects other than loading from the stack slot.
+  virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const;
+  
+  /// isStoreToStackSlot - If the specified machine instruction is a direct
+  /// store to a stack slot, return the virtual or physical register number of
+  /// the source reg along with the FrameIndex of the loaded stack slot.  If
+  /// not, return 0.  This predicate must return 0 if the instruction has
+  /// any side effects other than storing to the stack slot.
+  virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const;
+  
+  virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+                                MachineBasicBlock *FBB, 
+                                const std::vector<MachineOperand> &Cond) const;
+};
+
+}
+
+#endif
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
new file mode 100644 (file)
index 0000000..0a7e3ce
--- /dev/null
@@ -0,0 +1,468 @@
+//===- MipsInstrInfo.td - Mips Register defs --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction format superclass
+//===----------------------------------------------------------------------===//
+
+include "MipsInstrFormats.td"
+
+//===----------------------------------------------------------------------===//
+// Mips profiles and nodes
+//===----------------------------------------------------------------------===//
+
+// Call
+def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
+def MipsJmpLink     : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
+                             SDNPOutFlag]>;
+
+// Hi and Lo nodes are created to let easy manipulation of 16-bit when 
+// handling 32-bit immediates. They are used on MipsISelLowering to 
+// lower stuff like GlobalAddress, ExternalSymbol, ...
+// This two nodes have nothing to do with Mips Registers Hi and Lo.
+def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>;
+def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; 
+
+// Return 
+def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; 
+def MipsRet     : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, 
+                             SDNPOptInFlag]>;
+
+// These are target-independent nodes, but have target-specific formats.
+def SDT_MipsCallSeq : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
+def callseq_start   : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeq, 
+                             [SDNPHasChain, SDNPOutFlag]>;
+def callseq_end     : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeq, 
+                             [SDNPHasChain, SDNPOutFlag]>;
+
+// Instruction operand types
+def brtarget    : Operand<OtherVT>;
+def calltarget  : Operand<i32>;
+def uimm16      : Operand<i32>;
+def simm16      : Operand<i32>;
+def shamt       : Operand<i32>; 
+
+// Address operand
+def mem : Operand<i32> {
+  let PrintMethod = "printMemOperand";
+  let MIOperandInfo = (ops simm16, CPURegs);
+}
+
+//===----------------------------------------------------------------------===//
+// Mips Patterns and Transformations
+//===----------------------------------------------------------------------===//
+
+// Transformation Function - get the lower 16 bits.
+def LO16 : SDNodeXForm<imm, [{
+  return getI32Imm((unsigned)N->getValue() & 0xFFFF);
+}]>;
+
+// Transformation Function - get the higher 16 bits.
+def HI16 : SDNodeXForm<imm, [{
+  return getI32Imm((unsigned)N->getValue() >> 16);
+}]>;
+
+// Node immediate fits as 16-bit sign extended on target immediate.
+// e.g. addi, andi
+def immSExt16  : PatLeaf<(imm), [{
+  if (N->getValueType(0) == MVT::i32)
+    return (int32_t)N->getValue() == (short)N->getValue();
+  else
+    return (int64_t)N->getValue() == (short)N->getValue();
+}]>;
+
+// Node immediate fits as 16-bit zero extended on target immediate.
+// The LO16 param means that only the lower 16 bits of the node
+// immediate are caught.
+// e.g. addiu, sltiu
+def immZExt16  : PatLeaf<(imm), [{
+  return (uint64_t)N->getValue() == (unsigned short)N->getValue();
+}], LO16>;
+
+// Node immediate must have only it's 16 high bits set.
+// The HI16 param means that only the higher 16 bits of the node
+// immediate are caught.
+// e.g. lui
+def imm16ShiftedZExt : PatLeaf<(imm), [{
+  return (N->getValue() & ~uint64_t(0xFFFF0000)) == 0;
+}], HI16>;
+
+// shamt field must fit in 5 bits.
+def immZExt5 : PatLeaf<(imm), [{
+  return N->getValue() == ((N->getValue()) & 0x1f) ;
+}]>;
+
+// Mips Address Mode! SDNode frameindex could possibily be a match 
+// since load and store instructions from stack used it.
+def addr : ComplexPattern<i32, 2, "SelectAddr", [frameindex], []>;
+
+//===----------------------------------------------------------------------===//
+// Instructions specific format
+//===----------------------------------------------------------------------===//
+
+// Arithmetic 3 register operands
+let isCommutable = 1 in 
+class ArithR< bits<6> op, bits<6> func, string instr_asm, SDNode OpNode>: 
+  FR< op, 
+      func, 
+      (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), 
+      !strconcat(instr_asm, " $dst, $b, $c"), 
+      [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))] >;
+
+let isCommutable = 1 in 
+class ArithOverflowR< bits<6> op, bits<6> func, string instr_asm>: 
+  FR< op, 
+      func, 
+      (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), 
+      !strconcat(instr_asm, " $dst, $b, $c"), 
+      []>;
+
+// Arithmetic 2 register operands
+let isCommutable = 1 in
+class ArithI<bits<6> op, string instr_asm, SDNode OpNode, 
+             Operand Od, PatLeaf imm_type> : 
+  FI< op, 
+      (ops CPURegs:$dst, CPURegs:$b, Od:$c), 
+      !strconcat(instr_asm, " $dst, $b, $c"), 
+      [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))] >;
+
+// Arithmetic Multiply ADD/SUB
+let rd=0 in
+class MArithR<bits<6> func, string instr_asm> : 
+  FR< 0x1c, 
+      func,
+      (ops CPURegs:$rs, CPURegs:$rt), 
+      !strconcat(instr_asm, " $rs, $rt"), 
+      []>;
+
+//  Logical
+class LogicR<bits<6> func, string instr_asm, SDNode OpNode>:
+  FR< 0x00, 
+      func, 
+      (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), 
+      !strconcat(instr_asm, " $dst, $b, $c"), 
+      [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))] >;
+
+class LogicI<bits<6> op, string instr_asm, SDNode OpNode>:
+  FI< op,
+      (ops CPURegs:$dst, CPURegs:$b, uimm16:$c),
+      !strconcat(instr_asm, " $dst, $b, $c"),
+      [(set CPURegs:$dst, (OpNode CPURegs:$b, immSExt16:$c))]>;
+
+class LogicNOR<bits<6> op, bits<6> func, string instr_asm>:
+  FR< op, 
+      func, 
+      (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), 
+      !strconcat(instr_asm, " $dst, $b, $c"), 
+      [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))] >;
+
+// Shifts
+let rt = 0 in
+class LogicR_shift_imm<bits<6> func, string instr_asm, SDNode OpNode>:
+  FR< 0x00, 
+      func, 
+      (ops CPURegs:$dst, CPURegs:$b, shamt:$c),
+      !strconcat(instr_asm, " $dst, $b, $c"), 
+      [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))] >;
+
+class LogicR_shift_reg<bits<6> func, string instr_asm, SDNode OpNode>:
+  FR< 0x00, 
+      func, 
+      (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c),
+      !strconcat(instr_asm, " $dst, $b, $c"), 
+      [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))] >;
+
+// Load Upper Imediate
+class LoadUpper<bits<6> op, string instr_asm>:
+  FI< op,
+      (ops CPURegs:$dst, uimm16:$imm),
+      !strconcat(instr_asm, " $dst, $imm"),
+      [(set CPURegs:$dst, imm16ShiftedZExt:$imm)]>;
+
+// Memory Load/Store 
+let isLoad = 1 in
+class LoadM<bits<6> op, string instr_asm, PatFrag OpNode>:
+  FI< op,
+      (ops CPURegs:$dst, mem:$addr),
+      !strconcat(instr_asm, " $dst, $addr"),
+      [(set CPURegs:$dst, (OpNode addr:$addr))]>;
+
+let isStore = 1 in
+class StoreM<bits<6> op, string instr_asm, PatFrag OpNode>:
+  FI< op,
+      (ops CPURegs:$dst, mem:$addr),
+      !strconcat(instr_asm, " $dst, $addr"),
+      [(OpNode CPURegs:$dst, addr:$addr)]>;
+
+// Conditional Branch
+let isBranch = 1, noResults=1, isTerminator=1 in
+class CBranch<bits<6> op, string instr_asm, PatFrag cond_op>:
+  FI< op,
+      (ops CPURegs:$a, CPURegs:$b, brtarget:$offset),
+      !strconcat(instr_asm, " $a, $b, $offset"),
+      [(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)]>;
+
+class SetCC_R<bits<6> op, bits<6> func, string instr_asm,
+      PatFrag cond_op>:
+  FR< op,
+      func,
+      (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c),
+      !strconcat(instr_asm, " $dst, $b, $c"),
+      [(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))]>;
+
+class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op,
+      Operand Od, PatLeaf imm_type>:
+  FI< op,
+      (ops CPURegs:$dst, CPURegs:$b, Od:$c),
+      !strconcat(instr_asm, " $dst, $b, $c"),
+      [(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))]>;
+
+// Unconditional branch
+let hasCtrlDep=1, noResults=1, isTerminator=1 in
+class JumpFJ<bits<6> op, string instr_asm>:
+  FJ< op,
+      (ops brtarget:$target),
+      !strconcat(instr_asm, " $target"),
+      [(br bb:$target)]>;
+
+let hasCtrlDep=1, noResults=1, isTerminator=1, rd=0 in
+class JumpFR<bits<6> op, bits<6> func, string instr_asm>:
+  FR< op,
+      func,
+      (ops CPURegs:$target),
+      !strconcat(instr_asm, " $target"),
+      []>;
+
+// Jump and Link (Call)
+let isCall=1 in
+class JumpLink<bits<6> op, string instr_asm>: 
+  FJ< op,
+      (ops calltarget:$target),
+      !strconcat(instr_asm, " $target"),
+      [(MipsJmpLink imm:$target)]>;
+
+let isCall=1 in
+class JumpLinkReg<bits<6> op, bits<6> func, string instr_asm>:
+  FR< op,
+      func,
+      (ops CPURegs:$rd, CPURegs:$rs),
+      !strconcat(instr_asm, " $rs, $rd"),
+      []>;
+
+// Mul, Div 
+class MulDiv<bits<6> func, string instr_asm>: 
+  FR< 0x00, 
+      func, 
+      (ops CPURegs:$a, CPURegs:$b), 
+      !strconcat(instr_asm, " $a, $b"), 
+      []>;
+
+// Move from Hi/Lo 
+class MoveFromTo<bits<6> func, string instr_asm>:
+  FR< 0x00, 
+      func, 
+      (ops CPURegs:$dst), 
+      !strconcat(instr_asm, " $dst"), 
+      []>;
+
+// Count Leading Ones/Zeros in Word
+class CountLeading<bits<6> func, string instr_asm>:
+  FR< 0x1c, 
+      func, 
+      (ops CPURegs:$dst, CPURegs:$src), 
+      !strconcat(instr_asm, " $dst, $src"), 
+      []>;
+
+
+//===----------------------------------------------------------------------===//
+// Pseudo instructions
+//===----------------------------------------------------------------------===//
+
+class Pseudo<dag ops, string asmstr, list<dag> pattern>: 
+      MipsInst<ops, asmstr, pattern>;
+
+// As stack alignment is always done with addiu, we need a 16-bit immediate
+def ADJCALLSTACKDOWN : Pseudo<(ops uimm16:$amt),
+                              "!ADJCALLSTACKDOWN $amt",
+                              [(callseq_start imm:$amt)]>, Imp<[SP],[SP]>;
+def ADJCALLSTACKUP   : Pseudo<(ops uimm16:$amt),
+                              "!ADJCALLSTACKUP $amt",
+                              [(callseq_end imm:$amt)]>, Imp<[SP],[SP]>;
+
+def IMPLICIT_DEF_CPURegs : Pseudo<(ops CPURegs:$dst),
+                                  "!IMPLICIT_DEF $dst",
+                                  [(set CPURegs:$dst, (undef))]>;
+
+//===----------------------------------------------------------------------===//
+// Instruction definition
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Mips32 I
+//===----------------------------------------------------------------------===//
+
+// Arithmetic
+def ADDi    : ArithI<0x08, "addi",  add, simm16, immZExt16>;
+def ADDiu   : ArithI<0x09, "addiu", add, uimm16, immSExt16>;
+def MUL     : ArithR<0x1c, 0x02, "mul", mul>;
+def ADDu    : ArithR<0x00, 0x21, "addu", add>;
+def SUBu    : ArithR<0x00, 0x23, "subu", sub>;
+def ADD     : ArithOverflowR<0x00, 0x20, "add">;
+def SUB     : ArithOverflowR<0x00, 0x22, "sub">;
+def MADD    : MArithR<0x00, "madd">;
+def MADDU   : MArithR<0x01, "maddu">;
+def MSUB    : MArithR<0x04, "msub">;
+def MSUBU   : MArithR<0x05, "msubu">;
+
+// Logical
+def AND     : LogicR<0x24, "and", and>;
+def OR      : LogicR<0x25, "or",  or>;
+def XOR     : LogicR<0x26, "xor", xor>;
+def ANDi    : LogicI<0x0c, "andi", and>;
+def ORi     : LogicI<0x0d, "ori",  or>;
+def XORi    : LogicI<0x0e, "xori",  xor>;
+def NOR     : LogicNOR<0x00, 0x27, "nor">;
+
+// Shifts 
+def SLL     : LogicR_shift_imm<0x00, "sll", shl>;
+def SRL     : LogicR_shift_imm<0x02, "srl", srl>;
+def SRA     : LogicR_shift_imm<0x03, "sra", sra>;
+def SLLV    : LogicR_shift_reg<0x04, "sllv", shl>;
+def SRLV    : LogicR_shift_reg<0x06, "srlv", srl>;
+def SRAV    : LogicR_shift_reg<0x07, "srav", sra>;
+
+// Load Upper Immediate
+def LUi     : LoadUpper<0x0f, "lui">;
+
+// Load/Store
+def LB      : LoadM<0x20, "lb",  sextloadi8>;
+def LBu     : LoadM<0x24, "lbu", zextloadi8>;
+def LH      : LoadM<0x21, "lh",  sextloadi16>;
+def LHu     : LoadM<0x25, "lhu", zextloadi16>;
+def LW      : LoadM<0x23, "lw",  load>;
+def SB      : StoreM<0x28, "sb", truncstorei8>;
+def SH      : StoreM<0x29, "sh", truncstorei16>;
+def SW      : StoreM<0x2b, "sw", store>;
+
+// Conditional Branch
+def BEQ     : CBranch<0x04, "beq", seteq>;
+def BNE     : CBranch<0x05, "bne", setne>;
+def SLT     : SetCC_R<0x00, 0x2a, "slt", setlt>;
+def SLTu    : SetCC_R<0x00, 0x2b, "sltu", setult>;
+def SLTi    : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16>;
+def SLTiu   : SetCC_I<0x0b, "sltiu", setult, uimm16, immZExt16>;
+
+// Unconditional jump
+def J       : JumpFJ<0x02, "j">;
+def JR      : JumpFR<0x00, 0x08, "jr">;
+
+// Jump and Link (Call)
+def JAL     : JumpLink<0x03, "jal">;
+def JALR    : JumpLinkReg<0x00, 0x09, "jalr">;
+
+// MulDiv and Move From Hi/Lo operations, have
+// their correpondent SDNodes created on ISelDAG.
+// Special Mul, Div operations
+def MULT    : MulDiv<0x18, "mult">;
+def MULTu   : MulDiv<0x19, "multu">;
+def DIV     : MulDiv<0x1a, "div">;
+def DIVu    : MulDiv<0x1b, "divu">;
+
+// Move From Hi/Lo 
+def MFHI    : MoveFromTo<0x10, "mfhi">;
+def MFLO    : MoveFromTo<0x12, "mflo">;
+def MTHI    : MoveFromTo<0x11, "mthi">;
+def MTLO    : MoveFromTo<0x13, "mtlo">;
+
+// Count Leading
+def CLO     : CountLeading<0x21, "clo">;
+def CLZ     : CountLeading<0x20, "clz">;
+
+// No operation
+let addr=0 in
+def NOOP :  FJ<0, (ops), "nop", []>;
+
+// Ret instruction - as mips does not have "ret" a 
+// jr $ra must be generated.
+let isReturn=1, isTerminator=1, hasDelaySlot=1, noResults=1,
+    isBarrier=1, hasCtrlDep=1, rs=0, rt=0, shamt=0 in 
+{
+  def RET : FR <0x00, 0x02, (ops CPURegs:$target),
+                "jr $target", [(MipsRet CPURegs:$target)]>;
+}
+
+//===----------------------------------------------------------------------===//
+//  Arbitrary patterns that map to one or more instructions
+//===----------------------------------------------------------------------===//
+
+// Small immediates
+def : Pat<(i32 immSExt16:$in), 
+          (ORi ZERO, imm:$in)>;
+
+// Arbitrary immediates
+def : Pat<(i32 imm:$imm),
+          (ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>;
+
+// Call
+def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)),
+          (JAL tglobaladdr:$dst)>;
+def : Pat<(MipsJmpLink (i32 texternalsym:$dst)),
+          (JAL texternalsym:$dst)>;
+
+// GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable
+def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
+def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
+
+// When extracting the address from GlobalAddress we
+// need something of the form "addiu $reg, %lo(addr)"
+def : Pat<(add CPURegs:$a, (MipsLo tglobaladdr:$in)),
+          (ADDiu CPURegs:$a, tglobaladdr:$in)>;
+
+// Mips does not have not, so we increase the operation  
+def : Pat<(not CPURegs:$in),
+          (NOR CPURegs:$in, CPURegs:$in)>;
+
+// extended load and stores 
+def : Pat<(i32 (extloadi8  addr:$src)), (LBu addr:$src)>;
+def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
+def : Pat<(truncstorei1 CPURegs:$src, addr:$addr), 
+           (SB CPURegs:$src, addr:$src)>;
+
+// Conditional branch patterns.
+// cond branches patterns, 2 register operands signed.
+def : Pat<(brcond (setlt CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
+          (BNE (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setle CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
+          (BEQ (SLT CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setgt CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
+          (BNE (SLT CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setge CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
+          (BEQ (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
+
+// cond branches patterns, 2 register operands unsigned.
+def : Pat<(brcond (setult CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
+          (BNE (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setule CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
+          (BEQ (SLTu CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setugt CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
+          (BNE (SLTu CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setuge CPURegs:$lhs, CPURegs:$rhs), bb:$dst),
+          (BEQ (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>;
+
+// cond branches patterns, reg/imm operands signed.
+def : Pat<(brcond (setult CPURegs:$lhs, immSExt16:$rhs), bb:$dst),
+          (BNE (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setuge CPURegs:$lhs, immSExt16:$rhs), bb:$dst),
+          (BEQ (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>;
+
+// cond branches patterns, reg/imm operands unsigned.
+def : Pat<(brcond (setult CPURegs:$lhs, immZExt16:$rhs), bb:$dst),
+          (BNE (SLTiu CPURegs:$lhs, immZExt16:$rhs), ZERO, bb:$dst)>;
+def : Pat<(brcond (setuge CPURegs:$lhs, immZExt16:$rhs), bb:$dst),
+          (BEQ (SLTiu CPURegs:$lhs, immZExt16:$rhs), ZERO, bb:$dst)>;
diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp
new file mode 100644 (file)
index 0000000..a23a426
--- /dev/null
@@ -0,0 +1,288 @@
+//===- MipsRegisterInfo.cpp - MIPS Register Information -== -----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the MIPS implementation of the MRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mips-reg-info"
+
+#include "Mips.h"
+#include "MipsRegisterInfo.h"
+#include "llvm/Constants.h"
+#include "llvm/Type.h"
+#include "llvm/Function.h"
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineLocation.h"
+#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/STLExtras.h"
+//#include "MipsSubtarget.h"
+
+using namespace llvm;
+
+// TODO: add subtarget support
+MipsRegisterInfo::MipsRegisterInfo(const TargetInstrInfo &tii)
+  : MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP),
+  TII(tii) {}
+
+void MipsRegisterInfo::
+storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+          unsigned SrcReg, int FI, 
+          const TargetRegisterClass *RC) const 
+{
+  if (RC == Mips::CPURegsRegisterClass)
+    BuildMI(MBB, I, TII.get(Mips::SW)).addFrameIndex(FI)
+          .addImm(0).addReg(SrcReg, false, false, true);
+  else
+    assert(0 && "Can't store this register to stack slot");
+}
+
+void MipsRegisterInfo::
+loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+                     unsigned DestReg, int FI,
+                     const TargetRegisterClass *RC) const 
+{
+  if (RC == Mips::CPURegsRegisterClass)
+    BuildMI(MBB, I, TII.get(Mips::LW), DestReg).addImm(0).addFrameIndex(FI);
+  else
+    assert(0 && "Can't load this register from stack slot");
+}
+
+void MipsRegisterInfo::
+copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+             unsigned DestReg, unsigned SrcReg,
+             const TargetRegisterClass *RC) const 
+{
+  if (RC == Mips::CPURegsRegisterClass)
+    BuildMI(MBB, I, TII.get(Mips::ADDu), DestReg).addReg(Mips::ZERO)
+      .addReg(SrcReg);
+  else
+    assert (0 && "Can't copy this register");
+}
+
+void MipsRegisterInfo::reMaterialize(MachineBasicBlock &MBB, 
+                                      MachineBasicBlock::iterator I,
+                                      unsigned DestReg, 
+                                      const MachineInstr *Orig) const 
+{
+    MachineInstr *MI = Orig->clone();
+    MI->getOperand(0).setReg(DestReg);
+    MBB.insert(I, MI);
+}
+
+MachineInstr *MipsRegisterInfo::
+foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const 
+{
+  MachineInstr *NewMI = NULL;
+
+  switch (MI->getOpcode()) 
+  {
+    case Mips::ADDu:
+      if ((MI->getOperand(0).isRegister()) &&
+        (MI->getOperand(1).isRegister()) && 
+        (MI->getOperand(1).getReg() == Mips::ZERO) &&
+        (MI->getOperand(2).isRegister())) 
+      {
+        if (OpNum == 0)    // COPY -> STORE
+          NewMI = BuildMI(TII.get(Mips::SW)).addFrameIndex(FI)
+                  .addImm(0).addReg(MI->getOperand(2).getReg());
+        else               // COPY -> LOAD
+          NewMI = BuildMI(TII.get(Mips::LW), MI->getOperand(0)
+                  .getReg()).addImm(0).addFrameIndex(FI);
+      }
+      break;
+  }
+
+  if (NewMI)
+    NewMI->copyKillDeadInfo(MI);
+  return NewMI;
+}
+
+/// Mips Callee Saved Registers
+const unsigned* MipsRegisterInfo::
+getCalleeSavedRegs() const 
+{
+  // Mips calle-save register range is $16-$26(s0-s7)
+  static const unsigned CalleeSavedRegs[] = {  
+    Mips::S0, Mips::S1, Mips::S2, Mips::S3, 
+    Mips::S4, Mips::S5, Mips::S6, Mips::S7, 0
+  };
+  return CalleeSavedRegs;
+}
+
+/// Mips Callee Saved Register Classes
+const TargetRegisterClass* const* 
+MipsRegisterInfo::getCalleeSavedRegClasses() const 
+{
+  static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
+    &Mips::CPURegsRegClass, &Mips::CPURegsRegClass,
+    &Mips::CPURegsRegClass, &Mips::CPURegsRegClass,
+    &Mips::CPURegsRegClass, &Mips::CPURegsRegClass,
+    &Mips::CPURegsRegClass, &Mips::CPURegsRegClass, 0 
+  };
+  return CalleeSavedRegClasses;
+}
+
+BitVector MipsRegisterInfo::
+getReservedRegs(const MachineFunction &MF) const
+{
+  BitVector Reserved(getNumRegs());
+  Reserved.set(Mips::ZERO);
+  Reserved.set(Mips::AT);
+  Reserved.set(Mips::K0);
+  Reserved.set(Mips::K1);
+  Reserved.set(Mips::GP);
+  Reserved.set(Mips::SP);
+  Reserved.set(Mips::FP);
+  Reserved.set(Mips::RA);
+  return Reserved;
+}
+
+//===----------------------------------------------------------------------===//
+// Stack Frame Processing methods
+//===----------------------------------------------------------------------===//
+
+// True if target has frame pointer
+bool MipsRegisterInfo::
+hasFP(const MachineFunction &MF) const {
+  return false;
+}
+
+// This function eliminate ADJCALLSTACKDOWN, 
+// ADJCALLSTACKUP pseudo instructions
+void MipsRegisterInfo::
+eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator I) const {
+  // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
+  MBB.erase(I);
+}
+
+// FrameIndex represent objects inside a abstract stack.
+// We must replace FrameIndex with an stack/frame pointer
+// direct reference.
+void MipsRegisterInfo::
+eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, 
+                    RegScavenger *RS) const 
+{
+  unsigned i = 0;
+  MachineInstr &MI    = *II;
+  MachineFunction &MF = *MI.getParent()->getParent();
+
+  while (!MI.getOperand(i).isFrameIndex()) {
+    ++i;
+    assert(i < MI.getNumOperands() && 
+           "Instr doesn't have FrameIndex operand!");
+  }
+
+  // FrameInfo addressable stack objects are accessed 
+  // using neg. offsets, so we must add with the stack
+  // size to obtain $sp relative address.
+  int FrameIndex = MI.getOperand(i).getFrameIndex();
+  int stackSize  = MF.getFrameInfo()->getStackSize();
+  int spOffset   = MF.getFrameInfo()->getObjectOffset(FrameIndex);
+
+  #ifndef NDEBUG
+  DOUT << "\n<--------->\n";
+  MI.print(DOUT);
+  DOUT << "FrameIndex : " << FrameIndex << "\n";
+  DOUT << "spOffset   : " << spOffset << "\n";
+  DOUT << "stackSize  : " << stackSize << "\n";
+  #endif
+
+  // If the FrameIndex points to a positive SPOffset this
+  // means we are inside the callee and getting the arguments 
+  // from the caller stack
+  int Offset = (-(stackSize)) + spOffset; 
+
+  #ifndef NDEBUG
+  DOUT << "Offset     : " << Offset << "\n";
+  DOUT << "<--------->\n";
+  #endif
+
+  MI.getOperand(i-1).ChangeToImmediate(Offset);
+  MI.getOperand(i).ChangeToRegister(Mips::SP,false);
+}
+
+void MipsRegisterInfo::
+emitPrologue(MachineFunction &MF) const 
+{
+  MachineBasicBlock &MBB = MF.front();
+  MachineFrameInfo *MFI  = MF.getFrameInfo();
+
+  // Get the number of bytes to allocate from the FrameInfo
+  int NumBytes = (int) MFI->getStackSize();
+
+  // Do we need to allocate space on the stack?
+  if (NumBytes == 0) return;
+
+  // FIXME: is Stack Align needed here ?? (maybe it's done before...)
+  unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
+  NumBytes = -((NumBytes+Align-1)/Align*Align);
+
+  // Update frame info to pretend that this is part of the stack...
+  MFI->setStackSize(NumBytes);
+
+  // adjust stack : addi sp, sp, (-imm)
+  BuildMI(MBB, MBB.begin(), TII.get(Mips::ADDi), Mips::SP)
+      .addReg(Mips::SP).addImm(NumBytes);
+}
+
+void MipsRegisterInfo::
+emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const 
+{
+  MachineBasicBlock::iterator MBBI = prior(MBB.end());
+  MachineFrameInfo *MFI = MF.getFrameInfo();
+
+  // Get the number of bytes from FrameInfo
+  int NumBytes = (int) MFI->getStackSize();
+
+  // adjust stack  : insert addi sp, sp, (imm)
+  if (NumBytes) {
+    BuildMI(MBB, MBBI, TII.get(Mips::ADDi), Mips::SP)
+      .addReg(Mips::SP).addImm(-NumBytes);
+  }
+}
+
+void MipsRegisterInfo::
+processFunctionBeforeFrameFinalized(MachineFunction &MF) const {}
+
+unsigned MipsRegisterInfo::
+getRARegister() const {
+  return Mips::RA;
+}
+
+unsigned MipsRegisterInfo::
+getFrameRegister(MachineFunction &MF) const {
+  assert(0 && "What is the frame register");
+  return Mips::FP;
+}
+
+unsigned MipsRegisterInfo::
+getEHExceptionRegister() const {
+  assert(0 && "What is the exception register");
+  return 0;
+}
+
+unsigned MipsRegisterInfo::
+getEHHandlerRegister() const {
+  assert(0 && "What is the exception handler register");
+  return 0;
+}
+
+#include "MipsGenRegisterInfo.inc"
+
diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h
new file mode 100644 (file)
index 0000000..d84194f
--- /dev/null
@@ -0,0 +1,83 @@
+//===- MipsRegisterInfo.h - Mips Register Information Impl ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the Mips implementation of the MRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSREGISTERINFO_H
+#define MIPSREGISTERINFO_H
+
+#include "llvm/Target/MRegisterInfo.h"
+#include "MipsGenRegisterInfo.h.inc"
+
+namespace llvm {
+
+class TargetInstrInfo;
+class Type;
+
+struct MipsRegisterInfo : public MipsGenRegisterInfo {
+  const TargetInstrInfo &TII;
+  
+  MipsRegisterInfo(const TargetInstrInfo &tii);
+
+  /// Code Generation virtual methods...
+  void storeRegToStackSlot(MachineBasicBlock &MBB,
+                           MachineBasicBlock::iterator MBBI,
+                           unsigned SrcReg, int FrameIndex,
+                           const TargetRegisterClass *RC) const;
+
+  void loadRegFromStackSlot(MachineBasicBlock &MBB,
+              MachineBasicBlock::iterator MBBI,
+              unsigned DestReg, int FrameIndex,
+              const TargetRegisterClass *RC) const;
+
+  void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+                     unsigned DestReg, const MachineInstr *Orig) const;
+
+  MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
+                                  int FrameIndex) const;
+
+  void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+          unsigned DestReg, unsigned SrcReg,
+          const TargetRegisterClass *RC) const;
+  
+
+  const unsigned *getCalleeSavedRegs() const;
+
+  const TargetRegisterClass* const* getCalleeSavedRegClasses() const;
+
+  BitVector getReservedRegs(const MachineFunction &MF) const;
+
+  bool hasFP(const MachineFunction &MF) const;
+
+  void eliminateCallFramePseudoInstr(MachineFunction &MF,
+                                     MachineBasicBlock &MBB,
+                                     MachineBasicBlock::iterator I) const;
+
+  void eliminateFrameIndex(MachineBasicBlock::iterator II,
+                           int SPAdj, RegScavenger *RS = NULL) const;
+
+  void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
+
+  void emitPrologue(MachineFunction &MF) const;
+  void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
+  
+  // Debug information queries.
+  unsigned getRARegister() const;
+  unsigned getFrameRegister(MachineFunction &MF) const;
+
+  // Exception handling queries.
+  unsigned getEHExceptionRegister() const;
+  unsigned getEHHandlerRegister() const;
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td
new file mode 100644 (file)
index 0000000..2b7d15f
--- /dev/null
@@ -0,0 +1,80 @@
+//===- MipsRegisterInfo.td - Mips Register defs -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//  Declarations that describe the MIPS register file
+//===----------------------------------------------------------------------===//
+
+// We have banks of 32 registers each.
+class MipsReg<string n> : Register<n> {
+  field bits<5> Num;
+  let Namespace = "Mips";
+}
+
+// Mips CPU Registers
+class MipsGPRReg<bits<5> num, string n> : MipsReg<n> {
+  let Num = num;
+}
+
+// CPU GPR Registers
+def ZERO : MipsGPRReg< 0, "ZERO">, DwarfRegNum<0>;
+def AT : MipsGPRReg< 1, "AT">, DwarfRegNum<1>;
+def V0 : MipsGPRReg< 2, "2">, DwarfRegNum<2>;
+def V1 : MipsGPRReg< 3, "3">, DwarfRegNum<3>;
+def A0 : MipsGPRReg< 4, "4">, DwarfRegNum<5>;
+def A1 : MipsGPRReg< 5, "5">, DwarfRegNum<5>;
+def A2 : MipsGPRReg< 6, "6">, DwarfRegNum<6>;
+def A3 : MipsGPRReg< 7, "7">, DwarfRegNum<7>;
+def T0 : MipsGPRReg< 8, "8">, DwarfRegNum<8>;
+def T1 : MipsGPRReg< 9, "9">, DwarfRegNum<9>;
+def T2 : MipsGPRReg< 10, "10">, DwarfRegNum<10>;
+def T3 : MipsGPRReg< 11, "11">, DwarfRegNum<11>;
+def T4 : MipsGPRReg< 12, "12">, DwarfRegNum<12>;
+def T5 : MipsGPRReg< 13, "13">, DwarfRegNum<13>;
+def T6 : MipsGPRReg< 14, "14">, DwarfRegNum<14>;
+def T7 : MipsGPRReg< 15, "15">, DwarfRegNum<15>;
+def S0 : MipsGPRReg< 16, "16">, DwarfRegNum<16>;
+def S1 : MipsGPRReg< 17, "17">, DwarfRegNum<17>;
+def S2 : MipsGPRReg< 18, "18">, DwarfRegNum<18>;
+def S3 : MipsGPRReg< 19, "19">, DwarfRegNum<19>;
+def S4 : MipsGPRReg< 20, "20">, DwarfRegNum<20>;
+def S5 : MipsGPRReg< 21, "21">, DwarfRegNum<21>;
+def S6 : MipsGPRReg< 22, "22">, DwarfRegNum<22>;
+def S7 : MipsGPRReg< 23, "23">, DwarfRegNum<23>;
+def T8 : MipsGPRReg< 24, "24">, DwarfRegNum<24>;
+def T9 : MipsGPRReg< 25, "25">, DwarfRegNum<25>;
+def K0 : MipsGPRReg< 26, "26">, DwarfRegNum<26>;
+def K1 : MipsGPRReg< 27, "27">, DwarfRegNum<27>;
+def GP : MipsGPRReg< 28, "GP">, DwarfRegNum<28>;
+def SP : MipsGPRReg< 29, "SP">, DwarfRegNum<29>;
+def FP : MipsGPRReg< 30, "FP">, DwarfRegNum<30>;
+def RA : MipsGPRReg< 31, "RA">, DwarfRegNum<31>;
+
+// CPU Registers Class
+def CPURegs : RegisterClass<"Mips", [i32], 32, 
+  // Return Values and Arguments
+  [V0, V1, A0, A1, A2, A3,
+  // Not preserved across procedure calls
+  T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, 
+  // Callee save
+  S0, S1, S2, S3, S4, S5, S6, S7,
+  // Reserved
+  ZERO, AT, K0, K1, GP, SP, FP, RA]>
+{
+  let MethodProtos = [{
+    iterator allocation_order_end(const MachineFunction &MF) const;
+  }];
+  let MethodBodies = [{
+    CPURegsClass::iterator
+    CPURegsClass::allocation_order_end(const MachineFunction &MF) const {
+      // The last 8 registers on the list above are reserved
+      return end()-8;
+    }
+  }];
+}
diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp
new file mode 100644 (file)
index 0000000..a394f77
--- /dev/null
@@ -0,0 +1,26 @@
+//===- MipsSubtarget.cpp - Mips Subtarget Information -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Mips specific subclass of TargetSubtarget.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsSubtarget.h"
+#include "Mips.h"
+#include "MipsGenSubtarget.inc"
+using namespace llvm;
+
+MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M, 
+                             const std::string &FS) : isR3000(false) 
+{
+  std::string CPU = "generic";
+
+  // Parse features string.
+  ParseSubtargetFeatures(FS, CPU);
+}
diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h
new file mode 100644 (file)
index 0000000..7ec61ca
--- /dev/null
@@ -0,0 +1,43 @@
+//=====-- MipsSubtarget.h - Define Subtarget for the Mips -----*- C++ -*--====//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the Mips specific subclass of TargetSubtarget.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSSUBTARGET_H
+#define MIPSSUBTARGET_H
+
+#include "llvm/Target/TargetSubtarget.h"
+#include "llvm/Target/TargetMachine.h"
+
+#include <string>
+
+namespace llvm {
+class Module;
+
+class MipsSubtarget : public TargetSubtarget {
+protected:
+  bool isR3000;
+public:
+  /// This constructor initializes the data members to match that
+  /// of the specified module.
+  ///
+  MipsSubtarget(const TargetMachine &TM, const Module &M, 
+                const std::string &FS);
+  
+  /// ParseSubtargetFeatures - Parses features string setting specified 
+  /// subtarget options.  Definition of function is auto generated by tblgen.
+  void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU);
+
+  bool IsR3000() const { return isR3000; }
+};
+} // End llvm namespace
+
+#endif
diff --git a/lib/Target/Mips/MipsTargetAsmInfo.cpp b/lib/Target/Mips/MipsTargetAsmInfo.cpp
new file mode 100644 (file)
index 0000000..08166f6
--- /dev/null
@@ -0,0 +1,22 @@
+//===-- MipsTargetAsmInfo.cpp - Mips asm properties -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declarations of the MipsTargetAsmInfo properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsTargetAsmInfo.h"
+
+using namespace llvm;
+
+MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM) {
+  Data16bitsDirective = "\t.half\t";
+  Data32bitsDirective = "\t.word\t";
+  CommentString = "#";
+}
diff --git a/lib/Target/Mips/MipsTargetAsmInfo.h b/lib/Target/Mips/MipsTargetAsmInfo.h
new file mode 100644 (file)
index 0000000..908f036
--- /dev/null
@@ -0,0 +1,30 @@
+//=====-- MipsTargetAsmInfo.h - Mips asm properties -----------*- C++ -*--====//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the MipsTargetAsmInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSTARGETASMINFO_H
+#define MIPSTARGETASMINFO_H
+
+#include "llvm/Target/TargetAsmInfo.h"
+
+namespace llvm {
+
+  // Forward declaration.
+  class MipsTargetMachine;
+
+  struct MipsTargetAsmInfo : public TargetAsmInfo {
+    MipsTargetAsmInfo(const MipsTargetMachine &TM);
+  };
+
+} // namespace llvm
+
+#endif
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
new file mode 100644 (file)
index 0000000..de30284
--- /dev/null
@@ -0,0 +1,81 @@
+//===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements the info about Mips target spec.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Mips.h"
+#include "MipsTargetAsmInfo.h"
+#include "MipsTargetMachine.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Target/TargetMachineRegistry.h"
+using namespace llvm;
+
+namespace {
+  // Register the target.
+  RegisterTarget<MipsTargetMachine> X("mips", "  Mips");
+}
+
+const TargetAsmInfo *MipsTargetMachine::
+createTargetAsmInfo() const 
+{
+  return new MipsTargetAsmInfo(*this);
+}
+
+// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment
+// FrameInfo  --> StackGrowsDown, 8 bytes aligned, LOA : -4 (Ra : 0)
+MipsTargetMachine::
+MipsTargetMachine(const Module &M, const std::string &FS): 
+  Subtarget(*this, M, FS), DataLayout("E-p:32:32:32"), 
+  InstrInfo(*this), FrameInfo(TargetFrameInfo::StackGrowsDown, 8, -4),
+  TLInfo(*this) {}
+
+// return 0 and must specify -march to gen MIPS code.
+unsigned MipsTargetMachine::
+getModuleMatchQuality(const Module &M) 
+{
+  // We strongly match "mips-*".
+  std::string TT = M.getTargetTriple();
+  if (TT.size() >= 5 && std::string(TT.begin(), TT.begin()+5) == "mips-")
+    return 20;
+  
+  return 0;
+}
+
+// Install an instruction selector pass using 
+// the ISelDag to gen Mips code.
+bool MipsTargetMachine::
+addInstSelector(FunctionPassManager &PM, bool Fast) 
+{
+  PM.add(createMipsISelDag(*this));
+  return false;
+}
+
+// Implemented by targets that want to run passes immediately before 
+// machine code is emitted. return true if -print-machineinstrs should 
+// print out the code after the passes.
+// TODO: Delay slot must be implemented here.
+bool MipsTargetMachine::
+addPreEmitPass(FunctionPassManager &PM, bool Fast) 
+{
+  return false;
+}
+
+// Implements the AssemblyEmitter for the target. Must return
+// true if AssemblyEmitter is supported
+bool MipsTargetMachine::
+addAssemblyEmitter(FunctionPassManager &PM, bool Fast, 
+                   std::ostream &Out) 
+{
+  // Output assembly language.
+  PM.add(createMipsCodePrinterPass(Out, *this));
+  return false;
+}
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
new file mode 100644 (file)
index 0000000..9e1ccc3
--- /dev/null
@@ -0,0 +1,65 @@
+//===-- MipsTargetMachine.h - Define TargetMachine for Mips -00--*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bruno Cardoso Lopes and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the Mips specific subclass of TargetMachine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSTARGETMACHINE_H
+#define MIPSTARGETMACHINE_H
+
+#include "MipsSubtarget.h"
+#include "MipsInstrInfo.h"
+#include "MipsISelLowering.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetFrameInfo.h"
+
+namespace llvm {
+  class MipsTargetMachine : public LLVMTargetMachine {
+    MipsSubtarget       Subtarget;
+    const TargetData    DataLayout; // Calculates type size & alignment
+    MipsInstrInfo       InstrInfo;
+    TargetFrameInfo     FrameInfo;
+    MipsTargetLowering  TLInfo;
+  
+  protected:
+    virtual const TargetAsmInfo *createTargetAsmInfo() const;
+  
+  public:
+    MipsTargetMachine(const Module &M, const std::string &FS);
+
+    virtual const MipsInstrInfo   *getInstrInfo()     const 
+    { return &InstrInfo; }
+    virtual const TargetFrameInfo *getFrameInfo()     const 
+    { return &FrameInfo; }
+    virtual const TargetSubtarget *getSubtargetImpl() const 
+    { return &Subtarget; }
+    virtual const TargetData      *getTargetData()    const 
+    { return &DataLayout;}
+
+    virtual const MRegisterInfo   *getRegisterInfo()  const {
+      return &InstrInfo.getRegisterInfo();
+    }
+
+    virtual MipsTargetLowering   *getTargetLowering() const { 
+      return const_cast<MipsTargetLowering*>(&TLInfo); 
+    }
+
+    static unsigned getModuleMatchQuality(const Module &M);
+
+    // Pass Pipeline Configuration
+    virtual bool addInstSelector(FunctionPassManager &PM, bool Fast);
+    virtual bool addPreEmitPass(FunctionPassManager &PM, bool Fast);
+    virtual bool addAssemblyEmitter(FunctionPassManager &PM, bool Fast, 
+                                    std::ostream &Out);
+  };
+} // End llvm namespace
+
+#endif