summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/Mips/Makefile21
-rw-r--r--lib/Target/Mips/Mips.h38
-rw-r--r--lib/Target/Mips/Mips.td63
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp294
-rw-r--r--lib/Target/Mips/MipsCallingConv.td39
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp272
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp519
-rw-r--r--lib/Target/Mips/MipsISelLowering.h83
-rw-r--r--lib/Target/Mips/MipsInstrFormats.td96
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp114
-rw-r--r--lib/Target/Mips/MipsInstrInfo.h63
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td468
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp288
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.h83
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.td80
-rw-r--r--lib/Target/Mips/MipsSubtarget.cpp26
-rw-r--r--lib/Target/Mips/MipsSubtarget.h43
-rw-r--r--lib/Target/Mips/MipsTargetAsmInfo.cpp22
-rw-r--r--lib/Target/Mips/MipsTargetAsmInfo.h30
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp81
-rw-r--r--lib/Target/Mips/MipsTargetMachine.h65
21 files changed, 2788 insertions, 0 deletions
diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile
new file mode 100644
index 0000000000..6ebffc76e0
--- /dev/null
+++ b/lib/Target/Mips/Makefile
@@ -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
index 0000000000..48b08eaf80
--- /dev/null
+++ b/lib/Target/Mips/Mips.h
@@ -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
index 0000000000..662bc3b85d
--- /dev/null
+++ b/lib/Target/Mips/Mips.td
@@ -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
index 0000000000..fdf60d92a2
--- /dev/null
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -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
index 0000000000..23ef8503d3
--- /dev/null
+++ b/lib/Target/Mips/MipsCallingConv.td
@@ -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
index 0000000000..e660f9cb85
--- /dev/null
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -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
index 0000000000..98da5756a0
--- /dev/null
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -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
index 0000000000..3300f403f6
--- /dev/null
+++ b/lib/Target/Mips/MipsISelLowering.h
@@ -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
index 0000000000..b88fa90a25
--- /dev/null
+++ b/lib/Target/Mips/MipsInstrFormats.td
@@ -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
index 0000000000..808403067e
--- /dev/null
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -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
index 0000000000..356cf3d700
--- /dev/null
+++ b/lib/Target/Mips/MipsInstrInfo.h
@@ -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
index 0000000000..0a7e3ce29c
--- /dev/null
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -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
index 0000000000..a23a4264cf
--- /dev/null
+++ b/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -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
index 0000000000..d84194f31a
--- /dev/null
+++ b/lib/Target/Mips/MipsRegisterInfo.h
@@ -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
index 0000000000..2b7d15ff73
--- /dev/null
+++ b/lib/Target/Mips/MipsRegisterInfo.td
@@ -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
index 0000000000..a394f774ab
--- /dev/null
+++ b/lib/Target/Mips/MipsSubtarget.cpp
@@ -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
index 0000000000..7ec61ca95b
--- /dev/null
+++ b/lib/Target/Mips/MipsSubtarget.h
@@ -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
index 0000000000..08166f6f8e
--- /dev/null
+++ b/lib/Target/Mips/MipsTargetAsmInfo.cpp
@@ -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
index 0000000000..908f036bb1
--- /dev/null
+++ b/lib/Target/Mips/MipsTargetAsmInfo.h
@@ -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
index 0000000000..de30284e01
--- /dev/null
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -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
index 0000000000..9e1ccc3254
--- /dev/null
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -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