|
|
1.1 ! root 1: /* Subroutines for insn-output.c for Sun SPARC. ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: Contributed by Michael Tiemann ([email protected]) ! 4: ! 5: This file is part of GNU CC. ! 6: ! 7: GNU CC is distributed in the hope that it will be useful, ! 8: but WITHOUT ANY WARRANTY. No author or distributor ! 9: accepts responsibility to anyone for the consequences of using it ! 10: or for whether it serves any particular purpose or works at all, ! 11: unless he says so in writing. Refer to the GNU CC General Public ! 12: License for full details. ! 13: ! 14: Everyone is granted permission to copy, modify and redistribute ! 15: GNU CC, but only under the conditions described in the ! 16: GNU CC General Public License. A copy of this license is ! 17: supposed to have been given to you along with GNU CC so you ! 18: can know your rights and responsibilities. It should be in a ! 19: file named COPYING. Among other things, the copyright notice ! 20: and this notice must be preserved on all copies. */ ! 21: ! 22: /* Global variables for machine-dependend things. */ ! 23: ! 24: /* This should go away if we pass floats to regs via ! 25: the stack instead of the frame. */ ! 26: extern int frame_pointer_needed; ! 27: ! 28: static rtx find_addr_reg (); ! 29: ! 30: #if 0 ! 31: /* RTL expressions that we will cache during the entire compilation. */ ! 32: rtx reg_o0_rtx, reg_o1_rtx, reg_o2_rtx, reg_i7_rtx; ! 33: ! 34: void ! 35: init_emit_mdep () ! 36: { ! 37: /* These may be freely shared. */ ! 38: reg_o0_rtx = gen_rtx (REG, SImode, 8); ! 39: reg_o1_rtx = gen_rtx (REG, SImode, 9); ! 40: reg_o2_rtx = gen_rtx (REG, SImode, 10); ! 41: reg_i7_rtx = gen_rtx (REG, SImode, 31); ! 42: } ! 43: #endif ! 44: ! 45: int ! 46: arith_operand (op, mode) ! 47: rtx op; ! 48: enum machine_mode mode; ! 49: { ! 50: return (register_operand (op, mode) ! 51: || (GET_CODE (op) == CONST_INT && SMALL_INT (op))); ! 52: } ! 53: ! 54: int ! 55: arith32_operand (op, mode) ! 56: rtx op; ! 57: enum machine_mode mode; ! 58: { ! 59: return (register_operand (op, mode) || GET_CODE (op) == CONST_INT); ! 60: } ! 61: ! 62: /* Return the best assembler insn template ! 63: for moving operands[1] into operands[0] as a fullword. */ ! 64: ! 65: static char * ! 66: singlemove_string (operands) ! 67: rtx *operands; ! 68: { ! 69: if (GET_CODE (operands[0]) == MEM) ! 70: return "st %r1,%0"; ! 71: if (GET_CODE (operands[1]) == MEM) ! 72: return "ld %1,%0"; ! 73: return "add %1,%%g0,%0"; ! 74: } ! 75: ! 76: /* Output assembler code to perform a doubleword move insn ! 77: with operands OPERANDS. */ ! 78: ! 79: char * ! 80: output_move_double (operands) ! 81: rtx *operands; ! 82: { ! 83: enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1; ! 84: rtx latehalf[2]; ! 85: rtx addreg0 = 0, addreg1 = 0; ! 86: ! 87: /* First classify both operands. */ ! 88: ! 89: if (REG_P (operands[0])) ! 90: optype0 = REGOP; ! 91: else if (offsetable_memref_p (operands[0])) ! 92: optype0 = OFFSOP; ! 93: else if (GET_CODE (operands[0]) == MEM) ! 94: optype0 = MEMOP; ! 95: else ! 96: optype0 = RNDOP; ! 97: ! 98: if (REG_P (operands[1])) ! 99: optype1 = REGOP; ! 100: else if (CONSTANT_P (operands[1]) ! 101: || GET_CODE (operands[1]) == CONST_DOUBLE) ! 102: optype1 = CNSTOP; ! 103: else if (offsetable_memref_p (operands[1])) ! 104: optype1 = OFFSOP; ! 105: else if (GET_CODE (operands[1]) == MEM) ! 106: optype0 = MEMOP; ! 107: else ! 108: optype1 = RNDOP; ! 109: ! 110: /* Check for the cases that the operand constraints are not ! 111: supposed to allow to happen. Abort if we get one, ! 112: because generating code for these cases is painful. */ ! 113: ! 114: if (optype0 == RNDOP || optype1 == RNDOP) ! 115: abort (); ! 116: ! 117: /* If an operand is an unoffsettable memory ref, find a register ! 118: we can increment temporarily to make it refer to the second word. */ ! 119: ! 120: if (optype0 == MEMOP) ! 121: addreg0 = find_addr_reg (operands[0]); ! 122: ! 123: if (optype1 == MEMOP) ! 124: addreg1 = find_addr_reg (operands[1]); ! 125: ! 126: /* Ok, we can do one word at a time. ! 127: Normally we do the low-numbered word first, ! 128: but if either operand is autodecrementing then we ! 129: do the high-numbered word first. ! 130: ! 131: In either case, set up in LATEHALF the operands to use ! 132: for the high-numbered word and in some cases alter the ! 133: operands in OPERANDS to be suitable for the low-numbered word. */ ! 134: ! 135: if (optype0 == REGOP) ! 136: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); ! 137: else if (optype0 == OFFSOP) ! 138: latehalf[0] = adj_offsetable_operand (operands[0], 4); ! 139: else ! 140: latehalf[0] = operands[0]; ! 141: ! 142: if (optype1 == REGOP) ! 143: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); ! 144: else if (optype1 == OFFSOP) ! 145: latehalf[1] = adj_offsetable_operand (operands[1], 4); ! 146: else if (optype1 == CNSTOP) ! 147: { ! 148: if (CONSTANT_P (operands[1])) ! 149: latehalf[1] = const0_rtx; ! 150: else if (GET_CODE (operands[1]) == CONST_DOUBLE) ! 151: { ! 152: latehalf[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 1)); ! 153: operands[1] = gen_rtx (CONST_INT, VOIDmode, XINT (operands[1], 0)); ! 154: } ! 155: } ! 156: else ! 157: latehalf[1] = operands[1]; ! 158: ! 159: /* If the first move would clobber the source of the second one, ! 160: do them in the other order. This happens only for registers; ! 161: such overlap can't happen in memory unless the user explicitly ! 162: sets it up, and that is an undefined circumstance. */ ! 163: ! 164: if (optype0 == REGOP && optype1 == REGOP ! 165: && REGNO (operands[0]) == REGNO (latehalf[1])) ! 166: { ! 167: /* Make any unoffsetable addresses point at high-numbered word. */ ! 168: if (addreg0) ! 169: output_asm_insn ("add %0,0x4,%0", &addreg0); ! 170: if (addreg1) ! 171: output_asm_insn ("add %0,0x4,%0", &addreg1); ! 172: ! 173: /* Do that word. */ ! 174: output_asm_insn (singlemove_string (latehalf), latehalf); ! 175: ! 176: /* Undo the adds we just did. */ ! 177: if (addreg0) ! 178: output_asm_insn ("add %0,-0x4,%0", &addreg0); ! 179: if (addreg1) ! 180: output_asm_insn ("add %0,-0x4,%0", &addreg0); ! 181: ! 182: /* Do low-numbered word. */ ! 183: return singlemove_string (operands); ! 184: } ! 185: ! 186: /* Normal case: do the two words, low-numbered first. */ ! 187: ! 188: output_asm_insn (singlemove_string (operands), operands); ! 189: ! 190: /* Make any unoffsetable addresses point at high-numbered word. */ ! 191: if (addreg0) ! 192: output_asm_insn ("add %0,0x4,%0", &addreg0); ! 193: if (addreg1) ! 194: output_asm_insn ("add %0,0x4,%0", &addreg1); ! 195: ! 196: /* Do that word. */ ! 197: output_asm_insn (singlemove_string (latehalf), latehalf); ! 198: ! 199: /* Undo the adds we just did. */ ! 200: if (addreg0) ! 201: output_asm_insn ("add %0,-0x4,%0", &addreg0); ! 202: if (addreg1) ! 203: output_asm_insn ("add %0,-0x4,%0", &addreg1); ! 204: ! 205: return ""; ! 206: } ! 207: ! 208: static char * ! 209: output_fp_move_double (operands) ! 210: rtx *operands; ! 211: { ! 212: if (FP_REG_P (operands[0])) ! 213: { ! 214: if (FP_REG_P (operands[1])) ! 215: { ! 216: output_asm_insn ("fmovs %1,%0", operands); ! 217: operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1); ! 218: operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1); ! 219: return "fmovs %1,%0"; ! 220: } ! 221: if (GET_CODE (operands[1]) == REG) ! 222: /* No good, since a signal would probably clobber that word on the stack. */ ! 223: /* return "st %1,[%%sp-8]\n\tldd [%%sp-8],%0"; */ ! 224: { ! 225: rtx xoperands[2]; ! 226: int offset = - get_frame_size () - 8; ! 227: xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); ! 228: xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset + 4); ! 229: output_asm_insn ("st %1,[%%fp+%0]", xoperands); ! 230: xoperands[1] = operands[1]; ! 231: xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset); ! 232: output_asm_insn ("st %1,[%%fp+%0]", xoperands); ! 233: xoperands[1] = operands[0]; ! 234: output_asm_insn ("ldd [%%fp+%0],%1", xoperands); ! 235: return ""; ! 236: } ! 237: return "ldd %1,%0"; ! 238: } ! 239: else if (FP_REG_P (operands[1])) ! 240: { ! 241: if (GET_CODE (operands[0]) == REG) ! 242: /* No good, since a signal would probably clobber that word on the stack. */ ! 243: /* return "std %1,[%%sp-8]\n\tldd [%%sp-8],%0"; */ ! 244: { ! 245: rtx xoperands[2]; ! 246: int offset = - get_frame_size () - 8; ! 247: xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset); ! 248: xoperands[1] = operands[1]; ! 249: output_asm_insn ("st %1,[%%fp+%0]", xoperands); ! 250: xoperands[1] = operands[0]; ! 251: output_asm_insn ("ld [%%fp+%0],%1", xoperands); ! 252: xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); ! 253: xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset + 4); ! 254: output_asm_insn ("ld [%%fp+%0],%1", xoperands); ! 255: return ""; ! 256: } ! 257: return "std %1,%0"; ! 258: } ! 259: } ! 260: ! 261: /* Return a REG that occurs in ADDR with coefficient 1. ! 262: ADDR can be effectively incremented by incrementing REG. */ ! 263: ! 264: static rtx ! 265: find_addr_reg (addr) ! 266: rtx addr; ! 267: { ! 268: while (GET_CODE (addr) == PLUS) ! 269: { ! 270: if (GET_CODE (XEXP (addr, 0)) == REG) ! 271: addr = XEXP (addr, 0); ! 272: if (GET_CODE (XEXP (addr, 1)) == REG) ! 273: addr = XEXP (addr, 1); ! 274: if (CONSTANT_P (XEXP (addr, 0))) ! 275: addr = XEXP (addr, 1); ! 276: if (CONSTANT_P (XEXP (addr, 1))) ! 277: addr = XEXP (addr, 0); ! 278: } ! 279: if (GET_CODE (addr) == REG) ! 280: return addr; ! 281: return 0; ! 282: } ! 283: ! 284: /* Load the address specified by OPERANDS[3] into the register ! 285: specified by OPERANDS[0]. ! 286: ! 287: OPERANDS[3] may be the result of a sum, hence it could either be: ! 288: ! 289: (1) CONST ! 290: (2) REG ! 291: (2) REG + CONST_INT ! 292: (3) REG + REG + CONST_INT ! 293: ! 294: All cases are handled here. */ ! 295: ! 296: void ! 297: output_load_address (operands) ! 298: rtx *operands; ! 299: { ! 300: rtx base, offset; ! 301: ! 302: if (CONSTANT_P (operands[3])) ! 303: { ! 304: output_asm_insn ("set %3,%0", operands); ! 305: return; ! 306: } ! 307: ! 308: if (REG_P (operands[3])) ! 309: { ! 310: if (REGNO (operands[0]) != REGNO (operands[3])) ! 311: output_asm_insn ("mov %3,%0", operands); ! 312: return; ! 313: } ! 314: ! 315: base = XEXP (operands[3], 0); ! 316: offset = XEXP (operands[3], 1); ! 317: ! 318: if (GET_CODE (base) == CONST_INT) ! 319: { ! 320: rtx tmp = base; ! 321: base = offset; ! 322: offset = tmp; ! 323: } ! 324: ! 325: if (GET_CODE (offset) != CONST_INT) ! 326: abort (); ! 327: ! 328: if (REG_P (base)) ! 329: { ! 330: operands[6] = base; ! 331: operands[7] = offset; ! 332: if (SMALL_INT (offset)) ! 333: output_asm_insn ("add %6,%7,%0", operands); ! 334: else ! 335: output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands); ! 336: } ! 337: else ! 338: { ! 339: operands[6] = XEXP (base, 0); ! 340: operands[7] = XEXP (base, 1); ! 341: operands[8] = offset; ! 342: ! 343: if (SMALL_INT (offset)) ! 344: output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands); ! 345: else ! 346: output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands); ! 347: } ! 348: } ! 349: ! 350: char * ! 351: output_block_move (operands) ! 352: rtx *operands; ! 353: { ! 354: static int movstrsi_label = 0; ! 355: int align = 4; ! 356: ! 357: rtx xoperands[9]; ! 358: int available[3]; ! 359: int i, j; ! 360: ! 361: /* Since we clobber untold things, nix the condition codes. */ ! 362: CC_STATUS_INIT; ! 363: ! 364: /* Get past the MEMs. */ ! 365: operands[0] = XEXP (operands[0], 0); ! 366: operands[1] = XEXP (operands[1], 0); ! 367: ! 368: xoperands[0] = 0; ! 369: xoperands[1] = 0; ! 370: xoperands[2] = 0; ! 371: ! 372: available[0] = 1; ! 373: available[1] = 1; ! 374: available[2] = 1; ! 375: #if 1 ! 376: /* Prepare to juggle registers if necessary. */ ! 377: if (REG_P (operands[0]) && (unsigned) (REGNO (operands[0]) - 8) < 3) ! 378: { ! 379: xoperands[0] = operands[0]; ! 380: available[REGNO (operands[0]) - 8] = 0; ! 381: } ! 382: if (REG_P (operands[1]) && (unsigned) (REGNO (operands[1]) - 8) < 3) ! 383: { ! 384: xoperands[1] = operands[1]; ! 385: available[REGNO (operands[1]) - 8] = 0; ! 386: } ! 387: if (REG_P (operands[2]) && (unsigned) (REGNO (operands[2]) - 8) < 3) ! 388: { ! 389: xoperands[2] = operands[2]; ! 390: available[REGNO (operands[2]) - 8] = 0; ! 391: } ! 392: for (i = 0; i < 3; i++) ! 393: { ! 394: if (xoperands[i]) ! 395: continue; ! 396: if (available[0]) ! 397: { ! 398: xoperands[i] = gen_rtx (REG, SImode, 8); ! 399: available[0] = 0; ! 400: continue; ! 401: } ! 402: if (available[1]) ! 403: { ! 404: xoperands[i] = gen_rtx (REG, SImode, 9); ! 405: available[1] = 0; ! 406: continue; ! 407: } ! 408: xoperands[i] = gen_rtx (REG, SImode, 10); ! 409: available[2] = 0; ! 410: } ! 411: #endif ! 412: ! 413: /* First, figure out best alignment we may assume. */ ! 414: if (REG_P (operands[2])) ! 415: { ! 416: xoperands[5] = operands[2]; ! 417: output_asm_insn ("sub %5,0x1,%2", xoperands); ! 418: align = 1; ! 419: } ! 420: else ! 421: { ! 422: int i = INTVAL (operands[2]); ! 423: ! 424: if (i & 1) ! 425: align = 1; ! 426: else if (i & 3) ! 427: align = 2; ! 428: ! 429: /* predecrement count. */ ! 430: i -= align; ! 431: if (i < 0) abort (); ! 432: ! 433: xoperands[5] = gen_rtx (CONST_INT, VOIDmode, i); ! 434: ! 435: output_asm_insn ("set %5,%2", xoperands); ! 436: } ! 437: ! 438: /* Now, set up for pipelined operation: dest must contain ! 439: a pre-incremented address, because its index is pre-decremented. */ ! 440: ! 441: xoperands[3] = plus_constant (operands[0], align); ! 442: output_load_address (xoperands); ! 443: ! 444: xoperands[4] = operands[1]; ! 445: output_load_address (xoperands+1); ! 446: ! 447: xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++); ! 448: xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align); ! 449: ! 450: output_asm_insn ("\nLm%3:\n\tld [%1+%2],%%o7\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tst %%o7,[%0+%2]", xoperands); ! 451: return ""; ! 452: } ! 453: ! 454: #define ABS(x) ((x) < 0 ? -(x) : x) ! 455: ! 456: char * ! 457: output_mul_by_constant (insn, operands, unsignedp) ! 458: rtx insn; ! 459: rtx *operands; ! 460: int unsignedp; ! 461: { ! 462: int c; /* Size of constant */ ! 463: int shifts[BITS_PER_WORD]; /* Table of shifts */ ! 464: int p, log; /* A power of two, and its log */ ! 465: int d1, d2; /* Differences of c and p */ ! 466: int first = 1; /* True if dst has unknown data in it */ ! 467: int i; ! 468: ! 469: c = INTVAL (operands[2]); ! 470: if (c == 0) ! 471: { ! 472: /* should not happen. */ ! 473: abort (); ! 474: if (GET_CODE (operands[0]) == MEM) ! 475: return "st %%g0,%0"; ! 476: return "mov %%g0,%0"; ! 477: } ! 478: ! 479: #if 0 ! 480: printf ("open coding insn:\n"); ! 481: debug_rtx (insn); ! 482: printf ("done.\n"); ! 483: #endif ! 484: ! 485: output_asm_insn ("! start open coded multiply"); ! 486: ! 487: /* Clear out the table of shifts. */ ! 488: for (i = 0; i < BITS_PER_WORD; ++i) ! 489: shifts[i] = 0; ! 490: ! 491: while (c) ! 492: { ! 493: /* Find the power of two nearest ABS(c) */ ! 494: p = 1, log = 0; ! 495: do ! 496: { ! 497: d1 = ABS(c) - p; ! 498: p *= 2; ! 499: ++log; ! 500: } ! 501: while (p < ABS(c)); ! 502: d2 = p - ABS(c); ! 503: ! 504: /* Make an appropriate entry in shifts for p. */ ! 505: if (d2 < d1) ! 506: { ! 507: shifts[log] = c < 0 ? -1 : 1; ! 508: c = c < 0 ? d2 : -d2; ! 509: } ! 510: else ! 511: { ! 512: shifts[log - 1] = c < 0 ? -1 : 1; ! 513: c = c < 0 ? -d1 : d1; ! 514: } ! 515: } ! 516: ! 517: /* For now, use a known clobberable register. This could ! 518: be improved by looking at insn, and seeing if we ! 519: have a dying register contained therein. */ ! 520: regs_ever_live[15] = 1; ! 521: operands[3] = gen_rtx (REG, SImode, 15); ! 522: ! 523: /* Take care of the first insn in sequence. ! 524: We know we have at least one. */ ! 525: ! 526: /* A value of -1 in shifts says to subtract that power of two, and a value ! 527: of 1 says to add that power of two. */ ! 528: for (i = 0; ; i++) ! 529: if (shifts[i]) ! 530: { ! 531: if (i) ! 532: { ! 533: operands[2] = gen_rtx (CONST_INT, VOIDmode, i); ! 534: output_asm_insn ("sll %1,%2,%3", operands); ! 535: } ! 536: else if (REGNO (operands[3]) == 15) ! 537: output_asm_insn ("mov %1,%3", operands); ! 538: ! 539: log = i; ! 540: if (shifts[i] < 0) ! 541: output_asm_insn ("sub %%g0,%3,%0", operands); ! 542: else ! 543: output_asm_insn ("mov %3,%0", operands); ! 544: break; ! 545: } ! 546: ! 547: /* A value of -1 in shifts says to subtract that power of two, and a value ! 548: of 1 says to add that power of two--continued. */ ! 549: for (i += 1; i < BITS_PER_WORD; ++i) ! 550: if (shifts[i]) ! 551: { ! 552: if (i - log > 0) ! 553: { ! 554: operands[2] = gen_rtx (CONST_INT, VOIDmode, i - log); ! 555: output_asm_insn ("sll %3,%2,%3", operands); ! 556: } ! 557: else ! 558: { ! 559: operands[2] = gen_rtx (CONST_INT, VOIDmode, log - i); ! 560: output_asm_insn ("sra %3,%2,%3", operands); ! 561: } ! 562: log = i; ! 563: if (shifts[i] < 0) ! 564: output_asm_insn ("sub %0,%3,%0", operands); ! 565: else ! 566: output_asm_insn ("add %0,%3,%0", operands); ! 567: } ! 568: ! 569: output_asm_insn ("! end open coded multiply"); ! 570: ! 571: return ""; ! 572: } ! 573: ! 574: char * ! 575: output_mul_insn (operands, unsignedp) ! 576: rtx *operands; ! 577: int unsignedp; ! 578: { ! 579: int lucky1 = ((unsigned)REGNO (operands[1]) - 8) <= 1; ! 580: int lucky2 = ((unsigned)REGNO (operands[2]) - 8) <= 1; ! 581: ! 582: if (lucky1) ! 583: if (lucky2) ! 584: output_asm_insn ("call .mul,2\n\tnop", operands); ! 585: else ! 586: { ! 587: rtx xoperands[2]; ! 588: xoperands[0] = gen_rtx (REG, SImode, ! 589: 8 ^ (REGNO (operands[1]) == 8)); ! 590: xoperands[1] = operands[2]; ! 591: output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands); ! 592: } ! 593: else if (lucky2) ! 594: { ! 595: rtx xoperands[2]; ! 596: xoperands[0] = gen_rtx (REG, SImode, ! 597: 8 ^ (REGNO (operands[2]) == 8)); ! 598: xoperands[1] = operands[1]; ! 599: output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands); ! 600: } ! 601: else ! 602: { ! 603: output_asm_insn ("mov %1,%%o0\n\tcall .mul,2\n\tmov %2,%%o1", ! 604: operands); ! 605: } ! 606: ! 607: if (REGNO (operands[0]) == 8) ! 608: return ""; ! 609: return "mov %%o0,%0"; ! 610: } ! 611: ! 612: #if 0 ! 613: /* This function does not properly protect its operands. */ ! 614: char * ! 615: output_arith_insn (operands, name) ! 616: rtx *operands; ! 617: char *name; ! 618: { ! 619: extern struct _iobuf *asm_out_file; ! 620: ! 621: /* Does not commute. */ ! 622: rtx op1 = 0; ! 623: rtx op2 = 0; ! 624: ! 625: abort (); ! 626: if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 8) ! 627: op1 = operands[1]; ! 628: if (GET_CODE (operands[2]) == REG && REGNO (operands[2]) == 8) ! 629: op2 = operands[2]; ! 630: ! 631: if (op1 && op2) ! 632: { ! 633: /* ?? should have been done earlier. */ ! 634: abort (); ! 635: } ! 636: else ! 637: { ! 638: if (op2) ! 639: { ! 640: op1 = operands[1]; ! 641: if (REG_P (op1) && REGNO (op1) == 9) ! 642: { ! 643: output_asm_insn ("mov %%o1,%%o2\n\tmov %%o0,%%o1", operands); ! 644: fprintf (asm_out_file, "\tcall %s,2\n", name); ! 645: output_asm_insn ("mov %%o2,%%o0", operands); ! 646: goto done; ! 647: } ! 648: output_asm_insn ("mov %%o0,%%o1", operands); ! 649: if (GET_CODE (op1) == CONST_INT && ! SMALL_INT (op1)) ! 650: { ! 651: output_asm_insn ("sethi %%hi(%1),%%o0", operands); ! 652: fprintf (asm_out_file, "\tcall %s,2\n", name); ! 653: output_asm_insn ("add %%o0,%%lo(%1),%%o0", operands); ! 654: } ! 655: else ! 656: { ! 657: fprintf (asm_out_file, "\tcall %s,2\n", name); ! 658: if (GET_CODE (op1) == MEM) ! 659: output_asm_insn ("ld %1,%%o0", operands); ! 660: else ! 661: output_asm_insn ("mov %1,%%o0", operands); ! 662: } ! 663: } ! 664: else if (op1) ! 665: { ! 666: op2 = operands[2]; ! 667: if (REG_P (op2) && REGNO (operands[1]) == 9) ! 668: { ! 669: fprintf (asm_out_file, "\tcall %s,2\n\tnop\n"); ! 670: goto done; ! 671: } ! 672: if (GET_CODE (op2) == CONST_INT && ! SMALL_INT (op2)) ! 673: { ! 674: output_asm_insn ("sethi %%hi(%2),%%o1", operands); ! 675: fprintf (asm_out_file, "\tcall %s,2\n", name); ! 676: output_asm_insn ("add %%o1,%%lo(%2),%%o1", operands); ! 677: } ! 678: else ! 679: { ! 680: fprintf (asm_out_file, "\tcall %s,2\n", name); ! 681: if (GET_CODE (op2) == MEM) ! 682: output_asm_insn ("ld %2,%%o1", operands); ! 683: else ! 684: output_asm_insn ("mov %2,%%o1", operands); ! 685: } ! 686: } ! 687: else ! 688: { ! 689: op1 = operands[1]; ! 690: op2 = operands[2]; ! 691: ! 692: if (! REG_P (op2) || REGNO (op2) != 9) ! 693: if (GET_CODE (op2) == MEM) ! 694: output_asm_insn ("ld %2,%%o1", operands); ! 695: else if (GET_CODE (op2) != CONST_INT || SMALL_INT (op2)) ! 696: output_asm_insn ("mov %2,%%o1", operands); ! 697: else ! 698: output_asm_insn ("sethi %%hi(%2),%%o1\n\tadd %%o1,%%lo(%2),%%o1", operands); ! 699: if (GET_CODE (op1) == CONST_INT && ! SMALL_INT (op1)) ! 700: { ! 701: output_asm_insn ("sethi %%hi(%1),%%o0", operands); ! 702: fprintf (asm_out_file, "\tcall %s,2\n", name); ! 703: output_asm_insn ("add %%o0,%%lo(%1),%%o0", operands); ! 704: } ! 705: else ! 706: { ! 707: fprintf (asm_out_file, "\tcall %s,2\n", name); ! 708: if (GET_CODE (op1) == MEM) ! 709: output_asm_insn ("ld %1,%%o0", operands); ! 710: else ! 711: output_asm_insn ("mov %1,%%o0", operands); ! 712: } ! 713: } ! 714: done: ! 715: if (REG_P (operands[0]) && REGNO (operands[0]) == 8) ! 716: return ""; ! 717: if (GET_CODE (operands[0]) == MEM) ! 718: return "st %%o0,%0"; ! 719: return "mov %%o0,%0"; ! 720: } ! 721: } ! 722: #endif ! 723: ! 724: /* Make floating point register f0 contain 0. ! 725: SIZE is the number of registers (including f0) ! 726: which should contain 0. */ ! 727: ! 728: void ! 729: make_f0_contain_0 (size) ! 730: int size; ! 731: { ! 732: rtx xoperands[1]; ! 733: int offset = - get_frame_size () - 8; ! 734: ! 735: xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset); ! 736: if (size == 1) ! 737: output_asm_insn ("ld [%%fp%0],%%f0", xoperands); ! 738: else if (size == 2) ! 739: output_asm_insn ("ldd [%%fp%0],%%f0", xoperands); ! 740: } ! 741: ! 742: #if 0 ! 743: /* This was needed only for the "alloca" instruction. */ ! 744: #include "tree.h" ! 745: ! 746: int ! 747: tree_uid (node) ! 748: tree node; ! 749: { ! 750: return TREE_UID (node); ! 751: } ! 752: #endif ! 753:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.