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