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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [mmix/] [mmix.md] - Blame information for rev 816

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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