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

1.1.1.3   root        1: /* Subroutines for insn-output.c for Intel X86.
1.1.1.4 ! root        2:    Copyright (C) 1988, 1992, 1994, 1995 Free Software Foundation, Inc.
1.1       root        3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
1.1.1.4 ! root       18: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            19: Boston, MA 02111-1307, USA.  */
1.1       root       20: 
                     21: #include <stdio.h>
                     22: #include <setjmp.h>
1.1.1.4 ! root       23: #include <ctype.h>
1.1       root       24: #include "config.h"
                     25: #include "rtl.h"
                     26: #include "regs.h"
                     27: #include "hard-reg-set.h"
                     28: #include "real.h"
                     29: #include "insn-config.h"
                     30: #include "conditions.h"
                     31: #include "insn-flags.h"
                     32: #include "output.h"
                     33: #include "insn-attr.h"
                     34: #include "tree.h"
                     35: #include "flags.h"
1.1.1.2   root       36: #include "function.h"
1.1       root       37: 
                     38: #ifdef EXTRA_CONSTRAINT
                     39: /* If EXTRA_CONSTRAINT is defined, then the 'S'
                     40:    constraint in REG_CLASS_FROM_LETTER will no longer work, and various
                     41:    asm statements that need 'S' for class SIREG will break.  */
                     42:  error EXTRA_CONSTRAINT conflicts with S constraint letter
                     43: /* The previous line used to be #error, but some compilers barf
                     44:    even if the conditional was untrue.  */
                     45: #endif
                     46: 
                     47: #define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx))
                     48: 
                     49: extern FILE *asm_out_file;
                     50: extern char *strcat ();
                     51: 
                     52: char *singlemove_string ();
                     53: char *output_move_const_single ();
                     54: char *output_fp_cc0_set ();
                     55: 
                     56: char *hi_reg_name[] = HI_REGISTER_NAMES;
                     57: char *qi_reg_name[] = QI_REGISTER_NAMES;
                     58: char *qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES;
                     59: 
                     60: /* Array of the smallest class containing reg number REGNO, indexed by
                     61:    REGNO.  Used by REGNO_REG_CLASS in i386.h. */
                     62: 
                     63: enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
                     64: {
                     65:   /* ax, dx, cx, bx */
                     66:   AREG, DREG, CREG, BREG,
                     67:   /* si, di, bp, sp */
                     68:   SIREG, DIREG, INDEX_REGS, GENERAL_REGS,
                     69:   /* FP registers */
                     70:   FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS,
                     71:   FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,       
                     72:   /* arg pointer */
                     73:   INDEX_REGS
                     74: };
                     75: 
                     76: /* Test and compare insns in i386.md store the information needed to
                     77:    generate branch and scc insns here.  */
                     78: 
1.1.1.3   root       79: struct rtx_def *i386_compare_op0 = NULL_RTX;
                     80: struct rtx_def *i386_compare_op1 = NULL_RTX;
1.1       root       81: struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
1.1.1.3   root       82: 
                     83: /* Register allocation order */
1.1.1.4 ! root       84: char *i386_reg_alloc_order;
1.1.1.3   root       85: static char regs_allocated[FIRST_PSEUDO_REGISTER];
                     86: 
1.1.1.4 ! root       87: /* # of registers to use to pass arguments. */
        !            88: char *i386_regparm_string;                     /* # registers to use to pass args */
        !            89: int i386_regparm;                              /* i386_regparm_string as a number */
        !            90: 
        !            91: /* Alignment to use for loops and jumps */
        !            92: char *i386_align_loops_string;                 /* power of two alignment for loops */
        !            93: char *i386_align_jumps_string;                 /* power of two alignment for non-loop jumps */
        !            94: char *i386_align_funcs_string;                 /* power of two alignment for functions */
        !            95: 
        !            96: int i386_align_loops;                          /* power of two alignment for loops */
        !            97: int i386_align_jumps;                          /* power of two alignment for non-loop jumps */
        !            98: int i386_align_funcs;                          /* power of two alignment for functions */
        !            99: 
1.1.1.3   root      100: 
                    101: /* Sometimes certain combinations of command options do not make
                    102:    sense on a particular target machine.  You can define a macro
                    103:    `OVERRIDE_OPTIONS' to take account of this.  This macro, if
                    104:    defined, is executed once just after all the command options have
                    105:    been parsed.
                    106: 
                    107:    Don't use this macro to turn on various extra optimizations for
                    108:    `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
                    109: 
                    110: void
                    111: override_options ()
                    112: {
                    113:   int ch, i, regno;
1.1.1.4 ! root      114:   char *p;
        !           115:   int def_align;
1.1.1.3   root      116: 
                    117: #ifdef SUBTARGET_OVERRIDE_OPTIONS
                    118:   SUBTARGET_OVERRIDE_OPTIONS;
                    119: #endif
                    120: 
                    121:   /* Validate registers in register allocation order */
                    122:   if (i386_reg_alloc_order)
                    123:     {
                    124:       for (i = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
                    125:        {
                    126:          switch (ch)
                    127:            {
                    128:            case 'a':   regno = 0;      break;
                    129:            case 'd':   regno = 1;      break;
                    130:            case 'c':   regno = 2;      break;
                    131:            case 'b':   regno = 3;      break;
                    132:            case 'S':   regno = 4;      break;
                    133:            case 'D':   regno = 5;      break;
                    134:            case 'B':   regno = 6;      break;
                    135: 
                    136:            default:    fatal ("Register '%c' is unknown", ch);
                    137:            }
                    138: 
                    139:          if (regs_allocated[regno])
                    140:            fatal ("Register '%c' was already specified in the allocation order", ch);
                    141: 
                    142:          regs_allocated[regno] = 1;
                    143:        }
                    144:     }
1.1.1.4 ! root      145: 
        !           146:   /* Validate -mregparm= value */
        !           147:   if (i386_regparm_string)
        !           148:     {
        !           149:       i386_regparm = atoi (i386_regparm_string);
        !           150:       if (i386_regparm < 0 || i386_regparm > REGPARM_MAX)
        !           151:        fatal ("-mregparm=%d is not between 0 and %d", i386_regparm, REGPARM_MAX);
        !           152:     }
        !           153: 
        !           154:   def_align = (TARGET_386) ? 2 : 4;
        !           155: 
        !           156:   /* Validate -malign-loops= value, or provide default */
        !           157:   if (i386_align_loops_string)
        !           158:     {
        !           159:       i386_align_loops = atoi (i386_align_loops_string);
        !           160:       if (i386_align_loops < 0 || i386_align_loops > MAX_CODE_ALIGN)
        !           161:        fatal ("-malign-loops=%d is not between 0 and %d",
        !           162:               i386_align_loops, MAX_CODE_ALIGN);
        !           163:     }
        !           164:   else
        !           165:     i386_align_loops = 2;
        !           166: 
        !           167:   /* Validate -malign-jumps= value, or provide default */
        !           168:   if (i386_align_jumps_string)
        !           169:     {
        !           170:       i386_align_jumps = atoi (i386_align_jumps_string);
        !           171:       if (i386_align_jumps < 0 || i386_align_jumps > MAX_CODE_ALIGN)
        !           172:        fatal ("-malign-jumps=%d is not between 0 and %d",
        !           173:               i386_align_jumps, MAX_CODE_ALIGN);
        !           174:     }
        !           175:   else
        !           176:     i386_align_jumps = def_align;
        !           177: 
        !           178:   /* Validate -malign-functions= value, or provide default */
        !           179:   if (i386_align_funcs_string)
        !           180:     {
        !           181:       i386_align_funcs = atoi (i386_align_funcs_string);
        !           182:       if (i386_align_funcs < 0 || i386_align_funcs > MAX_CODE_ALIGN)
        !           183:        fatal ("-malign-functions=%d is not between 0 and %d",
        !           184:               i386_align_funcs, MAX_CODE_ALIGN);
        !           185:     }
        !           186:   else
        !           187:     i386_align_funcs = def_align;
1.1.1.3   root      188: }
                    189: 
                    190: /* A C statement (sans semicolon) to choose the order in which to
                    191:    allocate hard registers for pseudo-registers local to a basic
                    192:    block.
                    193: 
                    194:    Store the desired register order in the array `reg_alloc_order'.
                    195:    Element 0 should be the register to allocate first; element 1, the
                    196:    next register; and so on.
                    197: 
                    198:    The macro body should not assume anything about the contents of
                    199:    `reg_alloc_order' before execution of the macro.
                    200: 
                    201:    On most machines, it is not necessary to define this macro.  */
                    202: 
                    203: void
                    204: order_regs_for_local_alloc ()
                    205: {
                    206:   int i, ch, order, regno;
                    207: 
                    208:   /* User specified the register allocation order */
                    209:   if (i386_reg_alloc_order)
                    210:     {
                    211:       for (i = order = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
                    212:        {
                    213:          switch (ch)
                    214:            {
                    215:            case 'a':   regno = 0;      break;
                    216:            case 'd':   regno = 1;      break;
                    217:            case 'c':   regno = 2;      break;
                    218:            case 'b':   regno = 3;      break;
                    219:            case 'S':   regno = 4;      break;
                    220:            case 'D':   regno = 5;      break;
                    221:            case 'B':   regno = 6;      break;
                    222:            }
                    223: 
                    224:          reg_alloc_order[order++] = regno;
                    225:        }
                    226: 
                    227:       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                    228:        {
                    229:          if (!regs_allocated[i])
                    230:            reg_alloc_order[order++] = i;
                    231:        }
                    232:     }
                    233: 
                    234:   /* If users did not specify a register allocation order, favor eax
                    235:      normally except if DImode variables are used, in which case
                    236:      favor edx before eax, which seems to cause less spill register
                    237:      not found messages.  */
                    238:   else
                    239:     {
                    240:       rtx insn;
                    241: 
                    242:       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                    243:        reg_alloc_order[i] = i;
                    244: 
                    245:       if (optimize)
                    246:        {
                    247:          int use_dca = FALSE;
                    248: 
                    249:          for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
                    250:            {
                    251:              if (GET_CODE (insn) == INSN)
                    252:                {
                    253:                  rtx set = NULL_RTX;
                    254:                  rtx pattern = PATTERN (insn);
                    255: 
                    256:                  if (GET_CODE (pattern) == SET)
                    257:                    set = pattern;
                    258: 
                    259:                  else if ((GET_CODE (pattern) == PARALLEL
                    260:                            || GET_CODE (pattern) == SEQUENCE)
                    261:                           && GET_CODE (XVECEXP (pattern, 0, 0)) == SET)
                    262:                    set = XVECEXP (pattern, 0, 0);
                    263: 
                    264:                  if (set && GET_MODE (SET_SRC (set)) == DImode)
                    265:                    {
                    266:                      use_dca = TRUE;
                    267:                      break;
                    268:                    }
                    269:                }
                    270:            }
                    271: 
                    272:          if (use_dca)
                    273:            {
                    274:              reg_alloc_order[0] = 1;   /* edx */
                    275:              reg_alloc_order[1] = 2;   /* ecx */
                    276:              reg_alloc_order[2] = 0;   /* eax */
                    277:            }
                    278:        }
                    279:     }
                    280: }
                    281: 
1.1       root      282: 
1.1.1.4 ! root      283: /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
        !           284:    attribute for DECL.  The attributes in ATTRIBUTES have previously been
        !           285:    assigned to DECL.  */
        !           286: 
        !           287: int
        !           288: i386_valid_decl_attribute_p (decl, attributes, identifier, args)
        !           289:      tree decl;
        !           290:      tree attributes;
        !           291:      tree identifier;
        !           292:      tree args;
        !           293: {
        !           294:   return 0;
        !           295: }
        !           296: 
        !           297: /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
        !           298:    attribute for TYPE.  The attributes in ATTRIBUTES have previously been
        !           299:    assigned to TYPE.  */
        !           300: 
        !           301: int
        !           302: i386_valid_type_attribute_p (type, attributes, identifier, args)
        !           303:      tree type;
        !           304:      tree attributes;
        !           305:      tree identifier;
        !           306:      tree args;
        !           307: {
        !           308:   if (TREE_CODE (type) != FUNCTION_TYPE
        !           309:       && TREE_CODE (type) != FIELD_DECL
        !           310:       && TREE_CODE (type) != TYPE_DECL)
        !           311:     return 0;
        !           312: 
        !           313:   /* Stdcall attribute says callee is responsible for popping arguments
        !           314:      if they are not variable.  */
        !           315:   if (is_attribute_p ("stdcall", identifier))
        !           316:     return (args == NULL_TREE);
        !           317: 
        !           318:   /* Cdecl attribute says the callee is a normal C declaration */
        !           319:   if (is_attribute_p ("cdecl", identifier))
        !           320:     return (args == NULL_TREE);
        !           321: 
        !           322:   /* Regparm attribute specifies how many integer arguments are to be
        !           323:      passed in registers */
        !           324:   if (is_attribute_p ("regparm", identifier))
        !           325:     {
        !           326:       tree cst;
        !           327: 
        !           328:       if (!args || TREE_CODE (args) != TREE_LIST
        !           329:          || TREE_CHAIN (args) != NULL_TREE
        !           330:          || TREE_VALUE (args) == NULL_TREE)
        !           331:        return 0;
        !           332: 
        !           333:       cst = TREE_VALUE (args);
        !           334:       if (TREE_CODE (cst) != INTEGER_CST)
        !           335:        return 0;
        !           336: 
        !           337:       if (TREE_INT_CST_HIGH (cst) != 0
        !           338:          || TREE_INT_CST_LOW (cst) < 0
        !           339:          || TREE_INT_CST_LOW (cst) > REGPARM_MAX)
        !           340:        return 0;
        !           341: 
        !           342:       return 1;
        !           343:     }
        !           344: 
        !           345:   return 0;
        !           346: }
        !           347: 
        !           348: /* Return 0 if the attributes for two types are incompatible, 1 if they
        !           349:    are compatible, and 2 if they are nearly compatible (which causes a
        !           350:    warning to be generated).  */
        !           351: 
        !           352: int
        !           353: i386_comp_type_attributes (type1, type2)
        !           354:      tree type1;
        !           355:      tree type2;
        !           356: {
        !           357:   return 1;
        !           358: }
        !           359: 
        !           360: 
        !           361: /* Value is the number of bytes of arguments automatically
        !           362:    popped when returning from a subroutine call.
        !           363:    FUNDECL is the declaration node of the function (as a tree),
        !           364:    FUNTYPE is the data type of the function (as a tree),
        !           365:    or for a library call it is an identifier node for the subroutine name.
        !           366:    SIZE is the number of bytes of arguments passed on the stack.
        !           367: 
        !           368:    On the 80386, the RTD insn may be used to pop them if the number
        !           369:      of args is fixed, but if the number is variable then the caller
        !           370:      must pop them all.  RTD can't be used for library calls now
        !           371:      because the library is compiled with the Unix compiler.
        !           372:    Use of RTD is a selectable option, since it is incompatible with
        !           373:    standard Unix calling sequences.  If the option is not selected,
        !           374:    the caller must always pop the args.
        !           375: 
        !           376:    The attribute stdcall is equivalent to RTD on a per module basis.  */
        !           377: 
        !           378: int
        !           379: i386_return_pops_args (fundecl, funtype, size)
        !           380:      tree fundecl;
        !           381:      tree funtype;
        !           382:      int size;
        !           383: {
        !           384:   int rtd = TARGET_RTD;
        !           385: 
        !           386:   if (TREE_CODE (funtype) == IDENTIFIER_NODE)
        !           387:     return 0;
        !           388: 
        !           389:   /* Cdecl functions override -mrtd, and never pop the stack */
        !           390:   if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
        !           391:     return 0;
        !           392: 
        !           393:   /* Stdcall functions will pop the stack if not variable args */
        !           394:   if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
        !           395:     rtd = 1;
        !           396: 
        !           397:   if (rtd)
        !           398:     {
        !           399:       if (TYPE_ARG_TYPES (funtype) == NULL_TREE
        !           400:          || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
        !           401:        return size;
        !           402: 
        !           403:       if (aggregate_value_p (TREE_TYPE (funtype)))
        !           404:        return GET_MODE_SIZE (Pmode);
        !           405:     }
        !           406: 
        !           407:   return 0;
        !           408: }
        !           409: 
        !           410: 
        !           411: /* Argument support functions.  */
        !           412: 
        !           413: /* Initialize a variable CUM of type CUMULATIVE_ARGS
        !           414:    for a call to a function whose data type is FNTYPE.
        !           415:    For a library call, FNTYPE is 0.  */
        !           416: 
        !           417: void
        !           418: init_cumulative_args (cum, fntype, libname)
        !           419:      CUMULATIVE_ARGS *cum;     /* argument info to initialize */
        !           420:      tree fntype;              /* tree ptr for function decl */
        !           421:      rtx libname;              /* SYMBOL_REF of library name or 0 */
        !           422: {
        !           423:   static CUMULATIVE_ARGS zero_cum;
        !           424:   tree param, next_param;
        !           425: 
        !           426:   if (TARGET_DEBUG_ARG)
        !           427:     {
        !           428:       fprintf (stderr, "\ninit_cumulative_args (");
        !           429:       if (fntype)
        !           430:        {
        !           431:          tree ret_type = TREE_TYPE (fntype);
        !           432:          fprintf (stderr, "fntype code = %s, ret code = %s",
        !           433:                   tree_code_name[ (int)TREE_CODE (fntype) ],
        !           434:                   tree_code_name[ (int)TREE_CODE (ret_type) ]);
        !           435:        }
        !           436:       else
        !           437:        fprintf (stderr, "no fntype");
        !           438: 
        !           439:       if (libname)
        !           440:        fprintf (stderr, ", libname = %s", XSTR (libname, 0));
        !           441:     }
        !           442: 
        !           443:   *cum = zero_cum;
        !           444: 
        !           445:   /* Set up the number of registers to use for passing arguments.  */
        !           446:   cum->nregs = i386_regparm;
        !           447:   if (fntype)
        !           448:     {
        !           449:       tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));
        !           450:       if (attr)
        !           451:        cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
        !           452:     }
        !           453: 
        !           454:   /* Determine if this function has variable arguments.  This is
        !           455:      indicated by the last argument being 'void_type_mode' if there
        !           456:      are no variable arguments.  If there are variable arguments, then
        !           457:      we won't pass anything in registers */
        !           458: 
        !           459:   if (cum->nregs)
        !           460:     {
        !           461:       for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
        !           462:           param != (tree)0;
        !           463:           param = next_param)
        !           464:        {
        !           465:          next_param = TREE_CHAIN (param);
        !           466:          if (next_param == (tree)0 && TREE_VALUE (param) != void_type_node)
        !           467:            cum->nregs = 0;
        !           468:        }
        !           469:     }
        !           470: 
        !           471:   if (TARGET_DEBUG_ARG)
        !           472:     fprintf (stderr, ", nregs=%d )\n", cum->nregs);
        !           473: 
        !           474:   return;
        !           475: }
        !           476: 
        !           477: /* Update the data in CUM to advance over an argument
        !           478:    of mode MODE and data type TYPE.
        !           479:    (TYPE is null for libcalls where that information may not be available.)  */
        !           480: 
        !           481: void
        !           482: function_arg_advance (cum, mode, type, named)
        !           483:      CUMULATIVE_ARGS *cum;     /* current arg information */
        !           484:      enum machine_mode mode;   /* current arg mode */
        !           485:      tree type;                        /* type of the argument or 0 if lib support */
        !           486:      int named;                        /* whether or not the argument was named */
        !           487: {
        !           488:   int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
        !           489:   int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
        !           490: 
        !           491:   if (TARGET_DEBUG_ARG)
        !           492:     fprintf (stderr,
        !           493:             "function_adv( size=%d, words=%2d, nregs=%d, mode=%4s, named=%d )\n\n",
        !           494:             words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);
        !           495: 
        !           496:   cum->words += words;
        !           497:   cum->nregs -= words;
        !           498:   cum->regno += words;
        !           499: 
        !           500:   if (cum->nregs <= 0)
        !           501:     {
        !           502:       cum->nregs = 0;
        !           503:       cum->regno = 0;
        !           504:     }
        !           505: 
        !           506:   return;
        !           507: }
        !           508: 
        !           509: /* Define where to put the arguments to a function.
        !           510:    Value is zero to push the argument on the stack,
        !           511:    or a hard register in which to store the argument.
        !           512: 
        !           513:    MODE is the argument's machine mode.
        !           514:    TYPE is the data type of the argument (as a tree).
        !           515:     This is null for libcalls where that information may
        !           516:     not be available.
        !           517:    CUM is a variable of type CUMULATIVE_ARGS which gives info about
        !           518:     the preceding args and about the function being called.
        !           519:    NAMED is nonzero if this argument is a named parameter
        !           520:     (otherwise it is an extra parameter matching an ellipsis).  */
        !           521: 
        !           522: struct rtx_def *
        !           523: function_arg (cum, mode, type, named)
        !           524:      CUMULATIVE_ARGS *cum;     /* current arg information */
        !           525:      enum machine_mode mode;   /* current arg mode */
        !           526:      tree type;                        /* type of the argument or 0 if lib support */
        !           527:      int named;                        /* != 0 for normal args, == 0 for ... args */
        !           528: {
        !           529:   rtx ret   = NULL_RTX;
        !           530:   int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
        !           531:   int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
        !           532: 
        !           533:   switch (mode)
        !           534:     {
        !           535:     default:                   /* for now, pass fp/complex values on the stack */
        !           536:       break;
        !           537: 
        !           538:     case BLKmode:
        !           539:     case DImode:
        !           540:     case SImode:
        !           541:     case HImode:
        !           542:     case QImode:
        !           543:       if (words <= cum->nregs)
        !           544:        ret = gen_rtx (REG, mode, cum->regno);
        !           545:       break;
        !           546:     }
        !           547: 
        !           548:   if (TARGET_DEBUG_ARG)
        !           549:     {
        !           550:       fprintf (stderr,
        !           551:               "function_arg( size=%d, words=%2d, nregs=%d, mode=%4s, named=%d",
        !           552:               words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);
        !           553: 
        !           554:       if (ret)
        !           555:        fprintf (stderr, ", reg=%%e%s", reg_names[ REGNO(ret) ]);
        !           556:       else
        !           557:        fprintf (stderr, ", stack");
        !           558: 
        !           559:       fprintf (stderr, " )\n");
        !           560:     }
        !           561: 
        !           562:   return ret;
        !           563: }
        !           564: 
        !           565: /* For an arg passed partly in registers and partly in memory,
        !           566:    this is the number of registers used.
        !           567:    For args passed entirely in registers or entirely in memory, zero.  */
        !           568: 
        !           569: int
        !           570: function_arg_partial_nregs (cum, mode, type, named)
        !           571:      CUMULATIVE_ARGS *cum;     /* current arg information */
        !           572:      enum machine_mode mode;   /* current arg mode */
        !           573:      tree type;                        /* type of the argument or 0 if lib support */
        !           574:      int named;                        /* != 0 for normal args, == 0 for ... args */
        !           575: {
        !           576:   return 0;
        !           577: }
        !           578: 
        !           579: 
