1 ;; Machine description for RISC-V for GNU compiler.
2 ;; Copyright (C) 2011-2019 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 ;; Interrupt handler instructions.
64 ;; Blockage and synchronization.
71 [(RETURN_ADDR_REGNUM 1)
84 (include "predicates.md")
85 (include "constraints.md")
87 ;; ....................
91 ;; ....................
93 (define_attr "got" "unset,xgot_high,load"
94 (const_string "unset"))
96 ;; Classification of moves, extensions and truncations. Most values
97 ;; are as for "type" (see below) but there are also the following
98 ;; move-specific values:
100 ;; andi a single ANDI instruction
101 ;; shift_shift a shift left followed by a shift right
103 ;; This attribute is used to determine the instruction's length and
104 ;; scheduling type. For doubleword moves, the attribute always describes
105 ;; the split instructions; in some cases, it is more appropriate for the
106 ;; scheduling type to be "multi" instead.
107 (define_attr "move_type"
108 "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove,
109 const,logical,arith,andi,shift_shift"
110 (const_string "unknown"))
112 ;; Main data type used by the insn
113 (define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF"
114 (const_string "unknown"))
116 ;; True if the main data type is twice the size of a word.
117 (define_attr "dword_mode" "no,yes"
118 (cond [(and (eq_attr "mode" "DI,DF")
119 (eq (symbol_ref "TARGET_64BIT") (const_int 0)))
122 (and (eq_attr "mode" "TI,TF")
123 (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
124 (const_string "yes")]
125 (const_string "no")))
127 ;; Classification of each insn.
128 ;; branch conditional branch
129 ;; jump unconditional jump
130 ;; call unconditional call
131 ;; load load instruction(s)
132 ;; fpload floating point load
133 ;; store store instruction(s)
134 ;; fpstore floating point store
135 ;; mtc transfer to coprocessor
136 ;; mfc transfer from coprocessor
137 ;; const load constant
138 ;; arith integer arithmetic instructions
139 ;; logical integer logical instructions
140 ;; shift integer shift instructions
141 ;; slt set less than instructions
142 ;; imul integer multiply
143 ;; idiv integer divide
144 ;; move integer register move (addi rd, rs1, 0)
145 ;; fmove floating point register move
146 ;; fadd floating point add/subtract
147 ;; fmul floating point multiply
148 ;; fmadd floating point multiply-add
149 ;; fdiv floating point divide
150 ;; fcmp floating point compare
151 ;; fcvt floating point convert
152 ;; fsqrt floating point square root
153 ;; multi multiword sequence (or user asm statements)
155 ;; ghost an instruction that produces no real code
157 "unknown,branch,jump,call,load,fpload,store,fpstore,
158 mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
159 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost"
160 (cond [(eq_attr "got" "load") (const_string "load")
162 ;; If a doubleword move uses these expensive instructions,
163 ;; it is usually better to schedule them in the same way
164 ;; as the singleword form, rather than as "multi".
165 (eq_attr "move_type" "load") (const_string "load")
166 (eq_attr "move_type" "fpload") (const_string "fpload")
167 (eq_attr "move_type" "store") (const_string "store")
168 (eq_attr "move_type" "fpstore") (const_string "fpstore")
169 (eq_attr "move_type" "mtc") (const_string "mtc")
170 (eq_attr "move_type" "mfc") (const_string "mfc")
172 ;; These types of move are always single insns.
173 (eq_attr "move_type" "fmove") (const_string "fmove")
174 (eq_attr "move_type" "arith") (const_string "arith")
175 (eq_attr "move_type" "logical") (const_string "logical")
176 (eq_attr "move_type" "andi") (const_string "logical")
178 ;; These types of move are always split.
179 (eq_attr "move_type" "shift_shift")
180 (const_string "multi")
182 ;; These types of move are split for doubleword modes only.
183 (and (eq_attr "move_type" "move,const")
184 (eq_attr "dword_mode" "yes"))
185 (const_string "multi")
186 (eq_attr "move_type" "move") (const_string "move")
187 (eq_attr "move_type" "const") (const_string "const")]
188 (const_string "unknown")))
190 ;; Length of instruction in bytes.
191 (define_attr "length" ""
193 ;; Branches further than +/- 4 KiB require two instructions.
194 (eq_attr "type" "branch")
195 (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4088))
196 (le (minus (pc) (match_dup 0)) (const_int 4092)))
200 ;; Conservatively assume calls take two instructions (AUIPC + JALR).
201 ;; The linker will opportunistically relax the sequence to JAL.
202 (eq_attr "type" "call") (const_int 8)
204 ;; "Ghost" instructions occupy no space.
205 (eq_attr "type" "ghost") (const_int 0)
207 (eq_attr "got" "load") (const_int 8)
209 (eq_attr "type" "fcmp") (const_int 8)
211 ;; SHIFT_SHIFTs are decomposed into two separate instructions.
212 (eq_attr "move_type" "shift_shift")
215 ;; Check for doubleword moves that are decomposed into two
217 (and (eq_attr "move_type" "mtc,mfc,move")
218 (eq_attr "dword_mode" "yes"))
221 ;; Doubleword CONST{,N} moves are split into two word
223 (and (eq_attr "move_type" "const")
224 (eq_attr "dword_mode" "yes"))
225 (symbol_ref "riscv_split_const_insns (operands[1]) * 4")
227 ;; Otherwise, constants, loads and stores are handled by external
229 (eq_attr "move_type" "load,fpload")
230 (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4")
231 (eq_attr "move_type" "store,fpstore")
232 (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4")
235 ;; Is copying of this instruction disallowed?
236 (define_attr "cannot_copy" "no,yes" (const_string "no"))
238 ;; Microarchitectures we know how to tune for.
239 ;; Keep this in sync with enum riscv_microarchitecture.
242 (const (symbol_ref "((enum attr_tune) riscv_microarchitecture)")))
244 ;; Describe a user's asm statement.
245 (define_asm_attributes
246 [(set_attr "type" "multi")])
248 ;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated
249 ;; from the same template.
250 (define_mode_iterator GPR [SI (DI "TARGET_64BIT")])
252 ;; This mode iterator allows :P to be used for patterns that operate on
253 ;; pointer-sized quantities. Exactly one of the two alternatives will match.
254 (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
256 ;; Likewise, but for XLEN-sized quantities.
257 (define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")])
259 ;; Branches operate on XLEN-sized quantities, but for RV64 we accept
260 ;; QImode values so we can force zero-extension.
261 (define_mode_iterator BR [(QI "TARGET_64BIT") SI (DI "TARGET_64BIT")])
263 ;; 32-bit moves for which we provide move patterns.
264 (define_mode_iterator MOVE32 [SI])
266 ;; 64-bit modes for which we provide move patterns.
267 (define_mode_iterator MOVE64 [DI DF])
269 ;; Iterator for sub-32-bit integer modes.
270 (define_mode_iterator SHORT [QI HI])
272 ;; Iterator for HImode constant generation.
273 (define_mode_iterator HISI [HI SI])
275 ;; Iterator for QImode extension patterns.
276 (define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")])
278 ;; Iterator for hardware integer modes narrower than XLEN.
279 (define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")])
281 ;; Iterator for hardware-supported integer modes.
282 (define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
284 ;; Iterator for hardware-supported floating-point modes.
285 (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
286 (DF "TARGET_DOUBLE_FLOAT")])
288 ;; Iterator for floating-point modes that can be loaded into X registers.
289 (define_mode_iterator SOFTF [SF (DF "TARGET_64BIT")])
291 ;; This attribute gives the length suffix for a sign- or zero-extension
293 (define_mode_attr size [(QI "b") (HI "h")])
295 ;; Mode attributes for loads.
296 (define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
298 ;; Instruction names for integer loads that aren't explicitly sign or zero
299 ;; extended. See riscv_output_move and LOAD_EXTEND_OP.
300 (define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")])
302 ;; Mode attribute for FP loads into integer registers.
303 (define_mode_attr softload [(SF "lw") (DF "ld")])
305 ;; Instruction names for stores.
306 (define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
308 ;; Instruction names for FP stores from integer registers.
309 (define_mode_attr softstore [(SF "sw") (DF "sd")])
311 ;; This attribute gives the best constraint to use for registers of
313 (define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
315 ;; This attribute gives the format suffix for floating-point operations.
316 (define_mode_attr fmt [(SF "s") (DF "d")])
318 ;; This attribute gives the integer suffix for floating-point conversions.
319 (define_mode_attr ifmt [(SI "w") (DI "l")])
321 ;; This attribute gives the format suffix for atomic memory operations.
322 (define_mode_attr amo [(SI "w") (DI "d")])
324 ;; This attribute gives the upper-case mode name for one unit of a
325 ;; floating-point mode.
326 (define_mode_attr UNITMODE [(SF "SF") (DF "DF")])
328 ;; This attribute gives the integer mode that has half the size of
329 ;; the controlling mode.
330 (define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")])
332 ;; Iterator and attributes for floating-point rounding instructions.
333 (define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND])
334 (define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")])
335 (define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")])
337 ;; Iterator and attributes for quiet comparisons.
338 (define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET])
339 (define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")])
341 ;; This code iterator allows signed and unsigned widening multiplications
342 ;; to use the same template.
343 (define_code_iterator any_extend [sign_extend zero_extend])
345 ;; This code iterator allows the two right shift instructions to be
346 ;; generated from the same template.
347 (define_code_iterator any_shiftrt [ashiftrt lshiftrt])
349 ;; This code iterator allows the three shift instructions to be generated
350 ;; from the same template.
351 (define_code_iterator any_shift [ashift ashiftrt lshiftrt])
353 ;; This code iterator allows the three bitwise instructions to be generated
354 ;; from the same template.
355 (define_code_iterator any_bitwise [and ior xor])
357 ;; This code iterator allows unsigned and signed division to be generated
358 ;; from the same template.
359 (define_code_iterator any_div [div udiv mod umod])
361 ;; This code iterator allows unsigned and signed modulus to be generated
362 ;; from the same template.
363 (define_code_iterator any_mod [mod umod])
365 ;; These code iterators allow the signed and unsigned scc operations to use
366 ;; the same template.
367 (define_code_iterator any_gt [gt gtu])
368 (define_code_iterator any_ge [ge geu])
369 (define_code_iterator any_lt [lt ltu])
370 (define_code_iterator any_le [le leu])
372 ;; <u> expands to an empty string when doing a signed operation and
373 ;; "u" when doing an unsigned operation.
374 (define_code_attr u [(sign_extend "") (zero_extend "u")
380 ;; <su> is like <u>, but the signed form expands to "s" rather than "".
381 (define_code_attr su [(sign_extend "s") (zero_extend "u")])
383 ;; <optab> expands to the name of the optab for a particular code.
384 (define_code_attr optab [(ashift "ashl")
401 ;; <insn> expands to the name of the insn that implements a particular code.
402 (define_code_attr insn [(ashift "sll")
415 ;; Ghost instructions produce no real code and introduce no hazards.
416 ;; They exist purely to express an effect on dataflow.
417 (define_insn_reservation "ghost" 0
418 (eq_attr "type" "ghost")
422 ;; ....................
426 ;; ....................
429 (define_insn "add<mode>3"
430 [(set (match_operand:ANYF 0 "register_operand" "=f")
431 (plus:ANYF (match_operand:ANYF 1 "register_operand" " f")
432 (match_operand:ANYF 2 "register_operand" " f")))]
434 "fadd.<fmt>\t%0,%1,%2"
435 [(set_attr "type" "fadd")
436 (set_attr "mode" "<UNITMODE>")])
438 (define_insn "addsi3"
439 [(set (match_operand:SI 0 "register_operand" "=r,r")
440 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
441 (match_operand:SI 2 "arith_operand" " r,I")))]
443 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
444 [(set_attr "type" "arith")
445 (set_attr "mode" "SI")])
447 (define_insn "adddi3"
448 [(set (match_operand:DI 0 "register_operand" "=r,r")
449 (plus:DI (match_operand:DI 1 "register_operand" " r,r")
450 (match_operand:DI 2 "arith_operand" " r,I")))]
453 [(set_attr "type" "arith")
454 (set_attr "mode" "DI")])
456 (define_insn "*addsi3_extended"
457 [(set (match_operand:DI 0 "register_operand" "=r,r")
459 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
460 (match_operand:SI 2 "arith_operand" " r,I"))))]
463 [(set_attr "type" "arith")
464 (set_attr "mode" "SI")])
466 (define_insn "*addsi3_extended2"
467 [(set (match_operand:DI 0 "register_operand" "=r,r")
469 (subreg:SI (plus:DI (match_operand:DI 1 "register_operand" " r,r")
470 (match_operand:DI 2 "arith_operand" " r,I"))
474 [(set_attr "type" "arith")
475 (set_attr "mode" "SI")])
478 ;; ....................
482 ;; ....................
485 (define_insn "sub<mode>3"
486 [(set (match_operand:ANYF 0 "register_operand" "=f")
487 (minus:ANYF (match_operand:ANYF 1 "register_operand" " f")
488 (match_operand:ANYF 2 "register_operand" " f")))]
490 "fsub.<fmt>\t%0,%1,%2"
491 [(set_attr "type" "fadd")
492 (set_attr "mode" "<UNITMODE>")])
494 (define_insn "subdi3"
495 [(set (match_operand:DI 0 "register_operand" "= r")
496 (minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
497 (match_operand:DI 2 "register_operand" " r")))]
500 [(set_attr "type" "arith")
501 (set_attr "mode" "DI")])
503 (define_insn "subsi3"
504 [(set (match_operand:SI 0 "register_operand" "= r")
505 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
506 (match_operand:SI 2 "register_operand" " r")))]
508 { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; }
509 [(set_attr "type" "arith")
510 (set_attr "mode" "SI")])
512 (define_insn "*subsi3_extended"
513 [(set (match_operand:DI 0 "register_operand" "= r")
515 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
516 (match_operand:SI 2 "register_operand" " r"))))]
519 [(set_attr "type" "arith")
520 (set_attr "mode" "SI")])
522 (define_insn "*subsi3_extended2"
523 [(set (match_operand:DI 0 "register_operand" "= r")
525 (subreg:SI (minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
526 (match_operand:DI 2 "register_operand" " r"))
530 [(set_attr "type" "arith")
531 (set_attr "mode" "SI")])
533 (define_insn "negdi2"
534 [(set (match_operand:DI 0 "register_operand" "=r")
535 (neg:DI (match_operand:DI 1 "register_operand" " r")))]
538 [(set_attr "type" "arith")
539 (set_attr "mode" "DI")])
541 (define_insn "negsi2"
542 [(set (match_operand:SI 0 "register_operand" "=r")
543 (neg:SI (match_operand:SI 1 "register_operand" " r")))]
545 { return TARGET_64BIT ? "negw\t%0,%1" : "neg\t%0,%1"; }
546 [(set_attr "type" "arith")
547 (set_attr "mode" "SI")])
549 (define_insn "*negsi2_extended"
550 [(set (match_operand:DI 0 "register_operand" "=r")
552 (neg:SI (match_operand:SI 1 "register_operand" " r"))))]
555 [(set_attr "type" "arith")
556 (set_attr "mode" "SI")])
558 (define_insn "*negsi2_extended2"
559 [(set (match_operand:DI 0 "register_operand" "=r")
561 (subreg:SI (neg:DI (match_operand:DI 1 "register_operand" " r"))
565 [(set_attr "type" "arith")
566 (set_attr "mode" "SI")])
569 ;; ....................
573 ;; ....................
576 (define_insn "mul<mode>3"
577 [(set (match_operand:ANYF 0 "register_operand" "=f")
578 (mult:ANYF (match_operand:ANYF 1 "register_operand" " f")
579 (match_operand:ANYF 2 "register_operand" " f")))]
581 "fmul.<fmt>\t%0,%1,%2"
582 [(set_attr "type" "fmul")
583 (set_attr "mode" "<UNITMODE>")])
585 (define_insn "mulsi3"
586 [(set (match_operand:SI 0 "register_operand" "=r")
587 (mult:SI (match_operand:SI 1 "register_operand" " r")
588 (match_operand:SI 2 "register_operand" " r")))]
590 { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; }
591 [(set_attr "type" "imul")
592 (set_attr "mode" "SI")])
594 (define_insn "muldi3"
595 [(set (match_operand:DI 0 "register_operand" "=r")
596 (mult:DI (match_operand:DI 1 "register_operand" " r")
597 (match_operand:DI 2 "register_operand" " r")))]
598 "TARGET_MUL && TARGET_64BIT"
600 [(set_attr "type" "imul")
601 (set_attr "mode" "DI")])
603 (define_insn "*mulsi3_extended"
604 [(set (match_operand:DI 0 "register_operand" "=r")
606 (mult:SI (match_operand:SI 1 "register_operand" " r")
607 (match_operand:SI 2 "register_operand" " r"))))]
608 "TARGET_MUL && TARGET_64BIT"
610 [(set_attr "type" "imul")
611 (set_attr "mode" "SI")])
613 (define_insn "*mulsi3_extended2"
614 [(set (match_operand:DI 0 "register_operand" "=r")
616 (subreg:SI (mult:DI (match_operand:DI 1 "register_operand" " r")
617 (match_operand:DI 2 "register_operand" " r"))
619 "TARGET_MUL && TARGET_64BIT"
621 [(set_attr "type" "imul")
622 (set_attr "mode" "SI")])
625 ;; ........................
627 ;; MULTIPLICATION HIGH-PART
629 ;; ........................
633 (define_expand "<u>mulditi3"
634 [(set (match_operand:TI 0 "register_operand")
635 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
636 (any_extend:TI (match_operand:DI 2 "register_operand"))))]
637 "TARGET_MUL && TARGET_64BIT"
639 rtx low = gen_reg_rtx (DImode);
640 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
642 rtx high = gen_reg_rtx (DImode);
643 emit_insn (gen_<u>muldi3_highpart (high, operands[1], operands[2]));
645 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
646 emit_move_insn (gen_highpart (DImode, operands[0]), high);
650 (define_insn "<u>muldi3_highpart"
651 [(set (match_operand:DI 0 "register_operand" "=r")
654 (mult:TI (any_extend:TI
655 (match_operand:DI 1 "register_operand" " r"))
657 (match_operand:DI 2 "register_operand" " r")))
659 "TARGET_MUL && TARGET_64BIT"
661 [(set_attr "type" "imul")
662 (set_attr "mode" "DI")])
664 (define_expand "usmulditi3"
665 [(set (match_operand:TI 0 "register_operand")
666 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand"))
667 (sign_extend:TI (match_operand:DI 2 "register_operand"))))]
668 "TARGET_MUL && TARGET_64BIT"
670 rtx low = gen_reg_rtx (DImode);
671 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
673 rtx high = gen_reg_rtx (DImode);
674 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2]));
676 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
677 emit_move_insn (gen_highpart (DImode, operands[0]), high);
681 (define_insn "usmuldi3_highpart"
682 [(set (match_operand:DI 0 "register_operand" "=r")
685 (mult:TI (zero_extend:TI
686 (match_operand:DI 1 "register_operand" "r"))
688 (match_operand:DI 2 "register_operand" " r")))
690 "TARGET_MUL && TARGET_64BIT"
692 [(set_attr "type" "imul")
693 (set_attr "mode" "DI")])
695 (define_expand "<u>mulsidi3"
696 [(set (match_operand:DI 0 "register_operand" "=r")
697 (mult:DI (any_extend:DI
698 (match_operand:SI 1 "register_operand" " r"))
700 (match_operand:SI 2 "register_operand" " r"))))]
701 "TARGET_MUL && !TARGET_64BIT"
703 rtx temp = gen_reg_rtx (SImode);
704 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
705 emit_insn (gen_<u>mulsi3_highpart (riscv_subword (operands[0], true),
706 operands[1], operands[2]));
707 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
711 (define_insn "<u>mulsi3_highpart"
712 [(set (match_operand:SI 0 "register_operand" "=r")
715 (mult:DI (any_extend:DI
716 (match_operand:SI 1 "register_operand" " r"))
718 (match_operand:SI 2 "register_operand" " r")))
720 "TARGET_MUL && !TARGET_64BIT"
722 [(set_attr "type" "imul")
723 (set_attr "mode" "SI")])
726 (define_expand "usmulsidi3"
727 [(set (match_operand:DI 0 "register_operand" "=r")
728 (mult:DI (zero_extend:DI
729 (match_operand:SI 1 "register_operand" " r"))
731 (match_operand:SI 2 "register_operand" " r"))))]
732 "TARGET_MUL && !TARGET_64BIT"
734 rtx temp = gen_reg_rtx (SImode);
735 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
736 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true),
737 operands[1], operands[2]));
738 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
742 (define_insn "usmulsi3_highpart"
743 [(set (match_operand:SI 0 "register_operand" "=r")
746 (mult:DI (zero_extend:DI
747 (match_operand:SI 1 "register_operand" " r"))
749 (match_operand:SI 2 "register_operand" " r")))
751 "TARGET_MUL && !TARGET_64BIT"
753 [(set_attr "type" "imul")
754 (set_attr "mode" "SI")])
757 ;; ....................
759 ;; DIVISION and REMAINDER
761 ;; ....................
764 (define_insn "<optab>si3"
765 [(set (match_operand:SI 0 "register_operand" "=r")
766 (any_div:SI (match_operand:SI 1 "register_operand" " r")
767 (match_operand:SI 2 "register_operand" " r")))]
769 { return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2"; }
770 [(set_attr "type" "idiv")
771 (set_attr "mode" "SI")])
773 (define_insn "<optab>di3"
774 [(set (match_operand:DI 0 "register_operand" "=r")
775 (any_div:DI (match_operand:DI 1 "register_operand" " r")
776 (match_operand:DI 2 "register_operand" " r")))]
777 "TARGET_DIV && TARGET_64BIT"
778 "<insn>%i2\t%0,%1,%2"
779 [(set_attr "type" "idiv")
780 (set_attr "mode" "DI")])
782 (define_insn "*<optab>si3_extended"
783 [(set (match_operand:DI 0 "register_operand" "=r")
785 (any_div:SI (match_operand:SI 1 "register_operand" " r")
786 (match_operand:SI 2 "register_operand" " r"))))]
787 "TARGET_DIV && TARGET_64BIT"
788 "<insn>%i2w\t%0,%1,%2"
789 [(set_attr "type" "idiv")
790 (set_attr "mode" "DI")])
792 (define_insn "div<mode>3"
793 [(set (match_operand:ANYF 0 "register_operand" "=f")
794 (div:ANYF (match_operand:ANYF 1 "register_operand" " f")
795 (match_operand:ANYF 2 "register_operand" " f")))]
796 "TARGET_HARD_FLOAT && TARGET_FDIV"
797 "fdiv.<fmt>\t%0,%1,%2"
798 [(set_attr "type" "fdiv")
799 (set_attr "mode" "<UNITMODE>")])
802 ;; ....................
806 ;; ....................
808 (define_insn "sqrt<mode>2"
809 [(set (match_operand:ANYF 0 "register_operand" "=f")
810 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
811 "TARGET_HARD_FLOAT && TARGET_FDIV"
813 return "fsqrt.<fmt>\t%0,%1";
815 [(set_attr "type" "fsqrt")
816 (set_attr "mode" "<UNITMODE>")])
818 ;; Floating point multiply accumulate instructions.
821 (define_insn "fma<mode>4"
822 [(set (match_operand:ANYF 0 "register_operand" "=f")
823 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
824 (match_operand:ANYF 2 "register_operand" " f")
825 (match_operand:ANYF 3 "register_operand" " f")))]
827 "fmadd.<fmt>\t%0,%1,%2,%3"
828 [(set_attr "type" "fmadd")
829 (set_attr "mode" "<UNITMODE>")])
832 (define_insn "fms<mode>4"
833 [(set (match_operand:ANYF 0 "register_operand" "=f")
834 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
835 (match_operand:ANYF 2 "register_operand" " f")
836 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
838 "fmsub.<fmt>\t%0,%1,%2,%3"
839 [(set_attr "type" "fmadd")
840 (set_attr "mode" "<UNITMODE>")])
843 (define_insn "fnms<mode>4"
844 [(set (match_operand:ANYF 0 "register_operand" "=f")
846 (neg:ANYF (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"))))]
850 "fnmadd.<fmt>\t%0,%1,%2,%3"
851 [(set_attr "type" "fmadd")
852 (set_attr "mode" "<UNITMODE>")])
855 (define_insn "fnma<mode>4"
856 [(set (match_operand:ANYF 0 "register_operand" "=f")
858 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
859 (match_operand:ANYF 2 "register_operand" " f")
860 (match_operand:ANYF 3 "register_operand" " f")))]
862 "fnmsub.<fmt>\t%0,%1,%2,%3"
863 [(set_attr "type" "fmadd")
864 (set_attr "mode" "<UNITMODE>")])
866 ;; -(-a * b - c), modulo signed zeros
867 (define_insn "*fma<mode>4"
868 [(set (match_operand:ANYF 0 "register_operand" "=f")
871 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
872 (match_operand:ANYF 2 "register_operand" " f")
873 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
874 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
875 "fmadd.<fmt>\t%0,%1,%2,%3"
876 [(set_attr "type" "fmadd")
877 (set_attr "mode" "<UNITMODE>")])
879 ;; -(-a * b + c), modulo signed zeros
880 (define_insn "*fms<mode>4"
881 [(set (match_operand:ANYF 0 "register_operand" "=f")
884 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
885 (match_operand:ANYF 2 "register_operand" " f")
886 (match_operand:ANYF 3 "register_operand" " f"))))]
887 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
888 "fmsub.<fmt>\t%0,%1,%2,%3"
889 [(set_attr "type" "fmadd")
890 (set_attr "mode" "<UNITMODE>")])
892 ;; -(a * b + c), modulo signed zeros
893 (define_insn "*fnms<mode>4"
894 [(set (match_operand:ANYF 0 "register_operand" "=f")
897 (match_operand:ANYF 1 "register_operand" " f")
898 (match_operand:ANYF 2 "register_operand" " f")
899 (match_operand:ANYF 3 "register_operand" " f"))))]
900 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
901 "fnmadd.<fmt>\t%0,%1,%2,%3"
902 [(set_attr "type" "fmadd")
903 (set_attr "mode" "<UNITMODE>")])
905 ;; -(a * b - c), modulo signed zeros
906 (define_insn "*fnma<mode>4"
907 [(set (match_operand:ANYF 0 "register_operand" "=f")
910 (match_operand:ANYF 1 "register_operand" " f")
911 (match_operand:ANYF 2 "register_operand" " f")
912 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
913 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
914 "fnmsub.<fmt>\t%0,%1,%2,%3"
915 [(set_attr "type" "fmadd")
916 (set_attr "mode" "<UNITMODE>")])
919 ;; ....................
923 ;; ....................
925 (define_insn "abs<mode>2"
926 [(set (match_operand:ANYF 0 "register_operand" "=f")
927 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
930 [(set_attr "type" "fmove")
931 (set_attr "mode" "<UNITMODE>")])
933 (define_insn "copysign<mode>3"
934 [(set (match_operand:ANYF 0 "register_operand" "=f")
935 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")
936 (match_operand:ANYF 2 "register_operand" " f")]
939 "fsgnj.<fmt>\t%0,%1,%2"
940 [(set_attr "type" "fmove")
941 (set_attr "mode" "<UNITMODE>")])
943 (define_insn "neg<mode>2"
944 [(set (match_operand:ANYF 0 "register_operand" "=f")
945 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
948 [(set_attr "type" "fmove")
949 (set_attr "mode" "<UNITMODE>")])
952 ;; ....................
956 ;; ....................
958 (define_insn "smin<mode>3"
959 [(set (match_operand:ANYF 0 "register_operand" "=f")
960 (smin:ANYF (match_operand:ANYF 1 "register_operand" " f")
961 (match_operand:ANYF 2 "register_operand" " f")))]
963 "fmin.<fmt>\t%0,%1,%2"
964 [(set_attr "type" "fmove")
965 (set_attr "mode" "<UNITMODE>")])
967 (define_insn "smax<mode>3"
968 [(set (match_operand:ANYF 0 "register_operand" "=f")
969 (smax:ANYF (match_operand:ANYF 1 "register_operand" " f")
970 (match_operand:ANYF 2 "register_operand" " f")))]
972 "fmax.<fmt>\t%0,%1,%2"
973 [(set_attr "type" "fmove")
974 (set_attr "mode" "<UNITMODE>")])
977 ;; ....................
981 ;; ....................
984 ;; For RV64, we don't expose the SImode operations to the rtl expanders,
985 ;; but SImode versions exist for combine.
987 (define_insn "<optab><mode>3"
988 [(set (match_operand:X 0 "register_operand" "=r,r")
989 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
990 (match_operand:X 2 "arith_operand" " r,I")))]
992 "<insn>%i2\t%0,%1,%2"
993 [(set_attr "type" "logical")
994 (set_attr "mode" "<MODE>")])
996 (define_insn "*<optab>si3_internal"
997 [(set (match_operand:SI 0 "register_operand" "=r,r")
998 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
999 (match_operand:SI 2 "arith_operand" " r,I")))]
1001 "<insn>%i2\t%0,%1,%2"
1002 [(set_attr "type" "logical")
1003 (set_attr "mode" "SI")])
1005 (define_insn "one_cmpl<mode>2"
1006 [(set (match_operand:X 0 "register_operand" "=r")
1007 (not:X (match_operand:X 1 "register_operand" " r")))]
1010 [(set_attr "type" "logical")
1011 (set_attr "mode" "<MODE>")])
1013 (define_insn "*one_cmplsi2_internal"
1014 [(set (match_operand:SI 0 "register_operand" "=r")
1015 (not:SI (match_operand:SI 1 "register_operand" " r")))]
1018 [(set_attr "type" "logical")
1019 (set_attr "mode" "SI")])
1022 ;; ....................
1026 ;; ....................
1028 (define_insn "truncdfsf2"
1029 [(set (match_operand:SF 0 "register_operand" "=f")
1031 (match_operand:DF 1 "register_operand" " f")))]
1032 "TARGET_DOUBLE_FLOAT"
1034 [(set_attr "type" "fcvt")
1035 (set_attr "mode" "SF")])
1038 ;; ....................
1042 ;; ....................
1046 (define_insn_and_split "zero_extendsidi2"
1047 [(set (match_operand:DI 0 "register_operand" "=r,r")
1049 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1054 "&& reload_completed
1055 && REG_P (operands[1])
1056 && !paradoxical_subreg_p (operands[0])"
1058 (ashift:DI (match_dup 1) (const_int 32)))
1060 (lshiftrt:DI (match_dup 0) (const_int 32)))]
1061 { operands[1] = gen_lowpart (DImode, operands[1]); }
1062 [(set_attr "move_type" "shift_shift,load")
1063 (set_attr "mode" "DI")])
1065 (define_insn_and_split "zero_extendhi<GPR:mode>2"
1066 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1068 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
1073 "&& reload_completed
1074 && REG_P (operands[1])
1075 && !paradoxical_subreg_p (operands[0])"
1077 (ashift:GPR (match_dup 1) (match_dup 2)))
1079 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1081 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1082 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1084 [(set_attr "move_type" "shift_shift,load")
1085 (set_attr "mode" "<GPR:MODE>")])
1087 (define_insn "zero_extendqi<SUPERQI:mode>2"
1088 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1089 (zero_extend:SUPERQI
1090 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
1095 [(set_attr "move_type" "andi,load")
1096 (set_attr "mode" "<SUPERQI:MODE>")])
1099 ;; ....................
1103 ;; ....................
1105 (define_insn "extendsidi2"
1106 [(set (match_operand:DI 0 "register_operand" "=r,r")
1108 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1113 [(set_attr "move_type" "move,load")
1114 (set_attr "mode" "DI")])
1116 (define_insn_and_split "extend<SHORT:mode><SUPERQI:mode>2"
1117 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1118 (sign_extend:SUPERQI
1119 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
1123 l<SHORT:size>\t%0,%1"
1124 "&& reload_completed
1125 && REG_P (operands[1])
1126 && !paradoxical_subreg_p (operands[0])"
1127 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1128 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
1130 operands[0] = gen_lowpart (SImode, operands[0]);
1131 operands[1] = gen_lowpart (SImode, operands[1]);
1132 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1133 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1135 [(set_attr "move_type" "shift_shift,load")
1136 (set_attr "mode" "SI")])
1138 (define_insn "extendsfdf2"
1139 [(set (match_operand:DF 0 "register_operand" "=f")
1141 (match_operand:SF 1 "register_operand" " f")))]
1142 "TARGET_DOUBLE_FLOAT"
1144 [(set_attr "type" "fcvt")
1145 (set_attr "mode" "DF")])
1148 ;; ....................
1152 ;; ....................
1154 (define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
1155 [(set (match_operand:GPR 0 "register_operand" "=r")
1157 (match_operand:ANYF 1 "register_operand" " f")))]
1159 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
1160 [(set_attr "type" "fcvt")
1161 (set_attr "mode" "<ANYF:MODE>")])
1163 (define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2"
1164 [(set (match_operand:GPR 0 "register_operand" "=r")
1166 (match_operand:ANYF 1 "register_operand" " f")))]
1168 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
1169 [(set_attr "type" "fcvt")
1170 (set_attr "mode" "<ANYF:MODE>")])
1172 (define_insn "float<GPR:mode><ANYF:mode>2"
1173 [(set (match_operand:ANYF 0 "register_operand" "= f")
1175 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
1177 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
1178 [(set_attr "type" "fcvt")
1179 (set_attr "mode" "<ANYF:MODE>")])
1181 (define_insn "floatuns<GPR:mode><ANYF:mode>2"
1182 [(set (match_operand:ANYF 0 "register_operand" "= f")
1183 (unsigned_float:ANYF
1184 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
1186 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
1187 [(set_attr "type" "fcvt")
1188 (set_attr "mode" "<ANYF:MODE>")])
1190 (define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2"
1191 [(set (match_operand:GPR 0 "register_operand" "=r")
1193 [(match_operand:ANYF 1 "register_operand" " f")]
1196 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
1197 [(set_attr "type" "fcvt")
1198 (set_attr "mode" "<ANYF:MODE>")])
1201 ;; ....................
1205 ;; ....................
1207 ;; Lower-level instructions for loading an address from the GOT.
1208 ;; We could use MEMs, but an unspec gives more optimization
1211 (define_insn "got_load<mode>"
1212 [(set (match_operand:P 0 "register_operand" "=r")
1214 [(match_operand:P 1 "symbolic_operand" "")]
1218 [(set_attr "got" "load")
1219 (set_attr "mode" "<MODE>")])
1221 (define_insn "tls_add_tp_le<mode>"
1222 [(set (match_operand:P 0 "register_operand" "=r")
1224 [(match_operand:P 1 "register_operand" "r")
1225 (match_operand:P 2 "register_operand" "r")
1226 (match_operand:P 3 "symbolic_operand" "")]
1229 "add\t%0,%1,%2,%%tprel_add(%3)"
1230 [(set_attr "type" "arith")
1231 (set_attr "mode" "<MODE>")])
1233 (define_insn "got_load_tls_gd<mode>"
1234 [(set (match_operand:P 0 "register_operand" "=r")
1236 [(match_operand:P 1 "symbolic_operand" "")]
1240 [(set_attr "got" "load")
1241 (set_attr "mode" "<MODE>")])
1243 (define_insn "got_load_tls_ie<mode>"
1244 [(set (match_operand:P 0 "register_operand" "=r")
1246 [(match_operand:P 1 "symbolic_operand" "")]
1250 [(set_attr "got" "load")
1251 (set_attr "mode" "<MODE>")])
1253 (define_insn "auipc<mode>"
1254 [(set (match_operand:P 0 "register_operand" "=r")
1256 [(match_operand:P 1 "symbolic_operand" "")
1257 (match_operand:P 2 "const_int_operand")
1261 ".LA%2: auipc\t%0,%h1"
1262 [(set_attr "type" "auipc")
1263 (set_attr "cannot_copy" "yes")])
1265 ;; Instructions for adding the low 12 bits of an address to a register.
1266 ;; Operand 2 is the address: riscv_print_operand works out which relocation
1267 ;; should be applied.
1269 (define_insn "*low<mode>"
1270 [(set (match_operand:P 0 "register_operand" "=r")
1271 (lo_sum:P (match_operand:P 1 "register_operand" " r")
1272 (match_operand:P 2 "symbolic_operand" "")))]
1275 [(set_attr "type" "arith")
1276 (set_attr "mode" "<MODE>")])
1278 ;; Allow combine to split complex const_int load sequences, using operand 2
1279 ;; to store the intermediate results. See move_operand for details.
1281 [(set (match_operand:GPR 0 "register_operand")
1282 (match_operand:GPR 1 "splittable_const_int_operand"))
1283 (clobber (match_operand:GPR 2 "register_operand"))]
1287 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
1288 <GPR:MODE>mode, TRUE);
1292 ;; Likewise, for symbolic operands.
1294 [(set (match_operand:P 0 "register_operand")
1295 (match_operand:P 1))
1296 (clobber (match_operand:P 2 "register_operand"))]
1297 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL, TRUE)"
1298 [(set (match_dup 0) (match_dup 3))]
1300 riscv_split_symbol (operands[2], operands[1],
1301 MAX_MACHINE_MODE, &operands[3], TRUE);
1304 ;; 64-bit integer moves
1306 (define_expand "movdi"
1307 [(set (match_operand:DI 0 "")
1308 (match_operand:DI 1 ""))]
1311 if (riscv_legitimize_move (DImode, operands[0], operands[1]))
1315 (define_insn "*movdi_32bit"
1316 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m")
1317 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))]
1319 && (register_operand (operands[0], DImode)
1320 || reg_or_0_operand (operands[1], DImode))"
1321 { return riscv_output_move (operands[0], operands[1]); }
1322 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1323 (set_attr "mode" "DI")])
1325 (define_insn "*movdi_64bit"
1326 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m")
1327 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))]
1329 && (register_operand (operands[0], DImode)
1330 || reg_or_0_operand (operands[1], DImode))"
1331 { return riscv_output_move (operands[0], operands[1]); }
1332 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1333 (set_attr "mode" "DI")])
1335 ;; 32-bit Integer moves
1337 (define_expand "mov<mode>"
1338 [(set (match_operand:MOVE32 0 "")
1339 (match_operand:MOVE32 1 ""))]
1342 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
1346 (define_insn "*movsi_internal"
1347 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m")
1348 (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f"))]
1349 "(register_operand (operands[0], SImode)
1350 || reg_or_0_operand (operands[1], SImode))"
1351 { return riscv_output_move (operands[0], operands[1]); }
1352 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
1353 (set_attr "mode" "SI")])
1355 ;; 16-bit Integer moves
1357 ;; Unlike most other insns, the move insns can't be split with
1358 ;; different predicates, because register spilling and other parts of
1359 ;; the compiler, have memoized the insn number already.
1360 ;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
1362 (define_expand "movhi"
1363 [(set (match_operand:HI 0 "")
1364 (match_operand:HI 1 ""))]
1367 if (riscv_legitimize_move (HImode, operands[0], operands[1]))
1371 (define_insn "*movhi_internal"
1372 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1373 (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f"))]
1374 "(register_operand (operands[0], HImode)
1375 || reg_or_0_operand (operands[1], HImode))"
1376 { return riscv_output_move (operands[0], operands[1]); }
1377 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1378 (set_attr "mode" "HI")])
1380 ;; HImode constant generation; see riscv_move_integer for details.
1381 ;; si+si->hi without truncation is legal because of
1382 ;; TARGET_TRULY_NOOP_TRUNCATION.
1384 (define_insn "*add<mode>hi3"
1385 [(set (match_operand:HI 0 "register_operand" "=r,r")
1386 (plus:HI (match_operand:HISI 1 "register_operand" " r,r")
1387 (match_operand:HISI 2 "arith_operand" " r,I")))]
1389 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
1390 [(set_attr "type" "arith")
1391 (set_attr "mode" "HI")])
1393 (define_insn "*xor<mode>hi3"
1394 [(set (match_operand:HI 0 "register_operand" "=r,r")
1395 (xor:HI (match_operand:HISI 1 "register_operand" " r,r")
1396 (match_operand:HISI 2 "arith_operand" " r,I")))]
1399 [(set_attr "type" "logical")
1400 (set_attr "mode" "HI")])
1402 ;; 8-bit Integer moves
1404 (define_expand "movqi"
1405 [(set (match_operand:QI 0 "")
1406 (match_operand:QI 1 ""))]
1409 if (riscv_legitimize_move (QImode, operands[0], operands[1]))
1413 (define_insn "*movqi_internal"
1414 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1415 (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f"))]
1416 "(register_operand (operands[0], QImode)
1417 || reg_or_0_operand (operands[1], QImode))"
1418 { return riscv_output_move (operands[0], operands[1]); }
1419 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1420 (set_attr "mode" "QI")])
1422 ;; 32-bit floating point moves
1424 (define_expand "movsf"
1425 [(set (match_operand:SF 0 "")
1426 (match_operand:SF 1 ""))]
1429 if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
1433 (define_insn "*movsf_hardfloat"
1434 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1435 (match_operand:SF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
1437 && (register_operand (operands[0], SFmode)
1438 || reg_or_0_operand (operands[1], SFmode))"
1439 { return riscv_output_move (operands[0], operands[1]); }
1440 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1441 (set_attr "mode" "SF")])
1443 (define_insn "*movsf_softfloat"
1444 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
1445 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
1447 && (register_operand (operands[0], SFmode)
1448 || reg_or_0_operand (operands[1], SFmode))"
1449 { return riscv_output_move (operands[0], operands[1]); }
1450 [(set_attr "move_type" "move,load,store")
1451 (set_attr "mode" "SF")])
1453 ;; 64-bit floating point moves
1455 (define_expand "movdf"
1456 [(set (match_operand:DF 0 "")
1457 (match_operand:DF 1 ""))]
1460 if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
1464 ;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
1465 ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
1466 (define_insn "*movdf_hardfloat_rv32"
1467 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m")
1468 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))]
1469 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
1470 && (register_operand (operands[0], DFmode)
1471 || reg_or_0_operand (operands[1], DFmode))"
1472 { return riscv_output_move (operands[0], operands[1]); }
1473 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store")
1474 (set_attr "mode" "DF")])
1476 (define_insn "*movdf_hardfloat_rv64"
1477 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1478 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
1479 "TARGET_64BIT && TARGET_DOUBLE_FLOAT
1480 && (register_operand (operands[0], DFmode)
1481 || reg_or_0_operand (operands[1], DFmode))"
1482 { return riscv_output_move (operands[0], operands[1]); }
1483 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1484 (set_attr "mode" "DF")])
1486 (define_insn "*movdf_softfloat"
1487 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
1488 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
1489 "!TARGET_DOUBLE_FLOAT
1490 && (register_operand (operands[0], DFmode)
1491 || reg_or_0_operand (operands[1], DFmode))"
1492 { return riscv_output_move (operands[0], operands[1]); }
1493 [(set_attr "move_type" "move,load,store")
1494 (set_attr "mode" "DF")])
1497 [(set (match_operand:MOVE64 0 "nonimmediate_operand")
1498 (match_operand:MOVE64 1 "move_operand"))]
1500 && riscv_split_64bit_move_p (operands[0], operands[1])"
1503 riscv_split_doubleword_move (operands[0], operands[1]);
1507 (define_expand "cpymemsi"
1508 [(parallel [(set (match_operand:BLK 0 "general_operand")
1509 (match_operand:BLK 1 "general_operand"))
1510 (use (match_operand:SI 2 ""))
1511 (use (match_operand:SI 3 "const_int_operand"))])]
1514 if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
1520 ;; Expand in-line code to clear the instruction cache between operand[0] and
1522 (define_expand "clear_cache"
1523 [(match_operand 0 "pmode_register_operand")
1524 (match_operand 1 "pmode_register_operand")]
1527 #ifdef ICACHE_FLUSH_FUNC
1528 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC),
1529 LCT_NORMAL, VOIDmode, operands[0], Pmode,
1530 operands[1], Pmode, const0_rtx, Pmode);
1532 emit_insn (gen_fence_i ());
1537 (define_insn "fence"
1538 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
1542 (define_insn "fence_i"
1543 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
1548 ;; ....................
1552 ;; ....................
1554 ;; Use a QImode shift count, to avoid generating sign or zero extend
1555 ;; instructions for shift counts, and to avoid dropping subregs.
1556 ;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
1557 ;; defined, but use of that is discouraged.
1559 (define_insn "<optab>si3"
1560 [(set (match_operand:SI 0 "register_operand" "= r")
1562 (match_operand:SI 1 "register_operand" " r")
1563 (match_operand:QI 2 "arith_operand" " rI")))]
1566 if (GET_CODE (operands[2]) == CONST_INT)
1567 operands[2] = GEN_INT (INTVAL (operands[2])
1568 & (GET_MODE_BITSIZE (SImode) - 1));
1570 return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2";
1572 [(set_attr "type" "shift")
1573 (set_attr "mode" "SI")])
1575 (define_insn_and_split "*<optab>si3_mask"
1576 [(set (match_operand:SI 0 "register_operand" "= r")
1578 (match_operand:SI 1 "register_operand" " r")
1581 (match_operand:SI 2 "register_operand" "r")
1582 (match_operand 3 "const_int_operand")) 0)))]
1583 "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1584 == GET_MODE_BITSIZE (SImode)-1"
1588 (any_shift:SI (match_dup 1)
1590 "operands[2] = gen_lowpart (QImode, operands[2]);"
1591 [(set_attr "type" "shift")
1592 (set_attr "mode" "SI")])
1594 (define_insn_and_split "*<optab>si3_mask_1"
1595 [(set (match_operand:SI 0 "register_operand" "= r")
1597 (match_operand:SI 1 "register_operand" " r")
1600 (match_operand:DI 2 "register_operand" "r")
1601 (match_operand 3 "const_int_operand")) 0)))]
1603 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1604 == GET_MODE_BITSIZE (SImode)-1"
1608 (any_shift:SI (match_dup 1)
1610 "operands[2] = gen_lowpart (QImode, operands[2]);"
1611 [(set_attr "type" "shift")
1612 (set_attr "mode" "SI")])
1614 (define_insn "<optab>di3"
1615 [(set (match_operand:DI 0 "register_operand" "= r")
1617 (match_operand:DI 1 "register_operand" " r")
1618 (match_operand:QI 2 "arith_operand" " rI")))]
1621 if (GET_CODE (operands[2]) == CONST_INT)
1622 operands[2] = GEN_INT (INTVAL (operands[2])
1623 & (GET_MODE_BITSIZE (DImode) - 1));
1625 return "<insn>%i2\t%0,%1,%2";
1627 [(set_attr "type" "shift")
1628 (set_attr "mode" "DI")])
1630 (define_insn_and_split "*<optab>di3_mask"
1631 [(set (match_operand:DI 0 "register_operand" "= r")
1633 (match_operand:DI 1 "register_operand" " r")
1636 (match_operand:SI 2 "register_operand" "r")
1637 (match_operand 3 "const_int_operand")) 0)))]
1639 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1640 == GET_MODE_BITSIZE (DImode)-1"
1644 (any_shift:DI (match_dup 1)
1646 "operands[2] = gen_lowpart (QImode, operands[2]);"
1647 [(set_attr "type" "shift")
1648 (set_attr "mode" "DI")])
1650 (define_insn_and_split "*<optab>di3_mask_1"
1651 [(set (match_operand:DI 0 "register_operand" "= r")
1653 (match_operand:DI 1 "register_operand" " r")
1656 (match_operand:DI 2 "register_operand" "r")
1657 (match_operand 3 "const_int_operand")) 0)))]
1659 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1660 == GET_MODE_BITSIZE (DImode)-1"
1664 (any_shift:DI (match_dup 1)
1666 "operands[2] = gen_lowpart (QImode, operands[2]);"
1667 [(set_attr "type" "shift")
1668 (set_attr "mode" "DI")])
1670 (define_insn "*<optab>si3_extend"
1671 [(set (match_operand:DI 0 "register_operand" "= r")
1673 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
1674 (match_operand:QI 2 "arith_operand" " rI"))))]
1677 if (GET_CODE (operands[2]) == CONST_INT)
1678 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1680 return "<insn>%i2w\t%0,%1,%2";
1682 [(set_attr "type" "shift")
1683 (set_attr "mode" "SI")])
1685 (define_insn_and_split "*<optab>si3_extend_mask"
1686 [(set (match_operand:DI 0 "register_operand" "= r")
1689 (match_operand:SI 1 "register_operand" " r")
1692 (match_operand:SI 2 "register_operand" " r")
1693 (match_operand 3 "const_int_operand")) 0))))]
1695 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1696 == GET_MODE_BITSIZE (SImode)-1"
1701 (any_shift:SI (match_dup 1)
1703 "operands[2] = gen_lowpart (QImode, operands[2]);"
1704 [(set_attr "type" "shift")
1705 (set_attr "mode" "SI")])
1707 (define_insn_and_split "*<optab>si3_extend_mask_1"
1708 [(set (match_operand:DI 0 "register_operand" "= r")
1711 (match_operand:SI 1 "register_operand" " r")
1714 (match_operand:DI 2 "register_operand" " r")
1715 (match_operand 3 "const_int_operand")) 0))))]
1717 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1718 == GET_MODE_BITSIZE (SImode)-1"
1723 (any_shift:SI (match_dup 1)
1725 "operands[2] = gen_lowpart (QImode, operands[2]);"
1726 [(set_attr "type" "shift")
1727 (set_attr "mode" "SI")])
1729 ;; Non-canonical, but can be formed by ree when combine is not successful at
1730 ;; producing one of the two canonical patterns below.
1731 (define_insn "*lshrsi3_zero_extend_1"
1732 [(set (match_operand:DI 0 "register_operand" "=r")
1734 (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
1735 (match_operand 2 "const_int_operand"))))]
1736 "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
1738 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1740 return "srliw\t%0,%1,%2";
1742 [(set_attr "type" "shift")
1743 (set_attr "mode" "SI")])
1745 ;; Canonical form for a zero-extend of a logical right shift.
1746 (define_insn "*lshrsi3_zero_extend_2"
1747 [(set (match_operand:DI 0 "register_operand" "=r")
1748 (zero_extract:DI (match_operand:DI 1 "register_operand" " r")
1749 (match_operand 2 "const_int_operand")
1750 (match_operand 3 "const_int_operand")))]
1751 "(TARGET_64BIT && (INTVAL (operands[3]) > 0)
1752 && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
1754 return "srliw\t%0,%1,%3";
1756 [(set_attr "type" "shift")
1757 (set_attr "mode" "SI")])
1759 ;; Canonical form for a zero-extend of a logical right shift when the
1760 ;; shift count is 31.
1761 (define_insn "*lshrsi3_zero_extend_3"
1762 [(set (match_operand:DI 0 "register_operand" "=r")
1763 (lt:DI (match_operand:SI 1 "register_operand" " r")
1767 return "srliw\t%0,%1,31";
1769 [(set_attr "type" "shift")
1770 (set_attr "mode" "SI")])
1772 ;; Handle AND with 2^N-1 for N from 12 to XLEN. This can be split into
1773 ;; two logical shifts. Otherwise it requires 3 instructions: lui,
1774 ;; xor/addi/srli, and.
1776 ;; Generating a temporary for the shift output gives better combiner results;
1777 ;; and also fixes a problem where op0 could be a paradoxical reg and shifting
1778 ;; by amounts larger than the size of the SUBREG_REG doesn't work.
1780 [(set (match_operand:GPR 0 "register_operand")
1781 (and:GPR (match_operand:GPR 1 "register_operand")
1782 (match_operand:GPR 2 "p2m1_shift_operand")))
1783 (clobber (match_operand:GPR 3 "register_operand"))]
1786 (ashift:GPR (match_dup 1) (match_dup 2)))
1788 (lshiftrt:GPR (match_dup 3) (match_dup 2)))]
1790 /* Op2 is a VOIDmode constant, so get the mode size from op1. */
1791 operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1]))
1792 - exact_log2 (INTVAL (operands[2]) + 1));
1795 ;; Handle AND with 0xF...F0...0 where there are 32 to 63 zeros. This can be
1796 ;; split into two shifts. Otherwise it requires 3 instructions: li, sll, and.
1798 [(set (match_operand:DI 0 "register_operand")
1799 (and:DI (match_operand:DI 1 "register_operand")
1800 (match_operand:DI 2 "high_mask_shift_operand")))
1801 (clobber (match_operand:DI 3 "register_operand"))]
1804 (lshiftrt:DI (match_dup 1) (match_dup 2)))
1806 (ashift:DI (match_dup 3) (match_dup 2)))]
1808 operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2])));
1812 ;; ....................
1814 ;; CONDITIONAL BRANCHES
1816 ;; ....................
1818 ;; Conditional branches
1820 (define_insn "*branch<mode>"
1823 (match_operator 1 "order_operator"
1824 [(match_operand:X 2 "register_operand" "r")
1825 (match_operand:X 3 "reg_or_0_operand" "rJ")])
1826 (label_ref (match_operand 0 "" ""))
1830 [(set_attr "type" "branch")
1831 (set_attr "mode" "none")])
1833 ;; Patterns for implementations that optimize short forward branches.
1835 (define_expand "mov<mode>cc"
1836 [(set (match_operand:GPR 0 "register_operand")
1837 (if_then_else:GPR (match_operand 1 "comparison_operator")
1838 (match_operand:GPR 2 "register_operand")
1839 (match_operand:GPR 3 "sfb_alu_operand")))]
1842 rtx cmp = operands[1];
1843 /* We only handle word mode integer compares for now. */
1844 if (GET_MODE (XEXP (cmp, 0)) != word_mode)
1846 riscv_expand_conditional_move (operands[0], operands[2], operands[3],
1847 GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
1851 (define_insn "*mov<GPR:mode><X:mode>cc"
1852 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1854 (match_operator 5 "order_operator"
1855 [(match_operand:X 1 "register_operand" "r,r")
1856 (match_operand:X 2 "reg_or_0_operand" "rJ,rJ")])
1857 (match_operand:GPR 3 "register_operand" "0,0")
1858 (match_operand:GPR 4 "sfb_alu_operand" "rJ,IL")))]
1861 b%C5 %1,%z2,1f; mv %0,%z4; 1: # movcc
1862 b%C5 %1,%z2,1f; li %0,%4; 1: # movcc"
1863 [(set_attr "length" "8")
1864 (set_attr "type" "sfb_alu")
1865 (set_attr "mode" "<GPR:MODE>")])
1867 ;; Used to implement built-in functions.
1868 (define_expand "condjump"
1870 (if_then_else (match_operand 0)
1871 (label_ref (match_operand 1))
1874 (define_expand "cbranch<mode>4"
1876 (if_then_else (match_operator 0 "comparison_operator"
1877 [(match_operand:BR 1 "register_operand")
1878 (match_operand:BR 2 "nonmemory_operand")])
1879 (label_ref (match_operand 3 ""))
1883 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1884 operands[1], operands[2]);
1888 (define_expand "cbranch<mode>4"
1890 (if_then_else (match_operator 0 "fp_branch_comparison"
1891 [(match_operand:ANYF 1 "register_operand")
1892 (match_operand:ANYF 2 "register_operand")])
1893 (label_ref (match_operand 3 ""))
1897 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1898 operands[1], operands[2]);
1902 (define_insn_and_split "*branch_on_bit<X:mode>"
1905 (match_operator 0 "equality_operator"
1906 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1908 (match_operand 3 "branch_on_bit_operand"))
1910 (label_ref (match_operand 1))
1912 (clobber (match_scratch:X 4 "=&r"))]
1917 (ashift:X (match_dup 2) (match_dup 3)))
1920 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1921 (label_ref (match_operand 1))
1924 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
1925 operands[3] = GEN_INT (shift);
1927 if (GET_CODE (operands[0]) == EQ)
1928 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
1930 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
1933 (define_insn_and_split "*branch_on_bit_range<X:mode>"
1936 (match_operator 0 "equality_operator"
1937 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1938 (match_operand 3 "branch_on_bit_operand")
1941 (label_ref (match_operand 1))
1943 (clobber (match_scratch:X 4 "=&r"))]
1948 (ashift:X (match_dup 2) (match_dup 3)))
1951 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1952 (label_ref (match_operand 1))
1955 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
1959 ;; ....................
1961 ;; SETTING A REGISTER FROM A COMPARISON
1963 ;; ....................
1965 ;; Destination is always set in SI mode.
1967 (define_expand "cstore<mode>4"
1968 [(set (match_operand:SI 0 "register_operand")
1969 (match_operator:SI 1 "order_operator"
1970 [(match_operand:GPR 2 "register_operand")
1971 (match_operand:GPR 3 "nonmemory_operand")]))]
1974 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
1979 (define_expand "cstore<mode>4"
1980 [(set (match_operand:SI 0 "register_operand")
1981 (match_operator:SI 1 "fp_scc_comparison"
1982 [(match_operand:ANYF 2 "register_operand")
1983 (match_operand:ANYF 3 "register_operand")]))]
1986 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
1991 (define_insn "*cstore<ANYF:mode><X:mode>4"
1992 [(set (match_operand:X 0 "register_operand" "=r")
1993 (match_operator:X 1 "fp_native_comparison"
1994 [(match_operand:ANYF 2 "register_operand" " f")
1995 (match_operand:ANYF 3 "register_operand" " f")]))]
1997 "f%C1.<fmt>\t%0,%2,%3"
1998 [(set_attr "type" "fcmp")
1999 (set_attr "mode" "<UNITMODE>")])
2001 (define_expand "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
2002 [(parallel [(set (match_operand:X 0 "register_operand")
2004 [(match_operand:ANYF 1 "register_operand")
2005 (match_operand:ANYF 2 "register_operand")]
2007 (clobber (match_scratch:X 3))])]
2008 "TARGET_HARD_FLOAT")
2010 (define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_default"
2011 [(set (match_operand:X 0 "register_operand" "=r")
2013 [(match_operand:ANYF 1 "register_operand" " f")
2014 (match_operand:ANYF 2 "register_operand" " f")]
2016 (clobber (match_scratch:X 3 "=&r"))]
2017 "TARGET_HARD_FLOAT && ! HONOR_SNANS (<ANYF:MODE>mode)"
2018 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3"
2019 [(set_attr "type" "fcmp")
2020 (set_attr "mode" "<UNITMODE>")
2021 (set (attr "length") (const_int 12))])
2023 (define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_snan"
2024 [(set (match_operand:X 0 "register_operand" "=r")
2026 [(match_operand:ANYF 1 "register_operand" " f")
2027 (match_operand:ANYF 2 "register_operand" " f")]
2029 (clobber (match_scratch:X 3 "=&r"))]
2030 "TARGET_HARD_FLOAT && HONOR_SNANS (<ANYF:MODE>mode)"
2031 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3\n\tfeq.<fmt>\tzero,%1,%2"
2032 [(set_attr "type" "fcmp")
2033 (set_attr "mode" "<UNITMODE>")
2034 (set (attr "length") (const_int 16))])
2036 (define_insn "*seq_zero_<X:mode><GPR:mode>"
2037 [(set (match_operand:GPR 0 "register_operand" "=r")
2038 (eq:GPR (match_operand:X 1 "register_operand" " r")
2042 [(set_attr "type" "slt")
2043 (set_attr "mode" "<X:MODE>")])
2045 (define_insn "*sne_zero_<X:mode><GPR:mode>"
2046 [(set (match_operand:GPR 0 "register_operand" "=r")
2047 (ne:GPR (match_operand:X 1 "register_operand" " r")
2051 [(set_attr "type" "slt")
2052 (set_attr "mode" "<X:MODE>")])
2054 (define_insn "*sgt<u>_<X:mode><GPR:mode>"
2055 [(set (match_operand:GPR 0 "register_operand" "= r")
2056 (any_gt:GPR (match_operand:X 1 "register_operand" " r")
2057 (match_operand:X 2 "reg_or_0_operand" " rJ")))]
2060 [(set_attr "type" "slt")
2061 (set_attr "mode" "<X:MODE>")])
2063 (define_insn "*sge<u>_<X:mode><GPR:mode>"
2064 [(set (match_operand:GPR 0 "register_operand" "=r")
2065 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
2068 "slt%i2<u>\t%0,zero,%1"
2069 [(set_attr "type" "slt")
2070 (set_attr "mode" "<X:MODE>")])
2072 (define_insn "*slt<u>_<X:mode><GPR:mode>"
2073 [(set (match_operand:GPR 0 "register_operand" "= r")
2074 (any_lt:GPR (match_operand:X 1 "register_operand" " r")
2075 (match_operand:X 2 "arith_operand" " rI")))]
2077 "slt%i2<u>\t%0,%1,%2"
2078 [(set_attr "type" "slt")
2079 (set_attr "mode" "<X:MODE>")])
2081 (define_insn "*sle<u>_<X:mode><GPR:mode>"
2082 [(set (match_operand:GPR 0 "register_operand" "=r")
2083 (any_le:GPR (match_operand:X 1 "register_operand" " r")
2084 (match_operand:X 2 "sle_operand" "")))]
2087 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
2088 return "slt%i2<u>\t%0,%1,%2";
2090 [(set_attr "type" "slt")
2091 (set_attr "mode" "<X:MODE>")])
2094 ;; ....................
2096 ;; UNCONDITIONAL BRANCHES
2098 ;; ....................
2100 ;; Unconditional branches.
2104 (label_ref (match_operand 0 "" "")))]
2107 [(set_attr "type" "jump")
2108 (set_attr "mode" "none")])
2110 (define_expand "indirect_jump"
2111 [(set (pc) (match_operand 0 "register_operand"))]
2114 operands[0] = force_reg (Pmode, operands[0]);
2115 if (Pmode == SImode)
2116 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
2118 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
2122 (define_insn "indirect_jump<mode>"
2123 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
2126 [(set_attr "type" "jump")
2127 (set_attr "mode" "none")])
2129 (define_expand "tablejump"
2130 [(set (pc) (match_operand 0 "register_operand" ""))
2131 (use (label_ref (match_operand 1 "" "")))]
2134 if (CASE_VECTOR_PC_RELATIVE)
2135 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
2136 gen_rtx_LABEL_REF (Pmode, operands[1]),
2137 NULL_RTX, 0, OPTAB_DIRECT);
2139 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
2140 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
2142 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
2146 (define_insn "tablejump<mode>"
2147 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
2148 (use (label_ref (match_operand 1 "" "")))]
2151 [(set_attr "type" "jump")
2152 (set_attr "mode" "none")])
2155 ;; ....................
2157 ;; Function prologue/epilogue
2159 ;; ....................
2162 (define_expand "prologue"
2166 riscv_expand_prologue ();
2170 ;; Block any insns from being moved before this point, since the
2171 ;; profiling call to mcount can use various registers that aren't
2172 ;; saved or used to pass arguments.
2174 (define_insn "blockage"
2175 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
2178 [(set_attr "type" "ghost")
2179 (set_attr "mode" "none")])
2181 (define_expand "epilogue"
2185 riscv_expand_epilogue (NORMAL_RETURN);
2189 (define_expand "sibcall_epilogue"
2193 riscv_expand_epilogue (SIBCALL_RETURN);
2197 ;; Trivial return. Make it look like a normal return insn as that
2198 ;; allows jump optimizations to work better.
2200 (define_expand "return"
2202 "riscv_can_use_return_insn ()"
2205 (define_insn "simple_return"
2209 return riscv_output_return ();
2211 [(set_attr "type" "jump")
2212 (set_attr "mode" "none")])
2216 (define_insn "simple_return_internal"
2218 (use (match_operand 0 "pmode_register_operand" ""))]
2221 [(set_attr "type" "jump")
2222 (set_attr "mode" "none")])
2224 ;; This is used in compiling the unwind routines.
2225 (define_expand "eh_return"
2226 [(use (match_operand 0 "general_operand"))]
2229 if (GET_MODE (operands[0]) != word_mode)
2230 operands[0] = convert_to_mode (word_mode, operands[0], 0);
2232 emit_insn (gen_eh_set_lr_di (operands[0]));
2234 emit_insn (gen_eh_set_lr_si (operands[0]));
2236 emit_jump_insn (gen_eh_return_internal ());
2241 ;; Clobber the return address on the stack. We can't expand this
2242 ;; until we know where it will be put in the stack frame.
2244 (define_insn "eh_set_lr_si"
2245 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2246 (clobber (match_scratch:SI 1 "=&r"))]
2250 (define_insn "eh_set_lr_di"
2251 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2252 (clobber (match_scratch:DI 1 "=&r"))]
2257 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
2258 (clobber (match_scratch 1))]
2262 riscv_set_return_address (operands[0], operands[1]);
2266 (define_insn_and_split "eh_return_internal"
2270 "epilogue_completed"
2272 "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
2275 ;; ....................
2279 ;; ....................
2281 (define_expand "sibcall"
2282 [(parallel [(call (match_operand 0 "")
2283 (match_operand 1 ""))
2284 (use (match_operand 2 "")) ;; next_arg_reg
2285 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2288 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2289 emit_call_insn (gen_sibcall_internal (target, operands[1]));
2293 (define_insn "sibcall_internal"
2294 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
2295 (match_operand 1 "" ""))]
2296 "SIBLING_CALL_P (insn)"
2301 [(set_attr "type" "call")])
2303 (define_expand "sibcall_value"
2304 [(parallel [(set (match_operand 0 "")
2305 (call (match_operand 1 "")
2306 (match_operand 2 "")))
2307 (use (match_operand 3 ""))])] ;; next_arg_reg
2310 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2311 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
2315 (define_insn "sibcall_value_internal"
2316 [(set (match_operand 0 "" "")
2317 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
2318 (match_operand 2 "" "")))]
2319 "SIBLING_CALL_P (insn)"
2324 [(set_attr "type" "call")])
2326 (define_expand "call"
2327 [(parallel [(call (match_operand 0 "")
2328 (match_operand 1 ""))
2329 (use (match_operand 2 "")) ;; next_arg_reg
2330 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2333 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2334 emit_call_insn (gen_call_internal (target, operands[1]));
2338 (define_insn "call_internal"
2339 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
2340 (match_operand 1 "" ""))
2341 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2347 [(set_attr "type" "call")])
2349 (define_expand "call_value"
2350 [(parallel [(set (match_operand 0 "")
2351 (call (match_operand 1 "")
2352 (match_operand 2 "")))
2353 (use (match_operand 3 ""))])] ;; next_arg_reg
2356 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2357 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
2361 (define_insn "call_value_internal"
2362 [(set (match_operand 0 "" "")
2363 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
2364 (match_operand 2 "" "")))
2365 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2371 [(set_attr "type" "call")])
2373 ;; Call subroutine returning any type.
2375 (define_expand "untyped_call"
2376 [(parallel [(call (match_operand 0 "")
2378 (match_operand 1 "")
2379 (match_operand 2 "")])]
2384 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2386 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2388 rtx set = XVECEXP (operands[2], 0, i);
2389 riscv_emit_move (SET_DEST (set), SET_SRC (set));
2392 emit_insn (gen_blockage ());
2400 [(set_attr "type" "nop")
2401 (set_attr "mode" "none")])
2404 [(trap_if (const_int 1) (const_int 0))]
2408 (define_insn "gpr_save"
2409 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_SAVE)
2410 (clobber (reg:SI T0_REGNUM))
2411 (clobber (reg:SI T1_REGNUM))]
2413 { return riscv_output_gpr_save (INTVAL (operands[0])); })
2415 (define_insn "gpr_restore"
2416 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2418 "tail\t__riscv_restore_%0")
2420 (define_insn "gpr_restore_return"
2422 (use (match_operand 0 "pmode_register_operand" ""))
2427 (define_insn "riscv_frflags"
2428 [(set (match_operand:SI 0 "register_operand" "=r")
2429 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
2433 (define_insn "riscv_fsflags"
2434 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2438 (define_insn "riscv_mret"
2440 (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
2444 (define_insn "riscv_sret"
2446 (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
2450 (define_insn "riscv_uret"
2452 (unspec_volatile [(const_int 0)] UNSPECV_URET)]
2456 (define_insn "stack_tie<mode>"
2457 [(set (mem:BLK (scratch))
2458 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
2459 (match_operand:X 1 "register_operand" "r")]
2463 [(set_attr "length" "0")]
2466 ;; This fixes a failure with gcc.c-torture/execute/pr64242.c at -O2 for a
2467 ;; 32-bit target when using -mtune=sifive-7-series. The first sched pass
2468 ;; runs before register elimination, and we have a non-obvious dependency
2469 ;; between a use of the soft fp and a set of the hard fp. We fix this by
2470 ;; emitting a clobber using the hard fp between the two insns.
2471 (define_expand "restore_stack_nonlocal"
2472 [(match_operand 0 "register_operand")
2473 (match_operand 1 "memory_operand")]
2476 emit_move_insn (operands[0], operands[1]);
2477 /* Prevent the following hard fp restore from being moved before the move
2478 insn above which uses a copy of the soft fp reg. */
2479 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2484 (include "peephole.md")
2486 (include "generic.md")
2487 (include "sifive-7.md")