]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/bpf/bpf.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / bpf / bpf.md
CommitLineData
91dfef96 1;; Machine description for eBPF.
8d9254fc 2;; Copyright (C) 2019-2020 Free Software Foundation, Inc.
91dfef96
JM
3
4;; This file is part of GCC.
5
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.
10
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.
15
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/>.
19
20(include "predicates.md")
21(include "constraints.md")
22
23;;;; Unspecs
24
25(define_c_enum "unspec" [
26 UNSPEC_LDINDABS
27 UNSPEC_XADD
28])
29
30;;;; Constants
31
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)
45])
46
47;;;; Attributes
48
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).
61
62(define_attr "type"
63 "unknown,alu,alu32,end,ld,lddw,ldx,st,stx,jmp,xadd,multi"
64 (const_string "unknown"))
65
66;; Length of instruction in bytes.
67(define_attr "length" ""
68 (cond [
69 (eq_attr "type" "lddw") (const_int 16)
70 ] (const_int 8)))
71
72;; Describe a user's asm statement.
73(define_asm_attributes
74 [(set_attr "type" "multi")])
75
76;;;; Mode attributes and iterators
77
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 "")])
82
83;;;; NOPs
84
85(define_insn "nop"
86 [(const_int 0)]
87 ""
88 "mov\t%%r0,%%r0"
89 [(set_attr "type" "alu")])
90
91;;;; Arithmetic/Logical
92
93;; The arithmetic and logic operations below are defined for SI and DI
94;; modes. The mode iterator AM is used in order to expand to two
95;; insns, with the proper modes.
96;;
97;; 32-bit arithmetic (for SI modes) is implemented using the alu32
98;; instructions.
99
100(define_mode_iterator AM [SI DI])
101
102;;; Addition
103(define_insn "add<AM:mode>3"
104 [(set (match_operand:AM 0 "register_operand" "=r,r")
105 (plus:AM (match_operand:AM 1 "register_operand" " 0,0")
106 (match_operand:AM 2 "reg_or_imm_operand" " r,I")))]
107 "1"
108 "add<msuffix>\t%0,%2"
109 [(set_attr "type" "<mtype>")])
110
111;;; Subtraction
112
113;; Note that subtractions of constants become additions, so there is
114;; no need to handle immediate operands in the subMODE3 insns.
115
116(define_insn "sub<AM:mode>3"
117 [(set (match_operand:AM 0 "register_operand" "=r")
118 (minus:AM (match_operand:AM 1 "register_operand" " 0")
119 (match_operand:AM 2 "register_operand" " r")))]
120 ""
121 "sub<msuffix>\t%0,%2"
122 [(set_attr "type" "<mtype>")])
123
124;;; Negation
125(define_insn "neg<AM:mode>2"
126 [(set (match_operand:AM 0 "register_operand" "=r")
127 (neg:AM (match_operand:AM 1 "register_operand" " 0")))]
128 ""
129 "neg<msuffix>\t%0"
130 [(set_attr "type" "<mtype>")])
131
132;;; Multiplication
133(define_insn "mul<AM:mode>3"
134 [(set (match_operand:AM 0 "register_operand" "=r,r")
135 (mult:AM (match_operand:AM 1 "register_operand" " 0,0")
136 (match_operand:AM 2 "reg_or_imm_operand" " r,I")))]
137 ""
138 "mul<msuffix>\t%0,%2"
139 [(set_attr "type" "<mtype>")])
140
141(define_insn "*mulsidi3_zeroextend"
142 [(set (match_operand:DI 0 "register_operand" "=r,r")
143 (zero_extend:DI
144 (mult:SI (match_operand:SI 1 "register_operand" "0,0")
145 (match_operand:SI 2 "reg_or_imm_operand" "r,I"))))]
146 ""
147 "mul32\t%0,%2"
148 [(set_attr "type" "alu32")])
149
150;;; Division
151
152;; Note that eBPF doesn't provide instructions for signed integer
153;; division.
154
155(define_insn "udiv<AM:mode>3"
156 [(set (match_operand:AM 0 "register_operand" "=r,r")
157 (udiv:AM (match_operand:AM 1 "register_operand" " 0,0")
158 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
159 ""
160 "div<msuffix>\t%0,%2"
161 [(set_attr "type" "<mtype>")])
162
163;;; Modulus
164
165;; Note that eBPF doesn't provide instructions for signed integer
166;; remainder.
167
168(define_insn "umod<AM:mode>3"
169 [(set (match_operand:AM 0 "register_operand" "=r,r")
170 (umod:AM (match_operand:AM 1 "register_operand" " 0,0")
171 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
172 ""
173 "mod<msuffix>\t%0,%2"
174 [(set_attr "type" "<mtype>")])
175
176;;; Logical AND
177(define_insn "and<AM:mode>3"
178 [(set (match_operand:AM 0 "register_operand" "=r,r")
179 (and:AM (match_operand:AM 1 "register_operand" " 0,0")
180 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
181 ""
182 "and<msuffix>\t%0,%2"
183 [(set_attr "type" "<mtype>")])
184
185;;; Logical inclusive-OR
186(define_insn "ior<AM:mode>3"
187 [(set (match_operand:AM 0 "register_operand" "=r,r")
188 (ior:AM (match_operand:AM 1 "register_operand" " 0,0")
189 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
190 ""
191 "or<msuffix>\t%0,%2"
192 [(set_attr "type" "<mtype>")])
193
194;;; Logical exclusive-OR
195(define_insn "xor<AM:mode>3"
196 [(set (match_operand:AM 0 "register_operand" "=r,r")
197 (xor:AM (match_operand:AM 1 "register_operand" " 0,0")
198 (match_operand:AM 2 "reg_or_imm_operand" "r,I")))]
199 ""
200 "xor<msuffix>\t%0,%2"
201 [(set_attr "type" "<mtype>")])
202
203;;;; Conversions
204
205;;; Zero-extensions
206
207;; For register operands smaller than 32-bit zero-extending is
208;; achieved ANDing the value in the source register to a suitable
209;; mask.
210;;
211;; For register operands bigger or equal than 32-bit, we generate a
212;; mov32 instruction to zero the high 32-bits of the destination
213;; register.
214;;
215;; For memory operands, of any width, zero-extending is achieved using
216;; the ldx{bhwdw} instructions to load the values in registers.
217
218(define_insn "zero_extendhidi2"
219 [(set (match_operand:DI 0 "register_operand" "=r,r")
220 (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
221 ""
222 "@
223 and\t%0,0xffff
224 ldxh\t%0,%1"
225 [(set_attr "type" "alu,ldx")])
226
227(define_insn "zero_extendqidi2"
228 [(set (match_operand:DI 0 "register_operand" "=r,r")
229 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
230 ""
231 "@
232 and\t%0,0xff
233 ldxb\t%0,%1"
234 [(set_attr "type" "alu,ldx")])
235
236(define_insn "zero_extendsidi2"
237 [(set (match_operand:DI 0 "register_operand" "=r,r")
238 (zero_extend:DI
239 (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
240 ""
241 "@
242 mov32\t%0,%1
243 ldxw\t%0,%1"
244 [(set_attr "type" "alu,ldx")])
245
246;;; Sign-extension
247
248;; Sign-extending a 32-bit value into a 64-bit value is achieved using
249;; shifting, with instructions generated by the expand below.
250
251(define_expand "extendsidi2"
252 [(set (match_operand:DI 0 "register_operand")
253 (sign_extend:DI (match_operand:SI 1 "register_operand")))]
254 ""
255{
256 operands[1] = gen_lowpart (DImode, operands[1]);
257 emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (32)));
258 emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (32)));
259 DONE;
260})
261
262;;;; Data movement
263
264(define_mode_iterator MM [QI HI SI DI SF DF])
265
266(define_expand "mov<MM:mode>"
267 [(set (match_operand:MM 0 "general_operand")
268 (match_operand:MM 1 "general_operand"))]
269 ""
270 "
271{
272 if (!register_operand(operands[0], <MM:MODE>mode)
273 && !register_operand(operands[1], <MM:MODE>mode))
274 operands[1] = force_reg (<MM:MODE>mode, operands[1]);
275}")
276
277(define_insn "*mov<MM:mode>"
278 [(set (match_operand:MM 0 "nonimmediate_operand" "=r, r,r,m,m")
279 (match_operand:MM 1 "mov_src_operand" " m,rI,B,r,I"))]
280 ""
281 "@
282 ldx<mop>\t%0,%1
283 mov\t%0,%1
284 lddw\t%0,%1
285 stx<mop>\t%0,%1
286 st<mop>\t%0,%1"
287[(set_attr "type" "ldx,alu,alu,stx,st")])
288
289;;;; Shifts
290
291(define_mode_iterator SIM [SI DI])
292
293(define_insn "ashr<SIM:mode>3"
294 [(set (match_operand:SIM 0 "register_operand" "=r,r")
295 (ashiftrt:SIM (match_operand:SIM 1 "register_operand" " 0,0")
296 (match_operand:SIM 2 "reg_or_imm_operand" " r,I")))]
297 ""
298 "arsh<msuffix>\t%0,%2"
299 [(set_attr "type" "<mtype>")])
300
301(define_insn "ashl<SIM:mode>3"
302 [(set (match_operand:SIM 0 "register_operand" "=r,r")
303 (ashift:SIM (match_operand:SIM 1 "register_operand" " 0,0")
304 (match_operand:SIM 2 "reg_or_imm_operand" " r,I")))]
305 ""
306 "lsh<msuffix>\t%0,%2"
307 [(set_attr "type" "<mtype>")])
308
309(define_insn "lshr<SIM:mode>3"
310 [(set (match_operand:SIM 0 "register_operand" "=r,r")
311 (lshiftrt:SIM (match_operand:SIM 1 "register_operand" " 0,0")
312 (match_operand:SIM 2 "reg_or_imm_operand" " r,I")))]
313 ""
314 "rsh<msuffix>\t%0,%2"
315 [(set_attr "type" "<mtype>")])
316
317;;;; Conditional branches
318
319;; The eBPF jump instructions use 64-bit arithmetic when evaluating
320;; the jump conditions. Therefore we use DI modes below.
321
322(define_expand "cbranchdi4"
323 [(set (pc)
324 (if_then_else (match_operator 0 "comparison_operator"
325 [(match_operand:DI 1 "register_operand")
326 (match_operand:DI 2 "reg_or_imm_operand")])
327 (label_ref (match_operand 3 "" ""))
328 (pc)))]
329 ""
330{
331 if (!ordered_comparison_operator (operands[0], VOIDmode))
332 FAIL;
333})
334
335(define_insn "*branch_on_di"
336 [(set (pc)
337 (if_then_else (match_operator 3 "ordered_comparison_operator"
338 [(match_operand:DI 0 "register_operand" "r")
339 (match_operand:DI 1 "reg_or_imm_operand" "rI")])
340 (label_ref (match_operand 2 "" ""))
341 (pc)))]
342 ""
343{
344 int code = GET_CODE (operands[3]);
345
346 switch (code)
347 {
348 case EQ: return "jeq\t%0,%1,%2"; break;
349 case NE: return "jne\t%0,%1,%2"; break;
350 case LT: return "jslt\t%0,%1,%2"; break;
351 case LE: return "jsle\t%0,%1,%2"; break;
352 case GT: return "jsgt\t%0,%1,%2"; break;
353 case GE: return "jsge\t%0,%1,%2"; break;
354 case LTU: return "jlt\t%0,%1,%2"; break;
355 case LEU: return "jle\t%0,%1,%2"; break;
356 case GTU: return "jgt\t%0,%1,%2"; break;
357 case GEU: return "jge\t%0,%1,%2"; break;
358 default:
359 gcc_unreachable ();
360 return "";
361 }
362}
363 [(set_attr "type" "jmp")])
364
365;;;; Unconditional branches
366
367(define_insn "jump"
368 [(set (pc)
369 (label_ref (match_operand 0 "" "")))]
370 ""
371 "ja\t%0"
372[(set_attr "type" "jmp")])
373
374;;;; Function prologue/epilogue
375
376(define_insn "exit"
377 [(simple_return)]
378 ""
379 "exit"
380 [(set_attr "type" "jmp")])
381
382(define_expand "prologue"
383 [(const_int 0)]
384 ""
385{
386 bpf_expand_prologue ();
387 DONE;
388})
389
390(define_expand "epilogue"
391 [(const_int 0)]
392 ""
393{
394 bpf_expand_epilogue ();
395 DONE;
396})
397
398;;;; Function calls
399
400(define_expand "call"
401 [(parallel [(call (match_operand 0 "")
402 (match_operand 1 ""))
403 (use (match_operand 2 "")) ;; next_arg_reg
404 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
405 ""
406{
407 rtx target = XEXP (operands[0], 0);
408 emit_call_insn (gen_call_internal (target, operands[1]));
409 DONE;
410})
411
412(define_insn "call_internal"
413 [(call (mem:DI (match_operand:DI 0 "call_operand" "Sr"))
414 (match_operand:SI 1 "general_operand" ""))]
415 ;; operands[2] is next_arg_register
416 ;; operands[3] is struct_value_size_rtx.
417 ""
418 { return bpf_output_call (operands[0]); }
419 [(set_attr "type" "jmp")])
420
421(define_expand "call_value"
422 [(parallel [(set (match_operand 0 "")
423 (call (match_operand 1 "")
424 (match_operand 2 "")))
425 (use (match_operand 3 ""))])] ;; next_arg_reg
426 ""
427{
428 rtx target = XEXP (operands[1], 0);
429 emit_call_insn (gen_call_value_internal (operands[0], target,
430 operands[2]));
431 DONE;
432})
433
434(define_insn "call_value_internal"
435 [(set (match_operand 0 "register_operand" "")
436 (call (mem:DI (match_operand:DI 1 "call_operand" "Sr"))
437 (match_operand:SI 2 "general_operand" "")))]
438 ;; operands[3] is next_arg_register
439 ;; operands[4] is struct_value_size_rtx.
440 ""
441 { return bpf_output_call (operands[1]); }
442 [(set_attr "type" "jmp")])
443
444(define_insn "sibcall"
445 [(call (label_ref (match_operand 0 "" ""))
446 (match_operand:SI 1 "general_operand" ""))]
447 ;; operands[2] is next_arg_register
448 ;; operands[3] is struct_value_size_rtx.
449 ""
450 "ja\t%0"
451 [(set_attr "type" "jmp")])
452
453;;;; Non-generic load instructions
454
455(define_mode_iterator LDM [QI HI SI DI])
456(define_mode_attr ldop [(QI "b") (HI "h") (SI "w") (DI "dw")])
457
458(define_insn "ldind<ldop>"
459 [(set (reg:LDM R0_REGNUM)
460 (unspec:LDM [(match_operand:DI 0 "register_operand" "r")
461 (match_operand:SI 1 "imm32_operand" "I")]
462 UNSPEC_LDINDABS))
463 (clobber (reg:DI R1_REGNUM))
464 (clobber (reg:DI R2_REGNUM))
465 (clobber (reg:DI R3_REGNUM))
466 (clobber (reg:DI R4_REGNUM))]
467 ""
468 "ldind<ldop>\t%0,%1"
469 [(set_attr "type" "ld")])
470
471(define_insn "ldabs<ldop>"
472 [(set (reg:LDM R0_REGNUM)
473 (unspec:LDM [(match_operand:SI 0 "imm32_operand" "I")
474 (match_operand:SI 1 "imm32_operand" "I")]
475 UNSPEC_LDINDABS))
476 (clobber (reg:DI R1_REGNUM))
477 (clobber (reg:DI R2_REGNUM))
478 (clobber (reg:DI R3_REGNUM))
479 (clobber (reg:DI R4_REGNUM))]
480 ""
481 "ldabs<ldop>\t%0"
482 [(set_attr "type" "ld")])
483
484;;;; Atomic increments
485
486(define_mode_iterator AMO [SI DI])
487
488(define_insn "atomic_add<AMO:mode>"
489 [(set (match_operand:AMO 0 "memory_operand" "+m")
490 (unspec_volatile:AMO
491 [(plus:AMO (match_dup 0)
492 (match_operand:AMO 1 "register_operand" "r"))
493 (match_operand:SI 2 "const_int_operand")] ;; Memory model.
494 UNSPEC_XADD))]
495 ""
496 "xadd<mop>\t%0,%1"
497 [(set_attr "type" "xadd")])