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