]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/mmix/mmix.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / mmix / mmix.md
CommitLineData
bcf684c7 1;; GCC machine description for MMIX
8d9254fc 2;; Copyright (C) 2000-2020 Free Software Foundation, Inc.
bcf684c7
HPN
3;; Contributed by Hans-Peter Nilsson (hp@bitrange.com)
4
c583c5c3 5;; This file is part of GCC.
bcf684c7 6
c583c5c3 7;; GCC is free software; you can redistribute it and/or modify
bcf684c7 8;; it under the terms of the GNU General Public License as published by
2f83c7d6 9;; the Free Software Foundation; either version 3, or (at your option)
bcf684c7
HPN
10;; any later version.
11
c583c5c3 12;; GCC is distributed in the hope that it will be useful,
bcf684c7
HPN
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
2f83c7d6
NC
18;; along with GCC; see the file COPYING3. If not see
19;; <http://www.gnu.org/licenses/>.
bcf684c7
HPN
20
21;; The original PO technology requires these to be ordered by speed,
22;; so that assigner will pick the fastest.
23
24;; See file "rtl.def" for documentation on define_insn, match_*, et al.
25
26;; Uses of UNSPEC in this file:
27;; UNSPEC_VOLATILE:
28;;
29;; 0 sync_icache (sync icache before trampoline jump)
30;; 1 nonlocal_goto_receiver
31;;
32
33;; The order of insns is as in Node: Standard Names, with smaller modes
34;; before bigger modes.
35
91312b81 36(define_constants
db08fddf 37 [(MMIX_rJ_REGNUM 259)
34116c2a 38 (MMIX_rR_REGNUM 260)
db08fddf 39 (MMIX_fp_rO_OFFSET -24)]
91312b81 40)
cc73528f
HPN
41\f
42;; Operand and operator predicates.
bcf684c7 43
cc73528f 44(include "predicates.md")
e076319b 45(include "constraints.md")
cc73528f 46\f
bcf684c7
HPN
47;; FIXME: Can we remove the reg-to-reg for smaller modes? Shouldn't they
48;; be synthesized ok?
49(define_insn "movqi"
91312b81
HPN
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"))]
bcf684c7
HPN
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"
91312b81 79 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r ,r,x,r,r,m,??r")
bcf684c7
HPN
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"
a824924d
HPN
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"))]
bcf684c7
HPN
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
a824924d 107 LDA %0,%1
bcf684c7
HPN
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\f
2b18b49b
HPN
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"
73ba39fc
HPN
146 [(set (match_operand 0 "nonimmediate_operand" "=r,x,r,r,m")
147 (match_operand 1 "nonimmediate_operand" "r,r,x,m,r"))]
2b18b49b
HPN
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
73ba39fc
HPN
152 PUT %0,%1
153 GET %0,%1
2b18b49b
HPN
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\f
bcf684c7
HPN
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")
e076319b 277 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,LS")))]
bcf684c7
HPN
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\f
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
1f2641b6
HPN
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.
bcf684c7
HPN
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))
34116c2a
HPN
328 (clobber (scratch:DI))
329 (clobber (reg:DI MMIX_rR_REGNUM))])]
bcf684c7
HPN
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"
68e87fc9 336 [(set (match_operand:DI 0 "register_operand" "=&r,&r")
bcf684c7
HPN
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"))
34116c2a
HPN
340 (clobber (match_scratch:DI 4 "=2,2"))
341 (clobber (reg:DI MMIX_rR_REGNUM))]
bcf684c7
HPN
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\;\
346DIVU %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))
34116c2a
HPN
354 (clobber (scratch:DI))
355 (clobber (reg:DI MMIX_rR_REGNUM))])]
bcf684c7
HPN
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"
68e87fc9 362 [(set (match_operand:DI 0 "register_operand" "=&r,&r")
bcf684c7
HPN
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"))
34116c2a
HPN
366 (clobber (match_scratch:DI 4 "=2,2"))
367 (clobber (reg:DI MMIX_rR_REGNUM))]
bcf684c7
HPN
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\;\
372DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
373\f
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
bcf684c7 404(define_expand "negdf2"
6ee3db61
HPN
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"
bcf684c7 415 [(set (match_operand:DF 0 "register_operand" "=r")
6ee3db61
HPN
416 (neg:DF (match_operand:DF 1 "register_operand" "r")))
417 (use (match_operand:DI 2 "register_operand" "r"))]
bcf684c7 418 ""
6ee3db61 419 "XOR %0,%1,%2")
bcf684c7
HPN
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\f
bcf684c7
HPN
443;; When the user-patterns expand, the resulting insns will match the
444;; patterns below.
445
446;; We can fold the signed-compare where the register value is
447;; already equal to (compare:CCTYPE (reg) (const_int 0)).
448;; We can't do that at all for floating-point, due to NaN, +0.0
449;; and -0.0, and we can only do it for the non/zero test of
450;; unsigned, so that has to be done another way.
451;; FIXME: Perhaps a peep2 changing CCcode to a new code, that
452;; gets folded here.
f90b7a5a 453(define_insn "*cmpdi_folded"
bcf684c7
HPN
454 [(set (match_operand:CC 0 "register_operand" "=r")
455 (compare:CC
456 (match_operand:DI 1 "register_operand" "r")
457 (const_int 0)))]
458 ;; FIXME: Can we test equivalence any other way?
459 ;; FIXME: Can we fold any other way?
ab3e1ef6
HPN
460 "REG_P (operands[0]) && REG_P (operands[1])
461 && REGNO (operands[1]) == REGNO (operands[0])"
bcf684c7
HPN
462 "%% folded: cmp %0,%1,0")
463
f90b7a5a 464(define_insn "*cmps"
bcf684c7
HPN
465 [(set (match_operand:CC 0 "register_operand" "=r")
466 (compare:CC
467 (match_operand:DI 1 "register_operand" "r")
468 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
469 ""
470 "CMP %0,%1,%2")
471
472(define_insn "*cmpu"
473 [(set (match_operand:CC_UNS 0 "register_operand" "=r")
474 (compare:CC_UNS
475 (match_operand:DI 1 "register_operand" "r")
476 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
477 ""
478 "CMPU %0,%1,%2")
479
480(define_insn "*fcmp"
481 [(set (match_operand:CC_FP 0 "register_operand" "=r")
482 (compare:CC_FP
483 (match_operand:DF 1 "register_operand" "r")
484 (match_operand:DF 2 "register_operand" "r")))]
485 ""
486 "FCMP%e0 %0,%1,%2")
487
488;; FIXME: for -mieee, add fsub %0,%1,%1\;fsub %0,%2,%2 before to
489;; make signalling compliant.
490(define_insn "*feql"
491 [(set (match_operand:CC_FPEQ 0 "register_operand" "=r")
492 (compare:CC_FPEQ
493 (match_operand:DF 1 "register_operand" "r")
494 (match_operand:DF 2 "register_operand" "r")))]
495 ""
496 "FEQL%e0 %0,%1,%2")
497
498(define_insn "*fun"
499 [(set (match_operand:CC_FUN 0 "register_operand" "=r")
500 (compare:CC_FUN
501 (match_operand:DF 1 "register_operand" "r")
502 (match_operand:DF 2 "register_operand" "r")))]
503 ""
504 "FUN%e0 %0,%1,%2")
505\f
506;; In order to get correct rounding, we have to use SFLOT and SFLOTU for
507;; conversion. They do not convert to SFmode; they convert to DFmode,
508;; with rounding as of SFmode. They are not usable as is, but we pretend
509;; we have a single instruction but emit two.
510
511;; Note that this will (somewhat unexpectedly) create an inexact
512;; exception if rounding is necessary - has to be masked off in crt0?
513(define_expand "floatdisf2"
514 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
515 (float:SF
516 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
517 ;; Let's use a DI scratch, since SF don't generally get into
518 ;; registers. Dunno what's best; it's really a DF, but that
519 ;; doesn't logically follow from operands in the pattern.
520 (clobber (match_scratch:DI 2 "=&r"))])]
521 ""
522 "
523{
524 if (GET_CODE (operands[0]) != MEM)
525 {
526 rtx stack_slot;
527
528 /* FIXME: This stack-slot remains even at -O3. There must be a
529 better way. */
530 stack_slot
531 = validize_mem (assign_stack_temp (SFmode,
9474e8ab 532 GET_MODE_SIZE (SFmode)));
bcf684c7
HPN
533 emit_insn (gen_floatdisf2 (stack_slot, operands[1]));
534 emit_move_insn (operands[0], stack_slot);
535 DONE;
536 }
537}")
538
539(define_insn "*floatdisf2_real"
540 [(set (match_operand:SF 0 "memory_operand" "=m")
541 (float:SF
542 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
543 (clobber (match_scratch:DI 2 "=&r"))]
544 ""
545 "SFLOT %2,%1\;STSF %2,%0")
546
547(define_expand "floatunsdisf2"
548 [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
549 (unsigned_float:SF
550 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
551 ;; Let's use a DI scratch, since SF don't generally get into
552 ;; registers. Dunno what's best; it's really a DF, but that
553 ;; doesn't logically follow from operands in the pattern.
554 (clobber (scratch:DI))])]
555 ""
556 "
557{
558 if (GET_CODE (operands[0]) != MEM)
559 {
560 rtx stack_slot;
561
562 /* FIXME: This stack-slot remains even at -O3. Must be a better
563 way. */
564 stack_slot
565 = validize_mem (assign_stack_temp (SFmode,
9474e8ab 566 GET_MODE_SIZE (SFmode)));
bcf684c7
HPN
567 emit_insn (gen_floatunsdisf2 (stack_slot, operands[1]));
568 emit_move_insn (operands[0], stack_slot);
569 DONE;
570 }
571}")
572
573(define_insn "*floatunsdisf2_real"
574 [(set (match_operand:SF 0 "memory_operand" "=m")
575 (unsigned_float:SF
576 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))
577 (clobber (match_scratch:DI 2 "=&r"))]
578 ""
579 "SFLOTU %2,%1\;STSF %2,%0")
580
581;; Note that this will (somewhat unexpectedly) create an inexact
582;; exception if rounding is necessary - has to be masked off in crt0?
583(define_insn "floatdidf2"
584 [(set (match_operand:DF 0 "register_operand" "=r")
585 (float:DF
586 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
587 ""
588 "FLOT %0,%1")
589
590(define_insn "floatunsdidf2"
591 [(set (match_operand:DF 0 "register_operand" "=r")
592 (unsigned_float:DF
593 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")))]
594 ""
595 "FLOTU %0,%1")
596
597(define_insn "ftruncdf2"
598 [(set (match_operand:DF 0 "register_operand" "=r")
599 (fix:DF (match_operand:DF 1 "register_operand" "r")))]
600 ""
601 ;; ROUND_OFF
602 "FINT %0,1,%1")
603
604;; Note that this will (somewhat unexpectedly) create an inexact
605;; exception if rounding is necessary - has to be masked off in crt0?
606(define_insn "fix_truncdfdi2"
607 [(set (match_operand:DI 0 "register_operand" "=r")
608 (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
609 ""
610 ;; ROUND_OFF
611 "FIX %0,1,%1")
612
613(define_insn "fixuns_truncdfdi2"
614 [(set (match_operand:DI 0 "register_operand" "=r")
615 (unsigned_fix:DI
7e5037dc 616 (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
bcf684c7
HPN
617 ""
618 ;; ROUND_OFF
619 "FIXU %0,1,%1")
620
621;; It doesn't seem like it's possible to have memory_operand as a
622;; predicate here (testcase: libgcc2 floathisf). FIXME: Shouldn't it be
623;; possible to do that? Bug in GCC? Anyway, this used to be a simple
624;; pattern with a memory_operand predicate, but was split up with a
625;; define_expand with the old pattern as "anonymous".
f15643d4 626;; FIXME: Perhaps with TARGET_SECONDARY_MEMORY_NEEDED?
bcf684c7 627(define_expand "truncdfsf2"
11494830
HPN
628 [(set (match_operand:SF 0 "nonimmediate_operand")
629 (float_truncate:SF (match_operand:DF 1 "register_operand")))]
bcf684c7
HPN
630 ""
631 "
632{
633 if (GET_CODE (operands[0]) != MEM)
634 {
635 /* FIXME: There should be a way to say: 'put this in operands[0]
636 but *after* the expanded insn'. */
637 rtx stack_slot;
638
639 /* There is no sane destination but a register here, if it wasn't
640 already MEM. (It's too hard to get fatal_insn to work here.) */
641 if (! REG_P (operands[0]))
642 internal_error (\"MMIX Internal: Bad truncdfsf2 expansion\");
643
644 /* FIXME: This stack-slot remains even at -O3. Must be a better
645 way. */
646 stack_slot
647 = validize_mem (assign_stack_temp (SFmode,
9474e8ab 648 GET_MODE_SIZE (SFmode)));
bcf684c7
HPN
649 emit_insn (gen_truncdfsf2 (stack_slot, operands[1]));
650 emit_move_insn (operands[0], stack_slot);
651 DONE;
652 }
653}")
654
655(define_insn "*truncdfsf2_real"
656 [(set (match_operand:SF 0 "memory_operand" "=m")
ba82f58b 657 (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
bcf684c7
HPN
658 ""
659 "STSF %1,%0")
660
661;; Same comment as for truncdfsf2.
662(define_expand "extendsfdf2"
11494830
HPN
663 [(set (match_operand:DF 0 "register_operand")
664 (float_extend:DF (match_operand:SF 1 "nonimmediate_operand")))]
bcf684c7
HPN
665 ""
666 "
667{
668 if (GET_CODE (operands[1]) != MEM)
669 {
670 rtx stack_slot;
671
672 /* There is no sane destination but a register here, if it wasn't
673 already MEM. (It's too hard to get fatal_insn to work here.) */
674 if (! REG_P (operands[0]))
675 internal_error (\"MMIX Internal: Bad extendsfdf2 expansion\");
676
677 /* FIXME: This stack-slot remains even at -O3. There must be a
678 better way. */
679 stack_slot
680 = validize_mem (assign_stack_temp (SFmode,
9474e8ab 681 GET_MODE_SIZE (SFmode)));
bcf684c7
HPN
682 emit_move_insn (stack_slot, operands[1]);
683 emit_insn (gen_extendsfdf2 (operands[0], stack_slot));
684 DONE;
685 }
686}")
687
688(define_insn "*extendsfdf2_real"
689 [(set (match_operand:DF 0 "register_operand" "=r")
690 (float_extend:DF (match_operand:SF 1 "memory_operand" "m")))]
691 ""
692 "LDSF %0,%1")
693\f
694;; Neither sign-extend nor zero-extend are necessary; gcc knows how to
695;; synthesize using shifts or and, except with a memory source and not
696;; completely optimal. FIXME: Actually, other bugs surface when those
697;; patterns are defined; fix later.
698
699;; There are no sane values with the bit-patterns of (int) 0..255 except
700;; 0 to use in movdfcc.
701
702(define_expand "movdfcc"
f90b7a5a
PB
703 [(set (match_dup 4) (match_dup 5))
704 (set (match_operand:DF 0 "register_operand" "")
bcf684c7
HPN
705 (if_then_else:DF
706 (match_operand 1 "comparison_operator" "")
707 (match_operand:DF 2 "mmix_reg_or_0_operand" "")
708 (match_operand:DF 3 "mmix_reg_or_0_operand" "")))]
709 ""
710 "
711{
712 enum rtx_code code = GET_CODE (operands[1]);
f90b7a5a 713 if (code == LE || code == GE)
bcf684c7 714 FAIL;
f90b7a5a
PB
715
716 operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0),
717 XEXP (operands[1], 1));
718 operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]),
719 XEXP (operands[1], 0),
720 XEXP (operands[1], 1));
721 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
bcf684c7
HPN
722}")
723
724(define_expand "movdicc"
f90b7a5a
PB
725 [(set (match_dup 4) (match_dup 5))
726 (set (match_operand:DI 0 "register_operand" "")
bcf684c7
HPN
727 (if_then_else:DI
728 (match_operand 1 "comparison_operator" "")
729 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")
730 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "")))]
731 ""
732 "
733{
734 enum rtx_code code = GET_CODE (operands[1]);
f90b7a5a 735 if (code == LE || code == GE)
bcf684c7 736 FAIL;
f90b7a5a
PB
737
738 operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0),
739 XEXP (operands[1], 1));
740 operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]),
741 XEXP (operands[1], 0),
742 XEXP (operands[1], 1));
743 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
bcf684c7
HPN
744}")
745
746;; FIXME: Is this the right way to do "folding" of CCmode -> DImode?
747(define_insn "*movdicc_real_foldable"
748 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
749 (if_then_else:DI
750 (match_operator 2 "mmix_foldable_comparison_operator"
f972cae4 751 [(match_operand:DI 3 "register_operand" "r,r,r,r")
bcf684c7 752 (const_int 0)])
91312b81
HPN
753 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
754 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
bcf684c7
HPN
755 ""
756 "@
757 CS%d2 %0,%3,%1
758 CS%D2 %0,%3,%4
759 ZS%d2 %0,%3,%1
760 ZS%D2 %0,%3,%4")
761
69ffa7aa 762(define_insn "*movdicc_real_reversible"
bcf684c7 763 [(set
91312b81 764 (match_operand:DI 0 "register_operand" "=r ,r ,r ,r")
bcf684c7
HPN
765 (if_then_else:DI
766 (match_operator
767 2 "mmix_comparison_operator"
91312b81 768 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
bcf684c7 769 (const_int 0)])
91312b81
HPN
770 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
771 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
69ffa7aa 772 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
bcf684c7
HPN
773 "@
774 CS%d2 %0,%3,%1
775 CS%D2 %0,%3,%4
776 ZS%d2 %0,%3,%1
777 ZS%D2 %0,%3,%4")
778
69ffa7aa
HPN
779(define_insn "*movdicc_real_nonreversible"
780 [(set
781 (match_operand:DI 0 "register_operand" "=r ,r")
782 (if_then_else:DI
783 (match_operator
784 2 "mmix_comparison_operator"
785 [(match_operand 3 "mmix_reg_cc_operand" "r ,r")
786 (const_int 0)])
787 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,rI")
788 (match_operand:DI 4 "mmix_reg_or_0_operand" "0 ,GM")))]
789 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
790 "@
791 CS%d2 %0,%3,%1
792 ZS%d2 %0,%3,%1")
793
bcf684c7
HPN
794(define_insn "*movdfcc_real_foldable"
795 [(set
796 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
797 (if_then_else:DF
798 (match_operator
799 2 "mmix_foldable_comparison_operator"
f972cae4 800 [(match_operand:DI 3 "register_operand" "r ,r ,r ,r")
bcf684c7
HPN
801 (const_int 0)])
802 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
803 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
804 ""
805 "@
806 CS%d2 %0,%3,%1
807 CS%D2 %0,%3,%4
808 ZS%d2 %0,%3,%1
809 ZS%D2 %0,%3,%4")
810
69ffa7aa 811(define_insn "*movdfcc_real_reversible"
bcf684c7
HPN
812 [(set
813 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
814 (if_then_else:DF
815 (match_operator
816 2 "mmix_comparison_operator"
817 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
818 (const_int 0)])
819 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
820 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
69ffa7aa 821 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
bcf684c7
HPN
822 "@
823 CS%d2 %0,%3,%1
824 CS%D2 %0,%3,%4
825 ZS%d2 %0,%3,%1
826 ZS%D2 %0,%3,%4")
827
69ffa7aa
HPN
828(define_insn "*movdfcc_real_nonreversible"
829 [(set
830 (match_operand:DF 0 "register_operand" "=r ,r")
831 (if_then_else:DF
832 (match_operator
833 2 "mmix_comparison_operator"
834 [(match_operand 3 "mmix_reg_cc_operand" "r ,r")
835 (const_int 0)])
836 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,rGM")
837 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,GM")))]
838 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
839 "@
840 CS%d2 %0,%3,%1
841 ZS%d2 %0,%3,%1")
842
f90b7a5a 843;; FIXME: scc insns will probably help, I just skip them
bcf684c7
HPN
844;; right now. Revisit.
845\f
f90b7a5a
PB
846(define_expand "cbranchdi4"
847 [(set (match_dup 4)
848 (match_op_dup 5
849 [(match_operand:DI 1 "register_operand" "")
850 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")]))
851 (set (pc)
852 (if_then_else
853 (match_operator 0 "ordered_comparison_operator"
854 [(match_dup 4)
855 (const_int 0)])
856 (label_ref (match_operand 3 "" ""))
857 (pc)))]
bcf684c7
HPN
858 ""
859 "
860{
f90b7a5a
PB
861 operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]),
862 operands[1], operands[2]);
863 operands[5] = gen_rtx_fmt_ee (COMPARE,
864 GET_MODE (operands[4]),
865 operands[1], operands[2]);
bcf684c7
HPN
866}")
867
f90b7a5a
PB
868(define_expand "cbranchdf4"
869 [(set (match_dup 4)
870 (match_op_dup 5
871 [(match_operand:DF 1 "register_operand" "")
872 (match_operand:DF 2 "register_operand" "")]))
873 (set (pc)
874 (if_then_else
875 (match_operator 0 "float_comparison_operator"
876 [(match_dup 4)
877 (const_int 0)])
878 (label_ref (match_operand 3 "" ""))
879 (pc)))]
bcf684c7
HPN
880 ""
881 "
882{
bcf684c7 883 /* The head comment of optabs.c:can_compare_p says we're required to
ff482c8d 884 implement this, so we have to clean up the mess here. */
f90b7a5a 885 if (GET_CODE (operands[0]) == LE || GET_CODE (operands[0]) == GE)
bcf684c7 886 {
f90b7a5a
PB
887 enum rtx_code ltgt_code = GET_CODE (operands[0]) == LE ? LT : GT;
888 emit_cmp_and_jump_insns (operands[1], operands[2], ltgt_code, NULL_RTX,
889 DFmode, 0, operands[3]);
890 emit_cmp_and_jump_insns (operands[1], operands[2], EQ, NULL_RTX,
891 DFmode, 0, operands[3]);
bcf684c7
HPN
892 DONE;
893 }
bcf684c7 894
f90b7a5a
PB
895 operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]),
896 operands[1], operands[2]);
897 operands[5] = gen_rtx_fmt_ee (COMPARE,
898 GET_MODE (operands[4]),
899 operands[1], operands[2]);
bcf684c7
HPN
900}")
901
bcf684c7
HPN
902
903;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but
904;; there's no RTL code for it. Maybe revisit in future.
905
bcf684c7
HPN
906;; FIXME: Odd/Even matchers?
907(define_insn "*bCC_foldable"
908 [(set (pc)
909 (if_then_else
910 (match_operator 1 "mmix_foldable_comparison_operator"
f972cae4 911 [(match_operand:DI 2 "register_operand" "r")
bcf684c7
HPN
912 (const_int 0)])
913 (label_ref (match_operand 0 "" ""))
914 (pc)))]
915 ""
91312b81 916 "%+B%d1 %2,%0")
bcf684c7
HPN
917
918(define_insn "*bCC"
919 [(set (pc)
920 (if_then_else
921 (match_operator 1 "mmix_comparison_operator"
922 [(match_operand 2 "mmix_reg_cc_operand" "r")
923 (const_int 0)])
924 (label_ref (match_operand 0 "" ""))
925 (pc)))]
926 ""
91312b81 927 "%+B%d1 %2,%0")
bcf684c7
HPN
928
929(define_insn "*bCC_inverted_foldable"
930 [(set (pc)
931 (if_then_else
932 (match_operator 1 "mmix_foldable_comparison_operator"
f972cae4 933 [(match_operand:DI 2 "register_operand" "r")
bcf684c7
HPN
934 (const_int 0)])
935 (pc)
936 (label_ref (match_operand 0 "" ""))))]
937;; REVERSIBLE_CC_MODE is checked by mmix_foldable_comparison_operator.
938 ""
91312b81 939 "%+B%D1 %2,%0")
bcf684c7
HPN
940
941(define_insn "*bCC_inverted"
942 [(set (pc)
943 (if_then_else
944 (match_operator 1 "mmix_comparison_operator"
945 [(match_operand 2 "mmix_reg_cc_operand" "r")
946 (const_int 0)])
947 (pc)
948 (label_ref (match_operand 0 "" ""))))]
949 "REVERSIBLE_CC_MODE (GET_MODE (operands[2]))"
91312b81 950 "%+B%D1 %2,%0")
bcf684c7
HPN
951\f
952(define_expand "call"
953 [(parallel [(call (match_operand:QI 0 "memory_operand" "")
954 (match_operand 1 "general_operand" ""))
955 (use (match_operand 2 "general_operand" ""))
956 (clobber (match_dup 4))])
957 (set (match_dup 4) (match_dup 3))]
958 ""
959 "
960{
cc73528f
HPN
961 /* The caller checks that the operand is generally valid as an
962 address, but at -O0 nothing makes sure that it's also a valid
963 call address for a *call*; a mmix_symbolic_or_address_operand.
964 Force into a register if it isn't. */
965 if (!mmix_symbolic_or_address_operand (XEXP (operands[0], 0),
966 GET_MODE (XEXP (operands[0], 0))))
967 operands[0]
968 = replace_equiv_address (operands[0],
969 force_reg (Pmode, XEXP (operands[0], 0)));
970
bcf684c7
HPN
971 /* Since the epilogue 'uses' the return address, and it is clobbered
972 in the call, and we set it back after every call (all but one setting
973 will be optimized away), integrity is maintained. */
974 operands[3]
957ec0f9
HPN
975 = mmix_get_hard_reg_initial_val (Pmode,
976 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
bcf684c7
HPN
977
978 /* FIXME: There's a bug in gcc which causes NULL to be passed as
979 operand[2] when we get out of registers, which later confuses gcc.
980 Work around it by replacing it with const_int 0. Possibly documentation
981 error too. */
982 if (operands[2] == NULL_RTX)
983 operands[2] = const0_rtx;
3e0f61ac 984
bcf684c7
HPN
985 operands[4] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
986}")
987
988(define_expand "call_value"
989 [(parallel [(set (match_operand 0 "" "")
990 (call (match_operand:QI 1 "memory_operand" "")
991 (match_operand 2 "general_operand" "")))
992 (use (match_operand 3 "general_operand" ""))
993 (clobber (match_dup 5))])
994 (set (match_dup 5) (match_dup 4))]
995 ""
996 "
997{
cc73528f
HPN
998 /* The caller checks that the operand is generally valid as an
999 address, but at -O0 nothing makes sure that it's also a valid
1000 call address for a *call*; a mmix_symbolic_or_address_operand.
1001 Force into a register if it isn't. */
1002 if (!mmix_symbolic_or_address_operand (XEXP (operands[1], 0),
1003 GET_MODE (XEXP (operands[1], 0))))
1004 operands[1]
1005 = replace_equiv_address (operands[1],
1006 force_reg (Pmode, XEXP (operands[1], 0)));
1007
bcf684c7
HPN
1008 /* Since the epilogue 'uses' the return address, and it is clobbered
1009 in the call, and we set it back after every call (all but one setting
1010 will be optimized away), integrity is maintained. */
1011 operands[4]
957ec0f9
HPN
1012 = mmix_get_hard_reg_initial_val (Pmode,
1013 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
bcf684c7
HPN
1014
1015 /* FIXME: See 'call'. */
1016 if (operands[3] == NULL_RTX)
1017 operands[3] = const0_rtx;
1018
1019 /* FIXME: Documentation bug: operands[3] (operands[2] for 'call') is the
07338cf8
HPN
1020 *next* argument register, not the number of arguments in registers.
1021 (There used to be code here where that mattered.) */
bcf684c7
HPN
1022
1023 operands[5] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1024}")
1025
1026;; Don't use 'p' here. A 'p' must stand first in constraints, or reload
1027;; messes up, not registering the address for reload. Several C++
109b748d 1028;; testcases, including g++.brendan/crash40.C. FIXME: This is arguably a
bcf684c7
HPN
1029;; bug in gcc. Note line ~2612 in reload.c, that does things on the
1030;; condition <<else if (constraints[i][0] == 'p')>> and the comment on
1031;; ~3017 that says:
1032;; << case 'p':
1033;; /* All necessary reloads for an address_operand
1034;; were handled in find_reloads_address. */>>
1035;; Sorry, I have not dug deeper. If symbolic addresses are used
1036;; rarely compared to addresses in registers, disparaging the
1037;; first ("p") alternative by adding ? in the first operand
1038;; might do the trick. We define 'U' as a synonym to 'p', but without the
e9fef64c 1039;; caveats (and very small advantages) of 'p'.
e076319b 1040;; As of r190682 still so: newlib/libc/stdlib/dtoa.c ICEs if "p" is used.
bcf684c7
HPN
1041(define_insn "*call_real"
1042 [(call (mem:QI
1043 (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU"))
1044 (match_operand 1 "" ""))
1045 (use (match_operand 2 "" ""))
91312b81 1046 (clobber (reg:DI MMIX_rJ_REGNUM))]
bcf684c7
HPN
1047 ""
1048 "@
1049 PUSHJ $%p2,%0
1050 PUSHGO $%p2,%a0")
1051
1052(define_insn "*call_value_real"
1053 [(set (match_operand 0 "register_operand" "=r,r")
1054 (call (mem:QI
1055 (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU"))
1056 (match_operand 2 "" "")))
1057 (use (match_operand 3 "" ""))
91312b81 1058 (clobber (reg:DI MMIX_rJ_REGNUM))]
bcf684c7
HPN
1059 ""
1060 "@
1061 PUSHJ $%p3,%1
1062 PUSHGO $%p3,%a1")
1063
1064;; I hope untyped_call and untyped_return are not needed for MMIX.
43a88a8c 1065;; Users of Objective-C will notice.
bcf684c7 1066
957ec0f9
HPN
1067; Generated by GCC.
1068(define_expand "return"
66b8c57f
HPN
1069 [(return)]
1070 "mmix_use_simple_return ()"
957ec0f9
HPN
1071 "")
1072
1073; Generated by the epilogue expander.
1074(define_insn "*expanded_return"
1075 [(return)]
1076 ""
66b8c57f 1077 "POP %.,0")
bcf684c7 1078
957ec0f9
HPN
1079(define_expand "prologue"
1080 [(const_int 0)]
1081 ""
1082 "mmix_expand_prologue (); DONE;")
1083
1084; Note that the (return) from the expander itself is always the last insn
1085; in the epilogue.
1086(define_expand "epilogue"
1087 [(return)]
1088 ""
1089 "mmix_expand_epilogue ();")
1090
bcf684c7
HPN
1091(define_insn "nop"
1092 [(const_int 0)]
1093 ""
1094 "SWYM 0,0,0")
1095
1096(define_insn "jump"
1097 [(set (pc) (label_ref (match_operand 0 "" "")))]
1098 ""
1099 "JMP %0")
1100
1101(define_insn "indirect_jump"
1102 [(set (pc) (match_operand 0 "address_operand" "p"))]
1103 ""
1104 "GO $255,%a0")
1105
1106;; FIXME: This is just a jump, and should be expanded to one.
1107(define_insn "tablejump"
1108 [(set (pc) (match_operand:DI 0 "address_operand" "p"))
1109 (use (label_ref (match_operand 1 "" "")))]
1110 ""
1111 "GO $255,%a0")
1112
1113;; The only peculiar thing is that the register stack has to be unwound at
1114;; nonlocal_goto_receiver. At each function that has a nonlocal label, we
1115;; save at function entry the location of the "alpha" register stack
f6e89b80 1116;; pointer, rO, in a stack slot known to that function (right below where
bcf684c7
HPN
1117;; the frame-pointer would be located).
1118;; In the nonlocal goto receiver, we unwind the register stack by a series
1119;; of "pop 0,0" until rO equals the saved value. (If it goes lower, we
107a4b41 1120;; should die with a trap.)
bcf684c7 1121(define_expand "nonlocal_goto_receiver"
a271e61c 1122 [(parallel [(unspec_volatile [(match_dup 1)] 1)
bcf684c7 1123 (clobber (scratch:DI))
91312b81 1124 (clobber (reg:DI MMIX_rJ_REGNUM))])
db08fddf 1125 (set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))]
bcf684c7
HPN
1126 ""
1127 "
1128{
db08fddf 1129 operands[0]
957ec0f9
HPN
1130 = mmix_get_hard_reg_initial_val (Pmode,
1131 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
bcf684c7 1132
a271e61c 1133 /* We need the frame-pointer to be live or the equivalent
026c3cfd 1134 expression, so refer to it in the pattern. We can't use a MEM
a271e61c
HPN
1135 (that may contain out-of-range offsets in the final expression)
1136 for fear that middle-end will legitimize it or replace the address
1137 using temporary registers (which are not revived at this point). */
1138 operands[1] = frame_pointer_rtx;
1139
bcf684c7
HPN
1140 /* Mark this function as containing a landing-pad. */
1141 cfun->machine->has_landing_pad = 1;
1142}")
1143
db08fddf
HPN
1144;; GCC can insist on using saved registers to keep the slot address in
1145;; "across" the exception, or (perhaps) to use saved registers in the
1146;; address and re-use them after the register stack unwind, so it's best
1147;; to form the address ourselves.
bcf684c7 1148(define_insn "*nonlocal_goto_receiver_expanded"
a271e61c 1149 [(unspec_volatile [(match_operand:DI 1 "frame_pointer_operand" "Yf")] 1)
db08fddf 1150 (clobber (match_scratch:DI 0 "=&r"))
91312b81 1151 (clobber (reg:DI MMIX_rJ_REGNUM))]
bcf684c7 1152 ""
db08fddf 1153{
a271e61c 1154 rtx my_operands[3];
db08fddf
HPN
1155 const char *my_template
1156 = "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\
11570:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:";
1158
a271e61c
HPN
1159 my_operands[1] = operands[0];
1160 my_operands[2] = GEN_INT (-MMIX_fp_rO_OFFSET);
db08fddf 1161
a271e61c 1162 if (operands[1] == hard_frame_pointer_rtx)
db08fddf 1163 {
a271e61c
HPN
1164 mmix_output_register_setting (asm_out_file, REGNO (operands[0]),
1165 MMIX_fp_rO_OFFSET, 1);
1166 my_operands[0]
1167 = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, operands[0]);
db08fddf
HPN
1168 }
1169 else
1170 {
a9243bfc 1171 int64_t offs = INTVAL (XEXP (operands[1], 1));
a271e61c 1172 offs += MMIX_fp_rO_OFFSET;
db08fddf 1173
a271e61c 1174 if (insn_const_int_ok_for_constraint (offs, CONSTRAINT_I))
db08fddf
HPN
1175 my_operands[0]
1176 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs));
1177 else
1178 {
a271e61c 1179 mmix_output_register_setting (asm_out_file, REGNO (operands[0]),
db08fddf 1180 offs, 1);
a271e61c
HPN
1181 my_operands[0]
1182 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, operands[0]);
db08fddf
HPN
1183 }
1184 }
1185
1186 output_asm_insn (my_template, my_operands);
1187 return "";
1188})
bcf684c7
HPN
1189\f
1190(define_insn "*Naddu"
1191 [(set (match_operand:DI 0 "register_operand" "=r")
1192 (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r")
1193 (match_operand:DI 2 "const_int_operand" "n"))
f6e89b80 1194 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))]
bcf684c7
HPN
1195 "GET_CODE (operands[2]) == CONST_INT
1196 && (INTVAL (operands[2]) == 2
1197 || INTVAL (operands[2]) == 4
1198 || INTVAL (operands[2]) == 8
1199 || INTVAL (operands[2]) == 16)"
1200 "%2ADDU %0,%1,%3")
1201
1202(define_insn "*andn"
1203 [(set (match_operand:DI 0 "register_operand" "=r")
1204 (and:DI
1205 (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))
1206 (match_operand:DI 2 "register_operand" "r")))]
1207 ""
1208 "ANDN %0,%2,%1")
1209
1210(define_insn "*nand"
1211 [(set (match_operand:DI 0 "register_operand" "=r")
1212 (ior:DI
1213 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1214 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1215 ""
1216 "NAND %0,%1,%2")
1217
1218(define_insn "*nor"
1219 [(set (match_operand:DI 0 "register_operand" "=r")
1220 (and:DI
1221 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1222 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1223 ""
1224 "NOR %0,%1,%2")
1225
1226(define_insn "*nxor"
1227 [(set (match_operand:DI 0 "register_operand" "=r")
1228 (not:DI
1229 (xor:DI (match_operand:DI 1 "register_operand" "%r")
1230 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1231 ""
1232 "NXOR %0,%1,%2")
1233
1234(define_insn "sync_icache"
1235 [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")
1236 (match_operand:DI 1 "const_int_operand" "I")] 0)]
1237 ""
1238 "SYNCID %1,%0")
1239
1240;; Local Variables:
1241;; mode: lisp
1242;; indent-tabs-mode: t
1243;; End: