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

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

unix.superglobalmegacorp.com

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