riscv: thead: Add support for the XTheadMemIdx ISA extension
[official-gcc.git] / gcc / config / riscv / riscv.md
blobae2217d0907f07cd674048b854abc8a6d5a0ff87
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)
11 ;; any later version.
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.
39   UNSPEC_EH_RETURN
41   ;; Symbolic accesses.  The order of this list must match that of
42   ;; enum riscv_symbol_type in riscv-protos.h.
43   UNSPEC_ADDRESS_FIRST
44   UNSPEC_PCREL
45   UNSPEC_LOAD_GOT
46   UNSPEC_TLS
47   UNSPEC_TLS_LE
48   UNSPEC_TLS_IE
49   UNSPEC_TLS_GD
51   ;; High part of PC-relative address.
52   UNSPEC_AUIPC
54   ;; Floating-point unspecs.
55   UNSPEC_FLT_QUIET
56   UNSPEC_FLE_QUIET
57   UNSPEC_COPYSIGN
58   UNSPEC_RINT
59   UNSPEC_ROUND
60   UNSPEC_FLOOR
61   UNSPEC_CEIL
62   UNSPEC_BTRUNC
63   UNSPEC_ROUNDEVEN
64   UNSPEC_NEARBYINT
65   UNSPEC_LRINT
66   UNSPEC_LROUND
67   UNSPEC_FMIN
68   UNSPEC_FMAX
69   UNSPEC_FMINM
70   UNSPEC_FMAXM
72   ;; Stack tie
73   UNSPEC_TIE
75   ;; OR-COMBINE
76   UNSPEC_ORC_B
78   ;; Zbc unspecs
79   UNSPEC_CLMUL
80   UNSPEC_CLMULH
81   UNSPEC_CLMULR
83   ;; the calling convention of callee
84   UNSPEC_CALLEE_CC
86   ;; String unspecs
87   UNSPEC_STRLEN
90 (define_c_enum "unspecv" [
91   ;; Register save and restore.
92   UNSPECV_GPR_SAVE
93   UNSPECV_GPR_RESTORE
95   ;; Floating-point unspecs.
96   UNSPECV_FRCSR
97   UNSPECV_FSCSR
98   UNSPECV_FRFLAGS
99   UNSPECV_FSFLAGS
100   UNSPECV_FSNVSNAN
102   ;; Interrupt handler instructions.
103   UNSPECV_MRET
104   UNSPECV_SRET
105   UNSPECV_URET
107   ;; Blockage and synchronization.
108   UNSPECV_BLOCKAGE
109   UNSPECV_FENCE
110   UNSPECV_FENCE_I
112   ;; Stack Smash Protector
113   UNSPEC_SSP_SET
114   UNSPEC_SSP_TEST
116   ;; CMO instructions.
117   UNSPECV_CLEAN
118   UNSPECV_FLUSH
119   UNSPECV_INVAL
120   UNSPECV_ZERO
121   UNSPECV_PREI
123   ;; Zihintpause unspec
124   UNSPECV_PAUSE
126   ;; XTheadFmv unspec
127   UNSPEC_XTHEADFMV
128   UNSPEC_XTHEADFMV_HW
131 (define_constants
132   [(RETURN_ADDR_REGNUM          1)
133    (SP_REGNUM                   2)
134    (GP_REGNUM                   3)
135    (TP_REGNUM                   4)
136    (T0_REGNUM                   5)
137    (T1_REGNUM                   6)
138    (S0_REGNUM                   8)
139    (S1_REGNUM                   9)
140    (A0_REGNUM                   10)
141    (A1_REGNUM                   11)
142    (S2_REGNUM                   18)
143    (S3_REGNUM                   19)
144    (S4_REGNUM                   20)
145    (S5_REGNUM                   21)
146    (S6_REGNUM                   22)
147    (S7_REGNUM                   23)
148    (S8_REGNUM                   24)
149    (S9_REGNUM                   25)
150    (S10_REGNUM                  26)
151    (S11_REGNUM                  27)
153    (NORMAL_RETURN               0)
154    (SIBCALL_RETURN              1)
155    (EXCEPTION_RETURN            2)
156    (VL_REGNUM                   66)
157    (VTYPE_REGNUM                67)
158    (VXRM_REGNUM                 68)
159    (FRM_REGNUM                  69)
162 (include "predicates.md")
163 (include "constraints.md")
164 (include "iterators.md")
166 ;; ....................
168 ;;      Attributes
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,
237   RVVM2x2DF,RVVM1x2DF,
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)))
253          (const_string "yes")
255          (and (eq_attr "mode" "TI,TF")
256               (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
257          (const_string "yes")]
258         (const_string "no")))
260 ;; ISA attributes.
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")
267          (const_string "yes")
269          (and (eq_attr "ext" "f")
270               (match_test "TARGET_HARD_FLOAT"))
271          (const_string "yes")
273          (and (eq_attr "ext" "d")
274               (match_test "TARGET_DOUBLE_FLOAT"))
275          (const_string "yes")
277          (and (eq_attr "ext" "vector")
278               (match_test "TARGET_VECTOR"))
279          (const_string "yes")
280         ]
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
314 ;; nop          no operation
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
431 (define_attr "type"
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"
484   (cond [
485     (and (eq_attr "type" "vfmov,vfalu,vfmul,vfdiv,
486                           vfwalu,vfwmul,vfmuladd,vfwmuladd,
487                           vfsqrt,vfrecp,vfminmax,vfsgnj,vfcmp,
488                           vfclass,vfmerge,
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")))
494     (const_string "yes")
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")))
500     (const_string "yes")
501   ]
502   (const_string "no")))
504 ;; Attribute to control enable or disable instructions.
505 (define_attr "enabled" "no,yes"
506   (cond [
507     (eq_attr "ext_enabled" "no")
508     (const_string "no")
510     (eq_attr "fp_vector_disabled" "yes")
511     (const_string "no")
512   ]
513   (const_string "yes")))
515 ;; Length of instruction in bytes.
516 (define_attr "length" ""
517    (cond [
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)))
523           (const_int 4)
524           (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 1048568))
525                                   (le (minus (pc) (match_dup 0)) (const_int 1048572)))
526           (const_int 8)
527           (const_int 12)))
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)))
533           (const_int 4)
534           (const_int 8))
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")
547                 (const_int 8)
549           ;; Check for doubleword moves that are decomposed into two
550           ;; instructions.
551           (and (eq_attr "move_type" "mtc,mfc,move")
552                (eq_attr "dword_mode" "yes"))
553           (const_int 8)
555           ;; Doubleword CONST{,N} moves are split into two word
556           ;; CONST{,N} moves.
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
562           ;; routines.
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")
567           ] (const_int 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.
574 (define_attr "tune"
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")
586   "nothing")
589 ;;  ....................
591 ;;      ADDITION
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")))]
609   ""
610   "add%i2%~\t%0,%1,%2"
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")))]
618   ""
620   if (TARGET_64BIT)
621     {
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);
628       DONE;
629     }
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")))]
636   "TARGET_64BIT"
637   "add%i2\t%0,%1,%2"
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 "" ""))]
646   ""
648   if (TARGET_64BIT && <MODE>mode == SImode)
649     {
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));
658       else
659         t4 = operands[1];
660       if (GET_CODE (operands[2]) != CONST_INT)
661         emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
662       else
663         t5 = operands[2];
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);
668     }
669   else
670     {
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);
681     }
682   DONE;
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 "" ""))]
690   ""
692   if (TARGET_64BIT && <MODE>mode == SImode)
693     {
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));
699       else
700         t3 = operands[1];
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);
705     }
706   else
707     {
708       emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
709       riscv_expand_conditional_branch (operands[3], LTU, operands[0],
710                                        operands[1]);
711     }
713   DONE;
716 (define_insn "addsi3_extended"
717   [(set (match_operand:DI               0 "register_operand" "=r,r")
718         (sign_extend:DI
719              (plus:SI (match_operand:SI 1 "register_operand" " r,r")
720                       (match_operand:SI 2 "arith_operand"    " r,I"))))]
721   "TARGET_64BIT"
722   "add%i2w\t%0,%1,%2"
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")
728         (sign_extend:DI
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"))])))]
732   "TARGET_64BIT"
733   "add%i2w\t%0,%1,%2"
734   [(set_attr "type" "arith")
735    (set_attr "mode" "SI")])
738 ;;  ....................
740 ;;      SUBTRACTION
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")))]
758   "TARGET_64BIT"
759   "sub\t%0,%z1,%2"
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")))]
767   ""
768   "sub%~\t%0,%z1,%2"
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")))]
776   ""
778   if (TARGET_64BIT)
779     {
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);
786       DONE;
787     }
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 "" ""))]
795   ""
797   if (TARGET_64BIT && <MODE>mode == SImode)
798     {
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));
807       else
808         t4 = operands[1];
809       if (GET_CODE (operands[2]) != CONST_INT)
810         emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
811       else
812         t5 = operands[2];
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);
817     }
818   else
819     {
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);
832     }
834   DONE;
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 "" ""))]
842   ""
844   if (TARGET_64BIT && <MODE>mode == SImode)
845     {
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));
851       else
852         t3 = operands[1];
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);
857     }
858   else
859     {
860       emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
861       riscv_expand_conditional_branch (operands[3], LTU, operands[1],
862                                        operands[0]);
863     }
865   DONE;
869 (define_insn "subsi3_extended"
870   [(set (match_operand:DI               0 "register_operand" "= r")
871         (sign_extend:DI
872             (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
873                       (match_operand:SI 2 "register_operand" "  r"))))]
874   "TARGET_64BIT"
875   "subw\t%0,%z1,%2"
876   [(set_attr "type" "arith")
877    (set_attr "mode" "SI")])
879 (define_insn "*subsi3_extended2"
880   [(set (match_operand:DI                        0 "register_operand" "= r")
881         (sign_extend:DI
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"))])))]
885   "TARGET_64BIT"
886   "subw\t%0,%z1,%2"
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")))]
893   "TARGET_64BIT"
894   "neg\t%0,%1"
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")))]
901   ""
902   "neg%~\t%0,%1"
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")))]
909   ""
911   if (TARGET_64BIT)
912     {
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);
919       DONE;
920     }
923 (define_insn "negsi2_extended"
924   [(set (match_operand:DI          0 "register_operand" "=r")
925         (sign_extend:DI
926          (neg:SI (match_operand:SI 1 "register_operand" " r"))))]
927   "TARGET_64BIT"
928   "negw\t%0,%1"
929   [(set_attr "type" "arith")
930    (set_attr "mode" "SI")])
932 (define_insn "*negsi2_extended2"
933   [(set (match_operand:DI                     0 "register_operand" "=r")
934         (sign_extend:DI
935          (match_operator:SI 2 "subreg_lowpart_operator"
936            [(neg:DI (match_operand:DI 1 "register_operand" " r"))])))]
937   "TARGET_64BIT"
938   "negw\t%0,%1"
939   [(set_attr "type" "arith")
940    (set_attr "mode" "SI")])
943 ;;  ....................
945 ;;      MULTIPLICATION
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"
964   "mul%~\t%0,%1,%2"
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"
974   if (TARGET_64BIT)
975     {
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);
982       DONE;
983     }
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"
991   "mul\t%0,%1,%2"
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)
1003     {
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));
1011       else
1012         t4 = operands[1];
1013       if (GET_CODE (operands[2]) != CONST_INT)
1014         emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
1015       else
1016         t5 = operands[2];
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);
1023     }
1024   else
1025     {
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);
1035     }
1037   DONE;
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)
1048     {
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));
1058       else
1059         t3 = operands[1];
1060       if (GET_CODE (operands[2]) != CONST_INT)
1061         emit_insn (gen_extend_insn (t4, operands[2], DImode, SImode, 0));
1062       else
1063         t4 = operands[2];
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);
1072     }
1073   else
1074     {
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);
1081     }
1083   DONE;
1086 (define_insn "mulsi3_extended"
1087   [(set (match_operand:DI              0 "register_operand" "=r")
1088         (sign_extend:DI
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"
1092   "mulw\t%0,%1,%2"
1093   [(set_attr "type" "imul")
1094    (set_attr "mode" "SI")])
1096 (define_insn "*mulsi3_extended2"
1097   [(set (match_operand:DI                       0 "register_operand" "=r")
1098         (sign_extend:DI
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"
1103   "mulw\t%0,%1,%2"
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);
1130   DONE;
1133 (define_insn "<su>muldi3_highpart"
1134   [(set (match_operand:DI                0 "register_operand" "=r")
1135         (truncate:DI
1136           (lshiftrt:TI
1137             (mult:TI (any_extend:TI
1138                        (match_operand:DI 1 "register_operand" " r"))
1139                      (any_extend:TI
1140                        (match_operand:DI 2 "register_operand" " r")))
1141             (const_int 64))))]
1142   "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
1143   "mulh<u>\t%0,%1,%2"
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);
1161   DONE;
1164 (define_insn "usmuldi3_highpart"
1165   [(set (match_operand:DI                0 "register_operand" "=r")
1166         (truncate:DI
1167           (lshiftrt:TI
1168             (mult:TI (zero_extend:TI
1169                        (match_operand:DI 1 "register_operand"  "r"))
1170                      (sign_extend:TI
1171                        (match_operand:DI 2 "register_operand" " r")))
1172             (const_int 64))))]
1173   "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
1174   "mulhsu\t%0,%2,%1"
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"))
1182                  (any_extend:DI
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));
1191   DONE;
1194 (define_insn "<su>mulsi3_highpart"
1195   [(set (match_operand:SI                0 "register_operand" "=r")
1196         (truncate:SI
1197           (lshiftrt:DI
1198             (mult:DI (any_extend:DI
1199                        (match_operand:SI 1 "register_operand" " r"))
1200                      (any_extend:DI
1201                        (match_operand:SI 2 "register_operand" " r")))
1202             (const_int 32))))]
1203   "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
1204   "mulh<u>\t%0,%1,%2"
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"))
1213                  (sign_extend:DI
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));
1222   DONE;
1225 (define_insn "usmulsi3_highpart"
1226   [(set (match_operand:SI                0 "register_operand" "=r")
1227         (truncate:SI
1228           (lshiftrt:DI
1229             (mult:DI (zero_extend:DI
1230                        (match_operand:SI 1 "register_operand" " r"))
1231                      (sign_extend:DI
1232                        (match_operand:SI 2 "register_operand" " r")))
1233             (const_int 32))))]
1234   "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
1235   "mulhsu\t%0,%2,%1"
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")))]
1251   "TARGET_DIV"
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")))]
1260   "TARGET_DIV"
1262   if (TARGET_64BIT)
1263     {
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);
1270       DONE;
1271     }
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"
1284   [(parallel
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 ()"
1291   {
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));
1296       DONE;
1297   })
1299 (define_insn "<optab>si3_extended"
1300   [(set (match_operand:DI                 0 "register_operand" "=r")
1301         (sign_extend:DI
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 ;;  ....................
1321 ;;      SQUARE ROOT
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.
1337 ;; a * b + c
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>")])
1348 ;; a * b - c
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>")])
1359 ;; -a * b - c
1360 (define_insn "fnms<mode>4"
1361   [(set (match_operand:ANYF               0 "register_operand" "=f")
1362         (fma:ANYF
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>")])
1371 ;; -a * b + c
1372 (define_insn "fnma<mode>4"
1373   [(set (match_operand:ANYF               0 "register_operand" "=f")
1374         (fma:ANYF
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")
1386         (neg:ANYF
1387             (fma:ANYF
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")
1399         (neg:ANYF
1400             (fma:ANYF
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")
1412         (neg:ANYF
1413             (fma:ANYF
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")
1425         (neg:ANYF
1426             (fma:ANYF
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 ;;  ....................
1438 ;;      SIGN INJECTION
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"
1446   "fabs.<fmt>\t%0,%1"
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")]
1454                      UNSPEC_COPYSIGN))]
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"
1464   "fneg.<fmt>\t%0,%1"
1465   [(set_attr "type" "fmove")
1466    (set_attr "mode" "<UNITMODE>")])
1469 ;;  ....................
1471 ;;      MIN/MAX
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"))]
1479                      UNSPEC_FMINM))]
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"))]
1489                      UNSPEC_FMAXM))]
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"))]
1499                      UNSPEC_FMIN))]
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"))]
1509                      UNSPEC_FMAX))]
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 ;;  ....................
1536 ;;      LOGICAL
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")))]
1548   ""
1550   /* If the second operand is a mode mask, emit an extension
1551      insn instead.  */
1552   if (CONST_INT_P (operands[2]))
1553     {
1554       enum machine_mode tmode = VOIDmode;
1555       if (UINTVAL (operands[2]) == GET_MODE_MASK (HImode))
1556         tmode = HImode;
1557       else if (UINTVAL (operands[2]) == GET_MODE_MASK (SImode))
1558         tmode = SImode;
1560       if (tmode != VOIDmode)
1561         {
1562           rtx tmp = gen_lowpart (tmode, operands[1]);
1563           emit_insn (gen_extend_insn (operands[0], tmp, <MODE>mode, tmode, 1));
1564           DONE;
1565         }
1566     }
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")))]
1573   ""
1574   "and%i2\t%0,%1,%2"
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")))]
1582   ""
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")))]
1591   "TARGET_64BIT"
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")))]
1599   ""
1600   "not\t%0,%1"
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")))]
1607   "TARGET_64BIT"
1608   "not\t%0,%1"
1609   [(set_attr "type" "logical")
1610    (set_attr "mode" "SI")])
1613 ;;  ....................
1615 ;;      TRUNCATION
1617 ;;  ....................
1619 (define_insn "truncdfsf2"
1620   [(set (match_operand:SF     0 "register_operand" "=f")
1621         (float_truncate:SF
1622             (match_operand:DF 1 "register_operand" " f")))]
1623   "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
1624   "fcvt.s.d\t%0,%1"
1625   [(set_attr "type" "fcvt")
1626    (set_attr "mode" "SF")])
1628 (define_insn "truncsfhf2"
1629   [(set (match_operand:HF     0 "register_operand" "=f")
1630        (float_truncate:HF
1631            (match_operand:SF 1 "register_operand" " f")))]
1632   "TARGET_ZFHMIN || TARGET_ZHINXMIN"
1633   "fcvt.h.s\t%0,%1"
1634   [(set_attr "type" "fcvt")
1635    (set_attr "mode" "HF")])
1637 (define_insn "truncdfhf2"
1638   [(set (match_operand:HF     0 "register_operand" "=f")
1639        (float_truncate:HF
1640            (match_operand:DF 1 "register_operand" " f")))]
1641   "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
1642    (TARGET_ZHINXMIN && TARGET_ZDINX)"
1643   "fcvt.h.d\t%0,%1"
1644   [(set_attr "type" "fcvt")
1645    (set_attr "mode" "HF")])
1648 ;;  ....................
1650 ;;      ZERO EXTENSION
1652 ;;  ....................
1654 ;; Extension insns.
1656 (define_expand "zero_extendsidi2"
1657   [(set (match_operand:DI 0 "register_operand")
1658         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
1659   "TARGET_64BIT")
1661 (define_insn_and_split "*zero_extendsidi2_internal"
1662   [(set (match_operand:DI     0 "register_operand"     "=r,r")
1663         (zero_extend:DI
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)"
1668   "@
1669    #
1670    lwu\t%0,%1"
1671   "&& reload_completed
1672    && REG_P (operands[1])
1673    && !paradoxical_subreg_p (operands[0])"
1674   [(set (match_dup 0)
1675         (ashift:DI (match_dup 1) (const_int 32)))
1676    (set (match_dup 0)
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")
1685         (zero_extend:GPR
1686             (match_operand:HI 1 "nonimmediate_operand")))]
1687   "")
1689 (define_insn_and_split "*zero_extendhi<GPR:mode>2"
1690   [(set (match_operand:GPR    0 "register_operand"     "=r,r")
1691         (zero_extend:GPR
1692             (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
1693   "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
1694   "@
1695    #
1696    lhu\t%0,%1"
1697   "&& reload_completed
1698    && REG_P (operands[1])
1699    && !paradoxical_subreg_p (operands[0])"
1700   [(set (match_dup 0)
1701         (ashift:GPR (match_dup 1) (match_dup 2)))
1702    (set (match_dup 0)
1703         (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1704   {
1705     operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1706     operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1707   }
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")))]
1716   "")
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"
1723   "@
1724    andi\t%0,%1,0xff
1725    lbu\t%0,%1"
1726   [(set_attr "move_type" "andi,load")
1727    (set_attr "type" "multi")
1728    (set_attr "mode" "<SUPERQI:MODE>")])
1731 ;;  ....................
1733 ;;      SIGN EXTENSION
1735 ;;  ....................
1737 (define_expand "extendsidi2"
1738   [(set (match_operand:DI     0 "register_operand"     "=r,r")
1739         (sign_extend:DI
1740             (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1741   "TARGET_64BIT")
1743 (define_insn "*extendsidi2_internal"
1744   [(set (match_operand:DI     0 "register_operand"     "=r,r")
1745         (sign_extend:DI
1746             (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1747   "TARGET_64BIT && !TARGET_XTHEADMEMIDX"
1748   "@
1749    sext.w\t%0,%1
1750    lw\t%0,%1"
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")))]
1758   "")
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"
1765   "@
1766    #
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")
1785        (float_extend:SF
1786            (match_operand:HF 1 "register_operand" " f")))]
1787   "TARGET_ZFHMIN || TARGET_ZHINXMIN"
1788   "fcvt.s.h\t%0,%1"
1789   [(set_attr "type" "fcvt")
1790    (set_attr "mode" "SF")])
1792 (define_insn "extendsfdf2"
1793   [(set (match_operand:DF     0 "register_operand" "=f")
1794         (float_extend:DF
1795             (match_operand:SF 1 "register_operand" " f")))]
1796   "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
1797   "fcvt.d.s\t%0,%1"
1798   [(set_attr "type" "fcvt")
1799    (set_attr "mode" "DF")])
1801 (define_insn "extendhfdf2"
1802   [(set (match_operand:DF     0 "register_operand" "=f")
1803        (float_extend:DF
1804            (match_operand:HF 1 "register_operand" " f")))]
1805   "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
1806    (TARGET_ZHINXMIN && TARGET_ZDINX)"
1807   "fcvt.d.h\t%0,%1"
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 ""))]
1815   ""
1817   if (riscv_legitimize_move (HFmode, operands[0], operands[1]))
1818     DONE;
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"))]
1824   "TARGET_ZFHMIN
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"))]
1835   "!TARGET_ZFHMIN
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 ;;  ....................
1846 ;;      CONVERSIONS
1848 ;;  ....................
1850 (define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
1851   [(set (match_operand:GPR      0 "register_operand" "=r")
1852         (fix:GPR
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")
1861         (unsigned_fix:GPR
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")
1870         (float:ANYF
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")
1888         (unspec:GPR
1889             [(match_operand:ANYF 1 "register_operand" " f")]
1890             RINT))]
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")
1898         (unspec:ANYF
1899             [(match_operand:ANYF 1 "register_operand" " f")]
1900         ROUND))]
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")
1908         (unspec:ANYF
1909             [(match_operand:ANYF 1 "register_operand" " f")]
1910         UNSPEC_RINT))]
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 ;;  ....................
1919 ;;      DATA MOVEMENT
1921 ;;  ....................
1923 ;; Lower-level instructions for loading an address from the GOT.
1924 ;; We could use MEMs, but an unspec gives more optimization
1925 ;; opportunities.
1927 (define_insn "got_load<mode>"
1928    [(set (match_operand:P      0 "register_operand" "=r")
1929          (unspec:P
1930              [(match_operand:P 1 "symbolic_operand" "")]
1931              UNSPEC_LOAD_GOT))]
1932   ""
1933   "la\t%0,%1"
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")
1940         (unspec:P
1941             [(match_operand:P 1 "register_operand" "r")
1942              (match_operand:P 2 "register_operand" "r")
1943              (match_operand:P 3 "symbolic_operand" "")]
1944             UNSPEC_TLS_LE))]
1945   ""
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")
1952         (unspec:P
1953             [(match_operand:P 1 "symbolic_operand" "")]
1954             UNSPEC_TLS_GD))]
1955   ""
1956   "la.tls.gd\t%0,%1"
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")
1963         (unspec:P
1964             [(match_operand:P 1 "symbolic_operand" "")]
1965             UNSPEC_TLS_IE))]
1966   ""
1967   "la.tls.ie\t%0,%1"
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")
1974         (unspec:P
1975             [(match_operand:P      1 "symbolic_operand" "")
1976                   (match_operand:P 2 "const_int_operand")
1977                   (pc)]
1978             UNSPEC_AUIPC))]
1979   ""
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" "")))]
1992   ""
1993   "addi\t%0,%1,%R2"
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.
1999 (define_split
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"))]
2003   ""
2004   [(const_int 0)]
2006   riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
2007                       <GPR:MODE>mode);
2008   DONE;
2011 ;; Likewise, for symbolic operands.
2012 (define_split
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"))]
2032   "!ira_in_progress
2033    && !(p2m1_shift_operand (operands[1], <MODE>mode)
2034         || high_mask_shift_operand (operands[1], <MODE>mode))"
2035   "#"
2036   "&& 1"
2037   [(const_int 0)]
2039   riscv_move_integer (operands[0], operands[0], INTVAL (operands[1]),
2040                       <MODE>mode);
2041   DONE;
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 ""))]
2050   ""
2052   if (riscv_legitimize_move (DImode, operands[0], operands[1]))
2053     DONE;
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"))]
2059   "!TARGET_64BIT
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"))]
2071   "TARGET_64BIT
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 ""))]
2085   ""
2087   if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
2088     DONE;
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 ""))]
2114   ""
2116   if (riscv_legitimize_move (HImode, operands[0], operands[1]))
2117     DONE;
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")))]
2139   ""
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")))]
2148   ""
2149   "xor%i2\t%0,%1,%2"
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 ""))]
2158   ""
2160   if (riscv_legitimize_move (QImode, operands[0], operands[1]))
2161     DONE;
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 ""))]
2180   ""
2182   if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
2183     DONE;
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"))]
2189   "TARGET_HARD_FLOAT
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"))]
2200   "!TARGET_HARD_FLOAT
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 ""))]
2213   ""
2215   if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
2216     DONE;
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")
2257         (truncate:SI
2258             (match_operand:DF 1 "register_operand"  "zmvf")))]
2259   "TARGET_HARD_FLOAT && !TARGET_64BIT && TARGET_ZFA"
2260   "fmv.x.w\t%0,%1"
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")
2268         (truncate:SI
2269             (lshiftrt:DF
2270                 (match_operand:DF 1 "register_operand" "zmvf")
2271                 (const_int 32))))]
2272   "TARGET_HARD_FLOAT && !TARGET_64BIT && TARGET_ZFA"
2273   "fmvh.x.d\t%0,%1"
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")
2280         (plus:DF
2281             (match_operand:SI 2 "register_operand"     "zmvr")
2282             (ashift:SI
2283                 (match_operand:SI 1 "register_operand" "zmvr")
2284                 (const_int 32))))]
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")])
2291 (define_split
2292   [(set (match_operand:MOVE64 0 "nonimmediate_operand")
2293         (match_operand:MOVE64 1 "move_operand"))]
2294   "reload_completed
2295    && riscv_split_64bit_move_p (operands[0], operands[1])"
2296   [(const_int 0)]
2298   riscv_split_doubleword_move (operands[0], operands[1]);
2299   DONE;
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"))])]
2307   ""
2309   if (riscv_vector::expand_block_move (operands[0], operands[1], operands[2]))
2310     DONE;
2311   else if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
2312     DONE;
2313   else
2314     FAIL;
2317 ;; Expand in-line code to clear the instruction cache between operand[0] and
2318 ;; operand[1].
2319 (define_expand "clear_cache"
2320   [(match_operand 0 "pmode_register_operand")
2321    (match_operand 1 "pmode_register_operand")]
2322   ""
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);
2328 #else
2329   if (TARGET_ZIFENCEI)
2330     emit_insn (gen_fence_i ());
2331 #endif
2332   DONE;
2335 (define_insn "fence"
2336   [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
2337   ""
2338   "%|fence%-"
2339   [(set_attr "type" "atomic")])
2341 (define_insn "fence_i"
2342   [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
2343   "TARGET_ZIFENCEI"
2344   "fence.i"
2345   [(set_attr "type" "atomic")])
2347 (define_insn "riscv_pause"
2348   [(unspec_volatile [(const_int 0)] UNSPECV_PAUSE)]
2349   ""
2350   "* return TARGET_ZIHINTPAUSE ? \"pause\" : \".insn\t0x0100000f\";"
2351   [(set_attr "type" "atomic")])
2354 ;;  ....................
2356 ;;      SHIFTS
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")
2367         (any_shift:SI
2368             (match_operand:SI 1 "register_operand" "  r")
2369             (match_operand:QI 2 "arith_operand"    " rI")))]
2370   ""
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")))]
2385   ""
2387   if (TARGET_64BIT)
2388     {
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);
2395       DONE;
2396     }
2399 (define_insn "<optab>di3"
2400   [(set (match_operand:DI 0 "register_operand"     "= r")
2401         (any_shift:DI
2402             (match_operand:DI 1 "register_operand" "  r")
2403             (match_operand:QI 2 "arith_operand"    " rI")))]
2404   "TARGET_64BIT"
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")
2417         (any_shift:GPR
2418             (match_operand:GPR 1 "register_operand" "  r")
2419             (match_operator 4 "subreg_lowpart_operator"
2420              [(and:GPR2
2421                (match_operand:GPR2 2 "register_operand"  "r")
2422                (match_operand 3 "<GPR:shiftm1>"))])))]
2423   ""
2424   "#"
2425   "&& 1"
2426   [(set (match_dup 0)
2427         (any_shift:GPR (match_dup 1)
2428                       (match_dup 2)))]
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")
2435         (sign_extend:DI
2436             (any_shift:SI (match_operand:SI 1 "register_operand" "  r")
2437                           (match_operand:QI 2 "arith_operand"    " rI"))))]
2438   "TARGET_64BIT"
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")
2450         (sign_extend:DI
2451             (any_shift:SI
2452              (match_operand:SI 1 "register_operand" "  r")
2453              (match_operator 4 "subreg_lowpart_operator"
2454               [(and:GPR
2455                 (match_operand:GPR 2 "register_operand" " r")
2456                 (match_operand 3 "const_si_mask_operand"))]))))]
2457   "TARGET_64BIT"
2458   "#"
2459   "&& 1"
2460   [(set (match_dup 0)
2461         (sign_extend:DI
2462          (any_shift:SI (match_dup 1)
2463                        (match_dup 2))))]
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")
2472         (zero_extend:DI
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")
2503                (const_int 0)))]
2504   "TARGET_64BIT"
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.
2518 (define_split
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"))]
2523   ""
2524  [(set (match_dup 3)
2525        (ashift:GPR (match_dup 1) (match_dup 2)))
2526   (set (match_dup 0)
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.
2536 (define_split
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"))]
2541   "TARGET_64BIT"
2542   [(set (match_dup 3)
2543         (lshiftrt:DI (match_dup 1) (match_dup 2)))
2544    (set (match_dup 0)
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)"
2562   "#"
2563   "&& reload_completed"
2564   [(set (match_dup 4)
2565         (ashift:DI (match_dup 1) (const_int 32)))
2566    (set (match_dup 0)
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"
2582   [(set (pc)
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"))
2586                         (const_int 0)])
2587          (label_ref (match_operand 0 "" ""))
2588          (pc)))
2589    (clobber (match_scratch:X 4 "=&r"))]
2590   "!SMALL_OPERAND (INTVAL (operands[3]))"
2591   "#"
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"
2607   [(set (pc)
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"))
2611                         (const_int 0)])
2612          (label_ref (match_operand 0 "" ""))
2613          (pc)))
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]))"
2618   "#"
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>"
2635   [(set (pc)
2636         (if_then_else
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 "" ""))
2641          (pc)))]
2642   ""
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]))
2663     DONE;
2664   else
2665     FAIL;
2668 (define_insn "*mov<GPR:mode><X:mode>cc"
2669   [(set (match_operand:GPR 0 "register_operand" "=r,r")
2670         (if_then_else:GPR
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")))]
2676   "TARGET_SFB_ALU"
2677   "@
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"
2686   [(set (pc)
2687         (if_then_else (match_operand 0)
2688                       (label_ref (match_operand 1))
2689                       (pc)))])
2691 (define_expand "@cbranch<mode>4"
2692   [(set (pc)
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 ""))
2697                       (pc)))]
2698   ""
2700   riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2701                                    operands[1], operands[2]);
2702   DONE;
2705 (define_expand "@cbranch<mode>4"
2706   [(set (pc)
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 ""))
2711                       (pc)))]
2712   "TARGET_HARD_FLOAT || TARGET_ZFINX"
2714   riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
2715                                    operands[1], operands[2]);
2716   DONE;
2719 (define_insn_and_split "*branch_on_bit<X:mode>"
2720   [(set (pc)
2721         (if_then_else
2722             (match_operator 0 "equality_operator"
2723                 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
2724                                  (const_int 1)
2725                                  (match_operand 3 "branch_on_bit_operand"))
2726                                  (const_int 0)])
2727             (label_ref (match_operand 1))
2728             (pc)))
2729    (clobber (match_scratch:X 4 "=&r"))]
2730   ""
2731   "#"
2732   "reload_completed"
2733   [(set (match_dup 4)
2734         (ashift:X (match_dup 2) (match_dup 3)))
2735    (set (pc)
2736         (if_then_else
2737             (match_op_dup 0 [(match_dup 4) (const_int 0)])
2738             (label_ref (match_operand 1))
2739             (pc)))]
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);
2746   else
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>"
2752   [(set (pc)
2753         (if_then_else
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")
2757                                  (const_int 0))
2758                                  (const_int 0)])
2759             (label_ref (match_operand 1))
2760             (pc)))
2761    (clobber (match_scratch:X 4 "=&r"))]
2762   ""
2763   "#"
2764   "reload_completed"
2765   [(set (match_dup 4)
2766         (ashift:X (match_dup 2) (match_dup 3)))
2767    (set (pc)
2768         (if_then_else
2769             (match_op_dup 0 [(match_dup 4) (const_int 0)])
2770             (label_ref (match_operand 1))
2771             (pc)))]
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")]))]
2791   ""
2793   riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
2794                         operands[3]);
2795   DONE;
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],
2806                           operands[3]);
2807   DONE;
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")]
2824                    QUIET_COMPARISON))]
2825   "TARGET_HARD_FLOAT || TARGET_ZFINX"
2827   rtx op0 = operands[0];
2828   rtx op1 = operands[1];
2829   rtx op2 = operands[2];
2831   if (TARGET_ZFA)
2832     emit_insn (gen_f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_zfa(op0, op1, op2));
2833   else
2834     {
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),
2838                                              UNSPECV_FRFLAGS);
2839       rtx fsflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, tmp),
2840                                              UNSPECV_FSFLAGS);
2842       emit_insn (gen_rtx_SET (tmp, frflags));
2843       emit_insn (gen_rtx_SET (op0, cmp));
2844       emit_insn (fsflags);
2845     }
2847   if (HONOR_SNANS (<ANYF:MODE>mode))
2848     emit_insn (gen_rtx_UNSPEC_VOLATILE (<ANYF:MODE>mode,
2849                                         gen_rtvec (2, op1, op2),
2850                                         UNSPECV_FSNVSNAN));
2851   DONE;
2854 (define_insn "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_zfa"
2855    [(set (match_operand:X      0 "register_operand" "=r")
2856          (unspec:X
2857           [(match_operand:ANYF 1 "register_operand" " f")
2858            (match_operand:ANYF 2 "register_operand" " f")]
2859           QUIET_COMPARISON))]
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")
2869                 (const_int 0)))]
2870   ""
2871   "seqz\t%0,%1"
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")
2878                 (const_int 0)))]
2879   ""
2880   "snez\t%0,%1"
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")))]
2888   ""
2889   "sgt<u>\t%0,%1,%z2"
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")
2896                     (const_int 1)))]
2897   ""
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")))]
2906   ""
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" "")))]
2915   ""
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.
2932 (define_insn "jump"
2933   [(set (pc) (label_ref (match_operand 0 "" "")))]
2934   ""
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";
2941   return "j\t%l0";
2943   [(set_attr "type"     "jump")
2944    (set_attr "mode"     "none")])
2946 (define_expand "indirect_jump"
2947   [(set (pc) (match_operand 0 "register_operand"))]
2948   ""
2950   operands[0] = force_reg (Pmode, operands[0]);
2951   if (Pmode == SImode)
2952     emit_jump_insn (gen_indirect_jumpsi (operands[0]));
2953   else
2954     emit_jump_insn (gen_indirect_jumpdi (operands[0]));
2955   DONE;
2958 (define_insn "indirect_jump<mode>"
2959   [(set (pc) (match_operand:P 0 "register_operand" "l"))]
2960   ""
2961   "jr\t%0"
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 "" "")))]
2968   ""
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]));
2977   else
2978     emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
2979   DONE;
2982 (define_insn "tablejump<mode>"
2983   [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
2984    (use (label_ref (match_operand 1 "" "")))]
2985   ""
2986   "jr\t%0"
2987   [(set_attr "type" "jalr")
2988    (set_attr "mode" "none")])
2991 ;;  ....................
2993 ;;      Function prologue/epilogue
2995 ;;  ....................
2998 (define_expand "prologue"
2999   [(const_int 1)]
3000   ""
3002   riscv_expand_prologue ();
3003   DONE;
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)]
3012   ""
3013   ""
3014   [(set_attr "type" "ghost")
3015    (set_attr "mode" "none")])
3017 (define_expand "epilogue"
3018   [(const_int 2)]
3019   ""
3021   riscv_expand_epilogue (NORMAL_RETURN);
3022   DONE;
3025 (define_expand "sibcall_epilogue"
3026   [(const_int 2)]
3027   ""
3029   riscv_expand_epilogue (SIBCALL_RETURN);
3030   DONE;
3033 ;; Trivial return.  Make it look like a normal return insn as that
3034 ;; allows jump optimizations to work better.
3036 (define_expand "return"
3037   [(simple_return)]
3038   "riscv_can_use_return_insn ()"
3039   "")
3041 (define_insn "simple_return"
3042   [(simple_return)]
3043   ""
3045   return riscv_output_return ();
3047   [(set_attr "type"     "jalr")
3048    (set_attr "mode"     "none")])
3050 ;; Normal return.
3052 (define_insn "simple_return_internal"
3053   [(simple_return)
3054    (use (match_operand 0 "pmode_register_operand" ""))]
3055   ""
3056   "jr\t%0"
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"))]
3063   ""
3065   if (GET_MODE (operands[0]) != word_mode)
3066     operands[0] = convert_to_mode (word_mode, operands[0], 0);
3067   if (TARGET_64BIT)
3068     emit_insn (gen_eh_set_lr_di (operands[0]));
3069   else
3070     emit_insn (gen_eh_set_lr_si (operands[0]));
3072   emit_jump_insn (gen_eh_return_internal ());
3073   emit_barrier ();
3074   DONE;
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"))]
3083   "! TARGET_64BIT"
3084   "#"
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"))]
3090   "TARGET_64BIT"
3091   "#"
3092   [(set_attr "type" "jump")])
3094 (define_split
3095   [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
3096    (clobber (match_scratch 1))]
3097   "reload_completed"
3098   [(const_int 0)]
3100   riscv_set_return_address (operands[0], operands[1]);
3101   DONE;
3104 (define_insn_and_split "eh_return_internal"
3105   [(eh_return)]
3106   ""
3107   "#"
3108   "epilogue_completed"
3109   [(const_int 0)]
3110   "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;"
3111   [(set_attr "type" "ret")])
3114 ;;  ....................
3116 ;;      FUNCTION CALLS
3118 ;;  ....................
3120 (define_expand "sibcall"
3121   [(parallel [(call (match_operand 0 "")
3122                     (match_operand 1 ""))
3123               (use (unspec:SI [
3124                      (match_operand 2 "const_int_operand")
3125                    ] UNSPEC_CALLEE_CC))])]
3126   ""
3128   rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
3129   emit_call_insn (gen_sibcall_internal (target, operands[1], operands[2]));
3130   DONE;
3133 (define_insn "sibcall_internal"
3134   [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
3135          (match_operand 1 "" ""))
3136    (use (unspec:SI [
3137           (match_operand 2 "const_int_operand")
3138         ] UNSPEC_CALLEE_CC))]
3139   "SIBLING_CALL_P (insn)"
3140   "@
3141    jr\t%0
3142    tail\t%0
3143    tail\t%0@plt"
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 "")))
3150               (use (unspec:SI [
3151                      (match_operand 3 "const_int_operand")
3152                    ] UNSPEC_CALLEE_CC))])]
3153   ""
3155   rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
3156   emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2],
3157                                               operands[3]));
3158   DONE;
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 "" "")))
3165    (use (unspec:SI [
3166           (match_operand 3 "const_int_operand")
3167         ] UNSPEC_CALLEE_CC))]
3168   "SIBLING_CALL_P (insn)"
3169   "@
3170    jr\t%1
3171    tail\t%1
3172    tail\t%1@plt"
3173   [(set_attr "type" "call")])
3175 (define_expand "call"
3176   [(parallel [(call (match_operand 0 "")
3177                     (match_operand 1 ""))
3178               (use (unspec:SI [
3179                      (match_operand 2 "const_int_operand")
3180                    ] UNSPEC_CALLEE_CC))])]
3181   ""
3183   rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
3184   emit_call_insn (gen_call_internal (target, operands[1], operands[2]));
3185   DONE;
3188 (define_insn "call_internal"
3189   [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
3190          (match_operand 1 "" ""))
3191    (use (unspec:SI [
3192           (match_operand 2 "const_int_operand")
3193         ] UNSPEC_CALLEE_CC))
3194    (clobber (reg:SI RETURN_ADDR_REGNUM))]
3195   ""
3196   "@
3197    jalr\t%0
3198    call\t%0
3199    call\t%0@plt"
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 "")))
3206               (use (unspec:SI [
3207                      (match_operand 3 "const_int_operand")
3208                    ] UNSPEC_CALLEE_CC))])]
3209   ""
3211   rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
3212   emit_call_insn (gen_call_value_internal (operands[0], target, operands[2],
3213                                            operands[3]));
3214   DONE;
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 "" "")))
3221    (use (unspec:SI [
3222           (match_operand 3 "const_int_operand")
3223         ] UNSPEC_CALLEE_CC))
3224    (clobber (reg:SI RETURN_ADDR_REGNUM))]
3225   ""
3226   "@
3227    jalr\t%1
3228    call\t%1
3229    call\t%1@plt"
3230   [(set_attr "type" "call")])
3232 ;; Call subroutine returning any type.
3234 (define_expand "untyped_call"
3235   [(parallel [(call (match_operand 0 "")
3236                     (const_int 0))
3237               (match_operand 1 "")
3238               (match_operand 2 "")])]
3239   ""
3241   int i;
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++)
3248     {
3249       rtx set = XVECEXP (operands[2], 0, i);
3250       riscv_emit_move (SET_DEST (set), SET_SRC (set));
3251     }
3253   emit_insn (gen_blockage ());
3254   DONE;
3257 (define_insn "nop"
3258   [(const_int 0)]
3259   ""
3260   "nop"
3261   [(set_attr "type"     "nop")
3262    (set_attr "mode"     "none")])
3264 (define_insn "trap"
3265   [(trap_if (const_int 1) (const_int 0))]
3266   ""
3267   "ebreak"
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)])]
3278   ""
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)]
3284   ""
3285   "tail\t__riscv_restore_%0"
3286   [(set_attr "type" "call")])
3288 (define_insn "gpr_restore_return"
3289   [(return)
3290    (use (match_operand 0 "pmode_register_operand" ""))
3291    (const_int 0)]
3292   ""
3293   ""
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"
3300   "frcsr\t%0"
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"
3306   "fscsr\t%0"
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"
3313   "frflags\t%0"
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"
3319   "fsflags%i0\t%0"
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")]
3325                     UNSPECV_FSNVSNAN)]
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"
3332   [(return)
3333    (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
3334   ""
3335   "mret"
3336   [(set_attr "type" "ret")])
3338 (define_insn "riscv_sret"
3339   [(return)
3340    (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
3341   ""
3342   "sret"
3343   [(set_attr "type" "ret")])
3345 (define_insn "riscv_uret"
3346   [(return)
3347    (unspec_volatile [(const_int 0)] UNSPECV_URET)]
3348   ""
3349   "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")]
3356                     UNSPEC_TIE))]
3357   ""
3358   ""
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")]
3371   ""
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));
3377   DONE;
3380 ;; Named pattern for expanding thread pointer reference.
3381 (define_expand "get_thread_pointer<mode>"
3382   [(set (match_operand:P 0 "register_operand" "=r")
3383         (reg:P TP_REGNUM))]
3384   ""
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")]
3392   ""
3394   machine_mode mode = GET_MODE (operands[0]);
3395   if (riscv_stack_protector_guard == SSP_TLS)
3396   {
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);
3401   }
3403   emit_insn ((mode == DImode
3404               ? gen_stack_protect_set_di
3405               : gen_stack_protect_set_si) (operands[0], operands[1]));
3406   DONE;
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")]
3414          UNSPEC_SSP_SET))
3415    (set (match_scratch:GPR 2 "=&r") (const_int 0))]
3416   ""
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")
3424    (match_operand 2)]
3425   ""
3427   rtx result;
3428   machine_mode mode = GET_MODE (operands[0]);
3430   result = gen_reg_rtx(mode);
3431   if (riscv_stack_protector_guard == SSP_TLS)
3432   {
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);
3437   }
3438   emit_insn ((mode == DImode
3439                   ? gen_stack_protect_test_di
3440                   : gen_stack_protect_test_si) (result,
3441                                                 operands[0],
3442                                                 operands[1]));
3444   rtx cond = gen_rtx_EQ (VOIDmode, result, const0_rtx);
3445   emit_jump_insn (gen_cbranch4 (mode, cond, result, const0_rtx, operands[2]));
3447   DONE;
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")]
3454          UNSPEC_SSP_TEST))
3455    (clobber (match_scratch:GPR 3 "=&r"))]
3456   ""
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")]
3463     UNSPECV_CLEAN)]
3464   "TARGET_ZICBOM"
3465   "cbo.clean\t%a0"
3466   [(set_attr "type" "cbo")]
3469 (define_insn "riscv_flush_<mode>"
3470   [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3471     UNSPECV_FLUSH)]
3472   "TARGET_ZICBOM"
3473   "cbo.flush\t%a0"
3474   [(set_attr "type" "cbo")]
3477 (define_insn "riscv_inval_<mode>"
3478   [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3479     UNSPECV_INVAL)]
3480   "TARGET_ZICBOM"
3481   "cbo.inval\t%a0"
3482   [(set_attr "type" "cbo")]
3485 (define_insn "riscv_zero_<mode>"
3486   [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3487     UNSPECV_ZERO)]
3488   "TARGET_ZICBOZ"
3489   "cbo.zero\t%a0"
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"))]
3497   "TARGET_ZICBOP"
3499   switch (INTVAL (operands[1]))
3500   {
3501     case 0: return "prefetch.r\t%a0";
3502     case 1: return "prefetch.w\t%a0";
3503     default: gcc_unreachable ();
3504   }
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")]
3511               UNSPECV_PREI)]
3512   "TARGET_ZICBOP"
3513   "prefetch.i\t%a0"
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")))]
3521   "TARGET_XTHEADBB"
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")))]
3529   "TARGET_XTHEADBB"
3531   if (TARGET_XTHEADBB
3532       && (INTVAL (operands[2]) < 8) && (INTVAL (operands[3]) == 0))
3533     FAIL;
3536 (define_expand "maddhisi4"
3537   [(set (match_operand:SI 0 "register_operand")
3538         (plus:SI
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")))]
3542   "TARGET_XTHEADMAC"
3545 (define_expand "msubhisi4"
3546   [(set (match_operand:SI 0 "register_operand")
3547         (minus:SI
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")))))]
3551   "TARGET_XTHEADMAC"
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]))
3571     DONE;
3572   else
3573     FAIL;
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]))
3591     DONE;
3592   else
3593     FAIL;
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")]
3607                   UNSPEC_STRLEN))]
3608   "riscv_inline_strlen && !optimize_size && (TARGET_ZBB || TARGET_XTHEADBB)"
3610   rtx search_char = operands[2];
3612   if (search_char != const0_rtx)
3613     FAIL;
3615   if (riscv_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
3616     DONE;
3617   else
3618     FAIL;
3621 (include "bitmanip.md")
3622 (include "crypto.md")
3623 (include "sync.md")
3624 (include "sync-rvwmo.md")
3625 (include "sync-ztso.md")
3626 (include "peephole.md")
3627 (include "pic.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")
3634 (include "zc.md")
3635 (include "corev.md")