OSDN Git Service

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