OSDN Git Service

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