OSDN Git Service

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