1 ;; Machine description for RISC-V for GNU compiler.
2 ;; Copyright (C) 2011-2021 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.
69 ;; Stack Smash Protector
75 [(RETURN_ADDR_REGNUM 1)
98 (include "predicates.md")
99 (include "constraints.md")
101 ;; ....................
105 ;; ....................
107 (define_attr "got" "unset,xgot_high,load"
108 (const_string "unset"))
110 ;; Classification of moves, extensions and truncations. Most values
111 ;; are as for "type" (see below) but there are also the following
112 ;; move-specific values:
114 ;; andi a single ANDI instruction
115 ;; shift_shift a shift left followed by a shift right
117 ;; This attribute is used to determine the instruction's length and
118 ;; scheduling type. For doubleword moves, the attribute always describes
119 ;; the split instructions; in some cases, it is more appropriate for the
120 ;; scheduling type to be "multi" instead.
121 (define_attr "move_type"
122 "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove,
123 const,logical,arith,andi,shift_shift"
124 (const_string "unknown"))
126 ;; Main data type used by the insn
127 (define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF"
128 (const_string "unknown"))
130 ;; True if the main data type is twice the size of a word.
131 (define_attr "dword_mode" "no,yes"
132 (cond [(and (eq_attr "mode" "DI,DF")
133 (eq (symbol_ref "TARGET_64BIT") (const_int 0)))
136 (and (eq_attr "mode" "TI,TF")
137 (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
138 (const_string "yes")]
139 (const_string "no")))
141 ;; Classification of each insn.
142 ;; branch conditional branch
143 ;; jump unconditional jump
144 ;; call unconditional call
145 ;; load load instruction(s)
146 ;; fpload floating point load
147 ;; store store instruction(s)
148 ;; fpstore floating point store
149 ;; mtc transfer to coprocessor
150 ;; mfc transfer from coprocessor
151 ;; const load constant
152 ;; arith integer arithmetic instructions
153 ;; logical integer logical instructions
154 ;; shift integer shift instructions
155 ;; slt set less than instructions
156 ;; imul integer multiply
157 ;; idiv integer divide
158 ;; move integer register move (addi rd, rs1, 0)
159 ;; fmove floating point register move
160 ;; fadd floating point add/subtract
161 ;; fmul floating point multiply
162 ;; fmadd floating point multiply-add
163 ;; fdiv floating point divide
164 ;; fcmp floating point compare
165 ;; fcvt floating point convert
166 ;; fsqrt floating point square root
167 ;; multi multiword sequence (or user asm statements)
169 ;; ghost an instruction that produces no real code
171 "unknown,branch,jump,call,load,fpload,store,fpstore,
172 mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
173 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate"
174 (cond [(eq_attr "got" "load") (const_string "load")
176 ;; If a doubleword move uses these expensive instructions,
177 ;; it is usually better to schedule them in the same way
178 ;; as the singleword form, rather than as "multi".
179 (eq_attr "move_type" "load") (const_string "load")
180 (eq_attr "move_type" "fpload") (const_string "fpload")
181 (eq_attr "move_type" "store") (const_string "store")
182 (eq_attr "move_type" "fpstore") (const_string "fpstore")
183 (eq_attr "move_type" "mtc") (const_string "mtc")
184 (eq_attr "move_type" "mfc") (const_string "mfc")
186 ;; These types of move are always single insns.
187 (eq_attr "move_type" "fmove") (const_string "fmove")
188 (eq_attr "move_type" "arith") (const_string "arith")
189 (eq_attr "move_type" "logical") (const_string "logical")
190 (eq_attr "move_type" "andi") (const_string "logical")
192 ;; These types of move are always split.
193 (eq_attr "move_type" "shift_shift")
194 (const_string "multi")
196 ;; These types of move are split for doubleword modes only.
197 (and (eq_attr "move_type" "move,const")
198 (eq_attr "dword_mode" "yes"))
199 (const_string "multi")
200 (eq_attr "move_type" "move") (const_string "move")
201 (eq_attr "move_type" "const") (const_string "const")]
202 (const_string "unknown")))
204 ;; Length of instruction in bytes.
205 (define_attr "length" ""
207 ;; Branches further than +/- 4 KiB require two instructions.
208 (eq_attr "type" "branch")
209 (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4088))
210 (le (minus (pc) (match_dup 0)) (const_int 4092)))
214 ;; Conservatively assume calls take two instructions (AUIPC + JALR).
215 ;; The linker will opportunistically relax the sequence to JAL.
216 (eq_attr "type" "call") (const_int 8)
218 ;; "Ghost" instructions occupy no space.
219 (eq_attr "type" "ghost") (const_int 0)
221 (eq_attr "got" "load") (const_int 8)
223 (eq_attr "type" "fcmp") (const_int 8)
225 ;; SHIFT_SHIFTs are decomposed into two separate instructions.
226 (eq_attr "move_type" "shift_shift")
229 ;; Check for doubleword moves that are decomposed into two
231 (and (eq_attr "move_type" "mtc,mfc,move")
232 (eq_attr "dword_mode" "yes"))
235 ;; Doubleword CONST{,N} moves are split into two word
237 (and (eq_attr "move_type" "const")
238 (eq_attr "dword_mode" "yes"))
239 (symbol_ref "riscv_split_const_insns (operands[1]) * 4")
241 ;; Otherwise, constants, loads and stores are handled by external
243 (eq_attr "move_type" "load,fpload")
244 (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4")
245 (eq_attr "move_type" "store,fpstore")
246 (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4")
249 ;; Is copying of this instruction disallowed?
250 (define_attr "cannot_copy" "no,yes" (const_string "no"))
252 ;; Microarchitectures we know how to tune for.
253 ;; Keep this in sync with enum riscv_microarchitecture.
256 (const (symbol_ref "((enum attr_tune) riscv_microarchitecture)")))
258 ;; Describe a user's asm statement.
259 (define_asm_attributes
260 [(set_attr "type" "multi")])
262 ;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated
263 ;; from the same template.
264 (define_mode_iterator GPR [SI (DI "TARGET_64BIT")])
266 ;; This mode iterator allows :P to be used for patterns that operate on
267 ;; pointer-sized quantities. Exactly one of the two alternatives will match.
268 (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
270 ;; Likewise, but for XLEN-sized quantities.
271 (define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")])
273 ;; Branches operate on XLEN-sized quantities, but for RV64 we accept
274 ;; QImode values so we can force zero-extension.
275 (define_mode_iterator BR [(QI "TARGET_64BIT") SI (DI "TARGET_64BIT")])
277 ;; 32-bit moves for which we provide move patterns.
278 (define_mode_iterator MOVE32 [SI])
280 ;; 64-bit modes for which we provide move patterns.
281 (define_mode_iterator MOVE64 [DI DF])
283 ;; Iterator for sub-32-bit integer modes.
284 (define_mode_iterator SHORT [QI HI])
286 ;; Iterator for HImode constant generation.
287 (define_mode_iterator HISI [HI SI])
289 ;; Iterator for QImode extension patterns.
290 (define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")])
292 ;; Iterator for hardware integer modes narrower than XLEN.
293 (define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")])
295 ;; Iterator for hardware-supported integer modes.
296 (define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
298 ;; Iterator for hardware-supported floating-point modes.
299 (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
300 (DF "TARGET_DOUBLE_FLOAT")])
302 ;; Iterator for floating-point modes that can be loaded into X registers.
303 (define_mode_iterator SOFTF [SF (DF "TARGET_64BIT")])
305 ;; This attribute gives the length suffix for a sign- or zero-extension
307 (define_mode_attr size [(QI "b") (HI "h")])
309 ;; Mode attributes for loads.
310 (define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
312 ;; Instruction names for integer loads that aren't explicitly sign or zero
313 ;; extended. See riscv_output_move and LOAD_EXTEND_OP.
314 (define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")])
316 ;; Mode attribute for FP loads into integer registers.
317 (define_mode_attr softload [(SF "lw") (DF "ld")])
319 ;; Instruction names for stores.
320 (define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
322 ;; Instruction names for FP stores from integer registers.
323 (define_mode_attr softstore [(SF "sw") (DF "sd")])
325 ;; This attribute gives the best constraint to use for registers of
327 (define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
329 ;; This attribute gives the format suffix for floating-point operations.
330 (define_mode_attr fmt [(SF "s") (DF "d")])
332 ;; This attribute gives the integer suffix for floating-point conversions.
333 (define_mode_attr ifmt [(SI "w") (DI "l")])
335 ;; This attribute gives the format suffix for atomic memory operations.
336 (define_mode_attr amo [(SI "w") (DI "d")])
338 ;; This attribute gives the upper-case mode name for one unit of a
339 ;; floating-point mode.
340 (define_mode_attr UNITMODE [(SF "SF") (DF "DF")])
342 ;; This attribute gives the integer mode that has half the size of
343 ;; the controlling mode.
344 (define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")])
346 ;; Iterator and attributes for floating-point rounding instructions.
347 (define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND])
348 (define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")])
349 (define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")])
351 ;; Iterator and attributes for quiet comparisons.
352 (define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET])
353 (define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")])
355 ;; This code iterator allows signed and unsigned widening multiplications
356 ;; to use the same template.
357 (define_code_iterator any_extend [sign_extend zero_extend])
359 ;; This code iterator allows the two right shift instructions to be
360 ;; generated from the same template.
361 (define_code_iterator any_shiftrt [ashiftrt lshiftrt])
363 ;; This code iterator allows the three shift instructions to be generated
364 ;; from the same template.
365 (define_code_iterator any_shift [ashift ashiftrt lshiftrt])
367 ;; This code iterator allows the three bitwise instructions to be generated
368 ;; from the same template.
369 (define_code_iterator any_bitwise [and ior xor])
371 ;; This code iterator allows unsigned and signed division to be generated
372 ;; from the same template.
373 (define_code_iterator any_div [div udiv mod umod])
375 ;; This code iterator allows unsigned and signed modulus to be generated
376 ;; from the same template.
377 (define_code_iterator any_mod [mod umod])
379 ;; These code iterators allow the signed and unsigned scc operations to use
380 ;; the same template.
381 (define_code_iterator any_gt [gt gtu])
382 (define_code_iterator any_ge [ge geu])
383 (define_code_iterator any_lt [lt ltu])
384 (define_code_iterator any_le [le leu])
386 ;; <u> expands to an empty string when doing a signed operation and
387 ;; "u" when doing an unsigned operation.
388 (define_code_attr u [(sign_extend "") (zero_extend "u")
394 ;; <su> is like <u>, but the signed form expands to "s" rather than "".
395 (define_code_attr su [(sign_extend "s") (zero_extend "u")])
397 ;; <optab> expands to the name of the optab for a particular code.
398 (define_code_attr optab [(ashift "ashl")
415 ;; <insn> expands to the name of the insn that implements a particular code.
416 (define_code_attr insn [(ashift "sll")
429 ;; Ghost instructions produce no real code and introduce no hazards.
430 ;; They exist purely to express an effect on dataflow.
431 (define_insn_reservation "ghost" 0
432 (eq_attr "type" "ghost")
436 ;; ....................
440 ;; ....................
443 (define_insn "add<mode>3"
444 [(set (match_operand:ANYF 0 "register_operand" "=f")
445 (plus:ANYF (match_operand:ANYF 1 "register_operand" " f")
446 (match_operand:ANYF 2 "register_operand" " f")))]
448 "fadd.<fmt>\t%0,%1,%2"
449 [(set_attr "type" "fadd")
450 (set_attr "mode" "<UNITMODE>")])
452 (define_insn "addsi3"
453 [(set (match_operand:SI 0 "register_operand" "=r,r")
454 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
455 (match_operand:SI 2 "arith_operand" " r,I")))]
457 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
458 [(set_attr "type" "arith")
459 (set_attr "mode" "SI")])
461 (define_insn "adddi3"
462 [(set (match_operand:DI 0 "register_operand" "=r,r")
463 (plus:DI (match_operand:DI 1 "register_operand" " r,r")
464 (match_operand:DI 2 "arith_operand" " r,I")))]
467 [(set_attr "type" "arith")
468 (set_attr "mode" "DI")])
470 (define_expand "addv<mode>4"
471 [(set (match_operand:GPR 0 "register_operand" "=r,r")
472 (plus:GPR (match_operand:GPR 1 "register_operand" " r,r")
473 (match_operand:GPR 2 "arith_operand" " r,I")))
474 (label_ref (match_operand 3 "" ""))]
477 if (TARGET_64BIT && <MODE>mode == SImode)
479 rtx t3 = gen_reg_rtx (DImode);
480 rtx t4 = gen_reg_rtx (DImode);
481 rtx t5 = gen_reg_rtx (DImode);
482 rtx t6 = gen_reg_rtx (DImode);
484 emit_insn (gen_addsi3 (operands[0], operands[1], operands[2]));
485 if (GET_CODE (operands[1]) != CONST_INT)
486 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
489 if (GET_CODE (operands[2]) != CONST_INT)
490 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
493 emit_insn (gen_adddi3 (t3, t4, t5));
494 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
496 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
500 rtx t3 = gen_reg_rtx (<MODE>mode);
501 rtx t4 = gen_reg_rtx (<MODE>mode);
503 emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
504 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[2], const0_rtx);
505 emit_insn (gen_cstore<mode>4 (t3, cmp1, operands[2], const0_rtx));
506 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[0], operands[1]);
508 emit_insn (gen_cstore<mode>4 (t4, cmp2, operands[0], operands[1]));
509 riscv_expand_conditional_branch (operands[3], NE, t3, t4);
514 (define_expand "uaddv<mode>4"
515 [(set (match_operand:GPR 0 "register_operand" "=r,r")
516 (plus:GPR (match_operand:GPR 1 "register_operand" " r,r")
517 (match_operand:GPR 2 "arith_operand" " r,I")))
518 (label_ref (match_operand 3 "" ""))]
521 if (TARGET_64BIT && <MODE>mode == SImode)
523 rtx t3 = gen_reg_rtx (DImode);
524 rtx t4 = gen_reg_rtx (DImode);
526 if (GET_CODE (operands[1]) != CONST_INT)
527 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
530 emit_insn (gen_addsi3 (operands[0], operands[1], operands[2]));
531 emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
533 riscv_expand_conditional_branch (operands[3], LTU, t4, t3);
537 emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
538 riscv_expand_conditional_branch (operands[3], LTU, operands[0],
545 (define_insn "*addsi3_extended"
546 [(set (match_operand:DI 0 "register_operand" "=r,r")
548 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
549 (match_operand:SI 2 "arith_operand" " r,I"))))]
552 [(set_attr "type" "arith")
553 (set_attr "mode" "SI")])
555 (define_insn "*addsi3_extended2"
556 [(set (match_operand:DI 0 "register_operand" "=r,r")
558 (match_operator:SI 3 "subreg_lowpart_operator"
559 [(plus:DI (match_operand:DI 1 "register_operand" " r,r")
560 (match_operand:DI 2 "arith_operand" " r,I"))])))]
563 [(set_attr "type" "arith")
564 (set_attr "mode" "SI")])
567 ;; ....................
571 ;; ....................
574 (define_insn "sub<mode>3"
575 [(set (match_operand:ANYF 0 "register_operand" "=f")
576 (minus:ANYF (match_operand:ANYF 1 "register_operand" " f")
577 (match_operand:ANYF 2 "register_operand" " f")))]
579 "fsub.<fmt>\t%0,%1,%2"
580 [(set_attr "type" "fadd")
581 (set_attr "mode" "<UNITMODE>")])
583 (define_insn "subdi3"
584 [(set (match_operand:DI 0 "register_operand" "= r")
585 (minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
586 (match_operand:DI 2 "register_operand" " r")))]
589 [(set_attr "type" "arith")
590 (set_attr "mode" "DI")])
592 (define_insn "subsi3"
593 [(set (match_operand:SI 0 "register_operand" "= r")
594 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
595 (match_operand:SI 2 "register_operand" " r")))]
597 { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; }
598 [(set_attr "type" "arith")
599 (set_attr "mode" "SI")])
601 (define_expand "subv<mode>4"
602 [(set (match_operand:GPR 0 "register_operand" "= r")
603 (minus:GPR (match_operand:GPR 1 "reg_or_0_operand" " rJ")
604 (match_operand:GPR 2 "register_operand" " r")))
605 (label_ref (match_operand 3 "" ""))]
608 if (TARGET_64BIT && <MODE>mode == SImode)
610 rtx t3 = gen_reg_rtx (DImode);
611 rtx t4 = gen_reg_rtx (DImode);
612 rtx t5 = gen_reg_rtx (DImode);
613 rtx t6 = gen_reg_rtx (DImode);
615 emit_insn (gen_subsi3 (operands[0], operands[1], operands[2]));
616 if (GET_CODE (operands[1]) != CONST_INT)
617 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
620 if (GET_CODE (operands[2]) != CONST_INT)
621 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
624 emit_insn (gen_subdi3 (t3, t4, t5));
625 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
627 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
631 rtx t3 = gen_reg_rtx (<MODE>mode);
632 rtx t4 = gen_reg_rtx (<MODE>mode);
634 emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
636 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[2], const0_rtx);
637 emit_insn (gen_cstore<mode>4 (t3, cmp1, operands[2], const0_rtx));
639 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[1], operands[0]);
640 emit_insn (gen_cstore<mode>4 (t4, cmp2, operands[1], operands[0]));
642 riscv_expand_conditional_branch (operands[3], NE, t3, t4);
648 (define_expand "usubv<mode>4"
649 [(set (match_operand:GPR 0 "register_operand" "= r")
650 (minus:GPR (match_operand:GPR 1 "reg_or_0_operand" " rJ")
651 (match_operand:GPR 2 "register_operand" " r")))
652 (label_ref (match_operand 3 "" ""))]
655 if (TARGET_64BIT && <MODE>mode == SImode)
657 rtx t3 = gen_reg_rtx (DImode);
658 rtx t4 = gen_reg_rtx (DImode);
660 if (GET_CODE (operands[1]) != CONST_INT)
661 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
664 emit_insn (gen_subsi3 (operands[0], operands[1], operands[2]));
665 emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
667 riscv_expand_conditional_branch (operands[3], LTU, t3, t4);
671 emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
672 riscv_expand_conditional_branch (operands[3], LTU, operands[1],
680 (define_insn "*subsi3_extended"
681 [(set (match_operand:DI 0 "register_operand" "= r")
683 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
684 (match_operand:SI 2 "register_operand" " r"))))]
687 [(set_attr "type" "arith")
688 (set_attr "mode" "SI")])
690 (define_insn "*subsi3_extended2"
691 [(set (match_operand:DI 0 "register_operand" "= r")
693 (match_operator:SI 3 "subreg_lowpart_operator"
694 [(minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
695 (match_operand:DI 2 "register_operand" " r"))])))]
698 [(set_attr "type" "arith")
699 (set_attr "mode" "SI")])
701 (define_insn "negdi2"
702 [(set (match_operand:DI 0 "register_operand" "=r")
703 (neg:DI (match_operand:DI 1 "register_operand" " r")))]
706 [(set_attr "type" "arith")
707 (set_attr "mode" "DI")])
709 (define_insn "negsi2"
710 [(set (match_operand:SI 0 "register_operand" "=r")
711 (neg:SI (match_operand:SI 1 "register_operand" " r")))]
713 { return TARGET_64BIT ? "negw\t%0,%1" : "neg\t%0,%1"; }
714 [(set_attr "type" "arith")
715 (set_attr "mode" "SI")])
717 (define_insn "*negsi2_extended"
718 [(set (match_operand:DI 0 "register_operand" "=r")
720 (neg:SI (match_operand:SI 1 "register_operand" " r"))))]
723 [(set_attr "type" "arith")
724 (set_attr "mode" "SI")])
726 (define_insn "*negsi2_extended2"
727 [(set (match_operand:DI 0 "register_operand" "=r")
729 (match_operator:SI 2 "subreg_lowpart_operator"
730 [(neg:DI (match_operand:DI 1 "register_operand" " r"))])))]
733 [(set_attr "type" "arith")
734 (set_attr "mode" "SI")])
737 ;; ....................
741 ;; ....................
744 (define_insn "mul<mode>3"
745 [(set (match_operand:ANYF 0 "register_operand" "=f")
746 (mult:ANYF (match_operand:ANYF 1 "register_operand" " f")
747 (match_operand:ANYF 2 "register_operand" " f")))]
749 "fmul.<fmt>\t%0,%1,%2"
750 [(set_attr "type" "fmul")
751 (set_attr "mode" "<UNITMODE>")])
753 (define_insn "mulsi3"
754 [(set (match_operand:SI 0 "register_operand" "=r")
755 (mult:SI (match_operand:SI 1 "register_operand" " r")
756 (match_operand:SI 2 "register_operand" " r")))]
758 { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; }
759 [(set_attr "type" "imul")
760 (set_attr "mode" "SI")])
762 (define_insn "muldi3"
763 [(set (match_operand:DI 0 "register_operand" "=r")
764 (mult:DI (match_operand:DI 1 "register_operand" " r")
765 (match_operand:DI 2 "register_operand" " r")))]
766 "TARGET_MUL && TARGET_64BIT"
768 [(set_attr "type" "imul")
769 (set_attr "mode" "DI")])
771 (define_expand "mulv<mode>4"
772 [(set (match_operand:GPR 0 "register_operand" "=r")
773 (mult:GPR (match_operand:GPR 1 "register_operand" " r")
774 (match_operand:GPR 2 "register_operand" " r")))
775 (label_ref (match_operand 3 "" ""))]
778 if (TARGET_64BIT && <MODE>mode == SImode)
780 rtx t3 = gen_reg_rtx (DImode);
781 rtx t4 = gen_reg_rtx (DImode);
782 rtx t5 = gen_reg_rtx (DImode);
783 rtx t6 = gen_reg_rtx (DImode);
785 if (GET_CODE (operands[1]) != CONST_INT)
786 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
789 if (GET_CODE (operands[2]) != CONST_INT)
790 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
793 emit_insn (gen_muldi3 (t3, t4, t5));
795 emit_move_insn (operands[0], gen_lowpart (SImode, t3));
796 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
798 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
802 rtx hp = gen_reg_rtx (<MODE>mode);
803 rtx lp = gen_reg_rtx (<MODE>mode);
805 emit_insn (gen_smul<mode>3_highpart (hp, operands[1], operands[2]));
806 emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
807 emit_insn (gen_ashr<mode>3 (lp, operands[0],
808 GEN_INT (BITS_PER_WORD - 1)));
810 riscv_expand_conditional_branch (operands[3], NE, hp, lp);
816 (define_expand "umulv<mode>4"
817 [(set (match_operand:GPR 0 "register_operand" "=r")
818 (mult:GPR (match_operand:GPR 1 "register_operand" " r")
819 (match_operand:GPR 2 "register_operand" " r")))
820 (label_ref (match_operand 3 "" ""))]
823 if (TARGET_64BIT && <MODE>mode == SImode)
825 rtx t3 = gen_reg_rtx (DImode);
826 rtx t4 = gen_reg_rtx (DImode);
827 rtx t5 = gen_reg_rtx (DImode);
828 rtx t6 = gen_reg_rtx (DImode);
829 rtx t7 = gen_reg_rtx (DImode);
830 rtx t8 = gen_reg_rtx (DImode);
832 if (GET_CODE (operands[1]) != CONST_INT)
833 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
836 if (GET_CODE (operands[2]) != CONST_INT)
837 emit_insn (gen_extend_insn (t4, operands[2], DImode, SImode, 0));
841 emit_insn (gen_ashldi3 (t5, t3, GEN_INT (32)));
842 emit_insn (gen_ashldi3 (t6, t4, GEN_INT (32)));
843 emit_insn (gen_umuldi3_highpart (t7, t5, t6));
844 emit_move_insn (operands[0], gen_lowpart (SImode, t7));
845 emit_insn (gen_lshrdi3 (t8, t7, GEN_INT (32)));
847 riscv_expand_conditional_branch (operands[3], NE, t8, const0_rtx);
851 rtx hp = gen_reg_rtx (<MODE>mode);
853 emit_insn (gen_umul<mode>3_highpart (hp, operands[1], operands[2]));
854 emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
856 riscv_expand_conditional_branch (operands[3], NE, hp, const0_rtx);
862 (define_insn "*mulsi3_extended"
863 [(set (match_operand:DI 0 "register_operand" "=r")
865 (mult:SI (match_operand:SI 1 "register_operand" " r")
866 (match_operand:SI 2 "register_operand" " r"))))]
867 "TARGET_MUL && TARGET_64BIT"
869 [(set_attr "type" "imul")
870 (set_attr "mode" "SI")])
872 (define_insn "*mulsi3_extended2"
873 [(set (match_operand:DI 0 "register_operand" "=r")
875 (match_operator:SI 3 "subreg_lowpart_operator"
876 [(mult:DI (match_operand:DI 1 "register_operand" " r")
877 (match_operand:DI 2 "register_operand" " r"))])))]
878 "TARGET_MUL && TARGET_64BIT"
880 [(set_attr "type" "imul")
881 (set_attr "mode" "SI")])
884 ;; ........................
886 ;; MULTIPLICATION HIGH-PART
888 ;; ........................
892 (define_expand "<u>mulditi3"
893 [(set (match_operand:TI 0 "register_operand")
894 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
895 (any_extend:TI (match_operand:DI 2 "register_operand"))))]
896 "TARGET_MUL && TARGET_64BIT"
898 rtx low = gen_reg_rtx (DImode);
899 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
901 rtx high = gen_reg_rtx (DImode);
902 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
904 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
905 emit_move_insn (gen_highpart (DImode, operands[0]), high);
909 (define_insn "<su>muldi3_highpart"
910 [(set (match_operand:DI 0 "register_operand" "=r")
913 (mult:TI (any_extend:TI
914 (match_operand:DI 1 "register_operand" " r"))
916 (match_operand:DI 2 "register_operand" " r")))
918 "TARGET_MUL && TARGET_64BIT"
920 [(set_attr "type" "imul")
921 (set_attr "mode" "DI")])
923 (define_expand "usmulditi3"
924 [(set (match_operand:TI 0 "register_operand")
925 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand"))
926 (sign_extend:TI (match_operand:DI 2 "register_operand"))))]
927 "TARGET_MUL && TARGET_64BIT"
929 rtx low = gen_reg_rtx (DImode);
930 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
932 rtx high = gen_reg_rtx (DImode);
933 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2]));
935 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
936 emit_move_insn (gen_highpart (DImode, operands[0]), high);
940 (define_insn "usmuldi3_highpart"
941 [(set (match_operand:DI 0 "register_operand" "=r")
944 (mult:TI (zero_extend:TI
945 (match_operand:DI 1 "register_operand" "r"))
947 (match_operand:DI 2 "register_operand" " r")))
949 "TARGET_MUL && TARGET_64BIT"
951 [(set_attr "type" "imul")
952 (set_attr "mode" "DI")])
954 (define_expand "<u>mulsidi3"
955 [(set (match_operand:DI 0 "register_operand" "=r")
956 (mult:DI (any_extend:DI
957 (match_operand:SI 1 "register_operand" " r"))
959 (match_operand:SI 2 "register_operand" " r"))))]
960 "TARGET_MUL && !TARGET_64BIT"
962 rtx temp = gen_reg_rtx (SImode);
963 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
964 emit_insn (gen_<su>mulsi3_highpart (riscv_subword (operands[0], true),
965 operands[1], operands[2]));
966 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
970 (define_insn "<su>mulsi3_highpart"
971 [(set (match_operand:SI 0 "register_operand" "=r")
974 (mult:DI (any_extend:DI
975 (match_operand:SI 1 "register_operand" " r"))
977 (match_operand:SI 2 "register_operand" " r")))
979 "TARGET_MUL && !TARGET_64BIT"
981 [(set_attr "type" "imul")
982 (set_attr "mode" "SI")])
985 (define_expand "usmulsidi3"
986 [(set (match_operand:DI 0 "register_operand" "=r")
987 (mult:DI (zero_extend:DI
988 (match_operand:SI 1 "register_operand" " r"))
990 (match_operand:SI 2 "register_operand" " r"))))]
991 "TARGET_MUL && !TARGET_64BIT"
993 rtx temp = gen_reg_rtx (SImode);
994 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
995 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true),
996 operands[1], operands[2]));
997 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
1001 (define_insn "usmulsi3_highpart"
1002 [(set (match_operand:SI 0 "register_operand" "=r")
1005 (mult:DI (zero_extend:DI
1006 (match_operand:SI 1 "register_operand" " r"))
1008 (match_operand:SI 2 "register_operand" " r")))
1010 "TARGET_MUL && !TARGET_64BIT"
1012 [(set_attr "type" "imul")
1013 (set_attr "mode" "SI")])
1016 ;; ....................
1018 ;; DIVISION and REMAINDER
1020 ;; ....................
1023 (define_insn "<optab>si3"
1024 [(set (match_operand:SI 0 "register_operand" "=r")
1025 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1026 (match_operand:SI 2 "register_operand" " r")))]
1028 { return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2"; }
1029 [(set_attr "type" "idiv")
1030 (set_attr "mode" "SI")])
1032 (define_insn "<optab>di3"
1033 [(set (match_operand:DI 0 "register_operand" "=r")
1034 (any_div:DI (match_operand:DI 1 "register_operand" " r")
1035 (match_operand:DI 2 "register_operand" " r")))]
1036 "TARGET_DIV && TARGET_64BIT"
1037 "<insn>%i2\t%0,%1,%2"
1038 [(set_attr "type" "idiv")
1039 (set_attr "mode" "DI")])
1041 (define_insn "*<optab>si3_extended"
1042 [(set (match_operand:DI 0 "register_operand" "=r")
1044 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1045 (match_operand:SI 2 "register_operand" " r"))))]
1046 "TARGET_DIV && TARGET_64BIT"
1047 "<insn>%i2w\t%0,%1,%2"
1048 [(set_attr "type" "idiv")
1049 (set_attr "mode" "DI")])
1051 (define_insn "div<mode>3"
1052 [(set (match_operand:ANYF 0 "register_operand" "=f")
1053 (div:ANYF (match_operand:ANYF 1 "register_operand" " f")
1054 (match_operand:ANYF 2 "register_operand" " f")))]
1055 "TARGET_HARD_FLOAT && TARGET_FDIV"
1056 "fdiv.<fmt>\t%0,%1,%2"
1057 [(set_attr "type" "fdiv")
1058 (set_attr "mode" "<UNITMODE>")])
1061 ;; ....................
1065 ;; ....................
1067 (define_insn "sqrt<mode>2"
1068 [(set (match_operand:ANYF 0 "register_operand" "=f")
1069 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
1070 "TARGET_HARD_FLOAT && TARGET_FDIV"
1072 return "fsqrt.<fmt>\t%0,%1";
1074 [(set_attr "type" "fsqrt")
1075 (set_attr "mode" "<UNITMODE>")])
1077 ;; Floating point multiply accumulate instructions.
1080 (define_insn "fma<mode>4"
1081 [(set (match_operand:ANYF 0 "register_operand" "=f")
1082 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
1083 (match_operand:ANYF 2 "register_operand" " f")
1084 (match_operand:ANYF 3 "register_operand" " f")))]
1086 "fmadd.<fmt>\t%0,%1,%2,%3"
1087 [(set_attr "type" "fmadd")
1088 (set_attr "mode" "<UNITMODE>")])
1091 (define_insn "fms<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 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
1097 "fmsub.<fmt>\t%0,%1,%2,%3"
1098 [(set_attr "type" "fmadd")
1099 (set_attr "mode" "<UNITMODE>")])
1102 (define_insn "fnms<mode>4"
1103 [(set (match_operand:ANYF 0 "register_operand" "=f")
1105 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1106 (match_operand:ANYF 2 "register_operand" " f")
1107 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
1109 "fnmadd.<fmt>\t%0,%1,%2,%3"
1110 [(set_attr "type" "fmadd")
1111 (set_attr "mode" "<UNITMODE>")])
1114 (define_insn "fnma<mode>4"
1115 [(set (match_operand:ANYF 0 "register_operand" "=f")
1117 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1118 (match_operand:ANYF 2 "register_operand" " f")
1119 (match_operand:ANYF 3 "register_operand" " f")))]
1121 "fnmsub.<fmt>\t%0,%1,%2,%3"
1122 [(set_attr "type" "fmadd")
1123 (set_attr "mode" "<UNITMODE>")])
1125 ;; -(-a * b - c), modulo signed zeros
1126 (define_insn "*fma<mode>4"
1127 [(set (match_operand:ANYF 0 "register_operand" "=f")
1130 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1131 (match_operand:ANYF 2 "register_operand" " f")
1132 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
1133 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1134 "fmadd.<fmt>\t%0,%1,%2,%3"
1135 [(set_attr "type" "fmadd")
1136 (set_attr "mode" "<UNITMODE>")])
1138 ;; -(-a * b + c), modulo signed zeros
1139 (define_insn "*fms<mode>4"
1140 [(set (match_operand:ANYF 0 "register_operand" "=f")
1143 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1144 (match_operand:ANYF 2 "register_operand" " f")
1145 (match_operand:ANYF 3 "register_operand" " f"))))]
1146 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1147 "fmsub.<fmt>\t%0,%1,%2,%3"
1148 [(set_attr "type" "fmadd")
1149 (set_attr "mode" "<UNITMODE>")])
1151 ;; -(a * b + c), modulo signed zeros
1152 (define_insn "*fnms<mode>4"
1153 [(set (match_operand:ANYF 0 "register_operand" "=f")
1156 (match_operand:ANYF 1 "register_operand" " f")
1157 (match_operand:ANYF 2 "register_operand" " f")
1158 (match_operand:ANYF 3 "register_operand" " f"))))]
1159 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1160 "fnmadd.<fmt>\t%0,%1,%2,%3"
1161 [(set_attr "type" "fmadd")
1162 (set_attr "mode" "<UNITMODE>")])
1164 ;; -(a * b - c), modulo signed zeros
1165 (define_insn "*fnma<mode>4"
1166 [(set (match_operand:ANYF 0 "register_operand" "=f")
1169 (match_operand:ANYF 1 "register_operand" " f")
1170 (match_operand:ANYF 2 "register_operand" " f")
1171 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
1172 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1173 "fnmsub.<fmt>\t%0,%1,%2,%3"
1174 [(set_attr "type" "fmadd")
1175 (set_attr "mode" "<UNITMODE>")])
1178 ;; ....................
1182 ;; ....................
1184 (define_insn "abs<mode>2"
1185 [(set (match_operand:ANYF 0 "register_operand" "=f")
1186 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
1189 [(set_attr "type" "fmove")
1190 (set_attr "mode" "<UNITMODE>")])
1192 (define_insn "copysign<mode>3"
1193 [(set (match_operand:ANYF 0 "register_operand" "=f")
1194 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")
1195 (match_operand:ANYF 2 "register_operand" " f")]
1198 "fsgnj.<fmt>\t%0,%1,%2"
1199 [(set_attr "type" "fmove")
1200 (set_attr "mode" "<UNITMODE>")])
1202 (define_insn "neg<mode>2"
1203 [(set (match_operand:ANYF 0 "register_operand" "=f")
1204 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
1207 [(set_attr "type" "fmove")
1208 (set_attr "mode" "<UNITMODE>")])
1211 ;; ....................
1215 ;; ....................
1217 (define_insn "smin<mode>3"
1218 [(set (match_operand:ANYF 0 "register_operand" "=f")
1219 (smin:ANYF (match_operand:ANYF 1 "register_operand" " f")
1220 (match_operand:ANYF 2 "register_operand" " f")))]
1222 "fmin.<fmt>\t%0,%1,%2"
1223 [(set_attr "type" "fmove")
1224 (set_attr "mode" "<UNITMODE>")])
1226 (define_insn "smax<mode>3"
1227 [(set (match_operand:ANYF 0 "register_operand" "=f")
1228 (smax:ANYF (match_operand:ANYF 1 "register_operand" " f")
1229 (match_operand:ANYF 2 "register_operand" " f")))]
1231 "fmax.<fmt>\t%0,%1,%2"
1232 [(set_attr "type" "fmove")
1233 (set_attr "mode" "<UNITMODE>")])
1236 ;; ....................
1240 ;; ....................
1243 ;; For RV64, we don't expose the SImode operations to the rtl expanders,
1244 ;; but SImode versions exist for combine.
1246 (define_insn "<optab><mode>3"
1247 [(set (match_operand:X 0 "register_operand" "=r,r")
1248 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
1249 (match_operand:X 2 "arith_operand" " r,I")))]
1251 "<insn>%i2\t%0,%1,%2"
1252 [(set_attr "type" "logical")
1253 (set_attr "mode" "<MODE>")])
1255 (define_insn "*<optab>si3_internal"
1256 [(set (match_operand:SI 0 "register_operand" "=r,r")
1257 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
1258 (match_operand:SI 2 "arith_operand" " r,I")))]
1260 "<insn>%i2\t%0,%1,%2"
1261 [(set_attr "type" "logical")
1262 (set_attr "mode" "SI")])
1264 (define_insn "one_cmpl<mode>2"
1265 [(set (match_operand:X 0 "register_operand" "=r")
1266 (not:X (match_operand:X 1 "register_operand" " r")))]
1269 [(set_attr "type" "logical")
1270 (set_attr "mode" "<MODE>")])
1272 (define_insn "*one_cmplsi2_internal"
1273 [(set (match_operand:SI 0 "register_operand" "=r")
1274 (not:SI (match_operand:SI 1 "register_operand" " r")))]
1277 [(set_attr "type" "logical")
1278 (set_attr "mode" "SI")])
1281 ;; ....................
1285 ;; ....................
1287 (define_insn "truncdfsf2"
1288 [(set (match_operand:SF 0 "register_operand" "=f")
1290 (match_operand:DF 1 "register_operand" " f")))]
1291 "TARGET_DOUBLE_FLOAT"
1293 [(set_attr "type" "fcvt")
1294 (set_attr "mode" "SF")])
1297 ;; ....................
1301 ;; ....................
1305 (define_expand "zero_extendsidi2"
1306 [(set (match_operand:DI 0 "register_operand")
1307 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
1310 (define_insn_and_split "*zero_extendsidi2_internal"
1311 [(set (match_operand:DI 0 "register_operand" "=r,r")
1313 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1314 "TARGET_64BIT && !(TARGET_ZBA || TARGET_ZBB)"
1318 "&& reload_completed
1319 && REG_P (operands[1])
1320 && !paradoxical_subreg_p (operands[0])"
1322 (ashift:DI (match_dup 1) (const_int 32)))
1324 (lshiftrt:DI (match_dup 0) (const_int 32)))]
1325 { operands[1] = gen_lowpart (DImode, operands[1]); }
1326 [(set_attr "move_type" "shift_shift,load")
1327 (set_attr "mode" "DI")])
1329 (define_expand "zero_extendhi<GPR:mode>2"
1330 [(set (match_operand:GPR 0 "register_operand")
1332 (match_operand:HI 1 "nonimmediate_operand")))]
1335 (define_insn_and_split "*zero_extendhi<GPR:mode>2"
1336 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1338 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
1343 "&& reload_completed
1344 && REG_P (operands[1])
1345 && !paradoxical_subreg_p (operands[0])"
1347 (ashift:GPR (match_dup 1) (match_dup 2)))
1349 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1351 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1352 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1354 [(set_attr "move_type" "shift_shift,load")
1355 (set_attr "mode" "<GPR:MODE>")])
1357 (define_insn "zero_extendqi<SUPERQI:mode>2"
1358 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1359 (zero_extend:SUPERQI
1360 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
1365 [(set_attr "move_type" "andi,load")
1366 (set_attr "mode" "<SUPERQI:MODE>")])
1369 ;; ....................
1373 ;; ....................
1375 (define_insn "extendsidi2"
1376 [(set (match_operand:DI 0 "register_operand" "=r,r")
1378 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1383 [(set_attr "move_type" "move,load")
1384 (set_attr "mode" "DI")])
1386 (define_expand "extend<SHORT:mode><SUPERQI:mode>2"
1387 [(set (match_operand:SUPERQI 0 "register_operand")
1388 (sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_operand")))]
1391 (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
1392 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1393 (sign_extend:SUPERQI
1394 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
1398 l<SHORT:size>\t%0,%1"
1399 "&& reload_completed
1400 && REG_P (operands[1])
1401 && !paradoxical_subreg_p (operands[0])"
1402 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1403 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
1405 operands[0] = gen_lowpart (SImode, operands[0]);
1406 operands[1] = gen_lowpart (SImode, operands[1]);
1407 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1408 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1410 [(set_attr "move_type" "shift_shift,load")
1411 (set_attr "mode" "SI")])
1413 (define_insn "extendsfdf2"
1414 [(set (match_operand:DF 0 "register_operand" "=f")
1416 (match_operand:SF 1 "register_operand" " f")))]
1417 "TARGET_DOUBLE_FLOAT"
1419 [(set_attr "type" "fcvt")
1420 (set_attr "mode" "DF")])
1423 ;; ....................
1427 ;; ....................
1429 (define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
1430 [(set (match_operand:GPR 0 "register_operand" "=r")
1432 (match_operand:ANYF 1 "register_operand" " f")))]
1434 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
1435 [(set_attr "type" "fcvt")
1436 (set_attr "mode" "<ANYF:MODE>")])
1438 (define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2"
1439 [(set (match_operand:GPR 0 "register_operand" "=r")
1441 (match_operand:ANYF 1 "register_operand" " f")))]
1443 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
1444 [(set_attr "type" "fcvt")
1445 (set_attr "mode" "<ANYF:MODE>")])
1447 (define_insn "float<GPR:mode><ANYF:mode>2"
1448 [(set (match_operand:ANYF 0 "register_operand" "= f")
1450 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
1452 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
1453 [(set_attr "type" "fcvt")
1454 (set_attr "mode" "<ANYF:MODE>")])
1456 (define_insn "floatuns<GPR:mode><ANYF:mode>2"
1457 [(set (match_operand:ANYF 0 "register_operand" "= f")
1458 (unsigned_float:ANYF
1459 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
1461 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
1462 [(set_attr "type" "fcvt")
1463 (set_attr "mode" "<ANYF:MODE>")])
1465 (define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2"
1466 [(set (match_operand:GPR 0 "register_operand" "=r")
1468 [(match_operand:ANYF 1 "register_operand" " f")]
1471 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
1472 [(set_attr "type" "fcvt")
1473 (set_attr "mode" "<ANYF:MODE>")])
1476 ;; ....................
1480 ;; ....................
1482 ;; Lower-level instructions for loading an address from the GOT.
1483 ;; We could use MEMs, but an unspec gives more optimization
1486 (define_insn "got_load<mode>"
1487 [(set (match_operand:P 0 "register_operand" "=r")
1489 [(match_operand:P 1 "symbolic_operand" "")]
1493 [(set_attr "got" "load")
1494 (set_attr "mode" "<MODE>")])
1496 (define_insn "tls_add_tp_le<mode>"
1497 [(set (match_operand:P 0 "register_operand" "=r")
1499 [(match_operand:P 1 "register_operand" "r")
1500 (match_operand:P 2 "register_operand" "r")
1501 (match_operand:P 3 "symbolic_operand" "")]
1504 "add\t%0,%1,%2,%%tprel_add(%3)"
1505 [(set_attr "type" "arith")
1506 (set_attr "mode" "<MODE>")])
1508 (define_insn "got_load_tls_gd<mode>"
1509 [(set (match_operand:P 0 "register_operand" "=r")
1511 [(match_operand:P 1 "symbolic_operand" "")]
1515 [(set_attr "got" "load")
1516 (set_attr "mode" "<MODE>")])
1518 (define_insn "got_load_tls_ie<mode>"
1519 [(set (match_operand:P 0 "register_operand" "=r")
1521 [(match_operand:P 1 "symbolic_operand" "")]
1525 [(set_attr "got" "load")
1526 (set_attr "mode" "<MODE>")])
1528 (define_insn "auipc<mode>"
1529 [(set (match_operand:P 0 "register_operand" "=r")
1531 [(match_operand:P 1 "symbolic_operand" "")
1532 (match_operand:P 2 "const_int_operand")
1536 ".LA%2: auipc\t%0,%h1"
1537 [(set_attr "type" "auipc")
1538 (set_attr "cannot_copy" "yes")])
1540 ;; Instructions for adding the low 12 bits of an address to a register.
1541 ;; Operand 2 is the address: riscv_print_operand works out which relocation
1542 ;; should be applied.
1544 (define_insn "*low<mode>"
1545 [(set (match_operand:P 0 "register_operand" "=r")
1546 (lo_sum:P (match_operand:P 1 "register_operand" " r")
1547 (match_operand:P 2 "symbolic_operand" "")))]
1550 [(set_attr "type" "arith")
1551 (set_attr "mode" "<MODE>")])
1553 ;; Allow combine to split complex const_int load sequences, using operand 2
1554 ;; to store the intermediate results. See move_operand for details.
1556 [(set (match_operand:GPR 0 "register_operand")
1557 (match_operand:GPR 1 "splittable_const_int_operand"))
1558 (clobber (match_operand:GPR 2 "register_operand"))]
1562 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
1563 <GPR:MODE>mode, TRUE);
1567 ;; Likewise, for symbolic operands.
1569 [(set (match_operand:P 0 "register_operand")
1570 (match_operand:P 1))
1571 (clobber (match_operand:P 2 "register_operand"))]
1572 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL, TRUE)"
1573 [(set (match_dup 0) (match_dup 3))]
1575 riscv_split_symbol (operands[2], operands[1],
1576 MAX_MACHINE_MODE, &operands[3], TRUE);
1579 ;; 64-bit integer moves
1581 (define_expand "movdi"
1582 [(set (match_operand:DI 0 "")
1583 (match_operand:DI 1 ""))]
1586 if (riscv_legitimize_move (DImode, operands[0], operands[1]))
1590 (define_insn "*movdi_32bit"
1591 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m")
1592 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))]
1594 && (register_operand (operands[0], DImode)
1595 || reg_or_0_operand (operands[1], DImode))"
1596 { return riscv_output_move (operands[0], operands[1]); }
1597 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1598 (set_attr "mode" "DI")])
1600 (define_insn "*movdi_64bit"
1601 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m")
1602 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))]
1604 && (register_operand (operands[0], DImode)
1605 || reg_or_0_operand (operands[1], DImode))"
1606 { return riscv_output_move (operands[0], operands[1]); }
1607 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1608 (set_attr "mode" "DI")])
1610 ;; 32-bit Integer moves
1612 (define_expand "mov<mode>"
1613 [(set (match_operand:MOVE32 0 "")
1614 (match_operand:MOVE32 1 ""))]
1617 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
1621 (define_insn "*movsi_internal"
1622 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m")
1623 (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f"))]
1624 "(register_operand (operands[0], SImode)
1625 || reg_or_0_operand (operands[1], SImode))"
1626 { return riscv_output_move (operands[0], operands[1]); }
1627 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
1628 (set_attr "mode" "SI")])
1630 ;; 16-bit Integer moves
1632 ;; Unlike most other insns, the move insns can't be split with
1633 ;; different predicates, because register spilling and other parts of
1634 ;; the compiler, have memoized the insn number already.
1635 ;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
1637 (define_expand "movhi"
1638 [(set (match_operand:HI 0 "")
1639 (match_operand:HI 1 ""))]
1642 if (riscv_legitimize_move (HImode, operands[0], operands[1]))
1646 (define_insn "*movhi_internal"
1647 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1648 (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f"))]
1649 "(register_operand (operands[0], HImode)
1650 || reg_or_0_operand (operands[1], HImode))"
1651 { return riscv_output_move (operands[0], operands[1]); }
1652 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1653 (set_attr "mode" "HI")])
1655 ;; HImode constant generation; see riscv_move_integer for details.
1656 ;; si+si->hi without truncation is legal because of
1657 ;; TARGET_TRULY_NOOP_TRUNCATION.
1659 (define_insn "*add<mode>hi3"
1660 [(set (match_operand:HI 0 "register_operand" "=r,r")
1661 (plus:HI (match_operand:HISI 1 "register_operand" " r,r")
1662 (match_operand:HISI 2 "arith_operand" " r,I")))]
1664 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
1665 [(set_attr "type" "arith")
1666 (set_attr "mode" "HI")])
1668 (define_insn "*xor<mode>hi3"
1669 [(set (match_operand:HI 0 "register_operand" "=r,r")
1670 (xor:HI (match_operand:HISI 1 "register_operand" " r,r")
1671 (match_operand:HISI 2 "arith_operand" " r,I")))]
1674 [(set_attr "type" "logical")
1675 (set_attr "mode" "HI")])
1677 ;; 8-bit Integer moves
1679 (define_expand "movqi"
1680 [(set (match_operand:QI 0 "")
1681 (match_operand:QI 1 ""))]
1684 if (riscv_legitimize_move (QImode, operands[0], operands[1]))
1688 (define_insn "*movqi_internal"
1689 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1690 (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f"))]
1691 "(register_operand (operands[0], QImode)
1692 || reg_or_0_operand (operands[1], QImode))"
1693 { return riscv_output_move (operands[0], operands[1]); }
1694 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1695 (set_attr "mode" "QI")])
1697 ;; 32-bit floating point moves
1699 (define_expand "movsf"
1700 [(set (match_operand:SF 0 "")
1701 (match_operand:SF 1 ""))]
1704 if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
1708 (define_insn "*movsf_hardfloat"
1709 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1710 (match_operand:SF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
1712 && (register_operand (operands[0], SFmode)
1713 || reg_or_0_operand (operands[1], SFmode))"
1714 { return riscv_output_move (operands[0], operands[1]); }
1715 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1716 (set_attr "mode" "SF")])
1718 (define_insn "*movsf_softfloat"
1719 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
1720 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
1722 && (register_operand (operands[0], SFmode)
1723 || reg_or_0_operand (operands[1], SFmode))"
1724 { return riscv_output_move (operands[0], operands[1]); }
1725 [(set_attr "move_type" "move,load,store")
1726 (set_attr "mode" "SF")])
1728 ;; 64-bit floating point moves
1730 (define_expand "movdf"
1731 [(set (match_operand:DF 0 "")
1732 (match_operand:DF 1 ""))]
1735 if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
1739 ;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
1740 ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
1741 (define_insn "*movdf_hardfloat_rv32"
1742 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m")
1743 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))]
1744 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
1745 && (register_operand (operands[0], DFmode)
1746 || reg_or_0_operand (operands[1], DFmode))"
1747 { return riscv_output_move (operands[0], operands[1]); }
1748 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store")
1749 (set_attr "mode" "DF")])
1751 (define_insn "*movdf_hardfloat_rv64"
1752 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1753 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
1754 "TARGET_64BIT && TARGET_DOUBLE_FLOAT
1755 && (register_operand (operands[0], DFmode)
1756 || reg_or_0_operand (operands[1], DFmode))"
1757 { return riscv_output_move (operands[0], operands[1]); }
1758 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1759 (set_attr "mode" "DF")])
1761 (define_insn "*movdf_softfloat"
1762 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
1763 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
1764 "!TARGET_DOUBLE_FLOAT
1765 && (register_operand (operands[0], DFmode)
1766 || reg_or_0_operand (operands[1], DFmode))"
1767 { return riscv_output_move (operands[0], operands[1]); }
1768 [(set_attr "move_type" "move,load,store")
1769 (set_attr "mode" "DF")])
1772 [(set (match_operand:MOVE64 0 "nonimmediate_operand")
1773 (match_operand:MOVE64 1 "move_operand"))]
1775 && riscv_split_64bit_move_p (operands[0], operands[1])"
1778 riscv_split_doubleword_move (operands[0], operands[1]);
1782 (define_expand "cpymemsi"
1783 [(parallel [(set (match_operand:BLK 0 "general_operand")
1784 (match_operand:BLK 1 "general_operand"))
1785 (use (match_operand:SI 2 ""))
1786 (use (match_operand:SI 3 "const_int_operand"))])]
1789 if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
1795 ;; Expand in-line code to clear the instruction cache between operand[0] and
1797 (define_expand "clear_cache"
1798 [(match_operand 0 "pmode_register_operand")
1799 (match_operand 1 "pmode_register_operand")]
1802 #ifdef ICACHE_FLUSH_FUNC
1803 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC),
1804 LCT_NORMAL, VOIDmode, operands[0], Pmode,
1805 operands[1], Pmode, const0_rtx, Pmode);
1807 if (TARGET_ZIFENCEI)
1808 emit_insn (gen_fence_i ());
1813 (define_insn "fence"
1814 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
1818 (define_insn "fence_i"
1819 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
1824 ;; ....................
1828 ;; ....................
1830 ;; Use a QImode shift count, to avoid generating sign or zero extend
1831 ;; instructions for shift counts, and to avoid dropping subregs.
1832 ;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
1833 ;; defined, but use of that is discouraged.
1835 (define_insn "<optab>si3"
1836 [(set (match_operand:SI 0 "register_operand" "= r")
1838 (match_operand:SI 1 "register_operand" " r")
1839 (match_operand:QI 2 "arith_operand" " rI")))]
1842 if (GET_CODE (operands[2]) == CONST_INT)
1843 operands[2] = GEN_INT (INTVAL (operands[2])
1844 & (GET_MODE_BITSIZE (SImode) - 1));
1846 return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2";
1848 [(set_attr "type" "shift")
1849 (set_attr "mode" "SI")])
1851 (define_insn_and_split "*<optab>si3_mask"
1852 [(set (match_operand:SI 0 "register_operand" "= r")
1854 (match_operand:SI 1 "register_operand" " r")
1855 (match_operator 4 "subreg_lowpart_operator"
1857 (match_operand:SI 2 "register_operand" "r")
1858 (match_operand 3 "const_int_operand"))])))]
1859 "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1860 == GET_MODE_BITSIZE (SImode)-1"
1864 (any_shift:SI (match_dup 1)
1866 "operands[2] = gen_lowpart (QImode, operands[2]);"
1867 [(set_attr "type" "shift")
1868 (set_attr "mode" "SI")])
1870 (define_insn_and_split "*<optab>si3_mask_1"
1871 [(set (match_operand:SI 0 "register_operand" "= r")
1873 (match_operand:SI 1 "register_operand" " r")
1874 (match_operator 4 "subreg_lowpart_operator"
1876 (match_operand:DI 2 "register_operand" "r")
1877 (match_operand 3 "const_int_operand"))])))]
1879 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1880 == GET_MODE_BITSIZE (SImode)-1"
1884 (any_shift:SI (match_dup 1)
1886 "operands[2] = gen_lowpart (QImode, operands[2]);"
1887 [(set_attr "type" "shift")
1888 (set_attr "mode" "SI")])
1890 (define_insn "<optab>di3"
1891 [(set (match_operand:DI 0 "register_operand" "= r")
1893 (match_operand:DI 1 "register_operand" " r")
1894 (match_operand:QI 2 "arith_operand" " rI")))]
1897 if (GET_CODE (operands[2]) == CONST_INT)
1898 operands[2] = GEN_INT (INTVAL (operands[2])
1899 & (GET_MODE_BITSIZE (DImode) - 1));
1901 return "<insn>%i2\t%0,%1,%2";
1903 [(set_attr "type" "shift")
1904 (set_attr "mode" "DI")])
1906 (define_insn_and_split "*<optab>di3_mask"
1907 [(set (match_operand:DI 0 "register_operand" "= r")
1909 (match_operand:DI 1 "register_operand" " r")
1910 (match_operator 4 "subreg_lowpart_operator"
1912 (match_operand:SI 2 "register_operand" "r")
1913 (match_operand 3 "const_int_operand"))])))]
1915 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1916 == GET_MODE_BITSIZE (DImode)-1"
1920 (any_shift:DI (match_dup 1)
1922 "operands[2] = gen_lowpart (QImode, operands[2]);"
1923 [(set_attr "type" "shift")
1924 (set_attr "mode" "DI")])
1926 (define_insn_and_split "*<optab>di3_mask_1"
1927 [(set (match_operand:DI 0 "register_operand" "= r")
1929 (match_operand:DI 1 "register_operand" " r")
1930 (match_operator 4 "subreg_lowpart_operator"
1932 (match_operand:DI 2 "register_operand" "r")
1933 (match_operand 3 "const_int_operand"))])))]
1935 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1936 == GET_MODE_BITSIZE (DImode)-1"
1940 (any_shift:DI (match_dup 1)
1942 "operands[2] = gen_lowpart (QImode, operands[2]);"
1943 [(set_attr "type" "shift")
1944 (set_attr "mode" "DI")])
1946 (define_insn "*<optab>si3_extend"
1947 [(set (match_operand:DI 0 "register_operand" "= r")
1949 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
1950 (match_operand:QI 2 "arith_operand" " rI"))))]
1953 if (GET_CODE (operands[2]) == CONST_INT)
1954 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1956 return "<insn>%i2w\t%0,%1,%2";
1958 [(set_attr "type" "shift")
1959 (set_attr "mode" "SI")])
1961 (define_insn_and_split "*<optab>si3_extend_mask"
1962 [(set (match_operand:DI 0 "register_operand" "= r")
1965 (match_operand:SI 1 "register_operand" " r")
1966 (match_operator 4 "subreg_lowpart_operator"
1968 (match_operand:SI 2 "register_operand" " r")
1969 (match_operand 3 "const_int_operand"))]))))]
1971 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1972 == GET_MODE_BITSIZE (SImode)-1"
1977 (any_shift:SI (match_dup 1)
1979 "operands[2] = gen_lowpart (QImode, operands[2]);"
1980 [(set_attr "type" "shift")
1981 (set_attr "mode" "SI")])
1983 (define_insn_and_split "*<optab>si3_extend_mask_1"
1984 [(set (match_operand:DI 0 "register_operand" "= r")
1987 (match_operand:SI 1 "register_operand" " r")
1988 (match_operator 4 "subreg_lowpart_operator"
1990 (match_operand:DI 2 "register_operand" " r")
1991 (match_operand 3 "const_int_operand"))]))))]
1993 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1994 == GET_MODE_BITSIZE (SImode)-1"
1999 (any_shift:SI (match_dup 1)
2001 "operands[2] = gen_lowpart (QImode, operands[2]);"
2002 [(set_attr "type" "shift")
2003 (set_attr "mode" "SI")])
2005 ;; Non-canonical, but can be formed by ree when combine is not successful at
2006 ;; producing one of the two canonical patterns below.
2007 (define_insn "*lshrsi3_zero_extend_1"
2008 [(set (match_operand:DI 0 "register_operand" "=r")
2010 (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
2011 (match_operand 2 "const_int_operand"))))]
2012 "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
2014 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
2016 return "srliw\t%0,%1,%2";
2018 [(set_attr "type" "shift")
2019 (set_attr "mode" "SI")])
2021 ;; Canonical form for a zero-extend of a logical right shift.
2022 (define_insn "*lshrsi3_zero_extend_2"
2023 [(set (match_operand:DI 0 "register_operand" "=r")
2024 (zero_extract:DI (match_operand:DI 1 "register_operand" " r")
2025 (match_operand 2 "const_int_operand")
2026 (match_operand 3 "const_int_operand")))]
2027 "(TARGET_64BIT && (INTVAL (operands[3]) > 0)
2028 && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
2030 return "srliw\t%0,%1,%3";
2032 [(set_attr "type" "shift")
2033 (set_attr "mode" "SI")])
2035 ;; Canonical form for a zero-extend of a logical right shift when the
2036 ;; shift count is 31.
2037 (define_insn "*lshrsi3_zero_extend_3"
2038 [(set (match_operand:DI 0 "register_operand" "=r")
2039 (lt:DI (match_operand:SI 1 "register_operand" " r")
2043 return "srliw\t%0,%1,31";
2045 [(set_attr "type" "shift")
2046 (set_attr "mode" "SI")])
2048 ;; Handle AND with 2^N-1 for N from 12 to XLEN. This can be split into
2049 ;; two logical shifts. Otherwise it requires 3 instructions: lui,
2050 ;; xor/addi/srli, and.
2052 ;; Generating a temporary for the shift output gives better combiner results;
2053 ;; and also fixes a problem where op0 could be a paradoxical reg and shifting
2054 ;; by amounts larger than the size of the SUBREG_REG doesn't work.
2056 [(set (match_operand:GPR 0 "register_operand")
2057 (and:GPR (match_operand:GPR 1 "register_operand")
2058 (match_operand:GPR 2 "p2m1_shift_operand")))
2059 (clobber (match_operand:GPR 3 "register_operand"))]
2062 (ashift:GPR (match_dup 1) (match_dup 2)))
2064 (lshiftrt:GPR (match_dup 3) (match_dup 2)))]
2066 /* Op2 is a VOIDmode constant, so get the mode size from op1. */
2067 operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1]))
2068 - exact_log2 (INTVAL (operands[2]) + 1));
2071 ;; Handle AND with 0xF...F0...0 where there are 32 to 63 zeros. This can be
2072 ;; split into two shifts. Otherwise it requires 3 instructions: li, sll, and.
2074 [(set (match_operand:DI 0 "register_operand")
2075 (and:DI (match_operand:DI 1 "register_operand")
2076 (match_operand:DI 2 "high_mask_shift_operand")))
2077 (clobber (match_operand:DI 3 "register_operand"))]
2080 (lshiftrt:DI (match_dup 1) (match_dup 2)))
2082 (ashift:DI (match_dup 3) (match_dup 2)))]
2084 operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2])));
2087 ;; Handle SImode to DImode zero-extend combined with a left shift. This can
2088 ;; occur when unsigned int is used for array indexing. Split this into two
2089 ;; shifts. Otherwise we can get 3 shifts.
2091 (define_insn_and_split "zero_extendsidi2_shifted"
2092 [(set (match_operand:DI 0 "register_operand" "=r")
2093 (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
2094 (match_operand:QI 2 "immediate_operand" "I"))
2095 (match_operand 3 "immediate_operand" "")))
2096 (clobber (match_scratch:DI 4 "=&r"))]
2097 "TARGET_64BIT && !TARGET_ZBA
2098 && ((INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff)"
2100 "&& reload_completed"
2102 (ashift:DI (match_dup 1) (const_int 32)))
2104 (lshiftrt:DI (match_dup 4) (match_dup 5)))]
2105 "operands[5] = GEN_INT (32 - (INTVAL (operands [2])));"
2106 [(set_attr "type" "shift")
2107 (set_attr "mode" "DI")])
2110 ;; ....................
2112 ;; CONDITIONAL BRANCHES
2114 ;; ....................
2116 ;; Conditional branches
2118 (define_insn "*branch<mode>"
2121 (match_operator 1 "order_operator"
2122 [(match_operand:X 2 "register_operand" "r")
2123 (match_operand:X 3 "reg_or_0_operand" "rJ")])
2124 (label_ref (match_operand 0 "" ""))
2128 [(set_attr "type" "branch")
2129 (set_attr "mode" "none")])
2131 ;; Patterns for implementations that optimize short forward branches.
2133 (define_expand "mov<mode>cc"
2134 [(set (match_operand:GPR 0 "register_operand")
2135 (if_then_else:GPR (match_operand 1 "comparison_operator")
2136 (match_operand:GPR 2 "register_operand")
2137 (match_operand:GPR 3 "sfb_alu_operand")))]
2140 rtx cmp = operands[1];
2141 /* We only handle word mode integer compares for now. */
2142 if (GET_MODE (XEXP (cmp, 0)) != word_mode)
2144 riscv_expand_conditional_move (operands[0], operands[2], operands[3],
2145 GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
2149 (define_insn "*mov<GPR:mode><X:mode>cc"
2150 [(set (match_operand:GPR 0 "register_operand" "=r,r")
2152 (match_operator 5 "order_operator"
2153 [(match_operand:X 1 "register_operand" "r,r")
2154 (match_operand:X 2 "reg_or_0_operand" "rJ,rJ")])
2155 (match_operand:GPR 3 "register_operand" "0,0")
2156 (match_operand:GPR 4 "sfb_alu_operand" "rJ,IL")))]
2159 b%C5 %1,%z2,1f; mv %0,%z4; 1: # movcc
2160 b%C5 %1,%z2,1f; li %0,%4; 1: # movcc"
2161 [(set_attr "length" "8")
2162 (set_attr "type" "sfb_alu")
2163 (set_attr "mode" "<GPR:MODE>")])
2165 ;; Used to implement built-in functions.
2166 (define_expand "condjump"
2168 (if_then_else (match_operand 0)
2169 (label_ref (match_operand 1))
2172 (define_expand "@cbranch<mode>4"
2174 (if_then_else (match_operator 0 "comparison_operator"
2175 [(match_operand:BR 1 "register_operand")
2176 (match_operand:BR 2 "nonmemory_operand")])
2177 (label_ref (match_operand 3 ""))
2181 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2182 operands[1], operands[2]);
2186 (define_expand "@cbranch<mode>4"
2188 (if_then_else (match_operator 0 "fp_branch_comparison"
2189 [(match_operand:ANYF 1 "register_operand")
2190 (match_operand:ANYF 2 "register_operand")])
2191 (label_ref (match_operand 3 ""))
2195 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2196 operands[1], operands[2]);
2200 (define_insn_and_split "*branch_on_bit<X:mode>"
2203 (match_operator 0 "equality_operator"
2204 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2206 (match_operand 3 "branch_on_bit_operand"))
2208 (label_ref (match_operand 1))
2210 (clobber (match_scratch:X 4 "=&r"))]
2215 (ashift:X (match_dup 2) (match_dup 3)))
2218 (match_op_dup 0 [(match_dup 4) (const_int 0)])
2219 (label_ref (match_operand 1))
2222 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
2223 operands[3] = GEN_INT (shift);
2225 if (GET_CODE (operands[0]) == EQ)
2226 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
2228 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
2231 (define_insn_and_split "*branch_on_bit_range<X:mode>"
2234 (match_operator 0 "equality_operator"
2235 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2236 (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 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
2257 ;; ....................
2259 ;; SETTING A REGISTER FROM A COMPARISON
2261 ;; ....................
2263 ;; Destination is always set in SI mode.
2265 (define_expand "cstore<mode>4"
2266 [(set (match_operand:SI 0 "register_operand")
2267 (match_operator:SI 1 "order_operator"
2268 [(match_operand:GPR 2 "register_operand")
2269 (match_operand:GPR 3 "nonmemory_operand")]))]
2272 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
2277 (define_expand "cstore<mode>4"
2278 [(set (match_operand:SI 0 "register_operand")
2279 (match_operator:SI 1 "fp_scc_comparison"
2280 [(match_operand:ANYF 2 "register_operand")
2281 (match_operand:ANYF 3 "register_operand")]))]
2284 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
2289 (define_insn "*cstore<ANYF:mode><X:mode>4"
2290 [(set (match_operand:X 0 "register_operand" "=r")
2291 (match_operator:X 1 "fp_native_comparison"
2292 [(match_operand:ANYF 2 "register_operand" " f")
2293 (match_operand:ANYF 3 "register_operand" " f")]))]
2295 "f%C1.<fmt>\t%0,%2,%3"
2296 [(set_attr "type" "fcmp")
2297 (set_attr "mode" "<UNITMODE>")])
2299 (define_expand "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
2300 [(parallel [(set (match_operand:X 0 "register_operand")
2302 [(match_operand:ANYF 1 "register_operand")
2303 (match_operand:ANYF 2 "register_operand")]
2305 (clobber (match_scratch:X 3))])]
2306 "TARGET_HARD_FLOAT")
2308 (define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_default"
2309 [(set (match_operand:X 0 "register_operand" "=r")
2311 [(match_operand:ANYF 1 "register_operand" " f")
2312 (match_operand:ANYF 2 "register_operand" " f")]
2314 (clobber (match_scratch:X 3 "=&r"))]
2315 "TARGET_HARD_FLOAT && ! HONOR_SNANS (<ANYF:MODE>mode)"
2316 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3"
2317 [(set_attr "type" "fcmp")
2318 (set_attr "mode" "<UNITMODE>")
2319 (set (attr "length") (const_int 12))])
2321 (define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_snan"
2322 [(set (match_operand:X 0 "register_operand" "=r")
2324 [(match_operand:ANYF 1 "register_operand" " f")
2325 (match_operand:ANYF 2 "register_operand" " f")]
2327 (clobber (match_scratch:X 3 "=&r"))]
2328 "TARGET_HARD_FLOAT && HONOR_SNANS (<ANYF:MODE>mode)"
2329 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3\n\tfeq.<fmt>\tzero,%1,%2"
2330 [(set_attr "type" "fcmp")
2331 (set_attr "mode" "<UNITMODE>")
2332 (set (attr "length") (const_int 16))])
2334 (define_insn "*seq_zero_<X:mode><GPR:mode>"
2335 [(set (match_operand:GPR 0 "register_operand" "=r")
2336 (eq:GPR (match_operand:X 1 "register_operand" " r")
2340 [(set_attr "type" "slt")
2341 (set_attr "mode" "<X:MODE>")])
2343 (define_insn "*sne_zero_<X:mode><GPR:mode>"
2344 [(set (match_operand:GPR 0 "register_operand" "=r")
2345 (ne:GPR (match_operand:X 1 "register_operand" " r")
2349 [(set_attr "type" "slt")
2350 (set_attr "mode" "<X:MODE>")])
2352 (define_insn "*sgt<u>_<X:mode><GPR:mode>"
2353 [(set (match_operand:GPR 0 "register_operand" "= r")
2354 (any_gt:GPR (match_operand:X 1 "register_operand" " r")
2355 (match_operand:X 2 "reg_or_0_operand" " rJ")))]
2358 [(set_attr "type" "slt")
2359 (set_attr "mode" "<X:MODE>")])
2361 (define_insn "*sge<u>_<X:mode><GPR:mode>"
2362 [(set (match_operand:GPR 0 "register_operand" "=r")
2363 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
2366 "slt%i2<u>\t%0,zero,%1"
2367 [(set_attr "type" "slt")
2368 (set_attr "mode" "<X:MODE>")])
2370 (define_insn "*slt<u>_<X:mode><GPR:mode>"
2371 [(set (match_operand:GPR 0 "register_operand" "= r")
2372 (any_lt:GPR (match_operand:X 1 "register_operand" " r")
2373 (match_operand:X 2 "arith_operand" " rI")))]
2375 "slt%i2<u>\t%0,%1,%2"
2376 [(set_attr "type" "slt")
2377 (set_attr "mode" "<X:MODE>")])
2379 (define_insn "*sle<u>_<X:mode><GPR:mode>"
2380 [(set (match_operand:GPR 0 "register_operand" "=r")
2381 (any_le:GPR (match_operand:X 1 "register_operand" " r")
2382 (match_operand:X 2 "sle_operand" "")))]
2385 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
2386 return "slt%i2<u>\t%0,%1,%2";
2388 [(set_attr "type" "slt")
2389 (set_attr "mode" "<X:MODE>")])
2392 ;; ....................
2394 ;; UNCONDITIONAL BRANCHES
2396 ;; ....................
2398 ;; Unconditional branches.
2402 (label_ref (match_operand 0 "" "")))]
2405 [(set_attr "type" "jump")
2406 (set_attr "mode" "none")])
2408 (define_expand "indirect_jump"
2409 [(set (pc) (match_operand 0 "register_operand"))]
2412 operands[0] = force_reg (Pmode, operands[0]);
2413 if (Pmode == SImode)
2414 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
2416 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
2420 (define_insn "indirect_jump<mode>"
2421 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
2424 [(set_attr "type" "jump")
2425 (set_attr "mode" "none")])
2427 (define_expand "tablejump"
2428 [(set (pc) (match_operand 0 "register_operand" ""))
2429 (use (label_ref (match_operand 1 "" "")))]
2432 if (CASE_VECTOR_PC_RELATIVE)
2433 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
2434 gen_rtx_LABEL_REF (Pmode, operands[1]),
2435 NULL_RTX, 0, OPTAB_DIRECT);
2437 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
2438 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
2440 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
2444 (define_insn "tablejump<mode>"
2445 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
2446 (use (label_ref (match_operand 1 "" "")))]
2449 [(set_attr "type" "jump")
2450 (set_attr "mode" "none")])
2453 ;; ....................
2455 ;; Function prologue/epilogue
2457 ;; ....................
2460 (define_expand "prologue"
2464 riscv_expand_prologue ();
2468 ;; Block any insns from being moved before this point, since the
2469 ;; profiling call to mcount can use various registers that aren't
2470 ;; saved or used to pass arguments.
2472 (define_insn "blockage"
2473 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
2476 [(set_attr "type" "ghost")
2477 (set_attr "mode" "none")])
2479 (define_expand "epilogue"
2483 riscv_expand_epilogue (NORMAL_RETURN);
2487 (define_expand "sibcall_epilogue"
2491 riscv_expand_epilogue (SIBCALL_RETURN);
2495 ;; Trivial return. Make it look like a normal return insn as that
2496 ;; allows jump optimizations to work better.
2498 (define_expand "return"
2500 "riscv_can_use_return_insn ()"
2503 (define_insn "simple_return"
2507 return riscv_output_return ();
2509 [(set_attr "type" "jump")
2510 (set_attr "mode" "none")])
2514 (define_insn "simple_return_internal"
2516 (use (match_operand 0 "pmode_register_operand" ""))]
2519 [(set_attr "type" "jump")
2520 (set_attr "mode" "none")])
2522 ;; This is used in compiling the unwind routines.
2523 (define_expand "eh_return"
2524 [(use (match_operand 0 "general_operand"))]
2527 if (GET_MODE (operands[0]) != word_mode)
2528 operands[0] = convert_to_mode (word_mode, operands[0], 0);
2530 emit_insn (gen_eh_set_lr_di (operands[0]));
2532 emit_insn (gen_eh_set_lr_si (operands[0]));
2534 emit_jump_insn (gen_eh_return_internal ());
2539 ;; Clobber the return address on the stack. We can't expand this
2540 ;; until we know where it will be put in the stack frame.
2542 (define_insn "eh_set_lr_si"
2543 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2544 (clobber (match_scratch:SI 1 "=&r"))]
2548 (define_insn "eh_set_lr_di"
2549 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2550 (clobber (match_scratch:DI 1 "=&r"))]
2555 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
2556 (clobber (match_scratch 1))]
2560 riscv_set_return_address (operands[0], operands[1]);
2564 (define_insn_and_split "eh_return_internal"
2568 "epilogue_completed"
2570 "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
2573 ;; ....................
2577 ;; ....................
2579 (define_expand "sibcall"
2580 [(parallel [(call (match_operand 0 "")
2581 (match_operand 1 ""))
2582 (use (match_operand 2 "")) ;; next_arg_reg
2583 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2586 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2587 emit_call_insn (gen_sibcall_internal (target, operands[1]));
2591 (define_insn "sibcall_internal"
2592 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
2593 (match_operand 1 "" ""))]
2594 "SIBLING_CALL_P (insn)"
2599 [(set_attr "type" "call")])
2601 (define_expand "sibcall_value"
2602 [(parallel [(set (match_operand 0 "")
2603 (call (match_operand 1 "")
2604 (match_operand 2 "")))
2605 (use (match_operand 3 ""))])] ;; next_arg_reg
2608 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2609 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
2613 (define_insn "sibcall_value_internal"
2614 [(set (match_operand 0 "" "")
2615 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
2616 (match_operand 2 "" "")))]
2617 "SIBLING_CALL_P (insn)"
2622 [(set_attr "type" "call")])
2624 (define_expand "call"
2625 [(parallel [(call (match_operand 0 "")
2626 (match_operand 1 ""))
2627 (use (match_operand 2 "")) ;; next_arg_reg
2628 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2631 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2632 emit_call_insn (gen_call_internal (target, operands[1]));
2636 (define_insn "call_internal"
2637 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
2638 (match_operand 1 "" ""))
2639 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2645 [(set_attr "type" "call")])
2647 (define_expand "call_value"
2648 [(parallel [(set (match_operand 0 "")
2649 (call (match_operand 1 "")
2650 (match_operand 2 "")))
2651 (use (match_operand 3 ""))])] ;; next_arg_reg
2654 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2655 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
2659 (define_insn "call_value_internal"
2660 [(set (match_operand 0 "" "")
2661 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
2662 (match_operand 2 "" "")))
2663 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2669 [(set_attr "type" "call")])
2671 ;; Call subroutine returning any type.
2673 (define_expand "untyped_call"
2674 [(parallel [(call (match_operand 0 "")
2676 (match_operand 1 "")
2677 (match_operand 2 "")])]
2682 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2684 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2686 rtx set = XVECEXP (operands[2], 0, i);
2687 riscv_emit_move (SET_DEST (set), SET_SRC (set));
2690 emit_insn (gen_blockage ());
2698 [(set_attr "type" "nop")
2699 (set_attr "mode" "none")])
2702 [(trap_if (const_int 1) (const_int 0))]
2706 ;; Must use the registers that we save to prevent the rename reg optimization
2707 ;; pass from using them before the gpr_save pattern when shrink wrapping
2708 ;; occurs. See bug 95252 for instance.
2710 (define_insn "gpr_save"
2711 [(match_parallel 1 "gpr_save_operation"
2712 [(unspec_volatile [(match_operand 0 "const_int_operand")]
2713 UNSPECV_GPR_SAVE)])]
2715 "call\tt0,__riscv_save_%0")
2717 (define_insn "gpr_restore"
2718 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2720 "tail\t__riscv_restore_%0")
2722 (define_insn "gpr_restore_return"
2724 (use (match_operand 0 "pmode_register_operand" ""))
2729 (define_insn "riscv_frflags"
2730 [(set (match_operand:SI 0 "register_operand" "=r")
2731 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
2735 (define_insn "riscv_fsflags"
2736 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2740 (define_insn "riscv_mret"
2742 (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
2746 (define_insn "riscv_sret"
2748 (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
2752 (define_insn "riscv_uret"
2754 (unspec_volatile [(const_int 0)] UNSPECV_URET)]
2758 (define_insn "stack_tie<mode>"
2759 [(set (mem:BLK (scratch))
2760 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
2761 (match_operand:X 1 "register_operand" "r")]
2765 [(set_attr "length" "0")]
2768 ;; This fixes a failure with gcc.c-torture/execute/pr64242.c at -O2 for a
2769 ;; 32-bit target when using -mtune=sifive-7-series. The first sched pass
2770 ;; runs before register elimination, and we have a non-obvious dependency
2771 ;; between a use of the soft fp and a set of the hard fp. We fix this by
2772 ;; emitting a clobber using the hard fp between the two insns.
2773 (define_expand "restore_stack_nonlocal"
2774 [(match_operand 0 "register_operand")
2775 (match_operand 1 "memory_operand")]
2778 emit_move_insn (operands[0], operands[1]);
2779 /* Prevent the following hard fp restore from being moved before the move
2780 insn above which uses a copy of the soft fp reg. */
2781 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2785 ;; Named pattern for expanding thread pointer reference.
2786 (define_expand "get_thread_pointer<mode>"
2787 [(set (match_operand:P 0 "register_operand" "=r")
2792 ;; Named patterns for stack smashing protection.
2794 (define_expand "stack_protect_set"
2795 [(match_operand 0 "memory_operand")
2796 (match_operand 1 "memory_operand")]
2799 machine_mode mode = GET_MODE (operands[0]);
2800 if (riscv_stack_protector_guard == SSP_TLS)
2802 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
2803 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
2804 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
2805 operands[1] = gen_rtx_MEM (Pmode, addr);
2808 emit_insn ((mode == DImode
2809 ? gen_stack_protect_set_di
2810 : gen_stack_protect_set_si) (operands[0], operands[1]));
2814 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
2815 ;; canary value does not live beyond the life of this sequence.
2816 (define_insn "stack_protect_set_<mode>"
2817 [(set (match_operand:GPR 0 "memory_operand" "=m")
2818 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")]
2820 (set (match_scratch:GPR 2 "=&r") (const_int 0))]
2822 "<load>\\t%2, %1\;<store>\\t%2, %0\;li\t%2, 0"
2823 [(set_attr "length" "12")])
2825 (define_expand "stack_protect_test"
2826 [(match_operand 0 "memory_operand")
2827 (match_operand 1 "memory_operand")
2832 machine_mode mode = GET_MODE (operands[0]);
2834 result = gen_reg_rtx(mode);
2835 if (riscv_stack_protector_guard == SSP_TLS)
2837 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
2838 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
2839 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
2840 operands[1] = gen_rtx_MEM (Pmode, addr);
2842 emit_insn ((mode == DImode
2843 ? gen_stack_protect_test_di
2844 : gen_stack_protect_test_si) (result,
2848 rtx cond = gen_rtx_EQ (VOIDmode, result, const0_rtx);
2849 emit_jump_insn (gen_cbranch4 (mode, cond, result, const0_rtx, operands[2]));
2854 (define_insn "stack_protect_test_<mode>"
2855 [(set (match_operand:GPR 0 "register_operand" "=r")
2856 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")
2857 (match_operand:GPR 2 "memory_operand" "m")]
2859 (clobber (match_scratch:GPR 3 "=&r"))]
2861 "<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
2862 [(set_attr "length" "12")])
2864 (include "bitmanip.md")
2866 (include "peephole.md")
2868 (include "generic.md")
2869 (include "sifive-7.md")