|
|
1.1.1.3 ! root 1: /* Subroutines for insn-output.c for Intel X86. ! 2: Copyright (C) 1988, 1992, 1994 Free Software Foundation, Inc. 1.1 root 3: 4: This file is part of GNU CC. 5: 6: GNU CC is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU CC is distributed in the hope that it will be useful, 12: but WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14: GNU General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU CC; see the file COPYING. If not, write to 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 19: 20: #include <stdio.h> 21: #include <setjmp.h> 22: #include "config.h" 23: #include "rtl.h" 24: #include "regs.h" 25: #include "hard-reg-set.h" 26: #include "real.h" 27: #include "insn-config.h" 28: #include "conditions.h" 29: #include "insn-flags.h" 30: #include "output.h" 31: #include "insn-attr.h" 32: #include "tree.h" 33: #include "flags.h" 1.1.1.2 root 34: #include "function.h" 1.1 root 35: 36: #ifdef EXTRA_CONSTRAINT 37: /* If EXTRA_CONSTRAINT is defined, then the 'S' 38: constraint in REG_CLASS_FROM_LETTER will no longer work, and various 39: asm statements that need 'S' for class SIREG will break. */ 40: error EXTRA_CONSTRAINT conflicts with S constraint letter 41: /* The previous line used to be #error, but some compilers barf 42: even if the conditional was untrue. */ 43: #endif 44: 45: #define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx)) 46: 47: extern FILE *asm_out_file; 48: extern char *strcat (); 49: 50: char *singlemove_string (); 51: char *output_move_const_single (); 52: char *output_fp_cc0_set (); 53: 54: char *hi_reg_name[] = HI_REGISTER_NAMES; 55: char *qi_reg_name[] = QI_REGISTER_NAMES; 56: char *qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES; 57: 58: /* Array of the smallest class containing reg number REGNO, indexed by 59: REGNO. Used by REGNO_REG_CLASS in i386.h. */ 60: 61: enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] = 62: { 63: /* ax, dx, cx, bx */ 64: AREG, DREG, CREG, BREG, 65: /* si, di, bp, sp */ 66: SIREG, DIREG, INDEX_REGS, GENERAL_REGS, 67: /* FP registers */ 68: FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS, 69: FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, 70: /* arg pointer */ 71: INDEX_REGS 72: }; 73: 74: /* Test and compare insns in i386.md store the information needed to 75: generate branch and scc insns here. */ 76: 1.1.1.3 ! root 77: struct rtx_def *i386_compare_op0 = NULL_RTX; ! 78: struct rtx_def *i386_compare_op1 = NULL_RTX; 1.1 root 79: struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); 1.1.1.3 ! root 80: ! 81: /* Register allocation order */ ! 82: char *i386_reg_alloc_order = (char *)0; ! 83: static char regs_allocated[FIRST_PSEUDO_REGISTER]; ! 84: ! 85: ! 86: /* Sometimes certain combinations of command options do not make ! 87: sense on a particular target machine. You can define a macro ! 88: `OVERRIDE_OPTIONS' to take account of this. This macro, if ! 89: defined, is executed once just after all the command options have ! 90: been parsed. ! 91: ! 92: Don't use this macro to turn on various extra optimizations for ! 93: `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ ! 94: ! 95: void ! 96: override_options () ! 97: { ! 98: int ch, i, regno; ! 99: ! 100: #ifdef SUBTARGET_OVERRIDE_OPTIONS ! 101: SUBTARGET_OVERRIDE_OPTIONS; ! 102: #endif ! 103: ! 104: /* Validate registers in register allocation order */ ! 105: if (i386_reg_alloc_order) ! 106: { ! 107: for (i = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++) ! 108: { ! 109: switch (ch) ! 110: { ! 111: case 'a': regno = 0; break; ! 112: case 'd': regno = 1; break; ! 113: case 'c': regno = 2; break; ! 114: case 'b': regno = 3; break; ! 115: case 'S': regno = 4; break; ! 116: case 'D': regno = 5; break; ! 117: case 'B': regno = 6; break; ! 118: ! 119: default: fatal ("Register '%c' is unknown", ch); ! 120: } ! 121: ! 122: if (regs_allocated[regno]) ! 123: fatal ("Register '%c' was already specified in the allocation order", ch); ! 124: ! 125: regs_allocated[regno] = 1; ! 126: } ! 127: } ! 128: } ! 129: ! 130: /* A C statement (sans semicolon) to choose the order in which to ! 131: allocate hard registers for pseudo-registers local to a basic ! 132: block. ! 133: ! 134: Store the desired register order in the array `reg_alloc_order'. ! 135: Element 0 should be the register to allocate first; element 1, the ! 136: next register; and so on. ! 137: ! 138: The macro body should not assume anything about the contents of ! 139: `reg_alloc_order' before execution of the macro. ! 140: ! 141: On most machines, it is not necessary to define this macro. */ ! 142: ! 143: void ! 144: order_regs_for_local_alloc () ! 145: { ! 146: int i, ch, order, regno; ! 147: ! 148: /* User specified the register allocation order */ ! 149: if (i386_reg_alloc_order) ! 150: { ! 151: for (i = order = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++) ! 152: { ! 153: switch (ch) ! 154: { ! 155: case 'a': regno = 0; break; ! 156: case 'd': regno = 1; break; ! 157: case 'c': regno = 2; break; ! 158: case 'b': regno = 3; break; ! 159: case 'S': regno = 4; break; ! 160: case 'D': regno = 5; break; ! 161: case 'B': regno = 6; break; ! 162: } ! 163: ! 164: reg_alloc_order[order++] = regno; ! 165: } ! 166: ! 167: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 168: { ! 169: if (!regs_allocated[i]) ! 170: reg_alloc_order[order++] = i; ! 171: } ! 172: } ! 173: ! 174: /* If users did not specify a register allocation order, favor eax ! 175: normally except if DImode variables are used, in which case ! 176: favor edx before eax, which seems to cause less spill register ! 177: not found messages. */ ! 178: else ! 179: { ! 180: rtx insn; ! 181: ! 182: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 183: reg_alloc_order[i] = i; ! 184: ! 185: if (optimize) ! 186: { ! 187: int use_dca = FALSE; ! 188: ! 189: for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) ! 190: { ! 191: if (GET_CODE (insn) == INSN) ! 192: { ! 193: rtx set = NULL_RTX; ! 194: rtx pattern = PATTERN (insn); ! 195: ! 196: if (GET_CODE (pattern) == SET) ! 197: set = pattern; ! 198: ! 199: else if ((GET_CODE (pattern) == PARALLEL ! 200: || GET_CODE (pattern) == SEQUENCE) ! 201: && GET_CODE (XVECEXP (pattern, 0, 0)) == SET) ! 202: set = XVECEXP (pattern, 0, 0); ! 203: ! 204: if (set && GET_MODE (SET_SRC (set)) == DImode) ! 205: { ! 206: use_dca = TRUE; ! 207: break; ! 208: } ! 209: } ! 210: } ! 211: ! 212: if (use_dca) ! 213: { ! 214: reg_alloc_order[0] = 1; /* edx */ ! 215: reg_alloc_order[1] = 2; /* ecx */ ! 216: reg_alloc_order[2] = 0; /* eax */ ! 217: } ! 218: } ! 219: } ! 220: } ! 221: 1.1 root 222: 223: /* Output an insn whose source is a 386 integer register. SRC is the 224: rtx for the register, and TEMPLATE is the op-code template. SRC may 225: be either SImode or DImode. 226: 227: The template will be output with operands[0] as SRC, and operands[1] 228: as a pointer to the top of the 386 stack. So a call from floatsidf2 229: would look like this: 230: 231: output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 232: 233: where %z0 corresponds to the caller's operands[1], and is used to 234: emit the proper size suffix. 235: 236: ??? Extend this to handle HImode - a 387 can load and store HImode 237: values directly. */ 238: 239: void 240: output_op_from_reg (src, template) 241: rtx src; 242: char *template; 243: { 244: rtx xops[4]; 1.1.1.2 root 245: int size = GET_MODE_SIZE (GET_MODE (src)); 1.1 root 246: 247: xops[0] = src; 248: xops[1] = AT_SP (Pmode); 1.1.1.2 root 249: xops[2] = GEN_INT (size); 1.1 root 250: xops[3] = stack_pointer_rtx; 251: 1.1.1.2 root 252: if (size > UNITS_PER_WORD) 1.1 root 253: { 1.1.1.2 root 254: rtx high; 255: if (size > 2 * UNITS_PER_WORD) 256: { 257: high = gen_rtx (REG, SImode, REGNO (src) + 2); 258: output_asm_insn (AS1 (push%L0,%0), &high); 259: } 260: high = gen_rtx (REG, SImode, REGNO (src) + 1); 1.1 root 261: output_asm_insn (AS1 (push%L0,%0), &high); 262: } 263: output_asm_insn (AS1 (push%L0,%0), &src); 264: 265: output_asm_insn (template, xops); 266: 267: output_asm_insn (AS2 (add%L3,%2,%3), xops); 268: } 269: 270: /* Output an insn to pop an value from the 387 top-of-stack to 386 271: register DEST. The 387 register stack is popped if DIES is true. If 272: the mode of DEST is an integer mode, a `fist' integer store is done, 273: otherwise a `fst' float store is done. */ 274: 275: void 276: output_to_reg (dest, dies) 277: rtx dest; 278: int dies; 279: { 280: rtx xops[4]; 1.1.1.2 root 281: int size = GET_MODE_SIZE (GET_MODE (dest)); 1.1 root 282: 283: xops[0] = AT_SP (Pmode); 284: xops[1] = stack_pointer_rtx; 1.1.1.2 root 285: xops[2] = GEN_INT (size); 1.1 root 286: xops[3] = dest; 287: 288: output_asm_insn (AS2 (sub%L1,%2,%1), xops); 289: 290: if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT) 291: { 292: if (dies) 293: output_asm_insn (AS1 (fistp%z3,%y0), xops); 294: else 295: output_asm_insn (AS1 (fist%z3,%y0), xops); 296: } 297: else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT) 298: { 299: if (dies) 300: output_asm_insn (AS1 (fstp%z3,%y0), xops); 301: else 1.1.1.2 root 302: { 303: if (GET_MODE (dest) == XFmode) 304: { 305: output_asm_insn (AS1 (fstp%z3,%y0), xops); 306: output_asm_insn (AS1 (fld%z3,%y0), xops); 307: } 308: else 309: output_asm_insn (AS1 (fst%z3,%y0), xops); 310: } 1.1 root 311: } 312: else 313: abort (); 314: 315: output_asm_insn (AS1 (pop%L0,%0), &dest); 316: 1.1.1.2 root 317: if (size > UNITS_PER_WORD) 1.1 root 318: { 319: dest = gen_rtx (REG, SImode, REGNO (dest) + 1); 320: output_asm_insn (AS1 (pop%L0,%0), &dest); 1.1.1.2 root 321: if (size > 2 * UNITS_PER_WORD) 322: { 323: dest = gen_rtx (REG, SImode, REGNO (dest) + 1); 324: output_asm_insn (AS1 (pop%L0,%0), &dest); 325: } 1.1 root 326: } 327: } 328: 329: char * 330: singlemove_string (operands) 331: rtx *operands; 332: { 333: rtx x; 334: if (GET_CODE (operands[0]) == MEM 335: && GET_CODE (x = XEXP (operands[0], 0)) == PRE_DEC) 336: { 337: if (XEXP (x, 0) != stack_pointer_rtx) 338: abort (); 339: return "push%L1 %1"; 340: } 341: else if (GET_CODE (operands[1]) == CONST_DOUBLE) 342: { 343: return output_move_const_single (operands); 344: } 345: else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG) 346: return AS2 (mov%L0,%1,%0); 347: else if (CONSTANT_P (operands[1])) 348: return AS2 (mov%L0,%1,%0); 349: else 350: { 351: output_asm_insn ("push%L1 %1", operands); 352: return "pop%L0 %0"; 353: } 354: } 355: 356: /* Return a REG that occurs in ADDR with coefficient 1. 357: ADDR can be effectively incremented by incrementing REG. */ 358: 359: static rtx 360: find_addr_reg (addr) 361: rtx addr; 362: { 363: while (GET_CODE (addr) == PLUS) 364: { 365: if (GET_CODE (XEXP (addr, 0)) == REG) 366: addr = XEXP (addr, 0); 367: else if (GET_CODE (XEXP (addr, 1)) == REG) 368: addr = XEXP (addr, 1); 369: else if (CONSTANT_P (XEXP (addr, 0))) 370: addr = XEXP (addr, 1); 371: else if (CONSTANT_P (XEXP (addr, 1))) 372: addr = XEXP (addr, 0); 373: else 374: abort (); 375: } 376: if (GET_CODE (addr) == REG) 377: return addr; 378: abort (); 379: } 380: 1.1.1.3 ! root 381: 1.1 root 382: /* Output an insn to add the constant N to the register X. */ 383: 384: static void 385: asm_add (n, x) 386: int n; 387: rtx x; 388: { 389: rtx xops[2]; 1.1.1.3 ! root 390: xops[0] = x; ! 391: ! 392: if (n == -1) ! 393: output_asm_insn (AS1 (dec%L0,%0), xops); ! 394: else if (n == 1) ! 395: output_asm_insn (AS1 (inc%L0,%0), xops); ! 396: else if (n < 0) 1.1 root 397: { 1.1.1.3 ! root 398: xops[1] = GEN_INT (-n); ! 399: output_asm_insn (AS2 (sub%L0,%1,%0), xops); 1.1 root 400: } 401: else if (n > 0) 402: { 1.1.1.3 ! root 403: xops[1] = GEN_INT (n); ! 404: output_asm_insn (AS2 (add%L0,%1,%0), xops); 1.1 root 405: } 406: } 407: 1.1.1.3 ! root 408: 1.1 root 409: /* Output assembler code to perform a doubleword move insn 410: with operands OPERANDS. */ 411: 412: char * 413: output_move_double (operands) 414: rtx *operands; 415: { 416: enum {REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1; 417: rtx latehalf[2]; 1.1.1.2 root 418: rtx middlehalf[2]; 419: rtx xops[2]; 1.1 root 420: rtx addreg0 = 0, addreg1 = 0; 421: int dest_overlapped_low = 0; 1.1.1.2 root 422: int size = GET_MODE_SIZE (GET_MODE (operands[1])); 423: 424: middlehalf[0] = 0; 425: middlehalf[1] = 0; 1.1 root 426: 427: /* First classify both operands. */ 428: 429: if (REG_P (operands[0])) 430: optype0 = REGOP; 431: else if (offsettable_memref_p (operands[0])) 432: optype0 = OFFSOP; 433: else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) 434: optype0 = POPOP; 435: else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 436: optype0 = PUSHOP; 437: else if (GET_CODE (operands[0]) == MEM) 438: optype0 = MEMOP; 439: else 440: optype0 = RNDOP; 441: 442: if (REG_P (operands[1])) 443: optype1 = REGOP; 444: else if (CONSTANT_P (operands[1])) 445: optype1 = CNSTOP; 446: else if (offsettable_memref_p (operands[1])) 447: optype1 = OFFSOP; 448: else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC) 449: optype1 = POPOP; 450: else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) 451: optype1 = PUSHOP; 452: else if (GET_CODE (operands[1]) == MEM) 453: optype1 = MEMOP; 454: else 455: optype1 = RNDOP; 456: 457: /* Check for the cases that the operand constraints are not 458: supposed to allow to happen. Abort if we get one, 459: because generating code for these cases is painful. */ 460: 461: if (optype0 == RNDOP || optype1 == RNDOP) 462: abort (); 463: 464: /* If one operand is decrementing and one is incrementing 465: decrement the former register explicitly 466: and change that operand into ordinary indexing. */ 467: 468: if (optype0 == PUSHOP && optype1 == POPOP) 469: { 1.1.1.2 root 470: /* ??? Can this ever happen on i386? */ 1.1 root 471: operands[0] = XEXP (XEXP (operands[0], 0), 0); 1.1.1.2 root 472: asm_add (-size, operands[0]); 473: if (GET_MODE (operands[1]) == XFmode) 474: operands[0] = gen_rtx (MEM, XFmode, operands[0]); 475: else if (GET_MODE (operands[0]) == DFmode) 476: operands[0] = gen_rtx (MEM, DFmode, operands[0]); 477: else 478: operands[0] = gen_rtx (MEM, DImode, operands[0]); 1.1 root 479: optype0 = OFFSOP; 480: } 1.1.1.2 root 481: 1.1 root 482: if (optype0 == POPOP && optype1 == PUSHOP) 483: { 1.1.1.2 root 484: /* ??? Can this ever happen on i386? */ 1.1 root 485: operands[1] = XEXP (XEXP (operands[1], 0), 0); 1.1.1.2 root 486: asm_add (-size, operands[1]); 487: if (GET_MODE (operands[1]) == XFmode) 488: operands[1] = gen_rtx (MEM, XFmode, operands[1]); 489: else if (GET_MODE (operands[1]) == DFmode) 490: operands[1] = gen_rtx (MEM, DFmode, operands[1]); 491: else 492: operands[1] = gen_rtx (MEM, DImode, operands[1]); 1.1 root 493: optype1 = OFFSOP; 494: } 495: 496: /* If an operand is an unoffsettable memory ref, find a register 497: we can increment temporarily to make it refer to the second word. */ 498: 499: if (optype0 == MEMOP) 500: addreg0 = find_addr_reg (XEXP (operands[0], 0)); 501: 502: if (optype1 == MEMOP) 503: addreg1 = find_addr_reg (XEXP (operands[1], 0)); 504: 505: /* Ok, we can do one word at a time. 506: Normally we do the low-numbered word first, 507: but if either operand is autodecrementing then we 508: do the high-numbered word first. 509: 510: In either case, set up in LATEHALF the operands to use 511: for the high-numbered word and in some cases alter the 512: operands in OPERANDS to be suitable for the low-numbered word. */ 513: 1.1.1.2 root 514: if (size == 12) 515: { 516: if (optype0 == REGOP) 517: { 518: middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 519: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2); 520: } 521: else if (optype0 == OFFSOP) 522: { 523: middlehalf[0] = adj_offsettable_operand (operands[0], 4); 524: latehalf[0] = adj_offsettable_operand (operands[0], 8); 525: } 526: else 527: { 528: middlehalf[0] = operands[0]; 529: latehalf[0] = operands[0]; 530: } 531: 532: if (optype1 == REGOP) 533: { 534: middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); 535: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); 536: } 537: else if (optype1 == OFFSOP) 538: { 539: middlehalf[1] = adj_offsettable_operand (operands[1], 4); 540: latehalf[1] = adj_offsettable_operand (operands[1], 8); 541: } 542: else if (optype1 == CNSTOP) 543: { 544: if (GET_CODE (operands[1]) == CONST_DOUBLE) 545: { 546: REAL_VALUE_TYPE r; long l[3]; 1.1 root 547: 1.1.1.2 root 548: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); 549: REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l); 550: operands[1] = GEN_INT (l[0]); 551: middlehalf[1] = GEN_INT (l[1]); 552: latehalf[1] = GEN_INT (l[2]); 553: } 554: else if (CONSTANT_P (operands[1])) 555: /* No non-CONST_DOUBLE constant should ever appear here. */ 556: abort (); 557: } 558: else 1.1 root 559: { 1.1.1.2 root 560: middlehalf[1] = operands[1]; 561: latehalf[1] = operands[1]; 1.1 root 562: } 563: } 1.1.1.2 root 564: else /* size is not 12: */ 565: { 566: if (optype0 == REGOP) 567: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 568: else if (optype0 == OFFSOP) 569: latehalf[0] = adj_offsettable_operand (operands[0], 4); 570: else 571: latehalf[0] = operands[0]; 572: 573: if (optype1 == REGOP) 574: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); 575: else if (optype1 == OFFSOP) 576: latehalf[1] = adj_offsettable_operand (operands[1], 4); 577: else if (optype1 == CNSTOP) 578: { 579: if (GET_CODE (operands[1]) == CONST_DOUBLE) 580: split_double (operands[1], &operands[1], &latehalf[1]); 581: else if (CONSTANT_P (operands[1])) 582: { 583: /* ??? jrv: Can this really happen? A DImode constant 584: that isn't a CONST_DOUBLE? */ 585: if (GET_CODE (operands[1]) == CONST_INT 586: && INTVAL (operands[1]) < 0) 587: latehalf[1] = constm1_rtx; 588: else 589: latehalf[1] = const0_rtx; 590: } 591: } 592: else 593: latehalf[1] = operands[1]; 594: } 1.1 root 595: 596: /* If insn is effectively movd N (sp),-(sp) then we will do the 1.1.1.2 root 597: high word first. We should use the adjusted operand 1 598: (which is N+4 (sp) or N+8 (sp)) 599: for the low word and middle word as well, 600: to compensate for the first decrement of sp. */ 1.1 root 601: if (optype0 == PUSHOP 602: && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM 603: && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1])) 1.1.1.2 root 604: middlehalf[1] = operands[1] = latehalf[1]; 1.1 root 605: 606: /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)), 607: if the upper part of reg N does not appear in the MEM, arrange to 608: emit the move late-half first. Otherwise, compute the MEM address 609: into the upper part of N and use that as a pointer to the memory 610: operand. */ 611: if (optype0 == REGOP 612: && (optype1 == OFFSOP || optype1 == MEMOP)) 613: { 614: if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)) 615: && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) 616: { 617: /* If both halves of dest are used in the src memory address, 618: compute the address into latehalf of dest. */ 1.1.1.2 root 619: compadr: 1.1 root 620: xops[0] = latehalf[0]; 621: xops[1] = XEXP (operands[1], 0); 622: output_asm_insn (AS2 (lea%L0,%a1,%0), xops); 1.1.1.2 root 623: if( GET_MODE (operands[1]) == XFmode ) 624: { 625: /* abort (); */ 626: operands[1] = gen_rtx (MEM, XFmode, latehalf[0]); 627: middlehalf[1] = adj_offsettable_operand (operands[1], size-8); 628: latehalf[1] = adj_offsettable_operand (operands[1], size-4); 629: } 630: else 631: { 632: operands[1] = gen_rtx (MEM, DImode, latehalf[0]); 633: latehalf[1] = adj_offsettable_operand (operands[1], size-4); 634: } 635: } 636: else if (size == 12 637: && reg_mentioned_p (middlehalf[0], XEXP (operands[1], 0))) 638: { 639: /* Check for two regs used by both source and dest. */ 640: if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)) 641: || reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) 642: goto compadr; 643: 644: /* JRV says this can't happen: */ 645: if (addreg0 || addreg1) 646: abort(); 647: 648: /* Only the middle reg conflicts; simply put it last. */ 649: output_asm_insn (singlemove_string (operands), operands); 650: output_asm_insn (singlemove_string (latehalf), latehalf); 651: output_asm_insn (singlemove_string (middlehalf), middlehalf); 652: return ""; 1.1 root 653: } 654: else if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))) 655: /* If the low half of dest is mentioned in the source memory 656: address, the arrange to emit the move late half first. */ 657: dest_overlapped_low = 1; 658: } 659: 660: /* If one or both operands autodecrementing, 661: do the two words, high-numbered first. */ 662: 663: /* Likewise, the first move would clobber the source of the second one, 664: do them in the other order. This happens only for registers; 665: such overlap can't happen in memory unless the user explicitly 666: sets it up, and that is an undefined circumstance. */ 667: 1.1.1.2 root 668: /* 1.1 root 669: if (optype0 == PUSHOP || optype1 == PUSHOP 670: || (optype0 == REGOP && optype1 == REGOP 671: && REGNO (operands[0]) == REGNO (latehalf[1])) 672: || dest_overlapped_low) 1.1.1.2 root 673: */ 674: if (optype0 == PUSHOP || optype1 == PUSHOP 675: || (optype0 == REGOP && optype1 == REGOP 676: && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1])) 677: || REGNO (operands[0]) == REGNO (latehalf[1]))) 678: || dest_overlapped_low) 1.1 root 679: { 680: /* Make any unoffsettable addresses point at high-numbered word. */ 681: if (addreg0) 1.1.1.2 root 682: asm_add (size-4, addreg0); 1.1 root 683: if (addreg1) 1.1.1.2 root 684: asm_add (size-4, addreg1); 1.1 root 685: 686: /* Do that word. */ 687: output_asm_insn (singlemove_string (latehalf), latehalf); 688: 689: /* Undo the adds we just did. */ 690: if (addreg0) 691: asm_add (-4, addreg0); 692: if (addreg1) 693: asm_add (-4, addreg1); 694: 1.1.1.2 root 695: if (size == 12) 696: { 697: output_asm_insn (singlemove_string (middlehalf), middlehalf); 698: if (addreg0) 699: asm_add (-4, addreg0); 700: if (addreg1) 701: asm_add (-4, addreg1); 702: } 703: 1.1 root 704: /* Do low-numbered word. */ 705: return singlemove_string (operands); 706: } 707: 708: /* Normal case: do the two words, low-numbered first. */ 709: 710: output_asm_insn (singlemove_string (operands), operands); 711: 1.1.1.2 root 712: /* Do the middle one of the three words for long double */ 713: if (size == 12) 714: { 715: if (addreg0) 716: asm_add (4, addreg0); 717: if (addreg1) 718: asm_add (4, addreg1); 719: 720: output_asm_insn (singlemove_string (middlehalf), middlehalf); 721: } 722: 1.1 root 723: /* Make any unoffsettable addresses point at high-numbered word. */ 724: if (addreg0) 725: asm_add (4, addreg0); 726: if (addreg1) 727: asm_add (4, addreg1); 728: 729: /* Do that word. */ 730: output_asm_insn (singlemove_string (latehalf), latehalf); 731: 732: /* Undo the adds we just did. */ 733: if (addreg0) 1.1.1.2 root 734: asm_add (4-size, addreg0); 1.1 root 735: if (addreg1) 1.1.1.2 root 736: asm_add (4-size, addreg1); 1.1 root 737: 738: return ""; 739: } 1.1.1.3 ! root 740: ! 741: ! 742: #define MAX_TMPS 2 /* max temporary registers used */ ! 743: ! 744: /* Output the appropriate code to move push memory on the stack */ ! 745: ! 746: char * ! 747: output_move_pushmem (operands, insn, length, tmp_start, n_operands) ! 748: rtx operands[]; ! 749: rtx insn; ! 750: int length; ! 751: int tmp_start; ! 752: int n_operands; ! 753: { ! 754: ! 755: struct { ! 756: char *load; ! 757: char *push; ! 758: rtx xops[2]; ! 759: } tmp_info[MAX_TMPS]; ! 760: ! 761: rtx src = operands[1]; ! 762: int max_tmps = 0; ! 763: int offset = 0; ! 764: int stack_p = reg_overlap_mentioned_p (stack_pointer_rtx, src); ! 765: int stack_offset = 0; ! 766: int i, num_tmps; ! 767: rtx xops[1]; ! 768: ! 769: if (!offsettable_memref_p (src)) ! 770: fatal_insn ("Source is not offsettable", insn); ! 771: ! 772: if ((length & 3) != 0) ! 773: fatal_insn ("Pushing non-word aligned size", insn); ! 774: ! 775: /* Figure out which temporary registers we have available */ ! 776: for (i = tmp_start; i < n_operands; i++) ! 777: { ! 778: if (GET_CODE (operands[i]) == REG) ! 779: { ! 780: if (reg_overlap_mentioned_p (operands[i], src)) ! 781: continue; ! 782: ! 783: tmp_info[ max_tmps++ ].xops[1] = operands[i]; ! 784: if (max_tmps == MAX_TMPS) ! 785: break; ! 786: } ! 787: } ! 788: ! 789: if (max_tmps == 0) ! 790: for (offset = length - 4; offset >= 0; offset -= 4) ! 791: { ! 792: xops[0] = adj_offsettable_operand (src, offset + stack_offset); ! 793: output_asm_insn (AS1(push%L0,%0), xops); ! 794: if (stack_p) ! 795: stack_offset += 4; ! 796: } ! 797: ! 798: else ! 799: for (offset = length - 4; offset >= 0; ) ! 800: { ! 801: for (num_tmps = 0; num_tmps < max_tmps && offset >= 0; num_tmps++) ! 802: { ! 803: tmp_info[num_tmps].load = AS2(mov%L0,%0,%1); ! 804: tmp_info[num_tmps].push = AS1(push%L0,%1); ! 805: tmp_info[num_tmps].xops[0] = adj_offsettable_operand (src, offset + stack_offset); ! 806: offset -= 4; ! 807: } ! 808: ! 809: for (i = 0; i < num_tmps; i++) ! 810: output_asm_insn (tmp_info[i].load, tmp_info[i].xops); ! 811: ! 812: for (i = 0; i < num_tmps; i++) ! 813: output_asm_insn (tmp_info[i].push, tmp_info[i].xops); ! 814: ! 815: if (stack_p) ! 816: stack_offset += 4*num_tmps; ! 817: } ! 818: ! 819: return ""; ! 820: } ! 821: ! 822: ! 823: ! 824: /* Output the appropriate code to move data between two memory locations */ ! 825: ! 826: char * ! 827: output_move_memory (operands, insn, length, tmp_start, n_operands) ! 828: rtx operands[]; ! 829: rtx insn; ! 830: int length; ! 831: int tmp_start; ! 832: int n_operands; ! 833: { ! 834: struct { ! 835: char *load; ! 836: char *store; ! 837: rtx xops[3]; ! 838: } tmp_info[MAX_TMPS]; ! 839: ! 840: rtx dest = operands[0]; ! 841: rtx src = operands[1]; ! 842: rtx qi_tmp = NULL_RTX; ! 843: int max_tmps = 0; ! 844: int offset = 0; ! 845: int i, num_tmps; ! 846: rtx xops[3]; ! 847: ! 848: if (GET_CODE (dest) == MEM ! 849: && GET_CODE (XEXP (dest, 0)) == PRE_INC ! 850: && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx) ! 851: return output_move_pushmem (operands, insn, length, tmp_start, n_operands); ! 852: ! 853: if (!offsettable_memref_p (src)) ! 854: fatal_insn ("Source is not offsettable", insn); ! 855: ! 856: if (!offsettable_memref_p (dest)) ! 857: fatal_insn ("Destination is not offsettable", insn); ! 858: ! 859: /* Figure out which temporary registers we have available */ ! 860: for (i = tmp_start; i < n_operands; i++) ! 861: { ! 862: if (GET_CODE (operands[i]) == REG) ! 863: { ! 864: if ((length & 1) != 0 && !qi_tmp && QI_REG_P (operands[i])) ! 865: qi_tmp = operands[i]; ! 866: ! 867: if (reg_overlap_mentioned_p (operands[i], dest)) ! 868: fatal_insn ("Temporary register overlaps the destination", insn); ! 869: ! 870: if (reg_overlap_mentioned_p (operands[i], src)) ! 871: fatal_insn ("Temporary register overlaps the source", insn); ! 872: ! 873: tmp_info[ max_tmps++ ].xops[2] = operands[i]; ! 874: if (max_tmps == MAX_TMPS) ! 875: break; ! 876: } ! 877: } ! 878: ! 879: if (max_tmps == 0) ! 880: fatal_insn ("No scratch registers were found to do memory->memory moves", insn); ! 881: ! 882: if ((length & 1) != 0) ! 883: { ! 884: if (!qi_tmp) ! 885: fatal_insn ("No byte register found when moving odd # of bytes.", insn); ! 886: } ! 887: ! 888: while (length > 1) ! 889: { ! 890: for (num_tmps = 0; num_tmps < max_tmps; num_tmps++) ! 891: { ! 892: if (length >= 4) ! 893: { ! 894: tmp_info[num_tmps].load = AS2(mov%L0,%1,%2); ! 895: tmp_info[num_tmps].store = AS2(mov%L0,%2,%0); ! 896: tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset); ! 897: tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset); ! 898: offset += 4; ! 899: length -= 4; ! 900: } ! 901: else if (length >= 2) ! 902: { ! 903: tmp_info[num_tmps].load = AS2(mov%W0,%1,%2); ! 904: tmp_info[num_tmps].store = AS2(mov%W0,%2,%0); ! 905: tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset); ! 906: tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset); ! 907: offset += 2; ! 908: length -= 2; ! 909: } ! 910: else ! 911: break; ! 912: } ! 913: ! 914: for (i = 0; i < num_tmps; i++) ! 915: output_asm_insn (tmp_info[i].load, tmp_info[i].xops); ! 916: ! 917: for (i = 0; i < num_tmps; i++) ! 918: output_asm_insn (tmp_info[i].store, tmp_info[i].xops); ! 919: } ! 920: ! 921: if (length == 1) ! 922: { ! 923: xops[0] = adj_offsettable_operand (dest, offset); ! 924: xops[1] = adj_offsettable_operand (src, offset); ! 925: xops[2] = qi_tmp; ! 926: output_asm_insn (AS2(mov%B0,%1,%2), xops); ! 927: output_asm_insn (AS2(mov%B0,%2,%0), xops); ! 928: } ! 929: ! 930: return ""; ! 931: } ! 932: 1.1 root 933: 934: int 935: standard_80387_constant_p (x) 936: rtx x; 937: { 938: #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) 939: REAL_VALUE_TYPE d; 940: jmp_buf handler; 941: int is0, is1; 942: 943: if (setjmp (handler)) 944: return 0; 945: 946: set_float_handler (handler); 947: REAL_VALUE_FROM_CONST_DOUBLE (d, x); 948: is0 = REAL_VALUES_EQUAL (d, dconst0); 949: is1 = REAL_VALUES_EQUAL (d, dconst1); 950: set_float_handler (NULL_PTR); 951: 952: if (is0) 953: return 1; 954: 955: if (is1) 956: return 2; 957: 958: /* Note that on the 80387, other constants, such as pi, 959: are much slower to load as standard constants 960: than to load from doubles in memory! */ 961: #endif 962: 963: return 0; 964: } 965: 966: char * 967: output_move_const_single (operands) 968: rtx *operands; 969: { 970: if (FP_REG_P (operands[0])) 971: { 972: int conval = standard_80387_constant_p (operands[1]); 973: 974: if (conval == 1) 975: return "fldz"; 976: 977: if (conval == 2) 978: return "fld1"; 979: } 980: if (GET_CODE (operands[1]) == CONST_DOUBLE) 981: { 1.1.1.2 root 982: REAL_VALUE_TYPE r; long l; 983: 984: if (GET_MODE (operands[1]) == XFmode) 985: abort (); 986: 987: REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]); 988: REAL_VALUE_TO_TARGET_SINGLE (r, l); 989: operands[1] = GEN_INT (l); 1.1 root 990: } 991: return singlemove_string (operands); 992: } 993: 994: /* Returns 1 if OP is either a symbol reference or a sum of a symbol 995: reference and a constant. */ 996: 997: int 998: symbolic_operand (op, mode) 999: register rtx op; 1000: enum machine_mode mode; 1001: { 1002: switch (GET_CODE (op)) 1003: { 1004: case SYMBOL_REF: 1005: case LABEL_REF: 1006: return 1; 1007: case CONST: 1008: op = XEXP (op, 0); 1009: return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF 1010: || GET_CODE (XEXP (op, 0)) == LABEL_REF) 1011: && GET_CODE (XEXP (op, 1)) == CONST_INT); 1012: default: 1013: return 0; 1014: } 1015: } 1016: 1017: /* Test for a valid operand for a call instruction. 1018: Don't allow the arg pointer register or virtual regs 1019: since they may change into reg + const, which the patterns 1020: can't handle yet. */ 1021: 1022: int 1023: call_insn_operand (op, mode) 1024: rtx op; 1025: enum machine_mode mode; 1026: { 1027: if (GET_CODE (op) == MEM 1028: && ((CONSTANT_ADDRESS_P (XEXP (op, 0)) 1029: /* This makes a difference for PIC. */ 1030: && general_operand (XEXP (op, 0), Pmode)) 1031: || (GET_CODE (XEXP (op, 0)) == REG 1032: && XEXP (op, 0) != arg_pointer_rtx 1033: && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER 1034: && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) 1035: return 1; 1036: return 0; 1037: } 1038: 1039: /* Like call_insn_operand but allow (mem (symbol_ref ...)) 1040: even if pic. */ 1041: 1042: int 1043: expander_call_insn_operand (op, mode) 1044: rtx op; 1045: enum machine_mode mode; 1046: { 1047: if (GET_CODE (op) == MEM 1048: && (CONSTANT_ADDRESS_P (XEXP (op, 0)) 1049: || (GET_CODE (XEXP (op, 0)) == REG 1050: && XEXP (op, 0) != arg_pointer_rtx 1051: && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER 1052: && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) 1053: return 1; 1054: return 0; 1055: } 1056: 1057: /* Returns 1 if OP contains a symbol reference */ 1058: 1059: int 1060: symbolic_reference_mentioned_p (op) 1061: rtx op; 1062: { 1063: register char *fmt; 1064: register int i; 1065: 1066: if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) 1067: return 1; 1068: 1069: fmt = GET_RTX_FORMAT (GET_CODE (op)); 1070: for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) 1071: { 1072: if (fmt[i] == 'E') 1073: { 1074: register int j; 1075: 1076: for (j = XVECLEN (op, i) - 1; j >= 0; j--) 1077: if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) 1078: return 1; 1079: } 1080: else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) 1081: return 1; 1082: } 1083: 1084: return 0; 1085: } 1086: 1087: /* This function generates the assembly code for function entry. 1088: FILE is an stdio stream to output the code to. 1089: SIZE is an int: how many units of temporary storage to allocate. */ 1090: 1091: void 1092: function_prologue (file, size) 1093: FILE *file; 1094: int size; 1095: { 1096: register int regno; 1097: int limit; 1098: rtx xops[4]; 1099: int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table 1100: || current_function_uses_const_pool); 1101: 1102: xops[0] = stack_pointer_rtx; 1103: xops[1] = frame_pointer_rtx; 1104: xops[2] = GEN_INT (size); 1105: if (frame_pointer_needed) 1106: { 1107: output_asm_insn ("push%L1 %1", xops); 1108: output_asm_insn (AS2 (mov%L0,%0,%1), xops); 1109: } 1110: 1111: if (size) 1112: output_asm_insn (AS2 (sub%L0,%2,%0), xops); 1113: 1114: /* Note If use enter it is NOT reversed args. 1115: This one is not reversed from intel!! 1116: I think enter is slower. Also sdb doesn't like it. 1117: But if you want it the code is: 1118: { 1119: xops[3] = const0_rtx; 1120: output_asm_insn ("enter %2,%3", xops); 1121: } 1122: */ 1123: limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); 1124: for (regno = limit - 1; regno >= 0; regno--) 1125: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1126: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1127: { 1128: xops[0] = gen_rtx (REG, SImode, regno); 1129: output_asm_insn ("push%L0 %0", xops); 1130: } 1131: 1132: if (pic_reg_used) 1133: { 1134: xops[0] = pic_offset_table_rtx; 1135: xops[1] = (rtx) gen_label_rtx (); 1136: 1137: output_asm_insn (AS1 (call,%P1), xops); 1138: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1])); 1139: output_asm_insn (AS1 (pop%L0,%0), xops); 1140: output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops); 1141: } 1142: } 1143: 1144: /* Return 1 if it is appropriate to emit `ret' instructions in the 1145: body of a function. Do this only if the epilogue is simple, needing a 1146: couple of insns. Prior to reloading, we can't tell how many registers 1147: must be saved, so return 0 then. 1148: 1149: If NON_SAVING_SETJMP is defined and true, then it is not possible 1150: for the epilogue to be simple, so return 0. This is a special case 1151: since NON_SAVING_SETJMP will not cause regs_ever_live to change until 1152: final, but jump_optimize may need to know sooner if a `return' is OK. */ 1153: 1154: int 1155: simple_386_epilogue () 1156: { 1157: int regno; 1158: int nregs = 0; 1159: int reglimit = (frame_pointer_needed 1160: ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); 1161: int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table 1162: || current_function_uses_const_pool); 1163: 1164: #ifdef NON_SAVING_SETJMP 1165: if (NON_SAVING_SETJMP && current_function_calls_setjmp) 1166: return 0; 1167: #endif 1168: 1169: if (! reload_completed) 1170: return 0; 1171: 1172: for (regno = reglimit - 1; regno >= 0; regno--) 1173: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1174: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1175: nregs++; 1176: 1177: return nregs == 0 || ! frame_pointer_needed; 1178: } 1179: 1.1.1.3 ! root 1180: 1.1 root 1181: /* This function generates the assembly code for function exit. 1182: FILE is an stdio stream to output the code to. 1183: SIZE is an int: how many units of temporary storage to deallocate. */ 1184: 1185: void 1186: function_epilogue (file, size) 1187: FILE *file; 1188: int size; 1189: { 1190: register int regno; 1191: register int nregs, limit; 1192: int offset; 1193: rtx xops[3]; 1194: int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table 1195: || current_function_uses_const_pool); 1196: 1197: /* Compute the number of registers to pop */ 1198: 1199: limit = (frame_pointer_needed 1200: ? FRAME_POINTER_REGNUM 1201: : STACK_POINTER_REGNUM); 1202: 1203: nregs = 0; 1204: 1205: for (regno = limit - 1; regno >= 0; regno--) 1206: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1207: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1208: nregs++; 1209: 1210: /* sp is often unreliable so we must go off the frame pointer, 1211: */ 1212: 1213: /* In reality, we may not care if sp is unreliable, because we can 1214: restore the register relative to the frame pointer. In theory, 1215: since each move is the same speed as a pop, and we don't need the 1216: leal, this is faster. For now restore multiple registers the old 1217: way. */ 1218: 1219: offset = -size - (nregs * UNITS_PER_WORD); 1220: 1221: xops[2] = stack_pointer_rtx; 1222: 1223: if (nregs > 1 || ! frame_pointer_needed) 1224: { 1225: if (frame_pointer_needed) 1226: { 1227: xops[0] = adj_offsettable_operand (AT_BP (Pmode), offset); 1228: output_asm_insn (AS2 (lea%L2,%0,%2), xops); 1229: } 1230: 1231: for (regno = 0; regno < limit; regno++) 1232: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1233: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1234: { 1235: xops[0] = gen_rtx (REG, SImode, regno); 1236: output_asm_insn ("pop%L0 %0", xops); 1237: } 1238: } 1239: else 1240: for (regno = 0; regno < limit; regno++) 1241: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1242: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1243: { 1244: xops[0] = gen_rtx (REG, SImode, regno); 1245: xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset); 1246: output_asm_insn (AS2 (mov%L0,%1,%0), xops); 1247: offset += 4; 1248: } 1249: 1250: if (frame_pointer_needed) 1251: { 1252: /* On i486, mov & pop is faster than "leave". */ 1253: 1.1.1.3 ! root 1254: if (!TARGET_386) 1.1 root 1255: { 1256: xops[0] = frame_pointer_rtx; 1257: output_asm_insn (AS2 (mov%L2,%0,%2), xops); 1258: output_asm_insn ("pop%L0 %0", xops); 1259: } 1260: else 1261: output_asm_insn ("leave", xops); 1262: } 1263: else if (size) 1264: { 1265: /* If there is no frame pointer, we must still release the frame. */ 1266: 1267: xops[0] = GEN_INT (size); 1268: output_asm_insn (AS2 (add%L2,%0,%2), xops); 1269: } 1270: 1271: if (current_function_pops_args && current_function_args_size) 1272: { 1273: xops[1] = GEN_INT (current_function_pops_args); 1274: 1275: /* i386 can only pop 32K bytes (maybe 64K? Is it signed?). If 1276: asked to pop more, pop return address, do explicit add, and jump 1277: indirectly to the caller. */ 1278: 1279: if (current_function_pops_args >= 32768) 1280: { 1281: /* ??? Which register to use here? */ 1282: xops[0] = gen_rtx (REG, SImode, 2); 1283: output_asm_insn ("pop%L0 %0", xops); 1284: output_asm_insn (AS2 (add%L2,%1,%2), xops); 1285: output_asm_insn ("jmp %*%0", xops); 1286: } 1287: else 1288: output_asm_insn ("ret %1", xops); 1289: } 1290: else 1291: output_asm_insn ("ret", xops); 1292: } 1.1.1.3 ! root 1293: 1.1 root 1294: 1.1.1.3 ! root 1295: /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression ! 1296: that is a valid memory address for an instruction. ! 1297: The MODE argument is the machine mode for the MEM expression ! 1298: that wants to use this address. ! 1299: ! 1300: On x86, legitimate addresses are: ! 1301: base movl (base),reg ! 1302: displacement movl disp,reg ! 1303: base + displacement movl disp(base),reg ! 1304: index + base movl (base,index),reg ! 1305: (index + base) + displacement movl disp(base,index),reg ! 1306: index*scale movl (,index,scale),reg ! 1307: index*scale + disp movl disp(,index,scale),reg ! 1308: index*scale + base movl (base,index,scale),reg ! 1309: (index*scale + base) + disp movl disp(base,index,scale),reg ! 1310: ! 1311: In each case, scale can be 1, 2, 4, 8. */ ! 1312: ! 1313: /* This is exactly the same as print_operand_addr, except that ! 1314: it recognizes addresses instead of printing them. ! 1315: ! 1316: It only recognizes address in canonical form. LEGITIMIZE_ADDRESS should ! 1317: convert common non-canonical forms to canonical form so that they will ! 1318: be recognized. */ ! 1319: ! 1320: #define ADDR_INVALID(msg,insn) \ ! 1321: do { \ ! 1322: if (TARGET_DEBUG_ADDR) \ ! 1323: { \ ! 1324: fprintf (stderr, msg); \ ! 1325: debug_rtx (insn); \ ! 1326: } \ ! 1327: } while (0) 1.1 root 1328: 1.1.1.3 ! root 1329: int ! 1330: legitimate_address_p (mode, addr, strict) ! 1331: enum machine_mode mode; ! 1332: register rtx addr; ! 1333: int strict; ! 1334: { ! 1335: rtx base = NULL_RTX; ! 1336: rtx indx = NULL_RTX; ! 1337: rtx scale = NULL_RTX; ! 1338: rtx disp = NULL_RTX; ! 1339: ! 1340: if (TARGET_DEBUG_ADDR) ! 1341: { ! 1342: fprintf (stderr, ! 1343: "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n", ! 1344: GET_MODE_NAME (mode), strict); ! 1345: ! 1346: debug_rtx (addr); ! 1347: } ! 1348: ! 1349: if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG) ! 1350: base = addr; /* base reg */ ! 1351: ! 1352: else if (GET_CODE (addr) == PLUS) ! 1353: { ! 1354: rtx op0 = XEXP (addr, 0); ! 1355: rtx op1 = XEXP (addr, 1); ! 1356: enum rtx_code code0 = GET_CODE (op0); ! 1357: enum rtx_code code1 = GET_CODE (op1); ! 1358: ! 1359: if (code0 == REG || code0 == SUBREG) ! 1360: { ! 1361: if (code1 == REG || code1 == SUBREG) ! 1362: { ! 1363: indx = op0; /* index + base */ ! 1364: base = op1; ! 1365: } ! 1366: ! 1367: else ! 1368: { ! 1369: base = op0; /* base + displacement */ ! 1370: disp = op1; ! 1371: } ! 1372: } ! 1373: ! 1374: else if (code0 == MULT) ! 1375: { ! 1376: indx = XEXP (op0, 0); ! 1377: scale = XEXP (op0, 1); ! 1378: ! 1379: if (code1 == REG || code1 == SUBREG) ! 1380: base = op1; /* index*scale + base */ ! 1381: ! 1382: else ! 1383: disp = op1; /* index*scale + disp */ ! 1384: } ! 1385: ! 1386: else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT) ! 1387: { ! 1388: indx = XEXP (XEXP (op0, 0), 0); /* index*scale + base + disp */ ! 1389: scale = XEXP (XEXP (op0, 0), 1); ! 1390: base = XEXP (op0, 1); ! 1391: disp = op1; ! 1392: } ! 1393: ! 1394: else if (code0 == PLUS) ! 1395: { ! 1396: indx = XEXP (op0, 0); /* index + base + disp */ ! 1397: base = XEXP (op0, 1); ! 1398: disp = op1; ! 1399: } ! 1400: ! 1401: else ! 1402: { ! 1403: ADDR_INVALID ("PLUS subcode is not valid.\n", op0); ! 1404: return FALSE; ! 1405: } ! 1406: } ! 1407: ! 1408: else if (GET_CODE (addr) == MULT) ! 1409: { ! 1410: indx = XEXP (addr, 0); /* index*scale */ ! 1411: scale = XEXP (addr, 1); ! 1412: } ! 1413: ! 1414: else ! 1415: disp = addr; /* displacement */ ! 1416: ! 1417: /* Allow arg pointer and stack pointer as index if there is not scaling */ ! 1418: if (base && indx && !scale ! 1419: && (indx == arg_pointer_rtx || indx == stack_pointer_rtx)) ! 1420: { ! 1421: rtx tmp = base; ! 1422: base = indx; ! 1423: indx = tmp; ! 1424: } ! 1425: ! 1426: /* Validate base register */ ! 1427: /* Don't allow SUBREG's here, it can lead to spill failures when the base ! 1428: is one word out of a two word structure, which is represented internally ! 1429: as a DImode int. */ ! 1430: if (base) ! 1431: { ! 1432: if (GET_CODE (base) != REG) ! 1433: { ! 1434: ADDR_INVALID ("Base is not a register.\n", base); ! 1435: return FALSE; ! 1436: } ! 1437: ! 1438: if ((strict && !REG_OK_FOR_BASE_STRICT_P (base)) ! 1439: || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base))) ! 1440: { ! 1441: ADDR_INVALID ("Base is not valid.\n", base); ! 1442: return FALSE; ! 1443: } ! 1444: } ! 1445: ! 1446: /* Validate index register */ ! 1447: /* Don't allow SUBREG's here, it can lead to spill failures when the index ! 1448: is one word out of a two word structure, which is represented internally ! 1449: as a DImode int. */ ! 1450: if (indx) ! 1451: { ! 1452: if (GET_CODE (indx) != REG) ! 1453: { ! 1454: ADDR_INVALID ("Index is not a register.\n", indx); ! 1455: return FALSE; ! 1456: } ! 1457: ! 1458: if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx)) ! 1459: || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx))) ! 1460: { ! 1461: ADDR_INVALID ("Index is not valid.\n", indx); ! 1462: return FALSE; ! 1463: } ! 1464: } ! 1465: else if (scale) ! 1466: abort (); /* scale w/o index illegal */ ! 1467: ! 1468: /* Validate scale factor */ ! 1469: if (scale) ! 1470: { ! 1471: HOST_WIDE_INT value; ! 1472: ! 1473: if (GET_CODE (scale) != CONST_INT) ! 1474: { ! 1475: ADDR_INVALID ("Scale is not valid.\n", scale); ! 1476: return FALSE; ! 1477: } ! 1478: ! 1479: value = INTVAL (scale); ! 1480: if (value != 1 && value != 2 && value != 4 && value != 8) ! 1481: { ! 1482: ADDR_INVALID ("Scale is not a good multiplier.\n", scale); ! 1483: return FALSE; ! 1484: } ! 1485: } ! 1486: ! 1487: /* Validate displacement */ ! 1488: if (disp) ! 1489: { ! 1490: if (!CONSTANT_ADDRESS_P (disp)) ! 1491: { ! 1492: ADDR_INVALID ("Displacement is not valid.\n", disp); ! 1493: return FALSE; ! 1494: } ! 1495: ! 1496: if (GET_CODE (disp) == CONST_DOUBLE) ! 1497: { ! 1498: ADDR_INVALID ("Displacement is a const_double.\n", disp); ! 1499: return FALSE; ! 1500: } ! 1501: ! 1502: if (flag_pic && SYMBOLIC_CONST (disp) && base != pic_offset_table_rtx ! 1503: && (indx != pic_offset_table_rtx || scale != NULL_RTX)) ! 1504: { ! 1505: ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp); ! 1506: return FALSE; ! 1507: } ! 1508: ! 1509: if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp) ! 1510: && (base != NULL_RTX || indx != NULL_RTX)) ! 1511: { ! 1512: ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp); ! 1513: return FALSE; ! 1514: } ! 1515: } ! 1516: ! 1517: if (TARGET_DEBUG_ADDR) ! 1518: fprintf (stderr, "Address is valid.\n"); ! 1519: ! 1520: /* Everything looks valid, return true */ ! 1521: return TRUE; ! 1522: } ! 1523: ! 1524: ! 1525: /* Return a legitimate reference for ORIG (an address) using the ! 1526: register REG. If REG is 0, a new pseudo is generated. ! 1527: ! 1528: There are three types of references that must be handled: ! 1529: ! 1530: 1. Global data references must load the address from the GOT, via ! 1531: the PIC reg. An insn is emitted to do this load, and the reg is ! 1532: returned. ! 1533: ! 1534: 2. Static data references must compute the address as an offset ! 1535: from the GOT, whose base is in the PIC reg. An insn is emitted to ! 1536: compute the address into a reg, and the reg is returned. Static ! 1537: data objects have SYMBOL_REF_FLAG set to differentiate them from ! 1538: global data objects. ! 1539: ! 1540: 3. Constant pool addresses must be handled special. They are ! 1541: considered legitimate addresses, but only if not used with regs. ! 1542: When printed, the output routines know to print the reference with the ! 1543: PIC reg, even though the PIC reg doesn't appear in the RTL. ! 1544: ! 1545: GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC ! 1546: reg also appears in the address (except for constant pool references, ! 1547: noted above). ! 1548: ! 1549: "switch" statements also require special handling when generating ! 1550: PIC code. See comments by the `casesi' insn in i386.md for details. */ ! 1551: ! 1552: rtx ! 1553: legitimize_pic_address (orig, reg) ! 1554: rtx orig; ! 1555: rtx reg; ! 1556: { ! 1557: rtx addr = orig; ! 1558: rtx new = orig; ! 1559: ! 1560: if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF) ! 1561: { ! 1562: if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr)) ! 1563: reg = new = orig; ! 1564: else ! 1565: { ! 1566: if (reg == 0) ! 1567: reg = gen_reg_rtx (Pmode); ! 1568: ! 1569: if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr)) ! 1570: || GET_CODE (addr) == LABEL_REF) ! 1571: new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig); ! 1572: else ! 1573: new = gen_rtx (MEM, Pmode, ! 1574: gen_rtx (PLUS, Pmode, ! 1575: pic_offset_table_rtx, orig)); ! 1576: ! 1577: emit_move_insn (reg, new); ! 1578: } ! 1579: current_function_uses_pic_offset_table = 1; ! 1580: return reg; ! 1581: } ! 1582: else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS) ! 1583: { ! 1584: rtx base; ! 1585: ! 1586: if (GET_CODE (addr) == CONST) ! 1587: { ! 1588: addr = XEXP (addr, 0); ! 1589: if (GET_CODE (addr) != PLUS) ! 1590: abort (); ! 1591: } ! 1592: ! 1593: if (XEXP (addr, 0) == pic_offset_table_rtx) ! 1594: return orig; ! 1595: ! 1596: if (reg == 0) ! 1597: reg = gen_reg_rtx (Pmode); ! 1598: ! 1599: base = legitimize_pic_address (XEXP (addr, 0), reg); ! 1600: addr = legitimize_pic_address (XEXP (addr, 1), ! 1601: base == reg ? NULL_RTX : reg); ! 1602: ! 1603: if (GET_CODE (addr) == CONST_INT) ! 1604: return plus_constant (base, INTVAL (addr)); ! 1605: ! 1606: if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1))) ! 1607: { ! 1608: base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0)); ! 1609: addr = XEXP (addr, 1); ! 1610: } ! 1611: return gen_rtx (PLUS, Pmode, base, addr); ! 1612: } ! 1613: return new; ! 1614: } ! 1615: ! 1616: ! 1617: /* Emit insns to move operands[1] into operands[0]. */ ! 1618: ! 1619: void ! 1620: emit_pic_move (operands, mode) ! 1621: rtx *operands; ! 1622: enum machine_mode mode; ! 1623: { ! 1624: rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode); ! 1625: ! 1626: if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])) ! 1627: operands[1] = (rtx) force_reg (SImode, operands[1]); ! 1628: else ! 1629: operands[1] = legitimize_pic_address (operands[1], temp); ! 1630: } ! 1631: ! 1632: ! 1633: /* Try machine-dependent ways of modifying an illegitimate address ! 1634: to be legitimate. If we find one, return the new, valid address. ! 1635: This macro is used in only one place: `memory_address' in explow.c. ! 1636: ! 1637: OLDX is the address as it was before break_out_memory_refs was called. ! 1638: In some cases it is useful to look at this to decide what needs to be done. ! 1639: ! 1640: MODE and WIN are passed so that this macro can use ! 1641: GO_IF_LEGITIMATE_ADDRESS. ! 1642: ! 1643: It is always safe for this macro to do nothing. It exists to recognize ! 1644: opportunities to optimize the output. ! 1645: ! 1646: For the 80386, we handle X+REG by loading X into a register R and ! 1647: using R+REG. R will go in a general reg and indexing will be used. ! 1648: However, if REG is a broken-out memory address or multiplication, ! 1649: nothing needs to be done because REG can certainly go in a general reg. ! 1650: ! 1651: When -fpic is used, special handling is needed for symbolic references. ! 1652: See comments by legitimize_pic_address in i386.c for details. */ ! 1653: ! 1654: rtx ! 1655: legitimize_address (x, oldx, mode) ! 1656: register rtx x; ! 1657: register rtx oldx; ! 1658: enum machine_mode mode; ! 1659: { ! 1660: int changed = 0; ! 1661: unsigned log; ! 1662: ! 1663: if (TARGET_DEBUG_ADDR) ! 1664: { ! 1665: fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode)); ! 1666: debug_rtx (x); ! 1667: } ! 1668: ! 1669: if (flag_pic && SYMBOLIC_CONST (x)) ! 1670: return legitimize_pic_address (x, 0); ! 1671: ! 1672: /* Canonicalize shifts by 0, 1, 2, 3 into multiply */ ! 1673: if (GET_CODE (x) == ASHIFT ! 1674: && GET_CODE (XEXP (x, 1)) == CONST_INT ! 1675: && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4) ! 1676: { ! 1677: changed = 1; ! 1678: x = gen_rtx (MULT, Pmode, ! 1679: force_reg (Pmode, XEXP (x, 0)), ! 1680: GEN_INT (1 << log)); ! 1681: } ! 1682: ! 1683: if (GET_CODE (x) == PLUS) ! 1684: { ! 1685: /* Canonicalize shifts by 0, 1, 2, 3 into multiply */ ! 1686: if (GET_CODE (XEXP (x, 0)) == ASHIFT ! 1687: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT ! 1688: && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4) ! 1689: { ! 1690: changed = 1; ! 1691: XEXP (x, 0) = gen_rtx (MULT, Pmode, ! 1692: force_reg (Pmode, XEXP (XEXP (x, 0), 0)), ! 1693: GEN_INT (1 << log)); ! 1694: } ! 1695: ! 1696: if (GET_CODE (XEXP (x, 1)) == ASHIFT ! 1697: && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT ! 1698: && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4) ! 1699: { ! 1700: changed = 1; ! 1701: XEXP (x, 1) = gen_rtx (MULT, Pmode, ! 1702: force_reg (Pmode, XEXP (XEXP (x, 1), 0)), ! 1703: GEN_INT (1 << log)); ! 1704: } ! 1705: ! 1706: /* Put multiply first if it isn't already */ ! 1707: if (GET_CODE (XEXP (x, 1)) == MULT) ! 1708: { ! 1709: rtx tmp = XEXP (x, 0); ! 1710: XEXP (x, 0) = XEXP (x, 1); ! 1711: XEXP (x, 1) = tmp; ! 1712: changed = 1; ! 1713: } ! 1714: ! 1715: /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const))) ! 1716: into (plus (plus (mult (reg) (const)) (reg)) (const)). This can be ! 1717: created by virtual register instantiation, register elimination, and ! 1718: similar optimizations. */ ! 1719: if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS) ! 1720: { ! 1721: changed = 1; ! 1722: x = gen_rtx (PLUS, Pmode, ! 1723: gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)), ! 1724: XEXP (XEXP (x, 1), 1)); ! 1725: } ! 1726: ! 1727: /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const) ! 1728: into (plus (plus (mult (reg) (const)) (reg)) (const)). */ ! 1729: else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS ! 1730: && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT ! 1731: && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS ! 1732: && CONSTANT_P (XEXP (x, 1))) ! 1733: { ! 1734: rtx constant, other; ! 1735: ! 1736: if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! 1737: { ! 1738: constant = XEXP (x, 1); ! 1739: other = XEXP (XEXP (XEXP (x, 0), 1), 1); ! 1740: } ! 1741: else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT) ! 1742: { ! 1743: constant = XEXP (XEXP (XEXP (x, 0), 1), 1); ! 1744: other = XEXP (x, 1); ! 1745: } ! 1746: else ! 1747: constant = 0; ! 1748: ! 1749: if (constant) ! 1750: { ! 1751: changed = 1; ! 1752: x = gen_rtx (PLUS, Pmode, ! 1753: gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0), ! 1754: XEXP (XEXP (XEXP (x, 0), 1), 0)), ! 1755: plus_constant (other, INTVAL (constant))); ! 1756: } ! 1757: } ! 1758: ! 1759: if (changed && legitimate_address_p (mode, x, FALSE)) ! 1760: return x; ! 1761: ! 1762: if (GET_CODE (XEXP (x, 0)) == MULT) ! 1763: { ! 1764: changed = 1; ! 1765: XEXP (x, 0) = force_operand (XEXP (x, 0), 0); ! 1766: } ! 1767: ! 1768: if (GET_CODE (XEXP (x, 1)) == MULT) ! 1769: { ! 1770: changed = 1; ! 1771: XEXP (x, 1) = force_operand (XEXP (x, 1), 0); ! 1772: } ! 1773: ! 1774: if (changed ! 1775: && GET_CODE (XEXP (x, 1)) == REG ! 1776: && GET_CODE (XEXP (x, 0)) == REG) ! 1777: return x; ! 1778: ! 1779: if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1))) ! 1780: { ! 1781: changed = 1; ! 1782: x = legitimize_pic_address (x, 0); ! 1783: } ! 1784: ! 1785: if (changed && legitimate_address_p (mode, x, FALSE)) ! 1786: return x; ! 1787: ! 1788: if (GET_CODE (XEXP (x, 0)) == REG) ! 1789: { ! 1790: register rtx temp = gen_reg_rtx (Pmode); ! 1791: register rtx val = force_operand (XEXP (x, 1), temp); ! 1792: if (val != temp) ! 1793: emit_move_insn (temp, val); ! 1794: ! 1795: XEXP (x, 1) = temp; ! 1796: return x; ! 1797: } ! 1798: ! 1799: else if (GET_CODE (XEXP (x, 1)) == REG) ! 1800: { ! 1801: register rtx temp = gen_reg_rtx (Pmode); ! 1802: register rtx val = force_operand (XEXP (x, 0), temp); ! 1803: if (val != temp) ! 1804: emit_move_insn (temp, val); ! 1805: ! 1806: XEXP (x, 0) = temp; ! 1807: return x; ! 1808: } ! 1809: } ! 1810: ! 1811: return x; ! 1812: } ! 1813: ! 1814: ! 1815: /* Print an integer constant expression in assembler syntax. Addition ! 1816: and subtraction are the only arithmetic that may appear in these ! 1817: expressions. FILE is the stdio stream to write to, X is the rtx, and ! 1818: CODE is the operand print code from the output string. */ ! 1819: ! 1820: static void ! 1821: output_pic_addr_const (file, x, code) ! 1822: FILE *file; ! 1823: rtx x; ! 1824: int code; ! 1825: { ! 1826: char buf[256]; 1.1 root 1827: 1828: switch (GET_CODE (x)) 1829: { 1830: case PC: 1831: if (flag_pic) 1832: putc ('.', file); 1833: else 1834: abort (); 1835: break; 1836: 1837: case SYMBOL_REF: 1838: case LABEL_REF: 1839: if (GET_CODE (x) == SYMBOL_REF) 1840: assemble_name (file, XSTR (x, 0)); 1841: else 1842: { 1843: ASM_GENERATE_INTERNAL_LABEL (buf, "L", 1844: CODE_LABEL_NUMBER (XEXP (x, 0))); 1845: assemble_name (asm_out_file, buf); 1846: } 1847: 1848: if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) 1849: fprintf (file, "@GOTOFF(%%ebx)"); 1850: else if (code == 'P') 1851: fprintf (file, "@PLT"); 1.1.1.3 ! root 1852: else if (GET_CODE (x) == LABEL_REF) ! 1853: fprintf (file, "@GOTOFF"); ! 1854: else if (! SYMBOL_REF_FLAG (x)) 1.1 root 1855: fprintf (file, "@GOT"); 1856: else 1857: fprintf (file, "@GOTOFF"); 1858: 1859: break; 1860: 1861: case CODE_LABEL: 1862: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 1863: assemble_name (asm_out_file, buf); 1864: break; 1865: 1866: case CONST_INT: 1867: fprintf (file, "%d", INTVAL (x)); 1868: break; 1869: 1870: case CONST: 1871: /* This used to output parentheses around the expression, 1872: but that does not work on the 386 (either ATT or BSD assembler). */ 1873: output_pic_addr_const (file, XEXP (x, 0), code); 1874: break; 1875: 1876: case CONST_DOUBLE: 1877: if (GET_MODE (x) == VOIDmode) 1878: { 1879: /* We can use %d if the number is <32 bits and positive. */ 1880: if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) 1881: fprintf (file, "0x%x%08x", 1882: CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); 1883: else 1884: fprintf (file, "%d", CONST_DOUBLE_LOW (x)); 1885: } 1886: else 1887: /* We can't handle floating point constants; 1888: PRINT_OPERAND must handle them. */ 1889: output_operand_lossage ("floating constant misused"); 1890: break; 1891: 1892: case PLUS: 1893: /* Some assemblers need integer constants to appear last (eg masm). */ 1894: if (GET_CODE (XEXP (x, 0)) == CONST_INT) 1895: { 1896: output_pic_addr_const (file, XEXP (x, 1), code); 1897: if (INTVAL (XEXP (x, 0)) >= 0) 1898: fprintf (file, "+"); 1899: output_pic_addr_const (file, XEXP (x, 0), code); 1900: } 1901: else 1902: { 1903: output_pic_addr_const (file, XEXP (x, 0), code); 1904: if (INTVAL (XEXP (x, 1)) >= 0) 1905: fprintf (file, "+"); 1906: output_pic_addr_const (file, XEXP (x, 1), code); 1907: } 1908: break; 1909: 1910: case MINUS: 1911: output_pic_addr_const (file, XEXP (x, 0), code); 1912: fprintf (file, "-"); 1913: output_pic_addr_const (file, XEXP (x, 1), code); 1914: break; 1915: 1916: default: 1917: output_operand_lossage ("invalid expression as operand"); 1918: } 1919: } 1920: 1921: /* Meaning of CODE: 1922: f -- float insn (print a CONST_DOUBLE as a float rather than in hex). 1923: D,L,W,B,Q,S -- print the opcode suffix for specified size of operand. 1924: R -- print the prefix for register names. 1925: z -- print the opcode suffix for the size of the current operand. 1926: * -- print a star (in certain assembler syntax) 1927: w -- print the operand as if it's a "word" (HImode) even if it isn't. 1928: c -- don't print special prefixes before constant operands. 1929: */ 1930: 1931: void 1932: print_operand (file, x, code) 1933: FILE *file; 1934: rtx x; 1935: int code; 1936: { 1937: if (code) 1938: { 1939: switch (code) 1940: { 1941: case '*': 1942: if (USE_STAR) 1943: putc ('*', file); 1944: return; 1945: 1946: case 'L': 1947: PUT_OP_SIZE (code, 'l', file); 1948: return; 1949: 1950: case 'W': 1951: PUT_OP_SIZE (code, 'w', file); 1952: return; 1953: 1954: case 'B': 1955: PUT_OP_SIZE (code, 'b', file); 1956: return; 1957: 1958: case 'Q': 1959: PUT_OP_SIZE (code, 'l', file); 1960: return; 1961: 1962: case 'S': 1963: PUT_OP_SIZE (code, 's', file); 1964: return; 1965: 1.1.1.2 root 1966: case 'T': 1967: PUT_OP_SIZE (code, 't', file); 1968: return; 1969: 1.1 root 1970: case 'z': 1971: /* 387 opcodes don't get size suffixes if the operands are 1972: registers. */ 1973: 1974: if (STACK_REG_P (x)) 1975: return; 1976: 1977: /* this is the size of op from size of operand */ 1978: switch (GET_MODE_SIZE (GET_MODE (x))) 1979: { 1980: case 1: 1981: PUT_OP_SIZE ('B', 'b', file); 1982: return; 1983: 1984: case 2: 1985: PUT_OP_SIZE ('W', 'w', file); 1986: return; 1987: 1988: case 4: 1989: if (GET_MODE (x) == SFmode) 1990: { 1991: PUT_OP_SIZE ('S', 's', file); 1992: return; 1993: } 1994: else 1995: PUT_OP_SIZE ('L', 'l', file); 1996: return; 1997: 1.1.1.2 root 1998: case 12: 1999: PUT_OP_SIZE ('T', 't', file); 2000: return; 2001: 1.1 root 2002: case 8: 2003: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT) 2004: { 2005: #ifdef GAS_MNEMONICS 2006: PUT_OP_SIZE ('Q', 'q', file); 2007: return; 2008: #else 2009: PUT_OP_SIZE ('Q', 'l', file); /* Fall through */ 2010: #endif 2011: } 2012: 2013: PUT_OP_SIZE ('Q', 'l', file); 2014: return; 2015: } 2016: 2017: case 'b': 2018: case 'w': 2019: case 'k': 2020: case 'h': 2021: case 'y': 2022: case 'P': 2023: break; 2024: 2025: default: 2026: { 2027: char str[50]; 2028: 2029: sprintf (str, "invalid operand code `%c'", code); 2030: output_operand_lossage (str); 2031: } 2032: } 2033: } 2034: if (GET_CODE (x) == REG) 2035: { 2036: PRINT_REG (x, code, file); 2037: } 2038: else if (GET_CODE (x) == MEM) 2039: { 2040: PRINT_PTR (x, file); 2041: if (CONSTANT_ADDRESS_P (XEXP (x, 0))) 2042: { 2043: if (flag_pic) 2044: output_pic_addr_const (file, XEXP (x, 0), code); 2045: else 2046: output_addr_const (file, XEXP (x, 0)); 2047: } 2048: else 2049: output_address (XEXP (x, 0)); 2050: } 2051: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode) 2052: { 1.1.1.2 root 2053: REAL_VALUE_TYPE r; long l; 2054: REAL_VALUE_FROM_CONST_DOUBLE (r, x); 2055: REAL_VALUE_TO_TARGET_SINGLE (r, l); 1.1 root 2056: PRINT_IMMED_PREFIX (file); 1.1.1.2 root 2057: fprintf (file, "0x%x", l); 1.1 root 2058: } 1.1.1.2 root 2059: /* These float cases don't actually occur as immediate operands. */ 2060: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode) 1.1 root 2061: { 1.1.1.2 root 2062: REAL_VALUE_TYPE r; char dstr[30]; 2063: REAL_VALUE_FROM_CONST_DOUBLE (r, x); 2064: REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr); 2065: fprintf (file, "%s", dstr); 2066: } 2067: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode) 2068: { 2069: REAL_VALUE_TYPE r; char dstr[30]; 2070: REAL_VALUE_FROM_CONST_DOUBLE (r, x); 2071: REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr); 2072: fprintf (file, "%s", dstr); 1.1 root 2073: } 2074: else 2075: { 2076: if (code != 'P') 2077: { 2078: if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) 2079: PRINT_IMMED_PREFIX (file); 2080: else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF 2081: || GET_CODE (x) == LABEL_REF) 2082: PRINT_OFFSET_PREFIX (file); 2083: } 2084: if (flag_pic) 2085: output_pic_addr_const (file, x, code); 2086: else 2087: output_addr_const (file, x); 2088: } 2089: } 2090: 2091: /* Print a memory operand whose address is ADDR. */ 2092: 2093: void 2094: print_operand_address (file, addr) 2095: FILE *file; 2096: register rtx addr; 2097: { 2098: register rtx reg1, reg2, breg, ireg; 2099: rtx offset; 2100: 2101: switch (GET_CODE (addr)) 2102: { 2103: case REG: 2104: ADDR_BEG (file); 2105: fprintf (file, "%se", RP); 2106: fputs (hi_reg_name[REGNO (addr)], file); 2107: ADDR_END (file); 2108: break; 2109: 2110: case PLUS: 2111: reg1 = 0; 2112: reg2 = 0; 2113: ireg = 0; 2114: breg = 0; 2115: offset = 0; 2116: if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) 2117: { 2118: offset = XEXP (addr, 0); 2119: addr = XEXP (addr, 1); 2120: } 2121: else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) 2122: { 2123: offset = XEXP (addr, 1); 2124: addr = XEXP (addr, 0); 2125: } 2126: if (GET_CODE (addr) != PLUS) ; 2127: else if (GET_CODE (XEXP (addr, 0)) == MULT) 2128: { 2129: reg1 = XEXP (addr, 0); 2130: addr = XEXP (addr, 1); 2131: } 2132: else if (GET_CODE (XEXP (addr, 1)) == MULT) 2133: { 2134: reg1 = XEXP (addr, 1); 2135: addr = XEXP (addr, 0); 2136: } 2137: else if (GET_CODE (XEXP (addr, 0)) == REG) 2138: { 2139: reg1 = XEXP (addr, 0); 2140: addr = XEXP (addr, 1); 2141: } 2142: else if (GET_CODE (XEXP (addr, 1)) == REG) 2143: { 2144: reg1 = XEXP (addr, 1); 2145: addr = XEXP (addr, 0); 2146: } 2147: if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT) 2148: { 2149: if (reg1 == 0) reg1 = addr; 2150: else reg2 = addr; 2151: addr = 0; 2152: } 2153: if (offset != 0) 2154: { 2155: if (addr != 0) abort (); 2156: addr = offset; 2157: } 2158: if ((reg1 && GET_CODE (reg1) == MULT) 2159: || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) 2160: { 2161: breg = reg2; 2162: ireg = reg1; 2163: } 2164: else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) 2165: { 2166: breg = reg1; 2167: ireg = reg2; 2168: } 2169: 2170: if (ireg != 0 || breg != 0) 2171: { 2172: int scale = 1; 2173: 2174: if (addr != 0) 2175: { 1.1.1.3 ! root 2176: if (flag_pic) ! 2177: output_pic_addr_const (file, addr, 0); ! 2178: ! 2179: else if (GET_CODE (addr) == LABEL_REF) 1.1 root 2180: output_asm_label (addr); 1.1.1.3 ! root 2181: 1.1 root 2182: else 1.1.1.3 ! root 2183: output_addr_const (file, addr); 1.1 root 2184: } 2185: 2186: if (ireg != 0 && GET_CODE (ireg) == MULT) 2187: { 2188: scale = INTVAL (XEXP (ireg, 1)); 2189: ireg = XEXP (ireg, 0); 2190: } 2191: 2192: /* The stack pointer can only appear as a base register, 2193: never an index register, so exchange the regs if it is wrong. */ 2194: 2195: if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM) 2196: { 2197: rtx tmp; 2198: 2199: tmp = breg; 2200: breg = ireg; 2201: ireg = tmp; 2202: } 2203: 2204: /* output breg+ireg*scale */ 2205: PRINT_B_I_S (breg, ireg, scale, file); 2206: break; 2207: } 2208: 2209: case MULT: 2210: { 2211: int scale; 2212: if (GET_CODE (XEXP (addr, 0)) == CONST_INT) 2213: { 2214: scale = INTVAL (XEXP (addr, 0)); 2215: ireg = XEXP (addr, 1); 2216: } 2217: else 2218: { 2219: scale = INTVAL (XEXP (addr, 1)); 2220: ireg = XEXP (addr, 0); 2221: } 2222: output_addr_const (file, const0_rtx); 2223: PRINT_B_I_S ((rtx) 0, ireg, scale, file); 2224: } 2225: break; 2226: 2227: default: 2228: if (GET_CODE (addr) == CONST_INT 2229: && INTVAL (addr) < 0x8000 2230: && INTVAL (addr) >= -0x8000) 2231: fprintf (file, "%d", INTVAL (addr)); 2232: else 2233: { 2234: if (flag_pic) 2235: output_pic_addr_const (file, addr, 0); 2236: else 2237: output_addr_const (file, addr); 2238: } 2239: } 2240: } 2241: 2242: /* Set the cc_status for the results of an insn whose pattern is EXP. 2243: On the 80386, we assume that only test and compare insns, as well 1.1.1.3 ! root 2244: as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, 1.1 root 2245: ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully. 2246: Also, we assume that jumps, moves and sCOND don't affect the condition 2247: codes. All else clobbers the condition codes, by assumption. 2248: 2249: We assume that ALL integer add, minus, etc. instructions effect the 2250: condition codes. This MUST be consistent with i386.md. 2251: 2252: We don't record any float test or compare - the redundant test & 2253: compare check in final.c does not handle stack-like regs correctly. */ 2254: 2255: void 2256: notice_update_cc (exp) 2257: rtx exp; 2258: { 2259: if (GET_CODE (exp) == SET) 2260: { 2261: /* Jumps do not alter the cc's. */ 2262: if (SET_DEST (exp) == pc_rtx) 2263: return; 2264: /* Moving register or memory into a register: 2265: it doesn't alter the cc's, but it might invalidate 2266: the RTX's which we remember the cc's came from. 2267: (Note that moving a constant 0 or 1 MAY set the cc's). */ 2268: if (REG_P (SET_DEST (exp)) 2269: && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM 2270: || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<')) 2271: { 2272: if (cc_status.value1 2273: && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) 2274: cc_status.value1 = 0; 2275: if (cc_status.value2 2276: && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) 2277: cc_status.value2 = 0; 2278: return; 2279: } 2280: /* Moving register into memory doesn't alter the cc's. 2281: It may invalidate the RTX's which we remember the cc's came from. */ 2282: if (GET_CODE (SET_DEST (exp)) == MEM 2283: && (REG_P (SET_SRC (exp)) 2284: || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<')) 2285: { 2286: if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM) 2287: cc_status.value1 = 0; 2288: if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM) 2289: cc_status.value2 = 0; 2290: return; 2291: } 2292: /* Function calls clobber the cc's. */ 2293: else if (GET_CODE (SET_SRC (exp)) == CALL) 2294: { 2295: CC_STATUS_INIT; 2296: return; 2297: } 2298: /* Tests and compares set the cc's in predictable ways. */ 2299: else if (SET_DEST (exp) == cc0_rtx) 2300: { 2301: CC_STATUS_INIT; 2302: cc_status.value1 = SET_SRC (exp); 2303: return; 2304: } 2305: /* Certain instructions effect the condition codes. */ 2306: else if (GET_MODE (SET_SRC (exp)) == SImode 2307: || GET_MODE (SET_SRC (exp)) == HImode 2308: || GET_MODE (SET_SRC (exp)) == QImode) 2309: switch (GET_CODE (SET_SRC (exp))) 2310: { 2311: case ASHIFTRT: case LSHIFTRT: 1.1.1.3 ! root 2312: case ASHIFT: 1.1 root 2313: /* Shifts on the 386 don't set the condition codes if the 2314: shift count is zero. */ 2315: if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT) 2316: { 2317: CC_STATUS_INIT; 2318: break; 2319: } 2320: /* We assume that the CONST_INT is non-zero (this rtx would 2321: have been deleted if it were zero. */ 2322: 2323: case PLUS: case MINUS: case NEG: 2324: case AND: case IOR: case XOR: 2325: cc_status.flags = CC_NO_OVERFLOW; 2326: cc_status.value1 = SET_SRC (exp); 2327: cc_status.value2 = SET_DEST (exp); 2328: break; 2329: 2330: default: 2331: CC_STATUS_INIT; 2332: } 2333: else 2334: { 2335: CC_STATUS_INIT; 2336: } 2337: } 2338: else if (GET_CODE (exp) == PARALLEL 2339: && GET_CODE (XVECEXP (exp, 0, 0)) == SET) 2340: { 2341: if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) 2342: return; 2343: if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) 2344: { 2345: CC_STATUS_INIT; 2346: if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0)))) 2347: cc_status.flags |= CC_IN_80387; 2348: else 2349: cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); 2350: return; 2351: } 2352: CC_STATUS_INIT; 2353: } 2354: else 2355: { 2356: CC_STATUS_INIT; 2357: } 2358: } 2359: 2360: /* Split one or more DImode RTL references into pairs of SImode 2361: references. The RTL can be REG, offsettable MEM, integer constant, or 2362: CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to 2363: split and "num" is its length. lo_half and hi_half are output arrays 2364: that parallel "operands". */ 2365: 2366: void 2367: split_di (operands, num, lo_half, hi_half) 2368: rtx operands[]; 2369: int num; 2370: rtx lo_half[], hi_half[]; 2371: { 2372: while (num--) 2373: { 2374: if (GET_CODE (operands[num]) == REG) 2375: { 2376: lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num])); 2377: hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1); 2378: } 2379: else if (CONSTANT_P (operands[num])) 2380: { 2381: split_double (operands[num], &lo_half[num], &hi_half[num]); 2382: } 2383: else if (offsettable_memref_p (operands[num])) 2384: { 2385: lo_half[num] = operands[num]; 2386: hi_half[num] = adj_offsettable_operand (operands[num], 4); 2387: } 2388: else 2389: abort(); 2390: } 2391: } 2392: 2393: /* Return 1 if this is a valid binary operation on a 387. 2394: OP is the expression matched, and MODE is its mode. */ 2395: 2396: int 2397: binary_387_op (op, mode) 2398: register rtx op; 2399: enum machine_mode mode; 2400: { 2401: if (mode != VOIDmode && mode != GET_MODE (op)) 2402: return 0; 2403: 2404: switch (GET_CODE (op)) 2405: { 2406: case PLUS: 2407: case MINUS: 2408: case MULT: 2409: case DIV: 2410: return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT; 2411: 2412: default: 2413: return 0; 2414: } 2415: } 2416: 1.1.1.3 ! root 2417: 1.1 root 2418: /* Return 1 if this is a valid shift or rotate operation on a 386. 2419: OP is the expression matched, and MODE is its mode. */ 2420: 2421: int 2422: shift_op (op, mode) 2423: register rtx op; 2424: enum machine_mode mode; 2425: { 2426: rtx operand = XEXP (op, 0); 2427: 2428: if (mode != VOIDmode && mode != GET_MODE (op)) 2429: return 0; 2430: 2431: if (GET_MODE (operand) != GET_MODE (op) 2432: || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT) 2433: return 0; 2434: 2435: return (GET_CODE (op) == ASHIFT 2436: || GET_CODE (op) == ASHIFTRT 2437: || GET_CODE (op) == LSHIFTRT 2438: || GET_CODE (op) == ROTATE 2439: || GET_CODE (op) == ROTATERT); 2440: } 2441: 2442: /* Return 1 if OP is COMPARE rtx with mode VOIDmode. 2443: MODE is not used. */ 2444: 2445: int 2446: VOIDmode_compare_op (op, mode) 2447: register rtx op; 2448: enum machine_mode mode; 2449: { 2450: return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode; 2451: } 2452: 2453: /* Output code to perform a 387 binary operation in INSN, one of PLUS, 2454: MINUS, MULT or DIV. OPERANDS are the insn operands, where operands[3] 2455: is the expression of the binary operation. The output may either be 2456: emitted here, or returned to the caller, like all output_* functions. 2457: 2458: There is no guarantee that the operands are the same mode, as they 2459: might be within FLOAT or FLOAT_EXTEND expressions. */ 2460: 2461: char * 2462: output_387_binary_op (insn, operands) 2463: rtx insn; 2464: rtx *operands; 2465: { 2466: rtx temp; 2467: char *base_op; 2468: static char buf[100]; 2469: 2470: switch (GET_CODE (operands[3])) 2471: { 2472: case PLUS: 2473: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT 2474: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT) 2475: base_op = "fiadd"; 2476: else 2477: base_op = "fadd"; 2478: break; 2479: 2480: case MINUS: 2481: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT 2482: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT) 2483: base_op = "fisub"; 2484: else 2485: base_op = "fsub"; 2486: break; 2487: 2488: case MULT: 2489: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT 2490: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT) 2491: base_op = "fimul"; 2492: else 2493: base_op = "fmul"; 2494: break; 2495: 2496: case DIV: 2497: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT 2498: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT) 2499: base_op = "fidiv"; 2500: else 2501: base_op = "fdiv"; 2502: break; 2503: 2504: default: 2505: abort (); 2506: } 2507: 2508: strcpy (buf, base_op); 2509: 2510: switch (GET_CODE (operands[3])) 2511: { 2512: case MULT: 2513: case PLUS: 2514: if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) 2515: { 2516: temp = operands[2]; 2517: operands[2] = operands[1]; 2518: operands[1] = temp; 2519: } 2520: 2521: if (GET_CODE (operands[2]) == MEM) 2522: return strcat (buf, AS1 (%z2,%2)); 2523: 2524: if (NON_STACK_REG_P (operands[1])) 2525: { 2526: output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1))); 2527: RET; 2528: } 2529: else if (NON_STACK_REG_P (operands[2])) 2530: { 2531: output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1))); 2532: RET; 2533: } 2534: 2535: if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) 2536: return strcat (buf, AS2 (p,%2,%0)); 2537: 2538: if (STACK_TOP_P (operands[0])) 1.1.1.3 ! root 2539: return strcat (buf, AS2C (%y2,%0)); 1.1 root 2540: else 1.1.1.3 ! root 2541: return strcat (buf, AS2C (%2,%0)); 1.1 root 2542: 2543: case MINUS: 2544: case DIV: 2545: if (GET_CODE (operands[1]) == MEM) 2546: return strcat (buf, AS1 (r%z1,%1)); 2547: 2548: if (GET_CODE (operands[2]) == MEM) 2549: return strcat (buf, AS1 (%z2,%2)); 2550: 2551: if (NON_STACK_REG_P (operands[1])) 2552: { 2553: output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1))); 2554: RET; 2555: } 2556: else if (NON_STACK_REG_P (operands[2])) 2557: { 2558: output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1))); 2559: RET; 2560: } 2561: 2562: if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2])) 2563: abort (); 2564: 2565: if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) 2566: return strcat (buf, AS2 (rp,%2,%0)); 2567: 2568: if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) 2569: return strcat (buf, AS2 (p,%1,%0)); 2570: 2571: if (STACK_TOP_P (operands[0])) 2572: { 2573: if (STACK_TOP_P (operands[1])) 1.1.1.3 ! root 2574: return strcat (buf, AS2C (%y2,%0)); 1.1 root 2575: else 2576: return strcat (buf, AS2 (r,%y1,%0)); 2577: } 2578: else if (STACK_TOP_P (operands[1])) 1.1.1.3 ! root 2579: return strcat (buf, AS2C (%1,%0)); 1.1 root 2580: else 2581: return strcat (buf, AS2 (r,%2,%0)); 2582: 2583: default: 2584: abort (); 2585: } 2586: } 2587: 2588: /* Output code for INSN to convert a float to a signed int. OPERANDS 2589: are the insn operands. The output may be SFmode or DFmode and the 2590: input operand may be SImode or DImode. As a special case, make sure 2591: that the 387 stack top dies if the output mode is DImode, because the 2592: hardware requires this. */ 2593: 2594: char * 2595: output_fix_trunc (insn, operands) 2596: rtx insn; 2597: rtx *operands; 2598: { 2599: int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 2600: rtx xops[2]; 2601: 2602: if (! STACK_TOP_P (operands[1]) || 2603: (GET_MODE (operands[0]) == DImode && ! stack_top_dies)) 2604: abort (); 2605: 2606: xops[0] = GEN_INT (12); 2607: xops[1] = operands[4]; 2608: 2609: output_asm_insn (AS1 (fnstc%W2,%2), operands); 2610: output_asm_insn (AS2 (mov%L2,%2,%4), operands); 2611: output_asm_insn (AS2 (mov%B1,%0,%h1), xops); 2612: output_asm_insn (AS2 (mov%L4,%4,%3), operands); 2613: output_asm_insn (AS1 (fldc%W3,%3), operands); 2614: 2615: if (NON_STACK_REG_P (operands[0])) 2616: output_to_reg (operands[0], stack_top_dies); 2617: else if (GET_CODE (operands[0]) == MEM) 2618: { 2619: if (stack_top_dies) 2620: output_asm_insn (AS1 (fistp%z0,%0), operands); 2621: else 2622: output_asm_insn (AS1 (fist%z0,%0), operands); 2623: } 2624: else 2625: abort (); 2626: 2627: return AS1 (fldc%W2,%2); 2628: } 2629: 2630: /* Output code for INSN to compare OPERANDS. The two operands might 2631: not have the same mode: one might be within a FLOAT or FLOAT_EXTEND 2632: expression. If the compare is in mode CCFPEQmode, use an opcode that 2633: will not fault if a qNaN is present. */ 2634: 2635: char * 2636: output_float_compare (insn, operands) 2637: rtx insn; 2638: rtx *operands; 2639: { 2640: int stack_top_dies; 2641: rtx body = XVECEXP (PATTERN (insn), 0, 0); 2642: int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode; 2643: 2644: if (! STACK_TOP_P (operands[0])) 2645: abort (); 2646: 2647: stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 2648: 2649: if (STACK_REG_P (operands[1]) 2650: && stack_top_dies 2651: && find_regno_note (insn, REG_DEAD, REGNO (operands[1])) 2652: && REGNO (operands[1]) != FIRST_STACK_REG) 2653: { 2654: /* If both the top of the 387 stack dies, and the other operand 2655: is also a stack register that dies, then this must be a 2656: `fcompp' float compare */ 2657: 2658: if (unordered_compare) 2659: output_asm_insn ("fucompp", operands); 2660: else 2661: output_asm_insn ("fcompp", operands); 2662: } 2663: else 2664: { 2665: static char buf[100]; 2666: 2667: /* Decide if this is the integer or float compare opcode, or the 2668: unordered float compare. */ 2669: 2670: if (unordered_compare) 2671: strcpy (buf, "fucom"); 2672: else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT) 2673: strcpy (buf, "fcom"); 2674: else 2675: strcpy (buf, "ficom"); 2676: 2677: /* Modify the opcode if the 387 stack is to be popped. */ 2678: 2679: if (stack_top_dies) 2680: strcat (buf, "p"); 2681: 2682: if (NON_STACK_REG_P (operands[1])) 2683: output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1))); 2684: else 2685: output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands); 2686: } 2687: 2688: /* Now retrieve the condition code. */ 2689: 2690: return output_fp_cc0_set (insn); 2691: } 2692: 2693: /* Output opcodes to transfer the results of FP compare or test INSN 2694: from the FPU to the CPU flags. If TARGET_IEEE_FP, ensure that if the 2695: result of the compare or test is unordered, no comparison operator 2696: succeeds except NE. Return an output template, if any. */ 2697: 2698: char * 2699: output_fp_cc0_set (insn) 2700: rtx insn; 2701: { 2702: rtx xops[3]; 2703: rtx unordered_label; 2704: rtx next; 2705: enum rtx_code code; 2706: 2707: xops[0] = gen_rtx (REG, HImode, 0); 2708: output_asm_insn (AS1 (fnsts%W0,%0), xops); 2709: 2710: if (! TARGET_IEEE_FP) 2711: return "sahf"; 2712: 2713: next = next_cc0_user (insn); 2714: if (next == NULL_RTX) 2715: abort (); 2716: 2717: if (GET_CODE (next) == JUMP_INSN 2718: && GET_CODE (PATTERN (next)) == SET 2719: && SET_DEST (PATTERN (next)) == pc_rtx 2720: && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE) 2721: { 2722: code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)); 2723: } 2724: else if (GET_CODE (PATTERN (next)) == SET) 2725: { 2726: code = GET_CODE (SET_SRC (PATTERN (next))); 2727: } 2728: else 2729: abort (); 2730: 2731: xops[0] = gen_rtx (REG, QImode, 0); 2732: 2733: switch (code) 2734: { 2735: case GT: 2736: xops[1] = GEN_INT (0x45); 2737: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 2738: /* je label */ 2739: break; 2740: 2741: case LT: 2742: xops[1] = GEN_INT (0x45); 2743: xops[2] = GEN_INT (0x01); 2744: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 2745: output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); 2746: /* je label */ 2747: break; 2748: 2749: case GE: 2750: xops[1] = GEN_INT (0x05); 2751: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 2752: /* je label */ 2753: break; 2754: 2755: case LE: 2756: xops[1] = GEN_INT (0x45); 2757: xops[2] = GEN_INT (0x40); 2758: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 2759: output_asm_insn (AS1 (dec%B0,%h0), xops); 2760: output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); 2761: /* jb label */ 2762: break; 2763: 2764: case EQ: 2765: xops[1] = GEN_INT (0x45); 2766: xops[2] = GEN_INT (0x40); 2767: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 2768: output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); 2769: /* je label */ 2770: break; 2771: 2772: case NE: 2773: xops[1] = GEN_INT (0x44); 2774: xops[2] = GEN_INT (0x40); 2775: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 2776: output_asm_insn (AS2 (xor%B0,%2,%h0), xops); 2777: /* jne label */ 2778: break; 2779: 2780: case GTU: 2781: case LTU: 2782: case GEU: 2783: case LEU: 2784: default: 2785: abort (); 2786: } 2787: RET; 2788: } 2789: 2790: #define MAX_386_STACK_LOCALS 2 2791: 2792: static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS]; 2793: 1.1.1.2 root 2794: /* Define the structure for the machine field in struct function. */ 2795: struct machine_function 2796: { 2797: rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS]; 2798: }; 2799: 2800: /* Functions to save and restore i386_stack_locals. 2801: These will be called, via pointer variables, 2802: from push_function_context and pop_function_context. */ 2803: 2804: void 2805: save_386_machine_status (p) 2806: struct function *p; 2807: { 2808: p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals); 1.1.1.3 ! root 2809: bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals, 1.1.1.2 root 2810: sizeof i386_stack_locals); 2811: } 2812: 2813: void 2814: restore_386_machine_status (p) 2815: struct function *p; 2816: { 1.1.1.3 ! root 2817: bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals, 1.1.1.2 root 2818: sizeof i386_stack_locals); 2819: free (p->machine); 2820: } 2821: 1.1 root 2822: /* Clear stack slot assignments remembered from previous functions. 2823: This is called from INIT_EXPANDERS once before RTL is emitted for each 1.1.1.2 root 2824: function. */ 1.1 root 2825: 2826: void 2827: clear_386_stack_locals () 2828: { 2829: enum machine_mode mode; 2830: int n; 2831: 2832: for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE; 2833: mode = (enum machine_mode) ((int) mode + 1)) 2834: for (n = 0; n < MAX_386_STACK_LOCALS; n++) 2835: i386_stack_locals[(int) mode][n] = NULL_RTX; 1.1.1.2 root 2836: 2837: /* Arrange to save and restore i386_stack_locals around nested functions. */ 2838: save_machine_status = save_386_machine_status; 2839: restore_machine_status = restore_386_machine_status; 1.1 root 2840: } 2841: 2842: /* Return a MEM corresponding to a stack slot with mode MODE. 2843: Allocate a new slot if necessary. 2844: 2845: The RTL for a function can have several slots available: N is 2846: which slot to use. */ 2847: 2848: rtx 2849: assign_386_stack_local (mode, n) 2850: enum machine_mode mode; 2851: int n; 2852: { 2853: if (n < 0 || n >= MAX_386_STACK_LOCALS) 2854: abort (); 2855: 2856: if (i386_stack_locals[(int) mode][n] == NULL_RTX) 2857: i386_stack_locals[(int) mode][n] 2858: = assign_stack_local (mode, GET_MODE_SIZE (mode), 0); 2859: 2860: return i386_stack_locals[(int) mode][n]; 2861: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.