OSDN Git Service

(output_to_reg, output_fix_trunc): Use scratch memory
[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_subsi3 (xops[0], xops[0], 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   if (nregs > 1 || ! frame_pointer_needed)
2132     {
2133       if (frame_pointer_needed)
2134         {
2135           xops[0] = adj_offsettable_operand (AT_BP (QImode), offset);
2136           emit_insn (gen_movsi_lea (xops[2], XEXP (xops[0], 0)));
2137 /*        output_asm_insn (AS2 (lea%L2,%0,%2), xops);*/
2138         }
2139
2140       for (regno = 0; regno < limit; regno++)
2141         if ((regs_ever_live[regno] && ! call_used_regs[regno])
2142             || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
2143           {
2144             xops[0] = gen_rtx (REG, SImode, regno);
2145             emit_insn (gen_pop (xops[0]));
2146 /*          output_asm_insn ("pop%L0 %0", xops);*/
2147           }
2148     }
2149   else
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           xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset);
2156           emit_move_insn (xops[0], xops[1]);
2157 /*        output_asm_insn (AS2 (mov%L0,%1,%0), xops);*/
2158           offset += 4;
2159         }
2160
2161   if (frame_pointer_needed)
2162     {
2163       /* If not an i386, mov & pop is faster than "leave". */
2164
2165       if (TARGET_USE_LEAVE)
2166         emit_insn (gen_leave());
2167 /*      output_asm_insn ("leave", xops);*/
2168       else
2169         {
2170           xops[0] = frame_pointer_rtx;
2171           xops[1] = stack_pointer_rtx;
2172           emit_insn (gen_epilogue_set_stack_ptr());
2173 /*        output_asm_insn (AS2 (mov%L2,%0,%2), xops);*/
2174           emit_insn (gen_pop (xops[0]));
2175 /*        output_asm_insn ("pop%L0 %0", xops);*/
2176         }
2177     }
2178   else if (tsize)
2179     {
2180       /* If there is no frame pointer, we must still release the frame. */
2181
2182       xops[0] = GEN_INT (tsize);
2183       emit_insn (gen_rtx (SET, SImode,
2184                           xops[2],
2185                           gen_rtx (PLUS, SImode,
2186                                    xops[2],
2187                                    xops[0])));
2188 /*      output_asm_insn (AS2 (add%L2,%0,%2), xops);*/
2189     }
2190
2191 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
2192   if (profile_block_flag == 2)
2193     {
2194       FUNCTION_BLOCK_PROFILER_EXIT(file);
2195     }
2196 #endif
2197
2198   if (current_function_pops_args && current_function_args_size)
2199     {
2200       xops[1] = GEN_INT (current_function_pops_args);
2201
2202       /* i386 can only pop 32K bytes (maybe 64K?  Is it signed?).  If
2203          asked to pop more, pop return address, do explicit add, and jump
2204          indirectly to the caller. */
2205
2206       if (current_function_pops_args >= 32768)
2207         {
2208           /* ??? Which register to use here? */
2209           xops[0] = gen_rtx (REG, SImode, 2);
2210           emit_insn (gen_pop (xops[0]));
2211 /*        output_asm_insn ("pop%L0 %0", xops);*/
2212           emit_insn (gen_rtx (SET, SImode,
2213                               xops[2],
2214                               gen_rtx (PLUS, SImode,
2215                                        xops[1],
2216                                        xops[2])));
2217 /*        output_asm_insn (AS2 (add%L2,%1,%2), xops);*/
2218           emit_jump_insn (xops[0]);
2219 /*        output_asm_insn ("jmp %*%0", xops);*/
2220         }
2221       else
2222         emit_jump_insn (gen_return_pop_internal (xops[1]));
2223 /*        output_asm_insn ("ret %1", xops);*/
2224     }
2225   else
2226 /*    output_asm_insn ("ret", xops);*/
2227  emit_jump_insn (gen_return_internal ());
2228 }
2229
2230 \f
2231 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
2232    that is a valid memory address for an instruction.
2233    The MODE argument is the machine mode for the MEM expression
2234    that wants to use this address.
2235
2236    On x86, legitimate addresses are:
2237         base                            movl (base),reg
2238         displacement                    movl disp,reg
2239         base + displacement             movl disp(base),reg
2240         index + base                    movl (base,index),reg
2241         (index + base) + displacement   movl disp(base,index),reg
2242         index*scale                     movl (,index,scale),reg
2243         index*scale + disp              movl disp(,index,scale),reg
2244         index*scale + base              movl (base,index,scale),reg
2245         (index*scale + base) + disp     movl disp(base,index,scale),reg
2246
2247         In each case, scale can be 1, 2, 4, 8.  */
2248
2249 /* This is exactly the same as print_operand_addr, except that
2250    it recognizes addresses instead of printing them.
2251
2252    It only recognizes address in canonical form.  LEGITIMIZE_ADDRESS should
2253    convert common non-canonical forms to canonical form so that they will
2254    be recognized.  */
2255
2256 #define ADDR_INVALID(msg,insn)                                          \
2257 do {                                                                    \
2258   if (TARGET_DEBUG_ADDR)                                                \
2259     {                                                                   \
2260       fprintf (stderr, msg);                                            \
2261       debug_rtx (insn);                                                 \
2262     }                                                                   \
2263 } while (0)
2264
2265 int
2266 legitimate_address_p (mode, addr, strict)
2267      enum machine_mode mode;
2268      register rtx addr;
2269      int strict;
2270 {
2271   rtx base  = NULL_RTX;
2272   rtx indx  = NULL_RTX;
2273   rtx scale = NULL_RTX;
2274   rtx disp  = NULL_RTX;
2275
2276   if (TARGET_DEBUG_ADDR)
2277     {
2278       fprintf (stderr,
2279                "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
2280                GET_MODE_NAME (mode), strict);
2281
2282       debug_rtx (addr);
2283     }
2284
2285   if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
2286       base = addr;                              /* base reg */
2287
2288   else if (GET_CODE (addr) == PLUS)
2289     {
2290       rtx op0 = XEXP (addr, 0);
2291       rtx op1 = XEXP (addr, 1);
2292       enum rtx_code code0 = GET_CODE (op0);
2293       enum rtx_code code1 = GET_CODE (op1);
2294
2295       if (code0 == REG || code0 == SUBREG)
2296         {
2297           if (code1 == REG || code1 == SUBREG)
2298             {
2299               indx = op0;                       /* index + base */
2300               base = op1;
2301             }
2302
2303           else
2304             {
2305               base = op0;                       /* base + displacement */
2306               disp = op1;
2307             }
2308         }
2309
2310       else if (code0 == MULT)
2311         {
2312           indx  = XEXP (op0, 0);
2313           scale = XEXP (op0, 1);
2314
2315           if (code1 == REG || code1 == SUBREG)
2316             base = op1;                         /* index*scale + base */
2317
2318           else
2319             disp = op1;                         /* index*scale + disp */
2320         }
2321
2322       else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)
2323         {
2324           indx  = XEXP (XEXP (op0, 0), 0);      /* index*scale + base + disp */
2325           scale = XEXP (XEXP (op0, 0), 1);
2326           base  = XEXP (op0, 1);
2327           disp  = op1;
2328         }
2329
2330       else if (code0 == PLUS)
2331         {
2332           indx = XEXP (op0, 0);                 /* index + base + disp */
2333           base = XEXP (op0, 1);
2334           disp = op1;
2335         }
2336
2337       else
2338         {
2339           ADDR_INVALID ("PLUS subcode is not valid.\n", op0);
2340           return FALSE;
2341         }
2342     }
2343
2344   else if (GET_CODE (addr) == MULT)
2345     {
2346       indx  = XEXP (addr, 0);                   /* index*scale */
2347       scale = XEXP (addr, 1);
2348     }
2349
2350   else
2351     disp = addr;                                /* displacement */
2352
2353   /* Allow arg pointer and stack pointer as index if there is not scaling */
2354   if (base && indx && !scale
2355       && (indx == arg_pointer_rtx || indx == stack_pointer_rtx))
2356     {
2357       rtx tmp = base;
2358       base = indx;
2359       indx = tmp;
2360     }
2361
2362   /* Validate base register */
2363   /* Don't allow SUBREG's here, it can lead to spill failures when the base
2364      is one word out of a two word structure, which is represented internally
2365      as a DImode int.  */
2366   if (base)
2367     {
2368       if (GET_CODE (base) != REG)
2369         {
2370           ADDR_INVALID ("Base is not a register.\n", base);
2371           return FALSE;
2372         }
2373
2374       if ((strict && !REG_OK_FOR_BASE_STRICT_P (base))
2375           || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base)))
2376         {
2377           ADDR_INVALID ("Base is not valid.\n", base);
2378           return FALSE;
2379         }
2380     }
2381
2382   /* Validate index register */
2383   /* Don't allow SUBREG's here, it can lead to spill failures when the index
2384      is one word out of a two word structure, which is represented internally
2385      as a DImode int.  */
2386   if (indx)
2387     {
2388       if (GET_CODE (indx) != REG)
2389         {
2390           ADDR_INVALID ("Index is not a register.\n", indx);
2391           return FALSE;
2392         }
2393
2394       if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx))
2395           || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx)))
2396         {
2397           ADDR_INVALID ("Index is not valid.\n", indx);
2398           return FALSE;
2399         }
2400     }
2401   else if (scale)
2402     abort ();                                   /* scale w/o index invalid */
2403
2404   /* Validate scale factor */
2405   if (scale)
2406     {
2407       HOST_WIDE_INT value;
2408
2409       if (GET_CODE (scale) != CONST_INT)
2410         {
2411           ADDR_INVALID ("Scale is not valid.\n", scale);
2412           return FALSE;
2413         }
2414
2415       value = INTVAL (scale);
2416       if (value != 1 && value != 2 && value != 4 && value != 8)
2417         {
2418           ADDR_INVALID ("Scale is not a good multiplier.\n", scale);
2419           return FALSE;
2420         }
2421     }
2422
2423   /* Validate displacement
2424      Constant pool addresses must be handled special.  They are
2425      considered legitimate addresses, but only if not used with regs.
2426      When printed, the output routines know to print the reference with the
2427      PIC reg, even though the PIC reg doesn't appear in the RTL. */
2428   if (disp)
2429     {
2430       if (GET_CODE (disp) == SYMBOL_REF
2431           && CONSTANT_POOL_ADDRESS_P (disp)
2432           && !base
2433           && !indx)
2434         ;
2435
2436       else if (!CONSTANT_ADDRESS_P (disp))
2437         {
2438           ADDR_INVALID ("Displacement is not valid.\n", disp);
2439           return FALSE;
2440         }
2441
2442       else if (GET_CODE (disp) == CONST_DOUBLE)
2443         {
2444           ADDR_INVALID ("Displacement is a const_double.\n", disp);
2445           return FALSE;
2446         }
2447
2448       else if (flag_pic && SYMBOLIC_CONST (disp)
2449                && base != pic_offset_table_rtx
2450                && (indx != pic_offset_table_rtx || scale != NULL_RTX))
2451         {
2452           ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
2453           return FALSE;
2454         }
2455
2456       else if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
2457                && (base != NULL_RTX || indx != NULL_RTX))
2458         {
2459           ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp);
2460           return FALSE;
2461         }
2462     }
2463
2464   if (TARGET_DEBUG_ADDR)
2465     fprintf (stderr, "Address is valid.\n");
2466
2467   /* Everything looks valid, return true */
2468   return TRUE;
2469 }
2470
2471 \f
2472 /* Return a legitimate reference for ORIG (an address) using the
2473    register REG.  If REG is 0, a new pseudo is generated.
2474
2475    There are three types of references that must be handled:
2476
2477    1. Global data references must load the address from the GOT, via
2478       the PIC reg.  An insn is emitted to do this load, and the reg is
2479       returned.
2480
2481    2. Static data references must compute the address as an offset
2482       from the GOT, whose base is in the PIC reg.  An insn is emitted to
2483       compute the address into a reg, and the reg is returned.  Static
2484       data objects have SYMBOL_REF_FLAG set to differentiate them from
2485       global data objects.
2486
2487    3. Constant pool addresses must be handled special.  They are
2488       considered legitimate addresses, but only if not used with regs.
2489       When printed, the output routines know to print the reference with the
2490       PIC reg, even though the PIC reg doesn't appear in the RTL.
2491
2492    GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
2493    reg also appears in the address (except for constant pool references,
2494    noted above).
2495
2496    "switch" statements also require special handling when generating
2497    PIC code.  See comments by the `casesi' insn in i386.md for details.  */
2498
2499 rtx
2500 legitimize_pic_address (orig, reg)
2501      rtx orig;
2502      rtx reg;
2503 {
2504   rtx addr = orig;
2505   rtx new = orig;
2506
2507   if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
2508     {
2509       if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
2510         reg = new = orig;
2511       else
2512         {
2513           if (reg == 0)
2514             reg = gen_reg_rtx (Pmode);
2515
2516           if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
2517               || GET_CODE (addr) == LABEL_REF)
2518             new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
2519           else
2520             new = gen_rtx (MEM, Pmode,
2521                            gen_rtx (PLUS, Pmode,
2522                                     pic_offset_table_rtx, orig));
2523
2524           emit_move_insn (reg, new);
2525         }
2526       current_function_uses_pic_offset_table = 1;
2527       return reg;
2528     }
2529   else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
2530     {
2531       rtx base;
2532
2533       if (GET_CODE (addr) == CONST)
2534         {
2535           addr = XEXP (addr, 0);
2536           if (GET_CODE (addr) != PLUS)
2537             abort ();
2538         }
2539
2540       if (XEXP (addr, 0) == pic_offset_table_rtx)
2541         return orig;
2542
2543       if (reg == 0)
2544         reg = gen_reg_rtx (Pmode);
2545
2546       base = legitimize_pic_address (XEXP (addr, 0), reg);
2547       addr = legitimize_pic_address (XEXP (addr, 1),
2548                                      base == reg ? NULL_RTX : reg);
2549
2550       if (GET_CODE (addr) == CONST_INT)
2551         return plus_constant (base, INTVAL (addr));
2552
2553       if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
2554         {
2555           base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
2556           addr = XEXP (addr, 1);
2557         }
2558         return gen_rtx (PLUS, Pmode, base, addr);
2559     }
2560   return new;
2561 }
2562 \f
2563
2564 /* Emit insns to move operands[1] into operands[0].  */
2565
2566 void
2567 emit_pic_move (operands, mode)
2568      rtx *operands;
2569      enum machine_mode mode;
2570 {
2571   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
2572
2573   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
2574     operands[1] = (rtx) force_reg (SImode, operands[1]);
2575   else
2576     operands[1] = legitimize_pic_address (operands[1], temp);
2577 }
2578
2579 \f
2580 /* Try machine-dependent ways of modifying an illegitimate address
2581    to be legitimate.  If we find one, return the new, valid address.
2582    This macro is used in only one place: `memory_address' in explow.c.
2583
2584    OLDX is the address as it was before break_out_memory_refs was called.
2585    In some cases it is useful to look at this to decide what needs to be done.
2586
2587    MODE and WIN are passed so that this macro can use
2588    GO_IF_LEGITIMATE_ADDRESS.
2589
2590    It is always safe for this macro to do nothing.  It exists to recognize
2591    opportunities to optimize the output.
2592
2593    For the 80386, we handle X+REG by loading X into a register R and
2594    using R+REG.  R will go in a general reg and indexing will be used.
2595    However, if REG is a broken-out memory address or multiplication,
2596    nothing needs to be done because REG can certainly go in a general reg.
2597
2598    When -fpic is used, special handling is needed for symbolic references.
2599    See comments by legitimize_pic_address in i386.c for details.  */
2600
2601 rtx
2602 legitimize_address (x, oldx, mode)
2603      register rtx x;
2604      register rtx oldx;
2605      enum machine_mode mode;
2606 {
2607   int changed = 0;
2608   unsigned log;
2609
2610   if (TARGET_DEBUG_ADDR)
2611     {
2612       fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode));
2613       debug_rtx (x);
2614     }
2615
2616   if (flag_pic && SYMBOLIC_CONST (x))
2617     return legitimize_pic_address (x, 0);
2618
2619   /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
2620   if (GET_CODE (x) == ASHIFT
2621       && GET_CODE (XEXP (x, 1)) == CONST_INT
2622       && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
2623     {
2624       changed = 1;
2625       x = gen_rtx (MULT, Pmode,
2626                    force_reg (Pmode, XEXP (x, 0)),
2627                    GEN_INT (1 << log));
2628     }
2629
2630   if (GET_CODE (x) == PLUS)
2631     {
2632       /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
2633       if (GET_CODE (XEXP (x, 0)) == ASHIFT
2634           && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
2635           && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4)
2636         {
2637           changed = 1;
2638           XEXP (x, 0) = gen_rtx (MULT, Pmode,
2639                                  force_reg (Pmode, XEXP (XEXP (x, 0), 0)),
2640                                  GEN_INT (1 << log));
2641         }
2642
2643       if (GET_CODE (XEXP (x, 1)) == ASHIFT
2644           && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
2645           && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4)
2646         {
2647           changed = 1;
2648           XEXP (x, 1) = gen_rtx (MULT, Pmode,
2649                                  force_reg (Pmode, XEXP (XEXP (x, 1), 0)),
2650                                  GEN_INT (1 << log));
2651         }
2652
2653       /* Put multiply first if it isn't already */
2654       if (GET_CODE (XEXP (x, 1)) == MULT)
2655         {
2656           rtx tmp = XEXP (x, 0);
2657           XEXP (x, 0) = XEXP (x, 1);
2658           XEXP (x, 1) = tmp;
2659           changed = 1;
2660         }
2661
2662       /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))
2663          into (plus (plus (mult (reg) (const)) (reg)) (const)).  This can be
2664          created by virtual register instantiation, register elimination, and
2665          similar optimizations.  */
2666       if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)
2667         {
2668           changed = 1;
2669           x = gen_rtx (PLUS, Pmode,
2670                        gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)),
2671                        XEXP (XEXP (x, 1), 1));
2672         }
2673
2674       /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)
2675          into (plus (plus (mult (reg) (const)) (reg)) (const)).  */
2676       else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
2677                && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
2678                && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
2679                && CONSTANT_P (XEXP (x, 1)))
2680         {
2681           rtx constant, other;
2682
2683           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
2684             {
2685               constant = XEXP (x, 1);
2686               other = XEXP (XEXP (XEXP (x, 0), 1), 1);
2687             }
2688           else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
2689             {
2690               constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
2691               other = XEXP (x, 1);
2692             }
2693           else
2694             constant = 0;
2695
2696           if (constant)
2697             {
2698               changed = 1;
2699               x = gen_rtx (PLUS, Pmode,
2700                            gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),
2701                                     XEXP (XEXP (XEXP (x, 0), 1), 0)),
2702                            plus_constant (other, INTVAL (constant)));
2703             }
2704         }
2705
2706       if (changed && legitimate_address_p (mode, x, FALSE))
2707         return x;
2708
2709       if (GET_CODE (XEXP (x, 0)) == MULT)
2710         {
2711           changed = 1;
2712           XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
2713         }
2714
2715       if (GET_CODE (XEXP (x, 1)) == MULT)
2716         {
2717           changed = 1;
2718           XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
2719         }
2720
2721       if (changed
2722           && GET_CODE (XEXP (x, 1)) == REG
2723           && GET_CODE (XEXP (x, 0)) == REG)
2724         return x;
2725
2726       if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))
2727         {
2728           changed = 1;
2729           x = legitimize_pic_address (x, 0);
2730         }
2731
2732       if (changed && legitimate_address_p (mode, x, FALSE))
2733         return x;
2734
2735       if (GET_CODE (XEXP (x, 0)) == REG)
2736         {
2737           register rtx temp = gen_reg_rtx (Pmode);
2738           register rtx val  = force_operand (XEXP (x, 1), temp);
2739           if (val != temp)
2740             emit_move_insn (temp, val);
2741
2742           XEXP (x, 1) = temp;
2743           return x;
2744         }
2745
2746       else if (GET_CODE (XEXP (x, 1)) == REG)
2747         {
2748           register rtx temp = gen_reg_rtx (Pmode);
2749           register rtx val  = force_operand (XEXP (x, 0), temp);
2750           if (val != temp)
2751             emit_move_insn (temp, val);
2752
2753           XEXP (x, 0) = temp;
2754           return x;
2755         }
2756     }
2757
2758   return x;
2759 }
2760
2761 \f
2762 /* Print an integer constant expression in assembler syntax.  Addition
2763    and subtraction are the only arithmetic that may appear in these
2764    expressions.  FILE is the stdio stream to write to, X is the rtx, and
2765    CODE is the operand print code from the output string.  */
2766
2767 static void
2768 output_pic_addr_const (file, x, code)
2769      FILE *file;
2770      rtx x;
2771      int code;
2772 {
2773   char buf[256];
2774
2775   switch (GET_CODE (x))
2776     {
2777     case PC:
2778       if (flag_pic)
2779         putc ('.', file);
2780       else
2781         abort ();
2782       break;
2783
2784     case SYMBOL_REF:
2785     case LABEL_REF:
2786       if (GET_CODE (x) == SYMBOL_REF)
2787         assemble_name (file, XSTR (x, 0));
2788       else
2789         {
2790           ASM_GENERATE_INTERNAL_LABEL (buf, "L",
2791                                        CODE_LABEL_NUMBER (XEXP (x, 0)));
2792           assemble_name (asm_out_file, buf);
2793         }
2794
2795       if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
2796         fprintf (file, "@GOTOFF(%%ebx)");
2797       else if (code == 'P')
2798         fprintf (file, "@PLT");
2799       else if (GET_CODE (x) == LABEL_REF)
2800         fprintf (file, "@GOTOFF");
2801       else if (! SYMBOL_REF_FLAG (x))
2802         fprintf (file, "@GOT");
2803       else
2804         fprintf (file, "@GOTOFF");
2805
2806       break;
2807
2808     case CODE_LABEL:
2809       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
2810       assemble_name (asm_out_file, buf);
2811       break;
2812
2813     case CONST_INT:
2814       fprintf (file, "%d", INTVAL (x));
2815       break;
2816
2817     case CONST:
2818       /* This used to output parentheses around the expression,
2819          but that does not work on the 386 (either ATT or BSD assembler).  */
2820       output_pic_addr_const (file, XEXP (x, 0), code);
2821       break;
2822
2823     case CONST_DOUBLE:
2824       if (GET_MODE (x) == VOIDmode)
2825         {
2826           /* We can use %d if the number is <32 bits and positive.  */
2827           if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
2828             fprintf (file, "0x%x%08x",
2829                      CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
2830           else
2831             fprintf (file, "%d", CONST_DOUBLE_LOW (x));
2832         }
2833       else
2834         /* We can't handle floating point constants;
2835            PRINT_OPERAND must handle them.  */
2836         output_operand_lossage ("floating constant misused");
2837       break;
2838
2839     case PLUS:
2840       /* Some assemblers need integer constants to appear last (eg masm).  */
2841       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
2842         {
2843           output_pic_addr_const (file, XEXP (x, 1), code);
2844           if (INTVAL (XEXP (x, 0)) >= 0)
2845             fprintf (file, "+");
2846           output_pic_addr_const (file, XEXP (x, 0), code);
2847         }
2848       else
2849         {
2850           output_pic_addr_const (file, XEXP (x, 0), code);
2851           if (INTVAL (XEXP (x, 1)) >= 0)
2852             fprintf (file, "+");
2853           output_pic_addr_const (file, XEXP (x, 1), code);
2854         }
2855       break;
2856
2857     case MINUS:
2858       output_pic_addr_const (file, XEXP (x, 0), code);
2859       fprintf (file, "-");
2860       output_pic_addr_const (file, XEXP (x, 1), code);
2861       break;
2862
2863     default:
2864       output_operand_lossage ("invalid expression as operand");
2865     }
2866 }
2867 \f
2868 /* Append the correct conditional move suffix which corresponds to CODE */
2869
2870 static void
2871 put_condition_code (code, reverse_cc, mode, file)
2872      enum rtx_code code;
2873      int  reverse_cc;
2874      enum mode_class mode;
2875      FILE * file;
2876 {
2877   int ieee;
2878   ieee = (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
2879           && ! (cc_prev_status.flags & CC_FCOMI));
2880   if (reverse_cc && ! ieee)
2881     code = reverse_condition (code);
2882
2883   if (mode == MODE_INT)
2884   switch (code)
2885     {
2886       case NE: 
2887           if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2888             fputs ("b", file);
2889           else
2890             fputs ("ne", file);
2891           return;
2892       case EQ: 
2893           if (cc_prev_status.flags & CC_Z_IN_NOT_C)
2894             fputs ("ae", file);
2895           else
2896             fputs ("e", file);
2897           return;
2898       case GE: 
2899           fputs ("ge", file); return;
2900       case GT: 
2901           fputs ("g", file); return;
2902       case LE: 
2903           fputs ("le", file); return;
2904       case LT: 
2905           fputs ("l", file); return;
2906       case GEU: 
2907           fputs ("ae", file); return;
2908       case GTU: 
2909           fputs ("a", file); return;
2910       case LEU: 
2911           fputs ("be", file); return;
2912       case LTU: 
2913           fputs ("b", file); return;
2914       default: output_operand_lossage ("Invalid %%C operand");
2915     }
2916   else if (mode == MODE_FLOAT)
2917   switch (code)
2918     {
2919       case NE: 
2920           fputs (ieee ? (reverse_cc ? "ne" : "e") : "ne", file); return;
2921       case EQ: 
2922           fputs (ieee ? (reverse_cc ? "ne" : "e") : "e", file); return;
2923       case GE: 
2924           fputs (ieee ? (reverse_cc ? "ne" : "e") : "nb", file); return;
2925       case GT: 
2926           fputs (ieee ? (reverse_cc ? "ne" : "e") : "nbe", file); return;
2927       case LE: 
2928           fputs (ieee ? (reverse_cc ? "nb" : "b") : "be", file); return;
2929       case LT: 
2930           fputs (ieee ? (reverse_cc ? "ne" : "e") : "b", file); return;
2931       case GEU: 
2932           fputs (ieee ? (reverse_cc ? "ne" : "e") : "nb", file); return;
2933       case GTU: 
2934           fputs (ieee ? (reverse_cc ? "ne" : "e") : "nbe", file); return;
2935       case LEU: 
2936           fputs (ieee ? (reverse_cc ? "nb" : "b") : "be", file); return;
2937       case LTU: 
2938           fputs (ieee ? (reverse_cc ? "ne" : "e") : "b", file); return;
2939       default: output_operand_lossage ("Invalid %%C operand");
2940     }
2941 }
2942
2943 /* Meaning of CODE:
2944    L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
2945    C -- print opcode suffix for set/cmov insn.
2946    c -- like C, but print reversed condition
2947    F -- print opcode suffix for fcmov insn.
2948    f -- like C, but print reversed condition
2949    R -- print the prefix for register names.
2950    z -- print the opcode suffix for the size of the current operand.
2951    * -- print a star (in certain assembler syntax)
2952    w -- print the operand as if it's a "word" (HImode) even if it isn't.
2953    c -- don't print special prefixes before constant operands.
2954    J -- print the appropriate jump operand.
2955    s -- print a shift double count, followed by the assemblers argument
2956         delimiter.
2957    b -- print the QImode name of the register for the indicated operand.
2958         %b0 would print %al if operands[0] is reg 0.
2959    w --  likewise, print the HImode name of the register.
2960    k --  likewise, print the SImode name of the register.
2961    h --  print the QImode name for a "high" register, either ah, bh, ch or dh.
2962    y --  print "st(0)" instead of "st" as a register.
2963    P --  print as a PIC constant
2964 */
2965
2966 void
2967 print_operand (file, x, code)
2968      FILE *file;
2969      rtx x;
2970      int code;
2971 {
2972   if (code)
2973     {
2974       switch (code)
2975         {
2976         case '*':
2977           if (USE_STAR)
2978             putc ('*', file);
2979           return;
2980
2981         case 'L':
2982           PUT_OP_SIZE (code, 'l', file);
2983           return;
2984
2985         case 'W':
2986           PUT_OP_SIZE (code, 'w', file);
2987           return;
2988
2989         case 'B':
2990           PUT_OP_SIZE (code, 'b', file);
2991           return;
2992
2993         case 'Q':
2994           PUT_OP_SIZE (code, 'l', file);
2995           return;
2996
2997         case 'S':
2998           PUT_OP_SIZE (code, 's', file);
2999           return;
3000
3001         case 'T':
3002           PUT_OP_SIZE (code, 't', file);
3003           return;
3004
3005         case 'z':
3006           /* 387 opcodes don't get size suffixes if the operands are
3007              registers. */
3008
3009           if (STACK_REG_P (x))
3010             return;
3011
3012           /* this is the size of op from size of operand */
3013           switch (GET_MODE_SIZE (GET_MODE (x)))
3014             {
3015             case 1:
3016               PUT_OP_SIZE ('B', 'b', file);
3017               return;
3018
3019             case 2:
3020               PUT_OP_SIZE ('W', 'w', file);
3021               return;
3022
3023             case 4:
3024               if (GET_MODE (x) == SFmode)
3025                 {
3026                   PUT_OP_SIZE ('S', 's', file);
3027                   return;
3028                 }
3029               else
3030                 PUT_OP_SIZE ('L', 'l', file);
3031               return;
3032
3033             case 12:
3034                   PUT_OP_SIZE ('T', 't', file);
3035                   return;
3036
3037             case 8:
3038               if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
3039                 {
3040 #ifdef GAS_MNEMONICS
3041                   PUT_OP_SIZE ('Q', 'q', file);
3042                   return;
3043 #else
3044                   PUT_OP_SIZE ('Q', 'l', file); /* Fall through */
3045 #endif
3046                 }
3047
3048               PUT_OP_SIZE ('Q', 'l', file);
3049               return;
3050             }
3051
3052         case 'b':
3053         case 'w':
3054         case 'k':
3055         case 'h':
3056         case 'y':
3057         case 'P':
3058           break;
3059
3060         case 'J':
3061           switch (GET_CODE (x))
3062             {
3063               /* These conditions are appropriate for testing the result
3064                  of an arithmetic operation, not for a compare operation.
3065                  Cases GE, LT assume CC_NO_OVERFLOW true. All cases assume
3066                  CC_Z_IN_NOT_C false and not floating point.  */
3067             case NE:  fputs ("jne", file); return;
3068             case EQ:  fputs ("je",  file); return;
3069             case GE:  fputs ("jns", file); return;
3070             case LT:  fputs ("js",  file); return;
3071             case GEU: fputs ("jmp", file); return;
3072             case GTU: fputs ("jne",  file); return;
3073             case LEU: fputs ("je", file); return;
3074             case LTU: fputs ("#branch never",  file); return;
3075
3076             /* no matching branches for GT nor LE */
3077             }
3078           abort ();
3079
3080         case 's':
3081           if (GET_CODE (x) == CONST_INT || ! SHIFT_DOUBLE_OMITS_COUNT)
3082             {
3083               PRINT_OPERAND (file, x, 0);
3084               fputs (AS2C (,) + 1, file);
3085             }
3086           return;
3087
3088           /* This is used by the conditional move instructions.  */
3089         case 'C':
3090           put_condition_code (GET_CODE (x), 0, MODE_INT, file);
3091           return;
3092
3093           /* like above, but reverse condition */
3094         case 'c':
3095           put_condition_code (GET_CODE (x), 1, MODE_INT, file); return;
3096
3097         case 'F':
3098           put_condition_code (GET_CODE (x), 0, MODE_FLOAT, file);
3099           return;
3100
3101           /* like above, but reverse condition */
3102         case 'f':
3103           put_condition_code (GET_CODE (x), 1, MODE_FLOAT, file);
3104           return;
3105
3106         default:
3107           {
3108             char str[50];
3109
3110             sprintf (str, "invalid operand code `%c'", code);
3111             output_operand_lossage (str);
3112           }
3113         }
3114     }
3115   if (GET_CODE (x) == REG)
3116     {
3117       PRINT_REG (x, code, file);
3118     }
3119   else if (GET_CODE (x) == MEM)
3120     {
3121       PRINT_PTR (x, file);
3122       if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
3123         {
3124           if (flag_pic)
3125             output_pic_addr_const (file, XEXP (x, 0), code);
3126           else
3127             output_addr_const (file, XEXP (x, 0));
3128         }
3129       else
3130         output_address (XEXP (x, 0));
3131     }
3132   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
3133     {
3134       REAL_VALUE_TYPE r; long l;
3135       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3136       REAL_VALUE_TO_TARGET_SINGLE (r, l);
3137       PRINT_IMMED_PREFIX (file);
3138       fprintf (file, "0x%x", l);
3139     }
3140  /* These float cases don't actually occur as immediate operands. */
3141  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
3142     {
3143       REAL_VALUE_TYPE r; char dstr[30];
3144       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3145       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
3146       fprintf (file, "%s", dstr);
3147     }
3148   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode)
3149     {
3150       REAL_VALUE_TYPE r; char dstr[30];
3151       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3152       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
3153       fprintf (file, "%s", dstr);
3154     }
3155   else 
3156     {
3157       if (code != 'P')
3158         {
3159           if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
3160             PRINT_IMMED_PREFIX (file);
3161           else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
3162                    || GET_CODE (x) == LABEL_REF)
3163             PRINT_OFFSET_PREFIX (file);
3164         }
3165       if (flag_pic)
3166         output_pic_addr_const (file, x, code);
3167       else
3168         output_addr_const (file, x);
3169     }
3170 }
3171 \f
3172 /* Print a memory operand whose address is ADDR.  */
3173
3174 void
3175 print_operand_address (file, addr)
3176      FILE *file;
3177      register rtx addr;
3178 {
3179   register rtx reg1, reg2, breg, ireg;
3180   rtx offset;
3181
3182   switch (GET_CODE (addr))
3183     {
3184     case REG:
3185       ADDR_BEG (file);
3186       fprintf (file, "%se", RP);
3187       fputs (hi_reg_name[REGNO (addr)], file);
3188       ADDR_END (file);
3189       break;
3190
3191     case PLUS:
3192       reg1 = 0;
3193       reg2 = 0;
3194       ireg = 0;
3195       breg = 0;
3196       offset = 0;
3197       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
3198         {
3199           offset = XEXP (addr, 0);
3200           addr = XEXP (addr, 1);
3201         }
3202       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
3203         {
3204           offset = XEXP (addr, 1);
3205           addr = XEXP (addr, 0);
3206         }
3207       if (GET_CODE (addr) != PLUS) ;
3208       else if (GET_CODE (XEXP (addr, 0)) == MULT)
3209         {
3210           reg1 = XEXP (addr, 0);
3211           addr = XEXP (addr, 1);
3212         }
3213       else if (GET_CODE (XEXP (addr, 1)) == MULT)
3214         {
3215           reg1 = XEXP (addr, 1);
3216           addr = XEXP (addr, 0);
3217         }
3218       else if (GET_CODE (XEXP (addr, 0)) == REG)
3219         {
3220           reg1 = XEXP (addr, 0);
3221           addr = XEXP (addr, 1);
3222         }
3223       else if (GET_CODE (XEXP (addr, 1)) == REG)
3224         {
3225           reg1 = XEXP (addr, 1);
3226           addr = XEXP (addr, 0);
3227         }
3228       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
3229         {
3230           if (reg1 == 0) reg1 = addr;
3231           else reg2 = addr;
3232           addr = 0;
3233         }
3234       if (offset != 0)
3235         {
3236           if (addr != 0) abort ();
3237           addr = offset;
3238         }
3239       if ((reg1 && GET_CODE (reg1) == MULT)
3240           || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
3241         {
3242           breg = reg2;
3243           ireg = reg1;
3244         }
3245       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
3246         {
3247           breg = reg1;
3248           ireg = reg2;
3249         }
3250
3251       if (ireg != 0 || breg != 0)
3252         {
3253           int scale = 1;
3254
3255           if (addr != 0)
3256             {
3257               if (flag_pic)
3258                 output_pic_addr_const (file, addr, 0);
3259
3260               else if (GET_CODE (addr) == LABEL_REF)
3261                 output_asm_label (addr);
3262
3263               else
3264                 output_addr_const (file, addr);
3265             }
3266
3267           if (ireg != 0 && GET_CODE (ireg) == MULT)
3268             {
3269               scale = INTVAL (XEXP (ireg, 1));
3270               ireg = XEXP (ireg, 0);
3271             }
3272
3273           /* The stack pointer can only appear as a base register,
3274              never an index register, so exchange the regs if it is wrong. */
3275
3276           if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)
3277             {
3278               rtx tmp;
3279
3280               tmp = breg;
3281               breg = ireg;
3282               ireg = tmp;
3283             }
3284
3285           /* output breg+ireg*scale */
3286           PRINT_B_I_S (breg, ireg, scale, file);
3287           break;
3288         }
3289
3290     case MULT:
3291       {
3292         int scale;
3293         if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
3294           {
3295             scale = INTVAL (XEXP (addr, 0));
3296             ireg = XEXP (addr, 1);
3297           }
3298         else
3299           {
3300             scale = INTVAL (XEXP (addr, 1));
3301             ireg = XEXP (addr, 0);
3302           }
3303         output_addr_const (file, const0_rtx);
3304         PRINT_B_I_S ((rtx) 0, ireg, scale, file);
3305       }
3306       break;
3307
3308     default:
3309       if (GET_CODE (addr) == CONST_INT
3310           && INTVAL (addr) < 0x8000
3311           && INTVAL (addr) >= -0x8000)
3312         fprintf (file, "%d", INTVAL (addr));
3313       else
3314         {
3315           if (flag_pic)
3316             output_pic_addr_const (file, addr, 0);
3317           else
3318             output_addr_const (file, addr);
3319         }
3320     }
3321 }
3322 \f
3323 /* Set the cc_status for the results of an insn whose pattern is EXP.
3324    On the 80386, we assume that only test and compare insns, as well
3325    as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT,
3326    ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
3327    Also, we assume that jumps, moves and sCOND don't affect the condition
3328    codes.  All else clobbers the condition codes, by assumption.
3329
3330    We assume that ALL integer add, minus, etc. instructions effect the
3331    condition codes.  This MUST be consistent with i386.md.
3332
3333    We don't record any float test or compare - the redundant test &
3334    compare check in final.c does not handle stack-like regs correctly. */
3335
3336 void
3337 notice_update_cc (exp)
3338      rtx exp;
3339 {
3340   if (GET_CODE (exp) == SET)
3341     {
3342       /* Jumps do not alter the cc's.  */
3343       if (SET_DEST (exp) == pc_rtx)
3344         return;
3345 #ifdef IS_STACK_MODE
3346       /* Moving into a memory of stack_mode may have been moved
3347          in between the use and set of cc0 by loop_spl(). So
3348          old value of cc.status must be retained */
3349       if(GET_CODE(SET_DEST(exp))==MEM 
3350          && IS_STACK_MODE(GET_MODE(SET_DEST(exp))))
3351         {
3352           return;
3353         }
3354 #endif
3355       /* Moving register or memory into a register:
3356          it doesn't alter the cc's, but it might invalidate
3357          the RTX's which we remember the cc's came from.
3358          (Note that moving a constant 0 or 1 MAY set the cc's).  */
3359       if (REG_P (SET_DEST (exp))
3360           && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM
3361               || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
3362         {
3363           if (cc_status.value1
3364               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
3365             cc_status.value1 = 0;
3366           if (cc_status.value2
3367               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
3368             cc_status.value2 = 0;
3369           return;
3370         }
3371       /* Moving register into memory doesn't alter the cc's.
3372          It may invalidate the RTX's which we remember the cc's came from.  */
3373       if (GET_CODE (SET_DEST (exp)) == MEM
3374           && (REG_P (SET_SRC (exp))
3375               || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
3376         {
3377           if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
3378               || reg_mentioned_p (SET_DEST (exp), cc_status.value1))
3379             cc_status.value1 = 0;
3380           if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM
3381               || reg_mentioned_p (SET_DEST (exp), cc_status.value2))
3382             cc_status.value2 = 0;
3383           return;
3384         }
3385       /* Function calls clobber the cc's.  */
3386       else if (GET_CODE (SET_SRC (exp)) == CALL)
3387         {
3388           CC_STATUS_INIT;
3389           return;
3390         }
3391       /* Tests and compares set the cc's in predictable ways.  */
3392       else if (SET_DEST (exp) == cc0_rtx)
3393         {
3394           CC_STATUS_INIT;
3395           cc_status.value1 = SET_SRC (exp);
3396           return;
3397         }
3398       /* Certain instructions effect the condition codes. */
3399       else if (GET_MODE (SET_SRC (exp)) == SImode
3400                || GET_MODE (SET_SRC (exp)) == HImode
3401                || GET_MODE (SET_SRC (exp)) == QImode)
3402         switch (GET_CODE (SET_SRC (exp)))
3403           {
3404           case ASHIFTRT: case LSHIFTRT:
3405           case ASHIFT:
3406             /* Shifts on the 386 don't set the condition codes if the
3407                shift count is zero. */
3408             if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
3409               {
3410                 CC_STATUS_INIT;
3411                 break;
3412               }
3413             /* We assume that the CONST_INT is non-zero (this rtx would
3414                have been deleted if it were zero. */
3415
3416           case PLUS: case MINUS: case NEG:
3417           case AND: case IOR: case XOR:
3418             cc_status.flags = CC_NO_OVERFLOW;
3419             cc_status.value1 = SET_SRC (exp);
3420             cc_status.value2 = SET_DEST (exp);
3421             break;
3422
3423           default:
3424             CC_STATUS_INIT;
3425           }
3426       else
3427         {
3428           CC_STATUS_INIT;
3429         }
3430     }
3431   else if (GET_CODE (exp) == PARALLEL
3432            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
3433     {
3434       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
3435         return;
3436       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
3437         {
3438           CC_STATUS_INIT;
3439           if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
3440             {
3441               cc_status.flags |= CC_IN_80387;
3442               if (TARGET_CMOVE && stack_regs_mentioned_p
3443                   (XEXP (SET_SRC (XVECEXP (exp, 0, 0)), 1)))
3444                 cc_status.flags |= CC_FCOMI;
3445             }
3446           else
3447             cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
3448           return;
3449         }
3450       CC_STATUS_INIT;
3451     }
3452   else
3453     {
3454       CC_STATUS_INIT;
3455     }
3456 }
3457 \f
3458 /* Split one or more DImode RTL references into pairs of SImode
3459    references.  The RTL can be REG, offsettable MEM, integer constant, or
3460    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
3461    split and "num" is its length.  lo_half and hi_half are output arrays
3462    that parallel "operands". */
3463
3464 void
3465 split_di (operands, num, lo_half, hi_half)
3466      rtx operands[];
3467      int num;
3468      rtx lo_half[], hi_half[];
3469 {
3470   while (num--)
3471     {
3472       if (GET_CODE (operands[num]) == REG)
3473         {
3474           lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
3475           hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
3476         }
3477       else if (CONSTANT_P (operands[num]))
3478         {
3479           split_double (operands[num], &lo_half[num], &hi_half[num]);
3480         }
3481       else if (offsettable_memref_p (operands[num]))
3482         {
3483           lo_half[num] = operands[num];
3484           hi_half[num] = adj_offsettable_operand (operands[num], 4);
3485         }
3486       else
3487         abort();
3488     }
3489 }
3490 \f
3491 /* Return 1 if this is a valid binary operation on a 387.
3492    OP is the expression matched, and MODE is its mode. */
3493
3494 int
3495 binary_387_op (op, mode)
3496     register rtx op;
3497     enum machine_mode mode;
3498 {
3499   if (mode != VOIDmode && mode != GET_MODE (op))
3500     return 0;
3501
3502   switch (GET_CODE (op))
3503     {
3504     case PLUS:
3505     case MINUS:
3506     case MULT:
3507     case DIV:
3508       return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;
3509
3510     default:
3511       return 0;
3512     }
3513 }
3514
3515 \f
3516 /* Return 1 if this is a valid shift or rotate operation on a 386.
3517    OP is the expression matched, and MODE is its mode. */
3518
3519 int
3520 shift_op (op, mode)
3521     register rtx op;
3522     enum machine_mode mode;
3523 {
3524   rtx operand = XEXP (op, 0);
3525
3526   if (mode != VOIDmode && mode != GET_MODE (op))
3527     return 0;
3528
3529   if (GET_MODE (operand) != GET_MODE (op)
3530       || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
3531     return 0;
3532
3533   return (GET_CODE (op) == ASHIFT
3534           || GET_CODE (op) == ASHIFTRT
3535           || GET_CODE (op) == LSHIFTRT
3536           || GET_CODE (op) == ROTATE
3537           || GET_CODE (op) == ROTATERT);
3538 }
3539
3540 /* Return 1 if OP is COMPARE rtx with mode VOIDmode.
3541    MODE is not used.  */
3542
3543 int
3544 VOIDmode_compare_op (op, mode)
3545     register rtx op;
3546     enum machine_mode mode;
3547 {
3548   return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode;
3549 }
3550 \f
3551 /* Output code to perform a 387 binary operation in INSN, one of PLUS,
3552    MINUS, MULT or DIV.  OPERANDS are the insn operands, where operands[3]
3553    is the expression of the binary operation.  The output may either be
3554    emitted here, or returned to the caller, like all output_* functions.
3555
3556    There is no guarantee that the operands are the same mode, as they
3557    might be within FLOAT or FLOAT_EXTEND expressions. */
3558
3559 char *
3560 output_387_binary_op (insn, operands)
3561      rtx insn;
3562      rtx *operands;
3563 {
3564   rtx temp;
3565   char *base_op;
3566   static char buf[100];
3567
3568   switch (GET_CODE (operands[3]))
3569     {
3570     case PLUS:
3571       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3572           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3573         base_op = "fiadd";
3574       else
3575         base_op = "fadd";
3576       break;
3577
3578     case MINUS:
3579       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3580           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3581         base_op = "fisub";
3582       else
3583         base_op = "fsub";
3584       break;
3585
3586     case MULT:
3587       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3588           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3589         base_op = "fimul";
3590       else
3591         base_op = "fmul";
3592       break;
3593
3594     case DIV:
3595       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3596           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3597         base_op = "fidiv";
3598       else
3599         base_op = "fdiv";
3600       break;
3601
3602     default:
3603       abort ();
3604     }
3605
3606   strcpy (buf, base_op);
3607
3608   switch (GET_CODE (operands[3]))
3609     {
3610     case MULT:
3611     case PLUS:
3612       if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
3613         {
3614           temp = operands[2];
3615           operands[2] = operands[1];
3616           operands[1] = temp;
3617         }
3618
3619       if (GET_CODE (operands[2]) == MEM)
3620         return strcat (buf, AS1 (%z2,%2));
3621
3622       if (NON_STACK_REG_P (operands[1]))
3623         {
3624           output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
3625           RET;
3626         }
3627       else if (NON_STACK_REG_P (operands[2]))
3628         {
3629           output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
3630           RET;
3631         }
3632
3633       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
3634         return strcat (buf, AS2 (p,%2,%0));
3635
3636       if (STACK_TOP_P (operands[0]))
3637         return strcat (buf, AS2C (%y2,%0));
3638       else
3639         return strcat (buf, AS2C (%2,%0));
3640
3641     case MINUS:
3642     case DIV:
3643       if (GET_CODE (operands[1]) == MEM)
3644         return strcat (buf, AS1 (r%z1,%1));
3645
3646       if (GET_CODE (operands[2]) == MEM)
3647         return strcat (buf, AS1 (%z2,%2));
3648
3649       if (NON_STACK_REG_P (operands[1]))
3650         {
3651           output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));
3652           RET;
3653         }
3654       else if (NON_STACK_REG_P (operands[2]))
3655         {
3656           output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
3657           RET;
3658         }
3659
3660       if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
3661         abort ();
3662
3663       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
3664         return strcat (buf, AS2 (rp,%2,%0));
3665
3666       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3667         return strcat (buf, AS2 (p,%1,%0));
3668
3669       if (STACK_TOP_P (operands[0]))
3670         {
3671           if (STACK_TOP_P (operands[1]))
3672             return strcat (buf, AS2C (%y2,%0));
3673           else
3674             return strcat (buf, AS2 (r,%y1,%0));
3675         }
3676       else if (STACK_TOP_P (operands[1]))
3677         return strcat (buf, AS2C (%1,%0));
3678       else
3679         return strcat (buf, AS2 (r,%2,%0));
3680
3681     default:
3682       abort ();
3683     }
3684 }
3685 \f
3686 /* Output code for INSN to convert a float to a signed int.  OPERANDS
3687    are the insn operands.  The output may be SFmode or DFmode and the
3688    input operand may be SImode or DImode.  As a special case, make sure
3689    that the 387 stack top dies if the output mode is DImode, because the
3690    hardware requires this.  */
3691
3692 char *
3693 output_fix_trunc (insn, operands)
3694      rtx insn;
3695      rtx *operands;
3696 {
3697   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
3698   rtx xops[2];
3699
3700   if (! STACK_TOP_P (operands[1]) ||
3701       (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
3702     abort ();
3703
3704   xops[0] = GEN_INT (12);
3705   xops[1] = operands[4];
3706
3707   output_asm_insn (AS1 (fnstc%W2,%2), operands);
3708   output_asm_insn (AS2 (mov%L2,%2,%4), operands);
3709   output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
3710   output_asm_insn (AS2 (mov%L4,%4,%3), operands);
3711   output_asm_insn (AS1 (fldc%W3,%3), operands);
3712
3713   if (NON_STACK_REG_P (operands[0]))
3714     output_to_reg (operands[0], stack_top_dies, operands[3]);
3715   else if (GET_CODE (operands[0]) == MEM)
3716     {
3717       if (stack_top_dies)
3718         output_asm_insn (AS1 (fistp%z0,%0), operands);
3719       else
3720         output_asm_insn (AS1 (fist%z0,%0), operands);
3721     }
3722   else
3723     abort ();
3724
3725   return AS1 (fldc%W2,%2);
3726 }
3727 \f
3728 /* Output code for INSN to compare OPERANDS.  The two operands might
3729    not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
3730    expression.  If the compare is in mode CCFPEQmode, use an opcode that
3731    will not fault if a qNaN is present. */
3732
3733 char *
3734 output_float_compare (insn, operands)
3735      rtx insn;
3736      rtx *operands;
3737 {
3738   int stack_top_dies;
3739   rtx body = XVECEXP (PATTERN (insn), 0, 0);
3740   int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
3741   rtx tmp;
3742
3743   if (TARGET_CMOVE && STACK_REG_P (operands[1]))
3744     {
3745       cc_status.flags |= CC_FCOMI;
3746       cc_prev_status.flags &= ~CC_TEST_AX;
3747     }
3748
3749   if (! STACK_TOP_P (operands[0]))
3750     {
3751       tmp = operands[0];
3752       operands[0] = operands[1];
3753       operands[1] = tmp;
3754       cc_status.flags |= CC_REVERSED;
3755     }
3756     
3757   if (! STACK_TOP_P (operands[0]))
3758     abort ();
3759
3760   stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
3761
3762   if (STACK_REG_P (operands[1])
3763       && stack_top_dies
3764       && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
3765       && REGNO (operands[1]) != FIRST_STACK_REG)
3766     {
3767       /* If both the top of the 387 stack dies, and the other operand
3768          is also a stack register that dies, then this must be a
3769          `fcompp' float compare */
3770
3771       if (unordered_compare)
3772         if (cc_status.flags & CC_FCOMI)
3773           {
3774             output_asm_insn (AS2 (fucomip,%y1,%0), operands);
3775             output_asm_insn (AS1 (fstp, %y0), operands);
3776             RET;
3777           }
3778         else
3779           output_asm_insn ("fucompp", operands);
3780       else
3781         {
3782         if (cc_status.flags & CC_FCOMI)
3783           {
3784             output_asm_insn (AS2 (fcomip, %y1,%0), operands);
3785             output_asm_insn (AS1 (fstp, %y0), operands);
3786             RET;
3787           }
3788         else
3789           output_asm_insn ("fcompp", operands);
3790         }
3791     }
3792   else
3793     {
3794       static char buf[100];
3795
3796       /* Decide if this is the integer or float compare opcode, or the
3797          unordered float compare. */
3798
3799       if (unordered_compare)
3800         strcpy (buf, (cc_status.flags & CC_FCOMI) ? "fucomi" : "fucom");
3801       else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
3802         strcpy (buf, (cc_status.flags & CC_FCOMI) ? "fcomi" : "fcom");
3803       else
3804         strcpy (buf, "ficom");
3805
3806       /* Modify the opcode if the 387 stack is to be popped. */
3807
3808       if (stack_top_dies)
3809         strcat (buf, "p");
3810
3811       if (NON_STACK_REG_P (operands[1]))
3812         output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
3813       else if (cc_status.flags & CC_FCOMI) 
3814         {
3815           output_asm_insn (strcat (buf, AS2 (%z1,%y1,%0)), operands);
3816           RET;
3817         }
3818       else
3819         output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);
3820     }
3821
3822   /* Now retrieve the condition code. */
3823
3824   return output_fp_cc0_set (insn);
3825 }
3826 \f
3827 /* Output opcodes to transfer the results of FP compare or test INSN
3828    from the FPU to the CPU flags.  If TARGET_IEEE_FP, ensure that if the
3829    result of the compare or test is unordered, no comparison operator
3830    succeeds except NE.  Return an output template, if any.  */
3831
3832 char *
3833 output_fp_cc0_set (insn)
3834      rtx insn;
3835 {
3836   rtx xops[3];
3837   rtx unordered_label;
3838   rtx next;
3839   enum rtx_code code;
3840
3841   xops[0] = gen_rtx (REG, HImode, 0);
3842   output_asm_insn (AS1 (fnsts%W0,%0), xops);
3843
3844   if (! TARGET_IEEE_FP)
3845     {
3846       if (!(cc_status.flags & CC_REVERSED))
3847         {
3848           next = next_cc0_user (insn);
3849         
3850           if (GET_CODE (next) == JUMP_INSN
3851               && GET_CODE (PATTERN (next)) == SET
3852               && SET_DEST (PATTERN (next)) == pc_rtx
3853               && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3854             {
3855               code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3856             }
3857           else if (GET_CODE (PATTERN (next)) == SET)
3858             {
3859               code = GET_CODE (SET_SRC (PATTERN (next)));
3860             }
3861           else
3862             {
3863               return "sahf";
3864             }
3865           if (code == GT || code == LT || code == EQ || code == NE
3866               || code == LE || code == GE)
3867             { /* We will test eax directly */
3868               cc_status.flags |= CC_TEST_AX;
3869               RET;
3870             }
3871         }
3872       return "sahf";
3873     }
3874
3875   next = next_cc0_user (insn);
3876   if (next == NULL_RTX)
3877     abort ();
3878
3879   if (GET_CODE (next) == JUMP_INSN
3880       && GET_CODE (PATTERN (next)) == SET
3881       && SET_DEST (PATTERN (next)) == pc_rtx
3882       && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3883     {
3884       code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3885     }
3886   else if (GET_CODE (PATTERN (next)) == SET)
3887     {
3888       if (GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3889         code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3890       else code = GET_CODE (SET_SRC (PATTERN (next)));
3891     }
3892   else if (GET_CODE (PATTERN (next)) == PARALLEL
3893            && GET_CODE (XVECEXP (PATTERN (next), 0, 0)) == SET)
3894     {
3895       if (GET_CODE (SET_SRC (XVECEXP (PATTERN (next), 0, 0))) == IF_THEN_ELSE)
3896           code = GET_CODE (XEXP (SET_SRC (XVECEXP (PATTERN (next), 0, 0)), 0));
3897       else code = GET_CODE (SET_SRC (XVECEXP (PATTERN (next), 0, 0)));
3898     }
3899   else
3900     abort ();
3901
3902   xops[0] = gen_rtx (REG, QImode, 0);
3903
3904   switch (code)
3905     {
3906     case GT:
3907       xops[1] = GEN_INT (0x45);
3908       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3909       /* je label */
3910       break;
3911
3912     case LT:
3913       xops[1] = GEN_INT (0x45);
3914       xops[2] = GEN_INT (0x01);
3915       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3916       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3917       /* je label */
3918       break;
3919
3920     case GE:
3921       xops[1] = GEN_INT (0x05);
3922       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3923       /* je label */
3924       break;
3925
3926     case LE:
3927       xops[1] = GEN_INT (0x45);
3928       xops[2] = GEN_INT (0x40);
3929       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3930       output_asm_insn (AS1 (dec%B0,%h0), xops);
3931       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3932       /* jb label */
3933       break;
3934
3935     case EQ:
3936       xops[1] = GEN_INT (0x45);
3937       xops[2] = GEN_INT (0x40);
3938       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3939       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3940       /* je label */
3941       break;
3942
3943     case NE:
3944       xops[1] = GEN_INT (0x44);
3945       xops[2] = GEN_INT (0x40);
3946       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3947       output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
3948       /* jne label */
3949       break;
3950
3951     case GTU:
3952     case LTU:
3953     case GEU:
3954     case LEU:
3955     default:
3956       abort ();
3957     }
3958   RET;
3959 }
3960 \f
3961 #define MAX_386_STACK_LOCALS 2
3962
3963 static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
3964
3965 /* Define the structure for the machine field in struct function.  */
3966 struct machine_function
3967 {
3968   rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
3969 };
3970
3971 /* Functions to save and restore i386_stack_locals.
3972    These will be called, via pointer variables,
3973    from push_function_context and pop_function_context.  */
3974
3975 void
3976 save_386_machine_status (p)
3977      struct function *p;
3978 {
3979   p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals);
3980   bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals,
3981          sizeof i386_stack_locals);
3982 }
3983
3984 void
3985 restore_386_machine_status (p)
3986      struct function *p;
3987 {
3988   bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals,
3989          sizeof i386_stack_locals);
3990   free (p->machine);
3991 }
3992
3993 /* Clear stack slot assignments remembered from previous functions.
3994    This is called from INIT_EXPANDERS once before RTL is emitted for each
3995    function.  */
3996
3997 void
3998 clear_386_stack_locals ()
3999 {
4000   enum machine_mode mode;
4001   int n;
4002
4003   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
4004        mode = (enum machine_mode) ((int) mode + 1))
4005     for (n = 0; n < MAX_386_STACK_LOCALS; n++)
4006       i386_stack_locals[(int) mode][n] = NULL_RTX;
4007
4008   /* Arrange to save and restore i386_stack_locals around nested functions.  */
4009   save_machine_status = save_386_machine_status;
4010   restore_machine_status = restore_386_machine_status;
4011 }
4012
4013 /* Return a MEM corresponding to a stack slot with mode MODE.
4014    Allocate a new slot if necessary.
4015
4016    The RTL for a function can have several slots available: N is
4017    which slot to use.  */
4018
4019 rtx
4020 assign_386_stack_local (mode, n)
4021      enum machine_mode mode;
4022      int n;
4023 {
4024   if (n < 0 || n >= MAX_386_STACK_LOCALS)
4025     abort ();
4026
4027   if (i386_stack_locals[(int) mode][n] == NULL_RTX)
4028     i386_stack_locals[(int) mode][n]
4029       = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
4030
4031   return i386_stack_locals[(int) mode][n];
4032 }
4033
4034 \f
4035 int is_mul(op,mode)
4036     register rtx op;
4037     enum machine_mode mode;
4038 {
4039   return (GET_CODE (op) == MULT);
4040 }
4041
4042 int is_div(op,mode)
4043     register rtx op;
4044     enum machine_mode mode;
4045 {
4046   return (GET_CODE (op) == DIV);
4047 }
4048
4049 \f
4050 #ifdef NOTYET
4051 /* Create a new copy of an rtx.
4052    Recursively copies the operands of the rtx,
4053    except for those few rtx codes that are sharable.
4054    Doesn't share CONST  */
4055
4056 rtx
4057 copy_all_rtx (orig)
4058      register rtx orig;
4059 {
4060   register rtx copy;
4061   register int i, j;
4062   register RTX_CODE code;
4063   register char *format_ptr;
4064
4065   code = GET_CODE (orig);
4066
4067   switch (code)
4068     {
4069     case REG:
4070     case QUEUED:
4071     case CONST_INT:
4072     case CONST_DOUBLE:
4073     case SYMBOL_REF:
4074     case CODE_LABEL:
4075     case PC:
4076     case CC0:
4077     case SCRATCH:
4078       /* SCRATCH must be shared because they represent distinct values. */
4079       return orig;
4080
4081 #if 0
4082     case CONST:
4083       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
4084          a LABEL_REF, it isn't sharable.  */
4085       if (GET_CODE (XEXP (orig, 0)) == PLUS
4086           && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
4087           && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT)
4088         return orig;
4089       break;
4090 #endif
4091       /* A MEM with a constant address is not sharable.  The problem is that
4092          the constant address may need to be reloaded.  If the mem is shared,
4093          then reloading one copy of this mem will cause all copies to appear
4094          to have been reloaded.  */
4095     }
4096
4097   copy = rtx_alloc (code);
4098   PUT_MODE (copy, GET_MODE (orig));
4099   copy->in_struct = orig->in_struct;
4100   copy->volatil = orig->volatil;
4101   copy->unchanging = orig->unchanging;
4102   copy->integrated = orig->integrated;
4103   /* intel1 */
4104   copy->is_spill_rtx = orig->is_spill_rtx;
4105   
4106   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
4107
4108   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
4109     {
4110       switch (*format_ptr++)
4111         {
4112         case 'e':
4113           XEXP (copy, i) = XEXP (orig, i);
4114           if (XEXP (orig, i) != NULL)
4115             XEXP (copy, i) = copy_rtx (XEXP (orig, i));
4116           break;
4117
4118         case '0':
4119         case 'u':
4120           XEXP (copy, i) = XEXP (orig, i);
4121           break;
4122
4123         case 'E':
4124         case 'V':
4125           XVEC (copy, i) = XVEC (orig, i);
4126           if (XVEC (orig, i) != NULL)
4127             {
4128               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
4129               for (j = 0; j < XVECLEN (copy, i); j++)
4130                 XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
4131             }
4132           break;
4133
4134         case 'w':
4135           XWINT (copy, i) = XWINT (orig, i);
4136           break;
4137
4138         case 'i':
4139           XINT (copy, i) = XINT (orig, i);
4140           break;
4141
4142         case 's':
4143         case 'S':
4144           XSTR (copy, i) = XSTR (orig, i);
4145           break;
4146
4147         default:
4148           abort ();
4149         }
4150     }
4151   return copy;
4152 }
4153
4154 \f
4155 /* try to rewrite a memory address to make it valid */
4156 void 
4157 rewrite_address (mem_rtx)
4158      rtx mem_rtx;
4159 {
4160   rtx index_rtx, base_rtx, offset_rtx, scale_rtx, ret_rtx;
4161   int scale = 1;
4162   int offset_adjust = 0;
4163   int was_only_offset = 0;
4164   rtx mem_addr = XEXP (mem_rtx, 0);
4165   char *storage = (char *) oballoc (0);
4166   int in_struct = 0;
4167   int is_spill_rtx = 0;
4168
4169   in_struct = MEM_IN_STRUCT_P (mem_rtx);
4170   is_spill_rtx = RTX_IS_SPILL_P (mem_rtx);
4171
4172   if (GET_CODE (mem_addr) == PLUS &&
4173       GET_CODE (XEXP (mem_addr, 1)) == PLUS &&
4174       GET_CODE (XEXP (XEXP (mem_addr, 1), 0)) == REG)
4175     {                           /* this part is utilized by the combiner */
4176       ret_rtx =
4177         gen_rtx (PLUS, GET_MODE (mem_addr),
4178                  gen_rtx (PLUS, GET_MODE (XEXP (mem_addr, 1)),
4179                           XEXP (mem_addr, 0),
4180                           XEXP (XEXP (mem_addr, 1), 0)),
4181                  XEXP (XEXP (mem_addr, 1), 1));
4182       if (memory_address_p (GET_MODE (mem_rtx), ret_rtx))
4183         {
4184           XEXP (mem_rtx, 0) = ret_rtx;
4185           RTX_IS_SPILL_P (ret_rtx) = is_spill_rtx;
4186           return;
4187         }
4188       obfree (storage);
4189     }
4190
4191   /* this part is utilized by loop.c */
4192   /* If the address contains PLUS (reg,const) and this pattern is invalid
4193      in this case - try to rewrite the address to make it valid  intel1
4194   */
4195   storage = (char *) oballoc (0);
4196   index_rtx = base_rtx = offset_rtx = NULL;
4197   /* find the base index and offset elements of the memory address */
4198   if (GET_CODE (mem_addr) == PLUS)
4199     {
4200       if (GET_CODE (XEXP (mem_addr, 0)) == REG)
4201         {
4202           if (GET_CODE (XEXP (mem_addr, 1)) == REG)
4203             {
4204               base_rtx = XEXP (mem_addr, 1);
4205               index_rtx = XEXP (mem_addr, 0);
4206             }
4207           else
4208             {
4209               base_rtx = XEXP (mem_addr, 0);
4210               offset_rtx = XEXP (mem_addr, 1);
4211             }
4212         }
4213       else if (GET_CODE (XEXP (mem_addr, 0)) == MULT)
4214         {
4215           index_rtx = XEXP (mem_addr, 0);
4216           if (GET_CODE (XEXP (mem_addr, 1)) == REG)
4217             {
4218               base_rtx = XEXP (mem_addr, 1);
4219             }
4220           else
4221             {
4222               offset_rtx = XEXP (mem_addr, 1);
4223             }
4224         }
4225       else if (GET_CODE (XEXP (mem_addr, 0)) == PLUS)
4226         {
4227           /* intel1 */
4228           if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == PLUS &&
4229               GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0)) == MULT &&
4230               GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 0)) == REG &&
4231               GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 1)) == CONST_INT &&
4232               GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)) == CONST_INT &&
4233               GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == REG &&
4234               GET_CODE (XEXP (mem_addr, 1)) == SYMBOL_REF)
4235             {
4236               index_rtx = XEXP (XEXP (XEXP (mem_addr, 0), 0), 0);
4237               offset_rtx = XEXP (mem_addr, 1);
4238               base_rtx = XEXP (XEXP (mem_addr, 0), 1);
4239               offset_adjust = INTVAL (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1));
4240             }
4241           else
4242             {
4243               offset_rtx = XEXP (mem_addr, 1);
4244               index_rtx = XEXP (XEXP (mem_addr, 0), 0);
4245               base_rtx = XEXP (XEXP (mem_addr, 0), 1);
4246             }
4247         }
4248       else if (GET_CODE (XEXP (mem_addr, 0)) == CONST_INT)
4249         {
4250           was_only_offset = 1;
4251           index_rtx = NULL;
4252           base_rtx = NULL;
4253           offset_rtx = XEXP (mem_addr, 1);
4254           offset_adjust = INTVAL (XEXP (mem_addr, 0));
4255           if (offset_adjust == 0)
4256             {
4257               XEXP (mem_rtx, 0) = offset_rtx;
4258               RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
4259               return;
4260             }
4261         }
4262       else
4263         {
4264           obfree (storage);
4265           return;
4266         }
4267     }
4268   else if (GET_CODE (mem_addr) == MULT)
4269     {
4270       index_rtx = mem_addr;
4271     }
4272   else
4273     {
4274       obfree (storage);
4275       return;
4276     }
4277   if (index_rtx && GET_CODE (index_rtx) == MULT)
4278     {
4279       if (GET_CODE (XEXP (index_rtx, 1)) != CONST_INT)
4280         {
4281           obfree (storage);
4282           return;
4283         }
4284       scale_rtx = XEXP (index_rtx, 1);
4285       scale = INTVAL (scale_rtx);
4286       index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
4287     }
4288   /* now find which of the elements are invalid and try to fix them */
4289   if (index_rtx && GET_CODE (index_rtx) == CONST_INT && base_rtx == NULL)
4290     {
4291       offset_adjust = INTVAL (index_rtx) * scale;
4292       if (offset_rtx && GET_CODE (offset_rtx) == CONST &&
4293           GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
4294         {
4295           if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
4296               GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
4297             {
4298               offset_rtx = copy_all_rtx (offset_rtx);
4299               XEXP (XEXP (offset_rtx, 0), 1) =
4300                 gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
4301               if (!CONSTANT_P (offset_rtx))
4302                 {
4303                   obfree (storage);
4304                   return;
4305                 }
4306             }
4307         }
4308       else if (offset_rtx && GET_CODE (offset_rtx) == SYMBOL_REF)
4309         {
4310           offset_rtx =
4311             gen_rtx (CONST, GET_MODE (offset_rtx),
4312                      gen_rtx (PLUS, GET_MODE (offset_rtx),
4313                               offset_rtx,
4314                               gen_rtx (CONST_INT, 0, offset_adjust)));
4315           if (!CONSTANT_P (offset_rtx))
4316             {
4317               obfree (storage);
4318               return;
4319             }
4320         }
4321       else if (offset_rtx && GET_CODE (offset_rtx) == CONST_INT)
4322         {
4323           offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
4324         }
4325       else if (!offset_rtx)
4326         {
4327           offset_rtx = gen_rtx (CONST_INT, 0, 0);
4328         }
4329       RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
4330       XEXP (mem_rtx, 0) = offset_rtx;
4331       return;
4332     }
4333   if (base_rtx && GET_CODE (base_rtx) == PLUS &&
4334       GET_CODE (XEXP (base_rtx, 0)) == REG &&
4335       GET_CODE (XEXP (base_rtx, 1)) == CONST_INT)
4336     {
4337       offset_adjust += INTVAL (XEXP (base_rtx, 1));
4338       base_rtx = copy_all_rtx (XEXP (base_rtx, 0));
4339     }
4340   else if (base_rtx && GET_CODE (base_rtx) == CONST_INT)
4341     {
4342       offset_adjust += INTVAL (base_rtx);
4343       base_rtx = NULL;
4344     }
4345   if (index_rtx && GET_CODE (index_rtx) == PLUS &&
4346       GET_CODE (XEXP (index_rtx, 0)) == REG &&
4347       GET_CODE (XEXP (index_rtx, 1)) == CONST_INT)
4348     {
4349       offset_adjust += INTVAL (XEXP (index_rtx, 1)) * scale;
4350       index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
4351     }
4352   if (index_rtx)
4353     {
4354       if (!LEGITIMATE_INDEX_P (index_rtx)
4355       && !(index_rtx == stack_pointer_rtx && scale == 1 && base_rtx == NULL))
4356         {
4357           obfree (storage);
4358           return;
4359         }
4360     }
4361   if (base_rtx)
4362     {
4363       if (!LEGITIMATE_INDEX_P (base_rtx) && GET_CODE (base_rtx) != REG)
4364         {
4365           obfree (storage);
4366           return;
4367         }
4368     }
4369   if (offset_adjust != 0)
4370     {
4371       if (offset_rtx)
4372         {
4373           if (GET_CODE (offset_rtx) == CONST &&
4374               GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
4375             {
4376               if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
4377                   GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
4378                 {
4379                   offset_rtx = copy_all_rtx (offset_rtx);
4380                   XEXP (XEXP (offset_rtx, 0), 1) =
4381                     gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
4382                   if (!CONSTANT_P (offset_rtx))
4383                     {
4384                       obfree (storage);
4385                       return;
4386                     }
4387                 }
4388             }
4389           else if (GET_CODE (offset_rtx) == SYMBOL_REF)
4390             {
4391               offset_rtx =
4392                 gen_rtx (CONST, GET_MODE (offset_rtx),
4393                          gen_rtx (PLUS, GET_MODE (offset_rtx),
4394                                   offset_rtx,
4395                                   gen_rtx (CONST_INT, 0, offset_adjust)));
4396               if (!CONSTANT_P (offset_rtx))
4397                 {
4398                   obfree (storage);
4399                   return;
4400                 }
4401             }
4402           else if (GET_CODE (offset_rtx) == CONST_INT)
4403             {
4404               offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
4405             }
4406           else
4407             {
4408               obfree (storage);
4409               return;
4410             }
4411         }
4412       else
4413         {
4414           offset_rtx = gen_rtx (CONST_INT, 0, offset_adjust);
4415         }
4416       if (index_rtx)
4417         {
4418           if (base_rtx)
4419             {
4420               if (scale != 1)
4421                 {
4422                   if (GET_CODE (offset_rtx) == CONST_INT &&
4423                       INTVAL (offset_rtx) == 0)
4424                     {
4425                       ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx),
4426                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
4427                                       scale_rtx),
4428                                          base_rtx);
4429                     }
4430                   else
4431                     {
4432                       ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
4433                                          gen_rtx (PLUS, GET_MODE (base_rtx),
4434                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
4435                                       scale_rtx),
4436                                                   base_rtx),
4437                                          offset_rtx);
4438                     }
4439                 }
4440               else
4441                 {
4442                   if (GET_CODE (offset_rtx) == CONST_INT &&
4443                       INTVAL (offset_rtx) == 0)
4444                     {
4445                       ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, base_rtx);
4446                     }
4447                   else
4448                     {
4449                       ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
4450                              gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx,
4451                                       base_rtx),
4452                                          offset_rtx);
4453                     }
4454                 }
4455             }
4456           else
4457             {
4458               if (scale != 1)
4459                 {
4460                   if (GET_CODE (offset_rtx) == CONST_INT &&
4461                       INTVAL (offset_rtx) == 0)
4462                     {
4463                       ret_rtx = gen_rtx (MULT, GET_MODE (index_rtx), index_rtx, scale_rtx);
4464                     }
4465                   else
4466                     {
4467                       ret_rtx =
4468                         gen_rtx (PLUS, GET_MODE (offset_rtx),
4469                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
4470                                       scale_rtx),
4471                                  offset_rtx);
4472                     }
4473                 }
4474               else
4475                 {
4476                   if (GET_CODE (offset_rtx) == CONST_INT &&
4477                       INTVAL (offset_rtx) == 0)
4478                     {
4479                       ret_rtx = index_rtx;
4480                     }
4481                   else
4482                     {
4483                       ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, offset_rtx);
4484                     }
4485                 }
4486             }
4487         }
4488       else
4489         {
4490           if (base_rtx)
4491             {
4492               if (GET_CODE (offset_rtx) == CONST_INT &&
4493                   INTVAL (offset_rtx) == 0)
4494                 {
4495                   ret_rtx = base_rtx;
4496                 }
4497               else
4498                 {
4499                   ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx), base_rtx, offset_rtx);
4500                 }
4501             }
4502           else if (was_only_offset)
4503             {
4504               ret_rtx = offset_rtx;
4505             }
4506           else
4507             {
4508               obfree (storage);
4509               return;
4510             }
4511         }
4512       XEXP (mem_rtx, 0) = ret_rtx;
4513       RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
4514       return;
4515     }
4516   else
4517     {
4518       obfree (storage);
4519       return;
4520     }
4521 }
4522 #endif /* NOTYET */
4523
4524 \f
4525 /* return 1 if the first insn to set cc before insn also sets the register
4526    reg_rtx - otherwise return 0 */
4527 int
4528 last_to_set_cc (reg_rtx, insn)
4529      rtx reg_rtx, insn;
4530 {
4531   rtx prev_insn = PREV_INSN (insn);
4532
4533   while (prev_insn)
4534     {
4535       if (GET_CODE (prev_insn) == NOTE)
4536         ;
4537
4538       else if (GET_CODE (prev_insn) == INSN)
4539         {
4540           if (GET_CODE (PATTERN (prev_insn)) != SET)
4541             return (0);
4542
4543           if (rtx_equal_p (SET_DEST (PATTERN (prev_insn)), reg_rtx))
4544             {
4545               if (sets_condition_code (SET_SRC (PATTERN (prev_insn))))
4546                 return (1);
4547
4548               return (0);
4549             }
4550
4551           else if (!doesnt_set_condition_code (SET_SRC (PATTERN (prev_insn))))
4552             return (0);
4553         }
4554
4555       else
4556         return (0);
4557
4558       prev_insn = PREV_INSN (prev_insn);
4559     }
4560
4561   return (0);
4562 }
4563
4564 \f
4565 int
4566 doesnt_set_condition_code (pat)
4567      rtx pat;
4568 {
4569   switch (GET_CODE (pat))
4570     {
4571     case MEM:
4572     case REG:
4573       return (1);
4574
4575     default:
4576       return (0);
4577
4578     }
4579 }
4580
4581 \f
4582 int
4583 sets_condition_code (pat)
4584      rtx pat;
4585 {
4586   switch (GET_CODE (pat))
4587     {
4588     case PLUS:
4589     case MINUS:
4590     case AND:
4591     case IOR:
4592     case XOR:
4593     case NOT:
4594     case NEG:
4595     case MULT:
4596     case DIV:
4597     case MOD:
4598     case UDIV:
4599     case UMOD:
4600       return (1);
4601
4602     default:
4603       return (0);
4604
4605     }
4606 }
4607
4608 \f
4609 int
4610 str_immediate_operand (op, mode)
4611      register rtx op;
4612      enum machine_mode mode;
4613 {
4614   if (GET_CODE (op) == CONST_INT && INTVAL (op) <= 32 && INTVAL (op) >= 0)
4615     {
4616       return (1);
4617     }
4618   return (0);
4619 }
4620
4621 \f
4622 int
4623 is_fp_insn (insn)
4624      rtx insn;
4625 {
4626   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4627       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4628           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4629           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode))
4630     {
4631       return (1);
4632     }
4633
4634   return (0);
4635 }
4636
4637 /*
4638   Return 1 if the mode of the SET_DEST of insn is floating point
4639   and it is not an fld or a move from memory to memory.
4640   Otherwise return 0 */
4641 int
4642 is_fp_dest (insn)
4643      rtx insn;
4644 {
4645   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4646       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4647           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4648           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)
4649       && GET_CODE (SET_DEST (PATTERN (insn))) == REG
4650       && REGNO (SET_DEST (PATTERN (insn))) >= FIRST_FLOAT_REG
4651       && GET_CODE (SET_SRC (insn)) != MEM)
4652     {
4653       return (1);
4654     }
4655
4656   return (0);
4657 }
4658
4659 /*
4660   Return 1 if the mode of the SET_DEST floating point and is memory
4661   and the source is a register.  
4662 */
4663 int
4664 is_fp_store (insn)
4665      rtx insn;
4666 {
4667   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4668       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4669           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4670           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)
4671       && GET_CODE (SET_DEST (PATTERN (insn))) == MEM
4672       && GET_CODE (SET_SRC (PATTERN (insn))) == REG)
4673     {
4674       return (1);
4675     }
4676
4677   return (0);
4678 }
4679
4680 \f
4681 /*
4682   Return 1 if dep_insn sets a register which insn uses as a base
4683   or index to reference memory.
4684   otherwise return 0 */
4685
4686 int
4687 agi_dependent (insn, dep_insn)
4688      rtx insn, dep_insn;
4689 {
4690   if (GET_CODE (dep_insn) == INSN
4691       && GET_CODE (PATTERN (dep_insn)) == SET
4692       && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG)
4693     {
4694       return (reg_mentioned_in_mem (SET_DEST (PATTERN (dep_insn)), insn));
4695     }
4696
4697   if (GET_CODE (dep_insn) == INSN && GET_CODE (PATTERN (dep_insn)) == SET
4698       && GET_CODE (SET_DEST (PATTERN (dep_insn))) == MEM
4699       && push_operand (SET_DEST (PATTERN (dep_insn)),
4700                        GET_MODE (SET_DEST (PATTERN (dep_insn)))))
4701     {
4702       return (reg_mentioned_in_mem (stack_pointer_rtx, insn));
4703     }
4704   
4705   return (0);
4706 }
4707
4708 \f
4709 /*
4710   Return 1 if reg is used in rtl as a base or index for a memory ref
4711   otherwise return 0. */
4712
4713 int
4714 reg_mentioned_in_mem (reg, rtl)
4715      rtx reg, rtl;
4716 {
4717   register char *fmt;
4718   register int i;
4719   register enum rtx_code code;
4720
4721   if (rtl == NULL)
4722     return (0);
4723
4724   code = GET_CODE (rtl);
4725
4726   switch (code)
4727     {
4728     case HIGH:
4729     case CONST_INT:
4730     case CONST:
4731     case CONST_DOUBLE:
4732     case SYMBOL_REF:
4733     case LABEL_REF:
4734     case PC:
4735     case CC0:
4736     case SUBREG:
4737       return (0);
4738
4739
4740     }
4741
4742   if (code == MEM && reg_mentioned_p (reg, rtl))
4743     return (1);
4744
4745   fmt = GET_RTX_FORMAT (code);
4746   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4747     {
4748       if (fmt[i] == 'E')
4749         {
4750           register int j;
4751           for (j = XVECLEN (rtl, i) - 1; j >= 0; j--)
4752             {
4753               if (reg_mentioned_in_mem (reg, XVECEXP (rtl, i, j)))
4754                 return 1;
4755             }
4756         }
4757
4758       else if (fmt[i] == 'e' && reg_mentioned_in_mem (reg, XEXP (rtl, i)))
4759         return 1;
4760     }
4761
4762   return (0);
4763 }
4764 \f
4765 /* Output the approprate insns for doing strlen if not just doing repnz; scasb
4766
4767    operands[0] = result, initialized with the startaddress
4768    operands[1] = alignment of the address.
4769    operands[2] = scratch register, initialized with the startaddress when
4770                  not aligned, otherwise undefined
4771
4772    This is just the body. It needs the initialisations mentioned above and
4773    some address computing at the end.  These things are done in i386.md.  */
4774
4775 char *
4776 output_strlen_unroll (operands)
4777      rtx operands[];
4778 {
4779   rtx xops[18];
4780
4781   xops[0] = operands[0];                /* Result */
4782   /*        operands[1];                 * Alignment */
4783   xops[1] = operands[2];                /* Scratch */
4784   xops[2] = GEN_INT (0);
4785   xops[3] = GEN_INT (2);
4786   xops[4] = GEN_INT (3);
4787   xops[5] = GEN_INT (4);
4788   /* xops[6] = gen_label_rtx ();         * label when aligned to 3-byte */
4789   /* xops[7] = gen_label_rtx ();         * label when aligned to 2-byte */
4790   xops[8] = gen_label_rtx ();           /* label of main loop */
4791   if(TARGET_USE_Q_REG && QI_REG_P (xops[1]))
4792     xops[9] = gen_label_rtx ();         /* pentium optimisation */
4793   xops[10] = gen_label_rtx ();          /* end label 2 */
4794   xops[11] = gen_label_rtx ();          /* end label 1 */
4795   xops[12] = gen_label_rtx ();          /* end label */
4796   /* xops[13]                            * Temporary used */
4797   xops[14] = GEN_INT (0xff);
4798   xops[15] = GEN_INT (0xff00);
4799   xops[16] = GEN_INT (0xff0000);
4800   xops[17] = GEN_INT (0xff000000);
4801
4802     /* Loop to check 1..3 bytes for null to get an aligned pointer */
4803
4804     /* is there a known alignment and is it less then 4 */
4805   if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) < 4)
4806     {
4807         /* is there a known alignment and is it not 2 */
4808       if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2)
4809         {
4810           xops[6] = gen_label_rtx ();   /* label when aligned to 3-byte */
4811           xops[7] = gen_label_rtx ();   /* label when aligned to 2-byte */
4812
4813             /* leave just the 3 lower bits */
4814             /* if this is a q-register, then the high part is used later */
4815             /* therefore user andl rather than andb */
4816           output_asm_insn (AS2 (and%L1,%4,%1), xops);
4817             /* is aligned to 4-byte adress when zero */
4818           output_asm_insn (AS1 (je,%l8), xops);
4819             /* side-effect even Parity when %eax == 3 */
4820           output_asm_insn (AS1 (jp,%6), xops);
4821
4822             /* is it aligned to 2 bytes ? */
4823           if (QI_REG_P (xops[1]))
4824             output_asm_insn (AS2 (cmp%L1,%3,%1), xops);
4825           else
4826             output_asm_insn (AS2 (cmp%L1,%3,%1), xops);
4827           output_asm_insn (AS1 (je,%7), xops);
4828         }
4829       else
4830         {
4831             /* since the alignment is 2, we have to check 2 or 0 bytes */
4832
4833             /* check if is aligned to 4 - byte */
4834           output_asm_insn (AS2 (and%L1,%3,%1), xops);
4835             /* is aligned to 4-byte adress when zero */
4836           output_asm_insn (AS1 (je,%l8), xops);
4837         }
4838
4839       xops[13] = gen_rtx (MEM, QImode, xops[0]);
4840         /* now, compare the bytes */
4841         /* compare with the high part of a q-reg gives shorter code */
4842       if (QI_REG_P (xops[1]))
4843         {
4844             /* compare the first n unaligned byte on a byte per byte basis */
4845           output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4846             /* when zero we reached the end */
4847           output_asm_insn (AS1 (je,%l12), xops);
4848             /* increment the address */
4849           output_asm_insn (AS1 (inc%L0,%0), xops);
4850
4851             /* not needed with an alignment of 2 */
4852           if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2)
4853             {
4854               ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[7]));
4855               output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4856               output_asm_insn (AS1 (je,%l12), xops);
4857               output_asm_insn (AS1 (inc%L0,%0), xops);
4858
4859               ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[6]));
4860             }
4861           output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4862         }
4863       else
4864         {
4865           output_asm_insn (AS2 (cmp%B13,%2,%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[7]));
4870           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4871           output_asm_insn (AS1 (je,%l12), xops);
4872           output_asm_insn (AS1 (inc%L0,%0), xops);
4873
4874           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[6]));
4875           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4876         }
4877       output_asm_insn (AS1 (je,%l12), xops);
4878       output_asm_insn (AS1 (inc%L0,%0), xops);
4879     }
4880
4881     /* Generate loop to check 4 bytes at a time */
4882     /* IMHO it is not a good idea to align this loop.  It gives only */
4883     /* huge programs, but does not help to speed up */
4884   /* ASM_OUTPUT_LOOP_ALIGN (asm_out_file); */
4885   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[8]));
4886
4887   xops[13] = gen_rtx (MEM, SImode, xops[0]);
4888   output_asm_insn (AS2 (mov%L1,%13,%1), xops);
4889
4890   if (QI_REG_P (xops[1]))
4891     {
4892       /* On i586 it is faster to combine the hi- and lo- part as
4893          a kind of lookahead.  If anding both yields zero, then one
4894          of both *could* be zero, otherwise none of both is zero;
4895          this saves one instruction, on i486 this is slower
4896          tested with P-90, i486DX2-66, AMD486DX2-66  */
4897       if(TARGET_PENTIUM)
4898         {
4899           output_asm_insn (AS2 (test%B1,%h1,%b1), xops);
4900           output_asm_insn (AS1 (jne,%l9), xops);
4901         }
4902
4903         /* check first byte */
4904       output_asm_insn (AS2 (test%B1,%b1,%b1), xops);
4905       output_asm_insn (AS1 (je,%l12), xops);
4906
4907         /* check second byte */
4908       output_asm_insn (AS2 (test%B1,%h1,%h1), xops);
4909       output_asm_insn (AS1 (je,%l11), xops);
4910
4911       if(TARGET_PENTIUM)
4912           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[9]));
4913     }
4914   else
4915     {
4916         /* check first byte */
4917       output_asm_insn (AS2 (test%L1,%14,%1), xops);
4918       output_asm_insn (AS1 (je,%l12), xops);
4919
4920         /* check second byte */
4921       output_asm_insn (AS2 (test%L1,%15,%1), xops);
4922       output_asm_insn (AS1 (je,%l11), xops);
4923     }
4924
4925     /* check third byte */
4926   output_asm_insn (AS2 (test%L1,%16,%1), xops);
4927   output_asm_insn (AS1 (je,%l10), xops);
4928   
4929     /* check fourth byte and increment address */
4930   output_asm_insn (AS2 (add%L0,%5,%0), xops);
4931   output_asm_insn (AS2 (test%L1,%17,%1), xops);
4932   output_asm_insn (AS1 (jne,%l8), xops);
4933
4934     /* now generate fixups when the compare stops within a 4-byte word */
4935   output_asm_insn (AS2 (sub%L0,%4,%0), xops);
4936
4937   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[10]));
4938   output_asm_insn (AS1 (inc%L0,%0), xops);
4939
4940   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[11]));
4941   output_asm_insn (AS1 (inc%L0,%0), xops);
4942
4943   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[12]));
4944
4945   RET;
4946 }