[PR testsuite/116860] Testsuite adjustment for recently added tests
[official-gcc.git] / gcc / config / or1k / or1k.md
blob627e40084b34bcd4913cd4d1ffb7d4275df3d1c7
1 ;; Machine description for OpenRISC
2 ;; Copyright (C) 2018-2025 Free Software Foundation, Inc.
3 ;; Contributed by Stafford Horne
5 ;; This file is part of GCC.
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.
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.
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/>.
21 ;; -------------------------------------------------------------------------
22 ;; OpenRISC specific constraints, predicates and attributes
23 ;; -------------------------------------------------------------------------
25 (include "constraints.md")
26 (include "predicates.md")
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)]
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
51 (define_c_enum "unspecv" [
52   UNSPECV_SET_GOT
53   UNSPECV_LL
54   UNSPECV_SC
57 ;; Instruction scheduler
59 ; Most instructions are 4 bytes long.
60 (define_attr "length" "" (const_int 4))
62 (define_attr "type"
63   "alu,st,ld,control,multi,fpu"
64   (const_string "alu"))
66 (define_attr "insn_support" "class1,sext,sfimm,shftimm,ror,rori" (const_string "class1"))
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)))
82 ;; Describe a user's asm statement.
83 (define_asm_attributes
84   [(set_attr "type" "multi")])
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")
105 ; Define delay slots for any branch
106 (define_delay (eq_attr "type" "control")
107   [(eq_attr "type" "alu,st,ld") (nil) (nil)])
109 ;; -------------------------------------------------------------------------
110 ;; nop instruction
111 ;; -------------------------------------------------------------------------
113 (define_insn "nop"
114   [(const_int 0)]
115   ""
116   "l.nop")
118 ;; -------------------------------------------------------------------------
119 ;; Arithmetic instructions
120 ;; -------------------------------------------------------------------------
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")
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")
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")
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")
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")
166 ;; -------------------------------------------------------------------------
167 ;; Floating Point Arithmetic instructions
168 ;; -------------------------------------------------------------------------
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")])
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")])
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")])
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")])
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")])
207 ;; -------------------------------------------------------------------------
208 ;; Logical operators
209 ;; -------------------------------------------------------------------------
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")])
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")])
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")])
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")
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")
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")
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   "")
273 ;; -------------------------------------------------------------------------
274 ;; Move instructions
275 ;; -------------------------------------------------------------------------
277 (define_mode_iterator I [QI HI SI])
278 (define_mode_iterator I12 [QI HI])
280 (define_mode_attr ldst [(QI "b") (HI "h") (SI "w")])
281 (define_mode_attr zext_andi [(QI "0xff") (HI "0xffff")])
283 (define_expand "mov<I:mode>"
284   [(set (match_operand:I 0 "nonimmediate_operand" "")
285         (match_operand:I 1 "general_operand" ""))]
286   ""
288   or1k_expand_move (<MODE>mode, operands[0], operands[1]);
289   DONE;
292 ;; 8-bit, 16-bit and 32-bit moves
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")])
308 ;; Hi/Low moves for constant and symbol loading
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")])
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")])
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")])
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.
339 (define_expand "movdi"
340   [(set (match_operand:DI 0 "nonimmediate_operand" "")
341         (match_operand:DI 1 "general_operand" ""))]
342   ""
344   if (MEM_P (operands[0]) && !const0_operand(operands[1], DImode))
345     operands[1] = force_reg (DImode, operands[1]);
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   "&& 1"
355   [(const_int 0)]
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);
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;
376 ;; -------------------------------------------------------------------------
377 ;; Sign Extending
378 ;; -------------------------------------------------------------------------
380 ;; Zero extension can always be done with AND or an extending load.
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")
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.
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")
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")
408 ;; -------------------------------------------------------------------------
409 ;; Compare instructions
410 ;; -------------------------------------------------------------------------
412 ;; OpenRISC supports these integer comparisons:
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
421 ;;  EQ,NE,LT,LTU,LE,LEU,GT,GTU,GE,GEU
422 ;;  We iterate through all of these
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")])
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")])
440 ;; Support FP comparisons too
442 ;; The OpenRISC FPU supports these comparisons:
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
451 ;; Double precision is only supported on some hardware.  Only register/register
452 ;; comparisons are supported.  All comparisons are signed.
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")])
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")])
470 ;; -------------------------------------------------------------------------
471 ;; Conditional Store instructions
472 ;; -------------------------------------------------------------------------
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   ""
484   or1k_expand_compare (operands + 1);
485   PUT_MODE (operands[1], SImode);
486   emit_insn (gen_rtx_SET (operands[0], operands[1]));
487   DONE;
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"
501   or1k_expand_compare (operands + 1);
502   PUT_MODE (operands[1], SImode);
503   emit_insn (gen_rtx_SET (operands[0], operands[1]));
504   DONE;
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.
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   "")
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   "")
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   ""
539   rtx xops[3] = { operands[1], XEXP (operands[1], 0), XEXP (operands[1], 1) };
540   or1k_expand_compare (xops);
541   operands[1] = xops[0];
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   ""
553   return (GET_CODE (operands[3]) == NE
554           ? "l.cmov\t%0, %r1, %r2"
555           : "l.cmov\t%0, %r2, %r1");
557   "!TARGET_CMOV"
558   [(const_int 0)]
560   rtx x;
561   rtx label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
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     }
579   emit_label (XEXP (label, 0));
580   DONE;
583 ;; -------------------------------------------------------------------------
584 ;; Branch instructions
585 ;; -------------------------------------------------------------------------
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   ""
597   or1k_expand_compare (operands);
600 ;; Support FP branching
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"
612   or1k_expand_compare (operands);
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   ""
624   return (GET_CODE (operands[1]) == NE
625           ? "l.bf\t%0%#"
626           : "l.bnf\t%0%#");
628   [(set_attr "type" "control")])
630 ;; -------------------------------------------------------------------------
631 ;; Jump instructions
632 ;; -------------------------------------------------------------------------
634 (define_insn "jump"
635   [(set (pc) (label_ref (match_operand 0 "" "")))]
636   ""
637   "l.j\t%0%#"
638   [(set_attr "type" "control")])
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")])
646 ;; -------------------------------------------------------------------------
647 ;; Prologue & Epilogue
648 ;; -------------------------------------------------------------------------
650 (define_expand "prologue"
651   [(const_int 1)]
652   ""
654   or1k_expand_prologue ();
655   DONE;
658 ;; Expand epilogue as RTL
659 (define_expand "epilogue"
660   [(return)]
661   ""
663   or1k_expand_epilogue ();
664   emit_jump_insn (gen_simple_return ());
665   DONE;
668 (define_expand "sibcall_epilogue"
669   [(return)]
670   ""
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;
681 (define_expand "simple_return"
682   [(parallel [(simple_return) (use (match_dup 0))])]
683   ""
685   operands[0] = gen_rtx_REG (Pmode, LR_REGNUM);
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")])
695 (define_expand "eh_return"
696   [(use (match_operand 0 "general_operand"))]
697   ""
699   or1k_expand_eh_return (operands[0]);
700   DONE;
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   ""
713   gcc_unreachable ();
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   ""
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");
728   [(set_attr "length" "16")
729    (set_attr "type" "multi")])
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")
743 ;; -------------------------------------------------------------------------
744 ;; Atomic Operations
745 ;; -------------------------------------------------------------------------
747 ;; Note that MULT stands in for the non-existant NAND rtx_code.
748 (define_code_iterator FETCHOP [plus minus ior xor and mult])
750 (define_code_attr fetchop_name
751   [(plus "add")
752    (minus "sub")
753    (ior "or")
754    (xor "xor")
755    (and "and")
756    (mult "nand")])
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")])
766 (define_expand "mem_thread_fence"
767   [(match_operand:SI 0 "const_int_operand" "")]         ;; model
768   ""
770   memmodel model = memmodel_base (INTVAL (operands[0]));
771   if (model != MEMMODEL_RELAXED)
772     emit_insn (gen_msync ());
773   DONE;
776 (define_expand "msync"
777   [(set (match_dup 0) (unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))]
778   ""
780   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
781   MEM_VOLATILE_P (operands[0]) = 1;
784 (define_insn "*msync"
785   [(set (match_operand:BLK 0 "" "")
786         (unspec:BLK [(match_dup 0)] UNSPEC_MSYNC))]
787   ""
788   "l.msync")
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")])
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")])
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   ""
818   or1k_expand_atomic_compare_and_swap (operands);
819   DONE;
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   ""
833   or1k_expand_atomic_compare_and_swap_qihi (operands);
834   DONE;
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   ""
844   or1k_expand_atomic_exchange (operands);
845   DONE;
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   ""
855   or1k_expand_atomic_exchange_qihi (operands);
856   DONE;
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   ""
866   or1k_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL);
867   DONE;
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   ""
877   or1k_expand_atomic_op_qihi (<CODE>, operands[0], operands[1], NULL, NULL);
878   DONE;
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   ""
889   or1k_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL);
890   DONE;
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   ""
901   or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2],
902                               operands[0], NULL);
903   DONE;
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   ""
914   or1k_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0]);
915   DONE;
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   ""
926   or1k_expand_atomic_op_qihi (<CODE>, operands[1], operands[2],
927                               NULL, operands[0]);
928   DONE;
931 ;; -------------------------------------------------------------------------
932 ;; Call Instructions
933 ;; -------------------------------------------------------------------------
935 ;; Leave these to last, as the modeless operand for call_value
936 ;; interferes with normal patterns.
938 (define_expand "call"
939   [(call (match_operand 0) (match_operand 1))]
940   ""
942   or1k_expand_call (NULL, operands[0], operands[1], false);
943   DONE;
946 (define_expand "sibcall"
947   [(call (match_operand 0) (match_operand 1))]
948   ""
950   or1k_expand_call (NULL, operands[0], operands[1], true);
951   DONE;
954 (define_expand "call_value"
955   [(set (match_operand 0) (call (match_operand 1) (match_operand 2)))]
956   ""
958   or1k_expand_call (operands[0], operands[1], operands[2], false);
959   DONE;
962 (define_expand "sibcall_value"
963   [(set (match_operand 0) (call (match_operand 1) (match_operand 2)))]
964   ""
966   or1k_expand_call (operands[0], operands[1], operands[2], true);
967   DONE;
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")])
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")])
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")])
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")])