OSDN Git Service

(asm_output_function_prefix, function_prologue): Setup
[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 = {
76   1,                                    /* cost of an add instruction */
77   1,                                    /* cost of a lea instruction */
78   3,                                    /* variable shift costs */
79   1,                                    /* constant shift costs */
80   12,                                   /* cost of starting a multiply */
81   1,                                    /* cost of multiply per each bit set */
82   25                                    /* 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
1678 static rtx pic_label_rtx;
1679
1680 /* This function generates code for -fpic that loads %ebx with
1681    with the return address of the caller and then returns.  */
1682 void
1683 asm_output_function_prefix (file, name)
1684     FILE * file;
1685     char * name;
1686 {
1687   rtx xops[2];
1688   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1689                                   || current_function_uses_const_pool);
1690   xops[0] = pic_offset_table_rtx;
1691   xops[1] = stack_pointer_rtx;
1692
1693   if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION)
1694     {
1695       pic_label_rtx = (rtx) gen_label_rtx ();
1696       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (pic_label_rtx));
1697       output_asm_insn ("movl (%1),%0", xops);
1698       output_asm_insn ("ret", xops);
1699     }
1700 }
1701
1702 /* This function generates the assembly code for function entry.
1703    FILE is an stdio stream to output the code to.
1704    SIZE is an int: how many units of temporary storage to allocate. */
1705
1706 void
1707 function_prologue (file, size)
1708      FILE *file;
1709      int size;
1710 {
1711   register int regno;
1712   int limit;
1713   rtx xops[4];
1714   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1715                                   || current_function_uses_const_pool);
1716
1717   xops[0] = stack_pointer_rtx;
1718   xops[1] = frame_pointer_rtx;
1719   xops[2] = GEN_INT (size);
1720   if (frame_pointer_needed)
1721     {
1722       output_asm_insn ("push%L1 %1", xops);
1723       output_asm_insn (AS2 (mov%L0,%0,%1), xops);
1724     }
1725
1726   if (size)
1727     output_asm_insn (AS2 (sub%L0,%2,%0), xops);
1728
1729   /* Note If use enter it is NOT reversed args.
1730      This one is not reversed from intel!!
1731      I think enter is slower.  Also sdb doesn't like it.
1732      But if you want it the code is:
1733      {
1734      xops[3] = const0_rtx;
1735      output_asm_insn ("enter %2,%3", xops);
1736      }
1737      */
1738   limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
1739   for (regno = limit - 1; regno >= 0; regno--)
1740     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1741         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1742       {
1743         xops[0] = gen_rtx (REG, SImode, regno);
1744         output_asm_insn ("push%L0 %0", xops);
1745       }
1746
1747   if (pic_reg_used && TARGET_PENTIUMPRO)
1748     {
1749       xops[0] = pic_offset_table_rtx;
1750       xops[1] = pic_label_rtx;
1751
1752       output_asm_insn (AS1 (call,%P1), xops);
1753       output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_,%0", xops);
1754     }
1755   else {
1756     xops[0] = pic_offset_table_rtx;
1757     xops[1] = (rtx) gen_label_rtx ();
1758  
1759     output_asm_insn (AS1 (call,%P1), xops);
1760     ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));
1761     output_asm_insn (AS1 (pop%L0,%0), xops);
1762     output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops);
1763   } 
1764 }
1765
1766 /* Return 1 if it is appropriate to emit `ret' instructions in the
1767    body of a function.  Do this only if the epilogue is simple, needing a
1768    couple of insns.  Prior to reloading, we can't tell how many registers
1769    must be saved, so return 0 then.
1770
1771    If NON_SAVING_SETJMP is defined and true, then it is not possible
1772    for the epilogue to be simple, so return 0.  This is a special case
1773    since NON_SAVING_SETJMP will not cause regs_ever_live to change until
1774    final, but jump_optimize may need to know sooner if a `return' is OK.  */
1775
1776 int
1777 simple_386_epilogue ()
1778 {
1779   int regno;
1780   int nregs = 0;
1781   int reglimit = (frame_pointer_needed
1782                   ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
1783   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1784                                   || current_function_uses_const_pool);
1785
1786 #ifdef NON_SAVING_SETJMP
1787   if (NON_SAVING_SETJMP && current_function_calls_setjmp)
1788     return 0;
1789 #endif
1790
1791   if (! reload_completed)
1792     return 0;
1793
1794   for (regno = reglimit - 1; regno >= 0; regno--)
1795     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1796         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1797       nregs++;
1798
1799   return nregs == 0 || ! frame_pointer_needed;
1800 }
1801
1802 \f
1803 /* This function generates the assembly code for function exit.
1804    FILE is an stdio stream to output the code to.
1805    SIZE is an int: how many units of temporary storage to deallocate. */
1806
1807 void
1808 function_epilogue (file, size)
1809      FILE *file;
1810      int size;
1811 {
1812   register int regno;
1813   register int nregs, limit;
1814   int offset;
1815   rtx xops[3];
1816   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1817                                   || current_function_uses_const_pool);
1818
1819   /* Compute the number of registers to pop */
1820
1821   limit = (frame_pointer_needed
1822            ? FRAME_POINTER_REGNUM
1823            : STACK_POINTER_REGNUM);
1824
1825   nregs = 0;
1826
1827   for (regno = limit - 1; regno >= 0; regno--)
1828     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1829         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1830       nregs++;
1831
1832   /* sp is often  unreliable so we must go off the frame pointer,
1833    */
1834
1835   /* In reality, we may not care if sp is unreliable, because we can
1836      restore the register relative to the frame pointer.  In theory,
1837      since each move is the same speed as a pop, and we don't need the
1838      leal, this is faster.  For now restore multiple registers the old
1839      way. */
1840
1841   offset = -size - (nregs * UNITS_PER_WORD);
1842
1843   xops[2] = stack_pointer_rtx;
1844
1845   if (nregs > 1 || ! frame_pointer_needed)
1846     {
1847       if (frame_pointer_needed)
1848         {
1849           xops[0] = adj_offsettable_operand (AT_BP (Pmode), offset);
1850           output_asm_insn (AS2 (lea%L2,%0,%2), xops);
1851         }
1852
1853       for (regno = 0; regno < limit; regno++)
1854         if ((regs_ever_live[regno] && ! call_used_regs[regno])
1855             || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1856           {
1857             xops[0] = gen_rtx (REG, SImode, regno);
1858             output_asm_insn ("pop%L0 %0", xops);
1859           }
1860     }
1861   else
1862     for (regno = 0; regno < limit; regno++)
1863       if ((regs_ever_live[regno] && ! call_used_regs[regno])
1864           || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1865         {
1866           xops[0] = gen_rtx (REG, SImode, regno);
1867           xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset);
1868           output_asm_insn (AS2 (mov%L0,%1,%0), xops);
1869           offset += 4;
1870         }
1871
1872   if (frame_pointer_needed)
1873     {
1874       /* If not an i386, mov & pop is faster than "leave". */
1875
1876       if (TARGET_USE_LEAVE)
1877         output_asm_insn ("leave", xops);
1878       else
1879         {
1880           xops[0] = frame_pointer_rtx;
1881           output_asm_insn (AS2 (mov%L2,%0,%2), xops);
1882           output_asm_insn ("pop%L0 %0", xops);
1883         }
1884     }
1885   else if (size)
1886     {
1887       /* If there is no frame pointer, we must still release the frame. */
1888
1889       xops[0] = GEN_INT (size);
1890       output_asm_insn (AS2 (add%L2,%0,%2), xops);
1891     }
1892
1893 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
1894   if (profile_block_flag == 2)
1895     {
1896       FUNCTION_BLOCK_PROFILER_EXIT(file);
1897     }
1898 #endif
1899
1900   if (current_function_pops_args && current_function_args_size)
1901     {
1902       xops[1] = GEN_INT (current_function_pops_args);
1903
1904       /* i386 can only pop 32K bytes (maybe 64K?  Is it signed?).  If
1905          asked to pop more, pop return address, do explicit add, and jump
1906          indirectly to the caller. */
1907
1908       if (current_function_pops_args >= 32768)
1909         {
1910           /* ??? Which register to use here? */
1911           xops[0] = gen_rtx (REG, SImode, 2);
1912           output_asm_insn ("pop%L0 %0", xops);
1913           output_asm_insn (AS2 (add%L2,%1,%2), xops);
1914           output_asm_insn ("jmp %*%0", xops);
1915         }
1916       else
1917           output_asm_insn ("ret %1", xops);
1918     }
1919   else
1920     output_asm_insn ("ret", xops);
1921 }
1922
1923 \f
1924 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
1925    that is a valid memory address for an instruction.
1926    The MODE argument is the machine mode for the MEM expression
1927    that wants to use this address.
1928
1929    On x86, legitimate addresses are:
1930         base                            movl (base),reg
1931         displacement                    movl disp,reg
1932         base + displacement             movl disp(base),reg
1933         index + base                    movl (base,index),reg
1934         (index + base) + displacement   movl disp(base,index),reg
1935         index*scale                     movl (,index,scale),reg
1936         index*scale + disp              movl disp(,index,scale),reg
1937         index*scale + base              movl (base,index,scale),reg
1938         (index*scale + base) + disp     movl disp(base,index,scale),reg
1939
1940         In each case, scale can be 1, 2, 4, 8.  */
1941
1942 /* This is exactly the same as print_operand_addr, except that
1943    it recognizes addresses instead of printing them.
1944
1945    It only recognizes address in canonical form.  LEGITIMIZE_ADDRESS should
1946    convert common non-canonical forms to canonical form so that they will
1947    be recognized.  */
1948
1949 #define ADDR_INVALID(msg,insn)                                          \
1950 do {                                                                    \
1951   if (TARGET_DEBUG_ADDR)                                                \
1952     {                                                                   \
1953       fprintf (stderr, msg);                                            \
1954       debug_rtx (insn);                                                 \
1955     }                                                                   \
1956 } while (0)
1957
1958 int
1959 legitimate_address_p (mode, addr, strict)
1960      enum machine_mode mode;
1961      register rtx addr;
1962      int strict;
1963 {
1964   rtx base  = NULL_RTX;
1965   rtx indx  = NULL_RTX;
1966   rtx scale = NULL_RTX;
1967   rtx disp  = NULL_RTX;
1968
1969   if (TARGET_DEBUG_ADDR)
1970     {
1971       fprintf (stderr,
1972                "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
1973                GET_MODE_NAME (mode), strict);
1974
1975       debug_rtx (addr);
1976     }
1977
1978   if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
1979       base = addr;                              /* base reg */
1980
1981   else if (GET_CODE (addr) == PLUS)
1982     {
1983       rtx op0 = XEXP (addr, 0);
1984       rtx op1 = XEXP (addr, 1);
1985       enum rtx_code code0 = GET_CODE (op0);
1986       enum rtx_code code1 = GET_CODE (op1);
1987
1988       if (code0 == REG || code0 == SUBREG)
1989         {
1990           if (code1 == REG || code1 == SUBREG)
1991             {
1992               indx = op0;                       /* index + base */
1993               base = op1;
1994             }
1995
1996           else
1997             {
1998               base = op0;                       /* base + displacement */
1999               disp = op1;
2000             }
2001         }
2002
2003       else if (code0 == MULT)
2004         {
2005           indx  = XEXP (op0, 0);
2006           scale = XEXP (op0, 1);
2007
2008           if (code1 == REG || code1 == SUBREG)
2009             base = op1;                         /* index*scale + base */
2010
2011           else
2012             disp = op1;                         /* index*scale + disp */
2013         }
2014
2015       else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)
2016         {
2017           indx  = XEXP (XEXP (op0, 0), 0);      /* index*scale + base + disp */
2018           scale = XEXP (XEXP (op0, 0), 1);
2019           base  = XEXP (op0, 1);
2020           disp  = op1;
2021         }
2022
2023       else if (code0 == PLUS)
2024         {
2025           indx = XEXP (op0, 0);                 /* index + base + disp */
2026           base = XEXP (op0, 1);
2027           disp = op1;
2028         }
2029
2030       else
2031         {
2032           ADDR_INVALID ("PLUS subcode is not valid.\n", op0);
2033           return FALSE;
2034         }
2035     }
2036
2037   else if (GET_CODE (addr) == MULT)
2038     {
2039       indx  = XEXP (addr, 0);                   /* index*scale */
2040       scale = XEXP (addr, 1);
2041     }
2042
2043   else
2044     disp = addr;                                /* displacement */
2045
2046   /* Allow arg pointer and stack pointer as index if there is not scaling */
2047   if (base && indx && !scale
2048       && (indx == arg_pointer_rtx || indx == stack_pointer_rtx))
2049     {
2050       rtx tmp = base;
2051       base = indx;
2052       indx = tmp;
2053     }
2054
2055   /* Validate base register */
2056   /* Don't allow SUBREG's here, it can lead to spill failures when the base
2057      is one word out of a two word structure, which is represented internally
2058      as a DImode int.  */
2059   if (base)
2060     {
2061       if (GET_CODE (base) != REG)
2062         {
2063           ADDR_INVALID ("Base is not a register.\n", base);
2064           return FALSE;
2065         }
2066
2067       if ((strict && !REG_OK_FOR_BASE_STRICT_P (base))
2068           || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base)))
2069         {
2070           ADDR_INVALID ("Base is not valid.\n", base);
2071           return FALSE;
2072         }
2073     }
2074
2075   /* Validate index register */
2076   /* Don't allow SUBREG's here, it can lead to spill failures when the index
2077      is one word out of a two word structure, which is represented internally
2078      as a DImode int.  */
2079   if (indx)
2080     {
2081       if (GET_CODE (indx) != REG)
2082         {
2083           ADDR_INVALID ("Index is not a register.\n", indx);
2084           return FALSE;
2085         }
2086
2087       if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx))
2088           || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx)))
2089         {
2090           ADDR_INVALID ("Index is not valid.\n", indx);
2091           return FALSE;
2092         }
2093     }
2094   else if (scale)
2095     abort ();                                   /* scale w/o index invalid */
2096
2097   /* Validate scale factor */
2098   if (scale)
2099     {
2100       HOST_WIDE_INT value;
2101
2102       if (GET_CODE (scale) != CONST_INT)
2103         {
2104           ADDR_INVALID ("Scale is not valid.\n", scale);
2105           return FALSE;
2106         }
2107
2108       value = INTVAL (scale);
2109       if (value != 1 && value != 2 && value != 4 && value != 8)
2110         {
2111           ADDR_INVALID ("Scale is not a good multiplier.\n", scale);
2112           return FALSE;
2113         }
2114     }
2115
2116   /* Validate displacement
2117      Constant pool addresses must be handled special.  They are
2118      considered legitimate addresses, but only if not used with regs.
2119      When printed, the output routines know to print the reference with the
2120      PIC reg, even though the PIC reg doesn't appear in the RTL. */
2121   if (disp)
2122     {
2123       if (GET_CODE (disp) == SYMBOL_REF
2124           && CONSTANT_POOL_ADDRESS_P (disp)
2125           && !base
2126           && !indx)
2127         ;
2128
2129       else if (!CONSTANT_ADDRESS_P (disp))
2130         {
2131           ADDR_INVALID ("Displacement is not valid.\n", disp);
2132           return FALSE;
2133         }
2134
2135       else if (GET_CODE (disp) == CONST_DOUBLE)
2136         {
2137           ADDR_INVALID ("Displacement is a const_double.\n", disp);
2138           return FALSE;
2139         }
2140
2141       else if (flag_pic && SYMBOLIC_CONST (disp)
2142                && base != pic_offset_table_rtx
2143                && (indx != pic_offset_table_rtx || scale != NULL_RTX))
2144         {
2145           ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
2146           return FALSE;
2147         }
2148
2149       else if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
2150                && (base != NULL_RTX || indx != NULL_RTX))
2151         {
2152           ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp);
2153           return FALSE;
2154         }
2155     }
2156
2157   if (TARGET_DEBUG_ADDR)
2158     fprintf (stderr, "Address is valid.\n");
2159
2160   /* Everything looks valid, return true */
2161   return TRUE;
2162 }
2163
2164 \f
2165 /* Return a legitimate reference for ORIG (an address) using the
2166    register REG.  If REG is 0, a new pseudo is generated.
2167
2168    There are three types of references that must be handled:
2169
2170    1. Global data references must load the address from the GOT, via
2171       the PIC reg.  An insn is emitted to do this load, and the reg is
2172       returned.
2173
2174    2. Static data references must compute the address as an offset
2175       from the GOT, whose base is in the PIC reg.  An insn is emitted to
2176       compute the address into a reg, and the reg is returned.  Static
2177       data objects have SYMBOL_REF_FLAG set to differentiate them from
2178       global data objects.
2179
2180    3. Constant pool addresses must be handled special.  They are
2181       considered legitimate addresses, but only if not used with regs.
2182       When printed, the output routines know to print the reference with the
2183       PIC reg, even though the PIC reg doesn't appear in the RTL.
2184
2185    GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
2186    reg also appears in the address (except for constant pool references,
2187    noted above).
2188
2189    "switch" statements also require special handling when generating
2190    PIC code.  See comments by the `casesi' insn in i386.md for details.  */
2191
2192 rtx
2193 legitimize_pic_address (orig, reg)
2194      rtx orig;
2195      rtx reg;
2196 {
2197   rtx addr = orig;
2198   rtx new = orig;
2199
2200   if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
2201     {
2202       if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
2203         reg = new = orig;
2204       else
2205         {
2206           if (reg == 0)
2207             reg = gen_reg_rtx (Pmode);
2208
2209           if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
2210               || GET_CODE (addr) == LABEL_REF)
2211             new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
2212           else
2213             new = gen_rtx (MEM, Pmode,
2214                            gen_rtx (PLUS, Pmode,
2215                                     pic_offset_table_rtx, orig));
2216
2217           emit_move_insn (reg, new);
2218         }
2219       current_function_uses_pic_offset_table = 1;
2220       return reg;
2221     }
2222   else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
2223     {
2224       rtx base;
2225
2226       if (GET_CODE (addr) == CONST)
2227         {
2228           addr = XEXP (addr, 0);
2229           if (GET_CODE (addr) != PLUS)
2230             abort ();
2231         }
2232
2233       if (XEXP (addr, 0) == pic_offset_table_rtx)
2234         return orig;
2235
2236       if (reg == 0)
2237         reg = gen_reg_rtx (Pmode);
2238
2239       base = legitimize_pic_address (XEXP (addr, 0), reg);
2240       addr = legitimize_pic_address (XEXP (addr, 1),
2241                                      base == reg ? NULL_RTX : reg);
2242
2243       if (GET_CODE (addr) == CONST_INT)
2244         return plus_constant (base, INTVAL (addr));
2245
2246       if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
2247         {
2248           base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
2249           addr = XEXP (addr, 1);
2250         }
2251         return gen_rtx (PLUS, Pmode, base, addr);
2252     }
2253   return new;
2254 }
2255 \f
2256
2257 /* Emit insns to move operands[1] into operands[0].  */
2258
2259 void
2260 emit_pic_move (operands, mode)
2261      rtx *operands;
2262      enum machine_mode mode;
2263 {
2264   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
2265
2266   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
2267     operands[1] = (rtx) force_reg (SImode, operands[1]);
2268   else
2269     operands[1] = legitimize_pic_address (operands[1], temp);
2270 }
2271
2272 \f
2273 /* Try machine-dependent ways of modifying an illegitimate address
2274    to be legitimate.  If we find one, return the new, valid address.
2275    This macro is used in only one place: `memory_address' in explow.c.
2276
2277    OLDX is the address as it was before break_out_memory_refs was called.
2278    In some cases it is useful to look at this to decide what needs to be done.
2279
2280    MODE and WIN are passed so that this macro can use
2281    GO_IF_LEGITIMATE_ADDRESS.
2282
2283    It is always safe for this macro to do nothing.  It exists to recognize
2284    opportunities to optimize the output.
2285
2286    For the 80386, we handle X+REG by loading X into a register R and
2287    using R+REG.  R will go in a general reg and indexing will be used.
2288    However, if REG is a broken-out memory address or multiplication,
2289    nothing needs to be done because REG can certainly go in a general reg.
2290
2291    When -fpic is used, special handling is needed for symbolic references.
2292    See comments by legitimize_pic_address in i386.c for details.  */
2293
2294 rtx
2295 legitimize_address (x, oldx, mode)
2296      register rtx x;
2297      register rtx oldx;
2298      enum machine_mode mode;
2299 {
2300   int changed = 0;
2301   unsigned log;
2302
2303   if (TARGET_DEBUG_ADDR)
2304     {
2305       fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode));
2306       debug_rtx (x);
2307     }
2308
2309   if (flag_pic && SYMBOLIC_CONST (x))
2310     return legitimize_pic_address (x, 0);
2311
2312   /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
2313   if (GET_CODE (x) == ASHIFT
2314       && GET_CODE (XEXP (x, 1)) == CONST_INT
2315       && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
2316     {
2317       changed = 1;
2318       x = gen_rtx (MULT, Pmode,
2319                    force_reg (Pmode, XEXP (x, 0)),
2320                    GEN_INT (1 << log));
2321     }
2322
2323   if (GET_CODE (x) == PLUS)
2324     {
2325       /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
2326       if (GET_CODE (XEXP (x, 0)) == ASHIFT
2327           && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
2328           && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4)
2329         {
2330           changed = 1;
2331           XEXP (x, 0) = gen_rtx (MULT, Pmode,
2332                                  force_reg (Pmode, XEXP (XEXP (x, 0), 0)),
2333                                  GEN_INT (1 << log));
2334         }
2335
2336       if (GET_CODE (XEXP (x, 1)) == ASHIFT
2337           && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
2338           && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4)
2339         {
2340           changed = 1;
2341           XEXP (x, 1) = gen_rtx (MULT, Pmode,
2342                                  force_reg (Pmode, XEXP (XEXP (x, 1), 0)),
2343                                  GEN_INT (1 << log));
2344         }
2345
2346       /* Put multiply first if it isn't already */
2347       if (GET_CODE (XEXP (x, 1)) == MULT)
2348         {
2349           rtx tmp = XEXP (x, 0);
2350           XEXP (x, 0) = XEXP (x, 1);
2351           XEXP (x, 1) = tmp;
2352           changed = 1;
2353         }
2354
2355       /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))
2356          into (plus (plus (mult (reg) (const)) (reg)) (const)).  This can be
2357          created by virtual register instantiation, register elimination, and
2358          similar optimizations.  */
2359       if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)
2360         {
2361           changed = 1;
2362           x = gen_rtx (PLUS, Pmode,
2363                        gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)),
2364                        XEXP (XEXP (x, 1), 1));
2365         }
2366
2367       /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)
2368          into (plus (plus (mult (reg) (const)) (reg)) (const)).  */
2369       else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
2370                && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
2371                && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
2372                && CONSTANT_P (XEXP (x, 1)))
2373         {
2374           rtx constant, other;
2375
2376           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
2377             {
2378               constant = XEXP (x, 1);
2379               other = XEXP (XEXP (XEXP (x, 0), 1), 1);
2380             }
2381           else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
2382             {
2383               constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
2384               other = XEXP (x, 1);
2385             }
2386           else
2387             constant = 0;
2388
2389           if (constant)
2390             {
2391               changed = 1;
2392               x = gen_rtx (PLUS, Pmode,
2393                            gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),
2394                                     XEXP (XEXP (XEXP (x, 0), 1), 0)),
2395                            plus_constant (other, INTVAL (constant)));
2396             }
2397         }
2398
2399       if (changed && legitimate_address_p (mode, x, FALSE))
2400         return x;
2401
2402       if (GET_CODE (XEXP (x, 0)) == MULT)
2403         {
2404           changed = 1;
2405           XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
2406         }
2407
2408       if (GET_CODE (XEXP (x, 1)) == MULT)
2409         {
2410           changed = 1;
2411           XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
2412         }
2413
2414       if (changed
2415           && GET_CODE (XEXP (x, 1)) == REG
2416           && GET_CODE (XEXP (x, 0)) == REG)
2417         return x;
2418
2419       if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))
2420         {
2421           changed = 1;
2422           x = legitimize_pic_address (x, 0);
2423         }
2424
2425       if (changed && legitimate_address_p (mode, x, FALSE))
2426         return x;
2427
2428       if (GET_CODE (XEXP (x, 0)) == REG)
2429         {
2430           register rtx temp = gen_reg_rtx (Pmode);
2431           register rtx val  = force_operand (XEXP (x, 1), temp);
2432           if (val != temp)
2433             emit_move_insn (temp, val);
2434
2435           XEXP (x, 1) = temp;
2436           return x;
2437         }
2438
2439       else if (GET_CODE (XEXP (x, 1)) == REG)
2440         {
2441           register rtx temp = gen_reg_rtx (Pmode);
2442           register rtx val  = force_operand (XEXP (x, 0), temp);
2443           if (val != temp)
2444             emit_move_insn (temp, val);
2445
2446           XEXP (x, 0) = temp;
2447           return x;
2448         }
2449     }
2450
2451   return x;
2452 }
2453
2454 \f
2455 /* Print an integer constant expression in assembler syntax.  Addition
2456    and subtraction are the only arithmetic that may appear in these
2457    expressions.  FILE is the stdio stream to write to, X is the rtx, and
2458    CODE is the operand print code from the output string.  */
2459
2460 static void
2461 output_pic_addr_const (file, x, code)
2462      FILE *file;
2463      rtx x;
2464      int code;
2465 {
2466   char buf[256];
2467
2468   switch (GET_CODE (x))
2469     {
2470     case PC:
2471       if (flag_pic)
2472         putc ('.', file);
2473       else
2474         abort ();
2475       break;
2476
2477     case SYMBOL_REF:
2478     case LABEL_REF:
2479       if (GET_CODE (x) == SYMBOL_REF)
2480         assemble_name (file, XSTR (x, 0));
2481       else
2482         {
2483           ASM_GENERATE_INTERNAL_LABEL (buf, "L",
2484                                        CODE_LABEL_NUMBER (XEXP (x, 0)));
2485           assemble_name (asm_out_file, buf);
2486         }
2487
2488       if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
2489         fprintf (file, "@GOTOFF(%%ebx)");
2490       else if (code == 'P')
2491         fprintf (file, "@PLT");
2492       else if (GET_CODE (x) == LABEL_REF)
2493         fprintf (file, "@GOTOFF");
2494       else if (! SYMBOL_REF_FLAG (x))
2495         fprintf (file, "@GOT");
2496       else
2497         fprintf (file, "@GOTOFF");
2498
2499       break;
2500
2501     case CODE_LABEL:
2502       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
2503       assemble_name (asm_out_file, buf);
2504       break;
2505
2506     case CONST_INT:
2507       fprintf (file, "%d", INTVAL (x));
2508       break;
2509
2510     case CONST:
2511       /* This used to output parentheses around the expression,
2512          but that does not work on the 386 (either ATT or BSD assembler).  */
2513       output_pic_addr_const (file, XEXP (x, 0), code);
2514       break;
2515
2516     case CONST_DOUBLE:
2517       if (GET_MODE (x) == VOIDmode)
2518         {
2519           /* We can use %d if the number is <32 bits and positive.  */
2520           if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
2521             fprintf (file, "0x%x%08x",
2522                      CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
2523           else
2524             fprintf (file, "%d", CONST_DOUBLE_LOW (x));
2525         }
2526       else
2527         /* We can't handle floating point constants;
2528            PRINT_OPERAND must handle them.  */
2529         output_operand_lossage ("floating constant misused");
2530       break;
2531
2532     case PLUS:
2533       /* Some assemblers need integer constants to appear last (eg masm).  */
2534       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
2535         {
2536           output_pic_addr_const (file, XEXP (x, 1), code);
2537           if (INTVAL (XEXP (x, 0)) >= 0)
2538             fprintf (file, "+");
2539           output_pic_addr_const (file, XEXP (x, 0), code);
2540         }
2541       else
2542         {
2543           output_pic_addr_const (file, XEXP (x, 0), code);
2544           if (INTVAL (XEXP (x, 1)) >= 0)
2545             fprintf (file, "+");
2546           output_pic_addr_const (file, XEXP (x, 1), code);
2547         }
2548       break;
2549
2550     case MINUS:
2551       output_pic_addr_const (file, XEXP (x, 0), code);
2552       fprintf (file, "-");
2553       output_pic_addr_const (file, XEXP (x, 1), code);
2554       break;
2555
2556     default:
2557       output_operand_lossage ("invalid expression as operand");
2558     }
2559 }
2560 \f
2561
2562 /* Append the correct conditional move suffix which corresponds to CODE */
2563
2564 static void
2565 put_condition_code (code, file)
2566     enum rtx_code code;
2567     FILE * file;
2568 {
2569   switch (code)
2570     {
2571       case NE: 
2572           if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2573             fputs ("b", file);
2574           else
2575             fputs ("ne", file);
2576           return;
2577       case EQ: 
2578           if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2579             fputs ("ae", file);
2580           else
2581             fputs ("e", file);
2582           return;
2583       case GE: 
2584           fputs ("ge", file); return;
2585       case GT: 
2586           fputs ("g", file); return;
2587       case LE: 
2588           fputs ("le", file); return;
2589       case LT: 
2590           fputs ("l", file); return;
2591       case GEU: 
2592           fputs ("ae", file); return;
2593       case GTU: 
2594           fputs ("a", file); return;
2595       case LEU: 
2596           fputs ("be", file); return;
2597       case LTU: 
2598           fputs ("b", file); return;
2599       default: output_operand_lossage ("Invalid %%C operand");
2600     }
2601 }
2602
2603 /* Meaning of CODE:
2604    f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
2605    D,L,W,B,Q,S -- print the opcode suffix for specified size of operand.
2606    C -- print opcode suffix for set/cmov insn.
2607    N -- like C, but print reversed condition
2608    R -- print the prefix for register names.
2609    z -- print the opcode suffix for the size of the current operand.
2610    * -- print a star (in certain assembler syntax)
2611    w -- print the operand as if it's a "word" (HImode) even if it isn't.
2612    c -- don't print special prefixes before constant operands.
2613    J -- print the appropriate jump operand.
2614 */
2615
2616 void
2617 print_operand (file, x, code)
2618      FILE *file;
2619      rtx x;
2620      int code;
2621 {
2622   if (code)
2623     {
2624       switch (code)
2625         {
2626         case '*':
2627           if (USE_STAR)
2628             putc ('*', file);
2629           return;
2630
2631         case 'L':
2632           PUT_OP_SIZE (code, 'l', file);
2633           return;
2634
2635         case 'W':
2636           PUT_OP_SIZE (code, 'w', file);
2637           return;
2638
2639         case 'B':
2640           PUT_OP_SIZE (code, 'b', file);
2641           return;
2642
2643         case 'Q':
2644           PUT_OP_SIZE (code, 'l', file);
2645           return;
2646
2647         case 'S':
2648           PUT_OP_SIZE (code, 's', file);
2649           return;
2650
2651         case 'T':
2652           PUT_OP_SIZE (code, 't', file);
2653           return;
2654
2655         case 'z':
2656           /* 387 opcodes don't get size suffixes if the operands are
2657              registers. */
2658
2659           if (STACK_REG_P (x))
2660             return;
2661
2662           /* this is the size of op from size of operand */
2663           switch (GET_MODE_SIZE (GET_MODE (x)))
2664             {
2665             case 1:
2666               PUT_OP_SIZE ('B', 'b', file);
2667               return;
2668
2669             case 2:
2670               PUT_OP_SIZE ('W', 'w', file);
2671               return;
2672
2673             case 4:
2674               if (GET_MODE (x) == SFmode)
2675                 {
2676                   PUT_OP_SIZE ('S', 's', file);
2677                   return;
2678                 }
2679               else
2680                 PUT_OP_SIZE ('L', 'l', file);
2681               return;
2682
2683             case 12:
2684                   PUT_OP_SIZE ('T', 't', file);
2685                   return;
2686
2687             case 8:
2688               if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
2689                 {
2690 #ifdef GAS_MNEMONICS
2691                   PUT_OP_SIZE ('Q', 'q', file);
2692                   return;
2693 #else
2694                   PUT_OP_SIZE ('Q', 'l', file); /* Fall through */
2695 #endif
2696                 }
2697
2698               PUT_OP_SIZE ('Q', 'l', file);
2699               return;
2700             }
2701
2702         case 'b':
2703         case 'w':
2704         case 'k':
2705         case 'h':
2706         case 'y':
2707         case 'P':
2708           break;
2709
2710         case 'J':
2711           switch (GET_CODE (x))
2712             {
2713               /* These conditions are appropriate for testing the result
2714                  of an arithmetic operation, not for a compare operation.
2715                  Cases GE, LT assume CC_NO_OVERFLOW true. All cases assume
2716                  CC_Z_IN_NOT_C false and not floating point.  */
2717             case NE:  fputs ("jne", file); return;
2718             case EQ:  fputs ("je",  file); return;
2719             case GE:  fputs ("jns", file); return;
2720             case LT:  fputs ("js",  file); return;
2721             case GEU: fputs ("jmp", file); return;
2722             case GTU: fputs ("jne",  file); return;
2723             case LEU: fputs ("je", file); return;
2724             case LTU: fputs ("#branch never",  file); return;
2725
2726             /* no matching branches for GT nor LE */
2727             }
2728           abort ();
2729
2730       /* This is used by the conditional move instructions.  */
2731     case 'C':
2732         put_condition_code (GET_CODE (x), file);
2733         return;
2734       /* like above but reverse condition */
2735     case 'N':
2736         put_condition_code (reverse_condition (GET_CODE (x)), file);
2737         return;
2738
2739         default:
2740           {
2741             char str[50];
2742
2743             sprintf (str, "invalid operand code `%c'", code);
2744             output_operand_lossage (str);
2745           }
2746         }
2747     }
2748   if (GET_CODE (x) == REG)
2749     {
2750       PRINT_REG (x, code, file);
2751     }
2752   else if (GET_CODE (x) == MEM)
2753     {
2754       PRINT_PTR (x, file);
2755       if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
2756         {
2757           if (flag_pic)
2758             output_pic_addr_const (file, XEXP (x, 0), code);
2759           else
2760             output_addr_const (file, XEXP (x, 0));
2761         }
2762       else
2763         output_address (XEXP (x, 0));
2764     }
2765   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
2766     {
2767       REAL_VALUE_TYPE r; long l;
2768       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2769       REAL_VALUE_TO_TARGET_SINGLE (r, l);
2770       PRINT_IMMED_PREFIX (file);
2771       fprintf (file, "0x%x", l);
2772     }
2773  /* These float cases don't actually occur as immediate operands. */
2774  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
2775     {
2776       REAL_VALUE_TYPE r; char dstr[30];
2777       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2778       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
2779       fprintf (file, "%s", dstr);
2780     }
2781   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode)
2782     {
2783       REAL_VALUE_TYPE r; char dstr[30];
2784       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2785       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
2786       fprintf (file, "%s", dstr);
2787     }
2788   else 
2789     {
2790       if (code != 'P')
2791         {
2792           if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
2793             PRINT_IMMED_PREFIX (file);
2794           else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
2795                    || GET_CODE (x) == LABEL_REF)
2796             PRINT_OFFSET_PREFIX (file);
2797         }
2798       if (flag_pic)
2799         output_pic_addr_const (file, x, code);
2800       else
2801         output_addr_const (file, x);
2802     }
2803 }
2804 \f
2805 /* Print a memory operand whose address is ADDR.  */
2806
2807 void
2808 print_operand_address (file, addr)
2809      FILE *file;
2810      register rtx addr;
2811 {
2812   register rtx reg1, reg2, breg, ireg;
2813   rtx offset;
2814
2815   switch (GET_CODE (addr))
2816     {
2817     case REG:
2818       ADDR_BEG (file);
2819       fprintf (file, "%se", RP);
2820       fputs (hi_reg_name[REGNO (addr)], file);
2821       ADDR_END (file);
2822       break;
2823
2824     case PLUS:
2825       reg1 = 0;
2826       reg2 = 0;
2827       ireg = 0;
2828       breg = 0;
2829       offset = 0;
2830       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
2831         {
2832           offset = XEXP (addr, 0);
2833           addr = XEXP (addr, 1);
2834         }
2835       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
2836         {
2837           offset = XEXP (addr, 1);
2838           addr = XEXP (addr, 0);
2839         }
2840       if (GET_CODE (addr) != PLUS) ;
2841       else if (GET_CODE (XEXP (addr, 0)) == MULT)
2842         {
2843           reg1 = XEXP (addr, 0);
2844           addr = XEXP (addr, 1);
2845         }
2846       else if (GET_CODE (XEXP (addr, 1)) == MULT)
2847         {
2848           reg1 = XEXP (addr, 1);
2849           addr = XEXP (addr, 0);
2850         }
2851       else if (GET_CODE (XEXP (addr, 0)) == REG)
2852         {
2853           reg1 = XEXP (addr, 0);
2854           addr = XEXP (addr, 1);
2855         }
2856       else if (GET_CODE (XEXP (addr, 1)) == REG)
2857         {
2858           reg1 = XEXP (addr, 1);
2859           addr = XEXP (addr, 0);
2860         }
2861       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
2862         {
2863           if (reg1 == 0) reg1 = addr;
2864           else reg2 = addr;
2865           addr = 0;
2866         }
2867       if (offset != 0)
2868         {
2869           if (addr != 0) abort ();
2870           addr = offset;
2871         }
2872       if ((reg1 && GET_CODE (reg1) == MULT)
2873           || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
2874         {
2875           breg = reg2;
2876           ireg = reg1;
2877         }
2878       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
2879         {
2880           breg = reg1;
2881           ireg = reg2;
2882         }
2883
2884       if (ireg != 0 || breg != 0)
2885         {
2886           int scale = 1;
2887
2888           if (addr != 0)
2889             {
2890               if (flag_pic)
2891                 output_pic_addr_const (file, addr, 0);
2892
2893               else if (GET_CODE (addr) == LABEL_REF)
2894                 output_asm_label (addr);
2895
2896               else
2897                 output_addr_const (file, addr);
2898             }
2899
2900           if (ireg != 0 && GET_CODE (ireg) == MULT)
2901             {
2902               scale = INTVAL (XEXP (ireg, 1));
2903               ireg = XEXP (ireg, 0);
2904             }
2905
2906           /* The stack pointer can only appear as a base register,
2907              never an index register, so exchange the regs if it is wrong. */
2908
2909           if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)
2910             {
2911               rtx tmp;
2912
2913               tmp = breg;
2914               breg = ireg;
2915               ireg = tmp;
2916             }
2917
2918           /* output breg+ireg*scale */
2919           PRINT_B_I_S (breg, ireg, scale, file);
2920           break;
2921         }
2922
2923     case MULT:
2924       {
2925         int scale;
2926         if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
2927           {
2928             scale = INTVAL (XEXP (addr, 0));
2929             ireg = XEXP (addr, 1);
2930           }
2931         else
2932           {
2933             scale = INTVAL (XEXP (addr, 1));
2934             ireg = XEXP (addr, 0);
2935           }
2936         output_addr_const (file, const0_rtx);
2937         PRINT_B_I_S ((rtx) 0, ireg, scale, file);
2938       }
2939       break;
2940
2941     default:
2942       if (GET_CODE (addr) == CONST_INT
2943           && INTVAL (addr) < 0x8000
2944           && INTVAL (addr) >= -0x8000)
2945         fprintf (file, "%d", INTVAL (addr));
2946       else
2947         {
2948           if (flag_pic)
2949             output_pic_addr_const (file, addr, 0);
2950           else
2951             output_addr_const (file, addr);
2952         }
2953     }
2954 }
2955 \f
2956 /* Set the cc_status for the results of an insn whose pattern is EXP.
2957    On the 80386, we assume that only test and compare insns, as well
2958    as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT,
2959    ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
2960    Also, we assume that jumps, moves and sCOND don't affect the condition
2961    codes.  All else clobbers the condition codes, by assumption.
2962
2963    We assume that ALL integer add, minus, etc. instructions effect the
2964    condition codes.  This MUST be consistent with i386.md.
2965
2966    We don't record any float test or compare - the redundant test &
2967    compare check in final.c does not handle stack-like regs correctly. */
2968
2969 void
2970 notice_update_cc (exp)
2971      rtx exp;
2972 {
2973   if (GET_CODE (exp) == SET)
2974     {
2975       /* Jumps do not alter the cc's.  */
2976       if (SET_DEST (exp) == pc_rtx)
2977         return;
2978 #ifdef IS_STACK_MODE
2979       /* Moving into a memory of stack_mode may have been moved
2980          in between the use and set of cc0 by loop_spl(). So
2981          old value of cc.status must be retained */
2982       if(GET_CODE(SET_DEST(exp))==MEM 
2983          && IS_STACK_MODE(GET_MODE(SET_DEST(exp))))
2984         {
2985           return;
2986         }
2987 #endif
2988       /* Moving register or memory into a register:
2989          it doesn't alter the cc's, but it might invalidate
2990          the RTX's which we remember the cc's came from.
2991          (Note that moving a constant 0 or 1 MAY set the cc's).  */
2992       if (REG_P (SET_DEST (exp))
2993           && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM
2994               || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
2995         {
2996           if (cc_status.value1
2997               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
2998             cc_status.value1 = 0;
2999           if (cc_status.value2
3000               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
3001             cc_status.value2 = 0;
3002           return;
3003         }
3004       /* Moving register into memory doesn't alter the cc's.
3005          It may invalidate the RTX's which we remember the cc's came from.  */
3006       if (GET_CODE (SET_DEST (exp)) == MEM
3007           && (REG_P (SET_SRC (exp))
3008               || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
3009         {
3010           if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
3011               || reg_mentioned_p (SET_DEST (exp), cc_status.value1))
3012             cc_status.value1 = 0;
3013           if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM
3014               || reg_mentioned_p (SET_DEST (exp), cc_status.value2))
3015             cc_status.value2 = 0;
3016           return;
3017         }
3018       /* Function calls clobber the cc's.  */
3019       else if (GET_CODE (SET_SRC (exp)) == CALL)
3020         {
3021           CC_STATUS_INIT;
3022           return;
3023         }
3024       /* Tests and compares set the cc's in predictable ways.  */
3025       else if (SET_DEST (exp) == cc0_rtx)
3026         {
3027           CC_STATUS_INIT;
3028           cc_status.value1 = SET_SRC (exp);
3029           return;
3030         }
3031       /* Certain instructions effect the condition codes. */
3032       else if (GET_MODE (SET_SRC (exp)) == SImode
3033                || GET_MODE (SET_SRC (exp)) == HImode
3034                || GET_MODE (SET_SRC (exp)) == QImode)
3035         switch (GET_CODE (SET_SRC (exp)))
3036           {
3037           case ASHIFTRT: case LSHIFTRT:
3038           case ASHIFT:
3039             /* Shifts on the 386 don't set the condition codes if the
3040                shift count is zero. */
3041             if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
3042               {
3043                 CC_STATUS_INIT;
3044                 break;
3045               }
3046             /* We assume that the CONST_INT is non-zero (this rtx would
3047                have been deleted if it were zero. */
3048
3049           case PLUS: case MINUS: case NEG:
3050           case AND: case IOR: case XOR:
3051             cc_status.flags = CC_NO_OVERFLOW;
3052             cc_status.value1 = SET_SRC (exp);
3053             cc_status.value2 = SET_DEST (exp);
3054             break;
3055
3056           default:
3057             CC_STATUS_INIT;
3058           }
3059       else
3060         {
3061           CC_STATUS_INIT;
3062         }
3063     }
3064   else if (GET_CODE (exp) == PARALLEL
3065            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
3066     {
3067       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
3068         return;
3069       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
3070         {
3071           CC_STATUS_INIT;
3072           if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
3073             cc_status.flags |= CC_IN_80387;
3074           else
3075             cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
3076           return;
3077         }
3078       CC_STATUS_INIT;
3079     }
3080   else
3081     {
3082       CC_STATUS_INIT;
3083     }
3084 }
3085 \f
3086 /* Split one or more DImode RTL references into pairs of SImode
3087    references.  The RTL can be REG, offsettable MEM, integer constant, or
3088    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
3089    split and "num" is its length.  lo_half and hi_half are output arrays
3090    that parallel "operands". */
3091
3092 void
3093 split_di (operands, num, lo_half, hi_half)
3094      rtx operands[];
3095      int num;
3096      rtx lo_half[], hi_half[];
3097 {
3098   while (num--)
3099     {
3100       if (GET_CODE (operands[num]) == REG)
3101         {
3102           lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
3103           hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
3104         }
3105       else if (CONSTANT_P (operands[num]))
3106         {
3107           split_double (operands[num], &lo_half[num], &hi_half[num]);
3108         }
3109       else if (offsettable_memref_p (operands[num]))
3110         {
3111           lo_half[num] = operands[num];
3112           hi_half[num] = adj_offsettable_operand (operands[num], 4);
3113         }
3114       else
3115         abort();
3116     }
3117 }
3118 \f
3119 /* Return 1 if this is a valid binary operation on a 387.
3120    OP is the expression matched, and MODE is its mode. */
3121
3122 int
3123 binary_387_op (op, mode)
3124     register rtx op;
3125     enum machine_mode mode;
3126 {
3127   if (mode != VOIDmode && mode != GET_MODE (op))
3128     return 0;
3129
3130   switch (GET_CODE (op))
3131     {
3132     case PLUS:
3133     case MINUS:
3134     case MULT:
3135     case DIV:
3136       return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;
3137
3138     default:
3139       return 0;
3140     }
3141 }
3142
3143 \f
3144 /* Return 1 if this is a valid shift or rotate operation on a 386.
3145    OP is the expression matched, and MODE is its mode. */
3146
3147 int
3148 shift_op (op, mode)
3149     register rtx op;
3150     enum machine_mode mode;
3151 {
3152   rtx operand = XEXP (op, 0);
3153
3154   if (mode != VOIDmode && mode != GET_MODE (op))
3155     return 0;
3156
3157   if (GET_MODE (operand) != GET_MODE (op)
3158       || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
3159     return 0;
3160
3161   return (GET_CODE (op) == ASHIFT
3162           || GET_CODE (op) == ASHIFTRT
3163           || GET_CODE (op) == LSHIFTRT
3164           || GET_CODE (op) == ROTATE
3165           || GET_CODE (op) == ROTATERT);
3166 }
3167
3168 /* Return 1 if OP is COMPARE rtx with mode VOIDmode.
3169    MODE is not used.  */
3170
3171 int
3172 VOIDmode_compare_op (op, mode)
3173     register rtx op;
3174     enum machine_mode mode;
3175 {
3176   return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode;
3177 }
3178 \f
3179 /* Output code to perform a 387 binary operation in INSN, one of PLUS,
3180    MINUS, MULT or DIV.  OPERANDS are the insn operands, where operands[3]
3181    is the expression of the binary operation.  The output may either be
3182    emitted here, or returned to the caller, like all output_* functions.
3183
3184    There is no guarantee that the operands are the same mode, as they
3185    might be within FLOAT or FLOAT_EXTEND expressions. */
3186
3187 char *
3188 output_387_binary_op (insn, operands)
3189      rtx insn;
3190      rtx *operands;
3191 {
3192   rtx temp;
3193   char *base_op;
3194   static char buf[100];
3195
3196   switch (GET_CODE (operands[3]))
3197     {
3198     case PLUS:
3199       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3200           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3201         base_op = "fiadd";
3202       else
3203         base_op = "fadd";
3204       break;
3205
3206     case MINUS:
3207       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3208           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3209         base_op = "fisub";
3210       else
3211         base_op = "fsub";
3212       break;
3213
3214     case MULT:
3215       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3216           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3217         base_op = "fimul";
3218       else
3219         base_op = "fmul";
3220       break;
3221
3222     case DIV:
3223       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3224           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3225         base_op = "fidiv";
3226       else
3227         base_op = "fdiv";
3228       break;
3229
3230     default:
3231       abort ();
3232     }
3233
3234   strcpy (buf, base_op);
3235
3236   switch (GET_CODE (operands[3]))
3237     {
3238     case MULT:
3239     case PLUS:
3240       if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
3241         {
3242           temp = operands[2];
3243           operands[2] = operands[1];
3244           operands[1] = temp;
3245         }
3246
3247       if (GET_CODE (operands[2]) == MEM)
3248         return strcat (buf, AS1 (%z2,%2));
3249
3250       if (NON_STACK_REG_P (operands[1]))
3251         {
3252           output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
3253           RET;
3254         }
3255       else if (NON_STACK_REG_P (operands[2]))
3256         {
3257           output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
3258           RET;
3259         }
3260
3261       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
3262         return strcat (buf, AS2 (p,%2,%0));
3263
3264       if (STACK_TOP_P (operands[0]))
3265         return strcat (buf, AS2C (%y2,%0));
3266       else
3267         return strcat (buf, AS2C (%2,%0));
3268
3269     case MINUS:
3270     case DIV:
3271       if (GET_CODE (operands[1]) == MEM)
3272         return strcat (buf, AS1 (r%z1,%1));
3273
3274       if (GET_CODE (operands[2]) == MEM)
3275         return strcat (buf, AS1 (%z2,%2));
3276
3277       if (NON_STACK_REG_P (operands[1]))
3278         {
3279           output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));
3280           RET;
3281         }
3282       else if (NON_STACK_REG_P (operands[2]))
3283         {
3284           output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
3285           RET;
3286         }
3287
3288       if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
3289         abort ();
3290
3291       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
3292         return strcat (buf, AS2 (rp,%2,%0));
3293
3294       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3295         return strcat (buf, AS2 (p,%1,%0));
3296
3297       if (STACK_TOP_P (operands[0]))
3298         {
3299           if (STACK_TOP_P (operands[1]))
3300             return strcat (buf, AS2C (%y2,%0));
3301           else
3302             return strcat (buf, AS2 (r,%y1,%0));
3303         }
3304       else if (STACK_TOP_P (operands[1]))
3305         return strcat (buf, AS2C (%1,%0));
3306       else
3307         return strcat (buf, AS2 (r,%2,%0));
3308
3309     default:
3310       abort ();
3311     }
3312 }
3313 \f
3314 /* Output code for INSN to convert a float to a signed int.  OPERANDS
3315    are the insn operands.  The output may be SFmode or DFmode and the
3316    input operand may be SImode or DImode.  As a special case, make sure
3317    that the 387 stack top dies if the output mode is DImode, because the
3318    hardware requires this.  */
3319
3320 char *
3321 output_fix_trunc (insn, operands)
3322      rtx insn;
3323      rtx *operands;
3324 {
3325   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
3326   rtx xops[2];
3327
3328   if (! STACK_TOP_P (operands[1]) ||
3329       (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
3330     abort ();
3331
3332   xops[0] = GEN_INT (12);
3333   xops[1] = operands[4];
3334
3335   output_asm_insn (AS1 (fnstc%W2,%2), operands);
3336   output_asm_insn (AS2 (mov%L2,%2,%4), operands);
3337   output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
3338   output_asm_insn (AS2 (mov%L4,%4,%3), operands);
3339   output_asm_insn (AS1 (fldc%W3,%3), operands);
3340
3341   if (NON_STACK_REG_P (operands[0]))
3342     output_to_reg (operands[0], stack_top_dies);
3343   else if (GET_CODE (operands[0]) == MEM)
3344     {
3345       if (stack_top_dies)
3346         output_asm_insn (AS1 (fistp%z0,%0), operands);
3347       else
3348         output_asm_insn (AS1 (fist%z0,%0), operands);
3349     }
3350   else
3351     abort ();
3352
3353   return AS1 (fldc%W2,%2);
3354 }
3355 \f
3356 /* Output code for INSN to compare OPERANDS.  The two operands might
3357    not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
3358    expression.  If the compare is in mode CCFPEQmode, use an opcode that
3359    will not fault if a qNaN is present. */
3360
3361 char *
3362 output_float_compare (insn, operands)
3363      rtx insn;
3364      rtx *operands;
3365 {
3366   int stack_top_dies;
3367   rtx body = XVECEXP (PATTERN (insn), 0, 0);
3368   int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
3369
3370   rtx tmp;
3371   if (! STACK_TOP_P (operands[0]))
3372     {
3373       tmp = operands[0];
3374       operands[0] = operands[1];
3375       operands[1] = tmp;
3376       cc_status.flags |= CC_REVERSED;
3377     }
3378     
3379   if (! STACK_TOP_P (operands[0]))
3380     abort ();
3381
3382   stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
3383
3384   if (STACK_REG_P (operands[1])
3385       && stack_top_dies
3386       && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
3387       && REGNO (operands[1]) != FIRST_STACK_REG)
3388     {
3389       /* If both the top of the 387 stack dies, and the other operand
3390          is also a stack register that dies, then this must be a
3391          `fcompp' float compare */
3392
3393       if (unordered_compare)
3394         output_asm_insn ("fucompp", operands);
3395       else
3396         output_asm_insn ("fcompp", operands);
3397     }
3398   else
3399     {
3400       static char buf[100];
3401
3402       /* Decide if this is the integer or float compare opcode, or the
3403          unordered float compare. */
3404
3405       if (unordered_compare)
3406         strcpy (buf, "fucom");
3407       else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
3408         strcpy (buf, "fcom");
3409       else
3410         strcpy (buf, "ficom");
3411
3412       /* Modify the opcode if the 387 stack is to be popped. */
3413
3414       if (stack_top_dies)
3415         strcat (buf, "p");
3416
3417       if (NON_STACK_REG_P (operands[1]))
3418         output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
3419       else
3420         output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);
3421     }
3422
3423   /* Now retrieve the condition code. */
3424
3425   return output_fp_cc0_set (insn);
3426 }
3427 \f
3428 /* Output opcodes to transfer the results of FP compare or test INSN
3429    from the FPU to the CPU flags.  If TARGET_IEEE_FP, ensure that if the
3430    result of the compare or test is unordered, no comparison operator
3431    succeeds except NE.  Return an output template, if any.  */
3432
3433 char *
3434 output_fp_cc0_set (insn)
3435      rtx insn;
3436 {
3437   rtx xops[3];
3438   rtx unordered_label;
3439   rtx next;
3440   enum rtx_code code;
3441
3442   xops[0] = gen_rtx (REG, HImode, 0);
3443   output_asm_insn (AS1 (fnsts%W0,%0), xops);
3444
3445   if (! TARGET_IEEE_FP)
3446     {
3447       if (!(cc_status.flags & CC_REVERSED))
3448         {
3449           next = next_cc0_user (insn);
3450         
3451           if (GET_CODE (next) == JUMP_INSN
3452               && GET_CODE (PATTERN (next)) == SET
3453               && SET_DEST (PATTERN (next)) == pc_rtx
3454               && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3455             {
3456               code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3457             }
3458           else if (GET_CODE (PATTERN (next)) == SET)
3459             {
3460               code = GET_CODE (SET_SRC (PATTERN (next)));
3461             }
3462           else
3463             {
3464               return "sahf";
3465             }
3466           if (code == GT || code == LT || code == EQ || code == NE
3467               || code == LE || code == GE)
3468             { /* We will test eax directly */
3469               cc_status.flags |= CC_TEST_AX;
3470               RET;
3471             }
3472         }
3473       return "sahf";
3474     }
3475
3476   next = next_cc0_user (insn);
3477   if (next == NULL_RTX)
3478     abort ();
3479
3480   if (GET_CODE (next) == JUMP_INSN
3481       && GET_CODE (PATTERN (next)) == SET
3482       && SET_DEST (PATTERN (next)) == pc_rtx
3483       && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3484     {
3485       code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3486     }
3487   else if (GET_CODE (PATTERN (next)) == SET)
3488     {
3489       code = GET_CODE (SET_SRC (PATTERN (next)));
3490     }
3491   else
3492     abort ();
3493
3494   xops[0] = gen_rtx (REG, QImode, 0);
3495
3496   switch (code)
3497     {
3498     case GT:
3499       xops[1] = GEN_INT (0x45);
3500       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3501       /* je label */
3502       break;
3503
3504     case LT:
3505       xops[1] = GEN_INT (0x45);
3506       xops[2] = GEN_INT (0x01);
3507       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3508       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3509       /* je label */
3510       break;
3511
3512     case GE:
3513       xops[1] = GEN_INT (0x05);
3514       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3515       /* je label */
3516       break;
3517
3518     case LE:
3519       xops[1] = GEN_INT (0x45);
3520       xops[2] = GEN_INT (0x40);
3521       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3522       output_asm_insn (AS1 (dec%B0,%h0), xops);
3523       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3524       /* jb label */
3525       break;
3526
3527     case EQ:
3528       xops[1] = GEN_INT (0x45);
3529       xops[2] = GEN_INT (0x40);
3530       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3531       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3532       /* je label */
3533       break;
3534
3535     case NE:
3536       xops[1] = GEN_INT (0x44);
3537       xops[2] = GEN_INT (0x40);
3538       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3539       output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
3540       /* jne label */
3541       break;
3542
3543     case GTU:
3544     case LTU:
3545     case GEU:
3546     case LEU:
3547     default:
3548       abort ();
3549     }
3550   RET;
3551 }
3552 \f
3553 #define MAX_386_STACK_LOCALS 2
3554
3555 static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
3556
3557 /* Define the structure for the machine field in struct function.  */
3558 struct machine_function
3559 {
3560   rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
3561 };
3562
3563 /* Functions to save and restore i386_stack_locals.
3564    These will be called, via pointer variables,
3565    from push_function_context and pop_function_context.  */
3566
3567 void
3568 save_386_machine_status (p)
3569      struct function *p;
3570 {
3571   p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals);
3572   bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals,
3573          sizeof i386_stack_locals);
3574 }
3575
3576 void
3577 restore_386_machine_status (p)
3578      struct function *p;
3579 {
3580   bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals,
3581          sizeof i386_stack_locals);
3582   free (p->machine);
3583 }
3584
3585 /* Clear stack slot assignments remembered from previous functions.
3586    This is called from INIT_EXPANDERS once before RTL is emitted for each
3587    function.  */
3588
3589 void
3590 clear_386_stack_locals ()
3591 {
3592   enum machine_mode mode;
3593   int n;
3594
3595   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
3596        mode = (enum machine_mode) ((int) mode + 1))
3597     for (n = 0; n < MAX_386_STACK_LOCALS; n++)
3598       i386_stack_locals[(int) mode][n] = NULL_RTX;
3599
3600   /* Arrange to save and restore i386_stack_locals around nested functions.  */
3601   save_machine_status = save_386_machine_status;
3602   restore_machine_status = restore_386_machine_status;
3603 }
3604
3605 /* Return a MEM corresponding to a stack slot with mode MODE.
3606    Allocate a new slot if necessary.
3607
3608    The RTL for a function can have several slots available: N is
3609    which slot to use.  */
3610
3611 rtx
3612 assign_386_stack_local (mode, n)
3613      enum machine_mode mode;
3614      int n;
3615 {
3616   if (n < 0 || n >= MAX_386_STACK_LOCALS)
3617     abort ();
3618
3619   if (i386_stack_locals[(int) mode][n] == NULL_RTX)
3620     i386_stack_locals[(int) mode][n]
3621       = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
3622
3623   return i386_stack_locals[(int) mode][n];
3624 }
3625
3626 \f
3627 int is_mul(op,mode)
3628     register rtx op;
3629     enum machine_mode mode;
3630 {
3631   return (GET_CODE (op) == MULT);
3632 }
3633
3634 int is_div(op,mode)
3635     register rtx op;
3636     enum machine_mode mode;
3637 {
3638   return (GET_CODE (op) == DIV);
3639 }
3640
3641 \f
3642 #ifdef NOTYET
3643 /* Create a new copy of an rtx.
3644    Recursively copies the operands of the rtx,
3645    except for those few rtx codes that are sharable.
3646    Doesn't share CONST  */
3647
3648 rtx
3649 copy_all_rtx (orig)
3650      register rtx orig;
3651 {
3652   register rtx copy;
3653   register int i, j;
3654   register RTX_CODE code;
3655   register char *format_ptr;
3656
3657   code = GET_CODE (orig);
3658
3659   switch (code)
3660     {
3661     case REG:
3662     case QUEUED:
3663     case CONST_INT:
3664     case CONST_DOUBLE:
3665     case SYMBOL_REF:
3666     case CODE_LABEL:
3667     case PC:
3668     case CC0:
3669     case SCRATCH:
3670       /* SCRATCH must be shared because they represent distinct values. */
3671       return orig;
3672
3673 #if 0
3674     case CONST:
3675       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
3676          a LABEL_REF, it isn't sharable.  */
3677       if (GET_CODE (XEXP (orig, 0)) == PLUS
3678           && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
3679           && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT)
3680         return orig;
3681       break;
3682 #endif
3683       /* A MEM with a constant address is not sharable.  The problem is that
3684          the constant address may need to be reloaded.  If the mem is shared,
3685          then reloading one copy of this mem will cause all copies to appear
3686          to have been reloaded.  */
3687     }
3688
3689   copy = rtx_alloc (code);
3690   PUT_MODE (copy, GET_MODE (orig));
3691   copy->in_struct = orig->in_struct;
3692   copy->volatil = orig->volatil;
3693   copy->unchanging = orig->unchanging;
3694   copy->integrated = orig->integrated;
3695   /* intel1 */
3696   copy->is_spill_rtx = orig->is_spill_rtx;
3697   
3698   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
3699
3700   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
3701     {
3702       switch (*format_ptr++)
3703         {
3704         case 'e':
3705           XEXP (copy, i) = XEXP (orig, i);
3706           if (XEXP (orig, i) != NULL)
3707             XEXP (copy, i) = copy_rtx (XEXP (orig, i));
3708           break;
3709
3710         case '0':
3711         case 'u':
3712           XEXP (copy, i) = XEXP (orig, i);
3713           break;
3714
3715         case 'E':
3716         case 'V':
3717           XVEC (copy, i) = XVEC (orig, i);
3718           if (XVEC (orig, i) != NULL)
3719             {
3720               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
3721               for (j = 0; j < XVECLEN (copy, i); j++)
3722                 XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
3723             }
3724           break;
3725
3726         case 'w':
3727           XWINT (copy, i) = XWINT (orig, i);
3728           break;
3729
3730         case 'i':
3731           XINT (copy, i) = XINT (orig, i);
3732           break;
3733
3734         case 's':
3735         case 'S':
3736           XSTR (copy, i) = XSTR (orig, i);
3737           break;
3738
3739         default:
3740           abort ();
3741         }
3742     }
3743   return copy;
3744 }
3745
3746 \f
3747 /* try to rewrite a memory address to make it valid */
3748 void 
3749 rewrite_address (mem_rtx)
3750      rtx mem_rtx;
3751 {
3752   rtx index_rtx, base_rtx, offset_rtx, scale_rtx, ret_rtx;
3753   int scale = 1;
3754   int offset_adjust = 0;
3755   int was_only_offset = 0;
3756   rtx mem_addr = XEXP (mem_rtx, 0);
3757   char *storage = (char *) oballoc (0);
3758   int in_struct = 0;
3759   int is_spill_rtx = 0;
3760
3761   in_struct = MEM_IN_STRUCT_P (mem_rtx);
3762   is_spill_rtx = RTX_IS_SPILL_P (mem_rtx);
3763
3764   if (GET_CODE (mem_addr) == PLUS &&
3765       GET_CODE (XEXP (mem_addr, 1)) == PLUS &&
3766       GET_CODE (XEXP (XEXP (mem_addr, 1), 0)) == REG)
3767     {                           /* this part is utilized by the combiner */
3768       ret_rtx =
3769         gen_rtx (PLUS, GET_MODE (mem_addr),
3770                  gen_rtx (PLUS, GET_MODE (XEXP (mem_addr, 1)),
3771                           XEXP (mem_addr, 0),
3772                           XEXP (XEXP (mem_addr, 1), 0)),
3773                  XEXP (XEXP (mem_addr, 1), 1));
3774       if (memory_address_p (GET_MODE (mem_rtx), ret_rtx))
3775         {
3776           XEXP (mem_rtx, 0) = ret_rtx;
3777           RTX_IS_SPILL_P (ret_rtx) = is_spill_rtx;
3778           return;
3779         }
3780       obfree (storage);
3781     }
3782
3783   /* this part is utilized by loop.c */
3784   /* If the address contains PLUS (reg,const) and this pattern is invalid
3785      in this case - try to rewrite the address to make it valid  intel1
3786   */
3787   storage = (char *) oballoc (0);
3788   index_rtx = base_rtx = offset_rtx = NULL;
3789   /* find the base index and offset elements of the memory address */
3790   if (GET_CODE (mem_addr) == PLUS)
3791     {
3792       if (GET_CODE (XEXP (mem_addr, 0)) == REG)
3793         {
3794           if (GET_CODE (XEXP (mem_addr, 1)) == REG)
3795             {
3796               base_rtx = XEXP (mem_addr, 1);
3797               index_rtx = XEXP (mem_addr, 0);
3798             }
3799           else
3800             {
3801               base_rtx = XEXP (mem_addr, 0);
3802               offset_rtx = XEXP (mem_addr, 1);
3803             }
3804         }
3805       else if (GET_CODE (XEXP (mem_addr, 0)) == MULT)
3806         {
3807           index_rtx = XEXP (mem_addr, 0);
3808           if (GET_CODE (XEXP (mem_addr, 1)) == REG)
3809             {
3810               base_rtx = XEXP (mem_addr, 1);
3811             }
3812           else
3813             {
3814               offset_rtx = XEXP (mem_addr, 1);
3815             }
3816         }
3817       else if (GET_CODE (XEXP (mem_addr, 0)) == PLUS)
3818         {
3819           /* intel1 */
3820           if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == PLUS &&
3821               GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0)) == MULT &&
3822               GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 0)) == REG &&
3823               GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 1)) == CONST_INT &&
3824               GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)) == CONST_INT &&
3825               GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == REG &&
3826               GET_CODE (XEXP (mem_addr, 1)) == SYMBOL_REF)
3827             {
3828               index_rtx = XEXP (XEXP (XEXP (mem_addr, 0), 0), 0);
3829               offset_rtx = XEXP (mem_addr, 1);
3830               base_rtx = XEXP (XEXP (mem_addr, 0), 1);
3831               offset_adjust = INTVAL (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1));
3832             }
3833           else
3834             {
3835               offset_rtx = XEXP (mem_addr, 1);
3836               index_rtx = XEXP (XEXP (mem_addr, 0), 0);
3837               base_rtx = XEXP (XEXP (mem_addr, 0), 1);
3838             }
3839         }
3840       else if (GET_CODE (XEXP (mem_addr, 0)) == CONST_INT)
3841         {
3842           was_only_offset = 1;
3843           index_rtx = NULL;
3844           base_rtx = NULL;
3845           offset_rtx = XEXP (mem_addr, 1);
3846           offset_adjust = INTVAL (XEXP (mem_addr, 0));
3847           if (offset_adjust == 0)
3848             {
3849               XEXP (mem_rtx, 0) = offset_rtx;
3850               RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
3851               return;
3852             }
3853         }
3854       else
3855         {
3856           obfree (storage);
3857           return;
3858         }
3859     }
3860   else if (GET_CODE (mem_addr) == MULT)
3861     {
3862       index_rtx = mem_addr;
3863     }
3864   else
3865     {
3866       obfree (storage);
3867       return;
3868     }
3869   if (index_rtx && GET_CODE (index_rtx) == MULT)
3870     {
3871       if (GET_CODE (XEXP (index_rtx, 1)) != CONST_INT)
3872         {
3873           obfree (storage);
3874           return;
3875         }
3876       scale_rtx = XEXP (index_rtx, 1);
3877       scale = INTVAL (scale_rtx);
3878       index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
3879     }
3880   /* now find which of the elements are invalid and try to fix them */
3881   if (index_rtx && GET_CODE (index_rtx) == CONST_INT && base_rtx == NULL)
3882     {
3883       offset_adjust = INTVAL (index_rtx) * scale;
3884       if (offset_rtx && GET_CODE (offset_rtx) == CONST &&
3885           GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
3886         {
3887           if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
3888               GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
3889             {
3890               offset_rtx = copy_all_rtx (offset_rtx);
3891               XEXP (XEXP (offset_rtx, 0), 1) =
3892                 gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
3893               if (!CONSTANT_P (offset_rtx))
3894                 {
3895                   obfree (storage);
3896                   return;
3897                 }
3898             }
3899         }
3900       else if (offset_rtx && GET_CODE (offset_rtx) == SYMBOL_REF)
3901         {
3902           offset_rtx =
3903             gen_rtx (CONST, GET_MODE (offset_rtx),
3904                      gen_rtx (PLUS, GET_MODE (offset_rtx),
3905                               offset_rtx,
3906                               gen_rtx (CONST_INT, 0, offset_adjust)));
3907           if (!CONSTANT_P (offset_rtx))
3908             {
3909               obfree (storage);
3910               return;
3911             }
3912         }
3913       else if (offset_rtx && GET_CODE (offset_rtx) == CONST_INT)
3914         {
3915           offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
3916         }
3917       else if (!offset_rtx)
3918         {
3919           offset_rtx = gen_rtx (CONST_INT, 0, 0);
3920         }
3921       RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
3922       XEXP (mem_rtx, 0) = offset_rtx;
3923       return;
3924     }
3925   if (base_rtx && GET_CODE (base_rtx) == PLUS &&
3926       GET_CODE (XEXP (base_rtx, 0)) == REG &&
3927       GET_CODE (XEXP (base_rtx, 1)) == CONST_INT)
3928     {
3929       offset_adjust += INTVAL (XEXP (base_rtx, 1));
3930       base_rtx = copy_all_rtx (XEXP (base_rtx, 0));
3931     }
3932   else if (base_rtx && GET_CODE (base_rtx) == CONST_INT)
3933     {
3934       offset_adjust += INTVAL (base_rtx);
3935       base_rtx = NULL;
3936     }
3937   if (index_rtx && GET_CODE (index_rtx) == PLUS &&
3938       GET_CODE (XEXP (index_rtx, 0)) == REG &&
3939       GET_CODE (XEXP (index_rtx, 1)) == CONST_INT)
3940     {
3941       offset_adjust += INTVAL (XEXP (index_rtx, 1)) * scale;
3942       index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
3943     }
3944   if (index_rtx)
3945     {
3946       if (!LEGITIMATE_INDEX_P (index_rtx)
3947       && !(index_rtx == stack_pointer_rtx && scale == 1 && base_rtx == NULL))
3948         {
3949           obfree (storage);
3950           return;
3951         }
3952     }
3953   if (base_rtx)
3954     {
3955       if (!LEGITIMATE_INDEX_P (base_rtx) && GET_CODE (base_rtx) != REG)
3956         {
3957           obfree (storage);
3958           return;
3959         }
3960     }
3961   if (offset_adjust != 0)
3962     {
3963       if (offset_rtx)
3964         {
3965           if (GET_CODE (offset_rtx) == CONST &&
3966               GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
3967             {
3968               if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
3969                   GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
3970                 {
3971                   offset_rtx = copy_all_rtx (offset_rtx);
3972                   XEXP (XEXP (offset_rtx, 0), 1) =
3973                     gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
3974                   if (!CONSTANT_P (offset_rtx))
3975                     {
3976                       obfree (storage);
3977                       return;
3978                     }
3979                 }
3980             }
3981           else if (GET_CODE (offset_rtx) == SYMBOL_REF)
3982             {
3983               offset_rtx =
3984                 gen_rtx (CONST, GET_MODE (offset_rtx),
3985                          gen_rtx (PLUS, GET_MODE (offset_rtx),
3986                                   offset_rtx,
3987                                   gen_rtx (CONST_INT, 0, offset_adjust)));
3988               if (!CONSTANT_P (offset_rtx))
3989                 {
3990                   obfree (storage);
3991                   return;
3992                 }
3993             }
3994           else if (GET_CODE (offset_rtx) == CONST_INT)
3995             {
3996               offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
3997             }
3998           else
3999             {
4000               obfree (storage);
4001               return;
4002             }
4003         }
4004       else
4005         {
4006           offset_rtx = gen_rtx (CONST_INT, 0, offset_adjust);
4007         }
4008       if (index_rtx)
4009         {
4010           if (base_rtx)
4011             {
4012               if (scale != 1)
4013                 {
4014                   if (GET_CODE (offset_rtx) == CONST_INT &&
4015                       INTVAL (offset_rtx) == 0)
4016                     {
4017                       ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx),
4018                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
4019                                       scale_rtx),
4020                                          base_rtx);
4021                     }
4022                   else
4023                     {
4024                       ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
4025                                          gen_rtx (PLUS, GET_MODE (base_rtx),
4026                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
4027                                       scale_rtx),
4028                                                   base_rtx),
4029                                          offset_rtx);
4030                     }
4031                 }
4032               else
4033                 {
4034                   if (GET_CODE (offset_rtx) == CONST_INT &&
4035                       INTVAL (offset_rtx) == 0)
4036                     {
4037                       ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, base_rtx);
4038                     }
4039                   else
4040                     {
4041                       ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
4042                              gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx,
4043                                       base_rtx),
4044                                          offset_rtx);
4045                     }
4046                 }
4047             }
4048           else
4049             {
4050               if (scale != 1)
4051                 {
4052                   if (GET_CODE (offset_rtx) == CONST_INT &&
4053                       INTVAL (offset_rtx) == 0)
4054                     {
4055                       ret_rtx = gen_rtx (MULT, GET_MODE (index_rtx), index_rtx, scale_rtx);
4056                     }
4057                   else
4058                     {
4059                       ret_rtx =
4060                         gen_rtx (PLUS, GET_MODE (offset_rtx),
4061                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
4062                                       scale_rtx),
4063                                  offset_rtx);
4064                     }
4065                 }
4066               else
4067                 {
4068                   if (GET_CODE (offset_rtx) == CONST_INT &&
4069                       INTVAL (offset_rtx) == 0)
4070                     {
4071                       ret_rtx = index_rtx;
4072                     }
4073                   else
4074                     {
4075                       ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, offset_rtx);
4076                     }
4077                 }
4078             }
4079         }
4080       else
4081         {
4082           if (base_rtx)
4083             {
4084               if (GET_CODE (offset_rtx) == CONST_INT &&
4085                   INTVAL (offset_rtx) == 0)
4086                 {
4087                   ret_rtx = base_rtx;
4088                 }
4089               else
4090                 {
4091                   ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx), base_rtx, offset_rtx);
4092                 }
4093             }
4094           else if (was_only_offset)
4095             {
4096               ret_rtx = offset_rtx;
4097             }
4098           else
4099             {
4100               obfree (storage);
4101               return;
4102             }
4103         }
4104       XEXP (mem_rtx, 0) = ret_rtx;
4105       RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
4106       return;
4107     }
4108   else
4109     {
4110       obfree (storage);
4111       return;
4112     }
4113 }
4114 #endif /* NOTYET */
4115
4116 \f
4117 /* return 1 if the first insn to set cc before insn also sets the register
4118    reg_rtx - otherwise return 0 */
4119 int
4120 last_to_set_cc (reg_rtx, insn)
4121      rtx reg_rtx, insn;
4122 {
4123   rtx prev_insn = PREV_INSN (insn);
4124
4125   while (prev_insn)
4126     {
4127       if (GET_CODE (prev_insn) == NOTE)
4128         ;
4129
4130       else if (GET_CODE (prev_insn) == INSN)
4131         {
4132           if (GET_CODE (PATTERN (prev_insn)) != SET)
4133             return (0);
4134
4135           if (rtx_equal_p (SET_DEST (PATTERN (prev_insn)), reg_rtx))
4136             {
4137               if (sets_condition_code (SET_SRC (PATTERN (prev_insn))))
4138                 return (1);
4139
4140               return (0);
4141             }
4142
4143           else if (!doesnt_set_condition_code (SET_SRC (PATTERN (prev_insn))))
4144             return (0);
4145         }
4146
4147       else
4148         return (0);
4149
4150       prev_insn = PREV_INSN (prev_insn);
4151     }
4152
4153   return (0);
4154 }
4155
4156 \f
4157 int
4158 doesnt_set_condition_code (pat)
4159      rtx pat;
4160 {
4161   switch (GET_CODE (pat))
4162     {
4163     case MEM:
4164     case REG:
4165       return (1);
4166
4167     default:
4168       return (0);
4169
4170     }
4171 }
4172
4173 \f
4174 int
4175 sets_condition_code (pat)
4176      rtx pat;
4177 {
4178   switch (GET_CODE (pat))
4179     {
4180     case PLUS:
4181     case MINUS:
4182     case AND:
4183     case IOR:
4184     case XOR:
4185     case NOT:
4186     case NEG:
4187     case MULT:
4188     case DIV:
4189     case MOD:
4190     case UDIV:
4191     case UMOD:
4192       return (1);
4193
4194     default:
4195       return (0);
4196
4197     }
4198 }
4199
4200 \f
4201 int
4202 str_immediate_operand (op, mode)
4203      register rtx op;
4204      enum machine_mode mode;
4205 {
4206   if (GET_CODE (op) == CONST_INT && INTVAL (op) <= 32 && INTVAL (op) >= 0)
4207     {
4208       return (1);
4209     }
4210   return (0);
4211 }
4212
4213 \f
4214 int
4215 is_fp_insn (insn)
4216      rtx insn;
4217 {
4218   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4219       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4220           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4221           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode))
4222     {
4223       return (1);
4224     }
4225
4226   return (0);
4227 }
4228
4229 /*
4230   Return 1 if the mode of the SET_DEST of insn is floating point
4231   and it is not an fld or a move from memory to memory.
4232   Otherwise return 0 */
4233 int
4234 is_fp_dest (insn)
4235      rtx insn;
4236 {
4237   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4238       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4239           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4240           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)
4241       && GET_CODE (SET_DEST (PATTERN (insn))) == REG
4242       && REGNO (SET_DEST (PATTERN (insn))) >= FIRST_FLOAT_REG
4243       && GET_CODE (SET_SRC (insn)) != MEM)
4244     {
4245       return (1);
4246     }
4247
4248   return (0);
4249 }
4250
4251 /*
4252   Return 1 if the mode of the SET_DEST floating point and is memory
4253   and the source is a register.  
4254 */
4255 int
4256 is_fp_store (insn)
4257      rtx insn;
4258 {
4259   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4260       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4261           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4262           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)
4263       && GET_CODE (SET_DEST (PATTERN (insn))) == MEM
4264       && GET_CODE (SET_SRC (PATTERN (insn))) == REG)
4265     {
4266       return (1);
4267     }
4268
4269   return (0);
4270 }
4271
4272 \f
4273 /*
4274   Return 1 if dep_insn sets a register which insn uses as a base
4275   or index to reference memory.
4276   otherwise return 0 */
4277
4278 int
4279 agi_dependent (insn, dep_insn)
4280      rtx insn, dep_insn;
4281 {
4282   if (GET_CODE (dep_insn) == INSN
4283       && GET_CODE (PATTERN (dep_insn)) == SET
4284       && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG)
4285     {
4286       return (reg_mentioned_in_mem (SET_DEST (PATTERN (dep_insn)), insn));
4287     }
4288
4289   if (GET_CODE (dep_insn) == INSN && GET_CODE (PATTERN (dep_insn)) == SET
4290       && GET_CODE (SET_DEST (PATTERN (dep_insn))) == MEM
4291       && push_operand (SET_DEST (PATTERN (dep_insn)),
4292                        GET_MODE (SET_DEST (PATTERN (dep_insn)))))
4293     {
4294       return (reg_mentioned_in_mem (stack_pointer_rtx, insn));
4295     }
4296   
4297   return (0);
4298 }
4299
4300 \f
4301 /*
4302   Return 1 if reg is used in rtl as a base or index for a memory ref
4303   otherwise return 0. */
4304
4305 int
4306 reg_mentioned_in_mem (reg, rtl)
4307      rtx reg, rtl;
4308 {
4309   register char *fmt;
4310   register int i;
4311   register enum rtx_code code;
4312
4313   if (rtl == NULL)
4314     return (0);
4315
4316   code = GET_CODE (rtl);
4317
4318   switch (code)
4319     {
4320     case HIGH:
4321     case CONST_INT:
4322     case CONST:
4323     case CONST_DOUBLE:
4324     case SYMBOL_REF:
4325     case LABEL_REF:
4326     case PC:
4327     case CC0:
4328     case SUBREG:
4329       return (0);
4330
4331
4332     }
4333
4334   if (code == MEM && reg_mentioned_p (reg, rtl))
4335     return (1);
4336
4337   fmt = GET_RTX_FORMAT (code);
4338   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4339     {
4340       if (fmt[i] == 'E')
4341         {
4342           register int j;
4343           for (j = XVECLEN (rtl, i) - 1; j >= 0; j--)
4344             {
4345               if (reg_mentioned_in_mem (reg, XVECEXP (rtl, i, j)))
4346                 return 1;
4347             }
4348         }
4349
4350       else if (fmt[i] == 'e' && reg_mentioned_in_mem (reg, XEXP (rtl, i)))
4351         return 1;
4352     }
4353
4354   return (0);
4355 }
4356 \f
4357 /* Output the approprate insns for doing strlen if not just doing repnz; scasb
4358
4359    operands[0] = result, initialized with the startaddress
4360    operands[1] = alignment of the address.
4361    operands[2] = scratch register, initialized with the startaddress when
4362                  not aligned, otherwise undefined
4363
4364    This is just the body. It needs the initialisations mentioned above and
4365    some address computing at the end.  These things are done in i386.md.  */
4366
4367 char *
4368 output_strlen_unroll (operands)
4369      rtx operands[];
4370 {
4371   rtx xops[18];
4372
4373   xops[0] = operands[0];                /* Result */
4374   /*        operands[1];                 * Alignment */
4375   xops[1] = operands[2];                /* Scratch */
4376   xops[2] = GEN_INT (0);
4377   xops[3] = GEN_INT (2);
4378   xops[4] = GEN_INT (3);
4379   xops[5] = GEN_INT (4);
4380   /* xops[6] = gen_label_rtx ();         * label when aligned to 3-byte */
4381   /* xops[7] = gen_label_rtx ();         * label when aligned to 2-byte */
4382   xops[8] = gen_label_rtx ();           /* label of main loop */
4383   if(TARGET_USE_Q_REG && QI_REG_P (xops[1]))
4384     xops[9] = gen_label_rtx ();         /* pentium optimisation */
4385   xops[10] = gen_label_rtx ();          /* end label 2 */
4386   xops[11] = gen_label_rtx ();          /* end label 1 */
4387   xops[12] = gen_label_rtx ();          /* end label */
4388   /* xops[13]                            * Temporary used */
4389   xops[14] = GEN_INT (0xff);
4390   xops[15] = GEN_INT (0xff00);
4391   xops[16] = GEN_INT (0xff0000);
4392   xops[17] = GEN_INT (0xff000000);
4393
4394     /* Loop to check 1..3 bytes for null to get an aligned pointer */
4395
4396     /* is there a known alignment and is it less then 4 */
4397   if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) < 4)
4398     {
4399         /* is there a known alignment and is it not 2 */
4400       if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2)
4401         {
4402           xops[6] = gen_label_rtx ();   /* label when aligned to 3-byte */
4403           xops[7] = gen_label_rtx ();   /* label when aligned to 2-byte */
4404
4405             /* leave just the 3 lower bits */
4406             /* if this is a q-register, then the high part is used later */
4407             /* therefore user andl rather than andb */
4408           output_asm_insn (AS2 (and%L1,%4,%1), xops);
4409             /* is aligned to 4-byte adress when zero */
4410           output_asm_insn (AS1 (je,%l8), xops);
4411             /* side-effect even Parity when %eax == 3 */
4412           output_asm_insn (AS1 (jp,%6), xops);
4413
4414             /* is it aligned to 2 bytes ? */
4415           if (QI_REG_P (xops[1]))
4416             output_asm_insn (AS2 (cmp%L1,%3,%1), xops);
4417           else
4418             output_asm_insn (AS2 (cmp%L1,%3,%1), xops);
4419           output_asm_insn (AS1 (je,%7), xops);
4420         }
4421       else
4422         {
4423             /* since the alignment is 2, we have to check 2 or 0 bytes */
4424
4425             /* check if is aligned to 4 - byte */
4426           output_asm_insn (AS2 (and%L1,%3,%1), xops);
4427             /* is aligned to 4-byte adress when zero */
4428           output_asm_insn (AS1 (je,%l8), xops);
4429         }
4430
4431       xops[13] = gen_rtx (MEM, QImode, xops[0]);
4432         /* now, compare the bytes */
4433         /* compare with the high part of a q-reg gives shorter code */
4434       if (QI_REG_P (xops[1]))
4435         {
4436             /* compare the first n unaligned byte on a byte per byte basis */
4437           output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4438             /* when zero we reached the end */
4439           output_asm_insn (AS1 (je,%l12), xops);
4440             /* increment the address */
4441           output_asm_insn (AS1 (inc%L0,%0), xops);
4442
4443             /* not needed with an alignment of 2 */
4444           if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2)
4445             {
4446               ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[7]));
4447               output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4448               output_asm_insn (AS1 (je,%l12), xops);
4449               output_asm_insn (AS1 (inc%L0,%0), xops);
4450
4451               ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[6]));
4452             }
4453           output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4454         }
4455       else
4456         {
4457           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4458           output_asm_insn (AS1 (je,%l12), xops);
4459           output_asm_insn (AS1 (inc%L0,%0), xops);
4460
4461           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[7]));
4462           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4463           output_asm_insn (AS1 (je,%l12), xops);
4464           output_asm_insn (AS1 (inc%L0,%0), xops);
4465
4466           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[6]));
4467           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4468         }
4469       output_asm_insn (AS1 (je,%l12), xops);
4470       output_asm_insn (AS1 (inc%L0,%0), xops);
4471     }
4472
4473     /* Generate loop to check 4 bytes at a time */
4474     /* IMHO it is not a good idea to align this loop.  It gives only */
4475     /* huge programms, but does not help to speed up */
4476   /* ASM_OUTPUT_LOOP_ALIGN (asm_out_file); */
4477   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[8]));
4478
4479   xops[13] = gen_rtx (MEM, SImode, xops[0]);
4480   output_asm_insn (AS2 (mov%L1,%13,%1), xops);
4481
4482   if (QI_REG_P (xops[1]))
4483     {
4484         /* on i586 it is faster to compare the hi- and lo- part */
4485         /* as a kind of lookahead.  If xoring both is zero, then one */
4486         /* of both *could* be zero, otherwith none of both is zero */
4487         /* this saves one instruction, on i486 this is slower */
4488         /* testet with P-90, i486DX2-66, AMD486DX2-66 */
4489       if(TARGET_PENTIUM)
4490         {
4491           output_asm_insn (AS2 (test%B1,%h1,%b1), xops);
4492           output_asm_insn (AS1 (jne,%l9), xops);
4493         }
4494
4495         /* check first byte */
4496       output_asm_insn (AS2 (test%B1,%b1,%b1), xops);
4497       output_asm_insn (AS1 (je,%l12), xops);
4498
4499         /* check second byte */
4500       output_asm_insn (AS2 (test%B1,%h1,%h1), xops);
4501       output_asm_insn (AS1 (je,%l11), xops);
4502
4503       if(TARGET_PENTIUM)
4504           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[9]));
4505     }
4506   else
4507     {
4508         /* check first byte */
4509       output_asm_insn (AS2 (test%L1,%14,%1), xops);
4510       output_asm_insn (AS1 (je,%l12), xops);
4511
4512         /* check second byte */
4513       output_asm_insn (AS2 (test%L1,%15,%1), xops);
4514       output_asm_insn (AS1 (je,%l11), xops);
4515     }
4516
4517     /* check third byte */
4518   output_asm_insn (AS2 (test%L1,%16,%1), xops);
4519   output_asm_insn (AS1 (je,%l10), xops);
4520   
4521     /* check fourth byte and increment address */
4522   output_asm_insn (AS2 (add%L0,%5,%0), xops);
4523   output_asm_insn (AS2 (test%L1,%17,%1), xops);
4524   output_asm_insn (AS1 (jne,%l8), xops);
4525
4526     /* now generate fixups when the compare stops within a 4-byte word */
4527   output_asm_insn (AS2 (sub%L0,%4,%0), xops);
4528
4529   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[10]));
4530   output_asm_insn (AS1 (inc%L0,%0), xops);
4531
4532   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[11]));
4533   output_asm_insn (AS1 (inc%L0,%0), xops);
4534
4535   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[12]));
4536
4537   RET;
4538 }