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