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.
6 ;; This file is part of GCC.
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)
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.
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/>.
22 (define_c_enum "unspec" [
23 ;; Override return address for exception handling.
26 ;; Symbolic accesses. The order of this list must match that of
27 ;; enum riscv_symbol_type in riscv-protos.h.
36 ;; High part of PC-relative address.
39 ;; Floating-point unspecs.
50 (define_c_enum "unspecv" [
51 ;; Register save and restore.
55 ;; Floating-point unspecs.
59 ;; Blockage and synchronization.
66 [(RETURN_ADDR_REGNUM 1)
74 (include "predicates.md")
75 (include "constraints.md")
77 ;; ....................
81 ;; ....................
83 (define_attr "got" "unset,xgot_high,load"
84 (const_string "unset"))
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:
90 ;; andi a single ANDI instruction
91 ;; shift_shift a shift left followed by a shift right
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"))
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"))
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)))
112 (and (eq_attr "mode" "TI,TF")
113 (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
114 (const_string "yes")]
115 (const_string "no")))
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)
145 ;; ghost an instruction that produces no real code
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")
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")
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")
168 ;; These types of move are always split.
169 (eq_attr "move_type" "shift_shift")
170 (const_string "multi")
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")))
180 ;; Length of instruction in bytes.
181 (define_attr "length" ""
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)))
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)
194 ;; "Ghost" instructions occupy no space.
195 (eq_attr "type" "ghost") (const_int 0)
197 (eq_attr "got" "load") (const_int 8)
199 (eq_attr "type" "fcmp") (const_int 8)
201 ;; SHIFT_SHIFTs are decomposed into two separate instructions.
202 (eq_attr "move_type" "shift_shift")
205 ;; Check for doubleword moves that are decomposed into two
207 (and (eq_attr "move_type" "mtc,mfc,move")
208 (eq_attr "dword_mode" "yes"))
211 ;; Doubleword CONST{,N} moves are split into two word
213 (and (eq_attr "move_type" "const")
214 (eq_attr "dword_mode" "yes"))
215 (symbol_ref "riscv_split_const_insns (operands[1]) * 4")
217 ;; Otherwise, constants, loads and stores are handled by external
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")
225 ;; Is copying of this instruction disallowed?
226 (define_attr "cannot_copy" "no,yes" (const_string "no"))
228 ;; Describe a user's asm statement.
229 (define_asm_attributes
230 [(set_attr "type" "multi")])
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")])
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")])
240 ;; Likewise, but for XLEN-sized quantities.
241 (define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")])
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")])
247 ;; 32-bit moves for which we provide move patterns.
248 (define_mode_iterator MOVE32 [SI])
250 ;; 64-bit modes for which we provide move patterns.
251 (define_mode_iterator MOVE64 [DI DF])
253 ;; Iterator for sub-32-bit integer modes.
254 (define_mode_iterator SHORT [QI HI])
256 ;; Iterator for HImode constant generation.
257 (define_mode_iterator HISI [HI SI])
259 ;; Iterator for QImode extension patterns.
260 (define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")])
262 ;; Iterator for hardware integer modes narrower than XLEN.
263 (define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")])
265 ;; Iterator for hardware-supported integer modes.
266 (define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
268 ;; Iterator for hardware-supported floating-point modes.
269 (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
270 (DF "TARGET_DOUBLE_FLOAT")])
272 ;; This attribute gives the length suffix for a sign- or zero-extension
274 (define_mode_attr size [(QI "b") (HI "h")])
276 ;; Mode attributes for loads.
277 (define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
279 ;; Instruction names for stores.
280 (define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
282 ;; This attribute gives the best constraint to use for registers of
284 (define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
286 ;; This attribute gives the format suffix for floating-point operations.
287 (define_mode_attr fmt [(SF "s") (DF "d")])
289 ;; This attribute gives the integer suffix for floating-point conversions.
290 (define_mode_attr ifmt [(SI "w") (DI "l")])
292 ;; This attribute gives the format suffix for atomic memory operations.
293 (define_mode_attr amo [(SI "w") (DI "d")])
295 ;; This attribute gives the upper-case mode name for one unit of a
296 ;; floating-point mode.
297 (define_mode_attr UNITMODE [(SF "SF") (DF "DF")])
299 ;; This attribute gives the integer mode that has half the size of
300 ;; the controlling mode.
301 (define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")])
303 ;; Iterator and attributes for floating-point rounding instructions.
304 (define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND])
305 (define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")])
306 (define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")])
308 ;; Iterator and attributes for quiet comparisons.
309 (define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET])
310 (define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")])
312 ;; This code iterator allows signed and unsigned widening multiplications
313 ;; to use the same template.
314 (define_code_iterator any_extend [sign_extend zero_extend])
316 ;; This code iterator allows the two right shift instructions to be
317 ;; generated from the same template.
318 (define_code_iterator any_shiftrt [ashiftrt lshiftrt])
320 ;; This code iterator allows the three shift instructions to be generated
321 ;; from the same template.
322 (define_code_iterator any_shift [ashift ashiftrt lshiftrt])
324 ;; This code iterator allows the three bitwise instructions to be generated
325 ;; from the same template.
326 (define_code_iterator any_bitwise [and ior xor])
328 ;; This code iterator allows unsigned and signed division to be generated
329 ;; from the same template.
330 (define_code_iterator any_div [div udiv mod umod])
332 ;; This code iterator allows unsigned and signed modulus to be generated
333 ;; from the same template.
334 (define_code_iterator any_mod [mod umod])
336 ;; These code iterators allow the signed and unsigned scc operations to use
337 ;; the same template.
338 (define_code_iterator any_gt [gt gtu])
339 (define_code_iterator any_ge [ge geu])
340 (define_code_iterator any_lt [lt ltu])
341 (define_code_iterator any_le [le leu])
343 ;; <u> expands to an empty string when doing a signed operation and
344 ;; "u" when doing an unsigned operation.
345 (define_code_attr u [(sign_extend "") (zero_extend "u")
351 ;; <su> is like <u>, but the signed form expands to "s" rather than "".
352 (define_code_attr su [(sign_extend "s") (zero_extend "u")])
354 ;; <optab> expands to the name of the optab for a particular code.
355 (define_code_attr optab [(ashift "ashl")
372 ;; <insn> expands to the name of the insn that implements a particular code.
373 (define_code_attr insn [(ashift "sll")
386 ;; Ghost instructions produce no real code and introduce no hazards.
387 ;; They exist purely to express an effect on dataflow.
388 (define_insn_reservation "ghost" 0
389 (eq_attr "type" "ghost")
393 ;; ....................
397 ;; ....................
400 (define_insn "add<mode>3"
401 [(set (match_operand:ANYF 0 "register_operand" "=f")
402 (plus:ANYF (match_operand:ANYF 1 "register_operand" " f")
403 (match_operand:ANYF 2 "register_operand" " f")))]
405 "fadd.<fmt>\t%0,%1,%2"
406 [(set_attr "type" "fadd")
407 (set_attr "mode" "<UNITMODE>")])
409 (define_insn "addsi3"
410 [(set (match_operand:SI 0 "register_operand" "=r,r")
411 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
412 (match_operand:SI 2 "arith_operand" " r,I")))]
414 { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; }
415 [(set_attr "type" "arith")
416 (set_attr "mode" "SI")])
418 (define_insn "adddi3"
419 [(set (match_operand:DI 0 "register_operand" "=r,r")
420 (plus:DI (match_operand:DI 1 "register_operand" " r,r")
421 (match_operand:DI 2 "arith_operand" " r,I")))]
424 [(set_attr "type" "arith")
425 (set_attr "mode" "DI")])
427 (define_insn "*addsi3_extended"
428 [(set (match_operand:DI 0 "register_operand" "=r,r")
430 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
431 (match_operand:SI 2 "arith_operand" " r,I"))))]
434 [(set_attr "type" "arith")
435 (set_attr "mode" "SI")])
437 (define_insn "*addsi3_extended2"
438 [(set (match_operand:DI 0 "register_operand" "=r,r")
440 (subreg:SI (plus:DI (match_operand:DI 1 "register_operand" " r,r")
441 (match_operand:DI 2 "arith_operand" " r,I"))
445 [(set_attr "type" "arith")
446 (set_attr "mode" "SI")])
449 ;; ....................
453 ;; ....................
456 (define_insn "sub<mode>3"
457 [(set (match_operand:ANYF 0 "register_operand" "=f")
458 (minus:ANYF (match_operand:ANYF 1 "register_operand" " f")
459 (match_operand:ANYF 2 "register_operand" " f")))]
461 "fsub.<fmt>\t%0,%1,%2"
462 [(set_attr "type" "fadd")
463 (set_attr "mode" "<UNITMODE>")])
465 (define_insn "subdi3"
466 [(set (match_operand:DI 0 "register_operand" "= r")
467 (minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
468 (match_operand:DI 2 "register_operand" " r")))]
471 [(set_attr "type" "arith")
472 (set_attr "mode" "DI")])
474 (define_insn "subsi3"
475 [(set (match_operand:SI 0 "register_operand" "= r")
476 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
477 (match_operand:SI 2 "register_operand" " r")))]
479 { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; }
480 [(set_attr "type" "arith")
481 (set_attr "mode" "SI")])
483 (define_insn "*subsi3_extended"
484 [(set (match_operand:DI 0 "register_operand" "= r")
486 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
487 (match_operand:SI 2 "register_operand" " r"))))]
490 [(set_attr "type" "arith")
491 (set_attr "mode" "SI")])
493 (define_insn "*subsi3_extended2"
494 [(set (match_operand:DI 0 "register_operand" "=r")
496 (subreg:SI (minus:DI (match_operand:DI 1 "reg_or_0_operand" " r")
497 (match_operand:DI 2 "register_operand" " r"))
501 [(set_attr "type" "arith")
502 (set_attr "mode" "SI")])
505 ;; ....................
509 ;; ....................
512 (define_insn "mul<mode>3"
513 [(set (match_operand:ANYF 0 "register_operand" "=f")
514 (mult:ANYF (match_operand:ANYF 1 "register_operand" " f")
515 (match_operand:ANYF 2 "register_operand" " f")))]
517 "fmul.<fmt>\t%0,%1,%2"
518 [(set_attr "type" "fmul")
519 (set_attr "mode" "<UNITMODE>")])
521 (define_insn "mulsi3"
522 [(set (match_operand:SI 0 "register_operand" "=r")
523 (mult:SI (match_operand:SI 1 "register_operand" " r")
524 (match_operand:SI 2 "register_operand" " r")))]
526 { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; }
527 [(set_attr "type" "imul")
528 (set_attr "mode" "SI")])
530 (define_insn "muldi3"
531 [(set (match_operand:DI 0 "register_operand" "=r")
532 (mult:DI (match_operand:DI 1 "register_operand" " r")
533 (match_operand:DI 2 "register_operand" " r")))]
534 "TARGET_MUL && TARGET_64BIT"
536 [(set_attr "type" "imul")
537 (set_attr "mode" "DI")])
539 (define_insn "*mulsi3_extended"
540 [(set (match_operand:DI 0 "register_operand" "=r")
542 (mult:SI (match_operand:SI 1 "register_operand" " r")
543 (match_operand:SI 2 "register_operand" " r"))))]
544 "TARGET_MUL && TARGET_64BIT"
546 [(set_attr "type" "imul")
547 (set_attr "mode" "SI")])
549 (define_insn "*mulsi3_extended2"
550 [(set (match_operand:DI 0 "register_operand" "=r")
552 (subreg:SI (mult:DI (match_operand:DI 1 "register_operand" " r")
553 (match_operand:DI 2 "register_operand" " r"))
555 "TARGET_MUL && TARGET_64BIT"
557 [(set_attr "type" "imul")
558 (set_attr "mode" "SI")])
561 ;; ........................
563 ;; MULTIPLICATION HIGH-PART
565 ;; ........................
569 (define_expand "<u>mulditi3"
570 [(set (match_operand:TI 0 "register_operand")
571 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
572 (any_extend:TI (match_operand:DI 2 "register_operand"))))]
573 "TARGET_MUL && TARGET_64BIT"
575 rtx low = gen_reg_rtx (DImode);
576 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
578 rtx high = gen_reg_rtx (DImode);
579 emit_insn (gen_<u>muldi3_highpart (high, operands[1], operands[2]));
581 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
582 emit_move_insn (gen_highpart (DImode, operands[0]), high);
586 (define_insn "<u>muldi3_highpart"
587 [(set (match_operand:DI 0 "register_operand" "=r")
590 (mult:TI (any_extend:TI
591 (match_operand:DI 1 "register_operand" " r"))
593 (match_operand:DI 2 "register_operand" " r")))
595 "TARGET_MUL && TARGET_64BIT"
597 [(set_attr "type" "imul")
598 (set_attr "mode" "DI")])
600 (define_expand "usmulditi3"
601 [(set (match_operand:TI 0 "register_operand")
602 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand"))
603 (sign_extend:TI (match_operand:DI 2 "register_operand"))))]
604 "TARGET_MUL && TARGET_64BIT"
606 rtx low = gen_reg_rtx (DImode);
607 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
609 rtx high = gen_reg_rtx (DImode);
610 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2]));
612 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
613 emit_move_insn (gen_highpart (DImode, operands[0]), high);
617 (define_insn "usmuldi3_highpart"
618 [(set (match_operand:DI 0 "register_operand" "=r")
621 (mult:TI (zero_extend:TI
622 (match_operand:DI 1 "register_operand" "r"))
624 (match_operand:DI 2 "register_operand" " r")))
626 "TARGET_MUL && TARGET_64BIT"
628 [(set_attr "type" "imul")
629 (set_attr "mode" "DI")])
631 (define_expand "<u>mulsidi3"
632 [(set (match_operand:DI 0 "register_operand" "=r")
633 (mult:DI (any_extend:DI
634 (match_operand:SI 1 "register_operand" " r"))
636 (match_operand:SI 2 "register_operand" " r"))))]
637 "TARGET_MUL && !TARGET_64BIT"
639 rtx temp = gen_reg_rtx (SImode);
640 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
641 emit_insn (gen_<u>mulsi3_highpart (riscv_subword (operands[0], true),
642 operands[1], operands[2]));
643 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
647 (define_insn "<u>mulsi3_highpart"
648 [(set (match_operand:SI 0 "register_operand" "=r")
651 (mult:DI (any_extend:DI
652 (match_operand:SI 1 "register_operand" " r"))
654 (match_operand:SI 2 "register_operand" " r")))
656 "TARGET_MUL && !TARGET_64BIT"
658 [(set_attr "type" "imul")
659 (set_attr "mode" "SI")])
662 (define_expand "usmulsidi3"
663 [(set (match_operand:DI 0 "register_operand" "=r")
664 (mult:DI (zero_extend:DI
665 (match_operand:SI 1 "register_operand" " r"))
667 (match_operand:SI 2 "register_operand" " r"))))]
668 "TARGET_MUL && !TARGET_64BIT"
670 rtx temp = gen_reg_rtx (SImode);
671 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
672 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true),
673 operands[1], operands[2]));
674 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
678 (define_insn "usmulsi3_highpart"
679 [(set (match_operand:SI 0 "register_operand" "=r")
682 (mult:DI (zero_extend:DI
683 (match_operand:SI 1 "register_operand" " r"))
685 (match_operand:SI 2 "register_operand" " r")))
687 "TARGET_MUL && !TARGET_64BIT"
689 [(set_attr "type" "imul")
690 (set_attr "mode" "SI")])
693 ;; ....................
695 ;; DIVISION and REMAINDER
697 ;; ....................
700 (define_insn "<optab>si3"
701 [(set (match_operand:SI 0 "register_operand" "=r")
702 (any_div:SI (match_operand:SI 1 "register_operand" " r")
703 (match_operand:SI 2 "register_operand" " r")))]
705 { return TARGET_64BIT ? "<insn>w\t%0,%1,%2" : "<insn>\t%0,%1,%2"; }
706 [(set_attr "type" "idiv")
707 (set_attr "mode" "SI")])
709 (define_insn "<optab>di3"
710 [(set (match_operand:DI 0 "register_operand" "=r")
711 (any_div:DI (match_operand:DI 1 "register_operand" " r")
712 (match_operand:DI 2 "register_operand" " r")))]
713 "TARGET_DIV && TARGET_64BIT"
715 [(set_attr "type" "idiv")
716 (set_attr "mode" "DI")])
718 (define_insn "*<optab>si3_extended"
719 [(set (match_operand:DI 0 "register_operand" "=r")
721 (any_div:SI (match_operand:SI 1 "register_operand" " r")
722 (match_operand:SI 2 "register_operand" " r"))))]
723 "TARGET_DIV && TARGET_64BIT"
725 [(set_attr "type" "idiv")
726 (set_attr "mode" "DI")])
728 (define_insn "div<mode>3"
729 [(set (match_operand:ANYF 0 "register_operand" "=f")
730 (div:ANYF (match_operand:ANYF 1 "register_operand" " f")
731 (match_operand:ANYF 2 "register_operand" " f")))]
732 "TARGET_HARD_FLOAT && TARGET_FDIV"
733 "fdiv.<fmt>\t%0,%1,%2"
734 [(set_attr "type" "fdiv")
735 (set_attr "mode" "<UNITMODE>")])
738 ;; ....................
742 ;; ....................
744 (define_insn "sqrt<mode>2"
745 [(set (match_operand:ANYF 0 "register_operand" "=f")
746 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
747 "TARGET_HARD_FLOAT && TARGET_FDIV"
749 return "fsqrt.<fmt>\t%0,%1";
751 [(set_attr "type" "fsqrt")
752 (set_attr "mode" "<UNITMODE>")])
754 ;; Floating point multiply accumulate instructions.
757 (define_insn "fma<mode>4"
758 [(set (match_operand:ANYF 0 "register_operand" "=f")
759 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
760 (match_operand:ANYF 2 "register_operand" " f")
761 (match_operand:ANYF 3 "register_operand" " f")))]
763 "fmadd.<fmt>\t%0,%1,%2,%3"
764 [(set_attr "type" "fmadd")
765 (set_attr "mode" "<UNITMODE>")])
768 (define_insn "fms<mode>4"
769 [(set (match_operand:ANYF 0 "register_operand" "=f")
770 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
771 (match_operand:ANYF 2 "register_operand" " f")
772 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
774 "fmsub.<fmt>\t%0,%1,%2,%3"
775 [(set_attr "type" "fmadd")
776 (set_attr "mode" "<UNITMODE>")])
779 (define_insn "fnms<mode>4"
780 [(set (match_operand:ANYF 0 "register_operand" "=f")
782 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
783 (match_operand:ANYF 2 "register_operand" " f")
784 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
786 "fnmadd.<fmt>\t%0,%1,%2,%3"
787 [(set_attr "type" "fmadd")
788 (set_attr "mode" "<UNITMODE>")])
791 (define_insn "fnma<mode>4"
792 [(set (match_operand:ANYF 0 "register_operand" "=f")
794 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
795 (match_operand:ANYF 2 "register_operand" " f")
796 (match_operand:ANYF 3 "register_operand" " f")))]
798 "fnmsub.<fmt>\t%0,%1,%2,%3"
799 [(set_attr "type" "fmadd")
800 (set_attr "mode" "<UNITMODE>")])
802 ;; -(-a * b - c), modulo signed zeros
803 (define_insn "*fma<mode>4"
804 [(set (match_operand:ANYF 0 "register_operand" "=f")
807 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
808 (match_operand:ANYF 2 "register_operand" " f")
809 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
810 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
811 "fmadd.<fmt>\t%0,%1,%2,%3"
812 [(set_attr "type" "fmadd")
813 (set_attr "mode" "<UNITMODE>")])
815 ;; -(-a * b + c), modulo signed zeros
816 (define_insn "*fms<mode>4"
817 [(set (match_operand:ANYF 0 "register_operand" "=f")
820 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
821 (match_operand:ANYF 2 "register_operand" " f")
822 (match_operand:ANYF 3 "register_operand" " f"))))]
823 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
824 "fmsub.<fmt>\t%0,%1,%2,%3"
825 [(set_attr "type" "fmadd")
826 (set_attr "mode" "<UNITMODE>")])
828 ;; -(a * b + c), modulo signed zeros
829 (define_insn "*fnms<mode>4"
830 [(set (match_operand:ANYF 0 "register_operand" "=f")
833 (match_operand:ANYF 1 "register_operand" " f")
834 (match_operand:ANYF 2 "register_operand" " f")
835 (match_operand:ANYF 3 "register_operand" " f"))))]
836 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
837 "fnmadd.<fmt>\t%0,%1,%2,%3"
838 [(set_attr "type" "fmadd")
839 (set_attr "mode" "<UNITMODE>")])
841 ;; -(a * b - c), modulo signed zeros
842 (define_insn "*fnma<mode>4"
843 [(set (match_operand:ANYF 0 "register_operand" "=f")
846 (match_operand:ANYF 1 "register_operand" " f")
847 (match_operand:ANYF 2 "register_operand" " f")
848 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
849 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
850 "fnmsub.<fmt>\t%0,%1,%2,%3"
851 [(set_attr "type" "fmadd")
852 (set_attr "mode" "<UNITMODE>")])
855 ;; ....................
859 ;; ....................
861 (define_insn "abs<mode>2"
862 [(set (match_operand:ANYF 0 "register_operand" "=f")
863 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
866 [(set_attr "type" "fmove")
867 (set_attr "mode" "<UNITMODE>")])
869 (define_insn "copysign<mode>3"
870 [(set (match_operand:ANYF 0 "register_operand" "=f")
871 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")
872 (match_operand:ANYF 2 "register_operand" " f")]
875 "fsgnj.<fmt>\t%0,%1,%2"
876 [(set_attr "type" "fmove")
877 (set_attr "mode" "<UNITMODE>")])
879 (define_insn "neg<mode>2"
880 [(set (match_operand:ANYF 0 "register_operand" "=f")
881 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
884 [(set_attr "type" "fmove")
885 (set_attr "mode" "<UNITMODE>")])
888 ;; ....................
892 ;; ....................
894 (define_insn "smin<mode>3"
895 [(set (match_operand:ANYF 0 "register_operand" "=f")
896 (smin:ANYF (match_operand:ANYF 1 "register_operand" " f")
897 (match_operand:ANYF 2 "register_operand" " f")))]
899 "fmin.<fmt>\t%0,%1,%2"
900 [(set_attr "type" "fmove")
901 (set_attr "mode" "<UNITMODE>")])
903 (define_insn "smax<mode>3"
904 [(set (match_operand:ANYF 0 "register_operand" "=f")
905 (smax:ANYF (match_operand:ANYF 1 "register_operand" " f")
906 (match_operand:ANYF 2 "register_operand" " f")))]
908 "fmax.<fmt>\t%0,%1,%2"
909 [(set_attr "type" "fmove")
910 (set_attr "mode" "<UNITMODE>")])
913 ;; ....................
917 ;; ....................
920 ;; For RV64, we don't expose the SImode operations to the rtl expanders,
921 ;; but SImode versions exist for combine.
923 (define_insn "<optab><mode>3"
924 [(set (match_operand:X 0 "register_operand" "=r,r")
925 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
926 (match_operand:X 2 "arith_operand" " r,I")))]
929 [(set_attr "type" "logical")
930 (set_attr "mode" "<MODE>")])
932 (define_insn "*<optab>si3_internal"
933 [(set (match_operand:SI 0 "register_operand" "=r,r")
934 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
935 (match_operand:SI 2 "arith_operand" " r,I")))]
938 [(set_attr "type" "logical")
939 (set_attr "mode" "SI")])
941 (define_insn "one_cmpl<mode>2"
942 [(set (match_operand:X 0 "register_operand" "=r")
943 (not:X (match_operand:X 1 "register_operand" " r")))]
946 [(set_attr "type" "logical")
947 (set_attr "mode" "<MODE>")])
949 (define_insn "*one_cmplsi2_internal"
950 [(set (match_operand:SI 0 "register_operand" "=r")
951 (not:SI (match_operand:SI 1 "register_operand" " r")))]
954 [(set_attr "type" "logical")
955 (set_attr "mode" "SI")])
958 ;; ....................
962 ;; ....................
964 (define_insn "truncdfsf2"
965 [(set (match_operand:SF 0 "register_operand" "=f")
967 (match_operand:DF 1 "register_operand" " f")))]
968 "TARGET_DOUBLE_FLOAT"
970 [(set_attr "type" "fcvt")
971 (set_attr "mode" "SF")])
974 ;; ....................
978 ;; ....................
982 (define_insn_and_split "zero_extendsidi2"
983 [(set (match_operand:DI 0 "register_operand" "=r,r")
985 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
990 "&& reload_completed && REG_P (operands[1])"
992 (ashift:DI (match_dup 1) (const_int 32)))
994 (lshiftrt:DI (match_dup 0) (const_int 32)))]
995 { operands[1] = gen_lowpart (DImode, operands[1]); }
996 [(set_attr "move_type" "shift_shift,load")
997 (set_attr "mode" "DI")])
999 (define_insn_and_split "zero_extendhi<GPR:mode>2"
1000 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1002 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
1007 "&& reload_completed && REG_P (operands[1])"
1009 (ashift:GPR (match_dup 1) (match_dup 2)))
1011 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1013 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1014 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1016 [(set_attr "move_type" "shift_shift,load")
1017 (set_attr "mode" "<GPR:MODE>")])
1019 (define_insn "zero_extendqi<SUPERQI:mode>2"
1020 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1021 (zero_extend:SUPERQI
1022 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
1027 [(set_attr "move_type" "andi,load")
1028 (set_attr "mode" "<SUPERQI:MODE>")])
1031 ;; ....................
1035 ;; ....................
1037 (define_insn "extendsidi2"
1038 [(set (match_operand:DI 0 "register_operand" "=r,r")
1040 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1045 [(set_attr "move_type" "move,load")
1046 (set_attr "mode" "DI")])
1048 (define_insn_and_split "extend<SHORT:mode><SUPERQI:mode>2"
1049 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1050 (sign_extend:SUPERQI
1051 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
1055 l<SHORT:size>\t%0,%1"
1056 "&& reload_completed && REG_P (operands[1])"
1057 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1058 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
1060 operands[0] = gen_lowpart (SImode, operands[0]);
1061 operands[1] = gen_lowpart (SImode, operands[1]);
1062 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1063 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1065 [(set_attr "move_type" "shift_shift,load")
1066 (set_attr "mode" "SI")])
1068 (define_insn "extendsfdf2"
1069 [(set (match_operand:DF 0 "register_operand" "=f")
1071 (match_operand:SF 1 "register_operand" " f")))]
1072 "TARGET_DOUBLE_FLOAT"
1074 [(set_attr "type" "fcvt")
1075 (set_attr "mode" "DF")])
1078 ;; ....................
1082 ;; ....................
1084 (define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
1085 [(set (match_operand:GPR 0 "register_operand" "=r")
1087 (match_operand:ANYF 1 "register_operand" " f")))]
1089 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
1090 [(set_attr "type" "fcvt")
1091 (set_attr "mode" "<ANYF:MODE>")])
1093 (define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2"
1094 [(set (match_operand:GPR 0 "register_operand" "=r")
1096 (match_operand:ANYF 1 "register_operand" " f")))]
1098 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
1099 [(set_attr "type" "fcvt")
1100 (set_attr "mode" "<ANYF:MODE>")])
1102 (define_insn "float<GPR:mode><ANYF:mode>2"
1103 [(set (match_operand:ANYF 0 "register_operand" "= f")
1105 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
1107 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
1108 [(set_attr "type" "fcvt")
1109 (set_attr "mode" "<ANYF:MODE>")])
1111 (define_insn "floatuns<GPR:mode><ANYF:mode>2"
1112 [(set (match_operand:ANYF 0 "register_operand" "= f")
1113 (unsigned_float:ANYF
1114 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
1116 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
1117 [(set_attr "type" "fcvt")
1118 (set_attr "mode" "<ANYF:MODE>")])
1120 (define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2"
1121 [(set (match_operand:GPR 0 "register_operand" "=r")
1123 [(match_operand:ANYF 1 "register_operand" " f")]
1126 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
1127 [(set_attr "type" "fcvt")
1128 (set_attr "mode" "<ANYF:MODE>")])
1131 ;; ....................
1135 ;; ....................
1137 ;; Lower-level instructions for loading an address from the GOT.
1138 ;; We could use MEMs, but an unspec gives more optimization
1141 (define_insn "got_load<mode>"
1142 [(set (match_operand:P 0 "register_operand" "=r")
1144 [(match_operand:P 1 "symbolic_operand" "")]
1148 [(set_attr "got" "load")
1149 (set_attr "mode" "<MODE>")])
1151 (define_insn "tls_add_tp_le<mode>"
1152 [(set (match_operand:P 0 "register_operand" "=r")
1154 [(match_operand:P 1 "register_operand" "r")
1155 (match_operand:P 2 "register_operand" "r")
1156 (match_operand:P 3 "symbolic_operand" "")]
1159 "add\t%0,%1,%2,%%tprel_add(%3)"
1160 [(set_attr "type" "arith")
1161 (set_attr "mode" "<MODE>")])
1163 (define_insn "got_load_tls_gd<mode>"
1164 [(set (match_operand:P 0 "register_operand" "=r")
1166 [(match_operand:P 1 "symbolic_operand" "")]
1170 [(set_attr "got" "load")
1171 (set_attr "mode" "<MODE>")])
1173 (define_insn "got_load_tls_ie<mode>"
1174 [(set (match_operand:P 0 "register_operand" "=r")
1176 [(match_operand:P 1 "symbolic_operand" "")]
1180 [(set_attr "got" "load")
1181 (set_attr "mode" "<MODE>")])
1183 (define_insn "auipc<mode>"
1184 [(set (match_operand:P 0 "register_operand" "=r")
1186 [(match_operand:P 1 "symbolic_operand" "")
1187 (match_operand:P 2 "const_int_operand")
1191 ".LA%2: auipc\t%0,%h1"
1192 [(set_attr "type" "arith")
1193 (set_attr "cannot_copy" "yes")])
1195 ;; Instructions for adding the low 12 bits of an address to a register.
1196 ;; Operand 2 is the address: riscv_print_operand works out which relocation
1197 ;; should be applied.
1199 (define_insn "*low<mode>"
1200 [(set (match_operand:P 0 "register_operand" "=r")
1201 (lo_sum:P (match_operand:P 1 "register_operand" " r")
1202 (match_operand:P 2 "symbolic_operand" "")))]
1205 [(set_attr "type" "arith")
1206 (set_attr "mode" "<MODE>")])
1208 ;; Allow combine to split complex const_int load sequences, using operand 2
1209 ;; to store the intermediate results. See move_operand for details.
1211 [(set (match_operand:GPR 0 "register_operand")
1212 (match_operand:GPR 1 "splittable_const_int_operand"))
1213 (clobber (match_operand:GPR 2 "register_operand"))]
1217 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]));
1221 ;; Likewise, for symbolic operands.
1223 [(set (match_operand:P 0 "register_operand")
1224 (match_operand:P 1))
1225 (clobber (match_operand:P 2 "register_operand"))]
1226 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)"
1227 [(set (match_dup 0) (match_dup 3))]
1229 riscv_split_symbol (operands[2], operands[1],
1230 MAX_MACHINE_MODE, &operands[3]);
1233 ;; 64-bit integer moves
1235 (define_expand "movdi"
1236 [(set (match_operand:DI 0 "")
1237 (match_operand:DI 1 ""))]
1240 if (riscv_legitimize_move (DImode, operands[0], operands[1]))
1244 (define_insn "*movdi_32bit"
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,i,m,r,*J*r,*m,*f,*f,*f"))]
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")])
1254 (define_insn "*movdi_64bit"
1255 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m")
1256 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))]
1258 && (register_operand (operands[0], DImode)
1259 || reg_or_0_operand (operands[1], DImode))"
1260 { return riscv_output_move (operands[0], operands[1]); }
1261 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1262 (set_attr "mode" "DI")])
1264 ;; 32-bit Integer moves
1266 (define_expand "mov<mode>"
1267 [(set (match_operand:MOVE32 0 "")
1268 (match_operand:MOVE32 1 ""))]
1271 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
1275 (define_insn "*movsi_internal"
1276 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m")
1277 (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f"))]
1278 "(register_operand (operands[0], SImode)
1279 || reg_or_0_operand (operands[1], SImode))"
1280 { return riscv_output_move (operands[0], operands[1]); }
1281 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
1282 (set_attr "mode" "SI")])
1284 ;; 16-bit Integer moves
1286 ;; Unlike most other insns, the move insns can't be split with
1287 ;; different predicates, because register spilling and other parts of
1288 ;; the compiler, have memoized the insn number already.
1289 ;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
1291 (define_expand "movhi"
1292 [(set (match_operand:HI 0 "")
1293 (match_operand:HI 1 ""))]
1296 if (riscv_legitimize_move (HImode, operands[0], operands[1]))
1300 (define_insn "*movhi_internal"
1301 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1302 (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f"))]
1303 "(register_operand (operands[0], HImode)
1304 || reg_or_0_operand (operands[1], HImode))"
1305 { return riscv_output_move (operands[0], operands[1]); }
1306 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1307 (set_attr "mode" "HI")])
1309 ;; HImode constant generation; see riscv_move_integer for details.
1310 ;; si+si->hi without truncation is legal because of TRULY_NOOP_TRUNCATION.
1312 (define_insn "*add<mode>hi3"
1313 [(set (match_operand:HI 0 "register_operand" "=r,r")
1314 (plus:HI (match_operand:HISI 1 "register_operand" " r,r")
1315 (match_operand:HISI 2 "arith_operand" " r,I")))]
1317 { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; }
1318 [(set_attr "type" "arith")
1319 (set_attr "mode" "HI")])
1321 (define_insn "*xor<mode>hi3"
1322 [(set (match_operand:HI 0 "register_operand" "=r,r")
1323 (xor:HI (match_operand:HISI 1 "register_operand" " r,r")
1324 (match_operand:HISI 2 "arith_operand" " r,I")))]
1327 [(set_attr "type" "logical")
1328 (set_attr "mode" "HI")])
1330 ;; 8-bit Integer moves
1332 (define_expand "movqi"
1333 [(set (match_operand:QI 0 "")
1334 (match_operand:QI 1 ""))]
1337 if (riscv_legitimize_move (QImode, operands[0], operands[1]))
1341 (define_insn "*movqi_internal"
1342 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1343 (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f"))]
1344 "(register_operand (operands[0], QImode)
1345 || reg_or_0_operand (operands[1], QImode))"
1346 { return riscv_output_move (operands[0], operands[1]); }
1347 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1348 (set_attr "mode" "QI")])
1350 ;; 32-bit floating point moves
1352 (define_expand "movsf"
1353 [(set (match_operand:SF 0 "")
1354 (match_operand:SF 1 ""))]
1357 if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
1361 (define_insn "*movsf_hardfloat"
1362 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1363 (match_operand:SF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
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" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1369 (set_attr "mode" "SF")])
1371 (define_insn "*movsf_softfloat"
1372 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
1373 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
1375 && (register_operand (operands[0], SFmode)
1376 || reg_or_0_operand (operands[1], SFmode))"
1377 { return riscv_output_move (operands[0], operands[1]); }
1378 [(set_attr "move_type" "move,load,store")
1379 (set_attr "mode" "SF")])
1381 ;; 64-bit floating point moves
1383 (define_expand "movdf"
1384 [(set (match_operand:DF 0 "")
1385 (match_operand:DF 1 ""))]
1388 if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
1392 ;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
1393 ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
1394 (define_insn "*movdf_hardfloat_rv32"
1395 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m")
1396 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*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,move,load,store")
1402 (set_attr "mode" "DF")])
1404 (define_insn "*movdf_hardfloat_rv64"
1405 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1406 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
1407 "TARGET_64BIT && 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" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1412 (set_attr "mode" "DF")])
1414 (define_insn "*movdf_softfloat"
1415 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
1416 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
1417 "!TARGET_DOUBLE_FLOAT
1418 && (register_operand (operands[0], DFmode)
1419 || reg_or_0_operand (operands[1], DFmode))"
1420 { return riscv_output_move (operands[0], operands[1]); }
1421 [(set_attr "move_type" "move,load,store")
1422 (set_attr "mode" "DF")])
1425 [(set (match_operand:MOVE64 0 "nonimmediate_operand")
1426 (match_operand:MOVE64 1 "move_operand"))]
1428 && riscv_split_64bit_move_p (operands[0], operands[1])"
1431 riscv_split_doubleword_move (operands[0], operands[1]);
1435 ;; Expand in-line code to clear the instruction cache between operand[0] and
1437 (define_expand "clear_cache"
1438 [(match_operand 0 "pmode_register_operand")
1439 (match_operand 1 "pmode_register_operand")]
1442 emit_insn (gen_fence_i ());
1446 (define_insn "fence"
1447 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
1451 (define_insn "fence_i"
1452 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
1457 ;; ....................
1461 ;; ....................
1463 (define_insn "<optab>si3"
1464 [(set (match_operand:SI 0 "register_operand" "= r")
1466 (match_operand:SI 1 "register_operand" " r")
1467 (match_operand:SI 2 "arith_operand" " rI")))]
1470 if (GET_CODE (operands[2]) == CONST_INT)
1471 operands[2] = GEN_INT (INTVAL (operands[2])
1472 & (GET_MODE_BITSIZE (SImode) - 1));
1474 return TARGET_64BIT ? "<insn>w\t%0,%1,%2" : "<insn>\t%0,%1,%2";
1476 [(set_attr "type" "shift")
1477 (set_attr "mode" "SI")])
1479 (define_insn "<optab>di3"
1480 [(set (match_operand:DI 0 "register_operand" "= r")
1482 (match_operand:DI 1 "register_operand" " r")
1483 (match_operand:DI 2 "arith_operand" " rI")))]
1486 if (GET_CODE (operands[2]) == CONST_INT)
1487 operands[2] = GEN_INT (INTVAL (operands[2])
1488 & (GET_MODE_BITSIZE (DImode) - 1));
1490 return "<insn>\t%0,%1,%2";
1492 [(set_attr "type" "shift")
1493 (set_attr "mode" "DI")])
1495 (define_insn "*<optab>si3_extend"
1496 [(set (match_operand:DI 0 "register_operand" "= r")
1498 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
1499 (match_operand:SI 2 "arith_operand" " rI"))))]
1502 if (GET_CODE (operands[2]) == CONST_INT)
1503 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1505 return "<insn>w\t%0,%1,%2";
1507 [(set_attr "type" "shift")
1508 (set_attr "mode" "SI")])
1511 ;; ....................
1513 ;; CONDITIONAL BRANCHES
1515 ;; ....................
1517 ;; Conditional branches
1519 (define_insn "*branch_order<mode>"
1522 (match_operator 1 "order_operator"
1523 [(match_operand:X 2 "register_operand" "r")
1524 (match_operand:X 3 "register_operand" "r")])
1525 (label_ref (match_operand 0 "" ""))
1529 [(set_attr "type" "branch")
1530 (set_attr "mode" "none")])
1532 (define_insn "*branch_zero<mode>"
1535 (match_operator 1 "signed_order_operator"
1536 [(match_operand:X 2 "register_operand" "r")
1538 (label_ref (match_operand 0 "" ""))
1542 [(set_attr "type" "branch")
1543 (set_attr "mode" "none")])
1545 ;; Used to implement built-in functions.
1546 (define_expand "condjump"
1548 (if_then_else (match_operand 0)
1549 (label_ref (match_operand 1))
1552 (define_expand "cbranch<mode>4"
1554 (if_then_else (match_operator 0 "comparison_operator"
1555 [(match_operand:BR 1 "register_operand")
1556 (match_operand:BR 2 "nonmemory_operand")])
1557 (label_ref (match_operand 3 ""))
1561 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1562 operands[1], operands[2]);
1566 (define_expand "cbranch<mode>4"
1568 (if_then_else (match_operator 0 "fp_branch_comparison"
1569 [(match_operand:ANYF 1 "register_operand")
1570 (match_operand:ANYF 2 "register_operand")])
1571 (label_ref (match_operand 3 ""))
1575 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1576 operands[1], operands[2]);
1580 (define_insn_and_split "*branch_on_bit<X:mode>"
1583 (match_operator 0 "equality_operator"
1584 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1586 (match_operand 3 "branch_on_bit_operand"))
1588 (label_ref (match_operand 1))
1590 (clobber (match_scratch:X 4 "=&r"))]
1595 (ashift:X (match_dup 2) (match_dup 3)))
1598 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1599 (label_ref (match_operand 1))
1602 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
1603 operands[3] = GEN_INT (shift);
1605 if (GET_CODE (operands[0]) == EQ)
1606 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
1608 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
1611 (define_insn_and_split "*branch_on_bit_range<X:mode>"
1614 (match_operator 0 "equality_operator"
1615 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1616 (match_operand 3 "branch_on_bit_operand")
1619 (label_ref (match_operand 1))
1621 (clobber (match_scratch:X 4 "=&r"))]
1626 (ashift:X (match_dup 2) (match_dup 3)))
1629 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1630 (label_ref (match_operand 1))
1633 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
1637 ;; ....................
1639 ;; SETTING A REGISTER FROM A COMPARISON
1641 ;; ....................
1643 ;; Destination is always set in SI mode.
1645 (define_expand "cstore<mode>4"
1646 [(set (match_operand:SI 0 "register_operand")
1647 (match_operator:SI 1 "order_operator"
1648 [(match_operand:GPR 2 "register_operand")
1649 (match_operand:GPR 3 "nonmemory_operand")]))]
1652 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
1657 (define_expand "cstore<mode>4"
1658 [(set (match_operand:SI 0 "register_operand")
1659 (match_operator:SI 1 "fp_scc_comparison"
1660 [(match_operand:ANYF 2 "register_operand")
1661 (match_operand:ANYF 3 "register_operand")]))]
1664 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
1669 (define_insn "*cstore<ANYF:mode><X:mode>4"
1670 [(set (match_operand:X 0 "register_operand" "=r")
1671 (match_operator:X 1 "fp_native_comparison"
1672 [(match_operand:ANYF 2 "register_operand" " f")
1673 (match_operand:ANYF 3 "register_operand" " f")]))]
1675 "f%C1.<fmt>\t%0,%2,%3"
1676 [(set_attr "type" "fcmp")
1677 (set_attr "mode" "<UNITMODE>")])
1679 (define_insn "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
1680 [(set (match_operand:X 0 "register_operand" "=r")
1682 [(match_operand:ANYF 1 "register_operand" " f")
1683 (match_operand:ANYF 2 "register_operand" " f")]
1685 (clobber (match_scratch:X 3 "=&r"))]
1687 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3"
1688 [(set_attr "type" "fcmp")
1689 (set_attr "mode" "<UNITMODE>")
1690 (set (attr "length") (const_int 12))])
1692 (define_insn "*seq_zero_<X:mode><GPR:mode>"
1693 [(set (match_operand:GPR 0 "register_operand" "=r")
1694 (eq:GPR (match_operand:X 1 "register_operand" " r")
1698 [(set_attr "type" "slt")
1699 (set_attr "mode" "<X:MODE>")])
1701 (define_insn "*sne_zero_<X:mode><GPR:mode>"
1702 [(set (match_operand:GPR 0 "register_operand" "=r")
1703 (ne:GPR (match_operand:X 1 "register_operand" " r")
1707 [(set_attr "type" "slt")
1708 (set_attr "mode" "<X:MODE>")])
1710 (define_insn "*sgt<u>_<X:mode><GPR:mode>"
1711 [(set (match_operand:GPR 0 "register_operand" "= r")
1712 (any_gt:GPR (match_operand:X 1 "register_operand" " r")
1713 (match_operand:X 2 "reg_or_0_operand" " rJ")))]
1716 [(set_attr "type" "slt")
1717 (set_attr "mode" "<X:MODE>")])
1719 (define_insn "*sge<u>_<X:mode><GPR:mode>"
1720 [(set (match_operand:GPR 0 "register_operand" "=r")
1721 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
1724 "slt<u>\t%0,zero,%1"
1725 [(set_attr "type" "slt")
1726 (set_attr "mode" "<MODE>")])
1728 (define_insn "*slt<u>_<X:mode><GPR:mode>"
1729 [(set (match_operand:GPR 0 "register_operand" "= r")
1730 (any_lt:GPR (match_operand:X 1 "register_operand" " r")
1731 (match_operand:X 2 "arith_operand" " rI")))]
1734 [(set_attr "type" "slt")
1735 (set_attr "mode" "<MODE>")])
1737 (define_insn "*sle<u>_<X:mode><GPR:mode>"
1738 [(set (match_operand:GPR 0 "register_operand" "=r")
1739 (any_le:GPR (match_operand:X 1 "register_operand" " r")
1740 (match_operand:X 2 "sle_operand" "")))]
1743 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
1744 return "slt<u>\t%0,%1,%2";
1746 [(set_attr "type" "slt")
1747 (set_attr "mode" "<MODE>")])
1750 ;; ....................
1752 ;; UNCONDITIONAL BRANCHES
1754 ;; ....................
1756 ;; Unconditional branches.
1760 (label_ref (match_operand 0 "" "")))]
1763 [(set_attr "type" "jump")
1764 (set_attr "mode" "none")])
1766 (define_expand "indirect_jump"
1767 [(set (pc) (match_operand 0 "register_operand"))]
1770 operands[0] = force_reg (Pmode, operands[0]);
1771 if (Pmode == SImode)
1772 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
1774 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
1778 (define_insn "indirect_jump<mode>"
1779 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
1782 [(set_attr "type" "jump")
1783 (set_attr "mode" "none")])
1785 (define_expand "tablejump"
1786 [(set (pc) (match_operand 0 "register_operand" ""))
1787 (use (label_ref (match_operand 1 "" "")))]
1790 if (CASE_VECTOR_PC_RELATIVE)
1791 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
1792 gen_rtx_LABEL_REF (Pmode, operands[1]),
1793 NULL_RTX, 0, OPTAB_DIRECT);
1795 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
1796 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
1798 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
1802 (define_insn "tablejump<mode>"
1803 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
1804 (use (label_ref (match_operand 1 "" "")))]
1807 [(set_attr "type" "jump")
1808 (set_attr "mode" "none")])
1811 ;; ....................
1813 ;; Function prologue/epilogue
1815 ;; ....................
1818 (define_expand "prologue"
1822 riscv_expand_prologue ();
1826 ;; Block any insns from being moved before this point, since the
1827 ;; profiling call to mcount can use various registers that aren't
1828 ;; saved or used to pass arguments.
1830 (define_insn "blockage"
1831 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
1834 [(set_attr "type" "ghost")
1835 (set_attr "mode" "none")])
1837 (define_expand "epilogue"
1841 riscv_expand_epilogue (false);
1845 (define_expand "sibcall_epilogue"
1849 riscv_expand_epilogue (true);
1853 ;; Trivial return. Make it look like a normal return insn as that
1854 ;; allows jump optimizations to work better.
1856 (define_expand "return"
1858 "riscv_can_use_return_insn ()"
1861 (define_insn "simple_return"
1865 [(set_attr "type" "jump")
1866 (set_attr "mode" "none")])
1870 (define_insn "simple_return_internal"
1872 (use (match_operand 0 "pmode_register_operand" ""))]
1875 [(set_attr "type" "jump")
1876 (set_attr "mode" "none")])
1878 ;; This is used in compiling the unwind routines.
1879 (define_expand "eh_return"
1880 [(use (match_operand 0 "general_operand"))]
1883 if (GET_MODE (operands[0]) != word_mode)
1884 operands[0] = convert_to_mode (word_mode, operands[0], 0);
1886 emit_insn (gen_eh_set_lr_di (operands[0]));
1888 emit_insn (gen_eh_set_lr_si (operands[0]));
1892 ;; Clobber the return address on the stack. We can't expand this
1893 ;; until we know where it will be put in the stack frame.
1895 (define_insn "eh_set_lr_si"
1896 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
1897 (clobber (match_scratch:SI 1 "=&r"))]
1901 (define_insn "eh_set_lr_di"
1902 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
1903 (clobber (match_scratch:DI 1 "=&r"))]
1908 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
1909 (clobber (match_scratch 1))]
1913 riscv_set_return_address (operands[0], operands[1]);
1918 ;; ....................
1922 ;; ....................
1924 (define_expand "sibcall"
1925 [(parallel [(call (match_operand 0 "")
1926 (match_operand 1 ""))
1927 (use (match_operand 2 "")) ;; next_arg_reg
1928 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
1931 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
1932 emit_call_insn (gen_sibcall_internal (target, operands[1]));
1936 (define_insn "sibcall_internal"
1937 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
1938 (match_operand 1 "" ""))]
1939 "SIBLING_CALL_P (insn)"
1944 [(set_attr "type" "call")])
1946 (define_expand "sibcall_value"
1947 [(parallel [(set (match_operand 0 "")
1948 (call (match_operand 1 "")
1949 (match_operand 2 "")))
1950 (use (match_operand 3 ""))])] ;; next_arg_reg
1953 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
1954 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
1958 (define_insn "sibcall_value_internal"
1959 [(set (match_operand 0 "" "")
1960 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
1961 (match_operand 2 "" "")))]
1962 "SIBLING_CALL_P (insn)"
1967 [(set_attr "type" "call")])
1969 (define_expand "call"
1970 [(parallel [(call (match_operand 0 "")
1971 (match_operand 1 ""))
1972 (use (match_operand 2 "")) ;; next_arg_reg
1973 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
1976 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
1977 emit_call_insn (gen_call_internal (target, operands[1]));
1981 (define_insn "call_internal"
1982 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
1983 (match_operand 1 "" ""))
1984 (clobber (reg:SI RETURN_ADDR_REGNUM))]
1990 [(set_attr "type" "call")])
1992 (define_expand "call_value"
1993 [(parallel [(set (match_operand 0 "")
1994 (call (match_operand 1 "")
1995 (match_operand 2 "")))
1996 (use (match_operand 3 ""))])] ;; next_arg_reg
1999 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2000 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
2004 (define_insn "call_value_internal"
2005 [(set (match_operand 0 "" "")
2006 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
2007 (match_operand 2 "" "")))
2008 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2014 [(set_attr "type" "call")])
2016 ;; Call subroutine returning any type.
2018 (define_expand "untyped_call"
2019 [(parallel [(call (match_operand 0 "")
2021 (match_operand 1 "")
2022 (match_operand 2 "")])]
2027 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2029 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2031 rtx set = XVECEXP (operands[2], 0, i);
2032 riscv_emit_move (SET_DEST (set), SET_SRC (set));
2035 emit_insn (gen_blockage ());
2043 [(set_attr "type" "nop")
2044 (set_attr "mode" "none")])
2047 [(trap_if (const_int 1) (const_int 0))]
2051 (define_insn "gpr_save"
2052 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_SAVE)
2053 (clobber (reg:SI T0_REGNUM))
2054 (clobber (reg:SI T1_REGNUM))]
2056 { return riscv_output_gpr_save (INTVAL (operands[0])); })
2058 (define_insn "gpr_restore"
2059 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2061 "tail\t__riscv_restore_%0")
2063 (define_insn "gpr_restore_return"
2065 (use (match_operand 0 "pmode_register_operand" ""))
2070 (define_insn "riscv_frflags"
2071 [(set (match_operand:SI 0 "register_operand" "=r")
2072 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
2076 (define_insn "riscv_fsflags"
2077 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2081 (define_insn "stack_tie<mode>"
2082 [(set (mem:BLK (scratch))
2083 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
2084 (match_operand:X 1 "register_operand" "r")]
2088 [(set_attr "length" "0")]
2092 (include "peephole.md")
2094 (include "generic.md")