Index: lib/Target/NDS32/NDS32Instr16Bit.td =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32Instr16Bit.td @@ -0,0 +1,72 @@ +//===-- NDS32InstrInfo.td - NDS32 16 bit 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 16 bit instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Move Instructions +// + +def MOV55: MOV55Form<(outs GPR:$Rt), (ins GPR:$Ra), + "mov55\t$Rt, $Ra", []>, + Requires<[Has16Bit]>; + +let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in +def MOVI55 : MOVI55Form<(outs GPR:$Rt), (ins imm5s:$imm), + "movi55\t$Rt, $imm", + [(set GPR:$Rt, (imm5s:$imm))]>, + Requires<[Has16Bit]>; + + +//===----------------------------------------------------------------------===// +// Arithmetic Instructions +// + +let isAdd = 1 in +def ADD333 : ADD333Form<(outs lGPR:$Rt), (ins lGPR:$Ra, lGPR:$Rb), + "add333\t$Rt, $Ra, $Rb", + [(set lGPR:$Rt, (add lGPR:$Ra, lGPR:$Rb))]>, + Requires<[Has16Bit]>; + +let isAdd = 1 in +def ADDI333 : ADDI333Form<(outs lGPR:$Rt), (ins lGPR:$Ra, imm3u:$imm), + "addi333\t$Rt, $Ra, $imm", + [(set lGPR:$Rt, (add lGPR:$Ra, imm3u:$imm))]>, + Requires<[Has16Bit]>; + +def SUB333 : SUB333Form<(outs lGPR:$Rt), (ins lGPR:$Ra, lGPR:$Rb), + "sub333\t$Rt, $Ra, $Rb", + [(set lGPR:$Rt, (sub lGPR:$Ra, lGPR:$Rb))]>, + Requires<[Has16Bit]>; + +def SLLI333: SLLI333Form<(outs lGPR:$Rt), (ins lGPR:$Ra, imm3u:$imm), + "slli333\t$Rt, $Ra, $imm", + [(set lGPR:$Rt, (shl lGPR:$Ra, imm3u:$imm))]>, + Requires<[Has16Bit]>; + +class ALU33 subop_encode> : + MISC33Form<(outs lGPR:$Rt_wb), (ins lGPR:$Rt, lGPR:$Ra), + !strconcat(opstr, "\t$Rt, $Ra"), + [(set lGPR:$Rt_wb, (Op lGPR:$Rt, lGPR:$Ra))], + subop_encode>, + Requires<[Has16Bit]> { + let Constraints = "$Rt = $Rt_wb"; +} + +def AND33 : ALU33< "and33", and, 0b110>; +def MUL33 : ALU33< "mul33", mul, 0b100>; +def OR33 : ALU33< "or33" , or, 0b111>; +def XOR33 : ALU33< "xor33", xor, 0b101>; + +def NOT33 : MISC33Form<(outs lGPR:$Rt), (ins lGPR:$Ra), + "not33\t$Rt, $Ra", + [(set lGPR:$Rt, (not lGPR:$Ra))], 0b011>, + Requires<[Has16Bit]>; Index: lib/Target/NDS32/NDS32Instr16Formats.td =================================================================== --- /dev/null +++ lib/Target/NDS32/NDS32Instr16Formats.td @@ -0,0 +1,133 @@ +//===-- NDS32Instr16Formats.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 16 bit instructions format here +// + +class 16BitInst4BitOpcode opcode, + dag outs, dag ins, string asmstr, list pattern> + : NDS32Inst { + field bits<16> Inst; + let Size = 2; + let Pattern = pattern; + + let Inst{15} = 1; + let Inst{14-11} = opcode; +} + +class 16BitInst5BitOpcode opcode, + dag outs, dag ins, string asmstr, list pattern> + : NDS32Inst { + field bits<16> Inst; + let Size = 2; + let Pattern = pattern; + + let Inst{15} = 1; + let Inst{14-10} = opcode; +} + +class 16BitInst6BitOpcode opcode, + dag outs, dag ins, string asmstr, list pattern> + : NDS32Inst { + field bits<16> Inst; + let Size = 2; + let Pattern = pattern; + + let Inst{15} = 1; + let Inst{14-9} = opcode; +} + +class 16BitInst7BitOpcode opcode, + dag outs, dag ins, string asmstr, list pattern> + : NDS32Inst { + field bits<16> Inst; + let Size = 2; + let Pattern = pattern; + + let Inst{15} = 1; + let Inst{14-8} = opcode; +} + +class 16BitInst10BitOpcode opcode, + dag outs, dag ins, string asmstr, list pattern> + : NDS32Inst { + field bits<16> Inst; + let Size = 2; + let Pattern = pattern; + + let Inst{15} = 1; + let Inst{14-5} = opcode; +} + +class MOV55Form pattern> + : 16BitInst5BitOpcode<0b00000, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<5> Ra; + let Inst{9-5} = Rt; + let Inst{4-0} = Ra; +} + +class MOVI55Form pattern> + : 16BitInst5BitOpcode<0b00001, outs, ins, asmstr, pattern> { + bits<5> Rt; + bits<5> imm; + let Inst{9-5} = Rt; + let Inst{4-0} = imm; +} + +class ADD333Form pattern> + : 16BitInst6BitOpcode<0b001100, outs, ins, asmstr, pattern> { + bits<3> Rt; + bits<3> Ra; + bits<3> Rb; + let Inst{8-6} = Rt; + let Inst{5-3} = Ra; + let Inst{2-0} = Rb; +} + +class ADDI333Form pattern> + : 16BitInst6BitOpcode<0b001110, outs, ins, asmstr, pattern> { + bits<3> Rt; + bits<3> Ra; + bits<3> imm; + let Inst{8-6} = Rt; + let Inst{5-3} = Ra; + let Inst{2-0} = imm; +} + +class SLLI333Form pattern> + : 16BitInst6BitOpcode<0b001010, outs, ins, asmstr, pattern> { + bits<3> Rt; + bits<3> Ra; + bits<3> imm; + let Inst{8-6} = Rt; + let Inst{5-3} = Ra; + let Inst{2-0} = imm; +} + +class SUB333Form pattern> + : 16BitInst6BitOpcode<0b001101, outs, ins, asmstr, pattern> { + bits<3> Rt; + bits<3> Ra; + bits<3> Rb; + let Inst{8-6} = Rt; + let Inst{5-3} = Ra; + let Inst{2-0} = Rb; +} + +class MISC33Form pattern, + bits<3> subop_encode> + : 16BitInst6BitOpcode<0b111111, outs, ins, asmstr, pattern> { + bits<3> Rt; + bits<3> Ra; + let Inst{8-6} = Rt; + let Inst{5-3} = Ra; + let Inst{2-0} = subop_encode; +} Index: lib/Target/NDS32/NDS32InstrInfo.cpp =================================================================== --- lib/Target/NDS32/NDS32InstrInfo.cpp +++ lib/Target/NDS32/NDS32InstrInfo.cpp @@ -56,14 +56,24 @@ MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const { + MachineFunction &MF = *I->getParent()->getParent(); + const NDS32Subtarget &Subtarget = MF.getSubtarget(); unsigned Opc; + // Generate 32-bit ADDI when no-16bit is enabled if (NDS32::GPRRegClass.contains(DestReg, SrcReg)) { - Opc = NDS32::ADDI; + if (Subtarget.has16Bit()) + Opc = NDS32::MOV55; + else + Opc = NDS32::ADDI; } else llvm_unreachable("Impossible reg-to-reg copy"); - BuildMI(MBB, I, DL, get(Opc), DestReg) + if (Opc == NDS32::MOV55) + BuildMI(MBB, I, DL, get(Opc), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + else + BuildMI(MBB, I, DL, get(Opc), DestReg) .addReg(SrcReg, getKillRegState(KillSrc)).addImm(0); } Index: lib/Target/NDS32/NDS32InstrInfo.td =================================================================== --- lib/Target/NDS32/NDS32InstrInfo.td +++ lib/Target/NDS32/NDS32InstrInfo.td @@ -45,6 +45,14 @@ def NDS32udivrem : SDNode<"NDS32ISD::UDIVREM", SDTIntBinHiLoOp>; //===----------------------------------------------------------------------===// +// 16 bit Instructions +// + +include "NDS32Instr16Formats.td" +include "NDS32Instr16Bit.td" + + +//===----------------------------------------------------------------------===// // 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. Index: lib/Target/NDS32/NDS32Predicate.td =================================================================== --- lib/Target/NDS32/NDS32Predicate.td +++ lib/Target/NDS32/NDS32Predicate.td @@ -12,6 +12,13 @@ //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// +// NDS32 Instruction Predicate Definitions. +// + +def Has16Bit : Predicate<"Subtarget->has16Bit()">; + + +//===----------------------------------------------------------------------===// // Immediate Operand Predicates // @@ -27,6 +34,16 @@ class ImmAsmOperand : AsmOperandClass { let RenderMethod = "addImmOperands"; } +/// imm5s predicate - Immediate in the range [-(1 << 4) , (1 << 4)]. +def Imm5sAsmOperand: ImmAsmOperand { + let Name = "Imm5s"; + let DiagnosticType = "ImmRange5s"; +} +def imm5s : Operand, ImmLeaf= -(1 << 4) && Imm < (1 << 4); +}]> { +} + /// imm11s predicate - Immediate in the range [-(1 << 10) , (1 << 10)]. def Imm11sAsmOperand: ImmAsmOperand { let Name = "Imm11s"; @@ -57,6 +74,15 @@ }]> { } +/// imm3u predicate - Immediate in the range [0 , (1 << 3)]. +def Imm3uAsmOperand: ImmAsmOperand { + let Name = "Imm3u"; + let DiagnosticType = "ImmRange3u"; +} +def imm3u : Operand, ImmLeaf= 0 && Imm < (1 << 3); +}]> { +} /// imm5u predicate - Immediate in the range [0 , (1 << 5)]. def Imm5uAsmOperand: ImmAsmOperand { Index: test/CodeGen/NDS32/16-bit-alu.ll =================================================================== --- /dev/null +++ test/CodeGen/NDS32/16-bit-alu.ll @@ -0,0 +1,89 @@ +; 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 @mov55(i32 %a, i32 returned %b) local_unnamed_addr #0 { +entry: + ret i32 %b +; CHECK: mov55 $r0, $r1 +} + +; Function Attrs: norecurse nounwind readnone +define i32 @movi55() local_unnamed_addr #0 { +entry: + ret i32 2 +; CHECK: movi55 $r0, 2 +} + +; Function Attrs: norecurse nounwind readnone +define i32 @add333(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %add = add nsw i32 %b, %a +; CHECK: add333 $r0, $r1, $r0 + ret i32 %add +} + +; Function Attrs: norecurse nounwind readnone +define i32 @addi333(i32 %a) local_unnamed_addr #0 { +entry: + %add = add nsw i32 %a, 2 +; CHECK: addi333 $r0, $r0, 2 + ret i32 %add +} + +; Function Attrs: norecurse nounwind readnone +define i32 @sub333(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %sub = sub nsw i32 %a, %b +; CHECK: sub333 $r0, $r0, $r1 + ret i32 %sub +} + +; Function Attrs: norecurse nounwind readnone +define i32 @slli333(i32 %a) local_unnamed_addr #0 { +entry: + %shl = shl i32 %a, 4 +; CHECK: slli333 $r0, $r0, 4 + ret i32 %shl +} + +; Function Attrs: norecurse nounwind readnone +define i32 @and33(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %and = and i32 %b, %a +; CHECK: and33 $r1, $r0 + ret i32 %and +} + +; Function Attrs: norecurse nounwind readnone +define i32 @mul33(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %mul = mul nsw i32 %b, %a +; CHECK: mul33 $r1, $r0 + ret i32 %mul +} + +; Function Attrs: norecurse nounwind readnone +define i32 @or33(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %or = or i32 %b, %a +; CHECK: or33 $r1, $r0 + ret i32 %or +} + +; Function Attrs: norecurse nounwind readnone +define i32 @xor33(i32 %a, i32 %b) local_unnamed_addr #0 { +entry: + %xor = xor i32 %b, %a +; CHECK: xor33 $r1, $r0 + ret i32 %xor +} + +; Function Attrs: norecurse nounwind readnone +define i32 @not33(i32 %a) local_unnamed_addr #0 { +entry: + %neg = xor i32 %a, -1 +; CHECK: not33 $r0, $r0 + ret i32 %neg +} Index: test/CodeGen/NDS32/alu-insns.ll =================================================================== --- test/CodeGen/NDS32/alu-insns.ll +++ test/CodeGen/NDS32/alu-insns.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s | FileCheck %s +; RUN: llc -mattr=+no-16bit < %s | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-a:0:32-n32-S64" target triple = "nds32le---elf" Index: test/CodeGen/NDS32/post-inc.ll =================================================================== --- test/CodeGen/NDS32/post-inc.ll +++ test/CodeGen/NDS32/post-inc.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s | FileCheck %s +; RUN: llc -mattr=+no-16bit < %s | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-a:0:32-n32-S64" target triple = "nds32le---elf"