]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/riscv/riscv.md
Ability to build the GNAT runtime with project files
[thirdparty/gcc.git] / gcc / config / riscv / riscv.md
CommitLineData
09cae750 1;; Machine description for RISC-V for GNU compiler.
8d9254fc 2;; Copyright (C) 2011-2020 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,
4f475391 159 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,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"
36ec3f57
JJ
1054 "&& reload_completed
1055 && REG_P (operands[1])
1056 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1057 [(set (match_dup 0)
1058 (ashift:DI (match_dup 1) (const_int 32)))
1059 (set (match_dup 0)
1060 (lshiftrt:DI (match_dup 0) (const_int 32)))]
1061 { operands[1] = gen_lowpart (DImode, operands[1]); }
1062 [(set_attr "move_type" "shift_shift,load")
1063 (set_attr "mode" "DI")])
1064
1065(define_insn_and_split "zero_extendhi<GPR:mode>2"
248710c4
KC
1066 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1067 (zero_extend:GPR
1068 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1069 ""
1070 "@
1071 #
1072 lhu\t%0,%1"
36ec3f57
JJ
1073 "&& reload_completed
1074 && REG_P (operands[1])
1075 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1076 [(set (match_dup 0)
1077 (ashift:GPR (match_dup 1) (match_dup 2)))
1078 (set (match_dup 0)
1079 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1080 {
1081 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1082 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1083 }
1084 [(set_attr "move_type" "shift_shift,load")
1085 (set_attr "mode" "<GPR:MODE>")])
1086
1087(define_insn "zero_extendqi<SUPERQI:mode>2"
248710c4 1088 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1089 (zero_extend:SUPERQI
248710c4 1090 (match_operand:QI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1091 ""
1092 "@
0791ac18 1093 andi\t%0,%1,0xff
09cae750
PD
1094 lbu\t%0,%1"
1095 [(set_attr "move_type" "andi,load")
1096 (set_attr "mode" "<SUPERQI:MODE>")])
1097
1098;;
1099;; ....................
1100;;
1101;; SIGN EXTENSION
1102;;
1103;; ....................
1104
1105(define_insn "extendsidi2"
248710c4
KC
1106 [(set (match_operand:DI 0 "register_operand" "=r,r")
1107 (sign_extend:DI
1108 (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1109 "TARGET_64BIT"
1110 "@
1111 sext.w\t%0,%1
1112 lw\t%0,%1"
1113 [(set_attr "move_type" "move,load")
1114 (set_attr "mode" "DI")])
1115
1116(define_insn_and_split "extend<SHORT:mode><SUPERQI:mode>2"
248710c4 1117 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
09cae750 1118 (sign_extend:SUPERQI
248710c4 1119 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
09cae750
PD
1120 ""
1121 "@
1122 #
1123 l<SHORT:size>\t%0,%1"
36ec3f57
JJ
1124 "&& reload_completed
1125 && REG_P (operands[1])
1126 && !paradoxical_subreg_p (operands[0])"
09cae750
PD
1127 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1128 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
1129{
1130 operands[0] = gen_lowpart (SImode, operands[0]);
1131 operands[1] = gen_lowpart (SImode, operands[1]);
1132 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1133 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1134}
1135 [(set_attr "move_type" "shift_shift,load")
1136 (set_attr "mode" "SI")])
1137
1138(define_insn "extendsfdf2"
248710c4
KC
1139 [(set (match_operand:DF 0 "register_operand" "=f")
1140 (float_extend:DF
1141 (match_operand:SF 1 "register_operand" " f")))]
09cae750
PD
1142 "TARGET_DOUBLE_FLOAT"
1143 "fcvt.d.s\t%0,%1"
1144 [(set_attr "type" "fcvt")
1145 (set_attr "mode" "DF")])
1146
1147;;
1148;; ....................
1149;;
1150;; CONVERSIONS
1151;;
1152;; ....................
1153
1154(define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
248710c4
KC
1155 [(set (match_operand:GPR 0 "register_operand" "=r")
1156 (fix:GPR
1157 (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
1158 "TARGET_HARD_FLOAT"
1159 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
1160 [(set_attr "type" "fcvt")
1161 (set_attr "mode" "<ANYF:MODE>")])
1162
1163(define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2"
248710c4
KC
1164 [(set (match_operand:GPR 0 "register_operand" "=r")
1165 (unsigned_fix:GPR
1166 (match_operand:ANYF 1 "register_operand" " f")))]
09cae750
PD
1167 "TARGET_HARD_FLOAT"
1168 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
1169 [(set_attr "type" "fcvt")
1170 (set_attr "mode" "<ANYF:MODE>")])
1171
1172(define_insn "float<GPR:mode><ANYF:mode>2"
248710c4
KC
1173 [(set (match_operand:ANYF 0 "register_operand" "= f")
1174 (float:ANYF
1175 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
09cae750
PD
1176 "TARGET_HARD_FLOAT"
1177 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
1178 [(set_attr "type" "fcvt")
1179 (set_attr "mode" "<ANYF:MODE>")])
1180
1181(define_insn "floatuns<GPR:mode><ANYF:mode>2"
248710c4
KC
1182 [(set (match_operand:ANYF 0 "register_operand" "= f")
1183 (unsigned_float:ANYF
1184 (match_operand:GPR 1 "reg_or_0_operand" " rJ")))]
09cae750
PD
1185 "TARGET_HARD_FLOAT"
1186 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
1187 [(set_attr "type" "fcvt")
1188 (set_attr "mode" "<ANYF:MODE>")])
1189
1190(define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2"
248710c4
KC
1191 [(set (match_operand:GPR 0 "register_operand" "=r")
1192 (unspec:GPR
1193 [(match_operand:ANYF 1 "register_operand" " f")]
1194 RINT))]
09cae750
PD
1195 "TARGET_HARD_FLOAT"
1196 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
1197 [(set_attr "type" "fcvt")
1198 (set_attr "mode" "<ANYF:MODE>")])
1199
1200;;
1201;; ....................
1202;;
1203;; DATA MOVEMENT
1204;;
1205;; ....................
1206
1207;; Lower-level instructions for loading an address from the GOT.
1208;; We could use MEMs, but an unspec gives more optimization
1209;; opportunities.
1210
1211(define_insn "got_load<mode>"
248710c4
KC
1212 [(set (match_operand:P 0 "register_operand" "=r")
1213 (unspec:P
1214 [(match_operand:P 1 "symbolic_operand" "")]
1215 UNSPEC_LOAD_GOT))]
09cae750
PD
1216 ""
1217 "la\t%0,%1"
1218 [(set_attr "got" "load")
1219 (set_attr "mode" "<MODE>")])
1220
1221(define_insn "tls_add_tp_le<mode>"
248710c4
KC
1222 [(set (match_operand:P 0 "register_operand" "=r")
1223 (unspec:P
1224 [(match_operand:P 1 "register_operand" "r")
1225 (match_operand:P 2 "register_operand" "r")
1226 (match_operand:P 3 "symbolic_operand" "")]
1227 UNSPEC_TLS_LE))]
09cae750
PD
1228 ""
1229 "add\t%0,%1,%2,%%tprel_add(%3)"
1230 [(set_attr "type" "arith")
1231 (set_attr "mode" "<MODE>")])
1232
1233(define_insn "got_load_tls_gd<mode>"
248710c4
KC
1234 [(set (match_operand:P 0 "register_operand" "=r")
1235 (unspec:P
1236 [(match_operand:P 1 "symbolic_operand" "")]
1237 UNSPEC_TLS_GD))]
09cae750
PD
1238 ""
1239 "la.tls.gd\t%0,%1"
1240 [(set_attr "got" "load")
1241 (set_attr "mode" "<MODE>")])
1242
1243(define_insn "got_load_tls_ie<mode>"
248710c4
KC
1244 [(set (match_operand:P 0 "register_operand" "=r")
1245 (unspec:P
1246 [(match_operand:P 1 "symbolic_operand" "")]
1247 UNSPEC_TLS_IE))]
09cae750
PD
1248 ""
1249 "la.tls.ie\t%0,%1"
1250 [(set_attr "got" "load")
1251 (set_attr "mode" "<MODE>")])
1252
1253(define_insn "auipc<mode>"
248710c4
KC
1254 [(set (match_operand:P 0 "register_operand" "=r")
1255 (unspec:P
1256 [(match_operand:P 1 "symbolic_operand" "")
09cae750
PD
1257 (match_operand:P 2 "const_int_operand")
1258 (pc)]
248710c4 1259 UNSPEC_AUIPC))]
09cae750
PD
1260 ""
1261 ".LA%2: auipc\t%0,%h1"
88108b27 1262 [(set_attr "type" "auipc")
09cae750
PD
1263 (set_attr "cannot_copy" "yes")])
1264
1265;; Instructions for adding the low 12 bits of an address to a register.
1266;; Operand 2 is the address: riscv_print_operand works out which relocation
1267;; should be applied.
1268
1269(define_insn "*low<mode>"
248710c4
KC
1270 [(set (match_operand:P 0 "register_operand" "=r")
1271 (lo_sum:P (match_operand:P 1 "register_operand" " r")
09cae750
PD
1272 (match_operand:P 2 "symbolic_operand" "")))]
1273 ""
1274 "addi\t%0,%1,%R2"
1275 [(set_attr "type" "arith")
1276 (set_attr "mode" "<MODE>")])
1277
1278;; Allow combine to split complex const_int load sequences, using operand 2
1279;; to store the intermediate results. See move_operand for details.
1280(define_split
1281 [(set (match_operand:GPR 0 "register_operand")
1282 (match_operand:GPR 1 "splittable_const_int_operand"))
1283 (clobber (match_operand:GPR 2 "register_operand"))]
1284 ""
1285 [(const_int 0)]
1286{
51175507 1287 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]),
a923a463 1288 <GPR:MODE>mode, TRUE);
09cae750
PD
1289 DONE;
1290})
1291
1292;; Likewise, for symbolic operands.
1293(define_split
1294 [(set (match_operand:P 0 "register_operand")
1295 (match_operand:P 1))
1296 (clobber (match_operand:P 2 "register_operand"))]
a923a463 1297 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL, TRUE)"
09cae750
PD
1298 [(set (match_dup 0) (match_dup 3))]
1299{
1300 riscv_split_symbol (operands[2], operands[1],
a923a463 1301 MAX_MACHINE_MODE, &operands[3], TRUE);
09cae750
PD
1302})
1303
1304;; 64-bit integer moves
1305
1306(define_expand "movdi"
1307 [(set (match_operand:DI 0 "")
1308 (match_operand:DI 1 ""))]
1309 ""
1310{
1311 if (riscv_legitimize_move (DImode, operands[0], operands[1]))
1312 DONE;
1313})
1314
1315(define_insn "*movdi_32bit"
1316 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m")
248710c4 1317 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))]
09cae750
PD
1318 "!TARGET_64BIT
1319 && (register_operand (operands[0], DImode)
1320 || reg_or_0_operand (operands[1], DImode))"
1321 { return riscv_output_move (operands[0], operands[1]); }
1322 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1323 (set_attr "mode" "DI")])
1324
1325(define_insn "*movdi_64bit"
248710c4
KC
1326 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m")
1327 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))]
09cae750
PD
1328 "TARGET_64BIT
1329 && (register_operand (operands[0], DImode)
1330 || reg_or_0_operand (operands[1], DImode))"
1331 { return riscv_output_move (operands[0], operands[1]); }
1332 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1333 (set_attr "mode" "DI")])
1334
1335;; 32-bit Integer moves
1336
1337(define_expand "mov<mode>"
1338 [(set (match_operand:MOVE32 0 "")
1339 (match_operand:MOVE32 1 ""))]
1340 ""
1341{
1342 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
1343 DONE;
1344})
1345
1346(define_insn "*movsi_internal"
248710c4
KC
1347 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*m")
1348 (match_operand:SI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f"))]
09cae750
PD
1349 "(register_operand (operands[0], SImode)
1350 || reg_or_0_operand (operands[1], SImode))"
1351 { return riscv_output_move (operands[0], operands[1]); }
1352 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
1353 (set_attr "mode" "SI")])
1354
1355;; 16-bit Integer moves
1356
1357;; Unlike most other insns, the move insns can't be split with
1358;; different predicates, because register spilling and other parts of
1359;; the compiler, have memoized the insn number already.
1360;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
1361
1362(define_expand "movhi"
1363 [(set (match_operand:HI 0 "")
1364 (match_operand:HI 1 ""))]
1365 ""
1366{
1367 if (riscv_legitimize_move (HImode, operands[0], operands[1]))
1368 DONE;
1369})
1370
1371(define_insn "*movhi_internal"
248710c4
KC
1372 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1373 (match_operand:HI 1 "move_operand" " r,T,m,rJ,*r*J,*f"))]
09cae750
PD
1374 "(register_operand (operands[0], HImode)
1375 || reg_or_0_operand (operands[1], HImode))"
1376 { return riscv_output_move (operands[0], operands[1]); }
1377 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1378 (set_attr "mode" "HI")])
1379
1380;; HImode constant generation; see riscv_move_integer for details.
bb149ca2
RS
1381;; si+si->hi without truncation is legal because of
1382;; TARGET_TRULY_NOOP_TRUNCATION.
09cae750
PD
1383
1384(define_insn "*add<mode>hi3"
248710c4
KC
1385 [(set (match_operand:HI 0 "register_operand" "=r,r")
1386 (plus:HI (match_operand:HISI 1 "register_operand" " r,r")
1387 (match_operand:HISI 2 "arith_operand" " r,I")))]
09cae750 1388 ""
0791ac18 1389 { return TARGET_64BIT ? "add%i2w\t%0,%1,%2" : "add%i2\t%0,%1,%2"; }
09cae750
PD
1390 [(set_attr "type" "arith")
1391 (set_attr "mode" "HI")])
1392
1393(define_insn "*xor<mode>hi3"
248710c4
KC
1394 [(set (match_operand:HI 0 "register_operand" "=r,r")
1395 (xor:HI (match_operand:HISI 1 "register_operand" " r,r")
1396 (match_operand:HISI 2 "arith_operand" " r,I")))]
09cae750 1397 ""
0791ac18 1398 "xor%i2\t%0,%1,%2"
09cae750
PD
1399 [(set_attr "type" "logical")
1400 (set_attr "mode" "HI")])
1401
1402;; 8-bit Integer moves
1403
1404(define_expand "movqi"
1405 [(set (match_operand:QI 0 "")
1406 (match_operand:QI 1 ""))]
1407 ""
1408{
1409 if (riscv_legitimize_move (QImode, operands[0], operands[1]))
1410 DONE;
1411})
1412
1413(define_insn "*movqi_internal"
248710c4
KC
1414 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r, m, *f,*r")
1415 (match_operand:QI 1 "move_operand" " r,I,m,rJ,*r*J,*f"))]
09cae750
PD
1416 "(register_operand (operands[0], QImode)
1417 || reg_or_0_operand (operands[1], QImode))"
1418 { return riscv_output_move (operands[0], operands[1]); }
1419 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1420 (set_attr "mode" "QI")])
1421
1422;; 32-bit floating point moves
1423
1424(define_expand "movsf"
1425 [(set (match_operand:SF 0 "")
1426 (match_operand:SF 1 ""))]
1427 ""
1428{
1429 if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
1430 DONE;
1431})
1432
1433(define_insn "*movsf_hardfloat"
248710c4
KC
1434 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1435 (match_operand:SF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
09cae750
PD
1436 "TARGET_HARD_FLOAT
1437 && (register_operand (operands[0], SFmode)
1438 || reg_or_0_operand (operands[1], SFmode))"
1439 { return riscv_output_move (operands[0], operands[1]); }
1440 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1441 (set_attr "mode" "SF")])
1442
1443(define_insn "*movsf_softfloat"
248710c4
KC
1444 [(set (match_operand:SF 0 "nonimmediate_operand" "= r,r,m")
1445 (match_operand:SF 1 "move_operand" " Gr,m,r"))]
09cae750
PD
1446 "!TARGET_HARD_FLOAT
1447 && (register_operand (operands[0], SFmode)
1448 || reg_or_0_operand (operands[1], SFmode))"
1449 { return riscv_output_move (operands[0], operands[1]); }
1450 [(set_attr "move_type" "move,load,store")
1451 (set_attr "mode" "SF")])
1452
1453;; 64-bit floating point moves
1454
1455(define_expand "movdf"
1456 [(set (match_operand:DF 0 "")
1457 (match_operand:DF 1 ""))]
1458 ""
1459{
1460 if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
1461 DONE;
1462})
1463
1464;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
1465;; (However, we can still use fcvt.d.w to zero a floating-point register.)
1466(define_insn "*movdf_hardfloat_rv32"
248710c4
KC
1467 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m")
1468 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))]
09cae750
PD
1469 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
1470 && (register_operand (operands[0], DFmode)
1471 || reg_or_0_operand (operands[1], DFmode))"
1472 { return riscv_output_move (operands[0], operands[1]); }
1473 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store")
1474 (set_attr "mode" "DF")])
1475
1476(define_insn "*movdf_hardfloat_rv64"
248710c4
KC
1477 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
1478 (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
09cae750
PD
1479 "TARGET_64BIT && TARGET_DOUBLE_FLOAT
1480 && (register_operand (operands[0], DFmode)
1481 || reg_or_0_operand (operands[1], DFmode))"
1482 { return riscv_output_move (operands[0], operands[1]); }
1483 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1484 (set_attr "mode" "DF")])
1485
1486(define_insn "*movdf_softfloat"
248710c4
KC
1487 [(set (match_operand:DF 0 "nonimmediate_operand" "= r,r, m")
1488 (match_operand:DF 1 "move_operand" " rG,m,rG"))]
09cae750
PD
1489 "!TARGET_DOUBLE_FLOAT
1490 && (register_operand (operands[0], DFmode)
1491 || reg_or_0_operand (operands[1], DFmode))"
1492 { return riscv_output_move (operands[0], operands[1]); }
1493 [(set_attr "move_type" "move,load,store")
1494 (set_attr "mode" "DF")])
1495
1496(define_split
1497 [(set (match_operand:MOVE64 0 "nonimmediate_operand")
1498 (match_operand:MOVE64 1 "move_operand"))]
1499 "reload_completed
1500 && riscv_split_64bit_move_p (operands[0], operands[1])"
1501 [(const_int 0)]
1502{
1503 riscv_split_doubleword_move (operands[0], operands[1]);
1504 DONE;
1505})
1506
76715c32 1507(define_expand "cpymemsi"
6ed01e6b
AW
1508 [(parallel [(set (match_operand:BLK 0 "general_operand")
1509 (match_operand:BLK 1 "general_operand"))
1510 (use (match_operand:SI 2 ""))
1511 (use (match_operand:SI 3 "const_int_operand"))])]
1512 ""
1513{
1514 if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
1515 DONE;
1516 else
1517 FAIL;
1518})
1519
09cae750
PD
1520;; Expand in-line code to clear the instruction cache between operand[0] and
1521;; operand[1].
1522(define_expand "clear_cache"
1523 [(match_operand 0 "pmode_register_operand")
1524 (match_operand 1 "pmode_register_operand")]
1525 ""
1526{
f1bdc63a
AW
1527#ifdef ICACHE_FLUSH_FUNC
1528 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, ICACHE_FLUSH_FUNC),
1529 LCT_NORMAL, VOIDmode, operands[0], Pmode,
1530 operands[1], Pmode, const0_rtx, Pmode);
1531#else
09cae750 1532 emit_insn (gen_fence_i ());
f1bdc63a 1533#endif
09cae750
PD
1534 DONE;
1535})
1536
1537(define_insn "fence"
1538 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
1539 ""
1540 "%|fence%-")
1541
1542(define_insn "fence_i"
1543 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
1544 ""
1545 "fence.i")
1546
1547;;
1548;; ....................
1549;;
1550;; SHIFTS
1551;;
1552;; ....................
1553
b7ef9225
JW
1554;; Use a QImode shift count, to avoid generating sign or zero extend
1555;; instructions for shift counts, and to avoid dropping subregs.
1556;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
1557;; defined, but use of that is discouraged.
1558
09cae750 1559(define_insn "<optab>si3"
248710c4
KC
1560 [(set (match_operand:SI 0 "register_operand" "= r")
1561 (any_shift:SI
1562 (match_operand:SI 1 "register_operand" " r")
b7ef9225 1563 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
1564 ""
1565{
1566 if (GET_CODE (operands[2]) == CONST_INT)
1567 operands[2] = GEN_INT (INTVAL (operands[2])
1568 & (GET_MODE_BITSIZE (SImode) - 1));
1569
0791ac18 1570 return TARGET_64BIT ? "<insn>%i2w\t%0,%1,%2" : "<insn>%i2\t%0,%1,%2";
09cae750
PD
1571}
1572 [(set_attr "type" "shift")
1573 (set_attr "mode" "SI")])
1574
110fb19f 1575(define_insn_and_split "*<optab>si3_mask"
b7ef9225
JW
1576 [(set (match_operand:SI 0 "register_operand" "= r")
1577 (any_shift:SI
1578 (match_operand:SI 1 "register_operand" " r")
1579 (subreg:QI
1580 (and:SI
1581 (match_operand:SI 2 "register_operand" "r")
1582 (match_operand 3 "const_int_operand")) 0)))]
1583 "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1584 == GET_MODE_BITSIZE (SImode)-1"
1585 "#"
1586 "&& 1"
1587 [(set (match_dup 0)
1588 (any_shift:SI (match_dup 1)
1589 (match_dup 2)))]
1590 "operands[2] = gen_lowpart (QImode, operands[2]);"
1591 [(set_attr "type" "shift")
1592 (set_attr "mode" "SI")])
1593
110fb19f 1594(define_insn_and_split "*<optab>si3_mask_1"
b7ef9225
JW
1595 [(set (match_operand:SI 0 "register_operand" "= r")
1596 (any_shift:SI
1597 (match_operand:SI 1 "register_operand" " r")
1598 (subreg:QI
1599 (and:DI
1600 (match_operand:DI 2 "register_operand" "r")
1601 (match_operand 3 "const_int_operand")) 0)))]
1602 "TARGET_64BIT
1603 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1604 == GET_MODE_BITSIZE (SImode)-1"
1605 "#"
1606 "&& 1"
1607 [(set (match_dup 0)
1608 (any_shift:SI (match_dup 1)
1609 (match_dup 2)))]
1610 "operands[2] = gen_lowpart (QImode, operands[2]);"
1611 [(set_attr "type" "shift")
1612 (set_attr "mode" "SI")])
1613
09cae750 1614(define_insn "<optab>di3"
248710c4
KC
1615 [(set (match_operand:DI 0 "register_operand" "= r")
1616 (any_shift:DI
1617 (match_operand:DI 1 "register_operand" " r")
b7ef9225 1618 (match_operand:QI 2 "arith_operand" " rI")))]
09cae750
PD
1619 "TARGET_64BIT"
1620{
1621 if (GET_CODE (operands[2]) == CONST_INT)
1622 operands[2] = GEN_INT (INTVAL (operands[2])
1623 & (GET_MODE_BITSIZE (DImode) - 1));
1624
0791ac18 1625 return "<insn>%i2\t%0,%1,%2";
09cae750
PD
1626}
1627 [(set_attr "type" "shift")
1628 (set_attr "mode" "DI")])
1629
110fb19f 1630(define_insn_and_split "*<optab>di3_mask"
b7ef9225
JW
1631 [(set (match_operand:DI 0 "register_operand" "= r")
1632 (any_shift:DI
1633 (match_operand:DI 1 "register_operand" " r")
1634 (subreg:QI
1635 (and:SI
1636 (match_operand:SI 2 "register_operand" "r")
1637 (match_operand 3 "const_int_operand")) 0)))]
1638 "TARGET_64BIT
1639 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1640 == GET_MODE_BITSIZE (DImode)-1"
1641 "#"
1642 "&& 1"
1643 [(set (match_dup 0)
1644 (any_shift:DI (match_dup 1)
1645 (match_dup 2)))]
1646 "operands[2] = gen_lowpart (QImode, operands[2]);"
1647 [(set_attr "type" "shift")
1648 (set_attr "mode" "DI")])
1649
110fb19f 1650(define_insn_and_split "*<optab>di3_mask_1"
b7ef9225
JW
1651 [(set (match_operand:DI 0 "register_operand" "= r")
1652 (any_shift:DI
1653 (match_operand:DI 1 "register_operand" " r")
1654 (subreg:QI
1655 (and:DI
1656 (match_operand:DI 2 "register_operand" "r")
1657 (match_operand 3 "const_int_operand")) 0)))]
1658 "TARGET_64BIT
1659 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
1660 == GET_MODE_BITSIZE (DImode)-1"
1661 "#"
1662 "&& 1"
1663 [(set (match_dup 0)
1664 (any_shift:DI (match_dup 1)
1665 (match_dup 2)))]
1666 "operands[2] = gen_lowpart (QImode, operands[2]);"
1667 [(set_attr "type" "shift")
1668 (set_attr "mode" "DI")])
1669
09cae750 1670(define_insn "*<optab>si3_extend"
248710c4 1671 [(set (match_operand:DI 0 "register_operand" "= r")
09cae750 1672 (sign_extend:DI
248710c4 1673 (any_shift:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 1674 (match_operand:QI 2 "arith_operand" " rI"))))]
09cae750
PD
1675 "TARGET_64BIT"
1676{
1677 if (GET_CODE (operands[2]) == CONST_INT)
1678 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1679
0791ac18 1680 return "<insn>%i2w\t%0,%1,%2";
09cae750
PD
1681}
1682 [(set_attr "type" "shift")
1683 (set_attr "mode" "SI")])
1684
b7ef9225
JW
1685(define_insn_and_split "*<optab>si3_extend_mask"
1686 [(set (match_operand:DI 0 "register_operand" "= r")
1687 (sign_extend:DI
1688 (any_shift:SI
1689 (match_operand:SI 1 "register_operand" " r")
1690 (subreg:QI
1691 (and:SI
1692 (match_operand:SI 2 "register_operand" " r")
1693 (match_operand 3 "const_int_operand")) 0))))]
1694 "TARGET_64BIT
1695 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1696 == GET_MODE_BITSIZE (SImode)-1"
1697 "#"
1698 "&& 1"
1699 [(set (match_dup 0)
1700 (sign_extend:DI
1701 (any_shift:SI (match_dup 1)
1702 (match_dup 2))))]
1703 "operands[2] = gen_lowpart (QImode, operands[2]);"
1704 [(set_attr "type" "shift")
1705 (set_attr "mode" "SI")])
1706
1707(define_insn_and_split "*<optab>si3_extend_mask_1"
1708 [(set (match_operand:DI 0 "register_operand" "= r")
1709 (sign_extend:DI
1710 (any_shift:SI
1711 (match_operand:SI 1 "register_operand" " r")
1712 (subreg:QI
1713 (and:DI
1714 (match_operand:DI 2 "register_operand" " r")
1715 (match_operand 3 "const_int_operand")) 0))))]
1716 "TARGET_64BIT
1717 && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
1718 == GET_MODE_BITSIZE (SImode)-1"
1719 "#"
1720 "&& 1"
1721 [(set (match_dup 0)
1722 (sign_extend:DI
1723 (any_shift:SI (match_dup 1)
1724 (match_dup 2))))]
1725 "operands[2] = gen_lowpart (QImode, operands[2]);"
1726 [(set_attr "type" "shift")
1727 (set_attr "mode" "SI")])
1728
08539f3e
JW
1729;; Non-canonical, but can be formed by ree when combine is not successful at
1730;; producing one of the two canonical patterns below.
1731(define_insn "*lshrsi3_zero_extend_1"
1732 [(set (match_operand:DI 0 "register_operand" "=r")
1733 (zero_extend:DI
1734 (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
b7ef9225 1735 (match_operand 2 "const_int_operand"))))]
08539f3e
JW
1736 "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
1737{
1738 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1739
1740 return "srliw\t%0,%1,%2";
1741}
1742 [(set_attr "type" "shift")
1743 (set_attr "mode" "SI")])
1744
1745;; Canonical form for a zero-extend of a logical right shift.
1746(define_insn "*lshrsi3_zero_extend_2"
1747 [(set (match_operand:DI 0 "register_operand" "=r")
1748 (zero_extract:DI (match_operand:DI 1 "register_operand" " r")
1749 (match_operand 2 "const_int_operand")
1750 (match_operand 3 "const_int_operand")))]
1751 "(TARGET_64BIT && (INTVAL (operands[3]) > 0)
1752 && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
1753{
1754 return "srliw\t%0,%1,%3";
1755}
1756 [(set_attr "type" "shift")
1757 (set_attr "mode" "SI")])
1758
1759;; Canonical form for a zero-extend of a logical right shift when the
1760;; shift count is 31.
1761(define_insn "*lshrsi3_zero_extend_3"
1762 [(set (match_operand:DI 0 "register_operand" "=r")
1763 (lt:DI (match_operand:SI 1 "register_operand" " r")
1764 (const_int 0)))]
1765 "TARGET_64BIT"
1766{
1767 return "srliw\t%0,%1,31";
1768}
1769 [(set_attr "type" "shift")
1770 (set_attr "mode" "SI")])
1771
666fdc46
JW
1772;; Handle AND with 2^N-1 for N from 12 to XLEN. This can be split into
1773;; two logical shifts. Otherwise it requires 3 instructions: lui,
1774;; xor/addi/srli, and.
36ec3f57
JJ
1775
1776;; Generating a temporary for the shift output gives better combiner results;
1777;; and also fixes a problem where op0 could be a paradoxical reg and shifting
1778;; by amounts larger than the size of the SUBREG_REG doesn't work.
666fdc46
JW
1779(define_split
1780 [(set (match_operand:GPR 0 "register_operand")
1781 (and:GPR (match_operand:GPR 1 "register_operand")
36ec3f57
JJ
1782 (match_operand:GPR 2 "p2m1_shift_operand")))
1783 (clobber (match_operand:GPR 3 "register_operand"))]
666fdc46 1784 ""
36ec3f57 1785 [(set (match_dup 3)
666fdc46
JW
1786 (ashift:GPR (match_dup 1) (match_dup 2)))
1787 (set (match_dup 0)
36ec3f57 1788 (lshiftrt:GPR (match_dup 3) (match_dup 2)))]
666fdc46 1789{
ace4317a
JW
1790 /* Op2 is a VOIDmode constant, so get the mode size from op1. */
1791 operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1]))
666fdc46
JW
1792 - exact_log2 (INTVAL (operands[2]) + 1));
1793})
ace4317a 1794
666fdc46
JW
1795;; Handle AND with 0xF...F0...0 where there are 32 to 63 zeros. This can be
1796;; split into two shifts. Otherwise it requires 3 instructions: li, sll, and.
1797(define_split
1798 [(set (match_operand:DI 0 "register_operand")
1799 (and:DI (match_operand:DI 1 "register_operand")
36ec3f57
JJ
1800 (match_operand:DI 2 "high_mask_shift_operand")))
1801 (clobber (match_operand:DI 3 "register_operand"))]
666fdc46 1802 "TARGET_64BIT"
36ec3f57 1803 [(set (match_dup 3)
666fdc46
JW
1804 (lshiftrt:DI (match_dup 1) (match_dup 2)))
1805 (set (match_dup 0)
36ec3f57 1806 (ashift:DI (match_dup 3) (match_dup 2)))]
666fdc46
JW
1807{
1808 operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2])));
1809})
1810
09cae750
PD
1811;;
1812;; ....................
1813;;
1814;; CONDITIONAL BRANCHES
1815;;
1816;; ....................
1817
1818;; Conditional branches
1819
4f475391 1820(define_insn "*branch<mode>"
09cae750
PD
1821 [(set (pc)
1822 (if_then_else
1823 (match_operator 1 "order_operator"
1824 [(match_operand:X 2 "register_operand" "r")
4f475391 1825 (match_operand:X 3 "reg_or_0_operand" "rJ")])
09cae750
PD
1826 (label_ref (match_operand 0 "" ""))
1827 (pc)))]
1828 ""
4f475391 1829 "b%C1\t%2,%z3,%0"
09cae750
PD
1830 [(set_attr "type" "branch")
1831 (set_attr "mode" "none")])
1832
4f475391
AW
1833;; Patterns for implementations that optimize short forward branches.
1834
1835(define_expand "mov<mode>cc"
1836 [(set (match_operand:GPR 0 "register_operand")
1837 (if_then_else:GPR (match_operand 1 "comparison_operator")
1838 (match_operand:GPR 2 "register_operand")
1839 (match_operand:GPR 3 "sfb_alu_operand")))]
1840 "TARGET_SFB_ALU"
1841{
1842 rtx cmp = operands[1];
1843 /* We only handle word mode integer compares for now. */
1844 if (GET_MODE (XEXP (cmp, 0)) != word_mode)
1845 FAIL;
1846 riscv_expand_conditional_move (operands[0], operands[2], operands[3],
1847 GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
1848 DONE;
1849})
1850
1851(define_insn "*mov<GPR:mode><X:mode>cc"
1852 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1853 (if_then_else:GPR
1854 (match_operator 5 "order_operator"
1855 [(match_operand:X 1 "register_operand" "r,r")
1856 (match_operand:X 2 "reg_or_0_operand" "rJ,rJ")])
1857 (match_operand:GPR 3 "register_operand" "0,0")
1858 (match_operand:GPR 4 "sfb_alu_operand" "rJ,IL")))]
1859 "TARGET_SFB_ALU"
1860 "@
1861 b%C5 %1,%z2,1f; mv %0,%z4; 1: # movcc
1862 b%C5 %1,%z2,1f; li %0,%4; 1: # movcc"
1863 [(set_attr "length" "8")
1864 (set_attr "type" "sfb_alu")
1865 (set_attr "mode" "<GPR:MODE>")])
09cae750
PD
1866
1867;; Used to implement built-in functions.
1868(define_expand "condjump"
1869 [(set (pc)
1870 (if_then_else (match_operand 0)
1871 (label_ref (match_operand 1))
1872 (pc)))])
1873
1874(define_expand "cbranch<mode>4"
1875 [(set (pc)
1876 (if_then_else (match_operator 0 "comparison_operator"
248710c4
KC
1877 [(match_operand:BR 1 "register_operand")
1878 (match_operand:BR 2 "nonmemory_operand")])
09cae750
PD
1879 (label_ref (match_operand 3 ""))
1880 (pc)))]
1881 ""
1882{
1883 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1884 operands[1], operands[2]);
1885 DONE;
1886})
1887
1888(define_expand "cbranch<mode>4"
1889 [(set (pc)
1890 (if_then_else (match_operator 0 "fp_branch_comparison"
1891 [(match_operand:ANYF 1 "register_operand")
1892 (match_operand:ANYF 2 "register_operand")])
1893 (label_ref (match_operand 3 ""))
1894 (pc)))]
1895 "TARGET_HARD_FLOAT"
1896{
1897 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1898 operands[1], operands[2]);
1899 DONE;
1900})
1901
1902(define_insn_and_split "*branch_on_bit<X:mode>"
1903 [(set (pc)
1904 (if_then_else
248710c4
KC
1905 (match_operator 0 "equality_operator"
1906 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1907 (const_int 1)
1908 (match_operand 3 "branch_on_bit_operand"))
1909 (const_int 0)])
1910 (label_ref (match_operand 1))
1911 (pc)))
09cae750
PD
1912 (clobber (match_scratch:X 4 "=&r"))]
1913 ""
1914 "#"
1915 "reload_completed"
1916 [(set (match_dup 4)
1917 (ashift:X (match_dup 2) (match_dup 3)))
1918 (set (pc)
1919 (if_then_else
248710c4
KC
1920 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1921 (label_ref (match_operand 1))
1922 (pc)))]
09cae750
PD
1923{
1924 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
1925 operands[3] = GEN_INT (shift);
1926
1927 if (GET_CODE (operands[0]) == EQ)
1928 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
1929 else
1930 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
1931})
1932
1933(define_insn_and_split "*branch_on_bit_range<X:mode>"
1934 [(set (pc)
1935 (if_then_else
248710c4
KC
1936 (match_operator 0 "equality_operator"
1937 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1938 (match_operand 3 "branch_on_bit_operand")
1939 (const_int 0))
1940 (const_int 0)])
1941 (label_ref (match_operand 1))
1942 (pc)))
09cae750
PD
1943 (clobber (match_scratch:X 4 "=&r"))]
1944 ""
1945 "#"
1946 "reload_completed"
1947 [(set (match_dup 4)
1948 (ashift:X (match_dup 2) (match_dup 3)))
1949 (set (pc)
1950 (if_then_else
248710c4
KC
1951 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1952 (label_ref (match_operand 1))
1953 (pc)))]
09cae750
PD
1954{
1955 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
1956})
1957
1958;;
1959;; ....................
1960;;
1961;; SETTING A REGISTER FROM A COMPARISON
1962;;
1963;; ....................
1964
1965;; Destination is always set in SI mode.
1966
1967(define_expand "cstore<mode>4"
1968 [(set (match_operand:SI 0 "register_operand")
1969 (match_operator:SI 1 "order_operator"
248710c4
KC
1970 [(match_operand:GPR 2 "register_operand")
1971 (match_operand:GPR 3 "nonmemory_operand")]))]
09cae750
PD
1972 ""
1973{
1974 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
1975 operands[3]);
1976 DONE;
1977})
1978
1979(define_expand "cstore<mode>4"
1980 [(set (match_operand:SI 0 "register_operand")
1981 (match_operator:SI 1 "fp_scc_comparison"
248710c4
KC
1982 [(match_operand:ANYF 2 "register_operand")
1983 (match_operand:ANYF 3 "register_operand")]))]
09cae750
PD
1984 "TARGET_HARD_FLOAT"
1985{
1986 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
1987 operands[3]);
1988 DONE;
1989})
1990
1991(define_insn "*cstore<ANYF:mode><X:mode>4"
248710c4
KC
1992 [(set (match_operand:X 0 "register_operand" "=r")
1993 (match_operator:X 1 "fp_native_comparison"
1994 [(match_operand:ANYF 2 "register_operand" " f")
1995 (match_operand:ANYF 3 "register_operand" " f")]))]
09cae750
PD
1996 "TARGET_HARD_FLOAT"
1997 "f%C1.<fmt>\t%0,%2,%3"
1998 [(set_attr "type" "fcmp")
1999 (set_attr "mode" "<UNITMODE>")])
2000
1fcbfb00
AW
2001(define_expand "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
2002 [(parallel [(set (match_operand:X 0 "register_operand")
2003 (unspec:X
2004 [(match_operand:ANYF 1 "register_operand")
2005 (match_operand:ANYF 2 "register_operand")]
2006 QUIET_COMPARISON))
2007 (clobber (match_scratch:X 3))])]
2008 "TARGET_HARD_FLOAT")
2009
2010(define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_default"
2011 [(set (match_operand:X 0 "register_operand" "=r")
09cae750 2012 (unspec:X
1fcbfb00
AW
2013 [(match_operand:ANYF 1 "register_operand" " f")
2014 (match_operand:ANYF 2 "register_operand" " f")]
2015 QUIET_COMPARISON))
09cae750 2016 (clobber (match_scratch:X 3 "=&r"))]
1fcbfb00 2017 "TARGET_HARD_FLOAT && ! HONOR_SNANS (<ANYF:MODE>mode)"
09cae750
PD
2018 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3"
2019 [(set_attr "type" "fcmp")
2020 (set_attr "mode" "<UNITMODE>")
2021 (set (attr "length") (const_int 12))])
2022
1fcbfb00
AW
2023(define_insn "*f<quiet_pattern>_quiet<ANYF:mode><X:mode>4_snan"
2024 [(set (match_operand:X 0 "register_operand" "=r")
2025 (unspec:X
2026 [(match_operand:ANYF 1 "register_operand" " f")
2027 (match_operand:ANYF 2 "register_operand" " f")]
2028 QUIET_COMPARISON))
2029 (clobber (match_scratch:X 3 "=&r"))]
2030 "TARGET_HARD_FLOAT && HONOR_SNANS (<ANYF:MODE>mode)"
2031 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3\n\tfeq.<fmt>\tzero,%1,%2"
2032 [(set_attr "type" "fcmp")
2033 (set_attr "mode" "<UNITMODE>")
2034 (set (attr "length") (const_int 16))])
2035
09cae750 2036(define_insn "*seq_zero_<X:mode><GPR:mode>"
248710c4
KC
2037 [(set (match_operand:GPR 0 "register_operand" "=r")
2038 (eq:GPR (match_operand:X 1 "register_operand" " r")
2039 (const_int 0)))]
09cae750
PD
2040 ""
2041 "seqz\t%0,%1"
2042 [(set_attr "type" "slt")
2043 (set_attr "mode" "<X:MODE>")])
2044
2045(define_insn "*sne_zero_<X:mode><GPR:mode>"
248710c4
KC
2046 [(set (match_operand:GPR 0 "register_operand" "=r")
2047 (ne:GPR (match_operand:X 1 "register_operand" " r")
2048 (const_int 0)))]
09cae750
PD
2049 ""
2050 "snez\t%0,%1"
2051 [(set_attr "type" "slt")
2052 (set_attr "mode" "<X:MODE>")])
2053
2054(define_insn "*sgt<u>_<X:mode><GPR:mode>"
248710c4
KC
2055 [(set (match_operand:GPR 0 "register_operand" "= r")
2056 (any_gt:GPR (match_operand:X 1 "register_operand" " r")
2057 (match_operand:X 2 "reg_or_0_operand" " rJ")))]
09cae750
PD
2058 ""
2059 "sgt<u>\t%0,%1,%z2"
2060 [(set_attr "type" "slt")
2061 (set_attr "mode" "<X:MODE>")])
2062
2063(define_insn "*sge<u>_<X:mode><GPR:mode>"
248710c4
KC
2064 [(set (match_operand:GPR 0 "register_operand" "=r")
2065 (any_ge:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
2066 (const_int 1)))]
2067 ""
0791ac18 2068 "slt%i2<u>\t%0,zero,%1"
09cae750 2069 [(set_attr "type" "slt")
7ef00402 2070 (set_attr "mode" "<X:MODE>")])
09cae750
PD
2071
2072(define_insn "*slt<u>_<X:mode><GPR:mode>"
248710c4
KC
2073 [(set (match_operand:GPR 0 "register_operand" "= r")
2074 (any_lt:GPR (match_operand:X 1 "register_operand" " r")
2075 (match_operand:X 2 "arith_operand" " rI")))]
09cae750 2076 ""
0791ac18 2077 "slt%i2<u>\t%0,%1,%2"
09cae750 2078 [(set_attr "type" "slt")
7ef00402 2079 (set_attr "mode" "<X:MODE>")])
09cae750
PD
2080
2081(define_insn "*sle<u>_<X:mode><GPR:mode>"
248710c4
KC
2082 [(set (match_operand:GPR 0 "register_operand" "=r")
2083 (any_le:GPR (match_operand:X 1 "register_operand" " r")
09cae750
PD
2084 (match_operand:X 2 "sle_operand" "")))]
2085 ""
2086{
2087 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
0791ac18 2088 return "slt%i2<u>\t%0,%1,%2";
09cae750
PD
2089}
2090 [(set_attr "type" "slt")
7ef00402 2091 (set_attr "mode" "<X:MODE>")])
09cae750
PD
2092
2093;;
2094;; ....................
2095;;
2096;; UNCONDITIONAL BRANCHES
2097;;
2098;; ....................
2099
2100;; Unconditional branches.
2101
2102(define_insn "jump"
2103 [(set (pc)
2104 (label_ref (match_operand 0 "" "")))]
2105 ""
2106 "j\t%l0"
2107 [(set_attr "type" "jump")
2108 (set_attr "mode" "none")])
2109
2110(define_expand "indirect_jump"
2111 [(set (pc) (match_operand 0 "register_operand"))]
2112 ""
2113{
2114 operands[0] = force_reg (Pmode, operands[0]);
2115 if (Pmode == SImode)
2116 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
2117 else
2118 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
2119 DONE;
2120})
2121
2122(define_insn "indirect_jump<mode>"
2123 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
2124 ""
2125 "jr\t%0"
2126 [(set_attr "type" "jump")
2127 (set_attr "mode" "none")])
2128
2129(define_expand "tablejump"
2130 [(set (pc) (match_operand 0 "register_operand" ""))
2131 (use (label_ref (match_operand 1 "" "")))]
2132 ""
2133{
2134 if (CASE_VECTOR_PC_RELATIVE)
2135 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
2136 gen_rtx_LABEL_REF (Pmode, operands[1]),
2137 NULL_RTX, 0, OPTAB_DIRECT);
2138
2139 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
2140 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
2141 else
2142 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
2143 DONE;
2144})
2145
2146(define_insn "tablejump<mode>"
2147 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
2148 (use (label_ref (match_operand 1 "" "")))]
2149 ""
2150 "jr\t%0"
2151 [(set_attr "type" "jump")
2152 (set_attr "mode" "none")])
2153
2154;;
2155;; ....................
2156;;
2157;; Function prologue/epilogue
2158;;
2159;; ....................
2160;;
2161
2162(define_expand "prologue"
2163 [(const_int 1)]
2164 ""
2165{
2166 riscv_expand_prologue ();
2167 DONE;
2168})
2169
2170;; Block any insns from being moved before this point, since the
2171;; profiling call to mcount can use various registers that aren't
2172;; saved or used to pass arguments.
2173
2174(define_insn "blockage"
2175 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
2176 ""
2177 ""
2178 [(set_attr "type" "ghost")
2179 (set_attr "mode" "none")])
2180
2181(define_expand "epilogue"
2182 [(const_int 2)]
2183 ""
2184{
fd1e52dc 2185 riscv_expand_epilogue (NORMAL_RETURN);
09cae750
PD
2186 DONE;
2187})
2188
2189(define_expand "sibcall_epilogue"
2190 [(const_int 2)]
2191 ""
2192{
fd1e52dc 2193 riscv_expand_epilogue (SIBCALL_RETURN);
09cae750
PD
2194 DONE;
2195})
2196
2197;; Trivial return. Make it look like a normal return insn as that
2198;; allows jump optimizations to work better.
2199
2200(define_expand "return"
2201 [(simple_return)]
2202 "riscv_can_use_return_insn ()"
2203 "")
2204
2205(define_insn "simple_return"
2206 [(simple_return)]
2207 ""
8cad5b14
KC
2208{
2209 return riscv_output_return ();
2210}
09cae750
PD
2211 [(set_attr "type" "jump")
2212 (set_attr "mode" "none")])
2213
2214;; Normal return.
2215
2216(define_insn "simple_return_internal"
2217 [(simple_return)
2218 (use (match_operand 0 "pmode_register_operand" ""))]
2219 ""
2220 "jr\t%0"
2221 [(set_attr "type" "jump")
2222 (set_attr "mode" "none")])
2223
2224;; This is used in compiling the unwind routines.
2225(define_expand "eh_return"
2226 [(use (match_operand 0 "general_operand"))]
2227 ""
2228{
2229 if (GET_MODE (operands[0]) != word_mode)
2230 operands[0] = convert_to_mode (word_mode, operands[0], 0);
2231 if (TARGET_64BIT)
2232 emit_insn (gen_eh_set_lr_di (operands[0]));
2233 else
2234 emit_insn (gen_eh_set_lr_si (operands[0]));
fd1e52dc
JW
2235
2236 emit_jump_insn (gen_eh_return_internal ());
2237 emit_barrier ();
09cae750
PD
2238 DONE;
2239})
2240
2241;; Clobber the return address on the stack. We can't expand this
2242;; until we know where it will be put in the stack frame.
2243
2244(define_insn "eh_set_lr_si"
2245 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2246 (clobber (match_scratch:SI 1 "=&r"))]
2247 "! TARGET_64BIT"
2248 "#")
2249
2250(define_insn "eh_set_lr_di"
2251 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
2252 (clobber (match_scratch:DI 1 "=&r"))]
2253 "TARGET_64BIT"
2254 "#")
2255
2256(define_split
2257 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
2258 (clobber (match_scratch 1))]
2259 "reload_completed"
2260 [(const_int 0)]
2261{
2262 riscv_set_return_address (operands[0], operands[1]);
2263 DONE;
2264})
2265
fd1e52dc
JW
2266(define_insn_and_split "eh_return_internal"
2267 [(eh_return)]
2268 ""
2269 "#"
2270 "epilogue_completed"
2271 [(const_int 0)]
2272 "riscv_expand_epilogue (EXCEPTION_RETURN); DONE;")
2273
09cae750
PD
2274;;
2275;; ....................
2276;;
2277;; FUNCTION CALLS
2278;;
2279;; ....................
2280
2281(define_expand "sibcall"
2282 [(parallel [(call (match_operand 0 "")
2283 (match_operand 1 ""))
2284 (use (match_operand 2 "")) ;; next_arg_reg
2285 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2286 ""
2287{
2288 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2289 emit_call_insn (gen_sibcall_internal (target, operands[1]));
2290 DONE;
2291})
2292
2293(define_insn "sibcall_internal"
2294 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
2295 (match_operand 1 "" ""))]
2296 "SIBLING_CALL_P (insn)"
2297 "@
2298 jr\t%0
2299 tail\t%0
2300 tail\t%0@plt"
2301 [(set_attr "type" "call")])
2302
2303(define_expand "sibcall_value"
2304 [(parallel [(set (match_operand 0 "")
2305 (call (match_operand 1 "")
2306 (match_operand 2 "")))
2307 (use (match_operand 3 ""))])] ;; next_arg_reg
2308 ""
2309{
2310 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2311 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
2312 DONE;
2313})
2314
2315(define_insn "sibcall_value_internal"
2316 [(set (match_operand 0 "" "")
2317 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
2318 (match_operand 2 "" "")))]
2319 "SIBLING_CALL_P (insn)"
2320 "@
2321 jr\t%1
2322 tail\t%1
2323 tail\t%1@plt"
2324 [(set_attr "type" "call")])
2325
2326(define_expand "call"
2327 [(parallel [(call (match_operand 0 "")
2328 (match_operand 1 ""))
2329 (use (match_operand 2 "")) ;; next_arg_reg
2330 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
2331 ""
2332{
2333 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
2334 emit_call_insn (gen_call_internal (target, operands[1]));
2335 DONE;
2336})
2337
2338(define_insn "call_internal"
2339 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
2340 (match_operand 1 "" ""))
2341 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2342 ""
2343 "@
2344 jalr\t%0
2345 call\t%0
2346 call\t%0@plt"
2347 [(set_attr "type" "call")])
2348
2349(define_expand "call_value"
2350 [(parallel [(set (match_operand 0 "")
2351 (call (match_operand 1 "")
2352 (match_operand 2 "")))
2353 (use (match_operand 3 ""))])] ;; next_arg_reg
2354 ""
2355{
2356 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
2357 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
2358 DONE;
2359})
2360
2361(define_insn "call_value_internal"
2362 [(set (match_operand 0 "" "")
2363 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
2364 (match_operand 2 "" "")))
2365 (clobber (reg:SI RETURN_ADDR_REGNUM))]
2366 ""
2367 "@
2368 jalr\t%1
2369 call\t%1
2370 call\t%1@plt"
2371 [(set_attr "type" "call")])
2372
2373;; Call subroutine returning any type.
2374
2375(define_expand "untyped_call"
2376 [(parallel [(call (match_operand 0 "")
2377 (const_int 0))
2378 (match_operand 1 "")
2379 (match_operand 2 "")])]
2380 ""
2381{
2382 int i;
2383
2384 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2385
2386 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2387 {
2388 rtx set = XVECEXP (operands[2], 0, i);
2389 riscv_emit_move (SET_DEST (set), SET_SRC (set));
2390 }
2391
2392 emit_insn (gen_blockage ());
2393 DONE;
2394})
2395
2396(define_insn "nop"
2397 [(const_int 0)]
2398 ""
2399 "nop"
2400 [(set_attr "type" "nop")
2401 (set_attr "mode" "none")])
2402
2403(define_insn "trap"
2404 [(trap_if (const_int 1) (const_int 0))]
2405 ""
2406 "ebreak")
2407
2408(define_insn "gpr_save"
2409 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_SAVE)
2410 (clobber (reg:SI T0_REGNUM))
2411 (clobber (reg:SI T1_REGNUM))]
2412 ""
2413 { return riscv_output_gpr_save (INTVAL (operands[0])); })
2414
2415(define_insn "gpr_restore"
2416 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2417 ""
2418 "tail\t__riscv_restore_%0")
2419
2420(define_insn "gpr_restore_return"
2421 [(return)
2422 (use (match_operand 0 "pmode_register_operand" ""))
2423 (const_int 0)]
2424 ""
2425 "")
2426
2427(define_insn "riscv_frflags"
2428 [(set (match_operand:SI 0 "register_operand" "=r")
2429 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
2430 "TARGET_HARD_FLOAT"
d0ebdd9f 2431 "frflags\t%0")
09cae750
PD
2432
2433(define_insn "riscv_fsflags"
2434 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2435 "TARGET_HARD_FLOAT"
d0ebdd9f
JW
2436 "fsflags\t%0")
2437
2438(define_insn "riscv_mret"
eb153f07
JW
2439 [(return)
2440 (unspec_volatile [(const_int 0)] UNSPECV_MRET)]
d0ebdd9f
JW
2441 ""
2442 "mret")
09cae750 2443
ec74725c 2444(define_insn "riscv_sret"
eb153f07
JW
2445 [(return)
2446 (unspec_volatile [(const_int 0)] UNSPECV_SRET)]
ec74725c
JW
2447 ""
2448 "sret")
2449
2450(define_insn "riscv_uret"
eb153f07
JW
2451 [(return)
2452 (unspec_volatile [(const_int 0)] UNSPECV_URET)]
ec74725c
JW
2453 ""
2454 "uret")
2455
09cae750
PD
2456(define_insn "stack_tie<mode>"
2457 [(set (mem:BLK (scratch))
2458 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
2459 (match_operand:X 1 "register_operand" "r")]
2460 UNSPEC_TIE))]
2461 ""
2462 ""
2463 [(set_attr "length" "0")]
2464)
2465
88108b27
AW
2466;; This fixes a failure with gcc.c-torture/execute/pr64242.c at -O2 for a
2467;; 32-bit target when using -mtune=sifive-7-series. The first sched pass
2468;; runs before register elimination, and we have a non-obvious dependency
2469;; between a use of the soft fp and a set of the hard fp. We fix this by
2470;; emitting a clobber using the hard fp between the two insns.
2471(define_expand "restore_stack_nonlocal"
2472 [(match_operand 0 "register_operand")
2473 (match_operand 1 "memory_operand")]
2474 ""
2475{
2476 emit_move_insn (operands[0], operands[1]);
2477 /* Prevent the following hard fp restore from being moved before the move
2478 insn above which uses a copy of the soft fp reg. */
2479 emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
2480 DONE;
2481})
2482
09cae750
PD
2483(include "sync.md")
2484(include "peephole.md")
2485(include "pic.md")
2486(include "generic.md")
88108b27 2487(include "sifive-7.md")