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