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