Add assember CFI directives to millicode division and remainder routines.
[official-gcc.git] / gcc / config / bpf / bpf.md
blobf6be0a2123451289ddced0d9f37b5feaa916e2d7
1 ;; Machine description for eBPF.
2 ;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
4 ;; This file is part of GCC.
6 ;; GCC is free software; you can redistribute it and/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation; either version 3, or (at your option)
9 ;; any later version.
11 ;; GCC is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;; GNU General Public License for more details.
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with GCC; see the file COPYING3.  If not see
18 ;; <http://www.gnu.org/licenses/>.
20 (include "predicates.md")
21 (include "constraints.md")
23 ;;;; Unspecs
25 (define_c_enum "unspec" [
26   UNSPEC_LDINDABS
27   UNSPEC_XADD
30 ;;;; Constants
32 (define_constants
33   [(R0_REGNUM           0)
34    (R1_REGNUM           1)
35    (R2_REGNUM           2)
36    (R3_REGNUM           3)
37    (R4_REGNUM           4)
38    (R5_REGNUM           5)
39    (R6_REGNUM           6)
40    (R7_REGNUM           7)
41    (R8_REGNUM           8)
42    (R9_REGNUM           9)
43    (R10_REGNUM          10)
44    (R11_REGNUM          11)
47 ;;;; Attributes
49 ;; Instruction classes.
50 ;; alu          64-bit arithmetic.
51 ;; alu32        32-bit arithmetic.
52 ;; end          endianness conversion instructions.
53 ;; ld           load instructions.
54 ;; lddx         load 64-bit immediate instruction.
55 ;; ldx          generic load instructions.
56 ;; st           generic store instructions for immediates.
57 ;; stx          generic store instructions.
58 ;; jmp          jump instructions.
59 ;; xadd         atomic exchange-and-add instructions.
60 ;; multi        multiword sequence (or user asm statements).
62 (define_attr "type"
63   "unknown,alu,alu32,end,ld,lddw,ldx,st,stx,jmp,xadd,multi"
64   (const_string "unknown"))
66 ;; Length of instruction in bytes.
67 (define_attr "length" ""
68   (cond [
69          (eq_attr "type" "lddw") (const_int 16)
70          ] (const_int 8)))
72 ;; Describe a user's asm statement.
73 (define_asm_attributes
74   [(set_attr "type" "multi")])
76 ;;;; Mode attributes and iterators
78 (define_mode_attr mop [(QI "b") (HI "h") (SI "w") (DI "dw")
79                        (SF "w") (DF "dw")])
80 (define_mode_attr mtype [(SI "alu32") (DI "alu")])
81 (define_mode_attr msuffix [(SI "32") (DI "")])
83 ;;;; NOPs
85 ;; The Linux kernel verifier performs some optimizations that rely on
86 ;; nop instructions to be encoded as `ja 0', i.e. a jump to offset 0,
87 ;; which actually means to jump to the next instruction, since in BPF
88 ;; offsets are expressed in 64-bit words _minus one_.
90 (define_insn "nop"
91   [(const_int 0)]
92   ""
93   "ja\t0"
94   [(set_attr "type" "alu")])
96 ;;;; Arithmetic/Logical
98 ;; The arithmetic and logic operations below are defined for SI and DI
99 ;; modes.  The mode iterator AM is used in order to expand to two
100 ;; insns, with the proper modes.
102 ;; 32-bit arithmetic (for SI modes) is implemented using the alu32
103 ;; instructions, if available.
105 (define_mode_iterator AM [(SI "bpf_has_alu32") DI])
107 ;;; Addition
108 (define_insn "add<AM:mode>3"
109   [(set (match_operand:AM          0 "register_operand"   "=r,r")
110         (plus:AM (match_operand:AM 1 "register_operand"   " 0,0")
111                  (match_operand:AM 2 "reg_or_imm_operand" " r,I")))]
112   "1"
113   "add<msuffix>\t%0,%2"
114   [(set_attr "type" "<mtype>")])
116 ;;; Subtraction
118 ;; Note that subtractions of constants become additions, so there is
119 ;; no need to handle immediate operands in the subMODE3 insns.
121 (define_insn "sub<AM:mode>3"
122   [(set (match_operand:AM          0 "register_operand" "=r")
123         (minus:AM (match_operand:AM 1 "register_operand" " 0")
124                   (match_operand:AM 2 "register_operand" " r")))]
125   ""
126   "sub<msuffix>\t%0,%2"
127   [(set_attr "type" "<mtype>")])
129 ;;; Negation
130 (define_insn "neg<AM:mode>2"
131   [(set (match_operand:AM 0 "register_operand" "=r")
132         (neg:AM (match_operand:AM 1 "register_operand" " 0")))]
133   ""
134   "neg<msuffix>\t%0"
135   [(set_attr "type" "<mtype>")])
137 ;;; Multiplication
138 (define_insn "mul<AM:mode>3"
139   [(set (match_operand:AM          0 "register_operand"   "=r,r")
140         (mult:AM (match_operand:AM 1 "register_operand"   " 0,0")
141                  (match_operand:AM 2 "reg_or_imm_operand" " r,I")))]
142   ""
143   "mul<msuffix>\t%0,%2"
144   [(set_attr "type" "<mtype>")])
146 (define_insn "*mulsidi3_zeroextend"
147   [(set (match_operand:DI          0 "register_operand" "=r,r")
148         (zero_extend:DI
149          (mult:SI (match_operand:SI 1 "register_operand" "0,0")
150                   (match_operand:SI 2 "reg_or_imm_operand" "r,I"))))]
151   ""
152   "mul32\t%0,%2"
153   [(set_attr "type" "alu32")])
155 ;;; Division
157 ;; Note that eBPF doesn't provide instructions for signed integer
158 ;; division.
160 (define_insn "udiv<AM:mode>3"
161   [(set (match_operand:AM 0 "register_operand" "=r,r")
162         (udiv:AM (match_operand:AM 1 "register_operand" " 0,0")
163                  (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
164   ""
165   "div<msuffix>\t%0,%2"
166   [(set_attr "type" "<mtype>")])
168 ;; However, xBPF does provide a signed division operator, sdiv.
170 (define_insn "div<AM:mode>3"
171   [(set (match_operand:AM 0 "register_operand" "=r,r")
172         (div:AM (match_operand:AM 1 "register_operand" " 0,0")
173                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
174   "TARGET_XBPF"
175   "sdiv<msuffix>\t%0,%2"
176   [(set_attr "type" "<mtype>")])
178 ;;; Modulus
180 ;; Note that eBPF doesn't provide instructions for signed integer
181 ;; remainder.
183 (define_insn "umod<AM:mode>3"
184   [(set (match_operand:AM 0 "register_operand" "=r,r")
185         (umod:AM (match_operand:AM 1 "register_operand" " 0,0")
186                  (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
187   ""
188   "mod<msuffix>\t%0,%2"
189   [(set_attr "type" "<mtype>")])
191 ;; Again, xBPF provides a signed version, smod.
193 (define_insn "mod<AM:mode>3"
194   [(set (match_operand:AM 0 "register_operand" "=r,r")
195         (mod:AM (match_operand:AM 1 "register_operand" " 0,0")
196                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
197   "TARGET_XBPF"
198   "smod<msuffix>\t%0,%2"
199   [(set_attr "type" "<mtype>")])
201 ;;; Logical AND
202 (define_insn "and<AM:mode>3"
203   [(set (match_operand:AM 0 "register_operand" "=r,r")
204         (and:AM (match_operand:AM 1 "register_operand" " 0,0")
205                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
206   ""
207   "and<msuffix>\t%0,%2"
208   [(set_attr "type" "<mtype>")])
210 ;;; Logical inclusive-OR
211 (define_insn "ior<AM:mode>3"
212   [(set (match_operand:AM 0 "register_operand" "=r,r")
213         (ior:AM (match_operand:AM 1 "register_operand" " 0,0")
214                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
215   ""
216   "or<msuffix>\t%0,%2"
217   [(set_attr "type" "<mtype>")])
219 ;;; Logical exclusive-OR
220 (define_insn "xor<AM:mode>3"
221   [(set (match_operand:AM 0 "register_operand" "=r,r")
222         (xor:AM (match_operand:AM 1 "register_operand" " 0,0")
223                 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
224   ""
225   "xor<msuffix>\t%0,%2"
226   [(set_attr "type" "<mtype>")])
228 ;;;; Conversions
230 ;;; Zero-extensions
232 ;; For register operands smaller than 32-bit zero-extending is
233 ;; achieved ANDing the value in the source register to a suitable
234 ;; mask.
236 ;; For register operands bigger or equal than 32-bit, we generate a
237 ;; mov32 instruction to zero the high 32-bits of the destination
238 ;; register.
240 ;; For memory operands, of any width, zero-extending is achieved using
241 ;; the ldx{bhwdw} instructions to load the values in registers.
243 (define_insn "zero_extendhidi2"
244   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
245         (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "0,r,q")))]
246   ""
247   "@
248    and\t%0,0xffff
249    mov\t%0,%1\;and\t%0,0xffff
250    ldxh\t%0,%1"
251   [(set_attr "type" "alu,alu,ldx")])
253 (define_insn "zero_extendqidi2"
254   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
255         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "0,r,q")))]
256   ""
257   "@
258    and\t%0,0xff
259    mov\t%0,%1\;and\t%0,0xff
260    ldxb\t%0,%1"
261   [(set_attr "type" "alu,alu,ldx")])
263 (define_insn "zero_extendsidi2"
264   [(set (match_operand:DI 0 "register_operand" "=r,r")
265         (zero_extend:DI
266           (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
267   ""
268   "@
269    * return bpf_has_alu32 ? \"mov32\t%0,%1\" : \"mov\t%0,%1\;and\t%0,0xffffffff\";
270    ldxw\t%0,%1"
271   [(set_attr "type" "alu,ldx")])
273 ;;; Sign-extension
275 ;; Sign-extending a 32-bit value into a 64-bit value is achieved using
276 ;; shifting, with instructions generated by the expand below.
278 (define_expand "extendsidi2"
279   [(set (match_operand:DI 0 "register_operand")
280         (sign_extend:DI (match_operand:SI 1 "register_operand")))]
281   ""
283   operands[1] = gen_lowpart (DImode, operands[1]);
284   emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (32)));
285   emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (32)));
286   DONE;
289 ;;;; Data movement
291 (define_mode_iterator MM [QI HI SI DI SF DF])
293 (define_expand "mov<MM:mode>"
294   [(set (match_operand:MM 0 "general_operand")
295         (match_operand:MM 1 "general_operand"))]
296         ""
297         "
299   if (!register_operand(operands[0], <MM:MODE>mode)
300       && !register_operand(operands[1], <MM:MODE>mode))
301     operands[1] = force_reg (<MM:MODE>mode, operands[1]);
304 (define_insn "*mov<MM:mode>"
305   [(set (match_operand:MM 0 "nonimmediate_operand" "=r, r,r,q,q")
306         (match_operand:MM 1 "mov_src_operand"      " q,rI,B,r,I"))]
307   ""
308   "@
309    ldx<mop>\t%0,%1
310    mov\t%0,%1
311    lddw\t%0,%1
312    stx<mop>\t%0,%1
313    st<mop>\t%0,%1"
314 [(set_attr "type" "ldx,alu,alu,stx,st")])
316 ;;;; Shifts
318 (define_mode_iterator SIM [(SI "bpf_has_alu32") DI])
320 (define_insn "ashr<SIM:mode>3"
321   [(set (match_operand:SIM 0 "register_operand"                 "=r,r")
322         (ashiftrt:SIM (match_operand:SIM 1 "register_operand"   " 0,0")
323                       (match_operand:SIM 2 "reg_or_imm_operand" " r,I")))]
324   ""
325   "arsh<msuffix>\t%0,%2"
326   [(set_attr "type" "<mtype>")])
328 (define_insn "ashl<SIM:mode>3"
329   [(set (match_operand:SIM 0 "register_operand"               "=r,r")
330         (ashift:SIM (match_operand:SIM 1 "register_operand"   " 0,0")
331                     (match_operand:SIM 2 "reg_or_imm_operand" " r,I")))]
332   ""
333   "lsh<msuffix>\t%0,%2"
334   [(set_attr "type" "<mtype>")])
336 (define_insn "lshr<SIM:mode>3"
337   [(set (match_operand:SIM 0 "register_operand"                 "=r,r")
338         (lshiftrt:SIM (match_operand:SIM 1 "register_operand"   " 0,0")
339                       (match_operand:SIM 2 "reg_or_imm_operand" " r,I")))]
340   ""
341   "rsh<msuffix>\t%0,%2"
342   [(set_attr "type" "<mtype>")])
344 ;;;; Endianness conversion
346 (define_mode_iterator BSM [HI SI DI])
347 (define_mode_attr endmode [(HI "16") (SI "32") (DI "64")])
349 (define_insn "bswap<BSM:mode>2"
350   [(set (match_operand:BSM 0 "register_operand"            "=r")
351         (bswap:BSM (match_operand:BSM 1 "register_operand" " r")))]
352   ""
354   if (TARGET_BIG_ENDIAN)
355     return "endle\t%0, <endmode>";
356   else
357     return "endbe\t%0, <endmode>";
359   [(set_attr "type" "end")])
361 ;;;; Conditional branches
363 ;; The eBPF jump instructions use 64-bit arithmetic when evaluating
364 ;; the jump conditions.  Therefore we use DI modes below.
366 (define_mode_iterator JM [(SI "bpf_has_jmp32") DI])
368 (define_expand "cbranch<JM:mode>4"
369   [(set (pc)
370         (if_then_else (match_operator 0 "comparison_operator"
371                         [(match_operand:JM 1 "register_operand")
372                          (match_operand:JM 2 "reg_or_imm_operand")])
373                       (label_ref (match_operand 3 "" ""))
374                       (pc)))]
375   ""
377   if (!ordered_comparison_operator (operands[0], VOIDmode))
378     FAIL;
380   bpf_expand_cbranch (<JM:MODE>mode, operands);
383 (define_insn "*branch_on_<JM:mode>"
384   [(set (pc)
385         (if_then_else (match_operator 3 "ordered_comparison_operator"
386                          [(match_operand:JM 0 "register_operand" "r")
387                           (match_operand:JM 1 "reg_or_imm_operand" "rI")])
388                       (label_ref (match_operand 2 "" ""))
389                       (pc)))]
390   ""
392   int code = GET_CODE (operands[3]);
394   switch (code)
395   {
396   case EQ: return "jeq<msuffix>\t%0,%1,%2"; break;
397   case NE: return "jne<msuffix>\t%0,%1,%2"; break;
398   case LT: return "jslt<msuffix>\t%0,%1,%2"; break;
399   case LE: return "jsle<msuffix>\t%0,%1,%2"; break;
400   case GT: return "jsgt<msuffix>\t%0,%1,%2"; break;
401   case GE: return "jsge<msuffix>\t%0,%1,%2"; break;
402   case LTU: return "jlt<msuffix>\t%0,%1,%2"; break;
403   case LEU: return "jle<msuffix>\t%0,%1,%2"; break;
404   case GTU: return "jgt<msuffix>\t%0,%1,%2"; break;
405   case GEU: return "jge<msuffix>\t%0,%1,%2"; break;
406   default:
407     gcc_unreachable ();
408     return "";
409   }
411   [(set_attr "type" "jmp")])
413 ;;;; Unconditional branches
415 (define_insn "jump"
416   [(set (pc)
417         (label_ref (match_operand 0 "" "")))]
418   ""
419   "ja\t%0"
420 [(set_attr "type" "jmp")])
422 ;;;; Function prologue/epilogue
424 (define_insn "exit"
425   [(simple_return)]
426   ""
427   "exit"
428   [(set_attr "type" "jmp")])
430 (define_expand "prologue"
431   [(const_int 0)]
432   ""
434   bpf_expand_prologue ();
435   DONE;
438 (define_expand "epilogue"
439   [(const_int 0)]
440   ""
442   bpf_expand_epilogue ();
443   DONE;
446 ;;;; Function calls
448 (define_expand "call"
449   [(parallel [(call (match_operand 0 "")
450                     (match_operand 1 ""))
451               (use (match_operand 2 ""))        ;; next_arg_reg
452               (use (match_operand 3 ""))])]     ;; struct_value_size_rtx
453   ""
455   rtx target = XEXP (operands[0], 0);
456   emit_call_insn (gen_call_internal (target, operands[1]));
457   DONE;
460 (define_insn "call_internal"
461   [(call (mem:DI (match_operand:DI 0 "call_operand" "Sr"))
462          (match_operand:SI 1 "general_operand" ""))]
463   ;; operands[2] is next_arg_register
464   ;; operands[3] is struct_value_size_rtx.
465   ""
466   { return bpf_output_call (operands[0]); }
467   [(set_attr "type" "jmp")])
469 (define_expand "call_value"
470   [(parallel [(set (match_operand 0 "")
471                    (call (match_operand 1 "")
472                          (match_operand 2 "")))
473               (use (match_operand 3 ""))])]             ;; next_arg_reg
474   ""
476   rtx target = XEXP (operands[1], 0);
477   emit_call_insn (gen_call_value_internal (operands[0], target,
478                                            operands[2]));
479   DONE;
482 (define_insn "call_value_internal"
483   [(set (match_operand 0 "register_operand" "")
484         (call (mem:DI (match_operand:DI 1 "call_operand" "Sr"))
485               (match_operand:SI 2 "general_operand" "")))]
486   ;; operands[3] is next_arg_register
487   ;; operands[4] is struct_value_size_rtx.
488   ""
489   { return bpf_output_call (operands[1]); }
490   [(set_attr "type" "jmp")])
492 (define_insn "sibcall"
493   [(call (label_ref (match_operand 0 "" ""))
494          (match_operand:SI 1 "general_operand" ""))]
495   ;; operands[2] is next_arg_register
496   ;; operands[3] is struct_value_size_rtx.
497   ""
498   "ja\t%0"
499   [(set_attr "type" "jmp")])
501 ;;;; Non-generic load instructions
503 (define_mode_iterator LDM [QI HI SI DI])
504 (define_mode_attr ldop [(QI "b") (HI "h") (SI "w") (DI "dw")])
506 (define_insn "ldind<ldop>"
507   [(set (reg:LDM R0_REGNUM)
508         (unspec:LDM [(match_operand:DI 0 "register_operand" "r")
509                     (match_operand:SI 1 "imm32_operand" "I")]
510                     UNSPEC_LDINDABS))
511    (clobber (reg:DI R1_REGNUM))
512    (clobber (reg:DI R2_REGNUM))
513    (clobber (reg:DI R3_REGNUM))
514    (clobber (reg:DI R4_REGNUM))]
515   ""
516   "ldind<ldop>\t%0,%1"
517   [(set_attr "type" "ld")])
519 (define_insn "ldabs<ldop>"
520   [(set (reg:LDM R0_REGNUM)
521         (unspec:LDM [(match_operand:SI 0 "imm32_operand" "I")
522                     (match_operand:SI 1 "imm32_operand" "I")]
523                     UNSPEC_LDINDABS))
524    (clobber (reg:DI R1_REGNUM))
525    (clobber (reg:DI R2_REGNUM))
526    (clobber (reg:DI R3_REGNUM))
527    (clobber (reg:DI R4_REGNUM))]
528   ""
529   "ldabs<ldop>\t%0"
530   [(set_attr "type" "ld")])
532 ;;;; Atomic increments
534 (define_mode_iterator AMO [SI DI])
536 (define_insn "atomic_add<AMO:mode>"
537   [(set (match_operand:AMO 0 "memory_operand" "+m")
538         (unspec_volatile:AMO
539          [(plus:AMO (match_dup 0)
540                     (match_operand:AMO 1 "register_operand" "r"))
541           (match_operand:SI 2 "const_int_operand")] ;; Memory model.
542          UNSPEC_XADD))]
543   ""
544   "xadd<mop>\t%0,%1"
545   [(set_attr "type" "xadd")])