]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/riscv/riscv.md
[committed][RISC-V] Fix nearbyint failure on rv32 and formatting nits
[thirdparty/gcc.git] / gcc / config / riscv / riscv.md
CommitLineData
09cae750 1;; Machine description for RISC-V for GNU compiler.
a945c346 2;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
09cae750
PD
3;; Contributed by Andrew Waterman (andrew@sifive.com).
4;; Based on MIPS target for GNU compiler.
5
6;; This file is part of GCC.
7
8;; GCC is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation; either version 3, or (at your option)
11;; any later version.
12
13;; GCC is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with GCC; see the file COPYING3. If not see
20;; <http://www.gnu.org/licenses/>.
21
380b8fd9
AP
22
23;; Keep this list and the one above riscv_print_operand in sync.
24;; The special asm out single letter directives following a '%' are:
25;; h -- Print the high-part relocation associated with OP, after stripping
26;; any outermost HIGH.
27;; R -- Print the low-part relocation associated with OP.
28;; C -- Print the integer branch condition for comparison OP.
29;; A -- Print the atomic operation suffix for memory model OP.
30;; F -- Print a FENCE if the memory model requires a release.
31;; z -- Print x0 if OP is zero, otherwise print OP normally.
32;; i -- Print i if the operand is not a register.
33;; S -- Print shift-index of single-bit mask OP.
34;; T -- Print shift-index of inverted single-bit mask OP.
473d7aad 35;; ~ -- Print w if TARGET_64BIT is true; otherwise not print anything.
380b8fd9 36
09cae750
PD
37(define_c_enum "unspec" [
38 ;; Override return address for exception handling.
39 UNSPEC_EH_RETURN
40
41 ;; Symbolic accesses. The order of this list must match that of
42 ;; enum riscv_symbol_type in riscv-protos.h.
43 UNSPEC_ADDRESS_FIRST
d07d0e99 44 UNSPEC_FORCE_FOR_MEM
09cae750
PD
45 UNSPEC_PCREL
46 UNSPEC_LOAD_GOT
47 UNSPEC_TLS
48 UNSPEC_TLS_LE
49 UNSPEC_TLS_IE
50 UNSPEC_TLS_GD
97069657 51 UNSPEC_TLSDESC
09cae750
PD
52 ;; High part of PC-relative address.
53 UNSPEC_AUIPC
54
55 ;; Floating-point unspecs.
56 UNSPEC_FLT_QUIET
57 UNSPEC_FLE_QUIET
58 UNSPEC_COPYSIGN
30699b99
JM
59 UNSPEC_RINT
60 UNSPEC_ROUND
61 UNSPEC_FLOOR
62 UNSPEC_CEIL
63 UNSPEC_BTRUNC
64 UNSPEC_ROUNDEVEN
65 UNSPEC_NEARBYINT
09cae750 66 UNSPEC_LRINT
9ddd44b5
MR
67 UNSPEC_FMIN
68 UNSPEC_FMAX
30699b99
JM
69 UNSPEC_FMINM
70 UNSPEC_FMAXM
09cae750
PD
71
72 ;; Stack tie
73 UNSPEC_TIE
eab3d2d1
PT
74
75 ;; OR-COMBINE
76 UNSPEC_ORC_B
d9df45a6
KS
77
78 ;; Zbc unspecs
79 UNSPEC_CLMUL
80 UNSPEC_CLMULH
81 UNSPEC_CLMULR
fdd59c0f
LD
82
83 ;; the calling convention of callee
84 UNSPEC_CALLEE_CC
df48285b
CM
85
86 ;; String unspecs
87 UNSPEC_STRLEN
057dc349
KLC
88
89 ;; Workaround for HFmode without hardware extension
90 UNSPEC_FMV_SFP16_X
87ed3388
CM
91
92 ;; XTheadFmv moves
93 UNSPEC_XTHEADFMV
94 UNSPEC_XTHEADFMV_HW
09cae750
PD
95])
96
97(define_c_enum "unspecv" [
98 ;; Register save and restore.
99 UNSPECV_GPR_SAVE
100 UNSPECV_GPR_RESTORE
101
102 ;; Floating-point unspecs.
dbcbc858
JM
103 UNSPECV_FRCSR
104 UNSPECV_FSCSR
09cae750
PD
105 UNSPECV_FRFLAGS
106 UNSPECV_FSFLAGS
94f5a8f0 107 UNSPECV_FSNVSNAN
09cae750 108
d0ebdd9f
JW
109 ;; Interrupt handler instructions.
110 UNSPECV_MRET
ec74725c
JW
111 UNSPECV_SRET
112 UNSPECV_URET
d0ebdd9f 113
09cae750
PD
114 ;; Blockage and synchronization.
115 UNSPECV_BLOCKAGE
116 UNSPECV_FENCE
117 UNSPECV_FENCE_I
c931e8d5
CQ
118
119 ;; Stack Smash Protector
120 UNSPEC_SSP_SET
121 UNSPEC_SSP_TEST
3df3ca90
S
122
123 ;; CMO instructions.
124 UNSPECV_CLEAN
125 UNSPECV_FLUSH
126 UNSPECV_INVAL
127 UNSPECV_ZERO
128 UNSPECV_PREI
c717a92d
PT
129
130 ;; Zihintpause unspec
131 UNSPECV_PAUSE
75047aeb 132
52e809d5
JM
133 ;; XTheadInt unspec
134 UNSPECV_XTHEADINT_PUSH
135 UNSPECV_XTHEADINT_POP
09cae750
PD
136])
137
138(define_constants
139 [(RETURN_ADDR_REGNUM 1)
3d1d3132 140 (SP_REGNUM 2)
d0ebdd9f 141 (GP_REGNUM 3)
1073b500 142 (TP_REGNUM 4)
09cae750
PD
143 (T0_REGNUM 5)
144 (T1_REGNUM 6)
145 (S0_REGNUM 8)
146 (S1_REGNUM 9)
b27d323a 147 (A0_REGNUM 10)
490bf0b9 148 (A1_REGNUM 11)
09cae750 149 (S2_REGNUM 18)
d0e0c130
KC
150 (S3_REGNUM 19)
151 (S4_REGNUM 20)
152 (S5_REGNUM 21)
153 (S6_REGNUM 22)
154 (S7_REGNUM 23)
155 (S8_REGNUM 24)
156 (S9_REGNUM 25)
157 (S10_REGNUM 26)
158 (S11_REGNUM 27)
fd1e52dc
JW
159
160 (NORMAL_RETURN 0)
161 (SIBCALL_RETURN 1)
162 (EXCEPTION_RETURN 2)
31380d4b 163 (VL_REGNUM 66)
164 (VTYPE_REGNUM 67)
5ed88078 165 (VXRM_REGNUM 68)
8cd140d3 166 (FRM_REGNUM 69)
09cae750
PD
167])
168
169(include "predicates.md")
170(include "constraints.md")
43e74147 171(include "iterators.md")
09cae750
PD
172
173;; ....................
174;;
175;; Attributes
176;;
177;; ....................
178
179(define_attr "got" "unset,xgot_high,load"
180 (const_string "unset"))
181
182;; Classification of moves, extensions and truncations. Most values
183;; are as for "type" (see below) but there are also the following
184;; move-specific values:
185;;
186;; andi a single ANDI instruction
187;; shift_shift a shift left followed by a shift right
188;;
189;; This attribute is used to determine the instruction's length and
190;; scheduling type. For doubleword moves, the attribute always describes
191;; the split instructions; in some cases, it is more appropriate for the
192;; scheduling type to be "multi" instead.
193(define_attr "move_type"
194 "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove,
8fe75147 195 const,logical,arith,andi,shift_shift,rdvlenb"
09cae750
PD
196 (const_string "unknown"))
197
198;; Main data type used by the insn
f556cd8b 199(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,HF,SF,DF,TF,
879c52c9
JZ
200 RVVMF64BI,RVVMF32BI,RVVMF16BI,RVVMF8BI,RVVMF4BI,RVVMF2BI,RVVM1BI,
201 RVVM8QI,RVVM4QI,RVVM2QI,RVVM1QI,RVVMF2QI,RVVMF4QI,RVVMF8QI,
202 RVVM8HI,RVVM4HI,RVVM2HI,RVVM1HI,RVVMF2HI,RVVMF4HI,
203 RVVM8HF,RVVM4HF,RVVM2HF,RVVM1HF,RVVMF2HF,RVVMF4HF,
204 RVVM8SI,RVVM4SI,RVVM2SI,RVVM1SI,RVVMF2SI,
205 RVVM8SF,RVVM4SF,RVVM2SF,RVVM1SF,RVVMF2SF,
206 RVVM8DI,RVVM4DI,RVVM2DI,RVVM1DI,
207 RVVM8DF,RVVM4DF,RVVM2DF,RVVM1DF,
208 RVVM1x8QI,RVVMF2x8QI,RVVMF4x8QI,RVVMF8x8QI,
209 RVVM1x7QI,RVVMF2x7QI,RVVMF4x7QI,RVVMF8x7QI,
210 RVVM1x6QI,RVVMF2x6QI,RVVMF4x6QI,RVVMF8x6QI,
211 RVVM1x5QI,RVVMF2x5QI,RVVMF4x5QI,RVVMF8x5QI,
212 RVVM2x4QI,RVVM1x4QI,RVVMF2x4QI,RVVMF4x4QI,RVVMF8x4QI,
213 RVVM2x3QI,RVVM1x3QI,RVVMF2x3QI,RVVMF4x3QI,RVVMF8x3QI,
214 RVVM4x2QI,RVVM2x2QI,RVVM1x2QI,RVVMF2x2QI,RVVMF4x2QI,RVVMF8x2QI,
215 RVVM1x8HI,RVVMF2x8HI,RVVMF4x8HI,
216 RVVM1x7HI,RVVMF2x7HI,RVVMF4x7HI,
217 RVVM1x6HI,RVVMF2x6HI,RVVMF4x6HI,
218 RVVM1x5HI,RVVMF2x5HI,RVVMF4x5HI,
219 RVVM2x4HI,RVVM1x4HI,RVVMF2x4HI,RVVMF4x4HI,
220 RVVM2x3HI,RVVM1x3HI,RVVMF2x3HI,RVVMF4x3HI,
221 RVVM4x2HI,RVVM2x2HI,RVVM1x2HI,RVVMF2x2HI,RVVMF4x2HI,
222 RVVM1x8HF,RVVMF2x8HF,RVVMF4x8HF,RVVM1x7HF,RVVMF2x7HF,
223 RVVMF4x7HF,RVVM1x6HF,RVVMF2x6HF,RVVMF4x6HF,RVVM1x5HF,
224 RVVMF2x5HF,RVVMF4x5HF,RVVM2x4HF,RVVM1x4HF,RVVMF2x4HF,
225 RVVMF4x4HF,RVVM2x3HF,RVVM1x3HF,RVVMF2x3HF,RVVMF4x3HF,
226 RVVM4x2HF,RVVM2x2HF,RVVM1x2HF,RVVMF2x2HF,RVVMF4x2HF,
227 RVVM1x8SI,RVVMF2x8SI,
228 RVVM1x7SI,RVVMF2x7SI,
229 RVVM1x6SI,RVVMF2x6SI,
230 RVVM1x5SI,RVVMF2x5SI,
231 RVVM2x4SI,RVVM1x4SI,RVVMF2x4SI,
232 RVVM2x3SI,RVVM1x3SI,RVVMF2x3SI,
233 RVVM4x2SI,RVVM2x2SI,RVVM1x2SI,RVVMF2x2SI,
234 RVVM1x8SF,RVVMF2x8SF,RVVM1x7SF,RVVMF2x7SF,
235 RVVM1x6SF,RVVMF2x6SF,RVVM1x5SF,RVVMF2x5SF,
236 RVVM2x4SF,RVVM1x4SF,RVVMF2x4SF,RVVM2x3SF,
237 RVVM1x3SF,RVVMF2x3SF,RVVM4x2SF,RVVM2x2SF,
238 RVVM1x2SF,RVVMF2x2SF,
239 RVVM1x8DI,RVVM1x7DI,RVVM1x6DI,RVVM1x5DI,
240 RVVM2x4DI,RVVM1x4DI,RVVM2x3DI,RVVM1x3DI,
241 RVVM4x2DI,RVVM2x2DI,RVVM1x2DI,RVVM1x8DF,
242 RVVM1x7DF,RVVM1x6DF,RVVM1x5DF,RVVM2x4DF,
243 RVVM1x4DF,RVVM2x3DF,RVVM1x3DF,RVVM4x2DF,
33b153ff 244 RVVM2x2DF,RVVM1x2DF,
33b153ff
JZ
245 V1QI,V2QI,V4QI,V8QI,V16QI,V32QI,V64QI,V128QI,V256QI,V512QI,V1024QI,V2048QI,V4096QI,
246 V1HI,V2HI,V4HI,V8HI,V16HI,V32HI,V64HI,V128HI,V256HI,V512HI,V1024HI,V2048HI,
247 V1SI,V2SI,V4SI,V8SI,V16SI,V32SI,V64SI,V128SI,V256SI,V512SI,V1024SI,
248 V1DI,V2DI,V4DI,V8DI,V16DI,V32DI,V64DI,V128DI,V256DI,V512DI,
249 V1HF,V2HF,V4HF,V8HF,V16HF,V32HF,V64HF,V128HF,V256HF,V512HF,V1024HF,V2048HF,
250 V1SF,V2SF,V4SF,V8SF,V16SF,V32SF,V64SF,V128SF,V256SF,V512SF,V1024SF,
6aba1fa7
JZ
251 V1DF,V2DF,V4DF,V8DF,V16DF,V32DF,V64DF,V128DF,V256DF,V512DF,
252 V1BI,V2BI,V4BI,V8BI,V16BI,V32BI,V64BI,V128BI,V256BI,V512BI,V1024BI,V2048BI,V4096BI"
09cae750
PD
253 (const_string "unknown"))
254
255;; True if the main data type is twice the size of a word.
256(define_attr "dword_mode" "no,yes"
257 (cond [(and (eq_attr "mode" "DI,DF")
258 (eq (symbol_ref "TARGET_64BIT") (const_int 0)))
259 (const_string "yes")
260
261 (and (eq_attr "mode" "TI,TF")
262 (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
263 (const_string "yes")]
264 (const_string "no")))
265
8fe75147 266;; ISA attributes.
267(define_attr "ext" "base,f,d,vector"
268 (const_string "base"))
269
270;; True if the extension is enabled.
271(define_attr "ext_enabled" "no,yes"
272 (cond [(eq_attr "ext" "base")
273 (const_string "yes")
7b0073c6 274
8fe75147 275 (and (eq_attr "ext" "f")
276 (match_test "TARGET_HARD_FLOAT"))
277 (const_string "yes")
278
279 (and (eq_attr "ext" "d")
280 (match_test "TARGET_DOUBLE_FLOAT"))
281 (const_string "yes")
282
283 (and (eq_attr "ext" "vector")
284 (match_test "TARGET_VECTOR"))
285 (const_string "yes")
286 ]
287 (const_string "no")))
288
09cae750
PD
289;; Classification of each insn.
290;; branch conditional branch
71f90649
AW
291;; jump unconditional direct jump
292;; jalr unconditional indirect jump
293;; ret various returns, no arguments
09cae750
PD
294;; call unconditional call
295;; load load instruction(s)
296;; fpload floating point load
297;; store store instruction(s)
298;; fpstore floating point store
299;; mtc transfer to coprocessor
300;; mfc transfer from coprocessor
301;; const load constant
302;; arith integer arithmetic instructions
303;; logical integer logical instructions
304;; shift integer shift instructions
305;; slt set less than instructions
7b0073c6 306;; imul integer multiply
09cae750
PD
307;; idiv integer divide
308;; move integer register move (addi rd, rs1, 0)
309;; fmove floating point register move
310;; fadd floating point add/subtract
311;; fmul floating point multiply
312;; fmadd floating point multiply-add
313;; fdiv floating point divide
314;; fcmp floating point compare
315;; fcvt floating point convert
ec217f72
MC
316;; fcvt_i2f integer to floating point convert
317;; fcvt_f2i floating point to integer convert
09cae750
PD
318;; fsqrt floating point square root
319;; multi multiword sequence (or user asm statements)
3895dd76
CM
320;; auipc integer addition to PC
321;; sfb_alu SFB ALU instruction
09cae750 322;; nop no operation
decbf9ec 323;; trap trap instruction
09cae750 324;; ghost an instruction that produces no real code
833e651a 325;; bitmanip bit manipulation instructions
d9df45a6 326;; clmul clmul, clmulh, clmulr
3895dd76
CM
327;; rotate rotation instructions
328;; atomic atomic instructions
8e7ffe12 329;; condmove conditional moves
2c809510 330;; crypto cryptography instructions
d8751d9e 331;; mvpair zc move pair instructions
4074aede 332;; zicond zicond instructions
b8426900 333;; Classification of RVV instructions which will be added to each RVV .md pattern and used by scheduler.
334;; rdvlenb vector byte length vlenb csrr read
335;; rdvl vector length vl csrr read
e682d300 336;; wrvxrm vector fixed-point rounding mode write
e714af12 337;; wrfrm vector floating-point rounding mode write
1627d052 338;; vsetvl vector configuration-setting instrucions
b8426900 339;; 7. Vector Loads and Stores
340;; vlde vector unit-stride load instructions
341;; vste vector unit-stride store instructions
342;; vldm vector unit-stride mask load instructions
343;; vstm vector unit-stride mask store instructions
344;; vlds vector strided load instructions
345;; vsts vector strided store instructions
346;; vldux vector unordered indexed load instructions
347;; vldox vector ordered indexed load instructions
348;; vstux vector unordered indexed store instructions
349;; vstox vector ordered indexed store instructions
350;; vldff vector unit-stride fault-only-first load instructions
351;; vldr vector whole register load instructions
352;; vstr vector whole register store instructions
6313b045
JZZ
353;; vlsegde vector segment unit-stride load instructions
354;; vssegte vector segment unit-stride store instructions
355;; vlsegds vector segment strided load instructions
356;; vssegts vector segment strided store instructions
357;; vlsegdux vector segment unordered indexed load instructions
358;; vlsegdox vector segment ordered indexed load instructions
359;; vssegtux vector segment unordered indexed store instructions
360;; vssegtox vector segment ordered indexed store instructions
361;; vlsegdff vector segment unit-stride fault-only-first load instructions
b8426900 362;; 11. Vector integer arithmetic instructions
363;; vialu vector single-width integer add and subtract and logical nstructions
364;; viwalu vector widening integer add/subtract
365;; vext vector integer extension
366;; vicalu vector arithmetic with carry or borrow instructions
367;; vshift vector single-width bit shift instructions
368;; vnshift vector narrowing integer shift instructions
acb51b5c
JZZ
369;; viminmax vector integer min/max instructions
370;; vicmp vector integer comparison instructions
b8426900 371;; vimul vector single-width integer multiply instructions
372;; vidiv vector single-width integer divide instructions
373;; viwmul vector widening integer multiply instructions
374;; vimuladd vector single-width integer multiply-add instructions
375;; viwmuladd vector widening integer multiply-add instructions
376;; vimerge vector integer merge instructions
377;; vimov vector integer move vector instructions
378;; 12. Vector fixed-point arithmetic instructions
379;; vsalu vector single-width saturating add and subtract and logical instructions
380;; vaalu vector single-width averaging add and subtract and logical instructions
381;; vsmul vector single-width fractional multiply with rounding and saturation instructions
382;; vsshift vector single-width scaling shift instructions
383;; vnclip vector narrowing fixed-point clip instructions
384;; 13. Vector floating-point instructions
385;; vfalu vector single-width floating-point add/subtract instructions
386;; vfwalu vector widening floating-point add/subtract instructions
387;; vfmul vector single-width floating-point multiply instructions
388;; vfdiv vector single-width floating-point divide instructions
389;; vfwmul vector widening floating-point multiply instructions
390;; vfmuladd vector single-width floating-point multiply-add instructions
391;; vfwmuladd vector widening floating-point multiply-add instructions
392;; vfsqrt vector floating-point square-root instructions
393;; vfrecp vector floating-point reciprocal square-root instructions
acb51b5c
JZZ
394;; vfminmax vector floating-point min/max instructions
395;; vfcmp vector floating-point comparison instructions
b8426900 396;; vfsgnj vector floating-point sign-injection instructions
397;; vfclass vector floating-point classify instruction
398;; vfmerge vector floating-point merge instruction
399;; vfmov vector floating-point move instruction
400;; vfcvtitof vector single-width integer to floating-point instruction
401;; vfcvtftoi vector single-width floating-point to integer instruction
402;; vfwcvtitof vector widening integer to floating-point instruction
403;; vfwcvtftoi vector widening floating-point to integer instruction
404;; vfwcvtftof vector widening floating-point to floating-point instruction
405;; vfncvtitof vector narrowing integer to floating-point instruction
406;; vfncvtftoi vector narrowing floating-point to integer instruction
407;; vfncvtftof vector narrowing floating-point to floating-point instruction
408;; 14. Vector reduction operations
409;; vired vector single-width integer reduction instructions
410;; viwred vector widening integer reduction instructions
c878c658 411;; vfredu vector single-width floating-point un-ordered reduction instruction
b8426900 412;; vfredo vector single-width floating-point ordered reduction instruction
1bff101b 413;; vfwredu vector widening floating-point un-ordered reduction instruction
b8426900 414;; vfwredo vector widening floating-point ordered reduction instruction
415;; 15. Vector mask instructions
416;; vmalu vector mask-register logical instructions
417;; vmpop vector mask population count
418;; vmffs vector find-first-set mask bit
419;; vmsfs vector set mask bit
420;; vmiota vector iota
421;; vmidx vector element index instruction
422;; 16. Vector permutation instructions
1bff101b
JZZ
423;; vimovvx integer scalar move instructions
424;; vimovxv integer scalar move instructions
425;; vfmovvf floating-point scalar move instructions
426;; vfmovfv floating-point scalar move instructions
427;; vslideup vector slide instructions
428;; vslidedown vector slide instructions
429;; vislide1up vector slide instructions
430;; vislide1down vector slide instructions
431;; vfslide1up vector slide instructions
432;; vfslide1down vector slide instructions
433;; vgather vector register gather instructions
434;; vcompress vector compress instruction
435;; vmov whole vector register move
4b70c7c8 436;; vector unknown vector instruction
d3d6a96d
FW
437;; 17. Crypto Vector instructions
438;; vandn crypto vector bitwise and-not instructions
439;; vbrev crypto vector reverse bits in elements instructions
440;; vbrev8 crypto vector reverse bits in bytes instructions
441;; vrev8 crypto vector reverse bytes instructions
442;; vclz crypto vector count leading Zeros instructions
443;; vctz crypto vector count lrailing Zeros instructions
444;; vrol crypto vector rotate left instructions
445;; vror crypto vector rotate right instructions
446;; vwsll crypto vector widening shift left logical instructions
447;; vclmul crypto vector carry-less multiply - return low half instructions
448;; vclmulh crypto vector carry-less multiply - return high half instructions
449;; vghsh crypto vector add-multiply over GHASH Galois-Field instructions
450;; vgmul crypto vector multiply over GHASH Galois-Field instrumctions
451;; vaesef crypto vector AES final-round encryption instructions
452;; vaesem crypto vector AES middle-round encryption instructions
453;; vaesdf crypto vector AES final-round decryption instructions
454;; vaesdm crypto vector AES middle-round decryption instructions
455;; vaeskf1 crypto vector AES-128 Forward KeySchedule generation instructions
456;; vaeskf2 crypto vector AES-256 Forward KeySchedule generation instructions
457;; vaesz crypto vector AES round zero encryption/decryption instructions
458;; vsha2ms crypto vector SHA-2 message schedule instructions
459;; vsha2ch crypto vector SHA-2 two rounds of compression instructions
460;; vsha2cl crypto vector SHA-2 two rounds of compression instructions
461;; vsm4k crypto vector SM4 KeyExpansion instructions
462;; vsm4r crypto vector SM4 Rounds instructions
463;; vsm3me crypto vector SM3 Message Expansion instructions
464;; vsm3c crypto vector SM3 Compression instructions
09cae750 465(define_attr "type"
71f90649 466 "unknown,branch,jump,jalr,ret,call,load,fpload,store,fpstore,
09cae750 467 mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
ec217f72
MC
468 fmadd,fdiv,fcmp,fcvt,fcvt_i2f,fcvt_f2i,fsqrt,multi,auipc,sfb_alu,nop,trap,
469 ghost,bitmanip,rotate,clmul,min,max,minu,maxu,clz,ctz,cpop,
57b95223 470 atomic,condmove,crypto,mvpair,zicond,rdvlenb,rdvl,wrvxrm,wrfrm,
fd4829dd 471 rdfrm,vsetvl,vsetvl_pre,vlde,vste,vldm,vstm,vlds,vsts,
b8426900 472 vldux,vldox,vstux,vstox,vldff,vldr,vstr,
6313b045 473 vlsegde,vssegte,vlsegds,vssegts,vlsegdux,vlsegdox,vssegtux,vssegtox,vlsegdff,
acb51b5c 474 vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,
b8426900 475 vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge,vimov,
476 vsalu,vaalu,vsmul,vsshift,vnclip,
477 vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp,
acb51b5c 478 vfcmp,vfminmax,vfsgnj,vfclass,vfmerge,vfmov,
b8426900 479 vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi,
480 vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof,
c878c658 481 vired,viwred,vfredu,vfredo,vfwredu,vfwredo,
b8426900 482 vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,vfmovvf,vfmovfv,
1bff101b 483 vslideup,vslidedown,vislide1up,vislide1down,vfslide1up,vfslide1down,
d3d6a96d
FW
484 vgather,vcompress,vmov,vector,vandn,vbrev,vbrev8,vrev8,vclz,vctz,vcpop,vrol,vror,vwsll,
485 vclmul,vclmulh,vghsh,vgmul,vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz,
486 vsha2ms,vsha2ch,vsha2cl,vsm4k,vsm4r,vsm3me,vsm3c"
09cae750
PD
487 (cond [(eq_attr "got" "load") (const_string "load")
488
489 ;; If a doubleword move uses these expensive instructions,
490 ;; it is usually better to schedule them in the same way
491 ;; as the singleword form, rather than as "multi".
492 (eq_attr "move_type" "load") (const_string "load")
493 (eq_attr "move_type" "fpload") (const_string "fpload")
494 (eq_attr "move_type" "store") (const_string "store")
495 (eq_attr "move_type" "fpstore") (const_string "fpstore")
496 (eq_attr "move_type" "mtc") (const_string "mtc")
497 (eq_attr "move_type" "mfc") (const_string "mfc")
498
499 ;; These types of move are always single insns.
500 (eq_attr "move_type" "fmove") (const_string "fmove")
501 (eq_attr "move_type" "arith") (const_string "arith")
502 (eq_attr "move_type" "logical") (const_string "logical")
503 (eq_attr "move_type" "andi") (const_string "logical")
504
505 ;; These types of move are always split.
506 (eq_attr "move_type" "shift_shift")
507 (const_string "multi")
508
509 ;; These types of move are split for doubleword modes only.
510 (and (eq_attr "move_type" "move,const")
511 (eq_attr "dword_mode" "yes"))
512 (const_string "multi")
513 (eq_attr "move_type" "move") (const_string "move")
8fe75147 514 (eq_attr "move_type" "const") (const_string "const")
515 (eq_attr "move_type" "rdvlenb") (const_string "rdvlenb")]
09cae750
PD
516 (const_string "unknown")))
517
cb33116a
PL
518;; True if the float point vector is disabled.
519(define_attr "fp_vector_disabled" "no,yes"
520 (cond [
521 (and (eq_attr "type" "vfmov,vfalu,vfmul,vfdiv,
522 vfwalu,vfwmul,vfmuladd,vfwmuladd,
523 vfsqrt,vfrecp,vfminmax,vfsgnj,vfcmp,
524 vfclass,vfmerge,
525 vfncvtitof,vfwcvtftoi,vfcvtftoi,vfcvtitof,
526 vfredo,vfredu,vfwredo,vfwredu,
527 vfslide1up,vfslide1down")
879c52c9 528 (and (eq_attr "mode" "RVVM8HF,RVVM4HF,RVVM2HF,RVVM1HF,RVVMF2HF,RVVMF4HF")
cb33116a
PL
529 (match_test "!TARGET_ZVFH")))
530 (const_string "yes")
531
532 ;; The mode records as QI for the FP16 <=> INT8 instruction.
533 (and (eq_attr "type" "vfncvtftoi,vfwcvtitof")
879c52c9 534 (and (eq_attr "mode" "RVVM4QI,RVVM2QI,RVVM1QI,RVVMF2QI,RVVMF4QI,RVVMF8QI")
cb33116a
PL
535 (match_test "!TARGET_ZVFH")))
536 (const_string "yes")
537 ]
538 (const_string "no")))
539
cdf4729f
JSJ
540;; This attribute marks the alternatives not matching the constraints
541;; described in spec as disabled.
542(define_attr "spec_restriction" "none,thv,rvv"
543 (const_string "none"))
544
545(define_attr "spec_restriction_disabled" "no,yes"
546 (cond [(eq_attr "spec_restriction" "none")
547 (const_string "no")
548
549 (and (eq_attr "spec_restriction" "thv")
550 (match_test "TARGET_XTHEADVECTOR"))
551 (const_string "yes")
552
553 (and (eq_attr "spec_restriction" "rvv")
554 (match_test "TARGET_VECTOR && !TARGET_XTHEADVECTOR"))
555 (const_string "yes")
556 ]
557 (const_string "no")))
558
cb33116a
PL
559;; Attribute to control enable or disable instructions.
560(define_attr "enabled" "no,yes"
561 (cond [
562 (eq_attr "ext_enabled" "no")
563 (const_string "no")
564
565 (eq_attr "fp_vector_disabled" "yes")
566 (const_string "no")
bdad036d 567
cdf4729f
JSJ
568 (eq_attr "spec_restriction_disabled" "yes")
569 (const_string "no")
cb33116a
PL
570 ]
571 (const_string "yes")))
572
09cae750
PD
573;; Length of instruction in bytes.
574(define_attr "length" ""
575 (cond [
71f90649 576 ;; Branches further than +/- 1 MiB require three instructions.
09cae750
PD
577 ;; Branches further than +/- 4 KiB require two instructions.
578 (eq_attr "type" "branch")
c8bff398
MR
579 (if_then_else (and (le (minus (match_dup 0) (pc))
580 (const_int 4088))
581 (le (minus (pc) (match_dup 0))
582 (const_int 4092)))
583 (const_int 4)
584 (if_then_else (and (le (minus (match_dup 0) (pc))
585 (const_int 1048568))
586 (le (minus (pc) (match_dup 0))
587 (const_int 1048572)))
588 (const_int 8)
589 (const_int 12)))
71f90649
AW
590
591 ;; Jumps further than +/- 1 MiB require two instructions.
592 (eq_attr "type" "jump")
c8bff398
MR
593 (if_then_else (and (le (minus (match_dup 0) (pc))
594 (const_int 1048568))
595 (le (minus (pc) (match_dup 0))
596 (const_int 1048572)))
597 (const_int 4)
598 (const_int 8))
09cae750
PD
599
600 ;; Conservatively assume calls take two instructions (AUIPC + JALR).
601 ;; The linker will opportunistically relax the sequence to JAL.
602 (eq_attr "type" "call") (const_int 8)
603
604 ;; "Ghost" instructions occupy no space.
605 (eq_attr "type" "ghost") (const_int 0)
606
607 (eq_attr "got" "load") (const_int 8)
608
09cae750
PD
609 ;; SHIFT_SHIFTs are decomposed into two separate instructions.
610 (eq_attr "move_type" "shift_shift")
611 (const_int 8)
612
613 ;; Check for doubleword moves that are decomposed into two
614 ;; instructions.
615 (and (eq_attr "move_type" "mtc,mfc,move")
616 (eq_attr "dword_mode" "yes"))
617 (const_int 8)
618
619 ;; Doubleword CONST{,N} moves are split into two word
620 ;; CONST{,N} moves.
621 (and (eq_attr "move_type" "const")
622 (eq_attr "dword_mode" "yes"))
623 (symbol_ref "riscv_split_const_insns (operands[1]) * 4")
624
625 ;; Otherwise, constants, loads and stores are handled by external
626 ;; routines.
627 (eq_attr "move_type" "load,fpload")
628 (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4")
629 (eq_attr "move_type" "store,fpstore")
630 (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4")
631 ] (const_int 4)))
632
633;; Is copying of this instruction disallowed?
634(define_attr "cannot_copy" "no,yes" (const_string "no"))
635
88108b27
AW
636;; Microarchitectures we know how to tune for.
637;; Keep this in sync with enum riscv_microarchitecture.
638(define_attr "tune"
d91a0cee 639 "generic,sifive_7,sifive_p400,sifive_p600,xiangshan,generic_ooo"
88108b27
AW
640 (const (symbol_ref "((enum attr_tune) riscv_microarchitecture)")))
641
09cae750
PD
642;; Describe a user's asm statement.
643(define_asm_attributes
644 [(set_attr "type" "multi")])
645
09cae750
PD
646;; Ghost instructions produce no real code and introduce no hazards.
647;; They exist purely to express an effect on dataflow.
648(define_insn_reservation "ghost" 0
649 (eq_attr "type" "ghost")
650 "nothing")
651
652;;
653;; ....................
654;;
655;; ADDITION
656;;
657;; ....................
658;;
659
660(define_insn "add<mode>3"
248710c4
KC
661 [(set (match_operand:ANYF 0 "register_operand" "=f")
662 (plus:ANYF (match_operand:ANYF 1 "register_operand" " f")
663 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 664 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
665 "fadd.<fmt>\t%0,%1,%2"
666 [(set_attr "type" "fadd")
667 (set_attr "mode" "<UNITMODE>")])
668
99bfdb07 669(define_insn "*addsi3"
248710c4
KC
670 [(set (match_operand:SI 0 "register_operand" "=r,r")
671 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
672 (match_operand:SI 2 "arith_operand" " r,I")))]
09cae750 673 ""
473d7aad 674 "add%i2%~\t%0,%1,%2"
09cae750
PD
675 [(set_attr "type" "arith")
676 (set_attr "mode" "SI")])
677
99bfdb07
JL
678(define_expand "addsi3"
679 [(set (match_operand:SI 0 "register_operand" "=r,r")
680 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
681 (match_operand:SI 2 "arith_operand" " r,I")))]
682 ""
683{
684 if (TARGET_64BIT)
685 {
686 rtx t = gen_reg_rtx (DImode);
687 emit_insn (gen_addsi3_extended (t, operands[1], operands[2]));
688 t = gen_lowpart (SImode, t);
689 SUBREG_PROMOTED_VAR_P (t) = 1;
690 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
691 emit_move_insn (operands[0], t);
692 DONE;
693 }
694})
695
09cae750 696(define_insn "adddi3"
248710c4
KC
697 [(set (match_operand:DI 0 "register_operand" "=r,r")
698 (plus:DI (match_operand:DI 1 "register_operand" " r,r")
699 (match_operand:DI 2 "arith_operand" " r,I")))]
09cae750 700 "TARGET_64BIT"
0791ac18 701 "add%i2\t%0,%1,%2"
09cae750
PD
702 [(set_attr "type" "arith")
703 (set_attr "mode" "DI")])
704
6efd040c
L
705(define_expand "addv<mode>4"
706 [(set (match_operand:GPR 0 "register_operand" "=r,r")
707 (plus:GPR (match_operand:GPR 1 "register_operand" " r,r")
708 (match_operand:GPR 2 "arith_operand" " r,I")))
709 (label_ref (match_operand 3 "" ""))]
710 ""
711{
712 if (TARGET_64BIT && <MODE>mode == SImode)
713 {
714 rtx t3 = gen_reg_rtx (DImode);
715 rtx t4 = gen_reg_rtx (DImode);
716 rtx t5 = gen_reg_rtx (DImode);
717 rtx t6 = gen_reg_rtx (DImode);
718
99bfdb07 719 riscv_emit_binary (PLUS, operands[0], operands[1], operands[2]);
6efd040c
L
720 if (GET_CODE (operands[1]) != CONST_INT)
721 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
722 else
723 t4 = operands[1];
724 if (GET_CODE (operands[2]) != CONST_INT)
725 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
726 else
727 t5 = operands[2];
728 emit_insn (gen_adddi3 (t3, t4, t5));
729 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
730
731 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
732 }
733 else
734 {
735 rtx t3 = gen_reg_rtx (<MODE>mode);
736 rtx t4 = gen_reg_rtx (<MODE>mode);
737
738 emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
739 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[2], const0_rtx);
740 emit_insn (gen_cstore<mode>4 (t3, cmp1, operands[2], const0_rtx));
741 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[0], operands[1]);
742
743 emit_insn (gen_cstore<mode>4 (t4, cmp2, operands[0], operands[1]));
744 riscv_expand_conditional_branch (operands[3], NE, t3, t4);
745 }
746 DONE;
747})
748
749(define_expand "uaddv<mode>4"
750 [(set (match_operand:GPR 0 "register_operand" "=r,r")
751 (plus:GPR (match_operand:GPR 1 "register_operand" " r,r")
752 (match_operand:GPR 2 "arith_operand" " r,I")))
753 (label_ref (match_operand 3 "" ""))]
754 ""
755{
756 if (TARGET_64BIT && <MODE>mode == SImode)
757 {
758 rtx t3 = gen_reg_rtx (DImode);
759 rtx t4 = gen_reg_rtx (DImode);
760
761 if (GET_CODE (operands[1]) != CONST_INT)
762 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
763 else
764 t3 = operands[1];
99bfdb07 765 riscv_emit_binary (PLUS, operands[0], operands[1], operands[2]);
6efd040c
L
766 emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
767
768 riscv_expand_conditional_branch (operands[3], LTU, t4, t3);
769 }
770 else
771 {
772 emit_insn (gen_add3_insn (operands[0], operands[1], operands[2]));
773 riscv_expand_conditional_branch (operands[3], LTU, operands[0],
774 operands[1]);
775 }
776
777 DONE;
778})
779
99bfdb07 780(define_insn "addsi3_extended"
248710c4 781 [(set (match_operand:DI 0 "register_operand" "=r,r")
09cae750 782 (sign_extend:DI
248710c4
KC
783 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
784 (match_operand:SI 2 "arith_operand" " r,I"))))]
09cae750 785 "TARGET_64BIT"
0791ac18 786 "add%i2w\t%0,%1,%2"
09cae750
PD
787 [(set_attr "type" "arith")
788 (set_attr "mode" "SI")])
789
790(define_insn "*addsi3_extended2"
248710c4 791 [(set (match_operand:DI 0 "register_operand" "=r,r")
09cae750 792 (sign_extend:DI
7ac4dfec
MC
793 (match_operator:SI 3 "subreg_lowpart_operator"
794 [(plus:DI (match_operand:DI 1 "register_operand" " r,r")
795 (match_operand:DI 2 "arith_operand" " r,I"))])))]
09cae750 796 "TARGET_64BIT"
0791ac18 797 "add%i2w\t%0,%1,%2"
09cae750
PD
798 [(set_attr "type" "arith")
799 (set_attr "mode" "SI")])
800
801;;
802;; ....................
803;;
804;; SUBTRACTION
805;;
806;; ....................
807;;
808
809(define_insn "sub<mode>3"
248710c4
KC
810 [(set (match_operand:ANYF 0 "register_operand" "=f")
811 (minus:ANYF (match_operand:ANYF 1 "register_operand" " f")
812 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 813 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
814 "fsub.<fmt>\t%0,%1,%2"
815 [(set_attr "type" "fadd")
816 (set_attr "mode" "<UNITMODE>")])
817
818(define_insn "subdi3"
248710c4
KC
819 [(set (match_operand:DI 0 "register_operand" "= r")
820 (minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
821 (match_operand:DI 2 "register_operand" " r")))]
09cae750
PD
822 "TARGET_64BIT"
823 "sub\t%0,%z1,%2"
824 [(set_attr "type" "arith")
825 (set_attr "mode" "DI")])
826
99bfdb07 827(define_insn "*subsi3"
248710c4
KC
828 [(set (match_operand:SI 0 "register_operand" "= r")
829 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
830 (match_operand:SI 2 "register_operand" " r")))]
09cae750 831 ""
473d7aad 832 "sub%~\t%0,%z1,%2"
09cae750
PD
833 [(set_attr "type" "arith")
834 (set_attr "mode" "SI")])
835
99bfdb07
JL
836(define_expand "subsi3"
837 [(set (match_operand:SI 0 "register_operand" "= r")
838 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
839 (match_operand:SI 2 "register_operand" " r")))]
840 ""
841{
842 if (TARGET_64BIT)
843 {
844 rtx t = gen_reg_rtx (DImode);
845 emit_insn (gen_subsi3_extended (t, operands[1], operands[2]));
846 t = gen_lowpart (SImode, t);
847 SUBREG_PROMOTED_VAR_P (t) = 1;
848 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
849 emit_move_insn (operands[0], t);
850 DONE;
851 }
852})
853
6efd040c
L
854(define_expand "subv<mode>4"
855 [(set (match_operand:GPR 0 "register_operand" "= r")
856 (minus:GPR (match_operand:GPR 1 "reg_or_0_operand" " rJ")
857 (match_operand:GPR 2 "register_operand" " r")))
858 (label_ref (match_operand 3 "" ""))]
859 ""
860{
861 if (TARGET_64BIT && <MODE>mode == SImode)
862 {
863 rtx t3 = gen_reg_rtx (DImode);
864 rtx t4 = gen_reg_rtx (DImode);
865 rtx t5 = gen_reg_rtx (DImode);
866 rtx t6 = gen_reg_rtx (DImode);
867
99bfdb07 868 riscv_emit_binary (MINUS, operands[0], operands[1], operands[2]);
6efd040c
L
869 if (GET_CODE (operands[1]) != CONST_INT)
870 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
871 else
872 t4 = operands[1];
873 if (GET_CODE (operands[2]) != CONST_INT)
874 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
875 else
876 t5 = operands[2];
877 emit_insn (gen_subdi3 (t3, t4, t5));
878 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
879
880 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
881 }
882 else
883 {
884 rtx t3 = gen_reg_rtx (<MODE>mode);
885 rtx t4 = gen_reg_rtx (<MODE>mode);
886
887 emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
888
889 rtx cmp1 = gen_rtx_LT (<MODE>mode, operands[2], const0_rtx);
890 emit_insn (gen_cstore<mode>4 (t3, cmp1, operands[2], const0_rtx));
891
892 rtx cmp2 = gen_rtx_LT (<MODE>mode, operands[1], operands[0]);
893 emit_insn (gen_cstore<mode>4 (t4, cmp2, operands[1], operands[0]));
894
895 riscv_expand_conditional_branch (operands[3], NE, t3, t4);
896 }
897
898 DONE;
899})
900
901(define_expand "usubv<mode>4"
902 [(set (match_operand:GPR 0 "register_operand" "= r")
903 (minus:GPR (match_operand:GPR 1 "reg_or_0_operand" " rJ")
904 (match_operand:GPR 2 "register_operand" " r")))
905 (label_ref (match_operand 3 "" ""))]
906 ""
907{
908 if (TARGET_64BIT && <MODE>mode == SImode)
909 {
910 rtx t3 = gen_reg_rtx (DImode);
911 rtx t4 = gen_reg_rtx (DImode);
912
913 if (GET_CODE (operands[1]) != CONST_INT)
914 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
915 else
916 t3 = operands[1];
99bfdb07 917 riscv_emit_binary (MINUS, operands[0], operands[1], operands[2]);
6efd040c
L
918 emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
919
920 riscv_expand_conditional_branch (operands[3], LTU, t3, t4);
921 }
922 else
923 {
924 emit_insn (gen_sub3_insn (operands[0], operands[1], operands[2]));
925 riscv_expand_conditional_branch (operands[3], LTU, operands[1],
926 operands[0]);
927 }
928
929 DONE;
930})
931
932
99bfdb07 933(define_insn "subsi3_extended"
248710c4 934 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 935 (sign_extend:DI
248710c4
KC
936 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
937 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
938 "TARGET_64BIT"
939 "subw\t%0,%z1,%2"
940 [(set_attr "type" "arith")
941 (set_attr "mode" "SI")])
942
943(define_insn "*subsi3_extended2"
01414d53 944 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 945 (sign_extend:DI
7ac4dfec
MC
946 (match_operator:SI 3 "subreg_lowpart_operator"
947 [(minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ")
948 (match_operand:DI 2 "register_operand" " r"))])))]
09cae750
PD
949 "TARGET_64BIT"
950 "subw\t%0,%z1,%2"
951 [(set_attr "type" "arith")
952 (set_attr "mode" "SI")])
953
01414d53
JW
954(define_insn "negdi2"
955 [(set (match_operand:DI 0 "register_operand" "=r")
956 (neg:DI (match_operand:DI 1 "register_operand" " r")))]
957 "TARGET_64BIT"
958 "neg\t%0,%1"
959 [(set_attr "type" "arith")
960 (set_attr "mode" "DI")])
961
99bfdb07 962(define_insn "*negsi2"
01414d53
JW
963 [(set (match_operand:SI 0 "register_operand" "=r")
964 (neg:SI (match_operand:SI 1 "register_operand" " r")))]
965 ""
473d7aad 966 "neg%~\t%0,%1"
01414d53
JW
967 [(set_attr "type" "arith")
968 (set_attr "mode" "SI")])
969
99bfdb07
JL
970(define_expand "negsi2"
971 [(set (match_operand:SI 0 "register_operand" "=r")
972 (neg:SI (match_operand:SI 1 "register_operand" " r")))]
973 ""
974{
975 if (TARGET_64BIT)
976 {
977 rtx t = gen_reg_rtx (DImode);
978 emit_insn (gen_negsi2_extended (t, operands[1]));
979 t = gen_lowpart (SImode, t);
980 SUBREG_PROMOTED_VAR_P (t) = 1;
981 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
982 emit_move_insn (operands[0], t);
983 DONE;
984 }
985})
986
987(define_insn "negsi2_extended"
01414d53
JW
988 [(set (match_operand:DI 0 "register_operand" "=r")
989 (sign_extend:DI
990 (neg:SI (match_operand:SI 1 "register_operand" " r"))))]
991 "TARGET_64BIT"
992 "negw\t%0,%1"
993 [(set_attr "type" "arith")
994 (set_attr "mode" "SI")])
995
996(define_insn "*negsi2_extended2"
997 [(set (match_operand:DI 0 "register_operand" "=r")
998 (sign_extend:DI
7ac4dfec
MC
999 (match_operator:SI 2 "subreg_lowpart_operator"
1000 [(neg:DI (match_operand:DI 1 "register_operand" " r"))])))]
01414d53
JW
1001 "TARGET_64BIT"
1002 "negw\t%0,%1"
1003 [(set_attr "type" "arith")
1004 (set_attr "mode" "SI")])
1005
09cae750
PD
1006;;
1007;; ....................
1008;;
1009;; MULTIPLICATION
1010;;
1011;; ....................
1012;;
1013
1014(define_insn "mul<mode>3"
248710c4
KC
1015 [(set (match_operand:ANYF 0 "register_operand" "=f")
1016 (mult:ANYF (match_operand:ANYF 1 "register_operand" " f")
1017 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 1018 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1019 "fmul.<fmt>\t%0,%1,%2"
1020 [(set_attr "type" "fmul")
1021 (set_attr "mode" "<UNITMODE>")])
1022
99bfdb07 1023(define_insn "*mulsi3"
248710c4
KC
1024 [(set (match_operand:SI 0 "register_operand" "=r")
1025 (mult:SI (match_operand:SI 1 "register_operand" " r")
1026 (match_operand:SI 2 "register_operand" " r")))]
77e8e405 1027 "TARGET_ZMMUL || TARGET_MUL"
473d7aad 1028 "mul%~\t%0,%1,%2"
09cae750
PD
1029 [(set_attr "type" "imul")
1030 (set_attr "mode" "SI")])
1031
99bfdb07
JL
1032(define_expand "mulsi3"
1033 [(set (match_operand:SI 0 "register_operand" "=r")
1034 (mult:SI (match_operand:SI 1 "register_operand" " r")
1035 (match_operand:SI 2 "register_operand" " r")))]
1036 "TARGET_ZMMUL || TARGET_MUL"
1037{
1038 if (TARGET_64BIT)
1039 {
1040 rtx t = gen_reg_rtx (DImode);
1041 emit_insn (gen_mulsi3_extended (t, operands[1], operands[2]));
1042 t = gen_lowpart (SImode, t);
1043 SUBREG_PROMOTED_VAR_P (t) = 1;
1044 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
1045 emit_move_insn (operands[0], t);
1046 DONE;
1047 }
1048})
1049
09cae750 1050(define_insn "muldi3"
248710c4
KC
1051 [(set (match_operand:DI 0 "register_operand" "=r")
1052 (mult:DI (match_operand:DI 1 "register_operand" " r")
1053 (match_operand:DI 2 "register_operand" " r")))]
ae97ba1e 1054 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
1055 "mul\t%0,%1,%2"
1056 [(set_attr "type" "imul")
1057 (set_attr "mode" "DI")])
1058
6efd040c
L
1059(define_expand "mulv<mode>4"
1060 [(set (match_operand:GPR 0 "register_operand" "=r")
1061 (mult:GPR (match_operand:GPR 1 "register_operand" " r")
1062 (match_operand:GPR 2 "register_operand" " r")))
1063 (label_ref (match_operand 3 "" ""))]
77e8e405 1064 "TARGET_ZMMUL || TARGET_MUL"
6efd040c
L
1065{
1066 if (TARGET_64BIT && <MODE>mode == SImode)
1067 {
1068 rtx t3 = gen_reg_rtx (DImode);
1069 rtx t4 = gen_reg_rtx (DImode);
1070 rtx t5 = gen_reg_rtx (DImode);
1071 rtx t6 = gen_reg_rtx (DImode);
1072
1073 if (GET_CODE (operands[1]) != CONST_INT)
1074 emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
1075 else
1076 t4 = operands[1];
1077 if (GET_CODE (operands[2]) != CONST_INT)
1078 emit_insn (gen_extend_insn (t5, operands[2], DImode, SImode, 0));
1079 else
1080 t5 = operands[2];
1081 emit_insn (gen_muldi3 (t3, t4, t5));
1082
1083 emit_move_insn (operands[0], gen_lowpart (SImode, t3));
1084 emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
1085
1086 riscv_expand_conditional_branch (operands[3], NE, t6, t3);
1087 }
1088 else
1089 {
1090 rtx hp = gen_reg_rtx (<MODE>mode);
1091 rtx lp = gen_reg_rtx (<MODE>mode);
1092
68c081bb 1093 emit_insn (gen_smul<mode>3_highpart (hp, operands[1], operands[2]));
6efd040c 1094 emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
99bfdb07
JL
1095 riscv_emit_binary (ASHIFTRT, lp, operands[0],
1096 GEN_INT (BITS_PER_WORD - 1));
6efd040c
L
1097
1098 riscv_expand_conditional_branch (operands[3], NE, hp, lp);
1099 }
1100
1101 DONE;
1102})
1103
1104(define_expand "umulv<mode>4"
1105 [(set (match_operand:GPR 0 "register_operand" "=r")
1106 (mult:GPR (match_operand:GPR 1 "register_operand" " r")
1107 (match_operand:GPR 2 "register_operand" " r")))
1108 (label_ref (match_operand 3 "" ""))]
77e8e405 1109 "TARGET_ZMMUL || TARGET_MUL"
6efd040c
L
1110{
1111 if (TARGET_64BIT && <MODE>mode == SImode)
1112 {
1113 rtx t3 = gen_reg_rtx (DImode);
1114 rtx t4 = gen_reg_rtx (DImode);
1115 rtx t5 = gen_reg_rtx (DImode);
1116 rtx t6 = gen_reg_rtx (DImode);
1117 rtx t7 = gen_reg_rtx (DImode);
1118 rtx t8 = gen_reg_rtx (DImode);
1119
1120 if (GET_CODE (operands[1]) != CONST_INT)
1121 emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
1122 else
1123 t3 = operands[1];
1124 if (GET_CODE (operands[2]) != CONST_INT)
1125 emit_insn (gen_extend_insn (t4, operands[2], DImode, SImode, 0));
1126 else
1127 t4 = operands[2];
1128
1129 emit_insn (gen_ashldi3 (t5, t3, GEN_INT (32)));
1130 emit_insn (gen_ashldi3 (t6, t4, GEN_INT (32)));
1131 emit_insn (gen_umuldi3_highpart (t7, t5, t6));
1132 emit_move_insn (operands[0], gen_lowpart (SImode, t7));
1133 emit_insn (gen_lshrdi3 (t8, t7, GEN_INT (32)));
1134
1135 riscv_expand_conditional_branch (operands[3], NE, t8, const0_rtx);
1136 }
1137 else
1138 {
1139 rtx hp = gen_reg_rtx (<MODE>mode);
1140
1141 emit_insn (gen_umul<mode>3_highpart (hp, operands[1], operands[2]));
1142 emit_insn (gen_mul<mode>3 (operands[0], operands[1], operands[2]));
1143
1144 riscv_expand_conditional_branch (operands[3], NE, hp, const0_rtx);
1145 }
1146
1147 DONE;
1148})
1149
99bfdb07 1150(define_insn "mulsi3_extended"
248710c4 1151 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 1152 (sign_extend:DI
248710c4
KC
1153 (mult:SI (match_operand:SI 1 "register_operand" " r")
1154 (match_operand:SI 2 "register_operand" " r"))))]
77e8e405 1155 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
1156 "mulw\t%0,%1,%2"
1157 [(set_attr "type" "imul")
1158 (set_attr "mode" "SI")])
1159
1160(define_insn "*mulsi3_extended2"
248710c4 1161 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 1162 (sign_extend:DI
7ac4dfec
MC
1163 (match_operator:SI 3 "subreg_lowpart_operator"
1164 [(mult:DI (match_operand:DI 1 "register_operand" " r")
1165 (match_operand:DI 2 "register_operand" " r"))])))]
77e8e405 1166 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
1167 "mulw\t%0,%1,%2"
1168 [(set_attr "type" "imul")
1169 (set_attr "mode" "SI")])
1170
1171;;
1172;; ........................
1173;;
1174;; MULTIPLICATION HIGH-PART
1175;;
1176;; ........................
1177;;
1178
1179
1180(define_expand "<u>mulditi3"
248710c4 1181 [(set (match_operand:TI 0 "register_operand")
09cae750
PD
1182 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
1183 (any_extend:TI (match_operand:DI 2 "register_operand"))))]
77e8e405 1184 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
1185{
1186 rtx low = gen_reg_rtx (DImode);
1187 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
1188
1189 rtx high = gen_reg_rtx (DImode);
68c081bb 1190 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2]));
09cae750
PD
1191
1192 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1193 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1194 DONE;
1195})
1196
68c081bb 1197(define_insn "<su>muldi3_highpart"
248710c4 1198 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750
PD
1199 (truncate:DI
1200 (lshiftrt:TI
1201 (mult:TI (any_extend:TI
248710c4 1202 (match_operand:DI 1 "register_operand" " r"))
09cae750 1203 (any_extend:TI
248710c4 1204 (match_operand:DI 2 "register_operand" " r")))
09cae750 1205 (const_int 64))))]
77e8e405 1206 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
1207 "mulh<u>\t%0,%1,%2"
1208 [(set_attr "type" "imul")
1209 (set_attr "mode" "DI")])
1210
1211(define_expand "usmulditi3"
248710c4 1212 [(set (match_operand:TI 0 "register_operand")
09cae750
PD
1213 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand"))
1214 (sign_extend:TI (match_operand:DI 2 "register_operand"))))]
77e8e405 1215 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
1216{
1217 rtx low = gen_reg_rtx (DImode);
1218 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
1219
1220 rtx high = gen_reg_rtx (DImode);
1221 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2]));
1222
1223 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
1224 emit_move_insn (gen_highpart (DImode, operands[0]), high);
1225 DONE;
1226})
1227
1228(define_insn "usmuldi3_highpart"
248710c4 1229 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750
PD
1230 (truncate:DI
1231 (lshiftrt:TI
1232 (mult:TI (zero_extend:TI
248710c4 1233 (match_operand:DI 1 "register_operand" "r"))
09cae750 1234 (sign_extend:TI
248710c4 1235 (match_operand:DI 2 "register_operand" " r")))
09cae750 1236 (const_int 64))))]
77e8e405 1237 "(TARGET_ZMMUL || TARGET_MUL) && TARGET_64BIT"
09cae750
PD
1238 "mulhsu\t%0,%2,%1"
1239 [(set_attr "type" "imul")
1240 (set_attr "mode" "DI")])
1241
1242(define_expand "<u>mulsidi3"
248710c4 1243 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 1244 (mult:DI (any_extend:DI
248710c4 1245 (match_operand:SI 1 "register_operand" " r"))
09cae750 1246 (any_extend:DI
248710c4 1247 (match_operand:SI 2 "register_operand" " r"))))]
77e8e405 1248 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
09cae750
PD
1249{
1250 rtx temp = gen_reg_rtx (SImode);
99bfdb07 1251 riscv_emit_binary (MULT, temp, operands[1], operands[2]);
68c081bb 1252 emit_insn (gen_<su>mulsi3_highpart (riscv_subword (operands[0], true),
09cae750
PD
1253 operands[1], operands[2]));
1254 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
1255 DONE;
1256})
1257
68c081bb 1258(define_insn "<su>mulsi3_highpart"
248710c4 1259 [(set (match_operand:SI 0 "register_operand" "=r")
09cae750
PD
1260 (truncate:SI
1261 (lshiftrt:DI
1262 (mult:DI (any_extend:DI
248710c4 1263 (match_operand:SI 1 "register_operand" " r"))
09cae750 1264 (any_extend:DI
248710c4 1265 (match_operand:SI 2 "register_operand" " r")))
09cae750 1266 (const_int 32))))]
77e8e405 1267 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
09cae750
PD
1268 "mulh<u>\t%0,%1,%2"
1269 [(set_attr "type" "imul")
1270 (set_attr "mode" "SI")])
1271
1272
1273(define_expand "usmulsidi3"
248710c4 1274 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 1275 (mult:DI (zero_extend:DI
248710c4 1276 (match_operand:SI 1 "register_operand" " r"))
09cae750 1277 (sign_extend:DI
248710c4 1278 (match_operand:SI 2 "register_operand" " r"))))]
77e8e405 1279 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
09cae750
PD
1280{
1281 rtx temp = gen_reg_rtx (SImode);
99bfdb07 1282 riscv_emit_binary (MULT, temp, operands[1], operands[2]);
09cae750
PD
1283 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true),
1284 operands[1], operands[2]));
1285 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
1286 DONE;
1287})
1288
1289(define_insn "usmulsi3_highpart"
248710c4 1290 [(set (match_operand:SI 0 "register_operand" "=r")
09cae750
PD
1291 (truncate:SI
1292 (lshiftrt:DI
1293 (mult:DI (zero_extend:DI
248710c4 1294 (match_operand:SI 1 "register_operand" " r"))
09cae750 1295 (sign_extend:DI
248710c4 1296 (match_operand:SI 2 "register_operand" " r")))
09cae750 1297 (const_int 32))))]
77e8e405 1298 "(TARGET_ZMMUL || TARGET_MUL) && !TARGET_64BIT"
09cae750
PD
1299 "mulhsu\t%0,%2,%1"
1300 [(set_attr "type" "imul")
1301 (set_attr "mode" "SI")])
1302
1303;;
1304;; ....................
1305;;
1306;; DIVISION and REMAINDER
1307;;
1308;; ....................
1309;;
1310
99bfdb07 1311(define_insn "*<optab>si3"
248710c4
KC
1312 [(set (match_operand:SI 0 "register_operand" "=r")
1313 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1314 (match_operand:SI 2 "register_operand" " r")))]
09cae750 1315 "TARGET_DIV"
473d7aad 1316 "<insn>%i2%~\t%0,%1,%2"
09cae750
PD
1317 [(set_attr "type" "idiv")
1318 (set_attr "mode" "SI")])
1319
99bfdb07
JL
1320(define_expand "<optab>si3"
1321 [(set (match_operand:SI 0 "register_operand" "=r")
1322 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1323 (match_operand:SI 2 "register_operand" " r")))]
1324 "TARGET_DIV"
1325{
1326 if (TARGET_64BIT)
1327 {
1328 rtx t = gen_reg_rtx (DImode);
1329 emit_insn (gen_<optab>si3_extended (t, operands[1], operands[2]));
1330 t = gen_lowpart (SImode, t);
1331 SUBREG_PROMOTED_VAR_P (t) = 1;
1332 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
1333 emit_move_insn (operands[0], t);
1334 DONE;
1335 }
1336})
1337
09cae750 1338(define_insn "<optab>di3"
248710c4
KC
1339 [(set (match_operand:DI 0 "register_operand" "=r")
1340 (any_div:DI (match_operand:DI 1 "register_operand" " r")
1341 (match_operand:DI 2 "register_operand" " r")))]
09cae750 1342 "TARGET_DIV && TARGET_64BIT"
0791ac18 1343 "<insn>%i2\t%0,%1,%2"
09cae750
PD
1344 [(set_attr "type" "idiv")
1345 (set_attr "mode" "DI")])
1346
065be0ff
MM
1347(define_expand "<u>divmod<mode>4"
1348 [(parallel
1349 [(set (match_operand:GPR 0 "register_operand")
1350 (only_div:GPR (match_operand:GPR 1 "register_operand")
1351 (match_operand:GPR 2 "register_operand")))
1352 (set (match_operand:GPR 3 "register_operand")
1353 (<paired_mod>:GPR (match_dup 1) (match_dup 2)))])]
1354 "TARGET_DIV && riscv_use_divmod_expander ()"
1355 {
1356 rtx tmp = gen_reg_rtx (<MODE>mode);
1357 emit_insn (gen_<u>div<GPR:mode>3 (operands[0], operands[1], operands[2]));
1358 emit_insn (gen_mul<GPR:mode>3 (tmp, operands[0], operands[2]));
1359 emit_insn (gen_sub<GPR:mode>3 (operands[3], operands[1], tmp));
1360 DONE;
1361 })
1362
99bfdb07 1363(define_insn "<optab>si3_extended"
248710c4 1364 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 1365 (sign_extend:DI
248710c4
KC
1366 (any_div:SI (match_operand:SI 1 "register_operand" " r")
1367 (match_operand:SI 2 "register_operand" " r"))))]
09cae750 1368 "TARGET_DIV && TARGET_64BIT"
0791ac18 1369 "<insn>%i2w\t%0,%1,%2"
09cae750
PD
1370 [(set_attr "type" "idiv")
1371 (set_attr "mode" "DI")])
1372
1373(define_insn "div<mode>3"
248710c4
KC
1374 [(set (match_operand:ANYF 0 "register_operand" "=f")
1375 (div:ANYF (match_operand:ANYF 1 "register_operand" " f")
1376 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 1377 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
09cae750
PD
1378 "fdiv.<fmt>\t%0,%1,%2"
1379 [(set_attr "type" "fdiv")
1380 (set_attr "mode" "<UNITMODE>")])
1381
1382;;
1383;; ....................
1384;;
1385;; SQUARE ROOT
1386;;
1387;; ....................
1388
1389(define_insn "sqrt<mode>2"
248710c4
KC
1390 [(set (match_operand:ANYF 0 "register_operand" "=f")
1391 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
ac96e906 1392 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && TARGET_FDIV"
09cae750
PD
1393{
1394 return "fsqrt.<fmt>\t%0,%1";
1395}
1396 [(set_attr "type" "fsqrt")
1397 (set_attr "mode" "<UNITMODE>")])
1398
1399;; Floating point multiply accumulate instructions.
1400
1401;; a * b + c
1402(define_insn "fma<mode>4"
248710c4
KC
1403 [(set (match_operand:ANYF 0 "register_operand" "=f")
1404 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
1405 (match_operand:ANYF 2 "register_operand" " f")
1406 (match_operand:ANYF 3 "register_operand" " f")))]
ac96e906 1407 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1408 "fmadd.<fmt>\t%0,%1,%2,%3"
1409 [(set_attr "type" "fmadd")
1410 (set_attr "mode" "<UNITMODE>")])
1411
1412;; a * b - c
1413(define_insn "fms<mode>4"
248710c4
KC
1414 [(set (match_operand:ANYF 0 "register_operand" "=f")
1415 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
1416 (match_operand:ANYF 2 "register_operand" " f")
1417 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
ac96e906 1418 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1419 "fmsub.<fmt>\t%0,%1,%2,%3"
1420 [(set_attr "type" "fmadd")
1421 (set_attr "mode" "<UNITMODE>")])
1422
1423;; -a * b - c
1424(define_insn "fnms<mode>4"
248710c4
KC
1425 [(set (match_operand:ANYF 0 "register_operand" "=f")
1426 (fma:ANYF
1427 (neg:ANYF (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"))))]
ac96e906 1430 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1431 "fnmadd.<fmt>\t%0,%1,%2,%3"
1432 [(set_attr "type" "fmadd")
1433 (set_attr "mode" "<UNITMODE>")])
1434
1435;; -a * b + c
1436(define_insn "fnma<mode>4"
248710c4
KC
1437 [(set (match_operand:ANYF 0 "register_operand" "=f")
1438 (fma:ANYF
1439 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1440 (match_operand:ANYF 2 "register_operand" " f")
1441 (match_operand:ANYF 3 "register_operand" " f")))]
ac96e906 1442 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1443 "fnmsub.<fmt>\t%0,%1,%2,%3"
1444 [(set_attr "type" "fmadd")
1445 (set_attr "mode" "<UNITMODE>")])
1446
1447;; -(-a * b - c), modulo signed zeros
1448(define_insn "*fma<mode>4"
248710c4
KC
1449 [(set (match_operand:ANYF 0 "register_operand" "=f")
1450 (neg:ANYF
1451 (fma:ANYF
1452 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1453 (match_operand:ANYF 2 "register_operand" " f")
1454 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
ac96e906 1455 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
09cae750
PD
1456 "fmadd.<fmt>\t%0,%1,%2,%3"
1457 [(set_attr "type" "fmadd")
1458 (set_attr "mode" "<UNITMODE>")])
1459
1460;; -(-a * b + c), modulo signed zeros
1461(define_insn "*fms<mode>4"
248710c4
KC
1462 [(set (match_operand:ANYF 0 "register_operand" "=f")
1463 (neg:ANYF
1464 (fma:ANYF
1465 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
1466 (match_operand:ANYF 2 "register_operand" " f")
1467 (match_operand:ANYF 3 "register_operand" " f"))))]
ac96e906 1468 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
09cae750
PD
1469 "fmsub.<fmt>\t%0,%1,%2,%3"
1470 [(set_attr "type" "fmadd")
1471 (set_attr "mode" "<UNITMODE>")])
1472
1473;; -(a * b + c), modulo signed zeros
1474(define_insn "*fnms<mode>4"
248710c4
KC
1475 [(set (match_operand:ANYF 0 "register_operand" "=f")
1476 (neg:ANYF
1477 (fma:ANYF
1478 (match_operand:ANYF 1 "register_operand" " f")
1479 (match_operand:ANYF 2 "register_operand" " f")
1480 (match_operand:ANYF 3 "register_operand" " f"))))]
ac96e906 1481 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
09cae750
PD
1482 "fnmadd.<fmt>\t%0,%1,%2,%3"
1483 [(set_attr "type" "fmadd")
1484 (set_attr "mode" "<UNITMODE>")])
1485
1486;; -(a * b - c), modulo signed zeros
1487(define_insn "*fnma<mode>4"
248710c4
KC
1488 [(set (match_operand:ANYF 0 "register_operand" "=f")
1489 (neg:ANYF
1490 (fma:ANYF
1491 (match_operand:ANYF 1 "register_operand" " f")
1492 (match_operand:ANYF 2 "register_operand" " f")
1493 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
ac96e906 1494 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
09cae750
PD
1495 "fnmsub.<fmt>\t%0,%1,%2,%3"
1496 [(set_attr "type" "fmadd")
1497 (set_attr "mode" "<UNITMODE>")])
1498
1499;;
1500;; ....................
1501;;
1502;; SIGN INJECTION
1503;;
1504;; ....................
1505
1506(define_insn "abs<mode>2"
248710c4
KC
1507 [(set (match_operand:ANYF 0 "register_operand" "=f")
1508 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
ac96e906 1509 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1510 "fabs.<fmt>\t%0,%1"
1511 [(set_attr "type" "fmove")
1512 (set_attr "mode" "<UNITMODE>")])
1513
1514(define_insn "copysign<mode>3"
248710c4
KC
1515 [(set (match_operand:ANYF 0 "register_operand" "=f")
1516 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f")
1517 (match_operand:ANYF 2 "register_operand" " f")]
09cae750 1518 UNSPEC_COPYSIGN))]
ac96e906 1519 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1520 "fsgnj.<fmt>\t%0,%1,%2"
1521 [(set_attr "type" "fmove")
1522 (set_attr "mode" "<UNITMODE>")])
1523
1524(define_insn "neg<mode>2"
248710c4
KC
1525 [(set (match_operand:ANYF 0 "register_operand" "=f")
1526 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
ac96e906 1527 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1528 "fneg.<fmt>\t%0,%1"
1529 [(set_attr "type" "fmove")
1530 (set_attr "mode" "<UNITMODE>")])
1531
1532;;
1533;; ....................
1534;;
1535;; MIN/MAX
1536;;
1537;; ....................
1538
30699b99
JM
1539(define_insn "fminm<mode>3"
1540 [(set (match_operand:ANYF 0 "register_operand" "=f")
1541 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1542 (use (match_operand:ANYF 2 "register_operand" " f"))]
1543 UNSPEC_FMINM))]
1544 "TARGET_HARD_FLOAT && TARGET_ZFA"
1545 "fminm.<fmt>\t%0,%1,%2"
1546 [(set_attr "type" "fmove")
1547 (set_attr "mode" "<UNITMODE>")])
1548
1549(define_insn "fmaxm<mode>3"
1550 [(set (match_operand:ANYF 0 "register_operand" "=f")
1551 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1552 (use (match_operand:ANYF 2 "register_operand" " f"))]
1553 UNSPEC_FMAXM))]
1554 "TARGET_HARD_FLOAT && TARGET_ZFA"
1555 "fmaxm.<fmt>\t%0,%1,%2"
1556 [(set_attr "type" "fmove")
1557 (set_attr "mode" "<UNITMODE>")])
1558
9ddd44b5
MR
1559(define_insn "fmin<mode>3"
1560 [(set (match_operand:ANYF 0 "register_operand" "=f")
1561 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1562 (use (match_operand:ANYF 2 "register_operand" " f"))]
1563 UNSPEC_FMIN))]
ac96e906 1564 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SNANS (<MODE>mode)"
9ddd44b5
MR
1565 "fmin.<fmt>\t%0,%1,%2"
1566 [(set_attr "type" "fmove")
1567 (set_attr "mode" "<UNITMODE>")])
1568
1569(define_insn "fmax<mode>3"
1570 [(set (match_operand:ANYF 0 "register_operand" "=f")
1571 (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f"))
1572 (use (match_operand:ANYF 2 "register_operand" " f"))]
1573 UNSPEC_FMAX))]
ac96e906 1574 "(TARGET_HARD_FLOAT || TARGET_ZFINX) && !HONOR_SNANS (<MODE>mode)"
9ddd44b5
MR
1575 "fmax.<fmt>\t%0,%1,%2"
1576 [(set_attr "type" "fmove")
1577 (set_attr "mode" "<UNITMODE>")])
1578
09cae750 1579(define_insn "smin<mode>3"
248710c4
KC
1580 [(set (match_operand:ANYF 0 "register_operand" "=f")
1581 (smin:ANYF (match_operand:ANYF 1 "register_operand" " f")
1582 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 1583 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1584 "fmin.<fmt>\t%0,%1,%2"
1585 [(set_attr "type" "fmove")
1586 (set_attr "mode" "<UNITMODE>")])
1587
1588(define_insn "smax<mode>3"
248710c4
KC
1589 [(set (match_operand:ANYF 0 "register_operand" "=f")
1590 (smax:ANYF (match_operand:ANYF 1 "register_operand" " f")
1591 (match_operand:ANYF 2 "register_operand" " f")))]
ac96e906 1592 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
1593 "fmax.<fmt>\t%0,%1,%2"
1594 [(set_attr "type" "fmove")
1595 (set_attr "mode" "<UNITMODE>")])
1596
1597;;
1598;; ....................
1599;;
1600;; LOGICAL
1601;;
1602;; ....................
1603;;
1604
1605;; For RV64, we don't expose the SImode operations to the rtl expanders,
1606;; but SImode versions exist for combine.
1607
10680bc3
JH
1608(define_expand "and<mode>3"
1609 [(set (match_operand:X 0 "register_operand")
1610 (and:X (match_operand:X 1 "register_operand")
1611 (match_operand:X 2 "arith_operand_or_mode_mask")))]
1612 ""
1613{
1614 /* If the second operand is a mode mask, emit an extension
1615 insn instead. */
1616 if (CONST_INT_P (operands[2]))
1617 {
1618 enum machine_mode tmode = VOIDmode;
b1b92e72 1619 if (UINTVAL (operands[2]) == GET_MODE_MASK (HImode))
10680bc3 1620 tmode = HImode;
b1b92e72 1621 else if (UINTVAL (operands[2]) == GET_MODE_MASK (SImode))
10680bc3
JH
1622 tmode = SImode;
1623
1624 if (tmode != VOIDmode)
1625 {
1626 rtx tmp = gen_lowpart (tmode, operands[1]);
1627 emit_insn (gen_extend_insn (operands[0], tmp, <MODE>mode, tmode, 1));
1628 DONE;
1629 }
1630 }
10680bc3
JH
1631})
1632
1633(define_insn "*and<mode>3"
1634 [(set (match_operand:X 0 "register_operand" "=r,r")
1635 (and:X (match_operand:X 1 "register_operand" "%r,r")
1636 (match_operand:X 2 "arith_operand" " r,I")))]
1637 ""
1638 "and%i2\t%0,%1,%2"
1639 [(set_attr "type" "logical")
1640 (set_attr "mode" "<MODE>")])
1641
9b54bea4
JL
1642;; When we construct constants we may want to twiddle a single bit
1643;; by generating an IOR. But the constant likely doesn't fit
1644;; arith_operand. So the generic code will reload the constant into
1645;; a register. Post-reload we won't have the chance to squash things
1646;; back into a Zbs insn.
1647;;
1648;; So indirect through a define_expand. That allows us to have a
1649;; predicate that conditionally accepts single bit constants without
1650;; putting the details of Zbs instructions in here.
1651(define_expand "<optab><mode>3"
1652 [(set (match_operand:X 0 "register_operand")
1653 (any_or:X (match_operand:X 1 "register_operand" "")
1654 (match_operand:X 2 "arith_or_zbs_operand" "")))]
1655 "")
1656
1657(define_insn "*<optab><mode>3"
248710c4 1658 [(set (match_operand:X 0 "register_operand" "=r,r")
10680bc3 1659 (any_or:X (match_operand:X 1 "register_operand" "%r,r")
248710c4 1660 (match_operand:X 2 "arith_operand" " r,I")))]
09cae750 1661 ""
0791ac18 1662 "<insn>%i2\t%0,%1,%2"
09cae750
PD
1663 [(set_attr "type" "logical")
1664 (set_attr "mode" "<MODE>")])
1665
1666(define_insn "*<optab>si3_internal"
248710c4 1667 [(set (match_operand:SI 0 "register_operand" "=r,r")
09cae750 1668 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
248710c4 1669 (match_operand:SI 2 "arith_operand" " r,I")))]
09cae750 1670 "TARGET_64BIT"
0791ac18 1671 "<insn>%i2\t%0,%1,%2"
09cae750
PD
1672 [(set_attr "type" "logical")
1673 (set_attr "mode" "SI")])
1674
1675(define_insn "one_cmpl<mode>2"
248710c4
KC
1676 [(set (match_operand:X 0 "register_operand" "=r")
1677 (not:X (match_operand:X 1 "register_operand" " r")))]
09cae750
PD
1678 ""
1679 "not\t%0,%1"
1680 [(set_attr "type" "logical")
1681 (set_attr "mode" "<MODE>")])
1682
1683(define_insn "*one_cmplsi2_internal"
248710c4
KC
1684 [(set (match_operand:SI 0 "register_operand" "=r")
1685 (not:SI (match_operand:SI 1 "register_operand" " r")))]
09cae750
PD
1686 "TARGET_64BIT"
1687 "not\t%0,%1"
1688 [(set_attr "type" "logical")
1689 (set_attr "mode" "SI")])
1690
1691;;
1692;; ....................
1693;;
1694;; TRUNCATION
1695;;
1696;; ....................
1697
1698(define_insn "truncdfsf2"
248710c4
KC
1699 [(set (match_operand:SF 0 "register_operand" "=f")
1700 (float_truncate:SF
1701 (match_operand:DF 1 "register_operand" " f")))]
ac96e906 1702 "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
09cae750
PD
1703 "fcvt.s.d\t%0,%1"
1704 [(set_attr "type" "fcvt")
1705 (set_attr "mode" "SF")])
1706
bd159a76
KC
1707(define_insn "truncsfhf2"
1708 [(set (match_operand:HF 0 "register_operand" "=f")
1709 (float_truncate:HF
1710 (match_operand:SF 1 "register_operand" " f")))]
ac96e906 1711 "TARGET_ZFHMIN || TARGET_ZHINXMIN"
bd159a76
KC
1712 "fcvt.h.s\t%0,%1"
1713 [(set_attr "type" "fcvt")
1714 (set_attr "mode" "HF")])
1715
1716(define_insn "truncdfhf2"
1717 [(set (match_operand:HF 0 "register_operand" "=f")
1718 (float_truncate:HF
1719 (match_operand:DF 1 "register_operand" " f")))]
ac96e906
J
1720 "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
1721 (TARGET_ZHINXMIN && TARGET_ZDINX)"
bd159a76
KC
1722 "fcvt.h.d\t%0,%1"
1723 [(set_attr "type" "fcvt")
1724 (set_attr "mode" "HF")])
1725
09cae750
PD
1726;;
1727;; ....................
1728;;
1729;; ZERO EXTENSION
1730;;
1731;; ....................
1732
1733;; Extension insns.
1734
283b1707
JW
1735(define_expand "zero_extendsidi2"
1736 [(set (match_operand:DI 0 "register_operand")
1737 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
1738 "TARGET_64BIT")
1739
1740(define_insn_and_split "*zero_extendsidi2_internal"
248710c4
KC
1741 [(set (match_operand:DI 0 "register_operand" "=r,r")
1742 (zero_extend:DI
1743 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
2d65622f 1744 "TARGET_64BIT && !TARGET_ZBA && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
f625c017 1745 && !(REG_P (operands[1]) && VL_REG_P (REGNO (operands[1])))"
09cae750
PD
1746 "@
1747 #
1748 lwu\t%0,%1"
36ec3f57
JJ
1749 "&& reload_completed
1750 && REG_P (operands[1])
1751 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1752 [(set (match_dup 0)
1753 (ashift:DI (match_dup 1) (const_int 32)))
1754 (set (match_dup 0)
1755 (lshiftrt:DI (match_dup 0) (const_int 32)))]
1756 { operands[1] = gen_lowpart (DImode, operands[1]); }
1757 [(set_attr "move_type" "shift_shift,load")
decbf9ec 1758 (set_attr "type" "load")
09cae750
PD
1759 (set_attr "mode" "DI")])
1760
e596a283
JW
1761(define_expand "zero_extendhi<GPR:mode>2"
1762 [(set (match_operand:GPR 0 "register_operand")
1763 (zero_extend:GPR
1764 (match_operand:HI 1 "nonimmediate_operand")))]
1765 "")
1766
1767(define_insn_and_split "*zero_extendhi<GPR:mode>2"
248710c4
KC
1768 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1769 (zero_extend:GPR
1770 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
2d65622f 1771 "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
09cae750
PD
1772 "@
1773 #
1774 lhu\t%0,%1"
36ec3f57
JJ
1775 "&& reload_completed
1776 && REG_P (operands[1])
1777 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1778 [(set (match_dup 0)
1779 (ashift:GPR (match_dup 1) (match_dup 2)))
1780 (set (match_dup 0)
1781 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1782 {
1783 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1784 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1785 }
1786 [(set_attr "move_type" "shift_shift,load")
decbf9ec 1787 (set_attr "type" "load")
09cae750
PD
1788 (set_attr "mode" "<GPR:MODE>")])
1789
2d65622f
CM
1790(define_expand "zero_extendqi<SUPERQI:mode>2"
1791 [(set (match_operand:SUPERQI 0 "register_operand")
1792 (zero_extend:SUPERQI
1793 (match_operand:QI 1 "nonimmediate_operand")))]
1794 "")
1795
1796(define_insn "*zero_extendqi<SUPERQI:mode>2_internal"
248710c4 1797 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1798 (zero_extend:SUPERQI
248710c4 1799 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
2d65622f 1800 "!TARGET_XTHEADMEMIDX"
09cae750 1801 "@
0791ac18 1802 andi\t%0,%1,0xff
09cae750
PD
1803 lbu\t%0,%1"
1804 [(set_attr "move_type" "andi,load")
b7b387e1 1805 (set_attr "type" "arith,load")
09cae750
PD
1806 (set_attr "mode" "<SUPERQI:MODE>")])
1807
1808;;
1809;; ....................
1810;;
1811;; SIGN EXTENSION
1812;;
1813;; ....................
1814
2d65622f 1815(define_expand "extendsidi2"
248710c4
KC
1816 [(set (match_operand:DI 0 "register_operand" "=r,r")
1817 (sign_extend:DI
1818 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
2d65622f
CM
1819 "TARGET_64BIT")
1820
1821(define_insn "*extendsidi2_internal"
1822 [(set (match_operand:DI 0 "register_operand" "=r,r")
1823 (sign_extend:DI
1824 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
1825 "TARGET_64BIT && !TARGET_XTHEADMEMIDX"
09cae750
PD
1826 "@
1827 sext.w\t%0,%1
1828 lw\t%0,%1"
1829 [(set_attr "move_type" "move,load")
b7b387e1 1830 (set_attr "type" "move,load")
09cae750
PD
1831 (set_attr "mode" "DI")])
1832
e596a283
JW
1833(define_expand "extend<SHORT:mode><SUPERQI:mode>2"
1834 [(set (match_operand:SUPERQI 0 "register_operand")
1835 (sign_extend:SUPERQI (match_operand:SHORT 1 "nonimmediate_operand")))]
1836 "")
1837
1838(define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
248710c4 1839 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1840 (sign_extend:SUPERQI
248710c4 1841 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
2d65622f 1842 "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
09cae750
PD
1843 "@
1844 #
1845 l<SHORT:size>\t%0,%1"
36ec3f57
JJ
1846 "&& reload_completed
1847 && REG_P (operands[1])
1848 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1849 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1850 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
1851{
1852 operands[0] = gen_lowpart (SImode, operands[0]);
1853 operands[1] = gen_lowpart (SImode, operands[1]);
1854 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1855 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1856}
1857 [(set_attr "move_type" "shift_shift,load")
decbf9ec 1858 (set_attr "type" "load")
09cae750
PD
1859 (set_attr "mode" "SI")])
1860
bd159a76
KC
1861(define_insn "extendhfsf2"
1862 [(set (match_operand:SF 0 "register_operand" "=f")
1863 (float_extend:SF
1864 (match_operand:HF 1 "register_operand" " f")))]
ac96e906 1865 "TARGET_ZFHMIN || TARGET_ZHINXMIN"
bd159a76
KC
1866 "fcvt.s.h\t%0,%1"
1867 [(set_attr "type" "fcvt")
1868 (set_attr "mode" "SF")])
1869
09cae750 1870(define_insn "extendsfdf2"
248710c4
KC
1871 [(set (match_operand:DF 0 "register_operand" "=f")
1872 (float_extend:DF
1873 (match_operand:SF 1 "register_operand" " f")))]
ac96e906 1874 "TARGET_DOUBLE_FLOAT || TARGET_ZDINX"
09cae750
PD
1875 "fcvt.d.s\t%0,%1"
1876 [(set_attr "type" "fcvt")
1877 (set_attr "mode" "DF")])
1878
bd159a76
KC
1879(define_insn "extendhfdf2"
1880 [(set (match_operand:DF 0 "register_operand" "=f")
1881 (float_extend:DF
1882 (match_operand:HF 1 "register_operand" " f")))]
ac96e906
J
1883 "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
1884 (TARGET_ZHINXMIN && TARGET_ZDINX)"
bd159a76
KC
1885 "fcvt.d.h\t%0,%1"
1886 [(set_attr "type" "fcvt")
1887 (set_attr "mode" "DF")])
1888
27d68a60
KC
1889;; 16-bit floating point moves
1890(define_expand "movhf"
1891 [(set (match_operand:HF 0 "")
1892 (match_operand:HF 1 ""))]
1893 ""
1894{
1895 if (riscv_legitimize_move (HFmode, operands[0], operands[1]))
1896 DONE;
1897})
1898
bd159a76 1899(define_insn "*movhf_hardfloat"
30699b99
JM
1900 [(set (match_operand:HF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
1901 (match_operand:HF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))]
bd159a76
KC
1902 "TARGET_ZFHMIN
1903 && (register_operand (operands[0], HFmode)
1904 || reg_or_0_operand (operands[1], HFmode))"
1905 { return riscv_output_move (operands[0], operands[1]); }
30699b99 1906 [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
b7b387e1 1907 (set_attr "type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
bd159a76 1908 (set_attr "mode" "HF")])
27d68a60
KC
1909
1910(define_insn "*movhf_softfloat"
1911 [(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
1912 (match_operand:HF 1 "move_operand" " f,Gr,m,r,*r,*f"))]
bd159a76
KC
1913 "!TARGET_ZFHMIN
1914 && (register_operand (operands[0], HFmode)
1915 || reg_or_0_operand (operands[1], HFmode))"
27d68a60
KC
1916 { return riscv_output_move (operands[0], operands[1]); }
1917 [(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
b7b387e1 1918 (set_attr "type" "fmove,move,load,store,mtc,mfc")
27d68a60
KC
1919 (set_attr "mode" "HF")])
1920
057dc349
KLC
1921(define_insn "*movhf_softfloat_boxing"
1922 [(set (match_operand:HF 0 "register_operand" "=f")
1923 (unspec:HF [(match_operand:X 1 "register_operand" " r")] UNSPEC_FMV_SFP16_X))]
1924 "!TARGET_ZFHMIN"
1925 "fmv.w.x\t%0,%1"
1926 [(set_attr "type" "fmove")
1927 (set_attr "mode" "SF")])
1928
09cae750
PD
1929;;
1930;; ....................
1931;;
1932;; CONVERSIONS
1933;;
1934;; ....................
1935
f652a358
JH
1936(define_expand "<fix_uns>_trunc<ANYF:mode>si2"
1937 [(set (match_operand:SI 0 "register_operand" "=r")
1938 (fix_ops:SI
248710c4 1939 (match_operand:ANYF 1 "register_operand" " f")))]
ac96e906 1940 "TARGET_HARD_FLOAT || TARGET_ZFINX"
f652a358
JH
1941{
1942 if (TARGET_64BIT)
1943 {
1944 rtx t = gen_reg_rtx (DImode);
1945 emit_insn (gen_<fix_uns>_trunc<ANYF:mode>si2_sext (t, operands[1]));
1946 t = gen_lowpart (SImode, t);
1947 SUBREG_PROMOTED_VAR_P (t) = 1;
1948 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
1949 emit_move_insn (operands[0], t);
1950 DONE;
1951 }
1952})
1953
1954(define_insn "*<fix_uns>_trunc<ANYF:mode>si2"
1955 [(set (match_operand:SI 0 "register_operand" "=r")
1956 (fix_ops:SI
1957 (match_operand:ANYF 1 "register_operand" " f")))]
1958 "TARGET_HARD_FLOAT || TARGET_ZFINX"
1959 "fcvt.w<u>.<ANYF:fmt> %0,%1,rtz"
ec217f72 1960 [(set_attr "type" "fcvt_f2i")
09cae750
PD
1961 (set_attr "mode" "<ANYF:MODE>")])
1962
f652a358
JH
1963(define_insn "<fix_uns>_trunc<ANYF:mode>si2_sext"
1964 [(set (match_operand:DI 0 "register_operand" "=r")
1965 (sign_extend:DI (fix_ops:SI
1966 (match_operand:ANYF 1 "register_operand" " f"))))]
1967 "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
1968 "fcvt.w<u>.<ANYF:fmt> %0,%1,rtz"
1969 [(set_attr "type" "fcvt_f2i")
1970 (set_attr "mode" "<ANYF:MODE>")])
1971
1972(define_insn "<fix_uns>_trunc<ANYF:mode>di2"
1973 [(set (match_operand:DI 0 "register_operand" "=r")
1974 (fix_ops:DI
248710c4 1975 (match_operand:ANYF 1 "register_operand" " f")))]
f652a358
JH
1976 "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
1977 "fcvt.l<u>.<ANYF:fmt> %0,%1,rtz"
ec217f72 1978 [(set_attr "type" "fcvt_f2i")
09cae750
PD
1979 (set_attr "mode" "<ANYF:MODE>")])
1980
1981(define_insn "float<GPR:mode><ANYF:mode>2"
248710c4
KC
1982 [(set (match_operand:ANYF 0 "register_operand" "= f")
1983 (float:ANYF
1984 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
ac96e906 1985 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750 1986 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
ec217f72 1987 [(set_attr "type" "fcvt_i2f")
09cae750
PD
1988 (set_attr "mode" "<ANYF:MODE>")])
1989
1990(define_insn "floatuns<GPR:mode><ANYF:mode>2"
248710c4
KC
1991 [(set (match_operand:ANYF 0 "register_operand" "= f")
1992 (unsigned_float:ANYF
1993 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
ac96e906 1994 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750 1995 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
ec217f72 1996 [(set_attr "type" "fcvt_i2f")
09cae750
PD
1997 (set_attr "mode" "<ANYF:MODE>")])
1998
f652a358
JH
1999(define_expand "lrint<ANYF:mode>si2"
2000 [(set (match_operand:SI 0 "register_operand" "=r")
2001 (unspec:SI
2002 [(match_operand:ANYF 1 "register_operand" " f")]
2003 UNSPEC_LRINT))]
2004 "TARGET_HARD_FLOAT || TARGET_ZFINX"
2005{
2006 if (TARGET_64BIT)
2007 {
2008 rtx t = gen_reg_rtx (DImode);
2009 emit_insn (gen_lrint<ANYF:mode>si2_sext (t, operands[1]));
2010 t = gen_lowpart (SImode, t);
2011 SUBREG_PROMOTED_VAR_P (t) = 1;
2012 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
2013 emit_move_insn (operands[0], t);
2014 DONE;
2015 }
2016})
2017
2018(define_insn "*lrint<ANYF:mode>si2"
2019 [(set (match_operand:SI 0 "register_operand" "=r")
2020 (unspec:SI
248710c4 2021 [(match_operand:ANYF 1 "register_operand" " f")]
f652a358 2022 UNSPEC_LRINT))]
ac96e906 2023 "TARGET_HARD_FLOAT || TARGET_ZFINX"
f652a358 2024 "fcvt.w.<ANYF:fmt> %0,%1,dyn"
ec217f72 2025 [(set_attr "type" "fcvt_f2i")
09cae750
PD
2026 (set_attr "mode" "<ANYF:MODE>")])
2027
f652a358
JH
2028(define_insn "lrint<ANYF:mode>si2_sext"
2029 [(set (match_operand:DI 0 "register_operand" "=r")
2030 (sign_extend:DI (unspec:SI
2031 [(match_operand:ANYF 1 "register_operand" " f")]
2032 UNSPEC_LRINT)))]
2033 "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
2034 "fcvt.w.<ANYF:fmt> %0,%1,dyn"
2035 [(set_attr "type" "fcvt_f2i")
2036 (set_attr "mode" "<ANYF:MODE>")])
2037
2038(define_insn "lrint<ANYF:mode>di2"
2039 [(set (match_operand:DI 0 "register_operand" "=r")
2040 (unspec:DI
2041 [(match_operand:ANYF 1 "register_operand" " f")]
2042 UNSPEC_LRINT))]
2043 "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
2044 "fcvt.l.<ANYF:fmt> %0,%1,dyn"
2045 [(set_attr "type" "fcvt_f2i")
2046 (set_attr "mode" "<ANYF:MODE>")])
2047
2048(define_expand "l<round_pattern><ANYF:mode>si2"
2049 [(set (match_operand:SI 0 "register_operand" "=r")
2050 (unspec:SI
2051 [(match_operand:ANYF 1 "register_operand" " f")]
2052 ROUND))]
2053 "TARGET_HARD_FLOAT || TARGET_ZFINX"
2054{
2055 if (TARGET_64BIT)
2056 {
2057 rtx t = gen_reg_rtx (DImode);
2058 emit_insn (gen_l<round_pattern><ANYF:mode>si2_sext (t, operands[1]));
2059 t = gen_lowpart (SImode, t);
2060 SUBREG_PROMOTED_VAR_P (t) = 1;
2061 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
2062 emit_move_insn (operands[0], t);
2063 DONE;
2064 }
2065})
2066
2067(define_insn "*l<round_pattern><ANYF:mode>si2"
2068 [(set (match_operand:SI 0 "register_operand" "=r")
2069 (unspec:SI
2070 [(match_operand:ANYF 1 "register_operand" " f")]
2071 ROUND))]
2072 "TARGET_HARD_FLOAT || TARGET_ZFINX"
2073 "fcvt.w.<ANYF:fmt> %0,%1,<round_rm>"
2074 [(set_attr "type" "fcvt_f2i")
2075 (set_attr "mode" "<ANYF:MODE>")])
2076
2077(define_insn "l<round_pattern><ANYF:mode>si2_sext"
2078 [(set (match_operand:DI 0 "register_operand" "=r")
2079 (sign_extend:DI (unspec:SI
8367c996
JL
2080 [(match_operand:ANYF 1 "register_operand" " f")]
2081 ROUND)))]
f652a358
JH
2082 "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
2083 "fcvt.w.<ANYF:fmt> %0,%1,<round_rm>"
2084 [(set_attr "type" "fcvt_f2i")
2085 (set_attr "mode" "<ANYF:MODE>")])
2086
2087(define_insn "l<round_pattern><ANYF:mode>di2"
2088 [(set (match_operand:DI 0 "register_operand" "=r")
2089 (unspec:DI
2090 [(match_operand:ANYF 1 "register_operand" " f")]
2091 ROUND))]
2092 "TARGET_64BIT && (TARGET_HARD_FLOAT || TARGET_ZFINX)"
2093 "fcvt.l.<ANYF:fmt> %0,%1,<round_rm>"
2094 [(set_attr "type" "fcvt_f2i")
2095 (set_attr "mode" "<ANYF:MODE>")])
2096
8367c996
JL
2097;; There are a couple non-obvious restrictions to be aware of.
2098;;
2099;; We'll do a FP-INT conversion in the sequence. But we don't
2100;; have a .l (64bit) variant of those instructions for rv32.
2101;; To preserve proper semantics we must reject DFmode inputs
2102;; for rv32 unless Zfa is enabled.
2103;;
2104;; The ANYF iterator allows HFmode. We don't have all the
2105;; necessary patterns defined for HFmode. So restrict HFmode
2106;; to TARGET_ZFA.
f652a358
JH
2107(define_expand "<round_pattern><ANYF:mode>2"
2108 [(set (match_operand:ANYF 0 "register_operand" "=f")
8367c996
JL
2109 (unspec:ANYF
2110 [(match_operand:ANYF 1 "register_operand" " f")]
2111 ROUND))]
2112 "(TARGET_HARD_FLOAT
2113 && (TARGET_ZFA || flag_fp_int_builtin_inexact || !flag_trapping_math)
2114 && (TARGET_ZFA || TARGET_64BIT || <ANYF:MODE>mode != DFmode)
2115 && (TARGET_ZFA || <ANYF:MODE>mode != HFmode))"
f652a358
JH
2116{
2117 if (TARGET_ZFA)
2118 emit_insn (gen_<round_pattern><ANYF:mode>_zfa2 (operands[0],
2119 operands[1]));
2120 else
2121 {
2122 rtx reg;
2123 rtx label = gen_label_rtx ();
2124 rtx end_label = gen_label_rtx ();
2125 rtx abs_reg = gen_reg_rtx (<ANYF:MODE>mode);
2126 rtx coeff_reg = gen_reg_rtx (<ANYF:MODE>mode);
2127 rtx tmp_reg = gen_reg_rtx (<ANYF:MODE>mode);
2128
2129 riscv_emit_move (tmp_reg, operands[1]);
2130 riscv_emit_move (coeff_reg,
8367c996 2131 riscv_vector::get_fp_rounding_coefficient (<ANYF:MODE>mode));
f652a358
JH
2132 emit_insn (gen_abs<ANYF:mode>2 (abs_reg, operands[1]));
2133
2134 riscv_expand_conditional_branch (label, LT, abs_reg, coeff_reg);
2135
2136 emit_jump_insn (gen_jump (end_label));
2137 emit_barrier ();
2138
2139 emit_label (label);
2140 switch (<ANYF:MODE>mode)
8367c996
JL
2141 {
2142 case SFmode:
2143 reg = gen_reg_rtx (SImode);
2144 emit_insn (gen_l<round_pattern>sfsi2 (reg, operands[1]));
2145 emit_insn (gen_floatsisf2 (abs_reg, reg));
2146 break;
2147 case DFmode:
2148 reg = gen_reg_rtx (DImode);
2149 emit_insn (gen_l<round_pattern>dfdi2 (reg, operands[1]));
2150 emit_insn (gen_floatdidf2 (abs_reg, reg));
2151 break;
2152 default:
2153 gcc_unreachable ();
2154 }
f652a358
JH
2155
2156 emit_insn (gen_copysign<ANYF:mode>3 (tmp_reg, abs_reg, operands[1]));
2157
2158 emit_label (end_label);
2159 riscv_emit_move (operands[0], tmp_reg);
2160 }
2161
2162 DONE;
2163})
2164
2165(define_insn "<round_pattern><ANYF:mode>_zfa2"
30699b99
JM
2166 [(set (match_operand:ANYF 0 "register_operand" "=f")
2167 (unspec:ANYF
2168 [(match_operand:ANYF 1 "register_operand" " f")]
2169 ROUND))]
2170 "TARGET_HARD_FLOAT && TARGET_ZFA"
2171 "fround.<ANYF:fmt>\t%0,%1,<round_rm>"
2172 [(set_attr "type" "fcvt")
2173 (set_attr "mode" "<ANYF:MODE>")])
2174
2175(define_insn "rint<ANYF:mode>2"
2176 [(set (match_operand:ANYF 0 "register_operand" "=f")
2177 (unspec:ANYF
2178 [(match_operand:ANYF 1 "register_operand" " f")]
2179 UNSPEC_RINT))]
2180 "TARGET_HARD_FLOAT && TARGET_ZFA"
2181 "froundnx.<ANYF:fmt>\t%0,%1"
2182 [(set_attr "type" "fcvt")
2183 (set_attr "mode" "<ANYF:MODE>")])
2184
09cae750
PD
2185;;
2186;; ....................
2187;;
2188;; DATA MOVEMENT
2189;;
2190;; ....................
2191
2192;; Lower-level instructions for loading an address from the GOT.
2193;; We could use MEMs, but an unspec gives more optimization
2194;; opportunities.
2195
2196(define_insn "got_load<mode>"
248710c4
KC
2197 [(set (match_operand:P 0 "register_operand" "=r")
2198 (unspec:P
2199 [(match_operand:P 1 "symbolic_operand" "")]
2200 UNSPEC_LOAD_GOT))]
09cae750
PD
2201 ""
2202 "la\t%0,%1"
2203 [(set_attr "got" "load")
decbf9ec 2204 (set_attr "type" "load")
09cae750
PD
2205 (set_attr "mode" "<MODE>")])
2206
2207(define_insn "tls_add_tp_le<mode>"
248710c4
KC
2208 [(set (match_operand:P 0 "register_operand" "=r")
2209 (unspec:P
2210 [(match_operand:P 1 "register_operand" "r")
2211 (match_operand:P 2 "register_operand" "r")
2212 (match_operand:P 3 "symbolic_operand" "")]
2213 UNSPEC_TLS_LE))]
09cae750
PD
2214 ""
2215 "add\t%0,%1,%2,%%tprel_add(%3)"
2216 [(set_attr "type" "arith")
2217 (set_attr "mode" "<MODE>")])
2218
2219(define_insn "got_load_tls_gd<mode>"
248710c4
KC
2220 [(set (match_operand:P 0 "register_operand" "=r")
2221 (unspec:P
2222 [(match_operand:P 1 "symbolic_operand" "")]
2223 UNSPEC_TLS_GD))]
09cae750
PD
2224 ""
2225 "la.tls.gd\t%0,%1"
2226 [(set_attr "got" "load")
decbf9ec 2227 (set_attr "type" "load")
09cae750
PD
2228 (set_attr "mode" "<MODE>")])
2229
2230(define_insn "got_load_tls_ie<mode>"
248710c4
KC
2231 [(set (match_operand:P 0 "register_operand" "=r")
2232 (unspec:P
2233 [(match_operand:P 1 "symbolic_operand" "")]
2234 UNSPEC_TLS_IE))]
09cae750
PD
2235 ""
2236 "la.tls.ie\t%0,%1"
2237 [(set_attr "got" "load")
decbf9ec 2238 (set_attr "type" "load")
09cae750
PD
2239 (set_attr "mode" "<MODE>")])
2240
97069657
TI
2241(define_insn "@tlsdesc<mode>"
2242 [(set (reg:P A0_REGNUM)
2243 (unspec:P
2244 [(match_operand:P 0 "symbolic_operand" "")
2245 (match_operand:P 1 "const_int_operand")]
2246 UNSPEC_TLSDESC))
2247 (clobber (reg:P T0_REGNUM))]
2248 "TARGET_TLSDESC"
2249 {
2250 return ".LT%1: auipc\ta0,%%tlsdesc_hi(%0)\;"
2251 "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
2252 "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
2253 "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
2254 }
2255 [(set_attr "type" "multi")
2256 (set_attr "length" "16")
2257 (set_attr "mode" "<MODE>")])
2258
09cae750 2259(define_insn "auipc<mode>"
248710c4
KC
2260 [(set (match_operand:P 0 "register_operand" "=r")
2261 (unspec:P
2262 [(match_operand:P 1 "symbolic_operand" "")
09cae750
PD
2263 (match_operand:P 2 "const_int_operand")
2264 (pc)]
248710c4 2265 UNSPEC_AUIPC))]
09cae750
PD
2266 ""
2267 ".LA%2: auipc\t%0,%h1"
88108b27 2268 [(set_attr "type" "auipc")
09cae750
PD
2269 (set_attr "cannot_copy" "yes")])
2270
2271;; Instructions for adding the low 12 bits of an address to a register.
2272;; Operand 2 is the address: riscv_print_operand works out which relocation
2273;; should be applied.
2274
2275(define_insn "*low<mode>"
248710c4
KC
2276 [(set (match_operand:P 0 "register_operand" "=r")
2277 (lo_sum:P (match_operand:P 1 "register_operand" " r")
09cae750
PD
2278 (match_operand:P 2 "symbolic_operand" "")))]
2279 ""
2280 "addi\t%0,%1,%R2"
2281 [(set_attr "type" "arith")
2282 (set_attr "mode" "<MODE>")])
2283
2284;; Allow combine to split complex const_int load sequences, using operand 2
2285;; to store the intermediate results. See move_operand for details.
2286(define_split
2287 [(set (match_operand:GPR 0 "register_operand")
2288 (match_operand:GPR 1 "splittable_const_int_operand"))
2289 (clobber (match_operand:GPR 2 "register_operand"))]
2290 ""
2291 [(const_int 0)]
2292{
51175507 2293 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
05302544 2294 <GPR:MODE>mode);
09cae750
PD
2295 DONE;
2296})
2297
2298;; Likewise, for symbolic operands.
2299(define_split
2300 [(set (match_operand:P 0 "register_operand")
2301 (match_operand:P 1))
2302 (clobber (match_operand:P 2 "register_operand"))]
05302544 2303 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)"
09cae750
PD
2304 [(set (match_dup 0) (match_dup 3))]
2305{
2306 riscv_split_symbol (operands[2], operands[1],
05302544 2307 MAX_MACHINE_MODE, &operands[3]);
09cae750
PD
2308})
2309
2e886eef
RMZ
2310;; Pretend to have the ability to load complex const_int in order to get
2311;; better code generation around them.
2e886eef 2312;; But avoid constants that are special cased elsewhere.
c1bc7513
VG
2313;;
2314;; Hide it from IRA register equiv recog* () to elide potential undoing of split
2315;;
2e886eef
RMZ
2316(define_insn_and_split "*mvconst_internal"
2317 [(set (match_operand:GPR 0 "register_operand" "=r")
2318 (match_operand:GPR 1 "splittable_const_int_operand" "i"))]
c1bc7513
VG
2319 "!ira_in_progress
2320 && !(p2m1_shift_operand (operands[1], <MODE>mode)
2321 || high_mask_shift_operand (operands[1], <MODE>mode))"
2e886eef
RMZ
2322 "#"
2323 "&& 1"
2324 [(const_int 0)]
2325{
2326 riscv_move_integer (operands[0], operands[0], INTVAL (operands[1]),
05302544 2327 <MODE>mode);
2e886eef 2328 DONE;
decbf9ec
EL
2329}
2330[(set_attr "type" "move")])
2e886eef 2331
09cae750
PD
2332;; 64-bit integer moves
2333
2334(define_expand "movdi"
2335 [(set (match_operand:DI 0 "")
2336 (match_operand:DI 1 ""))]
2337 ""
2338{
2339 if (riscv_legitimize_move (DImode, operands[0], operands[1]))
2340 DONE;
2341})
2342
2343(define_insn "*movdi_32bit"
8fe75147 2344 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m,r")
2345 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f,vp"))]
09cae750
PD
2346 "!TARGET_64BIT
2347 && (register_operand (operands[0], DImode)
2348 || reg_or_0_operand (operands[1], DImode))"
2349 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 2350 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore,rdvlenb")
2351 (set_attr "mode" "DI")
b7b387e1 2352 (set_attr "type" "move,move,load,store,move,fpload,move,fmove,fpstore,move")
8fe75147 2353 (set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")])
09cae750
PD
2354
2355(define_insn "*movdi_64bit"
8fe75147 2356 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m,r")
2357 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f,vp"))]
09cae750
PD
2358 "TARGET_64BIT
2359 && (register_operand (operands[0], DImode)
2360 || reg_or_0_operand (operands[1], DImode))"
2361 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 2362 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore,rdvlenb")
2363 (set_attr "mode" "DI")
b7b387e1 2364 (set_attr "type" "move,move,load,store,mtc,fpload,mfc,fmove,fpstore,move")
8fe75147 2365 (set_attr "ext" "base,base,base,base,d,d,d,d,d,vector")])
09cae750
PD
2366
2367;; 32-bit Integer moves
2368
2369(define_expand "mov<mode>"
2370 [(set (match_operand:MOVE32 0 "")
2371 (match_operand:MOVE32 1 ""))]
2372 ""
2373{
2374 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
2375 DONE;
2376})
2377
2378(define_insn "*movsi_internal"
8fe75147 2379 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m,r")
2380 (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,vp"))]
09cae750 2381 "(register_operand (operands[0], SImode)
60bd33bc 2382 || reg_or_0_operand (operands[1], SImode))
f625c017 2383 && !(REG_P (operands[1]) && VL_REG_P (REGNO (operands[1])))"
09cae750 2384 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 2385 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore,rdvlenb")
2386 (set_attr "mode" "SI")
b7b387e1 2387 (set_attr "type" "move,move,load,store,mtc,fpload,mfc,fpstore,move")
8fe75147 2388 (set_attr "ext" "base,base,base,base,f,f,f,f,vector")])
09cae750
PD
2389
2390;; 16-bit Integer moves
2391
2392;; Unlike most other insns, the move insns can't be split with
2393;; different predicates, because register spilling and other parts of
2394;; the compiler, have memoized the insn number already.
2395;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
2396
2397(define_expand "movhi"
2398 [(set (match_operand:HI 0 "")
2399 (match_operand:HI 1 ""))]
2400 ""
2401{
2402 if (riscv_legitimize_move (HImode, operands[0], operands[1]))
2403 DONE;
2404})
2405
2406(define_insn "*movhi_internal"
8fe75147 2407 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r")
2408 (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f,vp"))]
09cae750
PD
2409 "(register_operand (operands[0], HImode)
2410 || reg_or_0_operand (operands[1], HImode))"
2411 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 2412 [(set_attr "move_type" "move,const,load,store,mtc,mfc,rdvlenb")
2413 (set_attr "mode" "HI")
b7b387e1 2414 (set_attr "type" "move,move,load,store,mtc,mfc,move")
8fe75147 2415 (set_attr "ext" "base,base,base,base,f,f,vector")])
09cae750
PD
2416
2417;; HImode constant generation; see riscv_move_integer for details.
bb149ca2
RS
2418;; si+si->hi without truncation is legal because of
2419;; TARGET_TRULY_NOOP_TRUNCATION.
09cae750
PD
2420
2421(define_insn "*add<mode>hi3"
248710c4
KC
2422 [(set (match_operand:HI 0 "register_operand" "=r,r")
2423 (plus:HI (match_operand:HISI 1 "register_operand" " r,r")
2424 (match_operand:HISI 2 "arith_operand" " r,I")))]
09cae750 2425 ""
473d7aad 2426 "add%i2%~\t%0,%1,%2"
09cae750
PD
2427 [(set_attr "type" "arith")
2428 (set_attr "mode" "HI")])
2429
2430(define_insn "*xor<mode>hi3"
248710c4
KC
2431 [(set (match_operand:HI 0 "register_operand" "=r,r")
2432 (xor:HI (match_operand:HISI 1 "register_operand" " r,r")
2433 (match_operand:HISI 2 "arith_operand" " r,I")))]
09cae750 2434 ""
0791ac18 2435 "xor%i2\t%0,%1,%2"
09cae750
PD
2436 [(set_attr "type" "logical")
2437 (set_attr "mode" "HI")])
2438
2439;; 8-bit Integer moves
2440
2441(define_expand "movqi"
2442 [(set (match_operand:QI 0 "")
2443 (match_operand:QI 1 ""))]
2444 ""
2445{
2446 if (riscv_legitimize_move (QImode, operands[0], operands[1]))
2447 DONE;
2448})
2449
2450(define_insn "*movqi_internal"
8fe75147 2451 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r,r")
2452 (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f,vp"))]
09cae750
PD
2453 "(register_operand (operands[0], QImode)
2454 || reg_or_0_operand (operands[1], QImode))"
2455 { return riscv_output_move (operands[0], operands[1]); }
8fe75147 2456 [(set_attr "move_type" "move,const,load,store,mtc,mfc,rdvlenb")
2457 (set_attr "mode" "QI")
b7b387e1 2458 (set_attr "type" "move,move,load,store,mtc,mfc,move")
8fe75147 2459 (set_attr "ext" "base,base,base,base,f,f,vector")])
09cae750
PD
2460
2461;; 32-bit floating point moves
2462
2463(define_expand "movsf"
2464 [(set (match_operand:SF 0 "")
2465 (match_operand:SF 1 ""))]
2466 ""
2467{
2468 if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
2469 DONE;
2470})
2471
2472(define_insn "*movsf_hardfloat"
30699b99
JM
2473 [(set (match_operand:SF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
2474 (match_operand:SF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))]
09cae750
PD
2475 "TARGET_HARD_FLOAT
2476 && (register_operand (operands[0], SFmode)
2477 || reg_or_0_operand (operands[1], SFmode))"
2478 { return riscv_output_move (operands[0], operands[1]); }
30699b99 2479 [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
b7b387e1 2480 (set_attr "type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
09cae750
PD
2481 (set_attr "mode" "SF")])
2482
2483(define_insn "*movsf_softfloat"
248710c4
KC
2484 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
2485 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
09cae750
PD
2486 "!TARGET_HARD_FLOAT
2487 && (register_operand (operands[0], SFmode)
2488 || reg_or_0_operand (operands[1], SFmode))"
2489 { return riscv_output_move (operands[0], operands[1]); }
2490 [(set_attr "move_type" "move,load,store")
b7b387e1 2491 (set_attr "type" "move,load,store")
09cae750
PD
2492 (set_attr "mode" "SF")])
2493
2494;; 64-bit floating point moves
2495
2496(define_expand "movdf"
2497 [(set (match_operand:DF 0 "")
2498 (match_operand:DF 1 ""))]
2499 ""
2500{
2501 if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
2502 DONE;
2503})
2504
75047aeb 2505
09cae750
PD
2506;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
2507;; (However, we can still use fcvt.d.w to zero a floating-point register.)
2508(define_insn "*movdf_hardfloat_rv32"
30699b99
JM
2509 [(set (match_operand:DF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*zmvf,*zmvr, *r,*r,*m")
2510 (match_operand:DF 1 "move_operand" " f,zfli,G,m,f,G,*zmvr,*zmvf,*r*G,*m,*r"))]
09cae750
PD
2511 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
2512 && (register_operand (operands[0], DFmode)
2513 || reg_or_0_operand (operands[1], DFmode))"
2514 { return riscv_output_move (operands[0], operands[1]); }
30699b99 2515 [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
b7b387e1 2516 (set_attr "type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
09cae750
PD
2517 (set_attr "mode" "DF")])
2518
2519(define_insn "*movdf_hardfloat_rv64"
30699b99
JM
2520 [(set (match_operand:DF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m")
2521 (match_operand:DF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*r*G,*m,*r"))]
09cae750
PD
2522 "TARGET_64BIT && TARGET_DOUBLE_FLOAT
2523 && (register_operand (operands[0], DFmode)
2524 || reg_or_0_operand (operands[1], DFmode))"
2525 { return riscv_output_move (operands[0], operands[1]); }
30699b99 2526 [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
b7b387e1 2527 (set_attr "type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
09cae750
PD
2528 (set_attr "mode" "DF")])
2529
2530(define_insn "*movdf_softfloat"
248710c4
KC
2531 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
2532 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
09cae750
PD
2533 "!TARGET_DOUBLE_FLOAT
2534 && (register_operand (operands[0], DFmode)
2535 || reg_or_0_operand (operands[1], DFmode))"
2536 { return riscv_output_move (operands[0], operands[1]); }
2537 [(set_attr "move_type" "move,load,store")
b7b387e1 2538 (set_attr "type" "fmove,fpload,fpstore")
09cae750
PD
2539 (set_attr "mode" "DF")])
2540
30699b99
JM
2541(define_insn "movsidf2_low_rv32"
2542 [(set (match_operand:SI 0 "register_operand" "= r")
2543 (truncate:SI
2544 (match_operand:DF 1 "register_operand" "zmvf")))]
2545 "TARGET_HARD_FLOAT && !TARGET_64BIT && TARGET_ZFA"
2546 "fmv.x.w\t%0,%1"
2547 [(set_attr "move_type" "fmove")
25c30049 2548 (set_attr "type" "fmove")
30699b99
JM
2549 (set_attr "mode" "DF")])
2550
2551
2552(define_insn "movsidf2_high_rv32"
2553 [(set (match_operand:SI 0 "register_operand" "= r")
2554 (truncate:SI
2555 (lshiftrt:DF
2556 (match_operand:DF 1 "register_operand" "zmvf")
2557 (const_int 32))))]
2558 "TARGET_HARD_FLOAT && !TARGET_64BIT && TARGET_ZFA"
2559 "fmvh.x.d\t%0,%1"
2560 [(set_attr "move_type" "fmove")
25c30049 2561 (set_attr "type" "fmove")
30699b99
JM
2562 (set_attr "mode" "DF")])
2563
2564(define_insn "movdfsisi3_rv32"
2565 [(set (match_operand:DF 0 "register_operand" "= f")
2566 (plus:DF
2567 (match_operand:SI 2 "register_operand" "zmvr")
2568 (ashift:SI
2569 (match_operand:SI 1 "register_operand" "zmvr")
2570 (const_int 32))))]
2571 "TARGET_HARD_FLOAT && !TARGET_64BIT && TARGET_ZFA"
2572 "fmvp.d.x\t%0,%2,%1"
2573 [(set_attr "move_type" "fmove")
25c30049 2574 (set_attr "type" "fmove")
30699b99
JM
2575 (set_attr "mode" "DF")])
2576
09cae750
PD
2577(define_split
2578 [(set (match_operand:MOVE64 0 "nonimmediate_operand")
2579 (match_operand:MOVE64 1 "move_operand"))]
2580 "reload_completed
2581 && riscv_split_64bit_move_p (operands[0], operands[1])"
2582 [(const_int 0)]
2583{
2584 riscv_split_doubleword_move (operands[0], operands[1]);
2585 DONE;
2586})
2587
9464e72b 2588(define_expand "cpymem<mode>"
6ed01e6b
AW
2589 [(parallel [(set (match_operand:BLK 0 "general_operand")
2590 (match_operand:BLK 1 "general_operand"))
9464e72b 2591 (use (match_operand:P 2 ""))
6ed01e6b
AW
2592 (use (match_operand:SI 3 "const_int_operand"))])]
2593 ""
2594{
4ae5a733 2595 if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
6ed01e6b
AW
2596 DONE;
2597 else
2598 FAIL;
2599})
2600
09cae750
PD
2601;; Expand in-line code to clear the instruction cache between operand[0] and
2602;; operand[1].
2603(define_expand "clear_cache"
2604 [(match_operand 0 "pmode_register_operand")
2605 (match_operand 1 "pmode_register_operand")]
2606 ""
2607{
f1bdc63a
AW
2608#ifdef ICACHE_FLUSH_FUNC
2609 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC),
2610 LCT_NORMAL, VOIDmode, operands[0], Pmode,
2611 operands[1], Pmode, const0_rtx, Pmode);
2612#else
b03be74b
KC
2613 if (TARGET_ZIFENCEI)
2614 emit_insn (gen_fence_i ());
f1bdc63a 2615#endif
09cae750
PD
2616 DONE;
2617})
2618
2619(define_insn "fence"
2620 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
2621 ""
decbf9ec
EL
2622 "%|fence%-"
2623 [(set_attr "type" "atomic")])
09cae750
PD
2624
2625(define_insn "fence_i"
2626 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
b03be74b 2627 "TARGET_ZIFENCEI"
decbf9ec
EL
2628 "fence.i"
2629 [(set_attr "type" "atomic")])
09cae750 2630
c717a92d
PT
2631(define_insn "riscv_pause"
2632 [(unspec_volatile [(const_int 0)] UNSPECV_PAUSE)]
2633 ""
decbf9ec
EL
2634 "* return TARGET_ZIHINTPAUSE ? \"pause\" : \".insn\t0x0100000f\";"
2635 [(set_attr "type" "atomic")])
c717a92d 2636
09cae750
PD
2637;;
2638;; ....................
2639;;
2640;; SHIFTS
2641;;
2642;; ....................
2643
b7ef9225
JW
2644;; Use a QImode shift count, to avoid generating sign or zero extend
2645;; instructions for shift counts, and to avoid dropping subregs.
2646;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
2647;; defined, but use of that is discouraged.
2648
99bfdb07 2649(define_insn "*<optab>si3"
248710c4
KC
2650 [(set (match_operand:SI 0 "register_operand" "= r")
2651 (any_shift:SI
2652 (match_operand:SI 1 "register_operand" " r")
b7ef9225 2653 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
2654 ""
2655{
2656 if (GET_CODE (operands[2]) == CONST_INT)
2657 operands[2] = GEN_INT (INTVAL (operands[2])
2658 & (GET_MODE_BITSIZE (SImode) - 1));
2659
473d7aad 2660 return "<insn>%i2%~\t%0,%1,%2";
09cae750
PD
2661}
2662 [(set_attr "type" "shift")
2663 (set_attr "mode" "SI")])
2664
99bfdb07
JL
2665(define_expand "<optab>si3"
2666 [(set (match_operand:SI 0 "register_operand" "= r")
2667 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
2668 (match_operand:QI 2 "arith_operand" " rI")))]
2669 ""
2670{
2671 if (TARGET_64BIT)
2672 {
2673 rtx t = gen_reg_rtx (DImode);
2674 emit_insn (gen_<optab>si3_extend (t, operands[1], operands[2]));
2675 t = gen_lowpart (SImode, t);
2676 SUBREG_PROMOTED_VAR_P (t) = 1;
2677 SUBREG_PROMOTED_SET (t, SRP_SIGNED);
2678 emit_move_insn (operands[0], t);
2679 DONE;
2680 }
2681})
2682
09cae750 2683(define_insn "<optab>di3"
248710c4
KC
2684 [(set (match_operand:DI 0 "register_operand" "= r")
2685 (any_shift:DI
2686 (match_operand:DI 1 "register_operand" " r")
b7ef9225 2687 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
2688 "TARGET_64BIT"
2689{
2690 if (GET_CODE (operands[2]) == CONST_INT)
2691 operands[2] = GEN_INT (INTVAL (operands[2])
2692 & (GET_MODE_BITSIZE (DImode) - 1));
2693
0791ac18 2694 return "<insn>%i2\t%0,%1,%2";
09cae750
PD
2695}
2696 [(set_attr "type" "shift")
2697 (set_attr "mode" "DI")])
2698
6da6ed95
JH
2699(define_insn_and_split "*<optab><GPR:mode>3_mask_1"
2700 [(set (match_operand:GPR 0 "register_operand" "= r")
2701 (any_shift:GPR
2702 (match_operand:GPR 1 "register_operand" " r")
7ac4dfec 2703 (match_operator 4 "subreg_lowpart_operator"
6da6ed95
JH
2704 [(and:GPR2
2705 (match_operand:GPR2 2 "register_operand" "r")
2706 (match_operand 3 "<GPR:shiftm1>"))])))]
2707 ""
b7ef9225
JW
2708 "#"
2709 "&& 1"
2710 [(set (match_dup 0)
6da6ed95 2711 (any_shift:GPR (match_dup 1)
b7ef9225
JW
2712 (match_dup 2)))]
2713 "operands[2] = gen_lowpart (QImode, operands[2]);"
2714 [(set_attr "type" "shift")
6da6ed95 2715 (set_attr "mode" "<GPR:MODE>")])
b7ef9225 2716
99bfdb07 2717(define_insn "<optab>si3_extend"
248710c4 2718 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 2719 (sign_extend:DI
248710c4 2720 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 2721 (match_operand:QI 2 "arith_operand" " rI"))))]
09cae750
PD
2722 "TARGET_64BIT"
2723{
2724 if (GET_CODE (operands[2]) == CONST_INT)
2725 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
2726
0791ac18 2727 return "<insn>%i2w\t%0,%1,%2";
09cae750
PD
2728}
2729 [(set_attr "type" "shift")
2730 (set_attr "mode" "SI")])
2731
b7ef9225
JW
2732(define_insn_and_split "*<optab>si3_extend_mask"
2733 [(set (match_operand:DI 0 "register_operand" "= r")
2734 (sign_extend:DI
2735 (any_shift:SI
2736 (match_operand:SI 1 "register_operand" " r")
7ac4dfec 2737 (match_operator 4 "subreg_lowpart_operator"
6da6ed95
JH
2738 [(and:GPR
2739 (match_operand:GPR 2 "register_operand" " r")
2740 (match_operand 3 "const_si_mask_operand"))]))))]
2741 "TARGET_64BIT"
b7ef9225
JW
2742 "#"
2743 "&& 1"
2744 [(set (match_dup 0)
2745 (sign_extend:DI
2746 (any_shift:SI (match_dup 1)
2747 (match_dup 2))))]
2748 "operands[2] = gen_lowpart (QImode, operands[2]);"
2749 [(set_attr "type" "shift")
2750 (set_attr "mode" "SI")])
2751
08539f3e
JW
2752;; Non-canonical, but can be formed by ree when combine is not successful at
2753;; producing one of the two canonical patterns below.
2754(define_insn "*lshrsi3_zero_extend_1"
2755 [(set (match_operand:DI 0 "register_operand" "=r")
2756 (zero_extend:DI
2757 (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 2758 (match_operand 2 "const_int_operand"))))]
08539f3e
JW
2759 "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
2760{
2761 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
2762
2763 return "srliw\t%0,%1,%2";
2764}
2765 [(set_attr "type" "shift")
2766 (set_attr "mode" "SI")])
2767
2768;; Canonical form for a zero-extend of a logical right shift.
2769(define_insn "*lshrsi3_zero_extend_2"
2770 [(set (match_operand:DI 0 "register_operand" "=r")
2771 (zero_extract:DI (match_operand:DI 1 "register_operand" " r")
2772 (match_operand 2 "const_int_operand")
2773 (match_operand 3 "const_int_operand")))]
2774 "(TARGET_64BIT && (INTVAL (operands[3]) > 0)
2775 && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
2776{
2777 return "srliw\t%0,%1,%3";
2778}
2779 [(set_attr "type" "shift")
2780 (set_attr "mode" "SI")])
2781
2782;; Canonical form for a zero-extend of a logical right shift when the
2783;; shift count is 31.
2784(define_insn "*lshrsi3_zero_extend_3"
2785 [(set (match_operand:DI 0 "register_operand" "=r")
2786 (lt:DI (match_operand:SI 1 "register_operand" " r")
2787 (const_int 0)))]
2788 "TARGET_64BIT"
2789{
2790 return "srliw\t%0,%1,31";
2791}
2792 [(set_attr "type" "shift")
2793 (set_attr "mode" "SI")])
2794
666fdc46
JW
2795;; Handle AND with 2^N-1 for N from 12 to XLEN. This can be split into
2796;; two logical shifts. Otherwise it requires 3 instructions: lui,
2797;; xor/addi/srli, and.
36ec3f57
JJ
2798
2799;; Generating a temporary for the shift output gives better combiner results;
2800;; and also fixes a problem where op0 could be a paradoxical reg and shifting
2801;; by amounts larger than the size of the SUBREG_REG doesn't work.
666fdc46
JW
2802(define_split
2803 [(set (match_operand:GPR 0 "register_operand")
2804 (and:GPR (match_operand:GPR 1 "register_operand")
36ec3f57
JJ
2805 (match_operand:GPR 2 "p2m1_shift_operand")))
2806 (clobber (match_operand:GPR 3 "register_operand"))]
666fdc46 2807 ""
36ec3f57 2808 [(set (match_dup 3)
666fdc46
JW
2809 (ashift:GPR (match_dup 1) (match_dup 2)))
2810 (set (match_dup 0)
36ec3f57 2811 (lshiftrt:GPR (match_dup 3) (match_dup 2)))]
666fdc46 2812{
ace4317a 2813 /* Op2 is a VOIDmode constant, so get the mode size from op1. */
3496ca4e 2814 operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1])).to_constant ()
666fdc46
JW
2815 - exact_log2 (INTVAL (operands[2]) + 1));
2816})
ace4317a 2817
666fdc46
JW
2818;; Handle AND with 0xF...F0...0 where there are 32 to 63 zeros. This can be
2819;; split into two shifts. Otherwise it requires 3 instructions: li, sll, and.
2820(define_split
2821 [(set (match_operand:DI 0 "register_operand")
2822 (and:DI (match_operand:DI 1 "register_operand")
36ec3f57
JJ
2823 (match_operand:DI 2 "high_mask_shift_operand")))
2824 (clobber (match_operand:DI 3 "register_operand"))]
666fdc46 2825 "TARGET_64BIT"
36ec3f57 2826 [(set (match_dup 3)
666fdc46
JW
2827 (lshiftrt:DI (match_dup 1) (match_dup 2)))
2828 (set (match_dup 0)
36ec3f57 2829 (ashift:DI (match_dup 3) (match_dup 2)))]
666fdc46
JW
2830{
2831 operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2])));
2832})
2833
d5cdcd5c
JW
2834;; Handle SImode to DImode zero-extend combined with a left shift. This can
2835;; occur when unsigned int is used for array indexing. Split this into two
2836;; shifts. Otherwise we can get 3 shifts.
2837
2838(define_insn_and_split "zero_extendsidi2_shifted"
2839 [(set (match_operand:DI 0 "register_operand" "=r")
2840 (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
2841 (match_operand:QI 2 "immediate_operand" "I"))
2842 (match_operand 3 "immediate_operand" "")))
2843 (clobber (match_scratch:DI 4 "=&r"))]
283b1707 2844 "TARGET_64BIT && !TARGET_ZBA
d5cdcd5c
JW
2845 && ((INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff)"
2846 "#"
2847 "&& reload_completed"
2848 [(set (match_dup 4)
2849 (ashift:DI (match_dup 1) (const_int 32)))
2850 (set (match_dup 0)
2851 (lshiftrt:DI (match_dup 4) (match_dup 5)))]
2852 "operands[5] = GEN_INT (32 - (INTVAL (operands [2])));"
2853 [(set_attr "type" "shift")
2854 (set_attr "mode" "DI")])
2855
09cae750
PD
2856;;
2857;; ....................
2858;;
2859;; CONDITIONAL BRANCHES
2860;;
2861;; ....................
2862
2863;; Conditional branches
2864
acbb5ef0
PT
2865(define_insn_and_split "*branch<ANYI:mode>_shiftedarith_equals_zero"
2866 [(set (pc)
2867 (if_then_else (match_operator 1 "equality_operator"
2868 [(and:ANYI (match_operand:ANYI 2 "register_operand" "r")
2869 (match_operand 3 "shifted_const_arith_operand" "i"))
2870 (const_int 0)])
2871 (label_ref (match_operand 0 "" ""))
2872 (pc)))
4c7d336b
PT
2873 (clobber (match_scratch:X 4 "=&r"))]
2874 "!SMALL_OPERAND (INTVAL (operands[3]))"
acbb5ef0
PT
2875 "#"
2876 "&& reload_completed"
4c7d336b
PT
2877 [(set (match_dup 4) (lshiftrt:X (subreg:X (match_dup 2) 0) (match_dup 6)))
2878 (set (match_dup 4) (and:X (match_dup 4) (match_dup 7)))
acbb5ef0
PT
2879 (set (pc) (if_then_else (match_op_dup 1 [(match_dup 4) (const_int 0)])
2880 (label_ref (match_dup 0)) (pc)))]
2881{
2882 HOST_WIDE_INT mask = INTVAL (operands[3]);
2883 int trailing = ctz_hwi (mask);
2884
2885 operands[6] = GEN_INT (trailing);
2886 operands[7] = GEN_INT (mask >> trailing);
decbf9ec
EL
2887}
2888[(set_attr "type" "branch")])
acbb5ef0
PT
2889
2890(define_insn_and_split "*branch<ANYI:mode>_shiftedmask_equals_zero"
2891 [(set (pc)
2892 (if_then_else (match_operator 1 "equality_operator"
2893 [(and:ANYI (match_operand:ANYI 2 "register_operand" "r")
2894 (match_operand 3 "consecutive_bits_operand" "i"))
2895 (const_int 0)])
2896 (label_ref (match_operand 0 "" ""))
2897 (pc)))
2898 (clobber (match_scratch:X 4 "=&r"))]
2899 "(INTVAL (operands[3]) >= 0 || !partial_subreg_p (operands[2]))
2900 && popcount_hwi (INTVAL (operands[3])) > 1
2901 && !SMALL_OPERAND (INTVAL (operands[3]))"
2902 "#"
2903 "&& reload_completed"
2904 [(set (match_dup 4) (ashift:X (subreg:X (match_dup 2) 0) (match_dup 6)))
2905 (set (match_dup 4) (lshiftrt:X (match_dup 4) (match_dup 7)))
2906 (set (pc) (if_then_else (match_op_dup 1 [(match_dup 4) (const_int 0)])
2907 (label_ref (match_dup 0)) (pc)))]
2908{
2909 unsigned HOST_WIDE_INT mask = INTVAL (operands[3]);
2910 int leading = clz_hwi (mask);
2911 int trailing = ctz_hwi (mask);
2912
2913 operands[6] = GEN_INT (leading);
2914 operands[7] = GEN_INT (leading + trailing);
decbf9ec
EL
2915}
2916[(set_attr "type" "branch")])
acbb5ef0 2917
4f475391 2918(define_insn "*branch<mode>"
09cae750
PD
2919 [(set (pc)
2920 (if_then_else
ae098dfe 2921 (match_operator 1 "ordered_comparison_operator"
09cae750 2922 [(match_operand:X 2 "register_operand" "r")
4f475391 2923 (match_operand:X 3 "reg_or_0_operand" "rJ")])
09cae750
PD
2924 (label_ref (match_operand 0 "" ""))
2925 (pc)))]
9eeca775 2926 "!TARGET_XCVBI"
71f90649
AW
2927{
2928 if (get_attr_length (insn) == 12)
2929 return "b%N1\t%2,%z3,1f; jump\t%l0,ra; 1:";
2930
2931 return "b%C1\t%2,%z3,%l0";
2932}
09cae750
PD
2933 [(set_attr "type" "branch")
2934 (set_attr "mode" "none")])
2935
40b243c4
MR
2936;; Conditional move and add patterns.
2937
4f475391
AW
2938(define_expand "mov<mode>cc"
2939 [(set (match_operand:GPR 0 "register_operand")
2940 (if_then_else:GPR (match_operand 1 "comparison_operator")
dc95b338
MR
2941 (match_operand:GPR 2 "movcc_operand")
2942 (match_operand:GPR 3 "movcc_operand")))]
2943 "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND_LIKE
2944 || TARGET_MOVCC"
4f475391 2945{
8e7ffe12
CM
2946 if (riscv_expand_conditional_move (operands[0], operands[1],
2947 operands[2], operands[3]))
2948 DONE;
2949 else
4f475391 2950 FAIL;
4f475391
AW
2951})
2952
40b243c4
MR
2953(define_expand "add<mode>cc"
2954 [(match_operand:GPR 0 "register_operand")
2955 (match_operand 1 "comparison_operator")
2956 (match_operand:GPR 2 "arith_operand")
2957 (match_operand:GPR 3 "arith_operand")]
2958 "TARGET_MOVCC"
2959{
2960 rtx cmp = operands[1];
2961 rtx cmp0 = XEXP (cmp, 0);
2962 rtx cmp1 = XEXP (cmp, 1);
2963 machine_mode mode0 = GET_MODE (cmp0);
2964
2965 /* We only handle word mode integer compares for now. */
2966 if (INTEGRAL_MODE_P (mode0) && mode0 != word_mode)
2967 FAIL;
2968
2969 enum rtx_code code = GET_CODE (cmp);
2970 rtx reg0 = gen_reg_rtx (<MODE>mode);
2971 rtx reg1 = gen_reg_rtx (<MODE>mode);
2972 rtx reg2 = gen_reg_rtx (<MODE>mode);
2973 bool invert = false;
2974
2975 if (INTEGRAL_MODE_P (mode0))
2976 riscv_expand_int_scc (reg0, code, cmp0, cmp1, &invert);
2977 else if (FLOAT_MODE_P (mode0) && fp_scc_comparison (cmp, GET_MODE (cmp)))
9a1a2e98 2978 riscv_expand_float_scc (reg0, code, cmp0, cmp1, &invert);
40b243c4
MR
2979 else
2980 FAIL;
2981
2982 if (invert)
2983 riscv_emit_binary (PLUS, reg1, reg0, constm1_rtx);
2984 else
2985 riscv_emit_unary (NEG, reg1, reg0);
2986 riscv_emit_binary (AND, reg2, reg1, operands[3]);
2987 riscv_emit_binary (PLUS, operands[0], reg2, operands[2]);
2988
2989 DONE;
2990})
2991
09cae750
PD
2992;; Used to implement built-in functions.
2993(define_expand "condjump"
2994 [(set (pc)
2995 (if_then_else (match_operand 0)
2996 (label_ref (match_operand 1))
2997 (pc)))])
2998
e1fcf14f 2999(define_expand "@cbranch<mode>4"
09cae750
PD
3000 [(set (pc)
3001 (if_then_else (match_operator 0 "comparison_operator"
248710c4
KC
3002 [(match_operand:BR 1 "register_operand")
3003 (match_operand:BR 2 "nonmemory_operand")])
09cae750
PD
3004 (label_ref (match_operand 3 ""))
3005 (pc)))]
3006 ""
3007{
3008 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
3009 operands[1], operands[2]);
3010 DONE;
3011})
3012
2f825475
MR
3013(define_expand "@cbranch<ANYF:mode>4"
3014 [(parallel [(set (pc)
3015 (if_then_else (match_operator 0 "fp_branch_comparison"
3016 [(match_operand:ANYF 1 "register_operand")
3017 (match_operand:ANYF 2 "register_operand")])
3018 (label_ref (match_operand 3 ""))
3019 (pc)))
3020 (clobber (match_operand 4 ""))])]
ac96e906 3021 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750 3022{
2f825475
MR
3023 if (!signed_order_operator (operands[0], GET_MODE (operands[0])))
3024 {
3025 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
3026 operands[1], operands[2]);
3027 DONE;
3028 }
3029 operands[4] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode);
09cae750
PD
3030})
3031
2f825475
MR
3032(define_insn_and_split "*cbranch<ANYF:mode>4"
3033 [(set (pc)
3034 (if_then_else (match_operator 1 "fp_native_comparison"
3035 [(match_operand:ANYF 2 "register_operand" "f")
3036 (match_operand:ANYF 3 "register_operand" "f")])
3037 (label_ref (match_operand 0 ""))
3038 (pc)))
3039 (clobber (match_operand:X 4 "register_operand" "=r"))]
3040 "TARGET_HARD_FLOAT || TARGET_ZFINX"
3041 "#"
3042 "&& reload_completed"
3043 [(set (match_dup 4)
3044 (match_op_dup:X 1 [(match_dup 2) (match_dup 3)]))
3045 (set (pc)
3046 (if_then_else (ne:X (match_dup 4) (const_int 0))
3047 (label_ref (match_operand 0))
3048 (pc)))]
3049 ""
3050 [(set_attr "type" "branch")
3051 (set (attr "length")
3052 (if_then_else (and (le (minus (match_dup 0) (pc))
3053 (const_int 4084))
3054 (le (minus (pc) (match_dup 0))
3055 (const_int 4096)))
3056 (const_int 8)
3057 (if_then_else (and (le (minus (match_dup 0) (pc))
3058 (const_int 1048564))
3059 (le (minus (pc) (match_dup 0))
3060 (const_int 1048576)))
3061 (const_int 12)
3062 (const_int 16))))])
3063
3064(define_insn_and_split "*cbranch<ANYF:mode>4"
3065 [(set (pc)
3066 (if_then_else (match_operator 1 "ne_operator"
3067 [(match_operand:ANYF 2 "register_operand" "f")
3068 (match_operand:ANYF 3 "register_operand" "f")])
3069 (label_ref (match_operand 0 ""))
3070 (pc)))
3071 (clobber (match_operand:X 4 "register_operand" "=r"))]
3072 "TARGET_HARD_FLOAT || TARGET_ZFINX"
3073 "#"
3074 "&& reload_completed"
3075 [(set (match_dup 4)
3076 (eq:X (match_dup 2) (match_dup 3)))
3077 (set (pc)
3078 (if_then_else (eq:X (match_dup 4) (const_int 0))
3079 (label_ref (match_operand 0))
3080 (pc)))]
3081 ""
3082 [(set_attr "type" "branch")
3083 (set (attr "length")
3084 (if_then_else (and (le (minus (match_dup 0) (pc))
3085 (const_int 4084))
3086 (le (minus (pc) (match_dup 0))
3087 (const_int 4096)))
3088 (const_int 8)
3089 (if_then_else (and (le (minus (match_dup 0) (pc))
3090 (const_int 1048564))
3091 (le (minus (pc) (match_dup 0))
3092 (const_int 1048576)))
3093 (const_int 12)
3094 (const_int 16))))])
3095
09cae750
PD
3096(define_insn_and_split "*branch_on_bit<X:mode>"
3097 [(set (pc)
3098 (if_then_else
248710c4
KC
3099 (match_operator 0 "equality_operator"
3100 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
3101 (const_int 1)
3102 (match_operand 3 "branch_on_bit_operand"))
3103 (const_int 0)])
3104 (label_ref (match_operand 1))
3105 (pc)))
09cae750
PD
3106 (clobber (match_scratch:X 4 "=&r"))]
3107 ""
3108 "#"
3109 "reload_completed"
3110 [(set (match_dup 4)
3111 (ashift:X (match_dup 2) (match_dup 3)))
3112 (set (pc)
3113 (if_then_else
248710c4
KC
3114 (match_op_dup 0 [(match_dup 4) (const_int 0)])
3115 (label_ref (match_operand 1))
3116 (pc)))]
09cae750
PD
3117{
3118 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
3119 operands[3] = GEN_INT (shift);
3120
3121 if (GET_CODE (operands[0]) == EQ)
3122 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
3123 else
3124 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
decbf9ec
EL
3125}
3126[(set_attr "type" "branch")])
09cae750
PD
3127
3128(define_insn_and_split "*branch_on_bit_range<X:mode>"
3129 [(set (pc)
3130 (if_then_else
248710c4
KC
3131 (match_operator 0 "equality_operator"
3132 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
3133 (match_operand 3 "branch_on_bit_operand")
3134 (const_int 0))
3135 (const_int 0)])
3136 (label_ref (match_operand 1))
3137 (pc)))
09cae750
PD
3138 (clobber (match_scratch:X 4 "=&r"))]
3139 ""
3140 "#"
3141 "reload_completed"
3142 [(set (match_dup 4)
3143 (ashift:X (match_dup 2) (match_dup 3)))
3144 (set (pc)
3145 (if_then_else
248710c4
KC
3146 (match_op_dup 0 [(match_dup 4) (const_int 0)])
3147 (label_ref (match_operand 1))
3148 (pc)))]
09cae750
PD
3149{
3150 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
decbf9ec
EL
3151}
3152[(set_attr "type" "branch")])
09cae750
PD
3153
3154;;
3155;; ....................
3156;;
3157;; SETTING A REGISTER FROM A COMPARISON
3158;;
3159;; ....................
3160
3161;; Destination is always set in SI mode.
3162
3163(define_expand "cstore<mode>4"
3164 [(set (match_operand:SI 0 "register_operand")
ae098dfe 3165 (match_operator:SI 1 "ordered_comparison_operator"
248710c4
KC
3166 [(match_operand:GPR 2 "register_operand")
3167 (match_operand:GPR 3 "nonmemory_operand")]))]
09cae750
PD
3168 ""
3169{
3170 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
3171 operands[3]);
3172 DONE;
3173})
3174
3175(define_expand "cstore<mode>4"
3176 [(set (match_operand:SI 0 "register_operand")
3177 (match_operator:SI 1 "fp_scc_comparison"
248710c4
KC
3178 [(match_operand:ANYF 2 "register_operand")
3179 (match_operand:ANYF 3 "register_operand")]))]
ac96e906 3180 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
3181{
3182 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
3183 operands[3]);
3184 DONE;
3185})
3186
3187(define_insn "*cstore<ANYF:mode><X:mode>4"
248710c4
KC
3188 [(set (match_operand:X 0 "register_operand" "=r")
3189 (match_operator:X 1 "fp_native_comparison"
3190 [(match_operand:ANYF 2 "register_operand" " f")
3191 (match_operand:ANYF 3 "register_operand" " f")]))]
ac96e906 3192 "TARGET_HARD_FLOAT || TARGET_ZFINX"
09cae750
PD
3193 "f%C1.<fmt>\t%0,%2,%3"
3194 [(set_attr "type" "fcmp")
3195 (set_attr "mode" "<UNITMODE>")])
3196
1fcbfb00 3197(define_expand "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
94f5a8f0
MR
3198 [(set (match_operand:X 0 "register_operand")
3199 (unspec:X [(match_operand:ANYF 1 "register_operand")
3200 (match_operand:ANYF 2 "register_operand")]
3201 QUIET_COMPARISON))]
ac96e906 3202 "TARGET_HARD_FLOAT || TARGET_ZFINX"
94f5a8f0
MR
3203{
3204 rtx op0 = operands[0];
3205 rtx op1 = operands[1];
3206 rtx op2 = operands[2];
30699b99
JM
3207
3208 if (TARGET_ZFA)
3209 emit_insn (gen_f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_zfa(op0, op1, op2));
3210 else
3211 {
3212 rtx tmp = gen_reg_rtx (SImode);
3213 rtx cmp = gen_rtx_<QUIET_PATTERN> (<X:MODE>mode, op1, op2);
3214 rtx frflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, const0_rtx),
3215 UNSPECV_FRFLAGS);
3216 rtx fsflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, tmp),
3217 UNSPECV_FSFLAGS);
3218
3219 emit_insn (gen_rtx_SET (tmp, frflags));
3220 emit_insn (gen_rtx_SET (op0, cmp));
3221 emit_insn (fsflags);
3222 }
3223
94f5a8f0
MR
3224 if (HONOR_SNANS (<ANYF:MODE>mode))
3225 emit_insn (gen_rtx_UNSPEC_VOLATILE (<ANYF:MODE>mode,
3226 gen_rtvec (2, op1, op2),
3227 UNSPECV_FSNVSNAN));
3228 DONE;
3229})
1fcbfb00 3230
30699b99
JM
3231(define_insn "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_zfa"
3232 [(set (match_operand:X 0 "register_operand" "=r")
3233 (unspec:X
3234 [(match_operand:ANYF 1 "register_operand" " f")
3235 (match_operand:ANYF 2 "register_operand" " f")]
3236 QUIET_COMPARISON))]
3237 "TARGET_HARD_FLOAT && TARGET_ZFA"
3238 "f<quiet_pattern>q.<fmt>\t%0,%1,%2"
3239 [(set_attr "type" "fcmp")
3240 (set_attr "mode" "<UNITMODE>")
3241 (set (attr "length") (const_int 16))])
3242
09cae750 3243(define_insn "*seq_zero_<X:mode><GPR:mode>"
248710c4
KC
3244 [(set (match_operand:GPR 0 "register_operand" "=r")
3245 (eq:GPR (match_operand:X 1 "register_operand" " r")
3246 (const_int 0)))]
09cae750
PD
3247 ""
3248 "seqz\t%0,%1"
3249 [(set_attr "type" "slt")
3250 (set_attr "mode" "<X:MODE>")])
3251
3252(define_insn "*sne_zero_<X:mode><GPR:mode>"
248710c4
KC
3253 [(set (match_operand:GPR 0 "register_operand" "=r")
3254 (ne:GPR (match_operand:X 1 "register_operand" " r")
3255 (const_int 0)))]
09cae750
PD
3256 ""
3257 "snez\t%0,%1"
3258 [(set_attr "type" "slt")
3259 (set_attr "mode" "<X:MODE>")])
3260
3261(define_insn "*sgt<u>_<X:mode><GPR:mode>"
248710c4
KC
3262 [(set (match_operand:GPR 0 "register_operand" "= r")
3263 (any_gt:GPR (match_operand:X 1 "register_operand" " r")
3264 (match_operand:X 2 "reg_or_0_operand" " rJ")))]
09cae750
PD
3265 ""
3266 "sgt<u>\t%0,%1,%z2"
3267 [(set_attr "type" "slt")
3268 (set_attr "mode" "<X:MODE>")])
3269
3270(define_insn "*sge<u>_<X:mode><GPR:mode>"
248710c4
KC
3271 [(set (match_operand:GPR 0 "register_operand" "=r")
3272 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
3273 (const_int 1)))]
3274 ""
325d5dd5 3275 "slti<u>\t%0,zero,%1"
09cae750 3276 [(set_attr "type" "slt")
7ef00402 3277 (set_attr "mode" "<X:MODE>")])
09cae750 3278
949f1ccf 3279(define_insn "@slt<u>_<X:mode><GPR:mode>3"
248710c4
KC
3280 [(set (match_operand:GPR 0 "register_operand" "= r")
3281 (any_lt:GPR (match_operand:X 1 "register_operand" " r")
3282 (match_operand:X 2 "arith_operand" " rI")))]
09cae750 3283 ""
0791ac18 3284 "slt%i2<u>\t%0,%1,%2"
09cae750 3285 [(set_attr "type" "slt")
7ef00402 3286 (set_attr "mode" "<X:MODE>")])
09cae750
PD
3287
3288(define_insn "*sle<u>_<X:mode><GPR:mode>"
248710c4
KC
3289 [(set (match_operand:GPR 0 "register_operand" "=r")
3290 (any_le:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
3291 (match_operand:X 2 "sle_operand" "")))]
3292 ""
3293{
3294 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
0791ac18 3295 return "slt%i2<u>\t%0,%1,%2";
09cae750
PD
3296}
3297 [(set_attr "type" "slt")
7ef00402 3298 (set_attr "mode" "<X:MODE>")])
09cae750
PD
3299
3300;;
3301;; ....................
3302;;
3303;; UNCONDITIONAL BRANCHES
3304;;
3305;; ....................
3306
3307;; Unconditional branches.
3308
3309(define_insn "jump"
71f90649 3310 [(set (pc) (label_ref (match_operand 0 "" "")))]
09cae750 3311 ""
71f90649
AW
3312{
3313 /* Hopefully this does not happen often as this is going
3314 to clobber $ra and muck up the return stack predictors. */
3315 if (get_attr_length (insn) == 8)
a3e50ee9 3316 return "jump\t%l0,ra";
71f90649
AW
3317
3318 return "j\t%l0";
3319}
09cae750
PD
3320 [(set_attr "type" "jump")
3321 (set_attr "mode" "none")])
3322
3323(define_expand "indirect_jump"
3324 [(set (pc) (match_operand 0 "register_operand"))]
3325 ""
3326{
3327 operands[0] = force_reg (Pmode, operands[0]);
3328 if (Pmode == SImode)
3329 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
3330 else
3331 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
3332 DONE;
3333})
3334
3335(define_insn "indirect_jump<mode>"
3336 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
3337 ""
3338 "jr\t%0"
71f90649 3339 [(set_attr "type" "jalr")
09cae750
PD
3340 (set_attr "mode" "none")])
3341
3342(define_expand "tablejump"
3343 [(set (pc) (match_operand 0 "register_operand" ""))
3344 (use (label_ref (match_operand 1 "" "")))]
3345 ""
3346{
3347 if (CASE_VECTOR_PC_RELATIVE)
3348 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
3349 gen_rtx_LABEL_REF (Pmode, operands[1]),
3350 NULL_RTX, 0, OPTAB_DIRECT);
3351
3352 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
3353 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
3354 else
3355 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
3356 DONE;
3357})
3358
3359(define_insn "tablejump<mode>"
3360 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
3361 (use (label_ref (match_operand 1 "" "")))]
3362 ""
3363 "jr\t%0"
71f90649 3364 [(set_attr "type" "jalr")
09cae750
PD
3365 (set_attr "mode" "none")])
3366
3367;;
3368;; ....................
3369;;
3370;; Function prologue/epilogue
3371;;
3372;; ....................
3373;;
3374
3375(define_expand "prologue"
3376 [(const_int 1)]
3377 ""
3378{
3379 riscv_expand_prologue ();
3380 DONE;
3381})
3382
3383;; Block any insns from being moved before this point, since the
3384;; profiling call to mcount can use various registers that aren't
3385;; saved or used to pass arguments.
3386
3387(define_insn "blockage"
3388 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
3389 ""
3390 ""
3391 [(set_attr "type" "ghost")
3392 (set_attr "mode" "none")])
3393
3394(define_expand "epilogue"
3395 [(const_int 2)]
3396 ""
3397{
fd1e52dc 3398 riscv_expand_epilogue (NORMAL_RETURN);
09cae750
PD
3399 DONE;
3400})
3401
3402(define_expand "sibcall_epilogue"
3403 [(const_int 2)]
3404 ""
3405{
fd1e52dc 3406 riscv_expand_epilogue (SIBCALL_RETURN);
09cae750
PD
3407 DONE;
3408})
3409
3410;; Trivial return. Make it look like a normal return insn as that
3411;; allows jump optimizations to work better.
3412
3413(define_expand "return"
3414 [(simple_return)]
3415 "riscv_can_use_return_insn ()"
3416 "")
3417
3418(define_insn "simple_return"
3419 [(simple_return)]
3420 ""
8cad5b14
KC
3421{
3422 return riscv_output_return ();
3423}
71f90649 3424 [(set_attr "type" "jalr")
09cae750
PD
3425 (set_attr "mode" "none")])
3426
3427;; Normal return.
3428
3429(define_insn "simple_return_internal"
3430 [(simple_return)
3431 (use (match_operand 0 "pmode_register_operand" ""))]
3432 ""
3433 "jr\t%0"
71f90649 3434 [(set_attr "type" "jalr")
09cae750
PD
3435 (set_attr "mode" "none")])
3436
3437;; This is used in compiling the unwind routines.
3438(define_expand "eh_return"
3439 [(use (match_operand 0 "general_operand"))]
3440 ""
3441{
3442 if (GET_MODE (operands[0]) != word_mode)
3443 operands[0] = convert_to_mode (word_mode, operands[0], 0);
3444 if (TARGET_64BIT)
3445 emit_insn (gen_eh_set_lr_di (operands[0]));
3446 else
3447 emit_insn (gen_eh_set_lr_si (operands[0]));
fd1e52dc
JW
3448
3449 emit_jump_insn (gen_eh_return_internal ());
3450 emit_barrier ();
09cae750
PD
3451 DONE;
3452})
3453
3454;; Clobber the return address on the stack. We can't expand this
3455;; until we know where it will be put in the stack frame.
3456
3457(define_insn "eh_set_lr_si"
3458 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
3459 (clobber (match_scratch:SI 1 "=&r"))]
3460 "! TARGET_64BIT"
decbf9ec
EL
3461 "#"
3462 [(set_attr "type" "jump")])
09cae750
PD
3463
3464(define_insn "eh_set_lr_di"
3465 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
3466 (clobber (match_scratch:DI 1 "=&r"))]
3467 "TARGET_64BIT"
decbf9ec
EL
3468 "#"
3469 [(set_attr "type" "jump")])
09cae750
PD
3470
3471(define_split
3472 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
3473 (clobber (match_scratch 1))]
3474 "reload_completed"
3475 [(const_int 0)]
3476{
3477 riscv_set_return_address (operands[0], operands[1]);
3478 DONE;
3479})
3480
fd1e52dc
JW
3481(define_insn_and_split "eh_return_internal"
3482 [(eh_return)]
3483 ""
3484 "#"
3485 "epilogue_completed"
3486 [(const_int 0)]
decbf9ec 3487 "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;"
71f90649 3488 [(set_attr "type" "ret")])
fd1e52dc 3489
09cae750
PD
3490;;
3491;; ....................
3492;;
3493;; FUNCTION CALLS
3494;;
3495;; ....................
3496
3497(define_expand "sibcall"
3498 [(parallel [(call (match_operand 0 "")
3499 (match_operand 1 ""))
fdd59c0f
LD
3500 (use (unspec:SI [
3501 (match_operand 2 "const_int_operand")
3502 ] UNSPEC_CALLEE_CC))])]
09cae750
PD
3503 ""
3504{
3505 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
fdd59c0f 3506 emit_call_insn (gen_sibcall_internal (target, operands[1], operands[2]));
09cae750
PD
3507 DONE;
3508})
3509
3510(define_insn "sibcall_internal"
3511 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
fdd59c0f
LD
3512 (match_operand 1 "" ""))
3513 (use (unspec:SI [
3514 (match_operand 2 "const_int_operand")
3515 ] UNSPEC_CALLEE_CC))]
09cae750
PD
3516 "SIBLING_CALL_P (insn)"
3517 "@
3518 jr\t%0
3519 tail\t%0
3520 tail\t%0@plt"
3521 [(set_attr "type" "call")])
3522
3523(define_expand "sibcall_value"
3524 [(parallel [(set (match_operand 0 "")
3525 (call (match_operand 1 "")
3526 (match_operand 2 "")))
fdd59c0f
LD
3527 (use (unspec:SI [
3528 (match_operand 3 "const_int_operand")
3529 ] UNSPEC_CALLEE_CC))])]
09cae750
PD
3530 ""
3531{
3532 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
fdd59c0f
LD
3533 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2],
3534 operands[3]));
09cae750
PD
3535 DONE;
3536})
3537
3538(define_insn "sibcall_value_internal"
3539 [(set (match_operand 0 "" "")
3540 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
fdd59c0f
LD
3541 (match_operand 2 "" "")))
3542 (use (unspec:SI [
3543 (match_operand 3 "const_int_operand")
3544 ] UNSPEC_CALLEE_CC))]
09cae750
PD
3545 "SIBLING_CALL_P (insn)"
3546 "@
3547 jr\t%1
3548 tail\t%1
3549 tail\t%1@plt"
3550 [(set_attr "type" "call")])
3551
3552(define_expand "call"
3553 [(parallel [(call (match_operand 0 "")
3554 (match_operand 1 ""))
fdd59c0f
LD
3555 (use (unspec:SI [
3556 (match_operand 2 "const_int_operand")
3557 ] UNSPEC_CALLEE_CC))])]
09cae750
PD
3558 ""
3559{
3560 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
fdd59c0f 3561 emit_call_insn (gen_call_internal (target, operands[1], operands[2]));
09cae750
PD
3562 DONE;
3563})
3564
3565(define_insn "call_internal"
3566 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
3567 (match_operand 1 "" ""))
fdd59c0f
LD
3568 (use (unspec:SI [
3569 (match_operand 2 "const_int_operand")
3570 ] UNSPEC_CALLEE_CC))
09cae750
PD
3571 (clobber (reg:SI RETURN_ADDR_REGNUM))]
3572 ""
3573 "@
3574 jalr\t%0
3575 call\t%0
3576 call\t%0@plt"
3577 [(set_attr "type" "call")])
3578
3579(define_expand "call_value"
3580 [(parallel [(set (match_operand 0 "")
3581 (call (match_operand 1 "")
3582 (match_operand 2 "")))
fdd59c0f
LD
3583 (use (unspec:SI [
3584 (match_operand 3 "const_int_operand")
3585 ] UNSPEC_CALLEE_CC))])]
09cae750
PD
3586 ""
3587{
3588 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
fdd59c0f
LD
3589 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2],
3590 operands[3]));
09cae750
PD
3591 DONE;
3592})
3593
3594(define_insn "call_value_internal"
3595 [(set (match_operand 0 "" "")
3596 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
3597 (match_operand 2 "" "")))
fdd59c0f
LD
3598 (use (unspec:SI [
3599 (match_operand 3 "const_int_operand")
3600 ] UNSPEC_CALLEE_CC))
09cae750
PD
3601 (clobber (reg:SI RETURN_ADDR_REGNUM))]
3602 ""
3603 "@
3604 jalr\t%1
3605 call\t%1
3606 call\t%1@plt"
3607 [(set_attr "type" "call")])
3608
3609;; Call subroutine returning any type.
3610
3611(define_expand "untyped_call"
3612 [(parallel [(call (match_operand 0 "")
3613 (const_int 0))
3614 (match_operand 1 "")
3615 (match_operand 2 "")])]
3616 ""
3617{
3618 int i;
3619
fdd59c0f
LD
3620 /* Untyped calls always use the RISCV_CC_BASE calling convention. */
3621 emit_call_insn (gen_call (operands[0], const0_rtx,
3622 gen_int_mode (RISCV_CC_BASE, SImode)));
09cae750
PD
3623
3624 for (i = 0; i < XVECLEN (operands[2], 0); i++)
3625 {
3626 rtx set = XVECEXP (operands[2], 0, i);
3627 riscv_emit_move (SET_DEST (set), SET_SRC (set));
3628 }
3629
3630 emit_insn (gen_blockage ());
3631 DONE;
3632})
3633
3634(define_insn "nop"
3635 [(const_int 0)]
3636 ""
3637 "nop"
3638 [(set_attr "type" "nop")
3639 (set_attr "mode" "none")])
3640
3641(define_insn "trap"
3642 [(trap_if (const_int 1) (const_int 0))]
3643 ""
decbf9ec
EL
3644 "ebreak"
3645 [(set_attr "type" "trap")])
09cae750 3646
d0e0c130
KC
3647;; Must use the registers that we save to prevent the rename reg optimization
3648;; pass from using them before the gpr_save pattern when shrink wrapping
3649;; occurs. See bug 95252 for instance.
3650
09cae750 3651(define_insn "gpr_save"
d0e0c130
KC
3652 [(match_parallel 1 "gpr_save_operation"
3653 [(unspec_volatile [(match_operand 0 "const_int_operand")]
3654 UNSPECV_GPR_SAVE)])]
09cae750 3655 ""
decbf9ec
EL
3656 "call\tt0,__riscv_save_%0"
3657 [(set_attr "type" "call")])
09cae750
PD
3658
3659(define_insn "gpr_restore"
3660 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
3661 ""
decbf9ec
EL
3662 "tail\t__riscv_restore_%0"
3663 [(set_attr "type" "call")])
09cae750
PD
3664
3665(define_insn "gpr_restore_return"
3666 [(return)
3667 (use (match_operand 0 "pmode_register_operand" ""))
3668 (const_int 0)]
3669 ""
decbf9ec 3670 ""
71f90649 3671 [(set_attr "type" "ret")])
09cae750 3672
dbcbc858
JM
3673(define_insn "riscv_frcsr"
3674 [(set (match_operand:SI 0 "register_operand" "=r")
07da9b7f 3675 (unspec_volatile:SI [(const_int 0)] UNSPECV_FRCSR))]
dbcbc858 3676 "TARGET_HARD_FLOAT || TARGET_ZFINX"
decbf9ec
EL
3677 "frcsr\t%0"
3678 [(set_attr "type" "fmove")])
dbcbc858
JM
3679
3680(define_insn "riscv_fscsr"
ad0dde0a 3681 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_FSCSR)]
dbcbc858 3682 "TARGET_HARD_FLOAT || TARGET_ZFINX"
decbf9ec
EL
3683 "fscsr\t%0"
3684 [(set_attr "type" "fmove")])
dbcbc858 3685
09cae750
PD
3686(define_insn "riscv_frflags"
3687 [(set (match_operand:SI 0 "register_operand" "=r")
07da9b7f 3688 (unspec_volatile:SI [(const_int 0)] UNSPECV_FRFLAGS))]
ac96e906 3689 "TARGET_HARD_FLOAT || TARGET_ZFINX"
decbf9ec
EL
3690 "frflags\t%0"
3691 [(set_attr "type" "fmove")])
09cae750
PD
3692
3693(define_insn "riscv_fsflags"
3694 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
ac96e906 3695 "TARGET_HARD_FLOAT || TARGET_ZFINX"
decbf9ec
EL
3696 "fsflags%i0\t%0"
3697 [(set_attr "type" "fmove")])
d0ebdd9f 3698
94f5a8f0
MR
3699(define_insn "*riscv_fsnvsnan<mode>2"
3700 [(unspec_volatile [(match_operand:ANYF 0 "register_operand" "f")
3701 (match_operand:ANYF 1 "register_operand" "f")]
3702 UNSPECV_FSNVSNAN)]
ac96e906 3703 "TARGET_HARD_FLOAT || TARGET_ZFINX"
94f5a8f0
MR
3704 "feq.<fmt>\tzero,%0,%1"
3705 [(set_attr "type" "fcmp")
3706 (set_attr "mode" "<UNITMODE>")])
3707
d0ebdd9f 3708(define_insn "riscv_mret"
eb153f07
JW
3709 [(return)
3710 (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
d0ebdd9f 3711 ""
decbf9ec 3712 "mret"
71f90649 3713 [(set_attr "type" "ret")])
09cae750 3714
ec74725c 3715(define_insn "riscv_sret"
eb153f07
JW
3716 [(return)
3717 (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
ec74725c 3718 ""
decbf9ec 3719 "sret"
71f90649 3720 [(set_attr "type" "ret")])
ec74725c
JW
3721
3722(define_insn "riscv_uret"
eb153f07
JW
3723 [(return)
3724 (unspec_volatile [(const_int 0)] UNSPECV_URET)]
ec74725c 3725 ""
decbf9ec 3726 "uret"
71f90649 3727 [(set_attr "type" "ret")])
ec74725c 3728
09cae750
PD
3729(define_insn "stack_tie<mode>"
3730 [(set (mem:BLK (scratch))
3731 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
3732 (match_operand:X 1 "register_operand" "r")]
3733 UNSPEC_TIE))]
3734 ""
3735 ""
decbf9ec
EL
3736 [(set_attr "type" "ghost")
3737 (set_attr "length" "0")]
09cae750
PD
3738)
3739
88108b27
AW
3740;; This fixes a failure with gcc.c-torture/execute/pr64242.c at -O2 for a
3741;; 32-bit target when using -mtune=sifive-7-series. The first sched pass
3742;; runs before register elimination, and we have a non-obvious dependency
3743;; between a use of the soft fp and a set of the hard fp. We fix this by
3744;; emitting a clobber using the hard fp between the two insns.
3745(define_expand "restore_stack_nonlocal"
3746 [(match_operand 0 "register_operand")
3747 (match_operand 1 "memory_operand")]
3748 ""
3749{
3750 emit_move_insn (operands[0], operands[1]);
3751 /* Prevent the following hard fp restore from being moved before the move
3752 insn above which uses a copy of the soft fp reg. */
3753 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
3754 DONE;
3755})
3756
1073b500
KC
3757;; Named pattern for expanding thread pointer reference.
3758(define_expand "get_thread_pointer<mode>"
3759 [(set (match_operand:P 0 "register_operand" "=r")
3760 (reg:P TP_REGNUM))]
3761 ""
3762{})
3763
c931e8d5
CQ
3764;; Named patterns for stack smashing protection.
3765
3766(define_expand "stack_protect_set"
3767 [(match_operand 0 "memory_operand")
3768 (match_operand 1 "memory_operand")]
3769 ""
3770{
3771 machine_mode mode = GET_MODE (operands[0]);
3772 if (riscv_stack_protector_guard == SSP_TLS)
3773 {
3774 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
3775 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
3776 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
3777 operands[1] = gen_rtx_MEM (Pmode, addr);
3778 }
3779
3780 emit_insn ((mode == DImode
3781 ? gen_stack_protect_set_di
3782 : gen_stack_protect_set_si) (operands[0], operands[1]));
3783 DONE;
3784})
3785
3786;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the
3787;; canary value does not live beyond the life of this sequence.
3788(define_insn "stack_protect_set_<mode>"
3789 [(set (match_operand:GPR 0 "memory_operand" "=m")
3790 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")]
3791 UNSPEC_SSP_SET))
3792 (set (match_scratch:GPR 2 "=&r") (const_int 0))]
3793 ""
3cf07cc5 3794 "<load>\t%2, %1\;<store>\t%2, %0\;li\t%2, 0"
decbf9ec
EL
3795 [(set_attr "type" "multi")
3796 (set_attr "length" "12")])
c931e8d5
CQ
3797
3798(define_expand "stack_protect_test"
3799 [(match_operand 0 "memory_operand")
3800 (match_operand 1 "memory_operand")
3801 (match_operand 2)]
3802 ""
3803{
3804 rtx result;
3805 machine_mode mode = GET_MODE (operands[0]);
3806
3807 result = gen_reg_rtx(mode);
3808 if (riscv_stack_protector_guard == SSP_TLS)
3809 {
3810 rtx reg = gen_rtx_REG (Pmode, riscv_stack_protector_guard_reg);
3811 rtx offset = GEN_INT (riscv_stack_protector_guard_offset);
3812 rtx addr = gen_rtx_PLUS (Pmode, reg, offset);
3813 operands[1] = gen_rtx_MEM (Pmode, addr);
3814 }
3815 emit_insn ((mode == DImode
3816 ? gen_stack_protect_test_di
3817 : gen_stack_protect_test_si) (result,
3818 operands[0],
3819 operands[1]));
3820
e1fcf14f
CM
3821 rtx cond = gen_rtx_EQ (VOIDmode, result, const0_rtx);
3822 emit_jump_insn (gen_cbranch4 (mode, cond, result, const0_rtx, operands[2]));
c931e8d5
CQ
3823
3824 DONE;
3825})
3826
3827(define_insn "stack_protect_test_<mode>"
3828 [(set (match_operand:GPR 0 "register_operand" "=r")
3829 (unspec:GPR [(match_operand:GPR 1 "memory_operand" "m")
3830 (match_operand:GPR 2 "memory_operand" "m")]
3831 UNSPEC_SSP_TEST))
3832 (clobber (match_scratch:GPR 3 "=&r"))]
3833 ""
3834 "<load>\t%3, %1\;<load>\t%0, %2\;xor\t%0, %3, %0\;li\t%3, 0"
decbf9ec
EL
3835 [(set_attr "type" "multi")
3836 (set_attr "length" "12")])
c931e8d5 3837
3df3ca90
S
3838(define_insn "riscv_clean_<mode>"
3839 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3840 UNSPECV_CLEAN)]
3841 "TARGET_ZICBOM"
3842 "cbo.clean\t%a0"
57b95223 3843 [(set_attr "type" "store")]
3df3ca90
S
3844)
3845
3846(define_insn "riscv_flush_<mode>"
3847 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3848 UNSPECV_FLUSH)]
3849 "TARGET_ZICBOM"
3850 "cbo.flush\t%a0"
57b95223 3851 [(set_attr "type" "store")]
3df3ca90
S
3852)
3853
3854(define_insn "riscv_inval_<mode>"
3855 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3856 UNSPECV_INVAL)]
3857 "TARGET_ZICBOM"
3858 "cbo.inval\t%a0"
57b95223 3859 [(set_attr "type" "store")]
3df3ca90
S
3860)
3861
3862(define_insn "riscv_zero_<mode>"
3863 [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")]
3864 UNSPECV_ZERO)]
3865 "TARGET_ZICBOZ"
3866 "cbo.zero\t%a0"
57b95223 3867 [(set_attr "type" "store")]
3df3ca90
S
3868)
3869
3870(define_insn "prefetch"
b943d577 3871 [(prefetch (match_operand 0 "address_operand" "r")
3df3ca90
S
3872 (match_operand 1 "imm5_operand" "i")
3873 (match_operand 2 "const_int_operand" "n"))]
3874 "TARGET_ZICBOP"
3875{
3876 switch (INTVAL (operands[1]))
3877 {
3878 case 0: return "prefetch.r\t%a0";
3879 case 1: return "prefetch.w\t%a0";
3880 default: gcc_unreachable ();
3881 }
decbf9ec 3882}
57b95223 3883 [(set_attr "type" "store")])
3df3ca90
S
3884
3885(define_insn "riscv_prefetchi_<mode>"
b943d577 3886 [(unspec_volatile:X [(match_operand:X 0 "address_operand" "r")
3df3ca90
S
3887 (match_operand:X 1 "imm5_operand" "i")]
3888 UNSPECV_PREI)]
3889 "TARGET_ZICBOP"
3890 "prefetch.i\t%a0"
57b95223 3891 [(set_attr "type" "store")])
3df3ca90 3892
c493fa38
CM
3893(define_expand "extv<mode>"
3894 [(set (match_operand:GPR 0 "register_operand" "=r")
3895 (sign_extract:GPR (match_operand:GPR 1 "register_operand" "r")
3896 (match_operand 2 "const_int_operand")
3897 (match_operand 3 "const_int_operand")))]
3898 "TARGET_XTHEADBB"
3899)
3900
3901(define_expand "extzv<mode>"
3902 [(set (match_operand:GPR 0 "register_operand" "=r")
3903 (zero_extract:GPR (match_operand:GPR 1 "register_operand" "r")
3904 (match_operand 2 "const_int_operand")
3905 (match_operand 3 "const_int_operand")))]
3906 "TARGET_XTHEADBB"
3907{
3908 if (TARGET_XTHEADBB
3909 && (INTVAL (operands[2]) < 8) && (INTVAL (operands[3]) == 0))
3910 FAIL;
3911})
3912
b2a1bef9
CM
3913(define_expand "maddhisi4"
3914 [(set (match_operand:SI 0 "register_operand")
3915 (plus:SI
3916 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand"))
3917 (sign_extend:SI (match_operand:HI 2 "register_operand")))
3918 (match_operand:SI 3 "register_operand")))]
3919 "TARGET_XTHEADMAC"
3920)
3921
3922(define_expand "msubhisi4"
3923 [(set (match_operand:SI 0 "register_operand")
3924 (minus:SI
3925 (match_operand:SI 3 "register_operand")
3926 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand"))
3927 (sign_extend:SI (match_operand:HI 2 "register_operand")))))]
3928 "TARGET_XTHEADMAC"
3929)
3930
949f1ccf
CM
3931;; String compare with length insn.
3932;; Argument 0 is the target (result)
3933;; Argument 1 is the source1
3934;; Argument 2 is the source2
3935;; Argument 3 is the length
3936;; Argument 4 is the alignment
3937
3938(define_expand "cmpstrnsi"
3939 [(parallel [(set (match_operand:SI 0)
3940 (compare:SI (match_operand:BLK 1)
3941 (match_operand:BLK 2)))
3942 (use (match_operand:SI 3))
3943 (use (match_operand:SI 4))])]
d468718c
RD
3944 "riscv_inline_strncmp && !optimize_size
3945 && (TARGET_ZBB || TARGET_XTHEADBB || TARGET_VECTOR)"
949f1ccf
CM
3946{
3947 if (riscv_expand_strcmp (operands[0], operands[1], operands[2],
3948 operands[3], operands[4]))
3949 DONE;
3950 else
3951 FAIL;
3952})
3953
3954;; String compare insn.
3955;; Argument 0 is the target (result)
3956;; Argument 1 is the source1
3957;; Argument 2 is the source2
3958;; Argument 3 is the alignment
3959
3960(define_expand "cmpstrsi"
3961 [(parallel [(set (match_operand:SI 0)
3962 (compare:SI (match_operand:BLK 1)
3963 (match_operand:BLK 2)))
3964 (use (match_operand:SI 3))])]
d468718c
RD
3965 "riscv_inline_strcmp && !optimize_size
3966 && (TARGET_ZBB || TARGET_XTHEADBB || TARGET_VECTOR)"
949f1ccf
CM
3967{
3968 if (riscv_expand_strcmp (operands[0], operands[1], operands[2],
3969 NULL_RTX, operands[3]))
3970 DONE;
3971 else
3972 FAIL;
3973})
3974
df48285b
CM
3975;; Search character in string (generalization of strlen).
3976;; Argument 0 is the resulting offset
3977;; Argument 1 is the string
3978;; Argument 2 is the search character
3979;; Argument 3 is the alignment
3980
3981(define_expand "strlen<mode>"
3982 [(set (match_operand:X 0 "register_operand")
3983 (unspec:X [(match_operand:BLK 1 "general_operand")
3984 (match_operand:SI 2 "const_int_operand")
3985 (match_operand:SI 3 "const_int_operand")]
3986 UNSPEC_STRLEN))]
2664964b
RD
3987 "riscv_inline_strlen && !optimize_size
3988 && (TARGET_ZBB || TARGET_XTHEADBB || TARGET_VECTOR)"
df48285b
CM
3989{
3990 rtx search_char = operands[2];
3991
3992 if (search_char != const0_rtx)
3993 FAIL;
3994
3995 if (riscv_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
3996 DONE;
3997 else
3998 FAIL;
3999})
4000
d07d0e99
KLC
4001(define_insn "*large_load_address"
4002 [(set (match_operand:DI 0 "register_operand" "=r")
4003 (mem:DI (match_operand 1 "pcrel_symbol_operand" "")))]
4004 "TARGET_64BIT && riscv_cmodel == CM_LARGE"
4005 "ld\t%0,%1"
4006 [(set_attr "type" "load")
4007 (set (attr "length") (const_int 8))])
4008
283b1707 4009(include "bitmanip.md")
2c809510 4010(include "crypto.md")
09cae750 4011(include "sync.md")
0ac32323
PN
4012(include "sync-rvwmo.md")
4013(include "sync-ztso.md")
09cae750
PD
4014(include "peephole.md")
4015(include "pic.md")
4016(include "generic.md")
88108b27 4017(include "sifive-7.md")
7c190f93 4018(include "sifive-p400.md")
ec217f72 4019(include "sifive-p600.md")
b77c3227 4020(include "thead.md")
6ec84c45 4021(include "generic-vector-ooo.md")
f8498436 4022(include "generic-ooo.md")
f56d48b2 4023(include "vector.md")
d3d6a96d 4024(include "vector-crypto.md")
74290c66 4025(include "zicond.md")
fc98a41c 4026(include "sfb.md")
3d1d3132 4027(include "zc.md")
400efddd 4028(include "corev.md")
d91a0cee 4029(include "xiangshan.md")