]>
Commit | Line | Data |
---|---|---|
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") |