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