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