xref: /freebsd/contrib/llvm-project/llvm/lib/Target/CSKY/CSKYInstrInfo.td (revision 66df505066f51e6d8411b966765d828817f88971)
1//===-- CSKYInstrInfo.td - Target Description for CSKY -----*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the CSKY instructions in TableGen format.
10//
11//===----------------------------------------------------------------------===//
12
13
14//===----------------------------------------------------------------------===//
15// CSKY specific DAG Nodes.
16//===----------------------------------------------------------------------===//
17
18// Target-dependent nodes.
19def CSKY_RET : SDNode<"CSKYISD::RET", SDTNone,
20    [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
21
22//===----------------------------------------------------------------------===//
23// Operand and SDNode transformation definitions.
24//===----------------------------------------------------------------------===//
25class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
26  let Name = prefix # "Imm" # width # suffix;
27  let RenderMethod = "addImmOperands";
28  let DiagnosticType = !strconcat("Invalid", Name);
29}
30
31class SImmAsmOperand<int width, string suffix = "">
32    : ImmAsmOperand<"S", width, suffix> {
33}
34
35class UImmAsmOperand<int width, string suffix = "">
36    : ImmAsmOperand<"U", width, suffix> {
37}
38
39class OImmAsmOperand<int width, string suffix = "">
40    : ImmAsmOperand<"O", width, suffix> {
41}
42
43class oimm<int num> : Operand<i32>,
44  ImmLeaf<i32, "return isUInt<"#num#">(Imm - 1);"> {
45  let EncoderMethod = "getOImmOpValue";
46  let ParserMatchClass = OImmAsmOperand<num>;
47}
48
49class uimm<int num, int shift = 0> : Operand<i32>,
50  ImmLeaf<i32, "return isShiftedUInt<"#num#", "#shift#">(Imm);"> {
51  let EncoderMethod = "getImmOpValue<"#shift#">";
52  let ParserMatchClass =
53    !if(!ne(shift, 0),
54        UImmAsmOperand<num, "Shift"#shift>,
55        UImmAsmOperand<num>);
56}
57
58class simm<int num, int shift = 0> : Operand<i32>,
59  ImmLeaf<i32, "return isShiftedInt<"#num#", "#shift#">(Imm);"> {
60  let EncoderMethod = "getImmOpValue<"#shift#">";
61  let ParserMatchClass = SImmAsmOperand<num>;
62}
63
64def nimm_XFORM : SDNodeXForm<imm, [{
65  return CurDAG->getTargetConstant(~N->getSExtValue(), SDLoc(N), MVT::i32);
66}]>;
67class nimm<int num> : Operand<i32>,
68  ImmLeaf<i32, "return isUInt<"#num#">(~Imm);", nimm_XFORM> {
69  let ParserMatchClass = UImmAsmOperand<num>;
70}
71
72def uimm32_hi16 : SDNodeXForm<imm, [{
73  return CurDAG->getTargetConstant((N->getZExtValue() >> 16) & 0xFFFF,
74    SDLoc(N), MVT::i32);
75}]>;
76def uimm16_16_xform : Operand<i32>,
77  ImmLeaf<i32, "return isShiftedUInt<16, 16>(Imm);", uimm32_hi16> {
78  let ParserMatchClass = UImmAsmOperand<16>;
79}
80
81def uimm_shift : Operand<i32>, ImmLeaf<i32, "return isUInt<2>(Imm);"> {
82  let EncoderMethod = "getImmShiftOpValue";
83  let ParserMatchClass = UImmAsmOperand<2>;
84}
85
86def CSKYSymbol : AsmOperandClass {
87  let Name = "CSKYSymbol";
88  let RenderMethod = "addImmOperands";
89  let DiagnosticType = "InvalidCSKYSymbol";
90  let ParserMethod = "parseCSKYSymbol";
91}
92
93def br_symbol : Operand<iPTR> {
94  let EncoderMethod =
95    "getBranchSymbolOpValue<CSKY::fixup_csky_pcrel_imm16_scale2>";
96  let ParserMatchClass = CSKYSymbol;
97}
98
99def call_symbol : Operand<iPTR> {
100  let ParserMatchClass = CSKYSymbol;
101  let EncoderMethod = "getCallSymbolOpValue";
102}
103
104def Constpool : AsmOperandClass {
105  let Name = "ConstpoolSymbol";
106  let RenderMethod = "addImmOperands";
107  let DiagnosticType = "InvalidConstpool";
108  let ParserMethod = "parseConstpoolSymbol";
109}
110
111def constpool_symbol : Operand<iPTR> {
112  let ParserMatchClass = Constpool;
113  let EncoderMethod =
114    "getConstpoolSymbolOpValue<CSKY::fixup_csky_pcrel_uimm16_scale4>";
115}
116
117def bare_symbol : Operand<iPTR> {
118  let ParserMatchClass = CSKYSymbol;
119  let EncoderMethod = "getBareSymbolOpValue";
120}
121
122def oimm12 : oimm<12>;
123def oimm16 : oimm<16>;
124
125def nimm12 : nimm<12>;
126
127def uimm5 : uimm<5>;
128def uimm12 : uimm<12>;
129def uimm12_1 : uimm<12, 1>;
130def uimm12_2 : uimm<12, 2>;
131def uimm16 : uimm<16>;
132
133
134//===----------------------------------------------------------------------===//
135// Instruction Formats
136//===----------------------------------------------------------------------===//
137
138include "CSKYInstrFormats.td"
139
140//===----------------------------------------------------------------------===//
141// Instruction definitions.
142//===----------------------------------------------------------------------===//
143
144class TriOpFrag<dag res> : PatFrag<(ops node: $LHS, node:$MHS, node:$RHS), res>;
145class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
146class UnOpFrag<dag res> : PatFrag<(ops node:$Src), res>;
147
148
149
150//===----------------------------------------------------------------------===//
151// Basic ALU instructions.
152//===----------------------------------------------------------------------===//
153
154  def ADDI32 : I_12<0x0, "addi32", add, oimm12>;
155  def SUBI32 : I_12<0x1, "subi32", sub, oimm12>;
156  def ORI32 : I_16_ZX<"ori32", uimm16,
157  [(set GPR:$rz, (or GPR:$rx, uimm16:$imm16))]>;
158  def XORI32 : I_12<0x4, "xori32", xor, uimm12>;
159  def ANDI32 : I_12<0x2, "andi32", and, uimm12>;
160  def ANDNI32 : I_12<0x3, "andni32", and, nimm12>;
161  def LSLI32 : I_5_XZ<0x12, 0x1, "lsli32",
162    (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5),
163    [(set GPR:$rz, (shl GPR:$rx, uimm5:$imm5))]>;
164  def LSRI32 : I_5_XZ<0x12, 0x2, "lsri32",
165    (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5),
166    [(set GPR:$rz, (srl GPR:$rx, uimm5:$imm5))]>;
167  def ASRI32 : I_5_XZ<0x12, 0x4, "asri32",
168    (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5),
169    [(set GPR:$rz, (sra GPR:$rx, uimm5:$imm5))]>;
170  def ROTLI32 : I_5_XZ<0x12, 0x8, "rotli32",
171    (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5),
172    [(set GPR:$rz, (rotl GPR:$rx, uimm5:$imm5))]>;
173
174
175  def ADDU32 : R_YXZ_SP_F1<0x0, 0x1,
176    BinOpFrag<(add node:$LHS, node:$RHS)>, "addu32", 1>;
177  def SUBU32 : R_YXZ_SP_F1<0x0, 0x4,
178    BinOpFrag<(sub node:$LHS, node:$RHS)>, "subu32">;
179  def MULT32 : R_YXZ_SP_F1<0x21, 0x1,
180    BinOpFrag<(mul node:$LHS, node:$RHS)>, "mult32", 1>;
181  def AND32 : R_YXZ_SP_F1<0x8, 0x1,
182    BinOpFrag<(and node:$LHS, node:$RHS)>, "and32", 1>;
183  def ANDN32 : R_YXZ_SP_F1<0x8, 0x2,
184    BinOpFrag<(and node:$LHS, (not node:$RHS))>, "andn32">;
185  def OR32: R_YXZ_SP_F1<0x9, 0x1,
186    BinOpFrag<(or node:$LHS, node:$RHS)>, "or32", 1>;
187  def XOR32 : R_YXZ_SP_F1<0x9, 0x2,
188    BinOpFrag<(xor node:$LHS, node:$RHS)>, "xor32", 1>;
189  def NOR32 : R_YXZ_SP_F1<0x9, 0x4,
190    BinOpFrag<(not (or node:$LHS, node:$RHS))>, "nor32", 1>;
191  def NOT32 : R_XXZ<0b001001, 0b00100, (outs GPR:$rz), (ins GPR:$rx),
192    "not32", [(set GPR:$rz, (not GPR:$rx))]>;
193  def LSL32 : R_YXZ_SP_F1<0x10, 0x1,
194    BinOpFrag<(shl node:$LHS, node:$RHS)>, "lsl32">;
195  def LSR32 : R_YXZ_SP_F1<0x10, 0x2,
196    BinOpFrag<(srl node:$LHS, node:$RHS)>, "lsr32">;
197  def ASR32 : R_YXZ_SP_F1<0x10, 0x4,
198    BinOpFrag<(sra node:$LHS, node:$RHS)>, "asr32">;
199  def ROTL32 : R_YXZ_SP_F1<0x10, 0x8,
200    BinOpFrag<(rotl node:$LHS, (and node:$RHS, 0x1f))>, "rotl32">;
201
202  // TODO: Shift series instr. with carry.
203
204  def IXH32 : R_YXZ_SP_F1<0x2, 0x1,
205    BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 1)))>, "ixh32">;
206  def IXW32 : R_YXZ_SP_F1<0x2, 0x2,
207    BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 2)))>, "ixw32">;
208
209  def IXD32 : R_YXZ_SP_F1<0x2, 0x4,
210    BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 3)))>, "ixd32">;
211
212  let isCommutable = 1 in
213  def ADDC32 : R_YXZ<0x31, 0x0, 0x2, (outs GPR:$rz, CARRY:$cout),
214    (ins GPR:$rx, GPR:$ry, CARRY:$cin), "addc32", []>;
215  def SUBC32 : R_YXZ<0x31, 0x0, 0x8, (outs GPR:$rz, CARRY:$cout),
216    (ins GPR:$rx, GPR:$ry, CARRY:$cin), "subc32", []>;
217
218  // TODO: incf32.
219  def DIVS32 : R_YXZ_SP_F1<0x20, 0x2,
220    BinOpFrag<(sdiv node:$LHS, node:$RHS)>, "divs32">;
221  def DIVU32 : R_YXZ_SP_F1<0x20, 0x1,
222    BinOpFrag<(udiv node:$LHS, node:$RHS)>, "divu32">;
223
224  def DECGT32 : I_5_XZ<0x4, 0x1, "decgt32",
225    (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, uimm5:$imm5), []>;
226  def DECLT32 : I_5_XZ<0x4, 0x2, "declt32",
227    (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, uimm5:$imm5), []>;
228  def DECNE32 : I_5_XZ<0x4, 0x4, "decne32",
229    (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, uimm5:$imm5), []>;
230
231  // TODO: s/zext.
232  def ZEXT32 : I_5_XZ_U<0x15, (outs GPR:$rz),
233    (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "zext32",[]>;
234  def SEXT32 : I_5_XZ_U<0x16, (outs GPR:$rz),
235    (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "sext32", []>;
236
237//===----------------------------------------------------------------------===//
238// Load & Store instructions.
239//===----------------------------------------------------------------------===//
240
241def LD32B : I_LD<AddrMode32B, 0x0, "ld32.b", uimm12>;
242def LD32H : I_LD<AddrMode32H, 0x1, "ld32.h", uimm12_1>;
243def LD32W : I_LD<AddrMode32WD, 0x2, "ld32.w", uimm12_2>;
244
245
246  def LD32BS : I_LD<AddrMode32B, 0x4, "ld32.bs", uimm12>;
247  def LD32HS : I_LD<AddrMode32H, 0x5, "ld32.hs", uimm12_1>;
248
249  // TODO: LDM and STM.
250
251
252def ST32B : I_ST<AddrMode32B, 0x0, "st32.b", uimm12>;
253def ST32H : I_ST<AddrMode32H, 0x1, "st32.h", uimm12_1>;
254def ST32W : I_ST<AddrMode32WD, 0x2, "st32.w", uimm12_2>;
255
256
257  def LDR32B :  I_LDR<0x0, "ldr32.b">;
258  def LDR32BS :  I_LDR<0x4, "ldr32.bs">;
259  def LDR32H :  I_LDR<0x1, "ldr32.h">;
260  def LDR32HS :  I_LDR<0x5, "ldr32.hs">;
261  def LDR32W :  I_LDR<0x2, "ldr32.w">;
262  def STR32B :  I_STR<0x0, "str32.b">;
263  def STR32H :  I_STR<0x1, "str32.h">;
264  def STR32W :  I_STR<0x2, "str32.w">;
265
266  //TODO: SPILL_CARRY and RESTORE_CARRY.
267
268//===----------------------------------------------------------------------===//
269// Compare instructions.
270//===----------------------------------------------------------------------===//
271
272  def CMPNEI32 : I_16_X<0x1A, "cmpnei32", uimm16>;
273  def CMPHSI32 : I_16_X<0x18, "cmphsi32", oimm16>;
274  def CMPLTI32 : I_16_X<0x19, "cmplti32", oimm16>;
275
276
277  def CMPNE32 : R_YX<0x1, 0x4, "cmpne32">;
278  def CMPHS32 : R_YX<0x1, 0x1, "cmphs32">;
279  def CMPLT32 : R_YX<0x1, 0x2, "cmplt32">;
280
281  // TODO: setc and clrc.
282  // TODO: test32 and tstnbz.
283
284//===----------------------------------------------------------------------===//
285// Data move instructions.
286//===----------------------------------------------------------------------===//
287
288  def MOVT32 : R_ZX<0x3, 0x2, "movt32", []>;
289  def MOVF32 : R_ZX<0x3, 0x1, "movf32", []>;
290  def MOVI32 : I_16_MOV<0x10, "movi32", uimm16>;
291  def MOVIH32 : I_16_MOV<0x11, "movih32", uimm16_16_xform>;
292  def MVC32 : R_Z_1<0x1, 0x8, "mvc32">;
293  def MOV32 : R_XZ<0x12, 0x1, "mov32">;
294
295  // TODO: ISEL Pseudo.
296
297  def MVCV32 : R_Z_1<0x1, 0x10, "mvcv32">;
298  // TODO: clrf and clrt.
299  def CLRF32 : R_Z_2<0xB, 0x1, "clrf32", []>;
300  def CLRT32 : R_Z_2<0xB, 0x2, "clrt32", []>;
301
302//===----------------------------------------------------------------------===//
303// Branch and call instructions.
304//===----------------------------------------------------------------------===//
305
306let isBranch = 1, isTerminator = 1 in {
307  let isBarrier = 1, isPredicable = 1 in
308    def BR32 : I_16_L<0x0, (outs), (ins br_symbol:$imm16), "br32\t$imm16",
309                     [(br bb:$imm16)]>;
310
311  def BT32 : I_16_L<0x3, (outs), (ins CARRY:$ca, br_symbol:$imm16),
312    "bt32\t$imm16", [(brcond CARRY:$ca, bb:$imm16)]>;
313  def BF32 : I_16_L<0x2, (outs), (ins CARRY:$ca, br_symbol:$imm16),
314    "bf32\t$imm16", []>;
315}
316
317
318  def BEZ32 : I_16_X_L<0x8, "bez32", br_symbol>;
319  def BNEZ32 : I_16_X_L<0x9, "bnez32", br_symbol>;
320  def BHZ32 : I_16_X_L<0xA, "bhz32", br_symbol>;
321  def BLSZ32 : I_16_X_L<0xB, "blsz32", br_symbol>;
322  def BLZ32 : I_16_X_L<0xC, "blz32", br_symbol>;
323  def BHSZ32 : I_16_X_L<0xD, "bhsz32", br_symbol>;
324
325  let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
326    def JMP32 : I_16_JX<0x6, "jmp32", [(brind GPR:$rx)]>; // jmp to register
327    def JMPI32 : I_16_L<0x16, (outs), (ins constpool_symbol:$imm16),
328                   "jmpi32\t$imm16", []>;
329  }
330
331  let isCall = 1, Defs = [ R15 ] in
332    def JSR32 : I_16_JX<0x7, "jsr32", []>;
333
334  let isCall = 1, Defs = [ R15 ] , mayLoad = 1 in
335    def JSRI32: I_16_L<0x17, (outs),
336      (ins constpool_symbol:$imm16), "jsri32\t$imm16", []>;
337
338
339def BSR32 : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>;
340
341def BSR32_BR : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>{
342  let isCodeGenOnly = 1;
343  let isBranch = 1;
344  let isTerminator = 1;
345  let isBarrier = 1;
346  let isPredicable = 1;
347  let Defs = [ R15 ];
348}
349
350
351  def RTS32 : I_16_RET<0x6, 0xF, "rts32", [(CSKY_RET)]>;
352
353
354def RTE32 : I_16_RET_I<0, 0, "rte32", []>;
355
356//===----------------------------------------------------------------------===//
357// Symbol address instructions.
358//===----------------------------------------------------------------------===//
359
360def GRS32 : I_18_Z_L<0x3, "grs32\t$rz, $offset",
361                    (outs GPR:$rz), (ins bare_symbol:$offset), []>;
362
363let mayLoad = 1, mayStore = 0 in {
364def LRW32 : I_16_Z_L<0x14, "lrw32", (ins constpool_symbol:$imm16), []>;
365let isCodeGenOnly = 1 in
366def LRW32_Gen : I_16_Z_L<0x14, "lrw32",
367  (ins bare_symbol:$src1, constpool_symbol:$imm16), []>;
368}
369
370// TODO: Atomic and fence instructions.
371// TODO: Other operations.
372// TODO: Special instructions.
373// TODO: Pseudo for assembly.
374