1 /* Subroutines for insn-output.c for Intel 860
2 Copyright (C) 1989, 1991, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
6 Written by Richard Stallman (rms@ai.mit.edu).
8 Hacked substantially by Ron Guilmette (rfg@netcom.com) to cater
9 to the whims of the System V Release 4 assembler.
11 This file is part of GNU CC.
13 GNU CC is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2, or (at your option)
18 GNU CC is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with GNU CC; see the file COPYING. If not, write to
25 the Free Software Foundation, 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA. */
35 #include "hard-reg-set.h"
37 #include "insn-config.h"
38 #include "conditions.h"
41 #include "insn-attr.h"
46 #include "target-def.h"
48 static rtx find_addr_reg
PARAMS ((rtx
));
49 static int reg_clobbered_p
PARAMS ((rtx
, rtx
));
50 static const char *singlemove_string
PARAMS ((rtx
*));
51 static const char *load_opcode
PARAMS ((enum machine_mode
, const char *, rtx
));
52 static const char *store_opcode
PARAMS ((enum machine_mode
, const char *, rtx
));
53 static void output_size_for_block_move
PARAMS ((rtx
, rtx
, rtx
));
55 #ifndef I860_REG_PREFIX
56 #define I860_REG_PREFIX ""
59 const char *i860_reg_prefix
= I860_REG_PREFIX
;
61 /* Save information from a "cmpxx" operation until the branch is emitted. */
63 rtx i860_compare_op0
, i860_compare_op1
;
65 /* Initialize the GCC target structure. */
67 struct gcc_target target
= TARGET_INITIALIZER
;
69 /* Return non-zero if this pattern, can be evaluated safely, even if it
72 safe_insn_src_p (op
, mode
)
74 enum machine_mode mode
;
76 /* Just experimenting. */
78 /* No floating point src is safe if it contains an arithmetic
79 operation, since that operation may trap. */
80 switch (GET_CODE (op
))
92 return CONSTANT_ADDRESS_P (XEXP (op
, 0));
94 /* We never need to negate or complement constants. */
96 return (mode
!= SFmode
&& mode
!= DFmode
);
113 return (mode
!= SFmode
&& mode
!= DFmode
);
120 if ((GET_CODE (XEXP (op
, 0)) == CONST_INT
&& ! SMALL_INT (XEXP (op
, 0)))
121 || (GET_CODE (XEXP (op
, 1)) == CONST_INT
&& ! SMALL_INT (XEXP (op
, 1))))
130 /* Return 1 if REG is clobbered in IN.
131 Return 2 if REG is used in IN.
132 Return 3 if REG is both used and clobbered in IN.
133 Return 0 if neither. */
136 reg_clobbered_p (reg
, in
)
140 register enum rtx_code code
;
145 code
= GET_CODE (in
);
147 if (code
== SET
|| code
== CLOBBER
)
149 rtx dest
= SET_DEST (in
);
153 while (GET_CODE (dest
) == STRICT_LOW_PART
154 || GET_CODE (dest
) == SUBREG
155 || GET_CODE (dest
) == SIGN_EXTRACT
156 || GET_CODE (dest
) == ZERO_EXTRACT
)
157 dest
= XEXP (dest
, 0);
161 else if (GET_CODE (dest
) == REG
162 && refers_to_regno_p (REGNO (reg
),
163 REGNO (reg
) + HARD_REGNO_NREGS (reg
, GET_MODE (reg
)),
167 /* Anything that sets just part of the register
168 is considered using as well as setting it.
169 But note that a straight SUBREG of a single-word value
170 clobbers the entire value. */
171 if (dest
!= SET_DEST (in
)
172 && ! (GET_CODE (SET_DEST (in
)) == SUBREG
173 || UNITS_PER_WORD
>= GET_MODE_SIZE (GET_MODE (dest
))))
180 used
= refers_to_regno_p (REGNO (reg
),
181 REGNO (reg
) + HARD_REGNO_NREGS (reg
, GET_MODE (reg
)),
184 used
= refers_to_regno_p (REGNO (reg
),
185 REGNO (reg
) + HARD_REGNO_NREGS (reg
, GET_MODE (reg
)),
189 return set
+ used
* 2;
192 if (refers_to_regno_p (REGNO (reg
),
193 REGNO (reg
) + HARD_REGNO_NREGS (reg
, GET_MODE (reg
)),
199 /* Return non-zero if OP can be written to without screwing up
200 GCC's model of what's going on. It is assumed that this operand
201 appears in the dest position of a SET insn in a conditional
202 branch's delay slot. AFTER is the label to start looking from. */
204 operand_clobbered_before_used_after (op
, after
)
208 /* Just experimenting. */
209 if (GET_CODE (op
) == CC0
)
211 if (GET_CODE (op
) == REG
)
215 if (op
== stack_pointer_rtx
)
218 /* Scan forward from the label, to see if the value of OP
219 is clobbered before the first use. */
221 for (insn
= NEXT_INSN (after
); insn
; insn
= NEXT_INSN (insn
))
223 if (GET_CODE (insn
) == NOTE
)
225 if (GET_CODE (insn
) == INSN
226 || GET_CODE (insn
) == JUMP_INSN
227 || GET_CODE (insn
) == CALL_INSN
)
229 switch (reg_clobbered_p (op
, PATTERN (insn
)))
239 /* If we reach another label without clobbering OP,
240 then we cannot safely write it here. */
241 else if (GET_CODE (insn
) == CODE_LABEL
)
243 if (GET_CODE (insn
) == JUMP_INSN
)
245 if (condjump_p (insn
))
247 /* This is a jump insn which has already
248 been mangled. We can't tell what it does. */
249 if (GET_CODE (PATTERN (insn
)) == PARALLEL
)
251 if (! JUMP_LABEL (insn
))
253 /* Keep following jumps. */
254 insn
= JUMP_LABEL (insn
);
260 /* In both of these cases, the first insn executed
261 for this op will be a orh whatever%h,%?r0,%?r31,
262 which is tolerable. */
263 if (GET_CODE (op
) == MEM
)
264 return (CONSTANT_ADDRESS_P (XEXP (op
, 0)));
269 /* Return non-zero if this pattern, as a source to a "SET",
270 is known to yield an instruction of unit size. */
272 single_insn_src_p (op
, mode
)
274 enum machine_mode mode
;
276 switch (GET_CODE (op
))
279 /* This is not always a single insn src, technically,
280 but output_delayed_branch knows how to deal with it. */
285 /* This is not a single insn src, technically,
286 but output_delayed_branch knows how to deal with it. */
295 /* We never need to negate or complement constants. */
297 return (mode
!= DFmode
);
304 /* Detect cases that require multiple instructions. */
305 if (CONSTANT_P (XEXP (op
, 1))
306 && !(GET_CODE (XEXP (op
, 1)) == CONST_INT
307 && SMALL_INT (XEXP (op
, 1))))
319 /* Not doing floating point, since they probably
320 take longer than the branch slot they might fill. */
321 return (mode
!= SFmode
&& mode
!= DFmode
);
324 if (GET_CODE (XEXP (op
, 1)) == NOT
)
326 rtx arg
= XEXP (XEXP (op
, 1), 0);
328 && !(GET_CODE (arg
) == CONST_INT
330 || (INTVAL (arg
) & 0xffff) == 0)))
335 /* Both small and round numbers take one instruction;
337 if (CONSTANT_P (XEXP (op
, 1))
338 && !(GET_CODE (XEXP (op
, 1)) == CONST_INT
339 && (SMALL_INT (XEXP (op
, 1))
340 || (INTVAL (XEXP (op
, 1)) & 0xffff) == 0)))
349 if (SUBREG_BYTE (op
) != 0)
351 return single_insn_src_p (SUBREG_REG (op
), mode
);
353 /* Not doing floating point, since they probably
354 take longer than the branch slot they might fill. */
368 /* Return non-zero only if OP is a register of mode MODE,
371 reg_or_0_operand (op
, mode
)
373 enum machine_mode mode
;
375 return (op
== const0_rtx
|| register_operand (op
, mode
)
376 || op
== CONST0_RTX (mode
));
379 /* Return truth value of whether OP can be used as an operands in a three
380 address add/subtract insn (such as add %o1,7,%l2) of mode MODE. */
383 arith_operand (op
, mode
)
385 enum machine_mode mode
;
387 return (register_operand (op
, mode
)
388 || (GET_CODE (op
) == CONST_INT
&& SMALL_INT (op
)));
391 /* Return 1 if OP is a valid first operand for a logical insn of mode MODE. */
394 logic_operand (op
, mode
)
396 enum machine_mode mode
;
398 return (register_operand (op
, mode
)
399 || (GET_CODE (op
) == CONST_INT
&& LOGIC_INT (op
)));
402 /* Return 1 if OP is a valid first operand for a shift insn of mode MODE. */
405 shift_operand (op
, mode
)
407 enum machine_mode mode
;
409 return (register_operand (op
, mode
)
410 || (GET_CODE (op
) == CONST_INT
));
413 /* Return 1 if OP is a valid first operand for either a logical insn
414 or an add insn of mode MODE. */
417 compare_operand (op
, mode
)
419 enum machine_mode mode
;
421 return (register_operand (op
, mode
)
422 || (GET_CODE (op
) == CONST_INT
&& SMALL_INT (op
) && LOGIC_INT (op
)));
425 /* Return truth value of whether OP can be used as the 5-bit immediate
426 operand of a bte or btne insn. */
429 bte_operand (op
, mode
)
431 enum machine_mode mode
;
433 return (register_operand (op
, mode
)
434 || (GET_CODE (op
) == CONST_INT
435 && (unsigned) INTVAL (op
) < 0x20));
438 /* Return 1 if OP is an indexed memory reference of mode MODE. */
441 indexed_operand (op
, mode
)
443 enum machine_mode mode
;
445 return (GET_CODE (op
) == MEM
&& GET_MODE (op
) == mode
446 && GET_CODE (XEXP (op
, 0)) == PLUS
447 && GET_MODE (XEXP (op
, 0)) == SImode
448 && register_operand (XEXP (XEXP (op
, 0), 0), SImode
)
449 && register_operand (XEXP (XEXP (op
, 0), 1), SImode
));
452 /* Return 1 if OP is a suitable source operand for a load insn
456 load_operand (op
, mode
)
458 enum machine_mode mode
;
460 return (memory_operand (op
, mode
) || indexed_operand (op
, mode
));
463 /* Return truth value of whether OP is a integer which fits the
464 range constraining immediate operands in add/subtract insns. */
469 enum machine_mode mode ATTRIBUTE_UNUSED
;
471 return (GET_CODE (op
) == CONST_INT
&& SMALL_INT (op
));
474 /* Return truth value of whether OP is a integer which fits the
475 range constraining immediate operands in logic insns. */
480 enum machine_mode mode ATTRIBUTE_UNUSED
;
482 return (GET_CODE (op
) == CONST_INT
&& LOGIC_INT (op
));
485 /* Test for a valid operand for a call instruction.
486 Don't allow the arg pointer register or virtual regs
487 since they may change into reg + const, which the patterns
491 call_insn_operand (op
, mode
)
493 enum machine_mode mode ATTRIBUTE_UNUSED
;
495 if (GET_CODE (op
) == MEM
496 && (CONSTANT_ADDRESS_P (XEXP (op
, 0))
497 || (GET_CODE (XEXP (op
, 0)) == REG
498 && XEXP (op
, 0) != arg_pointer_rtx
499 && !(REGNO (XEXP (op
, 0)) >= FIRST_PSEUDO_REGISTER
500 && REGNO (XEXP (op
, 0)) <= LAST_VIRTUAL_REGISTER
))))
505 /* Return the best assembler insn template
506 for moving operands[1] into operands[0] as a fullword. */
509 singlemove_string (operands
)
512 if (GET_CODE (operands
[0]) == MEM
)
514 if (GET_CODE (operands
[1]) != MEM
)
515 if (CONSTANT_ADDRESS_P (XEXP (operands
[0], 0)))
517 if (! ((cc_prev_status
.flags
& CC_KNOW_HI_R31
)
518 && (cc_prev_status
.flags
& CC_HI_R31_ADJ
)
519 && cc_prev_status
.mdep
== XEXP (operands
[0], 0)))
522 output_asm_insn ("orh %h0,%?r0,%?r31", operands
);
524 cc_status
.flags
|= CC_KNOW_HI_R31
| CC_HI_R31_ADJ
;
525 cc_status
.mdep
= XEXP (operands
[0], 0);
526 return "st.l %r1,%L0(%?r31)";
529 return "st.l %r1,%0";
536 cc_status
.flags
&= ~CC_F0_IS_0
;
537 xoperands
[0] = gen_rtx_REG (SFmode
, 32);
538 xoperands
[1] = operands
[1];
539 output_asm_insn (singlemove_string (xoperands
), xoperands
);
540 xoperands
[1] = xoperands
[0];
541 xoperands
[0] = operands
[0];
542 output_asm_insn (singlemove_string (xoperands
), xoperands
);
547 if (GET_CODE (operands
[1]) == MEM
)
549 if (CONSTANT_ADDRESS_P (XEXP (operands
[1], 0)))
551 if (! ((cc_prev_status
.flags
& CC_KNOW_HI_R31
)
552 && (cc_prev_status
.flags
& CC_HI_R31_ADJ
)
553 && cc_prev_status
.mdep
== XEXP (operands
[1], 0)))
556 output_asm_insn ("orh %h1,%?r0,%?r31", operands
);
558 cc_status
.flags
|= CC_KNOW_HI_R31
| CC_HI_R31_ADJ
;
559 cc_status
.mdep
= XEXP (operands
[1], 0);
560 return "ld.l %L1(%?r31),%0";
562 return "ld.l %m1,%0";
564 if (GET_CODE (operands
[1]) == CONST_INT
)
566 if (operands
[1] == const0_rtx
)
567 return "mov %?r0,%0";
568 if((INTVAL (operands
[1]) & 0xffff0000) == 0)
569 return "or %L1,%?r0,%0";
570 if((INTVAL (operands
[1]) & 0xffff8000) == 0xffff8000)
571 return "adds %1,%?r0,%0";
572 if((INTVAL (operands
[1]) & 0x0000ffff) == 0)
573 return "orh %H1,%?r0,%0";
575 return "orh %H1,%?r0,%0\n\tor %L1,%0,%0";
580 /* Output assembler code to perform a doubleword move insn
581 with operands OPERANDS. */
584 output_move_double (operands
)
587 enum { REGOP
, OFFSOP
, MEMOP
, PUSHOP
, POPOP
, CNSTOP
, RNDOP
} optype0
, optype1
;
589 rtx addreg0
= 0, addreg1
= 0;
590 int highest_first
= 0;
591 int no_addreg1_decrement
= 0;
593 /* First classify both operands. */
595 if (REG_P (operands
[0]))
597 else if (offsettable_memref_p (operands
[0]))
599 else if (GET_CODE (operands
[0]) == MEM
)
604 if (REG_P (operands
[1]))
606 else if (CONSTANT_P (operands
[1]))
608 else if (offsettable_memref_p (operands
[1]))
610 else if (GET_CODE (operands
[1]) == MEM
)
615 /* Check for the cases that the operand constraints are not
616 supposed to allow to happen. Abort if we get one,
617 because generating code for these cases is painful. */
619 if (optype0
== RNDOP
|| optype1
== RNDOP
)
622 /* If an operand is an unoffsettable memory ref, find a register
623 we can increment temporarily to make it refer to the second word. */
625 if (optype0
== MEMOP
)
626 addreg0
= find_addr_reg (XEXP (operands
[0], 0));
628 if (optype1
== MEMOP
)
629 addreg1
= find_addr_reg (XEXP (operands
[1], 0));
631 /* ??? Perhaps in some cases move double words
632 if there is a spare pair of floating regs. */
634 /* Ok, we can do one word at a time.
635 Normally we do the low-numbered word first,
636 but if either operand is autodecrementing then we
637 do the high-numbered word first.
639 In either case, set up in LATEHALF the operands to use
640 for the high-numbered word and in some cases alter the
641 operands in OPERANDS to be suitable for the low-numbered word. */
643 if (optype0
== REGOP
)
644 latehalf
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 1);
645 else if (optype0
== OFFSOP
)
646 latehalf
[0] = adj_offsettable_operand (operands
[0], 4);
648 latehalf
[0] = operands
[0];
650 if (optype1
== REGOP
)
651 latehalf
[1] = gen_rtx_REG (SImode
, REGNO (operands
[1]) + 1);
652 else if (optype1
== OFFSOP
)
653 latehalf
[1] = adj_offsettable_operand (operands
[1], 4);
654 else if (optype1
== CNSTOP
)
656 if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
657 split_double (operands
[1], &operands
[1], &latehalf
[1]);
658 else if (CONSTANT_P (operands
[1]))
659 latehalf
[1] = const0_rtx
;
662 latehalf
[1] = operands
[1];
664 /* If the first move would clobber the source of the second one,
665 do them in the other order.
667 RMS says "This happens only for registers;
668 such overlap can't happen in memory unless the user explicitly
669 sets it up, and that is an undefined circumstance."
671 but it happens on the sparc when loading parameter registers,
672 so I am going to define that circumstance, and make it work
675 if (optype0
== REGOP
&& optype1
== REGOP
676 && REGNO (operands
[0]) == REGNO (latehalf
[1]))
678 CC_STATUS_PARTIAL_INIT
;
679 /* Make any unoffsettable addresses point at high-numbered word. */
681 output_asm_insn ("adds 0x4,%0,%0", &addreg0
);
683 output_asm_insn ("adds 0x4,%0,%0", &addreg1
);
686 output_asm_insn (singlemove_string (latehalf
), latehalf
);
688 /* Undo the adds we just did. */
690 output_asm_insn ("adds -0x4,%0,%0", &addreg0
);
692 output_asm_insn ("adds -0x4,%0,%0", &addreg1
);
694 /* Do low-numbered word. */
695 return singlemove_string (operands
);
697 else if (optype0
== REGOP
&& optype1
!= REGOP
698 && reg_overlap_mentioned_p (operands
[0], operands
[1]))
700 /* If both halves of dest are used in the src memory address,
701 add the two regs and put them in the low reg (operands[0]).
702 Then it works to load latehalf first. */
703 if (reg_mentioned_p (operands
[0], XEXP (operands
[1], 0))
704 && reg_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
707 xops
[0] = latehalf
[0];
708 xops
[1] = operands
[0];
709 output_asm_insn ("adds %1,%0,%1", xops
);
710 operands
[1] = gen_rtx_MEM (DImode
, operands
[0]);
711 latehalf
[1] = adj_offsettable_operand (operands
[1], 4);
715 /* Only one register in the dest is used in the src memory address,
716 and this is the first register of the dest, so we want to do
717 the late half first here also. */
718 else if (! reg_mentioned_p (latehalf
[0], XEXP (operands
[1], 0)))
720 /* Only one register in the dest is used in the src memory address,
721 and this is the second register of the dest, so we want to do
722 the late half last. If addreg1 is set, and addreg1 is the same
723 register as latehalf, then we must suppress the trailing decrement,
724 because it would clobber the value just loaded. */
725 else if (addreg1
&& reg_mentioned_p (addreg1
, latehalf
[0]))
726 no_addreg1_decrement
= 1;
729 /* Normal case: do the two words, low-numbered first.
730 Overlap case (highest_first set): do high-numbered word first. */
733 output_asm_insn (singlemove_string (operands
), operands
);
735 CC_STATUS_PARTIAL_INIT
;
736 /* Make any unoffsettable addresses point at high-numbered word. */
738 output_asm_insn ("adds 0x4,%0,%0", &addreg0
);
740 output_asm_insn ("adds 0x4,%0,%0", &addreg1
);
743 output_asm_insn (singlemove_string (latehalf
), latehalf
);
745 /* Undo the adds we just did. */
747 output_asm_insn ("adds -0x4,%0,%0", &addreg0
);
748 if (addreg1
&& !no_addreg1_decrement
)
749 output_asm_insn ("adds -0x4,%0,%0", &addreg1
);
752 output_asm_insn (singlemove_string (operands
), operands
);
758 output_fp_move_double (operands
)
761 /* If the source operand is any sort of zero, use f0 instead. */
763 if (operands
[1] == CONST0_RTX (GET_MODE (operands
[1])))
764 operands
[1] = gen_rtx_REG (DFmode
, F0_REGNUM
);
766 if (FP_REG_P (operands
[0]))
768 if (FP_REG_P (operands
[1]))
769 return "fmov.dd %1,%0";
770 if (GET_CODE (operands
[1]) == REG
)
772 output_asm_insn ("ixfr %1,%0", operands
);
773 operands
[0] = gen_rtx_REG (VOIDmode
, REGNO (operands
[0]) + 1);
774 operands
[1] = gen_rtx_REG (VOIDmode
, REGNO (operands
[1]) + 1);
777 if (operands
[1] == CONST0_RTX (DFmode
))
778 return "fmov.dd f0,%0";
779 if (CONSTANT_ADDRESS_P (XEXP (operands
[1], 0)))
781 if (! ((cc_prev_status
.flags
& CC_KNOW_HI_R31
)
782 && (cc_prev_status
.flags
& CC_HI_R31_ADJ
)
783 && cc_prev_status
.mdep
== XEXP (operands
[1], 0)))
786 output_asm_insn ("orh %h1,%?r0,%?r31", operands
);
788 cc_status
.flags
|= CC_KNOW_HI_R31
| CC_HI_R31_ADJ
;
789 cc_status
.mdep
= XEXP (operands
[1], 0);
790 return "fld.d %L1(%?r31),%0";
792 return "fld.d %1,%0";
794 else if (FP_REG_P (operands
[1]))
796 if (GET_CODE (operands
[0]) == REG
)
798 output_asm_insn ("fxfr %1,%0", operands
);
799 operands
[0] = gen_rtx_REG (VOIDmode
, REGNO (operands
[0]) + 1);
800 operands
[1] = gen_rtx_REG (VOIDmode
, REGNO (operands
[1]) + 1);
803 if (CONSTANT_ADDRESS_P (XEXP (operands
[0], 0)))
805 if (! ((cc_prev_status
.flags
& CC_KNOW_HI_R31
)
806 && (cc_prev_status
.flags
& CC_HI_R31_ADJ
)
807 && cc_prev_status
.mdep
== XEXP (operands
[0], 0)))
810 output_asm_insn ("orh %h0,%?r0,%?r31", operands
);
812 cc_status
.flags
|= CC_KNOW_HI_R31
| CC_HI_R31_ADJ
;
813 cc_status
.mdep
= XEXP (operands
[0], 0);
814 return "fst.d %1,%L0(%?r31)";
816 return "fst.d %1,%0";
824 /* Return a REG that occurs in ADDR with coefficient 1.
825 ADDR can be effectively incremented by incrementing REG. */
831 while (GET_CODE (addr
) == PLUS
)
833 if (GET_CODE (XEXP (addr
, 0)) == REG
)
834 addr
= XEXP (addr
, 0);
835 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
836 addr
= XEXP (addr
, 1);
837 else if (CONSTANT_P (XEXP (addr
, 0)))
838 addr
= XEXP (addr
, 1);
839 else if (CONSTANT_P (XEXP (addr
, 1)))
840 addr
= XEXP (addr
, 0);
844 if (GET_CODE (addr
) == REG
)
851 /* Return a template for a load instruction with mode MODE and
852 arguments from the string ARGS.
854 This string is in static storage. */
857 load_opcode (mode
, args
, reg
)
858 enum machine_mode mode
;
894 sprintf (buf
, "%s %s", opcode
, args
);
898 /* Return a template for a store instruction with mode MODE and
899 arguments from the string ARGS.
901 This string is in static storage. */
904 store_opcode (mode
, args
, reg
)
905 enum machine_mode mode
;
941 sprintf (buf
, "%s %s", opcode
, args
);
945 /* Output a store-in-memory whose operands are OPERANDS[0,1].
946 OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.
948 This function returns a template for an insn.
949 This is in static storage.
951 It may also output some insns directly.
952 It may alter the values of operands[0] and operands[1]. */
955 output_store (operands
)
958 enum machine_mode mode
= GET_MODE (operands
[0]);
959 rtx address
= XEXP (operands
[0], 0);
961 cc_status
.flags
|= CC_KNOW_HI_R31
| CC_HI_R31_ADJ
;
962 cc_status
.mdep
= address
;
964 if (! ((cc_prev_status
.flags
& CC_KNOW_HI_R31
)
965 && (cc_prev_status
.flags
& CC_HI_R31_ADJ
)
966 && address
== cc_prev_status
.mdep
))
969 output_asm_insn ("orh %h0,%?r0,%?r31", operands
);
970 cc_prev_status
.mdep
= address
;
973 /* Store zero in two parts when appropriate. */
974 if (mode
== DFmode
&& operands
[1] == CONST0_RTX (DFmode
))
975 return store_opcode (DFmode
, "%r1,%L0(%?r31)", operands
[1]);
977 /* Code below isn't smart enough to move a doubleword in two parts,
978 so use output_move_double to do that in the cases that require it. */
979 if ((mode
== DImode
|| mode
== DFmode
)
980 && ! FP_REG_P (operands
[1]))
981 return output_move_double (operands
);
983 return store_opcode (mode
, "%r1,%L0(%?r31)", operands
[1]);
986 /* Output a load-from-memory whose operands are OPERANDS[0,1].
987 OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
989 This function returns a template for an insn.
990 This is in static storage.
992 It may also output some insns directly.
993 It may alter the values of operands[0] and operands[1]. */
996 output_load (operands
)
999 enum machine_mode mode
= GET_MODE (operands
[0]);
1000 rtx address
= XEXP (operands
[1], 0);
1002 /* We don't bother trying to see if we know %hi(address).
1003 This is because we are doing a load, and if we know the
1004 %hi value, we probably also know that value in memory. */
1005 cc_status
.flags
|= CC_KNOW_HI_R31
| CC_HI_R31_ADJ
;
1006 cc_status
.mdep
= address
;
1008 if (! ((cc_prev_status
.flags
& CC_KNOW_HI_R31
)
1009 && (cc_prev_status
.flags
& CC_HI_R31_ADJ
)
1010 && address
== cc_prev_status
.mdep
1011 && cc_prev_status
.mdep
== cc_status
.mdep
))
1014 output_asm_insn ("orh %h1,%?r0,%?r31", operands
);
1015 cc_prev_status
.mdep
= address
;
1018 /* Code below isn't smart enough to move a doubleword in two parts,
1019 so use output_move_double to do that in the cases that require it. */
1020 if ((mode
== DImode
|| mode
== DFmode
)
1021 && ! FP_REG_P (operands
[0]))
1022 return output_move_double (operands
);
1024 return load_opcode (mode
, "%L1(%?r31),%0", operands
[0]);
1028 /* Load the address specified by OPERANDS[3] into the register
1029 specified by OPERANDS[0].
1031 OPERANDS[3] may be the result of a sum, hence it could either be:
1036 (3) REG + REG + CONST_INT
1037 (4) REG + REG (special case of 3).
1039 Note that (3) is not a legitimate address.
1040 All cases are handled here. */
1043 output_load_address (operands
)
1048 if (CONSTANT_P (operands
[3]))
1050 output_asm_insn ("mov %3,%0", operands
);
1054 if (REG_P (operands
[3]))
1056 if (REGNO (operands
[0]) != REGNO (operands
[3]))
1057 output_asm_insn ("shl %?r0,%3,%0", operands
);
1061 if (GET_CODE (operands
[3]) != PLUS
)
1064 base
= XEXP (operands
[3], 0);
1065 offset
= XEXP (operands
[3], 1);
1067 if (GET_CODE (base
) == CONST_INT
)
1074 if (GET_CODE (offset
) != CONST_INT
)
1076 /* Operand is (PLUS (REG) (REG)). */
1078 offset
= const0_rtx
;
1084 operands
[7] = offset
;
1085 CC_STATUS_PARTIAL_INIT
;
1086 if (SMALL_INT (offset
))
1087 output_asm_insn ("adds %7,%6,%0", operands
);
1089 output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands
);
1091 else if (GET_CODE (base
) == PLUS
)
1093 operands
[6] = XEXP (base
, 0);
1094 operands
[7] = XEXP (base
, 1);
1095 operands
[8] = offset
;
1097 CC_STATUS_PARTIAL_INIT
;
1098 if (SMALL_INT (offset
))
1099 output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands
);
1101 output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands
);
1108 /* Output code to place a size count SIZE in register REG.
1109 Because block moves are pipelined, we don't include the
1110 first element in the transfer of SIZE to REG.
1111 For this, we subtract ALIGN. (Actually, I think it is not
1112 right to subtract on this machine, so right now we don't.) */
1115 output_size_for_block_move (size
, reg
, align
)
1116 rtx size
, reg
, align
;
1121 xoperands
[1] = size
;
1122 xoperands
[2] = align
;
1125 cc_status
.flags
&= ~ CC_KNOW_HI_R31
;
1126 output_asm_insn (singlemove_string (xoperands
), xoperands
);
1128 if (GET_CODE (size
) == REG
)
1129 output_asm_insn ("sub %2,%1,%0", xoperands
);
1132 xoperands
[1] = GEN_INT (INTVAL (size
) - INTVAL (align
));
1133 cc_status
.flags
&= ~ CC_KNOW_HI_R31
;
1134 output_asm_insn ("mov %1,%0", xoperands
);
1139 /* Emit code to perform a block move.
1141 OPERANDS[0] is the destination.
1142 OPERANDS[1] is the source.
1143 OPERANDS[2] is the size.
1144 OPERANDS[3] is the known safe alignment.
1145 OPERANDS[4..6] are pseudos we can safely clobber as temps. */
1148 output_block_move (operands
)
1151 /* A vector for our computed operands. Note that load_output_address
1152 makes use of (and can clobber) up to the 8th element of this vector. */
1157 static int movstrsi_label
= 0;
1159 rtx temp1
= operands
[4];
1160 rtx alignrtx
= operands
[3];
1161 int align
= INTVAL (alignrtx
);
1164 xoperands
[0] = operands
[0];
1165 xoperands
[1] = operands
[1];
1166 xoperands
[2] = temp1
;
1168 /* We can't move more than four bytes at a time
1169 because we have only one register to move them through. */
1173 alignrtx
= GEN_INT (4);
1176 /* Recognize special cases of block moves. These occur
1177 when GNU C++ is forced to treat something as BLKmode
1178 to keep it in memory, when its mode could be represented
1179 with something smaller.
1181 We cannot do this for global variables, since we don't know
1182 what pages they don't cross. Sigh. */
1183 if (GET_CODE (operands
[2]) == CONST_INT
1184 && ! CONSTANT_ADDRESS_P (operands
[0])
1185 && ! CONSTANT_ADDRESS_P (operands
[1]))
1187 int size
= INTVAL (operands
[2]);
1188 rtx op0
= xoperands
[0];
1189 rtx op1
= xoperands
[1];
1191 if ((align
& 3) == 0 && (size
& 3) == 0 && (size
>> 2) <= 16)
1193 if (memory_address_p (SImode
, plus_constant (op0
, size
))
1194 && memory_address_p (SImode
, plus_constant (op1
, size
)))
1196 cc_status
.flags
&= ~CC_KNOW_HI_R31
;
1197 for (i
= (size
>>2)-1; i
>= 0; i
--)
1199 xoperands
[0] = plus_constant (op0
, i
* 4);
1200 xoperands
[1] = plus_constant (op1
, i
* 4);
1201 output_asm_insn ("ld.l %a1,%?r31\n\tst.l %?r31,%a0",
1207 else if ((align
& 1) == 0 && (size
& 1) == 0 && (size
>> 1) <= 16)
1209 if (memory_address_p (HImode
, plus_constant (op0
, size
))
1210 && memory_address_p (HImode
, plus_constant (op1
, size
)))
1212 cc_status
.flags
&= ~CC_KNOW_HI_R31
;
1213 for (i
= (size
>>1)-1; i
>= 0; i
--)
1215 xoperands
[0] = plus_constant (op0
, i
* 2);
1216 xoperands
[1] = plus_constant (op1
, i
* 2);
1217 output_asm_insn ("ld.s %a1,%?r31\n\tst.s %?r31,%a0",
1223 else if (size
<= 16)
1225 if (memory_address_p (QImode
, plus_constant (op0
, size
))
1226 && memory_address_p (QImode
, plus_constant (op1
, size
)))
1228 cc_status
.flags
&= ~CC_KNOW_HI_R31
;
1229 for (i
= size
-1; i
>= 0; i
--)
1231 xoperands
[0] = plus_constant (op0
, i
);
1232 xoperands
[1] = plus_constant (op1
, i
);
1233 output_asm_insn ("ld.b %a1,%?r31\n\tst.b %?r31,%a0",
1241 /* Since we clobber untold things, nix the condition codes. */
1244 /* This is the size of the transfer.
1245 Either use the register which already contains the size,
1246 or use a free register (used by no operands). */
1247 output_size_for_block_move (operands
[2], operands
[4], alignrtx
);
1250 /* Also emit code to decrement the size value by ALIGN. */
1251 zoperands
[0] = operands
[0];
1252 zoperands
[3] = plus_constant (operands
[0], align
);
1253 output_load_address (zoperands
);
1256 /* Generate number for unique label. */
1258 xoperands
[3] = GEN_INT (movstrsi_label
++);
1260 /* Calculate the size of the chunks we will be trying to move first. */
1263 if ((align
& 3) == 0)
1265 else if ((align
& 1) == 0)
1271 /* Copy the increment (negative) to a register for bla insn. */
1273 xoperands
[4] = GEN_INT (- chunk_size
);
1274 xoperands
[5] = operands
[5];
1275 output_asm_insn ("adds %4,%?r0,%5", xoperands
);
1277 /* Predecrement the loop counter. This happens again also in the `bla'
1278 instruction which precedes the loop, but we need to have it done
1279 two times before we enter the loop because of the bizarre semantics
1280 of the bla instruction. */
1282 output_asm_insn ("adds %5,%2,%2", xoperands
);
1284 /* Check for the case where the original count was less than or equal to
1285 zero. Avoid going through the loop at all if the original count was
1286 indeed less than or equal to zero. Note that we treat the count as
1287 if it were a signed 32-bit quantity here, rather than an unsigned one,
1288 even though we really shouldn't. We have to do this because of the
1289 semantics of the `ble' instruction, which assume that the count is
1290 a signed 32-bit value. Anyway, in practice it won't matter because
1291 nobody is going to try to do a memcpy() of more than half of the
1292 entire address space (i.e. 2 gigabytes) anyway. */
1294 output_asm_insn ("bc .Le%3", xoperands
);
1296 /* Make available a register which is a temporary. */
1298 xoperands
[6] = operands
[6];
1300 /* Now the actual loop.
1301 In xoperands, elements 1 and 0 are the input and output vectors.
1302 Element 2 is the loop index. Element 5 is the increment. */
1304 output_asm_insn ("subs %1,%5,%1", xoperands
);
1305 output_asm_insn ("bla %5,%2,.Lm%3", xoperands
);
1306 output_asm_insn ("adds %0,%2,%6", xoperands
);
1307 output_asm_insn ("\n.Lm%3:", xoperands
); /* Label for bla above. */
1308 output_asm_insn ("\n.Ls%3:", xoperands
); /* Loop start label. */
1309 output_asm_insn ("adds %5,%6,%6", xoperands
);
1311 /* NOTE: The code here which is supposed to handle the cases where the
1312 sources and destinations are known to start on a 4 or 2 byte boundary
1313 are currently broken. They fail to do anything about the overflow
1314 bytes which might still need to be copied even after we have copied
1315 some number of words or halfwords. Thus, for now we use the lowest
1316 common denominator, i.e. the code which just copies some number of
1317 totally unaligned individual bytes. (See the calculation of
1318 chunk_size above. */
1320 if (chunk_size
== 4)
1322 output_asm_insn ("ld.l %2(%1),%?r31", xoperands
);
1323 output_asm_insn ("bla %5,%2,.Ls%3", xoperands
);
1324 output_asm_insn ("st.l %?r31,8(%6)", xoperands
);
1326 else if (chunk_size
== 2)
1328 output_asm_insn ("ld.s %2(%1),%?r31", xoperands
);
1329 output_asm_insn ("bla %5,%2,.Ls%3", xoperands
);
1330 output_asm_insn ("st.s %?r31,4(%6)", xoperands
);
1332 else /* chunk_size == 1 */
1334 output_asm_insn ("ld.b %2(%1),%?r31", xoperands
);
1335 output_asm_insn ("bla %5,%2,.Ls%3", xoperands
);
1336 output_asm_insn ("st.b %?r31,2(%6)", xoperands
);
1338 output_asm_insn ("\n.Le%3:", xoperands
); /* Here if count <= 0. */
1344 /* Output a delayed branch insn with the delay insn in its
1345 branch slot. The delayed branch insn template is in TEMPLATE,
1346 with operands OPERANDS. The insn in its delay slot is INSN.
1348 As a special case, since we know that all memory transfers are via
1349 ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
1350 reference around the branch as
1354 ld/st l%x(%?r31),...
1356 As another special case, we handle loading (SYMBOL_REF ...) and
1357 other large constants around branches as well:
1364 /* ??? Disabled because this re-recognition is incomplete and causes
1365 constrain_operands to segfault. Anyone who cares should fix up
1366 the code to use the DBR pass. */
1369 output_delayed_branch (template, operands
, insn
)
1370 const char *template;
1374 rtx src
= XVECEXP (PATTERN (insn
), 0, 1);
1375 rtx dest
= XVECEXP (PATTERN (insn
), 0, 0);
1377 /* See if we are doing some branch together with setting some register
1378 to some 32-bit value which does (or may) have some of the high-order
1379 16 bits set. If so, we need to set the register in two stages. One
1380 stage must be done before the branch, and the other one can be done
1381 in the delay slot. */
1383 if ( (GET_CODE (src
) == CONST_INT
1384 && ((unsigned) INTVAL (src
) & (unsigned) 0xffff0000) != (unsigned) 0)
1385 || (GET_CODE (src
) == SYMBOL_REF
)
1386 || (GET_CODE (src
) == LABEL_REF
)
1387 || (GET_CODE (src
) == CONST
))
1390 xoperands
[0] = dest
;
1393 CC_STATUS_PARTIAL_INIT
;
1394 /* Output the `orh' insn. */
1395 output_asm_insn ("orh %H1,%?r0,%0", xoperands
);
1397 /* Output the branch instruction next. */
1398 output_asm_insn (template, operands
);
1400 /* Now output the `or' insn. */
1401 output_asm_insn ("or %L1,%0,%0", xoperands
);
1403 else if ((GET_CODE (src
) == MEM
1404 && CONSTANT_ADDRESS_P (XEXP (src
, 0)))
1405 || (GET_CODE (dest
) == MEM
1406 && CONSTANT_ADDRESS_P (XEXP (dest
, 0))))
1409 const char *split_template
;
1410 xoperands
[0] = dest
;
1413 /* Output the `orh' insn. */
1414 if (GET_CODE (src
) == MEM
)
1416 if (! ((cc_prev_status
.flags
& CC_KNOW_HI_R31
)
1417 && (cc_prev_status
.flags
& CC_HI_R31_ADJ
)
1418 && cc_prev_status
.mdep
== XEXP (operands
[1], 0)))
1421 output_asm_insn ("orh %h1,%?r0,%?r31", xoperands
);
1423 split_template
= load_opcode (GET_MODE (dest
),
1424 "%L1(%?r31),%0", dest
);
1428 if (! ((cc_prev_status
.flags
& CC_KNOW_HI_R31
)
1429 && (cc_prev_status
.flags
& CC_HI_R31_ADJ
)
1430 && cc_prev_status
.mdep
== XEXP (operands
[0], 0)))
1433 output_asm_insn ("orh %h0,%?r0,%?r31", xoperands
);
1435 split_template
= store_opcode (GET_MODE (dest
),
1436 "%r1,%L0(%?r31)", src
);
1439 /* Output the branch instruction next. */
1440 output_asm_insn (template, operands
);
1442 /* Now output the load or store.
1443 No need to do a CC_STATUS_INIT, because we are branching anyway. */
1444 output_asm_insn (split_template
, xoperands
);
1448 int insn_code_number
;
1449 rtx pat
= gen_rtx_SET (VOIDmode
, dest
, src
);
1450 rtx delay_insn
= gen_rtx_INSN (VOIDmode
, 0, 0, 0, pat
, -1, 0, 0);
1453 /* Output the branch instruction first. */
1454 output_asm_insn (template, operands
);
1456 /* Now recognize the insn which we put in its delay slot.
1457 We must do this after outputting the branch insn,
1458 since operands may just be a pointer to `recog_data.operand'. */
1459 INSN_CODE (delay_insn
) = insn_code_number
1460 = recog (pat
, delay_insn
, NULL
);
1461 if (insn_code_number
== -1)
1464 for (i
= 0; i
< insn_data
[insn_code_number
].n_operands
; i
++)
1466 if (GET_CODE (recog_data
.operand
[i
]) == SUBREG
)
1467 recog_data
.operand
[i
] = alter_subreg (recog_data
.operand
[i
]);
1470 insn_extract (delay_insn
);
1471 if (! constrain_operands (1))
1472 fatal_insn_not_found (delay_insn
);
1474 template = get_insn_template (insn_code_number
, delay_insn
);
1475 output_asm_insn (template, recog_data
.operand
);
1481 /* Output a newly constructed insn DELAY_INSN. */
1483 output_delay_insn (delay_insn
)
1486 const char *template;
1487 int insn_code_number
;
1490 /* Now recognize the insn which we put in its delay slot.
1491 We must do this after outputting the branch insn,
1492 since operands may just be a pointer to `recog_data.operand'. */
1493 insn_code_number
= recog_memoized (delay_insn
);
1494 if (insn_code_number
== -1)
1497 /* Extract the operands of this delay insn. */
1498 INSN_CODE (delay_insn
) = insn_code_number
;
1499 insn_extract (delay_insn
);
1501 /* It is possible that this insn has not been properly scanned by final
1502 yet. If this insn's operands don't appear in the peephole's
1503 actual operands, then they won't be fixed up by final, so we
1504 make sure they get fixed up here. -- This is a kludge. */
1505 for (i
= 0; i
< insn_data
[insn_code_number
].n_operands
; i
++)
1507 if (GET_CODE (recog_data
.operand
[i
]) == SUBREG
)
1508 recog_data
.operand
[i
] = alter_subreg (recog_data
.operand
[i
]);
1511 if (! constrain_operands (1))
1514 cc_prev_status
= cc_status
;
1516 /* Update `cc_status' for this instruction.
1517 The instruction's output routine may change it further.
1518 If the output routine for a jump insn needs to depend
1519 on the cc status, it should look at cc_prev_status. */
1521 NOTICE_UPDATE_CC (PATTERN (delay_insn
), delay_insn
);
1523 /* Now get the template for what this insn would
1524 have been, without the branch. */
1526 template = get_insn_template (insn_code_number
, delay_insn
);
1527 output_asm_insn (template, recog_data
.operand
);
1532 /* Special routine to convert an SFmode value represented as a
1533 CONST_DOUBLE into its equivalent unsigned long bit pattern.
1534 We convert the value from a double precision floating-point
1535 value to single precision first, and thence to a bit-wise
1536 equivalent unsigned long value. This routine is used when
1537 generating an immediate move of an SFmode value directly
1538 into a general register because the svr4 assembler doesn't
1539 grok floating literals in instruction operand contexts. */
1542 sfmode_constant_to_ulong (x
)
1546 union { float f
; unsigned long i
; } u2
;
1548 if (GET_CODE (x
) != CONST_DOUBLE
|| GET_MODE (x
) != SFmode
)
1551 #if TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT
1552 error IEEE emulation needed
1554 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
1559 /* This function generates the assembly code for function entry.
1560 The macro FUNCTION_PROLOGUE in i860.h is defined to call this function.
1562 ASM_FILE is a stdio stream to output the code to.
1563 SIZE is an int: how many units of temporary storage to allocate.
1565 Refer to the array `regs_ever_live' to determine which registers
1566 to save; `regs_ever_live[I]' is nonzero if register number I
1567 is ever used in the function. This macro is responsible for
1568 knowing which registers should not be saved even if used.
1570 NOTE: `frame_lower_bytes' is the count of bytes which will lie
1571 between the new `fp' value and the new `sp' value after the
1572 prologue is done. `frame_upper_bytes' is the count of bytes
1573 that will lie between the new `fp' and the *old* `sp' value
1574 after the new `fp' is setup (in the prologue). The upper
1575 part of each frame always includes at least 2 words (8 bytes)
1576 to hold the saved frame pointer and the saved return address.
1578 The svr4 ABI for the i860 now requires that the values of the
1579 stack pointer and frame pointer registers be kept aligned to
1580 16-byte boundaries at all times. We obey that restriction here.
1582 The svr4 ABI for the i860 is entirely vague when it comes to specifying
1583 exactly where the "preserved" registers should be saved. The native
1584 svr4 C compiler I now have doesn't help to clarify the requirements
1585 very much because it is plainly out-of-date and non-ABI-compliant
1586 (in at least one important way, i.e. how it generates function
1589 The native svr4 C compiler saves the "preserved" registers (i.e.
1590 r4-r15 and f2-f7) in the lower part of a frame (i.e. at negative
1591 offsets from the frame pointer).
1593 Previous versions of GCC also saved the "preserved" registers in the
1594 "negative" part of the frame, but they saved them using positive
1595 offsets from the (adjusted) stack pointer (after it had been adjusted
1596 to allocate space for the new frame). That's just plain wrong
1597 because if the current function calls alloca(), the stack pointer
1598 will get moved, and it will be impossible to restore the registers
1599 properly again after that.
1601 Both compilers handled parameter registers (i.e. r16-r27 and f8-f15)
1602 by copying their values either into various "preserved" registers or
1603 into stack slots in the lower part of the current frame (as seemed
1604 appropriate, depending upon subsequent usage of these values).
1606 Here we want to save the preserved registers at some offset from the
1607 frame pointer register so as to avoid any possible problems arising
1608 from calls to alloca(). We can either save them at small positive
1609 offsets from the frame pointer, or at small negative offsets from
1610 the frame pointer. If we save them at small negative offsets from
1611 the frame pointer (i.e. in the lower part of the frame) then we
1612 must tell the rest of GCC (via STARTING_FRAME_OFFSET) exactly how
1613 many bytes of space we plan to use in the lower part of the frame
1614 for this purpose. Since other parts of the compiler reference the
1615 value of STARTING_FRAME_OFFSET long before final() calls this function,
1616 we would have to go ahead and assume the worst-case storage requirements
1617 for saving all of the "preserved" registers (and use that number, i.e.
1618 `80', to define STARTING_FRAME_OFFSET) if we wanted to save them in
1619 the lower part of the frame. That could potentially be very wasteful,
1620 and that wastefulness could really hamper people compiling for embedded
1621 i860 targets with very tight limits on stack space. Thus, we choose
1622 here to save the preserved registers in the upper part of the
1623 frame, so that we can decide at the very last minute how much (or how
1624 little) space we must allocate for this purpose.
1626 To satisfy the needs of the svr4 ABI "tdesc" scheme, preserved
1627 registers must always be saved so that the saved values of registers
1628 with higher numbers are at higher addresses. We obey that restriction
1631 There are two somewhat different ways that you can generate prologues
1632 here... i.e. pedantically ABI-compliant, and the "other" way. The
1633 "other" way is more consistent with what is currently generated by the
1634 "native" svr4 C compiler for the i860. That's important if you want
1635 to use the current (as of 8/91) incarnation of svr4 SDB for the i860.
1636 The SVR4 SDB for the i860 insists on having function prologues be
1639 To get fully ABI-compliant prologues, define I860_STRICT_ABI_PROLOGUES
1640 in the i860svr4.h file. (By default this is *not* defined).
1642 The differences between the ABI-compliant and non-ABI-compliant prologues
1643 are that (a) the ABI version seems to require the use of *signed*
1644 (rather than unsigned) adds and subtracts, and (b) the ordering of
1645 the various steps (e.g. saving preserved registers, saving the
1646 return address, setting up the new frame pointer value) is different.
1648 For strict ABI compliance, it seems to be the case that the very last
1649 thing that is supposed to happen in the prologue is getting the frame
1650 pointer set to its new value (but only after everything else has
1651 already been properly setup). We do that here, but only if the symbol
1652 I860_STRICT_ABI_PROLOGUES is defined.
1655 #ifndef STACK_ALIGNMENT
1656 #define STACK_ALIGNMENT 16
1659 extern char call_used_regs
[];
1661 char *current_function_original_name
;
1663 static int must_preserve_r1
;
1664 static unsigned must_preserve_bytes
;
1667 function_prologue (asm_file
, local_bytes
)
1668 register FILE *asm_file
;
1669 register unsigned local_bytes
;
1671 register unsigned frame_lower_bytes
;
1672 register unsigned frame_upper_bytes
;
1673 register unsigned total_fsize
;
1674 register unsigned preserved_reg_bytes
= 0;
1675 register unsigned i
;
1676 register unsigned preserved_so_far
= 0;
1678 must_preserve_r1
= (optimize
< 2 || ! leaf_function_p ());
1679 must_preserve_bytes
= 4 + (must_preserve_r1
? 4 : 0);
1681 /* Count registers that need preserving. Ignore r0. It never needs
1684 for (i
= 1; i
< FIRST_PSEUDO_REGISTER
; i
++)
1686 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
1687 preserved_reg_bytes
+= 4;
1690 /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
1692 frame_lower_bytes
= (local_bytes
+ STACK_ALIGNMENT
- 1) & -STACK_ALIGNMENT
;
1694 /* The upper part of each frame will contain the saved fp,
1695 the saved r1, and stack slots for all of the other "preserved"
1696 registers that we find we will need to save & restore. */
1698 frame_upper_bytes
= must_preserve_bytes
+ preserved_reg_bytes
;
1700 /* Round-up the frame_upper_bytes so that it's a multiple of 16. */
1703 = (frame_upper_bytes
+ STACK_ALIGNMENT
- 1) & -STACK_ALIGNMENT
;
1705 total_fsize
= frame_upper_bytes
+ frame_lower_bytes
;
1707 #ifndef I860_STRICT_ABI_PROLOGUES
1709 /* There are two kinds of function prologues.
1710 You use the "small" version if the total frame size is
1711 small enough so that it can fit into an immediate 16-bit
1712 value in one instruction. Otherwise, you use the "large"
1713 version of the function prologue. */
1715 if (total_fsize
> 0x7fff)
1717 /* Adjust the stack pointer. The ABI sez to do this using `adds',
1718 but the native C compiler on svr4 uses `addu'. */
1720 fprintf (asm_file
, "\taddu -%d,%ssp,%ssp\n",
1721 frame_upper_bytes
, i860_reg_prefix
, i860_reg_prefix
);
1723 /* Save the old frame pointer. */
1725 fprintf (asm_file
, "\tst.l %sfp,0(%ssp)\n",
1726 i860_reg_prefix
, i860_reg_prefix
);
1728 /* Setup the new frame pointer. The ABI sez to do this after
1729 preserving registers (using adds), but that's not what the
1730 native C compiler on svr4 does. */
1732 fprintf (asm_file
, "\taddu 0,%ssp,%sfp\n",
1733 i860_reg_prefix
, i860_reg_prefix
);
1735 /* Get the value of frame_lower_bytes into r31. */
1737 fprintf (asm_file
, "\torh %d,%sr0,%sr31\n",
1738 frame_lower_bytes
>> 16, i860_reg_prefix
, i860_reg_prefix
);
1739 fprintf (asm_file
, "\tor %d,%sr31,%sr31\n",
1740 frame_lower_bytes
& 0xffff, i860_reg_prefix
, i860_reg_prefix
);
1742 /* Now re-adjust the stack pointer using the value in r31.
1743 The ABI sez to do this with `subs' but SDB may prefer `subu'. */
1745 fprintf (asm_file
, "\tsubu %ssp,%sr31,%ssp\n",
1746 i860_reg_prefix
, i860_reg_prefix
, i860_reg_prefix
);
1748 /* Preserve registers. The ABI sez to do this before setting
1749 up the new frame pointer, but that's not what the native
1750 C compiler on svr4 does. */
1752 for (i
= 1; i
< 32; i
++)
1753 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
1754 fprintf (asm_file
, "\tst.l %s%s,%d(%sfp)\n",
1755 i860_reg_prefix
, reg_names
[i
],
1756 must_preserve_bytes
+ (4 * preserved_so_far
++),
1759 for (i
= 32; i
< 64; i
++)
1760 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
1761 fprintf (asm_file
, "\tfst.l %s%s,%d(%sfp)\n",
1762 i860_reg_prefix
, reg_names
[i
],
1763 must_preserve_bytes
+ (4 * preserved_so_far
++),
1766 /* Save the return address. */
1768 if (must_preserve_r1
)
1769 fprintf (asm_file
, "\tst.l %sr1,4(%sfp)\n",
1770 i860_reg_prefix
, i860_reg_prefix
);
1774 /* Adjust the stack pointer. The ABI sez to do this using `adds',
1775 but the native C compiler on svr4 uses `addu'. */
1777 fprintf (asm_file
, "\taddu -%d,%ssp,%ssp\n",
1778 total_fsize
, i860_reg_prefix
, i860_reg_prefix
);
1780 /* Save the old frame pointer. */
1782 fprintf (asm_file
, "\tst.l %sfp,%d(%ssp)\n",
1783 i860_reg_prefix
, frame_lower_bytes
, i860_reg_prefix
);
1785 /* Setup the new frame pointer. The ABI sez to do this after
1786 preserving registers and after saving the return address,
1787 (and its saz to do this using adds), but that's not what the
1788 native C compiler on svr4 does. */
1790 fprintf (asm_file
, "\taddu %d,%ssp,%sfp\n",
1791 frame_lower_bytes
, i860_reg_prefix
, i860_reg_prefix
);
1793 /* Preserve registers. The ABI sez to do this before setting
1794 up the new frame pointer, but that's not what the native
1795 compiler on svr4 does. */
1797 for (i
= 1; i
< 32; i
++)
1798 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
1799 fprintf (asm_file
, "\tst.l %s%s,%d(%sfp)\n",
1800 i860_reg_prefix
, reg_names
[i
],
1801 must_preserve_bytes
+ (4 * preserved_so_far
++),
1804 for (i
= 32; i
< 64; i
++)
1805 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
1806 fprintf (asm_file
, "\tfst.l %s%s,%d(%sfp)\n",
1807 i860_reg_prefix
, reg_names
[i
],
1808 must_preserve_bytes
+ (4 * preserved_so_far
++),
1811 /* Save the return address. The ABI sez to do this earlier,
1812 and also via an offset from %sp, but the native C compiler
1813 on svr4 does it later (i.e. now) and uses an offset from
1816 if (must_preserve_r1
)
1817 fprintf (asm_file
, "\tst.l %sr1,4(%sfp)\n",
1818 i860_reg_prefix
, i860_reg_prefix
);
1821 #else /* defined(I860_STRICT_ABI_PROLOGUES) */
1823 /* There are two kinds of function prologues.
1824 You use the "small" version if the total frame size is
1825 small enough so that it can fit into an immediate 16-bit
1826 value in one instruction. Otherwise, you use the "large"
1827 version of the function prologue. */
1829 if (total_fsize
> 0x7fff)
1831 /* Adjust the stack pointer (thereby allocating a new frame). */
1833 fprintf (asm_file
, "\tadds -%d,%ssp,%ssp\n",
1834 frame_upper_bytes
, i860_reg_prefix
, i860_reg_prefix
);
1836 /* Save the caller's frame pointer. */
1838 fprintf (asm_file
, "\tst.l %sfp,0(%ssp)\n",
1839 i860_reg_prefix
, i860_reg_prefix
);
1841 /* Save return address. */
1843 if (must_preserve_r1
)
1844 fprintf (asm_file
, "\tst.l %sr1,4(%ssp)\n",
1845 i860_reg_prefix
, i860_reg_prefix
);
1847 /* Get the value of frame_lower_bytes into r31 for later use. */
1849 fprintf (asm_file
, "\torh %d,%sr0,%sr31\n",
1850 frame_lower_bytes
>> 16, i860_reg_prefix
, i860_reg_prefix
);
1851 fprintf (asm_file
, "\tor %d,%sr31,%sr31\n",
1852 frame_lower_bytes
& 0xffff, i860_reg_prefix
, i860_reg_prefix
);
1854 /* Now re-adjust the stack pointer using the value in r31. */
1856 fprintf (asm_file
, "\tsubs %ssp,%sr31,%ssp\n",
1857 i860_reg_prefix
, i860_reg_prefix
, i860_reg_prefix
);
1859 /* Pre-compute value to be used as the new frame pointer. */
1861 fprintf (asm_file
, "\tadds %ssp,%sr31,%sr31\n",
1862 i860_reg_prefix
, i860_reg_prefix
, i860_reg_prefix
);
1864 /* Preserve registers. */
1866 for (i
= 1; i
< 32; i
++)
1867 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
1868 fprintf (asm_file
, "\tst.l %s%s,%d(%sr31)\n",
1869 i860_reg_prefix
, reg_names
[i
],
1870 must_preserve_bytes
+ (4 * preserved_so_far
++),
1873 for (i
= 32; i
< 64; i
++)
1874 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
1875 fprintf (asm_file
, "\tfst.l %s%s,%d(%sr31)\n",
1876 i860_reg_prefix
, reg_names
[i
],
1877 must_preserve_bytes
+ (4 * preserved_so_far
++),
1880 /* Actually set the new value of the frame pointer. */
1882 fprintf (asm_file
, "\tmov %sr31,%sfp\n",
1883 i860_reg_prefix
, i860_reg_prefix
);
1887 /* Adjust the stack pointer. */
1889 fprintf (asm_file
, "\tadds -%d,%ssp,%ssp\n",
1890 total_fsize
, i860_reg_prefix
, i860_reg_prefix
);
1892 /* Save the caller's frame pointer. */
1894 fprintf (asm_file
, "\tst.l %sfp,%d(%ssp)\n",
1895 i860_reg_prefix
, frame_lower_bytes
, i860_reg_prefix
);
1897 /* Save the return address. */
1899 if (must_preserve_r1
)
1900 fprintf (asm_file
, "\tst.l %sr1,%d(%ssp)\n",
1901 i860_reg_prefix
, frame_lower_bytes
+ 4, i860_reg_prefix
);
1903 /* Preserve registers. */
1905 for (i
= 1; i
< 32; i
++)
1906 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
1907 fprintf (asm_file
, "\tst.l %s%s,%d(%ssp)\n",
1908 i860_reg_prefix
, reg_names
[i
],
1909 frame_lower_bytes
+ must_preserve_bytes
+ (4 * preserved_so_far
++),
1912 for (i
= 32; i
< 64; i
++)
1913 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
1914 fprintf (asm_file
, "\tfst.l %s%s,%d(%ssp)\n",
1915 i860_reg_prefix
, reg_names
[i
],
1916 frame_lower_bytes
+ must_preserve_bytes
+ (4 * preserved_so_far
++),
1919 /* Setup the new frame pointer. */
1921 fprintf (asm_file
, "\tadds %d,%ssp,%sfp\n",
1922 frame_lower_bytes
, i860_reg_prefix
, i860_reg_prefix
);
1924 #endif /* defined(I860_STRICT_ABI_PROLOGUES) */
1926 #ifdef ASM_OUTPUT_PROLOGUE_SUFFIX
1927 ASM_OUTPUT_PROLOGUE_SUFFIX (asm_file
);
1928 #endif /* defined(ASM_OUTPUT_PROLOGUE_SUFFIX) */
1931 /* This function generates the assembly code for function exit.
1932 The macro FUNCTION_EPILOGUE in i860.h is defined to call this function.
1934 ASM_FILE is a stdio stream to output the code to.
1935 SIZE is an int: how many units of temporary storage to allocate.
1937 The function epilogue should not depend on the current stack pointer!
1938 It should use the frame pointer only. This is mandatory because
1939 of alloca; we also take advantage of it to omit stack adjustments
1942 Note that when we go to restore the preserved register values we must
1943 not try to address their slots by using offsets from the stack pointer.
1944 That's because the stack pointer may have been moved during the function
1945 execution due to a call to alloca(). Rather, we must restore all
1946 preserved registers via offsets from the frame pointer value.
1948 Note also that when the current frame is being "popped" (by adjusting
1949 the value of the stack pointer) on function exit, we must (for the
1950 sake of alloca) set the new value of the stack pointer based upon
1951 the current value of the frame pointer. We can't just add what we
1952 believe to be the (static) frame size to the stack pointer because
1953 if we did that, and alloca() had been called during this function,
1954 we would end up returning *without* having fully deallocated all of
1955 the space grabbed by alloca. If that happened, and a function
1956 containing one or more alloca() calls was called over and over again,
1957 then the stack would grow without limit!
1959 Finally note that the epilogues generated here are completely ABI
1960 compliant. They go out of their way to insure that the value in
1961 the frame pointer register is never less than the value in the stack
1962 pointer register. It's not clear why this relationship needs to be
1963 maintained at all times, but maintaining it only costs one extra
1964 instruction, so what the hell.
1967 /* This corresponds to a version 4 TDESC structure. Lower numbered
1968 versions successively omit the last word of the structure. We
1969 don't try to handle version 5 here. */
1971 typedef struct TDESC_flags
{
1974 int callable_block
:1;
1976 int fregs
:6; /* fp regs 2-7 */
1977 int iregs
:16; /* regs 0-15 */
1980 typedef struct TDESC
{
1982 int integer_reg_offset
; /* same as must_preserve_bytes */
1983 int floating_point_reg_offset
;
1984 unsigned int positive_frame_size
; /* same as frame_upper_bytes */
1985 unsigned int negative_frame_size
; /* same as frame_lower_bytes */
1989 function_epilogue (asm_file
, local_bytes
)
1990 register FILE *asm_file
;
1991 register unsigned local_bytes
;
1993 register unsigned frame_upper_bytes
;
1994 register unsigned frame_lower_bytes
;
1995 register unsigned preserved_reg_bytes
= 0;
1996 register unsigned i
;
1997 register unsigned restored_so_far
= 0;
1998 register unsigned int_restored
;
1999 register unsigned mask
;
2000 unsigned intflags
=0;
2001 register TDESC_flags
*flags
= (TDESC_flags
*) &intflags
;
2004 flags
->reg_packing
= 1;
2005 flags
->iregs
= 8; /* old fp always gets saved */
2007 /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
2009 frame_lower_bytes
= (local_bytes
+ STACK_ALIGNMENT
- 1) & -STACK_ALIGNMENT
;
2011 /* Count the number of registers that were preserved in the prologue.
2012 Ignore r0. It is never preserved. */
2014 for (i
= 1; i
< FIRST_PSEUDO_REGISTER
; i
++)
2016 if (regs_ever_live
[i
] && ! call_used_regs
[i
])
2017 preserved_reg_bytes
+= 4;
2020 /* The upper part of each frame will contain only saved fp,
2021 the saved r1, and stack slots for all of the other "preserved"
2022 registers that we find we will need to save & restore. */
2024 frame_upper_bytes
= must_preserve_bytes
+ preserved_reg_bytes
;
2026 /* Round-up frame_upper_bytes so that t is a multiple of 16. */
2029 = (frame_upper_bytes
+ STACK_ALIGNMENT
- 1) & -STACK_ALIGNMENT
;
2031 /* Restore all of the "preserved" registers that need restoring. */
2035 for (i
= 1; i
< 32; i
++, mask
<<=1)
2036 if (regs_ever_live
[i
] && ! call_used_regs
[i
]) {
2037 fprintf (asm_file
, "\tld.l %d(%sfp),%s%s\n",
2038 must_preserve_bytes
+ (4 * restored_so_far
++),
2039 i860_reg_prefix
, i860_reg_prefix
, reg_names
[i
]);
2040 if (i
> 3 && i
< 16)
2041 flags
->iregs
|= mask
;
2044 int_restored
= restored_so_far
;
2047 for (i
= 32; i
< 64; i
++) {
2048 if (regs_ever_live
[i
] && ! call_used_regs
[i
]) {
2049 fprintf (asm_file
, "\tfld.l %d(%sfp),%s%s\n",
2050 must_preserve_bytes
+ (4 * restored_so_far
++),
2051 i860_reg_prefix
, i860_reg_prefix
, reg_names
[i
]);
2052 if (i
> 33 && i
< 40)
2053 flags
->fregs
|= mask
;
2055 if (i
> 33 && i
< 40)
2059 /* Get the value we plan to use to restore the stack pointer into r31. */
2061 fprintf (asm_file
, "\tadds %d,%sfp,%sr31\n",
2062 frame_upper_bytes
, i860_reg_prefix
, i860_reg_prefix
);
2064 /* Restore the return address and the old frame pointer. */
2066 if (must_preserve_r1
) {
2067 fprintf (asm_file
, "\tld.l 4(%sfp),%sr1\n",
2068 i860_reg_prefix
, i860_reg_prefix
);
2072 fprintf (asm_file
, "\tld.l 0(%sfp),%sfp\n",
2073 i860_reg_prefix
, i860_reg_prefix
);
2075 /* Return and restore the old stack pointer value. */
2077 fprintf (asm_file
, "\tbri %sr1\n\tmov %sr31,%ssp\n",
2078 i860_reg_prefix
, i860_reg_prefix
, i860_reg_prefix
);
2080 #ifdef OUTPUT_TDESC /* Output an ABI-compliant TDESC entry */
2081 if (! frame_lower_bytes
) {
2083 if (! frame_upper_bytes
) {
2085 if (restored_so_far
== int_restored
) /* No FP saves */
2089 assemble_name(asm_file
,current_function_original_name
);
2090 fputs(".TDESC:\n", asm_file
);
2091 fprintf(asm_file
, "%s 0x%0x\n", ASM_LONG
, intflags
);
2092 fprintf(asm_file
, "%s %d\n", ASM_LONG
,
2093 int_restored
? must_preserve_bytes
: 0);
2094 if (flags
->version
> 1) {
2095 fprintf(asm_file
, "%s %d\n", ASM_LONG
,
2096 (restored_so_far
== int_restored
) ? 0 : must_preserve_bytes
+
2097 (4 * int_restored
));
2098 if (flags
->version
> 2) {
2099 fprintf(asm_file
, "%s %d\n", ASM_LONG
, frame_upper_bytes
);
2100 if (flags
->version
> 3)
2101 fprintf(asm_file
, "%s %d\n", ASM_LONG
, frame_lower_bytes
);
2105 fprintf(asm_file
, "%s ", ASM_LONG
);
2106 assemble_name(asm_file
, current_function_original_name
);
2107 fprintf(asm_file
, "\n%s ", ASM_LONG
);
2108 assemble_name(asm_file
, current_function_original_name
);
2109 fputs(".TDESC\n", asm_file
);
2115 /* Expand a library call to __builtin_saveregs. */
2119 rtx fn
= gen_rtx_SYMBOL_REF (Pmode
, "__builtin_saveregs");
2120 rtx save
= gen_reg_rtx (Pmode
);
2121 rtx valreg
= LIBCALL_VALUE (Pmode
);
2124 /* The return value register overlaps the first argument register.
2125 Save and restore it around the call. */
2126 emit_move_insn (save
, valreg
);
2127 ret
= emit_library_call_value (fn
, NULL_RTX
, 1, Pmode
, 0);
2128 if (GET_CODE (ret
) != REG
|| REGNO (ret
) < FIRST_PSEUDO_REGISTER
)
2129 ret
= copy_to_reg (ret
);
2130 emit_move_insn (valreg
, save
);
2136 i860_build_va_list ()
2138 tree field_ireg_used
, field_freg_used
, field_reg_base
, field_mem_ptr
;
2141 record
= make_node (RECORD_TYPE
);
2143 field_ireg_used
= build_decl (FIELD_DECL
, get_identifier ("__ireg_used"),
2144 unsigned_type_node
);
2145 field_freg_used
= build_decl (FIELD_DECL
, get_identifier ("__freg_used"),
2146 unsigned_type_node
);
2147 field_reg_base
= build_decl (FIELD_DECL
, get_identifier ("__reg_base"),
2149 field_mem_ptr
= build_decl (FIELD_DECL
, get_identifier ("__mem_ptr"),
2152 DECL_FIELD_CONTEXT (field_ireg_used
) = record
;
2153 DECL_FIELD_CONTEXT (field_freg_used
) = record
;
2154 DECL_FIELD_CONTEXT (field_reg_base
) = record
;
2155 DECL_FIELD_CONTEXT (field_mem_ptr
) = record
;
2157 #ifdef I860_SVR4_VA_LIST
2158 TYPE_FIELDS (record
) = field_ireg_used
;
2159 TREE_CHAIN (field_ireg_used
) = field_freg_used
;
2160 TREE_CHAIN (field_freg_used
) = field_reg_base
;
2161 TREE_CHAIN (field_reg_base
) = field_mem_ptr
;
2163 TYPE_FIELDS (record
) = field_reg_base
;
2164 TREE_CHAIN (field_reg_base
) = field_mem_ptr
;
2165 TREE_CHAIN (field_mem_ptr
) = field_ireg_used
;
2166 TREE_CHAIN (field_ireg_used
) = field_freg_used
;
2169 layout_type (record
);
2174 i860_va_start (stdarg_p
, valist
, nextarg
)
2181 saveregs
= make_tree (build_pointer_type (va_list_type_node
),
2182 expand_builtin_saveregs ());
2183 saveregs
= build1 (INDIRECT_REF
, va_list_type_node
, saveregs
);
2187 tree field_ireg_used
, field_freg_used
, field_reg_base
, field_mem_ptr
;
2188 tree ireg_used
, freg_used
, reg_base
, mem_ptr
;
2190 #ifdef I860_SVR4_VA_LIST
2191 field_ireg_used
= TYPE_FIELDS (va_list_type_node
);
2192 field_freg_used
= TREE_CHAIN (field_ireg_used
);
2193 field_reg_base
= TREE_CHAIN (field_freg_used
);
2194 field_mem_ptr
= TREE_CHAIN (field_reg_base
);
2196 field_reg_base
= TYPE_FIELDS (va_list_type_node
);
2197 field_mem_ptr
= TREE_CHAIN (field_reg_base
);
2198 field_ireg_used
= TREE_CHAIN (field_mem_ptr
);
2199 field_freg_used
= TREE_CHAIN (field_ireg_used
);
2202 ireg_used
= build (COMPONENT_REF
, TREE_TYPE (field_ireg_used
),
2203 valist
, field_ireg_used
);
2204 freg_used
= build (COMPONENT_REF
, TREE_TYPE (field_freg_used
),
2205 valist
, field_freg_used
);
2206 reg_base
= build (COMPONENT_REF
, TREE_TYPE (field_reg_base
),
2207 valist
, field_reg_base
);
2208 mem_ptr
= build (COMPONENT_REF
, TREE_TYPE (field_mem_ptr
),
2209 valist
, field_mem_ptr
);
2211 t
= build_int_2 (current_function_args_info
.ints
, 0);
2212 t
= build (MODIFY_EXPR
, TREE_TYPE (ireg_used
), ireg_used
, t
);
2213 TREE_SIDE_EFFECTS (t
) = 1;
2214 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
2216 t
= build_int_2 (ROUNDUP (current_function_args_info
.floats
, 8), 0);
2217 t
= build (MODIFY_EXPR
, TREE_TYPE (freg_used
), freg_used
, t
);
2218 TREE_SIDE_EFFECTS (t
) = 1;
2219 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
2221 t
= build (COMPONENT_REF
, TREE_TYPE (field_reg_base
),
2222 saveregs
, field_reg_base
);
2223 t
= build (MODIFY_EXPR
, TREE_TYPE (reg_base
), reg_base
, t
);
2224 TREE_SIDE_EFFECTS (t
) = 1;
2225 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
2227 t
= make_tree (ptr_type_node
, nextarg
);
2228 t
= build (MODIFY_EXPR
, TREE_TYPE (mem_ptr
), mem_ptr
, t
);
2229 TREE_SIDE_EFFECTS (t
) = 1;
2230 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
2234 t
= build (MODIFY_EXPR
, va_list_type_node
, valist
, saveregs
);
2235 TREE_SIDE_EFFECTS (t
) = 1;
2236 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
2240 #define NUM_PARM_FREGS 8
2241 #define NUM_PARM_IREGS 12
2242 #ifdef I860_SVR4_VARARGS
2243 #define FREG_OFFSET 0
2244 #define IREG_OFFSET (NUM_PARM_FREGS * UNITS_PER_WORD)
2246 #define FREG_OFFSET (NUM_PARM_IREGS * UNITS_PER_WORD)
2247 #define IREG_OFFSET 0
2251 i860_va_arg (valist
, type
)
2254 tree field_ireg_used
, field_freg_used
, field_reg_base
, field_mem_ptr
;
2255 tree type_ptr_node
, t
;
2256 rtx lab_over
= NULL_RTX
;
2258 HOST_WIDE_INT align
;
2260 #ifdef I860_SVR4_VA_LIST
2261 field_ireg_used
= TYPE_FIELDS (va_list_type_node
);
2262 field_freg_used
= TREE_CHAIN (field_ireg_used
);
2263 field_reg_base
= TREE_CHAIN (field_freg_used
);
2264 field_mem_ptr
= TREE_CHAIN (field_reg_base
);
2266 field_reg_base
= TYPE_FIELDS (va_list_type_node
);
2267 field_mem_ptr
= TREE_CHAIN (field_reg_base
);
2268 field_ireg_used
= TREE_CHAIN (field_mem_ptr
);
2269 field_freg_used
= TREE_CHAIN (field_ireg_used
);
2272 field_ireg_used
= build (COMPONENT_REF
, TREE_TYPE (field_ireg_used
),
2273 valist
, field_ireg_used
);
2274 field_freg_used
= build (COMPONENT_REF
, TREE_TYPE (field_freg_used
),
2275 valist
, field_freg_used
);
2276 field_reg_base
= build (COMPONENT_REF
, TREE_TYPE (field_reg_base
),
2277 valist
, field_reg_base
);
2278 field_mem_ptr
= build (COMPONENT_REF
, TREE_TYPE (field_mem_ptr
),
2279 valist
, field_mem_ptr
);
2281 ret
= gen_reg_rtx (Pmode
);
2282 type_ptr_node
= build_pointer_type (type
);
2284 if (! AGGREGATE_TYPE_P (type
))
2286 int nparm
, incr
, ofs
;
2290 if (FLOAT_TYPE_P (type
))
2292 field
= field_freg_used
;
2293 nparm
= NUM_PARM_FREGS
;
2299 field
= field_ireg_used
;
2300 nparm
= NUM_PARM_IREGS
;
2301 incr
= int_size_in_bytes (type
) / UNITS_PER_WORD
;
2305 lab_false
= gen_label_rtx ();
2306 lab_over
= gen_label_rtx ();
2308 emit_cmp_and_jump_insns (expand_expr (field
, NULL_RTX
, 0, 0),
2309 GEN_INT (nparm
- incr
), GT
, const0_rtx
,
2310 TYPE_MODE (TREE_TYPE (field
)),
2311 TREE_UNSIGNED (field
), 0, lab_false
);
2313 t
= fold (build (POSTINCREMENT_EXPR
, TREE_TYPE (field
), field
,
2314 build_int_2 (incr
, 0)));
2315 TREE_SIDE_EFFECTS (t
) = 1;
2317 t
= fold (build (MULT_EXPR
, TREE_TYPE (field
), field
,
2318 build_int_2 (UNITS_PER_WORD
, 0)));
2319 TREE_SIDE_EFFECTS (t
) = 1;
2321 t
= fold (build (PLUS_EXPR
, ptr_type_node
, field_reg_base
,
2322 fold (build (PLUS_EXPR
, TREE_TYPE (field
), t
,
2323 build_int_2 (ofs
, 0)))));
2324 TREE_SIDE_EFFECTS (t
) = 1;
2326 val
= expand_expr (t
, ret
, VOIDmode
, EXPAND_NORMAL
);
2328 emit_move_insn (ret
, val
);
2330 emit_jump_insn (gen_jump (lab_over
));
2332 emit_label (lab_false
);
2335 align
= TYPE_ALIGN (type
);
2336 if (align
< BITS_PER_WORD
)
2337 align
= BITS_PER_WORD
;
2338 align
/= BITS_PER_UNIT
;
2340 t
= build (PLUS_EXPR
, ptr_type_node
, field_mem_ptr
,
2341 build_int_2 (align
- 1, 0));
2342 t
= build (BIT_AND_EXPR
, ptr_type_node
, t
, build_int_2 (-align
, -1));
2344 val
= expand_expr (t
, ret
, VOIDmode
, EXPAND_NORMAL
);
2346 emit_move_insn (ret
, val
);
2348 t
= fold (build (PLUS_EXPR
, ptr_type_node
,
2349 make_tree (ptr_type_node
, ret
),
2350 build_int_2 (int_size_in_bytes (type
), 0)));
2351 t
= build (MODIFY_EXPR
, ptr_type_node
, field_mem_ptr
, t
);
2352 TREE_SIDE_EFFECTS (t
) = 1;
2353 expand_expr (t
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
2356 emit_label (lab_over
);