1;; Copyright (C) 2013-2018 Free Software Foundation, Inc.
2;;
3;; micromips.md   Machine Description for the microMIPS instruction set
4;; This file is part of GCC.
5
6;; GCC is free software; you can redistribute it and/or modify it
7;; under the terms of the GNU General Public License as published
8;; by the Free Software Foundation; either version 3, or (at your
9;; option) any later version.
10
11;; GCC is distributed in the hope that it will be useful, but WITHOUT
12;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14;; License for more details.
15
16;; You should have received a copy of the GNU General Public License
17;; along with GCC; see the file COPYING3.  If not see
18;; <http://www.gnu.org/licenses/>.
19
20(define_insn "*store_word_multiple"
21  [(match_parallel 0 ""
22       [(set (match_operand:SI 1 "memory_operand")
23	     (match_operand:SI 2 "register_operand"))])]
24  "TARGET_MICROMIPS
25   && umips_save_restore_pattern_p (true, operands[0])"
26  { return umips_output_save_restore (true, operands[0]); }
27  [(set_attr "type" "multimem")
28   (set_attr "mode" "SI")
29   (set_attr "can_delay" "no")])
30
31(define_insn "*load_word_multiple"
32  [(match_parallel 0 ""
33       [(set (match_operand:SI 1 "register_operand")
34	     (match_operand:SI 2 "memory_operand"))])]
35  "TARGET_MICROMIPS
36   && umips_save_restore_pattern_p (false, operands[0])"
37  { return umips_output_save_restore (false, operands[0]); }
38  [(set_attr "type" "multimem")
39   (set_attr "mode" "SI")
40   (set_attr "can_delay" "no")])
41
42;; For LWP.
43(define_peephole2
44  [(set (match_operand:SI 0 "d_operand" "")
45        (match_operand:SI 1 "non_volatile_mem_operand" ""))
46   (set (match_operand:SI 2 "d_operand" "")
47        (match_operand:SI 3 "non_volatile_mem_operand" ""))]
48  "TARGET_MICROMIPS
49   && umips_load_store_pair_p (true, operands)"
50  [(parallel [(set (match_dup 0) (match_dup 1))
51              (set (match_dup 2) (match_dup 3))])])
52
53;; The behavior of the LWP insn is undefined if placed in a delay slot.
54(define_insn "*lwp"
55  [(parallel [(set (match_operand:SI 0 "d_operand")
56		   (match_operand:SI 1 "non_volatile_mem_operand"))
57	      (set (match_operand:SI 2 "d_operand")
58		   (match_operand:SI 3 "non_volatile_mem_operand"))])]
59
60  "TARGET_MICROMIPS
61   && umips_load_store_pair_p (true, operands)"
62{
63  umips_output_load_store_pair (true, operands);
64  return "";
65}
66  [(set_attr "type" "load")
67   (set_attr "mode" "SI")
68   (set_attr "can_delay" "no")])
69
70;; For SWP.
71(define_peephole2
72  [(set (match_operand:SI 0 "non_volatile_mem_operand" "")
73        (match_operand:SI 1 "d_operand" ""))
74   (set (match_operand:SI 2 "non_volatile_mem_operand" "")
75        (match_operand:SI 3 "d_operand" ""))]
76  "TARGET_MICROMIPS
77   && umips_load_store_pair_p (false, operands)"
78  [(parallel [(set (match_dup 0) (match_dup 1))
79              (set (match_dup 2) (match_dup 3))])])
80
81;; The behavior of the SWP insn is undefined if placed in a delay slot.
82(define_insn "*swp"
83  [(set (match_operand:SI 0 "non_volatile_mem_operand")
84	(match_operand:SI 1 "d_operand"))
85   (set (match_operand:SI 2 "non_volatile_mem_operand")
86	(match_operand:SI 3 "d_operand"))]
87  "TARGET_MICROMIPS
88   && umips_load_store_pair_p (false, operands)"
89{
90  umips_output_load_store_pair (false, operands);
91  return "";
92}
93  [(set_attr "type" "store")
94   (set_attr "mode" "SI")
95   (set_attr "can_delay" "no")])
96
97;; For JRADDIUSP.
98(define_insn "jraddiusp"
99  [(return)
100   (use (reg:SI 31))
101   (set (reg:SI 29)
102	(plus:SI (reg:SI 29)
103		 (match_operand 0 "uw5_operand")))]
104  "TARGET_MICROMIPS"
105  "jraddiusp\t%0"
106  [(set_attr "type"	"trap")
107   (set_attr "can_delay" "no")
108   (set_attr "mode"	"SI")])
109
110;; For MOVEP.
111(define_peephole2
112  [(set (match_operand:MOVEP1 0 "register_operand" "")
113        (match_operand:MOVEP1 1 "movep_src_operand" ""))
114   (set (match_operand:MOVEP2 2 "register_operand" "")
115        (match_operand:MOVEP2 3 "movep_src_operand" ""))]
116  "TARGET_MICROMIPS
117   && umips_movep_target_p (operands[0], operands[2])"
118  [(parallel [(set (match_dup 0) (match_dup 1))
119              (set (match_dup 2) (match_dup 3))])])
120
121;; The behavior of the MOVEP insn is undefined if placed in a delay slot.
122(define_insn "*movep<MOVEP1:mode><MOVEP2:mode>"
123  [(set (match_operand:MOVEP1 0 "register_operand")
124	(match_operand:MOVEP1 1 "movep_src_operand"))
125   (set (match_operand:MOVEP2 2 "register_operand")
126	(match_operand:MOVEP2 3 "movep_src_operand"))]
127  "TARGET_MICROMIPS
128   && umips_movep_target_p (operands[0], operands[2])"
129{
130  if (REGNO (operands[0]) < REGNO (operands[2]))
131    return "movep\t%0,%2,%z1,%z3";
132  else
133    return "movep\t%2,%0,%z3,%z1";
134}
135  [(set_attr "type" "move")
136   (set_attr "mode" "<MODE>")
137   (set_attr "can_delay" "no")])
138