Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/riscv/riscv.md @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 ;; Machine description for RISC-V for GNU compiler. | |
2 ;; Copyright (C) 2011-2017 Free Software Foundation, Inc. | |
3 ;; Contributed by Andrew Waterman (andrew@sifive.com). | |
4 ;; Based on MIPS target for GNU compiler. | |
5 | |
6 ;; This file is part of GCC. | |
7 | |
8 ;; GCC is free software; you can redistribute it and/or modify | |
9 ;; it under the terms of the GNU General Public License as published by | |
10 ;; the Free Software Foundation; either version 3, or (at your option) | |
11 ;; any later version. | |
12 | |
13 ;; GCC is distributed in the hope that it will be useful, | |
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 ;; GNU General Public License for more details. | |
17 | |
18 ;; You should have received a copy of the GNU General Public License | |
19 ;; along with GCC; see the file COPYING3. If not see | |
20 ;; <http://www.gnu.org/licenses/>. | |
21 | |
22 (define_c_enum "unspec" [ | |
23 ;; Override return address for exception handling. | |
24 UNSPEC_EH_RETURN | |
25 | |
26 ;; Symbolic accesses. The order of this list must match that of | |
27 ;; enum riscv_symbol_type in riscv-protos.h. | |
28 UNSPEC_ADDRESS_FIRST | |
29 UNSPEC_PCREL | |
30 UNSPEC_LOAD_GOT | |
31 UNSPEC_TLS | |
32 UNSPEC_TLS_LE | |
33 UNSPEC_TLS_IE | |
34 UNSPEC_TLS_GD | |
35 | |
36 ;; High part of PC-relative address. | |
37 UNSPEC_AUIPC | |
38 | |
39 ;; Floating-point unspecs. | |
40 UNSPEC_FLT_QUIET | |
41 UNSPEC_FLE_QUIET | |
42 UNSPEC_COPYSIGN | |
43 UNSPEC_LRINT | |
44 UNSPEC_LROUND | |
45 | |
46 ;; Stack tie | |
47 UNSPEC_TIE | |
48 ]) | |
49 | |
50 (define_c_enum "unspecv" [ | |
51 ;; Register save and restore. | |
52 UNSPECV_GPR_SAVE | |
53 UNSPECV_GPR_RESTORE | |
54 | |
55 ;; Floating-point unspecs. | |
56 UNSPECV_FRFLAGS | |
57 UNSPECV_FSFLAGS | |
58 | |
59 ;; Blockage and synchronization. | |
60 UNSPECV_BLOCKAGE | |
61 UNSPECV_FENCE | |
62 UNSPECV_FENCE_I | |
63 ]) | |
64 | |
65 (define_constants | |
66 [(RETURN_ADDR_REGNUM 1) | |
67 (T0_REGNUM 5) | |
68 (T1_REGNUM 6) | |
69 (S0_REGNUM 8) | |
70 (S1_REGNUM 9) | |
71 (S2_REGNUM 18) | |
72 ]) | |
73 | |
74 (include "predicates.md") | |
75 (include "constraints.md") | |
76 | |
77 ;; .................... | |
78 ;; | |
79 ;; Attributes | |
80 ;; | |
81 ;; .................... | |
82 | |
83 (define_attr "got" "unset,xgot_high,load" | |
84 (const_string "unset")) | |
85 | |
86 ;; Classification of moves, extensions and truncations. Most values | |
87 ;; are as for "type" (see below) but there are also the following | |
88 ;; move-specific values: | |
89 ;; | |
90 ;; andi a single ANDI instruction | |
91 ;; shift_shift a shift left followed by a shift right | |
92 ;; | |
93 ;; This attribute is used to determine the instruction's length and | |
94 ;; scheduling type. For doubleword moves, the attribute always describes | |
95 ;; the split instructions; in some cases, it is more appropriate for the | |
96 ;; scheduling type to be "multi" instead. | |
97 (define_attr "move_type" | |
98 "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove, | |
99 const,logical,arith,andi,shift_shift" | |
100 (const_string "unknown")) | |
101 | |
102 ;; Main data type used by the insn | |
103 (define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF" | |
104 (const_string "unknown")) | |
105 | |
106 ;; True if the main data type is twice the size of a word. | |
107 (define_attr "dword_mode" "no,yes" | |
108 (cond [(and (eq_attr "mode" "DI,DF") | |
109 (eq (symbol_ref "TARGET_64BIT") (const_int 0))) | |
110 (const_string "yes") | |
111 | |
112 (and (eq_attr "mode" "TI,TF") | |
113 (ne (symbol_ref "TARGET_64BIT") (const_int 0))) | |
114 (const_string "yes")] | |
115 (const_string "no"))) | |
116 | |
117 ;; Classification of each insn. | |
118 ;; branch conditional branch | |
119 ;; jump unconditional jump | |
120 ;; call unconditional call | |
121 ;; load load instruction(s) | |
122 ;; fpload floating point load | |
123 ;; store store instruction(s) | |
124 ;; fpstore floating point store | |
125 ;; mtc transfer to coprocessor | |
126 ;; mfc transfer from coprocessor | |
127 ;; const load constant | |
128 ;; arith integer arithmetic instructions | |
129 ;; logical integer logical instructions | |
130 ;; shift integer shift instructions | |
131 ;; slt set less than instructions | |
132 ;; imul integer multiply | |
133 ;; idiv integer divide | |
134 ;; move integer register move (addi rd, rs1, 0) | |
135 ;; fmove floating point register move | |
136 ;; fadd floating point add/subtract | |
137 ;; fmul floating point multiply | |
138 ;; fmadd floating point multiply-add | |
139 ;; fdiv floating point divide | |
140 ;; fcmp floating point compare | |
141 ;; fcvt floating point convert | |
142 ;; fsqrt floating point square root | |
143 ;; multi multiword sequence (or user asm statements) | |
144 ;; nop no operation | |
145 ;; ghost an instruction that produces no real code | |
146 (define_attr "type" | |
147 "unknown,branch,jump,call,load,fpload,store,fpstore, | |
148 mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul, | |
149 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,nop,ghost" | |
150 (cond [(eq_attr "got" "load") (const_string "load") | |
151 | |
152 ;; If a doubleword move uses these expensive instructions, | |
153 ;; it is usually better to schedule them in the same way | |
154 ;; as the singleword form, rather than as "multi". | |
155 (eq_attr "move_type" "load") (const_string "load") | |
156 (eq_attr "move_type" "fpload") (const_string "fpload") | |
157 (eq_attr "move_type" "store") (const_string "store") | |
158 (eq_attr "move_type" "fpstore") (const_string "fpstore") | |
159 (eq_attr "move_type" "mtc") (const_string "mtc") | |
160 (eq_attr "move_type" "mfc") (const_string "mfc") | |
161 | |
162 ;; These types of move are always single insns. | |
163 (eq_attr "move_type" "fmove") (const_string "fmove") | |
164 (eq_attr "move_type" "arith") (const_string "arith") | |
165 (eq_attr "move_type" "logical") (const_string "logical") | |
166 (eq_attr "move_type" "andi") (const_string "logical") | |
167 | |
168 ;; These types of move are always split. | |
169 (eq_attr "move_type" "shift_shift") | |
170 (const_string "multi") | |
171 | |
172 ;; These types of move are split for doubleword modes only. | |
173 (and (eq_attr "move_type" "move,const") | |
174 (eq_attr "dword_mode" "yes")) | |
175 (const_string "multi") | |
176 (eq_attr "move_type" "move") (const_string "move") | |
177 (eq_attr "move_type" "const") (const_string "const")] | |
178 (const_string "unknown"))) | |
179 | |
180 ;; Length of instruction in bytes. | |
181 (define_attr "length" "" | |
182 (cond [ | |
183 ;; Branches further than +/- 4 KiB require two instructions. | |
184 (eq_attr "type" "branch") | |
185 (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4088)) | |
186 (le (minus (pc) (match_dup 0)) (const_int 4092))) | |
187 (const_int 4) | |
188 (const_int 8)) | |
189 | |
190 ;; Conservatively assume calls take two instructions (AUIPC + JALR). | |
191 ;; The linker will opportunistically relax the sequence to JAL. | |
192 (eq_attr "type" "call") (const_int 8) | |
193 | |
194 ;; "Ghost" instructions occupy no space. | |
195 (eq_attr "type" "ghost") (const_int 0) | |
196 | |
197 (eq_attr "got" "load") (const_int 8) | |
198 | |
199 (eq_attr "type" "fcmp") (const_int 8) | |
200 | |
201 ;; SHIFT_SHIFTs are decomposed into two separate instructions. | |
202 (eq_attr "move_type" "shift_shift") | |
203 (const_int 8) | |
204 | |
205 ;; Check for doubleword moves that are decomposed into two | |
206 ;; instructions. | |
207 (and (eq_attr "move_type" "mtc,mfc,move") | |
208 (eq_attr "dword_mode" "yes")) | |
209 (const_int 8) | |
210 | |
211 ;; Doubleword CONST{,N} moves are split into two word | |
212 ;; CONST{,N} moves. | |
213 (and (eq_attr "move_type" "const") | |
214 (eq_attr "dword_mode" "yes")) | |
215 (symbol_ref "riscv_split_const_insns (operands[1]) * 4") | |
216 | |
217 ;; Otherwise, constants, loads and stores are handled by external | |
218 ;; routines. | |
219 (eq_attr "move_type" "load,fpload") | |
220 (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4") | |
221 (eq_attr "move_type" "store,fpstore") | |
222 (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4") | |
223 ] (const_int 4))) | |
224 | |
225 ;; Is copying of this instruction disallowed? | |
226 (define_attr "cannot_copy" "no,yes" (const_string "no")) | |
227 | |
228 ;; Describe a user's asm statement. | |
229 (define_asm_attributes | |
230 [(set_attr "type" "multi")]) | |
231 | |
232 ;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated | |
233 ;; from the same template. | |
234 (define_mode_iterator GPR [SI (DI "TARGET_64BIT")]) | |
235 | |
236 ;; This mode iterator allows :P to be used for patterns that operate on | |
237 ;; pointer-sized quantities. Exactly one of the two alternatives will match. | |
238 (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) | |
239 | |
240 ;; Likewise, but for XLEN-sized quantities. | |
241 (define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")]) | |
242 | |
243 ;; Branches operate on XLEN-sized quantities, but for RV64 we accept | |
244 ;; QImode values so we can force zero-extension. | |
245 (define_mode_iterator BR [(QI "TARGET_64BIT") SI (DI "TARGET_64BIT")]) | |
246 | |
247 ;; 32-bit moves for which we provide move patterns. | |
248 (define_mode_iterator MOVE32 [SI]) | |
249 | |
250 ;; 64-bit modes for which we provide move patterns. | |
251 (define_mode_iterator MOVE64 [DI DF]) | |
252 | |
253 ;; Iterator for sub-32-bit integer modes. | |
254 (define_mode_iterator SHORT [QI HI]) | |
255 | |
256 ;; Iterator for HImode constant generation. | |
257 (define_mode_iterator HISI [HI SI]) | |
258 | |
259 ;; Iterator for QImode extension patterns. | |
260 (define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")]) | |
261 | |
262 ;; Iterator for extending loads. | |
263 (define_mode_iterator ZERO_EXTEND_LOAD [QI HI (SI "TARGET_64BIT")]) | |
264 | |
265 ;; Iterator for hardware integer modes narrower than XLEN. | |
266 (define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")]) | |
267 | |
268 ;; Iterator for hardware-supported integer modes. | |
269 (define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")]) | |
270 | |
271 ;; Iterator for hardware-supported floating-point modes. | |
272 (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT") | |
273 (DF "TARGET_DOUBLE_FLOAT")]) | |
274 | |
275 ;; This attribute gives the length suffix for a sign- or zero-extension | |
276 ;; instruction. | |
277 (define_mode_attr size [(QI "b") (HI "h")]) | |
278 | |
279 ;; Mode attributes for loads. | |
280 (define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")]) | |
281 | |
282 ;; Instruction names for stores. | |
283 (define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")]) | |
284 | |
285 ;; This attribute gives the best constraint to use for registers of | |
286 ;; a given mode. | |
287 (define_mode_attr reg [(SI "d") (DI "d") (CC "d")]) | |
288 | |
289 ;; This attribute gives the format suffix for floating-point operations. | |
290 (define_mode_attr fmt [(SF "s") (DF "d")]) | |
291 | |
292 ;; This attribute gives the integer suffix for floating-point conversions. | |
293 (define_mode_attr ifmt [(SI "w") (DI "l")]) | |
294 | |
295 ;; This attribute gives the format suffix for atomic memory operations. | |
296 (define_mode_attr amo [(SI "w") (DI "d")]) | |
297 | |
298 ;; This attribute gives the upper-case mode name for one unit of a | |
299 ;; floating-point mode. | |
300 (define_mode_attr UNITMODE [(SF "SF") (DF "DF")]) | |
301 | |
302 ;; This attribute gives the integer mode that has half the size of | |
303 ;; the controlling mode. | |
304 (define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")]) | |
305 | |
306 ;; Iterator and attributes for floating-point rounding instructions. | |
307 (define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND]) | |
308 (define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")]) | |
309 (define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")]) | |
310 | |
311 ;; Iterator and attributes for quiet comparisons. | |
312 (define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET]) | |
313 (define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")]) | |
314 | |
315 ;; This code iterator allows signed and unsigned widening multiplications | |
316 ;; to use the same template. | |
317 (define_code_iterator any_extend [sign_extend zero_extend]) | |
318 | |
319 ;; This code iterator allows the two right shift instructions to be | |
320 ;; generated from the same template. | |
321 (define_code_iterator any_shiftrt [ashiftrt lshiftrt]) | |
322 | |
323 ;; This code iterator allows the three shift instructions to be generated | |
324 ;; from the same template. | |
325 (define_code_iterator any_shift [ashift ashiftrt lshiftrt]) | |
326 | |
327 ;; This code iterator allows the three bitwise instructions to be generated | |
328 ;; from the same template. | |
329 (define_code_iterator any_bitwise [and ior xor]) | |
330 | |
331 ;; This code iterator allows unsigned and signed division to be generated | |
332 ;; from the same template. | |
333 (define_code_iterator any_div [div udiv mod umod]) | |
334 | |
335 ;; This code iterator allows unsigned and signed modulus to be generated | |
336 ;; from the same template. | |
337 (define_code_iterator any_mod [mod umod]) | |
338 | |
339 ;; These code iterators allow the signed and unsigned scc operations to use | |
340 ;; the same template. | |
341 (define_code_iterator any_gt [gt gtu]) | |
342 (define_code_iterator any_ge [ge geu]) | |
343 (define_code_iterator any_lt [lt ltu]) | |
344 (define_code_iterator any_le [le leu]) | |
345 | |
346 ;; <u> expands to an empty string when doing a signed operation and | |
347 ;; "u" when doing an unsigned operation. | |
348 (define_code_attr u [(sign_extend "") (zero_extend "u") | |
349 (gt "") (gtu "u") | |
350 (ge "") (geu "u") | |
351 (lt "") (ltu "u") | |
352 (le "") (leu "u")]) | |
353 | |
354 ;; <su> is like <u>, but the signed form expands to "s" rather than "". | |
355 (define_code_attr su [(sign_extend "s") (zero_extend "u")]) | |
356 | |
357 ;; <optab> expands to the name of the optab for a particular code. | |
358 (define_code_attr optab [(ashift "ashl") | |
359 (ashiftrt "ashr") | |
360 (lshiftrt "lshr") | |
361 (div "div") | |
362 (mod "mod") | |
363 (udiv "udiv") | |
364 (umod "umod") | |
365 (ge "ge") | |
366 (le "le") | |
367 (gt "gt") | |
368 (lt "lt") | |
369 (ior "ior") | |
370 (xor "xor") | |
371 (and "and") | |
372 (plus "add") | |
373 (minus "sub")]) | |
374 | |
375 ;; <insn> expands to the name of the insn that implements a particular code. | |
376 (define_code_attr insn [(ashift "sll") | |
377 (ashiftrt "sra") | |
378 (lshiftrt "srl") | |
379 (div "div") | |
380 (mod "rem") | |
381 (udiv "divu") | |
382 (umod "remu") | |
383 (ior "or") | |
384 (xor "xor") | |
385 (and "and") | |
386 (plus "add") | |
387 (minus "sub")]) | |
388 | |
389 ;; Ghost instructions produce no real code and introduce no hazards. | |
390 ;; They exist purely to express an effect on dataflow. | |
391 (define_insn_reservation "ghost" 0 | |
392 (eq_attr "type" "ghost") | |
393 "nothing") | |
394 | |
395 ;; | |
396 ;; .................... | |
397 ;; | |
398 ;; ADDITION | |
399 ;; | |
400 ;; .................... | |
401 ;; | |
402 | |
403 (define_insn "add<mode>3" | |
404 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
405 (plus:ANYF (match_operand:ANYF 1 "register_operand" " f") | |
406 (match_operand:ANYF 2 "register_operand" " f")))] | |
407 "TARGET_HARD_FLOAT" | |
408 "fadd.<fmt>\t%0,%1,%2" | |
409 [(set_attr "type" "fadd") | |
410 (set_attr "mode" "<UNITMODE>")]) | |
411 | |
412 (define_insn "addsi3" | |
413 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
414 (plus:SI (match_operand:SI 1 "register_operand" " r,r") | |
415 (match_operand:SI 2 "arith_operand" " r,I")))] | |
416 "" | |
417 { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; } | |
418 [(set_attr "type" "arith") | |
419 (set_attr "mode" "SI")]) | |
420 | |
421 (define_insn "adddi3" | |
422 [(set (match_operand:DI 0 "register_operand" "=r,r") | |
423 (plus:DI (match_operand:DI 1 "register_operand" " r,r") | |
424 (match_operand:DI 2 "arith_operand" " r,I")))] | |
425 "TARGET_64BIT" | |
426 "add\t%0,%1,%2" | |
427 [(set_attr "type" "arith") | |
428 (set_attr "mode" "DI")]) | |
429 | |
430 (define_insn "*addsi3_extended" | |
431 [(set (match_operand:DI 0 "register_operand" "=r,r") | |
432 (sign_extend:DI | |
433 (plus:SI (match_operand:SI 1 "register_operand" " r,r") | |
434 (match_operand:SI 2 "arith_operand" " r,I"))))] | |
435 "TARGET_64BIT" | |
436 "addw\t%0,%1,%2" | |
437 [(set_attr "type" "arith") | |
438 (set_attr "mode" "SI")]) | |
439 | |
440 (define_insn "*addsi3_extended2" | |
441 [(set (match_operand:DI 0 "register_operand" "=r,r") | |
442 (sign_extend:DI | |
443 (subreg:SI (plus:DI (match_operand:DI 1 "register_operand" " r,r") | |
444 (match_operand:DI 2 "arith_operand" " r,I")) | |
445 0)))] | |
446 "TARGET_64BIT" | |
447 "addw\t%0,%1,%2" | |
448 [(set_attr "type" "arith") | |
449 (set_attr "mode" "SI")]) | |
450 | |
451 ;; | |
452 ;; .................... | |
453 ;; | |
454 ;; SUBTRACTION | |
455 ;; | |
456 ;; .................... | |
457 ;; | |
458 | |
459 (define_insn "sub<mode>3" | |
460 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
461 (minus:ANYF (match_operand:ANYF 1 "register_operand" " f") | |
462 (match_operand:ANYF 2 "register_operand" " f")))] | |
463 "TARGET_HARD_FLOAT" | |
464 "fsub.<fmt>\t%0,%1,%2" | |
465 [(set_attr "type" "fadd") | |
466 (set_attr "mode" "<UNITMODE>")]) | |
467 | |
468 (define_insn "subdi3" | |
469 [(set (match_operand:DI 0 "register_operand" "= r") | |
470 (minus:DI (match_operand:DI 1 "reg_or_0_operand" " rJ") | |
471 (match_operand:DI 2 "register_operand" " r")))] | |
472 "TARGET_64BIT" | |
473 "sub\t%0,%z1,%2" | |
474 [(set_attr "type" "arith") | |
475 (set_attr "mode" "DI")]) | |
476 | |
477 (define_insn "subsi3" | |
478 [(set (match_operand:SI 0 "register_operand" "= r") | |
479 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ") | |
480 (match_operand:SI 2 "register_operand" " r")))] | |
481 "" | |
482 { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; } | |
483 [(set_attr "type" "arith") | |
484 (set_attr "mode" "SI")]) | |
485 | |
486 (define_insn "*subsi3_extended" | |
487 [(set (match_operand:DI 0 "register_operand" "= r") | |
488 (sign_extend:DI | |
489 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ") | |
490 (match_operand:SI 2 "register_operand" " r"))))] | |
491 "TARGET_64BIT" | |
492 "subw\t%0,%z1,%2" | |
493 [(set_attr "type" "arith") | |
494 (set_attr "mode" "SI")]) | |
495 | |
496 (define_insn "*subsi3_extended2" | |
497 [(set (match_operand:DI 0 "register_operand" "=r") | |
498 (sign_extend:DI | |
499 (subreg:SI (minus:DI (match_operand:DI 1 "reg_or_0_operand" " r") | |
500 (match_operand:DI 2 "register_operand" " r")) | |
501 0)))] | |
502 "TARGET_64BIT" | |
503 "subw\t%0,%z1,%2" | |
504 [(set_attr "type" "arith") | |
505 (set_attr "mode" "SI")]) | |
506 | |
507 ;; | |
508 ;; .................... | |
509 ;; | |
510 ;; MULTIPLICATION | |
511 ;; | |
512 ;; .................... | |
513 ;; | |
514 | |
515 (define_insn "mul<mode>3" | |
516 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
517 (mult:ANYF (match_operand:ANYF 1 "register_operand" " f") | |
518 (match_operand:ANYF 2 "register_operand" " f")))] | |
519 "TARGET_HARD_FLOAT" | |
520 "fmul.<fmt>\t%0,%1,%2" | |
521 [(set_attr "type" "fmul") | |
522 (set_attr "mode" "<UNITMODE>")]) | |
523 | |
524 (define_insn "mulsi3" | |
525 [(set (match_operand:SI 0 "register_operand" "=r") | |
526 (mult:SI (match_operand:SI 1 "register_operand" " r") | |
527 (match_operand:SI 2 "register_operand" " r")))] | |
528 "TARGET_MUL" | |
529 { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; } | |
530 [(set_attr "type" "imul") | |
531 (set_attr "mode" "SI")]) | |
532 | |
533 (define_insn "muldi3" | |
534 [(set (match_operand:DI 0 "register_operand" "=r") | |
535 (mult:DI (match_operand:DI 1 "register_operand" " r") | |
536 (match_operand:DI 2 "register_operand" " r")))] | |
537 "TARGET_MUL && TARGET_64BIT" | |
538 "mul\t%0,%1,%2" | |
539 [(set_attr "type" "imul") | |
540 (set_attr "mode" "DI")]) | |
541 | |
542 (define_insn "*mulsi3_extended" | |
543 [(set (match_operand:DI 0 "register_operand" "=r") | |
544 (sign_extend:DI | |
545 (mult:SI (match_operand:SI 1 "register_operand" " r") | |
546 (match_operand:SI 2 "register_operand" " r"))))] | |
547 "TARGET_MUL && TARGET_64BIT" | |
548 "mulw\t%0,%1,%2" | |
549 [(set_attr "type" "imul") | |
550 (set_attr "mode" "SI")]) | |
551 | |
552 (define_insn "*mulsi3_extended2" | |
553 [(set (match_operand:DI 0 "register_operand" "=r") | |
554 (sign_extend:DI | |
555 (subreg:SI (mult:DI (match_operand:DI 1 "register_operand" " r") | |
556 (match_operand:DI 2 "register_operand" " r")) | |
557 0)))] | |
558 "TARGET_MUL && TARGET_64BIT" | |
559 "mulw\t%0,%1,%2" | |
560 [(set_attr "type" "imul") | |
561 (set_attr "mode" "SI")]) | |
562 | |
563 ;; | |
564 ;; ........................ | |
565 ;; | |
566 ;; MULTIPLICATION HIGH-PART | |
567 ;; | |
568 ;; ........................ | |
569 ;; | |
570 | |
571 | |
572 (define_expand "<u>mulditi3" | |
573 [(set (match_operand:TI 0 "register_operand") | |
574 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand")) | |
575 (any_extend:TI (match_operand:DI 2 "register_operand"))))] | |
576 "TARGET_MUL && TARGET_64BIT" | |
577 { | |
578 rtx low = gen_reg_rtx (DImode); | |
579 emit_insn (gen_muldi3 (low, operands[1], operands[2])); | |
580 | |
581 rtx high = gen_reg_rtx (DImode); | |
582 emit_insn (gen_<u>muldi3_highpart (high, operands[1], operands[2])); | |
583 | |
584 emit_move_insn (gen_lowpart (DImode, operands[0]), low); | |
585 emit_move_insn (gen_highpart (DImode, operands[0]), high); | |
586 DONE; | |
587 }) | |
588 | |
589 (define_insn "<u>muldi3_highpart" | |
590 [(set (match_operand:DI 0 "register_operand" "=r") | |
591 (truncate:DI | |
592 (lshiftrt:TI | |
593 (mult:TI (any_extend:TI | |
594 (match_operand:DI 1 "register_operand" " r")) | |
595 (any_extend:TI | |
596 (match_operand:DI 2 "register_operand" " r"))) | |
597 (const_int 64))))] | |
598 "TARGET_MUL && TARGET_64BIT" | |
599 "mulh<u>\t%0,%1,%2" | |
600 [(set_attr "type" "imul") | |
601 (set_attr "mode" "DI")]) | |
602 | |
603 (define_expand "usmulditi3" | |
604 [(set (match_operand:TI 0 "register_operand") | |
605 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand")) | |
606 (sign_extend:TI (match_operand:DI 2 "register_operand"))))] | |
607 "TARGET_MUL && TARGET_64BIT" | |
608 { | |
609 rtx low = gen_reg_rtx (DImode); | |
610 emit_insn (gen_muldi3 (low, operands[1], operands[2])); | |
611 | |
612 rtx high = gen_reg_rtx (DImode); | |
613 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2])); | |
614 | |
615 emit_move_insn (gen_lowpart (DImode, operands[0]), low); | |
616 emit_move_insn (gen_highpart (DImode, operands[0]), high); | |
617 DONE; | |
618 }) | |
619 | |
620 (define_insn "usmuldi3_highpart" | |
621 [(set (match_operand:DI 0 "register_operand" "=r") | |
622 (truncate:DI | |
623 (lshiftrt:TI | |
624 (mult:TI (zero_extend:TI | |
625 (match_operand:DI 1 "register_operand" "r")) | |
626 (sign_extend:TI | |
627 (match_operand:DI 2 "register_operand" " r"))) | |
628 (const_int 64))))] | |
629 "TARGET_MUL && TARGET_64BIT" | |
630 "mulhsu\t%0,%2,%1" | |
631 [(set_attr "type" "imul") | |
632 (set_attr "mode" "DI")]) | |
633 | |
634 (define_expand "<u>mulsidi3" | |
635 [(set (match_operand:DI 0 "register_operand" "=r") | |
636 (mult:DI (any_extend:DI | |
637 (match_operand:SI 1 "register_operand" " r")) | |
638 (any_extend:DI | |
639 (match_operand:SI 2 "register_operand" " r"))))] | |
640 "TARGET_MUL && !TARGET_64BIT" | |
641 { | |
642 rtx temp = gen_reg_rtx (SImode); | |
643 emit_insn (gen_mulsi3 (temp, operands[1], operands[2])); | |
644 emit_insn (gen_<u>mulsi3_highpart (riscv_subword (operands[0], true), | |
645 operands[1], operands[2])); | |
646 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp)); | |
647 DONE; | |
648 }) | |
649 | |
650 (define_insn "<u>mulsi3_highpart" | |
651 [(set (match_operand:SI 0 "register_operand" "=r") | |
652 (truncate:SI | |
653 (lshiftrt:DI | |
654 (mult:DI (any_extend:DI | |
655 (match_operand:SI 1 "register_operand" " r")) | |
656 (any_extend:DI | |
657 (match_operand:SI 2 "register_operand" " r"))) | |
658 (const_int 32))))] | |
659 "TARGET_MUL && !TARGET_64BIT" | |
660 "mulh<u>\t%0,%1,%2" | |
661 [(set_attr "type" "imul") | |
662 (set_attr "mode" "SI")]) | |
663 | |
664 | |
665 (define_expand "usmulsidi3" | |
666 [(set (match_operand:DI 0 "register_operand" "=r") | |
667 (mult:DI (zero_extend:DI | |
668 (match_operand:SI 1 "register_operand" " r")) | |
669 (sign_extend:DI | |
670 (match_operand:SI 2 "register_operand" " r"))))] | |
671 "TARGET_MUL && !TARGET_64BIT" | |
672 { | |
673 rtx temp = gen_reg_rtx (SImode); | |
674 emit_insn (gen_mulsi3 (temp, operands[1], operands[2])); | |
675 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true), | |
676 operands[1], operands[2])); | |
677 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp)); | |
678 DONE; | |
679 }) | |
680 | |
681 (define_insn "usmulsi3_highpart" | |
682 [(set (match_operand:SI 0 "register_operand" "=r") | |
683 (truncate:SI | |
684 (lshiftrt:DI | |
685 (mult:DI (zero_extend:DI | |
686 (match_operand:SI 1 "register_operand" " r")) | |
687 (sign_extend:DI | |
688 (match_operand:SI 2 "register_operand" " r"))) | |
689 (const_int 32))))] | |
690 "TARGET_MUL && !TARGET_64BIT" | |
691 "mulhsu\t%0,%2,%1" | |
692 [(set_attr "type" "imul") | |
693 (set_attr "mode" "SI")]) | |
694 | |
695 ;; | |
696 ;; .................... | |
697 ;; | |
698 ;; DIVISION and REMAINDER | |
699 ;; | |
700 ;; .................... | |
701 ;; | |
702 | |
703 (define_insn "<optab>si3" | |
704 [(set (match_operand:SI 0 "register_operand" "=r") | |
705 (any_div:SI (match_operand:SI 1 "register_operand" " r") | |
706 (match_operand:SI 2 "register_operand" " r")))] | |
707 "TARGET_DIV" | |
708 { return TARGET_64BIT ? "<insn>w\t%0,%1,%2" : "<insn>\t%0,%1,%2"; } | |
709 [(set_attr "type" "idiv") | |
710 (set_attr "mode" "SI")]) | |
711 | |
712 (define_insn "<optab>di3" | |
713 [(set (match_operand:DI 0 "register_operand" "=r") | |
714 (any_div:DI (match_operand:DI 1 "register_operand" " r") | |
715 (match_operand:DI 2 "register_operand" " r")))] | |
716 "TARGET_DIV && TARGET_64BIT" | |
717 "<insn>\t%0,%1,%2" | |
718 [(set_attr "type" "idiv") | |
719 (set_attr "mode" "DI")]) | |
720 | |
721 (define_insn "*<optab>si3_extended" | |
722 [(set (match_operand:DI 0 "register_operand" "=r") | |
723 (sign_extend:DI | |
724 (any_div:SI (match_operand:SI 1 "register_operand" " r") | |
725 (match_operand:SI 2 "register_operand" " r"))))] | |
726 "TARGET_DIV && TARGET_64BIT" | |
727 "<insn>w\t%0,%1,%2" | |
728 [(set_attr "type" "idiv") | |
729 (set_attr "mode" "DI")]) | |
730 | |
731 (define_insn "div<mode>3" | |
732 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
733 (div:ANYF (match_operand:ANYF 1 "register_operand" " f") | |
734 (match_operand:ANYF 2 "register_operand" " f")))] | |
735 "TARGET_HARD_FLOAT && TARGET_FDIV" | |
736 "fdiv.<fmt>\t%0,%1,%2" | |
737 [(set_attr "type" "fdiv") | |
738 (set_attr "mode" "<UNITMODE>")]) | |
739 | |
740 ;; | |
741 ;; .................... | |
742 ;; | |
743 ;; SQUARE ROOT | |
744 ;; | |
745 ;; .................... | |
746 | |
747 (define_insn "sqrt<mode>2" | |
748 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
749 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))] | |
750 "TARGET_HARD_FLOAT && TARGET_FDIV" | |
751 { | |
752 return "fsqrt.<fmt>\t%0,%1"; | |
753 } | |
754 [(set_attr "type" "fsqrt") | |
755 (set_attr "mode" "<UNITMODE>")]) | |
756 | |
757 ;; Floating point multiply accumulate instructions. | |
758 | |
759 ;; a * b + c | |
760 (define_insn "fma<mode>4" | |
761 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
762 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f") | |
763 (match_operand:ANYF 2 "register_operand" " f") | |
764 (match_operand:ANYF 3 "register_operand" " f")))] | |
765 "TARGET_HARD_FLOAT" | |
766 "fmadd.<fmt>\t%0,%1,%2,%3" | |
767 [(set_attr "type" "fmadd") | |
768 (set_attr "mode" "<UNITMODE>")]) | |
769 | |
770 ;; a * b - c | |
771 (define_insn "fms<mode>4" | |
772 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
773 (fma:ANYF (match_operand:ANYF 1 "register_operand" " f") | |
774 (match_operand:ANYF 2 "register_operand" " f") | |
775 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))] | |
776 "TARGET_HARD_FLOAT" | |
777 "fmsub.<fmt>\t%0,%1,%2,%3" | |
778 [(set_attr "type" "fmadd") | |
779 (set_attr "mode" "<UNITMODE>")]) | |
780 | |
781 ;; -a * b - c | |
782 (define_insn "fnms<mode>4" | |
783 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
784 (fma:ANYF | |
785 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")) | |
786 (match_operand:ANYF 2 "register_operand" " f") | |
787 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))] | |
788 "TARGET_HARD_FLOAT" | |
789 "fnmadd.<fmt>\t%0,%1,%2,%3" | |
790 [(set_attr "type" "fmadd") | |
791 (set_attr "mode" "<UNITMODE>")]) | |
792 | |
793 ;; -a * b + c | |
794 (define_insn "fnma<mode>4" | |
795 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
796 (fma:ANYF | |
797 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")) | |
798 (match_operand:ANYF 2 "register_operand" " f") | |
799 (match_operand:ANYF 3 "register_operand" " f")))] | |
800 "TARGET_HARD_FLOAT" | |
801 "fnmsub.<fmt>\t%0,%1,%2,%3" | |
802 [(set_attr "type" "fmadd") | |
803 (set_attr "mode" "<UNITMODE>")]) | |
804 | |
805 ;; -(-a * b - c), modulo signed zeros | |
806 (define_insn "*fma<mode>4" | |
807 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
808 (neg:ANYF | |
809 (fma:ANYF | |
810 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")) | |
811 (match_operand:ANYF 2 "register_operand" " f") | |
812 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))] | |
813 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)" | |
814 "fmadd.<fmt>\t%0,%1,%2,%3" | |
815 [(set_attr "type" "fmadd") | |
816 (set_attr "mode" "<UNITMODE>")]) | |
817 | |
818 ;; -(-a * b + c), modulo signed zeros | |
819 (define_insn "*fms<mode>4" | |
820 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
821 (neg:ANYF | |
822 (fma:ANYF | |
823 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")) | |
824 (match_operand:ANYF 2 "register_operand" " f") | |
825 (match_operand:ANYF 3 "register_operand" " f"))))] | |
826 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)" | |
827 "fmsub.<fmt>\t%0,%1,%2,%3" | |
828 [(set_attr "type" "fmadd") | |
829 (set_attr "mode" "<UNITMODE>")]) | |
830 | |
831 ;; -(a * b + c), modulo signed zeros | |
832 (define_insn "*fnms<mode>4" | |
833 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
834 (neg:ANYF | |
835 (fma:ANYF | |
836 (match_operand:ANYF 1 "register_operand" " f") | |
837 (match_operand:ANYF 2 "register_operand" " f") | |
838 (match_operand:ANYF 3 "register_operand" " f"))))] | |
839 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)" | |
840 "fnmadd.<fmt>\t%0,%1,%2,%3" | |
841 [(set_attr "type" "fmadd") | |
842 (set_attr "mode" "<UNITMODE>")]) | |
843 | |
844 ;; -(a * b - c), modulo signed zeros | |
845 (define_insn "*fnma<mode>4" | |
846 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
847 (neg:ANYF | |
848 (fma:ANYF | |
849 (match_operand:ANYF 1 "register_operand" " f") | |
850 (match_operand:ANYF 2 "register_operand" " f") | |
851 (neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))] | |
852 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)" | |
853 "fnmsub.<fmt>\t%0,%1,%2,%3" | |
854 [(set_attr "type" "fmadd") | |
855 (set_attr "mode" "<UNITMODE>")]) | |
856 | |
857 ;; | |
858 ;; .................... | |
859 ;; | |
860 ;; SIGN INJECTION | |
861 ;; | |
862 ;; .................... | |
863 | |
864 (define_insn "abs<mode>2" | |
865 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
866 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))] | |
867 "TARGET_HARD_FLOAT" | |
868 "fabs.<fmt>\t%0,%1" | |
869 [(set_attr "type" "fmove") | |
870 (set_attr "mode" "<UNITMODE>")]) | |
871 | |
872 (define_insn "copysign<mode>3" | |
873 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
874 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" " f") | |
875 (match_operand:ANYF 2 "register_operand" " f")] | |
876 UNSPEC_COPYSIGN))] | |
877 "TARGET_HARD_FLOAT" | |
878 "fsgnj.<fmt>\t%0,%1,%2" | |
879 [(set_attr "type" "fmove") | |
880 (set_attr "mode" "<UNITMODE>")]) | |
881 | |
882 (define_insn "neg<mode>2" | |
883 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
884 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))] | |
885 "TARGET_HARD_FLOAT" | |
886 "fneg.<fmt>\t%0,%1" | |
887 [(set_attr "type" "fmove") | |
888 (set_attr "mode" "<UNITMODE>")]) | |
889 | |
890 ;; | |
891 ;; .................... | |
892 ;; | |
893 ;; MIN/MAX | |
894 ;; | |
895 ;; .................... | |
896 | |
897 (define_insn "smin<mode>3" | |
898 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
899 (smin:ANYF (match_operand:ANYF 1 "register_operand" " f") | |
900 (match_operand:ANYF 2 "register_operand" " f")))] | |
901 "TARGET_HARD_FLOAT" | |
902 "fmin.<fmt>\t%0,%1,%2" | |
903 [(set_attr "type" "fmove") | |
904 (set_attr "mode" "<UNITMODE>")]) | |
905 | |
906 (define_insn "smax<mode>3" | |
907 [(set (match_operand:ANYF 0 "register_operand" "=f") | |
908 (smax:ANYF (match_operand:ANYF 1 "register_operand" " f") | |
909 (match_operand:ANYF 2 "register_operand" " f")))] | |
910 "TARGET_HARD_FLOAT" | |
911 "fmax.<fmt>\t%0,%1,%2" | |
912 [(set_attr "type" "fmove") | |
913 (set_attr "mode" "<UNITMODE>")]) | |
914 | |
915 ;; | |
916 ;; .................... | |
917 ;; | |
918 ;; LOGICAL | |
919 ;; | |
920 ;; .................... | |
921 ;; | |
922 | |
923 ;; For RV64, we don't expose the SImode operations to the rtl expanders, | |
924 ;; but SImode versions exist for combine. | |
925 | |
926 (define_insn "<optab><mode>3" | |
927 [(set (match_operand:X 0 "register_operand" "=r,r") | |
928 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r") | |
929 (match_operand:X 2 "arith_operand" " r,I")))] | |
930 "" | |
931 "<insn>\t%0,%1,%2" | |
932 [(set_attr "type" "logical") | |
933 (set_attr "mode" "<MODE>")]) | |
934 | |
935 (define_insn "*<optab>si3_internal" | |
936 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
937 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r") | |
938 (match_operand:SI 2 "arith_operand" " r,I")))] | |
939 "TARGET_64BIT" | |
940 "<insn>\t%0,%1,%2" | |
941 [(set_attr "type" "logical") | |
942 (set_attr "mode" "SI")]) | |
943 | |
944 (define_insn "one_cmpl<mode>2" | |
945 [(set (match_operand:X 0 "register_operand" "=r") | |
946 (not:X (match_operand:X 1 "register_operand" " r")))] | |
947 "" | |
948 "not\t%0,%1" | |
949 [(set_attr "type" "logical") | |
950 (set_attr "mode" "<MODE>")]) | |
951 | |
952 (define_insn "*one_cmplsi2_internal" | |
953 [(set (match_operand:SI 0 "register_operand" "=r") | |
954 (not:SI (match_operand:SI 1 "register_operand" " r")))] | |
955 "TARGET_64BIT" | |
956 "not\t%0,%1" | |
957 [(set_attr "type" "logical") | |
958 (set_attr "mode" "SI")]) | |
959 | |
960 ;; | |
961 ;; .................... | |
962 ;; | |
963 ;; TRUNCATION | |
964 ;; | |
965 ;; .................... | |
966 | |
967 (define_insn "truncdfsf2" | |
968 [(set (match_operand:SF 0 "register_operand" "=f") | |
969 (float_truncate:SF | |
970 (match_operand:DF 1 "register_operand" " f")))] | |
971 "TARGET_DOUBLE_FLOAT" | |
972 "fcvt.s.d\t%0,%1" | |
973 [(set_attr "type" "fcvt") | |
974 (set_attr "mode" "SF")]) | |
975 | |
976 ;; | |
977 ;; .................... | |
978 ;; | |
979 ;; ZERO EXTENSION | |
980 ;; | |
981 ;; .................... | |
982 | |
983 ;; Extension insns. | |
984 | |
985 (define_insn_and_split "zero_extendsidi2" | |
986 [(set (match_operand:DI 0 "register_operand" "=r,r") | |
987 (zero_extend:DI | |
988 (match_operand:SI 1 "nonimmediate_operand" " r,m")))] | |
989 "TARGET_64BIT" | |
990 "@ | |
991 # | |
992 lwu\t%0,%1" | |
993 "&& reload_completed && REG_P (operands[1])" | |
994 [(set (match_dup 0) | |
995 (ashift:DI (match_dup 1) (const_int 32))) | |
996 (set (match_dup 0) | |
997 (lshiftrt:DI (match_dup 0) (const_int 32)))] | |
998 { operands[1] = gen_lowpart (DImode, operands[1]); } | |
999 [(set_attr "move_type" "shift_shift,load") | |
1000 (set_attr "mode" "DI")]) | |
1001 | |
1002 (define_insn_and_split "zero_extendhi<GPR:mode>2" | |
1003 [(set (match_operand:GPR 0 "register_operand" "=r,r") | |
1004 (zero_extend:GPR | |
1005 (match_operand:HI 1 "nonimmediate_operand" " r,m")))] | |
1006 "" | |
1007 "@ | |
1008 # | |
1009 lhu\t%0,%1" | |
1010 "&& reload_completed && REG_P (operands[1])" | |
1011 [(set (match_dup 0) | |
1012 (ashift:GPR (match_dup 1) (match_dup 2))) | |
1013 (set (match_dup 0) | |
1014 (lshiftrt:GPR (match_dup 0) (match_dup 2)))] | |
1015 { | |
1016 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]); | |
1017 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16); | |
1018 } | |
1019 [(set_attr "move_type" "shift_shift,load") | |
1020 (set_attr "mode" "<GPR:MODE>")]) | |
1021 | |
1022 (define_insn "zero_extendqi<SUPERQI:mode>2" | |
1023 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r") | |
1024 (zero_extend:SUPERQI | |
1025 (match_operand:QI 1 "nonimmediate_operand" " r,m")))] | |
1026 "" | |
1027 "@ | |
1028 and\t%0,%1,0xff | |
1029 lbu\t%0,%1" | |
1030 [(set_attr "move_type" "andi,load") | |
1031 (set_attr "mode" "<SUPERQI:MODE>")]) | |
1032 | |
1033 ;; | |
1034 ;; .................... | |
1035 ;; | |
1036 ;; SIGN EXTENSION | |
1037 ;; | |
1038 ;; .................... | |
1039 | |
1040 (define_insn "extendsidi2" | |
1041 [(set (match_operand:DI 0 "register_operand" "=r,r") | |
1042 (sign_extend:DI | |
1043 (match_operand:SI 1 "nonimmediate_operand" " r,m")))] | |
1044 "TARGET_64BIT" | |
1045 "@ | |
1046 sext.w\t%0,%1 | |
1047 lw\t%0,%1" | |
1048 [(set_attr "move_type" "move,load") | |
1049 (set_attr "mode" "DI")]) | |
1050 | |
1051 (define_insn_and_split "extend<SHORT:mode><SUPERQI:mode>2" | |
1052 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r") | |
1053 (sign_extend:SUPERQI | |
1054 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))] | |
1055 "" | |
1056 "@ | |
1057 # | |
1058 l<SHORT:size>\t%0,%1" | |
1059 "&& reload_completed && REG_P (operands[1])" | |
1060 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) | |
1061 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))] | |
1062 { | |
1063 operands[0] = gen_lowpart (SImode, operands[0]); | |
1064 operands[1] = gen_lowpart (SImode, operands[1]); | |
1065 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode) | |
1066 - GET_MODE_BITSIZE (<SHORT:MODE>mode)); | |
1067 } | |
1068 [(set_attr "move_type" "shift_shift,load") | |
1069 (set_attr "mode" "SI")]) | |
1070 | |
1071 (define_insn "extendsfdf2" | |
1072 [(set (match_operand:DF 0 "register_operand" "=f") | |
1073 (float_extend:DF | |
1074 (match_operand:SF 1 "register_operand" " f")))] | |
1075 "TARGET_DOUBLE_FLOAT" | |
1076 "fcvt.d.s\t%0,%1" | |
1077 [(set_attr "type" "fcvt") | |
1078 (set_attr "mode" "DF")]) | |
1079 | |
1080 ;; | |
1081 ;; .................... | |
1082 ;; | |
1083 ;; CONVERSIONS | |
1084 ;; | |
1085 ;; .................... | |
1086 | |
1087 (define_insn "fix_trunc<ANYF:mode><GPR:mode>2" | |
1088 [(set (match_operand:GPR 0 "register_operand" "=r") | |
1089 (fix:GPR | |
1090 (match_operand:ANYF 1 "register_operand" " f")))] | |
1091 "TARGET_HARD_FLOAT" | |
1092 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz" | |
1093 [(set_attr "type" "fcvt") | |
1094 (set_attr "mode" "<ANYF:MODE>")]) | |
1095 | |
1096 (define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2" | |
1097 [(set (match_operand:GPR 0 "register_operand" "=r") | |
1098 (unsigned_fix:GPR | |
1099 (match_operand:ANYF 1 "register_operand" " f")))] | |
1100 "TARGET_HARD_FLOAT" | |
1101 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz" | |
1102 [(set_attr "type" "fcvt") | |
1103 (set_attr "mode" "<ANYF:MODE>")]) | |
1104 | |
1105 (define_insn "float<GPR:mode><ANYF:mode>2" | |
1106 [(set (match_operand:ANYF 0 "register_operand" "= f") | |
1107 (float:ANYF | |
1108 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))] | |
1109 "TARGET_HARD_FLOAT" | |
1110 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1" | |
1111 [(set_attr "type" "fcvt") | |
1112 (set_attr "mode" "<ANYF:MODE>")]) | |
1113 | |
1114 (define_insn "floatuns<GPR:mode><ANYF:mode>2" | |
1115 [(set (match_operand:ANYF 0 "register_operand" "= f") | |
1116 (unsigned_float:ANYF | |
1117 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))] | |
1118 "TARGET_HARD_FLOAT" | |
1119 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1" | |
1120 [(set_attr "type" "fcvt") | |
1121 (set_attr "mode" "<ANYF:MODE>")]) | |
1122 | |
1123 (define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2" | |
1124 [(set (match_operand:GPR 0 "register_operand" "=r") | |
1125 (unspec:GPR | |
1126 [(match_operand:ANYF 1 "register_operand" " f")] | |
1127 RINT))] | |
1128 "TARGET_HARD_FLOAT" | |
1129 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>" | |
1130 [(set_attr "type" "fcvt") | |
1131 (set_attr "mode" "<ANYF:MODE>")]) | |
1132 | |
1133 ;; | |
1134 ;; .................... | |
1135 ;; | |
1136 ;; DATA MOVEMENT | |
1137 ;; | |
1138 ;; .................... | |
1139 | |
1140 ;; Lower-level instructions for loading an address from the GOT. | |
1141 ;; We could use MEMs, but an unspec gives more optimization | |
1142 ;; opportunities. | |
1143 | |
1144 (define_insn "got_load<mode>" | |
1145 [(set (match_operand:P 0 "register_operand" "=r") | |
1146 (unspec:P | |
1147 [(match_operand:P 1 "symbolic_operand" "")] | |
1148 UNSPEC_LOAD_GOT))] | |
1149 "" | |
1150 "la\t%0,%1" | |
1151 [(set_attr "got" "load") | |
1152 (set_attr "mode" "<MODE>")]) | |
1153 | |
1154 (define_insn "tls_add_tp_le<mode>" | |
1155 [(set (match_operand:P 0 "register_operand" "=r") | |
1156 (unspec:P | |
1157 [(match_operand:P 1 "register_operand" "r") | |
1158 (match_operand:P 2 "register_operand" "r") | |
1159 (match_operand:P 3 "symbolic_operand" "")] | |
1160 UNSPEC_TLS_LE))] | |
1161 "" | |
1162 "add\t%0,%1,%2,%%tprel_add(%3)" | |
1163 [(set_attr "type" "arith") | |
1164 (set_attr "mode" "<MODE>")]) | |
1165 | |
1166 (define_insn "got_load_tls_gd<mode>" | |
1167 [(set (match_operand:P 0 "register_operand" "=r") | |
1168 (unspec:P | |
1169 [(match_operand:P 1 "symbolic_operand" "")] | |
1170 UNSPEC_TLS_GD))] | |
1171 "" | |
1172 "la.tls.gd\t%0,%1" | |
1173 [(set_attr "got" "load") | |
1174 (set_attr "mode" "<MODE>")]) | |
1175 | |
1176 (define_insn "got_load_tls_ie<mode>" | |
1177 [(set (match_operand:P 0 "register_operand" "=r") | |
1178 (unspec:P | |
1179 [(match_operand:P 1 "symbolic_operand" "")] | |
1180 UNSPEC_TLS_IE))] | |
1181 "" | |
1182 "la.tls.ie\t%0,%1" | |
1183 [(set_attr "got" "load") | |
1184 (set_attr "mode" "<MODE>")]) | |
1185 | |
1186 (define_insn "auipc<mode>" | |
1187 [(set (match_operand:P 0 "register_operand" "=r") | |
1188 (unspec:P | |
1189 [(match_operand:P 1 "symbolic_operand" "") | |
1190 (match_operand:P 2 "const_int_operand") | |
1191 (pc)] | |
1192 UNSPEC_AUIPC))] | |
1193 "" | |
1194 ".LA%2: auipc\t%0,%h1" | |
1195 [(set_attr "type" "arith") | |
1196 (set_attr "cannot_copy" "yes")]) | |
1197 | |
1198 ;; Instructions for adding the low 12 bits of an address to a register. | |
1199 ;; Operand 2 is the address: riscv_print_operand works out which relocation | |
1200 ;; should be applied. | |
1201 | |
1202 (define_insn "*low<mode>" | |
1203 [(set (match_operand:P 0 "register_operand" "=r") | |
1204 (lo_sum:P (match_operand:P 1 "register_operand" " r") | |
1205 (match_operand:P 2 "symbolic_operand" "")))] | |
1206 "" | |
1207 "addi\t%0,%1,%R2" | |
1208 [(set_attr "type" "arith") | |
1209 (set_attr "mode" "<MODE>")]) | |
1210 | |
1211 ;; Allow combine to split complex const_int load sequences, using operand 2 | |
1212 ;; to store the intermediate results. See move_operand for details. | |
1213 (define_split | |
1214 [(set (match_operand:GPR 0 "register_operand") | |
1215 (match_operand:GPR 1 "splittable_const_int_operand")) | |
1216 (clobber (match_operand:GPR 2 "register_operand"))] | |
1217 "" | |
1218 [(const_int 0)] | |
1219 { | |
1220 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1])); | |
1221 DONE; | |
1222 }) | |
1223 | |
1224 ;; Likewise, for symbolic operands. | |
1225 (define_split | |
1226 [(set (match_operand:P 0 "register_operand") | |
1227 (match_operand:P 1)) | |
1228 (clobber (match_operand:P 2 "register_operand"))] | |
1229 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)" | |
1230 [(set (match_dup 0) (match_dup 3))] | |
1231 { | |
1232 riscv_split_symbol (operands[2], operands[1], | |
1233 MAX_MACHINE_MODE, &operands[3]); | |
1234 }) | |
1235 | |
1236 ;; 64-bit integer moves | |
1237 | |
1238 (define_expand "movdi" | |
1239 [(set (match_operand:DI 0 "") | |
1240 (match_operand:DI 1 ""))] | |
1241 "" | |
1242 { | |
1243 if (riscv_legitimize_move (DImode, operands[0], operands[1])) | |
1244 DONE; | |
1245 }) | |
1246 | |
1247 (define_insn "*movdi_32bit" | |
1248 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m") | |
1249 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))] | |
1250 "!TARGET_64BIT | |
1251 && (register_operand (operands[0], DImode) | |
1252 || reg_or_0_operand (operands[1], DImode))" | |
1253 { return riscv_output_move (operands[0], operands[1]); } | |
1254 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore") | |
1255 (set_attr "mode" "DI")]) | |
1256 | |
1257 (define_insn "*movdi_64bit" | |
1258 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m") | |
1259 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))] | |
1260 "TARGET_64BIT | |
1261 && (register_operand (operands[0], DImode) | |
1262 || reg_or_0_operand (operands[1], DImode))" | |
1263 { return riscv_output_move (operands[0], operands[1]); } | |
1264 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore") | |
1265 (set_attr "mode" "DI")]) | |
1266 | |
1267 ;; 32-bit Integer moves | |
1268 | |
1269 (define_expand "mov<mode>" | |
1270 [(set (match_operand:MOVE32 0 "") | |
1271 (match_operand:MOVE32 1 ""))] | |
1272 "" | |
1273 { | |
1274 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1])) | |
1275 DONE; | |
1276 }) | |
1277 | |
1278 (define_insn "*movsi_internal" | |
1279 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m") | |
1280 (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f"))] | |
1281 "(register_operand (operands[0], SImode) | |
1282 || reg_or_0_operand (operands[1], SImode))" | |
1283 { return riscv_output_move (operands[0], operands[1]); } | |
1284 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore") | |
1285 (set_attr "mode" "SI")]) | |
1286 | |
1287 ;; 16-bit Integer moves | |
1288 | |
1289 ;; Unlike most other insns, the move insns can't be split with | |
1290 ;; different predicates, because register spilling and other parts of | |
1291 ;; the compiler, have memoized the insn number already. | |
1292 ;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND. | |
1293 | |
1294 (define_expand "movhi" | |
1295 [(set (match_operand:HI 0 "") | |
1296 (match_operand:HI 1 ""))] | |
1297 "" | |
1298 { | |
1299 if (riscv_legitimize_move (HImode, operands[0], operands[1])) | |
1300 DONE; | |
1301 }) | |
1302 | |
1303 (define_insn "*movhi_internal" | |
1304 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r") | |
1305 (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f"))] | |
1306 "(register_operand (operands[0], HImode) | |
1307 || reg_or_0_operand (operands[1], HImode))" | |
1308 { return riscv_output_move (operands[0], operands[1]); } | |
1309 [(set_attr "move_type" "move,const,load,store,mtc,mfc") | |
1310 (set_attr "mode" "HI")]) | |
1311 | |
1312 ;; HImode constant generation; see riscv_move_integer for details. | |
1313 ;; si+si->hi without truncation is legal because of | |
1314 ;; TARGET_TRULY_NOOP_TRUNCATION. | |
1315 | |
1316 (define_insn "*add<mode>hi3" | |
1317 [(set (match_operand:HI 0 "register_operand" "=r,r") | |
1318 (plus:HI (match_operand:HISI 1 "register_operand" " r,r") | |
1319 (match_operand:HISI 2 "arith_operand" " r,I")))] | |
1320 "" | |
1321 { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; } | |
1322 [(set_attr "type" "arith") | |
1323 (set_attr "mode" "HI")]) | |
1324 | |
1325 (define_insn "*xor<mode>hi3" | |
1326 [(set (match_operand:HI 0 "register_operand" "=r,r") | |
1327 (xor:HI (match_operand:HISI 1 "register_operand" " r,r") | |
1328 (match_operand:HISI 2 "arith_operand" " r,I")))] | |
1329 "" | |
1330 "xor\t%0,%1,%2" | |
1331 [(set_attr "type" "logical") | |
1332 (set_attr "mode" "HI")]) | |
1333 | |
1334 ;; 8-bit Integer moves | |
1335 | |
1336 (define_expand "movqi" | |
1337 [(set (match_operand:QI 0 "") | |
1338 (match_operand:QI 1 ""))] | |
1339 "" | |
1340 { | |
1341 if (riscv_legitimize_move (QImode, operands[0], operands[1])) | |
1342 DONE; | |
1343 }) | |
1344 | |
1345 (define_insn "*movqi_internal" | |
1346 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r") | |
1347 (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f"))] | |
1348 "(register_operand (operands[0], QImode) | |
1349 || reg_or_0_operand (operands[1], QImode))" | |
1350 { return riscv_output_move (operands[0], operands[1]); } | |
1351 [(set_attr "move_type" "move,const,load,store,mtc,mfc") | |
1352 (set_attr "mode" "QI")]) | |
1353 | |
1354 ;; 32-bit floating point moves | |
1355 | |
1356 (define_expand "movsf" | |
1357 [(set (match_operand:SF 0 "") | |
1358 (match_operand:SF 1 ""))] | |
1359 "" | |
1360 { | |
1361 if (riscv_legitimize_move (SFmode, operands[0], operands[1])) | |
1362 DONE; | |
1363 }) | |
1364 | |
1365 (define_insn "*movsf_hardfloat" | |
1366 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m") | |
1367 (match_operand:SF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))] | |
1368 "TARGET_HARD_FLOAT | |
1369 && (register_operand (operands[0], SFmode) | |
1370 || reg_or_0_operand (operands[1], SFmode))" | |
1371 { return riscv_output_move (operands[0], operands[1]); } | |
1372 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") | |
1373 (set_attr "mode" "SF")]) | |
1374 | |
1375 (define_insn "*movsf_softfloat" | |
1376 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m") | |
1377 (match_operand:SF 1 "move_operand" " Gr,m,r"))] | |
1378 "!TARGET_HARD_FLOAT | |
1379 && (register_operand (operands[0], SFmode) | |
1380 || reg_or_0_operand (operands[1], SFmode))" | |
1381 { return riscv_output_move (operands[0], operands[1]); } | |
1382 [(set_attr "move_type" "move,load,store") | |
1383 (set_attr "mode" "SF")]) | |
1384 | |
1385 ;; 64-bit floating point moves | |
1386 | |
1387 (define_expand "movdf" | |
1388 [(set (match_operand:DF 0 "") | |
1389 (match_operand:DF 1 ""))] | |
1390 "" | |
1391 { | |
1392 if (riscv_legitimize_move (DFmode, operands[0], operands[1])) | |
1393 DONE; | |
1394 }) | |
1395 | |
1396 ;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead. | |
1397 ;; (However, we can still use fcvt.d.w to zero a floating-point register.) | |
1398 (define_insn "*movdf_hardfloat_rv32" | |
1399 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m") | |
1400 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))] | |
1401 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT | |
1402 && (register_operand (operands[0], DFmode) | |
1403 || reg_or_0_operand (operands[1], DFmode))" | |
1404 { return riscv_output_move (operands[0], operands[1]); } | |
1405 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store") | |
1406 (set_attr "mode" "DF")]) | |
1407 | |
1408 (define_insn "*movdf_hardfloat_rv64" | |
1409 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m") | |
1410 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))] | |
1411 "TARGET_64BIT && TARGET_DOUBLE_FLOAT | |
1412 && (register_operand (operands[0], DFmode) | |
1413 || reg_or_0_operand (operands[1], DFmode))" | |
1414 { return riscv_output_move (operands[0], operands[1]); } | |
1415 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") | |
1416 (set_attr "mode" "DF")]) | |
1417 | |
1418 (define_insn "*movdf_softfloat" | |
1419 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m") | |
1420 (match_operand:DF 1 "move_operand" " rG,m,rG"))] | |
1421 "!TARGET_DOUBLE_FLOAT | |
1422 && (register_operand (operands[0], DFmode) | |
1423 || reg_or_0_operand (operands[1], DFmode))" | |
1424 { return riscv_output_move (operands[0], operands[1]); } | |
1425 [(set_attr "move_type" "move,load,store") | |
1426 (set_attr "mode" "DF")]) | |
1427 | |
1428 (define_split | |
1429 [(set (match_operand:MOVE64 0 "nonimmediate_operand") | |
1430 (match_operand:MOVE64 1 "move_operand"))] | |
1431 "reload_completed | |
1432 && riscv_split_64bit_move_p (operands[0], operands[1])" | |
1433 [(const_int 0)] | |
1434 { | |
1435 riscv_split_doubleword_move (operands[0], operands[1]); | |
1436 DONE; | |
1437 }) | |
1438 | |
1439 ;; Expand in-line code to clear the instruction cache between operand[0] and | |
1440 ;; operand[1]. | |
1441 (define_expand "clear_cache" | |
1442 [(match_operand 0 "pmode_register_operand") | |
1443 (match_operand 1 "pmode_register_operand")] | |
1444 "" | |
1445 { | |
1446 emit_insn (gen_fence_i ()); | |
1447 DONE; | |
1448 }) | |
1449 | |
1450 (define_insn "fence" | |
1451 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)] | |
1452 "" | |
1453 "%|fence%-") | |
1454 | |
1455 (define_insn "fence_i" | |
1456 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)] | |
1457 "" | |
1458 "fence.i") | |
1459 | |
1460 ;; | |
1461 ;; .................... | |
1462 ;; | |
1463 ;; SHIFTS | |
1464 ;; | |
1465 ;; .................... | |
1466 | |
1467 (define_insn "<optab>si3" | |
1468 [(set (match_operand:SI 0 "register_operand" "= r") | |
1469 (any_shift:SI | |
1470 (match_operand:SI 1 "register_operand" " r") | |
1471 (match_operand:SI 2 "arith_operand" " rI")))] | |
1472 "" | |
1473 { | |
1474 if (GET_CODE (operands[2]) == CONST_INT) | |
1475 operands[2] = GEN_INT (INTVAL (operands[2]) | |
1476 & (GET_MODE_BITSIZE (SImode) - 1)); | |
1477 | |
1478 return TARGET_64BIT ? "<insn>w\t%0,%1,%2" : "<insn>\t%0,%1,%2"; | |
1479 } | |
1480 [(set_attr "type" "shift") | |
1481 (set_attr "mode" "SI")]) | |
1482 | |
1483 (define_insn "<optab>di3" | |
1484 [(set (match_operand:DI 0 "register_operand" "= r") | |
1485 (any_shift:DI | |
1486 (match_operand:DI 1 "register_operand" " r") | |
1487 (match_operand:DI 2 "arith_operand" " rI")))] | |
1488 "TARGET_64BIT" | |
1489 { | |
1490 if (GET_CODE (operands[2]) == CONST_INT) | |
1491 operands[2] = GEN_INT (INTVAL (operands[2]) | |
1492 & (GET_MODE_BITSIZE (DImode) - 1)); | |
1493 | |
1494 return "<insn>\t%0,%1,%2"; | |
1495 } | |
1496 [(set_attr "type" "shift") | |
1497 (set_attr "mode" "DI")]) | |
1498 | |
1499 (define_insn "*<optab>si3_extend" | |
1500 [(set (match_operand:DI 0 "register_operand" "= r") | |
1501 (sign_extend:DI | |
1502 (any_shift:SI (match_operand:SI 1 "register_operand" " r") | |
1503 (match_operand:SI 2 "arith_operand" " rI"))))] | |
1504 "TARGET_64BIT" | |
1505 { | |
1506 if (GET_CODE (operands[2]) == CONST_INT) | |
1507 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); | |
1508 | |
1509 return "<insn>w\t%0,%1,%2"; | |
1510 } | |
1511 [(set_attr "type" "shift") | |
1512 (set_attr "mode" "SI")]) | |
1513 | |
1514 ;; | |
1515 ;; .................... | |
1516 ;; | |
1517 ;; CONDITIONAL BRANCHES | |
1518 ;; | |
1519 ;; .................... | |
1520 | |
1521 ;; Conditional branches | |
1522 | |
1523 (define_insn "*branch_order<mode>" | |
1524 [(set (pc) | |
1525 (if_then_else | |
1526 (match_operator 1 "order_operator" | |
1527 [(match_operand:X 2 "register_operand" "r") | |
1528 (match_operand:X 3 "register_operand" "r")]) | |
1529 (label_ref (match_operand 0 "" "")) | |
1530 (pc)))] | |
1531 "" | |
1532 "b%C1\t%2,%3,%0" | |
1533 [(set_attr "type" "branch") | |
1534 (set_attr "mode" "none")]) | |
1535 | |
1536 (define_insn "*branch_zero<mode>" | |
1537 [(set (pc) | |
1538 (if_then_else | |
1539 (match_operator 1 "signed_order_operator" | |
1540 [(match_operand:X 2 "register_operand" "r") | |
1541 (const_int 0)]) | |
1542 (label_ref (match_operand 0 "" "")) | |
1543 (pc)))] | |
1544 "" | |
1545 "b%C1z\t%2,%0" | |
1546 [(set_attr "type" "branch") | |
1547 (set_attr "mode" "none")]) | |
1548 | |
1549 ;; Used to implement built-in functions. | |
1550 (define_expand "condjump" | |
1551 [(set (pc) | |
1552 (if_then_else (match_operand 0) | |
1553 (label_ref (match_operand 1)) | |
1554 (pc)))]) | |
1555 | |
1556 (define_expand "cbranch<mode>4" | |
1557 [(set (pc) | |
1558 (if_then_else (match_operator 0 "comparison_operator" | |
1559 [(match_operand:BR 1 "register_operand") | |
1560 (match_operand:BR 2 "nonmemory_operand")]) | |
1561 (label_ref (match_operand 3 "")) | |
1562 (pc)))] | |
1563 "" | |
1564 { | |
1565 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]), | |
1566 operands[1], operands[2]); | |
1567 DONE; | |
1568 }) | |
1569 | |
1570 (define_expand "cbranch<mode>4" | |
1571 [(set (pc) | |
1572 (if_then_else (match_operator 0 "fp_branch_comparison" | |
1573 [(match_operand:ANYF 1 "register_operand") | |
1574 (match_operand:ANYF 2 "register_operand")]) | |
1575 (label_ref (match_operand 3 "")) | |
1576 (pc)))] | |
1577 "TARGET_HARD_FLOAT" | |
1578 { | |
1579 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]), | |
1580 operands[1], operands[2]); | |
1581 DONE; | |
1582 }) | |
1583 | |
1584 (define_insn_and_split "*branch_on_bit<X:mode>" | |
1585 [(set (pc) | |
1586 (if_then_else | |
1587 (match_operator 0 "equality_operator" | |
1588 [(zero_extract:X (match_operand:X 2 "register_operand" "r") | |
1589 (const_int 1) | |
1590 (match_operand 3 "branch_on_bit_operand")) | |
1591 (const_int 0)]) | |
1592 (label_ref (match_operand 1)) | |
1593 (pc))) | |
1594 (clobber (match_scratch:X 4 "=&r"))] | |
1595 "" | |
1596 "#" | |
1597 "reload_completed" | |
1598 [(set (match_dup 4) | |
1599 (ashift:X (match_dup 2) (match_dup 3))) | |
1600 (set (pc) | |
1601 (if_then_else | |
1602 (match_op_dup 0 [(match_dup 4) (const_int 0)]) | |
1603 (label_ref (match_operand 1)) | |
1604 (pc)))] | |
1605 { | |
1606 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]); | |
1607 operands[3] = GEN_INT (shift); | |
1608 | |
1609 if (GET_CODE (operands[0]) == EQ) | |
1610 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx); | |
1611 else | |
1612 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx); | |
1613 }) | |
1614 | |
1615 (define_insn_and_split "*branch_on_bit_range<X:mode>" | |
1616 [(set (pc) | |
1617 (if_then_else | |
1618 (match_operator 0 "equality_operator" | |
1619 [(zero_extract:X (match_operand:X 2 "register_operand" "r") | |
1620 (match_operand 3 "branch_on_bit_operand") | |
1621 (const_int 0)) | |
1622 (const_int 0)]) | |
1623 (label_ref (match_operand 1)) | |
1624 (pc))) | |
1625 (clobber (match_scratch:X 4 "=&r"))] | |
1626 "" | |
1627 "#" | |
1628 "reload_completed" | |
1629 [(set (match_dup 4) | |
1630 (ashift:X (match_dup 2) (match_dup 3))) | |
1631 (set (pc) | |
1632 (if_then_else | |
1633 (match_op_dup 0 [(match_dup 4) (const_int 0)]) | |
1634 (label_ref (match_operand 1)) | |
1635 (pc)))] | |
1636 { | |
1637 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3])); | |
1638 }) | |
1639 | |
1640 ;; | |
1641 ;; .................... | |
1642 ;; | |
1643 ;; SETTING A REGISTER FROM A COMPARISON | |
1644 ;; | |
1645 ;; .................... | |
1646 | |
1647 ;; Destination is always set in SI mode. | |
1648 | |
1649 (define_expand "cstore<mode>4" | |
1650 [(set (match_operand:SI 0 "register_operand") | |
1651 (match_operator:SI 1 "order_operator" | |
1652 [(match_operand:GPR 2 "register_operand") | |
1653 (match_operand:GPR 3 "nonmemory_operand")]))] | |
1654 "" | |
1655 { | |
1656 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2], | |
1657 operands[3]); | |
1658 DONE; | |
1659 }) | |
1660 | |
1661 (define_expand "cstore<mode>4" | |
1662 [(set (match_operand:SI 0 "register_operand") | |
1663 (match_operator:SI 1 "fp_scc_comparison" | |
1664 [(match_operand:ANYF 2 "register_operand") | |
1665 (match_operand:ANYF 3 "register_operand")]))] | |
1666 "TARGET_HARD_FLOAT" | |
1667 { | |
1668 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2], | |
1669 operands[3]); | |
1670 DONE; | |
1671 }) | |
1672 | |
1673 (define_insn "*cstore<ANYF:mode><X:mode>4" | |
1674 [(set (match_operand:X 0 "register_operand" "=r") | |
1675 (match_operator:X 1 "fp_native_comparison" | |
1676 [(match_operand:ANYF 2 "register_operand" " f") | |
1677 (match_operand:ANYF 3 "register_operand" " f")]))] | |
1678 "TARGET_HARD_FLOAT" | |
1679 "f%C1.<fmt>\t%0,%2,%3" | |
1680 [(set_attr "type" "fcmp") | |
1681 (set_attr "mode" "<UNITMODE>")]) | |
1682 | |
1683 (define_insn "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4" | |
1684 [(set (match_operand:X 0 "register_operand" "=r") | |
1685 (unspec:X | |
1686 [(match_operand:ANYF 1 "register_operand" " f") | |
1687 (match_operand:ANYF 2 "register_operand" " f")] | |
1688 QUIET_COMPARISON)) | |
1689 (clobber (match_scratch:X 3 "=&r"))] | |
1690 "TARGET_HARD_FLOAT" | |
1691 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3" | |
1692 [(set_attr "type" "fcmp") | |
1693 (set_attr "mode" "<UNITMODE>") | |
1694 (set (attr "length") (const_int 12))]) | |
1695 | |
1696 (define_insn "*seq_zero_<X:mode><GPR:mode>" | |
1697 [(set (match_operand:GPR 0 "register_operand" "=r") | |
1698 (eq:GPR (match_operand:X 1 "register_operand" " r") | |
1699 (const_int 0)))] | |
1700 "" | |
1701 "seqz\t%0,%1" | |
1702 [(set_attr "type" "slt") | |
1703 (set_attr "mode" "<X:MODE>")]) | |
1704 | |
1705 (define_insn "*sne_zero_<X:mode><GPR:mode>" | |
1706 [(set (match_operand:GPR 0 "register_operand" "=r") | |
1707 (ne:GPR (match_operand:X 1 "register_operand" " r") | |
1708 (const_int 0)))] | |
1709 "" | |
1710 "snez\t%0,%1" | |
1711 [(set_attr "type" "slt") | |
1712 (set_attr "mode" "<X:MODE>")]) | |
1713 | |
1714 (define_insn "*sgt<u>_<X:mode><GPR:mode>" | |
1715 [(set (match_operand:GPR 0 "register_operand" "= r") | |
1716 (any_gt:GPR (match_operand:X 1 "register_operand" " r") | |
1717 (match_operand:X 2 "reg_or_0_operand" " rJ")))] | |
1718 "" | |
1719 "sgt<u>\t%0,%1,%z2" | |
1720 [(set_attr "type" "slt") | |
1721 (set_attr "mode" "<X:MODE>")]) | |
1722 | |
1723 (define_insn "*sge<u>_<X:mode><GPR:mode>" | |
1724 [(set (match_operand:GPR 0 "register_operand" "=r") | |
1725 (any_ge:GPR (match_operand:X 1 "register_operand" " r") | |
1726 (const_int 1)))] | |
1727 "" | |
1728 "slt<u>\t%0,zero,%1" | |
1729 [(set_attr "type" "slt") | |
1730 (set_attr "mode" "<MODE>")]) | |
1731 | |
1732 (define_insn "*slt<u>_<X:mode><GPR:mode>" | |
1733 [(set (match_operand:GPR 0 "register_operand" "= r") | |
1734 (any_lt:GPR (match_operand:X 1 "register_operand" " r") | |
1735 (match_operand:X 2 "arith_operand" " rI")))] | |
1736 "" | |
1737 "slt<u>\t%0,%1,%2" | |
1738 [(set_attr "type" "slt") | |
1739 (set_attr "mode" "<MODE>")]) | |
1740 | |
1741 (define_insn "*sle<u>_<X:mode><GPR:mode>" | |
1742 [(set (match_operand:GPR 0 "register_operand" "=r") | |
1743 (any_le:GPR (match_operand:X 1 "register_operand" " r") | |
1744 (match_operand:X 2 "sle_operand" "")))] | |
1745 "" | |
1746 { | |
1747 operands[2] = GEN_INT (INTVAL (operands[2]) + 1); | |
1748 return "slt<u>\t%0,%1,%2"; | |
1749 } | |
1750 [(set_attr "type" "slt") | |
1751 (set_attr "mode" "<MODE>")]) | |
1752 | |
1753 ;; | |
1754 ;; .................... | |
1755 ;; | |
1756 ;; UNCONDITIONAL BRANCHES | |
1757 ;; | |
1758 ;; .................... | |
1759 | |
1760 ;; Unconditional branches. | |
1761 | |
1762 (define_insn "jump" | |
1763 [(set (pc) | |
1764 (label_ref (match_operand 0 "" "")))] | |
1765 "" | |
1766 "j\t%l0" | |
1767 [(set_attr "type" "jump") | |
1768 (set_attr "mode" "none")]) | |
1769 | |
1770 (define_expand "indirect_jump" | |
1771 [(set (pc) (match_operand 0 "register_operand"))] | |
1772 "" | |
1773 { | |
1774 operands[0] = force_reg (Pmode, operands[0]); | |
1775 if (Pmode == SImode) | |
1776 emit_jump_insn (gen_indirect_jumpsi (operands[0])); | |
1777 else | |
1778 emit_jump_insn (gen_indirect_jumpdi (operands[0])); | |
1779 DONE; | |
1780 }) | |
1781 | |
1782 (define_insn "indirect_jump<mode>" | |
1783 [(set (pc) (match_operand:P 0 "register_operand" "l"))] | |
1784 "" | |
1785 "jr\t%0" | |
1786 [(set_attr "type" "jump") | |
1787 (set_attr "mode" "none")]) | |
1788 | |
1789 (define_expand "tablejump" | |
1790 [(set (pc) (match_operand 0 "register_operand" "")) | |
1791 (use (label_ref (match_operand 1 "" "")))] | |
1792 "" | |
1793 { | |
1794 if (CASE_VECTOR_PC_RELATIVE) | |
1795 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0], | |
1796 gen_rtx_LABEL_REF (Pmode, operands[1]), | |
1797 NULL_RTX, 0, OPTAB_DIRECT); | |
1798 | |
1799 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode) | |
1800 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); | |
1801 else | |
1802 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); | |
1803 DONE; | |
1804 }) | |
1805 | |
1806 (define_insn "tablejump<mode>" | |
1807 [(set (pc) (match_operand:GPR 0 "register_operand" "l")) | |
1808 (use (label_ref (match_operand 1 "" "")))] | |
1809 "" | |
1810 "jr\t%0" | |
1811 [(set_attr "type" "jump") | |
1812 (set_attr "mode" "none")]) | |
1813 | |
1814 ;; | |
1815 ;; .................... | |
1816 ;; | |
1817 ;; Function prologue/epilogue | |
1818 ;; | |
1819 ;; .................... | |
1820 ;; | |
1821 | |
1822 (define_expand "prologue" | |
1823 [(const_int 1)] | |
1824 "" | |
1825 { | |
1826 riscv_expand_prologue (); | |
1827 DONE; | |
1828 }) | |
1829 | |
1830 ;; Block any insns from being moved before this point, since the | |
1831 ;; profiling call to mcount can use various registers that aren't | |
1832 ;; saved or used to pass arguments. | |
1833 | |
1834 (define_insn "blockage" | |
1835 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] | |
1836 "" | |
1837 "" | |
1838 [(set_attr "type" "ghost") | |
1839 (set_attr "mode" "none")]) | |
1840 | |
1841 (define_expand "epilogue" | |
1842 [(const_int 2)] | |
1843 "" | |
1844 { | |
1845 riscv_expand_epilogue (false); | |
1846 DONE; | |
1847 }) | |
1848 | |
1849 (define_expand "sibcall_epilogue" | |
1850 [(const_int 2)] | |
1851 "" | |
1852 { | |
1853 riscv_expand_epilogue (true); | |
1854 DONE; | |
1855 }) | |
1856 | |
1857 ;; Trivial return. Make it look like a normal return insn as that | |
1858 ;; allows jump optimizations to work better. | |
1859 | |
1860 (define_expand "return" | |
1861 [(simple_return)] | |
1862 "riscv_can_use_return_insn ()" | |
1863 "") | |
1864 | |
1865 (define_insn "simple_return" | |
1866 [(simple_return)] | |
1867 "" | |
1868 "ret" | |
1869 [(set_attr "type" "jump") | |
1870 (set_attr "mode" "none")]) | |
1871 | |
1872 ;; Normal return. | |
1873 | |
1874 (define_insn "simple_return_internal" | |
1875 [(simple_return) | |
1876 (use (match_operand 0 "pmode_register_operand" ""))] | |
1877 "" | |
1878 "jr\t%0" | |
1879 [(set_attr "type" "jump") | |
1880 (set_attr "mode" "none")]) | |
1881 | |
1882 ;; This is used in compiling the unwind routines. | |
1883 (define_expand "eh_return" | |
1884 [(use (match_operand 0 "general_operand"))] | |
1885 "" | |
1886 { | |
1887 if (GET_MODE (operands[0]) != word_mode) | |
1888 operands[0] = convert_to_mode (word_mode, operands[0], 0); | |
1889 if (TARGET_64BIT) | |
1890 emit_insn (gen_eh_set_lr_di (operands[0])); | |
1891 else | |
1892 emit_insn (gen_eh_set_lr_si (operands[0])); | |
1893 DONE; | |
1894 }) | |
1895 | |
1896 ;; Clobber the return address on the stack. We can't expand this | |
1897 ;; until we know where it will be put in the stack frame. | |
1898 | |
1899 (define_insn "eh_set_lr_si" | |
1900 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN) | |
1901 (clobber (match_scratch:SI 1 "=&r"))] | |
1902 "! TARGET_64BIT" | |
1903 "#") | |
1904 | |
1905 (define_insn "eh_set_lr_di" | |
1906 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN) | |
1907 (clobber (match_scratch:DI 1 "=&r"))] | |
1908 "TARGET_64BIT" | |
1909 "#") | |
1910 | |
1911 (define_split | |
1912 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN) | |
1913 (clobber (match_scratch 1))] | |
1914 "reload_completed" | |
1915 [(const_int 0)] | |
1916 { | |
1917 riscv_set_return_address (operands[0], operands[1]); | |
1918 DONE; | |
1919 }) | |
1920 | |
1921 ;; | |
1922 ;; .................... | |
1923 ;; | |
1924 ;; FUNCTION CALLS | |
1925 ;; | |
1926 ;; .................... | |
1927 | |
1928 (define_expand "sibcall" | |
1929 [(parallel [(call (match_operand 0 "") | |
1930 (match_operand 1 "")) | |
1931 (use (match_operand 2 "")) ;; next_arg_reg | |
1932 (use (match_operand 3 ""))])] ;; struct_value_size_rtx | |
1933 "" | |
1934 { | |
1935 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0)); | |
1936 emit_call_insn (gen_sibcall_internal (target, operands[1])); | |
1937 DONE; | |
1938 }) | |
1939 | |
1940 (define_insn "sibcall_internal" | |
1941 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U")) | |
1942 (match_operand 1 "" ""))] | |
1943 "SIBLING_CALL_P (insn)" | |
1944 "@ | |
1945 jr\t%0 | |
1946 tail\t%0 | |
1947 tail\t%0@plt" | |
1948 [(set_attr "type" "call")]) | |
1949 | |
1950 (define_expand "sibcall_value" | |
1951 [(parallel [(set (match_operand 0 "") | |
1952 (call (match_operand 1 "") | |
1953 (match_operand 2 ""))) | |
1954 (use (match_operand 3 ""))])] ;; next_arg_reg | |
1955 "" | |
1956 { | |
1957 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0)); | |
1958 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2])); | |
1959 DONE; | |
1960 }) | |
1961 | |
1962 (define_insn "sibcall_value_internal" | |
1963 [(set (match_operand 0 "" "") | |
1964 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U")) | |
1965 (match_operand 2 "" "")))] | |
1966 "SIBLING_CALL_P (insn)" | |
1967 "@ | |
1968 jr\t%1 | |
1969 tail\t%1 | |
1970 tail\t%1@plt" | |
1971 [(set_attr "type" "call")]) | |
1972 | |
1973 (define_expand "call" | |
1974 [(parallel [(call (match_operand 0 "") | |
1975 (match_operand 1 "")) | |
1976 (use (match_operand 2 "")) ;; next_arg_reg | |
1977 (use (match_operand 3 ""))])] ;; struct_value_size_rtx | |
1978 "" | |
1979 { | |
1980 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0)); | |
1981 emit_call_insn (gen_call_internal (target, operands[1])); | |
1982 DONE; | |
1983 }) | |
1984 | |
1985 (define_insn "call_internal" | |
1986 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U")) | |
1987 (match_operand 1 "" "")) | |
1988 (clobber (reg:SI RETURN_ADDR_REGNUM))] | |
1989 "" | |
1990 "@ | |
1991 jalr\t%0 | |
1992 call\t%0 | |
1993 call\t%0@plt" | |
1994 [(set_attr "type" "call")]) | |
1995 | |
1996 (define_expand "call_value" | |
1997 [(parallel [(set (match_operand 0 "") | |
1998 (call (match_operand 1 "") | |
1999 (match_operand 2 ""))) | |
2000 (use (match_operand 3 ""))])] ;; next_arg_reg | |
2001 "" | |
2002 { | |
2003 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0)); | |
2004 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2])); | |
2005 DONE; | |
2006 }) | |
2007 | |
2008 (define_insn "call_value_internal" | |
2009 [(set (match_operand 0 "" "") | |
2010 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U")) | |
2011 (match_operand 2 "" ""))) | |
2012 (clobber (reg:SI RETURN_ADDR_REGNUM))] | |
2013 "" | |
2014 "@ | |
2015 jalr\t%1 | |
2016 call\t%1 | |
2017 call\t%1@plt" | |
2018 [(set_attr "type" "call")]) | |
2019 | |
2020 ;; Call subroutine returning any type. | |
2021 | |
2022 (define_expand "untyped_call" | |
2023 [(parallel [(call (match_operand 0 "") | |
2024 (const_int 0)) | |
2025 (match_operand 1 "") | |
2026 (match_operand 2 "")])] | |
2027 "" | |
2028 { | |
2029 int i; | |
2030 | |
2031 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); | |
2032 | |
2033 for (i = 0; i < XVECLEN (operands[2], 0); i++) | |
2034 { | |
2035 rtx set = XVECEXP (operands[2], 0, i); | |
2036 riscv_emit_move (SET_DEST (set), SET_SRC (set)); | |
2037 } | |
2038 | |
2039 emit_insn (gen_blockage ()); | |
2040 DONE; | |
2041 }) | |
2042 | |
2043 (define_insn "nop" | |
2044 [(const_int 0)] | |
2045 "" | |
2046 "nop" | |
2047 [(set_attr "type" "nop") | |
2048 (set_attr "mode" "none")]) | |
2049 | |
2050 (define_insn "trap" | |
2051 [(trap_if (const_int 1) (const_int 0))] | |
2052 "" | |
2053 "ebreak") | |
2054 | |
2055 (define_insn "gpr_save" | |
2056 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_SAVE) | |
2057 (clobber (reg:SI T0_REGNUM)) | |
2058 (clobber (reg:SI T1_REGNUM))] | |
2059 "" | |
2060 { return riscv_output_gpr_save (INTVAL (operands[0])); }) | |
2061 | |
2062 (define_insn "gpr_restore" | |
2063 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)] | |
2064 "" | |
2065 "tail\t__riscv_restore_%0") | |
2066 | |
2067 (define_insn "gpr_restore_return" | |
2068 [(return) | |
2069 (use (match_operand 0 "pmode_register_operand" "")) | |
2070 (const_int 0)] | |
2071 "" | |
2072 "") | |
2073 | |
2074 (define_insn "riscv_frflags" | |
2075 [(set (match_operand:SI 0 "register_operand" "=r") | |
2076 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))] | |
2077 "TARGET_HARD_FLOAT" | |
2078 "frflags %0") | |
2079 | |
2080 (define_insn "riscv_fsflags" | |
2081 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)] | |
2082 "TARGET_HARD_FLOAT" | |
2083 "fsflags %0") | |
2084 | |
2085 (define_insn "stack_tie<mode>" | |
2086 [(set (mem:BLK (scratch)) | |
2087 (unspec:BLK [(match_operand:X 0 "register_operand" "r") | |
2088 (match_operand:X 1 "register_operand" "r")] | |
2089 UNSPEC_TIE))] | |
2090 "" | |
2091 "" | |
2092 [(set_attr "length" "0")] | |
2093 ) | |
2094 | |
2095 (include "sync.md") | |
2096 (include "peephole.md") | |
2097 (include "pic.md") | |
2098 (include "generic.md") |