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