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