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