1.1       root      580: /* Output an insn whose source is a 386 integer register.  SRC is the
                    581:    rtx for the register, and TEMPLATE is the op-code template.  SRC may
                    582:    be either SImode or DImode.
                    583: 
                    584:    The template will be output with operands[0] as SRC, and operands[1]
                    585:    as a pointer to the top of the 386 stack.  So a call from floatsidf2
                    586:    would look like this:
                    587: 
                    588:       output_op_from_reg (operands[1], AS1 (fild%z0,%1));
                    589: 
                    590:    where %z0 corresponds to the caller's operands[1], and is used to
                    591:    emit the proper size suffix.
                    592: 
                    593:    ??? Extend this to handle HImode - a 387 can load and store HImode
                    594:    values directly. */
                    595: 
                    596: void
                    597: output_op_from_reg (src, template)
                    598:      rtx src;
                    599:      char *template;
                    600: {
                    601:   rtx xops[4];
1.1.1.2   root      602:   int size = GET_MODE_SIZE (GET_MODE (src));
1.1       root      603: 
                    604:   xops[0] = src;
                    605:   xops[1] = AT_SP (Pmode);
1.1.1.2   root      606:   xops[2] = GEN_INT (size);
1.1       root      607:   xops[3] = stack_pointer_rtx;
                    608: 
1.1.1.2   root      609:   if (size > UNITS_PER_WORD)
1.1       root      610:     {
1.1.1.2   root      611:       rtx high;
                    612:       if (size > 2 * UNITS_PER_WORD)
                    613:        {
                    614:          high = gen_rtx (REG, SImode, REGNO (src) + 2);
                    615:          output_asm_insn (AS1 (push%L0,%0), &high);
                    616:        }
                    617:       high = gen_rtx (REG, SImode, REGNO (src) + 1);
1.1       root      618:       output_asm_insn (AS1 (push%L0,%0), &high);
                    619:     }
                    620:   output_asm_insn (AS1 (push%L0,%0), &src);
                    621: 
                    622:   output_asm_insn (template, xops);
                    623: 
                    624:   output_asm_insn (AS2 (add%L3,%2,%3), xops);
                    625: }
                    626: 
                    627: /* Output an insn to pop an value from the 387 top-of-stack to 386
                    628:    register DEST. The 387 register stack is popped if DIES is true.  If
                    629:    the mode of DEST is an integer mode, a `fist' integer store is done,
                    630:    otherwise a `fst' float store is done. */
                    631: 
                    632: void
                    633: output_to_reg (dest, dies)
                    634:      rtx dest;
                    635:      int dies;
                    636: {
                    637:   rtx xops[4];
1.1.1.2   root      638:   int size = GET_MODE_SIZE (GET_MODE (dest));
1.1       root      639: 
                    640:   xops[0] = AT_SP (Pmode);
                    641:   xops[1] = stack_pointer_rtx;
1.1.1.2   root      642:   xops[2] = GEN_INT (size);
1.1       root      643:   xops[3] = dest;
                    644: 
                    645:   output_asm_insn (AS2 (sub%L1,%2,%1), xops);
                    646: 
                    647:   if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)
                    648:     {
                    649:       if (dies)
                    650:        output_asm_insn (AS1 (fistp%z3,%y0), xops);
                    651:       else
                    652:        output_asm_insn (AS1 (fist%z3,%y0), xops);
                    653:     }
                    654:   else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT)
                    655:     {
                    656:       if (dies)
                    657:        output_asm_insn (AS1 (fstp%z3,%y0), xops);
                    658:       else
1.1.1.2   root      659:        {
                    660:          if (GET_MODE (dest) == XFmode)
                    661:            {
                    662:              output_asm_insn (AS1 (fstp%z3,%y0), xops);
                    663:              output_asm_insn (AS1 (fld%z3,%y0), xops);
                    664:            }
                    665:          else
                    666:            output_asm_insn (AS1 (fst%z3,%y0), xops);
                    667:        }
1.1       root      668:     }
                    669:   else
                    670:     abort ();
                    671: 
                    672:   output_asm_insn (AS1 (pop%L0,%0), &dest);
                    673: 
1.1.1.2   root      674:   if (size > UNITS_PER_WORD)
1.1       root      675:     {
                    676:       dest = gen_rtx (REG, SImode, REGNO (dest) + 1);
                    677:       output_asm_insn (AS1 (pop%L0,%0), &dest);
1.1.1.2   root      678:       if (size > 2 * UNITS_PER_WORD)
                    679:        {
                    680:          dest = gen_rtx (REG, SImode, REGNO (dest) + 1);
                    681:          output_asm_insn (AS1 (pop%L0,%0), &dest);
                    682:        }
1.1       root      683:     }
                    684: }
                    685: 
                    686: char *
                    687: singlemove_string (operands)
                    688:      rtx *operands;
                    689: {
                    690:   rtx x;
                    691:   if (GET_CODE (operands[0]) == MEM
                    692:       && GET_CODE (x = XEXP (operands[0], 0)) == PRE_DEC)
                    693:     {
                    694:       if (XEXP (x, 0) != stack_pointer_rtx)
                    695:        abort ();
                    696:       return "push%L1 %1";
                    697:     }
                    698:   else if (GET_CODE (operands[1]) == CONST_DOUBLE)
                    699:     {
                    700:       return output_move_const_single (operands);
                    701:     }
                    702:   else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)
                    703:     return AS2 (mov%L0,%1,%0);
                    704:   else if (CONSTANT_P (operands[1]))
                    705:     return AS2 (mov%L0,%1,%0);
                    706:   else
                    707:     {
                    708:       output_asm_insn ("push%L1 %1", operands);
                    709:       return "pop%L0 %0";
                    710:     }
                    711: }
                    712: 
                    713: /* Return a REG that occurs in ADDR with coefficient 1.
                    714:    ADDR can be effectively incremented by incrementing REG.  */
                    715: 
                    716: static rtx
                    717: find_addr_reg (addr)
                    718:      rtx addr;
                    719: {
                    720:   while (GET_CODE (addr) == PLUS)
                    721:     {
                    722:       if (GET_CODE (XEXP (addr, 0)) == REG)
                    723:        addr = XEXP (addr, 0);
                    724:       else if (GET_CODE (XEXP (addr, 1)) == REG)
                    725:        addr = XEXP (addr, 1);
                    726:       else if (CONSTANT_P (XEXP (addr, 0)))
                    727:        addr = XEXP (addr, 1);
                    728:       else if (CONSTANT_P (XEXP (addr, 1)))
                    729:        addr = XEXP (addr, 0);
                    730:       else
                    731:        abort ();
                    732:     }
                    733:   if (GET_CODE (addr) == REG)
                    734:     return addr;
                    735:   abort ();
                    736: }
                    737: 
1.1.1.3   root      738: 
1.1       root      739: /* Output an insn to add the constant N to the register X.  */
                    740: 
                    741: static void
                    742: asm_add (n, x)
                    743:      int n;
                    744:      rtx x;
                    745: {
                    746:   rtx xops[2];
1.1.1.3   root      747:   xops[0] = x;
                    748: 
                    749:   if (n == -1)
                    750:     output_asm_insn (AS1 (dec%L0,%0), xops);
                    751:   else if (n == 1)
                    752:     output_asm_insn (AS1 (inc%L0,%0), xops);
                    753:   else if (n < 0)
1.1       root      754:     {
1.1.1.3   root      755:       xops[1] = GEN_INT (-n);
                    756:       output_asm_insn (AS2 (sub%L0,%1,%0), xops);
1.1       root      757:     }
                    758:   else if (n > 0)
                    759:     {
1.1.1.3   root      760:       xops[1] = GEN_INT (n);
                    761:       output_asm_insn (AS2 (add%L0,%1,%0), xops);
1.1       root      762:     }
                    763: }
                    764: 
1.1.1.3   root      765: 
1.1       root      766: /* Output assembler code to perform a doubleword move insn
                    767:    with operands OPERANDS.  */
                    768: 
                    769: char *
                    770: output_move_double (operands)
                    771:      rtx *operands;
                    772: {
                    773:   enum {REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
                    774:   rtx latehalf[2];
1.1.1.2   root      775:   rtx middlehalf[2];
                    776:   rtx xops[2];
1.1       root      777:   rtx addreg0 = 0, addreg1 = 0;
                    778:   int dest_overlapped_low = 0;
1.1.1.4 ! root      779:   int size = GET_MODE_SIZE (GET_MODE (operands[0]));
1.1.1.2   root      780: 
                    781:   middlehalf[0] = 0;
                    782:   middlehalf[1] = 0;
1.1       root      783: 
                    784:   /* First classify both operands.  */
                    785: 
                    786:   if (REG_P (operands[0]))
                    787:     optype0 = REGOP;
                    788:   else if (offsettable_memref_p (operands[0]))
                    789:     optype0 = OFFSOP;
                    790:   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
                    791:     optype0 = POPOP;
                    792:   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
                    793:     optype0 = PUSHOP;
                    794:   else if (GET_CODE (operands[0]) == MEM)
                    795:     optype0 = MEMOP;
                    796:   else
                    797:     optype0 = RNDOP;
                    798: 
                    799:   if (REG_P (operands[1]))
                    800:     optype1 = REGOP;
                    801:   else if (CONSTANT_P (operands[1]))
                    802:     optype1 = CNSTOP;
                    803:   else if (offsettable_memref_p (operands[1]))
                    804:     optype1 = OFFSOP;
                    805:   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
                    806:     optype1 = POPOP;
                    807:   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
                    808:     optype1 = PUSHOP;
                    809:   else if (GET_CODE (operands[1]) == MEM)
                    810:     optype1 = MEMOP;
                    811:   else
                    812:     optype1 = RNDOP;
                    813: 
                    814:   /* Check for the cases that the operand constraints are not
                    815:      supposed to allow to happen.  Abort if we get one,
                    816:      because generating code for these cases is painful.  */
                    817: 
                    818:   if (optype0 == RNDOP || optype1 == RNDOP)
                    819:     abort ();
                    820: 
                    821:   /* If one operand is decrementing and one is incrementing
                    822:      decrement the former register explicitly
                    823:      and change that operand into ordinary indexing.  */
                    824: 
                    825:   if (optype0 == PUSHOP && optype1 == POPOP)
                    826:     {
1.1.1.2   root      827:       /* ??? Can this ever happen on i386? */
1.1       root      828:       operands[0] = XEXP (XEXP (operands[0], 0), 0);
1.1.1.2   root      829:       asm_add (-size, operands[0]);
                    830:       if (GET_MODE (operands[1]) == XFmode)
                    831:         operands[0] = gen_rtx (MEM, XFmode, operands[0]);
                    832:       else if (GET_MODE (operands[0]) == DFmode)
                    833:         operands[0] = gen_rtx (MEM, DFmode, operands[0]);
                    834:       else
                    835:         operands[0] = gen_rtx (MEM, DImode, operands[0]);
1.1       root      836:       optype0 = OFFSOP;
                    837:     }
1.1.1.2   root      838: 
1.1       root      839:   if (optype0 == POPOP && optype1 == PUSHOP)
                    840:     {
1.1.1.2   root      841:       /* ??? Can this ever happen on i386? */
1.1       root      842:       operands[1] = XEXP (XEXP (operands[1], 0), 0);
1.1.1.2   root      843:       asm_add (-size, operands[1]);
                    844:       if (GET_MODE (operands[1]) == XFmode)
                    845:         operands[1] = gen_rtx (MEM, XFmode, operands[1]);
                    846:       else if (GET_MODE (operands[1]) == DFmode)
                    847:         operands[1] = gen_rtx (MEM, DFmode, operands[1]);
                    848:       else
                    849:         operands[1] = gen_rtx (MEM, DImode, operands[1]);
1.1       root      850:       optype1 = OFFSOP;
                    851:     }
                    852: 
                    853:   /* If an operand is an unoffsettable memory ref, find a register
                    854:      we can increment temporarily to make it refer to the second word.  */
                    855: 
                    856:   if (optype0 == MEMOP)
                    857:     addreg0 = find_addr_reg (XEXP (operands[0], 0));
                    858: 
                    859:   if (optype1 == MEMOP)
                    860:     addreg1 = find_addr_reg (XEXP (operands[1], 0));
                    861: 
                    862:   /* Ok, we can do one word at a time.
                    863:      Normally we do the low-numbered word first,
                    864:      but if either operand is autodecrementing then we
                    865:      do the high-numbered word first.
                    866: 
                    867:      In either case, set up in LATEHALF the operands to use
                    868:      for the high-numbered word and in some cases alter the
                    869:      operands in OPERANDS to be suitable for the low-numbered word.  */
                    870: 
1.1.1.2   root      871:   if (size == 12)
                    872:     {
                    873:       if (optype0 == REGOP)
                    874:        {
                    875:          middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    876:          latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
                    877:        }
                    878:       else if (optype0 == OFFSOP)
                    879:        {
                    880:          middlehalf[0] = adj_offsettable_operand (operands[0], 4);
                    881:          latehalf[0] = adj_offsettable_operand (operands[0], 8);
                    882:        }
                    883:       else
                    884:        {
                    885:          middlehalf[0] = operands[0];
                    886:          latehalf[0] = operands[0];
                    887:        }
                    888:     
                    889:       if (optype1 == REGOP)
                    890:        {
                    891:           middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    892:           latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
                    893:        }
                    894:       else if (optype1 == OFFSOP)
                    895:        {
                    896:           middlehalf[1] = adj_offsettable_operand (operands[1], 4);
                    897:           latehalf[1] = adj_offsettable_operand (operands[1], 8);
                    898:        }
                    899:       else if (optype1 == CNSTOP)
                    900:        {
                    901:          if (GET_CODE (operands[1]) == CONST_DOUBLE)
                    902:            {
                    903:              REAL_VALUE_TYPE r; long l[3];
1.1       root      904: 
1.1.1.2   root      905:              REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
                    906:              REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
                    907:              operands[1] = GEN_INT (l[0]);
                    908:              middlehalf[1] = GEN_INT (l[1]);
                    909:              latehalf[1] = GEN_INT (l[2]);
                    910:            }
                    911:          else if (CONSTANT_P (operands[1]))
                    912:            /* No non-CONST_DOUBLE constant should ever appear here.  */
                    913:            abort ();
                    914:         }
                    915:       else
1.1       root      916:        {
1.1.1.2   root      917:          middlehalf[1] = operands[1];
                    918:          latehalf[1] = operands[1];
1.1       root      919:        }
                    920:     }
1.1.1.2   root      921:   else /* size is not 12: */
                    922:     {
                    923:       if (optype0 == REGOP)
                    924:        latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    925:       else if (optype0 == OFFSOP)
                    926:        latehalf[0] = adj_offsettable_operand (operands[0], 4);
                    927:       else
                    928:        latehalf[0] = operands[0];
                    929: 
                    930:       if (optype1 == REGOP)
                    931:        latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    932:       else if (optype1 == OFFSOP)
                    933:        latehalf[1] = adj_offsettable_operand (operands[1], 4);
                    934:       else if (optype1 == CNSTOP)
1.1.1.4 ! root      935:        split_double (operands[1], &operands[1], &latehalf[1]);
1.1.1.2   root      936:       else
                    937:        latehalf[1] = operands[1];
                    938:     }
1.1       root      939: 
                    940:   /* If insn is effectively movd N (sp),-(sp) then we will do the
1.1.1.2   root      941:      high word first.  We should use the adjusted operand 1
                    942:      (which is N+4 (sp) or N+8 (sp))
                    943:      for the low word and middle word as well,
                    944:      to compensate for the first decrement of sp.  */
1.1       root      945:   if (optype0 == PUSHOP
                    946:       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
                    947:       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
1.1.1.2   root      948:     middlehalf[1] = operands[1] = latehalf[1];
1.1       root      949: 
                    950:   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
                    951:      if the upper part of reg N does not appear in the MEM, arrange to
                    952:      emit the move late-half first.  Otherwise, compute the MEM address
                    953:      into the upper part of N and use that as a pointer to the memory
                    954:      operand.  */
                    955:   if (optype0 == REGOP
                    956:       && (optype1 == OFFSOP || optype1 == MEMOP))
                    957:     {
                    958:       if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
                    959:          && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
                    960:        {
                    961:          /* If both halves of dest are used in the src memory address,
                    962:             compute the address into latehalf of dest.  */
1.1.1.2   root      963: compadr:
1.1       root      964:          xops[0] = latehalf[0];
                    965:          xops[1] = XEXP (operands[1], 0);
                    966:          output_asm_insn (AS2 (lea%L0,%a1,%0), xops);
1.1.1.2   root      967:          if( GET_MODE (operands[1]) == XFmode )
                    968:            {
                    969: /*         abort (); */
                    970:              operands[1] = gen_rtx (MEM, XFmode, latehalf[0]);
                    971:              middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
                    972:              latehalf[1] = adj_offsettable_operand (operands[1], size-4);
                    973:            }
                    974:          else
                    975:            {
                    976:              operands[1] = gen_rtx (MEM, DImode, latehalf[0]);
                    977:              latehalf[1] = adj_offsettable_operand (operands[1], size-4);
                    978:            }
                    979:        }
                    980:       else if (size == 12
                    981:                 && reg_mentioned_p (middlehalf[0], XEXP (operands[1], 0)))
                    982:        {
                    983:          /* Check for two regs used by both source and dest. */
                    984:          if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
                    985:                || reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
                    986:                goto compadr;
                    987: 
                    988:          /* JRV says this can't happen: */
                    989:          if (addreg0 || addreg1)
                    990:              abort();
                    991: 
                    992:          /* Only the middle reg conflicts; simply put it last. */
                    993:          output_asm_insn (singlemove_string (operands), operands);
                    994:          output_asm_insn (singlemove_string (latehalf), latehalf);
                    995:          output_asm_insn (singlemove_string (middlehalf), middlehalf);
                    996:          return "";
1.1       root      997:        }
                    998:       else if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
                    999:        /* If the low half of dest is mentioned in the source memory
                   1000:           address, the arrange to emit the move late half first.  */
                   1001:        dest_overlapped_low = 1;
                   1002:     }
                   1003: 
                   1004:   /* If one or both operands autodecrementing,
                   1005:      do the two words, high-numbered first.  */
                   1006: 
                   1007:   /* Likewise,  the first move would clobber the source of the second one,
                   1008:      do them in the other order.  This happens only for registers;
                   1009:      such overlap can't happen in memory unless the user explicitly
                   1010:      sets it up, and that is an undefined circumstance.  */
                   1011: 
1.1.1.2   root     1012: /*
1.1       root     1013:   if (optype0 == PUSHOP || optype1 == PUSHOP
                   1014:       || (optype0 == REGOP && optype1 == REGOP
                   1015:          && REGNO (operands[0]) == REGNO (latehalf[1]))
                   1016:       || dest_overlapped_low)
1.1.1.2   root     1017: */
                   1018:   if (optype0 == PUSHOP || optype1 == PUSHOP
                   1019:       || (optype0 == REGOP && optype1 == REGOP
                   1020:          && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
                   1021:              || REGNO (operands[0]) == REGNO (latehalf[1])))
                   1022:       || dest_overlapped_low)
1.1       root     1023:     {
                   1024:       /* Make any unoffsettable addresses point at high-numbered word.  */
                   1025:       if (addreg0)
1.1.1.2   root     1026:        asm_add (size-4, addreg0);
1.1       root     1027:       if (addreg1)
1.1.1.2   root     1028:        asm_add (size-4, addreg1);
1.1       root     1029: 
                   1030:       /* Do that word.  */
                   1031:       output_asm_insn (singlemove_string (latehalf), latehalf);
                   1032: 
                   1033:       /* Undo the adds we just did.  */
                   1034:       if (addreg0)
                   1035:          asm_add (-4, addreg0);
                   1036:       if (addreg1)
                   1037:        asm_add (-4, addreg1);
                   1038: 
1.1.1.2   root     1039:       if (size == 12)
                   1040:         {
                   1041:         output_asm_insn (singlemove_string (middlehalf), middlehalf);
                   1042:         if (addreg0)
                   1043:            asm_add (-4, addreg0);
                   1044:         if (addreg1)
                   1045:           asm_add (-4, addreg1);
                   1046:        }
                   1047: 
1.1       root     1048:       /* Do low-numbered word.  */
                   1049:       return singlemove_string (operands);
                   1050:     }
                   1051: 
                   1052:   /* Normal case: do the two words, low-numbered first.  */
                   1053: 
                   1054:   output_asm_insn (singlemove_string (operands), operands);
                   1055: 
1.1.1.2   root     1056:   /* Do the middle one of the three words for long double */
                   1057:   if (size == 12)
                   1058:     {
                   1059:       if (addreg0)
                   1060:         asm_add (4, addreg0);
                   1061:       if (addreg1)
                   1062:         asm_add (4, addreg1);
                   1063: 
                   1064:       output_asm_insn (singlemove_string (middlehalf), middlehalf);
                   1065:     }
                   1066: 
1.1       root     1067:   /* Make any unoffsettable addresses point at high-numbered word.  */
                   1068:   if (addreg0)
                   1069:     asm_add (4, addreg0);
                   1070:   if (addreg1)
                   1071:     asm_add (4, addreg1);
                   1072: 
                   1073:   /* Do that word.  */
                   1074:   output_asm_insn (singlemove_string (latehalf), latehalf);
                   1075: 
                   1076:   /* Undo the adds we just did.  */
                   1077:   if (addreg0)
1.1.1.2   root     1078:     asm_add (4-size, addreg0);
1.1       root     1079:   if (addreg1)
1.1.1.2   root     1080:     asm_add (4-size, addreg1);
1.1       root     1081: 
                   1082:   return "";
                   1083: }
1.1.1.3   root     1084: 
                   1085: 
                   1086: #define MAX_TMPS 2             /* max temporary registers used */
                   1087: 
                   1088: /* Output the appropriate code to move push memory on the stack */
                   1089: 
                   1090: char *
                   1091: output_move_pushmem (operands, insn, length, tmp_start, n_operands)
                   1092:      rtx operands[];
                   1093:      rtx insn;
                   1094:      int length;
                   1095:      int tmp_start;
                   1096:      int n_operands;
                   1097: {
                   1098: 
                   1099:   struct {
                   1100:     char *load;
                   1101:     char *push;
                   1102:     rtx   xops[2];
                   1103:   } tmp_info[MAX_TMPS];
                   1104: 
                   1105:   rtx src = operands[1];
                   1106:   int max_tmps = 0;
                   1107:   int offset = 0;
                   1108:   int stack_p = reg_overlap_mentioned_p (stack_pointer_rtx, src);
                   1109:   int stack_offset = 0;
                   1110:   int i, num_tmps;
                   1111:   rtx xops[1];
                   1112: 
                   1113:   if (!offsettable_memref_p (src))
                   1114:     fatal_insn ("Source is not offsettable", insn);
                   1115: 
                   1116:   if ((length & 3) != 0)
                   1117:     fatal_insn ("Pushing non-word aligned size", insn);
                   1118: 
                   1119:   /* Figure out which temporary registers we have available */
                   1120:   for (i = tmp_start; i < n_operands; i++)
                   1121:     {
                   1122:       if (GET_CODE (operands[i]) == REG)
                   1123:        {
                   1124:          if (reg_overlap_mentioned_p (operands[i], src))
                   1125:            continue;
                   1126: 
                   1127:          tmp_info[ max_tmps++ ].xops[1] = operands[i];
                   1128:          if (max_tmps == MAX_TMPS)
                   1129:            break;
                   1130:        }
                   1131:     }
                   1132: 
                   1133:   if (max_tmps == 0)
                   1134:     for (offset = length - 4; offset >= 0; offset -= 4)
                   1135:       {
                   1136:        xops[0] = adj_offsettable_operand (src, offset + stack_offset);
                   1137:        output_asm_insn (AS1(push%L0,%0), xops);
                   1138:        if (stack_p)
                   1139:          stack_offset += 4;
                   1140:       }
                   1141: 
                   1142:   else
                   1143:     for (offset = length - 4; offset >= 0; )
                   1144:       {
                   1145:        for (num_tmps = 0; num_tmps < max_tmps && offset >= 0; num_tmps++)
                   1146:          {
                   1147:            tmp_info[num_tmps].load    = AS2(mov%L0,%0,%1);
                   1148:            tmp_info[num_tmps].push    = AS1(push%L0,%1);
                   1149:            tmp_info[num_tmps].xops[0] = adj_offsettable_operand (src, offset + stack_offset);
                   1150:            offset -= 4;
                   1151:          }
                   1152: 
                   1153:        for (i = 0; i < num_tmps; i++)
                   1154:          output_asm_insn (tmp_info[i].load, tmp_info[i].xops);
                   1155: 
                   1156:        for (i = 0; i < num_tmps; i++)
                   1157:          output_asm_insn (tmp_info[i].push, tmp_info[i].xops);
                   1158: 
                   1159:        if (stack_p)
                   1160:          stack_offset += 4*num_tmps;
                   1161:       }
                   1162: 
                   1163:   return "";
                   1164: }
                   1165: 
                   1166: 
                   1167: 
                   1168: /* Output the appropriate code to move data between two memory locations */
                   1169: 
                   1170: char *
                   1171: output_move_memory (operands, insn, length, tmp_start, n_operands)
                   1172:      rtx operands[];
                   1173:      rtx insn;
                   1174:      int length;
                   1175:      int tmp_start;
                   1176:      int n_operands;
                   1177: {
                   1178:   struct {
                   1179:     char *load;
                   1180:     char *store;
                   1181:     rtx   xops[3];
                   1182:   } tmp_info[MAX_TMPS];
                   1183: 
                   1184:   rtx dest = operands[0];
                   1185:   rtx src  = operands[1];
                   1186:   rtx qi_tmp = NULL_RTX;
                   1187:   int max_tmps = 0;
                   1188:   int offset = 0;
                   1189:   int i, num_tmps;
                   1190:   rtx xops[3];
                   1191: 
                   1192:   if (GET_CODE (dest) == MEM
                   1193:       && GET_CODE (XEXP (dest, 0)) == PRE_INC
                   1194:       && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
                   1195:     return output_move_pushmem (operands, insn, length, tmp_start, n_operands);
                   1196: 
                   1197:   if (!offsettable_memref_p (src))
                   1198:     fatal_insn ("Source is not offsettable", insn);
                   1199: 
                   1200:   if (!offsettable_memref_p (dest))
                   1201:     fatal_insn ("Destination is not offsettable", insn);
                   1202: 
                   1203:   /* Figure out which temporary registers we have available */
                   1204:   for (i = tmp_start; i < n_operands; i++)
                   1205:     {
                   1206:       if (GET_CODE (operands[i]) == REG)
                   1207:        {
                   1208:          if ((length & 1) != 0 && !qi_tmp && QI_REG_P (operands[i]))
                   1209:            qi_tmp = operands[i];
                   1210: 
                   1211:          if (reg_overlap_mentioned_p (operands[i], dest))
                   1212:            fatal_insn ("Temporary register overlaps the destination", insn);
                   1213: 
                   1214:          if (reg_overlap_mentioned_p (operands[i], src))
                   1215:            fatal_insn ("Temporary register overlaps the source", insn);
                   1216: 
                   1217:          tmp_info[ max_tmps++ ].xops[2] = operands[i];
                   1218:          if (max_tmps == MAX_TMPS)
                   1219:            break;
                   1220:        }
                   1221:     }
                   1222: 
                   1223:   if (max_tmps == 0)
                   1224:     fatal_insn ("No scratch registers were found to do memory->memory moves", insn);
                   1225: 
                   1226:   if ((length & 1) != 0)
                   1227:     {
                   1228:       if (!qi_tmp)
                   1229:        fatal_insn ("No byte register found when moving odd # of bytes.", insn);
                   1230:     }
                   1231: 
                   1232:   while (length > 1)
                   1233:     {
                   1234:       for (num_tmps = 0; num_tmps < max_tmps; num_tmps++)
                   1235:        {
                   1236:          if (length >= 4)
                   1237:            {
                   1238:              tmp_info[num_tmps].load    = AS2(mov%L0,%1,%2);
                   1239:              tmp_info[num_tmps].store   = AS2(mov%L0,%2,%0);
                   1240:              tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset);
                   1241:              tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset);
                   1242:              offset += 4;
                   1243:              length -= 4;
                   1244:            }
                   1245:          else if (length >= 2)
                   1246:            {
                   1247:              tmp_info[num_tmps].load    = AS2(mov%W0,%1,%2);
                   1248:              tmp_info[num_tmps].store   = AS2(mov%W0,%2,%0);
                   1249:              tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset);
                   1250:              tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset);
                   1251:              offset += 2;
                   1252:              length -= 2;
                   1253:            }
                   1254:          else
                   1255:            break;
                   1256:        }
                   1257: 
                   1258:       for (i = 0; i < num_tmps; i++)
                   1259:        output_asm_insn (tmp_info[i].load, tmp_info[i].xops);
                   1260: 
                   1261:       for (i = 0; i < num_tmps; i++)
                   1262:        output_asm_insn (tmp_info[i].store, tmp_info[i].xops);
                   1263:     }
                   1264: 
                   1265:   if (length == 1)
                   1266:     {
                   1267:       xops[0] = adj_offsettable_operand (dest, offset);
                   1268:       xops[1] = adj_offsettable_operand (src, offset);
                   1269:       xops[2] = qi_tmp;
                   1270:       output_asm_insn (AS2(mov%B0,%1,%2), xops);
                   1271:       output_asm_insn (AS2(mov%B0,%2,%0), xops);
                   1272:     }
                   1273: 
                   1274:   return "";
                   1275: }
                   1276: 
1.1       root     1277: 
                   1278: int
                   1279: standard_80387_constant_p (x)
                   1280:      rtx x;
                   1281: {
                   1282: #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
                   1283:   REAL_VALUE_TYPE d;
                   1284:   jmp_buf handler;
                   1285:   int is0, is1;
                   1286: 
                   1287:   if (setjmp (handler))
                   1288:     return 0;
                   1289: 
                   1290:   set_float_handler (handler);
                   1291:   REAL_VALUE_FROM_CONST_DOUBLE (d, x);
                   1292:   is0 = REAL_VALUES_EQUAL (d, dconst0);
                   1293:   is1 = REAL_VALUES_EQUAL (d, dconst1);
                   1294:   set_float_handler (NULL_PTR);
                   1295: 
                   1296:   if (is0)
                   1297:     return 1;
                   1298: 
                   1299:   if (is1)
                   1300:     return 2;
                   1301: 
                   1302:   /* Note that on the 80387, other constants, such as pi,
                   1303:      are much slower to load as standard constants
                   1304:      than to load from doubles in memory!  */
                   1305: #endif
                   1306: 
                   1307:   return 0;
                   1308: }
                   1309: 
                   1310: char *
                   1311: output_move_const_single (operands)
                   1312:      rtx *operands;
                   1313: {
                   1314:   if (FP_REG_P (operands[0]))
                   1315:     {
                   1316:       int conval = standard_80387_constant_p (operands[1]);
                   1317: 
                   1318:       if (conval == 1)
                   1319:        return "fldz";
                   1320: 
                   1321:       if (conval == 2)
                   1322:        return "fld1";
                   1323:     }
                   1324:   if (GET_CODE (operands[1]) == CONST_DOUBLE)
                   1325:     {
1.1.1.2   root     1326:       REAL_VALUE_TYPE r; long l;
                   1327: 
                   1328:       if (GET_MODE (operands[1]) == XFmode)
                   1329:        abort ();
                   1330: 
                   1331:       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
                   1332:       REAL_VALUE_TO_TARGET_SINGLE (r, l);
                   1333:       operands[1] = GEN_INT (l);
1.1       root     1334:     }
                   1335:   return singlemove_string (operands);
                   1336: }
                   1337: 
                   1338: /* Returns 1 if OP is either a symbol reference or a sum of a symbol
                   1339:    reference and a constant.  */
                   1340: 
                   1341: int
                   1342: symbolic_operand (op, mode)
                   1343:      register rtx op;
                   1344:      enum machine_mode mode;
                   1345: {
                   1346:   switch (GET_CODE (op))
                   1347:     {
                   1348:     case SYMBOL_REF:
                   1349:     case LABEL_REF:
                   1350:       return 1;
                   1351:     case CONST:
                   1352:       op = XEXP (op, 0);
                   1353:       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
                   1354:               || GET_CODE (XEXP (op, 0)) == LABEL_REF)
                   1355:              && GET_CODE (XEXP (op, 1)) == CONST_INT);
                   1356:     default:
                   1357:       return 0;
                   1358:     }
                   1359: }
                   1360: 
                   1361: /* Test for a valid operand for a call instruction.
                   1362:    Don't allow the arg pointer register or virtual regs
                   1363:    since they may change into reg + const, which the patterns
                   1364:    can't handle yet.  */
                   1365: 
                   1366: int
                   1367: call_insn_operand (op, mode)
                   1368:      rtx op;
                   1369:      enum machine_mode mode;
                   1370: {
                   1371:   if (GET_CODE (op) == MEM
                   1372:       && ((CONSTANT_ADDRESS_P (XEXP (op, 0))
                   1373:           /* This makes a difference for PIC.  */
                   1374:           && general_operand (XEXP (op, 0), Pmode))
                   1375:          || (GET_CODE (XEXP (op, 0)) == REG
                   1376:              && XEXP (op, 0) != arg_pointer_rtx
                   1377:              && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
                   1378:                   && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
                   1379:     return 1;
                   1380:   return 0;
                   1381: }
                   1382: 
                   1383: /* Like call_insn_operand but allow (mem (symbol_ref ...))
                   1384:    even if pic.  */
                   1385: 
                   1386: int
                   1387: expander_call_insn_operand (op, mode)
                   1388:      rtx op;
                   1389:      enum machine_mode mode;
                   1390: {
                   1391:   if (GET_CODE (op) == MEM
                   1392:       && (CONSTANT_ADDRESS_P (XEXP (op, 0))
                   1393:          || (GET_CODE (XEXP (op, 0)) == REG
                   1394:              && XEXP (op, 0) != arg_pointer_rtx
                   1395:              && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
                   1396:                   && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
                   1397:     return 1;
                   1398:   return 0;
                   1399: }
1.1.1.4 ! root     1400: 
        !          1401: /* Return 1 if OP is a comparison operator that can use the condition code
        !          1402:    generated by an arithmetic operation. */
        !          1403: 
        !          1404: int
        !          1405: arithmetic_comparison_operator (op, mode)
        !          1406:      register rtx op;
        !          1407:      enum machine_mode mode;
        !          1408: {
        !          1409:   enum rtx_code code;
        !          1410: 
        !          1411:   if (mode != VOIDmode && mode != GET_MODE (op))
        !          1412:     return 0;
        !          1413:   code = GET_CODE (op);
        !          1414:   if (GET_RTX_CLASS (code) != '<')
        !          1415:     return 0;
        !          1416: 
        !          1417:   return (code != GT && code != LE);
        !          1418: }
1.1       root     1419: 
                   1420: /* Returns 1 if OP contains a symbol reference */
                   1421: 
                   1422: int
                   1423: symbolic_reference_mentioned_p (op)
                   1424:      rtx op;
                   1425: {
                   1426:   register char *fmt;
                   1427:   register int i;
                   1428: 
                   1429:   if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
                   1430:     return 1;
                   1431: 
                   1432:   fmt = GET_RTX_FORMAT (GET_CODE (op));
                   1433:   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
                   1434:     {
                   1435:       if (fmt[i] == 'E')
                   1436:        {
                   1437:          register int j;
                   1438: 
                   1439:          for (j = XVECLEN (op, i) - 1; j >= 0; j--)
                   1440:            if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
                   1441:              return 1;
                   1442:        }
                   1443:       else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
                   1444:        return 1;
                   1445:     }
                   1446: 
                   1447:   return 0;
                   1448: }
                   1449: 
                   1450: /* This function generates the assembly code for function entry.
                   1451:    FILE is an stdio stream to output the code to.
                   1452:    SIZE is an int: how many units of temporary storage to allocate. */
                   1453: 
                   1454: void
                   1455: function_prologue (file, size)
                   1456:      FILE *file;
                   1457:      int size;
                   1458: {
                   1459:   register int regno;
                   1460:   int limit;
                   1461:   rtx xops[4];
                   1462:   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
                   1463:                                  || current_function_uses_const_pool);
                   1464: 
                   1465:   xops[0] = stack_pointer_rtx;
                   1466:   xops[1] = frame_pointer_rtx;
                   1467:   xops[2] = GEN_INT (size);
                   1468:   if (frame_pointer_needed)
                   1469:     {
                   1470:       output_asm_insn ("push%L1 %1", xops);
                   1471:       output_asm_insn (AS2 (mov%L0,%0,%1), xops);
                   1472:     }
                   1473: 
                   1474:   if (size)
                   1475:     output_asm_insn (AS2 (sub%L0,%2,%0), xops);
                   1476: 
                   1477:   /* Note If use enter it is NOT reversed args.
                   1478:      This one is not reversed from intel!!
                   1479:      I think enter is slower.  Also sdb doesn't like it.
                   1480:      But if you want it the code is:
                   1481:      {
                   1482:      xops[3] = const0_rtx;
                   1483:      output_asm_insn ("enter %2,%3", xops);
                   1484:      }
                   1485:      */
                   1486:   limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
                   1487:   for (regno = limit - 1; regno >= 0; regno--)
                   1488:     if ((regs_ever_live[regno] && ! call_used_regs[regno])
                   1489:        || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
                   1490:       {
                   1491:        xops[0] = gen_rtx (REG, SImode, regno);
                   1492:        output_asm_insn ("push%L0 %0", xops);
                   1493:       }
                   1494: 
                   1495:   if (pic_reg_used)
                   1496:     {
                   1497:       xops[0] = pic_offset_table_rtx;
                   1498:       xops[1] = (rtx) gen_label_rtx ();
                   1499: 
                   1500:       output_asm_insn (AS1 (call,%P1), xops);
                   1501:       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));
                   1502:       output_asm_insn (AS1 (pop%L0,%0), xops);
                   1503:       output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops);
                   1504:     }
                   1505: }
                   1506: 
                   1507: /* Return 1 if it is appropriate to emit `ret' instructions in the
                   1508:    body of a function.  Do this only if the epilogue is simple, needing a
                   1509:    couple of insns.  Prior to reloading, we can't tell how many registers
                   1510:    must be saved, so return 0 then.
                   1511: 
                   1512:    If NON_SAVING_SETJMP is defined and true, then it is not possible
                   1513:    for the epilogue to be simple, so return 0.  This is a special case
                   1514:    since NON_SAVING_SETJMP will not cause regs_ever_live to change until
                   1515:    final, but jump_optimize may need to know sooner if a `return' is OK.  */
                   1516: 
                   1517: int
                   1518: simple_386_epilogue ()
                   1519: {
                   1520:   int regno;
                   1521:   int nregs = 0;
                   1522:   int reglimit = (frame_pointer_needed
                   1523:                  ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
                   1524:   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
                   1525:                                  || current_function_uses_const_pool);
                   1526: 
                   1527: #ifdef NON_SAVING_SETJMP
                   1528:   if (NON_SAVING_SETJMP && current_function_calls_setjmp)
                   1529:     return 0;
                   1530: #endif
                   1531: 
                   1532:   if (! reload_completed)
                   1533:     return 0;
                   1534: 
                   1535:   for (regno = reglimit - 1; regno >= 0; regno--)
                   1536:     if ((regs_ever_live[regno] && ! call_used_regs[regno])
                   1537:        || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
                   1538:       nregs++;
                   1539: 
                   1540:   return nregs == 0 || ! frame_pointer_needed;
                   1541: }
                   1542: 
1.1.1.3   root     1543: 
1.1       root     1544: /* This function generates the assembly code for function exit.
                   1545:    FILE is an stdio stream to output the code to.
                   1546:    SIZE is an int: how many units of temporary storage to deallocate. */
                   1547: 
                   1548: void
                   1549: function_epilogue (file, size)
                   1550:      FILE *file;
                   1551:      int size;
                   1552: {
                   1553:   register int regno;
                   1554:   register int nregs, limit;
                   1555:   int offset;
                   1556:   rtx xops[3];
                   1557:   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
                   1558:                                  || current_function_uses_const_pool);
                   1559: 
                   1560:   /* Compute the number of registers to pop */
                   1561: 
                   1562:   limit = (frame_pointer_needed
                   1563:           ? FRAME_POINTER_REGNUM
                   1564:           : STACK_POINTER_REGNUM);
                   1565: 
                   1566:   nregs = 0;
                   1567: 
                   1568:   for (regno = limit - 1; regno >= 0; regno--)
                   1569:     if ((regs_ever_live[regno] && ! call_used_regs[regno])
                   1570:        || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
                   1571:       nregs++;
                   1572: 
                   1573:   /* sp is often  unreliable so we must go off the frame pointer,
                   1574:    */
                   1575: 
                   1576:   /* In reality, we may not care if sp is unreliable, because we can
                   1577:      restore the register relative to the frame pointer.  In theory,
                   1578:      since each move is the same speed as a pop, and we don't need the
                   1579:      leal, this is faster.  For now restore multiple registers the old
                   1580:      way. */
                   1581: 
                   1582:   offset = -size - (nregs * UNITS_PER_WORD);
                   1583: 
                   1584:   xops[2] = stack_pointer_rtx;
                   1585: 
                   1586:   if (nregs > 1 || ! frame_pointer_needed)
                   1587:     {
                   1588:       if (frame_pointer_needed)
                   1589:        {
                   1590:          xops[0] = adj_offsettable_operand (AT_BP (Pmode), offset);
                   1591:          output_asm_insn (AS2 (lea%L2,%0,%2), xops);
                   1592:        }
                   1593: 
                   1594:       for (regno = 0; regno < limit; regno++)
                   1595:        if ((regs_ever_live[regno] && ! call_used_regs[regno])
                   1596:            || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
                   1597:          {
                   1598:            xops[0] = gen_rtx (REG, SImode, regno);
                   1599:            output_asm_insn ("pop%L0 %0", xops);
                   1600:          }
                   1601:     }
                   1602:   else
                   1603:     for (regno = 0; regno < limit; regno++)
                   1604:       if ((regs_ever_live[regno] && ! call_used_regs[regno])
                   1605:          || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
                   1606:        {
                   1607:          xops[0] = gen_rtx (REG, SImode, regno);
                   1608:          xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset);
                   1609:          output_asm_insn (AS2 (mov%L0,%1,%0), xops);
                   1610:          offset += 4;
                   1611:        }
                   1612: 
                   1613:   if (frame_pointer_needed)
                   1614:     {
                   1615:       /* On i486, mov & pop is faster than "leave". */
                   1616: 
1.1.1.3   root     1617:       if (!TARGET_386)
1.1       root     1618:        {
                   1619:          xops[0] = frame_pointer_rtx;
                   1620:          output_asm_insn (AS2 (mov%L2,%0,%2), xops);
                   1621:          output_asm_insn ("pop%L0 %0", xops);
                   1622:        }
                   1623:       else
                   1624:        output_asm_insn ("leave", xops);
                   1625:     }
                   1626:   else if (size)
                   1627:     {
                   1628:       /* If there is no frame pointer, we must still release the frame. */
                   1629: 
                   1630:       xops[0] = GEN_INT (size);
                   1631:       output_asm_insn (AS2 (add%L2,%0,%2), xops);
                   1632:     }
                   1633: 
                   1634:   if (current_function_pops_args && current_function_args_size)
                   1635:     {
                   1636:       xops[1] = GEN_INT (current_function_pops_args);
                   1637: 
                   1638:       /* i386 can only pop 32K bytes (maybe 64K?  Is it signed?).  If
                   1639:         asked to pop more, pop return address, do explicit add, and jump
                   1640:         indirectly to the caller. */
                   1641: 
                   1642:       if (current_function_pops_args >= 32768)
                   1643:        {
                   1644:          /* ??? Which register to use here? */
                   1645:          xops[0] = gen_rtx (REG, SImode, 2);
                   1646:          output_asm_insn ("pop%L0 %0", xops);
                   1647:          output_asm_insn (AS2 (add%L2,%1,%2), xops);
                   1648:          output_asm_insn ("jmp %*%0", xops);
                   1649:        }
                   1650:       else
                   1651:          output_asm_insn ("ret %1", xops);
                   1652:     }
                   1653:   else
                   1654:     output_asm_insn ("ret", xops);
                   1655: }
1.1.1.3   root     1656: 
1.1       root     1657: 
1.1.1.3   root     1658: /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
                   1659:    that is a valid memory address for an instruction.
                   1660:    The MODE argument is the machine mode for the MEM expression
                   1661:    that wants to use this address.
                   1662: 
                   1663:    On x86, legitimate addresses are:
                   1664:        base                            movl (base),reg
                   1665:        displacement                    movl disp,reg
                   1666:        base + displacement             movl disp(base),reg
                   1667:        index + base                    movl (base,index),reg
                   1668:        (index + base) + displacement   movl disp(base,index),reg
                   1669:        index*scale                     movl (,index,scale),reg
                   1670:        index*scale + disp              movl disp(,index,scale),reg
                   1671:        index*scale + base              movl (base,index,scale),reg
                   1672:        (index*scale + base) + disp     movl disp(base,index,scale),reg
                   1673: 
                   1674:        In each case, scale can be 1, 2, 4, 8.  */
                   1675: 
                   1676: /* This is exactly the same as print_operand_addr, except that
                   1677:    it recognizes addresses instead of printing them.
                   1678: 
                   1679:    It only recognizes address in canonical form.  LEGITIMIZE_ADDRESS should
                   1680:    convert common non-canonical forms to canonical form so that they will
                   1681:    be recognized.  */
                   1682: 
                   1683: #define ADDR_INVALID(msg,insn)                                         \
                   1684: do {                                                                   \
                   1685:   if (TARGET_DEBUG_ADDR)                                               \
                   1686:     {                                                                  \
                   1687:       fprintf (stderr, msg);                                           \
                   1688:       debug_rtx (insn);                                                        \
                   1689:     }                                                                  \
                   1690: } while (0)
1.1       root     1691: 
1.1.1.3   root     1692: int
                   1693: legitimate_address_p (mode, addr, strict)
                   1694:      enum machine_mode mode;
                   1695:      register rtx addr;
                   1696:      int strict;
                   1697: {
                   1698:   rtx base  = NULL_RTX;
                   1699:   rtx indx  = NULL_RTX;
                   1700:   rtx scale = NULL_RTX;
                   1701:   rtx disp  = NULL_RTX;
                   1702: 
                   1703:   if (TARGET_DEBUG_ADDR)
                   1704:     {
                   1705:       fprintf (stderr,
                   1706:               "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
                   1707:               GET_MODE_NAME (mode), strict);
                   1708: 
                   1709:       debug_rtx (addr);
                   1710:     }
                   1711: 
                   1712:   if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
                   1713:       base = addr;                             /* base reg */
                   1714: 
                   1715:   else if (GET_CODE (addr) == PLUS)
                   1716:     {
                   1717:       rtx op0 = XEXP (addr, 0);
                   1718:       rtx op1 = XEXP (addr, 1);
                   1719:       enum rtx_code code0 = GET_CODE (op0);
                   1720:       enum rtx_code code1 = GET_CODE (op1);
                   1721: 
                   1722:       if (code0 == REG || code0 == SUBREG)
                   1723:        {
                   1724:          if (code1 == REG || code1 == SUBREG)
                   1725:            {
                   1726:              indx = op0;                       /* index + base */
                   1727:              base = op1;
                   1728:            }
                   1729: 
                   1730:          else
                   1731:            {
                   1732:              base = op0;                       /* base + displacement */
                   1733:              disp = op1;
                   1734:            }
                   1735:        }
                   1736: 
                   1737:       else if (code0 == MULT)
                   1738:        {
                   1739:          indx  = XEXP (op0, 0);
                   1740:          scale = XEXP (op0, 1);
                   1741: 
                   1742:          if (code1 == REG || code1 == SUBREG)
                   1743:            base = op1;                         /* index*scale + base */
                   1744: 
                   1745:          else
                   1746:            disp = op1;                         /* index*scale + disp */
                   1747:        }
                   1748: 
                   1749:       else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)
                   1750:        {
                   1751:          indx  = XEXP (XEXP (op0, 0), 0);      /* index*scale + base + disp */
                   1752:          scale = XEXP (XEXP (op0, 0), 1);
                   1753:          base  = XEXP (op0, 1);
                   1754:          disp  = op1;
                   1755:        }
                   1756: 
                   1757:       else if (code0 == PLUS)
                   1758:        {
                   1759:          indx = XEXP (op0, 0);                 /* index + base + disp */
                   1760:          base = XEXP (op0, 1);
                   1761:          disp = op1;
                   1762:        }
                   1763: 
                   1764:       else
                   1765:        {
                   1766:          ADDR_INVALID ("PLUS subcode is not valid.\n", op0);
                   1767:          return FALSE;
                   1768:        }
                   1769:     }
                   1770: 
                   1771:   else if (GET_CODE (addr) == MULT)
                   1772:     {
                   1773:       indx  = XEXP (addr, 0);                  /* index*scale */
                   1774:       scale = XEXP (addr, 1);
                   1775:     }
                   1776: 
                   1777:   else
                   1778:     disp = addr;                               /* displacement */
                   1779: 
                   1780:   /* Allow arg pointer and stack pointer as index if there is not scaling */
                   1781:   if (base && indx && !scale
                   1782:       && (indx == arg_pointer_rtx || indx == stack_pointer_rtx))
                   1783:     {
                   1784:       rtx tmp = base;
                   1785:       base = indx;
                   1786:       indx = tmp;
                   1787:     }
                   1788: 
                   1789:   /* Validate base register */
                   1790:   /* Don't allow SUBREG's here, it can lead to spill failures when the base
                   1791:      is one word out of a two word structure, which is represented internally
                   1792:      as a DImode int.  */
                   1793:   if (base)
                   1794:     {
                   1795:       if (GET_CODE (base) != REG)
                   1796:        {
                   1797:          ADDR_INVALID ("Base is not a register.\n", base);
                   1798:          return FALSE;
                   1799:        }
                   1800: 
                   1801:       if ((strict && !REG_OK_FOR_BASE_STRICT_P (base))
                   1802:          || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base)))
                   1803:        {
                   1804:          ADDR_INVALID ("Base is not valid.\n", base);
                   1805:          return FALSE;
                   1806:        }
                   1807:     }
                   1808: 
                   1809:   /* Validate index register */
                   1810:   /* Don't allow SUBREG's here, it can lead to spill failures when the index
                   1811:      is one word out of a two word structure, which is represented internally
                   1812:      as a DImode int.  */
                   1813:   if (indx)
                   1814:     {
                   1815:       if (GET_CODE (indx) != REG)
                   1816:        {
                   1817:          ADDR_INVALID ("Index is not a register.\n", indx);
                   1818:          return FALSE;
                   1819:        }
                   1820: 
                   1821:       if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx))
                   1822:          || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx)))
                   1823:        {
                   1824:          ADDR_INVALID ("Index is not valid.\n", indx);
                   1825:          return FALSE;
                   1826:        }
                   1827:     }
                   1828:   else if (scale)
1.1.1.4 ! root     1829:     abort ();                                  /* scale w/o index invalid */
1.1.1.3   root     1830: 
                   1831:   /* Validate scale factor */
                   1832:   if (scale)
                   1833:     {
                   1834:       HOST_WIDE_INT value;
                   1835: 
                   1836:       if (GET_CODE (scale) != CONST_INT)
                   1837:        {
                   1838:          ADDR_INVALID ("Scale is not valid.\n", scale);
                   1839:          return FALSE;
                   1840:        }
                   1841: 
                   1842:       value = INTVAL (scale);
                   1843:       if (value != 1 && value != 2 && value != 4 && value != 8)
                   1844:        {
                   1845:          ADDR_INVALID ("Scale is not a good multiplier.\n", scale);
                   1846:          return FALSE;
                   1847:        }
                   1848:     }
                   1849: 
                   1850:   /* Validate displacement */
                   1851:   if (disp)
                   1852:     {
                   1853:       if (!CONSTANT_ADDRESS_P (disp))
                   1854:        {
                   1855:          ADDR_INVALID ("Displacement is not valid.\n", disp);
                   1856:          return FALSE;
                   1857:        }
                   1858: 
                   1859:       if (GET_CODE (disp) == CONST_DOUBLE)
                   1860:        {
                   1861:          ADDR_INVALID ("Displacement is a const_double.\n", disp);
                   1862:          return FALSE;
                   1863:        }
                   1864: 
                   1865:       if (flag_pic && SYMBOLIC_CONST (disp) && base != pic_offset_table_rtx
                   1866:          && (indx != pic_offset_table_rtx || scale != NULL_RTX))
                   1867:        {
                   1868:          ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
                   1869:          return FALSE;
                   1870:        }
                   1871: 
                   1872:       if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
                   1873:          && (base != NULL_RTX || indx != NULL_RTX))
                   1874:        {
                   1875:          ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp);
                   1876:          return FALSE;
                   1877:        }
                   1878:     }
                   1879: 
                   1880:   if (TARGET_DEBUG_ADDR)
                   1881:     fprintf (stderr, "Address is valid.\n");
                   1882: 
                   1883:   /* Everything looks valid, return true */
                   1884:   return TRUE;
                   1885: }
                   1886: 
                   1887: 
                   1888: /* Return a legitimate reference for ORIG (an address) using the
                   1889:    register REG.  If REG is 0, a new pseudo is generated.
                   1890: 
                   1891:    There are three types of references that must be handled:
                   1892: 
                   1893:    1. Global data references must load the address from the GOT, via
                   1894:       the PIC reg.  An insn is emitted to do this load, and the reg is
                   1895:       returned.
                   1896: 
                   1897:    2. Static data references must compute the address as an offset
                   1898:       from the GOT, whose base is in the PIC reg.  An insn is emitted to
                   1899:       compute the address into a reg, and the reg is returned.  Static
                   1900:       data objects have SYMBOL_REF_FLAG set to differentiate them from
                   1901:       global data objects.
                   1902: 
                   1903:    3. Constant pool addresses must be handled special.  They are
                   1904:       considered legitimate addresses, but only if not used with regs.
                   1905:       When printed, the output routines know to print the reference with the
                   1906:       PIC reg, even though the PIC reg doesn't appear in the RTL.
                   1907: 
                   1908:    GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
                   1909:    reg also appears in the address (except for constant pool references,
                   1910:    noted above).
                   1911: 
                   1912:    "switch" statements also require special handling when generating
                   1913:    PIC code.  See comments by the `casesi' insn in i386.md for details.  */
                   1914: 
                   1915: rtx
                   1916: legitimize_pic_address (orig, reg)
                   1917:      rtx orig;
                   1918:      rtx reg;
                   1919: {
                   1920:   rtx addr = orig;
                   1921:   rtx new = orig;
                   1922: 
                   1923:   if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
                   1924:     {
                   1925:       if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
                   1926:        reg = new = orig;
                   1927:       else
                   1928:        {
                   1929:          if (reg == 0)
                   1930:            reg = gen_reg_rtx (Pmode);
                   1931: 
                   1932:          if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
                   1933:              || GET_CODE (addr) == LABEL_REF)
                   1934:            new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
                   1935:          else
                   1936:            new = gen_rtx (MEM, Pmode,
                   1937:                           gen_rtx (PLUS, Pmode,
                   1938:                                    pic_offset_table_rtx, orig));
                   1939: 
                   1940:          emit_move_insn (reg, new);
                   1941:        }
                   1942:       current_function_uses_pic_offset_table = 1;
                   1943:       return reg;
                   1944:     }
                   1945:   else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
                   1946:     {
                   1947:       rtx base;
                   1948: 
                   1949:       if (GET_CODE (addr) == CONST)
                   1950:        {
                   1951:          addr = XEXP (addr, 0);
                   1952:          if (GET_CODE (addr) != PLUS)
                   1953:            abort ();
                   1954:        }
                   1955: 
                   1956:       if (XEXP (addr, 0) == pic_offset_table_rtx)
                   1957:        return orig;
                   1958: 
                   1959:       if (reg == 0)
                   1960:        reg = gen_reg_rtx (Pmode);
                   1961: 
                   1962:       base = legitimize_pic_address (XEXP (addr, 0), reg);
                   1963:       addr = legitimize_pic_address (XEXP (addr, 1),
                   1964:                                     base == reg ? NULL_RTX : reg);
                   1965: 
                   1966:       if (GET_CODE (addr) == CONST_INT)
                   1967:        return plus_constant (base, INTVAL (addr));
                   1968: 
                   1969:       if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
                   1970:        {
                   1971:          base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
                   1972:          addr = XEXP (addr, 1);
                   1973:        }
                   1974:        return gen_rtx (PLUS, Pmode, base, addr);
                   1975:     }
                   1976:   return new;
                   1977: }
                   1978: 
                   1979: 
                   1980: /* Emit insns to move operands[1] into operands[0].  */
                   1981: 
                   1982: void
                   1983: emit_pic_move (operands, mode)
                   1984:      rtx *operands;
                   1985:      enum machine_mode mode;
                   1986: {
                   1987:   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
                   1988: 
                   1989:   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
                   1990:     operands[1] = (rtx) force_reg (SImode, operands[1]);
                   1991:   else
                   1992:     operands[1] = legitimize_pic_address (operands[1], temp);
                   1993: }
                   1994: 
                   1995: 
                   1996: /* Try machine-dependent ways of modifying an illegitimate address
                   1997:    to be legitimate.  If we find one, return the new, valid address.
                   1998:    This macro is used in only one place: `memory_address' in explow.c.
                   1999: 
                   2000:    OLDX is the address as it was before break_out_memory_refs was called.
                   2001:    In some cases it is useful to look at this to decide what needs to be done.
                   2002: 
                   2003:    MODE and WIN are passed so that this macro can use
                   2004:    GO_IF_LEGITIMATE_ADDRESS.
                   2005: 
                   2006:    It is always safe for this macro to do nothing.  It exists to recognize
                   2007:    opportunities to optimize the output.
                   2008: 
                   2009:    For the 80386, we handle X+REG by loading X into a register R and
                   2010:    using R+REG.  R will go in a general reg and indexing will be used.
                   2011:    However, if REG is a broken-out memory address or multiplication,
                   2012:    nothing needs to be done because REG can certainly go in a general reg.
                   2013: 
                   2014:    When -fpic is used, special handling is needed for symbolic references.
                   2015:    See comments by legitimize_pic_address in i386.c for details.  */
                   2016: 
                   2017: rtx
                   2018: legitimize_address (x, oldx, mode)
                   2019:      register rtx x;
                   2020:      register rtx oldx;
                   2021:      enum machine_mode mode;
                   2022: {
                   2023:   int changed = 0;
                   2024:   unsigned log;
                   2025: 
                   2026:   if (TARGET_DEBUG_ADDR)
                   2027:     {
                   2028:       fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode));
                   2029:       debug_rtx (x);
                   2030:     }
                   2031: 
                   2032:   if (flag_pic && SYMBOLIC_CONST (x))
                   2033:     return legitimize_pic_address (x, 0);
                   2034: 
                   2035:   /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
                   2036:   if (GET_CODE (x) == ASHIFT
                   2037:       && GET_CODE (XEXP (x, 1)) == CONST_INT
                   2038:       && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
                   2039:     {
                   2040:       changed = 1;
                   2041:       x = gen_rtx (MULT, Pmode,
                   2042:                   force_reg (Pmode, XEXP (x, 0)),
                   2043:                   GEN_INT (1 << log));
                   2044:     }
                   2045: 
                   2046:   if (GET_CODE (x) == PLUS)
                   2047:     {
                   2048:       /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
                   2049:       if (GET_CODE (XEXP (x, 0)) == ASHIFT
                   2050:          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
                   2051:          && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4)
                   2052:        {
                   2053:          changed = 1;
                   2054:          XEXP (x, 0) = gen_rtx (MULT, Pmode,
                   2055:                                 force_reg (Pmode, XEXP (XEXP (x, 0), 0)),
                   2056:                                 GEN_INT (1 << log));
                   2057:        }
                   2058: 
                   2059:       if (GET_CODE (XEXP (x, 1)) == ASHIFT
                   2060:          && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
                   2061:          && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4)
                   2062:        {
                   2063:          changed = 1;
                   2064:          XEXP (x, 1) = gen_rtx (MULT, Pmode,
                   2065:                                 force_reg (Pmode, XEXP (XEXP (x, 1), 0)),
                   2066:                                 GEN_INT (1 << log));
                   2067:        }
                   2068: 
                   2069:       /* Put multiply first if it isn't already */
                   2070:       if (GET_CODE (XEXP (x, 1)) == MULT)
                   2071:        {
                   2072:          rtx tmp = XEXP (x, 0);
                   2073:          XEXP (x, 0) = XEXP (x, 1);
                   2074:          XEXP (x, 1) = tmp;
                   2075:          changed = 1;
                   2076:        }
                   2077: 
                   2078:       /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))
                   2079:         into (plus (plus (mult (reg) (const)) (reg)) (const)).  This can be
                   2080:         created by virtual register instantiation, register elimination, and
                   2081:         similar optimizations.  */
                   2082:       if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)
                   2083:        {
                   2084:          changed = 1;
                   2085:          x = gen_rtx (PLUS, Pmode,
                   2086:                       gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)),
                   2087:                       XEXP (XEXP (x, 1), 1));
                   2088:        }
                   2089: 
                   2090:       /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)
                   2091:         into (plus (plus (mult (reg) (const)) (reg)) (const)).  */
                   2092:       else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
                   2093:               && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
                   2094:               && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
                   2095:               && CONSTANT_P (XEXP (x, 1)))
                   2096:        {
                   2097:          rtx constant, other;
                   2098: 
                   2099:          if (GET_CODE (XEXP (x, 1)) == CONST_INT)
                   2100:            {
                   2101:              constant = XEXP (x, 1);
                   2102:              other = XEXP (XEXP (XEXP (x, 0), 1), 1);
                   2103:            }
                   2104:          else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
                   2105:            {
                   2106:              constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
                   2107:              other = XEXP (x, 1);
                   2108:            }
                   2109:          else
                   2110:            constant = 0;
                   2111: 
                   2112:          if (constant)
                   2113:            {
                   2114:              changed = 1;
                   2115:              x = gen_rtx (PLUS, Pmode,
                   2116:                           gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),
                   2117:                                    XEXP (XEXP (XEXP (x, 0), 1), 0)),
                   2118:                           plus_constant (other, INTVAL (constant)));
                   2119:            }
                   2120:        }
                   2121: 
                   2122:       if (changed && legitimate_address_p (mode, x, FALSE))
                   2123:        return x;
                   2124: 
                   2125:       if (GET_CODE (XEXP (x, 0)) == MULT)
                   2126:        {
                   2127:          changed = 1;
                   2128:          XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
                   2129:        }
                   2130: 
                   2131:       if (GET_CODE (XEXP (x, 1)) == MULT)
                   2132:        {
                   2133:          changed = 1;
                   2134:          XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
                   2135:        }
                   2136: 
                   2137:       if (changed
                   2138:          && GET_CODE (XEXP (x, 1)) == REG
                   2139:          && GET_CODE (XEXP (x, 0)) == REG)
                   2140:        return x;
                   2141: 
                   2142:       if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))
                   2143:        {
                   2144:          changed = 1;
                   2145:          x = legitimize_pic_address (x, 0);
                   2146:        }
                   2147: 
                   2148:       if (changed && legitimate_address_p (mode, x, FALSE))
                   2149:        return x;
                   2150: 
                   2151:       if (GET_CODE (XEXP (x, 0)) == REG)
                   2152:        {
                   2153:          register rtx temp = gen_reg_rtx (Pmode);
                   2154:          register rtx val  = force_operand (XEXP (x, 1), temp);
                   2155:          if (val != temp)
                   2156:            emit_move_insn (temp, val);
                   2157: 
                   2158:          XEXP (x, 1) = temp;
                   2159:          return x;
                   2160:        }
                   2161: 
                   2162:       else if (GET_CODE (XEXP (x, 1)) == REG)
                   2163:        {
                   2164:          register rtx temp = gen_reg_rtx (Pmode);
                   2165:          register rtx val  = force_operand (XEXP (x, 0), temp);
                   2166:          if (val != temp)
                   2167:            emit_move_insn (temp, val);
                   2168: 
                   2169:          XEXP (x, 0) = temp;
                   2170:          return x;
                   2171:        }
                   2172:     }
                   2173: 
                   2174:   return x;
                   2175: }
                   2176: 
                   2177: 
                   2178: /* Print an integer constant expression in assembler syntax.  Addition
                   2179:    and subtraction are the only arithmetic that may appear in these
                   2180:    expressions.  FILE is the stdio stream to write to, X is the rtx, and
                   2181:    CODE is the operand print code from the output string.  */
                   2182: 
                   2183: static void
                   2184: output_pic_addr_const (file, x, code)
                   2185:      FILE *file;
                   2186:      rtx x;
                   2187:      int code;
                   2188: {
                   2189:   char buf[256];
1.1       root     2190: 
                   2191:   switch (GET_CODE (x))
                   2192:     {
                   2193:     case PC:
                   2194:       if (flag_pic)
                   2195:        putc ('.', file);
                   2196:       else
                   2197:        abort ();
                   2198:       break;
                   2199: 
                   2200:     case SYMBOL_REF:
                   2201:     case LABEL_REF:
                   2202:       if (GET_CODE (x) == SYMBOL_REF)
                   2203:        assemble_name (file, XSTR (x, 0));
                   2204:       else
                   2205:        {
                   2206:          ASM_GENERATE_INTERNAL_LABEL (buf, "L",
                   2207:                                       CODE_LABEL_NUMBER (XEXP (x, 0)));
                   2208:          assemble_name (asm_out_file, buf);
                   2209:        }
                   2210: 
                   2211:       if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
                   2212:        fprintf (file, "@GOTOFF(%%ebx)");
                   2213:       else if (code == 'P')
                   2214:        fprintf (file, "@PLT");
1.1.1.3   root     2215:       else if (GET_CODE (x) == LABEL_REF)
                   2216:        fprintf (file, "@GOTOFF");
                   2217:       else if (! SYMBOL_REF_FLAG (x))
1.1       root     2218:        fprintf (file, "@GOT");
                   2219:       else
                   2220:        fprintf (file, "@GOTOFF");
                   2221: 
                   2222:       break;
                   2223: 
                   2224:     case CODE_LABEL:
                   2225:       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
                   2226:       assemble_name (asm_out_file, buf);
                   2227:       break;
                   2228: 
                   2229:     case CONST_INT:
                   2230:       fprintf (file, "%d", INTVAL (x));
                   2231:       break;
                   2232: 
                   2233:     case CONST:
                   2234:       /* This used to output parentheses around the expression,
                   2235:         but that does not work on the 386 (either ATT or BSD assembler).  */
                   2236:       output_pic_addr_const (file, XEXP (x, 0), code);
                   2237:       break;
                   2238: 
                   2239:     case CONST_DOUBLE:
                   2240:       if (GET_MODE (x) == VOIDmode)
                   2241:        {
                   2242:          /* We can use %d if the number is <32 bits and positive.  */
                   2243:          if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
                   2244:            fprintf (file, "0x%x%08x",
                   2245:                     CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
                   2246:          else
                   2247:            fprintf (file, "%d", CONST_DOUBLE_LOW (x));
                   2248:        }
                   2249:       else
                   2250:        /* We can't handle floating point constants;
                   2251:           PRINT_OPERAND must handle them.  */
                   2252:        output_operand_lossage ("floating constant misused");
                   2253:       break;
                   2254: 
                   2255:     case PLUS:
                   2256:       /* Some assemblers need integer constants to appear last (eg masm).  */
                   2257:       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
                   2258:        {
                   2259:          output_pic_addr_const (file, XEXP (x, 1), code);
                   2260:          if (INTVAL (XEXP (x, 0)) >= 0)
                   2261:            fprintf (file, "+");
                   2262:          output_pic_addr_const (file, XEXP (x, 0), code);
                   2263:        }
                   2264:       else
                   2265:        {
                   2266:          output_pic_addr_const (file, XEXP (x, 0), code);
                   2267:          if (INTVAL (XEXP (x, 1)) >= 0)
                   2268:            fprintf (file, "+");
                   2269:          output_pic_addr_const (file, XEXP (x, 1), code);
                   2270:        }
                   2271:       break;
                   2272: 
                   2273:     case MINUS:
                   2274:       output_pic_addr_const (file, XEXP (x, 0), code);
                   2275:       fprintf (file, "-");
                   2276:       output_pic_addr_const (file, XEXP (x, 1), code);
                   2277:       break;
                   2278: 
                   2279:     default:
                   2280:       output_operand_lossage ("invalid expression as operand");
                   2281:     }
                   2282: }
                   2283: 
                   2284: /* Meaning of CODE:
                   2285:    f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
                   2286:    D,L,W,B,Q,S -- print the opcode suffix for specified size of operand.
                   2287:    R -- print the prefix for register names.
                   2288:    z -- print the opcode suffix for the size of the current operand.
                   2289:    * -- print a star (in certain assembler syntax)
                   2290:    w -- print the operand as if it's a "word" (HImode) even if it isn't.
                   2291:    c -- don't print special prefixes before constant operands.
1.1.1.4 ! root     2292:    J -- print the appropriate jump operand.
1.1       root     2293: */
                   2294: 
                   2295: void
                   2296: print_operand (file, x, code)
                   2297:      FILE *file;
                   2298:      rtx x;
                   2299:      int code;
                   2300: {
                   2301:   if (code)
                   2302:     {
                   2303:       switch (code)
                   2304:        {
                   2305:        case '*':
                   2306:          if (USE_STAR)
                   2307:            putc ('*', file);
                   2308:          return;
                   2309: 
                   2310:        case 'L':
                   2311:          PUT_OP_SIZE (code, 'l', file);
                   2312:          return;
                   2313: 
                   2314:        case 'W':
                   2315:          PUT_OP_SIZE (code, 'w', file);
                   2316:          return;
                   2317: 
                   2318:        case 'B':
                   2319:          PUT_OP_SIZE (code, 'b', file);
                   2320:          return;
                   2321: 
                   2322:        case 'Q':
                   2323:          PUT_OP_SIZE (code, 'l', file);
                   2324:          return;
                   2325: 
                   2326:        case 'S':
                   2327:          PUT_OP_SIZE (code, 's', file);
                   2328:          return;
                   2329: 
1.1.1.2   root     2330:        case 'T':
                   2331:          PUT_OP_SIZE (code, 't', file);
                   2332:          return;
                   2333: 
1.1       root     2334:        case 'z':
                   2335:          /* 387 opcodes don't get size suffixes if the operands are
                   2336:             registers. */
                   2337: 
                   2338:          if (STACK_REG_P (x))
                   2339:            return;
                   2340: 
                   2341:          /* this is the size of op from size of operand */
                   2342:          switch (GET_MODE_SIZE (GET_MODE (x)))
                   2343:            {
                   2344:            case 1:
                   2345:              PUT_OP_SIZE ('B', 'b', file);
                   2346:              return;
                   2347: 
                   2348:            case 2:
                   2349:              PUT_OP_SIZE ('W', 'w', file);
                   2350:              return;
                   2351: 
                   2352:            case 4:
                   2353:              if (GET_MODE (x) == SFmode)
                   2354:                {
                   2355:                  PUT_OP_SIZE ('S', 's', file);
                   2356:                  return;
                   2357:                }
                   2358:              else
                   2359:                PUT_OP_SIZE ('L', 'l', file);
                   2360:              return;
                   2361: 
1.1.1.2   root     2362:            case 12:
                   2363:                  PUT_OP_SIZE ('T', 't', file);
                   2364:                  return;
                   2365: 
1.1       root     2366:            case 8:
                   2367:              if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
                   2368:                {
                   2369: #ifdef GAS_MNEMONICS
                   2370:                  PUT_OP_SIZE ('Q', 'q', file);
                   2371:                  return;
                   2372: #else
                   2373:                  PUT_OP_SIZE ('Q', 'l', file); /* Fall through */
                   2374: #endif
                   2375:                }
                   2376: 
                   2377:              PUT_OP_SIZE ('Q', 'l', file);
                   2378:              return;
                   2379:            }
                   2380: 
                   2381:        case 'b':
                   2382:        case 'w':
                   2383:        case 'k':
                   2384:        case 'h':
                   2385:        case 'y':
                   2386:        case 'P':
                   2387:          break;
                   2388: 
1.1.1.4 ! root     2389:        case 'J':
        !          2390:          switch (GET_CODE (x))
        !          2391:            {
        !          2392:              /* These conditions are appropriate for testing the result
        !          2393:                 of an arithmetic operation, not for a compare operation.
        !          2394:                 Cases GE, LT assume CC_NO_OVERFLOW true. All cases assume
        !          2395:                 CC_Z_IN_NOT_C false and not floating point.  */
        !          2396:            case NE:  fputs ("jne", file); return;
        !          2397:            case EQ:  fputs ("je",  file); return;
        !          2398:            case GE:  fputs ("jns", file); return;
        !          2399:            case LT:  fputs ("js",  file); return;
        !          2400:            case GEU: fputs ("jmp", file); return;
        !          2401:            case GTU: fputs ("jne",  file); return;
        !          2402:            case LEU: fputs ("je", file); return;
        !          2403:            case LTU: fputs ("#branch never",  file); return;
        !          2404: 
        !          2405:            /* no matching branches for GT nor LE */
        !          2406:            }
        !          2407:          abort ();
        !          2408: 
1.1       root     2409:        default:
                   2410:          {
                   2411:            char str[50];
                   2412: 
                   2413:            sprintf (str, "invalid operand code `%c'", code);
                   2414:            output_operand_lossage (str);
                   2415:          }
                   2416:        }
                   2417:     }
                   2418:   if (GET_CODE (x) == REG)
                   2419:     {
                   2420:       PRINT_REG (x, code, file);
                   2421:     }
                   2422:   else if (GET_CODE (x) == MEM)
                   2423:     {
                   2424:       PRINT_PTR (x, file);
                   2425:       if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
                   2426:        {
                   2427:          if (flag_pic)
                   2428:            output_pic_addr_const (file, XEXP (x, 0), code);
                   2429:          else
                   2430:            output_addr_const (file, XEXP (x, 0));
                   2431:        }
                   2432:       else
                   2433:        output_address (XEXP (x, 0));
                   2434:     }
                   2435:   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
                   2436:     {
1.1.1.2   root     2437:       REAL_VALUE_TYPE r; long l;
                   2438:       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
                   2439:       REAL_VALUE_TO_TARGET_SINGLE (r, l);
1.1       root     2440:       PRINT_IMMED_PREFIX (file);
1.1.1.2   root     2441:       fprintf (file, "0x%x", l);
1.1       root     2442:     }
1.1.1.2   root     2443:  /* These float cases don't actually occur as immediate operands. */
                   2444:  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
1.1       root     2445:     {
1.1.1.2   root     2446:       REAL_VALUE_TYPE r; char dstr[30];
                   2447:       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
                   2448:       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
                   2449:       fprintf (file, "%s", dstr);
                   2450:     }
                   2451:   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode)
                   2452:     {
                   2453:       REAL_VALUE_TYPE r; char dstr[30];
                   2454:       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
                   2455:       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
                   2456:       fprintf (file, "%s", dstr);
1.1       root     2457:     }
                   2458:   else 
                   2459:     {
                   2460:       if (code != 'P')
                   2461:        {
                   2462:          if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
                   2463:            PRINT_IMMED_PREFIX (file);
                   2464:          else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
                   2465:                   || GET_CODE (x) == LABEL_REF)
                   2466:            PRINT_OFFSET_PREFIX (file);
                   2467:        }
                   2468:       if (flag_pic)
                   2469:        output_pic_addr_const (file, x, code);
                   2470:       else
                   2471:        output_addr_const (file, x);
                   2472:     }
                   2473: }
                   2474: 
                   2475: /* Print a memory operand whose address is ADDR.  */
                   2476: 
                   2477: void
                   2478: print_operand_address (file, addr)
                   2479:      FILE *file;
                   2480:      register rtx addr;
                   2481: {
                   2482:   register rtx reg1, reg2, breg, ireg;
                   2483:   rtx offset;
                   2484: 
                   2485:   switch (GET_CODE (addr))
                   2486:     {
                   2487:     case REG:
                   2488:       ADDR_BEG (file);
                   2489:       fprintf (file, "%se", RP);
                   2490:       fputs (hi_reg_name[REGNO (addr)], file);
                   2491:       ADDR_END (file);
                   2492:       break;
                   2493: 
                   2494:     case PLUS:
                   2495:       reg1 = 0;
                   2496:       reg2 = 0;
                   2497:       ireg = 0;
                   2498:       breg = 0;
                   2499:       offset = 0;
                   2500:       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
                   2501:        {
                   2502:          offset = XEXP (addr, 0);
                   2503:          addr = XEXP (addr, 1);
                   2504:        }
                   2505:       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
                   2506:        {
                   2507:          offset = XEXP (addr, 1);
                   2508:          addr = XEXP (addr, 0);
                   2509:        }
                   2510:       if (GET_CODE (addr) != PLUS) ;
                   2511:       else if (GET_CODE (XEXP (addr, 0)) == MULT)
                   2512:        {
                   2513:          reg1 = XEXP (addr, 0);
                   2514:          addr = XEXP (addr, 1);
                   2515:        }
                   2516:       else if (GET_CODE (XEXP (addr, 1)) == MULT)
                   2517:        {
                   2518:          reg1 = XEXP (addr, 1);
                   2519:          addr = XEXP (addr, 0);
                   2520:        }
                   2521:       else if (GET_CODE (XEXP (addr, 0)) == REG)
                   2522:        {
                   2523:          reg1 = XEXP (addr, 0);
                   2524:          addr = XEXP (addr, 1);
                   2525:        }
                   2526:       else if (GET_CODE (XEXP (addr, 1)) == REG)
                   2527:        {
                   2528:          reg1 = XEXP (addr, 1);
                   2529:          addr = XEXP (addr, 0);
                   2530:        }
                   2531:       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
                   2532:        {
                   2533:          if (reg1 == 0) reg1 = addr;
                   2534:          else reg2 = addr;
                   2535:          addr = 0;
                   2536:        }
                   2537:       if (offset != 0)
                   2538:        {
                   2539:          if (addr != 0) abort ();
                   2540:          addr = offset;
                   2541:        }
                   2542:       if ((reg1 && GET_CODE (reg1) == MULT)
                   2543:          || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
                   2544:        {
                   2545:          breg = reg2;
                   2546:          ireg = reg1;
                   2547:        }
                   2548:       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
                   2549:        {
                   2550:          breg = reg1;
                   2551:          ireg = reg2;
                   2552:        }
                   2553: 
                   2554:       if (ireg != 0 || breg != 0)
                   2555:        {
                   2556:          int scale = 1;
                   2557: 
                   2558:          if (addr != 0)
                   2559:            {
1.1.1.3   root     2560:              if (flag_pic)
                   2561:                output_pic_addr_const (file, addr, 0);
                   2562: 
                   2563:              else if (GET_CODE (addr) == LABEL_REF)
1.1       root     2564:                output_asm_label (addr);
1.1.1.3   root     2565: 
1.1       root     2566:              else
1.1.1.3   root     2567:                output_addr_const (file, addr);
1.1       root     2568:            }
                   2569: 
                   2570:          if (ireg != 0 && GET_CODE (ireg) == MULT)
                   2571:            {
                   2572:              scale = INTVAL (XEXP (ireg, 1));
                   2573:              ireg = XEXP (ireg, 0);
                   2574:            }
                   2575: 
                   2576:          /* The stack pointer can only appear as a base register,
                   2577:             never an index register, so exchange the regs if it is wrong. */
                   2578: 
                   2579:          if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)
                   2580:            {
                   2581:              rtx tmp;
                   2582: 
                   2583:              tmp = breg;
                   2584:              breg = ireg;
                   2585:              ireg = tmp;
                   2586:            }
                   2587: 
                   2588:          /* output breg+ireg*scale */
                   2589:          PRINT_B_I_S (breg, ireg, scale, file);
                   2590:          break;
                   2591:        }
                   2592: 
                   2593:     case MULT:
                   2594:       {
                   2595:        int scale;
                   2596:        if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
                   2597:          {
                   2598:            scale = INTVAL (XEXP (addr, 0));
                   2599:            ireg = XEXP (addr, 1);
                   2600:          }
                   2601:        else
                   2602:          {
                   2603:            scale = INTVAL (XEXP (addr, 1));
                   2604:            ireg = XEXP (addr, 0);
                   2605:          }
                   2606:        output_addr_const (file, const0_rtx);
                   2607:        PRINT_B_I_S ((rtx) 0, ireg, scale, file);
                   2608:       }
                   2609:       break;
                   2610: 
                   2611:     default:
                   2612:       if (GET_CODE (addr) == CONST_INT
                   2613:          && INTVAL (addr) < 0x8000
                   2614:          && INTVAL (addr) >= -0x8000)
                   2615:        fprintf (file, "%d", INTVAL (addr));
                   2616:       else
                   2617:        {
                   2618:          if (flag_pic)
                   2619:            output_pic_addr_const (file, addr, 0);
                   2620:          else
                   2621:            output_addr_const (file, addr);
                   2622:        }
                   2623:     }
                   2624: }
                   2625: 
                   2626: /* Set the cc_status for the results of an insn whose pattern is EXP.
                   2627:    On the 80386, we assume that only test and compare insns, as well
1.1.1.3   root     2628:    as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT,
1.1       root     2629:    ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
                   2630:    Also, we assume that jumps, moves and sCOND don't affect the condition
                   2631:    codes.  All else clobbers the condition codes, by assumption.
                   2632: 
                   2633:    We assume that ALL integer add, minus, etc. instructions effect the
                   2634:    condition codes.  This MUST be consistent with i386.md.
                   2635: 
                   2636:    We don't record any float test or compare - the redundant test &
                   2637:    compare check in final.c does not handle stack-like regs correctly. */
                   2638: 
                   2639: void
                   2640: notice_update_cc (exp)
                   2641:      rtx exp;
                   2642: {
                   2643:   if (GET_CODE (exp) == SET)
                   2644:     {
                   2645:       /* Jumps do not alter the cc's.  */
                   2646:       if (SET_DEST (exp) == pc_rtx)
                   2647:        return;
                   2648:       /* Moving register or memory into a register:
                   2649:         it doesn't alter the cc's, but it might invalidate
                   2650:         the RTX's which we remember the cc's came from.
                   2651:         (Note that moving a constant 0 or 1 MAY set the cc's).  */
                   2652:       if (REG_P (SET_DEST (exp))
                   2653:          && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM
                   2654:              || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
                   2655:        {
                   2656:          if (cc_status.value1
                   2657:              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
                   2658:            cc_status.value1 = 0;
                   2659:          if (cc_status.value2
                   2660:              && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
                   2661:            cc_status.value2 = 0;
                   2662:          return;
                   2663:        }
                   2664:       /* Moving register into memory doesn't alter the cc's.
                   2665:         It may invalidate the RTX's which we remember the cc's came from.  */
                   2666:       if (GET_CODE (SET_DEST (exp)) == MEM
                   2667:          && (REG_P (SET_SRC (exp))
                   2668:              || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
                   2669:        {
                   2670:          if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
                   2671:            cc_status.value1 = 0;
                   2672:          if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
                   2673:            cc_status.value2 = 0;
                   2674:          return;
                   2675:        }
                   2676:       /* Function calls clobber the cc's.  */
                   2677:       else if (GET_CODE (SET_SRC (exp)) == CALL)
                   2678:        {
                   2679:          CC_STATUS_INIT;
                   2680:          return;
                   2681:        }
                   2682:       /* Tests and compares set the cc's in predictable ways.  */
                   2683:       else if (SET_DEST (exp) == cc0_rtx)
                   2684:        {
                   2685:          CC_STATUS_INIT;
                   2686:          cc_status.value1 = SET_SRC (exp);
                   2687:          return;
                   2688:        }
                   2689:       /* Certain instructions effect the condition codes. */
                   2690:       else if (GET_MODE (SET_SRC (exp)) == SImode
                   2691:               || GET_MODE (SET_SRC (exp)) == HImode
                   2692:               || GET_MODE (SET_SRC (exp)) == QImode)
                   2693:        switch (GET_CODE (SET_SRC (exp)))
                   2694:          {
                   2695:          case ASHIFTRT: case LSHIFTRT:
1.1.1.3   root     2696:          case ASHIFT:
1.1       root     2697:            /* Shifts on the 386 don't set the condition codes if the
                   2698:               shift count is zero. */
                   2699:            if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
                   2700:              {
                   2701:                CC_STATUS_INIT;
                   2702:                break;
                   2703:              }
                   2704:            /* We assume that the CONST_INT is non-zero (this rtx would
                   2705:               have been deleted if it were zero. */
                   2706: 
                   2707:          case PLUS: case MINUS: case NEG:
                   2708:          case AND: case IOR: case XOR:
                   2709:            cc_status.flags = CC_NO_OVERFLOW;
                   2710:            cc_status.value1 = SET_SRC (exp);
                   2711:            cc_status.value2 = SET_DEST (exp);
                   2712:            break;
                   2713: 
                   2714:          default:
                   2715:            CC_STATUS_INIT;
                   2716:          }
                   2717:       else
                   2718:        {
                   2719:          CC_STATUS_INIT;
                   2720:        }
                   2721:     }
                   2722:   else if (GET_CODE (exp) == PARALLEL
                   2723:           && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
                   2724:     {
                   2725:       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
                   2726:        return;
                   2727:       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
                   2728:        {
                   2729:          CC_STATUS_INIT;
                   2730:          if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
                   2731:            cc_status.flags |= CC_IN_80387;
                   2732:          else
                   2733:            cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
                   2734:          return;
                   2735:        }
                   2736:       CC_STATUS_INIT;
                   2737:     }
                   2738:   else
                   2739:     {
                   2740:       CC_STATUS_INIT;
                   2741:     }
                   2742: }
                   2743: 
                   2744: /* Split one or more DImode RTL references into pairs of SImode
                   2745:    references.  The RTL can be REG, offsettable MEM, integer constant, or
                   2746:    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
                   2747:    split and "num" is its length.  lo_half and hi_half are output arrays
                   2748:    that parallel "operands". */
                   2749: 
                   2750: void
                   2751: split_di (operands, num, lo_half, hi_half)
                   2752:      rtx operands[];
                   2753:      int num;
                   2754:      rtx lo_half[], hi_half[];
                   2755: {
                   2756:   while (num--)
                   2757:     {
                   2758:       if (GET_CODE (operands[num]) == REG)
                   2759:        {
                   2760:          lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
                   2761:          hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
                   2762:        }
                   2763:       else if (CONSTANT_P (operands[num]))
                   2764:        {
                   2765:          split_double (operands[num], &lo_half[num], &hi_half[num]);
                   2766:        }
                   2767:       else if (offsettable_memref_p (operands[num]))
                   2768:        {
                   2769:          lo_half[num] = operands[num];
                   2770:          hi_half[num] = adj_offsettable_operand (operands[num], 4);
                   2771:        }
                   2772:       else
                   2773:        abort();
                   2774:     }
                   2775: }
                   2776: 
                   2777: /* Return 1 if this is a valid binary operation on a 387.
                   2778:    OP is the expression matched, and MODE is its mode. */
                   2779: 
                   2780: int
                   2781: binary_387_op (op, mode)
                   2782:     register rtx op;
                   2783:     enum machine_mode mode;
                   2784: {
                   2785:   if (mode != VOIDmode && mode != GET_MODE (op))
                   2786:     return 0;
                   2787: 
                   2788:   switch (GET_CODE (op))
                   2789:     {
                   2790:     case PLUS:
                   2791:     case MINUS:
                   2792:     case MULT:
                   2793:     case DIV:
                   2794:       return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;
                   2795: 
                   2796:     default:
                   2797:       return 0;
                   2798:     }
                   2799: }
                   2800: 
1.1.1.3   root     2801: 
1.1       root     2802: /* Return 1 if this is a valid shift or rotate operation on a 386.
                   2803:    OP is the expression matched, and MODE is its mode. */
                   2804: 
                   2805: int
                   2806: shift_op (op, mode)
                   2807:     register rtx op;
                   2808:     enum machine_mode mode;
                   2809: {
                   2810:   rtx operand = XEXP (op, 0);
                   2811: 
                   2812:   if (mode != VOIDmode && mode != GET_MODE (op))
                   2813:     return 0;
                   2814: 
                   2815:   if (GET_MODE (operand) != GET_MODE (op)
                   2816:       || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
                   2817:     return 0;
                   2818: 
                   2819:   return (GET_CODE (op) == ASHIFT
                   2820:          || GET_CODE (op) == ASHIFTRT
                   2821:          || GET_CODE (op) == LSHIFTRT
                   2822:          || GET_CODE (op) == ROTATE
                   2823:          || GET_CODE (op) == ROTATERT);
                   2824: }
                   2825: 
                   2826: /* Return 1 if OP is COMPARE rtx with mode VOIDmode.
                   2827:    MODE is not used.  */
                   2828: 
                   2829: int
                   2830: VOIDmode_compare_op (op, mode)
                   2831:     register rtx op;
                   2832:     enum machine_mode mode;
                   2833: {
                   2834:   return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode;
                   2835: }
                   2836: 
                   2837: /* Output code to perform a 387 binary operation in INSN, one of PLUS,
                   2838:    MINUS, MULT or DIV.  OPERANDS are the insn operands, where operands[3]
                   2839:    is the expression of the binary operation.  The output may either be
                   2840:    emitted here, or returned to the caller, like all output_* functions.
                   2841: 
                   2842:    There is no guarantee that the operands are the same mode, as they
                   2843:    might be within FLOAT or FLOAT_EXTEND expressions. */
                   2844: 
                   2845: char *
                   2846: output_387_binary_op (insn, operands)
                   2847:      rtx insn;
                   2848:      rtx *operands;
                   2849: {
                   2850:   rtx temp;
                   2851:   char *base_op;
                   2852:   static char buf[100];
                   2853: 
                   2854:   switch (GET_CODE (operands[3]))
                   2855:     {
                   2856:     case PLUS:
                   2857:       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
                   2858:          || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
                   2859:        base_op = "fiadd";
                   2860:       else
                   2861:        base_op = "fadd";
                   2862:       break;
                   2863: 
                   2864:     case MINUS:
                   2865:       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
                   2866:          || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
                   2867:        base_op = "fisub";
                   2868:       else
                   2869:        base_op = "fsub";
                   2870:       break;
                   2871: 
                   2872:     case MULT:
                   2873:       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
                   2874:          || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
                   2875:        base_op = "fimul";
                   2876:       else
                   2877:        base_op = "fmul";
                   2878:       break;
                   2879: 
                   2880:     case DIV:
                   2881:       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
                   2882:          || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
                   2883:        base_op = "fidiv";
                   2884:       else
                   2885:        base_op = "fdiv";
                   2886:       break;
                   2887: 
                   2888:     default:
                   2889:       abort ();
                   2890:     }
                   2891: 
                   2892:   strcpy (buf, base_op);
                   2893: 
                   2894:   switch (GET_CODE (operands[3]))
                   2895:     {
                   2896:     case MULT:
                   2897:     case PLUS:
                   2898:       if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
                   2899:        {
                   2900:          temp = operands[2];
                   2901:          operands[2] = operands[1];
                   2902:          operands[1] = temp;
                   2903:        }
                   2904: 
                   2905:       if (GET_CODE (operands[2]) == MEM)
                   2906:        return strcat (buf, AS1 (%z2,%2));
                   2907: 
                   2908:       if (NON_STACK_REG_P (operands[1]))
                   2909:        {
                   2910:          output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
                   2911:          RET;
                   2912:        }
                   2913:       else if (NON_STACK_REG_P (operands[2]))
                   2914:        {
                   2915:          output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
                   2916:          RET;
                   2917:        }
                   2918: 
                   2919:       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
                   2920:        return strcat (buf, AS2 (p,%2,%0));
                   2921: 
                   2922:       if (STACK_TOP_P (operands[0]))
1.1.1.3   root     2923:        return strcat (buf, AS2C (%y2,%0));
1.1       root     2924:       else
1.1.1.3   root     2925:        return strcat (buf, AS2C (%2,%0));
1.1       root     2926: 
                   2927:     case MINUS:
                   2928:     case DIV:
                   2929:       if (GET_CODE (operands[1]) == MEM)
                   2930:        return strcat (buf, AS1 (r%z1,%1));
                   2931: 
                   2932:       if (GET_CODE (operands[2]) == MEM)
                   2933:        return strcat (buf, AS1 (%z2,%2));
                   2934: 
                   2935:       if (NON_STACK_REG_P (operands[1]))
                   2936:        {
                   2937:          output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));
                   2938:          RET;
                   2939:        }
                   2940:       else if (NON_STACK_REG_P (operands[2]))
                   2941:        {
                   2942:          output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
                   2943:          RET;
                   2944:        }
                   2945: 
                   2946:       if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
                   2947:        abort ();
                   2948: 
                   2949:       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
                   2950:        return strcat (buf, AS2 (rp,%2,%0));
                   2951: 
                   2952:       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
                   2953:        return strcat (buf, AS2 (p,%1,%0));
                   2954: 
                   2955:       if (STACK_TOP_P (operands[0]))
                   2956:        {
                   2957:          if (STACK_TOP_P (operands[1]))
1.1.1.3   root     2958:            return strcat (buf, AS2C (%y2,%0));
1.1       root     2959:          else
                   2960:            return strcat (buf, AS2 (r,%y1,%0));
                   2961:        }
                   2962:       else if (STACK_TOP_P (operands[1]))
1.1.1.3   root     2963:        return strcat (buf, AS2C (%1,%0));
1.1       root     2964:       else
                   2965:        return strcat (buf, AS2 (r,%2,%0));
                   2966: 
                   2967:     default:
                   2968:       abort ();
                   2969:     }
                   2970: }
                   2971: 
                   2972: /* Output code for INSN to convert a float to a signed int.  OPERANDS
                   2973:    are the insn operands.  The output may be SFmode or DFmode and the
                   2974:    input operand may be SImode or DImode.  As a special case, make sure
                   2975:    that the 387 stack top dies if the output mode is DImode, because the
                   2976:    hardware requires this.  */
                   2977: 
                   2978: char *
                   2979: output_fix_trunc (insn, operands)
                   2980:      rtx insn;
                   2981:      rtx *operands;
                   2982: {
                   2983:   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
                   2984:   rtx xops[2];
                   2985: 
                   2986:   if (! STACK_TOP_P (operands[1]) ||
                   2987:       (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
                   2988:     abort ();
                   2989: 
                   2990:   xops[0] = GEN_INT (12);
                   2991:   xops[1] = operands[4];
                   2992: 
                   2993:   output_asm_insn (AS1 (fnstc%W2,%2), operands);
                   2994:   output_asm_insn (AS2 (mov%L2,%2,%4), operands);
                   2995:   output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
                   2996:   output_asm_insn (AS2 (mov%L4,%4,%3), operands);
                   2997:   output_asm_insn (AS1 (fldc%W3,%3), operands);
                   2998: 
                   2999:   if (NON_STACK_REG_P (operands[0]))
                   3000:     output_to_reg (operands[0], stack_top_dies);
                   3001:   else if (GET_CODE (operands[0]) == MEM)
                   3002:     {
                   3003:       if (stack_top_dies)
                   3004:        output_asm_insn (AS1 (fistp%z0,%0), operands);
                   3005:       else
                   3006:        output_asm_insn (AS1 (fist%z0,%0), operands);
                   3007:     }
                   3008:   else
                   3009:     abort ();
                   3010: 
                   3011:   return AS1 (fldc%W2,%2);
                   3012: }
                   3013: 
                   3014: /* Output code for INSN to compare OPERANDS.  The two operands might
                   3015:    not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
                   3016:    expression.  If the compare is in mode CCFPEQmode, use an opcode that
                   3017:    will not fault if a qNaN is present. */
                   3018: 
                   3019: char *
                   3020: output_float_compare (insn, operands)
                   3021:      rtx insn;
                   3022:      rtx *operands;
                   3023: {
                   3024:   int stack_top_dies;
                   3025:   rtx body = XVECEXP (PATTERN (insn), 0, 0);
                   3026:   int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
                   3027: 
                   3028:   if (! STACK_TOP_P (operands[0]))
                   3029:     abort ();
                   3030: 
                   3031:   stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
                   3032: 
                   3033:   if (STACK_REG_P (operands[1])
                   3034:       && stack_top_dies
                   3035:       && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
                   3036:       && REGNO (operands[1]) != FIRST_STACK_REG)
                   3037:     {
                   3038:       /* If both the top of the 387 stack dies, and the other operand
                   3039:         is also a stack register that dies, then this must be a
                   3040:         `fcompp' float compare */
                   3041: 
                   3042:       if (unordered_compare)
                   3043:        output_asm_insn ("fucompp", operands);
                   3044:       else
                   3045:        output_asm_insn ("fcompp", operands);
                   3046:     }
                   3047:   else
                   3048:     {
                   3049:       static char buf[100];
                   3050: 
                   3051:       /* Decide if this is the integer or float compare opcode, or the
                   3052:         unordered float compare. */
                   3053: 
                   3054:       if (unordered_compare)
                   3055:        strcpy (buf, "fucom");
                   3056:       else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
                   3057:        strcpy (buf, "fcom");
                   3058:       else
                   3059:        strcpy (buf, "ficom");
                   3060: 
                   3061:       /* Modify the opcode if the 387 stack is to be popped. */
                   3062: 
                   3063:       if (stack_top_dies)
                   3064:        strcat (buf, "p");
                   3065: 
                   3066:       if (NON_STACK_REG_P (operands[1]))
                   3067:        output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
                   3068:       else
                   3069:         output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);
                   3070:     }
                   3071: 
                   3072:   /* Now retrieve the condition code. */
                   3073: 
                   3074:   return output_fp_cc0_set (insn);
                   3075: }
                   3076: 
                   3077: /* Output opcodes to transfer the results of FP compare or test INSN
                   3078:    from the FPU to the CPU flags.  If TARGET_IEEE_FP, ensure that if the
                   3079:    result of the compare or test is unordered, no comparison operator
                   3080:    succeeds except NE.  Return an output template, if any.  */
                   3081: 
                   3082: char *
                   3083: output_fp_cc0_set (insn)
                   3084:      rtx insn;
                   3085: {
                   3086:   rtx xops[3];
                   3087:   rtx unordered_label;
                   3088:   rtx next;
                   3089:   enum rtx_code code;
                   3090: 
                   3091:   xops[0] = gen_rtx (REG, HImode, 0);
                   3092:   output_asm_insn (AS1 (fnsts%W0,%0), xops);
                   3093: 
                   3094:   if (! TARGET_IEEE_FP)
                   3095:     return "sahf";
                   3096: 
                   3097:   next = next_cc0_user (insn);
                   3098:   if (next == NULL_RTX)
                   3099:     abort ();
                   3100: 
                   3101:   if (GET_CODE (next) == JUMP_INSN
                   3102:       && GET_CODE (PATTERN (next)) == SET
                   3103:       && SET_DEST (PATTERN (next)) == pc_rtx
                   3104:       && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
                   3105:     {
                   3106:       code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
                   3107:     }
                   3108:   else if (GET_CODE (PATTERN (next)) == SET)
                   3109:     {
                   3110:       code = GET_CODE (SET_SRC (PATTERN (next)));
                   3111:     }
                   3112:   else
                   3113:     abort ();
                   3114: 
                   3115:   xops[0] = gen_rtx (REG, QImode, 0);
                   3116: 
                   3117:   switch (code)
                   3118:     {
                   3119:     case GT:
                   3120:       xops[1] = GEN_INT (0x45);
                   3121:       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
                   3122:       /* je label */
                   3123:       break;
                   3124: 
                   3125:     case LT:
                   3126:       xops[1] = GEN_INT (0x45);
                   3127:       xops[2] = GEN_INT (0x01);
                   3128:       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
                   3129:       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
                   3130:       /* je label */
                   3131:       break;
                   3132: 
                   3133:     case GE:
                   3134:       xops[1] = GEN_INT (0x05);
                   3135:       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
                   3136:       /* je label */
                   3137:       break;
                   3138: 
                   3139:     case LE:
                   3140:       xops[1] = GEN_INT (0x45);
                   3141:       xops[2] = GEN_INT (0x40);
                   3142:       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
                   3143:       output_asm_insn (AS1 (dec%B0,%h0), xops);
                   3144:       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
                   3145:       /* jb label */
                   3146:       break;
                   3147: 
                   3148:     case EQ:
                   3149:       xops[1] = GEN_INT (0x45);
                   3150:       xops[2] = GEN_INT (0x40);
                   3151:       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
                   3152:       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
                   3153:       /* je label */
                   3154:       break;
                   3155: 
                   3156:     case NE:
                   3157:       xops[1] = GEN_INT (0x44);
                   3158:       xops[2] = GEN_INT (0x40);
                   3159:       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
                   3160:       output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
                   3161:       /* jne label */
                   3162:       break;
                   3163: 
                   3164:     case GTU:
                   3165:     case LTU:
                   3166:     case GEU:
                   3167:     case LEU:
                   3168:     default:
                   3169:       abort ();
                   3170:     }
                   3171:   RET;
                   3172: }
                   3173: 
                   3174: #define MAX_386_STACK_LOCALS 2
                   3175: 
                   3176: static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
                   3177: 
1.1.1.2   root     3178: /* Define the structure for the machine field in struct function.  */
                   3179: struct machine_function
                   3180: {
                   3181:   rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
                   3182: };
                   3183: 
                   3184: /* Functions to save and restore i386_stack_locals.
                   3185:    These will be called, via pointer variables,
                   3186:    from push_function_context and pop_function_context.  */
                   3187: 
                   3188: void
                   3189: save_386_machine_status (p)
                   3190:      struct function *p;
                   3191: {
                   3192:   p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals);
1.1.1.3   root     3193:   bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals,
1.1.1.2   root     3194:         sizeof i386_stack_locals);
                   3195: }
                   3196: 
                   3197: void
                   3198: restore_386_machine_status (p)
                   3199:      struct function *p;
                   3200: {
1.1.1.3   root     3201:   bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals,
1.1.1.2   root     3202:         sizeof i386_stack_locals);
                   3203:   free (p->machine);
                   3204: }
                   3205: 
1.1       root     3206: /* Clear stack slot assignments remembered from previous functions.
                   3207:    This is called from INIT_EXPANDERS once before RTL is emitted for each
1.1.1.2   root     3208:    function.  */
1.1       root     3209: 
                   3210: void
                   3211: clear_386_stack_locals ()
                   3212: {
                   3213:   enum machine_mode mode;
                   3214:   int n;
                   3215: 
                   3216:   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
                   3217:        mode = (enum machine_mode) ((int) mode + 1))
                   3218:     for (n = 0; n < MAX_386_STACK_LOCALS; n++)
                   3219:       i386_stack_locals[(int) mode][n] = NULL_RTX;
1.1.1.2   root     3220: 
                   3221:   /* Arrange to save and restore i386_stack_locals around nested functions.  */
                   3222:   save_machine_status = save_386_machine_status;
                   3223:   restore_machine_status = restore_386_machine_status;
1.1       root     3224: }
                   3225: 
                   3226: /* Return a MEM corresponding to a stack slot with mode MODE.
                   3227:    Allocate a new slot if necessary.
                   3228: 
                   3229:    The RTL for a function can have several slots available: N is
                   3230:    which slot to use.  */
                   3231: 
                   3232: rtx
                   3233: assign_386_stack_local (mode, n)
                   3234:      enum machine_mode mode;
                   3235:      int n;
                   3236: {
                   3237:   if (n < 0 || n >= MAX_386_STACK_LOCALS)
                   3238:     abort ();
                   3239: 
                   3240:   if (i386_stack_locals[(int) mode][n] == NULL_RTX)
                   3241:     i386_stack_locals[(int) mode][n]
                   3242:       = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
                   3243: 
                   3244:   return i386_stack_locals[(int) mode][n];
                   3245: }

unix.superglobalmegacorp.com

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