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