OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [config/] [mmix/] [mmix.md] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
;; GCC machine description for MMIX
2
;; Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
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 2, 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 COPYING.  If not, write to
20
;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21
;; Boston, MA 02110-1301, USA.
22
 
23
;; The original PO technology requires these to be ordered by speed,
24
;; so that assigner will pick the fastest.
25
 
26
;; See file "rtl.def" for documentation on define_insn, match_*, et al.
27
 
28
;; Uses of UNSPEC in this file:
29
;; UNSPEC_VOLATILE:
30
;;
31
;;      0        sync_icache (sync icache before trampoline jump)
32
;;      1       nonlocal_goto_receiver
33
;;
34
 
35
;; The order of insns is as in Node: Standard Names, with smaller modes
36
;; before bigger modes.
37
 
38
(define_constants
39
  [(MMIX_rJ_REGNUM 259)
40
   (MMIX_rR_REGNUM 260)
41
   (MMIX_fp_rO_OFFSET -24)]
42
)
43
 
44
;; Operand and operator predicates.
45
 
46
(include "predicates.md")
47
 
48
;; FIXME: Can we remove the reg-to-reg for smaller modes?  Shouldn't they
49
;; be synthesized ok?
50
(define_insn "movqi"
51
  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r ,r,x ,r,r,m,??r")
52
        (match_operand:QI 1 "general_operand"       "r,LS,K,rI,x,m,r,n"))]
53
  ""
54
  "@
55
   SET %0,%1
56
   %s1 %0,%v1
57
   NEGU %0,0,%n1
58
   PUT %0,%1
59
   GET %0,%1
60
   LDB%U0 %0,%1
61
   STBU %1,%0
62
   %r0%I1")
63
 
64
(define_insn "movhi"
65
  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,x,r,r,m,??r")
66
        (match_operand:HI 1 "general_operand"       "r,LS,K,r,x,m,r,n"))]
67
  ""
68
  "@
69
   SET %0,%1
70
   %s1 %0,%v1
71
   NEGU %0,0,%n1
72
   PUT %0,%1
73
   GET %0,%1
74
   LDW%U0 %0,%1
75
   STWU %1,%0
76
   %r0%I1")
77
 
78
;; gcc.c-torture/compile/920428-2.c fails if there's no "n".
79
(define_insn "movsi"
80
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r ,r,x,r,r,m,??r")
81
        (match_operand:SI 1 "general_operand"       "r,LS,K,r,x,m,r,n"))]
82
  ""
83
  "@
84
   SET %0,%1
85
   %s1 %0,%v1
86
   NEGU %0,0,%n1
87
   PUT %0,%1
88
   GET %0,%1
89
   LDT%U0 %0,%1
90
   STTU %1,%0
91
   %r0%I1")
92
 
93
;; We assume all "s" are addresses.  Does that hold?
94
(define_insn "movdi"
95
  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r")
96
        (match_operand:DI 1 "general_operand"       "r,LS,K,r,x,I,m,r,R,s,n"))]
97
  ""
98
  "@
99
   SET %0,%1
100
   %s1 %0,%v1
101
   NEGU %0,0,%n1
102
   PUT %0,%1
103
   GET %0,%1
104
   STCO %1,%0
105
   LDO %0,%1
106
   STOU %1,%0
107
   GETA %0,%1
108
   LDA %0,%1
109
   %r0%I1")
110
 
111
;; Note that we move around the float as a collection of bits; no
112
;; conversion to double.
113
(define_insn "movsf"
114
 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
115
       (match_operand:SF 1 "general_operand"       "r,G,r,x,m,r,F"))]
116
  ""
117
  "@
118
   SET %0,%1
119
   SETL %0,0
120
   PUT %0,%1
121
   GET %0,%1
122
   LDT %0,%1
123
   STTU %1,%0
124
   %r0%I1")
125
 
126
(define_insn "movdf"
127
  [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r")
128
        (match_operand:DF 1 "general_operand"       "r,G,r,x,m,r,F"))]
