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