diff --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp --- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp +++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp @@ -755,6 +755,10 @@ SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); return Error(ErrorLoc, "register is out of range"); } + case Match_InvalidSPOperand: { + SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); + return Error(ErrorLoc, "operand must be sp register"); + } case Match_RequiresSameSrcAndDst: { SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); return Error(ErrorLoc, "src and dst operand must be same"); diff --git a/llvm/lib/Target/CSKY/CSKY.td b/llvm/lib/Target/CSKY/CSKY.td --- a/llvm/lib/Target/CSKY/CSKY.td +++ b/llvm/lib/Target/CSKY/CSKY.td @@ -12,6 +12,12 @@ // CSKY subtarget features and instruction predicates. //===----------------------------------------------------------------------===// +def FeatureBTST16 : SubtargetFeature<"btst16", "HasBTST16", "true", + "Use the 16-bit btsti instruction">; +def HasBTST16 : Predicate<"Subtarget->hasBTST16()">, + AssemblerPredicate<(all_of FeatureBTST16), + "Use the 16-bit btsti instruction">; + // Atomic Support def FeatureExtendLrw : SubtargetFeature<"elrw", "HasExtendLrw", "true", "Use the extend LRW instruction">; @@ -19,6 +25,12 @@ AssemblerPredicate<(all_of FeatureExtendLrw), "Use the extend LRW instruction">; +def FeatureJAVA + : SubtargetFeature<"java", "HasJAVA", "true", "Enable java instructions">; +def HasJAVA : Predicate<"Subtarget->hasJAVA()">, + AssemblerPredicate<(all_of FeatureJAVA), + "Enable java instructions">; + def FeatureDoloop : SubtargetFeature<"doloop", "HasDoloop", "true", "Enable doloop instructions">; def HasDoloop : Predicate<"Subtarget->hasDoloop()">, diff --git a/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td @@ -0,0 +1,219 @@ +//===- CSKYInstrFormats16Instr.td - 16-bit Instr. Formats -*- tablegen --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +class J16 sop, string opstr, dag ins> + : CSKY16Inst { + bits<10> offset; + let Inst{15} = 0; + let Inst{14 - 10} = sop; + let Inst{9 - 0} = offset; +} + +class J16_B sop, string opstr> + : CSKY16Inst { + bits<10> offset; + let Inst{15} = 0; + let Inst{14 - 10} = sop; + let Inst{9 - 0} = offset; +} + +class R16_XYZ sop, string opstr, SDNode opnode> : CSKY16Inst { + bits<3> rz; + bits<3> rx; + bits<3> ry; + let Inst{15 - 11} = 0b01011; + let Inst{10 - 8} = rx; + let Inst{7 - 5} = rz; + let Inst{4 - 2} = ry; + let Inst{1, 0} = sop; +} + +class R16_XZ_BINOP op, bits<2> sop, string opstr, PatFrag opnode> : CSKY16Inst< + AddrModeNone, (outs sGPR:$rz), (ins sGPR:$rZ, sGPR:$rx), !strconcat(opstr, "\t$rz, $rx"), + [(set sGPR:$rz, (opnode sGPR:$rZ, sGPR:$rx))]> { + bits<4> rz; + bits<4> rx; + let Inst{15, 14} = 0b01; + let Inst{13 - 10} = op; + let Inst{9 - 6} = rz; + let Inst{5 - 2} = rx; + let Inst{1, 0} = sop; + let Constraints = "$rz = $rZ"; +} + +class R16_XZ_BINOP_NOPat op, bits<2> sop, string opstr> : CSKY16Inst< + AddrModeNone, (outs sGPR:$rz), (ins sGPR:$rZ, sGPR:$rx), !strconcat(opstr, "\t$rz, $rx"), + []> { + bits<4> rz; + bits<4> rx; + let Inst{15, 14} = 0b01; + let Inst{13 - 10} = op; + let Inst{9 - 6} = rz; + let Inst{5 - 2} = rx; + let Inst{1, 0} = sop; + let Constraints = "$rz = $rZ"; +} + +class R16_XZ_BINOP_C op, bits<2> sop, string opstr> : CSKY16Inst< + AddrModeNone, (outs sGPR:$rz, CARRY:$cout), + (ins sGPR:$rZ, sGPR:$rx, CARRY:$cin), !strconcat(opstr, "\t$rz, $rx"), []> { + bits<4> rz; + bits<4> rx; + let Inst{15, 14} = 0b01; + let Inst{13 - 10} = op; + let Inst{9 - 6} = rz; + let Inst{5 - 2} = rx; + let Inst{1, 0} = sop; + let Constraints = "$rz = $rZ"; +} + +class R16_XZ_UNOP op, bits<2> sop, string opstr> : CSKY16Inst< + AddrModeNone, (outs sGPR:$rz), (ins sGPR:$rx), !strconcat(opstr, "\t$rz, $rx"), + []> { + bits<4> rz; + bits<4> rx; + let Inst{15, 14} = 0b01; + let Inst{13 - 10} = op; + let Inst{9 - 6} = rz; + let Inst{5 - 2} = rx; + let Inst{1, 0} = sop; +} + +class R16_XY_CMP sop, string opstr> : CSKY16Inst< + AddrModeNone, (outs CARRY:$ca), (ins sGPR:$rx, sGPR:$ry), !strconcat(opstr, "\t$rx, $ry"), + []> { + bits<4> ry; + bits<4> rx; + let Inst{15, 14} = 0b01; + let Inst{13 - 10} = 0b1001; + let Inst{9 - 6} = ry; + let Inst{5 - 2} = rx; + let Inst{1, 0} = sop; + let isCompare = 1; +} + +class R16_X_J op_rz, bits<2> sop, string opstr> : CSKY16Inst< + AddrModeNone, (outs), (ins sGPR:$rx), !strconcat(opstr, "\t$rx"), []> { + bits<4> rx; + let Inst{15, 14} = 0b01; + let Inst{13 - 6} = op_rz; + let Inst{5 - 2} = rx; + let Inst{1, 0} = sop; +} + +class I16_Z_8 op, dag ins, string asmstr> + : CSKY16Inst { + bits<3> rz; + bits<8> imm8; + let Inst{15, 14} = 0b00; + let Inst{13 - 11} = op; + let Inst{10 - 8} = rz; + let Inst{7 - 0} = imm8; +} + +class I16_Z_5 sop, dag outs, dag ins,string opstr> + : CSKY16Inst { + bits<3> rz; + bits<5> imm5; + let Inst{15, 14} = 0b00; + let Inst{13 - 11} = 0b111; + let Inst{10 - 8} = rz; + let Inst{7 - 5} = sop; + let Inst{4 - 0} = imm5; +} + +class I16_X_CMP sop, string opstr, Operand Immoperand> : CSKY16Inst< + AddrModeNone, (outs CARRY:$ca), (ins mGPR:$rx, Immoperand:$imm5), + !strconcat(opstr, "\t$rx, $imm5"), []> { + bits<3> rx; + bits<5> imm5; + let Inst{15, 14} = 0b00; + let Inst{13 - 11} = 0b111; + let Inst{10 - 8} = rx; + let Inst{7 - 5} = sop; + let Inst{4 - 0} = imm5; + let isCompare = 1; +} + +class I16_SP_IMM7 sop, string opstr> : CSKY16Inst< + AddrModeNone, (outs SPOp:$sp2), (ins SPOp:$sp1, uimm7_2:$imm7), + !strconcat(opstr, "\t$sp2, $sp1, $imm7"), []> { + bits<7> imm7; + let Inst{15, 14} = 0b00; + let Inst{13 - 10} = 0b0101; + let Inst{9, 8} = imm7{6,5}; + let Inst{7 - 5} = sop; + let Inst{4 - 0} = imm7{4 - 0}; +} + +class I16_XZ_IMM5 sop, string opstr, SDNode opnode> : CSKY16Inst< + AddrModeNone, (outs mGPR:$rz), (ins mGPR:$rx, uimm5:$imm5), + !strconcat(opstr, "\t$rz, $rx, $imm5"), [(set mGPR:$rz, (opnode mGPR:$rx, uimm5:$imm5))]> { + bits<3> rx; + bits<3> rz; + bits<5> imm5; + let Inst{15, 14} = 0b01; + let Inst{13 - 11} = sop; + let Inst{10 - 8} = rx; + let Inst{7 - 5} = rz; + let Inst{4 - 0} = imm5; +} + +class I16_XZ_LDST sop, string opstr, dag outs, dag ins> + : CSKY16Inst { + bits<3> rx; + bits<3> rz; + bits<5> imm; + let Inst{15, 14} = 0b10; + let Inst{13 - 11} = sop; + let Inst{10 - 8} = rx; + let Inst{7 - 5} = rz; + let Inst{4 - 0} = imm; +} + +class I16_ZSP_LDST sop, string opstr, dag outs, dag ins> : CSKY16Inst< + am, outs, ins, !strconcat(opstr, "\t$rz, ($sp, ${addr})"), + []> { + bits<3> rz; + bits<8> addr; + let Inst{15, 14} = 0b10; + let Inst{13 - 11} = sop; + let Inst{10 - 8} = addr{7 - 5}; + let Inst{7 - 5} = rz; + let Inst{4 - 0} = addr{4 - 0}; +} + +class I16_XZ_IMM3 sop, string opstr, SDNode opnode> : CSKY16Inst< + AddrModeNone, (outs mGPR:$rz), (ins mGPR:$rx, oimm3:$oimm3), + !strconcat(opstr, "\t$rz, $rx, $oimm3"), [(set mGPR:$rz, (opnode mGPR:$rx, oimm3:$oimm3))]> { + bits<3> rx; + bits<3> rz; + bits<3> oimm3; + let Inst{15, 14} = 0b01; + let Inst{13 - 11} = 0b011; + let Inst{10 - 8} = rx; + let Inst{7 - 5} = rz; + let Inst{4 - 2} = oimm3; + let Inst{1, 0} = sop; +} + +class I16_BPushPop op, bits<2> uop, dag out, dag ins, string opstr> : + CSKY16Inst{ + bits<3> rz; + let Inst{15- 5} = op; + let Inst{4 -2} = rz; + let Inst{1,0} = uop; + let Predicates = [HasJAVA]; + let hasSideEffects = 1; +} diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td --- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td +++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td @@ -947,3 +947,5 @@ let hasSideEffects = 0, isNotDuplicable = 1 in def CONSTPOOL_ENTRY : CSKYPseudo<(outs), (ins i32imm:$instid, i32imm:$cpidx, i32imm:$size), "", []>; + +include "CSKYInstrInfo16Instr.td" diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td @@ -0,0 +1,452 @@ +//===-- CSKYInstrInfo16Instr.td - CSKY 16-bit Instruction --*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes the CSKY 16-bit instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// CSKY specific DAG Nodes. +//===----------------------------------------------------------------------===// + +// Target-dependent nodes. +def CSKY_NIE : SDNode<"CSKYISD::NIE", SDTNone, + [SDNPHasChain, SDNPOptInGlue]>; +def CSKY_NIR : SDNode<"CSKYISD::NIR", SDTNone, + [SDNPHasChain, SDNPOptInGlue]>; + +//===----------------------------------------------------------------------===// +// Operand and SDNode transformation definitions. +//===----------------------------------------------------------------------===// + +def br_symbol_16bit : Operand { + let EncoderMethod = + "getBranchSymbolOpValue"; + let ParserMatchClass = CSKYSymbol; + let DecoderMethod = "decodeSImmOperand<10, 1>"; + let PrintMethod = "printCSKYSymbolOperand"; + let OperandType = "OPERAND_PCREL"; +} + +def SPOperand : AsmOperandClass { + let Name = "SPOperand"; + let RenderMethod = "addRegOperands"; + let DiagnosticType = !strconcat("Invalid", Name); +} + +def SPOp : RegisterOperand { + let ParserMatchClass = SPOperand; +} + +def constpool_symbol_16bit : Operand { + let ParserMatchClass = Constpool; + let EncoderMethod = + "getConstpoolSymbolOpValue"; + let DecoderMethod = "decodeLRW16Imm8"; + let PrintMethod = "printConstpool"; + let OperandType = "OPERAND_PCREL"; +} + +//===----------------------------------------------------------------------===// +// Instruction Formats +//===----------------------------------------------------------------------===// + +include "CSKYInstrFormats16Instr.td" + +//===----------------------------------------------------------------------===// +// Instruction definitions. +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Basic ALU instructions. +//===----------------------------------------------------------------------===// + +let isCommutable = 1, isAdd = 1 in + def ADDU16 : R16_XYZ<0, "addu16", add>; +let Pattern = [(set mGPR:$rz, (sub mGPR:$rx, mGPR:$ry))] in + def SUBU16 : R16_XYZ<1, "subu16", sub>; + +let isCommutable = 1, isAdd = 1 in + def ADDC16 : R16_XZ_BINOP_C<0b1000, 0b01, "addc16">; +def SUBC16 : R16_XZ_BINOP_C<0b1000, 0b11, "subc16">; + +let isCommutable = 1 in { + let isAdd = 1 in + def ADDU16XZ : R16_XZ_BINOP<0b1000, 0b00, "addu16", BinOpFrag<(add node:$LHS, node:$RHS)>>; + def AND16 : R16_XZ_BINOP<0b1010, 0b00, "and16", BinOpFrag<(and node:$LHS, node:$RHS)>>; + def OR16 : R16_XZ_BINOP<0b1011, 0b00, "or16", BinOpFrag<(or node:$LHS, node:$RHS)>>; + def XOR16 : R16_XZ_BINOP<0b1011, 0b01, "xor16", BinOpFrag<(xor node:$LHS, node:$RHS)>>; + def NOR16 : R16_XZ_BINOP<0b1011, 0b10, "nor16", BinOpFrag<(not (or node:$LHS, node:$RHS))>>; + let isCodeGenOnly = 1 in + def NOT16 : R16_XZ_UNOP<0b1011, 0b10, "not16">; + def MULT16 : R16_XZ_BINOP<0b1111, 0b00, "mult16", BinOpFrag<(mul node:$LHS, node:$RHS)>>; +} +def SUBU16XZ : R16_XZ_BINOP<0b1000, 0b10, "subu16", BinOpFrag<(sub node:$LHS, node:$RHS)>>; +def ANDN16 : R16_XZ_BINOP<0b1010, 0b01, "andn16", BinOpFrag<(and node:$LHS, (not node:$RHS))>>; +def LSL16 : R16_XZ_BINOP<0b1100, 0b00, "lsl16", BinOpFrag<(shl node:$LHS, node:$RHS)>>; +def LSR16 : R16_XZ_BINOP<0b1100, 0b01, "lsr16", BinOpFrag<(srl node:$LHS, node:$RHS)>>; +def ASR16 : R16_XZ_BINOP<0b1100, 0b10, "asr16", BinOpFrag<(sra node:$LHS, node:$RHS)>>; +def ROTL16 : R16_XZ_BINOP<0b1100, 0b11, "rotl16", BinOpFrag<(rotl node:$LHS, (and node:$RHS, 0x1f))>>; + +def MULSH16 : R16_XZ_BINOP_NOPat<0b1111, 0b01, "mulsh16">; + +def ZEXTB16 : R16_XZ_UNOP<0b1101, 0b00, "zextb16">; +def ZEXTH16 : R16_XZ_UNOP<0b1101, 0b01, "zexth16">; +def SEXTB16 : R16_XZ_UNOP<0b1101, 0b10, "sextb16">; +def SEXTH16 : R16_XZ_UNOP<0b1101, 0b11, "sexth16">; + +let Constraints = "$rZ = $rz", isReMaterializable = 1, isAsCheapAsAMove = 1 in { + let isAdd = 1, Pattern = [(set mGPR:$rz, (add mGPR:$rZ, oimm8:$imm8))] in + def ADDI16 : I16_Z_8<0b100, (ins mGPR:$rZ, oimm8:$imm8), "addi16\t$rz, $imm8">; + let Pattern = [(set mGPR:$rz, (sub mGPR:$rZ, oimm8:$imm8))] in + def SUBI16 : I16_Z_8<0b101, (ins mGPR:$rZ, oimm8:$imm8), "subi16\t$rz, $imm8">; +} + +let isAdd = 1 in +def ADDI16ZSP : I16_Z_8<0b011, (ins SPOp:$sp, uimm8_2:$imm8), + "addi16\t$rz, $sp, $imm8">; + +let isAdd = 1 in +def ADDI16SPSP : I16_SP_IMM7<0b000,"addi16">; +def SUBI16SPSP : I16_SP_IMM7<0b001,"subi16">; + +let isReMaterializable = 1, isAsCheapAsAMove = 1 in { + def LSLI16 : I16_XZ_IMM5<0, "lsli16", shl>; + def LSRI16 : I16_XZ_IMM5<1, "lsri16", srl>; + def ASRI16 : I16_XZ_IMM5<2, "asri16", sra>; +} + +let isAdd = 1 in +def ADDI16XZ : I16_XZ_IMM3<0b10, "addi16", add>; +def SUBI16XZ : I16_XZ_IMM3<0b11, "subi16", sub>; + +let Size = 4 in +def NEG16 : CSKYPseudo<(outs mGPR:$rd), (ins mGPR:$rx), "neg16 $rd, $rx", []>; + +let Size = 4 in +def RSUBI16 : CSKYPseudo<(outs mGPR:$rd), + (ins mGPR:$rx, uimm8:$imm8), "rsubi16 $rd, $rx, $imm8", []>; + +//===----------------------------------------------------------------------===// +// Load & Store instructions. +//===----------------------------------------------------------------------===// + +def LD16B : I16_XZ_LDST; +def LD16H : I16_XZ_LDST; +def LD16W : I16_XZ_LDST; +def ST16B : I16_XZ_LDST; +def ST16H : I16_XZ_LDST; +def ST16W : I16_XZ_LDST; + +def LD16WSP : I16_ZSP_LDST; +def ST16WSP : I16_ZSP_LDST; + +//===----------------------------------------------------------------------===// +// Compare instructions. +//===----------------------------------------------------------------------===// + +def CMPHS16 : R16_XY_CMP<0, "cmphs16">; +def CMPLT16 : R16_XY_CMP<1, "cmplt16">; +let isCommutable = 1 in +def CMPNE16 : R16_XY_CMP<2, "cmpne16">; + + +def CMPHSI16 : I16_X_CMP<0, "cmphsi16", oimm5>; +def CMPLTI16 : I16_X_CMP<1, "cmplti16", oimm5>; +def CMPLEI16 : CSKYPseudo<(outs CARRY:$ca), (ins mGPR:$rx, uimm5:$imm5), + "cmplei16\t$rx, $imm5", []>; +def CMPNEI16 : I16_X_CMP<2, "cmpnei16", uimm5>; + +//===----------------------------------------------------------------------===// +// Data move instructions. +//===----------------------------------------------------------------------===// + + +def MOVI16 : I16_Z_8<0b110, (ins uimm8:$imm8), "movi16\t$rz, $imm8"> { + let isReMaterializable = 1; + let isAsCheapAsAMove = 1; + let isMoveImm = 1; + let Pattern = [(set mGPR:$rz, uimm8:$imm8)]; +} + +def MOV16 : CSKY16Inst { + bits<4> rz; + bits<4> rx; + let Inst{15,14} = 0b01; + let Inst{13 - 10} = 0b1011; + let Inst{9 - 6} = rz; + let Inst{5 - 2} = rx; + let Inst{1,0} = 0b11; +} + +// MVC16 is not in "cskyv2 instructions reference manul" +def MVCV16 : CSKY16Inst { + bits<4> rz; + let Inst{15,14} = 0b01; + let Inst{13 - 10} = 0b1001; + let Inst{9 - 6} = rz; + let Inst{5 - 2} = 0; + let Inst{1,0} = 0b11; +} + + +//===----------------------------------------------------------------------===// +// Branch and call instructions. +//===----------------------------------------------------------------------===// + +let isBranch = 1, isTerminator = 1 in { + let isBarrier = 1, isPredicable = 1 in + def BR16 : J16<1, "br16", (ins br_symbol_16bit:$offset)>; + + def BT16 : J16_B<2, "bt16">; + def BF16 : J16_B<3, "bf16">; +} + +def JMP16 : R16_X_J<0b11100000, 0b00, "jmp16"> { + let isBranch = 1; + let isTerminator = 1; + let isBarrier = 1; + let isIndirectBranch = 1; + let Pattern = [(brind sGPR:$rx)]; +} + +def JSR16 : R16_X_J<0b11101111, 0b01, "jsr16"> { + let isCall = 1; + let Defs = [ R15 ]; +} + +def RTS16 : CSKY16Inst { + let isTerminator = 1; + let isReturn = 1; + let isBarrier = 1; + let Inst = 0b0111100000111100; + let Uses = [R15]; + let isCodeGenOnly = 1; +} + +def JMPIX16 : CSKY16Inst { + bits<3> rx; + bits<2> indeximm2; + let Inst{15,14} = 0b00; + let Inst{13 - 11} = 0b111; + let Inst{10 - 8} = rx; + let Inst{7 - 2} = 0b111000; + let Inst{1,0} = indeximm2; + let Predicates = [HasJAVA]; + let Uses = [R30]; +} + +//===----------------------------------------------------------------------===// +// Symbol address instructions. +//===----------------------------------------------------------------------===// + +def LRW16 : CSKY16Inst { + bits<3> rz; + bits<8> label; + let Inst{15 - 13} = 0b000; + let Inst{12} = label{7}; + let Inst{11,10} = 0b00; + let Inst{9,8} = label{6,5}; + let Inst{7 - 5} = rz; + let Inst{4 - 0} = label{4-0}; + let mayLoad = 1; + let mayStore = 0; +} + +def LRW16_Gen : CSKY16Inst { + bits<3> rz; + bits<8> label; + let Inst{15 - 13} = 0b000; + let Inst{12} = label{7}; + let Inst{11,10} = 0b00; + let Inst{9,8} = label{6,5}; + let Inst{7 - 5} = rz; + let Inst{4 - 0} = label{4-0}; + let mayLoad = 1; + let mayStore = 0; + let isCodeGenOnly = 1; +} + + +//===----------------------------------------------------------------------===// +// Other operation instructions. +//===----------------------------------------------------------------------===// + +def REVB16 : R16_XZ_UNOP<0b1110, 0b10, "revb16">; +def REVH16 : R16_XZ_UNOP<0b1110, 0b11, "revh16">; + +let isCodeGenOnly = 1 in +def SETC16 : CSKY16Inst { + let Inst{15, 14} = 0b01; + let Inst{13 - 10} = 0b1001; + let Inst{9 - 6} = 0; + let Inst{5 - 2} = 0; + let Inst{1, 0} = 0; + let isCompare = 1; +} + +let isCodeGenOnly = 1 in +def CLRC16 : CSKY16Inst { + let Inst{15, 14} = 0b01; + let Inst{13 - 10} = 0b1001; + let Inst{9 - 6} = 0; + let Inst{5 - 2} = 0; + let Inst{1, 0} = 2; + let isCompare = 1; +} + +let Constraints = "$rZ = $rz" in { + def BCLRI16 : I16_Z_5<0b100, (outs mGPR:$rz), (ins mGPR:$rZ, uimm5:$imm5), + "bclri16">; + def BSETI16 : I16_Z_5<0b101, (outs mGPR:$rz), (ins mGPR:$rZ, uimm5:$imm5), + "bseti16">; +} + +let Predicates = [HasBTST16] in + def BTSTI16 : I16_Z_5<0b110, (outs CARRY:$ca), (ins mGPR:$rz, uimm5:$imm5), + "btsti16">; + +def TST16 : CSKY16Inst { + bits<4> ry; + bits<4> rx; + let Inst{15,14} = 0b01; + let Inst{13 - 10} = 0b1010; + let Inst{9 - 6} = ry; + let Inst{5 - 2} = rx; + let Inst{1,0} = 0b10; + let isCompare = 1; +} + +def TSTNBZ16 : CSKY16Inst { + bits<4> rx; + let Inst{15,14} = 0b01; + let Inst{13 - 10} = 0b1010; + let Inst{9 - 6} = 0b0000; + let Inst{5 - 2} = rx; + let Inst{1,0} = 0b11; + let isCompare = 1; +} + +//===----------------------------------------------------------------------===// +// Special instructions. +//===----------------------------------------------------------------------===// + +def BKPT : CSKY16Inst { + let Inst = 0; +} + +let mayStore = 1 in { +def BPUSHH : I16_BPushPop<0b00010100111, 0, (outs), (ins mGPR:$rz), "bpush.h $rz">; +def BPUSHW : I16_BPushPop<0b00010100111, 0b10, (outs), (ins mGPR:$rz), "bpush.w $rz">; +} + +let mayLoad = 1 in { +def BPOPH : I16_BPushPop<0b00010100101, 0, (outs mGPR:$rz), (ins), "bpop.h $rz">; +def BPOPW : I16_BPushPop<0b00010100101, 0b10, (outs mGPR:$rz), (ins), "bpop.w $rz">; +} + +def NIE : CSKY16Inst { + let Inst = 0b0001010001100000; +} + +let isBarrier = 1, isReturn = 1, isTerminator = 1 in +def NIR : CSKY16Inst { + let Inst = 0b0001010001100001; +} + +def IPUSH16 : CSKY16Inst { + let Inst{15- 5} = 0b00010100011; + let Inst{4-0} = 0b00010; + let Predicates = [iHasE1]; + let Defs = [R14]; + let Uses = [R14, R0, R1, R2, R3, R12, R13]; + let mayStore = 1; +} + +def IPOP16 : CSKY16Inst { + let Inst{15- 5} = 0b00010100011; + let Inst{4-0} = 0b00011; + let Predicates = [iHasE1]; + let Defs = [R14, R0, R1, R2, R3, R12, R13]; + let Uses = [R14]; + let mayLoad = 1; +} + +def PUSH16 : CSKY16Inst { + bits<5> regs; + + let Inst{15- 5} = 0b00010100110; + let Inst{4-0} = regs; + let Predicates = [iHasE1]; + let Defs = [R14]; + let Uses = [R14]; + let mayStore = 1; +} + +def POP16 : CSKY16Inst { + bits<5> regs; + + let Inst{15- 5} = 0b00010100100; + let Inst{4-0} = regs; + let Predicates = [iHasE1]; + let Defs = [R14]; + let Uses = [R14]; + let mayLoad = 1; +} + +//===----------------------------------------------------------------------===// +// CSKYPseudo +//===----------------------------------------------------------------------===// + +let usesCustomInserter = 1 in { + def ISEL16 : CSKYPseudo<(outs sGPR:$dst), + (ins CARRY:$cond, sGPR:$src1, sGPR:$src2), + "!isel16\t$dst, $src1, src2", + [(set sGPR:$dst, (select CARRY:$cond, sGPR:$src1, sGPR:$src2))]>; +} + +class JBranchPseudo : + CSKYPseudo { + let isBranch = 1; + let isTerminator = 1; + let isIndirectBranch = 1; + let mayLoad = 1; + let Size = 2; +} + +let isBarrier = 1 in +def JBR16 : JBranchPseudo<(outs), + (ins br_symbol_16bit:$src1), "jbr16\t$src1">; +def JBT16 : JBranchPseudo<(outs), + (ins CARRY:$ca, br_symbol_16bit:$src1), "jbt16\t$src1">; +def JBF16 : JBranchPseudo<(outs), + (ins CARRY:$ca, br_symbol_16bit:$src1), "jbf16\t$src1">; + +let mayLoad = 1, Size = 2, isCodeGenOnly = 0 in +def PseudoLRW16 : CSKYPseudo<(outs mGPR:$rz), + (ins bare_symbol:$src), "lrw16 $rz, $src", []>; diff --git a/llvm/lib/Target/CSKY/CSKYRegisterInfo.td b/llvm/lib/Target/CSKY/CSKYRegisterInfo.td --- a/llvm/lib/Target/CSKY/CSKYRegisterInfo.td +++ b/llvm/lib/Target/CSKY/CSKYRegisterInfo.td @@ -153,6 +153,21 @@ let Size = 32; } +// Register class for R0 - R15. +// Some 16-bit integer instructions can only access R0 - R15. +def sGPR : RegisterClass<"CSKY", [i32], 32, + (add (sequence "R%u", 0, 3), (sequence "R%u", 12, 13), R15, + (sequence "R%u", 4, 11), R14)> { + let Size = 32; +} + +// Register class for R0 - R7. +// Some 16-bit integer instructions can only access R0 - R7. +def mGPR : RegisterClass<"CSKY", [i32], 32, + (add (sequence "R%u", 0, 7))> { + let Size = 32; +} + def GPRPair : RegisterClass<"CSKY", [untyped], 32, (add GPRTuple)> { let Size = 64; } diff --git a/llvm/lib/Target/CSKY/CSKYSubtarget.h b/llvm/lib/Target/CSKY/CSKYSubtarget.h --- a/llvm/lib/Target/CSKY/CSKYSubtarget.h +++ b/llvm/lib/Target/CSKY/CSKYSubtarget.h @@ -43,6 +43,8 @@ bool HasFPUv3SingleFloat; bool HasFPUv3DoubleFloat; + bool HasBTST16; + bool HasJAVA; bool HasExtendLrw; bool HasDoloop; bool HasHighRegisters; @@ -95,6 +97,8 @@ bool hasFPUv3() const { return HasFPUv3SingleFloat || HasFPUv3DoubleFloat; } bool hasAnyFloatExt() const { return hasFPUv2() || hasFPUv3(); }; + bool hasBTST16() const { return HasBTST16; } + bool hasJAVA() const { return HasJAVA; } bool hasExtendLrw() const { return HasExtendLrw; } bool hasDoloop() const { return HasDoloop; } bool hasHighRegisters() const { return HasHighRegisters; } diff --git a/llvm/lib/Target/CSKY/CSKYSubtarget.cpp b/llvm/lib/Target/CSKY/CSKYSubtarget.cpp --- a/llvm/lib/Target/CSKY/CSKYSubtarget.cpp +++ b/llvm/lib/Target/CSKY/CSKYSubtarget.cpp @@ -36,6 +36,8 @@ HasFPUv3SingleFloat = false; HasFPUv3DoubleFloat = false; + HasBTST16 = false; + HasJAVA = false; HasExtendLrw = false; HasDoloop = false; HasHighRegisters = false; @@ -70,4 +72,3 @@ else return FloatABI == FloatABI::Hard; } - diff --git a/llvm/lib/Target/CSKY/CSKYTargetMachine.h b/llvm/lib/Target/CSKY/CSKYTargetMachine.h --- a/llvm/lib/Target/CSKY/CSKYTargetMachine.h +++ b/llvm/lib/Target/CSKY/CSKYTargetMachine.h @@ -13,6 +13,7 @@ #ifndef LLVM_LIB_TARGET_CSKY_CSKYTARGETMACHINE_H #define LLVM_LIB_TARGET_CSKY_CSKYTARGETMACHINE_H +#include "CSKYSubtarget.h" #include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetMachine.h" diff --git a/llvm/test/MC/CSKY/basic-16bit.s b/llvm/test/MC/CSKY/basic-16bit.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/CSKY/basic-16bit.s @@ -0,0 +1,270 @@ +# RUN: llvm-mc %s -triple=csky -show-encoding -csky-no-aliases -mattr=+e1 \ +# RUN: -mattr=+e2 -mattr=+btst16 | FileCheck -check-prefixes=CHECK-ASM %s + +# CHECK-ASM: addi16 a0, a0, 2 +# CHECK-ASM: encoding: [0x06,0x58] +addi16 a0, a0, 2 + +# CHECK-ASM: addi16 a0, sp, 4 +# CHECK-ASM: encoding: [0x01,0x18] +addi16 a0, sp, 4 + +# CHECK-ASM: addi16 a0, a1, 2 +# CHECK-ASM: encoding: [0x06,0x59] +addi16 a0, a1, 2 + +# CHECK-ASM: addi16 sp, sp, 8 +# CHECK-ASM: encoding: [0x02,0x14] +addi16 sp, sp, 8 + +# CHECK-ASM: subi16 a0, a0, 2 +# CHECK-ASM: encoding: [0x07,0x58] +subi16 a0, a0, 2 + +# CHECK-ASM: subi16 a0, a1, 2 +# CHECK-ASM: encoding: [0x07,0x59] +subi16 a0, a1, 2 + +# CHECK-ASM: subi16 sp, sp, 8 +# CHECK-ASM: encoding: [0x22,0x14] +subi16 sp, sp, 8 + +# CHECK-ASM: lsli16 a0, a1, 2 +# CHECK-ASM: encoding: [0x02,0x41] +lsli16 a0, a1, 2 + +# CHECK-ASM: lsri16 a0, a1, 2 +# CHECK-ASM: encoding: [0x02,0x49] +lsri16 a0, a1, 2 + +# CHECK-ASM: asri16 a0, a1, 2 +# CHECK-ASM: encoding: [0x02,0x51] +asri16 a0, a1, 2 + +# CHECK-ASM: btsti16 a0, 2 +# CHECK-ASM: encoding: [0xc2,0x38] +btsti16 a0, 2 + +# CHECK-ASM: bclri16 a0, 2 +# CHECK-ASM: encoding: [0x82,0x38] +bclri16 a0, 2 + +# CHECK-ASM: bseti16 a0, 2 +# CHECK-ASM: encoding: [0xa2,0x38] +bseti16 a0, 2 + +# CHECK-ASM: cmpnei16 a0, 2 +# CHECK-ASM: encoding: [0x42,0x38] +cmpnei16 a0, 2 + +# CHECK-ASM: cmphsi16 a0, 2 +# CHECK-ASM: encoding: [0x01,0x38] +cmphsi16 a0, 2 + +# CHECK-ASM: cmplti16 a0, 2 +# CHECK-ASM: encoding: [0x21,0x38] +cmplti16 a0, 2 + +# CHECK-ASM: movi16 a0, 2 +# CHECK-ASM: encoding: [0x02,0x30] +movi16 a0, 2 + +# CHECK-ASM: addu16 a3, l0, l1 +# CHECK-ASM: encoding: [0x74,0x5c] +addu16 a3, l0, l1 + +# CHECK-ASM: subu16 a3, l0, l1 +# CHECK-ASM: encoding: [0x75,0x5c] +subu16 a3, l0, l1 + +# CHECK-ASM: and16 a3, l0 +# CHECK-ASM: encoding: [0xd0,0x68] +and16 a3, l0 + +# CHECK-ASM: andn16 a3, l0 +# CHECK-ASM: encoding: [0xd1,0x68] +andn16 a3, l0 + +# CHECK-ASM: or16 a3, l0 +# CHECK-ASM: encoding: [0xd0,0x6c] +or16 a3, l0 + +# CHECK-ASM: xor16 a3, l0 +# CHECK-ASM: encoding: [0xd1,0x6c] +xor16 a3, l0 + +# CHECK-ASM: nor16 a3, l0 +# CHECK-ASM: encoding: [0xd2,0x6c] +nor16 a3, l0 + +# CHECK-ASM: lsl16 a3, l0 +# CHECK-ASM: encoding: [0xd0,0x70] +lsl16 a3, l0 + +# CHECK-ASM: rotl16 a3, l0 +# CHECK-ASM: encoding: [0xd3,0x70] +rotl16 a3, l0 + +# CHECK-ASM: lsr16 a3, l0 +# CHECK-ASM: encoding: [0xd1,0x70] +lsr16 a3, l0 + +# CHECK-ASM: asr16 a3, l0 +# CHECK-ASM: encoding: [0xd2,0x70] +asr16 a3, l0 + +# CHECK-ASM: mult16 a3, l0 +# CHECK-ASM: encoding: [0xd0,0x7c] +mult16 a3, l0 + +# CHECK-ASM: addc16 a3, l0 +# CHECK-ASM: encoding: [0xd1,0x60] +addc16 a3, l0 + +# CHECK-ASM: subc16 a3, l0 +# CHECK-ASM: encoding: [0xd3,0x60] +subc16 a3, l0 + +# CHECK-ASM: ld16.b a0, (a0, 2) +# CHECK-ASM: encoding: [0x02,0x80] +ld16.b a0, (a0, 2) + +# CHECK-ASM: ld16.h a0, (a0, 2) +# CHECK-ASM: encoding: [0x01,0x88] +ld16.h a0, (a0, 2) + +# CHECK-ASM: ld16.w a0, (a0, 4) +# CHECK-ASM: encoding: [0x01,0x90] +ld16.w a0, (a0, 4) + +# CHECK-ASM: ld16.w a0, (sp, 4) +# CHECK-ASM: encoding: [0x01,0x98] +ld16.w a0, (sp, 4) + +# CHECK-ASM: st16.b a0, (a0, 2) +# CHECK-ASM: encoding: [0x02,0xa0] +st16.b a0, (a0, 2) + +# CHECK-ASM: st16.h a0, (a0, 2) +# CHECK-ASM: encoding: [0x01,0xa8] +st16.h a0, (a0, 2) + +# CHECK-ASM: st16.w a0, (a0, 4) +# CHECK-ASM: encoding: [0x01,0xb0] +st16.w a0, (a0, 4) + +# CHECK-ASM: st16.w a0, (sp, 4) +# CHECK-ASM: encoding: [0x01,0xb8] +st16.w a0, (sp, 4) + +# CHECK-ASM: revb16 a3, l0 +# CHECK-ASM: encoding: [0xd2,0x78] +revb16 a3, l0 + +# CHECK-ASM: revh16 a3, l0 +# CHECK-ASM: encoding: [0xd3,0x78] +revh16 a3, l0 + +# CHECK-ASM: mvcv16 a3 +# CHECK-ASM: encoding: [0xc3,0x64] +mvcv16 a3 + +# CHECK-ASM: cmpne16 a3, l0 +# CHECK-ASM: encoding: [0x0e,0x65] +cmpne16 a3, l0 + +# CHECK-ASM: cmphs16 a3, l0 +# CHECK-ASM: encoding: [0x0c,0x65] +cmphs16 a3, l0 + +# CHECK-ASM: cmplt16 a3, l0 +# CHECK-ASM: encoding: [0x0d,0x65] +cmplt16 a3, l0 + +# CHECK-ASM: tst16 a3, l0 +# CHECK-ASM: encoding: [0x0e,0x69] +tst16 a3, l0 + +# CHECK-ASM: tstnbz16 a3 +# CHECK-ASM: encoding: [0x0f,0x68] +tstnbz16 a3 + +# CHECK-ASM: br16 .L.test +# CHECK-ASM: encoding: [A,0x04'A'] +# CHECK-ASM: fixup A - offset: 0, value: .L.test, kind: fixup_csky_pcrel_imm10_scale2 +.L.test: +br16 .L.test + +# CHECK-ASM: bt16 .L.test2 +# CHECK-ASM: encoding: [A,0x08'A'] +# CHECK-ASM: fixup A - offset: 0, value: .L.test2, kind: fixup_csky_pcrel_imm10_scale2 +.L.test2: +bt16 .L.test2 + +# CHECK-ASM: bf16 .L.test3 +# CHECK-ASM: encoding: [A,0x0c'A'] +# CHECK-ASM: fixup A - offset: 0, value: .L.test3, kind: fixup_csky_pcrel_imm10_scale2 +.L.test3: +bf16 .L.test3 + +# CHECK-ASM: jmp16 a3 +# CHECK-ASM: encoding: [0x0c,0x78] +jmp16 a3 + +# CHECK-ASM: jsr16 a3 +# CHECK-ASM: encoding: [0xcd,0x7b] +jsr16 a3 + +# CHECK-ASM: lrw16 a0, [.L.test14] +# CHECK-ASM: encoding: [A,A] +# CHECK-ASM: fixup A - offset: 0, value: .L.test14, kind: fixup_csky_pcrel_uimm7_scale4 +.L.test14: +lrw16 a0, [.L.test14] + +# RUN: not llvm-mc -triple csky -mattr=+e1 -mattr=+e2 -mattr=+btst16 --defsym=ERR=1 < %s 2>&1 | FileCheck %s + +.ifdef ERR + +# oimm8 +addi16 a0, 0 # CHECK: :[[#@LINE]]:12: error: operand must be sp register + +# oimm5 +cmphsi16 a0, 0 # CHECK: :[[#@LINE]]:14: error: immediate must be an integer in the range [1, 32] + +# uimm5 +lsli16 a0, a0, 32 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [0, 31] + +# uimm5/uimm5_1/uimm5_2 +ld32.b a0, (a0, -1) # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 4095] +ld32.h a0, (a0, 4095) # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [0, 4094] +ld32.h a0, (a0, 4093) # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [0, 4094] +ld32.w a0, (a0, 4093) # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 4 bytes in the range [0, 4092] +ld32.w a0, (a0, 2) # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 4 bytes in the range [0, 4092] + +st32.b a0, (a0, -1) # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 4095] +st32.h a0, (a0, 4095) # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [0, 4094] +st32.h a0, (a0, 4093) # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [0, 4094] +st32.w a0, (a0, 4093) # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 4 bytes in the range [0, 4092] +st32.w a0, (a0, 2) # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 4 bytes in the range [0, 4092] + +# Invalid mnemonics +subs t0, t2, t1 # CHECK: :[[#@LINE]]:1: error: unrecognized instruction mnemonic +nandi t0, t2, 0 # CHECK: :[[#@LINE]]:1: error: unrecognized instruction mnemonic + +# Invalid register names +addi16 foo, sp, 10 # CHECK: :[[#@LINE]]:8: error: unknown operand +lsli16 a10, a2, 0x20 # CHECK: :[[#@LINE]]:8: error: unknown operand +asri16 x16, s0, s0 # CHECK: :[[#@LINE]]:8: error: unknown operand + +# Invalid operand types +lsli16 a0, 22, 220 # CHECK: :[[#@LINE]]:12: error: invalid operand for instruction +subu16 a0, a1, 1 # CHECK: :[[#@LINE]]:16: error: invalid operand for instruction + +# Too many operands +lsli16 a0, a1, 0x11, 0x60 # CHECK: :[[@LINE]]:22: error: invalid operand for instruction + +# Too few operands +lsli16 a0 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction +lsl16 a0 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction + +.endif \ No newline at end of file