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