]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/riscv/riscv.md
DWARF: Add header for .debug_str_offsets table for dwarf_version 5.
[thirdparty/gcc.git] / gcc / config / riscv / riscv.md
CommitLineData
09cae750 1;; Machine description for RISC-V for GNU compiler.
85ec4feb 2;; Copyright (C) 2011-2018 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
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
0b661358
PD
262;; Iterator for extending loads.
263(define_mode_iterator ZERO_EXTEND_LOAD [QI HI (SI "TARGET_64BIT")])
264
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4
KC
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")))]
09cae750 416 ""
0791ac18 417 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
09cae750
PD
418 [(set_attr "type" "arith")
419 (set_attr "mode" "SI")])
420
421(define_insn "adddi3"
248710c4
KC
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")))]
09cae750 425 "TARGET_64BIT"
0791ac18 426 "add%i2\t%0,%1,%2"
09cae750
PD
427 [(set_attr "type" "arith")
428 (set_attr "mode" "DI")])
429
430(define_insn "*addsi3_extended"
248710c4 431 [(set (match_operand:DI 0 "register_operand" "=r,r")
09cae750 432 (sign_extend:DI
248710c4
KC
433 (plus:SI (match_operand:SI 1 "register_operand" " r,r")
434 (match_operand:SI 2 "arith_operand" " r,I"))))]
09cae750 435 "TARGET_64BIT"
0791ac18 436 "add%i2w\t%0,%1,%2"
09cae750
PD
437 [(set_attr "type" "arith")
438 (set_attr "mode" "SI")])
439
440(define_insn "*addsi3_extended2"
248710c4 441 [(set (match_operand:DI 0 "register_operand" "=r,r")
09cae750 442 (sign_extend:DI
248710c4
KC
443 (subreg:SI (plus:DI (match_operand:DI 1 "register_operand" " r,r")
444 (match_operand:DI 2 "arith_operand" " r,I"))
09cae750
PD
445 0)))]
446 "TARGET_64BIT"
0791ac18 447 "add%i2w\t%0,%1,%2"
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
472 "TARGET_64BIT"
473 "sub\t%0,%z1,%2"
474 [(set_attr "type" "arith")
475 (set_attr "mode" "DI")])
476
477(define_insn "subsi3"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4 487 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 488 (sign_extend:DI
248710c4
KC
489 (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
490 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
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"
248710c4 497 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 498 (sign_extend:DI
248710c4
KC
499 (subreg:SI (minus:DI (match_operand:DI 1 "reg_or_0_operand" " r")
500 (match_operand:DI 2 "register_operand" " r"))
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4 543 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 544 (sign_extend:DI
248710c4
KC
545 (mult:SI (match_operand:SI 1 "register_operand" " r")
546 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
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"
248710c4 553 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 554 (sign_extend:DI
248710c4
KC
555 (subreg:SI (mult:DI (match_operand:DI 1 "register_operand" " r")
556 (match_operand:DI 2 "register_operand" " r"))
09cae750
PD
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"
248710c4 573 [(set (match_operand:TI 0 "register_operand")
09cae750
PD
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"
248710c4 590 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750
PD
591 (truncate:DI
592 (lshiftrt:TI
593 (mult:TI (any_extend:TI
248710c4 594 (match_operand:DI 1 "register_operand" " r"))
09cae750 595 (any_extend:TI
248710c4 596 (match_operand:DI 2 "register_operand" " r")))
09cae750
PD
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"
248710c4 604 [(set (match_operand:TI 0 "register_operand")
09cae750
PD
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"
248710c4 621 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750
PD
622 (truncate:DI
623 (lshiftrt:TI
624 (mult:TI (zero_extend:TI
248710c4 625 (match_operand:DI 1 "register_operand" "r"))
09cae750 626 (sign_extend:TI
248710c4 627 (match_operand:DI 2 "register_operand" " r")))
09cae750
PD
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"
248710c4 635 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 636 (mult:DI (any_extend:DI
248710c4 637 (match_operand:SI 1 "register_operand" " r"))
09cae750 638 (any_extend:DI
248710c4 639 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
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"
248710c4 651 [(set (match_operand:SI 0 "register_operand" "=r")
09cae750
PD
652 (truncate:SI
653 (lshiftrt:DI
654 (mult:DI (any_extend:DI
248710c4 655 (match_operand:SI 1 "register_operand" " r"))
09cae750 656 (any_extend:DI
248710c4 657 (match_operand:SI 2 "register_operand" " r")))
09cae750
PD
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"
248710c4 666 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 667 (mult:DI (zero_extend:DI
248710c4 668 (match_operand:SI 1 "register_operand" " r"))
09cae750 669 (sign_extend:DI
248710c4 670 (match_operand:SI 2 "register_operand" " r"))))]
09cae750
PD
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"
248710c4 682 [(set (match_operand:SI 0 "register_operand" "=r")
09cae750
PD
683 (truncate:SI
684 (lshiftrt:DI
685 (mult:DI (zero_extend:DI
248710c4 686 (match_operand:SI 1 "register_operand" " r"))
09cae750 687 (sign_extend:DI
248710c4 688 (match_operand:SI 2 "register_operand" " r")))
09cae750
PD
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"
248710c4
KC
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")))]
09cae750 707 "TARGET_DIV"
0791ac18 708 { return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2"; }
09cae750
PD
709 [(set_attr "type" "idiv")
710 (set_attr "mode" "SI")])
711
712(define_insn "<optab>di3"
248710c4
KC
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")))]
09cae750 716 "TARGET_DIV && TARGET_64BIT"
0791ac18 717 "<insn>%i2\t%0,%1,%2"
09cae750
PD
718 [(set_attr "type" "idiv")
719 (set_attr "mode" "DI")])
720
721(define_insn "*<optab>si3_extended"
248710c4 722 [(set (match_operand:DI 0 "register_operand" "=r")
09cae750 723 (sign_extend:DI
248710c4
KC
724 (any_div:SI (match_operand:SI 1 "register_operand" " r")
725 (match_operand:SI 2 "register_operand" " r"))))]
09cae750 726 "TARGET_DIV && TARGET_64BIT"
0791ac18 727 "<insn>%i2w\t%0,%1,%2"
09cae750
PD
728 [(set_attr "type" "idiv")
729 (set_attr "mode" "DI")])
730
731(define_insn "div<mode>3"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4
KC
748 [(set (match_operand:ANYF 0 "register_operand" "=f")
749 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4
KC
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"))))]
09cae750
PD
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"
248710c4
KC
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"))))]
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4
KC
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")))))]
09cae750
PD
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"
248710c4
KC
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"))))]
09cae750
PD
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"
248710c4
KC
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"))))]
09cae750
PD
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"
248710c4
KC
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")))))]
09cae750
PD
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"
248710c4
KC
865 [(set (match_operand:ANYF 0 "register_operand" "=f")
866 (abs:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
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"
248710c4
KC
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")]
09cae750
PD
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"
248710c4
KC
883 [(set (match_operand:ANYF 0 "register_operand" "=f")
884 (neg:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4
KC
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")))]
09cae750
PD
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"
248710c4 927 [(set (match_operand:X 0 "register_operand" "=r,r")
09cae750 928 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
248710c4 929 (match_operand:X 2 "arith_operand" " r,I")))]
09cae750 930 ""
0791ac18 931 "<insn>%i2\t%0,%1,%2"
09cae750
PD
932 [(set_attr "type" "logical")
933 (set_attr "mode" "<MODE>")])
934
935(define_insn "*<optab>si3_internal"
248710c4 936 [(set (match_operand:SI 0 "register_operand" "=r,r")
09cae750 937 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
248710c4 938 (match_operand:SI 2 "arith_operand" " r,I")))]
09cae750 939 "TARGET_64BIT"
0791ac18 940 "<insn>%i2\t%0,%1,%2"
09cae750
PD
941 [(set_attr "type" "logical")
942 (set_attr "mode" "SI")])
943
944(define_insn "one_cmpl<mode>2"
248710c4
KC
945 [(set (match_operand:X 0 "register_operand" "=r")
946 (not:X (match_operand:X 1 "register_operand" " r")))]
09cae750
PD
947 ""
948 "not\t%0,%1"
949 [(set_attr "type" "logical")
950 (set_attr "mode" "<MODE>")])
951
952(define_insn "*one_cmplsi2_internal"
248710c4
KC
953 [(set (match_operand:SI 0 "register_operand" "=r")
954 (not:SI (match_operand:SI 1 "register_operand" " r")))]
09cae750
PD
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"
248710c4
KC
968 [(set (match_operand:SF 0 "register_operand" "=f")
969 (float_truncate:SF
970 (match_operand:DF 1 "register_operand" " f")))]
09cae750
PD
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"
248710c4
KC
986 [(set (match_operand:DI 0 "register_operand" "=r,r")
987 (zero_extend:DI
988 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
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"
248710c4
KC
1003 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1004 (zero_extend:GPR
1005 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
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"
248710c4 1023 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1024 (zero_extend:SUPERQI
248710c4 1025 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1026 ""
1027 "@
0791ac18 1028 andi\t%0,%1,0xff
09cae750
PD
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"
248710c4
KC
1041 [(set (match_operand:DI 0 "register_operand" "=r,r")
1042 (sign_extend:DI
1043 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
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"
248710c4 1052 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1053 (sign_extend:SUPERQI
248710c4 1054 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
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"
248710c4
KC
1072 [(set (match_operand:DF 0 "register_operand" "=f")
1073 (float_extend:DF
1074 (match_operand:SF 1 "register_operand" " f")))]
09cae750
PD
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"
248710c4
KC
1088 [(set (match_operand:GPR 0 "register_operand" "=r")
1089 (fix:GPR
1090 (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
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"
248710c4
KC
1097 [(set (match_operand:GPR 0 "register_operand" "=r")
1098 (unsigned_fix:GPR
1099 (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
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"
248710c4
KC
1106 [(set (match_operand:ANYF 0 "register_operand" "= f")
1107 (float:ANYF
1108 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
09cae750
PD
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"
248710c4
KC
1115 [(set (match_operand:ANYF 0 "register_operand" "= f")
1116 (unsigned_float:ANYF
1117 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
09cae750
PD
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"
248710c4
KC
1124 [(set (match_operand:GPR 0 "register_operand" "=r")
1125 (unspec:GPR
1126 [(match_operand:ANYF 1 "register_operand" " f")]
1127 RINT))]
09cae750
PD
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>"
248710c4
KC
1145 [(set (match_operand:P 0 "register_operand" "=r")
1146 (unspec:P
1147 [(match_operand:P 1 "symbolic_operand" "")]
1148 UNSPEC_LOAD_GOT))]
09cae750
PD
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>"
248710c4
KC
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))]
09cae750
PD
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>"
248710c4
KC
1167 [(set (match_operand:P 0 "register_operand" "=r")
1168 (unspec:P
1169 [(match_operand:P 1 "symbolic_operand" "")]
1170 UNSPEC_TLS_GD))]
09cae750
PD
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>"
248710c4
KC
1177 [(set (match_operand:P 0 "register_operand" "=r")
1178 (unspec:P
1179 [(match_operand:P 1 "symbolic_operand" "")]
1180 UNSPEC_TLS_IE))]
09cae750
PD
1181 ""
1182 "la.tls.ie\t%0,%1"
1183 [(set_attr "got" "load")
1184 (set_attr "mode" "<MODE>")])
1185
1186(define_insn "auipc<mode>"
248710c4
KC
1187 [(set (match_operand:P 0 "register_operand" "=r")
1188 (unspec:P
1189 [(match_operand:P 1 "symbolic_operand" "")
09cae750
PD
1190 (match_operand:P 2 "const_int_operand")
1191 (pc)]
248710c4 1192 UNSPEC_AUIPC))]
09cae750
PD
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>"
248710c4
KC
1203 [(set (match_operand:P 0 "register_operand" "=r")
1204 (lo_sum:P (match_operand:P 1 "register_operand" " r")
09cae750
PD
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")
248710c4 1249 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))]
09cae750
PD
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"
248710c4
KC
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"))]
09cae750
PD
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"
248710c4
KC
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"))]
09cae750
PD
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"
248710c4
KC
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"))]
09cae750
PD
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.
bb149ca2
RS
1313;; si+si->hi without truncation is legal because of
1314;; TARGET_TRULY_NOOP_TRUNCATION.
09cae750
PD
1315
1316(define_insn "*add<mode>hi3"
248710c4
KC
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")))]
09cae750 1320 ""
0791ac18 1321 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
09cae750
PD
1322 [(set_attr "type" "arith")
1323 (set_attr "mode" "HI")])
1324
1325(define_insn "*xor<mode>hi3"
248710c4
KC
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")))]
09cae750 1329 ""
0791ac18 1330 "xor%i2\t%0,%1,%2"
09cae750
PD
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"
248710c4
KC
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"))]
09cae750
PD
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"
248710c4
KC
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"))]
09cae750
PD
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"
248710c4
KC
1376 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
1377 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
09cae750
PD
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"
248710c4
KC
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"))]
09cae750
PD
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"
248710c4
KC
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"))]
09cae750
PD
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"
248710c4
KC
1419 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
1420 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
09cae750
PD
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
6ed01e6b
AW
1439(define_expand "movmemsi"
1440 [(parallel [(set (match_operand:BLK 0 "general_operand")
1441 (match_operand:BLK 1 "general_operand"))
1442 (use (match_operand:SI 2 ""))
1443 (use (match_operand:SI 3 "const_int_operand"))])]
1444 ""
1445{
1446 if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
1447 DONE;
1448 else
1449 FAIL;
1450})
1451
09cae750
PD
1452;; Expand in-line code to clear the instruction cache between operand[0] and
1453;; operand[1].
1454(define_expand "clear_cache"
1455 [(match_operand 0 "pmode_register_operand")
1456 (match_operand 1 "pmode_register_operand")]
1457 ""
1458{
f1bdc63a
AW
1459#ifdef ICACHE_FLUSH_FUNC
1460 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC),
1461 LCT_NORMAL, VOIDmode, operands[0], Pmode,
1462 operands[1], Pmode, const0_rtx, Pmode);
1463#else
09cae750 1464 emit_insn (gen_fence_i ());
f1bdc63a 1465#endif
09cae750
PD
1466 DONE;
1467})
1468
1469(define_insn "fence"
1470 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
1471 ""
1472 "%|fence%-")
1473
1474(define_insn "fence_i"
1475 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
1476 ""
1477 "fence.i")
1478
1479;;
1480;; ....................
1481;;
1482;; SHIFTS
1483;;
1484;; ....................
1485
b7ef9225
JW
1486;; Use a QImode shift count, to avoid generating sign or zero extend
1487;; instructions for shift counts, and to avoid dropping subregs.
1488;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
1489;; defined, but use of that is discouraged.
1490
09cae750 1491(define_insn "<optab>si3"
248710c4
KC
1492 [(set (match_operand:SI 0 "register_operand" "= r")
1493 (any_shift:SI
1494 (match_operand:SI 1 "register_operand" " r")
b7ef9225 1495 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
1496 ""
1497{
1498 if (GET_CODE (operands[2]) == CONST_INT)
1499 operands[2] = GEN_INT (INTVAL (operands[2])
1500 & (GET_MODE_BITSIZE (SImode) - 1));
1501
0791ac18 1502 return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2";
09cae750
PD
1503}
1504 [(set_attr "type" "shift")
1505 (set_attr "mode" "SI")])
1506
b7ef9225
JW
1507(define_insn_and_split "<optab>si3_mask"
1508 [(set (match_operand:SI 0 "register_operand" "= r")
1509 (any_shift:SI
1510 (match_operand:SI 1 "register_operand" " r")
1511 (subreg:QI
1512 (and:SI
1513 (match_operand:SI 2 "register_operand" "r")
1514 (match_operand 3 "const_int_operand")) 0)))]
1515 "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1516 == GET_MODE_BITSIZE (SImode)-1"
1517 "#"
1518 "&& 1"
1519 [(set (match_dup 0)
1520 (any_shift:SI (match_dup 1)
1521 (match_dup 2)))]
1522 "operands[2] = gen_lowpart (QImode, operands[2]);"
1523 [(set_attr "type" "shift")
1524 (set_attr "mode" "SI")])
1525
1526(define_insn_and_split "<optab>si3_mask_1"
1527 [(set (match_operand:SI 0 "register_operand" "= r")
1528 (any_shift:SI
1529 (match_operand:SI 1 "register_operand" " r")
1530 (subreg:QI
1531 (and:DI
1532 (match_operand:DI 2 "register_operand" "r")
1533 (match_operand 3 "const_int_operand")) 0)))]
1534 "TARGET_64BIT
1535 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1536 == GET_MODE_BITSIZE (SImode)-1"
1537 "#"
1538 "&& 1"
1539 [(set (match_dup 0)
1540 (any_shift:SI (match_dup 1)
1541 (match_dup 2)))]
1542 "operands[2] = gen_lowpart (QImode, operands[2]);"
1543 [(set_attr "type" "shift")
1544 (set_attr "mode" "SI")])
1545
09cae750 1546(define_insn "<optab>di3"
248710c4
KC
1547 [(set (match_operand:DI 0 "register_operand" "= r")
1548 (any_shift:DI
1549 (match_operand:DI 1 "register_operand" " r")
b7ef9225 1550 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
1551 "TARGET_64BIT"
1552{
1553 if (GET_CODE (operands[2]) == CONST_INT)
1554 operands[2] = GEN_INT (INTVAL (operands[2])
1555 & (GET_MODE_BITSIZE (DImode) - 1));
1556
0791ac18 1557 return "<insn>%i2\t%0,%1,%2";
09cae750
PD
1558}
1559 [(set_attr "type" "shift")
1560 (set_attr "mode" "DI")])
1561
b7ef9225
JW
1562(define_insn_and_split "<optab>di3_mask"
1563 [(set (match_operand:DI 0 "register_operand" "= r")
1564 (any_shift:DI
1565 (match_operand:DI 1 "register_operand" " r")
1566 (subreg:QI
1567 (and:SI
1568 (match_operand:SI 2 "register_operand" "r")
1569 (match_operand 3 "const_int_operand")) 0)))]
1570 "TARGET_64BIT
1571 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1572 == GET_MODE_BITSIZE (DImode)-1"
1573 "#"
1574 "&& 1"
1575 [(set (match_dup 0)
1576 (any_shift:DI (match_dup 1)
1577 (match_dup 2)))]
1578 "operands[2] = gen_lowpart (QImode, operands[2]);"
1579 [(set_attr "type" "shift")
1580 (set_attr "mode" "DI")])
1581
1582(define_insn_and_split "<optab>di3_mask_1"
1583 [(set (match_operand:DI 0 "register_operand" "= r")
1584 (any_shift:DI
1585 (match_operand:DI 1 "register_operand" " r")
1586 (subreg:QI
1587 (and:DI
1588 (match_operand:DI 2 "register_operand" "r")
1589 (match_operand 3 "const_int_operand")) 0)))]
1590 "TARGET_64BIT
1591 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1592 == GET_MODE_BITSIZE (DImode)-1"
1593 "#"
1594 "&& 1"
1595 [(set (match_dup 0)
1596 (any_shift:DI (match_dup 1)
1597 (match_dup 2)))]
1598 "operands[2] = gen_lowpart (QImode, operands[2]);"
1599 [(set_attr "type" "shift")
1600 (set_attr "mode" "DI")])
1601
09cae750 1602(define_insn "*<optab>si3_extend"
248710c4 1603 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 1604 (sign_extend:DI
248710c4 1605 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 1606 (match_operand:QI 2 "arith_operand" " rI"))))]
09cae750
PD
1607 "TARGET_64BIT"
1608{
1609 if (GET_CODE (operands[2]) == CONST_INT)
1610 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1611
0791ac18 1612 return "<insn>%i2w\t%0,%1,%2";
09cae750
PD
1613}
1614 [(set_attr "type" "shift")
1615 (set_attr "mode" "SI")])
1616
b7ef9225
JW
1617(define_insn_and_split "*<optab>si3_extend_mask"
1618 [(set (match_operand:DI 0 "register_operand" "= r")
1619 (sign_extend:DI
1620 (any_shift:SI
1621 (match_operand:SI 1 "register_operand" " r")
1622 (subreg:QI
1623 (and:SI
1624 (match_operand:SI 2 "register_operand" " r")
1625 (match_operand 3 "const_int_operand")) 0))))]
1626 "TARGET_64BIT
1627 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1628 == GET_MODE_BITSIZE (SImode)-1"
1629 "#"
1630 "&& 1"
1631 [(set (match_dup 0)
1632 (sign_extend:DI
1633 (any_shift:SI (match_dup 1)
1634 (match_dup 2))))]
1635 "operands[2] = gen_lowpart (QImode, operands[2]);"
1636 [(set_attr "type" "shift")
1637 (set_attr "mode" "SI")])
1638
1639(define_insn_and_split "*<optab>si3_extend_mask_1"
1640 [(set (match_operand:DI 0 "register_operand" "= r")
1641 (sign_extend:DI
1642 (any_shift:SI
1643 (match_operand:SI 1 "register_operand" " r")
1644 (subreg:QI
1645 (and:DI
1646 (match_operand:DI 2 "register_operand" " r")
1647 (match_operand 3 "const_int_operand")) 0))))]
1648 "TARGET_64BIT
1649 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1650 == GET_MODE_BITSIZE (SImode)-1"
1651 "#"
1652 "&& 1"
1653 [(set (match_dup 0)
1654 (sign_extend:DI
1655 (any_shift:SI (match_dup 1)
1656 (match_dup 2))))]
1657 "operands[2] = gen_lowpart (QImode, operands[2]);"
1658 [(set_attr "type" "shift")
1659 (set_attr "mode" "SI")])
1660
08539f3e
JW
1661;; Non-canonical, but can be formed by ree when combine is not successful at
1662;; producing one of the two canonical patterns below.
1663(define_insn "*lshrsi3_zero_extend_1"
1664 [(set (match_operand:DI 0 "register_operand" "=r")
1665 (zero_extend:DI
1666 (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 1667 (match_operand 2 "const_int_operand"))))]
08539f3e
JW
1668 "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
1669{
1670 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1671
1672 return "srliw\t%0,%1,%2";
1673}
1674 [(set_attr "type" "shift")
1675 (set_attr "mode" "SI")])
1676
1677;; Canonical form for a zero-extend of a logical right shift.
1678(define_insn "*lshrsi3_zero_extend_2"
1679 [(set (match_operand:DI 0 "register_operand" "=r")
1680 (zero_extract:DI (match_operand:DI 1 "register_operand" " r")
1681 (match_operand 2 "const_int_operand")
1682 (match_operand 3 "const_int_operand")))]
1683 "(TARGET_64BIT && (INTVAL (operands[3]) > 0)
1684 && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
1685{
1686 return "srliw\t%0,%1,%3";
1687}
1688 [(set_attr "type" "shift")
1689 (set_attr "mode" "SI")])
1690
1691;; Canonical form for a zero-extend of a logical right shift when the
1692;; shift count is 31.
1693(define_insn "*lshrsi3_zero_extend_3"
1694 [(set (match_operand:DI 0 "register_operand" "=r")
1695 (lt:DI (match_operand:SI 1 "register_operand" " r")
1696 (const_int 0)))]
1697 "TARGET_64BIT"
1698{
1699 return "srliw\t%0,%1,31";
1700}
1701 [(set_attr "type" "shift")
1702 (set_attr "mode" "SI")])
1703
09cae750
PD
1704;;
1705;; ....................
1706;;
1707;; CONDITIONAL BRANCHES
1708;;
1709;; ....................
1710
1711;; Conditional branches
1712
1713(define_insn "*branch_order<mode>"
1714 [(set (pc)
1715 (if_then_else
1716 (match_operator 1 "order_operator"
1717 [(match_operand:X 2 "register_operand" "r")
1718 (match_operand:X 3 "register_operand" "r")])
1719 (label_ref (match_operand 0 "" ""))
1720 (pc)))]
1721 ""
1722 "b%C1\t%2,%3,%0"
1723 [(set_attr "type" "branch")
1724 (set_attr "mode" "none")])
1725
1726(define_insn "*branch_zero<mode>"
1727 [(set (pc)
1728 (if_then_else
1729 (match_operator 1 "signed_order_operator"
1730 [(match_operand:X 2 "register_operand" "r")
1731 (const_int 0)])
1732 (label_ref (match_operand 0 "" ""))
1733 (pc)))]
1734 ""
1735 "b%C1z\t%2,%0"
1736 [(set_attr "type" "branch")
1737 (set_attr "mode" "none")])
1738
1739;; Used to implement built-in functions.
1740(define_expand "condjump"
1741 [(set (pc)
1742 (if_then_else (match_operand 0)
1743 (label_ref (match_operand 1))
1744 (pc)))])
1745
1746(define_expand "cbranch<mode>4"
1747 [(set (pc)
1748 (if_then_else (match_operator 0 "comparison_operator"
248710c4
KC
1749 [(match_operand:BR 1 "register_operand")
1750 (match_operand:BR 2 "nonmemory_operand")])
09cae750
PD
1751 (label_ref (match_operand 3 ""))
1752 (pc)))]
1753 ""
1754{
1755 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1756 operands[1], operands[2]);
1757 DONE;
1758})
1759
1760(define_expand "cbranch<mode>4"
1761 [(set (pc)
1762 (if_then_else (match_operator 0 "fp_branch_comparison"
1763 [(match_operand:ANYF 1 "register_operand")
1764 (match_operand:ANYF 2 "register_operand")])
1765 (label_ref (match_operand 3 ""))
1766 (pc)))]
1767 "TARGET_HARD_FLOAT"
1768{
1769 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1770 operands[1], operands[2]);
1771 DONE;
1772})
1773
1774(define_insn_and_split "*branch_on_bit<X:mode>"
1775 [(set (pc)
1776 (if_then_else
248710c4
KC
1777 (match_operator 0 "equality_operator"
1778 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1779 (const_int 1)
1780 (match_operand 3 "branch_on_bit_operand"))
1781 (const_int 0)])
1782 (label_ref (match_operand 1))
1783 (pc)))
09cae750
PD
1784 (clobber (match_scratch:X 4 "=&r"))]
1785 ""
1786 "#"
1787 "reload_completed"
1788 [(set (match_dup 4)
1789 (ashift:X (match_dup 2) (match_dup 3)))
1790 (set (pc)
1791 (if_then_else
248710c4
KC
1792 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1793 (label_ref (match_operand 1))
1794 (pc)))]
09cae750
PD
1795{
1796 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
1797 operands[3] = GEN_INT (shift);
1798
1799 if (GET_CODE (operands[0]) == EQ)
1800 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
1801 else
1802 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
1803})
1804
1805(define_insn_and_split "*branch_on_bit_range<X:mode>"
1806 [(set (pc)
1807 (if_then_else
248710c4
KC
1808 (match_operator 0 "equality_operator"
1809 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1810 (match_operand 3 "branch_on_bit_operand")
1811 (const_int 0))
1812 (const_int 0)])
1813 (label_ref (match_operand 1))
1814 (pc)))
09cae750
PD
1815 (clobber (match_scratch:X 4 "=&r"))]
1816 ""
1817 "#"
1818 "reload_completed"
1819 [(set (match_dup 4)
1820 (ashift:X (match_dup 2) (match_dup 3)))
1821 (set (pc)
1822 (if_then_else
248710c4
KC
1823 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1824 (label_ref (match_operand 1))
1825 (pc)))]
09cae750
PD
1826{
1827 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
1828})
1829
1830;;
1831;; ....................
1832;;
1833;; SETTING A REGISTER FROM A COMPARISON
1834;;
1835;; ....................
1836
1837;; Destination is always set in SI mode.
1838
1839(define_expand "cstore<mode>4"
1840 [(set (match_operand:SI 0 "register_operand")
1841 (match_operator:SI 1 "order_operator"
248710c4
KC
1842 [(match_operand:GPR 2 "register_operand")
1843 (match_operand:GPR 3 "nonmemory_operand")]))]
09cae750
PD
1844 ""
1845{
1846 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
1847 operands[3]);
1848 DONE;
1849})
1850
1851(define_expand "cstore<mode>4"
1852 [(set (match_operand:SI 0 "register_operand")
1853 (match_operator:SI 1 "fp_scc_comparison"
248710c4
KC
1854 [(match_operand:ANYF 2 "register_operand")
1855 (match_operand:ANYF 3 "register_operand")]))]
09cae750
PD
1856 "TARGET_HARD_FLOAT"
1857{
1858 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
1859 operands[3]);
1860 DONE;
1861})
1862
1863(define_insn "*cstore<ANYF:mode><X:mode>4"
248710c4
KC
1864 [(set (match_operand:X 0 "register_operand" "=r")
1865 (match_operator:X 1 "fp_native_comparison"
1866 [(match_operand:ANYF 2 "register_operand" " f")
1867 (match_operand:ANYF 3 "register_operand" " f")]))]
09cae750
PD
1868 "TARGET_HARD_FLOAT"
1869 "f%C1.<fmt>\t%0,%2,%3"
1870 [(set_attr "type" "fcmp")
1871 (set_attr "mode" "<UNITMODE>")])
1872
1873(define_insn "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
248710c4 1874 [(set (match_operand:X 0 "register_operand" "=r")
09cae750 1875 (unspec:X
248710c4
KC
1876 [(match_operand:ANYF 1 "register_operand" " f")
1877 (match_operand:ANYF 2 "register_operand" " f")]
1878 QUIET_COMPARISON))
09cae750
PD
1879 (clobber (match_scratch:X 3 "=&r"))]
1880 "TARGET_HARD_FLOAT"
1881 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3"
1882 [(set_attr "type" "fcmp")
1883 (set_attr "mode" "<UNITMODE>")
1884 (set (attr "length") (const_int 12))])
1885
1886(define_insn "*seq_zero_<X:mode><GPR:mode>"
248710c4
KC
1887 [(set (match_operand:GPR 0 "register_operand" "=r")
1888 (eq:GPR (match_operand:X 1 "register_operand" " r")
1889 (const_int 0)))]
09cae750
PD
1890 ""
1891 "seqz\t%0,%1"
1892 [(set_attr "type" "slt")
1893 (set_attr "mode" "<X:MODE>")])
1894
1895(define_insn "*sne_zero_<X:mode><GPR:mode>"
248710c4
KC
1896 [(set (match_operand:GPR 0 "register_operand" "=r")
1897 (ne:GPR (match_operand:X 1 "register_operand" " r")
1898 (const_int 0)))]
09cae750
PD
1899 ""
1900 "snez\t%0,%1"
1901 [(set_attr "type" "slt")
1902 (set_attr "mode" "<X:MODE>")])
1903
1904(define_insn "*sgt<u>_<X:mode><GPR:mode>"
248710c4
KC
1905 [(set (match_operand:GPR 0 "register_operand" "= r")
1906 (any_gt:GPR (match_operand:X 1 "register_operand" " r")
1907 (match_operand:X 2 "reg_or_0_operand" " rJ")))]
09cae750
PD
1908 ""
1909 "sgt<u>\t%0,%1,%z2"
1910 [(set_attr "type" "slt")
1911 (set_attr "mode" "<X:MODE>")])
1912
1913(define_insn "*sge<u>_<X:mode><GPR:mode>"
248710c4
KC
1914 [(set (match_operand:GPR 0 "register_operand" "=r")
1915 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
1916 (const_int 1)))]
1917 ""
0791ac18 1918 "slt%i2<u>\t%0,zero,%1"
09cae750
PD
1919 [(set_attr "type" "slt")
1920 (set_attr "mode" "<MODE>")])
1921
1922(define_insn "*slt<u>_<X:mode><GPR:mode>"
248710c4
KC
1923 [(set (match_operand:GPR 0 "register_operand" "= r")
1924 (any_lt:GPR (match_operand:X 1 "register_operand" " r")
1925 (match_operand:X 2 "arith_operand" " rI")))]
09cae750 1926 ""
0791ac18 1927 "slt%i2<u>\t%0,%1,%2"
09cae750
PD
1928 [(set_attr "type" "slt")
1929 (set_attr "mode" "<MODE>")])
1930
1931(define_insn "*sle<u>_<X:mode><GPR:mode>"
248710c4
KC
1932 [(set (match_operand:GPR 0 "register_operand" "=r")
1933 (any_le:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
1934 (match_operand:X 2 "sle_operand" "")))]
1935 ""
1936{
1937 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
0791ac18 1938 return "slt%i2<u>\t%0,%1,%2";
09cae750
PD
1939}
1940 [(set_attr "type" "slt")
1941 (set_attr "mode" "<MODE>")])
1942
1943;;
1944;; ....................
1945;;
1946;; UNCONDITIONAL BRANCHES
1947;;
1948;; ....................
1949
1950;; Unconditional branches.
1951
1952(define_insn "jump"
1953 [(set (pc)
1954 (label_ref (match_operand 0 "" "")))]
1955 ""
1956 "j\t%l0"
1957 [(set_attr "type" "jump")
1958 (set_attr "mode" "none")])
1959
1960(define_expand "indirect_jump"
1961 [(set (pc) (match_operand 0 "register_operand"))]
1962 ""
1963{
1964 operands[0] = force_reg (Pmode, operands[0]);
1965 if (Pmode == SImode)
1966 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
1967 else
1968 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
1969 DONE;
1970})
1971
1972(define_insn "indirect_jump<mode>"
1973 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
1974 ""
1975 "jr\t%0"
1976 [(set_attr "type" "jump")
1977 (set_attr "mode" "none")])
1978
1979(define_expand "tablejump"
1980 [(set (pc) (match_operand 0 "register_operand" ""))
1981 (use (label_ref (match_operand 1 "" "")))]
1982 ""
1983{
1984 if (CASE_VECTOR_PC_RELATIVE)
1985 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
1986 gen_rtx_LABEL_REF (Pmode, operands[1]),
1987 NULL_RTX, 0, OPTAB_DIRECT);
1988
1989 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
1990 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
1991 else
1992 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
1993 DONE;
1994})
1995
1996(define_insn "tablejump<mode>"
1997 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
1998 (use (label_ref (match_operand 1 "" "")))]
1999 ""
2000 "jr\t%0"
2001 [(set_attr "type" "jump")
2002 (set_attr "mode" "none")])
2003
2004;;
2005;; ....................
2006;;
2007;; Function prologue/epilogue
2008;;
2009;; ....................
2010;;
2011
2012(define_expand "prologue"
2013 [(const_int 1)]
2014 ""
2015{
2016 riscv_expand_prologue ();
2017 DONE;
2018})
2019
2020;; Block any insns from being moved before this point, since the
2021;; profiling call to mcount can use various registers that aren't
2022;; saved or used to pass arguments.
2023
2024(define_insn "blockage"
2025 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
2026 ""
2027 ""
2028 [(set_attr "type" "ghost")
2029 (set_attr "mode" "none")])
2030
2031(define_expand "epilogue"
2032 [(const_int 2)]
2033 ""
2034{
2035 riscv_expand_epilogue (false);
2036 DONE;
2037})
2038
2039(define_expand "sibcall_epilogue"
2040 [(const_int 2)]
2041 ""
2042{
2043 riscv_expand_epilogue (true);
2044 DONE;
2045})
2046
2047;; Trivial return. Make it look like a normal return insn as that
2048;; allows jump optimizations to work better.
2049
2050(define_expand "return"
2051 [(simple_return)]
2052 "riscv_can_use_return_insn ()"
2053 "")
2054
2055(define_insn "simple_return"
2056 [(simple_return)]
2057 ""
8cad5b14
KC
2058{
2059 return riscv_output_return ();
2060}
09cae750
PD
2061 [(set_attr "type" "jump")
2062 (set_attr "mode" "none")])
2063
2064;; Normal return.
2065
2066(define_insn "simple_return_internal"
2067 [(simple_return)
2068 (use (match_operand 0 "pmode_register_operand" ""))]
2069 ""
2070 "jr\t%0"
2071 [(set_attr "type" "jump")
2072 (set_attr "mode" "none")])
2073
2074;; This is used in compiling the unwind routines.
2075(define_expand "eh_return"
2076 [(use (match_operand 0 "general_operand"))]
2077 ""
2078{
2079 if (GET_MODE (operands[0]) != word_mode)
2080 operands[0] = convert_to_mode (word_mode, operands[0], 0);
2081 if (TARGET_64BIT)
2082 emit_insn (gen_eh_set_lr_di (operands[0]));
2083 else
2084 emit_insn (gen_eh_set_lr_si (operands[0]));
2085 DONE;
2086})
2087
2088;; Clobber the return address on the stack. We can't expand this
2089;; until we know where it will be put in the stack frame.
2090
2091(define_insn "eh_set_lr_si"
2092 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2093 (clobber (match_scratch:SI 1 "=&r"))]
2094 "! TARGET_64BIT"
2095 "#")
2096
2097(define_insn "eh_set_lr_di"
2098 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2099 (clobber (match_scratch:DI 1 "=&r"))]
2100 "TARGET_64BIT"
2101 "#")
2102
2103(define_split
2104 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
2105 (clobber (match_scratch 1))]
2106 "reload_completed"
2107 [(const_int 0)]
2108{
2109 riscv_set_return_address (operands[0], operands[1]);
2110 DONE;
2111})
2112
2113;;
2114;; ....................
2115;;
2116;; FUNCTION CALLS
2117;;
2118;; ....................
2119
2120(define_expand "sibcall"
2121 [(parallel [(call (match_operand 0 "")
2122 (match_operand 1 ""))
2123 (use (match_operand 2 "")) ;; next_arg_reg
2124 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2125 ""
2126{
2127 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2128 emit_call_insn (gen_sibcall_internal (target, operands[1]));
2129 DONE;
2130})
2131
2132(define_insn "sibcall_internal"
2133 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
2134 (match_operand 1 "" ""))]
2135 "SIBLING_CALL_P (insn)"
2136 "@
2137 jr\t%0
2138 tail\t%0
2139 tail\t%0@plt"
2140 [(set_attr "type" "call")])
2141
2142(define_expand "sibcall_value"
2143 [(parallel [(set (match_operand 0 "")
2144 (call (match_operand 1 "")
2145 (match_operand 2 "")))
2146 (use (match_operand 3 ""))])] ;; next_arg_reg
2147 ""
2148{
2149 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2150 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
2151 DONE;
2152})
2153
2154(define_insn "sibcall_value_internal"
2155 [(set (match_operand 0 "" "")
2156 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
2157 (match_operand 2 "" "")))]
2158 "SIBLING_CALL_P (insn)"
2159 "@
2160 jr\t%1
2161 tail\t%1
2162 tail\t%1@plt"
2163 [(set_attr "type" "call")])
2164
2165(define_expand "call"
2166 [(parallel [(call (match_operand 0 "")
2167 (match_operand 1 ""))
2168 (use (match_operand 2 "")) ;; next_arg_reg
2169 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2170 ""
2171{
2172 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2173 emit_call_insn (gen_call_internal (target, operands[1]));
2174 DONE;
2175})
2176
2177(define_insn "call_internal"
2178 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
2179 (match_operand 1 "" ""))
2180 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2181 ""
2182 "@
2183 jalr\t%0
2184 call\t%0
2185 call\t%0@plt"
2186 [(set_attr "type" "call")])
2187
2188(define_expand "call_value"
2189 [(parallel [(set (match_operand 0 "")
2190 (call (match_operand 1 "")
2191 (match_operand 2 "")))
2192 (use (match_operand 3 ""))])] ;; next_arg_reg
2193 ""
2194{
2195 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2196 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
2197 DONE;
2198})
2199
2200(define_insn "call_value_internal"
2201 [(set (match_operand 0 "" "")
2202 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
2203 (match_operand 2 "" "")))
2204 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2205 ""
2206 "@
2207 jalr\t%1
2208 call\t%1
2209 call\t%1@plt"
2210 [(set_attr "type" "call")])
2211
2212;; Call subroutine returning any type.
2213
2214(define_expand "untyped_call"
2215 [(parallel [(call (match_operand 0 "")
2216 (const_int 0))
2217 (match_operand 1 "")
2218 (match_operand 2 "")])]
2219 ""
2220{
2221 int i;
2222
2223 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2224
2225 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2226 {
2227 rtx set = XVECEXP (operands[2], 0, i);
2228 riscv_emit_move (SET_DEST (set), SET_SRC (set));
2229 }
2230
2231 emit_insn (gen_blockage ());
2232 DONE;
2233})
2234
2235(define_insn "nop"
2236 [(const_int 0)]
2237 ""
2238 "nop"
2239 [(set_attr "type" "nop")
2240 (set_attr "mode" "none")])
2241
2242(define_insn "trap"
2243 [(trap_if (const_int 1) (const_int 0))]
2244 ""
2245 "ebreak")
2246
2247(define_insn "gpr_save"
2248 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_SAVE)
2249 (clobber (reg:SI T0_REGNUM))
2250 (clobber (reg:SI T1_REGNUM))]
2251 ""
2252 { return riscv_output_gpr_save (INTVAL (operands[0])); })
2253
2254(define_insn "gpr_restore"
2255 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2256 ""
2257 "tail\t__riscv_restore_%0")
2258
2259(define_insn "gpr_restore_return"
2260 [(return)
2261 (use (match_operand 0 "pmode_register_operand" ""))
2262 (const_int 0)]
2263 ""
2264 "")
2265
2266(define_insn "riscv_frflags"
2267 [(set (match_operand:SI 0 "register_operand" "=r")
2268 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
2269 "TARGET_HARD_FLOAT"
2270 "frflags %0")
2271
2272(define_insn "riscv_fsflags"
2273 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2274 "TARGET_HARD_FLOAT"
2275 "fsflags %0")
2276
2277(define_insn "stack_tie<mode>"
2278 [(set (mem:BLK (scratch))
2279 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
2280 (match_operand:X 1 "register_operand" "r")]
2281 UNSPEC_TIE))]
2282 ""
2283 ""
2284 [(set_attr "length" "0")]
2285)
2286
2287(include "sync.md")
2288(include "peephole.md")
2289(include "pic.md")
2290(include "generic.md")