]> git.ipfire.org Git - thirdparty/gcc.git/blame_incremental - gcc/config/riscv/riscv.md
c++: ttp matching with constrained auto parm [PR99909]
[thirdparty/gcc.git] / gcc / config / riscv / riscv.md
... / ...
CommitLineData
1;; Machine description for RISC-V for GNU compiler.
2;; Copyright (C) 2011-2021 Free Software Foundation, Inc.
3;; Contributed by Andrew Waterman (andrew@sifive.com).
4;; Based on MIPS target for GNU compiler.
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
59 ;; Interrupt handler instructions.
60 UNSPECV_MRET
61 UNSPECV_SRET
62 UNSPECV_URET
63
64 ;; Blockage and synchronization.
65 UNSPECV_BLOCKAGE
66 UNSPECV_FENCE
67 UNSPECV_FENCE_I
68
69 ;; Stack Smash Protector
70 UNSPEC_SSP_SET
71 UNSPEC_SSP_TEST
72])
73
74(define_constants
75 [(RETURN_ADDR_REGNUM 1)
76 (GP_REGNUM 3)
77 (TP_REGNUM 4)
78 (T0_REGNUM 5)
79 (T1_REGNUM 6)
80 (S0_REGNUM 8)
81 (S1_REGNUM 9)
82 (S2_REGNUM 18)
83 (S3_REGNUM 19)
84 (S4_REGNUM 20)
85 (S5_REGNUM 21)
86 (S6_REGNUM 22)
87 (S7_REGNUM 23)
88 (S8_REGNUM 24)
89 (S9_REGNUM 25)
90 (S10_REGNUM 26)
91 (S11_REGNUM 27)
92
93 (NORMAL_RETURN 0)
94 (SIBCALL_RETURN 1)
95 (EXCEPTION_RETURN 2)
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,
173 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost"
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
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
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
302;; Iterator for floating-point modes that can be loaded into X registers.
303(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT")])
304
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
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
319;; Instruction names for stores.
320(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
321
322;; Instruction names for FP stores from integer registers.
323(define_mode_attr softstore [(SF "sw") (DF "sd")])
324
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"
444 [(set (match_operand:ANYF 0 "register_operand" "=f")
445 (plus:ANYF (match_operand:ANYF 1 "register_operand" " f")
446 (match_operand:ANYF 2 "register_operand" " f")))]
447 "TARGET_HARD_FLOAT"
448 "fadd.<fmt>\t%0,%1,%2"
449 [(set_attr "type" "fadd")
450 (set_attr "mode" "<UNITMODE>")])
451
452(define_insn "addsi3"
453 [(set (match_operand:SI 0 "register_operand" "=r,r")
454 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
455 (match_operand:SI 2 "arith_operand" " r,I")))]
456 ""
457 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
458 [(set_attr "type" "arith")
459 (set_attr "mode" "SI")])
460
461(define_insn "adddi3"
462 [(set (match_operand:DI 0 "register_operand" "=r,r")
463 (plus:DI (match_operand:DI 1 "register_operand" " r,r")
464 (match_operand:DI 2 "arith_operand" " r,I")))]
465 "TARGET_64BIT"
466 "add%i2\t%0,%1,%2"
467 [(set_attr "type" "arith")
468 (set_attr "mode" "DI")])
469
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
545(define_insn "*addsi3_extended"
546 [(set (match_operand:DI 0 "register_operand" "=r,r")
547 (sign_extend:DI
548 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
549 (match_operand:SI 2 "arith_operand" " r,I"))))]
550 "TARGET_64BIT"
551 "add%i2w\t%0,%1,%2"
552 [(set_attr "type" "arith")
553 (set_attr "mode" "SI")])
554
555(define_insn "*addsi3_extended2"
556 [(set (match_operand:DI 0 "register_operand" "=r,r")
557 (sign_extend:DI
558 (match_operator:SI 3 "subreg_lowpart_operator"
559 [(plus:DI (match_operand:DI 1 "register_operand" " r,r")
560 (match_operand:DI 2 "arith_operand" " r,I"))])))]
561 "TARGET_64BIT"
562 "add%i2w\t%0,%1,%2"
563 [(set_attr "type" "arith")
564 (set_attr "mode" "SI")])
565
566;;
567;; ....................
568;;
569;; SUBTRACTION
570;;
571;; ....................
572;;
573
574(define_insn "sub<mode>3"
575 [(set (match_operand:ANYF 0 "register_operand" "=f")
576 (minus:ANYF (match_operand:ANYF 1 "register_operand" " f")
577 (match_operand:ANYF 2 "register_operand" " f")))]
578 "TARGET_HARD_FLOAT"
579 "fsub.<fmt>\t%0,%1,%2"
580 [(set_attr "type" "fadd")
581 (set_attr "mode" "<UNITMODE>")])
582
583(define_insn "subdi3"
584 [(set (match_operand:DI 0 "register_operand" "= r")
585 (minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
586 (match_operand:DI 2 "register_operand" " r")))]
587 "TARGET_64BIT"
588 "sub\t%0,%z1,%2"
589 [(set_attr "type" "arith")
590 (set_attr "mode" "DI")])
591
592(define_insn "subsi3"
593 [(set (match_operand:SI 0 "register_operand" "= r")
594 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
595 (match_operand:SI 2 "register_operand" " r")))]
596 ""
597 { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; }
598 [(set_attr "type" "arith")
599 (set_attr "mode" "SI")])
600
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
680(define_insn "*subsi3_extended"
681 [(set (match_operand:DI 0 "register_operand" "= r")
682 (sign_extend:DI
683 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
684 (match_operand:SI 2 "register_operand" " r"))))]
685 "TARGET_64BIT"
686 "subw\t%0,%z1,%2"
687 [(set_attr "type" "arith")
688 (set_attr "mode" "SI")])
689
690(define_insn "*subsi3_extended2"
691 [(set (match_operand:DI 0 "register_operand" "= r")
692 (sign_extend:DI
693 (match_operator:SI 3 "subreg_lowpart_operator"
694 [(minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
695 (match_operand:DI 2 "register_operand" " r"))])))]
696 "TARGET_64BIT"
697 "subw\t%0,%z1,%2"
698 [(set_attr "type" "arith")
699 (set_attr "mode" "SI")])
700
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
729 (match_operator:SI 2 "subreg_lowpart_operator"
730 [(neg:DI (match_operand:DI 1 "register_operand" " r"))])))]
731 "TARGET_64BIT"
732 "negw\t%0,%1"
733 [(set_attr "type" "arith")
734 (set_attr "mode" "SI")])
735
736;;
737;; ....................
738;;
739;; MULTIPLICATION
740;;
741;; ....................
742;;
743
744(define_insn "mul<mode>3"
745 [(set (match_operand:ANYF 0 "register_operand" "=f")
746 (mult:ANYF (match_operand:ANYF 1 "register_operand" " f")
747 (match_operand:ANYF 2 "register_operand" " f")))]
748 "TARGET_HARD_FLOAT"
749 "fmul.<fmt>\t%0,%1,%2"
750 [(set_attr "type" "fmul")
751 (set_attr "mode" "<UNITMODE>")])
752
753(define_insn "mulsi3"
754 [(set (match_operand:SI 0 "register_operand" "=r")
755 (mult:SI (match_operand:SI 1 "register_operand" " r")
756 (match_operand:SI 2 "register_operand" " r")))]
757 "TARGET_MUL"
758 { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; }
759 [(set_attr "type" "imul")
760 (set_attr "mode" "SI")])
761
762(define_insn "muldi3"
763 [(set (match_operand:DI 0 "register_operand" "=r")
764 (mult:DI (match_operand:DI 1 "register_operand" " r")
765 (match_operand:DI 2 "register_operand" " r")))]
766 "TARGET_MUL && TARGET_64BIT"
767 "mul\t%0,%1,%2"
768 [(set_attr "type" "imul")
769 (set_attr "mode" "DI")])
770
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
862(define_insn "*mulsi3_extended"
863 [(set (match_operand:DI 0 "register_operand" "=r")
864 (sign_extend:DI
865 (mult:SI (match_operand:SI 1 "register_operand" " r")
866 (match_operand:SI 2 "register_operand" " r"))))]
867 "TARGET_MUL && TARGET_64BIT"
868 "mulw\t%0,%1,%2"
869 [(set_attr "type" "imul")
870 (set_attr "mode" "SI")])
871
872(define_insn "*mulsi3_extended2"
873 [(set (match_operand:DI 0 "register_operand" "=r")
874 (sign_extend:DI
875 (match_operator:SI 3 "subreg_lowpart_operator"
876 [(mult:DI (match_operand:DI 1 "register_operand" " r")
877 (match_operand:DI 2 "register_operand" " r"))])))]
878 "TARGET_MUL && TARGET_64BIT"
879 "mulw\t%0,%1,%2"
880 [(set_attr "type" "imul")
881 (set_attr "mode" "SI")])
882
883;;
884;; ........................
885;;
886;; MULTIPLICATION HIGH-PART
887;;
888;; ........................
889;;
890
891
892(define_expand "<u>mulditi3"
893 [(set (match_operand:TI 0 "register_operand")
894 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
895 (any_extend:TI (match_operand:DI 2 "register_operand"))))]
896 "TARGET_MUL && TARGET_64BIT"
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"
910 [(set (match_operand:DI 0 "register_operand" "=r")
911 (truncate:DI
912 (lshiftrt:TI
913 (mult:TI (any_extend:TI
914 (match_operand:DI 1 "register_operand" " r"))
915 (any_extend:TI
916 (match_operand:DI 2 "register_operand" " r")))
917 (const_int 64))))]
918 "TARGET_MUL && TARGET_64BIT"
919 "mulh<u>\t%0,%1,%2"
920 [(set_attr "type" "imul")
921 (set_attr "mode" "DI")])
922
923(define_expand "usmulditi3"
924 [(set (match_operand:TI 0 "register_operand")
925 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand"))
926 (sign_extend:TI (match_operand:DI 2 "register_operand"))))]
927 "TARGET_MUL && TARGET_64BIT"
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"
941 [(set (match_operand:DI 0 "register_operand" "=r")
942 (truncate:DI
943 (lshiftrt:TI
944 (mult:TI (zero_extend:TI
945 (match_operand:DI 1 "register_operand" "r"))
946 (sign_extend:TI
947 (match_operand:DI 2 "register_operand" " r")))
948 (const_int 64))))]
949 "TARGET_MUL && TARGET_64BIT"
950 "mulhsu\t%0,%2,%1"
951 [(set_attr "type" "imul")
952 (set_attr "mode" "DI")])
953
954(define_expand "<u>mulsidi3"
955 [(set (match_operand:DI 0 "register_operand" "=r")
956 (mult:DI (any_extend:DI
957 (match_operand:SI 1 "register_operand" " r"))
958 (any_extend:DI
959 (match_operand:SI 2 "register_operand" " r"))))]
960 "TARGET_MUL && !TARGET_64BIT"
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"
971 [(set (match_operand:SI 0 "register_operand" "=r")
972 (truncate:SI
973 (lshiftrt:DI
974 (mult:DI (any_extend:DI
975 (match_operand:SI 1 "register_operand" " r"))
976 (any_extend:DI
977 (match_operand:SI 2 "register_operand" " r")))
978 (const_int 32))))]
979 "TARGET_MUL && !TARGET_64BIT"
980 "mulh<u>\t%0,%1,%2"
981 [(set_attr "type" "imul")
982 (set_attr "mode" "SI")])
983
984
985(define_expand "usmulsidi3"
986 [(set (match_operand:DI 0 "register_operand" "=r")
987 (mult:DI (zero_extend:DI
988 (match_operand:SI 1 "register_operand" " r"))
989 (sign_extend:DI
990 (match_operand:SI 2 "register_operand" " r"))))]
991 "TARGET_MUL && !TARGET_64BIT"
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"
1002 [(set (match_operand:SI 0 "register_operand" "=r")
1003 (truncate:SI
1004 (lshiftrt:DI
1005 (mult:DI (zero_extend:DI
1006 (match_operand:SI 1 "register_operand" " r"))
1007 (sign_extend:DI
1008 (match_operand:SI 2 "register_operand" " r")))
1009 (const_int 32))))]
1010 "TARGET_MUL && !TARGET_64BIT"
1011 "mulhsu\t%0,%2,%1"
1012 [(set_attr "type" "imul")
1013 (set_attr "mode" "SI")])
1014
1015;;
1016;; ....................
1017;;
1018;; DIVISION and REMAINDER
1019;;
1020;; ....................
1021;;
1022
1023(define_insn "<optab>si3"
1024 [(set (match_operand:SI 0 "register_operand" "=r")
1025 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1026 (match_operand:SI 2 "register_operand" " r")))]
1027 "TARGET_DIV"
1028 { return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2"; }
1029 [(set_attr "type" "idiv")
1030 (set_attr "mode" "SI")])
1031
1032(define_insn "<optab>di3"
1033 [(set (match_operand:DI 0 "register_operand" "=r")
1034 (any_div:DI (match_operand:DI 1 "register_operand" " r")
1035 (match_operand:DI 2 "register_operand" " r")))]
1036 "TARGET_DIV && TARGET_64BIT"
1037 "<insn>%i2\t%0,%1,%2"
1038 [(set_attr "type" "idiv")
1039 (set_attr "mode" "DI")])
1040
1041(define_insn "*<optab>si3_extended"
1042 [(set (match_operand:DI 0 "register_operand" "=r")
1043 (sign_extend:DI
1044 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1045 (match_operand:SI 2 "register_operand" " r"))))]
1046 "TARGET_DIV && TARGET_64BIT"
1047 "<insn>%i2w\t%0,%1,%2"
1048 [(set_attr "type" "idiv")
1049 (set_attr "mode" "DI")])
1050
1051(define_insn "div<mode>3"
1052 [(set (match_operand:ANYF 0 "register_operand" "=f")
1053 (div:ANYF (match_operand:ANYF 1 "register_operand" " f")
1054 (match_operand:ANYF 2 "register_operand" " f")))]
1055 "TARGET_HARD_FLOAT && TARGET_FDIV"
1056 "fdiv.<fmt>\t%0,%1,%2"
1057 [(set_attr "type" "fdiv")
1058 (set_attr "mode" "<UNITMODE>")])
1059
1060;;
1061;; ....................
1062;;
1063;; SQUARE ROOT
1064;;
1065;; ....................
1066
1067(define_insn "sqrt<mode>2"
1068 [(set (match_operand:ANYF 0 "register_operand" "=f")
1069 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
1070 "TARGET_HARD_FLOAT && TARGET_FDIV"
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"
1081 [(set (match_operand:ANYF 0 "register_operand" "=f")
1082 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
1083 (match_operand:ANYF 2 "register_operand" " f")
1084 (match_operand:ANYF 3 "register_operand" " f")))]
1085 "TARGET_HARD_FLOAT"
1086 "fmadd.<fmt>\t%0,%1,%2,%3"
1087 [(set_attr "type" "fmadd")
1088 (set_attr "mode" "<UNITMODE>")])
1089
1090;; a * b - c
1091(define_insn "fms<mode>4"
1092 [(set (match_operand:ANYF 0 "register_operand" "=f")
1093 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
1094 (match_operand:ANYF 2 "register_operand" " f")
1095 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
1096 "TARGET_HARD_FLOAT"
1097 "fmsub.<fmt>\t%0,%1,%2,%3"
1098 [(set_attr "type" "fmadd")
1099 (set_attr "mode" "<UNITMODE>")])
1100
1101;; -a * b - c
1102(define_insn "fnms<mode>4"
1103 [(set (match_operand:ANYF 0 "register_operand" "=f")
1104 (fma:ANYF
1105 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1106 (match_operand:ANYF 2 "register_operand" " f")
1107 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
1108 "TARGET_HARD_FLOAT"
1109 "fnmadd.<fmt>\t%0,%1,%2,%3"
1110 [(set_attr "type" "fmadd")
1111 (set_attr "mode" "<UNITMODE>")])
1112
1113;; -a * b + c
1114(define_insn "fnma<mode>4"
1115 [(set (match_operand:ANYF 0 "register_operand" "=f")
1116 (fma:ANYF
1117 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1118 (match_operand:ANYF 2 "register_operand" " f")
1119 (match_operand:ANYF 3 "register_operand" " f")))]
1120 "TARGET_HARD_FLOAT"
1121 "fnmsub.<fmt>\t%0,%1,%2,%3"
1122 [(set_attr "type" "fmadd")
1123 (set_attr "mode" "<UNITMODE>")])
1124
1125;; -(-a * b - c), modulo signed zeros
1126(define_insn "*fma<mode>4"
1127 [(set (match_operand:ANYF 0 "register_operand" "=f")
1128 (neg:ANYF
1129 (fma:ANYF
1130 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1131 (match_operand:ANYF 2 "register_operand" " f")
1132 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
1133 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1134 "fmadd.<fmt>\t%0,%1,%2,%3"
1135 [(set_attr "type" "fmadd")
1136 (set_attr "mode" "<UNITMODE>")])
1137
1138;; -(-a * b + c), modulo signed zeros
1139(define_insn "*fms<mode>4"
1140 [(set (match_operand:ANYF 0 "register_operand" "=f")
1141 (neg:ANYF
1142 (fma:ANYF
1143 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1144 (match_operand:ANYF 2 "register_operand" " f")
1145 (match_operand:ANYF 3 "register_operand" " f"))))]
1146 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1147 "fmsub.<fmt>\t%0,%1,%2,%3"
1148 [(set_attr "type" "fmadd")
1149 (set_attr "mode" "<UNITMODE>")])
1150
1151;; -(a * b + c), modulo signed zeros
1152(define_insn "*fnms<mode>4"
1153 [(set (match_operand:ANYF 0 "register_operand" "=f")
1154 (neg:ANYF
1155 (fma:ANYF
1156 (match_operand:ANYF 1 "register_operand" " f")
1157 (match_operand:ANYF 2 "register_operand" " f")
1158 (match_operand:ANYF 3 "register_operand" " f"))))]
1159 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1160 "fnmadd.<fmt>\t%0,%1,%2,%3"
1161 [(set_attr "type" "fmadd")
1162 (set_attr "mode" "<UNITMODE>")])
1163
1164;; -(a * b - c), modulo signed zeros
1165(define_insn "*fnma<mode>4"
1166 [(set (match_operand:ANYF 0 "register_operand" "=f")
1167 (neg:ANYF
1168 (fma:ANYF
1169 (match_operand:ANYF 1 "register_operand" " f")
1170 (match_operand:ANYF 2 "register_operand" " f")
1171 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
1172 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1173 "fnmsub.<fmt>\t%0,%1,%2,%3"
1174 [(set_attr "type" "fmadd")
1175 (set_attr "mode" "<UNITMODE>")])
1176
1177;;
1178;; ....................
1179;;
1180;; SIGN INJECTION
1181;;
1182;; ....................
1183
1184(define_insn "abs<mode>2"
1185 [(set (match_operand:ANYF 0 "register_operand" "=f")
1186 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
1187 "TARGET_HARD_FLOAT"
1188 "fabs.<fmt>\t%0,%1"
1189 [(set_attr "type" "fmove")
1190 (set_attr "mode" "<UNITMODE>")])
1191
1192(define_insn "copysign<mode>3"
1193 [(set (match_operand:ANYF 0 "register_operand" "=f")
1194 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")
1195 (match_operand:ANYF 2 "register_operand" " f")]
1196 UNSPEC_COPYSIGN))]
1197 "TARGET_HARD_FLOAT"
1198 "fsgnj.<fmt>\t%0,%1,%2"
1199 [(set_attr "type" "fmove")
1200 (set_attr "mode" "<UNITMODE>")])
1201
1202(define_insn "neg<mode>2"
1203 [(set (match_operand:ANYF 0 "register_operand" "=f")
1204 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
1205 "TARGET_HARD_FLOAT"
1206 "fneg.<fmt>\t%0,%1"
1207 [(set_attr "type" "fmove")
1208 (set_attr "mode" "<UNITMODE>")])
1209
1210;;
1211;; ....................
1212;;
1213;; MIN/MAX
1214;;
1215;; ....................
1216
1217(define_insn "smin<mode>3"
1218 [(set (match_operand:ANYF 0 "register_operand" "=f")
1219 (smin:ANYF (match_operand:ANYF 1 "register_operand" " f")
1220 (match_operand:ANYF 2 "register_operand" " f")))]
1221 "TARGET_HARD_FLOAT"
1222 "fmin.<fmt>\t%0,%1,%2"
1223 [(set_attr "type" "fmove")
1224 (set_attr "mode" "<UNITMODE>")])
1225
1226(define_insn "smax<mode>3"
1227 [(set (match_operand:ANYF 0 "register_operand" "=f")
1228 (smax:ANYF (match_operand:ANYF 1 "register_operand" " f")
1229 (match_operand:ANYF 2 "register_operand" " f")))]
1230 "TARGET_HARD_FLOAT"
1231 "fmax.<fmt>\t%0,%1,%2"
1232 [(set_attr "type" "fmove")
1233 (set_attr "mode" "<UNITMODE>")])
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"
1247 [(set (match_operand:X 0 "register_operand" "=r,r")
1248 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
1249 (match_operand:X 2 "arith_operand" " r,I")))]
1250 ""
1251 "<insn>%i2\t%0,%1,%2"
1252 [(set_attr "type" "logical")
1253 (set_attr "mode" "<MODE>")])
1254
1255(define_insn "*<optab>si3_internal"
1256 [(set (match_operand:SI 0 "register_operand" "=r,r")
1257 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
1258 (match_operand:SI 2 "arith_operand" " r,I")))]
1259 "TARGET_64BIT"
1260 "<insn>%i2\t%0,%1,%2"
1261 [(set_attr "type" "logical")
1262 (set_attr "mode" "SI")])
1263
1264(define_insn "one_cmpl<mode>2"
1265 [(set (match_operand:X 0 "register_operand" "=r")
1266 (not:X (match_operand:X 1 "register_operand" " r")))]
1267 ""
1268 "not\t%0,%1"
1269 [(set_attr "type" "logical")
1270 (set_attr "mode" "<MODE>")])
1271
1272(define_insn "*one_cmplsi2_internal"
1273 [(set (match_operand:SI 0 "register_operand" "=r")
1274 (not:SI (match_operand:SI 1 "register_operand" " r")))]
1275 "TARGET_64BIT"
1276 "not\t%0,%1"
1277 [(set_attr "type" "logical")
1278 (set_attr "mode" "SI")])
1279
1280;;
1281;; ....................
1282;;
1283;; TRUNCATION
1284;;
1285;; ....................
1286
1287(define_insn "truncdfsf2"
1288 [(set (match_operand:SF 0 "register_operand" "=f")
1289 (float_truncate:SF
1290 (match_operand:DF 1 "register_operand" " f")))]
1291 "TARGET_DOUBLE_FLOAT"
1292 "fcvt.s.d\t%0,%1"
1293 [(set_attr "type" "fcvt")
1294 (set_attr "mode" "SF")])
1295
1296;;
1297;; ....................
1298;;
1299;; ZERO EXTENSION
1300;;
1301;; ....................
1302
1303;; Extension insns.
1304
1305(define_insn_and_split "zero_extendsidi2"
1306 [(set (match_operand:DI 0 "register_operand" "=r,r")
1307 (zero_extend:DI
1308 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1309 "TARGET_64BIT"
1310 "@
1311 #
1312 lwu\t%0,%1"
1313 "&& reload_completed
1314 && REG_P (operands[1])
1315 && !paradoxical_subreg_p (operands[0])"
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"
1325 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1326 (zero_extend:GPR
1327 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
1328 ""
1329 "@
1330 #
1331 lhu\t%0,%1"
1332 "&& reload_completed
1333 && REG_P (operands[1])
1334 && !paradoxical_subreg_p (operands[0])"
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"
1347 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1348 (zero_extend:SUPERQI
1349 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
1350 ""
1351 "@
1352 andi\t%0,%1,0xff
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"
1365 [(set (match_operand:DI 0 "register_operand" "=r,r")
1366 (sign_extend:DI
1367 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
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"
1376 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1377 (sign_extend:SUPERQI
1378 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
1379 ""
1380 "@
1381 #
1382 l<SHORT:size>\t%0,%1"
1383 "&& reload_completed
1384 && REG_P (operands[1])
1385 && !paradoxical_subreg_p (operands[0])"
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"
1398 [(set (match_operand:DF 0 "register_operand" "=f")
1399 (float_extend:DF
1400 (match_operand:SF 1 "register_operand" " f")))]
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"
1414 [(set (match_operand:GPR 0 "register_operand" "=r")
1415 (fix:GPR
1416 (match_operand:ANYF 1 "register_operand" " f")))]
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"
1423 [(set (match_operand:GPR 0 "register_operand" "=r")
1424 (unsigned_fix:GPR
1425 (match_operand:ANYF 1 "register_operand" " f")))]
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"
1432 [(set (match_operand:ANYF 0 "register_operand" "= f")
1433 (float:ANYF
1434 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
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"
1441 [(set (match_operand:ANYF 0 "register_operand" "= f")
1442 (unsigned_float:ANYF
1443 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
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"
1450 [(set (match_operand:GPR 0 "register_operand" "=r")
1451 (unspec:GPR
1452 [(match_operand:ANYF 1 "register_operand" " f")]
1453 RINT))]
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>"
1471 [(set (match_operand:P 0 "register_operand" "=r")
1472 (unspec:P
1473 [(match_operand:P 1 "symbolic_operand" "")]
1474 UNSPEC_LOAD_GOT))]
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>"
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))]
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>"
1493 [(set (match_operand:P 0 "register_operand" "=r")
1494 (unspec:P
1495 [(match_operand:P 1 "symbolic_operand" "")]
1496 UNSPEC_TLS_GD))]
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>"
1503 [(set (match_operand:P 0 "register_operand" "=r")
1504 (unspec:P
1505 [(match_operand:P 1 "symbolic_operand" "")]
1506 UNSPEC_TLS_IE))]
1507 ""
1508 "la.tls.ie\t%0,%1"
1509 [(set_attr "got" "load")
1510 (set_attr "mode" "<MODE>")])
1511
1512(define_insn "auipc<mode>"
1513 [(set (match_operand:P 0 "register_operand" "=r")
1514 (unspec:P
1515 [(match_operand:P 1 "symbolic_operand" "")
1516 (match_operand:P 2 "const_int_operand")
1517 (pc)]
1518 UNSPEC_AUIPC))]
1519 ""
1520 ".LA%2: auipc\t%0,%h1"
1521 [(set_attr "type" "auipc")
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>"
1529 [(set (match_operand:P 0 "register_operand" "=r")
1530 (lo_sum:P (match_operand:P 1 "register_operand" " r")
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{
1546 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
1547 <GPR:MODE>mode, TRUE);
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"))]
1556 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL, TRUE)"
1557 [(set (match_dup 0) (match_dup 3))]
1558{
1559 riscv_split_symbol (operands[2], operands[1],
1560 MAX_MACHINE_MODE, &operands[3], TRUE);
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")
1576 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))]
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"
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"))]
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"
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"))]
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"
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"))]
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.
1640;; si+si->hi without truncation is legal because of
1641;; TARGET_TRULY_NOOP_TRUNCATION.
1642
1643(define_insn "*add<mode>hi3"
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")))]
1647 ""
1648 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
1649 [(set_attr "type" "arith")
1650 (set_attr "mode" "HI")])
1651
1652(define_insn "*xor<mode>hi3"
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")))]
1656 ""
1657 "xor%i2\t%0,%1,%2"
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"
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"))]
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"
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"))]
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"
1703 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
1704 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
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"
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"))]
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"
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"))]
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"
1746 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
1747 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
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
1766(define_expand "cpymemsi"
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
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{
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
1791 if (TARGET_ZIFENCEI)
1792 emit_insn (gen_fence_i ());
1793#endif
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)]
1804 "TARGET_ZIFENCEI"
1805 "fence.i")
1806
1807;;
1808;; ....................
1809;;
1810;; SHIFTS
1811;;
1812;; ....................
1813
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
1819(define_insn "<optab>si3"
1820 [(set (match_operand:SI 0 "register_operand" "= r")
1821 (any_shift:SI
1822 (match_operand:SI 1 "register_operand" " r")
1823 (match_operand:QI 2 "arith_operand" " rI")))]
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
1830 return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2";
1831}
1832 [(set_attr "type" "shift")
1833 (set_attr "mode" "SI")])
1834
1835(define_insn_and_split "*<optab>si3_mask"
1836 [(set (match_operand:SI 0 "register_operand" "= r")
1837 (any_shift:SI
1838 (match_operand:SI 1 "register_operand" " r")
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"))])))]
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
1854(define_insn_and_split "*<optab>si3_mask_1"
1855 [(set (match_operand:SI 0 "register_operand" "= r")
1856 (any_shift:SI
1857 (match_operand:SI 1 "register_operand" " r")
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"))])))]
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
1874(define_insn "<optab>di3"
1875 [(set (match_operand:DI 0 "register_operand" "= r")
1876 (any_shift:DI
1877 (match_operand:DI 1 "register_operand" " r")
1878 (match_operand:QI 2 "arith_operand" " rI")))]
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
1885 return "<insn>%i2\t%0,%1,%2";
1886}
1887 [(set_attr "type" "shift")
1888 (set_attr "mode" "DI")])
1889
1890(define_insn_and_split "*<optab>di3_mask"
1891 [(set (match_operand:DI 0 "register_operand" "= r")
1892 (any_shift:DI
1893 (match_operand:DI 1 "register_operand" " r")
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"))])))]
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
1910(define_insn_and_split "*<optab>di3_mask_1"
1911 [(set (match_operand:DI 0 "register_operand" "= r")
1912 (any_shift:DI
1913 (match_operand:DI 1 "register_operand" " r")
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"))])))]
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
1930(define_insn "*<optab>si3_extend"
1931 [(set (match_operand:DI 0 "register_operand" "= r")
1932 (sign_extend:DI
1933 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
1934 (match_operand:QI 2 "arith_operand" " rI"))))]
1935 "TARGET_64BIT"
1936{
1937 if (GET_CODE (operands[2]) == CONST_INT)
1938 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1939
1940 return "<insn>%i2w\t%0,%1,%2";
1941}
1942 [(set_attr "type" "shift")
1943 (set_attr "mode" "SI")])
1944
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")
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"))]))))]
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")
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"))]))))]
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
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")
1995 (match_operand 2 "const_int_operand"))))]
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
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.
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.
2039(define_split
2040 [(set (match_operand:GPR 0 "register_operand")
2041 (and:GPR (match_operand:GPR 1 "register_operand")
2042 (match_operand:GPR 2 "p2m1_shift_operand")))
2043 (clobber (match_operand:GPR 3 "register_operand"))]
2044 ""
2045 [(set (match_dup 3)
2046 (ashift:GPR (match_dup 1) (match_dup 2)))
2047 (set (match_dup 0)
2048 (lshiftrt:GPR (match_dup 3) (match_dup 2)))]
2049{
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]))
2052 - exact_log2 (INTVAL (operands[2]) + 1));
2053})
2054
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")
2060 (match_operand:DI 2 "high_mask_shift_operand")))
2061 (clobber (match_operand:DI 3 "register_operand"))]
2062 "TARGET_64BIT"
2063 [(set (match_dup 3)
2064 (lshiftrt:DI (match_dup 1) (match_dup 2)))
2065 (set (match_dup 0)
2066 (ashift:DI (match_dup 3) (match_dup 2)))]
2067{
2068 operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2])));
2069})
2070
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
2093;;
2094;; ....................
2095;;
2096;; CONDITIONAL BRANCHES
2097;;
2098;; ....................
2099
2100;; Conditional branches
2101
2102(define_insn "*branch<mode>"
2103 [(set (pc)
2104 (if_then_else
2105 (match_operator 1 "order_operator"
2106 [(match_operand:X 2 "register_operand" "r")
2107 (match_operand:X 3 "reg_or_0_operand" "rJ")])
2108 (label_ref (match_operand 0 "" ""))
2109 (pc)))]
2110 ""
2111 "b%C1\t%2,%z3,%0"
2112 [(set_attr "type" "branch")
2113 (set_attr "mode" "none")])
2114
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>")])
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
2156(define_expand "@cbranch<mode>4"
2157 [(set (pc)
2158 (if_then_else (match_operator 0 "comparison_operator"
2159 [(match_operand:BR 1 "register_operand")
2160 (match_operand:BR 2 "nonmemory_operand")])
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
2170(define_expand "@cbranch<mode>4"
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
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)))
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
2202 (match_op_dup 0 [(match_dup 4) (const_int 0)])
2203 (label_ref (match_operand 1))
2204 (pc)))]
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
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)))
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
2233 (match_op_dup 0 [(match_dup 4) (const_int 0)])
2234 (label_ref (match_operand 1))
2235 (pc)))]
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"
2252 [(match_operand:GPR 2 "register_operand")
2253 (match_operand:GPR 3 "nonmemory_operand")]))]
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"
2264 [(match_operand:ANYF 2 "register_operand")
2265 (match_operand:ANYF 3 "register_operand")]))]
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"
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")]))]
2278 "TARGET_HARD_FLOAT"
2279 "f%C1.<fmt>\t%0,%2,%3"
2280 [(set_attr "type" "fcmp")
2281 (set_attr "mode" "<UNITMODE>")])
2282
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")
2294 (unspec:X
2295 [(match_operand:ANYF 1 "register_operand" " f")
2296 (match_operand:ANYF 2 "register_operand" " f")]
2297 QUIET_COMPARISON))
2298 (clobber (match_scratch:X 3 "=&r"))]
2299 "TARGET_HARD_FLOAT && ! HONOR_SNANS (<ANYF:MODE>mode)"
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
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
2318(define_insn "*seq_zero_<X:mode><GPR:mode>"
2319 [(set (match_operand:GPR 0 "register_operand" "=r")
2320 (eq:GPR (match_operand:X 1 "register_operand" " r")
2321 (const_int 0)))]
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>"
2328 [(set (match_operand:GPR 0 "register_operand" "=r")
2329 (ne:GPR (match_operand:X 1 "register_operand" " r")
2330 (const_int 0)))]
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>"
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")))]
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>"
2346 [(set (match_operand:GPR 0 "register_operand" "=r")
2347 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
2348 (const_int 1)))]
2349 ""
2350 "slt%i2<u>\t%0,zero,%1"
2351 [(set_attr "type" "slt")
2352 (set_attr "mode" "<X:MODE>")])
2353
2354(define_insn "*slt<u>_<X:mode><GPR:mode>"
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")))]
2358 ""
2359 "slt%i2<u>\t%0,%1,%2"
2360 [(set_attr "type" "slt")
2361 (set_attr "mode" "<X:MODE>")])
2362
2363(define_insn "*sle<u>_<X:mode><GPR:mode>"
2364 [(set (match_operand:GPR 0 "register_operand" "=r")
2365 (any_le:GPR (match_operand:X 1 "register_operand" " r")
2366 (match_operand:X 2 "sle_operand" "")))]
2367 ""
2368{
2369 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
2370 return "slt%i2<u>\t%0,%1,%2";
2371}
2372 [(set_attr "type" "slt")
2373 (set_attr "mode" "<X:MODE>")])
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{
2467 riscv_expand_epilogue (NORMAL_RETURN);
2468 DONE;
2469})
2470
2471(define_expand "sibcall_epilogue"
2472 [(const_int 2)]
2473 ""
2474{
2475 riscv_expand_epilogue (SIBCALL_RETURN);
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 ""
2490{
2491 return riscv_output_return ();
2492}
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]));
2517
2518 emit_jump_insn (gen_eh_return_internal ());
2519 emit_barrier ();
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
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
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
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
2694(define_insn "gpr_save"
2695 [(match_parallel 1 "gpr_save_operation"
2696 [(unspec_volatile [(match_operand 0 "const_int_operand")]
2697 UNSPECV_GPR_SAVE)])]
2698 ""
2699 "call\tt0,__riscv_save_%0")
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"
2717 "frflags\t%0")
2718
2719(define_insn "riscv_fsflags"
2720 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2721 "TARGET_HARD_FLOAT"
2722 "fsflags\t%0")
2723
2724(define_insn "riscv_mret"
2725 [(return)
2726 (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
2727 ""
2728 "mret")
2729
2730(define_insn "riscv_sret"
2731 [(return)
2732 (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
2733 ""
2734 "sret")
2735
2736(define_insn "riscv_uret"
2737 [(return)
2738 (unspec_volatile [(const_int 0)] UNSPECV_URET)]
2739 ""
2740 "uret")
2741
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
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
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
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
2832 rtx cond = gen_rtx_EQ (VOIDmode, result, const0_rtx);
2833 emit_jump_insn (gen_cbranch4 (mode, cond, result, const0_rtx, operands[2]));
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
2848(include "sync.md")
2849(include "peephole.md")
2850(include "pic.md")
2851(include "generic.md")
2852(include "sifive-7.md")