Mercurial > hg > CbC > CbC_gcc
annotate gcc/config/v850/v850.md @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | f6334be47118 |
rev | line source |
---|---|
0 | 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" | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
230 [(set (cc0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
231 (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
232 (const_int 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
233 (match_operand:QI 1 "const_int_operand" "n")) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
234 (const_int 0)))] |
0 | 235 "" |
236 "tst1 %1,%0" | |
237 [(set_attr "length" "4") | |
238 (set_attr "cc" "clobber")]) | |
239 | |
240 ;; This replaces ld.b;sar;andi with tst1;setf nz. | |
241 | |
242 (define_split | |
243 [(set (match_operand:SI 0 "register_operand" "") | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
244 (compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
245 (const_int 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
246 (match_operand 2 "const_int_operand" "")) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
247 (const_int 0)))] |
0 | 248 "" |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
249 [(set (cc0) (compare (zero_extract:SI (match_dup 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
250 (const_int 1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
251 (match_dup 2)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
252 (const_int 0))) |
0 | 253 (set (match_dup 0) (ne:SI (cc0) (const_int 0)))]) |
254 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
255 (define_expand "cbranchsi4" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
256 [(set (cc0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
257 (compare (match_operand:SI 1 "register_operand" "") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
258 (match_operand:SI 2 "reg_or_int5_operand" ""))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
259 (set (pc) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
260 (if_then_else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
261 (match_operator 0 "ordered_comparison_operator" [(cc0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
262 (const_int 0)]) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
263 (label_ref (match_operand 3 "" "")) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
264 (pc)))] |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
265 "") |
0 | 266 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
267 (define_expand "cstoresi4" |
0 | 268 [(set (cc0) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
269 (compare (match_operand:SI 2 "register_operand" "") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
270 (match_operand:SI 3 "reg_or_int5_operand" ""))) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
271 (set (match_operand:SI 0 "register_operand") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
272 (match_operator:SI 1 "ordered_comparison_operator" [(cc0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
273 (const_int 0)]))] |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
274 "") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
275 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
276 (define_insn "*cmpsi" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
277 [(set (cc0) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
278 (compare (match_operand:SI 0 "register_operand" "r,r,r") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
279 (match_operand:SI 1 "reg_or_int5_operand" "r,I,J")))] |
0 | 280 "" |
281 "@ | |
282 cmp %1,%0 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
283 cmp %.,%0 |
0 | 284 cmp %1,%0" |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
285 [(set_attr "length" "2,2,2") |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
286 (set_attr "cc" "compare,set_znv,compare")]) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
287 |
0 | 288 |
289 ;; ---------------------------------------------------------------------- | |
290 ;; ADD INSTRUCTIONS | |
291 ;; ---------------------------------------------------------------------- | |
292 | |
293 (define_insn "addsi3" | |
294 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
295 (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") | |
296 (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))] | |
297 "" | |
298 "@ | |
299 add %2,%0 | |
300 addi %2,%1,%0 | |
301 addi %O2(%P2),%1,%0" | |
302 [(set_attr "length" "2,4,4") | |
303 (set_attr "cc" "set_zn,set_zn,set_zn")]) | |
304 | |
305 ;; ---------------------------------------------------------------------- | |
306 ;; SUBTRACT INSTRUCTIONS | |
307 ;; ---------------------------------------------------------------------- | |
308 | |
309 (define_insn "subsi3" | |
310 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
311 (minus:SI (match_operand:SI 1 "register_operand" "0,r") | |
312 (match_operand:SI 2 "register_operand" "r,0")))] | |
313 "" | |
314 "@ | |
315 sub %2,%0 | |
316 subr %1,%0" | |
317 [(set_attr "length" "2,2") | |
318 (set_attr "cc" "set_zn")]) | |
319 | |
320 (define_insn "negsi2" | |
321 [(set (match_operand:SI 0 "register_operand" "=r") | |
322 (neg:SI (match_operand:SI 1 "register_operand" "0")))] | |
323 "" | |
324 "subr %.,%0" | |
325 [(set_attr "length" "2") | |
326 (set_attr "cc" "set_zn")]) | |
327 | |
328 ;; ---------------------------------------------------------------------- | |
329 ;; MULTIPLY INSTRUCTIONS | |
330 ;; ---------------------------------------------------------------------- | |
331 | |
332 (define_expand "mulhisi3" | |
333 [(set (match_operand:SI 0 "register_operand" "") | |
334 (mult:SI | |
335 (sign_extend:SI (match_operand:HI 1 "register_operand" "")) | |
336 (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))] | |
337 "" | |
338 "if (GET_CODE (operands[2]) == CONST_INT) | |
339 { | |
340 emit_insn (gen_mulhisi3_internal2 (operands[0], operands[1], operands[2])); | |
341 DONE; | |
342 }") | |
343 | |
344 (define_insn "*mulhisi3_internal1" | |
345 [(set (match_operand:SI 0 "register_operand" "=r") | |
346 (mult:SI | |
347 (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) | |
348 (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] | |
349 "" | |
350 "mulh %2,%0" | |
351 [(set_attr "length" "2") | |
352 (set_attr "cc" "none_0hit") | |
353 (set_attr "type" "mult")]) | |
354 | |
355 (define_insn "mulhisi3_internal2" | |
356 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
357 (mult:SI | |
358 (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,r")) | |
359 (match_operand:HI 2 "const_int_operand" "J,K")))] | |
360 "" | |
361 "@ | |
362 mulh %2,%0 | |
363 mulhi %2,%1,%0" | |
364 [(set_attr "length" "2,4") | |
365 (set_attr "cc" "none_0hit,none_0hit") | |
366 (set_attr "type" "mult")]) | |
367 | |
368 ;; ??? The scheduling info is probably wrong. | |
369 | |
370 ;; ??? This instruction can also generate the 32-bit highpart, but using it | |
371 ;; may increase code size counter to the desired result. | |
372 | |
373 ;; ??? This instructions can also give a DImode result. | |
374 | |
375 ;; ??? There is unsigned version, but it matters only for the DImode/highpart | |
376 ;; results. | |
377 | |
378 (define_insn "mulsi3" | |
379 [(set (match_operand:SI 0 "register_operand" "=r") | |
380 (mult:SI (match_operand:SI 1 "register_operand" "%0") | |
381 (match_operand:SI 2 "reg_or_int9_operand" "rO")))] | |
382 "TARGET_V850E" | |
383 "mul %2,%1,%." | |
384 [(set_attr "length" "4") | |
385 (set_attr "cc" "none_0hit") | |
386 (set_attr "type" "mult")]) | |
387 | |
388 ;; ---------------------------------------------------------------------- | |
389 ;; DIVIDE INSTRUCTIONS | |
390 ;; ---------------------------------------------------------------------- | |
391 | |
392 ;; ??? These insns do set the Z/N condition codes, except that they are based | |
393 ;; on only one of the two results, so it doesn't seem to make sense to use | |
394 ;; them. | |
395 | |
396 ;; ??? The scheduling info is probably wrong. | |
397 | |
398 (define_insn "divmodsi4" | |
399 [(set (match_operand:SI 0 "register_operand" "=r") | |
400 (div:SI (match_operand:SI 1 "register_operand" "0") | |
401 (match_operand:SI 2 "register_operand" "r"))) | |
402 (set (match_operand:SI 3 "register_operand" "=r") | |
403 (mod:SI (match_dup 1) | |
404 (match_dup 2)))] | |
405 "TARGET_V850E" | |
406 "div %2,%0,%3" | |
407 [(set_attr "length" "4") | |
408 (set_attr "cc" "clobber") | |
409 (set_attr "type" "other")]) | |
410 | |
411 (define_insn "udivmodsi4" | |
412 [(set (match_operand:SI 0 "register_operand" "=r") | |
413 (udiv:SI (match_operand:SI 1 "register_operand" "0") | |
414 (match_operand:SI 2 "register_operand" "r"))) | |
415 (set (match_operand:SI 3 "register_operand" "=r") | |
416 (umod:SI (match_dup 1) | |
417 (match_dup 2)))] | |
418 "TARGET_V850E" | |
419 "divu %2,%0,%3" | |
420 [(set_attr "length" "4") | |
421 (set_attr "cc" "clobber") | |
422 (set_attr "type" "other")]) | |
423 | |
424 ;; ??? There is a 2 byte instruction for generating only the quotient. | |
425 ;; However, it isn't clear how to compute the length field correctly. | |
426 | |
427 (define_insn "divmodhi4" | |
428 [(set (match_operand:HI 0 "register_operand" "=r") | |
429 (div:HI (match_operand:HI 1 "register_operand" "0") | |
430 (match_operand:HI 2 "register_operand" "r"))) | |
431 (set (match_operand:HI 3 "register_operand" "=r") | |
432 (mod:HI (match_dup 1) | |
433 (match_dup 2)))] | |
434 "TARGET_V850E" | |
435 "divh %2,%0,%3" | |
436 [(set_attr "length" "4") | |
437 (set_attr "cc" "clobber") | |
438 (set_attr "type" "other")]) | |
439 | |
440 ;; Half-words are sign-extended by default, so we must zero extend to a word | |
441 ;; here before doing the divide. | |
442 | |
443 (define_insn "udivmodhi4" | |
444 [(set (match_operand:HI 0 "register_operand" "=r") | |
445 (udiv:HI (match_operand:HI 1 "register_operand" "0") | |
446 (match_operand:HI 2 "register_operand" "r"))) | |
447 (set (match_operand:HI 3 "register_operand" "=r") | |
448 (umod:HI (match_dup 1) | |
449 (match_dup 2)))] | |
450 "TARGET_V850E" | |
451 "zxh %0 ; divhu %2,%0,%3" | |
452 [(set_attr "length" "4") | |
453 (set_attr "cc" "clobber") | |
454 (set_attr "type" "other")]) | |
455 | |
456 ;; ---------------------------------------------------------------------- | |
457 ;; AND INSTRUCTIONS | |
458 ;; ---------------------------------------------------------------------- | |
459 | |
460 (define_insn "*v850_clr1_1" | |
461 [(set (match_operand:QI 0 "memory_operand" "=m") | |
462 (subreg:QI | |
463 (and:SI (subreg:SI (match_dup 0) 0) | |
464 (match_operand:QI 1 "not_power_of_two_operand" "")) 0))] | |
465 "" | |
466 "* | |
467 { | |
468 rtx xoperands[2]; | |
469 xoperands[0] = operands[0]; | |
470 xoperands[1] = GEN_INT (~INTVAL (operands[1]) & 0xff); | |
471 output_asm_insn (\"clr1 %M1,%0\", xoperands); | |
472 return \"\"; | |
473 }" | |
474 [(set_attr "length" "4") | |
475 (set_attr "cc" "clobber")]) | |
476 | |
477 (define_insn "*v850_clr1_2" | |
478 [(set (match_operand:HI 0 "indirect_operand" "=m") | |
479 (subreg:HI | |
480 (and:SI (subreg:SI (match_dup 0) 0) | |
481 (match_operand:HI 1 "not_power_of_two_operand" "")) 0))] | |
482 "" | |
483 "* | |
484 { | |
485 int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffff); | |
486 | |
487 rtx xoperands[2]; | |
488 xoperands[0] = gen_rtx_MEM (QImode, | |
489 plus_constant (XEXP (operands[0], 0), log2 / 8)); | |
490 xoperands[1] = GEN_INT (log2 % 8); | |
491 output_asm_insn (\"clr1 %1,%0\", xoperands); | |
492 return \"\"; | |
493 }" | |
494 [(set_attr "length" "4") | |
495 (set_attr "cc" "clobber")]) | |
496 | |
497 (define_insn "*v850_clr1_3" | |
498 [(set (match_operand:SI 0 "indirect_operand" "=m") | |
499 (and:SI (match_dup 0) | |
500 (match_operand:SI 1 "not_power_of_two_operand" "")))] | |
501 "" | |
502 "* | |
503 { | |
504 int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffffffff); | |
505 | |
506 rtx xoperands[2]; | |
507 xoperands[0] = gen_rtx_MEM (QImode, | |
508 plus_constant (XEXP (operands[0], 0), log2 / 8)); | |
509 xoperands[1] = GEN_INT (log2 % 8); | |
510 output_asm_insn (\"clr1 %1,%0\", xoperands); | |
511 return \"\"; | |
512 }" | |
513 [(set_attr "length" "4") | |
514 (set_attr "cc" "clobber")]) | |
515 | |
516 (define_insn "andsi3" | |
517 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
518 (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
519 (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] | |
520 "" | |
521 "@ | |
522 and %2,%0 | |
523 and %.,%0 | |
524 andi %2,%1,%0" | |
525 [(set_attr "length" "2,2,4") | |
526 (set_attr "cc" "set_znv")]) | |
527 | |
528 ;; ---------------------------------------------------------------------- | |
529 ;; OR INSTRUCTIONS | |
530 ;; ---------------------------------------------------------------------- | |
531 | |
532 (define_insn "*v850_set1_1" | |
533 [(set (match_operand:QI 0 "memory_operand" "=m") | |
534 (subreg:QI (ior:SI (subreg:SI (match_dup 0) 0) | |
535 (match_operand 1 "power_of_two_operand" "")) 0))] | |
536 "" | |
537 "set1 %M1,%0" | |
538 [(set_attr "length" "4") | |
539 (set_attr "cc" "clobber")]) | |
540 | |
541 (define_insn "*v850_set1_2" | |
542 [(set (match_operand:HI 0 "indirect_operand" "=m") | |
543 (subreg:HI (ior:SI (subreg:SI (match_dup 0) 0) | |
544 (match_operand 1 "power_of_two_operand" "")) 0))] | |
545 "" | |
546 "* | |
547 { | |
548 int log2 = exact_log2 (INTVAL (operands[1])); | |
549 | |
550 if (log2 < 8) | |
551 return \"set1 %M1,%0\"; | |
552 else | |
553 { | |
554 rtx xoperands[2]; | |
555 xoperands[0] = gen_rtx_MEM (QImode, | |
556 plus_constant (XEXP (operands[0], 0), | |
557 log2 / 8)); | |
558 xoperands[1] = GEN_INT (log2 % 8); | |
559 output_asm_insn (\"set1 %1,%0\", xoperands); | |
560 } | |
561 return \"\"; | |
562 }" | |
563 [(set_attr "length" "4") | |
564 (set_attr "cc" "clobber")]) | |
565 | |
566 (define_insn "*v850_set1_3" | |
567 [(set (match_operand:SI 0 "indirect_operand" "=m") | |
568 (ior:SI (match_dup 0) | |
569 (match_operand 1 "power_of_two_operand" "")))] | |
570 "" | |
571 "* | |
572 { | |
573 int log2 = exact_log2 (INTVAL (operands[1])); | |
574 | |
575 if (log2 < 8) | |
576 return \"set1 %M1,%0\"; | |
577 else | |
578 { | |
579 rtx xoperands[2]; | |
580 xoperands[0] = gen_rtx_MEM (QImode, | |
581 plus_constant (XEXP (operands[0], 0), | |
582 log2 / 8)); | |
583 xoperands[1] = GEN_INT (log2 % 8); | |
584 output_asm_insn (\"set1 %1,%0\", xoperands); | |
585 } | |
586 return \"\"; | |
587 }" | |
588 [(set_attr "length" "4") | |
589 (set_attr "cc" "clobber")]) | |
590 | |
591 (define_insn "iorsi3" | |
592 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
593 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
594 (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] | |
595 "" | |
596 "@ | |
597 or %2,%0 | |
598 or %.,%0 | |
599 ori %2,%1,%0" | |
600 [(set_attr "length" "2,2,4") | |
601 (set_attr "cc" "set_znv")]) | |
602 | |
603 ;; ---------------------------------------------------------------------- | |
604 ;; XOR INSTRUCTIONS | |
605 ;; ---------------------------------------------------------------------- | |
606 | |
607 (define_insn "*v850_not1_1" | |
608 [(set (match_operand:QI 0 "memory_operand" "=m") | |
609 (subreg:QI (xor:SI (subreg:SI (match_dup 0) 0) | |
610 (match_operand 1 "power_of_two_operand" "")) 0))] | |
611 "" | |
612 "not1 %M1,%0" | |
613 [(set_attr "length" "4") | |
614 (set_attr "cc" "clobber")]) | |
615 | |
616 (define_insn "*v850_not1_2" | |
617 [(set (match_operand:HI 0 "indirect_operand" "=m") | |
618 (subreg:HI (xor:SI (subreg:SI (match_dup 0) 0) | |
619 (match_operand 1 "power_of_two_operand" "")) 0))] | |
620 "" | |
621 "* | |
622 { | |
623 int log2 = exact_log2 (INTVAL (operands[1])); | |
624 | |
625 if (log2 < 8) | |
626 return \"not1 %M1,%0\"; | |
627 else | |
628 { | |
629 rtx xoperands[2]; | |
630 xoperands[0] = gen_rtx_MEM (QImode, | |
631 plus_constant (XEXP (operands[0], 0), | |
632 log2 / 8)); | |
633 xoperands[1] = GEN_INT (log2 % 8); | |
634 output_asm_insn (\"not1 %1,%0\", xoperands); | |
635 } | |
636 return \"\"; | |
637 }" | |
638 [(set_attr "length" "4") | |
639 (set_attr "cc" "clobber")]) | |
640 | |
641 (define_insn "*v850_not1_3" | |
642 [(set (match_operand:SI 0 "indirect_operand" "=m") | |
643 (xor:SI (match_dup 0) | |
644 (match_operand 1 "power_of_two_operand" "")))] | |
645 "" | |
646 "* | |
647 { | |
648 int log2 = exact_log2 (INTVAL (operands[1])); | |
649 | |
650 if (log2 < 8) | |
651 return \"not1 %M1,%0\"; | |
652 else | |
653 { | |
654 rtx xoperands[2]; | |
655 xoperands[0] = gen_rtx_MEM (QImode, | |
656 plus_constant (XEXP (operands[0], 0), | |
657 log2 / 8)); | |
658 xoperands[1] = GEN_INT (log2 % 8); | |
659 output_asm_insn (\"not1 %1,%0\", xoperands); | |
660 } | |
661 return \"\"; | |
662 }" | |
663 [(set_attr "length" "4") | |
664 (set_attr "cc" "clobber")]) | |
665 | |
666 (define_insn "xorsi3" | |
667 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
668 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
669 (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] | |
670 "" | |
671 "@ | |
672 xor %2,%0 | |
673 xor %.,%0 | |
674 xori %2,%1,%0" | |
675 [(set_attr "length" "2,2,4") | |
676 (set_attr "cc" "set_znv")]) | |
677 | |
678 ;; ---------------------------------------------------------------------- | |
679 ;; NOT INSTRUCTIONS | |
680 ;; ---------------------------------------------------------------------- | |
681 | |
682 (define_insn "one_cmplsi2" | |
683 [(set (match_operand:SI 0 "register_operand" "=r") | |
684 (not:SI (match_operand:SI 1 "register_operand" "r")))] | |
685 "" | |
686 "not %1,%0" | |
687 [(set_attr "length" "2") | |
688 (set_attr "cc" "set_znv")]) | |
689 | |
690 ;; ----------------------------------------------------------------- | |
691 ;; BIT FIELDS | |
692 ;; ----------------------------------------------------------------- | |
693 | |
694 ;; ??? Is it worth defining insv and extv for the V850 series?!? | |
695 | |
696 ;; An insv pattern would be useful, but does not get used because | |
697 ;; store_bit_field never calls insv when storing a constant value into a | |
698 ;; single-bit bitfield. | |
699 | |
700 ;; extv/extzv patterns would be useful, but do not get used because | |
701 ;; optimize_bitfield_compare in fold-const usually converts single | |
702 ;; bit extracts into an AND with a mask. | |
703 | |
704 ;; ----------------------------------------------------------------- | |
705 ;; Scc INSTRUCTIONS | |
706 ;; ----------------------------------------------------------------- | |
707 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
708 (define_insn "*setcc" |
0 | 709 [(set (match_operand:SI 0 "register_operand" "=r") |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
710 (match_operator:SI 1 "comparison_operator" |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
711 [(cc0) (const_int 0)]))] |
0 | 712 "" |
713 "* | |
714 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
715 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
716 && (GET_CODE (operands[1]) == GT |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
717 || GET_CODE (operands[1]) == GE |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
718 || GET_CODE (operands[1]) == LE |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
719 || GET_CODE (operands[1]) == LT)) |
0 | 720 return 0; |
721 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
722 return \"setf %c1,%0\"; |
0 | 723 }" |
724 [(set_attr "length" "4") | |
725 (set_attr "cc" "none_0hit")]) | |
726 | |
727 ;; ---------------------------------------------------------------------- | |
728 ;; CONDITIONAL MOVE INSTRUCTIONS | |
729 ;; ---------------------------------------------------------------------- | |
730 | |
731 ;; Instructions using cc0 aren't allowed to have input reloads, so we must | |
732 ;; hide the fact that this instruction uses cc0. We do so by including the | |
733 ;; compare instruction inside it. | |
734 | |
735 (define_expand "movsicc" | |
736 [(set (match_operand:SI 0 "register_operand" "=r") | |
737 (if_then_else:SI | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
738 (match_operand 1 "comparison_operator") |
0 | 739 (match_operand:SI 2 "reg_or_const_operand" "rJ") |
740 (match_operand:SI 3 "reg_or_const_operand" "rI")))] | |
741 "TARGET_V850E" | |
742 " | |
743 { | |
744 if ( (GET_CODE (operands[2]) == CONST_INT | |
745 && GET_CODE (operands[3]) == CONST_INT)) | |
746 { | |
747 int o2 = INTVAL (operands[2]); | |
748 int o3 = INTVAL (operands[3]); | |
749 | |
750 if (o2 == 1 && o3 == 0) | |
751 FAIL; /* setf */ | |
752 if (o3 == 1 && o2 == 0) | |
753 FAIL; /* setf */ | |
754 if (o2 == 0 && (o3 < -16 || o3 > 15) && exact_log2 (o3) >= 0) | |
755 FAIL; /* setf + shift */ | |
756 if (o3 == 0 && (o2 < -16 || o2 > 15) && exact_log2 (o2) >=0) | |
757 FAIL; /* setf + shift */ | |
758 if (o2 != 0) | |
759 operands[2] = copy_to_mode_reg (SImode, operands[2]); | |
760 if (o3 !=0 ) | |
761 operands[3] = copy_to_mode_reg (SImode, operands[3]); | |
762 } | |
763 else | |
764 { | |
765 if (GET_CODE (operands[2]) != REG) | |
766 operands[2] = copy_to_mode_reg (SImode,operands[2]); | |
767 if (GET_CODE (operands[3]) != REG) | |
768 operands[3] = copy_to_mode_reg (SImode, operands[3]); | |
769 } | |
770 }") | |
771 | |
772 ;; ??? Clobbering the condition codes is overkill. | |
773 | |
774 ;; ??? We sometimes emit an unnecessary compare instruction because the | |
775 ;; condition codes may have already been set by an earlier instruction, | |
776 ;; but we have no code here to avoid the compare if it is unnecessary. | |
777 | |
778 (define_insn "*movsicc_normal" | |
779 [(set (match_operand:SI 0 "register_operand" "=r") | |
780 (if_then_else:SI | |
781 (match_operator 1 "comparison_operator" | |
782 [(match_operand:SI 4 "register_operand" "r") | |
783 (match_operand:SI 5 "reg_or_int5_operand" "rJ")]) | |
784 (match_operand:SI 2 "reg_or_int5_operand" "rJ") | |
785 (match_operand:SI 3 "reg_or_0_operand" "rI")))] | |
786 "TARGET_V850E" | |
787 "cmp %5,%4 ; cmov %c1,%2,%z3,%0" | |
788 [(set_attr "length" "6") | |
789 (set_attr "cc" "clobber")]) | |
790 | |
791 (define_insn "*movsicc_reversed" | |
792 [(set (match_operand:SI 0 "register_operand" "=r") | |
793 (if_then_else:SI | |
794 (match_operator 1 "comparison_operator" | |
795 [(match_operand:SI 4 "register_operand" "r") | |
796 (match_operand:SI 5 "reg_or_int5_operand" "rJ")]) | |
797 (match_operand:SI 2 "reg_or_0_operand" "rI") | |
798 (match_operand:SI 3 "reg_or_int5_operand" "rJ")))] | |
799 "TARGET_V850E" | |
800 "cmp %5,%4 ; cmov %C1,%3,%z2,%0" | |
801 [(set_attr "length" "6") | |
802 (set_attr "cc" "clobber")]) | |
803 | |
804 (define_insn "*movsicc_tst1" | |
805 [(set (match_operand:SI 0 "register_operand" "=r") | |
806 (if_then_else:SI | |
807 (match_operator 1 "comparison_operator" | |
808 [(zero_extract:SI | |
809 (match_operand:QI 2 "memory_operand" "m") | |
810 (const_int 1) | |
811 (match_operand 3 "const_int_operand" "n")) | |
812 (const_int 0)]) | |
813 (match_operand:SI 4 "reg_or_int5_operand" "rJ") | |
814 (match_operand:SI 5 "reg_or_0_operand" "rI")))] | |
815 "TARGET_V850E" | |
816 "tst1 %3,%2 ; cmov %c1,%4,%z5,%0" | |
817 [(set_attr "length" "8") | |
818 (set_attr "cc" "clobber")]) | |
819 | |
820 (define_insn "*movsicc_tst1_reversed" | |
821 [(set (match_operand:SI 0 "register_operand" "=r") | |
822 (if_then_else:SI | |
823 (match_operator 1 "comparison_operator" | |
824 [(zero_extract:SI | |
825 (match_operand:QI 2 "memory_operand" "m") | |
826 (const_int 1) | |
827 (match_operand 3 "const_int_operand" "n")) | |
828 (const_int 0)]) | |
829 (match_operand:SI 4 "reg_or_0_operand" "rI") | |
830 (match_operand:SI 5 "reg_or_int5_operand" "rJ")))] | |
831 "TARGET_V850E" | |
832 "tst1 %3,%2 ; cmov %C1,%5,%z4,%0" | |
833 [(set_attr "length" "8") | |
834 (set_attr "cc" "clobber")]) | |
835 | |
836 ;; Matching for sasf requires combining 4 instructions, so we provide a | |
837 ;; dummy pattern to match the first 3, which will always be turned into the | |
838 ;; second pattern by subsequent combining. As above, we must include the | |
839 ;; comparison to avoid input reloads in an insn using cc0. | |
840 | |
841 (define_insn "*sasf_1" | |
842 [(set (match_operand:SI 0 "register_operand" "") | |
843 (ior:SI (match_operator 1 "comparison_operator" [(cc0) (const_int 0)]) | |
844 (ashift:SI (match_operand:SI 2 "register_operand" "") | |
845 (const_int 1))))] | |
846 "TARGET_V850E" | |
847 "* gcc_unreachable ();") | |
848 | |
849 (define_insn "*sasf_2" | |
850 [(set (match_operand:SI 0 "register_operand" "=r") | |
851 (ior:SI | |
852 (match_operator 1 "comparison_operator" | |
853 [(match_operand:SI 3 "register_operand" "r") | |
854 (match_operand:SI 4 "reg_or_int5_operand" "rJ")]) | |
855 (ashift:SI (match_operand:SI 2 "register_operand" "0") | |
856 (const_int 1))))] | |
857 "TARGET_V850E" | |
858 "cmp %4,%3 ; sasf %c1,%0" | |
859 [(set_attr "length" "6") | |
860 (set_attr "cc" "clobber")]) | |
861 | |
862 (define_split | |
863 [(set (match_operand:SI 0 "register_operand" "") | |
864 (if_then_else:SI | |
865 (match_operator 1 "comparison_operator" | |
866 [(match_operand:SI 4 "register_operand" "") | |
867 (match_operand:SI 5 "reg_or_int5_operand" "")]) | |
868 (match_operand:SI 2 "const_int_operand" "") | |
869 (match_operand:SI 3 "const_int_operand" "")))] | |
870 "TARGET_V850E | |
871 && ((INTVAL (operands[2]) ^ INTVAL (operands[3])) == 1) | |
872 && ((INTVAL (operands[2]) + INTVAL (operands[3])) != 1) | |
873 && (GET_CODE (operands[5]) == CONST_INT | |
874 || REGNO (operands[0]) != REGNO (operands[5])) | |
875 && REGNO (operands[0]) != REGNO (operands[4])" | |
876 [(set (match_dup 0) (match_dup 6)) | |
877 (set (match_dup 0) | |
878 (ior:SI (match_op_dup 7 [(match_dup 4) (match_dup 5)]) | |
879 (ashift:SI (match_dup 0) (const_int 1))))] | |
880 " | |
881 { | |
882 operands[6] = GEN_INT (INTVAL (operands[2]) >> 1); | |
883 if (INTVAL (operands[2]) & 0x1) | |
884 operands[7] = operands[1]; | |
885 else | |
886 operands[7] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])), | |
887 GET_MODE (operands[1]), | |
888 XEXP (operands[1], 0), XEXP (operands[1], 1)); | |
889 }") | |
890 ;; --------------------------------------------------------------------- | |
891 ;; BYTE SWAP INSTRUCTIONS | |
892 ;; --------------------------------------------------------------------- | |
893 | |
894 (define_expand "rotlhi3" | |
895 [(set (match_operand:HI 0 "register_operand" "") | |
896 (rotate:HI (match_operand:HI 1 "register_operand" "") | |
897 (match_operand:HI 2 "const_int_operand" "")))] | |
898 "TARGET_V850E" | |
899 " | |
900 { | |
901 if (INTVAL (operands[2]) != 8) | |
902 FAIL; | |
903 }") | |
904 | |
905 (define_insn "*rotlhi3_8" | |
906 [(set (match_operand:HI 0 "register_operand" "=r") | |
907 (rotate:HI (match_operand:HI 1 "register_operand" "r") | |
908 (const_int 8)))] | |
909 "TARGET_V850E" | |
910 "bsh %1,%0" | |
911 [(set_attr "length" "4") | |
912 (set_attr "cc" "clobber")]) | |
913 | |
914 (define_expand "rotlsi3" | |
915 [(set (match_operand:SI 0 "register_operand" "") | |
916 (rotate:SI (match_operand:SI 1 "register_operand" "") | |
917 (match_operand:SI 2 "const_int_operand" "")))] | |
918 "TARGET_V850E" | |
919 " | |
920 { | |
921 if (INTVAL (operands[2]) != 16) | |
922 FAIL; | |
923 }") | |
924 | |
925 (define_insn "*rotlsi3_16" | |
926 [(set (match_operand:SI 0 "register_operand" "=r") | |
927 (rotate:SI (match_operand:SI 1 "register_operand" "r") | |
928 (const_int 16)))] | |
929 "TARGET_V850E" | |
930 "hsw %1,%0" | |
931 [(set_attr "length" "4") | |
932 (set_attr "cc" "clobber")]) | |
933 | |
934 ;; ---------------------------------------------------------------------- | |
935 ;; JUMP INSTRUCTIONS | |
936 ;; ---------------------------------------------------------------------- | |
937 | |
938 ;; Conditional jump instructions | |
939 | |
940 (define_insn "*branch_normal" | |
941 [(set (pc) | |
942 (if_then_else (match_operator 1 "comparison_operator" | |
943 [(cc0) (const_int 0)]) | |
944 (label_ref (match_operand 0 "" "")) | |
945 (pc)))] | |
946 "" | |
947 "* | |
948 { | |
949 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 | |
950 && (GET_CODE (operands[1]) == GT | |
951 || GET_CODE (operands[1]) == GE | |
952 || GET_CODE (operands[1]) == LE | |
953 || GET_CODE (operands[1]) == LT)) | |
954 return 0; | |
955 | |
956 if (get_attr_length (insn) == 2) | |
957 return \"b%b1 %l0\"; | |
958 else | |
959 return \"b%B1 .+6 ; jr %l0\"; | |
960 }" | |
961 [(set (attr "length") | |
962 (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
963 (const_int 256)) | |
964 (const_int 2) | |
965 (const_int 6))) | |
966 (set_attr "cc" "none")]) | |
967 | |
968 (define_insn "*branch_invert" | |
969 [(set (pc) | |
970 (if_then_else (match_operator 1 "comparison_operator" | |
971 [(cc0) (const_int 0)]) | |
972 (pc) | |
973 (label_ref (match_operand 0 "" ""))))] | |
974 "" | |
975 "* | |
976 { | |
977 if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 | |
978 && (GET_CODE (operands[1]) == GT | |
979 || GET_CODE (operands[1]) == GE | |
980 || GET_CODE (operands[1]) == LE | |
981 || GET_CODE (operands[1]) == LT)) | |
982 return 0; | |
983 if (get_attr_length (insn) == 2) | |
984 return \"b%B1 %l0\"; | |
985 else | |
986 return \"b%b1 .+6 ; jr %l0\"; | |
987 }" | |
988 [(set (attr "length") | |
989 (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
990 (const_int 256)) | |
991 (const_int 2) | |
992 (const_int 6))) | |
993 (set_attr "cc" "none")]) | |
994 | |
995 ;; Unconditional and other jump instructions. | |
996 | |
997 (define_insn "jump" | |
998 [(set (pc) | |
999 (label_ref (match_operand 0 "" "")))] | |
1000 "" | |
1001 "* | |
1002 { | |
1003 if (get_attr_length (insn) == 2) | |
1004 return \"br %0\"; | |
1005 else | |
1006 return \"jr %0\"; | |
1007 }" | |
1008 [(set (attr "length") | |
1009 (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
1010 (const_int 256)) | |
1011 (const_int 2) | |
1012 (const_int 4))) | |
1013 (set_attr "cc" "none")]) | |
1014 | |
1015 (define_insn "indirect_jump" | |
1016 [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
1017 "" | |
1018 "jmp %0" | |
1019 [(set_attr "length" "2") | |
1020 (set_attr "cc" "none")]) | |
1021 | |
1022 (define_insn "tablejump" | |
1023 [(set (pc) (match_operand:SI 0 "register_operand" "r")) | |
1024 (use (label_ref (match_operand 1 "" "")))] | |
1025 "" | |
1026 "jmp %0" | |
1027 [(set_attr "length" "2") | |
1028 (set_attr "cc" "none")]) | |
1029 | |
1030 (define_insn "switch" | |
1031 [(set (pc) | |
1032 (plus:SI | |
1033 (sign_extend:SI | |
1034 (mem:HI | |
1035 (plus:SI (ashift:SI (match_operand:SI 0 "register_operand" "r") | |
1036 (const_int 1)) | |
1037 (label_ref (match_operand 1 "" ""))))) | |
1038 (label_ref (match_dup 1))))] | |
1039 "TARGET_V850E" | |
1040 "switch %0" | |
1041 [(set_attr "length" "2") | |
1042 (set_attr "cc" "none")]) | |
1043 | |
1044 (define_expand "casesi" | |
1045 [(match_operand:SI 0 "register_operand" "") | |
1046 (match_operand:SI 1 "register_operand" "") | |
1047 (match_operand:SI 2 "register_operand" "") | |
1048 (match_operand 3 "" "") (match_operand 4 "" "")] | |
1049 "" | |
1050 " | |
1051 { | |
1052 rtx reg = gen_reg_rtx (SImode); | |
1053 rtx tableaddress = gen_reg_rtx (SImode); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1054 rtx test; |
0 | 1055 rtx mem; |
1056 | |
1057 /* Subtract the lower bound from the index. */ | |
1058 emit_insn (gen_subsi3 (reg, operands[0], operands[1])); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1059 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1060 /* Compare the result against the number of table entries; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1061 branch to the default label if out of range of the table. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1062 test = gen_rtx_fmt_ee (GTU, VOIDmode, reg, operands[2]); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1063 emit_jump_insn (gen_cbranchsi4 (test, reg, operands[2], operands[4])); |
0 | 1064 |
1065 /* Shift index for the table array access. */ | |
1066 emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1))); | |
1067 /* Load the table address into a pseudo. */ | |
1068 emit_insn (gen_movsi (tableaddress, | |
1069 gen_rtx_LABEL_REF (Pmode, operands[3]))); | |
1070 /* Add the table address to the index. */ | |
1071 emit_insn (gen_addsi3 (reg, reg, tableaddress)); | |
1072 /* Load the table entry. */ | |
1073 mem = gen_const_mem (CASE_VECTOR_MODE, reg); | |
1074 if (! TARGET_BIG_SWITCH) | |
1075 { | |
1076 rtx reg2 = gen_reg_rtx (HImode); | |
1077 emit_insn (gen_movhi (reg2, mem)); | |
1078 emit_insn (gen_extendhisi2 (reg, reg2)); | |
1079 } | |
1080 else | |
1081 emit_insn (gen_movsi (reg, mem)); | |
1082 /* Add the table address. */ | |
1083 emit_insn (gen_addsi3 (reg, reg, tableaddress)); | |
1084 /* Branch to the switch label. */ | |
1085 emit_jump_insn (gen_tablejump (reg, operands[3])); | |
1086 DONE; | |
1087 }") | |
1088 | |
1089 ;; Call subroutine with no return value. | |
1090 | |
1091 (define_expand "call" | |
1092 [(call (match_operand:QI 0 "general_operand" "") | |
1093 (match_operand:SI 1 "general_operand" ""))] | |
1094 "" | |
1095 " | |
1096 { | |
1097 if (! call_address_operand (XEXP (operands[0], 0), QImode) | |
1098 || TARGET_LONG_CALLS) | |
1099 XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); | |
1100 if (TARGET_LONG_CALLS) | |
1101 emit_call_insn (gen_call_internal_long (XEXP (operands[0], 0), operands[1])); | |
1102 else | |
1103 emit_call_insn (gen_call_internal_short (XEXP (operands[0], 0), operands[1])); | |
1104 | |
1105 DONE; | |
1106 }") | |
1107 | |
1108 (define_insn "call_internal_short" | |
1109 [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) | |
1110 (match_operand:SI 1 "general_operand" "g,g")) | |
1111 (clobber (reg:SI 31))] | |
1112 "! TARGET_LONG_CALLS" | |
1113 "@ | |
1114 jarl %0,r31 | |
1115 jarl .+4,r31 ; add 4,r31 ; jmp %0" | |
1116 [(set_attr "length" "4,8")] | |
1117 ) | |
1118 | |
1119 (define_insn "call_internal_long" | |
1120 [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) | |
1121 (match_operand:SI 1 "general_operand" "g,g")) | |
1122 (clobber (reg:SI 31))] | |
1123 "TARGET_LONG_CALLS" | |
1124 "* | |
1125 { | |
1126 if (which_alternative == 0) | |
1127 { | |
1128 if (GET_CODE (operands[0]) == REG) | |
1129 return \"jarl %0,r31\"; | |
1130 else | |
1131 return \"movhi hi(%0), r0, r11 ; movea lo(%0), r11, r11 ; jarl .+4,r31 ; add 4, r31 ; jmp r11\"; | |
1132 } | |
1133 else | |
1134 return \"jarl .+4,r31 ; add 4,r31 ; jmp %0\"; | |
1135 }" | |
1136 [(set_attr "length" "16,8")] | |
1137 ) | |
1138 | |
1139 ;; Call subroutine, returning value in operand 0 | |
1140 ;; (which must be a hard register). | |
1141 | |
1142 (define_expand "call_value" | |
1143 [(set (match_operand 0 "" "") | |
1144 (call (match_operand:QI 1 "general_operand" "") | |
1145 (match_operand:SI 2 "general_operand" "")))] | |
1146 "" | |
1147 " | |
1148 { | |
1149 if (! call_address_operand (XEXP (operands[1], 0), QImode) | |
1150 || TARGET_LONG_CALLS) | |
1151 XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); | |
1152 if (TARGET_LONG_CALLS) | |
1153 emit_call_insn (gen_call_value_internal_long (operands[0], | |
1154 XEXP (operands[1], 0), | |
1155 operands[2])); | |
1156 else | |
1157 emit_call_insn (gen_call_value_internal_short (operands[0], | |
1158 XEXP (operands[1], 0), | |
1159 operands[2])); | |
1160 DONE; | |
1161 }") | |
1162 | |
1163 (define_insn "call_value_internal_short" | |
1164 [(set (match_operand 0 "" "=r,r") | |
1165 (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) | |
1166 (match_operand:SI 2 "general_operand" "g,g"))) | |
1167 (clobber (reg:SI 31))] | |
1168 "! TARGET_LONG_CALLS" | |
1169 "@ | |
1170 jarl %1,r31 | |
1171 jarl .+4,r31 ; add 4,r31 ; jmp %1" | |
1172 [(set_attr "length" "4,8")] | |
1173 ) | |
1174 | |
1175 (define_insn "call_value_internal_long" | |
1176 [(set (match_operand 0 "" "=r,r") | |
1177 (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) | |
1178 (match_operand:SI 2 "general_operand" "g,g"))) | |
1179 (clobber (reg:SI 31))] | |
1180 "TARGET_LONG_CALLS" | |
1181 "* | |
1182 { | |
1183 if (which_alternative == 0) | |
1184 { | |
1185 if (GET_CODE (operands[1]) == REG) | |
1186 return \"jarl %1, r31\"; | |
1187 else | |
1188 /* Reload can generate this pattern.... */ | |
1189 return \"movhi hi(%1), r0, r11 ; movea lo(%1), r11, r11 ; jarl .+4, r31 ; add 4, r31 ; jmp r11\"; | |
1190 } | |
1191 else | |
1192 return \"jarl .+4, r31 ; add 4, r31 ; jmp %1\"; | |
1193 }" | |
1194 [(set_attr "length" "16,8")] | |
1195 ) | |
1196 | |
1197 (define_insn "nop" | |
1198 [(const_int 0)] | |
1199 "" | |
1200 "nop" | |
1201 [(set_attr "length" "2") | |
1202 (set_attr "cc" "none")]) | |
1203 | |
1204 ;; ---------------------------------------------------------------------- | |
1205 ;; EXTEND INSTRUCTIONS | |
1206 ;; ---------------------------------------------------------------------- | |
1207 | |
1208 (define_insn "" | |
1209 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") | |
1210 (zero_extend:SI | |
1211 (match_operand:HI 1 "nonimmediate_operand" "0,r,T,m")))] | |
1212 "TARGET_V850E" | |
1213 "@ | |
1214 zxh %0 | |
1215 andi 65535,%1,%0 | |
1216 sld.hu %1,%0 | |
1217 ld.hu %1,%0" | |
1218 [(set_attr "length" "2,4,2,4") | |
1219 (set_attr "cc" "none_0hit,set_znv,none_0hit,none_0hit")]) | |
1220 | |
1221 (define_insn "zero_extendhisi2" | |
1222 [(set (match_operand:SI 0 "register_operand" "=r") | |
1223 (zero_extend:SI | |
1224 (match_operand:HI 1 "register_operand" "r")))] | |
1225 "" | |
1226 "andi 65535,%1,%0" | |
1227 [(set_attr "length" "4") | |
1228 (set_attr "cc" "set_znv")]) | |
1229 | |
1230 (define_insn "" | |
1231 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") | |
1232 (zero_extend:SI | |
1233 (match_operand:QI 1 "nonimmediate_operand" "0,r,T,m")))] | |
1234 "TARGET_V850E" | |
1235 "@ | |
1236 zxb %0 | |
1237 andi 255,%1,%0 | |
1238 sld.bu %1,%0 | |
1239 ld.bu %1,%0" | |
1240 [(set_attr "length" "2,4,2,4") | |
1241 (set_attr "cc" "none_0hit,set_znv,none_0hit,none_0hit")]) | |
1242 | |
1243 (define_insn "zero_extendqisi2" | |
1244 [(set (match_operand:SI 0 "register_operand" "=r") | |
1245 (zero_extend:SI | |
1246 (match_operand:QI 1 "register_operand" "r")))] | |
1247 "" | |
1248 "andi 255,%1,%0" | |
1249 [(set_attr "length" "4") | |
1250 (set_attr "cc" "set_znv")]) | |
1251 | |
1252 ;;- sign extension instructions | |
1253 | |
1254 ;; ??? The extendhisi2 pattern should not emit shifts for v850e? | |
1255 | |
1256 (define_insn "*extendhisi_insn" | |
1257 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1258 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))] | |
1259 "TARGET_V850E" | |
1260 "@ | |
1261 sxh %0 | |
1262 sld.h %1,%0 | |
1263 ld.h %1,%0" | |
1264 [(set_attr "length" "2,2,4") | |
1265 (set_attr "cc" "none_0hit,none_0hit,none_0hit")]) | |
1266 | |
1267 ;; ??? This is missing a sign extend from memory pattern to match the ld.h | |
1268 ;; instruction. | |
1269 | |
1270 (define_expand "extendhisi2" | |
1271 [(set (match_dup 2) | |
1272 (ashift:SI (match_operand:HI 1 "register_operand" "") | |
1273 (const_int 16))) | |
1274 (set (match_operand:SI 0 "register_operand" "") | |
1275 (ashiftrt:SI (match_dup 2) | |
1276 (const_int 16)))] | |
1277 "" | |
1278 " | |
1279 { | |
1280 operands[1] = gen_lowpart (SImode, operands[1]); | |
1281 operands[2] = gen_reg_rtx (SImode); | |
1282 }") | |
1283 | |
1284 ;; ??? The extendqisi2 pattern should not emit shifts for v850e? | |
1285 | |
1286 (define_insn "*extendqisi_insn" | |
1287 [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1288 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))] | |
1289 "TARGET_V850E" | |
1290 "@ | |
1291 sxb %0 | |
1292 sld.b %1,%0 | |
1293 ld.b %1,%0" | |
1294 [(set_attr "length" "2,2,4") | |
1295 (set_attr "cc" "none_0hit,none_0hit,none_0hit")]) | |
1296 | |
1297 ;; ??? This is missing a sign extend from memory pattern to match the ld.b | |
1298 ;; instruction. | |
1299 | |
1300 (define_expand "extendqisi2" | |
1301 [(set (match_dup 2) | |
1302 (ashift:SI (match_operand:QI 1 "register_operand" "") | |
1303 (const_int 24))) | |
1304 (set (match_operand:SI 0 "register_operand" "") | |
1305 (ashiftrt:SI (match_dup 2) | |
1306 (const_int 24)))] | |
1307 "" | |
1308 " | |
1309 { | |
1310 operands[1] = gen_lowpart (SImode, operands[1]); | |
1311 operands[2] = gen_reg_rtx (SImode); | |
1312 }") | |
1313 | |
1314 ;; ---------------------------------------------------------------------- | |
1315 ;; SHIFTS | |
1316 ;; ---------------------------------------------------------------------- | |
1317 | |
1318 (define_insn "ashlsi3" | |
1319 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1320 (ashift:SI | |
1321 (match_operand:SI 1 "register_operand" "0,0") | |
1322 (match_operand:SI 2 "nonmemory_operand" "r,N")))] | |
1323 "" | |
1324 "@ | |
1325 shl %2,%0 | |
1326 shl %2,%0" | |
1327 [(set_attr "length" "4,2") | |
1328 (set_attr "cc" "set_znv")]) | |
1329 | |
1330 (define_insn "lshrsi3" | |
1331 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1332 (lshiftrt:SI | |
1333 (match_operand:SI 1 "register_operand" "0,0") | |
1334 (match_operand:SI 2 "nonmemory_operand" "r,N")))] | |
1335 "" | |
1336 "@ | |
1337 shr %2,%0 | |
1338 shr %2,%0" | |
1339 [(set_attr "length" "4,2") | |
1340 (set_attr "cc" "set_znv")]) | |
1341 | |
1342 (define_insn "ashrsi3" | |
1343 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1344 (ashiftrt:SI | |
1345 (match_operand:SI 1 "register_operand" "0,0") | |
1346 (match_operand:SI 2 "nonmemory_operand" "r,N")))] | |
1347 "" | |
1348 "@ | |
1349 sar %2,%0 | |
1350 sar %2,%0" | |
1351 [(set_attr "length" "4,2") | |
1352 (set_attr "cc" "set_znv")]) | |
1353 | |
1354 ;; ---------------------------------------------------------------------- | |
1355 ;; PROLOGUE/EPILOGUE | |
1356 ;; ---------------------------------------------------------------------- | |
1357 (define_expand "prologue" | |
1358 [(const_int 0)] | |
1359 "" | |
1360 "expand_prologue (); DONE;") | |
1361 | |
1362 (define_expand "epilogue" | |
1363 [(return)] | |
1364 "" | |
1365 " | |
1366 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1367 expand_epilogue (); |
0 | 1368 DONE; |
1369 }") | |
1370 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1371 (define_insn "return_simple" |
0 | 1372 [(return)] |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1373 "reload_completed" |
0 | 1374 "jmp [r31]" |
1375 [(set_attr "length" "2") | |
1376 (set_attr "cc" "none")]) | |
1377 | |
1378 (define_insn "return_internal" | |
1379 [(return) | |
1380 (use (reg:SI 31))] | |
1381 "" | |
1382 "jmp [r31]" | |
1383 [(set_attr "length" "2") | |
1384 (set_attr "cc" "none")]) | |
1385 | |
1386 | |
1387 | |
1388 ;; ---------------------------------------------------------------------- | |
1389 ;; HELPER INSTRUCTIONS for saving the prologue and epilogue registers | |
1390 ;; ---------------------------------------------------------------------- | |
1391 | |
1392 ;; This pattern will match a stack adjust RTX followed by any number of push | |
1393 ;; RTXs. These RTXs will then be turned into a suitable call to a worker | |
1394 ;; function. | |
1395 | |
1396 ;; | |
1397 ;; Actually, convert the RTXs into a PREPARE instruction. | |
1398 ;; | |
1399 (define_insn "" | |
1400 [(match_parallel 0 "pattern_is_ok_for_prepare" | |
1401 [(set (reg:SI 3) | |
1402 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
1403 (set (mem:SI (plus:SI (reg:SI 3) | |
1404 (match_operand:SI 2 "immediate_operand" "i"))) | |
1405 (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])] | |
1406 "TARGET_PROLOG_FUNCTION && TARGET_V850E" | |
1407 "* return construct_prepare_instruction (operands[0]); | |
1408 " | |
1409 [(set_attr "length" "4") | |
1410 (set_attr "cc" "none")]) | |
1411 | |
1412 (define_insn "" | |
1413 [(match_parallel 0 "pattern_is_ok_for_prologue" | |
1414 [(set (reg:SI 3) | |
1415 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
1416 (set (mem:SI (plus:SI (reg:SI 3) | |
1417 (match_operand:SI 2 "immediate_operand" "i"))) | |
1418 (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])] | |
1419 "TARGET_PROLOG_FUNCTION && TARGET_V850" | |
1420 "* return construct_save_jarl (operands[0]); | |
1421 " | |
1422 [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes") | |
1423 (const_string "16") | |
1424 (const_string "4"))) | |
1425 (set_attr "cc" "clobber")]) | |
1426 | |
1427 ;; | |
1428 ;; Actually, turn the RTXs into a DISPOSE instruction. | |
1429 ;; | |
1430 (define_insn "" | |
1431 [(match_parallel 0 "pattern_is_ok_for_dispose" | |
1432 [(return) | |
1433 (set (reg:SI 3) | |
1434 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
1435 (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r") | |
1436 (mem:SI (plus:SI (reg:SI 3) | |
1437 (match_operand:SI 3 "immediate_operand" "i"))))])] | |
1438 "TARGET_PROLOG_FUNCTION && TARGET_V850E" | |
1439 "* return construct_dispose_instruction (operands[0]); | |
1440 " | |
1441 [(set_attr "length" "4") | |
1442 (set_attr "cc" "none")]) | |
1443 | |
1444 ;; This pattern will match a return RTX followed by any number of pop RTXs | |
1445 ;; and possible a stack adjustment as well. These RTXs will be turned into | |
1446 ;; a suitable call to a worker function. | |
1447 | |
1448 (define_insn "" | |
1449 [(match_parallel 0 "pattern_is_ok_for_epilogue" | |
1450 [(return) | |
1451 (set (reg:SI 3) | |
1452 (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
1453 (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r") | |
1454 (mem:SI (plus:SI (reg:SI 3) | |
1455 (match_operand:SI 3 "immediate_operand" "i"))))])] | |
1456 "TARGET_PROLOG_FUNCTION && TARGET_V850" | |
1457 "* return construct_restore_jr (operands[0]); | |
1458 " | |
1459 [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes") | |
1460 (const_string "12") | |
1461 (const_string "4"))) | |
1462 (set_attr "cc" "clobber")]) | |
1463 | |
1464 ;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION. | |
1465 (define_insn "callt_save_interrupt" | |
1466 [(unspec_volatile [(const_int 0)] 2)] | |
1467 "TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1468 ;; The CALLT instruction stores the next address of CALLT to CTPC register | |
1469 ;; without saving its previous value. So if the interrupt handler | |
1470 ;; or its caller could possibly execute the CALLT insn, save_interrupt | |
1471 ;; MUST NOT be called via CALLT. | |
1472 "* | |
1473 { | |
1474 output_asm_insn (\"addi -24, sp, sp\", operands); | |
1475 output_asm_insn (\"st.w r10, 12[sp]\", operands); | |
1476 output_asm_insn (\"stsr ctpc, r10\", operands); | |
1477 output_asm_insn (\"st.w r10, 16[sp]\", operands); | |
1478 output_asm_insn (\"stsr ctpsw, r10\", operands); | |
1479 output_asm_insn (\"st.w r10, 20[sp]\", operands); | |
1480 output_asm_insn (\"callt ctoff(__callt_save_interrupt)\", operands); | |
1481 return \"\"; | |
1482 }" | |
1483 [(set_attr "length" "26") | |
1484 (set_attr "cc" "none")]) | |
1485 | |
1486 (define_insn "callt_return_interrupt" | |
1487 [(unspec_volatile [(const_int 0)] 3)] | |
1488 "TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1489 "callt ctoff(__callt_return_interrupt)" | |
1490 [(set_attr "length" "2") | |
1491 (set_attr "cc" "clobber")]) | |
1492 | |
1493 (define_insn "save_interrupt" | |
1494 [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -16))) | |
1495 (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 30)) | |
1496 (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 4)) | |
1497 (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 1)) | |
1498 (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 10))] | |
1499 "" | |
1500 "* | |
1501 { | |
1502 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
1503 return \"add -16,sp\;st.w r10,12[sp]\;jarl __save_interrupt,r10\"; | |
1504 else | |
1505 { | |
1506 output_asm_insn (\"add -16, sp\", operands); | |
1507 output_asm_insn (\"st.w r10, 12[sp]\", operands); | |
1508 output_asm_insn (\"st.w ep, 0[sp]\", operands); | |
1509 output_asm_insn (\"st.w gp, 4[sp]\", operands); | |
1510 output_asm_insn (\"st.w r1, 8[sp]\", operands); | |
1511 output_asm_insn (\"movhi hi(__ep), r0, ep\", operands); | |
1512 output_asm_insn (\"movea lo(__ep), ep, ep\", operands); | |
1513 output_asm_insn (\"movhi hi(__gp), r0, gp\", operands); | |
1514 output_asm_insn (\"movea lo(__gp), gp, gp\", operands); | |
1515 return \"\"; | |
1516 } | |
1517 }" | |
1518 [(set (attr "length") | |
1519 (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0)) | |
1520 (const_int 10) | |
1521 (const_int 34))) | |
1522 (set_attr "cc" "clobber")]) | |
1523 | |
1524 ;; Restore r1, r4, r10, and return from the interrupt | |
1525 (define_insn "return_interrupt" | |
1526 [(return) | |
1527 (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 16))) | |
1528 (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 12)))) | |
1529 (set (reg:SI 1) (mem:SI (plus:SI (reg:SI 3) (const_int 8)))) | |
1530 (set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4)))) | |
1531 (set (reg:SI 30) (mem:SI (reg:SI 3)))] | |
1532 "" | |
1533 "* | |
1534 { | |
1535 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
1536 return \"jr __return_interrupt\"; | |
1537 else | |
1538 { | |
1539 output_asm_insn (\"ld.w 0[sp], ep\", operands); | |
1540 output_asm_insn (\"ld.w 4[sp], gp\", operands); | |
1541 output_asm_insn (\"ld.w 8[sp], r1\", operands); | |
1542 output_asm_insn (\"ld.w 12[sp], r10\", operands); | |
1543 output_asm_insn (\"addi 16, sp, sp\", operands); | |
1544 output_asm_insn (\"reti\", operands); | |
1545 return \"\"; | |
1546 } | |
1547 }" | |
1548 [(set (attr "length") | |
1549 (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0)) | |
1550 (const_int 4) | |
1551 (const_int 24))) | |
1552 (set_attr "cc" "clobber")]) | |
1553 | |
1554 ;; Save all registers except for the registers saved in save_interrupt when | |
1555 ;; an interrupt function makes a call. | |
1556 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and | |
1557 ;; all of memory. This blocks insns from being moved across this point. | |
1558 ;; This is needed because the rest of the compiler is not ready to handle | |
1559 ;; insns this complicated. | |
1560 | |
1561 (define_insn "callt_save_all_interrupt" | |
1562 [(unspec_volatile [(const_int 0)] 0)] | |
1563 "TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1564 "callt ctoff(__callt_save_all_interrupt)" | |
1565 [(set_attr "length" "2") | |
1566 (set_attr "cc" "none")]) | |
1567 | |
1568 (define_insn "save_all_interrupt" | |
1569 [(unspec_volatile [(const_int 0)] 0)] | |
1570 "" | |
1571 "* | |
1572 { | |
1573 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
1574 return \"jarl __save_all_interrupt,r10\"; | |
1575 | |
1576 output_asm_insn (\"addi -120, sp, sp\", operands); | |
1577 | |
1578 if (TARGET_EP) | |
1579 { | |
1580 output_asm_insn (\"mov ep, r1\", operands); | |
1581 output_asm_insn (\"mov sp, ep\", operands); | |
1582 output_asm_insn (\"sst.w r31, 116[ep]\", operands); | |
1583 output_asm_insn (\"sst.w r2, 112[ep]\", operands); | |
1584 output_asm_insn (\"sst.w gp, 108[ep]\", operands); | |
1585 output_asm_insn (\"sst.w r6, 104[ep]\", operands); | |
1586 output_asm_insn (\"sst.w r7, 100[ep]\", operands); | |
1587 output_asm_insn (\"sst.w r8, 96[ep]\", operands); | |
1588 output_asm_insn (\"sst.w r9, 92[ep]\", operands); | |
1589 output_asm_insn (\"sst.w r11, 88[ep]\", operands); | |
1590 output_asm_insn (\"sst.w r12, 84[ep]\", operands); | |
1591 output_asm_insn (\"sst.w r13, 80[ep]\", operands); | |
1592 output_asm_insn (\"sst.w r14, 76[ep]\", operands); | |
1593 output_asm_insn (\"sst.w r15, 72[ep]\", operands); | |
1594 output_asm_insn (\"sst.w r16, 68[ep]\", operands); | |
1595 output_asm_insn (\"sst.w r17, 64[ep]\", operands); | |
1596 output_asm_insn (\"sst.w r18, 60[ep]\", operands); | |
1597 output_asm_insn (\"sst.w r19, 56[ep]\", operands); | |
1598 output_asm_insn (\"sst.w r20, 52[ep]\", operands); | |
1599 output_asm_insn (\"sst.w r21, 48[ep]\", operands); | |
1600 output_asm_insn (\"sst.w r22, 44[ep]\", operands); | |
1601 output_asm_insn (\"sst.w r23, 40[ep]\", operands); | |
1602 output_asm_insn (\"sst.w r24, 36[ep]\", operands); | |
1603 output_asm_insn (\"sst.w r25, 32[ep]\", operands); | |
1604 output_asm_insn (\"sst.w r26, 28[ep]\", operands); | |
1605 output_asm_insn (\"sst.w r27, 24[ep]\", operands); | |
1606 output_asm_insn (\"sst.w r28, 20[ep]\", operands); | |
1607 output_asm_insn (\"sst.w r29, 16[ep]\", operands); | |
1608 output_asm_insn (\"mov r1, ep\", operands); | |
1609 } | |
1610 else | |
1611 { | |
1612 output_asm_insn (\"st.w r31, 116[sp]\", operands); | |
1613 output_asm_insn (\"st.w r2, 112[sp]\", operands); | |
1614 output_asm_insn (\"st.w gp, 108[sp]\", operands); | |
1615 output_asm_insn (\"st.w r6, 104[sp]\", operands); | |
1616 output_asm_insn (\"st.w r7, 100[sp]\", operands); | |
1617 output_asm_insn (\"st.w r8, 96[sp]\", operands); | |
1618 output_asm_insn (\"st.w r9, 92[sp]\", operands); | |
1619 output_asm_insn (\"st.w r11, 88[sp]\", operands); | |
1620 output_asm_insn (\"st.w r12, 84[sp]\", operands); | |
1621 output_asm_insn (\"st.w r13, 80[sp]\", operands); | |
1622 output_asm_insn (\"st.w r14, 76[sp]\", operands); | |
1623 output_asm_insn (\"st.w r15, 72[sp]\", operands); | |
1624 output_asm_insn (\"st.w r16, 68[sp]\", operands); | |
1625 output_asm_insn (\"st.w r17, 64[sp]\", operands); | |
1626 output_asm_insn (\"st.w r18, 60[sp]\", operands); | |
1627 output_asm_insn (\"st.w r19, 56[sp]\", operands); | |
1628 output_asm_insn (\"st.w r20, 52[sp]\", operands); | |
1629 output_asm_insn (\"st.w r21, 48[sp]\", operands); | |
1630 output_asm_insn (\"st.w r22, 44[sp]\", operands); | |
1631 output_asm_insn (\"st.w r23, 40[sp]\", operands); | |
1632 output_asm_insn (\"st.w r24, 36[sp]\", operands); | |
1633 output_asm_insn (\"st.w r25, 32[sp]\", operands); | |
1634 output_asm_insn (\"st.w r26, 28[sp]\", operands); | |
1635 output_asm_insn (\"st.w r27, 24[sp]\", operands); | |
1636 output_asm_insn (\"st.w r28, 20[sp]\", operands); | |
1637 output_asm_insn (\"st.w r29, 16[sp]\", operands); | |
1638 } | |
1639 | |
1640 return \"\"; | |
1641 }" | |
1642 [(set (attr "length") | |
1643 (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0)) | |
1644 (const_int 4) | |
1645 (const_int 62) | |
1646 )) | |
1647 (set_attr "cc" "clobber")]) | |
1648 | |
1649 (define_insn "_save_all_interrupt" | |
1650 [(unspec_volatile [(const_int 0)] 0)] | |
1651 "TARGET_V850 && ! TARGET_LONG_CALLS" | |
1652 "jarl __save_all_interrupt,r10" | |
1653 [(set_attr "length" "4") | |
1654 (set_attr "cc" "clobber")]) | |
1655 | |
1656 ;; Restore all registers saved when an interrupt function makes a call. | |
1657 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and | |
1658 ;; all of memory. This blocks insns from being moved across this point. | |
1659 ;; This is needed because the rest of the compiler is not ready to handle | |
1660 ;; insns this complicated. | |
1661 | |
1662 (define_insn "callt_restore_all_interrupt" | |
1663 [(unspec_volatile [(const_int 0)] 1)] | |
1664 "TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1665 "callt ctoff(__callt_restore_all_interrupt)" | |
1666 [(set_attr "length" "2") | |
1667 (set_attr "cc" "none")]) | |
1668 | |
1669 (define_insn "restore_all_interrupt" | |
1670 [(unspec_volatile [(const_int 0)] 1)] | |
1671 "" | |
1672 "* | |
1673 { | |
1674 if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
1675 return \"jarl __restore_all_interrupt,r10\"; | |
1676 | |
1677 if (TARGET_EP) | |
1678 { | |
1679 output_asm_insn (\"mov ep, r1\", operands); | |
1680 output_asm_insn (\"mov sp, ep\", operands); | |
1681 output_asm_insn (\"sld.w 116[ep], r31\", operands); | |
1682 output_asm_insn (\"sld.w 112[ep], r2\", operands); | |
1683 output_asm_insn (\"sld.w 108[ep], gp\", operands); | |
1684 output_asm_insn (\"sld.w 104[ep], r6\", operands); | |
1685 output_asm_insn (\"sld.w 100[ep], r7\", operands); | |
1686 output_asm_insn (\"sld.w 96[ep], r8\", operands); | |
1687 output_asm_insn (\"sld.w 92[ep], r9\", operands); | |
1688 output_asm_insn (\"sld.w 88[ep], r11\", operands); | |
1689 output_asm_insn (\"sld.w 84[ep], r12\", operands); | |
1690 output_asm_insn (\"sld.w 80[ep], r13\", operands); | |
1691 output_asm_insn (\"sld.w 76[ep], r14\", operands); | |
1692 output_asm_insn (\"sld.w 72[ep], r15\", operands); | |
1693 output_asm_insn (\"sld.w 68[ep], r16\", operands); | |
1694 output_asm_insn (\"sld.w 64[ep], r17\", operands); | |
1695 output_asm_insn (\"sld.w 60[ep], r18\", operands); | |
1696 output_asm_insn (\"sld.w 56[ep], r19\", operands); | |
1697 output_asm_insn (\"sld.w 52[ep], r20\", operands); | |
1698 output_asm_insn (\"sld.w 48[ep], r21\", operands); | |
1699 output_asm_insn (\"sld.w 44[ep], r22\", operands); | |
1700 output_asm_insn (\"sld.w 40[ep], r23\", operands); | |
1701 output_asm_insn (\"sld.w 36[ep], r24\", operands); | |
1702 output_asm_insn (\"sld.w 32[ep], r25\", operands); | |
1703 output_asm_insn (\"sld.w 28[ep], r26\", operands); | |
1704 output_asm_insn (\"sld.w 24[ep], r27\", operands); | |
1705 output_asm_insn (\"sld.w 20[ep], r28\", operands); | |
1706 output_asm_insn (\"sld.w 16[ep], r29\", operands); | |
1707 output_asm_insn (\"mov r1, ep\", operands); | |
1708 } | |
1709 else | |
1710 { | |
1711 output_asm_insn (\"ld.w 116[sp], r31\", operands); | |
1712 output_asm_insn (\"ld.w 112[sp], r2\", operands); | |
1713 output_asm_insn (\"ld.w 108[sp], gp\", operands); | |
1714 output_asm_insn (\"ld.w 104[sp], r6\", operands); | |
1715 output_asm_insn (\"ld.w 100[sp], r7\", operands); | |
1716 output_asm_insn (\"ld.w 96[sp], r8\", operands); | |
1717 output_asm_insn (\"ld.w 92[sp], r9\", operands); | |
1718 output_asm_insn (\"ld.w 88[sp], r11\", operands); | |
1719 output_asm_insn (\"ld.w 84[sp], r12\", operands); | |
1720 output_asm_insn (\"ld.w 80[sp], r13\", operands); | |
1721 output_asm_insn (\"ld.w 76[sp], r14\", operands); | |
1722 output_asm_insn (\"ld.w 72[sp], r15\", operands); | |
1723 output_asm_insn (\"ld.w 68[sp], r16\", operands); | |
1724 output_asm_insn (\"ld.w 64[sp], r17\", operands); | |
1725 output_asm_insn (\"ld.w 60[sp], r18\", operands); | |
1726 output_asm_insn (\"ld.w 56[sp], r19\", operands); | |
1727 output_asm_insn (\"ld.w 52[sp], r20\", operands); | |
1728 output_asm_insn (\"ld.w 48[sp], r21\", operands); | |
1729 output_asm_insn (\"ld.w 44[sp], r22\", operands); | |
1730 output_asm_insn (\"ld.w 40[sp], r23\", operands); | |
1731 output_asm_insn (\"ld.w 36[sp], r24\", operands); | |
1732 output_asm_insn (\"ld.w 32[sp], r25\", operands); | |
1733 output_asm_insn (\"ld.w 28[sp], r26\", operands); | |
1734 output_asm_insn (\"ld.w 24[sp], r27\", operands); | |
1735 output_asm_insn (\"ld.w 20[sp], r28\", operands); | |
1736 output_asm_insn (\"ld.w 16[sp], r29\", operands); | |
1737 } | |
1738 output_asm_insn (\"addi 120, sp, sp\", operands); | |
1739 return \"\"; | |
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 62) | |
1745 )) | |
1746 (set_attr "cc" "clobber")]) | |
1747 | |
1748 (define_insn "_restore_all_interrupt" | |
1749 [(unspec_volatile [(const_int 0)] 1)] | |
1750 "TARGET_V850 && ! TARGET_LONG_CALLS" | |
1751 "jarl __restore_all_interrupt,r10" | |
1752 [(set_attr "length" "4") | |
1753 (set_attr "cc" "clobber")]) | |
1754 | |
1755 ;; Save r6-r9 for a variable argument function | |
1756 (define_insn "save_r6_r9_v850e" | |
1757 [(set (mem:SI (reg:SI 3)) (reg:SI 6)) | |
1758 (set (mem:SI (plus:SI (reg:SI 3) (const_int 4))) (reg:SI 7)) | |
1759 (set (mem:SI (plus:SI (reg:SI 3) (const_int 8))) (reg:SI 8)) | |
1760 (set (mem:SI (plus:SI (reg:SI 3) (const_int 12))) (reg:SI 9)) | |
1761 ] | |
1762 "TARGET_PROLOG_FUNCTION && TARGET_V850E && !TARGET_DISABLE_CALLT" | |
1763 "callt ctoff(__callt_save_r6_r9)" | |
1764 [(set_attr "length" "2") | |
1765 (set_attr "cc" "none")]) | |
1766 | |
1767 (define_insn "save_r6_r9" | |
1768 [(set (mem:SI (reg:SI 3)) (reg:SI 6)) | |
1769 (set (mem:SI (plus:SI (reg:SI 3) (const_int 4))) (reg:SI 7)) | |
1770 (set (mem:SI (plus:SI (reg:SI 3) (const_int 8))) (reg:SI 8)) | |
1771 (set (mem:SI (plus:SI (reg:SI 3) (const_int 12))) (reg:SI 9)) | |
1772 (clobber (reg:SI 10))] | |
1773 "TARGET_PROLOG_FUNCTION && ! TARGET_LONG_CALLS" | |
1774 "jarl __save_r6_r9,r10" | |
1775 [(set_attr "length" "4") | |
1776 (set_attr "cc" "clobber")]) | |
1777 |