RISC-V: Implement instruction patterns for ZBB extension.
[official-gcc.git] / gcc / config / riscv / riscv.md
blobdd4c24292f20d527e01466b92e5a8c99bd1700be
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)
11 ;; any later version.
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.
24   UNSPEC_EH_RETURN
26   ;; Symbolic accesses.  The order of this list must match that of
27   ;; enum riscv_symbol_type in riscv-protos.h.
28   UNSPEC_ADDRESS_FIRST
29   UNSPEC_PCREL
30   UNSPEC_LOAD_GOT
31   UNSPEC_TLS
32   UNSPEC_TLS_LE
33   UNSPEC_TLS_IE
34   UNSPEC_TLS_GD
36   ;; High part of PC-relative address.
37   UNSPEC_AUIPC
39   ;; Floating-point unspecs.
40   UNSPEC_FLT_QUIET
41   UNSPEC_FLE_QUIET
42   UNSPEC_COPYSIGN
43   UNSPEC_LRINT
44   UNSPEC_LROUND
46   ;; Stack tie
47   UNSPEC_TIE
50 (define_c_enum "unspecv" [
51   ;; Register save and restore.
52   UNSPECV_GPR_SAVE
53   UNSPECV_GPR_RESTORE
55   ;; Floating-point unspecs.
56   UNSPECV_FRFLAGS
57   UNSPECV_FSFLAGS
59   ;; Interrupt handler instructions.
60   UNSPECV_MRET
61   UNSPECV_SRET
62   UNSPECV_URET
64   ;; Blockage and synchronization.
65   UNSPECV_BLOCKAGE
66   UNSPECV_FENCE
67   UNSPECV_FENCE_I
69   ;; Stack Smash Protector
70   UNSPEC_SSP_SET
71   UNSPEC_SSP_TEST
74 (define_constants
75   [(RETURN_ADDR_REGNUM          1)
76    (GP_REGNUM                   3)
77    (TP_REGNUM                   4)
78    (T0_REGNUM                   5)
79    (T1_REGNUM                   6)
80    (S0_REGNUM                   8)
81    (S1_REGNUM                   9)
82    (S2_REGNUM                   18)
83    (S3_REGNUM                   19)
84    (S4_REGNUM                   20)
85    (S5_REGNUM                   21)
86    (S6_REGNUM                   22)
87    (S7_REGNUM                   23)
88    (S8_REGNUM                   24)
89    (S9_REGNUM                   25)
90    (S10_REGNUM                  26)
91    (S11_REGNUM                  27)
93    (NORMAL_RETURN               0)
94    (SIBCALL_RETURN              1)
95    (EXCEPTION_RETURN            2)
98 (include "predicates.md")
99 (include "constraints.md")
101 ;; ....................
103 ;;      Attributes
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)))
134          (const_string "yes")
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)
168 ;; nop          no operation
169 ;; ghost        an instruction that produces no real code
170 (define_attr "type"
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" ""
206    (cond [
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)))
211           (const_int 4)
212           (const_int 8))
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")
227                 (const_int 8)
229           ;; Check for doubleword moves that are decomposed into two
230           ;; instructions.
231           (and (eq_attr "move_type" "mtc,mfc,move")
232                (eq_attr "dword_mode" "yes"))
233           (const_int 8)
235           ;; Doubleword CONST{,N} moves are split into two word
236           ;; CONST{,N} moves.
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
242           ;; routines.
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")
247           ] (const_int 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.
254 (define_attr "tune"
255   "generic,sifive_7"
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
306 ;; instruction.
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
326 ;; a given mode.
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")
389                      (gt "") (gtu "u")
390                      (ge "") (geu "u")
391                      (lt "") (ltu "u")
392                      (le "") (leu "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")
399                          (ashiftrt "ashr")
400                          (lshiftrt "lshr")
401                          (div "div")
402                          (mod "mod")
403                          (udiv "udiv")
404                          (umod "umod")
405                          (ge "ge")
406                          (le "le")
407                          (gt "gt")
408                          (lt "lt")
409                          (ior "ior")
410                          (xor "xor")
411                          (and "and")
412                          (plus "add")
413                          (minus "sub")])
415 ;; <insn> expands to the name of the insn that implements a particular code.
416 (define_code_attr insn [(ashift "sll")
417                         (ashiftrt "sra")
418                         (lshiftrt "srl")
419                         (div "div")
420                         (mod "rem")
421                         (udiv "divu")
422                         (umod "remu")
423                         (ior "or")
424                         (xor "xor")
425                         (and "and")
426                         (plus "add")
427                         (minus "sub")])
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")
433   "nothing")
436 ;;  ....................
438 ;;      ADDITION
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")))]
447   "TARGET_HARD_FLOAT"
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")))]
456   ""
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")))]
465   "TARGET_64BIT"
466   "add%i2\t%0,%1,%2"
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 "" ""))]
475   ""
477   if (TARGET_64BIT && <MODE>mode == SImode)
478     {
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));
487       else
488         t4 = operands[1];
489       if (GET_CODE (operands[2]) != CONST_INT)
490         emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
491       else
492         t5 = operands[2];
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);
497     }
498   else
499     {
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);
510     }
511   DONE;
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 "" ""))]
519   ""
521   if (TARGET_64BIT && <MODE>mode == SImode)
522     {
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));
528       else
529         t3 = operands[1];
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);
534     }
535   else
536     {
537       emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
538       riscv_expand_conditional_branch (operands[3], LTU, operands[0],
539                                        operands[1]);
540     }
542   DONE;
545 (define_insn "*addsi3_extended"
546   [(set (match_operand:DI               0 "register_operand" "=r,r")
547         (sign_extend:DI
548              (plus:SI (match_operand:SI 1 "register_operand" " r,r")
549                       (match_operand:SI 2 "arith_operand"    " r,I"))))]
550   "TARGET_64BIT"
551   "add%i2w\t%0,%1,%2"
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")
557         (sign_extend:DI
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"))])))]
561   "TARGET_64BIT"
562   "add%i2w\t%0,%1,%2"
563   [(set_attr "type" "arith")
564    (set_attr "mode" "SI")])
567 ;;  ....................
569 ;;      SUBTRACTION
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")))]
578   "TARGET_HARD_FLOAT"
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")))]
587   "TARGET_64BIT"
588   "sub\t%0,%z1,%2"
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")))]
596   ""
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 "" ""))]
606   ""
608   if (TARGET_64BIT && <MODE>mode == SImode)
609     {
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));
618       else
619         t4 = operands[1];
620       if (GET_CODE (operands[2]) != CONST_INT)
621         emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
622       else
623         t5 = operands[2];
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);
628     }
629   else
630     {
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);
643     }
645   DONE;
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 "" ""))]
653   ""
655   if (TARGET_64BIT && <MODE>mode == SImode)
656     {
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));
662       else
663         t3 = operands[1];
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);
668     }
669   else
670     {
671       emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
672       riscv_expand_conditional_branch (operands[3], LTU, operands[1],
673                                        operands[0]);
674     }
676   DONE;
680 (define_insn "*subsi3_extended"
681   [(set (match_operand:DI               0 "register_operand" "= r")
682         (sign_extend:DI
683             (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
684                       (match_operand:SI 2 "register_operand" "  r"))))]
685   "TARGET_64BIT"
686   "subw\t%0,%z1,%2"
687   [(set_attr "type" "arith")
688    (set_attr "mode" "SI")])
690 (define_insn "*subsi3_extended2"
691   [(set (match_operand:DI                        0 "register_operand" "= r")
692         (sign_extend:DI
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"))])))]
696   "TARGET_64BIT"
697   "subw\t%0,%z1,%2"
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")))]
704   "TARGET_64BIT"
705   "neg\t%0,%1"
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")))]
712   ""
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")
719         (sign_extend:DI
720          (neg:SI (match_operand:SI 1 "register_operand" " r"))))]
721   "TARGET_64BIT"
722   "negw\t%0,%1"
723   [(set_attr "type" "arith")
724    (set_attr "mode" "SI")])
726 (define_insn "*negsi2_extended2"
727   [(set (match_operand:DI                     0 "register_operand" "=r")
728         (sign_extend:DI
729          (match_operator:SI 2 "subreg_lowpart_operator"
730            [(neg:DI (match_operand:DI 1 "register_operand" " r"))])))]
731   "TARGET_64BIT"
732   "negw\t%0,%1"
733   [(set_attr "type" "arith")
734    (set_attr "mode" "SI")])
737 ;;  ....................
739 ;;      MULTIPLICATION
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")))]
748   "TARGET_HARD_FLOAT"
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")))]
757   "TARGET_MUL"
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"
767   "mul\t%0,%1,%2"
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 "" ""))]
776   "TARGET_MUL"
778   if (TARGET_64BIT && <MODE>mode == SImode)
779     {
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));
787       else
788         t4 = operands[1];
789       if (GET_CODE (operands[2]) != CONST_INT)
790         emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
791       else
792         t5 = operands[2];
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);
799     }
800   else
801     {
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);
811     }
813   DONE;
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 "" ""))]
821   "TARGET_MUL"
823   if (TARGET_64BIT && <MODE>mode == SImode)
824     {
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));
834       else
835         t3 = operands[1];
836       if (GET_CODE (operands[2]) != CONST_INT)
837         emit_insn (gen_extend_insn (t4, operands[2], DImode, SImode, 0));
838       else
839         t4 = operands[2];
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);
848     }
849   else
850     {
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);
857     }
859   DONE;
862 (define_insn "*mulsi3_extended"
863   [(set (match_operand:DI              0 "register_operand" "=r")
864         (sign_extend:DI
865             (mult:SI (match_operand:SI 1 "register_operand" " r")
866                      (match_operand:SI 2 "register_operand" " r"))))]
867   "TARGET_MUL && TARGET_64BIT"
868   "mulw\t%0,%1,%2"
869   [(set_attr "type" "imul")
870    (set_attr "mode" "SI")])
872 (define_insn "*mulsi3_extended2"
873   [(set (match_operand:DI                       0 "register_operand" "=r")
874         (sign_extend:DI
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"
879   "mulw\t%0,%1,%2"
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);
906   DONE;
909 (define_insn "<su>muldi3_highpart"
910   [(set (match_operand:DI                0 "register_operand" "=r")
911         (truncate:DI
912           (lshiftrt:TI
913             (mult:TI (any_extend:TI
914                        (match_operand:DI 1 "register_operand" " r"))
915                      (any_extend:TI
916                        (match_operand:DI 2 "register_operand" " r")))
917             (const_int 64))))]
918   "TARGET_MUL && TARGET_64BIT"
919   "mulh<u>\t%0,%1,%2"
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);
937   DONE;
940 (define_insn "usmuldi3_highpart"
941   [(set (match_operand:DI                0 "register_operand" "=r")
942         (truncate:DI
943           (lshiftrt:TI
944             (mult:TI (zero_extend:TI
945                        (match_operand:DI 1 "register_operand"  "r"))
946                      (sign_extend:TI
947                        (match_operand:DI 2 "register_operand" " r")))
948             (const_int 64))))]
949   "TARGET_MUL && TARGET_64BIT"
950   "mulhsu\t%0,%2,%1"
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"))
958                  (any_extend:DI
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));
967   DONE;
970 (define_insn "<su>mulsi3_highpart"
971   [(set (match_operand:SI                0 "register_operand" "=r")
972         (truncate:SI
973           (lshiftrt:DI
974             (mult:DI (any_extend:DI
975                        (match_operand:SI 1 "register_operand" " r"))
976                      (any_extend:DI
977                        (match_operand:SI 2 "register_operand" " r")))
978             (const_int 32))))]
979   "TARGET_MUL && !TARGET_64BIT"
980   "mulh<u>\t%0,%1,%2"
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"))
989                  (sign_extend:DI
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));
998   DONE;
1001 (define_insn "usmulsi3_highpart"
1002   [(set (match_operand:SI                0 "register_operand" "=r")
1003         (truncate:SI
1004           (lshiftrt:DI
1005             (mult:DI (zero_extend:DI
1006                        (match_operand:SI 1 "register_operand" " r"))
1007                      (sign_extend:DI
1008                        (match_operand:SI 2 "register_operand" " r")))
1009             (const_int 32))))]
1010   "TARGET_MUL && !TARGET_64BIT"
1011   "mulhsu\t%0,%2,%1"
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")))]
1027   "TARGET_DIV"
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")
1043         (sign_extend:DI
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 ;;  ....................
1063 ;;      SQUARE ROOT
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.
1079 ;; a * b + c
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")))]
1085   "TARGET_HARD_FLOAT"
1086   "fmadd.<fmt>\t%0,%1,%2,%3"
1087   [(set_attr "type" "fmadd")
1088    (set_attr "mode" "<UNITMODE>")])
1090 ;; a * b - c
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"))))]
1096   "TARGET_HARD_FLOAT"
1097   "fmsub.<fmt>\t%0,%1,%2,%3"
1098   [(set_attr "type" "fmadd")
1099    (set_attr "mode" "<UNITMODE>")])
1101 ;; -a * b - c
1102 (define_insn "fnms<mode>4"
1103   [(set (match_operand:ANYF               0 "register_operand" "=f")
1104         (fma:ANYF
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"))))]
1108   "TARGET_HARD_FLOAT"
1109   "fnmadd.<fmt>\t%0,%1,%2,%3"
1110   [(set_attr "type" "fmadd")
1111    (set_attr "mode" "<UNITMODE>")])
1113 ;; -a * b + c
1114 (define_insn "fnma<mode>4"
1115   [(set (match_operand:ANYF               0 "register_operand" "=f")
1116         (fma:ANYF
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")))]
1120   "TARGET_HARD_FLOAT"
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")
1128         (neg:ANYF
1129             (fma:ANYF
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")
1141         (neg:ANYF
1142             (fma:ANYF
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")
1154         (neg:ANYF
1155             (fma:ANYF
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")
1167         (neg:ANYF
1168             (fma:ANYF
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 ;;  ....................
1180 ;;      SIGN INJECTION
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")))]
1187   "TARGET_HARD_FLOAT"
1188   "fabs.<fmt>\t%0,%1"
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")]
1196                      UNSPEC_COPYSIGN))]
1197   "TARGET_HARD_FLOAT"
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")))]
1205   "TARGET_HARD_FLOAT"
1206   "fneg.<fmt>\t%0,%1"
1207   [(set_attr "type" "fmove")
1208    (set_attr "mode" "<UNITMODE>")])
1211 ;;  ....................
1213 ;;      MIN/MAX
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")))]
1221   "TARGET_HARD_FLOAT"
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")))]
1230   "TARGET_HARD_FLOAT"
1231   "fmax.<fmt>\t%0,%1,%2"
1232   [(set_attr "type" "fmove")
1233    (set_attr "mode" "<UNITMODE>")])
1236 ;;  ....................
1238 ;;      LOGICAL
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")))]
1250   ""
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")))]
1259   "TARGET_64BIT"
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")))]
1267   ""
1268   "not\t%0,%1"
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")))]
1275   "TARGET_64BIT"
1276   "not\t%0,%1"
1277   [(set_attr "type" "logical")
1278    (set_attr "mode" "SI")])
1281 ;;  ....................
1283 ;;      TRUNCATION
1285 ;;  ....................
1287 (define_insn "truncdfsf2"
1288   [(set (match_operand:SF     0 "register_operand" "=f")
1289         (float_truncate:SF
1290             (match_operand:DF 1 "register_operand" " f")))]
1291   "TARGET_DOUBLE_FLOAT"
1292   "fcvt.s.d\t%0,%1"
1293   [(set_attr "type" "fcvt")
1294    (set_attr "mode" "SF")])
1297 ;;  ....................
1299 ;;      ZERO EXTENSION
1301 ;;  ....................
1303 ;; Extension insns.
1305 (define_expand "zero_extendsidi2"
1306   [(set (match_operand:DI 0 "register_operand")
1307         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
1308   "TARGET_64BIT")
1310 (define_insn_and_split "*zero_extendsidi2_internal"
1311   [(set (match_operand:DI     0 "register_operand"     "=r,r")
1312         (zero_extend:DI
1313             (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1314   "TARGET_64BIT && !(TARGET_ZBA || TARGET_ZBB)"
1315   "@
1316    #
1317    lwu\t%0,%1"
1318   "&& reload_completed
1319    && REG_P (operands[1])
1320    && !paradoxical_subreg_p (operands[0])"
1321   [(set (match_dup 0)
1322         (ashift:DI (match_dup 1) (const_int 32)))
1323    (set (match_dup 0)
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")
1331         (zero_extend:GPR
1332             (match_operand:HI 1 "nonimmediate_operand")))]
1333   "")
1335 (define_insn_and_split "*zero_extendhi<GPR:mode>2"
1336   [(set (match_operand:GPR    0 "register_operand"     "=r,r")
1337         (zero_extend:GPR
1338             (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
1339   "!TARGET_ZBB"
1340   "@
1341    #
1342    lhu\t%0,%1"
1343   "&& reload_completed
1344    && REG_P (operands[1])
1345    && !paradoxical_subreg_p (operands[0])"
1346   [(set (match_dup 0)
1347         (ashift:GPR (match_dup 1) (match_dup 2)))
1348    (set (match_dup 0)
1349         (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1350   {
1351     operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1352     operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1353   }
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")))]
1361   ""
1362   "@
1363    andi\t%0,%1,0xff
1364    lbu\t%0,%1"
1365   [(set_attr "move_type" "andi,load")
1366    (set_attr "mode" "<SUPERQI:MODE>")])
1369 ;;  ....................
1371 ;;      SIGN EXTENSION
1373 ;;  ....................
1375 (define_insn "extendsidi2"
1376   [(set (match_operand:DI     0 "register_operand"     "=r,r")
1377         (sign_extend:DI
1378             (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1379   "TARGET_64BIT"
1380   "@
1381    sext.w\t%0,%1
1382    lw\t%0,%1"
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")))]
1389   "")
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")))]
1395   "!TARGET_ZBB"
1396   "@
1397    #
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")
1415         (float_extend:DF
1416             (match_operand:SF 1 "register_operand" " f")))]
1417   "TARGET_DOUBLE_FLOAT"
1418   "fcvt.d.s\t%0,%1"
1419   [(set_attr "type" "fcvt")
1420    (set_attr "mode" "DF")])
1423 ;;  ....................
1425 ;;      CONVERSIONS
1427 ;;  ....................
1429 (define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
1430   [(set (match_operand:GPR      0 "register_operand" "=r")
1431         (fix:GPR
1432             (match_operand:ANYF 1 "register_operand" " f")))]
1433   "TARGET_HARD_FLOAT"
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")
1440         (unsigned_fix:GPR
1441             (match_operand:ANYF 1 "register_operand" " f")))]
1442   "TARGET_HARD_FLOAT"
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")
1449         (float:ANYF
1450             (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
1451   "TARGET_HARD_FLOAT"
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")))]
1460   "TARGET_HARD_FLOAT"
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")
1467         (unspec:GPR
1468             [(match_operand:ANYF 1 "register_operand" " f")]
1469             RINT))]
1470   "TARGET_HARD_FLOAT"
1471   "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
1472   [(set_attr "type" "fcvt")
1473    (set_attr "mode" "<ANYF:MODE>")])
1476 ;;  ....................
1478 ;;      DATA MOVEMENT
1480 ;;  ....................
1482 ;; Lower-level instructions for loading an address from the GOT.
1483 ;; We could use MEMs, but an unspec gives more optimization
1484 ;; opportunities.
1486 (define_insn "got_load<mode>"
1487    [(set (match_operand:P      0 "register_operand" "=r")
1488          (unspec:P
1489              [(match_operand:P 1 "symbolic_operand" "")]
1490              UNSPEC_LOAD_GOT))]
1491   ""
1492   "la\t%0,%1"
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")
1498         (unspec:P
1499             [(match_operand:P 1 "register_operand" "r")
1500              (match_operand:P 2 "register_operand" "r")
1501              (match_operand:P 3 "symbolic_operand" "")]
1502             UNSPEC_TLS_LE))]
1503   ""
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")
1510         (unspec:P
1511             [(match_operand:P 1 "symbolic_operand" "")]
1512             UNSPEC_TLS_GD))]
1513   ""
1514   "la.tls.gd\t%0,%1"
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")
1520         (unspec:P
1521             [(match_operand:P 1 "symbolic_operand" "")]
1522             UNSPEC_TLS_IE))]
1523   ""
1524   "la.tls.ie\t%0,%1"
1525   [(set_attr "got" "load")
1526    (set_attr "mode" "<MODE>")])
1528 (define_insn "auipc<mode>"
1529   [(set (match_operand:P           0 "register_operand" "=r")
1530         (unspec:P
1531             [(match_operand:P      1 "symbolic_operand" "")
1532                   (match_operand:P 2 "const_int_operand")
1533                   (pc)]
1534             UNSPEC_AUIPC))]
1535   ""
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" "")))]
1548   ""
1549   "addi\t%0,%1,%R2"
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.
1555 (define_split
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"))]
1559   ""
1560   [(const_int 0)]
1562   riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
1563                       <GPR:MODE>mode, TRUE);
1564   DONE;
1567 ;; Likewise, for symbolic operands.
1568 (define_split
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 ""))]
1584   ""
1586   if (riscv_legitimize_move (DImode, operands[0], operands[1]))
1587     DONE;
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"))]
1593   "!TARGET_64BIT
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"))]
1603   "TARGET_64BIT
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 ""))]
1615   ""
1617   if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
1618     DONE;
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 ""))]
1640   ""
1642   if (riscv_legitimize_move (HImode, operands[0], operands[1]))
1643     DONE;
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")))]
1663   ""
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")))]
1672   ""
1673   "xor%i2\t%0,%1,%2"
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 ""))]
1682   ""
1684   if (riscv_legitimize_move (QImode, operands[0], operands[1]))
1685     DONE;
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 ""))]
1702   ""
1704   if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
1705     DONE;
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"))]
1711   "TARGET_HARD_FLOAT
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"))]
1721   "!TARGET_HARD_FLOAT
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 ""))]
1733   ""
1735   if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
1736     DONE;
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")])
1771 (define_split
1772   [(set (match_operand:MOVE64 0 "nonimmediate_operand")
1773         (match_operand:MOVE64 1 "move_operand"))]
1774   "reload_completed
1775    && riscv_split_64bit_move_p (operands[0], operands[1])"
1776   [(const_int 0)]
1778   riscv_split_doubleword_move (operands[0], operands[1]);
1779   DONE;
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"))])]
1787   ""
1789   if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
1790     DONE;
1791   else
1792     FAIL;
1795 ;; Expand in-line code to clear the instruction cache between operand[0] and
1796 ;; operand[1].
1797 (define_expand "clear_cache"
1798   [(match_operand 0 "pmode_register_operand")
1799    (match_operand 1 "pmode_register_operand")]
1800   ""
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);
1806 #else
1807   if (TARGET_ZIFENCEI)
1808     emit_insn (gen_fence_i ());
1809 #endif
1810   DONE;
1813 (define_insn "fence"
1814   [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
1815   ""
1816   "%|fence%-")
1818 (define_insn "fence_i"
1819   [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
1820   "TARGET_ZIFENCEI"
1821   "fence.i")
1824 ;;  ....................
1826 ;;      SHIFTS
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")
1837         (any_shift:SI
1838             (match_operand:SI 1 "register_operand" "  r")
1839             (match_operand:QI 2 "arith_operand"    " rI")))]
1840   ""
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")
1853         (any_shift:SI
1854             (match_operand:SI 1 "register_operand" "  r")
1855             (match_operator 4 "subreg_lowpart_operator"
1856              [(and:SI
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"
1861   "#"
1862   "&& 1"
1863   [(set (match_dup 0)
1864         (any_shift:SI (match_dup 1)
1865                       (match_dup 2)))]
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")
1872         (any_shift:SI
1873             (match_operand:SI 1 "register_operand" "  r")
1874             (match_operator 4 "subreg_lowpart_operator"
1875              [(and:DI
1876                (match_operand:DI 2 "register_operand"  "r")
1877                (match_operand 3 "const_int_operand"))])))]
1878   "TARGET_64BIT
1879    && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1880        == GET_MODE_BITSIZE (SImode)-1"
1881   "#"
1882   "&& 1"
1883   [(set (match_dup 0)
1884         (any_shift:SI (match_dup 1)
1885                       (match_dup 2)))]
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")
1892         (any_shift:DI
1893             (match_operand:DI 1 "register_operand" "  r")
1894             (match_operand:QI 2 "arith_operand"    " rI")))]
1895   "TARGET_64BIT"
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")
1908         (any_shift:DI
1909             (match_operand:DI 1 "register_operand" "  r")
1910             (match_operator 4 "subreg_lowpart_operator"
1911              [(and:SI
1912                (match_operand:SI 2 "register_operand"  "r")
1913                (match_operand 3 "const_int_operand"))])))]
1914   "TARGET_64BIT
1915    && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1916        == GET_MODE_BITSIZE (DImode)-1"
1917   "#"
1918   "&& 1"
1919   [(set (match_dup 0)
1920         (any_shift:DI (match_dup 1)
1921                       (match_dup 2)))]
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")
1928         (any_shift:DI
1929             (match_operand:DI 1 "register_operand" "  r")
1930             (match_operator 4 "subreg_lowpart_operator"
1931              [(and:DI
1932                (match_operand:DI 2 "register_operand"  "r")
1933                (match_operand 3 "const_int_operand"))])))]
1934   "TARGET_64BIT
1935    && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1936        == GET_MODE_BITSIZE (DImode)-1"
1937   "#"
1938   "&& 1"
1939   [(set (match_dup 0)
1940         (any_shift:DI (match_dup 1)
1941                       (match_dup 2)))]
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")
1948         (sign_extend:DI
1949             (any_shift:SI (match_operand:SI 1 "register_operand" "  r")
1950                           (match_operand:QI 2 "arith_operand"    " rI"))))]
1951   "TARGET_64BIT"
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")
1963         (sign_extend:DI
1964             (any_shift:SI
1965              (match_operand:SI 1 "register_operand" "  r")
1966              (match_operator 4 "subreg_lowpart_operator"
1967               [(and:SI
1968                 (match_operand:SI 2 "register_operand" " r")
1969                 (match_operand 3 "const_int_operand"))]))))]
1970   "TARGET_64BIT
1971    && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1972        == GET_MODE_BITSIZE (SImode)-1"
1973   "#"
1974   "&& 1"
1975   [(set (match_dup 0)
1976         (sign_extend:DI
1977          (any_shift:SI (match_dup 1)
1978                        (match_dup 2))))]
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")
1985         (sign_extend:DI
1986             (any_shift:SI
1987              (match_operand:SI 1 "register_operand" "  r")
1988              (match_operator 4 "subreg_lowpart_operator"
1989               [(and:DI
1990                 (match_operand:DI 2 "register_operand" " r")
1991                 (match_operand 3 "const_int_operand"))]))))]
1992   "TARGET_64BIT
1993    && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1994        == GET_MODE_BITSIZE (SImode)-1"
1995   "#"
1996   "&& 1"
1997   [(set (match_dup 0)
1998         (sign_extend:DI
1999          (any_shift:SI (match_dup 1)
2000                        (match_dup 2))))]
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")
2009         (zero_extend:DI
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")
2040                (const_int 0)))]
2041   "TARGET_64BIT"
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.
2055 (define_split
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"))]
2060   ""
2061  [(set (match_dup 3)
2062        (ashift:GPR (match_dup 1) (match_dup 2)))
2063   (set (match_dup 0)
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.
2073 (define_split
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"))]
2078   "TARGET_64BIT"
2079   [(set (match_dup 3)
2080         (lshiftrt:DI (match_dup 1) (match_dup 2)))
2081    (set (match_dup 0)
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)"
2099   "#"
2100   "&& reload_completed"
2101   [(set (match_dup 4)
2102         (ashift:DI (match_dup 1) (const_int 32)))
2103    (set (match_dup 0)
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>"
2119   [(set (pc)
2120         (if_then_else
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 "" ""))
2125          (pc)))]
2126   ""
2127   "b%C1\t%2,%z3,%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")))]
2138   "TARGET_SFB_ALU"
2140   rtx cmp = operands[1];
2141   /* We only handle word mode integer compares for now.  */
2142   if (GET_MODE (XEXP (cmp, 0)) != word_mode)
2143     FAIL;
2144   riscv_expand_conditional_move (operands[0], operands[2], operands[3],
2145                                  GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
2146   DONE;
2149 (define_insn "*mov<GPR:mode><X:mode>cc"
2150   [(set (match_operand:GPR 0 "register_operand" "=r,r")
2151         (if_then_else:GPR
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")))]
2157   "TARGET_SFB_ALU"
2158   "@
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"
2167   [(set (pc)
2168         (if_then_else (match_operand 0)
2169                       (label_ref (match_operand 1))
2170                       (pc)))])
2172 (define_expand "@cbranch<mode>4"
2173   [(set (pc)
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 ""))
2178                       (pc)))]
2179   ""
2181   riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2182                                    operands[1], operands[2]);
2183   DONE;
2186 (define_expand "@cbranch<mode>4"
2187   [(set (pc)
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 ""))
2192                       (pc)))]
2193   "TARGET_HARD_FLOAT"
2195   riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2196                                    operands[1], operands[2]);
2197   DONE;
2200 (define_insn_and_split "*branch_on_bit<X:mode>"
2201   [(set (pc)
2202         (if_then_else
2203             (match_operator 0 "equality_operator"
2204                 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2205                                  (const_int 1)
2206                                  (match_operand 3 "branch_on_bit_operand"))
2207                                  (const_int 0)])
2208             (label_ref (match_operand 1))
2209             (pc)))
2210    (clobber (match_scratch:X 4 "=&r"))]
2211   ""
2212   "#"
2213   "reload_completed"
2214   [(set (match_dup 4)
2215         (ashift:X (match_dup 2) (match_dup 3)))
2216    (set (pc)
2217         (if_then_else
2218             (match_op_dup 0 [(match_dup 4) (const_int 0)])
2219             (label_ref (match_operand 1))
2220             (pc)))]
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);
2227   else
2228     operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
2231 (define_insn_and_split "*branch_on_bit_range<X:mode>"
2232   [(set (pc)
2233         (if_then_else
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")
2237                                  (const_int 0))
2238                                  (const_int 0)])
2239             (label_ref (match_operand 1))
2240             (pc)))
2241    (clobber (match_scratch:X 4 "=&r"))]
2242   ""
2243   "#"
2244   "reload_completed"
2245   [(set (match_dup 4)
2246         (ashift:X (match_dup 2) (match_dup 3)))
2247    (set (pc)
2248         (if_then_else
2249             (match_op_dup 0 [(match_dup 4) (const_int 0)])
2250             (label_ref (match_operand 1))
2251             (pc)))]
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")]))]
2270   ""
2272   riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
2273                         operands[3]);
2274   DONE;
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")]))]
2282   "TARGET_HARD_FLOAT"
2284   riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
2285                           operands[3]);
2286   DONE;
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")]))]
2294   "TARGET_HARD_FLOAT"
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")
2301                     (unspec:X
2302                      [(match_operand:ANYF 1 "register_operand")
2303                       (match_operand:ANYF 2 "register_operand")]
2304                      QUIET_COMPARISON))
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")
2310          (unspec:X
2311           [(match_operand:ANYF 1 "register_operand" " f")
2312            (match_operand:ANYF 2 "register_operand" " f")]
2313           QUIET_COMPARISON))
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")
2323          (unspec:X
2324           [(match_operand:ANYF 1 "register_operand" " f")
2325            (match_operand:ANYF 2 "register_operand" " f")]
2326           QUIET_COMPARISON))
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")
2337                 (const_int 0)))]
2338   ""
2339   "seqz\t%0,%1"
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")
2346                 (const_int 0)))]
2347   ""
2348   "snez\t%0,%1"
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")))]
2356   ""
2357   "sgt<u>\t%0,%1,%z2"
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")
2364                     (const_int 1)))]
2365   ""
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")))]
2374   ""
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" "")))]
2383   ""
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.
2400 (define_insn "jump"
2401   [(set (pc)
2402         (label_ref (match_operand 0 "" "")))]
2403   ""
2404   "j\t%l0"
2405   [(set_attr "type"     "jump")
2406    (set_attr "mode"     "none")])
2408 (define_expand "indirect_jump"
2409   [(set (pc) (match_operand 0 "register_operand"))]
2410   ""
2412   operands[0] = force_reg (Pmode, operands[0]);
2413   if (Pmode == SImode)
2414     emit_jump_insn (gen_indirect_jumpsi (operands[0]));
2415   else
2416     emit_jump_insn (gen_indirect_jumpdi (operands[0]));
2417   DONE;
2420 (define_insn "indirect_jump<mode>"
2421   [(set (pc) (match_operand:P 0 "register_operand" "l"))]
2422   ""
2423   "jr\t%0"
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 "" "")))]
2430   ""
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]));
2439   else
2440     emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
2441   DONE;
2444 (define_insn "tablejump<mode>"
2445   [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
2446    (use (label_ref (match_operand 1 "" "")))]
2447   ""
2448   "jr\t%0"
2449   [(set_attr "type" "jump")
2450    (set_attr "mode" "none")])
2453 ;;  ....................
2455 ;;      Function prologue/epilogue
2457 ;;  ....................
2460 (define_expand "prologue"
2461   [(const_int 1)]
2462   ""
2464   riscv_expand_prologue ();
2465   DONE;
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)]
2474   ""
2475   ""
2476   [(set_attr "type" "ghost")
2477    (set_attr "mode" "none")])
2479 (define_expand "epilogue"
2480   [(const_int 2)]
2481   ""
2483   riscv_expand_epilogue (NORMAL_RETURN);
2484   DONE;
2487 (define_expand "sibcall_epilogue"
2488   [(const_int 2)]
2489   ""
2491   riscv_expand_epilogue (SIBCALL_RETURN);
2492   DONE;
2495 ;; Trivial return.  Make it look like a normal return insn as that
2496 ;; allows jump optimizations to work better.
2498 (define_expand "return"
2499   [(simple_return)]
2500   "riscv_can_use_return_insn ()"
2501   "")
2503 (define_insn "simple_return"
2504   [(simple_return)]
2505   ""
2507   return riscv_output_return ();
2509   [(set_attr "type"     "jump")
2510    (set_attr "mode"     "none")])
2512 ;; Normal return.
2514 (define_insn "simple_return_internal"
2515   [(simple_return)
2516    (use (match_operand 0 "pmode_register_operand" ""))]
2517   ""
2518   "jr\t%0"
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"))]
2525   ""
2527   if (GET_MODE (operands[0]) != word_mode)
2528     operands[0] = convert_to_mode (word_mode, operands[0], 0);
2529   if (TARGET_64BIT)
2530     emit_insn (gen_eh_set_lr_di (operands[0]));
2531   else
2532     emit_insn (gen_eh_set_lr_si (operands[0]));
2534   emit_jump_insn (gen_eh_return_internal ());
2535   emit_barrier ();
2536   DONE;
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"))]
2545   "! TARGET_64BIT"
2546   "#")
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"))]
2551   "TARGET_64BIT"
2552   "#")
2554 (define_split
2555   [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
2556    (clobber (match_scratch 1))]
2557   "reload_completed"
2558   [(const_int 0)]
2560   riscv_set_return_address (operands[0], operands[1]);
2561   DONE;
2564 (define_insn_and_split "eh_return_internal"
2565   [(eh_return)]
2566   ""
2567   "#"
2568   "epilogue_completed"
2569   [(const_int 0)]
2570   "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
2573 ;;  ....................
2575 ;;      FUNCTION CALLS
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
2584   ""
2586   rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2587   emit_call_insn (gen_sibcall_internal (target, operands[1]));
2588   DONE;
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)"
2595   "@
2596    jr\t%0
2597    tail\t%0
2598    tail\t%0@plt"
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
2606   ""
2608   rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2609   emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
2610   DONE;
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)"
2618   "@
2619    jr\t%1
2620    tail\t%1
2621    tail\t%1@plt"
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
2629   ""
2631   rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2632   emit_call_insn (gen_call_internal (target, operands[1]));
2633   DONE;
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))]
2640   ""
2641   "@
2642    jalr\t%0
2643    call\t%0
2644    call\t%0@plt"
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
2652   ""
2654   rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2655   emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
2656   DONE;
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))]
2664   ""
2665   "@
2666    jalr\t%1
2667    call\t%1
2668    call\t%1@plt"
2669   [(set_attr "type" "call")])
2671 ;; Call subroutine returning any type.
2673 (define_expand "untyped_call"
2674   [(parallel [(call (match_operand 0 "")
2675                     (const_int 0))
2676               (match_operand 1 "")
2677               (match_operand 2 "")])]
2678   ""
2680   int i;
2682   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2684   for (i = 0; i < XVECLEN (operands[2], 0); i++)
2685     {
2686       rtx set = XVECEXP (operands[2], 0, i);
2687       riscv_emit_move (SET_DEST (set), SET_SRC (set));
2688     }
2690   emit_insn (gen_blockage ());
2691   DONE;
2694 (define_insn "nop"
2695   [(const_int 0)]
2696   ""
2697   "nop"
2698   [(set_attr "type"     "nop")
2699    (set_attr "mode"     "none")])
2701 (define_insn "trap"
2702   [(trap_if (const_int 1) (const_int 0))]
2703   ""
2704   "ebreak")
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)])]
2714   ""
2715   "call\tt0,__riscv_save_%0")
2717 (define_insn "gpr_restore"
2718   [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2719   ""
2720   "tail\t__riscv_restore_%0")
2722 (define_insn "gpr_restore_return"
2723   [(return)
2724    (use (match_operand 0 "pmode_register_operand" ""))
2725    (const_int 0)]
2726   ""
2727   "")
2729 (define_insn "riscv_frflags"
2730   [(set (match_operand:SI 0 "register_operand" "=r")
2731         (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
2732   "TARGET_HARD_FLOAT"
2733   "frflags\t%0")
2735 (define_insn "riscv_fsflags"
2736   [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2737   "TARGET_HARD_FLOAT"
2738   "fsflags\t%0")
2740 (define_insn "riscv_mret"
2741   [(return)
2742    (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
2743   ""
2744   "mret")
2746 (define_insn "riscv_sret"
2747   [(return)
2748    (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
2749   ""
2750   "sret")
2752 (define_insn "riscv_uret"
2753   [(return)
2754    (unspec_volatile [(const_int 0)] UNSPECV_URET)]
2755   ""
2756   "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")]
2762                     UNSPEC_TIE))]
2763   ""
2764   ""
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")]
2776   ""
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));
2782   DONE;
2785 ;; Named pattern for expanding thread pointer reference.
2786 (define_expand "get_thread_pointer<mode>"
2787   [(set (match_operand:P 0 "register_operand" "=r")
2788         (reg:P TP_REGNUM))]
2789   ""
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")]
2797   ""
2799   machine_mode mode = GET_MODE (operands[0]);
2800   if (riscv_stack_protector_guard == SSP_TLS)
2801   {
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);
2806   }
2808   emit_insn ((mode == DImode
2809               ? gen_stack_protect_set_di
2810               : gen_stack_protect_set_si) (operands[0], operands[1]));
2811   DONE;
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")]
2819          UNSPEC_SSP_SET))
2820    (set (match_scratch:GPR 2 "=&r") (const_int 0))]
2821   ""
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")
2828    (match_operand 2)]
2829   ""
2831   rtx result;
2832   machine_mode mode = GET_MODE (operands[0]);
2834   result = gen_reg_rtx(mode);
2835   if (riscv_stack_protector_guard == SSP_TLS)
2836   {
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);
2841   }
2842   emit_insn ((mode == DImode
2843                   ? gen_stack_protect_test_di
2844                   : gen_stack_protect_test_si) (result,
2845                                                 operands[0],
2846                                                 operands[1]));
2848   rtx cond = gen_rtx_EQ (VOIDmode, result, const0_rtx);
2849   emit_jump_insn (gen_cbranch4 (mode, cond, result, const0_rtx, operands[2]));
2851   DONE;
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")]
2858          UNSPEC_SSP_TEST))
2859    (clobber (match_scratch:GPR 3 "=&r"))]
2860   ""
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")
2865 (include "sync.md")
2866 (include "peephole.md")
2867 (include "pic.md")
2868 (include "generic.md")
2869 (include "sifive-7.md")