OSDN Git Service

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