comparison gcc/config/mmix/mmix.md @ 0:a06113de4d67

first commit
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 14:47:48 +0900
parents
children 77e2b8dfacca
comparison
equal deleted inserted replaced
-1:000000000000 0:a06113de4d67
1 ;; GCC machine description for MMIX
2 ;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Hans-Peter Nilsson (hp@bitrange.com)
5
6 ;; This file is part of GCC.
7
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
11 ;; any later version.
12
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
21
22 ;; The original PO technology requires these to be ordered by speed,
23 ;; so that assigner will pick the fastest.
24
25 ;; See file "rtl.def" for documentation on define_insn, match_*, et al.
26
27 ;; Uses of UNSPEC in this file:
28 ;; UNSPEC_VOLATILE:
29 ;;
30 ;; 0 sync_icache (sync icache before trampoline jump)
31 ;; 1 nonlocal_goto_receiver
32 ;;
33
34 ;; The order of insns is as in Node: Standard Names, with smaller modes
35 ;; before bigger modes.
36
37 (define_constants
38 [(MMIX_rJ_REGNUM 259)
39 (MMIX_rR_REGNUM 260)
40 (MMIX_fp_rO_OFFSET -24)]
41 )
42
43 ;; Operand and operator predicates.
44
45 (include "predicates.md")
46
47 ;; FIXME: Can we remove the reg-to-reg for smaller modes? Shouldn't they
48 ;; be synthesized ok?
49 (define_insn "movqi"
50 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r ,r,x ,r,r,m,??r")
51 (match_operand:QI 1 "general_operand" "r,LS,K,rI,x,m,r,n"))]
52 ""
53 "@
54 SET %0,%1
55 %s1 %0,%v1
56 NEGU %0,0,%n1
57 PUT %0,%1
58 GET %0,%1
59 LDB%U0 %0,%1
60 STBU %1,%0
61 %r0%I1")
62
63 (define_insn "movhi"
64 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,x,r,r,m,??r")
65 (match_operand:HI 1 "general_operand" "r,LS,K,r,x,m,r,n"))]
66 ""
67 "@
68 SET %0,%1
69 %s1 %0,%v1
70 NEGU %0,0,%n1
71 PUT %0,%1
72 GET %0,%1
73 LDW%U0 %0,%1
74 STWU %1,%0
75 %r0%I1")
76
77 ;; gcc.c-torture/compile/920428-2.c fails if there's no "n".
78 (define_insn "movsi"
79 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r ,r,x,r,r,m,??r")
80 (match_operand:SI 1 "general_operand" "r,LS,K,r,x,m,r,n"))]
81 ""
82 "@
83 SET %0,%1
84 %s1 %0,%v1
85 NEGU %0,0,%n1
86 PUT %0,%1
87 GET %0,%1
88 LDT%U0 %0,%1
89 STTU %1,%0
90 %r0%I1")
91
92 ;; We assume all "s" are addresses. Does that hold?
93 (define_insn "movdi"
94 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r")
95 (match_operand:DI 1 "general_operand" "r,LS,K,r,x,I,m,r,R,s,n"))]
96 ""
97 "@
98 SET %0,%1
99 %s1 %0,%v1
100 NEGU %0,0,%n1
101 PUT %0,%1
102 GET %0,%1
103 STCO %1,%0
104 LDO %0,%1
105 STOU %1,%0
106 GETA %0,%1
107 LDA %0,%1
108 %r0%I1")
109
110 ;; Note that we move around the float as a collection of bits; no
111 ;; conversion to double.
112 (define_insn "movsf"
113 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
114 (match_operand:SF 1 "general_operand" "r,G,r,x,m,r,F"))]
115 ""
116 "@
117 SET %0,%1
118 SETL %0,0
119 PUT %0,%1
120 GET %0,%1
121 LDT %0,%1
122 STTU %1,%0
123 %r0%I1")
124
125 (define_insn "movdf"
126 [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
127 (match_operand:DF 1 "general_operand" "r,G,r,x,m,r,F"))]
128 ""
129 "@
130 SET %0,%1
131 SETL %0,0
132 PUT %0,%1
133 GET %0,%1
134 LDO %0,%1
135 STOU %1,%0
136 %r0%I1")
137
138 ;; We need to be able to move around the values used as condition codes.
139 ;; First spotted as reported in
140 ;; <URL:http://gcc.gnu.org/ml/gcc-bugs/2003-03/msg00008.html> due to
141 ;; changes in loop optimization. The file machmode.def says they're of
142 ;; size 4 QI. Valid bit-patterns correspond to integers -1, 0 and 1, so
143 ;; we treat them as signed entities; see mmix-modes.def. The following
144 ;; expanders should cover all MODE_CC modes, and expand for this pattern.
145 (define_insn "*movcc_expanded"
146 [(set (match_operand 0 "nonimmediate_operand" "=r,x,r,r,m")
147 (match_operand 1 "nonimmediate_operand" "r,r,x,m,r"))]
148 "GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_CC
149 && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_CC"
150 "@
151 SET %0,%1
152 PUT %0,%1
153 GET %0,%1
154 LDT %0,%1
155 STT %1,%0")
156
157 (define_expand "movcc"
158 [(set (match_operand:CC 0 "nonimmediate_operand" "")
159 (match_operand:CC 1 "nonimmediate_operand" ""))]
160 ""
161 "")
162
163 (define_expand "movcc_uns"
164 [(set (match_operand:CC_UNS 0 "nonimmediate_operand" "")
165 (match_operand:CC_UNS 1 "nonimmediate_operand" ""))]
166 ""
167 "")
168
169 (define_expand "movcc_fp"
170 [(set (match_operand:CC_FP 0 "nonimmediate_operand" "")
171 (match_operand:CC_FP 1 "nonimmediate_operand" ""))]
172 ""
173 "")
174
175 (define_expand "movcc_fpeq"
176 [(set (match_operand:CC_FPEQ 0 "nonimmediate_operand" "")
177 (match_operand:CC_FPEQ 1 "nonimmediate_operand" ""))]
178 ""
179 "")
180
181 (define_expand "movcc_fun"
182 [(set (match_operand:CC_FUN 0 "nonimmediate_operand" "")
183 (match_operand:CC_FUN 1 "nonimmediate_operand" ""))]
184 ""
185 "")
186
187 (define_insn "adddi3"
188 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
189 (plus:DI
190 (match_operand:DI 1 "register_operand" "%r,r,0")
191 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,K,LS")))]
192 ""
193 "@
194 ADDU %0,%1,%2
195 SUBU %0,%1,%n2
196 %i2 %0,%v2")
197
198 (define_insn "adddf3"
199 [(set (match_operand:DF 0 "register_operand" "=r")
200 (plus:DF (match_operand:DF 1 "register_operand" "%r")
201 (match_operand:DF 2 "register_operand" "r")))]
202 ""
203 "FADD %0,%1,%2")
204
205 ;; Insn canonicalization *should* have removed the need for an integer
206 ;; in operand 2.
207 (define_insn "subdi3"
208 [(set (match_operand:DI 0 "register_operand" "=r,r")
209 (minus:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "r,I")
210 (match_operand:DI 2 "register_operand" "r,r")))]
211 ""
212 "@
213 SUBU %0,%1,%2
214 NEGU %0,%1,%2")
215
216 (define_insn "subdf3"
217 [(set (match_operand:DF 0 "register_operand" "=r")
218 (minus:DF (match_operand:DF 1 "register_operand" "r")
219 (match_operand:DF 2 "register_operand" "r")))]
220 ""
221 "FSUB %0,%1,%2")
222
223 ;; FIXME: Should we define_expand and match 2, 4, 8 (etc) with shift (or
224 ;; %{something}2ADDU %0,%1,0)? Hopefully GCC should still handle it, so
225 ;; we don't have to taint the machine description. If results are bad
226 ;; enough, we may have to do it anyway.
227 (define_insn "muldi3"
228 [(set (match_operand:DI 0 "register_operand" "=r,r")
229 (mult:DI (match_operand:DI 1 "register_operand" "%r,r")
230 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "O,rI")))
231 (clobber (match_scratch:DI 3 "=X,z"))]
232 ""
233 "@
234 %m2ADDU %0,%1,%1
235 MULU %0,%1,%2")
236
237 (define_insn "muldf3"
238 [(set (match_operand:DF 0 "register_operand" "=r")
239 (mult:DF (match_operand:DF 1 "register_operand" "r")
240 (match_operand:DF 2 "register_operand" "r")))]
241 ""
242 "FMUL %0,%1,%2")
243
244 (define_insn "divdf3"
245 [(set (match_operand:DF 0 "register_operand" "=r")
246 (div:DF (match_operand:DF 1 "register_operand" "r")
247 (match_operand:DF 2 "register_operand" "r")))]
248 ""
249 "FDIV %0,%1,%2")
250
251 ;; FIXME: Is "frem" doing the right operation for moddf3?
252 (define_insn "moddf3"
253 [(set (match_operand:DF 0 "register_operand" "=r")
254 (mod:DF (match_operand:DF 1 "register_operand" "r")
255 (match_operand:DF 2 "register_operand" "r")))]
256 ""
257 "FREM %0,%1,%2")
258
259 ;; FIXME: Should we define_expand for smin, smax, umin, umax using a
260 ;; nifty conditional sequence?
261
262 ;; FIXME: The cuter andn combinations don't get here, presumably because
263 ;; they ended up in the constant pool. Check: still?
264 (define_insn "anddi3"
265 [(set (match_operand:DI 0 "register_operand" "=r,r")
266 (and:DI
267 (match_operand:DI 1 "register_operand" "%r,0")
268 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,NT")))]
269 ""
270 "@
271 AND %0,%1,%2
272 %A2 %0,%V2")
273
274 (define_insn "iordi3"
275 [(set (match_operand:DI 0 "register_operand" "=r,r")
276 (ior:DI (match_operand:DI 1 "register_operand" "%r,0")
277 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rH,LS")))]
278 ""
279 "@
280 OR %0,%1,%2
281 %o2 %0,%v2")
282
283 (define_insn "xordi3"
284 [(set (match_operand:DI 0 "register_operand" "=r")
285 (xor:DI (match_operand:DI 1 "register_operand" "%r")
286 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
287 ""
288 "XOR %0,%1,%2")
289
290 ;; FIXME: When TImode works for other reasons (like cross-compiling from
291 ;; a 32-bit host), add back umulditi3 and umuldi3_highpart here.
292
293 ;; FIXME: Check what's really reasonable for the mod part.
294
295 ;; One day we might persuade GCC to expand divisions with constants the
296 ;; way MMIX does; giving the remainder the sign of the divisor. But even
297 ;; then, it might be good to have an option to divide the way "everybody
298 ;; else" does. Perhaps then, this option can be on by default. However,
299 ;; it's not likely to happen because major (C, C++, Fortran) language
300 ;; standards in effect at 2002-04-29 reportedly demand that the sign of
301 ;; the remainder must follow the sign of the dividend.
302
303 (define_insn "divmoddi4"
304 [(set (match_operand:DI 0 "register_operand" "=r")
305 (div:DI (match_operand:DI 1 "register_operand" "r")
306 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
307 (set (match_operand:DI 3 "register_operand" "=y")
308 (mod:DI (match_dup 1) (match_dup 2)))]
309 ;; Do the library stuff later.
310 "TARGET_KNUTH_DIVISION"
311 "DIV %0,%1,%2")
312
313 (define_insn "udivmoddi4"
314 [(set (match_operand:DI 0 "register_operand" "=r")
315 (udiv:DI (match_operand:DI 1 "register_operand" "r")
316 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
317 (set (match_operand:DI 3 "register_operand" "=y")
318 (umod:DI (match_dup 1) (match_dup 2)))]
319 ""
320 "DIVU %0,%1,%2")
321
322 (define_expand "divdi3"
323 [(parallel
324 [(set (match_operand:DI 0 "register_operand" "=&r")
325 (div:DI (match_operand:DI 1 "register_operand" "r")
326 (match_operand:DI 2 "register_operand" "r")))
327 (clobber (scratch:DI))
328 (clobber (scratch:DI))
329 (clobber (reg:DI MMIX_rR_REGNUM))])]
330 "! TARGET_KNUTH_DIVISION"
331 "")
332
333 ;; The %2-is-%1-case is there just to make sure things don't fail. Could
334 ;; presumably happen with optimizations off; no evidence.
335 (define_insn "*divdi3_nonknuth"
336 [(set (match_operand:DI 0 "register_operand" "=&r,r")
337 (div:DI (match_operand:DI 1 "register_operand" "r,r")
338 (match_operand:DI 2 "register_operand" "1,r")))
339 (clobber (match_scratch:DI 3 "=1,1"))
340 (clobber (match_scratch:DI 4 "=2,2"))
341 (clobber (reg:DI MMIX_rR_REGNUM))]
342 "! TARGET_KNUTH_DIVISION"
343 "@
344 SETL %0,1
345 XOR $255,%1,%2\;NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU %0,0,%1\;CSN %1,%1,%0\;\
346 DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1")
347
348 (define_expand "moddi3"
349 [(parallel
350 [(set (match_operand:DI 0 "register_operand" "=&r")
351 (mod:DI (match_operand:DI 1 "register_operand" "r")
352 (match_operand:DI 2 "register_operand" "r")))
353 (clobber (scratch:DI))
354 (clobber (scratch:DI))
355 (clobber (reg:DI MMIX_rR_REGNUM))])]
356 "! TARGET_KNUTH_DIVISION"
357 "")
358
359 ;; The %2-is-%1-case is there just to make sure things don't fail. Could
360 ;; presumably happen with optimizations off; no evidence.
361 (define_insn "*moddi3_nonknuth"
362 [(set (match_operand:DI 0 "register_operand" "=&r,r")
363 (mod:DI (match_operand:DI 1 "register_operand" "r,r")
364 (match_operand:DI 2 "register_operand" "1,r")))
365 (clobber (match_scratch:DI 3 "=1,1"))
366 (clobber (match_scratch:DI 4 "=2,2"))
367 (clobber (reg:DI MMIX_rR_REGNUM))]
368 "! TARGET_KNUTH_DIVISION"
369 "@
370 SETL %0,0
371 NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU $255,0,%1\;CSN %1,%1,$255\;\
372 DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
373
374 (define_insn "ashldi3"
375 [(set (match_operand:DI 0 "register_operand" "=r")
376 (ashift:DI
377 (match_operand:DI 1 "register_operand" "r")
378 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
379 ""
380 "SLU %0,%1,%2")
381
382 (define_insn "ashrdi3"
383 [(set (match_operand:DI 0 "register_operand" "=r")
384 (ashiftrt:DI
385 (match_operand:DI 1 "register_operand" "r")
386 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
387 ""
388 "SR %0,%1,%2")
389
390 (define_insn "lshrdi3"
391 [(set (match_operand:DI 0 "register_operand" "=r")
392 (lshiftrt:DI
393 (match_operand:DI 1 "register_operand" "r")
394 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
395 ""
396 "SRU %0,%1,%2")
397
398 (define_insn "negdi2"
399 [(set (match_operand:DI 0 "register_operand" "=r")
400 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
401 ""
402 "NEGU %0,0,%1")
403
404 (define_expand "negdf2"
405 [(parallel [(set (match_operand:DF 0 "register_operand" "=r")
406 (neg:DF (match_operand:DF 1 "register_operand" "r")))
407 (use (match_dup 2))])]
408 ""
409 {
410 /* Emit bit-flipping sequence to be IEEE-safe wrt. -+0. */
411 operands[2] = force_reg (DImode, GEN_INT ((HOST_WIDE_INT) 1 << 63));
412 })
413
414 (define_insn "*expanded_negdf2"
415 [(set (match_operand:DF 0 "register_operand" "=r")
416 (neg:DF (match_operand:DF 1 "register_operand" "r")))
417 (use (match_operand:DI 2 "register_operand" "r"))]
418 ""
419 "XOR %0,%1,%2")
420
421 ;; FIXME: define_expand for absdi2?
422
423 (define_insn "absdf2"
424 [(set (match_operand:DF 0 "register_operand" "=r")
425 (abs:DF (match_operand:DF 1 "register_operand" "0")))]
426 ""
427 "ANDNH %0,#8000")
428
429 (define_insn "sqrtdf2"
430 [(set (match_operand:DF 0 "register_operand" "=r")
431 (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
432 ""
433 "FSQRT %0,%1")
434
435 ;; FIXME: define_expand for ffssi2? (not ffsdi2 since int is SImode).
436
437 (define_insn "one_cmpldi2"
438 [(set (match_operand:DI 0 "register_operand" "=r")
439 (not:DI (match_operand:DI 1 "register_operand" "r")))]
440 ""
441 "NOR %0,%1,0")
442
443 ;; Since we don't have cc0, we do what is recommended in the manual;
444 ;; store away the operands for use in the branch, scc or movcc insn.
445 (define_expand "cmpdi"
446 [(match_operand:DI 0 "register_operand" "")
447 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "")]
448 ""
449 "
450 {
451 mmix_compare_op0 = operands[0];
452 mmix_compare_op1 = operands[1];
453 DONE;
454 }")
455
456 (define_expand "cmpdf"
457 [(match_operand:DF 0 "register_operand" "")
458 (match_operand:DF 1 "register_operand" "")]
459 ""
460 "
461 {
462 mmix_compare_op0 = operands[0];
463 mmix_compare_op1 = operands[1];
464 DONE;
465 }")
466
467 ;; When the user-patterns expand, the resulting insns will match the
468 ;; patterns below.
469
470 ;; We can fold the signed-compare where the register value is
471 ;; already equal to (compare:CCTYPE (reg) (const_int 0)).
472 ;; We can't do that at all for floating-point, due to NaN, +0.0
473 ;; and -0.0, and we can only do it for the non/zero test of
474 ;; unsigned, so that has to be done another way.
475 ;; FIXME: Perhaps a peep2 changing CCcode to a new code, that
476 ;; gets folded here.
477 (define_insn "*cmpcc_folded"
478 [(set (match_operand:CC 0 "register_operand" "=r")
479 (compare:CC
480 (match_operand:DI 1 "register_operand" "r")
481 (const_int 0)))]
482 ;; FIXME: Can we test equivalence any other way?
483 ;; FIXME: Can we fold any other way?
484 "REG_P (operands[0]) && REG_P (operands[1])
485 && REGNO (operands[1]) == REGNO (operands[0])"
486 "%% folded: cmp %0,%1,0")
487
488 (define_insn "*cmpcc"
489 [(set (match_operand:CC 0 "register_operand" "=r")
490 (compare:CC
491 (match_operand:DI 1 "register_operand" "r")
492 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
493 ""
494 "CMP %0,%1,%2")
495
496 (define_insn "*cmpu"
497 [(set (match_operand:CC_UNS 0 "register_operand" "=r")
498 (compare:CC_UNS
499 (match_operand:DI 1 "register_operand" "r")
500 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
501 ""
502 "CMPU %0,%1,%2")
503
504 (define_insn "*fcmp"
505 [(set (match_operand:CC_FP 0 "register_operand" "=r")
506 (compare:CC_FP
507 (match_operand:DF 1 "register_operand" "r")
508 (match_operand:DF 2 "register_operand" "r")))]
509 ""
510 "FCMP%e0 %0,%1,%2")
511
512 ;; FIXME: for -mieee, add fsub %0,%1,%1\;fsub %0,%2,%2 before to
513 ;; make signalling compliant.
514 (define_insn "*feql"
515 [(set (match_operand:CC_FPEQ 0 "register_operand" "=r")
516 (compare:CC_FPEQ
517 (match_operand:DF 1 "register_operand" "r")
518 (match_operand:DF 2 "register_operand" "r")))]
519 ""
520 "FEQL%e0 %0,%1,%2")
521
522 (define_insn "*fun"
523 [(set (match_operand:CC_FUN 0 "register_operand" "=r")
524 (compare:CC_FUN
525 (match_operand:DF 1 "register_operand" "r")
526 (match_operand:DF 2 "register_operand" "r")))]
527 ""
528 "FUN%e0 %0,%1,%2")
529
530 ;; In order to get correct rounding, we have to use SFLOT and SFLOTU for
531 ;; conversion. They do not convert to SFmode; they convert to DFmode,
532 ;; with rounding as of SFmode. They are not usable as is, but we pretend
533 ;; we have a single instruction but emit two.
534
535 ;; Note that this will (somewhat unexpectedly) create an inexact
536 ;; exception if rounding is necessary - has to be masked off in crt0?
537 (define_expand "floatdisf2"
538 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
539 (float:SF
540 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
541 ;; Let's use a DI scratch, since SF don't generally get into
542 ;; registers. Dunno what's best; it's really a DF, but that
543 ;; doesn't logically follow from operands in the pattern.
544 (clobber (match_scratch:DI 2 "=&r"))])]
545 ""
546 "
547 {
548 if (GET_CODE (operands[0]) != MEM)
549 {
550 rtx stack_slot;
551
552 /* FIXME: This stack-slot remains even at -O3. There must be a
553 better way. */
554 stack_slot
555 = validize_mem (assign_stack_temp (SFmode,
556 GET_MODE_SIZE (SFmode), 0));
557 emit_insn (gen_floatdisf2 (stack_slot, operands[1]));
558 emit_move_insn (operands[0], stack_slot);
559 DONE;
560 }
561 }")
562
563 (define_insn "*floatdisf2_real"
564 [(set (match_operand:SF 0 "memory_operand" "=m")
565 (float:SF
566 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
567 (clobber (match_scratch:DI 2 "=&r"))]
568 ""
569 "SFLOT %2,%1\;STSF %2,%0")
570
571 (define_expand "floatunsdisf2"
572 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
573 (unsigned_float:SF
574 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
575 ;; Let's use a DI scratch, since SF don't generally get into
576 ;; registers. Dunno what's best; it's really a DF, but that
577 ;; doesn't logically follow from operands in the pattern.
578 (clobber (scratch:DI))])]
579 ""
580 "
581 {
582 if (GET_CODE (operands[0]) != MEM)
583 {
584 rtx stack_slot;
585
586 /* FIXME: This stack-slot remains even at -O3. Must be a better
587 way. */
588 stack_slot
589 = validize_mem (assign_stack_temp (SFmode,
590 GET_MODE_SIZE (SFmode), 0));
591 emit_insn (gen_floatunsdisf2 (stack_slot, operands[1]));
592 emit_move_insn (operands[0], stack_slot);
593 DONE;
594 }
595 }")
596
597 (define_insn "*floatunsdisf2_real"
598 [(set (match_operand:SF 0 "memory_operand" "=m")
599 (unsigned_float:SF
600 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
601 (clobber (match_scratch:DI 2 "=&r"))]
602 ""
603 "SFLOTU %2,%1\;STSF %2,%0")
604
605 ;; Note that this will (somewhat unexpectedly) create an inexact
606 ;; exception if rounding is necessary - has to be masked off in crt0?
607 (define_insn "floatdidf2"
608 [(set (match_operand:DF 0 "register_operand" "=r")
609 (float:DF
610 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
611 ""
612 "FLOT %0,%1")
613
614 (define_insn "floatunsdidf2"
615 [(set (match_operand:DF 0 "register_operand" "=r")
616 (unsigned_float:DF
617 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
618 ""
619 "FLOTU %0,%1")
620
621 (define_insn "ftruncdf2"
622 [(set (match_operand:DF 0 "register_operand" "=r")
623 (fix:DF (match_operand:DF 1 "register_operand" "r")))]
624 ""
625 ;; ROUND_OFF
626 "FINT %0,1,%1")
627
628 ;; Note that this will (somewhat unexpectedly) create an inexact
629 ;; exception if rounding is necessary - has to be masked off in crt0?
630 (define_insn "fix_truncdfdi2"
631 [(set (match_operand:DI 0 "register_operand" "=r")
632 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
633 ""
634 ;; ROUND_OFF
635 "FIX %0,1,%1")
636
637 (define_insn "fixuns_truncdfdi2"
638 [(set (match_operand:DI 0 "register_operand" "=r")
639 (unsigned_fix:DI
640 (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
641 ""
642 ;; ROUND_OFF
643 "FIXU %0,1,%1")
644
645 ;; It doesn't seem like it's possible to have memory_operand as a
646 ;; predicate here (testcase: libgcc2 floathisf). FIXME: Shouldn't it be
647 ;; possible to do that? Bug in GCC? Anyway, this used to be a simple
648 ;; pattern with a memory_operand predicate, but was split up with a
649 ;; define_expand with the old pattern as "anonymous".
650 ;; FIXME: Perhaps with SECONDARY_MEMORY_NEEDED?
651 (define_expand "truncdfsf2"
652 [(set (match_operand:SF 0 "memory_operand" "")
653 (float_truncate:SF (match_operand:DF 1 "register_operand" "")))]
654 ""
655 "
656 {
657 if (GET_CODE (operands[0]) != MEM)
658 {
659 /* FIXME: There should be a way to say: 'put this in operands[0]
660 but *after* the expanded insn'. */
661 rtx stack_slot;
662
663 /* There is no sane destination but a register here, if it wasn't
664 already MEM. (It's too hard to get fatal_insn to work here.) */
665 if (! REG_P (operands[0]))
666 internal_error (\"MMIX Internal: Bad truncdfsf2 expansion\");
667
668 /* FIXME: This stack-slot remains even at -O3. Must be a better
669 way. */
670 stack_slot
671 = validize_mem (assign_stack_temp (SFmode,
672 GET_MODE_SIZE (SFmode), 0));
673 emit_insn (gen_truncdfsf2 (stack_slot, operands[1]));
674 emit_move_insn (operands[0], stack_slot);
675 DONE;
676 }
677 }")
678
679 (define_insn "*truncdfsf2_real"
680 [(set (match_operand:SF 0 "memory_operand" "=m")
681 (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
682 ""
683 "STSF %1,%0")
684
685 ;; Same comment as for truncdfsf2.
686 (define_expand "extendsfdf2"
687 [(set (match_operand:DF 0 "register_operand" "=r")
688 (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))]
689 ""
690 "
691 {
692 if (GET_CODE (operands[1]) != MEM)
693 {
694 rtx stack_slot;
695
696 /* There is no sane destination but a register here, if it wasn't
697 already MEM. (It's too hard to get fatal_insn to work here.) */
698 if (! REG_P (operands[0]))
699 internal_error (\"MMIX Internal: Bad extendsfdf2 expansion\");
700
701 /* FIXME: This stack-slot remains even at -O3. There must be a
702 better way. */
703 stack_slot
704 = validize_mem (assign_stack_temp (SFmode,
705 GET_MODE_SIZE (SFmode), 0));
706 emit_move_insn (stack_slot, operands[1]);
707 emit_insn (gen_extendsfdf2 (operands[0], stack_slot));
708 DONE;
709 }
710 }")
711
712 (define_insn "*extendsfdf2_real"
713 [(set (match_operand:DF 0 "register_operand" "=r")
714 (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))]
715 ""
716 "LDSF %0,%1")
717
718 ;; Neither sign-extend nor zero-extend are necessary; gcc knows how to
719 ;; synthesize using shifts or and, except with a memory source and not
720 ;; completely optimal. FIXME: Actually, other bugs surface when those
721 ;; patterns are defined; fix later.
722
723 ;; There are no sane values with the bit-patterns of (int) 0..255 except
724 ;; 0 to use in movdfcc.
725
726 (define_expand "movdfcc"
727 [(set (match_operand:DF 0 "register_operand" "")
728 (if_then_else:DF
729 (match_operand 1 "comparison_operator" "")
730 (match_operand:DF 2 "mmix_reg_or_0_operand" "")
731 (match_operand:DF 3 "mmix_reg_or_0_operand" "")))]
732 ""
733 "
734 {
735 enum rtx_code code = GET_CODE (operands[1]);
736 rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
737 mmix_compare_op1);
738 if (cc_reg == NULL_RTX)
739 FAIL;
740 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
741 }")
742
743 (define_expand "movdicc"
744 [(set (match_operand:DI 0 "register_operand" "")
745 (if_then_else:DI
746 (match_operand 1 "comparison_operator" "")
747 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")
748 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "")))]
749 ""
750 "
751 {
752 enum rtx_code code = GET_CODE (operands[1]);
753 rtx cc_reg = mmix_gen_compare_reg (code, mmix_compare_op0,
754 mmix_compare_op1);
755 if (cc_reg == NULL_RTX)
756 FAIL;
757 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
758 }")
759
760 ;; FIXME: Is this the right way to do "folding" of CCmode -> DImode?
761 (define_insn "*movdicc_real_foldable"
762 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
763 (if_then_else:DI
764 (match_operator 2 "mmix_foldable_comparison_operator"
765 [(match_operand:DI 3 "register_operand" "r,r,r,r")
766 (const_int 0)])
767 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
768 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
769 ""
770 "@
771 CS%d2 %0,%3,%1
772 CS%D2 %0,%3,%4
773 ZS%d2 %0,%3,%1
774 ZS%D2 %0,%3,%4")
775
776 (define_insn "*movdicc_real_reversible"
777 [(set
778 (match_operand:DI 0 "register_operand" "=r ,r ,r ,r")
779 (if_then_else:DI
780 (match_operator
781 2 "mmix_comparison_operator"
782 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
783 (const_int 0)])
784 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
785 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
786 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
787 "@
788 CS%d2 %0,%3,%1
789 CS%D2 %0,%3,%4
790 ZS%d2 %0,%3,%1
791 ZS%D2 %0,%3,%4")
792
793 (define_insn "*movdicc_real_nonreversible"
794 [(set
795 (match_operand:DI 0 "register_operand" "=r ,r")
796 (if_then_else:DI
797 (match_operator
798 2 "mmix_comparison_operator"
799 [(match_operand 3 "mmix_reg_cc_operand" "r ,r")
800 (const_int 0)])
801 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,rI")
802 (match_operand:DI 4 "mmix_reg_or_0_operand" "0 ,GM")))]
803 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
804 "@
805 CS%d2 %0,%3,%1
806 ZS%d2 %0,%3,%1")
807
808 (define_insn "*movdfcc_real_foldable"
809 [(set
810 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
811 (if_then_else:DF
812 (match_operator
813 2 "mmix_foldable_comparison_operator"
814 [(match_operand:DI 3 "register_operand" "r ,r ,r ,r")
815 (const_int 0)])
816 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
817 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
818 ""
819 "@
820 CS%d2 %0,%3,%1
821 CS%D2 %0,%3,%4
822 ZS%d2 %0,%3,%1
823 ZS%D2 %0,%3,%4")
824
825 (define_insn "*movdfcc_real_reversible"
826 [(set
827 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
828 (if_then_else:DF
829 (match_operator
830 2 "mmix_comparison_operator"
831 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
832 (const_int 0)])
833 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
834 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
835 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
836 "@
837 CS%d2 %0,%3,%1
838 CS%D2 %0,%3,%4
839 ZS%d2 %0,%3,%1
840 ZS%D2 %0,%3,%4")
841
842 (define_insn "*movdfcc_real_nonreversible"
843 [(set
844 (match_operand:DF 0 "register_operand" "=r ,r")
845 (if_then_else:DF
846 (match_operator
847 2 "mmix_comparison_operator"
848 [(match_operand 3 "mmix_reg_cc_operand" "r ,r")
849 (const_int 0)])
850 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,rGM")
851 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,GM")))]
852 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
853 "@
854 CS%d2 %0,%3,%1
855 ZS%d2 %0,%3,%1")
856
857 ;; FIXME: scc patterns will probably help, I just skip them
858 ;; right now. Revisit.
859
860 (define_expand "beq"
861 [(set (pc)
862 (if_then_else (eq (match_dup 1) (const_int 0))
863 (label_ref (match_operand 0 "" ""))
864 (pc)))]
865 ""
866 "
867 {
868 operands[1]
869 = mmix_gen_compare_reg (EQ, mmix_compare_op0, mmix_compare_op1);
870 }")
871
872 (define_expand "bne"
873 [(set (pc)
874 (if_then_else (ne (match_dup 1) (const_int 0))
875 (label_ref (match_operand 0 "" ""))
876 (pc)))]
877 ""
878 "
879 {
880 operands[1]
881 = mmix_gen_compare_reg (NE, mmix_compare_op0, mmix_compare_op1);
882 }")
883
884 (define_expand "bgt"
885 [(set (pc)
886 (if_then_else (gt (match_dup 1) (const_int 0))
887 (label_ref (match_operand 0 "" ""))
888 (pc)))]
889 ""
890 "
891 {
892 operands[1]
893 = mmix_gen_compare_reg (GT, mmix_compare_op0, mmix_compare_op1);
894 }")
895
896 (define_expand "ble"
897 [(set (pc)
898 (if_then_else (le (match_dup 1) (const_int 0))
899 (label_ref (match_operand 0 "" ""))
900 (pc)))]
901 ""
902 "
903 {
904 operands[1]
905 = mmix_gen_compare_reg (LE, mmix_compare_op0, mmix_compare_op1);
906
907 /* The head comment of optabs.c:can_compare_p says we're required to
908 implement this, so we have to clean up the mess here. */
909 if (operands[1] == NULL_RTX)
910 {
911 /* FIXME: Watch out for sharing/unsharing of rtx:es. */
912 emit_jump_insn ((*bcc_gen_fctn[(int) LT]) (operands[0]));
913 emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
914 DONE;
915 }
916 }")
917
918 (define_expand "bge"
919 [(set (pc)
920 (if_then_else (ge (match_dup 1) (const_int 0))
921 (label_ref (match_operand 0 "" ""))
922 (pc)))]
923 ""
924 "
925 {
926 operands[1]
927 = mmix_gen_compare_reg (GE, mmix_compare_op0, mmix_compare_op1);
928
929 /* The head comment of optabs.c:can_compare_p says we're required to
930 implement this, so we have to clean up the mess here. */
931 if (operands[1] == NULL_RTX)
932 {
933 /* FIXME: Watch out for sharing/unsharing of rtx:es. */
934 emit_jump_insn ((*bcc_gen_fctn[(int) GT]) (operands[0]));
935 emit_jump_insn ((*bcc_gen_fctn[(int) EQ]) (operands[0]));
936 DONE;
937 }
938 }")
939
940 (define_expand "blt"
941 [(set (pc)
942 (if_then_else (lt (match_dup 1) (const_int 0))
943 (label_ref (match_operand 0 "" ""))
944 (pc)))]
945 ""
946 "
947 {
948 operands[1]
949 = mmix_gen_compare_reg (LT, mmix_compare_op0, mmix_compare_op1);
950 }")
951
952 (define_expand "bgtu"
953 [(set (pc)
954 (if_then_else (gtu (match_dup 1) (const_int 0))
955 (label_ref (match_operand 0 "" ""))
956 (pc)))]
957 ""
958 "
959 {
960 operands[1]
961 = mmix_gen_compare_reg (GTU, mmix_compare_op0, mmix_compare_op1);
962 }")
963
964 (define_expand "bleu"
965 [(set (pc)
966 (if_then_else (leu (match_dup 1) (const_int 0))
967 (label_ref (match_operand 0 "" ""))
968 (pc)))]
969 ""
970 "
971 {
972 operands[1]
973 = mmix_gen_compare_reg (LEU, mmix_compare_op0, mmix_compare_op1);
974 }")
975
976 (define_expand "bgeu"
977 [(set (pc)
978 (if_then_else (geu (match_dup 1) (const_int 0))
979 (label_ref (match_operand 0 "" ""))
980 (pc)))]
981 ""
982 "
983 {
984 operands[1]
985 = mmix_gen_compare_reg (GEU, mmix_compare_op0, mmix_compare_op1);
986 }")
987
988 (define_expand "bltu"
989 [(set (pc)
990 (if_then_else (ltu (match_dup 1) (const_int 0))
991 (label_ref (match_operand 0 "" ""))
992 (pc)))]
993 ""
994 "
995 {
996 operands[1]
997 = mmix_gen_compare_reg (LTU, mmix_compare_op0, mmix_compare_op1);
998 }")
999
1000 (define_expand "bunordered"
1001 [(set (pc)
1002 (if_then_else (unordered (match_dup 1) (const_int 0))
1003 (label_ref (match_operand 0 "" ""))
1004 (pc)))]
1005 ""
1006 "
1007 {
1008 operands[1]
1009 = mmix_gen_compare_reg (UNORDERED, mmix_compare_op0, mmix_compare_op1);
1010
1011 if (operands[1] == NULL_RTX)
1012 FAIL;
1013 }")
1014
1015 (define_expand "bordered"
1016 [(set (pc)
1017 (if_then_else (ordered (match_dup 1) (const_int 0))
1018 (label_ref (match_operand 0 "" ""))
1019 (pc)))]
1020 ""
1021 "
1022 {
1023 operands[1]
1024 = mmix_gen_compare_reg (ORDERED, mmix_compare_op0, mmix_compare_op1);
1025 }")
1026
1027 ;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but
1028 ;; there's no RTL code for it. Maybe revisit in future.
1029
1030 ;; FIXME: Odd/Even matchers?
1031 (define_insn "*bCC_foldable"
1032 [(set (pc)
1033 (if_then_else
1034 (match_operator 1 "mmix_foldable_comparison_operator"
1035 [(match_operand:DI 2 "register_operand" "r")
1036 (const_int 0)])
1037 (label_ref (match_operand 0 "" ""))
1038 (pc)))]
1039 ""
1040 "%+B%d1 %2,%0")
1041
1042 (define_insn "*bCC"
1043 [(set (pc)
1044 (if_then_else
1045 (match_operator 1 "mmix_comparison_operator"
1046 [(match_operand 2 "mmix_reg_cc_operand" "r")
1047 (const_int 0)])
1048 (label_ref (match_operand 0 "" ""))
1049 (pc)))]
1050 ""
1051 "%+B%d1 %2,%0")
1052
1053 (define_insn "*bCC_inverted_foldable"
1054 [(set (pc)
1055 (if_then_else
1056 (match_operator 1 "mmix_foldable_comparison_operator"
1057 [(match_operand:DI 2 "register_operand" "r")
1058 (const_int 0)])
1059 (pc)
1060 (label_ref (match_operand 0 "" ""))))]
1061 ;; REVERSIBLE_CC_MODE is checked by mmix_foldable_comparison_operator.
1062 ""
1063 "%+B%D1 %2,%0")
1064
1065 (define_insn "*bCC_inverted"
1066 [(set (pc)
1067 (if_then_else
1068 (match_operator 1 "mmix_comparison_operator"
1069 [(match_operand 2 "mmix_reg_cc_operand" "r")
1070 (const_int 0)])
1071 (pc)
1072 (label_ref (match_operand 0 "" ""))))]
1073 "REVERSIBLE_CC_MODE (GET_MODE (operands[2]))"
1074 "%+B%D1 %2,%0")
1075
1076 (define_expand "call"
1077 [(parallel [(call (match_operand:QI 0 "memory_operand" "")
1078 (match_operand 1 "general_operand" ""))
1079 (use (match_operand 2 "general_operand" ""))
1080 (clobber (match_dup 4))])
1081 (set (match_dup 4) (match_dup 3))]
1082 ""
1083 "
1084 {
1085 /* The caller checks that the operand is generally valid as an
1086 address, but at -O0 nothing makes sure that it's also a valid
1087 call address for a *call*; a mmix_symbolic_or_address_operand.
1088 Force into a register if it isn't. */
1089 if (!mmix_symbolic_or_address_operand (XEXP (operands[0], 0),
1090 GET_MODE (XEXP (operands[0], 0))))
1091 operands[0]
1092 = replace_equiv_address (operands[0],
1093 force_reg (Pmode, XEXP (operands[0], 0)));
1094
1095 /* Since the epilogue 'uses' the return address, and it is clobbered
1096 in the call, and we set it back after every call (all but one setting
1097 will be optimized away), integrity is maintained. */
1098 operands[3]
1099 = mmix_get_hard_reg_initial_val (Pmode,
1100 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1101
1102 /* FIXME: There's a bug in gcc which causes NULL to be passed as
1103 operand[2] when we get out of registers, which later confuses gcc.
1104 Work around it by replacing it with const_int 0. Possibly documentation
1105 error too. */
1106 if (operands[2] == NULL_RTX)
1107 operands[2] = const0_rtx;
1108
1109 operands[4] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1110 }")
1111
1112 (define_expand "call_value"
1113 [(parallel [(set (match_operand 0 "" "")
1114 (call (match_operand:QI 1 "memory_operand" "")
1115 (match_operand 2 "general_operand" "")))
1116 (use (match_operand 3 "general_operand" ""))
1117 (clobber (match_dup 5))])
1118 (set (match_dup 5) (match_dup 4))]
1119 ""
1120 "
1121 {
1122 /* The caller checks that the operand is generally valid as an
1123 address, but at -O0 nothing makes sure that it's also a valid
1124 call address for a *call*; a mmix_symbolic_or_address_operand.
1125 Force into a register if it isn't. */
1126 if (!mmix_symbolic_or_address_operand (XEXP (operands[1], 0),
1127 GET_MODE (XEXP (operands[1], 0))))
1128 operands[1]
1129 = replace_equiv_address (operands[1],
1130 force_reg (Pmode, XEXP (operands[1], 0)));
1131
1132 /* Since the epilogue 'uses' the return address, and it is clobbered
1133 in the call, and we set it back after every call (all but one setting
1134 will be optimized away), integrity is maintained. */
1135 operands[4]
1136 = mmix_get_hard_reg_initial_val (Pmode,
1137 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1138
1139 /* FIXME: See 'call'. */
1140 if (operands[3] == NULL_RTX)
1141 operands[3] = const0_rtx;
1142
1143 /* FIXME: Documentation bug: operands[3] (operands[2] for 'call') is the
1144 *next* argument register, not the number of arguments in registers.
1145 (There used to be code here where that mattered.) */
1146
1147 operands[5] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1148 }")
1149
1150 ;; Don't use 'p' here. A 'p' must stand first in constraints, or reload
1151 ;; messes up, not registering the address for reload. Several C++
1152 ;; testcases, including g++.brendan/crash40.C. FIXME: This is arguably a
1153 ;; bug in gcc. Note line ~2612 in reload.c, that does things on the
1154 ;; condition <<else if (constraints[i][0] == 'p')>> and the comment on
1155 ;; ~3017 that says:
1156 ;; << case 'p':
1157 ;; /* All necessary reloads for an address_operand
1158 ;; were handled in find_reloads_address. */>>
1159 ;; Sorry, I have not dug deeper. If symbolic addresses are used
1160 ;; rarely compared to addresses in registers, disparaging the
1161 ;; first ("p") alternative by adding ? in the first operand
1162 ;; might do the trick. We define 'U' as a synonym to 'p', but without the
1163 ;; caveats (and very small advantages) of 'p'.
1164 (define_insn "*call_real"
1165 [(call (mem:QI
1166 (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU"))
1167 (match_operand 1 "" ""))
1168 (use (match_operand 2 "" ""))
1169 (clobber (reg:DI MMIX_rJ_REGNUM))]
1170 ""
1171 "@
1172 PUSHJ $%p2,%0
1173 PUSHGO $%p2,%a0")
1174
1175 (define_insn "*call_value_real"
1176 [(set (match_operand 0 "register_operand" "=r,r")
1177 (call (mem:QI
1178 (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU"))
1179 (match_operand 2 "" "")))
1180 (use (match_operand 3 "" ""))
1181 (clobber (reg:DI MMIX_rJ_REGNUM))]
1182 ""
1183 "@
1184 PUSHJ $%p3,%1
1185 PUSHGO $%p3,%a1")
1186
1187 ;; I hope untyped_call and untyped_return are not needed for MMIX.
1188 ;; Users of Objective-C will notice.
1189
1190 ; Generated by GCC.
1191 (define_expand "return"
1192 [(return)]
1193 "mmix_use_simple_return ()"
1194 "")
1195
1196 ; Generated by the epilogue expander.
1197 (define_insn "*expanded_return"
1198 [(return)]
1199 ""
1200 "POP %.,0")
1201
1202 (define_expand "prologue"
1203 [(const_int 0)]
1204 ""
1205 "mmix_expand_prologue (); DONE;")
1206
1207 ; Note that the (return) from the expander itself is always the last insn
1208 ; in the epilogue.
1209 (define_expand "epilogue"
1210 [(return)]
1211 ""
1212 "mmix_expand_epilogue ();")
1213
1214 (define_insn "nop"
1215 [(const_int 0)]
1216 ""
1217 "SWYM 0,0,0")
1218
1219 (define_insn "jump"
1220 [(set (pc) (label_ref (match_operand 0 "" "")))]
1221 ""
1222 "JMP %0")
1223
1224 (define_insn "indirect_jump"
1225 [(set (pc) (match_operand 0 "address_operand" "p"))]
1226 ""
1227 "GO $255,%a0")
1228
1229 ;; FIXME: This is just a jump, and should be expanded to one.
1230 (define_insn "tablejump"
1231 [(set (pc) (match_operand:DI 0 "address_operand" "p"))
1232 (use (label_ref (match_operand 1 "" "")))]
1233 ""
1234 "GO $255,%a0")
1235
1236 ;; The only peculiar thing is that the register stack has to be unwound at
1237 ;; nonlocal_goto_receiver. At each function that has a nonlocal label, we
1238 ;; save at function entry the location of the "alpha" register stack
1239 ;; pointer, rO, in a stack slot known to that function (right below where
1240 ;; the frame-pointer would be located).
1241 ;; In the nonlocal goto receiver, we unwind the register stack by a series
1242 ;; of "pop 0,0" until rO equals the saved value. (If it goes lower, we
1243 ;; should die with a trap.)
1244 (define_expand "nonlocal_goto_receiver"
1245 [(parallel [(unspec_volatile [(const_int 0)] 1)
1246 (clobber (scratch:DI))
1247 (clobber (reg:DI MMIX_rJ_REGNUM))])
1248 (set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))]
1249 ""
1250 "
1251 {
1252 operands[0]
1253 = mmix_get_hard_reg_initial_val (Pmode,
1254 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1255
1256 /* Mark this function as containing a landing-pad. */
1257 cfun->machine->has_landing_pad = 1;
1258 }")
1259
1260 ;; GCC can insist on using saved registers to keep the slot address in
1261 ;; "across" the exception, or (perhaps) to use saved registers in the
1262 ;; address and re-use them after the register stack unwind, so it's best
1263 ;; to form the address ourselves.
1264 (define_insn "*nonlocal_goto_receiver_expanded"
1265 [(unspec_volatile [(const_int 0)] 1)
1266 (clobber (match_scratch:DI 0 "=&r"))
1267 (clobber (reg:DI MMIX_rJ_REGNUM))]
1268 ""
1269 {
1270 rtx temp_reg = operands[0];
1271 rtx my_operands[2];
1272 HOST_WIDEST_INT offs;
1273 const char *my_template
1274 = "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\
1275 0:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:";
1276
1277 my_operands[1] = temp_reg;
1278
1279 /* If we have a frame-pointer (hence unknown stack-pointer offset),
1280 just use the frame-pointer and the known offset. */
1281 if (frame_pointer_needed)
1282 {
1283 my_operands[0] = GEN_INT (-MMIX_fp_rO_OFFSET);
1284
1285 output_asm_insn ("NEGU %1,0,%0", my_operands);
1286 my_operands[0] = gen_rtx_PLUS (Pmode, frame_pointer_rtx, temp_reg);
1287 }
1288 else
1289 {
1290 /* We know the fp-based offset, so "eliminate" it to be sp-based. */
1291 offs
1292 = (mmix_initial_elimination_offset (MMIX_FRAME_POINTER_REGNUM,
1293 MMIX_STACK_POINTER_REGNUM)
1294 + MMIX_fp_rO_OFFSET);
1295
1296 if (offs >= 0 && offs <= 255)
1297 my_operands[0]
1298 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs));
1299 else
1300 {
1301 mmix_output_register_setting (asm_out_file, REGNO (temp_reg),
1302 offs, 1);
1303 my_operands[0] = gen_rtx_PLUS (Pmode, stack_pointer_rtx, temp_reg);
1304 }
1305 }
1306
1307 output_asm_insn (my_template, my_operands);
1308 return "";
1309 })
1310
1311 (define_insn "*Naddu"
1312 [(set (match_operand:DI 0 "register_operand" "=r")
1313 (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r")
1314 (match_operand:DI 2 "const_int_operand" "n"))
1315 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))]
1316 "GET_CODE (operands[2]) == CONST_INT
1317 && (INTVAL (operands[2]) == 2
1318 || INTVAL (operands[2]) == 4
1319 || INTVAL (operands[2]) == 8
1320 || INTVAL (operands[2]) == 16)"
1321 "%2ADDU %0,%1,%3")
1322
1323 (define_insn "*andn"
1324 [(set (match_operand:DI 0 "register_operand" "=r")
1325 (and:DI
1326 (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))
1327 (match_operand:DI 2 "register_operand" "r")))]
1328 ""
1329 "ANDN %0,%2,%1")
1330
1331 (define_insn "*nand"
1332 [(set (match_operand:DI 0 "register_operand" "=r")
1333 (ior:DI
1334 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1335 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1336 ""
1337 "NAND %0,%1,%2")
1338
1339 (define_insn "*nor"
1340 [(set (match_operand:DI 0 "register_operand" "=r")
1341 (and:DI
1342 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1343 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1344 ""
1345 "NOR %0,%1,%2")
1346
1347 (define_insn "*nxor"
1348 [(set (match_operand:DI 0 "register_operand" "=r")
1349 (not:DI
1350 (xor:DI (match_operand:DI 1 "register_operand" "%r")
1351 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1352 ""
1353 "NXOR %0,%1,%2")
1354
1355 (define_insn "sync_icache"
1356 [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")
1357 (match_operand:DI 1 "const_int_operand" "I")] 0)]
1358 ""
1359 "SYNCID %1,%0")
1360
1361 ;; Local Variables:
1362 ;; mode: lisp
1363 ;; indent-tabs-mode: t
1364 ;; End: