OSDN Git Service

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