OSDN Git Service

* config/m32c/cond.md (cbranch<mode>4): Defer splitting until after reload.
[pf3gnuchains/gcc-fork.git] / gcc / config / m32c / cond.md
1 ;; Machine Descriptions for R8C/M16C/M32C
2 ;; Copyright (C) 2005
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Red Hat.
5 ;;
6 ;; This file is part of GCC.
7 ;;
8 ;; GCC is free software; you can redistribute it and/or modify it
9 ;; under the terms of the GNU General Public License as published
10 ;; by the Free Software Foundation; either version 2, or (at your
11 ;; option) any later version.
12 ;;
13 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
14 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16 ;; 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 COPYING.  If not, write to the Free
20 ;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21 ;; 02110-1301, USA.
22
23 ; conditionals - cmp, jcc, setcc, etc.
24
25 ; Special note about conditional instructions: GCC always emits the
26 ; compare right before the insn, which is good, because m32c's mov
27 ; insns modify the flags.  However, this means that any conditional
28 ; insn that may require reloading must be kept with its compare until
29 ; after reload finishes, else the reload insns might clobber the
30 ; flags.  Thus, these rules:
31 ;
32 ; * the cmp* expanders just save the operands in compare_op0 and
33 ;   compare_op1 via m32c_pend_compare.
34 ; * conditional insns that won't need reload can call
35 ;   m32c_unpend_compare before their expansion.
36 ; * other insns must expand to include the compare operands within,
37 ;   then split after reload to a separate compare and conditional.
38
39 ; Until support for relaxing is supported in gas, we must assume that
40 ; short labels won't reach, so we must use long labels.
41 ; Unfortunately, there aren't any conditional jumps with long labels,
42 ; so instead we invert the conditional and jump around a regular jump.
43
44 ; Note that we can, at some point in the future, add code to omit the
45 ; "cmp" portion of the insn if the preceding insn happened to set the
46 ; right flags already.  For example, a mov followed by a "cmp *,0" is
47 ; redundant; the move already set the Z flag.
48
49 (define_insn_and_split "cbranch<mode>4"
50   [(set (pc) (if_then_else
51               (match_operator 0 "m32c_cmp_operator"
52                               [(match_operand:QHPSI 1 "mra_operand" "RraSd")
53                                (match_operand:QHPSI 2 "mrai_operand" "iRraSd")])
54               (label_ref (match_operand 3 "" ""))
55               (pc)))]
56   ""
57   "#"
58   "reload_completed"
59   [(set (reg:CC FLG_REGNO)
60         (compare (match_dup 1)
61                  (match_dup 2)))
62    (set (pc) (if_then_else (match_dup 4)
63                            (label_ref (match_dup 3))
64                            (pc)))]
65   "operands[4] = m32c_cmp_flg_0 (operands[0]);"
66   )
67
68 (define_insn "stzx_16"
69   [(set (match_operand:QI 0 "mrai_operand" "=R0w,R0w,R0w")
70         (if_then_else:QI (eq (reg:CC FLG_REGNO) (const_int 0))
71                          (match_operand:QI 1 "const_int_operand" "i,i,0")
72                          (match_operand:QI 2 "const_int_operand" "i,0,i")))]
73   "TARGET_A16 && reload_completed"
74   "@
75    stzx\t%1,%2,%0
76    stz\t%1,%0
77    stnz\t%2,%0"
78   [(set_attr "flags" "n,n,n")]
79 )
80
81 (define_insn "stzx_24_<mode>"
82   [(set (match_operand:QHI 0 "mrai_operand" "=RraSd,RraSd,RraSd")
83         (if_then_else:QHI (eq (reg:CC FLG_REGNO) (const_int 0))
84                          (match_operand:QHI 1 "const_int_operand" "i,i,0")
85                          (match_operand:QHI 2 "const_int_operand" "i,0,i")))]
86   "TARGET_A24 && reload_completed"
87   "@
88    stzx.<bwl>\t%1,%2,%0
89    stz.<bwl>\t%1,%0
90    stnz.<bwl>\t%2,%0"
91   [(set_attr "flags" "n,n,n")])
92
93 (define_insn_and_split "stzx_reversed_<mode>"
94   [(set (match_operand:QHI 0 "m32c_r0_operand" "")
95         (if_then_else:QHI (ne (reg:CC FLG_REGNO) (const_int 0))
96                          (match_operand:QHI 1 "const_int_operand" "")
97                          (match_operand:QHI 2 "const_int_operand" "")))]
98   "(TARGET_A24 || GET_MODE (operands[0]) == QImode) && reload_completed"
99   "#"
100   ""
101   [(set (match_dup 0)
102         (if_then_else:QHI (eq (reg:CC FLG_REGNO) (const_int 0))
103                       (match_dup 2)
104                       (match_dup 1)))]
105   ""
106   )
107
108
109 (define_insn "cmp<mode>_op"
110   [(set (reg:CC FLG_REGNO)
111         (compare (match_operand:QHPSI 0 "mra_operand" "RraSd")
112                  (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))]
113   ""
114   "* return m32c_output_compare(insn, operands); "
115   [(set_attr "flags" "oszc")])
116
117 (define_expand "cmp<mode>"
118   [(set (reg:CC FLG_REGNO)
119         (compare (match_operand:QHPSI 0 "mra_operand" "RraSd")
120                  (match_operand:QHPSI 1 "mrai_operand" "RraSdi")))]
121   ""
122   "m32c_pend_compare (operands); DONE;")
123
124 (define_insn "b<code>_op"
125   [(set (pc)
126         (if_then_else (any_cond (reg:CC FLG_REGNO)
127                                 (const_int 0))
128                       (label_ref (match_operand 0 ""))
129                       (pc)))]
130   ""
131   "j<code>\t%l0"
132   [(set_attr "flags" "n")]
133 )
134
135 (define_expand "b<code>"
136   [(set (pc)
137         (if_then_else (any_cond (reg:CC FLG_REGNO)
138                                 (const_int 0))
139                       (label_ref (match_operand 0 ""))
140                       (pc)))]
141   ""
142   "m32c_unpend_compare ();"
143 )
144
145 ;; m32c_conditional_register_usage changes the setcc_gen_code array to
146 ;; point to the _24 variants if needed.
147
148 ;; We need to keep the compare and conditional sets together through
149 ;; reload, because reload might need to add address reloads to the
150 ;; set, which would clobber the flags.  By keeping them together, the
151 ;; reloads get put before the compare, thus preserving the flags.
152
153 ;; These are the post-split patterns for the conditional sets.
154
155 (define_insn "s<code>_op"
156   [(set (match_operand:QI 0 "register_operand" "=Rqi")
157         (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))]
158   "TARGET_A16 && reload_completed"
159   "* return m32c_scc_pattern(operands, <CODE>);")
160
161 (define_insn "s<code>_24_op"
162   [(set (match_operand:HI 0 "mra_operand" "=RhiSd")
163         (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))]
164   "TARGET_A24 && reload_completed"
165   "sc<code>\t%0"
166   [(set_attr "flags" "n")]
167 )
168
169 ;; These are the pre-split patterns for the conditional sets.  Yes,
170 ;; there are a lot of permutations.
171
172 (define_insn_and_split "s<code>_<mode>"
173   [(set (match_operand:QI 0 "register_operand" "=Rqi")
174         (any_cond:QI (match_operand:QHPSI 1 "mra_operand" "RraSd")
175                      (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))]
176   "TARGET_A16"
177   "#"
178   "reload_completed"
179   [(set (reg:CC FLG_REGNO)
180         (compare (match_dup 1)
181                  (match_dup 2)))
182    (set (match_dup 0)
183         (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))]
184   ""
185   [(set_attr "flags" "x")]
186 )
187
188 (define_insn_and_split "s<code>_<mode>_24"
189   [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd")
190         (any_cond:HI (match_operand:QHPSI 1 "mra_operand" "RraSd")
191                      (match_operand:QHPSI 2 "mrai_operand" "RraSdi")))]
192   "TARGET_A24"
193   "#"
194   "reload_completed"
195   [(set (reg:CC FLG_REGNO)
196         (compare (match_dup 1)
197                  (match_dup 2)))
198    (set (match_dup 0)
199         (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))]
200   ""
201   [(set_attr "flags" "x")]
202 )
203
204 (define_insn_and_split "movqicc_<code>_<mode>"
205   [(set (match_operand:QI 0 "register_operand" "")
206         (if_then_else:QI (eqne_cond:QI (match_operand:QHPSI 1 "mra_operand" "RraSd")
207                                        (match_operand:QHPSI 2 "mrai_operand" "RraSdi"))
208                           (match_operand:QI 3 "const_int_operand" "")
209                           (match_operand:QI 4 "const_int_operand" "")))]
210   ""
211   "#"
212   "reload_completed"
213   [(set (reg:CC FLG_REGNO)
214         (compare (match_dup 1)
215                  (match_dup 2)))
216    (set (match_dup 0)
217         (if_then_else:QI (eqne_cond:QI (reg:CC FLG_REGNO) (const_int 0))
218                          (match_dup 3)
219                          (match_dup 4)))]
220   ""
221   [(set_attr "flags" "x")]
222   )
223
224 (define_insn_and_split "movhicc_<code>_<mode>"
225   [(set (match_operand:HI 0 "register_operand" "")
226         (if_then_else:HI (eqne_cond:HI (match_operand:QHPSI 1 "mra_operand" "RraSd")
227                                        (match_operand:QHPSI 2 "mrai_operand" "RraSdi"))
228                           (match_operand:QI 3 "const_int_operand" "")
229                           (match_operand:QI 4 "const_int_operand" "")))]
230   "TARGET_A24"
231   "#"
232   "reload_completed"
233   [(set (reg:CC FLG_REGNO)
234         (compare (match_dup 1)
235                  (match_dup 2)))
236    (set (match_dup 0)
237         (if_then_else:HI (eqne_cond:HI (reg:CC FLG_REGNO) (const_int 0))
238                          (match_dup 3)
239                          (match_dup 4)))]
240   ""
241   [(set_attr "flags" "x")]
242   )
243
244 ;; And these are the expanders, which read the pending compare
245 ;; operands to build a combined insn.
246
247 (define_expand "s<code>"
248   [(set (match_operand:QI 0 "register_operand" "=Rqi")
249         (any_cond:QI (reg:CC FLG_REGNO) (const_int 0)))]
250   "TARGET_A16"
251   "m32c_expand_scc (<CODE>, operands); DONE;")
252
253 (define_expand "s<code>_24"
254   [(set (match_operand:HI 0 "mra_nopp_operand" "=RhiSd")
255         (any_cond:HI (reg:CC FLG_REGNO) (const_int 0)))]
256   "TARGET_A24"
257   "m32c_expand_scc (<CODE>, operands); DONE;")
258
259
260 (define_expand "movqicc"
261   [(set (match_operand:QI 0 "register_operand" "")
262         (if_then_else:QI (match_operand 1 "m32c_eqne_operator" "")
263                          (match_operand:QI 2 "const_int_operand" "")
264                          (match_operand:QI 3 "const_int_operand" "")))]
265   ""
266   "if (m32c_expand_movcc(operands))
267      FAIL;
268    DONE;"
269 )
270
271 (define_expand "movhicc"
272   [(set (match_operand:HI 0 "mra_operand" "")
273         (if_then_else:HI (match_operand 1 "m32c_eqne_operator" "")
274                          (match_operand:HI 2 "const_int_operand" "")
275                          (match_operand:HI 3 "const_int_operand" "")))]
276   "TARGET_A24"
277   "if (m32c_expand_movcc(operands))
278      FAIL;
279    DONE;"
280 )
281
282
283 ;; CMP opcodes subtract two values, set the flags, and discard the
284 ;; value.  This pattern recovers the sign of the discarded value based
285 ;; on the flags.  Operand 0 is set to -1, 0, or 1.  This is used for
286 ;; the cmpstr pattern.  For optimal code, this should be removed if
287 ;; followed by a suitable CMP insn (see the peephole following).  This
288 ;; pattern is 7 bytes and 5 cycles.  If you don't need specific
289 ;; values, a 5/4 pattern can be made with SCGT and BMLT to set the
290 ;; appropriate bits.
291
292 (define_insn "cond_to_int"
293   [(set (match_operand:HI 0 "mra_qi_operand" "=Rqi")
294         (if_then_else:HI (lt (reg:CC FLG_REGNO) (const_int 0))
295                          (const_int -1)
296                          (if_then_else:HI (eq (reg:CC FLG_REGNO) (const_int 0))
297                                           (const_int 0)
298                                           (const_int -1))))]
299   "TARGET_A24"
300   "sceq\t%0\n\tbmgt\t1,%h0\n\tdec.w\t%0"
301   [(set_attr "flags" "x")]
302   )  
303
304 ;; A cond_to_int followed by a compare against zero is essentially a no-op.
305
306 (define_peephole2
307   [(set (match_operand:HI 0 "mra_qi_operand" "")
308         (if_then_else:HI (lt (reg:CC FLG_REGNO) (const_int 0))
309                          (const_int -1)
310                          (if_then_else:HI (eq (reg:CC FLG_REGNO) (const_int 0))
311                                           (const_int 0)
312                                           (const_int -1))))
313    (set (reg:CC FLG_REGNO)
314         (compare (match_operand:HI 1 "mra_qi_operand" "")
315                  (const_int 0)))
316    ]
317   "rtx_equal_p(operands[0], operands[1])"
318   [(const_int 1)]
319   "")