OSDN Git Service

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