1 /* Subroutines for insn-output.c for Intel X86.
2 Copyright (C) 1988, 1992, 1994 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 #include "hard-reg-set.h"
27 #include "insn-config.h"
28 #include "conditions.h"
29 #include "insn-flags.h"
31 #include "insn-attr.h"
36 #ifdef EXTRA_CONSTRAINT
37 /* If EXTRA_CONSTRAINT is defined, then the 'S'
38 constraint in REG_CLASS_FROM_LETTER will no longer work, and various
39 asm statements that need 'S' for class SIREG will break. */
40 error EXTRA_CONSTRAINT conflicts with S constraint letter
41 /* The previous line used to be #error, but some compilers barf
42 even if the conditional was untrue. */
45 #define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx))
47 extern FILE *asm_out_file
;
48 extern char *strcat ();
50 char *singlemove_string ();
51 char *output_move_const_single ();
52 char *output_fp_cc0_set ();
54 char *hi_reg_name
[] = HI_REGISTER_NAMES
;
55 char *qi_reg_name
[] = QI_REGISTER_NAMES
;
56 char *qi_high_reg_name
[] = QI_HIGH_REGISTER_NAMES
;
58 /* Array of the smallest class containing reg number REGNO, indexed by
59 REGNO. Used by REGNO_REG_CLASS in i386.h. */
61 enum reg_class regclass_map
[FIRST_PSEUDO_REGISTER
] =
64 AREG
, DREG
, CREG
, BREG
,
66 SIREG
, DIREG
, INDEX_REGS
, GENERAL_REGS
,
68 FP_TOP_REG
, FP_SECOND_REG
, FLOAT_REGS
, FLOAT_REGS
,
69 FLOAT_REGS
, FLOAT_REGS
, FLOAT_REGS
, FLOAT_REGS
,
74 /* Test and compare insns in i386.md store the information needed to
75 generate branch and scc insns here. */
77 struct rtx_def
*i386_compare_op0
, *i386_compare_op1
;
78 struct rtx_def
*(*i386_compare_gen
)(), *(*i386_compare_gen_eq
)();
80 /* Output an insn whose source is a 386 integer register. SRC is the
81 rtx for the register, and TEMPLATE is the op-code template. SRC may
82 be either SImode or DImode.
84 The template will be output with operands[0] as SRC, and operands[1]
85 as a pointer to the top of the 386 stack. So a call from floatsidf2
88 output_op_from_reg (operands[1], AS1 (fild%z0,%1));
90 where %z0 corresponds to the caller's operands[1], and is used to
91 emit the proper size suffix.
93 ??? Extend this to handle HImode - a 387 can load and store HImode
97 output_op_from_reg (src
, template)
102 int size
= GET_MODE_SIZE (GET_MODE (src
));
105 xops
[1] = AT_SP (Pmode
);
106 xops
[2] = GEN_INT (size
);
107 xops
[3] = stack_pointer_rtx
;
109 if (size
> UNITS_PER_WORD
)
112 if (size
> 2 * UNITS_PER_WORD
)
114 high
= gen_rtx (REG
, SImode
, REGNO (src
) + 2);
115 output_asm_insn (AS1 (push
%L0
,%0), &high
);
117 high
= gen_rtx (REG
, SImode
, REGNO (src
) + 1);
118 output_asm_insn (AS1 (push
%L0
,%0), &high
);
120 output_asm_insn (AS1 (push
%L0
,%0), &src
);
122 output_asm_insn (template, xops
);
124 output_asm_insn (AS2 (add
%L3
,%2,%3), xops
);
127 /* Output an insn to pop an value from the 387 top-of-stack to 386
128 register DEST. The 387 register stack is popped if DIES is true. If
129 the mode of DEST is an integer mode, a `fist' integer store is done,
130 otherwise a `fst' float store is done. */
133 output_to_reg (dest
, dies
)
138 int size
= GET_MODE_SIZE (GET_MODE (dest
));
140 xops
[0] = AT_SP (Pmode
);
141 xops
[1] = stack_pointer_rtx
;
142 xops
[2] = GEN_INT (size
);
145 output_asm_insn (AS2 (sub
%L1
,%2,%1), xops
);
147 if (GET_MODE_CLASS (GET_MODE (dest
)) == MODE_INT
)
150 output_asm_insn (AS1 (fistp
%z3
,%y0
), xops
);
152 output_asm_insn (AS1 (fist
%z3
,%y0
), xops
);
154 else if (GET_MODE_CLASS (GET_MODE (dest
)) == MODE_FLOAT
)
157 output_asm_insn (AS1 (fstp
%z3
,%y0
), xops
);
160 if (GET_MODE (dest
) == XFmode
)
162 output_asm_insn (AS1 (fstp
%z3
,%y0
), xops
);
163 output_asm_insn (AS1 (fld
%z3
,%y0
), xops
);
166 output_asm_insn (AS1 (fst
%z3
,%y0
), xops
);
172 output_asm_insn (AS1 (pop
%L0
,%0), &dest
);
174 if (size
> UNITS_PER_WORD
)
176 dest
= gen_rtx (REG
, SImode
, REGNO (dest
) + 1);
177 output_asm_insn (AS1 (pop
%L0
,%0), &dest
);
178 if (size
> 2 * UNITS_PER_WORD
)
180 dest
= gen_rtx (REG
, SImode
, REGNO (dest
) + 1);
181 output_asm_insn (AS1 (pop
%L0
,%0), &dest
);
187 singlemove_string (operands
)
191 if (GET_CODE (operands
[0]) == MEM
192 && GET_CODE (x
= XEXP (operands
[0], 0)) == PRE_DEC
)
194 if (XEXP (x
, 0) != stack_pointer_rtx
)
198 else if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
200 return output_move_const_single (operands
);
202 else if (GET_CODE (operands
[0]) == REG
|| GET_CODE (operands
[1]) == REG
)
203 return AS2 (mov
%L0
,%1,%0);
204 else if (CONSTANT_P (operands
[1]))
205 return AS2 (mov
%L0
,%1,%0);
208 output_asm_insn ("push%L1 %1", operands
);
213 /* Return a REG that occurs in ADDR with coefficient 1.
214 ADDR can be effectively incremented by incrementing REG. */
220 while (GET_CODE (addr
) == PLUS
)
222 if (GET_CODE (XEXP (addr
, 0)) == REG
)
223 addr
= XEXP (addr
, 0);
224 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
225 addr
= XEXP (addr
, 1);
226 else if (CONSTANT_P (XEXP (addr
, 0)))
227 addr
= XEXP (addr
, 1);
228 else if (CONSTANT_P (XEXP (addr
, 1)))
229 addr
= XEXP (addr
, 0);
233 if (GET_CODE (addr
) == REG
)
238 /* Output an insn to add the constant N to the register X. */
249 output_asm_insn (AS1 (dec
%L0
,%0), xops
);
251 output_asm_insn (AS1 (inc
%L0
,%0), xops
);
254 xops
[1] = GEN_INT (-n
);
255 output_asm_insn (AS2 (sub
%L0
,%1,%0), xops
);
259 xops
[1] = GEN_INT (n
);
260 output_asm_insn (AS2 (add
%L0
,%1,%0), xops
);
264 /* Output assembler code to perform a doubleword move insn
265 with operands OPERANDS. */
268 output_move_double (operands
)
271 enum {REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
275 rtx addreg0
= 0, addreg1
= 0;
276 int dest_overlapped_low
= 0;
277 int size
= GET_MODE_SIZE (GET_MODE (operands
[1]));
282 /* First classify both operands. */
284 if (REG_P (operands
[0]))
286 else if (offsettable_memref_p (operands
[0]))
288 else if (GET_CODE (XEXP (operands
[0], 0)) == POST_INC
)
290 else if (GET_CODE (XEXP (operands
[0], 0)) == PRE_DEC
)
292 else if (GET_CODE (operands
[0]) == MEM
)
297 if (REG_P (operands
[1]))
299 else if (CONSTANT_P (operands
[1]))
301 else if (offsettable_memref_p (operands
[1]))
303 else if (GET_CODE (XEXP (operands
[1], 0)) == POST_INC
)
305 else if (GET_CODE (XEXP (operands
[1], 0)) == PRE_DEC
)
307 else if (GET_CODE (operands
[1]) == MEM
)
312 /* Check for the cases that the operand constraints are not
313 supposed to allow to happen. Abort if we get one,
314 because generating code for these cases is painful. */
316 if (optype0
== RNDOP
|| optype1
== RNDOP
)
319 /* If one operand is decrementing and one is incrementing
320 decrement the former register explicitly
321 and change that operand into ordinary indexing. */
323 if (optype0
== PUSHOP
&& optype1
== POPOP
)
325 /* ??? Can this ever happen on i386? */
326 operands
[0] = XEXP (XEXP (operands
[0], 0), 0);
327 asm_add (-size
, operands
[0]);
328 if (GET_MODE (operands
[1]) == XFmode
)
329 operands
[0] = gen_rtx (MEM
, XFmode
, operands
[0]);
330 else if (GET_MODE (operands
[0]) == DFmode
)
331 operands
[0] = gen_rtx (MEM
, DFmode
, operands
[0]);
333 operands
[0] = gen_rtx (MEM
, DImode
, operands
[0]);
337 if (optype0
== POPOP
&& optype1
== PUSHOP
)
339 /* ??? Can this ever happen on i386? */
340 operands
[1] = XEXP (XEXP (operands
[1], 0), 0);
341 asm_add (-size
, operands
[1]);
342 if (GET_MODE (operands
[1]) == XFmode
)
343 operands
[1] = gen_rtx (MEM
, XFmode
, operands
[1]);
344 else if (GET_MODE (operands
[1]) == DFmode
)
345 operands
[1] = gen_rtx (MEM
, DFmode
, operands
[1]);
347 operands
[1] = gen_rtx (MEM
, DImode
, operands
[1]);
351 /* If an operand is an unoffsettable memory ref, find a register
352 we can increment temporarily to make it refer to the second word. */
354 if (optype0
== MEMOP
)
355 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
357 if (optype1
== MEMOP
)
358 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
360 /* Ok, we can do one word at a time.
361 Normally we do the low-numbered word first,
362 but if either operand is autodecrementing then we
363 do the high-numbered word first.
365 In either case, set up in LATEHALF the operands to use
366 for the high-numbered word and in some cases alter the
367 operands in OPERANDS to be suitable for the low-numbered word. */
371 if (optype0
== REGOP
)
373 middlehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
374 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 2);
376 else if (optype0
== OFFSOP
)
378 middlehalf
[0] = adj_offsettable_operand (operands
[0], 4);
379 latehalf
[0] = adj_offsettable_operand (operands
[0], 8);
383 middlehalf
[0] = operands
[0];
384 latehalf
[0] = operands
[0];
387 if (optype1
== REGOP
)
389 middlehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
390 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 2);
392 else if (optype1
== OFFSOP
)
394 middlehalf
[1] = adj_offsettable_operand (operands
[1], 4);
395 latehalf
[1] = adj_offsettable_operand (operands
[1], 8);
397 else if (optype1
== CNSTOP
)
399 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
401 REAL_VALUE_TYPE r
; long l
[3];
403 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
404 REAL_VALUE_TO_TARGET_LONG_DOUBLE (r
, l
);
405 operands
[1] = GEN_INT (l
[0]);
406 middlehalf
[1] = GEN_INT (l
[1]);
407 latehalf
[1] = GEN_INT (l
[2]);
409 else if (CONSTANT_P (operands
[1]))
410 /* No non-CONST_DOUBLE constant should ever appear here. */
415 middlehalf
[1] = operands
[1];
416 latehalf
[1] = operands
[1];
419 else /* size is not 12: */
421 if (optype0
== REGOP
)
422 latehalf
[0] = gen_rtx (REG
, SImode
, REGNO (operands
[0]) + 1);
423 else if (optype0
== OFFSOP
)
424 latehalf
[0] = adj_offsettable_operand (operands
[0], 4);
426 latehalf
[0] = operands
[0];
428 if (optype1
== REGOP
)
429 latehalf
[1] = gen_rtx (REG
, SImode
, REGNO (operands
[1]) + 1);
430 else if (optype1
== OFFSOP
)
431 latehalf
[1] = adj_offsettable_operand (operands
[1], 4);
432 else if (optype1
== CNSTOP
)
434 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
435 split_double (operands
[1], &operands
[1], &latehalf
[1]);
436 else if (CONSTANT_P (operands
[1]))
438 /* ??? jrv: Can this really happen? A DImode constant
439 that isn't a CONST_DOUBLE? */
440 if (GET_CODE (operands
[1]) == CONST_INT
441 && INTVAL (operands
[1]) < 0)
442 latehalf
[1] = constm1_rtx
;
444 latehalf
[1] = const0_rtx
;
448 latehalf
[1] = operands
[1];
451 /* If insn is effectively movd N (sp),-(sp) then we will do the
452 high word first. We should use the adjusted operand 1
453 (which is N+4 (sp) or N+8 (sp))
454 for the low word and middle word as well,
455 to compensate for the first decrement of sp. */
456 if (optype0
== PUSHOP
457 && REGNO (XEXP (XEXP (operands
[0], 0), 0)) == STACK_POINTER_REGNUM
458 && reg_overlap_mentioned_p (stack_pointer_rtx
, operands
[1]))
459 middlehalf
[1] = operands
[1] = latehalf
[1];
461 /* For (set (reg:DI N) (mem:DI ... (reg:SI N) ...)),
462 if the upper part of reg N does not appear in the MEM, arrange to
463 emit the move late-half first. Otherwise, compute the MEM address
464 into the upper part of N and use that as a pointer to the memory
467 && (optype1
== OFFSOP
|| optype1
== MEMOP
))
469 if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0))
470 && reg_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
472 /* If both halves of dest are used in the src memory address,
473 compute the address into latehalf of dest. */
475 xops
[0] = latehalf
[0];
476 xops
[1] = XEXP (operands
[1], 0);
477 output_asm_insn (AS2 (lea
%L0
,%a1
,%0), xops
);
478 if( GET_MODE (operands
[1]) == XFmode
)
481 operands
[1] = gen_rtx (MEM
, XFmode
, latehalf
[0]);
482 middlehalf
[1] = adj_offsettable_operand (operands
[1], size
-8);
483 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
487 operands
[1] = gen_rtx (MEM
, DImode
, latehalf
[0]);
488 latehalf
[1] = adj_offsettable_operand (operands
[1], size
-4);
492 && reg_mentioned_p (middlehalf
[0], XEXP (operands
[1], 0)))
494 /* Check for two regs used by both source and dest. */
495 if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0))
496 || reg_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
499 /* JRV says this can't happen: */
500 if (addreg0
|| addreg1
)
503 /* Only the middle reg conflicts; simply put it last. */
504 output_asm_insn (singlemove_string (operands
), operands
);
505 output_asm_insn (singlemove_string (latehalf
), latehalf
);
506 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
509 else if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0)))
510 /* If the low half of dest is mentioned in the source memory
511 address, the arrange to emit the move late half first. */
512 dest_overlapped_low
= 1;
515 /* If one or both operands autodecrementing,
516 do the two words, high-numbered first. */
518 /* Likewise, the first move would clobber the source of the second one,
519 do them in the other order. This happens only for registers;
520 such overlap can't happen in memory unless the user explicitly
521 sets it up, and that is an undefined circumstance. */
524 if (optype0 == PUSHOP || optype1 == PUSHOP
525 || (optype0 == REGOP && optype1 == REGOP
526 && REGNO (operands[0]) == REGNO (latehalf[1]))
527 || dest_overlapped_low)
529 if (optype0
== PUSHOP
|| optype1
== PUSHOP
530 || (optype0
== REGOP
&& optype1
== REGOP
531 && ((middlehalf
[1] && REGNO (operands
[0]) == REGNO (middlehalf
[1]))
532 || REGNO (operands
[0]) == REGNO (latehalf
[1])))
533 || dest_overlapped_low
)
535 /* Make any unoffsettable addresses point at high-numbered word. */
537 asm_add (size
-4, addreg0
);
539 asm_add (size
-4, addreg1
);
542 output_asm_insn (singlemove_string (latehalf
), latehalf
);
544 /* Undo the adds we just did. */
546 asm_add (-4, addreg0
);
548 asm_add (-4, addreg1
);
552 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
554 asm_add (-4, addreg0
);
556 asm_add (-4, addreg1
);
559 /* Do low-numbered word. */
560 return singlemove_string (operands
);
563 /* Normal case: do the two words, low-numbered first. */
565 output_asm_insn (singlemove_string (operands
), operands
);
567 /* Do the middle one of the three words for long double */
571 asm_add (4, addreg0
);
573 asm_add (4, addreg1
);
575 output_asm_insn (singlemove_string (middlehalf
), middlehalf
);
578 /* Make any unoffsettable addresses point at high-numbered word. */
580 asm_add (4, addreg0
);
582 asm_add (4, addreg1
);
585 output_asm_insn (singlemove_string (latehalf
), latehalf
);
587 /* Undo the adds we just did. */
589 asm_add (4-size
, addreg0
);
591 asm_add (4-size
, addreg1
);
597 standard_80387_constant_p (x
)
600 #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
605 if (setjmp (handler
))
608 set_float_handler (handler
);
609 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
610 is0
= REAL_VALUES_EQUAL (d
, dconst0
);
611 is1
= REAL_VALUES_EQUAL (d
, dconst1
);
612 set_float_handler (NULL_PTR
);
620 /* Note that on the 80387, other constants, such as pi,
621 are much slower to load as standard constants
622 than to load from doubles in memory! */
629 output_move_const_single (operands
)
632 if (FP_REG_P (operands
[0]))
634 int conval
= standard_80387_constant_p (operands
[1]);
642 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
644 REAL_VALUE_TYPE r
; long l
;
646 if (GET_MODE (operands
[1]) == XFmode
)
649 REAL_VALUE_FROM_CONST_DOUBLE (r
, operands
[1]);
650 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
651 operands
[1] = GEN_INT (l
);
653 return singlemove_string (operands
);
656 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
657 reference and a constant. */
660 symbolic_operand (op
, mode
)
662 enum machine_mode mode
;
664 switch (GET_CODE (op
))
671 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
672 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
673 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
679 /* Test for a valid operand for a call instruction.
680 Don't allow the arg pointer register or virtual regs
681 since they may change into reg + const, which the patterns
685 call_insn_operand (op
, mode
)
687 enum machine_mode mode
;
689 if (GET_CODE (op
) == MEM
690 && ((CONSTANT_ADDRESS_P (XEXP (op
, 0))
691 /* This makes a difference for PIC. */
692 && general_operand (XEXP (op
, 0), Pmode
))
693 || (GET_CODE (XEXP (op
, 0)) == REG
694 && XEXP (op
, 0) != arg_pointer_rtx
695 && !(REGNO (XEXP (op
, 0)) >= FIRST_PSEUDO_REGISTER
696 && REGNO (XEXP (op
, 0)) <= LAST_VIRTUAL_REGISTER
))))
701 /* Like call_insn_operand but allow (mem (symbol_ref ...))
705 expander_call_insn_operand (op
, mode
)
707 enum machine_mode mode
;
709 if (GET_CODE (op
) == MEM
710 && (CONSTANT_ADDRESS_P (XEXP (op
, 0))
711 || (GET_CODE (XEXP (op
, 0)) == REG
712 && XEXP (op
, 0) != arg_pointer_rtx
713 && !(REGNO (XEXP (op
, 0)) >= FIRST_PSEUDO_REGISTER
714 && REGNO (XEXP (op
, 0)) <= LAST_VIRTUAL_REGISTER
))))
719 /* Returns 1 if OP contains a symbol reference */
722 symbolic_reference_mentioned_p (op
)
728 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
731 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
732 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
738 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
739 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
742 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
749 /* This function generates the assembly code for function entry.
750 FILE is an stdio stream to output the code to.
751 SIZE is an int: how many units of temporary storage to allocate. */
754 function_prologue (file
, size
)
761 int pic_reg_used
= flag_pic
&& (current_function_uses_pic_offset_table
762 || current_function_uses_const_pool
);
764 xops
[0] = stack_pointer_rtx
;
765 xops
[1] = frame_pointer_rtx
;
766 xops
[2] = GEN_INT (size
);
767 if (frame_pointer_needed
)
769 output_asm_insn ("push%L1 %1", xops
);
770 output_asm_insn (AS2 (mov
%L0
,%0,%1), xops
);
774 output_asm_insn (AS2 (sub
%L0
,%2,%0), xops
);
776 /* Note If use enter it is NOT reversed args.
777 This one is not reversed from intel!!
778 I think enter is slower. Also sdb doesn't like it.
779 But if you want it the code is:
781 xops[3] = const0_rtx;
782 output_asm_insn ("enter %2,%3", xops);
785 limit
= (frame_pointer_needed
? FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM
);
786 for (regno
= limit
- 1; regno
>= 0; regno
--)
787 if ((regs_ever_live
[regno
] && ! call_used_regs
[regno
])
788 || (regno
== PIC_OFFSET_TABLE_REGNUM
&& pic_reg_used
))
790 xops
[0] = gen_rtx (REG
, SImode
, regno
);
791 output_asm_insn ("push%L0 %0", xops
);
796 xops
[0] = pic_offset_table_rtx
;
797 xops
[1] = (rtx
) gen_label_rtx ();
799 output_asm_insn (AS1 (call
,%P1
), xops
);
800 ASM_OUTPUT_INTERNAL_LABEL (file
, "L", CODE_LABEL_NUMBER (xops
[1]));
801 output_asm_insn (AS1 (pop
%L0
,%0), xops
);
802 output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops
);
806 /* Return 1 if it is appropriate to emit `ret' instructions in the
807 body of a function. Do this only if the epilogue is simple, needing a
808 couple of insns. Prior to reloading, we can't tell how many registers
809 must be saved, so return 0 then.
811 If NON_SAVING_SETJMP is defined and true, then it is not possible
812 for the epilogue to be simple, so return 0. This is a special case
813 since NON_SAVING_SETJMP will not cause regs_ever_live to change until
814 final, but jump_optimize may need to know sooner if a `return' is OK. */
817 simple_386_epilogue ()
821 int reglimit
= (frame_pointer_needed
822 ? FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM
);
823 int pic_reg_used
= flag_pic
&& (current_function_uses_pic_offset_table
824 || current_function_uses_const_pool
);
826 #ifdef NON_SAVING_SETJMP
827 if (NON_SAVING_SETJMP
&& current_function_calls_setjmp
)
831 if (! reload_completed
)
834 for (regno
= reglimit
- 1; regno
>= 0; regno
--)
835 if ((regs_ever_live
[regno
] && ! call_used_regs
[regno
])
836 || (regno
== PIC_OFFSET_TABLE_REGNUM
&& pic_reg_used
))
839 return nregs
== 0 || ! frame_pointer_needed
;
843 /* This function generates the assembly code for function exit.
844 FILE is an stdio stream to output the code to.
845 SIZE is an int: how many units of temporary storage to deallocate. */
848 function_epilogue (file
, size
)
853 register int nregs
, limit
;
856 int pic_reg_used
= flag_pic
&& (current_function_uses_pic_offset_table
857 || current_function_uses_const_pool
);
859 /* Compute the number of registers to pop */
861 limit
= (frame_pointer_needed
862 ? FRAME_POINTER_REGNUM
863 : STACK_POINTER_REGNUM
);
867 for (regno
= limit
- 1; regno
>= 0; regno
--)
868 if ((regs_ever_live
[regno
] && ! call_used_regs
[regno
])
869 || (regno
== PIC_OFFSET_TABLE_REGNUM
&& pic_reg_used
))
872 /* sp is often unreliable so we must go off the frame pointer,
875 /* In reality, we may not care if sp is unreliable, because we can
876 restore the register relative to the frame pointer. In theory,
877 since each move is the same speed as a pop, and we don't need the
878 leal, this is faster. For now restore multiple registers the old
881 offset
= -size
- (nregs
* UNITS_PER_WORD
);
883 xops
[2] = stack_pointer_rtx
;
885 if (nregs
> 1 || ! frame_pointer_needed
)
887 if (frame_pointer_needed
)
889 xops
[0] = adj_offsettable_operand (AT_BP (Pmode
), offset
);
890 output_asm_insn (AS2 (lea
%L2
,%0,%2), xops
);
893 for (regno
= 0; regno
< limit
; regno
++)
894 if ((regs_ever_live
[regno
] && ! call_used_regs
[regno
])
895 || (regno
== PIC_OFFSET_TABLE_REGNUM
&& pic_reg_used
))
897 xops
[0] = gen_rtx (REG
, SImode
, regno
);
898 output_asm_insn ("pop%L0 %0", xops
);
902 for (regno
= 0; regno
< limit
; regno
++)
903 if ((regs_ever_live
[regno
] && ! call_used_regs
[regno
])
904 || (regno
== PIC_OFFSET_TABLE_REGNUM
&& pic_reg_used
))
906 xops
[0] = gen_rtx (REG
, SImode
, regno
);
907 xops
[1] = adj_offsettable_operand (AT_BP (Pmode
), offset
);
908 output_asm_insn (AS2 (mov
%L0
,%1,%0), xops
);
912 if (frame_pointer_needed
)
914 /* On i486, mov & pop is faster than "leave". */
918 xops
[0] = frame_pointer_rtx
;
919 output_asm_insn (AS2 (mov
%L2
,%0,%2), xops
);
920 output_asm_insn ("pop%L0 %0", xops
);
923 output_asm_insn ("leave", xops
);
927 /* If there is no frame pointer, we must still release the frame. */
929 xops
[0] = GEN_INT (size
);
930 output_asm_insn (AS2 (add
%L2
,%0,%2), xops
);
933 if (current_function_pops_args
&& current_function_args_size
)
935 xops
[1] = GEN_INT (current_function_pops_args
);
937 /* i386 can only pop 32K bytes (maybe 64K? Is it signed?). If
938 asked to pop more, pop return address, do explicit add, and jump
939 indirectly to the caller. */
941 if (current_function_pops_args
>= 32768)
943 /* ??? Which register to use here? */
944 xops
[0] = gen_rtx (REG
, SImode
, 2);
945 output_asm_insn ("pop%L0 %0", xops
);
946 output_asm_insn (AS2 (add
%L2
,%1,%2), xops
);
947 output_asm_insn ("jmp %*%0", xops
);
950 output_asm_insn ("ret %1", xops
);
953 output_asm_insn ("ret", xops
);
957 /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
958 that is a valid memory address for an instruction.
959 The MODE argument is the machine mode for the MEM expression
960 that wants to use this address.
962 On x86, legitimate addresses are:
964 displacement movl disp,reg
965 base + displacement movl disp(base),reg
966 index + base movl (base,index),reg
967 (index + base) + displacement movl disp(base,index),reg
968 index*scale movl (,index,scale),reg
969 index*scale + disp movl disp(,index,scale),reg
970 index*scale + base movl (base,index,scale),reg
971 (index*scale + base) + disp movl disp(base,index,scale),reg
973 In each case, scale can be 1, 2, 4, 8. */
975 /* This is exactly the same as print_operand_addr, except that
976 it recognizes addresses instead of printing them.
978 It only recognizes address in canonical form. LEGITIMIZE_ADDRESS should
979 convert common non-canonical forms to canonical form so that they will
982 #define ADDR_INVALID(msg,insn) \
984 if (TARGET_DEBUG_ADDR) \
986 fprintf (stderr, msg); \
992 legitimate_address_p (mode
, addr
, strict
)
993 enum machine_mode mode
;
999 rtx scale
= NULL_RTX
;
1000 rtx disp
= NULL_RTX
;
1002 if (TARGET_DEBUG_ADDR
)
1005 "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
1006 GET_MODE_NAME (mode
), strict
);
1011 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == SUBREG
)
1012 base
= addr
; /* base reg */
1014 else if (GET_CODE (addr
) == PLUS
)
1016 rtx op0
= XEXP (addr
, 0);
1017 rtx op1
= XEXP (addr
, 1);
1018 enum rtx_code code0
= GET_CODE (op0
);
1019 enum rtx_code code1
= GET_CODE (op1
);
1021 if (code0
== REG
|| code0
== SUBREG
)
1023 if (code1
== REG
|| code1
== SUBREG
)
1025 indx
= op0
; /* index + base */
1031 base
= op0
; /* base + displacement */
1036 else if (code0
== MULT
)
1038 indx
= XEXP (op0
, 0);
1039 scale
= XEXP (op0
, 1);
1041 if (code1
== REG
|| code1
== SUBREG
)
1042 base
= op1
; /* index*scale + base */
1045 disp
= op1
; /* index*scale + disp */
1048 else if (code0
== PLUS
&& GET_CODE (XEXP (op0
, 0)) == MULT
)
1050 indx
= XEXP (XEXP (op0
, 0), 0); /* index*scale + base + disp */
1051 scale
= XEXP (XEXP (op0
, 0), 1);
1052 base
= XEXP (op0
, 1);
1056 else if (code0
== PLUS
)
1058 indx
= XEXP (op0
, 0); /* index + base + disp */
1059 base
= XEXP (op0
, 1);
1065 ADDR_INVALID ("PLUS subcode is not valid.\n", op0
);
1070 else if (GET_CODE (addr
) == MULT
)
1072 indx
= XEXP (addr
, 0); /* index*scale */
1073 scale
= XEXP (addr
, 1);
1077 disp
= addr
; /* displacement */
1079 /* Validate base register */
1082 if (GET_CODE (base
) == SUBREG
)
1084 if (GET_CODE (SUBREG_REG (base
)) != REG
|| SUBREG_WORD (base
) != 0)
1086 ADDR_INVALID ("Base SUBREG is not of a REG.\n", base
);
1090 base
= SUBREG_REG (base
);
1093 if (GET_CODE (base
) != REG
1094 || ( strict
&& !REG_OK_FOR_BASE_STRICT_P (base
))
1095 || (!strict
&& !REG_OK_FOR_BASE_NONSTRICT_P (base
)))
1097 ADDR_INVALID ("Base is not valid.\n", base
);
1102 /* Validate index register */
1105 if (GET_CODE (indx
) == SUBREG
)
1107 if (GET_CODE (SUBREG_REG (indx
)) != REG
|| SUBREG_WORD (indx
) != 0)
1109 ADDR_INVALID ("Index SUBREG is not of a REG.", indx
);
1113 indx
= SUBREG_REG (indx
);
1116 if (GET_CODE (indx
) != REG
1117 || ( strict
&& !REG_OK_FOR_INDEX_STRICT_P (indx
))
1118 || (!strict
&& !REG_OK_FOR_INDEX_NONSTRICT_P (indx
)))
1120 ADDR_INVALID ("Index is not valid.\n", indx
);
1125 abort (); /* scale w/o index illegal */
1127 /* Validate scale factor */
1130 HOST_WIDE_INT value
;
1132 if (GET_CODE (scale
) != CONST_INT
)
1134 ADDR_INVALID ("Scale is not valid.\n", scale
);
1138 value
= INTVAL (scale
);
1139 if (value
!= 1 && value
!= 2 && value
!= 4 && value
!= 8)
1141 ADDR_INVALID ("Scale is not a good multiplier.\n", scale
);
1146 /* Validate displacement */
1149 if (!CONSTANT_ADDRESS_P (disp
))
1151 ADDR_INVALID ("Displacement is not valid.\n", disp
);
1155 if (GET_CODE (disp
) == CONST_DOUBLE
)
1157 ADDR_INVALID ("Displacement is a const_double.\n", disp
);
1161 if (flag_pic
&& SYMBOLIC_CONST (disp
) && base
!= pic_offset_table_rtx
1162 && (indx
!= pic_offset_table_rtx
|| scale
!= NULL_RTX
))
1164 ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp
);
1168 if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp
)
1169 && (base
!= NULL_RTX
|| indx
!= NULL_RTX
))
1171 ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp
);
1176 if (TARGET_DEBUG_ADDR
)
1177 fprintf (stderr
, "Address is valid.\n");
1179 /* Everything looks valid, return true */
1184 /* Return a legitimate reference for ORIG (an address) using the
1185 register REG. If REG is 0, a new pseudo is generated.
1187 There are three types of references that must be handled:
1189 1. Global data references must load the address from the GOT, via
1190 the PIC reg. An insn is emitted to do this load, and the reg is
1193 2. Static data references must compute the address as an offset
1194 from the GOT, whose base is in the PIC reg. An insn is emitted to
1195 compute the address into a reg, and the reg is returned. Static
1196 data objects have SYMBOL_REF_FLAG set to differentiate them from
1197 global data objects.
1199 3. Constant pool addresses must be handled special. They are
1200 considered legitimate addresses, but only if not used with regs.
1201 When printed, the output routines know to print the reference with the
1202 PIC reg, even though the PIC reg doesn't appear in the RTL.
1204 GO_IF_LEGITIMATE_ADDRESS rejects symbolic references unless the PIC
1205 reg also appears in the address (except for constant pool references,
1208 "switch" statements also require special handling when generating
1209 PIC code. See comments by the `casesi' insn in i386.md for details. */
1212 legitimize_pic_address (orig
, reg
)
1219 if (GET_CODE (addr
) == SYMBOL_REF
|| GET_CODE (addr
) == LABEL_REF
)
1221 if (GET_CODE (addr
) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (addr
))
1226 reg
= gen_reg_rtx (Pmode
);
1228 if (GET_CODE (addr
) == SYMBOL_REF
&& SYMBOL_REF_FLAG (addr
))
1229 new = gen_rtx (PLUS
, Pmode
, pic_offset_table_rtx
, orig
);
1231 new = gen_rtx (MEM
, Pmode
,
1232 gen_rtx (PLUS
, Pmode
,
1233 pic_offset_table_rtx
, orig
));
1235 emit_move_insn (reg
, new);
1237 current_function_uses_pic_offset_table
= 1;
1240 else if (GET_CODE (addr
) == CONST
|| GET_CODE (addr
) == PLUS
)
1244 if (GET_CODE (addr
) == CONST
)
1246 addr
= XEXP (addr
, 0);
1247 if (GET_CODE (addr
) != PLUS
)
1251 if (XEXP (addr
, 0) == pic_offset_table_rtx
)
1255 reg
= gen_reg_rtx (Pmode
);
1257 base
= legitimize_pic_address (XEXP (addr
, 0), reg
);
1258 addr
= legitimize_pic_address (XEXP (addr
, 1),
1259 base
== reg
? NULL_RTX
: reg
);
1261 if (GET_CODE (addr
) == CONST_INT
)
1262 return plus_constant (base
, INTVAL (addr
));
1264 if (GET_CODE (addr
) == PLUS
&& CONSTANT_P (XEXP (addr
, 1)))
1266 base
= gen_rtx (PLUS
, Pmode
, base
, XEXP (addr
, 0));
1267 addr
= XEXP (addr
, 1);
1269 return gen_rtx (PLUS
, Pmode
, base
, addr
);
1275 /* Emit insns to move operands[1] into operands[0]. */
1278 emit_pic_move (operands
, mode
)
1280 enum machine_mode mode
;
1282 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
1284 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
1285 operands
[1] = (rtx
) force_reg (SImode
, operands
[1]);
1287 operands
[1] = legitimize_pic_address (operands
[1], temp
);
1291 /* Try machine-dependent ways of modifying an illegitimate address
1292 to be legitimate. If we find one, return the new, valid address.
1293 This macro is used in only one place: `memory_address' in explow.c.
1295 OLDX is the address as it was before break_out_memory_refs was called.
1296 In some cases it is useful to look at this to decide what needs to be done.
1298 MODE and WIN are passed so that this macro can use
1299 GO_IF_LEGITIMATE_ADDRESS.
1301 It is always safe for this macro to do nothing. It exists to recognize
1302 opportunities to optimize the output.
1304 For the 80386, we handle X+REG by loading X into a register R and
1305 using R+REG. R will go in a general reg and indexing will be used.
1306 However, if REG is a broken-out memory address or multiplication,
1307 nothing needs to be done because REG can certainly go in a general reg.
1309 When -fpic is used, special handling is needed for symbolic references.
1310 See comments by legitimize_pic_address in i386.c for details. */
1313 legitimize_address (x
, oldx
, mode
)
1316 enum machine_mode mode
;
1321 if (TARGET_DEBUG_ADDR
)
1323 fprintf (stderr
, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode
));
1327 if (flag_pic
&& SYMBOLIC_CONST (x
))
1328 return legitimize_pic_address (x
, 0);
1330 /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
1331 if (GET_CODE (x
) == ASHIFT
1332 && GET_CODE (XEXP (x
, 1)) == CONST_INT
1333 && (log
= (unsigned)exact_log2 (INTVAL (XEXP (x
, 1)))) < 4)
1336 x
= gen_rtx (MULT
, Pmode
,
1337 force_reg (Pmode
, XEXP (x
, 0)),
1338 GEN_INT (1 << log
));
1341 if (GET_CODE (x
) == PLUS
)
1343 /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
1344 if (GET_CODE (XEXP (x
, 0)) == ASHIFT
1345 && GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
1346 && (log
= (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x
, 0), 1)))) < 4)
1349 XEXP (x
, 0) = gen_rtx (MULT
, Pmode
,
1350 force_reg (Pmode
, XEXP (XEXP (x
, 0), 0)),
1351 GEN_INT (1 << log
));
1354 if (GET_CODE (XEXP (x
, 1)) == ASHIFT
1355 && GET_CODE (XEXP (XEXP (x
, 1), 1)) == CONST_INT
1356 && (log
= (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x
, 1), 1)))) < 4)
1359 XEXP (x
, 1) = gen_rtx (MULT
, Pmode
,
1360 force_reg (Pmode
, XEXP (XEXP (x
, 1), 0)),
1361 GEN_INT (1 << log
));
1364 /* Put multiply first if it isn't already */
1365 if (GET_CODE (XEXP (x
, 1)) == MULT
)
1367 rtx tmp
= XEXP (x
, 0);
1368 XEXP (x
, 0) = XEXP (x
, 1);
1373 /* Canonicalize (plus (mult (reg) (const)) (plus (reg) (const)))
1374 into (plus (plus (mult (reg) (const)) (reg)) (const)). This can be
1375 created by virtual register instantiation, register elimination, and
1376 similar optimizations. */
1377 if (GET_CODE (XEXP (x
, 0)) == MULT
&& GET_CODE (XEXP (x
, 1)) == PLUS
)
1380 x
= gen_rtx (PLUS
, Pmode
,
1381 gen_rtx (PLUS
, Pmode
, XEXP (x
, 0), XEXP (XEXP (x
, 1), 0)),
1382 XEXP (XEXP (x
, 1), 1));
1385 /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const)
1386 into (plus (plus (mult (reg) (const)) (reg)) (const)). */
1387 else if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
, 0)) == PLUS
1388 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == MULT
1389 && GET_CODE (XEXP (XEXP (x
, 0), 1)) == PLUS
1390 && CONSTANT_P (XEXP (x
, 1)))
1392 rtx constant
, other
;
1394 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
1396 constant
= XEXP (x
, 1);
1397 other
= XEXP (XEXP (XEXP (x
, 0), 1), 1);
1399 else if (GET_CODE (XEXP (XEXP (XEXP (x
, 0), 1), 1)) == CONST_INT
)
1401 constant
= XEXP (XEXP (XEXP (x
, 0), 1), 1);
1402 other
= XEXP (x
, 1);
1410 x
= gen_rtx (PLUS
, Pmode
,
1411 gen_rtx (PLUS
, Pmode
, XEXP (XEXP (x
, 0), 0),
1412 XEXP (XEXP (XEXP (x
, 0), 1), 0)),
1413 plus_constant (other
, INTVAL (constant
)));
1417 if (changed
&& legitimate_address_p (mode
, x
, FALSE
))
1420 if (GET_CODE (XEXP (x
, 0)) == MULT
)
1423 XEXP (x
, 0) = force_operand (XEXP (x
, 0), 0);
1426 if (GET_CODE (XEXP (x
, 1)) == MULT
)
1429 XEXP (x
, 1) = force_operand (XEXP (x
, 1), 0);
1433 && GET_CODE (XEXP (x
, 1)) == REG
1434 && GET_CODE (XEXP (x
, 0)) == REG
)
1437 if (flag_pic
&& SYMBOLIC_CONST (XEXP (x
, 1)))
1440 x
= legitimize_pic_address (x
, 0);
1443 if (changed
&& legitimate_address_p (mode
, x
, FALSE
))
1446 if (GET_CODE (XEXP (x
, 0)) == REG
)
1448 register rtx temp
= gen_reg_rtx (Pmode
);
1449 register rtx val
= force_operand (XEXP (x
, 1), temp
);
1451 emit_move_insn (temp
, val
);
1457 else if (GET_CODE (XEXP (x
, 1)) == REG
)
1459 register rtx temp
= gen_reg_rtx (Pmode
);
1460 register rtx val
= force_operand (XEXP (x
, 0), temp
);
1462 emit_move_insn (temp
, val
);
1473 /* Print an integer constant expression in assembler syntax. Addition
1474 and subtraction are the only arithmetic that may appear in these
1475 expressions. FILE is the stdio stream to write to, X is the rtx, and
1476 CODE is the operand print code from the output string. */
1479 output_pic_addr_const (file
, x
, code
)
1486 switch (GET_CODE (x
))
1497 if (GET_CODE (x
) == SYMBOL_REF
)
1498 assemble_name (file
, XSTR (x
, 0));
1501 ASM_GENERATE_INTERNAL_LABEL (buf
, "L",
1502 CODE_LABEL_NUMBER (XEXP (x
, 0)));
1503 assemble_name (asm_out_file
, buf
);
1506 if (GET_CODE (x
) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x
))
1507 fprintf (file
, "@GOTOFF(%%ebx)");
1508 else if (code
== 'P')
1509 fprintf (file
, "@PLT");
1510 else if (GET_CODE (x
) == LABEL_REF
|| ! SYMBOL_REF_FLAG (x
))
1511 fprintf (file
, "@GOT");
1513 fprintf (file
, "@GOTOFF");
1518 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
1519 assemble_name (asm_out_file
, buf
);
1523 fprintf (file
, "%d", INTVAL (x
));
1527 /* This used to output parentheses around the expression,
1528 but that does not work on the 386 (either ATT or BSD assembler). */
1529 output_pic_addr_const (file
, XEXP (x
, 0), code
);
1533 if (GET_MODE (x
) == VOIDmode
)
1535 /* We can use %d if the number is <32 bits and positive. */
1536 if (CONST_DOUBLE_HIGH (x
) || CONST_DOUBLE_LOW (x
) < 0)
1537 fprintf (file
, "0x%x%08x",
1538 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
1540 fprintf (file
, "%d", CONST_DOUBLE_LOW (x
));
1543 /* We can't handle floating point constants;
1544 PRINT_OPERAND must handle them. */
1545 output_operand_lossage ("floating constant misused");
1549 /* Some assemblers need integer constants to appear last (eg masm). */
1550 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
1552 output_pic_addr_const (file
, XEXP (x
, 1), code
);
1553 if (INTVAL (XEXP (x
, 0)) >= 0)
1554 fprintf (file
, "+");
1555 output_pic_addr_const (file
, XEXP (x
, 0), code
);
1559 output_pic_addr_const (file
, XEXP (x
, 0), code
);
1560 if (INTVAL (XEXP (x
, 1)) >= 0)
1561 fprintf (file
, "+");
1562 output_pic_addr_const (file
, XEXP (x
, 1), code
);
1567 output_pic_addr_const (file
, XEXP (x
, 0), code
);
1568 fprintf (file
, "-");
1569 output_pic_addr_const (file
, XEXP (x
, 1), code
);
1573 output_operand_lossage ("invalid expression as operand");
1578 f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
1579 D,L,W,B,Q,S -- print the opcode suffix for specified size of operand.
1580 R -- print the prefix for register names.
1581 z -- print the opcode suffix for the size of the current operand.
1582 * -- print a star (in certain assembler syntax)
1583 w -- print the operand as if it's a "word" (HImode) even if it isn't.
1584 c -- don't print special prefixes before constant operands.
1588 print_operand (file
, x
, code
)
1603 PUT_OP_SIZE (code
, 'l', file
);
1607 PUT_OP_SIZE (code
, 'w', file
);
1611 PUT_OP_SIZE (code
, 'b', file
);
1615 PUT_OP_SIZE (code
, 'l', file
);
1619 PUT_OP_SIZE (code
, 's', file
);
1623 PUT_OP_SIZE (code
, 't', file
);
1627 /* 387 opcodes don't get size suffixes if the operands are
1630 if (STACK_REG_P (x
))
1633 /* this is the size of op from size of operand */
1634 switch (GET_MODE_SIZE (GET_MODE (x
)))
1637 PUT_OP_SIZE ('B', 'b', file
);
1641 PUT_OP_SIZE ('W', 'w', file
);
1645 if (GET_MODE (x
) == SFmode
)
1647 PUT_OP_SIZE ('S', 's', file
);
1651 PUT_OP_SIZE ('L', 'l', file
);
1655 PUT_OP_SIZE ('T', 't', file
);
1659 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_INT
)
1661 #ifdef GAS_MNEMONICS
1662 PUT_OP_SIZE ('Q', 'q', file
);
1665 PUT_OP_SIZE ('Q', 'l', file
); /* Fall through */
1669 PUT_OP_SIZE ('Q', 'l', file
);
1685 sprintf (str
, "invalid operand code `%c'", code
);
1686 output_operand_lossage (str
);
1690 if (GET_CODE (x
) == REG
)
1692 PRINT_REG (x
, code
, file
);
1694 else if (GET_CODE (x
) == MEM
)
1696 PRINT_PTR (x
, file
);
1697 if (CONSTANT_ADDRESS_P (XEXP (x
, 0)))
1700 output_pic_addr_const (file
, XEXP (x
, 0), code
);
1702 output_addr_const (file
, XEXP (x
, 0));
1705 output_address (XEXP (x
, 0));
1707 else if (GET_CODE (x
) == CONST_DOUBLE
&& GET_MODE (x
) == SFmode
)
1709 REAL_VALUE_TYPE r
; long l
;
1710 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1711 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1712 PRINT_IMMED_PREFIX (file
);
1713 fprintf (file
, "0x%x", l
);
1715 /* These float cases don't actually occur as immediate operands. */
1716 else if (GET_CODE (x
) == CONST_DOUBLE
&& GET_MODE (x
) == DFmode
)
1718 REAL_VALUE_TYPE r
; char dstr
[30];
1719 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1720 REAL_VALUE_TO_DECIMAL (r
, "%.22e", dstr
);
1721 fprintf (file
, "%s", dstr
);
1723 else if (GET_CODE (x
) == CONST_DOUBLE
&& GET_MODE (x
) == XFmode
)
1725 REAL_VALUE_TYPE r
; char dstr
[30];
1726 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1727 REAL_VALUE_TO_DECIMAL (r
, "%.22e", dstr
);
1728 fprintf (file
, "%s", dstr
);
1734 if (GET_CODE (x
) == CONST_INT
|| GET_CODE (x
) == CONST_DOUBLE
)
1735 PRINT_IMMED_PREFIX (file
);
1736 else if (GET_CODE (x
) == CONST
|| GET_CODE (x
) == SYMBOL_REF
1737 || GET_CODE (x
) == LABEL_REF
)
1738 PRINT_OFFSET_PREFIX (file
);
1741 output_pic_addr_const (file
, x
, code
);
1743 output_addr_const (file
, x
);
1747 /* Print a memory operand whose address is ADDR. */
1750 print_operand_address (file
, addr
)
1754 register rtx reg1
, reg2
, breg
, ireg
;
1757 switch (GET_CODE (addr
))
1761 fprintf (file
, "%se", RP
);
1762 fputs (hi_reg_name
[REGNO (addr
)], file
);
1772 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0)))
1774 offset
= XEXP (addr
, 0);
1775 addr
= XEXP (addr
, 1);
1777 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1)))
1779 offset
= XEXP (addr
, 1);
1780 addr
= XEXP (addr
, 0);
1782 if (GET_CODE (addr
) != PLUS
) ;
1783 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
1785 reg1
= XEXP (addr
, 0);
1786 addr
= XEXP (addr
, 1);
1788 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
1790 reg1
= XEXP (addr
, 1);
1791 addr
= XEXP (addr
, 0);
1793 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
1795 reg1
= XEXP (addr
, 0);
1796 addr
= XEXP (addr
, 1);
1798 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
1800 reg1
= XEXP (addr
, 1);
1801 addr
= XEXP (addr
, 0);
1803 if (GET_CODE (addr
) == REG
|| GET_CODE (addr
) == MULT
)
1805 if (reg1
== 0) reg1
= addr
;
1811 if (addr
!= 0) abort ();
1814 if ((reg1
&& GET_CODE (reg1
) == MULT
)
1815 || (reg2
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2
))))
1820 else if (reg1
!= 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1
)))
1826 if (ireg
!= 0 || breg
!= 0)
1832 if (GET_CODE (addr
) == LABEL_REF
)
1833 output_asm_label (addr
);
1837 output_pic_addr_const (file
, addr
, 0);
1839 output_addr_const (file
, addr
);
1843 if (ireg
!= 0 && GET_CODE (ireg
) == MULT
)
1845 scale
= INTVAL (XEXP (ireg
, 1));
1846 ireg
= XEXP (ireg
, 0);
1849 /* The stack pointer can only appear as a base register,
1850 never an index register, so exchange the regs if it is wrong. */
1852 if (scale
== 1 && ireg
&& REGNO (ireg
) == STACK_POINTER_REGNUM
)
1861 /* output breg+ireg*scale */
1862 PRINT_B_I_S (breg
, ireg
, scale
, file
);
1869 if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
1871 scale
= INTVAL (XEXP (addr
, 0));
1872 ireg
= XEXP (addr
, 1);
1876 scale
= INTVAL (XEXP (addr
, 1));
1877 ireg
= XEXP (addr
, 0);
1879 output_addr_const (file
, const0_rtx
);
1880 PRINT_B_I_S ((rtx
) 0, ireg
, scale
, file
);
1885 if (GET_CODE (addr
) == CONST_INT
1886 && INTVAL (addr
) < 0x8000
1887 && INTVAL (addr
) >= -0x8000)
1888 fprintf (file
, "%d", INTVAL (addr
));
1892 output_pic_addr_const (file
, addr
, 0);
1894 output_addr_const (file
, addr
);
1899 /* Set the cc_status for the results of an insn whose pattern is EXP.
1900 On the 80386, we assume that only test and compare insns, as well
1901 as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT,
1902 ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully.
1903 Also, we assume that jumps, moves and sCOND don't affect the condition
1904 codes. All else clobbers the condition codes, by assumption.
1906 We assume that ALL integer add, minus, etc. instructions effect the
1907 condition codes. This MUST be consistent with i386.md.
1909 We don't record any float test or compare - the redundant test &
1910 compare check in final.c does not handle stack-like regs correctly. */
1913 notice_update_cc (exp
)
1916 if (GET_CODE (exp
) == SET
)
1918 /* Jumps do not alter the cc's. */
1919 if (SET_DEST (exp
) == pc_rtx
)
1921 /* Moving register or memory into a register:
1922 it doesn't alter the cc's, but it might invalidate
1923 the RTX's which we remember the cc's came from.
1924 (Note that moving a constant 0 or 1 MAY set the cc's). */
1925 if (REG_P (SET_DEST (exp
))
1926 && (REG_P (SET_SRC (exp
)) || GET_CODE (SET_SRC (exp
)) == MEM
1927 || GET_RTX_CLASS (GET_CODE (SET_SRC (exp
))) == '<'))
1929 if (cc_status
.value1
1930 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
))
1931 cc_status
.value1
= 0;
1932 if (cc_status
.value2
1933 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
))
1934 cc_status
.value2
= 0;
1937 /* Moving register into memory doesn't alter the cc's.
1938 It may invalidate the RTX's which we remember the cc's came from. */
1939 if (GET_CODE (SET_DEST (exp
)) == MEM
1940 && (REG_P (SET_SRC (exp
))
1941 || GET_RTX_CLASS (GET_CODE (SET_SRC (exp
))) == '<'))
1943 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == MEM
)
1944 cc_status
.value1
= 0;
1945 if (cc_status
.value2
&& GET_CODE (cc_status
.value2
) == MEM
)
1946 cc_status
.value2
= 0;
1949 /* Function calls clobber the cc's. */
1950 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1955 /* Tests and compares set the cc's in predictable ways. */
1956 else if (SET_DEST (exp
) == cc0_rtx
)
1959 cc_status
.value1
= SET_SRC (exp
);
1962 /* Certain instructions effect the condition codes. */
1963 else if (GET_MODE (SET_SRC (exp
)) == SImode
1964 || GET_MODE (SET_SRC (exp
)) == HImode
1965 || GET_MODE (SET_SRC (exp
)) == QImode
)
1966 switch (GET_CODE (SET_SRC (exp
)))
1968 case ASHIFTRT
: case LSHIFTRT
:
1970 /* Shifts on the 386 don't set the condition codes if the
1971 shift count is zero. */
1972 if (GET_CODE (XEXP (SET_SRC (exp
), 1)) != CONST_INT
)
1977 /* We assume that the CONST_INT is non-zero (this rtx would
1978 have been deleted if it were zero. */
1980 case PLUS
: case MINUS
: case NEG
:
1981 case AND
: case IOR
: case XOR
:
1982 cc_status
.flags
= CC_NO_OVERFLOW
;
1983 cc_status
.value1
= SET_SRC (exp
);
1984 cc_status
.value2
= SET_DEST (exp
);
1995 else if (GET_CODE (exp
) == PARALLEL
1996 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
1998 if (SET_DEST (XVECEXP (exp
, 0, 0)) == pc_rtx
)
2000 if (SET_DEST (XVECEXP (exp
, 0, 0)) == cc0_rtx
)
2003 if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp
, 0, 0))))
2004 cc_status
.flags
|= CC_IN_80387
;
2006 cc_status
.value1
= SET_SRC (XVECEXP (exp
, 0, 0));
2017 /* Split one or more DImode RTL references into pairs of SImode
2018 references. The RTL can be REG, offsettable MEM, integer constant, or
2019 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
2020 split and "num" is its length. lo_half and hi_half are output arrays
2021 that parallel "operands". */
2024 split_di (operands
, num
, lo_half
, hi_half
)
2027 rtx lo_half
[], hi_half
[];
2031 if (GET_CODE (operands
[num
]) == REG
)
2033 lo_half
[num
] = gen_rtx (REG
, SImode
, REGNO (operands
[num
]));
2034 hi_half
[num
] = gen_rtx (REG
, SImode
, REGNO (operands
[num
]) + 1);
2036 else if (CONSTANT_P (operands
[num
]))
2038 split_double (operands
[num
], &lo_half
[num
], &hi_half
[num
]);
2040 else if (offsettable_memref_p (operands
[num
]))
2042 lo_half
[num
] = operands
[num
];
2043 hi_half
[num
] = adj_offsettable_operand (operands
[num
], 4);
2050 /* Return 1 if this is a valid binary operation on a 387.
2051 OP is the expression matched, and MODE is its mode. */
2054 binary_387_op (op
, mode
)
2056 enum machine_mode mode
;
2058 if (mode
!= VOIDmode
&& mode
!= GET_MODE (op
))
2061 switch (GET_CODE (op
))
2067 return GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
;
2075 /* Return 1 if this is a valid shift or rotate operation on a 386.
2076 OP is the expression matched, and MODE is its mode. */
2081 enum machine_mode mode
;
2083 rtx operand
= XEXP (op
, 0);
2085 if (mode
!= VOIDmode
&& mode
!= GET_MODE (op
))
2088 if (GET_MODE (operand
) != GET_MODE (op
)
2089 || GET_MODE_CLASS (GET_MODE (op
)) != MODE_INT
)
2092 return (GET_CODE (op
) == ASHIFT
2093 || GET_CODE (op
) == ASHIFTRT
2094 || GET_CODE (op
) == LSHIFTRT
2095 || GET_CODE (op
) == ROTATE
2096 || GET_CODE (op
) == ROTATERT
);
2099 /* Return 1 if OP is COMPARE rtx with mode VOIDmode.
2100 MODE is not used. */
2103 VOIDmode_compare_op (op
, mode
)
2105 enum machine_mode mode
;
2107 return GET_CODE (op
) == COMPARE
&& GET_MODE (op
) == VOIDmode
;
2110 /* Output code to perform a 387 binary operation in INSN, one of PLUS,
2111 MINUS, MULT or DIV. OPERANDS are the insn operands, where operands[3]
2112 is the expression of the binary operation. The output may either be
2113 emitted here, or returned to the caller, like all output_* functions.
2115 There is no guarantee that the operands are the same mode, as they
2116 might be within FLOAT or FLOAT_EXTEND expressions. */
2119 output_387_binary_op (insn
, operands
)
2125 static char buf
[100];
2127 switch (GET_CODE (operands
[3]))
2130 if (GET_MODE_CLASS (GET_MODE (operands
[1])) == MODE_INT
2131 || GET_MODE_CLASS (GET_MODE (operands
[2])) == MODE_INT
)
2138 if (GET_MODE_CLASS (GET_MODE (operands
[1])) == MODE_INT
2139 || GET_MODE_CLASS (GET_MODE (operands
[2])) == MODE_INT
)
2146 if (GET_MODE_CLASS (GET_MODE (operands
[1])) == MODE_INT
2147 || GET_MODE_CLASS (GET_MODE (operands
[2])) == MODE_INT
)
2154 if (GET_MODE_CLASS (GET_MODE (operands
[1])) == MODE_INT
2155 || GET_MODE_CLASS (GET_MODE (operands
[2])) == MODE_INT
)
2165 strcpy (buf
, base_op
);
2167 switch (GET_CODE (operands
[3]))
2171 if (REG_P (operands
[2]) && REGNO (operands
[0]) == REGNO (operands
[2]))
2174 operands
[2] = operands
[1];
2178 if (GET_CODE (operands
[2]) == MEM
)
2179 return strcat (buf
, AS1 (%z2
,%2));
2181 if (NON_STACK_REG_P (operands
[1]))
2183 output_op_from_reg (operands
[1], strcat (buf
, AS1 (%z0
,%1)));
2186 else if (NON_STACK_REG_P (operands
[2]))
2188 output_op_from_reg (operands
[2], strcat (buf
, AS1 (%z0
,%1)));
2192 if (find_regno_note (insn
, REG_DEAD
, REGNO (operands
[2])))
2193 return strcat (buf
, AS2 (p
,%2,%0));
2195 if (STACK_TOP_P (operands
[0]))
2196 return strcat (buf
, AS2 (,%y2
,%0));
2198 return strcat (buf
, AS2 (,%2,%0));
2202 if (GET_CODE (operands
[1]) == MEM
)
2203 return strcat (buf
, AS1 (r
%z1
,%1));
2205 if (GET_CODE (operands
[2]) == MEM
)
2206 return strcat (buf
, AS1 (%z2
,%2));
2208 if (NON_STACK_REG_P (operands
[1]))
2210 output_op_from_reg (operands
[1], strcat (buf
, AS1 (r
%z0
,%1)));
2213 else if (NON_STACK_REG_P (operands
[2]))
2215 output_op_from_reg (operands
[2], strcat (buf
, AS1 (%z0
,%1)));
2219 if (! STACK_REG_P (operands
[1]) || ! STACK_REG_P (operands
[2]))
2222 if (find_regno_note (insn
, REG_DEAD
, REGNO (operands
[2])))
2223 return strcat (buf
, AS2 (rp
,%2,%0));
2225 if (find_regno_note (insn
, REG_DEAD
, REGNO (operands
[1])))
2226 return strcat (buf
, AS2 (p
,%1,%0));
2228 if (STACK_TOP_P (operands
[0]))
2230 if (STACK_TOP_P (operands
[1]))
2231 return strcat (buf
, AS2 (,%y2
,%0));
2233 return strcat (buf
, AS2 (r
,%y1
,%0));
2235 else if (STACK_TOP_P (operands
[1]))
2236 return strcat (buf
, AS2 (,%1,%0));
2238 return strcat (buf
, AS2 (r
,%2,%0));
2245 /* Output code for INSN to convert a float to a signed int. OPERANDS
2246 are the insn operands. The output may be SFmode or DFmode and the
2247 input operand may be SImode or DImode. As a special case, make sure
2248 that the 387 stack top dies if the output mode is DImode, because the
2249 hardware requires this. */
2252 output_fix_trunc (insn
, operands
)
2256 int stack_top_dies
= find_regno_note (insn
, REG_DEAD
, FIRST_STACK_REG
) != 0;
2259 if (! STACK_TOP_P (operands
[1]) ||
2260 (GET_MODE (operands
[0]) == DImode
&& ! stack_top_dies
))
2263 xops
[0] = GEN_INT (12);
2264 xops
[1] = operands
[4];
2266 output_asm_insn (AS1 (fnstc
%W2
,%2), operands
);
2267 output_asm_insn (AS2 (mov
%L2
,%2,%4), operands
);
2268 output_asm_insn (AS2 (mov
%B1
,%0,%h1
), xops
);
2269 output_asm_insn (AS2 (mov
%L4
,%4,%3), operands
);
2270 output_asm_insn (AS1 (fldc
%W3
,%3), operands
);
2272 if (NON_STACK_REG_P (operands
[0]))
2273 output_to_reg (operands
[0], stack_top_dies
);
2274 else if (GET_CODE (operands
[0]) == MEM
)
2277 output_asm_insn (AS1 (fistp
%z0
,%0), operands
);
2279 output_asm_insn (AS1 (fist
%z0
,%0), operands
);
2284 return AS1 (fldc
%W2
,%2);
2287 /* Output code for INSN to compare OPERANDS. The two operands might
2288 not have the same mode: one might be within a FLOAT or FLOAT_EXTEND
2289 expression. If the compare is in mode CCFPEQmode, use an opcode that
2290 will not fault if a qNaN is present. */
2293 output_float_compare (insn
, operands
)
2298 rtx body
= XVECEXP (PATTERN (insn
), 0, 0);
2299 int unordered_compare
= GET_MODE (SET_SRC (body
)) == CCFPEQmode
;
2301 if (! STACK_TOP_P (operands
[0]))
2304 stack_top_dies
= find_regno_note (insn
, REG_DEAD
, FIRST_STACK_REG
) != 0;
2306 if (STACK_REG_P (operands
[1])
2308 && find_regno_note (insn
, REG_DEAD
, REGNO (operands
[1]))
2309 && REGNO (operands
[1]) != FIRST_STACK_REG
)
2311 /* If both the top of the 387 stack dies, and the other operand
2312 is also a stack register that dies, then this must be a
2313 `fcompp' float compare */
2315 if (unordered_compare
)
2316 output_asm_insn ("fucompp", operands
);
2318 output_asm_insn ("fcompp", operands
);
2322 static char buf
[100];
2324 /* Decide if this is the integer or float compare opcode, or the
2325 unordered float compare. */
2327 if (unordered_compare
)
2328 strcpy (buf
, "fucom");
2329 else if (GET_MODE_CLASS (GET_MODE (operands
[1])) == MODE_FLOAT
)
2330 strcpy (buf
, "fcom");
2332 strcpy (buf
, "ficom");
2334 /* Modify the opcode if the 387 stack is to be popped. */
2339 if (NON_STACK_REG_P (operands
[1]))
2340 output_op_from_reg (operands
[1], strcat (buf
, AS1 (%z0
,%1)));
2342 output_asm_insn (strcat (buf
, AS1 (%z1
,%y1
)), operands
);
2345 /* Now retrieve the condition code. */
2347 return output_fp_cc0_set (insn
);
2350 /* Output opcodes to transfer the results of FP compare or test INSN
2351 from the FPU to the CPU flags. If TARGET_IEEE_FP, ensure that if the
2352 result of the compare or test is unordered, no comparison operator
2353 succeeds except NE. Return an output template, if any. */
2356 output_fp_cc0_set (insn
)
2360 rtx unordered_label
;
2364 xops
[0] = gen_rtx (REG
, HImode
, 0);
2365 output_asm_insn (AS1 (fnsts
%W0
,%0), xops
);
2367 if (! TARGET_IEEE_FP
)
2370 next
= next_cc0_user (insn
);
2371 if (next
== NULL_RTX
)
2374 if (GET_CODE (next
) == JUMP_INSN
2375 && GET_CODE (PATTERN (next
)) == SET
2376 && SET_DEST (PATTERN (next
)) == pc_rtx
2377 && GET_CODE (SET_SRC (PATTERN (next
))) == IF_THEN_ELSE
)
2379 code
= GET_CODE (XEXP (SET_SRC (PATTERN (next
)), 0));
2381 else if (GET_CODE (PATTERN (next
)) == SET
)
2383 code
= GET_CODE (SET_SRC (PATTERN (next
)));
2388 xops
[0] = gen_rtx (REG
, QImode
, 0);
2393 xops
[1] = GEN_INT (0x45);
2394 output_asm_insn (AS2 (and%B0
,%1,%h0
), xops
);
2399 xops
[1] = GEN_INT (0x45);
2400 xops
[2] = GEN_INT (0x01);
2401 output_asm_insn (AS2 (and%B0
,%1,%h0
), xops
);
2402 output_asm_insn (AS2 (cmp
%B0
,%2,%h0
), xops
);
2407 xops
[1] = GEN_INT (0x05);
2408 output_asm_insn (AS2 (and%B0
,%1,%h0
), xops
);
2413 xops
[1] = GEN_INT (0x45);
2414 xops
[2] = GEN_INT (0x40);
2415 output_asm_insn (AS2 (and%B0
,%1,%h0
), xops
);
2416 output_asm_insn (AS1 (dec
%B0
,%h0
), xops
);
2417 output_asm_insn (AS2 (cmp
%B0
,%2,%h0
), xops
);
2422 xops
[1] = GEN_INT (0x45);
2423 xops
[2] = GEN_INT (0x40);
2424 output_asm_insn (AS2 (and%B0
,%1,%h0
), xops
);
2425 output_asm_insn (AS2 (cmp
%B0
,%2,%h0
), xops
);
2430 xops
[1] = GEN_INT (0x44);
2431 xops
[2] = GEN_INT (0x40);
2432 output_asm_insn (AS2 (and%B0
,%1,%h0
), xops
);
2433 output_asm_insn (AS2 (xor%B0
,%2,%h0
), xops
);
2447 #define MAX_386_STACK_LOCALS 2
2449 static rtx i386_stack_locals
[(int) MAX_MACHINE_MODE
][MAX_386_STACK_LOCALS
];
2451 /* Define the structure for the machine field in struct function. */
2452 struct machine_function
2454 rtx i386_stack_locals
[(int) MAX_MACHINE_MODE
][MAX_386_STACK_LOCALS
];
2457 /* Functions to save and restore i386_stack_locals.
2458 These will be called, via pointer variables,
2459 from push_function_context and pop_function_context. */
2462 save_386_machine_status (p
)
2465 p
->machine
= (struct machine_function
*) xmalloc (sizeof i386_stack_locals
);
2466 bcopy (i386_stack_locals
, p
->machine
->i386_stack_locals
,
2467 sizeof i386_stack_locals
);
2471 restore_386_machine_status (p
)
2474 bcopy (p
->machine
->i386_stack_locals
, i386_stack_locals
,
2475 sizeof i386_stack_locals
);
2479 /* Clear stack slot assignments remembered from previous functions.
2480 This is called from INIT_EXPANDERS once before RTL is emitted for each
2484 clear_386_stack_locals ()
2486 enum machine_mode mode
;
2489 for (mode
= VOIDmode
; (int) mode
< (int) MAX_MACHINE_MODE
;
2490 mode
= (enum machine_mode
) ((int) mode
+ 1))
2491 for (n
= 0; n
< MAX_386_STACK_LOCALS
; n
++)
2492 i386_stack_locals
[(int) mode
][n
] = NULL_RTX
;
2494 /* Arrange to save and restore i386_stack_locals around nested functions. */
2495 save_machine_status
= save_386_machine_status
;
2496 restore_machine_status
= restore_386_machine_status
;
2499 /* Return a MEM corresponding to a stack slot with mode MODE.
2500 Allocate a new slot if necessary.
2502 The RTL for a function can have several slots available: N is
2503 which slot to use. */
2506 assign_386_stack_local (mode
, n
)
2507 enum machine_mode mode
;
2510 if (n
< 0 || n
>= MAX_386_STACK_LOCALS
)
2513 if (i386_stack_locals
[(int) mode
][n
] == NULL_RTX
)
2514 i386_stack_locals
[(int) mode
][n
]
2515 = assign_stack_local (mode
, GET_MODE_SIZE (mode
), 0);
2517 return i386_stack_locals
[(int) mode
][n
];