]>
Commit | Line | Data |
---|---|---|
ae180d84 | 1 | ;; GCC machine description for NEC V850 |
a5544970 | 2 | ;; Copyright (C) 1996-2019 Free Software Foundation, Inc. |
c5c76735 | 3 | ;; Contributed by Jeff Law (law@cygnus.com). |
ae180d84 | 4 | |
301ee2f3 | 5 | ;; This file is part of GCC. |
ae180d84 | 6 | |
301ee2f3 | 7 | ;; GCC is free software; you can redistribute it and/or modify |
ae180d84 | 8 | ;; it under the terms of the GNU General Public License as published by |
2f83c7d6 | 9 | ;; the Free Software Foundation; either version 3, or (at your option) |
ae180d84 JL |
10 | ;; any later version. |
11 | ||
301ee2f3 | 12 | ;; GCC is distributed in the hope that it will be useful, |
ae180d84 JL |
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | ;; GNU General Public License for more details. | |
16 | ||
17 | ;; You should have received a copy of the GNU General Public License | |
2f83c7d6 NC |
18 | ;; along with GCC; see the file COPYING3. If not see |
19 | ;; <http://www.gnu.org/licenses/>. | |
ae180d84 JL |
20 | |
21 | ;; The original PO technology requires these to be ordered by speed, | |
22 | ;; so that assigner will pick the fastest. | |
23 | ||
24 | ;; See file "rtl.def" for documentation on define_insn, match_*, et. al. | |
25 | ||
26 | ;; The V851 manual states that the instruction address space is 16M; | |
27 | ;; the various branch/call instructions only have a 22bit offset (4M range). | |
28 | ;; | |
29 | ;; One day we'll probably need to handle calls to targets more than 4M | |
30 | ;; away. | |
1ec0eb08 JL |
31 | ;; |
32 | ||
33 | ;; Condition codes | |
34 | ;; | |
35 | ;; Data movement (load, store, register copy) does not modify condition | |
36 | ;; codes. But there is no way to add two registers together without | |
37 | ;; modifying the condition codes. | |
38 | ;; | |
39 | ;; So we do not expose the condition codes until after reload. The | |
40 | ;; general approach is to have a define_insn_and_split for the basic | |
41 | ;; operation with no condition codes in the pattern (to give the | |
42 | ;; optimizers maximal freedom). The splitter adds a clobber of the | |
43 | ;; condition codes after reload. There is a distinct pattern which | |
44 | ;; sets the condition codes. | |
45 | ;; | |
46 | ;; As noted, data movement does not affect condition codes. | |
47 | ;; | |
48 | ;; Arithmetic generally set the codes in the expected ways, with mul | |
49 | ;; instructions being a notable outlier. div instructions generally | |
50 | ;; do the right thing, except when the output registers are the same | |
51 | ;; when the flags do not get set. We just assume they're clobbered | |
52 | ;; for div instructions to avoid MD bloat with marginal benefit | |
53 | ;; | |
54 | ;; The bit manipulation instructions (clr1, not1, set1) set condition | |
55 | ;; codes, but not in a useful way (they're set to the prior status of | |
56 | ;; the bit). So we just model those as clobbers. tst1 does set the | |
57 | ;; condition codes in a useful way. We could perhaps do better with | |
58 | ;; these by noting they only modify the Z flag, it doesn't seem worth | |
59 | ;; the effort. | |
60 | ;; | |
61 | ;; Byte swaps seem to change the condition codes, but I haven't tried | |
62 | ;; to describe how. | |
63 | ;; | |
64 | ;; I have no documentation on the rotate instructions. They likely | |
65 | ;; set the condition codes, but I've left them as clobbers for now. | |
66 | ||
ae180d84 JL |
67 | |
68 | ;; The size of instructions in bytes. | |
69 | ||
223a9d64 N |
70 | ;;--------------------------------------------------------------------------- |
71 | ;; Constants | |
72 | ||
73 | ;; | |
74 | (define_constants | |
75 | [(ZERO_REGNUM 0) ; constant zero | |
76 | (SP_REGNUM 3) ; Stack Pointer | |
77 | (GP_REGNUM 4) ; GP Pointer | |
1a31dcd0 | 78 | (RV_REGNUM 10) ; Return value register |
223a9d64 N |
79 | (EP_REGNUM 30) ; EP pointer |
80 | (LP_REGNUM 31) ; Return address register | |
81 | (CC_REGNUM 32) ; Condition code pseudo register | |
82 | (FCC_REGNUM 33) ; Floating Condition code pseudo register | |
83 | ] | |
84 | ) | |
85 | ||
446514af JL |
86 | (define_c_enum "unspec" [ |
87 | UNSPEC_LOOP | |
88 | UNSPEC_RCP | |
89 | UNSPEC_RSQRT | |
90 | ]) | |
91 | ||
ae180d84 | 92 | (define_attr "length" "" |
0855247a | 93 | (const_int 4)) |
ae180d84 | 94 | |
be1d3f93 NC |
95 | (define_attr "long_calls" "yes,no" |
96 | (const (if_then_else (symbol_ref "TARGET_LONG_CALLS") | |
97 | (const_string "yes") | |
98 | (const_string "no")))) | |
99 | ||
ae180d84 JL |
100 | ;; Types of instructions (for scheduling purposes). |
101 | ||
223a9d64 | 102 | (define_attr "type" "load,store,bit1,mult,macc,div,fpu,single,other" |
ae180d84 JL |
103 | (const_string "other")) |
104 | ||
dbdbd982 | 105 | (define_attr "cpu" "none,v850,v850e,v850e1,v850e2,v850e2v3,v850e3v5" |
61c4c150 | 106 | (cond [(match_test "TARGET_V850") |
d9030ea4 N |
107 | (const_string "v850") |
108 | (match_test "TARGET_V850E") | |
109 | (const_string "v850e") | |
110 | (match_test "TARGET_V850E1") | |
111 | (const_string "v850e1") | |
112 | (match_test "TARGET_V850E2") | |
113 | (const_string "v850e2") | |
dbdbd982 NC |
114 | (match_test "TARGET_V850E2V3") |
115 | (const_string "v850e2v3") | |
116 | (match_test "TARGET_V850E3V5") | |
117 | (const_string "v850e3v5")] | |
d9030ea4 | 118 | (const_string "none"))) |
223a9d64 | 119 | |
ae180d84 JL |
120 | \f |
121 | ;; Function units for the V850. As best as I can tell, there's | |
122 | ;; a traditional memory load/use stall as well as a stall if | |
123 | ;; the result of a multiply is used too early. | |
ae180d84 | 124 | |
dbeff3e5 SB |
125 | (define_insn_reservation "v850_other" 1 |
126 | (eq_attr "type" "other") | |
127 | "nothing") | |
128 | (define_insn_reservation "v850_mult" 2 | |
129 | (eq_attr "type" "mult") | |
130 | "nothing") | |
131 | (define_insn_reservation "v850_memory" 2 | |
132 | (eq_attr "type" "load") | |
133 | "nothing") | |
83310f56 KH |
134 | |
135 | (include "predicates.md") | |
c6150df6 | 136 | (include "constraints.md") |
ae180d84 JL |
137 | \f |
138 | ;; ---------------------------------------------------------------------- | |
139 | ;; MOVE INSTRUCTIONS | |
140 | ;; ---------------------------------------------------------------------- | |
dbdbd982 NC |
141 | ;; movdi |
142 | ||
143 | (define_expand "movdi" | |
144 | [(set (match_operand:DI 0 "general_operand") | |
145 | (match_operand:DI 1 "general_operand"))] | |
146 | "TARGET_V850E3V5_UP" | |
147 | { | |
148 | /* One of the ops has to be in a register or 0. */ | |
149 | if (!register_operand (operand0, DImode) | |
150 | && !register_operand (operand1, DImode)) | |
151 | operands[1] = copy_to_mode_reg (DImode, operand1); | |
152 | ||
153 | if (register_operand (operand0, DImode) | |
154 | && (CONST_INT_P (operands[1]) || CONST_DOUBLE_P (operands[1]))) | |
155 | { | |
156 | int i; | |
157 | ||
158 | for (i = 0; i < UNITS_PER_WORD * 2; i += UNITS_PER_WORD) | |
159 | emit_move_insn (simplify_gen_subreg (SImode, operands[0], DImode, i), | |
160 | simplify_gen_subreg (SImode, operands[1], DImode, i)); | |
161 | DONE; | |
162 | } | |
163 | } | |
164 | ) | |
165 | ||
166 | (define_insn "*movdi_internal" | |
167 | [(set (match_operand:DI 0 "nonimmediate_operand" "=r,e!r,m") | |
168 | (match_operand:DI 1 "nonimmediate_operand" "r,m,e!r"))] | |
169 | "TARGET_V850E3V5_UP | |
170 | || (register_operand (operands[0], DImode) && register_operand (operands[1], DImode))" | |
171 | { return v850_gen_movdi (operands); } | |
172 | [(set_attr "length" "4,12,12") | |
03e32fb7 | 173 | (set_attr "type" "other,load,store")]) |
dbdbd982 | 174 | |
ae180d84 JL |
175 | ;; movqi |
176 | ||
177 | (define_expand "movqi" | |
178 | [(set (match_operand:QI 0 "general_operand" "") | |
179 | (match_operand:QI 1 "general_operand" ""))] | |
180 | "" | |
d9030ea4 N |
181 | { |
182 | /* One of the ops has to be in a register or 0 */ | |
183 | if (!register_operand (operand0, QImode) | |
184 | && !reg_or_0_operand (operand1, QImode)) | |
185 | operands[1] = copy_to_mode_reg (QImode, operand1); | |
186 | }) | |
ae180d84 JL |
187 | |
188 | (define_insn "*movqi_internal" | |
525f6ed7 | 189 | [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,Q,r,m,m") |
ae180d84 JL |
190 | (match_operand:QI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))] |
191 | "register_operand (operands[0], QImode) | |
192 | || reg_or_0_operand (operands[1], QImode)" | |
d9030ea4 N |
193 | { |
194 | return output_move_single (operands); | |
195 | } | |
ae180d84 | 196 | [(set_attr "length" "2,4,2,2,4,4,4") |
223a9d64 | 197 | (set_attr "type" "other,other,load,other,load,store,store")]) |
ae180d84 JL |
198 | |
199 | ;; movhi | |
200 | ||
201 | (define_expand "movhi" | |
202 | [(set (match_operand:HI 0 "general_operand" "") | |
203 | (match_operand:HI 1 "general_operand" ""))] | |
204 | "" | |
ae180d84 JL |
205 | { |
206 | /* One of the ops has to be in a register or 0 */ | |
207 | if (!register_operand (operand0, HImode) | |
208 | && !reg_or_0_operand (operand1, HImode)) | |
209 | operands[1] = copy_to_mode_reg (HImode, operand1); | |
d9030ea4 | 210 | }) |
ae180d84 JL |
211 | |
212 | (define_insn "*movhi_internal" | |
525f6ed7 | 213 | [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,Q,r,m,m") |
ae180d84 JL |
214 | (match_operand:HI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))] |
215 | "register_operand (operands[0], HImode) | |
216 | || reg_or_0_operand (operands[1], HImode)" | |
d9030ea4 N |
217 | { |
218 | return output_move_single (operands); | |
219 | } | |
ae180d84 | 220 | [(set_attr "length" "2,4,2,2,4,4,4") |
223a9d64 | 221 | (set_attr "type" "other,other,load,other,load,store,store")]) |
ae180d84 JL |
222 | |
223 | ;; movsi and helpers | |
224 | ||
225 | (define_insn "*movsi_high" | |
226 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1dcad079 | 227 | (high:SI (match_operand 1 "immediate_operand" "i")))] |
ae180d84 JL |
228 | "" |
229 | "movhi hi(%1),%.,%0" | |
230 | [(set_attr "length" "4") | |
ae180d84 JL |
231 | (set_attr "type" "other")]) |
232 | ||
233 | (define_insn "*movsi_lo" | |
234 | [(set (match_operand:SI 0 "register_operand" "=r") | |
235 | (lo_sum:SI (match_operand:SI 1 "register_operand" "r") | |
236 | (match_operand:SI 2 "immediate_operand" "i")))] | |
237 | "" | |
238 | "movea lo(%2),%1,%0" | |
239 | [(set_attr "length" "4") | |
ae180d84 JL |
240 | (set_attr "type" "other")]) |
241 | ||
242 | (define_expand "movsi" | |
243 | [(set (match_operand:SI 0 "general_operand" "") | |
244 | (match_operand:SI 1 "general_operand" ""))] | |
245 | "" | |
d9030ea4 N |
246 | { |
247 | /* One of the ops has to be in a register or 0 */ | |
248 | if (!register_operand (operand0, SImode) | |
249 | && !reg_or_0_operand (operand1, SImode)) | |
250 | operands[1] = copy_to_mode_reg (SImode, operand1); | |
251 | ||
252 | /* Some constants, as well as symbolic operands | |
253 | must be done with HIGH & LO_SUM patterns. */ | |
254 | if (CONSTANT_P (operands[1]) | |
255 | && GET_CODE (operands[1]) != HIGH | |
dbdbd982 | 256 | && ! (TARGET_V850E_UP) |
d9030ea4 N |
257 | && !special_symbolref_operand (operands[1], VOIDmode) |
258 | && !(GET_CODE (operands[1]) == CONST_INT | |
259 | && (CONST_OK_FOR_J (INTVAL (operands[1])) | |
260 | || CONST_OK_FOR_K (INTVAL (operands[1])) | |
261 | || CONST_OK_FOR_L (INTVAL (operands[1]))))) | |
262 | { | |
263 | rtx temp; | |
264 | ||
265 | if (reload_in_progress || reload_completed) | |
266 | temp = operands[0]; | |
267 | else | |
268 | temp = gen_reg_rtx (SImode); | |
269 | ||
f7df4a84 RS |
270 | emit_insn (gen_rtx_SET (temp, gen_rtx_HIGH (SImode, operand1))); |
271 | emit_insn (gen_rtx_SET (operand0, | |
d9030ea4 N |
272 | gen_rtx_LO_SUM (SImode, temp, operand1))); |
273 | DONE; | |
274 | } | |
275 | }) | |
ae180d84 | 276 | |
b4378319 | 277 | ;; This is the same as the following pattern, except that it includes |
22f23985 | 278 | ;; support for arbitrary 32-bit immediates. |
b4378319 NC |
279 | |
280 | ;; ??? This always loads addresses using hilo. If the only use of this address | |
281 | ;; was in a load/store, then we would get smaller code if we only loaded the | |
282 | ;; upper part with hi, and then put the lower part in the load/store insn. | |
283 | ||
284 | (define_insn "*movsi_internal_v850e" | |
525f6ed7 | 285 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,Q,r,r,m,m,r") |
b4378319 | 286 | (match_operand:SI 1 "general_operand" "Jr,K,L,Q,Ir,m,R,r,I,i"))] |
dbdbd982 | 287 | "(TARGET_V850E_UP) |
b4378319 NC |
288 | && (register_operand (operands[0], SImode) |
289 | || reg_or_0_operand (operands[1], SImode))" | |
d9030ea4 N |
290 | { |
291 | return output_move_single (operands); | |
292 | } | |
b4378319 | 293 | [(set_attr "length" "2,4,4,2,2,4,4,4,4,6") |
223a9d64 | 294 | (set_attr "type" "other,other,other,load,other,load,other,store,store,other")]) |
b4378319 | 295 | |
ae180d84 | 296 | (define_insn "*movsi_internal" |
525f6ed7 | 297 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,Q,r,r,m,m") |
ae180d84 JL |
298 | (match_operand:SI 1 "movsi_source_operand" "Jr,K,L,Q,Ir,m,R,r,I"))] |
299 | "register_operand (operands[0], SImode) | |
300 | || reg_or_0_operand (operands[1], SImode)" | |
d9030ea4 N |
301 | { |
302 | return output_move_single (operands); | |
303 | } | |
ae180d84 | 304 | [(set_attr "length" "2,4,4,2,2,4,4,4,4") |
223a9d64 | 305 | (set_attr "type" "other,other,other,load,other,load,store,store,other")]) |
ae180d84 | 306 | |
ae180d84 | 307 | (define_insn "*movsf_internal" |
525f6ed7 | 308 | [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,r,Q,r,m,m,r") |
ae180d84 JL |
309 | (match_operand:SF 1 "general_operand" "Jr,K,L,n,Q,Ir,m,r,IG,iF"))] |
310 | "register_operand (operands[0], SFmode) | |
311 | || reg_or_0_operand (operands[1], SFmode)" | |
d9030ea4 N |
312 | { |
313 | return output_move_single (operands); | |
314 | } | |
ae180d84 | 315 | [(set_attr "length" "2,4,4,8,2,2,4,4,4,8") |
223a9d64 | 316 | (set_attr "type" "other,other,other,other,load,other,load,store,store,other")]) |
ae180d84 | 317 | |
ae180d84 JL |
318 | ;; ---------------------------------------------------------------------- |
319 | ;; TEST INSTRUCTIONS | |
320 | ;; ---------------------------------------------------------------------- | |
321 | ||
322 | (define_insn "*v850_tst1" | |
1ec0eb08 | 323 | [(set (reg:CCZ CC_REGNUM) |
f90b7a5a PB |
324 | (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") |
325 | (const_int 1) | |
326 | (match_operand:QI 1 "const_int_operand" "n")) | |
327 | (const_int 0)))] | |
1ec0eb08 | 328 | "reload_completed" |
ae180d84 | 329 | "tst1 %1,%0" |
03e32fb7 | 330 | [(set_attr "length" "4")]) |
ae180d84 | 331 | |
1933ec7e | 332 | ;; This replaces ld.b;sar;andi with tst1;setf nz. |
1ec0eb08 | 333 | ;; Should there be variants for HI or SI modes? |
1933ec7e | 334 | |
1ec0eb08 | 335 | (define_insn_and_split "" |
1933ec7e | 336 | [(set (match_operand:SI 0 "register_operand" "") |
f90b7a5a PB |
337 | (compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "") |
338 | (const_int 1) | |
339 | (match_operand 2 "const_int_operand" "")) | |
340 | (const_int 0)))] | |
1933ec7e | 341 | "" |
1ec0eb08 JL |
342 | "#" |
343 | "reload_completed" | |
344 | [(set (reg:CCZ CC_REGNUM) (compare (zero_extract:SI (match_dup 1) | |
345 | (const_int 1) | |
346 | (match_dup 2)) | |
347 | (const_int 0))) | |
348 | (set (match_dup 0) (ne:SI (reg:CCZ CC_REGNUM) (const_int 0)))]) | |
1933ec7e | 349 | |
f90b7a5a | 350 | (define_expand "cbranchsi4" |
1ec0eb08 | 351 | [(set (pc) |
f90b7a5a | 352 | (if_then_else |
1ec0eb08 JL |
353 | (match_operator 0 "comparison_operator" |
354 | [(match_operand:SI 1 "register_operand") | |
355 | (match_operand:SI 2 "reg_or_int5_operand")]) | |
f90b7a5a PB |
356 | (label_ref (match_operand 3 "" "")) |
357 | (pc)))] | |
358 | "") | |
359 | ||
223a9d64 | 360 | (define_insn "cmpsi_insn" |
1ec0eb08 | 361 | [(set (reg:CC CC_REGNUM) |
223a9d64 N |
362 | (compare (match_operand:SI 0 "register_operand" "r,r") |
363 | (match_operand:SI 1 "reg_or_int5_operand" "r,J")))] | |
1ec0eb08 JL |
364 | "reload_completed" |
365 | "cmp %1,%0" | |
03e32fb7 | 366 | [(set_attr "length" "2,2")]) |
223a9d64 | 367 | |
1ec0eb08 | 368 | (define_insn_and_split "cbranchsf4" |
3cd232b5 NDD |
369 | [(set (pc) |
370 | (if_then_else (match_operator 0 "ordered_comparison_operator" | |
1ec0eb08 JL |
371 | [(match_operand:SF 1 "register_operand" "r") |
372 | (match_operand:SF 2 "register_operand" "r")]) | |
3cd232b5 | 373 | (label_ref (match_operand 3 "")) |
1ec0eb08 | 374 | (pc)))] |
dbdbd982 | 375 | "TARGET_USE_FPU" |
1ec0eb08 JL |
376 | "#" |
377 | "reload_completed" | |
378 | [(set (match_dup 4) (match_dup 5)) | |
379 | (set (pc) | |
380 | (if_then_else (match_dup 6) | |
381 | (label_ref (match_dup 3)) | |
382 | (pc)))] | |
383 | "{ | |
384 | /* This will generate the comparison insn at the start of | |
385 | the sequence and get us the right mode to use for our | |
386 | condition code registers. */ | |
387 | enum machine_mode mode | |
388 | = v850_gen_float_compare (GET_CODE (operands[0]), | |
389 | GET_MODE (operands[1]), | |
390 | operands[1], operands[2]); | |
391 | /* We want operands referring to CC_REGNUM and FCC_REGNUM | |
392 | in mode MODE. */ | |
393 | operands[4] = gen_rtx_REG (mode, CC_REGNUM); | |
394 | operands[5] = gen_rtx_REG (mode, FCC_REGNUM); | |
395 | if (mode == CC_FPU_NEmode) | |
396 | operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx); | |
397 | else | |
398 | operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx); | |
399 | }") | |
3cd232b5 NDD |
400 | |
401 | (define_insn "cstoresf4" | |
402 | [(set (match_operand:SI 0 "register_operand" "=r") | |
403 | (match_operator:SI 1 "ordered_comparison_operator" | |
404 | [(match_operand:SF 2 "register_operand" "r") | |
1ec0eb08 JL |
405 | (match_operand:SF 3 "register_operand" "r")])) |
406 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 407 | "TARGET_USE_FPU" |
3cd232b5 NDD |
408 | { |
409 | if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) | |
410 | return "cmpf.s %c1, %z2, %z3 ; trfsr ; setf nz, %0"; | |
411 | if (GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE) | |
412 | return "cmpf.s %c1, %z2, %z3 ; trfsr ; setf z, %0"; | |
413 | if (GET_CODE (operands[1]) == EQ) | |
414 | return "cmpf.s eq, %z2, %z3 ; trfsr ; setf z, %0"; | |
415 | if (GET_CODE (operands[1]) == NE) | |
416 | return "cmpf.s neq, %z2, %z3 ; trfsr ; setf nz, %0"; | |
417 | gcc_unreachable (); | |
418 | } | |
419 | [(set_attr "length" "12") | |
03e32fb7 | 420 | (set_attr "type" "fpu")]) |
3cd232b5 | 421 | |
1ec0eb08 | 422 | (define_insn_and_split "cbranchdf4" |
3cd232b5 NDD |
423 | [(set (pc) |
424 | (if_then_else (match_operator 0 "ordered_comparison_operator" | |
1ec0eb08 JL |
425 | [(match_operand:DF 1 "even_reg_operand" "r") |
426 | (match_operand:DF 2 "even_reg_operand" "r")]) | |
3cd232b5 | 427 | (label_ref (match_operand 3 "")) |
1ec0eb08 | 428 | (pc)))] |
dbdbd982 | 429 | "TARGET_USE_FPU" |
1ec0eb08 JL |
430 | "#" |
431 | "reload_completed" | |
432 | ;; How to get the mode here? | |
433 | [(set (match_dup 4) (match_dup 5)) | |
434 | (set (pc) | |
435 | (if_then_else (match_dup 6) | |
436 | (label_ref (match_dup 3)) | |
437 | (pc)))] | |
438 | "{ | |
439 | /* This will generate the comparison insn at the start of | |
440 | the sequence and get us the right mode to use for our | |
441 | condition code registers. */ | |
442 | enum machine_mode mode | |
443 | = v850_gen_float_compare (GET_CODE (operands[0]), | |
444 | GET_MODE (operands[1]), | |
445 | operands[1], operands[2]); | |
446 | PUT_MODE (operands[0], mode); | |
447 | /* We want operands referring to CC_REGNUM and FCC_REGNUM | |
448 | in mode MODE. */ | |
449 | operands[4] = gen_rtx_REG (mode, CC_REGNUM); | |
450 | operands[5] = gen_rtx_REG (mode, FCC_REGNUM); | |
451 | if (mode == CC_FPU_NEmode) | |
452 | operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx); | |
453 | else | |
454 | operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx); | |
455 | }") | |
3cd232b5 NDD |
456 | |
457 | (define_insn "cstoredf4" | |
458 | [(set (match_operand:SI 0 "register_operand" "=r") | |
459 | (match_operator:SI 1 "ordered_comparison_operator" | |
460 | [(match_operand:DF 2 "even_reg_operand" "r") | |
1ec0eb08 JL |
461 | (match_operand:DF 3 "even_reg_operand" "r")])) |
462 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 463 | "TARGET_USE_FPU" |
3cd232b5 NDD |
464 | { |
465 | if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) | |
466 | return "cmpf.d %c1, %z2, %z3 ; trfsr ; setf nz, %0"; | |
467 | if (GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE) | |
468 | return "cmpf.d %c1, %z2, %z3 ; trfsr ; setf z, %0"; | |
469 | if (GET_CODE (operands[1]) == EQ) | |
470 | return "cmpf.d eq, %z2, %z3 ; trfsr ; setf z ,%0"; | |
471 | if (GET_CODE (operands[1]) == NE) | |
472 | return "cmpf.d neq, %z2, %z3 ; trfsr ; setf nz, %0"; | |
473 | gcc_unreachable (); | |
474 | } | |
475 | [(set_attr "length" "12") | |
03e32fb7 | 476 | (set_attr "type" "fpu")]) |
3cd232b5 | 477 | |
ae180d84 JL |
478 | ;; ---------------------------------------------------------------------- |
479 | ;; ADD INSTRUCTIONS | |
480 | ;; ---------------------------------------------------------------------- | |
481 | ||
1ec0eb08 JL |
482 | (define_insn_and_split "addsi3" |
483 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
484 | (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") | |
485 | (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))] | |
486 | "" | |
487 | "#" | |
488 | "reload_completed" | |
489 | [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) | |
490 | (clobber (reg:CC CC_REGNUM))])]) | |
491 | ||
492 | (define_insn "addsi3_clobber_flags" | |
1933ec7e | 493 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
ae180d84 | 494 | (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") |
223a9d64 N |
495 | (match_operand:SI 2 "nonmemory_operand" "rJ,K,U"))) |
496 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
497 | "" |
498 | "@ | |
499 | add %2,%0 | |
500 | addi %2,%1,%0 | |
1933ec7e | 501 | addi %O2(%P2),%1,%0" |
03e32fb7 | 502 | [(set_attr "length" "2,4,4")]) |
ae180d84 | 503 | |
f8dc0f2b JL |
504 | (define_insn "addsi3_set_flags" |
505 | [(set (reg:CCNZ CC_REGNUM) | |
506 | (compare:CCNZ (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") | |
507 | (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")) | |
508 | (const_int 0))) | |
509 | (set (match_operand:SI 0 "register_operand" "=r,r,r") | |
510 | (plus:SI (match_dup 1) (match_dup 2)))] | |
511 | "reload_completed" | |
512 | "@ | |
513 | add %2,%0 | |
514 | addi %2,%1,%0 | |
515 | addi %O2(%P2),%1,%0" | |
516 | [(set_attr "length" "2,4,4")]) | |
517 | ||
ae180d84 JL |
518 | ;; ---------------------------------------------------------------------- |
519 | ;; SUBTRACT INSTRUCTIONS | |
520 | ;; ---------------------------------------------------------------------- | |
1ec0eb08 JL |
521 | (define_insn_and_split "subsi3" |
522 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
523 | (minus:SI (match_operand:SI 1 "register_operand" "0,r") | |
524 | (match_operand:SI 2 "register_operand" "r,0")))] | |
525 | "" | |
526 | "#" | |
527 | "reload_completed" | |
528 | [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) | |
529 | (clobber (reg:CC CC_REGNUM))])]) | |
ae180d84 | 530 | |
1ec0eb08 | 531 | (define_insn "subsi3_clobber_flags" |
ae180d84 JL |
532 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
533 | (minus:SI (match_operand:SI 1 "register_operand" "0,r") | |
223a9d64 N |
534 | (match_operand:SI 2 "register_operand" "r,0"))) |
535 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
536 | "" |
537 | "@ | |
538 | sub %2,%0 | |
539 | subr %1,%0" | |
03e32fb7 | 540 | [(set_attr "length" "2,2")]) |
ae180d84 | 541 | |
f8dc0f2b JL |
542 | (define_insn "*subsi3_set_flags" |
543 | [(set (reg:CCNZ CC_REGNUM) | |
544 | (compare:CCNZ (minus:SI (match_operand:SI 1 "register_operand" "0,r") | |
545 | (match_operand:SI 2 "nonmemory_operand" "r,0")) | |
546 | (const_int 0))) | |
547 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
548 | (minus:SI (match_dup 1) (match_dup 2)))] | |
549 | "reload_completed" | |
550 | "@ | |
551 | sub %2,%0 | |
552 | subr %1,%0" | |
553 | [(set_attr "length" "2,2")]) | |
554 | ||
1ec0eb08 JL |
555 | (define_insn_and_split "negsi2" |
556 | [(set (match_operand:SI 0 "register_operand" "=r") | |
557 | (neg:SI (match_operand:SI 1 "register_operand" "0")))] | |
558 | "" | |
559 | "#" | |
560 | "reload_completed" | |
561 | [(parallel [(set (match_dup 0) (neg:SI (match_dup 1))) | |
562 | (clobber (reg:CC CC_REGNUM))])]) | |
563 | ||
564 | (define_insn "negsi2_clobber_flags" | |
ae180d84 | 565 | [(set (match_operand:SI 0 "register_operand" "=r") |
223a9d64 N |
566 | (neg:SI (match_operand:SI 1 "register_operand" "0"))) |
567 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
568 | "" |
569 | "subr %.,%0" | |
03e32fb7 | 570 | [(set_attr "length" "2")]) |
ae180d84 | 571 | |
f8dc0f2b JL |
572 | (define_insn "*negsi2_set_flags" |
573 | [(set (reg:CCNZ CC_REGNUM) | |
574 | (compare:CCNZ (neg:SI (match_operand:SI 1 "register_operand" "0")) | |
575 | (const_int 0))) | |
576 | (set (match_operand:SI 0 "register_operand" "=r") | |
577 | (neg:SI (match_dup 1)))] | |
578 | "reload_completed" | |
579 | "subr %.,%0" | |
580 | [(set_attr "length" "2")]) | |
581 | ||
ae180d84 JL |
582 | ;; ---------------------------------------------------------------------- |
583 | ;; MULTIPLY INSTRUCTIONS | |
584 | ;; ---------------------------------------------------------------------- | |
585 | ||
586 | (define_expand "mulhisi3" | |
587 | [(set (match_operand:SI 0 "register_operand" "") | |
588 | (mult:SI | |
589 | (sign_extend:SI (match_operand:HI 1 "register_operand" "")) | |
590 | (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))] | |
591 | "" | |
d9030ea4 N |
592 | { |
593 | if (GET_CODE (operands[2]) == CONST_INT) | |
594 | { | |
595 | emit_insn (gen_mulhisi3_internal2 (operands[0], operands[1], operands[2])); | |
596 | DONE; | |
597 | } | |
598 | }) | |
ae180d84 JL |
599 | |
600 | (define_insn "*mulhisi3_internal1" | |
601 | [(set (match_operand:SI 0 "register_operand" "=r") | |
602 | (mult:SI | |
603 | (sign_extend:SI (match_operand:HI 1 "register_operand" "%0")) | |
604 | (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))] | |
605 | "" | |
606 | "mulh %2,%0" | |
607 | [(set_attr "length" "2") | |
ae180d84 JL |
608 | (set_attr "type" "mult")]) |
609 | ||
15bb534e | 610 | (define_insn "mulhisi3_internal2" |
ae180d84 JL |
611 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
612 | (mult:SI | |
613 | (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,r")) | |
15bb534e | 614 | (match_operand:HI 2 "const_int_operand" "J,K")))] |
ae180d84 JL |
615 | "" |
616 | "@ | |
617 | mulh %2,%0 | |
618 | mulhi %2,%1,%0" | |
619 | [(set_attr "length" "2,4") | |
ae180d84 JL |
620 | (set_attr "type" "mult")]) |
621 | ||
b4378319 NC |
622 | ;; ??? The scheduling info is probably wrong. |
623 | ||
22f23985 | 624 | ;; ??? This instruction can also generate the 32-bit highpart, but using it |
b4378319 NC |
625 | ;; may increase code size counter to the desired result. |
626 | ||
627 | ;; ??? This instructions can also give a DImode result. | |
628 | ||
629 | ;; ??? There is unsigned version, but it matters only for the DImode/highpart | |
630 | ;; results. | |
631 | ||
632 | (define_insn "mulsi3" | |
633 | [(set (match_operand:SI 0 "register_operand" "=r") | |
634 | (mult:SI (match_operand:SI 1 "register_operand" "%0") | |
b4378319 | 635 | (match_operand:SI 2 "reg_or_int9_operand" "rO")))] |
dbdbd982 | 636 | "(TARGET_V850E_UP)" |
b4378319 NC |
637 | "mul %2,%1,%." |
638 | [(set_attr "length" "4") | |
b4378319 NC |
639 | (set_attr "type" "mult")]) |
640 | ||
641 | ;; ---------------------------------------------------------------------- | |
642 | ;; DIVIDE INSTRUCTIONS | |
643 | ;; ---------------------------------------------------------------------- | |
644 | ||
645 | ;; ??? These insns do set the Z/N condition codes, except that they are based | |
646 | ;; on only one of the two results, so it doesn't seem to make sense to use | |
647 | ;; them. | |
648 | ||
649 | ;; ??? The scheduling info is probably wrong. | |
650 | ||
651 | (define_insn "divmodsi4" | |
652 | [(set (match_operand:SI 0 "register_operand" "=r") | |
653 | (div:SI (match_operand:SI 1 "register_operand" "0") | |
654 | (match_operand:SI 2 "register_operand" "r"))) | |
655 | (set (match_operand:SI 3 "register_operand" "=r") | |
656 | (mod:SI (match_dup 1) | |
223a9d64 N |
657 | (match_dup 2))) |
658 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 659 | "TARGET_V850E_UP" |
d9030ea4 | 660 | { |
dbdbd982 | 661 | if (TARGET_V850E2_UP) |
d9030ea4 | 662 | return "divq %2,%0,%3"; |
1dcad079 | 663 | else |
d9030ea4 N |
664 | return "div %2,%0,%3"; |
665 | } | |
b4378319 | 666 | [(set_attr "length" "4") |
223a9d64 | 667 | (set_attr "type" "div")]) |
b4378319 NC |
668 | |
669 | (define_insn "udivmodsi4" | |
670 | [(set (match_operand:SI 0 "register_operand" "=r") | |
671 | (udiv:SI (match_operand:SI 1 "register_operand" "0") | |
672 | (match_operand:SI 2 "register_operand" "r"))) | |
673 | (set (match_operand:SI 3 "register_operand" "=r") | |
674 | (umod:SI (match_dup 1) | |
223a9d64 N |
675 | (match_dup 2))) |
676 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 677 | "TARGET_V850E_UP" |
d9030ea4 | 678 | { |
dbdbd982 | 679 | if (TARGET_V850E2_UP) |
d9030ea4 N |
680 | return "divqu %2,%0,%3"; |
681 | else | |
682 | return "divu %2,%0,%3"; | |
683 | } | |
b4378319 | 684 | [(set_attr "length" "4") |
223a9d64 | 685 | (set_attr "type" "div")]) |
b4378319 NC |
686 | |
687 | ;; ??? There is a 2 byte instruction for generating only the quotient. | |
688 | ;; However, it isn't clear how to compute the length field correctly. | |
689 | ||
690 | (define_insn "divmodhi4" | |
691 | [(set (match_operand:HI 0 "register_operand" "=r") | |
692 | (div:HI (match_operand:HI 1 "register_operand" "0") | |
693 | (match_operand:HI 2 "register_operand" "r"))) | |
694 | (set (match_operand:HI 3 "register_operand" "=r") | |
695 | (mod:HI (match_dup 1) | |
223a9d64 N |
696 | (match_dup 2))) |
697 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 698 | "TARGET_V850E_UP" |
1ec0eb08 | 699 | "sxh %0\\n\\tdivh %2,%0,%3" |
ad111b8e | 700 | [(set_attr "length" "6") |
223a9d64 | 701 | (set_attr "type" "div")]) |
b4378319 | 702 | |
ad111b8e JL |
703 | ;; The half word needs to be zero/sign extended to 32 bits before doing |
704 | ;; the division/modulo operation. | |
b4378319 NC |
705 | |
706 | (define_insn "udivmodhi4" | |
707 | [(set (match_operand:HI 0 "register_operand" "=r") | |
708 | (udiv:HI (match_operand:HI 1 "register_operand" "0") | |
709 | (match_operand:HI 2 "register_operand" "r"))) | |
710 | (set (match_operand:HI 3 "register_operand" "=r") | |
711 | (umod:HI (match_dup 1) | |
223a9d64 N |
712 | (match_dup 2))) |
713 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 714 | "TARGET_V850E_UP" |
1ec0eb08 | 715 | "zxh %0\\n\\ndivhu %2,%0,%3" |
ad111b8e | 716 | [(set_attr "length" "6") |
223a9d64 | 717 | (set_attr "type" "div")]) |
ae180d84 JL |
718 | \f |
719 | ;; ---------------------------------------------------------------------- | |
720 | ;; AND INSTRUCTIONS | |
721 | ;; ---------------------------------------------------------------------- | |
722 | ||
723 | (define_insn "*v850_clr1_1" | |
724 | [(set (match_operand:QI 0 "memory_operand" "=m") | |
725 | (subreg:QI | |
726 | (and:SI (subreg:SI (match_dup 0) 0) | |
223a9d64 N |
727 | (match_operand:QI 1 "not_power_of_two_operand" "")) 0)) |
728 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 | 729 | "" |
ae180d84 JL |
730 | { |
731 | rtx xoperands[2]; | |
732 | xoperands[0] = operands[0]; | |
733 | xoperands[1] = GEN_INT (~INTVAL (operands[1]) & 0xff); | |
d9030ea4 N |
734 | output_asm_insn ("clr1 %M1,%0", xoperands); |
735 | return ""; | |
736 | } | |
ae180d84 | 737 | [(set_attr "length" "4") |
223a9d64 | 738 | (set_attr "type" "bit1")]) |
ae180d84 JL |
739 | |
740 | (define_insn "*v850_clr1_2" | |
29a65e3d | 741 | [(set (match_operand:HI 0 "indirect_operand" "=m") |
ae180d84 JL |
742 | (subreg:HI |
743 | (and:SI (subreg:SI (match_dup 0) 0) | |
223a9d64 N |
744 | (match_operand:HI 1 "not_power_of_two_operand" "")) 0)) |
745 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 | 746 | "" |
ae180d84 JL |
747 | { |
748 | int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffff); | |
749 | ||
750 | rtx xoperands[2]; | |
c5c76735 | 751 | xoperands[0] = gen_rtx_MEM (QImode, |
0a81f074 RS |
752 | plus_constant (Pmode, XEXP (operands[0], 0), |
753 | log2 / 8)); | |
ae180d84 | 754 | xoperands[1] = GEN_INT (log2 % 8); |
d9030ea4 N |
755 | output_asm_insn ("clr1 %1,%0", xoperands); |
756 | return ""; | |
757 | } | |
ae180d84 | 758 | [(set_attr "length" "4") |
223a9d64 | 759 | (set_attr "type" "bit1")]) |
ae180d84 JL |
760 | |
761 | (define_insn "*v850_clr1_3" | |
29a65e3d | 762 | [(set (match_operand:SI 0 "indirect_operand" "=m") |
ae180d84 | 763 | (and:SI (match_dup 0) |
223a9d64 N |
764 | (match_operand:SI 1 "not_power_of_two_operand" ""))) |
765 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 | 766 | "" |
ae180d84 JL |
767 | { |
768 | int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffffffff); | |
769 | ||
770 | rtx xoperands[2]; | |
c5c76735 | 771 | xoperands[0] = gen_rtx_MEM (QImode, |
0a81f074 RS |
772 | plus_constant (Pmode, XEXP (operands[0], 0), |
773 | log2 / 8)); | |
ae180d84 | 774 | xoperands[1] = GEN_INT (log2 % 8); |
d9030ea4 N |
775 | output_asm_insn ("clr1 %1,%0", xoperands); |
776 | return ""; | |
777 | } | |
ae180d84 | 778 | [(set_attr "length" "4") |
223a9d64 | 779 | (set_attr "type" "bit1")]) |
ae180d84 | 780 | |
1ec0eb08 JL |
781 | (define_insn_and_split "andsi3" |
782 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
783 | (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
784 | (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] | |
785 | "" | |
786 | "#" | |
787 | "reload_completed" | |
788 | [(parallel [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2))) | |
789 | (clobber (reg:CC CC_REGNUM))])]) | |
790 | ||
791 | (define_insn "andsi3_clobber_flags" | |
ae180d84 JL |
792 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
793 | (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
223a9d64 N |
794 | (match_operand:SI 2 "nonmemory_operand" "r,I,M"))) |
795 | (clobber (reg:CC CC_REGNUM))] | |
1ec0eb08 | 796 | "reload_completed" |
ae180d84 JL |
797 | "@ |
798 | and %2,%0 | |
799 | and %.,%0 | |
800 | andi %2,%1,%0" | |
03e32fb7 | 801 | [(set_attr "length" "2,2,4")]) |
ae180d84 | 802 | |
f8dc0f2b JL |
803 | (define_insn "andsi3_set_flags" |
804 | [(set (reg:CC CC_REGNUM) | |
805 | (compare:CC (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
806 | (match_operand:SI 2 "nonmemory_operand" "r,I,M")) | |
807 | (const_int 0))) | |
808 | (set (match_operand:SI 0 "register_operand" "=r,r,r") | |
809 | (and:SI (match_dup 1) (match_dup 2)))] | |
810 | "reload_completed" | |
811 | "@ | |
812 | and %2,%0 | |
813 | and %.,%0 | |
814 | andi %2,%1,%0" | |
815 | [(set_attr "length" "2,2,4")]) | |
816 | ||
ae180d84 JL |
817 | ;; ---------------------------------------------------------------------- |
818 | ;; OR INSTRUCTIONS | |
819 | ;; ---------------------------------------------------------------------- | |
820 | ||
821 | (define_insn "*v850_set1_1" | |
822 | [(set (match_operand:QI 0 "memory_operand" "=m") | |
823 | (subreg:QI (ior:SI (subreg:SI (match_dup 0) 0) | |
223a9d64 N |
824 | (match_operand 1 "power_of_two_operand" "")) 0)) |
825 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
826 | "" |
827 | "set1 %M1,%0" | |
828 | [(set_attr "length" "4") | |
223a9d64 | 829 | (set_attr "type" "bit1")]) |
ae180d84 JL |
830 | |
831 | (define_insn "*v850_set1_2" | |
29a65e3d | 832 | [(set (match_operand:HI 0 "indirect_operand" "=m") |
ae180d84 JL |
833 | (subreg:HI (ior:SI (subreg:SI (match_dup 0) 0) |
834 | (match_operand 1 "power_of_two_operand" "")) 0))] | |
835 | "" | |
ae180d84 JL |
836 | { |
837 | int log2 = exact_log2 (INTVAL (operands[1])); | |
838 | ||
839 | if (log2 < 8) | |
d9030ea4 | 840 | return "set1 %M1,%0"; |
ae180d84 JL |
841 | else |
842 | { | |
843 | rtx xoperands[2]; | |
c5c76735 | 844 | xoperands[0] = gen_rtx_MEM (QImode, |
0a81f074 | 845 | plus_constant (Pmode, XEXP (operands[0], 0), |
c5c76735 | 846 | log2 / 8)); |
ae180d84 | 847 | xoperands[1] = GEN_INT (log2 % 8); |
d9030ea4 | 848 | output_asm_insn ("set1 %1,%0", xoperands); |
ae180d84 | 849 | } |
d9030ea4 N |
850 | return ""; |
851 | } | |
ae180d84 | 852 | [(set_attr "length" "4") |
223a9d64 | 853 | (set_attr "type" "bit1")]) |
ae180d84 JL |
854 | |
855 | (define_insn "*v850_set1_3" | |
29a65e3d | 856 | [(set (match_operand:SI 0 "indirect_operand" "=m") |
ae180d84 | 857 | (ior:SI (match_dup 0) |
223a9d64 N |
858 | (match_operand 1 "power_of_two_operand" ""))) |
859 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 | 860 | "" |
ae180d84 JL |
861 | { |
862 | int log2 = exact_log2 (INTVAL (operands[1])); | |
863 | ||
864 | if (log2 < 8) | |
d9030ea4 | 865 | return "set1 %M1,%0"; |
ae180d84 JL |
866 | else |
867 | { | |
868 | rtx xoperands[2]; | |
c5c76735 | 869 | xoperands[0] = gen_rtx_MEM (QImode, |
0a81f074 | 870 | plus_constant (Pmode, XEXP (operands[0], 0), |
c5c76735 | 871 | log2 / 8)); |
ae180d84 | 872 | xoperands[1] = GEN_INT (log2 % 8); |
d9030ea4 | 873 | output_asm_insn ("set1 %1,%0", xoperands); |
ae180d84 | 874 | } |
d9030ea4 N |
875 | return ""; |
876 | } | |
ae180d84 | 877 | [(set_attr "length" "4") |
223a9d64 | 878 | (set_attr "type" "bit1")]) |
ae180d84 | 879 | |
1ec0eb08 JL |
880 | (define_insn_and_split "iorsi3" |
881 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
882 | (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
883 | (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] | |
884 | "" | |
885 | "#" | |
886 | "reload_completed" | |
887 | [(parallel [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2))) | |
888 | (clobber (reg:CC CC_REGNUM))])]) | |
889 | ||
890 | (define_insn "iorsi3_clobber_flags" | |
ae180d84 JL |
891 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
892 | (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
223a9d64 N |
893 | (match_operand:SI 2 "nonmemory_operand" "r,I,M"))) |
894 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
895 | "" |
896 | "@ | |
897 | or %2,%0 | |
898 | or %.,%0 | |
899 | ori %2,%1,%0" | |
03e32fb7 | 900 | [(set_attr "length" "2,2,4")]) |
ae180d84 | 901 | |
f8dc0f2b JL |
902 | (define_insn "*iorsi3_set_flags" |
903 | [(set (reg:CC CC_REGNUM) | |
904 | (compare:CC (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
905 | (match_operand:SI 2 "nonmemory_operand" "r,I,M")) | |
906 | (const_int 0))) | |
907 | (set (match_operand:SI 0 "register_operand" "=r,r,r") | |
908 | (ior:SI (match_dup 1) (match_dup 2)))] | |
909 | "reload_completed" | |
910 | "@ | |
911 | or %2,%0 | |
912 | or %.,%0 | |
913 | ori %2,%1,%0" | |
914 | [(set_attr "length" "2,2,4")]) | |
915 | ||
ae180d84 JL |
916 | ;; ---------------------------------------------------------------------- |
917 | ;; XOR INSTRUCTIONS | |
918 | ;; ---------------------------------------------------------------------- | |
919 | ||
920 | (define_insn "*v850_not1_1" | |
921 | [(set (match_operand:QI 0 "memory_operand" "=m") | |
922 | (subreg:QI (xor:SI (subreg:SI (match_dup 0) 0) | |
223a9d64 N |
923 | (match_operand 1 "power_of_two_operand" "")) 0)) |
924 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
925 | "" |
926 | "not1 %M1,%0" | |
927 | [(set_attr "length" "4") | |
223a9d64 | 928 | (set_attr "type" "bit1")]) |
ae180d84 JL |
929 | |
930 | (define_insn "*v850_not1_2" | |
29a65e3d | 931 | [(set (match_operand:HI 0 "indirect_operand" "=m") |
ae180d84 JL |
932 | (subreg:HI (xor:SI (subreg:SI (match_dup 0) 0) |
933 | (match_operand 1 "power_of_two_operand" "")) 0))] | |
934 | "" | |
ae180d84 JL |
935 | { |
936 | int log2 = exact_log2 (INTVAL (operands[1])); | |
937 | ||
938 | if (log2 < 8) | |
d9030ea4 | 939 | return "not1 %M1,%0"; |
ae180d84 JL |
940 | else |
941 | { | |
942 | rtx xoperands[2]; | |
c5c76735 | 943 | xoperands[0] = gen_rtx_MEM (QImode, |
0a81f074 | 944 | plus_constant (Pmode, XEXP (operands[0], 0), |
c5c76735 | 945 | log2 / 8)); |
ae180d84 | 946 | xoperands[1] = GEN_INT (log2 % 8); |
d9030ea4 | 947 | output_asm_insn ("not1 %1,%0", xoperands); |
ae180d84 | 948 | } |
d9030ea4 N |
949 | return ""; |
950 | } | |
ae180d84 | 951 | [(set_attr "length" "4") |
223a9d64 | 952 | (set_attr "type" "bit1")]) |
ae180d84 JL |
953 | |
954 | (define_insn "*v850_not1_3" | |
29a65e3d | 955 | [(set (match_operand:SI 0 "indirect_operand" "=m") |
ae180d84 | 956 | (xor:SI (match_dup 0) |
223a9d64 N |
957 | (match_operand 1 "power_of_two_operand" ""))) |
958 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 | 959 | "" |
ae180d84 JL |
960 | { |
961 | int log2 = exact_log2 (INTVAL (operands[1])); | |
962 | ||
963 | if (log2 < 8) | |
d9030ea4 | 964 | return "not1 %M1,%0"; |
ae180d84 JL |
965 | else |
966 | { | |
967 | rtx xoperands[2]; | |
c5c76735 | 968 | xoperands[0] = gen_rtx_MEM (QImode, |
0a81f074 | 969 | plus_constant (Pmode, XEXP (operands[0], 0), |
c5c76735 | 970 | log2 / 8)); |
ae180d84 | 971 | xoperands[1] = GEN_INT (log2 % 8); |
d9030ea4 | 972 | output_asm_insn ("not1 %1,%0", xoperands); |
ae180d84 | 973 | } |
d9030ea4 N |
974 | return ""; |
975 | } | |
ae180d84 | 976 | [(set_attr "length" "4") |
223a9d64 | 977 | (set_attr "type" "bit1")]) |
ae180d84 | 978 | |
1ec0eb08 JL |
979 | (define_insn_and_split "xorsi3" |
980 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
981 | (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
982 | (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] | |
983 | "" | |
984 | "#" | |
985 | "reload_completed" | |
986 | [(parallel [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) | |
987 | (clobber (reg:CC CC_REGNUM))])]) | |
988 | ||
989 | (define_insn "xorsi3_clobber_flags" | |
ae180d84 JL |
990 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") |
991 | (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
223a9d64 N |
992 | (match_operand:SI 2 "nonmemory_operand" "r,I,M"))) |
993 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
994 | "" |
995 | "@ | |
996 | xor %2,%0 | |
997 | xor %.,%0 | |
998 | xori %2,%1,%0" | |
03e32fb7 | 999 | [(set_attr "length" "2,2,4")]) |
1ec0eb08 | 1000 | |
f8dc0f2b JL |
1001 | (define_insn "*xorsi3_set_flags" |
1002 | [(set (reg:CC CC_REGNUM) | |
1003 | (compare:CC (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") | |
1004 | (match_operand:SI 2 "nonmemory_operand" "r,I,M")) | |
1005 | (const_int 0))) | |
1006 | (set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1007 | (xor:SI (match_dup 1) (match_dup 2)))] | |
1008 | "reload_completed" | |
1009 | "@ | |
1010 | xor %2,%0 | |
1011 | xor %.,%0 | |
1012 | xori %2,%1,%0" | |
1013 | [(set_attr "length" "2,2,4")]) | |
1014 | ||
ae180d84 JL |
1015 | \f |
1016 | ;; ---------------------------------------------------------------------- | |
1017 | ;; NOT INSTRUCTIONS | |
1018 | ;; ---------------------------------------------------------------------- | |
1019 | ||
1ec0eb08 JL |
1020 | (define_insn_and_split "one_cmplsi2" |
1021 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1022 | (not:SI (match_operand:SI 1 "register_operand" "r")))] | |
1023 | "" | |
1024 | "#" | |
1025 | "reload_completed" | |
1026 | [(parallel [(set (match_dup 0) (not:SI (match_dup 1))) | |
1027 | (clobber (reg:CC CC_REGNUM))])]) | |
1028 | ||
1029 | ||
1030 | (define_insn "one_cmplsi2_clobber_flags" | |
ae180d84 | 1031 | [(set (match_operand:SI 0 "register_operand" "=r") |
223a9d64 N |
1032 | (not:SI (match_operand:SI 1 "register_operand" "r"))) |
1033 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
1034 | "" |
1035 | "not %1,%0" | |
03e32fb7 | 1036 | [(set_attr "length" "2")]) |
223a9d64 | 1037 | |
f8dc0f2b JL |
1038 | (define_insn "*one_cmplsi2_set_flags" |
1039 | [(set (reg:CC CC_REGNUM) | |
1040 | (compare:CC (not:SI (match_operand:SI 1 "register_operand" "r")) | |
1041 | (const_int 0))) | |
1042 | (set (match_operand:SI 0 "register_operand" "=r") | |
1043 | (not:SI (match_dup 1)))] | |
1044 | "reload_completed" | |
1045 | "not %1,%0" | |
1046 | [(set_attr "length" "2")]) | |
1047 | ||
ae180d84 JL |
1048 | ;; ----------------------------------------------------------------- |
1049 | ;; BIT FIELDS | |
1050 | ;; ----------------------------------------------------------------- | |
1933ec7e JW |
1051 | |
1052 | ;; ??? Is it worth defining insv and extv for the V850 series?!? | |
1053 | ||
1054 | ;; An insv pattern would be useful, but does not get used because | |
1055 | ;; store_bit_field never calls insv when storing a constant value into a | |
1056 | ;; single-bit bitfield. | |
1057 | ||
1058 | ;; extv/extzv patterns would be useful, but do not get used because | |
1059 | ;; optimize_bitfield_compare in fold-const usually converts single | |
1060 | ;; bit extracts into an AND with a mask. | |
ae180d84 | 1061 | |
dbdbd982 NC |
1062 | (define_insn "insv" |
1063 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") | |
1064 | (match_operand:SI 1 "immediate_operand" "n") | |
1065 | (match_operand:SI 2 "immediate_operand" "n")) | |
1ec0eb08 JL |
1066 | (match_operand:SI 3 "register_operand" "r")) |
1067 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 NC |
1068 | "TARGET_V850E3V5_UP" |
1069 | "bins %3, %2, %1, %0" | |
03e32fb7 | 1070 | [(set_attr "length" "4")]) |
dbdbd982 | 1071 | |
ae180d84 JL |
1072 | ;; ----------------------------------------------------------------- |
1073 | ;; Scc INSTRUCTIONS | |
1074 | ;; ----------------------------------------------------------------- | |
1075 | ||
1ec0eb08 JL |
1076 | (define_insn_and_split "*cbranchsi4_insn" |
1077 | [(set (pc) | |
1078 | (if_then_else (match_operator 0 "comparison_operator" | |
1079 | [(match_operand:SI 1 "register_operand" "r") | |
1080 | (match_operand:SI 2 "reg_or_int5_operand" "rJ")]) | |
1081 | (label_ref (match_operand 3 "" "")) | |
1082 | (pc)))] | |
1083 | "" | |
1084 | "#" | |
1085 | "reload_completed" | |
1086 | [(set (reg:CC CC_REGNUM) | |
1087 | (compare:CC (match_dup 1) (match_dup 2))) | |
1088 | (set (pc) | |
1089 | (if_then_else (match_op_dup 0 | |
1090 | [(reg:CC CC_REGNUM) (const_int 0)]) | |
1091 | (label_ref (match_dup 3)) | |
1092 | (pc)))] | |
1093 | "") | |
1094 | ||
1095 | ||
1096 | (define_insn_and_split "cstoresi4" | |
ae180d84 | 1097 | [(set (match_operand:SI 0 "register_operand" "=r") |
f90b7a5a | 1098 | (match_operator:SI 1 "comparison_operator" |
1ec0eb08 JL |
1099 | [(match_operand:SI 2 "register_operand" "r") |
1100 | (match_operand:SI 3 "reg_or_int5_operand" "rJ")]))] | |
ae180d84 | 1101 | "" |
1ec0eb08 JL |
1102 | "#" |
1103 | "reload_completed" | |
1104 | [(set (reg:CC CC_REGNUM) | |
1105 | (compare:CC (match_dup 2) (match_dup 3))) | |
1106 | (set (match_dup 0) (match_op_dup 1 | |
1107 | [(reg:CC CC_REGNUM) (const_int 0)]))] | |
1108 | "") | |
ae180d84 | 1109 | |
1ec0eb08 | 1110 | (define_insn "*setcc_insn" |
223a9d64 | 1111 | [(set (match_operand:SI 0 "register_operand" "=r") |
1ec0eb08 JL |
1112 | (match_operator:SI 1 "comparison_operator" |
1113 | [(reg:CC CC_REGNUM) (const_int 0)]))] | |
1114 | "reload_completed" | |
1115 | "setf %c1,%0" | |
03e32fb7 | 1116 | [(set_attr "length" "4")]) |
223a9d64 N |
1117 | |
1118 | (define_insn "set_z_insn" | |
1119 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1120 | (match_operand 1 "v850_float_z_comparison_operator" ""))] | |
dbdbd982 | 1121 | "TARGET_V850E2V3_UP" |
223a9d64 | 1122 | "setf z,%0" |
03e32fb7 | 1123 | [(set_attr "length" "4")]) |
223a9d64 N |
1124 | |
1125 | (define_insn "set_nz_insn" | |
1126 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1127 | (match_operand 1 "v850_float_nz_comparison_operator" ""))] | |
dbdbd982 | 1128 | "TARGET_V850E2V3_UP" |
223a9d64 | 1129 | "setf nz,%0" |
03e32fb7 | 1130 | [(set_attr "length" "4")]) |
223a9d64 | 1131 | |
b4378319 NC |
1132 | ;; ---------------------------------------------------------------------- |
1133 | ;; CONDITIONAL MOVE INSTRUCTIONS | |
1134 | ;; ---------------------------------------------------------------------- | |
1135 | ||
1136 | ;; Instructions using cc0 aren't allowed to have input reloads, so we must | |
1137 | ;; hide the fact that this instruction uses cc0. We do so by including the | |
1138 | ;; compare instruction inside it. | |
1139 | ||
b4378319 NC |
1140 | (define_expand "movsicc" |
1141 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1142 | (if_then_else:SI | |
f90b7a5a | 1143 | (match_operand 1 "comparison_operator") |
b4378319 | 1144 | (match_operand:SI 2 "reg_or_const_operand" "rJ") |
b4378319 | 1145 | (match_operand:SI 3 "reg_or_const_operand" "rI")))] |
dbdbd982 | 1146 | "(TARGET_V850E_UP)" |
d9030ea4 | 1147 | { |
3cd232b5 NDD |
1148 | /* Make sure that we have an integer comparison... */ |
1149 | if (GET_MODE (XEXP (operands[1], 0)) != CCmode | |
1150 | && GET_MODE (XEXP (operands[1], 0)) != SImode) | |
1151 | FAIL; | |
1152 | ||
d9030ea4 N |
1153 | if ((GET_CODE (operands[2]) == CONST_INT |
1154 | && GET_CODE (operands[3]) == CONST_INT)) | |
1155 | { | |
1156 | int o2 = INTVAL (operands[2]); | |
1157 | int o3 = INTVAL (operands[3]); | |
1158 | ||
1159 | if (o2 == 1 && o3 == 0) | |
1160 | FAIL; /* setf */ | |
1161 | if (o3 == 1 && o2 == 0) | |
1162 | FAIL; /* setf */ | |
1163 | if (o2 == 0 && (o3 < -16 || o3 > 15) && exact_log2 (o3) >= 0) | |
1164 | FAIL; /* setf + shift */ | |
1165 | if (o3 == 0 && (o2 < -16 || o2 > 15) && exact_log2 (o2) >=0) | |
1166 | FAIL; /* setf + shift */ | |
1167 | if (o2 != 0) | |
1168 | operands[2] = copy_to_mode_reg (SImode, operands[2]); | |
1169 | if (o3 !=0 ) | |
1170 | operands[3] = copy_to_mode_reg (SImode, operands[3]); | |
1171 | } | |
1172 | else | |
1173 | { | |
1174 | if (GET_CODE (operands[2]) != REG) | |
1175 | operands[2] = copy_to_mode_reg (SImode,operands[2]); | |
1176 | if (GET_CODE (operands[3]) != REG) | |
1177 | operands[3] = copy_to_mode_reg (SImode, operands[3]); | |
1178 | } | |
1179 | }) | |
b4378319 | 1180 | |
223a9d64 N |
1181 | (define_insn "movsicc_normal_cc" |
1182 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1183 | (if_then_else:SI | |
1184 | (match_operator 1 "comparison_operator" | |
1185 | [(reg:CC CC_REGNUM) (const_int 0)]) | |
1186 | (match_operand:SI 2 "reg_or_int5_operand" "rJ") | |
1187 | (match_operand:SI 3 "reg_or_0_operand" "rI")))] | |
1ec0eb08 | 1188 | "reload_completed && (TARGET_V850E_UP)" |
223a9d64 | 1189 | "cmov %c1,%2,%z3,%0"; |
03e32fb7 | 1190 | [(set_attr "length" "6")]) |
223a9d64 N |
1191 | |
1192 | (define_insn "movsicc_reversed_cc" | |
1193 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1194 | (if_then_else:SI | |
1195 | (match_operator 1 "comparison_operator" | |
1196 | [(reg:CC CC_REGNUM) (const_int 0)]) | |
1197 | (match_operand:SI 2 "reg_or_0_operand" "rI") | |
1198 | (match_operand:SI 3 "reg_or_int5_operand" "rJ")))] | |
1ec0eb08 | 1199 | "reload_completed && (TARGET_V850E_UP)" |
223a9d64 | 1200 | "cmov %C1,%3,%z2,%0" |
03e32fb7 | 1201 | [(set_attr "length" "6")]) |
223a9d64 | 1202 | |
1ec0eb08 | 1203 | (define_insn_and_split "*movsicc_normal" |
b4378319 NC |
1204 | [(set (match_operand:SI 0 "register_operand" "=r") |
1205 | (if_then_else:SI | |
1206 | (match_operator 1 "comparison_operator" | |
1207 | [(match_operand:SI 4 "register_operand" "r") | |
1208 | (match_operand:SI 5 "reg_or_int5_operand" "rJ")]) | |
1209 | (match_operand:SI 2 "reg_or_int5_operand" "rJ") | |
1210 | (match_operand:SI 3 "reg_or_0_operand" "rI")))] | |
dbdbd982 | 1211 | "(TARGET_V850E_UP)" |
1ec0eb08 JL |
1212 | "#" |
1213 | "reload_completed" | |
1214 | [(set (reg:CC CC_REGNUM) | |
1215 | (compare:CC (match_dup 4) (match_dup 5))) | |
1216 | (set (match_dup 0) | |
1217 | (if_then_else:SI (match_op_dup 1 | |
1218 | [(reg:CC CC_REGNUM) (const_int 0)]) | |
1219 | (match_dup 2) (match_dup 3)))]) | |
b4378319 | 1220 | |
1ec0eb08 JL |
1221 | |
1222 | (define_insn_and_split "*movsicc_reversed" | |
b4378319 NC |
1223 | [(set (match_operand:SI 0 "register_operand" "=r") |
1224 | (if_then_else:SI | |
1225 | (match_operator 1 "comparison_operator" | |
1226 | [(match_operand:SI 4 "register_operand" "r") | |
1227 | (match_operand:SI 5 "reg_or_int5_operand" "rJ")]) | |
1ec0eb08 JL |
1228 | (match_operand:SI 2 "reg_or_int5_operand" "rI") |
1229 | (match_operand:SI 3 "reg_or_0_operand" "rJ")))] | |
dbdbd982 | 1230 | "(TARGET_V850E_UP)" |
1ec0eb08 JL |
1231 | "#" |
1232 | "reload_completed" | |
1233 | [(set (reg:CC CC_REGNUM) | |
1234 | (compare:CC (match_dup 4) (match_dup 5))) | |
1235 | (set (match_dup 0) | |
1236 | (if_then_else:SI (match_op_dup 1 | |
1237 | [(reg:CC CC_REGNUM) (const_int 0)]) | |
1238 | (match_dup 2) (match_dup 3)))]) | |
b4378319 | 1239 | |
1ec0eb08 | 1240 | ;; We could expose the setting of the condition codes here. |
b4378319 NC |
1241 | (define_insn "*movsicc_tst1" |
1242 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1243 | (if_then_else:SI | |
1244 | (match_operator 1 "comparison_operator" | |
1245 | [(zero_extract:SI | |
1246 | (match_operand:QI 2 "memory_operand" "m") | |
1247 | (const_int 1) | |
1248 | (match_operand 3 "const_int_operand" "n")) | |
1249 | (const_int 0)]) | |
1250 | (match_operand:SI 4 "reg_or_int5_operand" "rJ") | |
1ec0eb08 JL |
1251 | (match_operand:SI 5 "reg_or_0_operand" "rI"))) |
1252 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 1253 | "(TARGET_V850E_UP)" |
b4378319 | 1254 | "tst1 %3,%2 ; cmov %c1,%4,%z5,%0" |
03e32fb7 | 1255 | [(set_attr "length" "8")]) |
b4378319 | 1256 | |
1ec0eb08 | 1257 | ;; We could expose the setting of the condition codes here. |
b4378319 NC |
1258 | (define_insn "*movsicc_tst1_reversed" |
1259 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1260 | (if_then_else:SI | |
1261 | (match_operator 1 "comparison_operator" | |
1262 | [(zero_extract:SI | |
1263 | (match_operand:QI 2 "memory_operand" "m") | |
1264 | (const_int 1) | |
1265 | (match_operand 3 "const_int_operand" "n")) | |
1266 | (const_int 0)]) | |
1267 | (match_operand:SI 4 "reg_or_0_operand" "rI") | |
1ec0eb08 JL |
1268 | (match_operand:SI 5 "reg_or_int5_operand" "rJ"))) |
1269 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 1270 | "(TARGET_V850E_UP)" |
b4378319 | 1271 | "tst1 %3,%2 ; cmov %C1,%5,%z4,%0" |
03e32fb7 | 1272 | [(set_attr "length" "8")]) |
b4378319 NC |
1273 | |
1274 | ;; Matching for sasf requires combining 4 instructions, so we provide a | |
1275 | ;; dummy pattern to match the first 3, which will always be turned into the | |
1276 | ;; second pattern by subsequent combining. As above, we must include the | |
1277 | ;; comparison to avoid input reloads in an insn using cc0. | |
1278 | ||
1ec0eb08 JL |
1279 | ;; We could expose the setting of the condition codes here. |
1280 | ;; However, I haven't seen this pattern used, so I'm not going | |
1281 | ;; to bother. | |
223a9d64 | 1282 | (define_insn "*sasf" |
b4378319 NC |
1283 | [(set (match_operand:SI 0 "register_operand" "=r") |
1284 | (ior:SI | |
1285 | (match_operator 1 "comparison_operator" | |
1286 | [(match_operand:SI 3 "register_operand" "r") | |
1287 | (match_operand:SI 4 "reg_or_int5_operand" "rJ")]) | |
1288 | (ashift:SI (match_operand:SI 2 "register_operand" "0") | |
223a9d64 N |
1289 | (const_int 1)))) |
1290 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 1291 | "(TARGET_V850E_UP)" |
b4378319 | 1292 | "cmp %4,%3 ; sasf %c1,%0" |
03e32fb7 | 1293 | [(set_attr "length" "6")]) |
b4378319 NC |
1294 | |
1295 | (define_split | |
1296 | [(set (match_operand:SI 0 "register_operand" "") | |
1297 | (if_then_else:SI | |
1298 | (match_operator 1 "comparison_operator" | |
1299 | [(match_operand:SI 4 "register_operand" "") | |
1300 | (match_operand:SI 5 "reg_or_int5_operand" "")]) | |
1301 | (match_operand:SI 2 "const_int_operand" "") | |
223a9d64 N |
1302 | (match_operand:SI 3 "const_int_operand" ""))) |
1303 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 1304 | "(TARGET_V850E_UP) |
b4378319 NC |
1305 | && ((INTVAL (operands[2]) ^ INTVAL (operands[3])) == 1) |
1306 | && ((INTVAL (operands[2]) + INTVAL (operands[3])) != 1) | |
1307 | && (GET_CODE (operands[5]) == CONST_INT | |
1308 | || REGNO (operands[0]) != REGNO (operands[5])) | |
1309 | && REGNO (operands[0]) != REGNO (operands[4])" | |
1310 | [(set (match_dup 0) (match_dup 6)) | |
223a9d64 N |
1311 | (parallel [(set (match_dup 0) |
1312 | (ior:SI (match_op_dup 7 [(match_dup 4) (match_dup 5)]) | |
1313 | (ashift:SI (match_dup 0) (const_int 1)))) | |
1314 | (clobber (reg:CC CC_REGNUM))])] | |
d9030ea4 N |
1315 | { |
1316 | operands[6] = GEN_INT (INTVAL (operands[2]) >> 1); | |
1317 | if (INTVAL (operands[2]) & 0x1) | |
1318 | operands[7] = operands[1]; | |
1319 | else | |
1320 | operands[7] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])), | |
1321 | GET_MODE (operands[1]), | |
1322 | XEXP (operands[1], 0), XEXP (operands[1], 1)); | |
1323 | }) | |
223a9d64 | 1324 | |
b4378319 NC |
1325 | ;; --------------------------------------------------------------------- |
1326 | ;; BYTE SWAP INSTRUCTIONS | |
1327 | ;; --------------------------------------------------------------------- | |
b4378319 | 1328 | (define_expand "rotlhi3" |
223a9d64 N |
1329 | [(parallel [(set (match_operand:HI 0 "register_operand" "") |
1330 | (rotate:HI (match_operand:HI 1 "register_operand" "") | |
1331 | (match_operand:HI 2 "const_int_operand" ""))) | |
1332 | (clobber (reg:CC CC_REGNUM))])] | |
dbdbd982 | 1333 | "(TARGET_V850E_UP)" |
d9030ea4 N |
1334 | { |
1335 | if (INTVAL (operands[2]) != 8) | |
1336 | FAIL; | |
1337 | }) | |
b4378319 NC |
1338 | |
1339 | (define_insn "*rotlhi3_8" | |
1340 | [(set (match_operand:HI 0 "register_operand" "=r") | |
1341 | (rotate:HI (match_operand:HI 1 "register_operand" "r") | |
223a9d64 N |
1342 | (const_int 8))) |
1343 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 1344 | "(TARGET_V850E_UP)" |
b4378319 | 1345 | "bsh %1,%0" |
03e32fb7 | 1346 | [(set_attr "length" "4")]) |
b4378319 NC |
1347 | |
1348 | (define_expand "rotlsi3" | |
223a9d64 N |
1349 | [(parallel [(set (match_operand:SI 0 "register_operand" "") |
1350 | (rotate:SI (match_operand:SI 1 "register_operand" "") | |
1351 | (match_operand:SI 2 "const_int_operand" ""))) | |
1352 | (clobber (reg:CC CC_REGNUM))])] | |
dbdbd982 | 1353 | "(TARGET_V850E_UP)" |
d9030ea4 N |
1354 | { |
1355 | if (INTVAL (operands[2]) != 16) | |
1356 | FAIL; | |
1357 | }) | |
b4378319 | 1358 | |
dbdbd982 NC |
1359 | (define_insn "rotlsi3_a" |
1360 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1361 | (match_operator:SI 4 "ior_operator" | |
1362 | [(ashift:SI (match_operand:SI 1 "register_operand" "r") | |
1363 | (match_operand:SI 2 "const_int_operand" "n")) | |
1364 | (lshiftrt:SI (match_dup 1) | |
1ec0eb08 JL |
1365 | (match_operand:SI 3 "const_int_operand" "n"))])) |
1366 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 NC |
1367 | "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)" |
1368 | "rotl %2, %1, %0" | |
03e32fb7 | 1369 | [(set_attr "length" "4")]) |
dbdbd982 NC |
1370 | |
1371 | (define_insn "rotlsi3_b" | |
1372 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1373 | (match_operator:SI 4 "ior_operator" | |
1374 | [(lshiftrt:SI (match_operand:SI 1 "register_operand" "r") | |
1375 | (match_operand:SI 3 "const_int_operand" "n")) | |
1376 | (ashift:SI (match_dup 1) | |
1ec0eb08 JL |
1377 | (match_operand:SI 2 "const_int_operand" "n"))])) |
1378 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 NC |
1379 | "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)" |
1380 | "rotl %2, %1, %0" | |
03e32fb7 | 1381 | [(set_attr "length" "4")]) |
dbdbd982 NC |
1382 | |
1383 | (define_insn "rotlsi3_v850e3v5" | |
1384 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1385 | (rotate:SI (match_operand:SI 1 "register_operand" "r") | |
1386 | (match_operand:SI 2 "e3v5_shift_operand" "rn"))) | |
1387 | (clobber (reg:CC CC_REGNUM))] | |
1388 | "TARGET_V850E3V5_UP" | |
1389 | "rotl %2, %1, %0" | |
03e32fb7 | 1390 | [(set_attr "length" "4")]) |
dbdbd982 | 1391 | |
b4378319 NC |
1392 | (define_insn "*rotlsi3_16" |
1393 | [(set (match_operand:SI 0 "register_operand" "=r") | |
1394 | (rotate:SI (match_operand:SI 1 "register_operand" "r") | |
223a9d64 N |
1395 | (const_int 16))) |
1396 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 1397 | "(TARGET_V850E_UP)" |
b4378319 | 1398 | "hsw %1,%0" |
03e32fb7 | 1399 | [(set_attr "length" "4")]) |
223a9d64 | 1400 | |
ae180d84 JL |
1401 | ;; ---------------------------------------------------------------------- |
1402 | ;; JUMP INSTRUCTIONS | |
1403 | ;; ---------------------------------------------------------------------- | |
1404 | ||
dbdbd982 NC |
1405 | ;; Doloop |
1406 | ||
1407 | (define_expand "doloop_begin" | |
1408 | [(use (match_operand 0 "" "")) ; loop pseudo | |
1d0216c8 | 1409 | (use (match_operand 1 "" ""))] ; doloop_end pattern |
dbdbd982 NC |
1410 | "TARGET_V850E3V5_UP && TARGET_LOOP" |
1411 | { | |
1d0216c8 RS |
1412 | rtx loop_cnt = operands[0]; |
1413 | gcc_assert (GET_MODE (loop_cnt) == SImode); | |
dbdbd982 NC |
1414 | emit_insn (gen_fix_loop_counter (loop_cnt)); |
1415 | DONE; | |
1416 | } | |
1417 | ) | |
1418 | ||
1ec0eb08 | 1419 | ;; Note the embedded arithmetic. That affects the condition codes! |
dbdbd982 NC |
1420 | (define_insn "fix_loop_counter" |
1421 | [(unspec:SI [(match_operand:SI 0 "register_operand" "+r,!m") | |
1ec0eb08 JL |
1422 | (clobber (match_scratch:SI 1 "=X,r"))] UNSPEC_LOOP) |
1423 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 NC |
1424 | "TARGET_V850E3V5_UP && TARGET_LOOP" |
1425 | { | |
1426 | switch (which_alternative) | |
1427 | { | |
1428 | case 0: return "add 1, %0 # LOOP_BEGIN"; | |
1429 | case 1: return "ld.w %0, %1; add 1, %1; st.w %1, %0 # LOOP_BEGIN"; | |
1430 | default: gcc_unreachable (); | |
1431 | } | |
1432 | } | |
03e32fb7 | 1433 | [(set_attr "length" "2,6")]) |
dbdbd982 NC |
1434 | |
1435 | (define_expand "doloop_end" | |
1436 | [(use (match_operand 0 "" "")) ; loop pseudo | |
1d0216c8 | 1437 | (use (match_operand 1 "" ""))] ; label |
dbdbd982 NC |
1438 | "TARGET_V850E3V5_UP && TARGET_LOOP" |
1439 | { | |
1d0216c8 RS |
1440 | rtx loop_cnt = operands[0]; |
1441 | rtx label = operands[1]; | |
dbdbd982 | 1442 | |
dbdbd982 NC |
1443 | if (GET_MODE (loop_cnt) != SImode) |
1444 | FAIL; | |
1445 | ||
1446 | emit_jump_insn (gen_doloop_end_internal_loop (label, loop_cnt)); | |
1447 | DONE; | |
1448 | } | |
1449 | ) | |
1450 | ||
1451 | (define_insn "doloop_end_internal_loop" | |
1452 | [(set (pc) | |
1453 | (if_then_else (ne (match_operand:SI 1 "register_operand" "+r,!m") | |
1454 | (const_int 0)) | |
1455 | (label_ref (match_operand 0 "" "")) | |
1456 | (pc))) | |
1457 | (set (match_dup 1) (plus:SI (match_dup 1) (const_int -1))) | |
1458 | (clobber (match_scratch:SI 2 "=X,r")) | |
1459 | (clobber (reg:CC CC_REGNUM))] | |
1460 | "TARGET_V850E3V5_UP && TARGET_LOOP" | |
1461 | { | |
1462 | switch (which_alternative) | |
1463 | { | |
1464 | case 0: | |
1465 | if (get_attr_length (insn) == 4) | |
1466 | return "loop %1, %0 # LOOP.1.0"; | |
1467 | ||
1468 | return "add -1, %1; bne %l0 # LOOP.1.1"; | |
1469 | case 1: | |
1470 | return "ld.w %1, %2; add -1, %2; st.w %2, %1; bne %l0 # LOOP.2.1"; | |
1471 | default: | |
1472 | gcc_unreachable (); | |
1473 | } | |
1474 | } | |
1475 | [(set (attr "length") | |
1476 | (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
1477 | (const_int 65534)) | |
1478 | (const_int 4) | |
03e32fb7 | 1479 | (const_int 14)))]) |
dbdbd982 | 1480 | |
ae180d84 JL |
1481 | ;; Conditional jump instructions |
1482 | ||
1ec0eb08 | 1483 | (define_insn_and_split "*cbranchsi4_insn" |
ae180d84 | 1484 | [(set (pc) |
1ec0eb08 JL |
1485 | (if_then_else (match_operator 0 "comparison_operator" |
1486 | [(match_operand:SI 1 "register_operand" "r") | |
1487 | (match_operand:SI 2 "reg_or_int5_operand" "rJ")]) | |
1488 | (label_ref (match_operand 3 "" "")) | |
ae180d84 JL |
1489 | (pc)))] |
1490 | "" | |
1ec0eb08 JL |
1491 | "#" |
1492 | "reload_completed" | |
1493 | [(set (reg:CC CC_REGNUM) | |
1494 | (compare:CC (match_dup 1) (match_dup 2))) | |
1495 | (set (pc) | |
1496 | (if_then_else (match_op_dup 0 | |
1497 | [(reg:CC CC_REGNUM) (const_int 0)]) | |
1498 | (label_ref (match_dup 3)) | |
1499 | (pc)))] | |
1500 | "") | |
ae180d84 | 1501 | |
1ec0eb08 | 1502 | (define_insn "*branch_normal" |
ae180d84 JL |
1503 | [(set (pc) |
1504 | (if_then_else (match_operator 1 "comparison_operator" | |
1ec0eb08 | 1505 | [(reg CC_REGNUM) (const_int 0)]) |
223a9d64 N |
1506 | (label_ref (match_operand 0 "" "")) |
1507 | (pc)))] | |
1ec0eb08 | 1508 | "reload_completed" |
223a9d64 | 1509 | { |
1ec0eb08 | 1510 | bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode; |
223a9d64 | 1511 | if (get_attr_length (insn) == 2) |
1ec0eb08 JL |
1512 | { |
1513 | if (nzmode) | |
1514 | return "b%d1 %l0"; | |
1515 | else | |
1516 | return "b%b1 %l0"; | |
1517 | } | |
dbdbd982 | 1518 | if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) |
1ec0eb08 JL |
1519 | { |
1520 | if (nzmode) | |
1521 | return "b%d1 %l0"; | |
1522 | else | |
1523 | return "b%b1 %l0"; | |
1524 | } | |
1525 | if (nzmode) | |
1526 | return "b%D1 .+6 ; jr %l0"; | |
1527 | else | |
1528 | return "b%B1 .+6 ; jr %l0"; | |
d9030ea4 | 1529 | } |
223a9d64 N |
1530 | [(set (attr "length") |
1531 | (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
1532 | (const_int 256)) | |
1533 | (const_int 2) | |
dbdbd982 NC |
1534 | (if_then_else (lt (abs (minus (match_dup 0) (pc))) |
1535 | (const_int 65536)) | |
1536 | (const_int 4) | |
03e32fb7 | 1537 | (const_int 6))))]) |
223a9d64 | 1538 | |
1ec0eb08 | 1539 | (define_insn "*branch_invert" |
223a9d64 | 1540 | [(set (pc) |
1ec0eb08 JL |
1541 | (if_then_else (match_operator 1 "comparison_operator" |
1542 | [(reg CC_REGNUM) (const_int 0)]) | |
223a9d64 N |
1543 | (pc) |
1544 | (label_ref (match_operand 0 "" ""))))] | |
1ec0eb08 | 1545 | "reload_completed" |
223a9d64 | 1546 | { |
1ec0eb08 | 1547 | bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode; |
223a9d64 | 1548 | |
223a9d64 | 1549 | if (get_attr_length (insn) == 2) |
1ec0eb08 JL |
1550 | { |
1551 | if (nzmode) | |
1552 | return "b%D1 %l0"; | |
1553 | else | |
1554 | return "b%B1 %l0"; | |
1555 | } | |
dbdbd982 NC |
1556 | |
1557 | if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) | |
1ec0eb08 JL |
1558 | { |
1559 | if (nzmode) | |
1560 | return "b%D1 %l0"; | |
1561 | else | |
1562 | return "b%B1 %l0"; | |
1563 | } | |
dbdbd982 | 1564 | |
1ec0eb08 JL |
1565 | if (nzmode) |
1566 | return "b%d1 .+6 ; jr %l0"; | |
1567 | else | |
1568 | return "b%b1 .+6 ; jr %l0"; | |
d9030ea4 | 1569 | } |
223a9d64 N |
1570 | [(set (attr "length") |
1571 | (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
1572 | (const_int 256)) | |
1573 | (const_int 2) | |
dbdbd982 NC |
1574 | (if_then_else (lt (abs (minus (match_dup 0) (pc))) |
1575 | (const_int 65536)) | |
1576 | (const_int 4) | |
03e32fb7 | 1577 | (const_int 6))))]) |
223a9d64 | 1578 | |
ae180d84 JL |
1579 | ;; Unconditional and other jump instructions. |
1580 | ||
1581 | (define_insn "jump" | |
1582 | [(set (pc) | |
1583 | (label_ref (match_operand 0 "" "")))] | |
1584 | "" | |
ae180d84 | 1585 | { |
223a9d64 | 1586 | if (get_attr_length (insn) == 2) |
d9030ea4 | 1587 | return "br %0"; |
ae180d84 | 1588 | else |
d9030ea4 N |
1589 | return "jr %0"; |
1590 | } | |
ae180d84 JL |
1591 | [(set (attr "length") |
1592 | (if_then_else (lt (abs (minus (match_dup 0) (pc))) | |
1593 | (const_int 256)) | |
1594 | (const_int 2) | |
03e32fb7 | 1595 | (const_int 4)))]) |
ae180d84 JL |
1596 | |
1597 | (define_insn "indirect_jump" | |
1598 | [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
1599 | "" | |
1600 | "jmp %0" | |
03e32fb7 | 1601 | [(set_attr "length" "2")]) |
ae180d84 JL |
1602 | |
1603 | (define_insn "tablejump" | |
1604 | [(set (pc) (match_operand:SI 0 "register_operand" "r")) | |
1605 | (use (label_ref (match_operand 1 "" "")))] | |
1606 | "" | |
1607 | "jmp %0" | |
03e32fb7 | 1608 | [(set_attr "length" "2")]) |
ae180d84 | 1609 | |
b4378319 NC |
1610 | (define_insn "switch" |
1611 | [(set (pc) | |
1612 | (plus:SI | |
1613 | (sign_extend:SI | |
223a9d64 N |
1614 | (mem:HI |
1615 | (plus:SI (ashift:SI (match_operand:SI 0 "register_operand" "r") | |
1616 | (const_int 1)) | |
1617 | (label_ref (match_operand 1 "" ""))))) | |
1618 | (label_ref (match_dup 1))))] | |
dbdbd982 | 1619 | "(TARGET_V850E_UP)" |
b4378319 | 1620 | "switch %0" |
03e32fb7 | 1621 | [(set_attr "length" "2")]) |
b4378319 | 1622 | |
1933ec7e JW |
1623 | (define_expand "casesi" |
1624 | [(match_operand:SI 0 "register_operand" "") | |
1625 | (match_operand:SI 1 "register_operand" "") | |
1626 | (match_operand:SI 2 "register_operand" "") | |
1627 | (match_operand 3 "" "") (match_operand 4 "" "")] | |
1628 | "" | |
d9030ea4 N |
1629 | { |
1630 | rtx reg = gen_reg_rtx (SImode); | |
1631 | rtx tableaddress = gen_reg_rtx (SImode); | |
1632 | rtx test; | |
1633 | rtx mem; | |
1634 | ||
1635 | /* Subtract the lower bound from the index. */ | |
1636 | emit_insn (gen_subsi3 (reg, operands[0], operands[1])); | |
1637 | ||
1638 | /* Compare the result against the number of table entries; | |
1639 | branch to the default label if out of range of the table. */ | |
1640 | test = gen_rtx_fmt_ee (GTU, VOIDmode, reg, operands[2]); | |
1641 | emit_jump_insn (gen_cbranchsi4 (test, reg, operands[2], operands[4])); | |
1642 | ||
1643 | /* Shift index for the table array access. */ | |
1644 | emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1))); | |
1645 | /* Load the table address into a pseudo. */ | |
1646 | emit_insn (gen_movsi (tableaddress, | |
1647 | gen_rtx_LABEL_REF (Pmode, operands[3]))); | |
1648 | /* Add the table address to the index. */ | |
1649 | emit_insn (gen_addsi3 (reg, reg, tableaddress)); | |
1650 | /* Load the table entry. */ | |
1651 | mem = gen_const_mem (CASE_VECTOR_MODE, reg); | |
1652 | if (! TARGET_BIG_SWITCH) | |
1653 | { | |
1654 | rtx reg2 = gen_reg_rtx (HImode); | |
1655 | emit_insn (gen_movhi (reg2, mem)); | |
1656 | emit_insn (gen_extendhisi2 (reg, reg2)); | |
1657 | } | |
1658 | else | |
1659 | emit_insn (gen_movsi (reg, mem)); | |
1660 | /* Add the table address. */ | |
1661 | emit_insn (gen_addsi3 (reg, reg, tableaddress)); | |
1662 | /* Branch to the switch label. */ | |
1663 | emit_jump_insn (gen_tablejump (reg, operands[3])); | |
1664 | DONE; | |
1665 | }) | |
1933ec7e | 1666 | |
ae180d84 JL |
1667 | ;; Call subroutine with no return value. |
1668 | ||
1669 | (define_expand "call" | |
1670 | [(call (match_operand:QI 0 "general_operand" "") | |
1671 | (match_operand:SI 1 "general_operand" ""))] | |
1672 | "" | |
d9030ea4 N |
1673 | { |
1674 | if (! call_address_operand (XEXP (operands[0], 0), QImode) | |
1675 | || TARGET_LONG_CALLS) | |
1676 | XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); | |
1677 | if (TARGET_LONG_CALLS) | |
1678 | emit_call_insn (gen_call_internal_long (XEXP (operands[0], 0), operands[1])); | |
1679 | else | |
1680 | emit_call_insn (gen_call_internal_short (XEXP (operands[0], 0), operands[1])); | |
be1d3f93 | 1681 | |
d9030ea4 N |
1682 | DONE; |
1683 | }) | |
ae180d84 | 1684 | |
be1d3f93 | 1685 | (define_insn "call_internal_short" |
ae180d84 JL |
1686 | [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) |
1687 | (match_operand:SI 1 "general_operand" "g,g")) | |
1ec0eb08 | 1688 | (clobber (reg:CC CC_REGNUM)) |
ae180d84 | 1689 | (clobber (reg:SI 31))] |
be1d3f93 | 1690 | "! TARGET_LONG_CALLS" |
dbdbd982 NC |
1691 | { |
1692 | if (which_alternative == 1) | |
1693 | { | |
1694 | if (TARGET_V850E3V5_UP) | |
1695 | return "jarl [%0], r31"; | |
1696 | ||
1697 | return "jarl .+4, r31 ; add 4, r31 ; jmp %0"; | |
1698 | } | |
1699 | ||
1700 | return "jarl %0, r31"; | |
1701 | } | |
03e32fb7 | 1702 | [(set_attr "length" "4,8")]) |
be1d3f93 NC |
1703 | |
1704 | (define_insn "call_internal_long" | |
1705 | [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) | |
1706 | (match_operand:SI 1 "general_operand" "g,g")) | |
1ec0eb08 | 1707 | (clobber (reg:CC CC_REGNUM)) |
be1d3f93 NC |
1708 | (clobber (reg:SI 31))] |
1709 | "TARGET_LONG_CALLS" | |
d9030ea4 | 1710 | { |
be1d3f93 NC |
1711 | if (which_alternative == 0) |
1712 | { | |
1713 | if (GET_CODE (operands[0]) == REG) | |
d9030ea4 | 1714 | return "jarl %0,r31"; |
dbdbd982 NC |
1715 | |
1716 | if (TARGET_V850E3V5_UP) | |
1717 | return "mov hilo(%0), r11 ; jarl [r11], r31"; | |
1718 | ||
1719 | return "movhi hi(%0), r0, r11 ; movea lo(%0), r11, r11 ; jarl .+4,r31 ; add 4, r31 ; jmp r11"; | |
be1d3f93 | 1720 | } |
dbdbd982 NC |
1721 | |
1722 | if (TARGET_V850E3V5_UP) | |
1723 | return "jarl [%0], r31"; | |
1724 | ||
1725 | return "jarl .+4,r31 ; add 4,r31 ; jmp %0"; | |
d9030ea4 | 1726 | } |
03e32fb7 | 1727 | [(set_attr "length" "16,8")]) |
ae180d84 JL |
1728 | |
1729 | ;; Call subroutine, returning value in operand 0 | |
1730 | ;; (which must be a hard register). | |
1731 | ||
1732 | (define_expand "call_value" | |
1733 | [(set (match_operand 0 "" "") | |
1734 | (call (match_operand:QI 1 "general_operand" "") | |
1735 | (match_operand:SI 2 "general_operand" "")))] | |
1736 | "" | |
d9030ea4 N |
1737 | { |
1738 | if (! call_address_operand (XEXP (operands[1], 0), QImode) | |
1739 | || TARGET_LONG_CALLS) | |
1740 | XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); | |
1741 | if (TARGET_LONG_CALLS) | |
1742 | emit_call_insn (gen_call_value_internal_long (operands[0], | |
1743 | XEXP (operands[1], 0), | |
1744 | operands[2])); | |
1745 | else | |
1746 | emit_call_insn (gen_call_value_internal_short (operands[0], | |
1747 | XEXP (operands[1], 0), | |
1748 | operands[2])); | |
1749 | DONE; | |
1750 | }) | |
ae180d84 | 1751 | |
be1d3f93 | 1752 | (define_insn "call_value_internal_short" |
ae180d84 JL |
1753 | [(set (match_operand 0 "" "=r,r") |
1754 | (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) | |
1755 | (match_operand:SI 2 "general_operand" "g,g"))) | |
1ec0eb08 | 1756 | (clobber (reg:CC CC_REGNUM)) |
ae180d84 | 1757 | (clobber (reg:SI 31))] |
be1d3f93 | 1758 | "! TARGET_LONG_CALLS" |
dbdbd982 NC |
1759 | { |
1760 | if (which_alternative == 1) | |
1761 | { | |
1762 | if (TARGET_V850E3V5_UP) | |
1763 | return "jarl [%1], r31"; | |
1764 | ||
1765 | return "jarl .+4, r31 ; add 4, r31 ; jmp %1"; | |
1766 | } | |
1767 | ||
1768 | return "jarl %1, r31"; | |
1769 | } | |
03e32fb7 | 1770 | [(set_attr "length" "4,8")]) |
be1d3f93 NC |
1771 | |
1772 | (define_insn "call_value_internal_long" | |
1773 | [(set (match_operand 0 "" "=r,r") | |
1774 | (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) | |
1775 | (match_operand:SI 2 "general_operand" "g,g"))) | |
1ec0eb08 | 1776 | (clobber (reg:CC CC_REGNUM)) |
be1d3f93 NC |
1777 | (clobber (reg:SI 31))] |
1778 | "TARGET_LONG_CALLS" | |
d9030ea4 | 1779 | { |
be1d3f93 NC |
1780 | if (which_alternative == 0) |
1781 | { | |
1782 | if (GET_CODE (operands[1]) == REG) | |
d9030ea4 | 1783 | return "jarl %1, r31"; |
dbdbd982 | 1784 | |
d4de0221 | 1785 | /* Reload can generate this pattern.... */ |
dbdbd982 NC |
1786 | if (TARGET_V850E3V5_UP) |
1787 | return "mov hilo(%1), r11 ; jarl [r11], r31"; | |
1788 | ||
1789 | return "movhi hi(%1), r0, r11 ; movea lo(%1), r11, r11 ; jarl .+4, r31 ; add 4, r31 ; jmp r11"; | |
be1d3f93 | 1790 | } |
dbdbd982 NC |
1791 | |
1792 | if (TARGET_V850E3V5_UP) | |
1793 | return "jarl [%1], r31"; | |
1794 | ||
1795 | return "jarl .+4, r31 ; add 4, r31 ; jmp %1"; | |
d9030ea4 | 1796 | } |
03e32fb7 | 1797 | [(set_attr "length" "16,8")]) |
ae180d84 JL |
1798 | |
1799 | (define_insn "nop" | |
1800 | [(const_int 0)] | |
1801 | "" | |
1802 | "nop" | |
03e32fb7 | 1803 | [(set_attr "length" "2")]) |
ae180d84 JL |
1804 | \f |
1805 | ;; ---------------------------------------------------------------------- | |
1806 | ;; EXTEND INSTRUCTIONS | |
1807 | ;; ---------------------------------------------------------------------- | |
1808 | ||
1ec0eb08 | 1809 | ;; We only need the CC clobber because of the andi alternative |
1dcad079 | 1810 | (define_insn "*zero_extendhisi2_v850e" |
b4378319 NC |
1811 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") |
1812 | (zero_extend:SI | |
223a9d64 N |
1813 | (match_operand:HI 1 "nonimmediate_operand" "0,r,T,m"))) |
1814 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 1815 | "(TARGET_V850E_UP)" |
b4378319 NC |
1816 | "@ |
1817 | zxh %0 | |
1818 | andi 65535,%1,%0 | |
1819 | sld.hu %1,%0 | |
1820 | ld.hu %1,%0" | |
03e32fb7 | 1821 | [(set_attr "length" "2,4,2,4")]) |
ae180d84 | 1822 | |
1dcad079 | 1823 | (define_insn "*zero_extendhisi2_v850" |
ae180d84 JL |
1824 | [(set (match_operand:SI 0 "register_operand" "=r") |
1825 | (zero_extend:SI | |
223a9d64 | 1826 | (match_operand:HI 1 "register_operand" "r"))) |
1dcad079 | 1827 | (clobber (reg:CC CC_REGNUM))] ;; A lie, but we have to match the expander |
ae180d84 JL |
1828 | "" |
1829 | "andi 65535,%1,%0" | |
03e32fb7 | 1830 | [(set_attr "length" "4")]) |
ae180d84 | 1831 | |
f8dc0f2b JL |
1832 | (define_insn "*zero_extendhisi2_v850_set_flags" |
1833 | [(set (reg:CCNZ CC_REGNUM) | |
1834 | (compare:CCNZ (zero_extend:SI (match_operand:HI 1 "register_operand" "r")) | |
1835 | (const_int 0))) | |
1836 | (set (match_operand:SI 0 "register_operand" "=r") | |
1837 | (zero_extend:SI (match_dup 1)))] | |
1838 | "reload_completed" | |
1839 | "andi 65535,%1,%0" | |
1840 | [(set_attr "length" "4")]) | |
1841 | ||
1dcad079 NC |
1842 | (define_expand "zero_extendhisi2" |
1843 | [(parallel [(set (match_operand:SI 0 "register_operand") | |
1844 | (zero_extend:SI | |
1845 | (match_operand:HI 1 "nonimmediate_operand"))) | |
1846 | (clobber (reg:CC CC_REGNUM))])] | |
1847 | "" | |
1848 | { | |
dbdbd982 | 1849 | if (! (TARGET_V850E_UP)) |
1dcad079 | 1850 | operands[1] = force_reg (HImode, operands[1]); |
d9030ea4 | 1851 | }) |
1dcad079 NC |
1852 | |
1853 | (define_insn "*zero_extendqisi2_v850e" | |
b4378319 NC |
1854 | [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") |
1855 | (zero_extend:SI | |
223a9d64 N |
1856 | (match_operand:QI 1 "nonimmediate_operand" "0,r,T,m"))) |
1857 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 1858 | "(TARGET_V850E_UP)" |
b4378319 NC |
1859 | "@ |
1860 | zxb %0 | |
1861 | andi 255,%1,%0 | |
1862 | sld.bu %1,%0 | |
1863 | ld.bu %1,%0" | |
03e32fb7 | 1864 | [(set_attr "length" "2,4,2,4")]) |
145870b5 | 1865 | |
1dcad079 | 1866 | (define_insn "*zero_extendqisi2_v850" |
ae180d84 JL |
1867 | [(set (match_operand:SI 0 "register_operand" "=r") |
1868 | (zero_extend:SI | |
d9030ea4 | 1869 | (match_operand:QI 1 "register_operand" "r"))) |
1dcad079 | 1870 | (clobber (reg:CC CC_REGNUM))] ;; A lie, but we have to match the expander |
ae180d84 JL |
1871 | "" |
1872 | "andi 255,%1,%0" | |
03e32fb7 | 1873 | [(set_attr "length" "4")]) |
ae180d84 | 1874 | |
f8dc0f2b JL |
1875 | (define_insn "*zero_extendqisi2_v850_set_flags" |
1876 | [(set (reg:CCNZ CC_REGNUM) | |
1877 | (compare:CCNZ (zero_extend:SI (match_operand:QI 1 "register_operand" "r")) | |
1878 | (const_int 0))) | |
1879 | (set (match_operand:SI 0 "register_operand" "=r") | |
1880 | (zero_extend:SI (match_dup 1)))] | |
1881 | "reload_completed" | |
1882 | "andi 255,%1,%0" | |
1883 | [(set_attr "length" "4")]) | |
1884 | ||
1dcad079 NC |
1885 | (define_expand "zero_extendqisi2" |
1886 | [(parallel [(set (match_operand:SI 0 "register_operand") | |
1887 | (zero_extend:SI | |
1888 | (match_operand:QI 1 "nonimmediate_operand"))) | |
1889 | (clobber (reg:CC CC_REGNUM))])] | |
1890 | "" | |
1891 | { | |
dbdbd982 | 1892 | if (! (TARGET_V850E_UP)) |
1dcad079 | 1893 | operands[1] = force_reg (QImode, operands[1]); |
d9030ea4 | 1894 | }) |
1dcad079 | 1895 | |
ae180d84 JL |
1896 | ;;- sign extension instructions |
1897 | ||
b4378319 NC |
1898 | ;; ??? The extendhisi2 pattern should not emit shifts for v850e? |
1899 | ||
1900 | (define_insn "*extendhisi_insn" | |
1901 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1ec0eb08 | 1902 | (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))] |
dbdbd982 | 1903 | "(TARGET_V850E_UP)" |
b4378319 NC |
1904 | "@ |
1905 | sxh %0 | |
1906 | sld.h %1,%0 | |
1907 | ld.h %1,%0" | |
03e32fb7 | 1908 | [(set_attr "length" "2,2,4")]) |
145870b5 NC |
1909 | |
1910 | ;; ??? This is missing a sign extend from memory pattern to match the ld.h | |
1911 | ;; instruction. | |
1912 | ||
ae180d84 | 1913 | (define_expand "extendhisi2" |
223a9d64 N |
1914 | [(parallel [(set (match_dup 2) |
1915 | (ashift:SI (match_operand:HI 1 "register_operand" "") | |
1916 | (const_int 16))) | |
1917 | (clobber (reg:CC CC_REGNUM))]) | |
1918 | (parallel [(set (match_operand:SI 0 "register_operand" "") | |
1919 | (ashiftrt:SI (match_dup 2) | |
1920 | (const_int 16))) | |
1921 | (clobber (reg:CC CC_REGNUM))])] | |
ae180d84 | 1922 | "" |
d9030ea4 N |
1923 | { |
1924 | operands[1] = gen_lowpart (SImode, operands[1]); | |
1925 | operands[2] = gen_reg_rtx (SImode); | |
1926 | }) | |
ae180d84 | 1927 | |
b4378319 NC |
1928 | ;; ??? The extendqisi2 pattern should not emit shifts for v850e? |
1929 | ||
1930 | (define_insn "*extendqisi_insn" | |
1931 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
1ec0eb08 | 1932 | (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))] |
dbdbd982 | 1933 | "(TARGET_V850E_UP)" |
b4378319 NC |
1934 | "@ |
1935 | sxb %0 | |
1936 | sld.b %1,%0 | |
1937 | ld.b %1,%0" | |
03e32fb7 | 1938 | [(set_attr "length" "2,2,4")]) |
145870b5 NC |
1939 | |
1940 | ;; ??? This is missing a sign extend from memory pattern to match the ld.b | |
1941 | ;; instruction. | |
1942 | ||
ae180d84 | 1943 | (define_expand "extendqisi2" |
223a9d64 N |
1944 | [(parallel [(set (match_dup 2) |
1945 | (ashift:SI (match_operand:QI 1 "register_operand" "") | |
1946 | (const_int 24))) | |
1947 | (clobber (reg:CC CC_REGNUM))]) | |
1948 | (parallel [(set (match_operand:SI 0 "register_operand" "") | |
1949 | (ashiftrt:SI (match_dup 2) | |
1950 | (const_int 24))) | |
1951 | (clobber (reg:CC CC_REGNUM))])] | |
ae180d84 | 1952 | "" |
d9030ea4 N |
1953 | { |
1954 | operands[1] = gen_lowpart (SImode, operands[1]); | |
1955 | operands[2] = gen_reg_rtx (SImode); | |
1956 | }) | |
ae180d84 JL |
1957 | \f |
1958 | ;; ---------------------------------------------------------------------- | |
1959 | ;; SHIFTS | |
1960 | ;; ---------------------------------------------------------------------- | |
1961 | ||
1ec0eb08 JL |
1962 | (define_insn_and_split "ashlsi3" |
1963 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
1964 | (ashift:SI | |
1965 | (match_operand:SI 1 "register_operand" "0,0") | |
1966 | (match_operand:SI 2 "nonmemory_operand" "r,N")))] | |
1967 | "" | |
1968 | "#" | |
1969 | "reload_completed" | |
1970 | [(parallel [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) | |
1971 | (clobber (reg:CC CC_REGNUM))])]) | |
1972 | ||
1973 | (define_insn "ashlsi3_clobber_flags" | |
ae180d84 | 1974 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
223a9d64 N |
1975 | (ashift:SI |
1976 | (match_operand:SI 1 "register_operand" "0,0") | |
1977 | (match_operand:SI 2 "nonmemory_operand" "r,N"))) | |
1978 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
1979 | "" |
1980 | "@ | |
1981 | shl %2,%0 | |
1982 | shl %2,%0" | |
03e32fb7 | 1983 | [(set_attr "length" "4,2")]) |
223a9d64 | 1984 | |
f8dc0f2b JL |
1985 | (define_insn "ashlsi3_set_flags" |
1986 | [(set (reg:CCNZ CC_REGNUM) | |
1987 | (compare:CCNZ (ashift:SI (match_operand:SI 1 "register_operand" "0,0") | |
1988 | (match_operand:SI 2 "nonmemory_operand" "r,N")) | |
1989 | (const_int 0))) | |
1990 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
1991 | (ashift:SI (match_dup 1) (match_dup 2)))] | |
1992 | "reload_completed" | |
1993 | "@ | |
1994 | shl %2,%0 | |
1995 | shl %2,%0" | |
1996 | [(set_attr "length" "4,2")]) | |
1997 | ||
1ec0eb08 | 1998 | (define_insn "ashlsi3_v850e2_clobber_flags" |
223a9d64 N |
1999 | [(set (match_operand:SI 0 "register_operand" "=r") |
2000 | (ashift:SI | |
2001 | (match_operand:SI 1 "register_operand" "r") | |
2002 | (match_operand:SI 2 "nonmemory_operand" "r"))) | |
2003 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 2004 | "TARGET_V850E2_UP" |
223a9d64 | 2005 | "shl %2,%1,%0" |
03e32fb7 | 2006 | [(set_attr "length" "4")]) |
ae180d84 | 2007 | |
f8dc0f2b JL |
2008 | (define_insn "ashlsi3_v850e2_set_flags" |
2009 | [(set (reg:CCNZ CC_REGNUM) | |
2010 | (compare:CCNZ (ashift:SI (match_operand:SI 1 "register_operand" "r") | |
2011 | (match_operand:SI 2 "nonmemory_operand" "r")) | |
2012 | (const_int 0))) | |
2013 | (set (match_operand:SI 0 "register_operand" "=r") | |
2014 | (ashift:SI (match_dup 1) (match_dup 2)))] | |
2015 | "reload_completed && TARGET_V850E2_UP" | |
2016 | "shl %2,%1,%0" | |
2017 | [(set_attr "length" "4")]) | |
2018 | ||
1ec0eb08 JL |
2019 | (define_insn_and_split "lshrsi3" |
2020 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
2021 | (lshiftrt:SI | |
2022 | (match_operand:SI 1 "register_operand" "0,0") | |
2023 | (match_operand:SI 2 "nonmemory_operand" "r,N")))] | |
2024 | "" | |
2025 | "#" | |
2026 | "reload_completed" | |
2027 | [(parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (match_dup 2))) | |
2028 | (clobber (reg:CC CC_REGNUM))])]) | |
2029 | ||
2030 | (define_insn "lshrsi3_clobber_flags" | |
ae180d84 | 2031 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
223a9d64 N |
2032 | (lshiftrt:SI |
2033 | (match_operand:SI 1 "register_operand" "0,0") | |
2034 | (match_operand:SI 2 "nonmemory_operand" "r,N"))) | |
2035 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
2036 | "" |
2037 | "@ | |
2038 | shr %2,%0 | |
2039 | shr %2,%0" | |
03e32fb7 | 2040 | [(set_attr "length" "4,2")]) |
223a9d64 | 2041 | |
f8dc0f2b JL |
2042 | (define_insn "lshrsi3_set_flags" |
2043 | [(set (reg:CC CC_REGNUM) | |
2044 | (compare:CC (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") | |
2045 | (match_operand:SI 2 "nonmemory_operand" "r,N")) | |
2046 | (const_int 0))) | |
2047 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
2048 | (lshiftrt:SI (match_dup 1) (match_dup 2)))] | |
2049 | "reload_completed" | |
2050 | "@ | |
2051 | shr %2,%0 | |
2052 | shr %2,%0" | |
2053 | [(set_attr "length" "4,2")]) | |
2054 | ||
1ec0eb08 | 2055 | (define_insn "lshrsi3_v850e2_clobber_flags" |
223a9d64 N |
2056 | [(set (match_operand:SI 0 "register_operand" "=r") |
2057 | (lshiftrt:SI | |
2058 | (match_operand:SI 1 "register_operand" "r") | |
2059 | (match_operand:SI 2 "nonmemory_operand" "r"))) | |
2060 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 2061 | "TARGET_V850E2_UP" |
223a9d64 | 2062 | "shr %2,%1,%0" |
03e32fb7 | 2063 | [(set_attr "length" "4")]) |
ae180d84 | 2064 | |
f8dc0f2b JL |
2065 | (define_insn "lshrsi3_v850e2_set_flags" |
2066 | [(set (reg:CC CC_REGNUM) | |
2067 | (compare:CC (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") | |
2068 | (match_operand:SI 2 "nonmemory_operand" "r")) | |
2069 | (const_int 0))) | |
2070 | (set (match_operand:SI 0 "register_operand" "=r") | |
2071 | (lshiftrt:SI (match_dup 1) (match_dup 2)))] | |
2072 | "reload_completed && TARGET_V850E2_UP" | |
2073 | "shr %2,%1,%0" | |
2074 | [(set_attr "length" "4")]) | |
2075 | ||
1ec0eb08 JL |
2076 | (define_insn_and_split "ashrsi3" |
2077 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
2078 | (ashiftrt:SI | |
2079 | (match_operand:SI 1 "register_operand" "0,0") | |
2080 | (match_operand:SI 2 "nonmemory_operand" "r,N")))] | |
2081 | "" | |
2082 | "#" | |
2083 | "reload_completed" | |
2084 | [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (match_dup 2))) | |
2085 | (clobber (reg:CC CC_REGNUM))])]) | |
2086 | ||
2087 | (define_insn "ashrsi3_clobber_flags" | |
ae180d84 | 2088 | [(set (match_operand:SI 0 "register_operand" "=r,r") |
223a9d64 N |
2089 | (ashiftrt:SI |
2090 | (match_operand:SI 1 "register_operand" "0,0") | |
2091 | (match_operand:SI 2 "nonmemory_operand" "r,N"))) | |
2092 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 JL |
2093 | "" |
2094 | "@ | |
2095 | sar %2,%0 | |
2096 | sar %2,%0" | |
03e32fb7 | 2097 | [(set_attr "length" "4,2")]) |
223a9d64 | 2098 | |
f8dc0f2b JL |
2099 | (define_insn "ashrsi3_set_flags" |
2100 | [(set (reg:CC CC_REGNUM) | |
2101 | (compare:CC (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") | |
2102 | (match_operand:SI 2 "nonmemory_operand" "r,N")) | |
2103 | (const_int 0))) | |
2104 | (set (match_operand:SI 0 "register_operand" "=r,r") | |
2105 | (ashiftrt:SI (match_dup 1) (match_dup 2)))] | |
2106 | "reload_completed" | |
2107 | "@ | |
2108 | sar %2,%0 | |
2109 | sar %2,%0" | |
2110 | [(set_attr "length" "4,2")]) | |
2111 | ||
1ec0eb08 | 2112 | (define_insn "ashrsi3_v850e2_clobber_flags" |
223a9d64 N |
2113 | [(set (match_operand:SI 0 "register_operand" "=r") |
2114 | (ashiftrt:SI | |
2115 | (match_operand:SI 1 "register_operand" "r") | |
2116 | (match_operand:SI 2 "nonmemory_operand" "r"))) | |
2117 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 2118 | "TARGET_V850E2_UP" |
223a9d64 | 2119 | "sar %2,%1,%0" |
03e32fb7 | 2120 | [(set_attr "length" "4")]) |
223a9d64 | 2121 | |
f8dc0f2b JL |
2122 | (define_insn "ashrsi3_v850e2_set_flags" |
2123 | [(set (reg:CC CC_REGNUM) | |
2124 | (compare:CC (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") | |
2125 | (match_operand:SI 2 "nonmemory_operand" "r")) | |
2126 | (const_int 0))) | |
2127 | (set (match_operand:SI 0 "register_operand" "=r") | |
2128 | (ashiftrt:SI (match_dup 1) (match_dup 2)))] | |
2129 | "reload_completed && TARGET_V850E2_UP" | |
2130 | "sar %2,%1,%0" | |
2131 | [(set_attr "length" "4")]) | |
2132 | ||
223a9d64 N |
2133 | ;; ---------------------------------------------------------------------- |
2134 | ;; FIND FIRST BIT INSTRUCTION | |
2135 | ;; ---------------------------------------------------------------------- | |
2136 | ||
2137 | (define_insn "ffssi2" | |
2138 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2139 | (ffs:SI (match_operand:SI 1 "register_operand" "r"))) | |
2140 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 2141 | "TARGET_V850E2_UP" |
223a9d64 | 2142 | "sch1r %1,%0" |
03e32fb7 | 2143 | [(set_attr "length" "4")]) |
ae180d84 JL |
2144 | |
2145 | ;; ---------------------------------------------------------------------- | |
2146 | ;; PROLOGUE/EPILOGUE | |
2147 | ;; ---------------------------------------------------------------------- | |
2148 | (define_expand "prologue" | |
2149 | [(const_int 0)] | |
2150 | "" | |
d9030ea4 N |
2151 | { |
2152 | expand_prologue (); | |
2153 | DONE; | |
2154 | }) | |
ae180d84 JL |
2155 | |
2156 | (define_expand "epilogue" | |
2157 | [(return)] | |
2158 | "" | |
d9030ea4 N |
2159 | { |
2160 | expand_epilogue (); | |
2161 | DONE; | |
2162 | }) | |
ae180d84 | 2163 | |
7323a100 | 2164 | (define_insn "return_simple" |
ae180d84 | 2165 | [(return)] |
7323a100 | 2166 | "reload_completed" |
ae180d84 | 2167 | "jmp [r31]" |
03e32fb7 | 2168 | [(set_attr "length" "2")]) |
ae180d84 JL |
2169 | |
2170 | (define_insn "return_internal" | |
2171 | [(return) | |
2172 | (use (reg:SI 31))] | |
2173 | "" | |
2174 | "jmp [r31]" | |
03e32fb7 | 2175 | [(set_attr "length" "2")]) |
ae180d84 | 2176 | |
223a9d64 N |
2177 | ;; ---------------------------------------------------------------------- |
2178 | ;; v850e2V3 floating-point hardware support | |
2179 | ;; ---------------------------------------------------------------------- | |
2180 | ||
2181 | ||
2182 | (define_insn "addsf3" | |
2183 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2184 | (plus:SF (match_operand:SF 1 "register_operand" "r") | |
2185 | (match_operand:SF 2 "register_operand" "r")))] | |
b84d824d | 2186 | "TARGET_USE_FPU" |
223a9d64 N |
2187 | "addf.s %1,%2,%0" |
2188 | [(set_attr "length" "4") | |
223a9d64 N |
2189 | (set_attr "type" "fpu")]) |
2190 | ||
2191 | (define_insn "adddf3" | |
2192 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2193 | (plus:DF (match_operand:DF 1 "even_reg_operand" "r") | |
2194 | (match_operand:DF 2 "even_reg_operand" "r")))] | |
b84d824d | 2195 | "TARGET_USE_FPU" |
223a9d64 N |
2196 | "addf.d %1,%2,%0" |
2197 | [(set_attr "length" "4") | |
223a9d64 N |
2198 | (set_attr "type" "fpu")]) |
2199 | ||
2200 | (define_insn "subsf3" | |
2201 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2202 | (minus:SF (match_operand:SF 1 "register_operand" "r") | |
2203 | (match_operand:SF 2 "register_operand" "r")))] | |
b84d824d | 2204 | "TARGET_USE_FPU" |
223a9d64 N |
2205 | "subf.s %2,%1,%0" |
2206 | [(set_attr "length" "4") | |
223a9d64 N |
2207 | (set_attr "type" "fpu")]) |
2208 | ||
2209 | (define_insn "subdf3" | |
2210 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2211 | (minus:DF (match_operand:DF 1 "even_reg_operand" "r") | |
2212 | (match_operand:DF 2 "even_reg_operand" "r")))] | |
b84d824d | 2213 | "TARGET_USE_FPU" |
223a9d64 N |
2214 | "subf.d %2,%1,%0" |
2215 | [(set_attr "length" "4") | |
223a9d64 N |
2216 | (set_attr "type" "fpu")]) |
2217 | ||
2218 | (define_insn "mulsf3" | |
2219 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2220 | (mult:SF (match_operand:SF 1 "register_operand" "r") | |
2221 | (match_operand:SF 2 "register_operand" "r")))] | |
b84d824d | 2222 | "TARGET_USE_FPU" |
223a9d64 N |
2223 | "mulf.s %1,%2,%0" |
2224 | [(set_attr "length" "4") | |
223a9d64 N |
2225 | (set_attr "type" "fpu")]) |
2226 | ||
2227 | (define_insn "muldf3" | |
2228 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2229 | (mult:DF (match_operand:DF 1 "even_reg_operand" "r") | |
2230 | (match_operand:DF 2 "even_reg_operand" "r")))] | |
b84d824d | 2231 | "TARGET_USE_FPU" |
223a9d64 N |
2232 | "mulf.d %1,%2,%0" |
2233 | [(set_attr "length" "4") | |
223a9d64 N |
2234 | (set_attr "type" "fpu")]) |
2235 | ||
2236 | (define_insn "divsf3" | |
2237 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2238 | (div:SF (match_operand:SF 1 "register_operand" "r") | |
2239 | (match_operand:SF 2 "register_operand" "r")))] | |
b84d824d | 2240 | "TARGET_USE_FPU" |
223a9d64 N |
2241 | "divf.s %2,%1,%0" |
2242 | [(set_attr "length" "4") | |
223a9d64 N |
2243 | (set_attr "type" "fpu")]) |
2244 | ||
2245 | (define_insn "divdf3" | |
2246 | [(set (match_operand:DF 0 "register_operand" "=r") | |
2247 | (div:DF (match_operand:DF 1 "even_reg_operand" "r") | |
2248 | (match_operand:DF 2 "even_reg_operand" "r")))] | |
b84d824d | 2249 | "TARGET_USE_FPU" |
223a9d64 N |
2250 | "divf.d %2,%1,%0" |
2251 | [(set_attr "length" "4") | |
223a9d64 N |
2252 | (set_attr "type" "fpu")]) |
2253 | ||
2254 | (define_insn "minsf3" | |
2255 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2256 | (smin:SF (match_operand:SF 1 "reg_or_0_operand" "r") | |
2257 | (match_operand:SF 2 "reg_or_0_operand" "r")))] | |
b84d824d | 2258 | "TARGET_USE_FPU" |
223a9d64 N |
2259 | "minf.s %z1,%z2,%0" |
2260 | [(set_attr "length" "4") | |
223a9d64 N |
2261 | (set_attr "type" "fpu")]) |
2262 | ||
2263 | (define_insn "mindf3" | |
2264 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2265 | (smin:DF (match_operand:DF 1 "even_reg_operand" "r") | |
2266 | (match_operand:DF 2 "even_reg_operand" "r")))] | |
b84d824d | 2267 | "TARGET_USE_FPU" |
223a9d64 N |
2268 | "minf.d %1,%2,%0" |
2269 | [(set_attr "length" "4") | |
223a9d64 N |
2270 | (set_attr "type" "fpu")]) |
2271 | ||
2272 | (define_insn "maxsf3" | |
2273 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2274 | (smax:SF (match_operand:SF 1 "reg_or_0_operand" "r") | |
2275 | (match_operand:SF 2 "reg_or_0_operand" "r")))] | |
b84d824d | 2276 | "TARGET_USE_FPU" |
223a9d64 N |
2277 | "maxf.s %z1,%z2,%0" |
2278 | [(set_attr "length" "4") | |
223a9d64 N |
2279 | (set_attr "type" "fpu")]) |
2280 | ||
2281 | (define_insn "maxdf3" | |
2282 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2283 | (smax:DF (match_operand:DF 1 "even_reg_operand" "r") | |
2284 | (match_operand:DF 2 "even_reg_operand" "r")))] | |
b84d824d | 2285 | "TARGET_USE_FPU" |
223a9d64 N |
2286 | "maxf.d %1,%2,%0" |
2287 | [(set_attr "length" "4") | |
223a9d64 N |
2288 | (set_attr "type" "fpu")]) |
2289 | ||
2290 | (define_insn "abssf2" | |
2291 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2292 | (abs:SF (match_operand:SF 1 "register_operand" "r")))] | |
b84d824d | 2293 | "TARGET_USE_FPU" |
223a9d64 N |
2294 | "absf.s %1,%0" |
2295 | [(set_attr "length" "4") | |
223a9d64 N |
2296 | (set_attr "type" "fpu")]) |
2297 | ||
2298 | (define_insn "absdf2" | |
2299 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2300 | (abs:DF (match_operand:DF 1 "even_reg_operand" "r")))] | |
b84d824d | 2301 | "TARGET_USE_FPU" |
223a9d64 N |
2302 | "absf.d %1,%0" |
2303 | [(set_attr "length" "4") | |
223a9d64 N |
2304 | (set_attr "type" "fpu")]) |
2305 | ||
2306 | (define_insn "negsf2" | |
2307 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2308 | (neg:SF (match_operand:SF 1 "register_operand" "r")))] | |
b84d824d | 2309 | "TARGET_USE_FPU" |
223a9d64 N |
2310 | "negf.s %1,%0" |
2311 | [(set_attr "length" "4") | |
223a9d64 N |
2312 | (set_attr "type" "fpu")]) |
2313 | ||
2314 | (define_insn "negdf2" | |
2315 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2316 | (neg:DF (match_operand:DF 1 "even_reg_operand" "r")))] | |
b84d824d | 2317 | "TARGET_USE_FPU" |
223a9d64 N |
2318 | "negf.d %1,%0" |
2319 | [(set_attr "length" "4") | |
223a9d64 N |
2320 | (set_attr "type" "fpu")]) |
2321 | ||
2322 | ;; square-root | |
2323 | (define_insn "sqrtsf2" | |
2324 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2325 | (sqrt:SF (match_operand:SF 1 "register_operand" "r")))] | |
b84d824d | 2326 | "TARGET_USE_FPU" |
223a9d64 N |
2327 | "sqrtf.s %1,%0" |
2328 | [(set_attr "length" "4") | |
223a9d64 N |
2329 | (set_attr "type" "fpu")]) |
2330 | ||
2331 | (define_insn "sqrtdf2" | |
2332 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2333 | (sqrt:DF (match_operand:DF 1 "even_reg_operand" "r")))] | |
b84d824d | 2334 | "TARGET_USE_FPU" |
223a9d64 N |
2335 | "sqrtf.d %1,%0" |
2336 | [(set_attr "length" "4") | |
223a9d64 N |
2337 | (set_attr "type" "fpu")]) |
2338 | ||
2339 | ;; float -> int | |
2340 | (define_insn "fix_truncsfsi2" | |
2341 | [(set (match_operand:SI 0 "register_operand" "=r") | |
5e4aec98 | 2342 | (fix:SI (match_operand:SF 1 "register_operand" "r")))] |
b84d824d | 2343 | "TARGET_USE_FPU" |
223a9d64 N |
2344 | "trncf.sw %1,%0" |
2345 | [(set_attr "length" "4") | |
223a9d64 N |
2346 | (set_attr "type" "fpu")]) |
2347 | ||
b84d824d NC |
2348 | (define_insn "fixuns_truncsfsi2" |
2349 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2350 | (unsigned_fix:SI (match_operand:SF 1 "register_operand" "r")))] | |
2351 | "TARGET_USE_FPU" | |
2352 | "trncf.suw %1, %0" | |
2353 | [(set_attr "length" "4") | |
03e32fb7 | 2354 | (set_attr "type" "fpu")]) |
b84d824d | 2355 | |
223a9d64 N |
2356 | (define_insn "fix_truncdfsi2" |
2357 | [(set (match_operand:SI 0 "register_operand" "=r") | |
5e4aec98 | 2358 | (fix:SI (match_operand:DF 1 "even_reg_operand" "r")))] |
b84d824d | 2359 | "TARGET_USE_FPU" |
223a9d64 N |
2360 | "trncf.dw %1,%0" |
2361 | [(set_attr "length" "4") | |
223a9d64 N |
2362 | (set_attr "type" "fpu")]) |
2363 | ||
b84d824d NC |
2364 | (define_insn "fixuns_truncdfsi2" |
2365 | [(set (match_operand:SI 0 "register_operand" "=r") | |
2366 | (unsigned_fix:SI (match_operand:DF 1 "even_reg_operand" "r")))] | |
2367 | "TARGET_USE_FPU" | |
2368 | "trncf.duw %1, %0" | |
2369 | [(set_attr "length" "4") | |
03e32fb7 | 2370 | (set_attr "type" "fpu")]) |
5e4aec98 | 2371 | |
b84d824d NC |
2372 | (define_insn "fix_truncsfdi2" |
2373 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2374 | (fix:DI (match_operand:SF 1 "register_operand" "r")))] | |
2375 | "TARGET_USE_FPU" | |
2376 | "trncf.sl %1, %0" | |
2377 | [(set_attr "length" "4") | |
b84d824d NC |
2378 | (set_attr "type" "fpu")]) |
2379 | ||
2380 | (define_insn "fixuns_truncsfdi2" | |
2381 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2382 | (unsigned_fix:DI (match_operand:SF 1 "register_operand" "r")))] | |
2383 | "TARGET_USE_FPU" | |
2384 | "trncf.sul %1, %0" | |
2385 | [(set_attr "length" "4") | |
03e32fb7 | 2386 | (set_attr "type" "fpu")]) |
b84d824d NC |
2387 | |
2388 | (define_insn "fix_truncdfdi2" | |
2389 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2390 | (fix:DI (match_operand:DF 1 "even_reg_operand" "r")))] | |
2391 | "TARGET_USE_FPU" | |
2392 | "trncf.dl %1, %0" | |
2393 | [(set_attr "length" "4") | |
b84d824d NC |
2394 | (set_attr "type" "fpu")]) |
2395 | ||
2396 | (define_insn "fixuns_truncdfdi2" | |
2397 | [(set (match_operand:DI 0 "register_operand" "=r") | |
2398 | (unsigned_fix:DI (match_operand:DF 1 "even_reg_operand" "r")))] | |
2399 | "TARGET_USE_FPU" | |
2400 | "trncf.dul %1, %0" | |
2401 | [(set_attr "length" "4") | |
03e32fb7 | 2402 | (set_attr "type" "fpu")]) |
5e4aec98 | 2403 | |
223a9d64 N |
2404 | ;; int -> float |
2405 | (define_insn "floatsisf2" | |
2406 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2407 | (float:SF (match_operand:SI 1 "reg_or_0_operand" "rI")))] | |
b84d824d | 2408 | "TARGET_USE_FPU" |
223a9d64 N |
2409 | "cvtf.ws %z1, %0" |
2410 | [(set_attr "length" "4") | |
223a9d64 N |
2411 | (set_attr "type" "fpu")]) |
2412 | ||
b84d824d NC |
2413 | (define_insn "unsfloatsisf2" |
2414 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2415 | (unsigned_float:SF (match_operand:SI 1 "reg_or_0_operand" "rI")))] | |
2416 | "TARGET_USE_FPU" | |
2417 | "cvtf.uws %z1, %0" | |
2418 | [(set_attr "length" "4") | |
b84d824d NC |
2419 | (set_attr "type" "fpu")]) |
2420 | ||
223a9d64 N |
2421 | (define_insn "floatsidf2" |
2422 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2423 | (float:DF (match_operand:SI 1 "reg_or_0_operand" "rI")))] | |
b84d824d | 2424 | "TARGET_USE_FPU" |
223a9d64 N |
2425 | "cvtf.wd %z1,%0" |
2426 | [(set_attr "length" "4") | |
223a9d64 N |
2427 | (set_attr "type" "fpu")]) |
2428 | ||
b84d824d NC |
2429 | (define_insn "unsfloatsidf2" |
2430 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2431 | (unsigned_float:DF (match_operand:SI 1 "reg_or_0_operand" "rI")))] | |
2432 | "TARGET_USE_FPU" | |
2433 | "cvtf.uwd %z1, %0" | |
2434 | [(set_attr "length" "4") | |
b84d824d NC |
2435 | (set_attr "type" "fpu")]) |
2436 | ||
2437 | (define_insn "floatdisf2" | |
2438 | [(set (match_operand:SF 0 "even_reg_operand" "=r") | |
2439 | (float:SF (match_operand:DI 1 "reg_or_0_operand" "rI")))] | |
2440 | "TARGET_USE_FPU" | |
2441 | "cvtf.ls %z1, %0" | |
2442 | [(set_attr "length" "4") | |
b84d824d NC |
2443 | (set_attr "type" "fpu")]) |
2444 | ||
2445 | (define_insn "unsfloatdisf2" | |
2446 | [(set (match_operand:SF 0 "even_reg_operand" "=r") | |
2447 | (unsigned_float:SF (match_operand:DI 1 "reg_or_0_operand" "rI")))] | |
2448 | "TARGET_USE_FPU" | |
2449 | "cvtf.uls %z1, %0" | |
2450 | [(set_attr "length" "4") | |
b84d824d NC |
2451 | (set_attr "type" "fpu")]) |
2452 | ||
2453 | (define_insn "floatdidf2" | |
2454 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2455 | (float:DF (match_operand:DI 1 "reg_or_0_operand" "rI")))] | |
2456 | "TARGET_USE_FPU" | |
2457 | "cvtf.ld %z1, %0" | |
2458 | [(set_attr "length" "4") | |
b84d824d NC |
2459 | (set_attr "type" "fpu")]) |
2460 | ||
2461 | (define_insn "unsfloatdidf2" | |
2462 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2463 | (unsigned_float:DF (match_operand:DI 1 "reg_or_0_operand" "rI")))] | |
2464 | "TARGET_USE_FPU" | |
2465 | "cvtf.uld %z1, %0" | |
2466 | [(set_attr "length" "4") | |
b84d824d NC |
2467 | (set_attr "type" "fpu")]) |
2468 | ||
223a9d64 N |
2469 | ;; single-float -> double-float |
2470 | (define_insn "extendsfdf2" | |
2471 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2472 | (float_extend:DF | |
2473 | (match_operand:SF 1 "reg_or_0_operand" "rI")))] | |
b84d824d | 2474 | "TARGET_USE_FPU" |
223a9d64 N |
2475 | "cvtf.sd %z1,%0" |
2476 | [(set_attr "length" "4") | |
223a9d64 N |
2477 | (set_attr "type" "fpu")]) |
2478 | ||
2479 | ;; double-float -> single-float | |
2480 | (define_insn "truncdfsf2" | |
2481 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2482 | (float_truncate:SF | |
2483 | (match_operand:DF 1 "even_reg_operand" "r")))] | |
b84d824d | 2484 | "TARGET_USE_FPU" |
223a9d64 N |
2485 | "cvtf.ds %1,%0" |
2486 | [(set_attr "length" "4") | |
223a9d64 N |
2487 | (set_attr "type" "fpu")]) |
2488 | ||
2489 | ;; | |
2490 | ;; ---------------- special insns | |
2491 | ;; | |
2492 | ||
1ec0eb08 JL |
2493 | ;; reciprocal |
2494 | ||
446514af JL |
2495 | ;; Generic code demands that the recip and rsqrt named patterns |
2496 | ;; have precisely one operand. So that's what we expose in the | |
2497 | ;; expander via the strange UNSPEC. However, those expanders | |
2498 | ;; generate normal looking recip and rsqrt patterns. | |
2499 | ||
2500 | (define_expand "recipsf2" | |
2501 | [(set (match_operand:SF 0 "register_operand" "") | |
2502 | (unspec:SF [(match_operand:SF 1 "register_operand" "")] | |
2503 | UNSPEC_RCP))] | |
2504 | "TARGET_USE_FPU" | |
2505 | { | |
2506 | emit_insn (gen_recipsf2_insn (operands[0], CONST1_RTX (SFmode), operands[1])); | |
2507 | DONE; | |
2508 | }) | |
2509 | ||
2510 | (define_insn "recipsf2_insn" | |
223a9d64 N |
2511 | [(set (match_operand:SF 0 "register_operand" "=r") |
2512 | (div:SF (match_operand:SF 1 "const_float_1_operand" "") | |
2513 | (match_operand:SF 2 "register_operand" "r")))] | |
b84d824d | 2514 | "TARGET_USE_FPU" |
223a9d64 N |
2515 | "recipf.s %2,%0" |
2516 | [(set_attr "length" "4") | |
223a9d64 N |
2517 | (set_attr "type" "fpu")]) |
2518 | ||
446514af JL |
2519 | (define_expand "recipdf2" |
2520 | [(set (match_operand:DF 0 "even_reg_operand" "") | |
2521 | (unspec:DF [(match_operand:SF 1 "even_reg_operand" "")] | |
2522 | UNSPEC_RCP))] | |
2523 | "TARGET_USE_FPU" | |
2524 | { | |
2525 | emit_insn (gen_recipdf2_insn (operands[0], CONST1_RTX (DFmode), operands[1])); | |
2526 | DONE; | |
2527 | }) | |
2528 | ||
2529 | (define_insn "recipdf2_insn" | |
223a9d64 N |
2530 | [(set (match_operand:DF 0 "even_reg_operand" "=r") |
2531 | (div:DF (match_operand:DF 1 "const_float_1_operand" "") | |
2532 | (match_operand:DF 2 "even_reg_operand" "r")))] | |
b84d824d | 2533 | "TARGET_USE_FPU" |
223a9d64 N |
2534 | "recipf.d %2,%0" |
2535 | [(set_attr "length" "4") | |
223a9d64 N |
2536 | (set_attr "type" "fpu")]) |
2537 | ||
2538 | ;;; reciprocal of square-root | |
446514af JL |
2539 | (define_expand "rsqrtsf2" |
2540 | [(set (match_operand:SF 0 "register_operand" "=") | |
2541 | (unspec:SF [(match_operand:SF 1 "register_operand" "")] | |
2542 | UNSPEC_RSQRT))] | |
2543 | "TARGET_USE_FPU" | |
2544 | { | |
2545 | emit_insn (gen_rsqrtsf2_insn (operands[0], CONST1_RTX (SFmode), operands[1])); | |
2546 | DONE; | |
2547 | }) | |
2548 | ||
2549 | (define_insn "rsqrtsf2_insn" | |
223a9d64 N |
2550 | [(set (match_operand:SF 0 "register_operand" "=r") |
2551 | (div:SF (match_operand:SF 1 "const_float_1_operand" "") | |
2552 | (sqrt:SF (match_operand:SF 2 "register_operand" "r"))))] | |
b84d824d | 2553 | "TARGET_USE_FPU" |
223a9d64 N |
2554 | "rsqrtf.s %2,%0" |
2555 | [(set_attr "length" "4") | |
223a9d64 N |
2556 | (set_attr "type" "fpu")]) |
2557 | ||
446514af JL |
2558 | (define_expand "rsqrtdf2" |
2559 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2560 | (unspec:DF [(match_operand:DF 1 "even_reg_operand" "r")] | |
2561 | UNSPEC_RSQRT))] | |
2562 | "TARGET_USE_FPU" | |
2563 | { | |
2564 | emit_insn (gen_rsqrtdf2_insn (operands[0], CONST1_RTX (DFmode), operands[1])); | |
2565 | DONE; | |
2566 | }) | |
2567 | ||
2568 | (define_insn "rsqrtdf2_insn" | |
223a9d64 N |
2569 | [(set (match_operand:DF 0 "even_reg_operand" "=r") |
2570 | (div:DF (match_operand:DF 1 "const_float_1_operand" "") | |
2571 | (sqrt:DF (match_operand:DF 2 "even_reg_operand" "r"))))] | |
b84d824d | 2572 | "TARGET_USE_FPU" |
223a9d64 N |
2573 | "rsqrtf.d %2,%0" |
2574 | [(set_attr "length" "4") | |
223a9d64 N |
2575 | (set_attr "type" "fpu")]) |
2576 | ||
4d85233e NC |
2577 | ;; Note: The FPU-2.0 (ie pre e3v5) versions of these routines do not actually |
2578 | ;; need operand 4 to be the same as operand 0. But the FPU-2.0 versions are | |
2579 | ;; also deprecated so the loss of flexibility is unimportant. | |
2580 | ||
223a9d64 | 2581 | ;;; multiply-add |
2a5e3780 NC |
2582 | (define_insn "fmasf4" |
2583 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2584 | (fma:SF (match_operand:SF 1 "register_operand" "r") | |
2585 | (match_operand:SF 2 "register_operand" "r") | |
4d85233e | 2586 | (match_operand:SF 3 "register_operand" "0")))] |
b84d824d | 2587 | "TARGET_USE_FPU" |
4d85233e | 2588 | { return TARGET_V850E3V5_UP ? "fmaf.s %1, %2, %0" : "maddf.s %2, %1, %3, %0"; } |
223a9d64 | 2589 | [(set_attr "length" "4") |
223a9d64 N |
2590 | (set_attr "type" "fpu")]) |
2591 | ||
223a9d64 | 2592 | ;;; multiply-subtract |
2a5e3780 NC |
2593 | (define_insn "fmssf4" |
2594 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2595 | (fma:SF (match_operand:SF 1 "register_operand" "r") | |
2596 | (match_operand:SF 2 "register_operand" "r") | |
4d85233e | 2597 | (neg:SF (match_operand:SF 3 "register_operand" "0"))))] |
b84d824d | 2598 | "TARGET_USE_FPU" |
4d85233e | 2599 | { return TARGET_V850E3V5_UP ? "fmsf.s %1, %2, %0" : "msubf.s %2, %1, %3, %0"; } |
223a9d64 | 2600 | [(set_attr "length" "4") |
223a9d64 N |
2601 | (set_attr "type" "fpu")]) |
2602 | ||
2603 | ;;; negative-multiply-add | |
2a5e3780 NC |
2604 | (define_insn "fnmasf4" |
2605 | [(set (match_operand:SF 0 "register_operand" "=r") | |
b84d824d NC |
2606 | (neg:SF (fma:SF (match_operand:SF 1 "register_operand" "r") |
2607 | (match_operand:SF 2 "register_operand" "r") | |
4d85233e | 2608 | (match_operand:SF 3 "register_operand" "0"))))] |
b84d824d | 2609 | "TARGET_USE_FPU" |
4d85233e | 2610 | { return TARGET_V850E3V5_UP ? "fnmaf.s %1, %2, %0" : "nmaddf.s %2, %1, %3, %0"; } |
223a9d64 | 2611 | [(set_attr "length" "4") |
223a9d64 N |
2612 | (set_attr "type" "fpu")]) |
2613 | ||
2614 | ;; negative-multiply-subtract | |
2a5e3780 | 2615 | (define_insn "fnmssf4" |
4d85233e | 2616 | [(set (match_operand:SF 0 "register_operand" "=r") |
b84d824d NC |
2617 | (neg:SF (fma:SF (match_operand:SF 1 "register_operand" "r") |
2618 | (match_operand:SF 2 "register_operand" "r") | |
4d85233e | 2619 | (neg:SF (match_operand:SF 3 "register_operand" "0")))))] |
b84d824d | 2620 | "TARGET_USE_FPU" |
4d85233e | 2621 | { return TARGET_V850E3V5_UP ? "fnmsf.s %1, %2, %0" : "nmsubf.s %2, %1, %3, %0"; } |
223a9d64 | 2622 | [(set_attr "length" "4") |
223a9d64 N |
2623 | (set_attr "type" "fpu")]) |
2624 | ; | |
2625 | ; ---------------- comparison/conditionals | |
2626 | ; | |
2627 | ; SF | |
2628 | ||
2629 | (define_insn "cmpsf_le_insn" | |
2630 | [(set (reg:CC_FPU_LE FCC_REGNUM) | |
2631 | (compare:CC_FPU_LE (match_operand:SF 0 "register_operand" "r") | |
2632 | (match_operand:SF 1 "register_operand" "r")))] | |
1ec0eb08 | 2633 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2634 | "cmpf.s le, %z0, %z1" |
223a9d64 | 2635 | [(set_attr "length" "4") |
223a9d64 N |
2636 | (set_attr "type" "fpu")]) |
2637 | ||
2638 | (define_insn "cmpsf_lt_insn" | |
2639 | [(set (reg:CC_FPU_LT FCC_REGNUM) | |
2640 | (compare:CC_FPU_LT (match_operand:SF 0 "register_operand" "r") | |
2641 | (match_operand:SF 1 "register_operand" "r")))] | |
1ec0eb08 | 2642 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2643 | "cmpf.s lt, %z0, %z1" |
223a9d64 | 2644 | [(set_attr "length" "4") |
223a9d64 N |
2645 | (set_attr "type" "fpu")]) |
2646 | ||
2647 | (define_insn "cmpsf_ge_insn" | |
2648 | [(set (reg:CC_FPU_GE FCC_REGNUM) | |
2649 | (compare:CC_FPU_GE (match_operand:SF 0 "register_operand" "r") | |
2650 | (match_operand:SF 1 "register_operand" "r")))] | |
1ec0eb08 | 2651 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2652 | "cmpf.s le, %z1, %z0" |
223a9d64 | 2653 | [(set_attr "length" "4") |
223a9d64 N |
2654 | (set_attr "type" "fpu")]) |
2655 | ||
2656 | (define_insn "cmpsf_gt_insn" | |
2657 | [(set (reg:CC_FPU_GT FCC_REGNUM) | |
2658 | (compare:CC_FPU_GT (match_operand:SF 0 "register_operand" "r") | |
2659 | (match_operand:SF 1 "register_operand" "r")))] | |
1ec0eb08 | 2660 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2661 | "cmpf.s lt, %z1, %z0" |
223a9d64 | 2662 | [(set_attr "length" "4") |
223a9d64 N |
2663 | (set_attr "type" "fpu")]) |
2664 | ||
2665 | (define_insn "cmpsf_eq_insn" | |
2666 | [(set (reg:CC_FPU_EQ FCC_REGNUM) | |
2667 | (compare:CC_FPU_EQ (match_operand:SF 0 "register_operand" "r") | |
2668 | (match_operand:SF 1 "register_operand" "r")))] | |
1ec0eb08 | 2669 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2670 | "cmpf.s eq, %z0, %z1" |
223a9d64 | 2671 | [(set_attr "length" "4") |
223a9d64 N |
2672 | (set_attr "type" "fpu")]) |
2673 | ||
2674 | ; DF | |
2675 | ||
2676 | (define_insn "cmpdf_le_insn" | |
2677 | [(set (reg:CC_FPU_LE FCC_REGNUM) | |
2678 | (compare:CC_FPU_LE (match_operand:DF 0 "even_reg_operand" "r") | |
2679 | (match_operand:DF 1 "even_reg_operand" "r")))] | |
1ec0eb08 | 2680 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2681 | "cmpf.d le, %z0, %z1" |
223a9d64 | 2682 | [(set_attr "length" "4") |
223a9d64 N |
2683 | (set_attr "type" "fpu")]) |
2684 | ||
2685 | (define_insn "cmpdf_lt_insn" | |
2686 | [(set (reg:CC_FPU_LT FCC_REGNUM) | |
2687 | (compare:CC_FPU_LT (match_operand:DF 0 "even_reg_operand" "r") | |
2688 | (match_operand:DF 1 "even_reg_operand" "r")))] | |
1ec0eb08 | 2689 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2690 | "cmpf.d lt, %z0, %z1" |
223a9d64 | 2691 | [(set_attr "length" "4") |
223a9d64 N |
2692 | (set_attr "type" "fpu")]) |
2693 | ||
2694 | (define_insn "cmpdf_ge_insn" | |
2695 | [(set (reg:CC_FPU_GE FCC_REGNUM) | |
2696 | (compare:CC_FPU_GE (match_operand:DF 0 "even_reg_operand" "r") | |
2697 | (match_operand:DF 1 "even_reg_operand" "r")))] | |
1ec0eb08 | 2698 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2699 | "cmpf.d le, %z1, %z0" |
223a9d64 | 2700 | [(set_attr "length" "4") |
223a9d64 N |
2701 | (set_attr "type" "fpu")]) |
2702 | ||
2703 | (define_insn "cmpdf_gt_insn" | |
2704 | [(set (reg:CC_FPU_GT FCC_REGNUM) | |
2705 | (compare:CC_FPU_GT (match_operand:DF 0 "even_reg_operand" "r") | |
3cd232b5 | 2706 | (match_operand:DF 1 "even_reg_operand" "r")))] |
1ec0eb08 | 2707 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2708 | "cmpf.d lt, %z1, %z0" |
223a9d64 | 2709 | [(set_attr "length" "4") |
223a9d64 N |
2710 | (set_attr "type" "fpu")]) |
2711 | ||
2712 | (define_insn "cmpdf_eq_insn" | |
2713 | [(set (reg:CC_FPU_EQ FCC_REGNUM) | |
2714 | (compare:CC_FPU_EQ (match_operand:DF 0 "even_reg_operand" "r") | |
2715 | (match_operand:DF 1 "even_reg_operand" "r")))] | |
1ec0eb08 | 2716 | "reload_completed && TARGET_USE_FPU" |
3cd232b5 | 2717 | "cmpf.d eq, %z0, %z1" |
223a9d64 | 2718 | [(set_attr "length" "4") |
223a9d64 N |
2719 | (set_attr "type" "fpu")]) |
2720 | ||
223a9d64 N |
2721 | ;; |
2722 | ;; Transfer a v850e2v3 fcc to the Z bit of CC0 (this is necessary to do a | |
2723 | ;; conditional branch based on a floating-point compare) | |
2724 | ;; | |
2725 | ||
2726 | (define_insn "trfsr" | |
2727 | [(set (match_operand 0 "" "") (match_operand 1 "" ""))] | |
1ec0eb08 JL |
2728 | "reload_completed |
2729 | && TARGET_USE_FPU | |
223a9d64 N |
2730 | && GET_MODE(operands[0]) == GET_MODE(operands[1]) |
2731 | && GET_CODE(operands[0]) == REG && REGNO (operands[0]) == CC_REGNUM | |
2732 | && GET_CODE(operands[1]) == REG && REGNO (operands[1]) == FCC_REGNUM | |
2733 | && (GET_MODE(operands[0]) == CC_FPU_LEmode | |
2734 | || GET_MODE(operands[0]) == CC_FPU_GEmode | |
2735 | || GET_MODE(operands[0]) == CC_FPU_LTmode | |
2736 | || GET_MODE(operands[0]) == CC_FPU_GTmode | |
2737 | || GET_MODE(operands[0]) == CC_FPU_EQmode | |
2738 | || GET_MODE(operands[0]) == CC_FPU_NEmode)" | |
2739 | "trfsr" | |
2740 | [(set_attr "length" "4") | |
223a9d64 N |
2741 | (set_attr "type" "fpu")]) |
2742 | ||
2743 | ;; | |
2744 | ;; Floating-point conditional moves for the v850e2v3. | |
2745 | ;; | |
2746 | ||
2747 | ;; The actual v850e2v3 conditional move instructions | |
2748 | ;; | |
2749 | (define_insn "movsfcc_z_insn" | |
2750 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2751 | (if_then_else:SF | |
2752 | (match_operand 3 "v850_float_z_comparison_operator" "") | |
2753 | (match_operand:SF 1 "reg_or_0_operand" "rIG") | |
2754 | (match_operand:SF 2 "reg_or_0_operand" "rIG")))] | |
b84d824d | 2755 | "TARGET_USE_FPU" |
03e32fb7 | 2756 | "cmovf.s 0,%z1,%z2,%0") |
223a9d64 N |
2757 | |
2758 | (define_insn "movsfcc_nz_insn" | |
2759 | [(set (match_operand:SF 0 "register_operand" "=r") | |
2760 | (if_then_else:SF | |
2761 | (match_operand 3 "v850_float_nz_comparison_operator" "") | |
2762 | (match_operand:SF 1 "reg_or_0_operand" "rIG") | |
2763 | (match_operand:SF 2 "reg_or_0_operand" "rIG")))] | |
b84d824d | 2764 | "TARGET_USE_FPU" |
03e32fb7 | 2765 | "cmovf.s 0,%z2,%z1,%0") |
223a9d64 N |
2766 | |
2767 | (define_insn "movdfcc_z_insn" | |
2768 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2769 | (if_then_else:DF | |
2770 | (match_operand 3 "v850_float_z_comparison_operator" "") | |
2771 | (match_operand:DF 1 "even_reg_operand" "r") | |
2772 | (match_operand:DF 2 "even_reg_operand" "r")))] | |
b84d824d | 2773 | "TARGET_USE_FPU" |
03e32fb7 | 2774 | "cmovf.d 0,%z1,%z2,%0") |
223a9d64 N |
2775 | |
2776 | (define_insn "movdfcc_nz_insn" | |
2777 | [(set (match_operand:DF 0 "even_reg_operand" "=r") | |
2778 | (if_then_else:DF | |
2779 | (match_operand 3 "v850_float_nz_comparison_operator" "") | |
2780 | (match_operand:DF 1 "even_reg_operand" "r") | |
2781 | (match_operand:DF 2 "even_reg_operand" "r")))] | |
b84d824d | 2782 | "TARGET_USE_FPU" |
03e32fb7 | 2783 | "cmovf.d 0,%z2,%z1,%0") |
223a9d64 N |
2784 | |
2785 | (define_insn "movedfcc_z_zero" | |
2786 | [(set (match_operand:DF 0 "register_operand" "=r") | |
2787 | (if_then_else:DF | |
2788 | (match_operand 3 "v850_float_z_comparison_operator" "") | |
2789 | (match_operand:DF 1 "reg_or_0_operand" "rIG") | |
2790 | (match_operand:DF 2 "reg_or_0_operand" "rIG")))] | |
b84d824d | 2791 | "TARGET_USE_FPU" |
223a9d64 | 2792 | "cmovf.s 0,%z1,%z2,%0 ; cmovf.s 0,%Z1,%Z2,%R0" |
03e32fb7 | 2793 | [(set_attr "length" "8")]) |
223a9d64 N |
2794 | |
2795 | (define_insn "movedfcc_nz_zero" | |
2796 | [(set (match_operand:DF 0 "register_operand" "=r") | |
2797 | (if_then_else:DF | |
2798 | (match_operand 3 "v850_float_nz_comparison_operator" "") | |
2799 | (match_operand:DF 1 "reg_or_0_operand" "rIG") | |
2800 | (match_operand:DF 2 "reg_or_0_operand" "rIG")))] | |
b84d824d | 2801 | "TARGET_USE_FPU" |
223a9d64 | 2802 | "cmovf.s 0,%z2,%z1,%0 ; cmovf.s 0,%Z2,%Z1,%R0" |
03e32fb7 | 2803 | [(set_attr "length" "8")]) |
223a9d64 | 2804 | |
ae180d84 | 2805 | |
ae180d84 | 2806 | ;; ---------------------------------------------------------------------- |
22f23985 | 2807 | ;; HELPER INSTRUCTIONS for saving the prologue and epilogue registers |
ae180d84 JL |
2808 | ;; ---------------------------------------------------------------------- |
2809 | ||
9302e6e5 JL |
2810 | ;; This pattern will match a stack adjust RTX followed by any number of push |
2811 | ;; RTXs. These RTXs will then be turned into a suitable call to a worker | |
2812 | ;; function. | |
2813 | ||
b4378319 NC |
2814 | ;; |
2815 | ;; Actually, convert the RTXs into a PREPARE instruction. | |
2816 | ;; | |
223a9d64 | 2817 | |
b4378319 NC |
2818 | (define_insn "" |
2819 | [(match_parallel 0 "pattern_is_ok_for_prepare" | |
2820 | [(set (reg:SI 3) | |
2821 | (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
2822 | (set (mem:SI (plus:SI (reg:SI 3) | |
2823 | (match_operand:SI 2 "immediate_operand" "i"))) | |
2824 | (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])] | |
dbdbd982 | 2825 | "TARGET_PROLOG_FUNCTION && (TARGET_V850E_UP)" |
d9030ea4 N |
2826 | { |
2827 | return construct_prepare_instruction (operands[0]); | |
2828 | } | |
03e32fb7 | 2829 | [(set_attr "length" "4")]) |
145870b5 | 2830 | |
9302e6e5 JL |
2831 | (define_insn "" |
2832 | [(match_parallel 0 "pattern_is_ok_for_prologue" | |
2833 | [(set (reg:SI 3) | |
2834 | (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
145870b5 NC |
2835 | (set (mem:SI (plus:SI (reg:SI 3) |
2836 | (match_operand:SI 2 "immediate_operand" "i"))) | |
9302e6e5 | 2837 | (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])] |
223a9d64 | 2838 | "TARGET_PROLOG_FUNCTION" |
d9030ea4 N |
2839 | { |
2840 | return construct_save_jarl (operands[0]); | |
2841 | } | |
be1d3f93 NC |
2842 | [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes") |
2843 | (const_string "16") | |
03e32fb7 | 2844 | (const_string "4")))]) |
ae180d84 | 2845 | |
b4378319 NC |
2846 | ;; |
2847 | ;; Actually, turn the RTXs into a DISPOSE instruction. | |
2848 | ;; | |
2849 | (define_insn "" | |
2850 | [(match_parallel 0 "pattern_is_ok_for_dispose" | |
2851 | [(return) | |
2852 | (set (reg:SI 3) | |
2853 | (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
2854 | (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r") | |
2855 | (mem:SI (plus:SI (reg:SI 3) | |
2856 | (match_operand:SI 3 "immediate_operand" "i"))))])] | |
dbdbd982 | 2857 | "TARGET_PROLOG_FUNCTION && (TARGET_V850E_UP)" |
d9030ea4 N |
2858 | { |
2859 | return construct_dispose_instruction (operands[0]); | |
2860 | } | |
03e32fb7 | 2861 | [(set_attr "length" "4")]) |
b4378319 | 2862 | |
9302e6e5 JL |
2863 | ;; This pattern will match a return RTX followed by any number of pop RTXs |
2864 | ;; and possible a stack adjustment as well. These RTXs will be turned into | |
2865 | ;; a suitable call to a worker function. | |
ae180d84 | 2866 | |
9302e6e5 JL |
2867 | (define_insn "" |
2868 | [(match_parallel 0 "pattern_is_ok_for_epilogue" | |
2869 | [(return) | |
2870 | (set (reg:SI 3) | |
2871 | (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i"))) | |
997718c7 | 2872 | (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r") |
9302e6e5 JL |
2873 | (mem:SI (plus:SI (reg:SI 3) |
2874 | (match_operand:SI 3 "immediate_operand" "i"))))])] | |
223a9d64 | 2875 | "TARGET_PROLOG_FUNCTION" |
d9030ea4 N |
2876 | { |
2877 | return construct_restore_jr (operands[0]); | |
2878 | } | |
be1d3f93 NC |
2879 | [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes") |
2880 | (const_string "12") | |
03e32fb7 | 2881 | (const_string "4")))]) |
ae180d84 | 2882 | |
29a65e3d | 2883 | ;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION. |
b4378319 | 2884 | (define_insn "callt_save_interrupt" |
1ec0eb08 JL |
2885 | [(unspec_volatile [(const_int 0)] 2) |
2886 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 2887 | "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" |
b4378319 NC |
2888 | ;; The CALLT instruction stores the next address of CALLT to CTPC register |
2889 | ;; without saving its previous value. So if the interrupt handler | |
839a4992 | 2890 | ;; or its caller could possibly execute the CALLT insn, save_interrupt |
b4378319 | 2891 | ;; MUST NOT be called via CALLT. |
b4378319 | 2892 | { |
d9030ea4 N |
2893 | output_asm_insn ("addi -28, sp, sp", operands); |
2894 | output_asm_insn ("st.w r1, 24[sp]", operands); | |
2895 | output_asm_insn ("st.w r10, 12[sp]", operands); | |
2896 | output_asm_insn ("st.w r11, 16[sp]", operands); | |
2897 | output_asm_insn ("stsr ctpc, r10", operands); | |
2898 | output_asm_insn ("st.w r10, 20[sp]", operands); | |
2899 | output_asm_insn ("stsr ctpsw, r10", operands); | |
2900 | output_asm_insn ("st.w r10, 24[sp]", operands); | |
2901 | output_asm_insn ("callt ctoff(__callt_save_interrupt)", operands); | |
2902 | return ""; | |
2903 | } | |
03e32fb7 | 2904 | [(set_attr "length" "26")]) |
b4378319 NC |
2905 | |
2906 | (define_insn "callt_return_interrupt" | |
1ec0eb08 JL |
2907 | [(unspec_volatile [(const_int 0)] 3) |
2908 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 2909 | "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" |
b4378319 | 2910 | "callt ctoff(__callt_return_interrupt)" |
03e32fb7 | 2911 | [(set_attr "length" "2")]) |
b4378319 | 2912 | |
29a65e3d | 2913 | (define_insn "save_interrupt" |
223a9d64 N |
2914 | [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -20))) |
2915 | (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 30)) | |
2916 | (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 4)) | |
2917 | (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1)) | |
2918 | (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 10)) | |
1ec0eb08 JL |
2919 | (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 11)) |
2920 | (clobber (reg:CC CC_REGNUM))] | |
b4378319 | 2921 | "" |
b4378319 NC |
2922 | { |
2923 | if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
d9030ea4 | 2924 | return "addi -20,sp,sp \; st.w r11,16[sp] \; st.w r10,12[sp] \; jarl __save_interrupt,r10"; |
b4378319 NC |
2925 | else |
2926 | { | |
d9030ea4 N |
2927 | output_asm_insn ("addi -20, sp, sp", operands); |
2928 | output_asm_insn ("st.w r11, 16[sp]", operands); | |
2929 | output_asm_insn ("st.w r10, 12[sp]", operands); | |
2930 | output_asm_insn ("st.w ep, 0[sp]", operands); | |
2931 | output_asm_insn ("st.w gp, 4[sp]", operands); | |
2932 | output_asm_insn ("st.w r1, 8[sp]", operands); | |
2933 | output_asm_insn ("movhi hi(__ep), r0, ep", operands); | |
2934 | output_asm_insn ("movea lo(__ep), ep, ep", operands); | |
2935 | output_asm_insn ("movhi hi(__gp), r0, gp", operands); | |
2936 | output_asm_insn ("movea lo(__gp), gp, gp", operands); | |
2937 | return ""; | |
b4378319 | 2938 | } |
d9030ea4 | 2939 | } |
b4378319 | 2940 | [(set (attr "length") |
61c4c150 | 2941 | (if_then_else (match_test "TARGET_LONG_CALLS") |
b4378319 | 2942 | (const_int 10) |
03e32fb7 | 2943 | (const_int 34)))]) |
b4378319 | 2944 | |
b24bcfb3 | 2945 | ;; Restore r1, r4, r10, and return from the interrupt |
b4378319 | 2946 | (define_insn "return_interrupt" |
ae180d84 | 2947 | [(return) |
223a9d64 N |
2948 | (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 20))) |
2949 | (set (reg:SI 11) (mem:SI (plus:SI (reg:SI 3) (const_int 16)))) | |
b4378319 NC |
2950 | (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 12)))) |
2951 | (set (reg:SI 1) (mem:SI (plus:SI (reg:SI 3) (const_int 8)))) | |
2952 | (set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4)))) | |
1ec0eb08 JL |
2953 | (set (reg:SI 30) (mem:SI (reg:SI 3))) |
2954 | (clobber (reg:CC CC_REGNUM))] | |
ae180d84 | 2955 | "" |
b4378319 NC |
2956 | { |
2957 | if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
d9030ea4 | 2958 | return "jr __return_interrupt"; |
b4378319 NC |
2959 | else |
2960 | { | |
d9030ea4 N |
2961 | output_asm_insn ("ld.w 0[sp], ep", operands); |
2962 | output_asm_insn ("ld.w 4[sp], gp", operands); | |
2963 | output_asm_insn ("ld.w 8[sp], r1", operands); | |
2964 | output_asm_insn ("ld.w 12[sp], r10", operands); | |
2965 | output_asm_insn ("ld.w 16[sp], r11", operands); | |
2966 | output_asm_insn ("addi 20, sp, sp", operands); | |
2967 | output_asm_insn ("reti", operands); | |
2968 | return ""; | |
b4378319 | 2969 | } |
d9030ea4 | 2970 | } |
b4378319 | 2971 | [(set (attr "length") |
61c4c150 | 2972 | (if_then_else (match_test "TARGET_LONG_CALLS") |
b4378319 | 2973 | (const_int 4) |
03e32fb7 | 2974 | (const_int 24)))]) |
ae180d84 | 2975 | |
29a65e3d NC |
2976 | ;; Save all registers except for the registers saved in save_interrupt when |
2977 | ;; an interrupt function makes a call. | |
2978 | ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and | |
2979 | ;; all of memory. This blocks insns from being moved across this point. | |
2980 | ;; This is needed because the rest of the compiler is not ready to handle | |
2981 | ;; insns this complicated. | |
2982 | ||
b4378319 | 2983 | (define_insn "callt_save_all_interrupt" |
1ec0eb08 JL |
2984 | [(unspec_volatile [(const_int 0)] 0) |
2985 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 2986 | "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" |
b4378319 | 2987 | "callt ctoff(__callt_save_all_interrupt)" |
03e32fb7 | 2988 | [(set_attr "length" "2")]) |
b4378319 | 2989 | |
29a65e3d | 2990 | (define_insn "save_all_interrupt" |
1ec0eb08 JL |
2991 | [(unspec_volatile [(const_int 0)] 0) |
2992 | (clobber (reg:CC CC_REGNUM))] | |
b4378319 | 2993 | "" |
b4378319 NC |
2994 | { |
2995 | if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
d9030ea4 | 2996 | return "jarl __save_all_interrupt,r10"; |
b4378319 | 2997 | |
d9030ea4 | 2998 | output_asm_insn ("addi -120, sp, sp", operands); |
2ec6cd51 NC |
2999 | |
3000 | if (TARGET_EP) | |
3001 | { | |
d9030ea4 N |
3002 | output_asm_insn ("mov ep, r1", operands); |
3003 | output_asm_insn ("mov sp, ep", operands); | |
3004 | output_asm_insn ("sst.w r31, 116[ep]", operands); | |
3005 | output_asm_insn ("sst.w r2, 112[ep]", operands); | |
3006 | output_asm_insn ("sst.w gp, 108[ep]", operands); | |
3007 | output_asm_insn ("sst.w r6, 104[ep]", operands); | |
3008 | output_asm_insn ("sst.w r7, 100[ep]", operands); | |
3009 | output_asm_insn ("sst.w r8, 96[ep]", operands); | |
3010 | output_asm_insn ("sst.w r9, 92[ep]", operands); | |
3011 | output_asm_insn ("sst.w r11, 88[ep]", operands); | |
3012 | output_asm_insn ("sst.w r12, 84[ep]", operands); | |
3013 | output_asm_insn ("sst.w r13, 80[ep]", operands); | |
3014 | output_asm_insn ("sst.w r14, 76[ep]", operands); | |
3015 | output_asm_insn ("sst.w r15, 72[ep]", operands); | |
3016 | output_asm_insn ("sst.w r16, 68[ep]", operands); | |
3017 | output_asm_insn ("sst.w r17, 64[ep]", operands); | |
3018 | output_asm_insn ("sst.w r18, 60[ep]", operands); | |
3019 | output_asm_insn ("sst.w r19, 56[ep]", operands); | |
3020 | output_asm_insn ("sst.w r20, 52[ep]", operands); | |
3021 | output_asm_insn ("sst.w r21, 48[ep]", operands); | |
3022 | output_asm_insn ("sst.w r22, 44[ep]", operands); | |
3023 | output_asm_insn ("sst.w r23, 40[ep]", operands); | |
3024 | output_asm_insn ("sst.w r24, 36[ep]", operands); | |
3025 | output_asm_insn ("sst.w r25, 32[ep]", operands); | |
3026 | output_asm_insn ("sst.w r26, 28[ep]", operands); | |
3027 | output_asm_insn ("sst.w r27, 24[ep]", operands); | |
3028 | output_asm_insn ("sst.w r28, 20[ep]", operands); | |
3029 | output_asm_insn ("sst.w r29, 16[ep]", operands); | |
3030 | output_asm_insn ("mov r1, ep", operands); | |
2ec6cd51 NC |
3031 | } |
3032 | else | |
3033 | { | |
d9030ea4 N |
3034 | output_asm_insn ("st.w r31, 116[sp]", operands); |
3035 | output_asm_insn ("st.w r2, 112[sp]", operands); | |
3036 | output_asm_insn ("st.w gp, 108[sp]", operands); | |
3037 | output_asm_insn ("st.w r6, 104[sp]", operands); | |
3038 | output_asm_insn ("st.w r7, 100[sp]", operands); | |
3039 | output_asm_insn ("st.w r8, 96[sp]", operands); | |
3040 | output_asm_insn ("st.w r9, 92[sp]", operands); | |
3041 | output_asm_insn ("st.w r11, 88[sp]", operands); | |
3042 | output_asm_insn ("st.w r12, 84[sp]", operands); | |
3043 | output_asm_insn ("st.w r13, 80[sp]", operands); | |
3044 | output_asm_insn ("st.w r14, 76[sp]", operands); | |
3045 | output_asm_insn ("st.w r15, 72[sp]", operands); | |
3046 | output_asm_insn ("st.w r16, 68[sp]", operands); | |
3047 | output_asm_insn ("st.w r17, 64[sp]", operands); | |
3048 | output_asm_insn ("st.w r18, 60[sp]", operands); | |
3049 | output_asm_insn ("st.w r19, 56[sp]", operands); | |
3050 | output_asm_insn ("st.w r20, 52[sp]", operands); | |
3051 | output_asm_insn ("st.w r21, 48[sp]", operands); | |
3052 | output_asm_insn ("st.w r22, 44[sp]", operands); | |
3053 | output_asm_insn ("st.w r23, 40[sp]", operands); | |
3054 | output_asm_insn ("st.w r24, 36[sp]", operands); | |
3055 | output_asm_insn ("st.w r25, 32[sp]", operands); | |
3056 | output_asm_insn ("st.w r26, 28[sp]", operands); | |
3057 | output_asm_insn ("st.w r27, 24[sp]", operands); | |
3058 | output_asm_insn ("st.w r28, 20[sp]", operands); | |
3059 | output_asm_insn ("st.w r29, 16[sp]", operands); | |
2ec6cd51 NC |
3060 | } |
3061 | ||
d9030ea4 N |
3062 | return ""; |
3063 | } | |
b4378319 | 3064 | [(set (attr "length") |
61c4c150 | 3065 | (if_then_else (match_test "TARGET_LONG_CALLS") |
b4378319 | 3066 | (const_int 4) |
1ec0eb08 JL |
3067 | (const_int 62) |
3068 | ))]) | |
b4378319 NC |
3069 | |
3070 | (define_insn "_save_all_interrupt" | |
1ec0eb08 JL |
3071 | [(unspec_volatile [(const_int 0)] 0) |
3072 | (clobber (reg:CC CC_REGNUM))] | |
be1d3f93 | 3073 | "TARGET_V850 && ! TARGET_LONG_CALLS" |
29a65e3d | 3074 | "jarl __save_all_interrupt,r10" |
03e32fb7 | 3075 | [(set_attr "length" "4")]) |
29a65e3d | 3076 | |
ae180d84 JL |
3077 | ;; Restore all registers saved when an interrupt function makes a call. |
3078 | ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and | |
3079 | ;; all of memory. This blocks insns from being moved across this point. | |
956d6950 JL |
3080 | ;; This is needed because the rest of the compiler is not ready to handle |
3081 | ;; insns this complicated. | |
ae180d84 | 3082 | |
b4378319 | 3083 | (define_insn "callt_restore_all_interrupt" |
1ec0eb08 JL |
3084 | [(unspec_volatile [(const_int 0)] 1) |
3085 | (clobber (reg:CC CC_REGNUM))] | |
dbdbd982 | 3086 | "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" |
b4378319 | 3087 | "callt ctoff(__callt_restore_all_interrupt)" |
03e32fb7 | 3088 | [(set_attr "length" "2")]) |
b4378319 | 3089 | |
ae180d84 | 3090 | (define_insn "restore_all_interrupt" |
1ec0eb08 JL |
3091 | [(unspec_volatile [(const_int 0)] 1) |
3092 | (clobber (reg:CC CC_REGNUM))] | |
b4378319 | 3093 | "" |
b4378319 NC |
3094 | { |
3095 | if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) | |
d9030ea4 | 3096 | return "jarl __restore_all_interrupt,r10"; |
2ec6cd51 NC |
3097 | |
3098 | if (TARGET_EP) | |
b4378319 | 3099 | { |
d9030ea4 N |
3100 | output_asm_insn ("mov ep, r1", operands); |
3101 | output_asm_insn ("mov sp, ep", operands); | |
3102 | output_asm_insn ("sld.w 116[ep], r31", operands); | |
3103 | output_asm_insn ("sld.w 112[ep], r2", operands); | |
3104 | output_asm_insn ("sld.w 108[ep], gp", operands); | |
3105 | output_asm_insn ("sld.w 104[ep], r6", operands); | |
3106 | output_asm_insn ("sld.w 100[ep], r7", operands); | |
3107 | output_asm_insn ("sld.w 96[ep], r8", operands); | |
3108 | output_asm_insn ("sld.w 92[ep], r9", operands); | |
3109 | output_asm_insn ("sld.w 88[ep], r11", operands); | |
3110 | output_asm_insn ("sld.w 84[ep], r12", operands); | |
3111 | output_asm_insn ("sld.w 80[ep], r13", operands); | |
3112 | output_asm_insn ("sld.w 76[ep], r14", operands); | |
3113 | output_asm_insn ("sld.w 72[ep], r15", operands); | |
3114 | output_asm_insn ("sld.w 68[ep], r16", operands); | |
3115 | output_asm_insn ("sld.w 64[ep], r17", operands); | |
3116 | output_asm_insn ("sld.w 60[ep], r18", operands); | |
3117 | output_asm_insn ("sld.w 56[ep], r19", operands); | |
3118 | output_asm_insn ("sld.w 52[ep], r20", operands); | |
3119 | output_asm_insn ("sld.w 48[ep], r21", operands); | |
3120 | output_asm_insn ("sld.w 44[ep], r22", operands); | |
3121 | output_asm_insn ("sld.w 40[ep], r23", operands); | |
3122 | output_asm_insn ("sld.w 36[ep], r24", operands); | |
3123 | output_asm_insn ("sld.w 32[ep], r25", operands); | |
3124 | output_asm_insn ("sld.w 28[ep], r26", operands); | |
3125 | output_asm_insn ("sld.w 24[ep], r27", operands); | |
3126 | output_asm_insn ("sld.w 20[ep], r28", operands); | |
3127 | output_asm_insn ("sld.w 16[ep], r29", operands); | |
3128 | output_asm_insn ("mov r1, ep", operands); | |
b4378319 | 3129 | } |
2ec6cd51 NC |
3130 | else |
3131 | { | |
d9030ea4 N |
3132 | output_asm_insn ("ld.w 116[sp], r31", operands); |
3133 | output_asm_insn ("ld.w 112[sp], r2", operands); | |
3134 | output_asm_insn ("ld.w 108[sp], gp", operands); | |
3135 | output_asm_insn ("ld.w 104[sp], r6", operands); | |
3136 | output_asm_insn ("ld.w 100[sp], r7", operands); | |
3137 | output_asm_insn ("ld.w 96[sp], r8", operands); | |
3138 | output_asm_insn ("ld.w 92[sp], r9", operands); | |
3139 | output_asm_insn ("ld.w 88[sp], r11", operands); | |
3140 | output_asm_insn ("ld.w 84[sp], r12", operands); | |
3141 | output_asm_insn ("ld.w 80[sp], r13", operands); | |
3142 | output_asm_insn ("ld.w 76[sp], r14", operands); | |
3143 | output_asm_insn ("ld.w 72[sp], r15", operands); | |
3144 | output_asm_insn ("ld.w 68[sp], r16", operands); | |
3145 | output_asm_insn ("ld.w 64[sp], r17", operands); | |
3146 | output_asm_insn ("ld.w 60[sp], r18", operands); | |
3147 | output_asm_insn ("ld.w 56[sp], r19", operands); | |
3148 | output_asm_insn ("ld.w 52[sp], r20", operands); | |
3149 | output_asm_insn ("ld.w 48[sp], r21", operands); | |
3150 | output_asm_insn ("ld.w 44[sp], r22", operands); | |
3151 | output_asm_insn ("ld.w 40[sp], r23", operands); | |
3152 | output_asm_insn ("ld.w 36[sp], r24", operands); | |
3153 | output_asm_insn ("ld.w 32[sp], r25", operands); | |
3154 | output_asm_insn ("ld.w 28[sp], r26", operands); | |
3155 | output_asm_insn ("ld.w 24[sp], r27", operands); | |
3156 | output_asm_insn ("ld.w 20[sp], r28", operands); | |
3157 | output_asm_insn ("ld.w 16[sp], r29", operands); | |
2ec6cd51 | 3158 | } |
d9030ea4 N |
3159 | output_asm_insn ("addi 120, sp, sp", operands); |
3160 | return ""; | |
3161 | } | |
b4378319 | 3162 | [(set (attr "length") |
61c4c150 | 3163 | (if_then_else (match_test "TARGET_LONG_CALLS") |
b4378319 NC |
3164 | (const_int 4) |
3165 | (const_int 62) | |
03e32fb7 | 3166 | ))]) |
b4378319 NC |
3167 | |
3168 | (define_insn "_restore_all_interrupt" | |
1ec0eb08 JL |
3169 | [(unspec_volatile [(const_int 0)] 1) |
3170 | (clobber (reg:CC CC_REGNUM))] | |
be1d3f93 | 3171 | "TARGET_V850 && ! TARGET_LONG_CALLS" |
ae180d84 | 3172 | "jarl __restore_all_interrupt,r10" |
03e32fb7 | 3173 | [(set_attr "length" "4")]) |