]>
Commit | Line | Data |
---|---|---|
fef939d6 JB |
1 | ;; Machine description for FT32 |
2 | ;; Copyright (C) 2015 Free Software Foundation, Inc. | |
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")))] | |
104 | "" | |
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")))] | |
112 | "" | |
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")))] | |
120 | "" | |
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")))] | |
128 | "" | |
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 | ||
258 | ;; Push a register onto the stack | |
259 | (define_insn "movsi_push" | |
260 | [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) | |
261 | (match_operand:SI 0 "register_operand" "r"))] | |
262 | "" | |
263 | "push.l %0") | |
264 | ||
265 | ;; Pop a register from the stack | |
266 | (define_insn "movsi_pop" | |
267 | [(set (match_operand:SI 0 "register_operand" "=r") | |
268 | (mem:SI (post_inc:SI (reg:SI SP_REG))))] | |
269 | "" | |
270 | "pop.l %0") | |
271 | ||
272 | (define_expand "movsi" | |
273 | [(set (match_operand:SI 0 "general_operand" "") | |
274 | (match_operand:SI 1 "general_operand" ""))] | |
275 | "" | |
276 | { | |
277 | /* If this is a store, force the value into a register. */ | |
278 | if (!(reload_in_progress || reload_completed)) | |
279 | { | |
280 | if (MEM_P (operands[0])) | |
281 | { | |
282 | operands[1] = force_reg (SImode, operands[1]); | |
283 | if (MEM_P (XEXP (operands[0], 0))) | |
284 | operands[0] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[0], 0))); | |
285 | } | |
286 | else | |
287 | { | |
288 | if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0))) | |
289 | operands[1] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[1], 0))); | |
290 | } | |
291 | /* | |
292 | if (MEM_P (operands[0])) { | |
293 | rtx o = XEXP (operands[0], 0); | |
294 | if (!REG_P(o) && | |
295 | !CONST_INT_P(o) && | |
296 | GET_CODE(o) != SYMBOL_REF && | |
297 | GET_CODE(o) != LABEL_REF) { | |
298 | operands[0] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[0], 0))); | |
299 | } | |
300 | } | |
301 | */ | |
302 | } | |
303 | }) | |
304 | ||
305 | (define_insn "*rtestsi" | |
306 | [(set (reg:SI CC_REG) | |
307 | (match_operand:SI 0 "register_operand" "r"))] | |
308 | "" | |
309 | "cmp.l %0,0" | |
310 | ) | |
311 | ||
312 | (define_insn "*rtestqi" | |
313 | [(set (reg:QI CC_REG) | |
314 | (match_operand:QI 0 "register_operand" "r"))] | |
315 | "" | |
316 | "cmp.b %0,0" | |
317 | ) | |
318 | ||
319 | (define_insn "*movsi" | |
320 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,BW,r,r,r,r,A,r,r") | |
321 | (match_operand:SI 1 "ft32_general_movsrc_operand" "r,r,BW,A,S,i,r,e,f"))] | |
322 | "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" | |
323 | "@ | |
324 | move.l %0,%1 | |
325 | sti.l %0,%1 | |
326 | ldi.l %0,%1 | |
327 | lda.l %0,%1 | |
328 | ldk.l %0,%1 | |
329 | *return ft32_load_immediate(operands[0], INTVAL(operands[1])); | |
330 | sta.l %0,%1 | |
331 | lpm.l %0,%1 | |
332 | lpmi.l %0,%1" | |
333 | ) | |
334 | ||
335 | (define_expand "movqi" | |
336 | [(set (match_operand:QI 0 "general_operand" "") | |
337 | (match_operand:QI 1 "general_operand" ""))] | |
338 | "" | |
339 | { | |
340 | /* If this is a store, force the value into a register. */ | |
341 | if (!(reload_in_progress || reload_completed)) | |
342 | { | |
343 | if (MEM_P (operands[0])) | |
344 | { | |
345 | operands[1] = force_reg (QImode, operands[1]); | |
346 | if (MEM_P (XEXP (operands[0], 0))) | |
347 | operands[0] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[0], 0))); | |
348 | } | |
349 | else | |
350 | { | |
351 | if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0))) | |
352 | operands[1] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[1], 0))); | |
353 | } | |
354 | if (MEM_P (operands[0]) && !REG_P(XEXP (operands[0], 0))) | |
355 | { | |
356 | operands[0] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[0], 0))); | |
357 | } | |
358 | } | |
359 | }) | |
360 | ||
361 | (define_insn "zero_extendqisi2" | |
362 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r") | |
363 | (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "BW,r,f")))] | |
364 | "" | |
365 | "@ | |
366 | ldi.b %0,%1 | |
367 | and.l %0,%1,255 | |
368 | lpmi.b %0,%1" | |
369 | ) | |
370 | ||
371 | (define_insn "extendqisi2" | |
372 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r") | |
373 | (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r")))] | |
374 | "" | |
375 | "bexts.l %0,%1,(8<<5)|0" | |
376 | ) | |
377 | ||
378 | (define_insn "zero_extendhisi2" | |
379 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r") | |
380 | (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "BW,r,f")))] | |
381 | "" | |
382 | "@ | |
383 | ldi.s %0,%1 | |
384 | bextu.l %0,%1,(0<<5)|0 | |
385 | lpmi.s %0,%1" | |
386 | ) | |
387 | ||
388 | (define_insn "extendhisi2" | |
389 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r") | |
390 | (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))] | |
391 | "" | |
392 | "bexts.l %0,%1,(0<<5)|0" | |
393 | ) | |
394 | ||
395 | (define_insn "*movqi" | |
396 | [(set (match_operand:QI 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r,r") | |
397 | (match_operand:QI 1 "ft32_general_movsrc_operand" "r,r,BW,A,r,I,e,f"))] | |
398 | "register_operand (operands[0], QImode) | |
399 | || register_operand (operands[1], QImode)" | |
400 | "@ | |
401 | move.b %0,%1 | |
402 | sti.b %0,%1 | |
403 | ldi.b %0,%1 | |
404 | lda.b %0,%1 | |
405 | sta.b %0,%1 | |
406 | ldk.b %0,%1 | |
407 | lpm.b %0,%1 | |
408 | lpmi.b %0,%1" | |
409 | ) | |
410 | ||
411 | (define_expand "movhi" | |
412 | [(set (match_operand:HI 0 "general_operand" "") | |
413 | (match_operand:HI 1 "general_operand" ""))] | |
414 | "" | |
415 | { | |
416 | /* If this is a store, force the value into a register. */ | |
417 | if (!(reload_in_progress || reload_completed)) | |
418 | { | |
419 | if (MEM_P (operands[0])) | |
420 | { | |
421 | operands[1] = force_reg (HImode, operands[1]); | |
422 | if (MEM_P (XEXP (operands[0], 0))) | |
423 | operands[0] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[0], 0))); | |
424 | } | |
425 | else | |
426 | { | |
427 | if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0))) | |
428 | operands[1] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[1], 0))); | |
429 | } | |
430 | if (MEM_P (operands[0])) | |
431 | { | |
432 | rtx o = XEXP (operands[0], 0); | |
433 | if (!REG_P(o) && | |
434 | !CONST_INT_P(o) && | |
435 | GET_CODE(o) != SYMBOL_REF && | |
436 | GET_CODE(o) != LABEL_REF) { | |
437 | operands[0] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[0], 0))); | |
438 | } | |
439 | } | |
440 | } | |
441 | }) | |
442 | ||
443 | (define_insn "*movhi" | |
444 | [(set (match_operand:HI 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r,r") | |
445 | (match_operand:HI 1 "ft32_general_movsrc_operand" "r,r,BW,A,r,I,e,f"))] | |
446 | "(register_operand (operands[0], HImode) | |
447 | || register_operand (operands[1], HImode))" | |
448 | "@ | |
449 | move.s %0,%1 | |
450 | sti.s %0,%1 | |
451 | ldi.s %0,%1 | |
452 | lda.s %0,%1 | |
453 | sta.s %0,%1 | |
454 | ldk.s %0,%1 | |
455 | lpm.s %0,%1 | |
456 | lpmi.s %0,%1" | |
457 | ) | |
458 | ||
459 | (define_expand "movsf" | |
460 | [(set (match_operand:SF 0 "general_operand" "") | |
461 | (match_operand:SF 1 "general_operand" ""))] | |
462 | "" | |
463 | { | |
464 | /* If this is a store, force the value into a register. */ | |
465 | if (MEM_P (operands[0])) | |
466 | operands[1] = force_reg (SFmode, operands[1]); | |
467 | if (CONST_DOUBLE_P(operands[1])) | |
468 | operands[1] = force_const_mem(SFmode, operands[1]); | |
469 | }) | |
470 | ||
471 | (define_insn "*movsf" | |
472 | [(set (match_operand:SF 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r") | |
473 | (match_operand:SF 1 "ft32_general_movsrc_operand" "r,r,BW,A,r,I,f"))] | |
474 | "(register_operand (operands[0], SFmode) | |
475 | || register_operand (operands[1], SFmode))" | |
476 | "@ | |
477 | move.l %0,%1 | |
478 | sti.l %0,%1 | |
479 | ldi.l %0,%1 | |
480 | lda.l %0,%1 | |
481 | sta.l %0,%1 | |
482 | ldk.l %0,%1 | |
483 | lpmi.l %0,%1" | |
484 | ) | |
485 | ||
486 | ;; ------------------------------------------------------------------------- | |
487 | ;; Compare instructions | |
488 | ;; ------------------------------------------------------------------------- | |
489 | ||
490 | (define_expand "cbranchsi4" | |
491 | [(set (reg:CC CC_REG) | |
492 | (compare:CC | |
493 | (match_operand:SI 1 "register_operand" "") | |
494 | (match_operand:SI 2 "ft32_rimm_operand" ""))) | |
495 | (set (pc) | |
496 | (if_then_else (match_operator 0 "comparison_operator" | |
497 | [(reg:CC CC_REG) (const_int 0)]) | |
498 | (label_ref (match_operand 3 "" "")) | |
499 | (pc)))] | |
500 | "" | |
501 | "") | |
502 | ||
503 | (define_insn "cmpsi" | |
504 | [(set (reg:CC CC_REG) | |
505 | (compare:CC | |
506 | (match_operand:SI 0 "register_operand" "r,r") | |
507 | (match_operand:SI 1 "ft32_rimm_operand" "r,KA")))] | |
508 | "" | |
509 | "cmp.l %0,%1") | |
510 | ||
511 | (define_insn "" | |
512 | [(set (pc) | |
513 | (if_then_else | |
514 | (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
515 | (const_int 1) | |
516 | (match_operand:SI 1 "const_int_operand" "i")) | |
517 | (const_int 0)) | |
518 | (label_ref (match_operand 2 "" "")) | |
519 | (pc))) | |
520 | (clobber (reg:CC CC_REG))] | |
521 | "" | |
522 | "btst.l %0,(1<<5)|%1\;jmpc nz,%l2") | |
523 | ||
524 | (define_insn "" | |
525 | [(set (pc) | |
526 | (if_then_else | |
527 | (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") | |
528 | (const_int 1) | |
529 | (match_operand:SI 1 "const_int_operand" "i")) | |
530 | (const_int 0)) | |
531 | (label_ref (match_operand 2 "" "")) | |
532 | (pc))) | |
533 | (clobber (reg:CC CC_REG))] | |
534 | "" | |
535 | "btst.l %0,(1<<5)|%1\;jmpc z,%l2") | |
536 | ||
537 | (define_expand "cbranchqi4" | |
538 | [(set (reg:CC CC_REG) | |
539 | (compare:CC | |
540 | (match_operand:QI 1 "register_operand" "") | |
541 | (match_operand:QI 2 "ft32_rimm_operand" ""))) | |
542 | (set (pc) | |
543 | (if_then_else (match_operator 0 "comparison_operator" | |
544 | [(reg:CC CC_REG) (const_int 0)]) | |
545 | (label_ref (match_operand 3 "" "")) | |
546 | (pc)))] | |
547 | "" | |
548 | "") | |
549 | ||
550 | (define_insn "*cmpqi" | |
551 | [(set (reg:CC CC_REG) | |
552 | (compare:CC | |
553 | (match_operand:QI 0 "register_operand" "r,r") | |
554 | (match_operand:QI 1 "ft32_rimm_operand" "r,KA")))] | |
555 | "" | |
556 | "cmp.b %0,%1") | |
557 | ||
558 | ;; ------------------------------------------------------------------------- | |
559 | ;; Branch instructions | |
560 | ;; ------------------------------------------------------------------------- | |
561 | ||
562 | (define_code_iterator cond [ne eq lt ltu gt gtu ge le geu leu]) | |
563 | (define_code_attr CC [(ne "nz") (eq "z") (lt "lt") (ltu "b") | |
564 | (gt "gt") (gtu "a") (ge "gte") (le "lte") | |
565 | (geu "ae") (leu "be") ]) | |
566 | (define_code_attr rCC [(ne "z") (eq "nz") (lt "gte") (ltu "ae") | |
567 | (gt "lte") (gtu "be") (ge "lt") (le "gt") | |
568 | (geu "b") (leu "a") ]) | |
569 | ||
570 | (define_insn "*b<cond:code>" | |
571 | [(set (pc) | |
572 | (if_then_else (cond (reg:CC CC_REG) | |
573 | (const_int 0)) | |
574 | (label_ref (match_operand 0 "" "")) | |
575 | (pc)))] | |
576 | "" | |
577 | { | |
578 | return "jmpc <CC>,%l0"; | |
579 | } | |
580 | ) | |
581 | ||
582 | (define_expand "cstoresi4" | |
583 | [(set (reg:CC CC_REG) | |
584 | (compare:CC (match_operand:SI 2 "register_operand" "r,r") | |
585 | (match_operand:SI 3 "ft32_rimm_operand" "r,KA"))) | |
586 | (set (match_operand:SI 0 "register_operand") | |
587 | (match_operator:SI 1 "ordered_comparison_operator" | |
588 | [(reg:CC CC_REG) (const_int 0)]))] | |
589 | "" | |
590 | { | |
591 | rtx test; | |
592 | ||
593 | switch (GET_CODE (operands[1])) { | |
594 | case NE: | |
595 | case GEU: | |
596 | case LT: | |
597 | case LE: | |
598 | case LEU: | |
599 | test = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])), | |
600 | SImode, operands[2], operands[3]); | |
601 | emit_insn(gen_cstoresi4(operands[0], test, operands[2], operands[3])); | |
602 | emit_insn(gen_xorsi3(operands[0], operands[0], gen_int_mode(1, SImode))); | |
603 | DONE; | |
604 | default: | |
605 | ; | |
606 | } | |
607 | }) | |
608 | ||
609 | (define_insn "*seq" | |
610 | [(set (match_operand:SI 0 "register_operand" "=r") | |
611 | (eq:SI (reg CC_REG) (const_int 0)))] | |
612 | "" | |
613 | "bextu.l %0,$cc,32|0" | |
614 | ) | |
615 | ||
616 | (define_insn "*sltu" | |
617 | [(set (match_operand:SI 0 "register_operand" "=r") | |
618 | (ltu:SI (reg CC_REG) (const_int 0)))] | |
619 | "" | |
620 | "bextu.l %0,$cc,32|1" | |
621 | ) | |
622 | ||
623 | (define_insn "*sge" | |
624 | [(set (match_operand:SI 0 "register_operand" "=r") | |
625 | (ge:SI (reg CC_REG) (const_int 0)))] | |
626 | "" | |
627 | "bextu.l %0,$cc,32|4" | |
628 | ) | |
629 | ||
630 | (define_insn "*sgt" | |
631 | [(set (match_operand:SI 0 "register_operand" "=r") | |
632 | (gt:SI (reg CC_REG) (const_int 0)))] | |
633 | "" | |
634 | "bextu.l %0,$cc,32|5" | |
635 | ) | |
636 | ||
637 | (define_insn "*sgtu" | |
638 | [(set (match_operand:SI 0 "register_operand" "=r") | |
639 | (gtu:SI (reg CC_REG) (const_int 0)))] | |
640 | "" | |
641 | "bextu.l %0,$cc,32|6" | |
642 | ) | |
643 | ||
644 | ;; ------------------------------------------------------------------------- | |
645 | ;; Call and Jump instructions | |
646 | ;; ------------------------------------------------------------------------- | |
647 | ||
648 | (define_expand "call" | |
649 | [(call (match_operand:QI 0 "memory_operand" "") | |
650 | (match_operand 1 "general_operand" ""))] | |
651 | "" | |
652 | { | |
653 | gcc_assert (MEM_P (operands[0])); | |
654 | }) | |
655 | ||
656 | (define_insn "*call" | |
657 | [(call (mem:QI (match_operand:SI | |
658 | 0 "nonmemory_operand" "i,r")) | |
659 | (match_operand 1 "" ""))] | |
660 | "" | |
661 | "@ | |
662 | call %0 | |
663 | calli %0" | |
664 | ) | |
665 | ||
666 | (define_expand "call_value" | |
667 | [(set (match_operand 0 "" "") | |
668 | (call (match_operand:QI 1 "memory_operand" "") | |
669 | (match_operand 2 "" "")))] | |
670 | "" | |
671 | { | |
672 | gcc_assert (MEM_P (operands[1])); | |
673 | }) | |
674 | ||
675 | (define_insn "*call_value" | |
676 | [(set (match_operand 0 "register_operand" "=r") | |
677 | (call (mem:QI (match_operand:SI | |
678 | 1 "immediate_operand" "i")) | |
679 | (match_operand 2 "" "")))] | |
680 | "" | |
681 | "call %1" | |
682 | ) | |
683 | ||
684 | (define_insn "*call_value_indirect" | |
685 | [(set (match_operand 0 "register_operand" "=r") | |
686 | (call (mem:QI (match_operand:SI | |
687 | 1 "register_operand" "r")) | |
688 | (match_operand 2 "" "")))] | |
689 | "" | |
690 | "calli %1" | |
691 | ) | |
692 | ||
693 | (define_insn "indirect_jump" | |
694 | [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "r"))] | |
695 | "" | |
696 | "jmpi %0") | |
697 | ||
698 | (define_insn "jump" | |
699 | [(set (pc) | |
700 | (label_ref (match_operand 0 "" "")))] | |
701 | "" | |
702 | "jmp %l0" | |
703 | ) | |
704 | ||
705 | (define_insn "call_prolog" | |
706 | [(unspec:SI [(match_operand 0 "" "")] | |
707 | UNSPEC_JMP_PROLOG)] | |
708 | "" | |
709 | "call __prolog_%0" | |
710 | ) | |
711 | ||
712 | (define_insn "jump_epilog" | |
713 | [(unspec:SI [(match_operand 0 "" "")] | |
714 | UNSPEC_JMP_EPILOG)] | |
715 | "" | |
716 | "jmp __epilog_%0" | |
717 | ) | |
718 | ||
719 | (define_insn "jump_epilog24" | |
720 | [(unspec:SI [(match_operand 0 "" "")] | |
721 | UNSPEC_JMP_EPILOG24)] | |
722 | "" | |
723 | "jmp __epilog24_%0" | |
724 | ) | |
725 | ||
726 | ||
727 | ;; Subroutines of "casesi". | |
728 | ;; operand 0 is index | |
729 | ;; operand 1 is the minimum bound | |
730 | ;; operand 2 is the maximum bound - minimum bound + 1 | |
731 | ;; operand 3 is CODE_LABEL for the table; | |
732 | ;; operand 4 is the CODE_LABEL to go to if index out of range. | |
733 | ||
734 | (define_expand "casesi" | |
735 | [(match_operand:SI 0 "general_operand" "") | |
736 | (match_operand:SI 1 "const_int_operand" "") | |
737 | (match_operand:SI 2 "const_int_operand" "") | |
738 | (match_operand 3 "" "") | |
739 | (match_operand 4 "" "")] | |
740 | "" | |
741 | " | |
742 | { | |
743 | if (GET_CODE (operands[0]) != REG) | |
744 | operands[0] = force_reg (SImode, operands[0]); | |
745 | ||
746 | if (operands[1] != const0_rtx) | |
747 | { | |
748 | rtx index = gen_reg_rtx (SImode); | |
749 | rtx offset = gen_reg_rtx (SImode); | |
750 | ||
751 | emit_insn (gen_movsi (offset, operands[1])); | |
752 | emit_insn (gen_subsi3 (index, operands[0], offset)); | |
753 | operands[0] = index; | |
754 | } | |
755 | ||
756 | { | |
757 | rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]); | |
758 | emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4])); | |
759 | } | |
760 | ||
761 | emit_jump_insn (gen_casesi0 (operands[0], operands[3])); | |
762 | DONE; | |
763 | }") | |
764 | ||
765 | (define_insn "casesi0" | |
766 | [(set (pc) (mem:SI (plus:SI | |
767 | (mult:SI (match_operand:SI 0 "register_operand" "r") | |
768 | (const_int 4)) | |
769 | (label_ref (match_operand 1 "" ""))))) | |
770 | (clobber (match_scratch:SI 2 "=&r")) | |
771 | ] | |
772 | "" | |
773 | "ldk.l\t$cc,%l1\;ashl.l\t%2,%0,2\;add.l\t%2,%2,$cc\;jmpi\t%2" | |
774 | ) | |
775 | ||
776 | ;; ------------------------------------------------------------------------- | |
777 | ;; Atomic exchange instruction | |
778 | ;; ------------------------------------------------------------------------- | |
779 | ||
780 | (define_insn "atomic_exchangesi" | |
781 | [(set (match_operand:SI 0 "register_operand" "=&r,r") ;; output | |
782 | (match_operand:SI 1 "memory_operand" "+BW,A")) ;; memory | |
783 | (set (match_dup 1) | |
784 | (unspec:SI | |
785 | [(match_operand:SI 2 "register_operand" "0,0") ;; input | |
786 | (match_operand:SI 3 "const_int_operand")] ;; model | |
787 | UNSPEC_XCHG))] | |
788 | "" | |
789 | "@ | |
790 | exi.l %0,%1 | |
791 | exa.l %0,%1") | |
792 | ||
793 | (define_insn "atomic_exchangehi" | |
794 | [(set (match_operand:HI 0 "register_operand" "=&r,r") ;; output | |
795 | (match_operand:HI 1 "memory_operand" "+BW,A")) ;; memory | |
796 | (set (match_dup 1) | |
797 | (unspec:HI | |
798 | [(match_operand:HI 2 "register_operand" "0,0") ;; input | |
799 | (match_operand:HI 3 "const_int_operand")] ;; model | |
800 | UNSPEC_XCHG))] | |
801 | "" | |
802 | "@ | |
803 | exi.s %0,%1 | |
804 | exa.s %0,%1") | |
805 | ||
806 | (define_insn "atomic_exchangeqi" | |
807 | [(set (match_operand:QI 0 "register_operand" "=&r,r") ;; output | |
808 | (match_operand:QI 1 "memory_operand" "+BW,A")) ;; memory | |
809 | (set (match_dup 1) | |
810 | (unspec:QI | |
811 | [(match_operand:QI 2 "register_operand" "0,0") ;; input | |
812 | (match_operand:QI 3 "const_int_operand")] ;; model | |
813 | UNSPEC_XCHG))] | |
814 | "" | |
815 | "@ | |
816 | exi.b %0,%1 | |
817 | exa.b %0,%1") | |
818 | ||
819 | ;; ------------------------------------------------------------------------- | |
820 | ;; String instructions | |
821 | ;; ------------------------------------------------------------------------- | |
822 | ||
823 | (define_insn "cmpstrsi" | |
824 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
825 | (compare:SI (match_operand:BLK 1 "memory_operand" "W,BW") | |
826 | (match_operand:BLK 2 "memory_operand" "W,BW"))) | |
827 | (clobber (match_operand:SI 3)) | |
828 | ] | |
829 | "" | |
830 | "strcmp.%d3 %0,%b1,%b2" | |
831 | ) | |
832 | ||
833 | (define_insn "movstr" | |
834 | [(set (match_operand:BLK 1 "memory_operand" "=W") | |
835 | (match_operand:BLK 2 "memory_operand" "W")) | |
836 | (use (match_operand:SI 0)) | |
837 | (clobber (match_dup 0)) | |
838 | ] | |
839 | "0" | |
840 | "stpcpy %b1,%b2 # %0 %b1 %b2" | |
841 | ) | |
842 | ||
843 | (define_insn "movmemsi" | |
844 | [(set (match_operand:BLK 0 "memory_operand" "=W,W,BW") | |
845 | (match_operand:BLK 1 "memory_operand" "W,W,BW")) | |
846 | (use (match_operand:SI 2 "ft32_rimm_operand" "r,KA,rKA")) | |
847 | (use (match_operand:SI 3)) | |
848 | ] | |
849 | "" | |
850 | "memcpy.%d3 %b0,%b1,%2 # %3!" | |
851 | ) | |
852 | ||
853 | (define_insn "setmemsi" | |
854 | [(set (match_operand:BLK 0 "memory_operand" "=BW,BW") (unspec:BLK [ | |
855 | (use (match_operand:QI 2 "register_operand" "r,r")) | |
856 | (use (match_operand:SI 1 "ft32_rimm_operand" "r,KA")) | |
857 | ] UNSPEC_SETMEM)) | |
858 | (use (match_operand:SI 3)) | |
859 | ] | |
860 | "" | |
861 | "memset.%d3 %b0,%2,%1" | |
862 | ) | |
863 | ||
864 | (define_insn "strlensi" | |
865 | [(set (match_operand:SI 0 "register_operand" "=r") | |
866 | (unspec:SI [(match_operand:BLK 1 "memory_operand" "W") | |
867 | (match_operand:QI 2 "const_int_operand" "") | |
868 | (match_operand:SI 3 "ft32_rimm_operand" "")] | |
869 | UNSPEC_STRLEN))] | |
870 | "" | |
871 | "strlen.%d3 %0,%b1 # %2 %3" | |
872 | ) | |
873 | ||
874 | ;; ------------------------------------------------------------------------- | |
875 | ;; Prologue & Epilogue | |
876 | ;; ------------------------------------------------------------------------- | |
877 | ||
878 | (define_expand "prologue" | |
879 | [(clobber (const_int 0))] | |
880 | "" | |
881 | { | |
882 | extern void ft32_expand_prologue(); | |
883 | ft32_expand_prologue (); | |
884 | DONE; | |
885 | }) | |
886 | ||
887 | (define_expand "epilogue" | |
888 | [(return)] | |
889 | "" | |
890 | { | |
891 | extern void ft32_expand_epilogue(); | |
892 | ft32_expand_epilogue (); | |
893 | DONE; | |
894 | }) | |
895 | ||
896 | (define_insn "link" | |
897 | [ | |
898 | ;; (set (mem:SI (pre_dec:SI (reg:SI SP_REG))) | |
899 | ;; (reg:SI FP_REG)) | |
900 | (set (match_operand:SI 0) | |
901 | (reg:SI SP_REG)) | |
902 | (set (reg:SI SP_REG) | |
903 | (plus:SI (reg:SI SP_REG) | |
904 | (match_operand:SI 1 "general_operand" "L")))] | |
905 | "" | |
906 | "link %0,%m1" | |
907 | ) | |
908 | ||
909 | (define_insn "unlink" | |
910 | [(set (reg:SI FP_REG) | |
911 | (mem:SI (reg:SI FP_REG))) | |
912 | (set (reg:SI SP_REG) | |
913 | (plus:SI (reg:SI FP_REG) | |
914 | (const_int 4)))] | |
915 | "" | |
916 | "unlink $r29" | |
917 | ) | |
918 | ||
919 | (define_insn "returner" | |
920 | [(return)] | |
921 | "reload_completed" | |
922 | "return") | |
923 | ||
924 | (define_insn "returner24" | |
925 | [ | |
926 | (set (reg:SI SP_REG) | |
927 | (plus:SI | |
928 | (reg:SI SP_REG) | |
929 | (const_int 24))) | |
930 | (return)] | |
931 | "" | |
932 | "jmp __epilog24") |