OSDN Git Service

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