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