Index: lib/Target/NDS32/CMakeLists.txt =================================================================== --- lib/Target/NDS32/CMakeLists.txt +++ lib/Target/NDS32/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_TARGET_DEFINITIONS NDS32.td) tablegen(LLVM NDS32GenRegisterInfo.inc -gen-register-info) +tablegen(LLVM NDS32GenInstrInfo.inc -gen-instr-info) tablegen(LLVM NDS32GenCallingConv.inc -gen-callingconv) add_public_tablegen_target(NDS32CommonTableGen) Index: lib/Target/NDS32/NDS32.td =================================================================== --- lib/Target/NDS32/NDS32.td +++ lib/Target/NDS32/NDS32.td @@ -42,3 +42,19 @@ //===----------------------------------------------------------------------===// include "NDS32CallingConv.td" + +//===----------------------------------------------------------------------===// +// Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "NDS32InstrInfo.td" + +def NDS32InstrInfo : InstrInfo; + +//===----------------------------------------------------------------------===// +// Target Declaration +//===----------------------------------------------------------------------===// + +def NDS32 : Target { + let InstructionSet = NDS32InstrInfo; +} Index: lib/Target/NDS32/NDS32CondMov.td =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32CondMov.td @@ -0,0 +1,83 @@ +//===- NDS32CondMov.td - Describe NDS32 Conditional Moves --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the Conditional Moves implementation. +// +//===----------------------------------------------------------------------===// + +// Conditional moves: +class CMOVE subop_encode> : + ALU_1Form<(outs GPR:$Rt), (ins GPR:$Ra, GPR:$Rb, GPR:$F), + !strconcat(opstr, "\t$Rt, $Ra, $Rb"), []> { + let Constraints = "$F = $Rt"; + + bits<5> Rt; + bits<5> Ra; + bits<5> Rb; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-10} = Rb; + let Inst{9-5} = 0; + let Inst{4-0} = subop_encode; +} + +def CMOVZ : CMOVE<"cmovz", 0b11010>; +def CMOVN : CMOVE<"cmovn", 0b11011>; + +// select patterns +multiclass CMovzPats0 { + def : Pat<(select (i32 (setge GPR:$lhs, GPR:$rhs)), GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (SLTOp GPR:$lhs, GPR:$rhs), GPR:$F)>; + def : Pat<(select (i32 (setuge GPR:$lhs, GPR:$rhs)), GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (SLTuOp GPR:$lhs, GPR:$rhs), GPR:$F)>; + def : Pat<(select (i32 (setge GPR:$lhs, immSExt15:$rhs)), GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (SLTiOp GPR:$lhs, immSExt15:$rhs), GPR:$F)>; + def : Pat<(select (i32 (setuge GPR:$lh, immSExt15:$rh)), GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (SLTiuOp GPR:$lh, immSExt15:$rh), GPR:$F)>; + def : Pat<(select (i32 (setle GPR:$lhs, GPR:$rhs)), GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (SLTOp GPR:$rhs, GPR:$lhs), GPR:$F)>; + def : Pat<(select (i32 (setule GPR:$lhs, GPR:$rhs)), GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (SLTuOp GPR:$rhs, GPR:$lhs), GPR:$F)>; + def : Pat<(select (i32 (setgt GPR:$lhs, immSExt15Plus1:$rhs)), + GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (SLTiOp GPR:$lhs, (Plus1 imm:$rhs)), GPR:$F)>; + def : Pat<(select (i32 (setugt GPR:$lhs, immSExt15Plus1:$rhs)), + GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (SLTiuOp GPR:$lhs, (Plus1 imm:$rhs)), + GPR:$F)>; +} + +multiclass CMovzPats1 { + def : Pat<(select (i32 (seteq GPR:$lhs, GPR:$rhs)), GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (XOROp GPR:$lhs, GPR:$rhs), GPR:$F)>; + def : Pat<(select (i32 (seteq GPR:$lhs, 0)), GPR:$T, GPR:$F), + (MOVZInst GPR:$T, GPR:$lhs, GPR:$F)>; +} + +multiclass CMovzPats2 { + def : Pat<(select (i32 (seteq GPR:$lhs, imm15u:$imm)), GPR:$T, GPR:$F), + (MOVZInst GPR:$T, (XORiOp GPR:$lhs, imm15u:$imm), GPR:$F)>; +} + +multiclass CMovnPats { + def : Pat<(select (i32 (setne GPR:$lhs, GPR:$rhs)), GPR:$T, GPR:$F), + (MOVNInst GPR:$T, (XOROp GPR:$lhs, GPR:$rhs), GPR:$F)>; + def : Pat<(select GPR:$cond, GPR:$T, GPR:$F), + (MOVNInst GPR:$T, GPR:$cond, GPR:$F)>; + def : Pat<(select (i32 (setne GPR:$lhs, 0)),GPR:$T, GPR:$F), + (MOVNInst GPR:$T, GPR:$lhs, GPR:$F)>; +} + +// Instantiation of conditional move patterns. +defm : CMovzPats0 ; +defm : CMovzPats1 ; +defm : CMovzPats2 ; +defm : CMovnPats ; Index: lib/Target/NDS32/NDS32InstrFormats.td =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32InstrFormats.td @@ -0,0 +1,286 @@ +//===-- NDS32InstrFormats.td - NDS32 Instruction Formats -*- tablegen -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Describe NDS32 instructions format here +// + +// Generic NDS32 Format +class NDS32Inst : Instruction { + let Namespace = "NDS32"; + + dag OutOperandList = outs; + dag InOperandList = ins; + + let AsmString = asmstr; + + field bits<32> SoftFail = 0; +} + +class 32BitInst opcode, + dag outs, dag ins, string asmstr, list pattern> + : NDS32Inst { + field bits<32> Inst; + let Size = 4; + + let Pattern = pattern; + let Inst{31} = 0; + let Inst{30-25} = opcode; +} + +class SETHIForm pattern> + : 32BitInst<0b100011, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<20> imm; + let Inst{24-20} = Rt; + let Inst{19-0} = imm; +} + +class MOVIForm pattern> + : 32BitInst<0b100010, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<20> imm; + let Inst{24-20} = Rt; + let Inst{19-0} = imm; +} + +class ALU_1Form pattern> + : 32BitInst<0b100000, outs, ins, asmstr, pattern>; + + +class ALU_2Form_rr pattern, + bits<6> sub_opcode> + : 32BitInst<0b100001, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<5> Ra; + bits<5> Rb; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-10} = Rb; + let Inst{9-6} = 0; + let Inst{5-0} = sub_opcode; +} + +class ALU_2Form_r pattern, + bits<6> sub_opcode> + : 32BitInst<0b100001, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<5> Ra; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-6} = 0; + let Inst{5-0} = sub_opcode; +} + +class 32Bit_5R5R15Imm opcode, dag outs, dag ins, + string asmstr, list pattern> + : 32BitInst { + bits<5> Rt; + bits<5> Ra; + bits<15> imm; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-0} = imm; +} + +class ADDIForm pattern> + : 32Bit_5R5R15Imm<0b101000, outs, ins, asmstr, pattern>; + +class ANDIForm pattern> + : 32Bit_5R5R15Imm<0b101010, outs, ins, asmstr, pattern>; + +class XORIForm pattern> + : 32Bit_5R5R15Imm<0b101011, outs, ins, asmstr, pattern>; + +class ORIForm pattern> + : 32Bit_5R5R15Imm<0b101100, outs, ins, asmstr, pattern>; + +class SUBRIForm pattern> + : 32Bit_5R5R15Imm<0b101001, outs, ins, asmstr, pattern>; + +class BITCIForm pattern> + : 32Bit_5R5R15Imm<0b110011, outs, ins, asmstr, pattern>; + +class SLTIForm pattern> + : 32Bit_5R5R15Imm<0b101110, outs, ins, asmstr, pattern>; + +class SLTSIForm pattern> + : 32Bit_5R5R15Imm<0b101111, outs, ins, asmstr, pattern>; + + +class 32Bit_5R20Addr opcode, dag outs, dag ins, + string asmstr, list pattern> + : 32BitInst { + bits<5> Rt; + bits<20> addr; + let Inst{24-20} = Rt; + let Inst{19-15} = addr{19-15}; // Ra + let Inst{14-0} = addr{14-0}; // imm15s +} + +class LWIForm pattern> + : 32Bit_5R20Addr<0b000010, outs, ins, asmstr, pattern>; + +class LHIForm pattern> + : 32Bit_5R20Addr<0b000001, outs, ins, asmstr, pattern>; + +class LBIForm pattern> + : 32Bit_5R20Addr<0b000000, outs, ins, asmstr, pattern>; + +class LHSIForm pattern> + : 32Bit_5R20Addr<0b010001, outs, ins, asmstr, pattern>; + +class LBSIForm pattern> + : 32Bit_5R20Addr<0b010000, outs, ins, asmstr, pattern>; + +class SWIForm pattern> + : 32Bit_5R20Addr<0b001010, outs, ins, asmstr, pattern>; + +class SHIForm pattern> + : 32Bit_5R20Addr<0b001001, outs, ins, asmstr, pattern>; + +class SBIForm pattern> + : 32Bit_5R20Addr<0b001000, outs, ins, asmstr, pattern>; + + +class 32Bit_5R5R15IMM_BI opcode, dag outs, dag ins, + string asmstr, list pattern> + : 32BitInst { + bits<5> Rt; + bits<5> addr; + bits<15> offset; + let Inst{24-20} = Rt; + let Inst{19-15} = addr; // Ra + let Inst{14-0} = offset; // imm15s +} + +class LWI_BIForm pattern> + : 32Bit_5R5R15IMM_BI<0b000110, outs, ins, asmstr, pattern>; + +class LHI_BIForm pattern> + : 32Bit_5R5R15IMM_BI<0b000101, outs, ins, asmstr, pattern>; + +class LBI_BIForm pattern> + : 32Bit_5R5R15IMM_BI<0b000100, outs, ins, asmstr, pattern>; + +class LHSI_BIForm pattern> + : 32Bit_5R5R15IMM_BI<0b010101, outs, ins, asmstr, pattern>; + +class LBSI_BIForm pattern> + : 32Bit_5R5R15IMM_BI<0b010100, outs, ins, asmstr, pattern>; + +class SWI_BIForm pattern> + : 32Bit_5R5R15IMM_BI<0b001110, outs, ins, asmstr, pattern>; + +class SHI_BIForm pattern> + : 32Bit_5R5R15IMM_BI<0b001101, outs, ins, asmstr, pattern>; + +class SBI_BIForm pattern> + : 32Bit_5R5R15IMM_BI<0b001100, outs, ins, asmstr, pattern>; + + +class MEMForm pattern, + bits<8> subop_encode> + : 32BitInst<0b011100, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<12> addr; + let Inst{24-20} = Rt; + let Inst{19-15} = addr{11-7}; // Ra + let Inst{14-10} = addr{6-2}; // Rb + let Inst{9-8} = addr{1-0}; // sv + let Inst{7-0} = subop_encode; +} + +class MEMForm_BI pattern, + bits<8> subop_encode> + : 32BitInst<0b011100, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<5> addr; + bits<5> offset; + let Inst{24-20} = Rt; + let Inst{19-15} = addr; // Ra + let Inst{14-10} = offset; // Rb + let Inst{9-8} = 0; // sv + let Inst{7-0} = subop_encode; +} + +class LSMWForm pattern, bit isStore> + : 32BitInst<0b011101, outs, ins, asmstr, pattern> { + bits<19> regs; + let Inst{24-20} = regs{18-14};// Rb + let Inst{19-15} = regs{13-9}; // Ra + let Inst{14-10} = regs{8-4}; // Re + let Inst{9-6} = regs{3-0}; // Enable4 + //It's a multiple store instruction if isStore == 1 + let Inst{5} = isStore; + let Inst{1-0} = 0b00; +} + +class JIForm pattern> + : 32BitInst<0b100100, outs, ins, asmstr, pattern>; + +class JREGForm pattern> + : 32BitInst<0b100101, outs, ins, asmstr, pattern>; + +class BR1Form pattern, + bit beq_bne> + : 32BitInst<0b100110, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<5> Ra; + bits<14> offset; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14} = beq_bne; + let Inst{13-0} = offset; +} + +class BR2Form pattern, + bits<4> branch_encode> + : 32BitInst<0b100111, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<16> offset; + let Inst{24-20} = Rt; + let Inst{19-16} = branch_encode; + let Inst{15-0} = offset; +} + +class BR3Form pattern, + bit branch_encode> + : 32BitInst<0b101101, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<8> offset; + bits<11> imm; + let Inst{24-20} = Rt; + let Inst{19} = branch_encode; + let Inst{18-8} = imm; + let Inst{7-0} = offset; +} + +class DPREFIForm pattern, + bit d> + : 32BitInst<0b010011, outs, ins, asmstr, pattern> { + bits<4> subtype; + bits<20> addr; + let Inst{24} = d; + let Inst{23-20} = subtype; + let Inst{19-15} = addr{19-15}; // Ra + let Inst{14-0} = addr{14-0}; // imm15s +} + +class MISCForm pattern> + : 32BitInst<0b110010, outs, ins, asmstr, pattern>; + +// Pseudo instructions +class Pseudo pattern> + : 32BitInst<0b110010, outs, ins, asmstr, pattern> { + let Inst{15-0} = 0; + let Pattern = pattern; + let isCodeGenOnly = 1; + let isPseudo = 1; +} Index: lib/Target/NDS32/NDS32InstrInfo.td =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32InstrInfo.td @@ -0,0 +1,901 @@ +//===-- NDS32InstrInfo.td - NDS32 Instruction defs -------*- tablegen -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the NDS32 instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +include "NDS32InstrFormats.td" +include "NDS32Predicate.td" + +//===----------------------------------------------------------------------===// +// Type Profiles. +//===----------------------------------------------------------------------===// +def SDT_NDS32Call : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; +def SDT_NDS32CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; +def SDT_NDS32CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; + +def SDT_NDS32MEMCPY : SDTypeProfile<2, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>, + SDTCisVT<2, i32>, SDTCisVT<3, i32>, + SDTCisVT<4, i32>]>; + + +//===----------------------------------------------------------------------===// +// NDS32 Specific Node Definitions. +//===----------------------------------------------------------------------===// +def NDS32ret : SDNode<"NDS32ISD::RET", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +def NDS32iret : SDNode<"NDS32ISD::IRET", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + +def NDS32call : SDNode<"NDS32ISD::CALL", SDT_NDS32Call, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>; +def NDS32callseq_start : + SDNode<"ISD::CALLSEQ_START", SDT_NDS32CallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; +def NDS32callseq_end : + SDNode<"ISD::CALLSEQ_END", SDT_NDS32CallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +def NDS32memcopy : SDNode<"NDS32ISD::MEMCPY", SDT_NDS32MEMCPY, + [SDNPHasChain, SDNPInGlue, SDNPOutGlue, + SDNPMayStore, SDNPMayLoad]>; + +// Hi20 and Lo12 nodes are used to handle global addresses. Used on +// NDS32ISelLowering to lower stuff like GlobalAddress, ExternalSymbol +// static model. +def NDS32hi20 : SDNode<"NDS32ISD::Hi20", SDTIntUnaryOp>; +def NDS32lo12 : SDNode<"NDS32ISD::Lo12", SDTIntUnaryOp>; + +def NDS32sdivrem : SDNode<"NDS32ISD::SDIVREM", SDTIntBinHiLoOp>; +def NDS32udivrem : SDNode<"NDS32ISD::UDIVREM", SDTIntBinHiLoOp>; + + +//===----------------------------------------------------------------------===// +// 16 bit Instructions +// + +include "NDS32Instr16Formats.td" +include "NDS32Instr16Bit.td" + + +//===----------------------------------------------------------------------===// +// Instruction list.. +// +// ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into +// a stack adjustment and the codegen must know that they may modify the stack +// pointer before prolog-epilog rewriting occurs. +// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become +// sub / add. +let Defs = [SP], Uses = [SP] in { +def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt), + "#ADJCALLSTACKDOWN", + [(NDS32callseq_start timm:$amt)]>; +def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), + "#ADJCALLSTACKUP", + [(NDS32callseq_end timm:$amt1, timm:$amt2)]>; +} + +let hasSideEffects = 0 in +def NOP : Pseudo<(outs), (ins), "nop", []>; + +//===----------------------------------------------------------------------===// +// Control Flow Instructions... +// + +class JREG_ret pat, bits<2> dt_it> : + JREGForm<(outs), (ins), opstr, pat> { + let Inst{24-15} = 0; + let Inst{14-10} = 30; // LP register number + let Inst{9-8} = dt_it; // DT/IT + let Inst{7-6} = 0; + let Inst{5} = 1; + let Inst{4-0} = 0; +} + +let isReturn = 1, isTerminator = 1, isBarrier = 1 in { + def RET : JREG_ret<"ret", [(NDS32ret)], 0b00>; + + def IRET : MISCForm<(outs), (ins), "iret", [(NDS32iret)]> { + let Inst{24-5} = 0; + let Inst{4-0} = 0b00100; + } + def RET_TOFF : JREG_ret<"ret.toff", [], 0b11>; + def RET_ITOFF : JREG_ret<"ret.itoff", [], 0b01>; +} + +class JREG_jump pat, bits<2> dt_it, + bits<5> sub_opcode> : + JREGForm<(outs), (ins GPR:$Rb), + !strconcat(opstr, "\t$Rb"), pat> { + bits<5> Rb; + let Inst{24-15} = 0; + let Inst{14-10} = Rb; + let Inst{9-8} = dt_it; // DT/IT + let Inst{7-6} = 0; + let Inst{5} = 0; + let Inst{4-0} = sub_opcode; +} + +let isBranch = 1, isTerminator = 1, isBarrier=1 in { + + // Unconditional jump + def J : JIForm<(outs), (ins nds32_j_target:$target), + "j\t$target", + [(br bb:$target)]> { + bits<24> target; + let Inst{24} = 0; + let Inst{23-0} = target; + } + // Unconditional jump to to the target in register + def JR : JREG_jump<"jr", [(brind GPR:$Rb)], 0b00, 0b00000> { + let isIndirectBranch = 1; + } + + // Unconditional jump to to the target in register + // and turn off address translation for the target instruction + def JR_TOFF : JREG_jump<"jr.toff", [], 0b11, 0b00000>; + + // Unconditional jump to to the target in register + // and turn off instruction address translation for the target instruction + def JR_ITOFF : JREG_jump<"jr.itoff", [], 0b01, 0b00000>; + + def JRNEZ : JREG_jump<"jrnez", [], 0b00, 0b00010>; +} // isBranch, isTerminator + + +// Conditional Branch +class CondBranch : + BR1Form<(outs), (ins GPR:$Rt, GPR:$Ra, brtarget:$offset), + !strconcat(opstr, "\t$Rt, $Ra, $offset"), + [(brcond (i32 (cond_op GPR:$Rt, GPR:$Ra)), bb:$offset)], beq_bne> { + let isBranch = 1; + let isTerminator = 1; +} + +def BEQ : CondBranch<"beq", seteq, 0>; +def BNE : CondBranch<"bne", setne, 1>; + + +// Conditional Branch compare with zero +class CondBranchZero branch_encode> : + BR2Form<(outs), (ins GPR:$Rt, brzerotarget:$offset), + !strconcat(opstr, "\t$Rt, $offset"), + [(brcond (i32 (cond_op GPR:$Rt, 0)), bb:$offset)], branch_encode> { + let isBranch = 1; + let isTerminator = 1; +} + +def BEQZ : CondBranchZero<"beqz", seteq, 0b0010>; +def BGEZ : CondBranchZero<"bgez", setge, 0b0100>; +def BGTZ : CondBranchZero<"bgtz", setgt, 0b0110>; +def BLEZ : CondBranchZero<"blez", setle, 0b0111>; +def BLTZ : CondBranchZero<"bltz", setlt, 0b0101>; +def BNEZ : CondBranchZero<"bnez", setne, 0b0011>; + +// Conditional Branch compare with a constant +class CondBranchConstant : + BR3Form<(outs), (ins GPR:$Rt, imm11s:$imm, brtargetImm8s_32bit:$offset), + !strconcat(opstr, "\t$Rt, $imm, $offset"), + [(brcond (i32 (cond_op GPR:$Rt, imm11s:$imm)), bb:$offset)], + branch_encode> { + let isBranch = 1; + let isTerminator = 1; +} + +def BEQC : CondBranchConstant<"beqc", seteq, 0>; +def BNEC : CondBranchConstant<"bnec", setne, 1>; + + +//===----------------------------------------------------------------------===// +// Call Instructions... +// + +// Conditional Call compare with zero +class CondCallZero branch_encode> : + BR2Form<(outs), (ins GPR:$Rt, nds32_jal_target:$offset), + !strconcat(opstr, "\t$Rt, $offset"), [], branch_encode>; + +class JREG_call pat, bits<2> dt_it, + bits<5> sub_opcode> : + JREGForm<(outs), (ins GPR:$Rb), + !strconcat(opstr, "\t$Rb"), pat> { + bits<5> Rb; + let Inst{24-20} = 30; // LP register number + let Inst{19-15} = 0; + let Inst{14-10} = Rb; + let Inst{9-8} = dt_it; + let Inst{7-5} = 0; + let Inst{4-0} = sub_opcode; +} + +let isCall = 1, + Defs = [LP] in { + def JAL : JIForm<(outs), (ins nds32_jal_target:$func), + "jal\t$func", + [(NDS32call tglobaladdr:$func)]> { + bits<24> func; + let Inst{24} = 1; + let Inst{23-0} = func; + } + def JRAL : JREG_call<"jral", [(NDS32call GPR:$Rb)], 0b00, 0b00001>; + + //Unconditional function call to an instruction address stored in a register + //and turn on address translation for the target instruction. + def JRAL_TON : JREG_call<"jral.ton", [], 0b11, 0b00001>; + + //Unconditional function call to an instruction address stored in a register + //and turn on instruction address translation for the target instruction. + def JRAL_ITON : JREG_call<"jral.iton",[], 0b01, 0b00001>; + + def JRALNEZ : JREG_call<"jralnez", [], 0b01, 0b00011>; + + def BGEZAL : CondCallZero<"bgezal", setge, 0b1100>; + def BLTZAL : CondCallZero<"bltzal", setlt, 0b1101>; +} + + +//===----------------------------------------------------------------------===// +// Move Instructions +// + +def SETHI : SETHIForm<(outs GPR:$Rt), (ins imm20u:$imm), + "sethi\t$Rt, $imm", []>; + +let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in +def MOVI : MOVIForm<(outs GPR:$Rt), (ins imm20s:$imm), + "movi\t$Rt, $imm", + [(set GPR:$Rt, (imm20s:$imm))]>; + + +//===----------------------------------------------------------------------===// +// System Register Move Instructions +// + +// Move the content of a system register into a general register. +def MFSR : MISCForm<(outs GPR:$Rt), (ins i32imm:$sridx), + "mfsr\t$Rt, $sridx", []> { + bits<5> Rt; + bits<10> sridx; + let Inst{24-20} = Rt; + let Inst{19-10} = sridx; + let Inst{9-5} = 0; + let Inst{4-0} = 0b00010; +} + +// Move the content of a general register into a system register. +def MTSR : MISCForm<(outs), (ins GPR:$Ra, i32imm:$sridx), + "mtsr\t$Ra, $sridx", []> { + bits<5> Ra; + bits<10> sridx; + let Inst{24-20} = Ra; + let Inst{19-10} = sridx; + let Inst{9-5} = 0; + let Inst{4-0} = 0b00011; +} + + +//===----------------------------------------------------------------------===// +// Arithmetic Instructions +// + +class ALU_1_rr subop_encode> : + ALU_1Form<(outs GPR:$Rt), (ins GPR:$Ra, GPR:$Rb), + !strconcat(opstr, "\t$Rt, $Ra, $Rb"), + [(set GPR:$Rt, (Op GPR:$Ra, GPR:$Rb))]> { + bits<5> Rt; + bits<5> Ra; + bits<5> Rb; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-10} = Rb; + let Inst{9-5} = 0; + let Inst{4-0} = subop_encode; +} + +let isAdd = 1 in +def ADD : ALU_1_rr< "add", add, 0b00000>; +def SUB : ALU_1_rr< "sub", sub, 0b00001>; +def AND : ALU_1_rr< "and", and, 0b00010>; +def OR : ALU_1_rr< "or", or, 0b00100>; +def SLL : ALU_1_rr< "sll", shl, 0b01100>; +def SRL : ALU_1_rr< "srl", srl, 0b01101>; +def SRA : ALU_1_rr< "sra", sra, 0b01110>; +def XOR : ALU_1_rr< "xor", xor, 0b00011>; +def SLT : ALU_1_rr< "slt", setult, 0b00110>; +def SLTS : ALU_1_rr<"slts", setlt, 0b00111>; +def ROTR : ALU_1_rr<"rotr", rotr, 0b01111>; + + +class ALU_1_ri subop_encode> : + ALU_1Form<(outs GPR:$Rt), (ins GPR:$Ra, imm5u:$imm), + !strconcat(opstr, "\t$Rt, $Ra, $imm"), + [(set GPR:$Rt, (Op GPR:$Ra, imm5u:$imm))]> { + bits<5> Rt; + bits<5> Ra; + bits<5> imm; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-10} = imm; + let Inst{9-5} = 0; + let Inst{4-0} = subop_encode; +} + +def SLLI : ALU_1_ri<"slli", shl, 0b01000>; +def SRLI : ALU_1_ri<"srli", srl, 0b01001>; +def SRAI : ALU_1_ri<"srai", sra, 0b01010>; +def ROTRI : ALU_1_ri<"rotri",rotr,0b01011>; + + +let isAdd = 1 in +def ADDI : ADDIForm<(outs GPR:$Rt), (ins GPR:$Ra, imm15s:$imm), + "addi\t$Rt, $Ra, $imm", + [(set GPR:$Rt, (add GPR:$Ra, imm15s:$imm))]>; + +def SUBRI : SUBRIForm<(outs GPR:$Rt), (ins imm15s:$imm, GPR:$Ra), + "subri\t$Rt, $Ra, $imm", + [(set GPR:$Rt, (sub imm15s:$imm, GPR:$Ra))]>; + +def ANDI : ANDIForm<(outs GPR:$Rt), (ins GPR:$Ra, imm15u:$imm), + "andi\t$Rt, $Ra, $imm", + [(set GPR:$Rt, (and GPR:$Ra, imm15u:$imm))]>; + +def MUL : ALU_2Form_rr<(outs GPR:$Rt), (ins GPR:$Ra, GPR:$Rb), + "mul\t$Rt, $Ra, $Rb", + [(set GPR:$Rt, (mul GPR:$Ra, GPR:$Rb))], + 0b100100>; + +def MADDR32 : ALU_2Form_rr<(outs GPR:$wb), (ins GPR:$Rt, GPR:$Ra, GPR:$Rb), + "maddr32\t$Rt, $Ra, $Rb", + [(set GPR:$wb, (add GPR:$Rt, (mul GPR:$Ra, GPR:$Rb)))], + 0b110011>{ + let Inst{9-6} = 1; + let Constraints = "$Rt = $wb"; +} + +def MSUBR32 : ALU_2Form_rr<(outs GPR:$wb), (ins GPR:$Rt, GPR:$Ra, GPR:$Rb), + "msubr32\t$Rt, $Ra, $Rb", + [(set GPR:$wb, (sub GPR:$Rt, (mul GPR:$Ra, GPR:$Rb)))], + 0b110101>{ + let Inst{9-6} = 1; + let Constraints = "$Rt = $wb"; +} + +def ORI : ORIForm<(outs GPR:$Rt), (ins GPR:$Ra, imm15u:$imm), + "ori\t$Rt, $Ra, $imm", + [(set GPR:$Rt, (or GPR:$Ra, imm15u:$imm))]>; + +def XORI : XORIForm<(outs GPR:$Rt), (ins GPR:$Ra, imm15u:$imm), + "xori\t$Rt, $Ra, $imm", + [(set GPR:$Rt, (xor GPR:$Ra, imm15u:$imm))]>; + +def SLTI : SLTIForm<(outs GPR:$Rt), (ins GPR:$Ra, imm15s:$imm), + "slti\t$Rt, $Ra, $imm", + [(set GPR:$Rt, (setult GPR:$Ra, imm15s:$imm))]>; + +def SLTSI : SLTSIForm<(outs GPR:$Rt), (ins GPR:$Ra, imm15s:$imm), + "sltsi\t$Rt, $Ra, $imm", + [(set GPR:$Rt, (setlt GPR:$Ra, imm15s:$imm))]>; + +def NOR: ALU_1Form<(outs GPR:$Rt), (ins GPR:$Ra, GPR:$Rb), + "nor\t$Rt, $Ra, $Rb", + [(set GPR:$Rt, (not (or GPR:$Ra, GPR:$Rb)))]> { + let isCommutable = 1; + bits<5> Rt; + bits<5> Ra; + bits<5> Rb; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-10} = Rb; + let Inst{9-5} = 0; + let Inst{4-0} = 0b00101; +} + +def BITC: ALU_1Form<(outs GPR:$Rt), (ins GPR:$Ra, GPR:$Rb), + "bitc\t$Rt, $Ra, $Rb", + [(set GPR:$Rt, (and GPR:$Ra, (not GPR:$Rb)))]> { + bits<5> Rt; + bits<5> Ra; + bits<5> Rb; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-10} = Rb; + let Inst{9-5} = 0; + let Inst{4-0} = 0b10010; +} + +def BITCI: BITCIForm<(outs GPR:$Rt), (ins GPR:$Ra, imm15u:$imm), + "bitci\t$Rt, $Ra, $imm", + [(set GPR:$Rt, (and GPR:$Ra, (not imm15u:$imm)))]>; + +//===----------------------------------------------------------------------===// +// Arithmetic with Shift Immediate Instructions +// + +class ALU_shift subop_encode> : + ALU_1Form<(outs GPR:$Rt), (ins GPR:$Ra, GPR:$Rb, imm5u:$sh), + !strconcat(opstr, "\t$Rt, $Ra, $Rb, $sh"), + [(set GPR:$Rt, (Op GPR:$Ra, (Shift GPR:$Rb, imm5u:$sh)))]> { + bits<5> Rt; + bits<5> Ra; + bits<5> Rb; + bits<5> sh; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-10} = Rb; + let Inst{9-5} = sh; + let Inst{4-0} = subop_encode; +} + +def ADD_SLLI : ALU_shift<"add_slli", add, shl, 0b00000>; +def ADD_SRLI : ALU_shift<"add_srli", add, srl, 0b11100>; +def SUB_SLLI : ALU_shift<"sub_slli", sub, shl, 0b00001>; +def SUB_SRLI : ALU_shift<"sub_srli", sub, srl, 0b11101>; +def AND_SLLI : ALU_shift<"and_slli", and, shl, 0b00010>; +def AND_SRLI : ALU_shift<"and_srli", and, srl, 0b11110>; +def OR_SLLI : ALU_shift<"or_slli" , or, shl, 0b00100>; +def OR_SRLI : ALU_shift<"or_srli" , or, srl, 0b10101>; +def XOR_SLLI : ALU_shift<"xor_slli", xor, shl, 0b00011>; +def XOR_SRLI : ALU_shift<"xor_srli", xor, srl, 0b11111>; + + +//===----------------------------------------------------------------------===// +// Sign Extension Instructions +// + +class ALU_1_sextend subop_encode> : + ALU_1Form<(outs GPR:$Rt), (ins GPR:$Ra), + !strconcat(opstr, "\t$Rt, $Ra"), + [(set GPR:$Rt, (Op GPR:$Ra, vt))]> { + bits<5> Rt; + bits<5> Ra; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-5} = 0; + let Inst{4-0} = subop_encode; +} + +def SEB : ALU_1_sextend< "seb", sext_inreg, i8, 0b10000>; +def SEH : ALU_1_sextend< "seh", sext_inreg, i16, 0b10001>; + + +//===----------------------------------------------------------------------===// +// Division Instructions +// +// In NDS32 ISA, quotient and remainder register set to same register +// will only set quotient value to the register which match the semantic +// udiv/sdiv in dags. +class DIVrr subop_encode> : + ALU_1Form<(outs GPR:$Rt), (ins GPR:$Ra, GPR:$Rb), + !strconcat(opstr, "\t$Rt, $Rt, $Ra, $Rb"), + [(set GPR:$Rt, (Op GPR:$Ra, GPR:$Rb))]> { + bits<5> Rt; + bits<5> Ra; + bits<5> Rb; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-10} = Rb; + let Inst{9-5} = Rt; + let Inst{4-0} = subop_encode; +} + +class DIVREM subop_encode> : + ALU_1Form<(outs GPR:$Rt, GPR:$Rs), (ins GPR:$Ra, GPR:$Rb), + !strconcat(opstr, "\t$Rt, $Rs, $Ra, $Rb"), []> { + bits<5> Rt; + bits<5> Rs; + bits<5> Ra; + bits<5> Rb; + let Inst{24-20} = Rt; + let Inst{19-15} = Ra; + let Inst{14-10} = Rb; + let Inst{9-5} = Rs; + let Inst{4-0} = subop_encode; +} + +def UDIVREM : DIVREM< "divr", 0b10111>; +def SDIVREM : DIVREM< "divsr", 0b10110>; + + +//===----------------------------------------------------------------------===// +// Load / store multiple Instructions. +// + +class lsmw_modify_base : + LSMWForm<(outs GPR:$wb), (ins reglist:$regs, variable_ops), + !strconcat(opstr,"\t$regs"), [], isStore> { + let Constraints = "$regs.base = $wb"; + //Use either base+4 or base-4 as first memory address if use_next_pos == 1 + let Inst{4} = use_next_pos; + let Inst{3} = decrement; + let Inst{2} = 1; // Modify base register + let DecoderMethod = "DecodeLSMWModifyBase"; +} + +class lsmw : + LSMWForm<(outs), (ins reglist:$regs, variable_ops), + !strconcat(opstr,"\t$regs"), [], isStore> { + //Use either base+4 or base-4 as first memory address if use_next_pos == 1 + let Inst{4} = use_next_pos; + let Inst{3} = decrement; + let Inst{2} = 0; // Not modify base register +} + +multiclass nds32_lsmw { + def _ADM : lsmw_modify_base ; + def _BIM : lsmw_modify_base ; + def _AD : lsmw ; + def _BD : lsmw ; + def _BI : lsmw ; + def _AI : lsmw ; +} + +let hasSideEffects = 0 in { + +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in +defm LMW : nds32_lsmw<"lmw", 0>; + +let mayStore = 1, hasExtraSrcRegAllocReq = 1 in +defm SMW : nds32_lsmw<"smw", 1>; + +} // hasSideEffects + +let hasPostISelHook = 1, Constraints = "$newdst = $dst, $newsrc = $src" in { + // %newsrc, %newdst = MEMCPY %dst, %src, N, ...N scratch regs... + // Copies N registers worth of memory from address %src to address %dst + // and returns the incremented addresses. N scratch register will + // be attached for the copy to use. + def MEMCPY : Pseudo< + (outs GPR:$newdst, GPR:$newsrc), + (ins GPR:$dst, GPR:$src, i32imm:$nreg, variable_ops), + "", + [(set GPR:$newdst, GPR:$newsrc, + (NDS32memcopy GPR:$dst, GPR:$src, imm:$nreg))]>; +} + + +//===----------------------------------------------------------------------===// +// Load/Store Instructions +// + +let AddedComplexity = 4, mayLoad = 1 in { +def LWI: LWIForm<(outs GPR:$Rt), (ins addr_imm15s_word:$addr), + "lwi\t$Rt, $addr", + [(set GPR:$Rt, (load addr_imm15s_word:$addr))]>; + +def LHI: LHIForm<(outs GPR:$Rt), (ins addr_imm15s_half:$addr), + "lhi\t$Rt, $addr", + [(set GPR:$Rt, (zextloadi16 addr_imm15s_half:$addr))]>; + +def LBI: LBIForm<(outs GPR:$Rt), (ins addr_imm15s_byte:$addr), + "lbi\t$Rt, $addr", + [(set GPR:$Rt, (zextloadi8 addr_imm15s_byte:$addr))]>; + +def LHSI: LHSIForm<(outs GPR:$Rt), (ins addr_imm15s_half:$addr), + "lhsi\t$Rt, $addr", + [(set GPR:$Rt, (sextloadi16 addr_imm15s_half:$addr))]>; + +def LBSI: LBSIForm<(outs GPR:$Rt), (ins addr_imm15s_byte:$addr), + "lbsi\t$Rt, $addr", + [(set GPR:$Rt, (sextloadi8 addr_imm15s_byte:$addr))]>; + +def LWI_BI: LWI_BIForm<(outs GPR:$Rt, GPR:$Ra_wb), + (ins addr_reg:$addr, offset_imm15s_word:$offset), + "lwi.bi\t$Rt, $addr, $offset", []> { + let Constraints = "$addr.base = $Ra_wb"; +} + +def LHI_BI: LHI_BIForm<(outs GPR:$Rt, GPR:$Ra_wb), + (ins addr_reg:$addr, offset_imm15s_half:$offset), + "lhi.bi\t$Rt, $addr, $offset", []> { + let Constraints = "$addr.base = $Ra_wb"; +} + +def LBI_BI: LBI_BIForm<(outs GPR:$Rt, GPR:$Ra_wb), + (ins addr_reg:$addr, offset_imm15s_byte:$offset), + "lbi.bi\t$Rt, $addr, $offset", []> { + let Constraints = "$addr.base = $Ra_wb"; +} + +def LHSI_BI: LHSI_BIForm<(outs GPR:$Rt, GPR:$Ra_wb), + (ins addr_reg:$addr, offset_imm15s_half:$offset), + "lhsi.bi\t$Rt, $addr, $offset", []> { + let Constraints = "$addr.base = $Ra_wb"; +} + +def LBSI_BI: LBSI_BIForm<(outs GPR:$Rt, GPR:$Ra_wb), + (ins addr_reg:$addr, offset_imm15s_byte:$offset), + "lbsi.bi\t$Rt, $addr, $offset", []> { + let Constraints = "$addr.base = $Ra_wb"; +} +} + +let AddedComplexity = 4, mayStore = 1 in { +def SWI: SWIForm<(outs), (ins GPR:$Rt, addr_imm15s_word:$addr), + "swi\t$Rt, $addr", + [(store GPR:$Rt, addr_imm15s_word:$addr)]>; + +def SHI: SHIForm<(outs), (ins GPR:$Rt, addr_imm15s_half:$addr), + "shi\t$Rt, $addr", + [(truncstorei16 GPR:$Rt, addr_imm15s_half:$addr)]>; + +def SBI: SBIForm<(outs), (ins GPR:$Rt, addr_imm15s_byte:$addr), + "sbi\t$Rt, $addr", + [(truncstorei8 GPR:$Rt, addr_imm15s_byte:$addr)]>; + +def SWI_BI: SWI_BIForm<(outs GPR:$Ra_wb), + (ins GPR:$Rt, addr_reg:$addr, + offset_imm15s_word:$offset), + "swi.bi\t$Rt, $addr, $offset", []> { + let Constraints = "$addr.base = $Ra_wb,@earlyclobber $Ra_wb"; +} + +def SHI_BI: SHI_BIForm<(outs GPR:$Ra_wb), + (ins GPR:$Rt, addr_reg:$addr, + offset_imm15s_half:$offset), + "shi.bi\t$Rt, $addr, $offset", []> { + let Constraints = "$addr.base = $Ra_wb,@earlyclobber $Ra_wb"; +} + +def SBI_BI: SBI_BIForm<(outs GPR:$Ra_wb), + (ins GPR:$Rt, addr_reg:$addr, + offset_imm15s_byte:$offset), + "sbi.bi\t$Rt, $addr, $offset", []> { + let Constraints = "$addr.base = $Ra_wb,@earlyclobber $Ra_wb"; +} +} + +let mayLoad = 1 in +class MEM_load subop_encode> : + MEMForm<(outs GPR:$Rt), (ins ldst_reg_shift:$addr), + !strconcat(opstr, "\t$Rt, $addr"), + [(set GPR:$Rt, (Op ldst_reg_shift:$addr))], subop_encode>; + +def LW : MEM_load< "lw", load, 0b00000010>; +def LH : MEM_load< "lh", zextloadi16, 0b00000001>; +def LHS : MEM_load< "lhs", sextloadi16, 0b00010001>; +def LB : MEM_load< "lb", zextloadi8, 0b00000000>; +def LBS : MEM_load< "lbs", sextloadi8, 0b00010000>; + + +let mayStore = 1 in +class MEM_store subop_encode> : + MEMForm<(outs), (ins GPR:$Rt, ldst_reg_shift:$addr), + !strconcat(opstr, "\t$Rt, $addr"), + [(Op GPR:$Rt, ldst_reg_shift:$addr)], subop_encode>; + +def SW : MEM_store< "sw", store, 0b00001010>; +def SH : MEM_store< "sh", truncstorei16, 0b00001001>; +def SB : MEM_store< "sb", truncstorei8, 0b00001000>; + + +let mayLoad = 1 in +class MEM_load_post subop_encode> : + MEMForm_BI<(outs GPR:$Rt, GPR:$Ra_wb), + (ins addr_reg:$addr, offset_reg:$offset), + !strconcat(opstr, "\t$Rt, $addr, $offset"), + [], subop_encode> { + let Constraints = "$addr.base = $Ra_wb"; +} + +def LW_BI : MEM_load_post< "lw.bi", 0b00000110>; +def LH_BI : MEM_load_post< "lh.bi", 0b00000101>; +def LB_BI : MEM_load_post< "lb.bi", 0b00000100>; +def LHS_BI : MEM_load_post< "lhs.bi", 0b00010101>; +def LBS_BI : MEM_load_post< "lbs.bi", 0b00010100>; + + +let mayStore = 1 in +class MEM_store_post subop_encode> : + MEMForm_BI<(outs GPR:$Ra_wb), + (ins GPR:$Rt, addr_reg:$addr, offset_reg:$offset), + !strconcat(opstr, "\t$Rt, $addr, $offset"), + [], subop_encode> { + let Constraints = "$addr.base = $Ra_wb,@earlyclobber $Ra_wb"; +} + +def SW_BI : MEM_store_post< "sw.bi", 0b00001110>; +def SH_BI : MEM_store_post< "sh.bi", 0b00001101>; +def SB_BI : MEM_store_post< "sb.bi", 0b00001100>; + + +//To load a 32-bit word from memory into a general register +//with the user mode privilege address translation. +def LWUP: MEMForm<(outs GPR:$Rt), (ins ldst_reg_shift:$addr), + "lwup\t$Rt, $addr", [], 0b00100010>; + +//To store a 32-bit word from a general register into memory +//with the user mode privilege address translation. +def SWUP: MEMForm<(outs), (ins GPR:$Rt, ldst_reg_shift:$addr), + "swup\t$Rt, $addr", [], 0b00101010>; + + +//===----------------------------------------------------------------------===// +// Interlocking Instructions +// to perform an atomic read, modify and write sequence +// + +def LLW: MEMForm<(outs GPR:$Rt), (ins ldst_reg_shift:$addr), + "llw\t$Rt, $addr", [], 0b00011000>; + +def SCW: MEMForm<(outs GPR:$Rt), (ins ldst_reg_shift:$addr), + "scw\t$Rt, $addr", [], 0b00011001>; + +//===----------------------------------------------------------------------===// +// Data Prefetch Instructions +// + +def DPREF: MEMForm<(outs), (ins i32imm:$subtype, ldst_reg_shift:$addr), + "dpref\t$subtype, $addr", [], 0b00010011>; + +class DPREFI : + DPREFIForm<(outs), (ins i32imm:$subtype, addr_imm15s_word:$addr), + "dprefi.suffix\t$subtype, $addr", [], d>; + +def DPREFI_D : DPREFI< "d", 1>; +def DPREFI_W : DPREFI< "w", 0>; + + +//===----------------------------------------------------------------------===// +// Memory barriers Instructions +// + +let hasSideEffects = 1 in { + def DSB : MISCForm<(outs), (ins), "dsb", []> { + let Inst{24-5} = 0; + let Inst{4-0} = 0b01000; + } + def ISB : MISCForm<(outs), (ins), "isb", []> { + let Inst{24-5} = 0; + let Inst{4-0} = 0b01001; + } + def ISYNC : MISCForm<(outs), (ins GPR:$Ra), "isync\t$Ra", []> { + bits<5> Ra; + let Inst{24-20} = Ra; + let Inst{19-5} = 0; + let Inst{4-0} = 0b01101; + } + def MSYNC : MISCForm<(outs), (ins i32imm:$subtype), + "msync\t$subtype", []> { + bits<3> subtype; + let Inst{24-8} = 0; + let Inst{7-5} = subtype; + let Inst{4-0} = 0b01100; + } +} + +//===----------------------------------------------------------------------===// +// Performance Extension Instructions +// + +def CLZ : ALU_2Form_r<(outs GPR:$Rt), (ins GPR:$Ra), + "clz\t$Rt, $Ra", + [(set GPR:$Rt, (ctlz GPR:$Ra))], + 0b000111>; + + +//===----------------------------------------------------------------------===// +// MISC Instructions +// + +def SYSCALL : MISCForm<(outs), (ins i32imm:$swid), + "syscall\t$swid", []> { + bits<15> swid; + let Inst{24-20} = 0; + let Inst{19-5} = swid; + let Inst{4-0} = 0b01011; +} + +def BREAK : MISCForm<(outs), (ins i32imm:$swid), "break", []> { + bits<15> swid; + let Inst{24-20} = 0; + let Inst{19-5} = swid; + let Inst{4-0} = 0b01010; +} + + +//===----------------------------------------------------------------------===// +// Pattern Transformation +//===----------------------------------------------------------------------===// + +// hi/lo relocs +def : Pat<(NDS32hi20 tglobaladdr:$in), (SETHI tglobaladdr:$in)>; +def : Pat<(NDS32hi20 tblockaddress:$in), (SETHI tblockaddress:$in)>; +def : Pat<(NDS32hi20 tjumptable:$in), (SETHI tjumptable:$in)>; +def : Pat<(NDS32hi20 tconstpool:$in), (SETHI tconstpool:$in)>; +def : Pat<(NDS32hi20 tglobaltlsaddr:$in), (SETHI tglobaltlsaddr:$in)>; +def : Pat<(NDS32hi20 texternalsym:$in), (SETHI texternalsym:$in)>; + +def : Pat<(or GPR:$hi, (NDS32lo12 tglobaladdr:$lo)), + (ORI GPR:$hi, tglobaladdr:$lo)>; +def : Pat<(or GPR:$hi, (NDS32lo12 tblockaddress:$lo)), + (ORI GPR:$hi, tblockaddress:$lo)>; +def : Pat<(or GPR:$hi, (NDS32lo12 tjumptable:$lo)), + (ORI GPR:$hi, tjumptable:$lo)>; +def : Pat<(or GPR:$hi, (NDS32lo12 tconstpool:$lo)), + (ORI GPR:$hi, tconstpool:$lo)>; +def : Pat<(or GPR:$hi, (NDS32lo12 tglobaltlsaddr:$lo)), + (ORI GPR:$hi, tglobaltlsaddr:$lo)>; + +// division patterns +def : Pat<(NDS32sdivrem i32:$Ra, i32:$Rb), + (SDIVREM i32:$Ra, i32:$Rb)>; +def : Pat<(NDS32udivrem i32:$Ra, i32:$Rb), + (UDIVREM i32:$Ra, i32:$Rb)>; + + +// call patterns +def : Pat<(NDS32call (i32 tglobaladdr:$dst)), + (JAL tglobaladdr:$dst)>; +def : Pat<(NDS32call (i32 texternalsym:$dst)), + (JAL texternalsym:$dst)>; + +// brcond patterns +def : Pat<(brcond (i32 (setlt i32:$lhs, 1)), bb:$dst), + (BLEZ i32:$lhs, bb:$dst)>; +def : Pat<(brcond (i32 (setgt i32:$lhs, -1)), bb:$dst), + (BGEZ i32:$lhs, bb:$dst)>; +def : Pat<(brcond GPR:$cond, bb:$dst), + (BNEZ GPR:$cond, bb:$dst)>; + +// seteq patterns +def : Pat<(seteq GPR:$lhs, 0), + (SLTI GPR:$lhs, 1)>; +def : Pat<(seteq GPR:$lhs, imm15u:$imm), + (SLTI (XORI GPR:$lhs, imm15u:$imm), 1)>; +def : Pat<(seteq GPR:$lhs, GPR:$rhs), + (SLTI (XOR GPR:$lhs, GPR:$rhs), 1)>; + +// setne patterns +def : Pat<(setne GPR:$lhs, imm15u:$imm), + (SLT (MOVI 0), (XORI GPR:$lhs, imm15u:$imm))>; +def : Pat<(setne GPR:$lhs, GPR:$rhs), + (SLT (MOVI 0), (XOR GPR:$lhs, GPR:$rhs))>; + +// setge/setuge patterns +def : Pat<(setge GPR:$lhs, GPR:$rhs), + (XORI (SLTS GPR:$lhs, GPR:$rhs), 1)>; +def : Pat<(setge GPR:$lhs, imm15s:$rhs), + (XORI (SLTSI GPR:$lhs, imm15s:$rhs), 1)>; +def : Pat<(setuge GPR:$lhs, GPR:$rhs), + (XORI (SLT GPR:$lhs, GPR:$rhs), 1)>; +def : Pat<(setuge GPR:$lhs, imm15s:$rhs), + (XORI (SLTI GPR:$lhs, imm15s:$rhs), 1)>; + +// setgt/setugt patterns +def : Pat<(setgt GPR:$lhs, GPR:$rhs), + (SLTS GPR:$rhs, GPR:$lhs)>; +def : Pat<(setugt GPR:$lhs, GPR:$rhs), + (SLT GPR:$rhs, GPR:$lhs)>; + +// setle/setule patterns +def : Pat<(setle GPR:$lhs, GPR:$rhs), + (XORI (SLTS GPR:$rhs, GPR:$lhs), 1)>; +def : Pat<(setule GPR:$lhs, GPR:$rhs), + (XORI (SLT GPR:$rhs, GPR:$lhs), 1)>; + +// load patterns +def : Pat<(i32 (extloadi16 addr_imm15s_half:$src)), (LHI addr_imm15s_half:$src)>; +def : Pat<(i32 (extloadi8 addr_imm15s_byte:$src)), (LBI addr_imm15s_byte:$src)>; + +// Arbitrary immediates +def : Pat<(i32 imm:$imm), + (ORI (SETHI (HI20 imm:$imm)), (LO12 imm:$imm))>; + + +//===----------------------------------------------------------------------===// +// Conditional Move Instructions +// + +include "NDS32CondMov.td" + +//===----------------------------------------------------------------------===//