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

unix.superglobalmegacorp.com

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