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