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

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

unix.superglobalmegacorp.com

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