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