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