1;; Machine description for RISC-V for GNU compiler. 2;; Copyright (C) 2011-2017 Free Software Foundation, Inc. 3;; Contributed by Andrew Waterman (andrew@sifive.com). 4;; Based on MIPS target for GNU compiler. 5 6;; This file is part of GCC. 7 8;; GCC is free software; you can redistribute it and/or modify 9;; it under the terms of the GNU General Public License as published by 10;; the Free Software Foundation; either version 3, or (at your option) 11;; any later version. 12 13;; GCC is distributed in the hope that it will be useful, 14;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16;; GNU General Public License for more details. 17 18;; You should have received a copy of the GNU General Public License 19;; along with GCC; see the file COPYING3. If not see 20;; <http://www.gnu.org/licenses/>. 21 22(define_c_enum "unspec" [ 23 ;; Override return address for exception handling. 24 UNSPEC_EH_RETURN 25 26 ;; Symbolic accesses. The order of this list must match that of 27 ;; enum riscv_symbol_type in riscv-protos.h. 28 UNSPEC_ADDRESS_FIRST 29 UNSPEC_PCREL 30 UNSPEC_LOAD_GOT 31 UNSPEC_TLS 32 UNSPEC_TLS_LE 33 UNSPEC_TLS_IE 34 UNSPEC_TLS_GD 35 36 ;; High part of PC-relative address. 37 UNSPEC_AUIPC 38 39 ;; Floating-point unspecs. 40 UNSPEC_FLT_QUIET 41 UNSPEC_FLE_QUIET 42 UNSPEC_COPYSIGN 43 UNSPEC_LRINT 44 UNSPEC_LROUND 45 46 ;; Stack tie 47 UNSPEC_TIE 48]) 49 50(define_c_enum "unspecv" [ 51 ;; Register save and restore. 52 UNSPECV_GPR_SAVE 53 UNSPECV_GPR_RESTORE 54 55 ;; Floating-point unspecs. 56 UNSPECV_FRFLAGS 57 UNSPECV_FSFLAGS 58 59 ;; Blockage and synchronization. 60 UNSPECV_BLOCKAGE 61 UNSPECV_FENCE 62 UNSPECV_FENCE_I 63]) 64 65(define_constants 66 [(RETURN_ADDR_REGNUM 1) 67 (T0_REGNUM 5) 68 (T1_REGNUM 6) 69 (S0_REGNUM 8) 70 (S1_REGNUM 9) 71 (S2_REGNUM 18) 72]) 73 74(include "predicates.md") 75(include "constraints.md") 76 77;; .................... 78;; 79;; Attributes 80;; 81;; .................... 82 83(define_attr "got" "unset,xgot_high,load" 84 (const_string "unset")) 85 86;; Classification of moves, extensions and truncations. Most values 87;; are as for "type" (see below) but there are also the following 88;; move-specific values: 89;; 90;; andi a single ANDI instruction 91;; shift_shift a shift left followed by a shift right 92;; 93;; This attribute is used to determine the instruction's length and 94;; scheduling type. For doubleword moves, the attribute always describes 95;; the split instructions; in some cases, it is more appropriate for the 96;; scheduling type to be "multi" instead. 97(define_attr "move_type" 98 "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove, 99 const,logical,arith,andi,shift_shift" 100 (const_string "unknown")) 101 102;; Main data type used by the insn 103(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF" 104 (const_string "unknown")) 105 106;; True if the main data type is twice the size of a word. 107(define_attr "dword_mode" "no,yes" 108 (cond [(and (eq_attr "mode" "DI,DF") 109 (eq (symbol_ref "TARGET_64BIT") (const_int 0))) 110 (const_string "yes") 111 112 (and (eq_attr "mode" "TI,TF") 113 (ne (symbol_ref "TARGET_64BIT") (const_int 0))) 114 (const_string "yes")] 115 (const_string "no"))) 116 117;; Classification of each insn. 118;; branch conditional branch 119;; jump unconditional jump 120;; call unconditional call 121;; load load instruction(s) 122;; fpload floating point load 123;; store store instruction(s) 124;; fpstore floating point store 125;; mtc transfer to coprocessor 126;; mfc transfer from coprocessor 127;; const load constant 128;; arith integer arithmetic instructions 129;; logical integer logical instructions 130;; shift integer shift instructions 131;; slt set less than instructions 132;; imul integer multiply 133;; idiv integer divide 134;; move integer register move (addi rd, rs1, 0) 135;; fmove floating point register move 136;; fadd floating point add/subtract 137;; fmul floating point multiply 138;; fmadd floating point multiply-add 139;; fdiv floating point divide 140;; fcmp floating point compare 141;; fcvt floating point convert 142;; fsqrt floating point square root 143;; multi multiword sequence (or user asm statements) 144;; nop no operation 145;; ghost an instruction that produces no real code 146(define_attr "type" 147 "unknown,branch,jump,call,load,fpload,store,fpstore, 148 mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul, 149 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,nop,ghost" 150 (cond [(eq_attr "got" "load") (const_string "load") 151 152 ;; If a doubleword move uses these expensive instructions, 153 ;; it is usually better to schedule them in the same way 154 ;; as the singleword form, rather than as "multi". 155 (eq_attr "move_type" "load") (const_string "load") 156 (eq_attr "move_type" "fpload") (const_string "fpload") 157 (eq_attr "move_type" "store") (const_string "store") 158 (eq_attr "move_type" "fpstore") (const_string "fpstore") 159 (eq_attr "move_type" "mtc") (const_string "mtc") 160 (eq_attr "move_type" "mfc") (const_string "mfc") 161 162 ;; These types of move are always single insns. 163 (eq_attr "move_type" "fmove") (const_string "fmove") 164 (eq_attr "move_type" "arith") (const_string "arith") 165 (eq_attr "move_type" "logical") (const_string "logical") 166 (eq_attr "move_type" "andi") (const_string "logical") 167 168 ;; These types of move are always split. 169 (eq_attr "move_type" "shift_shift") 170 (const_string "multi") 171 172 ;; These types of move are split for doubleword modes only. 173 (and (eq_attr "move_type" "move,const") 174 (eq_attr "dword_mode" "yes")) 175 (const_string "multi") 176 (eq_attr "move_type" "move") (const_string "move") 177 (eq_attr "move_type" "const") (const_string "const")] 178 (const_string "unknown"))) 179 180;; Length of instruction in bytes. 181(define_attr "length" "" 182 (cond [ 183 ;; Branches further than +/- 4 KiB require two instructions. 184 (eq_attr "type" "branch") 185 (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4088)) 186 (le (minus (pc) (match_dup 0)) (const_int 4092))) 187 (const_int 4) 188 (const_int 8)) 189 190 ;; Conservatively assume calls take two instructions (AUIPC + JALR). 191 ;; The linker will opportunistically relax the sequence to JAL. 192 (eq_attr "type" "call") (const_int 8) 193 194 ;; "Ghost" instructions occupy no space. 195 (eq_attr "type" "ghost") (const_int 0) 196 197 (eq_attr "got" "load") (const_int 8) 198 199 (eq_attr "type" "fcmp") (const_int 8) 200 201 ;; SHIFT_SHIFTs are decomposed into two separate instructions. 202 (eq_attr "move_type" "shift_shift") 203 (const_int 8) 204 205 ;; Check for doubleword moves that are decomposed into two 206 ;; instructions. 207 (and (eq_attr "move_type" "mtc,mfc,move") 208 (eq_attr "dword_mode" "yes")) 209 (const_int 8) 210 211 ;; Doubleword CONST{,N} moves are split into two word 212 ;; CONST{,N} moves. 213 (and (eq_attr "move_type" "const") 214 (eq_attr "dword_mode" "yes")) 215 (symbol_ref "riscv_split_const_insns (operands[1]) * 4") 216 217 ;; Otherwise, constants, loads and stores are handled by external 218 ;; routines. 219 (eq_attr "move_type" "load,fpload") 220 (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4") 221 (eq_attr "move_type" "store,fpstore") 222 (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4") 223 ] (const_int 4))) 224 225;; Is copying of this instruction disallowed? 226(define_attr "cannot_copy" "no,yes" (const_string "no")) 227 228;; Describe a user's asm statement. 229(define_asm_attributes 230 [(set_attr "type" "multi")]) 231 232;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated 233;; from the same template. 234(define_mode_iterator GPR [SI (DI "TARGET_64BIT")]) 235 236;; This mode iterator allows :P to be used for patterns that operate on 237;; pointer-sized quantities. Exactly one of the two alternatives will match. 238(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) 239 240;; Likewise, but for XLEN-sized quantities. 241(define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")]) 242 243;; Branches operate on XLEN-sized quantities, but for RV64 we accept 244;; QImode values so we can force zero-extension. 245(define_mode_iterator BR [(QI "TARGET_64BIT") SI (DI "TARGET_64BIT")]) 246 247;; 32-bit moves for which we provide move patterns. 248(define_mode_iterator MOVE32 [SI]) 249 250;; 64-bit modes for which we provide move patterns. 251(define_mode_iterator MOVE64 [DI DF]) 252 253;; Iterator for sub-32-bit integer modes. 254(define_mode_iterator SHORT [QI HI]) 255 256;; Iterator for HImode constant generation. 257(define_mode_iterator HISI [HI SI]) 258 259;; Iterator for QImode extension patterns. 260(define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")]) 261 262;; Iterator for extending loads. 263(define_mode_iterator ZERO_EXTEND_LOAD [QI HI (SI "TARGET_64BIT")]) 264 265;; Iterator for hardware integer modes narrower than XLEN. 266(define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")]) 267 268;; Iterator for hardware-supported integer modes. 269(define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")]) 270 271;; Iterator for hardware-supported floating-point modes. 272(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT") 273 (DF "TARGET_DOUBLE_FLOAT")]) 274 275;; This attribute gives the length suffix for a sign- or zero-extension 276;; instruction. 277(define_mode_attr size [(QI "b") (HI "h")]) 278 279;; Mode attributes for loads. 280(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")]) 281 282;; Instruction names for stores. 283(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")]) 284 285;; This attribute gives the best constraint to use for registers of 286;; a given mode. 287(define_mode_attr reg [(SI "d") (DI "d") (CC "d")]) 288 289;; This attribute gives the format suffix for floating-point operations. 290(define_mode_attr fmt [(SF "s") (DF "d")]) 291 292;; This attribute gives the integer suffix for floating-point conversions. 293(define_mode_attr ifmt [(SI "w") (DI "l")]) 294 295;; This attribute gives the format suffix for atomic memory operations. 296(define_mode_attr amo [(SI "w") (DI "d")]) 297 298;; This attribute gives the upper-case mode name for one unit of a 299;; floating-point mode. 300(define_mode_attr UNITMODE [(SF "SF") (DF "DF")]) 301 302;; This attribute gives the integer mode that has half the size of 303;; the controlling mode. 304(define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")]) 305 306;; Iterator and attributes for floating-point rounding instructions. 307(define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND]) 308(define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")]) 309(define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")]) 310 311;; Iterator and attributes for quiet comparisons. 312(define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET]) 313(define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")]) 314 315;; This code iterator allows signed and unsigned widening multiplications 316;; to use the same template. 317(define_code_iterator any_extend [sign_extend zero_extend]) 318 319;; This code iterator allows the two right shift instructions to be 320;; generated from the same template. 321(define_code_iterator any_shiftrt [ashiftrt lshiftrt]) 322 323;; This code iterator allows the three shift instructions to be generated 324;; from the same template. 325(define_code_iterator any_shift [ashift ashiftrt lshiftrt]) 326 327;; This code iterator allows the three bitwise instructions to be generated 328;; from the same template. 329(define_code_iterator any_bitwise [and ior xor]) 330 331;; This code iterator allows unsigned and signed division to be generated 332;; from the same template. 333(define_code_iterator any_div [div udiv mod umod]) 334 335;; This code iterator allows unsigned and signed modulus to be generated 336;; from the same template. 337(define_code_iterator any_mod [mod umod]) 338 339;; These code iterators allow the signed and unsigned scc operations to use 340;; the same template. 341(define_code_iterator any_gt [gt gtu]) 342(define_code_iterator any_ge [ge geu]) 343(define_code_iterator any_lt [lt ltu]) 344(define_code_iterator any_le [le leu]) 345 346;; <u> expands to an empty string when doing a signed operation and 347;; "u" when doing an unsigned operation. 348(define_code_attr u [(sign_extend "") (zero_extend "u") 349 (gt "") (gtu "u") 350 (ge "") (geu "u") 351 (lt "") (ltu "u") 352 (le "") (leu "u")]) 353 354;; <su> is like <u>, but the signed form expands to "s" rather than "". 355(define_code_attr su [(sign_extend "s") (zero_extend "u")]) 356 357;; <optab> expands to the name of the optab for a particular code. 358(define_code_attr optab [(ashift "ashl") 359 (ashiftrt "ashr") 360 (lshiftrt "lshr") 361 (div "div") 362 (mod "mod") 363 (udiv "udiv") 364 (umod "umod") 365 (ge "ge") 366 (le "le") 367 (gt "gt") 368 (lt "lt") 369 (ior "ior") 370 (xor "xor") 371 (and "and") 372 (plus "add") 373 (minus "sub")]) 374 375;; <insn> expands to the name of the insn that implements a particular code. 376(define_code_attr insn [(ashift "sll") 377 (ashiftrt "sra") 378 (lshiftrt "srl") 379 (div "div") 380 (mod "rem") 381 (udiv "divu") 382 (umod "remu") 383 (ior "or") 384 (xor "xor") 385 (and "and") 386 (plus "add") 387 (minus "sub")]) 388 389;; Ghost instructions produce no real code and introduce no hazards. 390;; They exist purely to express an effect on dataflow. 391(define_insn_reservation "ghost" 0 392 (eq_attr "type" "ghost") 393 "nothing") 394 395;; 396;; .................... 397;; 398;; ADDITION 399;; 400;; .................... 401;; 402 403(define_insn "add<mode>3" 404 [(set (match_operand:ANYF 0 "register_operand" "=f") 405 (plus:ANYF (match_operand:ANYF 1 "register_operand" "f") 406 (match_operand:ANYF 2 "register_operand" "f")))] 407 "TARGET_HARD_FLOAT" 408 "fadd.<fmt>\t%0,%1,%2" 409 [(set_attr "type" "fadd") 410 (set_attr "mode" "<UNITMODE>")]) 411 412(define_insn "addsi3" 413 [(set (match_operand:SI 0 "register_operand" "=r,r") 414 (plus:SI (match_operand:SI 1 "register_operand" "r,r") 415 (match_operand:SI 2 "arith_operand" "r,I")))] 416 "" 417 { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; } 418 [(set_attr "type" "arith") 419 (set_attr "mode" "SI")]) 420 421(define_insn "adddi3" 422 [(set (match_operand:DI 0 "register_operand" "=r,r") 423 (plus:DI (match_operand:DI 1 "register_operand" "r,r") 424 (match_operand:DI 2 "arith_operand" "r,I")))] 425 "TARGET_64BIT" 426 "add\t%0,%1,%2" 427 [(set_attr "type" "arith") 428 (set_attr "mode" "DI")]) 429 430(define_insn "*addsi3_extended" 431 [(set (match_operand:DI 0 "register_operand" "=r,r") 432 (sign_extend:DI 433 (plus:SI (match_operand:SI 1 "register_operand" "r,r") 434 (match_operand:SI 2 "arith_operand" "r,I"))))] 435 "TARGET_64BIT" 436 "addw\t%0,%1,%2" 437 [(set_attr "type" "arith") 438 (set_attr "mode" "SI")]) 439 440(define_insn "*addsi3_extended2" 441 [(set (match_operand:DI 0 "register_operand" "=r,r") 442 (sign_extend:DI 443 (subreg:SI (plus:DI (match_operand:DI 1 "register_operand" "r,r") 444 (match_operand:DI 2 "arith_operand" "r,I")) 445 0)))] 446 "TARGET_64BIT" 447 "addw\t%0,%1,%2" 448 [(set_attr "type" "arith") 449 (set_attr "mode" "SI")]) 450 451;; 452;; .................... 453;; 454;; SUBTRACTION 455;; 456;; .................... 457;; 458 459(define_insn "sub<mode>3" 460 [(set (match_operand:ANYF 0 "register_operand" "=f") 461 (minus:ANYF (match_operand:ANYF 1 "register_operand" "f") 462 (match_operand:ANYF 2 "register_operand" "f")))] 463 "TARGET_HARD_FLOAT" 464 "fsub.<fmt>\t%0,%1,%2" 465 [(set_attr "type" "fadd") 466 (set_attr "mode" "<UNITMODE>")]) 467 468(define_insn "subdi3" 469 [(set (match_operand:DI 0 "register_operand" "=r") 470 (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") 471 (match_operand:DI 2 "register_operand" "r")))] 472 "TARGET_64BIT" 473 "sub\t%0,%z1,%2" 474 [(set_attr "type" "arith") 475 (set_attr "mode" "DI")]) 476 477(define_insn "subsi3" 478 [(set (match_operand:SI 0 "register_operand" "=r") 479 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") 480 (match_operand:SI 2 "register_operand" "r")))] 481 "" 482 { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; } 483 [(set_attr "type" "arith") 484 (set_attr "mode" "SI")]) 485 486(define_insn "*subsi3_extended" 487 [(set (match_operand:DI 0 "register_operand" "=r") 488 (sign_extend:DI 489 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") 490 (match_operand:SI 2 "register_operand" "r"))))] 491 "TARGET_64BIT" 492 "subw\t%0,%z1,%2" 493 [(set_attr "type" "arith") 494 (set_attr "mode" "SI")]) 495 496(define_insn "*subsi3_extended2" 497 [(set (match_operand:DI 0 "register_operand" "=r") 498 (sign_extend:DI 499 (subreg:SI (minus:DI (match_operand:DI 1 "reg_or_0_operand" "r") 500 (match_operand:DI 2 "register_operand" "r")) 501 0)))] 502 "TARGET_64BIT" 503 "subw\t%0,%z1,%2" 504 [(set_attr "type" "arith") 505 (set_attr "mode" "SI")]) 506 507;; 508;; .................... 509;; 510;; MULTIPLICATION 511;; 512;; .................... 513;; 514 515(define_insn "mul<mode>3" 516 [(set (match_operand:ANYF 0 "register_operand" "=f") 517 (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") 518 (match_operand:ANYF 2 "register_operand" "f")))] 519 "TARGET_HARD_FLOAT" 520 "fmul.<fmt>\t%0,%1,%2" 521 [(set_attr "type" "fmul") 522 (set_attr "mode" "<UNITMODE>")]) 523 524(define_insn "mulsi3" 525 [(set (match_operand:SI 0 "register_operand" "=r") 526 (mult:SI (match_operand:SI 1 "register_operand" "r") 527 (match_operand:SI 2 "register_operand" "r")))] 528 "TARGET_MUL" 529 { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; } 530 [(set_attr "type" "imul") 531 (set_attr "mode" "SI")]) 532 533(define_insn "muldi3" 534 [(set (match_operand:DI 0 "register_operand" "=r") 535 (mult:DI (match_operand:DI 1 "register_operand" "r") 536 (match_operand:DI 2 "register_operand" "r")))] 537 "TARGET_MUL && TARGET_64BIT" 538 "mul\t%0,%1,%2" 539 [(set_attr "type" "imul") 540 (set_attr "mode" "DI")]) 541 542(define_insn "*mulsi3_extended" 543 [(set (match_operand:DI 0 "register_operand" "=r") 544 (sign_extend:DI 545 (mult:SI (match_operand:SI 1 "register_operand" "r") 546 (match_operand:SI 2 "register_operand" "r"))))] 547 "TARGET_MUL && TARGET_64BIT" 548 "mulw\t%0,%1,%2" 549 [(set_attr "type" "imul") 550 (set_attr "mode" "SI")]) 551 552(define_insn "*mulsi3_extended2" 553 [(set (match_operand:DI 0 "register_operand" "=r") 554 (sign_extend:DI 555 (subreg:SI (mult:DI (match_operand:DI 1 "register_operand" "r") 556 (match_operand:DI 2 "register_operand" "r")) 557 0)))] 558 "TARGET_MUL && TARGET_64BIT" 559 "mulw\t%0,%1,%2" 560 [(set_attr "type" "imul") 561 (set_attr "mode" "SI")]) 562 563;; 564;; ........................ 565;; 566;; MULTIPLICATION HIGH-PART 567;; 568;; ........................ 569;; 570 571 572(define_expand "<u>mulditi3" 573 [(set (match_operand:TI 0 "register_operand") 574 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand")) 575 (any_extend:TI (match_operand:DI 2 "register_operand"))))] 576 "TARGET_MUL && TARGET_64BIT" 577{ 578 rtx low = gen_reg_rtx (DImode); 579 emit_insn (gen_muldi3 (low, operands[1], operands[2])); 580 581 rtx high = gen_reg_rtx (DImode); 582 emit_insn (gen_<u>muldi3_highpart (high, operands[1], operands[2])); 583 584 emit_move_insn (gen_lowpart (DImode, operands[0]), low); 585 emit_move_insn (gen_highpart (DImode, operands[0]), high); 586 DONE; 587}) 588 589(define_insn "<u>muldi3_highpart" 590 [(set (match_operand:DI 0 "register_operand" "=r") 591 (truncate:DI 592 (lshiftrt:TI 593 (mult:TI (any_extend:TI 594 (match_operand:DI 1 "register_operand" "r")) 595 (any_extend:TI 596 (match_operand:DI 2 "register_operand" "r"))) 597 (const_int 64))))] 598 "TARGET_MUL && TARGET_64BIT" 599 "mulh<u>\t%0,%1,%2" 600 [(set_attr "type" "imul") 601 (set_attr "mode" "DI")]) 602 603(define_expand "usmulditi3" 604 [(set (match_operand:TI 0 "register_operand") 605 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand")) 606 (sign_extend:TI (match_operand:DI 2 "register_operand"))))] 607 "TARGET_MUL && TARGET_64BIT" 608{ 609 rtx low = gen_reg_rtx (DImode); 610 emit_insn (gen_muldi3 (low, operands[1], operands[2])); 611 612 rtx high = gen_reg_rtx (DImode); 613 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2])); 614 615 emit_move_insn (gen_lowpart (DImode, operands[0]), low); 616 emit_move_insn (gen_highpart (DImode, operands[0]), high); 617 DONE; 618}) 619 620(define_insn "usmuldi3_highpart" 621 [(set (match_operand:DI 0 "register_operand" "=r") 622 (truncate:DI 623 (lshiftrt:TI 624 (mult:TI (zero_extend:TI 625 (match_operand:DI 1 "register_operand" "r")) 626 (sign_extend:TI 627 (match_operand:DI 2 "register_operand" "r"))) 628 (const_int 64))))] 629 "TARGET_MUL && TARGET_64BIT" 630 "mulhsu\t%0,%2,%1" 631 [(set_attr "type" "imul") 632 (set_attr "mode" "DI")]) 633 634(define_expand "<u>mulsidi3" 635 [(set (match_operand:DI 0 "register_operand" "=r") 636 (mult:DI (any_extend:DI 637 (match_operand:SI 1 "register_operand" "r")) 638 (any_extend:DI 639 (match_operand:SI 2 "register_operand" "r"))))] 640 "TARGET_MUL && !TARGET_64BIT" 641{ 642 rtx temp = gen_reg_rtx (SImode); 643 emit_insn (gen_mulsi3 (temp, operands[1], operands[2])); 644 emit_insn (gen_<u>mulsi3_highpart (riscv_subword (operands[0], true), 645 operands[1], operands[2])); 646 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp)); 647 DONE; 648}) 649 650(define_insn "<u>mulsi3_highpart" 651 [(set (match_operand:SI 0 "register_operand" "=r") 652 (truncate:SI 653 (lshiftrt:DI 654 (mult:DI (any_extend:DI 655 (match_operand:SI 1 "register_operand" "r")) 656 (any_extend:DI 657 (match_operand:SI 2 "register_operand" "r"))) 658 (const_int 32))))] 659 "TARGET_MUL && !TARGET_64BIT" 660 "mulh<u>\t%0,%1,%2" 661 [(set_attr "type" "imul") 662 (set_attr "mode" "SI")]) 663 664 665(define_expand "usmulsidi3" 666 [(set (match_operand:DI 0 "register_operand" "=r") 667 (mult:DI (zero_extend:DI 668 (match_operand:SI 1 "register_operand" "r")) 669 (sign_extend:DI 670 (match_operand:SI 2 "register_operand" "r"))))] 671 "TARGET_MUL && !TARGET_64BIT" 672{ 673 rtx temp = gen_reg_rtx (SImode); 674 emit_insn (gen_mulsi3 (temp, operands[1], operands[2])); 675 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true), 676 operands[1], operands[2])); 677 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp)); 678 DONE; 679}) 680 681(define_insn "usmulsi3_highpart" 682 [(set (match_operand:SI 0 "register_operand" "=r") 683 (truncate:SI 684 (lshiftrt:DI 685 (mult:DI (zero_extend:DI 686 (match_operand:SI 1 "register_operand" "r")) 687 (sign_extend:DI 688 (match_operand:SI 2 "register_operand" "r"))) 689 (const_int 32))))] 690 "TARGET_MUL && !TARGET_64BIT" 691 "mulhsu\t%0,%2,%1" 692 [(set_attr "type" "imul") 693 (set_attr "mode" "SI")]) 694 695;; 696;; .................... 697;; 698;; DIVISION and REMAINDER 699;; 700;; .................... 701;; 702 703(define_insn "<optab>si3" 704 [(set (match_operand:SI 0 "register_operand" "=r") 705 (any_div:SI (match_operand:SI 1 "register_operand" "r") 706 (match_operand:SI 2 "register_operand" "r")))] 707 "TARGET_DIV" 708 { return TARGET_64BIT ? "<insn>w\t%0,%1,%2" : "<insn>\t%0,%1,%2"; } 709 [(set_attr "type" "idiv") 710 (set_attr "mode" "SI")]) 711 712(define_insn "<optab>di3" 713 [(set (match_operand:DI 0 "register_operand" "=r") 714 (any_div:DI (match_operand:DI 1 "register_operand" "r") 715 (match_operand:DI 2 "register_operand" "r")))] 716 "TARGET_DIV && TARGET_64BIT" 717 "<insn>\t%0,%1,%2" 718 [(set_attr "type" "idiv") 719 (set_attr "mode" "DI")]) 720 721(define_insn "*<optab>si3_extended" 722 [(set (match_operand:DI 0 "register_operand" "=r") 723 (sign_extend:DI 724 (any_div:SI (match_operand:SI 1 "register_operand" "r") 725 (match_operand:SI 2 "register_operand" "r"))))] 726 "TARGET_DIV && TARGET_64BIT" 727 "<insn>w\t%0,%1,%2" 728 [(set_attr "type" "idiv") 729 (set_attr "mode" "DI")]) 730 731(define_insn "div<mode>3" 732 [(set (match_operand:ANYF 0 "register_operand" "=f") 733 (div:ANYF (match_operand:ANYF 1 "register_operand" "f") 734 (match_operand:ANYF 2 "register_operand" "f")))] 735 "TARGET_HARD_FLOAT && TARGET_FDIV" 736 "fdiv.<fmt>\t%0,%1,%2" 737 [(set_attr "type" "fdiv") 738 (set_attr "mode" "<UNITMODE>")]) 739 740;; 741;; .................... 742;; 743;; SQUARE ROOT 744;; 745;; .................... 746 747(define_insn "sqrt<mode>2" 748 [(set (match_operand:ANYF 0 "register_operand" "=f") 749 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 750 "TARGET_HARD_FLOAT && TARGET_FDIV" 751{ 752 return "fsqrt.<fmt>\t%0,%1"; 753} 754 [(set_attr "type" "fsqrt") 755 (set_attr "mode" "<UNITMODE>")]) 756 757;; Floating point multiply accumulate instructions. 758 759;; a * b + c 760(define_insn "fma<mode>4" 761 [(set (match_operand:ANYF 0 "register_operand" "=f") 762 (fma:ANYF 763 (match_operand:ANYF 1 "register_operand" "f") 764 (match_operand:ANYF 2 "register_operand" "f") 765 (match_operand:ANYF 3 "register_operand" "f")))] 766 "TARGET_HARD_FLOAT" 767 "fmadd.<fmt>\t%0,%1,%2,%3" 768 [(set_attr "type" "fmadd") 769 (set_attr "mode" "<UNITMODE>")]) 770 771;; a * b - c 772(define_insn "fms<mode>4" 773 [(set (match_operand:ANYF 0 "register_operand" "=f") 774 (fma:ANYF 775 (match_operand:ANYF 1 "register_operand" "f") 776 (match_operand:ANYF 2 "register_operand" "f") 777 (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))] 778 "TARGET_HARD_FLOAT" 779 "fmsub.<fmt>\t%0,%1,%2,%3" 780 [(set_attr "type" "fmadd") 781 (set_attr "mode" "<UNITMODE>")]) 782 783;; -a * b - c 784(define_insn "fnms<mode>4" 785 [(set (match_operand:ANYF 0 "register_operand" "=f") 786 (fma:ANYF 787 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) 788 (match_operand:ANYF 2 "register_operand" "f") 789 (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))] 790 "TARGET_HARD_FLOAT" 791 "fnmadd.<fmt>\t%0,%1,%2,%3" 792 [(set_attr "type" "fmadd") 793 (set_attr "mode" "<UNITMODE>")]) 794 795;; -a * b + c 796(define_insn "fnma<mode>4" 797 [(set (match_operand:ANYF 0 "register_operand" "=f") 798 (fma:ANYF 799 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) 800 (match_operand:ANYF 2 "register_operand" "f") 801 (match_operand:ANYF 3 "register_operand" "f")))] 802 "TARGET_HARD_FLOAT" 803 "fnmsub.<fmt>\t%0,%1,%2,%3" 804 [(set_attr "type" "fmadd") 805 (set_attr "mode" "<UNITMODE>")]) 806 807;; -(-a * b - c), modulo signed zeros 808(define_insn "*fma<mode>4" 809 [(set (match_operand:ANYF 0 "register_operand" "=f") 810 (neg:ANYF 811 (fma:ANYF 812 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) 813 (match_operand:ANYF 2 "register_operand" "f") 814 (neg:ANYF (match_operand:ANYF 3 "register_operand" "f")))))] 815 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)" 816 "fmadd.<fmt>\t%0,%1,%2,%3" 817 [(set_attr "type" "fmadd") 818 (set_attr "mode" "<UNITMODE>")]) 819 820;; -(-a * b + c), modulo signed zeros 821(define_insn "*fms<mode>4" 822 [(set (match_operand:ANYF 0 "register_operand" "=f") 823 (neg:ANYF 824 (fma:ANYF 825 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) 826 (match_operand:ANYF 2 "register_operand" "f") 827 (match_operand:ANYF 3 "register_operand" "f"))))] 828 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)" 829 "fmsub.<fmt>\t%0,%1,%2,%3" 830 [(set_attr "type" "fmadd") 831 (set_attr "mode" "<UNITMODE>")]) 832 833;; -(a * b + c), modulo signed zeros 834(define_insn "*fnms<mode>4" 835 [(set (match_operand:ANYF 0 "register_operand" "=f") 836 (neg:ANYF 837 (fma:ANYF 838 (match_operand:ANYF 1 "register_operand" "f") 839 (match_operand:ANYF 2 "register_operand" "f") 840 (match_operand:ANYF 3 "register_operand" "f"))))] 841 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)" 842 "fnmadd.<fmt>\t%0,%1,%2,%3" 843 [(set_attr "type" "fmadd") 844 (set_attr "mode" "<UNITMODE>")]) 845 846;; -(a * b - c), modulo signed zeros 847(define_insn "*fnma<mode>4" 848 [(set (match_operand:ANYF 0 "register_operand" "=f") 849 (neg:ANYF 850 (fma:ANYF 851 (match_operand:ANYF 1 "register_operand" "f") 852 (match_operand:ANYF 2 "register_operand" "f") 853 (neg:ANYF (match_operand:ANYF 3 "register_operand" "f")))))] 854 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)" 855 "fnmsub.<fmt>\t%0,%1,%2,%3" 856 [(set_attr "type" "fmadd") 857 (set_attr "mode" "<UNITMODE>")]) 858 859;; 860;; .................... 861;; 862;; SIGN INJECTION 863;; 864;; .................... 865 866(define_insn "abs<mode>2" 867 [(set (match_operand:ANYF 0 "register_operand" "=f") 868 (abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 869 "TARGET_HARD_FLOAT" 870 "fabs.<fmt>\t%0,%1" 871 [(set_attr "type" "fmove") 872 (set_attr "mode" "<UNITMODE>")]) 873 874(define_insn "copysign<mode>3" 875 [(set (match_operand:ANYF 0 "register_operand" "=f") 876 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f") 877 (match_operand:ANYF 2 "register_operand" "f")] 878 UNSPEC_COPYSIGN))] 879 "TARGET_HARD_FLOAT" 880 "fsgnj.<fmt>\t%0,%1,%2" 881 [(set_attr "type" "fmove") 882 (set_attr "mode" "<UNITMODE>")]) 883 884(define_insn "neg<mode>2" 885 [(set (match_operand:ANYF 0 "register_operand" "=f") 886 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))] 887 "TARGET_HARD_FLOAT" 888 "fneg.<fmt>\t%0,%1" 889 [(set_attr "type" "fmove") 890 (set_attr "mode" "<UNITMODE>")]) 891 892;; 893;; .................... 894;; 895;; MIN/MAX 896;; 897;; .................... 898 899(define_insn "smin<mode>3" 900 [(set (match_operand:ANYF 0 "register_operand" "=f") 901 (smin:ANYF (match_operand:ANYF 1 "register_operand" "f") 902 (match_operand:ANYF 2 "register_operand" "f")))] 903 "TARGET_HARD_FLOAT" 904 "fmin.<fmt>\t%0,%1,%2" 905 [(set_attr "type" "fmove") 906 (set_attr "mode" "<UNITMODE>")]) 907 908(define_insn "smax<mode>3" 909 [(set (match_operand:ANYF 0 "register_operand" "=f") 910 (smax:ANYF (match_operand:ANYF 1 "register_operand" "f") 911 (match_operand:ANYF 2 "register_operand" "f")))] 912 "TARGET_HARD_FLOAT" 913 "fmax.<fmt>\t%0,%1,%2" 914 [(set_attr "type" "fmove") 915 (set_attr "mode" "<UNITMODE>")]) 916 917;; 918;; .................... 919;; 920;; LOGICAL 921;; 922;; .................... 923;; 924 925;; For RV64, we don't expose the SImode operations to the rtl expanders, 926;; but SImode versions exist for combine. 927 928(define_insn "<optab><mode>3" 929 [(set (match_operand:X 0 "register_operand" "=r,r") 930 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r") 931 (match_operand:X 2 "arith_operand" "r,I")))] 932 "" 933 "<insn>\t%0,%1,%2" 934 [(set_attr "type" "logical") 935 (set_attr "mode" "<MODE>")]) 936 937(define_insn "*<optab>si3_internal" 938 [(set (match_operand:SI 0 "register_operand" "=r,r") 939 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r") 940 (match_operand:SI 2 "arith_operand" "r,I")))] 941 "TARGET_64BIT" 942 "<insn>\t%0,%1,%2" 943 [(set_attr "type" "logical") 944 (set_attr "mode" "SI")]) 945 946(define_insn "one_cmpl<mode>2" 947 [(set (match_operand:X 0 "register_operand" "=r") 948 (not:X (match_operand:X 1 "register_operand" "r")))] 949 "" 950 "not\t%0,%1" 951 [(set_attr "type" "logical") 952 (set_attr "mode" "<MODE>")]) 953 954(define_insn "*one_cmplsi2_internal" 955 [(set (match_operand:SI 0 "register_operand" "=r") 956 (not:SI (match_operand:SI 1 "register_operand" "r")))] 957 "TARGET_64BIT" 958 "not\t%0,%1" 959 [(set_attr "type" "logical") 960 (set_attr "mode" "SI")]) 961 962;; 963;; .................... 964;; 965;; TRUNCATION 966;; 967;; .................... 968 969(define_insn "truncdfsf2" 970 [(set (match_operand:SF 0 "register_operand" "=f") 971 (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] 972 "TARGET_DOUBLE_FLOAT" 973 "fcvt.s.d\t%0,%1" 974 [(set_attr "type" "fcvt") 975 (set_attr "mode" "SF")]) 976 977;; 978;; .................... 979;; 980;; ZERO EXTENSION 981;; 982;; .................... 983 984;; Extension insns. 985 986(define_insn_and_split "zero_extendsidi2" 987 [(set (match_operand:DI 0 "register_operand" "=r,r") 988 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))] 989 "TARGET_64BIT" 990 "@ 991 # 992 lwu\t%0,%1" 993 "&& reload_completed && REG_P (operands[1])" 994 [(set (match_dup 0) 995 (ashift:DI (match_dup 1) (const_int 32))) 996 (set (match_dup 0) 997 (lshiftrt:DI (match_dup 0) (const_int 32)))] 998 { operands[1] = gen_lowpart (DImode, operands[1]); } 999 [(set_attr "move_type" "shift_shift,load") 1000 (set_attr "mode" "DI")]) 1001 1002(define_insn_and_split "zero_extendhi<GPR:mode>2" 1003 [(set (match_operand:GPR 0 "register_operand" "=r,r") 1004 (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))] 1005 "" 1006 "@ 1007 # 1008 lhu\t%0,%1" 1009 "&& reload_completed && REG_P (operands[1])" 1010 [(set (match_dup 0) 1011 (ashift:GPR (match_dup 1) (match_dup 2))) 1012 (set (match_dup 0) 1013 (lshiftrt:GPR (match_dup 0) (match_dup 2)))] 1014 { 1015 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]); 1016 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16); 1017 } 1018 [(set_attr "move_type" "shift_shift,load") 1019 (set_attr "mode" "<GPR:MODE>")]) 1020 1021(define_insn "zero_extendqi<SUPERQI:mode>2" 1022 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r") 1023 (zero_extend:SUPERQI 1024 (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 1025 "" 1026 "@ 1027 and\t%0,%1,0xff 1028 lbu\t%0,%1" 1029 [(set_attr "move_type" "andi,load") 1030 (set_attr "mode" "<SUPERQI:MODE>")]) 1031 1032;; 1033;; .................... 1034;; 1035;; SIGN EXTENSION 1036;; 1037;; .................... 1038 1039(define_insn "extendsidi2" 1040 [(set (match_operand:DI 0 "register_operand" "=r,r") 1041 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))] 1042 "TARGET_64BIT" 1043 "@ 1044 sext.w\t%0,%1 1045 lw\t%0,%1" 1046 [(set_attr "move_type" "move,load") 1047 (set_attr "mode" "DI")]) 1048 1049(define_insn_and_split "extend<SHORT:mode><SUPERQI:mode>2" 1050 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r") 1051 (sign_extend:SUPERQI 1052 (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))] 1053 "" 1054 "@ 1055 # 1056 l<SHORT:size>\t%0,%1" 1057 "&& reload_completed && REG_P (operands[1])" 1058 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) 1059 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))] 1060{ 1061 operands[0] = gen_lowpart (SImode, operands[0]); 1062 operands[1] = gen_lowpart (SImode, operands[1]); 1063 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode) 1064 - GET_MODE_BITSIZE (<SHORT:MODE>mode)); 1065} 1066 [(set_attr "move_type" "shift_shift,load") 1067 (set_attr "mode" "SI")]) 1068 1069(define_insn "extendsfdf2" 1070 [(set (match_operand:DF 0 "register_operand" "=f") 1071 (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] 1072 "TARGET_DOUBLE_FLOAT" 1073 "fcvt.d.s\t%0,%1" 1074 [(set_attr "type" "fcvt") 1075 (set_attr "mode" "DF")]) 1076 1077;; 1078;; .................... 1079;; 1080;; CONVERSIONS 1081;; 1082;; .................... 1083 1084(define_insn "fix_trunc<ANYF:mode><GPR:mode>2" 1085 [(set (match_operand:GPR 0 "register_operand" "=r") 1086 (fix:GPR (match_operand:ANYF 1 "register_operand" "f")))] 1087 "TARGET_HARD_FLOAT" 1088 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz" 1089 [(set_attr "type" "fcvt") 1090 (set_attr "mode" "<ANYF:MODE>")]) 1091 1092(define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2" 1093 [(set (match_operand:GPR 0 "register_operand" "=r") 1094 (unsigned_fix:GPR (match_operand:ANYF 1 "register_operand" "f")))] 1095 "TARGET_HARD_FLOAT" 1096 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz" 1097 [(set_attr "type" "fcvt") 1098 (set_attr "mode" "<ANYF:MODE>")]) 1099 1100(define_insn "float<GPR:mode><ANYF:mode>2" 1101 [(set (match_operand:ANYF 0 "register_operand" "=f") 1102 (float:ANYF (match_operand:GPR 1 "reg_or_0_operand" "rJ")))] 1103 "TARGET_HARD_FLOAT" 1104 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1" 1105 [(set_attr "type" "fcvt") 1106 (set_attr "mode" "<ANYF:MODE>")]) 1107 1108(define_insn "floatuns<GPR:mode><ANYF:mode>2" 1109 [(set (match_operand:ANYF 0 "register_operand" "=f") 1110 (unsigned_float:ANYF (match_operand:GPR 1 "reg_or_0_operand" "rJ")))] 1111 "TARGET_HARD_FLOAT" 1112 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1" 1113 [(set_attr "type" "fcvt") 1114 (set_attr "mode" "<ANYF:MODE>")]) 1115 1116(define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2" 1117 [(set (match_operand:GPR 0 "register_operand" "=r") 1118 (unspec:GPR [(match_operand:ANYF 1 "register_operand" "f")] 1119 RINT))] 1120 "TARGET_HARD_FLOAT" 1121 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>" 1122 [(set_attr "type" "fcvt") 1123 (set_attr "mode" "<ANYF:MODE>")]) 1124 1125;; 1126;; .................... 1127;; 1128;; DATA MOVEMENT 1129;; 1130;; .................... 1131 1132;; Lower-level instructions for loading an address from the GOT. 1133;; We could use MEMs, but an unspec gives more optimization 1134;; opportunities. 1135 1136(define_insn "got_load<mode>" 1137 [(set (match_operand:P 0 "register_operand" "=r") 1138 (unspec:P [(match_operand:P 1 "symbolic_operand" "")] 1139 UNSPEC_LOAD_GOT))] 1140 "" 1141 "la\t%0,%1" 1142 [(set_attr "got" "load") 1143 (set_attr "mode" "<MODE>")]) 1144 1145(define_insn "tls_add_tp_le<mode>" 1146 [(set (match_operand:P 0 "register_operand" "=r") 1147 (unspec:P [(match_operand:P 1 "register_operand" "r") 1148 (match_operand:P 2 "register_operand" "r") 1149 (match_operand:P 3 "symbolic_operand" "")] 1150 UNSPEC_TLS_LE))] 1151 "" 1152 "add\t%0,%1,%2,%%tprel_add(%3)" 1153 [(set_attr "type" "arith") 1154 (set_attr "mode" "<MODE>")]) 1155 1156(define_insn "got_load_tls_gd<mode>" 1157 [(set (match_operand:P 0 "register_operand" "=r") 1158 (unspec:P [(match_operand:P 1 "symbolic_operand" "")] 1159 UNSPEC_TLS_GD))] 1160 "" 1161 "la.tls.gd\t%0,%1" 1162 [(set_attr "got" "load") 1163 (set_attr "mode" "<MODE>")]) 1164 1165(define_insn "got_load_tls_ie<mode>" 1166 [(set (match_operand:P 0 "register_operand" "=r") 1167 (unspec:P [(match_operand:P 1 "symbolic_operand" "")] 1168 UNSPEC_TLS_IE))] 1169 "" 1170 "la.tls.ie\t%0,%1" 1171 [(set_attr "got" "load") 1172 (set_attr "mode" "<MODE>")]) 1173 1174(define_insn "auipc<mode>" 1175 [(set (match_operand:P 0 "register_operand" "=r") 1176 (unspec:P [(match_operand:P 1 "symbolic_operand" "") 1177 (match_operand:P 2 "const_int_operand") 1178 (pc)] 1179 UNSPEC_AUIPC))] 1180 "" 1181 ".LA%2: auipc\t%0,%h1" 1182 [(set_attr "type" "arith") 1183 (set_attr "cannot_copy" "yes")]) 1184 1185;; Instructions for adding the low 12 bits of an address to a register. 1186;; Operand 2 is the address: riscv_print_operand works out which relocation 1187;; should be applied. 1188 1189(define_insn "*low<mode>" 1190 [(set (match_operand:P 0 "register_operand" "=r") 1191 (lo_sum:P (match_operand:P 1 "register_operand" "r") 1192 (match_operand:P 2 "symbolic_operand" "")))] 1193 "" 1194 "addi\t%0,%1,%R2" 1195 [(set_attr "type" "arith") 1196 (set_attr "mode" "<MODE>")]) 1197 1198;; Allow combine to split complex const_int load sequences, using operand 2 1199;; to store the intermediate results. See move_operand for details. 1200(define_split 1201 [(set (match_operand:GPR 0 "register_operand") 1202 (match_operand:GPR 1 "splittable_const_int_operand")) 1203 (clobber (match_operand:GPR 2 "register_operand"))] 1204 "" 1205 [(const_int 0)] 1206{ 1207 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1])); 1208 DONE; 1209}) 1210 1211;; Likewise, for symbolic operands. 1212(define_split 1213 [(set (match_operand:P 0 "register_operand") 1214 (match_operand:P 1)) 1215 (clobber (match_operand:P 2 "register_operand"))] 1216 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)" 1217 [(set (match_dup 0) (match_dup 3))] 1218{ 1219 riscv_split_symbol (operands[2], operands[1], 1220 MAX_MACHINE_MODE, &operands[3]); 1221}) 1222 1223;; 64-bit integer moves 1224 1225(define_expand "movdi" 1226 [(set (match_operand:DI 0 "") 1227 (match_operand:DI 1 ""))] 1228 "" 1229{ 1230 if (riscv_legitimize_move (DImode, operands[0], operands[1])) 1231 DONE; 1232}) 1233 1234(define_insn "*movdi_32bit" 1235 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m") 1236 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))] 1237 "!TARGET_64BIT 1238 && (register_operand (operands[0], DImode) 1239 || reg_or_0_operand (operands[1], DImode))" 1240 { return riscv_output_move (operands[0], operands[1]); } 1241 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore") 1242 (set_attr "mode" "DI")]) 1243 1244(define_insn "*movdi_64bit" 1245 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m,*f,*f,*r,*f,*m") 1246 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))] 1247 "TARGET_64BIT 1248 && (register_operand (operands[0], DImode) 1249 || reg_or_0_operand (operands[1], DImode))" 1250 { return riscv_output_move (operands[0], operands[1]); } 1251 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore") 1252 (set_attr "mode" "DI")]) 1253 1254;; 32-bit Integer moves 1255 1256(define_expand "mov<mode>" 1257 [(set (match_operand:MOVE32 0 "") 1258 (match_operand:MOVE32 1 ""))] 1259 "" 1260{ 1261 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1])) 1262 DONE; 1263}) 1264 1265(define_insn "*movsi_internal" 1266 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,*r,*m") 1267 (match_operand:SI 1 "move_operand" "r,T,m,rJ,*r*J,*m,*f,*f"))] 1268 "(register_operand (operands[0], SImode) 1269 || reg_or_0_operand (operands[1], SImode))" 1270 { return riscv_output_move (operands[0], operands[1]); } 1271 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore") 1272 (set_attr "mode" "SI")]) 1273 1274;; 16-bit Integer moves 1275 1276;; Unlike most other insns, the move insns can't be split with 1277;; different predicates, because register spilling and other parts of 1278;; the compiler, have memoized the insn number already. 1279;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. 1280 1281(define_expand "movhi" 1282 [(set (match_operand:HI 0 "") 1283 (match_operand:HI 1 ""))] 1284 "" 1285{ 1286 if (riscv_legitimize_move (HImode, operands[0], operands[1])) 1287 DONE; 1288}) 1289 1290(define_insn "*movhi_internal" 1291 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r") 1292 (match_operand:HI 1 "move_operand" "r,T,m,rJ,*r*J,*f"))] 1293 "(register_operand (operands[0], HImode) 1294 || reg_or_0_operand (operands[1], HImode))" 1295 { return riscv_output_move (operands[0], operands[1]); } 1296 [(set_attr "move_type" "move,const,load,store,mtc,mfc") 1297 (set_attr "mode" "HI")]) 1298 1299;; HImode constant generation; see riscv_move_integer for details. 1300;; si+si->hi without truncation is legal because of TRULY_NOOP_TRUNCATION. 1301 1302(define_insn "*add<mode>hi3" 1303 [(set (match_operand:HI 0 "register_operand" "=r,r") 1304 (plus:HI (match_operand:HISI 1 "register_operand" "r,r") 1305 (match_operand:HISI 2 "arith_operand" "r,I")))] 1306 "" 1307 { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; } 1308 [(set_attr "type" "arith") 1309 (set_attr "mode" "HI")]) 1310 1311(define_insn "*xor<mode>hi3" 1312 [(set (match_operand:HI 0 "register_operand" "=r,r") 1313 (xor:HI (match_operand:HISI 1 "register_operand" "r,r") 1314 (match_operand:HISI 2 "arith_operand" "r,I")))] 1315 "" 1316 "xor\t%0,%1,%2" 1317 [(set_attr "type" "logical") 1318 (set_attr "mode" "HI")]) 1319 1320;; 8-bit Integer moves 1321 1322(define_expand "movqi" 1323 [(set (match_operand:QI 0 "") 1324 (match_operand:QI 1 ""))] 1325 "" 1326{ 1327 if (riscv_legitimize_move (QImode, operands[0], operands[1])) 1328 DONE; 1329}) 1330 1331(define_insn "*movqi_internal" 1332 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r") 1333 (match_operand:QI 1 "move_operand" "r,I,m,rJ,*r*J,*f"))] 1334 "(register_operand (operands[0], QImode) 1335 || reg_or_0_operand (operands[1], QImode))" 1336 { return riscv_output_move (operands[0], operands[1]); } 1337 [(set_attr "move_type" "move,const,load,store,mtc,mfc") 1338 (set_attr "mode" "QI")]) 1339 1340;; 32-bit floating point moves 1341 1342(define_expand "movsf" 1343 [(set (match_operand:SF 0 "") 1344 (match_operand:SF 1 ""))] 1345 "" 1346{ 1347 if (riscv_legitimize_move (SFmode, operands[0], operands[1])) 1348 DONE; 1349}) 1350 1351(define_insn "*movsf_hardfloat" 1352 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,*r,*r,*m") 1353 (match_operand:SF 1 "move_operand" "f,G,m,f,G,*r,*f,*G*r,*m,*r"))] 1354 "TARGET_HARD_FLOAT 1355 && (register_operand (operands[0], SFmode) 1356 || reg_or_0_operand (operands[1], SFmode))" 1357 { return riscv_output_move (operands[0], operands[1]); } 1358 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") 1359 (set_attr "mode" "SF")]) 1360 1361(define_insn "*movsf_softfloat" 1362 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") 1363 (match_operand:SF 1 "move_operand" "Gr,m,r"))] 1364 "!TARGET_HARD_FLOAT 1365 && (register_operand (operands[0], SFmode) 1366 || reg_or_0_operand (operands[1], SFmode))" 1367 { return riscv_output_move (operands[0], operands[1]); } 1368 [(set_attr "move_type" "move,load,store") 1369 (set_attr "mode" "SF")]) 1370 1371;; 64-bit floating point moves 1372 1373(define_expand "movdf" 1374 [(set (match_operand:DF 0 "") 1375 (match_operand:DF 1 ""))] 1376 "" 1377{ 1378 if (riscv_legitimize_move (DFmode, operands[0], operands[1])) 1379 DONE; 1380}) 1381 1382;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead. 1383;; (However, we can still use fcvt.d.w to zero a floating-point register.) 1384(define_insn "*movdf_hardfloat_rv32" 1385 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*r,*r,*m") 1386 (match_operand:DF 1 "move_operand" "f,G,m,f,G,*r*G,*m,*r"))] 1387 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT 1388 && (register_operand (operands[0], DFmode) 1389 || reg_or_0_operand (operands[1], DFmode))" 1390 { return riscv_output_move (operands[0], operands[1]); } 1391 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store") 1392 (set_attr "mode" "DF")]) 1393 1394(define_insn "*movdf_hardfloat_rv64" 1395 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,*r,*r,*m") 1396 (match_operand:DF 1 "move_operand" "f,G,m,f,G,*r,*f,*r*G,*m,*r"))] 1397 "TARGET_64BIT && TARGET_DOUBLE_FLOAT 1398 && (register_operand (operands[0], DFmode) 1399 || reg_or_0_operand (operands[1], DFmode))" 1400 { return riscv_output_move (operands[0], operands[1]); } 1401 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") 1402 (set_attr "mode" "DF")]) 1403 1404(define_insn "*movdf_softfloat" 1405 [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m") 1406 (match_operand:DF 1 "move_operand" "rG,m,rG"))] 1407 "!TARGET_DOUBLE_FLOAT 1408 && (register_operand (operands[0], DFmode) 1409 || reg_or_0_operand (operands[1], DFmode))" 1410 { return riscv_output_move (operands[0], operands[1]); } 1411 [(set_attr "move_type" "move,load,store") 1412 (set_attr "mode" "DF")]) 1413 1414(define_split 1415 [(set (match_operand:MOVE64 0 "nonimmediate_operand") 1416 (match_operand:MOVE64 1 "move_operand"))] 1417 "reload_completed 1418 && riscv_split_64bit_move_p (operands[0], operands[1])" 1419 [(const_int 0)] 1420{ 1421 riscv_split_doubleword_move (operands[0], operands[1]); 1422 DONE; 1423}) 1424 1425;; Expand in-line code to clear the instruction cache between operand[0] and 1426;; operand[1]. 1427(define_expand "clear_cache" 1428 [(match_operand 0 "pmode_register_operand") 1429 (match_operand 1 "pmode_register_operand")] 1430 "" 1431{ 1432#ifdef ICACHE_FLUSH_FUNC 1433 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC), 1434 LCT_NORMAL, VOIDmode, 3, operands[0], Pmode, 1435 operands[1], Pmode, const0_rtx, Pmode); 1436#else 1437 emit_insn (gen_fence_i ()); 1438#endif 1439 DONE; 1440}) 1441 1442(define_insn "fence" 1443 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)] 1444 "" 1445 "%|fence%-") 1446 1447(define_insn "fence_i" 1448 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)] 1449 "" 1450 "fence.i") 1451 1452;; 1453;; .................... 1454;; 1455;; SHIFTS 1456;; 1457;; .................... 1458 1459(define_insn "<optab>si3" 1460 [(set (match_operand:SI 0 "register_operand" "=r") 1461 (any_shift:SI (match_operand:SI 1 "register_operand" "r") 1462 (match_operand:SI 2 "arith_operand" "rI")))] 1463 "" 1464{ 1465 if (GET_CODE (operands[2]) == CONST_INT) 1466 operands[2] = GEN_INT (INTVAL (operands[2]) 1467 & (GET_MODE_BITSIZE (SImode) - 1)); 1468 1469 return TARGET_64BIT ? "<insn>w\t%0,%1,%2" : "<insn>\t%0,%1,%2"; 1470} 1471 [(set_attr "type" "shift") 1472 (set_attr "mode" "SI")]) 1473 1474(define_insn "<optab>di3" 1475 [(set (match_operand:DI 0 "register_operand" "=r") 1476 (any_shift:DI (match_operand:DI 1 "register_operand" "r") 1477 (match_operand:DI 2 "arith_operand" "rI")))] 1478 "TARGET_64BIT" 1479{ 1480 if (GET_CODE (operands[2]) == CONST_INT) 1481 operands[2] = GEN_INT (INTVAL (operands[2]) 1482 & (GET_MODE_BITSIZE (DImode) - 1)); 1483 1484 return "<insn>\t%0,%1,%2"; 1485} 1486 [(set_attr "type" "shift") 1487 (set_attr "mode" "DI")]) 1488 1489(define_insn "*<optab>si3_extend" 1490 [(set (match_operand:DI 0 "register_operand" "=r") 1491 (sign_extend:DI 1492 (any_shift:SI (match_operand:SI 1 "register_operand" "r") 1493 (match_operand:SI 2 "arith_operand" "rI"))))] 1494 "TARGET_64BIT" 1495{ 1496 if (GET_CODE (operands[2]) == CONST_INT) 1497 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); 1498 1499 return "<insn>w\t%0,%1,%2"; 1500} 1501 [(set_attr "type" "shift") 1502 (set_attr "mode" "SI")]) 1503 1504;; 1505;; .................... 1506;; 1507;; CONDITIONAL BRANCHES 1508;; 1509;; .................... 1510 1511;; Conditional branches 1512 1513(define_insn "*branch_order<mode>" 1514 [(set (pc) 1515 (if_then_else 1516 (match_operator 1 "order_operator" 1517 [(match_operand:X 2 "register_operand" "r") 1518 (match_operand:X 3 "register_operand" "r")]) 1519 (label_ref (match_operand 0 "" "")) 1520 (pc)))] 1521 "" 1522 "b%C1\t%2,%3,%0" 1523 [(set_attr "type" "branch") 1524 (set_attr "mode" "none")]) 1525 1526(define_insn "*branch_zero<mode>" 1527 [(set (pc) 1528 (if_then_else 1529 (match_operator 1 "signed_order_operator" 1530 [(match_operand:X 2 "register_operand" "r") 1531 (const_int 0)]) 1532 (label_ref (match_operand 0 "" "")) 1533 (pc)))] 1534 "" 1535 "b%C1z\t%2,%0" 1536 [(set_attr "type" "branch") 1537 (set_attr "mode" "none")]) 1538 1539;; Used to implement built-in functions. 1540(define_expand "condjump" 1541 [(set (pc) 1542 (if_then_else (match_operand 0) 1543 (label_ref (match_operand 1)) 1544 (pc)))]) 1545 1546(define_expand "cbranch<mode>4" 1547 [(set (pc) 1548 (if_then_else (match_operator 0 "comparison_operator" 1549 [(match_operand:BR 1 "register_operand") 1550 (match_operand:BR 2 "nonmemory_operand")]) 1551 (label_ref (match_operand 3 "")) 1552 (pc)))] 1553 "" 1554{ 1555 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]), 1556 operands[1], operands[2]); 1557 DONE; 1558}) 1559 1560(define_expand "cbranch<mode>4" 1561 [(set (pc) 1562 (if_then_else (match_operator 0 "fp_branch_comparison" 1563 [(match_operand:ANYF 1 "register_operand") 1564 (match_operand:ANYF 2 "register_operand")]) 1565 (label_ref (match_operand 3 "")) 1566 (pc)))] 1567 "TARGET_HARD_FLOAT" 1568{ 1569 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]), 1570 operands[1], operands[2]); 1571 DONE; 1572}) 1573 1574(define_insn_and_split "*branch_on_bit<X:mode>" 1575 [(set (pc) 1576 (if_then_else 1577 (match_operator 0 "equality_operator" 1578 [(zero_extract:X (match_operand:X 2 "register_operand" "r") 1579 (const_int 1) 1580 (match_operand 3 "branch_on_bit_operand")) 1581 (const_int 0)]) 1582 (label_ref (match_operand 1)) 1583 (pc))) 1584 (clobber (match_scratch:X 4 "=&r"))] 1585 "" 1586 "#" 1587 "reload_completed" 1588 [(set (match_dup 4) 1589 (ashift:X (match_dup 2) (match_dup 3))) 1590 (set (pc) 1591 (if_then_else 1592 (match_op_dup 0 [(match_dup 4) (const_int 0)]) 1593 (label_ref (match_operand 1)) 1594 (pc)))] 1595{ 1596 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]); 1597 operands[3] = GEN_INT (shift); 1598 1599 if (GET_CODE (operands[0]) == EQ) 1600 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx); 1601 else 1602 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx); 1603}) 1604 1605(define_insn_and_split "*branch_on_bit_range<X:mode>" 1606 [(set (pc) 1607 (if_then_else 1608 (match_operator 0 "equality_operator" 1609 [(zero_extract:X (match_operand:X 2 "register_operand" "r") 1610 (match_operand 3 "branch_on_bit_operand") 1611 (const_int 0)) 1612 (const_int 0)]) 1613 (label_ref (match_operand 1)) 1614 (pc))) 1615 (clobber (match_scratch:X 4 "=&r"))] 1616 "" 1617 "#" 1618 "reload_completed" 1619 [(set (match_dup 4) 1620 (ashift:X (match_dup 2) (match_dup 3))) 1621 (set (pc) 1622 (if_then_else 1623 (match_op_dup 0 [(match_dup 4) (const_int 0)]) 1624 (label_ref (match_operand 1)) 1625 (pc)))] 1626{ 1627 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3])); 1628}) 1629 1630;; 1631;; .................... 1632;; 1633;; SETTING A REGISTER FROM A COMPARISON 1634;; 1635;; .................... 1636 1637;; Destination is always set in SI mode. 1638 1639(define_expand "cstore<mode>4" 1640 [(set (match_operand:SI 0 "register_operand") 1641 (match_operator:SI 1 "order_operator" 1642 [(match_operand:GPR 2 "register_operand") 1643 (match_operand:GPR 3 "nonmemory_operand")]))] 1644 "" 1645{ 1646 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2], 1647 operands[3]); 1648 DONE; 1649}) 1650 1651(define_expand "cstore<mode>4" 1652 [(set (match_operand:SI 0 "register_operand") 1653 (match_operator:SI 1 "fp_scc_comparison" 1654 [(match_operand:ANYF 2 "register_operand") 1655 (match_operand:ANYF 3 "register_operand")]))] 1656 "TARGET_HARD_FLOAT" 1657{ 1658 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2], 1659 operands[3]); 1660 DONE; 1661}) 1662 1663(define_insn "*cstore<ANYF:mode><X:mode>4" 1664 [(set (match_operand:X 0 "register_operand" "=r") 1665 (match_operator:X 1 "fp_native_comparison" 1666 [(match_operand:ANYF 2 "register_operand" "f") 1667 (match_operand:ANYF 3 "register_operand" "f")]))] 1668 "TARGET_HARD_FLOAT" 1669 "f%C1.<fmt>\t%0,%2,%3" 1670 [(set_attr "type" "fcmp") 1671 (set_attr "mode" "<UNITMODE>")]) 1672 1673(define_insn "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4" 1674 [(set (match_operand:X 0 "register_operand" "=r") 1675 (unspec:X 1676 [(match_operand:ANYF 1 "register_operand" "f") 1677 (match_operand:ANYF 2 "register_operand" "f")] 1678 QUIET_COMPARISON)) 1679 (clobber (match_scratch:X 3 "=&r"))] 1680 "TARGET_HARD_FLOAT" 1681 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3" 1682 [(set_attr "type" "fcmp") 1683 (set_attr "mode" "<UNITMODE>") 1684 (set (attr "length") (const_int 12))]) 1685 1686(define_insn "*seq_zero_<X:mode><GPR:mode>" 1687 [(set (match_operand:GPR 0 "register_operand" "=r") 1688 (eq:GPR (match_operand:X 1 "register_operand" "r") 1689 (const_int 0)))] 1690 "" 1691 "seqz\t%0,%1" 1692 [(set_attr "type" "slt") 1693 (set_attr "mode" "<X:MODE>")]) 1694 1695(define_insn "*sne_zero_<X:mode><GPR:mode>" 1696 [(set (match_operand:GPR 0 "register_operand" "=r") 1697 (ne:GPR (match_operand:X 1 "register_operand" "r") 1698 (const_int 0)))] 1699 "" 1700 "snez\t%0,%1" 1701 [(set_attr "type" "slt") 1702 (set_attr "mode" "<X:MODE>")]) 1703 1704(define_insn "*sgt<u>_<X:mode><GPR:mode>" 1705 [(set (match_operand:GPR 0 "register_operand" "=r") 1706 (any_gt:GPR (match_operand:X 1 "register_operand" "r") 1707 (match_operand:X 2 "reg_or_0_operand" "rJ")))] 1708 "" 1709 "sgt<u>\t%0,%1,%z2" 1710 [(set_attr "type" "slt") 1711 (set_attr "mode" "<X:MODE>")]) 1712 1713(define_insn "*sge<u>_<X:mode><GPR:mode>" 1714 [(set (match_operand:GPR 0 "register_operand" "=r") 1715 (any_ge:GPR (match_operand:X 1 "register_operand" "r") 1716 (const_int 1)))] 1717 "" 1718 "slt<u>\t%0,zero,%1" 1719 [(set_attr "type" "slt") 1720 (set_attr "mode" "<MODE>")]) 1721 1722(define_insn "*slt<u>_<X:mode><GPR:mode>" 1723 [(set (match_operand:GPR 0 "register_operand" "=r") 1724 (any_lt:GPR (match_operand:X 1 "register_operand" "r") 1725 (match_operand:X 2 "arith_operand" "rI")))] 1726 "" 1727 "slt<u>\t%0,%1,%2" 1728 [(set_attr "type" "slt") 1729 (set_attr "mode" "<MODE>")]) 1730 1731(define_insn "*sle<u>_<X:mode><GPR:mode>" 1732 [(set (match_operand:GPR 0 "register_operand" "=r") 1733 (any_le:GPR (match_operand:X 1 "register_operand" "r") 1734 (match_operand:X 2 "sle_operand" "")))] 1735 "" 1736{ 1737 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); 1738 return "slt<u>\t%0,%1,%2"; 1739} 1740 [(set_attr "type" "slt") 1741 (set_attr "mode" "<MODE>")]) 1742 1743;; 1744;; .................... 1745;; 1746;; UNCONDITIONAL BRANCHES 1747;; 1748;; .................... 1749 1750;; Unconditional branches. 1751 1752(define_insn "jump" 1753 [(set (pc) 1754 (label_ref (match_operand 0 "" "")))] 1755 "" 1756 "j\t%l0" 1757 [(set_attr "type" "jump") 1758 (set_attr "mode" "none")]) 1759 1760(define_expand "indirect_jump" 1761 [(set (pc) (match_operand 0 "register_operand"))] 1762 "" 1763{ 1764 operands[0] = force_reg (Pmode, operands[0]); 1765 if (Pmode == SImode) 1766 emit_jump_insn (gen_indirect_jumpsi (operands[0])); 1767 else 1768 emit_jump_insn (gen_indirect_jumpdi (operands[0])); 1769 DONE; 1770}) 1771 1772(define_insn "indirect_jump<mode>" 1773 [(set (pc) (match_operand:P 0 "register_operand" "l"))] 1774 "" 1775 "jr\t%0" 1776 [(set_attr "type" "jump") 1777 (set_attr "mode" "none")]) 1778 1779(define_expand "tablejump" 1780 [(set (pc) (match_operand 0 "register_operand" "")) 1781 (use (label_ref (match_operand 1 "" "")))] 1782 "" 1783{ 1784 if (CASE_VECTOR_PC_RELATIVE) 1785 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0], 1786 gen_rtx_LABEL_REF (Pmode, operands[1]), 1787 NULL_RTX, 0, OPTAB_DIRECT); 1788 1789 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode) 1790 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); 1791 else 1792 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); 1793 DONE; 1794}) 1795 1796(define_insn "tablejump<mode>" 1797 [(set (pc) (match_operand:GPR 0 "register_operand" "l")) 1798 (use (label_ref (match_operand 1 "" "")))] 1799 "" 1800 "jr\t%0" 1801 [(set_attr "type" "jump") 1802 (set_attr "mode" "none")]) 1803 1804;; 1805;; .................... 1806;; 1807;; Function prologue/epilogue 1808;; 1809;; .................... 1810;; 1811 1812(define_expand "prologue" 1813 [(const_int 1)] 1814 "" 1815{ 1816 riscv_expand_prologue (); 1817 DONE; 1818}) 1819 1820;; Block any insns from being moved before this point, since the 1821;; profiling call to mcount can use various registers that aren't 1822;; saved or used to pass arguments. 1823 1824(define_insn "blockage" 1825 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] 1826 "" 1827 "" 1828 [(set_attr "type" "ghost") 1829 (set_attr "mode" "none")]) 1830 1831(define_expand "epilogue" 1832 [(const_int 2)] 1833 "" 1834{ 1835 riscv_expand_epilogue (false); 1836 DONE; 1837}) 1838 1839(define_expand "sibcall_epilogue" 1840 [(const_int 2)] 1841 "" 1842{ 1843 riscv_expand_epilogue (true); 1844 DONE; 1845}) 1846 1847;; Trivial return. Make it look like a normal return insn as that 1848;; allows jump optimizations to work better. 1849 1850(define_expand "return" 1851 [(simple_return)] 1852 "riscv_can_use_return_insn ()" 1853 "") 1854 1855(define_insn "simple_return" 1856 [(simple_return)] 1857 "" 1858 "ret" 1859 [(set_attr "type" "jump") 1860 (set_attr "mode" "none")]) 1861 1862;; Normal return. 1863 1864(define_insn "simple_return_internal" 1865 [(simple_return) 1866 (use (match_operand 0 "pmode_register_operand" ""))] 1867 "" 1868 "jr\t%0" 1869 [(set_attr "type" "jump") 1870 (set_attr "mode" "none")]) 1871 1872;; This is used in compiling the unwind routines. 1873(define_expand "eh_return" 1874 [(use (match_operand 0 "general_operand"))] 1875 "" 1876{ 1877 if (GET_MODE (operands[0]) != word_mode) 1878 operands[0] = convert_to_mode (word_mode, operands[0], 0); 1879 if (TARGET_64BIT) 1880 emit_insn (gen_eh_set_lr_di (operands[0])); 1881 else 1882 emit_insn (gen_eh_set_lr_si (operands[0])); 1883 DONE; 1884}) 1885 1886;; Clobber the return address on the stack. We can't expand this 1887;; until we know where it will be put in the stack frame. 1888 1889(define_insn "eh_set_lr_si" 1890 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN) 1891 (clobber (match_scratch:SI 1 "=&r"))] 1892 "! TARGET_64BIT" 1893 "#") 1894 1895(define_insn "eh_set_lr_di" 1896 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN) 1897 (clobber (match_scratch:DI 1 "=&r"))] 1898 "TARGET_64BIT" 1899 "#") 1900 1901(define_split 1902 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN) 1903 (clobber (match_scratch 1))] 1904 "reload_completed" 1905 [(const_int 0)] 1906{ 1907 riscv_set_return_address (operands[0], operands[1]); 1908 DONE; 1909}) 1910 1911;; 1912;; .................... 1913;; 1914;; FUNCTION CALLS 1915;; 1916;; .................... 1917 1918(define_expand "sibcall" 1919 [(parallel [(call (match_operand 0 "") 1920 (match_operand 1 "")) 1921 (use (match_operand 2 "")) ;; next_arg_reg 1922 (use (match_operand 3 ""))])] ;; struct_value_size_rtx 1923 "" 1924{ 1925 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0)); 1926 emit_call_insn (gen_sibcall_internal (target, operands[1])); 1927 DONE; 1928}) 1929 1930(define_insn "sibcall_internal" 1931 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U")) 1932 (match_operand 1 "" ""))] 1933 "SIBLING_CALL_P (insn)" 1934 "@ 1935 jr\t%0 1936 tail\t%0 1937 tail\t%0@plt" 1938 [(set_attr "type" "call")]) 1939 1940(define_expand "sibcall_value" 1941 [(parallel [(set (match_operand 0 "") 1942 (call (match_operand 1 "") 1943 (match_operand 2 ""))) 1944 (use (match_operand 3 ""))])] ;; next_arg_reg 1945 "" 1946{ 1947 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0)); 1948 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2])); 1949 DONE; 1950}) 1951 1952(define_insn "sibcall_value_internal" 1953 [(set (match_operand 0 "" "") 1954 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U")) 1955 (match_operand 2 "" "")))] 1956 "SIBLING_CALL_P (insn)" 1957 "@ 1958 jr\t%1 1959 tail\t%1 1960 tail\t%1@plt" 1961 [(set_attr "type" "call")]) 1962 1963(define_expand "call" 1964 [(parallel [(call (match_operand 0 "") 1965 (match_operand 1 "")) 1966 (use (match_operand 2 "")) ;; next_arg_reg 1967 (use (match_operand 3 ""))])] ;; struct_value_size_rtx 1968 "" 1969{ 1970 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0)); 1971 emit_call_insn (gen_call_internal (target, operands[1])); 1972 DONE; 1973}) 1974 1975(define_insn "call_internal" 1976 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U")) 1977 (match_operand 1 "" "")) 1978 (clobber (reg:SI RETURN_ADDR_REGNUM))] 1979 "" 1980 "@ 1981 jalr\t%0 1982 call\t%0 1983 call\t%0@plt" 1984 [(set_attr "type" "call")]) 1985 1986(define_expand "call_value" 1987 [(parallel [(set (match_operand 0 "") 1988 (call (match_operand 1 "") 1989 (match_operand 2 ""))) 1990 (use (match_operand 3 ""))])] ;; next_arg_reg 1991 "" 1992{ 1993 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0)); 1994 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2])); 1995 DONE; 1996}) 1997 1998(define_insn "call_value_internal" 1999 [(set (match_operand 0 "" "") 2000 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U")) 2001 (match_operand 2 "" ""))) 2002 (clobber (reg:SI RETURN_ADDR_REGNUM))] 2003 "" 2004 "@ 2005 jalr\t%1 2006 call\t%1 2007 call\t%1@plt" 2008 [(set_attr "type" "call")]) 2009 2010;; Call subroutine returning any type. 2011 2012(define_expand "untyped_call" 2013 [(parallel [(call (match_operand 0 "") 2014 (const_int 0)) 2015 (match_operand 1 "") 2016 (match_operand 2 "")])] 2017 "" 2018{ 2019 int i; 2020 2021 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); 2022 2023 for (i = 0; i < XVECLEN (operands[2], 0); i++) 2024 { 2025 rtx set = XVECEXP (operands[2], 0, i); 2026 riscv_emit_move (SET_DEST (set), SET_SRC (set)); 2027 } 2028 2029 emit_insn (gen_blockage ()); 2030 DONE; 2031}) 2032 2033(define_insn "nop" 2034 [(const_int 0)] 2035 "" 2036 "nop" 2037 [(set_attr "type" "nop") 2038 (set_attr "mode" "none")]) 2039 2040(define_insn "trap" 2041 [(trap_if (const_int 1) (const_int 0))] 2042 "" 2043 "ebreak") 2044 2045(define_insn "gpr_save" 2046 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_SAVE) 2047 (clobber (reg:SI T0_REGNUM)) 2048 (clobber (reg:SI T1_REGNUM))] 2049 "" 2050 { return riscv_output_gpr_save (INTVAL (operands[0])); }) 2051 2052(define_insn "gpr_restore" 2053 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)] 2054 "" 2055 "tail\t__riscv_restore_%0") 2056 2057(define_insn "gpr_restore_return" 2058 [(return) 2059 (use (match_operand 0 "pmode_register_operand" "")) 2060 (const_int 0)] 2061 "" 2062 "") 2063 2064(define_insn "riscv_frflags" 2065 [(set (match_operand:SI 0 "register_operand" "=r") 2066 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))] 2067 "TARGET_HARD_FLOAT" 2068 "frflags %0") 2069 2070(define_insn "riscv_fsflags" 2071 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)] 2072 "TARGET_HARD_FLOAT" 2073 "fsflags %0") 2074 2075(define_insn "stack_tie<mode>" 2076 [(set (mem:BLK (scratch)) 2077 (unspec:BLK [(match_operand:X 0 "register_operand" "r") 2078 (match_operand:X 1 "register_operand" "r")] 2079 UNSPEC_TIE))] 2080 "" 2081 "" 2082 [(set_attr "length" "0")] 2083) 2084 2085(include "sync.md") 2086(include "peephole.md") 2087(include "pic.md") 2088(include "generic.md") 2089