]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/riscv/riscv.md
re PR target/79038 (Improve PowerPC ISA 3.0 conversion between integers and hardware...
[thirdparty/gcc.git] / gcc / config / riscv / riscv.md
CommitLineData
09cae750
PD
1;; Machine description for RISC-V for GNU compiler.
2;; Copyright (C) 2011-2017 Free Software Foundation, Inc.
3;; Contributed by Andrew Waterman (andrew@sifive.com).
4;; Based on MIPS target for GNU compiler.
5
6;; This file is part of GCC.
7
8;; GCC is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation; either version 3, or (at your option)
11;; any later version.
12
13;; GCC is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with GCC; see the file COPYING3. If not see
20;; <http://www.gnu.org/licenses/>.
21
22(define_c_enum "unspec" [
23 ;; Override return address for exception handling.
24 UNSPEC_EH_RETURN
25
26 ;; Symbolic accesses. The order of this list must match that of
27 ;; enum riscv_symbol_type in riscv-protos.h.
28 UNSPEC_ADDRESS_FIRST
29 UNSPEC_PCREL
30 UNSPEC_LOAD_GOT
31 UNSPEC_TLS
32 UNSPEC_TLS_LE
33 UNSPEC_TLS_IE
34 UNSPEC_TLS_GD
35
36 ;; High part of PC-relative address.
37 UNSPEC_AUIPC
38
39 ;; Floating-point unspecs.
40 UNSPEC_FLT_QUIET
41 UNSPEC_FLE_QUIET
42 UNSPEC_COPYSIGN
43 UNSPEC_LRINT
44 UNSPEC_LROUND
45
46 ;; Stack tie
47 UNSPEC_TIE
48])
49
50(define_c_enum "unspecv" [
51 ;; Register save and restore.
52 UNSPECV_GPR_SAVE
53 UNSPECV_GPR_RESTORE
54
55 ;; Floating-point unspecs.
56 UNSPECV_FRFLAGS
57 UNSPECV_FSFLAGS
58
59 ;; Blockage and synchronization.
60 UNSPECV_BLOCKAGE
61 UNSPECV_FENCE
62 UNSPECV_FENCE_I
63])
64
65(define_constants
66 [(RETURN_ADDR_REGNUM 1)
67 (T0_REGNUM 5)
68 (T1_REGNUM 6)
69 (S0_REGNUM 8)
70 (S1_REGNUM 9)
71 (S2_REGNUM 18)
72])
73
74(include "predicates.md")
75(include "constraints.md")
76
77;; ....................
78;;
79;; Attributes
80;;
81;; ....................
82
83(define_attr "got" "unset,xgot_high,load"
84 (const_string "unset"))
85
86;; Classification of moves, extensions and truncations. Most values
87;; are as for "type" (see below) but there are also the following
88;; move-specific values:
89;;
90;; andi a single ANDI instruction
91;; shift_shift a shift left followed by a shift right
92;;
93;; This attribute is used to determine the instruction's length and
94;; scheduling type. For doubleword moves, the attribute always describes
95;; the split instructions; in some cases, it is more appropriate for the
96;; scheduling type to be "multi" instead.
97(define_attr "move_type"
98 "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove,
99 const,logical,arith,andi,shift_shift"
100 (const_string "unknown"))
101
102;; Main data type used by the insn
103(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF"
104 (const_string "unknown"))
105
106;; True if the main data type is twice the size of a word.
107(define_attr "dword_mode" "no,yes"
108 (cond [(and (eq_attr "mode" "DI,DF")
109 (eq (symbol_ref "TARGET_64BIT") (const_int 0)))
110 (const_string "yes")
111
112 (and (eq_attr "mode" "TI,TF")
113 (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
114 (const_string "yes")]
115 (const_string "no")))
116
117;; Classification of each insn.
118;; branch conditional branch
119;; jump unconditional jump
120;; call unconditional call
121;; load load instruction(s)
122;; fpload floating point load
123;; store store instruction(s)
124;; fpstore floating point store
125;; mtc transfer to coprocessor
126;; mfc transfer from coprocessor
127;; const load constant
128;; arith integer arithmetic instructions
129;; logical integer logical instructions
130;; shift integer shift instructions
131;; slt set less than instructions
132;; imul integer multiply
133;; idiv integer divide
134;; move integer register move (addi rd, rs1, 0)
135;; fmove floating point register move
136;; fadd floating point add/subtract
137;; fmul floating point multiply
138;; fmadd floating point multiply-add
139;; fdiv floating point divide
140;; fcmp floating point compare
141;; fcvt floating point convert
142;; fsqrt floating point square root
143;; multi multiword sequence (or user asm statements)
144;; nop no operation
145;; ghost an instruction that produces no real code
146(define_attr "type"
147 "unknown,branch,jump,call,load,fpload,store,fpstore,
148 mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
149 fmadd,fdiv,fcmp,fcvt,fsqrt,multi,nop,ghost"
150 (cond [(eq_attr "got" "load") (const_string "load")
151
152 ;; If a doubleword move uses these expensive instructions,
153 ;; it is usually better to schedule them in the same way
154 ;; as the singleword form, rather than as "multi".
155 (eq_attr "move_type" "load") (const_string "load")
156 (eq_attr "move_type" "fpload") (const_string "fpload")
157 (eq_attr "move_type" "store") (const_string "store")
158 (eq_attr "move_type" "fpstore") (const_string "fpstore")
159 (eq_attr "move_type" "mtc") (const_string "mtc")
160 (eq_attr "move_type" "mfc") (const_string "mfc")
161
162 ;; These types of move are always single insns.
163 (eq_attr "move_type" "fmove") (const_string "fmove")
164 (eq_attr "move_type" "arith") (const_string "arith")
165 (eq_attr "move_type" "logical") (const_string "logical")
166 (eq_attr "move_type" "andi") (const_string "logical")
167
168 ;; These types of move are always split.
169 (eq_attr "move_type" "shift_shift")
170 (const_string "multi")
171
172 ;; These types of move are split for doubleword modes only.
173 (and (eq_attr "move_type" "move,const")
174 (eq_attr "dword_mode" "yes"))
175 (const_string "multi")
176 (eq_attr "move_type" "move") (const_string "move")
177 (eq_attr "move_type" "const") (const_string "const")]
178 (const_string "unknown")))
179
180;; Length of instruction in bytes.
181(define_attr "length" ""
182 (cond [
183 ;; Branches further than +/- 4 KiB require two instructions.
184 (eq_attr "type" "branch")
185 (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4088))
186 (le (minus (pc) (match_dup 0)) (const_int 4092)))
187 (const_int 4)
188 (const_int 8))
189
190 ;; Conservatively assume calls take two instructions (AUIPC + JALR).
191 ;; The linker will opportunistically relax the sequence to JAL.
192 (eq_attr "type" "call") (const_int 8)
193
194 ;; "Ghost" instructions occupy no space.
195 (eq_attr "type" "ghost") (const_int 0)
196
197 (eq_attr "got" "load") (const_int 8)
198
199 (eq_attr "type" "fcmp") (const_int 8)
200
201 ;; SHIFT_SHIFTs are decomposed into two separate instructions.
202 (eq_attr "move_type" "shift_shift")
203 (const_int 8)
204
205 ;; Check for doubleword moves that are decomposed into two
206 ;; instructions.
207 (and (eq_attr "move_type" "mtc,mfc,move")
208 (eq_attr "dword_mode" "yes"))
209 (const_int 8)
210
211 ;; Doubleword CONST{,N} moves are split into two word
212 ;; CONST{,N} moves.
213 (and (eq_attr "move_type" "const")
214 (eq_attr "dword_mode" "yes"))
215 (symbol_ref "riscv_split_const_insns (operands[1]) * 4")
216
217 ;; Otherwise, constants, loads and stores are handled by external
218 ;; routines.
219 (eq_attr "move_type" "load,fpload")
220 (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4")
221 (eq_attr "move_type" "store,fpstore")
222 (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4")
223 ] (const_int 4)))
224
225;; Is copying of this instruction disallowed?
226(define_attr "cannot_copy" "no,yes" (const_string "no"))
227
228;; Describe a user's asm statement.
229(define_asm_attributes
230 [(set_attr "type" "multi")])
231
232;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated
233;; from the same template.
234(define_mode_iterator GPR [SI (DI "TARGET_64BIT")])
235
236;; This mode iterator allows :P to be used for patterns that operate on
237;; pointer-sized quantities. Exactly one of the two alternatives will match.
238(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
239
240;; Likewise, but for XLEN-sized quantities.
241(define_mode_iterator X [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")])
242
243;; Branches operate on XLEN-sized quantities, but for RV64 we accept
244;; QImode values so we can force zero-extension.
245(define_mode_iterator BR [(QI "TARGET_64BIT") SI (DI "TARGET_64BIT")])
246
247;; 32-bit moves for which we provide move patterns.
248(define_mode_iterator MOVE32 [SI])
249
250;; 64-bit modes for which we provide move patterns.
251(define_mode_iterator MOVE64 [DI DF])
252
253;; Iterator for sub-32-bit integer modes.
254(define_mode_iterator SHORT [QI HI])
255
256;; Iterator for HImode constant generation.
257(define_mode_iterator HISI [HI SI])
258
259;; Iterator for QImode extension patterns.
260(define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")])
261
262;; Iterator for hardware integer modes narrower than XLEN.
263(define_mode_iterator SUBX [QI HI (SI "TARGET_64BIT")])
264
265;; Iterator for hardware-supported integer modes.
266(define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
267
268;; Iterator for hardware-supported floating-point modes.
269(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
270 (DF "TARGET_DOUBLE_FLOAT")])
271
272;; This attribute gives the length suffix for a sign- or zero-extension
273;; instruction.
274(define_mode_attr size [(QI "b") (HI "h")])
275
276;; Mode attributes for loads.
277(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
278
279;; Instruction names for stores.
280(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
281
282;; This attribute gives the best constraint to use for registers of
283;; a given mode.
284(define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
285
286;; This attribute gives the format suffix for floating-point operations.
287(define_mode_attr fmt [(SF "s") (DF "d")])
288
289;; This attribute gives the integer suffix for floating-point conversions.
290(define_mode_attr ifmt [(SI "w") (DI "l")])
291
292;; This attribute gives the format suffix for atomic memory operations.
293(define_mode_attr amo [(SI "w") (DI "d")])
294
295;; This attribute gives the upper-case mode name for one unit of a
296;; floating-point mode.
297(define_mode_attr UNITMODE [(SF "SF") (DF "DF")])
298
299;; This attribute gives the integer mode that has half the size of
300;; the controlling mode.
301(define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")])
302
303;; Iterator and attributes for floating-point rounding instructions.
304(define_int_iterator RINT [UNSPEC_LRINT UNSPEC_LROUND])
305(define_int_attr rint_pattern [(UNSPEC_LRINT "rint") (UNSPEC_LROUND "round")])
306(define_int_attr rint_rm [(UNSPEC_LRINT "dyn") (UNSPEC_LROUND "rmm")])
307
308;; Iterator and attributes for quiet comparisons.
309(define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET])
310(define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")])
311
312;; This code iterator allows signed and unsigned widening multiplications
313;; to use the same template.
314(define_code_iterator any_extend [sign_extend zero_extend])
315
316;; This code iterator allows the two right shift instructions to be
317;; generated from the same template.
318(define_code_iterator any_shiftrt [ashiftrt lshiftrt])
319
320;; This code iterator allows the three shift instructions to be generated
321;; from the same template.
322(define_code_iterator any_shift [ashift ashiftrt lshiftrt])
323
324;; This code iterator allows the three bitwise instructions to be generated
325;; from the same template.
326(define_code_iterator any_bitwise [and ior xor])
327
328;; This code iterator allows unsigned and signed division to be generated
329;; from the same template.
330(define_code_iterator any_div [div udiv mod umod])
331
332;; This code iterator allows unsigned and signed modulus to be generated
333;; from the same template.
334(define_code_iterator any_mod [mod umod])
335
336;; These code iterators allow the signed and unsigned scc operations to use
337;; the same template.
338(define_code_iterator any_gt [gt gtu])
339(define_code_iterator any_ge [ge geu])
340(define_code_iterator any_lt [lt ltu])
341(define_code_iterator any_le [le leu])
342
343;; <u> expands to an empty string when doing a signed operation and
344;; "u" when doing an unsigned operation.
345(define_code_attr u [(sign_extend "") (zero_extend "u")
346 (gt "") (gtu "u")
347 (ge "") (geu "u")
348 (lt "") (ltu "u")
349 (le "") (leu "u")])
350
351;; <su> is like <u>, but the signed form expands to "s" rather than "".
352(define_code_attr su [(sign_extend "s") (zero_extend "u")])
353
354;; <optab> expands to the name of the optab for a particular code.
355(define_code_attr optab [(ashift "ashl")
356 (ashiftrt "ashr")
357 (lshiftrt "lshr")
358 (div "div")
359 (mod "mod")
360 (udiv "udiv")
361 (umod "umod")
362 (ge "ge")
363 (le "le")
364 (gt "gt")
365 (lt "lt")
366 (ior "ior")
367 (xor "xor")
368 (and "and")
369 (plus "add")
370 (minus "sub")])
371
372;; <insn> expands to the name of the insn that implements a particular code.
373(define_code_attr insn [(ashift "sll")
374 (ashiftrt "sra")
375 (lshiftrt "srl")
376 (div "div")
377 (mod "rem")
378 (udiv "divu")
379 (umod "remu")
380 (ior "or")
381 (xor "xor")
382 (and "and")
383 (plus "add")
384 (minus "sub")])
385
386;; Ghost instructions produce no real code and introduce no hazards.
387;; They exist purely to express an effect on dataflow.
388(define_insn_reservation "ghost" 0
389 (eq_attr "type" "ghost")
390 "nothing")
391
392;;
393;; ....................
394;;
395;; ADDITION
396;;
397;; ....................
398;;
399
400(define_insn "add<mode>3"
401 [(set (match_operand:ANYF 0 "register_operand" "=f")
402 (plus:ANYF (match_operand:ANYF 1 "register_operand" "f")
403 (match_operand:ANYF 2 "register_operand" "f")))]
404 "TARGET_HARD_FLOAT"
405 "fadd.<fmt>\t%0,%1,%2"
406 [(set_attr "type" "fadd")
407 (set_attr "mode" "<UNITMODE>")])
408
409(define_insn "addsi3"
410 [(set (match_operand:SI 0 "register_operand" "=r,r")
411 (plus:SI (match_operand:SI 1 "register_operand" "r,r")
412 (match_operand:SI 2 "arith_operand" "r,I")))]
413 ""
414 { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; }
415 [(set_attr "type" "arith")
416 (set_attr "mode" "SI")])
417
418(define_insn "adddi3"
419 [(set (match_operand:DI 0 "register_operand" "=r,r")
420 (plus:DI (match_operand:DI 1 "register_operand" "r,r")
421 (match_operand:DI 2 "arith_operand" "r,I")))]
422 "TARGET_64BIT"
423 "add\t%0,%1,%2"
424 [(set_attr "type" "arith")
425 (set_attr "mode" "DI")])
426
427(define_insn "*addsi3_extended"
428 [(set (match_operand:DI 0 "register_operand" "=r,r")
429 (sign_extend:DI
430 (plus:SI (match_operand:SI 1 "register_operand" "r,r")
431 (match_operand:SI 2 "arith_operand" "r,I"))))]
432 "TARGET_64BIT"
433 "addw\t%0,%1,%2"
434 [(set_attr "type" "arith")
435 (set_attr "mode" "SI")])
436
437(define_insn "*addsi3_extended2"
438 [(set (match_operand:DI 0 "register_operand" "=r,r")
439 (sign_extend:DI
440 (subreg:SI (plus:DI (match_operand:DI 1 "register_operand" "r,r")
441 (match_operand:DI 2 "arith_operand" "r,I"))
442 0)))]
443 "TARGET_64BIT"
444 "addw\t%0,%1,%2"
445 [(set_attr "type" "arith")
446 (set_attr "mode" "SI")])
447
448;;
449;; ....................
450;;
451;; SUBTRACTION
452;;
453;; ....................
454;;
455
456(define_insn "sub<mode>3"
457 [(set (match_operand:ANYF 0 "register_operand" "=f")
458 (minus:ANYF (match_operand:ANYF 1 "register_operand" "f")
459 (match_operand:ANYF 2 "register_operand" "f")))]
460 "TARGET_HARD_FLOAT"
461 "fsub.<fmt>\t%0,%1,%2"
462 [(set_attr "type" "fadd")
463 (set_attr "mode" "<UNITMODE>")])
464
465(define_insn "subdi3"
466 [(set (match_operand:DI 0 "register_operand" "=r")
467 (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
468 (match_operand:DI 2 "register_operand" "r")))]
469 "TARGET_64BIT"
470 "sub\t%0,%z1,%2"
471 [(set_attr "type" "arith")
472 (set_attr "mode" "DI")])
473
474(define_insn "subsi3"
475 [(set (match_operand:SI 0 "register_operand" "=r")
476 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
477 (match_operand:SI 2 "register_operand" "r")))]
478 ""
479 { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; }
480 [(set_attr "type" "arith")
481 (set_attr "mode" "SI")])
482
483(define_insn "*subsi3_extended"
484 [(set (match_operand:DI 0 "register_operand" "=r")
485 (sign_extend:DI
486 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
487 (match_operand:SI 2 "register_operand" "r"))))]
488 "TARGET_64BIT"
489 "subw\t%0,%z1,%2"
490 [(set_attr "type" "arith")
491 (set_attr "mode" "SI")])
492
493(define_insn "*subsi3_extended2"
494 [(set (match_operand:DI 0 "register_operand" "=r")
495 (sign_extend:DI
496 (subreg:SI (minus:DI (match_operand:DI 1 "reg_or_0_operand" "r")
497 (match_operand:DI 2 "register_operand" "r"))
498 0)))]
499 "TARGET_64BIT"
500 "subw\t%0,%z1,%2"
501 [(set_attr "type" "arith")
502 (set_attr "mode" "SI")])
503
504;;
505;; ....................
506;;
507;; MULTIPLICATION
508;;
509;; ....................
510;;
511
512(define_insn "mul<mode>3"
513 [(set (match_operand:ANYF 0 "register_operand" "=f")
514 (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
515 (match_operand:ANYF 2 "register_operand" "f")))]
516 "TARGET_HARD_FLOAT"
517 "fmul.<fmt>\t%0,%1,%2"
518 [(set_attr "type" "fmul")
519 (set_attr "mode" "<UNITMODE>")])
520
521(define_insn "mulsi3"
522 [(set (match_operand:SI 0 "register_operand" "=r")
523 (mult:SI (match_operand:SI 1 "register_operand" "r")
524 (match_operand:SI 2 "register_operand" "r")))]
525 "TARGET_MUL"
526 { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; }
527 [(set_attr "type" "imul")
528 (set_attr "mode" "SI")])
529
530(define_insn "muldi3"
531 [(set (match_operand:DI 0 "register_operand" "=r")
532 (mult:DI (match_operand:DI 1 "register_operand" "r")
533 (match_operand:DI 2 "register_operand" "r")))]
534 "TARGET_MUL && TARGET_64BIT"
535 "mul\t%0,%1,%2"
536 [(set_attr "type" "imul")
537 (set_attr "mode" "DI")])
538
539(define_insn "*mulsi3_extended"
540 [(set (match_operand:DI 0 "register_operand" "=r")
541 (sign_extend:DI
542 (mult:SI (match_operand:SI 1 "register_operand" "r")
543 (match_operand:SI 2 "register_operand" "r"))))]
544 "TARGET_MUL && TARGET_64BIT"
545 "mulw\t%0,%1,%2"
546 [(set_attr "type" "imul")
547 (set_attr "mode" "SI")])
548
549(define_insn "*mulsi3_extended2"
550 [(set (match_operand:DI 0 "register_operand" "=r")
551 (sign_extend:DI
552 (subreg:SI (mult:DI (match_operand:DI 1 "register_operand" "r")
553 (match_operand:DI 2 "register_operand" "r"))
554 0)))]
555 "TARGET_MUL && TARGET_64BIT"
556 "mulw\t%0,%1,%2"
557 [(set_attr "type" "imul")
558 (set_attr "mode" "SI")])
559
560;;
561;; ........................
562;;
563;; MULTIPLICATION HIGH-PART
564;;
565;; ........................
566;;
567
568
569(define_expand "<u>mulditi3"
570 [(set (match_operand:TI 0 "register_operand")
571 (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
572 (any_extend:TI (match_operand:DI 2 "register_operand"))))]
573 "TARGET_MUL && TARGET_64BIT"
574{
575 rtx low = gen_reg_rtx (DImode);
576 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
577
578 rtx high = gen_reg_rtx (DImode);
579 emit_insn (gen_<u>muldi3_highpart (high, operands[1], operands[2]));
580
581 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
582 emit_move_insn (gen_highpart (DImode, operands[0]), high);
583 DONE;
584})
585
586(define_insn "<u>muldi3_highpart"
587 [(set (match_operand:DI 0 "register_operand" "=r")
588 (truncate:DI
589 (lshiftrt:TI
590 (mult:TI (any_extend:TI
591 (match_operand:DI 1 "register_operand" "r"))
592 (any_extend:TI
593 (match_operand:DI 2 "register_operand" "r")))
594 (const_int 64))))]
595 "TARGET_MUL && TARGET_64BIT"
596 "mulh<u>\t%0,%1,%2"
597 [(set_attr "type" "imul")
598 (set_attr "mode" "DI")])
599
600(define_expand "usmulditi3"
601 [(set (match_operand:TI 0 "register_operand")
602 (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand"))
603 (sign_extend:TI (match_operand:DI 2 "register_operand"))))]
604 "TARGET_MUL && TARGET_64BIT"
605{
606 rtx low = gen_reg_rtx (DImode);
607 emit_insn (gen_muldi3 (low, operands[1], operands[2]));
608
609 rtx high = gen_reg_rtx (DImode);
610 emit_insn (gen_usmuldi3_highpart (high, operands[1], operands[2]));
611
612 emit_move_insn (gen_lowpart (DImode, operands[0]), low);
613 emit_move_insn (gen_highpart (DImode, operands[0]), high);
614 DONE;
615})
616
617(define_insn "usmuldi3_highpart"
618 [(set (match_operand:DI 0 "register_operand" "=r")
619 (truncate:DI
620 (lshiftrt:TI
621 (mult:TI (zero_extend:TI
622 (match_operand:DI 1 "register_operand" "r"))
623 (sign_extend:TI
624 (match_operand:DI 2 "register_operand" "r")))
625 (const_int 64))))]
626 "TARGET_MUL && TARGET_64BIT"
627 "mulhsu\t%0,%2,%1"
628 [(set_attr "type" "imul")
629 (set_attr "mode" "DI")])
630
631(define_expand "<u>mulsidi3"
632 [(set (match_operand:DI 0 "register_operand" "=r")
633 (mult:DI (any_extend:DI
634 (match_operand:SI 1 "register_operand" "r"))
635 (any_extend:DI
636 (match_operand:SI 2 "register_operand" "r"))))]
637 "TARGET_MUL && !TARGET_64BIT"
638{
639 rtx temp = gen_reg_rtx (SImode);
640 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
641 emit_insn (gen_<u>mulsi3_highpart (riscv_subword (operands[0], true),
642 operands[1], operands[2]));
643 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
644 DONE;
645})
646
647(define_insn "<u>mulsi3_highpart"
648 [(set (match_operand:SI 0 "register_operand" "=r")
649 (truncate:SI
650 (lshiftrt:DI
651 (mult:DI (any_extend:DI
652 (match_operand:SI 1 "register_operand" "r"))
653 (any_extend:DI
654 (match_operand:SI 2 "register_operand" "r")))
655 (const_int 32))))]
656 "TARGET_MUL && !TARGET_64BIT"
657 "mulh<u>\t%0,%1,%2"
658 [(set_attr "type" "imul")
659 (set_attr "mode" "SI")])
660
661
662(define_expand "usmulsidi3"
663 [(set (match_operand:DI 0 "register_operand" "=r")
664 (mult:DI (zero_extend:DI
665 (match_operand:SI 1 "register_operand" "r"))
666 (sign_extend:DI
667 (match_operand:SI 2 "register_operand" "r"))))]
668 "TARGET_MUL && !TARGET_64BIT"
669{
670 rtx temp = gen_reg_rtx (SImode);
671 emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
672 emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true),
673 operands[1], operands[2]));
674 emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
675 DONE;
676})
677
678(define_insn "usmulsi3_highpart"
679 [(set (match_operand:SI 0 "register_operand" "=r")
680 (truncate:SI
681 (lshiftrt:DI
682 (mult:DI (zero_extend:DI
683 (match_operand:SI 1 "register_operand" "r"))
684 (sign_extend:DI
685 (match_operand:SI 2 "register_operand" "r")))
686 (const_int 32))))]
687 "TARGET_MUL && !TARGET_64BIT"
688 "mulhsu\t%0,%2,%1"
689 [(set_attr "type" "imul")
690 (set_attr "mode" "SI")])
691
692;;
693;; ....................
694;;
695;; DIVISION and REMAINDER
696;;
697;; ....................
698;;
699
700(define_insn "<optab>si3"
701 [(set (match_operand:SI 0 "register_operand" "=r")
702 (any_div:SI (match_operand:SI 1 "register_operand" "r")
703 (match_operand:SI 2 "register_operand" "r")))]
704 "TARGET_DIV"
705 { return TARGET_64BIT ? "<insn>w\t%0,%1,%2" : "<insn>\t%0,%1,%2"; }
706 [(set_attr "type" "idiv")
707 (set_attr "mode" "SI")])
708
709(define_insn "<optab>di3"
710 [(set (match_operand:DI 0 "register_operand" "=r")
711 (any_div:DI (match_operand:DI 1 "register_operand" "r")
712 (match_operand:DI 2 "register_operand" "r")))]
713 "TARGET_DIV && TARGET_64BIT"
714 "<insn>\t%0,%1,%2"
715 [(set_attr "type" "idiv")
716 (set_attr "mode" "DI")])
717
718(define_insn "*<optab>si3_extended"
719 [(set (match_operand:DI 0 "register_operand" "=r")
720 (sign_extend:DI
721 (any_div:SI (match_operand:SI 1 "register_operand" "r")
722 (match_operand:SI 2 "register_operand" "r"))))]
723 "TARGET_DIV && TARGET_64BIT"
724 "<insn>w\t%0,%1,%2"
725 [(set_attr "type" "idiv")
726 (set_attr "mode" "DI")])
727
728(define_insn "div<mode>3"
729 [(set (match_operand:ANYF 0 "register_operand" "=f")
730 (div:ANYF (match_operand:ANYF 1 "register_operand" "f")
731 (match_operand:ANYF 2 "register_operand" "f")))]
732 "TARGET_HARD_FLOAT && TARGET_FDIV"
733 "fdiv.<fmt>\t%0,%1,%2"
734 [(set_attr "type" "fdiv")
735 (set_attr "mode" "<UNITMODE>")])
736
737;;
738;; ....................
739;;
740;; SQUARE ROOT
741;;
742;; ....................
743
744(define_insn "sqrt<mode>2"
745 [(set (match_operand:ANYF 0 "register_operand" "=f")
746 (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
747 "TARGET_HARD_FLOAT && TARGET_FDIV"
748{
749 return "fsqrt.<fmt>\t%0,%1";
750}
751 [(set_attr "type" "fsqrt")
752 (set_attr "mode" "<UNITMODE>")])
753
754;; Floating point multiply accumulate instructions.
755
756;; a * b + c
757(define_insn "fma<mode>4"
758 [(set (match_operand:ANYF 0 "register_operand" "=f")
759 (fma:ANYF
760 (match_operand:ANYF 1 "register_operand" "f")
761 (match_operand:ANYF 2 "register_operand" "f")
762 (match_operand:ANYF 3 "register_operand" "f")))]
763 "TARGET_HARD_FLOAT"
764 "fmadd.<fmt>\t%0,%1,%2,%3"
765 [(set_attr "type" "fmadd")
766 (set_attr "mode" "<UNITMODE>")])
767
768;; a * b - c
769(define_insn "fms<mode>4"
770 [(set (match_operand:ANYF 0 "register_operand" "=f")
771 (fma:ANYF
772 (match_operand:ANYF 1 "register_operand" "f")
773 (match_operand:ANYF 2 "register_operand" "f")
774 (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))]
775 "TARGET_HARD_FLOAT"
776 "fmsub.<fmt>\t%0,%1,%2,%3"
777 [(set_attr "type" "fmadd")
778 (set_attr "mode" "<UNITMODE>")])
779
780;; -a * b - c
781(define_insn "fnms<mode>4"
782 [(set (match_operand:ANYF 0 "register_operand" "=f")
783 (fma:ANYF
784 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
785 (match_operand:ANYF 2 "register_operand" "f")
786 (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))]
787 "TARGET_HARD_FLOAT"
788 "fnmadd.<fmt>\t%0,%1,%2,%3"
789 [(set_attr "type" "fmadd")
790 (set_attr "mode" "<UNITMODE>")])
791
792;; -a * b + c
793(define_insn "fnma<mode>4"
794 [(set (match_operand:ANYF 0 "register_operand" "=f")
795 (fma:ANYF
796 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
797 (match_operand:ANYF 2 "register_operand" "f")
798 (match_operand:ANYF 3 "register_operand" "f")))]
799 "TARGET_HARD_FLOAT"
800 "fnmsub.<fmt>\t%0,%1,%2,%3"
801 [(set_attr "type" "fmadd")
802 (set_attr "mode" "<UNITMODE>")])
803
804;; -(-a * b - c), modulo signed zeros
805(define_insn "*fma<mode>4"
806 [(set (match_operand:ANYF 0 "register_operand" "=f")
807 (neg:ANYF
808 (fma:ANYF
809 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
810 (match_operand:ANYF 2 "register_operand" "f")
811 (neg:ANYF (match_operand:ANYF 3 "register_operand" "f")))))]
812 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
813 "fmadd.<fmt>\t%0,%1,%2,%3"
814 [(set_attr "type" "fmadd")
815 (set_attr "mode" "<UNITMODE>")])
816
817;; -(-a * b + c), modulo signed zeros
818(define_insn "*fms<mode>4"
819 [(set (match_operand:ANYF 0 "register_operand" "=f")
820 (neg:ANYF
821 (fma:ANYF
822 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
823 (match_operand:ANYF 2 "register_operand" "f")
824 (match_operand:ANYF 3 "register_operand" "f"))))]
825 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
826 "fmsub.<fmt>\t%0,%1,%2,%3"
827 [(set_attr "type" "fmadd")
828 (set_attr "mode" "<UNITMODE>")])
829
830;; -(a * b + c), modulo signed zeros
831(define_insn "*fnms<mode>4"
832 [(set (match_operand:ANYF 0 "register_operand" "=f")
833 (neg:ANYF
834 (fma:ANYF
835 (match_operand:ANYF 1 "register_operand" "f")
836 (match_operand:ANYF 2 "register_operand" "f")
837 (match_operand:ANYF 3 "register_operand" "f"))))]
838 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
839 "fnmadd.<fmt>\t%0,%1,%2,%3"
840 [(set_attr "type" "fmadd")
841 (set_attr "mode" "<UNITMODE>")])
842
843;; -(a * b - c), modulo signed zeros
844(define_insn "*fnma<mode>4"
845 [(set (match_operand:ANYF 0 "register_operand" "=f")
846 (neg:ANYF
847 (fma:ANYF
848 (match_operand:ANYF 1 "register_operand" "f")
849 (match_operand:ANYF 2 "register_operand" "f")
850 (neg:ANYF (match_operand:ANYF 3 "register_operand" "f")))))]
851 "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
852 "fnmsub.<fmt>\t%0,%1,%2,%3"
853 [(set_attr "type" "fmadd")
854 (set_attr "mode" "<UNITMODE>")])
855
856;;
857;; ....................
858;;
859;; SIGN INJECTION
860;;
861;; ....................
862
863(define_insn "abs<mode>2"
864 [(set (match_operand:ANYF 0 "register_operand" "=f")
865 (abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
866 "TARGET_HARD_FLOAT"
867 "fabs.<fmt>\t%0,%1"
868 [(set_attr "type" "fmove")
869 (set_attr "mode" "<UNITMODE>")])
870
871(define_insn "copysign<mode>3"
872 [(set (match_operand:ANYF 0 "register_operand" "=f")
873 (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")
874 (match_operand:ANYF 2 "register_operand" "f")]
875 UNSPEC_COPYSIGN))]
876 "TARGET_HARD_FLOAT"
877 "fsgnj.<fmt>\t%0,%1,%2"
878 [(set_attr "type" "fmove")
879 (set_attr "mode" "<UNITMODE>")])
880
881(define_insn "neg<mode>2"
882 [(set (match_operand:ANYF 0 "register_operand" "=f")
883 (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
884 "TARGET_HARD_FLOAT"
885 "fneg.<fmt>\t%0,%1"
886 [(set_attr "type" "fmove")
887 (set_attr "mode" "<UNITMODE>")])
888
889;;
890;; ....................
891;;
892;; MIN/MAX
893;;
894;; ....................
895
896(define_insn "smin<mode>3"
897 [(set (match_operand:ANYF 0 "register_operand" "=f")
898 (smin:ANYF (match_operand:ANYF 1 "register_operand" "f")
899 (match_operand:ANYF 2 "register_operand" "f")))]
900 "TARGET_HARD_FLOAT"
901 "fmin.<fmt>\t%0,%1,%2"
902 [(set_attr "type" "fmove")
903 (set_attr "mode" "<UNITMODE>")])
904
905(define_insn "smax<mode>3"
906 [(set (match_operand:ANYF 0 "register_operand" "=f")
907 (smax:ANYF (match_operand:ANYF 1 "register_operand" "f")
908 (match_operand:ANYF 2 "register_operand" "f")))]
909 "TARGET_HARD_FLOAT"
910 "fmax.<fmt>\t%0,%1,%2"
911 [(set_attr "type" "fmove")
912 (set_attr "mode" "<UNITMODE>")])
913
914;;
915;; ....................
916;;
917;; LOGICAL
918;;
919;; ....................
920;;
921
922;; For RV64, we don't expose the SImode operations to the rtl expanders,
923;; but SImode versions exist for combine.
924
925(define_insn "<optab><mode>3"
926 [(set (match_operand:X 0 "register_operand" "=r,r")
927 (any_bitwise:X (match_operand:X 1 "register_operand" "%r,r")
928 (match_operand:X 2 "arith_operand" "r,I")))]
929 ""
930 "<insn>\t%0,%1,%2"
931 [(set_attr "type" "logical")
932 (set_attr "mode" "<MODE>")])
933
934(define_insn "*<optab>si3_internal"
935 [(set (match_operand:SI 0 "register_operand" "=r,r")
936 (any_bitwise:SI (match_operand:SI 1 "register_operand" "%r,r")
937 (match_operand:SI 2 "arith_operand" "r,I")))]
938 "TARGET_64BIT"
939 "<insn>\t%0,%1,%2"
940 [(set_attr "type" "logical")
941 (set_attr "mode" "SI")])
942
943(define_insn "one_cmpl<mode>2"
944 [(set (match_operand:X 0 "register_operand" "=r")
945 (not:X (match_operand:X 1 "register_operand" "r")))]
946 ""
947 "not\t%0,%1"
948 [(set_attr "type" "logical")
949 (set_attr "mode" "<MODE>")])
950
951(define_insn "*one_cmplsi2_internal"
952 [(set (match_operand:SI 0 "register_operand" "=r")
953 (not:SI (match_operand:SI 1 "register_operand" "r")))]
954 "TARGET_64BIT"
955 "not\t%0,%1"
956 [(set_attr "type" "logical")
957 (set_attr "mode" "SI")])
958
959;;
960;; ....................
961;;
962;; TRUNCATION
963;;
964;; ....................
965
966(define_insn "truncdfsf2"
967 [(set (match_operand:SF 0 "register_operand" "=f")
968 (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
969 "TARGET_DOUBLE_FLOAT"
970 "fcvt.s.d\t%0,%1"
971 [(set_attr "type" "fcvt")
972 (set_attr "mode" "SF")])
973
974;;
975;; ....................
976;;
977;; ZERO EXTENSION
978;;
979;; ....................
980
981;; Extension insns.
982
983(define_insn_and_split "zero_extendsidi2"
984 [(set (match_operand:DI 0 "register_operand" "=r,r")
985 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
986 "TARGET_64BIT"
987 "@
988 #
989 lwu\t%0,%1"
990 "&& reload_completed && REG_P (operands[1])"
991 [(set (match_dup 0)
992 (ashift:DI (match_dup 1) (const_int 32)))
993 (set (match_dup 0)
994 (lshiftrt:DI (match_dup 0) (const_int 32)))]
995 { operands[1] = gen_lowpart (DImode, operands[1]); }
996 [(set_attr "move_type" "shift_shift,load")
997 (set_attr "mode" "DI")])
998
999(define_insn_and_split "zero_extendhi<GPR:mode>2"
1000 [(set (match_operand:GPR 0 "register_operand" "=r,r")
1001 (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1002 ""
1003 "@
1004 #
1005 lhu\t%0,%1"
1006 "&& reload_completed && REG_P (operands[1])"
1007 [(set (match_dup 0)
1008 (ashift:GPR (match_dup 1) (match_dup 2)))
1009 (set (match_dup 0)
1010 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
1011 {
1012 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
1013 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
1014 }
1015 [(set_attr "move_type" "shift_shift,load")
1016 (set_attr "mode" "<GPR:MODE>")])
1017
1018(define_insn "zero_extendqi<SUPERQI:mode>2"
1019 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1020 (zero_extend:SUPERQI
1021 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1022 ""
1023 "@
1024 and\t%0,%1,0xff
1025 lbu\t%0,%1"
1026 [(set_attr "move_type" "andi,load")
1027 (set_attr "mode" "<SUPERQI:MODE>")])
1028
1029;;
1030;; ....................
1031;;
1032;; SIGN EXTENSION
1033;;
1034;; ....................
1035
1036(define_insn "extendsidi2"
1037 [(set (match_operand:DI 0 "register_operand" "=r,r")
1038 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
1039 "TARGET_64BIT"
1040 "@
1041 sext.w\t%0,%1
1042 lw\t%0,%1"
1043 [(set_attr "move_type" "move,load")
1044 (set_attr "mode" "DI")])
1045
1046(define_insn_and_split "extend<SHORT:mode><SUPERQI:mode>2"
1047 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
1048 (sign_extend:SUPERQI
1049 (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
1050 ""
1051 "@
1052 #
1053 l<SHORT:size>\t%0,%1"
1054 "&& reload_completed && REG_P (operands[1])"
1055 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1056 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
1057{
1058 operands[0] = gen_lowpart (SImode, operands[0]);
1059 operands[1] = gen_lowpart (SImode, operands[1]);
1060 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
1061 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
1062}
1063 [(set_attr "move_type" "shift_shift,load")
1064 (set_attr "mode" "SI")])
1065
1066(define_insn "extendsfdf2"
1067 [(set (match_operand:DF 0 "register_operand" "=f")
1068 (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
1069 "TARGET_DOUBLE_FLOAT"
1070 "fcvt.d.s\t%0,%1"
1071 [(set_attr "type" "fcvt")
1072 (set_attr "mode" "DF")])
1073
1074;;
1075;; ....................
1076;;
1077;; CONVERSIONS
1078;;
1079;; ....................
1080
1081(define_insn "fix_trunc<ANYF:mode><GPR:mode>2"
1082 [(set (match_operand:GPR 0 "register_operand" "=r")
1083 (fix:GPR (match_operand:ANYF 1 "register_operand" "f")))]
1084 "TARGET_HARD_FLOAT"
1085 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,rtz"
1086 [(set_attr "type" "fcvt")
1087 (set_attr "mode" "<ANYF:MODE>")])
1088
1089(define_insn "fixuns_trunc<ANYF:mode><GPR:mode>2"
1090 [(set (match_operand:GPR 0 "register_operand" "=r")
1091 (unsigned_fix:GPR (match_operand:ANYF 1 "register_operand" "f")))]
1092 "TARGET_HARD_FLOAT"
1093 "fcvt.<GPR:ifmt>u.<ANYF:fmt> %0,%1,rtz"
1094 [(set_attr "type" "fcvt")
1095 (set_attr "mode" "<ANYF:MODE>")])
1096
1097(define_insn "float<GPR:mode><ANYF:mode>2"
1098 [(set (match_operand:ANYF 0 "register_operand" "=f")
1099 (float:ANYF (match_operand:GPR 1 "reg_or_0_operand" "rJ")))]
1100 "TARGET_HARD_FLOAT"
1101 "fcvt.<ANYF:fmt>.<GPR:ifmt>\t%0,%z1"
1102 [(set_attr "type" "fcvt")
1103 (set_attr "mode" "<ANYF:MODE>")])
1104
1105(define_insn "floatuns<GPR:mode><ANYF:mode>2"
1106 [(set (match_operand:ANYF 0 "register_operand" "=f")
1107 (unsigned_float:ANYF (match_operand:GPR 1 "reg_or_0_operand" "rJ")))]
1108 "TARGET_HARD_FLOAT"
1109 "fcvt.<ANYF:fmt>.<GPR:ifmt>u\t%0,%z1"
1110 [(set_attr "type" "fcvt")
1111 (set_attr "mode" "<ANYF:MODE>")])
1112
1113(define_insn "l<rint_pattern><ANYF:mode><GPR:mode>2"
1114 [(set (match_operand:GPR 0 "register_operand" "=r")
1115 (unspec:GPR [(match_operand:ANYF 1 "register_operand" "f")]
1116 RINT))]
1117 "TARGET_HARD_FLOAT"
1118 "fcvt.<GPR:ifmt>.<ANYF:fmt> %0,%1,<rint_rm>"
1119 [(set_attr "type" "fcvt")
1120 (set_attr "mode" "<ANYF:MODE>")])
1121
1122;;
1123;; ....................
1124;;
1125;; DATA MOVEMENT
1126;;
1127;; ....................
1128
1129;; Lower-level instructions for loading an address from the GOT.
1130;; We could use MEMs, but an unspec gives more optimization
1131;; opportunities.
1132
1133(define_insn "got_load<mode>"
1134 [(set (match_operand:P 0 "register_operand" "=r")
1135 (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
1136 UNSPEC_LOAD_GOT))]
1137 ""
1138 "la\t%0,%1"
1139 [(set_attr "got" "load")
1140 (set_attr "mode" "<MODE>")])
1141
1142(define_insn "tls_add_tp_le<mode>"
1143 [(set (match_operand:P 0 "register_operand" "=r")
1144 (unspec:P [(match_operand:P 1 "register_operand" "r")
1145 (match_operand:P 2 "register_operand" "r")
1146 (match_operand:P 3 "symbolic_operand" "")]
1147 UNSPEC_TLS_LE))]
1148 ""
1149 "add\t%0,%1,%2,%%tprel_add(%3)"
1150 [(set_attr "type" "arith")
1151 (set_attr "mode" "<MODE>")])
1152
1153(define_insn "got_load_tls_gd<mode>"
1154 [(set (match_operand:P 0 "register_operand" "=r")
1155 (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
1156 UNSPEC_TLS_GD))]
1157 ""
1158 "la.tls.gd\t%0,%1"
1159 [(set_attr "got" "load")
1160 (set_attr "mode" "<MODE>")])
1161
1162(define_insn "got_load_tls_ie<mode>"
1163 [(set (match_operand:P 0 "register_operand" "=r")
1164 (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
1165 UNSPEC_TLS_IE))]
1166 ""
1167 "la.tls.ie\t%0,%1"
1168 [(set_attr "got" "load")
1169 (set_attr "mode" "<MODE>")])
1170
1171(define_insn "auipc<mode>"
1172 [(set (match_operand:P 0 "register_operand" "=r")
1173 (unspec:P [(match_operand:P 1 "symbolic_operand" "")
1174 (match_operand:P 2 "const_int_operand")
1175 (pc)]
1176 UNSPEC_AUIPC))]
1177 ""
1178 ".LA%2: auipc\t%0,%h1"
1179 [(set_attr "type" "arith")
1180 (set_attr "cannot_copy" "yes")])
1181
1182;; Instructions for adding the low 12 bits of an address to a register.
1183;; Operand 2 is the address: riscv_print_operand works out which relocation
1184;; should be applied.
1185
1186(define_insn "*low<mode>"
1187 [(set (match_operand:P 0 "register_operand" "=r")
1188 (lo_sum:P (match_operand:P 1 "register_operand" "r")
1189 (match_operand:P 2 "symbolic_operand" "")))]
1190 ""
1191 "addi\t%0,%1,%R2"
1192 [(set_attr "type" "arith")
1193 (set_attr "mode" "<MODE>")])
1194
1195;; Allow combine to split complex const_int load sequences, using operand 2
1196;; to store the intermediate results. See move_operand for details.
1197(define_split
1198 [(set (match_operand:GPR 0 "register_operand")
1199 (match_operand:GPR 1 "splittable_const_int_operand"))
1200 (clobber (match_operand:GPR 2 "register_operand"))]
1201 ""
1202 [(const_int 0)]
1203{
1204 riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]));
1205 DONE;
1206})
1207
1208;; Likewise, for symbolic operands.
1209(define_split
1210 [(set (match_operand:P 0 "register_operand")
1211 (match_operand:P 1))
1212 (clobber (match_operand:P 2 "register_operand"))]
1213 "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)"
1214 [(set (match_dup 0) (match_dup 3))]
1215{
1216 riscv_split_symbol (operands[2], operands[1],
1217 MAX_MACHINE_MODE, &operands[3]);
1218})
1219
1220;; 64-bit integer moves
1221
1222(define_expand "movdi"
1223 [(set (match_operand:DI 0 "")
1224 (match_operand:DI 1 ""))]
1225 ""
1226{
1227 if (riscv_legitimize_move (DImode, operands[0], operands[1]))
1228 DONE;
1229})
1230
1231(define_insn "*movdi_32bit"
1232 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m")
1233 (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f"))]
1234 "!TARGET_64BIT
1235 && (register_operand (operands[0], DImode)
1236 || reg_or_0_operand (operands[1], DImode))"
1237 { return riscv_output_move (operands[0], operands[1]); }
1238 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1239 (set_attr "mode" "DI")])
1240
1241(define_insn "*movdi_64bit"
1242 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m,*f,*f,*r,*f,*m")
1243 (match_operand:DI 1 "move_operand" " r,T,m,rJ,*r*J,*m,*f,*f,*f"))]
1244 "TARGET_64BIT
1245 && (register_operand (operands[0], DImode)
1246 || reg_or_0_operand (operands[1], DImode))"
1247 { return riscv_output_move (operands[0], operands[1]); }
1248 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fmove,fpstore")
1249 (set_attr "mode" "DI")])
1250
1251;; 32-bit Integer moves
1252
1253(define_expand "mov<mode>"
1254 [(set (match_operand:MOVE32 0 "")
1255 (match_operand:MOVE32 1 ""))]
1256 ""
1257{
1258 if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
1259 DONE;
1260})
1261
1262(define_insn "*movsi_internal"
1263 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,*r,*m")
1264 (match_operand:SI 1 "move_operand" "r,T,m,rJ,*r*J,*m,*f,*f"))]
1265 "(register_operand (operands[0], SImode)
1266 || reg_or_0_operand (operands[1], SImode))"
1267 { return riscv_output_move (operands[0], operands[1]); }
1268 [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
1269 (set_attr "mode" "SI")])
1270
1271;; 16-bit Integer moves
1272
1273;; Unlike most other insns, the move insns can't be split with
1274;; different predicates, because register spilling and other parts of
1275;; the compiler, have memoized the insn number already.
1276;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
1277
1278(define_expand "movhi"
1279 [(set (match_operand:HI 0 "")
1280 (match_operand:HI 1 ""))]
1281 ""
1282{
1283 if (riscv_legitimize_move (HImode, operands[0], operands[1]))
1284 DONE;
1285})
1286
1287(define_insn "*movhi_internal"
1288 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r")
1289 (match_operand:HI 1 "move_operand" "r,T,m,rJ,*r*J,*f"))]
1290 "(register_operand (operands[0], HImode)
1291 || reg_or_0_operand (operands[1], HImode))"
1292 { return riscv_output_move (operands[0], operands[1]); }
1293 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1294 (set_attr "mode" "HI")])
1295
1296;; HImode constant generation; see riscv_move_integer for details.
1297;; si+si->hi without truncation is legal because of TRULY_NOOP_TRUNCATION.
1298
1299(define_insn "*add<mode>hi3"
1300 [(set (match_operand:HI 0 "register_operand" "=r,r")
1301 (plus:HI (match_operand:HISI 1 "register_operand" "r,r")
1302 (match_operand:HISI 2 "arith_operand" "r,I")))]
1303 ""
1304 { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; }
1305 [(set_attr "type" "arith")
1306 (set_attr "mode" "HI")])
1307
1308(define_insn "*xor<mode>hi3"
1309 [(set (match_operand:HI 0 "register_operand" "=r,r")
1310 (xor:HI (match_operand:HISI 1 "register_operand" "r,r")
1311 (match_operand:HISI 2 "arith_operand" "r,I")))]
1312 ""
1313 "xor\t%0,%1,%2"
1314 [(set_attr "type" "logical")
1315 (set_attr "mode" "HI")])
1316
1317;; 8-bit Integer moves
1318
1319(define_expand "movqi"
1320 [(set (match_operand:QI 0 "")
1321 (match_operand:QI 1 ""))]
1322 ""
1323{
1324 if (riscv_legitimize_move (QImode, operands[0], operands[1]))
1325 DONE;
1326})
1327
1328(define_insn "*movqi_internal"
1329 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r")
1330 (match_operand:QI 1 "move_operand" "r,I,m,rJ,*r*J,*f"))]
1331 "(register_operand (operands[0], QImode)
1332 || reg_or_0_operand (operands[1], QImode))"
1333 { return riscv_output_move (operands[0], operands[1]); }
1334 [(set_attr "move_type" "move,const,load,store,mtc,mfc")
1335 (set_attr "mode" "QI")])
1336
1337;; 32-bit floating point moves
1338
1339(define_expand "movsf"
1340 [(set (match_operand:SF 0 "")
1341 (match_operand:SF 1 ""))]
1342 ""
1343{
1344 if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
1345 DONE;
1346})
1347
1348(define_insn "*movsf_hardfloat"
1349 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,*r,*r,*m")
1350 (match_operand:SF 1 "move_operand" "f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
1351 "TARGET_HARD_FLOAT
1352 && (register_operand (operands[0], SFmode)
1353 || reg_or_0_operand (operands[1], SFmode))"
1354 { return riscv_output_move (operands[0], operands[1]); }
1355 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1356 (set_attr "mode" "SF")])
1357
1358(define_insn "*movsf_softfloat"
1359 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
1360 (match_operand:SF 1 "move_operand" "Gr,m,r"))]
1361 "!TARGET_HARD_FLOAT
1362 && (register_operand (operands[0], SFmode)
1363 || reg_or_0_operand (operands[1], SFmode))"
1364 { return riscv_output_move (operands[0], operands[1]); }
1365 [(set_attr "move_type" "move,load,store")
1366 (set_attr "mode" "SF")])
1367
1368;; 64-bit floating point moves
1369
1370(define_expand "movdf"
1371 [(set (match_operand:DF 0 "")
1372 (match_operand:DF 1 ""))]
1373 ""
1374{
1375 if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
1376 DONE;
1377})
1378
1379;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead.
1380;; (However, we can still use fcvt.d.w to zero a floating-point register.)
1381(define_insn "*movdf_hardfloat_rv32"
1382 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*r,*r,*m")
1383 (match_operand:DF 1 "move_operand" "f,G,m,f,G,*r*G,*m,*r"))]
1384 "!TARGET_64BIT && TARGET_DOUBLE_FLOAT
1385 && (register_operand (operands[0], DFmode)
1386 || reg_or_0_operand (operands[1], DFmode))"
1387 { return riscv_output_move (operands[0], operands[1]); }
1388 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store")
1389 (set_attr "mode" "DF")])
1390
1391(define_insn "*movdf_hardfloat_rv64"
1392 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,*r,*r,*m")
1393 (match_operand:DF 1 "move_operand" "f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
1394 "TARGET_64BIT && TARGET_DOUBLE_FLOAT
1395 && (register_operand (operands[0], DFmode)
1396 || reg_or_0_operand (operands[1], DFmode))"
1397 { return riscv_output_move (operands[0], operands[1]); }
1398 [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
1399 (set_attr "mode" "DF")])
1400
1401(define_insn "*movdf_softfloat"
1402 [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
1403 (match_operand:DF 1 "move_operand" "rG,m,rG"))]
1404 "!TARGET_DOUBLE_FLOAT
1405 && (register_operand (operands[0], DFmode)
1406 || reg_or_0_operand (operands[1], DFmode))"
1407 { return riscv_output_move (operands[0], operands[1]); }
1408 [(set_attr "move_type" "move,load,store")
1409 (set_attr "mode" "DF")])
1410
1411(define_split
1412 [(set (match_operand:MOVE64 0 "nonimmediate_operand")
1413 (match_operand:MOVE64 1 "move_operand"))]
1414 "reload_completed
1415 && riscv_split_64bit_move_p (operands[0], operands[1])"
1416 [(const_int 0)]
1417{
1418 riscv_split_doubleword_move (operands[0], operands[1]);
1419 DONE;
1420})
1421
1422;; Expand in-line code to clear the instruction cache between operand[0] and
1423;; operand[1].
1424(define_expand "clear_cache"
1425 [(match_operand 0 "pmode_register_operand")
1426 (match_operand 1 "pmode_register_operand")]
1427 ""
1428{
1429 emit_insn (gen_fence_i ());
1430 DONE;
1431})
1432
1433(define_insn "fence"
1434 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE)]
1435 ""
1436 "%|fence%-")
1437
1438(define_insn "fence_i"
1439 [(unspec_volatile [(const_int 0)] UNSPECV_FENCE_I)]
1440 ""
1441 "fence.i")
1442
1443;;
1444;; ....................
1445;;
1446;; SHIFTS
1447;;
1448;; ....................
1449
1450(define_insn "<optab>si3"
1451 [(set (match_operand:SI 0 "register_operand" "=r")
1452 (any_shift:SI (match_operand:SI 1 "register_operand" "r")
1453 (match_operand:SI 2 "arith_operand" "rI")))]
1454 ""
1455{
1456 if (GET_CODE (operands[2]) == CONST_INT)
1457 operands[2] = GEN_INT (INTVAL (operands[2])
1458 & (GET_MODE_BITSIZE (SImode) - 1));
1459
1460 return TARGET_64BIT ? "<insn>w\t%0,%1,%2" : "<insn>\t%0,%1,%2";
1461}
1462 [(set_attr "type" "shift")
1463 (set_attr "mode" "SI")])
1464
1465(define_insn "<optab>di3"
1466 [(set (match_operand:DI 0 "register_operand" "=r")
1467 (any_shift:DI (match_operand:DI 1 "register_operand" "r")
1468 (match_operand:DI 2 "arith_operand" "rI")))]
1469 "TARGET_64BIT"
1470{
1471 if (GET_CODE (operands[2]) == CONST_INT)
1472 operands[2] = GEN_INT (INTVAL (operands[2])
1473 & (GET_MODE_BITSIZE (DImode) - 1));
1474
1475 return "<insn>\t%0,%1,%2";
1476}
1477 [(set_attr "type" "shift")
1478 (set_attr "mode" "DI")])
1479
1480(define_insn "*<optab>si3_extend"
1481 [(set (match_operand:DI 0 "register_operand" "=r")
1482 (sign_extend:DI
1483 (any_shift:SI (match_operand:SI 1 "register_operand" "r")
1484 (match_operand:SI 2 "arith_operand" "rI"))))]
1485 "TARGET_64BIT"
1486{
1487 if (GET_CODE (operands[2]) == CONST_INT)
1488 operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
1489
1490 return "<insn>w\t%0,%1,%2";
1491}
1492 [(set_attr "type" "shift")
1493 (set_attr "mode" "SI")])
1494
1495;;
1496;; ....................
1497;;
1498;; CONDITIONAL BRANCHES
1499;;
1500;; ....................
1501
1502;; Conditional branches
1503
1504(define_insn "*branch_order<mode>"
1505 [(set (pc)
1506 (if_then_else
1507 (match_operator 1 "order_operator"
1508 [(match_operand:X 2 "register_operand" "r")
1509 (match_operand:X 3 "register_operand" "r")])
1510 (label_ref (match_operand 0 "" ""))
1511 (pc)))]
1512 ""
1513 "b%C1\t%2,%3,%0"
1514 [(set_attr "type" "branch")
1515 (set_attr "mode" "none")])
1516
1517(define_insn "*branch_zero<mode>"
1518 [(set (pc)
1519 (if_then_else
1520 (match_operator 1 "signed_order_operator"
1521 [(match_operand:X 2 "register_operand" "r")
1522 (const_int 0)])
1523 (label_ref (match_operand 0 "" ""))
1524 (pc)))]
1525 ""
1526 "b%C1z\t%2,%0"
1527 [(set_attr "type" "branch")
1528 (set_attr "mode" "none")])
1529
1530;; Used to implement built-in functions.
1531(define_expand "condjump"
1532 [(set (pc)
1533 (if_then_else (match_operand 0)
1534 (label_ref (match_operand 1))
1535 (pc)))])
1536
1537(define_expand "cbranch<mode>4"
1538 [(set (pc)
1539 (if_then_else (match_operator 0 "comparison_operator"
1540 [(match_operand:BR 1 "register_operand")
1541 (match_operand:BR 2 "nonmemory_operand")])
1542 (label_ref (match_operand 3 ""))
1543 (pc)))]
1544 ""
1545{
1546 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1547 operands[1], operands[2]);
1548 DONE;
1549})
1550
1551(define_expand "cbranch<mode>4"
1552 [(set (pc)
1553 (if_then_else (match_operator 0 "fp_branch_comparison"
1554 [(match_operand:ANYF 1 "register_operand")
1555 (match_operand:ANYF 2 "register_operand")])
1556 (label_ref (match_operand 3 ""))
1557 (pc)))]
1558 "TARGET_HARD_FLOAT"
1559{
1560 riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]),
1561 operands[1], operands[2]);
1562 DONE;
1563})
1564
1565(define_insn_and_split "*branch_on_bit<X:mode>"
1566 [(set (pc)
1567 (if_then_else
1568 (match_operator 0 "equality_operator"
1569 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1570 (const_int 1)
1571 (match_operand 3 "branch_on_bit_operand"))
1572 (const_int 0)])
1573 (label_ref (match_operand 1))
1574 (pc)))
1575 (clobber (match_scratch:X 4 "=&r"))]
1576 ""
1577 "#"
1578 "reload_completed"
1579 [(set (match_dup 4)
1580 (ashift:X (match_dup 2) (match_dup 3)))
1581 (set (pc)
1582 (if_then_else
1583 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1584 (label_ref (match_operand 1))
1585 (pc)))]
1586{
1587 int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
1588 operands[3] = GEN_INT (shift);
1589
1590 if (GET_CODE (operands[0]) == EQ)
1591 operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
1592 else
1593 operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
1594})
1595
1596(define_insn_and_split "*branch_on_bit_range<X:mode>"
1597 [(set (pc)
1598 (if_then_else
1599 (match_operator 0 "equality_operator"
1600 [(zero_extract:X (match_operand:X 2 "register_operand" "r")
1601 (match_operand 3 "branch_on_bit_operand")
1602 (const_int 0))
1603 (const_int 0)])
1604 (label_ref (match_operand 1))
1605 (pc)))
1606 (clobber (match_scratch:X 4 "=&r"))]
1607 ""
1608 "#"
1609 "reload_completed"
1610 [(set (match_dup 4)
1611 (ashift:X (match_dup 2) (match_dup 3)))
1612 (set (pc)
1613 (if_then_else
1614 (match_op_dup 0 [(match_dup 4) (const_int 0)])
1615 (label_ref (match_operand 1))
1616 (pc)))]
1617{
1618 operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
1619})
1620
1621;;
1622;; ....................
1623;;
1624;; SETTING A REGISTER FROM A COMPARISON
1625;;
1626;; ....................
1627
1628;; Destination is always set in SI mode.
1629
1630(define_expand "cstore<mode>4"
1631 [(set (match_operand:SI 0 "register_operand")
1632 (match_operator:SI 1 "order_operator"
1633 [(match_operand:GPR 2 "register_operand")
1634 (match_operand:GPR 3 "nonmemory_operand")]))]
1635 ""
1636{
1637 riscv_expand_int_scc (operands[0], GET_CODE (operands[1]), operands[2],
1638 operands[3]);
1639 DONE;
1640})
1641
1642(define_expand "cstore<mode>4"
1643 [(set (match_operand:SI 0 "register_operand")
1644 (match_operator:SI 1 "fp_scc_comparison"
1645 [(match_operand:ANYF 2 "register_operand")
1646 (match_operand:ANYF 3 "register_operand")]))]
1647 "TARGET_HARD_FLOAT"
1648{
1649 riscv_expand_float_scc (operands[0], GET_CODE (operands[1]), operands[2],
1650 operands[3]);
1651 DONE;
1652})
1653
1654(define_insn "*cstore<ANYF:mode><X:mode>4"
1655 [(set (match_operand:X 0 "register_operand" "=r")
1656 (match_operator:X 1 "fp_native_comparison"
1657 [(match_operand:ANYF 2 "register_operand" "f")
1658 (match_operand:ANYF 3 "register_operand" "f")]))]
1659 "TARGET_HARD_FLOAT"
1660 "f%C1.<fmt>\t%0,%2,%3"
1661 [(set_attr "type" "fcmp")
1662 (set_attr "mode" "<UNITMODE>")])
1663
1664(define_insn "f<quiet_pattern>_quiet<ANYF:mode><X:mode>4"
1665 [(set (match_operand:X 0 "register_operand" "=r")
1666 (unspec:X
1667 [(match_operand:ANYF 1 "register_operand" "f")
1668 (match_operand:ANYF 2 "register_operand" "f")]
1669 QUIET_COMPARISON))
1670 (clobber (match_scratch:X 3 "=&r"))]
1671 "TARGET_HARD_FLOAT"
1672 "frflags\t%3\n\tf<quiet_pattern>.<fmt>\t%0,%1,%2\n\tfsflags %3"
1673 [(set_attr "type" "fcmp")
1674 (set_attr "mode" "<UNITMODE>")
1675 (set (attr "length") (const_int 12))])
1676
1677(define_insn "*seq_zero_<X:mode><GPR:mode>"
1678 [(set (match_operand:GPR 0 "register_operand" "=r")
1679 (eq:GPR (match_operand:X 1 "register_operand" "r")
1680 (const_int 0)))]
1681 ""
1682 "seqz\t%0,%1"
1683 [(set_attr "type" "slt")
1684 (set_attr "mode" "<X:MODE>")])
1685
1686(define_insn "*sne_zero_<X:mode><GPR:mode>"
1687 [(set (match_operand:GPR 0 "register_operand" "=r")
1688 (ne:GPR (match_operand:X 1 "register_operand" "r")
1689 (const_int 0)))]
1690 ""
1691 "snez\t%0,%1"
1692 [(set_attr "type" "slt")
1693 (set_attr "mode" "<X:MODE>")])
1694
1695(define_insn "*sgt<u>_<X:mode><GPR:mode>"
1696 [(set (match_operand:GPR 0 "register_operand" "=r")
1697 (any_gt:GPR (match_operand:X 1 "register_operand" "r")
1698 (match_operand:X 2 "reg_or_0_operand" "rJ")))]
1699 ""
1700 "sgt<u>\t%0,%1,%z2"
1701 [(set_attr "type" "slt")
1702 (set_attr "mode" "<X:MODE>")])
1703
1704(define_insn "*sge<u>_<X:mode><GPR:mode>"
1705 [(set (match_operand:GPR 0 "register_operand" "=r")
1706 (any_ge:GPR (match_operand:X 1 "register_operand" "r")
1707 (const_int 1)))]
1708 ""
1709 "slt<u>\t%0,zero,%1"
1710 [(set_attr "type" "slt")
1711 (set_attr "mode" "<MODE>")])
1712
1713(define_insn "*slt<u>_<X:mode><GPR:mode>"
1714 [(set (match_operand:GPR 0 "register_operand" "=r")
1715 (any_lt:GPR (match_operand:X 1 "register_operand" "r")
1716 (match_operand:X 2 "arith_operand" "rI")))]
1717 ""
1718 "slt<u>\t%0,%1,%2"
1719 [(set_attr "type" "slt")
1720 (set_attr "mode" "<MODE>")])
1721
1722(define_insn "*sle<u>_<X:mode><GPR:mode>"
1723 [(set (match_operand:GPR 0 "register_operand" "=r")
1724 (any_le:GPR (match_operand:X 1 "register_operand" "r")
1725 (match_operand:X 2 "sle_operand" "")))]
1726 ""
1727{
1728 operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
1729 return "slt<u>\t%0,%1,%2";
1730}
1731 [(set_attr "type" "slt")
1732 (set_attr "mode" "<MODE>")])
1733
1734;;
1735;; ....................
1736;;
1737;; UNCONDITIONAL BRANCHES
1738;;
1739;; ....................
1740
1741;; Unconditional branches.
1742
1743(define_insn "jump"
1744 [(set (pc)
1745 (label_ref (match_operand 0 "" "")))]
1746 ""
1747 "j\t%l0"
1748 [(set_attr "type" "jump")
1749 (set_attr "mode" "none")])
1750
1751(define_expand "indirect_jump"
1752 [(set (pc) (match_operand 0 "register_operand"))]
1753 ""
1754{
1755 operands[0] = force_reg (Pmode, operands[0]);
1756 if (Pmode == SImode)
1757 emit_jump_insn (gen_indirect_jumpsi (operands[0]));
1758 else
1759 emit_jump_insn (gen_indirect_jumpdi (operands[0]));
1760 DONE;
1761})
1762
1763(define_insn "indirect_jump<mode>"
1764 [(set (pc) (match_operand:P 0 "register_operand" "l"))]
1765 ""
1766 "jr\t%0"
1767 [(set_attr "type" "jump")
1768 (set_attr "mode" "none")])
1769
1770(define_expand "tablejump"
1771 [(set (pc) (match_operand 0 "register_operand" ""))
1772 (use (label_ref (match_operand 1 "" "")))]
1773 ""
1774{
1775 if (CASE_VECTOR_PC_RELATIVE)
1776 operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
1777 gen_rtx_LABEL_REF (Pmode, operands[1]),
1778 NULL_RTX, 0, OPTAB_DIRECT);
1779
1780 if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
1781 emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
1782 else
1783 emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
1784 DONE;
1785})
1786
1787(define_insn "tablejump<mode>"
1788 [(set (pc) (match_operand:GPR 0 "register_operand" "l"))
1789 (use (label_ref (match_operand 1 "" "")))]
1790 ""
1791 "jr\t%0"
1792 [(set_attr "type" "jump")
1793 (set_attr "mode" "none")])
1794
1795;;
1796;; ....................
1797;;
1798;; Function prologue/epilogue
1799;;
1800;; ....................
1801;;
1802
1803(define_expand "prologue"
1804 [(const_int 1)]
1805 ""
1806{
1807 riscv_expand_prologue ();
1808 DONE;
1809})
1810
1811;; Block any insns from being moved before this point, since the
1812;; profiling call to mcount can use various registers that aren't
1813;; saved or used to pass arguments.
1814
1815(define_insn "blockage"
1816 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
1817 ""
1818 ""
1819 [(set_attr "type" "ghost")
1820 (set_attr "mode" "none")])
1821
1822(define_expand "epilogue"
1823 [(const_int 2)]
1824 ""
1825{
1826 riscv_expand_epilogue (false);
1827 DONE;
1828})
1829
1830(define_expand "sibcall_epilogue"
1831 [(const_int 2)]
1832 ""
1833{
1834 riscv_expand_epilogue (true);
1835 DONE;
1836})
1837
1838;; Trivial return. Make it look like a normal return insn as that
1839;; allows jump optimizations to work better.
1840
1841(define_expand "return"
1842 [(simple_return)]
1843 "riscv_can_use_return_insn ()"
1844 "")
1845
1846(define_insn "simple_return"
1847 [(simple_return)]
1848 ""
1849 "ret"
1850 [(set_attr "type" "jump")
1851 (set_attr "mode" "none")])
1852
1853;; Normal return.
1854
1855(define_insn "simple_return_internal"
1856 [(simple_return)
1857 (use (match_operand 0 "pmode_register_operand" ""))]
1858 ""
1859 "jr\t%0"
1860 [(set_attr "type" "jump")
1861 (set_attr "mode" "none")])
1862
1863;; This is used in compiling the unwind routines.
1864(define_expand "eh_return"
1865 [(use (match_operand 0 "general_operand"))]
1866 ""
1867{
1868 if (GET_MODE (operands[0]) != word_mode)
1869 operands[0] = convert_to_mode (word_mode, operands[0], 0);
1870 if (TARGET_64BIT)
1871 emit_insn (gen_eh_set_lr_di (operands[0]));
1872 else
1873 emit_insn (gen_eh_set_lr_si (operands[0]));
1874 DONE;
1875})
1876
1877;; Clobber the return address on the stack. We can't expand this
1878;; until we know where it will be put in the stack frame.
1879
1880(define_insn "eh_set_lr_si"
1881 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
1882 (clobber (match_scratch:SI 1 "=&r"))]
1883 "! TARGET_64BIT"
1884 "#")
1885
1886(define_insn "eh_set_lr_di"
1887 [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
1888 (clobber (match_scratch:DI 1 "=&r"))]
1889 "TARGET_64BIT"
1890 "#")
1891
1892(define_split
1893 [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
1894 (clobber (match_scratch 1))]
1895 "reload_completed"
1896 [(const_int 0)]
1897{
1898 riscv_set_return_address (operands[0], operands[1]);
1899 DONE;
1900})
1901
1902;;
1903;; ....................
1904;;
1905;; FUNCTION CALLS
1906;;
1907;; ....................
1908
1909(define_expand "sibcall"
1910 [(parallel [(call (match_operand 0 "")
1911 (match_operand 1 ""))
1912 (use (match_operand 2 "")) ;; next_arg_reg
1913 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
1914 ""
1915{
1916 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
1917 emit_call_insn (gen_sibcall_internal (target, operands[1]));
1918 DONE;
1919})
1920
1921(define_insn "sibcall_internal"
1922 [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
1923 (match_operand 1 "" ""))]
1924 "SIBLING_CALL_P (insn)"
1925 "@
1926 jr\t%0
1927 tail\t%0
1928 tail\t%0@plt"
1929 [(set_attr "type" "call")])
1930
1931(define_expand "sibcall_value"
1932 [(parallel [(set (match_operand 0 "")
1933 (call (match_operand 1 "")
1934 (match_operand 2 "")))
1935 (use (match_operand 3 ""))])] ;; next_arg_reg
1936 ""
1937{
1938 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
1939 emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
1940 DONE;
1941})
1942
1943(define_insn "sibcall_value_internal"
1944 [(set (match_operand 0 "" "")
1945 (call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
1946 (match_operand 2 "" "")))]
1947 "SIBLING_CALL_P (insn)"
1948 "@
1949 jr\t%1
1950 tail\t%1
1951 tail\t%1@plt"
1952 [(set_attr "type" "call")])
1953
1954(define_expand "call"
1955 [(parallel [(call (match_operand 0 "")
1956 (match_operand 1 ""))
1957 (use (match_operand 2 "")) ;; next_arg_reg
1958 (use (match_operand 3 ""))])] ;; struct_value_size_rtx
1959 ""
1960{
1961 rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
1962 emit_call_insn (gen_call_internal (target, operands[1]));
1963 DONE;
1964})
1965
1966(define_insn "call_internal"
1967 [(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
1968 (match_operand 1 "" ""))
1969 (clobber (reg:SI RETURN_ADDR_REGNUM))]
1970 ""
1971 "@
1972 jalr\t%0
1973 call\t%0
1974 call\t%0@plt"
1975 [(set_attr "type" "call")])
1976
1977(define_expand "call_value"
1978 [(parallel [(set (match_operand 0 "")
1979 (call (match_operand 1 "")
1980 (match_operand 2 "")))
1981 (use (match_operand 3 ""))])] ;; next_arg_reg
1982 ""
1983{
1984 rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
1985 emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
1986 DONE;
1987})
1988
1989(define_insn "call_value_internal"
1990 [(set (match_operand 0 "" "")
1991 (call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
1992 (match_operand 2 "" "")))
1993 (clobber (reg:SI RETURN_ADDR_REGNUM))]
1994 ""
1995 "@
1996 jalr\t%1
1997 call\t%1
1998 call\t%1@plt"
1999 [(set_attr "type" "call")])
2000
2001;; Call subroutine returning any type.
2002
2003(define_expand "untyped_call"
2004 [(parallel [(call (match_operand 0 "")
2005 (const_int 0))
2006 (match_operand 1 "")
2007 (match_operand 2 "")])]
2008 ""
2009{
2010 int i;
2011
2012 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2013
2014 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2015 {
2016 rtx set = XVECEXP (operands[2], 0, i);
2017 riscv_emit_move (SET_DEST (set), SET_SRC (set));
2018 }
2019
2020 emit_insn (gen_blockage ());
2021 DONE;
2022})
2023
2024(define_insn "nop"
2025 [(const_int 0)]
2026 ""
2027 "nop"
2028 [(set_attr "type" "nop")
2029 (set_attr "mode" "none")])
2030
2031(define_insn "trap"
2032 [(trap_if (const_int 1) (const_int 0))]
2033 ""
2034 "ebreak")
2035
2036(define_insn "gpr_save"
2037 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_SAVE)
2038 (clobber (reg:SI T0_REGNUM))
2039 (clobber (reg:SI T1_REGNUM))]
2040 ""
2041 { return riscv_output_gpr_save (INTVAL (operands[0])); })
2042
2043(define_insn "gpr_restore"
2044 [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPECV_GPR_RESTORE)]
2045 ""
2046 "tail\t__riscv_restore_%0")
2047
2048(define_insn "gpr_restore_return"
2049 [(return)
2050 (use (match_operand 0 "pmode_register_operand" ""))
2051 (const_int 0)]
2052 ""
2053 "")
2054
2055(define_insn "riscv_frflags"
2056 [(set (match_operand:SI 0 "register_operand" "=r")
2057 (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))]
2058 "TARGET_HARD_FLOAT"
2059 "frflags %0")
2060
2061(define_insn "riscv_fsflags"
2062 [(unspec_volatile [(match_operand:SI 0 "csr_operand" "rK")] UNSPECV_FSFLAGS)]
2063 "TARGET_HARD_FLOAT"
2064 "fsflags %0")
2065
2066(define_insn "stack_tie<mode>"
2067 [(set (mem:BLK (scratch))
2068 (unspec:BLK [(match_operand:X 0 "register_operand" "r")
2069 (match_operand:X 1 "register_operand" "r")]
2070 UNSPEC_TIE))]
2071 ""
2072 ""
2073 [(set_attr "length" "0")]
2074)
2075
2076(include "sync.md")
2077(include "peephole.md")
2078(include "pic.md")
2079(include "generic.md")