1;; GCC machine description for MMIX 2;; Copyright (C) 2000-2015 Free Software Foundation, Inc. 3;; Contributed by Hans-Peter Nilsson (hp@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;; Operand and operator predicates. 43 44(include "predicates.md") 45(include "constraints.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;; <URL:http://gcc.gnu.org/ml/gcc-bugs/2003-03/msg00008.html> 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" "rI,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\;\ 346DIVU %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\;\ 372DIVU %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))); 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))); 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))); 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))); 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 <<else if (constraints[i][0] == 'p')>> 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;; As of r190682 still so: newlib/libc/stdlib/dtoa.c ICEs if "p" is used. 1041(define_insn "*call_real" 1042 [(call (mem:QI 1043 (match_operand:DI 0 "mmix_symbolic_or_address_operand" "s,rU")) 1044 (match_operand 1 "" "")) 1045 (use (match_operand 2 "" "")) 1046 (clobber (reg:DI MMIX_rJ_REGNUM))] 1047 "" 1048 "@ 1049 PUSHJ $%p2,%0 1050 PUSHGO $%p2,%a0") 1051 1052(define_insn "*call_value_real" 1053 [(set (match_operand 0 "register_operand" "=r,r") 1054 (call (mem:QI 1055 (match_operand:DI 1 "mmix_symbolic_or_address_operand" "s,rU")) 1056 (match_operand 2 "" ""))) 1057 (use (match_operand 3 "" "")) 1058 (clobber (reg:DI MMIX_rJ_REGNUM))] 1059 "" 1060 "@ 1061 PUSHJ $%p3,%1 1062 PUSHGO $%p3,%a1") 1063 1064;; I hope untyped_call and untyped_return are not needed for MMIX. 1065;; Users of Objective-C will notice. 1066 1067; Generated by GCC. 1068(define_expand "return" 1069 [(return)] 1070 "mmix_use_simple_return ()" 1071 "") 1072 1073; Generated by the epilogue expander. 1074(define_insn "*expanded_return" 1075 [(return)] 1076 "" 1077 "POP %.,0") 1078 1079(define_expand "prologue" 1080 [(const_int 0)] 1081 "" 1082 "mmix_expand_prologue (); DONE;") 1083 1084; Note that the (return) from the expander itself is always the last insn 1085; in the epilogue. 1086(define_expand "epilogue" 1087 [(return)] 1088 "" 1089 "mmix_expand_epilogue ();") 1090 1091(define_insn "nop" 1092 [(const_int 0)] 1093 "" 1094 "SWYM 0,0,0") 1095 1096(define_insn "jump" 1097 [(set (pc) (label_ref (match_operand 0 "" "")))] 1098 "" 1099 "JMP %0") 1100 1101(define_insn "indirect_jump" 1102 [(set (pc) (match_operand 0 "address_operand" "p"))] 1103 "" 1104 "GO $255,%a0") 1105 1106;; FIXME: This is just a jump, and should be expanded to one. 1107(define_insn "tablejump" 1108 [(set (pc) (match_operand:DI 0 "address_operand" "p")) 1109 (use (label_ref (match_operand 1 "" "")))] 1110 "" 1111 "GO $255,%a0") 1112 1113;; The only peculiar thing is that the register stack has to be unwound at 1114;; nonlocal_goto_receiver. At each function that has a nonlocal label, we 1115;; save at function entry the location of the "alpha" register stack 1116;; pointer, rO, in a stack slot known to that function (right below where 1117;; the frame-pointer would be located). 1118;; In the nonlocal goto receiver, we unwind the register stack by a series 1119;; of "pop 0,0" until rO equals the saved value. (If it goes lower, we 1120;; should die with a trap.) 1121(define_expand "nonlocal_goto_receiver" 1122 [(parallel [(unspec_volatile [(match_dup 1)] 1) 1123 (clobber (scratch:DI)) 1124 (clobber (reg:DI MMIX_rJ_REGNUM))]) 1125 (set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))] 1126 "" 1127 " 1128{ 1129 operands[0] 1130 = mmix_get_hard_reg_initial_val (Pmode, 1131 MMIX_INCOMING_RETURN_ADDRESS_REGNUM); 1132 1133 /* We need the frame-pointer to be live or the equivalent 1134 expression, so refer to in in the pattern. We can't use a MEM 1135 (that may contain out-of-range offsets in the final expression) 1136 for fear that middle-end will legitimize it or replace the address 1137 using temporary registers (which are not revived at this point). */ 1138 operands[1] = frame_pointer_rtx; 1139 1140 /* Mark this function as containing a landing-pad. */ 1141 cfun->machine->has_landing_pad = 1; 1142}") 1143 1144;; GCC can insist on using saved registers to keep the slot address in 1145;; "across" the exception, or (perhaps) to use saved registers in the 1146;; address and re-use them after the register stack unwind, so it's best 1147;; to form the address ourselves. 1148(define_insn "*nonlocal_goto_receiver_expanded" 1149 [(unspec_volatile [(match_operand:DI 1 "frame_pointer_operand" "Yf")] 1) 1150 (clobber (match_scratch:DI 0 "=&r")) 1151 (clobber (reg:DI MMIX_rJ_REGNUM))] 1152 "" 1153{ 1154 rtx my_operands[3]; 1155 const char *my_template 1156 = "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\ 11570:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:"; 1158 1159 my_operands[1] = operands[0]; 1160 my_operands[2] = GEN_INT (-MMIX_fp_rO_OFFSET); 1161 1162 if (operands[1] == hard_frame_pointer_rtx) 1163 { 1164 mmix_output_register_setting (asm_out_file, REGNO (operands[0]), 1165 MMIX_fp_rO_OFFSET, 1); 1166 my_operands[0] 1167 = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, operands[0]); 1168 } 1169 else 1170 { 1171 int64_t offs = INTVAL (XEXP (operands[1], 1)); 1172 offs += MMIX_fp_rO_OFFSET; 1173 1174 if (insn_const_int_ok_for_constraint (offs, CONSTRAINT_I)) 1175 my_operands[0] 1176 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs)); 1177 else 1178 { 1179 mmix_output_register_setting (asm_out_file, REGNO (operands[0]), 1180 offs, 1); 1181 my_operands[0] 1182 = gen_rtx_PLUS (Pmode, stack_pointer_rtx, operands[0]); 1183 } 1184 } 1185 1186 output_asm_insn (my_template, my_operands); 1187 return ""; 1188}) 1189 1190(define_insn "*Naddu" 1191 [(set (match_operand:DI 0 "register_operand" "=r") 1192 (plus:DI (mult:DI (match_operand:DI 1 "register_operand" "r") 1193 (match_operand:DI 2 "const_int_operand" "n")) 1194 (match_operand:DI 3 "mmix_reg_or_8bit_operand" "rI")))] 1195 "GET_CODE (operands[2]) == CONST_INT 1196 && (INTVAL (operands[2]) == 2 1197 || INTVAL (operands[2]) == 4 1198 || INTVAL (operands[2]) == 8 1199 || INTVAL (operands[2]) == 16)" 1200 "%2ADDU %0,%1,%3") 1201 1202(define_insn "*andn" 1203 [(set (match_operand:DI 0 "register_operand" "=r") 1204 (and:DI 1205 (not:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "rI")) 1206 (match_operand:DI 2 "register_operand" "r")))] 1207 "" 1208 "ANDN %0,%2,%1") 1209 1210(define_insn "*nand" 1211 [(set (match_operand:DI 0 "register_operand" "=r") 1212 (ior:DI 1213 (not:DI (match_operand:DI 1 "register_operand" "%r")) 1214 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))] 1215 "" 1216 "NAND %0,%1,%2") 1217 1218(define_insn "*nor" 1219 [(set (match_operand:DI 0 "register_operand" "=r") 1220 (and:DI 1221 (not:DI (match_operand:DI 1 "register_operand" "%r")) 1222 (not:DI (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))] 1223 "" 1224 "NOR %0,%1,%2") 1225 1226(define_insn "*nxor" 1227 [(set (match_operand:DI 0 "register_operand" "=r") 1228 (not:DI 1229 (xor:DI (match_operand:DI 1 "register_operand" "%r") 1230 (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))))] 1231 "" 1232 "NXOR %0,%1,%2") 1233 1234(define_insn "sync_icache" 1235 [(unspec_volatile [(match_operand:DI 0 "memory_operand" "m") 1236 (match_operand:DI 1 "const_int_operand" "I")] 0)] 1237 "" 1238 "SYNCID %1,%0") 1239 1240;; Local Variables: 1241;; mode: lisp 1242;; indent-tabs-mode: t 1243;; End: 1244