Annotation of gcc/config/i386/i386.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.