]>
Commit | Line | Data |
---|---|---|
fef939d6 | 1 | ;; Machine description for FT32 |
cbe34bb5 | 2 | ;; Copyright (C) 2015-2017 Free Software Foundation, Inc. |
fef939d6 JB |
3 | ;; Contributed by FTDI <support@ftdi.com> |
4 | ||
5 | ;; This file is part of GCC. | |
6 | ||
7 | ;; GCC is free software; you can redistribute it and/or modify it | |
8 | ;; under the terms of the GNU General Public License as published | |
9 | ;; by the Free Software Foundation; either version 3, or (at your | |
10 | ;; option) any later version. | |
11 | ||
12 | ;; GCC is distributed in the hope that it will be useful, but WITHOUT | |
13 | ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 | ;; License for more details. | |
16 | ||
17 | ;; You should have received a copy of the GNU General Public License | |
18 | ;; along with GCC; see the file COPYING3. If not see | |
19 | ;; <http://www.gnu.org/licenses/>. | |
20 | ||
21 | ;; ------------------------------------------------------------------------- | |
22 | ;; FT32 specific constraints, predicates and attributes | |
23 | ;; ------------------------------------------------------------------------- | |
24 | ||
25 | (include "constraints.md") | |
26 | (include "predicates.md") | |
27 | ||
28 | (define_constants [ | |
29 | (FP_REG 0) | |
30 | (SP_REG 1) | |
31 | (CC_REG 35) | |
32 | ]) | |
33 | ||
34 | (define_c_enum "unspec" | |
35 | [UNSPEC_STRLEN | |
36 | UNSPEC_MOVMEM | |
37 | UNSPEC_SETMEM | |
38 | UNSPEC_STPCPY | |
39 | UNSPEC_INDEX_JMP | |
40 | UNSPEC_LPM | |
41 | UNSPEC_FMUL | |
42 | UNSPEC_FMULS | |
43 | UNSPEC_FMULSU | |
44 | UNSPEC_COPYSIGN | |
45 | UNSPEC_IDENTITY | |
46 | UNSPEC_INSERT_BITS | |
47 | UNSPEC_JMP_EPILOG | |
48 | UNSPEC_JMP_EPILOG24 | |
49 | UNSPEC_JMP_PROLOG | |
50 | UNSPEC_XCHG | |
51 | ]) | |
52 | ||
53 | ;; ------------------------------------------------------------------------- | |
54 | ;; nop instruction | |
55 | ;; ------------------------------------------------------------------------- | |
56 | ||
57 | (define_insn "nop" | |
58 | [(const_int 0)] | |
59 | "" | |
60 | "nop") | |
61 | ||
62 | ;; ------------------------------------------------------------------------- | |
63 | ;; Arithmetic instructions | |
64 | ;; ------------------------------------------------------------------------- | |
65 | ||
66 | (define_insn "addsi3" | |
67 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
68 | (plus:SI | |
69 | (match_operand:SI 1 "register_operand" "r,r") | |
70 | (match_operand:SI 2 "ft32_rimm_operand" "KA,r"))) | |
71 | ] | |
72 | "" | |
73 | "add.l %0,%1,%2") | |
74 | ||
75 | (define_insn "subsi3" | |
76 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
77 | (minus:SI | |
78 | (match_operand:SI 1 "register_operand" "r,r") | |
79 | (match_operand:SI 2 "ft32_rimm_operand" "KA,r")))] | |
80 | "" | |
81 | "sub.l %0,%1,%2") | |
82 | ||
83 | (define_insn "mulsi3" | |
84 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
85 | (mult:SI | |
86 | (match_operand:SI 1 "register_operand" "r,r") | |
87 | (match_operand:SI 2 "ft32_rimm_operand" "KA,r")))] | |
88 | "" | |
89 | "mul.l %0,%1,%2") | |
90 | ||
91 | (define_insn "umulsidi3" | |
92 | [(set (match_operand:DI 0 "register_operand" "=r,r") | |
93 | (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r")) | |
94 | (zero_extend:DI (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))) | |
95 | (clobber (reg:CC CC_REG))] | |
96 | "" | |
97 | "mul.l $cc,%1,%2\;muluh.l %h0,%1,%2\;move.l %0,$cc") | |
98 | ||
99 | (define_insn "divsi3" | |
100 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
101 | (div:SI | |
102 | (match_operand:SI 1 "register_operand" "r,r") | |
103 | (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))] | |
dc2e8995 | 104 | "!TARGET_NODIV" |
fef939d6 JB |
105 | "div.l %0,%1,%2") |
106 | ||
107 | (define_insn "modsi3" | |
108 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
109 | (mod:SI | |
110 | (match_operand:SI 1 "register_operand" "r,r") | |
111 | (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))] | |
dc2e8995 | 112 | "!TARGET_NODIV" |
fef939d6 JB |
113 | "mod.l %0,%1,%2") |
114 | ||
115 | (define_insn "udivsi3" | |
116 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
117 | (udiv:SI | |
118 | (match_operand:SI 1 "register_operand" "r,r") | |
119 | (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))] | |
dc2e8995 | 120 | "!TARGET_NODIV" |
fef939d6 JB |
121 | "udiv.l %0,%1,%2") |
122 | ||
123 | (define_insn "umodsi3" | |
124 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
125 | (umod:SI | |
126 | (match_operand:SI 1 "register_operand" "r,r") | |
127 | (match_operand:SI 2 "register_operand" "r,KA")))] | |
dc2e8995 | 128 | "!TARGET_NODIV" |
fef939d6 JB |
129 | "umod.l %0,%1,%2") |
130 | ||
131 | (define_insn "extvsi" | |
132 | [(set (match_operand:SI 0 "register_operand" "=r") | |
133 | (sign_extract:SI (match_operand:SI 1 "register_operand" "r") | |
134 | (match_operand:SI 2 "ft32_bwidth_operand" "b") | |
135 | (match_operand:SI 3 "const_int_operand" "i")))] | |
136 | "" | |
137 | "bexts.l %0,%1,((15 & %2) << 5) | (%3)") | |
138 | ||
139 | (define_insn "extzvsi" | |
140 | [(set (match_operand:SI 0 "register_operand" "=r") | |
141 | (zero_extract:SI (match_operand:SI 1 "register_operand" "r") | |
142 | (match_operand:SI 2 "ft32_bwidth_operand" "b") | |
143 | (match_operand:SI 3 "const_int_operand" "i")))] | |
144 | "" | |
145 | "bextu.l %0,%1,((15 & %2) << 5) | (%3)") | |
146 | ||
147 | (define_insn "insvsi" | |
148 | [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,r") | |
149 | (match_operand:SI 1 "ft32_bwidth_operand" "b,b") | |
150 | (match_operand:SI 2 "const_int_operand" "i,i")) | |
151 | (match_operand:SI 3 "general_operand" "r,O")) | |
152 | (clobber (match_scratch:SI 4 "=&r,r"))] | |
153 | "" | |
154 | { | |
155 | if (which_alternative == 0) | |
156 | { | |
157 | return \"ldl.l %4,%3,((%1&15)<<5)|(%2)\;bins.l %0,%0,%4\"; | |
158 | } | |
159 | else | |
160 | { | |
161 | if ((INTVAL(operands[3]) == 0) || (INTVAL(operands[1]) == 1)) | |
162 | return \"bins.l %0,%0,(%3<<9)|((%1&15)<<5)|(%2)\"; | |
163 | else | |
164 | return \"ldk.l %4,(%3<<10)|((%1&15)<<5)|(%2)\;bins.l %0,%0,%4\"; | |
165 | } | |
166 | }) | |
167 | ||
168 | ;; ------------------------------------------------------------------------- | |
169 | ;; Unary arithmetic instructions | |
170 | ;; ------------------------------------------------------------------------- | |
171 | ||
172 | (define_insn "one_cmplsi2" | |
173 | [(set (match_operand:SI 0 "register_operand" "=r") | |
174 | (not:SI (match_operand:SI 1 "register_operand" "r")))] | |
175 | "" | |
176 | "xor.l %0,%1,-1") | |
177 | ||
178 | ;; ------------------------------------------------------------------------- | |
179 | ;; Logical operators | |
180 | ;; ------------------------------------------------------------------------- | |
181 | ||
182 | (define_insn "andsi3" | |
183 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
184 | (and:SI (match_operand:SI 1 "register_operand" "r,r,r") | |
185 | (match_operand:SI 2 "general_operand" "r,x,KA")))] | |
186 | "" | |
187 | "@ | |
188 | and.l %0,%1,%2 | |
189 | bins.l %0,%1,%g2 | |
190 | and.l %0,%1,%2") | |
191 | ||
192 | (define_insn "andqi3" | |
193 | [(set (match_operand:QI 0 "register_operand" "=r,r,r") | |
194 | (and:QI (match_operand:QI 1 "register_operand" "r,r,r") | |
195 | (match_operand:QI 2 "general_operand" "r,x,KA")))] | |
196 | "" | |
197 | "@ | |
198 | and.b %0,%1,%2 | |
199 | bins.b %0,%1,%g2 | |
200 | and.b %0,%1,%2") | |
201 | ||
202 | (define_insn "xorsi3" | |
203 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
204 | (xor:SI (match_operand:SI 1 "register_operand" "r,r") | |
205 | (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))] | |
206 | "" | |
207 | { | |
208 | return "xor.l %0,%1,%2"; | |
209 | }) | |
210 | ||
211 | (define_insn "iorsi3" | |
212 | [(set (match_operand:SI 0 "register_operand" "=r,r,r") | |
213 | (ior:SI (match_operand:SI 1 "register_operand" "r,r,r") | |
214 | (match_operand:SI 2 "general_operand" "r,w,KA")))] | |
215 | "" | |
216 | "@ | |
217 | or.l %0,%1,%2 | |
218 | bins.l %0,%1,%f2 | |
219 | or.l %0,%1,%2") | |
220 | ||
221 | ;; ------------------------------------------------------------------------- | |
222 | ;; Shifters | |
223 | ;; ------------------------------------------------------------------------- | |
224 | ||
225 | (define_insn "ashlsi3" | |
226 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
227 | (ashift:SI (match_operand:SI 1 "register_operand" "r,r") | |
228 | (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))] | |
229 | "" | |
230 | { | |
231 | return "ashl.l %0,%1,%2"; | |
232 | }) | |
233 | ||
234 | (define_insn "ashrsi3" | |
235 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
236 | (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r") | |
237 | (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))] | |
238 | "" | |
239 | { | |
240 | return "ashr.l %0,%1,%2"; | |
241 | }) | |
242 | ||
243 | (define_insn "lshrsi3" | |
244 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
245 | (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r") | |
246 | (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))] | |
247 | "" | |
248 | { | |
249 | return "lshr.l %0,%1,%2"; | |
250 | }) | |
251 | ||
252 | ;; ------------------------------------------------------------------------- | |
253 | ;; Move instructions | |
254 | ;; ------------------------------------------------------------------------- | |
255 | ||
256 | ;; SImode | |
257 | ||
6d82151f JB |
258 | (define_insn "*sne" |
259 | [(set (match_operand:SI 0 "register_operand" "=r") | |
260 | (reg:SI CC_REG))] | |
261 | "" | |
262 | "bextu.l %0,$cc,32|0\;xor.l %0,%0,-1" | |
263 | ) | |
264 | ||
fef939d6 JB |
265 | ;; Push a register onto the stack |
266 | (define_insn "movsi_push" | |
267 | [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) | |
268 | (match_operand:SI 0 "register_operand" "r"))] | |
269 | "" | |
270 | "push.l %0") | |
271 | ||
272 | ;; Pop a register from the stack | |
273 | (define_insn "movsi_pop" | |
274 | [(set (match_operand:SI 0 "register_operand" "=r") | |
275 | (mem:SI (post_inc:SI (reg:SI SP_REG))))] | |
276 | "" | |
277 | "pop.l %0") | |
278 | ||
279 | (define_expand "movsi" | |
280 | [(set (match_operand:SI 0 "general_operand" "") | |
281 | (match_operand:SI 1 "general_operand" ""))] | |
282 | "" | |
283 | { | |
284 | /* If this is a store, force the value into a register. */ | |
285 | if (!(reload_in_progress || reload_completed)) | |
286 | { | |
287 | if (MEM_P (operands[0])) | |
288 | { | |
289 | operands[1] = force_reg (SImode, operands[1]); | |
290 | if (MEM_P (XEXP (operands[0], 0))) | |
291 | operands[0] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[0], 0))); | |
292 | } | |
293 | else | |
294 | { | |
295 | if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0))) | |
296 | operands[1] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[1], 0))); | |
297 | } | |
298 | /* | |
299 | if (MEM_P (operands[0])) { | |
300 | rtx o = XEXP (operands[0], 0); | |
301 | if (!REG_P(o) && | |
302 | !CONST_INT_P(o) && | |
303 | GET_CODE(o) != SYMBOL_REF && | |
304 | GET_CODE(o) != LABEL_REF) { | |
305 | operands[0] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[0], 0))); | |
306 | } | |
307 | } | |
308 | */ | |
309 | } | |
310 | }) | |
311 | ||
312 | (define_insn "*rtestsi" | |
313 | [(set (reg:SI CC_REG) | |
314 | (match_operand:SI 0 "register_operand" "r"))] | |
315 | "" | |
316 | "cmp.l %0,0" | |
317 | ) | |
318 | ||
319 | (define_insn "*rtestqi" | |
320 | [(set (reg:QI CC_REG) | |
321 | (match_operand:QI 0 "register_operand" "r"))] | |
322 | "" | |
323 | "cmp.b %0,0" | |
324 | ) | |
325 | ||
326 | (define_insn "*movsi" | |
327 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,BW,r,r,r,r,A,r,r") | |
328 | (match_operand:SI 1 "ft32_general_movsrc_operand" "r,r,BW,A,S,i,r,e,f"))] | |
329 | "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" | |
330 | "@ | |
331 | move.l %0,%1 | |
332 | sti.l %0,%1 | |
333 | ldi.l %0,%1 | |
334 | lda.l %0,%1 | |
335 | ldk.l %0,%1 | |
336 | *return ft32_load_immediate(operands[0], INTVAL(operands[1])); | |
337 | sta.l %0,%1 | |
338 | lpm.l %0,%1 | |
339 | lpmi.l %0,%1" | |
340 | ) | |
341 | ||
342 | (define_expand "movqi" | |
343 | [(set (match_operand:QI 0 "general_operand" "") | |
344 | (match_operand:QI 1 "general_operand" ""))] | |
345 | "" | |
346 | { | |
347 | /* If this is a store, force the value into a register. */ | |
348 | if (!(reload_in_progress || reload_completed)) | |
349 | { | |
350 | if (MEM_P (operands[0])) | |
351 | { | |
352 | operands[1] = force_reg (QImode, operands[1]); | |
353 | if (MEM_P (XEXP (operands[0], 0))) | |
354 | operands[0] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[0], 0))); | |
355 | } | |
356 | else | |
357 | { | |
358 | if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0))) | |
359 | operands[1] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[1], 0))); | |
360 | } | |
361 | if (MEM_P (operands[0]) && !REG_P(XEXP (operands[0], 0))) | |
362 | { | |
363 | operands[0] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[0], 0))); | |
364 | } | |
365 | } | |
366 | }) | |
367 | ||
368 | (define_insn "zero_extendqisi2" | |
369 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r") | |
370 | (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "BW,r,f")))] | |
371 | "" | |
372 | "@ | |
373 | ldi.b %0,%1 | |
374 | and.l %0,%1,255 | |
375 | lpmi.b %0,%1" | |
376 | ) | |
377 | ||
378 | (define_insn "extendqisi2" | |
379 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r") | |
380 | (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r")))] | |
381 | "" | |
382 | "bexts.l %0,%1,(8<<5)|0" | |
383 | ) | |
384 | ||
385 | (define_insn "zero_extendhisi2" | |
386 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r") | |
387 | (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "BW,r,f")))] | |
388 | "" | |
389 | "@ | |
390 | ldi.s %0,%1 | |
391 | bextu.l %0,%1,(0<<5)|0 | |
392 | lpmi.s %0,%1" | |
393 | ) | |
394 | ||
395 | (define_insn "extendhisi2" | |
396 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r") | |
397 | (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))] | |
398 | "" | |
399 | "bexts.l %0,%1,(0<<5)|0" | |
400 | ) | |
401 | ||
402 | (define_insn "*movqi" | |
403 | [(set (match_operand:QI 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r,r") | |
404 | (match_operand:QI 1 "ft32_general_movsrc_operand" "r,r,BW,A,r,I,e,f"))] | |
405 | "register_operand (operands[0], QImode) | |
406 | || register_operand (operands[1], QImode)" | |
407 | "@ | |
408 | move.b %0,%1 | |
409 | sti.b %0,%1 | |
410 | ldi.b %0,%1 | |
411 | lda.b %0,%1 | |
412 | sta.b %0,%1 | |
413 | ldk.b %0,%1 | |
414 | lpm.b %0,%1 | |
415 | lpmi.b %0,%1" | |
416 | ) | |
417 | ||
418 | (define_expand "movhi" | |
419 | [(set (match_operand:HI 0 "general_operand" "") | |
420 | (match_operand:HI 1 "general_operand" ""))] | |
421 | "" | |
422 | { | |
423 | /* If this is a store, force the value into a register. */ | |
424 | if (!(reload_in_progress || reload_completed)) | |
425 | { | |
426 | if (MEM_P (operands[0])) | |
427 | { | |
428 | operands[1] = force_reg (HImode, operands[1]); | |
429 | if (MEM_P (XEXP (operands[0], 0))) | |
430 | operands[0] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[0], 0))); | |
431 | } | |
432 | else | |
433 | { | |
434 | if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0))) | |
435 | operands[1] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[1], 0))); | |
436 | } | |
437 | if (MEM_P (operands[0])) | |
438 | { | |
439 | rtx o = XEXP (operands[0], 0); | |
440 | if (!REG_P(o) && | |
441 | !CONST_INT_P(o) && | |
442 | GET_CODE(o) != SYMBOL_REF && | |
443 | GET_CODE(o) != LABEL_REF) { | |
444 | operands[0] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[0], 0))); | |
445 | } | |
446 | } | |
447 | } | |
448 | }) | |
449 | ||
450 | (define_insn "*movhi" | |
451 | [(set (match_operand:HI 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r,r") | |
452 | (match_operand:HI 1 "ft32_general_movsrc_operand" "r,r,BW,A,r,I,e,f"))] | |
453 | "(register_operand (operands[0], HImode) | |
454 | || register_operand (operands[1], HImode))" | |
455 | "@ | |
456 | move.s %0,%1 | |
457 | sti.s %0,%1 | |
458 | ldi.s %0,%1 | |
459 | lda.s %0,%1 | |
460 | sta.s %0,%1 | |
461 | ldk.s %0,%1 | |
462 | lpm.s %0,%1 | |
463 | lpmi.s %0,%1" | |
464 | ) | |
465 | ||
466 | (define_expand "movsf" | |
467 | [(set (match_operand:SF 0 "general_operand" "") | |
468 | (match_operand:SF 1 "general_operand" ""))] | |
469 | "" | |
470 | { | |
471 | /* If this is a store, force the value into a register. */ | |
472 | if (MEM_P (operands[0])) | |
473 | operands[1] = force_reg (SFmode, operands[1]); | |
474 | if (CONST_DOUBLE_P(operands[1])) | |
475 | operands[1] = force_const_mem(SFmode, operands[1]); | |
476 | }) | |
477 | ||
478 | (define_insn "*movsf" | |
479 | [(set (match_operand:SF 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r") | |
480 | (match_operand:SF 1 "ft32_general_movsrc_operand" "r,r,BW,A,r,I,f"))] | |
481 | "(register_operand (operands[0], SFmode) | |
482 | || register_operand (operands[1], SFmode))" | |
483 | "@ | |
484 | move.l %0,%1 | |
485 | sti.l %0,%1 | |
486 | ldi.l %0,%1 | |
487 | lda.l %0,%1 | |
488 | sta.l %0,%1 | |
489 | ldk.l %0,%1 | |
490 | lpmi.l %0,%1" | |
491 | ) | |
492 | ||
493 | ;; ------------------------------------------------------------------------- | |
494 | ;; Compare instructions | |
495 | ;; ------------------------------------------------------------------------- | |
496 | ||
497 | (define_expand "cbranchsi4" | |
498 | [(set (reg:CC CC_REG) | |
499 | (compare:CC | |
500 | (match_operand:SI 1 "register_operand" "") | |
501 | (match_operand:SI 2 "ft32_rimm_operand" ""))) | |
502 | (set (pc) | |
503 | (if_then_else (match_operator 0 "comparison_operator" | |
504 | [(reg:CC CC_REG) (const_int 0)]) | |
505 | (label_ref (match_operand 3 "" "")) | |
506 | (pc)))] | |
507 | "" | |
508 | "") | |
509 | ||
510 | (define_insn "cmpsi" | |
511 | [(set (reg:CC CC_REG) | |
512 | (compare:CC | |
513 | (match_operand:SI 0 "register_operand" "r,r") | |
514 | (match_operand:SI 1 "ft32_rimm_operand" "r,KA")))] | |
515 | "" | |
516 | "cmp.l %0,%1") | |
517 | ||
518 | (define_insn "" | |
519 | [(set (pc) | |
520 | (if_then_else | |
521 | (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
522 | (const_int 1) | |
523 | (match_operand:SI 1 "const_int_operand" "i")) | |
524 | (const_int 0)) | |
525 | (label_ref (match_operand 2 "" "")) | |
526 | (pc))) | |
527 | (clobber (reg:CC CC_REG))] | |
528 | "" | |
529 | "btst.l %0,(1<<5)|%1\;jmpc nz,%l2") | |
530 | ||
531 | (define_insn "" | |
532 | [(set (pc) | |
533 | (if_then_else | |
534 | (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
535 | (const_int 1) | |
536 | (match_operand:SI 1 "const_int_operand" "i")) | |
537 | (const_int 0)) | |
538 | (label_ref (match_operand 2 "" "")) | |
539 | (pc))) | |
540 | (clobber (reg:CC CC_REG))] | |
541 | "" | |
542 | "btst.l %0,(1<<5)|%1\;jmpc z,%l2") | |
543 | ||
544 | (define_expand "cbranchqi4" | |
545 | [(set (reg:CC CC_REG) | |
546 | (compare:CC | |
547 | (match_operand:QI 1 "register_operand" "") | |
548 | (match_operand:QI 2 "ft32_rimm_operand" ""))) | |
549 | (set (pc) | |
550 | (if_then_else (match_operator 0 "comparison_operator" | |
551 | [(reg:CC CC_REG) (const_int 0)]) | |
552 | (label_ref (match_operand 3 "" "")) | |
553 | (pc)))] | |
554 | "" | |
555 | "") | |
556 | ||
557 | (define_insn "*cmpqi" | |
558 | [(set (reg:CC CC_REG) | |
559 | (compare:CC | |
560 | (match_operand:QI 0 "register_operand" "r,r") | |
561 | (match_operand:QI 1 "ft32_rimm_operand" "r,KA")))] | |
562 | "" | |
563 | "cmp.b %0,%1") | |
564 | ||
565 | ;; ------------------------------------------------------------------------- | |
566 | ;; Branch instructions | |
567 | ;; ------------------------------------------------------------------------- | |
568 | ||
569 | (define_code_iterator cond [ne eq lt ltu gt gtu ge le geu leu]) | |
570 | (define_code_attr CC [(ne "nz") (eq "z") (lt "lt") (ltu "b") | |
571 | (gt "gt") (gtu "a") (ge "gte") (le "lte") | |
572 | (geu "ae") (leu "be") ]) | |
573 | (define_code_attr rCC [(ne "z") (eq "nz") (lt "gte") (ltu "ae") | |
574 | (gt "lte") (gtu "be") (ge "lt") (le "gt") | |
575 | (geu "b") (leu "a") ]) | |
576 | ||
577 | (define_insn "*b<cond:code>" | |
578 | [(set (pc) | |
579 | (if_then_else (cond (reg:CC CC_REG) | |
580 | (const_int 0)) | |
581 | (label_ref (match_operand 0 "" "")) | |
582 | (pc)))] | |
583 | "" | |
584 | { | |
585 | return "jmpc <CC>,%l0"; | |
586 | } | |
587 | ) | |
588 | ||
589 | (define_expand "cstoresi4" | |
590 | [(set (reg:CC CC_REG) | |
591 | (compare:CC (match_operand:SI 2 "register_operand" "r,r") | |
592 | (match_operand:SI 3 "ft32_rimm_operand" "r,KA"))) | |
593 | (set (match_operand:SI 0 "register_operand") | |
594 | (match_operator:SI 1 "ordered_comparison_operator" | |
595 | [(reg:CC CC_REG) (const_int 0)]))] | |
596 | "" | |
597 | { | |
598 | rtx test; | |
599 | ||
600 | switch (GET_CODE (operands[1])) { | |
601 | case NE: | |
602 | case GEU: | |
603 | case LT: | |
604 | case LE: | |
605 | case LEU: | |
606 | test = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])), | |
607 | SImode, operands[2], operands[3]); | |
608 | emit_insn(gen_cstoresi4(operands[0], test, operands[2], operands[3])); | |
609 | emit_insn(gen_xorsi3(operands[0], operands[0], gen_int_mode(1, SImode))); | |
610 | DONE; | |
611 | default: | |
612 | ; | |
613 | } | |
614 | }) | |
615 | ||
616 | (define_insn "*seq" | |
617 | [(set (match_operand:SI 0 "register_operand" "=r") | |
618 | (eq:SI (reg CC_REG) (const_int 0)))] | |
619 | "" | |
620 | "bextu.l %0,$cc,32|0" | |
621 | ) | |
622 | ||
623 | (define_insn "*sltu" | |
624 | [(set (match_operand:SI 0 "register_operand" "=r") | |
625 | (ltu:SI (reg CC_REG) (const_int 0)))] | |
626 | "" | |
627 | "bextu.l %0,$cc,32|1" | |
628 | ) | |
629 | ||
630 | (define_insn "*sge" | |
631 | [(set (match_operand:SI 0 "register_operand" "=r") | |
632 | (ge:SI (reg CC_REG) (const_int 0)))] | |
633 | "" | |
634 | "bextu.l %0,$cc,32|4" | |
635 | ) | |
636 | ||
637 | (define_insn "*sgt" | |
638 | [(set (match_operand:SI 0 "register_operand" "=r") | |
639 | (gt:SI (reg CC_REG) (const_int 0)))] | |
640 | "" | |
641 | "bextu.l %0,$cc,32|5" | |
642 | ) | |
643 | ||
644 | (define_insn "*sgtu" | |
645 | [(set (match_operand:SI 0 "register_operand" "=r") | |
646 | (gtu:SI (reg CC_REG) (const_int 0)))] | |
647 | "" | |
648 | "bextu.l %0,$cc,32|6" | |
649 | ) | |
650 | ||
651 | ;; ------------------------------------------------------------------------- | |
652 | ;; Call and Jump instructions | |
653 | ;; ------------------------------------------------------------------------- | |
654 | ||
655 | (define_expand "call" | |
656 | [(call (match_operand:QI 0 "memory_operand" "") | |
657 | (match_operand 1 "general_operand" ""))] | |
658 | "" | |
659 | { | |
660 | gcc_assert (MEM_P (operands[0])); | |
661 | }) | |
662 | ||
663 | (define_insn "*call" | |
664 | [(call (mem:QI (match_operand:SI | |
665 | 0 "nonmemory_operand" "i,r")) | |
666 | (match_operand 1 "" ""))] | |
667 | "" | |
668 | "@ | |
669 | call %0 | |
670 | calli %0" | |
671 | ) | |
672 | ||
673 | (define_expand "call_value" | |
674 | [(set (match_operand 0 "" "") | |
675 | (call (match_operand:QI 1 "memory_operand" "") | |
676 | (match_operand 2 "" "")))] | |
677 | "" | |
678 | { | |
679 | gcc_assert (MEM_P (operands[1])); | |
680 | }) | |
681 | ||
682 | (define_insn "*call_value" | |
683 | [(set (match_operand 0 "register_operand" "=r") | |
684 | (call (mem:QI (match_operand:SI | |
685 | 1 "immediate_operand" "i")) | |
686 | (match_operand 2 "" "")))] | |
687 | "" | |
688 | "call %1" | |
689 | ) | |
690 | ||
691 | (define_insn "*call_value_indirect" | |
692 | [(set (match_operand 0 "register_operand" "=r") | |
693 | (call (mem:QI (match_operand:SI | |
694 | 1 "register_operand" "r")) | |
695 | (match_operand 2 "" "")))] | |
696 | "" | |
697 | "calli %1" | |
698 | ) | |
699 | ||
700 | (define_insn "indirect_jump" | |
701 | [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "r"))] | |
702 | "" | |
703 | "jmpi %0") | |
704 | ||
705 | (define_insn "jump" | |
706 | [(set (pc) | |
707 | (label_ref (match_operand 0 "" "")))] | |
708 | "" | |
709 | "jmp %l0" | |
710 | ) | |
711 | ||
712 | (define_insn "call_prolog" | |
713 | [(unspec:SI [(match_operand 0 "" "")] | |
714 | UNSPEC_JMP_PROLOG)] | |
715 | "" | |
716 | "call __prolog_%0" | |
717 | ) | |
718 | ||
719 | (define_insn "jump_epilog" | |
720 | [(unspec:SI [(match_operand 0 "" "")] | |
721 | UNSPEC_JMP_EPILOG)] | |
722 | "" | |
723 | "jmp __epilog_%0" | |
724 | ) | |
725 | ||
726 | (define_insn "jump_epilog24" | |
727 | [(unspec:SI [(match_operand 0 "" "")] | |
728 | UNSPEC_JMP_EPILOG24)] | |
729 | "" | |
730 | "jmp __epilog24_%0" | |
731 | ) | |
732 | ||
733 | ||
734 | ;; Subroutines of "casesi". | |
735 | ;; operand 0 is index | |
736 | ;; operand 1 is the minimum bound | |
737 | ;; operand 2 is the maximum bound - minimum bound + 1 | |
738 | ;; operand 3 is CODE_LABEL for the table; | |
739 | ;; operand 4 is the CODE_LABEL to go to if index out of range. | |
740 | ||
741 | (define_expand "casesi" | |
742 | [(match_operand:SI 0 "general_operand" "") | |
743 | (match_operand:SI 1 "const_int_operand" "") | |
744 | (match_operand:SI 2 "const_int_operand" "") | |
745 | (match_operand 3 "" "") | |
746 | (match_operand 4 "" "")] | |
747 | "" | |
748 | " | |
749 | { | |
750 | if (GET_CODE (operands[0]) != REG) | |
751 | operands[0] = force_reg (SImode, operands[0]); | |
752 | ||
753 | if (operands[1] != const0_rtx) | |
754 | { | |
755 | rtx index = gen_reg_rtx (SImode); | |
756 | rtx offset = gen_reg_rtx (SImode); | |
757 | ||
758 | emit_insn (gen_movsi (offset, operands[1])); | |
759 | emit_insn (gen_subsi3 (index, operands[0], offset)); | |
760 | operands[0] = index; | |
761 | } | |
762 | ||
763 | { | |
764 | rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]); | |
765 | emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4])); | |
766 | } | |
767 | ||
768 | emit_jump_insn (gen_casesi0 (operands[0], operands[3])); | |
769 | DONE; | |
770 | }") | |
771 | ||
772 | (define_insn "casesi0" | |
773 | [(set (pc) (mem:SI (plus:SI | |
774 | (mult:SI (match_operand:SI 0 "register_operand" "r") | |
775 | (const_int 4)) | |
776 | (label_ref (match_operand 1 "" ""))))) | |
777 | (clobber (match_scratch:SI 2 "=&r")) | |
778 | ] | |
779 | "" | |
780 | "ldk.l\t$cc,%l1\;ashl.l\t%2,%0,2\;add.l\t%2,%2,$cc\;jmpi\t%2" | |
781 | ) | |
782 | ||
783 | ;; ------------------------------------------------------------------------- | |
784 | ;; Atomic exchange instruction | |
785 | ;; ------------------------------------------------------------------------- | |
786 | ||
787 | (define_insn "atomic_exchangesi" | |
788 | [(set (match_operand:SI 0 "register_operand" "=&r,r") ;; output | |
789 | (match_operand:SI 1 "memory_operand" "+BW,A")) ;; memory | |
790 | (set (match_dup 1) | |
791 | (unspec:SI | |
792 | [(match_operand:SI 2 "register_operand" "0,0") ;; input | |
793 | (match_operand:SI 3 "const_int_operand")] ;; model | |
794 | UNSPEC_XCHG))] | |
795 | "" | |
796 | "@ | |
797 | exi.l %0,%1 | |
798 | exa.l %0,%1") | |
799 | ||
800 | (define_insn "atomic_exchangehi" | |
801 | [(set (match_operand:HI 0 "register_operand" "=&r,r") ;; output | |
802 | (match_operand:HI 1 "memory_operand" "+BW,A")) ;; memory | |
803 | (set (match_dup 1) | |
804 | (unspec:HI | |
805 | [(match_operand:HI 2 "register_operand" "0,0") ;; input | |
806 | (match_operand:HI 3 "const_int_operand")] ;; model | |
807 | UNSPEC_XCHG))] | |
808 | "" | |
809 | "@ | |
810 | exi.s %0,%1 | |
811 | exa.s %0,%1") | |
812 | ||
813 | (define_insn "atomic_exchangeqi" | |
814 | [(set (match_operand:QI 0 "register_operand" "=&r,r") ;; output | |
815 | (match_operand:QI 1 "memory_operand" "+BW,A")) ;; memory | |
816 | (set (match_dup 1) | |
817 | (unspec:QI | |
818 | [(match_operand:QI 2 "register_operand" "0,0") ;; input | |
819 | (match_operand:QI 3 "const_int_operand")] ;; model | |
820 | UNSPEC_XCHG))] | |
821 | "" | |
822 | "@ | |
823 | exi.b %0,%1 | |
824 | exa.b %0,%1") | |
825 | ||
826 | ;; ------------------------------------------------------------------------- | |
827 | ;; String instructions | |
828 | ;; ------------------------------------------------------------------------- | |
829 | ||
830 | (define_insn "cmpstrsi" | |
831 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
832 | (compare:SI (match_operand:BLK 1 "memory_operand" "W,BW") | |
833 | (match_operand:BLK 2 "memory_operand" "W,BW"))) | |
834 | (clobber (match_operand:SI 3)) | |
835 | ] | |
836 | "" | |
837 | "strcmp.%d3 %0,%b1,%b2" | |
838 | ) | |
839 | ||
840 | (define_insn "movstr" | |
841 | [(set (match_operand:BLK 1 "memory_operand" "=W") | |
842 | (match_operand:BLK 2 "memory_operand" "W")) | |
843 | (use (match_operand:SI 0)) | |
844 | (clobber (match_dup 0)) | |
845 | ] | |
846 | "0" | |
847 | "stpcpy %b1,%b2 # %0 %b1 %b2" | |
848 | ) | |
849 | ||
850 | (define_insn "movmemsi" | |
d3adfe5d JB |
851 | [(set (match_operand:BLK 0 "memory_operand" "=W,BW") |
852 | (match_operand:BLK 1 "memory_operand" "W,BW")) | |
853 | (use (match_operand:SI 2 "ft32_imm_operand" "KA,KA")) | |
fef939d6 JB |
854 | (use (match_operand:SI 3)) |
855 | ] | |
856 | "" | |
d3adfe5d | 857 | "memcpy.%d3 %b0,%b1,%2 " |
fef939d6 JB |
858 | ) |
859 | ||
860 | (define_insn "setmemsi" | |
d3adfe5d JB |
861 | [(set (match_operand:BLK 0 "memory_operand" "=BW") (unspec:BLK [ |
862 | (use (match_operand:QI 2 "register_operand" "r")) | |
863 | (use (match_operand:SI 1 "ft32_imm_operand" "KA")) | |
fef939d6 JB |
864 | ] UNSPEC_SETMEM)) |
865 | (use (match_operand:SI 3)) | |
866 | ] | |
867 | "" | |
868 | "memset.%d3 %b0,%2,%1" | |
869 | ) | |
870 | ||
871 | (define_insn "strlensi" | |
872 | [(set (match_operand:SI 0 "register_operand" "=r") | |
873 | (unspec:SI [(match_operand:BLK 1 "memory_operand" "W") | |
874 | (match_operand:QI 2 "const_int_operand" "") | |
875 | (match_operand:SI 3 "ft32_rimm_operand" "")] | |
876 | UNSPEC_STRLEN))] | |
877 | "" | |
878 | "strlen.%d3 %0,%b1 # %2 %3" | |
879 | ) | |
880 | ||
881 | ;; ------------------------------------------------------------------------- | |
882 | ;; Prologue & Epilogue | |
883 | ;; ------------------------------------------------------------------------- | |
884 | ||
885 | (define_expand "prologue" | |
886 | [(clobber (const_int 0))] | |
887 | "" | |
888 | { | |
889 | extern void ft32_expand_prologue(); | |
890 | ft32_expand_prologue (); | |
891 | DONE; | |
892 | }) | |
893 | ||
6d82151f | 894 | |
fef939d6 JB |
895 | (define_expand "epilogue" |
896 | [(return)] | |
897 | "" | |
898 | { | |
899 | extern void ft32_expand_epilogue(); | |
900 | ft32_expand_epilogue (); | |
901 | DONE; | |
902 | }) | |
903 | ||
904 | (define_insn "link" | |
905 | [ | |
906 | ;; (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) | |
907 | ;; (reg:SI FP_REG)) | |
908 | (set (match_operand:SI 0) | |
909 | (reg:SI SP_REG)) | |
910 | (set (reg:SI SP_REG) | |
911 | (plus:SI (reg:SI SP_REG) | |
912 | (match_operand:SI 1 "general_operand" "L")))] | |
913 | "" | |
914 | "link %0,%m1" | |
915 | ) | |
916 | ||
917 | (define_insn "unlink" | |
918 | [(set (reg:SI FP_REG) | |
919 | (mem:SI (reg:SI FP_REG))) | |
920 | (set (reg:SI SP_REG) | |
921 | (plus:SI (reg:SI FP_REG) | |
922 | (const_int 4)))] | |
923 | "" | |
924 | "unlink $r29" | |
925 | ) | |
926 | ||
927 | (define_insn "returner" | |
928 | [(return)] | |
929 | "reload_completed" | |
930 | "return") | |
931 | ||
d48ab010 JB |
932 | (define_insn "pretend_returner" |
933 | [(set (reg:SI SP_REG) | |
934 | (plus:SI (reg:SI SP_REG) | |
935 | (match_operand:SI 0))) | |
936 | (return)] | |
937 | "reload_completed" | |
938 | "pop.l $cc\;add.l $sp,$sp,%0\;jmpi $cc") | |
939 | ||
fef939d6 JB |
940 | (define_insn "returner24" |
941 | [ | |
942 | (set (reg:SI SP_REG) | |
943 | (plus:SI | |
944 | (reg:SI SP_REG) | |
945 | (const_int 24))) | |
946 | (return)] | |
947 | "" | |
948 | "jmp __epilog24") |