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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [mmix/] [mmix.md] - Blame information for rev 709

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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