OSDN Git Service

(ix86_binary_operator_ok): one memory operand is OK.
[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 || GET_RTX_CLASS (code) == 'c');
1623 }
1624 \f
1625 /* Attempt to expand a unary operator.  Make the expansion closer to the
1626    actual machine, then just general_operand, which will allow 2 separate
1627    memory references (one output, one input) in a single insn.  Return
1628    whether the insn fails, or succeeds.  */
1629
1630 int
1631 ix86_expand_unary_operator (code, mode, operands)
1632      enum rtx_code code;
1633      enum machine_mode mode;
1634      rtx operands[];
1635 {
1636   rtx insn;
1637
1638   /* If optimizing, copy to regs to improve CSE */
1639   if (TARGET_PSEUDO
1640       && optimize
1641       && ((reload_in_progress | reload_completed) == 0)
1642       && GET_CODE (operands[1]) == MEM)
1643     {
1644       operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
1645     }
1646
1647   if (!ix86_unary_operator_ok (code, mode, operands))
1648     {
1649       if ((!TARGET_PSEUDO || !optimize)
1650           && ((reload_in_progress | reload_completed) == 0)
1651           && GET_CODE (operands[1]) == MEM)
1652         {
1653           operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
1654           if (!ix86_unary_operator_ok (code, mode, operands))
1655             return FALSE;
1656         }
1657       else
1658         return FALSE;
1659     }
1660
1661   return TRUE;
1662 }
1663 \f
1664 /* Return TRUE or FALSE depending on whether the unary operator meets the
1665    appropriate constraints.  */
1666
1667 int
1668 ix86_unary_operator_ok (code, mode, operands)
1669      enum rtx_code code;
1670      enum machine_mode mode;
1671      rtx operands[2];
1672 {
1673   return TRUE;
1674 }
1675
1676 \f
1677 /* This function generates the assembly code for function entry.
1678    FILE is an stdio stream to output the code to.
1679    SIZE is an int: how many units of temporary storage to allocate. */
1680
1681 void
1682 function_prologue (file, size)
1683      FILE *file;
1684      int size;
1685 {
1686   register int regno;
1687   int limit;
1688   rtx xops[4];
1689   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1690                                   || current_function_uses_const_pool);
1691
1692   xops[0] = stack_pointer_rtx;
1693   xops[1] = frame_pointer_rtx;
1694   xops[2] = GEN_INT (size);
1695   if (frame_pointer_needed)
1696     {
1697       output_asm_insn ("push%L1 %1", xops);
1698       output_asm_insn (AS2 (mov%L0,%0,%1), xops);
1699     }
1700
1701   if (size)
1702     output_asm_insn (AS2 (sub%L0,%2,%0), xops);
1703
1704   /* Note If use enter it is NOT reversed args.
1705      This one is not reversed from intel!!
1706      I think enter is slower.  Also sdb doesn't like it.
1707      But if you want it the code is:
1708      {
1709      xops[3] = const0_rtx;
1710      output_asm_insn ("enter %2,%3", xops);
1711      }
1712      */
1713   limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
1714   for (regno = limit - 1; regno >= 0; regno--)
1715     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1716         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1717       {
1718         xops[0] = gen_rtx (REG, SImode, regno);
1719         output_asm_insn ("push%L0 %0", xops);
1720       }
1721
1722   if (pic_reg_used)
1723     {
1724       xops[0] = pic_offset_table_rtx;
1725       xops[1] = (rtx) gen_label_rtx ();
1726
1727       output_asm_insn (AS1 (call,%P1), xops);
1728       ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1]));
1729       output_asm_insn (AS1 (pop%L0,%0), xops);
1730       output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops);
1731     }
1732 }
1733
1734 /* Return 1 if it is appropriate to emit `ret' instructions in the
1735    body of a function.  Do this only if the epilogue is simple, needing a
1736    couple of insns.  Prior to reloading, we can't tell how many registers
1737    must be saved, so return 0 then.
1738
1739    If NON_SAVING_SETJMP is defined and true, then it is not possible
1740    for the epilogue to be simple, so return 0.  This is a special case
1741    since NON_SAVING_SETJMP will not cause regs_ever_live to change until
1742    final, but jump_optimize may need to know sooner if a `return' is OK.  */
1743
1744 int
1745 simple_386_epilogue ()
1746 {
1747   int regno;
1748   int nregs = 0;
1749   int reglimit = (frame_pointer_needed
1750                   ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
1751   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1752                                   || current_function_uses_const_pool);
1753
1754 #ifdef NON_SAVING_SETJMP
1755   if (NON_SAVING_SETJMP && current_function_calls_setjmp)
1756     return 0;
1757 #endif
1758
1759   if (! reload_completed)
1760     return 0;
1761
1762   for (regno = reglimit - 1; regno >= 0; regno--)
1763     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1764         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1765       nregs++;
1766
1767   return nregs == 0 || ! frame_pointer_needed;
1768 }
1769
1770 \f
1771 /* This function generates the assembly code for function exit.
1772    FILE is an stdio stream to output the code to.
1773    SIZE is an int: how many units of temporary storage to deallocate. */
1774
1775 void
1776 function_epilogue (file, size)
1777      FILE *file;
1778      int size;
1779 {
1780   register int regno;
1781   register int nregs, limit;
1782   int offset;
1783   rtx xops[3];
1784   int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table
1785                                   || current_function_uses_const_pool);
1786
1787   /* Compute the number of registers to pop */
1788
1789   limit = (frame_pointer_needed
1790            ? FRAME_POINTER_REGNUM
1791            : STACK_POINTER_REGNUM);
1792
1793   nregs = 0;
1794
1795   for (regno = limit - 1; regno >= 0; regno--)
1796     if ((regs_ever_live[regno] && ! call_used_regs[regno])
1797         || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1798       nregs++;
1799
1800   /* sp is often  unreliable so we must go off the frame pointer,
1801    */
1802
1803   /* In reality, we may not care if sp is unreliable, because we can
1804      restore the register relative to the frame pointer.  In theory,
1805      since each move is the same speed as a pop, and we don't need the
1806      leal, this is faster.  For now restore multiple registers the old
1807      way. */
1808
1809   offset = -size - (nregs * UNITS_PER_WORD);
1810
1811   xops[2] = stack_pointer_rtx;
1812
1813   if (nregs > 1 || ! frame_pointer_needed)
1814     {
1815       if (frame_pointer_needed)
1816         {
1817           xops[0] = adj_offsettable_operand (AT_BP (Pmode), offset);
1818           output_asm_insn (AS2 (lea%L2,%0,%2), xops);
1819         }
1820
1821       for (regno = 0; regno < limit; regno++)
1822         if ((regs_ever_live[regno] && ! call_used_regs[regno])
1823             || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1824           {
1825             xops[0] = gen_rtx (REG, SImode, regno);
1826             output_asm_insn ("pop%L0 %0", xops);
1827           }
1828     }
1829   else
1830     for (regno = 0; regno < limit; regno++)
1831       if ((regs_ever_live[regno] && ! call_used_regs[regno])
1832           || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
1833         {
1834           xops[0] = gen_rtx (REG, SImode, regno);
1835           xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset);
1836           output_asm_insn (AS2 (mov%L0,%1,%0), xops);
1837           offset += 4;
1838         }
1839
1840   if (frame_pointer_needed)
1841     {
1842       /* If not an i386, mov & pop is faster than "leave". */
1843
1844       if (TARGET_USE_LEAVE)
1845         output_asm_insn ("leave", xops);
1846       else
1847         {
1848           xops[0] = frame_pointer_rtx;
1849           output_asm_insn (AS2 (mov%L2,%0,%2), xops);
1850           output_asm_insn ("pop%L0 %0", xops);
1851         }
1852     }
1853   else if (size)
1854     {
1855       /* If there is no frame pointer, we must still release the frame. */
1856
1857       xops[0] = GEN_INT (size);
1858       output_asm_insn (AS2 (add%L2,%0,%2), xops);
1859     }
1860
1861 #ifdef FUNCTION_BLOCK_PROFILER_EXIT
1862   if (profile_block_flag == 2)
1863     {
1864       FUNCTION_BLOCK_PROFILER_EXIT(file);
1865     }
1866 #endif
1867
1868   if (current_function_pops_args && current_function_args_size)
1869     {
1870       xops[1] = GEN_INT (current_function_pops_args);
1871
1872       /* i386 can only pop 32K bytes (maybe 64K?  Is it signed?).  If
1873          asked to pop more, pop return address, do explicit add, and jump
1874          indirectly to the caller. */
1875
1876       if (current_function_pops_args >= 32768)
1877         {
1878           /* ??? Which register to use here? */
1879           xops[0] = gen_rtx (REG, SImode, 2);
1880           output_asm_insn ("pop%L0 %0", xops);
1881           output_asm_insn (AS2 (add%L2,%1,%2), xops);
1882           output_asm_insn ("jmp %*%0", xops);
1883         }
1884       else
1885           output_asm_insn ("ret %1", xops);
1886     }
1887   else
1888     output_asm_insn ("ret", xops);
1889 }
1890
1891 \f
1892 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
1893    that is a valid memory address for an instruction.
1894    The MODE argument is the machine mode for the MEM expression
1895    that wants to use this address.
1896
1897    On x86, legitimate addresses are:
1898         base                            movl (base),reg
1899         displacement                    movl disp,reg
1900         base + displacement             movl disp(base),reg
1901         index + base                    movl (base,index),reg
1902         (index + base) + displacement   movl disp(base,index),reg
1903         index*scale                     movl (,index,scale),reg
1904         index*scale + disp              movl disp(,index,scale),reg
1905         index*scale + base              movl (base,index,scale),reg
1906         (index*scale + base) + disp     movl disp(base,index,scale),reg
1907
1908         In each case, scale can be 1, 2, 4, 8.  */
1909
1910 /* This is exactly the same as print_operand_addr, except that
1911    it recognizes addresses instead of printing them.
1912
1913    It only recognizes address in canonical form.  LEGITIMIZE_ADDRESS should
1914    convert common non-canonical forms to canonical form so that they will
1915    be recognized.  */
1916
1917 #define ADDR_INVALID(msg,insn)                                          \
1918 do {                                                                    \
1919   if (TARGET_DEBUG_ADDR)                                                \
1920     {                                                                   \
1921       fprintf (stderr, msg);                                            \
1922       debug_rtx (insn);                                                 \
1923     }                                                                   \
1924 } while (0)
1925
1926 int
1927 legitimate_address_p (mode, addr, strict)
1928      enum machine_mode mode;
1929      register rtx addr;
1930      int strict;
1931 {
1932   rtx base  = NULL_RTX;
1933   rtx indx  = NULL_RTX;
1934   rtx scale = NULL_RTX;
1935   rtx disp  = NULL_RTX;
1936
1937   if (TARGET_DEBUG_ADDR)
1938     {
1939       fprintf (stderr,
1940                "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
1941                GET_MODE_NAME (mode), strict);
1942
1943       debug_rtx (addr);
1944     }
1945
1946   if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG)
1947       base = addr;                              /* base reg */
1948
1949   else if (GET_CODE (addr) == PLUS)
1950     {
1951       rtx op0 = XEXP (addr, 0);
1952       rtx op1 = XEXP (addr, 1);
1953       enum rtx_code code0 = GET_CODE (op0);
1954       enum rtx_code code1 = GET_CODE (op1);
1955
1956       if (code0 == REG || code0 == SUBREG)
1957         {
1958           if (code1 == REG || code1 == SUBREG)
1959             {
1960               indx = op0;                       /* index + base */
1961               base = op1;
1962             }
1963
1964           else
1965             {
1966               base = op0;                       /* base + displacement */
1967               disp = op1;
1968             }
1969         }
1970
1971       else if (code0 == MULT)
1972         {
1973           indx  = XEXP (op0, 0);
1974           scale = XEXP (op0, 1);
1975
1976           if (code1 == REG || code1 == SUBREG)
1977             base = op1;                         /* index*scale + base */
1978
1979           else
1980             disp = op1;                         /* index*scale + disp */
1981         }
1982
1983       else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT)
1984         {
1985           indx  = XEXP (XEXP (op0, 0), 0);      /* index*scale + base + disp */
1986           scale = XEXP (XEXP (op0, 0), 1);
1987           base  = XEXP (op0, 1);
1988           disp  = op1;
1989         }
1990
1991       else if (code0 == PLUS)
1992         {
1993           indx = XEXP (op0, 0);                 /* index + base + disp */
1994           base = XEXP (op0, 1);
1995           disp = op1;
1996         }
1997
1998       else
1999         {
2000           ADDR_INVALID ("PLUS subcode is not valid.\n", op0);
2001           return FALSE;
2002         }
2003     }
2004
2005   else if (GET_CODE (addr) == MULT)
2006     {
2007       indx  = XEXP (addr, 0);                   /* index*scale */
2008       scale = XEXP (addr, 1);
2009     }
2010
2011   else
2012     disp = addr;                                /* displacement */
2013
2014   /* Allow arg pointer and stack pointer as index if there is not scaling */
2015   if (base && indx && !scale
2016       && (indx == arg_pointer_rtx || indx == stack_pointer_rtx))
2017     {
2018       rtx tmp = base;
2019       base = indx;
2020       indx = tmp;
2021     }
2022
2023   /* Validate base register */
2024   /* Don't allow SUBREG's here, it can lead to spill failures when the base
2025      is one word out of a two word structure, which is represented internally
2026      as a DImode int.  */
2027   if (base)
2028     {
2029       if (GET_CODE (base) != REG)
2030         {
2031           ADDR_INVALID ("Base is not a register.\n", base);
2032           return FALSE;
2033         }
2034
2035       if ((strict && !REG_OK_FOR_BASE_STRICT_P (base))
2036           || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base)))
2037         {
2038           ADDR_INVALID ("Base is not valid.\n", base);
2039           return FALSE;
2040         }
2041     }
2042
2043   /* Validate index register */
2044   /* Don't allow SUBREG's here, it can lead to spill failures when the index
2045      is one word out of a two word structure, which is represented internally
2046      as a DImode int.  */
2047   if (indx)
2048     {
2049       if (GET_CODE (indx) != REG)
2050         {
2051           ADDR_INVALID ("Index is not a register.\n", indx);
2052           return FALSE;
2053         }
2054
2055       if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx))
2056           || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx)))
2057         {
2058           ADDR_INVALID ("Index is not valid.\n", indx);
2059           return FALSE;
2060         }
2061     }
2062   else if (scale)
2063     abort ();                                   /* scale w/o index invalid */
2064
2065   /* Validate scale factor */
2066   if (scale)
2067     {
2068       HOST_WIDE_INT value;
2069
2070       if (GET_CODE (scale) != CONST_INT)
2071         {
2072           ADDR_INVALID ("Scale is not valid.\n", scale);
2073           return FALSE;
2074         }
2075
2076       value = INTVAL (scale);
2077       if (value != 1 && value != 2 && value != 4 && value != 8)
2078         {
2079           ADDR_INVALID ("Scale is not a good multiplier.\n", scale);
2080           return FALSE;
2081         }
2082     }
2083
2084   /* Validate displacement
2085      Constant pool addresses must be handled special.  They are
2086      considered legitimate addresses, but only if not used with regs.
2087      When printed, the output routines know to print the reference with the
2088      PIC reg, even though the PIC reg doesn't appear in the RTL. */
2089   if (disp)
2090     {
2091       if (GET_CODE (disp) == SYMBOL_REF
2092           && CONSTANT_POOL_ADDRESS_P (disp)
2093           && !base
2094           && !indx)
2095         ;
2096
2097       else if (!CONSTANT_ADDRESS_P (disp))
2098         {
2099           ADDR_INVALID ("Displacement is not valid.\n", disp);
2100           return FALSE;
2101         }
2102
2103       else if (GET_CODE (disp) == CONST_DOUBLE)
2104         {
2105           ADDR_INVALID ("Displacement is a const_double.\n", disp);
2106           return FALSE;
2107         }
2108
2109       else if (flag_pic && SYMBOLIC_CONST (disp)
2110                && base != pic_offset_table_rtx
2111                && (indx != pic_offset_table_rtx || scale != NULL_RTX))
2112         {
2113           ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp);
2114           return FALSE;
2115         }
2116
2117       else if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp)
2118                && (base != NULL_RTX || indx != NULL_RTX))
2119         {
2120           ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp);
2121           return FALSE;
2122         }
2123     }
2124
2125   if (TARGET_DEBUG_ADDR)
2126     fprintf (stderr, "Address is valid.\n");
2127
2128   /* Everything looks valid, return true */
2129   return TRUE;
2130 }
2131
2132 \f
2133 /* Return a legitimate reference for ORIG (an address) using the
2134    register REG.  If REG is 0, a new pseudo is generated.
2135
2136    There are three types of references that must be handled:
2137
2138    1. Global data references must load the address from the GOT, via
2139       the PIC reg.  An insn is emitted to do this load, and the reg is
2140       returned.
2141
2142    2. Static data references must compute the address as an offset
2143       from the GOT, whose base is in the PIC reg.  An insn is emitted to
2144       compute the address into a reg, and the reg is returned.  Static
2145       data objects have SYMBOL_REF_FLAG set to differentiate them from
2146       global data objects.
2147
2148    3. Constant pool addresses must be handled special.  They are
2149       considered legitimate addresses, but only if not used with regs.
2150       When printed, the output routines know to print the reference with the
2151       PIC reg, even though the PIC reg doesn't appear in the RTL.
2152
2153    GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
2154    reg also appears in the address (except for constant pool references,
2155    noted above).
2156
2157    "switch" statements also require special handling when generating
2158    PIC code.  See comments by the `casesi' insn in i386.md for details.  */
2159
2160 rtx
2161 legitimize_pic_address (orig, reg)
2162      rtx orig;
2163      rtx reg;
2164 {
2165   rtx addr = orig;
2166   rtx new = orig;
2167
2168   if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
2169     {
2170       if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
2171         reg = new = orig;
2172       else
2173         {
2174           if (reg == 0)
2175             reg = gen_reg_rtx (Pmode);
2176
2177           if ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr))
2178               || GET_CODE (addr) == LABEL_REF)
2179             new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig);
2180           else
2181             new = gen_rtx (MEM, Pmode,
2182                            gen_rtx (PLUS, Pmode,
2183                                     pic_offset_table_rtx, orig));
2184
2185           emit_move_insn (reg, new);
2186         }
2187       current_function_uses_pic_offset_table = 1;
2188       return reg;
2189     }
2190   else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
2191     {
2192       rtx base;
2193
2194       if (GET_CODE (addr) == CONST)
2195         {
2196           addr = XEXP (addr, 0);
2197           if (GET_CODE (addr) != PLUS)
2198             abort ();
2199         }
2200
2201       if (XEXP (addr, 0) == pic_offset_table_rtx)
2202         return orig;
2203
2204       if (reg == 0)
2205         reg = gen_reg_rtx (Pmode);
2206
2207       base = legitimize_pic_address (XEXP (addr, 0), reg);
2208       addr = legitimize_pic_address (XEXP (addr, 1),
2209                                      base == reg ? NULL_RTX : reg);
2210
2211       if (GET_CODE (addr) == CONST_INT)
2212         return plus_constant (base, INTVAL (addr));
2213
2214       if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
2215         {
2216           base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0));
2217           addr = XEXP (addr, 1);
2218         }
2219         return gen_rtx (PLUS, Pmode, base, addr);
2220     }
2221   return new;
2222 }
2223 \f
2224
2225 /* Emit insns to move operands[1] into operands[0].  */
2226
2227 void
2228 emit_pic_move (operands, mode)
2229      rtx *operands;
2230      enum machine_mode mode;
2231 {
2232   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
2233
2234   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
2235     operands[1] = (rtx) force_reg (SImode, operands[1]);
2236   else
2237     operands[1] = legitimize_pic_address (operands[1], temp);
2238 }
2239
2240 \f
2241 /* Try machine-dependent ways of modifying an illegitimate address
2242    to be legitimate.  If we find one, return the new, valid address.
2243    This macro is used in only one place: `memory_address' in explow.c.
2244
2245    OLDX is the address as it was before break_out_memory_refs was called.
2246    In some cases it is useful to look at this to decide what needs to be done.
2247
2248    MODE and WIN are passed so that this macro can use
2249    GO_IF_LEGITIMATE_ADDRESS.
2250
2251    It is always safe for this macro to do nothing.  It exists to recognize
2252    opportunities to optimize the output.
2253
2254    For the 80386, we handle X+REG by loading X into a register R and
2255    using R+REG.  R will go in a general reg and indexing will be used.
2256    However, if REG is a broken-out memory address or multiplication,
2257    nothing needs to be done because REG can certainly go in a general reg.
2258
2259    When -fpic is used, special handling is needed for symbolic references.
2260    See comments by legitimize_pic_address in i386.c for details.  */
2261
2262 rtx
2263 legitimize_address (x, oldx, mode)
2264      register rtx x;
2265      register rtx oldx;
2266      enum machine_mode mode;
2267 {
2268   int changed = 0;
2269   unsigned log;
2270
2271   if (TARGET_DEBUG_ADDR)
2272     {
2273       fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode));
2274       debug_rtx (x);
2275     }
2276
2277   if (flag_pic && SYMBOLIC_CONST (x))
2278     return legitimize_pic_address (x, 0);
2279
2280   /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
2281   if (GET_CODE (x) == ASHIFT
2282       && GET_CODE (XEXP (x, 1)) == CONST_INT
2283       && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4)
2284     {
2285       changed = 1;
2286       x = gen_rtx (MULT, Pmode,
2287                    force_reg (Pmode, XEXP (x, 0)),
2288                    GEN_INT (1 << log));
2289     }
2290
2291   if (GET_CODE (x) == PLUS)
2292     {
2293       /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
2294       if (GET_CODE (XEXP (x, 0)) == ASHIFT
2295           && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
2296           && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4)
2297         {
2298           changed = 1;
2299           XEXP (x, 0) = gen_rtx (MULT, Pmode,
2300                                  force_reg (Pmode, XEXP (XEXP (x, 0), 0)),
2301                                  GEN_INT (1 << log));
2302         }
2303
2304       if (GET_CODE (XEXP (x, 1)) == ASHIFT
2305           && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
2306           && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1)))) < 4)
2307         {
2308           changed = 1;
2309           XEXP (x, 1) = gen_rtx (MULT, Pmode,
2310                                  force_reg (Pmode, XEXP (XEXP (x, 1), 0)),
2311                                  GEN_INT (1 << log));
2312         }
2313
2314       /* Put multiply first if it isn't already */
2315       if (GET_CODE (XEXP (x, 1)) == MULT)
2316         {
2317           rtx tmp = XEXP (x, 0);
2318           XEXP (x, 0) = XEXP (x, 1);
2319           XEXP (x, 1) = tmp;
2320           changed = 1;
2321         }
2322
2323       /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))
2324          into (plus (plus (mult (reg) (const)) (reg)) (const)).  This can be
2325          created by virtual register instantiation, register elimination, and
2326          similar optimizations.  */
2327       if (GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == PLUS)
2328         {
2329           changed = 1;
2330           x = gen_rtx (PLUS, Pmode,
2331                        gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)),
2332                        XEXP (XEXP (x, 1), 1));
2333         }
2334
2335       /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)
2336          into (plus (plus (mult (reg) (const)) (reg)) (const)).  */
2337       else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
2338                && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
2339                && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS
2340                && CONSTANT_P (XEXP (x, 1)))
2341         {
2342           rtx constant, other;
2343
2344           if (GET_CODE (XEXP (x, 1)) == CONST_INT)
2345             {
2346               constant = XEXP (x, 1);
2347               other = XEXP (XEXP (XEXP (x, 0), 1), 1);
2348             }
2349           else if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 1)) == CONST_INT)
2350             {
2351               constant = XEXP (XEXP (XEXP (x, 0), 1), 1);
2352               other = XEXP (x, 1);
2353             }
2354           else
2355             constant = 0;
2356
2357           if (constant)
2358             {
2359               changed = 1;
2360               x = gen_rtx (PLUS, Pmode,
2361                            gen_rtx (PLUS, Pmode, XEXP (XEXP (x, 0), 0),
2362                                     XEXP (XEXP (XEXP (x, 0), 1), 0)),
2363                            plus_constant (other, INTVAL (constant)));
2364             }
2365         }
2366
2367       if (changed && legitimate_address_p (mode, x, FALSE))
2368         return x;
2369
2370       if (GET_CODE (XEXP (x, 0)) == MULT)
2371         {
2372           changed = 1;
2373           XEXP (x, 0) = force_operand (XEXP (x, 0), 0);
2374         }
2375
2376       if (GET_CODE (XEXP (x, 1)) == MULT)
2377         {
2378           changed = 1;
2379           XEXP (x, 1) = force_operand (XEXP (x, 1), 0);
2380         }
2381
2382       if (changed
2383           && GET_CODE (XEXP (x, 1)) == REG
2384           && GET_CODE (XEXP (x, 0)) == REG)
2385         return x;
2386
2387       if (flag_pic && SYMBOLIC_CONST (XEXP (x, 1)))
2388         {
2389           changed = 1;
2390           x = legitimize_pic_address (x, 0);
2391         }
2392
2393       if (changed && legitimate_address_p (mode, x, FALSE))
2394         return x;
2395
2396       if (GET_CODE (XEXP (x, 0)) == REG)
2397         {
2398           register rtx temp = gen_reg_rtx (Pmode);
2399           register rtx val  = force_operand (XEXP (x, 1), temp);
2400           if (val != temp)
2401             emit_move_insn (temp, val);
2402
2403           XEXP (x, 1) = temp;
2404           return x;
2405         }
2406
2407       else if (GET_CODE (XEXP (x, 1)) == REG)
2408         {
2409           register rtx temp = gen_reg_rtx (Pmode);
2410           register rtx val  = force_operand (XEXP (x, 0), temp);
2411           if (val != temp)
2412             emit_move_insn (temp, val);
2413
2414           XEXP (x, 0) = temp;
2415           return x;
2416         }
2417     }
2418
2419   return x;
2420 }
2421
2422 \f
2423 /* Print an integer constant expression in assembler syntax.  Addition
2424    and subtraction are the only arithmetic that may appear in these
2425    expressions.  FILE is the stdio stream to write to, X is the rtx, and
2426    CODE is the operand print code from the output string.  */
2427
2428 static void
2429 output_pic_addr_const (file, x, code)
2430      FILE *file;
2431      rtx x;
2432      int code;
2433 {
2434   char buf[256];
2435
2436   switch (GET_CODE (x))
2437     {
2438     case PC:
2439       if (flag_pic)
2440         putc ('.', file);
2441       else
2442         abort ();
2443       break;
2444
2445     case SYMBOL_REF:
2446     case LABEL_REF:
2447       if (GET_CODE (x) == SYMBOL_REF)
2448         assemble_name (file, XSTR (x, 0));
2449       else
2450         {
2451           ASM_GENERATE_INTERNAL_LABEL (buf, "L",
2452                                        CODE_LABEL_NUMBER (XEXP (x, 0)));
2453           assemble_name (asm_out_file, buf);
2454         }
2455
2456       if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
2457         fprintf (file, "@GOTOFF(%%ebx)");
2458       else if (code == 'P')
2459         fprintf (file, "@PLT");
2460       else if (GET_CODE (x) == LABEL_REF)
2461         fprintf (file, "@GOTOFF");
2462       else if (! SYMBOL_REF_FLAG (x))
2463         fprintf (file, "@GOT");
2464       else
2465         fprintf (file, "@GOTOFF");
2466
2467       break;
2468
2469     case CODE_LABEL:
2470       ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
2471       assemble_name (asm_out_file, buf);
2472       break;
2473
2474     case CONST_INT:
2475       fprintf (file, "%d", INTVAL (x));
2476       break;
2477
2478     case CONST:
2479       /* This used to output parentheses around the expression,
2480          but that does not work on the 386 (either ATT or BSD assembler).  */
2481       output_pic_addr_const (file, XEXP (x, 0), code);
2482       break;
2483
2484     case CONST_DOUBLE:
2485       if (GET_MODE (x) == VOIDmode)
2486         {
2487           /* We can use %d if the number is <32 bits and positive.  */
2488           if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0)
2489             fprintf (file, "0x%x%08x",
2490                      CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
2491           else
2492             fprintf (file, "%d", CONST_DOUBLE_LOW (x));
2493         }
2494       else
2495         /* We can't handle floating point constants;
2496            PRINT_OPERAND must handle them.  */
2497         output_operand_lossage ("floating constant misused");
2498       break;
2499
2500     case PLUS:
2501       /* Some assemblers need integer constants to appear last (eg masm).  */
2502       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
2503         {
2504           output_pic_addr_const (file, XEXP (x, 1), code);
2505           if (INTVAL (XEXP (x, 0)) >= 0)
2506             fprintf (file, "+");
2507           output_pic_addr_const (file, XEXP (x, 0), code);
2508         }
2509       else
2510         {
2511           output_pic_addr_const (file, XEXP (x, 0), code);
2512           if (INTVAL (XEXP (x, 1)) >= 0)
2513             fprintf (file, "+");
2514           output_pic_addr_const (file, XEXP (x, 1), code);
2515         }
2516       break;
2517
2518     case MINUS:
2519       output_pic_addr_const (file, XEXP (x, 0), code);
2520       fprintf (file, "-");
2521       output_pic_addr_const (file, XEXP (x, 1), code);
2522       break;
2523
2524     default:
2525       output_operand_lossage ("invalid expression as operand");
2526     }
2527 }
2528 \f
2529 /* Meaning of CODE:
2530    f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
2531    D,L,W,B,Q,S -- print the opcode suffix for specified size of operand.
2532    R -- print the prefix for register names.
2533    z -- print the opcode suffix for the size of the current operand.
2534    * -- print a star (in certain assembler syntax)
2535    w -- print the operand as if it's a "word" (HImode) even if it isn't.
2536    c -- don't print special prefixes before constant operands.
2537    J -- print the appropriate jump operand.
2538 */
2539
2540 void
2541 print_operand (file, x, code)
2542      FILE *file;
2543      rtx x;
2544      int code;
2545 {
2546   if (code)
2547     {
2548       switch (code)
2549         {
2550         case '*':
2551           if (USE_STAR)
2552             putc ('*', file);
2553           return;
2554
2555         case 'L':
2556           PUT_OP_SIZE (code, 'l', file);
2557           return;
2558
2559         case 'W':
2560           PUT_OP_SIZE (code, 'w', file);
2561           return;
2562
2563         case 'B':
2564           PUT_OP_SIZE (code, 'b', file);
2565           return;
2566
2567         case 'Q':
2568           PUT_OP_SIZE (code, 'l', file);
2569           return;
2570
2571         case 'S':
2572           PUT_OP_SIZE (code, 's', file);
2573           return;
2574
2575         case 'T':
2576           PUT_OP_SIZE (code, 't', file);
2577           return;
2578
2579         case 'z':
2580           /* 387 opcodes don't get size suffixes if the operands are
2581              registers. */
2582
2583           if (STACK_REG_P (x))
2584             return;
2585
2586           /* this is the size of op from size of operand */
2587           switch (GET_MODE_SIZE (GET_MODE (x)))
2588             {
2589             case 1:
2590               PUT_OP_SIZE ('B', 'b', file);
2591               return;
2592
2593             case 2:
2594               PUT_OP_SIZE ('W', 'w', file);
2595               return;
2596
2597             case 4:
2598               if (GET_MODE (x) == SFmode)
2599                 {
2600                   PUT_OP_SIZE ('S', 's', file);
2601                   return;
2602                 }
2603               else
2604                 PUT_OP_SIZE ('L', 'l', file);
2605               return;
2606
2607             case 12:
2608                   PUT_OP_SIZE ('T', 't', file);
2609                   return;
2610
2611             case 8:
2612               if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
2613                 {
2614 #ifdef GAS_MNEMONICS
2615                   PUT_OP_SIZE ('Q', 'q', file);
2616                   return;
2617 #else
2618                   PUT_OP_SIZE ('Q', 'l', file); /* Fall through */
2619 #endif
2620                 }
2621
2622               PUT_OP_SIZE ('Q', 'l', file);
2623               return;
2624             }
2625
2626         case 'b':
2627         case 'w':
2628         case 'k':
2629         case 'h':
2630         case 'y':
2631         case 'P':
2632           break;
2633
2634         case 'J':
2635           switch (GET_CODE (x))
2636             {
2637               /* These conditions are appropriate for testing the result
2638                  of an arithmetic operation, not for a compare operation.
2639                  Cases GE, LT assume CC_NO_OVERFLOW true. All cases assume
2640                  CC_Z_IN_NOT_C false and not floating point.  */
2641             case NE:  fputs ("jne", file); return;
2642             case EQ:  fputs ("je",  file); return;
2643             case GE:  fputs ("jns", file); return;
2644             case LT:  fputs ("js",  file); return;
2645             case GEU: fputs ("jmp", file); return;
2646             case GTU: fputs ("jne",  file); return;
2647             case LEU: fputs ("je", file); return;
2648             case LTU: fputs ("#branch never",  file); return;
2649
2650             /* no matching branches for GT nor LE */
2651             }
2652           abort ();
2653
2654         default:
2655           {
2656             char str[50];
2657
2658             sprintf (str, "invalid operand code `%c'", code);
2659             output_operand_lossage (str);
2660           }
2661         }
2662     }
2663   if (GET_CODE (x) == REG)
2664     {
2665       PRINT_REG (x, code, file);
2666     }
2667   else if (GET_CODE (x) == MEM)
2668     {
2669       PRINT_PTR (x, file);
2670       if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
2671         {
2672           if (flag_pic)
2673             output_pic_addr_const (file, XEXP (x, 0), code);
2674           else
2675             output_addr_const (file, XEXP (x, 0));
2676         }
2677       else
2678         output_address (XEXP (x, 0));
2679     }
2680   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
2681     {
2682       REAL_VALUE_TYPE r; long l;
2683       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2684       REAL_VALUE_TO_TARGET_SINGLE (r, l);
2685       PRINT_IMMED_PREFIX (file);
2686       fprintf (file, "0x%x", l);
2687     }
2688  /* These float cases don't actually occur as immediate operands. */
2689  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
2690     {
2691       REAL_VALUE_TYPE r; char dstr[30];
2692       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2693       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
2694       fprintf (file, "%s", dstr);
2695     }
2696   else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode)
2697     {
2698       REAL_VALUE_TYPE r; char dstr[30];
2699       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
2700       REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr);
2701       fprintf (file, "%s", dstr);
2702     }
2703   else 
2704     {
2705       if (code != 'P')
2706         {
2707           if (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
2708             PRINT_IMMED_PREFIX (file);
2709           else if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF
2710                    || GET_CODE (x) == LABEL_REF)
2711             PRINT_OFFSET_PREFIX (file);
2712         }
2713       if (flag_pic)
2714         output_pic_addr_const (file, x, code);
2715       else
2716         output_addr_const (file, x);
2717     }
2718 }
2719 \f
2720 /* Print a memory operand whose address is ADDR.  */
2721
2722 void
2723 print_operand_address (file, addr)
2724      FILE *file;
2725      register rtx addr;
2726 {
2727   register rtx reg1, reg2, breg, ireg;
2728   rtx offset;
2729
2730   switch (GET_CODE (addr))
2731     {
2732     case REG:
2733       ADDR_BEG (file);
2734       fprintf (file, "%se", RP);
2735       fputs (hi_reg_name[REGNO (addr)], file);
2736       ADDR_END (file);
2737       break;
2738
2739     case PLUS:
2740       reg1 = 0;
2741       reg2 = 0;
2742       ireg = 0;
2743       breg = 0;
2744       offset = 0;
2745       if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
2746         {
2747           offset = XEXP (addr, 0);
2748           addr = XEXP (addr, 1);
2749         }
2750       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
2751         {
2752           offset = XEXP (addr, 1);
2753           addr = XEXP (addr, 0);
2754         }
2755       if (GET_CODE (addr) != PLUS) ;
2756       else if (GET_CODE (XEXP (addr, 0)) == MULT)
2757         {
2758           reg1 = XEXP (addr, 0);
2759           addr = XEXP (addr, 1);
2760         }
2761       else if (GET_CODE (XEXP (addr, 1)) == MULT)
2762         {
2763           reg1 = XEXP (addr, 1);
2764           addr = XEXP (addr, 0);
2765         }
2766       else if (GET_CODE (XEXP (addr, 0)) == REG)
2767         {
2768           reg1 = XEXP (addr, 0);
2769           addr = XEXP (addr, 1);
2770         }
2771       else if (GET_CODE (XEXP (addr, 1)) == REG)
2772         {
2773           reg1 = XEXP (addr, 1);
2774           addr = XEXP (addr, 0);
2775         }
2776       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
2777         {
2778           if (reg1 == 0) reg1 = addr;
2779           else reg2 = addr;
2780           addr = 0;
2781         }
2782       if (offset != 0)
2783         {
2784           if (addr != 0) abort ();
2785           addr = offset;
2786         }
2787       if ((reg1 && GET_CODE (reg1) == MULT)
2788           || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
2789         {
2790           breg = reg2;
2791           ireg = reg1;
2792         }
2793       else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
2794         {
2795           breg = reg1;
2796           ireg = reg2;
2797         }
2798
2799       if (ireg != 0 || breg != 0)
2800         {
2801           int scale = 1;
2802
2803           if (addr != 0)
2804             {
2805               if (flag_pic)
2806                 output_pic_addr_const (file, addr, 0);
2807
2808               else if (GET_CODE (addr) == LABEL_REF)
2809                 output_asm_label (addr);
2810
2811               else
2812                 output_addr_const (file, addr);
2813             }
2814
2815           if (ireg != 0 && GET_CODE (ireg) == MULT)
2816             {
2817               scale = INTVAL (XEXP (ireg, 1));
2818               ireg = XEXP (ireg, 0);
2819             }
2820
2821           /* The stack pointer can only appear as a base register,
2822              never an index register, so exchange the regs if it is wrong. */
2823
2824           if (scale == 1 && ireg && REGNO (ireg) == STACK_POINTER_REGNUM)
2825             {
2826               rtx tmp;
2827
2828               tmp = breg;
2829               breg = ireg;
2830               ireg = tmp;
2831             }
2832
2833           /* output breg+ireg*scale */
2834           PRINT_B_I_S (breg, ireg, scale, file);
2835           break;
2836         }
2837
2838     case MULT:
2839       {
2840         int scale;
2841         if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
2842           {
2843             scale = INTVAL (XEXP (addr, 0));
2844             ireg = XEXP (addr, 1);
2845           }
2846         else
2847           {
2848             scale = INTVAL (XEXP (addr, 1));
2849             ireg = XEXP (addr, 0);
2850           }
2851         output_addr_const (file, const0_rtx);
2852         PRINT_B_I_S ((rtx) 0, ireg, scale, file);
2853       }
2854       break;
2855
2856     default:
2857       if (GET_CODE (addr) == CONST_INT
2858           && INTVAL (addr) < 0x8000
2859           && INTVAL (addr) >= -0x8000)
2860         fprintf (file, "%d", INTVAL (addr));
2861       else
2862         {
2863           if (flag_pic)
2864             output_pic_addr_const (file, addr, 0);
2865           else
2866             output_addr_const (file, addr);
2867         }
2868     }
2869 }
2870 \f
2871 /* Set the cc_status for the results of an insn whose pattern is EXP.
2872    On the 80386, we assume that only test and compare insns, as well
2873    as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT,
2874    ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
2875    Also, we assume that jumps, moves and sCOND don't affect the condition
2876    codes.  All else clobbers the condition codes, by assumption.
2877
2878    We assume that ALL integer add, minus, etc. instructions effect the
2879    condition codes.  This MUST be consistent with i386.md.
2880
2881    We don't record any float test or compare - the redundant test &
2882    compare check in final.c does not handle stack-like regs correctly. */
2883
2884 void
2885 notice_update_cc (exp)
2886      rtx exp;
2887 {
2888   if (GET_CODE (exp) == SET)
2889     {
2890       /* Jumps do not alter the cc's.  */
2891       if (SET_DEST (exp) == pc_rtx)
2892         return;
2893 #ifdef IS_STACK_MODE
2894       /* Moving into a memory of stack_mode may have been moved
2895          in between the use and set of cc0 by loop_spl(). So
2896          old value of cc.status must be retained */
2897       if(GET_CODE(SET_DEST(exp))==MEM 
2898          && IS_STACK_MODE(GET_MODE(SET_DEST(exp))))
2899         {
2900           return;
2901         }
2902 #endif
2903       /* Moving register or memory into a register:
2904          it doesn't alter the cc's, but it might invalidate
2905          the RTX's which we remember the cc's came from.
2906          (Note that moving a constant 0 or 1 MAY set the cc's).  */
2907       if (REG_P (SET_DEST (exp))
2908           && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM
2909               || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
2910         {
2911           if (cc_status.value1
2912               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
2913             cc_status.value1 = 0;
2914           if (cc_status.value2
2915               && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
2916             cc_status.value2 = 0;
2917           return;
2918         }
2919       /* Moving register into memory doesn't alter the cc's.
2920          It may invalidate the RTX's which we remember the cc's came from.  */
2921       if (GET_CODE (SET_DEST (exp)) == MEM
2922           && (REG_P (SET_SRC (exp))
2923               || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<'))
2924         {
2925           if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
2926             cc_status.value1 = 0;
2927           if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
2928             cc_status.value2 = 0;
2929           return;
2930         }
2931       /* Function calls clobber the cc's.  */
2932       else if (GET_CODE (SET_SRC (exp)) == CALL)
2933         {
2934           CC_STATUS_INIT;
2935           return;
2936         }
2937       /* Tests and compares set the cc's in predictable ways.  */
2938       else if (SET_DEST (exp) == cc0_rtx)
2939         {
2940           CC_STATUS_INIT;
2941           cc_status.value1 = SET_SRC (exp);
2942           return;
2943         }
2944       /* Certain instructions effect the condition codes. */
2945       else if (GET_MODE (SET_SRC (exp)) == SImode
2946                || GET_MODE (SET_SRC (exp)) == HImode
2947                || GET_MODE (SET_SRC (exp)) == QImode)
2948         switch (GET_CODE (SET_SRC (exp)))
2949           {
2950           case ASHIFTRT: case LSHIFTRT:
2951           case ASHIFT:
2952             /* Shifts on the 386 don't set the condition codes if the
2953                shift count is zero. */
2954             if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT)
2955               {
2956                 CC_STATUS_INIT;
2957                 break;
2958               }
2959             /* We assume that the CONST_INT is non-zero (this rtx would
2960                have been deleted if it were zero. */
2961
2962           case PLUS: case MINUS: case NEG:
2963           case AND: case IOR: case XOR:
2964             cc_status.flags = CC_NO_OVERFLOW;
2965             cc_status.value1 = SET_SRC (exp);
2966             cc_status.value2 = SET_DEST (exp);
2967             break;
2968
2969           default:
2970             CC_STATUS_INIT;
2971           }
2972       else
2973         {
2974           CC_STATUS_INIT;
2975         }
2976     }
2977   else if (GET_CODE (exp) == PARALLEL
2978            && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
2979     {
2980       if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
2981         return;
2982       if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
2983         {
2984           CC_STATUS_INIT;
2985           if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0))))
2986             cc_status.flags |= CC_IN_80387;
2987           else
2988             cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
2989           return;
2990         }
2991       CC_STATUS_INIT;
2992     }
2993   else
2994     {
2995       CC_STATUS_INIT;
2996     }
2997 }
2998 \f
2999 /* Split one or more DImode RTL references into pairs of SImode
3000    references.  The RTL can be REG, offsettable MEM, integer constant, or
3001    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
3002    split and "num" is its length.  lo_half and hi_half are output arrays
3003    that parallel "operands". */
3004
3005 void
3006 split_di (operands, num, lo_half, hi_half)
3007      rtx operands[];
3008      int num;
3009      rtx lo_half[], hi_half[];
3010 {
3011   while (num--)
3012     {
3013       if (GET_CODE (operands[num]) == REG)
3014         {
3015           lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]));
3016           hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
3017         }
3018       else if (CONSTANT_P (operands[num]))
3019         {
3020           split_double (operands[num], &lo_half[num], &hi_half[num]);
3021         }
3022       else if (offsettable_memref_p (operands[num]))
3023         {
3024           lo_half[num] = operands[num];
3025           hi_half[num] = adj_offsettable_operand (operands[num], 4);
3026         }
3027       else
3028         abort();
3029     }
3030 }
3031 \f
3032 /* Return 1 if this is a valid binary operation on a 387.
3033    OP is the expression matched, and MODE is its mode. */
3034
3035 int
3036 binary_387_op (op, mode)
3037     register rtx op;
3038     enum machine_mode mode;
3039 {
3040   if (mode != VOIDmode && mode != GET_MODE (op))
3041     return 0;
3042
3043   switch (GET_CODE (op))
3044     {
3045     case PLUS:
3046     case MINUS:
3047     case MULT:
3048     case DIV:
3049       return GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT;
3050
3051     default:
3052       return 0;
3053     }
3054 }
3055
3056 \f
3057 /* Return 1 if this is a valid shift or rotate operation on a 386.
3058    OP is the expression matched, and MODE is its mode. */
3059
3060 int
3061 shift_op (op, mode)
3062     register rtx op;
3063     enum machine_mode mode;
3064 {
3065   rtx operand = XEXP (op, 0);
3066
3067   if (mode != VOIDmode && mode != GET_MODE (op))
3068     return 0;
3069
3070   if (GET_MODE (operand) != GET_MODE (op)
3071       || GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
3072     return 0;
3073
3074   return (GET_CODE (op) == ASHIFT
3075           || GET_CODE (op) == ASHIFTRT
3076           || GET_CODE (op) == LSHIFTRT
3077           || GET_CODE (op) == ROTATE
3078           || GET_CODE (op) == ROTATERT);
3079 }
3080
3081 /* Return 1 if OP is COMPARE rtx with mode VOIDmode.
3082    MODE is not used.  */
3083
3084 int
3085 VOIDmode_compare_op (op, mode)
3086     register rtx op;
3087     enum machine_mode mode;
3088 {
3089   return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode;
3090 }
3091 \f
3092 /* Output code to perform a 387 binary operation in INSN, one of PLUS,
3093    MINUS, MULT or DIV.  OPERANDS are the insn operands, where operands[3]
3094    is the expression of the binary operation.  The output may either be
3095    emitted here, or returned to the caller, like all output_* functions.
3096
3097    There is no guarantee that the operands are the same mode, as they
3098    might be within FLOAT or FLOAT_EXTEND expressions. */
3099
3100 char *
3101 output_387_binary_op (insn, operands)
3102      rtx insn;
3103      rtx *operands;
3104 {
3105   rtx temp;
3106   char *base_op;
3107   static char buf[100];
3108
3109   switch (GET_CODE (operands[3]))
3110     {
3111     case PLUS:
3112       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3113           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3114         base_op = "fiadd";
3115       else
3116         base_op = "fadd";
3117       break;
3118
3119     case MINUS:
3120       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3121           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3122         base_op = "fisub";
3123       else
3124         base_op = "fsub";
3125       break;
3126
3127     case MULT:
3128       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3129           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3130         base_op = "fimul";
3131       else
3132         base_op = "fmul";
3133       break;
3134
3135     case DIV:
3136       if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
3137           || GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT)
3138         base_op = "fidiv";
3139       else
3140         base_op = "fdiv";
3141       break;
3142
3143     default:
3144       abort ();
3145     }
3146
3147   strcpy (buf, base_op);
3148
3149   switch (GET_CODE (operands[3]))
3150     {
3151     case MULT:
3152     case PLUS:
3153       if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
3154         {
3155           temp = operands[2];
3156           operands[2] = operands[1];
3157           operands[1] = temp;
3158         }
3159
3160       if (GET_CODE (operands[2]) == MEM)
3161         return strcat (buf, AS1 (%z2,%2));
3162
3163       if (NON_STACK_REG_P (operands[1]))
3164         {
3165           output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
3166           RET;
3167         }
3168       else if (NON_STACK_REG_P (operands[2]))
3169         {
3170           output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
3171           RET;
3172         }
3173
3174       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
3175         return strcat (buf, AS2 (p,%2,%0));
3176
3177       if (STACK_TOP_P (operands[0]))
3178         return strcat (buf, AS2C (%y2,%0));
3179       else
3180         return strcat (buf, AS2C (%2,%0));
3181
3182     case MINUS:
3183     case DIV:
3184       if (GET_CODE (operands[1]) == MEM)
3185         return strcat (buf, AS1 (r%z1,%1));
3186
3187       if (GET_CODE (operands[2]) == MEM)
3188         return strcat (buf, AS1 (%z2,%2));
3189
3190       if (NON_STACK_REG_P (operands[1]))
3191         {
3192           output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1)));
3193           RET;
3194         }
3195       else if (NON_STACK_REG_P (operands[2]))
3196         {
3197           output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1)));
3198           RET;
3199         }
3200
3201       if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2]))
3202         abort ();
3203
3204       if (find_regno_note (insn, REG_DEAD, REGNO (operands[2])))
3205         return strcat (buf, AS2 (rp,%2,%0));
3206
3207       if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
3208         return strcat (buf, AS2 (p,%1,%0));
3209
3210       if (STACK_TOP_P (operands[0]))
3211         {
3212           if (STACK_TOP_P (operands[1]))
3213             return strcat (buf, AS2C (%y2,%0));
3214           else
3215             return strcat (buf, AS2 (r,%y1,%0));
3216         }
3217       else if (STACK_TOP_P (operands[1]))
3218         return strcat (buf, AS2C (%1,%0));
3219       else
3220         return strcat (buf, AS2 (r,%2,%0));
3221
3222     default:
3223       abort ();
3224     }
3225 }
3226 \f
3227 /* Output code for INSN to convert a float to a signed int.  OPERANDS
3228    are the insn operands.  The output may be SFmode or DFmode and the
3229    input operand may be SImode or DImode.  As a special case, make sure
3230    that the 387 stack top dies if the output mode is DImode, because the
3231    hardware requires this.  */
3232
3233 char *
3234 output_fix_trunc (insn, operands)
3235      rtx insn;
3236      rtx *operands;
3237 {
3238   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
3239   rtx xops[2];
3240
3241   if (! STACK_TOP_P (operands[1]) ||
3242       (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
3243     abort ();
3244
3245   xops[0] = GEN_INT (12);
3246   xops[1] = operands[4];
3247
3248   output_asm_insn (AS1 (fnstc%W2,%2), operands);
3249   output_asm_insn (AS2 (mov%L2,%2,%4), operands);
3250   output_asm_insn (AS2 (mov%B1,%0,%h1), xops);
3251   output_asm_insn (AS2 (mov%L4,%4,%3), operands);
3252   output_asm_insn (AS1 (fldc%W3,%3), operands);
3253
3254   if (NON_STACK_REG_P (operands[0]))
3255     output_to_reg (operands[0], stack_top_dies);
3256   else if (GET_CODE (operands[0]) == MEM)
3257     {
3258       if (stack_top_dies)
3259         output_asm_insn (AS1 (fistp%z0,%0), operands);
3260       else
3261         output_asm_insn (AS1 (fist%z0,%0), operands);
3262     }
3263   else
3264     abort ();
3265
3266   return AS1 (fldc%W2,%2);
3267 }
3268 \f
3269 /* Output code for INSN to compare OPERANDS.  The two operands might
3270    not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
3271    expression.  If the compare is in mode CCFPEQmode, use an opcode that
3272    will not fault if a qNaN is present. */
3273
3274 char *
3275 output_float_compare (insn, operands)
3276      rtx insn;
3277      rtx *operands;
3278 {
3279   int stack_top_dies;
3280   rtx body = XVECEXP (PATTERN (insn), 0, 0);
3281   int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode;
3282
3283   rtx tmp;
3284   if (! STACK_TOP_P (operands[0]))
3285     {
3286       tmp = operands[0];
3287       operands[0] = operands[1];
3288       operands[1] = tmp;
3289       cc_status.flags |= CC_REVERSED;
3290     }
3291     
3292   if (! STACK_TOP_P (operands[0]))
3293     abort ();
3294
3295   stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
3296
3297   if (STACK_REG_P (operands[1])
3298       && stack_top_dies
3299       && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
3300       && REGNO (operands[1]) != FIRST_STACK_REG)
3301     {
3302       /* If both the top of the 387 stack dies, and the other operand
3303          is also a stack register that dies, then this must be a
3304          `fcompp' float compare */
3305
3306       if (unordered_compare)
3307         output_asm_insn ("fucompp", operands);
3308       else
3309         output_asm_insn ("fcompp", operands);
3310     }
3311   else
3312     {
3313       static char buf[100];
3314
3315       /* Decide if this is the integer or float compare opcode, or the
3316          unordered float compare. */
3317
3318       if (unordered_compare)
3319         strcpy (buf, "fucom");
3320       else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT)
3321         strcpy (buf, "fcom");
3322       else
3323         strcpy (buf, "ficom");
3324
3325       /* Modify the opcode if the 387 stack is to be popped. */
3326
3327       if (stack_top_dies)
3328         strcat (buf, "p");
3329
3330       if (NON_STACK_REG_P (operands[1]))
3331         output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1)));
3332       else
3333         output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands);
3334     }
3335
3336   /* Now retrieve the condition code. */
3337
3338   return output_fp_cc0_set (insn);
3339 }
3340 \f
3341 /* Output opcodes to transfer the results of FP compare or test INSN
3342    from the FPU to the CPU flags.  If TARGET_IEEE_FP, ensure that if the
3343    result of the compare or test is unordered, no comparison operator
3344    succeeds except NE.  Return an output template, if any.  */
3345
3346 char *
3347 output_fp_cc0_set (insn)
3348      rtx insn;
3349 {
3350   rtx xops[3];
3351   rtx unordered_label;
3352   rtx next;
3353   enum rtx_code code;
3354
3355   xops[0] = gen_rtx (REG, HImode, 0);
3356   output_asm_insn (AS1 (fnsts%W0,%0), xops);
3357
3358   if (! TARGET_IEEE_FP)
3359     {
3360       if (!(cc_status.flags & CC_REVERSED))
3361         {
3362           next = next_cc0_user (insn);
3363         
3364           if (GET_CODE (next) == JUMP_INSN
3365               && GET_CODE (PATTERN (next)) == SET
3366               && SET_DEST (PATTERN (next)) == pc_rtx
3367               && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3368             {
3369               code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3370             }
3371           else if (GET_CODE (PATTERN (next)) == SET)
3372             {
3373               code = GET_CODE (SET_SRC (PATTERN (next)));
3374             }
3375           else
3376             {
3377               return "sahf";
3378             }
3379           if (code == GT || code == LT || code == EQ || code == NE
3380               || code == LE || code == GE)
3381             { /* We will test eax directly */
3382               cc_status.flags |= CC_TEST_AX;
3383               RET;
3384             }
3385         }
3386       return "sahf";
3387     }
3388
3389   next = next_cc0_user (insn);
3390   if (next == NULL_RTX)
3391     abort ();
3392
3393   if (GET_CODE (next) == JUMP_INSN
3394       && GET_CODE (PATTERN (next)) == SET
3395       && SET_DEST (PATTERN (next)) == pc_rtx
3396       && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE)
3397     {
3398       code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0));
3399     }
3400   else if (GET_CODE (PATTERN (next)) == SET)
3401     {
3402       code = GET_CODE (SET_SRC (PATTERN (next)));
3403     }
3404   else
3405     abort ();
3406
3407   xops[0] = gen_rtx (REG, QImode, 0);
3408
3409   switch (code)
3410     {
3411     case GT:
3412       xops[1] = GEN_INT (0x45);
3413       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3414       /* je label */
3415       break;
3416
3417     case LT:
3418       xops[1] = GEN_INT (0x45);
3419       xops[2] = GEN_INT (0x01);
3420       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3421       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3422       /* je label */
3423       break;
3424
3425     case GE:
3426       xops[1] = GEN_INT (0x05);
3427       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3428       /* je label */
3429       break;
3430
3431     case LE:
3432       xops[1] = GEN_INT (0x45);
3433       xops[2] = GEN_INT (0x40);
3434       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3435       output_asm_insn (AS1 (dec%B0,%h0), xops);
3436       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3437       /* jb label */
3438       break;
3439
3440     case EQ:
3441       xops[1] = GEN_INT (0x45);
3442       xops[2] = GEN_INT (0x40);
3443       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3444       output_asm_insn (AS2 (cmp%B0,%2,%h0), xops);
3445       /* je label */
3446       break;
3447
3448     case NE:
3449       xops[1] = GEN_INT (0x44);
3450       xops[2] = GEN_INT (0x40);
3451       output_asm_insn (AS2 (and%B0,%1,%h0), xops);
3452       output_asm_insn (AS2 (xor%B0,%2,%h0), xops);
3453       /* jne label */
3454       break;
3455
3456     case GTU:
3457     case LTU:
3458     case GEU:
3459     case LEU:
3460     default:
3461       abort ();
3462     }
3463   RET;
3464 }
3465 \f
3466 #define MAX_386_STACK_LOCALS 2
3467
3468 static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
3469
3470 /* Define the structure for the machine field in struct function.  */
3471 struct machine_function
3472 {
3473   rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
3474 };
3475
3476 /* Functions to save and restore i386_stack_locals.
3477    These will be called, via pointer variables,
3478    from push_function_context and pop_function_context.  */
3479
3480 void
3481 save_386_machine_status (p)
3482      struct function *p;
3483 {
3484   p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals);
3485   bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals,
3486          sizeof i386_stack_locals);
3487 }
3488
3489 void
3490 restore_386_machine_status (p)
3491      struct function *p;
3492 {
3493   bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals,
3494          sizeof i386_stack_locals);
3495   free (p->machine);
3496 }
3497
3498 /* Clear stack slot assignments remembered from previous functions.
3499    This is called from INIT_EXPANDERS once before RTL is emitted for each
3500    function.  */
3501
3502 void
3503 clear_386_stack_locals ()
3504 {
3505   enum machine_mode mode;
3506   int n;
3507
3508   for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
3509        mode = (enum machine_mode) ((int) mode + 1))
3510     for (n = 0; n < MAX_386_STACK_LOCALS; n++)
3511       i386_stack_locals[(int) mode][n] = NULL_RTX;
3512
3513   /* Arrange to save and restore i386_stack_locals around nested functions.  */
3514   save_machine_status = save_386_machine_status;
3515   restore_machine_status = restore_386_machine_status;
3516 }
3517
3518 /* Return a MEM corresponding to a stack slot with mode MODE.
3519    Allocate a new slot if necessary.
3520
3521    The RTL for a function can have several slots available: N is
3522    which slot to use.  */
3523
3524 rtx
3525 assign_386_stack_local (mode, n)
3526      enum machine_mode mode;
3527      int n;
3528 {
3529   if (n < 0 || n >= MAX_386_STACK_LOCALS)
3530     abort ();
3531
3532   if (i386_stack_locals[(int) mode][n] == NULL_RTX)
3533     i386_stack_locals[(int) mode][n]
3534       = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
3535
3536   return i386_stack_locals[(int) mode][n];
3537 }
3538
3539 \f
3540 int is_mul(op,mode)
3541     register rtx op;
3542     enum machine_mode mode;
3543 {
3544   return (GET_CODE (op) == MULT);
3545 }
3546
3547 int is_div(op,mode)
3548     register rtx op;
3549     enum machine_mode mode;
3550 {
3551   return (GET_CODE (op) == DIV);
3552 }
3553
3554 \f
3555 #ifdef NOTYET
3556 /* Create a new copy of an rtx.
3557    Recursively copies the operands of the rtx,
3558    except for those few rtx codes that are sharable.
3559    Doesn't share CONST  */
3560
3561 rtx
3562 copy_all_rtx (orig)
3563      register rtx orig;
3564 {
3565   register rtx copy;
3566   register int i, j;
3567   register RTX_CODE code;
3568   register char *format_ptr;
3569
3570   code = GET_CODE (orig);
3571
3572   switch (code)
3573     {
3574     case REG:
3575     case QUEUED:
3576     case CONST_INT:
3577     case CONST_DOUBLE:
3578     case SYMBOL_REF:
3579     case CODE_LABEL:
3580     case PC:
3581     case CC0:
3582     case SCRATCH:
3583       /* SCRATCH must be shared because they represent distinct values. */
3584       return orig;
3585
3586 #if 0
3587     case CONST:
3588       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
3589          a LABEL_REF, it isn't sharable.  */
3590       if (GET_CODE (XEXP (orig, 0)) == PLUS
3591           && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF
3592           && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT)
3593         return orig;
3594       break;
3595 #endif
3596       /* A MEM with a constant address is not sharable.  The problem is that
3597          the constant address may need to be reloaded.  If the mem is shared,
3598          then reloading one copy of this mem will cause all copies to appear
3599          to have been reloaded.  */
3600     }
3601
3602   copy = rtx_alloc (code);
3603   PUT_MODE (copy, GET_MODE (orig));
3604   copy->in_struct = orig->in_struct;
3605   copy->volatil = orig->volatil;
3606   copy->unchanging = orig->unchanging;
3607   copy->integrated = orig->integrated;
3608   /* intel1 */
3609   copy->is_spill_rtx = orig->is_spill_rtx;
3610   
3611   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
3612
3613   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
3614     {
3615       switch (*format_ptr++)
3616         {
3617         case 'e':
3618           XEXP (copy, i) = XEXP (orig, i);
3619           if (XEXP (orig, i) != NULL)
3620             XEXP (copy, i) = copy_rtx (XEXP (orig, i));
3621           break;
3622
3623         case '0':
3624         case 'u':
3625           XEXP (copy, i) = XEXP (orig, i);
3626           break;
3627
3628         case 'E':
3629         case 'V':
3630           XVEC (copy, i) = XVEC (orig, i);
3631           if (XVEC (orig, i) != NULL)
3632             {
3633               XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
3634               for (j = 0; j < XVECLEN (copy, i); j++)
3635                 XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
3636             }
3637           break;
3638
3639         case 'w':
3640           XWINT (copy, i) = XWINT (orig, i);
3641           break;
3642
3643         case 'i':
3644           XINT (copy, i) = XINT (orig, i);
3645           break;
3646
3647         case 's':
3648         case 'S':
3649           XSTR (copy, i) = XSTR (orig, i);
3650           break;
3651
3652         default:
3653           abort ();
3654         }
3655     }
3656   return copy;
3657 }
3658
3659 \f
3660 /* try to rewrite a memory address to make it valid */
3661 void 
3662 rewrite_address (mem_rtx)
3663      rtx mem_rtx;
3664 {
3665   rtx index_rtx, base_rtx, offset_rtx, scale_rtx, ret_rtx;
3666   int scale = 1;
3667   int offset_adjust = 0;
3668   int was_only_offset = 0;
3669   rtx mem_addr = XEXP (mem_rtx, 0);
3670   char *storage = (char *) oballoc (0);
3671   int in_struct = 0;
3672   int is_spill_rtx = 0;
3673
3674   in_struct = MEM_IN_STRUCT_P (mem_rtx);
3675   is_spill_rtx = RTX_IS_SPILL_P (mem_rtx);
3676
3677   if (GET_CODE (mem_addr) == PLUS &&
3678       GET_CODE (XEXP (mem_addr, 1)) == PLUS &&
3679       GET_CODE (XEXP (XEXP (mem_addr, 1), 0)) == REG)
3680     {                           /* this part is utilized by the combiner */
3681       ret_rtx =
3682         gen_rtx (PLUS, GET_MODE (mem_addr),
3683                  gen_rtx (PLUS, GET_MODE (XEXP (mem_addr, 1)),
3684                           XEXP (mem_addr, 0),
3685                           XEXP (XEXP (mem_addr, 1), 0)),
3686                  XEXP (XEXP (mem_addr, 1), 1));
3687       if (memory_address_p (GET_MODE (mem_rtx), ret_rtx))
3688         {
3689           XEXP (mem_rtx, 0) = ret_rtx;
3690           RTX_IS_SPILL_P (ret_rtx) = is_spill_rtx;
3691           return;
3692         }
3693       obfree (storage);
3694     }
3695
3696   /* this part is utilized by loop.c */
3697   /* If the address contains PLUS (reg,const) and this pattern is invalid
3698      in this case - try to rewrite the address to make it valid  intel1
3699   */
3700   storage = (char *) oballoc (0);
3701   index_rtx = base_rtx = offset_rtx = NULL;
3702   /* find the base index and offset elements of the memory address */
3703   if (GET_CODE (mem_addr) == PLUS)
3704     {
3705       if (GET_CODE (XEXP (mem_addr, 0)) == REG)
3706         {
3707           if (GET_CODE (XEXP (mem_addr, 1)) == REG)
3708             {
3709               base_rtx = XEXP (mem_addr, 1);
3710               index_rtx = XEXP (mem_addr, 0);
3711             }
3712           else
3713             {
3714               base_rtx = XEXP (mem_addr, 0);
3715               offset_rtx = XEXP (mem_addr, 1);
3716             }
3717         }
3718       else if (GET_CODE (XEXP (mem_addr, 0)) == MULT)
3719         {
3720           index_rtx = XEXP (mem_addr, 0);
3721           if (GET_CODE (XEXP (mem_addr, 1)) == REG)
3722             {
3723               base_rtx = XEXP (mem_addr, 1);
3724             }
3725           else
3726             {
3727               offset_rtx = XEXP (mem_addr, 1);
3728             }
3729         }
3730       else if (GET_CODE (XEXP (mem_addr, 0)) == PLUS)
3731         {
3732           /* intel1 */
3733           if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == PLUS &&
3734               GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0)) == MULT &&
3735               GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 0)) == REG &&
3736               GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 1)) == CONST_INT &&
3737               GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)) == CONST_INT &&
3738               GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == REG &&
3739               GET_CODE (XEXP (mem_addr, 1)) == SYMBOL_REF)
3740             {
3741               index_rtx = XEXP (XEXP (XEXP (mem_addr, 0), 0), 0);
3742               offset_rtx = XEXP (mem_addr, 1);
3743               base_rtx = XEXP (XEXP (mem_addr, 0), 1);
3744               offset_adjust = INTVAL (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1));
3745             }
3746           else
3747             {
3748               offset_rtx = XEXP (mem_addr, 1);
3749               index_rtx = XEXP (XEXP (mem_addr, 0), 0);
3750               base_rtx = XEXP (XEXP (mem_addr, 0), 1);
3751             }
3752         }
3753       else if (GET_CODE (XEXP (mem_addr, 0)) == CONST_INT)
3754         {
3755           was_only_offset = 1;
3756           index_rtx = NULL;
3757           base_rtx = NULL;
3758           offset_rtx = XEXP (mem_addr, 1);
3759           offset_adjust = INTVAL (XEXP (mem_addr, 0));
3760           if (offset_adjust == 0)
3761             {
3762               XEXP (mem_rtx, 0) = offset_rtx;
3763               RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
3764               return;
3765             }
3766         }
3767       else
3768         {
3769           obfree (storage);
3770           return;
3771         }
3772     }
3773   else if (GET_CODE (mem_addr) == MULT)
3774     {
3775       index_rtx = mem_addr;
3776     }
3777   else
3778     {
3779       obfree (storage);
3780       return;
3781     }
3782   if (index_rtx && GET_CODE (index_rtx) == MULT)
3783     {
3784       if (GET_CODE (XEXP (index_rtx, 1)) != CONST_INT)
3785         {
3786           obfree (storage);
3787           return;
3788         }
3789       scale_rtx = XEXP (index_rtx, 1);
3790       scale = INTVAL (scale_rtx);
3791       index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
3792     }
3793   /* now find which of the elements are invalid and try to fix them */
3794   if (index_rtx && GET_CODE (index_rtx) == CONST_INT && base_rtx == NULL)
3795     {
3796       offset_adjust = INTVAL (index_rtx) * scale;
3797       if (offset_rtx && GET_CODE (offset_rtx) == CONST &&
3798           GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
3799         {
3800           if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
3801               GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
3802             {
3803               offset_rtx = copy_all_rtx (offset_rtx);
3804               XEXP (XEXP (offset_rtx, 0), 1) =
3805                 gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
3806               if (!CONSTANT_P (offset_rtx))
3807                 {
3808                   obfree (storage);
3809                   return;
3810                 }
3811             }
3812         }
3813       else if (offset_rtx && GET_CODE (offset_rtx) == SYMBOL_REF)
3814         {
3815           offset_rtx =
3816             gen_rtx (CONST, GET_MODE (offset_rtx),
3817                      gen_rtx (PLUS, GET_MODE (offset_rtx),
3818                               offset_rtx,
3819                               gen_rtx (CONST_INT, 0, offset_adjust)));
3820           if (!CONSTANT_P (offset_rtx))
3821             {
3822               obfree (storage);
3823               return;
3824             }
3825         }
3826       else if (offset_rtx && GET_CODE (offset_rtx) == CONST_INT)
3827         {
3828           offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
3829         }
3830       else if (!offset_rtx)
3831         {
3832           offset_rtx = gen_rtx (CONST_INT, 0, 0);
3833         }
3834       RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
3835       XEXP (mem_rtx, 0) = offset_rtx;
3836       return;
3837     }
3838   if (base_rtx && GET_CODE (base_rtx) == PLUS &&
3839       GET_CODE (XEXP (base_rtx, 0)) == REG &&
3840       GET_CODE (XEXP (base_rtx, 1)) == CONST_INT)
3841     {
3842       offset_adjust += INTVAL (XEXP (base_rtx, 1));
3843       base_rtx = copy_all_rtx (XEXP (base_rtx, 0));
3844     }
3845   else if (base_rtx && GET_CODE (base_rtx) == CONST_INT)
3846     {
3847       offset_adjust += INTVAL (base_rtx);
3848       base_rtx = NULL;
3849     }
3850   if (index_rtx && GET_CODE (index_rtx) == PLUS &&
3851       GET_CODE (XEXP (index_rtx, 0)) == REG &&
3852       GET_CODE (XEXP (index_rtx, 1)) == CONST_INT)
3853     {
3854       offset_adjust += INTVAL (XEXP (index_rtx, 1)) * scale;
3855       index_rtx = copy_all_rtx (XEXP (index_rtx, 0));
3856     }
3857   if (index_rtx)
3858     {
3859       if (!LEGITIMATE_INDEX_P (index_rtx)
3860       && !(index_rtx == stack_pointer_rtx && scale == 1 && base_rtx == NULL))
3861         {
3862           obfree (storage);
3863           return;
3864         }
3865     }
3866   if (base_rtx)
3867     {
3868       if (!LEGITIMATE_INDEX_P (base_rtx) && GET_CODE (base_rtx) != REG)
3869         {
3870           obfree (storage);
3871           return;
3872         }
3873     }
3874   if (offset_adjust != 0)
3875     {
3876       if (offset_rtx)
3877         {
3878           if (GET_CODE (offset_rtx) == CONST &&
3879               GET_CODE (XEXP (offset_rtx, 0)) == PLUS)
3880             {
3881               if (GET_CODE (XEXP (XEXP (offset_rtx, 0), 0)) == SYMBOL_REF &&
3882                   GET_CODE (XEXP (XEXP (offset_rtx, 0), 1)) == CONST_INT)
3883                 {
3884                   offset_rtx = copy_all_rtx (offset_rtx);
3885                   XEXP (XEXP (offset_rtx, 0), 1) =
3886                     gen_rtx (CONST_INT, 0, INTVAL (XEXP (XEXP (offset_rtx, 0), 1)) + offset_adjust);
3887                   if (!CONSTANT_P (offset_rtx))
3888                     {
3889                       obfree (storage);
3890                       return;
3891                     }
3892                 }
3893             }
3894           else if (GET_CODE (offset_rtx) == SYMBOL_REF)
3895             {
3896               offset_rtx =
3897                 gen_rtx (CONST, GET_MODE (offset_rtx),
3898                          gen_rtx (PLUS, GET_MODE (offset_rtx),
3899                                   offset_rtx,
3900                                   gen_rtx (CONST_INT, 0, offset_adjust)));
3901               if (!CONSTANT_P (offset_rtx))
3902                 {
3903                   obfree (storage);
3904                   return;
3905                 }
3906             }
3907           else if (GET_CODE (offset_rtx) == CONST_INT)
3908             {
3909               offset_rtx = gen_rtx (CONST_INT, 0, INTVAL (offset_rtx) + offset_adjust);
3910             }
3911           else
3912             {
3913               obfree (storage);
3914               return;
3915             }
3916         }
3917       else
3918         {
3919           offset_rtx = gen_rtx (CONST_INT, 0, offset_adjust);
3920         }
3921       if (index_rtx)
3922         {
3923           if (base_rtx)
3924             {
3925               if (scale != 1)
3926                 {
3927                   if (GET_CODE (offset_rtx) == CONST_INT &&
3928                       INTVAL (offset_rtx) == 0)
3929                     {
3930                       ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx),
3931                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
3932                                       scale_rtx),
3933                                          base_rtx);
3934                     }
3935                   else
3936                     {
3937                       ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
3938                                          gen_rtx (PLUS, GET_MODE (base_rtx),
3939                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
3940                                       scale_rtx),
3941                                                   base_rtx),
3942                                          offset_rtx);
3943                     }
3944                 }
3945               else
3946                 {
3947                   if (GET_CODE (offset_rtx) == CONST_INT &&
3948                       INTVAL (offset_rtx) == 0)
3949                     {
3950                       ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, base_rtx);
3951                     }
3952                   else
3953                     {
3954                       ret_rtx = gen_rtx (PLUS, GET_MODE (offset_rtx),
3955                              gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx,
3956                                       base_rtx),
3957                                          offset_rtx);
3958                     }
3959                 }
3960             }
3961           else
3962             {
3963               if (scale != 1)
3964                 {
3965                   if (GET_CODE (offset_rtx) == CONST_INT &&
3966                       INTVAL (offset_rtx) == 0)
3967                     {
3968                       ret_rtx = gen_rtx (MULT, GET_MODE (index_rtx), index_rtx, scale_rtx);
3969                     }
3970                   else
3971                     {
3972                       ret_rtx =
3973                         gen_rtx (PLUS, GET_MODE (offset_rtx),
3974                              gen_rtx (MULT, GET_MODE (index_rtx), index_rtx,
3975                                       scale_rtx),
3976                                  offset_rtx);
3977                     }
3978                 }
3979               else
3980                 {
3981                   if (GET_CODE (offset_rtx) == CONST_INT &&
3982                       INTVAL (offset_rtx) == 0)
3983                     {
3984                       ret_rtx = index_rtx;
3985                     }
3986                   else
3987                     {
3988                       ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), index_rtx, offset_rtx);
3989                     }
3990                 }
3991             }
3992         }
3993       else
3994         {
3995           if (base_rtx)
3996             {
3997               if (GET_CODE (offset_rtx) == CONST_INT &&
3998                   INTVAL (offset_rtx) == 0)
3999                 {
4000                   ret_rtx = base_rtx;
4001                 }
4002               else
4003                 {
4004                   ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx), base_rtx, offset_rtx);
4005                 }
4006             }
4007           else if (was_only_offset)
4008             {
4009               ret_rtx = offset_rtx;
4010             }
4011           else
4012             {
4013               obfree (storage);
4014               return;
4015             }
4016         }
4017       XEXP (mem_rtx, 0) = ret_rtx;
4018       RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx;
4019       return;
4020     }
4021   else
4022     {
4023       obfree (storage);
4024       return;
4025     }
4026 }
4027 #endif /* NOTYET */
4028
4029 \f
4030 /* return 1 if the first insn to set cc before insn also sets the register
4031    reg_rtx - otherwise return 0 */
4032 int
4033 last_to_set_cc (reg_rtx, insn)
4034      rtx reg_rtx, insn;
4035 {
4036   rtx prev_insn = PREV_INSN (insn);
4037
4038   while (prev_insn)
4039     {
4040       if (GET_CODE (prev_insn) == NOTE)
4041         ;
4042
4043       else if (GET_CODE (prev_insn) == INSN)
4044         {
4045           if (GET_CODE (PATTERN (prev_insn)) != SET)
4046             return (0);
4047
4048           if (rtx_equal_p (SET_DEST (PATTERN (prev_insn)), reg_rtx))
4049             {
4050               if (sets_condition_code (SET_SRC (PATTERN (prev_insn))))
4051                 return (1);
4052
4053               return (0);
4054             }
4055
4056           else if (!doesnt_set_condition_code (SET_SRC (PATTERN (prev_insn))))
4057             return (0);
4058         }
4059
4060       else
4061         return (0);
4062
4063       prev_insn = PREV_INSN (prev_insn);
4064     }
4065
4066   return (0);
4067 }
4068
4069 \f
4070 int
4071 doesnt_set_condition_code (pat)
4072      rtx pat;
4073 {
4074   switch (GET_CODE (pat))
4075     {
4076     case MEM:
4077     case REG:
4078       return (1);
4079
4080     default:
4081       return (0);
4082
4083     }
4084 }
4085
4086 \f
4087 int
4088 sets_condition_code (pat)
4089      rtx pat;
4090 {
4091   switch (GET_CODE (pat))
4092     {
4093     case PLUS:
4094     case MINUS:
4095     case AND:
4096     case IOR:
4097     case XOR:
4098     case NOT:
4099     case NEG:
4100     case MULT:
4101     case DIV:
4102     case MOD:
4103     case UDIV:
4104     case UMOD:
4105       return (1);
4106
4107     default:
4108       return (0);
4109
4110     }
4111 }
4112
4113 \f
4114 int
4115 str_immediate_operand (op, mode)
4116      register rtx op;
4117      enum machine_mode mode;
4118 {
4119   if (GET_CODE (op) == CONST_INT && INTVAL (op) <= 32 && INTVAL (op) >= 0)
4120     {
4121       return (1);
4122     }
4123   return (0);
4124 }
4125
4126 \f
4127 int
4128 is_fp_insn (insn)
4129      rtx insn;
4130 {
4131   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4132       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4133           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4134           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode))
4135     {
4136       return (1);
4137     }
4138
4139   return (0);
4140 }
4141
4142 /*
4143   Return 1 if the mode of the SET_DEST of insn is floating point
4144   and it is not an fld or a move from memory to memory.
4145   Otherwise return 0 */
4146 int
4147 is_fp_dest (insn)
4148      rtx insn;
4149 {
4150   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4151       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4152           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4153           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)
4154       && GET_CODE (SET_DEST (PATTERN (insn))) == REG
4155       && REGNO (SET_DEST (PATTERN (insn))) >= FIRST_FLOAT_REG
4156       && GET_CODE (SET_SRC (insn)) != MEM)
4157     {
4158       return (1);
4159     }
4160
4161   return (0);
4162 }
4163
4164 /*
4165   Return 1 if the mode of the SET_DEST floating point and is memory
4166   and the source is a register.  
4167 */
4168 int
4169 is_fp_store (insn)
4170      rtx insn;
4171 {
4172   if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET
4173       && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode
4174           || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode
4175           || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)
4176       && GET_CODE (SET_DEST (PATTERN (insn))) == MEM
4177       && GET_CODE (SET_SRC (PATTERN (insn))) == REG)
4178     {
4179       return (1);
4180     }
4181
4182   return (0);
4183 }
4184
4185 \f
4186 /*
4187   Return 1 if dep_insn sets a register which insn uses as a base
4188   or index to reference memory.
4189   otherwise return 0 */
4190
4191 int
4192 agi_dependent (insn, dep_insn)
4193      rtx insn, dep_insn;
4194 {
4195   if (GET_CODE (dep_insn) == INSN
4196       && GET_CODE (PATTERN (dep_insn)) == SET
4197       && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG)
4198     {
4199       return (reg_mentioned_in_mem (SET_DEST (PATTERN (dep_insn)), insn));
4200     }
4201
4202   if (GET_CODE (dep_insn) == INSN && GET_CODE (PATTERN (dep_insn)) == SET
4203       && GET_CODE (SET_DEST (PATTERN (dep_insn))) == MEM
4204       && push_operand (SET_DEST (PATTERN (dep_insn)),
4205                        GET_MODE (SET_DEST (PATTERN (dep_insn)))))
4206     {
4207       return (reg_mentioned_in_mem (stack_pointer_rtx, insn));
4208     }
4209   
4210   return (0);
4211 }
4212
4213 \f
4214 /*
4215   Return 1 if reg is used in rtl as a base or index for a memory ref
4216   otherwise return 0. */
4217
4218 int
4219 reg_mentioned_in_mem (reg, rtl)
4220      rtx reg, rtl;
4221 {
4222   register char *fmt;
4223   register int i;
4224   register enum rtx_code code;
4225
4226   if (rtl == NULL)
4227     return (0);
4228
4229   code = GET_CODE (rtl);
4230
4231   switch (code)
4232     {
4233     case HIGH:
4234     case CONST_INT:
4235     case CONST:
4236     case CONST_DOUBLE:
4237     case SYMBOL_REF:
4238     case LABEL_REF:
4239     case PC:
4240     case CC0:
4241     case SUBREG:
4242       return (0);
4243
4244
4245     }
4246
4247   if (code == MEM && reg_mentioned_p (reg, rtl))
4248     return (1);
4249
4250   fmt = GET_RTX_FORMAT (code);
4251   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
4252     {
4253       if (fmt[i] == 'E')
4254         {
4255           register int j;
4256           for (j = XVECLEN (rtl, i) - 1; j >= 0; j--)
4257             {
4258               if (reg_mentioned_in_mem (reg, XVECEXP (rtl, i, j)))
4259                 return 1;
4260             }
4261         }
4262
4263       else if (fmt[i] == 'e' && reg_mentioned_in_mem (reg, XEXP (rtl, i)))
4264         return 1;
4265     }
4266
4267   return (0);
4268 }
4269 \f
4270 /* Output the approprate insns for doing strlen if not just doing repnz; scasb
4271
4272    operands[0] = result, initialized with the startaddress
4273    operands[1] = alignment of the address.
4274    operands[2] = scratch register, initialized with the startaddress when
4275                  not aligned, otherwise undefined
4276
4277    This is just the body. It needs the initialisations mentioned above and
4278    some address computing at the end.  These things are done in i386.md.  */
4279
4280 char *
4281 output_strlen_unroll (operands)
4282      rtx operands[];
4283 {
4284   rtx xops[18];
4285
4286   xops[0] = operands[0];                /* Result */
4287   /*        operands[1];                 * Alignment */
4288   xops[1] = operands[2];                /* Scratch */
4289   xops[2] = GEN_INT (0);
4290   xops[3] = GEN_INT (2);
4291   xops[4] = GEN_INT (3);
4292   xops[5] = GEN_INT (4);
4293   /* xops[6] = gen_label_rtx ();         * label when aligned to 3-byte */
4294   /* xops[7] = gen_label_rtx ();         * label when aligned to 2-byte */
4295   xops[8] = gen_label_rtx ();           /* label of main loop */
4296   if(TARGET_USE_Q_REG && QI_REG_P (xops[1]))
4297     xops[9] = gen_label_rtx ();         /* pentium optimisation */
4298   xops[10] = gen_label_rtx ();          /* end label 2 */
4299   xops[11] = gen_label_rtx ();          /* end label 1 */
4300   xops[12] = gen_label_rtx ();          /* end label */
4301   /* xops[13]                            * Temporary used */
4302   xops[14] = GEN_INT (0xff);
4303   xops[15] = GEN_INT (0xff00);
4304   xops[16] = GEN_INT (0xff0000);
4305   xops[17] = GEN_INT (0xff000000);
4306
4307     /* Loop to check 1..3 bytes for null to get an aligned pointer */
4308
4309     /* is there a known alignment and is it less then 4 */
4310   if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) < 4)
4311     {
4312         /* is there a known alignment and is it not 2 */
4313       if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2)
4314         {
4315           xops[6] = gen_label_rtx ();   /* label when aligned to 3-byte */
4316           xops[7] = gen_label_rtx ();   /* label when aligned to 2-byte */
4317
4318             /* leave just the 3 lower bits */
4319             /* if this is a q-register, then the high part is used later */
4320             /* therefore user andl rather than andb */
4321           output_asm_insn (AS2 (and%L1,%4,%1), xops);
4322             /* is aligned to 4-byte adress when zero */
4323           output_asm_insn (AS1 (je,%l8), xops);
4324             /* side-effect even Parity when %eax == 3 */
4325           output_asm_insn (AS1 (jp,%6), xops);
4326
4327             /* is it aligned to 2 bytes ? */
4328           if (QI_REG_P (xops[1]))
4329             output_asm_insn (AS2 (cmp%L1,%3,%1), xops);
4330           else
4331             output_asm_insn (AS2 (cmp%L1,%3,%1), xops);
4332           output_asm_insn (AS1 (je,%7), xops);
4333         }
4334       else
4335         {
4336             /* since the alignment is 2, we have to check 2 or 0 bytes */
4337
4338             /* check if is aligned to 4 - byte */
4339           output_asm_insn (AS2 (and%L1,%3,%1), xops);
4340             /* is aligned to 4-byte adress when zero */
4341           output_asm_insn (AS1 (je,%l8), xops);
4342         }
4343
4344       xops[13] = gen_rtx (MEM, QImode, xops[0]);
4345         /* now, compare the bytes */
4346         /* compare with the high part of a q-reg gives shorter code */
4347       if (QI_REG_P (xops[1]))
4348         {
4349             /* compare the first n unaligned byte on a byte per byte basis */
4350           output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4351             /* when zero we reached the end */
4352           output_asm_insn (AS1 (je,%l12), xops);
4353             /* increment the address */
4354           output_asm_insn (AS1 (inc%L0,%0), xops);
4355
4356             /* not needed with an alignment of 2 */
4357           if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2)
4358             {
4359               ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[7]));
4360               output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4361               output_asm_insn (AS1 (je,%l12), xops);
4362               output_asm_insn (AS1 (inc%L0,%0), xops);
4363
4364               ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[6]));
4365             }
4366           output_asm_insn (AS2 (cmp%B1,%h1,%13), xops);
4367         }
4368       else
4369         {
4370           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4371           output_asm_insn (AS1 (je,%l12), xops);
4372           output_asm_insn (AS1 (inc%L0,%0), xops);
4373
4374           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[7]));
4375           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4376           output_asm_insn (AS1 (je,%l12), xops);
4377           output_asm_insn (AS1 (inc%L0,%0), xops);
4378
4379           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[6]));
4380           output_asm_insn (AS2 (cmp%B13,%2,%13), xops);
4381         }
4382       output_asm_insn (AS1 (je,%l12), xops);
4383       output_asm_insn (AS1 (inc%L0,%0), xops);
4384     }
4385
4386     /* Generate loop to check 4 bytes at a time */
4387     /* IMHO it is not a good idea to align this loop.  It gives only */
4388     /* huge programms, but does not help to speed up */
4389   /* ASM_OUTPUT_LOOP_ALIGN (asm_out_file); */
4390   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[8]));
4391
4392   xops[13] = gen_rtx (MEM, SImode, xops[0]);
4393   output_asm_insn (AS2 (mov%L1,%13,%1), xops);
4394
4395   if (QI_REG_P (xops[1]))
4396     {
4397         /* on i586 it is faster to compare the hi- and lo- part */
4398         /* as a kind of lookahead.  If xoring both is zero, then one */
4399         /* of both *could* be zero, otherwith none of both is zero */
4400         /* this saves one instruction, on i486 this is slower */
4401         /* testet with P-90, i486DX2-66, AMD486DX2-66 */
4402       if(TARGET_PENTIUM)
4403         {
4404           output_asm_insn (AS2 (test%B1,%h1,%b1), xops);
4405           output_asm_insn (AS1 (jne,%l9), xops);
4406         }
4407
4408         /* check first byte */
4409       output_asm_insn (AS2 (test%B1,%b1,%b1), xops);
4410       output_asm_insn (AS1 (je,%l12), xops);
4411
4412         /* check second byte */
4413       output_asm_insn (AS2 (test%B1,%h1,%h1), xops);
4414       output_asm_insn (AS1 (je,%l11), xops);
4415
4416       if(TARGET_PENTIUM)
4417           ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[9]));
4418     }
4419   else
4420     {
4421         /* check first byte */
4422       output_asm_insn (AS2 (test%L1,%14,%1), xops);
4423       output_asm_insn (AS1 (je,%l12), xops);
4424
4425         /* check second byte */
4426       output_asm_insn (AS2 (test%L1,%15,%1), xops);
4427       output_asm_insn (AS1 (je,%l11), xops);
4428     }
4429
4430     /* check third byte */
4431   output_asm_insn (AS2 (test%L1,%16,%1), xops);
4432   output_asm_insn (AS1 (je,%l10), xops);
4433   
4434     /* check fourth byte and increment address */
4435   output_asm_insn (AS2 (add%L0,%5,%0), xops);
4436   output_asm_insn (AS2 (test%L1,%17,%1), xops);
4437   output_asm_insn (AS1 (jne,%l8), xops);
4438
4439     /* now generate fixups when the compare stops within a 4-byte word */
4440   output_asm_insn (AS2 (sub%L0,%4,%0), xops);
4441
4442   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[10]));
4443   output_asm_insn (AS1 (inc%L0,%0), xops);
4444
4445   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[11]));
4446   output_asm_insn (AS1 (inc%L0,%0), xops);
4447
4448   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[12]));
4449
4450   RET;
4451 }