]>
Commit | Line | Data |
---|---|---|
1f92da87 | 1 | ;; Machine description of the Renesas M32R cpu for GNU C compiler |
99dee823 | 2 | ;; Copyright (C) 1996-2021 Free Software Foundation, Inc. |
8c5ca3b9 | 3 | |
7ec022b2 | 4 | ;; This file is part of GCC. |
8c5ca3b9 | 5 | |
1f92da87 NC |
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 | |
2f83c7d6 | 8 | ;; by the Free Software Foundation; either version 3, or (at your |
1f92da87 | 9 | ;; option) any later version. |
8c5ca3b9 | 10 | |
1f92da87 NC |
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. | |
8c5ca3b9 DE |
15 | |
16 | ;; You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
17 | ;; along with GCC; see the file COPYING3. If not see |
18 | ;; <http://www.gnu.org/licenses/>. | |
8c5ca3b9 DE |
19 | |
20 | ;; See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
8c5ca3b9 | 21 | \f |
a2ab189d KH |
22 | ;; UNSPEC_VOLATILE usage |
23 | (define_constants | |
24 | [(UNSPECV_BLOCKAGE 0) | |
25 | (UNSPECV_FLUSH_ICACHE 1)]) | |
26 | ||
27 | ;; UNSPEC usage | |
28 | (define_constants | |
29 | [(UNSPEC_LOAD_SDA_BASE 2) | |
30 | (UNSPEC_SET_CBIT 3) | |
31 | (UNSPEC_PIC_LOAD_ADDR 4) | |
c331bf08 KI |
32 | (UNSPEC_GET_PC 5) |
33 | (UNSPEC_GOTOFF 6) | |
34 | ]) | |
a2ab189d | 35 | |
8c5ca3b9 | 36 | ;; Insn type. Used to default other attribute values. |
8c5ca3b9 | 37 | (define_attr "type" |
5b8ae21f | 38 | "int2,int4,load2,load4,load8,store2,store4,store8,shift2,shift4,mul2,div4,uncond_branch,branch,call,multi,misc" |
8c5ca3b9 DE |
39 | (const_string "misc")) |
40 | ||
41 | ;; Length in bytes. | |
42 | (define_attr "length" "" | |
5b8ae21f | 43 | (cond [(eq_attr "type" "int2,load2,store2,shift2,mul2") |
8c5ca3b9 DE |
44 | (const_int 2) |
45 | ||
5b8ae21f MM |
46 | (eq_attr "type" "int4,load4,store4,shift4,div4") |
47 | (const_int 4) | |
8c5ca3b9 DE |
48 | |
49 | (eq_attr "type" "multi") | |
50 | (const_int 8) | |
51 | ||
52 | (eq_attr "type" "uncond_branch,branch,call") | |
53 | (const_int 4)] | |
54 | ||
55 | (const_int 4))) | |
56 | ||
57 | ;; The length here is the length of a single asm. Unfortunately it might be | |
58 | ;; 2 or 4 so we must allow for 4. That's ok though. | |
59 | (define_asm_attributes | |
60 | [(set_attr "length" "4") | |
61 | (set_attr "type" "multi")]) | |
2b7972b0 | 62 | |
5ad6fca5 | 63 | ;; Whether an instruction is short (16-bit) or long (32-bit). |
2b7972b0 | 64 | (define_attr "insn_size" "short,long" |
5b8ae21f | 65 | (if_then_else (eq_attr "type" "int2,load2,store2,shift2,mul2") |
2b7972b0 MM |
66 | (const_string "short") |
67 | (const_string "long"))) | |
68 | ||
5ad6fca5 SB |
69 | ;; The target CPU we're compiling for. |
70 | (define_attr "cpu" "m32r,m32r2,m32rx" | |
f18d1d16 | 71 | (cond [(match_test "TARGET_M32RX") |
5ad6fca5 | 72 | (const_string "m32rx") |
f18d1d16 | 73 | (match_test "TARGET_M32R2") |
5ad6fca5 SB |
74 | (const_string "m32r2")] |
75 | (const_string "m32r"))) | |
76 | ||
77 | ;; Defines the pipeline where an instruction can be executed on. | |
78 | ;; For the M32R, a short instruction can execute one of the two pipes. | |
79 | ;; For the M32Rx, the restrictions are modelled in the second | |
18d7916e NC |
80 | ;; condition of this attribute definition. |
81 | (define_attr "m32r_pipeline" "either,s,o,long" | |
5ad6fca5 SB |
82 | (cond [(and (eq_attr "cpu" "m32r") |
83 | (eq_attr "insn_size" "short")) | |
84 | (const_string "either") | |
de41e41c | 85 | (eq_attr "insn_size" "!short") |
5ad6fca5 | 86 | (const_string "long")] |
18d7916e | 87 | (cond [(eq_attr "type" "int2") |
5ad6fca5 | 88 | (const_string "either") |
18d7916e | 89 | (eq_attr "type" "load2,store2,shift2,uncond_branch,branch,call") |
5ad6fca5 | 90 | (const_string "o") |
18d7916e | 91 | (eq_attr "type" "mul2") |
5ad6fca5 | 92 | (const_string "s")] |
18d7916e | 93 | (const_string "long")))) |
8c5ca3b9 | 94 | \f |
2b7972b0 MM |
95 | ;; :::::::::::::::::::: |
96 | ;; :: | |
5ad6fca5 | 97 | ;; :: Pipeline description |
2b7972b0 MM |
98 | ;; :: |
99 | ;; :::::::::::::::::::: | |
100 | ||
5ad6fca5 SB |
101 | ;; This model is based on Chapter 2, Appendix 3 and Appendix 4 of the |
102 | ;; "M32R-FPU Software Manual", Revision 1.01, plus additional information | |
103 | ;; obtained by our best friend and mine, Google. | |
104 | ;; | |
105 | ;; The pipeline is modelled as a fetch unit, and a core with a memory unit, | |
106 | ;; two execution units, where "fetch" models IF and D, "memory" for MEM1 | |
107 | ;; and MEM2, and "EXEC" for E, E1, E2, EM, and EA. Writeback and | |
108 | ;; bypasses are not modelled. | |
109 | (define_automaton "m32r") | |
110 | ||
111 | ;; We pretend there are two short (16 bits) instruction fetchers. The | |
112 | ;; "s" short fetcher cannot be reserved until the "o" short fetcher is | |
113 | ;; reserved. Some instructions reserve both the left and right fetchers. | |
114 | ;; These fetch units are a hack to get GCC to better pack the instructions | |
115 | ;; for the M32Rx processor, which has two execution pipes. | |
116 | ;; | |
85f65093 KH |
117 | ;; In reality there is only one decoder, which can decode either two 16-bit |
118 | ;; instructions, or a single 32-bit instruction. | |
2b7972b0 | 119 | ;; |
5ad6fca5 | 120 | ;; Note, "fetch" models both the IF and the D pipeline stages. |
2b7972b0 | 121 | ;; |
5ad6fca5 SB |
122 | ;; The m32rx core has two execution pipes. We name them o_E and s_E. |
123 | ;; In addition, there's a memory unit. | |
124 | ||
125 | (define_cpu_unit "o_IF,s_IF,o_E,s_E,memory" "m32r") | |
126 | ||
127 | ;; Prevent the s pipe from being reserved before the o pipe. | |
18d7916e NC |
128 | (absence_set "s_IF" "o_IF") |
129 | (absence_set "s_E" "o_E") | |
5ad6fca5 SB |
130 | |
131 | ;; On the M32Rx, long instructions execute on both pipes, so reserve | |
132 | ;; both fetch slots and both pipes. | |
133 | (define_reservation "long_IF" "o_IF+s_IF") | |
134 | (define_reservation "long_E" "o_E+s_E") | |
135 | ||
136 | ;; :::::::::::::::::::: | |
137 | ||
138 | ;; Simple instructions do 4 stages: IF D E WB. WB is not modelled. | |
139 | ;; Hence, ready latency is 1. | |
140 | (define_insn_reservation "short_left" 1 | |
141 | (and (eq_attr "m32r_pipeline" "o") | |
142 | (and (eq_attr "insn_size" "short") | |
143 | (eq_attr "type" "!load2"))) | |
144 | "o_IF,o_E") | |
145 | ||
146 | (define_insn_reservation "short_right" 1 | |
147 | (and (eq_attr "m32r_pipeline" "s") | |
5b8ae21f MM |
148 | (and (eq_attr "insn_size" "short") |
149 | (eq_attr "type" "!load2"))) | |
5ad6fca5 | 150 | "s_IF,s_E") |
8c5ca3b9 | 151 | |
5ad6fca5 SB |
152 | (define_insn_reservation "short_either" 1 |
153 | (and (eq_attr "m32r_pipeline" "either") | |
154 | (and (eq_attr "insn_size" "short") | |
155 | (eq_attr "type" "!load2"))) | |
156 | "o_IF|s_IF,o_E|s_E") | |
8c5ca3b9 | 157 | |
5ad6fca5 SB |
158 | (define_insn_reservation "long_m32r" 1 |
159 | (and (eq_attr "cpu" "m32r") | |
5b8ae21f MM |
160 | (and (eq_attr "insn_size" "long") |
161 | (eq_attr "type" "!load4,load8"))) | |
5ad6fca5 | 162 | "long_IF,long_E") |
5b8ae21f | 163 | |
5ad6fca5 SB |
164 | (define_insn_reservation "long_m32rx" 2 |
165 | (and (eq_attr "m32r_pipeline" "long") | |
de41e41c BE |
166 | (and (eq_attr "insn_size" "long") |
167 | (eq_attr "type" "!load4,load8"))) | |
5ad6fca5 SB |
168 | "long_IF,long_E") |
169 | ||
170 | ;; Load/store instructions do 6 stages: IF D E MEM1 MEM2 WB. | |
171 | ;; MEM1 may require more than one cycle depending on locality. We | |
19525b57 | 172 | ;; optimistically assume all memory is nearby, i.e. MEM1 takes only |
5ad6fca5 SB |
173 | ;; one cycle. Hence, ready latency is 3. |
174 | ||
175 | ;; The M32Rx can do short load/store only on the left pipe. | |
176 | (define_insn_reservation "short_load_left" 3 | |
177 | (and (eq_attr "m32r_pipeline" "o") | |
178 | (and (eq_attr "insn_size" "short") | |
179 | (eq_attr "type" "load2"))) | |
180 | "o_IF,o_E,memory*2") | |
de41e41c | 181 | |
5ad6fca5 SB |
182 | (define_insn_reservation "short_load" 3 |
183 | (and (eq_attr "m32r_pipeline" "either") | |
184 | (and (eq_attr "insn_size" "short") | |
185 | (eq_attr "type" "load2"))) | |
186 | "s_IF|o_IF,s_E|o_E,memory*2") | |
187 | ||
188 | (define_insn_reservation "long_load" 3 | |
189 | (and (eq_attr "cpu" "m32r") | |
de41e41c BE |
190 | (and (eq_attr "insn_size" "long") |
191 | (eq_attr "type" "load4,load8"))) | |
5ad6fca5 SB |
192 | "long_IF,long_E,memory*2") |
193 | ||
194 | (define_insn_reservation "long_load_m32rx" 3 | |
195 | (and (eq_attr "m32r_pipeline" "long") | |
196 | (eq_attr "type" "load4,load8")) | |
197 | "long_IF,long_E,memory*2") | |
198 | ||
8c5ca3b9 | 199 | \f |
22a14e0d | 200 | (include "predicates.md") |
fbaeb717 | 201 | (include "constraints.md") |
e2265be0 | 202 | |
8c5ca3b9 | 203 | ;; Expand prologue as RTL |
5b8ae21f MM |
204 | (define_expand "prologue" |
205 | [(const_int 1)] | |
206 | "" | |
207 | " | |
208 | { | |
209 | m32r_expand_prologue (); | |
210 | DONE; | |
211 | }") | |
212 | ||
e2265be0 KK |
213 | ;; Expand epilogue as RTL |
214 | (define_expand "epilogue" | |
215 | [(return)] | |
216 | "" | |
217 | " | |
218 | { | |
219 | m32r_expand_epilogue (); | |
220 | emit_jump_insn (gen_return_normal ()); | |
221 | DONE; | |
222 | }") | |
8c5ca3b9 DE |
223 | \f |
224 | ;; Move instructions. | |
225 | ;; | |
226 | ;; For QI and HI moves, the register must contain the full properly | |
227 | ;; sign-extended value. nonzero_bits assumes this [otherwise | |
228 | ;; SHORT_IMMEDIATES_SIGN_EXTEND must be used, but the comment for it | |
229 | ;; says it's a kludge and the .md files should be fixed instead]. | |
230 | ||
231 | (define_expand "movqi" | |
232 | [(set (match_operand:QI 0 "general_operand" "") | |
233 | (match_operand:QI 1 "general_operand" ""))] | |
234 | "" | |
235 | " | |
236 | { | |
ad126521 KI |
237 | /* Fixup PIC cases. */ |
238 | if (flag_pic) | |
239 | { | |
240 | if (symbolic_operand (operands[1], QImode)) | |
241 | { | |
242 | if (reload_in_progress || reload_completed) | |
243 | operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); | |
244 | else | |
245 | operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); | |
246 | } | |
247 | } | |
248 | ||
8c5ca3b9 DE |
249 | /* Everything except mem = const or mem = mem can be done easily. |
250 | Objects in the small data area are handled too. */ | |
251 | ||
d000f0d9 | 252 | if (MEM_P (operands[0])) |
8c5ca3b9 DE |
253 | operands[1] = force_reg (QImode, operands[1]); |
254 | }") | |
255 | ||
256 | (define_insn "*movqi_insn" | |
5b8ae21f MM |
257 | [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,r,r,T,m") |
258 | (match_operand:QI 1 "move_src_operand" "r,I,JQR,T,m,r,r"))] | |
8c5ca3b9 DE |
259 | "register_operand (operands[0], QImode) || register_operand (operands[1], QImode)" |
260 | "@ | |
261 | mv %0,%1 | |
262 | ldi %0,%#%1 | |
263 | ldi %0,%#%1 | |
264 | ldub %0,%1 | |
5b8ae21f MM |
265 | ldub %0,%1 |
266 | stb %1,%0 | |
8c5ca3b9 | 267 | stb %1,%0" |
5b8ae21f MM |
268 | [(set_attr "type" "int2,int2,int4,load2,load4,store2,store4") |
269 | (set_attr "length" "2,2,4,2,4,2,4")]) | |
8c5ca3b9 DE |
270 | |
271 | (define_expand "movhi" | |
272 | [(set (match_operand:HI 0 "general_operand" "") | |
273 | (match_operand:HI 1 "general_operand" ""))] | |
274 | "" | |
275 | " | |
276 | { | |
ad126521 KI |
277 | /* Fixup PIC cases. */ |
278 | if (flag_pic) | |
279 | { | |
280 | if (symbolic_operand (operands[1], HImode)) | |
281 | { | |
282 | if (reload_in_progress || reload_completed) | |
283 | operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); | |
284 | else | |
285 | operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); | |
286 | } | |
287 | } | |
288 | ||
8c5ca3b9 DE |
289 | /* Everything except mem = const or mem = mem can be done easily. */ |
290 | ||
d000f0d9 | 291 | if (MEM_P (operands[0])) |
8c5ca3b9 DE |
292 | operands[1] = force_reg (HImode, operands[1]); |
293 | }") | |
294 | ||
295 | (define_insn "*movhi_insn" | |
5b8ae21f MM |
296 | [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,r,r,r,T,m") |
297 | (match_operand:HI 1 "move_src_operand" "r,I,JQR,K,T,m,r,r"))] | |
8c5ca3b9 DE |
298 | "register_operand (operands[0], HImode) || register_operand (operands[1], HImode)" |
299 | "@ | |
300 | mv %0,%1 | |
301 | ldi %0,%#%1 | |
302 | ldi %0,%#%1 | |
303 | ld24 %0,%#%1 | |
304 | lduh %0,%1 | |
5b8ae21f MM |
305 | lduh %0,%1 |
306 | sth %1,%0 | |
8c5ca3b9 | 307 | sth %1,%0" |
5b8ae21f MM |
308 | [(set_attr "type" "int2,int2,int4,int4,load2,load4,store2,store4") |
309 | (set_attr "length" "2,2,4,4,2,4,2,4")]) | |
310 | ||
311 | (define_expand "movsi_push" | |
312 | [(set (mem:SI (pre_dec:SI (match_operand:SI 0 "register_operand" ""))) | |
313 | (match_operand:SI 1 "register_operand" ""))] | |
314 | "" | |
315 | "") | |
316 | ||
317 | (define_expand "movsi_pop" | |
318 | [(set (match_operand:SI 0 "register_operand" "") | |
319 | (mem:SI (post_inc:SI (match_operand:SI 1 "register_operand" ""))))] | |
320 | "" | |
321 | "") | |
8c5ca3b9 DE |
322 | |
323 | (define_expand "movsi" | |
324 | [(set (match_operand:SI 0 "general_operand" "") | |
325 | (match_operand:SI 1 "general_operand" ""))] | |
326 | "" | |
327 | " | |
328 | { | |
ad126521 KI |
329 | /* Fixup PIC cases. */ |
330 | if (flag_pic) | |
331 | { | |
332 | if (symbolic_operand (operands[1], SImode)) | |
333 | { | |
334 | if (reload_in_progress || reload_completed) | |
335 | operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); | |
336 | else | |
337 | operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); | |
338 | } | |
339 | } | |
340 | ||
4d6c607f | 341 | /* Everything except mem = const or mem = mem can be done easily. */ |
8c5ca3b9 | 342 | |
d000f0d9 | 343 | if (MEM_P (operands[0])) |
8c5ca3b9 DE |
344 | operands[1] = force_reg (SImode, operands[1]); |
345 | ||
4d6c607f | 346 | /* Small Data Area reference? */ |
8c5ca3b9 DE |
347 | if (small_data_operand (operands[1], SImode)) |
348 | { | |
349 | emit_insn (gen_movsi_sda (operands[0], operands[1])); | |
350 | DONE; | |
351 | } | |
4d6c607f DE |
352 | |
353 | /* If medium or large code model, symbols have to be loaded with | |
354 | seth/add3. */ | |
355 | if (addr32_operand (operands[1], SImode)) | |
8c5ca3b9 DE |
356 | { |
357 | emit_insn (gen_movsi_addr32 (operands[0], operands[1])); | |
358 | DONE; | |
359 | } | |
360 | }") | |
361 | ||
4b6bb562 | 362 | ;; ??? Do we need a const_double constraint here for large unsigned values? |
5b8ae21f | 363 | (define_insn "*movsi_insn" |
56e2e762 | 364 | [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,r,r,r,r,r,r,T,S,m") |
5b8ae21f | 365 | (match_operand:SI 1 "move_src_operand" "r,I,J,MQ,L,n,T,U,m,r,r,r"))] |
8c5ca3b9 | 366 | "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" |
5b8ae21f MM |
367 | "* |
368 | { | |
d000f0d9 | 369 | if (REG_P (operands[0]) || GET_CODE (operands[1]) == SUBREG) |
5b8ae21f MM |
370 | { |
371 | switch (GET_CODE (operands[1])) | |
372 | { | |
5b8ae21f MM |
373 | default: |
374 | break; | |
375 | ||
376 | case REG: | |
377 | case SUBREG: | |
378 | return \"mv %0,%1\"; | |
379 | ||
380 | case MEM: | |
56e2e762 NC |
381 | if (GET_CODE (XEXP (operands[1], 0)) == POST_INC |
382 | && XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx) | |
383 | return \"pop %0\"; | |
384 | ||
5b8ae21f MM |
385 | return \"ld %0,%1\"; |
386 | ||
387 | case CONST_INT: | |
fbaeb717 | 388 | if (satisfies_constraint_J (operands[1])) |
5b8ae21f MM |
389 | return \"ldi %0,%#%1\\t; %X1\"; |
390 | ||
fbaeb717 | 391 | if (satisfies_constraint_M (operands[1])) |
5b8ae21f MM |
392 | return \"ld24 %0,%#%1\\t; %X1\"; |
393 | ||
fbaeb717 | 394 | if (satisfies_constraint_L (operands[1])) |
5b8ae21f MM |
395 | return \"seth %0,%#%T1\\t; %X1\"; |
396 | ||
397 | return \"#\"; | |
398 | ||
399 | case CONST: | |
400 | case SYMBOL_REF: | |
401 | case LABEL_REF: | |
402 | if (TARGET_ADDR24) | |
403 | return \"ld24 %0,%#%1\"; | |
404 | ||
405 | return \"#\"; | |
406 | } | |
407 | } | |
408 | ||
d000f0d9 SZ |
409 | else if (MEM_P (operands[0]) |
410 | && (REG_P (operands[1]) || GET_CODE (operands[1]) == SUBREG)) | |
56e2e762 NC |
411 | { |
412 | if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC | |
413 | && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx) | |
414 | return \"push %1\"; | |
415 | ||
416 | return \"st %1,%0\"; | |
417 | } | |
5b8ae21f | 418 | |
75c3cfba | 419 | gcc_unreachable (); |
5b8ae21f MM |
420 | }" |
421 | [(set_attr "type" "int2,int2,int4,int4,int4,multi,load2,load2,load4,store2,store2,store4") | |
422 | (set_attr "length" "2,2,4,4,4,8,2,2,4,2,2,4")]) | |
8c5ca3b9 | 423 | |
4d6c607f DE |
424 | ; Try to use a four byte / two byte pair for constants not loadable with |
425 | ; ldi, ld24, seth. | |
426 | ||
427 | (define_split | |
428 | [(set (match_operand:SI 0 "register_operand" "") | |
429 | (match_operand:SI 1 "two_insn_const_operand" ""))] | |
430 | "" | |
431 | [(set (match_dup 0) (match_dup 2)) | |
432 | (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 3)))] | |
433 | " | |
434 | { | |
435 | unsigned HOST_WIDE_INT val = INTVAL (operands[1]); | |
436 | unsigned HOST_WIDE_INT tmp; | |
437 | int shift; | |
438 | ||
439 | /* In all cases we will emit two instructions. However we try to | |
4b6bb562 | 440 | use 2 byte instructions wherever possible. We can assume the |
4d6c607f DE |
441 | constant isn't loadable with any of ldi, ld24, or seth. */ |
442 | ||
85f65093 | 443 | /* See if we can load a 24-bit unsigned value and invert it. */ |
4d6c607f DE |
444 | if (UINT24_P (~ val)) |
445 | { | |
446 | emit_insn (gen_movsi (operands[0], GEN_INT (~ val))); | |
447 | emit_insn (gen_one_cmplsi2 (operands[0], operands[0])); | |
448 | DONE; | |
449 | } | |
450 | ||
85f65093 | 451 | /* See if we can load a 24-bit unsigned value and shift it into place. |
4d6c607f DE |
452 | 0x01fffffe is just beyond ld24's range. */ |
453 | for (shift = 1, tmp = 0x01fffffe; | |
454 | shift < 8; | |
455 | ++shift, tmp <<= 1) | |
456 | { | |
457 | if ((val & ~tmp) == 0) | |
458 | { | |
459 | emit_insn (gen_movsi (operands[0], GEN_INT (val >> shift))); | |
460 | emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (shift))); | |
461 | DONE; | |
462 | } | |
463 | } | |
464 | ||
737e7965 JW |
465 | /* Can't use any two byte insn, fall back to seth/or3. Use ~0xffff instead |
466 | of 0xffff0000, since the later fails on a 64-bit host. */ | |
467 | operands[2] = GEN_INT ((val) & ~0xffff); | |
4d6c607f DE |
468 | operands[3] = GEN_INT ((val) & 0xffff); |
469 | }") | |
470 | ||
5b8ae21f MM |
471 | (define_split |
472 | [(set (match_operand:SI 0 "register_operand" "") | |
a98dd5bb | 473 | (match_operand:SI 1 "seth_add3_operand" ""))] |
5b8ae21f MM |
474 | "TARGET_ADDR32" |
475 | [(set (match_dup 0) | |
476 | (high:SI (match_dup 1))) | |
477 | (set (match_dup 0) | |
478 | (lo_sum:SI (match_dup 0) | |
479 | (match_dup 1)))] | |
480 | "") | |
481 | ||
8c5ca3b9 DE |
482 | ;; Small data area support. |
483 | ;; The address of _SDA_BASE_ is loaded into a register and all objects in | |
484 | ;; the small data area are indexed off that. This is done for each reference | |
485 | ;; but cse will clean things up for us. We let the compiler choose the | |
486 | ;; register to use so we needn't allocate (and maybe even fix) a special | |
85f65093 | 487 | ;; register to use. Since the load and store insns have a 16-bit offset the |
8c5ca3b9 DE |
488 | ;; total size of the data area can be 64K. However, if the data area lives |
489 | ;; above 16M (24 bits), _SDA_BASE_ will have to be loaded with seth/add3 which | |
490 | ;; would then yield 3 instructions to reference an object [though there would | |
491 | ;; be no net loss if two or more objects were referenced]. The 3 insns can be | |
492 | ;; reduced back to 2 if the size of the small data area were reduced to 32K | |
493 | ;; [then seth + ld/st would work for any object in the area]. Doing this | |
494 | ;; would require special handling of _SDA_BASE_ (its value would be | |
495 | ;; (.sdata + 32K) & 0xffff0000) and reloc computations would be different | |
4b6bb562 | 496 | ;; [I think]. What to do about this is deferred until later and for now we |
8c5ca3b9 DE |
497 | ;; require .sdata to be in the first 16M. |
498 | ||
499 | (define_expand "movsi_sda" | |
500 | [(set (match_dup 2) | |
bd5ca07e | 501 | (unspec:SI [(const_int 0)] UNSPEC_LOAD_SDA_BASE)) |
8c5ca3b9 DE |
502 | (set (match_operand:SI 0 "register_operand" "") |
503 | (lo_sum:SI (match_dup 2) | |
504 | (match_operand:SI 1 "small_data_operand" "")))] | |
505 | "" | |
506 | " | |
507 | { | |
508 | if (reload_in_progress || reload_completed) | |
509 | operands[2] = operands[0]; | |
510 | else | |
511 | operands[2] = gen_reg_rtx (SImode); | |
512 | }") | |
513 | ||
91c18512 KI |
514 | (define_insn "*load_sda_base_32" |
515 | [(set (match_operand:SI 0 "register_operand" "=r") | |
516 | (unspec:SI [(const_int 0)] UNSPEC_LOAD_SDA_BASE))] | |
517 | "TARGET_ADDR32" | |
518 | "seth %0,%#shigh(_SDA_BASE_)\;add3 %0,%0,%#low(_SDA_BASE_)" | |
519 | [(set_attr "type" "multi") | |
520 | (set_attr "length" "8")]) | |
521 | ||
8c5ca3b9 DE |
522 | (define_insn "*load_sda_base" |
523 | [(set (match_operand:SI 0 "register_operand" "=r") | |
a2ab189d | 524 | (unspec:SI [(const_int 0)] UNSPEC_LOAD_SDA_BASE))] |
8c5ca3b9 DE |
525 | "" |
526 | "ld24 %0,#_SDA_BASE_" | |
5b8ae21f MM |
527 | [(set_attr "type" "int4") |
528 | (set_attr "length" "4")]) | |
8c5ca3b9 | 529 | |
85f65093 | 530 | ;; 32-bit address support. |
8c5ca3b9 DE |
531 | |
532 | (define_expand "movsi_addr32" | |
533 | [(set (match_dup 2) | |
534 | ; addr32_operand isn't used because it's too restrictive, | |
535 | ; seth_add3_operand is more general and thus safer. | |
536 | (high:SI (match_operand:SI 1 "seth_add3_operand" ""))) | |
537 | (set (match_operand:SI 0 "register_operand" "") | |
538 | (lo_sum:SI (match_dup 2) (match_dup 1)))] | |
539 | "" | |
540 | " | |
541 | { | |
542 | if (reload_in_progress || reload_completed) | |
543 | operands[2] = operands[0]; | |
544 | else | |
545 | operands[2] = gen_reg_rtx (SImode); | |
546 | }") | |
547 | ||
548 | (define_insn "set_hi_si" | |
549 | [(set (match_operand:SI 0 "register_operand" "=r") | |
550 | (high:SI (match_operand 1 "symbolic_operand" "")))] | |
551 | "" | |
552 | "seth %0,%#shigh(%1)" | |
5b8ae21f MM |
553 | [(set_attr "type" "int4") |
554 | (set_attr "length" "4")]) | |
8c5ca3b9 DE |
555 | |
556 | (define_insn "lo_sum_si" | |
557 | [(set (match_operand:SI 0 "register_operand" "=r") | |
558 | (lo_sum:SI (match_operand:SI 1 "register_operand" "r") | |
559 | (match_operand:SI 2 "immediate_operand" "in")))] | |
560 | "" | |
561 | "add3 %0,%1,%#%B2" | |
5b8ae21f MM |
562 | [(set_attr "type" "int4") |
563 | (set_attr "length" "4")]) | |
8c5ca3b9 DE |
564 | |
565 | (define_expand "movdi" | |
566 | [(set (match_operand:DI 0 "general_operand" "") | |
567 | (match_operand:DI 1 "general_operand" ""))] | |
568 | "" | |
569 | " | |
570 | { | |
ad126521 KI |
571 | /* Fixup PIC cases. */ |
572 | if (flag_pic) | |
573 | { | |
574 | if (symbolic_operand (operands[1], DImode)) | |
575 | { | |
576 | if (reload_in_progress || reload_completed) | |
577 | operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); | |
578 | else | |
579 | operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); | |
580 | } | |
581 | } | |
582 | ||
8c5ca3b9 DE |
583 | /* Everything except mem = const or mem = mem can be done easily. */ |
584 | ||
d000f0d9 | 585 | if (MEM_P (operands[0])) |
8c5ca3b9 | 586 | operands[1] = force_reg (DImode, operands[1]); |
8c5ca3b9 DE |
587 | }") |
588 | ||
589 | (define_insn "*movdi_insn" | |
5b8ae21f MM |
590 | [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,r,m") |
591 | (match_operand:DI 1 "move_double_src_operand" "r,nG,F,m,r"))] | |
8c5ca3b9 | 592 | "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" |
5b8ae21f MM |
593 | "#" |
594 | [(set_attr "type" "multi,multi,multi,load8,store8") | |
595 | (set_attr "length" "4,4,16,6,6")]) | |
8c5ca3b9 DE |
596 | |
597 | (define_split | |
5b8ae21f MM |
598 | [(set (match_operand:DI 0 "move_dest_operand" "") |
599 | (match_operand:DI 1 "move_double_src_operand" ""))] | |
8c5ca3b9 | 600 | "reload_completed" |
5b8ae21f MM |
601 | [(match_dup 2)] |
602 | "operands[2] = gen_split_move_double (operands);") | |
8c5ca3b9 DE |
603 | \f |
604 | ;; Floating point move insns. | |
605 | ||
606 | (define_expand "movsf" | |
607 | [(set (match_operand:SF 0 "general_operand" "") | |
608 | (match_operand:SF 1 "general_operand" ""))] | |
609 | "" | |
610 | " | |
611 | { | |
ad126521 KI |
612 | /* Fixup PIC cases. */ |
613 | if (flag_pic) | |
614 | { | |
615 | if (symbolic_operand (operands[1], SFmode)) | |
616 | { | |
617 | if (reload_in_progress || reload_completed) | |
618 | operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); | |
619 | else | |
620 | operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); | |
621 | } | |
622 | } | |
623 | ||
8c5ca3b9 DE |
624 | /* Everything except mem = const or mem = mem can be done easily. */ |
625 | ||
d000f0d9 | 626 | if (MEM_P (operands[0])) |
8c5ca3b9 DE |
627 | operands[1] = force_reg (SFmode, operands[1]); |
628 | }") | |
629 | ||
630 | (define_insn "*movsf_insn" | |
56e2e762 NC |
631 | [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,r,r,T,S,m") |
632 | (match_operand:SF 1 "move_src_operand" "r,F,U,S,m,r,r,r"))] | |
8c5ca3b9 | 633 | "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)" |
5b8ae21f MM |
634 | "@ |
635 | mv %0,%1 | |
636 | # | |
637 | ld %0,%1 | |
638 | ld %0,%1 | |
56e2e762 NC |
639 | ld %0,%1 |
640 | st %1,%0 | |
5b8ae21f MM |
641 | st %1,%0 |
642 | st %1,%0" | |
8c5ca3b9 | 643 | ;; ??? Length of alternative 1 is either 2, 4 or 8. |
56e2e762 NC |
644 | [(set_attr "type" "int2,multi,load2,load2,load4,store2,store2,store4") |
645 | (set_attr "length" "2,8,2,2,4,2,2,4")]) | |
5b8ae21f MM |
646 | |
647 | (define_split | |
648 | [(set (match_operand:SF 0 "register_operand" "") | |
649 | (match_operand:SF 1 "const_double_operand" ""))] | |
650 | "reload_completed" | |
651 | [(set (match_dup 2) (match_dup 3))] | |
652 | " | |
653 | { | |
5b8ae21f | 654 | operands[2] = operand_subword (operands[0], 0, 0, SFmode); |
b5a3eb84 | 655 | operands[3] = operand_subword (operands[1], 0, 0, SFmode); |
5b8ae21f | 656 | }") |
8c5ca3b9 DE |
657 | |
658 | (define_expand "movdf" | |
659 | [(set (match_operand:DF 0 "general_operand" "") | |
660 | (match_operand:DF 1 "general_operand" ""))] | |
661 | "" | |
662 | " | |
663 | { | |
ad126521 KI |
664 | /* Fixup PIC cases. */ |
665 | if (flag_pic) | |
666 | { | |
667 | if (symbolic_operand (operands[1], DFmode)) | |
668 | { | |
669 | if (reload_in_progress || reload_completed) | |
670 | operands[1] = m32r_legitimize_pic_address (operands[1], operands[0]); | |
671 | else | |
672 | operands[1] = m32r_legitimize_pic_address (operands[1], NULL_RTX); | |
673 | } | |
674 | } | |
675 | ||
8c5ca3b9 DE |
676 | /* Everything except mem = const or mem = mem can be done easily. */ |
677 | ||
d000f0d9 | 678 | if (MEM_P (operands[0])) |
8c5ca3b9 | 679 | operands[1] = force_reg (DFmode, operands[1]); |
8c5ca3b9 DE |
680 | }") |
681 | ||
682 | (define_insn "*movdf_insn" | |
683 | [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m") | |
5b8ae21f | 684 | (match_operand:DF 1 "move_double_src_operand" "r,F,m,r"))] |
8c5ca3b9 | 685 | "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" |
5b8ae21f MM |
686 | "#" |
687 | [(set_attr "type" "multi,multi,load8,store8") | |
688 | (set_attr "length" "4,16,6,6")]) | |
689 | ||
690 | (define_split | |
691 | [(set (match_operand:DF 0 "move_dest_operand" "") | |
692 | (match_operand:DF 1 "move_double_src_operand" ""))] | |
693 | "reload_completed" | |
694 | [(match_dup 2)] | |
695 | "operands[2] = gen_split_move_double (operands);") | |
8c5ca3b9 DE |
696 | \f |
697 | ;; Zero extension instructions. | |
698 | ||
699 | (define_insn "zero_extendqihi2" | |
5b8ae21f | 700 | [(set (match_operand:HI 0 "register_operand" "=r,r,r") |
56e2e762 | 701 | (zero_extend:HI (match_operand:QI 1 "extend_operand" "r,T,m")))] |
8c5ca3b9 DE |
702 | "" |
703 | "@ | |
704 | and3 %0,%1,%#255 | |
5b8ae21f | 705 | ldub %0,%1 |
8c5ca3b9 | 706 | ldub %0,%1" |
5b8ae21f MM |
707 | [(set_attr "type" "int4,load2,load4") |
708 | (set_attr "length" "4,2,4")]) | |
8c5ca3b9 DE |
709 | |
710 | (define_insn "zero_extendqisi2" | |
5b8ae21f | 711 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
56e2e762 | 712 | (zero_extend:SI (match_operand:QI 1 "extend_operand" "r,T,m")))] |
8c5ca3b9 DE |
713 | "" |
714 | "@ | |
715 | and3 %0,%1,%#255 | |
5b8ae21f | 716 | ldub %0,%1 |
8c5ca3b9 | 717 | ldub %0,%1" |
5b8ae21f MM |
718 | [(set_attr "type" "int4,load2,load4") |
719 | (set_attr "length" "4,2,4")]) | |
8c5ca3b9 DE |
720 | |
721 | (define_insn "zero_extendhisi2" | |
5b8ae21f | 722 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
56e2e762 | 723 | (zero_extend:SI (match_operand:HI 1 "extend_operand" "r,T,m")))] |
8c5ca3b9 DE |
724 | "" |
725 | "@ | |
726 | and3 %0,%1,%#65535 | |
5b8ae21f | 727 | lduh %0,%1 |
8c5ca3b9 | 728 | lduh %0,%1" |
5b8ae21f MM |
729 | [(set_attr "type" "int4,load2,load4") |
730 | (set_attr "length" "4,2,4")]) | |
8c5ca3b9 | 731 | \f |
56e2e762 NC |
732 | ;; Signed conversions from a smaller integer to a larger integer |
733 | (define_insn "extendqihi2" | |
734 | [(set (match_operand:HI 0 "register_operand" "=r,r,r") | |
735 | (sign_extend:HI (match_operand:QI 1 "extend_operand" "0,T,m")))] | |
736 | "" | |
737 | "@ | |
738 | # | |
739 | ldb %0,%1 | |
740 | ldb %0,%1" | |
741 | [(set_attr "type" "multi,load2,load4") | |
742 | (set_attr "length" "2,2,4")]) | |
8c5ca3b9 | 743 | |
56e2e762 | 744 | (define_split |
8c5ca3b9 DE |
745 | [(set (match_operand:HI 0 "register_operand" "") |
746 | (sign_extend:HI (match_operand:QI 1 "register_operand" "")))] | |
56e2e762 NC |
747 | "reload_completed" |
748 | [(match_dup 2) | |
749 | (match_dup 3)] | |
8c5ca3b9 DE |
750 | " |
751 | { | |
56e2e762 | 752 | rtx op0 = gen_lowpart (SImode, operands[0]); |
e512ab39 | 753 | rtx shift = GEN_INT (24); |
8c5ca3b9 | 754 | |
56e2e762 NC |
755 | operands[2] = gen_ashlsi3 (op0, op0, shift); |
756 | operands[3] = gen_ashrsi3 (op0, op0, shift); | |
8c5ca3b9 DE |
757 | }") |
758 | ||
56e2e762 NC |
759 | (define_insn "extendqisi2" |
760 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
761 | (sign_extend:SI (match_operand:QI 1 "extend_operand" "0,T,m")))] | |
8c5ca3b9 | 762 | "" |
56e2e762 NC |
763 | "@ |
764 | # | |
765 | ldb %0,%1 | |
766 | ldb %0,%1" | |
767 | [(set_attr "type" "multi,load2,load4") | |
768 | (set_attr "length" "4,2,4")]) | |
8c5ca3b9 | 769 | |
56e2e762 | 770 | (define_split |
8c5ca3b9 DE |
771 | [(set (match_operand:SI 0 "register_operand" "") |
772 | (sign_extend:SI (match_operand:QI 1 "register_operand" "")))] | |
56e2e762 NC |
773 | "reload_completed" |
774 | [(match_dup 2) | |
775 | (match_dup 3)] | |
8c5ca3b9 DE |
776 | " |
777 | { | |
e512ab39 | 778 | rtx shift = GEN_INT (24); |
8c5ca3b9 | 779 | |
5a67e41f KH |
780 | operands[2] = gen_ashlsi3 (operands[0], operands[0], shift); |
781 | operands[3] = gen_ashrsi3 (operands[0], operands[0], shift); | |
8c5ca3b9 DE |
782 | }") |
783 | ||
56e2e762 NC |
784 | (define_insn "extendhisi2" |
785 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
786 | (sign_extend:SI (match_operand:HI 1 "extend_operand" "0,T,m")))] | |
8c5ca3b9 | 787 | "" |
56e2e762 NC |
788 | "@ |
789 | # | |
790 | ldh %0,%1 | |
791 | ldh %0,%1" | |
792 | [(set_attr "type" "multi,load2,load4") | |
793 | (set_attr "length" "4,2,4")]) | |
8c5ca3b9 | 794 | |
56e2e762 | 795 | (define_split |
8c5ca3b9 DE |
796 | [(set (match_operand:SI 0 "register_operand" "") |
797 | (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] | |
56e2e762 NC |
798 | "reload_completed" |
799 | [(match_dup 2) | |
800 | (match_dup 3)] | |
8c5ca3b9 DE |
801 | " |
802 | { | |
e512ab39 | 803 | rtx shift = GEN_INT (16); |
8c5ca3b9 | 804 | |
5a67e41f KH |
805 | operands[2] = gen_ashlsi3 (operands[0], operands[0], shift); |
806 | operands[3] = gen_ashrsi3 (operands[0], operands[0], shift); | |
8c5ca3b9 | 807 | }") |
8c5ca3b9 DE |
808 | \f |
809 | ;; Arithmetic instructions. | |
810 | ||
811 | ; ??? Adding an alternative to split add3 of small constants into two | |
812 | ; insns yields better instruction packing but slower code. Adds of small | |
813 | ; values is done a lot. | |
814 | ||
815 | (define_insn "addsi3" | |
816 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
817 | (plus:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
818 | (match_operand:SI 2 "nonmemory_operand" "r,I,J")))] | |
819 | "" | |
820 | "@ | |
821 | add %0,%2 | |
822 | addi %0,%#%2 | |
823 | add3 %0,%1,%#%2" | |
5b8ae21f | 824 | [(set_attr "type" "int2,int2,int4") |
8c5ca3b9 DE |
825 | (set_attr "length" "2,2,4")]) |
826 | ||
827 | ;(define_split | |
828 | ; [(set (match_operand:SI 0 "register_operand" "") | |
829 | ; (plus:SI (match_operand:SI 1 "register_operand" "") | |
830 | ; (match_operand:SI 2 "int8_operand" "")))] | |
831 | ; "reload_completed | |
832 | ; && REGNO (operands[0]) != REGNO (operands[1]) | |
fbaeb717 | 833 | ; && satisfies_constraint_I (operands[2]) |
8c5ca3b9 DE |
834 | ; && INTVAL (operands[2]) != 0" |
835 | ; [(set (match_dup 0) (match_dup 1)) | |
836 | ; (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))] | |
837 | ; "") | |
838 | ||
839 | (define_insn "adddi3" | |
840 | [(set (match_operand:DI 0 "register_operand" "=r") | |
841 | (plus:DI (match_operand:DI 1 "register_operand" "%0") | |
842 | (match_operand:DI 2 "register_operand" "r"))) | |
58ebda9c | 843 | (clobber (reg:CC 17))] |
8c5ca3b9 | 844 | "" |
5b8ae21f MM |
845 | "#" |
846 | [(set_attr "type" "multi") | |
8c5ca3b9 DE |
847 | (set_attr "length" "6")]) |
848 | ||
5b8ae21f MM |
849 | ;; ??? The cmp clears the condition bit. Can we speed up somehow? |
850 | (define_split | |
851 | [(set (match_operand:DI 0 "register_operand" "") | |
852 | (plus:DI (match_operand:DI 1 "register_operand" "") | |
853 | (match_operand:DI 2 "register_operand" ""))) | |
58ebda9c | 854 | (clobber (reg:CC 17))] |
5b8ae21f | 855 | "reload_completed" |
58ebda9c | 856 | [(parallel [(set (reg:CC 17) |
5b8ae21f MM |
857 | (const_int 0)) |
858 | (use (match_dup 4))]) | |
859 | (parallel [(set (match_dup 4) | |
860 | (plus:SI (match_dup 4) | |
861 | (plus:SI (match_dup 5) | |
58ebda9c KH |
862 | (ne:SI (reg:CC 17) (const_int 0))))) |
863 | (set (reg:CC 17) | |
a2ab189d | 864 | (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))]) |
5b8ae21f MM |
865 | (parallel [(set (match_dup 6) |
866 | (plus:SI (match_dup 6) | |
867 | (plus:SI (match_dup 7) | |
58ebda9c KH |
868 | (ne:SI (reg:CC 17) (const_int 0))))) |
869 | (set (reg:CC 17) | |
a2ab189d | 870 | (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))])] |
5b8ae21f MM |
871 | " |
872 | { | |
873 | operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode); | |
874 | operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode); | |
875 | operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode); | |
876 | operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode); | |
877 | }") | |
878 | ||
879 | (define_insn "*clear_c" | |
58ebda9c | 880 | [(set (reg:CC 17) |
5b8ae21f MM |
881 | (const_int 0)) |
882 | (use (match_operand:SI 0 "register_operand" "r"))] | |
883 | "" | |
884 | "cmp %0,%0" | |
885 | [(set_attr "type" "int2") | |
886 | (set_attr "length" "2")]) | |
887 | ||
888 | (define_insn "*add_carry" | |
889 | [(set (match_operand:SI 0 "register_operand" "=r") | |
890 | (plus:SI (match_operand:SI 1 "register_operand" "%0") | |
891 | (plus:SI (match_operand:SI 2 "register_operand" "r") | |
58ebda9c KH |
892 | (ne:SI (reg:CC 17) (const_int 0))))) |
893 | (set (reg:CC 17) | |
a2ab189d | 894 | (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))] |
5b8ae21f MM |
895 | "" |
896 | "addx %0,%2" | |
897 | [(set_attr "type" "int2") | |
898 | (set_attr "length" "2")]) | |
899 | ||
8c5ca3b9 DE |
900 | (define_insn "subsi3" |
901 | [(set (match_operand:SI 0 "register_operand" "=r") | |
902 | (minus:SI (match_operand:SI 1 "register_operand" "0") | |
903 | (match_operand:SI 2 "register_operand" "r")))] | |
904 | "" | |
905 | "sub %0,%2" | |
5b8ae21f MM |
906 | [(set_attr "type" "int2") |
907 | (set_attr "length" "2")]) | |
8c5ca3b9 DE |
908 | |
909 | (define_insn "subdi3" | |
910 | [(set (match_operand:DI 0 "register_operand" "=r") | |
911 | (minus:DI (match_operand:DI 1 "register_operand" "0") | |
912 | (match_operand:DI 2 "register_operand" "r"))) | |
58ebda9c | 913 | (clobber (reg:CC 17))] |
8c5ca3b9 | 914 | "" |
5b8ae21f MM |
915 | "#" |
916 | [(set_attr "type" "multi") | |
8c5ca3b9 | 917 | (set_attr "length" "6")]) |
5b8ae21f MM |
918 | |
919 | ;; ??? The cmp clears the condition bit. Can we speed up somehow? | |
920 | (define_split | |
921 | [(set (match_operand:DI 0 "register_operand" "") | |
922 | (minus:DI (match_operand:DI 1 "register_operand" "") | |
923 | (match_operand:DI 2 "register_operand" ""))) | |
58ebda9c | 924 | (clobber (reg:CC 17))] |
5b8ae21f | 925 | "reload_completed" |
58ebda9c | 926 | [(parallel [(set (reg:CC 17) |
5b8ae21f MM |
927 | (const_int 0)) |
928 | (use (match_dup 4))]) | |
929 | (parallel [(set (match_dup 4) | |
930 | (minus:SI (match_dup 4) | |
931 | (minus:SI (match_dup 5) | |
58ebda9c KH |
932 | (ne:SI (reg:CC 17) (const_int 0))))) |
933 | (set (reg:CC 17) | |
a2ab189d | 934 | (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))]) |
5b8ae21f MM |
935 | (parallel [(set (match_dup 6) |
936 | (minus:SI (match_dup 6) | |
937 | (minus:SI (match_dup 7) | |
58ebda9c KH |
938 | (ne:SI (reg:CC 17) (const_int 0))))) |
939 | (set (reg:CC 17) | |
a2ab189d | 940 | (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))])] |
5b8ae21f MM |
941 | " |
942 | { | |
943 | operands[4] = operand_subword (operands[0], (WORDS_BIG_ENDIAN != 0), 0, DImode); | |
944 | operands[5] = operand_subword (operands[2], (WORDS_BIG_ENDIAN != 0), 0, DImode); | |
945 | operands[6] = operand_subword (operands[0], (WORDS_BIG_ENDIAN == 0), 0, DImode); | |
946 | operands[7] = operand_subword (operands[2], (WORDS_BIG_ENDIAN == 0), 0, DImode); | |
947 | }") | |
948 | ||
949 | (define_insn "*sub_carry" | |
950 | [(set (match_operand:SI 0 "register_operand" "=r") | |
951 | (minus:SI (match_operand:SI 1 "register_operand" "%0") | |
952 | (minus:SI (match_operand:SI 2 "register_operand" "r") | |
58ebda9c KH |
953 | (ne:SI (reg:CC 17) (const_int 0))))) |
954 | (set (reg:CC 17) | |
a2ab189d | 955 | (unspec:CC [(const_int 0)] UNSPEC_SET_CBIT))] |
5b8ae21f MM |
956 | "" |
957 | "subx %0,%2" | |
958 | [(set_attr "type" "int2") | |
959 | (set_attr "length" "2")]) | |
8c5ca3b9 DE |
960 | \f |
961 | ; Multiply/Divide instructions. | |
962 | ||
963 | (define_insn "mulhisi3" | |
964 | [(set (match_operand:SI 0 "register_operand" "=r") | |
965 | (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "r")) | |
966 | (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] | |
967 | "" | |
968 | "mullo %1,%2\;mvfacmi %0" | |
5b8ae21f | 969 | [(set_attr "type" "multi") |
8c5ca3b9 DE |
970 | (set_attr "length" "4")]) |
971 | ||
972 | (define_insn "mulsi3" | |
973 | [(set (match_operand:SI 0 "register_operand" "=r") | |
974 | (mult:SI (match_operand:SI 1 "register_operand" "%0") | |
975 | (match_operand:SI 2 "register_operand" "r")))] | |
976 | "" | |
977 | "mul %0,%2" | |
5b8ae21f MM |
978 | [(set_attr "type" "mul2") |
979 | (set_attr "length" "2")]) | |
8c5ca3b9 DE |
980 | |
981 | (define_insn "divsi3" | |
982 | [(set (match_operand:SI 0 "register_operand" "=r") | |
983 | (div:SI (match_operand:SI 1 "register_operand" "0") | |
984 | (match_operand:SI 2 "register_operand" "r")))] | |
985 | "" | |
986 | "div %0,%2" | |
5b8ae21f MM |
987 | [(set_attr "type" "div4") |
988 | (set_attr "length" "4")]) | |
8c5ca3b9 DE |
989 | |
990 | (define_insn "udivsi3" | |
991 | [(set (match_operand:SI 0 "register_operand" "=r") | |
992 | (udiv:SI (match_operand:SI 1 "register_operand" "0") | |
993 | (match_operand:SI 2 "register_operand" "r")))] | |
994 | "" | |
995 | "divu %0,%2" | |
5b8ae21f MM |
996 | [(set_attr "type" "div4") |
997 | (set_attr "length" "4")]) | |
8c5ca3b9 DE |
998 | |
999 | (define_insn "modsi3" | |
1000 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1001 | (mod:SI (match_operand:SI 1 "register_operand" "0") | |
1002 | (match_operand:SI 2 "register_operand" "r")))] | |
1003 | "" | |
1004 | "rem %0,%2" | |
5b8ae21f MM |
1005 | [(set_attr "type" "div4") |
1006 | (set_attr "length" "4")]) | |
8c5ca3b9 DE |
1007 | |
1008 | (define_insn "umodsi3" | |
1009 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1010 | (umod:SI (match_operand:SI 1 "register_operand" "0") | |
1011 | (match_operand:SI 2 "register_operand" "r")))] | |
1012 | "" | |
1013 | "remu %0,%2" | |
5b8ae21f MM |
1014 | [(set_attr "type" "div4") |
1015 | (set_attr "length" "4")]) | |
8c5ca3b9 DE |
1016 | \f |
1017 | ;; Boolean instructions. | |
1018 | ;; | |
1019 | ;; We don't define the DImode versions as expand_binop does a good enough job. | |
1020 | ;; And if it doesn't it should be fixed. | |
1021 | ||
1022 | (define_insn "andsi3" | |
1023 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1024 | (and:SI (match_operand:SI 1 "register_operand" "%0,r") | |
56e2e762 | 1025 | (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))] |
8c5ca3b9 | 1026 | "" |
56e2e762 NC |
1027 | "* |
1028 | { | |
1029 | /* If we are worried about space, see if we can break this up into two | |
1030 | short instructions, which might eliminate a NOP being inserted. */ | |
1031 | if (optimize_size | |
1032 | && m32r_not_same_reg (operands[0], operands[1]) | |
fbaeb717 | 1033 | && satisfies_constraint_I (operands[2])) |
56e2e762 NC |
1034 | return \"#\"; |
1035 | ||
d000f0d9 | 1036 | else if (CONST_INT_P (operands[2])) |
56e2e762 NC |
1037 | return \"and3 %0,%1,%#%X2\"; |
1038 | ||
1039 | return \"and %0,%2\"; | |
1040 | }" | |
5b8ae21f MM |
1041 | [(set_attr "type" "int2,int4") |
1042 | (set_attr "length" "2,4")]) | |
8c5ca3b9 | 1043 | |
56e2e762 NC |
1044 | (define_split |
1045 | [(set (match_operand:SI 0 "register_operand" "") | |
1046 | (and:SI (match_operand:SI 1 "register_operand" "") | |
1047 | (match_operand:SI 2 "int8_operand" "")))] | |
1048 | "optimize_size && m32r_not_same_reg (operands[0], operands[1])" | |
1049 | [(set (match_dup 0) (match_dup 2)) | |
c73a5e94 | 1050 | (set (match_dup 0) (and:SI (match_dup 0) (match_dup 1)))] |
56e2e762 NC |
1051 | "") |
1052 | ||
8c5ca3b9 DE |
1053 | (define_insn "iorsi3" |
1054 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1055 | (ior:SI (match_operand:SI 1 "register_operand" "%0,r") | |
56e2e762 | 1056 | (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))] |
8c5ca3b9 | 1057 | "" |
56e2e762 NC |
1058 | "* |
1059 | { | |
1060 | /* If we are worried about space, see if we can break this up into two | |
1061 | short instructions, which might eliminate a NOP being inserted. */ | |
1062 | if (optimize_size | |
1063 | && m32r_not_same_reg (operands[0], operands[1]) | |
fbaeb717 | 1064 | && satisfies_constraint_I (operands[2])) |
56e2e762 NC |
1065 | return \"#\"; |
1066 | ||
d000f0d9 | 1067 | else if (CONST_INT_P (operands[2])) |
56e2e762 NC |
1068 | return \"or3 %0,%1,%#%X2\"; |
1069 | ||
1070 | return \"or %0,%2\"; | |
1071 | }" | |
5b8ae21f MM |
1072 | [(set_attr "type" "int2,int4") |
1073 | (set_attr "length" "2,4")]) | |
8c5ca3b9 | 1074 | |
56e2e762 NC |
1075 | (define_split |
1076 | [(set (match_operand:SI 0 "register_operand" "") | |
1077 | (ior:SI (match_operand:SI 1 "register_operand" "") | |
1078 | (match_operand:SI 2 "int8_operand" "")))] | |
1079 | "optimize_size && m32r_not_same_reg (operands[0], operands[1])" | |
1080 | [(set (match_dup 0) (match_dup 2)) | |
c73a5e94 | 1081 | (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 1)))] |
56e2e762 NC |
1082 | "") |
1083 | ||
8c5ca3b9 DE |
1084 | (define_insn "xorsi3" |
1085 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1086 | (xor:SI (match_operand:SI 1 "register_operand" "%0,r") | |
56e2e762 | 1087 | (match_operand:SI 2 "reg_or_uint16_operand" "r,K")))] |
8c5ca3b9 | 1088 | "" |
56e2e762 NC |
1089 | "* |
1090 | { | |
1091 | /* If we are worried about space, see if we can break this up into two | |
1092 | short instructions, which might eliminate a NOP being inserted. */ | |
1093 | if (optimize_size | |
1094 | && m32r_not_same_reg (operands[0], operands[1]) | |
fbaeb717 | 1095 | && satisfies_constraint_I (operands[2])) |
56e2e762 NC |
1096 | return \"#\"; |
1097 | ||
d000f0d9 | 1098 | else if (CONST_INT_P (operands[2])) |
56e2e762 NC |
1099 | return \"xor3 %0,%1,%#%X2\"; |
1100 | ||
1101 | return \"xor %0,%2\"; | |
1102 | }" | |
5b8ae21f MM |
1103 | [(set_attr "type" "int2,int4") |
1104 | (set_attr "length" "2,4")]) | |
8c5ca3b9 | 1105 | |
56e2e762 NC |
1106 | (define_split |
1107 | [(set (match_operand:SI 0 "register_operand" "") | |
1108 | (xor:SI (match_operand:SI 1 "register_operand" "") | |
1109 | (match_operand:SI 2 "int8_operand" "")))] | |
1110 | "optimize_size && m32r_not_same_reg (operands[0], operands[1])" | |
1111 | [(set (match_dup 0) (match_dup 2)) | |
c73a5e94 | 1112 | (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1)))] |
56e2e762 NC |
1113 | "") |
1114 | ||
8c5ca3b9 DE |
1115 | (define_insn "negsi2" |
1116 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1117 | (neg:SI (match_operand:SI 1 "register_operand" "r")))] | |
1118 | "" | |
1119 | "neg %0,%1" | |
5b8ae21f MM |
1120 | [(set_attr "type" "int2") |
1121 | (set_attr "length" "2")]) | |
8c5ca3b9 DE |
1122 | |
1123 | (define_insn "one_cmplsi2" | |
1124 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1125 | (not:SI (match_operand:SI 1 "register_operand" "r")))] | |
1126 | "" | |
1127 | "not %0,%1" | |
5b8ae21f MM |
1128 | [(set_attr "type" "int2") |
1129 | (set_attr "length" "2")]) | |
8c5ca3b9 DE |
1130 | \f |
1131 | ;; Shift instructions. | |
1132 | ||
1133 | (define_insn "ashlsi3" | |
1134 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1135 | (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r") | |
1136 | (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))] | |
1137 | "" | |
1138 | "@ | |
1139 | sll %0,%2 | |
1140 | slli %0,%#%2 | |
1141 | sll3 %0,%1,%#%2" | |
5b8ae21f | 1142 | [(set_attr "type" "shift2,shift2,shift4") |
8c5ca3b9 DE |
1143 | (set_attr "length" "2,2,4")]) |
1144 | ||
1145 | (define_insn "ashrsi3" | |
1146 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1147 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") | |
1148 | (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))] | |
1149 | "" | |
1150 | "@ | |
1151 | sra %0,%2 | |
1152 | srai %0,%#%2 | |
1153 | sra3 %0,%1,%#%2" | |
5b8ae21f | 1154 | [(set_attr "type" "shift2,shift2,shift4") |
8c5ca3b9 DE |
1155 | (set_attr "length" "2,2,4")]) |
1156 | ||
1157 | (define_insn "lshrsi3" | |
1158 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1159 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r") | |
1160 | (match_operand:SI 2 "reg_or_uint16_operand" "r,O,K")))] | |
1161 | "" | |
1162 | "@ | |
1163 | srl %0,%2 | |
1164 | srli %0,%#%2 | |
1165 | srl3 %0,%1,%#%2" | |
5b8ae21f | 1166 | [(set_attr "type" "shift2,shift2,shift4") |
8c5ca3b9 DE |
1167 | (set_attr "length" "2,2,4")]) |
1168 | \f | |
1169 | ;; Compare instructions. | |
1170 | ;; This controls RTL generation and register allocation. | |
1171 | ||
e2265be0 | 1172 | ;; We generate RTL for comparisons and branches by having the cmpxx |
8c5ca3b9 DE |
1173 | ;; patterns store away the operands. Then the bcc patterns |
1174 | ;; emit RTL for both the compare and the branch. | |
1175 | ;; | |
1176 | ;; On the m32r it is more efficient to use the bxxz instructions and | |
1177 | ;; thus merge the compare and branch into one instruction, so they are | |
4b6bb562 | 1178 | ;; preferred. |
8c5ca3b9 | 1179 | |
de41e41c | 1180 | (define_insn "cmp_eqsi_zero_insn" |
58ebda9c KH |
1181 | [(set (reg:CC 17) |
1182 | (eq:CC (match_operand:SI 0 "register_operand" "r,r") | |
de41e41c | 1183 | (match_operand:SI 1 "reg_or_zero_operand" "r,P")))] |
6975bd2c | 1184 | "TARGET_M32RX || TARGET_M32R2" |
de41e41c BE |
1185 | "@ |
1186 | cmpeq %0, %1 | |
1187 | cmpz %0" | |
1188 | [(set_attr "type" "int4") | |
1189 | (set_attr "length" "4")]) | |
1190 | ||
8c5ca3b9 DE |
1191 | ;; The cmp_xxx_insn patterns set the condition bit to the result of the |
1192 | ;; comparison. There isn't a "compare equal" instruction so cmp_eqsi_insn | |
1193 | ;; is quite inefficient. However, it is rarely used. | |
1194 | ||
1195 | (define_insn "cmp_eqsi_insn" | |
58ebda9c KH |
1196 | [(set (reg:CC 17) |
1197 | (eq:CC (match_operand:SI 0 "register_operand" "r,r") | |
de41e41c | 1198 | (match_operand:SI 1 "reg_or_cmp_int16_operand" "r,P"))) |
8c5ca3b9 | 1199 | (clobber (match_scratch:SI 2 "=&r,&r"))] |
2b7972b0 MM |
1200 | "" |
1201 | "* | |
1202 | { | |
1203 | if (which_alternative == 0) | |
1204 | { | |
1205 | return \"mv %2,%0\;sub %2,%1\;cmpui %2,#1\"; | |
1206 | } | |
1207 | else | |
1208 | { | |
1209 | if (INTVAL (operands [1]) == 0) | |
1210 | return \"cmpui %0, #1\"; | |
1211 | else if (REGNO (operands [2]) == REGNO (operands [0])) | |
1212 | return \"addi %0,%#%N1\;cmpui %2,#1\"; | |
1213 | else | |
1214 | return \"add3 %2,%0,%#%N1\;cmpui %2,#1\"; | |
1215 | } | |
1216 | }" | |
5b8ae21f | 1217 | [(set_attr "type" "multi,multi") |
8c5ca3b9 DE |
1218 | (set_attr "length" "8,8")]) |
1219 | ||
1220 | (define_insn "cmp_ltsi_insn" | |
58ebda9c KH |
1221 | [(set (reg:CC 17) |
1222 | (lt:CC (match_operand:SI 0 "register_operand" "r,r") | |
de41e41c | 1223 | (match_operand:SI 1 "reg_or_int16_operand" "r,J")))] |
8c5ca3b9 DE |
1224 | "" |
1225 | "@ | |
1226 | cmp %0,%1 | |
1227 | cmpi %0,%#%1" | |
5b8ae21f MM |
1228 | [(set_attr "type" "int2,int4") |
1229 | (set_attr "length" "2,4")]) | |
8c5ca3b9 DE |
1230 | |
1231 | (define_insn "cmp_ltusi_insn" | |
58ebda9c KH |
1232 | [(set (reg:CC 17) |
1233 | (ltu:CC (match_operand:SI 0 "register_operand" "r,r") | |
de41e41c | 1234 | (match_operand:SI 1 "reg_or_int16_operand" "r,J")))] |
8c5ca3b9 | 1235 | "" |
5b8ae21f MM |
1236 | "@ |
1237 | cmpu %0,%1 | |
1238 | cmpui %0,%#%1" | |
1239 | [(set_attr "type" "int2,int4") | |
1240 | (set_attr "length" "2,4")]) | |
8c5ca3b9 DE |
1241 | \f |
1242 | ;; These control RTL generation for conditional jump insns. | |
1243 | ||
f90b7a5a PB |
1244 | (define_expand "cbranchsi4" |
1245 | ; the comparison is emitted by gen_compare if needed. | |
8c5ca3b9 | 1246 | [(set (pc) |
f90b7a5a PB |
1247 | (if_then_else (match_operator 0 "ordered_comparison_operator" |
1248 | [(match_operand:SI 1 "register_operand" "") | |
1249 | (match_operand:SI 2 "reg_or_cmp_int16_operand" "")]) | |
1250 | (label_ref (match_operand 3 "" "")) | |
8c5ca3b9 DE |
1251 | (pc)))] |
1252 | "" | |
1253 | " | |
1254 | { | |
f90b7a5a PB |
1255 | operands[0] = gen_compare (GET_CODE (operands[0]), operands[1], operands[2], FALSE); |
1256 | operands[1] = XEXP (operands[0], 0); | |
1257 | operands[2] = XEXP (operands[0], 1); | |
8c5ca3b9 DE |
1258 | }") |
1259 | ||
1260 | ;; Now match both normal and inverted jump. | |
1261 | ||
1262 | (define_insn "*branch_insn" | |
1263 | [(set (pc) | |
1264 | (if_then_else (match_operator 1 "eqne_comparison_operator" | |
1265 | [(reg 17) (const_int 0)]) | |
1266 | (label_ref (match_operand 0 "" "")) | |
1267 | (pc)))] | |
1268 | "" | |
1269 | "* | |
1270 | { | |
2b7972b0 MM |
1271 | static char instruction[40]; |
1272 | sprintf (instruction, \"%s%s %%l0\", | |
1273 | (GET_CODE (operands[1]) == NE) ? \"bc\" : \"bnc\", | |
1274 | (get_attr_length (insn) == 2) ? \".s\" : \"\"); | |
1275 | return instruction; | |
8c5ca3b9 DE |
1276 | }" |
1277 | [(set_attr "type" "branch") | |
721cedf2 KI |
1278 | ; cf PR gcc/28508 |
1279 | ; We use 300/600 instead of 512,1024 to account for inaccurate insn | |
8c5ca3b9 DE |
1280 | ; lengths and insn alignments that are complex to track. |
1281 | ; It's not important that we be hyper-precise here. It may be more | |
1282 | ; important blah blah blah when the chip supports parallel execution | |
1283 | ; blah blah blah but until then blah blah blah this is simple and | |
1284 | ; suffices. | |
1285 | (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) | |
721cedf2 KI |
1286 | (const_int 300)) |
1287 | (const_int 600)) | |
8c5ca3b9 DE |
1288 | (const_int 2) |
1289 | (const_int 4)))]) | |
1290 | ||
1291 | (define_insn "*rev_branch_insn" | |
1292 | [(set (pc) | |
1293 | (if_then_else (match_operator 1 "eqne_comparison_operator" | |
1294 | [(reg 17) (const_int 0)]) | |
1295 | (pc) | |
1296 | (label_ref (match_operand 0 "" ""))))] | |
1297 | ;"REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))" | |
1298 | "" | |
1299 | "* | |
1300 | { | |
2b7972b0 MM |
1301 | static char instruction[40]; |
1302 | sprintf (instruction, \"%s%s %%l0\", | |
1303 | (GET_CODE (operands[1]) == EQ) ? \"bc\" : \"bnc\", | |
1304 | (get_attr_length (insn) == 2) ? \".s\" : \"\"); | |
1305 | return instruction; | |
8c5ca3b9 DE |
1306 | }" |
1307 | [(set_attr "type" "branch") | |
721cedf2 KI |
1308 | ; cf PR gcc/28508 |
1309 | ; We use 300/600 instead of 512,1024 to account for inaccurate insn | |
8c5ca3b9 DE |
1310 | ; lengths and insn alignments that are complex to track. |
1311 | ; It's not important that we be hyper-precise here. It may be more | |
1312 | ; important blah blah blah when the chip supports parallel execution | |
1313 | ; blah blah blah but until then blah blah blah this is simple and | |
1314 | ; suffices. | |
1315 | (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) | |
721cedf2 KI |
1316 | (const_int 300)) |
1317 | (const_int 600)) | |
8c5ca3b9 DE |
1318 | (const_int 2) |
1319 | (const_int 4)))]) | |
1320 | ||
1321 | ; reg/reg compare and branch insns | |
1322 | ||
1323 | (define_insn "*reg_branch_insn" | |
1324 | [(set (pc) | |
1325 | (if_then_else (match_operator 1 "eqne_comparison_operator" | |
1326 | [(match_operand:SI 2 "register_operand" "r") | |
1327 | (match_operand:SI 3 "register_operand" "r")]) | |
1328 | (label_ref (match_operand 0 "" "")) | |
1329 | (pc)))] | |
1330 | "" | |
1331 | "* | |
1332 | { | |
1333 | /* Is branch target reachable with beq/bne? */ | |
1334 | if (get_attr_length (insn) == 4) | |
1335 | { | |
1336 | if (GET_CODE (operands[1]) == EQ) | |
1337 | return \"beq %2,%3,%l0\"; | |
1338 | else | |
1339 | return \"bne %2,%3,%l0\"; | |
1340 | } | |
1341 | else | |
1342 | { | |
1343 | if (GET_CODE (operands[1]) == EQ) | |
1344 | return \"bne %2,%3,1f\;bra %l0\;1:\"; | |
1345 | else | |
1346 | return \"beq %2,%3,1f\;bra %l0\;1:\"; | |
1347 | } | |
1348 | }" | |
1349 | [(set_attr "type" "branch") | |
1350 | ; We use 25000/50000 instead of 32768/65536 to account for slot filling | |
1351 | ; which is complex to track and inaccurate length specs. | |
1352 | (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) | |
1353 | (const_int 25000)) | |
1354 | (const_int 50000)) | |
1355 | (const_int 4) | |
1356 | (const_int 8)))]) | |
1357 | ||
1358 | (define_insn "*rev_reg_branch_insn" | |
1359 | [(set (pc) | |
1360 | (if_then_else (match_operator 1 "eqne_comparison_operator" | |
1361 | [(match_operand:SI 2 "register_operand" "r") | |
1362 | (match_operand:SI 3 "register_operand" "r")]) | |
1363 | (pc) | |
1364 | (label_ref (match_operand 0 "" ""))))] | |
1365 | "" | |
1366 | "* | |
1367 | { | |
1368 | /* Is branch target reachable with beq/bne? */ | |
1369 | if (get_attr_length (insn) == 4) | |
1370 | { | |
1371 | if (GET_CODE (operands[1]) == NE) | |
1372 | return \"beq %2,%3,%l0\"; | |
1373 | else | |
1374 | return \"bne %2,%3,%l0\"; | |
1375 | } | |
1376 | else | |
1377 | { | |
1378 | if (GET_CODE (operands[1]) == NE) | |
1379 | return \"bne %2,%3,1f\;bra %l0\;1:\"; | |
1380 | else | |
1381 | return \"beq %2,%3,1f\;bra %l0\;1:\"; | |
1382 | } | |
1383 | }" | |
1384 | [(set_attr "type" "branch") | |
1385 | ; We use 25000/50000 instead of 32768/65536 to account for slot filling | |
1386 | ; which is complex to track and inaccurate length specs. | |
1387 | (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) | |
1388 | (const_int 25000)) | |
1389 | (const_int 50000)) | |
1390 | (const_int 4) | |
1391 | (const_int 8)))]) | |
1392 | ||
1393 | ; reg/zero compare and branch insns | |
1394 | ||
1395 | (define_insn "*zero_branch_insn" | |
1396 | [(set (pc) | |
1397 | (if_then_else (match_operator 1 "signed_comparison_operator" | |
1398 | [(match_operand:SI 2 "register_operand" "r") | |
1399 | (const_int 0)]) | |
1400 | (label_ref (match_operand 0 "" "")) | |
1401 | (pc)))] | |
1402 | "" | |
1403 | "* | |
1404 | { | |
a5a9cb26 | 1405 | const char *br,*invbr; |
8c5ca3b9 DE |
1406 | char asmtext[40]; |
1407 | ||
1408 | switch (GET_CODE (operands[1])) | |
1409 | { | |
1410 | case EQ : br = \"eq\"; invbr = \"ne\"; break; | |
1411 | case NE : br = \"ne\"; invbr = \"eq\"; break; | |
1412 | case LE : br = \"le\"; invbr = \"gt\"; break; | |
1413 | case GT : br = \"gt\"; invbr = \"le\"; break; | |
1414 | case LT : br = \"lt\"; invbr = \"ge\"; break; | |
1415 | case GE : br = \"ge\"; invbr = \"lt\"; break; | |
61f3b78f | 1416 | |
75c3cfba | 1417 | default: gcc_unreachable (); |
8c5ca3b9 DE |
1418 | } |
1419 | ||
1420 | /* Is branch target reachable with bxxz? */ | |
1421 | if (get_attr_length (insn) == 4) | |
1422 | { | |
1423 | sprintf (asmtext, \"b%sz %%2,%%l0\", br); | |
1424 | output_asm_insn (asmtext, operands); | |
1425 | } | |
1426 | else | |
1427 | { | |
1428 | sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", invbr); | |
1429 | output_asm_insn (asmtext, operands); | |
1430 | } | |
1431 | return \"\"; | |
1432 | }" | |
1433 | [(set_attr "type" "branch") | |
1434 | ; We use 25000/50000 instead of 32768/65536 to account for slot filling | |
1435 | ; which is complex to track and inaccurate length specs. | |
1436 | (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) | |
1437 | (const_int 25000)) | |
1438 | (const_int 50000)) | |
1439 | (const_int 4) | |
1440 | (const_int 8)))]) | |
1441 | ||
1442 | (define_insn "*rev_zero_branch_insn" | |
1443 | [(set (pc) | |
1444 | (if_then_else (match_operator 1 "eqne_comparison_operator" | |
1445 | [(match_operand:SI 2 "register_operand" "r") | |
1446 | (const_int 0)]) | |
1447 | (pc) | |
1448 | (label_ref (match_operand 0 "" ""))))] | |
1449 | "" | |
1450 | "* | |
1451 | { | |
a5a9cb26 | 1452 | const char *br,*invbr; |
8c5ca3b9 DE |
1453 | char asmtext[40]; |
1454 | ||
1455 | switch (GET_CODE (operands[1])) | |
1456 | { | |
1457 | case EQ : br = \"eq\"; invbr = \"ne\"; break; | |
1458 | case NE : br = \"ne\"; invbr = \"eq\"; break; | |
1459 | case LE : br = \"le\"; invbr = \"gt\"; break; | |
1460 | case GT : br = \"gt\"; invbr = \"le\"; break; | |
1461 | case LT : br = \"lt\"; invbr = \"ge\"; break; | |
1462 | case GE : br = \"ge\"; invbr = \"lt\"; break; | |
61f3b78f | 1463 | |
75c3cfba | 1464 | default: gcc_unreachable (); |
8c5ca3b9 DE |
1465 | } |
1466 | ||
1467 | /* Is branch target reachable with bxxz? */ | |
1468 | if (get_attr_length (insn) == 4) | |
1469 | { | |
1470 | sprintf (asmtext, \"b%sz %%2,%%l0\", invbr); | |
1471 | output_asm_insn (asmtext, operands); | |
1472 | } | |
1473 | else | |
1474 | { | |
1475 | sprintf (asmtext, \"b%sz %%2,1f\;bra %%l0\;1:\", br); | |
1476 | output_asm_insn (asmtext, operands); | |
1477 | } | |
1478 | return \"\"; | |
1479 | }" | |
1480 | [(set_attr "type" "branch") | |
1481 | ; We use 25000/50000 instead of 32768/65536 to account for slot filling | |
1482 | ; which is complex to track and inaccurate length specs. | |
1483 | (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) | |
1484 | (const_int 25000)) | |
1485 | (const_int 50000)) | |
1486 | (const_int 4) | |
1487 | (const_int 8)))]) | |
1488 | \f | |
56e2e762 NC |
1489 | ;; S<cc> operations to set a register to 1/0 based on a comparison |
1490 | ||
f90b7a5a PB |
1491 | (define_expand "cstoresi4" |
1492 | [(match_operand:SI 0 "register_operand" "") | |
1493 | (match_operator:SI 1 "ordered_comparison_operator" | |
1494 | [(match_operand:SI 2 "register_operand" "") | |
1495 | (match_operand:SI 3 "reg_or_cmp_int16_operand" "")])] | |
56e2e762 NC |
1496 | "" |
1497 | " | |
1498 | { | |
f90b7a5a | 1499 | if (GET_MODE (operands[0]) != SImode) |
56e2e762 NC |
1500 | FAIL; |
1501 | ||
f90b7a5a PB |
1502 | if (!gen_cond_store (GET_CODE (operands[1]), |
1503 | operands[0], operands[2], operands[3])) | |
1504 | FAIL; | |
56e2e762 | 1505 | |
56e2e762 NC |
1506 | DONE; |
1507 | }") | |
1508 | ||
de41e41c BE |
1509 | (define_insn "seq_insn_m32rx" |
1510 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1511 | (eq:SI (match_operand:SI 1 "register_operand" "%r") | |
1512 | (match_operand:SI 2 "reg_or_zero_operand" "rP"))) | |
58ebda9c | 1513 | (clobber (reg:CC 17))] |
6975bd2c | 1514 | "TARGET_M32RX || TARGET_M32R2" |
de41e41c BE |
1515 | "#" |
1516 | [(set_attr "type" "multi") | |
1517 | (set_attr "length" "6")]) | |
1518 | ||
1519 | (define_split | |
1520 | [(set (match_operand:SI 0 "register_operand" "") | |
1521 | (eq:SI (match_operand:SI 1 "register_operand" "") | |
1522 | (match_operand:SI 2 "reg_or_zero_operand" ""))) | |
58ebda9c | 1523 | (clobber (reg:CC 17))] |
6975bd2c | 1524 | "TARGET_M32RX || TARGET_M32R2" |
58ebda9c KH |
1525 | [(set (reg:CC 17) |
1526 | (eq:CC (match_dup 1) | |
de41e41c BE |
1527 | (match_dup 2))) |
1528 | (set (match_dup 0) | |
58ebda9c | 1529 | (ne:SI (reg:CC 17) (const_int 0)))] |
de41e41c BE |
1530 | "") |
1531 | ||
56e2e762 NC |
1532 | (define_insn "seq_zero_insn" |
1533 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1534 | (eq:SI (match_operand:SI 1 "register_operand" "r") | |
1535 | (const_int 0))) | |
58ebda9c | 1536 | (clobber (reg:CC 17))] |
56e2e762 NC |
1537 | "TARGET_M32R" |
1538 | "#" | |
1539 | [(set_attr "type" "multi") | |
1540 | (set_attr "length" "6")]) | |
1541 | ||
1542 | (define_split | |
1543 | [(set (match_operand:SI 0 "register_operand" "") | |
1544 | (eq:SI (match_operand:SI 1 "register_operand" "") | |
1545 | (const_int 0))) | |
58ebda9c | 1546 | (clobber (reg:CC 17))] |
56e2e762 NC |
1547 | "TARGET_M32R" |
1548 | [(match_dup 3)] | |
1549 | " | |
1550 | { | |
1551 | rtx op0 = operands[0]; | |
1552 | rtx op1 = operands[1]; | |
1553 | ||
1554 | start_sequence (); | |
a556fd39 | 1555 | emit_insn (gen_cmp_ltusi_insn (op1, const1_rtx)); |
56e2e762 | 1556 | emit_insn (gen_movcc_insn (op0)); |
9d0fa9d6 | 1557 | operands[3] = get_insns (); |
56e2e762 NC |
1558 | end_sequence (); |
1559 | }") | |
1560 | ||
1561 | (define_insn "seq_insn" | |
1562 | [(set (match_operand:SI 0 "register_operand" "=r,r,??r,r") | |
1563 | (eq:SI (match_operand:SI 1 "register_operand" "r,r,r,r") | |
1564 | (match_operand:SI 2 "reg_or_eq_int16_operand" "r,r,r,PK"))) | |
58ebda9c | 1565 | (clobber (reg:CC 17)) |
56e2e762 NC |
1566 | (clobber (match_scratch:SI 3 "=1,2,&r,r"))] |
1567 | "TARGET_M32R" | |
1568 | "#" | |
1569 | [(set_attr "type" "multi") | |
1570 | (set_attr "length" "8,8,10,10")]) | |
1571 | ||
1572 | (define_split | |
1573 | [(set (match_operand:SI 0 "register_operand" "") | |
1574 | (eq:SI (match_operand:SI 1 "register_operand" "") | |
1575 | (match_operand:SI 2 "reg_or_eq_int16_operand" ""))) | |
58ebda9c | 1576 | (clobber (reg:CC 17)) |
56e2e762 NC |
1577 | (clobber (match_scratch:SI 3 ""))] |
1578 | "TARGET_M32R && reload_completed" | |
1579 | [(match_dup 4)] | |
1580 | " | |
1581 | { | |
1582 | rtx op0 = operands[0]; | |
1583 | rtx op1 = operands[1]; | |
1584 | rtx op2 = operands[2]; | |
1585 | rtx op3 = operands[3]; | |
1586 | HOST_WIDE_INT value; | |
1587 | ||
d000f0d9 | 1588 | if (REG_P (op2) && REG_P (op3) |
56e2e762 NC |
1589 | && REGNO (op2) == REGNO (op3)) |
1590 | { | |
1591 | op1 = operands[2]; | |
1592 | op2 = operands[1]; | |
1593 | } | |
1594 | ||
1595 | start_sequence (); | |
d000f0d9 | 1596 | if (REG_P (op1) && REG_P (op3) |
56e2e762 NC |
1597 | && REGNO (op1) != REGNO (op3)) |
1598 | { | |
1599 | emit_move_insn (op3, op1); | |
1600 | op1 = op3; | |
1601 | } | |
1602 | ||
fbaeb717 | 1603 | if (satisfies_constraint_P (op2) && (value = INTVAL (op2)) != 0) |
56e2e762 NC |
1604 | emit_insn (gen_addsi3 (op3, op1, GEN_INT (-value))); |
1605 | else | |
1606 | emit_insn (gen_xorsi3 (op3, op1, op2)); | |
1607 | ||
a556fd39 | 1608 | emit_insn (gen_cmp_ltusi_insn (op3, const1_rtx)); |
56e2e762 | 1609 | emit_insn (gen_movcc_insn (op0)); |
9d0fa9d6 | 1610 | operands[4] = get_insns (); |
56e2e762 NC |
1611 | end_sequence (); |
1612 | }") | |
1613 | ||
56e2e762 NC |
1614 | (define_insn "sne_zero_insn" |
1615 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1616 | (ne:SI (match_operand:SI 1 "register_operand" "r") | |
1617 | (const_int 0))) | |
58ebda9c | 1618 | (clobber (reg:CC 17)) |
56e2e762 NC |
1619 | (clobber (match_scratch:SI 2 "=&r"))] |
1620 | "" | |
1621 | "#" | |
1622 | [(set_attr "type" "multi") | |
1623 | (set_attr "length" "6")]) | |
1624 | ||
1625 | (define_split | |
1626 | [(set (match_operand:SI 0 "register_operand" "") | |
1627 | (ne:SI (match_operand:SI 1 "register_operand" "") | |
1628 | (const_int 0))) | |
58ebda9c | 1629 | (clobber (reg:CC 17)) |
56e2e762 NC |
1630 | (clobber (match_scratch:SI 2 ""))] |
1631 | "reload_completed" | |
1632 | [(set (match_dup 2) | |
1633 | (const_int 0)) | |
58ebda9c KH |
1634 | (set (reg:CC 17) |
1635 | (ltu:CC (match_dup 2) | |
56e2e762 NC |
1636 | (match_dup 1))) |
1637 | (set (match_dup 0) | |
58ebda9c | 1638 | (ne:SI (reg:CC 17) (const_int 0)))] |
56e2e762 | 1639 | "") |
e2265be0 | 1640 | |
56e2e762 NC |
1641 | (define_insn "slt_insn" |
1642 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1643 | (lt:SI (match_operand:SI 1 "register_operand" "r,r") | |
1644 | (match_operand:SI 2 "reg_or_int16_operand" "r,J"))) | |
58ebda9c | 1645 | (clobber (reg:CC 17))] |
56e2e762 NC |
1646 | "" |
1647 | "#" | |
1648 | [(set_attr "type" "multi") | |
1649 | (set_attr "length" "4,6")]) | |
1650 | ||
1651 | (define_split | |
1652 | [(set (match_operand:SI 0 "register_operand" "") | |
1653 | (lt:SI (match_operand:SI 1 "register_operand" "") | |
1654 | (match_operand:SI 2 "reg_or_int16_operand" ""))) | |
58ebda9c | 1655 | (clobber (reg:CC 17))] |
56e2e762 | 1656 | "" |
58ebda9c KH |
1657 | [(set (reg:CC 17) |
1658 | (lt:CC (match_dup 1) | |
56e2e762 NC |
1659 | (match_dup 2))) |
1660 | (set (match_dup 0) | |
58ebda9c | 1661 | (ne:SI (reg:CC 17) (const_int 0)))] |
56e2e762 NC |
1662 | "") |
1663 | ||
56e2e762 NC |
1664 | (define_insn "sle_insn" |
1665 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1666 | (le:SI (match_operand:SI 1 "register_operand" "r") | |
1667 | (match_operand:SI 2 "register_operand" "r"))) | |
58ebda9c | 1668 | (clobber (reg:CC 17))] |
56e2e762 NC |
1669 | "" |
1670 | "#" | |
1671 | [(set_attr "type" "multi") | |
1672 | (set_attr "length" "8")]) | |
1673 | ||
1674 | (define_split | |
1675 | [(set (match_operand:SI 0 "register_operand" "") | |
1676 | (le:SI (match_operand:SI 1 "register_operand" "") | |
1677 | (match_operand:SI 2 "register_operand" ""))) | |
58ebda9c | 1678 | (clobber (reg:CC 17))] |
56e2e762 | 1679 | "!optimize_size" |
58ebda9c KH |
1680 | [(set (reg:CC 17) |
1681 | (lt:CC (match_dup 2) | |
56e2e762 NC |
1682 | (match_dup 1))) |
1683 | (set (match_dup 0) | |
58ebda9c | 1684 | (ne:SI (reg:CC 17) (const_int 0))) |
56e2e762 NC |
1685 | (set (match_dup 0) |
1686 | (xor:SI (match_dup 0) | |
1687 | (const_int 1)))] | |
1688 | "") | |
1689 | ||
1690 | ;; If optimizing for space, use -(reg - 1) to invert the comparison rather than | |
1691 | ;; xor reg,reg,1 which might eliminate a NOP being inserted. | |
1692 | (define_split | |
1693 | [(set (match_operand:SI 0 "register_operand" "") | |
1694 | (le:SI (match_operand:SI 1 "register_operand" "") | |
1695 | (match_operand:SI 2 "register_operand" ""))) | |
58ebda9c | 1696 | (clobber (reg:CC 17))] |
56e2e762 | 1697 | "optimize_size" |
58ebda9c KH |
1698 | [(set (reg:CC 17) |
1699 | (lt:CC (match_dup 2) | |
56e2e762 NC |
1700 | (match_dup 1))) |
1701 | (set (match_dup 0) | |
58ebda9c | 1702 | (ne:SI (reg:CC 17) (const_int 0))) |
56e2e762 NC |
1703 | (set (match_dup 0) |
1704 | (plus:SI (match_dup 0) | |
1705 | (const_int -1))) | |
1706 | (set (match_dup 0) | |
1707 | (neg:SI (match_dup 0)))] | |
1708 | "") | |
1709 | ||
56e2e762 NC |
1710 | (define_insn "sge_insn" |
1711 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1712 | (ge:SI (match_operand:SI 1 "register_operand" "r,r") | |
1713 | (match_operand:SI 2 "reg_or_int16_operand" "r,J"))) | |
58ebda9c | 1714 | (clobber (reg:CC 17))] |
56e2e762 NC |
1715 | "" |
1716 | "#" | |
1717 | [(set_attr "type" "multi") | |
1718 | (set_attr "length" "8,10")]) | |
1719 | ||
1720 | (define_split | |
1721 | [(set (match_operand:SI 0 "register_operand" "") | |
1722 | (ge:SI (match_operand:SI 1 "register_operand" "") | |
1723 | (match_operand:SI 2 "reg_or_int16_operand" ""))) | |
58ebda9c | 1724 | (clobber (reg:CC 17))] |
56e2e762 | 1725 | "!optimize_size" |
58ebda9c KH |
1726 | [(set (reg:CC 17) |
1727 | (lt:CC (match_dup 1) | |
56e2e762 NC |
1728 | (match_dup 2))) |
1729 | (set (match_dup 0) | |
58ebda9c | 1730 | (ne:SI (reg:CC 17) (const_int 0))) |
56e2e762 NC |
1731 | (set (match_dup 0) |
1732 | (xor:SI (match_dup 0) | |
1733 | (const_int 1)))] | |
1734 | "") | |
1735 | ||
1736 | ;; If optimizing for space, use -(reg - 1) to invert the comparison rather than | |
1737 | ;; xor reg,reg,1 which might eliminate a NOP being inserted. | |
1738 | (define_split | |
1739 | [(set (match_operand:SI 0 "register_operand" "") | |
1740 | (ge:SI (match_operand:SI 1 "register_operand" "") | |
1741 | (match_operand:SI 2 "reg_or_int16_operand" ""))) | |
58ebda9c | 1742 | (clobber (reg:CC 17))] |
56e2e762 | 1743 | "optimize_size" |
58ebda9c KH |
1744 | [(set (reg:CC 17) |
1745 | (lt:CC (match_dup 1) | |
56e2e762 NC |
1746 | (match_dup 2))) |
1747 | (set (match_dup 0) | |
58ebda9c | 1748 | (ne:SI (reg:CC 17) (const_int 0))) |
56e2e762 NC |
1749 | (set (match_dup 0) |
1750 | (plus:SI (match_dup 0) | |
1751 | (const_int -1))) | |
1752 | (set (match_dup 0) | |
1753 | (neg:SI (match_dup 0)))] | |
1754 | "") | |
1755 | ||
56e2e762 NC |
1756 | (define_insn "sltu_insn" |
1757 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1758 | (ltu:SI (match_operand:SI 1 "register_operand" "r,r") | |
1759 | (match_operand:SI 2 "reg_or_int16_operand" "r,J"))) | |
58ebda9c | 1760 | (clobber (reg:CC 17))] |
56e2e762 NC |
1761 | "" |
1762 | "#" | |
1763 | [(set_attr "type" "multi") | |
1764 | (set_attr "length" "6,8")]) | |
1765 | ||
1766 | (define_split | |
1767 | [(set (match_operand:SI 0 "register_operand" "") | |
1768 | (ltu:SI (match_operand:SI 1 "register_operand" "") | |
1769 | (match_operand:SI 2 "reg_or_int16_operand" ""))) | |
58ebda9c | 1770 | (clobber (reg:CC 17))] |
56e2e762 | 1771 | "" |
58ebda9c KH |
1772 | [(set (reg:CC 17) |
1773 | (ltu:CC (match_dup 1) | |
56e2e762 NC |
1774 | (match_dup 2))) |
1775 | (set (match_dup 0) | |
58ebda9c | 1776 | (ne:SI (reg:CC 17) (const_int 0)))] |
56e2e762 NC |
1777 | "") |
1778 | ||
56e2e762 NC |
1779 | (define_insn "sleu_insn" |
1780 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1781 | (leu:SI (match_operand:SI 1 "register_operand" "r") | |
1782 | (match_operand:SI 2 "register_operand" "r"))) | |
58ebda9c | 1783 | (clobber (reg:CC 17))] |
56e2e762 NC |
1784 | "" |
1785 | "#" | |
1786 | [(set_attr "type" "multi") | |
1787 | (set_attr "length" "8")]) | |
1788 | ||
1789 | (define_split | |
1790 | [(set (match_operand:SI 0 "register_operand" "") | |
1791 | (leu:SI (match_operand:SI 1 "register_operand" "") | |
1792 | (match_operand:SI 2 "register_operand" ""))) | |
58ebda9c | 1793 | (clobber (reg:CC 17))] |
56e2e762 | 1794 | "!optimize_size" |
58ebda9c KH |
1795 | [(set (reg:CC 17) |
1796 | (ltu:CC (match_dup 2) | |
56e2e762 NC |
1797 | (match_dup 1))) |
1798 | (set (match_dup 0) | |
58ebda9c | 1799 | (ne:SI (reg:CC 17) (const_int 0))) |
56e2e762 NC |
1800 | (set (match_dup 0) |
1801 | (xor:SI (match_dup 0) | |
1802 | (const_int 1)))] | |
1803 | "") | |
1804 | ||
1805 | ;; If optimizing for space, use -(reg - 1) to invert the comparison rather than | |
1806 | ;; xor reg,reg,1 which might eliminate a NOP being inserted. | |
1807 | (define_split | |
1808 | [(set (match_operand:SI 0 "register_operand" "") | |
1809 | (leu:SI (match_operand:SI 1 "register_operand" "") | |
1810 | (match_operand:SI 2 "register_operand" ""))) | |
58ebda9c | 1811 | (clobber (reg:CC 17))] |
56e2e762 | 1812 | "optimize_size" |
58ebda9c KH |
1813 | [(set (reg:CC 17) |
1814 | (ltu:CC (match_dup 2) | |
56e2e762 NC |
1815 | (match_dup 1))) |
1816 | (set (match_dup 0) | |
58ebda9c | 1817 | (ne:SI (reg:CC 17) (const_int 0))) |
56e2e762 NC |
1818 | (set (match_dup 0) |
1819 | (plus:SI (match_dup 0) | |
1820 | (const_int -1))) | |
1821 | (set (match_dup 0) | |
1822 | (neg:SI (match_dup 0)))] | |
1823 | "") | |
1824 | ||
56e2e762 NC |
1825 | (define_insn "sgeu_insn" |
1826 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1827 | (geu:SI (match_operand:SI 1 "register_operand" "r,r") | |
1828 | (match_operand:SI 2 "reg_or_int16_operand" "r,J"))) | |
58ebda9c | 1829 | (clobber (reg:CC 17))] |
56e2e762 NC |
1830 | "" |
1831 | "#" | |
1832 | [(set_attr "type" "multi") | |
1833 | (set_attr "length" "8,10")]) | |
1834 | ||
1835 | (define_split | |
1836 | [(set (match_operand:SI 0 "register_operand" "") | |
1837 | (geu:SI (match_operand:SI 1 "register_operand" "") | |
1838 | (match_operand:SI 2 "reg_or_int16_operand" ""))) | |
58ebda9c | 1839 | (clobber (reg:CC 17))] |
56e2e762 | 1840 | "!optimize_size" |
58ebda9c KH |
1841 | [(set (reg:CC 17) |
1842 | (ltu:CC (match_dup 1) | |
56e2e762 NC |
1843 | (match_dup 2))) |
1844 | (set (match_dup 0) | |
58ebda9c | 1845 | (ne:SI (reg:CC 17) (const_int 0))) |
56e2e762 NC |
1846 | (set (match_dup 0) |
1847 | (xor:SI (match_dup 0) | |
1848 | (const_int 1)))] | |
1849 | "") | |
1850 | ||
1851 | ;; If optimizing for space, use -(reg - 1) to invert the comparison rather than | |
1852 | ;; xor reg,reg,1 which might eliminate a NOP being inserted. | |
1853 | (define_split | |
1854 | [(set (match_operand:SI 0 "register_operand" "") | |
1855 | (geu:SI (match_operand:SI 1 "register_operand" "") | |
1856 | (match_operand:SI 2 "reg_or_int16_operand" ""))) | |
58ebda9c | 1857 | (clobber (reg:CC 17))] |
56e2e762 | 1858 | "optimize_size" |
58ebda9c KH |
1859 | [(set (reg:CC 17) |
1860 | (ltu:CC (match_dup 1) | |
56e2e762 NC |
1861 | (match_dup 2))) |
1862 | (set (match_dup 0) | |
58ebda9c | 1863 | (ne:SI (reg:CC 17) (const_int 0))) |
56e2e762 NC |
1864 | (set (match_dup 0) |
1865 | (plus:SI (match_dup 0) | |
1866 | (const_int -1))) | |
1867 | (set (match_dup 0) | |
1868 | (neg:SI (match_dup 0)))] | |
1869 | "") | |
1870 | ||
1871 | (define_insn "movcc_insn" | |
1872 | [(set (match_operand:SI 0 "register_operand" "=r") | |
58ebda9c | 1873 | (ne:SI (reg:CC 17) (const_int 0)))] |
56e2e762 NC |
1874 | "" |
1875 | "mvfc %0, cbr" | |
1876 | [(set_attr "type" "misc") | |
1877 | (set_attr "length" "2")]) | |
1878 | ||
1879 | \f | |
8c5ca3b9 DE |
1880 | ;; Unconditional and other jump instructions. |
1881 | ||
1882 | (define_insn "jump" | |
1883 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
1884 | "" | |
1885 | "bra %l0" | |
1886 | [(set_attr "type" "uncond_branch") | |
1887 | (set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) | |
1888 | (const_int 400)) | |
1889 | (const_int 800)) | |
1890 | (const_int 2) | |
1891 | (const_int 4)))]) | |
1892 | ||
1893 | (define_insn "indirect_jump" | |
1894 | [(set (pc) (match_operand:SI 0 "address_operand" "p"))] | |
1895 | "" | |
1896 | "jmp %a0" | |
1897 | [(set_attr "type" "uncond_branch") | |
1898 | (set_attr "length" "2")]) | |
56e2e762 | 1899 | |
e2265be0 KK |
1900 | (define_insn "return_lr" |
1901 | [(parallel [(return) (use (reg:SI 14))])] | |
1902 | "" | |
56e2e762 NC |
1903 | "jmp lr" |
1904 | [(set_attr "type" "uncond_branch") | |
1905 | (set_attr "length" "2")]) | |
e2265be0 KK |
1906 | |
1907 | (define_insn "return_rte" | |
1908 | [(return)] | |
1909 | "" | |
1910 | "rte" | |
1911 | [(set_attr "type" "uncond_branch") | |
1912 | (set_attr "length" "2")]) | |
1913 | ||
1914 | (define_expand "return" | |
1915 | [(return)] | |
1916 | "direct_return ()" | |
1917 | " | |
1918 | { | |
1919 | emit_jump_insn (gen_return_lr ()); | |
1920 | DONE; | |
1921 | }") | |
1922 | ||
1923 | (define_expand "return_normal" | |
1924 | [(return)] | |
1925 | "!direct_return ()" | |
1926 | " | |
1927 | { | |
1928 | enum m32r_function_type fn_type; | |
1929 | ||
1930 | fn_type = m32r_compute_function_type (current_function_decl); | |
1931 | if (M32R_INTERRUPT_P (fn_type)) | |
1932 | { | |
1933 | emit_jump_insn (gen_return_rte ()); | |
1934 | DONE; | |
1935 | } | |
1936 | ||
1937 | emit_jump_insn (gen_return_lr ()); | |
1938 | DONE; | |
1939 | }") | |
1940 | ||
ad126521 KI |
1941 | (define_expand "tablejump" |
1942 | [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) | |
1943 | (use (label_ref (match_operand 1 "" "")))])] | |
1944 | "" | |
1945 | " | |
1946 | { | |
1947 | /* In pic mode, our address differences are against the base of the | |
1948 | table. Add that base value back in; CSE ought to be able to combine | |
1949 | the two address loads. */ | |
1950 | if (flag_pic) | |
1951 | { | |
1952 | rtx tmp, tmp2; | |
1953 | ||
1954 | tmp = gen_rtx_LABEL_REF (Pmode, operands[1]); | |
1955 | tmp2 = operands[0]; | |
1956 | tmp = gen_rtx_PLUS (Pmode, tmp2, tmp); | |
1957 | operands[0] = memory_address (Pmode, tmp); | |
1958 | } | |
1959 | }") | |
1960 | ||
1961 | (define_insn "*tablejump_insn" | |
8c5ca3b9 DE |
1962 | [(set (pc) (match_operand:SI 0 "address_operand" "p")) |
1963 | (use (label_ref (match_operand 1 "" "")))] | |
1964 | "" | |
1965 | "jmp %a0" | |
1966 | [(set_attr "type" "uncond_branch") | |
1967 | (set_attr "length" "2")]) | |
1968 | ||
1969 | (define_expand "call" | |
1970 | ;; operands[1] is stack_size_rtx | |
1971 | ;; operands[2] is next_arg_register | |
1972 | [(parallel [(call (match_operand:SI 0 "call_operand" "") | |
1973 | (match_operand 1 "" "")) | |
1974 | (clobber (reg:SI 14))])] | |
1975 | "" | |
ad126521 KI |
1976 | " |
1977 | { | |
1978 | if (flag_pic) | |
e3b5732b | 1979 | crtl->uses_pic_offset_table = 1; |
ad126521 | 1980 | }") |
8c5ca3b9 DE |
1981 | |
1982 | (define_insn "*call_via_reg" | |
1983 | [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) | |
1984 | (match_operand 1 "" "")) | |
1985 | (clobber (reg:SI 14))] | |
1986 | "" | |
1987 | "jl %0" | |
1988 | [(set_attr "type" "call") | |
1989 | (set_attr "length" "2")]) | |
1990 | ||
1991 | (define_insn "*call_via_label" | |
1992 | [(call (mem:SI (match_operand:SI 0 "call_address_operand" "")) | |
1993 | (match_operand 1 "" "")) | |
1994 | (clobber (reg:SI 14))] | |
1995 | "" | |
1996 | "* | |
1997 | { | |
1998 | int call26_p = call26_operand (operands[0], FUNCTION_MODE); | |
1999 | ||
2000 | if (! call26_p) | |
2001 | { | |
2002 | /* We may not be able to reach with a `bl' insn so punt and leave it to | |
2003 | the linker. | |
2004 | We do this here, rather than doing a force_reg in the define_expand | |
2005 | so these insns won't be separated, say by scheduling, thus simplifying | |
2006 | the linker. */ | |
2007 | return \"seth r14,%T0\;add3 r14,r14,%B0\;jl r14\"; | |
2008 | } | |
2009 | else | |
2010 | return \"bl %0\"; | |
2011 | }" | |
2012 | [(set_attr "type" "call") | |
2013 | (set (attr "length") | |
f18d1d16 | 2014 | (if_then_else (not (match_test "call26_operand (operands[0], FUNCTION_MODE)")) |
8c5ca3b9 DE |
2015 | (const_int 12) ; 10 + 2 for nop filler |
2016 | ; The return address must be on a 4 byte boundary so | |
2017 | ; there's no point in using a value of 2 here. A 2 byte | |
2018 | ; insn may go in the left slot but we currently can't | |
2019 | ; use such knowledge. | |
2020 | (const_int 4)))]) | |
2021 | ||
2022 | (define_expand "call_value" | |
2023 | ;; operand 2 is stack_size_rtx | |
2024 | ;; operand 3 is next_arg_register | |
2025 | [(parallel [(set (match_operand 0 "register_operand" "=r") | |
2026 | (call (match_operand:SI 1 "call_operand" "") | |
2027 | (match_operand 2 "" ""))) | |
2028 | (clobber (reg:SI 14))])] | |
2029 | "" | |
e2265be0 | 2030 | " |
ad126521 KI |
2031 | { |
2032 | if (flag_pic) | |
e3b5732b | 2033 | crtl->uses_pic_offset_table = 1; |
ad126521 | 2034 | }") |
8c5ca3b9 DE |
2035 | |
2036 | (define_insn "*call_value_via_reg" | |
2037 | [(set (match_operand 0 "register_operand" "=r") | |
2038 | (call (mem:SI (match_operand:SI 1 "register_operand" "r")) | |
2039 | (match_operand 2 "" ""))) | |
2040 | (clobber (reg:SI 14))] | |
2041 | "" | |
2042 | "jl %1" | |
2043 | [(set_attr "type" "call") | |
2044 | (set_attr "length" "2")]) | |
2045 | ||
2046 | (define_insn "*call_value_via_label" | |
2047 | [(set (match_operand 0 "register_operand" "=r") | |
2048 | (call (mem:SI (match_operand:SI 1 "call_address_operand" "")) | |
2049 | (match_operand 2 "" ""))) | |
2050 | (clobber (reg:SI 14))] | |
2051 | "" | |
2052 | "* | |
2053 | { | |
2054 | int call26_p = call26_operand (operands[1], FUNCTION_MODE); | |
2055 | ||
ad126521 | 2056 | if (flag_pic) |
e3b5732b | 2057 | crtl->uses_pic_offset_table = 1; |
ad126521 | 2058 | |
8c5ca3b9 DE |
2059 | if (! call26_p) |
2060 | { | |
2061 | /* We may not be able to reach with a `bl' insn so punt and leave it to | |
2062 | the linker. | |
2063 | We do this here, rather than doing a force_reg in the define_expand | |
2064 | so these insns won't be separated, say by scheduling, thus simplifying | |
2065 | the linker. */ | |
2066 | return \"seth r14,%T1\;add3 r14,r14,%B1\;jl r14\"; | |
2067 | } | |
2068 | else | |
2069 | return \"bl %1\"; | |
2070 | }" | |
2071 | [(set_attr "type" "call") | |
2072 | (set (attr "length") | |
f18d1d16 | 2073 | (if_then_else (not (match_test "call26_operand (operands[1], FUNCTION_MODE)")) |
8c5ca3b9 DE |
2074 | (const_int 12) ; 10 + 2 for nop filler |
2075 | ; The return address must be on a 4 byte boundary so | |
2076 | ; there's no point in using a value of 2 here. A 2 byte | |
2077 | ; insn may go in the left slot but we currently can't | |
2078 | ; use such knowledge. | |
2079 | (const_int 4)))]) | |
2080 | \f | |
2081 | (define_insn "nop" | |
2082 | [(const_int 0)] | |
2083 | "" | |
2084 | "nop" | |
5b8ae21f | 2085 | [(set_attr "type" "int2") |
8c5ca3b9 DE |
2086 | (set_attr "length" "2")]) |
2087 | ||
2088 | ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and | |
2089 | ;; all of memory. This blocks insns from being moved across this point. | |
2090 | ||
2091 | (define_insn "blockage" | |
a2ab189d | 2092 | [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] |
8c5ca3b9 DE |
2093 | "" |
2094 | "") | |
2095 | ||
2096 | ;; Special pattern to flush the icache. | |
2097 | ||
2098 | (define_insn "flush_icache" | |
a2ab189d KH |
2099 | [(unspec_volatile [(match_operand 0 "memory_operand" "m")] |
2100 | UNSPECV_FLUSH_ICACHE) | |
ad126521 KI |
2101 | (match_operand 1 "" "") |
2102 | (clobber (reg:SI 17))] | |
8c5ca3b9 | 2103 | "" |
ad126521 KI |
2104 | "* return \"trap %#%1 ; flush-icache\";" |
2105 | [(set_attr "type" "int4") | |
2106 | (set_attr "length" "4")]) | |
2b7972b0 | 2107 | \f |
56e2e762 NC |
2108 | ;; Speed up fabs and provide correct sign handling for -0 |
2109 | ||
2110 | (define_insn "absdf2" | |
2111 | [(set (match_operand:DF 0 "register_operand" "=r") | |
2112 | (abs:DF (match_operand:DF 1 "register_operand" "0")))] | |
2113 | "" | |
2114 | "#" | |
2115 | [(set_attr "type" "multi") | |
2116 | (set_attr "length" "4")]) | |
2117 | ||
2118 | (define_split | |
2119 | [(set (match_operand:DF 0 "register_operand" "") | |
2120 | (abs:DF (match_operand:DF 1 "register_operand" "")))] | |
2121 | "reload_completed" | |
2122 | [(set (match_dup 2) | |
2123 | (ashift:SI (match_dup 2) | |
2124 | (const_int 1))) | |
2125 | (set (match_dup 2) | |
2126 | (lshiftrt:SI (match_dup 2) | |
2127 | (const_int 1)))] | |
2128 | "operands[2] = gen_highpart (SImode, operands[0]);") | |
2129 | ||
2130 | (define_insn "abssf2" | |
2131 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2132 | (abs:SF (match_operand:SF 1 "register_operand" "0")))] | |
2133 | "" | |
2134 | "#" | |
2135 | [(set_attr "type" "multi") | |
2136 | (set_attr "length" "4")]) | |
2137 | ||
2138 | (define_split | |
2139 | [(set (match_operand:SF 0 "register_operand" "") | |
2140 | (abs:SF (match_operand:SF 1 "register_operand" "")))] | |
2141 | "reload_completed" | |
2142 | [(set (match_dup 2) | |
2143 | (ashift:SI (match_dup 2) | |
2144 | (const_int 1))) | |
2145 | (set (match_dup 2) | |
2146 | (lshiftrt:SI (match_dup 2) | |
2147 | (const_int 1)))] | |
2148 | "operands[2] = gen_highpart (SImode, operands[0]);") | |
2149 | \f | |
2b7972b0 MM |
2150 | ;; Conditional move instructions |
2151 | ;; Based on those done for the d10v | |
2152 | ||
2b7972b0 MM |
2153 | (define_expand "movsicc" |
2154 | [ | |
2155 | (set (match_operand:SI 0 "register_operand" "r") | |
2156 | (if_then_else:SI (match_operand 1 "" "") | |
2157 | (match_operand:SI 2 "conditional_move_operand" "O") | |
2158 | (match_operand:SI 3 "conditional_move_operand" "O") | |
2159 | ) | |
2160 | ) | |
2161 | ] | |
2162 | "" | |
2163 | " | |
2164 | { | |
20f46632 NC |
2165 | /* FIXME: This expansion is hold over from a failed conversion of this |
2166 | port away from using cc0. It still relies upon the last comparison | |
2167 | being the one that is now tested. Disabled for now in order to | |
2168 | improve the generation of working code. */ | |
2169 | FAIL; | |
2170 | ||
2b7972b0 MM |
2171 | if (! zero_and_one (operands [2], operands [3])) |
2172 | FAIL; | |
2173 | ||
67f63f32 | 2174 | /* Generate the comparison that will set the carry flag. */ |
f90b7a5a PB |
2175 | operands[1] = gen_compare (GET_CODE (operands[1]), XEXP (operands[1], 0), |
2176 | XEXP (operands[1], 1), TRUE); | |
2b7972b0 MM |
2177 | |
2178 | /* See other movsicc pattern below for reason why. */ | |
56e2e762 | 2179 | emit_insn (gen_blockage ()); |
2b7972b0 MM |
2180 | }") |
2181 | ||
2182 | ;; Generate the conditional instructions based on how the carry flag is examined. | |
2183 | (define_insn "*movsicc_internal" | |
997718c7 | 2184 | [(set (match_operand:SI 0 "register_operand" "=r") |
2b7972b0 MM |
2185 | (if_then_else:SI (match_operand 1 "carry_compare_operand" "") |
2186 | (match_operand:SI 2 "conditional_move_operand" "O") | |
2187 | (match_operand:SI 3 "conditional_move_operand" "O") | |
2188 | ) | |
2189 | )] | |
2190 | "zero_and_one (operands [2], operands[3])" | |
2191 | "* return emit_cond_move (operands, insn);" | |
5b8ae21f | 2192 | [(set_attr "type" "multi") |
2b7972b0 MM |
2193 | (set_attr "length" "8") |
2194 | ] | |
2195 | ) | |
2196 | ||
8c5ca3b9 | 2197 | \f |
d2a73f8e NC |
2198 | ;; Block moves, see m32r.c for more details. |
2199 | ;; Argument 0 is the destination | |
2200 | ;; Argument 1 is the source | |
2201 | ;; Argument 2 is the length | |
2202 | ;; Argument 3 is the alignment | |
2203 | ||
76715c32 | 2204 | (define_expand "cpymemsi" |
d2a73f8e NC |
2205 | [(parallel [(set (match_operand:BLK 0 "general_operand" "") |
2206 | (match_operand:BLK 1 "general_operand" "")) | |
2207 | (use (match_operand:SI 2 "immediate_operand" "")) | |
2208 | (use (match_operand:SI 3 "immediate_operand" ""))])] | |
2209 | "" | |
2210 | " | |
2211 | { | |
0be4693a | 2212 | if (operands[0]) /* Avoid unused code messages. */ |
d2a73f8e | 2213 | { |
0be4693a KI |
2214 | if (m32r_expand_block_move (operands)) |
2215 | DONE; | |
2216 | else | |
2217 | FAIL; | |
d2a73f8e NC |
2218 | } |
2219 | }") | |
2220 | ||
2221 | ;; Insn generated by block moves | |
2222 | ||
76715c32 | 2223 | (define_insn "cpymemsi_internal" |
81ad38a6 KH |
2224 | [(set (mem:BLK (match_operand:SI 0 "register_operand" "r")) ;; destination |
2225 | (mem:BLK (match_operand:SI 1 "register_operand" "r"))) ;; source | |
d2a73f8e | 2226 | (use (match_operand:SI 2 "m32r_block_immediate_operand" "J"));; # bytes to move |
81ad38a6 | 2227 | (set (match_operand:SI 3 "register_operand" "=0") |
085fd657 KI |
2228 | (plus:SI (minus (match_dup 2) (const_int 4)) |
2229 | (match_dup 0))) | |
81ad38a6 KH |
2230 | (set (match_operand:SI 4 "register_operand" "=1") |
2231 | (plus:SI (match_dup 1) | |
2232 | (match_dup 2))) | |
2233 | (clobber (match_scratch:SI 5 "=&r")) ;; temp1 | |
2234 | (clobber (match_scratch:SI 6 "=&r"))] ;; temp2 | |
d2a73f8e | 2235 | "" |
16f104b3 | 2236 | "* m32r_output_block_move (insn, operands); return \"\"; " |
d2a73f8e NC |
2237 | [(set_attr "type" "store8") |
2238 | (set_attr "length" "72")]) ;; Maximum | |
ad126521 KI |
2239 | |
2240 | ;; PIC | |
2241 | ||
2242 | /* When generating pic, we need to load the symbol offset into a register. | |
2243 | So that the optimizer does not confuse this with a normal symbol load | |
2244 | we use an unspec. The offset will be loaded from a constant pool entry, | |
2245 | since that is the only type of relocation we can use. */ | |
2246 | ||
2247 | (define_insn "pic_load_addr" | |
2248 | [(set (match_operand:SI 0 "register_operand" "=r") | |
a2ab189d | 2249 | (unspec:SI [(match_operand 1 "" "")] UNSPEC_PIC_LOAD_ADDR))] |
ad126521 KI |
2250 | "flag_pic" |
2251 | "ld24 %0,%#%1" | |
2252 | [(set_attr "type" "int4")]) | |
2253 | ||
c331bf08 KI |
2254 | (define_insn "gotoff_load_addr" |
2255 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2256 | (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFF))] | |
2257 | "flag_pic" | |
2258 | "seth %0, %#shigh(%1@GOTOFF)\;add3 %0, %0, low(%1@GOTOFF)" | |
2259 | [(set_attr "type" "int4") | |
2260 | (set_attr "length" "8")]) | |
2261 | ||
ad126521 KI |
2262 | ;; Load program counter insns. |
2263 | ||
2264 | (define_insn "get_pc" | |
2265 | [(clobber (reg:SI 14)) | |
3681df8f | 2266 | (set (match_operand 0 "register_operand" "=r,r") |
a2ab189d | 2267 | (unspec [(match_operand 1 "" "")] UNSPEC_GET_PC)) |
3681df8f | 2268 | (use (match_operand:SI 2 "immediate_operand" "W,i"))] |
ad126521 | 2269 | "flag_pic" |
3681df8f NC |
2270 | "@ |
2271 | bl.s .+4\;seth %0,%#shigh(%1)\;add3 %0,%0,%#low(%1+4)\;add %0,lr | |
2272 | bl.s .+4\;ld24 %0,%#%1\;add %0,lr" | |
2273 | [(set_attr "length" "12,8")]) | |
ad126521 KI |
2274 | |
2275 | (define_expand "builtin_setjmp_receiver" | |
2276 | [(label_ref (match_operand 0 "" ""))] | |
2277 | "flag_pic" | |
2278 | " | |
2279 | { | |
2280 | m32r_load_pic_register (); | |
2281 | DONE; | |
2282 | }") |