1 | ;;- Machine description for the Hitachi SH. |
---|
2 | ;; Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. |
---|
3 | ;; Contributed by Steve Chamberlain (sac@cygnus.com). |
---|
4 | ;; Improved by Jim Wilson (wilson@cygnus.com). |
---|
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 |
---|
20 | ;; the Free Software Foundation, 59 Temple Place - Suite 330, |
---|
21 | ;; Boston, MA 02111-1307, USA. |
---|
22 | |
---|
23 | |
---|
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 | |
---|
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 | |
---|
32 | ;; ??? The MAC.W and MAC.L instructions are not supported. There is no |
---|
33 | ;; way to generate them. |
---|
34 | |
---|
35 | ;; ??? The cmp/str instruction is not supported. Perhaps it can be used |
---|
36 | ;; for a str* inline function. |
---|
37 | |
---|
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 | |
---|
42 | ;; Special constraints for SH machine description: |
---|
43 | ;; |
---|
44 | ;; t -- T |
---|
45 | ;; x -- mac |
---|
46 | ;; l -- pr |
---|
47 | ;; z -- r0 |
---|
48 | ;; |
---|
49 | ;; Special formats used for outputting SH instructions: |
---|
50 | ;; |
---|
51 | ;; %. -- print a .s if insn needs delay slot |
---|
52 | ;; %@ -- print rte/rts if is/isn't an interrupt function |
---|
53 | ;; %# -- output a nop if there is nothing to put in the delay slot |
---|
54 | ;; %O -- print a constant without the # |
---|
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 |
---|
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 |
---|
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 |
---|
66 | ;; ------------------------------------------------------------------------- |
---|
67 | ;; Attributes |
---|
68 | ;; ------------------------------------------------------------------------- |
---|
69 | |
---|
70 | ;; Target CPU. |
---|
71 | |
---|
72 | (define_attr "cpu" |
---|
73 | "sh1,sh2,sh3,sh3e" |
---|
74 | (const (symbol_ref "sh_cpu_attr"))) |
---|
75 | |
---|
76 | (define_attr "endian" "big,little" |
---|
77 | (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN") |
---|
78 | (const_string "little") (const_string "big")))) |
---|
79 | |
---|
80 | ;; cbranch conditional branch instructions |
---|
81 | ;; jump unconditional jumps |
---|
82 | ;; arith ordinary arithmetic |
---|
83 | ;; arith3 a compound insn that behaves similarly to a sequence of |
---|
84 | ;; three insns of type arith |
---|
85 | ;; arith3b like above, but might end with a redirected branch |
---|
86 | ;; load from memory |
---|
87 | ;; load_si Likewise, SImode variant for general register. |
---|
88 | ;; store to memory |
---|
89 | ;; move register to register |
---|
90 | ;; fmove register to register, floating point |
---|
91 | ;; smpy word precision integer multiply |
---|
92 | ;; dmpy longword or doublelongword precision integer multiply |
---|
93 | ;; return rts |
---|
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 |
---|
96 | ;; pcload pc relative load of constant value |
---|
97 | ;; pcload_si Likewise, SImode variant for general register. |
---|
98 | ;; rte return from exception |
---|
99 | ;; sfunc special function call with known used registers |
---|
100 | ;; call function call |
---|
101 | ;; fp floating point |
---|
102 | ;; fdiv floating point divide (or square root) |
---|
103 | ;; gp_fpul move between general purpose register and fpul |
---|
104 | ;; nil no-op move, will be deleted. |
---|
105 | |
---|
106 | (define_attr "type" |
---|
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" |
---|
108 | (const_string "other")) |
---|
109 | |
---|
110 | ; If a conditional branch destination is within -252..258 bytes away |
---|
111 | ; from the instruction it can be 2 bytes long. Something in the |
---|
112 | ; range -4090..4100 bytes can be 6 bytes long. All other conditional |
---|
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. |
---|
116 | |
---|
117 | ; An unconditional jump in the range -4092..4098 can be 2 bytes long. |
---|
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. |
---|
123 | |
---|
124 | ; All other instructions are two bytes long by default. |
---|
125 | |
---|
126 | (define_attr "length" "" |
---|
127 | (cond [(eq_attr "type" "cbranch") |
---|
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)) |
---|
137 | (eq_attr "type" "jump") |
---|
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)) |
---|
153 | ] (const_int 2))) |
---|
154 | |
---|
155 | ;; (define_function_unit {name} {num-units} {n-users} {test} |
---|
156 | ;; {ready-delay} {issue-delay} [{conflict-list}]) |
---|
157 | |
---|
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. |
---|
163 | |
---|
164 | ;; Loads have a latency of two. |
---|
165 | ;; However, call insn can have ;; a delay slot, so that we want one more |
---|
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. |
---|
172 | ;; We only do this for SImode loads of general registers, to make the work |
---|
173 | ;; for ADJUST_COST easier. |
---|
174 | (define_function_unit "memory" 1 0 |
---|
175 | (eq_attr "type" "load_si,pcload_si") |
---|
176 | 3 2) |
---|
177 | (define_function_unit "memory" 1 0 |
---|
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) |
---|
189 | |
---|
190 | ;; ??? These are approximations. |
---|
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) |
---|
193 | |
---|
194 | (define_function_unit "fp" 1 0 (eq_attr "type" "fp,fmove") 2 1) |
---|
195 | (define_function_unit "fp" 1 0 (eq_attr "type" "fdiv") 13 12) |
---|
196 | |
---|
197 | |
---|
198 | ; Definitions for filling branch delay slots. |
---|
199 | |
---|
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 | |
---|
207 | (define_attr "in_delay_slot" "yes,no" |
---|
208 | (cond [(eq_attr "type" "cbranch") (const_string "no") |
---|
209 | (eq_attr "type" "pcload,pcload_si") (const_string "no") |
---|
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 |
---|
215 | (eq_attr "needs_delay_slot" "yes") |
---|
216 | [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) |
---|
217 | |
---|
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. |
---|
220 | ;; ??? On the SH3, the rte instruction does not use the stack, so a pop |
---|
221 | ;; instruction can go in the delay slot. |
---|
222 | |
---|
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 | |
---|
226 | (define_delay |
---|
227 | (eq_attr "type" "return") |
---|
228 | [(and (eq_attr "in_delay_slot" "yes") |
---|
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 | |
---|
245 | (define_delay |
---|
246 | (and (eq_attr "type" "cbranch") |
---|
247 | (ne (symbol_ref "TARGET_SH2") (const_int 0))) |
---|
248 | [(eq_attr "in_delay_slot" "yes") (eq_attr "in_delay_slot" "yes") (nil)]) |
---|
249 | |
---|
250 | ;; ------------------------------------------------------------------------- |
---|
251 | ;; SImode signed integer comparisons |
---|
252 | ;; ------------------------------------------------------------------------- |
---|
253 | |
---|
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") |
---|
261 | |
---|
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. |
---|
265 | ;; Probably should use r0 for mem/imm compares, but force constant into a |
---|
266 | ;; register for pseudo/imm compares. |
---|
267 | |
---|
268 | (define_insn "cmpeqsi_t" |
---|
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")))] |
---|
271 | "" |
---|
272 | "@ |
---|
273 | tst %0,%0 |
---|
274 | cmp/eq %1,%0 |
---|
275 | cmp/eq %1,%0") |
---|
276 | |
---|
277 | (define_insn "cmpgtsi_t" |
---|
278 | [(set (reg:SI 18) (gt:SI (match_operand:SI 0 "arith_reg_operand" "r,r") |
---|
279 | (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] |
---|
280 | "" |
---|
281 | "@ |
---|
282 | cmp/gt %1,%0 |
---|
283 | cmp/pl %0") |
---|
284 | |
---|
285 | (define_insn "cmpgesi_t" |
---|
286 | [(set (reg:SI 18) (ge:SI (match_operand:SI 0 "arith_reg_operand" "r,r") |
---|
287 | (match_operand:SI 1 "arith_reg_or_0_operand" "r,N")))] |
---|
288 | "" |
---|
289 | "@ |
---|
290 | cmp/ge %1,%0 |
---|
291 | cmp/pz %0") |
---|
292 | |
---|
293 | ;; ------------------------------------------------------------------------- |
---|
294 | ;; SImode unsigned integer comparisons |
---|
295 | ;; ------------------------------------------------------------------------- |
---|
296 | |
---|
297 | (define_insn "cmpgeusi_t" |
---|
298 | [(set (reg:SI 18) (geu:SI (match_operand:SI 0 "arith_reg_operand" "r") |
---|
299 | (match_operand:SI 1 "arith_reg_operand" "r")))] |
---|
300 | "" |
---|
301 | "cmp/hs %1,%0") |
---|
302 | |
---|
303 | (define_insn "cmpgtusi_t" |
---|
304 | [(set (reg:SI 18) (gtu:SI (match_operand:SI 0 "arith_reg_operand" "r") |
---|
305 | (match_operand:SI 1 "arith_reg_operand" "r")))] |
---|
306 | "" |
---|
307 | "cmp/hi %1,%0") |
---|
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" |
---|
313 | [(set (reg:SI 18) (compare (match_operand:SI 0 "arith_operand" "") |
---|
314 | (match_operand:SI 1 "arith_operand" "")))] |
---|
315 | "" |
---|
316 | " |
---|
317 | { |
---|
318 | sh_compare_op0 = operands[0]; |
---|
319 | sh_compare_op1 = operands[1]; |
---|
320 | DONE; |
---|
321 | }") |
---|
322 | |
---|
323 | ;; ------------------------------------------------------------------------- |
---|
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 | |
---|
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 | |
---|
410 | ;; ------------------------------------------------------------------------- |
---|
411 | ;; Addition instructions |
---|
412 | ;; ------------------------------------------------------------------------- |
---|
413 | |
---|
414 | ;; ??? This should be a define expand. |
---|
415 | |
---|
416 | (define_insn "adddi3" |
---|
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"))) |
---|
420 | (clobber (reg:SI 18))] |
---|
421 | "" |
---|
422 | "#" |
---|
423 | [(set_attr "length" "6")]) |
---|
424 | |
---|
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 | |
---|
466 | (define_insn "addsi3" |
---|
467 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
468 | (plus:SI (match_operand:SI 1 "arith_operand" "%0") |
---|
469 | (match_operand:SI 2 "arith_operand" "rI")))] |
---|
470 | "" |
---|
471 | "add %2,%0" |
---|
472 | [(set_attr "type" "arith")]) |
---|
473 | |
---|
474 | ;; ------------------------------------------------------------------------- |
---|
475 | ;; Subtraction instructions |
---|
476 | ;; ------------------------------------------------------------------------- |
---|
477 | |
---|
478 | ;; ??? This should be a define expand. |
---|
479 | |
---|
480 | (define_insn "subdi3" |
---|
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"))) |
---|
484 | (clobber (reg:SI 18))] |
---|
485 | "" |
---|
486 | "#" |
---|
487 | [(set_attr "length" "6")]) |
---|
488 | |
---|
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 | |
---|
530 | (define_insn "*subsi3_internal" |
---|
531 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
532 | (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") |
---|
533 | (match_operand:SI 2 "arith_reg_operand" "r")))] |
---|
534 | "" |
---|
535 | "sub %2,%0" |
---|
536 | [(set_attr "type" "arith")]) |
---|
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 | }") |
---|
557 | |
---|
558 | ;; ------------------------------------------------------------------------- |
---|
559 | ;; Division instructions |
---|
560 | ;; ------------------------------------------------------------------------- |
---|
561 | |
---|
562 | ;; We take advantage of the library routines which don't clobber as many |
---|
563 | ;; registers as a normal function call would. |
---|
564 | |
---|
565 | ;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it |
---|
566 | ;; also has an effect on the register that holds the address of the sfunc. |
---|
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 | |
---|
576 | ;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than |
---|
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. |
---|
583 | |
---|
584 | (define_insn "" |
---|
585 | [(set (match_operand:SI 0 "register_operand" "=z") |
---|
586 | (udiv:SI (reg:SI 4) (reg:SI 5))) |
---|
587 | (clobber (reg:SI 18)) |
---|
588 | (clobber (reg:SI 17)) |
---|
589 | (clobber (reg:SI 4)) |
---|
590 | (use (match_operand:SI 1 "arith_reg_operand" "r"))] |
---|
591 | "" |
---|
592 | "jsr @%1%#" |
---|
593 | [(set_attr "type" "sfunc") |
---|
594 | (set_attr "needs_delay_slot" "yes")]) |
---|
595 | |
---|
596 | (define_expand "udivsi3" |
---|
597 | [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) |
---|
598 | (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) |
---|
599 | (set (match_dup 3) (symbol_ref:SI "__udivsi3")) |
---|
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))])] |
---|
607 | "" |
---|
608 | "operands[3] = gen_reg_rtx(SImode);") |
---|
609 | |
---|
610 | (define_insn "" |
---|
611 | [(set (match_operand:SI 0 "register_operand" "=z") |
---|
612 | (div:SI (reg:SI 4) (reg:SI 5))) |
---|
613 | (clobber (reg:SI 18)) |
---|
614 | (clobber (reg:SI 17)) |
---|
615 | (clobber (reg:SI 1)) |
---|
616 | (clobber (reg:SI 2)) |
---|
617 | (clobber (reg:SI 3)) |
---|
618 | (use (match_operand:SI 1 "arith_reg_operand" "r"))] |
---|
619 | "" |
---|
620 | "jsr @%1%#" |
---|
621 | [(set_attr "type" "sfunc") |
---|
622 | (set_attr "needs_delay_slot" "yes")]) |
---|
623 | |
---|
624 | (define_expand "divsi3" |
---|
625 | [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) |
---|
626 | (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) |
---|
627 | (set (match_dup 3) (symbol_ref:SI "__sdivsi3")) |
---|
628 | (parallel [(set (match_operand:SI 0 "register_operand" "") |
---|
629 | (div:SI (reg:SI 4) |
---|
630 | (reg:SI 5))) |
---|
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))])] |
---|
637 | "" |
---|
638 | "operands[3] = gen_reg_rtx(SImode);") |
---|
639 | |
---|
640 | ;; ------------------------------------------------------------------------- |
---|
641 | ;; Multiplication instructions |
---|
642 | ;; ------------------------------------------------------------------------- |
---|
643 | |
---|
644 | (define_insn "" |
---|
645 | [(set (reg:SI 21) |
---|
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"))))] |
---|
648 | "" |
---|
649 | "mulu %1,%0" |
---|
650 | [(set_attr "type" "smpy")]) |
---|
651 | |
---|
652 | (define_insn "" |
---|
653 | [(set (reg:SI 21) |
---|
654 | (mult:SI (sign_extend:SI |
---|
655 | (match_operand:HI 0 "arith_reg_operand" "r")) |
---|
656 | (sign_extend:SI |
---|
657 | (match_operand:HI 1 "arith_reg_operand" "r"))))] |
---|
658 | "" |
---|
659 | "muls %1,%0" |
---|
660 | [(set_attr "type" "smpy")]) |
---|
661 | |
---|
662 | (define_expand "mulhisi3" |
---|
663 | [(set (reg:SI 21) |
---|
664 | (mult:SI (sign_extend:SI |
---|
665 | (match_operand:HI 1 "arith_reg_operand" "")) |
---|
666 | (sign_extend:SI |
---|
667 | (match_operand:HI 2 "arith_reg_operand" "")))) |
---|
668 | (set (match_operand:SI 0 "arith_reg_operand" "") |
---|
669 | (reg:SI 21))] |
---|
670 | "" |
---|
671 | "") |
---|
672 | |
---|
673 | (define_expand "umulhisi3" |
---|
674 | [(set (reg:SI 21) |
---|
675 | (mult:SI (zero_extend:SI |
---|
676 | (match_operand:HI 1 "arith_reg_operand" "")) |
---|
677 | (zero_extend:SI |
---|
678 | (match_operand:HI 2 "arith_reg_operand" "")))) |
---|
679 | (set (match_operand:SI 0 "arith_reg_operand" "") |
---|
680 | (reg:SI 21))] |
---|
681 | "" |
---|
682 | "") |
---|
683 | |
---|
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 "" |
---|
688 | [(set (match_operand:SI 1 "register_operand" "=z") |
---|
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)) |
---|
696 | (use (match_operand:SI 0 "arith_reg_operand" "r"))] |
---|
697 | "" |
---|
698 | "jsr @%0%#" |
---|
699 | [(set_attr "type" "sfunc") |
---|
700 | (set_attr "needs_delay_slot" "yes")]) |
---|
701 | |
---|
702 | (define_expand "mulsi3_call" |
---|
703 | [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) |
---|
704 | (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) |
---|
705 | (set (match_dup 3) (symbol_ref:SI "__mulsi3")) |
---|
706 | (parallel[(set (match_operand:SI 0 "register_operand" "") |
---|
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)) |
---|
715 | (use (match_dup 3))])] |
---|
716 | "" |
---|
717 | "operands[3] = gen_reg_rtx(SImode);") |
---|
718 | |
---|
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" |
---|
725 | [(set_attr "type" "dmpy")]) |
---|
726 | |
---|
727 | (define_expand "mulsi3" |
---|
728 | [(set (reg:SI 21) |
---|
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" "") |
---|
732 | (reg:SI 21))] |
---|
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 | }") |
---|
744 | |
---|
745 | (define_insn "mulsidi3_i" |
---|
746 | [(set (reg:DI 20) |
---|
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"))))] |
---|
749 | "TARGET_SH2" |
---|
750 | "dmuls.l %1,%0" |
---|
751 | [(set_attr "type" "dmpy")]) |
---|
752 | |
---|
753 | (define_expand "mulsidi3" |
---|
754 | [(set (reg:DI 20) |
---|
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" "") |
---|
758 | (reg:DI 20))] |
---|
759 | "TARGET_SH2" |
---|
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); |
---|
768 | |
---|
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" |
---|
779 | [(set (reg:DI 20) |
---|
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"))))] |
---|
782 | "TARGET_SH2" |
---|
783 | "dmulu.l %1,%0" |
---|
784 | [(set_attr "type" "dmpy")]) |
---|
785 | |
---|
786 | (define_expand "umulsidi3" |
---|
787 | [(set (reg:DI 20) |
---|
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" "") |
---|
791 | (reg:DI 20))] |
---|
792 | "TARGET_SH2" |
---|
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 | }") |
---|
810 | |
---|
811 | (define_insn "" |
---|
812 | [(set (reg:SI 20) |
---|
813 | (truncate:SI |
---|
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"))) |
---|
816 | (const_int 32)))) |
---|
817 | (clobber (reg:SI 21))] |
---|
818 | "TARGET_SH2" |
---|
819 | "dmuls.l %1,%0" |
---|
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 |
---|
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"))) |
---|
839 | (const_int 32)))) |
---|
840 | (clobber (reg:SI 21))] |
---|
841 | "TARGET_SH2" |
---|
842 | "dmulu.l %1,%0" |
---|
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" |
---|
855 | "") |
---|
856 | |
---|
857 | ;; ------------------------------------------------------------------------- |
---|
858 | ;; Logical operations |
---|
859 | ;; ------------------------------------------------------------------------- |
---|
860 | |
---|
861 | (define_insn "" |
---|
862 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") |
---|
863 | (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") |
---|
864 | (match_operand:SI 2 "logical_operand" "r,L")))] |
---|
865 | "" |
---|
866 | "and %2,%0" |
---|
867 | [(set_attr "type" "arith")]) |
---|
868 | |
---|
869 | ;; If the constant is 255, then emit a extu.b instruction instead of an |
---|
870 | ;; and, since that will give better code. |
---|
871 | |
---|
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 | "" |
---|
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 | }") |
---|
886 | |
---|
887 | (define_insn "iorsi3" |
---|
888 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") |
---|
889 | (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") |
---|
890 | (match_operand:SI 2 "logical_operand" "r,L")))] |
---|
891 | "" |
---|
892 | "or %2,%0" |
---|
893 | [(set_attr "type" "arith")]) |
---|
894 | |
---|
895 | (define_insn "xorsi3" |
---|
896 | [(set (match_operand:SI 0 "arith_reg_operand" "=z,r") |
---|
897 | (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") |
---|
898 | (match_operand:SI 2 "logical_operand" "L,r")))] |
---|
899 | "" |
---|
900 | "xor %2,%0" |
---|
901 | [(set_attr "type" "arith")]) |
---|
902 | |
---|
903 | ;; ------------------------------------------------------------------------- |
---|
904 | ;; Shifts and rotates |
---|
905 | ;; ------------------------------------------------------------------------- |
---|
906 | |
---|
907 | (define_insn "rotlsi3_1" |
---|
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))) |
---|
911 | (set (reg:SI 18) |
---|
912 | (lshiftrt:SI (match_dup 1) (const_int 31)))] |
---|
913 | "" |
---|
914 | "rotl %0" |
---|
915 | [(set_attr "type" "arith")]) |
---|
916 | |
---|
917 | (define_insn "rotlsi3_31" |
---|
918 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
919 | (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") |
---|
920 | (const_int 31))) |
---|
921 | (clobber (reg:SI 18))] |
---|
922 | "" |
---|
923 | "rotr %0" |
---|
924 | [(set_attr "type" "arith")]) |
---|
925 | |
---|
926 | (define_insn "rotlsi3_16" |
---|
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)))] |
---|
930 | "" |
---|
931 | "swap.w %1,%0" |
---|
932 | [(set_attr "type" "arith")]) |
---|
933 | |
---|
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 | { |
---|
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 | |
---|
950 | if (GET_CODE (operands[2]) != CONST_INT) |
---|
951 | FAIL; |
---|
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) |
---|
958 | { |
---|
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 | } |
---|
980 | } |
---|
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; |
---|
988 | }") |
---|
989 | |
---|
990 | (define_insn "*rotlhi3_8" |
---|
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 | "" |
---|
995 | "swap.b %1,%0" |
---|
996 | [(set_attr "type" "arith")]) |
---|
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 | }") |
---|
1008 | |
---|
1009 | ;; |
---|
1010 | ;; shift left |
---|
1011 | |
---|
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" |
---|
1017 | "shld %2,%0" |
---|
1018 | [(set_attr "type" "dyn_shift")]) |
---|
1019 | |
---|
1020 | (define_insn "ashlsi3_k" |
---|
1021 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") |
---|
1022 | (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0") |
---|
1023 | (match_operand:SI 2 "const_int_operand" "M,K")))] |
---|
1024 | "CONST_OK_FOR_K (INTVAL (operands[2]))" |
---|
1025 | "@ |
---|
1026 | add %0,%0 |
---|
1027 | shll%O2 %0" |
---|
1028 | [(set_attr "type" "arith")]) |
---|
1029 | |
---|
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 |
---|
1037 | shll%O2 %0" |
---|
1038 | [(set_attr "type" "arith")]) |
---|
1039 | |
---|
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") |
---|
1043 | (match_operand:SI 2 "const_int_operand" "n"))) |
---|
1044 | (clobber (reg:SI 18))] |
---|
1045 | "! sh_dynamicalize_shift_p (operands[2])" |
---|
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"))) |
---|
1055 | (set_attr "type" "arith")]) |
---|
1056 | |
---|
1057 | (define_split |
---|
1058 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
1059 | (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") |
---|
1060 | (match_operand:SI 2 "const_int_operand" "n"))) |
---|
1061 | (clobber (reg:SI 18))] |
---|
1062 | "" |
---|
1063 | [(use (reg:SI 0))] |
---|
1064 | " |
---|
1065 | { |
---|
1066 | gen_shifty_op (ASHIFT, operands); |
---|
1067 | DONE; |
---|
1068 | }") |
---|
1069 | |
---|
1070 | (define_expand "ashlsi3" |
---|
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))])] |
---|
1075 | "" |
---|
1076 | " |
---|
1077 | { |
---|
1078 | if (GET_CODE (operands[2]) == CONST_INT |
---|
1079 | && sh_dynamicalize_shift_p (operands[2])) |
---|
1080 | operands[2] = force_reg (SImode, operands[2]); |
---|
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 | } |
---|
1086 | if (! immediate_operand (operands[2], GET_MODE (operands[2]))) |
---|
1087 | FAIL; |
---|
1088 | }") |
---|
1089 | |
---|
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 | |
---|
1118 | ; |
---|
1119 | ; arithmetic shift right |
---|
1120 | ; |
---|
1121 | |
---|
1122 | (define_insn "ashrsi3_k" |
---|
1123 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
1124 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") |
---|
1125 | (match_operand:SI 2 "const_int_operand" "M"))) |
---|
1126 | (clobber (reg:SI 18))] |
---|
1127 | "INTVAL (operands[2]) == 1" |
---|
1128 | "shar %0" |
---|
1129 | [(set_attr "type" "arith")]) |
---|
1130 | |
---|
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 | |
---|
1140 | ;; ??? This should be a define expand. |
---|
1141 | |
---|
1142 | (define_insn "ashrsi2_16" |
---|
1143 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
1144 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") |
---|
1145 | (const_int 16)))] |
---|
1146 | "" |
---|
1147 | "#" |
---|
1148 | [(set_attr "length" "4")]) |
---|
1149 | |
---|
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 | |
---|
1159 | ;; ??? This should be a define expand. |
---|
1160 | |
---|
1161 | (define_insn "ashrsi2_31" |
---|
1162 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
1163 | (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") |
---|
1164 | (const_int 31))) |
---|
1165 | (clobber (reg:SI 18))] |
---|
1166 | "" |
---|
1167 | "#" |
---|
1168 | [(set_attr "length" "4")]) |
---|
1169 | |
---|
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 | |
---|
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" |
---|
1198 | "shad %2,%0" |
---|
1199 | [(set_attr "type" "dyn_shift")]) |
---|
1200 | |
---|
1201 | (define_insn "ashrsi3_n" |
---|
1202 | [(set (reg:SI 4) |
---|
1203 | (ashiftrt:SI (reg:SI 4) |
---|
1204 | (match_operand:SI 0 "const_int_operand" "i"))) |
---|
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") |
---|
1211 | (set_attr "needs_delay_slot" "yes")]) |
---|
1212 | |
---|
1213 | (define_expand "ashrsi3" |
---|
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))])] |
---|
1218 | "" |
---|
1219 | "if (expand_ashiftrt (operands)) DONE; else FAIL;") |
---|
1220 | |
---|
1221 | ;; logical shift right |
---|
1222 | |
---|
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" |
---|
1228 | "shld %2,%0" |
---|
1229 | [(set_attr "type" "dyn_shift")]) |
---|
1230 | |
---|
1231 | ;; Only the single bit shift clobbers the T bit. |
---|
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") |
---|
1236 | (match_operand:SI 2 "const_int_operand" "M"))) |
---|
1237 | (clobber (reg:SI 18))] |
---|
1238 | "CONST_OK_FOR_M (INTVAL (operands[2]))" |
---|
1239 | "shlr %0" |
---|
1240 | [(set_attr "type" "arith")]) |
---|
1241 | |
---|
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") |
---|
1245 | (match_operand:SI 2 "const_int_operand" "K")))] |
---|
1246 | "CONST_OK_FOR_K (INTVAL (operands[2])) |
---|
1247 | && ! CONST_OK_FOR_M (INTVAL (operands[2]))" |
---|
1248 | "shlr%O2 %0" |
---|
1249 | [(set_attr "type" "arith")]) |
---|
1250 | |
---|
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]))" |
---|
1257 | "shlr %0" |
---|
1258 | [(set_attr "type" "arith")]) |
---|
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]))" |
---|
1266 | "shlr%O2 %0" |
---|
1267 | [(set_attr "type" "arith")]) |
---|
1268 | |
---|
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") |
---|
1272 | (match_operand:SI 2 "const_int_operand" "n"))) |
---|
1273 | (clobber (reg:SI 18))] |
---|
1274 | "! sh_dynamicalize_shift_p (operands[2])" |
---|
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"))) |
---|
1284 | (set_attr "type" "arith")]) |
---|
1285 | |
---|
1286 | (define_split |
---|
1287 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
1288 | (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") |
---|
1289 | (match_operand:SI 2 "const_int_operand" "n"))) |
---|
1290 | (clobber (reg:SI 18))] |
---|
1291 | "" |
---|
1292 | [(use (reg:SI 0))] |
---|
1293 | " |
---|
1294 | { |
---|
1295 | gen_shifty_op (LSHIFTRT, operands); |
---|
1296 | DONE; |
---|
1297 | }") |
---|
1298 | |
---|
1299 | (define_expand "lshrsi3" |
---|
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))])] |
---|
1304 | "" |
---|
1305 | " |
---|
1306 | { |
---|
1307 | if (GET_CODE (operands[2]) == CONST_INT |
---|
1308 | && sh_dynamicalize_shift_p (operands[2])) |
---|
1309 | operands[2] = force_reg (SImode, operands[2]); |
---|
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)); |
---|
1314 | emit_insn (gen_lshrsi3_d (operands[0], operands[1], count)); |
---|
1315 | DONE; |
---|
1316 | } |
---|
1317 | if (! immediate_operand (operands[2], GET_MODE (operands[2]))) |
---|
1318 | FAIL; |
---|
1319 | }") |
---|
1320 | |
---|
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 | |
---|
1350 | ;; ??? This should be a define expand. |
---|
1351 | |
---|
1352 | (define_insn "ashldi3_k" |
---|
1353 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") |
---|
1354 | (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") |
---|
1355 | (const_int 1))) |
---|
1356 | (clobber (reg:SI 18))] |
---|
1357 | "" |
---|
1358 | "shll %R0\;rotcl %S0" |
---|
1359 | [(set_attr "length" "4") |
---|
1360 | (set_attr "type" "arith")]) |
---|
1361 | |
---|
1362 | (define_expand "ashldi3" |
---|
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))])] |
---|
1367 | "" |
---|
1368 | "{ if (GET_CODE (operands[2]) != CONST_INT |
---|
1369 | || INTVAL (operands[2]) != 1) FAIL;} ") |
---|
1370 | |
---|
1371 | ;; ??? This should be a define expand. |
---|
1372 | |
---|
1373 | (define_insn "lshrdi3_k" |
---|
1374 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") |
---|
1375 | (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") |
---|
1376 | (const_int 1))) |
---|
1377 | (clobber (reg:SI 18))] |
---|
1378 | "" |
---|
1379 | "shlr %S0\;rotcr %R0" |
---|
1380 | [(set_attr "length" "4") |
---|
1381 | (set_attr "type" "arith")]) |
---|
1382 | |
---|
1383 | (define_expand "lshrdi3" |
---|
1384 | [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") |
---|
1385 | (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") |
---|
1386 | (match_operand:DI 2 "immediate_operand" ""))) |
---|
1387 | (clobber (reg:SI 18))])] |
---|
1388 | "" |
---|
1389 | "{ if (GET_CODE (operands[2]) != CONST_INT |
---|
1390 | || INTVAL (operands[2]) != 1) FAIL;} ") |
---|
1391 | |
---|
1392 | ;; ??? This should be a define expand. |
---|
1393 | |
---|
1394 | (define_insn "ashrdi3_k" |
---|
1395 | [(set (match_operand:DI 0 "arith_reg_operand" "=r") |
---|
1396 | (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") |
---|
1397 | (const_int 1))) |
---|
1398 | (clobber (reg:SI 18))] |
---|
1399 | "" |
---|
1400 | "shar %S0\;rotcr %R0" |
---|
1401 | [(set_attr "length" "4") |
---|
1402 | (set_attr "type" "arith")]) |
---|
1403 | |
---|
1404 | (define_expand "ashrdi3" |
---|
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))])] |
---|
1409 | "" |
---|
1410 | "{ if (GET_CODE (operands[2]) != CONST_INT |
---|
1411 | || INTVAL (operands[2]) != 1) FAIL; } ") |
---|
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)) |
---|
1500 | (const_string "8") |
---|
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 | { |
---|
1518 | rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1]; |
---|
1519 | |
---|
1520 | if (INTVAL (operands[2])) |
---|
1521 | { |
---|
1522 | gen_shifty_op (LSHIFTRT, operands); |
---|
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))] |
---|
1555 | "(unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5" |
---|
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 | |
---|
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 | "" |
---|
1608 | "xtrct %1,%0" |
---|
1609 | [(set_attr "type" "arith")]) |
---|
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 | "" |
---|
1618 | "xtrct %2,%0" |
---|
1619 | [(set_attr "type" "arith")]) |
---|
1620 | |
---|
1621 | ;; ------------------------------------------------------------------------- |
---|
1622 | ;; Unary arithmetic |
---|
1623 | ;; ------------------------------------------------------------------------- |
---|
1624 | |
---|
1625 | (define_insn "negc" |
---|
1626 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
1627 | (neg:SI (plus:SI (reg:SI 18) |
---|
1628 | (match_operand:SI 1 "arith_reg_operand" "r")))) |
---|
1629 | (set (reg:SI 18) |
---|
1630 | (ne:SI (ior:SI (reg:SI 18) (match_dup 1)) |
---|
1631 | (const_int 0)))] |
---|
1632 | "" |
---|
1633 | "negc %1,%0" |
---|
1634 | [(set_attr "type" "arith")]) |
---|
1635 | |
---|
1636 | (define_expand "negdi2" |
---|
1637 | [(set (match_operand:DI 0 "arith_reg_operand" "") |
---|
1638 | (neg:DI (match_operand:DI 1 "arith_reg_operand" ""))) |
---|
1639 | (clobber (reg:SI 18))] |
---|
1640 | "" |
---|
1641 | " |
---|
1642 | { |
---|
1643 | int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1); |
---|
1644 | int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0); |
---|
1645 | |
---|
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); |
---|
1651 | |
---|
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 | }") |
---|
1657 | |
---|
1658 | (define_insn "negsi2" |
---|
1659 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
1660 | (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))] |
---|
1661 | "" |
---|
1662 | "neg %1,%0" |
---|
1663 | [(set_attr "type" "arith")]) |
---|
1664 | |
---|
1665 | (define_insn "one_cmplsi2" |
---|
1666 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
1667 | (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))] |
---|
1668 | "" |
---|
1669 | "not %1,%0" |
---|
1670 | [(set_attr "type" "arith")]) |
---|
1671 | |
---|
1672 | ;; ------------------------------------------------------------------------- |
---|
1673 | ;; Zero extension instructions |
---|
1674 | ;; ------------------------------------------------------------------------- |
---|
1675 | |
---|
1676 | (define_insn "zero_extendhisi2" |
---|
1677 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
1678 | (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))] |
---|
1679 | "" |
---|
1680 | "extu.w %1,%0" |
---|
1681 | [(set_attr "type" "arith")]) |
---|
1682 | |
---|
1683 | (define_insn "zero_extendqisi2" |
---|
1684 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
1685 | (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))] |
---|
1686 | "" |
---|
1687 | "extu.b %1,%0" |
---|
1688 | [(set_attr "type" "arith")]) |
---|
1689 | |
---|
1690 | (define_insn "zero_extendqihi2" |
---|
1691 | [(set (match_operand:HI 0 "arith_reg_operand" "=r") |
---|
1692 | (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] |
---|
1693 | "" |
---|
1694 | "extu.b %1,%0" |
---|
1695 | [(set_attr "type" "arith")]) |
---|
1696 | |
---|
1697 | ;; ------------------------------------------------------------------------- |
---|
1698 | ;; Sign extension instructions |
---|
1699 | ;; ------------------------------------------------------------------------- |
---|
1700 | |
---|
1701 | ;; ??? This should be a define expand. |
---|
1702 | ;; ??? Or perhaps it should be dropped? |
---|
1703 | |
---|
1704 | /* There is no point in defining extendsidi2; convert_move generates good |
---|
1705 | code for that. */ |
---|
1706 | |
---|
1707 | (define_insn "extendhisi2" |
---|
1708 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") |
---|
1709 | (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))] |
---|
1710 | "" |
---|
1711 | "@ |
---|
1712 | exts.w %1,%0 |
---|
1713 | mov.w %1,%0" |
---|
1714 | [(set_attr "type" "arith,load")]) |
---|
1715 | |
---|
1716 | (define_insn "extendqisi2" |
---|
1717 | [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") |
---|
1718 | (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))] |
---|
1719 | "" |
---|
1720 | "@ |
---|
1721 | exts.b %1,%0 |
---|
1722 | mov.b %1,%0" |
---|
1723 | [(set_attr "type" "arith,load")]) |
---|
1724 | |
---|
1725 | (define_insn "extendqihi2" |
---|
1726 | [(set (match_operand:HI 0 "arith_reg_operand" "=r,r") |
---|
1727 | (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))] |
---|
1728 | "" |
---|
1729 | "@ |
---|
1730 | exts.b %1,%0 |
---|
1731 | mov.b %1,%0" |
---|
1732 | [(set_attr "type" "arith,load")]) |
---|
1733 | |
---|
1734 | ;; ------------------------------------------------------------------------- |
---|
1735 | ;; Move instructions |
---|
1736 | ;; ------------------------------------------------------------------------- |
---|
1737 | |
---|
1738 | ;; define push and pop so it is easy for sh.c |
---|
1739 | |
---|
1740 | (define_insn "push" |
---|
1741 | [(set (mem:SI (pre_dec:SI (reg:SI 15))) |
---|
1742 | (match_operand:SI 0 "register_operand" "r,l,x"))] |
---|
1743 | "" |
---|
1744 | "@ |
---|
1745 | mov.l %0,@-r15 |
---|
1746 | sts.l %0,@-r15 |
---|
1747 | sts.l %0,@-r15" |
---|
1748 | [(set_attr "type" "store,pstore,store") |
---|
1749 | (set_attr "hit_stack" "yes")]) |
---|
1750 | |
---|
1751 | (define_insn "pop" |
---|
1752 | [(set (match_operand:SI 0 "register_operand" "=r,l,x") |
---|
1753 | (mem:SI (post_inc:SI (reg:SI 15))))] |
---|
1754 | "" |
---|
1755 | "@ |
---|
1756 | mov.l @r15+,%0 |
---|
1757 | lds.l @r15+,%0 |
---|
1758 | lds.l @r15+,%0" |
---|
1759 | [(set_attr "type" "load,pload,load") |
---|
1760 | (set_attr "hit_stack" "yes")]) |
---|
1761 | |
---|
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"))] |
---|
1765 | "TARGET_SH3E" |
---|
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))))] |
---|
1776 | "TARGET_SH3E" |
---|
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 | |
---|
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. |
---|
1787 | |
---|
1788 | (define_insn "clrt" |
---|
1789 | [(set (reg:SI 18) (const_int 0))] |
---|
1790 | "" |
---|
1791 | "clrt") |
---|
1792 | |
---|
1793 | (define_insn "sett" |
---|
1794 | [(set (reg:SI 18) (const_int 1))] |
---|
1795 | "" |
---|
1796 | "sett") |
---|
1797 | |
---|
1798 | ;; t/r is first, so that it will be preferred over r/r when reloading a move |
---|
1799 | ;; of a pseudo-reg into the T reg |
---|
1800 | (define_insn "movsi_i" |
---|
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"))] |
---|
1803 | " |
---|
1804 | ! TARGET_SH3E |
---|
1805 | && (register_operand (operands[0], SImode) |
---|
1806 | || register_operand (operands[1], SImode))" |
---|
1807 | "@ |
---|
1808 | cmp/pl %1 |
---|
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 |
---|
1816 | sts.l %1,%0 |
---|
1817 | lds %1,%0 |
---|
1818 | lds.l %1,%0 |
---|
1819 | lds.l %1,%0 |
---|
1820 | fake %1,%0" |
---|
1821 | [(set_attr "type" "*,pcload_si,move,load_si,move,move,store,store,pstore,move,load,pload,pcload_si") |
---|
1822 | (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*")]) |
---|
1823 | |
---|
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) |
---|
1826 | ;; ??? This allows moves from macl to fpul to be recognized, but these moves |
---|
1827 | ;; will require a reload. |
---|
1828 | (define_insn "movsi_ie" |
---|
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"))] |
---|
1831 | "TARGET_SH3E |
---|
1832 | && (register_operand (operands[0], SImode) |
---|
1833 | || register_operand (operands[1], SImode))" |
---|
1834 | "@ |
---|
1835 | mov.l %1,%0 |
---|
1836 | mov %1,%0 |
---|
1837 | cmp/pl %1 |
---|
1838 | mov.l %1,%0 |
---|
1839 | sts %1,%0 |
---|
1840 | movt %0 |
---|
1841 | mov.l %1,%0 |
---|
1842 | sts.l %1,%0 |
---|
1843 | sts.l %1,%0 |
---|
1844 | lds %1,%0 |
---|
1845 | lds.l %1,%0 |
---|
1846 | lds.l %1,%0 |
---|
1847 | fake %1,%0 |
---|
1848 | lds %1,%0 |
---|
1849 | sts %1,%0 |
---|
1850 | ! move optimized away" |
---|
1851 | [(set_attr "type" "pcload_si,move,*,load_si,move,move,store,store,pstore,move,load,pload,pcload_si,gp_fpul,gp_fpul,nil") |
---|
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")]) |
---|
1868 | (define_expand "movsi" |
---|
1869 | [(set (match_operand:SI 0 "general_movdst_operand" "") |
---|
1870 | (match_operand:SI 1 "general_movsrc_operand" ""))] |
---|
1871 | "" |
---|
1872 | "{ if (prepare_move_operands (operands, SImode)) DONE; }") |
---|
1873 | |
---|
1874 | (define_insn "movqi_i" |
---|
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) |
---|
1878 | || arith_reg_operand (operands[1], QImode)" |
---|
1879 | "@ |
---|
1880 | mov %1,%0 |
---|
1881 | mov.b %1,%0 |
---|
1882 | mov.b %1,%0 |
---|
1883 | movt %0 |
---|
1884 | sts %1,%0 |
---|
1885 | lds %1,%0" |
---|
1886 | [(set_attr "type" "move,load,store,move,move,move")]) |
---|
1887 | |
---|
1888 | (define_expand "movqi" |
---|
1889 | [(set (match_operand:QI 0 "general_operand" "") |
---|
1890 | (match_operand:QI 1 "general_operand" ""))] |
---|
1891 | "" |
---|
1892 | "{ if (prepare_move_operands (operands, QImode)) DONE; }") |
---|
1893 | |
---|
1894 | (define_insn "movhi_i" |
---|
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"))] |
---|
1897 | "arith_reg_operand (operands[0], HImode) |
---|
1898 | || arith_reg_operand (operands[1], HImode)" |
---|
1899 | "@ |
---|
1900 | mov.w %1,%0 |
---|
1901 | mov %1,%0 |
---|
1902 | mov.w %1,%0 |
---|
1903 | movt %0 |
---|
1904 | mov.w %1,%0 |
---|
1905 | sts %1,%0 |
---|
1906 | lds %1,%0 |
---|
1907 | fake %1,%0" |
---|
1908 | [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")]) |
---|
1909 | |
---|
1910 | (define_expand "movhi" |
---|
1911 | [(set (match_operand:HI 0 "general_movdst_operand" "") |
---|
1912 | (match_operand:HI 1 "general_movsrc_operand" ""))] |
---|
1913 | "" |
---|
1914 | "{ if (prepare_move_operands (operands, HImode)) DONE; }") |
---|
1915 | |
---|
1916 | ;; ??? This should be a define expand. |
---|
1917 | |
---|
1918 | ;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c |
---|
1919 | ;; compiled with -m2 -ml -O3 -funroll-loops |
---|
1920 | (define_insn "" |
---|
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"))] |
---|
1923 | "arith_reg_operand (operands[0], DImode) |
---|
1924 | || arith_reg_operand (operands[1], DImode)" |
---|
1925 | "* return output_movedouble (insn, operands, DImode);" |
---|
1926 | [(set_attr "length" "4") |
---|
1927 | (set_attr "type" "pcload,move,load,store,move,pcload,move,move")]) |
---|
1928 | |
---|
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. |
---|
1931 | |
---|
1932 | (define_split |
---|
1933 | [(set (match_operand:DI 0 "general_movdst_operand" "") |
---|
1934 | (match_operand:DI 1 "general_movsrc_operand" ""))] |
---|
1935 | "reload_completed" |
---|
1936 | [(set (match_dup 2) (match_dup 3)) |
---|
1937 | (set (match_dup 4) (match_dup 5))] |
---|
1938 | " |
---|
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)) |
---|
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 | }") |
---|
1975 | |
---|
1976 | (define_expand "movdi" |
---|
1977 | [(set (match_operand:DI 0 "general_movdst_operand" "") |
---|
1978 | (match_operand:DI 1 "general_movsrc_operand" ""))] |
---|
1979 | "" |
---|
1980 | "{ if ( prepare_move_operands (operands, DImode)) DONE; }") |
---|
1981 | |
---|
1982 | ;; ??? This should be a define expand. |
---|
1983 | |
---|
1984 | (define_insn "movdf_k" |
---|
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"))] |
---|
1987 | "arith_reg_operand (operands[0], DFmode) |
---|
1988 | || arith_reg_operand (operands[1], DFmode)" |
---|
1989 | "* return output_movedouble (insn, operands, DFmode);" |
---|
1990 | [(set_attr "length" "4") |
---|
1991 | (set_attr "type" "move,pcload,load,store")]) |
---|
1992 | |
---|
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. |
---|
1995 | |
---|
1996 | (define_split |
---|
1997 | [(set (match_operand:DF 0 "general_movdst_operand" "") |
---|
1998 | (match_operand:DF 1 "general_movsrc_operand" ""))] |
---|
1999 | "reload_completed" |
---|
2000 | [(set (match_dup 2) (match_dup 3)) |
---|
2001 | (set (match_dup 4) (match_dup 5))] |
---|
2002 | " |
---|
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)) |
---|
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 | |
---|
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 | |
---|
2095 | (define_expand "movdf" |
---|
2096 | [(set (match_operand:DF 0 "general_movdst_operand" "") |
---|
2097 | (match_operand:DF 1 "general_movsrc_operand" ""))] |
---|
2098 | "" |
---|
2099 | " |
---|
2100 | { |
---|
2101 | if (prepare_move_operands (operands, DFmode)) DONE; |
---|
2102 | }") |
---|
2103 | |
---|
2104 | |
---|
2105 | (define_insn "movsf_i" |
---|
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"))] |
---|
2108 | " |
---|
2109 | ! TARGET_SH3E |
---|
2110 | && (arith_reg_operand (operands[0], SFmode) |
---|
2111 | || arith_reg_operand (operands[1], SFmode))" |
---|
2112 | "@ |
---|
2113 | mov %1,%0 |
---|
2114 | mov %1,%0 |
---|
2115 | mov.l %1,%0 |
---|
2116 | mov.l %1,%0 |
---|
2117 | mov.l %1,%0 |
---|
2118 | lds %1,%0 |
---|
2119 | sts %1,%0" |
---|
2120 | [(set_attr "type" "move,move,pcload,load,store,move,move")]) |
---|
2121 | |
---|
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. |
---|
2125 | (define_insn "movsf_ie" |
---|
2126 | [(set (match_operand:SF 0 "general_movdst_operand" |
---|
2127 | "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,y") |
---|
2128 | (match_operand:SF 1 "general_movsrc_operand" |
---|
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"))] |
---|
2131 | |
---|
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 |
---|
2140 | # |
---|
2141 | fmov.s %1,%0 |
---|
2142 | fmov.s %1,%0 |
---|
2143 | mov.l %1,%0 |
---|
2144 | mov.l %1,%0 |
---|
2145 | mov.l %1,%0 |
---|
2146 | fsts fpul,%0 |
---|
2147 | flds %1,fpul |
---|
2148 | lds.l %1,%0 |
---|
2149 | # |
---|
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")]) |
---|
2155 | |
---|
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 | |
---|
2167 | (define_expand "movsf" |
---|
2168 | [(set (match_operand:SF 0 "general_movdst_operand" "") |
---|
2169 | (match_operand:SF 1 "general_movsrc_operand" ""))] |
---|
2170 | "" |
---|
2171 | " |
---|
2172 | { |
---|
2173 | if (prepare_move_operands (operands, SFmode)) |
---|
2174 | DONE; |
---|
2175 | if (TARGET_SH3E) |
---|
2176 | { |
---|
2177 | emit_insn (gen_movsf_ie (operands[0], operands[1])); |
---|
2178 | DONE; |
---|
2179 | } |
---|
2180 | }") |
---|
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 | "") |
---|
2188 | |
---|
2189 | ;; ------------------------------------------------------------------------ |
---|
2190 | ;; Define the real conditional branch instructions. |
---|
2191 | ;; ------------------------------------------------------------------------ |
---|
2192 | |
---|
2193 | (define_insn "branch_true" |
---|
2194 | [(set (pc) (if_then_else (ne (reg:SI 18) (const_int 0)) |
---|
2195 | (label_ref (match_operand 0 "" "")) |
---|
2196 | (pc)))] |
---|
2197 | "" |
---|
2198 | "* return output_branch (1, insn, operands);" |
---|
2199 | [(set_attr "type" "cbranch")]) |
---|
2200 | |
---|
2201 | (define_insn "branch_false" |
---|
2202 | [(set (pc) (if_then_else (eq (reg:SI 18) (const_int 0)) |
---|
2203 | (label_ref (match_operand 0 "" "")) |
---|
2204 | (pc)))] |
---|
2205 | "" |
---|
2206 | "* return output_branch (0, insn, operands);" |
---|
2207 | [(set_attr "type" "cbranch")]) |
---|
2208 | |
---|
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))] |
---|
2215 | "" |
---|
2216 | "" |
---|
2217 | [(set_attr "length" "0")]) |
---|
2218 | |
---|
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))] |
---|
2224 | "" |
---|
2225 | "" |
---|
2226 | [(set_attr "length" "0")]) |
---|
2227 | |
---|
2228 | ;; Conditional branch insns |
---|
2229 | |
---|
2230 | (define_expand "beq" |
---|
2231 | [(set (pc) |
---|
2232 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
---|
2233 | (label_ref (match_operand 0 "" "")) |
---|
2234 | (pc)))] |
---|
2235 | "" |
---|
2236 | "from_compare (operands, EQ);") |
---|
2237 | |
---|
2238 | (define_expand "bne" |
---|
2239 | [(set (pc) |
---|
2240 | (if_then_else (eq (reg:SI 18) (const_int 0)) |
---|
2241 | (label_ref (match_operand 0 "" "")) |
---|
2242 | (pc)))] |
---|
2243 | "" |
---|
2244 | "from_compare (operands, EQ);") |
---|
2245 | |
---|
2246 | (define_expand "bgt" |
---|
2247 | [(set (pc) |
---|
2248 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
---|
2249 | (label_ref (match_operand 0 "" "")) |
---|
2250 | (pc)))] |
---|
2251 | "" |
---|
2252 | "from_compare (operands, GT);") |
---|
2253 | |
---|
2254 | (define_expand "blt" |
---|
2255 | [(set (pc) |
---|
2256 | (if_then_else (eq (reg:SI 18) (const_int 0)) |
---|
2257 | (label_ref (match_operand 0 "" "")) |
---|
2258 | (pc)))] |
---|
2259 | "" |
---|
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 | } |
---|
2270 | from_compare (operands, GE); |
---|
2271 | }") |
---|
2272 | |
---|
2273 | (define_expand "ble" |
---|
2274 | [(set (pc) |
---|
2275 | (if_then_else (eq (reg:SI 18) (const_int 0)) |
---|
2276 | (label_ref (match_operand 0 "" "")) |
---|
2277 | (pc)))] |
---|
2278 | "" |
---|
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 | }") |
---|
2293 | |
---|
2294 | (define_expand "bge" |
---|
2295 | [(set (pc) |
---|
2296 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
---|
2297 | (label_ref (match_operand 0 "" "")) |
---|
2298 | (pc)))] |
---|
2299 | "" |
---|
2300 | " |
---|
2301 | { |
---|
2302 | if (TARGET_SH3E |
---|
2303 | && ! TARGET_IEEE |
---|
2304 | && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT) |
---|
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 | }") |
---|
2314 | |
---|
2315 | (define_expand "bgtu" |
---|
2316 | [(set (pc) |
---|
2317 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
---|
2318 | (label_ref (match_operand 0 "" "")) |
---|
2319 | (pc)))] |
---|
2320 | "" |
---|
2321 | "from_compare (operands, GTU); ") |
---|
2322 | |
---|
2323 | (define_expand "bltu" |
---|
2324 | [(set (pc) |
---|
2325 | (if_then_else (eq (reg:SI 18) (const_int 0)) |
---|
2326 | (label_ref (match_operand 0 "" "")) |
---|
2327 | (pc)))] |
---|
2328 | "" |
---|
2329 | "from_compare (operands, GEU);") |
---|
2330 | |
---|
2331 | (define_expand "bgeu" |
---|
2332 | [(set (pc) |
---|
2333 | (if_then_else (ne (reg:SI 18) (const_int 0)) |
---|
2334 | (label_ref (match_operand 0 "" "")) |
---|
2335 | (pc)))] |
---|
2336 | "" |
---|
2337 | "from_compare (operands, GEU);") |
---|
2338 | |
---|
2339 | (define_expand "bleu" |
---|
2340 | [(set (pc) |
---|
2341 | (if_then_else (eq (reg:SI 18) (const_int 0)) |
---|
2342 | (label_ref (match_operand 0 "" "")) |
---|
2343 | (pc)))] |
---|
2344 | "" |
---|
2345 | "from_compare (operands, GTU);") |
---|
2346 | |
---|
2347 | ;; ------------------------------------------------------------------------ |
---|
2348 | ;; Jump and linkage insns |
---|
2349 | ;; ------------------------------------------------------------------------ |
---|
2350 | |
---|
2351 | (define_insn "jump" |
---|
2352 | [(set (pc) |
---|
2353 | (label_ref (match_operand 0 "" "")))] |
---|
2354 | "" |
---|
2355 | "* |
---|
2356 | { |
---|
2357 | /* The length is 16 if the delay slot is unfilled. */ |
---|
2358 | if (get_attr_length(insn) > 4) |
---|
2359 | return output_far_jump(insn, operands[0]); |
---|
2360 | else |
---|
2361 | return \"bra %l0%#\"; |
---|
2362 | }" |
---|
2363 | [(set_attr "type" "jump") |
---|
2364 | (set_attr "needs_delay_slot" "yes")]) |
---|
2365 | |
---|
2366 | (define_insn "calli" |
---|
2367 | [(call (mem:SI (match_operand:SI 0 "arith_reg_operand" "r")) |
---|
2368 | (match_operand 1 "" "")) |
---|
2369 | (clobber (reg:SI 17))] |
---|
2370 | "" |
---|
2371 | "jsr @%0%#" |
---|
2372 | [(set_attr "type" "call") |
---|
2373 | (set_attr "needs_delay_slot" "yes")]) |
---|
2374 | |
---|
2375 | (define_insn "call_valuei" |
---|
2376 | [(set (match_operand 0 "" "=rf") |
---|
2377 | (call (mem:SI (match_operand:SI 1 "arith_reg_operand" "r")) |
---|
2378 | (match_operand 2 "" ""))) |
---|
2379 | (clobber (reg:SI 17))] |
---|
2380 | "" |
---|
2381 | "jsr @%1%#" |
---|
2382 | [(set_attr "type" "call") |
---|
2383 | (set_attr "needs_delay_slot" "yes")]) |
---|
2384 | |
---|
2385 | (define_expand "call" |
---|
2386 | [(parallel [(call (mem:SI (match_operand 0 "arith_reg_operand" "")) |
---|
2387 | (match_operand 1 "" "")) |
---|
2388 | (clobber (reg:SI 17))])] |
---|
2389 | "" |
---|
2390 | "operands[0] = force_reg (SImode, XEXP (operands[0], 0));") |
---|
2391 | |
---|
2392 | (define_expand "call_value" |
---|
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))])] |
---|
2397 | "" |
---|
2398 | "operands[1] = force_reg (SImode, XEXP (operands[1], 0));") |
---|
2399 | |
---|
2400 | (define_insn "indirect_jump" |
---|
2401 | [(set (pc) |
---|
2402 | (match_operand:SI 0 "arith_reg_operand" "r"))] |
---|
2403 | "" |
---|
2404 | "jmp @%0%#" |
---|
2405 | [(set_attr "needs_delay_slot" "yes") |
---|
2406 | (set_attr "type" "jump_ind")]) |
---|
2407 | |
---|
2408 | ;; The use of operand 1 / 2 helps us distinguish case table jumps |
---|
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 | |
---|
2412 | ;; For SH1 processors. |
---|
2413 | (define_insn "casesi_jump_1" |
---|
2414 | [(set (pc) |
---|
2415 | (match_operand:SI 0 "register_operand" "r")) |
---|
2416 | (use (label_ref (match_operand 1 "" "")))] |
---|
2417 | "" |
---|
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")]) |
---|
2437 | |
---|
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 | }") |
---|
2467 | |
---|
2468 | ;; ------------------------------------------------------------------------ |
---|
2469 | ;; Misc insns |
---|
2470 | ;; ------------------------------------------------------------------------ |
---|
2471 | |
---|
2472 | (define_insn "dect" |
---|
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)))] |
---|
2476 | "TARGET_SH2" |
---|
2477 | "dt %0" |
---|
2478 | [(set_attr "type" "arith")]) |
---|
2479 | |
---|
2480 | (define_insn "nop" |
---|
2481 | [(const_int 0)] |
---|
2482 | "" |
---|
2483 | "nop") |
---|
2484 | |
---|
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, |
---|
2489 | |
---|
2490 | (define_insn "mova" |
---|
2491 | [(set (reg:SI 0) |
---|
2492 | (unspec [(label_ref (match_operand 0 "" ""))] 1))] |
---|
2493 | "" |
---|
2494 | "mova %O0,r0" |
---|
2495 | [(set_attr "in_delay_slot" "no") |
---|
2496 | (set_attr "type" "arith")]) |
---|
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" |
---|
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) |
---|
2548 | (match_operand:SI 1 "arith_operand" ""))) |
---|
2549 | (set (reg:SI 18) |
---|
2550 | (gtu:SI (match_dup 4) |
---|
2551 | (match_operand:SI 2 "arith_reg_operand" ""))) |
---|
2552 | (set (pc) |
---|
2553 | (if_then_else (ne (reg:SI 18) |
---|
2554 | (const_int 0)) |
---|
2555 | (label_ref (match_operand 3 "" "")) |
---|
2556 | (pc)))] |
---|
2557 | "" |
---|
2558 | "") |
---|
2559 | |
---|
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"))] |
---|
2605 | "" |
---|
2606 | "* |
---|
2607 | { |
---|
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 | } |
---|
2630 | }" |
---|
2631 | [(set_attr "length" "4")]) |
---|
2632 | |
---|
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. |
---|
2649 | ;; The actual work is done in ADJUST_INSN_LENGTH, because length attributes |
---|
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 | |
---|
2657 | (define_insn "return" |
---|
2658 | [(return)] |
---|
2659 | "reload_completed" |
---|
2660 | "%@ %#" |
---|
2661 | [(set_attr "type" "return") |
---|
2662 | (set_attr "needs_delay_slot" "yes")]) |
---|
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")]) |
---|
2679 | |
---|
2680 | ;; ------------------------------------------------------------------------ |
---|
2681 | ;; Scc instructions |
---|
2682 | ;; ------------------------------------------------------------------------ |
---|
2683 | |
---|
2684 | (define_insn "movt" |
---|
2685 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
2686 | (eq:SI (reg:SI 18) (const_int 1)))] |
---|
2687 | "" |
---|
2688 | "movt %0" |
---|
2689 | [(set_attr "type" "arith")]) |
---|
2690 | |
---|
2691 | (define_expand "seq" |
---|
2692 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
2693 | (match_dup 1))] |
---|
2694 | "" |
---|
2695 | "operands[1] = prepare_scc_operands (EQ);") |
---|
2696 | |
---|
2697 | (define_expand "slt" |
---|
2698 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
2699 | (match_dup 1))] |
---|
2700 | "" |
---|
2701 | "operands[1] = prepare_scc_operands (LT);") |
---|
2702 | |
---|
2703 | (define_expand "sle" |
---|
2704 | [(match_operand:SI 0 "arith_reg_operand" "")] |
---|
2705 | "" |
---|
2706 | " |
---|
2707 | { |
---|
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; |
---|
2713 | }") |
---|
2714 | |
---|
2715 | (define_expand "sgt" |
---|
2716 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
2717 | (match_dup 1))] |
---|
2718 | "" |
---|
2719 | "operands[1] = prepare_scc_operands (GT);") |
---|
2720 | |
---|
2721 | (define_expand "sge" |
---|
2722 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
2723 | (match_dup 1))] |
---|
2724 | "" |
---|
2725 | " |
---|
2726 | { |
---|
2727 | if (GET_MODE (sh_compare_op0) == SFmode) |
---|
2728 | { |
---|
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))); |
---|
2745 | DONE; |
---|
2746 | } |
---|
2747 | operands[1] = prepare_scc_operands (GE); |
---|
2748 | }") |
---|
2749 | |
---|
2750 | (define_expand "sgtu" |
---|
2751 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
2752 | (match_dup 1))] |
---|
2753 | "" |
---|
2754 | "operands[1] = prepare_scc_operands (GTU);") |
---|
2755 | |
---|
2756 | (define_expand "sltu" |
---|
2757 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
2758 | (match_dup 1))] |
---|
2759 | "" |
---|
2760 | "operands[1] = prepare_scc_operands (LTU);") |
---|
2761 | |
---|
2762 | (define_expand "sleu" |
---|
2763 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
2764 | (match_dup 1))] |
---|
2765 | "" |
---|
2766 | "operands[1] = prepare_scc_operands (LEU);") |
---|
2767 | |
---|
2768 | (define_expand "sgeu" |
---|
2769 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
2770 | (match_dup 1))] |
---|
2771 | "" |
---|
2772 | "operands[1] = prepare_scc_operands (GEU);") |
---|
2773 | |
---|
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 | |
---|
2782 | (define_expand "sne" |
---|
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 | |
---|
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 | |
---|
2809 | ;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1. |
---|
2810 | ;; This prevents a regression that occurred when we switched from xor to |
---|
2811 | ;; mov/neg for sne. |
---|
2812 | |
---|
2813 | (define_split |
---|
2814 | [(set (match_operand:SI 0 "arith_reg_operand" "") |
---|
2815 | (plus:SI (reg:SI 18) |
---|
2816 | (const_int -1)))] |
---|
2817 | "" |
---|
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 | "") |
---|
2821 | |
---|
2822 | ;; ------------------------------------------------------------------------- |
---|
2823 | ;; Instructions to cope with inline literal tables |
---|
2824 | ;; ------------------------------------------------------------------------- |
---|
2825 | |
---|
2826 | ; 2 byte integer in line |
---|
2827 | |
---|
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 | |
---|
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 | |
---|
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 | |
---|
2901 | ; align to a two byte boundary |
---|
2902 | |
---|
2903 | (define_insn "align_2" |
---|
2904 | [(unspec_volatile [(const_int 1)] 1)] |
---|
2905 | "" |
---|
2906 | ".align 1" |
---|
2907 | [(set_attr "length" "0") |
---|
2908 | (set_attr "in_delay_slot" "no")]) |
---|
2909 | |
---|
2910 | ; align to a four byte boundary |
---|
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 |
---|
2920 | |
---|
2921 | (define_insn "align_log" |
---|
2922 | [(unspec_volatile [(match_operand 0 "const_int_operand" "")] 1)] |
---|
2923 | "" |
---|
2924 | ".align %O0" |
---|
2925 | ;; Need a variable length for this to be processed in each shorten_branch pass. |
---|
2926 | ;; The actual work is done in ADJUST_INSN_LENGTH, because length attributes |
---|
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")]) |
---|
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 | |
---|
2941 | ;; ------------------------------------------------------------------------- |
---|
2942 | ;; Misc |
---|
2943 | ;; ------------------------------------------------------------------------- |
---|
2944 | |
---|
2945 | ;; String/block move insn. |
---|
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)) |
---|
2969 | (clobber (reg:SI 0))])] |
---|
2970 | "" |
---|
2971 | "jsr @%0%#" |
---|
2972 | [(set_attr "type" "sfunc") |
---|
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%#" |
---|
2987 | [(set_attr "type" "sfunc") |
---|
2988 | (set_attr "needs_delay_slot" "yes")]) |
---|
2989 | |
---|
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" |
---|
3001 | "fadd %2,%0" |
---|
3002 | [(set_attr "type" "fp")]) |
---|
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") |
---|
3007 | (match_operand:SF 2 "arith_reg_operand" "f")))] |
---|
3008 | "TARGET_SH3E" |
---|
3009 | "fsub %2,%0" |
---|
3010 | [(set_attr "type" "fp")]) |
---|
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" |
---|
3017 | "fmul %2,%0" |
---|
3018 | [(set_attr "type" "fp")]) |
---|
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" |
---|
3026 | "fmac fr0,%2,%0" |
---|
3027 | [(set_attr "type" "fp")]) |
---|
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") |
---|
3032 | (match_operand:SF 2 "arith_reg_operand" "f")))] |
---|
3033 | "TARGET_SH3E" |
---|
3034 | "fdiv %2,%0" |
---|
3035 | [(set_attr "type" "fdiv")]) |
---|
3036 | |
---|
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 | "") |
---|
3044 | |
---|
3045 | (define_insn "*floatsisf2_ie" |
---|
3046 | [(set (match_operand:SF 0 "arith_reg_operand" "=f") |
---|
3047 | (float:SF (reg:SI 22)))] |
---|
3048 | "TARGET_SH3E" |
---|
3049 | "float fpul,%0" |
---|
3050 | [(set_attr "type" "fp")]) |
---|
3051 | |
---|
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 | "") |
---|
3059 | |
---|
3060 | (define_insn "*fixsfsi" |
---|
3061 | [(set (reg:SI 22) |
---|
3062 | (fix:SI (match_operand:SF 0 "arith_reg_operand" "f")))] |
---|
3063 | "TARGET_SH3E" |
---|
3064 | "ftrc %0,fpul" |
---|
3065 | [(set_attr "type" "fp")]) |
---|
3066 | |
---|
3067 | (define_insn "cmpgtsf_t" |
---|
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" |
---|
3071 | "fcmp/gt %1,%0" |
---|
3072 | [(set_attr "type" "fp")]) |
---|
3073 | |
---|
3074 | (define_insn "cmpeqsf_t" |
---|
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" |
---|
3078 | "fcmp/eq %1,%0" |
---|
3079 | [(set_attr "type" "fp")]) |
---|
3080 | |
---|
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 | |
---|
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 | }") |
---|
3100 | |
---|
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" |
---|
3105 | "fneg %0" |
---|
3106 | [(set_attr "type" "fp")]) |
---|
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" |
---|
3112 | "fsqrt %0" |
---|
3113 | [(set_attr "type" "fdiv")]) |
---|
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" |
---|
3119 | "fabs %0" |
---|
3120 | [(set_attr "type" "fp")]) |
---|
3121 | |
---|
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 | |
---|
3170 | ;; ------------------------------------------------------------------------- |
---|
3171 | ;; Peepholes |
---|
3172 | ;; ------------------------------------------------------------------------- |
---|
3173 | |
---|
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. |
---|
3176 | |
---|
3177 | (define_peephole |
---|
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") |
---|
3183 | |
---|
3184 | ;; See the comment on the dt combiner pattern above. |
---|
3185 | |
---|
3186 | (define_peephole |
---|
3187 | [(set (match_operand:SI 0 "arith_reg_operand" "=r") |
---|
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") |
---|
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" ""))] |
---|
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)" |
---|
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)))] |
---|
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)" |
---|
3283 | "mov.l @(%0,%1),%2") |
---|
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)" |
---|
3295 | "fmov{.s|} %2,@(%0,%1)") |
---|
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)" |
---|
3308 | "fmov{.s|} @(%0,%1),%2") |
---|
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")]) |
---|
3324 | |
---|
3325 | ;; Switch back to the original stack for interrupt functions with the |
---|
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")]) |
---|