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.
6 ;; This file is part of GCC.
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)
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.
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/>.
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.
37 (define_c_enum "unspec" [
38 ;; Override return address for exception handling.
41 ;; Symbolic accesses. The order of this list must match that of
42 ;; enum riscv_symbol_type in riscv-protos.h.
51 ;; High part of PC-relative address.
54 ;; Floating-point unspecs.
83 ;; the calling convention of callee
90 (define_c_enum "unspecv" [
91 ;; Register save and restore.
95 ;; Floating-point unspecs.
102 ;; Interrupt handler instructions.
107 ;; Blockage and synchronization.
112 ;; Stack Smash Protector
123 ;; Zihintpause unspec
132 [(RETURN_ADDR_REGNUM 1)
162 (include "predicates.md")
163 (include "constraints.md")
164 (include "iterators.md")
166 ;; ....................
170 ;; ....................
172 (define_attr "got" "unset,xgot_high,load"
173 (const_string "unset"))
175 ;; Classification of moves, extensions and truncations. Most values
176 ;; are as for "type" (see below) but there are also the following
177 ;; move-specific values:
179 ;; andi a single ANDI instruction
180 ;; shift_shift a shift left followed by a shift right
182 ;; This attribute is used to determine the instruction's length and
183 ;; scheduling type. For doubleword moves, the attribute always describes
184 ;; the split instructions; in some cases, it is more appropriate for the
185 ;; scheduling type to be "multi" instead.
186 (define_attr "move_type"
187 "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove,
188 const,logical,arith,andi,shift_shift,rdvlenb"
189 (const_string "unknown"))
191 ;; Main data type used by the insn
192 (define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,HF,SF,DF,TF,
193 RVVMF64BI,RVVMF32BI,RVVMF16BI,RVVMF8BI,RVVMF4BI,RVVMF2BI,RVVM1BI,
194 RVVM8QI,RVVM4QI,RVVM2QI,RVVM1QI,RVVMF2QI,RVVMF4QI,RVVMF8QI,
195 RVVM8HI,RVVM4HI,RVVM2HI,RVVM1HI,RVVMF2HI,RVVMF4HI,
196 RVVM8HF,RVVM4HF,RVVM2HF,RVVM1HF,RVVMF2HF,RVVMF4HF,
197 RVVM8SI,RVVM4SI,RVVM2SI,RVVM1SI,RVVMF2SI,
198 RVVM8SF,RVVM4SF,RVVM2SF,RVVM1SF,RVVMF2SF,
199 RVVM8DI,RVVM4DI,RVVM2DI,RVVM1DI,
200 RVVM8DF,RVVM4DF,RVVM2DF,RVVM1DF,
201 RVVM1x8QI,RVVMF2x8QI,RVVMF4x8QI,RVVMF8x8QI,
202 RVVM1x7QI,RVVMF2x7QI,RVVMF4x7QI,RVVMF8x7QI,
203 RVVM1x6QI,RVVMF2x6QI,RVVMF4x6QI,RVVMF8x6QI,
204 RVVM1x5QI,RVVMF2x5QI,RVVMF4x5QI,RVVMF8x5QI,
205 RVVM2x4QI,RVVM1x4QI,RVVMF2x4QI,RVVMF4x4QI,RVVMF8x4QI,
206 RVVM2x3QI,RVVM1x3QI,RVVMF2x3QI,RVVMF4x3QI,RVVMF8x3QI,
207 RVVM4x2QI,RVVM2x2QI,RVVM1x2QI,RVVMF2x2QI,RVVMF4x2QI,RVVMF8x2QI,
208 RVVM1x8HI,RVVMF2x8HI,RVVMF4x8HI,
209 RVVM1x7HI,RVVMF2x7HI,RVVMF4x7HI,
210 RVVM1x6HI,RVVMF2x6HI,RVVMF4x6HI,
211 RVVM1x5HI,RVVMF2x5HI,RVVMF4x5HI,
212 RVVM2x4HI,RVVM1x4HI,RVVMF2x4HI,RVVMF4x4HI,
213 RVVM2x3HI,RVVM1x3HI,RVVMF2x3HI,RVVMF4x3HI,
214 RVVM4x2HI,RVVM2x2HI,RVVM1x2HI,RVVMF2x2HI,RVVMF4x2HI,
215 RVVM1x8HF,RVVMF2x8HF,RVVMF4x8HF,RVVM1x7HF,RVVMF2x7HF,
216 RVVMF4x7HF,RVVM1x6HF,RVVMF2x6HF,RVVMF4x6HF,RVVM1x5HF,
217 RVVMF2x5HF,RVVMF4x5HF,RVVM2x4HF,RVVM1x4HF,RVVMF2x4HF,
218 RVVMF4x4HF,RVVM2x3HF,RVVM1x3HF,RVVMF2x3HF,RVVMF4x3HF,
219 RVVM4x2HF,RVVM2x2HF,RVVM1x2HF,RVVMF2x2HF,RVVMF4x2HF,
220 RVVM1x8SI,RVVMF2x8SI,
221 RVVM1x7SI,RVVMF2x7SI,
222 RVVM1x6SI,RVVMF2x6SI,
223 RVVM1x5SI,RVVMF2x5SI,
224 RVVM2x4SI,RVVM1x4SI,RVVMF2x4SI,
225 RVVM2x3SI,RVVM1x3SI,RVVMF2x3SI,
226 RVVM4x2SI,RVVM2x2SI,RVVM1x2SI,RVVMF2x2SI,
227 RVVM1x8SF,RVVMF2x8SF,RVVM1x7SF,RVVMF2x7SF,
228 RVVM1x6SF,RVVMF2x6SF,RVVM1x5SF,RVVMF2x5SF,
229 RVVM2x4SF,RVVM1x4SF,RVVMF2x4SF,RVVM2x3SF,
230 RVVM1x3SF,RVVMF2x3SF,RVVM4x2SF,RVVM2x2SF,
231 RVVM1x2SF,RVVMF2x2SF,
232 RVVM1x8DI,RVVM1x7DI,RVVM1x6DI,RVVM1x5DI,
233 RVVM2x4DI,RVVM1x4DI,RVVM2x3DI,RVVM1x3DI,
234 RVVM4x2DI,RVVM2x2DI,RVVM1x2DI,RVVM1x8DF,
235 RVVM1x7DF,RVVM1x6DF,RVVM1x5DF,RVVM2x4DF,
236 RVVM1x4DF,RVVM2x3DF,RVVM1x3DF,RVVM4x2DF,
238 VNx2x1DF,VNx3x1DF,VNx4x1DF,VNx5x1DF,VNx6x1DF,VNx7x1DF,VNx8x1DF,
239 V1QI,V2QI,V4QI,V8QI,V16QI,V32QI,V64QI,V128QI,V256QI,V512QI,V1024QI,V2048QI,V4096QI,
240 V1HI,V2HI,V4HI,V8HI,V16HI,V32HI,V64HI,V128HI,V256HI,V512HI,V1024HI,V2048HI,
241 V1SI,V2SI,V4SI,V8SI,V16SI,V32SI,V64SI,V128SI,V256SI,V512SI,V1024SI,
242 V1DI,V2DI,V4DI,V8DI,V16DI,V32DI,V64DI,V128DI,V256DI,V512DI,
243 V1HF,V2HF,V4HF,V8HF,V16HF,V32HF,V64HF,V128HF,V256HF,V512HF,V1024HF,V2048HF,
244 V1SF,V2SF,V4SF,V8SF,V16SF,V32SF,V64SF,V128SF,V256SF,V512SF,V1024SF,
245 V1DF,V2DF,V4DF,V8DF,V16DF,V32DF,V64DF,V128DF,V256DF,V512DF,
246 V1BI,V2BI,V4BI,V8BI,V16BI,V32BI,V64BI,V128BI,V256BI,V512BI,V1024BI,V2048BI,V4096BI"
247 (const_string "unknown"))
249 ;; True if the main data type is twice the size of a word.
250 (define_attr "dword_mode" "no,yes"
251 (cond [(and (eq_attr "mode" "DI,DF")
252 (eq (symbol_ref "TARGET_64BIT") (const_int 0)))
255 (and (eq_attr "mode" "TI,TF")
256 (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
257 (const_string "yes")]
258 (const_string "no")))
261 (define_attr "ext" "base,f,d,vector"
262 (const_string "base"))
264 ;; True if the extension is enabled.
265 (define_attr "ext_enabled" "no,yes"
266 (cond [(eq_attr "ext" "base")
269 (and (eq_attr "ext" "f")
270 (match_test "TARGET_HARD_FLOAT"))
273 (and (eq_attr "ext" "d")
274 (match_test "TARGET_DOUBLE_FLOAT"))
277 (and (eq_attr "ext" "vector")
278 (match_test "TARGET_VECTOR"))
281 (const_string "no")))
283 ;; Classification of each insn.
284 ;; branch conditional branch
285 ;; jump unconditional direct jump
286 ;; jalr unconditional indirect jump
287 ;; ret various returns, no arguments
288 ;; call unconditional call
289 ;; load load instruction(s)
290 ;; fpload floating point load
291 ;; store store instruction(s)
292 ;; fpstore floating point store
293 ;; mtc transfer to coprocessor
294 ;; mfc transfer from coprocessor
295 ;; const load constant
296 ;; arith integer arithmetic instructions
297 ;; logical integer logical instructions
298 ;; shift integer shift instructions
299 ;; slt set less than instructions
300 ;; imul integer multiply
301 ;; idiv integer divide
302 ;; move integer register move (addi rd, rs1, 0)
303 ;; fmove floating point register move
304 ;; fadd floating point add/subtract
305 ;; fmul floating point multiply
306 ;; fmadd floating point multiply-add
307 ;; fdiv floating point divide
308 ;; fcmp floating point compare
309 ;; fcvt floating point convert
310 ;; fsqrt floating point square root
311 ;; multi multiword sequence (or user asm statements)
312 ;; auipc integer addition to PC
313 ;; sfb_alu SFB ALU instruction
315 ;; trap trap instruction
316 ;; ghost an instruction that produces no real code
317 ;; bitmanip bit manipulation instructions
318 ;; clmul clmul, clmulh, clmulr
319 ;; rotate rotation instructions
320 ;; atomic atomic instructions
321 ;; condmove conditional moves
322 ;; cbo cache block instructions
323 ;; crypto cryptography instructions
324 ;; pushpop zc push and pop instructions
325 ;; mvpair zc move pair instructions
326 ;; zicond zicond instructions
327 ;; Classification of RVV instructions which will be added to each RVV .md pattern and used by scheduler.
328 ;; rdvlenb vector byte length vlenb csrr read
329 ;; rdvl vector length vl csrr read
330 ;; wrvxrm vector fixed-point rounding mode write
331 ;; wrfrm vector floating-point rounding mode write
332 ;; vsetvl vector configuration-setting instrucions
333 ;; 7. Vector Loads and Stores
334 ;; vlde vector unit-stride load instructions
335 ;; vste vector unit-stride store instructions
336 ;; vldm vector unit-stride mask load instructions
337 ;; vstm vector unit-stride mask store instructions
338 ;; vlds vector strided load instructions
339 ;; vsts vector strided store instructions
340 ;; vldux vector unordered indexed load instructions
341 ;; vldox vector ordered indexed load instructions
342 ;; vstux vector unordered indexed store instructions
343 ;; vstox vector ordered indexed store instructions
344 ;; vldff vector unit-stride fault-only-first load instructions
345 ;; vldr vector whole register load instructions
346 ;; vstr vector whole register store instructions
347 ;; vlsegde vector segment unit-stride load instructions
348 ;; vssegte vector segment unit-stride store instructions
349 ;; vlsegds vector segment strided load instructions
350 ;; vssegts vector segment strided store instructions
351 ;; vlsegdux vector segment unordered indexed load instructions
352 ;; vlsegdox vector segment ordered indexed load instructions
353 ;; vssegtux vector segment unordered indexed store instructions
354 ;; vssegtox vector segment ordered indexed store instructions
355 ;; vlsegdff vector segment unit-stride fault-only-first load instructions
356 ;; 11. Vector integer arithmetic instructions
357 ;; vialu vector single-width integer add and subtract and logical nstructions
358 ;; viwalu vector widening integer add/subtract
359 ;; vext vector integer extension
360 ;; vicalu vector arithmetic with carry or borrow instructions
361 ;; vshift vector single-width bit shift instructions
362 ;; vnshift vector narrowing integer shift instructions
363 ;; viminmax vector integer min/max instructions
364 ;; vicmp vector integer comparison instructions
365 ;; vimul vector single-width integer multiply instructions
366 ;; vidiv vector single-width integer divide instructions
367 ;; viwmul vector widening integer multiply instructions
368 ;; vimuladd vector single-width integer multiply-add instructions
369 ;; viwmuladd vector widening integer multiply-add instructions
370 ;; vimerge vector integer merge instructions
371 ;; vimov vector integer move vector instructions
372 ;; 12. Vector fixed-point arithmetic instructions
373 ;; vsalu vector single-width saturating add and subtract and logical instructions
374 ;; vaalu vector single-width averaging add and subtract and logical instructions
375 ;; vsmul vector single-width fractional multiply with rounding and saturation instructions
376 ;; vsshift vector single-width scaling shift instructions
377 ;; vnclip vector narrowing fixed-point clip instructions
378 ;; 13. Vector floating-point instructions
379 ;; vfalu vector single-width floating-point add/subtract instructions
380 ;; vfwalu vector widening floating-point add/subtract instructions
381 ;; vfmul vector single-width floating-point multiply instructions
382 ;; vfdiv vector single-width floating-point divide instructions
383 ;; vfwmul vector widening floating-point multiply instructions
384 ;; vfmuladd vector single-width floating-point multiply-add instructions
385 ;; vfwmuladd vector widening floating-point multiply-add instructions
386 ;; vfsqrt vector floating-point square-root instructions
387 ;; vfrecp vector floating-point reciprocal square-root instructions
388 ;; vfminmax vector floating-point min/max instructions
389 ;; vfcmp vector floating-point comparison instructions
390 ;; vfsgnj vector floating-point sign-injection instructions
391 ;; vfclass vector floating-point classify instruction
392 ;; vfmerge vector floating-point merge instruction
393 ;; vfmov vector floating-point move instruction
394 ;; vfcvtitof vector single-width integer to floating-point instruction
395 ;; vfcvtftoi vector single-width floating-point to integer instruction
396 ;; vfwcvtitof vector widening integer to floating-point instruction
397 ;; vfwcvtftoi vector widening floating-point to integer instruction
398 ;; vfwcvtftof vector widening floating-point to floating-point instruction
399 ;; vfncvtitof vector narrowing integer to floating-point instruction
400 ;; vfncvtftoi vector narrowing floating-point to integer instruction
401 ;; vfncvtftof vector narrowing floating-point to floating-point instruction
402 ;; 14. Vector reduction operations
403 ;; vired vector single-width integer reduction instructions
404 ;; viwred vector widening integer reduction instructions
405 ;; vfredu vector single-width floating-point un-ordered reduction instruction
406 ;; vfredo vector single-width floating-point ordered reduction instruction
407 ;; vfwredu vector widening floating-point un-ordered reduction instruction
408 ;; vfwredo vector widening floating-point ordered reduction instruction
409 ;; 15. Vector mask instructions
410 ;; vmalu vector mask-register logical instructions
411 ;; vmpop vector mask population count
412 ;; vmffs vector find-first-set mask bit
413 ;; vmsfs vector set mask bit
414 ;; vmiota vector iota
415 ;; vmidx vector element index instruction
416 ;; 16. Vector permutation instructions
417 ;; vimovvx integer scalar move instructions
418 ;; vimovxv integer scalar move instructions
419 ;; vfmovvf floating-point scalar move instructions
420 ;; vfmovfv floating-point scalar move instructions
421 ;; vslideup vector slide instructions
422 ;; vslidedown vector slide instructions
423 ;; vislide1up vector slide instructions
424 ;; vislide1down vector slide instructions
425 ;; vfslide1up vector slide instructions
426 ;; vfslide1down vector slide instructions
427 ;; vgather vector register gather instructions
428 ;; vcompress vector compress instruction
429 ;; vmov whole vector register move
430 ;; vector unknown vector instruction
432 "unknown,branch,jump,jalr,ret,call,load,fpload,store,fpstore,
433 mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
434 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,trap,ghost,bitmanip,
435 rotate,clmul,min,max,minu,maxu,clz,ctz,cpop,
436 atomic,condmove,cbo,crypto,pushpop,mvpair,zicond,rdvlenb,rdvl,wrvxrm,wrfrm,
437 rdfrm,vsetvl,vsetvl_pre,vlde,vste,vldm,vstm,vlds,vsts,
438 vldux,vldox,vstux,vstox,vldff,vldr,vstr,
439 vlsegde,vssegte,vlsegds,vssegts,vlsegdux,vlsegdox,vssegtux,vssegtox,vlsegdff,
440 vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,
441 vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge,vimov,
442 vsalu,vaalu,vsmul,vsshift,vnclip,
443 vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp,
444 vfcmp,vfminmax,vfsgnj,vfclass,vfmerge,vfmov,
445 vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi,
446 vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof,
447 vired,viwred,vfredu,vfredo,vfwredu,vfwredo,
448 vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,vfmovvf,vfmovfv,
449 vslideup,vslidedown,vislide1up,vislide1down,vfslide1up,vfslide1down,
450 vgather,vcompress,vmov,vector"
451 (cond [(eq_attr "got" "load") (const_string "load")
453 ;; If a doubleword move uses these expensive instructions,
454 ;; it is usually better to schedule them in the same way
455 ;; as the singleword form, rather than as "multi".
456 (eq_attr "move_type" "load") (const_string "load")
457 (eq_attr "move_type" "fpload") (const_string "fpload")
458 (eq_attr "move_type" "store") (const_string "store")
459 (eq_attr "move_type" "fpstore") (const_string "fpstore")
460 (eq_attr "move_type" "mtc") (const_string "mtc")
461 (eq_attr "move_type" "mfc") (const_string "mfc")
463 ;; These types of move are always single insns.
464 (eq_attr "move_type" "fmove") (const_string "fmove")
465 (eq_attr "move_type" "arith") (const_string "arith")
466 (eq_attr "move_type" "logical") (const_string "logical")
467 (eq_attr "move_type" "andi") (const_string "logical")
469 ;; These types of move are always split.
470 (eq_attr "move_type" "shift_shift")
471 (const_string "multi")
473 ;; These types of move are split for doubleword modes only.
474 (and (eq_attr "move_type" "move,const")
475 (eq_attr "dword_mode" "yes"))
476 (const_string "multi")
477 (eq_attr "move_type" "move") (const_string "move")
478 (eq_attr "move_type" "const") (const_string "const")
479 (eq_attr "move_type" "rdvlenb") (const_string "rdvlenb")]
480 (const_string "unknown")))
482 ;; True if the float point vector is disabled.
483 (define_attr "fp_vector_disabled" "no,yes"
485 (and (eq_attr "type" "vfmov,vfalu,vfmul,vfdiv,
486 vfwalu,vfwmul,vfmuladd,vfwmuladd,
487 vfsqrt,vfrecp,vfminmax,vfsgnj,vfcmp,
489 vfncvtitof,vfwcvtftoi,vfcvtftoi,vfcvtitof,
490 vfredo,vfredu,vfwredo,vfwredu,
491 vfslide1up,vfslide1down")
492 (and (eq_attr "mode" "RVVM8HF,RVVM4HF,RVVM2HF,RVVM1HF,RVVMF2HF,RVVMF4HF")
493 (match_test "!TARGET_ZVFH")))
496 ;; The mode records as QI for the FP16 <=> INT8 instruction.
497 (and (eq_attr "type" "vfncvtftoi,vfwcvtitof")
498 (and (eq_attr "mode" "RVVM4QI,RVVM2QI,RVVM1QI,RVVMF2QI,RVVMF4QI,RVVMF8QI")
499 (match_test "!TARGET_ZVFH")))
502 (const_string "no")))
504 ;; Attribute to control enable or disable instructions.
505 (define_attr "enabled" "no,yes"
507 (eq_attr "ext_enabled" "no")
510 (eq_attr "fp_vector_disabled" "yes")
513 (const_string "yes")))
515 ;; Length of instruction in bytes.
516 (define_attr "length" ""
518 ;; Branches further than +/- 1 MiB require three instructions.
519 ;; Branches further than +/- 4 KiB require two instructions.
520 (eq_attr "type" "branch")
521 (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4088))
522 (le (minus (pc) (match_dup 0)) (const_int 4092)))
524 (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 1048568))
525 (le (minus (pc) (match_dup 0)) (const_int 1048572)))
529 ;; Jumps further than +/- 1 MiB require two instructions.
530 (eq_attr "type" "jump")
531 (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 1048568))
532 (le (minus (pc) (match_dup 0)) (const_int 1048572)))
536 ;; Conservatively assume calls take two instructions (AUIPC + JALR).
537 ;; The linker will opportunistically relax the sequence to JAL.
538 (eq_attr "type" "call") (const_int 8)
540 ;; "Ghost" instructions occupy no space.
541 (eq_attr "type" "ghost") (const_int 0)
543 (eq_attr "got" "load") (const_int 8)
545 ;; SHIFT_SHIFTs are decomposed into two separate instructions.
546 (eq_attr "move_type" "shift_shift")
549 ;; Check for doubleword moves that are decomposed into two
551 (and (eq_attr "move_type" "mtc,mfc,move")
552 (eq_attr "dword_mode" "yes"))
555 ;; Doubleword CONST{,N} moves are split into two word
557 (and (eq_attr "move_type" "const")
558 (eq_attr "dword_mode" "yes"))
559 (symbol_ref "riscv_split_const_insns (operands[1]) * 4")
561 ;; Otherwise, constants, loads and stores are handled by external
563 (eq_attr "move_type" "load,fpload")
564 (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4")
565 (eq_attr "move_type" "store,fpstore")
566 (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4")
569 ;; Is copying of this instruction disallowed?
570 (define_attr "cannot_copy" "no,yes" (const_string "no"))
572 ;; Microarchitectures we know how to tune for.
573 ;; Keep this in sync with enum riscv_microarchitecture.
575 "generic,sifive_7,generic_ooo"
576 (const (symbol_ref "((enum attr_tune) riscv_microarchitecture)")))
578 ;; Describe a user's asm statement.
579 (define_asm_attributes
580 [(set_attr "type" "multi")])
582 ;; Ghost instructions produce no real code and introduce no hazards.
583 ;; They exist purely to express an effect on dataflow.
584 (define_insn_reservation "ghost" 0
585 (eq_attr "type" "ghost")
589 ;; ....................
593 ;; ....................
596 (define_insn "add<mode>3"
597 [(set (match_operand:ANYF 0 "register_operand" "=f")
598 (plus:ANYF (match_operand:ANYF 1 "register_operand" " f")
599 (match_operand:ANYF 2 "register_operand" " f")))]
600 "TARGET_HARD_FLOAT || TARGET_ZFINX"
601 "fadd.<fmt>\t%0,%1,%2"
602 [(set_attr "type" "fadd")
603 (set_attr "mode" "<UNITMODE>")])
605 (define_insn "*addsi3"
606 [(set (match_operand:SI 0 "register_operand" "=r,r")
607 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
608 (match_operand:SI 2 "arith_operand" " r,I")))]
611 [(set_attr "type" "arith")
612 (set_attr "mode" "SI")])
614 (define_expand "addsi3"
615 [(set (match_operand:SI 0 "register_operand" "=r,r")
616 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
617 (match_operand:SI 2 "arith_operand" " r,I")))]
622 rtx t = gen_reg_rtx (DImode);
623 emit_insn (gen_addsi3_extended (t, operands[1], operands[2]));
624 t = gen_lowpart (SImode, t);
625 SUBREG_PROMOTED_VAR_P (t) = 1;
626 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
627 emit_move_insn (operands[0], t);
632 (define_insn "adddi3"
633 [(set (match_operand:DI 0 "register_operand" "=r,r")
634 (plus:DI (match_operand:DI 1 "register_operand" " r,r")
635 (match_operand:DI 2 "arith_operand" " r,I")))]
638 [(set_attr "type" "arith")
639 (set_attr "mode" "DI")])
641 (define_expand "addv<mode>4"
642 [(set (match_operand:GPR 0 "register_operand" "=r,r")
643 (plus:GPR (match_operand:GPR 1 "register_operand" " r,r")
644 (match_operand:GPR 2 "arith_operand" " r,I")))
645 (label_ref (match_operand 3 "" ""))]
648 if (TARGET_64BIT && <MODE>mode == SImode)
650 rtx t3 = gen_reg_rtx (DImode);
651 rtx t4 = gen_reg_rtx (DImode);
652 rtx t5 = gen_reg_rtx (DImode);
653 rtx t6 = gen_reg_rtx (DImode);
655 riscv_emit_binary (PLUS, operands[0], operands[1], operands[2]);
656 if (GET_CODE (operands[1]) != CONST_INT)
657 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
660 if (GET_CODE (operands[2]) != CONST_INT)
661 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
664 emit_insn (gen_adddi3 (t3, t4, t5));
665 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
667 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
671 rtx t3 = gen_reg_rtx (<MODE>mode);
672 rtx t4 = gen_reg_rtx (<MODE>mode);
674 emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
675 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[2], const0_rtx);
676 emit_insn (gen_cstore<mode>4 (t3, cmp1, operands[2], const0_rtx));
677 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[0], operands[1]);
679 emit_insn (gen_cstore<mode>4 (t4, cmp2, operands[0], operands[1]));
680 riscv_expand_conditional_branch (operands[3], NE, t3, t4);
685 (define_expand "uaddv<mode>4"
686 [(set (match_operand:GPR 0 "register_operand" "=r,r")
687 (plus:GPR (match_operand:GPR 1 "register_operand" " r,r")
688 (match_operand:GPR 2 "arith_operand" " r,I")))
689 (label_ref (match_operand 3 "" ""))]
692 if (TARGET_64BIT && <MODE>mode == SImode)
694 rtx t3 = gen_reg_rtx (DImode);
695 rtx t4 = gen_reg_rtx (DImode);
697 if (GET_CODE (operands[1]) != CONST_INT)
698 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
701 riscv_emit_binary (PLUS, operands[0], operands[1], operands[2]);
702 emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
704 riscv_expand_conditional_branch (operands[3], LTU, t4, t3);
708 emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
709 riscv_expand_conditional_branch (operands[3], LTU, operands[0],
716 (define_insn "addsi3_extended"
717 [(set (match_operand:DI 0 "register_operand" "=r,r")
719 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
720 (match_operand:SI 2 "arith_operand" " r,I"))))]
723 [(set_attr "type" "arith")
724 (set_attr "mode" "SI")])
726 (define_insn "*addsi3_extended2"
727 [(set (match_operand:DI 0 "register_operand" "=r,r")
729 (match_operator:SI 3 "subreg_lowpart_operator"
730 [(plus:DI (match_operand:DI 1 "register_operand" " r,r")
731 (match_operand:DI 2 "arith_operand" " r,I"))])))]
734 [(set_attr "type" "arith")
735 (set_attr "mode" "SI")])
738 ;; ....................
742 ;; ....................
745 (define_insn "sub<mode>3"
746 [(set (match_operand:ANYF 0 "register_operand" "=f")
747 (minus:ANYF (match_operand:ANYF 1 "register_operand" " f")
748 (match_operand:ANYF 2 "register_operand" " f")))]
749 "TARGET_HARD_FLOAT || TARGET_ZFINX"
750 "fsub.<fmt>\t%0,%1,%2"
751 [(set_attr "type" "fadd")
752 (set_attr "mode" "<UNITMODE>")])
754 (define_insn "subdi3"
755 [(set (match_operand:DI 0 "register_operand" "= r")
756 (minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
757 (match_operand:DI 2 "register_operand" " r")))]
760 [(set_attr "type" "arith")
761 (set_attr "mode" "DI")])
763 (define_insn "*subsi3"
764 [(set (match_operand:SI 0 "register_operand" "= r")
765 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
766 (match_operand:SI 2 "register_operand" " r")))]
769 [(set_attr "type" "arith")
770 (set_attr "mode" "SI")])
772 (define_expand "subsi3"
773 [(set (match_operand:SI 0 "register_operand" "= r")
774 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
775 (match_operand:SI 2 "register_operand" " r")))]
780 rtx t = gen_reg_rtx (DImode);
781 emit_insn (gen_subsi3_extended (t, operands[1], operands[2]));
782 t = gen_lowpart (SImode, t);
783 SUBREG_PROMOTED_VAR_P (t) = 1;
784 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
785 emit_move_insn (operands[0], t);
790 (define_expand "subv<mode>4"
791 [(set (match_operand:GPR 0 "register_operand" "= r")
792 (minus:GPR (match_operand:GPR 1 "reg_or_0_operand" " rJ")
793 (match_operand:GPR 2 "register_operand" " r")))
794 (label_ref (match_operand 3 "" ""))]
797 if (TARGET_64BIT && <MODE>mode == SImode)
799 rtx t3 = gen_reg_rtx (DImode);
800 rtx t4 = gen_reg_rtx (DImode);
801 rtx t5 = gen_reg_rtx (DImode);
802 rtx t6 = gen_reg_rtx (DImode);
804 riscv_emit_binary (MINUS, operands[0], operands[1], operands[2]);
805 if (GET_CODE (operands[1]) != CONST_INT)
806 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
809 if (GET_CODE (operands[2]) != CONST_INT)
810 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
813 emit_insn (gen_subdi3 (t3, t4, t5));
814 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
816 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
820 rtx t3 = gen_reg_rtx (<MODE>mode);
821 rtx t4 = gen_reg_rtx (<MODE>mode);
823 emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
825 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[2], const0_rtx);
826 emit_insn (gen_cstore<mode>4 (t3, cmp1, operands[2], const0_rtx));
828 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[1], operands[0]);
829 emit_insn (gen_cstore<mode>4 (t4, cmp2, operands[1], operands[0]));
831 riscv_expand_conditional_branch (operands[3], NE, t3, t4);
837 (define_expand "usubv<mode>4"
838 [(set (match_operand:GPR 0 "register_operand" "= r")
839 (minus:GPR (match_operand:GPR 1 "reg_or_0_operand" " rJ")
840 (match_operand:GPR 2 "register_operand" " r")))
841 (label_ref (match_operand 3 "" ""))]
844 if (TARGET_64BIT && <MODE>mode == SImode)
846 rtx t3 = gen_reg_rtx (DImode);
847 rtx t4 = gen_reg_rtx (DImode);
849 if (GET_CODE (operands[1]) != CONST_INT)
850 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
853 riscv_emit_binary (MINUS, operands[0], operands[1], operands[2]);
854 emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
856 riscv_expand_conditional_branch (operands[3], LTU, t3, t4);
860 emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
861 riscv_expand_conditional_branch (operands[3], LTU, operands[1],
869 (define_insn "subsi3_extended"
870 [(set (match_operand:DI 0 "register_operand" "= r")
872 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
873 (match_operand:SI 2 "register_operand" " r"))))]
876 [(set_attr "type" "arith")
877 (set_attr "mode" "SI")])
879 (define_insn "*subsi3_extended2"
880 [(set (match_operand:DI 0 "register_operand" "= r")
882 (match_operator:SI 3 "subreg_lowpart_operator"
883 [(minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
884 (match_operand:DI 2 "register_operand" " r"))])))]
887 [(set_attr "type" "arith")
888 (set_attr "mode" "SI")])
890 (define_insn "negdi2"
891 [(set (match_operand:DI 0 "register_operand" "=r")
892 (neg:DI (match_operand:DI 1 "register_operand" " r")))]
895 [(set_attr "type" "arith")
896 (set_attr "mode" "DI")])
898 (define_insn "*negsi2"
899 [(set (match_operand:SI 0 "register_operand" "=r")
900 (neg:SI (match_operand:SI 1 "register_operand" " r")))]
903 [(set_attr "type" "arith")
904 (set_attr "mode" "SI")])
906 (define_expand "negsi2"
907 [(set (match_operand:SI 0 "register_operand" "=r")
908 (neg:SI (match_operand:SI 1 "register_operand" " r")))]
913 rtx t = gen_reg_rtx (DImode);
914 emit_insn (gen_negsi2_extended (t, operands[1]));
915 t = gen_lowpart (SImode, t);
916 SUBREG_PROMOTED_VAR_P (t) = 1;
917 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
918 emit_move_insn (operands[0], t);
923 (define_insn "negsi2_extended"
924 [(set (match_operand:DI 0 "register_operand" "=r")
926 (neg:SI (match_operand:SI 1 "register_operand" " r"))))]
929 [(set_attr "type" "arith")
930 (set_attr "mode" "SI")])
932 (define_insn "*negsi2_extended2"
933 [(set (match_operand:DI 0 "register_operand" "=r")
935 (match_operator:SI 2 "subreg_lowpart_operator"
936 [(neg:DI (match_operand:DI 1 "register_operand" " r"))])))]
939 [(set_attr "type" "arith")
940 (set_attr "mode" "SI")])
943 ;; ....................
947 ;; ....................
950 (define_insn "mul<mode>3"
951 [(set (match_operand:ANYF 0 "register_operand" "=f")
952 (mult:ANYF (match_operand:ANYF 1 "register_operand" " f")
953 (match_operand:ANYF 2 "register_operand" " f")))]
954 "TARGET_HARD_FLOAT || TARGET_ZFINX"
955 "fmul.<fmt>\t%0,%1,%2"
956 [(set_attr "type" "fmul")
957 (set_attr "mode" "<UNITMODE>")])
959 (define_insn "*mulsi3"
960 [(set (match_operand:SI 0 "register_operand" "=r")
961 (mult:SI (match_operand:SI 1 "register_operand" " r")
962 (match_operand:SI 2 "register_operand" " r")))]
963 "TARGET_ZMMUL || TARGET_MUL"
965 [(set_attr "type" "imul")
966 (set_attr "mode" "SI")])
968 (define_expand "mulsi3"
969 [(set (match_operand:SI 0 "register_operand" "=r")
970 (mult:SI (match_operand:SI 1 "register_operand" " r")
971 (match_operand:SI 2 "register_operand" " r")))]
972 "TARGET_ZMMUL || TARGET_MUL"
976 rtx t = gen_reg_rtx (DImode);
977 emit_insn (gen_mulsi3_extended (t, operands[1], operands[2]));
978 t = gen_lowpart (SImode, t);
979 SUBREG_PROMOTED_VAR_P (t) = 1;
980 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
981 emit_move_insn (operands[0], t);
986 (define_insn "muldi3"
987 [(set (match_operand:DI 0 "register_operand" "=r")
988 (mult:DI (match_operand:DI 1 "register_operand" " r")
989 (match_operand:DI 2 "register_operand" " r")))]
990 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
992 [(set_attr "type" "imul")
993 (set_attr "mode" "DI")])
995 (define_expand "mulv<mode>4"
996 [(set (match_operand:GPR 0 "register_operand" "=r")
997 (mult:GPR (match_operand:GPR 1 "register_operand" " r")
998 (match_operand:GPR 2 "register_operand" " r")))
999 (label_ref (match_operand 3 "" ""))]
1000 "TARGET_ZMMUL || TARGET_MUL"
1002 if (TARGET_64BIT && <MODE>mode == SImode)
1004 rtx t3 = gen_reg_rtx (DImode);
1005 rtx t4 = gen_reg_rtx (DImode);
1006 rtx t5 = gen_reg_rtx (DImode);
1007 rtx t6 = gen_reg_rtx (DImode);
1009 if (GET_CODE (operands[1]) != CONST_INT)
1010 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
1013 if (GET_CODE (operands[2]) != CONST_INT)
1014 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
1017 emit_insn (gen_muldi3 (t3, t4, t5));
1019 emit_move_insn (operands[0], gen_lowpart (SImode, t3));
1020 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
1022 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
1026 rtx hp = gen_reg_rtx (<MODE>mode);
1027 rtx lp = gen_reg_rtx (<MODE>mode);
1029 emit_insn (gen_smul<mode>3_highpart (hp, operands[1], operands[2]));
1030 emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
1031 riscv_emit_binary (ASHIFTRT, lp, operands[0],
1032 GEN_INT (BITS_PER_WORD - 1));
1034 riscv_expand_conditional_branch (operands[3], NE, hp, lp);
1040 (define_expand "umulv<mode>4"
1041 [(set (match_operand:GPR 0 "register_operand" "=r")
1042 (mult:GPR (match_operand:GPR 1 "register_operand" " r")
1043 (match_operand:GPR 2 "register_operand" " r")))
1044 (label_ref (match_operand 3 "" ""))]
1045 "TARGET_ZMMUL || TARGET_MUL"
1047 if (TARGET_64BIT && <MODE>mode == SImode)
1049 rtx t3 = gen_reg_rtx (DImode);
1050 rtx t4 = gen_reg_rtx (DImode);
1051 rtx t5 = gen_reg_rtx (DImode);
1052 rtx t6 = gen_reg_rtx (DImode);
1053 rtx t7 = gen_reg_rtx (DImode);
1054 rtx t8 = gen_reg_rtx (DImode);
1056 if (GET_CODE (operands[1]) != CONST_INT)
1057 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
1060 if (GET_CODE (operands[2]) != CONST_INT)
1061 emit_insn (gen_extend_insn (t4, operands[2], DImode, SImode, 0));
1065 emit_insn (gen_ashldi3 (t5, t3, GEN_INT (32)));
1066 emit_insn (gen_ashldi3 (t6, t4, GEN_INT (32)));
1067 emit_insn (gen_umuldi3_highpart (t7, t5, t6));
1068 emit_move_insn (operands[0], gen_lowpart (SImode, t7));
1069 emit_insn (gen_lshrdi3 (t8, t7, GEN_INT (32)));
1071 riscv_expand_conditional_branch (operands[3], NE, t8, const0_rtx);
1075 rtx hp = gen_reg_rtx (<MODE>mode);
1077 emit_insn (gen_umul<mode>3_highpart (hp, operands[1], operands[2]));
1078 emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
1080 riscv_expand_conditional_branch (operands[3], NE, hp, const0_rtx);
1086 (define_insn "mulsi3_extended"
1087 [(set (match_operand:DI 0 "register_operand" "=r")
1089 (mult:SI (match_operand:SI 1 "register_operand" " r")
1090 (match_operand:SI 2 "register_operand" " r"))))]
1091 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
1093 [(set_attr "type" "imul")
1094 (set_attr "mode" "SI")])
1096 (define_insn "*mulsi3_extended2"
1097 [(set (match_operand:DI 0 "register_operand" "=r")
1099 (match_operator:SI 3 "subreg_lowpart_operator"
1100 [(mult:DI (match_operand:DI 1 "register_operand" " r")
1101 (match_operand:DI 2 "register_operand" " r"))])))]
1102 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
1104 [(set_attr "type" "imul")
1105 (set_attr "mode" "SI")])
1108 ;; ........................
1110 ;; MULTIPLICATION HIGH-PART
1112 ;; ........................
1116 (define_expand "<u>mulditi3"
1117 [(set (match_operand:TI 0 "register_operand")
1118 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
1119 (any_extend:TI (match_operand:DI 2 "register_operand"))))]
1120 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
1122 rtx low = gen_reg_rtx (DImode);
1123 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
1125 rtx high = gen_reg_rtx (DImode);
1126 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
1128 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1129 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1133 (define_insn "<su>muldi3_highpart"
1134 [(set (match_operand:DI 0 "register_operand" "=r")
1137 (mult:TI (any_extend:TI
1138 (match_operand:DI 1 "register_operand" " r"))
1140 (match_operand:DI 2 "register_operand" " r")))
1142 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
1144 [(set_attr "type" "imul")
1145 (set_attr "mode" "DI")])
1147 (define_expand "usmulditi3"
1148 [(set (match_operand:TI 0 "register_operand")
1149 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand"))
1150 (sign_extend:TI (match_operand:DI 2 "register_operand"))))]
1151 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
1153 rtx low = gen_reg_rtx (DImode);
1154 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
1156 rtx high = gen_reg_rtx (DImode);
1157 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2]));
1159 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1160 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1164 (define_insn "usmuldi3_highpart"
1165 [(set (match_operand:DI 0 "register_operand" "=r")
1168 (mult:TI (zero_extend:TI
1169 (match_operand:DI 1 "register_operand" "r"))
1171 (match_operand:DI 2 "register_operand" " r")))
1173 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
1175 [(set_attr "type" "imul")
1176 (set_attr "mode" "DI")])
1178 (define_expand "<u>mulsidi3"
1179 [(set (match_operand:DI 0 "register_operand" "=r")
1180 (mult:DI (any_extend:DI
1181 (match_operand:SI 1 "register_operand" " r"))
1183 (match_operand:SI 2 "register_operand" " r"))))]
1184 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
1186 rtx temp = gen_reg_rtx (SImode);
1187 riscv_emit_binary (MULT, temp, operands[1], operands[2]);
1188 emit_insn (gen_<su>mulsi3_highpart (riscv_subword (operands[0], true),
1189 operands[1], operands[2]));
1190 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
1194 (define_insn "<su>mulsi3_highpart"
1195 [(set (match_operand:SI 0 "register_operand" "=r")
1198 (mult:DI (any_extend:DI
1199 (match_operand:SI 1 "register_operand" " r"))
1201 (match_operand:SI 2 "register_operand" " r")))
1203 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
1205 [(set_attr "type" "imul")
1206 (set_attr "mode" "SI")])
1209 (define_expand "usmulsidi3"
1210 [(set (match_operand:DI 0 "register_operand" "=r")
1211 (mult:DI (zero_extend:DI
1212 (match_operand:SI 1 "register_operand" " r"))
1214 (match_operand:SI 2 "register_operand" " r"))))]
1215 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
1217 rtx temp = gen_reg_rtx (SImode);
1218 riscv_emit_binary (MULT, temp, operands[1], operands[2]);
1219 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true),
1220 operands[1], operands[2]));
1221 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
1225 (define_insn "usmulsi3_highpart"
1226 [(set (match_operand:SI 0 "register_operand" "=r")
1229 (mult:DI (zero_extend:DI
1230 (match_operand:SI 1 "register_operand" " r"))
1232 (match_operand:SI 2 "register_operand" " r")))
1234 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
1236 [(set_attr "type" "imul")
1237 (set_attr "mode" "SI")])
1240 ;; ....................
1242 ;; DIVISION and REMAINDER
1244 ;; ....................
1247 (define_insn "*<optab>si3"
1248 [(set (match_operand:SI 0 "register_operand" "=r")
1249 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1250 (match_operand:SI 2 "register_operand" " r")))]
1252 "<insn>%i2%~\t%0,%1,%2"
1253 [(set_attr "type" "idiv")
1254 (set_attr "mode" "SI")])
1256 (define_expand "<optab>si3"
1257 [(set (match_operand:SI 0 "register_operand" "=r")
1258 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1259 (match_operand:SI 2 "register_operand" " r")))]
1264 rtx t = gen_reg_rtx (DImode);
1265 emit_insn (gen_<optab>si3_extended (t, operands[1], operands[2]));
1266 t = gen_lowpart (SImode, t);
1267 SUBREG_PROMOTED_VAR_P (t) = 1;
1268 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
1269 emit_move_insn (operands[0], t);
1274 (define_insn "<optab>di3"
1275 [(set (match_operand:DI 0 "register_operand" "=r")
1276 (any_div:DI (match_operand:DI 1 "register_operand" " r")
1277 (match_operand:DI 2 "register_operand" " r")))]
1278 "TARGET_DIV && TARGET_64BIT"
1279 "<insn>%i2\t%0,%1,%2"
1280 [(set_attr "type" "idiv")
1281 (set_attr "mode" "DI")])
1283 (define_expand "<u>divmod<mode>4"
1285 [(set (match_operand:GPR 0 "register_operand")
1286 (only_div:GPR (match_operand:GPR 1 "register_operand")
1287 (match_operand:GPR 2 "register_operand")))
1288 (set (match_operand:GPR 3 "register_operand")
1289 (<paired_mod>:GPR (match_dup 1) (match_dup 2)))])]
1290 "TARGET_DIV && riscv_use_divmod_expander ()"
1292 rtx tmp = gen_reg_rtx (<MODE>mode);
1293 emit_insn (gen_<u>div<GPR:mode>3 (operands[0], operands[1], operands[2]));
1294 emit_insn (gen_mul<GPR:mode>3 (tmp, operands[0], operands[2]));
1295 emit_insn (gen_sub<GPR:mode>3 (operands[3], operands[1], tmp));
1299 (define_insn "<optab>si3_extended"
1300 [(set (match_operand:DI 0 "register_operand" "=r")
1302 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1303 (match_operand:SI 2 "register_operand" " r"))))]
1304 "TARGET_DIV && TARGET_64BIT"
1305 "<insn>%i2w\t%0,%1,%2"
1306 [(set_attr "type" "idiv")
1307 (set_attr "mode" "DI")])
1309 (define_insn "div<mode>3"
1310 [(set (match_operand:ANYF 0 "register_operand" "=f")
1311 (div:ANYF (match_operand:ANYF 1 "register_operand" " f")
1312 (match_operand:ANYF 2 "register_operand" " f")))]
1313 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
1314 "fdiv.<fmt>\t%0,%1,%2"
1315 [(set_attr "type" "fdiv")
1316 (set_attr "mode" "<UNITMODE>")])
1319 ;; ....................
1323 ;; ....................
1325 (define_insn "sqrt<mode>2"
1326 [(set (match_operand:ANYF 0 "register_operand" "=f")
1327 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
1328 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
1330 return "fsqrt.<fmt>\t%0,%1";
1332 [(set_attr "type" "fsqrt")
1333 (set_attr "mode" "<UNITMODE>")])
1335 ;; Floating point multiply accumulate instructions.
1338 (define_insn "fma<mode>4"
1339 [(set (match_operand:ANYF 0 "register_operand" "=f")
1340 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
1341 (match_operand:ANYF 2 "register_operand" " f")
1342 (match_operand:ANYF 3 "register_operand" " f")))]
1343 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1344 "fmadd.<fmt>\t%0,%1,%2,%3"
1345 [(set_attr "type" "fmadd")
1346 (set_attr "mode" "<UNITMODE>")])
1349 (define_insn "fms<mode>4"
1350 [(set (match_operand:ANYF 0 "register_operand" "=f")
1351 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
1352 (match_operand:ANYF 2 "register_operand" " f")
1353 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
1354 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1355 "fmsub.<fmt>\t%0,%1,%2,%3"
1356 [(set_attr "type" "fmadd")
1357 (set_attr "mode" "<UNITMODE>")])
1360 (define_insn "fnms<mode>4"
1361 [(set (match_operand:ANYF 0 "register_operand" "=f")
1363 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1364 (match_operand:ANYF 2 "register_operand" " f")
1365 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
1366 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1367 "fnmadd.<fmt>\t%0,%1,%2,%3"
1368 [(set_attr "type" "fmadd")
1369 (set_attr "mode" "<UNITMODE>")])
1372 (define_insn "fnma<mode>4"
1373 [(set (match_operand:ANYF 0 "register_operand" "=f")
1375 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1376 (match_operand:ANYF 2 "register_operand" " f")
1377 (match_operand:ANYF 3 "register_operand" " f")))]
1378 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1379 "fnmsub.<fmt>\t%0,%1,%2,%3"
1380 [(set_attr "type" "fmadd")
1381 (set_attr "mode" "<UNITMODE>")])
1383 ;; -(-a * b - c), modulo signed zeros
1384 (define_insn "*fma<mode>4"
1385 [(set (match_operand:ANYF 0 "register_operand" "=f")
1388 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1389 (match_operand:ANYF 2 "register_operand" " f")
1390 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
1391 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1392 "fmadd.<fmt>\t%0,%1,%2,%3"
1393 [(set_attr "type" "fmadd")
1394 (set_attr "mode" "<UNITMODE>")])
1396 ;; -(-a * b + c), modulo signed zeros
1397 (define_insn "*fms<mode>4"
1398 [(set (match_operand:ANYF 0 "register_operand" "=f")
1401 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1402 (match_operand:ANYF 2 "register_operand" " f")
1403 (match_operand:ANYF 3 "register_operand" " f"))))]
1404 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1405 "fmsub.<fmt>\t%0,%1,%2,%3"
1406 [(set_attr "type" "fmadd")
1407 (set_attr "mode" "<UNITMODE>")])
1409 ;; -(a * b + c), modulo signed zeros
1410 (define_insn "*fnms<mode>4"
1411 [(set (match_operand:ANYF 0 "register_operand" "=f")
1414 (match_operand:ANYF 1 "register_operand" " f")
1415 (match_operand:ANYF 2 "register_operand" " f")
1416 (match_operand:ANYF 3 "register_operand" " f"))))]
1417 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1418 "fnmadd.<fmt>\t%0,%1,%2,%3"
1419 [(set_attr "type" "fmadd")
1420 (set_attr "mode" "<UNITMODE>")])
1422 ;; -(a * b - c), modulo signed zeros
1423 (define_insn "*fnma<mode>4"
1424 [(set (match_operand:ANYF 0 "register_operand" "=f")
1427 (match_operand:ANYF 1 "register_operand" " f")
1428 (match_operand:ANYF 2 "register_operand" " f")
1429 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
1430 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
1431 "fnmsub.<fmt>\t%0,%1,%2,%3"
1432 [(set_attr "type" "fmadd")
1433 (set_attr "mode" "<UNITMODE>")])
1436 ;; ....................
1440 ;; ....................
1442 (define_insn "abs<mode>2"
1443 [(set (match_operand:ANYF 0 "register_operand" "=f")
1444 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
1445 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1447 [(set_attr "type" "fmove")
1448 (set_attr "mode" "<UNITMODE>")])
1450 (define_insn "copysign<mode>3"
1451 [(set (match_operand:ANYF 0 "register_operand" "=f")
1452 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")
1453 (match_operand:ANYF 2 "register_operand" " f")]
1455 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1456 "fsgnj.<fmt>\t%0,%1,%2"
1457 [(set_attr "type" "fmove")
1458 (set_attr "mode" "<UNITMODE>")])
1460 (define_insn "neg<mode>2"
1461 [(set (match_operand:ANYF 0 "register_operand" "=f")
1462 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
1463 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1465 [(set_attr "type" "fmove")
1466 (set_attr "mode" "<UNITMODE>")])
1469 ;; ....................
1473 ;; ....................
1475 (define_insn "fminm<mode>3"
1476 [(set (match_operand:ANYF 0 "register_operand" "=f")
1477 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1478 (use (match_operand:ANYF 2 "register_operand" " f"))]
1480 "TARGET_HARD_FLOAT && TARGET_ZFA"
1481 "fminm.<fmt>\t%0,%1,%2"
1482 [(set_attr "type" "fmove")
1483 (set_attr "mode" "<UNITMODE>")])
1485 (define_insn "fmaxm<mode>3"
1486 [(set (match_operand:ANYF 0 "register_operand" "=f")
1487 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1488 (use (match_operand:ANYF 2 "register_operand" " f"))]
1490 "TARGET_HARD_FLOAT && TARGET_ZFA"
1491 "fmaxm.<fmt>\t%0,%1,%2"
1492 [(set_attr "type" "fmove")
1493 (set_attr "mode" "<UNITMODE>")])
1495 (define_insn "fmin<mode>3"
1496 [(set (match_operand:ANYF 0 "register_operand" "=f")
1497 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1498 (use (match_operand:ANYF 2 "register_operand" " f"))]
1500 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SNANS (<MODE>mode)"
1501 "fmin.<fmt>\t%0,%1,%2"
1502 [(set_attr "type" "fmove")
1503 (set_attr "mode" "<UNITMODE>")])
1505 (define_insn "fmax<mode>3"
1506 [(set (match_operand:ANYF 0 "register_operand" "=f")
1507 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1508 (use (match_operand:ANYF 2 "register_operand" " f"))]
1510 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SNANS (<MODE>mode)"
1511 "fmax.<fmt>\t%0,%1,%2"
1512 [(set_attr "type" "fmove")
1513 (set_attr "mode" "<UNITMODE>")])
1515 (define_insn "smin<mode>3"
1516 [(set (match_operand:ANYF 0 "register_operand" "=f")
1517 (smin:ANYF (match_operand:ANYF 1 "register_operand" " f")
1518 (match_operand:ANYF 2 "register_operand" " f")))]
1519 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1520 "fmin.<fmt>\t%0,%1,%2"
1521 [(set_attr "type" "fmove")
1522 (set_attr "mode" "<UNITMODE>")])
1524 (define_insn "smax<mode>3"
1525 [(set (match_operand:ANYF 0 "register_operand" "=f")
1526 (smax:ANYF (match_operand:ANYF 1 "register_operand" " f")
1527 (match_operand:ANYF 2 "register_operand" " f")))]
1528 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1529 "fmax.<fmt>\t%0,%1,%2"
1530 [(set_attr "type" "fmove")
1531 (set_attr "mode" "<UNITMODE>")])
1534 ;; ....................
1538 ;; ....................
1541 ;; For RV64, we don't expose the SImode operations to the rtl expanders,
1542 ;; but SImode versions exist for combine.
1544 (define_expand "and<mode>3"
1545 [(set (match_operand:X 0 "register_operand")
1546 (and:X (match_operand:X 1 "register_operand")
1547 (match_operand:X 2 "arith_operand_or_mode_mask")))]
1550 /* If the second operand is a mode mask, emit an extension
1552 if (CONST_INT_P (operands[2]))
1554 enum machine_mode tmode = VOIDmode;
1555 if (UINTVAL (operands[2]) == GET_MODE_MASK (HImode))
1557 else if (UINTVAL (operands[2]) == GET_MODE_MASK (SImode))
1560 if (tmode != VOIDmode)
1562 rtx tmp = gen_lowpart (tmode, operands[1]);
1563 emit_insn (gen_extend_insn (operands[0], tmp, <MODE>mode, tmode, 1));
1569 (define_insn "*and<mode>3"
1570 [(set (match_operand:X 0 "register_operand" "=r,r")
1571 (and:X (match_operand:X 1 "register_operand" "%r,r")
1572 (match_operand:X 2 "arith_operand" " r,I")))]
1575 [(set_attr "type" "logical")
1576 (set_attr "mode" "<MODE>")])
1578 (define_insn "<optab><mode>3"
1579 [(set (match_operand:X 0 "register_operand" "=r,r")
1580 (any_or:X (match_operand:X 1 "register_operand" "%r,r")
1581 (match_operand:X 2 "arith_operand" " r,I")))]
1583 "<insn>%i2\t%0,%1,%2"
1584 [(set_attr "type" "logical")
1585 (set_attr "mode" "<MODE>")])
1587 (define_insn "*<optab>si3_internal"
1588 [(set (match_operand:SI 0 "register_operand" "=r,r")
1589 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
1590 (match_operand:SI 2 "arith_operand" " r,I")))]
1592 "<insn>%i2\t%0,%1,%2"
1593 [(set_attr "type" "logical")
1594 (set_attr "mode" "SI")])
1596 (define_insn "one_cmpl<mode>2"
1597 [(set (match_operand:X 0 "register_operand" "=r")
1598 (not:X (match_operand:X 1 "register_operand" " r")))]
1601 [(set_attr "type" "logical")
1602 (set_attr "mode" "<MODE>")])
1604 (define_insn "*one_cmplsi2_internal"
1605 [(set (match_operand:SI 0 "register_operand" "=r")
1606 (not:SI (match_operand:SI 1 "register_operand" " r")))]
1609 [(set_attr "type" "logical")
1610 (set_attr "mode" "SI")])
1613 ;; ....................
1617 ;; ....................
1619 (define_insn "truncdfsf2"
1620 [(set (match_operand:SF 0 "register_operand" "=f")
1622 (match_operand:DF 1 "register_operand" " f")))]
1623 "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
1625 [(set_attr "type" "fcvt")
1626 (set_attr "mode" "SF")])
1628 (define_insn "truncsfhf2"
1629 [(set (match_operand:HF 0 "register_operand" "=f")
1631 (match_operand:SF 1 "register_operand" " f")))]
1632 "TARGET_ZFHMIN || TARGET_ZHINXMIN"
1634 [(set_attr "type" "fcvt")
1635 (set_attr "mode" "HF")])
1637 (define_insn "truncdfhf2"
1638 [(set (match_operand:HF 0 "register_operand" "=f")
1640 (match_operand:DF 1 "register_operand" " f")))]
1641 "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
1642 (TARGET_ZHINXMIN && TARGET_ZDINX)"
1644 [(set_attr "type" "fcvt")
1645 (set_attr "mode" "HF")])
1648 ;; ....................
1652 ;; ....................
1656 (define_expand "zero_extendsidi2"
1657 [(set (match_operand:DI 0 "register_operand")
1658 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
1661 (define_insn_and_split "*zero_extendsidi2_internal"
1662 [(set (match_operand:DI 0 "register_operand" "=r,r")
1664 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1665 "TARGET_64BIT && !TARGET_ZBA && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
1666 && !(register_operand (operands[1], SImode)
1667 && reg_or_subregno (operands[1]) == VL_REGNUM)"
1671 "&& reload_completed
1672 && REG_P (operands[1])
1673 && !paradoxical_subreg_p (operands[0])"
1675 (ashift:DI (match_dup 1) (const_int 32)))
1677 (lshiftrt:DI (match_dup 0) (const_int 32)))]
1678 { operands[1] = gen_lowpart (DImode, operands[1]); }
1679 [(set_attr "move_type" "shift_shift,load")
1680 (set_attr "type" "load")
1681 (set_attr "mode" "DI")])
1683 (define_expand "zero_extendhi<GPR:mode>2"
1684 [(set (match_operand:GPR 0 "register_operand")
1686 (match_operand:HI 1 "nonimmediate_operand")))]
1689 (define_insn_and_split "*zero_extendhi<GPR:mode>2"
1690 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1692 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
1693 "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
1697 "&& reload_completed
1698 && REG_P (operands[1])
1699 && !paradoxical_subreg_p (operands[0])"
1701 (ashift:GPR (match_dup 1) (match_dup 2)))
1703 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1705 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1706 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1708 [(set_attr "move_type" "shift_shift,load")
1709 (set_attr "type" "load")
1710 (set_attr "mode" "<GPR:MODE>")])
1712 (define_expand "zero_extendqi<SUPERQI:mode>2"
1713 [(set (match_operand:SUPERQI 0 "register_operand")
1714 (zero_extend:SUPERQI
1715 (match_operand:QI 1 "nonimmediate_operand")))]
1718 (define_insn "*zero_extendqi<SUPERQI:mode>2_internal"
1719 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1720 (zero_extend:SUPERQI
1721 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
1722 "!TARGET_XTHEADMEMIDX"
1726 [(set_attr "move_type" "andi,load")
1727 (set_attr "type" "multi")
1728 (set_attr "mode" "<SUPERQI:MODE>")])
1731 ;; ....................
1735 ;; ....................
1737 (define_expand "extendsidi2"
1738 [(set (match_operand:DI 0 "register_operand" "=r,r")
1740 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1743 (define_insn "*extendsidi2_internal"
1744 [(set (match_operand:DI 0 "register_operand" "=r,r")
1746 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1747 "TARGET_64BIT && !TARGET_XTHEADMEMIDX"
1751 [(set_attr "move_type" "move,load")
1752 (set_attr "type" "multi")
1753 (set_attr "mode" "DI")])
1755 (define_expand "extend<SHORT:mode><SUPERQI:mode>2"
1756 [(set (match_operand:SUPERQI 0 "register_operand")
1757 (sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_operand")))]
1760 (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
1761 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1762 (sign_extend:SUPERQI
1763 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
1764 "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
1767 l<SHORT:size>\t%0,%1"
1768 "&& reload_completed
1769 && REG_P (operands[1])
1770 && !paradoxical_subreg_p (operands[0])"
1771 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1772 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
1774 operands[0] = gen_lowpart (SImode, operands[0]);
1775 operands[1] = gen_lowpart (SImode, operands[1]);
1776 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1777 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1779 [(set_attr "move_type" "shift_shift,load")
1780 (set_attr "type" "load")
1781 (set_attr "mode" "SI")])
1783 (define_insn "extendhfsf2"
1784 [(set (match_operand:SF 0 "register_operand" "=f")
1786 (match_operand:HF 1 "register_operand" " f")))]
1787 "TARGET_ZFHMIN || TARGET_ZHINXMIN"
1789 [(set_attr "type" "fcvt")
1790 (set_attr "mode" "SF")])
1792 (define_insn "extendsfdf2"
1793 [(set (match_operand:DF 0 "register_operand" "=f")
1795 (match_operand:SF 1 "register_operand" " f")))]
1796 "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
1798 [(set_attr "type" "fcvt")
1799 (set_attr "mode" "DF")])
1801 (define_insn "extendhfdf2"
1802 [(set (match_operand:DF 0 "register_operand" "=f")
1804 (match_operand:HF 1 "register_operand" " f")))]
1805 "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
1806 (TARGET_ZHINXMIN && TARGET_ZDINX)"
1808 [(set_attr "type" "fcvt")
1809 (set_attr "mode" "DF")])
1811 ;; 16-bit floating point moves
1812 (define_expand "movhf"
1813 [(set (match_operand:HF 0 "")
1814 (match_operand:HF 1 ""))]
1817 if (riscv_legitimize_move (HFmode, operands[0], operands[1]))
1821 (define_insn "*movhf_hardfloat"
1822 [(set (match_operand:HF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
1823 (match_operand:HF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))]
1825 && (register_operand (operands[0], HFmode)
1826 || reg_or_0_operand (operands[1], HFmode))"
1827 { return riscv_output_move (operands[0], operands[1]); }
1828 [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1829 (set_attr "type" "fmove")
1830 (set_attr "mode" "HF")])
1832 (define_insn "*movhf_softfloat"
1833 [(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
1834 (match_operand:HF 1 "move_operand" " f,Gr,m,r,*r,*f"))]
1836 && (register_operand (operands[0], HFmode)
1837 || reg_or_0_operand (operands[1], HFmode))"
1838 { return riscv_output_move (operands[0], operands[1]); }
1839 [(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
1840 (set_attr "type" "fmove")
1841 (set_attr "mode" "HF")])
1844 ;; ....................
1848 ;; ....................
1850 (define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
1851 [(set (match_operand:GPR 0 "register_operand" "=r")
1853 (match_operand:ANYF 1 "register_operand" " f")))]
1854 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1855 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
1856 [(set_attr "type" "fcvt")
1857 (set_attr "mode" "<ANYF:MODE>")])
1859 (define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2"
1860 [(set (match_operand:GPR 0 "register_operand" "=r")
1862 (match_operand:ANYF 1 "register_operand" " f")))]
1863 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1864 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
1865 [(set_attr "type" "fcvt")
1866 (set_attr "mode" "<ANYF:MODE>")])
1868 (define_insn "float<GPR:mode><ANYF:mode>2"
1869 [(set (match_operand:ANYF 0 "register_operand" "= f")
1871 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
1872 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1873 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
1874 [(set_attr "type" "fcvt")
1875 (set_attr "mode" "<ANYF:MODE>")])
1877 (define_insn "floatuns<GPR:mode><ANYF:mode>2"
1878 [(set (match_operand:ANYF 0 "register_operand" "= f")
1879 (unsigned_float:ANYF
1880 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
1881 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1882 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
1883 [(set_attr "type" "fcvt")
1884 (set_attr "mode" "<ANYF:MODE>")])
1886 (define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2"
1887 [(set (match_operand:GPR 0 "register_operand" "=r")
1889 [(match_operand:ANYF 1 "register_operand" " f")]
1891 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1892 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
1893 [(set_attr "type" "fcvt")
1894 (set_attr "mode" "<ANYF:MODE>")])
1896 (define_insn "<round_pattern><ANYF:mode>2"
1897 [(set (match_operand:ANYF 0 "register_operand" "=f")
1899 [(match_operand:ANYF 1 "register_operand" " f")]
1901 "TARGET_HARD_FLOAT && TARGET_ZFA"
1902 "fround.<ANYF:fmt>\t%0,%1,<round_rm>"
1903 [(set_attr "type" "fcvt")
1904 (set_attr "mode" "<ANYF:MODE>")])
1906 (define_insn "rint<ANYF:mode>2"
1907 [(set (match_operand:ANYF 0 "register_operand" "=f")
1909 [(match_operand:ANYF 1 "register_operand" " f")]
1911 "TARGET_HARD_FLOAT && TARGET_ZFA"
1912 "froundnx.<ANYF:fmt>\t%0,%1"
1913 [(set_attr "type" "fcvt")
1914 (set_attr "mode" "<ANYF:MODE>")])
1917 ;; ....................
1921 ;; ....................
1923 ;; Lower-level instructions for loading an address from the GOT.
1924 ;; We could use MEMs, but an unspec gives more optimization
1927 (define_insn "got_load<mode>"
1928 [(set (match_operand:P 0 "register_operand" "=r")
1930 [(match_operand:P 1 "symbolic_operand" "")]
1934 [(set_attr "got" "load")
1935 (set_attr "type" "load")
1936 (set_attr "mode" "<MODE>")])
1938 (define_insn "tls_add_tp_le<mode>"
1939 [(set (match_operand:P 0 "register_operand" "=r")
1941 [(match_operand:P 1 "register_operand" "r")
1942 (match_operand:P 2 "register_operand" "r")
1943 (match_operand:P 3 "symbolic_operand" "")]
1946 "add\t%0,%1,%2,%%tprel_add(%3)"
1947 [(set_attr "type" "arith")
1948 (set_attr "mode" "<MODE>")])
1950 (define_insn "got_load_tls_gd<mode>"
1951 [(set (match_operand:P 0 "register_operand" "=r")
1953 [(match_operand:P 1 "symbolic_operand" "")]
1957 [(set_attr "got" "load")
1958 (set_attr "type" "load")
1959 (set_attr "mode" "<MODE>")])
1961 (define_insn "got_load_tls_ie<mode>"
1962 [(set (match_operand:P 0 "register_operand" "=r")
1964 [(match_operand:P 1 "symbolic_operand" "")]
1968 [(set_attr "got" "load")
1969 (set_attr "type" "load")
1970 (set_attr "mode" "<MODE>")])
1972 (define_insn "auipc<mode>"
1973 [(set (match_operand:P 0 "register_operand" "=r")
1975 [(match_operand:P 1 "symbolic_operand" "")
1976 (match_operand:P 2 "const_int_operand")
1980 ".LA%2: auipc\t%0,%h1"
1981 [(set_attr "type" "auipc")
1982 (set_attr "cannot_copy" "yes")])
1984 ;; Instructions for adding the low 12 bits of an address to a register.
1985 ;; Operand 2 is the address: riscv_print_operand works out which relocation
1986 ;; should be applied.
1988 (define_insn "*low<mode>"
1989 [(set (match_operand:P 0 "register_operand" "=r")
1990 (lo_sum:P (match_operand:P 1 "register_operand" " r")
1991 (match_operand:P 2 "symbolic_operand" "")))]
1994 [(set_attr "type" "arith")
1995 (set_attr "mode" "<MODE>")])
1997 ;; Allow combine to split complex const_int load sequences, using operand 2
1998 ;; to store the intermediate results. See move_operand for details.
2000 [(set (match_operand:GPR 0 "register_operand")
2001 (match_operand:GPR 1 "splittable_const_int_operand"))
2002 (clobber (match_operand:GPR 2 "register_operand"))]
2006 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
2011 ;; Likewise, for symbolic operands.
2013 [(set (match_operand:P 0 "register_operand")
2014 (match_operand:P 1))
2015 (clobber (match_operand:P 2 "register_operand"))]
2016 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)"
2017 [(set (match_dup 0) (match_dup 3))]
2019 riscv_split_symbol (operands[2], operands[1],
2020 MAX_MACHINE_MODE, &operands[3]);
2023 ;; Pretend to have the ability to load complex const_int in order to get
2024 ;; better code generation around them.
2025 ;; But avoid constants that are special cased elsewhere.
2027 ;; Hide it from IRA register equiv recog* () to elide potential undoing of split
2029 (define_insn_and_split "*mvconst_internal"
2030 [(set (match_operand:GPR 0 "register_operand" "=r")
2031 (match_operand:GPR 1 "splittable_const_int_operand" "i"))]
2033 && !(p2m1_shift_operand (operands[1], <MODE>mode)
2034 || high_mask_shift_operand (operands[1], <MODE>mode))"
2039 riscv_move_integer (operands[0], operands[0], INTVAL (operands[1]),
2043 [(set_attr "type" "move")])
2045 ;; 64-bit integer moves
2047 (define_expand "movdi"
2048 [(set (match_operand:DI 0 "")
2049 (match_operand:DI 1 ""))]
2052 if (riscv_legitimize_move (DImode, operands[0], operands[1]))
2056 (define_insn "*movdi_32bit"
2057 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m,r")
2058 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f,vp"))]
2060 && (register_operand (operands[0], DImode)
2061 || reg_or_0_operand (operands[1], DImode))"
2062 { return riscv_output_move (operands[0], operands[1]); }
2063 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore,rdvlenb")
2064 (set_attr "mode" "DI")
2065 (set_attr "type" "move")
2066 (set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")])
2068 (define_insn "*movdi_64bit"
2069 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m,r")
2070 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f,vp"))]
2072 && (register_operand (operands[0], DImode)
2073 || reg_or_0_operand (operands[1], DImode))"
2074 { return riscv_output_move (operands[0], operands[1]); }
2075 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore,rdvlenb")
2076 (set_attr "mode" "DI")
2077 (set_attr "type" "move")
2078 (set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")])
2080 ;; 32-bit Integer moves
2082 (define_expand "mov<mode>"
2083 [(set (match_operand:MOVE32 0 "")
2084 (match_operand:MOVE32 1 ""))]
2087 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
2091 (define_insn "*movsi_internal"
2092 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m,r")
2093 (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,vp"))]
2094 "(register_operand (operands[0], SImode)
2095 || reg_or_0_operand (operands[1], SImode))
2096 && !(register_operand (operands[1], SImode)
2097 && reg_or_subregno (operands[1]) == VL_REGNUM)"
2098 { return riscv_output_move (operands[0], operands[1]); }
2099 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore,rdvlenb")
2100 (set_attr "mode" "SI")
2101 (set_attr "type" "move")
2102 (set_attr "ext" "base,base,base,base,f,f,f,f,vector")])
2104 ;; 16-bit Integer moves
2106 ;; Unlike most other insns, the move insns can't be split with
2107 ;; different predicates, because register spilling and other parts of
2108 ;; the compiler, have memoized the insn number already.
2109 ;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
2111 (define_expand "movhi"
2112 [(set (match_operand:HI 0 "")
2113 (match_operand:HI 1 ""))]
2116 if (riscv_legitimize_move (HImode, operands[0], operands[1]))
2120 (define_insn "*movhi_internal"
2121 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r")
2122 (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f,vp"))]
2123 "(register_operand (operands[0], HImode)
2124 || reg_or_0_operand (operands[1], HImode))"
2125 { return riscv_output_move (operands[0], operands[1]); }
2126 [(set_attr "move_type" "move,const,load,store,mtc,mfc,rdvlenb")
2127 (set_attr "mode" "HI")
2128 (set_attr "type" "move")
2129 (set_attr "ext" "base,base,base,base,f,f,vector")])
2131 ;; HImode constant generation; see riscv_move_integer for details.
2132 ;; si+si->hi without truncation is legal because of
2133 ;; TARGET_TRULY_NOOP_TRUNCATION.
2135 (define_insn "*add<mode>hi3"
2136 [(set (match_operand:HI 0 "register_operand" "=r,r")
2137 (plus:HI (match_operand:HISI 1 "register_operand" " r,r")
2138 (match_operand:HISI 2 "arith_operand" " r,I")))]
2140 "add%i2%~\t%0,%1,%2"
2141 [(set_attr "type" "arith")
2142 (set_attr "mode" "HI")])
2144 (define_insn "*xor<mode>hi3"
2145 [(set (match_operand:HI 0 "register_operand" "=r,r")
2146 (xor:HI (match_operand:HISI 1 "register_operand" " r,r")
2147 (match_operand:HISI 2 "arith_operand" " r,I")))]
2150 [(set_attr "type" "logical")
2151 (set_attr "mode" "HI")])
2153 ;; 8-bit Integer moves
2155 (define_expand "movqi"
2156 [(set (match_operand:QI 0 "")
2157 (match_operand:QI 1 ""))]
2160 if (riscv_legitimize_move (QImode, operands[0], operands[1]))
2164 (define_insn "*movqi_internal"
2165 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r")
2166 (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f,vp"))]
2167 "(register_operand (operands[0], QImode)
2168 || reg_or_0_operand (operands[1], QImode))"
2169 { return riscv_output_move (operands[0], operands[1]); }
2170 [(set_attr "move_type" "move,const,load,store,mtc,mfc,rdvlenb")
2171 (set_attr "mode" "QI")
2172 (set_attr "type" "move")
2173 (set_attr "ext" "base,base,base,base,f,f,vector")])
2175 ;; 32-bit floating point moves
2177 (define_expand "movsf"
2178 [(set (match_operand:SF 0 "")
2179 (match_operand:SF 1 ""))]
2182 if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
2186 (define_insn "*movsf_hardfloat"
2187 [(set (match_operand:SF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
2188 (match_operand:SF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))]
2190 && (register_operand (operands[0], SFmode)
2191 || reg_or_0_operand (operands[1], SFmode))"
2192 { return riscv_output_move (operands[0], operands[1]); }
2193 [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
2194 (set_attr "type" "fmove")
2195 (set_attr "mode" "SF")])
2197 (define_insn "*movsf_softfloat"
2198 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
2199 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
2201 && (register_operand (operands[0], SFmode)
2202 || reg_or_0_operand (operands[1], SFmode))"
2203 { return riscv_output_move (operands[0], operands[1]); }
2204 [(set_attr "move_type" "move,load,store")
2205 (set_attr "type" "fmove")
2206 (set_attr "mode" "SF")])
2208 ;; 64-bit floating point moves
2210 (define_expand "movdf"
2211 [(set (match_operand:DF 0 "")
2212 (match_operand:DF 1 ""))]
2215 if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
2220 ;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
2221 ;; (However, we can still use fcvt.d.w to zero a floating-point register.)
2222 (define_insn "*movdf_hardfloat_rv32"
2223 [(set (match_operand:DF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*zmvf,*zmvr, *r,*r,*m")
2224 (match_operand:DF 1 "move_operand" " f,zfli,G,m,f,G,*zmvr,*zmvf,*r*G,*m,*r"))]
2225 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
2226 && (register_operand (operands[0], DFmode)
2227 || reg_or_0_operand (operands[1], DFmode))"
2228 { return riscv_output_move (operands[0], operands[1]); }
2229 [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
2230 (set_attr "type" "fmove")
2231 (set_attr "mode" "DF")])
2233 (define_insn "*movdf_hardfloat_rv64"
2234 [(set (match_operand:DF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
2235 (match_operand:DF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*r*G,*m,*r"))]
2236 "TARGET_64BIT && TARGET_DOUBLE_FLOAT
2237 && (register_operand (operands[0], DFmode)
2238 || reg_or_0_operand (operands[1], DFmode))"
2239 { return riscv_output_move (operands[0], operands[1]); }
2240 [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
2241 (set_attr "type" "fmove")
2242 (set_attr "mode" "DF")])
2244 (define_insn "*movdf_softfloat"
2245 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
2246 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
2247 "!TARGET_DOUBLE_FLOAT
2248 && (register_operand (operands[0], DFmode)
2249 || reg_or_0_operand (operands[1], DFmode))"
2250 { return riscv_output_move (operands[0], operands[1]); }
2251 [(set_attr "move_type" "move,load,store")
2252 (set_attr "type" "fmove")
2253 (set_attr "mode" "DF")])
2255 (define_insn "movsidf2_low_rv32"
2256 [(set (match_operand:SI 0 "register_operand" "= r")
2258 (match_operand:DF 1 "register_operand" "zmvf")))]
2259 "TARGET_HARD_FLOAT && !TARGET_64BIT && TARGET_ZFA"
2261 [(set_attr "move_type" "fmove")
2262 (set_attr "type" "fmove")
2263 (set_attr "mode" "DF")])
2266 (define_insn "movsidf2_high_rv32"
2267 [(set (match_operand:SI 0 "register_operand" "= r")
2270 (match_operand:DF 1 "register_operand" "zmvf")
2272 "TARGET_HARD_FLOAT && !TARGET_64BIT && TARGET_ZFA"
2274 [(set_attr "move_type" "fmove")
2275 (set_attr "type" "fmove")
2276 (set_attr "mode" "DF")])
2278 (define_insn "movdfsisi3_rv32"
2279 [(set (match_operand:DF 0 "register_operand" "= f")
2281 (match_operand:SI 2 "register_operand" "zmvr")
2283 (match_operand:SI 1 "register_operand" "zmvr")
2285 "TARGET_HARD_FLOAT && !TARGET_64BIT && TARGET_ZFA"
2286 "fmvp.d.x\t%0,%2,%1"
2287 [(set_attr "move_type" "fmove")
2288 (set_attr "type" "fmove")
2289 (set_attr "mode" "DF")])
2292 [(set (match_operand:MOVE64 0 "nonimmediate_operand")
2293 (match_operand:MOVE64 1 "move_operand"))]
2295 && riscv_split_64bit_move_p (operands[0], operands[1])"
2298 riscv_split_doubleword_move (operands[0], operands[1]);
2302 (define_expand "cpymem<mode>"
2303 [(parallel [(set (match_operand:BLK 0 "general_operand")
2304 (match_operand:BLK 1 "general_operand"))
2305 (use (match_operand:P 2 ""))
2306 (use (match_operand:SI 3 "const_int_operand"))])]
2309 if (riscv_vector::expand_block_move (operands[0], operands[1], operands[2]))
2311 else if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
2317 ;; Expand in-line code to clear the instruction cache between operand[0] and
2319 (define_expand "clear_cache"
2320 [(match_operand 0 "pmode_register_operand")
2321 (match_operand 1 "pmode_register_operand")]
2324 #ifdef ICACHE_FLUSH_FUNC
2325 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC),
2326 LCT_NORMAL, VOIDmode, operands[0], Pmode,
2327 operands[1], Pmode, const0_rtx, Pmode);
2329 if (TARGET_ZIFENCEI)
2330 emit_insn (gen_fence_i ());
2335 (define_insn "fence"
2336 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
2339 [(set_attr "type" "atomic")])
2341 (define_insn "fence_i"
2342 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
2345 [(set_attr "type" "atomic")])
2347 (define_insn "riscv_pause"
2348 [(unspec_volatile [(const_int 0)] UNSPECV_PAUSE)]
2350 "* return TARGET_ZIHINTPAUSE ? \"pause\" : \".insn\t0x0100000f\";"
2351 [(set_attr "type" "atomic")])
2354 ;; ....................
2358 ;; ....................
2360 ;; Use a QImode shift count, to avoid generating sign or zero extend
2361 ;; instructions for shift counts, and to avoid dropping subregs.
2362 ;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
2363 ;; defined, but use of that is discouraged.
2365 (define_insn "*<optab>si3"
2366 [(set (match_operand:SI 0 "register_operand" "= r")
2368 (match_operand:SI 1 "register_operand" " r")
2369 (match_operand:QI 2 "arith_operand" " rI")))]
2372 if (GET_CODE (operands[2]) == CONST_INT)
2373 operands[2] = GEN_INT (INTVAL (operands[2])
2374 & (GET_MODE_BITSIZE (SImode) - 1));
2376 return "<insn>%i2%~\t%0,%1,%2";
2378 [(set_attr "type" "shift")
2379 (set_attr "mode" "SI")])
2381 (define_expand "<optab>si3"
2382 [(set (match_operand:SI 0 "register_operand" "= r")
2383 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
2384 (match_operand:QI 2 "arith_operand" " rI")))]
2389 rtx t = gen_reg_rtx (DImode);
2390 emit_insn (gen_<optab>si3_extend (t, operands[1], operands[2]));
2391 t = gen_lowpart (SImode, t);
2392 SUBREG_PROMOTED_VAR_P (t) = 1;
2393 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
2394 emit_move_insn (operands[0], t);
2399 (define_insn "<optab>di3"
2400 [(set (match_operand:DI 0 "register_operand" "= r")
2402 (match_operand:DI 1 "register_operand" " r")
2403 (match_operand:QI 2 "arith_operand" " rI")))]
2406 if (GET_CODE (operands[2]) == CONST_INT)
2407 operands[2] = GEN_INT (INTVAL (operands[2])
2408 & (GET_MODE_BITSIZE (DImode) - 1));
2410 return "<insn>%i2\t%0,%1,%2";
2412 [(set_attr "type" "shift")
2413 (set_attr "mode" "DI")])
2415 (define_insn_and_split "*<optab><GPR:mode>3_mask_1"
2416 [(set (match_operand:GPR 0 "register_operand" "= r")
2418 (match_operand:GPR 1 "register_operand" " r")
2419 (match_operator 4 "subreg_lowpart_operator"
2421 (match_operand:GPR2 2 "register_operand" "r")
2422 (match_operand 3 "<GPR:shiftm1>"))])))]
2427 (any_shift:GPR (match_dup 1)
2429 "operands[2] = gen_lowpart (QImode, operands[2]);"
2430 [(set_attr "type" "shift")
2431 (set_attr "mode" "<GPR:MODE>")])
2433 (define_insn "<optab>si3_extend"
2434 [(set (match_operand:DI 0 "register_operand" "= r")
2436 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
2437 (match_operand:QI 2 "arith_operand" " rI"))))]
2440 if (GET_CODE (operands[2]) == CONST_INT)
2441 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
2443 return "<insn>%i2w\t%0,%1,%2";
2445 [(set_attr "type" "shift")
2446 (set_attr "mode" "SI")])
2448 (define_insn_and_split "*<optab>si3_extend_mask"
2449 [(set (match_operand:DI 0 "register_operand" "= r")
2452 (match_operand:SI 1 "register_operand" " r")
2453 (match_operator 4 "subreg_lowpart_operator"
2455 (match_operand:GPR 2 "register_operand" " r")
2456 (match_operand 3 "const_si_mask_operand"))]))))]
2462 (any_shift:SI (match_dup 1)
2464 "operands[2] = gen_lowpart (QImode, operands[2]);"
2465 [(set_attr "type" "shift")
2466 (set_attr "mode" "SI")])
2468 ;; Non-canonical, but can be formed by ree when combine is not successful at
2469 ;; producing one of the two canonical patterns below.
2470 (define_insn "*lshrsi3_zero_extend_1"
2471 [(set (match_operand:DI 0 "register_operand" "=r")
2473 (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
2474 (match_operand 2 "const_int_operand"))))]
2475 "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
2477 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
2479 return "srliw\t%0,%1,%2";
2481 [(set_attr "type" "shift")
2482 (set_attr "mode" "SI")])
2484 ;; Canonical form for a zero-extend of a logical right shift.
2485 (define_insn "*lshrsi3_zero_extend_2"
2486 [(set (match_operand:DI 0 "register_operand" "=r")
2487 (zero_extract:DI (match_operand:DI 1 "register_operand" " r")
2488 (match_operand 2 "const_int_operand")
2489 (match_operand 3 "const_int_operand")))]
2490 "(TARGET_64BIT && (INTVAL (operands[3]) > 0)
2491 && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
2493 return "srliw\t%0,%1,%3";
2495 [(set_attr "type" "shift")
2496 (set_attr "mode" "SI")])
2498 ;; Canonical form for a zero-extend of a logical right shift when the
2499 ;; shift count is 31.
2500 (define_insn "*lshrsi3_zero_extend_3"
2501 [(set (match_operand:DI 0 "register_operand" "=r")
2502 (lt:DI (match_operand:SI 1 "register_operand" " r")
2506 return "srliw\t%0,%1,31";
2508 [(set_attr "type" "shift")
2509 (set_attr "mode" "SI")])
2511 ;; Handle AND with 2^N-1 for N from 12 to XLEN. This can be split into
2512 ;; two logical shifts. Otherwise it requires 3 instructions: lui,
2513 ;; xor/addi/srli, and.
2515 ;; Generating a temporary for the shift output gives better combiner results;
2516 ;; and also fixes a problem where op0 could be a paradoxical reg and shifting
2517 ;; by amounts larger than the size of the SUBREG_REG doesn't work.
2519 [(set (match_operand:GPR 0 "register_operand")
2520 (and:GPR (match_operand:GPR 1 "register_operand")
2521 (match_operand:GPR 2 "p2m1_shift_operand")))
2522 (clobber (match_operand:GPR 3 "register_operand"))]
2525 (ashift:GPR (match_dup 1) (match_dup 2)))
2527 (lshiftrt:GPR (match_dup 3) (match_dup 2)))]
2529 /* Op2 is a VOIDmode constant, so get the mode size from op1. */
2530 operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1])).to_constant ()
2531 - exact_log2 (INTVAL (operands[2]) + 1));
2534 ;; Handle AND with 0xF...F0...0 where there are 32 to 63 zeros. This can be
2535 ;; split into two shifts. Otherwise it requires 3 instructions: li, sll, and.
2537 [(set (match_operand:DI 0 "register_operand")
2538 (and:DI (match_operand:DI 1 "register_operand")
2539 (match_operand:DI 2 "high_mask_shift_operand")))
2540 (clobber (match_operand:DI 3 "register_operand"))]
2543 (lshiftrt:DI (match_dup 1) (match_dup 2)))
2545 (ashift:DI (match_dup 3) (match_dup 2)))]
2547 operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2])));
2550 ;; Handle SImode to DImode zero-extend combined with a left shift. This can
2551 ;; occur when unsigned int is used for array indexing. Split this into two
2552 ;; shifts. Otherwise we can get 3 shifts.
2554 (define_insn_and_split "zero_extendsidi2_shifted"
2555 [(set (match_operand:DI 0 "register_operand" "=r")
2556 (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
2557 (match_operand:QI 2 "immediate_operand" "I"))
2558 (match_operand 3 "immediate_operand" "")))
2559 (clobber (match_scratch:DI 4 "=&r"))]
2560 "TARGET_64BIT && !TARGET_ZBA
2561 && ((INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff)"
2563 "&& reload_completed"
2565 (ashift:DI (match_dup 1) (const_int 32)))
2567 (lshiftrt:DI (match_dup 4) (match_dup 5)))]
2568 "operands[5] = GEN_INT (32 - (INTVAL (operands [2])));"
2569 [(set_attr "type" "shift")
2570 (set_attr "mode" "DI")])
2573 ;; ....................
2575 ;; CONDITIONAL BRANCHES
2577 ;; ....................
2579 ;; Conditional branches
2581 (define_insn_and_split "*branch<ANYI:mode>_shiftedarith_equals_zero"
2583 (if_then_else (match_operator 1 "equality_operator"
2584 [(and:ANYI (match_operand:ANYI 2 "register_operand" "r")
2585 (match_operand 3 "shifted_const_arith_operand" "i"))
2587 (label_ref (match_operand 0 "" ""))
2589 (clobber (match_scratch:X 4 "=&r"))]
2590 "!SMALL_OPERAND (INTVAL (operands[3]))"
2592 "&& reload_completed"
2593 [(set (match_dup 4) (lshiftrt:X (subreg:X (match_dup 2) 0) (match_dup 6)))
2594 (set (match_dup 4) (and:X (match_dup 4) (match_dup 7)))
2595 (set (pc) (if_then_else (match_op_dup 1 [(match_dup 4) (const_int 0)])
2596 (label_ref (match_dup 0)) (pc)))]
2598 HOST_WIDE_INT mask = INTVAL (operands[3]);
2599 int trailing = ctz_hwi (mask);
2601 operands[6] = GEN_INT (trailing);
2602 operands[7] = GEN_INT (mask >> trailing);
2604 [(set_attr "type" "branch")])
2606 (define_insn_and_split "*branch<ANYI:mode>_shiftedmask_equals_zero"
2608 (if_then_else (match_operator 1 "equality_operator"
2609 [(and:ANYI (match_operand:ANYI 2 "register_operand" "r")
2610 (match_operand 3 "consecutive_bits_operand" "i"))
2612 (label_ref (match_operand 0 "" ""))
2614 (clobber (match_scratch:X 4 "=&r"))]
2615 "(INTVAL (operands[3]) >= 0 || !partial_subreg_p (operands[2]))
2616 && popcount_hwi (INTVAL (operands[3])) > 1
2617 && !SMALL_OPERAND (INTVAL (operands[3]))"
2619 "&& reload_completed"
2620 [(set (match_dup 4) (ashift:X (subreg:X (match_dup 2) 0) (match_dup 6)))
2621 (set (match_dup 4) (lshiftrt:X (match_dup 4) (match_dup 7)))
2622 (set (pc) (if_then_else (match_op_dup 1 [(match_dup 4) (const_int 0)])
2623 (label_ref (match_dup 0)) (pc)))]
2625 unsigned HOST_WIDE_INT mask = INTVAL (operands[3]);
2626 int leading = clz_hwi (mask);
2627 int trailing = ctz_hwi (mask);
2629 operands[6] = GEN_INT (leading);
2630 operands[7] = GEN_INT (leading + trailing);
2632 [(set_attr "type" "branch")])
2634 (define_insn "*branch<mode>"
2637 (match_operator 1 "order_operator"
2638 [(match_operand:X 2 "register_operand" "r")
2639 (match_operand:X 3 "reg_or_0_operand" "rJ")])
2640 (label_ref (match_operand 0 "" ""))
2644 if (get_attr_length (insn) == 12)
2645 return "b%N1\t%2,%z3,1f; jump\t%l0,ra; 1:";
2647 return "b%C1\t%2,%z3,%l0";
2649 [(set_attr "type" "branch")
2650 (set_attr "mode" "none")])
2652 ;; Patterns for implementations that optimize short forward branches.
2654 (define_expand "mov<mode>cc"
2655 [(set (match_operand:GPR 0 "register_operand")
2656 (if_then_else:GPR (match_operand 1 "comparison_operator")
2657 (match_operand:GPR 2 "sfb_alu_operand")
2658 (match_operand:GPR 3 "sfb_alu_operand")))]
2659 "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND_LIKE"
2661 if (riscv_expand_conditional_move (operands[0], operands[1],
2662 operands[2], operands[3]))
2668 (define_insn "*mov<GPR:mode><X:mode>cc"
2669 [(set (match_operand:GPR 0 "register_operand" "=r,r")
2671 (match_operator 5 "order_operator"
2672 [(match_operand:X 1 "register_operand" "r,r")
2673 (match_operand:X 2 "reg_or_0_operand" "rJ,rJ")])
2674 (match_operand:GPR 3 "register_operand" "0,0")
2675 (match_operand:GPR 4 "sfb_alu_operand" "rJ,IL")))]
2678 b%C5\t%1,%z2,1f\t# movcc\;mv\t%0,%z4\n1:
2679 b%C5\t%1,%z2,1f\t# movcc\;li\t%0,%4\n1:"
2680 [(set_attr "length" "8")
2681 (set_attr "type" "sfb_alu")
2682 (set_attr "mode" "<GPR:MODE>")])
2684 ;; Used to implement built-in functions.
2685 (define_expand "condjump"
2687 (if_then_else (match_operand 0)
2688 (label_ref (match_operand 1))
2691 (define_expand "@cbranch<mode>4"
2693 (if_then_else (match_operator 0 "comparison_operator"
2694 [(match_operand:BR 1 "register_operand")
2695 (match_operand:BR 2 "nonmemory_operand")])
2696 (label_ref (match_operand 3 ""))
2700 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2701 operands[1], operands[2]);
2705 (define_expand "@cbranch<mode>4"
2707 (if_then_else (match_operator 0 "fp_branch_comparison"
2708 [(match_operand:ANYF 1 "register_operand")
2709 (match_operand:ANYF 2 "register_operand")])
2710 (label_ref (match_operand 3 ""))
2712 "TARGET_HARD_FLOAT || TARGET_ZFINX"
2714 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2715 operands[1], operands[2]);
2719 (define_insn_and_split "*branch_on_bit<X:mode>"
2722 (match_operator 0 "equality_operator"
2723 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2725 (match_operand 3 "branch_on_bit_operand"))
2727 (label_ref (match_operand 1))
2729 (clobber (match_scratch:X 4 "=&r"))]
2734 (ashift:X (match_dup 2) (match_dup 3)))
2737 (match_op_dup 0 [(match_dup 4) (const_int 0)])
2738 (label_ref (match_operand 1))
2741 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
2742 operands[3] = GEN_INT (shift);
2744 if (GET_CODE (operands[0]) == EQ)
2745 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
2747 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
2749 [(set_attr "type" "branch")])
2751 (define_insn_and_split "*branch_on_bit_range<X:mode>"
2754 (match_operator 0 "equality_operator"
2755 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2756 (match_operand 3 "branch_on_bit_operand")
2759 (label_ref (match_operand 1))
2761 (clobber (match_scratch:X 4 "=&r"))]
2766 (ashift:X (match_dup 2) (match_dup 3)))
2769 (match_op_dup 0 [(match_dup 4) (const_int 0)])
2770 (label_ref (match_operand 1))
2773 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
2775 [(set_attr "type" "branch")])
2778 ;; ....................
2780 ;; SETTING A REGISTER FROM A COMPARISON
2782 ;; ....................
2784 ;; Destination is always set in SI mode.
2786 (define_expand "cstore<mode>4"
2787 [(set (match_operand:SI 0 "register_operand")
2788 (match_operator:SI 1 "order_operator"
2789 [(match_operand:GPR 2 "register_operand")
2790 (match_operand:GPR 3 "nonmemory_operand")]))]
2793 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
2798 (define_expand "cstore<mode>4"
2799 [(set (match_operand:SI 0 "register_operand")
2800 (match_operator:SI 1 "fp_scc_comparison"
2801 [(match_operand:ANYF 2 "register_operand")
2802 (match_operand:ANYF 3 "register_operand")]))]
2803 "TARGET_HARD_FLOAT || TARGET_ZFINX"
2805 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
2810 (define_insn "*cstore<ANYF:mode><X:mode>4"
2811 [(set (match_operand:X 0 "register_operand" "=r")
2812 (match_operator:X 1 "fp_native_comparison"
2813 [(match_operand:ANYF 2 "register_operand" " f")
2814 (match_operand:ANYF 3 "register_operand" " f")]))]
2815 "TARGET_HARD_FLOAT || TARGET_ZFINX"
2816 "f%C1.<fmt>\t%0,%2,%3"
2817 [(set_attr "type" "fcmp")
2818 (set_attr "mode" "<UNITMODE>")])
2820 (define_expand "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
2821 [(set (match_operand:X 0 "register_operand")
2822 (unspec:X [(match_operand:ANYF 1 "register_operand")
2823 (match_operand:ANYF 2 "register_operand")]
2825 "TARGET_HARD_FLOAT || TARGET_ZFINX"
2827 rtx op0 = operands[0];
2828 rtx op1 = operands[1];
2829 rtx op2 = operands[2];
2832 emit_insn (gen_f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_zfa(op0, op1, op2));
2835 rtx tmp = gen_reg_rtx (SImode);
2836 rtx cmp = gen_rtx_<QUIET_PATTERN> (<X:MODE>mode, op1, op2);
2837 rtx frflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, const0_rtx),
2839 rtx fsflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, tmp),
2842 emit_insn (gen_rtx_SET (tmp, frflags));
2843 emit_insn (gen_rtx_SET (op0, cmp));
2844 emit_insn (fsflags);
2847 if (HONOR_SNANS (<ANYF:MODE>mode))
2848 emit_insn (gen_rtx_UNSPEC_VOLATILE (<ANYF:MODE>mode,
2849 gen_rtvec (2, op1, op2),
2854 (define_insn "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_zfa"
2855 [(set (match_operand:X 0 "register_operand" "=r")
2857 [(match_operand:ANYF 1 "register_operand" " f")
2858 (match_operand:ANYF 2 "register_operand" " f")]
2860 "TARGET_HARD_FLOAT && TARGET_ZFA"
2861 "f<quiet_pattern>q.<fmt>\t%0,%1,%2"
2862 [(set_attr "type" "fcmp")
2863 (set_attr "mode" "<UNITMODE>")
2864 (set (attr "length") (const_int 16))])
2866 (define_insn "*seq_zero_<X:mode><GPR:mode>"
2867 [(set (match_operand:GPR 0 "register_operand" "=r")
2868 (eq:GPR (match_operand:X 1 "register_operand" " r")
2872 [(set_attr "type" "slt")
2873 (set_attr "mode" "<X:MODE>")])
2875 (define_insn "*sne_zero_<X:mode><GPR:mode>"
2876 [(set (match_operand:GPR 0 "register_operand" "=r")
2877 (ne:GPR (match_operand:X 1 "register_operand" " r")
2881 [(set_attr "type" "slt")
2882 (set_attr "mode" "<X:MODE>")])
2884 (define_insn "*sgt<u>_<X:mode><GPR:mode>"
2885 [(set (match_operand:GPR 0 "register_operand" "= r")
2886 (any_gt:GPR (match_operand:X 1 "register_operand" " r")
2887 (match_operand:X 2 "reg_or_0_operand" " rJ")))]
2890 [(set_attr "type" "slt")
2891 (set_attr "mode" "<X:MODE>")])
2893 (define_insn "*sge<u>_<X:mode><GPR:mode>"
2894 [(set (match_operand:GPR 0 "register_operand" "=r")
2895 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
2898 "slt%i2<u>\t%0,zero,%1"
2899 [(set_attr "type" "slt")
2900 (set_attr "mode" "<X:MODE>")])
2902 (define_insn "@slt<u>_<X:mode><GPR:mode>3"
2903 [(set (match_operand:GPR 0 "register_operand" "= r")
2904 (any_lt:GPR (match_operand:X 1 "register_operand" " r")
2905 (match_operand:X 2 "arith_operand" " rI")))]
2907 "slt%i2<u>\t%0,%1,%2"
2908 [(set_attr "type" "slt")
2909 (set_attr "mode" "<X:MODE>")])
2911 (define_insn "*sle<u>_<X:mode><GPR:mode>"
2912 [(set (match_operand:GPR 0 "register_operand" "=r")
2913 (any_le:GPR (match_operand:X 1 "register_operand" " r")
2914 (match_operand:X 2 "sle_operand" "")))]
2917 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
2918 return "slt%i2<u>\t%0,%1,%2";
2920 [(set_attr "type" "slt")
2921 (set_attr "mode" "<X:MODE>")])
2924 ;; ....................
2926 ;; UNCONDITIONAL BRANCHES
2928 ;; ....................
2930 ;; Unconditional branches.
2933 [(set (pc) (label_ref (match_operand 0 "" "")))]
2936 /* Hopefully this does not happen often as this is going
2937 to clobber $ra and muck up the return stack predictors. */
2938 if (get_attr_length (insn) == 8)
2939 return "jump\t%l0,ra";
2943 [(set_attr "type" "jump")
2944 (set_attr "mode" "none")])
2946 (define_expand "indirect_jump"
2947 [(set (pc) (match_operand 0 "register_operand"))]
2950 operands[0] = force_reg (Pmode, operands[0]);
2951 if (Pmode == SImode)
2952 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
2954 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
2958 (define_insn "indirect_jump<mode>"
2959 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
2962 [(set_attr "type" "jalr")
2963 (set_attr "mode" "none")])
2965 (define_expand "tablejump"
2966 [(set (pc) (match_operand 0 "register_operand" ""))
2967 (use (label_ref (match_operand 1 "" "")))]
2970 if (CASE_VECTOR_PC_RELATIVE)
2971 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
2972 gen_rtx_LABEL_REF (Pmode, operands[1]),
2973 NULL_RTX, 0, OPTAB_DIRECT);
2975 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
2976 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
2978 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
2982 (define_insn "tablejump<mode>"
2983 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
2984 (use (label_ref (match_operand 1 "" "")))]
2987 [(set_attr "type" "jalr")
2988 (set_attr "mode" "none")])
2991 ;; ....................
2993 ;; Function prologue/epilogue
2995 ;; ....................
2998 (define_expand "prologue"
3002 riscv_expand_prologue ();
3006 ;; Block any insns from being moved before this point, since the
3007 ;; profiling call to mcount can use various registers that aren't
3008 ;; saved or used to pass arguments.
3010 (define_insn "blockage"
3011 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
3014 [(set_attr "type" "ghost")
3015 (set_attr "mode" "none")])
3017 (define_expand "epilogue"
3021 riscv_expand_epilogue (NORMAL_RETURN);
3025 (define_expand "sibcall_epilogue"
3029 riscv_expand_epilogue (SIBCALL_RETURN);
3033 ;; Trivial return. Make it look like a normal return insn as that
3034 ;; allows jump optimizations to work better.
3036 (define_expand "return"
3038 "riscv_can_use_return_insn ()"
3041 (define_insn "simple_return"
3045 return riscv_output_return ();
3047 [(set_attr "type" "jalr")
3048 (set_attr "mode" "none")])
3052 (define_insn "simple_return_internal"
3054 (use (match_operand 0 "pmode_register_operand" ""))]
3057 [(set_attr "type" "jalr")
3058 (set_attr "mode" "none")])
3060 ;; This is used in compiling the unwind routines.
3061 (define_expand "eh_return"
3062 [(use (match_operand 0 "general_operand"))]
3065 if (GET_MODE (operands[0]) != word_mode)
3066 operands[0] = convert_to_mode (word_mode, operands[0], 0);
3068 emit_insn (gen_eh_set_lr_di (operands[0]));
3070 emit_insn (gen_eh_set_lr_si (operands[0]));
3072 emit_jump_insn (gen_eh_return_internal ());
3077 ;; Clobber the return address on the stack. We can't expand this
3078 ;; until we know where it will be put in the stack frame.
3080 (define_insn "eh_set_lr_si"
3081 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
3082 (clobber (match_scratch:SI 1 "=&r"))]
3085 [(set_attr "type" "jump")])
3087 (define_insn "eh_set_lr_di"
3088 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
3089 (clobber (match_scratch:DI 1 "=&r"))]
3092 [(set_attr "type" "jump")])
3095 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
3096 (clobber (match_scratch 1))]
3100 riscv_set_return_address (operands[0], operands[1]);
3104 (define_insn_and_split "eh_return_internal"
3108 "epilogue_completed"
3110 "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;"
3111 [(set_attr "type" "ret")])
3114 ;; ....................
3118 ;; ....................
3120 (define_expand "sibcall"
3121 [(parallel [(call (match_operand 0 "")
3122 (match_operand 1 ""))
3124 (match_operand 2 "const_int_operand")
3125 ] UNSPEC_CALLEE_CC))])]
3128 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
3129 emit_call_insn (gen_sibcall_internal (target, operands[1], operands[2]));
3133 (define_insn "sibcall_internal"
3134 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
3135 (match_operand 1 "" ""))
3137 (match_operand 2 "const_int_operand")
3138 ] UNSPEC_CALLEE_CC))]
3139 "SIBLING_CALL_P (insn)"
3144 [(set_attr "type" "call")])
3146 (define_expand "sibcall_value"
3147 [(parallel [(set (match_operand 0 "")
3148 (call (match_operand 1 "")
3149 (match_operand 2 "")))
3151 (match_operand 3 "const_int_operand")
3152 ] UNSPEC_CALLEE_CC))])]
3155 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
3156 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2],
3161 (define_insn "sibcall_value_internal"
3162 [(set (match_operand 0 "" "")
3163 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
3164 (match_operand 2 "" "")))
3166 (match_operand 3 "const_int_operand")
3167 ] UNSPEC_CALLEE_CC))]
3168 "SIBLING_CALL_P (insn)"
3173 [(set_attr "type" "call")])
3175 (define_expand "call"
3176 [(parallel [(call (match_operand 0 "")
3177 (match_operand 1 ""))
3179 (match_operand 2 "const_int_operand")
3180 ] UNSPEC_CALLEE_CC))])]
3183 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
3184 emit_call_insn (gen_call_internal (target, operands[1], operands[2]));
3188 (define_insn "call_internal"
3189 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
3190 (match_operand 1 "" ""))
3192 (match_operand 2 "const_int_operand")
3193 ] UNSPEC_CALLEE_CC))
3194 (clobber (reg:SI RETURN_ADDR_REGNUM))]
3200 [(set_attr "type" "call")])
3202 (define_expand "call_value"
3203 [(parallel [(set (match_operand 0 "")
3204 (call (match_operand 1 "")
3205 (match_operand 2 "")))
3207 (match_operand 3 "const_int_operand")
3208 ] UNSPEC_CALLEE_CC))])]
3211 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
3212 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2],
3217 (define_insn "call_value_internal"
3218 [(set (match_operand 0 "" "")
3219 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
3220 (match_operand 2 "" "")))
3222 (match_operand 3 "const_int_operand")
3223 ] UNSPEC_CALLEE_CC))
3224 (clobber (reg:SI RETURN_ADDR_REGNUM))]
3230 [(set_attr "type" "call")])
3232 ;; Call subroutine returning any type.
3234 (define_expand "untyped_call"
3235 [(parallel [(call (match_operand 0 "")
3237 (match_operand 1 "")
3238 (match_operand 2 "")])]
3243 /* Untyped calls always use the RISCV_CC_BASE calling convention. */
3244 emit_call_insn (gen_call (operands[0], const0_rtx,
3245 gen_int_mode (RISCV_CC_BASE, SImode)));
3247 for (i = 0; i < XVECLEN (operands[2], 0); i++)
3249 rtx set = XVECEXP (operands[2], 0, i);
3250 riscv_emit_move (SET_DEST (set), SET_SRC (set));
3253 emit_insn (gen_blockage ());
3261 [(set_attr "type" "nop")
3262 (set_attr "mode" "none")])
3265 [(trap_if (const_int 1) (const_int 0))]
3268 [(set_attr "type" "trap")])
3270 ;; Must use the registers that we save to prevent the rename reg optimization
3271 ;; pass from using them before the gpr_save pattern when shrink wrapping
3272 ;; occurs. See bug 95252 for instance.
3274 (define_insn "gpr_save"
3275 [(match_parallel 1 "gpr_save_operation"
3276 [(unspec_volatile [(match_operand 0 "const_int_operand")]
3277 UNSPECV_GPR_SAVE)])]
3279 "call\tt0,__riscv_save_%0"
3280 [(set_attr "type" "call")])
3282 (define_insn "gpr_restore"
3283 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
3285 "tail\t__riscv_restore_%0"
3286 [(set_attr "type" "call")])
3288 (define_insn "gpr_restore_return"
3290 (use (match_operand 0 "pmode_register_operand" ""))
3294 [(set_attr "type" "ret")])
3296 (define_insn "riscv_frcsr"
3297 [(set (match_operand:SI 0 "register_operand" "=r")
3298 (unspec_volatile [(const_int 0)] UNSPECV_FRCSR))]
3299 "TARGET_HARD_FLOAT || TARGET_ZFINX"
3301 [(set_attr "type" "fmove")])
3303 (define_insn "riscv_fscsr"
3304 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_FSCSR)]
3305 "TARGET_HARD_FLOAT || TARGET_ZFINX"
3307 [(set_attr "type" "fmove")])
3309 (define_insn "riscv_frflags"
3310 [(set (match_operand:SI 0 "register_operand" "=r")
3311 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
3312 "TARGET_HARD_FLOAT || TARGET_ZFINX"
3314 [(set_attr "type" "fmove")])
3316 (define_insn "riscv_fsflags"
3317 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
3318 "TARGET_HARD_FLOAT || TARGET_ZFINX"
3320 [(set_attr "type" "fmove")])
3322 (define_insn "*riscv_fsnvsnan<mode>2"
3323 [(unspec_volatile [(match_operand:ANYF 0 "register_operand" "f")
3324 (match_operand:ANYF 1 "register_operand" "f")]
3326 "TARGET_HARD_FLOAT || TARGET_ZFINX"
3327 "feq.<fmt>\tzero,%0,%1"
3328 [(set_attr "type" "fcmp")
3329 (set_attr "mode" "<UNITMODE>")])
3331 (define_insn "riscv_mret"
3333 (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
3336 [(set_attr "type" "ret")])
3338 (define_insn "riscv_sret"
3340 (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
3343 [(set_attr "type" "ret")])
3345 (define_insn "riscv_uret"
3347 (unspec_volatile [(const_int 0)] UNSPECV_URET)]
3350 [(set_attr "type" "ret")])
3352 (define_insn "stack_tie<mode>"
3353 [(set (mem:BLK (scratch))
3354 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
3355 (match_operand:X 1 "register_operand" "r")]
3359 [(set_attr "type" "ghost")
3360 (set_attr "length" "0")]
3363 ;; This fixes a failure with gcc.c-torture/execute/pr64242.c at -O2 for a
3364 ;; 32-bit target when using -mtune=sifive-7-series. The first sched pass
3365 ;; runs before register elimination, and we have a non-obvious dependency
3366 ;; between a use of the soft fp and a set of the hard fp. We fix this by
3367 ;; emitting a clobber using the hard fp between the two insns.
3368 (define_expand "restore_stack_nonlocal"
3369 [(match_operand 0 "register_operand")
3370 (match_operand 1 "memory_operand")]
3373 emit_move_insn (operands[0], operands[1]);
3374 /* Prevent the following hard fp restore from being moved before the move
3375 insn above which uses a copy of the soft fp reg. */
3376 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
3380 ;; Named pattern for expanding thread pointer reference.
3381 (define_expand "get_thread_pointer<mode>"
3382 [(set (match_operand:P 0 "register_operand" "=r")
3387 ;; Named patterns for stack smashing protection.
3389 (define_expand "stack_protect_set"
3390 [(match_operand 0 "memory_operand")
3391 (match_operand 1 "memory_operand")]
3394 machine_mode mode = GET_MODE (operands[0]);
3395 if (riscv_stack_protector_guard == SSP_TLS)
3397 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
3398 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
3399 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
3400 operands[1] = gen_rtx_MEM (Pmode, addr);
3403 emit_insn ((mode == DImode
3404 ? gen_stack_protect_set_di
3405 : gen_stack_protect_set_si) (operands[0], operands[1]));
3409 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
3410 ;; canary value does not live beyond the life of this sequence.
3411 (define_insn "stack_protect_set_<mode>"
3412 [(set (match_operand:GPR 0 "memory_operand" "=m")
3413 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")]
3415 (set (match_scratch:GPR 2 "=&r") (const_int 0))]
3417 "<load>\t%2, %1\;<store>\t%2, %0\;li\t%2, 0"
3418 [(set_attr "type" "multi")
3419 (set_attr "length" "12")])
3421 (define_expand "stack_protect_test"
3422 [(match_operand 0 "memory_operand")
3423 (match_operand 1 "memory_operand")
3428 machine_mode mode = GET_MODE (operands[0]);
3430 result = gen_reg_rtx(mode);
3431 if (riscv_stack_protector_guard == SSP_TLS)
3433 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
3434 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
3435 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
3436 operands[1] = gen_rtx_MEM (Pmode, addr);
3438 emit_insn ((mode == DImode
3439 ? gen_stack_protect_test_di
3440 : gen_stack_protect_test_si) (result,
3444 rtx cond = gen_rtx_EQ (VOIDmode, result, const0_rtx);
3445 emit_jump_insn (gen_cbranch4 (mode, cond, result, const0_rtx, operands[2]));
3450 (define_insn "stack_protect_test_<mode>"
3451 [(set (match_operand:GPR 0 "register_operand" "=r")
3452 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")
3453 (match_operand:GPR 2 "memory_operand" "m")]
3455 (clobber (match_scratch:GPR 3 "=&r"))]
3457 "<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
3458 [(set_attr "type" "multi")
3459 (set_attr "length" "12")])
3461 (define_insn "riscv_clean_<mode>"
3462 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3466 [(set_attr "type" "cbo")]
3469 (define_insn "riscv_flush_<mode>"
3470 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3474 [(set_attr "type" "cbo")]
3477 (define_insn "riscv_inval_<mode>"
3478 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3482 [(set_attr "type" "cbo")]
3485 (define_insn "riscv_zero_<mode>"
3486 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3490 [(set_attr "type" "cbo")]
3493 (define_insn "prefetch"
3494 [(prefetch (match_operand 0 "address_operand" "r")
3495 (match_operand 1 "imm5_operand" "i")
3496 (match_operand 2 "const_int_operand" "n"))]
3499 switch (INTVAL (operands[1]))
3501 case 0: return "prefetch.r\t%a0";
3502 case 1: return "prefetch.w\t%a0";
3503 default: gcc_unreachable ();
3506 [(set_attr "type" "cbo")])
3508 (define_insn "riscv_prefetchi_<mode>"
3509 [(unspec_volatile:X [(match_operand:X 0 "address_operand" "r")
3510 (match_operand:X 1 "imm5_operand" "i")]
3514 [(set_attr "type" "cbo")])
3516 (define_expand "extv<mode>"
3517 [(set (match_operand:GPR 0 "register_operand" "=r")
3518 (sign_extract:GPR (match_operand:GPR 1 "register_operand" "r")
3519 (match_operand 2 "const_int_operand")
3520 (match_operand 3 "const_int_operand")))]
3524 (define_expand "extzv<mode>"
3525 [(set (match_operand:GPR 0 "register_operand" "=r")
3526 (zero_extract:GPR (match_operand:GPR 1 "register_operand" "r")
3527 (match_operand 2 "const_int_operand")
3528 (match_operand 3 "const_int_operand")))]
3532 && (INTVAL (operands[2]) < 8) && (INTVAL (operands[3]) == 0))
3536 (define_expand "maddhisi4"
3537 [(set (match_operand:SI 0 "register_operand")
3539 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand"))
3540 (sign_extend:SI (match_operand:HI 2 "register_operand")))
3541 (match_operand:SI 3 "register_operand")))]
3545 (define_expand "msubhisi4"
3546 [(set (match_operand:SI 0 "register_operand")
3548 (match_operand:SI 3 "register_operand")
3549 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand"))
3550 (sign_extend:SI (match_operand:HI 2 "register_operand")))))]
3554 ;; String compare with length insn.
3555 ;; Argument 0 is the target (result)
3556 ;; Argument 1 is the source1
3557 ;; Argument 2 is the source2
3558 ;; Argument 3 is the length
3559 ;; Argument 4 is the alignment
3561 (define_expand "cmpstrnsi"
3562 [(parallel [(set (match_operand:SI 0)
3563 (compare:SI (match_operand:BLK 1)
3564 (match_operand:BLK 2)))
3565 (use (match_operand:SI 3))
3566 (use (match_operand:SI 4))])]
3567 "riscv_inline_strncmp && !optimize_size && (TARGET_ZBB || TARGET_XTHEADBB)"
3569 if (riscv_expand_strcmp (operands[0], operands[1], operands[2],
3570 operands[3], operands[4]))
3576 ;; String compare insn.
3577 ;; Argument 0 is the target (result)
3578 ;; Argument 1 is the source1
3579 ;; Argument 2 is the source2
3580 ;; Argument 3 is the alignment
3582 (define_expand "cmpstrsi"
3583 [(parallel [(set (match_operand:SI 0)
3584 (compare:SI (match_operand:BLK 1)
3585 (match_operand:BLK 2)))
3586 (use (match_operand:SI 3))])]
3587 "riscv_inline_strcmp && !optimize_size && (TARGET_ZBB || TARGET_XTHEADBB)"
3589 if (riscv_expand_strcmp (operands[0], operands[1], operands[2],
3590 NULL_RTX, operands[3]))
3596 ;; Search character in string (generalization of strlen).
3597 ;; Argument 0 is the resulting offset
3598 ;; Argument 1 is the string
3599 ;; Argument 2 is the search character
3600 ;; Argument 3 is the alignment
3602 (define_expand "strlen<mode>"
3603 [(set (match_operand:X 0 "register_operand")
3604 (unspec:X [(match_operand:BLK 1 "general_operand")
3605 (match_operand:SI 2 "const_int_operand")
3606 (match_operand:SI 3 "const_int_operand")]
3608 "riscv_inline_strlen && !optimize_size && (TARGET_ZBB || TARGET_XTHEADBB)"
3610 rtx search_char = operands[2];
3612 if (search_char != const0_rtx)
3615 if (riscv_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
3621 (include "bitmanip.md")
3622 (include "crypto.md")
3624 (include "sync-rvwmo.md")
3625 (include "sync-ztso.md")
3626 (include "peephole.md")
3628 (include "generic.md")
3629 (include "sifive-7.md")
3630 (include "thead.md")
3631 (include "generic-ooo.md")
3632 (include "vector.md")
3633 (include "zicond.md")
3635 (include "corev.md")