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