OSDN Git Service

(put_condition_code, print_operand, output_fp_cc0_set):
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.c
1 /* Subroutines for insn-output.c for Intel X86.
2    Copyright (C) 1988, 1992, 1994, 1995, 1996 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include <stdio.h>
22 #include <setjmp.h>
23 #include <ctype.h>
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"
36 #include "except.h"
37 #include "function.h"
38
39 #ifdef EXTRA_CONSTRAINT
40 /* If EXTRA_CONSTRAINT is defined, then the 'S'
41    constraint in REG_CLASS_FROM_LETTER will no longer work, and various
42    asm statements that need 'S' for class SIREG will break.  */
43  error EXTRA_CONSTRAINT conflicts with S constraint letter
44 /* The previous line used to be #error, but some compilers barf
45    even if the conditional was untrue.  */
46 #endif
47
48 enum reg_mem                    /* Type of an operand for ix86_{binary,unary}_operator_ok */
49 {
50   reg_p,
51   mem_p,
52   imm_p
53 };
54
55 /* Processor costs (relative to an add) */
56 struct processor_costs i386_cost = {    /* 386 specific costs */
57   1,                                    /* cost of an add instruction (2 cycles) */
58   1,                                    /* cost of a lea instruction */
59   3,                                    /* variable shift costs */
60   2,                                    /* constant shift costs */
61   6,                                    /* cost of starting a multiply */
62   1,                                    /* cost of multiply per each bit set */
63   23                                    /* cost of a divide/mod */
64 };
65
66 struct processor_costs i486_cost = {    /* 486 specific costs */
67   1,                                    /* cost of an add instruction */
68   1,                                    /* cost of a lea instruction */
69   3,                                    /* variable shift costs */
70   2,                                    /* constant shift costs */
71   12,                                   /* cost of starting a multiply */
72   1,                                    /* cost of multiply per each bit set */
73   40                                    /* cost of a divide/mod */
74 };
75
76 struct processor_costs pentium_cost = {
77   1,                                    /* cost of an add instruction */
78   1,                                    /* cost of a lea instruction */
79   3,                                    /* variable shift costs */
80   1,                                    /* constant shift costs */
81   12,                                   /* cost of starting a multiply */
82   1,                                    /* cost of multiply per each bit set */
83   25                                    /* cost of a divide/mod */
84 };
85
86 struct processor_costs *ix86_cost = &pentium_cost;
87
88 #define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx))
89
90 extern FILE *asm_out_file;
91 extern char *strcat ();
92
93 char *singlemove_string ();
94 char *output_move_const_single ();
95 char *output_fp_cc0_set ();
96
97 char *hi_reg_name[] = HI_REGISTER_NAMES;
98 char *qi_reg_name[] = QI_REGISTER_NAMES;
99 char *qi_high_reg_name[] = QI_HIGH_REGISTER_NAMES;
100
101 /* Array of the smallest class containing reg number REGNO, indexed by
102    REGNO.  Used by REGNO_REG_CLASS in i386.h. */
103
104 enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
105 {
106   /* ax, dx, cx, bx */
107   AREG, DREG, CREG, BREG,
108   /* si, di, bp, sp */
109   SIREG, DIREG, INDEX_REGS, GENERAL_REGS,
110   /* FP registers */
111   FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS,
112   FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS,       
113   /* arg pointer */
114   INDEX_REGS
115 };
116
117 /* Test and compare insns in i386.md store the information needed to
118    generate branch and scc insns here.  */
119
120 struct rtx_def *i386_compare_op0 = NULL_RTX;
121 struct rtx_def *i386_compare_op1 = NULL_RTX;
122 struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)();
123
124 /* which cpu are we scheduling for */
125 enum processor_type ix86_cpu;
126
127 /* which instruction set architecture to use.  */
128 int ix86_isa;
129
130 /* Strings to hold which cpu and instruction set architecture  to use.  */
131 char *ix86_cpu_string;          /* for -mcpu=<xxx> */
132 char *ix86_isa_string;          /* for -misa=<xxx> */
133
134 /* Register allocation order */
135 char *i386_reg_alloc_order;
136 static char regs_allocated[FIRST_PSEUDO_REGISTER];
137
138 /* # of registers to use to pass arguments. */
139 char *i386_regparm_string;                      /* # registers to use to pass args */
140 int i386_regparm;                               /* i386_regparm_string as a number */
141
142 /* Alignment to use for loops and jumps */
143 char *i386_align_loops_string;                  /* power of two alignment for loops */
144 char *i386_align_jumps_string;                  /* power of two alignment for non-loop jumps */
145 char *i386_align_funcs_string;                  /* power of two alignment for functions */
146
147 int i386_align_loops;                           /* power of two alignment for loops */
148 int i386_align_jumps;                           /* power of two alignment for non-loop jumps */
149 int i386_align_funcs;                           /* power of two alignment for functions */
150
151 /* Sometimes certain combinations of command options do not make
152    sense on a particular target machine.  You can define a macro
153    `OVERRIDE_OPTIONS' to take account of this.  This macro, if
154    defined, is executed once just after all the command options have
155    been parsed.
156
157    Don't use this macro to turn on various extra optimizations for
158    `-O'.  That is what `OPTIMIZATION_OPTIONS' is for.  */
159
160 void
161 override_options ()
162 {
163   int ch, i, j, regno;
164   char *p;
165   int def_align;
166
167   static struct ptt
168     {
169       char *name;               /* Canonical processor name.  */
170       enum processor_type processor; /* Processor type enum value.  */
171       struct processor_costs *cost; /* Processor costs */
172       int target_enable;        /* Target flags to enable.  */
173       int target_disable;       /* Target flags to disable.  */
174     } processor_target_table[]
175       = {{PROCESSOR_COMMON_STRING, PROCESSOR_COMMON, &i486_cost, 0, 0},
176            {PROCESSOR_I386_STRING, PROCESSOR_I386, &i386_cost, 0, 0},
177            {PROCESSOR_I486_STRING, PROCESSOR_I486, &i486_cost, 0, 0},
178            {PROCESSOR_I586_STRING, PROCESSOR_PENTIUM, &pentium_cost, 0, 0},
179            {PROCESSOR_PENTIUM_STRING, PROCESSOR_PENTIUM, &pentium_cost, 0, 0},
180            {PROCESSOR_I686_STRING, PROCESSOR_PENTIUMPRO, &pentium_cost, 0, 0},
181            {PROCESSOR_PENTIUMPRO_STRING, PROCESSOR_PENTIUMPRO, &pentium_cost, 0, 0}};
182
183   int ptt_size = sizeof (processor_target_table) / sizeof (struct ptt);
184
185 #ifdef SUBTARGET_OVERRIDE_OPTIONS
186   SUBTARGET_OVERRIDE_OPTIONS;
187 #endif
188
189   /* Validate registers in register allocation order */
190   if (i386_reg_alloc_order)
191     {
192       for (i = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
193         {
194           switch (ch)
195             {
196             case 'a':   regno = 0;      break;
197             case 'd':   regno = 1;      break;
198             case 'c':   regno = 2;      break;
199             case 'b':   regno = 3;      break;
200             case 'S':   regno = 4;      break;
201             case 'D':   regno = 5;      break;
202             case 'B':   regno = 6;      break;
203
204             default:    fatal ("Register '%c' is unknown", ch);
205             }
206
207           if (regs_allocated[regno])
208             fatal ("Register '%c' was already specified in the allocation order", ch);
209
210           regs_allocated[regno] = 1;
211         }
212     }
213
214   /* Get the architectural level.  */
215   if (ix86_isa_string == (char *)0)
216       ix86_isa_string = PROCESSOR_DEFAULT_STRING;
217
218   for (i = 0; i < ptt_size; i++)
219     if (! strcmp (ix86_isa_string, processor_target_table[i].name))
220       {
221         ix86_isa = processor_target_table[i].processor;
222         if (ix86_cpu_string == (char *)0)
223           ix86_cpu_string = processor_target_table[i].name;
224         break;
225       }
226
227   if (i == ptt_size)
228     {
229       error ("bad value (%s) for -misa= switch", ix86_isa_string);
230       ix86_isa_string = PROCESSOR_DEFAULT_STRING;
231       ix86_isa = PROCESSOR_DEFAULT;
232     }
233
234   for (j = 0; j < ptt_size; j++)
235     if (! strcmp (ix86_cpu_string, processor_target_table[j].name))
236       {
237         ix86_cpu = processor_target_table[j].processor;
238         if (i > j && (int)ix86_isa >= (int)PROCESSOR_PENTIUMPRO)
239           error ("-mcpu=%s does not support -march=%s", ix86_cpu_string, ix86_isa_string);
240
241         target_flags |= processor_target_table[j].target_enable;
242         target_flags &= ~processor_target_table[j].target_disable;
243         break;
244       }
245
246   if (j == ptt_size)
247     {
248       error ("bad value (%s) for -mcpu= switch", ix86_cpu_string);
249       ix86_cpu_string = PROCESSOR_DEFAULT_STRING;
250       ix86_cpu = PROCESSOR_DEFAULT;
251     }
252
253   /* Validate -mregparm= value */
254   if (i386_regparm_string)
255     {
256       i386_regparm = atoi (i386_regparm_string);
257       if (i386_regparm < 0 || i386_regparm > REGPARM_MAX)
258         fatal ("-mregparm=%d is not between 0 and %d", i386_regparm, REGPARM_MAX);
259     }
260
261   def_align = (TARGET_386) ? 2 : 4;
262
263   /* Validate -malign-loops= value, or provide default */
264   if (i386_align_loops_string)
265     {
266       i386_align_loops = atoi (i386_align_loops_string);
267       if (i386_align_loops < 0 || i386_align_loops > MAX_CODE_ALIGN)
268         fatal ("-malign-loops=%d is not between 0 and %d",
269                i386_align_loops, MAX_CODE_ALIGN);
270     }
271   else
272     i386_align_loops = 2;
273
274   /* Validate -malign-jumps= value, or provide default */
275   if (i386_align_jumps_string)
276     {
277       i386_align_jumps = atoi (i386_align_jumps_string);
278       if (i386_align_jumps < 0 || i386_align_jumps > MAX_CODE_ALIGN)
279         fatal ("-malign-jumps=%d is not between 0 and %d",
280                i386_align_jumps, MAX_CODE_ALIGN);
281     }
282   else
283     i386_align_jumps = def_align;
284
285   /* Validate -malign-functions= value, or provide default */
286   if (i386_align_funcs_string)
287     {
288       i386_align_funcs = atoi (i386_align_funcs_string);
289       if (i386_align_funcs < 0 || i386_align_funcs > MAX_CODE_ALIGN)
290         fatal ("-malign-functions=%d is not between 0 and %d",
291                i386_align_funcs, MAX_CODE_ALIGN);
292     }
293   else
294     i386_align_funcs = def_align;
295
296   if (TARGET_OMIT_LEAF_FRAME_POINTER)   /* keep nonleaf frame pointers */
297     flag_omit_frame_pointer = 1;
298
299   /* pic references don't explicitly mention pic_offset_table_rtx */
300   if (flag_pic)
301     target_flags &= ~MASK_SCHEDULE_PROLOGUE;
302 }
303 \f
304 /* A C statement (sans semicolon) to choose the order in which to
305    allocate hard registers for pseudo-registers local to a basic
306    block.
307
308    Store the desired register order in the array `reg_alloc_order'.
309    Element 0 should be the register to allocate first; element 1, the
310    next register; and so on.
311
312    The macro body should not assume anything about the contents of
313    `reg_alloc_order' before execution of the macro.
314
315    On most machines, it is not necessary to define this macro.  */
316
317 void
318 order_regs_for_local_alloc ()
319 {
320   int i, ch, order, regno;
321
322   /* User specified the register allocation order */
323   if (i386_reg_alloc_order)
324     {
325       for (i = order = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++)
326         {
327           switch (ch)
328             {
329             case 'a':   regno = 0;      break;
330             case 'd':   regno = 1;      break;
331             case 'c':   regno = 2;      break;
332             case 'b':   regno = 3;      break;
333             case 'S':   regno = 4;      break;
334             case 'D':   regno = 5;      break;
335             case 'B':   regno = 6;      break;
336             }
337
338           reg_alloc_order[order++] = regno;
339         }
340
341       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
342         {
343           if (!regs_allocated[i])
344             reg_alloc_order[order++] = i;
345         }
346     }
347
348   /* If users did not specify a register allocation order, use natural order */
349   else
350     {
351       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
352         reg_alloc_order[i] = i;
353     }
354 }
355
356 \f
357 void
358 optimization_options (level)
359      int level;
360 {
361   /* For -O2, and beyond, turn off -fschedule-insns by default.  It tends to
362      make the problem with not enough registers even worse */
363 #ifdef INSN_SCHEDULING
364   if (level > 1)
365     flag_schedule_insns = 0;
366 #endif
367 }
368 \f
369 /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
370    attribute for DECL.  The attributes in ATTRIBUTES have previously been
371    assigned to DECL.  */
372
373 int
374 i386_valid_decl_attribute_p (decl, attributes, identifier, args)
375      tree decl;
376      tree attributes;
377      tree identifier;
378      tree args;
379 {
380   return 0;
381 }
382
383 /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
384    attribute for TYPE.  The attributes in ATTRIBUTES have previously been
385    assigned to TYPE.  */
386
387 int
388 i386_valid_type_attribute_p (type, attributes, identifier, args)
389      tree type;
390      tree attributes;
391      tree identifier;
392      tree args;
393 {
394   if (TREE_CODE (type) != FUNCTION_TYPE
395       && TREE_CODE (type) != FIELD_DECL
396       && TREE_CODE (type) != TYPE_DECL)
397     return 0;
398
399   /* Stdcall attribute says callee is responsible for popping arguments
400      if they are not variable.  */
401   if (is_attribute_p ("stdcall", identifier))
402     return (args == NULL_TREE);
403
404   /* Cdecl attribute says the callee is a normal C declaration */
405   if (is_attribute_p ("cdecl", identifier))
406     return (args == NULL_TREE);
407
408   /* Regparm attribute specifies how many integer arguments are to be
409      passed in registers */
410   if (is_attribute_p ("regparm", identifier))
411     {
412       tree cst;
413
414       if (!args || TREE_CODE (args) != TREE_LIST
415           || TREE_CHAIN (args) != NULL_TREE
416           || TREE_VALUE (args) == NULL_TREE)
417         return 0;
418
419       cst = TREE_VALUE (args);
420       if (TREE_CODE (cst) != INTEGER_CST)
421         return 0;
422
423       if (TREE_INT_CST_HIGH (cst) != 0
424           || TREE_INT_CST_LOW (cst) < 0
425           || TREE_INT_CST_LOW (cst) > REGPARM_MAX)
426         return 0;
427
428       return 1;
429     }
430
431   return 0;
432 }
433
434 /* Return 0 if the attributes for two types are incompatible, 1 if they
435    are compatible, and 2 if they are nearly compatible (which causes a
436    warning to be generated).  */
437
438 int
439 i386_comp_type_attributes (type1, type2)
440      tree type1;
441      tree type2;
442 {
443   return 1;
444 }
445
446 \f
447 /* Value is the number of bytes of arguments automatically
448    popped when returning from a subroutine call.
449    FUNDECL is the declaration node of the function (as a tree),
450    FUNTYPE is the data type of the function (as a tree),
451    or for a library call it is an identifier node for the subroutine name.
452    SIZE is the number of bytes of arguments passed on the stack.
453
454    On the 80386, the RTD insn may be used to pop them if the number
455      of args is fixed, but if the number is variable then the caller
456      must pop them all.  RTD can't be used for library calls now
457      because the library is compiled with the Unix compiler.
458    Use of RTD is a selectable option, since it is incompatible with
459    standard Unix calling sequences.  If the option is not selected,
460    the caller must always pop the args.
461
462    The attribute stdcall is equivalent to RTD on a per module basis.  */
463
464 int
465 i386_return_pops_args (fundecl, funtype, size)
466      tree fundecl;
467      tree funtype;
468      int size;
469
470   int rtd = TARGET_RTD;
471
472   if (TREE_CODE (funtype) == IDENTIFIER_NODE)
473     return 0;
474
475     /* Cdecl functions override -mrtd, and never pop the stack */
476   if (!lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) {
477   
478     /* Stdcall functions will pop the stack if not variable args */
479     if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype)))
480       rtd = 1;
481   
482     if (rtd
483         && (TYPE_ARG_TYPES (funtype) == NULL_TREE
484             || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node)))
485       return size;
486   }
487   
488   /* Lose any fake structure return argument */
489   if (aggregate_value_p (TREE_TYPE (funtype)))
490     return GET_MODE_SIZE (Pmode);
491   
492     return 0;
493 }
494
495 \f
496 /* Argument support functions.  */
497
498 /* Initialize a variable CUM of type CUMULATIVE_ARGS
499    for a call to a function whose data type is FNTYPE.
500    For a library call, FNTYPE is 0.  */
501
502 void
503 init_cumulative_args (cum, fntype, libname)
504      CUMULATIVE_ARGS *cum;      /* argument info to initialize */
505      tree fntype;               /* tree ptr for function decl */
506      rtx libname;               /* SYMBOL_REF of library name or 0 */
507 {
508   static CUMULATIVE_ARGS zero_cum;
509   tree param, next_param;
510
511   if (TARGET_DEBUG_ARG)
512     {
513       fprintf (stderr, "\ninit_cumulative_args (");
514       if (fntype)
515         {
516           tree ret_type = TREE_TYPE (fntype);
517           fprintf (stderr, "fntype code = %s, ret code = %s",
518                    tree_code_name[ (int)TREE_CODE (fntype) ],
519                    tree_code_name[ (int)TREE_CODE (ret_type) ]);
520         }
521       else
522         fprintf (stderr, "no fntype");
523
524       if (libname)
525         fprintf (stderr, ", libname = %s", XSTR (libname, 0));
526     }
527
528   *cum = zero_cum;
529
530   /* Set up the number of registers to use for passing arguments.  */
531   cum->nregs = i386_regparm;
532   if (fntype)
533     {
534       tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));
535       if (attr)
536         cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
537     }
538
539   /* Determine if this function has variable arguments.  This is
540      indicated by the last argument being 'void_type_mode' if there
541      are no variable arguments.  If there are variable arguments, then
542      we won't pass anything in registers */
543
544   if (cum->nregs)
545     {
546       for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
547            param != (tree)0;
548            param = next_param)
549         {
550           next_param = TREE_CHAIN (param);
551           if (next_param == (tree)0 && TREE_VALUE (param) != void_type_node)
552             cum->nregs = 0;
553         }
554     }
555
556   if (TARGET_DEBUG_ARG)
557     fprintf (stderr, ", nregs=%d )\n", cum->nregs);
558
559   return;
560 }
561
562 /* Update the data in CUM to advance over an argument
563    of mode MODE and data type TYPE.
564    (TYPE is null for libcalls where that information may not be available.)  */
565
566 void
567 function_arg_advance (cum, mode, type, named)
568      CUMULATIVE_ARGS *cum;      /* current arg information */
569      enum machine_mode mode;    /* current arg mode */
570      tree type;                 /* type of the argument or 0 if lib support */
571      int named;                 /* whether or not the argument was named */
572 {
573   int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
574   int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
575
576   if (TARGET_DEBUG_ARG)
577     fprintf (stderr,
578              "function_adv( size=%d, words=%2d, nregs=%d, mode=%4s, named=%d )\n\n",
579              words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);
580
581   cum->words += words;
582   cum->nregs -= words;
583   cum->regno += words;
584
585   if (cum->nregs <= 0)
586     {
587       cum->nregs = 0;
588       cum->regno = 0;
589     }
590
591   return;
592 }
593
594 /* Define where to put the arguments to a function.
595    Value is zero to push the argument on the stack,
596    or a hard register in which to store the argument.
597
598    MODE is the argument's machine mode.
599    TYPE is the data type of the argument (as a tree).
600     This is null for libcalls where that information may
601     not be available.
602    CUM is a variable of type CUMULATIVE_ARGS which gives info about
603     the preceding args and about the function being called.
604    NAMED is nonzero if this argument is a named parameter
605     (otherwise it is an extra parameter matching an ellipsis).  */
606
607 struct rtx_def *
608 function_arg (cum, mode, type, named)
609      CUMULATIVE_ARGS *cum;      /* current arg information */
610      enum machine_mode mode;    /* current arg mode */
611      tree type;                 /* type of the argument or 0 if lib support */
612      int named;                 /* != 0 for normal args, == 0 for ... args */
613 {
614   rtx ret   = NULL_RTX;
615   int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
616   int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
617
618   switch (mode)
619     {
620     default:                    /* for now, pass fp/complex values on the stack */
621       break;
622
623     case BLKmode:
624     case DImode:
625     case SImode:
626     case HImode:
627     case QImode:
628       if (words <= cum->nregs)
629         ret = gen_rtx (REG, mode, cum->regno);
630       break;
631     }
632
633   if (TARGET_DEBUG_ARG)
634     {
635       fprintf (stderr,
636                "function_arg( size=%d, words=%2d, nregs=%d, mode=%4s, named=%d",
637                words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);
638
639       if (ret)
640         fprintf (stderr, ", reg=%%e%s", reg_names[ REGNO(ret) ]);
641       else
642         fprintf (stderr, ", stack");
643
644       fprintf (stderr, " )\n");
645     }
646
647   return ret;
648 }
649
650 /* For an arg passed partly in registers and partly in memory,
651    this is the number of registers used.
652    For args passed entirely in registers or entirely in memory, zero.  */
653
654 int
655 function_arg_partial_nregs (cum, mode, type, named)
656      CUMULATIVE_ARGS *cum;      /* current arg information */
657      enum machine_mode mode;    /* current arg mode */
658      tree type;                 /* type of the argument or 0 if lib support */
659      int named;                 /* != 0 for normal args, == 0 for ... args */
660 {
661   return 0;
662 }
663
664 \f
665 /* Output an insn whose source is a 386 integer register.  SRC is the
666    rtx for the register, and TEMPLATE is the op-code template.  SRC may
667    be either SImode or DImode.
668
669    The template will be output with operands[0] as SRC, and operands[1]
670    as a pointer to the top of the 386 stack.  So a call from floatsidf2
671    would look like this:
672
673       output_op_from_reg (operands[1], AS1 (fild%z0,%1));
674
675    where %z0 corresponds to the caller's operands[1], and is used to
676    emit the proper size suffix.
677
678    ??? Extend this to handle HImode - a 387 can load and store HImode
679    values directly. */
680
681 void
682 output_op_from_reg (src, template)
683      rtx src;
684      char *template;
685 {
686   rtx xops[4];
687   int size = GET_MODE_SIZE (GET_MODE (src));
688
689   xops[0] = src;
690   xops[1] = AT_SP (Pmode);
691   xops[2] = GEN_INT (size);
692   xops[3] = stack_pointer_rtx;
693
694   if (size > UNITS_PER_WORD)
695     {
696       rtx high;
697       if (size > 2 * UNITS_PER_WORD)
698         {
699           high = gen_rtx (REG, SImode, REGNO (src) + 2);
700           output_asm_insn (AS1 (push%L0,%0), &high);
701         }
702       high = gen_rtx (REG, SImode, REGNO (src) + 1);
703       output_asm_insn (AS1 (push%L0,%0), &high);
704     }
705   output_asm_insn (AS1 (push%L0,%0), &src);
706
707   output_asm_insn (template, xops);
708
709   output_asm_insn (AS2 (add%L3,%2,%3), xops);
710 }
711 \f
712 /* Output an insn to pop an value from the 387 top-of-stack to 386
713    register DEST. The 387 register stack is popped if DIES is true.  If
714    the mode of DEST is an integer mode, a `fist' integer store is done,
715    otherwise a `fst' float store is done. */
716
717 void
718 output_to_reg (dest, dies)
719      rtx dest;
720      int dies;
721 {
722   rtx xops[4];
723   int size = GET_MODE_SIZE (GET_MODE (dest));
724
725   xops[0] = AT_SP (Pmode);
726   xops[1] = stack_pointer_rtx;
727   xops[2] = GEN_INT (size);
728   xops[3] = dest;
729
730   output_asm_insn (AS2 (sub%L1,%2,%1), xops);
731
732   if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT)
733     {
734       if (dies)
735         output_asm_insn (AS1 (fistp%z3,%y0), xops);
736       else
737         output_asm_insn (AS1 (fist%z3,%y0), xops);
738     }
739   else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT)
740     {
741       if (dies)
742         output_asm_insn (AS1 (fstp%z3,%y0), xops);
743       else
744         {
745           if (GET_MODE (dest) == XFmode)
746             {
747               output_asm_insn (AS1 (fstp%z3,%y0), xops);
748               output_asm_insn (AS1 (fld%z3,%y0), xops);
749             }
750           else
751             output_asm_insn (AS1 (fst%z3,%y0), xops);
752         }
753     }
754   else
755     abort ();
756
757   output_asm_insn (AS1 (pop%L0,%0), &dest);
758
759   if (size > UNITS_PER_WORD)
760     {
761       dest = gen_rtx (REG, SImode, REGNO (dest) + 1);
762       output_asm_insn (AS1 (pop%L0,%0), &dest);
763       if (size > 2 * UNITS_PER_WORD)
764         {
765           dest = gen_rtx (REG, SImode, REGNO (dest) + 1);
766           output_asm_insn (AS1 (pop%L0,%0), &dest);
767         }
768     }
769 }
770 \f
771 char *
772 singlemove_string (operands)
773      rtx *operands;
774 {
775   rtx x;
776   if (GET_CODE (operands[0]) == MEM
777       && GET_CODE (x = XEXP (operands[0], 0)) == PRE_DEC)
778     {
779       if (XEXP (x, 0) != stack_pointer_rtx)
780         abort ();
781       return "push%L1 %1";
782     }
783   else if (GET_CODE (operands[1]) == CONST_DOUBLE)
784     {
785       return output_move_const_single (operands);
786     }
787   else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG)
788     return AS2 (mov%L0,%1,%0);
789   else if (CONSTANT_P (operands[1]))
790     return AS2 (mov%L0,%1,%0);
791   else
792     {
793       output_asm_insn ("push%L1 %1", operands);
794       return "pop%L0 %0";
795     }
796 }
797 \f
798 /* Return a REG that occurs in ADDR with coefficient 1.
799    ADDR can be effectively incremented by incrementing REG.  */
800
801 static rtx
802 find_addr_reg (addr)
803      rtx addr;
804 {
805   while (GET_CODE (addr) == PLUS)
806     {
807       if (GET_CODE (XEXP (addr, 0)) == REG)
808         addr = XEXP (addr, 0);
809       else if (GET_CODE (XEXP (addr, 1)) == REG)
810         addr = XEXP (addr, 1);
811       else if (CONSTANT_P (XEXP (addr, 0)))
812         addr = XEXP (addr, 1);
813       else if (CONSTANT_P (XEXP (addr, 1)))
814         addr = XEXP (addr, 0);
815       else
816         abort ();
817     }
818   if (GET_CODE (addr) == REG)
819     return addr;
820   abort ();
821 }
822
823 \f
824 /* Output an insn to add the constant N to the register X.  */
825
826 static void
827 asm_add (n, x)
828      int n;
829      rtx x;
830 {
831   rtx xops[2];
832   xops[0] = x;
833
834   if (n == -1)
835     output_asm_insn (AS1 (dec%L0,%0), xops);
836   else if (n == 1)
837     output_asm_insn (AS1 (inc%L0,%0), xops);
838   else if (n < 0)
839     {
840       xops[1] = GEN_INT (-n);
841       output_asm_insn (AS2 (sub%L0,%1,%0), xops);
842     }
843   else if (n > 0)
844     {
845       xops[1] = GEN_INT (n);
846       output_asm_insn (AS2 (add%L0,%1,%0), xops);
847     }
848 }
849
850 \f
851 /* Output assembler code to perform a doubleword move insn
852    with operands OPERANDS.  */
853
854 char *
855 output_move_double (operands)
856      rtx *operands;
857 {
858   enum {REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
859   rtx latehalf[2];
860   rtx middlehalf[2];
861   rtx xops[2];
862   rtx addreg0 = 0, addreg1 = 0;
863   int dest_overlapped_low = 0;
864   int size = GET_MODE_SIZE (GET_MODE (operands[0]));
865
866   middlehalf[0] = 0;
867   middlehalf[1] = 0;
868
869   /* First classify both operands.  */
870
871   if (REG_P (operands[0]))
872     optype0 = REGOP;
873   else if (offsettable_memref_p (operands[0]))
874     optype0 = OFFSOP;
875   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
876     optype0 = POPOP;
877   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
878     optype0 = PUSHOP;
879   else if (GET_CODE (operands[0]) == MEM)
880     optype0 = MEMOP;
881   else
882     optype0 = RNDOP;
883
884   if (REG_P (operands[1]))
885     optype1 = REGOP;
886   else if (CONSTANT_P (operands[1]))
887     optype1 = CNSTOP;
888   else if (offsettable_memref_p (operands[1]))
889     optype1 = OFFSOP;
890   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
891     optype1 = POPOP;
892   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
893     optype1 = PUSHOP;
894   else if (GET_CODE (operands[1]) == MEM)
895     optype1 = MEMOP;
896   else
897     optype1 = RNDOP;
898
899   /* Check for the cases that the operand constraints are not
900      supposed to allow to happen.  Abort if we get one,
901      because generating code for these cases is painful.  */
902
903   if (optype0 == RNDOP || optype1 == RNDOP)
904     abort ();
905
906   /* If one operand is decrementing and one is incrementing
907      decrement the former register explicitly
908      and change that operand into ordinary indexing.  */
909
910   if (optype0 == PUSHOP && optype1 == POPOP)
911     {
912       /* ??? Can this ever happen on i386? */
913       operands[0] = XEXP (XEXP (operands[0], 0), 0);
914       asm_add (-size, operands[0]);
915       if (GET_MODE (operands[1]) == XFmode)
916         operands[0] = gen_rtx (MEM, XFmode, operands[0]);
917       else if (GET_MODE (operands[0]) == DFmode)
918         operands[0] = gen_rtx (MEM, DFmode, operands[0]);
919       else
920         operands[0] = gen_rtx (MEM, DImode, operands[0]);
921       optype0 = OFFSOP;
922     }
923
924   if (optype0 == POPOP && optype1 == PUSHOP)
925     {
926       /* ??? Can this ever happen on i386? */
927       operands[1] = XEXP (XEXP (operands[1], 0), 0);
928       asm_add (-size, operands[1]);
929       if (GET_MODE (operands[1]) == XFmode)
930         operands[1] = gen_rtx (MEM, XFmode, operands[1]);
931       else if (GET_MODE (operands[1]) == DFmode)
932         operands[1] = gen_rtx (MEM, DFmode, operands[1]);
933       else
934         operands[1] = gen_rtx (MEM, DImode, operands[1]);
935       optype1 = OFFSOP;
936     }
937
938   /* If an operand is an unoffsettable memory ref, find a register
939      we can increment temporarily to make it refer to the second word.  */
940
941   if (optype0 == MEMOP)
942     addreg0 = find_addr_reg (XEXP (operands[0], 0));
943
944   if (optype1 == MEMOP)
945     addreg1 = find_addr_reg (XEXP (operands[1], 0));
946
947   /* Ok, we can do one word at a time.
948      Normally we do the low-numbered word first,
949      but if either operand is autodecrementing then we
950      do the high-numbered word first.
951
952      In either case, set up in LATEHALF the operands to use
953      for the high-numbered word and in some cases alter the
954      operands in OPERANDS to be suitable for the low-numbered word.  */
955
956   if (size == 12)
957     {
958       if (optype0 == REGOP)
959         {
960           middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
961           latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
962         }
963       else if (optype0 == OFFSOP)
964         {
965           middlehalf[0] = adj_offsettable_operand (operands[0], 4);
966           latehalf[0] = adj_offsettable_operand (operands[0], 8);
967         }
968       else
969         {
970          middlehalf[0] = operands[0];
971          latehalf[0] = operands[0];
972         }
973     
974       if (optype1 == REGOP)
975         {
976           middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
977           latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
978         }
979       else if (optype1 == OFFSOP)
980         {
981           middlehalf[1] = adj_offsettable_operand (operands[1], 4);
982           latehalf[1] = adj_offsettable_operand (operands[1], 8);
983         }
984       else if (optype1 == CNSTOP)
985         {
986           if (GET_CODE (operands[1]) == CONST_DOUBLE)
987             {
988               REAL_VALUE_TYPE r; long l[3];
989
990               REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
991               REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
992               operands[1] = GEN_INT (l[0]);
993               middlehalf[1] = GEN_INT (l[1]);
994               latehalf[1] = GEN_INT (l[2]);
995             }
996           else if (CONSTANT_P (operands[1]))
997             /* No non-CONST_DOUBLE constant should ever appear here.  */
998             abort ();
999         }
1000       else
1001         {
1002           middlehalf[1] = operands[1];
1003           latehalf[1] = operands[1];
1004         }
1005     }
1006   else /* size is not 12: */
1007     {
1008       if (optype0 == REGOP)
1009         latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
1010       else if (optype0 == OFFSOP)
1011         latehalf[0] = adj_offsettable_operand (operands[0], 4);
1012       else
1013         latehalf[0] = operands[0];
1014
1015       if (optype1 == REGOP)
1016         latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
1017       else if (optype1 == OFFSOP)
1018         latehalf[1] = adj_offsettable_operand (operands[1], 4);
1019       else if (optype1 == CNSTOP)
1020         split_double (operands[1], &operands[1], &latehalf[1]);
1021       else
1022         latehalf[1] = operands[1];
1023     }
1024
1025   /* If insn is effectively movd N (sp),-(sp) then we will do the
1026      high word first.  We should use the adjusted operand 1
1027      (which is N+4 (sp) or N+8 (sp))
1028      for the low word and middle word as well,
1029      to compensate for the first decrement of sp.  */
1030   if (optype0 == PUSHOP
1031       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
1032       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
1033     middlehalf[1] = operands[1] = latehalf[1];
1034
1035   /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
1036      if the upper part of reg N does not appear in the MEM, arrange to
1037      emit the move late-half first.  Otherwise, compute the MEM address
1038      into the upper part of N and use that as a pointer to the memory
1039      operand.  */
1040   if (optype0 == REGOP
1041       && (optype1 == OFFSOP || optype1 == MEMOP))
1042     {
1043       if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
1044           && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1045         {
1046           /* If both halves of dest are used in the src memory address,
1047              compute the address into latehalf of dest.  */
1048 compadr:
1049           xops[0] = latehalf[0];
1050           xops[1] = XEXP (operands[1], 0);
1051           output_asm_insn (AS2 (lea%L0,%a1,%0), xops);
1052           if( GET_MODE (operands[1]) == XFmode )
1053             {
1054 /*          abort (); */
1055               operands[1] = gen_rtx (MEM, XFmode, latehalf[0]);
1056               middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
1057               latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1058             }
1059           else
1060             {
1061               operands[1] = gen_rtx (MEM, DImode, latehalf[0]);
1062               latehalf[1] = adj_offsettable_operand (operands[1], size-4);
1063             }
1064         }
1065       else if (size == 12
1066                  && reg_mentioned_p (middlehalf[0], XEXP (operands[1], 0)))
1067         {
1068           /* Check for two regs used by both source and dest. */
1069           if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
1070                 || reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
1071                 goto compadr;
1072
1073           /* JRV says this can't happen: */
1074           if (addreg0 || addreg1)
1075               abort();
1076
1077           /* Only the middle reg conflicts; simply put it last. */
1078           output_asm_insn (singlemove_string (operands), operands);
1079           output_asm_insn (singlemove_string (latehalf), latehalf);
1080           output_asm_insn (singlemove_string (middlehalf), middlehalf);
1081           return "";
1082         }
1083       else if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)))
1084         /* If the low half of dest is mentioned in the source memory
1085            address, the arrange to emit the move late half first.  */
1086         dest_overlapped_low = 1;
1087     }
1088
1089   /* If one or both operands autodecrementing,
1090      do the two words, high-numbered first.  */
1091
1092   /* Likewise,  the first move would clobber the source of the second one,
1093      do them in the other order.  This happens only for registers;
1094      such overlap can't happen in memory unless the user explicitly
1095      sets it up, and that is an undefined circumstance.  */
1096
1097 /*
1098   if (optype0 == PUSHOP || optype1 == PUSHOP
1099       || (optype0 == REGOP && optype1 == REGOP
1100           && REGNO (operands[0]) == REGNO (latehalf[1]))
1101       || dest_overlapped_low)
1102 */
1103   if (optype0 == PUSHOP || optype1 == PUSHOP
1104       || (optype0 == REGOP && optype1 == REGOP
1105           && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1]))
1106               || REGNO (operands[0]) == REGNO (latehalf[1])))
1107       || dest_overlapped_low)
1108     {
1109       /* Make any unoffsettable addresses point at high-numbered word.  */
1110       if (addreg0)
1111         asm_add (size-4, addreg0);
1112       if (addreg1)
1113         asm_add (size-4, addreg1);
1114
1115       /* Do that word.  */
1116       output_asm_insn (singlemove_string (latehalf), latehalf);
1117
1118       /* Undo the adds we just did.  */
1119       if (addreg0)
1120          asm_add (-4, addreg0);
1121       if (addreg1)
1122         asm_add (-4, addreg1);
1123
1124       if (size == 12)
1125         {
1126         output_asm_insn (singlemove_string (middlehalf), middlehalf);
1127         if (addreg0)
1128            asm_add (-4, addreg0);
1129         if (addreg1)
1130            asm_add (-4, addreg1);
1131         }
1132
1133       /* Do low-numbered word.  */
1134       return singlemove_string (operands);
1135     }
1136
1137   /* Normal case: do the two words, low-numbered first.  */
1138
1139   output_asm_insn (singlemove_string (operands), operands);
1140
1141   /* Do the middle one of the three words for long double */
1142   if (size == 12)
1143     {
1144       if (addreg0)
1145         asm_add (4, addreg0);
1146       if (addreg1)
1147         asm_add (4, addreg1);
1148
1149       output_asm_insn (singlemove_string (middlehalf), middlehalf);
1150     }
1151
1152   /* Make any unoffsettable addresses point at high-numbered word.  */
1153   if (addreg0)
1154     asm_add (4, addreg0);
1155   if (addreg1)
1156     asm_add (4, addreg1);
1157
1158   /* Do that word.  */
1159   output_asm_insn (singlemove_string (latehalf), latehalf);
1160
1161   /* Undo the adds we just did.  */
1162   if (addreg0)
1163     asm_add (4-size, addreg0);
1164   if (addreg1)
1165     asm_add (4-size, addreg1);
1166
1167   return "";
1168 }
1169
1170 \f
1171 #define MAX_TMPS 2              /* max temporary registers used */
1172
1173 /* Output the appropriate code to move push memory on the stack */
1174
1175 char *
1176 output_move_pushmem (operands, insn, length, tmp_start, n_operands)
1177      rtx operands[];
1178      rtx insn;
1179      int length;
1180      int tmp_start;
1181      int n_operands;
1182 {
1183
1184   struct {
1185     char *load;
1186     char *push;
1187     rtx   xops[2];
1188   } tmp_info[MAX_TMPS];
1189
1190   rtx src = operands[1];
1191   int max_tmps = 0;
1192   int offset = 0;
1193   int stack_p = reg_overlap_mentioned_p (stack_pointer_rtx, src);
1194   int stack_offset = 0;
1195   int i, num_tmps;
1196   rtx xops[1];
1197
1198   if (!offsettable_memref_p (src))
1199     fatal_insn ("Source is not offsettable", insn);
1200
1201   if ((length & 3) != 0)
1202     fatal_insn ("Pushing non-word aligned size", insn);
1203
1204   /* Figure out which temporary registers we have available */
1205   for (i = tmp_start; i < n_operands; i++)
1206     {
1207       if (GET_CODE (operands[i]) == REG)
1208         {
1209           if (reg_overlap_mentioned_p (operands[i], src))
1210             continue;
1211
1212           tmp_info[ max_tmps++ ].xops[1] = operands[i];
1213           if (max_tmps == MAX_TMPS)
1214             break;
1215         }
1216     }
1217
1218   if (max_tmps == 0)
1219     for (offset = length - 4; offset >= 0; offset -= 4)
1220       {
1221         xops[0] = adj_offsettable_operand (src, offset + stack_offset);
1222         output_asm_insn (AS1(push%L0,%0), xops);
1223         if (stack_p)
1224           stack_offset += 4;
1225       }
1226
1227   else
1228     for (offset = length - 4; offset >= 0; )
1229       {
1230         for (num_tmps = 0; num_tmps < max_tmps && offset >= 0; num_tmps++)
1231           {
1232             tmp_info[num_tmps].load    = AS2(mov%L0,%0,%1);
1233             tmp_info[num_tmps].push    = AS1(push%L0,%1);
1234             tmp_info[num_tmps].xops[0] = adj_offsettable_operand (src, offset + stack_offset);
1235             offset -= 4;
1236           }
1237
1238         for (i = 0; i < num_tmps; i++)
1239           output_asm_insn (tmp_info[i].load, tmp_info[i].xops);
1240
1241         for (i = 0; i < num_tmps; i++)
1242           output_asm_insn (tmp_info[i].push, tmp_info[i].xops);
1243
1244         if (stack_p)
1245           stack_offset += 4*num_tmps;
1246       }
1247
1248   return "";
1249 }
1250
1251 \f
1252
1253 /* Output the appropriate code to move data between two memory locations */
1254
1255 char *
1256 output_move_memory (operands, insn, length, tmp_start, n_operands)
1257      rtx operands[];
1258      rtx insn;
1259      int length;
1260      int tmp_start;
1261      int n_operands;
1262 {
1263   struct {
1264     char *load;
1265     char *store;
1266     rtx   xops[3];
1267   } tmp_info[MAX_TMPS];
1268
1269   rtx dest = operands[0];
1270   rtx src  = operands[1];
1271   rtx qi_tmp = NULL_RTX;
1272   int max_tmps = 0;
1273   int offset = 0;
1274   int i, num_tmps;
1275   rtx xops[3];
1276
1277   if (GET_CODE (dest) == MEM
1278       && GET_CODE (XEXP (dest, 0)) == PRE_INC
1279       && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
1280     return output_move_pushmem (operands, insn, length, tmp_start, n_operands);
1281
1282   if (!offsettable_memref_p (src))
1283     fatal_insn ("Source is not offsettable", insn);
1284
1285   if (!offsettable_memref_p (dest))
1286     fatal_insn ("Destination is not offsettable", insn);
1287
1288   /* Figure out which temporary registers we have available */
1289   for (i = tmp_start; i < n_operands; i++)
1290     {
1291       if (GET_CODE (operands[i]) == REG)
1292         {
1293           if ((length & 1) != 0 && !qi_tmp && QI_REG_P (operands[i]))
1294             qi_tmp = operands[i];
1295
1296           if (reg_overlap_mentioned_p (operands[i], dest))
1297             fatal_insn ("Temporary register overlaps the destination", insn);
1298
1299           if (reg_overlap_mentioned_p (operands[i], src))
1300             fatal_insn ("Temporary register overlaps the source", insn);
1301
1302           tmp_info[ max_tmps++ ].xops[2] = operands[i];
1303           if (max_tmps == MAX_TMPS)
1304             break;
1305         }
1306     }
1307
1308   if (max_tmps == 0)
1309     fatal_insn ("No scratch registers were found to do memory->memory moves", insn);
1310
1311   if ((length & 1) != 0)
1312     {
1313       if (!qi_tmp)
1314         fatal_insn ("No byte register found when moving odd # of bytes.", insn);
1315     }
1316
1317   while (length > 1)
1318     {
1319       for (num_tmps = 0; num_tmps < max_tmps; num_tmps++)
1320         {
1321           if (length >= 4)
1322             {
1323               tmp_info[num_tmps].load    = AS2(mov%L0,%1,%2);
1324               tmp_info[num_tmps].store   = AS2(mov%L0,%2,%0);
1325               tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset);
1326               tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset);
1327               offset += 4;
1328               length -= 4;
1329             }
1330           else if (length >= 2)
1331             {
1332               tmp_info[num_tmps].load    = AS2(mov%W0,%1,%2);
1333               tmp_info[num_tmps].store   = AS2(mov%W0,%2,%0);
1334               tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset);
1335               tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset);
1336               offset += 2;
1337               length -= 2;
1338             }
1339           else
1340             break;
1341         }
1342
1343       for (i = 0; i < num_tmps; i++)
1344         output_asm_insn (tmp_info[i].load, tmp_info[i].xops);
1345
1346       for (i = 0; i < num_tmps; i++)
1347         output_asm_insn (tmp_info[i].store, tmp_info[i].xops);
1348     }
1349
1350   if (length == 1)
1351     {
1352       xops[0] = adj_offsettable_operand (dest, offset);
1353       xops[1] = adj_offsettable_operand (src, offset);
1354       xops[2] = qi_tmp;
1355       output_asm_insn (AS2(mov%B0,%1,%2), xops);
1356       output_asm_insn (AS2(mov%B0,%2,%0), xops);
1357     }
1358
1359   return "";
1360 }
1361
1362 \f
1363 int
1364 standard_80387_constant_p (x)
1365      rtx x;
1366 {
1367 #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
1368   REAL_VALUE_TYPE d;
1369   jmp_buf handler;
1370   int is0, is1;
1371
1372   if (setjmp (handler))
1373     return 0;
1374
1375   set_float_handler (handler);
1376   REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1377   is0 = REAL_VALUES_EQUAL (d, dconst0) && !REAL_VALUE_MINUS_ZERO (d);
1378   is1 = REAL_VALUES_EQUAL (d, dconst1);
1379   set_float_handler (NULL_PTR);
1380
1381   if (is0)
1382     return 1;
1383
1384   if (is1)
1385     return 2;
1386
1387   /* Note that on the 80387, other constants, such as pi,
1388      are much slower to load as standard constants
1389      than to load from doubles in memory!  */
1390 #endif
1391
1392   return 0;
1393 }
1394
1395 char *
1396 output_move_const_single (operands)
1397      rtx *operands;
1398 {
1399   if (FP_REG_P (operands[0]))
1400     {
1401       int conval = standard_80387_constant_p (operands[1]);
1402
1403       if (conval == 1)
1404         return "fldz";
1405
1406       if (conval == 2)
1407         return "fld1";
1408     }
1409   if (GET_CODE (operands[1]) == CONST_DOUBLE)
1410     {
1411       REAL_VALUE_TYPE r; long l;
1412
1413       if (GET_MODE (operands[1]) == XFmode)
1414         abort ();
1415
1416       REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
1417       REAL_VALUE_TO_TARGET_SINGLE (r, l);
1418       operands[1] = GEN_INT (l);
1419     }
1420   return singlemove_string (operands);
1421 }
1422 \f
1423 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
1424    reference and a constant.  */
1425
1426 int
1427 symbolic_operand (op, mode)
1428      register rtx op;
1429      enum machine_mode mode;
1430 {
1431   switch (GET_CODE (op))
1432     {
1433     case SYMBOL_REF:
1434     case LABEL_REF:
1435       return 1;
1436     case CONST:
1437       op = XEXP (op, 0);
1438       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1439                || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1440               && GET_CODE (XEXP (op, 1)) == CONST_INT);
1441     default:
1442       return 0;
1443     }
1444 }
1445
1446 /* Test for a valid operand for a call instruction.
1447    Don't allow the arg pointer register or virtual regs
1448    since they may change into reg + const, which the patterns
1449    can't handle yet.  */
1450
1451 int
1452 call_insn_operand (op, mode)
1453      rtx op;
1454      enum machine_mode mode;
1455 {
1456   if (GET_CODE (op) == MEM
1457       && ((CONSTANT_ADDRESS_P (XEXP (op, 0))
1458            /* This makes a difference for PIC.  */
1459            && general_operand (XEXP (op, 0), Pmode))
1460           || (GET_CODE (XEXP (op, 0)) == REG
1461               && XEXP (op, 0) != arg_pointer_rtx
1462               && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
1463                    && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
1464     return 1;
1465   return 0;
1466 }
1467
1468 /* Like call_insn_operand but allow (mem (symbol_ref ...))
1469    even if pic.  */
1470
1471 int
1472 expander_call_insn_operand (op, mode)
1473      rtx op;
1474      enum machine_mode mode;
1475 {
1476   if (GET_CODE (op) == MEM
1477       && (CONSTANT_ADDRESS_P (XEXP (op, 0))
1478           || (GET_CODE (XEXP (op, 0)) == REG
1479               && XEXP (op, 0) != arg_pointer_rtx
1480               && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
1481                    && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
1482     return 1;
1483   return 0;
1484 }
1485
1486 /* Return 1 if OP is a comparison operator that can use the condition code
1487    generated by an arithmetic operation. */
1488
1489 int
1490 arithmetic_comparison_operator (op, mode)
1491      register rtx op;
1492      enum machine_mode mode;
1493 {
1494   enum rtx_code code;
1495
1496   if (mode != VOIDmode && mode != GET_MODE (op))
1497     return 0;
1498   code = GET_CODE (op);
1499   if (GET_RTX_CLASS (code) != '<')
1500     return 0;
1501
1502   return (code != GT && code != LE);
1503 }
1504 \f
1505 /* Returns 1 if OP contains a symbol reference */
1506
1507 int
1508 symbolic_reference_mentioned_p (op)
1509      rtx op;
1510 {
1511   register char *fmt;
1512   register int i;
1513
1514   if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1515     return 1;
1516
1517   fmt = GET_RTX_FORMAT (GET_CODE (op));
1518   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1519     {
1520       if (fmt[i] == 'E')
1521         {
1522           register int j;
1523
1524           for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1525             if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1526               return 1;
1527         }
1528       else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1529         return 1;
1530     }
1531
1532   return 0;
1533 }
1534 \f
1535 /* Attempt to expand a binary operator.  Make the expansion closer to the
1536    actual machine, then just general_operand, which will allow 3 separate
1537    memory references (one output, two input) in a single insn.  Return
1538    whether the insn fails, or succeeds.  */
1539
1540 int
1541 ix86_expand_binary_operator (code, mode, operands)
1542      enum rtx_code code;
1543      enum machine_mode mode;
1544      rtx operands[];
1545 {
1546   rtx insn;
1547   int i;
1548   int modified;
1549
1550   /* Recognize <var1> = <value> <op> <var1> for commutative operators */
1551   if (GET_RTX_CLASS (code) == 'c'
1552       && (rtx_equal_p (operands[0], operands[2])
1553           || immediate_operand (operands[1], mode)))
1554     {
1555       rtx temp = operands[1];
1556       operands[1] = operands[2];
1557       operands[2] = temp;
1558     }
1559
1560   /* If optimizing, copy to regs to improve CSE */
1561   if (TARGET_PSEUDO && optimize && ((reload_in_progress | reload_completed) == 0))
1562     {
1563       if (GET_CODE (operands[1]) == MEM && !rtx_equal_p (operands[0], operands[1]))
1564         operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
1565
1566       if (GET_CODE (operands[2]) == MEM)
1567         operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
1568
1569       if (GET_CODE (operands[1]) == CONST_INT && code == MINUS)
1570         {
1571           rtx temp = gen_reg_rtx (GET_MODE (operands[0]));
1572           emit_move_insn (temp, operands[1]);
1573           operands[1] = temp;
1574           return TRUE;
1575         }         
1576     }
1577
1578   if (!ix86_binary_operator_ok (code, mode, operands))
1579     {
1580       /* If not optimizing, try to make a valid insn (optimize code previously did
1581          this above to improve chances of CSE) */
1582
1583       if ((!TARGET_PSEUDO || !optimize)
1584           && ((reload_in_progress | reload_completed) == 0)
1585           && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM))
1586         {
1587           modified = FALSE;
1588           if (GET_CODE (operands[1]) == MEM && !rtx_equal_p (operands[0], operands[1]))
1589             {
1590               operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
1591               modified = TRUE;
1592             }
1593
1594           if (GET_CODE (operands[2]) == MEM)
1595             {
1596               operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
1597               modified = TRUE;
1598             }
1599
1600           if (GET_CODE (operands[1]) == CONST_INT && code == MINUS)
1601             {
1602               rtx temp = gen_reg_rtx (GET_MODE (operands[0]));
1603               emit_move_insn (temp, operands[1]);
1604               operands[1] = temp;
1605               return TRUE;
1606             }     
1607
1608           if (modified && !ix86_binary_operator_ok (code, mode, operands))
1609             return FALSE;
1610         }
1611       else
1612         return FALSE;
1613     }
1614
1615   return TRUE;
1616 }
1617 \f
1618 /* Return TRUE or FALSE depending on whether the binary operator meets the
1619    appropriate constraints.  */
1620
1621 int
1622 ix86_binary_operator_ok (code, mode, operands)
1623      enum rtx_code code;
1624      enum machine_mode mode;
1625      rtx operands[3];
1626 {
1627   return (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
1628     && (GET_CODE (operands[1]) != CONST_INT || GET_RTX_CLASS (code) == 'c');
1629 }
1630 \f
1631 /* Attempt to expand a unary operator.  Make the expansion closer to the
1632    actual machine, then just general_operand, which will allow 2 separate
1633    memory references (one output, one input) in a single insn.  Return
1634    whether the insn fails, or succeeds.  */
1635
1636 int
1637 ix86_expand_unary_operator (code, mode, operands)
1638      enum rtx_code code;
1639      enum machine_mode mode;
1640      rtx operands[];
1641 {
1642   rtx insn;
1643
1644   /* If optimizing, copy to regs to improve CSE */
1645   if (TARGET_PSEUDO
1646       && optimize
1647       && ((reload_in_progress | reload_completed) == 0)
1648       && GET_CODE (operands[1]) == MEM)
1649     {
1650       operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
1651     }
1652
1653   if (!ix86_unary_operator_ok (code, mode, operands))
1654     {
1655       if ((!TARGET_PSEUDO || !optimize)
1656           && ((reload_in_progress | reload_completed) == 0)
1657           && GET_CODE (operands[1]) == MEM)
1658         {
1659           operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
1660           if (!ix86_unary_operator_ok (code, mode, operands))
1661             return FALSE;
1662         }
1663       else
1664         return FALSE;
1665     }
1666
1667   return TRUE;
1668 }
1669 \f
1670 /* Return TRUE or FALSE depending on whether the unary operator meets the
1671    appropriate constraints.  */
1672
1673 int
1674 ix86_unary_operator_ok (code, mode, operands)
1675      enum rtx_code code;
1676      enum machine_mode mode;
1677      rtx operands[2];
1678 {
1679   return TRUE;
1680 }
1681
1682 \f
1683
1684 static rtx pic_label_rtx;
1685
1686 /* This function generates code for -fpic that loads %ebx with
1687    with the return address of the caller and then returns.  */
1688 void
1689 asm_output_function_prefix (file, name)
1690     FILE * file;
1691     char * name;
1692 {
1693   rtx xops[2];
1694   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1695                                   || current_function_uses_const_pool);
1696   xops[0] = pic_offset_table_rtx;
1697   xops[1] = stack_pointer_rtx;
1698
1699   /* deep branch prediction favors having a return for every call */
1700   if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)
1701     {
1702       if (pic_label_rtx == 0)
1703       pic_label_rtx = (rtx) gen_label_rtx ();
1704       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (pic_label_rtx));
1705       output_asm_insn ("movl (%1),%0", xops);
1706       output_asm_insn ("ret", xops);
1707     }
1708 }
1709
1710 /* Set up the stack and frame (if desired) for the function.  */
1711
1712 void
1713 function_prologue (file, size)
1714      FILE *file;
1715      int size;
1716 {
1717   register int regno;
1718   int limit;
1719   rtx xops[4];
1720   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1721                                   || current_function_uses_const_pool);
1722   long tsize = get_frame_size ();
1723
1724   /* pic references don't explicitly mention pic_offset_table_rtx */
1725   if (TARGET_SCHEDULE_PROLOGUE)
1726     return;
1727   
1728   xops[0] = stack_pointer_rtx;
1729   xops[1] = frame_pointer_rtx;
1730   xops[2] = GEN_INT (tsize);
1731   if (frame_pointer_needed)
1732     {
1733       output_asm_insn ("push%L1 %1", xops); 
1734       output_asm_insn (AS2 (mov%L0,%0,%1), xops); 
1735     }
1736
1737   if (tsize)
1738     output_asm_insn (AS2 (sub%L0,%2,%0), xops);
1739
1740   /* Note If use enter it is NOT reversed args.
1741      This one is not reversed from intel!!
1742      I think enter is slower.  Also sdb doesn't like it.
1743      But if you want it the code is:
1744      {
1745      xops[3] = const0_rtx;
1746      output_asm_insn ("enter %2,%3", xops);
1747      }
1748      */
1749   limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
1750   for (regno = limit - 1; regno >= 0; regno--)
1751     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1752         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1753       {
1754         xops[0] = gen_rtx (REG, SImode, regno);
1755         output_asm_insn ("push%L0 %0", xops);
1756       }
1757
1758   if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)
1759     {
1760       xops[0] = pic_offset_table_rtx;
1761       if (pic_label_rtx == 0)
1762         pic_label_rtx = (rtx) gen_label_rtx ();
1763       xops[1] = pic_label_rtx;
1764
1765       output_asm_insn (AS1 (call,%P1), xops);
1766       output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_,%0", xops);
1767     }
1768   else if (pic_reg_used)
1769     {
1770     xops[0] = pic_offset_table_rtx;
1771     xops[1] = (rtx) gen_label_rtx ();
1772  
1773       output_asm_insn (AS1 (call,%P1), xops);
1774       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));
1775       output_asm_insn (AS1 (pop%L0,%0), xops);
1776       output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops);
1777   } 
1778 }
1779
1780 /* This function generates the assembly code for function entry.
1781    FILE is an stdio stream to output the code to.
1782    SIZE is an int: how many units of temporary storage to allocate. */
1783
1784 void
1785 ix86_expand_prologue ()
1786 {
1787   register int regno;
1788   int limit;
1789   rtx xops[4];
1790   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1791                                   || current_function_uses_const_pool);
1792   long tsize = get_frame_size ();
1793
1794   if (!TARGET_SCHEDULE_PROLOGUE)
1795     return;
1796   
1797   xops[0] = stack_pointer_rtx;
1798   xops[1] = frame_pointer_rtx;
1799   xops[2] = GEN_INT (tsize);
1800   if (frame_pointer_needed)
1801     {
1802       emit_insn (gen_rtx (SET, 0,
1803                           gen_rtx (MEM, SImode,
1804                                    gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
1805                           frame_pointer_rtx));
1806       emit_move_insn (xops[1], xops[0]);
1807     }
1808
1809   if (tsize)
1810     emit_insn (gen_rtx (SET, SImode,
1811                           xops[0],
1812                           gen_rtx (MINUS, SImode,
1813                                    xops[0],
1814                                    xops[2])));
1815
1816   /* Note If use enter it is NOT reversed args.
1817      This one is not reversed from intel!!
1818      I think enter is slower.  Also sdb doesn't like it.
1819      But if you want it the code is:
1820      {
1821      xops[3] = const0_rtx;
1822      output_asm_insn ("enter %2,%3", xops);
1823      }
1824      */
1825   limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
1826   for (regno = limit - 1; regno >= 0; regno--)
1827     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1828         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1829       {
1830         xops[0] = gen_rtx (REG, SImode, regno);
1831         emit_insn (gen_rtx (SET, 0,
1832                             gen_rtx (MEM, SImode,
1833                                      gen_rtx (PRE_DEC, SImode, stack_pointer_rtx)),
1834                           xops[0]));
1835       }
1836
1837   if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)
1838     {
1839       xops[0] = pic_offset_table_rtx;
1840       if (pic_label_rtx == 0)
1841         pic_label_rtx = (rtx) gen_label_rtx ();
1842       xops[1] = pic_label_rtx;
1843
1844       emit_insn (gen_prologue_get_pc (xops[0], gen_rtx (CONST_INT, Pmode, CODE_LABEL_NUMBER(xops[1]))));
1845       emit_insn (gen_prologue_set_got (xops[0], 
1846                  gen_rtx (SYMBOL_REF, Pmode, "$_GLOBAL_OFFSET_TABLE_"), 
1847                  gen_rtx (CONST_INT, Pmode, CODE_LABEL_NUMBER(xops[1]))));
1848     }
1849   else if (pic_reg_used)
1850     {
1851     xops[0] = pic_offset_table_rtx;
1852     xops[1] = (rtx) gen_label_rtx ();
1853  
1854       emit_insn (gen_prologue_get_pc (xops[0], gen_rtx (CONST_INT, Pmode, CODE_LABEL_NUMBER(xops[1]))));
1855       emit_insn (gen_pop (xops[0]));
1856       emit_insn (gen_prologue_set_got (xops[0], 
1857                  gen_rtx (SYMBOL_REF, Pmode, "$_GLOBAL_OFFSET_TABLE_"), 
1858                  gen_rtx (CONST_INT, Pmode, CODE_LABEL_NUMBER (xops[1]))));
1859   } 
1860 }
1861
1862 /* Restore function stack, frame, and registers. */ 
1863
1864 void
1865 function_epilogue (file, size)
1866      FILE *file;
1867      int size;
1868 {
1869 }
1870
1871 /* Return 1 if it is appropriate to emit `ret' instructions in the
1872    body of a function.  Do this only if the epilogue is simple, needing a
1873    couple of insns.  Prior to reloading, we can't tell how many registers
1874    must be saved, so return 0 then.  Return 0 if there is no frame 
1875    marker to de-allocate.
1876
1877    If NON_SAVING_SETJMP is defined and true, then it is not possible
1878    for the epilogue to be simple, so return 0.  This is a special case
1879    since NON_SAVING_SETJMP will not cause regs_ever_live to change
1880    until final, but jump_optimize may need to know sooner if a
1881    `return' is OK.  */
1882
1883 int
1884 ix86_can_use_return_insn_p ()
1885 {
1886   int regno;
1887   int nregs = 0;
1888   int reglimit = (frame_pointer_needed
1889                   ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
1890   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1891                                   || current_function_uses_const_pool);
1892
1893 #ifdef NON_SAVING_SETJMP
1894   if (NON_SAVING_SETJMP && current_function_calls_setjmp)
1895     return 0;
1896 #endif
1897
1898   if (! reload_completed)
1899     return 0;
1900
1901   for (regno = reglimit - 1; regno >= 0; regno--)
1902     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1903         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1904       nregs++;
1905
1906   return nregs == 0 || ! frame_pointer_needed;
1907 }
1908
1909 \f
1910 /* This function generates the assembly code for function exit.
1911    FILE is an stdio stream to output the code to.
1912    SIZE is an int: how many units of temporary storage to deallocate. */
1913
1914 void
1915 ix86_expand_epilogue ()
1916 {
1917   register int regno;
1918   register int nregs, limit;
1919   int offset;
1920   rtx xops[3];
1921   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1922                                   || current_function_uses_const_pool);
1923   long tsize = get_frame_size ();
1924
1925   /* Compute the number of registers to pop */
1926
1927   limit = (frame_pointer_needed
1928            ? FRAME_POINTER_REGNUM
1929            : STACK_POINTER_REGNUM);
1930
1931   nregs = 0;
1932
1933   for (regno = limit - 1; regno >= 0; regno--)
1934     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1935         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1936       nregs++;
1937
1938   /* sp is often  unreliable so we must go off the frame pointer,
1939    */
1940
1941   /* In reality, we may not care if sp is unreliable, because we can
1942      restore the register relative to the frame pointer.  In theory,
1943      since each move is the same speed as a pop, and we don't need the
1944      leal, this is faster.  For now restore multiple registers the old
1945      way. */
1946
1947   offset = -tsize - (nregs * UNITS_PER_WORD);
1948
1949   xops[2] = stack_pointer_rtx;
1950
1951   if (nregs > 1 || ! frame_pointer_needed)
1952     {
1953       if (frame_pointer_needed)
1954         {
1955           xops[0] = adj_offsettable_operand (AT_BP (QImode), offset);
1956           emit_insn (gen_movsi_lea (xops[2], XEXP (xops[0], 0)));
1957 /*        output_asm_insn (AS2 (lea%L2,%0,%2), xops);*/
1958         }
1959
1960       for (regno = 0; regno < limit; regno++)
1961         if ((regs_ever_live[regno] && ! call_used_regs[regno])
1962             || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1963           {
1964             xops[0] = gen_rtx (REG, SImode, regno);
1965             emit_insn (gen_pop (xops[0]));
1966 /*          output_asm_insn ("pop%L0 %0", xops);*/
1967           }
1968     }
1969   else
1970     for (regno = 0; regno < limit; regno++)
1971       if ((regs_ever_live[regno] && ! call_used_regs[regno])
1972           || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1973         {
1974           xops[0] = gen_rtx (REG, SImode, regno);
1975           xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset);
1976           emit_move_insn (xops[0], xops[1]);
1977 /*        output_asm_insn (AS2 (mov%L0,%1,%0), xops);*/
1978           offset += 4;
1979         }
1980
1981   if (frame_pointer_needed)
1982     {
1983       /* If not an i386, mov & pop is faster than "leave". */
1984
1985       if (TARGET_USE_LEAVE)
1986         emit_insn (gen_leave());
1987 /*      output_asm_insn ("leave", xops);*/
1988       else
1989         {
1990           xops[0] = frame_pointer_rtx;
1991           xops[1] = stack_pointer_rtx;
1992           emit_insn (gen_epilogue_set_stack_ptr());
1993 /*        output_asm_insn (AS2 (mov%L2,%0,%2), xops);*/
1994           emit_insn (gen_pop (xops[0]));
1995 /*        output_asm_insn ("pop%L0 %0", xops);*/
1996         }
1997     }
1998   else if (tsize)
1999     {
2000       /* If there is no frame pointer, we must still release the frame. */
2001
2002       xops[0] = GEN_INT (tsize);
2003       emit_insn (gen_rtx (SET, SImode,
2004                           xops[2],
2005                           gen_rtx (PLUS, SImode,
2006                                    xops[2],
2007                                    xops[0])));
2008 /*      output_asm_insn (AS2 (add%L2,%0,%2), xops);*/
2009     }
2010
2011 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
2012   if (profile_block_flag == 2)
2013     {
2014       FUNCTION_BLOCK_PROFILER_EXIT(file);
2015     }
2016 #endif
2017
2018   if (current_function_pops_args && current_function_args_size)
2019     {
2020       xops[1] = GEN_INT (current_function_pops_args);
2021
2022       /* i386 can only pop 32K bytes (maybe 64K?  Is it signed?).  If
2023          asked to pop more, pop return address, do explicit add, and jump
2024          indirectly to the caller. */
2025
2026       if (current_function_pops_args >= 32768)
2027         {
2028           /* ??? Which register to use here? */
2029           xops[0] = gen_rtx (REG, SImode, 2);
2030           emit_insn (gen_pop (xops[0]));
2031 /*        output_asm_insn ("pop%L0 %0", xops);*/
2032           emit_insn (gen_rtx (SET, SImode,
2033                               xops[2],
2034                               gen_rtx (PLUS, SImode,
2035                                        xops[1],
2036                                        xops[2])));
2037 /*        output_asm_insn (AS2 (add%L2,%1,%2), xops);*/
2038           emit_jump_insn (xops[0]);
2039 /*        output_asm_insn ("jmp %*%0", xops);*/
2040         }
2041       else
2042         emit_jump_insn (gen_return_pop_internal (xops[1]));
2043 /*        output_asm_insn ("ret %1", xops);*/
2044     }
2045   else
2046 /*    output_asm_insn ("ret", xops);*/
2047  emit_jump_insn (gen_return_internal ());
2048 }
2049
2050 \f
2051 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
2052    that is a valid memory address for an instruction.
2053    The MODE argument is the machine mode for the MEM expression
2054    that wants to use this address.
2055
2056    On x86, legitimate addresses are:
2057         base                            movl (base),reg
2058         displacement                    movl disp,reg
2059         base + displacement             movl disp(base),reg
2060         index + base                    movl (base,index),reg
2061         (index + base) + displacement   movl disp(base,index),reg
2062         index*scale                     movl (,index,scale),reg
2063         index*scale + disp              movl disp(,index,scale),reg
2064         index*scale + base              movl (base,index,scale),reg
2065         (index*scale + base) + disp     movl disp(base,index,scale),reg
2066
2067         In each case, scale can be 1, 2, 4, 8.  */
2068
2069 /* This is exactly the same as print_operand_addr, except that
2070    it recognizes addresses instead of printing them.
2071
2072    It only recognizes address in canonical form.  LEGITIMIZE_ADDRESS should
2073    convert common non-canonical forms to canonical form so that they will
2074    be recognized.  */
2075
2076 #define ADDR_INVALID(msg,insn)                                          \
2077 do {                                                                    \
2078   if (TARGET_DEBUG_ADDR)                                                \
2079     {                                                                   \
2080       fprintf (stderr, msg);                                            \
2081       debug_rtx (insn);                                                 \
2082     }                                                                   \
2083 } while (0)
2084
2085 int
2086 legitimate_address_p (mode, addr, strict)
2087      enum machine_mode mode;
2088      register rtx addr;
2089      int strict;
2090 {
2091   rtx base  = NULL_RTX;
2092   rtx indx  = NULL_RTX;
2093   rtx scale = NULL_RTX;
2094   rtx disp  = NULL_RTX;
2095
2096   if (TARGET_DEBUG_ADDR)
2097     {
2098       fprintf (stderr,
2099                "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
2100                GET_MODE_NAME (mode), strict);
2101
2102       debug_rtx (addr);
2103     }
2104
2105   if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
2106       base = addr;                              /* base reg */
2107
2108   else if (GET_CODE (addr) == PLUS)
2109     {
2110       rtx op0 = XEXP (addr, 0);
2111       rtx op1 = XEXP (addr, 1);
2112       enum rtx_code code0 = GET_CODE (op0);
2113       enum rtx_code code1 = GET_CODE (op1);
2114
2115       if (code0 == REG || code0 == SUBREG)
2116         {
2117           if (code1 == REG || code1 == SUBREG)
2118             {
2119               indx = op0;                       /* index + base */
2120               base = op1;
2121             }
2122
2123           else
2124             {
2125               base = op0;                       /* base + displacement */
2126               disp = op1;
2127             }
2128         }
2129
2130       else if (code0 == MULT)
2131         {
2132           indx  = XEXP (op0, 0);
2133           scale = XEXP (op0, 1);
2134
2135           if (code1 == REG || code1 == SUBREG)
2136             base = op1;                         /* index*scale + base */
2137
2138           else
2139             disp = op1;                         /* index*scale + disp */
2140         }
2141
2142       else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)
2143         {
2144           indx  = XEXP (XEXP (op0, 0), 0);      /* index*scale + base + disp */
2145           scale = XEXP (XEXP (op0, 0), 1);
2146           base  = XEXP (op0, 1);
2147           disp  = op1;
2148         }
2149
2150       else if (code0 == PLUS)
2151         {
2152           indx = XEXP (op0, 0);                 /* index + base + disp */
2153           base = XEXP (op0, 1);
2154           disp = op1;
2155         }
2156
2157       else
2158         {
2159           ADDR_INVALID ("PLUS subcode is not valid.\n", op0);
2160           return FALSE;
2161         }
2162     }
2163
2164   else if (GET_CODE (addr) == MULT)
2165     {
2166       indx  = XEXP (addr, 0);                   /* index*scale */
2167       scale = XEXP (addr, 1);
2168     }
2169
2170   else
2171     disp = addr;                                /* displacement */
2172
2173   /* Allow arg pointer and stack pointer as index if there is not scaling */
2174   if (base && indx && !scale
2175       && (indx == arg_pointer_rtx || indx == stack_pointer_rtx))
2176     {
2177       rtx tmp = base;
2178       base = indx;
2179       indx = tmp;
2180     }
2181
2182   /* Validate base register */
2183   /* Don't allow SUBREG's here, it can lead to spill failures when the base
2184      is one word out of a two word structure, which is represented internally
2185      as a DImode int.  */
2186   if (base)
2187     {
2188       if (GET_CODE (base) != REG)
2189         {
2190           ADDR_INVALID ("Base is not a register.\n", base);
2191           return FALSE;
2192         }
2193
2194       if ((strict && !REG_OK_FOR_BASE_STRICT_P (base))
2195           || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base)))
2196         {
2197           ADDR_INVALID ("Base is not valid.\n", base);
2198           return FALSE;
2199         }
2200     }
2201
2202   /* Validate index register */
2203   /* Don't allow SUBREG's here, it can lead to spill failures when the index
2204      is one word out of a two word structure, which is represented internally
2205      as a DImode int.  */
2206   if (indx)
2207     {
2208       if (GET_CODE (indx) != REG)
2209         {
2210           ADDR_INVALID ("Index is not a register.\n", indx);
2211           return FALSE;
2212         }
2213
2214       if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx))
2215           || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx)))
2216         {
2217           ADDR_INVALID ("Index is not valid.\n", indx);
2218           return FALSE;
2219         }
2220     }
2221   else if (scale)
2222     abort ();                                   /* scale w/o index invalid */
2223
2224   /* Validate scale factor */
2225   if (scale)
2226     {
2227       HOST_WIDE_INT value;
2228
2229       if (GET_CODE (scale) != CONST_INT)
2230         {
2231           ADDR_INVALID ("Scale is not valid.\n", scale);
2232           return FALSE;
2233         }
2234
2235       value = INTVAL (scale);
2236       if (value != 1 && value != 2 && value != 4 && value != 8)
2237         {
2238           ADDR_INVALID ("Scale is not a good multiplier.\n", scale);
2239           return FALSE;
2240         }
2241     }
2242
2243   /* Validate displacement
2244      Constant pool addresses must be handled special.  They are
2245      considered legitimate addresses, but only if not used with regs.
2246      When printed, the output routines know to print the reference with the
2247      PIC reg, even though the PIC reg doesn't appear in the RTL. */
2248   if (disp)
2249     {
2250       if (GET_CODE (disp) == SYMBOL_REF
2251           && CONSTANT_POOL_ADDRESS_P (disp)
2252           && !base
2253           && !indx)
2254         ;
2255
2256       else if (!CONSTANT_ADDRESS_P (disp))
2257         {
2258           ADDR_INVALID ("Displacement is not valid.\n", disp);
2259           return FALSE;
2260         }
2261
2262       else if (GET_CODE (disp) == CONST_DOUBLE)
2263         {
2264           ADDR_INVALID ("Displacement is a const_double.\n", disp);
2265           return FALSE;
2266         }
2267
2268       else if (flag_pic && SYMBOLIC_CONST (disp)
2269                && base != pic_offset_table_rtx
2270                && (indx != pic_offset_table_rtx || scale != NULL_RTX))
2271         {
2272           ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
2273           return FALSE;
2274         }
2275
2276       else if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
2277                && (base != NULL_RTX || indx != NULL_RTX))
2278         {
2279           ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp);
2280           return FALSE;
2281         }
2282     }
2283
2284   if (TARGET_DEBUG_ADDR)
2285     fprintf (stderr, "Address is valid.\n");
2286
2287   /* Everything looks valid, return true */
2288   return TRUE;
2289 }
2290
2291 \f
2292 /* Return a legitimate reference for ORIG (an address) using the
2293    register REG.  If REG is 0, a new pseudo is generated.
2294
2295    There are three types of references that must be handled:
2296
2297    1. Global data references must load the address from the GOT, via
2298       the PIC reg.  An insn is emitted to do this load, and the reg is
2299       returned.
2300
2301    2. Static data references must compute the address as an offset
2302       from the GOT, whose base is in the PIC reg.  An insn is emitted to
2303       compute the address into a reg, and the reg is returned.  Static
2304       data objects have SYMBOL_REF_FLAG set to differentiate them from
2305       global data objects.
2306
2307    3. Constant pool addresses must be handled special.  They are
2308       considered legitimate addresses, but only if not used with regs.
2309       When printed, the output routines know to print the reference with the
2310       PIC reg, even though the PIC reg doesn't appear in the RTL.
2311
2312    GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
2313    reg also appears in the address (except for constant pool references,
2314    noted above).
2315
2316    "switch" statements also require special handling when generating
2317    PIC code.  See comments by the `casesi' insn in i386.md for details.  */
2318
2319 rtx
2320 legitimize_pic_address (orig, reg)
2321      rtx orig;
2322      rtx reg;
2323 {
2324   rtx addr = orig;
2325   rtx new = orig;
2326
2327   if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
2328     {
2329       if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
2330         reg = new = orig;
2331       else
2332         {
2333           if (reg == 0)
2334             reg = gen_reg_rtx (Pmode);
2335
2336           if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
2337               || GET_CODE (addr) == LABEL_REF)
2338             new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
2339           else
2340             new = gen_rtx (MEM, Pmode,
2341                            gen_rtx (PLUS, Pmode,
2342                                     pic_offset_table_rtx, orig));
2343
2344           emit_move_insn (reg, new);
2345         }
2346       current_function_uses_pic_offset_table = 1;
2347       return reg;
2348     }
2349   else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
2350     {
2351       rtx base;
2352
2353       if (GET_CODE (addr) == CONST)
2354         {
2355           addr = XEXP (addr, 0);
2356           if (GET_CODE (addr) != PLUS)
2357             abort ();
2358         }
2359
2360       if (XEXP (addr, 0) == pic_offset_table_rtx)
2361         return orig;
2362
2363       if (reg == 0)
2364         reg = gen_reg_rtx (Pmode);
2365
2366       base = legitimize_pic_address (XEXP (addr, 0), reg);
2367       addr = legitimize_pic_address (XEXP (addr, 1),
2368                                      base == reg ? NULL_RTX : reg);
2369
2370       if (GET_CODE (addr) == CONST_INT)
2371         return plus_constant (base, INTVAL (addr));
2372
2373       if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
2374         {
2375           base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
2376           addr = XEXP (addr, 1);
2377         }
2378         return gen_rtx (PLUS, Pmode, base, addr);
2379     }
2380   return new;
2381 }
2382 \f
2383
2384 /* Emit insns to move operands[1] into operands[0].  */
2385
2386 void
2387 emit_pic_move (operands, mode)
2388      rtx *operands;
2389      enum machine_mode mode;
2390 {
2391   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
2392
2393   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
2394     operands[1] = (rtx) force_reg (SImode, operands[1]);
2395   else
2396     operands[1] = legitimize_pic_address (operands[1], temp);
2397 }
2398
2399 \f
2400 /* Try machine-dependent ways of modifying an illegitimate address
2401    to be legitimate.  If we find one, return the new, valid address.
2402    This macro is used in only one place: `memory_address' in explow.c.
2403
2404    OLDX is the address as it was before break_out_memory_refs was called.
2405    In some cases it is useful to look at this to decide what needs to be done.
2406
2407    MODE and WIN are passed so that this macro can use
2408    GO_IF_LEGITIMATE_ADDRESS.
2409
2410    It is always safe for this macro to do nothing.  It exists to recognize
2411    opportunities to optimize the output.
2412
2413    For the 80386, we handle X+REG by loading X into a register R and
2414    using R+REG.  R will go in a general reg and indexing will be used.
2415    However, if REG is a broken-out memory address or multiplication,
2416    nothing needs to be done because REG can certainly go in a general reg.
2417
2418    When -fpic is used, special handling is needed for symbolic references.
2419    See comments by legitimize_pic_address in i386.c for details.  */
2420
2421 rtx
2422 legitimize_address (x, oldx, mode)
2423      register rtx x;
2424      register rtx oldx;
2425      enum machine_mode mode;
2426 {
2427   int changed = 0;
2428   unsigned log;
2429
2430   if (TARGET_DEBUG_ADDR)
2431     {
2432       fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode));
2433       debug_rtx (x);
2434     }
2435
2436   if (flag_pic && SYMBOLIC_CONST (x))
2437     return legitimize_pic_address (x, 0);
2438
2439   /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
2440   if (GET_CODE (x) == ASHIFT
2441       && GET_CODE (XEXP (x, 1)) == CONST_INT
2442       && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
2443     {
2444       changed = 1;
2445       x = gen_rtx (MULT, Pmode,
2446                    force_reg (Pmode, XEXP (x, 0)),
2447                    GEN_INT (1 << log));
2448     }
2449
2450   if (GET_CODE (x) == PLUS)
2451     {
2452       /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
2453       if (GET_CODE (XEXP (x, 0)) == ASHIFT
2454           && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
2455           && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4)
2456         {
2457           changed = 1;
2458           XEXP (x, 0) = gen_rtx (MULT, Pmode,
2459                                  force_reg (Pmode, XEXP (XEXP (x, 0), 0)),
2460                                  GEN_INT (1 << log));
2461         }
2462
2463       if (GET_CODE (XEXP (x, 1)) == ASHIFT
2464           && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
2465           && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4)
2466         {
2467           changed = 1;
2468           XEXP (x, 1) = gen_rtx (MULT, Pmode,
2469                                  force_reg (Pmode, XEXP (XEXP (x, 1), 0)),
2470                                  GEN_INT (1 << log));
2471         }
2472
2473       /* Put multiply first if it isn't already */
2474       if (GET_CODE (XEXP (x, 1)) == MULT)
2475         {
2476           rtx tmp = XEXP (x, 0);
2477           XEXP (x, 0) = XEXP (x, 1);
2478           XEXP (x, 1) = tmp;
2479           changed = 1;
2480         }
2481
2482       /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))
2483          into (plus (plus (mult (reg) (const)) (reg)) (const)).  This can be
2484          created by virtual register instantiation, register elimination, and
2485          similar optimizations.  */
2486       if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)
2487         {
2488           changed = 1;
2489           x = gen_rtx (PLUS, Pmode,
2490                        gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)),
2491                        XEXP (XEXP (x, 1), 1));
2492         }
2493
2494       /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)
2495          into (plus (plus (mult (reg) (const)) (reg)) (const)).  */
2496       else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
2497                && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
2498                && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
2499                && CONSTANT_P (XEXP (x, 1)))
2500         {
2501           rtx constant, other;
2502
2503           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
2504             {
2505               constant = XEXP (x, 1);
2506               other = XEXP (XEXP (XEXP (x, 0), 1), 1);
2507             }
2508           else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
2509             {
2510               constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
2511               other = XEXP (x, 1);
2512             }
2513           else
2514             constant = 0;
2515
2516           if (constant)
2517             {
2518               changed = 1;
2519               x = gen_rtx (PLUS, Pmode,
2520                            gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),
2521                                     XEXP (XEXP (XEXP (x, 0), 1), 0)),
2522                            plus_constant (other, INTVAL (constant)));
2523             }
2524         }
2525
2526       if (changed && legitimate_address_p (mode, x, FALSE))
2527         return x;
2528
2529       if (GET_CODE (XEXP (x, 0)) == MULT)
2530         {
2531           changed = 1;
2532           XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
2533         }
2534
2535       if (GET_CODE (XEXP (x, 1)) == MULT)
2536         {
2537           changed = 1;
2538           XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
2539         }
2540
2541       if (changed
2542           && GET_CODE (XEXP (x, 1)) == REG
2543           && GET_CODE (XEXP (x, 0)) == REG)
2544         return x;
2545
2546       if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))
2547         {
2548           changed = 1;
2549           x = legitimize_pic_address (x, 0);
2550         }
2551
2552       if (changed && legitimate_address_p (mode, x, FALSE))
2553         return x;
2554
2555       if (GET_CODE (XEXP (x, 0)) == REG)
2556         {
2557           register rtx temp = gen_reg_rtx (Pmode);
2558           register rtx val  = force_operand (XEXP (x, 1), temp);
2559           if (val != temp)
2560             emit_move_insn (temp, val);
2561
2562           XEXP (x, 1) = temp;
2563           return x;
2564         }
2565
2566       else if (GET_CODE (XEXP (x, 1)) == REG)
2567         {
2568           register rtx temp = gen_reg_rtx (Pmode);
2569           register rtx val  = force_operand (XEXP (x, 0), temp);
2570           if (val != temp)
2571             emit_move_insn (temp, val);
2572
2573           XEXP (x, 0) = temp;
2574           return x;
2575         }
2576     }
2577
2578   return x;
2579 }
2580
2581 \f
2582 /* Print an integer constant expression in assembler syntax.  Addition
2583    and subtraction are the only arithmetic that may appear in these
2584    expressions.  FILE is the stdio stream to write to, X is the rtx, and
2585    CODE is the operand print code from the output string.  */
2586
2587 static void
2588 output_pic_addr_const (file, x, code)
2589      FILE *file;
2590      rtx x;
2591      int code;
2592 {
2593   char buf[256];
2594
2595   switch (GET_CODE (x))
2596     {
2597     case PC:
2598       if (flag_pic)
2599         putc ('.', file);
2600       else
2601         abort ();
2602       break;
2603
2604     case SYMBOL_REF:
2605     case LABEL_REF:
2606       if (GET_CODE (x) == SYMBOL_REF)
2607         assemble_name (file, XSTR (x, 0));
2608       else
2609         {
2610           ASM_GENERATE_INTERNAL_LABEL (buf, "L",
2611                                        CODE_LABEL_NUMBER (XEXP (x, 0)));
2612           assemble_name (asm_out_file, buf);
2613         }
2614
2615       if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
2616         fprintf (file, "@GOTOFF(%%ebx)");
2617       else if (code == 'P')
2618         fprintf (file, "@PLT");
2619       else if (GET_CODE (x) == LABEL_REF)
2620         fprintf (file, "@GOTOFF");
2621       else if (! SYMBOL_REF_FLAG (x))
2622         fprintf (file, "@GOT");
2623       else
2624         fprintf (file, "@GOTOFF");
2625
2626       break;
2627
2628     case CODE_LABEL:
2629       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
2630       assemble_name (asm_out_file, buf);
2631       break;
2632
2633     case CONST_INT:
2634       fprintf (file, "%d", INTVAL (x));
2635       break;
2636
2637     case CONST:
2638       /* This used to output parentheses around the expression,
2639          but that does not work on the 386 (either ATT or BSD assembler).  */
2640       output_pic_addr_const (file, XEXP (x, 0), code);
2641       break;
2642
2643     case CONST_DOUBLE:
2644       if (GET_MODE (x) == VOIDmode)
2645         {
2646           /* We can use %d if the number is <32 bits and positive.  */
2647           if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
2648             fprintf (file, "0x%x%08x",
2649                      CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
2650           else
2651             fprintf (file, "%d", CONST_DOUBLE_LOW (x));
2652         }
2653       else
2654         /* We can't handle floating point constants;
2655            PRINT_OPERAND must handle them.  */
2656         output_operand_lossage ("floating constant misused");
2657       break;
2658
2659     case PLUS:
2660       /* Some assemblers need integer constants to appear last (eg masm).  */
2661       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
2662         {
2663           output_pic_addr_const (file, XEXP (x, 1), code);
2664           if (INTVAL (XEXP (x, 0)) >= 0)
2665             fprintf (file, "+");
2666           output_pic_addr_const (file, XEXP (x, 0), code);
2667         }
2668       else
2669         {
2670           output_pic_addr_const (file, XEXP (x, 0), code);
2671           if (INTVAL (XEXP (x, 1)) >= 0)
2672             fprintf (file, "+");
2673           output_pic_addr_const (file, XEXP (x, 1), code);
2674         }
2675       break;
2676
2677     case MINUS:
2678       output_pic_addr_const (file, XEXP (x, 0), code);
2679       fprintf (file, "-");
2680       output_pic_addr_const (file, XEXP (x, 1), code);
2681       break;
2682
2683     default:
2684       output_operand_lossage ("invalid expression as operand");
2685     }
2686 }
2687 \f
2688 /* Append the correct conditional move suffix which corresponds to CODE */
2689
2690 static void
2691 put_condition_code (code, mode, file)
2692      enum rtx_code code;
2693      enum mode_class mode;
2694      FILE * file;
2695 {
2696   if (mode == MODE_INT)
2697   switch (code)
2698     {
2699       case NE: 
2700           if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2701             fputs ("b", file);
2702           else
2703             fputs ("ne", file);
2704           return;
2705       case EQ: 
2706           if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2707             fputs ("ae", file);
2708           else
2709             fputs ("e", file);
2710           return;
2711       case GE: 
2712           fputs ("ge", file); return;
2713       case GT: 
2714           fputs ("g", file); return;
2715       case LE: 
2716           fputs ("le", file); return;
2717       case LT: 
2718           fputs ("l", file); return;
2719       case GEU: 
2720           fputs ("ae", file); return;
2721       case GTU: 
2722           fputs ("a", file); return;
2723       case LEU: 
2724           fputs ("be", file); return;
2725       case LTU: 
2726           fputs ("b", file); return;
2727       default: output_operand_lossage ("Invalid %%C operand");
2728     }
2729   else if (mode == MODE_FLOAT)
2730   switch (code)
2731     {
2732       case NE: 
2733           fputs ("ne", file); return;
2734       case EQ: 
2735           fputs ("e", file); return;
2736       case GE: 
2737           fputs ("nb", file); return;
2738       case GT: 
2739           fputs ("nbe", file); return;
2740       case LE: 
2741           fputs ("be", file); return;
2742       case LT: 
2743           fputs ("b", file); return;
2744       case GEU: 
2745           fputs ("nb", file); return;
2746       case GTU: 
2747           fputs ("nbe", file); return;
2748       case LEU: 
2749           fputs ("be", file); return;
2750       case LTU: 
2751           fputs ("b", file); return;
2752       default: output_operand_lossage ("Invalid %%C operand");
2753     }
2754 }
2755
2756 /* Meaning of CODE:
2757    L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
2758    C -- print opcode suffix for set/cmov insn.
2759    c -- like C, but print reversed condition
2760    F -- print opcode suffix for fcmov insn.
2761    f -- like C, but print reversed condition
2762    R -- print the prefix for register names.
2763    z -- print the opcode suffix for the size of the current operand.
2764    * -- print a star (in certain assembler syntax)
2765    w -- print the operand as if it's a "word" (HImode) even if it isn't.
2766    c -- don't print special prefixes before constant operands.
2767    J -- print the appropriate jump operand.
2768    s -- print a shift double count, followed by the assemblers argument
2769         delimiter.
2770    b -- print the QImode name of the register for the indicated operand.
2771         %b0 would print %al if operands[0] is reg 0.
2772    w --  likewise, print the HImode name of the register.
2773    k --  likewise, print the SImode name of the register.
2774    h --  print the QImode name for a "high" register, either ah, bh, ch or dh.
2775    y --  print "st(0)" instead of "st" as a register.
2776    P --  print as a PIC constant
2777 */
2778
2779 void
2780 print_operand (file, x, code)
2781      FILE *file;
2782      rtx x;
2783      int code;
2784 {
2785   if (code)
2786     {
2787       switch (code)
2788         {
2789         case '*':
2790           if (USE_STAR)
2791             putc ('*', file);
2792           return;
2793
2794         case 'L':
2795           PUT_OP_SIZE (code, 'l', file);
2796           return;
2797
2798         case 'W':
2799           PUT_OP_SIZE (code, 'w', file);
2800           return;
2801
2802         case 'B':
2803           PUT_OP_SIZE (code, 'b', file);
2804           return;
2805
2806         case 'Q':
2807           PUT_OP_SIZE (code, 'l', file);
2808           return;
2809
2810         case 'S':
2811           PUT_OP_SIZE (code, 's', file);
2812           return;
2813
2814         case 'T':
2815           PUT_OP_SIZE (code, 't', file);
2816           return;
2817
2818         case 'z':
2819           /* 387 opcodes don't get size suffixes if the operands are
2820              registers. */
2821
2822           if (STACK_REG_P (x))
2823             return;
2824
2825           /* this is the size of op from size of operand */
2826           switch (GET_MODE_SIZE (GET_MODE (x)))
2827             {
2828             case 1:
2829               PUT_OP_SIZE ('B', 'b', file);
2830               return;
2831
2832             case 2:
2833               PUT_OP_SIZE ('W', 'w', file);
2834               return;
2835
2836             case 4:
2837               if (GET_MODE (x) == SFmode)
2838                 {
2839                   PUT_OP_SIZE ('S', 's', file);
2840                   return;
2841                 }
2842               else
2843                 PUT_OP_SIZE ('L', 'l', file);
2844               return;
2845
2846             case 12:
2847                   PUT_OP_SIZE ('T', 't', file);
2848                   return;
2849
2850             case 8:
2851               if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
2852                 {
2853 #ifdef GAS_MNEMONICS
2854                   PUT_OP_SIZE ('Q', 'q', file);
2855                   return;
2856 #else
2857                   PUT_OP_SIZE ('Q', 'l', file); /* Fall through */
2858 #endif
2859                 }
2860
2861               PUT_OP_SIZE ('Q', 'l', file);
2862               return;
2863             }
2864
2865         case 'b':
2866         case 'w':
2867         case 'k':
2868         case 'h':
2869         case 'y':
2870         case 'P':
2871           break;
2872
2873         case 'J':
2874           switch (GET_CODE (x))
2875             {
2876               /* These conditions are appropriate for testing the result
2877                  of an arithmetic operation, not for a compare operation.
2878                  Cases GE, LT assume CC_NO_OVERFLOW true. All cases assume
2879                  CC_Z_IN_NOT_C false and not floating point.  */
2880             case NE:  fputs ("jne", file); return;
2881             case EQ:  fputs ("je",  file); return;
2882             case GE:  fputs ("jns", file); return;
2883             case LT:  fputs ("js",  file); return;
2884             case GEU: fputs ("jmp", file); return;
2885             case GTU: fputs ("jne",  file); return;
2886             case LEU: fputs ("je", file); return;
2887             case LTU: fputs ("#branch never",  file); return;
2888
2889             /* no matching branches for GT nor LE */
2890             }
2891           abort ();
2892
2893         case 's':
2894           if (GET_CODE (x) == CONST_INT || ! SHIFT_DOUBLE_OMITS_COUNT)
2895             {
2896               PRINT_OPERAND (file, x, 0);
2897               fputs (AS2C (,) + 1, file);
2898             }
2899           return;
2900
2901           /* This is used by the conditional move instructions.  */
2902         case 'C':
2903           put_condition_code (GET_CODE (x), MODE_INT, file);
2904           return;
2905
2906           /* like above, but reverse condition */
2907         case 'c':
2908           put_condition_code (reverse_condition (GET_CODE (x)), MODE_INT, file);
2909           return;
2910
2911         case 'F':
2912           put_condition_code (GET_CODE (x), MODE_FLOAT, file);
2913           return;
2914
2915           /* like above, but reverse condition */
2916         case 'f':
2917           put_condition_code (reverse_condition (GET_CODE (x)),
2918                               MODE_FLOAT, file);
2919           return;
2920
2921         default:
2922           {
2923             char str[50];
2924
2925             sprintf (str, "invalid operand code `%c'", code);
2926             output_operand_lossage (str);
2927           }
2928         }
2929     }
2930   if (GET_CODE (x) == REG)
2931     {
2932       PRINT_REG (x, code, file);
2933     }
2934   else if (GET_CODE (x) == MEM)
2935     {
2936       PRINT_PTR (x, file);
2937       if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
2938         {
2939           if (flag_pic)
2940             output_pic_addr_const (file, XEXP (x, 0), code);
2941           else
2942             output_addr_const (file, XEXP (x, 0));
2943         }
2944       else
2945         output_address (XEXP (x, 0));
2946     }
2947   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
2948     {
2949       REAL_VALUE_TYPE r; long l;
2950       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2951       REAL_VALUE_TO_TARGET_SINGLE (r, l);
2952       PRINT_IMMED_PREFIX (file);
2953       fprintf (file, "0x%x", l);
2954     }
2955  /* These float cases don't actually occur as immediate operands. */
2956  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
2957     {
2958       REAL_VALUE_TYPE r; char dstr[30];
2959       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2960       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
2961       fprintf (file, "%s", dstr);
2962     }
2963   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode)
2964     {
2965       REAL_VALUE_TYPE r; char dstr[30];
2966       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2967       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
2968       fprintf (file, "%s", dstr);
2969     }
2970   else 
2971     {
2972       if (code != 'P')
2973         {
2974           if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
2975             PRINT_IMMED_PREFIX (file);
2976           else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
2977                    || GET_CODE (x) == LABEL_REF)
2978             PRINT_OFFSET_PREFIX (file);
2979         }
2980       if (flag_pic)
2981         output_pic_addr_const (file, x, code);
2982       else
2983         output_addr_const (file, x);
2984     }
2985 }
2986 \f
2987 /* Print a memory operand whose address is ADDR.  */
2988
2989 void
2990 print_operand_address (file, addr)
2991      FILE *file;
2992      register rtx addr;
2993 {
2994   register rtx reg1, reg2, breg, ireg;
2995   rtx offset;
2996
2997   switch (GET_CODE (addr))
2998     {
2999     case REG:
3000       ADDR_BEG (file);
3001       fprintf (file, "%se", RP);
3002       fputs (hi_reg_name[REGNO (addr)], file);
3003       ADDR_END (file);
3004       break;
3005
3006     case PLUS:
3007       reg1 = 0;
3008       reg2 = 0;
3009       ireg = 0;
3010       breg = 0;
3011       offset = 0;
3012       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
3013         {
3014           offset = XEXP (addr, 0);
3015           addr = XEXP (addr, 1);
3016         }
3017       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
3018         {
3019           offset = XEXP (addr, 1);
3020           addr = XEXP (addr, 0);
3021         }
3022       if (GET_CODE (addr) != PLUS) ;
3023       else if (GET_CODE (XEXP (addr, 0)) == MULT)
3024         {
3025           reg1 = XEXP (addr, 0);
3026           addr = XEXP (addr, 1);
3027         }
3028       else if (GET_CODE (XEXP (addr, 1)) == MULT)
3029         {
3030           reg1 = XEXP (addr, 1);
3031           addr = XEXP (addr, 0);
3032         }
3033       else if (GET_CODE (XEXP (addr, 0)) == REG)
3034         {
3035           reg1 = XEXP (addr, 0);
3036           addr = XEXP (addr, 1);
3037         }
3038       else if (GET_CODE (XEXP (addr, 1)) == REG)
3039         {
3040           reg1 = XEXP (addr, 1);
3041           addr = XEXP (addr, 0);
3042         }
3043       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
3044         {
3045           if (reg1 == 0) reg1 = addr;
3046           else reg2 = addr;
3047           addr = 0;
3048         }
3049       if (offset != 0)
3050         {
3051           if (addr != 0) abort ();
3052           addr = offset;
3053         }
3054       if ((reg1 && GET_CODE (reg1) == MULT)
3055           || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
3056         {
3057           breg = reg2;
3058           ireg = reg1;
3059         }
3060       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
3061         {
3062           breg = reg1;
3063           ireg = reg2;
3064         }
3065
3066       if (ireg != 0 || breg != 0)
3067         {
3068           int scale = 1;
3069
3070           if (addr != 0)
3071             {
3072               if (flag_pic)
3073                 output_pic_addr_const (file, addr, 0);
3074
3075               else if (GET_CODE (addr) == LABEL_REF)
3076                 output_asm_label (addr);
3077
3078               else
3079                 output_addr_const (file, addr);
3080             }
3081
3082           if (ireg != 0 && GET_CODE (ireg) == MULT)
3083             {
3084               scale = INTVAL (XEXP (ireg, 1));
3085               ireg = XEXP (ireg, 0);
3086             }
3087
3088           /* The stack pointer can only appear as a base register,
3089              never an index register, so exchange the regs if it is wrong. */
3090
3091           if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)
3092             {
3093               rtx tmp;
3094
3095               tmp = breg;
3096               breg = ireg;
3097               ireg = tmp;
3098             }
3099
3100           /* output breg+ireg*scale */
3101           PRINT_B_I_S (breg, ireg, scale, file);
3102           break;
3103         }
3104
3105     case MULT:
3106       {
3107         int scale;
3108         if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
3109           {
3110             scale = INTVAL (XEXP (addr, 0));
3111             ireg = XEXP (addr, 1);
3112           }
3113         else
3114           {
3115             scale = INTVAL (XEXP (addr, 1));
3116             ireg = XEXP (addr, 0);
3117           }
3118         output_addr_const (file, const0_rtx);
3119         PRINT_B_I_S ((rtx) 0, ireg, scale, file);
3120       }
3121       break;
3122
3123     default:
3124       if (GET_CODE (addr) == CONST_INT
3125           && INTVAL (addr) < 0x8000
3126           && INTVAL (addr) >= -0x8000)
3127         fprintf (file, "%d", INTVAL (addr));
3128       else
3129         {
3130           if (flag_pic)
3131             output_pic_addr_const (file, addr, 0);
3132           else
3133             output_addr_const (file, addr);
3134         }
3135     }
3136 }
3137 \f
3138 /* Set the cc_status for the results of an insn whose pattern is EXP.
3139    On the 80386, we assume that only test and compare insns, as well
3140    as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT,
3141    ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
3142    Also, we assume that jumps, moves and sCOND don't affect the condition
3143    codes.  All else clobbers the condition codes, by assumption.
3144
3145    We assume that ALL integer add, minus, etc. instructions effect the
3146    condition codes.  This MUST be consistent with i386.md.
3147
3148    We don't record any float test or compare - the redundant test &
3149    compare check in final.c does not handle stack-like regs correctly. */
3150
3151 void
3152 notice_update_cc (exp)
3153      rtx exp;
3154 {
3155   if (GET_CODE (exp) == SET)
3156     {
3157       /* Jumps do not alter the cc's.  */
3158       if (SET_DEST (exp) == pc_rtx)
3159         return;
3160 #ifdef IS_STACK_MODE
3161       /* Moving into a memory of stack_mode may have been moved
3162          in between the use and set of cc0 by loop_spl(). So
3163          old value of cc.status must be retained */
3164       if(GET_CODE(SET_DEST(exp))==MEM 
3165          && IS_STACK_MODE(GET_MODE(SET_DEST(exp))))
3166         {
3167           return;
3168         }
3169 #endif
3170       /* Moving register or memory into a register:
3171          it doesn't alter the cc's, but it might invalidate
3172          the RTX's which we remember the cc's came from.
3173          (Note that moving a constant 0 or 1 MAY set the cc's).  */
3174       if (REG_P (SET_DEST (exp))
3175           && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM
3176               || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
3177         {
3178           if (cc_status.value1
3179               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
3180             cc_status.value1 = 0;
3181           if (cc_status.value2
3182               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
3183             cc_status.value2 = 0;
3184           return;
3185         }
3186       /* Moving register into memory doesn't alter the cc's.
3187          It may invalidate the RTX's which we remember the cc's came from.  */
3188       if (GET_CODE (SET_DEST (exp)) == MEM
3189           && (REG_P (SET_SRC (exp))
3190               || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
3191         {
3192           if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
3193               || reg_mentioned_p (SET_DEST (exp), cc_status.value1))
3194             cc_status.value1 = 0;
3195           if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM
3196               || reg_mentioned_p (SET_DEST (exp), cc_status.value2))
3197             cc_status.value2 = 0;
3198           return;
3199         }
3200       /* Function calls clobber the cc's.  */
3201       else if (GET_CODE (SET_SRC (exp)) == CALL)
3202         {
3203           CC_STATUS_INIT;
3204           return;
3205         }
3206       /* Tests and compares set the cc's in predictable ways.  */
3207       else if (SET_DEST (exp) == cc0_rtx)
3208         {
3209           CC_STATUS_INIT;
3210           cc_status.value1 = SET_SRC (exp);
3211           return;
3212         }
3213       /* Certain instructions effect the condition codes. */
3214       else if (GET_MODE (SET_SRC (exp)) == SImode
3215                || GET_MODE (SET_SRC (exp)) == HImode
3216                || GET_MODE (SET_SRC (exp)) == QImode)
3217         switch (GET_CODE (SET_SRC (exp)))
3218           {
3219           case ASHIFTRT: case LSHIFTRT:
3220           case ASHIFT:
3221             /* Shifts on the 386 don't set the condition codes if the
3222                shift count is zero. */
3223             if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
3224               {
3225                 CC_STATUS_INIT;
3226                 break;
3227               }
3228             /* We assume that the CONST_INT is non-zero (this rtx would
3229                have been deleted if it were zero. */
3230
3231           case PLUS: case MINUS: case NEG:
3232           case AND: case IOR: case XOR:
3233             cc_status.flags = CC_NO_OVERFLOW;
3234             cc_status.value1 = SET_SRC (exp);
3235             cc_status.value2 = SET_DEST (exp);
3236             break;
3237
3238           default:
3239             CC_STATUS_INIT;
3240           }
3241       else
3242         {
3243           CC_STATUS_INIT;
3244         }
3245     }
3246   else if (GET_CODE (exp) == PARALLEL
3247            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
3248     {
3249       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
3250         return;
3251       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
3252         {
3253           CC_STATUS_INIT;
3254           if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
3255             cc_status.flags |= CC_IN_80387;
3256           else
3257             cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
3258           return;
3259         }
3260       CC_STATUS_INIT;
3261     }
3262   else
3263     {
3264       CC_STATUS_INIT;
3265     }
3266 }
3267 \f
3268 /* Split one or more DImode RTL references into pairs of SImode
3269    references.  The RTL can be REG, offsettable MEM, integer constant, or
3270    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
3271    split and "num" is its length.  lo_half and hi_half are output arrays
3272    that parallel "operands". */
3273
3274 void
3275 split_di (operands, num, lo_half, hi_half)
3276      rtx operands[];
3277      int num;
3278      rtx lo_half[], hi_half[];
3279 {
3280   while (num--)
3281     {
3282       if (GET_CODE (operands[num]) == REG)
3283         {
3284           lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
3285           hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
3286         }
3287       else if (CONSTANT_P (operands[num]))
3288         {
3289           split_double (operands[num], &lo_half[num], &hi_half[num]);
3290         }
3291       else if (offsettable_memref_p (operands[num]))
3292         {
3293           lo_half[num] = operands[num];
3294           hi_half[num] = adj_offsettable_operand (operands[num], 4);
3295         }
3296       else
3297         abort();
3298     }
3299 }
3300 \f
3301 /* Return 1 if this is a valid binary operation on a 387.
3302    OP is the expression matched, and MODE is its mode. */
3303
3304 int
3305 binary_387_op (op, mode)
3306     register rtx op;
3307     enum machine_mode mode;
3308 {
3309   if (mode != VOIDmode && mode != GET_MODE (op))
3310     return 0;
3311
3312   switch (GET_CODE (op))
3313     {
3314     case PLUS:
3315     case MINUS:
3316     case MULT:
3317     case DIV:
3318       return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;
3319
3320     default:
3321       return 0;
3322     }
3323 }
3324
3325 \f
3326 /* Return 1 if this is a valid shift or rotate operation on a 386.
3327    OP is the expression matched, and MODE is its mode. */
3328
3329 int
3330 shift_op (op, mode)
3331     register rtx op;
3332     enum machine_mode mode;
3333 {
3334   rtx operand = XEXP (op, 0);
3335
3336   if (mode != VOIDmode && mode != GET_MODE (op))
3337     return 0;
3338
3339   if (GET_MODE (operand) != GET_MODE (op)
3340       || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
3341     return 0;
3342
3343   return (GET_CODE (op) == ASHIFT
3344           || GET_CODE (op) == ASHIFTRT
3345           || GET_CODE (op) == LSHIFTRT
3346           || GET_CODE (op) == ROTATE
3347           || GET_CODE (op) == ROTATERT);
3348 }
3349
3350 /* Return 1 if OP is COMPARE rtx with mode VOIDmode.
3351    MODE is not used.  */
3352
3353 int
3354 VOIDmode_compare_op (op, mode)
3355     register rtx op;
3356     enum machine_mode mode;
3357 {
3358   return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode;
3359 }
3360 \f
3361 /* Output code to perform a 387 binary operation in INSN, one of PLUS,
3362    MINUS, MULT or DIV.  OPERANDS are the insn operands, where operands[3]
3363    is the expression of the binary operation.  The output may either be
3364    emitted here, or returned to the caller, like all output_* functions.
3365
3366    There is no guarantee that the operands are the same mode, as they
3367    might be within FLOAT or FLOAT_EXTEND expressions. */
3368
3369 char *
3370 output_387_binary_op (insn, operands)
3371      rtx insn;
3372      rtx *operands;
3373 {
3374   rtx temp;
3375   char *base_op;
3376   static char buf[100];
3377
3378   switch (GET_CODE (operands[3]))
3379     {
3380     case PLUS:
3381       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3382           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3383         base_op = "fiadd";
3384       else
3385         base_op = "fadd";
3386       break;
3387
3388     case MINUS:
3389       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3390           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3391         base_op = "fisub";
3392       else
3393         base_op = "fsub";
3394       break;
3395
3396     case MULT:
3397       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3398           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3399         base_op = "fimul";
3400       else
3401         base_op = "fmul";
3402       break;
3403
3404     case DIV:
3405       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3406           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3407         base_op = "fidiv";
3408       else
3409         base_op = "fdiv";
3410       break;
3411
3412     default:
3413       abort ();
3414     }
3415
3416   strcpy (buf, base_op);
3417
3418   switch (GET_CODE (operands[3]))
3419     {
3420     case MULT:
3421     case PLUS:
3422       if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
3423         {
3424           temp = operands[2];
3425           operands[2] = operands[1];
3426           operands[1] = temp;
3427         }
3428
3429       if (GET_CODE (operands[2]) == MEM)
3430         return strcat (buf, AS1 (%z2,%2));
3431
3432       if (NON_STACK_REG_P (operands[1]))
3433         {
3434           output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
3435           RET;
3436         }
3437       else if (NON_STACK_REG_P (operands[2]))
3438         {
3439           output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
3440           RET;
3441         }
3442
3443       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
3444         return strcat (buf, AS2 (p,%2,%0));
3445
3446       if (STACK_TOP_P (operands[0]))
3447         return strcat (buf, AS2C (%y2,%0));
3448       else
3449         return strcat (buf, AS2C (%2,%0));
3450
3451     case MINUS:
3452     case DIV:
3453       if (GET_CODE (operands[1]) == MEM)
3454         return strcat (buf, AS1 (r%z1,%1));
3455
3456       if (GET_CODE (operands[2]) == MEM)
3457         return strcat (buf, AS1 (%z2,%2));
3458
3459       if (NON_STACK_REG_P (operands[1]))
3460         {
3461           output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));
3462           RET;
3463         }
3464       else if (NON_STACK_REG_P (operands[2]))
3465         {
3466           output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
3467           RET;
3468         }
3469
3470       if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
3471         abort ();
3472
3473       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
3474         return strcat (buf, AS2 (rp,%2,%0));
3475
3476       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3477         return strcat (buf, AS2 (p,%1,%0));
3478
3479       if (STACK_TOP_P (operands[0]))
3480         {
3481           if (STACK_TOP_P (operands[1]))
3482             return strcat (buf, AS2C (%y2,%0));
3483           else
3484             return strcat (buf, AS2 (r,%y1,%0));
3485         }
3486       else if (STACK_TOP_P (operands[1]))
3487         return strcat (buf, AS2C (%1,%0));
3488       else
3489         return strcat (buf, AS2 (r,%2,%0));
3490
3491     default:
3492       abort ();
3493     }
3494 }
3495 \f
3496 /* Output code for INSN to convert a float to a signed int.  OPERANDS
3497    are the insn operands.  The output may be SFmode or DFmode and the
3498    input operand may be SImode or DImode.  As a special case, make sure
3499    that the 387 stack top dies if the output mode is DImode, because the
3500    hardware requires this.  */
3501
3502 char *
3503 output_fix_trunc (insn, operands)
3504      rtx insn;
3505      rtx *operands;
3506 {
3507   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
3508   rtx xops[2];
3509
3510   if (! STACK_TOP_P (operands[1]) ||
3511       (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
3512     abort ();
3513
3514   xops[0] = GEN_INT (12);
3515   xops[1] = operands[4];
3516
3517   output_asm_insn (AS1 (fnstc%W2,%2), operands);
3518   output_asm_insn (AS2 (mov%L2,%2,%4), operands);
3519   output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
3520   output_asm_insn (AS2 (mov%L4,%4,%3), operands);
3521   output_asm_insn (AS1 (fldc%W3,%3), operands);
3522
3523   if (NON_STACK_REG_P (operands[0]))
3524     output_to_reg (operands[0], stack_top_dies);
3525   else if (GET_CODE (operands[0]) == MEM)
3526     {
3527       if (stack_top_dies)
3528         output_asm_insn (AS1 (fistp%z0,%0), operands);
3529       else
3530         output_asm_insn (AS1 (fist%z0,%0), operands);
3531     }
3532   else
3533     abort ();
3534
3535   return AS1 (fldc%W2,%2);
3536 }
3537 \f
3538 /* Output code for INSN to compare OPERANDS.  The two operands might
3539    not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
3540    expression.  If the compare is in mode CCFPEQmode, use an opcode that
3541    will not fault if a qNaN is present. */
3542
3543 char *
3544 output_float_compare (insn, operands)
3545      rtx insn;
3546      rtx *operands;
3547 {
3548   int stack_top_dies;
3549   rtx body = XVECEXP (PATTERN (insn), 0, 0);
3550   int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
3551
3552   rtx tmp;
3553   if (! STACK_TOP_P (operands[0]))
3554     {
3555       tmp = operands[0];
3556       operands[0] = operands[1];
3557       operands[1] = tmp;
3558       cc_status.flags |= CC_REVERSED;
3559     }
3560     
3561   if (! STACK_TOP_P (operands[0]))
3562     abort ();
3563
3564   stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
3565
3566   if (STACK_REG_P (operands[1])
3567       && stack_top_dies
3568       && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
3569       && REGNO (operands[1]) != FIRST_STACK_REG)
3570     {
3571       /* If both the top of the 387 stack dies, and the other operand
3572          is also a stack register that dies, then this must be a
3573          `fcompp' float compare */
3574
3575       if (unordered_compare)
3576         output_asm_insn ("fucompp", operands);
3577       else
3578         output_asm_insn ("fcompp", operands);
3579     }
3580   else
3581     {
3582       static char buf[100];
3583
3584       /* Decide if this is the integer or float compare opcode, or the
3585          unordered float compare. */
3586
3587       if (unordered_compare)
3588         strcpy (buf, "fucom");
3589       else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
3590         strcpy (buf, "fcom");
3591       else
3592         strcpy (buf, "ficom");
3593
3594       /* Modify the opcode if the 387 stack is to be popped. */
3595
3596       if (stack_top_dies)
3597         strcat (buf, "p");
3598
3599       if (NON_STACK_REG_P (operands[1]))
3600         output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
3601       else
3602         output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);
3603     }
3604
3605   /* Now retrieve the condition code. */
3606
3607   return output_fp_cc0_set (insn);
3608 }
3609 \f
3610 /* Output opcodes to transfer the results of FP compare or test INSN
3611    from the FPU to the CPU flags.  If TARGET_IEEE_FP, ensure that if the
3612    result of the compare or test is unordered, no comparison operator
3613    succeeds except NE.  Return an output template, if any.  */
3614
3615 char *
3616 output_fp_cc0_set (insn)
3617      rtx insn;
3618 {
3619   rtx xops[3];
3620   rtx unordered_label;
3621   rtx next;
3622   enum rtx_code code;
3623
3624   xops[0] = gen_rtx (REG, HImode, 0);
3625   output_asm_insn (AS1 (fnsts%W0,%0), xops);
3626
3627   if (! TARGET_IEEE_FP)
3628     {
3629       if (!(cc_status.flags & CC_REVERSED))
3630         {
3631           next = next_cc0_user (insn);
3632         
3633           if (GET_CODE (next) == JUMP_INSN
3634               && GET_CODE (PATTERN (next)) == SET
3635               && SET_DEST (PATTERN (next)) == pc_rtx
3636               && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3637             {
3638               code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3639             }
3640           else if (GET_CODE (PATTERN (next)) == SET)
3641             {
3642               code = GET_CODE (SET_SRC (PATTERN (next)));
3643             }
3644           else
3645             {
3646               return "sahf";
3647             }
3648           if (code == GT || code == LT || code == EQ || code == NE
3649               || code == LE || code == GE)
3650             { /* We will test eax directly */
3651               cc_status.flags |= CC_TEST_AX;
3652               RET;
3653             }
3654         }
3655       return "sahf";
3656     }
3657
3658   next = next_cc0_user (insn);
3659   if (next == NULL_RTX)
3660     abort ();
3661
3662   if (GET_CODE (next) == JUMP_INSN
3663       && GET_CODE (PATTERN (next)) == SET
3664       && SET_DEST (PATTERN (next)) == pc_rtx
3665       && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3666     {
3667       code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3668     }
3669   else if (GET_CODE (PATTERN (next)) == SET)
3670     {
3671       if (GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3672         code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3673       else code = GET_CODE (SET_SRC (PATTERN (next)));
3674     }
3675   else
3676     abort ();
3677
3678   xops[0] = gen_rtx (REG, QImode, 0);
3679
3680   switch (code)
3681     {
3682     case GT:
3683       xops[1] = GEN_INT (0x45);
3684       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3685       /* je label */
3686       break;
3687
3688     case LT:
3689       xops[1] = GEN_INT (0x45);
3690       xops[2] = GEN_INT (0x01);
3691       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3692       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3693       /* je label */
3694       break;
3695
3696     case GE:
3697       xops[1] = GEN_INT (0x05);
3698       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3699       /* je label */
3700       break;
3701
3702     case LE:
3703       xops[1] = GEN_INT (0x45);
3704       xops[2] = GEN_INT (0x40);
3705       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3706       output_asm_insn (AS1 (dec%B0,%h0), xops);
3707       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3708       /* jb label */
3709       break;
3710
3711     case EQ:
3712       xops[1] = GEN_INT (0x45);
3713       xops[2] = GEN_INT (0x40);
3714       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3715       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3716       /* je label */
3717       break;
3718
3719     case NE:
3720       xops[1] = GEN_INT (0x44);
3721       xops[2] = GEN_INT (0x40);
3722       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3723       output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
3724       /* jne label */
3725       break;
3726
3727     case GTU:
3728     case LTU:
3729     case GEU:
3730     case LEU:
3731     default:
3732       abort ();
3733     }
3734   RET;
3735 }
3736 \f
3737 #define MAX_386_STACK_LOCALS 2
3738
3739 static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
3740
3741 /* Define the structure for the machine field in struct function.  */
3742 struct machine_function
3743 {
3744   rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
3745 };
3746
3747 /* Functions to save and restore i386_stack_locals.
3748    These will be called, via pointer variables,
3749    from push_function_context and pop_function_context.  */
3750
3751 void
3752 save_386_machine_status (p)
3753      struct function *p;
3754 {
3755   p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals);
3756   bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals,
3757          sizeof i386_stack_locals);
3758 }
3759
3760 void
3761 restore_386_machine_status (p)
3762      struct function *p;
3763 {
3764   bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals,
3765          sizeof i386_stack_locals);
3766   free (p->machine);
3767 }
3768
3769 /* Clear stack slot assignments remembered from previous functions.
3770    This is called from INIT_EXPANDERS once before RTL is emitted for each
3771    function.  */
3772
3773 void
3774 clear_386_stack_locals ()
3775 {
3776   enum machine_mode mode;
3777   int n;
3778
3779   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
3780        mode = (enum machine_mode) ((int) mode + 1))
3781     for (n = 0; n < MAX_386_STACK_LOCALS; n++)
3782       i386_stack_locals[(int) mode][n] = NULL_RTX;
3783
3784   /* Arrange to save and restore i386_stack_locals around nested functions.  */
3785   save_machine_status = save_386_machine_status;
3786   restore_machine_status = restore_386_machine_status;
3787 }
3788
3789 /* Return a MEM corresponding to a stack slot with mode MODE.
3790    Allocate a new slot if necessary.
3791
3792    The RTL for a function can have several slots available: N is
3793    which slot to use.  */
3794
3795 rtx
3796 assign_386_stack_local (mode, n)
3797      enum machine_mode mode;
3798      int n;
3799 {
3800   if (n < 0 || n >= MAX_386_STACK_LOCALS)
3801     abort ();
3802
3803   if (i386_stack_locals[(int) mode][n] == NULL_RTX)
3804     i386_stack_locals[(int) mode][n]
3805       = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
3806
3807   return i386_stack_locals[(int) mode][n];
3808 }
3809
3810 \f
3811 int is_mul(op,mode)
3812     register rtx op;
3813     enum machine_mode mode;
3814 {
3815   return (GET_CODE (op) == MULT);
3816 }
3817
3818 int is_div(op,mode)
3819     register rtx op;
3820     enum machine_mode mode;
3821 {
3822   return (GET_CODE (op) == DIV);
3823 }
3824
3825 \f
3826 #ifdef NOTYET
3827 /* Create a new copy of an rtx.
3828    Recursively copies the operands of the rtx,
3829    except for those few rtx codes that are sharable.
3830    Doesn't share CONST  */
3831
3832 rtx
3833 copy_all_rtx (orig)
3834      register rtx orig;
3835 {
3836   register rtx copy;
3837   register int i, j;
3838   register RTX_CODE code;
3839   register char *format_ptr;
3840
3841   code = GET_CODE (orig);
3842
3843   switch (code)
3844     {
3845     case REG:
3846     case QUEUED:
3847     case CONST_INT:
3848     case CONST_DOUBLE:
3849     case SYMBOL_REF:
3850     case CODE_LABEL:
3851     case PC:
3852     case CC0:
3853     case SCRATCH:
3854       /* SCRATCH must be shared because they represent distinct values. */
3855       return orig;
3856
3857 #if 0
3858     case CONST:
3859       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
3860          a LABEL_REF, it isn't sharable.  */
3861       if (GET_CODE (XEXP (orig, 0)) == PLUS
3862           && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
3863           && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT)
3864         return orig;
3865       break;
3866 #endif
3867       /* A MEM with a constant address is not sharable.  The problem is that
3868          the constant address may need to be reloaded.  If the mem is shared,
3869          then reloading one copy of this mem will cause all copies to appear
3870          to have been reloaded.  */
3871     }
3872
3873   copy = rtx_alloc (code);
3874   PUT_MODE (copy, GET_MODE (orig));
3875   copy->in_struct = orig->in_struct;
3876   copy->volatil = orig->volatil;
3877   copy->unchanging = orig->unchanging;
3878   copy->integrated = orig->integrated;
3879   /* intel1 */
3880   copy->is_spill_rtx = orig->is_spill_rtx;
3881   
3882   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
3883
3884   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
3885     {
3886       switch (*format_ptr++)
3887         {
3888         case 'e':
3889           XEXP (copy, i) = XEXP (orig, i);
3890           if (XEXP (orig, i) != NULL)
3891             XEXP (copy, i) = copy_rtx (XEXP (orig, i));
3892           break;
3893
3894         case '0':
3895         case 'u':
3896           XEXP (copy, i) = XEXP (orig, i);
3897           break;
3898
3899         case 'E':
3900         case 'V':
3901           XVEC (copy, i) = XVEC (orig, i);
3902           if (XVEC (orig, i) != NULL)
3903             {
3904               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
3905               for (j = 0; j < XVECLEN (copy, i); j++)
3906                 XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
3907             }
3908           break;
3909
3910         case 'w':
3911           XWINT (copy, i) = XWINT (orig, i);
3912           break;
3913
3914         case 'i':
3915           XINT (copy, i) = XINT (orig, i);
3916           break;
3917
3918         case 's':
3919         case 'S':
3920           XSTR (copy, i) = XSTR (orig, i);
3921           break;
3922
3923         default:
3924           abort ();
3925         }
3926     }
3927   return copy;
3928 }
3929
3930 \f
3931 /* try to rewrite a memory address to make it valid */
3932 void 
3933 rewrite_address (mem_rtx)
3934      rtx mem_rtx;
3935 {
3936   rtx index_rtx, base_rtx, offset_rtx, scale_rtx, ret_rtx;
3937   int scale = 1;
3938   int offset_adjust = 0;
3939   int was_only_offset = 0;
3940   rtx mem_addr = XEXP (mem_rtx, 0);
3941   char *storage = (char *) oballoc (0);
3942   int in_struct = 0;
3943   int is_spill_rtx = 0;
3944
3945   in_struct = MEM_IN_STRUCT_P (mem_rtx);
3946   is_spill_rtx = RTX_IS_SPILL_P (mem_rtx);
3947
3948   if (GET_CODE (mem_addr) == PLUS &&
3949       GET_CODE (XEXP (mem_addr, 1)) == PLUS &&
3950       GET_CODE (XEXP (XEXP (mem_addr, 1), 0)) == REG)
3951     {                           /* this part is utilized by the combiner */
3952       ret_rtx =
3953         gen_rtx (PLUS, GET_MODE (mem_addr),
3954                  gen_rtx (PLUS, GET_MODE (XEXP (mem_addr, 1)),
3955                           XEXP (mem_addr, 0),
3956                           XEXP (XEXP (mem_addr, 1), 0)),
3957                  XEXP (XEXP (mem_addr, 1), 1));
3958       if (memory_address_p (GET_MODE (mem_rtx), ret_rtx))
3959         {
3960           XEXP (mem_rtx, 0) = ret_rtx;
3961           RTX_IS_SPILL_P (ret_rtx) = is_spill_rtx;
3962           return;
3963         }
3964       obfree (storage);
3965     }
3966
3967   /* this part is utilized by loop.c */
3968   /* If the address contains PLUS (reg,const) and this pattern is invalid
3969      in this case - try to rewrite the address to make it valid  intel1
3970   */
3971   storage = (char *) oballoc (0);
3972   index_rtx = base_rtx = offset_rtx = NULL;
3973   /* find the base index and offset elements of the memory address */
3974   if (GET_CODE (mem_addr) == PLUS)
3975     {
3976       if (GET_CODE (XEXP (mem_addr, 0)) == REG)
3977         {
3978           if (GET_CODE (XEXP (mem_addr, 1)) == REG)
3979             {
3980               base_rtx = XEXP (mem_addr, 1);
3981               index_rtx = XEXP (mem_addr, 0);
3982             }
3983           else
3984             {
3985               base_rtx = XEXP (mem_addr, 0);
3986               offset_rtx = XEXP (mem_addr, 1);
3987             }
3988         }
3989       else if (GET_CODE (XEXP (mem_addr, 0)) == MULT)
3990         {
3991           index_rtx = XEXP (mem_addr, 0);
3992           if (GET_CODE (XEXP (mem_addr, 1)) == REG)
3993             {
3994               base_rtx = XEXP (mem_addr, 1);
3995             }
3996           else
3997             {
3998               offset_rtx = XEXP (mem_addr, 1);
3999             }
4000         }
4001       else if (GET_CODE (XEXP (mem_addr, 0)) == PLUS)
4002         {
4003           /* intel1 */
4004           if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == PLUS &&
4005               GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0)) == MULT &&
4006               GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 0)) == REG &&
4007               GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 1)) == CONST_INT &&
4008               GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)) == CONST_INT &&
4009               GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == REG &&
4010               GET_CODE (XEXP (mem_addr, 1)) == SYMBOL_REF)
4011             {
4012               index_rtx = XEXP (XEXP (XEXP (mem_addr, 0), 0), 0);
4013               offset_rtx = XEXP (mem_addr, 1);
4014               base_rtx = XEXP (XEXP (mem_addr, 0), 1);
4015               offset_adjust = INTVAL (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1));
4016             }
4017           else
4018             {
4019               offset_rtx = XEXP (mem_addr, 1);
4020               index_rtx = XEXP (XEXP (mem_addr, 0), 0);
4021               base_rtx = XEXP (XEXP (mem_addr, 0), 1);
4022             }
4023         }
4024       else if (GET_CODE (XEXP (mem_addr, 0)) == CONST_INT)
4025         {
4026           was_only_offset = 1;
4027           index_rtx = NULL;
4028           base_rtx = NULL;
4029           offset_rtx = XEXP (mem_addr, 1);
4030           offset_adjust = INTVAL (XEXP (mem_addr, 0));
4031           if (offset_adjust == 0)
4032             {
4033               XEXP (mem_rtx, 0) = offset_rtx;
4034               RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
4035               return;
4036             }
4037         }
4038       else
4039         {
4040           obfree (storage);
4041           return;
4042         }
4043     }
4044   else if (GET_CODE (mem_addr) == MULT)
4045     {
4046       index_rtx = mem_addr;
4047     }
4048   else
4049     {
4050       obfree (storage);
4051       return;
4052     }
4053   if (index_rtx && GET_CODE (index_rtx) == MULT)
4054     {
4055       if (GET_CODE (XEXP (index_rtx, 1)) != CONST_INT)
4056         {
4057           obfree (storage);
4058           return;
4059         }
4060       scale_rtx = XEXP (index_rtx, 1);
4061       scale = INTVAL (scale_rtx);
4062       index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
4063     }
4064   /* now find which of the elements are invalid and try to fix them */
4065   if (index_rtx && GET_CODE (index_rtx) == CONST_INT && base_rtx == NULL)
4066     {
4067       offset_adjust = INTVAL (index_rtx) * scale;
4068       if (offset_rtx && GET_CODE (offset_rtx) == CONST &&
4069           GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
4070         {
4071           if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
4072               GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
4073             {
4074               offset_rtx = copy_all_rtx (offset_rtx);
4075               XEXP (XEXP (offset_rtx, 0), 1) =
4076                 gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
4077               if (!CONSTANT_P (offset_rtx))
4078                 {
4079                   obfree (storage);
4080                   return;
4081                 }
4082             }
4083         }
4084       else if (offset_rtx && GET_CODE (offset_rtx) == SYMBOL_REF)
4085         {
4086           offset_rtx =
4087             gen_rtx (CONST, GET_MODE (offset_rtx),
4088                      gen_rtx (PLUS, GET_MODE (offset_rtx),
4089                               offset_rtx,
4090                               gen_rtx (CONST_INT, 0, offset_adjust)));
4091           if (!CONSTANT_P (offset_rtx))
4092             {
4093               obfree (storage);
4094               return;
4095             }
4096         }
4097       else if (offset_rtx && GET_CODE (offset_rtx) == CONST_INT)
4098         {
4099           offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
4100         }
4101       else if (!offset_rtx)
4102         {
4103           offset_rtx = gen_rtx (CONST_INT, 0, 0);
4104         }
4105       RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
4106       XEXP (mem_rtx, 0) = offset_rtx;
4107       return;
4108     }
4109   if (base_rtx && GET_CODE (base_rtx) == PLUS &&
4110       GET_CODE (XEXP (base_rtx, 0)) == REG &&
4111       GET_CODE (XEXP (base_rtx, 1)) == CONST_INT)
4112     {
4113       offset_adjust += INTVAL (XEXP (base_rtx, 1));
4114       base_rtx = copy_all_rtx (XEXP (base_rtx, 0));
4115     }
4116   else if (base_rtx && GET_CODE (base_rtx) == CONST_INT)
4117     {
4118       offset_adjust += INTVAL (base_rtx);
4119       base_rtx = NULL;
4120     }
4121   if (index_rtx && GET_CODE (index_rtx) == PLUS &&
4122       GET_CODE (XEXP (index_rtx, 0)) == REG &&
4123       GET_CODE (XEXP (index_rtx, 1)) == CONST_INT)
4124     {
4125       offset_adjust += INTVAL (XEXP (index_rtx, 1)) * scale;
4126       index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
4127     }
4128   if (index_rtx)
4129     {
4130       if (!LEGITIMATE_INDEX_P (index_rtx)
4131       && !(index_rtx == stack_pointer_rtx && scale == 1 && base_rtx == NULL))
4132         {
4133           obfree (storage);
4134           return;
4135         }
4136     }
4137   if (base_rtx)
4138     {
4139       if (!LEGITIMATE_INDEX_P (base_rtx) && GET_CODE (base_rtx) != REG)
4140         {
4141           obfree (storage);
4142           return;
4143         }
4144     }
4145   if (offset_adjust != 0)
4146     {
4147       if (offset_rtx)
4148         {
4149           if (GET_CODE (offset_rtx) == CONST &&
4150               GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
4151             {
4152               if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
4153                   GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
4154                 {
4155                   offset_rtx = copy_all_rtx (offset_rtx);
4156                   XEXP (XEXP (offset_rtx, 0), 1) =
4157                     gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
4158                   if (!CONSTANT_P (offset_rtx))
4159                     {
4160                       obfree (storage);
4161                       return;
4162                     }
4163                 }
4164             }
4165           else if (GET_CODE (offset_rtx) == SYMBOL_REF)
4166             {
4167               offset_rtx =
4168                 gen_rtx (CONST, GET_MODE (offset_rtx),
4169                          gen_rtx (PLUS, GET_MODE (offset_rtx),
4170                                   offset_rtx,
4171                                   gen_rtx (CONST_INT, 0, offset_adjust)));
4172               if (!CONSTANT_P (offset_rtx))
4173                 {
4174                   obfree (storage);
4175                   return;
4176                 }
4177             }
4178           else if (GET_CODE (offset_rtx) == CONST_INT)
4179             {
4180               offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
4181             }
4182           else
4183             {
4184               obfree (storage);
4185               return;
4186             }
4187         }
4188       else
4189         {
4190           offset_rtx = gen_rtx (CONST_INT, 0, offset_adjust);
4191         }
4192       if (index_rtx)
4193         {
4194           if (base_rtx)
4195             {
4196               if (scale != 1)
4197                 {
4198                   if (GET_CODE (offset_rtx) == CONST_INT &&
4199                       INTVAL (offset_rtx) == 0)
4200                     {
4201                       ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx),
4202                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
4203                                       scale_rtx),
4204                                          base_rtx);
4205                     }
4206                   else
4207                     {
4208                       ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
4209                                          gen_rtx (PLUS, GET_MODE (base_rtx),
4210                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
4211                                       scale_rtx),
4212                                                   base_rtx),
4213                                          offset_rtx);
4214                     }
4215                 }
4216               else
4217                 {
4218                   if (GET_CODE (offset_rtx) == CONST_INT &&
4219                       INTVAL (offset_rtx) == 0)
4220                     {
4221                       ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, base_rtx);
4222                     }
4223                   else
4224                     {
4225                       ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
4226                              gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx,
4227                                       base_rtx),
4228                                          offset_rtx);
4229                     }
4230                 }
4231             }
4232           else
4233             {
4234               if (scale != 1)
4235                 {
4236                   if (GET_CODE (offset_rtx) == CONST_INT &&
4237                       INTVAL (offset_rtx) == 0)
4238                     {
4239                       ret_rtx = gen_rtx (MULT, GET_MODE (index_rtx), index_rtx, scale_rtx);
4240                     }
4241                   else
4242                     {
4243                       ret_rtx =
4244                         gen_rtx (PLUS, GET_MODE (offset_rtx),
4245                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
4246                                       scale_rtx),
4247                                  offset_rtx);
4248                     }
4249                 }
4250               else
4251                 {
4252                   if (GET_CODE (offset_rtx) == CONST_INT &&
4253                       INTVAL (offset_rtx) == 0)
4254                     {
4255                       ret_rtx = index_rtx;
4256                     }
4257                   else
4258                     {
4259                       ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, offset_rtx);
4260                     }
4261                 }
4262             }
4263         }
4264       else
4265         {
4266           if (base_rtx)
4267             {
4268               if (GET_CODE (offset_rtx) == CONST_INT &&
4269                   INTVAL (offset_rtx) == 0)
4270                 {
4271                   ret_rtx = base_rtx;
4272                 }
4273               else
4274                 {
4275                   ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx), base_rtx, offset_rtx);
4276                 }
4277             }
4278           else if (was_only_offset)
4279             {
4280               ret_rtx = offset_rtx;
4281             }
4282           else
4283             {
4284               obfree (storage);
4285               return;
4286             }
4287         }
4288       XEXP (mem_rtx, 0) = ret_rtx;
4289       RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
4290       return;
4291     }
4292   else
4293     {
4294       obfree (storage);
4295       return;
4296     }
4297 }
4298 #endif /* NOTYET */
4299
4300 \f
4301 /* return 1 if the first insn to set cc before insn also sets the register
4302    reg_rtx - otherwise return 0 */
4303 int
4304 last_to_set_cc (reg_rtx, insn)
4305      rtx reg_rtx, insn;
4306 {
4307   rtx prev_insn = PREV_INSN (insn);
4308
4309   while (prev_insn)
4310     {
4311       if (GET_CODE (prev_insn) == NOTE)
4312         ;
4313
4314       else if (GET_CODE (prev_insn) == INSN)
4315         {
4316           if (GET_CODE (PATTERN (prev_insn)) != SET)
4317             return (0);
4318
4319           if (rtx_equal_p (SET_DEST (PATTERN (prev_insn)), reg_rtx))
4320             {
4321               if (sets_condition_code (SET_SRC (PATTERN (prev_insn))))
4322                 return (1);
4323
4324               return (0);
4325             }
4326
4327           else if (!doesnt_set_condition_code (SET_SRC (PATTERN (prev_insn))))
4328             return (0);
4329         }
4330
4331       else
4332         return (0);
4333
4334       prev_insn = PREV_INSN (prev_insn);
4335     }
4336
4337   return (0);
4338 }
4339
4340 \f
4341 int
4342 doesnt_set_condition_code (pat)
4343      rtx pat;
4344 {
4345   switch (GET_CODE (pat))
4346     {
4347     case MEM:
4348     case REG:
4349       return (1);
4350
4351     default:
4352       return (0);
4353
4354     }
4355 }
4356
4357 \f
4358 int
4359 sets_condition_code (pat)
4360      rtx pat;
4361 {
4362   switch (GET_CODE (pat))
4363     {
4364     case PLUS:
4365     case MINUS:
4366     case AND:
4367     case IOR:
4368     case XOR:
4369     case NOT:
4370     case NEG:
4371     case MULT:
4372     case DIV:
4373     case MOD:
4374     case UDIV:
4375     case UMOD:
4376       return (1);
4377
4378     default:
4379       return (0);
4380
4381     }
4382 }
4383
4384 \f
4385 int
4386 str_immediate_operand (op, mode)
4387      register rtx op;
4388      enum machine_mode mode;
4389 {
4390   if (GET_CODE (op) == CONST_INT && INTVAL (op) <= 32 && INTVAL (op) >= 0)
4391     {
4392       return (1);
4393     }
4394   return (0);
4395 }
4396
4397 \f
4398 int
4399 is_fp_insn (insn)
4400      rtx insn;
4401 {
4402   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4403       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4404           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4405           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode))
4406     {
4407       return (1);
4408     }
4409
4410   return (0);
4411 }
4412
4413 /*
4414   Return 1 if the mode of the SET_DEST of insn is floating point
4415   and it is not an fld or a move from memory to memory.
4416   Otherwise return 0 */
4417 int
4418 is_fp_dest (insn)
4419      rtx insn;
4420 {
4421   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4422       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4423           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4424           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)
4425       && GET_CODE (SET_DEST (PATTERN (insn))) == REG
4426       && REGNO (SET_DEST (PATTERN (insn))) >= FIRST_FLOAT_REG
4427       && GET_CODE (SET_SRC (insn)) != MEM)
4428     {
4429       return (1);
4430     }
4431
4432   return (0);
4433 }
4434
4435 /*
4436   Return 1 if the mode of the SET_DEST floating point and is memory
4437   and the source is a register.  
4438 */
4439 int
4440 is_fp_store (insn)
4441      rtx insn;
4442 {
4443   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4444       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4445           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4446           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)
4447       && GET_CODE (SET_DEST (PATTERN (insn))) == MEM
4448       && GET_CODE (SET_SRC (PATTERN (insn))) == REG)
4449     {
4450       return (1);
4451     }
4452
4453   return (0);
4454 }
4455
4456 \f
4457 /*
4458   Return 1 if dep_insn sets a register which insn uses as a base
4459   or index to reference memory.
4460   otherwise return 0 */
4461
4462 int
4463 agi_dependent (insn, dep_insn)
4464      rtx insn, dep_insn;
4465 {
4466   if (GET_CODE (dep_insn) == INSN
4467       && GET_CODE (PATTERN (dep_insn)) == SET
4468       && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG)
4469     {
4470       return (reg_mentioned_in_mem (SET_DEST (PATTERN (dep_insn)), insn));
4471     }
4472
4473   if (GET_CODE (dep_insn) == INSN && GET_CODE (PATTERN (dep_insn)) == SET
4474       && GET_CODE (SET_DEST (PATTERN (dep_insn))) == MEM
4475       && push_operand (SET_DEST (PATTERN (dep_insn)),
4476                        GET_MODE (SET_DEST (PATTERN (dep_insn)))))
4477     {
4478       return (reg_mentioned_in_mem (stack_pointer_rtx, insn));
4479     }
4480   
4481   return (0);
4482 }
4483
4484 \f
4485 /*
4486   Return 1 if reg is used in rtl as a base or index for a memory ref
4487   otherwise return 0. */
4488
4489 int
4490 reg_mentioned_in_mem (reg, rtl)
4491      rtx reg, rtl;
4492 {
4493   register char *fmt;
4494   register int i;
4495   register enum rtx_code code;
4496
4497   if (rtl == NULL)
4498     return (0);
4499
4500   code = GET_CODE (rtl);
4501
4502   switch (code)
4503     {
4504     case HIGH:
4505     case CONST_INT:
4506     case CONST:
4507     case CONST_DOUBLE:
4508     case SYMBOL_REF:
4509     case LABEL_REF:
4510     case PC:
4511     case CC0:
4512     case SUBREG:
4513       return (0);
4514
4515
4516     }
4517
4518   if (code == MEM && reg_mentioned_p (reg, rtl))
4519     return (1);
4520
4521   fmt = GET_RTX_FORMAT (code);
4522   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4523     {
4524       if (fmt[i] == 'E')
4525         {
4526           register int j;
4527           for (j = XVECLEN (rtl, i) - 1; j >= 0; j--)
4528             {
4529               if (reg_mentioned_in_mem (reg, XVECEXP (rtl, i, j)))
4530                 return 1;
4531             }
4532         }
4533
4534       else if (fmt[i] == 'e' && reg_mentioned_in_mem (reg, XEXP (rtl, i)))
4535         return 1;
4536     }
4537
4538   return (0);
4539 }
4540 \f
4541 /* Output the approprate insns for doing strlen if not just doing repnz; scasb
4542
4543    operands[0] = result, initialized with the startaddress
4544    operands[1] = alignment of the address.
4545    operands[2] = scratch register, initialized with the startaddress when
4546                  not aligned, otherwise undefined
4547
4548    This is just the body. It needs the initialisations mentioned above and
4549    some address computing at the end.  These things are done in i386.md.  */
4550
4551 char *
4552 output_strlen_unroll (operands)
4553      rtx operands[];
4554 {
4555   rtx xops[18];
4556
4557   xops[0] = operands[0];                /* Result */
4558   /*        operands[1];                 * Alignment */
4559   xops[1] = operands[2];                /* Scratch */
4560   xops[2] = GEN_INT (0);
4561   xops[3] = GEN_INT (2);
4562   xops[4] = GEN_INT (3);
4563   xops[5] = GEN_INT (4);
4564   /* xops[6] = gen_label_rtx ();         * label when aligned to 3-byte */
4565   /* xops[7] = gen_label_rtx ();         * label when aligned to 2-byte */
4566   xops[8] = gen_label_rtx ();           /* label of main loop */
4567   if(TARGET_USE_Q_REG && QI_REG_P (xops[1]))
4568     xops[9] = gen_label_rtx ();         /* pentium optimisation */
4569   xops[10] = gen_label_rtx ();          /* end label 2 */
4570   xops[11] = gen_label_rtx ();          /* end label 1 */
4571   xops[12] = gen_label_rtx ();          /* end label */
4572   /* xops[13]                            * Temporary used */
4573   xops[14] = GEN_INT (0xff);
4574   xops[15] = GEN_INT (0xff00);
4575   xops[16] = GEN_INT (0xff0000);
4576   xops[17] = GEN_INT (0xff000000);
4577
4578     /* Loop to check 1..3 bytes for null to get an aligned pointer */
4579
4580     /* is there a known alignment and is it less then 4 */
4581   if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) < 4)
4582     {
4583         /* is there a known alignment and is it not 2 */
4584       if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2)
4585         {
4586           xops[6] = gen_label_rtx ();   /* label when aligned to 3-byte */
4587           xops[7] = gen_label_rtx ();   /* label when aligned to 2-byte */
4588
4589             /* leave just the 3 lower bits */
4590             /* if this is a q-register, then the high part is used later */
4591             /* therefore user andl rather than andb */
4592           output_asm_insn (AS2 (and%L1,%4,%1), xops);
4593             /* is aligned to 4-byte adress when zero */
4594           output_asm_insn (AS1 (je,%l8), xops);
4595             /* side-effect even Parity when %eax == 3 */
4596           output_asm_insn (AS1 (jp,%6), xops);
4597
4598             /* is it aligned to 2 bytes ? */
4599           if (QI_REG_P (xops[1]))
4600             output_asm_insn (AS2 (cmp%L1,%3,%1), xops);
4601           else
4602             output_asm_insn (AS2 (cmp%L1,%3,%1), xops);
4603           output_asm_insn (AS1 (je,%7), xops);
4604         }
4605       else
4606         {
4607             /* since the alignment is 2, we have to check 2 or 0 bytes */
4608
4609             /* check if is aligned to 4 - byte */
4610           output_asm_insn (AS2 (and%L1,%3,%1), xops);
4611             /* is aligned to 4-byte adress when zero */
4612           output_asm_insn (AS1 (je,%l8), xops);
4613         }
4614
4615       xops[13] = gen_rtx (MEM, QImode, xops[0]);
4616         /* now, compare the bytes */
4617         /* compare with the high part of a q-reg gives shorter code */
4618       if (QI_REG_P (xops[1]))
4619         {
4620             /* compare the first n unaligned byte on a byte per byte basis */
4621           output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4622             /* when zero we reached the end */
4623           output_asm_insn (AS1 (je,%l12), xops);
4624             /* increment the address */
4625           output_asm_insn (AS1 (inc%L0,%0), xops);
4626
4627             /* not needed with an alignment of 2 */
4628           if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2)
4629             {
4630               ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[7]));
4631               output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4632               output_asm_insn (AS1 (je,%l12), xops);
4633               output_asm_insn (AS1 (inc%L0,%0), xops);
4634
4635               ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[6]));
4636             }
4637           output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4638         }
4639       else
4640         {
4641           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4642           output_asm_insn (AS1 (je,%l12), xops);
4643           output_asm_insn (AS1 (inc%L0,%0), xops);
4644
4645           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[7]));
4646           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4647           output_asm_insn (AS1 (je,%l12), xops);
4648           output_asm_insn (AS1 (inc%L0,%0), xops);
4649
4650           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[6]));
4651           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4652         }
4653       output_asm_insn (AS1 (je,%l12), xops);
4654       output_asm_insn (AS1 (inc%L0,%0), xops);
4655     }
4656
4657     /* Generate loop to check 4 bytes at a time */
4658     /* IMHO it is not a good idea to align this loop.  It gives only */
4659     /* huge programs, but does not help to speed up */
4660   /* ASM_OUTPUT_LOOP_ALIGN (asm_out_file); */
4661   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[8]));
4662
4663   xops[13] = gen_rtx (MEM, SImode, xops[0]);
4664   output_asm_insn (AS2 (mov%L1,%13,%1), xops);
4665
4666   if (QI_REG_P (xops[1]))
4667     {
4668       /* On i586 it is faster to combine the hi- and lo- part as
4669          a kind of lookahead.  If anding both yields zero, then one
4670          of both *could* be zero, otherwise none of both is zero;
4671          this saves one instruction, on i486 this is slower
4672          tested with P-90, i486DX2-66, AMD486DX2-66  */
4673       if(TARGET_PENTIUM)
4674         {
4675           output_asm_insn (AS2 (test%B1,%h1,%b1), xops);
4676           output_asm_insn (AS1 (jne,%l9), xops);
4677         }
4678
4679         /* check first byte */
4680       output_asm_insn (AS2 (test%B1,%b1,%b1), xops);
4681       output_asm_insn (AS1 (je,%l12), xops);
4682
4683         /* check second byte */
4684       output_asm_insn (AS2 (test%B1,%h1,%h1), xops);
4685       output_asm_insn (AS1 (je,%l11), xops);
4686
4687       if(TARGET_PENTIUM)
4688           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[9]));
4689     }
4690   else
4691     {
4692         /* check first byte */
4693       output_asm_insn (AS2 (test%L1,%14,%1), xops);
4694       output_asm_insn (AS1 (je,%l12), xops);
4695
4696         /* check second byte */
4697       output_asm_insn (AS2 (test%L1,%15,%1), xops);
4698       output_asm_insn (AS1 (je,%l11), xops);
4699     }
4700
4701     /* check third byte */
4702   output_asm_insn (AS2 (test%L1,%16,%1), xops);
4703   output_asm_insn (AS1 (je,%l10), xops);
4704   
4705     /* check fourth byte and increment address */
4706   output_asm_insn (AS2 (add%L0,%5,%0), xops);
4707   output_asm_insn (AS2 (test%L1,%17,%1), xops);
4708   output_asm_insn (AS1 (jne,%l8), xops);
4709
4710     /* now generate fixups when the compare stops within a 4-byte word */
4711   output_asm_insn (AS2 (sub%L0,%4,%0), xops);
4712
4713   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[10]));
4714   output_asm_insn (AS1 (inc%L0,%0), xops);
4715
4716   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[11]));
4717   output_asm_insn (AS1 (inc%L0,%0), xops);
4718
4719   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[12]));
4720
4721   RET;
4722 }