]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/riscv/riscv.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / riscv / riscv.md
CommitLineData
09cae750 1;; Machine description for RISC-V for GNU compiler.
83ffe9cd 2;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
09cae750
PD
3;; Contributed by Andrew Waterman (andrew@sifive.com).
4;; Based on MIPS target for GNU compiler.
5
6;; This file is part of GCC.
7
8;; GCC is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation; either version 3, or (at your option)
11;; any later version.
12
13;; GCC is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with GCC; see the file COPYING3. If not see
20;; <http://www.gnu.org/licenses/>.
21
380b8fd9
AP
22
23;; Keep this list and the one above riscv_print_operand in sync.
24;; The special asm out single letter directives following a '%' are:
25;; h -- Print the high-part relocation associated with OP, after stripping
26;; any outermost HIGH.
27;; R -- Print the low-part relocation associated with OP.
28;; C -- Print the integer branch condition for comparison OP.
29;; A -- Print the atomic operation suffix for memory model OP.
30;; F -- Print a FENCE if the memory model requires a release.
31;; z -- Print x0 if OP is zero, otherwise print OP normally.
32;; i -- Print i if the operand is not a register.
33;; S -- Print shift-index of single-bit mask OP.
34;; T -- Print shift-index of inverted single-bit mask OP.
473d7aad 35;; ~ -- Print w if TARGET_64BIT is true; otherwise not print anything.
380b8fd9 36
09cae750
PD
37(define_c_enum "unspec" [
38 ;; Override return address for exception handling.
39 UNSPEC_EH_RETURN
40
41 ;; Symbolic accesses. The order of this list must match that of
42 ;; enum riscv_symbol_type in riscv-protos.h.
43 UNSPEC_ADDRESS_FIRST
44 UNSPEC_PCREL
45 UNSPEC_LOAD_GOT
46 UNSPEC_TLS
47 UNSPEC_TLS_LE
48 UNSPEC_TLS_IE
49 UNSPEC_TLS_GD
50
51 ;; High part of PC-relative address.
52 UNSPEC_AUIPC
53
54 ;; Floating-point unspecs.
55 UNSPEC_FLT_QUIET
56 UNSPEC_FLE_QUIET
57 UNSPEC_COPYSIGN
58 UNSPEC_LRINT
59 UNSPEC_LROUND
9ddd44b5
MR
60 UNSPEC_FMIN
61 UNSPEC_FMAX
09cae750
PD
62
63 ;; Stack tie
64 UNSPEC_TIE
eab3d2d1
PT
65
66 ;; OR-COMBINE
67 UNSPEC_ORC_B
09cae750
PD
68])
69
70(define_c_enum "unspecv" [
71 ;; Register save and restore.
72 UNSPECV_GPR_SAVE
73 UNSPECV_GPR_RESTORE
74
75 ;; Floating-point unspecs.
76 UNSPECV_FRFLAGS
77 UNSPECV_FSFLAGS
94f5a8f0 78 UNSPECV_FSNVSNAN
09cae750 79
d0ebdd9f
JW
80 ;; Interrupt handler instructions.
81 UNSPECV_MRET
ec74725c
JW
82 UNSPECV_SRET
83 UNSPECV_URET
d0ebdd9f 84
09cae750
PD
85 ;; Blockage and synchronization.
86 UNSPECV_BLOCKAGE
87 UNSPECV_FENCE
88 UNSPECV_FENCE_I
c931e8d5
CQ
89
90 ;; Stack Smash Protector
91 UNSPEC_SSP_SET
92 UNSPEC_SSP_TEST
3df3ca90
S
93
94 ;; CMO instructions.
95 UNSPECV_CLEAN
96 UNSPECV_FLUSH
97 UNSPECV_INVAL
98 UNSPECV_ZERO
99 UNSPECV_PREI
c717a92d
PT
100
101 ;; Zihintpause unspec
102 UNSPECV_PAUSE
09cae750
PD
103])
104
105(define_constants
106 [(RETURN_ADDR_REGNUM 1)
d0ebdd9f 107 (GP_REGNUM 3)
1073b500 108 (TP_REGNUM 4)
09cae750
PD
109 (T0_REGNUM 5)
110 (T1_REGNUM 6)
111 (S0_REGNUM 8)
112 (S1_REGNUM 9)
113 (S2_REGNUM 18)
d0e0c130
KC
114 (S3_REGNUM 19)
115 (S4_REGNUM 20)
116 (S5_REGNUM 21)
117 (S6_REGNUM 22)
118 (S7_REGNUM 23)
119 (S8_REGNUM 24)
120 (S9_REGNUM 25)
121 (S10_REGNUM 26)
122 (S11_REGNUM 27)
fd1e52dc
JW
123
124 (NORMAL_RETURN 0)
125 (SIBCALL_RETURN 1)
126 (EXCEPTION_RETURN 2)
31380d4b 127 (VL_REGNUM 66)
128 (VTYPE_REGNUM 67)
09cae750
PD
129])
130
131(include "predicates.md")
132(include "constraints.md")
43e74147 133(include "iterators.md")
09cae750
PD
134
135;; ....................
136;;
137;; Attributes
138;;
139;; ....................
140
141(define_attr "got" "unset,xgot_high,load"
142 (const_string "unset"))
143
144;; Classification of moves, extensions and truncations. Most values
145;; are as for "type" (see below) but there are also the following
146;; move-specific values:
147;;
148;; andi a single ANDI instruction
149;; shift_shift a shift left followed by a shift right
150;;
151;; This attribute is used to determine the instruction's length and
152;; scheduling type. For doubleword moves, the attribute always describes
153;; the split instructions; in some cases, it is more appropriate for the
154;; scheduling type to be "multi" instead.
155(define_attr "move_type"
156 "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove,
8fe75147 157 const,logical,arith,andi,shift_shift,rdvlenb"
09cae750
PD
158 (const_string "unknown"))
159
160;; Main data type used by the insn
f556cd8b
JZZ
161(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,HF,SF,DF,TF,
162 VNx1BI,VNx2BI,VNx4BI,VNx8BI,VNx16BI,VNx32BI,VNx64BI,
163 VNx1QI,VNx2QI,VNx4QI,VNx8QI,VNx16QI,VNx32QI,VNx64QI,
164 VNx1HI,VNx2HI,VNx4HI,VNx8HI,VNx16HI,VNx32HI,
165 VNx1SI,VNx2SI,VNx4SI,VNx8SI,VNx16SI,
166 VNx1DI,VNx2DI,VNx4DI,VNx8DI,
167 VNx1SF,VNx2SF,VNx4SF,VNx8SF,VNx16SF,
168 VNx1DF,VNx2DF,VNx4DF,VNx8DF"
09cae750
PD
169 (const_string "unknown"))
170
171;; True if the main data type is twice the size of a word.
172(define_attr "dword_mode" "no,yes"
173 (cond [(and (eq_attr "mode" "DI,DF")
174 (eq (symbol_ref "TARGET_64BIT") (const_int 0)))
175 (const_string "yes")
176
177 (and (eq_attr "mode" "TI,TF")
178 (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
179 (const_string "yes")]
180 (const_string "no")))
181
8fe75147 182;; ISA attributes.
183(define_attr "ext" "base,f,d,vector"
184 (const_string "base"))
185
186;; True if the extension is enabled.
187(define_attr "ext_enabled" "no,yes"
188 (cond [(eq_attr "ext" "base")
189 (const_string "yes")
190
191 (and (eq_attr "ext" "f")
192 (match_test "TARGET_HARD_FLOAT"))
193 (const_string "yes")
194
195 (and (eq_attr "ext" "d")
196 (match_test "TARGET_DOUBLE_FLOAT"))
197 (const_string "yes")
198
199 (and (eq_attr "ext" "vector")
200 (match_test "TARGET_VECTOR"))
201 (const_string "yes")
202 ]
203 (const_string "no")))
204
205;; Attribute to control enable or disable instructions.
206(define_attr "enabled" "no,yes"
207 (cond [(eq_attr "ext_enabled" "no")
208 (const_string "no")]
209 (const_string "yes")))
210
09cae750
PD
211;; Classification of each insn.
212;; branch conditional branch
213;; jump unconditional jump
214;; call unconditional call
215;; load load instruction(s)
216;; fpload floating point load
217;; store store instruction(s)
218;; fpstore floating point store
219;; mtc transfer to coprocessor
220;; mfc transfer from coprocessor
221;; const load constant
222;; arith integer arithmetic instructions
223;; logical integer logical instructions
224;; shift integer shift instructions
225;; slt set less than instructions
226;; imul integer multiply
227;; idiv integer divide
228;; move integer register move (addi rd, rs1, 0)
229;; fmove floating point register move
230;; fadd floating point add/subtract
231;; fmul floating point multiply
232;; fmadd floating point multiply-add
233;; fdiv floating point divide
234;; fcmp floating point compare
235;; fcvt floating point convert
236;; fsqrt floating point square root
237;; multi multiword sequence (or user asm statements)
3895dd76
CM
238;; auipc integer addition to PC
239;; sfb_alu SFB ALU instruction
09cae750
PD
240;; nop no operation
241;; ghost an instruction that produces no real code
833e651a 242;; bitmanip bit manipulation instructions
3895dd76
CM
243;; rotate rotation instructions
244;; atomic atomic instructions
b8426900 245;; Classification of RVV instructions which will be added to each RVV .md pattern and used by scheduler.
246;; rdvlenb vector byte length vlenb csrr read
247;; rdvl vector length vl csrr read
1627d052 248;; vsetvl vector configuration-setting instrucions
b8426900 249;; 7. Vector Loads and Stores
250;; vlde vector unit-stride load instructions
251;; vste vector unit-stride store instructions
252;; vldm vector unit-stride mask load instructions
253;; vstm vector unit-stride mask store instructions
254;; vlds vector strided load instructions
255;; vsts vector strided store instructions
256;; vldux vector unordered indexed load instructions
257;; vldox vector ordered indexed load instructions
258;; vstux vector unordered indexed store instructions
259;; vstox vector ordered indexed store instructions
260;; vldff vector unit-stride fault-only-first load instructions
261;; vldr vector whole register load instructions
262;; vstr vector whole register store instructions
263;; 11. Vector integer arithmetic instructions
264;; vialu vector single-width integer add and subtract and logical nstructions
265;; viwalu vector widening integer add/subtract
266;; vext vector integer extension
267;; vicalu vector arithmetic with carry or borrow instructions
268;; vshift vector single-width bit shift instructions
269;; vnshift vector narrowing integer shift instructions
270;; vicmp vector integer comparison/min/max instructions
271;; vimul vector single-width integer multiply instructions
272;; vidiv vector single-width integer divide instructions
273;; viwmul vector widening integer multiply instructions
274;; vimuladd vector single-width integer multiply-add instructions
275;; viwmuladd vector widening integer multiply-add instructions
276;; vimerge vector integer merge instructions
277;; vimov vector integer move vector instructions
278;; 12. Vector fixed-point arithmetic instructions
279;; vsalu vector single-width saturating add and subtract and logical instructions
280;; vaalu vector single-width averaging add and subtract and logical instructions
281;; vsmul vector single-width fractional multiply with rounding and saturation instructions
282;; vsshift vector single-width scaling shift instructions
283;; vnclip vector narrowing fixed-point clip instructions
284;; 13. Vector floating-point instructions
285;; vfalu vector single-width floating-point add/subtract instructions
286;; vfwalu vector widening floating-point add/subtract instructions
287;; vfmul vector single-width floating-point multiply instructions
288;; vfdiv vector single-width floating-point divide instructions
289;; vfwmul vector widening floating-point multiply instructions
290;; vfmuladd vector single-width floating-point multiply-add instructions
291;; vfwmuladd vector widening floating-point multiply-add instructions
292;; vfsqrt vector floating-point square-root instructions
293;; vfrecp vector floating-point reciprocal square-root instructions
294;; vfcmp vector floating-point comparison/min/max instructions
295;; vfsgnj vector floating-point sign-injection instructions
296;; vfclass vector floating-point classify instruction
297;; vfmerge vector floating-point merge instruction
298;; vfmov vector floating-point move instruction
299;; vfcvtitof vector single-width integer to floating-point instruction
300;; vfcvtftoi vector single-width floating-point to integer instruction
301;; vfwcvtitof vector widening integer to floating-point instruction
302;; vfwcvtftoi vector widening floating-point to integer instruction
303;; vfwcvtftof vector widening floating-point to floating-point instruction
304;; vfncvtitof vector narrowing integer to floating-point instruction
305;; vfncvtftoi vector narrowing floating-point to integer instruction
306;; vfncvtftof vector narrowing floating-point to floating-point instruction
307;; 14. Vector reduction operations
308;; vired vector single-width integer reduction instructions
309;; viwred vector widening integer reduction instructions
310;; vfred vector single-width floating-point un-ordered reduction instruction
311;; vfredo vector single-width floating-point ordered reduction instruction
312;; vfwred vector widening floating-point un-ordered reduction instruction
313;; vfwredo vector widening floating-point ordered reduction instruction
314;; 15. Vector mask instructions
315;; vmalu vector mask-register logical instructions
316;; vmpop vector mask population count
317;; vmffs vector find-first-set mask bit
318;; vmsfs vector set mask bit
319;; vmiota vector iota
320;; vmidx vector element index instruction
321;; 16. Vector permutation instructions
322;; vimovvx integer scalar move instructions
323;; vimovxv integer scalar move instructions
324;; vfmovvf floating-point scalar move instructions
325;; vfmovfv floating-point scalar move instructions
326;; vislide vector slide instructions
327;; vislide1 vector slide instructions
328;; vfslide1 vector slide instructions
329;; vgather vector register gather instructions
330;; vcompress vector compress instruction
331;; vmov whole vector register move
09cae750
PD
332(define_attr "type"
333 "unknown,branch,jump,call,load,fpload,store,fpstore,
334 mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
b8426900 335 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate,
bdac4b47 336 atomic,rdvlenb,rdvl,vsetvl,vlde,vste,vldm,vstm,vlds,vsts,
b8426900 337 vldux,vldox,vstux,vstox,vldff,vldr,vstr,
338 vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,
339 vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge,vimov,
340 vsalu,vaalu,vsmul,vsshift,vnclip,
341 vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp,
342 vfcmp,vfsgnj,vfclass,vfmerge,vfmov,
343 vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi,
344 vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof,
345 vired,viwred,vfred,vfredo,vfwred,vfwredo,
346 vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,vfmovvf,vfmovfv,
347 vislide,vislide1,vfslide1,vgather,vcompress,vmov"
09cae750
PD
348 (cond [(eq_attr "got" "load") (const_string "load")
349
350 ;; If a doubleword move uses these expensive instructions,
351 ;; it is usually better to schedule them in the same way
352 ;; as the singleword form, rather than as "multi".
353 (eq_attr "move_type" "load") (const_string "load")
354 (eq_attr "move_type" "fpload") (const_string "fpload")
355 (eq_attr "move_type" "store") (const_string "store")
356 (eq_attr "move_type" "fpstore") (const_string "fpstore")
357 (eq_attr "move_type" "mtc") (const_string "mtc")
358 (eq_attr "move_type" "mfc") (const_string "mfc")
359
360 ;; These types of move are always single insns.
361 (eq_attr "move_type" "fmove") (const_string "fmove")
362 (eq_attr "move_type" "arith") (const_string "arith")
363 (eq_attr "move_type" "logical") (const_string "logical")
364 (eq_attr "move_type" "andi") (const_string "logical")
365
366 ;; These types of move are always split.
367 (eq_attr "move_type" "shift_shift")
368 (const_string "multi")
369
370 ;; These types of move are split for doubleword modes only.
371 (and (eq_attr "move_type" "move,const")
372 (eq_attr "dword_mode" "yes"))
373 (const_string "multi")
374 (eq_attr "move_type" "move") (const_string "move")
8fe75147 375 (eq_attr "move_type" "const") (const_string "const")
376 (eq_attr "move_type" "rdvlenb") (const_string "rdvlenb")]
09cae750
PD
377 (const_string "unknown")))
378
379;; Length of instruction in bytes.
380(define_attr "length" ""
381 (cond [
382 ;; Branches further than +/- 4 KiB require two instructions.
383 (eq_attr "type" "branch")
384 (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4088))
385 (le (minus (pc) (match_dup 0)) (const_int 4092)))
386 (const_int 4)
387 (const_int 8))
388
389 ;; Conservatively assume calls take two instructions (AUIPC + JALR).
390 ;; The linker will opportunistically relax the sequence to JAL.
391 (eq_attr "type" "call") (const_int 8)
392
393 ;; "Ghost" instructions occupy no space.
394 (eq_attr "type" "ghost") (const_int 0)
395
396 (eq_attr "got" "load") (const_int 8)
397
09cae750
PD
398 ;; SHIFT_SHIFTs are decomposed into two separate instructions.
399 (eq_attr "move_type" "shift_shift")
400 (const_int 8)
401
402 ;; Check for doubleword moves that are decomposed into two
403 ;; instructions.
404 (and (eq_attr "move_type" "mtc,mfc,move")
405 (eq_attr "dword_mode" "yes"))
406 (const_int 8)
407
408 ;; Doubleword CONST{,N} moves are split into two word
409 ;; CONST{,N} moves.
410 (and (eq_attr "move_type" "const")
411 (eq_attr "dword_mode" "yes"))
412 (symbol_ref "riscv_split_const_insns (operands[1]) * 4")
413
414 ;; Otherwise, constants, loads and stores are handled by external
415 ;; routines.
416 (eq_attr "move_type" "load,fpload")
417 (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4")
418 (eq_attr "move_type" "store,fpstore")
419 (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4")
420 ] (const_int 4)))
421
422;; Is copying of this instruction disallowed?
423(define_attr "cannot_copy" "no,yes" (const_string "no"))
424
88108b27
AW
425;; Microarchitectures we know how to tune for.
426;; Keep this in sync with enum riscv_microarchitecture.
427(define_attr "tune"
428 "generic,sifive_7"
429 (const (symbol_ref "((enum attr_tune) riscv_microarchitecture)")))
430
09cae750
PD
431;; Describe a user's asm statement.
432(define_asm_attributes
433 [(set_attr "type" "multi")])
434
09cae750
PD
435;; Ghost instructions produce no real code and introduce no hazards.
436;; They exist purely to express an effect on dataflow.
437(define_insn_reservation "ghost" 0
438 (eq_attr "type" "ghost")
439 "nothing")
440
441;;
442;; ....................
443;;
444;; ADDITION
445;;
446;; ....................
447;;
448
449(define_insn "add<mode>3"
248710c4
KC
450 [(set (match_operand:ANYF 0 "register_operand" "=f")
451 (plus:ANYF (match_operand:ANYF 1 "register_operand" " f")
452 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 453 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
454 "fadd.<fmt>\t%0,%1,%2"
455 [(set_attr "type" "fadd")
456 (set_attr "mode" "<UNITMODE>")])
457
458(define_insn "addsi3"
248710c4
KC
459 [(set (match_operand:SI 0 "register_operand" "=r,r")
460 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
461 (match_operand:SI 2 "arith_operand" " r,I")))]
09cae750 462 ""
473d7aad 463 "add%i2%~\t%0,%1,%2"
09cae750
PD
464 [(set_attr "type" "arith")
465 (set_attr "mode" "SI")])
466
467(define_insn "adddi3"
248710c4
KC
468 [(set (match_operand:DI 0 "register_operand" "=r,r")
469 (plus:DI (match_operand:DI 1 "register_operand" " r,r")
470 (match_operand:DI 2 "arith_operand" " r,I")))]
09cae750 471 "TARGET_64BIT"
0791ac18 472 "add%i2\t%0,%1,%2"
09cae750
PD
473 [(set_attr "type" "arith")
474 (set_attr "mode" "DI")])
475
6efd040c
L
476(define_expand "addv<mode>4"
477 [(set (match_operand:GPR 0 "register_operand" "=r,r")
478 (plus:GPR (match_operand:GPR 1 "register_operand" " r,r")
479 (match_operand:GPR 2 "arith_operand" " r,I")))
480 (label_ref (match_operand 3 "" ""))]
481 ""
482{
483 if (TARGET_64BIT && <MODE>mode == SImode)
484 {
485 rtx t3 = gen_reg_rtx (DImode);
486 rtx t4 = gen_reg_rtx (DImode);
487 rtx t5 = gen_reg_rtx (DImode);
488 rtx t6 = gen_reg_rtx (DImode);
489
490 emit_insn (gen_addsi3 (operands[0], operands[1], operands[2]));
491 if (GET_CODE (operands[1]) != CONST_INT)
492 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
493 else
494 t4 = operands[1];
495 if (GET_CODE (operands[2]) != CONST_INT)
496 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
497 else
498 t5 = operands[2];
499 emit_insn (gen_adddi3 (t3, t4, t5));
500 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
501
502 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
503 }
504 else
505 {
506 rtx t3 = gen_reg_rtx (<MODE>mode);
507 rtx t4 = gen_reg_rtx (<MODE>mode);
508
509 emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
510 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[2], const0_rtx);
511 emit_insn (gen_cstore<mode>4 (t3, cmp1, operands[2], const0_rtx));
512 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[0], operands[1]);
513
514 emit_insn (gen_cstore<mode>4 (t4, cmp2, operands[0], operands[1]));
515 riscv_expand_conditional_branch (operands[3], NE, t3, t4);
516 }
517 DONE;
518})
519
520(define_expand "uaddv<mode>4"
521 [(set (match_operand:GPR 0 "register_operand" "=r,r")
522 (plus:GPR (match_operand:GPR 1 "register_operand" " r,r")
523 (match_operand:GPR 2 "arith_operand" " r,I")))
524 (label_ref (match_operand 3 "" ""))]
525 ""
526{
527 if (TARGET_64BIT && <MODE>mode == SImode)
528 {
529 rtx t3 = gen_reg_rtx (DImode);
530 rtx t4 = gen_reg_rtx (DImode);
531
532 if (GET_CODE (operands[1]) != CONST_INT)
533 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
534 else
535 t3 = operands[1];
536 emit_insn (gen_addsi3 (operands[0], operands[1], operands[2]));
537 emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
538
539 riscv_expand_conditional_branch (operands[3], LTU, t4, t3);
540 }
541 else
542 {
543 emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
544 riscv_expand_conditional_branch (operands[3], LTU, operands[0],
545 operands[1]);
546 }
547
548 DONE;
549})
550
09cae750 551(define_insn "*addsi3_extended"
248710c4 552 [(set (match_operand:DI 0 "register_operand" "=r,r")
09cae750 553 (sign_extend:DI
248710c4
KC
554 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
555 (match_operand:SI 2 "arith_operand" " r,I"))))]
09cae750 556 "TARGET_64BIT"
0791ac18 557 "add%i2w\t%0,%1,%2"
09cae750
PD
558 [(set_attr "type" "arith")
559 (set_attr "mode" "SI")])
560
561(define_insn "*addsi3_extended2"
248710c4 562 [(set (match_operand:DI 0 "register_operand" "=r,r")
09cae750 563 (sign_extend:DI
7ac4dfec
MC
564 (match_operator:SI 3 "subreg_lowpart_operator"
565 [(plus:DI (match_operand:DI 1 "register_operand" " r,r")
566 (match_operand:DI 2 "arith_operand" " r,I"))])))]
09cae750 567 "TARGET_64BIT"
0791ac18 568 "add%i2w\t%0,%1,%2"
09cae750
PD
569 [(set_attr "type" "arith")
570 (set_attr "mode" "SI")])
571
572;;
573;; ....................
574;;
575;; SUBTRACTION
576;;
577;; ....................
578;;
579
580(define_insn "sub<mode>3"
248710c4
KC
581 [(set (match_operand:ANYF 0 "register_operand" "=f")
582 (minus:ANYF (match_operand:ANYF 1 "register_operand" " f")
583 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 584 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
585 "fsub.<fmt>\t%0,%1,%2"
586 [(set_attr "type" "fadd")
587 (set_attr "mode" "<UNITMODE>")])
588
589(define_insn "subdi3"
248710c4
KC
590 [(set (match_operand:DI 0 "register_operand" "= r")
591 (minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
592 (match_operand:DI 2 "register_operand" " r")))]
09cae750
PD
593 "TARGET_64BIT"
594 "sub\t%0,%z1,%2"
595 [(set_attr "type" "arith")
596 (set_attr "mode" "DI")])
597
598(define_insn "subsi3"
248710c4
KC
599 [(set (match_operand:SI 0 "register_operand" "= r")
600 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
601 (match_operand:SI 2 "register_operand" " r")))]
09cae750 602 ""
473d7aad 603 "sub%~\t%0,%z1,%2"
09cae750
PD
604 [(set_attr "type" "arith")
605 (set_attr "mode" "SI")])
606
6efd040c
L
607(define_expand "subv<mode>4"
608 [(set (match_operand:GPR 0 "register_operand" "= r")
609 (minus:GPR (match_operand:GPR 1 "reg_or_0_operand" " rJ")
610 (match_operand:GPR 2 "register_operand" " r")))
611 (label_ref (match_operand 3 "" ""))]
612 ""
613{
614 if (TARGET_64BIT && <MODE>mode == SImode)
615 {
616 rtx t3 = gen_reg_rtx (DImode);
617 rtx t4 = gen_reg_rtx (DImode);
618 rtx t5 = gen_reg_rtx (DImode);
619 rtx t6 = gen_reg_rtx (DImode);
620
621 emit_insn (gen_subsi3 (operands[0], operands[1], operands[2]));
622 if (GET_CODE (operands[1]) != CONST_INT)
623 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
624 else
625 t4 = operands[1];
626 if (GET_CODE (operands[2]) != CONST_INT)
627 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
628 else
629 t5 = operands[2];
630 emit_insn (gen_subdi3 (t3, t4, t5));
631 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
632
633 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
634 }
635 else
636 {
637 rtx t3 = gen_reg_rtx (<MODE>mode);
638 rtx t4 = gen_reg_rtx (<MODE>mode);
639
640 emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
641
642 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[2], const0_rtx);
643 emit_insn (gen_cstore<mode>4 (t3, cmp1, operands[2], const0_rtx));
644
645 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[1], operands[0]);
646 emit_insn (gen_cstore<mode>4 (t4, cmp2, operands[1], operands[0]));
647
648 riscv_expand_conditional_branch (operands[3], NE, t3, t4);
649 }
650
651 DONE;
652})
653
654(define_expand "usubv<mode>4"
655 [(set (match_operand:GPR 0 "register_operand" "= r")
656 (minus:GPR (match_operand:GPR 1 "reg_or_0_operand" " rJ")
657 (match_operand:GPR 2 "register_operand" " r")))
658 (label_ref (match_operand 3 "" ""))]
659 ""
660{
661 if (TARGET_64BIT && <MODE>mode == SImode)
662 {
663 rtx t3 = gen_reg_rtx (DImode);
664 rtx t4 = gen_reg_rtx (DImode);
665
666 if (GET_CODE (operands[1]) != CONST_INT)
667 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
668 else
669 t3 = operands[1];
670 emit_insn (gen_subsi3 (operands[0], operands[1], operands[2]));
671 emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
672
673 riscv_expand_conditional_branch (operands[3], LTU, t3, t4);
674 }
675 else
676 {
677 emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
678 riscv_expand_conditional_branch (operands[3], LTU, operands[1],
679 operands[0]);
680 }
681
682 DONE;
683})
684
685
09cae750 686(define_insn "*subsi3_extended"
248710c4 687 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 688 (sign_extend:DI
248710c4
KC
689 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
690 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
691 "TARGET_64BIT"
692 "subw\t%0,%z1,%2"
693 [(set_attr "type" "arith")
694 (set_attr "mode" "SI")])
695
696(define_insn "*subsi3_extended2"
01414d53 697 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 698 (sign_extend:DI
7ac4dfec
MC
699 (match_operator:SI 3 "subreg_lowpart_operator"
700 [(minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
701 (match_operand:DI 2 "register_operand" " r"))])))]
09cae750
PD
702 "TARGET_64BIT"
703 "subw\t%0,%z1,%2"
704 [(set_attr "type" "arith")
705 (set_attr "mode" "SI")])
706
01414d53
JW
707(define_insn "negdi2"
708 [(set (match_operand:DI 0 "register_operand" "=r")
709 (neg:DI (match_operand:DI 1 "register_operand" " r")))]
710 "TARGET_64BIT"
711 "neg\t%0,%1"
712 [(set_attr "type" "arith")
713 (set_attr "mode" "DI")])
714
715(define_insn "negsi2"
716 [(set (match_operand:SI 0 "register_operand" "=r")
717 (neg:SI (match_operand:SI 1 "register_operand" " r")))]
718 ""
473d7aad 719 "neg%~\t%0,%1"
01414d53
JW
720 [(set_attr "type" "arith")
721 (set_attr "mode" "SI")])
722
723(define_insn "*negsi2_extended"
724 [(set (match_operand:DI 0 "register_operand" "=r")
725 (sign_extend:DI
726 (neg:SI (match_operand:SI 1 "register_operand" " r"))))]
727 "TARGET_64BIT"
728 "negw\t%0,%1"
729 [(set_attr "type" "arith")
730 (set_attr "mode" "SI")])
731
732(define_insn "*negsi2_extended2"
733 [(set (match_operand:DI 0 "register_operand" "=r")
734 (sign_extend:DI
7ac4dfec
MC
735 (match_operator:SI 2 "subreg_lowpart_operator"
736 [(neg:DI (match_operand:DI 1 "register_operand" " r"))])))]
01414d53
JW
737 "TARGET_64BIT"
738 "negw\t%0,%1"
739 [(set_attr "type" "arith")
740 (set_attr "mode" "SI")])
741
09cae750
PD
742;;
743;; ....................
744;;
745;; MULTIPLICATION
746;;
747;; ....................
748;;
749
750(define_insn "mul<mode>3"
248710c4
KC
751 [(set (match_operand:ANYF 0 "register_operand" "=f")
752 (mult:ANYF (match_operand:ANYF 1 "register_operand" " f")
753 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 754 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
755 "fmul.<fmt>\t%0,%1,%2"
756 [(set_attr "type" "fmul")
757 (set_attr "mode" "<UNITMODE>")])
758
759(define_insn "mulsi3"
248710c4
KC
760 [(set (match_operand:SI 0 "register_operand" "=r")
761 (mult:SI (match_operand:SI 1 "register_operand" " r")
762 (match_operand:SI 2 "register_operand" " r")))]
77e8e405 763 "TARGET_ZMMUL || TARGET_MUL"
473d7aad 764 "mul%~\t%0,%1,%2"
09cae750
PD
765 [(set_attr "type" "imul")
766 (set_attr "mode" "SI")])
767
768(define_insn "muldi3"
248710c4
KC
769 [(set (match_operand:DI 0 "register_operand" "=r")
770 (mult:DI (match_operand:DI 1 "register_operand" " r")
771 (match_operand:DI 2 "register_operand" " r")))]
ae97ba1e 772 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
773 "mul\t%0,%1,%2"
774 [(set_attr "type" "imul")
775 (set_attr "mode" "DI")])
776
6efd040c
L
777(define_expand "mulv<mode>4"
778 [(set (match_operand:GPR 0 "register_operand" "=r")
779 (mult:GPR (match_operand:GPR 1 "register_operand" " r")
780 (match_operand:GPR 2 "register_operand" " r")))
781 (label_ref (match_operand 3 "" ""))]
77e8e405 782 "TARGET_ZMMUL || TARGET_MUL"
6efd040c
L
783{
784 if (TARGET_64BIT && <MODE>mode == SImode)
785 {
786 rtx t3 = gen_reg_rtx (DImode);
787 rtx t4 = gen_reg_rtx (DImode);
788 rtx t5 = gen_reg_rtx (DImode);
789 rtx t6 = gen_reg_rtx (DImode);
790
791 if (GET_CODE (operands[1]) != CONST_INT)
792 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
793 else
794 t4 = operands[1];
795 if (GET_CODE (operands[2]) != CONST_INT)
796 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
797 else
798 t5 = operands[2];
799 emit_insn (gen_muldi3 (t3, t4, t5));
800
801 emit_move_insn (operands[0], gen_lowpart (SImode, t3));
802 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
803
804 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
805 }
806 else
807 {
808 rtx hp = gen_reg_rtx (<MODE>mode);
809 rtx lp = gen_reg_rtx (<MODE>mode);
810
68c081bb 811 emit_insn (gen_smul<mode>3_highpart (hp, operands[1], operands[2]));
6efd040c
L
812 emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
813 emit_insn (gen_ashr<mode>3 (lp, operands[0],
814 GEN_INT (BITS_PER_WORD - 1)));
815
816 riscv_expand_conditional_branch (operands[3], NE, hp, lp);
817 }
818
819 DONE;
820})
821
822(define_expand "umulv<mode>4"
823 [(set (match_operand:GPR 0 "register_operand" "=r")
824 (mult:GPR (match_operand:GPR 1 "register_operand" " r")
825 (match_operand:GPR 2 "register_operand" " r")))
826 (label_ref (match_operand 3 "" ""))]
77e8e405 827 "TARGET_ZMMUL || TARGET_MUL"
6efd040c
L
828{
829 if (TARGET_64BIT && <MODE>mode == SImode)
830 {
831 rtx t3 = gen_reg_rtx (DImode);
832 rtx t4 = gen_reg_rtx (DImode);
833 rtx t5 = gen_reg_rtx (DImode);
834 rtx t6 = gen_reg_rtx (DImode);
835 rtx t7 = gen_reg_rtx (DImode);
836 rtx t8 = gen_reg_rtx (DImode);
837
838 if (GET_CODE (operands[1]) != CONST_INT)
839 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
840 else
841 t3 = operands[1];
842 if (GET_CODE (operands[2]) != CONST_INT)
843 emit_insn (gen_extend_insn (t4, operands[2], DImode, SImode, 0));
844 else
845 t4 = operands[2];
846
847 emit_insn (gen_ashldi3 (t5, t3, GEN_INT (32)));
848 emit_insn (gen_ashldi3 (t6, t4, GEN_INT (32)));
849 emit_insn (gen_umuldi3_highpart (t7, t5, t6));
850 emit_move_insn (operands[0], gen_lowpart (SImode, t7));
851 emit_insn (gen_lshrdi3 (t8, t7, GEN_INT (32)));
852
853 riscv_expand_conditional_branch (operands[3], NE, t8, const0_rtx);
854 }
855 else
856 {
857 rtx hp = gen_reg_rtx (<MODE>mode);
858
859 emit_insn (gen_umul<mode>3_highpart (hp, operands[1], operands[2]));
860 emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
861
862 riscv_expand_conditional_branch (operands[3], NE, hp, const0_rtx);
863 }
864
865 DONE;
866})
867
09cae750 868(define_insn "*mulsi3_extended"
248710c4 869 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 870 (sign_extend:DI
248710c4
KC
871 (mult:SI (match_operand:SI 1 "register_operand" " r")
872 (match_operand:SI 2 "register_operand" " r"))))]
77e8e405 873 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
874 "mulw\t%0,%1,%2"
875 [(set_attr "type" "imul")
876 (set_attr "mode" "SI")])
877
878(define_insn "*mulsi3_extended2"
248710c4 879 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 880 (sign_extend:DI
7ac4dfec
MC
881 (match_operator:SI 3 "subreg_lowpart_operator"
882 [(mult:DI (match_operand:DI 1 "register_operand" " r")
883 (match_operand:DI 2 "register_operand" " r"))])))]
77e8e405 884 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
885 "mulw\t%0,%1,%2"
886 [(set_attr "type" "imul")
887 (set_attr "mode" "SI")])
888
889;;
890;; ........................
891;;
892;; MULTIPLICATION HIGH-PART
893;;
894;; ........................
895;;
896
897
898(define_expand "<u>mulditi3"
248710c4 899 [(set (match_operand:TI 0 "register_operand")
09cae750
PD
900 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
901 (any_extend:TI (match_operand:DI 2 "register_operand"))))]
77e8e405 902 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
903{
904 rtx low = gen_reg_rtx (DImode);
905 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
906
907 rtx high = gen_reg_rtx (DImode);
68c081bb 908 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
09cae750
PD
909
910 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
911 emit_move_insn (gen_highpart (DImode, operands[0]), high);
912 DONE;
913})
914
68c081bb 915(define_insn "<su>muldi3_highpart"
248710c4 916 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750
PD
917 (truncate:DI
918 (lshiftrt:TI
919 (mult:TI (any_extend:TI
248710c4 920 (match_operand:DI 1 "register_operand" " r"))
09cae750 921 (any_extend:TI
248710c4 922 (match_operand:DI 2 "register_operand" " r")))
09cae750 923 (const_int 64))))]
77e8e405 924 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
925 "mulh<u>\t%0,%1,%2"
926 [(set_attr "type" "imul")
927 (set_attr "mode" "DI")])
928
929(define_expand "usmulditi3"
248710c4 930 [(set (match_operand:TI 0 "register_operand")
09cae750
PD
931 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand"))
932 (sign_extend:TI (match_operand:DI 2 "register_operand"))))]
77e8e405 933 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
934{
935 rtx low = gen_reg_rtx (DImode);
936 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
937
938 rtx high = gen_reg_rtx (DImode);
939 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2]));
940
941 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
942 emit_move_insn (gen_highpart (DImode, operands[0]), high);
943 DONE;
944})
945
946(define_insn "usmuldi3_highpart"
248710c4 947 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750
PD
948 (truncate:DI
949 (lshiftrt:TI
950 (mult:TI (zero_extend:TI
248710c4 951 (match_operand:DI 1 "register_operand" "r"))
09cae750 952 (sign_extend:TI
248710c4 953 (match_operand:DI 2 "register_operand" " r")))
09cae750 954 (const_int 64))))]
77e8e405 955 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
956 "mulhsu\t%0,%2,%1"
957 [(set_attr "type" "imul")
958 (set_attr "mode" "DI")])
959
960(define_expand "<u>mulsidi3"
248710c4 961 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 962 (mult:DI (any_extend:DI
248710c4 963 (match_operand:SI 1 "register_operand" " r"))
09cae750 964 (any_extend:DI
248710c4 965 (match_operand:SI 2 "register_operand" " r"))))]
77e8e405 966 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
09cae750
PD
967{
968 rtx temp = gen_reg_rtx (SImode);
969 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
68c081bb 970 emit_insn (gen_<su>mulsi3_highpart (riscv_subword (operands[0], true),
09cae750
PD
971 operands[1], operands[2]));
972 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
973 DONE;
974})
975
68c081bb 976(define_insn "<su>mulsi3_highpart"
248710c4 977 [(set (match_operand:SI 0 "register_operand" "=r")
09cae750
PD
978 (truncate:SI
979 (lshiftrt:DI
980 (mult:DI (any_extend:DI
248710c4 981 (match_operand:SI 1 "register_operand" " r"))
09cae750 982 (any_extend:DI
248710c4 983 (match_operand:SI 2 "register_operand" " r")))
09cae750 984 (const_int 32))))]
77e8e405 985 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
09cae750
PD
986 "mulh<u>\t%0,%1,%2"
987 [(set_attr "type" "imul")
988 (set_attr "mode" "SI")])
989
990
991(define_expand "usmulsidi3"
248710c4 992 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 993 (mult:DI (zero_extend:DI
248710c4 994 (match_operand:SI 1 "register_operand" " r"))
09cae750 995 (sign_extend:DI
248710c4 996 (match_operand:SI 2 "register_operand" " r"))))]
77e8e405 997 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
09cae750
PD
998{
999 rtx temp = gen_reg_rtx (SImode);
1000 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
1001 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true),
1002 operands[1], operands[2]));
1003 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
1004 DONE;
1005})
1006
1007(define_insn "usmulsi3_highpart"
248710c4 1008 [(set (match_operand:SI 0 "register_operand" "=r")
09cae750
PD
1009 (truncate:SI
1010 (lshiftrt:DI
1011 (mult:DI (zero_extend:DI
248710c4 1012 (match_operand:SI 1 "register_operand" " r"))
09cae750 1013 (sign_extend:DI
248710c4 1014 (match_operand:SI 2 "register_operand" " r")))
09cae750 1015 (const_int 32))))]
77e8e405 1016 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
09cae750
PD
1017 "mulhsu\t%0,%2,%1"
1018 [(set_attr "type" "imul")
1019 (set_attr "mode" "SI")])
1020
1021;;
1022;; ....................
1023;;
1024;; DIVISION and REMAINDER
1025;;
1026;; ....................
1027;;
1028
1029(define_insn "<optab>si3"
248710c4
KC
1030 [(set (match_operand:SI 0 "register_operand" "=r")
1031 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1032 (match_operand:SI 2 "register_operand" " r")))]
09cae750 1033 "TARGET_DIV"
473d7aad 1034 "<insn>%i2%~\t%0,%1,%2"
09cae750
PD
1035 [(set_attr "type" "idiv")
1036 (set_attr "mode" "SI")])
1037
1038(define_insn "<optab>di3"
248710c4
KC
1039 [(set (match_operand:DI 0 "register_operand" "=r")
1040 (any_div:DI (match_operand:DI 1 "register_operand" " r")
1041 (match_operand:DI 2 "register_operand" " r")))]
09cae750 1042 "TARGET_DIV && TARGET_64BIT"
0791ac18 1043 "<insn>%i2\t%0,%1,%2"
09cae750
PD
1044 [(set_attr "type" "idiv")
1045 (set_attr "mode" "DI")])
1046
1047(define_insn "*<optab>si3_extended"
248710c4 1048 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 1049 (sign_extend:DI
248710c4
KC
1050 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1051 (match_operand:SI 2 "register_operand" " r"))))]
09cae750 1052 "TARGET_DIV && TARGET_64BIT"
0791ac18 1053 "<insn>%i2w\t%0,%1,%2"
09cae750
PD
1054 [(set_attr "type" "idiv")
1055 (set_attr "mode" "DI")])
1056
1057(define_insn "div<mode>3"
248710c4
KC
1058 [(set (match_operand:ANYF 0 "register_operand" "=f")
1059 (div:ANYF (match_operand:ANYF 1 "register_operand" " f")
1060 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 1061 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
09cae750
PD
1062 "fdiv.<fmt>\t%0,%1,%2"
1063 [(set_attr "type" "fdiv")
1064 (set_attr "mode" "<UNITMODE>")])
1065
1066;;
1067;; ....................
1068;;
1069;; SQUARE ROOT
1070;;
1071;; ....................
1072
1073(define_insn "sqrt<mode>2"
248710c4
KC
1074 [(set (match_operand:ANYF 0 "register_operand" "=f")
1075 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
ac96e906 1076 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
09cae750
PD
1077{
1078 return "fsqrt.<fmt>\t%0,%1";
1079}
1080 [(set_attr "type" "fsqrt")
1081 (set_attr "mode" "<UNITMODE>")])
1082
1083;; Floating point multiply accumulate instructions.
1084
1085;; a * b + c
1086(define_insn "fma<mode>4"
248710c4
KC
1087 [(set (match_operand:ANYF 0 "register_operand" "=f")
1088 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
1089 (match_operand:ANYF 2 "register_operand" " f")
1090 (match_operand:ANYF 3 "register_operand" " f")))]
ac96e906 1091 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1092 "fmadd.<fmt>\t%0,%1,%2,%3"
1093 [(set_attr "type" "fmadd")
1094 (set_attr "mode" "<UNITMODE>")])
1095
1096;; a * b - c
1097(define_insn "fms<mode>4"
248710c4
KC
1098 [(set (match_operand:ANYF 0 "register_operand" "=f")
1099 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
1100 (match_operand:ANYF 2 "register_operand" " f")
1101 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
ac96e906 1102 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1103 "fmsub.<fmt>\t%0,%1,%2,%3"
1104 [(set_attr "type" "fmadd")
1105 (set_attr "mode" "<UNITMODE>")])
1106
1107;; -a * b - c
1108(define_insn "fnms<mode>4"
248710c4
KC
1109 [(set (match_operand:ANYF 0 "register_operand" "=f")
1110 (fma:ANYF
1111 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1112 (match_operand:ANYF 2 "register_operand" " f")
1113 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
ac96e906 1114 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1115 "fnmadd.<fmt>\t%0,%1,%2,%3"
1116 [(set_attr "type" "fmadd")
1117 (set_attr "mode" "<UNITMODE>")])
1118
1119;; -a * b + c
1120(define_insn "fnma<mode>4"
248710c4
KC
1121 [(set (match_operand:ANYF 0 "register_operand" "=f")
1122 (fma:ANYF
1123 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1124 (match_operand:ANYF 2 "register_operand" " f")
1125 (match_operand:ANYF 3 "register_operand" " f")))]
ac96e906 1126 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1127 "fnmsub.<fmt>\t%0,%1,%2,%3"
1128 [(set_attr "type" "fmadd")
1129 (set_attr "mode" "<UNITMODE>")])
1130
1131;; -(-a * b - c), modulo signed zeros
1132(define_insn "*fma<mode>4"
248710c4
KC
1133 [(set (match_operand:ANYF 0 "register_operand" "=f")
1134 (neg:ANYF
1135 (fma:ANYF
1136 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1137 (match_operand:ANYF 2 "register_operand" " f")
1138 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
ac96e906 1139 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
09cae750
PD
1140 "fmadd.<fmt>\t%0,%1,%2,%3"
1141 [(set_attr "type" "fmadd")
1142 (set_attr "mode" "<UNITMODE>")])
1143
1144;; -(-a * b + c), modulo signed zeros
1145(define_insn "*fms<mode>4"
248710c4
KC
1146 [(set (match_operand:ANYF 0 "register_operand" "=f")
1147 (neg:ANYF
1148 (fma:ANYF
1149 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1150 (match_operand:ANYF 2 "register_operand" " f")
1151 (match_operand:ANYF 3 "register_operand" " f"))))]
ac96e906 1152 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
09cae750
PD
1153 "fmsub.<fmt>\t%0,%1,%2,%3"
1154 [(set_attr "type" "fmadd")
1155 (set_attr "mode" "<UNITMODE>")])
1156
1157;; -(a * b + c), modulo signed zeros
1158(define_insn "*fnms<mode>4"
248710c4
KC
1159 [(set (match_operand:ANYF 0 "register_operand" "=f")
1160 (neg:ANYF
1161 (fma:ANYF
1162 (match_operand:ANYF 1 "register_operand" " f")
1163 (match_operand:ANYF 2 "register_operand" " f")
1164 (match_operand:ANYF 3 "register_operand" " f"))))]
ac96e906 1165 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
09cae750
PD
1166 "fnmadd.<fmt>\t%0,%1,%2,%3"
1167 [(set_attr "type" "fmadd")
1168 (set_attr "mode" "<UNITMODE>")])
1169
1170;; -(a * b - c), modulo signed zeros
1171(define_insn "*fnma<mode>4"
248710c4
KC
1172 [(set (match_operand:ANYF 0 "register_operand" "=f")
1173 (neg:ANYF
1174 (fma:ANYF
1175 (match_operand:ANYF 1 "register_operand" " f")
1176 (match_operand:ANYF 2 "register_operand" " f")
1177 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
ac96e906 1178 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
09cae750
PD
1179 "fnmsub.<fmt>\t%0,%1,%2,%3"
1180 [(set_attr "type" "fmadd")
1181 (set_attr "mode" "<UNITMODE>")])
1182
1183;;
1184;; ....................
1185;;
1186;; SIGN INJECTION
1187;;
1188;; ....................
1189
1190(define_insn "abs<mode>2"
248710c4
KC
1191 [(set (match_operand:ANYF 0 "register_operand" "=f")
1192 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
ac96e906 1193 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1194 "fabs.<fmt>\t%0,%1"
1195 [(set_attr "type" "fmove")
1196 (set_attr "mode" "<UNITMODE>")])
1197
1198(define_insn "copysign<mode>3"
248710c4
KC
1199 [(set (match_operand:ANYF 0 "register_operand" "=f")
1200 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")
1201 (match_operand:ANYF 2 "register_operand" " f")]
09cae750 1202 UNSPEC_COPYSIGN))]
ac96e906 1203 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1204 "fsgnj.<fmt>\t%0,%1,%2"
1205 [(set_attr "type" "fmove")
1206 (set_attr "mode" "<UNITMODE>")])
1207
1208(define_insn "neg<mode>2"
248710c4
KC
1209 [(set (match_operand:ANYF 0 "register_operand" "=f")
1210 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
ac96e906 1211 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1212 "fneg.<fmt>\t%0,%1"
1213 [(set_attr "type" "fmove")
1214 (set_attr "mode" "<UNITMODE>")])
1215
1216;;
1217;; ....................
1218;;
1219;; MIN/MAX
1220;;
1221;; ....................
1222
9ddd44b5
MR
1223(define_insn "fmin<mode>3"
1224 [(set (match_operand:ANYF 0 "register_operand" "=f")
1225 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1226 (use (match_operand:ANYF 2 "register_operand" " f"))]
1227 UNSPEC_FMIN))]
ac96e906 1228 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SNANS (<MODE>mode)"
9ddd44b5
MR
1229 "fmin.<fmt>\t%0,%1,%2"
1230 [(set_attr "type" "fmove")
1231 (set_attr "mode" "<UNITMODE>")])
1232
1233(define_insn "fmax<mode>3"
1234 [(set (match_operand:ANYF 0 "register_operand" "=f")
1235 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1236 (use (match_operand:ANYF 2 "register_operand" " f"))]
1237 UNSPEC_FMAX))]
ac96e906 1238 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SNANS (<MODE>mode)"
9ddd44b5
MR
1239 "fmax.<fmt>\t%0,%1,%2"
1240 [(set_attr "type" "fmove")
1241 (set_attr "mode" "<UNITMODE>")])
1242
09cae750 1243(define_insn "smin<mode>3"
248710c4
KC
1244 [(set (match_operand:ANYF 0 "register_operand" "=f")
1245 (smin:ANYF (match_operand:ANYF 1 "register_operand" " f")
1246 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 1247 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1248 "fmin.<fmt>\t%0,%1,%2"
1249 [(set_attr "type" "fmove")
1250 (set_attr "mode" "<UNITMODE>")])
1251
1252(define_insn "smax<mode>3"
248710c4
KC
1253 [(set (match_operand:ANYF 0 "register_operand" "=f")
1254 (smax:ANYF (match_operand:ANYF 1 "register_operand" " f")
1255 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 1256 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1257 "fmax.<fmt>\t%0,%1,%2"
1258 [(set_attr "type" "fmove")
1259 (set_attr "mode" "<UNITMODE>")])
1260
1261;;
1262;; ....................
1263;;
1264;; LOGICAL
1265;;
1266;; ....................
1267;;
1268
1269;; For RV64, we don't expose the SImode operations to the rtl expanders,
1270;; but SImode versions exist for combine.
1271
1272(define_insn "<optab><mode>3"
248710c4 1273 [(set (match_operand:X 0 "register_operand" "=r,r")
09cae750 1274 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
248710c4 1275 (match_operand:X 2 "arith_operand" " r,I")))]
09cae750 1276 ""
0791ac18 1277 "<insn>%i2\t%0,%1,%2"
09cae750
PD
1278 [(set_attr "type" "logical")
1279 (set_attr "mode" "<MODE>")])
1280
1281(define_insn "*<optab>si3_internal"
248710c4 1282 [(set (match_operand:SI 0 "register_operand" "=r,r")
09cae750 1283 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
248710c4 1284 (match_operand:SI 2 "arith_operand" " r,I")))]
09cae750 1285 "TARGET_64BIT"
0791ac18 1286 "<insn>%i2\t%0,%1,%2"
09cae750
PD
1287 [(set_attr "type" "logical")
1288 (set_attr "mode" "SI")])
1289
1290(define_insn "one_cmpl<mode>2"
248710c4
KC
1291 [(set (match_operand:X 0 "register_operand" "=r")
1292 (not:X (match_operand:X 1 "register_operand" " r")))]
09cae750
PD
1293 ""
1294 "not\t%0,%1"
1295 [(set_attr "type" "logical")
1296 (set_attr "mode" "<MODE>")])
1297
1298(define_insn "*one_cmplsi2_internal"
248710c4
KC
1299 [(set (match_operand:SI 0 "register_operand" "=r")
1300 (not:SI (match_operand:SI 1 "register_operand" " r")))]
09cae750
PD
1301 "TARGET_64BIT"
1302 "not\t%0,%1"
1303 [(set_attr "type" "logical")
1304 (set_attr "mode" "SI")])
1305
1306;;
1307;; ....................
1308;;
1309;; TRUNCATION
1310;;
1311;; ....................
1312
1313(define_insn "truncdfsf2"
248710c4
KC
1314 [(set (match_operand:SF 0 "register_operand" "=f")
1315 (float_truncate:SF
1316 (match_operand:DF 1 "register_operand" " f")))]
ac96e906 1317 "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
09cae750
PD
1318 "fcvt.s.d\t%0,%1"
1319 [(set_attr "type" "fcvt")
1320 (set_attr "mode" "SF")])
1321
bd159a76
KC
1322(define_insn "truncsfhf2"
1323 [(set (match_operand:HF 0 "register_operand" "=f")
1324 (float_truncate:HF
1325 (match_operand:SF 1 "register_operand" " f")))]
ac96e906 1326 "TARGET_ZFHMIN || TARGET_ZHINXMIN"
bd159a76
KC
1327 "fcvt.h.s\t%0,%1"
1328 [(set_attr "type" "fcvt")
1329 (set_attr "mode" "HF")])
1330
1331(define_insn "truncdfhf2"
1332 [(set (match_operand:HF 0 "register_operand" "=f")
1333 (float_truncate:HF
1334 (match_operand:DF 1 "register_operand" " f")))]
ac96e906
J
1335 "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
1336 (TARGET_ZHINXMIN && TARGET_ZDINX)"
bd159a76
KC
1337 "fcvt.h.d\t%0,%1"
1338 [(set_attr "type" "fcvt")
1339 (set_attr "mode" "HF")])
1340
09cae750
PD
1341;;
1342;; ....................
1343;;
1344;; ZERO EXTENSION
1345;;
1346;; ....................
1347
1348;; Extension insns.
1349
283b1707
JW
1350(define_expand "zero_extendsidi2"
1351 [(set (match_operand:DI 0 "register_operand")
1352 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
1353 "TARGET_64BIT")
1354
1355(define_insn_and_split "*zero_extendsidi2_internal"
248710c4
KC
1356 [(set (match_operand:DI 0 "register_operand" "=r,r")
1357 (zero_extend:DI
1358 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
2dc835cd 1359 "TARGET_64BIT && !TARGET_ZBA"
09cae750
PD
1360 "@
1361 #
1362 lwu\t%0,%1"
36ec3f57
JJ
1363 "&& reload_completed
1364 && REG_P (operands[1])
1365 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1366 [(set (match_dup 0)
1367 (ashift:DI (match_dup 1) (const_int 32)))
1368 (set (match_dup 0)
1369 (lshiftrt:DI (match_dup 0) (const_int 32)))]
1370 { operands[1] = gen_lowpart (DImode, operands[1]); }
1371 [(set_attr "move_type" "shift_shift,load")
1372 (set_attr "mode" "DI")])
1373
e596a283
JW
1374(define_expand "zero_extendhi<GPR:mode>2"
1375 [(set (match_operand:GPR 0 "register_operand")
1376 (zero_extend:GPR
1377 (match_operand:HI 1 "nonimmediate_operand")))]
1378 "")
1379
1380(define_insn_and_split "*zero_extendhi<GPR:mode>2"
248710c4
KC
1381 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1382 (zero_extend:GPR
1383 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
e596a283 1384 "!TARGET_ZBB"
09cae750
PD
1385 "@
1386 #
1387 lhu\t%0,%1"
36ec3f57
JJ
1388 "&& reload_completed
1389 && REG_P (operands[1])
1390 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1391 [(set (match_dup 0)
1392 (ashift:GPR (match_dup 1) (match_dup 2)))
1393 (set (match_dup 0)
1394 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1395 {
1396 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1397 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1398 }
1399 [(set_attr "move_type" "shift_shift,load")
1400 (set_attr "mode" "<GPR:MODE>")])
1401
1402(define_insn "zero_extendqi<SUPERQI:mode>2"
248710c4 1403 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1404 (zero_extend:SUPERQI
248710c4 1405 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1406 ""
1407 "@
0791ac18 1408 andi\t%0,%1,0xff
09cae750
PD
1409 lbu\t%0,%1"
1410 [(set_attr "move_type" "andi,load")
1411 (set_attr "mode" "<SUPERQI:MODE>")])
1412
1413;;
1414;; ....................
1415;;
1416;; SIGN EXTENSION
1417;;
1418;; ....................
1419
1420(define_insn "extendsidi2"
248710c4
KC
1421 [(set (match_operand:DI 0 "register_operand" "=r,r")
1422 (sign_extend:DI
1423 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1424 "TARGET_64BIT"
1425 "@
1426 sext.w\t%0,%1
1427 lw\t%0,%1"
1428 [(set_attr "move_type" "move,load")
1429 (set_attr "mode" "DI")])
1430
e596a283
JW
1431(define_expand "extend<SHORT:mode><SUPERQI:mode>2"
1432 [(set (match_operand:SUPERQI 0 "register_operand")
1433 (sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_operand")))]
1434 "")
1435
1436(define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
248710c4 1437 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1438 (sign_extend:SUPERQI
248710c4 1439 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
e596a283 1440 "!TARGET_ZBB"
09cae750
PD
1441 "@
1442 #
1443 l<SHORT:size>\t%0,%1"
36ec3f57
JJ
1444 "&& reload_completed
1445 && REG_P (operands[1])
1446 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1447 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1448 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
1449{
1450 operands[0] = gen_lowpart (SImode, operands[0]);
1451 operands[1] = gen_lowpart (SImode, operands[1]);
1452 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1453 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1454}
1455 [(set_attr "move_type" "shift_shift,load")
1456 (set_attr "mode" "SI")])
1457
bd159a76
KC
1458(define_insn "extendhfsf2"
1459 [(set (match_operand:SF 0 "register_operand" "=f")
1460 (float_extend:SF
1461 (match_operand:HF 1 "register_operand" " f")))]
ac96e906 1462 "TARGET_ZFHMIN || TARGET_ZHINXMIN"
bd159a76
KC
1463 "fcvt.s.h\t%0,%1"
1464 [(set_attr "type" "fcvt")
1465 (set_attr "mode" "SF")])
1466
09cae750 1467(define_insn "extendsfdf2"
248710c4
KC
1468 [(set (match_operand:DF 0 "register_operand" "=f")
1469 (float_extend:DF
1470 (match_operand:SF 1 "register_operand" " f")))]
ac96e906 1471 "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
09cae750
PD
1472 "fcvt.d.s\t%0,%1"
1473 [(set_attr "type" "fcvt")
1474 (set_attr "mode" "DF")])
1475
bd159a76
KC
1476(define_insn "extendhfdf2"
1477 [(set (match_operand:DF 0 "register_operand" "=f")
1478 (float_extend:DF
1479 (match_operand:HF 1 "register_operand" " f")))]
ac96e906
J
1480 "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
1481 (TARGET_ZHINXMIN && TARGET_ZDINX)"
bd159a76
KC
1482 "fcvt.d.h\t%0,%1"
1483 [(set_attr "type" "fcvt")
1484 (set_attr "mode" "DF")])
1485
27d68a60
KC
1486;; 16-bit floating point moves
1487(define_expand "movhf"
1488 [(set (match_operand:HF 0 "")
1489 (match_operand:HF 1 ""))]
1490 ""
1491{
1492 if (riscv_legitimize_move (HFmode, operands[0], operands[1]))
1493 DONE;
1494})
1495
bd159a76
KC
1496(define_insn "*movhf_hardfloat"
1497 [(set (match_operand:HF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1498 (match_operand:HF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
1499 "TARGET_ZFHMIN
1500 && (register_operand (operands[0], HFmode)
1501 || reg_or_0_operand (operands[1], HFmode))"
1502 { return riscv_output_move (operands[0], operands[1]); }
1503 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1504 (set_attr "mode" "HF")])
27d68a60
KC
1505
1506(define_insn "*movhf_softfloat"
1507 [(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
1508 (match_operand:HF 1 "move_operand" " f,Gr,m,r,*r,*f"))]
bd159a76
KC
1509 "!TARGET_ZFHMIN
1510 && (register_operand (operands[0], HFmode)
1511 || reg_or_0_operand (operands[1], HFmode))"
27d68a60
KC
1512 { return riscv_output_move (operands[0], operands[1]); }
1513 [(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
1514 (set_attr "mode" "HF")])
1515
09cae750
PD
1516;;
1517;; ....................
1518;;
1519;; CONVERSIONS
1520;;
1521;; ....................
1522
1523(define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
248710c4
KC
1524 [(set (match_operand:GPR 0 "register_operand" "=r")
1525 (fix:GPR
1526 (match_operand:ANYF 1 "register_operand" " f")))]
ac96e906 1527 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1528 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
1529 [(set_attr "type" "fcvt")
1530 (set_attr "mode" "<ANYF:MODE>")])
1531
1532(define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2"
248710c4
KC
1533 [(set (match_operand:GPR 0 "register_operand" "=r")
1534 (unsigned_fix:GPR
1535 (match_operand:ANYF 1 "register_operand" " f")))]
ac96e906 1536 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1537 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
1538 [(set_attr "type" "fcvt")
1539 (set_attr "mode" "<ANYF:MODE>")])
1540
1541(define_insn "float<GPR:mode><ANYF:mode>2"
248710c4
KC
1542 [(set (match_operand:ANYF 0 "register_operand" "= f")
1543 (float:ANYF
1544 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
ac96e906 1545 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1546 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
1547 [(set_attr "type" "fcvt")
1548 (set_attr "mode" "<ANYF:MODE>")])
1549
1550(define_insn "floatuns<GPR:mode><ANYF:mode>2"
248710c4
KC
1551 [(set (match_operand:ANYF 0 "register_operand" "= f")
1552 (unsigned_float:ANYF
1553 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
ac96e906 1554 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1555 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
1556 [(set_attr "type" "fcvt")
1557 (set_attr "mode" "<ANYF:MODE>")])
1558
1559(define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2"
248710c4
KC
1560 [(set (match_operand:GPR 0 "register_operand" "=r")
1561 (unspec:GPR
1562 [(match_operand:ANYF 1 "register_operand" " f")]
1563 RINT))]
ac96e906 1564 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1565 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
1566 [(set_attr "type" "fcvt")
1567 (set_attr "mode" "<ANYF:MODE>")])
1568
1569;;
1570;; ....................
1571;;
1572;; DATA MOVEMENT
1573;;
1574;; ....................
1575
1576;; Lower-level instructions for loading an address from the GOT.
1577;; We could use MEMs, but an unspec gives more optimization
1578;; opportunities.
1579
1580(define_insn "got_load<mode>"
248710c4
KC
1581 [(set (match_operand:P 0 "register_operand" "=r")
1582 (unspec:P
1583 [(match_operand:P 1 "symbolic_operand" "")]
1584 UNSPEC_LOAD_GOT))]
09cae750
PD
1585 ""
1586 "la\t%0,%1"
1587 [(set_attr "got" "load")
1588 (set_attr "mode" "<MODE>")])
1589
1590(define_insn "tls_add_tp_le<mode>"
248710c4
KC
1591 [(set (match_operand:P 0 "register_operand" "=r")
1592 (unspec:P
1593 [(match_operand:P 1 "register_operand" "r")
1594 (match_operand:P 2 "register_operand" "r")
1595 (match_operand:P 3 "symbolic_operand" "")]
1596 UNSPEC_TLS_LE))]
09cae750
PD
1597 ""
1598 "add\t%0,%1,%2,%%tprel_add(%3)"
1599 [(set_attr "type" "arith")
1600 (set_attr "mode" "<MODE>")])
1601
1602(define_insn "got_load_tls_gd<mode>"
248710c4
KC
1603 [(set (match_operand:P 0 "register_operand" "=r")
1604 (unspec:P
1605 [(match_operand:P 1 "symbolic_operand" "")]
1606 UNSPEC_TLS_GD))]
09cae750
PD
1607 ""
1608 "la.tls.gd\t%0,%1"
1609 [(set_attr "got" "load")
1610 (set_attr "mode" "<MODE>")])
1611
1612(define_insn "got_load_tls_ie<mode>"
248710c4
KC
1613 [(set (match_operand:P 0 "register_operand" "=r")
1614 (unspec:P
1615 [(match_operand:P 1 "symbolic_operand" "")]
1616 UNSPEC_TLS_IE))]
09cae750
PD
1617 ""
1618 "la.tls.ie\t%0,%1"
1619 [(set_attr "got" "load")
1620 (set_attr "mode" "<MODE>")])
1621
1622(define_insn "auipc<mode>"
248710c4
KC
1623 [(set (match_operand:P 0 "register_operand" "=r")
1624 (unspec:P
1625 [(match_operand:P 1 "symbolic_operand" "")
09cae750
PD
1626 (match_operand:P 2 "const_int_operand")
1627 (pc)]
248710c4 1628 UNSPEC_AUIPC))]
09cae750
PD
1629 ""
1630 ".LA%2: auipc\t%0,%h1"
88108b27 1631 [(set_attr "type" "auipc")
09cae750
PD
1632 (set_attr "cannot_copy" "yes")])
1633
1634;; Instructions for adding the low 12 bits of an address to a register.
1635;; Operand 2 is the address: riscv_print_operand works out which relocation
1636;; should be applied.
1637
1638(define_insn "*low<mode>"
248710c4
KC
1639 [(set (match_operand:P 0 "register_operand" "=r")
1640 (lo_sum:P (match_operand:P 1 "register_operand" " r")
09cae750
PD
1641 (match_operand:P 2 "symbolic_operand" "")))]
1642 ""
1643 "addi\t%0,%1,%R2"
1644 [(set_attr "type" "arith")
1645 (set_attr "mode" "<MODE>")])
1646
1647;; Allow combine to split complex const_int load sequences, using operand 2
1648;; to store the intermediate results. See move_operand for details.
1649(define_split
1650 [(set (match_operand:GPR 0 "register_operand")
1651 (match_operand:GPR 1 "splittable_const_int_operand"))
1652 (clobber (match_operand:GPR 2 "register_operand"))]
1653 ""
1654 [(const_int 0)]
1655{
51175507 1656 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
a923a463 1657 <GPR:MODE>mode, TRUE);
09cae750
PD
1658 DONE;
1659})
1660
1661;; Likewise, for symbolic operands.
1662(define_split
1663 [(set (match_operand:P 0 "register_operand")
1664 (match_operand:P 1))
1665 (clobber (match_operand:P 2 "register_operand"))]
a923a463 1666 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL, TRUE)"
09cae750
PD
1667 [(set (match_dup 0) (match_dup 3))]
1668{
1669 riscv_split_symbol (operands[2], operands[1],
a923a463 1670 MAX_MACHINE_MODE, &operands[3], TRUE);
09cae750
PD
1671})
1672
2e886eef
RMZ
1673;; Pretend to have the ability to load complex const_int in order to get
1674;; better code generation around them.
1675;;
1676;; But avoid constants that are special cased elsewhere.
1677(define_insn_and_split "*mvconst_internal"
1678 [(set (match_operand:GPR 0 "register_operand" "=r")
1679 (match_operand:GPR 1 "splittable_const_int_operand" "i"))]
103f963e
JL
1680 "!(p2m1_shift_operand (operands[1], <MODE>mode)
1681 || high_mask_shift_operand (operands[1], <MODE>mode))"
2e886eef
RMZ
1682 "#"
1683 "&& 1"
1684 [(const_int 0)]
1685{
1686 riscv_move_integer (operands[0], operands[0], INTVAL (operands[1]),
1687 <MODE>mode, TRUE);
1688 DONE;
1689})
1690
09cae750
PD
1691;; 64-bit integer moves
1692
1693(define_expand "movdi"
1694 [(set (match_operand:DI 0 "")
1695 (match_operand:DI 1 ""))]
1696 ""
1697{
1698 if (riscv_legitimize_move (DImode, operands[0], operands[1]))
1699 DONE;
1700})
1701
1702(define_insn "*movdi_32bit"
8fe75147 1703 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m,r")
1704 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f,vp"))]
09cae750
PD
1705 "!TARGET_64BIT
1706 && (register_operand (operands[0], DImode)
1707 || reg_or_0_operand (operands[1], DImode))"
1708 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 1709 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore,rdvlenb")
1710 (set_attr "mode" "DI")
1711 (set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")])
09cae750
PD
1712
1713(define_insn "*movdi_64bit"
8fe75147 1714 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m,r")
1715 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f,vp"))]
09cae750
PD
1716 "TARGET_64BIT
1717 && (register_operand (operands[0], DImode)
1718 || reg_or_0_operand (operands[1], DImode))"
1719 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 1720 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore,rdvlenb")
1721 (set_attr "mode" "DI")
1722 (set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")])
09cae750
PD
1723
1724;; 32-bit Integer moves
1725
1726(define_expand "mov<mode>"
1727 [(set (match_operand:MOVE32 0 "")
1728 (match_operand:MOVE32 1 ""))]
1729 ""
1730{
1731 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
1732 DONE;
1733})
1734
1735(define_insn "*movsi_internal"
8fe75147 1736 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m,r")
1737 (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,vp"))]
09cae750
PD
1738 "(register_operand (operands[0], SImode)
1739 || reg_or_0_operand (operands[1], SImode))"
1740 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 1741 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore,rdvlenb")
1742 (set_attr "mode" "SI")
1743 (set_attr "ext" "base,base,base,base,f,f,f,f,vector")])
09cae750
PD
1744
1745;; 16-bit Integer moves
1746
1747;; Unlike most other insns, the move insns can't be split with
1748;; different predicates, because register spilling and other parts of
1749;; the compiler, have memoized the insn number already.
1750;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
1751
1752(define_expand "movhi"
1753 [(set (match_operand:HI 0 "")
1754 (match_operand:HI 1 ""))]
1755 ""
1756{
1757 if (riscv_legitimize_move (HImode, operands[0], operands[1]))
1758 DONE;
1759})
1760
1761(define_insn "*movhi_internal"
8fe75147 1762 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r")
1763 (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f,vp"))]
09cae750
PD
1764 "(register_operand (operands[0], HImode)
1765 || reg_or_0_operand (operands[1], HImode))"
1766 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 1767 [(set_attr "move_type" "move,const,load,store,mtc,mfc,rdvlenb")
1768 (set_attr "mode" "HI")
1769 (set_attr "ext" "base,base,base,base,f,f,vector")])
09cae750
PD
1770
1771;; HImode constant generation; see riscv_move_integer for details.
bb149ca2
RS
1772;; si+si->hi without truncation is legal because of
1773;; TARGET_TRULY_NOOP_TRUNCATION.
09cae750
PD
1774
1775(define_insn "*add<mode>hi3"
248710c4
KC
1776 [(set (match_operand:HI 0 "register_operand" "=r,r")
1777 (plus:HI (match_operand:HISI 1 "register_operand" " r,r")
1778 (match_operand:HISI 2 "arith_operand" " r,I")))]
09cae750 1779 ""
473d7aad 1780 "add%i2%~\t%0,%1,%2"
09cae750
PD
1781 [(set_attr "type" "arith")
1782 (set_attr "mode" "HI")])
1783
1784(define_insn "*xor<mode>hi3"
248710c4
KC
1785 [(set (match_operand:HI 0 "register_operand" "=r,r")
1786 (xor:HI (match_operand:HISI 1 "register_operand" " r,r")
1787 (match_operand:HISI 2 "arith_operand" " r,I")))]
09cae750 1788 ""
0791ac18 1789 "xor%i2\t%0,%1,%2"
09cae750
PD
1790 [(set_attr "type" "logical")
1791 (set_attr "mode" "HI")])
1792
1793;; 8-bit Integer moves
1794
1795(define_expand "movqi"
1796 [(set (match_operand:QI 0 "")
1797 (match_operand:QI 1 ""))]
1798 ""
1799{
1800 if (riscv_legitimize_move (QImode, operands[0], operands[1]))
1801 DONE;
1802})
1803
1804(define_insn "*movqi_internal"
8fe75147 1805 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r")
1806 (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f,vp"))]
09cae750
PD
1807 "(register_operand (operands[0], QImode)
1808 || reg_or_0_operand (operands[1], QImode))"
1809 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 1810 [(set_attr "move_type" "move,const,load,store,mtc,mfc,rdvlenb")
1811 (set_attr "mode" "QI")
1812 (set_attr "ext" "base,base,base,base,f,f,vector")])
09cae750
PD
1813
1814;; 32-bit floating point moves
1815
1816(define_expand "movsf"
1817 [(set (match_operand:SF 0 "")
1818 (match_operand:SF 1 ""))]
1819 ""
1820{
1821 if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
1822 DONE;
1823})
1824
1825(define_insn "*movsf_hardfloat"
248710c4
KC
1826 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1827 (match_operand:SF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
09cae750
PD
1828 "TARGET_HARD_FLOAT
1829 && (register_operand (operands[0], SFmode)
1830 || reg_or_0_operand (operands[1], SFmode))"
1831 { return riscv_output_move (operands[0], operands[1]); }
1832 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1833 (set_attr "mode" "SF")])
1834
1835(define_insn "*movsf_softfloat"
248710c4
KC
1836 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
1837 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
09cae750
PD
1838 "!TARGET_HARD_FLOAT
1839 && (register_operand (operands[0], SFmode)
1840 || reg_or_0_operand (operands[1], SFmode))"
1841 { return riscv_output_move (operands[0], operands[1]); }
1842 [(set_attr "move_type" "move,load,store")
1843 (set_attr "mode" "SF")])
1844
1845;; 64-bit floating point moves
1846
1847(define_expand "movdf"
1848 [(set (match_operand:DF 0 "")
1849 (match_operand:DF 1 ""))]
1850 ""
1851{
1852 if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
1853 DONE;
1854})
1855
1856;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
1857;; (However, we can still use fcvt.d.w to zero a floating-point register.)
1858(define_insn "*movdf_hardfloat_rv32"
248710c4
KC
1859 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m")
1860 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))]
09cae750
PD
1861 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
1862 && (register_operand (operands[0], DFmode)
1863 || reg_or_0_operand (operands[1], DFmode))"
1864 { return riscv_output_move (operands[0], operands[1]); }
1865 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store")
1866 (set_attr "mode" "DF")])
1867
1868(define_insn "*movdf_hardfloat_rv64"
248710c4
KC
1869 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1870 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
09cae750
PD
1871 "TARGET_64BIT && TARGET_DOUBLE_FLOAT
1872 && (register_operand (operands[0], DFmode)
1873 || reg_or_0_operand (operands[1], DFmode))"
1874 { return riscv_output_move (operands[0], operands[1]); }
1875 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1876 (set_attr "mode" "DF")])
1877
1878(define_insn "*movdf_softfloat"
248710c4
KC
1879 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
1880 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
09cae750
PD
1881 "!TARGET_DOUBLE_FLOAT
1882 && (register_operand (operands[0], DFmode)
1883 || reg_or_0_operand (operands[1], DFmode))"
1884 { return riscv_output_move (operands[0], operands[1]); }
1885 [(set_attr "move_type" "move,load,store")
1886 (set_attr "mode" "DF")])
1887
1888(define_split
1889 [(set (match_operand:MOVE64 0 "nonimmediate_operand")
1890 (match_operand:MOVE64 1 "move_operand"))]
1891 "reload_completed
1892 && riscv_split_64bit_move_p (operands[0], operands[1])"
1893 [(const_int 0)]
1894{
1895 riscv_split_doubleword_move (operands[0], operands[1]);
1896 DONE;
1897})
1898
76715c32 1899(define_expand "cpymemsi"
6ed01e6b
AW
1900 [(parallel [(set (match_operand:BLK 0 "general_operand")
1901 (match_operand:BLK 1 "general_operand"))
1902 (use (match_operand:SI 2 ""))
1903 (use (match_operand:SI 3 "const_int_operand"))])]
1904 ""
1905{
1906 if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
1907 DONE;
1908 else
1909 FAIL;
1910})
1911
09cae750
PD
1912;; Expand in-line code to clear the instruction cache between operand[0] and
1913;; operand[1].
1914(define_expand "clear_cache"
1915 [(match_operand 0 "pmode_register_operand")
1916 (match_operand 1 "pmode_register_operand")]
1917 ""
1918{
f1bdc63a
AW
1919#ifdef ICACHE_FLUSH_FUNC
1920 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC),
1921 LCT_NORMAL, VOIDmode, operands[0], Pmode,
1922 operands[1], Pmode, const0_rtx, Pmode);
1923#else
b03be74b
KC
1924 if (TARGET_ZIFENCEI)
1925 emit_insn (gen_fence_i ());
f1bdc63a 1926#endif
09cae750
PD
1927 DONE;
1928})
1929
1930(define_insn "fence"
1931 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
1932 ""
1933 "%|fence%-")
1934
1935(define_insn "fence_i"
1936 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
b03be74b 1937 "TARGET_ZIFENCEI"
09cae750
PD
1938 "fence.i")
1939
c717a92d
PT
1940(define_insn "riscv_pause"
1941 [(unspec_volatile [(const_int 0)] UNSPECV_PAUSE)]
1942 ""
1943 "pause")
1944
09cae750
PD
1945;;
1946;; ....................
1947;;
1948;; SHIFTS
1949;;
1950;; ....................
1951
b7ef9225
JW
1952;; Use a QImode shift count, to avoid generating sign or zero extend
1953;; instructions for shift counts, and to avoid dropping subregs.
1954;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
1955;; defined, but use of that is discouraged.
1956
09cae750 1957(define_insn "<optab>si3"
248710c4
KC
1958 [(set (match_operand:SI 0 "register_operand" "= r")
1959 (any_shift:SI
1960 (match_operand:SI 1 "register_operand" " r")
b7ef9225 1961 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
1962 ""
1963{
1964 if (GET_CODE (operands[2]) == CONST_INT)
1965 operands[2] = GEN_INT (INTVAL (operands[2])
1966 & (GET_MODE_BITSIZE (SImode) - 1));
1967
473d7aad 1968 return "<insn>%i2%~\t%0,%1,%2";
09cae750
PD
1969}
1970 [(set_attr "type" "shift")
1971 (set_attr "mode" "SI")])
1972
110fb19f 1973(define_insn_and_split "*<optab>si3_mask"
b7ef9225
JW
1974 [(set (match_operand:SI 0 "register_operand" "= r")
1975 (any_shift:SI
1976 (match_operand:SI 1 "register_operand" " r")
7ac4dfec
MC
1977 (match_operator 4 "subreg_lowpart_operator"
1978 [(and:SI
1979 (match_operand:SI 2 "register_operand" "r")
1980 (match_operand 3 "const_int_operand"))])))]
b7ef9225
JW
1981 "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1982 == GET_MODE_BITSIZE (SImode)-1"
1983 "#"
1984 "&& 1"
1985 [(set (match_dup 0)
1986 (any_shift:SI (match_dup 1)
1987 (match_dup 2)))]
1988 "operands[2] = gen_lowpart (QImode, operands[2]);"
1989 [(set_attr "type" "shift")
1990 (set_attr "mode" "SI")])
1991
110fb19f 1992(define_insn_and_split "*<optab>si3_mask_1"
b7ef9225
JW
1993 [(set (match_operand:SI 0 "register_operand" "= r")
1994 (any_shift:SI
1995 (match_operand:SI 1 "register_operand" " r")
7ac4dfec
MC
1996 (match_operator 4 "subreg_lowpart_operator"
1997 [(and:DI
1998 (match_operand:DI 2 "register_operand" "r")
1999 (match_operand 3 "const_int_operand"))])))]
b7ef9225
JW
2000 "TARGET_64BIT
2001 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
2002 == GET_MODE_BITSIZE (SImode)-1"
2003 "#"
2004 "&& 1"
2005 [(set (match_dup 0)
2006 (any_shift:SI (match_dup 1)
2007 (match_dup 2)))]
2008 "operands[2] = gen_lowpart (QImode, operands[2]);"
2009 [(set_attr "type" "shift")
2010 (set_attr "mode" "SI")])
2011
09cae750 2012(define_insn "<optab>di3"
248710c4
KC
2013 [(set (match_operand:DI 0 "register_operand" "= r")
2014 (any_shift:DI
2015 (match_operand:DI 1 "register_operand" " r")
b7ef9225 2016 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
2017 "TARGET_64BIT"
2018{
2019 if (GET_CODE (operands[2]) == CONST_INT)
2020 operands[2] = GEN_INT (INTVAL (operands[2])
2021 & (GET_MODE_BITSIZE (DImode) - 1));
2022
0791ac18 2023 return "<insn>%i2\t%0,%1,%2";
09cae750
PD
2024}
2025 [(set_attr "type" "shift")
2026 (set_attr "mode" "DI")])
2027
110fb19f 2028(define_insn_and_split "*<optab>di3_mask"
b7ef9225
JW
2029 [(set (match_operand:DI 0 "register_operand" "= r")
2030 (any_shift:DI
2031 (match_operand:DI 1 "register_operand" " r")
7ac4dfec
MC
2032 (match_operator 4 "subreg_lowpart_operator"
2033 [(and:SI
2034 (match_operand:SI 2 "register_operand" "r")
2035 (match_operand 3 "const_int_operand"))])))]
b7ef9225
JW
2036 "TARGET_64BIT
2037 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
2038 == GET_MODE_BITSIZE (DImode)-1"
2039 "#"
2040 "&& 1"
2041 [(set (match_dup 0)
2042 (any_shift:DI (match_dup 1)
2043 (match_dup 2)))]
2044 "operands[2] = gen_lowpart (QImode, operands[2]);"
2045 [(set_attr "type" "shift")
2046 (set_attr "mode" "DI")])
2047
110fb19f 2048(define_insn_and_split "*<optab>di3_mask_1"
b7ef9225
JW
2049 [(set (match_operand:DI 0 "register_operand" "= r")
2050 (any_shift:DI
2051 (match_operand:DI 1 "register_operand" " r")
7ac4dfec
MC
2052 (match_operator 4 "subreg_lowpart_operator"
2053 [(and:DI
2054 (match_operand:DI 2 "register_operand" "r")
2055 (match_operand 3 "const_int_operand"))])))]
b7ef9225
JW
2056 "TARGET_64BIT
2057 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
2058 == GET_MODE_BITSIZE (DImode)-1"
2059 "#"
2060 "&& 1"
2061 [(set (match_dup 0)
2062 (any_shift:DI (match_dup 1)
2063 (match_dup 2)))]
2064 "operands[2] = gen_lowpart (QImode, operands[2]);"
2065 [(set_attr "type" "shift")
2066 (set_attr "mode" "DI")])
2067
09cae750 2068(define_insn "*<optab>si3_extend"
248710c4 2069 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 2070 (sign_extend:DI
248710c4 2071 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 2072 (match_operand:QI 2 "arith_operand" " rI"))))]
09cae750
PD
2073 "TARGET_64BIT"
2074{
2075 if (GET_CODE (operands[2]) == CONST_INT)
2076 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
2077
0791ac18 2078 return "<insn>%i2w\t%0,%1,%2";
09cae750
PD
2079}
2080 [(set_attr "type" "shift")
2081 (set_attr "mode" "SI")])
2082
b7ef9225
JW
2083(define_insn_and_split "*<optab>si3_extend_mask"
2084 [(set (match_operand:DI 0 "register_operand" "= r")
2085 (sign_extend:DI
2086 (any_shift:SI
2087 (match_operand:SI 1 "register_operand" " r")
7ac4dfec
MC
2088 (match_operator 4 "subreg_lowpart_operator"
2089 [(and:SI
2090 (match_operand:SI 2 "register_operand" " r")
2091 (match_operand 3 "const_int_operand"))]))))]
b7ef9225
JW
2092 "TARGET_64BIT
2093 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
2094 == GET_MODE_BITSIZE (SImode)-1"
2095 "#"
2096 "&& 1"
2097 [(set (match_dup 0)
2098 (sign_extend:DI
2099 (any_shift:SI (match_dup 1)
2100 (match_dup 2))))]
2101 "operands[2] = gen_lowpart (QImode, operands[2]);"
2102 [(set_attr "type" "shift")
2103 (set_attr "mode" "SI")])
2104
2105(define_insn_and_split "*<optab>si3_extend_mask_1"
2106 [(set (match_operand:DI 0 "register_operand" "= r")
2107 (sign_extend:DI
2108 (any_shift:SI
2109 (match_operand:SI 1 "register_operand" " r")
7ac4dfec
MC
2110 (match_operator 4 "subreg_lowpart_operator"
2111 [(and:DI
2112 (match_operand:DI 2 "register_operand" " r")
2113 (match_operand 3 "const_int_operand"))]))))]
b7ef9225
JW
2114 "TARGET_64BIT
2115 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
2116 == GET_MODE_BITSIZE (SImode)-1"
2117 "#"
2118 "&& 1"
2119 [(set (match_dup 0)
2120 (sign_extend:DI
2121 (any_shift:SI (match_dup 1)
2122 (match_dup 2))))]
2123 "operands[2] = gen_lowpart (QImode, operands[2]);"
2124 [(set_attr "type" "shift")
2125 (set_attr "mode" "SI")])
2126
08539f3e
JW
2127;; Non-canonical, but can be formed by ree when combine is not successful at
2128;; producing one of the two canonical patterns below.
2129(define_insn "*lshrsi3_zero_extend_1"
2130 [(set (match_operand:DI 0 "register_operand" "=r")
2131 (zero_extend:DI
2132 (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 2133 (match_operand 2 "const_int_operand"))))]
08539f3e
JW
2134 "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
2135{
2136 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
2137
2138 return "srliw\t%0,%1,%2";
2139}
2140 [(set_attr "type" "shift")
2141 (set_attr "mode" "SI")])
2142
2143;; Canonical form for a zero-extend of a logical right shift.
2144(define_insn "*lshrsi3_zero_extend_2"
2145 [(set (match_operand:DI 0 "register_operand" "=r")
2146 (zero_extract:DI (match_operand:DI 1 "register_operand" " r")
2147 (match_operand 2 "const_int_operand")
2148 (match_operand 3 "const_int_operand")))]
2149 "(TARGET_64BIT && (INTVAL (operands[3]) > 0)
2150 && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
2151{
2152 return "srliw\t%0,%1,%3";
2153}
2154 [(set_attr "type" "shift")
2155 (set_attr "mode" "SI")])
2156
2157;; Canonical form for a zero-extend of a logical right shift when the
2158;; shift count is 31.
2159(define_insn "*lshrsi3_zero_extend_3"
2160 [(set (match_operand:DI 0 "register_operand" "=r")
2161 (lt:DI (match_operand:SI 1 "register_operand" " r")
2162 (const_int 0)))]
2163 "TARGET_64BIT"
2164{
2165 return "srliw\t%0,%1,31";
2166}
2167 [(set_attr "type" "shift")
2168 (set_attr "mode" "SI")])
2169
666fdc46
JW
2170;; Handle AND with 2^N-1 for N from 12 to XLEN. This can be split into
2171;; two logical shifts. Otherwise it requires 3 instructions: lui,
2172;; xor/addi/srli, and.
36ec3f57
JJ
2173
2174;; Generating a temporary for the shift output gives better combiner results;
2175;; and also fixes a problem where op0 could be a paradoxical reg and shifting
2176;; by amounts larger than the size of the SUBREG_REG doesn't work.
666fdc46
JW
2177(define_split
2178 [(set (match_operand:GPR 0 "register_operand")
2179 (and:GPR (match_operand:GPR 1 "register_operand")
36ec3f57
JJ
2180 (match_operand:GPR 2 "p2m1_shift_operand")))
2181 (clobber (match_operand:GPR 3 "register_operand"))]
666fdc46 2182 ""
36ec3f57 2183 [(set (match_dup 3)
666fdc46
JW
2184 (ashift:GPR (match_dup 1) (match_dup 2)))
2185 (set (match_dup 0)
36ec3f57 2186 (lshiftrt:GPR (match_dup 3) (match_dup 2)))]
666fdc46 2187{
ace4317a 2188 /* Op2 is a VOIDmode constant, so get the mode size from op1. */
3496ca4e 2189 operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1])).to_constant ()
666fdc46
JW
2190 - exact_log2 (INTVAL (operands[2]) + 1));
2191})
ace4317a 2192
666fdc46
JW
2193;; Handle AND with 0xF...F0...0 where there are 32 to 63 zeros. This can be
2194;; split into two shifts. Otherwise it requires 3 instructions: li, sll, and.
2195(define_split
2196 [(set (match_operand:DI 0 "register_operand")
2197 (and:DI (match_operand:DI 1 "register_operand")
36ec3f57
JJ
2198 (match_operand:DI 2 "high_mask_shift_operand")))
2199 (clobber (match_operand:DI 3 "register_operand"))]
666fdc46 2200 "TARGET_64BIT"
36ec3f57 2201 [(set (match_dup 3)
666fdc46
JW
2202 (lshiftrt:DI (match_dup 1) (match_dup 2)))
2203 (set (match_dup 0)
36ec3f57 2204 (ashift:DI (match_dup 3) (match_dup 2)))]
666fdc46
JW
2205{
2206 operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2])));
2207})
2208
d5cdcd5c
JW
2209;; Handle SImode to DImode zero-extend combined with a left shift. This can
2210;; occur when unsigned int is used for array indexing. Split this into two
2211;; shifts. Otherwise we can get 3 shifts.
2212
2213(define_insn_and_split "zero_extendsidi2_shifted"
2214 [(set (match_operand:DI 0 "register_operand" "=r")
2215 (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
2216 (match_operand:QI 2 "immediate_operand" "I"))
2217 (match_operand 3 "immediate_operand" "")))
2218 (clobber (match_scratch:DI 4 "=&r"))]
283b1707 2219 "TARGET_64BIT && !TARGET_ZBA
d5cdcd5c
JW
2220 && ((INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff)"
2221 "#"
2222 "&& reload_completed"
2223 [(set (match_dup 4)
2224 (ashift:DI (match_dup 1) (const_int 32)))
2225 (set (match_dup 0)
2226 (lshiftrt:DI (match_dup 4) (match_dup 5)))]
2227 "operands[5] = GEN_INT (32 - (INTVAL (operands [2])));"
2228 [(set_attr "type" "shift")
2229 (set_attr "mode" "DI")])
2230
09cae750
PD
2231;;
2232;; ....................
2233;;
2234;; CONDITIONAL BRANCHES
2235;;
2236;; ....................
2237
2238;; Conditional branches
2239
acbb5ef0
PT
2240(define_insn_and_split "*branch<ANYI:mode>_shiftedarith_equals_zero"
2241 [(set (pc)
2242 (if_then_else (match_operator 1 "equality_operator"
2243 [(and:ANYI (match_operand:ANYI 2 "register_operand" "r")
2244 (match_operand 3 "shifted_const_arith_operand" "i"))
2245 (const_int 0)])
2246 (label_ref (match_operand 0 "" ""))
2247 (pc)))
4c7d336b
PT
2248 (clobber (match_scratch:X 4 "=&r"))]
2249 "!SMALL_OPERAND (INTVAL (operands[3]))"
acbb5ef0
PT
2250 "#"
2251 "&& reload_completed"
4c7d336b
PT
2252 [(set (match_dup 4) (lshiftrt:X (subreg:X (match_dup 2) 0) (match_dup 6)))
2253 (set (match_dup 4) (and:X (match_dup 4) (match_dup 7)))
acbb5ef0
PT
2254 (set (pc) (if_then_else (match_op_dup 1 [(match_dup 4) (const_int 0)])
2255 (label_ref (match_dup 0)) (pc)))]
2256{
2257 HOST_WIDE_INT mask = INTVAL (operands[3]);
2258 int trailing = ctz_hwi (mask);
2259
2260 operands[6] = GEN_INT (trailing);
2261 operands[7] = GEN_INT (mask >> trailing);
2262})
2263
2264(define_insn_and_split "*branch<ANYI:mode>_shiftedmask_equals_zero"
2265 [(set (pc)
2266 (if_then_else (match_operator 1 "equality_operator"
2267 [(and:ANYI (match_operand:ANYI 2 "register_operand" "r")
2268 (match_operand 3 "consecutive_bits_operand" "i"))
2269 (const_int 0)])
2270 (label_ref (match_operand 0 "" ""))
2271 (pc)))
2272 (clobber (match_scratch:X 4 "=&r"))]
2273 "(INTVAL (operands[3]) >= 0 || !partial_subreg_p (operands[2]))
2274 && popcount_hwi (INTVAL (operands[3])) > 1
2275 && !SMALL_OPERAND (INTVAL (operands[3]))"
2276 "#"
2277 "&& reload_completed"
2278 [(set (match_dup 4) (ashift:X (subreg:X (match_dup 2) 0) (match_dup 6)))
2279 (set (match_dup 4) (lshiftrt:X (match_dup 4) (match_dup 7)))
2280 (set (pc) (if_then_else (match_op_dup 1 [(match_dup 4) (const_int 0)])
2281 (label_ref (match_dup 0)) (pc)))]
2282{
2283 unsigned HOST_WIDE_INT mask = INTVAL (operands[3]);
2284 int leading = clz_hwi (mask);
2285 int trailing = ctz_hwi (mask);
2286
2287 operands[6] = GEN_INT (leading);
2288 operands[7] = GEN_INT (leading + trailing);
2289})
2290
4f475391 2291(define_insn "*branch<mode>"
09cae750
PD
2292 [(set (pc)
2293 (if_then_else
2294 (match_operator 1 "order_operator"
2295 [(match_operand:X 2 "register_operand" "r")
4f475391 2296 (match_operand:X 3 "reg_or_0_operand" "rJ")])
09cae750
PD
2297 (label_ref (match_operand 0 "" ""))
2298 (pc)))]
2299 ""
4f475391 2300 "b%C1\t%2,%z3,%0"
09cae750
PD
2301 [(set_attr "type" "branch")
2302 (set_attr "mode" "none")])
2303
4f475391
AW
2304;; Patterns for implementations that optimize short forward branches.
2305
2306(define_expand "mov<mode>cc"
2307 [(set (match_operand:GPR 0 "register_operand")
2308 (if_then_else:GPR (match_operand 1 "comparison_operator")
2309 (match_operand:GPR 2 "register_operand")
2310 (match_operand:GPR 3 "sfb_alu_operand")))]
2311 "TARGET_SFB_ALU"
2312{
2313 rtx cmp = operands[1];
2314 /* We only handle word mode integer compares for now. */
2315 if (GET_MODE (XEXP (cmp, 0)) != word_mode)
2316 FAIL;
2317 riscv_expand_conditional_move (operands[0], operands[2], operands[3],
2318 GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
2319 DONE;
2320})
2321
2322(define_insn "*mov<GPR:mode><X:mode>cc"
2323 [(set (match_operand:GPR 0 "register_operand" "=r,r")
2324 (if_then_else:GPR
2325 (match_operator 5 "order_operator"
2326 [(match_operand:X 1 "register_operand" "r,r")
2327 (match_operand:X 2 "reg_or_0_operand" "rJ,rJ")])
2328 (match_operand:GPR 3 "register_operand" "0,0")
2329 (match_operand:GPR 4 "sfb_alu_operand" "rJ,IL")))]
2330 "TARGET_SFB_ALU"
2331 "@
7f5ec900
MR
2332 b%C5\t%1,%z2,1f\t# movcc\;mv\t%0,%z4\n1:
2333 b%C5\t%1,%z2,1f\t# movcc\;li\t%0,%4\n1:"
4f475391
AW
2334 [(set_attr "length" "8")
2335 (set_attr "type" "sfb_alu")
2336 (set_attr "mode" "<GPR:MODE>")])
09cae750
PD
2337
2338;; Used to implement built-in functions.
2339(define_expand "condjump"
2340 [(set (pc)
2341 (if_then_else (match_operand 0)
2342 (label_ref (match_operand 1))
2343 (pc)))])
2344
e1fcf14f 2345(define_expand "@cbranch<mode>4"
09cae750
PD
2346 [(set (pc)
2347 (if_then_else (match_operator 0 "comparison_operator"
248710c4
KC
2348 [(match_operand:BR 1 "register_operand")
2349 (match_operand:BR 2 "nonmemory_operand")])
09cae750
PD
2350 (label_ref (match_operand 3 ""))
2351 (pc)))]
2352 ""
2353{
2354 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2355 operands[1], operands[2]);
2356 DONE;
2357})
2358
e1fcf14f 2359(define_expand "@cbranch<mode>4"
09cae750
PD
2360 [(set (pc)
2361 (if_then_else (match_operator 0 "fp_branch_comparison"
2362 [(match_operand:ANYF 1 "register_operand")
2363 (match_operand:ANYF 2 "register_operand")])
2364 (label_ref (match_operand 3 ""))
2365 (pc)))]
ac96e906 2366 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
2367{
2368 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2369 operands[1], operands[2]);
2370 DONE;
2371})
2372
2373(define_insn_and_split "*branch_on_bit<X:mode>"
2374 [(set (pc)
2375 (if_then_else
248710c4
KC
2376 (match_operator 0 "equality_operator"
2377 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2378 (const_int 1)
2379 (match_operand 3 "branch_on_bit_operand"))
2380 (const_int 0)])
2381 (label_ref (match_operand 1))
2382 (pc)))
09cae750
PD
2383 (clobber (match_scratch:X 4 "=&r"))]
2384 ""
2385 "#"
2386 "reload_completed"
2387 [(set (match_dup 4)
2388 (ashift:X (match_dup 2) (match_dup 3)))
2389 (set (pc)
2390 (if_then_else
248710c4
KC
2391 (match_op_dup 0 [(match_dup 4) (const_int 0)])
2392 (label_ref (match_operand 1))
2393 (pc)))]
09cae750
PD
2394{
2395 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
2396 operands[3] = GEN_INT (shift);
2397
2398 if (GET_CODE (operands[0]) == EQ)
2399 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
2400 else
2401 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
2402})
2403
2404(define_insn_and_split "*branch_on_bit_range<X:mode>"
2405 [(set (pc)
2406 (if_then_else
248710c4
KC
2407 (match_operator 0 "equality_operator"
2408 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2409 (match_operand 3 "branch_on_bit_operand")
2410 (const_int 0))
2411 (const_int 0)])
2412 (label_ref (match_operand 1))
2413 (pc)))
09cae750
PD
2414 (clobber (match_scratch:X 4 "=&r"))]
2415 ""
2416 "#"
2417 "reload_completed"
2418 [(set (match_dup 4)
2419 (ashift:X (match_dup 2) (match_dup 3)))
2420 (set (pc)
2421 (if_then_else
248710c4
KC
2422 (match_op_dup 0 [(match_dup 4) (const_int 0)])
2423 (label_ref (match_operand 1))
2424 (pc)))]
09cae750
PD
2425{
2426 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
2427})
2428
2429;;
2430;; ....................
2431;;
2432;; SETTING A REGISTER FROM A COMPARISON
2433;;
2434;; ....................
2435
2436;; Destination is always set in SI mode.
2437
2438(define_expand "cstore<mode>4"
2439 [(set (match_operand:SI 0 "register_operand")
2440 (match_operator:SI 1 "order_operator"
248710c4
KC
2441 [(match_operand:GPR 2 "register_operand")
2442 (match_operand:GPR 3 "nonmemory_operand")]))]
09cae750
PD
2443 ""
2444{
2445 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
2446 operands[3]);
2447 DONE;
2448})
2449
2450(define_expand "cstore<mode>4"
2451 [(set (match_operand:SI 0 "register_operand")
2452 (match_operator:SI 1 "fp_scc_comparison"
248710c4
KC
2453 [(match_operand:ANYF 2 "register_operand")
2454 (match_operand:ANYF 3 "register_operand")]))]
ac96e906 2455 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
2456{
2457 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
2458 operands[3]);
2459 DONE;
2460})
2461
2462(define_insn "*cstore<ANYF:mode><X:mode>4"
248710c4
KC
2463 [(set (match_operand:X 0 "register_operand" "=r")
2464 (match_operator:X 1 "fp_native_comparison"
2465 [(match_operand:ANYF 2 "register_operand" " f")
2466 (match_operand:ANYF 3 "register_operand" " f")]))]
ac96e906 2467 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
2468 "f%C1.<fmt>\t%0,%2,%3"
2469 [(set_attr "type" "fcmp")
2470 (set_attr "mode" "<UNITMODE>")])
2471
1fcbfb00 2472(define_expand "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
94f5a8f0
MR
2473 [(set (match_operand:X 0 "register_operand")
2474 (unspec:X [(match_operand:ANYF 1 "register_operand")
2475 (match_operand:ANYF 2 "register_operand")]
2476 QUIET_COMPARISON))]
ac96e906 2477 "TARGET_HARD_FLOAT || TARGET_ZFINX"
94f5a8f0
MR
2478{
2479 rtx op0 = operands[0];
2480 rtx op1 = operands[1];
2481 rtx op2 = operands[2];
2482 rtx tmp = gen_reg_rtx (SImode);
2483 rtx cmp = gen_rtx_<QUIET_PATTERN> (<X:MODE>mode, op1, op2);
2484 rtx frflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, const0_rtx),
2485 UNSPECV_FRFLAGS);
2486 rtx fsflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, tmp),
2487 UNSPECV_FSFLAGS);
2488
2489 emit_insn (gen_rtx_SET (tmp, frflags));
2490 emit_insn (gen_rtx_SET (op0, cmp));
2491 emit_insn (fsflags);
2492 if (HONOR_SNANS (<ANYF:MODE>mode))
2493 emit_insn (gen_rtx_UNSPEC_VOLATILE (<ANYF:MODE>mode,
2494 gen_rtvec (2, op1, op2),
2495 UNSPECV_FSNVSNAN));
2496 DONE;
2497})
1fcbfb00 2498
09cae750 2499(define_insn "*seq_zero_<X:mode><GPR:mode>"
248710c4
KC
2500 [(set (match_operand:GPR 0 "register_operand" "=r")
2501 (eq:GPR (match_operand:X 1 "register_operand" " r")
2502 (const_int 0)))]
09cae750
PD
2503 ""
2504 "seqz\t%0,%1"
2505 [(set_attr "type" "slt")
2506 (set_attr "mode" "<X:MODE>")])
2507
2508(define_insn "*sne_zero_<X:mode><GPR:mode>"
248710c4
KC
2509 [(set (match_operand:GPR 0 "register_operand" "=r")
2510 (ne:GPR (match_operand:X 1 "register_operand" " r")
2511 (const_int 0)))]
09cae750
PD
2512 ""
2513 "snez\t%0,%1"
2514 [(set_attr "type" "slt")
2515 (set_attr "mode" "<X:MODE>")])
2516
2517(define_insn "*sgt<u>_<X:mode><GPR:mode>"
248710c4
KC
2518 [(set (match_operand:GPR 0 "register_operand" "= r")
2519 (any_gt:GPR (match_operand:X 1 "register_operand" " r")
2520 (match_operand:X 2 "reg_or_0_operand" " rJ")))]
09cae750
PD
2521 ""
2522 "sgt<u>\t%0,%1,%z2"
2523 [(set_attr "type" "slt")
2524 (set_attr "mode" "<X:MODE>")])
2525
2526(define_insn "*sge<u>_<X:mode><GPR:mode>"
248710c4
KC
2527 [(set (match_operand:GPR 0 "register_operand" "=r")
2528 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
2529 (const_int 1)))]
2530 ""
0791ac18 2531 "slt%i2<u>\t%0,zero,%1"
09cae750 2532 [(set_attr "type" "slt")
7ef00402 2533 (set_attr "mode" "<X:MODE>")])
09cae750
PD
2534
2535(define_insn "*slt<u>_<X:mode><GPR:mode>"
248710c4
KC
2536 [(set (match_operand:GPR 0 "register_operand" "= r")
2537 (any_lt:GPR (match_operand:X 1 "register_operand" " r")
2538 (match_operand:X 2 "arith_operand" " rI")))]
09cae750 2539 ""
0791ac18 2540 "slt%i2<u>\t%0,%1,%2"
09cae750 2541 [(set_attr "type" "slt")
7ef00402 2542 (set_attr "mode" "<X:MODE>")])
09cae750
PD
2543
2544(define_insn "*sle<u>_<X:mode><GPR:mode>"
248710c4
KC
2545 [(set (match_operand:GPR 0 "register_operand" "=r")
2546 (any_le:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
2547 (match_operand:X 2 "sle_operand" "")))]
2548 ""
2549{
2550 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
0791ac18 2551 return "slt%i2<u>\t%0,%1,%2";
09cae750
PD
2552}
2553 [(set_attr "type" "slt")
7ef00402 2554 (set_attr "mode" "<X:MODE>")])
09cae750
PD
2555
2556;;
2557;; ....................
2558;;
2559;; UNCONDITIONAL BRANCHES
2560;;
2561;; ....................
2562
2563;; Unconditional branches.
2564
2565(define_insn "jump"
2566 [(set (pc)
2567 (label_ref (match_operand 0 "" "")))]
2568 ""
2569 "j\t%l0"
2570 [(set_attr "type" "jump")
2571 (set_attr "mode" "none")])
2572
2573(define_expand "indirect_jump"
2574 [(set (pc) (match_operand 0 "register_operand"))]
2575 ""
2576{
2577 operands[0] = force_reg (Pmode, operands[0]);
2578 if (Pmode == SImode)
2579 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
2580 else
2581 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
2582 DONE;
2583})
2584
2585(define_insn "indirect_jump<mode>"
2586 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
2587 ""
2588 "jr\t%0"
2589 [(set_attr "type" "jump")
2590 (set_attr "mode" "none")])
2591
2592(define_expand "tablejump"
2593 [(set (pc) (match_operand 0 "register_operand" ""))
2594 (use (label_ref (match_operand 1 "" "")))]
2595 ""
2596{
2597 if (CASE_VECTOR_PC_RELATIVE)
2598 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
2599 gen_rtx_LABEL_REF (Pmode, operands[1]),
2600 NULL_RTX, 0, OPTAB_DIRECT);
2601
2602 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
2603 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
2604 else
2605 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
2606 DONE;
2607})
2608
2609(define_insn "tablejump<mode>"
2610 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
2611 (use (label_ref (match_operand 1 "" "")))]
2612 ""
2613 "jr\t%0"
2614 [(set_attr "type" "jump")
2615 (set_attr "mode" "none")])
2616
2617;;
2618;; ....................
2619;;
2620;; Function prologue/epilogue
2621;;
2622;; ....................
2623;;
2624
2625(define_expand "prologue"
2626 [(const_int 1)]
2627 ""
2628{
2629 riscv_expand_prologue ();
2630 DONE;
2631})
2632
2633;; Block any insns from being moved before this point, since the
2634;; profiling call to mcount can use various registers that aren't
2635;; saved or used to pass arguments.
2636
2637(define_insn "blockage"
2638 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
2639 ""
2640 ""
2641 [(set_attr "type" "ghost")
2642 (set_attr "mode" "none")])
2643
2644(define_expand "epilogue"
2645 [(const_int 2)]
2646 ""
2647{
fd1e52dc 2648 riscv_expand_epilogue (NORMAL_RETURN);
09cae750
PD
2649 DONE;
2650})
2651
2652(define_expand "sibcall_epilogue"
2653 [(const_int 2)]
2654 ""
2655{
fd1e52dc 2656 riscv_expand_epilogue (SIBCALL_RETURN);
09cae750
PD
2657 DONE;
2658})
2659
2660;; Trivial return. Make it look like a normal return insn as that
2661;; allows jump optimizations to work better.
2662
2663(define_expand "return"
2664 [(simple_return)]
2665 "riscv_can_use_return_insn ()"
2666 "")
2667
2668(define_insn "simple_return"
2669 [(simple_return)]
2670 ""
8cad5b14
KC
2671{
2672 return riscv_output_return ();
2673}
09cae750
PD
2674 [(set_attr "type" "jump")
2675 (set_attr "mode" "none")])
2676
2677;; Normal return.
2678
2679(define_insn "simple_return_internal"
2680 [(simple_return)
2681 (use (match_operand 0 "pmode_register_operand" ""))]
2682 ""
2683 "jr\t%0"
2684 [(set_attr "type" "jump")
2685 (set_attr "mode" "none")])
2686
2687;; This is used in compiling the unwind routines.
2688(define_expand "eh_return"
2689 [(use (match_operand 0 "general_operand"))]
2690 ""
2691{
2692 if (GET_MODE (operands[0]) != word_mode)
2693 operands[0] = convert_to_mode (word_mode, operands[0], 0);
2694 if (TARGET_64BIT)
2695 emit_insn (gen_eh_set_lr_di (operands[0]));
2696 else
2697 emit_insn (gen_eh_set_lr_si (operands[0]));
fd1e52dc
JW
2698
2699 emit_jump_insn (gen_eh_return_internal ());
2700 emit_barrier ();
09cae750
PD
2701 DONE;
2702})
2703
2704;; Clobber the return address on the stack. We can't expand this
2705;; until we know where it will be put in the stack frame.
2706
2707(define_insn "eh_set_lr_si"
2708 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2709 (clobber (match_scratch:SI 1 "=&r"))]
2710 "! TARGET_64BIT"
2711 "#")
2712
2713(define_insn "eh_set_lr_di"
2714 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2715 (clobber (match_scratch:DI 1 "=&r"))]
2716 "TARGET_64BIT"
2717 "#")
2718
2719(define_split
2720 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
2721 (clobber (match_scratch 1))]
2722 "reload_completed"
2723 [(const_int 0)]
2724{
2725 riscv_set_return_address (operands[0], operands[1]);
2726 DONE;
2727})
2728
fd1e52dc
JW
2729(define_insn_and_split "eh_return_internal"
2730 [(eh_return)]
2731 ""
2732 "#"
2733 "epilogue_completed"
2734 [(const_int 0)]
2735 "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
2736
09cae750
PD
2737;;
2738;; ....................
2739;;
2740;; FUNCTION CALLS
2741;;
2742;; ....................
2743
2744(define_expand "sibcall"
2745 [(parallel [(call (match_operand 0 "")
2746 (match_operand 1 ""))
2747 (use (match_operand 2 "")) ;; next_arg_reg
2748 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2749 ""
2750{
2751 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2752 emit_call_insn (gen_sibcall_internal (target, operands[1]));
2753 DONE;
2754})
2755
2756(define_insn "sibcall_internal"
2757 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
2758 (match_operand 1 "" ""))]
2759 "SIBLING_CALL_P (insn)"
2760 "@
2761 jr\t%0
2762 tail\t%0
2763 tail\t%0@plt"
2764 [(set_attr "type" "call")])
2765
2766(define_expand "sibcall_value"
2767 [(parallel [(set (match_operand 0 "")
2768 (call (match_operand 1 "")
2769 (match_operand 2 "")))
2770 (use (match_operand 3 ""))])] ;; next_arg_reg
2771 ""
2772{
2773 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2774 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
2775 DONE;
2776})
2777
2778(define_insn "sibcall_value_internal"
2779 [(set (match_operand 0 "" "")
2780 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
2781 (match_operand 2 "" "")))]
2782 "SIBLING_CALL_P (insn)"
2783 "@
2784 jr\t%1
2785 tail\t%1
2786 tail\t%1@plt"
2787 [(set_attr "type" "call")])
2788
2789(define_expand "call"
2790 [(parallel [(call (match_operand 0 "")
2791 (match_operand 1 ""))
2792 (use (match_operand 2 "")) ;; next_arg_reg
2793 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2794 ""
2795{
2796 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2797 emit_call_insn (gen_call_internal (target, operands[1]));
2798 DONE;
2799})
2800
2801(define_insn "call_internal"
2802 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
2803 (match_operand 1 "" ""))
2804 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2805 ""
2806 "@
2807 jalr\t%0
2808 call\t%0
2809 call\t%0@plt"
2810 [(set_attr "type" "call")])
2811
2812(define_expand "call_value"
2813 [(parallel [(set (match_operand 0 "")
2814 (call (match_operand 1 "")
2815 (match_operand 2 "")))
2816 (use (match_operand 3 ""))])] ;; next_arg_reg
2817 ""
2818{
2819 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2820 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
2821 DONE;
2822})
2823
2824(define_insn "call_value_internal"
2825 [(set (match_operand 0 "" "")
2826 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
2827 (match_operand 2 "" "")))
2828 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2829 ""
2830 "@
2831 jalr\t%1
2832 call\t%1
2833 call\t%1@plt"
2834 [(set_attr "type" "call")])
2835
2836;; Call subroutine returning any type.
2837
2838(define_expand "untyped_call"
2839 [(parallel [(call (match_operand 0 "")
2840 (const_int 0))
2841 (match_operand 1 "")
2842 (match_operand 2 "")])]
2843 ""
2844{
2845 int i;
2846
2847 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2848
2849 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2850 {
2851 rtx set = XVECEXP (operands[2], 0, i);
2852 riscv_emit_move (SET_DEST (set), SET_SRC (set));
2853 }
2854
2855 emit_insn (gen_blockage ());
2856 DONE;
2857})
2858
2859(define_insn "nop"
2860 [(const_int 0)]
2861 ""
2862 "nop"
2863 [(set_attr "type" "nop")
2864 (set_attr "mode" "none")])
2865
2866(define_insn "trap"
2867 [(trap_if (const_int 1) (const_int 0))]
2868 ""
2869 "ebreak")
2870
d0e0c130
KC
2871;; Must use the registers that we save to prevent the rename reg optimization
2872;; pass from using them before the gpr_save pattern when shrink wrapping
2873;; occurs. See bug 95252 for instance.
2874
09cae750 2875(define_insn "gpr_save"
d0e0c130
KC
2876 [(match_parallel 1 "gpr_save_operation"
2877 [(unspec_volatile [(match_operand 0 "const_int_operand")]
2878 UNSPECV_GPR_SAVE)])]
09cae750 2879 ""
dcf41a4e 2880 "call\tt0,__riscv_save_%0")
09cae750
PD
2881
2882(define_insn "gpr_restore"
2883 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2884 ""
2885 "tail\t__riscv_restore_%0")
2886
2887(define_insn "gpr_restore_return"
2888 [(return)
2889 (use (match_operand 0 "pmode_register_operand" ""))
2890 (const_int 0)]
2891 ""
2892 "")
2893
2894(define_insn "riscv_frflags"
2895 [(set (match_operand:SI 0 "register_operand" "=r")
2896 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
ac96e906 2897 "TARGET_HARD_FLOAT || TARGET_ZFINX"
d0ebdd9f 2898 "frflags\t%0")
09cae750
PD
2899
2900(define_insn "riscv_fsflags"
2901 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
ac96e906 2902 "TARGET_HARD_FLOAT || TARGET_ZFINX"
d0ebdd9f
JW
2903 "fsflags\t%0")
2904
94f5a8f0
MR
2905(define_insn "*riscv_fsnvsnan<mode>2"
2906 [(unspec_volatile [(match_operand:ANYF 0 "register_operand" "f")
2907 (match_operand:ANYF 1 "register_operand" "f")]
2908 UNSPECV_FSNVSNAN)]
ac96e906 2909 "TARGET_HARD_FLOAT || TARGET_ZFINX"
94f5a8f0
MR
2910 "feq.<fmt>\tzero,%0,%1"
2911 [(set_attr "type" "fcmp")
2912 (set_attr "mode" "<UNITMODE>")])
2913
d0ebdd9f 2914(define_insn "riscv_mret"
eb153f07
JW
2915 [(return)
2916 (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
d0ebdd9f
JW
2917 ""
2918 "mret")
09cae750 2919
ec74725c 2920(define_insn "riscv_sret"
eb153f07
JW
2921 [(return)
2922 (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
ec74725c
JW
2923 ""
2924 "sret")
2925
2926(define_insn "riscv_uret"
eb153f07
JW
2927 [(return)
2928 (unspec_volatile [(const_int 0)] UNSPECV_URET)]
ec74725c
JW
2929 ""
2930 "uret")
2931
09cae750
PD
2932(define_insn "stack_tie<mode>"
2933 [(set (mem:BLK (scratch))
2934 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
2935 (match_operand:X 1 "register_operand" "r")]
2936 UNSPEC_TIE))]
2937 ""
2938 ""
2939 [(set_attr "length" "0")]
2940)
2941
88108b27
AW
2942;; This fixes a failure with gcc.c-torture/execute/pr64242.c at -O2 for a
2943;; 32-bit target when using -mtune=sifive-7-series. The first sched pass
2944;; runs before register elimination, and we have a non-obvious dependency
2945;; between a use of the soft fp and a set of the hard fp. We fix this by
2946;; emitting a clobber using the hard fp between the two insns.
2947(define_expand "restore_stack_nonlocal"
2948 [(match_operand 0 "register_operand")
2949 (match_operand 1 "memory_operand")]
2950 ""
2951{
2952 emit_move_insn (operands[0], operands[1]);
2953 /* Prevent the following hard fp restore from being moved before the move
2954 insn above which uses a copy of the soft fp reg. */
2955 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2956 DONE;
2957})
2958
1073b500
KC
2959;; Named pattern for expanding thread pointer reference.
2960(define_expand "get_thread_pointer<mode>"
2961 [(set (match_operand:P 0 "register_operand" "=r")
2962 (reg:P TP_REGNUM))]
2963 ""
2964{})
2965
c931e8d5
CQ
2966;; Named patterns for stack smashing protection.
2967
2968(define_expand "stack_protect_set"
2969 [(match_operand 0 "memory_operand")
2970 (match_operand 1 "memory_operand")]
2971 ""
2972{
2973 machine_mode mode = GET_MODE (operands[0]);
2974 if (riscv_stack_protector_guard == SSP_TLS)
2975 {
2976 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
2977 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
2978 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
2979 operands[1] = gen_rtx_MEM (Pmode, addr);
2980 }
2981
2982 emit_insn ((mode == DImode
2983 ? gen_stack_protect_set_di
2984 : gen_stack_protect_set_si) (operands[0], operands[1]));
2985 DONE;
2986})
2987
2988;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
2989;; canary value does not live beyond the life of this sequence.
2990(define_insn "stack_protect_set_<mode>"
2991 [(set (match_operand:GPR 0 "memory_operand" "=m")
2992 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")]
2993 UNSPEC_SSP_SET))
2994 (set (match_scratch:GPR 2 "=&r") (const_int 0))]
2995 ""
3cf07cc5 2996 "<load>\t%2, %1\;<store>\t%2, %0\;li\t%2, 0"
c931e8d5
CQ
2997 [(set_attr "length" "12")])
2998
2999(define_expand "stack_protect_test"
3000 [(match_operand 0 "memory_operand")
3001 (match_operand 1 "memory_operand")
3002 (match_operand 2)]
3003 ""
3004{
3005 rtx result;
3006 machine_mode mode = GET_MODE (operands[0]);
3007
3008 result = gen_reg_rtx(mode);
3009 if (riscv_stack_protector_guard == SSP_TLS)
3010 {
3011 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
3012 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
3013 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
3014 operands[1] = gen_rtx_MEM (Pmode, addr);
3015 }
3016 emit_insn ((mode == DImode
3017 ? gen_stack_protect_test_di
3018 : gen_stack_protect_test_si) (result,
3019 operands[0],
3020 operands[1]));
3021
e1fcf14f
CM
3022 rtx cond = gen_rtx_EQ (VOIDmode, result, const0_rtx);
3023 emit_jump_insn (gen_cbranch4 (mode, cond, result, const0_rtx, operands[2]));
c931e8d5
CQ
3024
3025 DONE;
3026})
3027
3028(define_insn "stack_protect_test_<mode>"
3029 [(set (match_operand:GPR 0 "register_operand" "=r")
3030 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")
3031 (match_operand:GPR 2 "memory_operand" "m")]
3032 UNSPEC_SSP_TEST))
3033 (clobber (match_scratch:GPR 3 "=&r"))]
3034 ""
3035 "<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
3036 [(set_attr "length" "12")])
3037
3df3ca90
S
3038(define_insn "riscv_clean_<mode>"
3039 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3040 UNSPECV_CLEAN)]
3041 "TARGET_ZICBOM"
3042 "cbo.clean\t%a0"
3043)
3044
3045(define_insn "riscv_flush_<mode>"
3046 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3047 UNSPECV_FLUSH)]
3048 "TARGET_ZICBOM"
3049 "cbo.flush\t%a0"
3050)
3051
3052(define_insn "riscv_inval_<mode>"
3053 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3054 UNSPECV_INVAL)]
3055 "TARGET_ZICBOM"
3056 "cbo.inval\t%a0"
3057)
3058
3059(define_insn "riscv_zero_<mode>"
3060 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3061 UNSPECV_ZERO)]
3062 "TARGET_ZICBOZ"
3063 "cbo.zero\t%a0"
3064)
3065
3066(define_insn "prefetch"
3067 [(prefetch (match_operand 0 "address_operand" "p")
3068 (match_operand 1 "imm5_operand" "i")
3069 (match_operand 2 "const_int_operand" "n"))]
3070 "TARGET_ZICBOP"
3071{
3072 switch (INTVAL (operands[1]))
3073 {
3074 case 0: return "prefetch.r\t%a0";
3075 case 1: return "prefetch.w\t%a0";
3076 default: gcc_unreachable ();
3077 }
3078})
3079
3080(define_insn "riscv_prefetchi_<mode>"
3081 [(unspec_volatile:X [(match_operand:X 0 "address_operand" "p")
3082 (match_operand:X 1 "imm5_operand" "i")]
3083 UNSPECV_PREI)]
3084 "TARGET_ZICBOP"
3085 "prefetch.i\t%a0"
3086)
3087
283b1707 3088(include "bitmanip.md")
09cae750
PD
3089(include "sync.md")
3090(include "peephole.md")
3091(include "pic.md")
3092(include "generic.md")
88108b27 3093(include "sifive-7.md")
f56d48b2 3094(include "vector.md")