]>
Commit | Line | Data |
---|---|---|
51aea58d | 1 | ;;- Machine description for the Hitachi SH. |
d38fbd28 | 2 | ;; Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. |
51aea58d JW |
3 | ;; Contributed by Steve Chamberlain (sac@cygnus.com). |
4 | ;; Improved by Jim Wilson (wilson@cygnus.com). | |
bc45ade3 SC |
5 | |
6 | ;; This file is part of GNU CC. | |
7 | ||
8 | ;; GNU CC is free software; you can redistribute it and/or modify | |
9 | ;; it under the terms of the GNU General Public License as published by | |
10 | ;; the Free Software Foundation; either version 2, or (at your option) | |
11 | ;; any later version. | |
12 | ||
13 | ;; GNU CC is distributed in the hope that it will be useful, | |
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 | |
19 | ;; along with GNU CC; see the file COPYING. If not, write to | |
3f63df56 RK |
20 | ;; the Free Software Foundation, 59 Temple Place - Suite 330, |
21 | ;; Boston, MA 02111-1307, USA. | |
bc45ade3 | 22 | |
bc45ade3 | 23 | |
d0aae509 RK |
24 | ;; ??? Should prepend a * to all pattern names which are not used. |
25 | ;; This will make the compiler smaller, and rebuilds after changes faster. | |
26 | ||
ffae286a JW |
27 | ;; ??? Should be enhanced to include support for many more GNU superoptimizer |
28 | ;; sequences. Especially the sequences for arithmetic right shifts. | |
29 | ||
30 | ;; ??? Should check all DImode patterns for consistency and usefulness. | |
31 | ||
51bd623f JW |
32 | ;; ??? The MAC.W and MAC.L instructions are not supported. There is no |
33 | ;; way to generate them. | |
34 | ||
ffae286a JW |
35 | ;; ??? The cmp/str instruction is not supported. Perhaps it can be used |
36 | ;; for a str* inline function. | |
37 | ||
4ed4cb9a JR |
38 | ;; BSR is not generated by the compiler proper, but when relaxing, it |
39 | ;; generates .uses pseudo-ops that allow linker relaxation to create | |
40 | ;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c | |
41 | ||
0d7e008e SC |
42 | ;; Special constraints for SH machine description: |
43 | ;; | |
07a45e5c JW |
44 | ;; t -- T |
45 | ;; x -- mac | |
46 | ;; l -- pr | |
0d7e008e SC |
47 | ;; z -- r0 |
48 | ;; | |
49 | ;; Special formats used for outputting SH instructions: | |
50 | ;; | |
51 | ;; %. -- print a .s if insn needs delay slot | |
51aea58d | 52 | ;; %@ -- print rte/rts if is/isn't an interrupt function |
0d7e008e | 53 | ;; %# -- output a nop if there is nothing to put in the delay slot |
0d7e008e | 54 | ;; %O -- print a constant without the # |
51aea58d JW |
55 | ;; %R -- print the lsw reg of a double |
56 | ;; %S -- print the msw reg of a double | |
57 | ;; %T -- print next word of a double REG or MEM | |
0d7e008e SC |
58 | ;; |
59 | ;; Special predicates: | |
60 | ;; | |
61 | ;; arith_operand -- operand is valid source for arithmetic op | |
62 | ;; arith_reg_operand -- operand is valid register for arithmetic op | |
0d7e008e SC |
63 | ;; general_movdst_operand -- operand is valid move destination |
64 | ;; general_movsrc_operand -- operand is valid move source | |
65 | ;; logical_operand -- operand is valid source for logical op | |
bc45ade3 SC |
66 | ;; ------------------------------------------------------------------------- |
67 | ;; Attributes | |
68 | ;; ------------------------------------------------------------------------- | |
69 | ||
eeb531d5 | 70 | ;; Target CPU. |
b9654711 | 71 | |
1245df60 R |
72 | (define_attr "cpu" |
73 | "sh1,sh2,sh3,sh3e" | |
07a45e5c | 74 | (const (symbol_ref "sh_cpu_attr"))) |
961c4780 | 75 | |
1245df60 R |
76 | (define_attr "endian" "big,little" |
77 | (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN") | |
78 | (const_string "little") (const_string "big")))) | |
79 | ||
0d7e008e SC |
80 | ;; cbranch conditional branch instructions |
81 | ;; jump unconditional jumps | |
82 | ;; arith ordinary arithmetic | |
956d6950 | 83 | ;; arith3 a compound insn that behaves similarly to a sequence of |
1245df60 R |
84 | ;; three insns of type arith |
85 | ;; arith3b like above, but might end with a redirected branch | |
0d7e008e | 86 | ;; load from memory |
1245df60 | 87 | ;; load_si Likewise, SImode variant for general register. |
0d7e008e SC |
88 | ;; store to memory |
89 | ;; move register to register | |
1245df60 | 90 | ;; fmove register to register, floating point |
51bd623f JW |
91 | ;; smpy word precision integer multiply |
92 | ;; dmpy longword or doublelongword precision integer multiply | |
0d7e008e | 93 | ;; return rts |
ffae286a JW |
94 | ;; pload load of pr reg, which can't be put into delay slot of rts |
95 | ;; pstore store of pr reg, which can't be put into delay slot of jsr | |
22e1ebf1 | 96 | ;; pcload pc relative load of constant value |
1245df60 | 97 | ;; pcload_si Likewise, SImode variant for general register. |
0d7e008e SC |
98 | ;; rte return from exception |
99 | ;; sfunc special function call with known used registers | |
ffae286a | 100 | ;; call function call |
c1aef54d ILT |
101 | ;; fp floating point |
102 | ;; fdiv floating point divide (or square root) | |
1245df60 | 103 | ;; gp_fpul move between general purpose register and fpul |
4dff12bf | 104 | ;; nil no-op move, will be deleted. |
0d7e008e | 105 | |
07a45e5c | 106 | (define_attr "type" |
4dff12bf | 107 | "cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,other,load,load_si,store,move,fmove,smpy,dmpy,return,pload,pstore,pcload,pcload_si,rte,sfunc,call,fp,fdiv,gp_fpul,nil" |
bc45ade3 SC |
108 | (const_string "other")) |
109 | ||
07a45e5c | 110 | ; If a conditional branch destination is within -252..258 bytes away |
bc45ade3 | 111 | ; from the instruction it can be 2 bytes long. Something in the |
22e1ebf1 | 112 | ; range -4090..4100 bytes can be 6 bytes long. All other conditional |
1245df60 R |
113 | ; branches are initially assumed to be 16 bytes long. |
114 | ; In machine_dependent_reorg, we split all branches that are longer than | |
115 | ; 2 bytes. | |
bc45ade3 | 116 | |
22e1ebf1 | 117 | ; An unconditional jump in the range -4092..4098 can be 2 bytes long. |
1245df60 R |
118 | ; For wider ranges, we need a combination of a code and a data part. |
119 | ; If we can get a scratch register for a long range jump, the code | |
120 | ; part can be 4 bytes long; otherwise, it must be 8 bytes long. | |
121 | ; If the jump is in the range -32764..32770, the data part can be 2 bytes | |
122 | ; long; otherwise, it must be 6 bytes long. | |
bc45ade3 SC |
123 | |
124 | ; All other instructions are two bytes long by default. | |
125 | ||
07a45e5c | 126 | (define_attr "length" "" |
bc45ade3 | 127 | (cond [(eq_attr "type" "cbranch") |
1245df60 R |
128 | (cond [(ne (symbol_ref "short_cbranch_p (insn)") (const_int 0)) |
129 | (const_int 2) | |
130 | (ne (symbol_ref "med_branch_p (insn, 2)") (const_int 0)) | |
131 | (const_int 6) | |
132 | (ne (symbol_ref "braf_branch_p (insn, 2)") (const_int 0)) | |
133 | (const_int 10) | |
134 | (ne (pc) (pc)) | |
135 | (const_int 12) | |
136 | ] (const_int 16)) | |
bc45ade3 | 137 | (eq_attr "type" "jump") |
1245df60 R |
138 | (cond [(ne (symbol_ref "med_branch_p (insn, 0)") (const_int 0)) |
139 | (const_int 2) | |
140 | (and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))") | |
141 | (symbol_ref "INSN")) | |
142 | (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))") | |
143 | (symbol_ref "code_for_indirect_jump_scratch"))) | |
144 | (if_then_else (ne (symbol_ref "braf_branch_p (insn, 0)") | |
145 | (const_int 0)) | |
146 | (const_int 6) | |
147 | (const_int 10)) | |
148 | (ne (symbol_ref "braf_branch_p (insn, 0)") (const_int 0)) | |
149 | (const_int 10) | |
150 | (ne (pc) (pc)) | |
151 | (const_int 12) | |
152 | ] (const_int 14)) | |
bc45ade3 | 153 | ] (const_int 2))) |
b9654711 SC |
154 | |
155 | ;; (define_function_unit {name} {num-units} {n-users} {test} | |
156 | ;; {ready-delay} {issue-delay} [{conflict-list}]) | |
07a45e5c | 157 | |
c1aef54d ILT |
158 | ;; Load and store instructions save a cycle if they are aligned on a |
159 | ;; four byte boundary. Using a function unit for stores encourages | |
160 | ;; gcc to separate load and store instructions by one instruction, | |
161 | ;; which makes it more likely that the linker will be able to word | |
162 | ;; align them when relaxing. | |
1245df60 R |
163 | |
164 | ;; Loads have a latency of two. | |
deeef0ac | 165 | ;; However, call insns can have a delay slot, so that we want one more |
1245df60 R |
166 | ;; insn to be scheduled between the load of the function address and the call. |
167 | ;; This is equivalent to a latency of three. | |
168 | ;; We cannot use a conflict list for this, because we need to distinguish | |
169 | ;; between the actual call address and the function arguments. | |
170 | ;; ADJUST_COST can only properly handle reductions of the cost, so we | |
171 | ;; use a latency of three here. | |
956d6950 | 172 | ;; We only do this for SImode loads of general registers, to make the work |
1245df60 R |
173 | ;; for ADJUST_COST easier. |
174 | (define_function_unit "memory" 1 0 | |
175 | (eq_attr "type" "load_si,pcload_si") | |
176 | 3 2) | |
c1aef54d | 177 | (define_function_unit "memory" 1 0 |
1245df60 R |
178 | (eq_attr "type" "load,pcload,pload,store,pstore") |
179 | 2 2) | |
180 | ||
181 | (define_function_unit "int" 1 0 | |
182 | (eq_attr "type" "arith3,arith3b") 3 3) | |
183 | ||
184 | (define_function_unit "int" 1 0 | |
185 | (eq_attr "type" "dyn_shift") 2 2) | |
186 | ||
187 | (define_function_unit "int" 1 0 | |
188 | (eq_attr "type" "arith,arith3b,dyn_shift") 2 2) | |
c1aef54d ILT |
189 | |
190 | ;; ??? These are approximations. | |
51bd623f JW |
191 | (define_function_unit "mpy" 1 0 (eq_attr "type" "smpy") 2 2) |
192 | (define_function_unit "mpy" 1 0 (eq_attr "type" "dmpy") 3 3) | |
bc45ade3 | 193 | |
1245df60 | 194 | (define_function_unit "fp" 1 0 (eq_attr "type" "fp,fmove") 2 1) |
c1aef54d | 195 | (define_function_unit "fp" 1 0 (eq_attr "type" "fdiv") 13 12) |
45348d9e | 196 | |
1245df60 | 197 | |
51bd623f | 198 | ; Definitions for filling branch delay slots. |
bc45ade3 | 199 | |
51bd623f JW |
200 | (define_attr "needs_delay_slot" "yes,no" (const_string "no")) |
201 | ||
202 | (define_attr "hit_stack" "yes,no" (const_string "no")) | |
203 | ||
204 | (define_attr "interrupt_function" "no,yes" | |
205 | (const (symbol_ref "pragma_interrupt"))) | |
206 | ||
07a45e5c | 207 | (define_attr "in_delay_slot" "yes,no" |
51bd623f | 208 | (cond [(eq_attr "type" "cbranch") (const_string "no") |
1245df60 | 209 | (eq_attr "type" "pcload,pcload_si") (const_string "no") |
51bd623f JW |
210 | (eq_attr "needs_delay_slot" "yes") (const_string "no") |
211 | (eq_attr "length" "2") (const_string "yes") | |
212 | ] (const_string "no"))) | |
213 | ||
214 | (define_delay | |
0d7e008e | 215 | (eq_attr "needs_delay_slot" "yes") |
b9654711 SC |
216 | [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) |
217 | ||
51aea58d JW |
218 | ;; On the SH and SH2, the rte instruction reads the return pc from the stack, |
219 | ;; and thus we can't put a pop instruction in its delay slot. | |
6b005b88 JW |
220 | ;; ??? On the SH3, the rte instruction does not use the stack, so a pop |
221 | ;; instruction can go in the delay slot. | |
51aea58d | 222 | |
ffae286a JW |
223 | ;; Since a normal return (rts) implicitly uses the PR register, |
224 | ;; we can't allow PR register loads in an rts delay slot. | |
225 | ||
07a45e5c | 226 | (define_delay |
961c4780 | 227 | (eq_attr "type" "return") |
07a45e5c | 228 | [(and (eq_attr "in_delay_slot" "yes") |
ffae286a JW |
229 | (ior (and (eq_attr "interrupt_function" "no") |
230 | (eq_attr "type" "!pload")) | |
231 | (and (eq_attr "interrupt_function" "yes") | |
232 | (eq_attr "hit_stack" "no")))) (nil) (nil)]) | |
233 | ||
234 | ;; Since a call implicitly uses the PR register, we can't allow | |
235 | ;; a PR register store in a jsr delay slot. | |
236 | ||
237 | (define_delay | |
238 | (ior (eq_attr "type" "call") (eq_attr "type" "sfunc")) | |
239 | [(and (eq_attr "in_delay_slot" "yes") | |
240 | (eq_attr "type" "!pstore")) (nil) (nil)]) | |
241 | ||
242 | ;; Say that we have annulled true branches, since this gives smaller and | |
243 | ;; faster code when branches are predicted as not taken. | |
244 | ||
07a45e5c JW |
245 | (define_delay |
246 | (and (eq_attr "type" "cbranch") | |
1245df60 | 247 | (ne (symbol_ref "TARGET_SH2") (const_int 0))) |
2fad984b | 248 | [(eq_attr "in_delay_slot" "yes") (eq_attr "in_delay_slot" "yes") (nil)]) |
bc45ade3 SC |
249 | \f |
250 | ;; ------------------------------------------------------------------------- | |
251 | ;; SImode signed integer comparisons | |
252 | ;; ------------------------------------------------------------------------- | |
253 | ||
51bd623f JW |
254 | (define_insn "" |
255 | [(set (reg:SI 18) | |
256 | (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r") | |
257 | (match_operand:SI 1 "arith_operand" "L,r")) | |
258 | (const_int 0)))] | |
259 | "" | |
260 | "tst %1,%0") | |
0d7e008e | 261 | |
07a45e5c JW |
262 | ;; ??? Perhaps should only accept reg/constant if the register is reg 0. |
263 | ;; That would still allow reload to create cmpi instructions, but would | |
264 | ;; perhaps allow forcing the constant into a register when that is better. | |
ffae286a JW |
265 | ;; Probably should use r0 for mem/imm compares, but force constant into a |
266 | ;; register for pseudo/imm compares. | |
07a45e5c | 267 | |
0d7e008e | 268 | (define_insn "cmpeqsi_t" |
22e1ebf1 JW |
269 | [(set (reg:SI 18) (eq:SI (match_operand:SI 0 "arith_reg_operand" "r,z,r") |
270 | (match_operand:SI 1 "arith_operand" "N,rI,r")))] | |
0d7e008e SC |
271 | "" |
272 | "@ | |
51bd623f | 273 | tst %0,%0 |
0d7e008e SC |
274 | cmp/eq %1,%0 |
275 | cmp/eq %1,%0") | |
bc45ade3 SC |
276 | |
277 | (define_insn "cmpgtsi_t" | |
0d7e008e | 278 | [(set (reg:SI 18) (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r") |
22e1ebf1 | 279 | (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] |
bc45ade3 | 280 | "" |
0d7e008e | 281 | "@ |
22e1ebf1 JW |
282 | cmp/gt %1,%0 |
283 | cmp/pl %0") | |
bc45ade3 SC |
284 | |
285 | (define_insn "cmpgesi_t" | |
0d7e008e | 286 | [(set (reg:SI 18) (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r") |
22e1ebf1 | 287 | (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] |
bc45ade3 | 288 | "" |
0d7e008e | 289 | "@ |
22e1ebf1 JW |
290 | cmp/ge %1,%0 |
291 | cmp/pz %0") | |
bc45ade3 SC |
292 | \f |
293 | ;; ------------------------------------------------------------------------- | |
294 | ;; SImode unsigned integer comparisons | |
295 | ;; ------------------------------------------------------------------------- | |
296 | ||
297 | (define_insn "cmpgeusi_t" | |
22e1ebf1 JW |
298 | [(set (reg:SI 18) (geu:SI (match_operand:SI 0 "arith_reg_operand" "r") |
299 | (match_operand:SI 1 "arith_reg_operand" "r")))] | |
bc45ade3 | 300 | "" |
22e1ebf1 | 301 | "cmp/hs %1,%0") |
bc45ade3 SC |
302 | |
303 | (define_insn "cmpgtusi_t" | |
22e1ebf1 JW |
304 | [(set (reg:SI 18) (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r") |
305 | (match_operand:SI 1 "arith_reg_operand" "r")))] | |
bc45ade3 | 306 | "" |
22e1ebf1 | 307 | "cmp/hi %1,%0") |
bc45ade3 SC |
308 | |
309 | ;; We save the compare operands in the cmpxx patterns and use them when | |
310 | ;; we generate the branch. | |
311 | ||
312 | (define_expand "cmpsi" | |
0d7e008e SC |
313 | [(set (reg:SI 18) (compare (match_operand:SI 0 "arith_operand" "") |
314 | (match_operand:SI 1 "arith_operand" "")))] | |
bc45ade3 SC |
315 | "" |
316 | " | |
0d7e008e SC |
317 | { |
318 | sh_compare_op0 = operands[0]; | |
bc45ade3 SC |
319 | sh_compare_op1 = operands[1]; |
320 | DONE; | |
321 | }") | |
bc45ade3 SC |
322 | \f |
323 | ;; ------------------------------------------------------------------------- | |
1245df60 R |
324 | ;; DImode signed integer comparisons |
325 | ;; ------------------------------------------------------------------------- | |
326 | ||
327 | ;; ??? Could get better scheduling by splitting the initial test from the | |
328 | ;; rest of the insn after reload. However, the gain would hardly justify | |
329 | ;; the sh.md size increase necessary to do that. | |
330 | ||
331 | (define_insn "" | |
332 | [(set (reg:SI 18) | |
333 | (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r") | |
334 | (match_operand:DI 1 "arith_operand" "r")) | |
335 | (const_int 0)))] | |
336 | "" | |
337 | "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\", | |
338 | insn, operands);" | |
339 | [(set_attr "length" "6") | |
340 | (set_attr "type" "arith3b")]) | |
341 | ||
342 | (define_insn "cmpeqdi_t" | |
343 | [(set (reg:SI 18) (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r") | |
344 | (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))] | |
345 | "" | |
346 | "* | |
347 | return output_branchy_insn | |
348 | (EQ, | |
349 | (which_alternative | |
350 | ? \"cmp/eq\\t%S1,%S0\;bf\\t%l9\;cmp/eq\\t%R1,%R0\" | |
351 | : \"tst\\t%S0,%S0\;bf\\t%l9\;tst\\t%R0,%R0\"), | |
352 | insn, operands);" | |
353 | [(set_attr "length" "6") | |
354 | (set_attr "type" "arith3b")]) | |
355 | ||
356 | (define_insn "cmpgtdi_t" | |
357 | [(set (reg:SI 18) (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r") | |
358 | (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] | |
359 | "TARGET_SH2" | |
360 | "@ | |
361 | cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=: | |
362 | tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:" | |
363 | [(set_attr "length" "8") | |
364 | (set_attr "type" "arith3")]) | |
365 | ||
366 | (define_insn "cmpgedi_t" | |
367 | [(set (reg:SI 18) (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r") | |
368 | (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))] | |
369 | "TARGET_SH2" | |
370 | "@ | |
371 | cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=: | |
372 | cmp/pz\\t%S0" | |
373 | [(set_attr "length" "8,2") | |
374 | (set_attr "type" "arith3,arith")]) | |
375 | \f | |
376 | ;; ------------------------------------------------------------------------- | |
377 | ;; DImode unsigned integer comparisons | |
378 | ;; ------------------------------------------------------------------------- | |
379 | ||
380 | (define_insn "cmpgeudi_t" | |
381 | [(set (reg:SI 18) (geu:SI (match_operand:DI 0 "arith_reg_operand" "r") | |
382 | (match_operand:DI 1 "arith_reg_operand" "r")))] | |
383 | "TARGET_SH2" | |
384 | "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:" | |
385 | [(set_attr "length" "8") | |
386 | (set_attr "type" "arith3")]) | |
387 | ||
388 | (define_insn "cmpgtudi_t" | |
389 | [(set (reg:SI 18) (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r") | |
390 | (match_operand:DI 1 "arith_reg_operand" "r")))] | |
391 | "TARGET_SH2" | |
392 | "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:" | |
393 | [(set_attr "length" "8") | |
394 | (set_attr "type" "arith3")]) | |
395 | ||
396 | ;; We save the compare operands in the cmpxx patterns and use them when | |
397 | ;; we generate the branch. | |
398 | ||
399 | (define_expand "cmpdi" | |
400 | [(set (reg:SI 18) (compare (match_operand:DI 0 "arith_operand" "") | |
401 | (match_operand:DI 1 "arith_operand" "")))] | |
402 | "TARGET_SH2" | |
403 | " | |
404 | { | |
405 | sh_compare_op0 = operands[0]; | |
406 | sh_compare_op1 = operands[1]; | |
407 | DONE; | |
408 | }") | |
409 | \f | |
410 | ;; ------------------------------------------------------------------------- | |
bc45ade3 SC |
411 | ;; Addition instructions |
412 | ;; ------------------------------------------------------------------------- | |
413 | ||
ffae286a | 414 | ;; ??? This should be a define expand. |
0d7e008e | 415 | |
4fdd1f85 | 416 | (define_insn "adddi3" |
07a45e5c JW |
417 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") |
418 | (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0") | |
419 | (match_operand:DI 2 "arith_reg_operand" "r"))) | |
8e87e161 SC |
420 | (clobber (reg:SI 18))] |
421 | "" | |
1245df60 | 422 | "#" |
4fdd1f85 | 423 | [(set_attr "length" "6")]) |
961c4780 | 424 | |
1245df60 R |
425 | (define_split |
426 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") | |
427 | (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0") | |
428 | (match_operand:DI 2 "arith_reg_operand" "r"))) | |
429 | (clobber (reg:SI 18))] | |
430 | "reload_completed" | |
431 | [(const_int 0)] | |
432 | " | |
433 | { | |
434 | rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]); | |
435 | high0 = gen_rtx (REG, SImode, | |
436 | true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); | |
437 | high2 = gen_rtx (REG, SImode, | |
438 | true_regnum (operands[2]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); | |
439 | emit_insn (gen_clrt ()); | |
440 | emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2]))); | |
441 | emit_insn (gen_addc1 (high0, high0, high2)); | |
442 | DONE; | |
443 | }") | |
444 | ||
445 | (define_insn "addc" | |
446 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
447 | (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
448 | (match_operand:SI 2 "arith_reg_operand" "r")) | |
449 | (reg:SI 18))) | |
450 | (set (reg:SI 18) | |
451 | (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] | |
452 | "" | |
453 | "addc %2,%0" | |
454 | [(set_attr "type" "arith")]) | |
455 | ||
456 | (define_insn "addc1" | |
457 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
458 | (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
459 | (match_operand:SI 2 "arith_reg_operand" "r")) | |
460 | (reg:SI 18))) | |
461 | (clobber (reg:SI 18))] | |
462 | "" | |
463 | "addc %2,%0" | |
464 | [(set_attr "type" "arith")]) | |
465 | ||
51bd623f | 466 | (define_insn "addsi3" |
aa684c94 | 467 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
51bd623f | 468 | (plus:SI (match_operand:SI 1 "arith_operand" "%0") |
bc45ade3 SC |
469 | (match_operand:SI 2 "arith_operand" "rI")))] |
470 | "" | |
471 | "add %2,%0" | |
22e1ebf1 | 472 | [(set_attr "type" "arith")]) |
bc45ade3 SC |
473 | \f |
474 | ;; ------------------------------------------------------------------------- | |
475 | ;; Subtraction instructions | |
476 | ;; ------------------------------------------------------------------------- | |
477 | ||
ffae286a | 478 | ;; ??? This should be a define expand. |
8e87e161 | 479 | |
4fdd1f85 | 480 | (define_insn "subdi3" |
07a45e5c JW |
481 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") |
482 | (minus:DI (match_operand:DI 1 "arith_reg_operand" "0") | |
483 | (match_operand:DI 2 "arith_reg_operand" "r"))) | |
bc45ade3 SC |
484 | (clobber (reg:SI 18))] |
485 | "" | |
1245df60 | 486 | "#" |
4fdd1f85 | 487 | [(set_attr "length" "6")]) |
bc45ade3 | 488 | |
1245df60 R |
489 | (define_split |
490 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") | |
491 | (minus:DI (match_operand:DI 1 "arith_reg_operand" "0") | |
492 | (match_operand:DI 2 "arith_reg_operand" "r"))) | |
493 | (clobber (reg:SI 18))] | |
494 | "reload_completed" | |
495 | [(const_int 0)] | |
496 | " | |
497 | { | |
498 | rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]); | |
499 | high0 = gen_rtx (REG, SImode, | |
500 | true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); | |
501 | high2 = gen_rtx (REG, SImode, | |
502 | true_regnum (operands[2]) + (TARGET_LITTLE_ENDIAN ? 1 : 0)); | |
503 | emit_insn (gen_clrt ()); | |
504 | emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2]))); | |
505 | emit_insn (gen_subc1 (high0, high0, high2)); | |
506 | DONE; | |
507 | }") | |
508 | ||
509 | (define_insn "subc" | |
510 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
511 | (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
512 | (match_operand:SI 2 "arith_reg_operand" "r")) | |
513 | (reg:SI 18))) | |
514 | (set (reg:SI 18) | |
515 | (gtu:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))] | |
516 | "" | |
517 | "subc %2,%0" | |
518 | [(set_attr "type" "arith")]) | |
519 | ||
520 | (define_insn "subc1" | |
521 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
522 | (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
523 | (match_operand:SI 2 "arith_reg_operand" "r")) | |
524 | (reg:SI 18))) | |
525 | (clobber (reg:SI 18))] | |
526 | "" | |
527 | "subc %2,%0" | |
528 | [(set_attr "type" "arith")]) | |
529 | ||
caca3c8a | 530 | (define_insn "*subsi3_internal" |
0d7e008e SC |
531 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
532 | (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
ffae286a | 533 | (match_operand:SI 2 "arith_reg_operand" "r")))] |
bc45ade3 | 534 | "" |
0d7e008e | 535 | "sub %2,%0" |
bc45ade3 | 536 | [(set_attr "type" "arith")]) |
caca3c8a JW |
537 | |
538 | ;; Convert `constant - reg' to `neg rX; add rX, #const' since this | |
539 | ;; will sometimes save one instruction. Otherwise we might get | |
540 | ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs | |
541 | ;; are the same. | |
542 | ||
543 | (define_expand "subsi3" | |
544 | [(set (match_operand:SI 0 "arith_reg_operand" "") | |
545 | (minus:SI (match_operand:SI 1 "arith_operand" "") | |
546 | (match_operand:SI 2 "arith_reg_operand" "")))] | |
547 | "" | |
548 | " | |
549 | { | |
550 | if (GET_CODE (operands[1]) == CONST_INT) | |
551 | { | |
552 | emit_insn (gen_negsi2 (operands[0], operands[2])); | |
553 | emit_insn (gen_addsi3 (operands[0], operands[0], operands[1])); | |
554 | DONE; | |
555 | } | |
556 | }") | |
bc45ade3 SC |
557 | \f |
558 | ;; ------------------------------------------------------------------------- | |
0d7e008e | 559 | ;; Division instructions |
bc45ade3 SC |
560 | ;; ------------------------------------------------------------------------- |
561 | ||
ffae286a | 562 | ;; We take advantage of the library routines which don't clobber as many |
0d7e008e SC |
563 | ;; registers as a normal function call would. |
564 | ||
1245df60 | 565 | ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it |
956d6950 | 566 | ;; also has an effect on the register that holds the address of the sfunc. |
1245df60 R |
567 | ;; To make this work, we have an extra dummy insns that shows the use |
568 | ;; of this register for reorg. | |
569 | ||
570 | (define_insn "use_sfunc_addr" | |
571 | [(set (reg:SI 17) (unspec [(match_operand:SI 0 "register_operand" "r")] 5))] | |
572 | "" | |
573 | "" | |
574 | [(set_attr "length" "0")]) | |
575 | ||
ddd5a7c1 | 576 | ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than |
e96a50cc JW |
577 | ;; hard register 0. If we used hard register 0, then the next instruction |
578 | ;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg | |
579 | ;; gets allocated to a stack slot that needs its address reloaded, then | |
580 | ;; there is nothing to prevent reload from using r0 to reload the address. | |
581 | ;; This reload would clobber the value in r0 we are trying to store. | |
582 | ;; If we let reload allocate r0, then this problem can never happen. | |
0d7e008e SC |
583 | |
584 | (define_insn "" | |
1245df60 | 585 | [(set (match_operand:SI 0 "register_operand" "=z") |
0d7e008e SC |
586 | (udiv:SI (reg:SI 4) (reg:SI 5))) |
587 | (clobber (reg:SI 18)) | |
588 | (clobber (reg:SI 17)) | |
0d7e008e | 589 | (clobber (reg:SI 4)) |
1245df60 | 590 | (use (match_operand:SI 1 "arith_reg_operand" "r"))] |
0d7e008e | 591 | "" |
1245df60 | 592 | "jsr @%1%#" |
0d7e008e | 593 | [(set_attr "type" "sfunc") |
0d7e008e SC |
594 | (set_attr "needs_delay_slot" "yes")]) |
595 | ||
596 | (define_expand "udivsi3" | |
51aea58d JW |
597 | [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) |
598 | (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) | |
0d7e008e | 599 | (set (match_dup 3) (symbol_ref:SI "__udivsi3")) |
ffae286a JW |
600 | (parallel [(set (match_operand:SI 0 "register_operand" "") |
601 | (udiv:SI (reg:SI 4) | |
602 | (reg:SI 5))) | |
603 | (clobber (reg:SI 18)) | |
604 | (clobber (reg:SI 17)) | |
605 | (clobber (reg:SI 4)) | |
606 | (use (match_dup 3))])] | |
0d7e008e SC |
607 | "" |
608 | "operands[3] = gen_reg_rtx(SImode);") | |
609 | ||
0d7e008e | 610 | (define_insn "" |
1245df60 | 611 | [(set (match_operand:SI 0 "register_operand" "=z") |
0d7e008e SC |
612 | (div:SI (reg:SI 4) (reg:SI 5))) |
613 | (clobber (reg:SI 18)) | |
614 | (clobber (reg:SI 17)) | |
4fdd1f85 SC |
615 | (clobber (reg:SI 1)) |
616 | (clobber (reg:SI 2)) | |
0d7e008e | 617 | (clobber (reg:SI 3)) |
1245df60 | 618 | (use (match_operand:SI 1 "arith_reg_operand" "r"))] |
0d7e008e | 619 | "" |
1245df60 | 620 | "jsr @%1%#" |
0d7e008e | 621 | [(set_attr "type" "sfunc") |
0d7e008e SC |
622 | (set_attr "needs_delay_slot" "yes")]) |
623 | ||
624 | (define_expand "divsi3" | |
51aea58d JW |
625 | [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) |
626 | (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) | |
0d7e008e | 627 | (set (match_dup 3) (symbol_ref:SI "__sdivsi3")) |
ffae286a JW |
628 | (parallel [(set (match_operand:SI 0 "register_operand" "") |
629 | (div:SI (reg:SI 4) | |
0d7e008e | 630 | (reg:SI 5))) |
ffae286a JW |
631 | (clobber (reg:SI 18)) |
632 | (clobber (reg:SI 17)) | |
633 | (clobber (reg:SI 1)) | |
634 | (clobber (reg:SI 2)) | |
635 | (clobber (reg:SI 3)) | |
636 | (use (match_dup 3))])] | |
0d7e008e SC |
637 | "" |
638 | "operands[3] = gen_reg_rtx(SImode);") | |
0d7e008e SC |
639 | \f |
640 | ;; ------------------------------------------------------------------------- | |
641 | ;; Multiplication instructions | |
642 | ;; ------------------------------------------------------------------------- | |
643 | ||
bc45ade3 SC |
644 | (define_insn "" |
645 | [(set (reg:SI 21) | |
af55dae3 JW |
646 | (mult:SI (zero_extend:SI (match_operand:HI 0 "arith_reg_operand" "r")) |
647 | (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r"))))] | |
bc45ade3 | 648 | "" |
af55dae3 | 649 | "mulu %1,%0" |
b9654711 | 650 | [(set_attr "type" "smpy")]) |
bc45ade3 SC |
651 | |
652 | (define_insn "" | |
653 | [(set (reg:SI 21) | |
654 | (mult:SI (sign_extend:SI | |
af55dae3 | 655 | (match_operand:HI 0 "arith_reg_operand" "r")) |
bc45ade3 | 656 | (sign_extend:SI |
af55dae3 | 657 | (match_operand:HI 1 "arith_reg_operand" "r"))))] |
bc45ade3 | 658 | "" |
af55dae3 | 659 | "muls %1,%0" |
b9654711 | 660 | [(set_attr "type" "smpy")]) |
bc45ade3 SC |
661 | |
662 | (define_expand "mulhisi3" | |
663 | [(set (reg:SI 21) | |
664 | (mult:SI (sign_extend:SI | |
51aea58d | 665 | (match_operand:HI 1 "arith_reg_operand" "")) |
bc45ade3 | 666 | (sign_extend:SI |
51aea58d JW |
667 | (match_operand:HI 2 "arith_reg_operand" "")))) |
668 | (set (match_operand:SI 0 "arith_reg_operand" "") | |
bc45ade3 SC |
669 | (reg:SI 21))] |
670 | "" | |
671 | "") | |
672 | ||
673 | (define_expand "umulhisi3" | |
674 | [(set (reg:SI 21) | |
675 | (mult:SI (zero_extend:SI | |
51aea58d | 676 | (match_operand:HI 1 "arith_reg_operand" "")) |
bc45ade3 | 677 | (zero_extend:SI |
51aea58d JW |
678 | (match_operand:HI 2 "arith_reg_operand" "")))) |
679 | (set (match_operand:SI 0 "arith_reg_operand" "") | |
bc45ade3 SC |
680 | (reg:SI 21))] |
681 | "" | |
682 | "") | |
683 | ||
0d7e008e SC |
684 | ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate |
685 | ;; a call to a routine which clobbers known registers. | |
686 | ||
687 | (define_insn "" | |
e96a50cc | 688 | [(set (match_operand:SI 1 "register_operand" "=z") |
0d7e008e SC |
689 | (mult:SI (reg:SI 4) (reg:SI 5))) |
690 | (clobber (reg:SI 21)) | |
691 | (clobber (reg:SI 18)) | |
692 | (clobber (reg:SI 17)) | |
693 | (clobber (reg:SI 3)) | |
694 | (clobber (reg:SI 2)) | |
695 | (clobber (reg:SI 1)) | |
07a45e5c | 696 | (use (match_operand:SI 0 "arith_reg_operand" "r"))] |
0d7e008e SC |
697 | "" |
698 | "jsr @%0%#" | |
699 | [(set_attr "type" "sfunc") | |
0d7e008e SC |
700 | (set_attr "needs_delay_slot" "yes")]) |
701 | ||
702 | (define_expand "mulsi3_call" | |
51aea58d JW |
703 | [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) |
704 | (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) | |
0d7e008e | 705 | (set (match_dup 3) (symbol_ref:SI "__mulsi3")) |
51aea58d | 706 | (parallel[(set (match_operand:SI 0 "register_operand" "") |
0d7e008e SC |
707 | (mult:SI (reg:SI 4) |
708 | (reg:SI 5))) | |
709 | (clobber (reg:SI 21)) | |
710 | (clobber (reg:SI 18)) | |
711 | (clobber (reg:SI 17)) | |
712 | (clobber (reg:SI 3)) | |
713 | (clobber (reg:SI 2)) | |
714 | (clobber (reg:SI 1)) | |
e96a50cc | 715 | (use (match_dup 3))])] |
0d7e008e SC |
716 | "" |
717 | "operands[3] = gen_reg_rtx(SImode);") | |
07a45e5c | 718 | |
0d7e008e SC |
719 | (define_insn "mul_l" |
720 | [(set (reg:SI 21) | |
721 | (mult:SI (match_operand:SI 0 "arith_reg_operand" "r") | |
722 | (match_operand:SI 1 "arith_reg_operand" "r")))] | |
723 | "TARGET_SH2" | |
724 | "mul.l %1,%0" | |
51bd623f | 725 | [(set_attr "type" "dmpy")]) |
0d7e008e SC |
726 | |
727 | (define_expand "mulsi3" | |
728 | [(set (reg:SI 21) | |
51aea58d JW |
729 | (mult:SI (match_operand:SI 1 "arith_reg_operand" "") |
730 | (match_operand:SI 2 "arith_reg_operand" ""))) | |
731 | (set (match_operand:SI 0 "arith_reg_operand" "") | |
0d7e008e | 732 | (reg:SI 21))] |
51bd623f JW |
733 | "" |
734 | " | |
735 | { | |
736 | if (!TARGET_SH2) | |
737 | { | |
738 | FAIL; | |
739 | /* ??? Does this give worse or better code? */ | |
740 | emit_insn (gen_mulsi3_call (operands[0], operands[1], operands[2])); | |
741 | DONE; | |
742 | } | |
743 | }") | |
00f8ff66 | 744 | |
af55dae3 | 745 | (define_insn "mulsidi3_i" |
0d7e008e | 746 | [(set (reg:DI 20) |
af55dae3 JW |
747 | (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) |
748 | (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))] | |
06e1bace | 749 | "TARGET_SH2" |
af55dae3 | 750 | "dmuls.l %1,%0" |
0d7e008e SC |
751 | [(set_attr "type" "dmpy")]) |
752 | ||
753 | (define_expand "mulsidi3" | |
754 | [(set (reg:DI 20) | |
51aea58d JW |
755 | (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) |
756 | (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))) | |
757 | (set (match_operand:DI 0 "arith_reg_operand" "") | |
0d7e008e | 758 | (reg:DI 20))] |
06e1bace | 759 | "TARGET_SH2" |
af55dae3 JW |
760 | " |
761 | { | |
762 | /* We must swap the two words when copying them from MACH/MACL to the | |
763 | output register. */ | |
764 | if (TARGET_LITTLE_ENDIAN) | |
765 | { | |
766 | rtx low_dst = operand_subword (operands[0], 0, 1, DImode); | |
767 | rtx high_dst = operand_subword (operands[0], 1, 1, DImode); | |
0d7e008e | 768 | |
af55dae3 JW |
769 | emit_insn (gen_mulsidi3_i (operands[1], operands[2])); |
770 | ||
771 | emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); | |
772 | emit_move_insn (low_dst, gen_rtx (REG, SImode, 21)); | |
773 | emit_move_insn (high_dst, gen_rtx (REG, SImode, 20)); | |
774 | DONE; | |
775 | } | |
776 | }") | |
777 | ||
778 | (define_insn "umulsidi3_i" | |
0d7e008e | 779 | [(set (reg:DI 20) |
af55dae3 JW |
780 | (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) |
781 | (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))] | |
06e1bace | 782 | "TARGET_SH2" |
af55dae3 | 783 | "dmulu.l %1,%0" |
0d7e008e SC |
784 | [(set_attr "type" "dmpy")]) |
785 | ||
786 | (define_expand "umulsidi3" | |
787 | [(set (reg:DI 20) | |
51aea58d JW |
788 | (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) |
789 | (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))) | |
790 | (set (match_operand:DI 0 "arith_reg_operand" "") | |
0d7e008e | 791 | (reg:DI 20))] |
06e1bace | 792 | "TARGET_SH2" |
af55dae3 JW |
793 | " |
794 | { | |
795 | /* We must swap the two words when copying them from MACH/MACL to the | |
796 | output register. */ | |
797 | if (TARGET_LITTLE_ENDIAN) | |
798 | { | |
799 | rtx low_dst = operand_subword (operands[0], 0, 1, DImode); | |
800 | rtx high_dst = operand_subword (operands[0], 1, 1, DImode); | |
801 | ||
802 | emit_insn (gen_umulsidi3_i (operands[1], operands[2])); | |
803 | ||
804 | emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); | |
805 | emit_move_insn (low_dst, gen_rtx (REG, SImode, 21)); | |
806 | emit_move_insn (high_dst, gen_rtx (REG, SImode, 20)); | |
807 | DONE; | |
808 | } | |
809 | }") | |
06e1bace RK |
810 | |
811 | (define_insn "" | |
812 | [(set (reg:SI 20) | |
813 | (truncate:SI | |
af55dae3 JW |
814 | (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) |
815 | (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) | |
06e1bace RK |
816 | (const_int 32)))) |
817 | (clobber (reg:SI 21))] | |
818 | "TARGET_SH2" | |
af55dae3 | 819 | "dmuls.l %1,%0" |
06e1bace RK |
820 | [(set_attr "type" "dmpy")]) |
821 | ||
822 | (define_expand "smulsi3_highpart" | |
823 | [(parallel [(set (reg:SI 20) | |
824 | (truncate:SI | |
825 | (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) | |
826 | (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) | |
827 | (const_int 32)))) | |
828 | (clobber (reg:SI 21))]) | |
829 | (set (match_operand:SI 0 "arith_reg_operand" "") | |
830 | (reg:SI 20))] | |
831 | "TARGET_SH2" | |
832 | "") | |
833 | ||
834 | (define_insn "" | |
835 | [(set (reg:SI 20) | |
836 | (truncate:SI | |
af55dae3 JW |
837 | (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) |
838 | (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) | |
06e1bace RK |
839 | (const_int 32)))) |
840 | (clobber (reg:SI 21))] | |
841 | "TARGET_SH2" | |
af55dae3 | 842 | "dmulu.l %1,%0" |
06e1bace RK |
843 | [(set_attr "type" "dmpy")]) |
844 | ||
845 | (define_expand "umulsi3_highpart" | |
846 | [(parallel [(set (reg:SI 20) | |
847 | (truncate:SI | |
848 | (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) | |
849 | (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))) | |
850 | (const_int 32)))) | |
851 | (clobber (reg:SI 21))]) | |
852 | (set (match_operand:SI 0 "arith_reg_operand" "") | |
853 | (reg:SI 20))] | |
854 | "TARGET_SH2" | |
0d7e008e | 855 | "") |
bc45ade3 SC |
856 | \f |
857 | ;; ------------------------------------------------------------------------- | |
858 | ;; Logical operations | |
859 | ;; ------------------------------------------------------------------------- | |
860 | ||
0d7e008e | 861 | (define_insn "" |
aa684c94 SC |
862 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") |
863 | (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") | |
bc45ade3 SC |
864 | (match_operand:SI 2 "logical_operand" "r,L")))] |
865 | "" | |
866 | "and %2,%0" | |
867 | [(set_attr "type" "arith")]) | |
868 | ||
51bd623f JW |
869 | ;; If the constant is 255, then emit a extu.b instruction instead of an |
870 | ;; and, since that will give better code. | |
871 | ||
0d7e008e SC |
872 | (define_expand "andsi3" |
873 | [(set (match_operand:SI 0 "arith_reg_operand" "") | |
874 | (and:SI (match_operand:SI 1 "arith_reg_operand" "") | |
875 | (match_operand:SI 2 "logical_operand" "")))] | |
876 | "" | |
51bd623f JW |
877 | " |
878 | { | |
879 | if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255) | |
880 | { | |
881 | emit_insn (gen_zero_extendqisi2 (operands[0], | |
882 | gen_lowpart (QImode, operands[1]))); | |
883 | DONE; | |
884 | } | |
885 | }") | |
0d7e008e | 886 | |
bc45ade3 | 887 | (define_insn "iorsi3" |
aa684c94 SC |
888 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") |
889 | (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") | |
bc45ade3 SC |
890 | (match_operand:SI 2 "logical_operand" "r,L")))] |
891 | "" | |
1245df60 R |
892 | "or %2,%0" |
893 | [(set_attr "type" "arith")]) | |
bc45ade3 SC |
894 | |
895 | (define_insn "xorsi3" | |
0d7e008e | 896 | [(set (match_operand:SI 0 "arith_reg_operand" "=z,r") |
aa684c94 | 897 | (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") |
0d7e008e | 898 | (match_operand:SI 2 "logical_operand" "L,r")))] |
bc45ade3 SC |
899 | "" |
900 | "xor %2,%0" | |
901 | [(set_attr "type" "arith")]) | |
bc45ade3 SC |
902 | \f |
903 | ;; ------------------------------------------------------------------------- | |
904 | ;; Shifts and rotates | |
905 | ;; ------------------------------------------------------------------------- | |
906 | ||
51bd623f | 907 | (define_insn "rotlsi3_1" |
b9654711 SC |
908 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
909 | (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
910 | (const_int 1))) | |
51aea58d JW |
911 | (set (reg:SI 18) |
912 | (lshiftrt:SI (match_dup 1) (const_int 31)))] | |
b9654711 | 913 | "" |
1245df60 R |
914 | "rotl %0" |
915 | [(set_attr "type" "arith")]) | |
b9654711 | 916 | |
51bd623f | 917 | (define_insn "rotlsi3_31" |
b9654711 | 918 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
51bd623f JW |
919 | (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") |
920 | (const_int 31))) | |
b9654711 SC |
921 | (clobber (reg:SI 18))] |
922 | "" | |
1245df60 R |
923 | "rotr %0" |
924 | [(set_attr "type" "arith")]) | |
b9654711 | 925 | |
1245df60 | 926 | (define_insn "rotlsi3_16" |
51bd623f JW |
927 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
928 | (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r") | |
929 | (const_int 16)))] | |
b9654711 | 930 | "" |
1245df60 R |
931 | "swap.w %1,%0" |
932 | [(set_attr "type" "arith")]) | |
b9654711 | 933 | |
51bd623f JW |
934 | (define_expand "rotlsi3" |
935 | [(set (match_operand:SI 0 "arith_reg_operand" "") | |
936 | (rotate:SI (match_operand:SI 1 "arith_reg_operand" "") | |
937 | (match_operand:SI 2 "immediate_operand" "")))] | |
938 | "" | |
939 | " | |
940 | { | |
1245df60 R |
941 | static char rot_tab[] = { |
942 | 000, 000, 000, 000, 000, 000, 010, 001, | |
943 | 001, 001, 011, 013, 003, 003, 003, 003, | |
944 | 003, 003, 003, 003, 003, 013, 012, 002, | |
945 | 002, 002, 010, 000, 000, 000, 000, 000, | |
946 | }; | |
947 | ||
948 | int count, choice; | |
949 | ||
51bd623f JW |
950 | if (GET_CODE (operands[2]) != CONST_INT) |
951 | FAIL; | |
1245df60 R |
952 | count = INTVAL (operands[2]); |
953 | choice = rot_tab[count]; | |
954 | if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1) | |
955 | FAIL; | |
956 | choice &= 7; | |
957 | switch (choice) | |
51bd623f | 958 | { |
1245df60 R |
959 | case 0: |
960 | emit_move_insn (operands[0], operands[1]); | |
961 | count -= (count & 16) * 2; | |
962 | break; | |
963 | case 3: | |
964 | emit_insn (gen_rotlsi3_16 (operands[0], operands[1])); | |
965 | count -= 16; | |
966 | break; | |
967 | case 1: | |
968 | case 2: | |
969 | { | |
970 | rtx parts[2]; | |
971 | parts[0] = gen_reg_rtx (SImode); | |
972 | parts[1] = gen_reg_rtx (SImode); | |
973 | emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1])); | |
974 | parts[choice-1] = operands[1]; | |
975 | emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8))); | |
976 | emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8))); | |
977 | emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1])); | |
978 | count = (count & ~16) - 8; | |
979 | } | |
51bd623f | 980 | } |
1245df60 R |
981 | |
982 | for (; count > 0; count--) | |
983 | emit_insn (gen_rotlsi3_1 (operands[0], operands[0])); | |
984 | for (; count < 0; count++) | |
985 | emit_insn (gen_rotlsi3_31 (operands[0], operands[0])); | |
986 | ||
987 | DONE; | |
51bd623f JW |
988 | }") |
989 | ||
1245df60 | 990 | (define_insn "*rotlhi3_8" |
51bd623f JW |
991 | [(set (match_operand:HI 0 "arith_reg_operand" "=r") |
992 | (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r") | |
993 | (const_int 8)))] | |
994 | "" | |
1245df60 R |
995 | "swap.b %1,%0" |
996 | [(set_attr "type" "arith")]) | |
51bd623f JW |
997 | |
998 | (define_expand "rotlhi3" | |
999 | [(set (match_operand:HI 0 "arith_reg_operand" "") | |
1000 | (rotate:HI (match_operand:HI 1 "arith_reg_operand" "") | |
1001 | (match_operand:HI 2 "immediate_operand" "")))] | |
1002 | "" | |
1003 | " | |
1004 | { | |
1005 | if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 8) | |
1006 | FAIL; | |
1007 | }") | |
0d7e008e SC |
1008 | |
1009 | ;; | |
1010 | ;; shift left | |
1011 | ||
6b005b88 JW |
1012 | (define_insn "ashlsi3_d" |
1013 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1014 | (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
1015 | (match_operand:SI 2 "arith_reg_operand" "r")))] | |
1016 | "TARGET_SH3" | |
1245df60 R |
1017 | "shld %2,%0" |
1018 | [(set_attr "type" "dyn_shift")]) | |
51aea58d | 1019 | |
bc45ade3 | 1020 | (define_insn "ashlsi3_k" |
aa684c94 SC |
1021 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") |
1022 | (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0") | |
ffae286a | 1023 | (match_operand:SI 2 "const_int_operand" "M,K")))] |
0d7e008e SC |
1024 | "CONST_OK_FOR_K (INTVAL (operands[2]))" |
1025 | "@ | |
51bd623f | 1026 | add %0,%0 |
1245df60 R |
1027 | shll%O2 %0" |
1028 | [(set_attr "type" "arith")]) | |
0d7e008e | 1029 | |
98e819b9 JW |
1030 | (define_insn "ashlhi3_k" |
1031 | [(set (match_operand:HI 0 "arith_reg_operand" "=r,r") | |
1032 | (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0") | |
1033 | (match_operand:HI 2 "const_int_operand" "M,K")))] | |
1034 | "CONST_OK_FOR_K (INTVAL (operands[2]))" | |
1035 | "@ | |
1036 | add %0,%0 | |
1245df60 R |
1037 | shll%O2 %0" |
1038 | [(set_attr "type" "arith")]) | |
98e819b9 | 1039 | |
0d7e008e SC |
1040 | (define_insn "ashlsi3_n" |
1041 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1042 | (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
ffae286a | 1043 | (match_operand:SI 2 "const_int_operand" "n"))) |
0d7e008e | 1044 | (clobber (reg:SI 18))] |
1245df60 | 1045 | "! sh_dynamicalize_shift_p (operands[2])" |
07a45e5c JW |
1046 | "#" |
1047 | [(set (attr "length") | |
1048 | (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1)) | |
1049 | (const_string "2") | |
1050 | (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2)) | |
1051 | (const_string "4") | |
1052 | (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3)) | |
1053 | (const_string "6")] | |
1054 | (const_string "8"))) | |
bc45ade3 SC |
1055 | (set_attr "type" "arith")]) |
1056 | ||
07a45e5c JW |
1057 | (define_split |
1058 | [(set (match_operand:SI 0 "arith_reg_operand" "") | |
1059 | (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") | |
ffae286a | 1060 | (match_operand:SI 2 "const_int_operand" "n"))) |
07a45e5c JW |
1061 | (clobber (reg:SI 18))] |
1062 | "" | |
1063 | [(use (reg:SI 0))] | |
1064 | " | |
1065 | { | |
1066 | gen_shifty_op (ASHIFT, operands); | |
1067 | DONE; | |
1068 | }") | |
1069 | ||
bc45ade3 | 1070 | (define_expand "ashlsi3" |
ffae286a JW |
1071 | [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") |
1072 | (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") | |
1073 | (match_operand:SI 2 "nonmemory_operand" ""))) | |
1074 | (clobber (reg:SI 18))])] | |
bc45ade3 | 1075 | "" |
d2f09a2f JW |
1076 | " |
1077 | { | |
1245df60 R |
1078 | if (GET_CODE (operands[2]) == CONST_INT |
1079 | && sh_dynamicalize_shift_p (operands[2])) | |
1080 | operands[2] = force_reg (SImode, operands[2]); | |
6b005b88 JW |
1081 | if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2]))) |
1082 | { | |
1083 | emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2])); | |
1084 | DONE; | |
1085 | } | |
d2f09a2f JW |
1086 | if (! immediate_operand (operands[2], GET_MODE (operands[2]))) |
1087 | FAIL; | |
1088 | }") | |
0d7e008e | 1089 | |
98e819b9 JW |
1090 | (define_insn "ashlhi3" |
1091 | [(set (match_operand:HI 0 "arith_reg_operand" "=r") | |
1092 | (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0") | |
1093 | (match_operand:HI 2 "const_int_operand" "n"))) | |
1094 | (clobber (reg:SI 18))] | |
1095 | "" | |
1096 | "#" | |
1097 | [(set (attr "length") | |
1098 | (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1)) | |
1099 | (const_string "2") | |
1100 | (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2)) | |
1101 | (const_string "4")] | |
1102 | (const_string "6"))) | |
1103 | (set_attr "type" "arith")]) | |
1104 | ||
1105 | (define_split | |
1106 | [(set (match_operand:HI 0 "arith_reg_operand" "") | |
1107 | (ashift:HI (match_operand:HI 1 "arith_reg_operand" "") | |
1108 | (match_operand:HI 2 "const_int_operand" "n"))) | |
1109 | (clobber (reg:SI 18))] | |
1110 | "" | |
1111 | [(use (reg:SI 0))] | |
1112 | " | |
1113 | { | |
1114 | gen_shifty_hi_op (ASHIFT, operands); | |
1115 | DONE; | |
1116 | }") | |
1117 | ||
0d7e008e SC |
1118 | ; |
1119 | ; arithmetic shift right | |
1120 | ; | |
bc45ade3 SC |
1121 | |
1122 | (define_insn "ashrsi3_k" | |
aa684c94 SC |
1123 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
1124 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
ffae286a | 1125 | (match_operand:SI 2 "const_int_operand" "M"))) |
b9654711 | 1126 | (clobber (reg:SI 18))] |
ffae286a | 1127 | "INTVAL (operands[2]) == 1" |
bc45ade3 SC |
1128 | "shar %0" |
1129 | [(set_attr "type" "arith")]) | |
1130 | ||
98e819b9 JW |
1131 | (define_insn "ashrhi3_k" |
1132 | [(set (match_operand:HI 0 "arith_reg_operand" "=r") | |
1133 | (ashiftrt:HI (match_operand:HI 1 "arith_reg_operand" "0") | |
1134 | (match_operand:HI 2 "const_int_operand" "M"))) | |
1135 | (clobber (reg:SI 18))] | |
1136 | "INTVAL (operands[2]) == 1" | |
1137 | "shar %0" | |
1138 | [(set_attr "type" "arith")]) | |
1139 | ||
ffae286a JW |
1140 | ;; ??? This should be a define expand. |
1141 | ||
00f8ff66 | 1142 | (define_insn "ashrsi2_16" |
07a45e5c JW |
1143 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
1144 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") | |
3e8bd1ce | 1145 | (const_int 16)))] |
00f8ff66 | 1146 | "" |
1245df60 | 1147 | "#" |
00f8ff66 SC |
1148 | [(set_attr "length" "4")]) |
1149 | ||
1245df60 R |
1150 | (define_split |
1151 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1152 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") | |
1153 | (const_int 16)))] | |
1154 | "" | |
1155 | [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16))) | |
1156 | (set (match_dup 0) (sign_extend:SI (match_dup 2)))] | |
1157 | "operands[2] = gen_lowpart (HImode, operands[0]);") | |
1158 | ||
ffae286a JW |
1159 | ;; ??? This should be a define expand. |
1160 | ||
00f8ff66 | 1161 | (define_insn "ashrsi2_31" |
6b005b88 | 1162 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
1245df60 R |
1163 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") |
1164 | (const_int 31))) | |
3e8bd1ce | 1165 | (clobber (reg:SI 18))] |
00f8ff66 | 1166 | "" |
1245df60 | 1167 | "#" |
6b005b88 | 1168 | [(set_attr "length" "4")]) |
3e8bd1ce | 1169 | |
1245df60 R |
1170 | (define_split |
1171 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1172 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
1173 | (const_int 31))) | |
1174 | (clobber (reg:SI 18))] | |
1175 | "" | |
1176 | [(const_int 0)] | |
1177 | " | |
1178 | { | |
1179 | emit_insn (gen_ashlsi_c (operands[0], operands[1], operands[1])); | |
1180 | emit_insn (gen_subc1 (operands[0], operands[0], operands[0])); | |
1181 | DONE; | |
1182 | }") | |
1183 | ||
1184 | (define_insn "ashlsi_c" | |
1185 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1186 | (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) | |
1187 | (set (reg:SI 18) (lt:SI (match_operand:SI 2 "arith_reg_operand" "0") | |
1188 | (const_int 0)))] | |
1189 | "" | |
1190 | "shll %0" | |
1191 | [(set_attr "type" "arith")]) | |
1192 | ||
6b005b88 JW |
1193 | (define_insn "ashrsi3_d" |
1194 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1195 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
1196 | (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] | |
1197 | "TARGET_SH3" | |
1245df60 R |
1198 | "shad %2,%0" |
1199 | [(set_attr "type" "dyn_shift")]) | |
51aea58d | 1200 | |
0d7e008e SC |
1201 | (define_insn "ashrsi3_n" |
1202 | [(set (reg:SI 4) | |
1203 | (ashiftrt:SI (reg:SI 4) | |
ffae286a | 1204 | (match_operand:SI 0 "const_int_operand" "i"))) |
0d7e008e SC |
1205 | (clobber (reg:SI 18)) |
1206 | (clobber (reg:SI 17)) | |
1207 | (use (match_operand:SI 1 "arith_reg_operand" "r"))] | |
1208 | "" | |
1209 | "jsr @%1%#" | |
1210 | [(set_attr "type" "sfunc") | |
0d7e008e SC |
1211 | (set_attr "needs_delay_slot" "yes")]) |
1212 | ||
bc45ade3 | 1213 | (define_expand "ashrsi3" |
ffae286a JW |
1214 | [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") |
1215 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") | |
1216 | (match_operand:SI 2 "nonmemory_operand" ""))) | |
1217 | (clobber (reg:SI 18))])] | |
bc45ade3 | 1218 | "" |
51aea58d | 1219 | "if (expand_ashiftrt (operands)) DONE; else FAIL;") |
0d7e008e | 1220 | |
07a45e5c | 1221 | ;; logical shift right |
bc45ade3 | 1222 | |
6b005b88 JW |
1223 | (define_insn "lshrsi3_d" |
1224 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1225 | (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
1226 | (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] | |
1227 | "TARGET_SH3" | |
1245df60 R |
1228 | "shld %2,%0" |
1229 | [(set_attr "type" "dyn_shift")]) | |
00f8ff66 | 1230 | |
ffae286a | 1231 | ;; Only the single bit shift clobbers the T bit. |
07a45e5c JW |
1232 | |
1233 | (define_insn "lshrsi3_m" | |
1234 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1235 | (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
ffae286a | 1236 | (match_operand:SI 2 "const_int_operand" "M"))) |
b9654711 | 1237 | (clobber (reg:SI 18))] |
07a45e5c | 1238 | "CONST_OK_FOR_M (INTVAL (operands[2]))" |
1245df60 R |
1239 | "shlr %0" |
1240 | [(set_attr "type" "arith")]) | |
0d7e008e | 1241 | |
07a45e5c JW |
1242 | (define_insn "lshrsi3_k" |
1243 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1244 | (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
ffae286a | 1245 | (match_operand:SI 2 "const_int_operand" "K")))] |
07a45e5c JW |
1246 | "CONST_OK_FOR_K (INTVAL (operands[2])) |
1247 | && ! CONST_OK_FOR_M (INTVAL (operands[2]))" | |
1245df60 R |
1248 | "shlr%O2 %0" |
1249 | [(set_attr "type" "arith")]) | |
0d7e008e | 1250 | |
98e819b9 JW |
1251 | (define_insn "lshrhi3_m" |
1252 | [(set (match_operand:HI 0 "arith_reg_operand" "=r") | |
1253 | (lshiftrt:HI (match_operand:HI 1 "arith_reg_operand" "0") | |
1254 | (match_operand:HI 2 "const_int_operand" "M"))) | |
1255 | (clobber (reg:SI 18))] | |
1256 | "CONST_OK_FOR_M (INTVAL (operands[2]))" | |
1245df60 R |
1257 | "shlr %0" |
1258 | [(set_attr "type" "arith")]) | |
98e819b9 JW |
1259 | |
1260 | (define_insn "lshrhi3_k" | |
1261 | [(set (match_operand:HI 0 "arith_reg_operand" "=r") | |
1262 | (lshiftrt:HI (match_operand:HI 1 "arith_reg_operand" "0") | |
1263 | (match_operand:HI 2 "const_int_operand" "K")))] | |
1264 | "CONST_OK_FOR_K (INTVAL (operands[2])) | |
1265 | && ! CONST_OK_FOR_M (INTVAL (operands[2]))" | |
1245df60 R |
1266 | "shlr%O2 %0" |
1267 | [(set_attr "type" "arith")]) | |
98e819b9 | 1268 | |
0d7e008e SC |
1269 | (define_insn "lshrsi3_n" |
1270 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1271 | (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
ffae286a | 1272 | (match_operand:SI 2 "const_int_operand" "n"))) |
0d7e008e | 1273 | (clobber (reg:SI 18))] |
1245df60 | 1274 | "! sh_dynamicalize_shift_p (operands[2])" |
07a45e5c JW |
1275 | "#" |
1276 | [(set (attr "length") | |
1277 | (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1)) | |
1278 | (const_string "2") | |
1279 | (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2)) | |
1280 | (const_string "4") | |
1281 | (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 3)) | |
1282 | (const_string "6")] | |
1283 | (const_string "8"))) | |
bc45ade3 SC |
1284 | (set_attr "type" "arith")]) |
1285 | ||
07a45e5c JW |
1286 | (define_split |
1287 | [(set (match_operand:SI 0 "arith_reg_operand" "") | |
1288 | (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") | |
ffae286a | 1289 | (match_operand:SI 2 "const_int_operand" "n"))) |
07a45e5c JW |
1290 | (clobber (reg:SI 18))] |
1291 | "" | |
1292 | [(use (reg:SI 0))] | |
1293 | " | |
1294 | { | |
1295 | gen_shifty_op (LSHIFTRT, operands); | |
1296 | DONE; | |
1297 | }") | |
1298 | ||
bc45ade3 | 1299 | (define_expand "lshrsi3" |
ffae286a JW |
1300 | [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") |
1301 | (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") | |
1302 | (match_operand:SI 2 "nonmemory_operand" ""))) | |
1303 | (clobber (reg:SI 18))])] | |
bc45ade3 | 1304 | "" |
d2f09a2f JW |
1305 | " |
1306 | { | |
1245df60 R |
1307 | if (GET_CODE (operands[2]) == CONST_INT |
1308 | && sh_dynamicalize_shift_p (operands[2])) | |
1309 | operands[2] = force_reg (SImode, operands[2]); | |
6b005b88 JW |
1310 | if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2]))) |
1311 | { | |
1312 | rtx count = copy_to_mode_reg (SImode, operands[2]); | |
1313 | emit_insn (gen_negsi2 (count, count)); | |
7b7499bf | 1314 | emit_insn (gen_lshrsi3_d (operands[0], operands[1], count)); |
6b005b88 JW |
1315 | DONE; |
1316 | } | |
d2f09a2f JW |
1317 | if (! immediate_operand (operands[2], GET_MODE (operands[2]))) |
1318 | FAIL; | |
1319 | }") | |
bc45ade3 | 1320 | |
98e819b9 JW |
1321 | (define_insn "lshrhi3" |
1322 | [(set (match_operand:HI 0 "arith_reg_operand" "=r") | |
1323 | (lshiftrt:HI (match_operand:HI 1 "arith_reg_operand" "0") | |
1324 | (match_operand:HI 2 "const_int_operand" "n"))) | |
1325 | (clobber (reg:SI 18))] | |
1326 | "" | |
1327 | "#" | |
1328 | ;; ??? length attribute is sometimes six instead of four. | |
1329 | [(set (attr "length") | |
1330 | (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1)) | |
1331 | (const_string "2") | |
1332 | (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2)) | |
1333 | (const_string "4")] | |
1334 | (const_string "6"))) | |
1335 | (set_attr "type" "arith")]) | |
1336 | ||
1337 | (define_split | |
1338 | [(set (match_operand:HI 0 "arith_reg_operand" "") | |
1339 | (lshiftrt:HI (match_operand:HI 1 "arith_reg_operand" "") | |
1340 | (match_operand:HI 2 "const_int_operand" "n"))) | |
1341 | (clobber (reg:SI 18))] | |
1342 | "" | |
1343 | [(use (reg:SI 0))] | |
1344 | " | |
1345 | { | |
1346 | gen_shifty_hi_op (LSHIFTRT, operands); | |
1347 | DONE; | |
1348 | }") | |
1349 | ||
ffae286a JW |
1350 | ;; ??? This should be a define expand. |
1351 | ||
bc45ade3 | 1352 | (define_insn "ashldi3_k" |
aa684c94 SC |
1353 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") |
1354 | (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") | |
8e87e161 | 1355 | (const_int 1))) |
bc45ade3 SC |
1356 | (clobber (reg:SI 18))] |
1357 | "" | |
00f8ff66 | 1358 | "shll %R0\;rotcl %S0" |
1245df60 R |
1359 | [(set_attr "length" "4") |
1360 | (set_attr "type" "arith")]) | |
bc45ade3 SC |
1361 | |
1362 | (define_expand "ashldi3" | |
ffae286a JW |
1363 | [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") |
1364 | (ashift:DI (match_operand:DI 1 "arith_reg_operand" "") | |
1365 | (match_operand:DI 2 "immediate_operand" ""))) | |
1366 | (clobber (reg:SI 18))])] | |
bc45ade3 | 1367 | "" |
07a45e5c | 1368 | "{ if (GET_CODE (operands[2]) != CONST_INT |
ffae286a JW |
1369 | || INTVAL (operands[2]) != 1) FAIL;} ") |
1370 | ||
1371 | ;; ??? This should be a define expand. | |
bc45ade3 SC |
1372 | |
1373 | (define_insn "lshrdi3_k" | |
aa684c94 | 1374 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") |
b9654711 | 1375 | (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") |
8e87e161 | 1376 | (const_int 1))) |
b9654711 | 1377 | (clobber (reg:SI 18))] |
bc45ade3 | 1378 | "" |
00f8ff66 | 1379 | "shlr %S0\;rotcr %R0" |
1245df60 R |
1380 | [(set_attr "length" "4") |
1381 | (set_attr "type" "arith")]) | |
bc45ade3 SC |
1382 | |
1383 | (define_expand "lshrdi3" | |
ffae286a JW |
1384 | [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") |
1385 | (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") | |
bc45ade3 SC |
1386 | (match_operand:DI 2 "immediate_operand" ""))) |
1387 | (clobber (reg:SI 18))])] | |
1388 | "" | |
07a45e5c | 1389 | "{ if (GET_CODE (operands[2]) != CONST_INT |
ffae286a JW |
1390 | || INTVAL (operands[2]) != 1) FAIL;} ") |
1391 | ||
1392 | ;; ??? This should be a define expand. | |
bc45ade3 SC |
1393 | |
1394 | (define_insn "ashrdi3_k" | |
aa684c94 SC |
1395 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") |
1396 | (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") | |
8e87e161 | 1397 | (const_int 1))) |
bc45ade3 SC |
1398 | (clobber (reg:SI 18))] |
1399 | "" | |
00f8ff66 | 1400 | "shar %S0\;rotcr %R0" |
1245df60 R |
1401 | [(set_attr "length" "4") |
1402 | (set_attr "type" "arith")]) | |
bc45ade3 SC |
1403 | |
1404 | (define_expand "ashrdi3" | |
ffae286a JW |
1405 | [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") |
1406 | (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") | |
1407 | (match_operand:DI 2 "immediate_operand" ""))) | |
1408 | (clobber (reg:SI 18))])] | |
bc45ade3 | 1409 | "" |
07a45e5c | 1410 | "{ if (GET_CODE (operands[2]) != CONST_INT |
ffae286a | 1411 | || INTVAL (operands[2]) != 1) FAIL; } ") |
98e819b9 JW |
1412 | |
1413 | ;; combined left/right shift | |
1414 | ||
1415 | (define_split | |
1416 | [(set (match_operand:SI 0 "register_operand" "") | |
1417 | (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") | |
1418 | (match_operand:SI 2 "const_int_operand" "n")) | |
1419 | (match_operand:SI 3 "const_int_operand" "n")))] | |
1420 | "(unsigned)INTVAL (operands[2]) < 32" | |
1421 | [(use (reg:SI 0))] | |
1422 | "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL; | |
1423 | DONE;") | |
1424 | ||
1425 | (define_split | |
1426 | [(set (match_operand:SI 0 "register_operand" "") | |
1427 | (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "") | |
1428 | (match_operand:SI 2 "const_int_operand" "n")) | |
1429 | (match_operand:SI 3 "const_int_operand" "n"))) | |
1430 | (clobber (reg:SI 18))] | |
1431 | "(unsigned)INTVAL (operands[2]) < 32" | |
1432 | [(use (reg:SI 0))] | |
1433 | "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL; | |
1434 | DONE;") | |
1435 | ||
1436 | (define_insn "" | |
1437 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1438 | (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") | |
1439 | (match_operand:SI 2 "const_int_operand" "n")) | |
1440 | (match_operand:SI 3 "const_int_operand" "n"))) | |
1441 | (clobber (reg:SI 18))] | |
1442 | "shl_and_kind (operands[2], operands[3], 0) == 1" | |
1443 | "#" | |
1444 | [(set (attr "length") | |
1445 | (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) | |
1446 | (const_string "4") | |
1447 | (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) | |
1448 | (const_string "6") | |
1449 | (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) | |
1450 | (const_string "8") | |
1451 | (eq (symbol_ref "shl_and_length (insn)") (const_int 5)) | |
1452 | (const_string "10") | |
1453 | (eq (symbol_ref "shl_and_length (insn)") (const_int 6)) | |
1454 | (const_string "12") | |
1455 | (eq (symbol_ref "shl_and_length (insn)") (const_int 7)) | |
1456 | (const_string "14") | |
1457 | (eq (symbol_ref "shl_and_length (insn)") (const_int 8)) | |
1458 | (const_string "16")] | |
1459 | (const_string "18"))) | |
1460 | (set_attr "type" "arith")]) | |
1461 | ||
1462 | (define_insn "" | |
1463 | [(set (match_operand:SI 0 "register_operand" "=z") | |
1464 | (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") | |
1465 | (match_operand:SI 2 "const_int_operand" "n")) | |
1466 | (match_operand:SI 3 "const_int_operand" "n"))) | |
1467 | (clobber (reg:SI 18))] | |
1468 | "shl_and_kind (operands[2], operands[3], 0) == 2" | |
1469 | "#" | |
1470 | [(set (attr "length") | |
1471 | (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2)) | |
1472 | (const_string "4") | |
1473 | (eq (symbol_ref "shl_and_length (insn)") (const_int 3)) | |
1474 | (const_string "6") | |
1475 | (eq (symbol_ref "shl_and_length (insn)") (const_int 4)) | |
1476 | (const_string "8")] | |
1477 | (const_string "10"))) | |
1478 | (set_attr "type" "arith")]) | |
1479 | ||
1480 | ;; shift left / and combination with a scratch register: The combine pass | |
1481 | ;; does not accept the individual instructions, even though they are | |
1482 | ;; cheap. But it needs a precise description so that it is usable after | |
1483 | ;; reload. | |
1484 | (define_insn "and_shl_scratch" | |
1485 | [(set (match_operand:SI 0 "register_operand" "=r,&r") | |
1486 | (lshiftrt:SI (ashift:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0") | |
1487 | (match_operand:SI 2 "const_int_operand" "N,n")) | |
1488 | (match_operand:SI 3 "" "0,r")) | |
1489 | (match_operand:SI 4 "const_int_operand" "n,n")) | |
1490 | (match_operand:SI 5 "const_int_operand" "n,n"))) | |
1491 | (clobber (reg:SI 18))] | |
1492 | "" | |
1493 | "#" | |
1494 | [(set (attr "length") | |
1495 | (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2)) | |
1496 | (const_string "4") | |
1497 | (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3)) | |
1498 | (const_string "6") | |
1499 | (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4)) | |
9788ff4d | 1500 | (const_string "8") |
98e819b9 JW |
1501 | (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5)) |
1502 | (const_string "10")] | |
1503 | (const_string "12"))) | |
1504 | (set_attr "type" "arith")]) | |
1505 | ||
1506 | (define_split | |
1507 | [(set (match_operand:SI 0 "register_operand" "=r,&r") | |
1508 | (lshiftrt:SI (ashift:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0") | |
1509 | (match_operand:SI 2 "const_int_operand" "N,n")) | |
1510 | (match_operand:SI 3 "register_operand" "0,r")) | |
1511 | (match_operand:SI 4 "const_int_operand" "n,n")) | |
1512 | (match_operand:SI 5 "const_int_operand" "n,n"))) | |
1513 | (clobber (reg:SI 18))] | |
1514 | "" | |
1515 | [(use (reg:SI 0))] | |
1516 | " | |
1517 | { | |
fc2380b9 | 1518 | rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1]; |
98e819b9 JW |
1519 | |
1520 | if (INTVAL (operands[2])) | |
1521 | { | |
1522 | gen_shifty_op (LSHIFTRT, operands); | |
98e819b9 JW |
1523 | } |
1524 | emit_insn (gen_andsi3 (operands[0], operands[0], and_source)); | |
1525 | operands[2] = operands[4]; | |
1526 | gen_shifty_op (ASHIFT, operands); | |
1527 | if (INTVAL (operands[5])) | |
1528 | { | |
1529 | operands[2] = operands[5]; | |
1530 | gen_shifty_op (LSHIFTRT, operands); | |
1531 | } | |
1532 | DONE; | |
1533 | }") | |
1534 | ||
1535 | ;; signed left/right shift combination. | |
1536 | (define_split | |
1537 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1538 | (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") | |
1539 | (match_operand:SI 2 "const_int_operand" "n")) | |
1540 | (match_operand:SI 3 "const_int_operand" "n") | |
1541 | (const_int 0))) | |
1542 | (clobber (reg:SI 18))] | |
1543 | "" | |
1544 | [(use (reg:SI 0))] | |
1545 | "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL; | |
1546 | DONE;") | |
1547 | ||
1548 | (define_insn "shl_sext_ext" | |
1549 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1550 | (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") | |
1551 | (match_operand:SI 2 "const_int_operand" "n")) | |
1552 | (match_operand:SI 3 "const_int_operand" "n") | |
1553 | (const_int 0))) | |
1554 | (clobber (reg:SI 18))] | |
3c377a2a | 1555 | "(unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5" |
98e819b9 JW |
1556 | "#" |
1557 | [(set (attr "length") | |
1558 | (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1)) | |
1559 | (const_string "2") | |
1560 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 2)) | |
1561 | (const_string "4") | |
1562 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) | |
1563 | (const_string "6") | |
1564 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) | |
1565 | (const_string "8") | |
1566 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) | |
1567 | (const_string "10") | |
1568 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) | |
1569 | (const_string "12") | |
1570 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 7)) | |
1571 | (const_string "14") | |
1572 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 8)) | |
1573 | (const_string "16")] | |
1574 | (const_string "18"))) | |
1575 | (set_attr "type" "arith")]) | |
1576 | ||
1577 | (define_insn "shl_sext_sub" | |
1578 | [(set (match_operand:SI 0 "register_operand" "=z") | |
1579 | (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "0") | |
1580 | (match_operand:SI 2 "const_int_operand" "n")) | |
1581 | (match_operand:SI 3 "const_int_operand" "n") | |
1582 | (const_int 0))) | |
1583 | (clobber (reg:SI 18))] | |
1584 | "(shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6" | |
1585 | "#" | |
1586 | [(set (attr "length") | |
1587 | (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3)) | |
1588 | (const_string "6") | |
1589 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 4)) | |
1590 | (const_string "8") | |
1591 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 5)) | |
1592 | (const_string "10") | |
1593 | (eq (symbol_ref "shl_sext_length (insn)") (const_int 6)) | |
1594 | (const_string "12")] | |
1595 | (const_string "14"))) | |
1596 | (set_attr "type" "arith")]) | |
1597 | ||
977eef43 JW |
1598 | ;; These patterns are found in expansions of DImode shifts by 16, and |
1599 | ;; allow the xtrct instruction to be generated from C source. | |
1600 | ||
1601 | (define_insn "xtrct_left" | |
1602 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1603 | (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") | |
1604 | (const_int 16)) | |
1605 | (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0") | |
1606 | (const_int 16))))] | |
1607 | "" | |
1245df60 R |
1608 | "xtrct %1,%0" |
1609 | [(set_attr "type" "arith")]) | |
977eef43 JW |
1610 | |
1611 | (define_insn "xtrct_right" | |
1612 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
1613 | (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") | |
1614 | (const_int 16)) | |
1615 | (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r") | |
1616 | (const_int 16))))] | |
1617 | "" | |
1245df60 R |
1618 | "xtrct %2,%0" |
1619 | [(set_attr "type" "arith")]) | |
bc45ade3 SC |
1620 | \f |
1621 | ;; ------------------------------------------------------------------------- | |
1622 | ;; Unary arithmetic | |
1623 | ;; ------------------------------------------------------------------------- | |
1624 | ||
8e87e161 SC |
1625 | (define_insn "negc" |
1626 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
51bd623f JW |
1627 | (neg:SI (plus:SI (reg:SI 18) |
1628 | (match_operand:SI 1 "arith_reg_operand" "r")))) | |
1629 | (set (reg:SI 18) | |
07a45e5c | 1630 | (ne:SI (ior:SI (reg:SI 18) (match_dup 1)) |
51bd623f | 1631 | (const_int 0)))] |
bc45ade3 | 1632 | "" |
8e87e161 | 1633 | "negc %1,%0" |
22e1ebf1 | 1634 | [(set_attr "type" "arith")]) |
bc45ade3 | 1635 | |
8e87e161 | 1636 | (define_expand "negdi2" |
51aea58d JW |
1637 | [(set (match_operand:DI 0 "arith_reg_operand" "") |
1638 | (neg:DI (match_operand:DI 1 "arith_reg_operand" ""))) | |
8e87e161 SC |
1639 | (clobber (reg:SI 18))] |
1640 | "" | |
ffae286a JW |
1641 | " |
1642 | { | |
0a0b733a RK |
1643 | int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1); |
1644 | int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0); | |
8e87e161 | 1645 | |
0a0b733a RK |
1646 | rtx low_src = operand_subword (operands[1], low_word, 0, DImode); |
1647 | rtx high_src = operand_subword (operands[1], high_word, 0, DImode); | |
1648 | ||
1649 | rtx low_dst = operand_subword (operands[0], low_word, 1, DImode); | |
1650 | rtx high_dst = operand_subword (operands[0], high_word, 1, DImode); | |
8e87e161 | 1651 | |
ffae286a JW |
1652 | emit_insn (gen_clrt ()); |
1653 | emit_insn (gen_negc (low_dst, low_src)); | |
1654 | emit_insn (gen_negc (high_dst, high_src)); | |
1655 | DONE; | |
1656 | }") | |
8e87e161 | 1657 | |
bc45ade3 | 1658 | (define_insn "negsi2" |
aa684c94 SC |
1659 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
1660 | (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))] | |
bc45ade3 SC |
1661 | "" |
1662 | "neg %1,%0" | |
1663 | [(set_attr "type" "arith")]) | |
1664 | ||
1665 | (define_insn "one_cmplsi2" | |
aa684c94 SC |
1666 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
1667 | (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))] | |
bc45ade3 SC |
1668 | "" |
1669 | "not %1,%0" | |
0d7e008e | 1670 | [(set_attr "type" "arith")]) |
bc45ade3 SC |
1671 | \f |
1672 | ;; ------------------------------------------------------------------------- | |
1673 | ;; Zero extension instructions | |
1674 | ;; ------------------------------------------------------------------------- | |
1675 | ||
1676 | (define_insn "zero_extendhisi2" | |
aa684c94 SC |
1677 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
1678 | (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))] | |
bc45ade3 SC |
1679 | "" |
1680 | "extu.w %1,%0" | |
1681 | [(set_attr "type" "arith")]) | |
1682 | ||
1683 | (define_insn "zero_extendqisi2" | |
aa684c94 SC |
1684 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
1685 | (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))] | |
bc45ade3 SC |
1686 | "" |
1687 | "extu.b %1,%0" | |
07a45e5c | 1688 | [(set_attr "type" "arith")]) |
bc45ade3 SC |
1689 | |
1690 | (define_insn "zero_extendqihi2" | |
aa684c94 SC |
1691 | [(set (match_operand:HI 0 "arith_reg_operand" "=r") |
1692 | (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] | |
bc45ade3 SC |
1693 | "" |
1694 | "extu.b %1,%0" | |
07a45e5c | 1695 | [(set_attr "type" "arith")]) |
bc45ade3 SC |
1696 | \f |
1697 | ;; ------------------------------------------------------------------------- | |
1698 | ;; Sign extension instructions | |
1699 | ;; ------------------------------------------------------------------------- | |
1700 | ||
ffae286a JW |
1701 | ;; ??? This should be a define expand. |
1702 | ;; ??? Or perhaps it should be dropped? | |
1703 | ||
1245df60 R |
1704 | /* There is no point in defining extendsidi2; convert_move generates good |
1705 | code for that. */ | |
bc45ade3 SC |
1706 | |
1707 | (define_insn "extendhisi2" | |
51bd623f JW |
1708 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") |
1709 | (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))] | |
bc45ade3 | 1710 | "" |
0d7e008e SC |
1711 | "@ |
1712 | exts.w %1,%0 | |
0d7e008e | 1713 | mov.w %1,%0" |
51bd623f | 1714 | [(set_attr "type" "arith,load")]) |
bc45ade3 SC |
1715 | |
1716 | (define_insn "extendqisi2" | |
51bd623f JW |
1717 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") |
1718 | (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))] | |
bc45ade3 | 1719 | "" |
0d7e008e SC |
1720 | "@ |
1721 | exts.b %1,%0 | |
51bd623f JW |
1722 | mov.b %1,%0" |
1723 | [(set_attr "type" "arith,load")]) | |
bc45ade3 SC |
1724 | |
1725 | (define_insn "extendqihi2" | |
51bd623f JW |
1726 | [(set (match_operand:HI 0 "arith_reg_operand" "=r,r") |
1727 | (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))] | |
bc45ade3 | 1728 | "" |
0d7e008e SC |
1729 | "@ |
1730 | exts.b %1,%0 | |
51bd623f JW |
1731 | mov.b %1,%0" |
1732 | [(set_attr "type" "arith,load")]) | |
bc45ade3 SC |
1733 | \f |
1734 | ;; ------------------------------------------------------------------------- | |
1735 | ;; Move instructions | |
1736 | ;; ------------------------------------------------------------------------- | |
1737 | ||
0d7e008e | 1738 | ;; define push and pop so it is easy for sh.c |
b9654711 SC |
1739 | |
1740 | (define_insn "push" | |
1741 | [(set (mem:SI (pre_dec:SI (reg:SI 15))) | |
ffae286a | 1742 | (match_operand:SI 0 "register_operand" "r,l,x"))] |
b9654711 SC |
1743 | "" |
1744 | "@ | |
1745 | mov.l %0,@-r15 | |
ffae286a | 1746 | sts.l %0,@-r15 |
51bd623f | 1747 | sts.l %0,@-r15" |
ffae286a | 1748 | [(set_attr "type" "store,pstore,store") |
0d7e008e | 1749 | (set_attr "hit_stack" "yes")]) |
b9654711 SC |
1750 | |
1751 | (define_insn "pop" | |
51bd623f | 1752 | [(set (match_operand:SI 0 "register_operand" "=r,l,x") |
b9654711 SC |
1753 | (mem:SI (post_inc:SI (reg:SI 15))))] |
1754 | "" | |
1755 | "@ | |
1756 | mov.l @r15+,%0 | |
51bd623f | 1757 | lds.l @r15+,%0 |
0d7e008e | 1758 | lds.l @r15+,%0" |
51bd623f | 1759 | [(set_attr "type" "load,pload,load") |
0d7e008e | 1760 | (set_attr "hit_stack" "yes")]) |
b9654711 | 1761 | |
45348d9e JW |
1762 | (define_insn "push_e" |
1763 | [(set (mem:SF (pre_dec:SI (reg:SI 15))) | |
1764 | (match_operand:SF 0 "register_operand" "r,f,y"))] | |
8255ed68 | 1765 | "TARGET_SH3E" |
45348d9e JW |
1766 | "@ |
1767 | mov.l %0,@-r15 | |
1768 | fmov.s %0,@-r15 | |
1769 | sts.l %0,@-r15" | |
1770 | [(set_attr "type" "store") | |
1771 | (set_attr "hit_stack" "yes")]) | |
1772 | ||
1773 | (define_insn "pop_e" | |
1774 | [(set (match_operand:SF 0 "register_operand" "=r,f,y") | |
1775 | (mem:SF (post_inc:SI (reg:SI 15))))] | |
8255ed68 | 1776 | "TARGET_SH3E" |
45348d9e JW |
1777 | "@ |
1778 | mov.l @r15+,%0 | |
1779 | fmov.s @r15+,%0 | |
1780 | lds.l @r15+,%0" | |
1781 | [(set_attr "type" "load") | |
1782 | (set_attr "hit_stack" "yes")]) | |
1783 | ||
e3391510 JW |
1784 | ;; These two patterns can happen as the result of optimization, when |
1785 | ;; comparisons get simplified to a move of zero or 1 into the T reg. | |
1786 | ;; They don't disappear completely, because the T reg is a fixed hard reg. | |
ffae286a | 1787 | |
0d7e008e SC |
1788 | (define_insn "clrt" |
1789 | [(set (reg:SI 18) (const_int 0))] | |
b9654711 | 1790 | "" |
0d7e008e | 1791 | "clrt") |
bc45ade3 | 1792 | |
e3391510 JW |
1793 | (define_insn "sett" |
1794 | [(set (reg:SI 18) (const_int 1))] | |
1795 | "" | |
1796 | "sett") | |
1797 | ||
1245df60 | 1798 | ;; t/r is first, so that it will be preferred over r/r when reloading a move |
ffae286a | 1799 | ;; of a pseudo-reg into the T reg |
0d7e008e | 1800 | (define_insn "movsi_i" |
1245df60 R |
1801 | [(set (match_operand:SI 0 "general_movdst_operand" "=t,r,r,r,r,r,m,<,<,xl,x,l,r") |
1802 | (match_operand:SI 1 "general_movsrc_operand" "r,Q,rI,m,xl,t,r,x,l,r,>,>,i"))] | |
45348d9e | 1803 | " |
1245df60 R |
1804 | ! TARGET_SH3E |
1805 | && (register_operand (operands[0], SImode) | |
1806 | || register_operand (operands[1], SImode))" | |
8e87e161 | 1807 | "@ |
1245df60 | 1808 | cmp/pl %1 |
8e87e161 SC |
1809 | mov.l %1,%0 |
1810 | mov %1,%0 | |
1811 | mov.l %1,%0 | |
1812 | sts %1,%0 | |
1813 | movt %0 | |
1814 | mov.l %1,%0 | |
1815 | sts.l %1,%0 | |
1245df60 | 1816 | sts.l %1,%0 |
8e87e161 SC |
1817 | lds %1,%0 |
1818 | lds.l %1,%0 | |
1245df60 | 1819 | lds.l %1,%0 |
51bd623f | 1820 | fake %1,%0" |
1245df60 R |
1821 | [(set_attr "type" "*,pcload_si,move,load_si,move,move,store,store,pstore,move,load,pload,pcload_si") |
1822 | (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*")]) | |
07a45e5c | 1823 | |
1245df60 R |
1824 | ;; t/r must come after r/r, lest reload will try to reload stuff like |
1825 | ;; (subreg:SI (reg:SF 38 fr14) 0) into T (compiling stdlib/strtod.c -m3e -O2) | |
45348d9e JW |
1826 | ;; ??? This allows moves from macl to fpul to be recognized, but these moves |
1827 | ;; will require a reload. | |
1828 | (define_insn "movsi_ie" | |
1245df60 R |
1829 | [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,m,<,<,xl,x,l,r,y,r,y") |
1830 | (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,m,xl,t,r,x,l,r,>,>,i,r,y,y"))] | |
45348d9e JW |
1831 | "TARGET_SH3E |
1832 | && (register_operand (operands[0], SImode) | |
1833 | || register_operand (operands[1], SImode))" | |
1834 | "@ | |
45348d9e JW |
1835 | mov.l %1,%0 |
1836 | mov %1,%0 | |
1245df60 | 1837 | cmp/pl %1 |
45348d9e JW |
1838 | mov.l %1,%0 |
1839 | sts %1,%0 | |
1840 | movt %0 | |
1841 | mov.l %1,%0 | |
1842 | sts.l %1,%0 | |
1245df60 | 1843 | sts.l %1,%0 |
45348d9e JW |
1844 | lds %1,%0 |
1845 | lds.l %1,%0 | |
1245df60 | 1846 | lds.l %1,%0 |
45348d9e JW |
1847 | fake %1,%0 |
1848 | lds %1,%0 | |
1245df60 R |
1849 | sts %1,%0 |
1850 | ! move optimized away" | |
4dff12bf | 1851 | [(set_attr "type" "pcload_si,move,*,load_si,move,move,store,store,pstore,move,load,pload,pcload_si,gp_fpul,gp_fpul,nil") |
1245df60 R |
1852 | (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")]) |
1853 | ||
1854 | (define_insn "movsi_i_lowpart" | |
1855 | [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,r,m,r")) | |
1856 | (match_operand:SI 1 "general_movsrc_operand" "Q,rI,m,xl,t,r,i"))] | |
1857 | "register_operand (operands[0], SImode) | |
1858 | || register_operand (operands[1], SImode)" | |
1859 | "@ | |
1860 | mov.l %1,%0 | |
1861 | mov %1,%0 | |
1862 | mov.l %1,%0 | |
1863 | sts %1,%0 | |
1864 | movt %0 | |
1865 | mov.l %1,%0 | |
1866 | fake %1,%0" | |
1867 | [(set_attr "type" "pcload,move,load,move,move,store,pcload")]) | |
bc45ade3 | 1868 | (define_expand "movsi" |
0d7e008e SC |
1869 | [(set (match_operand:SI 0 "general_movdst_operand" "") |
1870 | (match_operand:SI 1 "general_movsrc_operand" ""))] | |
bc45ade3 | 1871 | "" |
ffae286a | 1872 | "{ if (prepare_move_operands (operands, SImode)) DONE; }") |
961c4780 | 1873 | |
bc45ade3 | 1874 | (define_insn "movqi_i" |
07a45e5c JW |
1875 | [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,r,l") |
1876 | (match_operand:QI 1 "general_movsrc_operand" "ri,m,r,t,l,r"))] | |
1877 | "arith_reg_operand (operands[0], QImode) | |
0d7e008e | 1878 | || arith_reg_operand (operands[1], QImode)" |
bc45ade3 SC |
1879 | "@ |
1880 | mov %1,%0 | |
0d7e008e SC |
1881 | mov.b %1,%0 |
1882 | mov.b %1,%0 | |
1883 | movt %0 | |
bc45ade3 | 1884 | sts %1,%0 |
0d7e008e | 1885 | lds %1,%0" |
22e1ebf1 | 1886 | [(set_attr "type" "move,load,store,move,move,move")]) |
bc45ade3 SC |
1887 | |
1888 | (define_expand "movqi" | |
1889 | [(set (match_operand:QI 0 "general_operand" "") | |
1890 | (match_operand:QI 1 "general_operand" ""))] | |
1891 | "" | |
ffae286a | 1892 | "{ if (prepare_move_operands (operands, QImode)) DONE; }") |
bc45ade3 SC |
1893 | |
1894 | (define_insn "movhi_i" | |
07a45e5c JW |
1895 | [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r") |
1896 | (match_operand:HI 1 "general_movsrc_operand" "Q,rI,m,t,r,l,r,i"))] | |
51aea58d JW |
1897 | "arith_reg_operand (operands[0], HImode) |
1898 | || arith_reg_operand (operands[1], HImode)" | |
8e87e161 SC |
1899 | "@ |
1900 | mov.w %1,%0 | |
1901 | mov %1,%0 | |
1902 | mov.w %1,%0 | |
1903 | movt %0 | |
1904 | mov.w %1,%0 | |
8e87e161 | 1905 | sts %1,%0 |
51bd623f JW |
1906 | lds %1,%0 |
1907 | fake %1,%0" | |
27232d28 | 1908 | [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")]) |
bc45ade3 SC |
1909 | |
1910 | (define_expand "movhi" | |
0d7e008e SC |
1911 | [(set (match_operand:HI 0 "general_movdst_operand" "") |
1912 | (match_operand:HI 1 "general_movsrc_operand" ""))] | |
bc45ade3 | 1913 | "" |
ffae286a JW |
1914 | "{ if (prepare_move_operands (operands, HImode)) DONE; }") |
1915 | ||
1916 | ;; ??? This should be a define expand. | |
0d7e008e | 1917 | |
1245df60 R |
1918 | ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c |
1919 | ;; compiled with -m2 -ml -O3 -funroll-loops | |
0d7e008e | 1920 | (define_insn "" |
1245df60 R |
1921 | [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x") |
1922 | (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I,i,x,r"))] | |
51aea58d JW |
1923 | "arith_reg_operand (operands[0], DImode) |
1924 | || arith_reg_operand (operands[1], DImode)" | |
0d7e008e | 1925 | "* return output_movedouble (insn, operands, DImode);" |
22e1ebf1 | 1926 | [(set_attr "length" "4") |
1245df60 | 1927 | (set_attr "type" "pcload,move,load,store,move,pcload,move,move")]) |
bc45ade3 | 1928 | |
d0aae509 RK |
1929 | ;; If the output is a register and the input is memory or a register, we have |
1930 | ;; to be careful and see which word needs to be loaded first. | |
b9b7c1c9 | 1931 | |
8e87e161 SC |
1932 | (define_split |
1933 | [(set (match_operand:DI 0 "general_movdst_operand" "") | |
1934 | (match_operand:DI 1 "general_movsrc_operand" ""))] | |
d0aae509 | 1935 | "reload_completed" |
8e87e161 SC |
1936 | [(set (match_dup 2) (match_dup 3)) |
1937 | (set (match_dup 4) (match_dup 5))] | |
1938 | " | |
d0aae509 RK |
1939 | { |
1940 | int regno; | |
1941 | ||
1942 | if ((GET_CODE (operands[0]) == MEM | |
1943 | && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) | |
1944 | || (GET_CODE (operands[1]) == MEM | |
1945 | && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) | |
1946 | FAIL; | |
1947 | ||
1948 | if (GET_CODE (operands[0]) == REG) | |
1949 | regno = REGNO (operands[0]); | |
1950 | else if (GET_CODE (operands[0]) == SUBREG) | |
1951 | regno = REGNO (SUBREG_REG (operands[0])) + SUBREG_WORD (operands[0]); | |
1952 | else if (GET_CODE (operands[0]) == MEM) | |
1953 | regno = -1; | |
1954 | ||
1955 | if (regno == -1 | |
1956 | || ! refers_to_regno_p (regno, regno + 1, operands[1], 0)) | |
8e87e161 SC |
1957 | { |
1958 | operands[2] = operand_subword (operands[0], 0, 0, DImode); | |
1959 | operands[3] = operand_subword (operands[1], 0, 0, DImode); | |
1960 | operands[4] = operand_subword (operands[0], 1, 0, DImode); | |
1961 | operands[5] = operand_subword (operands[1], 1, 0, DImode); | |
1962 | } | |
1963 | else | |
1964 | { | |
1965 | operands[2] = operand_subword (operands[0], 1, 0, DImode); | |
1966 | operands[3] = operand_subword (operands[1], 1, 0, DImode); | |
1967 | operands[4] = operand_subword (operands[0], 0, 0, DImode); | |
1968 | operands[5] = operand_subword (operands[1], 0, 0, DImode); | |
1969 | } | |
1970 | ||
1971 | if (operands[2] == 0 || operands[3] == 0 | |
1972 | || operands[4] == 0 || operands[5] == 0) | |
1973 | FAIL; | |
1974 | }") | |
961c4780 | 1975 | |
bc45ade3 | 1976 | (define_expand "movdi" |
961c4780 SC |
1977 | [(set (match_operand:DI 0 "general_movdst_operand" "") |
1978 | (match_operand:DI 1 "general_movsrc_operand" ""))] | |
bc45ade3 | 1979 | "" |
ffae286a JW |
1980 | "{ if ( prepare_move_operands (operands, DImode)) DONE; }") |
1981 | ||
1982 | ;; ??? This should be a define expand. | |
bc45ade3 | 1983 | |
bc45ade3 | 1984 | (define_insn "movdf_k" |
3e943b59 JR |
1985 | [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m") |
1986 | (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))] | |
51aea58d JW |
1987 | "arith_reg_operand (operands[0], DFmode) |
1988 | || arith_reg_operand (operands[1], DFmode)" | |
0d7e008e | 1989 | "* return output_movedouble (insn, operands, DFmode);" |
b9654711 | 1990 | [(set_attr "length" "4") |
3e943b59 | 1991 | (set_attr "type" "move,pcload,load,store")]) |
bc45ade3 | 1992 | |
d0aae509 RK |
1993 | ;; If the output is a register and the input is memory or a register, we have |
1994 | ;; to be careful and see which word needs to be loaded first. | |
07a45e5c | 1995 | |
8e87e161 SC |
1996 | (define_split |
1997 | [(set (match_operand:DF 0 "general_movdst_operand" "") | |
1998 | (match_operand:DF 1 "general_movsrc_operand" ""))] | |
d0aae509 | 1999 | "reload_completed" |
8e87e161 SC |
2000 | [(set (match_dup 2) (match_dup 3)) |
2001 | (set (match_dup 4) (match_dup 5))] | |
2002 | " | |
d0aae509 RK |
2003 | { |
2004 | int regno; | |
2005 | ||
2006 | if ((GET_CODE (operands[0]) == MEM | |
2007 | && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) | |
2008 | || (GET_CODE (operands[1]) == MEM | |
2009 | && GET_CODE (XEXP (operands[1], 0)) == POST_INC)) | |
2010 | FAIL; | |
2011 | ||
2012 | if (GET_CODE (operands[0]) == REG) | |
2013 | regno = REGNO (operands[0]); | |
2014 | else if (GET_CODE (operands[0]) == SUBREG) | |
2015 | regno = REGNO (SUBREG_REG (operands[0])) + SUBREG_WORD (operands[0]); | |
2016 | else if (GET_CODE (operands[0]) == MEM) | |
2017 | regno = -1; | |
2018 | ||
2019 | if (regno == -1 | |
2020 | || ! refers_to_regno_p (regno, regno + 1, operands[1], 0)) | |
8e87e161 SC |
2021 | { |
2022 | operands[2] = operand_subword (operands[0], 0, 0, DFmode); | |
2023 | operands[3] = operand_subword (operands[1], 0, 0, DFmode); | |
2024 | operands[4] = operand_subword (operands[0], 1, 0, DFmode); | |
2025 | operands[5] = operand_subword (operands[1], 1, 0, DFmode); | |
2026 | } | |
2027 | else | |
2028 | { | |
2029 | operands[2] = operand_subword (operands[0], 1, 0, DFmode); | |
2030 | operands[3] = operand_subword (operands[1], 1, 0, DFmode); | |
2031 | operands[4] = operand_subword (operands[0], 0, 0, DFmode); | |
2032 | operands[5] = operand_subword (operands[1], 0, 0, DFmode); | |
2033 | } | |
2034 | ||
2035 | if (operands[2] == 0 || operands[3] == 0 | |
2036 | || operands[4] == 0 || operands[5] == 0) | |
2037 | FAIL; | |
2038 | }") | |
2039 | ||
653bd7a6 JW |
2040 | ;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is |
2041 | ;; used only once, let combine add in the index again. | |
2042 | ||
2043 | (define_split | |
2044 | [(set (match_operand:SI 0 "register_operand" "") | |
2045 | (match_operand:SI 1 "" "")) | |
2046 | (clobber (match_operand 2 "register_operand" ""))] | |
2047 | "! reload_in_progress && ! reload_completed" | |
2048 | [(use (reg:SI 0))] | |
2049 | " | |
2050 | { | |
2051 | rtx addr, reg, const_int; | |
2052 | ||
2053 | if (GET_CODE (operands[1]) != MEM) | |
2054 | FAIL; | |
2055 | addr = XEXP (operands[1], 0); | |
2056 | if (GET_CODE (addr) != PLUS) | |
2057 | FAIL; | |
2058 | reg = XEXP (addr, 0); | |
2059 | const_int = XEXP (addr, 1); | |
2060 | if (GET_CODE (reg) != REG || GET_CODE (const_int) != CONST_INT) | |
2061 | FAIL; | |
2062 | emit_move_insn (operands[2], const_int); | |
2063 | emit_move_insn (operands[0], | |
2064 | change_address (operands[1], VOIDmode, | |
2065 | gen_rtx (PLUS, SImode, reg, operands[2]))); | |
2066 | DONE; | |
2067 | }") | |
2068 | ||
2069 | (define_split | |
2070 | [(set (match_operand:SI 1 "" "") | |
2071 | (match_operand:SI 0 "register_operand" "")) | |
2072 | (clobber (match_operand 2 "register_operand" ""))] | |
2073 | "! reload_in_progress && ! reload_completed" | |
2074 | [(use (reg:SI 0))] | |
2075 | " | |
2076 | { | |
2077 | rtx addr, reg, const_int; | |
2078 | ||
2079 | if (GET_CODE (operands[1]) != MEM) | |
2080 | FAIL; | |
2081 | addr = XEXP (operands[1], 0); | |
2082 | if (GET_CODE (addr) != PLUS) | |
2083 | FAIL; | |
2084 | reg = XEXP (addr, 0); | |
2085 | const_int = XEXP (addr, 1); | |
2086 | if (GET_CODE (reg) != REG || GET_CODE (const_int) != CONST_INT) | |
2087 | FAIL; | |
2088 | emit_move_insn (operands[2], const_int); | |
2089 | emit_move_insn (change_address (operands[1], VOIDmode, | |
2090 | gen_rtx (PLUS, SImode, reg, operands[2])), | |
2091 | operands[0]); | |
2092 | DONE; | |
2093 | }") | |
2094 | ||
bc45ade3 | 2095 | (define_expand "movdf" |
0d7e008e SC |
2096 | [(set (match_operand:DF 0 "general_movdst_operand" "") |
2097 | (match_operand:DF 1 "general_movsrc_operand" ""))] | |
bc45ade3 | 2098 | "" |
1245df60 R |
2099 | " |
2100 | { | |
2101 | if (prepare_move_operands (operands, DFmode)) DONE; | |
2102 | }") | |
2103 | ||
bc45ade3 | 2104 | |
bc45ade3 | 2105 | (define_insn "movsf_i" |
3e943b59 JR |
2106 | [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r") |
2107 | (match_operand:SF 1 "general_movsrc_operand" "r,I,FQ,m,r,r,l"))] | |
45348d9e | 2108 | " |
1245df60 R |
2109 | ! TARGET_SH3E |
2110 | && (arith_reg_operand (operands[0], SFmode) | |
2111 | || arith_reg_operand (operands[1], SFmode))" | |
bc45ade3 SC |
2112 | "@ |
2113 | mov %1,%0 | |
2114 | mov %1,%0 | |
2115 | mov.l %1,%0 | |
2116 | mov.l %1,%0 | |
3e943b59 | 2117 | mov.l %1,%0 |
b9654711 | 2118 | lds %1,%0 |
0d7e008e | 2119 | sts %1,%0" |
3e943b59 | 2120 | [(set_attr "type" "move,move,pcload,load,store,move,move")]) |
bc45ade3 | 2121 | |
4dff12bf R |
2122 | ;; We may not split the ry/yr/XX alternatives to movsi_ie, since |
2123 | ;; update_flow_info would not know where to put REG_EQUAL notes | |
2124 | ;; when the destination changes mode. | |
45348d9e | 2125 | (define_insn "movsf_ie" |
7f74cc8d | 2126 | [(set (match_operand:SF 0 "general_movdst_operand" |
4dff12bf | 2127 | "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,y") |
7f74cc8d | 2128 | (match_operand:SF 1 "general_movsrc_operand" |
4dff12bf R |
2129 | "f,r,G,H,FQ,m,f,FQ,m,r,y,f,>,fr,y,r,y")) |
2130 | (clobber (match_scratch:SI 2 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X"))] | |
7f74cc8d | 2131 | |
45348d9e JW |
2132 | "TARGET_SH3E |
2133 | && (arith_reg_operand (operands[0], SFmode) | |
2134 | || arith_reg_operand (operands[1], SFmode))" | |
2135 | "@ | |
2136 | fmov %1,%0 | |
2137 | mov %1,%0 | |
2138 | fldi0 %0 | |
2139 | fldi1 %0 | |
7f74cc8d | 2140 | # |
45348d9e JW |
2141 | fmov.s %1,%0 |
2142 | fmov.s %1,%0 | |
2143 | mov.l %1,%0 | |
2144 | mov.l %1,%0 | |
3e943b59 | 2145 | mov.l %1,%0 |
1245df60 R |
2146 | fsts fpul,%0 |
2147 | flds %1,fpul | |
2148 | lds.l %1,%0 | |
2149 | # | |
4dff12bf R |
2150 | sts %1,%0 |
2151 | lds %1,%0 | |
2152 | ! move optimized away" | |
2153 | [(set_attr "type" "fmove,move,fmove,fmove,pcload,load,store,pcload,load,store,fmove,fmove,load,*,gp_fpul,gp_fpul,nil") | |
2154 | (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,*,2,2,0")]) | |
45348d9e | 2155 | |
1245df60 R |
2156 | (define_split |
2157 | [(set (match_operand:SF 0 "register_operand" "") | |
2158 | (match_operand:SF 1 "register_operand" "")) | |
2159 | (clobber (reg:SI 22))] | |
2160 | "" | |
2161 | [(parallel [(set (reg:SF 22) (match_dup 1)) | |
2162 | (clobber (scratch:SI))]) | |
2163 | (parallel [(set (match_dup 0) (reg:SF 22)) | |
2164 | (clobber (scratch:SI))])] | |
2165 | "") | |
2166 | ||
bc45ade3 | 2167 | (define_expand "movsf" |
0d7e008e | 2168 | [(set (match_operand:SF 0 "general_movdst_operand" "") |
3e943b59 | 2169 | (match_operand:SF 1 "general_movsrc_operand" ""))] |
bc45ade3 | 2170 | "" |
3e943b59 JR |
2171 | " |
2172 | { | |
2173 | if (prepare_move_operands (operands, SFmode)) | |
2174 | DONE; | |
7f74cc8d | 2175 | if (TARGET_SH3E) |
3e943b59 | 2176 | { |
7f74cc8d | 2177 | emit_insn (gen_movsf_ie (operands[0], operands[1])); |
3e943b59 JR |
2178 | DONE; |
2179 | } | |
2180 | }") | |
7f74cc8d JR |
2181 | |
2182 | (define_expand "reload_insf" | |
2183 | [(parallel [(set (match_operand:SF 0 "register_operand" "=f") | |
2184 | (match_operand:SF 1 "immediate_operand" "FQ")) | |
2185 | (clobber (match_operand:SI 2 "register_operand" "=&z"))])] | |
2186 | "" | |
2187 | "") | |
bc45ade3 SC |
2188 | \f |
2189 | ;; ------------------------------------------------------------------------ | |
2190 | ;; Define the real conditional branch instructions. | |
2191 | ;; ------------------------------------------------------------------------ | |
2192 | ||
2193 | (define_insn "branch_true" | |
7c225e88 | 2194 | [(set (pc) (if_then_else (ne (reg:SI 18) (const_int 0)) |
bc45ade3 SC |
2195 | (label_ref (match_operand 0 "" "")) |
2196 | (pc)))] | |
2197 | "" | |
51aea58d | 2198 | "* return output_branch (1, insn, operands);" |
bc45ade3 SC |
2199 | [(set_attr "type" "cbranch")]) |
2200 | ||
2201 | (define_insn "branch_false" | |
7c225e88 | 2202 | [(set (pc) (if_then_else (eq (reg:SI 18) (const_int 0)) |
bc45ade3 SC |
2203 | (label_ref (match_operand 0 "" "")) |
2204 | (pc)))] | |
2205 | "" | |
51aea58d | 2206 | "* return output_branch (0, insn, operands);" |
bc45ade3 SC |
2207 | [(set_attr "type" "cbranch")]) |
2208 | ||
1245df60 R |
2209 | ;; Patterns to prevent reorg from re-combining a condbranch with a branch |
2210 | ;; which destination is too far away. | |
2211 | ;; The const_int_operand is distinct for each branch target; it avoids | |
2212 | ;; unwanted matches with redundant_insn. | |
2213 | (define_insn "block_branch_redirect" | |
2214 | [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] 4))] | |
bc45ade3 | 2215 | "" |
1245df60 R |
2216 | "" |
2217 | [(set_attr "length" "0")]) | |
bc45ade3 | 2218 | |
1245df60 R |
2219 | ;; This one has the additional purpose to record a possible scratch register |
2220 | ;; for the following branch. | |
2221 | (define_insn "indirect_jump_scratch" | |
2222 | [(set (match_operand 0 "register_operand" "r") | |
2223 | (unspec [(match_operand 1 "const_int_operand" "")] 4))] | |
bc45ade3 | 2224 | "" |
1245df60 R |
2225 | "" |
2226 | [(set_attr "length" "0")]) | |
bc45ade3 SC |
2227 | \f |
2228 | ;; Conditional branch insns | |
2229 | ||
2230 | (define_expand "beq" | |
1245df60 | 2231 | [(set (pc) |
7c225e88 | 2232 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
bc45ade3 SC |
2233 | (label_ref (match_operand 0 "" "")) |
2234 | (pc)))] | |
2235 | "" | |
0d7e008e | 2236 | "from_compare (operands, EQ);") |
bc45ade3 | 2237 | |
bc45ade3 | 2238 | (define_expand "bne" |
1245df60 R |
2239 | [(set (pc) |
2240 | (if_then_else (eq (reg:SI 18) (const_int 0)) | |
2241 | (label_ref (match_operand 0 "" "")) | |
2242 | (pc)))] | |
bc45ade3 | 2243 | "" |
1245df60 | 2244 | "from_compare (operands, EQ);") |
bc45ade3 SC |
2245 | |
2246 | (define_expand "bgt" | |
1245df60 | 2247 | [(set (pc) |
7c225e88 | 2248 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
bc45ade3 | 2249 | (label_ref (match_operand 0 "" "")) |
ffae286a | 2250 | (pc)))] |
bc45ade3 | 2251 | "" |
0d7e008e | 2252 | "from_compare (operands, GT);") |
bc45ade3 SC |
2253 | |
2254 | (define_expand "blt" | |
1245df60 R |
2255 | [(set (pc) |
2256 | (if_then_else (eq (reg:SI 18) (const_int 0)) | |
2257 | (label_ref (match_operand 0 "" "")) | |
2258 | (pc)))] | |
bc45ade3 | 2259 | "" |
45348d9e JW |
2260 | " |
2261 | { | |
2262 | if (GET_MODE (sh_compare_op0) == SFmode) | |
2263 | { | |
2264 | rtx tmp = sh_compare_op0; | |
2265 | sh_compare_op0 = sh_compare_op1; | |
2266 | sh_compare_op1 = tmp; | |
2267 | emit_insn (gen_bgt (operands[0])); | |
2268 | DONE; | |
2269 | } | |
1245df60 | 2270 | from_compare (operands, GE); |
45348d9e | 2271 | }") |
bc45ade3 SC |
2272 | |
2273 | (define_expand "ble" | |
1245df60 R |
2274 | [(set (pc) |
2275 | (if_then_else (eq (reg:SI 18) (const_int 0)) | |
2276 | (label_ref (match_operand 0 "" "")) | |
2277 | (pc)))] | |
bc45ade3 | 2278 | "" |
1245df60 R |
2279 | " |
2280 | { | |
2281 | if (TARGET_SH3E | |
2282 | && TARGET_IEEE | |
2283 | && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) | |
2284 | { | |
2285 | rtx tmp = sh_compare_op0; | |
2286 | sh_compare_op0 = sh_compare_op1; | |
2287 | sh_compare_op1 = tmp; | |
2288 | emit_insn (gen_bge (operands[0])); | |
2289 | DONE; | |
2290 | } | |
2291 | from_compare (operands, GT); | |
2292 | }") | |
bc45ade3 SC |
2293 | |
2294 | (define_expand "bge" | |
1245df60 | 2295 | [(set (pc) |
7c225e88 | 2296 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
bc45ade3 | 2297 | (label_ref (match_operand 0 "" "")) |
ffae286a | 2298 | (pc)))] |
bc45ade3 | 2299 | "" |
45348d9e JW |
2300 | " |
2301 | { | |
1245df60 R |
2302 | if (TARGET_SH3E |
2303 | && ! TARGET_IEEE | |
2304 | && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) | |
45348d9e JW |
2305 | { |
2306 | rtx tmp = sh_compare_op0; | |
2307 | sh_compare_op0 = sh_compare_op1; | |
2308 | sh_compare_op1 = tmp; | |
2309 | emit_insn (gen_ble (operands[0])); | |
2310 | DONE; | |
2311 | } | |
2312 | from_compare (operands, GE); | |
2313 | }") | |
bc45ade3 SC |
2314 | |
2315 | (define_expand "bgtu" | |
1245df60 | 2316 | [(set (pc) |
7c225e88 | 2317 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
bc45ade3 SC |
2318 | (label_ref (match_operand 0 "" "")) |
2319 | (pc)))] | |
2320 | "" | |
0d7e008e | 2321 | "from_compare (operands, GTU); ") |
bc45ade3 SC |
2322 | |
2323 | (define_expand "bltu" | |
1245df60 R |
2324 | [(set (pc) |
2325 | (if_then_else (eq (reg:SI 18) (const_int 0)) | |
2326 | (label_ref (match_operand 0 "" "")) | |
2327 | (pc)))] | |
bc45ade3 | 2328 | "" |
1245df60 | 2329 | "from_compare (operands, GEU);") |
bc45ade3 SC |
2330 | |
2331 | (define_expand "bgeu" | |
1245df60 | 2332 | [(set (pc) |
7c225e88 | 2333 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
bc45ade3 | 2334 | (label_ref (match_operand 0 "" "")) |
ffae286a | 2335 | (pc)))] |
bc45ade3 | 2336 | "" |
0d7e008e | 2337 | "from_compare (operands, GEU);") |
bc45ade3 SC |
2338 | |
2339 | (define_expand "bleu" | |
1245df60 R |
2340 | [(set (pc) |
2341 | (if_then_else (eq (reg:SI 18) (const_int 0)) | |
2342 | (label_ref (match_operand 0 "" "")) | |
2343 | (pc)))] | |
bc45ade3 | 2344 | "" |
1245df60 | 2345 | "from_compare (operands, GTU);") |
bc45ade3 SC |
2346 | \f |
2347 | ;; ------------------------------------------------------------------------ | |
2348 | ;; Jump and linkage insns | |
2349 | ;; ------------------------------------------------------------------------ | |
2350 | ||
0d7e008e | 2351 | (define_insn "jump" |
bc45ade3 SC |
2352 | [(set (pc) |
2353 | (label_ref (match_operand 0 "" "")))] | |
2354 | "" | |
2355 | "* | |
2356 | { | |
22e1ebf1 | 2357 | /* The length is 16 if the delay slot is unfilled. */ |
1245df60 | 2358 | if (get_attr_length(insn) > 4) |
51aea58d | 2359 | return output_far_jump(insn, operands[0]); |
bc45ade3 | 2360 | else |
51aea58d | 2361 | return \"bra %l0%#\"; |
bc45ade3 SC |
2362 | }" |
2363 | [(set_attr "type" "jump") | |
2364 | (set_attr "needs_delay_slot" "yes")]) | |
2365 | ||
bc45ade3 | 2366 | (define_insn "calli" |
aa684c94 | 2367 | [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) |
bc45ade3 SC |
2368 | (match_operand 1 "" "")) |
2369 | (clobber (reg:SI 17))] | |
2370 | "" | |
2371 | "jsr @%0%#" | |
ffae286a JW |
2372 | [(set_attr "type" "call") |
2373 | (set_attr "needs_delay_slot" "yes")]) | |
961c4780 | 2374 | |
bc45ade3 SC |
2375 | (define_insn "call_valuei" |
2376 | [(set (match_operand 0 "" "=rf") | |
aa684c94 | 2377 | (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) |
bc45ade3 SC |
2378 | (match_operand 2 "" ""))) |
2379 | (clobber (reg:SI 17))] | |
2380 | "" | |
2381 | "jsr @%1%#" | |
ffae286a JW |
2382 | [(set_attr "type" "call") |
2383 | (set_attr "needs_delay_slot" "yes")]) | |
bc45ade3 SC |
2384 | |
2385 | (define_expand "call" | |
51aea58d JW |
2386 | [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) |
2387 | (match_operand 1 "" "")) | |
2388 | (clobber (reg:SI 17))])] | |
bc45ade3 | 2389 | "" |
51aea58d | 2390 | "operands[0] = force_reg (SImode, XEXP (operands[0], 0));") |
bc45ade3 SC |
2391 | |
2392 | (define_expand "call_value" | |
51aea58d JW |
2393 | [(parallel [(set (match_operand 0 "arith_reg_operand" "") |
2394 | (call (mem:SI (match_operand 1 "arith_reg_operand" "")) | |
2395 | (match_operand 2 "" ""))) | |
2396 | (clobber (reg:SI 17))])] | |
bc45ade3 | 2397 | "" |
51aea58d | 2398 | "operands[1] = force_reg (SImode, XEXP (operands[1], 0));") |
bc45ade3 SC |
2399 | |
2400 | (define_insn "indirect_jump" | |
2401 | [(set (pc) | |
aa684c94 | 2402 | (match_operand:SI 0 "arith_reg_operand" "r"))] |
bc45ade3 | 2403 | "" |
b9654711 | 2404 | "jmp @%0%#" |
1245df60 R |
2405 | [(set_attr "needs_delay_slot" "yes") |
2406 | (set_attr "type" "jump_ind")]) | |
a1a0806a | 2407 | |
1245df60 | 2408 | ;; The use of operand 1 / 2 helps us distinguish case table jumps |
f1ffca1c JW |
2409 | ;; which can be present in structured code from indirect jumps which can not |
2410 | ;; be present in structured code. This allows -fprofile-arcs to work. | |
2411 | ||
1245df60 R |
2412 | ;; For SH1 processors. |
2413 | (define_insn "casesi_jump_1" | |
f1ffca1c | 2414 | [(set (pc) |
1245df60 | 2415 | (match_operand:SI 0 "register_operand" "r")) |
f1ffca1c JW |
2416 | (use (label_ref (match_operand 1 "" "")))] |
2417 | "" | |
1245df60 R |
2418 | "jmp @%0%#" |
2419 | [(set_attr "needs_delay_slot" "yes") | |
2420 | (set_attr "type" "jump_ind")]) | |
2421 | ||
2422 | ;; For all later processors. | |
2423 | (define_insn "casesi_jump_2" | |
2424 | [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r") | |
2425 | (match_operand 1 "braf_label_ref_operand" ""))) | |
2426 | (use (label_ref (match_operand 2 "" "")))] | |
2427 | "" | |
2428 | "braf %0%#" | |
2429 | [(set_attr "needs_delay_slot" "yes") | |
2430 | (set_attr "type" "jump_ind")]) | |
2431 | ||
2432 | (define_insn "dummy_jump" | |
2433 | [(set (pc) (const_int 0))] | |
2434 | "" | |
2435 | "" | |
2436 | [(set_attr "length" "0")]) | |
f1ffca1c | 2437 | |
a1a0806a JW |
2438 | ;; Call subroutine returning any type. |
2439 | ;; ??? This probably doesn't work. | |
2440 | ||
2441 | (define_expand "untyped_call" | |
2442 | [(parallel [(call (match_operand 0 "" "") | |
2443 | (const_int 0)) | |
2444 | (match_operand 1 "" "") | |
2445 | (match_operand 2 "" "")])] | |
2446 | "TARGET_SH3E" | |
2447 | " | |
2448 | { | |
2449 | int i; | |
2450 | ||
2451 | emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx, const0_rtx)); | |
2452 | ||
2453 | for (i = 0; i < XVECLEN (operands[2], 0); i++) | |
2454 | { | |
2455 | rtx set = XVECEXP (operands[2], 0, i); | |
2456 | emit_move_insn (SET_DEST (set), SET_SRC (set)); | |
2457 | } | |
2458 | ||
2459 | /* The optimizer does not know that the call sets the function value | |
2460 | registers we stored in the result block. We avoid problems by | |
2461 | claiming that all hard registers are used and clobbered at this | |
2462 | point. */ | |
2463 | emit_insn (gen_blockage ()); | |
2464 | ||
2465 | DONE; | |
2466 | }") | |
bc45ade3 SC |
2467 | \f |
2468 | ;; ------------------------------------------------------------------------ | |
2469 | ;; Misc insns | |
2470 | ;; ------------------------------------------------------------------------ | |
2471 | ||
51bd623f | 2472 | (define_insn "dect" |
aff48e32 JR |
2473 | [(set (reg:SI 18) |
2474 | (eq:SI (match_operand:SI 0 "arith_reg_operand" "+r") (const_int 1))) | |
2475 | (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] | |
51bd623f | 2476 | "TARGET_SH2" |
1245df60 R |
2477 | "dt %0" |
2478 | [(set_attr "type" "arith")]) | |
bc45ade3 SC |
2479 | |
2480 | (define_insn "nop" | |
2481 | [(const_int 0)] | |
2482 | "" | |
51bd623f | 2483 | "nop") |
0d7e008e | 2484 | |
1245df60 R |
2485 | ;; Load address of a label. This is only generated by the casesi expand, |
2486 | ;; and by machine_dependent_reorg (fixing up fp moves). | |
2487 | ;; This must use unspec, because this only works for labels that are | |
2488 | ;; within range, | |
0d7e008e SC |
2489 | |
2490 | (define_insn "mova" | |
07a45e5c | 2491 | [(set (reg:SI 0) |
51bd623f | 2492 | (unspec [(label_ref (match_operand 0 "" ""))] 1))] |
0d7e008e SC |
2493 | "" |
2494 | "mova %O0,r0" | |
1245df60 R |
2495 | [(set_attr "in_delay_slot" "no") |
2496 | (set_attr "type" "arith")]) | |
0d7e008e SC |
2497 | |
2498 | ;; case instruction for switch statements. | |
2499 | ||
2500 | ;; Operand 0 is index | |
2501 | ;; operand 1 is the minimum bound | |
2502 | ;; operand 2 is the maximum bound - minimum bound + 1 | |
2503 | ;; operand 3 is CODE_LABEL for the table; | |
2504 | ;; operand 4 is the CODE_LABEL to go to if index out of range. | |
2505 | ||
2506 | (define_expand "casesi" | |
1245df60 R |
2507 | [(match_operand:SI 0 "arith_reg_operand" "") |
2508 | (match_operand:SI 1 "arith_reg_operand" "") | |
2509 | (match_operand:SI 2 "arith_reg_operand" "") | |
2510 | (match_operand 3 "" "") (match_operand 4 "" "")] | |
2511 | "" | |
2512 | " | |
2513 | { | |
2514 | rtx reg = gen_reg_rtx (SImode); | |
2515 | rtx reg2 = gen_reg_rtx (SImode); | |
2516 | operands[1] = copy_to_mode_reg (SImode, operands[1]); | |
2517 | operands[2] = copy_to_mode_reg (SImode, operands[2]); | |
2518 | /* If optimizing, casesi_worker depends on the mode of the instruction | |
2519 | before label it 'uses' - operands[3]. */ | |
2520 | emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4], | |
2521 | reg)); | |
2522 | emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3])); | |
2523 | if (TARGET_SH2) | |
2524 | { | |
2525 | rtx lab = gen_label_rtx (); | |
2526 | emit_jump_insn (gen_casesi_jump_2 (reg2, | |
2527 | gen_rtx (LABEL_REF, VOIDmode, lab), | |
2528 | operands[3])); | |
2529 | emit_label (lab); | |
2530 | /* Put a fake jump after the label, lest some optimization might | |
2531 | delete the barrier and LAB. */ | |
2532 | emit_jump_insn (gen_dummy_jump ()); | |
2533 | } | |
2534 | else | |
2535 | { | |
2536 | emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3])); | |
2537 | } | |
2538 | /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to | |
2539 | operands[3], but to lab. We will fix this up in | |
2540 | machine_dependent_reorg. */ | |
2541 | emit_barrier (); | |
2542 | DONE; | |
2543 | }") | |
2544 | ||
2545 | (define_expand "casesi_0" | |
2546 | [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" "")) | |
2547 | (set (match_dup 4) (minus:SI (match_dup 4) | |
0d7e008e SC |
2548 | (match_operand:SI 1 "arith_operand" ""))) |
2549 | (set (reg:SI 18) | |
1245df60 | 2550 | (gtu:SI (match_dup 4) |
22e1ebf1 | 2551 | (match_operand:SI 2 "arith_reg_operand" ""))) |
0d7e008e | 2552 | (set (pc) |
7c225e88 JW |
2553 | (if_then_else (ne (reg:SI 18) |
2554 | (const_int 0)) | |
1245df60 R |
2555 | (label_ref (match_operand 3 "" "")) |
2556 | (pc)))] | |
0d7e008e | 2557 | "" |
1245df60 | 2558 | "") |
0d7e008e | 2559 | |
1245df60 R |
2560 | ;; ??? reload might clobber r0 if we use it explicitly in the RTL before |
2561 | ;; reload; using a R0_REGS pseudo reg is likely to give poor code. | |
2562 | ;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload. | |
2563 | ||
2564 | (define_insn "casesi_worker_0" | |
2565 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
2566 | (unspec [(match_operand 1 "register_operand" "0,r") | |
2567 | (label_ref (match_operand 2 "" ""))] 2)) | |
2568 | (clobber (match_scratch:SI 3 "=X,1")) | |
2569 | (clobber (match_scratch:SI 4 "=&z,z"))] | |
2570 | "" | |
2571 | "#") | |
2572 | ||
2573 | (define_split | |
2574 | [(set (match_operand:SI 0 "register_operand" "") | |
2575 | (unspec [(match_operand 1 "register_operand" "") | |
2576 | (label_ref (match_operand 2 "" ""))] 2)) | |
2577 | (clobber (match_scratch:SI 3 "")) | |
2578 | (clobber (match_scratch:SI 4 ""))] | |
2579 | "! TARGET_SH2 && reload_completed" | |
2580 | [(set (reg:SI 0) (unspec [(label_ref (match_dup 2))] 1)) | |
2581 | (parallel [(set (match_dup 0) | |
2582 | (unspec [(reg:SI 0) (match_dup 1) (label_ref (match_dup 2))] 2)) | |
2583 | (clobber (match_dup 3))]) | |
2584 | (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI 0)))] | |
2585 | "LABEL_NUSES (operands[2])++;") | |
2586 | ||
2587 | (define_split | |
2588 | [(set (match_operand:SI 0 "register_operand" "") | |
2589 | (unspec [(match_operand 1 "register_operand" "") | |
2590 | (label_ref (match_operand 2 "" ""))] 2)) | |
2591 | (clobber (match_scratch:SI 3 "")) | |
2592 | (clobber (match_scratch:SI 4 ""))] | |
2593 | "TARGET_SH2 && reload_completed" | |
2594 | [(set (reg:SI 0) (unspec [(label_ref (match_dup 2))] 1)) | |
2595 | (parallel [(set (match_dup 0) | |
2596 | (unspec [(reg:SI 0) (match_dup 1) (label_ref (match_dup 2))] 2)) | |
2597 | (clobber (match_dup 3))])] | |
2598 | "LABEL_NUSES (operands[2])++;") | |
2599 | ||
2600 | (define_insn "*casesi_worker" | |
2601 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
2602 | (unspec [(reg:SI 0) (match_operand 1 "register_operand" "0,r") | |
2603 | (label_ref (match_operand 2 "" ""))] 2)) | |
2604 | (clobber (match_scratch:SI 3 "=X,1"))] | |
0d7e008e | 2605 | "" |
4fdd1f85 | 2606 | "* |
ffae286a | 2607 | { |
1245df60 R |
2608 | enum machine_mode mode |
2609 | = optimize | |
2610 | ? GET_MODE (PATTERN (prev_real_insn (operands[2]))) | |
2611 | : sh_addr_diff_vec_mode; | |
2612 | switch (mode) | |
2613 | { | |
2614 | case SImode: | |
2615 | return \"shll2 %1\;mov.l @(r0,%1),%0\"; | |
2616 | case HImode: | |
2617 | return \"add %1,%1\;mov.w @(r0,%1),%0\"; | |
2618 | case QImode: | |
2619 | { | |
2620 | rtx adj = PATTERN (prev_real_insn (operands[2])); | |
2621 | if ((insn_addresses[INSN_UID (XEXP ( XVECEXP (adj, 0, 1), 0))] | |
2622 | - insn_addresses[INSN_UID (XEXP (XVECEXP (adj, 0, 2), 0))]) | |
2623 | <= 126) | |
2624 | return \"mov.b @(r0,%1),%0\"; | |
2625 | return \"mov.b @(r0,%1),%0\;extu.b %0,%0\"; | |
2626 | } | |
2627 | default: | |
2628 | abort (); | |
2629 | } | |
ffae286a | 2630 | }" |
51bd623f | 2631 | [(set_attr "length" "4")]) |
0d7e008e | 2632 | |
1245df60 R |
2633 | ;; Include ADDR_DIFF_VECS in the shorten_branches pass; we have to |
2634 | ;; use a negative-length instruction to actually accomplish this. | |
2635 | (define_insn "addr_diff_vec_adjust" | |
2636 | [(unspec_volatile [(label_ref (match_operand 0 "" "")) | |
2637 | (label_ref (match_operand 1 "" "")) | |
2638 | (label_ref (match_operand 2 "" "")) | |
2639 | (match_operand 3 "const_int_operand" "")] 7)] | |
2640 | "" | |
2641 | "* | |
2642 | { | |
2643 | /* ??? ASM_OUTPUT_ADDR_DIFF_ELT gets passed no context information, so | |
2644 | we must use a kludge with a global variable. */ | |
2645 | sh_addr_diff_vec_mode = GET_MODE (PATTERN (insn)); | |
2646 | return \"\"; | |
2647 | }" | |
2648 | ;; Need a variable length for this to be processed in each shorten_branch pass. | |
956d6950 | 2649 | ;; The actual work is done in ADJUST_INSN_LENGTH, because length attributes |
1245df60 R |
2650 | ;; need to be (a choice of) constants. |
2651 | ;; We use the calculated length before ADJUST_INSN_LENGTH to | |
2652 | ;; determine if the insn_addresses array contents are valid. | |
2653 | [(set (attr "length") | |
2654 | (if_then_else (eq (pc) (const_int -1)) | |
2655 | (const_int 2) (const_int 0)))]) | |
2656 | ||
961c4780 | 2657 | (define_insn "return" |
0d7e008e | 2658 | [(return)] |
961c4780 SC |
2659 | "reload_completed" |
2660 | "%@ %#" | |
51bd623f JW |
2661 | [(set_attr "type" "return") |
2662 | (set_attr "needs_delay_slot" "yes")]) | |
b9654711 SC |
2663 | |
2664 | (define_expand "prologue" | |
2665 | [(const_int 0)] | |
2666 | "" | |
2667 | "sh_expand_prologue (); DONE;") | |
2668 | ||
2669 | (define_expand "epilogue" | |
2670 | [(return)] | |
2671 | "" | |
2672 | "sh_expand_epilogue ();") | |
2673 | ||
2674 | (define_insn "blockage" | |
2675 | [(unspec_volatile [(const_int 0)] 0)] | |
2676 | "" | |
2677 | "" | |
2678 | [(set_attr "length" "0")]) | |
bc45ade3 SC |
2679 | \f |
2680 | ;; ------------------------------------------------------------------------ | |
2681 | ;; Scc instructions | |
2682 | ;; ------------------------------------------------------------------------ | |
2683 | ||
0d7e008e | 2684 | (define_insn "movt" |
aa684c94 | 2685 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
961c4780 | 2686 | (eq:SI (reg:SI 18) (const_int 1)))] |
bc45ade3 | 2687 | "" |
1245df60 R |
2688 | "movt %0" |
2689 | [(set_attr "type" "arith")]) | |
bc45ade3 SC |
2690 | |
2691 | (define_expand "seq" | |
aa684c94 | 2692 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
bc45ade3 SC |
2693 | (match_dup 1))] |
2694 | "" | |
2695 | "operands[1] = prepare_scc_operands (EQ);") | |
2696 | ||
2697 | (define_expand "slt" | |
aa684c94 | 2698 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
bc45ade3 SC |
2699 | (match_dup 1))] |
2700 | "" | |
2701 | "operands[1] = prepare_scc_operands (LT);") | |
2702 | ||
2703 | (define_expand "sle" | |
1245df60 | 2704 | [(match_operand:SI 0 "arith_reg_operand" "")] |
bc45ade3 | 2705 | "" |
45348d9e JW |
2706 | " |
2707 | { | |
1245df60 R |
2708 | rtx tmp = sh_compare_op0; |
2709 | sh_compare_op0 = sh_compare_op1; | |
2710 | sh_compare_op1 = tmp; | |
2711 | emit_insn (gen_sge (operands[0])); | |
2712 | DONE; | |
45348d9e | 2713 | }") |
bc45ade3 SC |
2714 | |
2715 | (define_expand "sgt" | |
aa684c94 | 2716 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
bc45ade3 SC |
2717 | (match_dup 1))] |
2718 | "" | |
2719 | "operands[1] = prepare_scc_operands (GT);") | |
2720 | ||
2721 | (define_expand "sge" | |
aa684c94 | 2722 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
bc45ade3 SC |
2723 | (match_dup 1))] |
2724 | "" | |
45348d9e JW |
2725 | " |
2726 | { | |
2727 | if (GET_MODE (sh_compare_op0) == SFmode) | |
2728 | { | |
1245df60 R |
2729 | if (TARGET_IEEE) |
2730 | { | |
2731 | rtx t_reg = gen_rtx (REG, SImode, T_REG); | |
2732 | rtx lab = gen_label_rtx (); | |
2733 | emit_insn (gen_rtx (SET, VOIDmode, t_reg, | |
2734 | gen_rtx (EQ, SImode, sh_compare_op0, | |
2735 | sh_compare_op1))); | |
2736 | emit_jump_insn (gen_branch_true (lab)); | |
2737 | emit_insn (gen_rtx (SET, VOIDmode, t_reg, | |
2738 | gen_rtx (GT, SImode, sh_compare_op0, | |
2739 | sh_compare_op1))); | |
2740 | emit_label (lab); | |
2741 | emit_insn (gen_movt (operands[0])); | |
2742 | } | |
2743 | else | |
2744 | emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT))); | |
45348d9e JW |
2745 | DONE; |
2746 | } | |
2747 | operands[1] = prepare_scc_operands (GE); | |
2748 | }") | |
bc45ade3 SC |
2749 | |
2750 | (define_expand "sgtu" | |
aa684c94 | 2751 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
bc45ade3 SC |
2752 | (match_dup 1))] |
2753 | "" | |
2754 | "operands[1] = prepare_scc_operands (GTU);") | |
2755 | ||
2756 | (define_expand "sltu" | |
aa684c94 | 2757 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
bc45ade3 SC |
2758 | (match_dup 1))] |
2759 | "" | |
2760 | "operands[1] = prepare_scc_operands (LTU);") | |
2761 | ||
2762 | (define_expand "sleu" | |
aa684c94 | 2763 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
bc45ade3 SC |
2764 | (match_dup 1))] |
2765 | "" | |
2766 | "operands[1] = prepare_scc_operands (LEU);") | |
2767 | ||
2768 | (define_expand "sgeu" | |
aa684c94 | 2769 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
bc45ade3 SC |
2770 | (match_dup 1))] |
2771 | "" | |
2772 | "operands[1] = prepare_scc_operands (GEU);") | |
2773 | ||
8bca10f4 JW |
2774 | ;; sne moves the complement of the T reg to DEST like this: |
2775 | ;; cmp/eq ... | |
2776 | ;; mov #-1,temp | |
2777 | ;; negc temp,dest | |
2778 | ;; This is better than xoring compare result with 1 because it does | |
2779 | ;; not require r0 and further, the -1 may be CSE-ed or lifted out of a | |
2780 | ;; loop. | |
2781 | ||
bc45ade3 | 2782 | (define_expand "sne" |
8bca10f4 JW |
2783 | [(set (match_dup 2) (const_int -1)) |
2784 | (parallel [(set (match_operand:SI 0 "arith_reg_operand" "") | |
2785 | (neg:SI (plus:SI (match_dup 1) | |
2786 | (match_dup 2)))) | |
2787 | (set (reg:SI 18) | |
2788 | (ne:SI (ior:SI (match_dup 1) (match_dup 2)) | |
2789 | (const_int 0)))])] | |
2790 | "" | |
2791 | " | |
2792 | { | |
2793 | operands[1] = prepare_scc_operands (EQ); | |
2794 | operands[2] = gen_reg_rtx (SImode); | |
2795 | }") | |
2796 | ||
1245df60 R |
2797 | ;; Use the same trick for FP sle / sge |
2798 | (define_expand "movnegt" | |
2799 | [(set (match_dup 2) (const_int -1)) | |
2800 | (parallel [(set (match_operand 0 "" "") | |
2801 | (neg:SI (plus:SI (match_dup 1) | |
2802 | (match_dup 2)))) | |
2803 | (set (reg:SI 18) | |
2804 | (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2)) | |
2805 | (const_int 0)))])] | |
2806 | "" | |
2807 | "operands[2] = gen_reg_rtx (SImode);") | |
2808 | ||
8bca10f4 | 2809 | ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1. |
956d6950 | 2810 | ;; This prevents a regression that occurred when we switched from xor to |
8bca10f4 JW |
2811 | ;; mov/neg for sne. |
2812 | ||
2813 | (define_split | |
aa684c94 | 2814 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
8bca10f4 JW |
2815 | (plus:SI (reg:SI 18) |
2816 | (const_int -1)))] | |
bc45ade3 | 2817 | "" |
8bca10f4 JW |
2818 | [(set (match_dup 0) (eq:SI (reg:SI 18) (const_int 1))) |
2819 | (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] | |
2820 | "") | |
bc45ade3 | 2821 | |
0d7e008e SC |
2822 | ;; ------------------------------------------------------------------------- |
2823 | ;; Instructions to cope with inline literal tables | |
2824 | ;; ------------------------------------------------------------------------- | |
2825 | ||
2826 | ; 2 byte integer in line | |
b9654711 | 2827 | |
0d7e008e SC |
2828 | (define_insn "consttable_2" |
2829 | [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 2)] | |
2830 | "" | |
2831 | "* | |
2832 | { | |
2833 | assemble_integer (operands[0], 2, 1); | |
2834 | return \"\"; | |
2835 | }" | |
2836 | [(set_attr "length" "2") | |
2837 | (set_attr "in_delay_slot" "no")]) | |
2838 | ||
2839 | ; 4 byte integer in line | |
2840 | ||
2841 | (define_insn "consttable_4" | |
2842 | [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 4)] | |
2843 | "" | |
2844 | "* | |
2845 | { | |
2846 | assemble_integer (operands[0], 4, 1); | |
2847 | return \"\"; | |
2848 | }" | |
2849 | [(set_attr "length" "4") | |
2850 | (set_attr "in_delay_slot" "no")]) | |
2851 | ||
2852 | ; 8 byte integer in line | |
2853 | ||
2854 | (define_insn "consttable_8" | |
2855 | [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 6)] | |
2856 | "" | |
2857 | "* | |
2858 | { | |
2859 | assemble_integer (operands[0], 8, 1); | |
2860 | return \"\"; | |
2861 | }" | |
2862 | [(set_attr "length" "8") | |
2863 | (set_attr "in_delay_slot" "no")]) | |
2864 | ||
3e943b59 JR |
2865 | ; 4 byte floating point |
2866 | ||
2867 | (define_insn "consttable_sf" | |
2868 | [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")] 4)] | |
2869 | "" | |
2870 | "* | |
2871 | { | |
2872 | union real_extract u; | |
2873 | bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); | |
2874 | assemble_real (u.d, SFmode); | |
2875 | return \"\"; | |
2876 | }" | |
2877 | [(set_attr "length" "4") | |
2878 | (set_attr "in_delay_slot" "no")]) | |
2879 | ||
2880 | ; 8 byte floating point | |
2881 | ||
2882 | (define_insn "consttable_df" | |
2883 | [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")] 6)] | |
2884 | "" | |
2885 | "* | |
2886 | { | |
2887 | union real_extract u; | |
2888 | bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u); | |
2889 | assemble_real (u.d, DFmode); | |
2890 | return \"\"; | |
2891 | }" | |
2892 | [(set_attr "length" "8") | |
2893 | (set_attr "in_delay_slot" "no")]) | |
2894 | ||
1245df60 R |
2895 | ;; Alignment is needed for some constant tables; it may also be added for |
2896 | ;; Instructions at the start of loops, or after unconditional branches. | |
2897 | ;; ??? We would get more accurate lengths if we did instruction | |
2898 | ;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used | |
2899 | ;; here is too conservative. | |
2900 | ||
0d7e008e SC |
2901 | ; align to a two byte boundary |
2902 | ||
2903 | (define_insn "align_2" | |
1245df60 | 2904 | [(unspec_volatile [(const_int 1)] 1)] |
0d7e008e SC |
2905 | "" |
2906 | ".align 1" | |
2907 | [(set_attr "length" "0") | |
2908 | (set_attr "in_delay_slot" "no")]) | |
2909 | ||
2910 | ; align to a four byte boundary | |
1245df60 R |
2911 | ;; align_4 and align_log are instructions for the starts of loops, or |
2912 | ;; after unconditional branches, which may take up extra room. | |
2913 | ||
2914 | (define_expand "align_4" | |
2915 | [(unspec_volatile [(const_int 2)] 1)] | |
2916 | "" | |
2917 | "") | |
2918 | ||
2919 | ; align to a cache line boundary | |
0d7e008e | 2920 | |
1245df60 R |
2921 | (define_insn "align_log" |
2922 | [(unspec_volatile [(match_operand 0 "const_int_operand" "")] 1)] | |
0d7e008e | 2923 | "" |
1245df60 R |
2924 | ".align %O0" |
2925 | ;; Need a variable length for this to be processed in each shorten_branch pass. | |
956d6950 | 2926 | ;; The actual work is done in ADJUST_INSN_LENGTH, because length attributes |
1245df60 R |
2927 | ;; need to be (a choice of) constants. |
2928 | [(set (attr "length") | |
2929 | (if_then_else (ne (pc) (pc)) (const_int 2) (const_int 0))) | |
2930 | (set_attr "in_delay_slot" "no")]) | |
0d7e008e SC |
2931 | |
2932 | ; emitted at the end of the literal table, used to emit the | |
2933 | ; 32bit branch labels if needed. | |
2934 | ||
2935 | (define_insn "consttable_end" | |
2936 | [(unspec_volatile [(const_int 0)] 11)] | |
2937 | "" | |
2938 | "* return output_jump_label_table ();" | |
2939 | [(set_attr "in_delay_slot" "no")]) | |
2940 | ||
0d7e008e SC |
2941 | ;; ------------------------------------------------------------------------- |
2942 | ;; Misc | |
2943 | ;; ------------------------------------------------------------------------- | |
2944 | ||
07a45e5c | 2945 | ;; String/block move insn. |
0d7e008e SC |
2946 | |
2947 | (define_expand "movstrsi" | |
2948 | [(parallel [(set (mem:BLK (match_operand:BLK 0 "" "")) | |
2949 | (mem:BLK (match_operand:BLK 1 "" ""))) | |
2950 | (use (match_operand:SI 2 "nonmemory_operand" "")) | |
2951 | (use (match_operand:SI 3 "immediate_operand" "")) | |
2952 | (clobber (reg:SI 17)) | |
2953 | (clobber (reg:SI 4)) | |
2954 | (clobber (reg:SI 5)) | |
2955 | (clobber (reg:SI 0))])] | |
2956 | "" | |
2957 | " | |
2958 | { | |
2959 | if(expand_block_move (operands)) | |
2960 | DONE; | |
2961 | else FAIL; | |
2962 | }") | |
2963 | ||
2964 | (define_insn "block_move_real" | |
2965 | [(parallel [(set (mem:BLK (reg:SI 4)) | |
2966 | (mem:BLK (reg:SI 5))) | |
2967 | (use (match_operand:SI 0 "arith_reg_operand" "r")) | |
2968 | (clobber (reg:SI 17)) | |
0d7e008e SC |
2969 | (clobber (reg:SI 0))])] |
2970 | "" | |
2971 | "jsr @%0%#" | |
22e1ebf1 | 2972 | [(set_attr "type" "sfunc") |
0d7e008e SC |
2973 | (set_attr "needs_delay_slot" "yes")]) |
2974 | ||
2975 | (define_insn "block_lump_real" | |
2976 | [(parallel [(set (mem:BLK (reg:SI 4)) | |
2977 | (mem:BLK (reg:SI 5))) | |
2978 | (use (match_operand:SI 0 "arith_reg_operand" "r")) | |
2979 | (use (reg:SI 6)) | |
2980 | (clobber (reg:SI 17)) | |
2981 | (clobber (reg:SI 4)) | |
2982 | (clobber (reg:SI 5)) | |
2983 | (clobber (reg:SI 6)) | |
2984 | (clobber (reg:SI 0))])] | |
2985 | "" | |
2986 | "jsr @%0%#" | |
22e1ebf1 | 2987 | [(set_attr "type" "sfunc") |
0d7e008e | 2988 | (set_attr "needs_delay_slot" "yes")]) |
45348d9e JW |
2989 | \f |
2990 | ;; ------------------------------------------------------------------------- | |
2991 | ;; Floating point instructions. | |
2992 | ;; ------------------------------------------------------------------------- | |
2993 | ||
2994 | ;; ??? All patterns should have a type attribute. | |
2995 | ||
2996 | (define_insn "addsf3" | |
2997 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") | |
2998 | (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0") | |
2999 | (match_operand:SF 2 "arith_reg_operand" "f")))] | |
3000 | "TARGET_SH3E" | |
c1aef54d ILT |
3001 | "fadd %2,%0" |
3002 | [(set_attr "type" "fp")]) | |
45348d9e JW |
3003 | |
3004 | (define_insn "subsf3" | |
3005 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") | |
3006 | (minus:SF (match_operand:SF 1 "arith_reg_operand" "0") | |
1245df60 | 3007 | (match_operand:SF 2 "arith_reg_operand" "f")))] |
45348d9e | 3008 | "TARGET_SH3E" |
c1aef54d ILT |
3009 | "fsub %2,%0" |
3010 | [(set_attr "type" "fp")]) | |
45348d9e JW |
3011 | |
3012 | (define_insn "mulsf3" | |
3013 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") | |
3014 | (mult:SF (match_operand:SF 1 "arith_reg_operand" "%0") | |
3015 | (match_operand:SF 2 "arith_reg_operand" "f")))] | |
3016 | "TARGET_SH3E" | |
c1aef54d ILT |
3017 | "fmul %2,%0" |
3018 | [(set_attr "type" "fp")]) | |
45348d9e JW |
3019 | |
3020 | (define_insn "*macsf3" | |
3021 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") | |
3022 | (plus:SF (mult:SF (match_operand:SF 1 "arith_reg_operand" "%w") | |
3023 | (match_operand:SF 2 "arith_reg_operand" "f")) | |
3024 | (match_operand:SF 3 "arith_reg_operand" "0")))] | |
3025 | "TARGET_SH3E" | |
c1aef54d ILT |
3026 | "fmac fr0,%2,%0" |
3027 | [(set_attr "type" "fp")]) | |
45348d9e JW |
3028 | |
3029 | (define_insn "divsf3" | |
3030 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") | |
3031 | (div:SF (match_operand:SF 1 "arith_reg_operand" "0") | |
1245df60 | 3032 | (match_operand:SF 2 "arith_reg_operand" "f")))] |
45348d9e | 3033 | "TARGET_SH3E" |
c1aef54d ILT |
3034 | "fdiv %2,%0" |
3035 | [(set_attr "type" "fdiv")]) | |
45348d9e | 3036 | |
1245df60 R |
3037 | (define_expand "floatsisf2" |
3038 | [(set (reg:SI 22) | |
3039 | (match_operand:SI 1 "arith_reg_operand" "")) | |
3040 | (set (match_operand:SF 0 "arith_reg_operand" "") | |
3041 | (float:SF (reg:SI 22)))] | |
3042 | "TARGET_SH3E" | |
3043 | "") | |
45348d9e | 3044 | |
1245df60 | 3045 | (define_insn "*floatsisf2_ie" |
45348d9e | 3046 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") |
1245df60 | 3047 | (float:SF (reg:SI 22)))] |
45348d9e | 3048 | "TARGET_SH3E" |
1245df60 R |
3049 | "float fpul,%0" |
3050 | [(set_attr "type" "fp")]) | |
45348d9e | 3051 | |
1245df60 R |
3052 | (define_expand "fix_truncsfsi2" |
3053 | [(set (reg:SI 22) | |
3054 | (fix:SI (match_operand:SF 1 "arith_reg_operand" "f"))) | |
3055 | (set (match_operand:SI 0 "arith_reg_operand" "=r") | |
3056 | (reg:SI 22))] | |
3057 | "TARGET_SH3E" | |
3058 | "") | |
45348d9e | 3059 | |
1245df60 R |
3060 | (define_insn "*fixsfsi" |
3061 | [(set (reg:SI 22) | |
3062 | (fix:SI (match_operand:SF 0 "arith_reg_operand" "f")))] | |
45348d9e | 3063 | "TARGET_SH3E" |
1245df60 R |
3064 | "ftrc %0,fpul" |
3065 | [(set_attr "type" "fp")]) | |
45348d9e | 3066 | |
1245df60 | 3067 | (define_insn "cmpgtsf_t" |
45348d9e JW |
3068 | [(set (reg:SI 18) (gt:SI (match_operand:SF 0 "arith_reg_operand" "f") |
3069 | (match_operand:SF 1 "arith_reg_operand" "f")))] | |
3070 | "TARGET_SH3E" | |
c1aef54d ILT |
3071 | "fcmp/gt %1,%0" |
3072 | [(set_attr "type" "fp")]) | |
45348d9e | 3073 | |
1245df60 | 3074 | (define_insn "cmpeqsf_t" |
45348d9e JW |
3075 | [(set (reg:SI 18) (eq:SI (match_operand:SF 0 "arith_reg_operand" "f") |
3076 | (match_operand:SF 1 "arith_reg_operand" "f")))] | |
3077 | "TARGET_SH3E" | |
c1aef54d ILT |
3078 | "fcmp/eq %1,%0" |
3079 | [(set_attr "type" "fp")]) | |
45348d9e | 3080 | |
1245df60 R |
3081 | (define_insn "ieee_ccmpeqsf_t" |
3082 | [(set (reg:SI 18) (ior:SI (reg:SI 18) | |
3083 | (eq:SI (match_operand:SF 0 "arith_reg_operand" "f") | |
3084 | (match_operand:SF 1 "arith_reg_operand" "f"))))] | |
3085 | "TARGET_SH3E && TARGET_IEEE" | |
3086 | "* return output_ieee_ccmpeq (insn, operands);" | |
3087 | [(set_attr "length" "4")]) | |
3088 | ||
3089 | ||
45348d9e JW |
3090 | (define_expand "cmpsf" |
3091 | [(set (reg:SI 18) (compare (match_operand:SF 0 "arith_operand" "") | |
3092 | (match_operand:SF 1 "arith_operand" "")))] | |
3093 | "TARGET_SH3E" | |
3094 | " | |
3095 | { | |
3096 | sh_compare_op0 = operands[0]; | |
3097 | sh_compare_op1 = operands[1]; | |
3098 | DONE; | |
3099 | }") | |
b9654711 | 3100 | |
45348d9e JW |
3101 | (define_insn "negsf2" |
3102 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") | |
3103 | (neg:SF (match_operand:SF 1 "arith_reg_operand" "0")))] | |
3104 | "TARGET_SH3E" | |
c1aef54d ILT |
3105 | "fneg %0" |
3106 | [(set_attr "type" "fp")]) | |
45348d9e JW |
3107 | |
3108 | (define_insn "sqrtsf2" | |
3109 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") | |
3110 | (sqrt:DF (match_operand:SF 1 "arith_reg_operand" "0")))] | |
3111 | "TARGET_SH3E" | |
c1aef54d ILT |
3112 | "fsqrt %0" |
3113 | [(set_attr "type" "fdiv")]) | |
45348d9e JW |
3114 | |
3115 | (define_insn "abssf2" | |
3116 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") | |
3117 | (abs:SF (match_operand:SF 1 "arith_reg_operand" "0")))] | |
3118 | "TARGET_SH3E" | |
c1aef54d ILT |
3119 | "fabs %0" |
3120 | [(set_attr "type" "fp")]) | |
45348d9e | 3121 | \f |
725de644 JW |
3122 | ;; Bit field extract patterns. These give better code for packed bitfields, |
3123 | ;; because they allow auto-increment addresses to be generated. | |
3124 | ||
3125 | (define_expand "insv" | |
3126 | [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "") | |
3127 | (match_operand:SI 1 "immediate_operand" "") | |
3128 | (match_operand:SI 2 "immediate_operand" "")) | |
3129 | (match_operand:SI 3 "general_operand" ""))] | |
3130 | "! TARGET_LITTLE_ENDIAN" | |
3131 | " | |
3132 | { | |
3133 | rtx addr_target, orig_address, shift_reg; | |
3134 | HOST_WIDE_INT size; | |
3135 | ||
3136 | /* ??? expmed doesn't care for non-register predicates. */ | |
3137 | if (! memory_operand (operands[0], VOIDmode) | |
3138 | || ! immediate_operand (operands[1], VOIDmode) | |
3139 | || ! immediate_operand (operands[2], VOIDmode) | |
3140 | || ! general_operand (operands[3], VOIDmode)) | |
3141 | FAIL; | |
3142 | /* If this isn't a 16 / 24 / 32 bit field, or if | |
3143 | it doesn't start on a byte boundary, then fail. */ | |
3144 | size = INTVAL (operands[1]); | |
3145 | if (size < 16 || size > 32 || size % 8 != 0 | |
3146 | || (INTVAL (operands[2]) % 8) != 0) | |
3147 | FAIL; | |
3148 | ||
3149 | size /= 8; | |
3150 | orig_address = XEXP (operands[0], 0); | |
3151 | addr_target = gen_reg_rtx (SImode); | |
3152 | shift_reg = gen_reg_rtx (SImode); | |
3153 | emit_insn (gen_movsi (shift_reg, operands[3])); | |
3154 | emit_insn (gen_addsi3 (addr_target, orig_address, GEN_INT (size - 1))); | |
3155 | ||
3156 | operands[0] = change_address (operands[0], QImode, addr_target); | |
3157 | emit_insn (gen_movqi (operands[0], gen_rtx (SUBREG, QImode, shift_reg, 0))); | |
3158 | ||
3159 | while (size -= 1) | |
3160 | { | |
3161 | emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8))); | |
3162 | emit_insn (gen_addsi3 (addr_target, addr_target, GEN_INT (-1))); | |
3163 | emit_insn (gen_movqi (operands[0], | |
3164 | gen_rtx (SUBREG, QImode, shift_reg, 0))); | |
3165 | } | |
3166 | ||
3167 | DONE; | |
3168 | }") | |
3169 | \f | |
51bd623f JW |
3170 | ;; ------------------------------------------------------------------------- |
3171 | ;; Peepholes | |
3172 | ;; ------------------------------------------------------------------------- | |
961c4780 | 3173 | |
51bd623f JW |
3174 | ;; This matches cases where a stack pointer increment at the start of the |
3175 | ;; epilogue combines with a stack slot read loading the return value. | |
aa684c94 | 3176 | |
07a45e5c | 3177 | (define_peephole |
51bd623f JW |
3178 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
3179 | (mem:SI (match_operand:SI 1 "arith_reg_operand" ""))) | |
3180 | (set (match_dup 1) (plus:SI (match_dup 1) (const_int 4)))] | |
3181 | "REGNO (operands[1]) != REGNO (operands[0])" | |
3182 | "mov.l @%1+,%0") | |
00f8ff66 | 3183 | |
51bd623f | 3184 | ;; See the comment on the dt combiner pattern above. |
00f8ff66 | 3185 | |
07a45e5c JW |
3186 | (define_peephole |
3187 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") | |
00f8ff66 SC |
3188 | (plus:SI (match_dup 0) |
3189 | (const_int -1))) | |
3190 | (set (reg:SI 18) | |
3191 | (eq:SI (match_dup 0) | |
3192 | (const_int 0)))] | |
3193 | "TARGET_SH2" | |
3194 | "dt %0") | |
e4931540 RK |
3195 | |
3196 | ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn' | |
3197 | ;; to `mov #k,r0; mov.l @(r0,r15),rn'. These sequences are generated by | |
3198 | ;; reload when the constant is too large for a reg+offset address. | |
3199 | ||
3200 | ;; ??? We would get much better code if this was done in reload. This would | |
3201 | ;; require modifying find_reloads_address to recognize that if the constant | |
3202 | ;; is out-of-range for an immediate add, then we get better code by reloading | |
3203 | ;; the constant into a register than by reloading the sum into a register, | |
3204 | ;; since the former is one instruction shorter if the address does not need | |
3205 | ;; to be offsettable. Unfortunately this does not work, because there is | |
3206 | ;; only one register, r0, that can be used as an index register. This register | |
3207 | ;; is also the function return value register. So, if we try to force reload | |
3208 | ;; to use double-reg addresses, then we end up with some instructions that | |
3209 | ;; need to use r0 twice. The only way to fix this is to change the calling | |
3210 | ;; convention so that r0 is not used to return values. | |
3211 | ||
3212 | (define_peephole | |
3213 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3214 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3215 | (set (mem:SI (match_dup 0)) | |
3216 | (match_operand:SI 2 "general_movsrc_operand" ""))] | |
3217 | "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" | |
3218 | "mov.l %2,@(%0,%1)") | |
3219 | ||
3220 | (define_peephole | |
3221 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3222 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3223 | (set (match_operand:SI 2 "general_movdst_operand" "") | |
3224 | (mem:SI (match_dup 0)))] | |
3225 | "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" | |
3226 | "mov.l @(%0,%1),%2") | |
3227 | ||
3228 | (define_peephole | |
3229 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3230 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3231 | (set (mem:HI (match_dup 0)) | |
3232 | (match_operand:HI 2 "general_movsrc_operand" ""))] | |
3233 | "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" | |
3234 | "mov.w %2,@(%0,%1)") | |
3235 | ||
3236 | (define_peephole | |
3237 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3238 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3239 | (set (match_operand:HI 2 "general_movdst_operand" "") | |
3240 | (mem:HI (match_dup 0)))] | |
3241 | "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" | |
3242 | "mov.w @(%0,%1),%2") | |
3243 | ||
3244 | (define_peephole | |
3245 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3246 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3247 | (set (mem:QI (match_dup 0)) | |
3248 | (match_operand:QI 2 "general_movsrc_operand" ""))] | |
3249 | "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" | |
3250 | "mov.b %2,@(%0,%1)") | |
3251 | ||
3252 | (define_peephole | |
3253 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3254 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3255 | (set (match_operand:QI 2 "general_movdst_operand" "") | |
3256 | (mem:QI (match_dup 0)))] | |
3257 | "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)" | |
3258 | "mov.b @(%0,%1),%2") | |
3259 | ||
3260 | (define_peephole | |
3261 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3262 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3263 | (set (mem:SF (match_dup 0)) | |
3264 | (match_operand:SF 2 "general_movsrc_operand" ""))] | |
45348d9e JW |
3265 | "REGNO (operands[0]) == 0 |
3266 | && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16) | |
3267 | || (GET_CODE (operands[2]) == SUBREG | |
3268 | && REGNO (SUBREG_REG (operands[2])) < 16)) | |
3269 | && reg_unused_after (operands[0], insn)" | |
e4931540 RK |
3270 | "mov.l %2,@(%0,%1)") |
3271 | ||
3272 | (define_peephole | |
3273 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3274 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3275 | (set (match_operand:SF 2 "general_movdst_operand" "") | |
3276 | ||
3277 | (mem:SF (match_dup 0)))] | |
45348d9e JW |
3278 | "REGNO (operands[0]) == 0 |
3279 | && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16) | |
3280 | || (GET_CODE (operands[2]) == SUBREG | |
3281 | && REGNO (SUBREG_REG (operands[2])) < 16)) | |
3282 | && reg_unused_after (operands[0], insn)" | |
e4931540 | 3283 | "mov.l @(%0,%1),%2") |
45348d9e JW |
3284 | |
3285 | (define_peephole | |
3286 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3287 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3288 | (set (mem:SF (match_dup 0)) | |
3289 | (match_operand:SF 2 "general_movsrc_operand" ""))] | |
3290 | "REGNO (operands[0]) == 0 | |
3291 | && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) >= FIRST_FP_REG) | |
3292 | || (GET_CODE (operands[2]) == SUBREG | |
3293 | && REGNO (SUBREG_REG (operands[2])) >= FIRST_FP_REG)) | |
3294 | && reg_unused_after (operands[0], insn)" | |
1245df60 | 3295 | "fmov{.s|} %2,@(%0,%1)") |
45348d9e JW |
3296 | |
3297 | (define_peephole | |
3298 | [(set (match_operand:SI 0 "register_operand" "=r") | |
3299 | (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r"))) | |
3300 | (set (match_operand:SF 2 "general_movdst_operand" "") | |
3301 | ||
3302 | (mem:SF (match_dup 0)))] | |
3303 | "REGNO (operands[0]) == 0 | |
3304 | && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) >= FIRST_FP_REG) | |
3305 | || (GET_CODE (operands[2]) == SUBREG | |
3306 | && REGNO (SUBREG_REG (operands[2])) >= FIRST_FP_REG)) | |
3307 | && reg_unused_after (operands[0], insn)" | |
1245df60 | 3308 | "fmov{.s|} @(%0,%1),%2") |
4408efce JL |
3309 | |
3310 | ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). */ | |
3311 | (define_insn "sp_switch_1" | |
3312 | [(const_int 1)] | |
3313 | "" | |
3314 | "* | |
3315 | { | |
3316 | rtx xoperands[1]; | |
3317 | ||
3318 | xoperands[0] = sp_switch; | |
3319 | output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", xoperands); | |
3320 | output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", xoperands); | |
3321 | return \"mov r0,r15\"; | |
3322 | }" | |
3323 | [(set_attr "length" "10")]) | |
4408efce | 3324 | |
956d6950 | 3325 | ;; Switch back to the original stack for interrupt functions with the |
4408efce JL |
3326 | ;; sp_switch attribute. */ |
3327 | (define_insn "sp_switch_2" | |
3328 | [(const_int 2)] | |
3329 | "" | |
3330 | "mov.l @r15+,r15\;mov.l @r15+,r0" | |
3331 | [(set_attr "length" "4")]) |