OSDN Git Service

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