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