]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/riscv/riscv.md
c++: ttp matching with constrained auto parm [PR99909]
[thirdparty/gcc.git] / gcc / config / riscv / riscv.md
CommitLineData
09cae750 1;; Machine description for RISC-V for GNU compiler.
99dee823 2;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
09cae750
PD
3;; Contributed by Andrew Waterman (andrew@sifive.com).
4;; Based on MIPS target for GNU compiler.
5
6;; This file is part of GCC.
7
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.
12
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.
17
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/>.
21
22(define_c_enum "unspec" [
23 ;; Override return address for exception handling.
24 UNSPEC_EH_RETURN
25
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
35
36 ;; High part of PC-relative address.
37 UNSPEC_AUIPC
38
39 ;; Floating-point unspecs.
40 UNSPEC_FLT_QUIET
41 UNSPEC_FLE_QUIET
42 UNSPEC_COPYSIGN
43 UNSPEC_LRINT
44 UNSPEC_LROUND
45
46 ;; Stack tie
47 UNSPEC_TIE
48])
49
50(define_c_enum "unspecv" [
51 ;; Register save and restore.
52 UNSPECV_GPR_SAVE
53 UNSPECV_GPR_RESTORE
54
55 ;; Floating-point unspecs.
56 UNSPECV_FRFLAGS
57 UNSPECV_FSFLAGS
58
d0ebdd9f
JW
59 ;; Interrupt handler instructions.
60 UNSPECV_MRET
ec74725c
JW
61 UNSPECV_SRET
62 UNSPECV_URET
d0ebdd9f 63
09cae750
PD
64 ;; Blockage and synchronization.
65 UNSPECV_BLOCKAGE
66 UNSPECV_FENCE
67 UNSPECV_FENCE_I
c931e8d5
CQ
68
69 ;; Stack Smash Protector
70 UNSPEC_SSP_SET
71 UNSPEC_SSP_TEST
09cae750
PD
72])
73
74(define_constants
75 [(RETURN_ADDR_REGNUM 1)
d0ebdd9f 76 (GP_REGNUM 3)
1073b500 77 (TP_REGNUM 4)
09cae750
PD
78 (T0_REGNUM 5)
79 (T1_REGNUM 6)
80 (S0_REGNUM 8)
81 (S1_REGNUM 9)
82 (S2_REGNUM 18)
d0e0c130
KC
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)
fd1e52dc
JW
92
93 (NORMAL_RETURN 0)
94 (SIBCALL_RETURN 1)
95 (EXCEPTION_RETURN 2)
09cae750
PD
96])
97
98(include "predicates.md")
99(include "constraints.md")
100
101;; ....................
102;;
103;; Attributes
104;;
105;; ....................
106
107(define_attr "got" "unset,xgot_high,load"
108 (const_string "unset"))
109
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:
113;;
114;; andi a single ANDI instruction
115;; shift_shift a shift left followed by a shift right
116;;
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"))
125
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"))
129
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")
135
136 (and (eq_attr "mode" "TI,TF")
137 (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
138 (const_string "yes")]
139 (const_string "no")))
140
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,
4f475391 173 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost"
09cae750
PD
174 (cond [(eq_attr "got" "load") (const_string "load")
175
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")
185
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")
191
192 ;; These types of move are always split.
193 (eq_attr "move_type" "shift_shift")
194 (const_string "multi")
195
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")))
203
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))
213
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)
217
218 ;; "Ghost" instructions occupy no space.
219 (eq_attr "type" "ghost") (const_int 0)
220
221 (eq_attr "got" "load") (const_int 8)
222
223 (eq_attr "type" "fcmp") (const_int 8)
224
225 ;; SHIFT_SHIFTs are decomposed into two separate instructions.
226 (eq_attr "move_type" "shift_shift")
227 (const_int 8)
228
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)
234
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")
240
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)))
248
249;; Is copying of this instruction disallowed?
250(define_attr "cannot_copy" "no,yes" (const_string "no"))
251
88108b27
AW
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)")))
257
09cae750
PD
258;; Describe a user's asm statement.
259(define_asm_attributes
260 [(set_attr "type" "multi")])
261
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")])
265
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")])
269
270;; Likewise, but for XLEN-sized quantities.
271(define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")])
272
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")])
276
277;; 32-bit moves for which we provide move patterns.
278(define_mode_iterator MOVE32 [SI])
279
280;; 64-bit modes for which we provide move patterns.
281(define_mode_iterator MOVE64 [DI DF])
282
283;; Iterator for sub-32-bit integer modes.
284(define_mode_iterator SHORT [QI HI])
285
286;; Iterator for HImode constant generation.
287(define_mode_iterator HISI [HI SI])
288
289;; Iterator for QImode extension patterns.
290(define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")])
291
292;; Iterator for hardware integer modes narrower than XLEN.
293(define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")])
294
295;; Iterator for hardware-supported integer modes.
296(define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
297
298;; Iterator for hardware-supported floating-point modes.
299(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
300 (DF "TARGET_DOUBLE_FLOAT")])
301
efc60124
JW
302;; Iterator for floating-point modes that can be loaded into X registers.
303(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT")])
304
09cae750
PD
305;; This attribute gives the length suffix for a sign- or zero-extension
306;; instruction.
307(define_mode_attr size [(QI "b") (HI "h")])
308
309;; Mode attributes for loads.
310(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
311
efc60124
JW
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")])
315
316;; Mode attribute for FP loads into integer registers.
317(define_mode_attr softload [(SF "lw") (DF "ld")])
318
09cae750
PD
319;; Instruction names for stores.
320(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
321
efc60124
JW
322;; Instruction names for FP stores from integer registers.
323(define_mode_attr softstore [(SF "sw") (DF "sd")])
324
09cae750
PD
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")])
328
329;; This attribute gives the format suffix for floating-point operations.
330(define_mode_attr fmt [(SF "s") (DF "d")])
331
332;; This attribute gives the integer suffix for floating-point conversions.
333(define_mode_attr ifmt [(SI "w") (DI "l")])
334
335;; This attribute gives the format suffix for atomic memory operations.
336(define_mode_attr amo [(SI "w") (DI "d")])
337
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")])
341
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")])
345
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")])
350
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")])
354
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])
358
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])
362
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])
366
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])
370
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])
374
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])
378
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])
385
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")])
393
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")])
396
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")])
414
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")])
428
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")
434
435;;
436;; ....................
437;;
438;; ADDITION
439;;
440;; ....................
441;;
442
443(define_insn "add<mode>3"
248710c4
KC
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")))]
09cae750
PD
447 "TARGET_HARD_FLOAT"
448 "fadd.<fmt>\t%0,%1,%2"
449 [(set_attr "type" "fadd")
450 (set_attr "mode" "<UNITMODE>")])
451
452(define_insn "addsi3"
248710c4
KC
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")))]
09cae750 456 ""
0791ac18 457 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
09cae750
PD
458 [(set_attr "type" "arith")
459 (set_attr "mode" "SI")])
460
461(define_insn "adddi3"
248710c4
KC
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")))]
09cae750 465 "TARGET_64BIT"
0791ac18 466 "add%i2\t%0,%1,%2"
09cae750
PD
467 [(set_attr "type" "arith")
468 (set_attr "mode" "DI")])
469
6efd040c
L
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 ""
476{
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);
483
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));
495
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);
502
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]);
507
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;
512})
513
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 ""
520{
521 if (TARGET_64BIT && <MODE>mode == SImode)
522 {
523 rtx t3 = gen_reg_rtx (DImode);
524 rtx t4 = gen_reg_rtx (DImode);
525
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));
532
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 }
541
542 DONE;
543})
544
09cae750 545(define_insn "*addsi3_extended"
248710c4 546 [(set (match_operand:DI 0 "register_operand" "=r,r")
09cae750 547 (sign_extend:DI
248710c4
KC
548 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
549 (match_operand:SI 2 "arith_operand" " r,I"))))]
09cae750 550 "TARGET_64BIT"
0791ac18 551 "add%i2w\t%0,%1,%2"
09cae750
PD
552 [(set_attr "type" "arith")
553 (set_attr "mode" "SI")])
554
555(define_insn "*addsi3_extended2"
248710c4 556 [(set (match_operand:DI 0 "register_operand" "=r,r")
09cae750 557 (sign_extend:DI
7ac4dfec
MC
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"))])))]
09cae750 561 "TARGET_64BIT"
0791ac18 562 "add%i2w\t%0,%1,%2"
09cae750
PD
563 [(set_attr "type" "arith")
564 (set_attr "mode" "SI")])
565
566;;
567;; ....................
568;;
569;; SUBTRACTION
570;;
571;; ....................
572;;
573
574(define_insn "sub<mode>3"
248710c4
KC
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")))]
09cae750
PD
578 "TARGET_HARD_FLOAT"
579 "fsub.<fmt>\t%0,%1,%2"
580 [(set_attr "type" "fadd")
581 (set_attr "mode" "<UNITMODE>")])
582
583(define_insn "subdi3"
248710c4
KC
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")))]
09cae750
PD
587 "TARGET_64BIT"
588 "sub\t%0,%z1,%2"
589 [(set_attr "type" "arith")
590 (set_attr "mode" "DI")])
591
592(define_insn "subsi3"
248710c4
KC
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")))]
09cae750
PD
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")])
600
6efd040c
L
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 ""
607{
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);
614
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));
626
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);
633
634 emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
635
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));
638
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]));
641
642 riscv_expand_conditional_branch (operands[3], NE, t3, t4);
643 }
644
645 DONE;
646})
647
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 ""
654{
655 if (TARGET_64BIT && <MODE>mode == SImode)
656 {
657 rtx t3 = gen_reg_rtx (DImode);
658 rtx t4 = gen_reg_rtx (DImode);
659
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));
666
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 }
675
676 DONE;
677})
678
679
09cae750 680(define_insn "*subsi3_extended"
248710c4 681 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 682 (sign_extend:DI
248710c4
KC
683 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
684 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
685 "TARGET_64BIT"
686 "subw\t%0,%z1,%2"
687 [(set_attr "type" "arith")
688 (set_attr "mode" "SI")])
689
690(define_insn "*subsi3_extended2"
01414d53 691 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 692 (sign_extend:DI
7ac4dfec
MC
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"))])))]
09cae750
PD
696 "TARGET_64BIT"
697 "subw\t%0,%z1,%2"
698 [(set_attr "type" "arith")
699 (set_attr "mode" "SI")])
700
01414d53
JW
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")])
708
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")])
716
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")])
725
726(define_insn "*negsi2_extended2"
727 [(set (match_operand:DI 0 "register_operand" "=r")
728 (sign_extend:DI
7ac4dfec
MC
729 (match_operator:SI 2 "subreg_lowpart_operator"
730 [(neg:DI (match_operand:DI 1 "register_operand" " r"))])))]
01414d53
JW
731 "TARGET_64BIT"
732 "negw\t%0,%1"
733 [(set_attr "type" "arith")
734 (set_attr "mode" "SI")])
735
09cae750
PD
736;;
737;; ....................
738;;
739;; MULTIPLICATION
740;;
741;; ....................
742;;
743
744(define_insn "mul<mode>3"
248710c4
KC
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")))]
09cae750
PD
748 "TARGET_HARD_FLOAT"
749 "fmul.<fmt>\t%0,%1,%2"
750 [(set_attr "type" "fmul")
751 (set_attr "mode" "<UNITMODE>")])
752
753(define_insn "mulsi3"
248710c4
KC
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")))]
09cae750
PD
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")])
761
762(define_insn "muldi3"
248710c4
KC
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")))]
09cae750
PD
766 "TARGET_MUL && TARGET_64BIT"
767 "mul\t%0,%1,%2"
768 [(set_attr "type" "imul")
769 (set_attr "mode" "DI")])
770
6efd040c
L
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"
777{
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);
784
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));
794
795 emit_move_insn (operands[0], gen_lowpart (SImode, t3));
796 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
797
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);
804
805 emit_insn (gen_mul<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)));
809
810 riscv_expand_conditional_branch (operands[3], NE, hp, lp);
811 }
812
813 DONE;
814})
815
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"
822{
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);
831
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];
840
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)));
846
847 riscv_expand_conditional_branch (operands[3], NE, t8, const0_rtx);
848 }
849 else
850 {
851 rtx hp = gen_reg_rtx (<MODE>mode);
852
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]));
855
856 riscv_expand_conditional_branch (operands[3], NE, hp, const0_rtx);
857 }
858
859 DONE;
860})
861
09cae750 862(define_insn "*mulsi3_extended"
248710c4 863 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 864 (sign_extend:DI
248710c4
KC
865 (mult:SI (match_operand:SI 1 "register_operand" " r")
866 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
867 "TARGET_MUL && TARGET_64BIT"
868 "mulw\t%0,%1,%2"
869 [(set_attr "type" "imul")
870 (set_attr "mode" "SI")])
871
872(define_insn "*mulsi3_extended2"
248710c4 873 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 874 (sign_extend:DI
7ac4dfec
MC
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"))])))]
09cae750
PD
878 "TARGET_MUL && TARGET_64BIT"
879 "mulw\t%0,%1,%2"
880 [(set_attr "type" "imul")
881 (set_attr "mode" "SI")])
882
883;;
884;; ........................
885;;
886;; MULTIPLICATION HIGH-PART
887;;
888;; ........................
889;;
890
891
892(define_expand "<u>mulditi3"
248710c4 893 [(set (match_operand:TI 0 "register_operand")
09cae750
PD
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"
897{
898 rtx low = gen_reg_rtx (DImode);
899 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
900
901 rtx high = gen_reg_rtx (DImode);
902 emit_insn (gen_<u>muldi3_highpart (high, operands[1], operands[2]));
903
904 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
905 emit_move_insn (gen_highpart (DImode, operands[0]), high);
906 DONE;
907})
908
909(define_insn "<u>muldi3_highpart"
248710c4 910 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750
PD
911 (truncate:DI
912 (lshiftrt:TI
913 (mult:TI (any_extend:TI
248710c4 914 (match_operand:DI 1 "register_operand" " r"))
09cae750 915 (any_extend:TI
248710c4 916 (match_operand:DI 2 "register_operand" " r")))
09cae750
PD
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")])
922
923(define_expand "usmulditi3"
248710c4 924 [(set (match_operand:TI 0 "register_operand")
09cae750
PD
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"
928{
929 rtx low = gen_reg_rtx (DImode);
930 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
931
932 rtx high = gen_reg_rtx (DImode);
933 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2]));
934
935 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
936 emit_move_insn (gen_highpart (DImode, operands[0]), high);
937 DONE;
938})
939
940(define_insn "usmuldi3_highpart"
248710c4 941 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750
PD
942 (truncate:DI
943 (lshiftrt:TI
944 (mult:TI (zero_extend:TI
248710c4 945 (match_operand:DI 1 "register_operand" "r"))
09cae750 946 (sign_extend:TI
248710c4 947 (match_operand:DI 2 "register_operand" " r")))
09cae750
PD
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")])
953
954(define_expand "<u>mulsidi3"
248710c4 955 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 956 (mult:DI (any_extend:DI
248710c4 957 (match_operand:SI 1 "register_operand" " r"))
09cae750 958 (any_extend:DI
248710c4 959 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
960 "TARGET_MUL && !TARGET_64BIT"
961{
962 rtx temp = gen_reg_rtx (SImode);
963 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
964 emit_insn (gen_<u>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;
968})
969
970(define_insn "<u>mulsi3_highpart"
248710c4 971 [(set (match_operand:SI 0 "register_operand" "=r")
09cae750
PD
972 (truncate:SI
973 (lshiftrt:DI
974 (mult:DI (any_extend:DI
248710c4 975 (match_operand:SI 1 "register_operand" " r"))
09cae750 976 (any_extend:DI
248710c4 977 (match_operand:SI 2 "register_operand" " r")))
09cae750
PD
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")])
983
984
985(define_expand "usmulsidi3"
248710c4 986 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 987 (mult:DI (zero_extend:DI
248710c4 988 (match_operand:SI 1 "register_operand" " r"))
09cae750 989 (sign_extend:DI
248710c4 990 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
991 "TARGET_MUL && !TARGET_64BIT"
992{
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;
999})
1000
1001(define_insn "usmulsi3_highpart"
248710c4 1002 [(set (match_operand:SI 0 "register_operand" "=r")
09cae750
PD
1003 (truncate:SI
1004 (lshiftrt:DI
1005 (mult:DI (zero_extend:DI
248710c4 1006 (match_operand:SI 1 "register_operand" " r"))
09cae750 1007 (sign_extend:DI
248710c4 1008 (match_operand:SI 2 "register_operand" " r")))
09cae750
PD
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")])
1014
1015;;
1016;; ....................
1017;;
1018;; DIVISION and REMAINDER
1019;;
1020;; ....................
1021;;
1022
1023(define_insn "<optab>si3"
248710c4
KC
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")))]
09cae750 1027 "TARGET_DIV"
0791ac18 1028 { return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2"; }
09cae750
PD
1029 [(set_attr "type" "idiv")
1030 (set_attr "mode" "SI")])
1031
1032(define_insn "<optab>di3"
248710c4
KC
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")))]
09cae750 1036 "TARGET_DIV && TARGET_64BIT"
0791ac18 1037 "<insn>%i2\t%0,%1,%2"
09cae750
PD
1038 [(set_attr "type" "idiv")
1039 (set_attr "mode" "DI")])
1040
1041(define_insn "*<optab>si3_extended"
248710c4 1042 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 1043 (sign_extend:DI
248710c4
KC
1044 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1045 (match_operand:SI 2 "register_operand" " r"))))]
09cae750 1046 "TARGET_DIV && TARGET_64BIT"
0791ac18 1047 "<insn>%i2w\t%0,%1,%2"
09cae750
PD
1048 [(set_attr "type" "idiv")
1049 (set_attr "mode" "DI")])
1050
1051(define_insn "div<mode>3"
248710c4
KC
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")))]
09cae750
PD
1055 "TARGET_HARD_FLOAT && TARGET_FDIV"
1056 "fdiv.<fmt>\t%0,%1,%2"
1057 [(set_attr "type" "fdiv")
1058 (set_attr "mode" "<UNITMODE>")])
1059
1060;;
1061;; ....................
1062;;
1063;; SQUARE ROOT
1064;;
1065;; ....................
1066
1067(define_insn "sqrt<mode>2"
248710c4
KC
1068 [(set (match_operand:ANYF 0 "register_operand" "=f")
1069 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
1070 "TARGET_HARD_FLOAT && TARGET_FDIV"
1071{
1072 return "fsqrt.<fmt>\t%0,%1";
1073}
1074 [(set_attr "type" "fsqrt")
1075 (set_attr "mode" "<UNITMODE>")])
1076
1077;; Floating point multiply accumulate instructions.
1078
1079;; a * b + c
1080(define_insn "fma<mode>4"
248710c4
KC
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")))]
09cae750
PD
1085 "TARGET_HARD_FLOAT"
1086 "fmadd.<fmt>\t%0,%1,%2,%3"
1087 [(set_attr "type" "fmadd")
1088 (set_attr "mode" "<UNITMODE>")])
1089
1090;; a * b - c
1091(define_insn "fms<mode>4"
248710c4
KC
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"))))]
09cae750
PD
1096 "TARGET_HARD_FLOAT"
1097 "fmsub.<fmt>\t%0,%1,%2,%3"
1098 [(set_attr "type" "fmadd")
1099 (set_attr "mode" "<UNITMODE>")])
1100
1101;; -a * b - c
1102(define_insn "fnms<mode>4"
248710c4
KC
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"))))]
09cae750
PD
1108 "TARGET_HARD_FLOAT"
1109 "fnmadd.<fmt>\t%0,%1,%2,%3"
1110 [(set_attr "type" "fmadd")
1111 (set_attr "mode" "<UNITMODE>")])
1112
1113;; -a * b + c
1114(define_insn "fnma<mode>4"
248710c4
KC
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")))]
09cae750
PD
1120 "TARGET_HARD_FLOAT"
1121 "fnmsub.<fmt>\t%0,%1,%2,%3"
1122 [(set_attr "type" "fmadd")
1123 (set_attr "mode" "<UNITMODE>")])
1124
1125;; -(-a * b - c), modulo signed zeros
1126(define_insn "*fma<mode>4"
248710c4
KC
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")))))]
09cae750
PD
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>")])
1137
1138;; -(-a * b + c), modulo signed zeros
1139(define_insn "*fms<mode>4"
248710c4
KC
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"))))]
09cae750
PD
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>")])
1150
1151;; -(a * b + c), modulo signed zeros
1152(define_insn "*fnms<mode>4"
248710c4
KC
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"))))]
09cae750
PD
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>")])
1163
1164;; -(a * b - c), modulo signed zeros
1165(define_insn "*fnma<mode>4"
248710c4
KC
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")))))]
09cae750
PD
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>")])
1176
1177;;
1178;; ....................
1179;;
1180;; SIGN INJECTION
1181;;
1182;; ....................
1183
1184(define_insn "abs<mode>2"
248710c4
KC
1185 [(set (match_operand:ANYF 0 "register_operand" "=f")
1186 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
1187 "TARGET_HARD_FLOAT"
1188 "fabs.<fmt>\t%0,%1"
1189 [(set_attr "type" "fmove")
1190 (set_attr "mode" "<UNITMODE>")])
1191
1192(define_insn "copysign<mode>3"
248710c4
KC
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")]
09cae750
PD
1196 UNSPEC_COPYSIGN))]
1197 "TARGET_HARD_FLOAT"
1198 "fsgnj.<fmt>\t%0,%1,%2"
1199 [(set_attr "type" "fmove")
1200 (set_attr "mode" "<UNITMODE>")])
1201
1202(define_insn "neg<mode>2"
248710c4
KC
1203 [(set (match_operand:ANYF 0 "register_operand" "=f")
1204 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
1205 "TARGET_HARD_FLOAT"
1206 "fneg.<fmt>\t%0,%1"
1207 [(set_attr "type" "fmove")
1208 (set_attr "mode" "<UNITMODE>")])
1209
1210;;
1211;; ....................
1212;;
1213;; MIN/MAX
1214;;
1215;; ....................
1216
1217(define_insn "smin<mode>3"
248710c4
KC
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")))]
09cae750
PD
1221 "TARGET_HARD_FLOAT"
1222 "fmin.<fmt>\t%0,%1,%2"
1223 [(set_attr "type" "fmove")
1224 (set_attr "mode" "<UNITMODE>")])
1225
1226(define_insn "smax<mode>3"
248710c4
KC
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")))]
09cae750
PD
1230 "TARGET_HARD_FLOAT"
1231 "fmax.<fmt>\t%0,%1,%2"
1232 [(set_attr "type" "fmove")
1233 (set_attr "mode" "<UNITMODE>")])
1234
1235;;
1236;; ....................
1237;;
1238;; LOGICAL
1239;;
1240;; ....................
1241;;
1242
1243;; For RV64, we don't expose the SImode operations to the rtl expanders,
1244;; but SImode versions exist for combine.
1245
1246(define_insn "<optab><mode>3"
248710c4 1247 [(set (match_operand:X 0 "register_operand" "=r,r")
09cae750 1248 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
248710c4 1249 (match_operand:X 2 "arith_operand" " r,I")))]
09cae750 1250 ""
0791ac18 1251 "<insn>%i2\t%0,%1,%2"
09cae750
PD
1252 [(set_attr "type" "logical")
1253 (set_attr "mode" "<MODE>")])
1254
1255(define_insn "*<optab>si3_internal"
248710c4 1256 [(set (match_operand:SI 0 "register_operand" "=r,r")
09cae750 1257 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
248710c4 1258 (match_operand:SI 2 "arith_operand" " r,I")))]
09cae750 1259 "TARGET_64BIT"
0791ac18 1260 "<insn>%i2\t%0,%1,%2"
09cae750
PD
1261 [(set_attr "type" "logical")
1262 (set_attr "mode" "SI")])
1263
1264(define_insn "one_cmpl<mode>2"
248710c4
KC
1265 [(set (match_operand:X 0 "register_operand" "=r")
1266 (not:X (match_operand:X 1 "register_operand" " r")))]
09cae750
PD
1267 ""
1268 "not\t%0,%1"
1269 [(set_attr "type" "logical")
1270 (set_attr "mode" "<MODE>")])
1271
1272(define_insn "*one_cmplsi2_internal"
248710c4
KC
1273 [(set (match_operand:SI 0 "register_operand" "=r")
1274 (not:SI (match_operand:SI 1 "register_operand" " r")))]
09cae750
PD
1275 "TARGET_64BIT"
1276 "not\t%0,%1"
1277 [(set_attr "type" "logical")
1278 (set_attr "mode" "SI")])
1279
1280;;
1281;; ....................
1282;;
1283;; TRUNCATION
1284;;
1285;; ....................
1286
1287(define_insn "truncdfsf2"
248710c4
KC
1288 [(set (match_operand:SF 0 "register_operand" "=f")
1289 (float_truncate:SF
1290 (match_operand:DF 1 "register_operand" " f")))]
09cae750
PD
1291 "TARGET_DOUBLE_FLOAT"
1292 "fcvt.s.d\t%0,%1"
1293 [(set_attr "type" "fcvt")
1294 (set_attr "mode" "SF")])
1295
1296;;
1297;; ....................
1298;;
1299;; ZERO EXTENSION
1300;;
1301;; ....................
1302
1303;; Extension insns.
1304
1305(define_insn_and_split "zero_extendsidi2"
248710c4
KC
1306 [(set (match_operand:DI 0 "register_operand" "=r,r")
1307 (zero_extend:DI
1308 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1309 "TARGET_64BIT"
1310 "@
1311 #
1312 lwu\t%0,%1"
36ec3f57
JJ
1313 "&& reload_completed
1314 && REG_P (operands[1])
1315 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1316 [(set (match_dup 0)
1317 (ashift:DI (match_dup 1) (const_int 32)))
1318 (set (match_dup 0)
1319 (lshiftrt:DI (match_dup 0) (const_int 32)))]
1320 { operands[1] = gen_lowpart (DImode, operands[1]); }
1321 [(set_attr "move_type" "shift_shift,load")
1322 (set_attr "mode" "DI")])
1323
1324(define_insn_and_split "zero_extendhi<GPR:mode>2"
248710c4
KC
1325 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1326 (zero_extend:GPR
1327 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1328 ""
1329 "@
1330 #
1331 lhu\t%0,%1"
36ec3f57
JJ
1332 "&& reload_completed
1333 && REG_P (operands[1])
1334 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1335 [(set (match_dup 0)
1336 (ashift:GPR (match_dup 1) (match_dup 2)))
1337 (set (match_dup 0)
1338 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1339 {
1340 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1341 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1342 }
1343 [(set_attr "move_type" "shift_shift,load")
1344 (set_attr "mode" "<GPR:MODE>")])
1345
1346(define_insn "zero_extendqi<SUPERQI:mode>2"
248710c4 1347 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1348 (zero_extend:SUPERQI
248710c4 1349 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1350 ""
1351 "@
0791ac18 1352 andi\t%0,%1,0xff
09cae750
PD
1353 lbu\t%0,%1"
1354 [(set_attr "move_type" "andi,load")
1355 (set_attr "mode" "<SUPERQI:MODE>")])
1356
1357;;
1358;; ....................
1359;;
1360;; SIGN EXTENSION
1361;;
1362;; ....................
1363
1364(define_insn "extendsidi2"
248710c4
KC
1365 [(set (match_operand:DI 0 "register_operand" "=r,r")
1366 (sign_extend:DI
1367 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1368 "TARGET_64BIT"
1369 "@
1370 sext.w\t%0,%1
1371 lw\t%0,%1"
1372 [(set_attr "move_type" "move,load")
1373 (set_attr "mode" "DI")])
1374
1375(define_insn_and_split "extend<SHORT:mode><SUPERQI:mode>2"
248710c4 1376 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1377 (sign_extend:SUPERQI
248710c4 1378 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1379 ""
1380 "@
1381 #
1382 l<SHORT:size>\t%0,%1"
36ec3f57
JJ
1383 "&& reload_completed
1384 && REG_P (operands[1])
1385 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1386 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1387 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
1388{
1389 operands[0] = gen_lowpart (SImode, operands[0]);
1390 operands[1] = gen_lowpart (SImode, operands[1]);
1391 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1392 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1393}
1394 [(set_attr "move_type" "shift_shift,load")
1395 (set_attr "mode" "SI")])
1396
1397(define_insn "extendsfdf2"
248710c4
KC
1398 [(set (match_operand:DF 0 "register_operand" "=f")
1399 (float_extend:DF
1400 (match_operand:SF 1 "register_operand" " f")))]
09cae750
PD
1401 "TARGET_DOUBLE_FLOAT"
1402 "fcvt.d.s\t%0,%1"
1403 [(set_attr "type" "fcvt")
1404 (set_attr "mode" "DF")])
1405
1406;;
1407;; ....................
1408;;
1409;; CONVERSIONS
1410;;
1411;; ....................
1412
1413(define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
248710c4
KC
1414 [(set (match_operand:GPR 0 "register_operand" "=r")
1415 (fix:GPR
1416 (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
1417 "TARGET_HARD_FLOAT"
1418 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
1419 [(set_attr "type" "fcvt")
1420 (set_attr "mode" "<ANYF:MODE>")])
1421
1422(define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2"
248710c4
KC
1423 [(set (match_operand:GPR 0 "register_operand" "=r")
1424 (unsigned_fix:GPR
1425 (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
1426 "TARGET_HARD_FLOAT"
1427 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
1428 [(set_attr "type" "fcvt")
1429 (set_attr "mode" "<ANYF:MODE>")])
1430
1431(define_insn "float<GPR:mode><ANYF:mode>2"
248710c4
KC
1432 [(set (match_operand:ANYF 0 "register_operand" "= f")
1433 (float:ANYF
1434 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
09cae750
PD
1435 "TARGET_HARD_FLOAT"
1436 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
1437 [(set_attr "type" "fcvt")
1438 (set_attr "mode" "<ANYF:MODE>")])
1439
1440(define_insn "floatuns<GPR:mode><ANYF:mode>2"
248710c4
KC
1441 [(set (match_operand:ANYF 0 "register_operand" "= f")
1442 (unsigned_float:ANYF
1443 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
09cae750
PD
1444 "TARGET_HARD_FLOAT"
1445 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
1446 [(set_attr "type" "fcvt")
1447 (set_attr "mode" "<ANYF:MODE>")])
1448
1449(define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2"
248710c4
KC
1450 [(set (match_operand:GPR 0 "register_operand" "=r")
1451 (unspec:GPR
1452 [(match_operand:ANYF 1 "register_operand" " f")]
1453 RINT))]
09cae750
PD
1454 "TARGET_HARD_FLOAT"
1455 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
1456 [(set_attr "type" "fcvt")
1457 (set_attr "mode" "<ANYF:MODE>")])
1458
1459;;
1460;; ....................
1461;;
1462;; DATA MOVEMENT
1463;;
1464;; ....................
1465
1466;; Lower-level instructions for loading an address from the GOT.
1467;; We could use MEMs, but an unspec gives more optimization
1468;; opportunities.
1469
1470(define_insn "got_load<mode>"
248710c4
KC
1471 [(set (match_operand:P 0 "register_operand" "=r")
1472 (unspec:P
1473 [(match_operand:P 1 "symbolic_operand" "")]
1474 UNSPEC_LOAD_GOT))]
09cae750
PD
1475 ""
1476 "la\t%0,%1"
1477 [(set_attr "got" "load")
1478 (set_attr "mode" "<MODE>")])
1479
1480(define_insn "tls_add_tp_le<mode>"
248710c4
KC
1481 [(set (match_operand:P 0 "register_operand" "=r")
1482 (unspec:P
1483 [(match_operand:P 1 "register_operand" "r")
1484 (match_operand:P 2 "register_operand" "r")
1485 (match_operand:P 3 "symbolic_operand" "")]
1486 UNSPEC_TLS_LE))]
09cae750
PD
1487 ""
1488 "add\t%0,%1,%2,%%tprel_add(%3)"
1489 [(set_attr "type" "arith")
1490 (set_attr "mode" "<MODE>")])
1491
1492(define_insn "got_load_tls_gd<mode>"
248710c4
KC
1493 [(set (match_operand:P 0 "register_operand" "=r")
1494 (unspec:P
1495 [(match_operand:P 1 "symbolic_operand" "")]
1496 UNSPEC_TLS_GD))]
09cae750
PD
1497 ""
1498 "la.tls.gd\t%0,%1"
1499 [(set_attr "got" "load")
1500 (set_attr "mode" "<MODE>")])
1501
1502(define_insn "got_load_tls_ie<mode>"
248710c4
KC
1503 [(set (match_operand:P 0 "register_operand" "=r")
1504 (unspec:P
1505 [(match_operand:P 1 "symbolic_operand" "")]
1506 UNSPEC_TLS_IE))]
09cae750
PD
1507 ""
1508 "la.tls.ie\t%0,%1"
1509 [(set_attr "got" "load")
1510 (set_attr "mode" "<MODE>")])
1511
1512(define_insn "auipc<mode>"
248710c4
KC
1513 [(set (match_operand:P 0 "register_operand" "=r")
1514 (unspec:P
1515 [(match_operand:P 1 "symbolic_operand" "")
09cae750
PD
1516 (match_operand:P 2 "const_int_operand")
1517 (pc)]
248710c4 1518 UNSPEC_AUIPC))]
09cae750
PD
1519 ""
1520 ".LA%2: auipc\t%0,%h1"
88108b27 1521 [(set_attr "type" "auipc")
09cae750
PD
1522 (set_attr "cannot_copy" "yes")])
1523
1524;; Instructions for adding the low 12 bits of an address to a register.
1525;; Operand 2 is the address: riscv_print_operand works out which relocation
1526;; should be applied.
1527
1528(define_insn "*low<mode>"
248710c4
KC
1529 [(set (match_operand:P 0 "register_operand" "=r")
1530 (lo_sum:P (match_operand:P 1 "register_operand" " r")
09cae750
PD
1531 (match_operand:P 2 "symbolic_operand" "")))]
1532 ""
1533 "addi\t%0,%1,%R2"
1534 [(set_attr "type" "arith")
1535 (set_attr "mode" "<MODE>")])
1536
1537;; Allow combine to split complex const_int load sequences, using operand 2
1538;; to store the intermediate results. See move_operand for details.
1539(define_split
1540 [(set (match_operand:GPR 0 "register_operand")
1541 (match_operand:GPR 1 "splittable_const_int_operand"))
1542 (clobber (match_operand:GPR 2 "register_operand"))]
1543 ""
1544 [(const_int 0)]
1545{
51175507 1546 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
a923a463 1547 <GPR:MODE>mode, TRUE);
09cae750
PD
1548 DONE;
1549})
1550
1551;; Likewise, for symbolic operands.
1552(define_split
1553 [(set (match_operand:P 0 "register_operand")
1554 (match_operand:P 1))
1555 (clobber (match_operand:P 2 "register_operand"))]
a923a463 1556 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL, TRUE)"
09cae750
PD
1557 [(set (match_dup 0) (match_dup 3))]
1558{
1559 riscv_split_symbol (operands[2], operands[1],
a923a463 1560 MAX_MACHINE_MODE, &operands[3], TRUE);
09cae750
PD
1561})
1562
1563;; 64-bit integer moves
1564
1565(define_expand "movdi"
1566 [(set (match_operand:DI 0 "")
1567 (match_operand:DI 1 ""))]
1568 ""
1569{
1570 if (riscv_legitimize_move (DImode, operands[0], operands[1]))
1571 DONE;
1572})
1573
1574(define_insn "*movdi_32bit"
1575 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m")
248710c4 1576 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))]
09cae750
PD
1577 "!TARGET_64BIT
1578 && (register_operand (operands[0], DImode)
1579 || reg_or_0_operand (operands[1], DImode))"
1580 { return riscv_output_move (operands[0], operands[1]); }
1581 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1582 (set_attr "mode" "DI")])
1583
1584(define_insn "*movdi_64bit"
248710c4
KC
1585 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m")
1586 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))]
09cae750
PD
1587 "TARGET_64BIT
1588 && (register_operand (operands[0], DImode)
1589 || reg_or_0_operand (operands[1], DImode))"
1590 { return riscv_output_move (operands[0], operands[1]); }
1591 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1592 (set_attr "mode" "DI")])
1593
1594;; 32-bit Integer moves
1595
1596(define_expand "mov<mode>"
1597 [(set (match_operand:MOVE32 0 "")
1598 (match_operand:MOVE32 1 ""))]
1599 ""
1600{
1601 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
1602 DONE;
1603})
1604
1605(define_insn "*movsi_internal"
248710c4
KC
1606 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m")
1607 (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f"))]
09cae750
PD
1608 "(register_operand (operands[0], SImode)
1609 || reg_or_0_operand (operands[1], SImode))"
1610 { return riscv_output_move (operands[0], operands[1]); }
1611 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
1612 (set_attr "mode" "SI")])
1613
1614;; 16-bit Integer moves
1615
1616;; Unlike most other insns, the move insns can't be split with
1617;; different predicates, because register spilling and other parts of
1618;; the compiler, have memoized the insn number already.
1619;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
1620
1621(define_expand "movhi"
1622 [(set (match_operand:HI 0 "")
1623 (match_operand:HI 1 ""))]
1624 ""
1625{
1626 if (riscv_legitimize_move (HImode, operands[0], operands[1]))
1627 DONE;
1628})
1629
1630(define_insn "*movhi_internal"
248710c4
KC
1631 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1632 (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f"))]
09cae750
PD
1633 "(register_operand (operands[0], HImode)
1634 || reg_or_0_operand (operands[1], HImode))"
1635 { return riscv_output_move (operands[0], operands[1]); }
1636 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1637 (set_attr "mode" "HI")])
1638
1639;; HImode constant generation; see riscv_move_integer for details.
bb149ca2
RS
1640;; si+si->hi without truncation is legal because of
1641;; TARGET_TRULY_NOOP_TRUNCATION.
09cae750
PD
1642
1643(define_insn "*add<mode>hi3"
248710c4
KC
1644 [(set (match_operand:HI 0 "register_operand" "=r,r")
1645 (plus:HI (match_operand:HISI 1 "register_operand" " r,r")
1646 (match_operand:HISI 2 "arith_operand" " r,I")))]
09cae750 1647 ""
0791ac18 1648 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
09cae750
PD
1649 [(set_attr "type" "arith")
1650 (set_attr "mode" "HI")])
1651
1652(define_insn "*xor<mode>hi3"
248710c4
KC
1653 [(set (match_operand:HI 0 "register_operand" "=r,r")
1654 (xor:HI (match_operand:HISI 1 "register_operand" " r,r")
1655 (match_operand:HISI 2 "arith_operand" " r,I")))]
09cae750 1656 ""
0791ac18 1657 "xor%i2\t%0,%1,%2"
09cae750
PD
1658 [(set_attr "type" "logical")
1659 (set_attr "mode" "HI")])
1660
1661;; 8-bit Integer moves
1662
1663(define_expand "movqi"
1664 [(set (match_operand:QI 0 "")
1665 (match_operand:QI 1 ""))]
1666 ""
1667{
1668 if (riscv_legitimize_move (QImode, operands[0], operands[1]))
1669 DONE;
1670})
1671
1672(define_insn "*movqi_internal"
248710c4
KC
1673 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1674 (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f"))]
09cae750
PD
1675 "(register_operand (operands[0], QImode)
1676 || reg_or_0_operand (operands[1], QImode))"
1677 { return riscv_output_move (operands[0], operands[1]); }
1678 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1679 (set_attr "mode" "QI")])
1680
1681;; 32-bit floating point moves
1682
1683(define_expand "movsf"
1684 [(set (match_operand:SF 0 "")
1685 (match_operand:SF 1 ""))]
1686 ""
1687{
1688 if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
1689 DONE;
1690})
1691
1692(define_insn "*movsf_hardfloat"
248710c4
KC
1693 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1694 (match_operand:SF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
09cae750
PD
1695 "TARGET_HARD_FLOAT
1696 && (register_operand (operands[0], SFmode)
1697 || reg_or_0_operand (operands[1], SFmode))"
1698 { return riscv_output_move (operands[0], operands[1]); }
1699 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1700 (set_attr "mode" "SF")])
1701
1702(define_insn "*movsf_softfloat"
248710c4
KC
1703 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
1704 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
09cae750
PD
1705 "!TARGET_HARD_FLOAT
1706 && (register_operand (operands[0], SFmode)
1707 || reg_or_0_operand (operands[1], SFmode))"
1708 { return riscv_output_move (operands[0], operands[1]); }
1709 [(set_attr "move_type" "move,load,store")
1710 (set_attr "mode" "SF")])
1711
1712;; 64-bit floating point moves
1713
1714(define_expand "movdf"
1715 [(set (match_operand:DF 0 "")
1716 (match_operand:DF 1 ""))]
1717 ""
1718{
1719 if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
1720 DONE;
1721})
1722
1723;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
1724;; (However, we can still use fcvt.d.w to zero a floating-point register.)
1725(define_insn "*movdf_hardfloat_rv32"
248710c4
KC
1726 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m")
1727 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))]
09cae750
PD
1728 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
1729 && (register_operand (operands[0], DFmode)
1730 || reg_or_0_operand (operands[1], DFmode))"
1731 { return riscv_output_move (operands[0], operands[1]); }
1732 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store")
1733 (set_attr "mode" "DF")])
1734
1735(define_insn "*movdf_hardfloat_rv64"
248710c4
KC
1736 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1737 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
09cae750
PD
1738 "TARGET_64BIT && TARGET_DOUBLE_FLOAT
1739 && (register_operand (operands[0], DFmode)
1740 || reg_or_0_operand (operands[1], DFmode))"
1741 { return riscv_output_move (operands[0], operands[1]); }
1742 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1743 (set_attr "mode" "DF")])
1744
1745(define_insn "*movdf_softfloat"
248710c4
KC
1746 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
1747 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
09cae750
PD
1748 "!TARGET_DOUBLE_FLOAT
1749 && (register_operand (operands[0], DFmode)
1750 || reg_or_0_operand (operands[1], DFmode))"
1751 { return riscv_output_move (operands[0], operands[1]); }
1752 [(set_attr "move_type" "move,load,store")
1753 (set_attr "mode" "DF")])
1754
1755(define_split
1756 [(set (match_operand:MOVE64 0 "nonimmediate_operand")
1757 (match_operand:MOVE64 1 "move_operand"))]
1758 "reload_completed
1759 && riscv_split_64bit_move_p (operands[0], operands[1])"
1760 [(const_int 0)]
1761{
1762 riscv_split_doubleword_move (operands[0], operands[1]);
1763 DONE;
1764})
1765
76715c32 1766(define_expand "cpymemsi"
6ed01e6b
AW
1767 [(parallel [(set (match_operand:BLK 0 "general_operand")
1768 (match_operand:BLK 1 "general_operand"))
1769 (use (match_operand:SI 2 ""))
1770 (use (match_operand:SI 3 "const_int_operand"))])]
1771 ""
1772{
1773 if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
1774 DONE;
1775 else
1776 FAIL;
1777})
1778
09cae750
PD
1779;; Expand in-line code to clear the instruction cache between operand[0] and
1780;; operand[1].
1781(define_expand "clear_cache"
1782 [(match_operand 0 "pmode_register_operand")
1783 (match_operand 1 "pmode_register_operand")]
1784 ""
1785{
f1bdc63a
AW
1786#ifdef ICACHE_FLUSH_FUNC
1787 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC),
1788 LCT_NORMAL, VOIDmode, operands[0], Pmode,
1789 operands[1], Pmode, const0_rtx, Pmode);
1790#else
b03be74b
KC
1791 if (TARGET_ZIFENCEI)
1792 emit_insn (gen_fence_i ());
f1bdc63a 1793#endif
09cae750
PD
1794 DONE;
1795})
1796
1797(define_insn "fence"
1798 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
1799 ""
1800 "%|fence%-")
1801
1802(define_insn "fence_i"
1803 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
b03be74b 1804 "TARGET_ZIFENCEI"
09cae750
PD
1805 "fence.i")
1806
1807;;
1808;; ....................
1809;;
1810;; SHIFTS
1811;;
1812;; ....................
1813
b7ef9225
JW
1814;; Use a QImode shift count, to avoid generating sign or zero extend
1815;; instructions for shift counts, and to avoid dropping subregs.
1816;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
1817;; defined, but use of that is discouraged.
1818
09cae750 1819(define_insn "<optab>si3"
248710c4
KC
1820 [(set (match_operand:SI 0 "register_operand" "= r")
1821 (any_shift:SI
1822 (match_operand:SI 1 "register_operand" " r")
b7ef9225 1823 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
1824 ""
1825{
1826 if (GET_CODE (operands[2]) == CONST_INT)
1827 operands[2] = GEN_INT (INTVAL (operands[2])
1828 & (GET_MODE_BITSIZE (SImode) - 1));
1829
0791ac18 1830 return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2";
09cae750
PD
1831}
1832 [(set_attr "type" "shift")
1833 (set_attr "mode" "SI")])
1834
110fb19f 1835(define_insn_and_split "*<optab>si3_mask"
b7ef9225
JW
1836 [(set (match_operand:SI 0 "register_operand" "= r")
1837 (any_shift:SI
1838 (match_operand:SI 1 "register_operand" " r")
7ac4dfec
MC
1839 (match_operator 4 "subreg_lowpart_operator"
1840 [(and:SI
1841 (match_operand:SI 2 "register_operand" "r")
1842 (match_operand 3 "const_int_operand"))])))]
b7ef9225
JW
1843 "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1844 == GET_MODE_BITSIZE (SImode)-1"
1845 "#"
1846 "&& 1"
1847 [(set (match_dup 0)
1848 (any_shift:SI (match_dup 1)
1849 (match_dup 2)))]
1850 "operands[2] = gen_lowpart (QImode, operands[2]);"
1851 [(set_attr "type" "shift")
1852 (set_attr "mode" "SI")])
1853
110fb19f 1854(define_insn_and_split "*<optab>si3_mask_1"
b7ef9225
JW
1855 [(set (match_operand:SI 0 "register_operand" "= r")
1856 (any_shift:SI
1857 (match_operand:SI 1 "register_operand" " r")
7ac4dfec
MC
1858 (match_operator 4 "subreg_lowpart_operator"
1859 [(and:DI
1860 (match_operand:DI 2 "register_operand" "r")
1861 (match_operand 3 "const_int_operand"))])))]
b7ef9225
JW
1862 "TARGET_64BIT
1863 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1864 == GET_MODE_BITSIZE (SImode)-1"
1865 "#"
1866 "&& 1"
1867 [(set (match_dup 0)
1868 (any_shift:SI (match_dup 1)
1869 (match_dup 2)))]
1870 "operands[2] = gen_lowpart (QImode, operands[2]);"
1871 [(set_attr "type" "shift")
1872 (set_attr "mode" "SI")])
1873
09cae750 1874(define_insn "<optab>di3"
248710c4
KC
1875 [(set (match_operand:DI 0 "register_operand" "= r")
1876 (any_shift:DI
1877 (match_operand:DI 1 "register_operand" " r")
b7ef9225 1878 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
1879 "TARGET_64BIT"
1880{
1881 if (GET_CODE (operands[2]) == CONST_INT)
1882 operands[2] = GEN_INT (INTVAL (operands[2])
1883 & (GET_MODE_BITSIZE (DImode) - 1));
1884
0791ac18 1885 return "<insn>%i2\t%0,%1,%2";
09cae750
PD
1886}
1887 [(set_attr "type" "shift")
1888 (set_attr "mode" "DI")])
1889
110fb19f 1890(define_insn_and_split "*<optab>di3_mask"
b7ef9225
JW
1891 [(set (match_operand:DI 0 "register_operand" "= r")
1892 (any_shift:DI
1893 (match_operand:DI 1 "register_operand" " r")
7ac4dfec
MC
1894 (match_operator 4 "subreg_lowpart_operator"
1895 [(and:SI
1896 (match_operand:SI 2 "register_operand" "r")
1897 (match_operand 3 "const_int_operand"))])))]
b7ef9225
JW
1898 "TARGET_64BIT
1899 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1900 == GET_MODE_BITSIZE (DImode)-1"
1901 "#"
1902 "&& 1"
1903 [(set (match_dup 0)
1904 (any_shift:DI (match_dup 1)
1905 (match_dup 2)))]
1906 "operands[2] = gen_lowpart (QImode, operands[2]);"
1907 [(set_attr "type" "shift")
1908 (set_attr "mode" "DI")])
1909
110fb19f 1910(define_insn_and_split "*<optab>di3_mask_1"
b7ef9225
JW
1911 [(set (match_operand:DI 0 "register_operand" "= r")
1912 (any_shift:DI
1913 (match_operand:DI 1 "register_operand" " r")
7ac4dfec
MC
1914 (match_operator 4 "subreg_lowpart_operator"
1915 [(and:DI
1916 (match_operand:DI 2 "register_operand" "r")
1917 (match_operand 3 "const_int_operand"))])))]
b7ef9225
JW
1918 "TARGET_64BIT
1919 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1920 == GET_MODE_BITSIZE (DImode)-1"
1921 "#"
1922 "&& 1"
1923 [(set (match_dup 0)
1924 (any_shift:DI (match_dup 1)
1925 (match_dup 2)))]
1926 "operands[2] = gen_lowpart (QImode, operands[2]);"
1927 [(set_attr "type" "shift")
1928 (set_attr "mode" "DI")])
1929
09cae750 1930(define_insn "*<optab>si3_extend"
248710c4 1931 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 1932 (sign_extend:DI
248710c4 1933 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 1934 (match_operand:QI 2 "arith_operand" " rI"))))]
09cae750
PD
1935 "TARGET_64BIT"
1936{
1937 if (GET_CODE (operands[2]) == CONST_INT)
1938 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1939
0791ac18 1940 return "<insn>%i2w\t%0,%1,%2";
09cae750
PD
1941}
1942 [(set_attr "type" "shift")
1943 (set_attr "mode" "SI")])
1944
b7ef9225
JW
1945(define_insn_and_split "*<optab>si3_extend_mask"
1946 [(set (match_operand:DI 0 "register_operand" "= r")
1947 (sign_extend:DI
1948 (any_shift:SI
1949 (match_operand:SI 1 "register_operand" " r")
7ac4dfec
MC
1950 (match_operator 4 "subreg_lowpart_operator"
1951 [(and:SI
1952 (match_operand:SI 2 "register_operand" " r")
1953 (match_operand 3 "const_int_operand"))]))))]
b7ef9225
JW
1954 "TARGET_64BIT
1955 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1956 == GET_MODE_BITSIZE (SImode)-1"
1957 "#"
1958 "&& 1"
1959 [(set (match_dup 0)
1960 (sign_extend:DI
1961 (any_shift:SI (match_dup 1)
1962 (match_dup 2))))]
1963 "operands[2] = gen_lowpart (QImode, operands[2]);"
1964 [(set_attr "type" "shift")
1965 (set_attr "mode" "SI")])
1966
1967(define_insn_and_split "*<optab>si3_extend_mask_1"
1968 [(set (match_operand:DI 0 "register_operand" "= r")
1969 (sign_extend:DI
1970 (any_shift:SI
1971 (match_operand:SI 1 "register_operand" " r")
7ac4dfec
MC
1972 (match_operator 4 "subreg_lowpart_operator"
1973 [(and:DI
1974 (match_operand:DI 2 "register_operand" " r")
1975 (match_operand 3 "const_int_operand"))]))))]
b7ef9225
JW
1976 "TARGET_64BIT
1977 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1978 == GET_MODE_BITSIZE (SImode)-1"
1979 "#"
1980 "&& 1"
1981 [(set (match_dup 0)
1982 (sign_extend:DI
1983 (any_shift:SI (match_dup 1)
1984 (match_dup 2))))]
1985 "operands[2] = gen_lowpart (QImode, operands[2]);"
1986 [(set_attr "type" "shift")
1987 (set_attr "mode" "SI")])
1988
08539f3e
JW
1989;; Non-canonical, but can be formed by ree when combine is not successful at
1990;; producing one of the two canonical patterns below.
1991(define_insn "*lshrsi3_zero_extend_1"
1992 [(set (match_operand:DI 0 "register_operand" "=r")
1993 (zero_extend:DI
1994 (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 1995 (match_operand 2 "const_int_operand"))))]
08539f3e
JW
1996 "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
1997{
1998 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1999
2000 return "srliw\t%0,%1,%2";
2001}
2002 [(set_attr "type" "shift")
2003 (set_attr "mode" "SI")])
2004
2005;; Canonical form for a zero-extend of a logical right shift.
2006(define_insn "*lshrsi3_zero_extend_2"
2007 [(set (match_operand:DI 0 "register_operand" "=r")
2008 (zero_extract:DI (match_operand:DI 1 "register_operand" " r")
2009 (match_operand 2 "const_int_operand")
2010 (match_operand 3 "const_int_operand")))]
2011 "(TARGET_64BIT && (INTVAL (operands[3]) > 0)
2012 && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
2013{
2014 return "srliw\t%0,%1,%3";
2015}
2016 [(set_attr "type" "shift")
2017 (set_attr "mode" "SI")])
2018
2019;; Canonical form for a zero-extend of a logical right shift when the
2020;; shift count is 31.
2021(define_insn "*lshrsi3_zero_extend_3"
2022 [(set (match_operand:DI 0 "register_operand" "=r")
2023 (lt:DI (match_operand:SI 1 "register_operand" " r")
2024 (const_int 0)))]
2025 "TARGET_64BIT"
2026{
2027 return "srliw\t%0,%1,31";
2028}
2029 [(set_attr "type" "shift")
2030 (set_attr "mode" "SI")])
2031
666fdc46
JW
2032;; Handle AND with 2^N-1 for N from 12 to XLEN. This can be split into
2033;; two logical shifts. Otherwise it requires 3 instructions: lui,
2034;; xor/addi/srli, and.
36ec3f57
JJ
2035
2036;; Generating a temporary for the shift output gives better combiner results;
2037;; and also fixes a problem where op0 could be a paradoxical reg and shifting
2038;; by amounts larger than the size of the SUBREG_REG doesn't work.
666fdc46
JW
2039(define_split
2040 [(set (match_operand:GPR 0 "register_operand")
2041 (and:GPR (match_operand:GPR 1 "register_operand")
36ec3f57
JJ
2042 (match_operand:GPR 2 "p2m1_shift_operand")))
2043 (clobber (match_operand:GPR 3 "register_operand"))]
666fdc46 2044 ""
36ec3f57 2045 [(set (match_dup 3)
666fdc46
JW
2046 (ashift:GPR (match_dup 1) (match_dup 2)))
2047 (set (match_dup 0)
36ec3f57 2048 (lshiftrt:GPR (match_dup 3) (match_dup 2)))]
666fdc46 2049{
ace4317a
JW
2050 /* Op2 is a VOIDmode constant, so get the mode size from op1. */
2051 operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1]))
666fdc46
JW
2052 - exact_log2 (INTVAL (operands[2]) + 1));
2053})
ace4317a 2054
666fdc46
JW
2055;; Handle AND with 0xF...F0...0 where there are 32 to 63 zeros. This can be
2056;; split into two shifts. Otherwise it requires 3 instructions: li, sll, and.
2057(define_split
2058 [(set (match_operand:DI 0 "register_operand")
2059 (and:DI (match_operand:DI 1 "register_operand")
36ec3f57
JJ
2060 (match_operand:DI 2 "high_mask_shift_operand")))
2061 (clobber (match_operand:DI 3 "register_operand"))]
666fdc46 2062 "TARGET_64BIT"
36ec3f57 2063 [(set (match_dup 3)
666fdc46
JW
2064 (lshiftrt:DI (match_dup 1) (match_dup 2)))
2065 (set (match_dup 0)
36ec3f57 2066 (ashift:DI (match_dup 3) (match_dup 2)))]
666fdc46
JW
2067{
2068 operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2])));
2069})
2070
d5cdcd5c
JW
2071;; Handle SImode to DImode zero-extend combined with a left shift. This can
2072;; occur when unsigned int is used for array indexing. Split this into two
2073;; shifts. Otherwise we can get 3 shifts.
2074
2075(define_insn_and_split "zero_extendsidi2_shifted"
2076 [(set (match_operand:DI 0 "register_operand" "=r")
2077 (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
2078 (match_operand:QI 2 "immediate_operand" "I"))
2079 (match_operand 3 "immediate_operand" "")))
2080 (clobber (match_scratch:DI 4 "=&r"))]
2081 "TARGET_64BIT
2082 && ((INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff)"
2083 "#"
2084 "&& reload_completed"
2085 [(set (match_dup 4)
2086 (ashift:DI (match_dup 1) (const_int 32)))
2087 (set (match_dup 0)
2088 (lshiftrt:DI (match_dup 4) (match_dup 5)))]
2089 "operands[5] = GEN_INT (32 - (INTVAL (operands [2])));"
2090 [(set_attr "type" "shift")
2091 (set_attr "mode" "DI")])
2092
09cae750
PD
2093;;
2094;; ....................
2095;;
2096;; CONDITIONAL BRANCHES
2097;;
2098;; ....................
2099
2100;; Conditional branches
2101
4f475391 2102(define_insn "*branch<mode>"
09cae750
PD
2103 [(set (pc)
2104 (if_then_else
2105 (match_operator 1 "order_operator"
2106 [(match_operand:X 2 "register_operand" "r")
4f475391 2107 (match_operand:X 3 "reg_or_0_operand" "rJ")])
09cae750
PD
2108 (label_ref (match_operand 0 "" ""))
2109 (pc)))]
2110 ""
4f475391 2111 "b%C1\t%2,%z3,%0"
09cae750
PD
2112 [(set_attr "type" "branch")
2113 (set_attr "mode" "none")])
2114
4f475391
AW
2115;; Patterns for implementations that optimize short forward branches.
2116
2117(define_expand "mov<mode>cc"
2118 [(set (match_operand:GPR 0 "register_operand")
2119 (if_then_else:GPR (match_operand 1 "comparison_operator")
2120 (match_operand:GPR 2 "register_operand")
2121 (match_operand:GPR 3 "sfb_alu_operand")))]
2122 "TARGET_SFB_ALU"
2123{
2124 rtx cmp = operands[1];
2125 /* We only handle word mode integer compares for now. */
2126 if (GET_MODE (XEXP (cmp, 0)) != word_mode)
2127 FAIL;
2128 riscv_expand_conditional_move (operands[0], operands[2], operands[3],
2129 GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
2130 DONE;
2131})
2132
2133(define_insn "*mov<GPR:mode><X:mode>cc"
2134 [(set (match_operand:GPR 0 "register_operand" "=r,r")
2135 (if_then_else:GPR
2136 (match_operator 5 "order_operator"
2137 [(match_operand:X 1 "register_operand" "r,r")
2138 (match_operand:X 2 "reg_or_0_operand" "rJ,rJ")])
2139 (match_operand:GPR 3 "register_operand" "0,0")
2140 (match_operand:GPR 4 "sfb_alu_operand" "rJ,IL")))]
2141 "TARGET_SFB_ALU"
2142 "@
2143 b%C5 %1,%z2,1f; mv %0,%z4; 1: # movcc
2144 b%C5 %1,%z2,1f; li %0,%4; 1: # movcc"
2145 [(set_attr "length" "8")
2146 (set_attr "type" "sfb_alu")
2147 (set_attr "mode" "<GPR:MODE>")])
09cae750
PD
2148
2149;; Used to implement built-in functions.
2150(define_expand "condjump"
2151 [(set (pc)
2152 (if_then_else (match_operand 0)
2153 (label_ref (match_operand 1))
2154 (pc)))])
2155
e1fcf14f 2156(define_expand "@cbranch<mode>4"
09cae750
PD
2157 [(set (pc)
2158 (if_then_else (match_operator 0 "comparison_operator"
248710c4
KC
2159 [(match_operand:BR 1 "register_operand")
2160 (match_operand:BR 2 "nonmemory_operand")])
09cae750
PD
2161 (label_ref (match_operand 3 ""))
2162 (pc)))]
2163 ""
2164{
2165 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2166 operands[1], operands[2]);
2167 DONE;
2168})
2169
e1fcf14f 2170(define_expand "@cbranch<mode>4"
09cae750
PD
2171 [(set (pc)
2172 (if_then_else (match_operator 0 "fp_branch_comparison"
2173 [(match_operand:ANYF 1 "register_operand")
2174 (match_operand:ANYF 2 "register_operand")])
2175 (label_ref (match_operand 3 ""))
2176 (pc)))]
2177 "TARGET_HARD_FLOAT"
2178{
2179 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2180 operands[1], operands[2]);
2181 DONE;
2182})
2183
2184(define_insn_and_split "*branch_on_bit<X:mode>"
2185 [(set (pc)
2186 (if_then_else
248710c4
KC
2187 (match_operator 0 "equality_operator"
2188 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2189 (const_int 1)
2190 (match_operand 3 "branch_on_bit_operand"))
2191 (const_int 0)])
2192 (label_ref (match_operand 1))
2193 (pc)))
09cae750
PD
2194 (clobber (match_scratch:X 4 "=&r"))]
2195 ""
2196 "#"
2197 "reload_completed"
2198 [(set (match_dup 4)
2199 (ashift:X (match_dup 2) (match_dup 3)))
2200 (set (pc)
2201 (if_then_else
248710c4
KC
2202 (match_op_dup 0 [(match_dup 4) (const_int 0)])
2203 (label_ref (match_operand 1))
2204 (pc)))]
09cae750
PD
2205{
2206 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
2207 operands[3] = GEN_INT (shift);
2208
2209 if (GET_CODE (operands[0]) == EQ)
2210 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
2211 else
2212 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
2213})
2214
2215(define_insn_and_split "*branch_on_bit_range<X:mode>"
2216 [(set (pc)
2217 (if_then_else
248710c4
KC
2218 (match_operator 0 "equality_operator"
2219 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2220 (match_operand 3 "branch_on_bit_operand")
2221 (const_int 0))
2222 (const_int 0)])
2223 (label_ref (match_operand 1))
2224 (pc)))
09cae750
PD
2225 (clobber (match_scratch:X 4 "=&r"))]
2226 ""
2227 "#"
2228 "reload_completed"
2229 [(set (match_dup 4)
2230 (ashift:X (match_dup 2) (match_dup 3)))
2231 (set (pc)
2232 (if_then_else
248710c4
KC
2233 (match_op_dup 0 [(match_dup 4) (const_int 0)])
2234 (label_ref (match_operand 1))
2235 (pc)))]
09cae750
PD
2236{
2237 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
2238})
2239
2240;;
2241;; ....................
2242;;
2243;; SETTING A REGISTER FROM A COMPARISON
2244;;
2245;; ....................
2246
2247;; Destination is always set in SI mode.
2248
2249(define_expand "cstore<mode>4"
2250 [(set (match_operand:SI 0 "register_operand")
2251 (match_operator:SI 1 "order_operator"
248710c4
KC
2252 [(match_operand:GPR 2 "register_operand")
2253 (match_operand:GPR 3 "nonmemory_operand")]))]
09cae750
PD
2254 ""
2255{
2256 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
2257 operands[3]);
2258 DONE;
2259})
2260
2261(define_expand "cstore<mode>4"
2262 [(set (match_operand:SI 0 "register_operand")
2263 (match_operator:SI 1 "fp_scc_comparison"
248710c4
KC
2264 [(match_operand:ANYF 2 "register_operand")
2265 (match_operand:ANYF 3 "register_operand")]))]
09cae750
PD
2266 "TARGET_HARD_FLOAT"
2267{
2268 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
2269 operands[3]);
2270 DONE;
2271})
2272
2273(define_insn "*cstore<ANYF:mode><X:mode>4"
248710c4
KC
2274 [(set (match_operand:X 0 "register_operand" "=r")
2275 (match_operator:X 1 "fp_native_comparison"
2276 [(match_operand:ANYF 2 "register_operand" " f")
2277 (match_operand:ANYF 3 "register_operand" " f")]))]
09cae750
PD
2278 "TARGET_HARD_FLOAT"
2279 "f%C1.<fmt>\t%0,%2,%3"
2280 [(set_attr "type" "fcmp")
2281 (set_attr "mode" "<UNITMODE>")])
2282
1fcbfb00
AW
2283(define_expand "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
2284 [(parallel [(set (match_operand:X 0 "register_operand")
2285 (unspec:X
2286 [(match_operand:ANYF 1 "register_operand")
2287 (match_operand:ANYF 2 "register_operand")]
2288 QUIET_COMPARISON))
2289 (clobber (match_scratch:X 3))])]
2290 "TARGET_HARD_FLOAT")
2291
2292(define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_default"
2293 [(set (match_operand:X 0 "register_operand" "=r")
09cae750 2294 (unspec:X
1fcbfb00
AW
2295 [(match_operand:ANYF 1 "register_operand" " f")
2296 (match_operand:ANYF 2 "register_operand" " f")]
2297 QUIET_COMPARISON))
09cae750 2298 (clobber (match_scratch:X 3 "=&r"))]
1fcbfb00 2299 "TARGET_HARD_FLOAT && ! HONOR_SNANS (<ANYF:MODE>mode)"
09cae750
PD
2300 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3"
2301 [(set_attr "type" "fcmp")
2302 (set_attr "mode" "<UNITMODE>")
2303 (set (attr "length") (const_int 12))])
2304
1fcbfb00
AW
2305(define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_snan"
2306 [(set (match_operand:X 0 "register_operand" "=r")
2307 (unspec:X
2308 [(match_operand:ANYF 1 "register_operand" " f")
2309 (match_operand:ANYF 2 "register_operand" " f")]
2310 QUIET_COMPARISON))
2311 (clobber (match_scratch:X 3 "=&r"))]
2312 "TARGET_HARD_FLOAT && HONOR_SNANS (<ANYF:MODE>mode)"
2313 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3\n\tfeq.<fmt>\tzero,%1,%2"
2314 [(set_attr "type" "fcmp")
2315 (set_attr "mode" "<UNITMODE>")
2316 (set (attr "length") (const_int 16))])
2317
09cae750 2318(define_insn "*seq_zero_<X:mode><GPR:mode>"
248710c4
KC
2319 [(set (match_operand:GPR 0 "register_operand" "=r")
2320 (eq:GPR (match_operand:X 1 "register_operand" " r")
2321 (const_int 0)))]
09cae750
PD
2322 ""
2323 "seqz\t%0,%1"
2324 [(set_attr "type" "slt")
2325 (set_attr "mode" "<X:MODE>")])
2326
2327(define_insn "*sne_zero_<X:mode><GPR:mode>"
248710c4
KC
2328 [(set (match_operand:GPR 0 "register_operand" "=r")
2329 (ne:GPR (match_operand:X 1 "register_operand" " r")
2330 (const_int 0)))]
09cae750
PD
2331 ""
2332 "snez\t%0,%1"
2333 [(set_attr "type" "slt")
2334 (set_attr "mode" "<X:MODE>")])
2335
2336(define_insn "*sgt<u>_<X:mode><GPR:mode>"
248710c4
KC
2337 [(set (match_operand:GPR 0 "register_operand" "= r")
2338 (any_gt:GPR (match_operand:X 1 "register_operand" " r")
2339 (match_operand:X 2 "reg_or_0_operand" " rJ")))]
09cae750
PD
2340 ""
2341 "sgt<u>\t%0,%1,%z2"
2342 [(set_attr "type" "slt")
2343 (set_attr "mode" "<X:MODE>")])
2344
2345(define_insn "*sge<u>_<X:mode><GPR:mode>"
248710c4
KC
2346 [(set (match_operand:GPR 0 "register_operand" "=r")
2347 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
2348 (const_int 1)))]
2349 ""
0791ac18 2350 "slt%i2<u>\t%0,zero,%1"
09cae750 2351 [(set_attr "type" "slt")
7ef00402 2352 (set_attr "mode" "<X:MODE>")])
09cae750
PD
2353
2354(define_insn "*slt<u>_<X:mode><GPR:mode>"
248710c4
KC
2355 [(set (match_operand:GPR 0 "register_operand" "= r")
2356 (any_lt:GPR (match_operand:X 1 "register_operand" " r")
2357 (match_operand:X 2 "arith_operand" " rI")))]
09cae750 2358 ""
0791ac18 2359 "slt%i2<u>\t%0,%1,%2"
09cae750 2360 [(set_attr "type" "slt")
7ef00402 2361 (set_attr "mode" "<X:MODE>")])
09cae750
PD
2362
2363(define_insn "*sle<u>_<X:mode><GPR:mode>"
248710c4
KC
2364 [(set (match_operand:GPR 0 "register_operand" "=r")
2365 (any_le:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
2366 (match_operand:X 2 "sle_operand" "")))]
2367 ""
2368{
2369 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
0791ac18 2370 return "slt%i2<u>\t%0,%1,%2";
09cae750
PD
2371}
2372 [(set_attr "type" "slt")
7ef00402 2373 (set_attr "mode" "<X:MODE>")])
09cae750
PD
2374
2375;;
2376;; ....................
2377;;
2378;; UNCONDITIONAL BRANCHES
2379;;
2380;; ....................
2381
2382;; Unconditional branches.
2383
2384(define_insn "jump"
2385 [(set (pc)
2386 (label_ref (match_operand 0 "" "")))]
2387 ""
2388 "j\t%l0"
2389 [(set_attr "type" "jump")
2390 (set_attr "mode" "none")])
2391
2392(define_expand "indirect_jump"
2393 [(set (pc) (match_operand 0 "register_operand"))]
2394 ""
2395{
2396 operands[0] = force_reg (Pmode, operands[0]);
2397 if (Pmode == SImode)
2398 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
2399 else
2400 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
2401 DONE;
2402})
2403
2404(define_insn "indirect_jump<mode>"
2405 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
2406 ""
2407 "jr\t%0"
2408 [(set_attr "type" "jump")
2409 (set_attr "mode" "none")])
2410
2411(define_expand "tablejump"
2412 [(set (pc) (match_operand 0 "register_operand" ""))
2413 (use (label_ref (match_operand 1 "" "")))]
2414 ""
2415{
2416 if (CASE_VECTOR_PC_RELATIVE)
2417 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
2418 gen_rtx_LABEL_REF (Pmode, operands[1]),
2419 NULL_RTX, 0, OPTAB_DIRECT);
2420
2421 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
2422 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
2423 else
2424 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
2425 DONE;
2426})
2427
2428(define_insn "tablejump<mode>"
2429 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
2430 (use (label_ref (match_operand 1 "" "")))]
2431 ""
2432 "jr\t%0"
2433 [(set_attr "type" "jump")
2434 (set_attr "mode" "none")])
2435
2436;;
2437;; ....................
2438;;
2439;; Function prologue/epilogue
2440;;
2441;; ....................
2442;;
2443
2444(define_expand "prologue"
2445 [(const_int 1)]
2446 ""
2447{
2448 riscv_expand_prologue ();
2449 DONE;
2450})
2451
2452;; Block any insns from being moved before this point, since the
2453;; profiling call to mcount can use various registers that aren't
2454;; saved or used to pass arguments.
2455
2456(define_insn "blockage"
2457 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
2458 ""
2459 ""
2460 [(set_attr "type" "ghost")
2461 (set_attr "mode" "none")])
2462
2463(define_expand "epilogue"
2464 [(const_int 2)]
2465 ""
2466{
fd1e52dc 2467 riscv_expand_epilogue (NORMAL_RETURN);
09cae750
PD
2468 DONE;
2469})
2470
2471(define_expand "sibcall_epilogue"
2472 [(const_int 2)]
2473 ""
2474{
fd1e52dc 2475 riscv_expand_epilogue (SIBCALL_RETURN);
09cae750
PD
2476 DONE;
2477})
2478
2479;; Trivial return. Make it look like a normal return insn as that
2480;; allows jump optimizations to work better.
2481
2482(define_expand "return"
2483 [(simple_return)]
2484 "riscv_can_use_return_insn ()"
2485 "")
2486
2487(define_insn "simple_return"
2488 [(simple_return)]
2489 ""
8cad5b14
KC
2490{
2491 return riscv_output_return ();
2492}
09cae750
PD
2493 [(set_attr "type" "jump")
2494 (set_attr "mode" "none")])
2495
2496;; Normal return.
2497
2498(define_insn "simple_return_internal"
2499 [(simple_return)
2500 (use (match_operand 0 "pmode_register_operand" ""))]
2501 ""
2502 "jr\t%0"
2503 [(set_attr "type" "jump")
2504 (set_attr "mode" "none")])
2505
2506;; This is used in compiling the unwind routines.
2507(define_expand "eh_return"
2508 [(use (match_operand 0 "general_operand"))]
2509 ""
2510{
2511 if (GET_MODE (operands[0]) != word_mode)
2512 operands[0] = convert_to_mode (word_mode, operands[0], 0);
2513 if (TARGET_64BIT)
2514 emit_insn (gen_eh_set_lr_di (operands[0]));
2515 else
2516 emit_insn (gen_eh_set_lr_si (operands[0]));
fd1e52dc
JW
2517
2518 emit_jump_insn (gen_eh_return_internal ());
2519 emit_barrier ();
09cae750
PD
2520 DONE;
2521})
2522
2523;; Clobber the return address on the stack. We can't expand this
2524;; until we know where it will be put in the stack frame.
2525
2526(define_insn "eh_set_lr_si"
2527 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2528 (clobber (match_scratch:SI 1 "=&r"))]
2529 "! TARGET_64BIT"
2530 "#")
2531
2532(define_insn "eh_set_lr_di"
2533 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2534 (clobber (match_scratch:DI 1 "=&r"))]
2535 "TARGET_64BIT"
2536 "#")
2537
2538(define_split
2539 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
2540 (clobber (match_scratch 1))]
2541 "reload_completed"
2542 [(const_int 0)]
2543{
2544 riscv_set_return_address (operands[0], operands[1]);
2545 DONE;
2546})
2547
fd1e52dc
JW
2548(define_insn_and_split "eh_return_internal"
2549 [(eh_return)]
2550 ""
2551 "#"
2552 "epilogue_completed"
2553 [(const_int 0)]
2554 "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
2555
09cae750
PD
2556;;
2557;; ....................
2558;;
2559;; FUNCTION CALLS
2560;;
2561;; ....................
2562
2563(define_expand "sibcall"
2564 [(parallel [(call (match_operand 0 "")
2565 (match_operand 1 ""))
2566 (use (match_operand 2 "")) ;; next_arg_reg
2567 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2568 ""
2569{
2570 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2571 emit_call_insn (gen_sibcall_internal (target, operands[1]));
2572 DONE;
2573})
2574
2575(define_insn "sibcall_internal"
2576 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
2577 (match_operand 1 "" ""))]
2578 "SIBLING_CALL_P (insn)"
2579 "@
2580 jr\t%0
2581 tail\t%0
2582 tail\t%0@plt"
2583 [(set_attr "type" "call")])
2584
2585(define_expand "sibcall_value"
2586 [(parallel [(set (match_operand 0 "")
2587 (call (match_operand 1 "")
2588 (match_operand 2 "")))
2589 (use (match_operand 3 ""))])] ;; next_arg_reg
2590 ""
2591{
2592 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2593 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
2594 DONE;
2595})
2596
2597(define_insn "sibcall_value_internal"
2598 [(set (match_operand 0 "" "")
2599 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
2600 (match_operand 2 "" "")))]
2601 "SIBLING_CALL_P (insn)"
2602 "@
2603 jr\t%1
2604 tail\t%1
2605 tail\t%1@plt"
2606 [(set_attr "type" "call")])
2607
2608(define_expand "call"
2609 [(parallel [(call (match_operand 0 "")
2610 (match_operand 1 ""))
2611 (use (match_operand 2 "")) ;; next_arg_reg
2612 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2613 ""
2614{
2615 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2616 emit_call_insn (gen_call_internal (target, operands[1]));
2617 DONE;
2618})
2619
2620(define_insn "call_internal"
2621 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
2622 (match_operand 1 "" ""))
2623 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2624 ""
2625 "@
2626 jalr\t%0
2627 call\t%0
2628 call\t%0@plt"
2629 [(set_attr "type" "call")])
2630
2631(define_expand "call_value"
2632 [(parallel [(set (match_operand 0 "")
2633 (call (match_operand 1 "")
2634 (match_operand 2 "")))
2635 (use (match_operand 3 ""))])] ;; next_arg_reg
2636 ""
2637{
2638 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2639 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
2640 DONE;
2641})
2642
2643(define_insn "call_value_internal"
2644 [(set (match_operand 0 "" "")
2645 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
2646 (match_operand 2 "" "")))
2647 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2648 ""
2649 "@
2650 jalr\t%1
2651 call\t%1
2652 call\t%1@plt"
2653 [(set_attr "type" "call")])
2654
2655;; Call subroutine returning any type.
2656
2657(define_expand "untyped_call"
2658 [(parallel [(call (match_operand 0 "")
2659 (const_int 0))
2660 (match_operand 1 "")
2661 (match_operand 2 "")])]
2662 ""
2663{
2664 int i;
2665
2666 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2667
2668 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2669 {
2670 rtx set = XVECEXP (operands[2], 0, i);
2671 riscv_emit_move (SET_DEST (set), SET_SRC (set));
2672 }
2673
2674 emit_insn (gen_blockage ());
2675 DONE;
2676})
2677
2678(define_insn "nop"
2679 [(const_int 0)]
2680 ""
2681 "nop"
2682 [(set_attr "type" "nop")
2683 (set_attr "mode" "none")])
2684
2685(define_insn "trap"
2686 [(trap_if (const_int 1) (const_int 0))]
2687 ""
2688 "ebreak")
2689
d0e0c130
KC
2690;; Must use the registers that we save to prevent the rename reg optimization
2691;; pass from using them before the gpr_save pattern when shrink wrapping
2692;; occurs. See bug 95252 for instance.
2693
09cae750 2694(define_insn "gpr_save"
d0e0c130
KC
2695 [(match_parallel 1 "gpr_save_operation"
2696 [(unspec_volatile [(match_operand 0 "const_int_operand")]
2697 UNSPECV_GPR_SAVE)])]
09cae750 2698 ""
dcf41a4e 2699 "call\tt0,__riscv_save_%0")
09cae750
PD
2700
2701(define_insn "gpr_restore"
2702 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2703 ""
2704 "tail\t__riscv_restore_%0")
2705
2706(define_insn "gpr_restore_return"
2707 [(return)
2708 (use (match_operand 0 "pmode_register_operand" ""))
2709 (const_int 0)]
2710 ""
2711 "")
2712
2713(define_insn "riscv_frflags"
2714 [(set (match_operand:SI 0 "register_operand" "=r")
2715 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
2716 "TARGET_HARD_FLOAT"
d0ebdd9f 2717 "frflags\t%0")
09cae750
PD
2718
2719(define_insn "riscv_fsflags"
2720 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2721 "TARGET_HARD_FLOAT"
d0ebdd9f
JW
2722 "fsflags\t%0")
2723
2724(define_insn "riscv_mret"
eb153f07
JW
2725 [(return)
2726 (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
d0ebdd9f
JW
2727 ""
2728 "mret")
09cae750 2729
ec74725c 2730(define_insn "riscv_sret"
eb153f07
JW
2731 [(return)
2732 (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
ec74725c
JW
2733 ""
2734 "sret")
2735
2736(define_insn "riscv_uret"
eb153f07
JW
2737 [(return)
2738 (unspec_volatile [(const_int 0)] UNSPECV_URET)]
ec74725c
JW
2739 ""
2740 "uret")
2741
09cae750
PD
2742(define_insn "stack_tie<mode>"
2743 [(set (mem:BLK (scratch))
2744 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
2745 (match_operand:X 1 "register_operand" "r")]
2746 UNSPEC_TIE))]
2747 ""
2748 ""
2749 [(set_attr "length" "0")]
2750)
2751
88108b27
AW
2752;; This fixes a failure with gcc.c-torture/execute/pr64242.c at -O2 for a
2753;; 32-bit target when using -mtune=sifive-7-series. The first sched pass
2754;; runs before register elimination, and we have a non-obvious dependency
2755;; between a use of the soft fp and a set of the hard fp. We fix this by
2756;; emitting a clobber using the hard fp between the two insns.
2757(define_expand "restore_stack_nonlocal"
2758 [(match_operand 0 "register_operand")
2759 (match_operand 1 "memory_operand")]
2760 ""
2761{
2762 emit_move_insn (operands[0], operands[1]);
2763 /* Prevent the following hard fp restore from being moved before the move
2764 insn above which uses a copy of the soft fp reg. */
2765 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2766 DONE;
2767})
2768
1073b500
KC
2769;; Named pattern for expanding thread pointer reference.
2770(define_expand "get_thread_pointer<mode>"
2771 [(set (match_operand:P 0 "register_operand" "=r")
2772 (reg:P TP_REGNUM))]
2773 ""
2774{})
2775
c931e8d5
CQ
2776;; Named patterns for stack smashing protection.
2777
2778(define_expand "stack_protect_set"
2779 [(match_operand 0 "memory_operand")
2780 (match_operand 1 "memory_operand")]
2781 ""
2782{
2783 machine_mode mode = GET_MODE (operands[0]);
2784 if (riscv_stack_protector_guard == SSP_TLS)
2785 {
2786 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
2787 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
2788 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
2789 operands[1] = gen_rtx_MEM (Pmode, addr);
2790 }
2791
2792 emit_insn ((mode == DImode
2793 ? gen_stack_protect_set_di
2794 : gen_stack_protect_set_si) (operands[0], operands[1]));
2795 DONE;
2796})
2797
2798;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
2799;; canary value does not live beyond the life of this sequence.
2800(define_insn "stack_protect_set_<mode>"
2801 [(set (match_operand:GPR 0 "memory_operand" "=m")
2802 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")]
2803 UNSPEC_SSP_SET))
2804 (set (match_scratch:GPR 2 "=&r") (const_int 0))]
2805 ""
2806 "<load>\\t%2, %1\;<store>\\t%2, %0\;li\t%2, 0"
2807 [(set_attr "length" "12")])
2808
2809(define_expand "stack_protect_test"
2810 [(match_operand 0 "memory_operand")
2811 (match_operand 1 "memory_operand")
2812 (match_operand 2)]
2813 ""
2814{
2815 rtx result;
2816 machine_mode mode = GET_MODE (operands[0]);
2817
2818 result = gen_reg_rtx(mode);
2819 if (riscv_stack_protector_guard == SSP_TLS)
2820 {
2821 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
2822 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
2823 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
2824 operands[1] = gen_rtx_MEM (Pmode, addr);
2825 }
2826 emit_insn ((mode == DImode
2827 ? gen_stack_protect_test_di
2828 : gen_stack_protect_test_si) (result,
2829 operands[0],
2830 operands[1]));
2831
e1fcf14f
CM
2832 rtx cond = gen_rtx_EQ (VOIDmode, result, const0_rtx);
2833 emit_jump_insn (gen_cbranch4 (mode, cond, result, const0_rtx, operands[2]));
c931e8d5
CQ
2834
2835 DONE;
2836})
2837
2838(define_insn "stack_protect_test_<mode>"
2839 [(set (match_operand:GPR 0 "register_operand" "=r")
2840 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")
2841 (match_operand:GPR 2 "memory_operand" "m")]
2842 UNSPEC_SSP_TEST))
2843 (clobber (match_scratch:GPR 3 "=&r"))]
2844 ""
2845 "<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
2846 [(set_attr "length" "12")])
2847
09cae750
PD
2848(include "sync.md")
2849(include "peephole.md")
2850(include "pic.md")
2851(include "generic.md")
88108b27 2852(include "sifive-7.md")