summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Nios2
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Nios2')
-rw-r--r--llvm/lib/Target/Nios2/Nios2ISelLowering.cpp29
-rw-r--r--llvm/lib/Target/Nios2/Nios2InstrFormats.td66
-rw-r--r--llvm/lib/Target/Nios2/Nios2InstrInfo.cpp11
-rw-r--r--llvm/lib/Target/Nios2/Nios2InstrInfo.h4
-rw-r--r--llvm/lib/Target/Nios2/Nios2InstrInfo.td39
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>;
OpenPOWER on IntegriCloud