]>
Commit | Line | Data |
---|---|---|
309dd885 | 1 | ;; FR30 machine description. |
d652f226 | 2 | ;; Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005, 2007, 2010 |
f17178cf | 3 | ;; Free Software Foundation, Inc. |
309dd885 NC |
4 | ;; Contributed by Cygnus Solutions. |
5 | ||
7ec022b2 | 6 | ;; This file is part of GCC. |
309dd885 | 7 | |
7ec022b2 | 8 | ;; GCC is free software; you can redistribute it and/or modify |
309dd885 | 9 | ;; it under the terms of the GNU General Public License as published by |
2f83c7d6 | 10 | ;; the Free Software Foundation; either version 3, or (at your option) |
309dd885 NC |
11 | ;; any later version. |
12 | ||
7ec022b2 | 13 | ;; GCC is distributed in the hope that it will be useful, |
309dd885 NC |
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | ;; GNU General Public License for more details. | |
17 | ||
18 | ;; You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
19 | ;; along with GCC; see the file COPYING3. If not see |
20 | ;; <http://www.gnu.org/licenses/>. | |
309dd885 NC |
21 | |
22 | ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
23 | ||
309dd885 NC |
24 | ;;{{{ Attributes |
25 | ||
26 | (define_attr "length" "" (const_int 2)) | |
27 | ||
28 | ;; Used to distinguish between small memory model targets and big mode targets. | |
29 | ||
30 | (define_attr "size" "small,big" | |
31 | (const (if_then_else (symbol_ref "TARGET_SMALL_MODEL") | |
32 | (const_string "small") | |
33 | (const_string "big")))) | |
34 | ||
35 | ||
36 | ;; Define an attribute to be used by the delay slot code. | |
6fc0bb99 | 37 | ;; An instruction by default is considered to be 'delayable' |
309dd885 | 38 | ;; that is, it can be placed into a delay slot, but it is not |
40b982a9 | 39 | ;; itself a delayed branch type instruction. An instruction |
696e78bf KH |
40 | ;; whose type is 'delayed' is one which has a delay slot, and |
41 | ;; an instruction whose delay_type is 'other' is one which does | |
309dd885 NC |
42 | ;; not have a delay slot, nor can it be placed into a delay slot. |
43 | ||
44 | (define_attr "delay_type" "delayable,delayed,other" (const_string "delayable")) | |
45 | ||
46 | ;;}}} \f | |
47 | ;;{{{ Delay Slot Specifications | |
48 | ||
49 | (define_delay (eq_attr "delay_type" "delayed") | |
50 | [(and (eq_attr "delay_type" "delayable") | |
51 | (eq_attr "length" "2")) | |
52 | (nil) | |
53 | (nil)] | |
54 | ) | |
55 | ||
f17178cf | 56 | (include "predicates.md") |
ad1c1eeb | 57 | (include "constraints.md") |
f17178cf | 58 | |
309dd885 NC |
59 | ;;}}} |
60 | ;;{{{ Moves | |
61 | ||
62 | ;;{{{ Comment | |
63 | ||
64 | ;; Wrap moves in define_expand to prevent memory->memory moves from being | |
65 | ;; generated at the RTL level, which generates better code for most machines | |
66 | ;; which can't do mem->mem moves. | |
67 | ||
68 | ;; If operand 0 is a `subreg' with mode M of a register whose own mode is wider | |
69 | ;; than M, the effect of this instruction is to store the specified value in | |
70 | ;; the part of the register that corresponds to mode M. The effect on the rest | |
71 | ;; of the register is undefined. | |
72 | ||
73 | ;; This class of patterns is special in several ways. First of all, each of | |
74 | ;; these names *must* be defined, because there is no other way to copy a datum | |
75 | ;; from one place to another. | |
76 | ||
77 | ;; Second, these patterns are not used solely in the RTL generation pass. Even | |
78 | ;; the reload pass can generate move insns to copy values from stack slots into | |
79 | ;; temporary registers. When it does so, one of the operands is a hard | |
80 | ;; register and the other is an operand that can need to be reloaded into a | |
81 | ;; register. | |
82 | ||
83 | ;; Therefore, when given such a pair of operands, the pattern must | |
84 | ;; generate RTL which needs no reloading and needs no temporary | |
85 | ;; registers--no registers other than the operands. For example, if | |
86 | ;; you support the pattern with a `define_expand', then in such a | |
87 | ;; case the `define_expand' mustn't call `force_reg' or any other such | |
88 | ;; function which might generate new pseudo registers. | |
89 | ||
90 | ;; This requirement exists even for subword modes on a RISC machine | |
91 | ;; where fetching those modes from memory normally requires several | |
92 | ;; insns and some temporary registers. Look in `spur.md' to see how | |
93 | ;; the requirement can be satisfied. | |
94 | ||
95 | ;; During reload a memory reference with an invalid address may be passed as an | |
96 | ;; operand. Such an address will be replaced with a valid address later in the | |
97 | ;; reload pass. In this case, nothing may be done with the address except to | |
98 | ;; use it as it stands. If it is copied, it will not be replaced with a valid | |
99 | ;; address. No attempt should be made to make such an address into a valid | |
100 | ;; address and no routine (such as `change_address') that will do so may be | |
101 | ;; called. Note that `general_operand' will fail when applied to such an | |
102 | ;; address. | |
103 | ;; | |
104 | ;; The global variable `reload_in_progress' (which must be explicitly declared | |
105 | ;; if required) can be used to determine whether such special handling is | |
106 | ;; required. | |
107 | ;; | |
108 | ;; The variety of operands that have reloads depends on the rest of | |
109 | ;; the machine description, but typically on a RISC machine these can | |
110 | ;; only be pseudo registers that did not get hard registers, while on | |
111 | ;; other machines explicit memory references will get optional | |
112 | ;; reloads. | |
113 | ;; | |
114 | ;; If a scratch register is required to move an object to or from memory, it | |
115 | ;; can be allocated using `gen_reg_rtx' prior to reload. But this is | |
116 | ;; impossible during and after reload. If there are cases needing scratch | |
117 | ;; registers after reload, you must define `SECONDARY_INPUT_RELOAD_CLASS' and | |
118 | ;; perhaps also `SECONDARY_OUTPUT_RELOAD_CLASS' to detect them, and provide | |
119 | ;; patterns `reload_inM' or `reload_outM' to handle them. | |
120 | ||
121 | ;; The constraints on a `moveM' must permit moving any hard register to any | |
122 | ;; other hard register provided that `HARD_REGNO_MODE_OK' permits mode M in | |
123 | ;; both registers and `REGISTER_MOVE_COST' applied to their classes returns a | |
124 | ;; value of 2. | |
125 | ||
126 | ;; It is obligatory to support floating point `moveM' instructions | |
127 | ;; into and out of any registers that can hold fixed point values, | |
128 | ;; because unions and structures (which have modes `SImode' or | |
129 | ;; `DImode') can be in those registers and they may have floating | |
130 | ;; point members. | |
131 | ||
132 | ;; There may also be a need to support fixed point `moveM' instructions in and | |
133 | ;; out of floating point registers. Unfortunately, I have forgotten why this | |
134 | ;; was so, and I don't know whether it is still true. If `HARD_REGNO_MODE_OK' | |
135 | ;; rejects fixed point values in floating point registers, then the constraints | |
136 | ;; of the fixed point `moveM' instructions must be designed to avoid ever | |
137 | ;; trying to reload into a floating point register. | |
138 | ||
139 | ;;}}} | |
140 | ;;{{{ Push and Pop | |
141 | ||
142 | ;; Push a register onto the stack | |
143 | (define_insn "movsi_push" | |
a7edae0a MS |
144 | [(set (mem:SI (pre_dec:SI (reg:SI 15))) |
145 | (match_operand:SI 0 "register_operand" "a"))] | |
309dd885 NC |
146 | "" |
147 | "st %0, @-r15" | |
148 | ) | |
149 | ||
150 | ;; Pop a register off the stack | |
151 | (define_insn "movsi_pop" | |
a7edae0a MS |
152 | [(set (match_operand:SI 0 "register_operand" "=a") |
153 | (mem:SI (post_inc:SI (reg:SI 15))))] | |
309dd885 NC |
154 | "" |
155 | "ld @r15+, %0" | |
156 | ) | |
157 | ||
158 | ;;}}} | |
159 | ;;{{{ 1 Byte Moves | |
160 | ||
161 | (define_expand "movqi" | |
162 | [(set (match_operand:QI 0 "general_operand" "") | |
163 | (match_operand:QI 1 "general_operand" ""))] | |
164 | "" | |
165 | " | |
166 | { | |
167 | if (!reload_in_progress | |
168 | && !reload_completed | |
169 | && GET_CODE (operands[0]) == MEM | |
170 | && (GET_CODE (operands[1]) == MEM | |
171 | || immediate_operand (operands[1], QImode))) | |
172 | operands[1] = copy_to_mode_reg (QImode, operands[1]); | |
173 | }") | |
174 | ||
175 | (define_insn "movqi_unsigned_register_load" | |
176 | [(set (match_operand:SI 0 "register_operand" "=r") | |
177 | (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] | |
178 | "" | |
179 | "ldub %1, %0" | |
180 | ) | |
181 | ||
182 | (define_expand "movqi_signed_register_load" | |
183 | [(set (match_operand:SI 0 "register_operand" "") | |
184 | (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))] | |
185 | "" | |
186 | " | |
187 | emit_insn (gen_movqi_unsigned_register_load (operands[0], operands[1])); | |
188 | emit_insn (gen_extendqisi2 (operands[0], operands[0])); | |
189 | DONE; | |
190 | " | |
191 | ) | |
192 | ||
193 | (define_insn "*movqi_internal" | |
194 | [(set (match_operand:QI 0 "nonimmediate_operand" "=r,red,m,r") | |
195 | (match_operand:QI 1 "general_operand" "i,red,r,rm"))] | |
196 | "" | |
197 | "@ | |
198 | ldi:8\\t#%A1, %0 | |
199 | mov \\t%1, %0 | |
200 | stb \\t%1, %0 | |
201 | ldub \\t%1, %0" | |
202 | ) | |
203 | ||
204 | ;;}}} | |
205 | ;;{{{ 2 Byte Moves | |
206 | ||
207 | (define_expand "movhi" | |
208 | [(set (match_operand:HI 0 "general_operand" "") | |
209 | (match_operand:HI 1 "general_operand" ""))] | |
210 | "" | |
211 | " | |
212 | { | |
213 | if (!reload_in_progress | |
214 | && !reload_completed | |
215 | && GET_CODE (operands[0]) == MEM | |
216 | && (GET_CODE (operands[1]) == MEM | |
217 | || immediate_operand (operands[1], HImode))) | |
218 | operands[1] = copy_to_mode_reg (HImode, operands[1]); | |
219 | }") | |
220 | ||
221 | (define_insn "movhi_unsigned_register_load" | |
222 | [(set (match_operand:SI 0 "register_operand" "=r") | |
223 | (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] | |
224 | "" | |
225 | "lduh %1, %0" | |
226 | ) | |
227 | ||
228 | (define_expand "movhi_signed_register_load" | |
229 | [(set (match_operand:SI 0 "register_operand" "") | |
230 | (sign_extend:SI (match_operand:HI 1 "memory_operand" "")))] | |
231 | "" | |
232 | " | |
233 | emit_insn (gen_movhi_unsigned_register_load (operands[0], operands[1])); | |
234 | emit_insn (gen_extendhisi2 (operands[0], operands[0])); | |
235 | DONE; | |
236 | " | |
237 | ) | |
238 | ||
239 | (define_insn "*movhi_internal" | |
240 | [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,red,m,r") | |
241 | (match_operand:HI 1 "general_operand" "L,M,n,red,r,rm"))] | |
242 | "" | |
243 | "@ | |
244 | ldi:8 \\t#%1, %0 | |
245 | ldi:20\\t#%1, %0 | |
246 | ldi:32\\t#%1, %0 | |
247 | mov \\t%1, %0 | |
248 | sth \\t%1, %0 | |
249 | lduh \\t%1, %0" | |
250 | [(set_attr "length" "*,4,6,*,*,*")] | |
251 | ) | |
252 | ||
253 | ;;}}} | |
254 | ;;{{{ 4 Byte Moves | |
255 | ||
256 | ;; If the destination is a MEM and the source is a | |
257 | ;; MEM or an CONST_INT move the source into a register. | |
258 | (define_expand "movsi" | |
259 | [(set (match_operand:SI 0 "nonimmediate_operand" "") | |
260 | (match_operand:SI 1 "general_operand" ""))] | |
261 | "" | |
262 | "{ | |
263 | if (!reload_in_progress | |
264 | && !reload_completed | |
265 | && GET_CODE(operands[0]) == MEM | |
266 | && (GET_CODE (operands[1]) == MEM | |
267 | || immediate_operand (operands[1], SImode))) | |
268 | operands[1] = copy_to_mode_reg (SImode, operands[1]); | |
269 | }" | |
270 | ) | |
271 | ||
272 | ;; We can do some clever tricks when loading certain immediate | |
273 | ;; values. We implement these tricks as define_splits, rather | |
274 | ;; than putting the code into the define_expand "movsi" above, | |
275 | ;; because if we put them there, they will be evaluated at RTL | |
276 | ;; generation time and then the combiner pass will come along | |
277 | ;; and replace the multiple insns that have been generated with | |
278 | ;; the original, slower, load insns. (The combiner pass only | |
279 | ;; cares about reducing the number of instructions, it does not | |
280 | ;; care about instruction lengths or speeds). Splits are | |
281 | ;; evaluated after the combine pass and before the scheduling | |
282 | ;; passes, so that they are the perfect place to put this | |
283 | ;; intelligence. | |
284 | ;; | |
285 | ;; XXX we probably ought to implement these for QI and HI mode | |
286 | ;; loads as well. | |
287 | ||
288 | ;; If we are loading a small negative constant we can save space | |
289 | ;; and time by loading the positive value and then sign extending it. | |
290 | (define_split | |
997718c7 | 291 | [(set (match_operand:SI 0 "register_operand" "") |
5c7666c1 | 292 | (match_operand:SI 1 "const_int_operand" ""))] |
acb188c1 RS |
293 | "INTVAL (operands[1]) <= -1 && INTVAL (operands[1]) >= -128 |
294 | && (GET_CODE (operands[0]) != SUBREG | |
295 | || SCALAR_INT_MODE_P (GET_MODE (XEXP (operands[0], 0))))" | |
a7edae0a MS |
296 | [(set (match_dup 0) (match_dup 1)) |
297 | (set (match_dup 0) (sign_extend:SI (match_dup 2)))] | |
309dd885 | 298 | "{ |
5c7666c1 NC |
299 | operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff); |
300 | operands[2] = gen_lowpart (QImode, operands[0]); | |
309dd885 NC |
301 | }" |
302 | ) | |
303 | ||
304 | ;; If we are loading a large negative constant, one which does | |
305 | ;; not have any of its bottom 24 bit set, then we can save time | |
306 | ;; and space by loading the byte value and shifting it into place. | |
307 | (define_split | |
997718c7 | 308 | [(set (match_operand:SI 0 "register_operand" "") |
5c7666c1 NC |
309 | (match_operand:SI 1 "const_int_operand" ""))] |
310 | "(INTVAL (operands[1]) < 0) && ((INTVAL (operands[1]) & 0x00ffffff) == 0)" | |
a7edae0a MS |
311 | [(set (match_dup 0) (match_dup 2)) |
312 | (parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 24))) | |
309dd885 NC |
313 | (clobber (reg:CC 16))])] |
314 | "{ | |
315 | HOST_WIDE_INT val = INTVAL (operands[1]); | |
316 | operands[2] = GEN_INT (val >> 24); | |
317 | }" | |
318 | ) | |
319 | ||
320 | ;; If we are loading a large positive constant, one which has bits | |
696e78bf | 321 | ;; in the top byte set, but whose set bits all lie within an 8 bit |
309dd885 NC |
322 | ;; range, then we can save time and space by loading the byte value |
323 | ;; and shifting it into place. | |
324 | (define_split | |
997718c7 | 325 | [(set (match_operand:SI 0 "register_operand" "") |
5c7666c1 | 326 | (match_operand:SI 1 "const_int_operand" ""))] |
309dd885 | 327 | "(INTVAL (operands[1]) > 0x00ffffff) |
5c7666c1 | 328 | && ((INTVAL (operands[1]) >> exact_log2 (INTVAL (operands[1]) & (- INTVAL (operands[1])))) < 0x100)" |
a7edae0a MS |
329 | [(set (match_dup 0) (match_dup 2)) |
330 | (parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 3))) | |
309dd885 NC |
331 | (clobber (reg:CC 16))])] |
332 | "{ | |
333 | HOST_WIDE_INT val = INTVAL (operands[1]); | |
334 | int shift = exact_log2 (val & ( - val)); | |
335 | operands[2] = GEN_INT (val >> shift); | |
336 | operands[3] = GEN_INT (shift); | |
337 | }" | |
338 | ) | |
339 | ||
340 | ;; When TARGET_SMALL_MODEL is defined we assume that all symbolic | |
341 | ;; values are addresses which will fit in 20 bits. | |
342 | ||
343 | (define_insn "movsi_internal" | |
08937250 LP |
344 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,red,V,r,m") |
345 | (match_operand:SI 1 "general_operand" "L,M,n,i,rde,r,rm,r"))] | |
309dd885 NC |
346 | "" |
347 | "* | |
348 | { | |
349 | switch (which_alternative) | |
350 | { | |
351 | case 0: return \"ldi:8 \\t#%1, %0\"; | |
352 | case 1: return \"ldi:20\\t#%1, %0\"; | |
353 | case 2: return \"ldi:32\\t#%1, %0\"; | |
354 | case 3: if (TARGET_SMALL_MODEL) | |
355 | return \"ldi:20\\t%1, %0\"; | |
356 | else | |
357 | return \"ldi:32\\t%1, %0\"; | |
358 | case 4: return \"mov \\t%1, %0\"; | |
359 | case 5: return \"st \\t%1, %0\"; | |
360 | case 6: return \"ld \\t%1, %0\"; | |
08937250 LP |
361 | case 7: return \"st \\t%1, %0\"; |
362 | default: gcc_unreachable (); | |
363 | } | |
309dd885 NC |
364 | }" |
365 | [(set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 4) | |
366 | (eq_attr "alternative" "2") (const_int 6) | |
367 | (eq_attr "alternative" "3") | |
368 | (if_then_else (eq_attr "size" "small") | |
369 | (const_int 4) | |
370 | (const_int 6))] | |
371 | (const_int 2)))] | |
372 | ) | |
373 | ||
aeb4f5ef NC |
374 | ;;}}} |
375 | ;;{{{ 8 Byte Moves | |
376 | ||
377 | ;; Note - the FR30 does not have an 8 byte load/store instruction | |
378 | ;; but we have to support this pattern because some other patterns | |
112cdef5 | 379 | ;; (e.g. muldisi2) can produce a DImode result. |
aeb4f5ef NC |
380 | ;; (This code is stolen from the M32R port.) |
381 | ||
382 | (define_expand "movdi" | |
ed31d14c LP |
383 | [(set (match_operand:DI 0 "nonimmediate_operand" "") |
384 | (match_operand:DI 1 "general_operand" ""))] | |
aeb4f5ef NC |
385 | "" |
386 | " | |
387 | /* Everything except mem = const or mem = mem can be done easily. */ | |
ed31d14c | 388 | |
aeb4f5ef NC |
389 | if (GET_CODE (operands[0]) == MEM) |
390 | operands[1] = force_reg (DImode, operands[1]); | |
ed31d14c LP |
391 | " |
392 | ) | |
aeb4f5ef NC |
393 | |
394 | ;; We use an insn and a split so that we can generate | |
395 | ;; RTL rather than text from fr30_move_double(). | |
396 | ||
397 | (define_insn "*movdi_insn" | |
398 | [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,m,r") | |
ed31d14c | 399 | (match_operand:DI 1 "di_operand" "r,m,r,nF"))] |
aeb4f5ef NC |
400 | "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" |
401 | "#" | |
402 | [(set_attr "length" "4,8,12,12")] | |
403 | ) | |
404 | ||
405 | (define_split | |
406 | [(set (match_operand:DI 0 "nonimmediate_di_operand" "") | |
ed31d14c | 407 | (match_operand:DI 1 "di_operand" ""))] |
aeb4f5ef NC |
408 | "reload_completed" |
409 | [(match_dup 2)] | |
ed31d14c LP |
410 | "operands[2] = fr30_move_double (operands);" |
411 | ) | |
aeb4f5ef | 412 | |
309dd885 NC |
413 | ;;}}} |
414 | ;;{{{ Load & Store Multiple Registers | |
415 | ||
416 | ;; The load multiple and store multiple patterns are implemented | |
417 | ;; as peepholes because the only time they are expected to occur | |
418 | ;; is during function prologues and epilogues. | |
419 | ||
420 | (define_peephole | |
a7edae0a MS |
421 | [(set (mem:SI (pre_dec:SI (reg:SI 15))) |
422 | (match_operand:SI 0 "high_register_operand" "h")) | |
423 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
424 | (match_operand:SI 1 "high_register_operand" "h")) | |
425 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
426 | (match_operand:SI 2 "high_register_operand" "h")) | |
427 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
428 | (match_operand:SI 3 "high_register_operand" "h"))] | |
309dd885 NC |
429 | "fr30_check_multiple_regs (operands, 4, 1)" |
430 | "stm1 (%0, %1, %2, %3)" | |
431 | [(set_attr "delay_type" "other")] | |
432 | ) | |
433 | ||
434 | (define_peephole | |
a7edae0a MS |
435 | [(set (mem:SI (pre_dec:SI (reg:SI 15))) |
436 | (match_operand:SI 0 "high_register_operand" "h")) | |
437 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
438 | (match_operand:SI 1 "high_register_operand" "h")) | |
439 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
440 | (match_operand:SI 2 "high_register_operand" "h"))] | |
309dd885 NC |
441 | "fr30_check_multiple_regs (operands, 3, 1)" |
442 | "stm1 (%0, %1, %2)" | |
443 | [(set_attr "delay_type" "other")] | |
444 | ) | |
445 | ||
446 | (define_peephole | |
a7edae0a MS |
447 | [(set (mem:SI (pre_dec:SI (reg:SI 15))) |
448 | (match_operand:SI 0 "high_register_operand" "h")) | |
449 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
450 | (match_operand:SI 1 "high_register_operand" "h"))] | |
309dd885 NC |
451 | "fr30_check_multiple_regs (operands, 2, 1)" |
452 | "stm1 (%0, %1)" | |
453 | [(set_attr "delay_type" "other")] | |
454 | ) | |
455 | ||
456 | (define_peephole | |
a7edae0a MS |
457 | [(set (match_operand:SI 0 "high_register_operand" "h") |
458 | (mem:SI (post_inc:SI (reg:SI 15)))) | |
459 | (set (match_operand:SI 1 "high_register_operand" "h") | |
460 | (mem:SI (post_inc:SI (reg:SI 15)))) | |
461 | (set (match_operand:SI 2 "high_register_operand" "h") | |
462 | (mem:SI (post_inc:SI (reg:SI 15)))) | |
463 | (set (match_operand:SI 3 "high_register_operand" "h") | |
464 | (mem:SI (post_inc:SI (reg:SI 15))))] | |
309dd885 NC |
465 | "fr30_check_multiple_regs (operands, 4, 0)" |
466 | "ldm1 (%0, %1, %2, %3)" | |
467 | [(set_attr "delay_type" "other")] | |
468 | ) | |
469 | ||
470 | (define_peephole | |
a7edae0a MS |
471 | [(set (match_operand:SI 0 "high_register_operand" "h") |
472 | (mem:SI (post_inc:SI (reg:SI 15)))) | |
473 | (set (match_operand:SI 1 "high_register_operand" "h") | |
474 | (mem:SI (post_inc:SI (reg:SI 15)))) | |
475 | (set (match_operand:SI 2 "high_register_operand" "h") | |
476 | (mem:SI (post_inc:SI (reg:SI 15))))] | |
309dd885 NC |
477 | "fr30_check_multiple_regs (operands, 3, 0)" |
478 | "ldm1 (%0, %1, %2)" | |
479 | [(set_attr "delay_type" "other")] | |
480 | ) | |
481 | ||
482 | (define_peephole | |
a7edae0a MS |
483 | [(set (match_operand:SI 0 "high_register_operand" "h") |
484 | (mem:SI (post_inc:SI (reg:SI 15)))) | |
485 | (set (match_operand:SI 1 "high_register_operand" "h") | |
486 | (mem:SI (post_inc:SI (reg:SI 15))))] | |
309dd885 NC |
487 | "fr30_check_multiple_regs (operands, 2, 0)" |
488 | "ldm1 (%0, %1)" | |
489 | [(set_attr "delay_type" "other")] | |
490 | ) | |
491 | ||
492 | (define_peephole | |
a7edae0a MS |
493 | [(set (mem:SI (pre_dec:SI (reg:SI 15))) |
494 | (match_operand:SI 0 "low_register_operand" "l")) | |
495 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
496 | (match_operand:SI 1 "low_register_operand" "l")) | |
497 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
498 | (match_operand:SI 2 "low_register_operand" "l")) | |
499 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
500 | (match_operand:SI 3 "low_register_operand" "l"))] | |
309dd885 NC |
501 | "fr30_check_multiple_regs (operands, 4, 1)" |
502 | "stm0 (%0, %1, %2, %3)" | |
503 | [(set_attr "delay_type" "other")] | |
504 | ) | |
505 | ||
506 | (define_peephole | |
a7edae0a MS |
507 | [(set (mem:SI (pre_dec:SI (reg:SI 15))) |
508 | (match_operand:SI 0 "low_register_operand" "l")) | |
509 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
510 | (match_operand:SI 1 "low_register_operand" "l")) | |
511 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
512 | (match_operand:SI 2 "low_register_operand" "l"))] | |
309dd885 NC |
513 | "fr30_check_multiple_regs (operands, 3, 1)" |
514 | "stm0 (%0, %1, %2)" | |
515 | [(set_attr "delay_type" "other")] | |
516 | ) | |
517 | ||
518 | (define_peephole | |
a7edae0a MS |
519 | [(set (mem:SI (pre_dec:SI (reg:SI 15))) |
520 | (match_operand:SI 0 "low_register_operand" "l")) | |
521 | (set (mem:SI (pre_dec:SI (reg:SI 15))) | |
522 | (match_operand:SI 1 "low_register_operand" "l"))] | |
309dd885 NC |
523 | "fr30_check_multiple_regs (operands, 2, 1)" |
524 | "stm0 (%0, %1)" | |
525 | [(set_attr "delay_type" "other")] | |
526 | ) | |
527 | ||
528 | ;;}}} | |
529 | ;;{{{ Floating Point Moves | |
530 | ||
531 | ;; Note - Patterns for SF mode moves are compulsory, but | |
05713b80 | 532 | ;; patterns for DF are optional, as GCC can synthesize them. |
309dd885 NC |
533 | |
534 | (define_expand "movsf" | |
535 | [(set (match_operand:SF 0 "general_operand" "") | |
536 | (match_operand:SF 1 "general_operand" ""))] | |
537 | "" | |
538 | "{ | |
539 | if (!reload_in_progress && !reload_completed | |
540 | && memory_operand (operands[0], SFmode) | |
541 | && memory_operand (operands[1], SFmode)) | |
542 | operands[1] = copy_to_mode_reg (SFmode, operands[1]); | |
543 | }" | |
544 | ) | |
545 | ||
546 | (define_insn "*movsf_internal" | |
547 | [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,red,m,r") | |
548 | (match_operand:SF 1 "general_operand" "Fn,i,rde,r,rm"))] | |
549 | "" | |
550 | "* | |
551 | { | |
552 | switch (which_alternative) | |
553 | { | |
554 | case 0: return \"ldi:32\\t%1, %0\"; | |
555 | case 1: if (TARGET_SMALL_MODEL) | |
556 | return \"ldi:20\\t%1, %0\"; | |
557 | else | |
558 | return \"ldi:32\\t%1, %0\"; | |
559 | case 2: return \"mov \\t%1, %0\"; | |
560 | case 3: return \"st \\t%1, %0\"; | |
561 | case 4: return \"ld \\t%1, %0\"; | |
4e81e7c2 | 562 | default: gcc_unreachable (); |
309dd885 NC |
563 | } |
564 | }" | |
565 | [(set (attr "length") (cond [(eq_attr "alternative" "0") (const_int 6) | |
566 | (eq_attr "alternative" "1") | |
567 | (if_then_else (eq_attr "size" "small") | |
568 | (const_int 4) | |
569 | (const_int 6))] | |
570 | (const_int 2)))] | |
571 | ) | |
572 | ||
573 | (define_insn "*movsf_constant_store" | |
997718c7 | 574 | [(set (match_operand:SF 0 "memory_operand" "=m") |
309dd885 NC |
575 | (match_operand:SF 1 "immediate_operand" "F"))] |
576 | "" | |
577 | "* | |
578 | { | |
1943c2c1 | 579 | const char * ldi_instr; |
82a9bba5 | 580 | const char * tmp_reg; |
309dd885 | 581 | static char buffer[100]; |
309dd885 | 582 | |
02809efd | 583 | ldi_instr = fr30_const_double_is_zero (operands[1]) ? \"ldi:8\" : \"ldi:32\"; |
309dd885 NC |
584 | |
585 | tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER]; | |
586 | ||
587 | sprintf (buffer, \"%s\\t#%%1, %s\\t;\\n\\tst\\t%s, %%0\\t; Created by movsf_constant_store\", | |
588 | ldi_instr, tmp_reg, tmp_reg); | |
589 | ||
590 | return buffer; | |
591 | }" | |
592 | [(set_attr "length" "8")] | |
593 | ) | |
594 | ||
595 | ;;}}} | |
596 | ||
597 | ;;}}} \f | |
598 | ;;{{{ Conversions | |
599 | ||
600 | ;; Signed conversions from a smaller integer to a larger integer | |
601 | ||
602 | (define_insn "extendqisi2" | |
603 | [(set (match_operand:SI 0 "register_operand" "=r") | |
604 | (sign_extend:SI (match_operand:QI 1 "register_operand" "0")))] | |
605 | "" | |
606 | "extsb %0" | |
607 | ) | |
608 | ||
609 | (define_insn "extendhisi2" | |
610 | [(set (match_operand:SI 0 "register_operand" "=r") | |
611 | (sign_extend:SI (match_operand:HI 1 "register_operand" "0")))] | |
612 | "" | |
613 | "extsh %0" | |
614 | ) | |
615 | ||
616 | ;; Unsigned conversions from a smaller integer to a larger integer | |
617 | ||
618 | (define_insn "zero_extendqisi2" | |
619 | [(set (match_operand:SI 0 "register_operand" "=r") | |
620 | (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))] | |
621 | "" | |
622 | "extub %0" | |
623 | ) | |
624 | ||
625 | (define_insn "zero_extendhisi2" | |
626 | [(set (match_operand:SI 0 "register_operand" "=r") | |
627 | (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))] | |
628 | "" | |
629 | "extuh %0" | |
630 | ) | |
631 | ||
632 | ;;}}} \f | |
633 | ;;{{{ Arithmetic | |
634 | ||
635 | ;;{{{ Addition | |
636 | ||
637 | ;; This is a special pattern just for adjusting the stack size. | |
638 | (define_insn "add_to_stack" | |
639 | [(set (reg:SI 15) | |
640 | (plus:SI (reg:SI 15) | |
641 | (match_operand:SI 0 "stack_add_operand" "i")))] | |
642 | "" | |
643 | "addsp %0" | |
644 | ) | |
645 | ||
646 | ;; We need some trickery to be able to handle the addition of | |
112cdef5 | 647 | ;; large (i.e. outside +/- 16) constants. We need to be able to |
309dd885 | 648 | ;; handle this because reload assumes that it can generate add |
839a4992 | 649 | ;; instructions with arbitrary sized constants. |
309dd885 NC |
650 | (define_expand "addsi3" |
651 | [(set (match_operand:SI 0 "register_operand" "") | |
652 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
653 | (match_operand:SI 2 "nonmemory_operand" "")))] | |
654 | "" | |
655 | "{ | |
656 | if ( GET_CODE (operands[2]) == REG | |
657 | || GET_CODE (operands[2]) == SUBREG) | |
658 | emit_insn (gen_addsi_regs (operands[0], operands[1], operands[2])); | |
659 | else if (GET_CODE (operands[2]) != CONST_INT) | |
660 | emit_insn (gen_addsi_big_int (operands[0], operands[1], operands[2])); | |
a02ee5b2 RS |
661 | else if (INTVAL (operands[2]) >= -16 |
662 | && INTVAL (operands[2]) <= 15 | |
e2972de5 RIL |
663 | && (!REG_P (operands[1]) |
664 | || !REGNO_PTR_FRAME_P (REGNO (operands[1])) | |
a02ee5b2 | 665 | || REGNO (operands[1]) == STACK_POINTER_REGNUM)) |
309dd885 NC |
666 | emit_insn (gen_addsi_small_int (operands[0], operands[1], operands[2])); |
667 | else | |
668 | emit_insn (gen_addsi_big_int (operands[0], operands[1], operands[2])); | |
669 | DONE; | |
670 | }" | |
671 | ) | |
672 | ||
673 | (define_insn "addsi_regs" | |
674 | [(set (match_operand:SI 0 "register_operand" "=r") | |
675 | (plus:SI (match_operand:SI 1 "register_operand" "%0") | |
676 | (match_operand:SI 2 "register_operand" "r")))] | |
677 | "" | |
678 | "addn %2, %0" | |
679 | ) | |
680 | ||
aaceac0b | 681 | ;; Do not allow an eliminable register in the source register. It |
9cd10576 | 682 | ;; might be eliminated in favor of the stack pointer, probably |
aaceac0b | 683 | ;; increasing the offset, and so rendering the instruction illegal. |
309dd885 NC |
684 | (define_insn "addsi_small_int" |
685 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
686 | (plus:SI (match_operand:SI 1 "register_operand" "0,0") | |
687 | (match_operand:SI 2 "add_immediate_operand" "I,J")))] | |
e2972de5 RIL |
688 | "!REG_P (operands[1]) |
689 | || !REGNO_PTR_FRAME_P (REGNO (operands[1])) | |
a02ee5b2 | 690 | || REGNO (operands[1]) == STACK_POINTER_REGNUM" |
309dd885 NC |
691 | "@ |
692 | addn %2, %0 | |
693 | addn2 %2, %0" | |
694 | ) | |
695 | ||
696 | (define_expand "addsi_big_int" | |
697 | [(set (match_operand:SI 0 "register_operand" "") | |
698 | (plus:SI (match_operand:SI 1 "register_operand" "") | |
699 | (match_operand:SI 2 "immediate_operand" "")))] | |
700 | "" | |
701 | "{ | |
702 | /* Cope with the possibility that ops 0 and 1 are the same register. */ | |
e2972de5 | 703 | if (rtx_equal_p (operands[0], operands[1])) |
309dd885 NC |
704 | { |
705 | if (reload_in_progress || reload_completed) | |
706 | { | |
707 | rtx reg = gen_rtx_REG (SImode, 0/*COMPILER_SCRATCH_REGISTER*/); | |
708 | ||
709 | emit_insn (gen_movsi (reg, operands[2])); | |
710 | emit_insn (gen_addsi_regs (operands[0], operands[0], reg)); | |
711 | } | |
712 | else | |
713 | { | |
714 | operands[2] = force_reg (SImode, operands[2]); | |
715 | emit_insn (gen_addsi_regs (operands[0], operands[0], operands[2])); | |
716 | } | |
717 | } | |
718 | else | |
719 | { | |
720 | emit_insn (gen_movsi (operands[0], operands[2])); | |
721 | emit_insn (gen_addsi_regs (operands[0], operands[0], operands[1])); | |
722 | } | |
723 | DONE; | |
724 | }" | |
725 | ) | |
726 | ||
727 | (define_insn "*addsi_for_reload" | |
728 | [(set (match_operand:SI 0 "register_operand" "=&r,r,r") | |
729 | (plus:SI (match_operand:SI 1 "register_operand" "r,r,r") | |
730 | (match_operand:SI 2 "immediate_operand" "L,M,n")))] | |
731 | "reload_in_progress || reload_completed" | |
732 | "@ | |
733 | ldi:8\\t#%2, %0 \\n\\taddn\\t%1, %0 | |
734 | ldi:20\\t#%2, %0 \\n\\taddn\\t%1, %0 | |
735 | ldi:32\\t#%2, %0 \\n\\taddn\\t%1, %0" | |
736 | [(set_attr "length" "4,6,8")] | |
737 | ) | |
738 | ||
739 | ;;}}} | |
740 | ;;{{{ Subtraction | |
741 | ||
742 | (define_insn "subsi3" | |
743 | [(set (match_operand:SI 0 "register_operand" "=r") | |
997718c7 RH |
744 | (minus:SI (match_operand:SI 1 "register_operand" "0") |
745 | (match_operand:SI 2 "register_operand" "r")))] | |
309dd885 NC |
746 | "" |
747 | "subn %2, %0" | |
748 | ) | |
749 | ||
750 | ;;}}} | |
751 | ;;{{{ Multiplication | |
752 | ||
a7b376ee | 753 | ;; Signed multiplication producing 64-bit results from 32-bit inputs |
309dd885 NC |
754 | (define_insn "mulsidi3" |
755 | [(set (match_operand:DI 0 "register_operand" "=r") | |
756 | (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%r")) | |
757 | (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))) | |
758 | (clobber (reg:CC 16))] | |
759 | "" | |
760 | "mul %2, %1\\n\\tmov\\tmdh, %0\\n\\tmov\\tmdl, %p0" | |
761 | [(set_attr "length" "6")] | |
762 | ) | |
763 | ||
a7b376ee | 764 | ;; Unsigned multiplication producing 64-bit results from 32-bit inputs |
309dd885 NC |
765 | (define_insn "umulsidi3" |
766 | [(set (match_operand:DI 0 "register_operand" "=r") | |
767 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%r")) | |
768 | (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))) | |
769 | (clobber (reg:CC 16))] | |
770 | "" | |
771 | "mulu %2, %1\\n\\tmov\\tmdh, %0\\n\\tmov\\tmdl, %p0" | |
772 | [(set_attr "length" "6")] | |
773 | ) | |
774 | ||
a7b376ee | 775 | ;; Signed multiplication producing 32-bit result from 16-bit inputs |
309dd885 NC |
776 | (define_insn "mulhisi3" |
777 | [(set (match_operand:SI 0 "register_operand" "=r") | |
778 | (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r")) | |
779 | (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))) | |
780 | (clobber (reg:CC 16))] | |
781 | "" | |
782 | "mulh %2, %1\\n\\tmov\\tmdl, %0" | |
783 | [(set_attr "length" "4")] | |
784 | ) | |
785 | ||
a7b376ee | 786 | ;; Unsigned multiplication producing 32-bit result from 16-bit inputs |
309dd885 NC |
787 | (define_insn "umulhisi3" |
788 | [(set (match_operand:SI 0 "register_operand" "=r") | |
789 | (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%r")) | |
790 | (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))) | |
791 | (clobber (reg:CC 16))] | |
792 | "" | |
793 | "muluh %2, %1\\n\\tmov\\tmdl, %0" | |
794 | [(set_attr "length" "4")] | |
795 | ) | |
796 | ||
a7b376ee | 797 | ;; Signed multiplication producing 32-bit result from 32-bit inputs |
309dd885 NC |
798 | (define_insn "mulsi3" |
799 | [(set (match_operand:SI 0 "register_operand" "=r") | |
800 | (mult:SI (match_operand:SI 1 "register_operand" "%r") | |
801 | (match_operand:SI 2 "register_operand" "r"))) | |
802 | (clobber (reg:CC 16))] | |
803 | "" | |
804 | "mul %2, %1\\n\\tmov\\tmdl, %0" | |
805 | [(set_attr "length" "4")] | |
806 | ) | |
807 | ||
808 | ;;}}} | |
309dd885 NC |
809 | ;;}}} \f |
810 | ;;{{{ Shifts | |
811 | ||
812 | ;; Arithmetic Shift Left | |
813 | (define_insn "ashlsi3" | |
814 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
815 | (ashift:SI (match_operand:SI 1 "register_operand" "0,0,0") | |
816 | (match_operand:SI 2 "nonmemory_operand" "r,I,K"))) | |
817 | (clobber (reg:CC 16))] | |
818 | "" | |
819 | "@ | |
820 | lsl %2, %0 | |
821 | lsl %2, %0 | |
822 | lsl2 %x2, %0" | |
823 | ) | |
824 | ||
825 | ;; Arithmetic Shift Right | |
826 | (define_insn "ashrsi3" | |
827 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
828 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0") | |
829 | (match_operand:SI 2 "nonmemory_operand" "r,I,K"))) | |
830 | (clobber (reg:CC 16))] | |
831 | "" | |
832 | "@ | |
833 | asr %2, %0 | |
834 | asr %2, %0 | |
835 | asr2 %x2, %0" | |
836 | ) | |
837 | ||
838 | ;; Logical Shift Right | |
839 | (define_insn "lshrsi3" | |
840 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
841 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,0") | |
842 | (match_operand:SI 2 "nonmemory_operand" "r,I,K"))) | |
843 | (clobber (reg:CC 16))] | |
844 | "" | |
845 | "@ | |
846 | lsr %2, %0 | |
847 | lsr %2, %0 | |
848 | lsr2 %x2, %0" | |
849 | ) | |
850 | ||
851 | ;;}}} \f | |
852 | ;;{{{ Logical Operations | |
853 | ||
a7b376ee | 854 | ;; Logical AND, 32-bit integers |
309dd885 NC |
855 | (define_insn "andsi3" |
856 | [(set (match_operand:SI 0 "register_operand" "=r") | |
857 | (and:SI (match_operand:SI 1 "register_operand" "%r") | |
858 | (match_operand:SI 2 "register_operand" "0"))) | |
859 | (clobber (reg:CC 16))] | |
860 | "" | |
861 | "and %1, %0" | |
862 | ) | |
863 | ||
a7b376ee | 864 | ;; Inclusive OR, 32-bit integers |
309dd885 NC |
865 | (define_insn "iorsi3" |
866 | [(set (match_operand:SI 0 "register_operand" "=r") | |
867 | (ior:SI (match_operand:SI 1 "register_operand" "%r") | |
868 | (match_operand:SI 2 "register_operand" "0"))) | |
869 | (clobber (reg:CC 16))] | |
870 | "" | |
871 | "or %1, %0" | |
872 | ) | |
873 | ||
a7b376ee | 874 | ;; Exclusive OR, 32-bit integers |
309dd885 NC |
875 | (define_insn "xorsi3" |
876 | [(set (match_operand:SI 0 "register_operand" "=r") | |
877 | (xor:SI (match_operand:SI 1 "register_operand" "%r") | |
878 | (match_operand:SI 2 "register_operand" "0"))) | |
879 | (clobber (reg:CC 16))] | |
880 | "" | |
881 | "eor %1, %0" | |
882 | ) | |
883 | ||
a7b376ee | 884 | ;; One's complement, 32-bit integers |
309dd885 NC |
885 | (define_expand "one_cmplsi2" |
886 | [(set (match_operand:SI 0 "register_operand" "") | |
887 | (not:SI (match_operand:SI 1 "register_operand" "")))] | |
888 | "" | |
889 | "{ | |
e2972de5 | 890 | if (rtx_equal_p (operands[0], operands[1])) |
309dd885 NC |
891 | { |
892 | if (reload_in_progress || reload_completed) | |
893 | { | |
894 | rtx reg = gen_rtx_REG (SImode, 0/*COMPILER_SCRATCH_REGISTER*/); | |
895 | ||
a556fd39 | 896 | emit_insn (gen_movsi (reg, constm1_rtx)); |
309dd885 NC |
897 | emit_insn (gen_xorsi3 (operands[0], operands[0], reg)); |
898 | } | |
899 | else | |
900 | { | |
901 | rtx reg = gen_reg_rtx (SImode); | |
902 | ||
a556fd39 | 903 | emit_insn (gen_movsi (reg, constm1_rtx)); |
309dd885 NC |
904 | emit_insn (gen_xorsi3 (operands[0], operands[0], reg)); |
905 | } | |
906 | } | |
907 | else | |
908 | { | |
a556fd39 | 909 | emit_insn (gen_movsi_internal (operands[0], constm1_rtx)); |
309dd885 NC |
910 | emit_insn (gen_xorsi3 (operands[0], operands[1], operands[0])); |
911 | } | |
912 | DONE; | |
913 | }" | |
914 | ) | |
915 | ||
916 | ;;}}} \f | |
917 | ;;{{{ Comparisons | |
918 | ||
f90b7a5a | 919 | ;; The actual comparisons, generated by the cbranch and/or cstore expanders |
309dd885 NC |
920 | |
921 | (define_insn "*cmpsi_internal" | |
922 | [(set (reg:CC 16) | |
923 | (compare:CC (match_operand:SI 0 "register_operand" "r,r,r") | |
924 | (match_operand:SI 1 "nonmemory_operand" "r,I,J")))] | |
925 | "" | |
926 | "@ | |
927 | cmp %1, %0 | |
928 | cmp %1, %0 | |
929 | cmp2 %1, %0" | |
930 | ) | |
931 | ||
932 | ;;}}} \f | |
933 | ;;{{{ Branches | |
934 | ||
935 | ;; Define_expands called by the machine independent part of the compiler | |
936 | ;; to allocate a new comparison register | |
937 | ||
f90b7a5a | 938 | (define_expand "cbranchsi4" |
309dd885 | 939 | [(set (reg:CC 16) |
f90b7a5a PB |
940 | (compare:CC (match_operand:SI 1 "register_operand" "") |
941 | (match_operand:SI 2 "nonmemory_operand" ""))) | |
309dd885 | 942 | (set (pc) |
baecdd1e | 943 | (if_then_else (match_operator 0 "ordered_comparison_operator" |
f90b7a5a PB |
944 | [(reg:CC 16) (const_int 0)]) |
945 | (label_ref (match_operand 3 "" "")) | |
309dd885 NC |
946 | (pc)))] |
947 | "" | |
309dd885 | 948 | "" |
309dd885 NC |
949 | ) |
950 | ||
309dd885 NC |
951 | |
952 | ;; Actual branches. We must allow for the (label_ref) and the (pc) to be | |
953 | ;; swapped. If they are swapped, it reverses the sense of the branch. | |
954 | ||
955 | ;; This pattern matches the (branch-if-true) branches generated above. | |
956 | ;; It generates two different instruction sequences depending upon how | |
957 | ;; far away the destination is. | |
958 | ||
959 | ;; The calculation for the instruction length is derived as follows: | |
a7b376ee | 960 | ;; The branch instruction has a 9-bit signed displacement so we have |
309dd885 NC |
961 | ;; this inequality for the displacement: |
962 | ;; | |
963 | ;; -256 <= pc < 256 | |
964 | ;; or | |
965 | ;; -256 + 256 <= pc + 256 < 256 + 256 | |
112cdef5 | 966 | ;; i.e. |
309dd885 NC |
967 | ;; 0 <= pc + 256 < 512 |
968 | ;; | |
969 | ;; if we consider the displacement as an unsigned value, then negative | |
970 | ;; displacements become very large positive displacements, and the | |
971 | ;; inequality becomes: | |
972 | ;; | |
973 | ;; pc + 256 < 512 | |
974 | ;; | |
975 | ;; In order to allow for the fact that the real branch instruction works | |
976 | ;; from pc + 2, we increase the offset to 258. | |
977 | ;; | |
978 | ;; Note - we do not have to worry about whether the branch is delayed or | |
272d0bee | 979 | ;; not, as branch shortening happens after delay slot reorganization. |
309dd885 NC |
980 | |
981 | (define_insn "*branch_true" | |
982 | [(set (pc) | |
baecdd1e NC |
983 | (if_then_else (match_operator 0 "comparison_operator" |
984 | [(reg:CC 16) | |
985 | (const_int 0)]) | |
309dd885 NC |
986 | (label_ref (match_operand 1 "" "")) |
987 | (pc)))] | |
988 | "" | |
989 | "* | |
990 | { | |
991 | if (get_attr_length (insn) == 2) | |
992 | return \"b%b0%#\\t%l1\"; | |
993 | else | |
994 | { | |
82a9bba5 NC |
995 | static char buffer [100]; |
996 | const char * tmp_reg; | |
1943c2c1 | 997 | const char * ldi_insn; |
309dd885 NC |
998 | |
999 | tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER]; | |
1000 | ||
1001 | ldi_insn = TARGET_SMALL_MODEL ? \"ldi:20\" : \"ldi:32\"; | |
1002 | ||
1003 | /* The code produced here is, for say the EQ case: | |
1004 | ||
1005 | Bne 1f | |
1006 | LDI <label>, r0 | |
1007 | JMP r0 | |
1008 | 1: */ | |
1009 | ||
1010 | sprintf (buffer, | |
1011 | \"b%%B0\\t1f\\t;\\n\\t%s\\t%%l1, %s\\t;\\n\\tjmp%%#\\t@%s\\t;\\n1:\", | |
1012 | ldi_insn, tmp_reg, tmp_reg); | |
1013 | ||
1014 | return buffer; | |
1015 | } | |
1016 | }" | |
1017 | [(set (attr "length") (if_then_else | |
1018 | (ltu | |
1019 | (plus | |
1020 | (minus | |
1021 | (match_dup 1) | |
1022 | (pc)) | |
1023 | (const_int 254)) | |
1024 | (const_int 506)) | |
1025 | (const_int 2) | |
1026 | (if_then_else (eq_attr "size" "small") | |
1027 | (const_int 8) | |
1028 | (const_int 10)))) | |
1029 | (set_attr "delay_type" "delayed")] | |
1030 | ) | |
1031 | ||
1032 | ||
1033 | ;; This pattern is a duplicate of the previous one, except that the | |
1034 | ;; branch occurs if the test is false, so the %B operator is used. | |
1035 | (define_insn "*branch_false" | |
1036 | [(set (pc) | |
baecdd1e NC |
1037 | (if_then_else (match_operator 0 "comparison_operator" |
1038 | [(reg:CC 16) | |
1039 | (const_int 0)]) | |
309dd885 NC |
1040 | (pc) |
1041 | (label_ref (match_operand 1 "" ""))))] | |
1042 | "" | |
1043 | "* | |
1044 | { | |
1045 | if (get_attr_length (insn) == 2) | |
1046 | return \"b%B0%#\\t%l1 \"; | |
1047 | else | |
1048 | { | |
82a9bba5 NC |
1049 | static char buffer [100]; |
1050 | const char * tmp_reg; | |
1943c2c1 | 1051 | const char * ldi_insn; |
309dd885 NC |
1052 | |
1053 | tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER]; | |
1054 | ||
1055 | ldi_insn = TARGET_SMALL_MODEL ? \"ldi:20\" : \"ldi:32\"; | |
1056 | ||
1057 | sprintf (buffer, | |
1058 | \"b%%b0\\t1f\\t;\\n\\t%s\\t%%l1, %s\\t;\\n\\tjmp%%#\\t@%s\\t;\\n1:\", | |
1059 | ldi_insn, tmp_reg, tmp_reg); | |
1060 | ||
1061 | return buffer; | |
1062 | } | |
1063 | }" | |
1064 | [(set (attr "length") (if_then_else (ltu (plus (minus (match_dup 1) (pc)) | |
1065 | (const_int 254)) | |
1066 | (const_int 506)) | |
1067 | (const_int 2) | |
1068 | (if_then_else (eq_attr "size" "small") | |
1069 | (const_int 8) | |
1070 | (const_int 10)))) | |
1071 | (set_attr "delay_type" "delayed")] | |
1072 | ) | |
1073 | ||
1074 | ;;}}} \f | |
1075 | ;;{{{ Calls & Jumps | |
1076 | ||
1077 | ;; Subroutine call instruction returning no value. Operand 0 is the function | |
1078 | ;; to call; operand 1 is the number of bytes of arguments pushed (in mode | |
1079 | ;; `SImode', except it is normally a `const_int'); operand 2 is the number of | |
1080 | ;; registers used as operands. | |
1081 | ||
1082 | (define_insn "call" | |
6e11d5e9 | 1083 | [(call (match_operand 0 "call_operand" "Qm") |
309dd885 NC |
1084 | (match_operand 1 "" "g")) |
1085 | (clobber (reg:SI 17))] | |
1086 | "" | |
1087 | "call%#\\t%0" | |
1088 | [(set_attr "delay_type" "delayed")] | |
1089 | ) | |
1090 | ||
1091 | ;; Subroutine call instruction returning a value. Operand 0 is the hard | |
1092 | ;; register in which the value is returned. There are three more operands, the | |
1093 | ;; same as the three operands of the `call' instruction (but with numbers | |
1094 | ;; increased by one). | |
1095 | ||
1096 | ;; Subroutines that return `BLKmode' objects use the `call' insn. | |
1097 | ||
1098 | (define_insn "call_value" | |
1099 | [(set (match_operand 0 "register_operand" "=r") | |
6e11d5e9 | 1100 | (call (match_operand 1 "call_operand" "Qm") |
309dd885 NC |
1101 | (match_operand 2 "" "g"))) |
1102 | (clobber (reg:SI 17))] | |
1103 | "" | |
1104 | "call%#\\t%1" | |
1105 | [(set_attr "delay_type" "delayed")] | |
1106 | ) | |
1107 | ||
1108 | ;; Normal unconditional jump. | |
1109 | ;; For a description of the computation of the length | |
1110 | ;; attribute see the branch patterns above. | |
a29b099d JJ |
1111 | ;; |
1112 | ;; Although this instruction really clobbers r0, flow | |
1113 | ;; relies on jump being simplejump_p in several places | |
1114 | ;; and as r0 is fixed, this doesn't change anything | |
309dd885 | 1115 | (define_insn "jump" |
a29b099d | 1116 | [(set (pc) (label_ref (match_operand 0 "" "")))] |
309dd885 NC |
1117 | "" |
1118 | "* | |
1119 | { | |
1120 | if (get_attr_length (insn) == 2) | |
1121 | return \"bra%#\\t%0\"; | |
1122 | else | |
1123 | { | |
82a9bba5 NC |
1124 | static char buffer [100]; |
1125 | const char * tmp_reg; | |
1943c2c1 | 1126 | const char * ldi_insn; |
309dd885 NC |
1127 | |
1128 | tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER]; | |
1129 | ||
1130 | ldi_insn = TARGET_SMALL_MODEL ? \"ldi:20\" : \"ldi:32\"; | |
1131 | ||
1132 | sprintf (buffer, \"%s\\t%%0, %s\\t;\\n\\tjmp%%#\\t@%s\\t;\", | |
1133 | ldi_insn, tmp_reg, tmp_reg); | |
1134 | ||
1135 | return buffer; | |
1136 | } | |
1137 | }" | |
1138 | [(set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc)) | |
1139 | (const_int 254)) | |
1140 | (const_int 506)) | |
1141 | (const_int 2) | |
1142 | (if_then_else (eq_attr "size" "small") | |
1143 | (const_int 6) | |
1144 | (const_int 8)))) | |
1145 | (set_attr "delay_type" "delayed")] | |
1146 | ) | |
1147 | ||
1148 | ;; Indirect jump through a register | |
1149 | (define_insn "indirect_jump" | |
1150 | [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "r"))] | |
1151 | "GET_CODE (operands[0]) != MEM || GET_CODE (XEXP (operands[0], 0)) != PLUS" | |
1152 | "jmp%#\\t@%0" | |
1153 | [(set_attr "delay_type" "delayed")] | |
1154 | ) | |
1155 | ||
1156 | (define_insn "tablejump" | |
1157 | [(set (pc) (match_operand:SI 0 "register_operand" "r")) | |
1158 | (use (label_ref (match_operand 1 "" "")))] | |
1159 | "" | |
1160 | "jmp%#\\t@%0" | |
1161 | [(set_attr "delay_type" "delayed")] | |
1162 | ) | |
1163 | ||
1164 | ;;}}} \f | |
1165 | ;;{{{ Function Prologues and Epilogues | |
1166 | ||
1167 | ;; Called after register allocation to add any instructions needed for the | |
1168 | ;; prologue. Using a prologue insn is favored compared to putting all of the | |
08c148a8 | 1169 | ;; instructions in output_function_prologue(), since it allows the scheduler |
309dd885 NC |
1170 | ;; to intermix instructions with the saves of the caller saved registers. In |
1171 | ;; some cases, it might be necessary to emit a barrier instruction as the last | |
1172 | ;; insn to prevent such scheduling. | |
1173 | (define_expand "prologue" | |
82a9bba5 | 1174 | [(clobber (const_int 0))] |
309dd885 NC |
1175 | "" |
1176 | "{ | |
1177 | fr30_expand_prologue (); | |
1178 | DONE; | |
1179 | }" | |
1180 | ) | |
1181 | ||
1182 | ;; Called after register allocation to add any instructions needed for the | |
5519a4f9 | 1183 | ;; epilogue. Using an epilogue insn is favored compared to putting all of the |
08c148a8 | 1184 | ;; instructions in output_function_epilogue(), since it allows the scheduler |
309dd885 NC |
1185 | ;; to intermix instructions with the restores of the caller saved registers. |
1186 | ;; In some cases, it might be necessary to emit a barrier instruction as the | |
1187 | ;; first insn to prevent such scheduling. | |
1188 | (define_expand "epilogue" | |
1189 | [(return)] | |
1190 | "" | |
1191 | "{ | |
1192 | fr30_expand_epilogue (); | |
1193 | DONE; | |
1194 | }" | |
1195 | ) | |
1196 | ||
1197 | (define_insn "return_from_func" | |
1198 | [(return) | |
1199 | (use (reg:SI 17))] | |
1200 | "reload_completed" | |
1201 | "ret%#" | |
1202 | [(set_attr "delay_type" "delayed")] | |
1203 | ) | |
1204 | ||
1205 | (define_insn "leave_func" | |
0db0c836 NF |
1206 | [(set (reg:SI 15) (plus:SI (reg:SI 14) (const_int 4))) |
1207 | (set (reg:SI 14) (mem:SI (minus:SI (reg:SI 15) (const_int 4))))] | |
309dd885 NC |
1208 | "reload_completed" |
1209 | "leave" | |
1210 | ) | |
1211 | ||
e2972de5 RIL |
1212 | (define_expand "enter_func" |
1213 | [(parallel | |
a7edae0a MS |
1214 | [(set (mem:SI (minus:SI (match_dup 1) |
1215 | (const_int 4))) | |
1216 | (match_dup 2)) | |
1217 | (set (match_dup 2) | |
1218 | (minus:SI (match_dup 1) | |
1219 | (const_int 4))) | |
1220 | (set (match_dup 1) | |
1221 | (minus:SI (match_dup 1) | |
1222 | (match_operand:SI 0 "immediate_operand")))] | |
e2972de5 RIL |
1223 | )] |
1224 | "" | |
1225 | { | |
1226 | operands[1] = stack_pointer_rtx; | |
1227 | operands[2] = hard_frame_pointer_rtx; | |
1228 | }) | |
1229 | ||
1230 | (define_insn "*enter_func" | |
a7edae0a MS |
1231 | [(set (mem:SI (minus:SI (reg:SI 15) |
1232 | (const_int 4))) | |
1233 | (reg:SI 14)) | |
1234 | (set (reg:SI 14) | |
1235 | (minus:SI (reg:SI 15) | |
1236 | (const_int 4))) | |
1237 | (set (reg:SI 15) | |
1238 | (minus:SI (reg:SI 15) | |
1239 | (match_operand 0 "immediate_operand" "i")))] | |
309dd885 NC |
1240 | "reload_completed" |
1241 | "enter #%0" | |
1242 | [(set_attr "delay_type" "other")] | |
1243 | ) | |
1244 | ||
1245 | ;;}}} \f | |
1246 | ;;{{{ Miscellaneous | |
1247 | ||
1248 | ;; No operation, needed in case the user uses -g but not -O. | |
1249 | (define_insn "nop" | |
1250 | [(const_int 0)] | |
1251 | "" | |
1252 | "nop" | |
1253 | ) | |
1254 | ||
1255 | ;; Pseudo instruction that prevents the scheduler from moving code above this | |
1256 | ;; point. | |
1257 | (define_insn "blockage" | |
1258 | [(unspec_volatile [(const_int 0)] 0)] | |
1259 | "" | |
1260 | "" | |
1261 | [(set_attr "length" "0")] | |
1262 | ) | |
5c7666c1 | 1263 | ;;}}} \f |
309dd885 NC |
1264 | |
1265 | ;; Local Variables: | |
1266 | ;; mode: md | |
1267 | ;; folded-file: t | |
1268 | ;; End: |