diff options
Diffstat (limited to 'llvm/lib/Target/Nios2')
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2ISelLowering.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2InstrFormats.td | 66 | ||||
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2InstrInfo.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2InstrInfo.h | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Nios2/Nios2InstrInfo.td | 39 |
5 files changed, 138 insertions, 11 deletions
diff --git a/llvm/lib/Target/Nios2/Nios2ISelLowering.cpp b/llvm/lib/Target/Nios2/Nios2ISelLowering.cpp index 99aa43f960c..008ce157072 100644 --- a/llvm/lib/Target/Nios2/Nios2ISelLowering.cpp +++ b/llvm/lib/Target/Nios2/Nios2ISelLowering.cpp @@ -32,9 +32,38 @@ Nios2TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, SelectionDAG &DAG) const { + // CCValAssign - represent the assignment of + // the return value to a location + SmallVector<CCValAssign, 16> RVLocs; + MachineFunction &MF = DAG.getMachineFunction(); + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); + // Analyze return values. + CCInfo.CheckReturn(Outs, RetCC_Nios2EABI); + SDValue Flag; SmallVector<SDValue, 4> RetOps(1, Chain); + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + SDValue Val = OutVals[i]; + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + if (RVLocs[i].getValVT() != RVLocs[i].getLocVT()) + Val = DAG.getNode(ISD::BITCAST, DL, RVLocs[i].getLocVT(), Val); + + Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag); + + // Guarantee that all emitted copies are stuck together with flags. + Flag = Chain.getValue(1); + RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); + } + + if (Flag.getNode()) + RetOps.push_back(Flag); + return DAG.getNode(Nios2ISD::Ret, DL, MVT::Other, RetOps); } diff --git a/llvm/lib/Target/Nios2/Nios2InstrFormats.td b/llvm/lib/Target/Nios2/Nios2InstrFormats.td index 58578501d80..f57bf03bba3 100644 --- a/llvm/lib/Target/Nios2/Nios2InstrFormats.td +++ b/llvm/lib/Target/Nios2/Nios2InstrFormats.td @@ -20,14 +20,44 @@ class Format<bits<6> val> { bits<6> Value = val; } -def Pseudo : Format<0>; -def FrmI : Format<1>; -def FrmR : Format<2>; -def FrmJ : Format<3>; -def FrmOther : Format<4>; // Instruction w/ a custom format +def Pseudo : Format<0>; +// Nios2 R1 instr formats: +def FrmI : Format<1>; +def FrmR : Format<2>; +def FrmJ : Format<3>; +def FrmOther : Format<4>; // Instruction w/ a custom format +// Nios2 R2 instr 32-bit formats: +def FrmL26 : Format<5>; // corresponds to J format in R1 +def FrmF2I16 : Format<6>; // corresponds to I format in R1 +def FrmF2X4I12 : Format<7>; +def FrmF1X4I12 : Format<8>; +def FrmF1X4L17 : Format<9>; +def FrmF3X6L5 : Format<10>; // corresponds to R format in R1 +def FrmF2X6L10 : Format<11>; +def FrmF3X6 : Format<12>; // corresponds to R format in R1 +def FrmF3X8 : Format<13>; // corresponds to custom format in R1 +// Nios2 R2 instr 16-bit formats: +def FrmI10 : Format<14>; +def FrmT1I7 : Format<15>; +def FrmT2I4 : Format<16>; +def FrmT1X1I6 : Format<17>; +def FrmX1I7 : Format<18>; +def FrmL5I4X1 : Format<19>; +def FrmT2X1L3 : Format<20>; +def FrmT2X1I3 : Format<21>; +def FrmT3X1 : Format<22>; +def FrmT2X3 : Format<23>; +def FrmF1X1 : Format<24>; +def FrmX2L5 : Format<25>; +def FrmF1I5 : Format<26>; +def FrmF2 : Format<27>; -def isNios2r1 : Predicate<"Subtarget->isNios2r1()">; -def isNios2r2 : Predicate<"Subtarget->isNios2r2()">; +//===----------------------------------------------------------------------===// +// Instruction Predicates: +//===----------------------------------------------------------------------===// + +def isNios2r1 : Predicate<"Subtarget->isNios2r1()">; +def isNios2r2 : Predicate<"Subtarget->isNios2r2()">; class PredicateControl { // Predicates related to specific target CPU features @@ -151,6 +181,27 @@ class FJ<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern, } //===----------------------------------------------------------------------===// +// Format F3X6 (R2) instruction : <|opx|RSV|C|B|A|opcode|> +//===----------------------------------------------------------------------===// + +class F3X6<bits<6> opx, dag outs, dag ins, string asmstr, list<dag> pattern, + InstrItinClass itin>: + Nios2R2Inst32<outs, ins, asmstr, pattern, itin, FrmF3X6> { + bits<5> rC; + bits<5> rB; + bits<5> rA; + bits<5> rsv = 0; + + let Opcode = 0x20; /* opcode is always 0x20 (OPX group) for F3X6 instr. */ + + let Inst{31-26} = opx; /* opx stands for opcode extension */ + let Inst{25-21} = rsv; + let Inst{20-16} = rC; + let Inst{15-11} = rB; + let Inst{10-6} = rA; +} + +//===----------------------------------------------------------------------===// // Multiclasses for common instructions of both R1 and R2: //===----------------------------------------------------------------------===// @@ -160,6 +211,7 @@ multiclass CommonInstr_R_F3X6_opx<bits<6> opxR1, bits<6> opxR2, dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin> { def NAME#_R1 : FR<opxR1, outs, ins, asmstr, pattern, itin>; + def NAME#_R2 : F3X6<opxR2, outs, ins, asmstr, pattern, itin>; } // Multiclass for instructions that have R format in R1 and F3X6 format in R2 diff --git a/llvm/lib/Target/Nios2/Nios2InstrInfo.cpp b/llvm/lib/Target/Nios2/Nios2InstrInfo.cpp index df435d2715d..9700cba3595 100644 --- a/llvm/lib/Target/Nios2/Nios2InstrInfo.cpp +++ b/llvm/lib/Target/Nios2/Nios2InstrInfo.cpp @@ -41,3 +41,14 @@ bool Nios2InstrInfo::expandPostRAPseudo(MachineInstr &MI) const { MBB.erase(MI); return true; } + +void Nios2InstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + const DebugLoc &DL, unsigned DestReg, + unsigned SrcReg, bool KillSrc) const { + unsigned opc = Subtarget.hasNios2r2() ? Nios2::ADD_R2 : Nios2::ADD_R1; + BuildMI(MBB, I, DL, get(opc)) + .addReg(DestReg, RegState::Define) + .addReg(Nios2::ZERO) + .addReg(SrcReg, getKillRegState(KillSrc)); +} diff --git a/llvm/lib/Target/Nios2/Nios2InstrInfo.h b/llvm/lib/Target/Nios2/Nios2InstrInfo.h index a994d3662db..52f6e7e9c7c 100644 --- a/llvm/lib/Target/Nios2/Nios2InstrInfo.h +++ b/llvm/lib/Target/Nios2/Nios2InstrInfo.h @@ -39,6 +39,10 @@ public: const Nios2RegisterInfo &getRegisterInfo() const { return RI; }; bool expandPostRAPseudo(MachineInstr &MI) const override; + + void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, + bool KillSrc) const override; }; } // namespace llvm diff --git a/llvm/lib/Target/Nios2/Nios2InstrInfo.td b/llvm/lib/Target/Nios2/Nios2InstrInfo.td index 7a39b31a25a..dee84f74bcb 100644 --- a/llvm/lib/Target/Nios2/Nios2InstrInfo.td +++ b/llvm/lib/Target/Nios2/Nios2InstrInfo.td @@ -30,6 +30,10 @@ def simm16 : Operand<i32> { // e.g. addi, andi def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>; +// Custom return SDNode +def Nios2Ret : SDNode<"Nios2ISD::Ret", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -45,6 +49,16 @@ multiclass ArithLogicRegImm16<bits<6> op, string mnemonic, SDNode opNode, (opNode CPURegs:$rA, immType:$imm))], IIAlu>; +// Arithmetic and logical instructions with 3 register operands. +// Defines R1 and R2 instruction at the same time. +multiclass ArithLogicReg<bits<6> opx, string mnemonic, + SDNode opNode>: + CommonInstr_R_F3X6<opx, (outs CPURegs:$rC), + (ins CPURegs:$rA, CPURegs:$rB), + !strconcat(mnemonic, "\t$rC, $rA, $rB"), + [(set CPURegs:$rC, (opNode CPURegs:$rA, CPURegs:$rB))], + IIAlu>; + multiclass Return<bits<6> opx, dag outs, dag ins, string mnemonic> { let rB = 0, rC = 0, isReturn = 1, @@ -55,14 +69,31 @@ multiclass Return<bits<6> opx, dag outs, dag ins, string mnemonic> { } } -// Custom return SDNode -def Nios2Ret : SDNode<"Nios2ISD::Ret", SDTNone, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; - //===----------------------------------------------------------------------===// // Nios2 Instructions //===----------------------------------------------------------------------===// +/// Arithmetic instructions operating on registers. +let isCommutable = 1 , + isReMaterializable = 1 in { + defm ADD : ArithLogicReg<0x31, "add", add>; + defm AND : ArithLogicReg<0x0e, "and", and>; + defm OR : ArithLogicReg<0x16, "or", or>; + defm XOR : ArithLogicReg<0x1e, "xor", xor>; + defm MUL : ArithLogicReg<0x27, "mul", mul>; +} + +let isReMaterializable = 1 in { + defm SUB : ArithLogicReg<0x39, "sub", sub>; +} + +defm DIVU : ArithLogicReg<0x24, "divu", udiv>; +defm DIV : ArithLogicReg<0x25, "div", sdiv>; + +defm SLL : ArithLogicReg<0x13, "sll", shl>; +defm SRL : ArithLogicReg<0x1b, "srl", srl>; +defm SRA : ArithLogicReg<0x3b, "sra", sra>; + /// Arithmetic Instructions (ALU Immediate) defm ADDI : ArithLogicRegImm16<0x04, "addi", add, simm16, immSExt16>; |