xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaInstrInfo.td (revision b64c5a0ace59af62eff52bfe110a521dc73c937b)
1//===- XtensaInstrInfo.td - Target Description for Xtensa -*- tablegen -*--===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// See https://llvm.org/LICENSE.txt for license information.
7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8//
9//===----------------------------------------------------------------------===//
10//
11// This file describes the Xtensa instructions in TableGen format.
12//
13//===----------------------------------------------------------------------===//
14
15include "XtensaInstrFormats.td"
16include "XtensaOperands.td"
17include "XtensaOperators.td"
18
19//===----------------------------------------------------------------------===//
20// Arithmetic & Logical instructions
21//===----------------------------------------------------------------------===//
22
23class ArithLogic_RRR<bits<4> oper2, bits<4> oper1, string instrAsm,
24      SDPatternOperator opNode, bit isComm = 0>
25  : RRR_Inst<0x00, oper1, oper2, (outs AR:$r), (ins AR:$s, AR:$t),
26             instrAsm#"\t$r, $s, $t",
27            [(set AR:$r, (opNode AR:$s, AR:$t))]> {
28  let isCommutable = isComm;
29  let isReMaterializable = 0;
30}
31
32def ADD : ArithLogic_RRR<0x08, 0x00, "add", add, 1>;
33def SUB : ArithLogic_RRR<0x0C, 0x00, "sub", sub>;
34def AND : ArithLogic_RRR<0x01, 0x00, "and", and, 1>;
35def OR  : ArithLogic_RRR<0x02, 0x00, "or", or, 1>;
36def XOR : ArithLogic_RRR<0x03, 0x00, "xor", xor, 1>;
37
38class ADDX<bits<4> oper, string instrAsm, list<dag> pattern>
39  : RRR_Inst<0x00, 0x00, oper, (outs AR:$r), (ins AR:$s, AR:$t),
40             instrAsm#"\t$r, $s, $t", pattern>;
41
42def ADDX2 : ADDX<0x09, "addx2", [(set AR:$r, (add AR:$t, (shl AR:$s, (i32 1))))]>;
43def ADDX4 : ADDX<0x0A, "addx4", [(set AR:$r, (add AR:$t, (shl AR:$s, (i32 2))))]>;
44def ADDX8 : ADDX<0x0B, "addx8", [(set AR:$r, (add AR:$t, (shl AR:$s, (i32 3))))]>;
45
46class SUBX<bits<4> oper, string instrAsm, list<dag> pattern>
47  : RRR_Inst<0x00, 0x00, oper, (outs AR:$r), (ins AR:$s, AR:$t),
48             instrAsm#"\t$r, $s, $t", pattern>;
49
50def SUBX2 : SUBX<0x0D, "subx2", [(set AR:$r, (sub (shl AR:$s, (i32 1)), AR:$t))]>;
51def SUBX4 : SUBX<0x0E, "subx4", [(set AR:$r, (sub (shl AR:$s, (i32 2)), AR:$t))]>;
52def SUBX8 : SUBX<0x0F, "subx8", [(set AR:$r, (sub (shl AR:$s, (i32 3)), AR:$t))]>;
53
54def ABS : RRR_Inst<0x00, 0x00, 0x06, (outs AR:$r), (ins AR:$t),
55                  "abs\t$r, $t", []> {
56  let s = 0x1;
57}
58
59def ADDI : RRI8_Inst<0x02, (outs AR:$t), (ins AR:$s, imm8:$imm8),
60                    "addi\t$t, $s, $imm8",
61                    [(set AR:$t, (add AR:$s, imm8:$imm8))]> {
62  let r = 0x0C;
63}
64
65def ADDMI : RRI8_Inst<0x02, (outs AR:$t), (ins AR:$s, imm8_sh8:$imm_sh8),
66                     "addmi\t$t, $s, $imm_sh8",
67                     [(set AR:$t, (add AR:$s, imm8_sh8:$imm_sh8))]> {
68  bits<16> imm_sh8;
69
70  let r = 0x0D;
71  let imm8 = imm_sh8{15-8};
72}
73
74def NEG : RRR_Inst<0x00, 0x00, 0x06, (outs AR:$r), (ins AR:$t),
75                  "neg\t$r, $t",
76                  [(set AR:$r, (ineg AR:$t))]> {
77  let s = 0x00;
78}
79
80//===----------------------------------------------------------------------===//
81// Move instructions
82//===----------------------------------------------------------------------===//
83def MOVI : RRI8_Inst<0x02, (outs AR:$t), (ins imm12m:$imm),
84                    "movi\t$t, $imm",
85                    [(set AR:$t, imm12m:$imm)]> {
86  bits<12> imm;
87
88  let imm8{7-0} = imm{7-0};
89  let s{3-0} = imm{11-8};
90  let r = 0xa;
91}
92
93def MOVEQZ : RRR_Inst<0x00, 0x03, 0x08, (outs AR:$r), (ins AR:$s, AR:$t),
94                     "moveqz\t$r, $s, $t", []>;
95def MOVNEZ : RRR_Inst<0x00, 0x03, 0x09, (outs AR:$r), (ins AR:$s, AR:$t),
96                     "movnez\t$r, $s, $t", []>;
97def MOVLTZ : RRR_Inst<0x00, 0x03, 0x0A, (outs AR:$r), (ins AR:$s, AR:$t),
98                     "movltz\t$r, $s, $t", []>;
99def MOVGEZ : RRR_Inst<0x00, 0x03, 0x0B, (outs AR:$r), (ins AR:$s, AR:$t),
100                     "movgez\t$r, $s, $t", []>;
101
102//===----------------------------------------------------------------------===//
103// Shift instructions
104//===----------------------------------------------------------------------===//
105
106let Uses = [SAR] in {
107  def SLL : RRR_Inst<0x00, 0x01, 0x0A, (outs AR:$r), (ins AR:$s),
108                    "sll\t$r, $s", []> {
109    let t = 0x00;
110  }
111
112  def SRA : RRR_Inst<0x00, 0x01, 0x0B, (outs AR:$r), (ins AR:$t),
113                    "sra\t$r, $t", []> {
114    let s = 0x00;
115  }
116
117  def SRC : RRR_Inst<0x00, 0x01, 0x08, (outs AR:$r), (ins AR:$s, AR:$t),
118                    "src\t$r, $s, $t", []>;
119
120  def SRL : RRR_Inst<0x00, 0x01, 0x09, (outs AR:$r), (ins AR:$t),
121                    "srl\t$r, $t", []> {
122    let s = 0x00;
123  }
124}
125
126let Defs = [SAR] in {
127  def SSL : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins AR:$s),
128                    "ssl\t$s", []> {
129    let r = 0x01;
130    let t = 0x00;
131  }
132
133  def SSR : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins AR:$s),
134                    "ssr\t$s", []> {
135    let r = 0x00;
136    let t = 0x00;
137  }
138}
139
140def EXTUI : RRR_Inst<0x00, 0x04, 0x00, (outs AR:$r), (ins AR:$t, uimm5:$imm1, imm1_16:$imm2),
141                    "extui\t$r, $t, $imm1, $imm2", []> {
142  bits<5> imm1;
143  bits<4> imm2;
144
145  let s = imm1{3-0};
146  let Inst{16} = imm1{4};
147  let Inst{23-20} = imm2;
148}
149
150def SRAI : RRR_Inst<0x00, 0x01, 0x02, (outs AR:$r), (ins AR:$t, uimm5:$sa),
151                   "srai\t$r, $t, $sa",
152                   [(set AR:$r, (sra AR:$t, uimm5:$sa))]> {
153  bits<5> sa;
154
155  let Inst{20} = sa{4};
156  let s = sa{3-0};
157}
158
159def SRLI : RRR_Inst<0x00, 0x01, 0x04, (outs AR:$r), (ins AR:$t, uimm4:$sa),
160                   "srli\t$r, $t, $sa",
161                   [(set AR:$r, (srl AR:$t, uimm4:$sa))]> {
162  bits<4> sa;
163
164  let s = sa;
165}
166
167def SLLI : RRR_Inst<0x00, 0x01, 0x00, (outs AR:$r), (ins AR:$s, shimm1_31:$sa),
168                   "slli\t$r, $s, $sa",
169                   [(set AR:$r, (shl AR:$s, shimm1_31:$sa))]> {
170  bits<5> sa;
171
172  let Inst{20} = sa{4};
173  let t = sa{3-0};
174}
175
176def SSA8L : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins AR:$s),
177                    "ssa8l\t$s", []> {
178  let r = 0x2;
179  let t = 0x0;
180}
181
182def SSAI : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins uimm5:$imm),
183                   "ssai\t$imm", []> {
184  bits<5> imm;
185
186  let r = 0x04;
187  let s = imm{3-0};
188  let t{3-1} = 0;
189  let t{0} = imm{4};
190}
191
192//===----------------------------------------------------------------------===//
193// Load and store instructions
194//===----------------------------------------------------------------------===//
195
196// Load instructions
197let mayLoad = 1 in {
198
199  class Load_RRI8<bits<4> oper, string instrAsm, SDPatternOperator opNode,
200        ComplexPattern addrOp, Operand memOp>
201	  : RRI8_Inst<0x02, (outs AR:$t), (ins memOp:$addr),
202                instrAsm#"\t$t, $addr",
203               [(set AR:$t, (opNode addrOp:$addr))]> {
204    bits<12> addr;
205
206    let r = oper;
207    let imm8{7-0} = addr{11-4};
208    let s{3-0} = addr{3-0};
209  }
210}
211
212def L8UI  : Load_RRI8<0x00, "l8ui", zextloadi8, addr_ish1, mem8>;
213def L16SI : Load_RRI8<0x09, "l16si", sextloadi16, addr_ish2, mem16>;
214def L16UI : Load_RRI8<0x01, "l16ui", zextloadi16, addr_ish2, mem16>;
215def L32I  : Load_RRI8<0x02, "l32i", load, addr_ish4, mem32>;
216
217// Store instructions
218let mayStore = 1 in {
219  class Store_II8<bits<4> oper, string instrAsm, SDPatternOperator opNode,
220        ComplexPattern addrOp, Operand memOp>
221	  : RRI8_Inst<0x02, (outs), (ins AR:$t, memOp:$addr),
222                instrAsm#"\t$t, $addr",
223               [(opNode AR:$t, addrOp:$addr)]> {
224    bits<12> addr;
225
226    let r = oper;
227    let imm8{7-0} = addr{11-4};
228    let s{3-0} = addr{3-0};
229  }
230}
231
232def S8I  : Store_II8<0x04, "s8i", truncstorei8, addr_ish1, mem8>;
233def S16I : Store_II8<0x05, "s16i", truncstorei16, addr_ish2, mem16>;
234def S32I : Store_II8<0x06, "s32i", store, addr_ish4, mem32>;
235
236def L32R : RI16_Inst<0x01, (outs AR:$t), (ins L32Rtarget:$label),
237                    "l32r\t$t, $label", []> {
238  bits<16> label;
239  let imm16 = label;
240}
241
242// pcrel addr loading using L32R
243def : Pat<(Xtensa_pcrel_wrapper tconstpool : $in), (L32R tconstpool : $in)>;
244
245// FrameIndexes are legalized when they are operands from load/store
246// instructions. The same not happens for stack address copies, so an
247// add op with mem ComplexPattern is used and the stack address copy
248// can be matched.
249// Setting of attribute mayLoad is trick to process instruction operands
250// in function XtensaRegisterInfo::eliminateFI
251
252let isCodeGenOnly = 1, mayLoad = 1 in {
253
254  def LEA_ADD : RRI8_Inst<0x02, (outs AR:$t), (ins mem32:$addr),
255       "addi\t$t, $addr",
256       [(set AR:$t, addr_ish4:$addr)]> {
257    bits<12> addr;
258
259    let r = 0x0C;
260    let imm8{7-0} = addr{11-4};
261    let s{3-0} = addr{3-0};
262  }
263}
264
265//extending loads
266def : Pat<(i32 (extloadi1  addr_ish1:$addr)), (L8UI addr_ish1:$addr)>;
267def : Pat<(i32 (extloadi8  addr_ish1:$addr)), (L8UI addr_ish1:$addr)>;
268def : Pat<(i32 (extloadi16 addr_ish2:$addr)), (L16UI addr_ish2:$addr)>;
269
270//===----------------------------------------------------------------------===//
271// Conditional branch instructions
272//===----------------------------------------------------------------------===//
273let isBranch = 1, isTerminator = 1 in {
274  class Branch_RR<bits<4> oper, string instrAsm, CondCode CC>
275      : RRI8_Inst<0x07, (outs),
276                 (ins AR:$s, AR:$t, brtarget:$target),
277                  instrAsm#"\t$s, $t, $target",
278                 [(brcc CC, AR:$s, AR:$t,  bb:$target)]> {
279    bits<8> target;
280
281    let r = oper;
282    let imm8 = target;
283  }
284
285  class Branch_RI<bits<4> oper, string instrAsm, CondCode CC>
286      : RRI8_Inst<0x06, (outs),
287                 (ins AR:$s, b4const:$imm, brtarget:$target),
288                  instrAsm#"\t$s, $imm, $target",
289                 [(brcc CC, AR:$s, b4const:$imm,  bb:$target)]> {
290    bits<4> imm;
291    bits<8> target;
292
293    let t = oper;
294    let r = imm;
295    let imm8 = target;
296  }
297
298  class Branch_RIU<bits<4> oper, string instrAsm, CondCode CC>
299    : RRI8_Inst<0x06, (outs),
300               (ins AR:$s, b4constu:$imm, brtarget:$target),
301                instrAsm#"\t$s, $imm, $target",
302               [(brcc CC, AR:$s, b4constu:$imm,  bb:$target)]> {
303    bits<4> imm;
304    bits<8> target;
305
306    let t = oper;
307    let r = imm;
308    let imm8 = target;
309  }
310
311  class Branch_RZ<bits<2> n, bits<2> m, string instrAsm, CondCode CC>
312    : BRI12_Inst<0x06, n, m, (outs),
313                (ins AR:$s, brtarget:$target),
314                 instrAsm#"\t$s, $target",
315                [(brcc CC, AR:$s, (i32 0),  bb:$target)]> {
316    bits<12> target;
317
318    let imm12 = target;
319  }
320}
321
322def BEQ   : Branch_RR<0x01, "beq", SETEQ>;
323def BNE   : Branch_RR<0x09, "bne", SETNE>;
324def BGE   : Branch_RR<0x0A, "bge", SETGE>;
325def BLT   : Branch_RR<0x02, "blt", SETLT>;
326def BGEU  : Branch_RR<0x0B, "bgeu", SETUGE>;
327def BLTU  : Branch_RR<0x03, "bltu", SETULT>;
328
329def BEQI  : Branch_RI<0x02, "beqi", SETEQ>;
330def BNEI  : Branch_RI<0x06, "bnei", SETNE>;
331def BGEI  : Branch_RI<0x0E, "bgei", SETGE>;
332def BLTI  : Branch_RI<0x0A, "blti", SETLT>;
333def BGEUI : Branch_RIU<0x0F, "bgeui", SETUGE>;
334def BLTUI : Branch_RIU<0x0B, "bltui", SETULT>;
335
336def BEQZ  : Branch_RZ<0x01, 0x00, "beqz", SETEQ>;
337def BNEZ  : Branch_RZ<0x01, 0x01, "bnez", SETNE>;
338def BGEZ  : Branch_RZ<0x01, 0x03, "bgez", SETGE>;
339def BLTZ  : Branch_RZ<0x01, 0x02, "bltz", SETLT>;
340
341def BALL : RRI8_Inst<0x07, (outs),
342                    (ins AR:$s, AR:$t, brtarget:$target),
343                    "ball\t$s, $t, $target", []> {
344  bits<8> target;
345
346  let r = 0x04;
347  let imm8 = target;
348}
349
350def BANY : RRI8_Inst<0x07, (outs),
351                    (ins AR:$s, AR:$t, brtarget:$target),
352                    "bany\t$s, $t, $target", []> {
353  bits<8> target;
354
355  let r = 0x08;
356  let imm8 = target;
357}
358
359def BBC : RRI8_Inst<0x07, (outs),
360                   (ins AR:$s, AR:$t, brtarget:$target),
361                   "bbc\t$s, $t, $target", []> {
362  bits<8> target;
363
364  let r = 0x05;
365  let imm8 = target;
366}
367
368def BBS : RRI8_Inst<0x07, (outs),
369                   (ins AR:$s, AR:$t, brtarget:$target),
370                   "bbs\t$s, $t, $target", []> {
371  bits<8> target;
372
373  let r = 0x0d;
374  let imm8 = target;
375}
376
377def BNALL : RRI8_Inst<0x07, (outs),
378                    (ins AR:$s, AR:$t, brtarget:$target),
379                    "bnall\t$s, $t, $target", []> {
380  bits<8> target;
381
382  let r = 0x0c;
383  let imm8 = target;
384}
385
386def BNONE : RRI8_Inst<0x07, (outs),
387                     (ins AR:$s, AR:$t, brtarget:$target),
388                     "bnone\t$s, $t, $target", []> {
389  bits<8> target;
390
391  let r = 0x00;
392  let imm8 = target;
393}
394
395def BBCI : RRI8_Inst<0x07, (outs),
396                    (ins AR:$s, uimm5:$imm, brtarget:$target),
397                    "bbci\t$s, $imm, $target", []> {
398  bits<8> target;
399  bits<5> imm;
400
401  let r{3-1} = 0x3;
402  let r{0} = imm{4};
403  let t{3-0} = imm{3-0};
404  let imm8 = target;
405}
406
407def BBSI : RRI8_Inst<0x07, (outs),
408                    (ins AR:$s, uimm5:$imm, brtarget:$target),
409                    "bbsi\t$s, $imm, $target", []> {
410  bits<8> target;
411  bits<5> imm;
412
413  let r{3-1} = 0x7;
414  let r{0} = imm{4};
415  let t{3-0} = imm{3-0};
416  let imm8 = target;
417}
418
419//===----------------------------------------------------------------------===//
420// Call and jump instructions
421//===----------------------------------------------------------------------===//
422
423let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
424  def J : CALL_Inst<0x06, (outs), (ins jumptarget:$offset),
425                   "j\t$offset",
426                   [(br bb:$offset)]> {
427    let n = 0x0;
428  }
429
430  def JX : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s),
431                     "jx\t$s",
432                     [(brind AR:$s)]> {
433    let m = 0x2;
434    let n = 0x2;
435    let r = 0;
436    let isIndirectBranch = 1;
437  }
438}
439
440let isCall = 1, Defs = [A0] in {
441  def CALL0 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset),
442                       "call0\t$offset", []> {
443    let n = 0;
444  }
445
446  def CALLX0 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s),
447                         "callx0\t$s", []> {
448    let m = 0x3;
449    let n = 0x0;
450    let r = 0;
451  }
452}
453
454let isReturn = 1, isTerminator = 1,
455    isBarrier = 1, Uses = [A0] in {
456
457  def RET : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins),
458                      "ret", [(Xtensa_ret)]> {
459    let m = 0x2;
460    let n = 0x0;
461    let s = 0;
462    let r = 0;
463  }
464}
465
466// Call patterns
467def : Pat<(Xtensa_call (i32 tglobaladdr:$dst)),
468          (CALL0 tglobaladdr:$dst)>;
469def : Pat<(Xtensa_call (i32 texternalsym:$dst)),
470          (CALL0 texternalsym:$dst)>;
471def : Pat<(Xtensa_call AR:$dst),
472          (CALLX0 AR:$dst)>;
473
474let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1, Size = 3 in {
475  def BR_JT: Pseudo<(outs), (ins AR:$s, i32imm:$jt),
476                    "!br_jt_p, $s, $jt",
477                    [(Xtensa_brjt AR:$s, tjumptable:$jt)]>;
478}
479
480//===----------------------------------------------------------------------===//
481// Mem barrier instructions
482//===----------------------------------------------------------------------===//
483
484def MEMW :  RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
485                    "memw", []> {
486  let r = 0x2;
487  let t = 0x0c;
488  let s = 0x0;
489}
490
491def EXTW : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
492                   "extw", []> {
493  let r = 0x2;
494  let s = 0x0;
495  let t = 0xd;
496  let hasSideEffects = 1;
497}
498
499//===----------------------------------------------------------------------===//
500// Processor control instructions
501//===----------------------------------------------------------------------===//
502
503def DSYNC : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
504                    "dsync", []> {
505  let r = 0x2;
506  let s = 0x0;
507  let t = 0x3;
508  let hasSideEffects = 1;
509}
510
511def ISYNC : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
512                    "isync", []> {
513  let r = 0x2;
514  let s = 0x0;
515  let t = 0x0;
516  let hasSideEffects = 1;
517}
518
519def RSYNC : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
520                    "rsync", []> {
521  let r = 0x2;
522  let s = 0x0;
523  let t = 0x1;
524  let hasSideEffects = 1;
525}
526
527def ESYNC : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
528                    "esync", []> {
529  let r = 0x2;
530  let s = 0x0;
531  let t = 0x2;
532  let hasSideEffects = 1;
533}
534
535def NOP : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins),
536                  "nop", []> {
537  let r = 0x02;
538  let s = 0x00;
539  let t = 0x0f;
540}
541
542def WSR : RSR_Inst<0x00, 0x03, 0x01, (outs SR:$sr), (ins AR:$t),
543                  "wsr\t$t, $sr", []>;
544
545def RSR : RSR_Inst<0x00, 0x03, 0x00, (outs AR:$t), (ins SR:$sr),
546                  "rsr\t$t, $sr", []>;
547
548def XSR : RSR_Inst<0x00, 0x01, 0x06, (outs AR:$ard, SR:$srd), (ins AR:$t, SR:$sr),
549                  "xsr\t$t, $sr", []> {
550  let Constraints = "$ard = $t, $srd = $sr";
551}
552
553//===----------------------------------------------------------------------===//
554// Stack allocation
555//===----------------------------------------------------------------------===//
556
557// ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into
558// a stack adjustment and the codegen must know that they may modify the stack
559// pointer before prolog-epilog rewriting occurs.
560let Defs = [SP], Uses = [SP] in {
561  def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
562                               "#ADJCALLSTACKDOWN",
563                               [(Xtensa_callseq_start timm:$amt1, timm:$amt2)]>;
564  def ADJCALLSTACKUP   : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
565                               "#ADJCALLSTACKUP",
566                               [(Xtensa_callseq_end timm:$amt1, timm:$amt2)]>;
567}
568
569//===----------------------------------------------------------------------===//
570// Generic select instruction
571//===----------------------------------------------------------------------===//
572let usesCustomInserter = 1 in {
573  def SELECT : Pseudo<(outs AR:$dst), (ins AR:$lhs, AR:$rhs, AR:$t, AR:$f, i32imm:$cond),
574                     "!select $dst, $lhs, $rhs, $t, $f, $cond",
575                     [(set i32:$dst, (Xtensa_select_cc i32:$lhs, i32:$rhs, i32:$t, i32:$f, imm:$cond))]>;
576}
577