Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/v850/v850.md @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 ;; GCC machine description for NEC V850 | |
2 ;; Copyright (C) 1996, 1997, 1998, 1999, 2002, 2004, 2005, 2007, 2008 | |
3 ;; Free Software Foundation, Inc. | |
4 ;; Contributed by Jeff Law (law@cygnus.com). | |
5 | |
6 ;; This file is part of GCC. | |
7 | |
8 ;; GCC 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 3, or (at your option) | |
11 ;; any later version. | |
12 | |
13 ;; GCC 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 GCC; see the file COPYING3. If not see | |
20 ;; <http://www.gnu.org/licenses/>. | |
21 | |
22 ;; The original PO technology requires these to be ordered by speed, | |
23 ;; so that assigner will pick the fastest. | |
24 | |
25 ;; See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
26 | |
27 ;; The V851 manual states that the instruction address space is 16M; | |
28 ;; the various branch/call instructions only have a 22bit offset (4M range). | |
29 ;; | |
30 ;; One day we'll probably need to handle calls to targets more than 4M | |
31 ;; away. | |
32 | |
33 ;; The size of instructions in bytes. | |
34 | |
35 (define_attr "length" "" | |
36 (const_int 4)) | |
37 | |
38 (define_attr "long_calls" "yes,no" | |
39 (const (if_then_else (symbol_ref "TARGET_LONG_CALLS") | |
40 (const_string "yes") | |
41 (const_string "no")))) | |
42 | |
43 ;; Types of instructions (for scheduling purposes). | |
44 | |
45 (define_attr "type" "load,mult,other" | |
46 (const_string "other")) | |
47 | |
48 ;; Condition code settings. | |
49 ;; none - insn does not affect cc | |
50 ;; none_0hit - insn does not affect cc but it does modify operand 0 | |
51 ;; This attribute is used to keep track of when operand 0 changes. | |
52 ;; See the description of NOTICE_UPDATE_CC for more info. | |
53 ;; set_znv - sets z,n,v to usable values; c is unknown. | |
54 ;; set_zn - sets z,n to usable values; v,c is unknown. | |
55 ;; compare - compare instruction | |
56 ;; clobber - value of cc is unknown | |
57 (define_attr "cc" "none,none_0hit,set_zn,set_znv,compare,clobber" | |
58 (const_string "clobber")) | |
59 | |
60 ;; Function units for the V850. As best as I can tell, there's | |
61 ;; a traditional memory load/use stall as well as a stall if | |
62 ;; the result of a multiply is used too early. | |
63 | |
64 (define_insn_reservation "v850_other" 1 | |
65 (eq_attr "type" "other") | |
66 "nothing") | |
67 (define_insn_reservation "v850_mult" 2 | |
68 (eq_attr "type" "mult") | |
69 "nothing") | |
70 (define_insn_reservation "v850_memory" 2 | |
71 (eq_attr "type" "load") | |
72 "nothing") | |
73 | |
74 (include "predicates.md") | |
75 | |
76 ;; ---------------------------------------------------------------------- | |
77 ;; MOVE INSTRUCTIONS | |
78 ;; ---------------------------------------------------------------------- | |
79 | |
80 ;; movqi | |
81 | |
82 (define_expand "movqi" | |
83 [(set (match_operand:QI 0 "general_operand" "") | |
84 (match_operand:QI 1 "general_operand" ""))] | |
85 "" | |
86 " | |
87 { | |
88 /* One of the ops has to be in a register or 0 */ | |
89 if (!register_operand (operand0, QImode) | |
90 && !reg_or_0_operand (operand1, QImode)) | |
91 operands[1] = copy_to_mode_reg (QImode, operand1); | |
92 }") | |
93 | |
94 (define_insn "*movqi_internal" | |
95 [(set (match_operand:QI 0 "general_operand" "=r,r,r,Q,r,m,m") | |
96 (match_operand:QI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))] | |
97 "register_operand (operands[0], QImode) | |
98 || reg_or_0_operand (operands[1], QImode)" | |
99 "* return output_move_single (operands);" | |
100 [(set_attr "length" "2,4,2,2,4,4,4") | |
101 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") | |
102 (set_attr "type" "other,other,load,other,load,other,other")]) | |
103 | |
104 ;; movhi | |
105 | |
106 (define_expand "movhi" | |
107 [(set (match_operand:HI 0 "general_operand" "") | |
108 (match_operand:HI 1 "general_operand" ""))] | |
109 "" | |
110 " | |
111 { | |
112 /* One of the ops has to be in a register or 0 */ | |
113 if (!register_operand (operand0, HImode) | |
114 && !reg_or_0_operand (operand1, HImode)) | |
115 operands[1] = copy_to_mode_reg (HImode, operand1); | |
116 }") | |
117 | |
118 (define_insn "*movhi_internal" | |
119 [(set (match_operand:HI 0 "general_operand" "=r,r,r,Q,r,m,m") | |
120 (match_operand:HI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))] | |
121 "register_operand (operands[0], HImode) | |
122 || reg_or_0_operand (operands[1], HImode)" | |
123 "* return output_move_single (operands);" | |
124 [(set_attr "length" "2,4,2,2,4,4,4") | |
125 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") | |
126 (set_attr "type" "other,other,load,other,load,other,other")]) | |
127 | |
128 ;; movsi and helpers | |
129 | |
130 (define_insn "*movsi_high" | |
131 [(set (match_operand:SI 0 "register_operand" "=r") | |
132 (high:SI (match_operand 1 "" "")))] | |
133 "" | |
134 "movhi hi(%1),%.,%0" | |
135 [(set_attr "length" "4") | |
136 (set_attr "cc" "none_0hit") | |
137 (set_attr "type" "other")]) | |
138 | |
139 (define_insn "*movsi_lo" | |
140 [(set (match_operand:SI 0 "register_operand" "=r") | |
141 (lo_sum:SI (match_operand:SI 1 "register_operand" "r") | |
142 (match_operand:SI 2 "immediate_operand" "i")))] | |
143 "" | |
144 "movea lo(%2),%1,%0" | |
145 [(set_attr "length" "4") | |
146 (set_attr "cc" "none_0hit") | |
147 (set_attr "type" "other")]) | |
148 | |
149 (define_expand "movsi" | |
150 [(set (match_operand:SI 0 "general_operand" "") | |
151 (match_operand:SI 1 "general_operand" ""))] | |
152 "" | |
153 " | |
154 { | |
155 /* One of the ops has to be in a register or 0 */ | |
156 if (!register_operand (operand0, SImode) | |
157 && !reg_or_0_operand (operand1, SImode)) | |
158 operands[1] = copy_to_mode_reg (SImode, operand1); | |
159 | |
160 /* Some constants, as well as symbolic operands | |
161 must be done with HIGH & LO_SUM patterns. */ | |
162 if (CONSTANT_P (operands[1]) | |
163 && GET_CODE (operands[1]) != HIGH | |
164 && ! TARGET_V850E | |
165 && !special_symbolref_operand (operands[1], VOIDmode) | |
166 && !(GET_CODE (operands[1]) == CONST_INT | |
167 && (CONST_OK_FOR_J (INTVAL (operands[1])) | |
168 || CONST_OK_FOR_K (INTVAL (operands[1])) | |
169 || CONST_OK_FOR_L (INTVAL (operands[1]))))) | |
170 { | |
171 rtx temp; | |
172 | |
173 if (reload_in_progress || reload_completed) | |
174 temp = operands[0]; | |
175 else | |
176 temp = gen_reg_rtx (SImode); | |
177 | |
178 emit_insn (gen_rtx_SET (SImode, temp, | |
179 gen_rtx_HIGH (SImode, operand1))); | |
180 emit_insn (gen_rtx_SET (SImode, operand0, | |
181 gen_rtx_LO_SUM (SImode, temp, operand1))); | |
182 DONE; | |
183 } | |
184 }") | |
185 | |
186 ;; This is the same as the following pattern, except that it includes | |
187 ;; support for arbitrary 32-bit immediates. | |
188 | |
189 ;; ??? This always loads addresses using hilo. If the only use of this address | |
190 ;; was in a load/store, then we would get smaller code if we only loaded the | |
191 ;; upper part with hi, and then put the lower part in the load/store insn. | |
192 | |
193 (define_insn "*movsi_internal_v850e" | |
194 [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,Q,r,r,m,m,r") | |
195 (match_operand:SI 1 "general_operand" "Jr,K,L,Q,Ir,m,R,r,I,i"))] | |
196 "TARGET_V850E | |
197 && (register_operand (operands[0], SImode) | |
198 || reg_or_0_operand (operands[1], SImode))" | |
199 "* return output_move_single (operands);" | |
200 [(set_attr "length" "2,4,4,2,2,4,4,4,4,6") | |
201 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") | |
202 (set_attr "type" "other,other,other,load,other,load,other,other,other,other")]) | |
203 | |
204 (define_insn "*movsi_internal" | |
205 [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,Q,r,r,m,m") | |
206 (match_operand:SI 1 "movsi_source_operand" "Jr,K,L,Q,Ir,m,R,r,I"))] | |
207 "register_operand (operands[0], SImode) | |
208 || reg_or_0_operand (operands[1], SImode)" | |
209 "* return output_move_single (operands);" | |
210 [(set_attr "length" "2,4,4,2,2,4,4,4,4") | |
211 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") | |
212 (set_attr "type" "other,other,other,load,other,load,other,other,other")]) | |
213 | |
214 (define_insn "*movsf_internal" | |
215 [(set (match_operand:SF 0 "general_operand" "=r,r,r,r,r,Q,r,m,m,r") | |
216 (match_operand:SF 1 "general_operand" "Jr,K,L,n,Q,Ir,m,r,IG,iF"))] | |
217 "register_operand (operands[0], SFmode) | |
218 || reg_or_0_operand (operands[1], SFmode)" | |
219 "* return output_move_single (operands);" | |
220 [(set_attr "length" "2,4,4,8,2,2,4,4,4,8") | |
221 (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit") | |
222 (set_attr "type" "other,other,other,other,load,other,load,other,other,other")]) | |
223 | |
224 | |
225 ;; ---------------------------------------------------------------------- | |
226 ;; TEST INSTRUCTIONS | |
227 ;; ---------------------------------------------------------------------- | |
228 | |
229 (define_insn "*v850_tst1" | |
230 [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") | |
231 (const_int 1) | |
232 (match_operand:QI 1 "const_int_operand" "n")))] | |
233 "" | |
234 "tst1 %1,%0" | |
235 [(set_attr "length" "4") | |
236 (set_attr "cc" "clobber")]) | |
237 | |
238 ;; This replaces ld.b;sar;andi with tst1;setf nz. | |
239 | |
240 ;; ??? The zero_extract sets the Z bit to the opposite of what one would | |
241 ;; expect. This perhaps should be wrapped in a (eq: X (const_int 0)). | |
242 | |
243 (define_split | |
244 [(set (match_operand:SI 0 "register_operand" "") | |
245 (zero_extract:SI (match_operand:QI 1 "memory_operand" "") | |
246 (const_int 1) | |
247 (match_operand 2 "const_int_operand" "")))] | |
248 "" | |
249 [(set (cc0) (zero_extract:SI (match_dup 1) | |
250 (const_int 1) | |
251 (match_dup 2))) | |
252 (set (match_dup 0) (ne:SI (cc0) (const_int 0)))]) | |
253 | |
254 (define_insn "tstsi" | |
255 [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] | |
256 "" | |
257 "cmp %.,%0" | |
258 [(set_attr "length" "2") | |
259 (set_attr "cc" "set_znv")]) | |
260 | |
261 (define_insn "cmpsi" | |
262 [(set (cc0) | |
263 (compare (match_operand:SI 0 "register_operand" "r,r") | |
264 (match_operand:SI 1 "reg_or_int5_operand" "r,J")))] | |
265 "" | |
266 "@ | |
267 cmp %1,%0 | |
268 cmp %1,%0" | |
269 [(set_attr "length" "2,2") | |
270 (set_attr "cc" "compare")]) | |
271 | |
272 ;; ---------------------------------------------------------------------- | |
273 ;; ADD INSTRUCTIONS | |
274 ;; ---------------------------------------------------------------------- | |
275 | |
276 (define_insn "addsi3" | |
277 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
278 (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") | |
279 (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))] | |
280 "" | |
281 "@ | |
282 add %2,%0 | |
283 addi %2,%1,%0 | |
284 addi %O2(%P2),%1,%0" | |
285 [(set_attr "length" "2,4,4") | |
286 (set_attr "cc" "set_zn,set_zn,set_zn")]) | |
287 | |
288 ;; ---------------------------------------------------------------------- | |
289 ;; SUBTRACT INSTRUCTIONS | |
290 ;; ---------------------------------------------------------------------- | |
291 | |
292 (define_insn "subsi3" | |
293 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
294 (minus:SI (match_operand:SI 1 "register_operand" "0,r") | |
295 (match_operand:SI 2 "register_operand" "r,0")))] | |
296 "" | |
297 "@ | |
298 sub %2,%0 | |
299 subr %1,%0" | |
300 [(set_attr "length" "2,2") | |
301 (set_attr "cc" "set_zn")]) | |
302 | |
303 (define_insn "negsi2" | |
304 [(set (match_operand:SI 0 "register_operand" "=r") | |
305 (neg:SI (match_operand:SI 1 "register_operand" "0")))] | |
306 "" | |
307 "subr %.,%0" | |
308 [(set_attr "length" "2") | |
309 (set_attr "cc" "set_zn")]) | |
310 | |
311 ;; ---------------------------------------------------------------------- | |
312 ;; MULTIPLY INSTRUCTIONS | |
313 ;; ---------------------------------------------------------------------- | |
314 | |
315 (define_expand "mulhisi3" | |
316 [(set (match_operand:SI 0 "register_operand" "") | |
317 (mult:SI | |
318 (sign_extend:SI (match_operand:HI 1 "register_operand" "")) | |
319 (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))] | |
320 "" | |
321 "if (GET_CODE (operands[2]) == CONST_INT) | |
322 { | |
323 emit_insn (gen_mulhisi3_internal2 (operands[0], operands[1], operands[2])); | |
324 DONE; | |
325 }") | |
326 | |
327 (define_insn "*mulhisi3_internal1" | |
328 [(set (match_operand:SI 0 "register_operand" "=r") | |
329 (mult:SI | |
330 (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) | |
331 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] | |
332 "" | |
333 "mulh %2,%0" | |
334 [(set_attr "length" "2") | |
335 (set_attr "cc" "none_0hit") | |
336 (set_attr "type" "mult")]) | |
337 | |
338 (define_insn "mulhisi3_internal2" | |
339 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
340 (mult:SI | |
341 (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,r")) | |
342 (match_operand:HI 2 "const_int_operand" "J,K")))] | |
343 "" | |
344 "@ | |
345 mulh %2,%0 | |
346 mulhi %2,%1,%0" | |
347 [(set_attr "length" "2,4") | |
348 (set_attr "cc" "none_0hit,none_0hit") | |
349 (set_attr "type" "mult")]) | |
350 | |
351 ;; ??? The scheduling info is probably wrong. | |
352 | |
353 ;; ??? This instruction can also generate the 32-bit highpart, but using it | |
354 ;; may increase code size counter to the desired result. | |
355 | |
356 ;; ??? This instructions can also give a DImode result. | |
357 | |
358 ;; ??? There is unsigned version, but it matters only for the DImode/highpart | |
359 ;; results. | |
360 | |
361 (define_insn "mulsi3" | |
362 [(set (match_operand:SI 0 "register_operand" "=r") | |
363 (mult:SI (match_operand:SI 1 "register_operand" "%0") | |
364 (match_operand:SI 2 "reg_or_int9_operand" "rO")))] | |
365 "TARGET_V850E" | |
366 "mul %2,%1,%." | |
367 [(set_attr "length" "4") | |
368 (set_attr "cc" "none_0hit") | |
369 (set_attr "type" "mult")]) | |
370 | |
371 ;; ---------------------------------------------------------------------- | |
372 ;; DIVIDE INSTRUCTIONS | |
373 ;; ---------------------------------------------------------------------- | |
374 | |
375 ;; ??? These insns do set the Z/N condition codes, except that they are based | |
376 ;; on only one of the two results, so it doesn't seem to make sense to use | |
377 ;; them. | |
378 | |
379 ;; ??? The scheduling info is probably wrong. | |
380 | |
381 (define_insn "divmodsi4" | |
382 [(set (match_operand:SI 0 "register_operand" "=r") | |
383 (div:SI (match_operand:SI 1 "register_operand" "0") | |
384 (match_operand:SI 2 "register_operand" "r"))) | |
385 (set (match_operand:SI 3 "register_operand" "=r") | |
386 (mod:SI (match_dup 1) | |
387 (match_dup 2)))] | |
388 "TARGET_V850E" | |
389 "div %2,%0,%3" | |
390 [(set_attr "length" "4") | |
391 (set_attr "cc" "clobber") | |
392 (set_attr "type" "other")]) | |
393 | |
394 (define_insn "udivmodsi4" | |
395 [(set (match_operand:SI 0 "register_operand" "=r") | |
396 (udiv:SI (match_operand:SI 1 "register_operand" "0") | |
397 (match_operand:SI 2 "register_operand" "r"))) | |
398 (set (match_operand:SI 3 "register_operand" "=r") | |
399 (umod:SI (match_dup 1) | |
400 (match_dup 2)))] | |
401 "TARGET_V850E" | |
402 "divu %2,%0,%3" | |
403 [(set_attr "length" "4") | |
404 (set_attr "cc" "clobber") | |
405 (set_attr "type" "other")]) | |
406 | |
407 ;; ??? There is a 2 byte instruction for generating only the quotient. | |
408 ;; However, it isn't clear how to compute the length field correctly. | |
409 | |
410 (define_insn "divmodhi4" | |
411 [(set (match_operand:HI 0 "register_operand" "=r") | |
412 (div:HI (match_operand:HI 1 "register_operand" "0") | |
413 (match_operand:HI 2 "register_operand" "r"))) | |
414 (set (match_operand:HI 3 "register_operand" "=r") | |
415 (mod:HI (match_dup 1) | |
416 (match_dup 2)))] | |
417 "TARGET_V850E" | |
418 "divh %2,%0,%3" | |
419 [(set_attr "length" "4") | |
420 (set_attr "cc" "clobber") | |
421 (set_attr "type" "other")]) | |
422 | |
423 ;; Half-words are sign-extended by default, so we must zero extend to a word | |
424 ;; here before doing the divide. | |
425 | |
426 (define_insn "udivmodhi4" | |
427 [(set (match_operand:HI 0 "register_operand" "=r") | |
428 (udiv:HI (match_operand:HI 1 "register_operand" "0") | |
429 (match_operand:HI 2 "register_operand" "r"))) | |
430 (set (match_operand:HI 3 "register_operand" "=r") | |
431 (umod:HI (match_dup 1) | |
432 (match_dup 2)))] | |
433 "TARGET_V850E" | |
434 "zxh %0 ; divhu %2,%0,%3" | |
435 [(set_attr "length" "4") | |
436 (set_attr "cc" "clobber") | |
437 (set_attr "type" "other")]) | |
438 | |
439 ;; ---------------------------------------------------------------------- | |
440 ;; AND INSTRUCTIONS | |
441 ;; ---------------------------------------------------------------------- | |
442 | |
443 (define_insn "*v850_clr1_1" | |
444 [(set (match_operand:QI 0 "memory_operand" "=m") | |
445 (subreg:QI | |
446 (and:SI (subreg:SI (match_dup 0) 0) | |
447 (match_operand:QI 1 "not_power_of_two_operand" "")) 0))] | |
448 "" | |
449 "* | |
450 { | |
451 rtx xoperands[2]; | |
452 xoperands[0] = operands[0]; | |
453 xoperands[1] = GEN_INT (~INTVAL (operands[1]) & 0xff); | |
454 output_asm_insn (\"clr1 %M1,%0\", xoperands); | |
455 return \"\"; | |
456 }" | |
457 [(set_attr "length" "4") | |
458 (set_attr "cc" "clobber")]) | |
459 | |
460 (define_insn "*v850_clr1_2" | |
461 [(set (match_operand:HI 0 "indirect_operand" "=m") | |
462 (subreg:HI | |
463 (and:SI (subreg:SI (match_dup 0) 0) | |
464 (match_operand:HI 1 "not_power_of_two_operand" "")) 0))] | |
465 "" | |
466 "* | |
467 { | |
468 int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffff); | |
469 | |
470 rtx xoperands[2]; | |
471 xoperands[0] = gen_rtx_MEM (QImode, | |
472 plus_constant (XEXP (operands[0], 0), log2 / 8)); | |
473 xoperands[1] = GEN_INT (log2 % 8); | |
474 output_asm_insn (\"clr1 %1,%0\", xoperands); | |
475 return \"\"; | |
476 }" | |
477 [(set_attr "length" "4") | |
478 (set_attr "cc" "clobber")]) | |
479 | |
480 (define_insn "*v850_clr1_3" | |
481 [(set (match_operand:SI 0 "indirect_operand" "=m") | |
482 (and:SI (match_dup 0) | |
483 (match_operand:SI 1 "not_power_of_two_operand" "")))] | |
484 "" | |
485 "* | |
486 { | |
487 int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffffffff); | |
488 | |
489 rtx xoperands[2]; | |
490 xoperands[0] = gen_rtx_MEM (QImode, | |
491 plus_constant (XEXP (operands[0], 0), log2 / 8)); | |
492 xoperands[1] = GEN_INT (log2 % 8); | |
493 output_asm_insn (\"clr1 %1,%0\", xoperands); | |
494 return \"\"; | |
495 }" | |
496 [(set_attr "length" "4") | |
497 (set_attr "cc" "clobber")]) | |
498 | |
499 (define_insn "andsi3" | |
500 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
501 (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
502 (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] | |
503 "" | |
504 "@ | |
505 and %2,%0 | |
506 and %.,%0 | |
507 andi %2,%1,%0" | |
508 [(set_attr "length" "2,2,4") | |
509 (set_attr "cc" "set_znv")]) | |
510 | |
511 ;; ---------------------------------------------------------------------- | |
512 ;; OR INSTRUCTIONS | |
513 ;; ---------------------------------------------------------------------- | |
514 | |
515 (define_insn "*v850_set1_1" | |
516 [(set (match_operand:QI 0 "memory_operand" "=m") | |
517 (subreg:QI (ior:SI (subreg:SI (match_dup 0) 0) | |
518 (match_operand 1 "power_of_two_operand" "")) 0))] | |
519 "" | |
520 "set1 %M1,%0" | |
521 [(set_attr "length" "4") | |
522 (set_attr "cc" "clobber")]) | |
523 | |
524 (define_insn "*v850_set1_2" | |
525 [(set (match_operand:HI 0 "indirect_operand" "=m") | |
526 (subreg:HI (ior:SI (subreg:SI (match_dup 0) 0) | |
527 (match_operand 1 "power_of_two_operand" "")) 0))] | |
528 "" | |
529 "* | |
530 { | |
531 int log2 = exact_log2 (INTVAL (operands[1])); | |
532 | |
533 if (log2 < 8) | |
534 return \"set1 %M1,%0\"; | |
535 else | |
536 { | |
537 rtx xoperands[2]; | |
538 xoperands[0] = gen_rtx_MEM (QImode, | |
539 plus_constant (XEXP (operands[0], 0), | |
540 log2 / 8)); | |
541 xoperands[1] = GEN_INT (log2 % 8); | |
542 output_asm_insn (\"set1 %1,%0\", xoperands); | |
543 } | |
544 return \"\"; | |
545 }" | |
546 [(set_attr "length" "4") | |
547 (set_attr "cc" "clobber")]) | |
548 | |
549 (define_insn "*v850_set1_3" | |
550 [(set (match_operand:SI 0 "indirect_operand" "=m") | |
551 (ior:SI (match_dup 0) | |
552 (match_operand 1 "power_of_two_operand" "")))] | |
553 "" | |
554 "* | |
555 { | |
556 int log2 = exact_log2 (INTVAL (operands[1])); | |
557 | |
558 if (log2 < 8) | |
559 return \"set1 %M1,%0\"; | |
560 else | |
561 { | |
562 rtx xoperands[2]; | |
563 xoperands[0] = gen_rtx_MEM (QImode, | |
564 plus_constant (XEXP (operands[0], 0), | |
565 log2 / 8)); | |
566 xoperands[1] = GEN_INT (log2 % 8); | |
567 output_asm_insn (\"set1 %1,%0\", xoperands); | |
568 } | |
569 return \"\"; | |
570 }" | |
571 [(set_attr "length" "4") | |
572 (set_attr "cc" "clobber")]) | |
573 | |
574 (define_insn "iorsi3" | |
575 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
576 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
577 (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] | |
578 "" | |
579 "@ | |
580 or %2,%0 | |
581 or %.,%0 | |
582 ori %2,%1,%0" | |
583 [(set_attr "length" "2,2,4") | |
584 (set_attr "cc" "set_znv")]) | |
585 | |
586 ;; ---------------------------------------------------------------------- | |
587 ;; XOR INSTRUCTIONS | |
588 ;; ---------------------------------------------------------------------- | |
589 | |
590 (define_insn "*v850_not1_1" | |
591 [(set (match_operand:QI 0 "memory_operand" "=m") | |
592 (subreg:QI (xor:SI (subreg:SI (match_dup 0) 0) | |
593 (match_operand 1 "power_of_two_operand" "")) 0))] | |
594 "" | |
595 "not1 %M1,%0" | |
596 [(set_attr "length" "4") | |
597 (set_attr "cc" "clobber")]) | |
598 | |
599 (define_insn "*v850_not1_2" | |
600 [(set (match_operand:HI 0 "indirect_operand" "=m") | |
601 (subreg:HI (xor:SI (subreg:SI (match_dup 0) 0) | |
602 (match_operand 1 "power_of_two_operand" "")) 0))] | |
603 "" | |
604 "* | |
605 { | |
606 int log2 = exact_log2 (INTVAL (operands[1])); | |
607 | |
608 if (log2 < 8) | |
609 return \"not1 %M1,%0\"; | |
610 else | |
611 { | |
612 rtx xoperands[2]; | |
613 xoperands[0] = gen_rtx_MEM (QImode, | |
614 plus_constant (XEXP (operands[0], 0), | |
615 log2 / 8)); | |
616 xoperands[1] = GEN_INT (log2 % 8); | |
617 output_asm_insn (\"not1 %1,%0\", xoperands); | |
618 } | |
619 return \"\"; | |
620 }" | |
621 [(set_attr "length" "4") | |
622 (set_attr "cc" "clobber")]) | |
623 | |
624 (define_insn "*v850_not1_3" | |
625 [(set (match_operand:SI 0 "indirect_operand" "=m") | |
626 (xor:SI (match_dup 0) | |
627 (match_operand 1 "power_of_two_operand" "")))] | |
628 "" | |
629 "* | |
630 { | |
631 int log2 = exact_log2 (INTVAL (operands[1])); | |
632 | |
633 if (log2 < 8) | |
634 return \"not1 %M1,%0\"; | |
635 else | |
636 { | |
637 rtx xoperands[2]; | |
638 xoperands[0] = gen_rtx_MEM (QImode, | |
639 plus_constant (XEXP (operands[0], 0), | |
640 log2 / 8)); | |
641 xoperands[1] = GEN_INT (log2 % 8); | |
642 output_asm_insn (\"not1 %1,%0\", xoperands); | |
643 } | |
644 return \"\"; | |
645 }" | |
646 [(set_attr "length" "4") | |
647 (set_attr "cc" "clobber")]) | |
648 | |
649 (define_insn "xorsi3" | |
650 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
651 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
652 (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] | |
653 "" | |
654 "@ | |
655 xor %2,%0 | |
656 xor %.,%0 | |
657 xori %2,%1,%0" | |
658 [(set_attr "length" "2,2,4") | |
659 (set_attr "cc" "set_znv")]) | |
660 | |
661 ;; ---------------------------------------------------------------------- | |
662 ;; NOT INSTRUCTIONS | |
663 ;; ---------------------------------------------------------------------- | |
664 | |
665 (define_insn "one_cmplsi2" | |
666 [(set (match_operand:SI 0 "register_operand" "=r") | |
667 (not:SI (match_operand:SI 1 "register_operand" "r")))] | |
668 "" | |
669 "not %1,%0" | |
670 [(set_attr "length" "2") | |
671 (set_attr "cc" "set_znv")]) | |
672 | |
673 ;; ----------------------------------------------------------------- | |
674 ;; BIT FIELDS | |
675 ;; ----------------------------------------------------------------- | |
676 | |
677 ;; ??? Is it worth defining insv and extv for the V850 series?!? | |
678 | |
679 ;; An insv pattern would be useful, but does not get used because | |
680 ;; store_bit_field never calls insv when storing a constant value into a | |
681 ;; single-bit bitfield. | |
682 | |
683 ;; extv/extzv patterns would be useful, but do not get used because | |
684 ;; optimize_bitfield_compare in fold-const usually converts single | |
685 ;; bit extracts into an AND with a mask. | |
686 | |
687 ;; ----------------------------------------------------------------- | |
688 ;; Scc INSTRUCTIONS | |
689 ;; ----------------------------------------------------------------- | |
690 | |
691 (define_insn "sle" | |
692 [(set (match_operand:SI 0 "register_operand" "=r") | |
693 (le:SI (cc0) (const_int 0)))] | |
694 "" | |
695 "* | |
696 { | |
697 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) | |
698 return 0; | |
699 | |
700 return \"setf le,%0\"; | |
701 }" | |
702 [(set_attr "length" "4") | |
703 (set_attr "cc" "none_0hit")]) | |
704 | |
705 (define_insn "sleu" | |
706 [(set (match_operand:SI 0 "register_operand" "=r") | |
707 (leu:SI (cc0) (const_int 0)))] | |
708 "" | |
709 "setf nh,%0" | |
710 [(set_attr "length" "4") | |
711 (set_attr "cc" "none_0hit")]) | |
712 | |
713 (define_insn "sge" | |
714 [(set (match_operand:SI 0 "register_operand" "=r") | |
715 (ge:SI (cc0) (const_int 0)))] | |
716 "" | |
717 "* | |
718 { | |
719 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) | |
720 return 0; | |
721 | |
722 return \"setf ge,%0\"; | |
723 }" | |
724 [(set_attr "length" "4") | |
725 (set_attr "cc" "none_0hit")]) | |
726 | |
727 (define_insn "sgeu" | |
728 [(set (match_operand:SI 0 "register_operand" "=r") | |
729 (geu:SI (cc0) (const_int 0)))] | |
730 "" | |
731 "setf nl,%0" | |
732 [(set_attr "length" "4") | |
733 (set_attr "cc" "none_0hit")]) | |
734 | |
735 (define_insn "slt" | |
736 [(set (match_operand:SI 0 "register_operand" "=r") | |
737 (lt:SI (cc0) (const_int 0)))] | |
738 "" | |
739 "* | |
740 { | |
741 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) | |
742 return 0; | |
743 | |
744 return \"setf lt,%0\"; | |
745 }" | |
746 [(set_attr "length" "4") | |
747 (set_attr "cc" "none_0hit")]) | |
748 | |
749 (define_insn "sltu" | |
750 [(set (match_operand:SI 0 "register_operand" "=r") | |
751 (ltu:SI (cc0) (const_int 0)))] | |
752 "" | |
753 "setf l,%0" | |
754 [(set_attr "length" "4") | |
755 (set_attr "cc" "none_0hit")]) | |
756 | |
757 (define_insn "sgt" | |
758 [(set (match_operand:SI 0 "register_operand" "=r") | |
759 (gt:SI (cc0) (const_int 0)))] | |
760 "" | |
761 "* | |
762 { | |
763 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0) | |
764 return 0; | |
765 | |
766 return \"setf gt,%0\"; | |
767 }" | |
768 [(set_attr "length" "4") | |
769 (set_attr "cc" "none_0hit")]) | |
770 | |
771 (define_insn "sgtu" | |
772 [(set (match_operand:SI 0 "register_operand" "=r") | |
773 (gtu:SI (cc0) (const_int 0)))] | |
774 "" | |
775 "setf h,%0" | |
776 [(set_attr "length" "4") | |
777 (set_attr "cc" "none_0hit")]) | |
778 | |
779 (define_insn "seq" | |
780 [(set (match_operand:SI 0 "register_operand" "=r") | |
781 (eq:SI (cc0) (const_int 0)))] | |
782 "" | |
783 "setf z,%0" | |
784 [(set_attr "length" "4") | |
785 (set_attr "cc" "none_0hit")]) | |
786 | |
787 (define_insn "sne" | |
788 [(set (match_operand:SI 0 "register_operand" "=r") | |
789 (ne:SI (cc0) (const_int 0)))] | |
790 "" | |
791 "setf nz,%0" | |
792 [(set_attr "length" "4") | |
793 (set_attr "cc" "none_0hit")]) | |
794 | |
795 ;; ---------------------------------------------------------------------- | |
796 ;; CONDITIONAL MOVE INSTRUCTIONS | |
797 ;; ---------------------------------------------------------------------- | |
798 | |
799 ;; Instructions using cc0 aren't allowed to have input reloads, so we must | |
800 ;; hide the fact that this instruction uses cc0. We do so by including the | |
801 ;; compare instruction inside it. | |
802 | |
803 ;; ??? This is very ugly. The right way to do this is to modify cmpsi so | |
804 ;; that it doesn't emit RTL, and then modify the bcc/scc patterns so that | |
805 ;; they emit RTL for the compare instruction. Unfortunately, this requires | |
806 ;; lots of changes that will be hard to sanitize. So for now, cmpsi still | |
807 ;; emits RTL, and I get the compare operands here from the previous insn. | |
808 | |
809 (define_expand "movsicc" | |
810 [(set (match_operand:SI 0 "register_operand" "=r") | |
811 (if_then_else:SI | |
812 (match_operator 1 "comparison_operator" | |
813 [(match_dup 4) (match_dup 5)]) | |
814 (match_operand:SI 2 "reg_or_const_operand" "rJ") | |
815 (match_operand:SI 3 "reg_or_const_operand" "rI")))] | |
816 "TARGET_V850E" | |
817 " | |
818 { | |
819 rtx insn = get_last_insn_anywhere (); | |
820 rtx src; | |
821 | |
822 if ( (GET_CODE (operands[2]) == CONST_INT | |
823 && GET_CODE (operands[3]) == CONST_INT)) | |
824 { | |
825 int o2 = INTVAL (operands[2]); | |
826 int o3 = INTVAL (operands[3]); | |
827 | |
828 if (o2 == 1 && o3 == 0) | |
829 FAIL; /* setf */ | |
830 if (o3 == 1 && o2 == 0) | |
831 FAIL; /* setf */ | |
832 if (o2 == 0 && (o3 < -16 || o3 > 15) && exact_log2 (o3) >= 0) | |
833 FAIL; /* setf + shift */ | |
834 if (o3 == 0 && (o2 < -16 || o2 > 15) && exact_log2 (o2) >=0) | |
835 FAIL; /* setf + shift */ | |
836 if (o2 != 0) | |
837 operands[2] = copy_to_mode_reg (SImode, operands[2]); | |
838 if (o3 !=0 ) | |
839 operands[3] = copy_to_mode_reg (SImode, operands[3]); | |
840 } | |
841 else | |
842 { | |
843 if (GET_CODE (operands[2]) != REG) | |
844 operands[2] = copy_to_mode_reg (SImode,operands[2]); | |
845 if (GET_CODE (operands[3]) != REG) | |
846 operands[3] = copy_to_mode_reg (SImode, operands[3]); | |
847 } | |
848 gcc_assert (GET_CODE (insn) == INSN | |
849 && GET_CODE (PATTERN (insn)) == SET | |
850 && SET_DEST (PATTERN (insn)) == cc0_rtx); | |
851 | |
852 src = SET_SRC (PATTERN (insn)); | |
853 | |
854 switch (GET_CODE (src)) | |
855 { | |
856 case COMPARE: | |
857 operands[4] = XEXP (src, 0); | |
858 operands[5] = XEXP (src, 1); | |
859 break; | |
860 | |
861 case REG: | |
862 case SUBREG: | |
863 operands[4] = src; | |
864 operands[5] = const0_rtx; | |
865 break; | |
866 | |
867 default: | |
868 gcc_unreachable (); | |
869 } | |
870 }") | |
871 | |
872 ;; ??? Clobbering the condition codes is overkill. | |
873 | |
874 ;; ??? We sometimes emit an unnecessary compare instruction because the | |
875 ;; condition codes may have already been set by an earlier instruction, | |
876 ;; but we have no code here to avoid the compare if it is unnecessary. | |
877 | |
878 (define_insn "*movsicc_normal" | |
879 [(set (match_operand:SI 0 "register_operand" "=r") | |
880 (if_then_else:SI | |
881 (match_operator 1 "comparison_operator" | |
882 [(match_operand:SI 4 "register_operand" "r") | |
883 (match_operand:SI 5 "reg_or_int5_operand" "rJ")]) | |
884 (match_operand:SI 2 "reg_or_int5_operand" "rJ") | |
885 (match_operand:SI 3 "reg_or_0_operand" "rI")))] | |
886 "TARGET_V850E" | |
887 "cmp %5,%4 ; cmov %c1,%2,%z3,%0" | |
888 [(set_attr "length" "6") | |
889 (set_attr "cc" "clobber")]) | |
890 | |
891 (define_insn "*movsicc_reversed" | |
892 [(set (match_operand:SI 0 "register_operand" "=r") | |
893 (if_then_else:SI | |
894 (match_operator 1 "comparison_operator" | |
895 [(match_operand:SI 4 "register_operand" "r") | |
896 (match_operand:SI 5 "reg_or_int5_operand" "rJ")]) | |
897 (match_operand:SI 2 "reg_or_0_operand" "rI") | |
898 (match_operand:SI 3 "reg_or_int5_operand" "rJ")))] | |
899 "TARGET_V850E" | |
900 "cmp %5,%4 ; cmov %C1,%3,%z2,%0" | |
901 [(set_attr "length" "6") | |
902 (set_attr "cc" "clobber")]) | |
903 | |
904 (define_insn "*movsicc_tst1" | |
905 [(set (match_operand:SI 0 "register_operand" "=r") | |
906 (if_then_else:SI | |
907 (match_operator 1 "comparison_operator" | |
908 [(zero_extract:SI | |
909 (match_operand:QI 2 "memory_operand" "m") | |
910 (const_int 1) | |
911 (match_operand 3 "const_int_operand" "n")) | |
912 (const_int 0)]) | |
913 (match_operand:SI 4 "reg_or_int5_operand" "rJ") | |
914 (match_operand:SI 5 "reg_or_0_operand" "rI")))] | |
915 "TARGET_V850E" | |
916 "tst1 %3,%2 ; cmov %c1,%4,%z5,%0" | |
917 [(set_attr "length" "8") | |
918 (set_attr "cc" "clobber")]) | |
919 | |
920 (define_insn "*movsicc_tst1_reversed" | |
921 [(set (match_operand:SI 0 "register_operand" "=r") | |
922 (if_then_else:SI | |
923 (match_operator 1 "comparison_operator" | |
924 [(zero_extract:SI | |
925 (match_operand:QI 2 "memory_operand" "m") | |
926 (const_int 1) | |
927 (match_operand 3 "const_int_operand" "n")) | |
928 (const_int 0)]) | |
929 (match_operand:SI 4 "reg_or_0_operand" "rI") | |
930 (match_operand:SI 5 "reg_or_int5_operand" "rJ")))] | |
931 "TARGET_V850E" | |
932 "tst1 %3,%2 ; cmov %C1,%5,%z4,%0" | |
933 [(set_attr "length" "8") | |
934 (set_attr "cc" "clobber")]) | |
935 | |
936 ;; Matching for sasf requires combining 4 instructions, so we provide a | |
937 ;; dummy pattern to match the first 3, which will always be turned into the | |
938 ;; second pattern by subsequent combining. As above, we must include the | |
939 ;; comparison to avoid input reloads in an insn using cc0. | |
940 | |
941 (define_insn "*sasf_1" | |
942 [(set (match_operand:SI 0 "register_operand" "") | |
943 (ior:SI (match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) | |
944 (ashift:SI (match_operand:SI 2 "register_operand" "") | |
945 (const_int 1))))] | |
946 "TARGET_V850E" | |
947 "* gcc_unreachable ();") | |
948 | |
949 (define_insn "*sasf_2" | |
950 [(set (match_operand:SI 0 "register_operand" "=r") | |
951 (ior:SI | |
952 (match_operator 1 "comparison_operator" | |
953 [(match_operand:SI 3 "register_operand" "r") | |
954 (match_operand:SI 4 "reg_or_int5_operand" "rJ")]) | |
955 (ashift:SI (match_operand:SI 2 "register_operand" "0") | |
956 (const_int 1))))] | |
957 "TARGET_V850E" | |
958 "cmp %4,%3 ; sasf %c1,%0" | |
959 [(set_attr "length" "6") | |
960 (set_attr "cc" "clobber")]) | |
961 | |
962 (define_split | |
963 [(set (match_operand:SI 0 "register_operand" "") | |
964 (if_then_else:SI | |
965 (match_operator 1 "comparison_operator" | |
966 [(match_operand:SI 4 "register_operand" "") | |
967 (match_operand:SI 5 "reg_or_int5_operand" "")]) | |
968 (match_operand:SI 2 "const_int_operand" "") | |
969 (match_operand:SI 3 "const_int_operand" "")))] | |
970 "TARGET_V850E | |
971 && ((INTVAL (operands[2]) ^ INTVAL (operands[3])) == 1) | |
972 && ((INTVAL (operands[2]) + INTVAL (operands[3])) != 1) | |
973 && (GET_CODE (operands[5]) == CONST_INT | |
974 || REGNO (operands[0]) != REGNO (operands[5])) | |
975 && REGNO (operands[0]) != REGNO (operands[4])" | |
976 [(set (match_dup 0) (match_dup 6)) | |
977 (set (match_dup 0) | |
978 (ior:SI (match_op_dup 7 [(match_dup 4) (match_dup 5)]) | |
979 (ashift:SI (match_dup 0) (const_int 1))))] | |
980 " | |
981 { | |
982 operands[6] = GEN_INT (INTVAL (operands[2]) >> 1); | |
983 if (INTVAL (operands[2]) & 0x1) | |
984 operands[7] = operands[1]; | |
985 else | |
986 operands[7] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])), | |
987 GET_MODE (operands[1]), | |
988 XEXP (operands[1], 0), XEXP (operands[1], 1)); | |
989 }") | |
990 ;; --------------------------------------------------------------------- | |
991 ;; BYTE SWAP INSTRUCTIONS | |
992 ;; --------------------------------------------------------------------- | |
993 | |
994 (define_expand "rotlhi3" | |
995 [(set (match_operand:HI 0 "register_operand" "") | |
996 (rotate:HI (match_operand:HI 1 "register_operand" "") | |
997 (match_operand:HI 2 "const_int_operand" "")))] | |
998 "TARGET_V850E" | |
999 " | |
1000 { | |
1001 if (INTVAL (operands[2]) != 8) | |
1002 FAIL; | |
1003 }") | |
1004 | |
1005 (define_insn "*rotlhi3_8" | |
1006 [(set (match_operand:HI 0 "register_operand" "=r") | |
1007 (rotate:HI (match_operand:HI 1 "register_operand" "r") | |
1008 (const_int 8)))] | |
1009 "TARGET_V850E" | |
1010 "bsh %1,%0" | |
1011 [(set_attr "length" "4") | |
1012 (set_attr "cc" "clobber")]) | |
1013 | |
1014 (define_expand "rotlsi3" | |
1015 [(set (match_operand:SI 0 "register_operand" "") | |
1016 (rotate:SI (match_operand:SI 1 "register_operand" "") | |
1017 (match_operand:SI 2 "const_int_operand" "")))] | |
1018 "TARGET_V850E" | |
1019 " | |
1020 { | |
1021 if (INTVAL (operands[2]) != 16) | |
1022 FAIL; | |
1023 }") | |
1024 | |
1025 (define_insn "*rotlsi3_16" | |
1026 [(set (match_operand:SI 0 "register_operand" "=r") | |
1027 (rotate:SI (match_operand:SI 1 "register_operand" "r") | |
1028 (const_int 16)))] | |
1029 "TARGET_V850E" | |
1030 "hsw %1,%0" | |
1031 [(set_attr "length" "4") | |
1032 (set_attr "cc" "clobber")]) | |
1033 | |
1034 ;; ---------------------------------------------------------------------- | |
1035 ;; JUMP INSTRUCTIONS | |
1036 ;; ---------------------------------------------------------------------- | |
1037 | |
1038 ;; Conditional jump instructions | |
1039 | |
1040 (define_expand "ble" | |
1041 [(set (pc) | |
1042 (if_then_else (le (cc0) | |
1043 (const_int 0)) | |
1044 (label_ref (match_operand 0 "" "")) | |
1045 (pc)))] | |
1046 "" | |
1047 "") | |
1048 | |
1049 (define_expand "bleu" | |
1050 [(set (pc) | |
1051 (if_then_else (leu (cc0) | |
1052 (const_int 0)) | |
1053 (label_ref (match_operand 0 "" "")) | |
1054 (pc)))] | |
1055 "" | |
1056 "") | |
1057 | |
1058 (define_expand "bge" | |
1059 [(set (pc) | |
1060 (if_then_else (ge (cc0) | |
1061 (const_int 0)) | |
1062 (label_ref (match_operand 0 "" "")) | |
1063 (pc)))] | |
1064 "" | |
1065 "") | |
1066 | |
1067 (define_expand "bgeu" | |
1068 [(set (pc) | |
1069 (if_then_else (geu (cc0) | |
1070 (const_int 0)) | |
1071 (label_ref (match_operand 0 "" "")) | |
1072 (pc)))] | |
1073 "" | |
1074 "") | |
1075 | |
1076 (define_expand "blt" | |
1077 [(set (pc) | |
1078 (if_then_else (lt (cc0) | |
1079 (const_int 0)) | |
1080 (label_ref (match_operand 0 "" "")) | |
1081 (pc)))] | |
1082 "" | |
1083 "") | |
1084 | |
1085 (define_expand "bltu" | |
1086 [(set (pc) | |
1087 (if_then_else (ltu (cc0) | |
1088 (const_int 0)) | |
1089 (label_ref (match_operand 0 "" "")) | |
1090 (pc)))] | |
1091 "" | |
1092 "") | |
1093 | |
1094 (define_expand "bgt" | |
1095 [(set (pc) | |
1096 (if_then_else (gt (cc0) | |
1097 (const_int 0)) | |
1098 (label_ref (match_operand 0 "" "")) | |
1099 (pc)))] | |
1100 "" | |
1101 "") | |
1102 | |
1103 (define_expand "bgtu" | |
1104 [(set (pc) | |
1105 (if_then_else (gtu (cc0) | |
1106 (const_int 0)) | |
1107 (label_ref (match_operand 0 "" "")) | |
1108 (pc)))] | |
1109 "" | |
1110 "") | |
1111 | |
1112 (define_expand "beq" | |
1113 [(set (pc) | |
1114 (if_then_else (eq (cc0) | |
1115 (const_int 0)) | |
1116 (label_ref (match_operand 0 "" "")) | |
1117 (pc)))] | |
1118 "" | |
1119 "") | |
1120 | |
1121 (define_expand "bne" | |
1122 [(set (pc) | |
1123 (if_then_else (ne (cc0) | |
1124 (const_int 0)) | |
1125 (label_ref (match_operand 0 "" "")) | |
1126 (pc)))] | |
1127 "" | |
1128 "") | |
1129 | |
1130 (define_insn "*branch_normal" | |
1131 [(set (pc) | |
1132 (if_then_else (match_operator 1 "comparison_operator" | |
1133 [(cc0) (const_int 0)]) | |
1134 (label_ref (match_operand 0 "" "")) | |
1135 (pc)))] | |
1136 "" | |
1137 "* | |
1138 { | |
1139 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 | |
1140 && (GET_CODE (operands[1]) == GT | |
1141 || GET_CODE (operands[1]) == GE | |
1142 || GET_CODE (operands[1]) == LE | |
1143 || GET_CODE (operands[1]) == LT)) | |
1144 return 0; | |
1145 | |
1146 if (get_attr_length (insn) == 2) | |
1147 return \"b%b1 %l0\"; | |
1148 else | |
1149 return \"b%B1 .+6 ; jr %l0\"; | |
1150 }" | |
1151 [(set (attr "length") | |
1152 (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
1153 (const_int 256)) | |
1154 (const_int 2) | |
1155 (const_int 6))) | |
1156 (set_attr "cc" "none")]) | |
1157 | |
1158 (define_insn "*branch_invert" | |
1159 [(set (pc) | |
1160 (if_then_else (match_operator 1 "comparison_operator" | |
1161 [(cc0) (const_int 0)]) | |
1162 (pc) | |
1163 (label_ref (match_operand 0 "" ""))))] | |
1164 "" | |
1165 "* | |
1166 { | |
1167 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 | |
1168 && (GET_CODE (operands[1]) == GT | |
1169 || GET_CODE (operands[1]) == GE | |
1170 || GET_CODE (operands[1]) == LE | |
1171 || GET_CODE (operands[1]) == LT)) | |
1172 return 0; | |
1173 if (get_attr_length (insn) == 2) | |
1174 return \"b%B1 %l0\"; | |
1175 else | |
1176 return \"b%b1 .+6 ; jr %l0\"; | |
1177 }" | |
1178 [(set (attr "length") | |
1179 (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
1180 (const_int 256)) | |
1181 (const_int 2) | |
1182 (const_int 6))) | |
1183 (set_attr "cc" "none")]) | |
1184 | |
1185 ;; Unconditional and other jump instructions. | |
1186 | |
1187 (define_insn "jump" | |
1188 [(set (pc) | |
1189 (label_ref (match_operand 0 "" "")))] | |
1190 "" | |
1191 "* | |
1192 { | |
1193 if (get_attr_length (insn) == 2) | |
1194 return \"br %0\"; | |
1195 else | |
1196 return \"jr %0\"; | |
1197 }" | |
1198 [(set (attr "length") | |
1199 (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
1200 (const_int 256)) | |
1201 (const_int 2) | |
1202 (const_int 4))) | |
1203 (set_attr "cc" "none")]) | |
1204 | |
1205 (define_insn "indirect_jump" | |
1206 [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
1207 "" | |
1208 "jmp %0" | |
1209 [(set_attr "length" "2") | |
1210 (set_attr "cc" "none")]) | |
1211 | |
1212 (define_insn "tablejump" | |
1213 [(set (pc) (match_operand:SI 0 "register_operand" "r")) | |
1214 (use (label_ref (match_operand 1 "" "")))] | |
1215 "" | |
1216 "jmp %0" | |
1217 [(set_attr "length" "2") | |
1218 (set_attr "cc" "none")]) | |
1219 | |
1220 (define_insn "switch" | |
1221 [(set (pc) | |
1222 (plus:SI | |
1223 (sign_extend:SI | |
1224 (mem:HI | |
1225 (plus:SI (ashift:SI (match_operand:SI 0 "register_operand" "r") | |
1226 (const_int 1)) | |
1227 (label_ref (match_operand 1 "" ""))))) | |
1228 (label_ref (match_dup 1))))] | |
1229 "TARGET_V850E" | |
1230 "switch %0" | |
1231 [(set_attr "length" "2") | |
1232 (set_attr "cc" "none")]) | |
1233 | |
1234 (define_expand "casesi" | |
1235 [(match_operand:SI 0 "register_operand" "") | |
1236 (match_operand:SI 1 "register_operand" "") | |
1237 (match_operand:SI 2 "register_operand" "") | |
1238 (match_operand 3 "" "") (match_operand 4 "" "")] | |
1239 "" | |
1240 " | |
1241 { | |
1242 rtx reg = gen_reg_rtx (SImode); | |
1243 rtx tableaddress = gen_reg_rtx (SImode); | |
1244 rtx mem; | |
1245 | |
1246 /* Subtract the lower bound from the index. */ | |
1247 emit_insn (gen_subsi3 (reg, operands[0], operands[1])); | |
1248 /* Compare the result against the number of table entries. */ | |
1249 emit_insn (gen_cmpsi (reg, operands[2])); | |
1250 /* Branch to the default label if out of range of the table. */ | |
1251 emit_jump_insn (gen_bgtu (operands[4])); | |
1252 | |
1253 /* Shift index for the table array access. */ | |
1254 emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1))); | |
1255 /* Load the table address into a pseudo. */ | |
1256 emit_insn (gen_movsi (tableaddress, | |
1257 gen_rtx_LABEL_REF (Pmode, operands[3]))); | |
1258 /* Add the table address to the index. */ | |
1259 emit_insn (gen_addsi3 (reg, reg, tableaddress)); | |
1260 /* Load the table entry. */ | |
1261 mem = gen_const_mem (CASE_VECTOR_MODE, reg); | |
1262 if (! TARGET_BIG_SWITCH) | |
1263 { | |
1264 rtx reg2 = gen_reg_rtx (HImode); | |
1265 emit_insn (gen_movhi (reg2, mem)); | |
1266 emit_insn (gen_extendhisi2 (reg, reg2)); | |
1267 } | |
1268 else | |
1269 emit_insn (gen_movsi (reg, mem)); | |
1270 /* Add the table address. */ | |
1271 emit_insn (gen_addsi3 (reg, reg, tableaddress)); | |
1272 /* Branch to the switch label. */ | |
1273 emit_jump_insn (gen_tablejump (reg, operands[3])); | |
1274 DONE; | |
1275 }") | |
1276 | |
1277 ;; Call subroutine with no return value. | |
1278 | |
1279 (define_expand "call" | |
1280 [(call (match_operand:QI 0 "general_operand" "") | |
1281 (match_operand:SI 1 "general_operand" ""))] | |
1282 "" | |
1283 " | |
1284 { | |
1285 if (! call_address_operand (XEXP (operands[0], 0), QImode) | |
1286 || TARGET_LONG_CALLS) | |
1287 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); | |
1288 if (TARGET_LONG_CALLS) | |
1289 emit_call_insn (gen_call_internal_long (XEXP (operands[0], 0), operands[1])); | |
1290 else | |
1291 emit_call_insn (gen_call_internal_short (XEXP (operands[0], 0), operands[1])); | |
1292 | |
1293 DONE; | |
1294 }") | |
1295 | |
1296 (define_insn "call_internal_short" | |
1297 [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) | |
1298 (match_operand:SI 1 "general_operand" "g,g")) | |
1299 (clobber (reg:SI 31))] | |
1300 "! TARGET_LONG_CALLS" | |
1301 "@ | |
1302 jarl %0,r31 | |
1303 jarl .+4,r31 ; add 4,r31 ; jmp %0" | |
1304 [(set_attr "length" "4,8")] | |
1305 ) | |
1306 | |
1307 (define_insn "call_internal_long" | |
1308 [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) | |
1309 (match_operand:SI 1 "general_operand" "g,g")) | |
1310 (clobber (reg:SI 31))] | |
1311 "TARGET_LONG_CALLS" | |
1312 "* | |
1313 { | |
1314 if (which_alternative == 0) | |
1315 { | |
1316 if (GET_CODE (operands[0]) == REG) | |
1317 return \"jarl %0,r31\"; | |
1318 else | |
1319 return \"movhi hi(%0), r0, r11 ; movea lo(%0), r11, r11 ; jarl .+4,r31 ; add 4, r31 ; jmp r11\"; | |
1320 } | |
1321 else | |
1322 return \"jarl .+4,r31 ; add 4,r31 ; jmp %0\"; | |
1323 }" | |
1324 [(set_attr "length" "16,8")] | |
1325 ) | |
1326 | |
1327 ;; Call subroutine, returning value in operand 0 | |
1328 ;; (which must be a hard register). | |
1329 | |
1330 (define_expand "call_value" | |
1331 [(set (match_operand 0 "" "") | |
1332 (call (match_operand:QI 1 "general_operand" "") | |
1333 (match_operand:SI 2 "general_operand" "")))] | |
1334 "" | |
1335 " | |
1336 { | |
1337 if (! call_address_operand (XEXP (operands[1], 0), QImode) | |
1338 || TARGET_LONG_CALLS) | |
1339 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); | |
1340 if (TARGET_LONG_CALLS) | |
1341 emit_call_insn (gen_call_value_internal_long (operands[0], | |
1342 XEXP (operands[1], 0), | |
1343 operands[2])); | |
1344 else | |
1345 emit_call_insn (gen_call_value_internal_short (operands[0], | |
1346 XEXP (operands[1], 0), | |
1347 operands[2])); | |
1348 DONE; | |
1349 }") | |
1350 | |
1351 (define_insn "call_value_internal_short" | |
1352 [(set (match_operand 0 "" "=r,r") | |
1353 (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) | |
1354 (match_operand:SI 2 "general_operand" "g,g"))) | |
1355 (clobber (reg:SI 31))] | |
1356 "! TARGET_LONG_CALLS" | |
1357 "@ | |
1358 jarl %1,r31 | |
1359 jarl .+4,r31 ; add 4,r31 ; jmp %1" | |
1360 [(set_attr "length" "4,8")] | |
1361 ) | |
1362 | |
1363 (define_insn "call_value_internal_long" | |
1364 [(set (match_operand 0 "" "=r,r") | |
1365 (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) | |
1366 (match_operand:SI 2 "general_operand" "g,g"))) | |
1367 (clobber (reg:SI 31))] | |
1368 "TARGET_LONG_CALLS" | |
1369 "* | |
1370 { | |
1371 if (which_alternative == 0) | |
1372 { | |
1373 if (GET_CODE (operands[1]) == REG) | |
1374 return \"jarl %1, r31\"; | |
1375 else | |
1376 /* Reload can generate this pattern.... */ | |
1377 return \"movhi hi(%1), r0, r11 ; movea lo(%1), r11, r11 ; jarl .+4, r31 ; add 4, r31 ; jmp r11\"; | |
1378 } | |
1379 else | |
1380 return \"jarl .+4, r31 ; add 4, r31 ; jmp %1\"; | |
1381 }" | |
1382 [(set_attr "length" "16,8")] | |
1383 ) | |
1384 | |
1385 (define_insn "nop" | |
1386 [(const_int 0)] | |
1387 "" | |
1388 "nop" | |
1389 [(set_attr "length" "2") | |
1390 (set_attr "cc" "none")]) | |
1391 | |
1392 ;; ---------------------------------------------------------------------- | |
1393 ;; EXTEND INSTRUCTIONS | |
1394 ;; ---------------------------------------------------------------------- | |
1395 | |
1396 (define_insn "" | |
1397 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") | |
1398 (zero_extend:SI | |
1399 (match_operand:HI 1 "nonimmediate_operand" "0,r,T,m")))] | |
1400 "TARGET_V850E" | |
1401 "@ | |
1402 zxh %0 | |
1403 andi 65535,%1,%0 | |
1404 sld.hu %1,%0 | |
1405 ld.hu %1,%0" | |
1406 [(set_attr "length" "2,4,2,4") | |
1407 (set_attr "cc" "none_0hit,set_znv,none_0hit,none_0hit")]) | |
1408 | |
1409 (define_insn "zero_extendhisi2" | |
1410 [(set (match_operand:SI 0 "register_operand" "=r") | |
1411 (zero_extend:SI | |
1412 (match_operand:HI 1 "register_operand" "r")))] | |
1413 "" | |
1414 "andi 65535,%1,%0" | |
1415 [(set_attr "length" "4") | |
1416 (set_attr "cc" "set_znv")]) | |
1417 | |
1418 (define_insn "" | |
1419 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") | |
1420 (zero_extend:SI | |
1421 (match_operand:QI 1 "nonimmediate_operand" "0,r,T,m")))] | |
1422 "TARGET_V850E" | |
1423 "@ | |
1424 zxb %0 | |
1425 andi 255,%1,%0 | |
1426 sld.bu %1,%0 | |
1427 ld.bu %1,%0" | |
1428 [(set_attr "length" "2,4,2,4") | |
1429 (set_attr "cc" "none_0hit,set_znv,none_0hit,none_0hit")]) | |
1430 | |
1431 (define_insn "zero_extendqisi2" | |
1432 [(set (match_operand:SI 0 "register_operand" "=r") | |
1433 (zero_extend:SI | |
1434 (match_operand:QI 1 "register_operand" "r")))] | |
1435 "" | |
1436 "andi 255,%1,%0" | |
1437 [(set_attr "length" "4") | |
1438 (set_attr "cc" "set_znv")]) | |
1439 | |
1440 ;;- sign extension instructions | |
1441 | |
1442 ;; ??? The extendhisi2 pattern should not emit shifts for v850e? | |
1443 | |
1444 (define_insn "*extendhisi_insn" | |
1445 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1446 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))] | |
1447 "TARGET_V850E" | |
1448 "@ | |
1449 sxh %0 | |
1450 sld.h %1,%0 | |
1451 ld.h %1,%0" | |
1452 [(set_attr "length" "2,2,4") | |
1453 (set_attr "cc" "none_0hit,none_0hit,none_0hit")]) | |
1454 | |
1455 ;; ??? This is missing a sign extend from memory pattern to match the ld.h | |
1456 ;; instruction. | |
1457 | |
1458 (define_expand "extendhisi2" | |
1459 [(set (match_dup 2) | |
1460 (ashift:SI (match_operand:HI 1 "register_operand" "") | |
1461 (const_int 16))) | |
1462 (set (match_operand:SI 0 "register_operand" "") | |
1463 (ashiftrt:SI (match_dup 2) | |
1464 (const_int 16)))] | |
1465 "" | |
1466 " | |
1467 { | |
1468 operands[1] = gen_lowpart (SImode, operands[1]); | |
1469 operands[2] = gen_reg_rtx (SImode); | |
1470 }") | |
1471 | |
1472 ;; ??? The extendqisi2 pattern should not emit shifts for v850e? | |
1473 | |
1474 (define_insn "*extendqisi_insn" | |
1475 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1476 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))] | |
1477 "TARGET_V850E" | |
1478 "@ | |
1479 sxb %0 | |
1480 sld.b %1,%0 | |
1481 ld.b %1,%0" | |
1482 [(set_attr "length" "2,2,4") | |
1483 (set_attr "cc" "none_0hit,none_0hit,none_0hit")]) | |
1484 | |
1485 ;; ??? This is missing a sign extend from memory pattern to match the ld.b | |
1486 ;; instruction. | |
1487 | |
1488 (define_expand "extendqisi2" | |
1489 [(set (match_dup 2) | |
1490 (ashift:SI (match_operand:QI 1 "register_operand" "") | |
1491 (const_int 24))) | |
1492 (set (match_operand:SI 0 "register_operand" "") | |
1493 (ashiftrt:SI (match_dup 2) | |
1494 (const_int 24)))] | |
1495 "" | |
1496 " | |
1497 { | |
1498 operands[1] = gen_lowpart (SImode, operands[1]); | |
1499 operands[2] = gen_reg_rtx (SImode); | |
1500 }") | |
1501 | |
1502 ;; ---------------------------------------------------------------------- | |
1503 ;; SHIFTS | |
1504 ;; ---------------------------------------------------------------------- | |
1505 | |
1506 (define_insn "ashlsi3" | |
1507 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1508 (ashift:SI | |
1509 (match_operand:SI 1 "register_operand" "0,0") | |
1510 (match_operand:SI 2 "nonmemory_operand" "r,N")))] | |
1511 "" | |
1512 "@ | |
1513 shl %2,%0 | |
1514 shl %2,%0" | |
1515 [(set_attr "length" "4,2") | |
1516 (set_attr "cc" "set_znv")]) | |
1517 | |
1518 (define_insn "lshrsi3" | |
1519 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1520 (lshiftrt:SI | |
1521 (match_operand:SI 1 "register_operand" "0,0") | |
1522 (match_operand:SI 2 "nonmemory_operand" "r,N")))] | |
1523 "" | |
1524 "@ | |
1525 shr %2,%0 | |
1526 shr %2,%0" | |
1527 [(set_attr "length" "4,2") | |
1528 (set_attr "cc" "set_znv")]) | |
1529 | |
1530 (define_insn "ashrsi3" | |
1531 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1532 (ashiftrt:SI | |
1533 (match_operand:SI 1 "register_operand" "0,0") | |
1534 (match_operand:SI 2 "nonmemory_operand" "r,N")))] | |
1535 "" | |
1536 "@ | |
1537 sar %2,%0 | |
1538 sar %2,%0" | |
1539 [(set_attr "length" "4,2") | |
1540 (set_attr "cc" "set_znv")]) | |
1541 | |
1542 ;; ---------------------------------------------------------------------- | |
1543 ;; PROLOGUE/EPILOGUE | |
1544 ;; ---------------------------------------------------------------------- | |
1545 (define_expand "prologue" | |
1546 [(const_int 0)] | |
1547 "" | |
1548 "expand_prologue (); DONE;") | |
1549 | |
1550 (define_expand "epilogue" | |
1551 [(return)] | |
1552 "" | |
1553 " | |
1554 { | |
1555 /* Try to use the trivial return first. Else use the | |
1556 full epilogue. */ | |
1557 if (0) | |
1558 emit_jump_insn (gen_return ()); | |
1559 else | |
1560 expand_epilogue (); | |
1561 DONE; | |
1562 }") | |
1563 | |
1564 (define_insn "return" | |
1565 [(return)] | |
1566 "reload_completed && compute_frame_size (get_frame_size (), (long *)0) == 0" | |
1567 "jmp [r31]" | |
1568 [(set_attr "length" "2") | |
1569 (set_attr "cc" "none")]) | |
1570 | |
1571 (define_insn "return_internal" | |
1572 [(return) | |
1573 (use (reg:SI 31))] | |
1574 "" | |
1575 "jmp [r31]" | |
1576 [(set_attr "length" "2") | |
1577 (set_attr "cc" "none")]) | |
1578 | |
1579 | |
1580 | |
1581 ;; ---------------------------------------------------------------------- | |
1582 ;; HELPER INSTRUCTIONS for saving the prologue and epilogue registers | |
1583 ;; ---------------------------------------------------------------------- | |
1584 | |
1585 ;; This pattern will match a stack adjust RTX followed by any number of push | |
1586 ;; RTXs. These RTXs will then be turned into a suitable call to a worker | |
1587 ;; function. | |
1588 | |
1589 ;; | |
1590 ;; Actually, convert the RTXs into a PREPARE instruction. | |
1591 ;; | |
1592 (define_insn "" | |
1593 [(match_parallel 0 "pattern_is_ok_for_prepare" | |
1594 [(set (reg:SI 3) | |
1595 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
1596 (set (mem:SI (plus:SI (reg:SI 3) | |
1597 (match_operand:SI 2 "immediate_operand" "i"))) | |
1598 (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])] | |
1599 "TARGET_PROLOG_FUNCTION && TARGET_V850E" | |
1600 "* return construct_prepare_instruction (operands[0]); | |
1601 " | |
1602 [(set_attr "length" "4") | |
1603 (set_attr "cc" "none")]) | |
1604 | |
1605 (define_insn "" | |
1606 [(match_parallel 0 "pattern_is_ok_for_prologue" | |
1607 [(set (reg:SI 3) | |
1608 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
1609 (set (mem:SI (plus:SI (reg:SI 3) | |
1610 (match_operand:SI 2 "immediate_operand" "i"))) | |
1611 (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])] | |
1612 "TARGET_PROLOG_FUNCTION && TARGET_V850" | |
1613 "* return construct_save_jarl (operands[0]); | |
1614 " | |
1615 [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes") | |
1616 (const_string "16") | |
1617 (const_string "4"))) | |
1618 (set_attr "cc" "clobber")]) | |
1619 | |
1620 ;; | |
1621 ;; Actually, turn the RTXs into a DISPOSE instruction. | |
1622 ;; | |
1623 (define_insn "" | |
1624 [(match_parallel 0 "pattern_is_ok_for_dispose" | |
1625 [(return) | |
1626 (set (reg:SI 3) | |
1627 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
1628 (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r") | |
1629 (mem:SI (plus:SI (reg:SI 3) | |
1630 (match_operand:SI 3 "immediate_operand" "i"))))])] | |
1631 "TARGET_PROLOG_FUNCTION && TARGET_V850E" | |
1632 "* return construct_dispose_instruction (operands[0]); | |
1633 " | |
1634 [(set_attr "length" "4") | |
1635 (set_attr "cc" "none")]) | |
1636 | |
1637 ;; This pattern will match a return RTX followed by any number of pop RTXs | |
1638 ;; and possible a stack adjustment as well. These RTXs will be turned into | |
1639 ;; a suitable call to a worker function. | |
1640 | |
1641 (define_insn "" | |
1642 [(match_parallel 0 "pattern_is_ok_for_epilogue" | |
1643 [(return) | |
1644 (set (reg:SI 3) | |
1645 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
1646 (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r") | |
1647 (mem:SI (plus:SI (reg:SI 3) | |
1648 (match_operand:SI 3 "immediate_operand" "i"))))])] | |
1649 "TARGET_PROLOG_FUNCTION && TARGET_V850" | |
1650 "* return construct_restore_jr (operands[0]); | |
1651 " | |
1652 [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes") | |
1653 (const_string "12") | |
1654 (const_string "4"))) | |
1655 (set_attr "cc" "clobber")]) | |
1656 | |
1657 ;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION. | |
1658 (define_insn "callt_save_interrupt" | |
1659 [(unspec_volatile [(const_int 0)] 2)] | |
1660 "TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1661 ;; The CALLT instruction stores the next address of CALLT to CTPC register | |
1662 ;; without saving its previous value. So if the interrupt handler | |
1663 ;; or its caller could possibly execute the CALLT insn, save_interrupt | |
1664 ;; MUST NOT be called via CALLT. | |
1665 "* | |
1666 { | |
1667 output_asm_insn (\"addi -24, sp, sp\", operands); | |
1668 output_asm_insn (\"st.w r10, 12[sp]\", operands); | |
1669 output_asm_insn (\"stsr ctpc, r10\", operands); | |
1670 output_asm_insn (\"st.w r10, 16[sp]\", operands); | |
1671 output_asm_insn (\"stsr ctpsw, r10\", operands); | |
1672 output_asm_insn (\"st.w r10, 20[sp]\", operands); | |
1673 output_asm_insn (\"callt ctoff(__callt_save_interrupt)\", operands); | |
1674 return \"\"; | |
1675 }" | |
1676 [(set_attr "length" "26") | |
1677 (set_attr "cc" "none")]) | |
1678 | |
1679 (define_insn "callt_return_interrupt" | |
1680 [(unspec_volatile [(const_int 0)] 3)] | |
1681 "TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1682 "callt ctoff(__callt_return_interrupt)" | |
1683 [(set_attr "length" "2") | |
1684 (set_attr "cc" "clobber")]) | |
1685 | |
1686 (define_insn "save_interrupt" | |
1687 [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -16))) | |
1688 (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 30)) | |
1689 (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 4)) | |
1690 (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 1)) | |
1691 (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 10))] | |
1692 "" | |
1693 "* | |
1694 { | |
1695 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
1696 return \"add -16,sp\;st.w r10,12[sp]\;jarl __save_interrupt,r10\"; | |
1697 else | |
1698 { | |
1699 output_asm_insn (\"add -16, sp\", operands); | |
1700 output_asm_insn (\"st.w r10, 12[sp]\", operands); | |
1701 output_asm_insn (\"st.w ep, 0[sp]\", operands); | |
1702 output_asm_insn (\"st.w gp, 4[sp]\", operands); | |
1703 output_asm_insn (\"st.w r1, 8[sp]\", operands); | |
1704 output_asm_insn (\"movhi hi(__ep), r0, ep\", operands); | |
1705 output_asm_insn (\"movea lo(__ep), ep, ep\", operands); | |
1706 output_asm_insn (\"movhi hi(__gp), r0, gp\", operands); | |
1707 output_asm_insn (\"movea lo(__gp), gp, gp\", operands); | |
1708 return \"\"; | |
1709 } | |
1710 }" | |
1711 [(set (attr "length") | |
1712 (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0)) | |
1713 (const_int 10) | |
1714 (const_int 34))) | |
1715 (set_attr "cc" "clobber")]) | |
1716 | |
1717 ;; Restore r1, r4, r10, and return from the interrupt | |
1718 (define_insn "return_interrupt" | |
1719 [(return) | |
1720 (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 16))) | |
1721 (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 12)))) | |
1722 (set (reg:SI 1) (mem:SI (plus:SI (reg:SI 3) (const_int 8)))) | |
1723 (set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4)))) | |
1724 (set (reg:SI 30) (mem:SI (reg:SI 3)))] | |
1725 "" | |
1726 "* | |
1727 { | |
1728 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
1729 return \"jr __return_interrupt\"; | |
1730 else | |
1731 { | |
1732 output_asm_insn (\"ld.w 0[sp], ep\", operands); | |
1733 output_asm_insn (\"ld.w 4[sp], gp\", operands); | |
1734 output_asm_insn (\"ld.w 8[sp], r1\", operands); | |
1735 output_asm_insn (\"ld.w 12[sp], r10\", operands); | |
1736 output_asm_insn (\"addi 16, sp, sp\", operands); | |
1737 output_asm_insn (\"reti\", operands); | |
1738 return \"\"; | |
1739 } | |
1740 }" | |
1741 [(set (attr "length") | |
1742 (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0)) | |
1743 (const_int 4) | |
1744 (const_int 24))) | |
1745 (set_attr "cc" "clobber")]) | |
1746 | |
1747 ;; Save all registers except for the registers saved in save_interrupt when | |
1748 ;; an interrupt function makes a call. | |
1749 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and | |
1750 ;; all of memory. This blocks insns from being moved across this point. | |
1751 ;; This is needed because the rest of the compiler is not ready to handle | |
1752 ;; insns this complicated. | |
1753 | |
1754 (define_insn "callt_save_all_interrupt" | |
1755 [(unspec_volatile [(const_int 0)] 0)] | |
1756 "TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1757 "callt ctoff(__callt_save_all_interrupt)" | |
1758 [(set_attr "length" "2") | |
1759 (set_attr "cc" "none")]) | |
1760 | |
1761 (define_insn "save_all_interrupt" | |
1762 [(unspec_volatile [(const_int 0)] 0)] | |
1763 "" | |
1764 "* | |
1765 { | |
1766 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
1767 return \"jarl __save_all_interrupt,r10\"; | |
1768 | |
1769 output_asm_insn (\"addi -120, sp, sp\", operands); | |
1770 | |
1771 if (TARGET_EP) | |
1772 { | |
1773 output_asm_insn (\"mov ep, r1\", operands); | |
1774 output_asm_insn (\"mov sp, ep\", operands); | |
1775 output_asm_insn (\"sst.w r31, 116[ep]\", operands); | |
1776 output_asm_insn (\"sst.w r2, 112[ep]\", operands); | |
1777 output_asm_insn (\"sst.w gp, 108[ep]\", operands); | |
1778 output_asm_insn (\"sst.w r6, 104[ep]\", operands); | |
1779 output_asm_insn (\"sst.w r7, 100[ep]\", operands); | |
1780 output_asm_insn (\"sst.w r8, 96[ep]\", operands); | |
1781 output_asm_insn (\"sst.w r9, 92[ep]\", operands); | |
1782 output_asm_insn (\"sst.w r11, 88[ep]\", operands); | |
1783 output_asm_insn (\"sst.w r12, 84[ep]\", operands); | |
1784 output_asm_insn (\"sst.w r13, 80[ep]\", operands); | |
1785 output_asm_insn (\"sst.w r14, 76[ep]\", operands); | |
1786 output_asm_insn (\"sst.w r15, 72[ep]\", operands); | |
1787 output_asm_insn (\"sst.w r16, 68[ep]\", operands); | |
1788 output_asm_insn (\"sst.w r17, 64[ep]\", operands); | |
1789 output_asm_insn (\"sst.w r18, 60[ep]\", operands); | |
1790 output_asm_insn (\"sst.w r19, 56[ep]\", operands); | |
1791 output_asm_insn (\"sst.w r20, 52[ep]\", operands); | |
1792 output_asm_insn (\"sst.w r21, 48[ep]\", operands); | |
1793 output_asm_insn (\"sst.w r22, 44[ep]\", operands); | |
1794 output_asm_insn (\"sst.w r23, 40[ep]\", operands); | |
1795 output_asm_insn (\"sst.w r24, 36[ep]\", operands); | |
1796 output_asm_insn (\"sst.w r25, 32[ep]\", operands); | |
1797 output_asm_insn (\"sst.w r26, 28[ep]\", operands); | |
1798 output_asm_insn (\"sst.w r27, 24[ep]\", operands); | |
1799 output_asm_insn (\"sst.w r28, 20[ep]\", operands); | |
1800 output_asm_insn (\"sst.w r29, 16[ep]\", operands); | |
1801 output_asm_insn (\"mov r1, ep\", operands); | |
1802 } | |
1803 else | |
1804 { | |
1805 output_asm_insn (\"st.w r31, 116[sp]\", operands); | |
1806 output_asm_insn (\"st.w r2, 112[sp]\", operands); | |
1807 output_asm_insn (\"st.w gp, 108[sp]\", operands); | |
1808 output_asm_insn (\"st.w r6, 104[sp]\", operands); | |
1809 output_asm_insn (\"st.w r7, 100[sp]\", operands); | |
1810 output_asm_insn (\"st.w r8, 96[sp]\", operands); | |
1811 output_asm_insn (\"st.w r9, 92[sp]\", operands); | |
1812 output_asm_insn (\"st.w r11, 88[sp]\", operands); | |
1813 output_asm_insn (\"st.w r12, 84[sp]\", operands); | |
1814 output_asm_insn (\"st.w r13, 80[sp]\", operands); | |
1815 output_asm_insn (\"st.w r14, 76[sp]\", operands); | |
1816 output_asm_insn (\"st.w r15, 72[sp]\", operands); | |
1817 output_asm_insn (\"st.w r16, 68[sp]\", operands); | |
1818 output_asm_insn (\"st.w r17, 64[sp]\", operands); | |
1819 output_asm_insn (\"st.w r18, 60[sp]\", operands); | |
1820 output_asm_insn (\"st.w r19, 56[sp]\", operands); | |
1821 output_asm_insn (\"st.w r20, 52[sp]\", operands); | |
1822 output_asm_insn (\"st.w r21, 48[sp]\", operands); | |
1823 output_asm_insn (\"st.w r22, 44[sp]\", operands); | |
1824 output_asm_insn (\"st.w r23, 40[sp]\", operands); | |
1825 output_asm_insn (\"st.w r24, 36[sp]\", operands); | |
1826 output_asm_insn (\"st.w r25, 32[sp]\", operands); | |
1827 output_asm_insn (\"st.w r26, 28[sp]\", operands); | |
1828 output_asm_insn (\"st.w r27, 24[sp]\", operands); | |
1829 output_asm_insn (\"st.w r28, 20[sp]\", operands); | |
1830 output_asm_insn (\"st.w r29, 16[sp]\", operands); | |
1831 } | |
1832 | |
1833 return \"\"; | |
1834 }" | |
1835 [(set (attr "length") | |
1836 (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0)) | |
1837 (const_int 4) | |
1838 (const_int 62) | |
1839 )) | |
1840 (set_attr "cc" "clobber")]) | |
1841 | |
1842 (define_insn "_save_all_interrupt" | |
1843 [(unspec_volatile [(const_int 0)] 0)] | |
1844 "TARGET_V850 && ! TARGET_LONG_CALLS" | |
1845 "jarl __save_all_interrupt,r10" | |
1846 [(set_attr "length" "4") | |
1847 (set_attr "cc" "clobber")]) | |
1848 | |
1849 ;; Restore all registers saved when an interrupt function makes a call. | |
1850 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and | |
1851 ;; all of memory. This blocks insns from being moved across this point. | |
1852 ;; This is needed because the rest of the compiler is not ready to handle | |
1853 ;; insns this complicated. | |
1854 | |
1855 (define_insn "callt_restore_all_interrupt" | |
1856 [(unspec_volatile [(const_int 0)] 1)] | |
1857 "TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1858 "callt ctoff(__callt_restore_all_interrupt)" | |
1859 [(set_attr "length" "2") | |
1860 (set_attr "cc" "none")]) | |
1861 | |
1862 (define_insn "restore_all_interrupt" | |
1863 [(unspec_volatile [(const_int 0)] 1)] | |
1864 "" | |
1865 "* | |
1866 { | |
1867 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
1868 return \"jarl __restore_all_interrupt,r10\"; | |
1869 | |
1870 if (TARGET_EP) | |
1871 { | |
1872 output_asm_insn (\"mov ep, r1\", operands); | |
1873 output_asm_insn (\"mov sp, ep\", operands); | |
1874 output_asm_insn (\"sld.w 116[ep], r31\", operands); | |
1875 output_asm_insn (\"sld.w 112[ep], r2\", operands); | |
1876 output_asm_insn (\"sld.w 108[ep], gp\", operands); | |
1877 output_asm_insn (\"sld.w 104[ep], r6\", operands); | |
1878 output_asm_insn (\"sld.w 100[ep], r7\", operands); | |
1879 output_asm_insn (\"sld.w 96[ep], r8\", operands); | |
1880 output_asm_insn (\"sld.w 92[ep], r9\", operands); | |
1881 output_asm_insn (\"sld.w 88[ep], r11\", operands); | |
1882 output_asm_insn (\"sld.w 84[ep], r12\", operands); | |
1883 output_asm_insn (\"sld.w 80[ep], r13\", operands); | |
1884 output_asm_insn (\"sld.w 76[ep], r14\", operands); | |
1885 output_asm_insn (\"sld.w 72[ep], r15\", operands); | |
1886 output_asm_insn (\"sld.w 68[ep], r16\", operands); | |
1887 output_asm_insn (\"sld.w 64[ep], r17\", operands); | |
1888 output_asm_insn (\"sld.w 60[ep], r18\", operands); | |
1889 output_asm_insn (\"sld.w 56[ep], r19\", operands); | |
1890 output_asm_insn (\"sld.w 52[ep], r20\", operands); | |
1891 output_asm_insn (\"sld.w 48[ep], r21\", operands); | |
1892 output_asm_insn (\"sld.w 44[ep], r22\", operands); | |
1893 output_asm_insn (\"sld.w 40[ep], r23\", operands); | |
1894 output_asm_insn (\"sld.w 36[ep], r24\", operands); | |
1895 output_asm_insn (\"sld.w 32[ep], r25\", operands); | |
1896 output_asm_insn (\"sld.w 28[ep], r26\", operands); | |
1897 output_asm_insn (\"sld.w 24[ep], r27\", operands); | |
1898 output_asm_insn (\"sld.w 20[ep], r28\", operands); | |
1899 output_asm_insn (\"sld.w 16[ep], r29\", operands); | |
1900 output_asm_insn (\"mov r1, ep\", operands); | |
1901 } | |
1902 else | |
1903 { | |
1904 output_asm_insn (\"ld.w 116[sp], r31\", operands); | |
1905 output_asm_insn (\"ld.w 112[sp], r2\", operands); | |
1906 output_asm_insn (\"ld.w 108[sp], gp\", operands); | |
1907 output_asm_insn (\"ld.w 104[sp], r6\", operands); | |
1908 output_asm_insn (\"ld.w 100[sp], r7\", operands); | |
1909 output_asm_insn (\"ld.w 96[sp], r8\", operands); | |
1910 output_asm_insn (\"ld.w 92[sp], r9\", operands); | |
1911 output_asm_insn (\"ld.w 88[sp], r11\", operands); | |
1912 output_asm_insn (\"ld.w 84[sp], r12\", operands); | |
1913 output_asm_insn (\"ld.w 80[sp], r13\", operands); | |
1914 output_asm_insn (\"ld.w 76[sp], r14\", operands); | |
1915 output_asm_insn (\"ld.w 72[sp], r15\", operands); | |
1916 output_asm_insn (\"ld.w 68[sp], r16\", operands); | |
1917 output_asm_insn (\"ld.w 64[sp], r17\", operands); | |
1918 output_asm_insn (\"ld.w 60[sp], r18\", operands); | |
1919 output_asm_insn (\"ld.w 56[sp], r19\", operands); | |
1920 output_asm_insn (\"ld.w 52[sp], r20\", operands); | |
1921 output_asm_insn (\"ld.w 48[sp], r21\", operands); | |
1922 output_asm_insn (\"ld.w 44[sp], r22\", operands); | |
1923 output_asm_insn (\"ld.w 40[sp], r23\", operands); | |
1924 output_asm_insn (\"ld.w 36[sp], r24\", operands); | |
1925 output_asm_insn (\"ld.w 32[sp], r25\", operands); | |
1926 output_asm_insn (\"ld.w 28[sp], r26\", operands); | |
1927 output_asm_insn (\"ld.w 24[sp], r27\", operands); | |
1928 output_asm_insn (\"ld.w 20[sp], r28\", operands); | |
1929 output_asm_insn (\"ld.w 16[sp], r29\", operands); | |
1930 } | |
1931 output_asm_insn (\"addi 120, sp, sp\", operands); | |
1932 return \"\"; | |
1933 }" | |
1934 [(set (attr "length") | |
1935 (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0)) | |
1936 (const_int 4) | |
1937 (const_int 62) | |
1938 )) | |
1939 (set_attr "cc" "clobber")]) | |
1940 | |
1941 (define_insn "_restore_all_interrupt" | |
1942 [(unspec_volatile [(const_int 0)] 1)] | |
1943 "TARGET_V850 && ! TARGET_LONG_CALLS" | |
1944 "jarl __restore_all_interrupt,r10" | |
1945 [(set_attr "length" "4") | |
1946 (set_attr "cc" "clobber")]) | |
1947 | |
1948 ;; Save r6-r9 for a variable argument function | |
1949 (define_insn "save_r6_r9_v850e" | |
1950 [(set (mem:SI (reg:SI 3)) (reg:SI 6)) | |
1951 (set (mem:SI (plus:SI (reg:SI 3) (const_int 4))) (reg:SI 7)) | |
1952 (set (mem:SI (plus:SI (reg:SI 3) (const_int 8))) (reg:SI 8)) | |
1953 (set (mem:SI (plus:SI (reg:SI 3) (const_int 12))) (reg:SI 9)) | |
1954 ] | |
1955 "TARGET_PROLOG_FUNCTION && TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1956 "callt ctoff(__callt_save_r6_r9)" | |
1957 [(set_attr "length" "2") | |
1958 (set_attr "cc" "none")]) | |
1959 | |
1960 (define_insn "save_r6_r9" | |
1961 [(set (mem:SI (reg:SI 3)) (reg:SI 6)) | |
1962 (set (mem:SI (plus:SI (reg:SI 3) (const_int 4))) (reg:SI 7)) | |
1963 (set (mem:SI (plus:SI (reg:SI 3) (const_int 8))) (reg:SI 8)) | |
1964 (set (mem:SI (plus:SI (reg:SI 3) (const_int 12))) (reg:SI 9)) | |
1965 (clobber (reg:SI 10))] | |
1966 "TARGET_PROLOG_FUNCTION && ! TARGET_LONG_CALLS" | |
1967 "jarl __save_r6_r9,r10" | |
1968 [(set_attr "length" "4") | |
1969 (set_attr "cc" "clobber")]) | |
1970 |