Index: lib/Target/NDS32/NDS32InstrFormats.td =================================================================== --- lib/Target/NDS32/NDS32InstrFormats.td +++ lib/Target/NDS32/NDS32InstrFormats.td @@ -34,6 +34,55 @@ let Inst{30-25} = opcode; } +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 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 SLTIForm pattern> + : 32Bit_5R5R15Imm<0b101110, outs, ins, asmstr, pattern>; + +class SLTSIForm pattern> + : 32Bit_5R5R15Imm<0b101111, outs, ins, asmstr, pattern>; + + class JREGForm pattern> : 32BitInst<0b100101, outs, ins, asmstr, pattern>; Index: lib/Target/NDS32/NDS32InstrInfo.td =================================================================== --- lib/Target/NDS32/NDS32InstrInfo.td +++ lib/Target/NDS32/NDS32InstrInfo.td @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// include "NDS32InstrFormats.td" +include "NDS32Predicate.td" //===----------------------------------------------------------------------===// // Type Profiles. @@ -46,6 +47,137 @@ [(NDS32callseq_end timm:$amt1, timm:$amt2)]>; } + +//===----------------------------------------------------------------------===// +// 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; +} + + class JREG_ret pat, bits<2> dt_it> : JREGForm<(outs), (ins), opstr, pat> { let Inst{24-15} = 0; Index: lib/Target/NDS32/NDS32Predicate.td =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32Predicate.td @@ -0,0 +1,59 @@ +//===-- NDS32Predicate.td - NDS32 Predicate 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 Predicate defs in TableGen format. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Immediate Operand Predicates +// + +class ImmAsmOperand : AsmOperandClass { let RenderMethod = "addImmOperands"; } + +/// imm15s predicate - Immediate in the range [-(1 << 14) , (1 << 14)]. +def Imm15sAsmOperand: ImmAsmOperand { + let Name = "Imm15s"; + let DiagnosticType = "ImmRange15s"; +} +def imm15s : Operand, ImmLeaf= -(1 << 14) && Imm < (1 << 14); +}]> { +} + +/// imm20s predicate - Immediate in the range [-(1 << 19) , (1 << 19)]. +def Imm20sAsmOperand: ImmAsmOperand { + let Name = "Imm20s"; + let DiagnosticType = "ImmRange20s"; +} +def imm20s : Operand, ImmLeaf= -(1 << 19) && Imm < (1 << 19); +}]> { +} + + +/// imm5u predicate - Immediate in the range [0 , (1 << 5)]. +def Imm5uAsmOperand: ImmAsmOperand { + let Name = "Imm5u"; + let DiagnosticType = "ImmRange5u"; +} +def imm5u : Operand, ImmLeaf= 0 && Imm < (1 << 5); +}]> { +} + +/// imm15u predicate - Immediate in the range [0 , (1 << 15)]. +def Imm15uAsmOperand: ImmAsmOperand { + let Name = "Imm15u"; + let DiagnosticType = "ImmRange15u"; +} +def imm15u : Operand, ImmLeaf= 0 && Imm < (1 << 15); +}]> { +} Index: test/CodeGen/NDS32/alu-insns.ll =================================================================== --- /dev/null +++ test/CodeGen/NDS32/alu-insns.ll @@ -0,0 +1,224 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "e-m:e-p:32:32-i64:64-a:0:32-n32-S64" +target triple = "nds32le---elf" + +; Function Attrs: norecurse nounwind readnone +define i32 @add(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %add = add nsw i32 %b, %a +; CHECK: add $r0, $r1, $r0 + ret i32 %add +} + +; Function Attrs: norecurse nounwind readnone +define i32 @sub(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %sub = sub nsw i32 %a, %b +; CHECK: sub $r0, $r0, $r1 + ret i32 %sub +} + +; Function Attrs: norecurse nounwind readnone +define i32 @mul(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %mul = mul nsw i32 %b, %a +; CHECK: mul $r0, $r1, $r0 + ret i32 %mul +} + +; Function Attrs: norecurse nounwind readnone +define i32 @or(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %or = or i32 %b, %a +; CHECK: or $r0, $r1, $r0 + ret i32 %or +} + +; Function Attrs: norecurse nounwind readnone +define i32 @xor(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %xor = xor i32 %b, %a +; CHECK: xor $r0, $r1, $r0 + ret i32 %xor +} + +; Function Attrs: norecurse nounwind readnone +define i32 @sll(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %shl = shl i32 %a, %b +; CHECK: sll $r0, $r0, $r1 + ret i32 %shl +} + +; Function Attrs: norecurse nounwind readnone +define i32 @sra(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %shr = ashr i32 %a, %b +; CHECK: sra $r0, $r0, $r1 + ret i32 %shr +} + +; Function Attrs: norecurse nounwind readnone +define i32 @srl(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %shr = lshr i32 %a, %b +; CHECK: srl $r0, $r0, $r1 + ret i32 %shr +} + +; Function Attrs: norecurse nounwind readnone +define i32 @slts(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %cmp = icmp slt i32 %a, %b + %conv = zext i1 %cmp to i32 +; CHECK: slts $r0, $r0, $r1 + ret i32 %conv +} + +; Function Attrs: norecurse nounwind readnone +define i32 @slt(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %cmp = icmp ult i32 %a, %b + %conv = zext i1 %cmp to i32 +; CHECK: slt $r0, $r0, $r1 + ret i32 %conv +} + +; Function Attrs: norecurse nounwind readnone +define i32 @rotr(i32 %x, i32 %n) local_unnamed_addr #0 { +entry: + %shr = lshr i32 %x, %n + %sub = sub nsw i32 32, %n + %shl = shl i32 %x, %sub + %or = or i32 %shl, %shr +; CHECK: rotr $r0, $r0, $r1 + ret i32 %or +} + +; Function Attrs: norecurse nounwind readnone +define i32 @addi(i32 %a) local_unnamed_addr #0 { +entry: + %add = add i32 %a, 100 +; CHECK: addi $r0, $r0, 100 + ret i32 %add +} + +; Function Attrs: norecurse nounwind readnone +define i32 @subri(i32 %a) local_unnamed_addr #0 { +entry: + %sub = sub i32 100, %a +; CHECK: subri $r0, $r0, 100 + ret i32 %sub +} + +; Function Attrs: norecurse nounwind readnone +define i32 @slli(i32 %a) local_unnamed_addr #0 { +entry: + %shl = shl i32 %a, 10 +; CHECK: slli $r0, $r0, 10 + ret i32 %shl +} + +; Function Attrs: norecurse nounwind readnone +define i32 @srli(i32 %a) local_unnamed_addr #0 { +entry: + %shr = lshr i32 %a, 10 +; CHECK: srli $r0, $r0, 10 + ret i32 %shr +} + +; Function Attrs: norecurse nounwind readnone +define i32 @srai(i32 %a) local_unnamed_addr #0 { +entry: + %shr = ashr i32 %a, 10 +; CHECK: srai $r0, $r0, 10 + ret i32 %shr +} + +; Function Attrs: norecurse nounwind readnone +define i32 @rotri(i32 %x) local_unnamed_addr #0 { +entry: + %shr = lshr i32 %x, 10 + %shl = shl i32 %x, 22 + %or = or i32 %shr, %shl +; CHECK: rotri $r0, $r0, 10 + ret i32 %or +} + +; Function Attrs: norecurse nounwind readnone +define i32 @andi(i32 %a) local_unnamed_addr #0 { +entry: + %and = and i32 %a, 10 +; CHECK: andi $r0, $r0, 10 + ret i32 %and +} + +; Function Attrs: norecurse nounwind readnone +define i32 @maddr32(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %mul = mul nsw i32 %b, %a + %add = add nsw i32 %mul, %a +; CHECK: maddr32 $r0, $r1, $r0 + ret i32 %add +} + +; Function Attrs: norecurse nounwind readnone +define i32 @msubr32(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %mul = mul nsw i32 %b, %a + %sub = sub nsw i32 %a, %mul +; CHECK: msubr32 $r0, $r1, $r0 + ret i32 %sub +} + +; Function Attrs: norecurse nounwind readnone +define i32 @ori(i32 %a) local_unnamed_addr #0 { +entry: + %or = or i32 %a, 10 +; CHECK: ori $r0, $r0, 10 + ret i32 %or +} + +; Function Attrs: norecurse nounwind readnone +define i32 @xori(i32 %a) local_unnamed_addr #0 { +entry: + %xor = xor i32 %a, 10 +; CHECK: xori $r0, $r0, 10 + ret i32 %xor +} + +; Function Attrs: norecurse nounwind readnone +define i32 @sltsi(i32 %a) local_unnamed_addr #0 { +entry: + %cmp = icmp slt i32 %a, 10 + %conv = zext i1 %cmp to i32 +; CHECK: sltsi $r0, $r0, 10 + ret i32 %conv +} + +; Function Attrs: norecurse nounwind readnone +define i32 @slti(i32 %a) local_unnamed_addr #0 { +entry: + %cmp = icmp ult i32 %a, 10 + %conv = zext i1 %cmp to i32 +; CHECK: slti $r0, $r0, 10 + ret i32 %conv +} + +; Function Attrs: norecurse nounwind readnone +define i32 @nor(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %or = or i32 %b, %a + %neg = xor i32 %or, -1 +; CHECK: nor $r0, $r1, $r0 + ret i32 %neg +} + +; Function Attrs: norecurse nounwind readnone +define i32 @bitc(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %neg = xor i32 %b, -1 + %and = and i32 %neg, %a +; CHECK: bitc $r0, $r0, $r1 + ret i32 %and +} Index: test/CodeGen/NDS32/lit.local.cfg =================================================================== --- /dev/null +++ test/CodeGen/NDS32/lit.local.cfg @@ -0,0 +1,3 @@ +if not 'NDS32' in config.root.targets: + config.unsupported = True +