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