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