OSDN Git Service

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