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