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