|
|
1.1 root 1: /* Subroutines for insn-output.c for Intel 80386. 1.1.1.4 ! root 2: Copyright (C) 1988, 1992 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 "config.h" 22: #include "rtl.h" 23: #include "regs.h" 24: #include "hard-reg-set.h" 25: #include "real.h" 26: #include "insn-config.h" 27: #include "conditions.h" 28: #include "insn-flags.h" 29: #include "output.h" 30: #include "insn-attr.h" 31: #include "tree.h" 32: #include "flags.h" 33: 1.1.1.2 root 34: #ifdef EXTRA_CONSTRAINT 35: /* If EXTRA_CONSTRAINT is defined, then the 'S' 36: constraint in REG_CLASS_FROM_LETTER will no longer work, and various 37: asm statements that need 'S' for class SIREG will break. */ 1.1.1.4 ! root 38: error EXTRA_CONSTRAINT conflicts with S constraint letter ! 39: /* The previous line used to be #error, but some compilers barf ! 40: even if the conditional was untrue. */ 1.1.1.2 root 41: #endif 42: 1.1 root 43: #define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx)) 44: 45: extern FILE *asm_out_file; 46: extern char *strcat (); 47: 48: char *singlemove_string (); 49: char *output_move_const_single (); 1.1.1.3 root 50: char *output_fp_cc0_set (); 1.1 root 51: 1.1.1.4 ! root 52: char *hi_reg_name[] = HI_REGISTER_NAMES; ! 53: char *qi_reg_name[] = QI_REGISTER_NAMES; ! 54: char *qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES; 1.1 root 55: 56: /* Array of the smallest class containing reg number REGNO, indexed by 57: REGNO. Used by REGNO_REG_CLASS in i386.h. */ 58: 59: enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] = 60: { 61: /* ax, dx, cx, bx */ 1.1.1.2 root 62: AREG, DREG, CREG, BREG, 1.1 root 63: /* si, di, bp, sp */ 64: SIREG, DIREG, INDEX_REGS, GENERAL_REGS, 65: /* FP registers */ 66: FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS, 67: FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, 68: /* arg pointer */ 69: INDEX_REGS 70: }; 1.1.1.3 root 71: 72: /* Test and compare insns in i386.md store the information needed to 73: generate branch and scc insns here. */ 74: 75: struct rtx_def *i386_compare_op0, *i386_compare_op1; 76: struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); 1.1 root 77: 78: /* Output an insn whose source is a 386 integer register. SRC is the 79: rtx for the register, and TEMPLATE is the op-code template. SRC may 80: be either SImode or DImode. 81: 82: The template will be output with operands[0] as SRC, and operands[1] 83: as a pointer to the top of the 386 stack. So a call from floatsidf2 84: would look like this: 85: 86: output_op_from_reg (operands[1], AS1 (fild%z0,%1)); 87: 88: where %z0 corresponds to the caller's operands[1], and is used to 89: emit the proper size suffix. 90: 91: ??? Extend this to handle HImode - a 387 can load and store HImode 92: values directly. */ 93: 94: void 95: output_op_from_reg (src, template) 96: rtx src; 97: char *template; 98: { 99: rtx xops[4]; 100: 101: xops[0] = src; 102: xops[1] = AT_SP (Pmode); 1.1.1.4 ! root 103: xops[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (src))); 1.1 root 104: xops[3] = stack_pointer_rtx; 105: 106: if (GET_MODE_SIZE (GET_MODE (src)) > UNITS_PER_WORD) 107: { 108: rtx high = gen_rtx (REG, SImode, REGNO (src) + 1); 109: output_asm_insn (AS1 (push%L0,%0), &high); 110: } 111: output_asm_insn (AS1 (push%L0,%0), &src); 112: 113: output_asm_insn (template, xops); 114: 115: output_asm_insn (AS2 (add%L3,%2,%3), xops); 116: } 117: 118: /* Output an insn to pop an value from the 387 top-of-stack to 386 119: register DEST. The 387 register stack is popped if DIES is true. If 120: the mode of DEST is an integer mode, a `fist' integer store is done, 121: otherwise a `fst' float store is done. */ 122: 123: void 124: output_to_reg (dest, dies) 125: rtx dest; 126: int dies; 127: { 128: rtx xops[4]; 129: 130: xops[0] = AT_SP (Pmode); 131: xops[1] = stack_pointer_rtx; 1.1.1.4 ! root 132: xops[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (dest))); 1.1 root 133: xops[3] = dest; 134: 135: output_asm_insn (AS2 (sub%L1,%2,%1), xops); 136: 137: if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT) 138: { 139: if (dies) 140: output_asm_insn (AS1 (fistp%z3,%y0), xops); 141: else 142: output_asm_insn (AS1 (fist%z3,%y0), xops); 143: } 144: else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT) 145: { 146: if (dies) 147: output_asm_insn (AS1 (fstp%z3,%y0), xops); 148: else 149: output_asm_insn (AS1 (fst%z3,%y0), xops); 150: } 151: else 152: abort (); 153: 154: output_asm_insn (AS1 (pop%L0,%0), &dest); 155: 156: if (GET_MODE_SIZE (GET_MODE (dest)) > UNITS_PER_WORD) 157: { 158: dest = gen_rtx (REG, SImode, REGNO (dest) + 1); 159: output_asm_insn (AS1 (pop%L0,%0), &dest); 160: } 161: } 162: 163: char * 164: singlemove_string (operands) 165: rtx *operands; 166: { 167: rtx x; 168: if (GET_CODE (operands[0]) == MEM 169: && GET_CODE (x = XEXP (operands[0], 0)) == PRE_DEC) 170: { 171: if (XEXP (x, 0) != stack_pointer_rtx) 172: abort (); 173: return "push%L1 %1"; 174: } 175: else if (GET_CODE (operands[1]) == CONST_DOUBLE) 176: { 177: return output_move_const_single (operands); 178: } 179: else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG) 180: return AS2 (mov%L0,%1,%0); 181: else if (CONSTANT_P (operands[1])) 182: return AS2 (mov%L0,%1,%0); 183: else 184: { 185: output_asm_insn ("push%L1 %1", operands); 186: return "pop%L0 %0"; 187: } 188: } 189: 190: /* Return a REG that occurs in ADDR with coefficient 1. 191: ADDR can be effectively incremented by incrementing REG. */ 192: 193: static rtx 194: find_addr_reg (addr) 195: rtx addr; 196: { 197: while (GET_CODE (addr) == PLUS) 198: { 199: if (GET_CODE (XEXP (addr, 0)) == REG) 200: addr = XEXP (addr, 0); 201: else if (GET_CODE (XEXP (addr, 1)) == REG) 202: addr = XEXP (addr, 1); 203: else if (CONSTANT_P (XEXP (addr, 0))) 204: addr = XEXP (addr, 1); 205: else if (CONSTANT_P (XEXP (addr, 1))) 206: addr = XEXP (addr, 0); 207: else 208: abort (); 209: } 210: if (GET_CODE (addr) == REG) 211: return addr; 212: abort (); 213: } 214: 215: /* Output an insn to add the constant N to the register X. */ 216: 217: static void 218: asm_add (n, x) 219: int n; 220: rtx x; 221: { 222: rtx xops[2]; 223: xops[1] = x; 224: if (n < 0) 225: { 1.1.1.4 ! root 226: xops[0] = GEN_INT (-n); 1.1 root 227: output_asm_insn (AS2 (sub%L0,%0,%1), xops); 228: } 229: else if (n > 0) 230: { 1.1.1.4 ! root 231: xops[0] = GEN_INT (n); 1.1 root 232: output_asm_insn (AS2 (add%L0,%0,%1), xops); 233: } 234: } 235: 236: /* Output assembler code to perform a doubleword move insn 237: with operands OPERANDS. */ 238: 239: char * 240: output_move_double (operands) 241: rtx *operands; 242: { 243: enum {REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1; 244: rtx latehalf[2]; 245: rtx addreg0 = 0, addreg1 = 0; 1.1.1.4 ! root 246: int dest_overlapped_low = 0; 1.1 root 247: 248: /* First classify both operands. */ 249: 250: if (REG_P (operands[0])) 251: optype0 = REGOP; 252: else if (offsettable_memref_p (operands[0])) 253: optype0 = OFFSOP; 254: else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) 255: optype0 = POPOP; 256: else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) 257: optype0 = PUSHOP; 258: else if (GET_CODE (operands[0]) == MEM) 259: optype0 = MEMOP; 260: else 261: optype0 = RNDOP; 262: 263: if (REG_P (operands[1])) 264: optype1 = REGOP; 265: else if (CONSTANT_P (operands[1])) 266: optype1 = CNSTOP; 267: else if (offsettable_memref_p (operands[1])) 268: optype1 = OFFSOP; 269: else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC) 270: optype1 = POPOP; 271: else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) 272: optype1 = PUSHOP; 273: else if (GET_CODE (operands[1]) == MEM) 274: optype1 = MEMOP; 275: else 276: optype1 = RNDOP; 277: 278: /* Check for the cases that the operand constraints are not 279: supposed to allow to happen. Abort if we get one, 280: because generating code for these cases is painful. */ 281: 282: if (optype0 == RNDOP || optype1 == RNDOP) 283: abort (); 284: 285: /* If one operand is decrementing and one is incrementing 286: decrement the former register explicitly 287: and change that operand into ordinary indexing. */ 288: 289: if (optype0 == PUSHOP && optype1 == POPOP) 290: { 291: operands[0] = XEXP (XEXP (operands[0], 0), 0); 292: asm_add (-8, operands[0]); 293: operands[0] = gen_rtx (MEM, DImode, operands[0]); 294: optype0 = OFFSOP; 295: } 296: if (optype0 == POPOP && optype1 == PUSHOP) 297: { 298: operands[1] = XEXP (XEXP (operands[1], 0), 0); 299: asm_add (-8, operands[1]); 300: operands[1] = gen_rtx (MEM, DImode, operands[1]); 301: optype1 = OFFSOP; 302: } 303: 304: /* If an operand is an unoffsettable memory ref, find a register 305: we can increment temporarily to make it refer to the second word. */ 306: 307: if (optype0 == MEMOP) 308: addreg0 = find_addr_reg (XEXP (operands[0], 0)); 309: 310: if (optype1 == MEMOP) 311: addreg1 = find_addr_reg (XEXP (operands[1], 0)); 312: 313: /* Ok, we can do one word at a time. 314: Normally we do the low-numbered word first, 315: but if either operand is autodecrementing then we 316: do the high-numbered word first. 317: 318: In either case, set up in LATEHALF the operands to use 319: for the high-numbered word and in some cases alter the 320: operands in OPERANDS to be suitable for the low-numbered word. */ 321: 322: if (optype0 == REGOP) 323: latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); 324: else if (optype0 == OFFSOP) 325: latehalf[0] = adj_offsettable_operand (operands[0], 4); 326: else 327: latehalf[0] = operands[0]; 328: 329: if (optype1 == REGOP) 330: latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); 331: else if (optype1 == OFFSOP) 332: latehalf[1] = adj_offsettable_operand (operands[1], 4); 333: else if (optype1 == CNSTOP) 334: { 335: if (GET_CODE (operands[1]) == CONST_DOUBLE) 336: split_double (operands[1], &operands[1], &latehalf[1]); 337: else if (CONSTANT_P (operands[1])) 1.1.1.2 root 338: { 339: if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0) 340: latehalf[1] = constm1_rtx; 341: else 342: latehalf[1] = const0_rtx; 343: } 1.1 root 344: } 345: else 346: latehalf[1] = operands[1]; 347: 348: /* If insn is effectively movd N (sp),-(sp) then we will do the 349: high word first. We should use the adjusted operand 1 (which is N+4 (sp)) 350: for the low word as well, to compensate for the first decrement of sp. */ 351: if (optype0 == PUSHOP 352: && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM 353: && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1])) 354: operands[1] = latehalf[1]; 355: 1.1.1.4 ! root 356: /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)), ! 357: if the upper part of reg N does not appear in the MEM, arrange to ! 358: emit the move late-half first. Otherwise, compute the MEM address ! 359: into the upper part of N and use that as a pointer to the memory ! 360: operand. */ ! 361: if (optype0 == REGOP ! 362: && (optype1 == OFFSOP || optype1 == MEMOP)) ! 363: { ! 364: if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)) ! 365: && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) ! 366: { ! 367: /* If both halves of dest are used in the src memory address, ! 368: compute the address into latehalf of dest. */ ! 369: rtx xops[2]; ! 370: xops[0] = latehalf[0]; ! 371: xops[1] = XEXP (operands[1], 0); ! 372: output_asm_insn (AS2 (lea%L0,%a1,%0), xops); ! 373: operands[1] = gen_rtx (MEM, DImode, latehalf[0]); ! 374: latehalf[1] = adj_offsettable_operand (operands[1], 4); ! 375: } ! 376: else if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))) ! 377: /* If the low half of dest is mentioned in the source memory ! 378: address, the arrange to emit the move late half first. */ ! 379: dest_overlapped_low = 1; ! 380: } ! 381: 1.1 root 382: /* If one or both operands autodecrementing, 383: do the two words, high-numbered first. */ 384: 385: /* Likewise, the first move would clobber the source of the second one, 386: do them in the other order. This happens only for registers; 387: such overlap can't happen in memory unless the user explicitly 388: sets it up, and that is an undefined circumstance. */ 389: 390: if (optype0 == PUSHOP || optype1 == PUSHOP 391: || (optype0 == REGOP && optype1 == REGOP 1.1.1.4 ! root 392: && REGNO (operands[0]) == REGNO (latehalf[1])) ! 393: || dest_overlapped_low) 1.1 root 394: { 395: /* Make any unoffsettable addresses point at high-numbered word. */ 396: if (addreg0) 397: asm_add (4, addreg0); 398: if (addreg1) 399: asm_add (4, addreg1); 400: 401: /* Do that word. */ 402: output_asm_insn (singlemove_string (latehalf), latehalf); 403: 404: /* Undo the adds we just did. */ 405: if (addreg0) 406: asm_add (-4, addreg0); 407: if (addreg1) 408: asm_add (-4, addreg1); 409: 410: /* Do low-numbered word. */ 411: return singlemove_string (operands); 412: } 413: 414: /* Normal case: do the two words, low-numbered first. */ 415: 416: output_asm_insn (singlemove_string (operands), operands); 417: 418: /* Make any unoffsettable addresses point at high-numbered word. */ 419: if (addreg0) 420: asm_add (4, addreg0); 421: if (addreg1) 422: asm_add (4, addreg1); 423: 424: /* Do that word. */ 425: output_asm_insn (singlemove_string (latehalf), latehalf); 426: 427: /* Undo the adds we just did. */ 428: if (addreg0) 429: asm_add (-4, addreg0); 430: if (addreg1) 431: asm_add (-4, addreg1); 432: 433: return ""; 434: } 435: 436: int 437: standard_80387_constant_p (x) 438: rtx x; 439: { 440: union real_extract u; 441: register double d; 442: 443: bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u); 444: d = u.d; 445: 446: if (d == 0) 447: return 1; 448: 449: if (d == 1) 450: return 2; 451: 452: /* Note that on the 80387, other constants, such as pi, 453: are much slower to load as standard constants 454: than to load from doubles in memory! */ 455: 456: return 0; 457: } 458: 459: char * 460: output_move_const_single (operands) 461: rtx *operands; 462: { 463: if (FP_REG_P (operands[0])) 464: { 465: int conval = standard_80387_constant_p (operands[1]); 466: 467: if (conval == 1) 468: return "fldz"; 469: 470: if (conval == 2) 471: return "fld1"; 472: } 473: if (GET_CODE (operands[1]) == CONST_DOUBLE) 474: { 475: union { int i[2]; double d;} u1; 476: union { int i; float f;} u2; 477: u1.i[0] = CONST_DOUBLE_LOW (operands[1]); 478: u1.i[1] = CONST_DOUBLE_HIGH (operands[1]); 479: u2.f = u1.d; 1.1.1.4 ! root 480: operands[1] = GEN_INT (u2.i); 1.1 root 481: } 482: return singlemove_string (operands); 483: } 484: 485: /* Returns 1 if OP is either a symbol reference or a sum of a symbol 486: reference and a constant. */ 487: 488: int 489: symbolic_operand (op, mode) 490: register rtx op; 491: enum machine_mode mode; 492: { 493: switch (GET_CODE (op)) 494: { 495: case SYMBOL_REF: 496: case LABEL_REF: 497: return 1; 498: case CONST: 499: op = XEXP (op, 0); 500: return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF 501: || GET_CODE (XEXP (op, 0)) == LABEL_REF) 502: && GET_CODE (XEXP (op, 1)) == CONST_INT); 503: default: 504: return 0; 505: } 506: } 507: 508: /* Returns 1 if OP contains a symbol reference */ 509: 510: int 511: symbolic_reference_mentioned_p (op) 512: rtx op; 513: { 514: register char *fmt; 515: register int i; 516: 517: if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) 518: return 1; 519: 520: fmt = GET_RTX_FORMAT (GET_CODE (op)); 521: for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) 522: { 523: if (fmt[i] == 'E') 524: { 525: register int j; 526: 527: for (j = XVECLEN (op, i) - 1; j >= 0; j--) 528: if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) 529: return 1; 530: } 531: else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) 532: return 1; 533: } 534: 535: return 0; 536: } 537: 538: /* Return a legitimate reference for ORIG (an address) using the 539: register REG. If REG is 0, a new pseudo is generated. 540: 541: There are three types of references that must be handled: 542: 543: 1. Global data references must load the address from the GOT, via 544: the PIC reg. An insn is emitted to do this load, and the reg is 545: returned. 546: 547: 2. Static data references must compute the address as an offset 548: from the GOT, whose base is in the PIC reg. An insn is emitted to 549: compute the address into a reg, and the reg is returned. Static 550: data objects have SYMBOL_REF_FLAG set to differentiate them from 551: global data objects. 552: 553: 3. Constant pool addresses must be handled special. They are 554: considered legitimate addresses, but only if not used with regs. 555: When printed, the output routines know to print the reference with the 556: PIC reg, even though the PIC reg doesn't appear in the RTL. 557: 558: GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC 559: reg also appears in the address (except for constant pool references, 560: noted above). 561: 562: "switch" statements also require special handling when generating 563: PIC code. See comments by the `casesi' insn in i386.md for details. */ 564: 565: rtx 566: legitimize_pic_address (orig, reg) 567: rtx orig; 568: rtx reg; 569: { 570: rtx addr = orig; 571: rtx new = orig; 572: 573: if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF) 574: { 575: if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr)) 576: reg = new = orig; 577: else 578: { 579: if (reg == 0) 580: reg = gen_reg_rtx (Pmode); 581: 582: if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr)) 583: new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig); 584: else 585: new = gen_rtx (MEM, Pmode, 586: gen_rtx (PLUS, Pmode, 587: pic_offset_table_rtx, orig)); 588: 589: emit_move_insn (reg, new); 590: } 591: current_function_uses_pic_offset_table = 1; 592: return reg; 593: } 594: else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS) 595: { 596: rtx base; 597: 598: if (GET_CODE (addr) == CONST) 599: { 600: addr = XEXP (addr, 0); 601: if (GET_CODE (addr) != PLUS) 602: abort (); 603: } 604: 605: if (XEXP (addr, 0) == pic_offset_table_rtx) 606: return orig; 607: 608: if (reg == 0) 609: reg = gen_reg_rtx (Pmode); 610: 611: base = legitimize_pic_address (XEXP (addr, 0), reg); 1.1.1.4 ! root 612: addr = legitimize_pic_address (XEXP (addr, 1), ! 613: base == reg ? NULL_RTX : reg); 1.1 root 614: 615: if (GET_CODE (addr) == CONST_INT) 616: return plus_constant (base, INTVAL (addr)); 617: 618: if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1))) 619: { 620: base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0)); 621: addr = XEXP (addr, 1); 622: } 623: return gen_rtx (PLUS, Pmode, base, addr); 624: } 625: return new; 626: } 627: 628: /* Emit insns to move operands[1] into operands[0]. */ 629: 630: void 631: emit_pic_move (operands, mode) 632: rtx *operands; 633: enum machine_mode mode; 634: { 635: rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode); 636: 637: if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])) 638: operands[1] = (rtx) force_reg (SImode, operands[1]); 639: else 640: operands[1] = legitimize_pic_address (operands[1], temp); 641: } 642: 643: /* This function generates the assembly code for function entry. 644: FILE is an stdio stream to output the code to. 645: SIZE is an int: how many units of temporary storage to allocate. */ 646: 647: void 648: function_prologue (file, size) 649: FILE *file; 650: int size; 651: { 652: register int regno; 653: int limit; 654: rtx xops[4]; 1.1.1.3 root 655: int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table 656: || current_function_uses_const_pool); 1.1 root 657: 658: xops[0] = stack_pointer_rtx; 659: xops[1] = frame_pointer_rtx; 1.1.1.4 ! root 660: xops[2] = GEN_INT (size); 1.1 root 661: if (frame_pointer_needed) 662: { 663: output_asm_insn ("push%L1 %1", xops); 664: output_asm_insn (AS2 (mov%L0,%0,%1), xops); 665: } 666: 667: if (size) 668: output_asm_insn (AS2 (sub%L0,%2,%0), xops); 669: 670: /* Note If use enter it is NOT reversed args. 671: This one is not reversed from intel!! 672: I think enter is slower. Also sdb doesn't like it. 673: But if you want it the code is: 674: { 675: xops[3] = const0_rtx; 676: output_asm_insn ("enter %2,%3", xops); 677: } 678: */ 679: limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); 680: for (regno = limit - 1; regno >= 0; regno--) 681: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1.1.1.3 root 682: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1.1 root 683: { 684: xops[0] = gen_rtx (REG, SImode, regno); 685: output_asm_insn ("push%L0 %0", xops); 686: } 687: 1.1.1.3 root 688: if (pic_reg_used) 1.1 root 689: { 690: xops[0] = pic_offset_table_rtx; 691: xops[1] = (rtx) gen_label_rtx (); 692: 693: output_asm_insn (AS1 (call,%P1), xops); 694: ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1])); 695: output_asm_insn (AS1 (pop%L0,%0), xops); 696: output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops); 697: } 698: } 699: 700: /* Return 1 if it is appropriate to emit `ret' instructions in the 701: body of a function. Do this only if the epilogue is simple, needing a 702: couple of insns. Prior to reloading, we can't tell how many registers 703: must be saved, so return 0 then. 704: 705: If NON_SAVING_SETJMP is defined and true, then it is not possible 706: for the epilogue to be simple, so return 0. This is a special case 707: since NON_SAVING_SETJMP will not cause regs_ever_live to change until 708: final, but jump_optimize may need to know sooner if a `return' is OK. */ 709: 710: int 711: simple_386_epilogue () 712: { 713: int regno; 714: int nregs = 0; 715: int reglimit = (frame_pointer_needed 716: ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); 1.1.1.3 root 717: int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table 718: || current_function_uses_const_pool); 1.1 root 719: 720: #ifdef NON_SAVING_SETJMP 721: if (NON_SAVING_SETJMP && current_function_calls_setjmp) 722: return 0; 723: #endif 724: 725: if (! reload_completed) 726: return 0; 727: 728: for (regno = reglimit - 1; regno >= 0; regno--) 729: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1.1.1.3 root 730: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1.1 root 731: nregs++; 732: 733: return nregs == 0 || ! frame_pointer_needed; 734: } 735: 736: /* This function generates the assembly code for function exit. 737: FILE is an stdio stream to output the code to. 738: SIZE is an int: how many units of temporary storage to deallocate. */ 739: 740: void 741: function_epilogue (file, size) 742: FILE *file; 743: int size; 744: { 745: register int regno; 746: register int nregs, limit; 747: int offset; 748: rtx xops[3]; 1.1.1.3 root 749: int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table 750: || current_function_uses_const_pool); 1.1 root 751: 752: /* Compute the number of registers to pop */ 753: 754: limit = (frame_pointer_needed 755: ? FRAME_POINTER_REGNUM 756: : STACK_POINTER_REGNUM); 757: 758: nregs = 0; 759: 760: for (regno = limit - 1; regno >= 0; regno--) 761: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1.1.1.3 root 762: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1.1 root 763: nregs++; 764: 765: /* sp is often unreliable so we must go off the frame pointer, 766: */ 767: 768: /* In reality, we may not care if sp is unreliable, because we can 769: restore the register relative to the frame pointer. In theory, 770: since each move is the same speed as a pop, and we don't need the 771: leal, this is faster. For now restore multiple registers the old 772: way. */ 773: 774: offset = -size - (nregs * UNITS_PER_WORD); 775: 776: xops[2] = stack_pointer_rtx; 777: 778: if (nregs > 1 || ! frame_pointer_needed) 779: { 780: if (frame_pointer_needed) 781: { 782: xops[0] = adj_offsettable_operand (AT_BP (Pmode), offset); 783: output_asm_insn (AS2 (lea%L2,%0,%2), xops); 784: } 785: 786: for (regno = 0; regno < limit; regno++) 787: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1.1.1.3 root 788: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1.1 root 789: { 790: xops[0] = gen_rtx (REG, SImode, regno); 791: output_asm_insn ("pop%L0 %0", xops); 792: } 793: } 794: else 795: for (regno = 0; regno < limit; regno++) 796: if ((regs_ever_live[regno] && ! call_used_regs[regno]) 1.1.1.3 root 797: || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) 1.1 root 798: { 799: xops[0] = gen_rtx (REG, SImode, regno); 800: xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset); 801: output_asm_insn (AS2 (mov%L0,%1,%0), xops); 802: offset += 4; 803: } 804: 805: if (frame_pointer_needed) 806: { 807: /* On i486, mov & pop is faster than "leave". */ 808: 809: if (TARGET_486) 810: { 811: xops[0] = frame_pointer_rtx; 812: output_asm_insn (AS2 (mov%L2,%0,%2), xops); 813: output_asm_insn ("pop%L0 %0", xops); 814: } 815: else 816: output_asm_insn ("leave", xops); 817: } 818: else if (size) 819: { 820: /* If there is no frame pointer, we must still release the frame. */ 821: 1.1.1.4 ! root 822: xops[0] = GEN_INT (size); 1.1 root 823: output_asm_insn (AS2 (add%L2,%0,%2), xops); 824: } 825: 826: if (current_function_pops_args && current_function_args_size) 827: { 1.1.1.4 ! root 828: xops[1] = GEN_INT (current_function_pops_args); 1.1 root 829: 830: /* i386 can only pop 32K bytes (maybe 64K? Is it signed?). If 831: asked to pop more, pop return address, do explicit add, and jump 832: indirectly to the caller. */ 833: 834: if (current_function_pops_args >= 32768) 835: { 836: /* ??? Which register to use here? */ 837: xops[0] = gen_rtx (REG, SImode, 2); 838: output_asm_insn ("pop%L0 %0", xops); 839: output_asm_insn (AS2 (add%L2,%1,%2), xops); 840: output_asm_insn ("jmp %*%0", xops); 841: } 842: else 843: output_asm_insn ("ret %1", xops); 844: } 845: else 846: output_asm_insn ("ret", xops); 847: } 848: 849: /* Print an integer constant expression in assembler syntax. Addition 850: and subtraction are the only arithmetic that may appear in these 851: expressions. FILE is the stdio stream to write to, X is the rtx, and 852: CODE is the operand print code from the output string. */ 853: 854: static void 855: output_pic_addr_const (file, x, code) 856: FILE *file; 857: rtx x; 858: int code; 859: { 860: char buf[256]; 861: 862: switch (GET_CODE (x)) 863: { 864: case PC: 865: if (flag_pic) 866: putc ('.', file); 867: else 868: abort (); 869: break; 870: 871: case SYMBOL_REF: 872: case LABEL_REF: 873: if (GET_CODE (x) == SYMBOL_REF) 874: assemble_name (file, XSTR (x, 0)); 875: else 876: { 877: ASM_GENERATE_INTERNAL_LABEL (buf, "L", 878: CODE_LABEL_NUMBER (XEXP (x, 0))); 879: assemble_name (asm_out_file, buf); 880: } 881: 882: if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) 883: fprintf (file, "@GOTOFF(%%ebx)"); 884: else if (code == 'P') 885: fprintf (file, "@PLT"); 886: else if (GET_CODE (x) == LABEL_REF || ! SYMBOL_REF_FLAG (x)) 887: fprintf (file, "@GOT"); 888: else 889: fprintf (file, "@GOTOFF"); 890: 891: break; 892: 893: case CODE_LABEL: 894: ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); 895: assemble_name (asm_out_file, buf); 896: break; 897: 898: case CONST_INT: 899: fprintf (file, "%d", INTVAL (x)); 900: break; 901: 902: case CONST: 903: /* This used to output parentheses around the expression, 904: but that does not work on the 386 (either ATT or BSD assembler). */ 905: output_pic_addr_const (file, XEXP (x, 0), code); 906: break; 907: 908: case CONST_DOUBLE: 909: if (GET_MODE (x) == VOIDmode) 910: { 911: /* We can use %d if the number is <32 bits and positive. */ 912: if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) 913: fprintf (file, "0x%x%08x", 914: CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); 915: else 916: fprintf (file, "%d", CONST_DOUBLE_LOW (x)); 917: } 918: else 919: /* We can't handle floating point constants; 920: PRINT_OPERAND must handle them. */ 921: output_operand_lossage ("floating constant misused"); 922: break; 923: 924: case PLUS: 925: /* Some assemblers need integer constants to appear last (eg masm). */ 926: if (GET_CODE (XEXP (x, 0)) == CONST_INT) 927: { 928: output_pic_addr_const (file, XEXP (x, 1), code); 929: if (INTVAL (XEXP (x, 0)) >= 0) 930: fprintf (file, "+"); 931: output_pic_addr_const (file, XEXP (x, 0), code); 932: } 933: else 934: { 935: output_pic_addr_const (file, XEXP (x, 0), code); 936: if (INTVAL (XEXP (x, 1)) >= 0) 937: fprintf (file, "+"); 938: output_pic_addr_const (file, XEXP (x, 1), code); 939: } 940: break; 941: 942: case MINUS: 943: output_pic_addr_const (file, XEXP (x, 0), code); 944: fprintf (file, "-"); 945: output_pic_addr_const (file, XEXP (x, 1), code); 946: break; 947: 948: default: 949: output_operand_lossage ("invalid expression as operand"); 950: } 951: } 952: 953: /* Meaning of CODE: 954: f -- float insn (print a CONST_DOUBLE as a float rather than in hex). 955: D,L,W,B,Q,S -- print the opcode suffix for specified size of operand. 956: R -- print the prefix for register names. 957: z -- print the opcode suffix for the size of the current operand. 958: * -- print a star (in certain assembler syntax) 959: w -- print the operand as if it's a "word" (HImode) even if it isn't. 960: c -- don't print special prefixes before constant operands. 961: */ 962: 963: void 964: print_operand (file, x, code) 965: FILE *file; 966: rtx x; 967: int code; 968: { 969: if (code) 970: { 971: switch (code) 972: { 973: case '*': 974: if (USE_STAR) 975: putc ('*', file); 976: return; 977: 978: case 'L': 979: PUT_OP_SIZE (code, 'l', file); 980: return; 981: 982: case 'W': 983: PUT_OP_SIZE (code, 'w', file); 984: return; 985: 986: case 'B': 987: PUT_OP_SIZE (code, 'b', file); 988: return; 989: 990: case 'Q': 991: PUT_OP_SIZE (code, 'l', file); 992: return; 993: 994: case 'S': 995: PUT_OP_SIZE (code, 's', file); 996: return; 997: 998: case 'z': 999: /* 387 opcodes don't get size suffixes if the operands are 1000: registers. */ 1001: 1002: if (STACK_REG_P (x)) 1003: return; 1004: 1005: /* this is the size of op from size of operand */ 1006: switch (GET_MODE_SIZE (GET_MODE (x))) 1007: { 1008: case 1: 1009: PUT_OP_SIZE ('B', 'b', file); 1010: return; 1011: 1012: case 2: 1013: PUT_OP_SIZE ('W', 'w', file); 1014: return; 1015: 1016: case 4: 1017: if (GET_MODE (x) == SFmode) 1018: { 1019: PUT_OP_SIZE ('S', 's', file); 1020: return; 1021: } 1022: else 1023: PUT_OP_SIZE ('L', 'l', file); 1024: return; 1025: 1026: case 8: 1027: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT) 1.1.1.3 root 1028: { 1029: #ifdef GAS_MNEMONICS 1030: PUT_OP_SIZE ('Q', 'q', file); 1031: return; 1032: #else 1033: PUT_OP_SIZE ('Q', 'l', file); /* Fall through */ 1034: #endif 1035: } 1.1 root 1036: 1037: PUT_OP_SIZE ('Q', 'l', file); 1038: return; 1039: } 1.1.1.3 root 1040: 1041: case 'b': 1042: case 'w': 1043: case 'k': 1044: case 'h': 1045: case 'y': 1046: case 'P': 1047: break; 1048: 1049: default: 1.1.1.4 ! root 1050: { ! 1051: char str[50]; ! 1052: ! 1053: sprintf (str, "invalid operand code `%c'", code); ! 1054: output_operand_lossage (str); ! 1055: } 1.1 root 1056: } 1057: } 1058: if (GET_CODE (x) == REG) 1059: { 1060: PRINT_REG (x, code, file); 1061: } 1062: else if (GET_CODE (x) == MEM) 1063: { 1064: PRINT_PTR (x, file); 1065: if (CONSTANT_ADDRESS_P (XEXP (x, 0))) 1066: { 1067: if (flag_pic) 1068: output_pic_addr_const (file, XEXP (x, 0), code); 1069: else 1070: output_addr_const (file, XEXP (x, 0)); 1071: } 1072: else 1073: output_address (XEXP (x, 0)); 1074: } 1075: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode) 1076: { 1077: union { double d; int i[2]; } u; 1078: union { float f; int i; } u1; 1079: u.i[0] = CONST_DOUBLE_LOW (x); 1080: u.i[1] = CONST_DOUBLE_HIGH (x); 1081: u1.f = u.d; 1.1.1.3 root 1082: PRINT_IMMED_PREFIX (file); 1083: fprintf (file, "0x%x", u1.i); 1.1 root 1084: } 1085: else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode) 1086: { 1087: union { double d; int i[2]; } u; 1088: u.i[0] = CONST_DOUBLE_LOW (x); 1089: u.i[1] = CONST_DOUBLE_HIGH (x); 1090: fprintf (file, "%.22e", u.d); 1091: } 1092: else 1093: { 1.1.1.3 root 1094: if (code != 'P') 1.1 root 1095: { 1.1.1.3 root 1096: if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE) 1.1 root 1097: PRINT_IMMED_PREFIX (file); 1098: else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF 1099: || GET_CODE (x) == LABEL_REF) 1100: PRINT_OFFSET_PREFIX (file); 1101: } 1102: if (flag_pic) 1103: output_pic_addr_const (file, x, code); 1104: else 1105: output_addr_const (file, x); 1106: } 1107: } 1108: 1109: /* Print a memory operand whose address is ADDR. */ 1110: 1111: void 1112: print_operand_address (file, addr) 1113: FILE *file; 1114: register rtx addr; 1115: { 1116: register rtx reg1, reg2, breg, ireg; 1117: rtx offset; 1118: 1119: switch (GET_CODE (addr)) 1120: { 1121: case REG: 1122: ADDR_BEG (file); 1123: fprintf (file, "%se", RP); 1124: fputs (hi_reg_name[REGNO (addr)], file); 1125: ADDR_END (file); 1126: break; 1127: 1128: case PLUS: 1129: reg1 = 0; 1130: reg2 = 0; 1131: ireg = 0; 1132: breg = 0; 1133: offset = 0; 1134: if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) 1135: { 1136: offset = XEXP (addr, 0); 1137: addr = XEXP (addr, 1); 1138: } 1139: else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) 1140: { 1141: offset = XEXP (addr, 1); 1142: addr = XEXP (addr, 0); 1143: } 1144: if (GET_CODE (addr) != PLUS) ; 1145: else if (GET_CODE (XEXP (addr, 0)) == MULT) 1146: { 1147: reg1 = XEXP (addr, 0); 1148: addr = XEXP (addr, 1); 1149: } 1150: else if (GET_CODE (XEXP (addr, 1)) == MULT) 1151: { 1152: reg1 = XEXP (addr, 1); 1153: addr = XEXP (addr, 0); 1154: } 1155: else if (GET_CODE (XEXP (addr, 0)) == REG) 1156: { 1157: reg1 = XEXP (addr, 0); 1158: addr = XEXP (addr, 1); 1159: } 1160: else if (GET_CODE (XEXP (addr, 1)) == REG) 1161: { 1162: reg1 = XEXP (addr, 1); 1163: addr = XEXP (addr, 0); 1164: } 1165: if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT) 1166: { 1167: if (reg1 == 0) reg1 = addr; 1168: else reg2 = addr; 1169: addr = 0; 1170: } 1171: if (offset != 0) 1172: { 1173: if (addr != 0) abort (); 1174: addr = offset; 1175: } 1176: if ((reg1 && GET_CODE (reg1) == MULT) 1177: || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) 1178: { 1179: breg = reg2; 1180: ireg = reg1; 1181: } 1182: else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) 1183: { 1184: breg = reg1; 1185: ireg = reg2; 1186: } 1187: 1188: if (ireg != 0 || breg != 0) 1189: { 1190: int scale = 1; 1191: 1192: if (addr != 0) 1193: { 1194: if (GET_CODE (addr) == LABEL_REF) 1195: output_asm_label (addr); 1196: else 1197: { 1198: if (flag_pic) 1199: output_pic_addr_const (file, addr, 0); 1200: else 1201: output_addr_const (file, addr); 1202: } 1203: } 1204: 1205: if (ireg != 0 && GET_CODE (ireg) == MULT) 1206: { 1207: scale = INTVAL (XEXP (ireg, 1)); 1208: ireg = XEXP (ireg, 0); 1209: } 1210: 1211: /* The stack pointer can only appear as a base register, 1212: never an index register, so exchange the regs if it is wrong. */ 1213: 1214: if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM) 1215: { 1216: rtx tmp; 1217: 1218: tmp = breg; 1219: breg = ireg; 1220: ireg = tmp; 1221: } 1222: 1223: /* output breg+ireg*scale */ 1224: PRINT_B_I_S (breg, ireg, scale, file); 1225: break; 1226: } 1227: 1228: case MULT: 1229: { 1230: int scale; 1231: if (GET_CODE (XEXP (addr, 0)) == CONST_INT) 1232: { 1233: scale = INTVAL (XEXP (addr, 0)); 1234: ireg = XEXP (addr, 1); 1235: } 1236: else 1237: { 1238: scale = INTVAL (XEXP (addr, 1)); 1239: ireg = XEXP (addr, 0); 1240: } 1241: output_addr_const (file, const0_rtx); 1242: PRINT_B_I_S ((rtx) 0, ireg, scale, file); 1243: } 1244: break; 1245: 1246: default: 1247: if (GET_CODE (addr) == CONST_INT 1248: && INTVAL (addr) < 0x8000 1249: && INTVAL (addr) >= -0x8000) 1250: fprintf (file, "%d", INTVAL (addr)); 1251: else 1252: { 1253: if (flag_pic) 1254: output_pic_addr_const (file, addr, 0); 1255: else 1256: output_addr_const (file, addr); 1257: } 1258: } 1259: } 1260: 1261: /* Set the cc_status for the results of an insn whose pattern is EXP. 1262: On the 80386, we assume that only test and compare insns, as well 1263: as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, LSHIFT, 1264: ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully. 1265: Also, we assume that jumps, moves and sCOND don't affect the condition 1266: codes. All else clobbers the condition codes, by assumption. 1267: 1268: We assume that ALL integer add, minus, etc. instructions effect the 1269: condition codes. This MUST be consistent with i386.md. 1270: 1271: We don't record any float test or compare - the redundant test & 1272: compare check in final.c does not handle stack-like regs correctly. */ 1273: 1274: void 1275: notice_update_cc (exp) 1276: rtx exp; 1277: { 1278: if (GET_CODE (exp) == SET) 1279: { 1280: /* Jumps do not alter the cc's. */ 1281: if (SET_DEST (exp) == pc_rtx) 1282: return; 1283: /* Moving register or memory into a register: 1284: it doesn't alter the cc's, but it might invalidate 1285: the RTX's which we remember the cc's came from. 1286: (Note that moving a constant 0 or 1 MAY set the cc's). */ 1287: if (REG_P (SET_DEST (exp)) 1288: && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM 1289: || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<')) 1290: { 1291: if (cc_status.value1 1292: && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) 1293: cc_status.value1 = 0; 1294: if (cc_status.value2 1295: && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) 1296: cc_status.value2 = 0; 1297: return; 1298: } 1299: /* Moving register into memory doesn't alter the cc's. 1300: It may invalidate the RTX's which we remember the cc's came from. */ 1301: if (GET_CODE (SET_DEST (exp)) == MEM 1302: && (REG_P (SET_SRC (exp)) 1303: || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<')) 1304: { 1305: if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM) 1306: cc_status.value1 = 0; 1307: if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM) 1308: cc_status.value2 = 0; 1309: return; 1310: } 1311: /* Function calls clobber the cc's. */ 1312: else if (GET_CODE (SET_SRC (exp)) == CALL) 1313: { 1314: CC_STATUS_INIT; 1315: return; 1316: } 1317: /* Tests and compares set the cc's in predictable ways. */ 1318: else if (SET_DEST (exp) == cc0_rtx) 1319: { 1320: CC_STATUS_INIT; 1321: cc_status.value1 = SET_SRC (exp); 1322: return; 1323: } 1324: /* Certain instructions effect the condition codes. */ 1325: else if (GET_MODE (SET_SRC (exp)) == SImode 1326: || GET_MODE (SET_SRC (exp)) == HImode 1327: || GET_MODE (SET_SRC (exp)) == QImode) 1328: switch (GET_CODE (SET_SRC (exp))) 1329: { 1330: case ASHIFTRT: case LSHIFTRT: 1331: case ASHIFT: case LSHIFT: 1332: /* Shifts on the 386 don't set the condition codes if the 1333: shift count is zero. */ 1334: if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT) 1335: { 1336: CC_STATUS_INIT; 1337: break; 1338: } 1339: /* We assume that the CONST_INT is non-zero (this rtx would 1340: have been deleted if it were zero. */ 1341: 1342: case PLUS: case MINUS: case NEG: 1343: case AND: case IOR: case XOR: 1344: cc_status.flags = CC_NO_OVERFLOW; 1345: cc_status.value1 = SET_SRC (exp); 1346: cc_status.value2 = SET_DEST (exp); 1347: break; 1348: 1349: default: 1350: CC_STATUS_INIT; 1351: } 1352: else 1353: { 1354: CC_STATUS_INIT; 1355: } 1356: } 1357: else if (GET_CODE (exp) == PARALLEL 1358: && GET_CODE (XVECEXP (exp, 0, 0)) == SET) 1359: { 1360: if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) 1361: return; 1362: if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) 1363: { 1364: CC_STATUS_INIT; 1.1.1.4 ! root 1365: if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0)))) ! 1366: cc_status.flags |= CC_IN_80387; ! 1367: else 1.1 root 1368: cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); 1369: return; 1370: } 1371: CC_STATUS_INIT; 1372: } 1373: else 1374: { 1375: CC_STATUS_INIT; 1376: } 1377: } 1378: 1379: /* Split one or more DImode RTL references into pairs of SImode 1380: references. The RTL can be REG, offsettable MEM, integer constant, or 1381: CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to 1382: split and "num" is its length. lo_half and hi_half are output arrays 1383: that parallel "operands". */ 1384: 1385: void 1386: split_di (operands, num, lo_half, hi_half) 1387: rtx operands[]; 1388: int num; 1389: rtx lo_half[], hi_half[]; 1390: { 1391: while (num--) 1392: { 1393: if (GET_CODE (operands[num]) == REG) 1394: { 1395: lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num])); 1396: hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1); 1397: } 1398: else if (CONSTANT_P (operands[num])) 1399: { 1400: split_double (operands[num], &lo_half[num], &hi_half[num]); 1401: } 1402: else if (offsettable_memref_p (operands[num])) 1403: { 1404: lo_half[num] = operands[num]; 1405: hi_half[num] = adj_offsettable_operand (operands[num], 4); 1406: } 1407: else 1408: abort(); 1409: } 1410: } 1411: 1412: /* Return 1 if this is a valid binary operation on a 387. 1413: OP is the expression matched, and MODE is its mode. */ 1414: 1415: int 1416: binary_387_op (op, mode) 1417: register rtx op; 1418: enum machine_mode mode; 1419: { 1420: if (mode != VOIDmode && mode != GET_MODE (op)) 1421: return 0; 1422: 1423: switch (GET_CODE (op)) 1424: { 1425: case PLUS: 1426: case MINUS: 1427: case MULT: 1428: case DIV: 1429: return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT; 1430: 1431: default: 1432: return 0; 1433: } 1434: } 1435: 1436: /* Return 1 if this is a valid conversion operation on a 387. 1437: OP is the expression matched, and MODE is its mode. */ 1438: 1439: int 1440: convert_387_op (op, mode) 1441: register rtx op; 1442: enum machine_mode mode; 1443: { 1444: if (mode != VOIDmode && mode != GET_MODE (op)) 1445: return 0; 1446: 1447: switch (GET_CODE (op)) 1448: { 1449: case FLOAT: 1450: return GET_MODE (XEXP (op, 0)) == SImode; 1451: 1452: case FLOAT_EXTEND: 1453: return mode == DFmode && GET_MODE (XEXP (op, 0)) == SFmode; 1454: 1455: default: 1456: return 0; 1457: } 1458: } 1459: 1460: /* Return 1 if this is a valid shift or rotate operation on a 386. 1461: OP is the expression matched, and MODE is its mode. */ 1462: 1463: int 1464: shift_op (op, mode) 1465: register rtx op; 1466: enum machine_mode mode; 1467: { 1468: rtx operand = XEXP (op, 0); 1469: 1470: if (mode != VOIDmode && mode != GET_MODE (op)) 1471: return 0; 1472: 1473: if (GET_MODE (operand) != GET_MODE (op) 1474: || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT) 1475: return 0; 1476: 1477: return (GET_CODE (op) == ASHIFT 1478: || GET_CODE (op) == ASHIFTRT 1479: || GET_CODE (op) == LSHIFTRT 1480: || GET_CODE (op) == ROTATE 1481: || GET_CODE (op) == ROTATERT); 1482: } 1483: 1484: /* Output code to perform a 387 binary operation in INSN, one of PLUS, 1485: MINUS, MULT or DIV. OPERANDS are the insn operands, where operands[3] 1486: is the expression of the binary operation. The output may either be 1487: emitted here, or returned to the caller, like all output_* functions. 1488: 1489: There is no guarantee that the operands are the same mode, as they 1490: might be within FLOAT or FLOAT_EXTEND expressions. */ 1491: 1492: char * 1493: output_387_binary_op (insn, operands) 1494: rtx insn; 1495: rtx *operands; 1496: { 1497: rtx temp; 1498: char *base_op; 1499: static char buf[100]; 1500: 1501: switch (GET_CODE (operands[3])) 1502: { 1503: case PLUS: 1504: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT 1505: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT) 1506: base_op = "fiadd"; 1507: else 1508: base_op = "fadd"; 1509: break; 1510: 1511: case MINUS: 1512: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT 1513: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT) 1514: base_op = "fisub"; 1515: else 1516: base_op = "fsub"; 1517: break; 1518: 1519: case MULT: 1520: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT 1521: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT) 1522: base_op = "fimul"; 1523: else 1524: base_op = "fmul"; 1525: break; 1526: 1527: case DIV: 1528: if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT 1529: || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT) 1530: base_op = "fidiv"; 1531: else 1532: base_op = "fdiv"; 1533: break; 1534: 1535: default: 1536: abort (); 1537: } 1538: 1539: strcpy (buf, base_op); 1540: 1541: switch (GET_CODE (operands[3])) 1542: { 1543: case MULT: 1544: case PLUS: 1545: if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) 1546: { 1547: temp = operands[2]; 1548: operands[2] = operands[1]; 1549: operands[1] = temp; 1550: } 1551: 1552: if (GET_CODE (operands[2]) == MEM) 1553: return strcat (buf, AS1 (%z2,%2)); 1554: 1555: if (NON_STACK_REG_P (operands[1])) 1556: { 1557: output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1))); 1558: RET; 1559: } 1560: else if (NON_STACK_REG_P (operands[2])) 1561: { 1562: output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1))); 1563: RET; 1564: } 1565: 1566: if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) 1567: return strcat (buf, AS2 (p,%2,%0)); 1568: 1569: if (STACK_TOP_P (operands[0])) 1570: return strcat (buf, AS2 (,%y2,%0)); 1571: else 1572: return strcat (buf, AS2 (,%2,%0)); 1573: 1574: case MINUS: 1575: case DIV: 1576: if (GET_CODE (operands[1]) == MEM) 1577: return strcat (buf, AS1 (r%z1,%1)); 1578: 1579: if (GET_CODE (operands[2]) == MEM) 1580: return strcat (buf, AS1 (%z2,%2)); 1581: 1582: if (NON_STACK_REG_P (operands[1])) 1583: { 1584: output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1))); 1585: RET; 1586: } 1587: else if (NON_STACK_REG_P (operands[2])) 1588: { 1589: output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1))); 1590: RET; 1591: } 1592: 1593: if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2])) 1594: abort (); 1595: 1596: if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) 1597: return strcat (buf, AS2 (rp,%2,%0)); 1598: 1599: if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) 1600: return strcat (buf, AS2 (p,%1,%0)); 1601: 1602: if (STACK_TOP_P (operands[0])) 1603: { 1604: if (STACK_TOP_P (operands[1])) 1605: return strcat (buf, AS2 (,%y2,%0)); 1606: else 1607: return strcat (buf, AS2 (r,%y1,%0)); 1608: } 1609: else if (STACK_TOP_P (operands[1])) 1610: return strcat (buf, AS2 (,%1,%0)); 1611: else 1612: return strcat (buf, AS2 (r,%2,%0)); 1613: 1614: default: 1615: abort (); 1616: } 1617: } 1618: 1619: /* Output code for INSN to convert a float to a signed int. OPERANDS 1620: are the insn operands. The output may be SFmode or DFmode and the 1621: input operand may be SImode or DImode. As a special case, make sure 1622: that the 387 stack top dies if the output mode is DImode, because the 1623: hardware requires this. */ 1624: 1625: char * 1626: output_fix_trunc (insn, operands) 1627: rtx insn; 1628: rtx *operands; 1629: { 1630: int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1631: rtx xops[6]; 1632: 1633: if (! STACK_TOP_P (operands[1]) || 1634: (GET_MODE (operands[0]) == DImode && ! stack_top_dies)) 1635: abort (); 1636: 1637: xops[0] = stack_pointer_rtx; 1638: xops[1] = AT_SP (SImode); 1639: xops[2] = adj_offsettable_operand (xops[1], 2); 1.1.1.4 ! root 1640: xops[3] = GEN_INT (4); ! 1641: xops[4] = GEN_INT (0xc00); 1.1 root 1642: xops[5] = operands[2]; 1643: 1644: output_asm_insn (AS2 (sub%L0,%3,%0), xops); 1645: output_asm_insn (AS1 (fnstc%W5,%1), xops); 1646: output_asm_insn (AS2 (mov%W5,%1,%5), xops); 1647: output_asm_insn (AS2 (or%W5,%4,%5), xops); 1648: output_asm_insn (AS2 (mov%W5,%5,%2), xops); 1649: output_asm_insn (AS1 (fldc%W5,%2), xops); 1650: 1651: if (NON_STACK_REG_P (operands[0])) 1652: output_to_reg (operands[0], stack_top_dies); 1653: else if (GET_CODE (operands[0]) == MEM) 1654: { 1655: /* If frame pointer elimination is being done, the MEM reference 1656: might be an index off of the stack pointer. In that case, 1657: since we have already adjusted %esp above, adjust the operand 1658: address so it points where it should. */ 1659: 1660: if (! frame_pointer_needed 1661: && reg_mentioned_p (stack_pointer_rtx, operands[0])) 1662: operands[0] = adj_offsettable_operand (operands[0], 4); 1663: 1664: if (stack_top_dies) 1665: output_asm_insn (AS1 (fistp%z0,%0), operands); 1666: else 1667: output_asm_insn (AS1 (fist%z0,%0), operands); 1668: } 1669: else 1670: abort (); 1671: 1672: output_asm_insn (AS1 (fldc%W5,%1), xops); 1673: output_asm_insn (AS2 (add%L0,%3,%0), xops); 1674: 1675: RET; 1676: } 1677: 1678: /* Output code for INSN to compare OPERANDS. The two operands might 1679: not have the same mode: one might be within a FLOAT or FLOAT_EXTEND 1.1.1.3 root 1680: expression. If the compare is in mode CCFPEQmode, use an opcode that 1681: will not fault if a qNaN is present. */ 1.1 root 1682: 1683: char * 1684: output_float_compare (insn, operands) 1685: rtx insn; 1686: rtx *operands; 1687: { 1688: int stack_top_dies; 1.1.1.3 root 1689: rtx body = XVECEXP (PATTERN (insn), 0, 0); 1690: int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode; 1.1 root 1691: 1692: if (! STACK_TOP_P (operands[0])) 1693: abort (); 1694: 1695: stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; 1696: 1697: if (STACK_REG_P (operands[1]) 1698: && stack_top_dies 1699: && find_regno_note (insn, REG_DEAD, REGNO (operands[1])) 1700: && REGNO (operands[1]) != FIRST_STACK_REG) 1701: { 1702: /* If both the top of the 387 stack dies, and the other operand 1703: is also a stack register that dies, then this must be a 1704: `fcompp' float compare */ 1705: 1.1.1.3 root 1706: if (unordered_compare) 1707: output_asm_insn ("fucompp", operands); 1708: else 1709: output_asm_insn ("fcompp", operands); 1.1 root 1710: } 1711: else 1712: { 1713: static char buf[100]; 1714: 1.1.1.3 root 1715: /* Decide if this is the integer or float compare opcode, or the 1716: unordered float compare. */ 1.1 root 1717: 1.1.1.3 root 1718: if (unordered_compare) 1719: strcpy (buf, "fucom"); 1720: else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT) 1.1 root 1721: strcpy (buf, "fcom"); 1722: else 1723: strcpy (buf, "ficom"); 1724: 1725: /* Modify the opcode if the 387 stack is to be popped. */ 1726: 1727: if (stack_top_dies) 1728: strcat (buf, "p"); 1729: 1730: if (NON_STACK_REG_P (operands[1])) 1731: output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1))); 1732: else 1733: output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands); 1734: } 1735: 1736: /* Now retrieve the condition code. */ 1737: 1.1.1.3 root 1738: return output_fp_cc0_set (insn); 1739: } 1740: 1741: /* Output opcodes to transfer the results of FP compare or test INSN 1742: from the FPU to the CPU flags. If TARGET_IEEE_FP, ensure that if the 1743: result of the compare or test is unordered, no comparison operator 1744: succeeds except NE. Return an output template, if any. */ 1745: 1746: char * 1747: output_fp_cc0_set (insn) 1748: rtx insn; 1749: { 1750: rtx xops[3]; 1751: rtx unordered_label; 1752: rtx next; 1753: enum rtx_code code; 1754: 1755: xops[0] = gen_rtx (REG, HImode, 0); 1756: output_asm_insn (AS1 (fnsts%W0,%0), xops); 1757: 1758: if (! TARGET_IEEE_FP) 1759: return "sahf"; 1760: 1761: next = next_cc0_user (insn); 1.1 root 1762: 1.1.1.3 root 1763: if (GET_CODE (next) == JUMP_INSN 1764: && GET_CODE (PATTERN (next)) == SET 1765: && SET_DEST (PATTERN (next)) == pc_rtx 1766: && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE) 1767: { 1768: code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)); 1769: } 1770: else if (GET_CODE (PATTERN (next)) == SET) 1771: { 1772: code = GET_CODE (SET_SRC (PATTERN (next))); 1773: } 1774: else 1775: abort (); 1776: 1777: xops[0] = gen_rtx (REG, QImode, 0); 1778: 1779: switch (code) 1780: { 1781: case GT: 1.1.1.4 ! root 1782: xops[1] = GEN_INT (0x45); 1.1.1.3 root 1783: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 1784: /* je label */ 1785: break; 1786: 1787: case LT: 1.1.1.4 ! root 1788: xops[1] = GEN_INT (0x45); ! 1789: xops[2] = GEN_INT (0x01); 1.1.1.3 root 1790: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 1791: output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); 1792: /* je label */ 1793: break; 1794: 1795: case GE: 1.1.1.4 ! root 1796: xops[1] = GEN_INT (0x05); 1.1.1.3 root 1797: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 1798: /* je label */ 1799: break; 1800: 1801: case LE: 1.1.1.4 ! root 1802: xops[1] = GEN_INT (0x45); ! 1803: xops[2] = GEN_INT (0x40); 1.1.1.3 root 1804: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 1805: output_asm_insn (AS1 (dec%B0,%h0), xops); 1806: output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); 1807: /* jb label */ 1808: break; 1809: 1810: case EQ: 1.1.1.4 ! root 1811: xops[1] = GEN_INT (0x45); ! 1812: xops[2] = GEN_INT (0x40); 1.1.1.3 root 1813: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 1814: output_asm_insn (AS2 (cmp%B0,%2,%h0), xops); 1815: /* je label */ 1816: break; 1817: 1818: case NE: 1.1.1.4 ! root 1819: xops[1] = GEN_INT (0x44); ! 1820: xops[2] = GEN_INT (0x40); 1.1.1.3 root 1821: output_asm_insn (AS2 (and%B0,%1,%h0), xops); 1822: output_asm_insn (AS2 (xor%B0,%2,%h0), xops); 1823: /* jne label */ 1824: break; 1825: 1826: case GTU: 1827: case LTU: 1828: case GEU: 1829: case LEU: 1830: default: 1831: abort (); 1832: } 1833: RET; 1.1 root 1834: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.