]> 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
99dee823 2;; Copyright (C) 2000-2021 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)
11b8ffa4
HPN
41
42(define_mode_iterator MM [QI HI SI DI SF DF])
cc73528f
HPN
43\f
44;; Operand and operator predicates.
bcf684c7 45
cc73528f 46(include "predicates.md")
e076319b 47(include "constraints.md")
cc73528f 48\f
bcf684c7
HPN
49;; FIXME: Can we remove the reg-to-reg for smaller modes? Shouldn't they
50;; be synthesized ok?
11b8ffa4
HPN
51(define_expand "mov<mode>"
52 [(set (match_operand:MM 0 "nonimmediate_operand")
53 (match_operand:MM 1 "general_operand"))]
54 ""
55{
56 /* Help pre-register-allocation to use at least one register in a move.
57 FIXME: support STCO also for DFmode (storing 0.0). */
58 if (!REG_P (operands[0]) && !REG_P (operands[1])
59 && (<MODE>mode != DImode
60 || !memory_operand (operands[0], DImode)
61 || !satisfies_constraint_I (operands[1])))
62 operands[1] = force_reg (<MODE>mode, operands[1]);
63})
64
65(define_insn "*movqi_expanded"
91312b81
HPN
66 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r ,r,x ,r,r,m,??r")
67 (match_operand:QI 1 "general_operand" "r,LS,K,rI,x,m,r,n"))]
11b8ffa4
HPN
68 "register_operand (operands[0], QImode)
69 || register_operand (operands[1], QImode)"
bcf684c7
HPN
70 "@
71 SET %0,%1
72 %s1 %0,%v1
73 NEGU %0,0,%n1
74 PUT %0,%1
75 GET %0,%1
76 LDB%U0 %0,%1
77 STBU %1,%0
78 %r0%I1")
79
11b8ffa4 80(define_insn "*movhi_expanded"
bcf684c7
HPN
81 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,x,r,r,m,??r")
82 (match_operand:HI 1 "general_operand" "r,LS,K,r,x,m,r,n"))]
11b8ffa4
HPN
83 "register_operand (operands[0], HImode)
84 || register_operand (operands[1], HImode)"
bcf684c7
HPN
85 "@
86 SET %0,%1
87 %s1 %0,%v1
88 NEGU %0,0,%n1
89 PUT %0,%1
90 GET %0,%1
91 LDW%U0 %0,%1
92 STWU %1,%0
93 %r0%I1")
94
95;; gcc.c-torture/compile/920428-2.c fails if there's no "n".
11b8ffa4 96(define_insn "*movsi_expanded"
91312b81 97 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r ,r,x,r,r,m,??r")
bcf684c7 98 (match_operand:SI 1 "general_operand" "r,LS,K,r,x,m,r,n"))]
11b8ffa4
HPN
99 "register_operand (operands[0], SImode)
100 || register_operand (operands[1], SImode)"
bcf684c7
HPN
101 "@
102 SET %0,%1
103 %s1 %0,%v1
104 NEGU %0,0,%n1
105 PUT %0,%1
106 GET %0,%1
107 LDT%U0 %0,%1
108 STTU %1,%0
109 %r0%I1")
110
111;; We assume all "s" are addresses. Does that hold?
11b8ffa4 112(define_insn "*movdi_expanded"
a824924d
HPN
113 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r")
114 (match_operand:DI 1 "general_operand" "r,LS,K,r,x,I,m,r,R,s,n"))]
11b8ffa4
HPN
115 "register_operand (operands[0], DImode)
116 || register_operand (operands[1], DImode)
117 || (memory_operand (operands[0], DImode)
118 && satisfies_constraint_I (operands[1]))"
bcf684c7
HPN
119 "@
120 SET %0,%1
121 %s1 %0,%v1
122 NEGU %0,0,%n1
123 PUT %0,%1
124 GET %0,%1
125 STCO %1,%0
126 LDO %0,%1
127 STOU %1,%0
128 GETA %0,%1
a824924d 129 LDA %0,%1
bcf684c7
HPN
130 %r0%I1")
131
132;; Note that we move around the float as a collection of bits; no
133;; conversion to double.
11b8ffa4 134(define_insn "*movsf_expanded"
bcf684c7
HPN
135 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
136 (match_operand:SF 1 "general_operand" "r,G,r,x,m,r,F"))]
11b8ffa4
HPN
137 "register_operand (operands[0], SFmode)
138 || register_operand (operands[1], SFmode)"
bcf684c7
HPN
139 "@
140 SET %0,%1
141 SETL %0,0
142 PUT %0,%1
143 GET %0,%1
144 LDT %0,%1
145 STTU %1,%0
146 %r0%I1")
147
11b8ffa4 148(define_insn "*movdf_expanded"
bcf684c7
HPN
149 [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
150 (match_operand:DF 1 "general_operand" "r,G,r,x,m,r,F"))]
11b8ffa4
HPN
151 "register_operand (operands[0], DFmode)
152 || register_operand (operands[1], DFmode)"
bcf684c7
HPN
153 "@
154 SET %0,%1
155 SETL %0,0
156 PUT %0,%1
157 GET %0,%1
158 LDO %0,%1
159 STOU %1,%0
160 %r0%I1")
161\f
2b18b49b
HPN
162;; We need to be able to move around the values used as condition codes.
163;; First spotted as reported in
164;; <URL:http://gcc.gnu.org/ml/gcc-bugs/2003-03/msg00008.html> due to
165;; changes in loop optimization. The file machmode.def says they're of
166;; size 4 QI. Valid bit-patterns correspond to integers -1, 0 and 1, so
167;; we treat them as signed entities; see mmix-modes.def. The following
168;; expanders should cover all MODE_CC modes, and expand for this pattern.
169(define_insn "*movcc_expanded"
73ba39fc
HPN
170 [(set (match_operand 0 "nonimmediate_operand" "=r,x,r,r,m")
171 (match_operand 1 "nonimmediate_operand" "r,r,x,m,r"))]
2b18b49b
HPN
172 "GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_CC
173 && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_CC"
174 "@
175 SET %0,%1
73ba39fc
HPN
176 PUT %0,%1
177 GET %0,%1
2b18b49b
HPN
178 LDT %0,%1
179 STT %1,%0")
180
181(define_expand "movcc"
182 [(set (match_operand:CC 0 "nonimmediate_operand" "")
183 (match_operand:CC 1 "nonimmediate_operand" ""))]
184 ""
185 "")
186
187(define_expand "movcc_uns"
188 [(set (match_operand:CC_UNS 0 "nonimmediate_operand" "")
189 (match_operand:CC_UNS 1 "nonimmediate_operand" ""))]
190 ""
191 "")
192
193(define_expand "movcc_fp"
194 [(set (match_operand:CC_FP 0 "nonimmediate_operand" "")
195 (match_operand:CC_FP 1 "nonimmediate_operand" ""))]
196 ""
197 "")
198
199(define_expand "movcc_fpeq"
200 [(set (match_operand:CC_FPEQ 0 "nonimmediate_operand" "")
201 (match_operand:CC_FPEQ 1 "nonimmediate_operand" ""))]
202 ""
203 "")
204
205(define_expand "movcc_fun"
206 [(set (match_operand:CC_FUN 0 "nonimmediate_operand" "")
207 (match_operand:CC_FUN 1 "nonimmediate_operand" ""))]
208 ""
209 "")
210\f
bcf684c7
HPN
211(define_insn "adddi3"
212 [(set (match_operand:DI 0 "register_operand" "=r,r,r")
213 (plus:DI
214 (match_operand:DI 1 "register_operand" "%r,r,0")
215 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,K,LS")))]
216 ""
217 "@
218 ADDU %0,%1,%2
219 SUBU %0,%1,%n2
220 %i2 %0,%v2")
221
222(define_insn "adddf3"
223 [(set (match_operand:DF 0 "register_operand" "=r")
224 (plus:DF (match_operand:DF 1 "register_operand" "%r")
225 (match_operand:DF 2 "register_operand" "r")))]
226 ""
227 "FADD %0,%1,%2")
228
229;; Insn canonicalization *should* have removed the need for an integer
230;; in operand 2.
231(define_insn "subdi3"
232 [(set (match_operand:DI 0 "register_operand" "=r,r")
233 (minus:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "r,I")
234 (match_operand:DI 2 "register_operand" "r,r")))]
235 ""
236 "@
237 SUBU %0,%1,%2
238 NEGU %0,%1,%2")
239
240(define_insn "subdf3"
241 [(set (match_operand:DF 0 "register_operand" "=r")
242 (minus:DF (match_operand:DF 1 "register_operand" "r")
243 (match_operand:DF 2 "register_operand" "r")))]
244 ""
245 "FSUB %0,%1,%2")
246
247;; FIXME: Should we define_expand and match 2, 4, 8 (etc) with shift (or
248;; %{something}2ADDU %0,%1,0)? Hopefully GCC should still handle it, so
249;; we don't have to taint the machine description. If results are bad
250;; enough, we may have to do it anyway.
251(define_insn "muldi3"
252 [(set (match_operand:DI 0 "register_operand" "=r,r")
253 (mult:DI (match_operand:DI 1 "register_operand" "%r,r")
254 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "O,rI")))
255 (clobber (match_scratch:DI 3 "=X,z"))]
256 ""
257 "@
258 %m2ADDU %0,%1,%1
259 MULU %0,%1,%2")
260
261(define_insn "muldf3"
262 [(set (match_operand:DF 0 "register_operand" "=r")
263 (mult:DF (match_operand:DF 1 "register_operand" "r")
264 (match_operand:DF 2 "register_operand" "r")))]
265 ""
266 "FMUL %0,%1,%2")
267
268(define_insn "divdf3"
269 [(set (match_operand:DF 0 "register_operand" "=r")
270 (div:DF (match_operand:DF 1 "register_operand" "r")
271 (match_operand:DF 2 "register_operand" "r")))]
272 ""
273 "FDIV %0,%1,%2")
274
275;; FIXME: Is "frem" doing the right operation for moddf3?
276(define_insn "moddf3"
277 [(set (match_operand:DF 0 "register_operand" "=r")
278 (mod:DF (match_operand:DF 1 "register_operand" "r")
279 (match_operand:DF 2 "register_operand" "r")))]
280 ""
281 "FREM %0,%1,%2")
282
283;; FIXME: Should we define_expand for smin, smax, umin, umax using a
284;; nifty conditional sequence?
285
286;; FIXME: The cuter andn combinations don't get here, presumably because
287;; they ended up in the constant pool. Check: still?
288(define_insn "anddi3"
289 [(set (match_operand:DI 0 "register_operand" "=r,r")
290 (and:DI
291 (match_operand:DI 1 "register_operand" "%r,0")
292 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,NT")))]
293 ""
294 "@
295 AND %0,%1,%2
296 %A2 %0,%V2")
297
298(define_insn "iordi3"
299 [(set (match_operand:DI 0 "register_operand" "=r,r")
300 (ior:DI (match_operand:DI 1 "register_operand" "%r,0")
e076319b 301 (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,LS")))]
bcf684c7
HPN
302 ""
303 "@
304 OR %0,%1,%2
305 %o2 %0,%v2")
306
307(define_insn "xordi3"
308 [(set (match_operand:DI 0 "register_operand" "=r")
309 (xor:DI (match_operand:DI 1 "register_operand" "%r")
310 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
311 ""
312 "XOR %0,%1,%2")
313\f
314;; FIXME: When TImode works for other reasons (like cross-compiling from
315;; a 32-bit host), add back umulditi3 and umuldi3_highpart here.
316
317;; FIXME: Check what's really reasonable for the mod part.
318
319;; One day we might persuade GCC to expand divisions with constants the
320;; way MMIX does; giving the remainder the sign of the divisor. But even
321;; then, it might be good to have an option to divide the way "everybody
1f2641b6
HPN
322;; else" does. Perhaps then, this option can be on by default. However,
323;; it's not likely to happen because major (C, C++, Fortran) language
324;; standards in effect at 2002-04-29 reportedly demand that the sign of
325;; the remainder must follow the sign of the dividend.
bcf684c7
HPN
326
327(define_insn "divmoddi4"
328 [(set (match_operand:DI 0 "register_operand" "=r")
329 (div:DI (match_operand:DI 1 "register_operand" "r")
330 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
331 (set (match_operand:DI 3 "register_operand" "=y")
332 (mod:DI (match_dup 1) (match_dup 2)))]
333 ;; Do the library stuff later.
334 "TARGET_KNUTH_DIVISION"
335 "DIV %0,%1,%2")
336
337(define_insn "udivmoddi4"
338 [(set (match_operand:DI 0 "register_operand" "=r")
339 (udiv:DI (match_operand:DI 1 "register_operand" "r")
340 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
341 (set (match_operand:DI 3 "register_operand" "=y")
342 (umod:DI (match_dup 1) (match_dup 2)))]
343 ""
344 "DIVU %0,%1,%2")
345
346(define_expand "divdi3"
347 [(parallel
348 [(set (match_operand:DI 0 "register_operand" "=&r")
349 (div:DI (match_operand:DI 1 "register_operand" "r")
350 (match_operand:DI 2 "register_operand" "r")))
351 (clobber (scratch:DI))
34116c2a
HPN
352 (clobber (scratch:DI))
353 (clobber (reg:DI MMIX_rR_REGNUM))])]
bcf684c7
HPN
354 "! TARGET_KNUTH_DIVISION"
355 "")
356
357;; The %2-is-%1-case is there just to make sure things don't fail. Could
358;; presumably happen with optimizations off; no evidence.
359(define_insn "*divdi3_nonknuth"
68e87fc9 360 [(set (match_operand:DI 0 "register_operand" "=&r,&r")
bcf684c7
HPN
361 (div:DI (match_operand:DI 1 "register_operand" "r,r")
362 (match_operand:DI 2 "register_operand" "1,r")))
363 (clobber (match_scratch:DI 3 "=1,1"))
34116c2a
HPN
364 (clobber (match_scratch:DI 4 "=2,2"))
365 (clobber (reg:DI MMIX_rR_REGNUM))]
bcf684c7
HPN
366 "! TARGET_KNUTH_DIVISION"
367 "@
368 SETL %0,1
369 XOR $255,%1,%2\;NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU %0,0,%1\;CSN %1,%1,%0\;\
370DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1")
371
372(define_expand "moddi3"
373 [(parallel
374 [(set (match_operand:DI 0 "register_operand" "=&r")
375 (mod:DI (match_operand:DI 1 "register_operand" "r")
376 (match_operand:DI 2 "register_operand" "r")))
377 (clobber (scratch:DI))
34116c2a
HPN
378 (clobber (scratch:DI))
379 (clobber (reg:DI MMIX_rR_REGNUM))])]
bcf684c7
HPN
380 "! TARGET_KNUTH_DIVISION"
381 "")
382
383;; The %2-is-%1-case is there just to make sure things don't fail. Could
384;; presumably happen with optimizations off; no evidence.
385(define_insn "*moddi3_nonknuth"
68e87fc9 386 [(set (match_operand:DI 0 "register_operand" "=&r,&r")
bcf684c7
HPN
387 (mod:DI (match_operand:DI 1 "register_operand" "r,r")
388 (match_operand:DI 2 "register_operand" "1,r")))
389 (clobber (match_scratch:DI 3 "=1,1"))
34116c2a
HPN
390 (clobber (match_scratch:DI 4 "=2,2"))
391 (clobber (reg:DI MMIX_rR_REGNUM))]
bcf684c7
HPN
392 "! TARGET_KNUTH_DIVISION"
393 "@
394 SETL %0,0
395 NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU $255,0,%1\;CSN %1,%1,$255\;\
396DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
397\f
398(define_insn "ashldi3"
399 [(set (match_operand:DI 0 "register_operand" "=r")
400 (ashift:DI
401 (match_operand:DI 1 "register_operand" "r")
402 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
403 ""
404 "SLU %0,%1,%2")
405
406(define_insn "ashrdi3"
407 [(set (match_operand:DI 0 "register_operand" "=r")
408 (ashiftrt:DI
409 (match_operand:DI 1 "register_operand" "r")
410 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
411 ""
412 "SR %0,%1,%2")
413
414(define_insn "lshrdi3"
415 [(set (match_operand:DI 0 "register_operand" "=r")
416 (lshiftrt:DI
417 (match_operand:DI 1 "register_operand" "r")
418 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
419 ""
420 "SRU %0,%1,%2")
421
422(define_insn "negdi2"
423 [(set (match_operand:DI 0 "register_operand" "=r")
424 (neg:DI (match_operand:DI 1 "register_operand" "r")))]
425 ""
426 "NEGU %0,0,%1")
427
bcf684c7 428(define_expand "negdf2"
6ee3db61
HPN
429 [(parallel [(set (match_operand:DF 0 "register_operand" "=r")
430 (neg:DF (match_operand:DF 1 "register_operand" "r")))
431 (use (match_dup 2))])]
432 ""
433{
434 /* Emit bit-flipping sequence to be IEEE-safe wrt. -+0. */
435 operands[2] = force_reg (DImode, GEN_INT ((HOST_WIDE_INT) 1 << 63));
436})
437
438(define_insn "*expanded_negdf2"
bcf684c7 439 [(set (match_operand:DF 0 "register_operand" "=r")
6ee3db61
HPN
440 (neg:DF (match_operand:DF 1 "register_operand" "r")))
441 (use (match_operand:DI 2 "register_operand" "r"))]
bcf684c7 442 ""
6ee3db61 443 "XOR %0,%1,%2")
bcf684c7
HPN
444
445;; FIXME: define_expand for absdi2?
446
447(define_insn "absdf2"
448 [(set (match_operand:DF 0 "register_operand" "=r")
449 (abs:DF (match_operand:DF 1 "register_operand" "0")))]
450 ""
451 "ANDNH %0,#8000")
452
453(define_insn "sqrtdf2"
454 [(set (match_operand:DF 0 "register_operand" "=r")
455 (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
456 ""
457 "FSQRT %0,%1")
458
459;; FIXME: define_expand for ffssi2? (not ffsdi2 since int is SImode).
460
461(define_insn "one_cmpldi2"
462 [(set (match_operand:DI 0 "register_operand" "=r")
463 (not:DI (match_operand:DI 1 "register_operand" "r")))]
464 ""
465 "NOR %0,%1,0")
466\f
bcf684c7
HPN
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.
f90b7a5a 477(define_insn "*cmpdi_folded"
bcf684c7
HPN
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?
ab3e1ef6
HPN
484 "REG_P (operands[0]) && REG_P (operands[1])
485 && REGNO (operands[1]) == REGNO (operands[0])"
bcf684c7
HPN
486 "%% folded: cmp %0,%1,0")
487
f90b7a5a 488(define_insn "*cmps"
bcf684c7
HPN
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\f
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,
9474e8ab 556 GET_MODE_SIZE (SFmode)));
bcf684c7
HPN
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,
9474e8ab 590 GET_MODE_SIZE (SFmode)));
bcf684c7
HPN
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
7e5037dc 640 (fix:DF (match_operand:DF 1 "register_operand" "r"))))]
bcf684c7
HPN
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".
f15643d4 650;; FIXME: Perhaps with TARGET_SECONDARY_MEMORY_NEEDED?
bcf684c7 651(define_expand "truncdfsf2"
11494830
HPN
652 [(set (match_operand:SF 0 "nonimmediate_operand")
653 (float_truncate:SF (match_operand:DF 1 "register_operand")))]
bcf684c7
HPN
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,
9474e8ab 672 GET_MODE_SIZE (SFmode)));
bcf684c7
HPN
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")
ba82f58b 681 (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
bcf684c7
HPN
682 ""
683 "STSF %1,%0")
684
685;; Same comment as for truncdfsf2.
686(define_expand "extendsfdf2"
11494830
HPN
687 [(set (match_operand:DF 0 "register_operand")
688 (float_extend:DF (match_operand:SF 1 "nonimmediate_operand")))]
bcf684c7
HPN
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,
9474e8ab 705 GET_MODE_SIZE (SFmode)));
bcf684c7
HPN
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\f
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"
f90b7a5a
PB
727 [(set (match_dup 4) (match_dup 5))
728 (set (match_operand:DF 0 "register_operand" "")
bcf684c7
HPN
729 (if_then_else:DF
730 (match_operand 1 "comparison_operator" "")
731 (match_operand:DF 2 "mmix_reg_or_0_operand" "")
732 (match_operand:DF 3 "mmix_reg_or_0_operand" "")))]
733 ""
734 "
735{
736 enum rtx_code code = GET_CODE (operands[1]);
f90b7a5a 737 if (code == LE || code == GE)
bcf684c7 738 FAIL;
f90b7a5a
PB
739
740 operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0),
741 XEXP (operands[1], 1));
742 operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]),
743 XEXP (operands[1], 0),
744 XEXP (operands[1], 1));
745 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
bcf684c7
HPN
746}")
747
748(define_expand "movdicc"
f90b7a5a
PB
749 [(set (match_dup 4) (match_dup 5))
750 (set (match_operand:DI 0 "register_operand" "")
bcf684c7
HPN
751 (if_then_else:DI
752 (match_operand 1 "comparison_operator" "")
753 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")
754 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "")))]
755 ""
756 "
757{
758 enum rtx_code code = GET_CODE (operands[1]);
f90b7a5a 759 if (code == LE || code == GE)
bcf684c7 760 FAIL;
f90b7a5a
PB
761
762 operands[4] = mmix_gen_compare_reg (code, XEXP (operands[1], 0),
763 XEXP (operands[1], 1));
764 operands[5] = gen_rtx_COMPARE (GET_MODE (operands[4]),
765 XEXP (operands[1], 0),
766 XEXP (operands[1], 1));
767 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, operands[4], const0_rtx);
bcf684c7
HPN
768}")
769
770;; FIXME: Is this the right way to do "folding" of CCmode -> DImode?
771(define_insn "*movdicc_real_foldable"
772 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
773 (if_then_else:DI
774 (match_operator 2 "mmix_foldable_comparison_operator"
f972cae4 775 [(match_operand:DI 3 "register_operand" "r,r,r,r")
bcf684c7 776 (const_int 0)])
91312b81
HPN
777 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
778 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
bcf684c7
HPN
779 ""
780 "@
781 CS%d2 %0,%3,%1
782 CS%D2 %0,%3,%4
783 ZS%d2 %0,%3,%1
784 ZS%D2 %0,%3,%4")
785
69ffa7aa 786(define_insn "*movdicc_real_reversible"
bcf684c7 787 [(set
91312b81 788 (match_operand:DI 0 "register_operand" "=r ,r ,r ,r")
bcf684c7
HPN
789 (if_then_else:DI
790 (match_operator
791 2 "mmix_comparison_operator"
91312b81 792 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
bcf684c7 793 (const_int 0)])
91312b81
HPN
794 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,0 ,rI,GM")
795 (match_operand:DI 4 "mmix_reg_or_8bit_operand" "0 ,rI,GM,rI")))]
69ffa7aa 796 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
bcf684c7
HPN
797 "@
798 CS%d2 %0,%3,%1
799 CS%D2 %0,%3,%4
800 ZS%d2 %0,%3,%1
801 ZS%D2 %0,%3,%4")
802
69ffa7aa
HPN
803(define_insn "*movdicc_real_nonreversible"
804 [(set
805 (match_operand:DI 0 "register_operand" "=r ,r")
806 (if_then_else:DI
807 (match_operator
808 2 "mmix_comparison_operator"
809 [(match_operand 3 "mmix_reg_cc_operand" "r ,r")
810 (const_int 0)])
811 (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI,rI")
812 (match_operand:DI 4 "mmix_reg_or_0_operand" "0 ,GM")))]
813 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
814 "@
815 CS%d2 %0,%3,%1
816 ZS%d2 %0,%3,%1")
817
bcf684c7
HPN
818(define_insn "*movdfcc_real_foldable"
819 [(set
820 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
821 (if_then_else:DF
822 (match_operator
823 2 "mmix_foldable_comparison_operator"
f972cae4 824 [(match_operand:DI 3 "register_operand" "r ,r ,r ,r")
bcf684c7
HPN
825 (const_int 0)])
826 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
827 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
828 ""
829 "@
830 CS%d2 %0,%3,%1
831 CS%D2 %0,%3,%4
832 ZS%d2 %0,%3,%1
833 ZS%D2 %0,%3,%4")
834
69ffa7aa 835(define_insn "*movdfcc_real_reversible"
bcf684c7
HPN
836 [(set
837 (match_operand:DF 0 "register_operand" "=r ,r ,r ,r")
838 (if_then_else:DF
839 (match_operator
840 2 "mmix_comparison_operator"
841 [(match_operand 3 "mmix_reg_cc_operand" "r ,r ,r ,r")
842 (const_int 0)])
843 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,0 ,rGM,GM")
844 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,rGM,GM ,rGM")))]
69ffa7aa 845 "REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
bcf684c7
HPN
846 "@
847 CS%d2 %0,%3,%1
848 CS%D2 %0,%3,%4
849 ZS%d2 %0,%3,%1
850 ZS%D2 %0,%3,%4")
851
69ffa7aa
HPN
852(define_insn "*movdfcc_real_nonreversible"
853 [(set
854 (match_operand:DF 0 "register_operand" "=r ,r")
855 (if_then_else:DF
856 (match_operator
857 2 "mmix_comparison_operator"
858 [(match_operand 3 "mmix_reg_cc_operand" "r ,r")
859 (const_int 0)])
860 (match_operand:DF 1 "mmix_reg_or_0_operand" "rGM,rGM")
861 (match_operand:DF 4 "mmix_reg_or_0_operand" "0 ,GM")))]
862 "!REVERSIBLE_CC_MODE (GET_MODE (operands[3]))"
863 "@
864 CS%d2 %0,%3,%1
865 ZS%d2 %0,%3,%1")
866
f90b7a5a 867;; FIXME: scc insns will probably help, I just skip them
bcf684c7
HPN
868;; right now. Revisit.
869\f
f90b7a5a
PB
870(define_expand "cbranchdi4"
871 [(set (match_dup 4)
872 (match_op_dup 5
873 [(match_operand:DI 1 "register_operand" "")
874 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "")]))
875 (set (pc)
876 (if_then_else
877 (match_operator 0 "ordered_comparison_operator"
878 [(match_dup 4)
879 (const_int 0)])
880 (label_ref (match_operand 3 "" ""))
881 (pc)))]
bcf684c7
HPN
882 ""
883 "
884{
f90b7a5a
PB
885 operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]),
886 operands[1], operands[2]);
887 operands[5] = gen_rtx_fmt_ee (COMPARE,
888 GET_MODE (operands[4]),
889 operands[1], operands[2]);
bcf684c7
HPN
890}")
891
f90b7a5a
PB
892(define_expand "cbranchdf4"
893 [(set (match_dup 4)
894 (match_op_dup 5
895 [(match_operand:DF 1 "register_operand" "")
896 (match_operand:DF 2 "register_operand" "")]))
897 (set (pc)
898 (if_then_else
899 (match_operator 0 "float_comparison_operator"
900 [(match_dup 4)
901 (const_int 0)])
902 (label_ref (match_operand 3 "" ""))
903 (pc)))]
bcf684c7
HPN
904 ""
905 "
906{
bcf684c7 907 /* The head comment of optabs.c:can_compare_p says we're required to
ff482c8d 908 implement this, so we have to clean up the mess here. */
f90b7a5a 909 if (GET_CODE (operands[0]) == LE || GET_CODE (operands[0]) == GE)
bcf684c7 910 {
f90b7a5a
PB
911 enum rtx_code ltgt_code = GET_CODE (operands[0]) == LE ? LT : GT;
912 emit_cmp_and_jump_insns (operands[1], operands[2], ltgt_code, NULL_RTX,
913 DFmode, 0, operands[3]);
914 emit_cmp_and_jump_insns (operands[1], operands[2], EQ, NULL_RTX,
915 DFmode, 0, operands[3]);
bcf684c7
HPN
916 DONE;
917 }
bcf684c7 918
f90b7a5a
PB
919 operands[4] = mmix_gen_compare_reg (GET_CODE (operands[0]),
920 operands[1], operands[2]);
921 operands[5] = gen_rtx_fmt_ee (COMPARE,
922 GET_MODE (operands[4]),
923 operands[1], operands[2]);
bcf684c7
HPN
924}")
925
bcf684c7
HPN
926
927;; FIXME: we can emit an unordered-or-*not*-equal compare in one insn, but
928;; there's no RTL code for it. Maybe revisit in future.
929
bcf684c7
HPN
930;; FIXME: Odd/Even matchers?
931(define_insn "*bCC_foldable"
932 [(set (pc)
933 (if_then_else
934 (match_operator 1 "mmix_foldable_comparison_operator"
f972cae4 935 [(match_operand:DI 2 "register_operand" "r")
bcf684c7
HPN
936 (const_int 0)])
937 (label_ref (match_operand 0 "" ""))
938 (pc)))]
939 ""
91312b81 940 "%+B%d1 %2,%0")
bcf684c7
HPN
941
942(define_insn "*bCC"
943 [(set (pc)
944 (if_then_else
945 (match_operator 1 "mmix_comparison_operator"
946 [(match_operand 2 "mmix_reg_cc_operand" "r")
947 (const_int 0)])
948 (label_ref (match_operand 0 "" ""))
949 (pc)))]
950 ""
91312b81 951 "%+B%d1 %2,%0")
bcf684c7
HPN
952
953(define_insn "*bCC_inverted_foldable"
954 [(set (pc)
955 (if_then_else
956 (match_operator 1 "mmix_foldable_comparison_operator"
f972cae4 957 [(match_operand:DI 2 "register_operand" "r")
bcf684c7
HPN
958 (const_int 0)])
959 (pc)
960 (label_ref (match_operand 0 "" ""))))]
961;; REVERSIBLE_CC_MODE is checked by mmix_foldable_comparison_operator.
962 ""
91312b81 963 "%+B%D1 %2,%0")
bcf684c7
HPN
964
965(define_insn "*bCC_inverted"
966 [(set (pc)
967 (if_then_else
968 (match_operator 1 "mmix_comparison_operator"
969 [(match_operand 2 "mmix_reg_cc_operand" "r")
970 (const_int 0)])
971 (pc)
972 (label_ref (match_operand 0 "" ""))))]
973 "REVERSIBLE_CC_MODE (GET_MODE (operands[2]))"
91312b81 974 "%+B%D1 %2,%0")
bcf684c7
HPN
975\f
976(define_expand "call"
977 [(parallel [(call (match_operand:QI 0 "memory_operand" "")
978 (match_operand 1 "general_operand" ""))
979 (use (match_operand 2 "general_operand" ""))
980 (clobber (match_dup 4))])
981 (set (match_dup 4) (match_dup 3))]
982 ""
983 "
984{
cc73528f
HPN
985 /* The caller checks that the operand is generally valid as an
986 address, but at -O0 nothing makes sure that it's also a valid
987 call address for a *call*; a mmix_symbolic_or_address_operand.
988 Force into a register if it isn't. */
989 if (!mmix_symbolic_or_address_operand (XEXP (operands[0], 0),
990 GET_MODE (XEXP (operands[0], 0))))
991 operands[0]
992 = replace_equiv_address (operands[0],
993 force_reg (Pmode, XEXP (operands[0], 0)));
994
bcf684c7
HPN
995 /* Since the epilogue 'uses' the return address, and it is clobbered
996 in the call, and we set it back after every call (all but one setting
997 will be optimized away), integrity is maintained. */
998 operands[3]
957ec0f9
HPN
999 = mmix_get_hard_reg_initial_val (Pmode,
1000 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
bcf684c7
HPN
1001
1002 /* FIXME: There's a bug in gcc which causes NULL to be passed as
1003 operand[2] when we get out of registers, which later confuses gcc.
1004 Work around it by replacing it with const_int 0. Possibly documentation
1005 error too. */
1006 if (operands[2] == NULL_RTX)
1007 operands[2] = const0_rtx;
3e0f61ac 1008
bcf684c7
HPN
1009 operands[4] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1010}")
1011
1012(define_expand "call_value"
1013 [(parallel [(set (match_operand 0 "" "")
1014 (call (match_operand:QI 1 "memory_operand" "")
1015 (match_operand 2 "general_operand" "")))
1016 (use (match_operand 3 "general_operand" ""))
1017 (clobber (match_dup 5))])
1018 (set (match_dup 5) (match_dup 4))]
1019 ""
1020 "
1021{
cc73528f
HPN
1022 /* The caller checks that the operand is generally valid as an
1023 address, but at -O0 nothing makes sure that it's also a valid
1024 call address for a *call*; a mmix_symbolic_or_address_operand.
1025 Force into a register if it isn't. */
1026 if (!mmix_symbolic_or_address_operand (XEXP (operands[1], 0),
1027 GET_MODE (XEXP (operands[1], 0))))
1028 operands[1]
1029 = replace_equiv_address (operands[1],
1030 force_reg (Pmode, XEXP (operands[1], 0)));
1031
bcf684c7
HPN
1032 /* Since the epilogue 'uses' the return address, and it is clobbered
1033 in the call, and we set it back after every call (all but one setting
1034 will be optimized away), integrity is maintained. */
1035 operands[4]
957ec0f9
HPN
1036 = mmix_get_hard_reg_initial_val (Pmode,
1037 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
bcf684c7
HPN
1038
1039 /* FIXME: See 'call'. */
1040 if (operands[3] == NULL_RTX)
1041 operands[3] = const0_rtx;
1042
1043 /* FIXME: Documentation bug: operands[3] (operands[2] for 'call') is the
07338cf8
HPN
1044 *next* argument register, not the number of arguments in registers.
1045 (There used to be code here where that mattered.) */
bcf684c7
HPN
1046
1047 operands[5] = gen_rtx_REG (DImode, MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
1048}")
1049
1050;; Don't use 'p' here. A 'p' must stand first in constraints, or reload
1051;; messes up, not registering the address for reload. Several C++
109b748d 1052;; testcases, including g++.brendan/crash40.C. FIXME: This is arguably a
bcf684c7
HPN
1053;; bug in gcc. Note line ~2612 in reload.c, that does things on the
1054;; condition <<else if (constraints[i][0] == 'p')>> and the comment on
1055;; ~3017 that says:
1056;; << case 'p':
1057;; /* All necessary reloads for an address_operand
1058;; were handled in find_reloads_address. */>>
1059;; Sorry, I have not dug deeper. If symbolic addresses are used
1060;; rarely compared to addresses in registers, disparaging the
1061;; first ("p") alternative by adding ? in the first operand
1062;; might do the trick. We define 'U' as a synonym to 'p', but without the
e9fef64c 1063;; caveats (and very small advantages) of 'p'.
e076319b 1064;; As of r190682 still so: newlib/libc/stdlib/dtoa.c ICEs if "p" is used.
bcf684c7
HPN
1065(define_insn "*call_real"
1066 [(call (mem:QI
1067 (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU"))
1068 (match_operand 1 "" ""))
1069 (use (match_operand 2 "" ""))
91312b81 1070 (clobber (reg:DI MMIX_rJ_REGNUM))]
bcf684c7
HPN
1071 ""
1072 "@
1073 PUSHJ $%p2,%0
1074 PUSHGO $%p2,%a0")
1075
1076(define_insn "*call_value_real"
1077 [(set (match_operand 0 "register_operand" "=r,r")
1078 (call (mem:QI
1079 (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU"))
1080 (match_operand 2 "" "")))
1081 (use (match_operand 3 "" ""))
91312b81 1082 (clobber (reg:DI MMIX_rJ_REGNUM))]
bcf684c7
HPN
1083 ""
1084 "@
1085 PUSHJ $%p3,%1
1086 PUSHGO $%p3,%a1")
1087
1088;; I hope untyped_call and untyped_return are not needed for MMIX.
43a88a8c 1089;; Users of Objective-C will notice.
bcf684c7 1090
957ec0f9
HPN
1091; Generated by GCC.
1092(define_expand "return"
66b8c57f
HPN
1093 [(return)]
1094 "mmix_use_simple_return ()"
957ec0f9
HPN
1095 "")
1096
1097; Generated by the epilogue expander.
1098(define_insn "*expanded_return"
1099 [(return)]
1100 ""
66b8c57f 1101 "POP %.,0")
bcf684c7 1102
957ec0f9
HPN
1103(define_expand "prologue"
1104 [(const_int 0)]
1105 ""
1106 "mmix_expand_prologue (); DONE;")
1107
1108; Note that the (return) from the expander itself is always the last insn
1109; in the epilogue.
1110(define_expand "epilogue"
1111 [(return)]
1112 ""
1113 "mmix_expand_epilogue ();")
1114
bcf684c7
HPN
1115(define_insn "nop"
1116 [(const_int 0)]
1117 ""
1118 "SWYM 0,0,0")
1119
1120(define_insn "jump"
1121 [(set (pc) (label_ref (match_operand 0 "" "")))]
1122 ""
1123 "JMP %0")
1124
1125(define_insn "indirect_jump"
1126 [(set (pc) (match_operand 0 "address_operand" "p"))]
1127 ""
1128 "GO $255,%a0")
1129
1130;; FIXME: This is just a jump, and should be expanded to one.
1131(define_insn "tablejump"
1132 [(set (pc) (match_operand:DI 0 "address_operand" "p"))
1133 (use (label_ref (match_operand 1 "" "")))]
1134 ""
1135 "GO $255,%a0")
1136
1137;; The only peculiar thing is that the register stack has to be unwound at
1138;; nonlocal_goto_receiver. At each function that has a nonlocal label, we
1139;; save at function entry the location of the "alpha" register stack
f6e89b80 1140;; pointer, rO, in a stack slot known to that function (right below where
bcf684c7
HPN
1141;; the frame-pointer would be located).
1142;; In the nonlocal goto receiver, we unwind the register stack by a series
1143;; of "pop 0,0" until rO equals the saved value. (If it goes lower, we
107a4b41 1144;; should die with a trap.)
bcf684c7 1145(define_expand "nonlocal_goto_receiver"
a271e61c 1146 [(parallel [(unspec_volatile [(match_dup 1)] 1)
bcf684c7 1147 (clobber (scratch:DI))
91312b81 1148 (clobber (reg:DI MMIX_rJ_REGNUM))])
db08fddf 1149 (set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))]
bcf684c7
HPN
1150 ""
1151 "
1152{
db08fddf 1153 operands[0]
957ec0f9
HPN
1154 = mmix_get_hard_reg_initial_val (Pmode,
1155 MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
bcf684c7 1156
a271e61c 1157 /* We need the frame-pointer to be live or the equivalent
026c3cfd 1158 expression, so refer to it in the pattern. We can't use a MEM
a271e61c
HPN
1159 (that may contain out-of-range offsets in the final expression)
1160 for fear that middle-end will legitimize it or replace the address
1161 using temporary registers (which are not revived at this point). */
1162 operands[1] = frame_pointer_rtx;
1163
bcf684c7
HPN
1164 /* Mark this function as containing a landing-pad. */
1165 cfun->machine->has_landing_pad = 1;
1166}")
1167
db08fddf
HPN
1168;; GCC can insist on using saved registers to keep the slot address in
1169;; "across" the exception, or (perhaps) to use saved registers in the
1170;; address and re-use them after the register stack unwind, so it's best
1171;; to form the address ourselves.
bcf684c7 1172(define_insn "*nonlocal_goto_receiver_expanded"
a271e61c 1173 [(unspec_volatile [(match_operand:DI 1 "frame_pointer_operand" "Yf")] 1)
db08fddf 1174 (clobber (match_scratch:DI 0 "=&r"))
91312b81 1175 (clobber (reg:DI MMIX_rJ_REGNUM))]
bcf684c7 1176 ""
db08fddf 1177{
a271e61c 1178 rtx my_operands[3];
db08fddf
HPN
1179 const char *my_template
1180 = "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\
11810:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:";
1182
a271e61c
HPN
1183 my_operands[1] = operands[0];
1184 my_operands[2] = GEN_INT (-MMIX_fp_rO_OFFSET);
db08fddf 1185
a271e61c 1186 if (operands[1] == hard_frame_pointer_rtx)
db08fddf 1187 {
a271e61c
HPN
1188 mmix_output_register_setting (asm_out_file, REGNO (operands[0]),
1189 MMIX_fp_rO_OFFSET, 1);
1190 my_operands[0]
1191 = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, operands[0]);
db08fddf
HPN
1192 }
1193 else
1194 {
a9243bfc 1195 int64_t offs = INTVAL (XEXP (operands[1], 1));
a271e61c 1196 offs += MMIX_fp_rO_OFFSET;
db08fddf 1197
a271e61c 1198 if (insn_const_int_ok_for_constraint (offs, CONSTRAINT_I))
db08fddf
HPN
1199 my_operands[0]
1200 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs));
1201 else
1202 {
a271e61c 1203 mmix_output_register_setting (asm_out_file, REGNO (operands[0]),
db08fddf 1204 offs, 1);
a271e61c
HPN
1205 my_operands[0]
1206 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, operands[0]);
db08fddf
HPN
1207 }
1208 }
1209
1210 output_asm_insn (my_template, my_operands);
1211 return "";
1212})
bcf684c7
HPN
1213\f
1214(define_insn "*Naddu"
1215 [(set (match_operand:DI 0 "register_operand" "=r")
1216 (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r")
1217 (match_operand:DI 2 "const_int_operand" "n"))
f6e89b80 1218 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))]
bcf684c7
HPN
1219 "GET_CODE (operands[2]) == CONST_INT
1220 && (INTVAL (operands[2]) == 2
1221 || INTVAL (operands[2]) == 4
1222 || INTVAL (operands[2]) == 8
1223 || INTVAL (operands[2]) == 16)"
1224 "%2ADDU %0,%1,%3")
1225
1226(define_insn "*andn"
1227 [(set (match_operand:DI 0 "register_operand" "=r")
1228 (and:DI
1229 (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI"))
1230 (match_operand:DI 2 "register_operand" "r")))]
1231 ""
1232 "ANDN %0,%2,%1")
1233
1234(define_insn "*nand"
1235 [(set (match_operand:DI 0 "register_operand" "=r")
1236 (ior:DI
1237 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1238 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1239 ""
1240 "NAND %0,%1,%2")
1241
1242(define_insn "*nor"
1243 [(set (match_operand:DI 0 "register_operand" "=r")
1244 (and:DI
1245 (not:DI (match_operand:DI 1 "register_operand" "%r"))
1246 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1247 ""
1248 "NOR %0,%1,%2")
1249
1250(define_insn "*nxor"
1251 [(set (match_operand:DI 0 "register_operand" "=r")
1252 (not:DI
1253 (xor:DI (match_operand:DI 1 "register_operand" "%r")
1254 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))]
1255 ""
1256 "NXOR %0,%1,%2")
1257
1258(define_insn "sync_icache"
1259 [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m")
1260 (match_operand:DI 1 "const_int_operand" "I")] 0)]
1261 ""
1262 "SYNCID %1,%0")
1263
1264;; Local Variables:
1265;; mode: lisp
1266;; indent-tabs-mode: t
1267;; End: