1;; Machine description for OpenRISC
2;; Copyright (C) 2018-2020 Free Software Foundation, Inc.
3;; Contributed by Stafford Horne
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify it
8;; under the terms of the GNU General Public License as published
9;; by the Free Software Foundation; either version 3, or (at your
10;; option) any later version.
11
12;; GCC is distributed in the hope that it will be useful, but WITHOUT
13;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15;; License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3.  If not see
19;; <http://www.gnu.org/licenses/>.
20
21;; -------------------------------------------------------------------------
22;; OpenRISC specific constraints, predicates and attributes
23;; -------------------------------------------------------------------------
24
25(include "constraints.md")
26(include "predicates.md")
27
28;; Register numbers
29(define_constants
30  [(SP_REGNUM       1)
31   (HFP_REGNUM      2)
32   (LR_REGNUM       9)
33   (TLS_REGNUM     10)
34   (RV_REGNUM      11)
35   (PE_TMP_REGNUM  13)
36   (AP_REGNUM      32)
37   (SFP_REGNUM     33)
38   (SR_F_REGNUM    34)]
39)
40
41(define_c_enum "unspec" [
42  UNSPEC_SET_GOT
43  UNSPEC_GOT
44  UNSPEC_GOTOFF
45  UNSPEC_TPOFF
46  UNSPEC_GOTTPOFF
47  UNSPEC_TLSGD
48  UNSPEC_MSYNC
49])
50
51(define_c_enum "unspecv" [
52  UNSPECV_SET_GOT
53  UNSPECV_LL
54  UNSPECV_SC
55])
56
57;; Instruction scheduler
58
59; Most instructions are 4 bytes long.
60(define_attr "length" "" (const_int 4))
61
62(define_attr "type"
63  "alu,st,ld,control,multi,fpu"
64  (const_string "alu"))
65
66(define_attr "insn_support" "class1,sext,sfimm,shftimm,ror,rori" (const_string "class1"))
67
68(define_attr "enabled" ""
69  (cond [(eq_attr "insn_support" "class1") (const_int 1)
70	 (and (eq_attr "insn_support" "sext")
71	      (ne (symbol_ref "TARGET_SEXT") (const_int 0))) (const_int 1)
72	 (and (eq_attr "insn_support" "sfimm")
73	      (ne (symbol_ref "TARGET_SFIMM") (const_int 0))) (const_int 1)
74	 (and (eq_attr "insn_support" "shftimm")
75	      (ne (symbol_ref "TARGET_SHFTIMM") (const_int 0))) (const_int 1)
76	 (and (eq_attr "insn_support" "ror")
77	      (ne (symbol_ref "TARGET_ROR") (const_int 0))) (const_int 1)
78	 (and (eq_attr "insn_support" "rori")
79	      (ne (symbol_ref "TARGET_RORI") (const_int 0))) (const_int 1)]
80	(const_int 0)))
81
82;; Describe a user's asm statement.
83(define_asm_attributes
84  [(set_attr "type" "multi")])
85
86(define_automaton "or1k")
87(define_cpu_unit "cpu" "or1k")
88(define_insn_reservation "alu" 1
89  (eq_attr "type" "alu")
90  "cpu")
91(define_insn_reservation "st" 1
92  (eq_attr "type" "st")
93  "cpu")
94(define_insn_reservation "ld" 3
95  (eq_attr "type" "st")
96  "cpu")
97(define_insn_reservation "control" 1
98  (eq_attr "type" "control")
99  "cpu")
100(define_insn_reservation "fpu" 2
101  (eq_attr "type" "fpu")
102  "cpu")
103
104
105; Define delay slots for any branch
106(define_delay (eq_attr "type" "control")
107  [(eq_attr "type" "alu,st,ld") (nil) (nil)])
108
109;; -------------------------------------------------------------------------
110;; nop instruction
111;; -------------------------------------------------------------------------
112
113(define_insn "nop"
114  [(const_int 0)]
115  ""
116  "l.nop")
117
118;; -------------------------------------------------------------------------
119;; Arithmetic instructions
120;; -------------------------------------------------------------------------
121
122(define_insn "addsi3"
123  [(set (match_operand:SI 0 "register_operand" "=r,r")
124	  (plus:SI
125	   (match_operand:SI 1 "register_operand"   "%r,r")
126	   (match_operand:SI 2 "reg_or_s16_operand" " r,I")))]
127  ""
128  "@
129  l.add\t%0, %1, %2
130  l.addi\t%0, %1, %2")
131
132(define_insn "mulsi3"
133  [(set (match_operand:SI 0 "register_operand" "=r,r")
134	  (mult:SI
135	   (match_operand:SI 1 "register_operand"   "%r,r")
136	   (match_operand:SI 2 "reg_or_s16_operand" " r,I")))]
137  "!TARGET_SOFT_MUL"
138  "@
139  l.mul\t%0, %1, %2
140  l.muli\t%0, %1, %2")
141
142(define_insn "divsi3"
143  [(set (match_operand:SI 0 "register_operand" "=r")
144	  (div:SI
145	   (match_operand:SI 1 "register_operand" "r")
146	   (match_operand:SI 2 "register_operand" "r")))]
147  "!TARGET_SOFT_DIV"
148  "l.div\t%0, %1, %2")
149
150(define_insn "udivsi3"
151  [(set (match_operand:SI 0 "register_operand" "=r")
152	  (udiv:SI
153	   (match_operand:SI 1 "register_operand" "r")
154	   (match_operand:SI 2 "register_operand" "r")))]
155  "!TARGET_SOFT_DIV"
156  "l.divu\t%0, %1, %2")
157
158(define_insn "subsi3"
159  [(set (match_operand:SI 0 "register_operand" "=r")
160	  (minus:SI
161	   (match_operand:SI 1 "reg_or_0_operand" "rO")
162	   (match_operand:SI 2 "register_operand" "r")))]
163  ""
164  "l.sub\t%0, %r1, %2")
165
166;; -------------------------------------------------------------------------
167;; Floating Point Arithmetic instructions
168;; -------------------------------------------------------------------------
169
170;; Mode iterator for single/double float
171(define_mode_iterator F [(SF "TARGET_HARD_FLOAT")
172			 (DF "TARGET_DOUBLE_FLOAT")])
173(define_mode_attr f [(SF "s") (DF "d")])
174(define_mode_attr fr [(SF "r") (DF "d")])
175(define_mode_attr fi [(SF "si") (DF "di")])
176(define_mode_attr FI [(SF "SI") (DF "DI")])
177
178;; Basic arithmetic instructions
179(define_code_iterator FOP [plus minus mult div])
180(define_code_attr fop [(plus "add") (minus "sub") (mult "mul") (div "div")])
181
182(define_insn "<fop><F:mode>3"
183  [(set (match_operand:F 0 "register_operand" "=<fr>")
184	(FOP:F (match_operand:F 1 "register_operand" "<fr>")
185	       (match_operand:F 2 "register_operand" "<fr>")))]
186  "TARGET_HARD_FLOAT"
187  "lf.<fop>.<f>\t%d0, %d1, %d2"
188  [(set_attr "type" "fpu")])
189
190;; Basic float<->int conversion
191(define_insn "float<fi><F:mode>2"
192  [(set (match_operand:F 0 "register_operand" "=<fr>")
193	(float:F
194	    (match_operand:<FI> 1 "register_operand" "<fr>")))]
195  "TARGET_HARD_FLOAT"
196  "lf.itof.<f>\t%d0, %d1"
197  [(set_attr "type" "fpu")])
198
199(define_insn "fix_trunc<F:mode><fi>2"
200  [(set (match_operand:<FI> 0 "register_operand" "=<fr>")
201	(fix:<FI>
202	    (match_operand:F 1 "register_operand" "<fr>")))]
203  "TARGET_HARD_FLOAT"
204  "lf.ftoi.<f>\t%d0, %d1"
205  [(set_attr "type" "fpu")])
206
207;; -------------------------------------------------------------------------
208;; Logical operators
209;; -------------------------------------------------------------------------
210
211(define_code_iterator SHIFT  [ashift ashiftrt lshiftrt])
212(define_code_attr shift_op   [(ashift "ashl") (ashiftrt "ashr")
213			      (lshiftrt "lshr")])
214(define_code_attr shift_asm  [(ashift "sll") (ashiftrt "sra")
215			      (lshiftrt "srl")])
216
217(define_insn "<shift_op>si3"
218  [(set (match_operand:SI 0 "register_operand" "=r,r")
219	(SHIFT:SI (match_operand:SI 1 "register_operand"  "r,r")
220		  (match_operand:SI 2 "reg_or_u6_operand" "r,n")))]
221  ""
222  "@
223   l.<shift_asm>\t%0, %1, %2
224   l.<shift_asm>i\t%0, %1, %2"
225  [(set_attr "insn_support" "*,shftimm")])
226
227(define_insn "rotrsi3"
228  [(set (match_operand:SI 0 "register_operand" "=r,r")
229	(rotatert:SI (match_operand:SI 1 "register_operand"  "r,r")
230		     (match_operand:SI 2 "ror_reg_or_u6_operand" "r,n")))]
231  "TARGET_ROR || TARGET_RORI"
232  "@
233   l.ror\t%0, %1, %2
234   l.rori\t%0, %1, %2"
235  [(set_attr "insn_support" "ror,rori")])
236
237(define_insn "andsi3"
238  [(set (match_operand:SI 0 "register_operand" "=r,r")
239	  (and:SI
240	   (match_operand:SI 1 "register_operand"   "%r,r")
241	   (match_operand:SI 2 "reg_or_u16_operand" " r,K")))]
242  ""
243  "@
244  l.and\t%0, %1, %2
245  l.andi\t%0, %1, %2")
246
247(define_insn "xorsi3"
248  [(set (match_operand:SI 0 "register_operand" "=r,r")
249	  (xor:SI
250	   (match_operand:SI 1 "register_operand"   "%r,r")
251	   (match_operand:SI 2 "reg_or_s16_operand" " r,I")))]
252  ""
253  "@
254  l.xor\t%0, %1, %2
255  l.xori\t%0, %1, %2")
256
257(define_insn "iorsi3"
258  [(set (match_operand:SI 0 "register_operand" "=r,r")
259	  (ior:SI
260	   (match_operand:SI 1 "register_operand"   "%r,r")
261	   (match_operand:SI 2 "reg_or_u16_operand" " r,K")))]
262  ""
263  "@
264  l.or\t%0, %1, %2
265  l.ori\t%0, %1, %2")
266
267(define_expand "one_cmplsi2"
268  [(set (match_operand:SI 0 "register_operand" "")
269	(xor:SI (match_operand:SI 1 "register_operand" "") (const_int -1)))]
270  ""
271  "")
272
273;; -------------------------------------------------------------------------
274;; Move instructions
275;; -------------------------------------------------------------------------
276
277(define_mode_iterator I [QI HI SI])
278(define_mode_iterator I12 [QI HI])
279
280(define_mode_attr ldst [(QI "b") (HI "h") (SI "w")])
281(define_mode_attr zext_andi [(QI "0xff") (HI "0xffff")])
282
283(define_expand "mov<I:mode>"
284  [(set (match_operand:I 0 "nonimmediate_operand" "")
285	(match_operand:I 1 "general_operand" ""))]
286  ""
287{
288  or1k_expand_move (<MODE>mode, operands[0], operands[1]);
289  DONE;
290})
291
292;; 8-bit, 16-bit and 32-bit moves
293
294(define_insn "*mov<I:mode>_internal"
295  [(set (match_operand:I 0 "nonimmediate_operand" "=r,r,r,r, m,r")
296	(match_operand:I 1 "input_operand"        " r,M,K,I,rO,m"))]
297  "register_operand (operands[0], <I:MODE>mode)
298   || reg_or_0_operand (operands[1], <I:MODE>mode)"
299  "@
300   l.or\t%0, %1, %1
301   l.movhi\t%0, hi(%1)
302   l.ori\t%0, r0, %1
303   l.xori\t%0, r0, %1
304   l.s<I:ldst>\t%0, %r1
305   l.l<I:ldst>z\t%0, %1"
306  [(set_attr "type" "alu,alu,alu,alu,st,ld")])
307
308;; Hi/Low moves for constant and symbol loading
309
310(define_insn "movsi_high"
311  [(set (match_operand:SI 0 "register_operand" "=r")
312	(high:SI (match_operand:SI 1 "high_operand" "")))]
313  ""
314  "l.movhi\t%0, %h1"
315  [(set_attr "type" "alu")])
316
317(define_insn "*movsi_lo_sum_iori"
318  [(set (match_operand:SI 0 "register_operand" "=r")
319	(lo_sum:SI (match_operand:SI 1 "register_operand"  "r")
320		   (match_operand:SI 2 "losum_ior_operand" "")))]
321  ""
322  "l.ori\t%0, %1, %L2"
323  [(set_attr "type" "alu")])
324
325(define_insn "*movsi_lo_sum_addi"
326  [(set (match_operand:SI 0 "register_operand" "=r")
327	(lo_sum:SI (match_operand:SI 1 "register_operand"  "r")
328		   (match_operand:SI 2 "losum_add_operand" "")))]
329  ""
330  "l.addi\t%0, %1, %L2"
331  [(set_attr "type" "alu")])
332
333;; 64-bit moves
334;; ??? The clobber that emit_move_multi_word emits is arguably incorrect.
335;; Consider gcc.c-torture/execute/20030222-1.c, where a reg-reg DImode
336;; move gets register allocated to a no-op move.  At which point the
337;; we actively clobber the input.
338
339(define_expand "movdi"
340  [(set (match_operand:DI 0 "nonimmediate_operand" "")
341	(match_operand:DI 1 "general_operand" ""))]
342  ""
343{
344  if (MEM_P (operands[0]) && !const0_operand(operands[1], DImode))
345    operands[1] = force_reg (DImode, operands[1]);
346})
347
348(define_insn_and_split "*movdi"
349  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,o,r")
350	(match_operand:DI 1 "general_operand"      " r,o,rO,n"))]
351  "register_operand (operands[0], DImode)
352   || reg_or_0_operand (operands[1], DImode)"
353  "#"
354  ""
355  [(const_int 0)]
356{
357  rtx l0 = operand_subword (operands[0], 0, 0, DImode);
358  rtx l1 = operand_subword (operands[1], 0, 0, DImode);
359  rtx h0 = operand_subword (operands[0], 1, 0, DImode);
360  rtx h1 = operand_subword (operands[1], 1, 0, DImode);
361
362  if (reload_completed && reg_overlap_mentioned_p (l0, h1))
363    {
364      gcc_assert (!reg_overlap_mentioned_p (h0, l1));
365      emit_move_insn (h0, h1);
366      emit_move_insn (l0, l1);
367    }
368  else
369    {
370      emit_move_insn (l0, l1);
371      emit_move_insn (h0, h1);
372    }
373  DONE;
374})
375
376;; -------------------------------------------------------------------------
377;; Sign Extending
378;; -------------------------------------------------------------------------
379
380;; Zero extension can always be done with AND or an extending load.
381
382(define_insn "zero_extend<mode>si2"
383  [(set (match_operand:SI 0 "register_operand"                     "=r,r")
384	(zero_extend:SI (match_operand:I12 1 "reg_or_mem_operand" "r,m")))]
385  ""
386  "@
387   l.andi\t%0, %1, <zext_andi>
388   l.l<ldst>z\t%0, %1")
389
390;; Sign extension in registers is an optional extension, but the
391;; extending load is always available.  If SEXT is not available,
392;; force the middle-end to do the expansion to shifts.
393
394(define_insn "extend<mode>si2"
395  [(set (match_operand:SI 0 "register_operand"                      "=r,r")
396	(sign_extend:SI (match_operand:I12 1 "reg_or_mem_operand"  "r,m")))]
397  "TARGET_SEXT"
398  "@
399   l.ext<ldst>s\t%0, %1
400   l.l<ldst>s\t%0, %1")
401
402(define_insn "*extend<mode>si2_mem"
403  [(set (match_operand:SI 0 "register_operand"                "=r")
404	(sign_extend:SI (match_operand:I12 1 "memory_operand"  "m")))]
405  ""
406  "l.l<ldst>s\t%0, %1")
407
408;; -------------------------------------------------------------------------
409;; Compare instructions
410;; -------------------------------------------------------------------------
411
412;; OpenRISC supports these integer comparisons:
413;;
414;;     l.sfeq[i] - equality, r r or r i
415;;     l.sfne[i] - not equal, r r or r i
416;;     l.sflt{s,u}[i] - less than, signed or unsigned, r r or r i
417;;     l.sfle{s,u}[i] - less than or equal, signed or unsigned, r r or r i
418;;     l.sfgt{s,u}[i] - greater than, signed or unsigned, r r or r i
419;;     l.sfge{s,u}[i] - greater than or equal, signed or unsigned, r r or r i
420;;
421;;  EQ,NE,LT,LTU,LE,LEU,GT,GTU,GE,GEU
422;;  We iterate through all of these
423;;
424
425(define_code_iterator intcmpcc [ne eq lt ltu gt gtu ge le geu leu])
426(define_code_attr insn [(ne "ne") (eq "eq") (lt "lts") (ltu "ltu")
427			(gt "gts") (gtu "gtu") (ge "ges") (le "les")
428			(geu "geu") (leu "leu")])
429
430(define_insn "*sf_insn"
431  [(set (reg:BI SR_F_REGNUM)
432	(intcmpcc:BI (match_operand:SI 0 "reg_or_0_operand"   "rO,rO")
433		     (match_operand:SI 1 "reg_or_s16_operand" "r,I")))]
434  ""
435  "@
436   l.sf<insn>\t%r0, %1
437   l.sf<insn>i\t%r0, %1"
438  [(set_attr "insn_support" "*,sfimm")])
439
440;; Support FP comparisons too
441
442;; The OpenRISC FPU supports these comparisons:
443;;
444;;    lf.sfeq.{d,s} - equality, r r, double or single precision
445;;    lf.sfge.{d,s} - greater than or equal, r r, double or single precision
446;;    lf.sfgt.{d,s} - greater than, r r, double or single precision
447;;    lf.sfle.{d,s} - less than or equal, r r, double or single precision
448;;    lf.sflt.{d,s} - less than, r r, double or single precision
449;;    lf.sfne.{d,s} - not equal, r r, double or single precision
450;;
451;; Double precision is only supported on some hardware.  Only register/register
452;; comparisons are supported.  All comparisons are signed.
453
454(define_code_iterator fpcmpcc [ne eq lt gt ge le uneq unle unlt ungt unge
455			       unordered])
456(define_code_attr fpcmpinsn [(ne "ne") (eq "eq") (lt "lt") (gt "gt") (ge "ge")
457			     (le "le") (uneq "ueq") (unle "ule") (unlt "ult")
458			     (ungt "ugt") (unge "uge") (unordered "un")])
459
460
461(define_insn "*sf_fp_insn"
462  [(set (reg:BI SR_F_REGNUM)
463	(fpcmpcc:BI (match_operand:F 0 "register_operand" "<fr>")
464		    (match_operand:F 1 "register_operand" "<fr>")))]
465  "TARGET_HARD_FLOAT"
466  "lf.sf<fpcmpinsn>.<f>\t%d0, %d1"
467  [(set_attr "type" "fpu")])
468
469
470;; -------------------------------------------------------------------------
471;; Conditional Store instructions
472;; -------------------------------------------------------------------------
473
474(define_expand "cstoresi4"
475  [(set (match_operand:SI 0 "register_operand" "")
476	(if_then_else:SI
477	  (match_operator 1 "comparison_operator"
478	    [(match_operand:SI 2 "reg_or_0_operand" "")
479	     (match_operand:SI 3 "reg_or_s16_operand" "")])
480	  (match_dup 0)
481	  (const_int 0)))]
482  ""
483{
484  or1k_expand_compare (operands + 1);
485  PUT_MODE (operands[1], SImode);
486  emit_insn (gen_rtx_SET (operands[0], operands[1]));
487  DONE;
488})
489
490;; Support FP cstores too
491(define_expand "cstore<F:mode>4"
492  [(set (match_operand:SI 0 "register_operand" "")
493	(if_then_else:F
494	  (match_operator 1 "fp_comparison_operator"
495	    [(match_operand:F 2 "register_operand" "")
496	     (match_operand:F 3 "register_operand" "")])
497	  (match_dup 0)
498	  (const_int 0)))]
499  "TARGET_HARD_FLOAT"
500{
501  or1k_expand_compare (operands + 1);
502  PUT_MODE (operands[1], SImode);
503  emit_insn (gen_rtx_SET (operands[0], operands[1]));
504  DONE;
505})
506
507;; Being able to "copy" SR_F to a general register is helpful for
508;; the atomic insns, wherein the usual usage is to test the success
509;; of the compare-and-swap.  Representing the operation in this way,
510;; rather than exposing the cmov immediately, allows the optimizers
511;; to propagate the use of SR_F directly into a branch.
512
513(define_expand "sne_sr_f"
514  [(set (match_operand:SI 0 "register_operand" "=r")
515	(ne:SI (reg:BI SR_F_REGNUM) (const_int 0)))]
516  "")
517
518(define_insn_and_split "*scc"
519  [(set (match_operand:SI 0 "register_operand" "=r")
520	(match_operator:SI 1 "equality_comparison_operator"
521	  [(reg:BI SR_F_REGNUM) (const_int 0)]))]
522  ""
523  "#"
524  "reload_completed"
525  [(set (match_dup 0) (const_int 1))
526   (set (match_dup 0)
527	(if_then_else:SI (match_dup 1)
528	  (match_dup 0)
529	  (const_int 0)))]
530  "")
531
532(define_expand "mov<I:mode>cc"
533  [(set (match_operand:I 0 "register_operand" "")
534	(if_then_else:I (match_operand 1 "comparison_operator" "")
535	  (match_operand:I 2 "reg_or_0_operand" "")
536	  (match_operand:I 3 "reg_or_0_operand" "")))]
537  ""
538{
539  rtx xops[3] = { operands[1], XEXP (operands[1], 0), XEXP (operands[1], 1) };
540  or1k_expand_compare (xops);
541  operands[1] = xops[0];
542})
543
544(define_insn_and_split "*cmov<I:mode>"
545  [(set (match_operand:I 0 "register_operand" "=r")
546	(if_then_else:I
547	  (match_operator 3 "equality_comparison_operator"
548	    [(reg:BI SR_F_REGNUM) (const_int 0)])
549	  (match_operand:I 1 "reg_or_0_operand" "rO")
550	  (match_operand:I 2 "reg_or_0_operand" "rO")))]
551  ""
552{
553  return (GET_CODE (operands[3]) == NE
554	  ? "l.cmov\t%0, %r1, %r2"
555	  : "l.cmov\t%0, %r2, %r1");
556}
557  "!TARGET_CMOV"
558  [(const_int 0)]
559{
560  rtx x;
561  rtx label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
562
563  /* Generated a *cbranch pattern.  */
564  if (rtx_equal_p (operands[0], operands[2]))
565    {
566      PUT_CODE (operands[3], (GET_CODE (operands[3]) == NE) ? EQ : NE);
567      x = gen_rtx_IF_THEN_ELSE (VOIDmode, operands[3], label, pc_rtx);
568      emit_jump_insn (gen_rtx_SET (pc_rtx, x));
569      emit_move_insn (operands[0], operands[1]);
570    }
571  else
572    {
573      x = gen_rtx_IF_THEN_ELSE (VOIDmode, operands[3], label, pc_rtx);
574      emit_move_insn (operands[0], operands[1]);
575      emit_jump_insn (gen_rtx_SET (pc_rtx, x));
576      emit_move_insn (operands[0], operands[2]);
577    }
578
579  emit_label (XEXP (label, 0));
580  DONE;
581})
582
583;; -------------------------------------------------------------------------
584;; Branch instructions
585;; -------------------------------------------------------------------------
586
587(define_expand "cbranchsi4"
588  [(set (pc)
589	(if_then_else
590	  (match_operator 0 "comparison_operator"
591	    [(match_operand:SI 1 "reg_or_0_operand" "")
592	     (match_operand:SI 2 "reg_or_s16_operand" "")])
593	  (label_ref (match_operand 3 "" ""))
594	  (pc)))]
595  ""
596{
597  or1k_expand_compare (operands);
598})
599
600;; Support FP branching
601
602(define_expand "cbranch<F:mode>4"
603  [(set (pc)
604	(if_then_else
605	  (match_operator 0 "fp_comparison_operator"
606	    [(match_operand:F 1 "register_operand" "")
607	     (match_operand:F 2 "register_operand" "")])
608	  (label_ref (match_operand 3 "" ""))
609	  (pc)))]
610  "TARGET_HARD_FLOAT"
611{
612  or1k_expand_compare (operands);
613})
614
615(define_insn "*cbranch"
616  [(set (pc)
617	(if_then_else
618	  (match_operator 1 "equality_comparison_operator"
619	    [(reg:BI SR_F_REGNUM) (const_int 0)])
620	  (label_ref (match_operand 0 "" ""))
621	  (pc)))]
622  ""
623{
624  return (GET_CODE (operands[1]) == NE
625	  ? "l.bf\t%0%#"
626	  : "l.bnf\t%0%#");
627}
628  [(set_attr "type" "control")])
629
630;; -------------------------------------------------------------------------
631;; Jump instructions
632;; -------------------------------------------------------------------------
633
634(define_insn "jump"
635  [(set (pc) (label_ref (match_operand 0 "" "")))]
636  ""
637  "l.j\t%0%#"
638  [(set_attr "type" "control")])
639
640(define_insn "indirect_jump"
641  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
642  ""
643  "l.jr\t%0%#"
644  [(set_attr "type" "control")])
645
646;; -------------------------------------------------------------------------
647;; Prologue & Epilogue
648;; -------------------------------------------------------------------------
649
650(define_expand "prologue"
651  [(const_int 1)]
652  ""
653{
654  or1k_expand_prologue ();
655  DONE;
656})
657
658;; Expand epilogue as RTL
659(define_expand "epilogue"
660  [(return)]
661  ""
662{
663  or1k_expand_epilogue ();
664  emit_jump_insn (gen_simple_return ());
665  DONE;
666})
667
668(define_expand "sibcall_epilogue"
669  [(return)]
670  ""
671{
672  or1k_expand_epilogue ();
673  /* Placing a USE of LR here, rather than as a REG_USE on the
674     sibcall itself, means that LR is not unnecessarily live
675     within the function itself, which would force creation of
676     a stack frame.  */
677  emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, LR_REGNUM)));
678  DONE;
679})
680
681(define_expand "simple_return"
682  [(parallel [(simple_return) (use (match_dup 0))])]
683  ""
684{
685  operands[0] = gen_rtx_REG (Pmode, LR_REGNUM);
686})
687
688(define_insn "*simple_return"
689  [(simple_return)
690   (use (match_operand:SI 0 "register_operand" "r"))]
691  ""
692  "l.jr\t%0%#"
693  [(set_attr "type" "control")])
694
695(define_expand "eh_return"
696  [(use (match_operand 0 "general_operand"))]
697  ""
698{
699  or1k_expand_eh_return (operands[0]);
700  DONE;
701})
702
703;; This is a placeholder, during RA, in order to create the PIC regiter.
704;; We do this so that we don't unconditionally mark the LR register as
705;; clobbered.  It is replaced during prologue generation with the proper
706;; set_got pattern below.  This works because the set_got_tmp insn is the
707;; first insn in the stream and that it isn't moved during RA.
708(define_insn "set_got_tmp"
709  [(set (match_operand:SI 0 "register_operand" "=t")
710	(unspec_volatile:SI [(const_int 0)] UNSPECV_SET_GOT))]
711  ""
712{
713  gcc_unreachable ();
714})
715
716;; The insn to initialize the GOT.
717(define_insn "set_got"
718  [(set (match_operand:SI 0 "register_operand" "=t")
719	(unspec:SI [(const_int 0)] UNSPEC_SET_GOT))
720   (clobber (reg:SI LR_REGNUM))]
721  ""
722{
723  return ("l.jal\t8\;"
724	  " l.movhi\t%0, gotpchi(_GLOBAL_OFFSET_TABLE_-4)\;"
725	  "l.ori\t%0, %0, gotpclo(_GLOBAL_OFFSET_TABLE_+0)\;"
726	  "l.add\t%0, %0, r9");
727}
728  [(set_attr "length" "16")
729   (set_attr "type" "multi")])
730
731;; Block memory operations from being scheduled across frame (de)allocation.
732(define_insn "frame_addsi3"
733  [(set (match_operand:SI 0 "register_operand" "=r,r")
734	  (plus:SI
735	   (match_operand:SI 1 "register_operand"   "%r,r")
736	   (match_operand:SI 2 "reg_or_s16_operand" " r,I")))
737   (clobber (mem:BLK (scratch)))]
738  "reload_completed"
739  "@
740  l.add\t%0, %1, %2
741  l.addi\t%0, %1, %2")
742
743;; -------------------------------------------------------------------------
744;; Atomic Operations
745;; -------------------------------------------------------------------------
746
747;; Note that MULT stands in for the non-existant NAND rtx_code.
748(define_code_iterator FETCHOP [plus minus ior xor and mult])
749
750(define_code_attr fetchop_name
751  [(plus "add")
752   (minus "sub")
753   (ior "or")
754   (xor "xor")
755   (and "and")
756   (mult "nand")])
757
758(define_code_attr fetchop_pred
759  [(plus "reg_or_s16_operand")
760   (minus "register_operand")
761   (ior "reg_or_u16_operand")
762   (xor "reg_or_s16_operand")
763   (and "reg_or_u16_operand")
764   (mult "reg_or_u16_operand")])
765
766(define_expand "mem_thread_fence"
767  [(match_operand:SI 0 "const_int_operand" "")]		;; model
768  ""
769{
770  memmodel model = memmodel_base (INTVAL (operands[0]));
771  if (model != MEMMODEL_RELAXED)
772    emit_insn (gen_msync ());
773  DONE;
774})
775
776(define_expand "msync"
777  [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))]
778  ""
779{
780  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
781  MEM_VOLATILE_P (operands[0]) = 1;
782})
783
784(define_insn "*msync"
785  [(set (match_operand:BLK 0 "" "")
786	(unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))]
787  ""
788  "l.msync")
789
790(define_insn "load_locked_si"
791  [(set (match_operand:SI 0 "register_operand" "=r")
792	(unspec_volatile:SI
793	  [(match_operand:SI 1 "memory_operand" "m")] UNSPECV_LL))]
794  ""
795  "l.lwa\t%0,%1"
796  [(set_attr "type" "ld")])
797
798(define_insn "store_conditional_si"
799  [(set (reg:BI SR_F_REGNUM)
800	(unspec_volatile:BI [(const_int 0)] UNSPECV_SC))
801   (set (match_operand:SI 0 "memory_operand" "=m")
802	(match_operand:SI 1 "reg_or_0_operand" "rO"))]
803  ""
804  "l.swa\t%0,%r1"
805  [(set_attr "type" "st")])
806
807(define_expand "atomic_compare_and_swapsi"
808  [(match_operand:SI 0 "register_operand")   ;; bool output
809   (match_operand:SI 1 "register_operand")   ;; val output
810   (match_operand:SI 2 "memory_operand")     ;; memory
811   (match_operand:SI 3 "reg_or_s16_operand") ;; expected
812   (match_operand:SI 4 "reg_or_0_operand")   ;; desired
813   (match_operand:SI 5 "const_int_operand")  ;; is_weak
814   (match_operand:SI 6 "const_int_operand")  ;; mod_s
815   (match_operand:SI 7 "const_int_operand")] ;; mod_f
816  ""
817{
818  or1k_expand_atomic_compare_and_swap (operands);
819  DONE;
820})
821
822(define_expand "atomic_compare_and_swap<mode>"
823  [(match_operand:SI 0 "register_operand")   ;; bool output
824   (match_operand:I12 1 "register_operand")  ;; val output
825   (match_operand:I12 2 "memory_operand")    ;; memory
826   (match_operand:I12 3 "register_operand")  ;; expected
827   (match_operand:I12 4 "reg_or_0_operand")  ;; desired
828   (match_operand:SI 5 "const_int_operand")  ;; is_weak
829   (match_operand:SI 6 "const_int_operand")  ;; mod_s
830   (match_operand:SI 7 "const_int_operand")] ;; mod_f
831  ""
832{
833  or1k_expand_atomic_compare_and_swap_qihi (operands);
834  DONE;
835})
836
837(define_expand "atomic_exchangesi"
838  [(match_operand:SI 0 "register_operand")	;; output
839   (match_operand:SI 1 "memory_operand")	;; memory
840   (match_operand:SI 2 "reg_or_0_operand")	;; input
841   (match_operand:SI 3 "const_int_operand")]	;; model
842  ""
843{
844  or1k_expand_atomic_exchange (operands);
845  DONE;
846})
847
848(define_expand "atomic_exchange<mode>"
849  [(match_operand:I12 0 "register_operand")	;; output
850   (match_operand:I12 1 "memory_operand")	;; memory
851   (match_operand:I12 2 "reg_or_0_operand")	;; input
852   (match_operand:SI 3 "const_int_operand")]	;; model
853  ""
854{
855  or1k_expand_atomic_exchange_qihi (operands);
856  DONE;
857})
858
859(define_expand "atomic_<fetchop_name>si"
860  [(match_operand:SI 0 "memory_operand")	;; memory
861   (FETCHOP:SI (match_dup 0)
862     (match_operand:SI 1 "<fetchop_pred>"))	;; operand
863   (match_operand:SI 2 "const_int_operand")]	;; model
864  ""
865{
866  or1k_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL);
867  DONE;
868})
869
870(define_expand "atomic_<fetchop_name><mode>"
871  [(match_operand:I12 0 "memory_operand")	;; memory
872   (FETCHOP:I12 (match_dup 0)
873     (match_operand:I12 1 "register_operand"))	;; operand
874   (match_operand:SI 2 "const_int_operand")]	;; model
875  ""
876{
877  or1k_expand_atomic_op_qihi (<CODE>, operands[0], operands[1], NULL, NULL);
878  DONE;
879})
880
881(define_expand "atomic_fetch_<fetchop_name>si"
882  [(match_operand:SI 0 "register_operand" "")		;; output
883   (match_operand:SI 1 "memory_operand" "")		;; memory
884   (FETCHOP:SI (match_dup 1)
885     (match_operand:SI 2 "<fetchop_pred>" ""))		;; operand
886   (match_operand:SI 3 "const_int_operand" "")]		;; model
887  ""
888{
889  or1k_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL);
890  DONE;
891})
892
893(define_expand "atomic_fetch_<fetchop_name><mode>"
894  [(match_operand:I12 0 "register_operand" "")		;; output
895   (match_operand:I12 1 "memory_operand" "")		;; memory
896   (FETCHOP:I12 (match_dup 1)
897     (match_operand:I12 2 "<fetchop_pred>" ""))		;; operand
898   (match_operand:SI 3 "const_int_operand" "")]		;; model
899  ""
900{
901  or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2],
902			      operands[0], NULL);
903  DONE;
904})
905
906(define_expand "atomic_<fetchop_name>_fetchsi"
907  [(match_operand:SI 0 "register_operand" "")		;; output
908   (match_operand:SI 1 "memory_operand" "")		;; memory
909   (FETCHOP:SI (match_dup 1)
910     (match_operand:SI 2 "<fetchop_pred>" ""))		;; operand
911   (match_operand:SI 3 "const_int_operand" "")]		;; model
912  ""
913{
914  or1k_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0]);
915  DONE;
916})
917
918(define_expand "atomic_<fetchop_name>_fetch<mode>"
919  [(match_operand:I12 0 "register_operand" "")		;; output
920   (match_operand:I12 1 "memory_operand" "")		;; memory
921   (FETCHOP:I12 (match_dup 1)
922     (match_operand:I12 2 "<fetchop_pred>" ""))	;; operand
923   (match_operand:SI 3 "const_int_operand" "")]		;; model
924  ""
925{
926  or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2],
927			      NULL, operands[0]);
928  DONE;
929})
930
931;; -------------------------------------------------------------------------
932;; Call Instructions
933;; -------------------------------------------------------------------------
934
935;; Leave these to last, as the modeless operand for call_value
936;; interferes with normal patterns.
937
938(define_expand "call"
939  [(call (match_operand 0) (match_operand 1))]
940  ""
941{
942  or1k_expand_call (NULL, operands[0], operands[1], false);
943  DONE;
944})
945
946(define_expand "sibcall"
947  [(call (match_operand 0) (match_operand 1))]
948  ""
949{
950  or1k_expand_call (NULL, operands[0], operands[1], true);
951  DONE;
952})
953
954(define_expand "call_value"
955  [(set (match_operand 0) (call (match_operand 1) (match_operand 2)))]
956  ""
957{
958  or1k_expand_call (operands[0], operands[1], operands[2], false);
959  DONE;
960})
961
962(define_expand "sibcall_value"
963  [(set (match_operand 0) (call (match_operand 1) (match_operand 2)))]
964  ""
965{
966  or1k_expand_call (operands[0], operands[1], operands[2], true);
967  DONE;
968})
969
970(define_insn "*call"
971  [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "r,s"))
972	 (match_operand 1))
973   (clobber (reg:SI LR_REGNUM))]
974  "!SIBLING_CALL_P (insn)"
975  "@
976   l.jalr\t%0%#
977   l.jal\t%P0%#"
978  [(set_attr "type" "control")])
979
980(define_insn "*sibcall"
981  [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "c,s"))
982	 (match_operand 1))]
983  "SIBLING_CALL_P (insn)"
984  "@
985   l.jr\t%0%#
986   l.j\t%P0%#"
987  [(set_attr "type" "control")])
988
989(define_insn "*call_value"
990  [(set (match_operand 0)
991	(call (mem:SI (match_operand:SI 1 "call_insn_operand" "r,s"))
992	      (match_operand 2)))
993   (clobber (reg:SI LR_REGNUM))]
994  "!SIBLING_CALL_P (insn)"
995  "@
996   l.jalr\t%1%#
997   l.jal\t%P1%#"
998  [(set_attr "type" "control")])
999
1000(define_insn "*sibcall_value"
1001  [(set (match_operand 0)
1002	(call (mem:SI (match_operand:SI 1 "call_insn_operand" "c,s"))
1003	      (match_operand 2)))]
1004  "SIBLING_CALL_P (insn)"
1005  "@
1006   l.jr\t%1%#
1007   l.j\t%P1%#"
1008  [(set_attr "type" "control")])
1009