111
|
1 ;; Machine description for FT32
|
131
|
2 ;; Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
111
|
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 "!TARGET_NODIV"
|
|
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 "!TARGET_NODIV"
|
|
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 "!TARGET_NODIV"
|
|
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 "!TARGET_NODIV"
|
|
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 (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
|
|
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 ""
|
131
|
780 {
|
|
781 if (TARGET_NOPM)
|
|
782 return \"ldk.l\t$cc,%l1\;ashl.l\t%2,%0,2\;add.l\t%2,%2,$cc\;ldi.l\t%2,%2,0\;jmpi\t%2\";
|
|
783 else
|
|
784 return \"ldk.l\t$cc,%l1\;ashl.l\t%2,%0,2\;add.l\t%2,%2,$cc\;lpmi.l\t%2,%2,0\;jmpi\t%2\";
|
|
785 })
|
111
|
786
|
|
787 ;; -------------------------------------------------------------------------
|
|
788 ;; Atomic exchange instruction
|
|
789 ;; -------------------------------------------------------------------------
|
|
790
|
|
791 (define_insn "atomic_exchangesi"
|
|
792 [(set (match_operand:SI 0 "register_operand" "=&r,r") ;; output
|
|
793 (match_operand:SI 1 "memory_operand" "+BW,A")) ;; memory
|
|
794 (set (match_dup 1)
|
|
795 (unspec:SI
|
|
796 [(match_operand:SI 2 "register_operand" "0,0") ;; input
|
|
797 (match_operand:SI 3 "const_int_operand")] ;; model
|
|
798 UNSPEC_XCHG))]
|
|
799 ""
|
|
800 "@
|
|
801 exi.l %0,%1
|
|
802 exa.l %0,%1")
|
|
803
|
|
804 (define_insn "atomic_exchangehi"
|
|
805 [(set (match_operand:HI 0 "register_operand" "=&r,r") ;; output
|
|
806 (match_operand:HI 1 "memory_operand" "+BW,A")) ;; memory
|
|
807 (set (match_dup 1)
|
|
808 (unspec:HI
|
|
809 [(match_operand:HI 2 "register_operand" "0,0") ;; input
|
|
810 (match_operand:HI 3 "const_int_operand")] ;; model
|
|
811 UNSPEC_XCHG))]
|
|
812 ""
|
|
813 "@
|
|
814 exi.s %0,%1
|
|
815 exa.s %0,%1")
|
|
816
|
|
817 (define_insn "atomic_exchangeqi"
|
|
818 [(set (match_operand:QI 0 "register_operand" "=&r,r") ;; output
|
|
819 (match_operand:QI 1 "memory_operand" "+BW,A")) ;; memory
|
|
820 (set (match_dup 1)
|
|
821 (unspec:QI
|
|
822 [(match_operand:QI 2 "register_operand" "0,0") ;; input
|
|
823 (match_operand:QI 3 "const_int_operand")] ;; model
|
|
824 UNSPEC_XCHG))]
|
|
825 ""
|
|
826 "@
|
|
827 exi.b %0,%1
|
|
828 exa.b %0,%1")
|
|
829
|
|
830 ;; -------------------------------------------------------------------------
|
|
831 ;; String instructions
|
|
832 ;; -------------------------------------------------------------------------
|
|
833
|
|
834 (define_insn "cmpstrsi"
|
|
835 [(set (match_operand:SI 0 "register_operand" "=r,r")
|
|
836 (compare:SI (match_operand:BLK 1 "memory_operand" "W,BW")
|
|
837 (match_operand:BLK 2 "memory_operand" "W,BW")))
|
|
838 (clobber (match_operand:SI 3))
|
|
839 ]
|
|
840 ""
|
|
841 "strcmp.%d3 %0,%b1,%b2"
|
|
842 )
|
|
843
|
|
844 (define_insn "movstr"
|
|
845 [(set (match_operand:BLK 1 "memory_operand" "=W")
|
|
846 (match_operand:BLK 2 "memory_operand" "W"))
|
|
847 (use (match_operand:SI 0))
|
|
848 (clobber (match_dup 0))
|
|
849 ]
|
|
850 "0"
|
|
851 "stpcpy %b1,%b2 # %0 %b1 %b2"
|
|
852 )
|
|
853
|
|
854 (define_insn "movmemsi"
|
|
855 [(set (match_operand:BLK 0 "memory_operand" "=W,BW")
|
|
856 (match_operand:BLK 1 "memory_operand" "W,BW"))
|
|
857 (use (match_operand:SI 2 "ft32_imm_operand" "KA,KA"))
|
|
858 (use (match_operand:SI 3))
|
|
859 ]
|
|
860 ""
|
|
861 "memcpy.%d3 %b0,%b1,%2 "
|
|
862 )
|
|
863
|
|
864 (define_insn "setmemsi"
|
|
865 [(set (match_operand:BLK 0 "memory_operand" "=BW") (unspec:BLK [
|
|
866 (use (match_operand:QI 2 "register_operand" "r"))
|
|
867 (use (match_operand:SI 1 "ft32_imm_operand" "KA"))
|
|
868 ] UNSPEC_SETMEM))
|
|
869 (use (match_operand:SI 3))
|
|
870 ]
|
|
871 ""
|
|
872 "memset.%d3 %b0,%2,%1"
|
|
873 )
|
|
874
|
|
875 (define_insn "strlensi"
|
|
876 [(set (match_operand:SI 0 "register_operand" "=r")
|
|
877 (unspec:SI [(match_operand:BLK 1 "memory_operand" "W")
|
|
878 (match_operand:QI 2 "const_int_operand" "")
|
|
879 (match_operand:SI 3 "ft32_rimm_operand" "")]
|
|
880 UNSPEC_STRLEN))]
|
|
881 ""
|
|
882 "strlen.%d3 %0,%b1 # %2 %3"
|
|
883 )
|
|
884
|
|
885 ;; -------------------------------------------------------------------------
|
|
886 ;; Prologue & Epilogue
|
|
887 ;; -------------------------------------------------------------------------
|
|
888
|
|
889 (define_expand "prologue"
|
|
890 [(clobber (const_int 0))]
|
|
891 ""
|
|
892 {
|
|
893 extern void ft32_expand_prologue();
|
|
894 ft32_expand_prologue ();
|
|
895 DONE;
|
|
896 })
|
|
897
|
|
898
|
|
899 (define_expand "epilogue"
|
|
900 [(return)]
|
|
901 ""
|
|
902 {
|
|
903 extern void ft32_expand_epilogue();
|
|
904 ft32_expand_epilogue ();
|
|
905 DONE;
|
|
906 })
|
|
907
|
|
908 (define_insn "link"
|
|
909 [
|
|
910 ;; (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
|
|
911 ;; (reg:SI FP_REG))
|
|
912 (set (match_operand:SI 0)
|
|
913 (reg:SI SP_REG))
|
|
914 (set (reg:SI SP_REG)
|
|
915 (plus:SI (reg:SI SP_REG)
|
|
916 (match_operand:SI 1 "general_operand" "L")))]
|
|
917 ""
|
|
918 "link %0,%m1"
|
|
919 )
|
|
920
|
|
921 (define_insn "unlink"
|
|
922 [(set (reg:SI FP_REG)
|
|
923 (mem:SI (reg:SI FP_REG)))
|
|
924 (set (reg:SI SP_REG)
|
|
925 (plus:SI (reg:SI FP_REG)
|
|
926 (const_int 4)))]
|
|
927 ""
|
|
928 "unlink $r29"
|
|
929 )
|
|
930
|
|
931 (define_insn "returner"
|
|
932 [(return)]
|
|
933 "reload_completed"
|
|
934 "return")
|
|
935
|
|
936 (define_insn "pretend_returner"
|
|
937 [(set (reg:SI SP_REG)
|
|
938 (plus:SI (reg:SI SP_REG)
|
|
939 (match_operand:SI 0)))
|
|
940 (return)]
|
|
941 "reload_completed"
|
|
942 "pop.l $cc\;add.l $sp,$sp,%0\;jmpi $cc")
|
|
943
|
|
944 (define_insn "returner24"
|
|
945 [
|
|
946 (set (reg:SI SP_REG)
|
|
947 (plus:SI
|
|
948 (reg:SI SP_REG)
|
|
949 (const_int 24)))
|
|
950 (return)]
|
|
951 ""
|
|
952 "jmp __epilog24")
|