OSDN Git Service

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