1;; Machine description for eBPF. 2;; Copyright (C) 2019-2020 Free Software Foundation, Inc. 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")]) 498