1 ;; Machine description for RISC-V for GNU compiler.
2 ;; Copyright (C)
2011-
2022 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.
52 (define_c_enum "unspecv" [
53 ;; Register save and restore.
57 ;; Floating-point unspecs.
61 ;; Interrupt handler instructions.
66 ;; Blockage and synchronization.
71 ;; Stack Smash Protector
84 [(RETURN_ADDR_REGNUM
1)
107 (include "predicates.md")
108 (include "constraints.md")
110 ;; ....................
114 ;; ....................
116 (define_attr "got" "unset,xgot_high,load"
117 (const_string "unset"))
119 ;; Classification of moves, extensions and truncations. Most values
120 ;; are as for "type" (see below) but there are also the following
121 ;; move-specific values:
123 ;; andi a single ANDI instruction
124 ;; shift_shift a shift left followed by a shift right
126 ;; This attribute is used to determine the instruction's length and
127 ;; scheduling type. For doubleword moves, the attribute always describes
128 ;; the split instructions; in some cases, it is more appropriate for the
129 ;; scheduling type to be "multi" instead.
130 (define_attr "move_type"
131 "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove,
132 const,logical,arith,andi,shift_shift"
133 (const_string "unknown"))
135 ;; Main data type used by the insn
136 (define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF"
137 (const_string "unknown"))
139 ;; True if the main data type is twice the size of a word.
140 (define_attr "dword_mode" "no,yes"
141 (cond [(and (eq_attr "mode" "DI,DF")
142 (eq (symbol_ref "TARGET_64BIT") (const_int
0)))
145 (and (eq_attr "mode" "TI,TF")
146 (ne (symbol_ref "TARGET_64BIT") (const_int
0)))
147 (const_string "yes")]
148 (const_string "no")))
150 ;; Classification of each insn.
151 ;; branch conditional branch
152 ;; jump unconditional jump
153 ;; call unconditional call
154 ;; load load instruction(s)
155 ;; fpload floating point load
156 ;; store store instruction(s)
157 ;; fpstore floating point store
158 ;; mtc transfer to coprocessor
159 ;; mfc transfer from coprocessor
160 ;; const load constant
161 ;; arith integer arithmetic instructions
162 ;; auipc integer addition to PC
163 ;; logical integer logical instructions
164 ;; shift integer shift instructions
165 ;; slt set less than instructions
166 ;; imul integer multiply
167 ;; idiv integer divide
168 ;; move integer register move (addi rd, rs1,
0)
169 ;; fmove floating point register move
170 ;; fadd floating point add/subtract
171 ;; fmul floating point multiply
172 ;; fmadd floating point multiply-add
173 ;; fdiv floating point divide
174 ;; fcmp floating point compare
175 ;; fcvt floating point convert
176 ;; fsqrt floating point square root
177 ;; multi multiword sequence (or user asm statements)
179 ;; ghost an instruction that produces no real code
180 ;; bitmanip bit manipulation instructions
182 "unknown,branch,jump,call,load,fpload,store,fpstore,
183 mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
184 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate"
185 (cond [(eq_attr "got" "load") (const_string "load")
187 ;; If a doubleword move uses these expensive instructions,
188 ;; it is usually better to schedule them in the same way
189 ;; as the singleword form, rather than as "multi".
190 (eq_attr "move_type" "load") (const_string "load")
191 (eq_attr "move_type" "fpload") (const_string "fpload")
192 (eq_attr "move_type" "store") (const_string "store")
193 (eq_attr "move_type" "fpstore") (const_string "fpstore")
194 (eq_attr "move_type" "mtc") (const_string "mtc")
195 (eq_attr "move_type" "mfc") (const_string "mfc")
197 ;; These types of move are always single insns.
198 (eq_attr "move_type" "fmove") (const_string "fmove")
199 (eq_attr "move_type" "arith") (const_string "arith")
200 (eq_attr "move_type" "logical") (const_string "logical")
201 (eq_attr "move_type" "andi") (const_string "logical")
203 ;; These types of move are always split.
204 (eq_attr "move_type" "shift_shift")
205 (const_string "multi")
207 ;; These types of move are split for doubleword modes only.
208 (and (eq_attr "move_type" "move,const")
209 (eq_attr "dword_mode" "yes"))
210 (const_string "multi")
211 (eq_attr "move_type" "move") (const_string "move")
212 (eq_attr "move_type" "const") (const_string "const")]
213 (const_string "unknown")))
215 ;; Length of instruction in bytes.
216 (define_attr "length" ""
218 ;; Branches further than +/-
4 KiB require two instructions.
219 (eq_attr "type" "branch")
220 (if_then_else (and (le (minus (match_dup
0) (pc)) (const_int
4088))
221 (le (minus (pc) (match_dup
0)) (const_int
4092)))
225 ;; Conservatively assume calls take two instructions (AUIPC + JALR).
226 ;; The linker will opportunistically relax the sequence to JAL.
227 (eq_attr "type" "call") (const_int
8)
229 ;; "Ghost" instructions occupy no space.
230 (eq_attr "type" "ghost") (const_int
0)
232 (eq_attr "got" "load") (const_int
8)
234 (eq_attr "type" "fcmp") (const_int
8)
236 ;; SHIFT_SHIFTs are decomposed into two separate instructions.
237 (eq_attr "move_type" "shift_shift")
240 ;; Check for doubleword moves that are decomposed into two
242 (and (eq_attr "move_type" "mtc,mfc,move")
243 (eq_attr "dword_mode" "yes"))
246 ;; Doubleword CONST{,N} moves are split into two word
248 (and (eq_attr "move_type" "const")
249 (eq_attr "dword_mode" "yes"))
250 (symbol_ref "riscv_split_const_insns (operands[
1]) *
4")
252 ;; Otherwise, constants, loads and stores are handled by external
254 (eq_attr "move_type" "load,fpload")
255 (symbol_ref "riscv_load_store_insns (operands[
1], insn) *
4")
256 (eq_attr "move_type" "store,fpstore")
257 (symbol_ref "riscv_load_store_insns (operands[
0], insn) *
4")
260 ;; Is copying of this instruction disallowed?
261 (define_attr "cannot_copy" "no,yes" (const_string "no"))
263 ;; Microarchitectures we know how to tune for.
264 ;; Keep this in sync with enum riscv_microarchitecture.
267 (const (symbol_ref "((enum attr_tune) riscv_microarchitecture)")))
269 ;; Describe a user's asm statement.
270 (define_asm_attributes
271 [(set_attr "type" "multi")])
273 ;; This mode iterator allows
32-bit and
64-bit GPR patterns to be generated
274 ;; from the same template.
275 (define_mode_iterator GPR [SI (DI "TARGET_64BIT")])
277 ;; This mode iterator allows :P to be used for patterns that operate on
278 ;; pointer-sized quantities. Exactly one of the two alternatives will match.
279 (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
281 ;; Likewise, but for XLEN-sized quantities.
282 (define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")])
284 ;; Branches operate on XLEN-sized quantities, but for RV64 we accept
285 ;; QImode values so we can force zero-extension.
286 (define_mode_iterator BR [(QI "TARGET_64BIT") SI (DI "TARGET_64BIT")])
288 ;;
32-bit moves for which we provide move patterns.
289 (define_mode_iterator MOVE32 [SI])
291 ;;
64-bit modes for which we provide move patterns.
292 (define_mode_iterator MOVE64 [DI DF])
294 ;; Iterator for sub-
32-bit integer modes.
295 (define_mode_iterator SHORT [QI HI])
297 ;; Iterator for HImode constant generation.
298 (define_mode_iterator HISI [HI SI])
300 ;; Iterator for QImode extension patterns.
301 (define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")])
303 ;; Iterator for hardware integer modes narrower than XLEN.
304 (define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")])
306 ;; Iterator for hardware-supported integer modes.
307 (define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
309 ;; Iterator for hardware-supported floating-point modes.
310 (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
311 (DF "TARGET_DOUBLE_FLOAT")])
313 ;; Iterator for floating-point modes that can be loaded into X registers.
314 (define_mode_iterator SOFTF [SF (DF "TARGET_64BIT")])
316 ;; This attribute gives the length suffix for a sign- or zero-extension
318 (define_mode_attr size [(QI "b") (HI "h")])
320 ;; Mode attributes for loads.
321 (define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
323 ;; Instruction names for integer loads that aren't explicitly sign or zero
324 ;; extended. See riscv_output_move and LOAD_EXTEND_OP.
325 (define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")])
327 ;; Mode attribute for FP loads into integer registers.
328 (define_mode_attr softload [(SF "lw") (DF "ld")])
330 ;; Instruction names for stores.
331 (define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
333 ;; Instruction names for FP stores from integer registers.
334 (define_mode_attr softstore [(SF "sw") (DF "sd")])
336 ;; This attribute gives the best constraint to use for registers of
338 (define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
340 ;; This attribute gives the format suffix for floating-point operations.
341 (define_mode_attr fmt [(SF "s") (DF "d")])
343 ;; This attribute gives the integer suffix for floating-point conversions.
344 (define_mode_attr ifmt [(SI "w") (DI "l")])
346 ;; This attribute gives the format suffix for atomic memory operations.
347 (define_mode_attr amo [(SI "w") (DI "d")])
349 ;; This attribute gives the upper-case mode name for one unit of a
350 ;; floating-point mode.
351 (define_mode_attr UNITMODE [(SF "SF") (DF "DF")])
353 ;; This attribute gives the integer mode that has half the size of
354 ;; the controlling mode.
355 (define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")])
357 ;; Iterator and attributes for floating-point rounding instructions.
358 (define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND])
359 (define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")])
360 (define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")])
362 ;; Iterator and attributes for quiet comparisons.
363 (define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET])
364 (define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")])
366 ;; This code iterator allows signed and unsigned widening multiplications
367 ;; to use the same template.
368 (define_code_iterator any_extend [sign_extend zero_extend])
370 ;; This code iterator allows the two right shift instructions to be
371 ;; generated from the same template.
372 (define_code_iterator any_shiftrt [ashiftrt lshiftrt])
374 ;; This code iterator allows the three shift instructions to be generated
375 ;; from the same template.
376 (define_code_iterator any_shift [ashift ashiftrt lshiftrt])
378 ;; This code iterator allows the three bitwise instructions to be generated
379 ;; from the same template.
380 (define_code_iterator any_bitwise [and ior xor])
382 ;; This code iterator allows unsigned and signed division to be generated
383 ;; from the same template.
384 (define_code_iterator any_div [div udiv mod umod])
386 ;; This code iterator allows unsigned and signed modulus to be generated
387 ;; from the same template.
388 (define_code_iterator any_mod [mod umod])
390 ;; These code iterators allow the signed and unsigned scc operations to use
391 ;; the same template.
392 (define_code_iterator any_gt [gt gtu])
393 (define_code_iterator any_ge [ge geu])
394 (define_code_iterator any_lt [lt ltu])
395 (define_code_iterator any_le [le leu])
397 ;; <u> expands to an empty string when doing a signed operation and
398 ;; "u" when doing an unsigned operation.
399 (define_code_attr u [(sign_extend "") (zero_extend "u")
405 ;; <su> is like <u>, but the signed form expands to "s" rather than "".
406 (define_code_attr su [(sign_extend "s") (zero_extend "u")])
408 ;; <optab> expands to the name of the optab for a particular code.
409 (define_code_attr optab [(ashift "ashl")
426 ;; <insn> expands to the name of the insn that implements a particular code.
427 (define_code_attr insn [(ashift "sll")
440 ;; Ghost instructions produce no real code and introduce no hazards.
441 ;; They exist purely to express an effect on dataflow.
442 (define_insn_reservation "ghost"
0
443 (eq_attr "type" "ghost")
447 ;; ....................
451 ;; ....................
454 (define_insn "add<mode>
3"
455 [(set (match_operand:ANYF
0 "register_operand" "=f")
456 (plus:ANYF (match_operand:ANYF
1 "register_operand" " f")
457 (match_operand:ANYF
2 "register_operand" " f")))]
459 "fadd.<fmt>
\t%
0,%
1,%
2"
460 [(set_attr "type" "fadd")
461 (set_attr "mode" "<UNITMODE>")])
463 (define_insn "addsi3"
464 [(set (match_operand:SI
0 "register_operand" "=r,r")
465 (plus:SI (match_operand:SI
1 "register_operand" " r,r")
466 (match_operand:SI
2 "arith_operand" " r,I")))]
468 { return TARGET_64BIT ? "add%i2w
\t%
0,%
1,%
2" : "add%i2
\t%
0,%
1,%
2"; }
469 [(set_attr "type" "arith")
470 (set_attr "mode" "SI")])
472 (define_insn "adddi3"
473 [(set (match_operand:DI
0 "register_operand" "=r,r")
474 (plus:DI (match_operand:DI
1 "register_operand" " r,r")
475 (match_operand:DI
2 "arith_operand" " r,I")))]
478 [(set_attr "type" "arith")
479 (set_attr "mode" "DI")])
481 (define_expand "addv<mode>
4"
482 [(set (match_operand:GPR
0 "register_operand" "=r,r")
483 (plus:GPR (match_operand:GPR
1 "register_operand" " r,r")
484 (match_operand:GPR
2 "arith_operand" " r,I")))
485 (label_ref (match_operand
3 "" ""))]
488 if (TARGET_64BIT && <MODE>mode == SImode)
490 rtx t3 = gen_reg_rtx (DImode);
491 rtx t4 = gen_reg_rtx (DImode);
492 rtx t5 = gen_reg_rtx (DImode);
493 rtx t6 = gen_reg_rtx (DImode);
495 emit_insn (gen_addsi3 (operands[
0], operands[
1], operands[
2]));
496 if (GET_CODE (operands[
1]) != CONST_INT)
497 emit_insn (gen_extend_insn (t4, operands[
1], DImode, SImode,
0));
500 if (GET_CODE (operands[
2]) != CONST_INT)
501 emit_insn (gen_extend_insn (t5, operands[
2], DImode, SImode,
0));
504 emit_insn (gen_adddi3 (t3, t4, t5));
505 emit_insn (gen_extend_insn (t6, operands[
0], DImode, SImode,
0));
507 riscv_expand_conditional_branch (operands[
3], NE, t6, t3);
511 rtx t3 = gen_reg_rtx (<MODE>mode);
512 rtx t4 = gen_reg_rtx (<MODE>mode);
514 emit_insn (gen_add3_insn (operands[
0], operands[
1], operands[
2]));
515 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[
2], const0_rtx);
516 emit_insn (gen_cstore<mode>
4 (t3, cmp1, operands[
2], const0_rtx));
517 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[
0], operands[
1]);
519 emit_insn (gen_cstore<mode>
4 (t4, cmp2, operands[
0], operands[
1]));
520 riscv_expand_conditional_branch (operands[
3], NE, t3, t4);
525 (define_expand "uaddv<mode>
4"
526 [(set (match_operand:GPR
0 "register_operand" "=r,r")
527 (plus:GPR (match_operand:GPR
1 "register_operand" " r,r")
528 (match_operand:GPR
2 "arith_operand" " r,I")))
529 (label_ref (match_operand
3 "" ""))]
532 if (TARGET_64BIT && <MODE>mode == SImode)
534 rtx t3 = gen_reg_rtx (DImode);
535 rtx t4 = gen_reg_rtx (DImode);
537 if (GET_CODE (operands[
1]) != CONST_INT)
538 emit_insn (gen_extend_insn (t3, operands[
1], DImode, SImode,
0));
541 emit_insn (gen_addsi3 (operands[
0], operands[
1], operands[
2]));
542 emit_insn (gen_extend_insn (t4, operands[
0], DImode, SImode,
0));
544 riscv_expand_conditional_branch (operands[
3], LTU, t4, t3);
548 emit_insn (gen_add3_insn (operands[
0], operands[
1], operands[
2]));
549 riscv_expand_conditional_branch (operands[
3], LTU, operands[
0],
556 (define_insn "*addsi3_extended"
557 [(set (match_operand:DI
0 "register_operand" "=r,r")
559 (plus:SI (match_operand:SI
1 "register_operand" " r,r")
560 (match_operand:SI
2 "arith_operand" " r,I"))))]
563 [(set_attr "type" "arith")
564 (set_attr "mode" "SI")])
566 (define_insn "*addsi3_extended2"
567 [(set (match_operand:DI
0 "register_operand" "=r,r")
569 (match_operator:SI
3 "subreg_lowpart_operator"
570 [(plus:DI (match_operand:DI
1 "register_operand" " r,r")
571 (match_operand:DI
2 "arith_operand" " r,I"))])))]
574 [(set_attr "type" "arith")
575 (set_attr "mode" "SI")])
578 ;; ....................
582 ;; ....................
585 (define_insn "sub<mode>
3"
586 [(set (match_operand:ANYF
0 "register_operand" "=f")
587 (minus:ANYF (match_operand:ANYF
1 "register_operand" " f")
588 (match_operand:ANYF
2 "register_operand" " f")))]
590 "fsub.<fmt>
\t%
0,%
1,%
2"
591 [(set_attr "type" "fadd")
592 (set_attr "mode" "<UNITMODE>")])
594 (define_insn "subdi3"
595 [(set (match_operand:DI
0 "register_operand" "= r")
596 (minus:DI (match_operand:DI
1 "reg_or_0_operand" " rJ")
597 (match_operand:DI
2 "register_operand" " r")))]
600 [(set_attr "type" "arith")
601 (set_attr "mode" "DI")])
603 (define_insn "subsi3"
604 [(set (match_operand:SI
0 "register_operand" "= r")
605 (minus:SI (match_operand:SI
1 "reg_or_0_operand" " rJ")
606 (match_operand:SI
2 "register_operand" " r")))]
608 { return TARGET_64BIT ? "subw
\t%
0,%z1,%
2" : "sub
\t%
0,%z1,%
2"; }
609 [(set_attr "type" "arith")
610 (set_attr "mode" "SI")])
612 (define_expand "subv<mode>
4"
613 [(set (match_operand:GPR
0 "register_operand" "= r")
614 (minus:GPR (match_operand:GPR
1 "reg_or_0_operand" " rJ")
615 (match_operand:GPR
2 "register_operand" " r")))
616 (label_ref (match_operand
3 "" ""))]
619 if (TARGET_64BIT && <MODE>mode == SImode)
621 rtx t3 = gen_reg_rtx (DImode);
622 rtx t4 = gen_reg_rtx (DImode);
623 rtx t5 = gen_reg_rtx (DImode);
624 rtx t6 = gen_reg_rtx (DImode);
626 emit_insn (gen_subsi3 (operands[
0], operands[
1], operands[
2]));
627 if (GET_CODE (operands[
1]) != CONST_INT)
628 emit_insn (gen_extend_insn (t4, operands[
1], DImode, SImode,
0));
631 if (GET_CODE (operands[
2]) != CONST_INT)
632 emit_insn (gen_extend_insn (t5, operands[
2], DImode, SImode,
0));
635 emit_insn (gen_subdi3 (t3, t4, t5));
636 emit_insn (gen_extend_insn (t6, operands[
0], DImode, SImode,
0));
638 riscv_expand_conditional_branch (operands[
3], NE, t6, t3);
642 rtx t3 = gen_reg_rtx (<MODE>mode);
643 rtx t4 = gen_reg_rtx (<MODE>mode);
645 emit_insn (gen_sub3_insn (operands[
0], operands[
1], operands[
2]));
647 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[
2], const0_rtx);
648 emit_insn (gen_cstore<mode>
4 (t3, cmp1, operands[
2], const0_rtx));
650 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[
1], operands[
0]);
651 emit_insn (gen_cstore<mode>
4 (t4, cmp2, operands[
1], operands[
0]));
653 riscv_expand_conditional_branch (operands[
3], NE, t3, t4);
659 (define_expand "usubv<mode>
4"
660 [(set (match_operand:GPR
0 "register_operand" "= r")
661 (minus:GPR (match_operand:GPR
1 "reg_or_0_operand" " rJ")
662 (match_operand:GPR
2 "register_operand" " r")))
663 (label_ref (match_operand
3 "" ""))]
666 if (TARGET_64BIT && <MODE>mode == SImode)
668 rtx t3 = gen_reg_rtx (DImode);
669 rtx t4 = gen_reg_rtx (DImode);
671 if (GET_CODE (operands[
1]) != CONST_INT)
672 emit_insn (gen_extend_insn (t3, operands[
1], DImode, SImode,
0));
675 emit_insn (gen_subsi3 (operands[
0], operands[
1], operands[
2]));
676 emit_insn (gen_extend_insn (t4, operands[
0], DImode, SImode,
0));
678 riscv_expand_conditional_branch (operands[
3], LTU, t3, t4);
682 emit_insn (gen_sub3_insn (operands[
0], operands[
1], operands[
2]));
683 riscv_expand_conditional_branch (operands[
3], LTU, operands[
1],
691 (define_insn "*subsi3_extended"
692 [(set (match_operand:DI
0 "register_operand" "= r")
694 (minus:SI (match_operand:SI
1 "reg_or_0_operand" " rJ")
695 (match_operand:SI
2 "register_operand" " r"))))]
698 [(set_attr "type" "arith")
699 (set_attr "mode" "SI")])
701 (define_insn "*subsi3_extended2"
702 [(set (match_operand:DI
0 "register_operand" "= r")
704 (match_operator:SI
3 "subreg_lowpart_operator"
705 [(minus:DI (match_operand:DI
1 "reg_or_0_operand" " rJ")
706 (match_operand:DI
2 "register_operand" " r"))])))]
709 [(set_attr "type" "arith")
710 (set_attr "mode" "SI")])
712 (define_insn "negdi2"
713 [(set (match_operand:DI
0 "register_operand" "=r")
714 (neg:DI (match_operand:DI
1 "register_operand" " r")))]
717 [(set_attr "type" "arith")
718 (set_attr "mode" "DI")])
720 (define_insn "negsi2"
721 [(set (match_operand:SI
0 "register_operand" "=r")
722 (neg:SI (match_operand:SI
1 "register_operand" " r")))]
724 { return TARGET_64BIT ? "negw
\t%
0,%
1" : "neg
\t%
0,%
1"; }
725 [(set_attr "type" "arith")
726 (set_attr "mode" "SI")])
728 (define_insn "*negsi2_extended"
729 [(set (match_operand:DI
0 "register_operand" "=r")
731 (neg:SI (match_operand:SI
1 "register_operand" " r"))))]
734 [(set_attr "type" "arith")
735 (set_attr "mode" "SI")])
737 (define_insn "*negsi2_extended2"
738 [(set (match_operand:DI
0 "register_operand" "=r")
740 (match_operator:SI
2 "subreg_lowpart_operator"
741 [(neg:DI (match_operand:DI
1 "register_operand" " r"))])))]
744 [(set_attr "type" "arith")
745 (set_attr "mode" "SI")])
748 ;; ....................
752 ;; ....................
755 (define_insn "mul<mode>
3"
756 [(set (match_operand:ANYF
0 "register_operand" "=f")
757 (mult:ANYF (match_operand:ANYF
1 "register_operand" " f")
758 (match_operand:ANYF
2 "register_operand" " f")))]
760 "fmul.<fmt>
\t%
0,%
1,%
2"
761 [(set_attr "type" "fmul")
762 (set_attr "mode" "<UNITMODE>")])
764 (define_insn "mulsi3"
765 [(set (match_operand:SI
0 "register_operand" "=r")
766 (mult:SI (match_operand:SI
1 "register_operand" " r")
767 (match_operand:SI
2 "register_operand" " r")))]
769 { return TARGET_64BIT ? "mulw
\t%
0,%
1,%
2" : "mul
\t%
0,%
1,%
2"; }
770 [(set_attr "type" "imul")
771 (set_attr "mode" "SI")])
773 (define_insn "muldi3"
774 [(set (match_operand:DI
0 "register_operand" "=r")
775 (mult:DI (match_operand:DI
1 "register_operand" " r")
776 (match_operand:DI
2 "register_operand" " r")))]
777 "TARGET_MUL && TARGET_64BIT"
779 [(set_attr "type" "imul")
780 (set_attr "mode" "DI")])
782 (define_expand "mulv<mode>
4"
783 [(set (match_operand:GPR
0 "register_operand" "=r")
784 (mult:GPR (match_operand:GPR
1 "register_operand" " r")
785 (match_operand:GPR
2 "register_operand" " r")))
786 (label_ref (match_operand
3 "" ""))]
789 if (TARGET_64BIT && <MODE>mode == SImode)
791 rtx t3 = gen_reg_rtx (DImode);
792 rtx t4 = gen_reg_rtx (DImode);
793 rtx t5 = gen_reg_rtx (DImode);
794 rtx t6 = gen_reg_rtx (DImode);
796 if (GET_CODE (operands[
1]) != CONST_INT)
797 emit_insn (gen_extend_insn (t4, operands[
1], DImode, SImode,
0));
800 if (GET_CODE (operands[
2]) != CONST_INT)
801 emit_insn (gen_extend_insn (t5, operands[
2], DImode, SImode,
0));
804 emit_insn (gen_muldi3 (t3, t4, t5));
806 emit_move_insn (operands[
0], gen_lowpart (SImode, t3));
807 emit_insn (gen_extend_insn (t6, operands[
0], DImode, SImode,
0));
809 riscv_expand_conditional_branch (operands[
3], NE, t6, t3);
813 rtx hp = gen_reg_rtx (<MODE>mode);
814 rtx lp = gen_reg_rtx (<MODE>mode);
816 emit_insn (gen_smul<mode>
3_highpart (hp, operands[
1], operands[
2]));
817 emit_insn (gen_mul<mode>
3 (operands[
0], operands[
1], operands[
2]));
818 emit_insn (gen_ashr<mode>
3 (lp, operands[
0],
819 GEN_INT (BITS_PER_WORD -
1)));
821 riscv_expand_conditional_branch (operands[
3], NE, hp, lp);
827 (define_expand "umulv<mode>
4"
828 [(set (match_operand:GPR
0 "register_operand" "=r")
829 (mult:GPR (match_operand:GPR
1 "register_operand" " r")
830 (match_operand:GPR
2 "register_operand" " r")))
831 (label_ref (match_operand
3 "" ""))]
834 if (TARGET_64BIT && <MODE>mode == SImode)
836 rtx t3 = gen_reg_rtx (DImode);
837 rtx t4 = gen_reg_rtx (DImode);
838 rtx t5 = gen_reg_rtx (DImode);
839 rtx t6 = gen_reg_rtx (DImode);
840 rtx t7 = gen_reg_rtx (DImode);
841 rtx t8 = gen_reg_rtx (DImode);
843 if (GET_CODE (operands[
1]) != CONST_INT)
844 emit_insn (gen_extend_insn (t3, operands[
1], DImode, SImode,
0));
847 if (GET_CODE (operands[
2]) != CONST_INT)
848 emit_insn (gen_extend_insn (t4, operands[
2], DImode, SImode,
0));
852 emit_insn (gen_ashldi3 (t5, t3, GEN_INT (
32)));
853 emit_insn (gen_ashldi3 (t6, t4, GEN_INT (
32)));
854 emit_insn (gen_umuldi3_highpart (t7, t5, t6));
855 emit_move_insn (operands[
0], gen_lowpart (SImode, t7));
856 emit_insn (gen_lshrdi3 (t8, t7, GEN_INT (
32)));
858 riscv_expand_conditional_branch (operands[
3], NE, t8, const0_rtx);
862 rtx hp = gen_reg_rtx (<MODE>mode);
864 emit_insn (gen_umul<mode>
3_highpart (hp, operands[
1], operands[
2]));
865 emit_insn (gen_mul<mode>
3 (operands[
0], operands[
1], operands[
2]));
867 riscv_expand_conditional_branch (operands[
3], NE, hp, const0_rtx);
873 (define_insn "*mulsi3_extended"
874 [(set (match_operand:DI
0 "register_operand" "=r")
876 (mult:SI (match_operand:SI
1 "register_operand" " r")
877 (match_operand:SI
2 "register_operand" " r"))))]
878 "TARGET_MUL && TARGET_64BIT"
880 [(set_attr "type" "imul")
881 (set_attr "mode" "SI")])
883 (define_insn "*mulsi3_extended2"
884 [(set (match_operand:DI
0 "register_operand" "=r")
886 (match_operator:SI
3 "subreg_lowpart_operator"
887 [(mult:DI (match_operand:DI
1 "register_operand" " r")
888 (match_operand:DI
2 "register_operand" " r"))])))]
889 "TARGET_MUL && TARGET_64BIT"
891 [(set_attr "type" "imul")
892 (set_attr "mode" "SI")])
895 ;; ........................
897 ;; MULTIPLICATION HIGH-PART
899 ;; ........................
903 (define_expand "<u>mulditi3"
904 [(set (match_operand:TI
0 "register_operand")
905 (mult:TI (any_extend:TI (match_operand:DI
1 "register_operand"))
906 (any_extend:TI (match_operand:DI
2 "register_operand"))))]
907 "TARGET_MUL && TARGET_64BIT"
909 rtx low = gen_reg_rtx (DImode);
910 emit_insn (gen_muldi3 (low, operands[
1], operands[
2]));
912 rtx high = gen_reg_rtx (DImode);
913 emit_insn (gen_<su>muldi3_highpart (high, operands[
1], operands[
2]));
915 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
916 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
920 (define_insn "<su>muldi3_highpart"
921 [(set (match_operand:DI
0 "register_operand" "=r")
924 (mult:TI (any_extend:TI
925 (match_operand:DI
1 "register_operand" " r"))
927 (match_operand:DI
2 "register_operand" " r")))
929 "TARGET_MUL && TARGET_64BIT"
931 [(set_attr "type" "imul")
932 (set_attr "mode" "DI")])
934 (define_expand "usmulditi3"
935 [(set (match_operand:TI
0 "register_operand")
936 (mult:TI (zero_extend:TI (match_operand:DI
1 "register_operand"))
937 (sign_extend:TI (match_operand:DI
2 "register_operand"))))]
938 "TARGET_MUL && TARGET_64BIT"
940 rtx low = gen_reg_rtx (DImode);
941 emit_insn (gen_muldi3 (low, operands[
1], operands[
2]));
943 rtx high = gen_reg_rtx (DImode);
944 emit_insn (gen_usmuldi3_highpart (high, operands[
1], operands[
2]));
946 emit_move_insn (gen_lowpart (DImode, operands[
0]), low);
947 emit_move_insn (gen_highpart (DImode, operands[
0]), high);
951 (define_insn "usmuldi3_highpart"
952 [(set (match_operand:DI
0 "register_operand" "=r")
955 (mult:TI (zero_extend:TI
956 (match_operand:DI
1 "register_operand" "r"))
958 (match_operand:DI
2 "register_operand" " r")))
960 "TARGET_MUL && TARGET_64BIT"
962 [(set_attr "type" "imul")
963 (set_attr "mode" "DI")])
965 (define_expand "<u>mulsidi3"
966 [(set (match_operand:DI
0 "register_operand" "=r")
967 (mult:DI (any_extend:DI
968 (match_operand:SI
1 "register_operand" " r"))
970 (match_operand:SI
2 "register_operand" " r"))))]
971 "TARGET_MUL && !TARGET_64BIT"
973 rtx temp = gen_reg_rtx (SImode);
974 emit_insn (gen_mulsi3 (temp, operands[
1], operands[
2]));
975 emit_insn (gen_<su>mulsi3_highpart (riscv_subword (operands[
0], true),
976 operands[
1], operands[
2]));
977 emit_insn (gen_movsi (riscv_subword (operands[
0], false), temp));
981 (define_insn "<su>mulsi3_highpart"
982 [(set (match_operand:SI
0 "register_operand" "=r")
985 (mult:DI (any_extend:DI
986 (match_operand:SI
1 "register_operand" " r"))
988 (match_operand:SI
2 "register_operand" " r")))
990 "TARGET_MUL && !TARGET_64BIT"
992 [(set_attr "type" "imul")
993 (set_attr "mode" "SI")])
996 (define_expand "usmulsidi3"
997 [(set (match_operand:DI
0 "register_operand" "=r")
998 (mult:DI (zero_extend:DI
999 (match_operand:SI
1 "register_operand" " r"))
1001 (match_operand:SI
2 "register_operand" " r"))))]
1002 "TARGET_MUL && !TARGET_64BIT"
1004 rtx temp = gen_reg_rtx (SImode);
1005 emit_insn (gen_mulsi3 (temp, operands[
1], operands[
2]));
1006 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[
0], true),
1007 operands[
1], operands[
2]));
1008 emit_insn (gen_movsi (riscv_subword (operands[
0], false), temp));
1012 (define_insn "usmulsi3_highpart"
1013 [(set (match_operand:SI
0 "register_operand" "=r")
1016 (mult:DI (zero_extend:DI
1017 (match_operand:SI
1 "register_operand" " r"))
1019 (match_operand:SI
2 "register_operand" " r")))
1021 "TARGET_MUL && !TARGET_64BIT"
1023 [(set_attr "type" "imul")
1024 (set_attr "mode" "SI")])
1027 ;; ....................
1029 ;; DIVISION and REMAINDER
1031 ;; ....................
1034 (define_insn "<optab>si3"
1035 [(set (match_operand:SI
0 "register_operand" "=r")
1036 (any_div:SI (match_operand:SI
1 "register_operand" " r")
1037 (match_operand:SI
2 "register_operand" " r")))]
1039 { return TARGET_64BIT ? "<insn>%i2w
\t%
0,%
1,%
2" : "<insn>%i2
\t%
0,%
1,%
2"; }
1040 [(set_attr "type" "idiv")
1041 (set_attr "mode" "SI")])
1043 (define_insn "<optab>di3"
1044 [(set (match_operand:DI
0 "register_operand" "=r")
1045 (any_div:DI (match_operand:DI
1 "register_operand" " r")
1046 (match_operand:DI
2 "register_operand" " r")))]
1047 "TARGET_DIV && TARGET_64BIT"
1048 "<insn>%i2
\t%
0,%
1,%
2"
1049 [(set_attr "type" "idiv")
1050 (set_attr "mode" "DI")])
1052 (define_insn "*<optab>si3_extended"
1053 [(set (match_operand:DI
0 "register_operand" "=r")
1055 (any_div:SI (match_operand:SI
1 "register_operand" " r")
1056 (match_operand:SI
2 "register_operand" " r"))))]
1057 "TARGET_DIV && TARGET_64BIT"
1058 "<insn>%i2w
\t%
0,%
1,%
2"
1059 [(set_attr "type" "idiv")
1060 (set_attr "mode" "DI")])
1062 (define_insn "div<mode>
3"
1063 [(set (match_operand:ANYF
0 "register_operand" "=f")
1064 (div:ANYF (match_operand:ANYF
1 "register_operand" " f")
1065 (match_operand:ANYF
2 "register_operand" " f")))]
1066 "TARGET_HARD_FLOAT && TARGET_FDIV"
1067 "fdiv.<fmt>
\t%
0,%
1,%
2"
1068 [(set_attr "type" "fdiv")
1069 (set_attr "mode" "<UNITMODE>")])
1072 ;; ....................
1076 ;; ....................
1078 (define_insn "sqrt<mode>
2"
1079 [(set (match_operand:ANYF
0 "register_operand" "=f")
1080 (sqrt:ANYF (match_operand:ANYF
1 "register_operand" " f")))]
1081 "TARGET_HARD_FLOAT && TARGET_FDIV"
1083 return "fsqrt.<fmt>
\t%
0,%
1";
1085 [(set_attr "type" "fsqrt")
1086 (set_attr "mode" "<UNITMODE>")])
1088 ;; Floating point multiply accumulate instructions.
1091 (define_insn "fma<mode>
4"
1092 [(set (match_operand:ANYF
0 "register_operand" "=f")
1093 (fma:ANYF (match_operand:ANYF
1 "register_operand" " f")
1094 (match_operand:ANYF
2 "register_operand" " f")
1095 (match_operand:ANYF
3 "register_operand" " f")))]
1097 "fmadd.<fmt>
\t%
0,%
1,%
2,%
3"
1098 [(set_attr "type" "fmadd")
1099 (set_attr "mode" "<UNITMODE>")])
1102 (define_insn "fms<mode>
4"
1103 [(set (match_operand:ANYF
0 "register_operand" "=f")
1104 (fma:ANYF (match_operand:ANYF
1 "register_operand" " f")
1105 (match_operand:ANYF
2 "register_operand" " f")
1106 (neg:ANYF (match_operand:ANYF
3 "register_operand" " f"))))]
1108 "fmsub.<fmt>
\t%
0,%
1,%
2,%
3"
1109 [(set_attr "type" "fmadd")
1110 (set_attr "mode" "<UNITMODE>")])
1113 (define_insn "fnms<mode>
4"
1114 [(set (match_operand:ANYF
0 "register_operand" "=f")
1116 (neg:ANYF (match_operand:ANYF
1 "register_operand" " f"))
1117 (match_operand:ANYF
2 "register_operand" " f")
1118 (neg:ANYF (match_operand:ANYF
3 "register_operand" " f"))))]
1120 "fnmadd.<fmt>
\t%
0,%
1,%
2,%
3"
1121 [(set_attr "type" "fmadd")
1122 (set_attr "mode" "<UNITMODE>")])
1125 (define_insn "fnma<mode>
4"
1126 [(set (match_operand:ANYF
0 "register_operand" "=f")
1128 (neg:ANYF (match_operand:ANYF
1 "register_operand" " f"))
1129 (match_operand:ANYF
2 "register_operand" " f")
1130 (match_operand:ANYF
3 "register_operand" " f")))]
1132 "fnmsub.<fmt>
\t%
0,%
1,%
2,%
3"
1133 [(set_attr "type" "fmadd")
1134 (set_attr "mode" "<UNITMODE>")])
1136 ;; -(-a * b - c), modulo signed zeros
1137 (define_insn "*fma<mode>
4"
1138 [(set (match_operand:ANYF
0 "register_operand" "=f")
1141 (neg:ANYF (match_operand:ANYF
1 "register_operand" " f"))
1142 (match_operand:ANYF
2 "register_operand" " f")
1143 (neg:ANYF (match_operand:ANYF
3 "register_operand" " f")))))]
1144 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1145 "fmadd.<fmt>
\t%
0,%
1,%
2,%
3"
1146 [(set_attr "type" "fmadd")
1147 (set_attr "mode" "<UNITMODE>")])
1149 ;; -(-a * b + c), modulo signed zeros
1150 (define_insn "*fms<mode>
4"
1151 [(set (match_operand:ANYF
0 "register_operand" "=f")
1154 (neg:ANYF (match_operand:ANYF
1 "register_operand" " f"))
1155 (match_operand:ANYF
2 "register_operand" " f")
1156 (match_operand:ANYF
3 "register_operand" " f"))))]
1157 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1158 "fmsub.<fmt>
\t%
0,%
1,%
2,%
3"
1159 [(set_attr "type" "fmadd")
1160 (set_attr "mode" "<UNITMODE>")])
1162 ;; -(a * b + c), modulo signed zeros
1163 (define_insn "*fnms<mode>
4"
1164 [(set (match_operand:ANYF
0 "register_operand" "=f")
1167 (match_operand:ANYF
1 "register_operand" " f")
1168 (match_operand:ANYF
2 "register_operand" " f")
1169 (match_operand:ANYF
3 "register_operand" " f"))))]
1170 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1171 "fnmadd.<fmt>
\t%
0,%
1,%
2,%
3"
1172 [(set_attr "type" "fmadd")
1173 (set_attr "mode" "<UNITMODE>")])
1175 ;; -(a * b - c), modulo signed zeros
1176 (define_insn "*fnma<mode>
4"
1177 [(set (match_operand:ANYF
0 "register_operand" "=f")
1180 (match_operand:ANYF
1 "register_operand" " f")
1181 (match_operand:ANYF
2 "register_operand" " f")
1182 (neg:ANYF (match_operand:ANYF
3 "register_operand" " f")))))]
1183 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1184 "fnmsub.<fmt>
\t%
0,%
1,%
2,%
3"
1185 [(set_attr "type" "fmadd")
1186 (set_attr "mode" "<UNITMODE>")])
1189 ;; ....................
1193 ;; ....................
1195 (define_insn "abs<mode>
2"
1196 [(set (match_operand:ANYF
0 "register_operand" "=f")
1197 (abs:ANYF (match_operand:ANYF
1 "register_operand" " f")))]
1200 [(set_attr "type" "fmove")
1201 (set_attr "mode" "<UNITMODE>")])
1203 (define_insn "copysign<mode>
3"
1204 [(set (match_operand:ANYF
0 "register_operand" "=f")
1205 (unspec:ANYF [(match_operand:ANYF
1 "register_operand" " f")
1206 (match_operand:ANYF
2 "register_operand" " f")]
1209 "fsgnj.<fmt>
\t%
0,%
1,%
2"
1210 [(set_attr "type" "fmove")
1211 (set_attr "mode" "<UNITMODE>")])
1213 (define_insn "neg<mode>
2"
1214 [(set (match_operand:ANYF
0 "register_operand" "=f")
1215 (neg:ANYF (match_operand:ANYF
1 "register_operand" " f")))]
1218 [(set_attr "type" "fmove")
1219 (set_attr "mode" "<UNITMODE>")])
1222 ;; ....................
1226 ;; ....................
1228 (define_insn "fmin<mode>
3"
1229 [(set (match_operand:ANYF
0 "register_operand" "=f")
1230 (unspec:ANYF [(use (match_operand:ANYF
1 "register_operand" " f"))
1231 (use (match_operand:ANYF
2 "register_operand" " f"))]
1233 "TARGET_HARD_FLOAT && !HONOR_SNANS (<MODE>mode)"
1234 "fmin.<fmt>
\t%
0,%
1,%
2"
1235 [(set_attr "type" "fmove")
1236 (set_attr "mode" "<UNITMODE>")])
1238 (define_insn "fmax<mode>
3"
1239 [(set (match_operand:ANYF
0 "register_operand" "=f")
1240 (unspec:ANYF [(use (match_operand:ANYF
1 "register_operand" " f"))
1241 (use (match_operand:ANYF
2 "register_operand" " f"))]
1243 "TARGET_HARD_FLOAT && !HONOR_SNANS (<MODE>mode)"
1244 "fmax.<fmt>
\t%
0,%
1,%
2"
1245 [(set_attr "type" "fmove")
1246 (set_attr "mode" "<UNITMODE>")])
1248 (define_insn "smin<mode>
3"
1249 [(set (match_operand:ANYF
0 "register_operand" "=f")
1250 (smin:ANYF (match_operand:ANYF
1 "register_operand" " f")
1251 (match_operand:ANYF
2 "register_operand" " f")))]
1253 "fmin.<fmt>
\t%
0,%
1,%
2"
1254 [(set_attr "type" "fmove")
1255 (set_attr "mode" "<UNITMODE>")])
1257 (define_insn "smax<mode>
3"
1258 [(set (match_operand:ANYF
0 "register_operand" "=f")
1259 (smax:ANYF (match_operand:ANYF
1 "register_operand" " f")
1260 (match_operand:ANYF
2 "register_operand" " f")))]
1262 "fmax.<fmt>
\t%
0,%
1,%
2"
1263 [(set_attr "type" "fmove")
1264 (set_attr "mode" "<UNITMODE>")])
1267 ;; ....................
1271 ;; ....................
1274 ;; For RV64, we don't expose the SImode operations to the rtl expanders,
1275 ;; but SImode versions exist for combine.
1277 (define_insn "<optab><mode>
3"
1278 [(set (match_operand:X
0 "register_operand" "=r,r")
1279 (any_bitwise:X (match_operand:X
1 "register_operand" "%r,r")
1280 (match_operand:X
2 "arith_operand" " r,I")))]
1282 "<insn>%i2
\t%
0,%
1,%
2"
1283 [(set_attr "type" "logical")
1284 (set_attr "mode" "<MODE>")])
1286 (define_insn "*<optab>si3_internal"
1287 [(set (match_operand:SI
0 "register_operand" "=r,r")
1288 (any_bitwise:SI (match_operand:SI
1 "register_operand" "%r,r")
1289 (match_operand:SI
2 "arith_operand" " r,I")))]
1291 "<insn>%i2
\t%
0,%
1,%
2"
1292 [(set_attr "type" "logical")
1293 (set_attr "mode" "SI")])
1295 (define_insn "one_cmpl<mode>
2"
1296 [(set (match_operand:X
0 "register_operand" "=r")
1297 (not:X (match_operand:X
1 "register_operand" " r")))]
1300 [(set_attr "type" "logical")
1301 (set_attr "mode" "<MODE>")])
1303 (define_insn "*one_cmplsi2_internal"
1304 [(set (match_operand:SI
0 "register_operand" "=r")
1305 (not:SI (match_operand:SI
1 "register_operand" " r")))]
1308 [(set_attr "type" "logical")
1309 (set_attr "mode" "SI")])
1312 ;; ....................
1316 ;; ....................
1318 (define_insn "truncdfsf2"
1319 [(set (match_operand:SF
0 "register_operand" "=f")
1321 (match_operand:DF
1 "register_operand" " f")))]
1322 "TARGET_DOUBLE_FLOAT"
1324 [(set_attr "type" "fcvt")
1325 (set_attr "mode" "SF")])
1328 ;; ....................
1332 ;; ....................
1336 (define_expand "zero_extendsidi2"
1337 [(set (match_operand:DI
0 "register_operand")
1338 (zero_extend:DI (match_operand:SI
1 "nonimmediate_operand")))]
1341 (define_insn_and_split "*zero_extendsidi2_internal"
1342 [(set (match_operand:DI
0 "register_operand" "=r,r")
1344 (match_operand:SI
1 "nonimmediate_operand" " r,m")))]
1345 "TARGET_64BIT && !TARGET_ZBA"
1349 "&& reload_completed
1350 && REG_P (operands[
1])
1351 && !paradoxical_subreg_p (operands[
0])"
1353 (ashift:DI (match_dup
1) (const_int
32)))
1355 (lshiftrt:DI (match_dup
0) (const_int
32)))]
1356 { operands[
1] = gen_lowpart (DImode, operands[
1]); }
1357 [(set_attr "move_type" "shift_shift,load")
1358 (set_attr "mode" "DI")])
1360 (define_expand "zero_extendhi<GPR:mode>
2"
1361 [(set (match_operand:GPR
0 "register_operand")
1363 (match_operand:HI
1 "nonimmediate_operand")))]
1366 (define_insn_and_split "*zero_extendhi<GPR:mode>
2"
1367 [(set (match_operand:GPR
0 "register_operand" "=r,r")
1369 (match_operand:HI
1 "nonimmediate_operand" " r,m")))]
1374 "&& reload_completed
1375 && REG_P (operands[
1])
1376 && !paradoxical_subreg_p (operands[
0])"
1378 (ashift:GPR (match_dup
1) (match_dup
2)))
1380 (lshiftrt:GPR (match_dup
0) (match_dup
2)))]
1382 operands[
1] = gen_lowpart (<GPR:MODE>mode, operands[
1]);
1383 operands[
2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) -
16);
1385 [(set_attr "move_type" "shift_shift,load")
1386 (set_attr "mode" "<GPR:MODE>")])
1388 (define_insn "zero_extendqi<SUPERQI:mode>
2"
1389 [(set (match_operand:SUPERQI
0 "register_operand" "=r,r")
1390 (zero_extend:SUPERQI
1391 (match_operand:QI
1 "nonimmediate_operand" " r,m")))]
1396 [(set_attr "move_type" "andi,load")
1397 (set_attr "mode" "<SUPERQI:MODE>")])
1400 ;; ....................
1404 ;; ....................
1406 (define_insn "extendsidi2"
1407 [(set (match_operand:DI
0 "register_operand" "=r,r")
1409 (match_operand:SI
1 "nonimmediate_operand" " r,m")))]
1414 [(set_attr "move_type" "move,load")
1415 (set_attr "mode" "DI")])
1417 (define_expand "extend<SHORT:mode><SUPERQI:mode>
2"
1418 [(set (match_operand:SUPERQI
0 "register_operand")
1419 (sign_extend:SUPERQI (match_operand:SHORT
1 "nonimmediate_operand")))]
1422 (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>
2"
1423 [(set (match_operand:SUPERQI
0 "register_operand" "=r,r")
1424 (sign_extend:SUPERQI
1425 (match_operand:SHORT
1 "nonimmediate_operand" " r,m")))]
1429 l<SHORT:size>
\t%
0,%
1"
1430 "&& reload_completed
1431 && REG_P (operands[
1])
1432 && !paradoxical_subreg_p (operands[
0])"
1433 [(set (match_dup
0) (ashift:SI (match_dup
1) (match_dup
2)))
1434 (set (match_dup
0) (ashiftrt:SI (match_dup
0) (match_dup
2)))]
1436 operands[
0] = gen_lowpart (SImode, operands[
0]);
1437 operands[
1] = gen_lowpart (SImode, operands[
1]);
1438 operands[
2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1439 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1441 [(set_attr "move_type" "shift_shift,load")
1442 (set_attr "mode" "SI")])
1444 (define_insn "extendsfdf2"
1445 [(set (match_operand:DF
0 "register_operand" "=f")
1447 (match_operand:SF
1 "register_operand" " f")))]
1448 "TARGET_DOUBLE_FLOAT"
1450 [(set_attr "type" "fcvt")
1451 (set_attr "mode" "DF")])
1454 ;; ....................
1458 ;; ....................
1460 (define_insn "fix_trunc<ANYF:mode><GPR:mode>
2"
1461 [(set (match_operand:GPR
0 "register_operand" "=r")
1463 (match_operand:ANYF
1 "register_operand" " f")))]
1465 "fcvt.<GPR:ifmt>.<ANYF:fmt> %
0,%
1,rtz"
1466 [(set_attr "type" "fcvt")
1467 (set_attr "mode" "<ANYF:MODE>")])
1469 (define_insn "fixuns_trunc<ANYF:mode><GPR:mode>
2"
1470 [(set (match_operand:GPR
0 "register_operand" "=r")
1472 (match_operand:ANYF
1 "register_operand" " f")))]
1474 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %
0,%
1,rtz"
1475 [(set_attr "type" "fcvt")
1476 (set_attr "mode" "<ANYF:MODE>")])
1478 (define_insn "float<GPR:mode><ANYF:mode>
2"
1479 [(set (match_operand:ANYF
0 "register_operand" "= f")
1481 (match_operand:GPR
1 "reg_or_0_operand" " rJ")))]
1483 "fcvt.<ANYF:fmt>.<GPR:ifmt>
\t%
0,%z1"
1484 [(set_attr "type" "fcvt")
1485 (set_attr "mode" "<ANYF:MODE>")])
1487 (define_insn "floatuns<GPR:mode><ANYF:mode>
2"
1488 [(set (match_operand:ANYF
0 "register_operand" "= f")
1489 (unsigned_float:ANYF
1490 (match_operand:GPR
1 "reg_or_0_operand" " rJ")))]
1492 "fcvt.<ANYF:fmt>.<GPR:ifmt>u
\t%
0,%z1"
1493 [(set_attr "type" "fcvt")
1494 (set_attr "mode" "<ANYF:MODE>")])
1496 (define_insn "l<rint_pattern><ANYF:mode><GPR:mode>
2"
1497 [(set (match_operand:GPR
0 "register_operand" "=r")
1499 [(match_operand:ANYF
1 "register_operand" " f")]
1502 "fcvt.<GPR:ifmt>.<ANYF:fmt> %
0,%
1,<rint_rm>"
1503 [(set_attr "type" "fcvt")
1504 (set_attr "mode" "<ANYF:MODE>")])
1507 ;; ....................
1511 ;; ....................
1513 ;; Lower-level instructions for loading an address from the GOT.
1514 ;; We could use MEMs, but an unspec gives more optimization
1517 (define_insn "got_load<mode>"
1518 [(set (match_operand:P
0 "register_operand" "=r")
1520 [(match_operand:P
1 "symbolic_operand" "")]
1524 [(set_attr "got" "load")
1525 (set_attr "mode" "<MODE>")])
1527 (define_insn "tls_add_tp_le<mode>"
1528 [(set (match_operand:P
0 "register_operand" "=r")
1530 [(match_operand:P
1 "register_operand" "r")
1531 (match_operand:P
2 "register_operand" "r")
1532 (match_operand:P
3 "symbolic_operand" "")]
1535 "add
\t%
0,%
1,%
2,%%tprel_add(%
3)"
1536 [(set_attr "type" "arith")
1537 (set_attr "mode" "<MODE>")])
1539 (define_insn "got_load_tls_gd<mode>"
1540 [(set (match_operand:P
0 "register_operand" "=r")
1542 [(match_operand:P
1 "symbolic_operand" "")]
1546 [(set_attr "got" "load")
1547 (set_attr "mode" "<MODE>")])
1549 (define_insn "got_load_tls_ie<mode>"
1550 [(set (match_operand:P
0 "register_operand" "=r")
1552 [(match_operand:P
1 "symbolic_operand" "")]
1556 [(set_attr "got" "load")
1557 (set_attr "mode" "<MODE>")])
1559 (define_insn "auipc<mode>"
1560 [(set (match_operand:P
0 "register_operand" "=r")
1562 [(match_operand:P
1 "symbolic_operand" "")
1563 (match_operand:P
2 "const_int_operand")
1567 ".LA%
2: auipc
\t%
0,%h1"
1568 [(set_attr "type" "auipc")
1569 (set_attr "cannot_copy" "yes")])
1571 ;; Instructions for adding the low
12 bits of an address to a register.
1572 ;; Operand
2 is the address: riscv_print_operand works out which relocation
1573 ;; should be applied.
1575 (define_insn "*low<mode>"
1576 [(set (match_operand:P
0 "register_operand" "=r")
1577 (lo_sum:P (match_operand:P
1 "register_operand" " r")
1578 (match_operand:P
2 "symbolic_operand" "")))]
1581 [(set_attr "type" "arith")
1582 (set_attr "mode" "<MODE>")])
1584 ;; Allow combine to split complex const_int load sequences, using operand
2
1585 ;; to store the intermediate results. See move_operand for details.
1587 [(set (match_operand:GPR
0 "register_operand")
1588 (match_operand:GPR
1 "splittable_const_int_operand"))
1589 (clobber (match_operand:GPR
2 "register_operand"))]
1593 riscv_move_integer (operands[
2], operands[
0], INTVAL (operands[
1]),
1594 <GPR:MODE>mode, TRUE);
1598 ;; Likewise, for symbolic operands.
1600 [(set (match_operand:P
0 "register_operand")
1601 (match_operand:P
1))
1602 (clobber (match_operand:P
2 "register_operand"))]
1603 "riscv_split_symbol (operands[
2], operands[
1], MAX_MACHINE_MODE, NULL, TRUE)"
1604 [(set (match_dup
0) (match_dup
3))]
1606 riscv_split_symbol (operands[
2], operands[
1],
1607 MAX_MACHINE_MODE, &operands[
3], TRUE);
1610 ;;
64-bit integer moves
1612 (define_expand "movdi"
1613 [(set (match_operand:DI
0 "")
1614 (match_operand:DI
1 ""))]
1617 if (riscv_legitimize_move (DImode, operands[
0], operands[
1]))
1621 (define_insn "*movdi_32bit"
1622 [(set (match_operand:DI
0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m")
1623 (match_operand:DI
1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))]
1625 && (register_operand (operands[
0], DImode)
1626 || reg_or_0_operand (operands[
1], DImode))"
1627 { return riscv_output_move (operands[
0], operands[
1]); }
1628 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1629 (set_attr "mode" "DI")])
1631 (define_insn "*movdi_64bit"
1632 [(set (match_operand:DI
0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m")
1633 (match_operand:DI
1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))]
1635 && (register_operand (operands[
0], DImode)
1636 || reg_or_0_operand (operands[
1], DImode))"
1637 { return riscv_output_move (operands[
0], operands[
1]); }
1638 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1639 (set_attr "mode" "DI")])
1641 ;;
32-bit Integer moves
1643 (define_expand "mov<mode>"
1644 [(set (match_operand:MOVE32
0 "")
1645 (match_operand:MOVE32
1 ""))]
1648 if (riscv_legitimize_move (<MODE>mode, operands[
0], operands[
1]))
1652 (define_insn "*movsi_internal"
1653 [(set (match_operand:SI
0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m")
1654 (match_operand:SI
1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f"))]
1655 "(register_operand (operands[
0], SImode)
1656 || reg_or_0_operand (operands[
1], SImode))"
1657 { return riscv_output_move (operands[
0], operands[
1]); }
1658 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
1659 (set_attr "mode" "SI")])
1661 ;;
16-bit Integer moves
1663 ;; Unlike most other insns, the move insns can't be split with
1664 ;; different predicates, because register spilling and other parts of
1665 ;; the compiler, have memoized the insn number already.
1666 ;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
1668 (define_expand "movhi"
1669 [(set (match_operand:HI
0 "")
1670 (match_operand:HI
1 ""))]
1673 if (riscv_legitimize_move (HImode, operands[
0], operands[
1]))
1677 (define_insn "*movhi_internal"
1678 [(set (match_operand:HI
0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1679 (match_operand:HI
1 "move_operand" " r,T,m,rJ,*r*J,*f"))]
1680 "(register_operand (operands[
0], HImode)
1681 || reg_or_0_operand (operands[
1], HImode))"
1682 { return riscv_output_move (operands[
0], operands[
1]); }
1683 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1684 (set_attr "mode" "HI")])
1686 ;; HImode constant generation; see riscv_move_integer for details.
1687 ;; si+si->hi without truncation is legal because of
1688 ;; TARGET_TRULY_NOOP_TRUNCATION.
1690 (define_insn "*add<mode>hi3"
1691 [(set (match_operand:HI
0 "register_operand" "=r,r")
1692 (plus:HI (match_operand:HISI
1 "register_operand" " r,r")
1693 (match_operand:HISI
2 "arith_operand" " r,I")))]
1695 { return TARGET_64BIT ? "add%i2w
\t%
0,%
1,%
2" : "add%i2
\t%
0,%
1,%
2"; }
1696 [(set_attr "type" "arith")
1697 (set_attr "mode" "HI")])
1699 (define_insn "*xor<mode>hi3"
1700 [(set (match_operand:HI
0 "register_operand" "=r,r")
1701 (xor:HI (match_operand:HISI
1 "register_operand" " r,r")
1702 (match_operand:HISI
2 "arith_operand" " r,I")))]
1705 [(set_attr "type" "logical")
1706 (set_attr "mode" "HI")])
1708 ;;
8-bit Integer moves
1710 (define_expand "movqi"
1711 [(set (match_operand:QI
0 "")
1712 (match_operand:QI
1 ""))]
1715 if (riscv_legitimize_move (QImode, operands[
0], operands[
1]))
1719 (define_insn "*movqi_internal"
1720 [(set (match_operand:QI
0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1721 (match_operand:QI
1 "move_operand" " r,I,m,rJ,*r*J,*f"))]
1722 "(register_operand (operands[
0], QImode)
1723 || reg_or_0_operand (operands[
1], QImode))"
1724 { return riscv_output_move (operands[
0], operands[
1]); }
1725 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1726 (set_attr "mode" "QI")])
1728 ;;
32-bit floating point moves
1730 (define_expand "movsf"
1731 [(set (match_operand:SF
0 "")
1732 (match_operand:SF
1 ""))]
1735 if (riscv_legitimize_move (SFmode, operands[
0], operands[
1]))
1739 (define_insn "*movsf_hardfloat"
1740 [(set (match_operand:SF
0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1741 (match_operand:SF
1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
1743 && (register_operand (operands[
0], SFmode)
1744 || reg_or_0_operand (operands[
1], SFmode))"
1745 { return riscv_output_move (operands[
0], operands[
1]); }
1746 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1747 (set_attr "mode" "SF")])
1749 (define_insn "*movsf_softfloat"
1750 [(set (match_operand:SF
0 "nonimmediate_operand" "= r,r,m")
1751 (match_operand:SF
1 "move_operand" " Gr,m,r"))]
1753 && (register_operand (operands[
0], SFmode)
1754 || reg_or_0_operand (operands[
1], SFmode))"
1755 { return riscv_output_move (operands[
0], operands[
1]); }
1756 [(set_attr "move_type" "move,load,store")
1757 (set_attr "mode" "SF")])
1759 ;;
64-bit floating point moves
1761 (define_expand "movdf"
1762 [(set (match_operand:DF
0 "")
1763 (match_operand:DF
1 ""))]
1766 if (riscv_legitimize_move (DFmode, operands[
0], operands[
1]))
1770 ;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
1771 ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
1772 (define_insn "*movdf_hardfloat_rv32"
1773 [(set (match_operand:DF
0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m")
1774 (match_operand:DF
1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))]
1775 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
1776 && (register_operand (operands[
0], DFmode)
1777 || reg_or_0_operand (operands[
1], DFmode))"
1778 { return riscv_output_move (operands[
0], operands[
1]); }
1779 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store")
1780 (set_attr "mode" "DF")])
1782 (define_insn "*movdf_hardfloat_rv64"
1783 [(set (match_operand:DF
0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1784 (match_operand:DF
1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
1785 "TARGET_64BIT && TARGET_DOUBLE_FLOAT
1786 && (register_operand (operands[
0], DFmode)
1787 || reg_or_0_operand (operands[
1], DFmode))"
1788 { return riscv_output_move (operands[
0], operands[
1]); }
1789 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1790 (set_attr "mode" "DF")])
1792 (define_insn "*movdf_softfloat"
1793 [(set (match_operand:DF
0 "nonimmediate_operand" "= r,r, m")
1794 (match_operand:DF
1 "move_operand" " rG,m,rG"))]
1795 "!TARGET_DOUBLE_FLOAT
1796 && (register_operand (operands[
0], DFmode)
1797 || reg_or_0_operand (operands[
1], DFmode))"
1798 { return riscv_output_move (operands[
0], operands[
1]); }
1799 [(set_attr "move_type" "move,load,store")
1800 (set_attr "mode" "DF")])
1803 [(set (match_operand:MOVE64
0 "nonimmediate_operand")
1804 (match_operand:MOVE64
1 "move_operand"))]
1806 && riscv_split_64bit_move_p (operands[
0], operands[
1])"
1809 riscv_split_doubleword_move (operands[
0], operands[
1]);
1813 (define_expand "cpymemsi"
1814 [(parallel [(set (match_operand:BLK
0 "general_operand")
1815 (match_operand:BLK
1 "general_operand"))
1816 (use (match_operand:SI
2 ""))
1817 (use (match_operand:SI
3 "const_int_operand"))])]
1820 if (riscv_expand_block_move (operands[
0], operands[
1], operands[
2]))
1826 ;; Expand in-line code to clear the instruction cache between operand[
0] and
1828 (define_expand "clear_cache"
1829 [(match_operand
0 "pmode_register_operand")
1830 (match_operand
1 "pmode_register_operand")]
1833 #ifdef ICACHE_FLUSH_FUNC
1834 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC),
1835 LCT_NORMAL, VOIDmode, operands[
0], Pmode,
1836 operands[
1], Pmode, const0_rtx, Pmode);
1838 if (TARGET_ZIFENCEI)
1839 emit_insn (gen_fence_i ());
1844 (define_insn "fence"
1845 [(unspec_volatile [(const_int
0)] UNSPECV_FENCE)]
1849 (define_insn "fence_i"
1850 [(unspec_volatile [(const_int
0)] UNSPECV_FENCE_I)]
1855 ;; ....................
1859 ;; ....................
1861 ;; Use a QImode shift count, to avoid generating sign or zero extend
1862 ;; instructions for shift counts, and to avoid dropping subregs.
1863 ;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
1864 ;; defined, but use of that is discouraged.
1866 (define_insn "<optab>si3"
1867 [(set (match_operand:SI
0 "register_operand" "= r")
1869 (match_operand:SI
1 "register_operand" " r")
1870 (match_operand:QI
2 "arith_operand" " rI")))]
1873 if (GET_CODE (operands[
2]) == CONST_INT)
1874 operands[
2] = GEN_INT (INTVAL (operands[
2])
1875 & (GET_MODE_BITSIZE (SImode) -
1));
1877 return TARGET_64BIT ? "<insn>%i2w
\t%
0,%
1,%
2" : "<insn>%i2
\t%
0,%
1,%
2";
1879 [(set_attr "type" "shift")
1880 (set_attr "mode" "SI")])
1882 (define_insn_and_split "*<optab>si3_mask"
1883 [(set (match_operand:SI
0 "register_operand" "= r")
1885 (match_operand:SI
1 "register_operand" " r")
1886 (match_operator
4 "subreg_lowpart_operator"
1888 (match_operand:SI
2 "register_operand" "r")
1889 (match_operand
3 "const_int_operand"))])))]
1890 "(INTVAL (operands[
3]) & (GET_MODE_BITSIZE (SImode)-
1))
1891 == GET_MODE_BITSIZE (SImode)-
1"
1895 (any_shift:SI (match_dup
1)
1897 "operands[
2] = gen_lowpart (QImode, operands[
2]);"
1898 [(set_attr "type" "shift")
1899 (set_attr "mode" "SI")])
1901 (define_insn_and_split "*<optab>si3_mask_1"
1902 [(set (match_operand:SI
0 "register_operand" "= r")
1904 (match_operand:SI
1 "register_operand" " r")
1905 (match_operator
4 "subreg_lowpart_operator"
1907 (match_operand:DI
2 "register_operand" "r")
1908 (match_operand
3 "const_int_operand"))])))]
1910 && (INTVAL (operands[
3]) & (GET_MODE_BITSIZE (SImode)-
1))
1911 == GET_MODE_BITSIZE (SImode)-
1"
1915 (any_shift:SI (match_dup
1)
1917 "operands[
2] = gen_lowpart (QImode, operands[
2]);"
1918 [(set_attr "type" "shift")
1919 (set_attr "mode" "SI")])
1921 (define_insn "<optab>di3"
1922 [(set (match_operand:DI
0 "register_operand" "= r")
1924 (match_operand:DI
1 "register_operand" " r")
1925 (match_operand:QI
2 "arith_operand" " rI")))]
1928 if (GET_CODE (operands[
2]) == CONST_INT)
1929 operands[
2] = GEN_INT (INTVAL (operands[
2])
1930 & (GET_MODE_BITSIZE (DImode) -
1));
1932 return "<insn>%i2
\t%
0,%
1,%
2";
1934 [(set_attr "type" "shift")
1935 (set_attr "mode" "DI")])
1937 (define_insn_and_split "*<optab>di3_mask"
1938 [(set (match_operand:DI
0 "register_operand" "= r")
1940 (match_operand:DI
1 "register_operand" " r")
1941 (match_operator
4 "subreg_lowpart_operator"
1943 (match_operand:SI
2 "register_operand" "r")
1944 (match_operand
3 "const_int_operand"))])))]
1946 && (INTVAL (operands[
3]) & (GET_MODE_BITSIZE (DImode)-
1))
1947 == GET_MODE_BITSIZE (DImode)-
1"
1951 (any_shift:DI (match_dup
1)
1953 "operands[
2] = gen_lowpart (QImode, operands[
2]);"
1954 [(set_attr "type" "shift")
1955 (set_attr "mode" "DI")])
1957 (define_insn_and_split "*<optab>di3_mask_1"
1958 [(set (match_operand:DI
0 "register_operand" "= r")
1960 (match_operand:DI
1 "register_operand" " r")
1961 (match_operator
4 "subreg_lowpart_operator"
1963 (match_operand:DI
2 "register_operand" "r")
1964 (match_operand
3 "const_int_operand"))])))]
1966 && (INTVAL (operands[
3]) & (GET_MODE_BITSIZE (DImode)-
1))
1967 == GET_MODE_BITSIZE (DImode)-
1"
1971 (any_shift:DI (match_dup
1)
1973 "operands[
2] = gen_lowpart (QImode, operands[
2]);"
1974 [(set_attr "type" "shift")
1975 (set_attr "mode" "DI")])
1977 (define_insn "*<optab>si3_extend"
1978 [(set (match_operand:DI
0 "register_operand" "= r")
1980 (any_shift:SI (match_operand:SI
1 "register_operand" " r")
1981 (match_operand:QI
2 "arith_operand" " rI"))))]
1984 if (GET_CODE (operands[
2]) == CONST_INT)
1985 operands[
2] = GEN_INT (INTVAL (operands[
2]) &
0x1f);
1987 return "<insn>%i2w
\t%
0,%
1,%
2";
1989 [(set_attr "type" "shift")
1990 (set_attr "mode" "SI")])
1992 (define_insn_and_split "*<optab>si3_extend_mask"
1993 [(set (match_operand:DI
0 "register_operand" "= r")
1996 (match_operand:SI
1 "register_operand" " r")
1997 (match_operator
4 "subreg_lowpart_operator"
1999 (match_operand:SI
2 "register_operand" " r")
2000 (match_operand
3 "const_int_operand"))]))))]
2002 && (INTVAL (operands[
3]) & (GET_MODE_BITSIZE (SImode)-
1))
2003 == GET_MODE_BITSIZE (SImode)-
1"
2008 (any_shift:SI (match_dup
1)
2010 "operands[
2] = gen_lowpart (QImode, operands[
2]);"
2011 [(set_attr "type" "shift")
2012 (set_attr "mode" "SI")])
2014 (define_insn_and_split "*<optab>si3_extend_mask_1"
2015 [(set (match_operand:DI
0 "register_operand" "= r")
2018 (match_operand:SI
1 "register_operand" " r")
2019 (match_operator
4 "subreg_lowpart_operator"
2021 (match_operand:DI
2 "register_operand" " r")
2022 (match_operand
3 "const_int_operand"))]))))]
2024 && (INTVAL (operands[
3]) & (GET_MODE_BITSIZE (SImode)-
1))
2025 == GET_MODE_BITSIZE (SImode)-
1"
2030 (any_shift:SI (match_dup
1)
2032 "operands[
2] = gen_lowpart (QImode, operands[
2]);"
2033 [(set_attr "type" "shift")
2034 (set_attr "mode" "SI")])
2036 ;; Non-canonical, but can be formed by ree when combine is not successful at
2037 ;; producing one of the two canonical patterns below.
2038 (define_insn "*lshrsi3_zero_extend_1"
2039 [(set (match_operand:DI
0 "register_operand" "=r")
2041 (lshiftrt:SI (match_operand:SI
1 "register_operand" " r")
2042 (match_operand
2 "const_int_operand"))))]
2043 "TARGET_64BIT && (INTVAL (operands[
2]) &
0x1f) >
0"
2045 operands[
2] = GEN_INT (INTVAL (operands[
2]) &
0x1f);
2047 return "srliw
\t%
0,%
1,%
2";
2049 [(set_attr "type" "shift")
2050 (set_attr "mode" "SI")])
2052 ;; Canonical form for a zero-extend of a logical right shift.
2053 (define_insn "*lshrsi3_zero_extend_2"
2054 [(set (match_operand:DI
0 "register_operand" "=r")
2055 (zero_extract:DI (match_operand:DI
1 "register_operand" " r")
2056 (match_operand
2 "const_int_operand")
2057 (match_operand
3 "const_int_operand")))]
2058 "(TARGET_64BIT && (INTVAL (operands[
3]) >
0)
2059 && (INTVAL (operands[
2]) + INTVAL (operands[
3]) ==
32))"
2061 return "srliw
\t%
0,%
1,%
3";
2063 [(set_attr "type" "shift")
2064 (set_attr "mode" "SI")])
2066 ;; Canonical form for a zero-extend of a logical right shift when the
2067 ;; shift count is
31.
2068 (define_insn "*lshrsi3_zero_extend_3"
2069 [(set (match_operand:DI
0 "register_operand" "=r")
2070 (lt:DI (match_operand:SI
1 "register_operand" " r")
2074 return "srliw
\t%
0,%
1,
31";
2076 [(set_attr "type" "shift")
2077 (set_attr "mode" "SI")])
2079 ;; Handle AND with
2^N-
1 for N from
12 to XLEN. This can be split into
2080 ;; two logical shifts. Otherwise it requires
3 instructions: lui,
2081 ;; xor/addi/srli, and.
2083 ;; Generating a temporary for the shift output gives better combiner results;
2084 ;; and also fixes a problem where op0 could be a paradoxical reg and shifting
2085 ;; by amounts larger than the size of the SUBREG_REG doesn't work.
2087 [(set (match_operand:GPR
0 "register_operand")
2088 (and:GPR (match_operand:GPR
1 "register_operand")
2089 (match_operand:GPR
2 "p2m1_shift_operand")))
2090 (clobber (match_operand:GPR
3 "register_operand"))]
2093 (ashift:GPR (match_dup
1) (match_dup
2)))
2095 (lshiftrt:GPR (match_dup
3) (match_dup
2)))]
2097 /* Op2 is a VOIDmode constant, so get the mode size from op1. */
2098 operands[
2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[
1]))
2099 - exact_log2 (INTVAL (operands[
2]) +
1));
2102 ;; Handle AND with
0xF...F0..
.0 where there are
32 to
63 zeros. This can be
2103 ;; split into two shifts. Otherwise it requires
3 instructions: li, sll, and.
2105 [(set (match_operand:DI
0 "register_operand")
2106 (and:DI (match_operand:DI
1 "register_operand")
2107 (match_operand:DI
2 "high_mask_shift_operand")))
2108 (clobber (match_operand:DI
3 "register_operand"))]
2111 (lshiftrt:DI (match_dup
1) (match_dup
2)))
2113 (ashift:DI (match_dup
3) (match_dup
2)))]
2115 operands[
2] = GEN_INT (ctz_hwi (INTVAL (operands[
2])));
2118 ;; Handle SImode to DImode zero-extend combined with a left shift. This can
2119 ;; occur when unsigned int is used for array indexing. Split this into two
2120 ;; shifts. Otherwise we can get
3 shifts.
2122 (define_insn_and_split "zero_extendsidi2_shifted"
2123 [(set (match_operand:DI
0 "register_operand" "=r")
2124 (and:DI (ashift:DI (match_operand:DI
1 "register_operand" "r")
2125 (match_operand:QI
2 "immediate_operand" "I"))
2126 (match_operand
3 "immediate_operand" "")))
2127 (clobber (match_scratch:DI
4 "=&r"))]
2128 "TARGET_64BIT && !TARGET_ZBA
2129 && ((INTVAL (operands[
3]) >> INTVAL (operands[
2])) ==
0xffffffff)"
2131 "&& reload_completed"
2133 (ashift:DI (match_dup
1) (const_int
32)))
2135 (lshiftrt:DI (match_dup
4) (match_dup
5)))]
2136 "operands[
5] = GEN_INT (
32 - (INTVAL (operands [
2])));"
2137 [(set_attr "type" "shift")
2138 (set_attr "mode" "DI")])
2141 ;; ....................
2143 ;; CONDITIONAL BRANCHES
2145 ;; ....................
2147 ;; Conditional branches
2149 (define_insn "*branch<mode>"
2152 (match_operator
1 "order_operator"
2153 [(match_operand:X
2 "register_operand" "r")
2154 (match_operand:X
3 "reg_or_0_operand" "rJ")])
2155 (label_ref (match_operand
0 "" ""))
2159 [(set_attr "type" "branch")
2160 (set_attr "mode" "none")])
2162 ;; Patterns for implementations that optimize short forward branches.
2164 (define_expand "mov<mode>cc"
2165 [(set (match_operand:GPR
0 "register_operand")
2166 (if_then_else:GPR (match_operand
1 "comparison_operator")
2167 (match_operand:GPR
2 "register_operand")
2168 (match_operand:GPR
3 "sfb_alu_operand")))]
2171 rtx cmp = operands[
1];
2172 /* We only handle word mode integer compares for now. */
2173 if (GET_MODE (XEXP (cmp,
0)) != word_mode)
2175 riscv_expand_conditional_move (operands[
0], operands[
2], operands[
3],
2176 GET_CODE (cmp), XEXP (cmp,
0), XEXP (cmp,
1));
2180 (define_insn "*mov<GPR:mode><X:mode>cc"
2181 [(set (match_operand:GPR
0 "register_operand" "=r,r")
2183 (match_operator
5 "order_operator"
2184 [(match_operand:X
1 "register_operand" "r,r")
2185 (match_operand:X
2 "reg_or_0_operand" "rJ,rJ")])
2186 (match_operand:GPR
3 "register_operand" "
0,
0")
2187 (match_operand:GPR
4 "sfb_alu_operand" "rJ,IL")))]
2190 b%C5 %
1,%z2,
1f; mv %
0,%z4;
1: # movcc
2191 b%C5 %
1,%z2,
1f; li %
0,%
4;
1: # movcc"
2192 [(set_attr "length" "
8")
2193 (set_attr "type" "sfb_alu")
2194 (set_attr "mode" "<GPR:MODE>")])
2196 ;; Used to implement built-in functions.
2197 (define_expand "condjump"
2199 (if_then_else (match_operand
0)
2200 (label_ref (match_operand
1))
2203 (define_expand "@cbranch<mode>
4"
2205 (if_then_else (match_operator
0 "comparison_operator"
2206 [(match_operand:BR
1 "register_operand")
2207 (match_operand:BR
2 "nonmemory_operand")])
2208 (label_ref (match_operand
3 ""))
2212 riscv_expand_conditional_branch (operands[
3], GET_CODE (operands[
0]),
2213 operands[
1], operands[
2]);
2217 (define_expand "@cbranch<mode>
4"
2219 (if_then_else (match_operator
0 "fp_branch_comparison"
2220 [(match_operand:ANYF
1 "register_operand")
2221 (match_operand:ANYF
2 "register_operand")])
2222 (label_ref (match_operand
3 ""))
2226 riscv_expand_conditional_branch (operands[
3], GET_CODE (operands[
0]),
2227 operands[
1], operands[
2]);
2231 (define_insn_and_split "*branch_on_bit<X:mode>"
2234 (match_operator
0 "equality_operator"
2235 [(zero_extract:X (match_operand:X
2 "register_operand" "r")
2237 (match_operand
3 "branch_on_bit_operand"))
2239 (label_ref (match_operand
1))
2241 (clobber (match_scratch:X
4 "=&r"))]
2246 (ashift:X (match_dup
2) (match_dup
3)))
2249 (match_op_dup
0 [(match_dup
4) (const_int
0)])
2250 (label_ref (match_operand
1))
2253 int shift = GET_MODE_BITSIZE (<MODE>mode) -
1 - INTVAL (operands[
3]);
2254 operands[
3] = GEN_INT (shift);
2256 if (GET_CODE (operands[
0]) == EQ)
2257 operands[
0] = gen_rtx_GE (<MODE>mode, operands[
4], const0_rtx);
2259 operands[
0] = gen_rtx_LT (<MODE>mode, operands[
4], const0_rtx);
2262 (define_insn_and_split "*branch_on_bit_range<X:mode>"
2265 (match_operator
0 "equality_operator"
2266 [(zero_extract:X (match_operand:X
2 "register_operand" "r")
2267 (match_operand
3 "branch_on_bit_operand")
2270 (label_ref (match_operand
1))
2272 (clobber (match_scratch:X
4 "=&r"))]
2277 (ashift:X (match_dup
2) (match_dup
3)))
2280 (match_op_dup
0 [(match_dup
4) (const_int
0)])
2281 (label_ref (match_operand
1))
2284 operands[
3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[
3]));
2288 ;; ....................
2290 ;; SETTING A REGISTER FROM A COMPARISON
2292 ;; ....................
2294 ;; Destination is always set in SI mode.
2296 (define_expand "cstore<mode>
4"
2297 [(set (match_operand:SI
0 "register_operand")
2298 (match_operator:SI
1 "order_operator"
2299 [(match_operand:GPR
2 "register_operand")
2300 (match_operand:GPR
3 "nonmemory_operand")]))]
2303 riscv_expand_int_scc (operands[
0], GET_CODE (operands[
1]), operands[
2],
2308 (define_expand "cstore<mode>
4"
2309 [(set (match_operand:SI
0 "register_operand")
2310 (match_operator:SI
1 "fp_scc_comparison"
2311 [(match_operand:ANYF
2 "register_operand")
2312 (match_operand:ANYF
3 "register_operand")]))]
2315 riscv_expand_float_scc (operands[
0], GET_CODE (operands[
1]), operands[
2],
2320 (define_insn "*cstore<ANYF:mode><X:mode>
4"
2321 [(set (match_operand:X
0 "register_operand" "=r")
2322 (match_operator:X
1 "fp_native_comparison"
2323 [(match_operand:ANYF
2 "register_operand" " f")
2324 (match_operand:ANYF
3 "register_operand" " f")]))]
2326 "f%C1.<fmt>
\t%
0,%
2,%
3"
2327 [(set_attr "type" "fcmp")
2328 (set_attr "mode" "<UNITMODE>")])
2330 (define_expand "f<quiet_pattern>_quiet<ANYF:mode><X:mode>
4"
2331 [(parallel [(set (match_operand:X
0 "register_operand")
2333 [(match_operand:ANYF
1 "register_operand")
2334 (match_operand:ANYF
2 "register_operand")]
2336 (clobber (match_scratch:X
3))])]
2337 "TARGET_HARD_FLOAT")
2339 (define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>
4_default"
2340 [(set (match_operand:X
0 "register_operand" "=r")
2342 [(match_operand:ANYF
1 "register_operand" " f")
2343 (match_operand:ANYF
2 "register_operand" " f")]
2345 (clobber (match_scratch:X
3 "=&r"))]
2346 "TARGET_HARD_FLOAT && ! HONOR_SNANS (<ANYF:MODE>mode)"
2347 "frflags
\t%
3\n\tf<quiet_pattern>.<fmt>
\t%
0,%
1,%
2\n\tfsflags %
3"
2348 [(set_attr "type" "fcmp")
2349 (set_attr "mode" "<UNITMODE>")
2350 (set (attr "length") (const_int
12))])
2352 (define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>
4_snan"
2353 [(set (match_operand:X
0 "register_operand" "=r")
2355 [(match_operand:ANYF
1 "register_operand" " f")
2356 (match_operand:ANYF
2 "register_operand" " f")]
2358 (clobber (match_scratch:X
3 "=&r"))]
2359 "TARGET_HARD_FLOAT && HONOR_SNANS (<ANYF:MODE>mode)"
2360 "frflags
\t%
3\n\tf<quiet_pattern>.<fmt>
\t%
0,%
1,%
2\n\tfsflags %
3\n\tfeq.<fmt>
\tzero,%
1,%
2"
2361 [(set_attr "type" "fcmp")
2362 (set_attr "mode" "<UNITMODE>")
2363 (set (attr "length") (const_int
16))])
2365 (define_insn "*seq_zero_<X:mode><GPR:mode>"
2366 [(set (match_operand:GPR
0 "register_operand" "=r")
2367 (eq:GPR (match_operand:X
1 "register_operand" " r")
2371 [(set_attr "type" "slt")
2372 (set_attr "mode" "<X:MODE>")])
2374 (define_insn "*sne_zero_<X:mode><GPR:mode>"
2375 [(set (match_operand:GPR
0 "register_operand" "=r")
2376 (ne:GPR (match_operand:X
1 "register_operand" " r")
2380 [(set_attr "type" "slt")
2381 (set_attr "mode" "<X:MODE>")])
2383 (define_insn "*sgt<u>_<X:mode><GPR:mode>"
2384 [(set (match_operand:GPR
0 "register_operand" "= r")
2385 (any_gt:GPR (match_operand:X
1 "register_operand" " r")
2386 (match_operand:X
2 "reg_or_0_operand" " rJ")))]
2389 [(set_attr "type" "slt")
2390 (set_attr "mode" "<X:MODE>")])
2392 (define_insn "*sge<u>_<X:mode><GPR:mode>"
2393 [(set (match_operand:GPR
0 "register_operand" "=r")
2394 (any_ge:GPR (match_operand:X
1 "register_operand" " r")
2397 "slt%i2<u>
\t%
0,zero,%
1"
2398 [(set_attr "type" "slt")
2399 (set_attr "mode" "<X:MODE>")])
2401 (define_insn "*slt<u>_<X:mode><GPR:mode>"
2402 [(set (match_operand:GPR
0 "register_operand" "= r")
2403 (any_lt:GPR (match_operand:X
1 "register_operand" " r")
2404 (match_operand:X
2 "arith_operand" " rI")))]
2406 "slt%i2<u>
\t%
0,%
1,%
2"
2407 [(set_attr "type" "slt")
2408 (set_attr "mode" "<X:MODE>")])
2410 (define_insn "*sle<u>_<X:mode><GPR:mode>"
2411 [(set (match_operand:GPR
0 "register_operand" "=r")
2412 (any_le:GPR (match_operand:X
1 "register_operand" " r")
2413 (match_operand:X
2 "sle_operand" "")))]
2416 operands[
2] = GEN_INT (INTVAL (operands[
2]) +
1);
2417 return "slt%i2<u>
\t%
0,%
1,%
2";
2419 [(set_attr "type" "slt")
2420 (set_attr "mode" "<X:MODE>")])
2423 ;; ....................
2425 ;; UNCONDITIONAL BRANCHES
2427 ;; ....................
2429 ;; Unconditional branches.
2433 (label_ref (match_operand
0 "" "")))]
2436 [(set_attr "type" "jump")
2437 (set_attr "mode" "none")])
2439 (define_expand "indirect_jump"
2440 [(set (pc) (match_operand
0 "register_operand"))]
2443 operands[
0] = force_reg (Pmode, operands[
0]);
2444 if (Pmode == SImode)
2445 emit_jump_insn (gen_indirect_jumpsi (operands[
0]));
2447 emit_jump_insn (gen_indirect_jumpdi (operands[
0]));
2451 (define_insn "indirect_jump<mode>"
2452 [(set (pc) (match_operand:P
0 "register_operand" "l"))]
2455 [(set_attr "type" "jump")
2456 (set_attr "mode" "none")])
2458 (define_expand "tablejump"
2459 [(set (pc) (match_operand
0 "register_operand" ""))
2460 (use (label_ref (match_operand
1 "" "")))]
2463 if (CASE_VECTOR_PC_RELATIVE)
2464 operands[
0] = expand_simple_binop (Pmode, PLUS, operands[
0],
2465 gen_rtx_LABEL_REF (Pmode, operands[
1]),
2466 NULL_RTX,
0, OPTAB_DIRECT);
2468 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
2469 emit_jump_insn (gen_tablejumpdi (operands[
0], operands[
1]));
2471 emit_jump_insn (gen_tablejumpsi (operands[
0], operands[
1]));
2475 (define_insn "tablejump<mode>"
2476 [(set (pc) (match_operand:GPR
0 "register_operand" "l"))
2477 (use (label_ref (match_operand
1 "" "")))]
2480 [(set_attr "type" "jump")
2481 (set_attr "mode" "none")])
2484 ;; ....................
2486 ;; Function prologue/epilogue
2488 ;; ....................
2491 (define_expand "prologue"
2495 riscv_expand_prologue ();
2499 ;; Block any insns from being moved before this point, since the
2500 ;; profiling call to mcount can use various registers that aren't
2501 ;; saved or used to pass arguments.
2503 (define_insn "blockage"
2504 [(unspec_volatile [(const_int
0)] UNSPECV_BLOCKAGE)]
2507 [(set_attr "type" "ghost")
2508 (set_attr "mode" "none")])
2510 (define_expand "epilogue"
2514 riscv_expand_epilogue (NORMAL_RETURN);
2518 (define_expand "sibcall_epilogue"
2522 riscv_expand_epilogue (SIBCALL_RETURN);
2526 ;; Trivial return. Make it look like a normal return insn as that
2527 ;; allows jump optimizations to work better.
2529 (define_expand "return"
2531 "riscv_can_use_return_insn ()"
2534 (define_insn "simple_return"
2538 return riscv_output_return ();
2540 [(set_attr "type" "jump")
2541 (set_attr "mode" "none")])
2545 (define_insn "simple_return_internal"
2547 (use (match_operand
0 "pmode_register_operand" ""))]
2550 [(set_attr "type" "jump")
2551 (set_attr "mode" "none")])
2553 ;; This is used in compiling the unwind routines.
2554 (define_expand "eh_return"
2555 [(use (match_operand
0 "general_operand"))]
2558 if (GET_MODE (operands[
0]) != word_mode)
2559 operands[
0] = convert_to_mode (word_mode, operands[
0],
0);
2561 emit_insn (gen_eh_set_lr_di (operands[
0]));
2563 emit_insn (gen_eh_set_lr_si (operands[
0]));
2565 emit_jump_insn (gen_eh_return_internal ());
2570 ;; Clobber the return address on the stack. We can't expand this
2571 ;; until we know where it will be put in the stack frame.
2573 (define_insn "eh_set_lr_si"
2574 [(unspec [(match_operand:SI
0 "register_operand" "r")] UNSPEC_EH_RETURN)
2575 (clobber (match_scratch:SI
1 "=&r"))]
2579 (define_insn "eh_set_lr_di"
2580 [(unspec [(match_operand:DI
0 "register_operand" "r")] UNSPEC_EH_RETURN)
2581 (clobber (match_scratch:DI
1 "=&r"))]
2586 [(unspec [(match_operand
0 "register_operand")] UNSPEC_EH_RETURN)
2587 (clobber (match_scratch
1))]
2591 riscv_set_return_address (operands[
0], operands[
1]);
2595 (define_insn_and_split "eh_return_internal"
2599 "epilogue_completed"
2601 "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
2604 ;; ....................
2608 ;; ....................
2610 (define_expand "sibcall"
2611 [(parallel [(call (match_operand
0 "")
2612 (match_operand
1 ""))
2613 (use (match_operand
2 "")) ;; next_arg_reg
2614 (use (match_operand
3 ""))])] ;; struct_value_size_rtx
2617 rtx target = riscv_legitimize_call_address (XEXP (operands[
0],
0));
2618 emit_call_insn (gen_sibcall_internal (target, operands[
1]));
2622 (define_insn "sibcall_internal"
2623 [(call (mem:SI (match_operand
0 "call_insn_operand" "j,S,U"))
2624 (match_operand
1 "" ""))]
2625 "SIBLING_CALL_P (insn)"
2630 [(set_attr "type" "call")])
2632 (define_expand "sibcall_value"
2633 [(parallel [(set (match_operand
0 "")
2634 (call (match_operand
1 "")
2635 (match_operand
2 "")))
2636 (use (match_operand
3 ""))])] ;; next_arg_reg
2639 rtx target = riscv_legitimize_call_address (XEXP (operands[
1],
0));
2640 emit_call_insn (gen_sibcall_value_internal (operands[
0], target, operands[
2]));
2644 (define_insn "sibcall_value_internal"
2645 [(set (match_operand
0 "" "")
2646 (call (mem:SI (match_operand
1 "call_insn_operand" "j,S,U"))
2647 (match_operand
2 "" "")))]
2648 "SIBLING_CALL_P (insn)"
2653 [(set_attr "type" "call")])
2655 (define_expand "call"
2656 [(parallel [(call (match_operand
0 "")
2657 (match_operand
1 ""))
2658 (use (match_operand
2 "")) ;; next_arg_reg
2659 (use (match_operand
3 ""))])] ;; struct_value_size_rtx
2662 rtx target = riscv_legitimize_call_address (XEXP (operands[
0],
0));
2663 emit_call_insn (gen_call_internal (target, operands[
1]));
2667 (define_insn "call_internal"
2668 [(call (mem:SI (match_operand
0 "call_insn_operand" "l,S,U"))
2669 (match_operand
1 "" ""))
2670 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2676 [(set_attr "type" "call")])
2678 (define_expand "call_value"
2679 [(parallel [(set (match_operand
0 "")
2680 (call (match_operand
1 "")
2681 (match_operand
2 "")))
2682 (use (match_operand
3 ""))])] ;; next_arg_reg
2685 rtx target = riscv_legitimize_call_address (XEXP (operands[
1],
0));
2686 emit_call_insn (gen_call_value_internal (operands[
0], target, operands[
2]));
2690 (define_insn "call_value_internal"
2691 [(set (match_operand
0 "" "")
2692 (call (mem:SI (match_operand
1 "call_insn_operand" "l,S,U"))
2693 (match_operand
2 "" "")))
2694 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2700 [(set_attr "type" "call")])
2702 ;; Call subroutine returning any type.
2704 (define_expand "untyped_call"
2705 [(parallel [(call (match_operand
0 "")
2707 (match_operand
1 "")
2708 (match_operand
2 "")])]
2713 emit_call_insn (gen_call (operands[
0], const0_rtx, NULL, const0_rtx));
2715 for (i =
0; i < XVECLEN (operands[
2],
0); i++)
2717 rtx set = XVECEXP (operands[
2],
0, i);
2718 riscv_emit_move (SET_DEST (set), SET_SRC (set));
2721 emit_insn (gen_blockage ());
2729 [(set_attr "type" "nop")
2730 (set_attr "mode" "none")])
2733 [(trap_if (const_int
1) (const_int
0))]
2737 ;; Must use the registers that we save to prevent the rename reg optimization
2738 ;; pass from using them before the gpr_save pattern when shrink wrapping
2739 ;; occurs. See bug
95252 for instance.
2741 (define_insn "gpr_save"
2742 [(match_parallel
1 "gpr_save_operation"
2743 [(unspec_volatile [(match_operand
0 "const_int_operand")]
2744 UNSPECV_GPR_SAVE)])]
2746 "call
\tt
0,__riscv_save_%
0")
2748 (define_insn "gpr_restore"
2749 [(unspec_volatile [(match_operand
0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2751 "tail
\t__riscv_restore_%
0")
2753 (define_insn "gpr_restore_return"
2755 (use (match_operand
0 "pmode_register_operand" ""))
2760 (define_insn "riscv_frflags"
2761 [(set (match_operand:SI
0 "register_operand" "=r")
2762 (unspec_volatile [(const_int
0)] UNSPECV_FRFLAGS))]
2766 (define_insn "riscv_fsflags"
2767 [(unspec_volatile [(match_operand:SI
0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2771 (define_insn "riscv_mret"
2773 (unspec_volatile [(const_int
0)] UNSPECV_MRET)]
2777 (define_insn "riscv_sret"
2779 (unspec_volatile [(const_int
0)] UNSPECV_SRET)]
2783 (define_insn "riscv_uret"
2785 (unspec_volatile [(const_int
0)] UNSPECV_URET)]
2789 (define_insn "stack_tie<mode>"
2790 [(set (mem:BLK (scratch))
2791 (unspec:BLK [(match_operand:X
0 "register_operand" "r")
2792 (match_operand:X
1 "register_operand" "r")]
2796 [(set_attr "length" "
0")]
2799 ;; This fixes a failure with gcc.c-torture/execute/pr64242.c at -O2 for a
2800 ;;
32-bit target when using -mtune=sifive-
7-series. The first sched pass
2801 ;; runs before register elimination, and we have a non-obvious dependency
2802 ;; between a use of the soft fp and a set of the hard fp. We fix this by
2803 ;; emitting a clobber using the hard fp between the two insns.
2804 (define_expand "restore_stack_nonlocal"
2805 [(match_operand
0 "register_operand")
2806 (match_operand
1 "memory_operand")]
2809 emit_move_insn (operands[
0], operands[
1]);
2810 /* Prevent the following hard fp restore from being moved before the move
2811 insn above which uses a copy of the soft fp reg. */
2812 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2816 ;; Named pattern for expanding thread pointer reference.
2817 (define_expand "get_thread_pointer<mode>"
2818 [(set (match_operand:P
0 "register_operand" "=r")
2823 ;; Named patterns for stack smashing protection.
2825 (define_expand "stack_protect_set"
2826 [(match_operand
0 "memory_operand")
2827 (match_operand
1 "memory_operand")]
2830 machine_mode mode = GET_MODE (operands[
0]);
2831 if (riscv_stack_protector_guard == SSP_TLS)
2833 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
2834 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
2835 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
2836 operands[
1] = gen_rtx_MEM (Pmode, addr);
2839 emit_insn ((mode == DImode
2840 ? gen_stack_protect_set_di
2841 : gen_stack_protect_set_si) (operands[
0], operands[
1]));
2845 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
2846 ;; canary value does not live beyond the life of this sequence.
2847 (define_insn "stack_protect_set_<mode>"
2848 [(set (match_operand:GPR
0 "memory_operand" "=m")
2849 (unspec:GPR [(match_operand:GPR
1 "memory_operand" "m")]
2851 (set (match_scratch:GPR
2 "=&r") (const_int
0))]
2853 "<load>
\\t%
2, %
1\;<store>
\\t%
2, %
0\;li
\t%
2,
0"
2854 [(set_attr "length" "
12")])
2856 (define_expand "stack_protect_test"
2857 [(match_operand
0 "memory_operand")
2858 (match_operand
1 "memory_operand")
2863 machine_mode mode = GET_MODE (operands[
0]);
2865 result = gen_reg_rtx(mode);
2866 if (riscv_stack_protector_guard == SSP_TLS)
2868 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
2869 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
2870 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
2871 operands[
1] = gen_rtx_MEM (Pmode, addr);
2873 emit_insn ((mode == DImode
2874 ? gen_stack_protect_test_di
2875 : gen_stack_protect_test_si) (result,
2879 rtx cond = gen_rtx_EQ (VOIDmode, result, const0_rtx);
2880 emit_jump_insn (gen_cbranch4 (mode, cond, result, const0_rtx, operands[
2]));
2885 (define_insn "stack_protect_test_<mode>"
2886 [(set (match_operand:GPR
0 "register_operand" "=r")
2887 (unspec:GPR [(match_operand:GPR
1 "memory_operand" "m")
2888 (match_operand:GPR
2 "memory_operand" "m")]
2890 (clobber (match_scratch:GPR
3 "=&r"))]
2892 "<load>
\t%
3, %
1\;<load>
\t%
0, %
2\;xor
\t%
0, %
3, %
0\;li
\t%
3,
0"
2893 [(set_attr "length" "
12")])
2895 (define_insn "riscv_clean_<mode>"
2896 [(unspec_volatile:X [(match_operand:X
0 "register_operand" "r")]
2902 (define_insn "riscv_flush_<mode>"
2903 [(unspec_volatile:X [(match_operand:X
0 "register_operand" "r")]
2909 (define_insn "riscv_inval_<mode>"
2910 [(unspec_volatile:X [(match_operand:X
0 "register_operand" "r")]
2916 (define_insn "riscv_zero_<mode>"
2917 [(unspec_volatile:X [(match_operand:X
0 "register_operand" "r")]
2923 (define_insn "prefetch"
2924 [(prefetch (match_operand
0 "address_operand" "p")
2925 (match_operand
1 "imm5_operand" "i")
2926 (match_operand
2 "const_int_operand" "n"))]
2929 switch (INTVAL (operands[
1]))
2931 case
0: return "prefetch.r
\t%a0";
2932 case
1: return "prefetch.w
\t%a0";
2933 default: gcc_unreachable ();
2937 (define_insn "riscv_prefetchi_<mode>"
2938 [(unspec_volatile:X [(match_operand:X
0 "address_operand" "p")
2939 (match_operand:X
1 "imm5_operand" "i")]
2945 (include "bitmanip.md")
2947 (include "peephole.md")
2949 (include "generic.md")
2950 (include "sifive-
7.md")