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)
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")
25 (define_c_enum "unspec" [
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).
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" ""
69 (eq_attr "type" "lddw") (const_int 16)
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")
80 (define_mode_attr mtype [(SI "alu32") (DI "alu")])
81 (define_mode_attr msuffix [(SI "32") (DI "")])
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_.
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])
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")))]
113 "add<msuffix>\t%0,%2"
114 [(set_attr "type" "<mtype>")])
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")))]
126 "sub<msuffix>\t%0,%2"
127 [(set_attr "type" "<mtype>")])
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")))]
135 [(set_attr "type" "<mtype>")])
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")))]
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")
149 (mult:SI (match_operand:SI 1 "register_operand" "0,0")
150 (match_operand:SI 2 "reg_or_imm_operand" "r,I"))))]
153 [(set_attr "type" "alu32")])
157 ;; Note that eBPF doesn't provide instructions for signed integer
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")))]
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")))]
175 "sdiv<msuffix>\t%0,%2"
176 [(set_attr "type" "<mtype>")])
180 ;; Note that eBPF doesn't provide instructions for signed integer
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")))]
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")))]
198 "smod<msuffix>\t%0,%2"
199 [(set_attr "type" "<mtype>")])
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")))]
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")))]
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")))]
225 "xor<msuffix>\t%0,%2"
226 [(set_attr "type" "<mtype>")])
232 ;; For register operands smaller than 32-bit zero-extending is
233 ;; achieved ANDing the value in the source register to a suitable
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
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")))]
249 mov\t%0,%1\;and\t%0,0xffff
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")))]
259 mov\t%0,%1\;and\t%0,0xff
261 [(set_attr "type" "alu,alu,ldx")])
263 (define_insn "zero_extendsidi2"
264 [(set (match_operand:DI 0 "register_operand" "=r,r")
266 (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
269 * return bpf_has_alu32 ? \"mov32\t%0,%1\" : \"mov\t%0,%1\;and\t%0,0xffffffff\";
271 [(set_attr "type" "alu,ldx")])
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")))]
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)));
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"))]
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"))]
314 [(set_attr "type" "ldx,alu,alu,stx,st")])
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")))]
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")))]
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")))]
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")))]
354 if (TARGET_BIG_ENDIAN)
355 return "endle\t%0, <endmode>";
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"
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 "" ""))
377 if (!ordered_comparison_operator (operands[0], VOIDmode))
380 bpf_expand_cbranch (<JM:MODE>mode, operands);
383 (define_insn "*branch_on_<JM:mode>"
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 "" ""))
392 int code = GET_CODE (operands[3]);
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;
411 [(set_attr "type" "jmp")])
413 ;;;; Unconditional branches
417 (label_ref (match_operand 0 "" "")))]
420 [(set_attr "type" "jmp")])
422 ;;;; Function prologue/epilogue
428 [(set_attr "type" "jmp")])
430 (define_expand "prologue"
434 bpf_expand_prologue ();
438 (define_expand "epilogue"
442 bpf_expand_epilogue ();
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
455 rtx target = XEXP (operands[0], 0);
456 emit_call_insn (gen_call_internal (target, operands[1]));
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.
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
476 rtx target = XEXP (operands[1], 0);
477 emit_call_insn (gen_call_value_internal (operands[0], target,
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.
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.
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")]
511 (clobber (reg:DI R1_REGNUM))
512 (clobber (reg:DI R2_REGNUM))
513 (clobber (reg:DI R3_REGNUM))
514 (clobber (reg:DI R4_REGNUM))]
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")]
524 (clobber (reg:DI R1_REGNUM))
525 (clobber (reg:DI R2_REGNUM))
526 (clobber (reg:DI R3_REGNUM))
527 (clobber (reg:DI R4_REGNUM))]
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")
539 [(plus:AMO (match_dup 0)
540 (match_operand:AMO 1 "register_operand" "r"))
541 (match_operand:SI 2 "const_int_operand")] ;; Memory model.
545 [(set_attr "type" "xadd")])