129
  ""
130
  "@
131
   SET %0,%1
132
   SETL %0,0
133
   PUT %0,%1
134
   GET %0,%1
135
   LDO %0,%1
136
   STOU %1,%0
137
   %r0%I1")
138
 
139
;; We need to be able to move around the values used as condition codes.
140
;; First spotted as reported in
141
;;  due to
142
;; changes in loop optimization.  The file machmode.def says they're of
143
;; size 4 QI.  Valid bit-patterns correspond to integers -1, 0 and 1, so
144
;; we treat them as signed entities; see mmix-modes.def.  The following
145
;; expanders should cover all MODE_CC modes, and expand for this pattern.
146
(define_insn "*movcc_expanded"
147
  [(set (match_operand 0 "nonimmediate_operand" "=r,x,r,r,m")
148
        (match_operand 1 "nonimmediate_operand"  "r,r,x,m,r"))]
149
  "GET_MODE_CLASS (GET_MODE (operands[0])) == MODE_CC
150
   && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_CC"
151
  "@
152
   SET %0,%1
153
   PUT %0,%1
154
   GET %0,%1
155
   LDT %0,%1
156
   STT %1,%0")
157
 
158
(define_expand "movcc"
159
  [(set (match_operand:CC 0 "nonimmediate_operand" "")
160
        (match_operand:CC 1 "nonimmediate_operand" ""))]
161
  ""
162
  "")
163
 
164
(define_expand "movcc_uns"
165
  [(set (match_operand:CC_UNS 0 "nonimmediate_operand" "")
166
        (match_operand:CC_UNS 1 "nonimmediate_operand" ""))]
167
  ""
168
  "")
169
 
170
(define_expand "movcc_fp"
171
  [(set (match_operand:CC_FP 0 "nonimmediate_operand" "")
172
        (match_operand:CC_FP 1 "nonimmediate_operand" ""))]
173
  ""
174
  "")
175
 
176
(define_expand "movcc_fpeq"
177
  [(set (match_operand:CC_FPEQ 0 "nonimmediate_operand" "")
178
        (match_operand:CC_FPEQ 1 "nonimmediate_operand" ""))]
179
  ""
180
  "")
181
 
182
(define_expand "movcc_fun"
183
  [(set (match_operand:CC_FUN 0 "nonimmediate_operand" "")
184
        (match_operand:CC_FUN 1 "nonimmediate_operand" ""))]
185
  ""
186
  "")
187
 
188
(define_insn "adddi3"
189
  [(set (match_operand:DI 0 "register_operand"  "=r,r,r")
190
        (plus:DI
191
         (match_operand:DI 1 "register_operand" "%r,r,0")
192
         (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,K,LS")))]
193
  ""
194
  "@
195
   ADDU %0,%1,%2
196
   SUBU %0,%1,%n2
197
   %i2 %0,%v2")
198
 
199
(define_insn "adddf3"
200
  [(set (match_operand:DF 0 "register_operand" "=r")
201
        (plus:DF (match_operand:DF 1 "register_operand" "%r")
202
                 (match_operand:DF 2 "register_operand" "r")))]
203
  ""
204
  "FADD %0,%1,%2")
205
 
206
;; Insn canonicalization *should* have removed the need for an integer
207
;; in operand 2.
208
(define_insn "subdi3"
209
  [(set (match_operand:DI 0 "register_operand" "=r,r")
210
        (minus:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "r,I")
211
                  (match_operand:DI 2 "register_operand" "r,r")))]
212
  ""
213
  "@
214
   SUBU %0,%1,%2
215
   NEGU %0,%1,%2")
216
 
217
(define_insn "subdf3"
218
  [(set (match_operand:DF 0 "register_operand" "=r")
219
        (minus:DF (match_operand:DF 1 "register_operand" "r")
220
                  (match_operand:DF 2 "register_operand" "r")))]
221
  ""
222
  "FSUB %0,%1,%2")
223
 
224
;; FIXME: Should we define_expand and match 2, 4, 8 (etc) with shift (or
225
;; %{something}2ADDU %0,%1,0)?  Hopefully GCC should still handle it, so
226
;; we don't have to taint the machine description.  If results are bad
227
;; enough, we may have to do it anyway.
228
(define_insn "muldi3"
229
  [(set (match_operand:DI 0 "register_operand" "=r,r")
230
        (mult:DI (match_operand:DI 1 "register_operand" "%r,r")
231
                 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "O,rI")))
232
   (clobber (match_scratch:DI 3 "=X,z"))]
233
  ""
234
  "@
235
   %m2ADDU %0,%1,%1
236
   MULU %0,%1,%2")
237
 
238
(define_insn "muldf3"
239
  [(set (match_operand:DF 0 "register_operand" "=r")
240
        (mult:DF (match_operand:DF 1 "register_operand" "r")
241
                 (match_operand:DF 2 "register_operand" "r")))]
242
  ""
243
  "FMUL %0,%1,%2")
244
 
245
(define_insn "divdf3"
246
  [(set (match_operand:DF 0 "register_operand" "=r")
247
        (div:DF (match_operand:DF 1 "register_operand" "r")
248
                (match_operand:DF 2 "register_operand" "r")))]
249
  ""
250
  "FDIV %0,%1,%2")
251
 
252
;; FIXME: Is "frem" doing the right operation for moddf3?
253
(define_insn "moddf3"
254
  [(set (match_operand:DF 0 "register_operand" "=r")
255
        (mod:DF (match_operand:DF 1 "register_operand" "r")
256
                (match_operand:DF 2 "register_operand" "r")))]
257
  ""
258
  "FREM %0,%1,%2")
259
 
260
;; FIXME: Should we define_expand for smin, smax, umin, umax using a
261
;; nifty conditional sequence?
262
 
263
;; FIXME: The cuter andn combinations don't get here, presumably because
264
;; they ended up in the constant pool.  Check: still?
265
(define_insn "anddi3"
266
  [(set (match_operand:DI 0 "register_operand" "=r,r")
267
        (and:DI
268
         (match_operand:DI 1 "register_operand" "%r,0")
269
         (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,NT")))]
270
  ""
271
  "@
272
   AND %0,%1,%2
273
   %A2 %0,%V2")
274
 
275
(define_insn "iordi3"
276
  [(set (match_operand:DI 0 "register_operand" "=r,r")
277
        (ior:DI (match_operand:DI 1 "register_operand" "%r,0")
278
                (match_operand:DI 2 "mmix_reg_or_constant_operand" "rH,LS")))]
279
  ""
280
  "@
281
   OR %0,%1,%2
282
   %o2 %0,%v2")
283
 
284
(define_insn "xordi3"
285
  [(set (match_operand:DI 0 "register_operand" "=r")
286
        (xor:DI (match_operand:DI 1 "register_operand" "%r")
287
                (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
288
  ""
289
  "XOR %0,%1,%2")
290
 
291
;; FIXME:  When TImode works for other reasons (like cross-compiling from
292
;; a 32-bit host), add back umulditi3 and umuldi3_highpart here.
293
 
294
;; FIXME: Check what's really reasonable for the mod part.
295
 
296
;; One day we might persuade GCC to expand divisions with constants the
297
;; way MMIX does; giving the remainder the sign of the divisor.  But even
298
;; then, it might be good to have an option to divide the way "everybody
299
;; else" does.  Perhaps then, this option can be on by default.  However,
300
;; it's not likely to happen because major (C, C++, Fortran) language
301
;; standards in effect at 2002-04-29 reportedly demand that the sign of
302
;; the remainder must follow the sign of the dividend.
303
 
304
(define_insn "divmoddi4"
305
  [(set (match_operand:DI 0 "register_operand" "=r")
306
        (div:DI (match_operand:DI 1 "register_operand" "r")
307
                (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
308
   (set (match_operand:DI 3 "register_operand" "=y")
309
        (mod:DI (match_dup 1) (match_dup 2)))]
310
  ;; Do the library stuff later.
311
  "TARGET_KNUTH_DIVISION"
312
  "DIV %0,%1,%2")
313
 
314
(define_insn "udivmoddi4"
315
  [(set (match_operand:DI 0 "register_operand" "=r")
316
        (udiv:DI (match_operand:DI 1 "register_operand" "r")
317
                 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))
318
   (set (match_operand:DI 3 "register_operand" "=y")
319
        (umod:DI (match_dup 1) (match_dup 2)))]
320
  ""
321
  "DIVU %0,%1,%2")
322
 
323
(define_expand "divdi3"
324
  [(parallel
325
    [(set (match_operand:DI 0 "register_operand" "=&r")
326
          (div:DI (match_operand:DI 1 "register_operand" "r")
327
                  (match_operand:DI 2 "register_operand" "r")))
328
     (clobber (scratch:DI))
329
     (clobber (scratch:DI))
330
     (clobber (reg:DI MMIX_rR_REGNUM))])]
331
  "! TARGET_KNUTH_DIVISION"
332
  "")
333
 
334
;; The %2-is-%1-case is there just to make sure things don't fail.  Could
335
;; presumably happen with optimizations off; no evidence.
336
(define_insn "*divdi3_nonknuth"
337
  [(set (match_operand:DI 0 "register_operand" "=&r,r")
338
        (div:DI (match_operand:DI 1 "register_operand" "r,r")
339
                (match_operand:DI 2 "register_operand" "1,r")))
340
   (clobber (match_scratch:DI 3 "=1,1"))
341
   (clobber (match_scratch:DI 4 "=2,2"))
342
   (clobber (reg:DI MMIX_rR_REGNUM))]
343
  "! TARGET_KNUTH_DIVISION"
344
  "@
345
   SETL %0,1
346
   XOR $255,%1,%2\;NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU %0,0,%1\;CSN %1,%1,%0\;\
347
DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1")
348
 
349
(define_expand "moddi3"
350
  [(parallel
351
    [(set (match_operand:DI 0 "register_operand" "=&r")
352
          (mod:DI (match_operand:DI 1 "register_operand" "r")
353
                  (match_operand:DI 2 "register_operand" "r")))
354
     (clobber (scratch:DI))
355
     (clobber (scratch:DI))
356
     (clobber (reg:DI MMIX_rR_REGNUM))])]
357
  "! TARGET_KNUTH_DIVISION"
358
  "")
359
 
360
;; The %2-is-%1-case is there just to make sure things don't fail.  Could
361
;; presumably happen with optimizations off; no evidence.
362
(define_insn "*moddi3_nonknuth"
363
  [(set (match_operand:DI 0 "register_operand" "=&r,r")
364
        (mod:DI (match_operand:DI 1 "register_operand" "r,r")
365
                (match_operand:DI 2 "register_operand" "1,r")))
366
   (clobber (match_scratch:DI 3 "=1,1"))
367
   (clobber (match_scratch:DI 4 "=2,2"))
368
   (clobber (reg:DI MMIX_rR_REGNUM))]
369
  "! TARGET_KNUTH_DIVISION"
370
  "@
371
   SETL %0,0
372
   NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU $255,0,%1\;CSN %1,%1,$255\;\
373
DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")
374
 
375
(define_insn "ashldi3"
376
  [(set (match_operand:DI 0 "register_operand" "=r")
377
        (ashift:DI
378
         (match_operand:DI 1 "register_operand" "r")
379
         (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
380
  ""
381
  "SLU %0,%1,%2")
382
 
383
(define_insn "ashrdi3"
384
  [(set (match_operand:DI 0 "register_operand" "=r")
385
        (ashiftrt:DI
386
         (match_operand:DI 1 "register_operand" "r")
387
         (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
388
  ""
389
  "SR %0,%1,%2")
390
 
391
(define_insn "lshrdi3"
392
  [(set (match_operand:DI 0 "register_operand" "=r")
393
        (lshiftrt:DI
394
         (match_operand:DI 1 "register_operand" "r")
395
         (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))]
396
  ""
397
  "SRU %0,%1,%2")
398
 
399
(define_insn "negdi2"
400
  [(set (match_operand:DI 0 "register_operand" "=r")
401
        (neg:DI (match_operand:DI 1 "register_operand" "r")))]
402
  ""
403
  "NEGU %0,0,%1")
404
 
405
(define_expand "negdf2"
406
  [(parallel [(set (match_operand:DF 0 "register_operand" "=r")
407
                   (neg:DF (match_operand:DF 1 "register_operand" "r")))
408
              (use (match_dup 2))])]
409
  ""
410
{
411
  /* Emit bit-flipping sequence to be IEEE-safe wrt. -+0.  */
412
  operands[2] = force_reg (DImode, GEN_INT ((HOST_WIDE_INT) 1 << 63));
413
})
414
 
415
(define_insn "*expanded_negdf2"
416
  [(set (match_operand:DF 0 "register_operand" "=r")
417
        (neg:DF (match_operand:DF 1 "register_operand" "r")))
418
   (use (match_operand:DI 2 "register_operand" "r"))]
419
  ""
420
  "XOR %0,%1,%2")
421
 
422
;; FIXME: define_expand for absdi2?
423
 
424
(define_insn "absdf2"
425
  [(set (match_operand:DF 0 "register_operand" "=r")
426
        (abs:DF (match_operand:DF 1 "register_operand" "0")))]
427
  ""
428
  "ANDNH %0,#8000")
429
 
430
(define_insn "sqrtdf2"
431
  [(set (match_operand:DF 0 "register_operand" "=r")
432
        (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
433
  ""
434
  "FSQRT %0,%1")
435
 
436
;; FIXME: define_expand for ffssi2? (not ffsdi2 since int is SImode).
437
 
438
(define_insn "one_cmpldi2"
439
  [(set (match_operand:DI 0 "register_operand" "=r")
440
        (not:DI (match_operand:DI 1 "register_operand" "r")))]
441
  ""
442
  "NOR %0,%1,0")
443
 
444
;; Since we don't have cc0, we do what is recommended in the manual;
445
;; store away the operands for use in the branch, scc or movcc insn.
446
(define_expand "cmpdi"
447
  [(match_operand:DI 0 "register_operand" "")
448
   (match_operand:DI 1 "mmix_reg_or_8bit_operand" "")]
449
  ""
450
  "
451
{
452
  mmix_compare_op0 = operands[0];
453
  mmix_compare_op1 = operands[1];
454
  DONE;
455
}")
456
 
457
(define_expand "cmpdf"
458
  [(match_operand:DF 0 "register_operand" "")
459
   (match_operand:DF 1 "register_operand" "")]
460
  ""
461
  "
462
{
463
  mmix_compare_op0 = operands[0];
464
  mmix_compare_op1 = operands[1];
465
  DONE;
466
}")
467
 
468
;; When the user-patterns expand, the resulting insns will match the
469
;; patterns below.
470
 
471
;; We can fold the signed-compare where the register value is
472
;; already equal to (compare:CCTYPE (reg) (const_int 0)).
473
;;  We can't do that at all for floating-point, due to NaN, +0.0
474
;; and -0.0, and we can only do it for the non/zero test of
475
;; unsigned, so that has to be done another way.
476
;;  FIXME: Perhaps a peep2 changing CCcode to a new code, that
477
;; gets folded here.
478
(define_insn "*cmpcc_folded"
479
  [(set (match_operand:CC 0 "register_operand" "=r")
480
        (compare:CC
481
         (match_operand:DI 1 "register_operand" "r")
482
         (const_int 0)))]
483
  ;; FIXME: Can we test equivalence any other way?
484
  ;; FIXME: Can we fold any other way?
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 <> 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:

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.