1 /* Subroutines for insn-output.c for Intel 860
2 Copyright (C) 1989, 1991, 1997, 1998, 1999, 2000, 2001
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));
54 static void i860_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
55 static void i860_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
57 #ifndef I860_REG_PREFIX
58 #define I860_REG_PREFIX ""
61 const char *i860_reg_prefix = I860_REG_PREFIX;
63 /* Save information from a "cmpxx" operation until the branch is emitted. */
65 rtx i860_compare_op0, i860_compare_op1;
67 /* Initialize the GCC target structure. */
68 #undef TARGET_ASM_FUNCTION_PROLOGUE
69 #define TARGET_ASM_FUNCTION_PROLOGUE i860_output_function_prologue
70 #undef TARGET_ASM_FUNCTION_EPILOGUE
71 #define TARGET_ASM_FUNCTION_EPILOGUE i860_output_function_epilogue
73 struct gcc_target targetm = TARGET_INITIALIZER;
75 /* Return non-zero if this pattern, can be evaluated safely, even if it
78 safe_insn_src_p (op, mode)
80 enum machine_mode mode;
82 /* Just experimenting. */
84 /* No floating point src is safe if it contains an arithmetic
85 operation, since that operation may trap. */
86 switch (GET_CODE (op))
98 return CONSTANT_ADDRESS_P (XEXP (op, 0));
100 /* We never need to negate or complement constants. */
102 return (mode != SFmode && mode != DFmode);
119 return (mode != SFmode && mode != DFmode);
126 if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
127 || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
136 /* Return 1 if REG is clobbered in IN.
137 Return 2 if REG is used in IN.
138 Return 3 if REG is both used and clobbered in IN.
139 Return 0 if neither. */
142 reg_clobbered_p (reg, in)
146 register enum rtx_code code;
151 code = GET_CODE (in);
153 if (code == SET || code == CLOBBER)
155 rtx dest = SET_DEST (in);
159 while (GET_CODE (dest) == STRICT_LOW_PART
160 || GET_CODE (dest) == SUBREG
161 || GET_CODE (dest) == SIGN_EXTRACT
162 || GET_CODE (dest) == ZERO_EXTRACT)
163 dest = XEXP (dest, 0);
167 else if (GET_CODE (dest) == REG
168 && refers_to_regno_p (REGNO (reg),
169 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
173 /* Anything that sets just part of the register
174 is considered using as well as setting it.
175 But note that a straight SUBREG of a single-word value
176 clobbers the entire value. */
177 if (dest != SET_DEST (in)
178 && ! (GET_CODE (SET_DEST (in)) == SUBREG
179 || UNITS_PER_WORD >= GET_MODE_SIZE (GET_MODE (dest))))
186 used = refers_to_regno_p (REGNO (reg),
187 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
190 used = refers_to_regno_p (REGNO (reg),
191 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
195 return set + used * 2;
198 if (refers_to_regno_p (REGNO (reg),
199 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
205 /* Return non-zero if OP can be written to without screwing up
206 GCC's model of what's going on. It is assumed that this operand
207 appears in the dest position of a SET insn in a conditional
208 branch's delay slot. AFTER is the label to start looking from. */
210 operand_clobbered_before_used_after (op, after)
214 /* Just experimenting. */
215 if (GET_CODE (op) == CC0)
217 if (GET_CODE (op) == REG)
221 if (op == stack_pointer_rtx)
224 /* Scan forward from the label, to see if the value of OP
225 is clobbered before the first use. */
227 for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
229 if (GET_CODE (insn) == NOTE)
231 if (GET_CODE (insn) == INSN
232 || GET_CODE (insn) == JUMP_INSN
233 || GET_CODE (insn) == CALL_INSN)
235 switch (reg_clobbered_p (op, PATTERN (insn)))
245 /* If we reach another label without clobbering OP,
246 then we cannot safely write it here. */
247 else if (GET_CODE (insn) == CODE_LABEL)
249 if (GET_CODE (insn) == JUMP_INSN)
251 if (condjump_p (insn))
253 /* This is a jump insn which has already
254 been mangled. We can't tell what it does. */
255 if (GET_CODE (PATTERN (insn)) == PARALLEL)
257 if (! JUMP_LABEL (insn))
259 /* Keep following jumps. */
260 insn = JUMP_LABEL (insn);
266 /* In both of these cases, the first insn executed
267 for this op will be a orh whatever%h,%?r0,%?r31,
268 which is tolerable. */
269 if (GET_CODE (op) == MEM)
270 return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
275 /* Return non-zero if this pattern, as a source to a "SET",
276 is known to yield an instruction of unit size. */
278 single_insn_src_p (op, mode)
280 enum machine_mode mode;
282 switch (GET_CODE (op))
285 /* This is not always a single insn src, technically,
286 but output_delayed_branch knows how to deal with it. */
291 /* This is not a single insn src, technically,
292 but output_delayed_branch knows how to deal with it. */
301 /* We never need to negate or complement constants. */
303 return (mode != DFmode);
310 /* Detect cases that require multiple instructions. */
311 if (CONSTANT_P (XEXP (op, 1))
312 && !(GET_CODE (XEXP (op, 1)) == CONST_INT
313 && SMALL_INT (XEXP (op, 1))))
325 /* Not doing floating point, since they probably
326 take longer than the branch slot they might fill. */
327 return (mode != SFmode && mode != DFmode);
330 if (GET_CODE (XEXP (op, 1)) == NOT)
332 rtx arg = XEXP (XEXP (op, 1), 0);
334 && !(GET_CODE (arg) == CONST_INT
336 || (INTVAL (arg) & 0xffff) == 0)))
341 /* Both small and round numbers take one instruction;
343 if (CONSTANT_P (XEXP (op, 1))
344 && !(GET_CODE (XEXP (op, 1)) == CONST_INT
345 && (SMALL_INT (XEXP (op, 1))
346 || (INTVAL (XEXP (op, 1)) & 0xffff) == 0)))
355 if (SUBREG_BYTE (op) != 0)
357 return single_insn_src_p (SUBREG_REG (op), mode);
359 /* Not doing floating point, since they probably
360 take longer than the branch slot they might fill. */
374 /* Return non-zero only if OP is a register of mode MODE,
377 reg_or_0_operand (op, mode)
379 enum machine_mode mode;
381 return (op == const0_rtx || register_operand (op, mode)
382 || op == CONST0_RTX (mode));
385 /* Return truth value of whether OP can be used as an operands in a three
386 address add/subtract insn (such as add %o1,7,%l2) of mode MODE. */
389 arith_operand (op, mode)
391 enum machine_mode mode;
393 return (register_operand (op, mode)
394 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
397 /* Return 1 if OP is a valid first operand for a logical insn of mode MODE. */
400 logic_operand (op, mode)
402 enum machine_mode mode;
404 return (register_operand (op, mode)
405 || (GET_CODE (op) == CONST_INT && LOGIC_INT (op)));
408 /* Return 1 if OP is a valid first operand for a shift insn of mode MODE. */
411 shift_operand (op, mode)
413 enum machine_mode mode;
415 return (register_operand (op, mode)
416 || (GET_CODE (op) == CONST_INT));
419 /* Return 1 if OP is a valid first operand for either a logical insn
420 or an add insn of mode MODE. */
423 compare_operand (op, mode)
425 enum machine_mode mode;
427 return (register_operand (op, mode)
428 || (GET_CODE (op) == CONST_INT && SMALL_INT (op) && LOGIC_INT (op)));
431 /* Return truth value of whether OP can be used as the 5-bit immediate
432 operand of a bte or btne insn. */
435 bte_operand (op, mode)
437 enum machine_mode mode;
439 return (register_operand (op, mode)
440 || (GET_CODE (op) == CONST_INT
441 && (unsigned) INTVAL (op) < 0x20));
444 /* Return 1 if OP is an indexed memory reference of mode MODE. */
447 indexed_operand (op, mode)
449 enum machine_mode mode;
451 return (GET_CODE (op) == MEM && GET_MODE (op) == mode
452 && GET_CODE (XEXP (op, 0)) == PLUS
453 && GET_MODE (XEXP (op, 0)) == SImode
454 && register_operand (XEXP (XEXP (op, 0), 0), SImode)
455 && register_operand (XEXP (XEXP (op, 0), 1), SImode));
458 /* Return 1 if OP is a suitable source operand for a load insn
462 load_operand (op, mode)
464 enum machine_mode mode;
466 return (memory_operand (op, mode) || indexed_operand (op, mode));
469 /* Return truth value of whether OP is a integer which fits the
470 range constraining immediate operands in add/subtract insns. */
475 enum machine_mode mode ATTRIBUTE_UNUSED;
477 return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
480 /* Return truth value of whether OP is a integer which fits the
481 range constraining immediate operands in logic insns. */
486 enum machine_mode mode ATTRIBUTE_UNUSED;
488 return (GET_CODE (op) == CONST_INT && LOGIC_INT (op));
491 /* Test for a valid operand for a call instruction.
492 Don't allow the arg pointer register or virtual regs
493 since they may change into reg + const, which the patterns
497 call_insn_operand (op, mode)
499 enum machine_mode mode ATTRIBUTE_UNUSED;
501 if (GET_CODE (op) == MEM
502 && (CONSTANT_ADDRESS_P (XEXP (op, 0))
503 || (GET_CODE (XEXP (op, 0)) == REG
504 && XEXP (op, 0) != arg_pointer_rtx
505 && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER
506 && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER))))
511 /* Return the best assembler insn template
512 for moving operands[1] into operands[0] as a fullword. */
515 singlemove_string (operands)
518 if (GET_CODE (operands[0]) == MEM)
520 if (GET_CODE (operands[1]) != MEM)
521 if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
523 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
524 && (cc_prev_status.flags & CC_HI_R31_ADJ)
525 && cc_prev_status.mdep == XEXP (operands[0], 0)))
528 output_asm_insn ("orh %h0,%?r0,%?r31", operands);
530 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
531 cc_status.mdep = XEXP (operands[0], 0);
532 return "st.l %r1,%L0(%?r31)";
535 return "st.l %r1,%0";
542 cc_status.flags &= ~CC_F0_IS_0;
543 xoperands[0] = gen_rtx_REG (SFmode, 32);
544 xoperands[1] = operands[1];
545 output_asm_insn (singlemove_string (xoperands), xoperands);
546 xoperands[1] = xoperands[0];
547 xoperands[0] = operands[0];
548 output_asm_insn (singlemove_string (xoperands), xoperands);
553 if (GET_CODE (operands[1]) == MEM)
555 if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
557 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
558 && (cc_prev_status.flags & CC_HI_R31_ADJ)
559 && cc_prev_status.mdep == XEXP (operands[1], 0)))
562 output_asm_insn ("orh %h1,%?r0,%?r31", operands);
564 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
565 cc_status.mdep = XEXP (operands[1], 0);
566 return "ld.l %L1(%?r31),%0";
568 return "ld.l %m1,%0";
570 if (GET_CODE (operands[1]) == CONST_INT)
572 if (operands[1] == const0_rtx)
573 return "mov %?r0,%0";
574 if((INTVAL (operands[1]) & 0xffff0000) == 0)
575 return "or %L1,%?r0,%0";
576 if((INTVAL (operands[1]) & 0xffff8000) == 0xffff8000)
577 return "adds %1,%?r0,%0";
578 if((INTVAL (operands[1]) & 0x0000ffff) == 0)
579 return "orh %H1,%?r0,%0";
581 return "orh %H1,%?r0,%0\n\tor %L1,%0,%0";
586 /* Output assembler code to perform a doubleword move insn
587 with operands OPERANDS. */
590 output_move_double (operands)
593 enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
595 rtx addreg0 = 0, addreg1 = 0;
596 int highest_first = 0;
597 int no_addreg1_decrement = 0;
599 /* First classify both operands. */
601 if (REG_P (operands[0]))
603 else if (offsettable_memref_p (operands[0]))
605 else if (GET_CODE (operands[0]) == MEM)
610 if (REG_P (operands[1]))
612 else if (CONSTANT_P (operands[1]))
614 else if (offsettable_memref_p (operands[1]))
616 else if (GET_CODE (operands[1]) == MEM)
621 /* Check for the cases that the operand constraints are not
622 supposed to allow to happen. Abort if we get one,
623 because generating code for these cases is painful. */
625 if (optype0 == RNDOP || optype1 == RNDOP)
628 /* If an operand is an unoffsettable memory ref, find a register
629 we can increment temporarily to make it refer to the second word. */
631 if (optype0 == MEMOP)
632 addreg0 = find_addr_reg (XEXP (operands[0], 0));
634 if (optype1 == MEMOP)
635 addreg1 = find_addr_reg (XEXP (operands[1], 0));
637 /* ??? Perhaps in some cases move double words
638 if there is a spare pair of floating regs. */
640 /* Ok, we can do one word at a time.
641 Normally we do the low-numbered word first,
642 but if either operand is autodecrementing then we
643 do the high-numbered word first.
645 In either case, set up in LATEHALF the operands to use
646 for the high-numbered word and in some cases alter the
647 operands in OPERANDS to be suitable for the low-numbered word. */
649 if (optype0 == REGOP)
650 latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
651 else if (optype0 == OFFSOP)
652 latehalf[0] = adjust_address (operands[0], SImode, 4);
654 latehalf[0] = operands[0];
656 if (optype1 == REGOP)
657 latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
658 else if (optype1 == OFFSOP)
659 latehalf[1] = adjust_address (operands[1], SImode, 4);
660 else if (optype1 == CNSTOP)
662 if (GET_CODE (operands[1]) == CONST_DOUBLE)
663 split_double (operands[1], &operands[1], &latehalf[1]);
664 else if (CONSTANT_P (operands[1]))
665 latehalf[1] = const0_rtx;
668 latehalf[1] = operands[1];
670 /* If the first move would clobber the source of the second one,
671 do them in the other order.
673 RMS says "This happens only for registers;
674 such overlap can't happen in memory unless the user explicitly
675 sets it up, and that is an undefined circumstance."
677 but it happens on the sparc when loading parameter registers,
678 so I am going to define that circumstance, and make it work
681 if (optype0 == REGOP && optype1 == REGOP
682 && REGNO (operands[0]) == REGNO (latehalf[1]))
684 CC_STATUS_PARTIAL_INIT;
685 /* Make any unoffsettable addresses point at high-numbered word. */
687 output_asm_insn ("adds 0x4,%0,%0", &addreg0);
689 output_asm_insn ("adds 0x4,%0,%0", &addreg1);
692 output_asm_insn (singlemove_string (latehalf), latehalf);
694 /* Undo the adds we just did. */
696 output_asm_insn ("adds -0x4,%0,%0", &addreg0);
698 output_asm_insn ("adds -0x4,%0,%0", &addreg1);
700 /* Do low-numbered word. */
701 return singlemove_string (operands);
703 else if (optype0 == REGOP && optype1 != REGOP
704 && reg_overlap_mentioned_p (operands[0], operands[1]))
706 /* If both halves of dest are used in the src memory address,
707 add the two regs and put them in the low reg (operands[0]).
708 Then it works to load latehalf first. */
709 if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))
710 && reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
713 xops[0] = latehalf[0];
714 xops[1] = operands[0];
715 output_asm_insn ("adds %1,%0,%1", xops);
716 operands[1] = gen_rtx_MEM (DImode, operands[0]);
717 latehalf[1] = adjust_address (operands[1], SImode, 4);
721 /* Only one register in the dest is used in the src memory address,
722 and this is the first register of the dest, so we want to do
723 the late half first here also. */
724 else if (! reg_mentioned_p (latehalf[0], XEXP (operands[1], 0)))
726 /* Only one register in the dest is used in the src memory address,
727 and this is the second register of the dest, so we want to do
728 the late half last. If addreg1 is set, and addreg1 is the same
729 register as latehalf, then we must suppress the trailing decrement,
730 because it would clobber the value just loaded. */
731 else if (addreg1 && reg_mentioned_p (addreg1, latehalf[0]))
732 no_addreg1_decrement = 1;
735 /* Normal case: do the two words, low-numbered first.
736 Overlap case (highest_first set): do high-numbered word first. */
739 output_asm_insn (singlemove_string (operands), operands);
741 CC_STATUS_PARTIAL_INIT;
742 /* Make any unoffsettable addresses point at high-numbered word. */
744 output_asm_insn ("adds 0x4,%0,%0", &addreg0);
746 output_asm_insn ("adds 0x4,%0,%0", &addreg1);
749 output_asm_insn (singlemove_string (latehalf), latehalf);
751 /* Undo the adds we just did. */
753 output_asm_insn ("adds -0x4,%0,%0", &addreg0);
754 if (addreg1 && !no_addreg1_decrement)
755 output_asm_insn ("adds -0x4,%0,%0", &addreg1);
758 output_asm_insn (singlemove_string (operands), operands);
764 output_fp_move_double (operands)
767 /* If the source operand is any sort of zero, use f0 instead. */
769 if (operands[1] == CONST0_RTX (GET_MODE (operands[1])))
770 operands[1] = gen_rtx_REG (DFmode, F0_REGNUM);
772 if (FP_REG_P (operands[0]))
774 if (FP_REG_P (operands[1]))
775 return "fmov.dd %1,%0";
776 if (GET_CODE (operands[1]) == REG)
778 output_asm_insn ("ixfr %1,%0", operands);
779 operands[0] = gen_rtx_REG (VOIDmode, REGNO (operands[0]) + 1);
780 operands[1] = gen_rtx_REG (VOIDmode, REGNO (operands[1]) + 1);
783 if (operands[1] == CONST0_RTX (DFmode))
784 return "fmov.dd f0,%0";
785 if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
787 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
788 && (cc_prev_status.flags & CC_HI_R31_ADJ)
789 && cc_prev_status.mdep == XEXP (operands[1], 0)))
792 output_asm_insn ("orh %h1,%?r0,%?r31", operands);
794 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
795 cc_status.mdep = XEXP (operands[1], 0);
796 return "fld.d %L1(%?r31),%0";
798 return "fld.d %1,%0";
800 else if (FP_REG_P (operands[1]))
802 if (GET_CODE (operands[0]) == REG)
804 output_asm_insn ("fxfr %1,%0", operands);
805 operands[0] = gen_rtx_REG (VOIDmode, REGNO (operands[0]) + 1);
806 operands[1] = gen_rtx_REG (VOIDmode, REGNO (operands[1]) + 1);
809 if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
811 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
812 && (cc_prev_status.flags & CC_HI_R31_ADJ)
813 && cc_prev_status.mdep == XEXP (operands[0], 0)))
816 output_asm_insn ("orh %h0,%?r0,%?r31", operands);
818 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
819 cc_status.mdep = XEXP (operands[0], 0);
820 return "fst.d %1,%L0(%?r31)";
822 return "fst.d %1,%0";
830 /* Return a REG that occurs in ADDR with coefficient 1.
831 ADDR can be effectively incremented by incrementing REG. */
837 while (GET_CODE (addr) == PLUS)
839 if (GET_CODE (XEXP (addr, 0)) == REG)
840 addr = XEXP (addr, 0);
841 else if (GET_CODE (XEXP (addr, 1)) == REG)
842 addr = XEXP (addr, 1);
843 else if (CONSTANT_P (XEXP (addr, 0)))
844 addr = XEXP (addr, 1);
845 else if (CONSTANT_P (XEXP (addr, 1)))
846 addr = XEXP (addr, 0);
850 if (GET_CODE (addr) == REG)
857 /* Return a template for a load instruction with mode MODE and
858 arguments from the string ARGS.
860 This string is in static storage. */
863 load_opcode (mode, args, reg)
864 enum machine_mode mode;
900 sprintf (buf, "%s %s", opcode, args);
904 /* Return a template for a store instruction with mode MODE and
905 arguments from the string ARGS.
907 This string is in static storage. */
910 store_opcode (mode, args, reg)
911 enum machine_mode mode;
947 sprintf (buf, "%s %s", opcode, args);
951 /* Output a store-in-memory whose operands are OPERANDS[0,1].
952 OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.
954 This function returns a template for an insn.
955 This is in static storage.
957 It may also output some insns directly.
958 It may alter the values of operands[0] and operands[1]. */
961 output_store (operands)
964 enum machine_mode mode = GET_MODE (operands[0]);
965 rtx address = XEXP (operands[0], 0);
967 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
968 cc_status.mdep = address;
970 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
971 && (cc_prev_status.flags & CC_HI_R31_ADJ)
972 && address == cc_prev_status.mdep))
975 output_asm_insn ("orh %h0,%?r0,%?r31", operands);
976 cc_prev_status.mdep = address;
979 /* Store zero in two parts when appropriate. */
980 if (mode == DFmode && operands[1] == CONST0_RTX (DFmode))
981 return store_opcode (DFmode, "%r1,%L0(%?r31)", operands[1]);
983 /* Code below isn't smart enough to move a doubleword in two parts,
984 so use output_move_double to do that in the cases that require it. */
985 if ((mode == DImode || mode == DFmode)
986 && ! FP_REG_P (operands[1]))
987 return output_move_double (operands);
989 return store_opcode (mode, "%r1,%L0(%?r31)", operands[1]);
992 /* Output a load-from-memory whose operands are OPERANDS[0,1].
993 OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
995 This function returns a template for an insn.
996 This is in static storage.
998 It may also output some insns directly.
999 It may alter the values of operands[0] and operands[1]. */
1002 output_load (operands)
1005 enum machine_mode mode = GET_MODE (operands[0]);
1006 rtx address = XEXP (operands[1], 0);
1008 /* We don't bother trying to see if we know %hi(address).
1009 This is because we are doing a load, and if we know the
1010 %hi value, we probably also know that value in memory. */
1011 cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
1012 cc_status.mdep = address;
1014 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1015 && (cc_prev_status.flags & CC_HI_R31_ADJ)
1016 && address == cc_prev_status.mdep
1017 && cc_prev_status.mdep == cc_status.mdep))
1020 output_asm_insn ("orh %h1,%?r0,%?r31", operands);
1021 cc_prev_status.mdep = address;
1024 /* Code below isn't smart enough to move a doubleword in two parts,
1025 so use output_move_double to do that in the cases that require it. */
1026 if ((mode == DImode || mode == DFmode)
1027 && ! FP_REG_P (operands[0]))
1028 return output_move_double (operands);
1030 return load_opcode (mode, "%L1(%?r31),%0", operands[0]);
1034 /* Load the address specified by OPERANDS[3] into the register
1035 specified by OPERANDS[0].
1037 OPERANDS[3] may be the result of a sum, hence it could either be:
1042 (3) REG + REG + CONST_INT
1043 (4) REG + REG (special case of 3).
1045 Note that (3) is not a legitimate address.
1046 All cases are handled here. */
1049 output_load_address (operands)
1054 if (CONSTANT_P (operands[3]))
1056 output_asm_insn ("mov %3,%0", operands);
1060 if (REG_P (operands[3]))
1062 if (REGNO (operands[0]) != REGNO (operands[3]))
1063 output_asm_insn ("shl %?r0,%3,%0", operands);
1067 if (GET_CODE (operands[3]) != PLUS)
1070 base = XEXP (operands[3], 0);
1071 offset = XEXP (operands[3], 1);
1073 if (GET_CODE (base) == CONST_INT)
1080 if (GET_CODE (offset) != CONST_INT)
1082 /* Operand is (PLUS (REG) (REG)). */
1084 offset = const0_rtx;
1090 operands[7] = offset;
1091 CC_STATUS_PARTIAL_INIT;
1092 if (SMALL_INT (offset))
1093 output_asm_insn ("adds %7,%6,%0", operands);
1095 output_asm_insn ("mov %7,%0\n\tadds %0,%6,%0", operands);
1097 else if (GET_CODE (base) == PLUS)
1099 operands[6] = XEXP (base, 0);
1100 operands[7] = XEXP (base, 1);
1101 operands[8] = offset;
1103 CC_STATUS_PARTIAL_INIT;
1104 if (SMALL_INT (offset))
1105 output_asm_insn ("adds %6,%7,%0\n\tadds %8,%0,%0", operands);
1107 output_asm_insn ("mov %8,%0\n\tadds %0,%6,%0\n\tadds %0,%7,%0", operands);
1114 /* Output code to place a size count SIZE in register REG.
1115 Because block moves are pipelined, we don't include the
1116 first element in the transfer of SIZE to REG.
1117 For this, we subtract ALIGN. (Actually, I think it is not
1118 right to subtract on this machine, so right now we don't.) */
1121 output_size_for_block_move (size, reg, align)
1122 rtx size, reg, align;
1127 xoperands[1] = size;
1128 xoperands[2] = align;
1131 cc_status.flags &= ~ CC_KNOW_HI_R31;
1132 output_asm_insn (singlemove_string (xoperands), xoperands);
1134 if (GET_CODE (size) == REG)
1135 output_asm_insn ("sub %2,%1,%0", xoperands);
1138 xoperands[1] = GEN_INT (INTVAL (size) - INTVAL (align));
1139 cc_status.flags &= ~ CC_KNOW_HI_R31;
1140 output_asm_insn ("mov %1,%0", xoperands);
1145 /* Emit code to perform a block move.
1147 OPERANDS[0] is the destination.
1148 OPERANDS[1] is the source.
1149 OPERANDS[2] is the size.
1150 OPERANDS[3] is the known safe alignment.
1151 OPERANDS[4..6] are pseudos we can safely clobber as temps. */
1154 output_block_move (operands)
1157 /* A vector for our computed operands. Note that load_output_address
1158 makes use of (and can clobber) up to the 8th element of this vector. */
1163 static int movstrsi_label = 0;
1165 rtx temp1 = operands[4];
1166 rtx alignrtx = operands[3];
1167 int align = INTVAL (alignrtx);
1170 xoperands[0] = operands[0];
1171 xoperands[1] = operands[1];
1172 xoperands[2] = temp1;
1174 /* We can't move more than four bytes at a time
1175 because we have only one register to move them through. */
1179 alignrtx = GEN_INT (4);
1182 /* Recognize special cases of block moves. These occur
1183 when GNU C++ is forced to treat something as BLKmode
1184 to keep it in memory, when its mode could be represented
1185 with something smaller.
1187 We cannot do this for global variables, since we don't know
1188 what pages they don't cross. Sigh. */
1189 if (GET_CODE (operands[2]) == CONST_INT
1190 && ! CONSTANT_ADDRESS_P (operands[0])
1191 && ! CONSTANT_ADDRESS_P (operands[1]))
1193 int size = INTVAL (operands[2]);
1194 rtx op0 = xoperands[0];
1195 rtx op1 = xoperands[1];
1197 if ((align & 3) == 0 && (size & 3) == 0 && (size >> 2) <= 16)
1199 if (memory_address_p (SImode, plus_constant (op0, size))
1200 && memory_address_p (SImode, plus_constant (op1, size)))
1202 cc_status.flags &= ~CC_KNOW_HI_R31;
1203 for (i = (size>>2)-1; i >= 0; i--)
1205 xoperands[0] = plus_constant (op0, i * 4);
1206 xoperands[1] = plus_constant (op1, i * 4);
1207 output_asm_insn ("ld.l %a1,%?r31\n\tst.l %?r31,%a0",
1213 else if ((align & 1) == 0 && (size & 1) == 0 && (size >> 1) <= 16)
1215 if (memory_address_p (HImode, plus_constant (op0, size))
1216 && memory_address_p (HImode, plus_constant (op1, size)))
1218 cc_status.flags &= ~CC_KNOW_HI_R31;
1219 for (i = (size>>1)-1; i >= 0; i--)
1221 xoperands[0] = plus_constant (op0, i * 2);
1222 xoperands[1] = plus_constant (op1, i * 2);
1223 output_asm_insn ("ld.s %a1,%?r31\n\tst.s %?r31,%a0",
1229 else if (size <= 16)
1231 if (memory_address_p (QImode, plus_constant (op0, size))
1232 && memory_address_p (QImode, plus_constant (op1, size)))
1234 cc_status.flags &= ~CC_KNOW_HI_R31;
1235 for (i = size-1; i >= 0; i--)
1237 xoperands[0] = plus_constant (op0, i);
1238 xoperands[1] = plus_constant (op1, i);
1239 output_asm_insn ("ld.b %a1,%?r31\n\tst.b %?r31,%a0",
1247 /* Since we clobber untold things, nix the condition codes. */
1250 /* This is the size of the transfer.
1251 Either use the register which already contains the size,
1252 or use a free register (used by no operands). */
1253 output_size_for_block_move (operands[2], operands[4], alignrtx);
1256 /* Also emit code to decrement the size value by ALIGN. */
1257 zoperands[0] = operands[0];
1258 zoperands[3] = plus_constant (operands[0], align);
1259 output_load_address (zoperands);
1262 /* Generate number for unique label. */
1264 xoperands[3] = GEN_INT (movstrsi_label++);
1266 /* Calculate the size of the chunks we will be trying to move first. */
1269 if ((align & 3) == 0)
1271 else if ((align & 1) == 0)
1277 /* Copy the increment (negative) to a register for bla insn. */
1279 xoperands[4] = GEN_INT (- chunk_size);
1280 xoperands[5] = operands[5];
1281 output_asm_insn ("adds %4,%?r0,%5", xoperands);
1283 /* Predecrement the loop counter. This happens again also in the `bla'
1284 instruction which precedes the loop, but we need to have it done
1285 two times before we enter the loop because of the bizarre semantics
1286 of the bla instruction. */
1288 output_asm_insn ("adds %5,%2,%2", xoperands);
1290 /* Check for the case where the original count was less than or equal to
1291 zero. Avoid going through the loop at all if the original count was
1292 indeed less than or equal to zero. Note that we treat the count as
1293 if it were a signed 32-bit quantity here, rather than an unsigned one,
1294 even though we really shouldn't. We have to do this because of the
1295 semantics of the `ble' instruction, which assume that the count is
1296 a signed 32-bit value. Anyway, in practice it won't matter because
1297 nobody is going to try to do a memcpy() of more than half of the
1298 entire address space (i.e. 2 gigabytes) anyway. */
1300 output_asm_insn ("bc .Le%3", xoperands);
1302 /* Make available a register which is a temporary. */
1304 xoperands[6] = operands[6];
1306 /* Now the actual loop.
1307 In xoperands, elements 1 and 0 are the input and output vectors.
1308 Element 2 is the loop index. Element 5 is the increment. */
1310 output_asm_insn ("subs %1,%5,%1", xoperands);
1311 output_asm_insn ("bla %5,%2,.Lm%3", xoperands);
1312 output_asm_insn ("adds %0,%2,%6", xoperands);
1313 output_asm_insn ("\n.Lm%3:", xoperands); /* Label for bla above. */
1314 output_asm_insn ("\n.Ls%3:", xoperands); /* Loop start label. */
1315 output_asm_insn ("adds %5,%6,%6", xoperands);
1317 /* NOTE: The code here which is supposed to handle the cases where the
1318 sources and destinations are known to start on a 4 or 2 byte boundary
1319 are currently broken. They fail to do anything about the overflow
1320 bytes which might still need to be copied even after we have copied
1321 some number of words or halfwords. Thus, for now we use the lowest
1322 common denominator, i.e. the code which just copies some number of
1323 totally unaligned individual bytes. (See the calculation of
1324 chunk_size above. */
1326 if (chunk_size == 4)
1328 output_asm_insn ("ld.l %2(%1),%?r31", xoperands);
1329 output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
1330 output_asm_insn ("st.l %?r31,8(%6)", xoperands);
1332 else if (chunk_size == 2)
1334 output_asm_insn ("ld.s %2(%1),%?r31", xoperands);
1335 output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
1336 output_asm_insn ("st.s %?r31,4(%6)", xoperands);
1338 else /* chunk_size == 1 */
1340 output_asm_insn ("ld.b %2(%1),%?r31", xoperands);
1341 output_asm_insn ("bla %5,%2,.Ls%3", xoperands);
1342 output_asm_insn ("st.b %?r31,2(%6)", xoperands);
1344 output_asm_insn ("\n.Le%3:", xoperands); /* Here if count <= 0. */
1350 /* Output a delayed branch insn with the delay insn in its
1351 branch slot. The delayed branch insn template is in TEMPLATE,
1352 with operands OPERANDS. The insn in its delay slot is INSN.
1354 As a special case, since we know that all memory transfers are via
1355 ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
1356 reference around the branch as
1360 ld/st l%x(%?r31),...
1362 As another special case, we handle loading (SYMBOL_REF ...) and
1363 other large constants around branches as well:
1370 /* ??? Disabled because this re-recognition is incomplete and causes
1371 constrain_operands to segfault. Anyone who cares should fix up
1372 the code to use the DBR pass. */
1375 output_delayed_branch (template, operands, insn)
1376 const char *template;
1380 rtx src = XVECEXP (PATTERN (insn), 0, 1);
1381 rtx dest = XVECEXP (PATTERN (insn), 0, 0);
1383 /* See if we are doing some branch together with setting some register
1384 to some 32-bit value which does (or may) have some of the high-order
1385 16 bits set. If so, we need to set the register in two stages. One
1386 stage must be done before the branch, and the other one can be done
1387 in the delay slot. */
1389 if ( (GET_CODE (src) == CONST_INT
1390 && ((unsigned) INTVAL (src) & (unsigned) 0xffff0000) != (unsigned) 0)
1391 || (GET_CODE (src) == SYMBOL_REF)
1392 || (GET_CODE (src) == LABEL_REF)
1393 || (GET_CODE (src) == CONST))
1396 xoperands[0] = dest;
1399 CC_STATUS_PARTIAL_INIT;
1400 /* Output the `orh' insn. */
1401 output_asm_insn ("orh %H1,%?r0,%0", xoperands);
1403 /* Output the branch instruction next. */
1404 output_asm_insn (template, operands);
1406 /* Now output the `or' insn. */
1407 output_asm_insn ("or %L1,%0,%0", xoperands);
1409 else if ((GET_CODE (src) == MEM
1410 && CONSTANT_ADDRESS_P (XEXP (src, 0)))
1411 || (GET_CODE (dest) == MEM
1412 && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
1415 const char *split_template;
1416 xoperands[0] = dest;
1419 /* Output the `orh' insn. */
1420 if (GET_CODE (src) == MEM)
1422 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1423 && (cc_prev_status.flags & CC_HI_R31_ADJ)
1424 && cc_prev_status.mdep == XEXP (operands[1], 0)))
1427 output_asm_insn ("orh %h1,%?r0,%?r31", xoperands);
1429 split_template = load_opcode (GET_MODE (dest),
1430 "%L1(%?r31),%0", dest);
1434 if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
1435 && (cc_prev_status.flags & CC_HI_R31_ADJ)
1436 && cc_prev_status.mdep == XEXP (operands[0], 0)))
1439 output_asm_insn ("orh %h0,%?r0,%?r31", xoperands);
1441 split_template = store_opcode (GET_MODE (dest),
1442 "%r1,%L0(%?r31)", src);
1445 /* Output the branch instruction next. */
1446 output_asm_insn (template, operands);
1448 /* Now output the load or store.
1449 No need to do a CC_STATUS_INIT, because we are branching anyway. */
1450 output_asm_insn (split_template, xoperands);
1454 int insn_code_number;
1455 rtx pat = gen_rtx_SET (VOIDmode, dest, src);
1456 rtx delay_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, pat, -1, 0, 0);
1459 /* Output the branch instruction first. */
1460 output_asm_insn (template, operands);
1462 /* Now recognize the insn which we put in its delay slot.
1463 We must do this after outputting the branch insn,
1464 since operands may just be a pointer to `recog_data.operand'. */
1465 INSN_CODE (delay_insn) = insn_code_number
1466 = recog (pat, delay_insn, NULL);
1467 if (insn_code_number == -1)
1470 for (i = 0; i < insn_data[insn_code_number].n_operands; i++)
1472 if (GET_CODE (recog_data.operand[i]) == SUBREG)
1473 recog_data.operand[i] = alter_subreg (recog_data.operand[i]);
1476 insn_extract (delay_insn);
1477 if (! constrain_operands (1))
1478 fatal_insn_not_found (delay_insn);
1480 template = get_insn_template (insn_code_number, delay_insn);
1481 output_asm_insn (template, recog_data.operand);
1487 /* Output a newly constructed insn DELAY_INSN. */
1489 output_delay_insn (delay_insn)
1492 const char *template;
1493 int insn_code_number;
1496 /* Now recognize the insn which we put in its delay slot.
1497 We must do this after outputting the branch insn,
1498 since operands may just be a pointer to `recog_data.operand'. */
1499 insn_code_number = recog_memoized (delay_insn);
1500 if (insn_code_number == -1)
1503 /* Extract the operands of this delay insn. */
1504 INSN_CODE (delay_insn) = insn_code_number;
1505 insn_extract (delay_insn);
1507 /* It is possible that this insn has not been properly scanned by final
1508 yet. If this insn's operands don't appear in the peephole's
1509 actual operands, then they won't be fixed up by final, so we
1510 make sure they get fixed up here. -- This is a kludge. */
1511 for (i = 0; i < insn_data[insn_code_number].n_operands; i++)
1513 if (GET_CODE (recog_data.operand[i]) == SUBREG)
1514 recog_data.operand[i] = alter_subreg (recog_data.operand[i]);
1517 if (! constrain_operands (1))
1520 cc_prev_status = cc_status;
1522 /* Update `cc_status' for this instruction.
1523 The instruction's output routine may change it further.
1524 If the output routine for a jump insn needs to depend
1525 on the cc status, it should look at cc_prev_status. */
1527 NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
1529 /* Now get the template for what this insn would
1530 have been, without the branch. */
1532 template = get_insn_template (insn_code_number, delay_insn);
1533 output_asm_insn (template, recog_data.operand);
1538 /* Special routine to convert an SFmode value represented as a
1539 CONST_DOUBLE into its equivalent unsigned long bit pattern.
1540 We convert the value from a double precision floating-point
1541 value to single precision first, and thence to a bit-wise
1542 equivalent unsigned long value. This routine is used when
1543 generating an immediate move of an SFmode value directly
1544 into a general register because the svr4 assembler doesn't
1545 grok floating literals in instruction operand contexts. */
1548 sfmode_constant_to_ulong (x)
1552 union { float f; unsigned long i; } u2;
1554 if (GET_CODE (x) != CONST_DOUBLE || GET_MODE (x) != SFmode)
1557 #if TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT
1558 error IEEE emulation needed
1560 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
1565 /* This function generates the assembly code for function entry.
1567 ASM_FILE is a stdio stream to output the code to.
1568 SIZE is an int: how many units of temporary storage to allocate.
1570 Refer to the array `regs_ever_live' to determine which registers
1571 to save; `regs_ever_live[I]' is nonzero if register number I
1572 is ever used in the function. This macro is responsible for
1573 knowing which registers should not be saved even if used.
1575 NOTE: `frame_lower_bytes' is the count of bytes which will lie
1576 between the new `fp' value and the new `sp' value after the
1577 prologue is done. `frame_upper_bytes' is the count of bytes
1578 that will lie between the new `fp' and the *old* `sp' value
1579 after the new `fp' is setup (in the prologue). The upper
1580 part of each frame always includes at least 2 words (8 bytes)
1581 to hold the saved frame pointer and the saved return address.
1583 The svr4 ABI for the i860 now requires that the values of the
1584 stack pointer and frame pointer registers be kept aligned to
1585 16-byte boundaries at all times. We obey that restriction here.
1587 The svr4 ABI for the i860 is entirely vague when it comes to specifying
1588 exactly where the "preserved" registers should be saved. The native
1589 svr4 C compiler I now have doesn't help to clarify the requirements
1590 very much because it is plainly out-of-date and non-ABI-compliant
1591 (in at least one important way, i.e. how it generates function
1594 The native svr4 C compiler saves the "preserved" registers (i.e.
1595 r4-r15 and f2-f7) in the lower part of a frame (i.e. at negative
1596 offsets from the frame pointer).
1598 Previous versions of GCC also saved the "preserved" registers in the
1599 "negative" part of the frame, but they saved them using positive
1600 offsets from the (adjusted) stack pointer (after it had been adjusted
1601 to allocate space for the new frame). That's just plain wrong
1602 because if the current function calls alloca(), the stack pointer
1603 will get moved, and it will be impossible to restore the registers
1604 properly again after that.
1606 Both compilers handled parameter registers (i.e. r16-r27 and f8-f15)
1607 by copying their values either into various "preserved" registers or
1608 into stack slots in the lower part of the current frame (as seemed
1609 appropriate, depending upon subsequent usage of these values).
1611 Here we want to save the preserved registers at some offset from the
1612 frame pointer register so as to avoid any possible problems arising
1613 from calls to alloca(). We can either save them at small positive
1614 offsets from the frame pointer, or at small negative offsets from
1615 the frame pointer. If we save them at small negative offsets from
1616 the frame pointer (i.e. in the lower part of the frame) then we
1617 must tell the rest of GCC (via STARTING_FRAME_OFFSET) exactly how
1618 many bytes of space we plan to use in the lower part of the frame
1619 for this purpose. Since other parts of the compiler reference the
1620 value of STARTING_FRAME_OFFSET long before final() calls this function,
1621 we would have to go ahead and assume the worst-case storage requirements
1622 for saving all of the "preserved" registers (and use that number, i.e.
1623 `80', to define STARTING_FRAME_OFFSET) if we wanted to save them in
1624 the lower part of the frame. That could potentially be very wasteful,
1625 and that wastefulness could really hamper people compiling for embedded
1626 i860 targets with very tight limits on stack space. Thus, we choose
1627 here to save the preserved registers in the upper part of the
1628 frame, so that we can decide at the very last minute how much (or how
1629 little) space we must allocate for this purpose.
1631 To satisfy the needs of the svr4 ABI "tdesc" scheme, preserved
1632 registers must always be saved so that the saved values of registers
1633 with higher numbers are at higher addresses. We obey that restriction
1636 There are two somewhat different ways that you can generate prologues
1637 here... i.e. pedantically ABI-compliant, and the "other" way. The
1638 "other" way is more consistent with what is currently generated by the
1639 "native" svr4 C compiler for the i860. That's important if you want
1640 to use the current (as of 8/91) incarnation of svr4 SDB for the i860.
1641 The SVR4 SDB for the i860 insists on having function prologues be
1644 To get fully ABI-compliant prologues, define I860_STRICT_ABI_PROLOGUES
1645 in the i860svr4.h file. (By default this is *not* defined).
1647 The differences between the ABI-compliant and non-ABI-compliant prologues
1648 are that (a) the ABI version seems to require the use of *signed*
1649 (rather than unsigned) adds and subtracts, and (b) the ordering of
1650 the various steps (e.g. saving preserved registers, saving the
1651 return address, setting up the new frame pointer value) is different.
1653 For strict ABI compliance, it seems to be the case that the very last
1654 thing that is supposed to happen in the prologue is getting the frame
1655 pointer set to its new value (but only after everything else has
1656 already been properly setup). We do that here, but only if the symbol
1657 I860_STRICT_ABI_PROLOGUES is defined.
1660 #ifndef STACK_ALIGNMENT
1661 #define STACK_ALIGNMENT 16
1664 extern char call_used_regs[];
1666 char *current_function_original_name;
1668 static int must_preserve_r1;
1669 static unsigned must_preserve_bytes;
1672 i860_output_function_prologue (asm_file, local_bytes)
1673 register FILE *asm_file;
1674 register HOST_WIDE_INT local_bytes;
1676 register HOST_WIDE_INT frame_lower_bytes;
1677 register HOST_WIDE_INT frame_upper_bytes;
1678 register HOST_WIDE_INT total_fsize;
1679 register unsigned preserved_reg_bytes = 0;
1680 register unsigned i;
1681 register unsigned preserved_so_far = 0;
1683 must_preserve_r1 = (optimize < 2 || ! leaf_function_p ());
1684 must_preserve_bytes = 4 + (must_preserve_r1 ? 4 : 0);
1686 /* Count registers that need preserving. Ignore r0. It never needs
1689 for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
1691 if (regs_ever_live[i] && ! call_used_regs[i])
1692 preserved_reg_bytes += 4;
1695 /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
1697 frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1699 /* The upper part of each frame will contain the saved fp,
1700 the saved r1, and stack slots for all of the other "preserved"
1701 registers that we find we will need to save & restore. */
1703 frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
1705 /* Round-up the frame_upper_bytes so that it's a multiple of 16. */
1708 = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
1710 total_fsize = frame_upper_bytes + frame_lower_bytes;
1712 #ifndef I860_STRICT_ABI_PROLOGUES
1714 /* There are two kinds of function prologues.
1715 You use the "small" version if the total frame size is
1716 small enough so that it can fit into an immediate 16-bit
1717 value in one instruction. Otherwise, you use the "large"
1718 version of the function prologue. */
1720 if (total_fsize > 0x7fff)
1722 /* Adjust the stack pointer. The ABI sez to do this using `adds',
1723 but the native C compiler on svr4 uses `addu'. */
1725 fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
1726 frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
1728 /* Save the old frame pointer. */
1730 fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
1731 i860_reg_prefix, i860_reg_prefix);
1733 /* Setup the new frame pointer. The ABI sez to do this after
1734 preserving registers (using adds), but that's not what the
1735 native C compiler on svr4 does. */
1737 fprintf (asm_file, "\taddu 0,%ssp,%sfp\n",
1738 i860_reg_prefix, i860_reg_prefix);
1740 /* Get the value of frame_lower_bytes into r31. */
1742 fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
1743 frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
1744 fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
1745 frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
1747 /* Now re-adjust the stack pointer using the value in r31.
1748 The ABI sez to do this with `subs' but SDB may prefer `subu'. */
1750 fprintf (asm_file, "\tsubu %ssp,%sr31,%ssp\n",
1751 i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1753 /* Preserve registers. The ABI sez to do this before setting
1754 up the new frame pointer, but that's not what the native
1755 C compiler on svr4 does. */
1757 for (i = 1; i < 32; i++)
1758 if (regs_ever_live[i] && ! call_used_regs[i])
1759 fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
1760 i860_reg_prefix, reg_names[i],
1761 must_preserve_bytes + (4 * preserved_so_far++),
1764 for (i = 32; i < 64; i++)
1765 if (regs_ever_live[i] && ! call_used_regs[i])
1766 fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
1767 i860_reg_prefix, reg_names[i],
1768 must_preserve_bytes + (4 * preserved_so_far++),
1771 /* Save the return address. */
1773 if (must_preserve_r1)
1774 fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
1775 i860_reg_prefix, i860_reg_prefix);
1779 /* Adjust the stack pointer. The ABI sez to do this using `adds',
1780 but the native C compiler on svr4 uses `addu'. */
1782 fprintf (asm_file, "\taddu -%d,%ssp,%ssp\n",
1783 total_fsize, i860_reg_prefix, i860_reg_prefix);
1785 /* Save the old frame pointer. */
1787 fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
1788 i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
1790 /* Setup the new frame pointer. The ABI sez to do this after
1791 preserving registers and after saving the return address,
1792 (and its saz to do this using adds), but that's not what the
1793 native C compiler on svr4 does. */
1795 fprintf (asm_file, "\taddu %d,%ssp,%sfp\n",
1796 frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
1798 /* Preserve registers. The ABI sez to do this before setting
1799 up the new frame pointer, but that's not what the native
1800 compiler on svr4 does. */
1802 for (i = 1; i < 32; i++)
1803 if (regs_ever_live[i] && ! call_used_regs[i])
1804 fprintf (asm_file, "\tst.l %s%s,%d(%sfp)\n",
1805 i860_reg_prefix, reg_names[i],
1806 must_preserve_bytes + (4 * preserved_so_far++),
1809 for (i = 32; i < 64; i++)
1810 if (regs_ever_live[i] && ! call_used_regs[i])
1811 fprintf (asm_file, "\tfst.l %s%s,%d(%sfp)\n",
1812 i860_reg_prefix, reg_names[i],
1813 must_preserve_bytes + (4 * preserved_so_far++),
1816 /* Save the return address. The ABI sez to do this earlier,
1817 and also via an offset from %sp, but the native C compiler
1818 on svr4 does it later (i.e. now) and uses an offset from
1821 if (must_preserve_r1)
1822 fprintf (asm_file, "\tst.l %sr1,4(%sfp)\n",
1823 i860_reg_prefix, i860_reg_prefix);
1826 #else /* defined(I860_STRICT_ABI_PROLOGUES) */
1828 /* There are two kinds of function prologues.
1829 You use the "small" version if the total frame size is
1830 small enough so that it can fit into an immediate 16-bit
1831 value in one instruction. Otherwise, you use the "large"
1832 version of the function prologue. */
1834 if (total_fsize > 0x7fff)
1836 /* Adjust the stack pointer (thereby allocating a new frame). */
1838 fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
1839 frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
1841 /* Save the caller's frame pointer. */
1843 fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
1844 i860_reg_prefix, i860_reg_prefix);
1846 /* Save return address. */
1848 if (must_preserve_r1)
1849 fprintf (asm_file, "\tst.l %sr1,4(%ssp)\n",
1850 i860_reg_prefix, i860_reg_prefix);
1852 /* Get the value of frame_lower_bytes into r31 for later use. */
1854 fprintf (asm_file, "\torh %d,%sr0,%sr31\n",
1855 frame_lower_bytes >> 16, i860_reg_prefix, i860_reg_prefix);
1856 fprintf (asm_file, "\tor %d,%sr31,%sr31\n",
1857 frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
1859 /* Now re-adjust the stack pointer using the value in r31. */
1861 fprintf (asm_file, "\tsubs %ssp,%sr31,%ssp\n",
1862 i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1864 /* Pre-compute value to be used as the new frame pointer. */
1866 fprintf (asm_file, "\tadds %ssp,%sr31,%sr31\n",
1867 i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
1869 /* Preserve registers. */
1871 for (i = 1; i < 32; i++)
1872 if (regs_ever_live[i] && ! call_used_regs[i])
1873 fprintf (asm_file, "\tst.l %s%s,%d(%sr31)\n",
1874 i860_reg_prefix, reg_names[i],
1875 must_preserve_bytes + (4 * preserved_so_far++),
1878 for (i = 32; i < 64; i++)
1879 if (regs_ever_live[i] && ! call_used_regs[i])
1880 fprintf (asm_file, "\tfst.l %s%s,%d(%sr31)\n",
1881 i860_reg_prefix, reg_names[i],
1882 must_preserve_bytes + (4 * preserved_so_far++),
1885 /* Actually set the new value of the frame pointer. */
1887 fprintf (asm_file, "\tmov %sr31,%sfp\n",
1888 i860_reg_prefix, i860_reg_prefix);
1892 /* Adjust the stack pointer. */
1894 fprintf (asm_file, "\tadds -%d,%ssp,%ssp\n",
1895 total_fsize, i860_reg_prefix, i860_reg_prefix);
1897 /* Save the caller's frame pointer. */
1899 fprintf (asm_file, "\tst.l %sfp,%d(%ssp)\n",
1900 i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
1902 /* Save the return address. */
1904 if (must_preserve_r1)
1905 fprintf (asm_file, "\tst.l %sr1,%d(%ssp)\n",
1906 i860_reg_prefix, frame_lower_bytes + 4, i860_reg_prefix);
1908 /* Preserve registers. */
1910 for (i = 1; i < 32; i++)
1911 if (regs_ever_live[i] && ! call_used_regs[i])
1912 fprintf (asm_file, "\tst.l %s%s,%d(%ssp)\n",
1913 i860_reg_prefix, reg_names[i],
1914 frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
1917 for (i = 32; i < 64; i++)
1918 if (regs_ever_live[i] && ! call_used_regs[i])
1919 fprintf (asm_file, "\tfst.l %s%s,%d(%ssp)\n",
1920 i860_reg_prefix, reg_names[i],
1921 frame_lower_bytes + must_preserve_bytes + (4 * preserved_so_far++),
1924 /* Setup the new frame pointer. */
1926 fprintf (asm_file, "\tadds %d,%ssp,%sfp\n",
1927 frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
1929 #endif /* defined(I860_STRICT_ABI_PROLOGUES) */
1931 #ifdef ASM_OUTPUT_PROLOGUE_SUFFIX
1932 ASM_OUTPUT_PROLOGUE_SUFFIX (asm_file);
1933 #endif /* defined(ASM_OUTPUT_PROLOGUE_SUFFIX) */
1936 /* This function generates the assembly code for function exit.
1938 ASM_FILE is a stdio stream to output the code to.
1939 SIZE is an int: how many units of temporary storage to allocate.
1941 The function epilogue should not depend on the current stack pointer!
1942 It should use the frame pointer only. This is mandatory because
1943 of alloca; we also take advantage of it to omit stack adjustments
1946 Note that when we go to restore the preserved register values we must
1947 not try to address their slots by using offsets from the stack pointer.
1948 That's because the stack pointer may have been moved during the function
1949 execution due to a call to alloca(). Rather, we must restore all
1950 preserved registers via offsets from the frame pointer value.
1952 Note also that when the current frame is being "popped" (by adjusting
1953 the value of the stack pointer) on function exit, we must (for the
1954 sake of alloca) set the new value of the stack pointer based upon
1955 the current value of the frame pointer. We can't just add what we
1956 believe to be the (static) frame size to the stack pointer because
1957 if we did that, and alloca() had been called during this function,
1958 we would end up returning *without* having fully deallocated all of
1959 the space grabbed by alloca. If that happened, and a function
1960 containing one or more alloca() calls was called over and over again,
1961 then the stack would grow without limit!
1963 Finally note that the epilogues generated here are completely ABI
1964 compliant. They go out of their way to insure that the value in
1965 the frame pointer register is never less than the value in the stack
1966 pointer register. It's not clear why this relationship needs to be
1967 maintained at all times, but maintaining it only costs one extra
1968 instruction, so what the hell.
1971 /* This corresponds to a version 4 TDESC structure. Lower numbered
1972 versions successively omit the last word of the structure. We
1973 don't try to handle version 5 here. */
1975 typedef struct TDESC_flags {
1978 int callable_block:1;
1980 int fregs:6; /* fp regs 2-7 */
1981 int iregs:16; /* regs 0-15 */
1984 typedef struct TDESC {
1986 int integer_reg_offset; /* same as must_preserve_bytes */
1987 int floating_point_reg_offset;
1988 unsigned int positive_frame_size; /* same as frame_upper_bytes */
1989 unsigned int negative_frame_size; /* same as frame_lower_bytes */
1993 i860_output_function_epilogue (asm_file, local_bytes)
1994 register FILE *asm_file;
1995 register HOST_WIDE_INT local_bytes;
1997 register HOST_WIDE_INT frame_upper_bytes;
1998 register HOST_WIDE_INT frame_lower_bytes;
1999 register HOST_WIDE_INT preserved_reg_bytes = 0;
2000 register unsigned i;
2001 register unsigned restored_so_far = 0;
2002 register unsigned int_restored;
2003 register unsigned mask;
2004 unsigned intflags=0;
2005 register TDESC_flags *flags = (TDESC_flags *) &intflags;
2008 flags->reg_packing = 1;
2009 flags->iregs = 8; /* old fp always gets saved */
2011 /* Round-up the frame_lower_bytes so that it's a multiple of 16. */
2013 frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
2015 /* Count the number of registers that were preserved in the prologue.
2016 Ignore r0. It is never preserved. */
2018 for (i = 1; i < FIRST_PSEUDO_REGISTER; i++)
2020 if (regs_ever_live[i] && ! call_used_regs[i])
2021 preserved_reg_bytes += 4;
2024 /* The upper part of each frame will contain only saved fp,
2025 the saved r1, and stack slots for all of the other "preserved"
2026 registers that we find we will need to save & restore. */
2028 frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
2030 /* Round-up frame_upper_bytes so that t is a multiple of 16. */
2033 = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
2035 /* Restore all of the "preserved" registers that need restoring. */
2039 for (i = 1; i < 32; i++, mask<<=1)
2040 if (regs_ever_live[i] && ! call_used_regs[i]) {
2041 fprintf (asm_file, "\tld.l %d(%sfp),%s%s\n",
2042 must_preserve_bytes + (4 * restored_so_far++),
2043 i860_reg_prefix, i860_reg_prefix, reg_names[i]);
2044 if (i > 3 && i < 16)
2045 flags->iregs |= mask;
2048 int_restored = restored_so_far;
2051 for (i = 32; i < 64; i++) {
2052 if (regs_ever_live[i] && ! call_used_regs[i]) {
2053 fprintf (asm_file, "\tfld.l %d(%sfp),%s%s\n",
2054 must_preserve_bytes + (4 * restored_so_far++),
2055 i860_reg_prefix, i860_reg_prefix, reg_names[i]);
2056 if (i > 33 && i < 40)
2057 flags->fregs |= mask;
2059 if (i > 33 && i < 40)
2063 /* Get the value we plan to use to restore the stack pointer into r31. */
2065 fprintf (asm_file, "\tadds %d,%sfp,%sr31\n",
2066 frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
2068 /* Restore the return address and the old frame pointer. */
2070 if (must_preserve_r1) {
2071 fprintf (asm_file, "\tld.l 4(%sfp),%sr1\n",
2072 i860_reg_prefix, i860_reg_prefix);
2076 fprintf (asm_file, "\tld.l 0(%sfp),%sfp\n",
2077 i860_reg_prefix, i860_reg_prefix);
2079 /* Return and restore the old stack pointer value. */
2081 fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n",
2082 i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
2084 #ifdef OUTPUT_TDESC /* Output an ABI-compliant TDESC entry */
2085 if (! frame_lower_bytes) {
2087 if (! frame_upper_bytes) {
2089 if (restored_so_far == int_restored) /* No FP saves */
2093 assemble_name(asm_file,current_function_original_name);
2094 fputs(".TDESC:\n", asm_file);
2095 fprintf(asm_file, "%s 0x%0x\n", ASM_LONG, intflags);
2096 fprintf(asm_file, "%s %d\n", ASM_LONG,
2097 int_restored ? must_preserve_bytes : 0);
2098 if (flags->version > 1) {
2099 fprintf(asm_file, "%s %d\n", ASM_LONG,
2100 (restored_so_far == int_restored) ? 0 : must_preserve_bytes +
2101 (4 * int_restored));
2102 if (flags->version > 2) {
2103 fprintf(asm_file, "%s %d\n", ASM_LONG, frame_upper_bytes);
2104 if (flags->version > 3)
2105 fprintf(asm_file, "%s %d\n", ASM_LONG, frame_lower_bytes);
2109 fprintf(asm_file, "%s ", ASM_LONG);
2110 assemble_name(asm_file, current_function_original_name);
2111 fprintf(asm_file, "\n%s ", ASM_LONG);
2112 assemble_name(asm_file, current_function_original_name);
2113 fputs(".TDESC\n", asm_file);
2119 /* Expand a library call to __builtin_saveregs. */
2123 rtx fn = gen_rtx_SYMBOL_REF (Pmode, "__builtin_saveregs");
2124 rtx save = gen_reg_rtx (Pmode);
2125 rtx valreg = LIBCALL_VALUE (Pmode);
2128 /* The return value register overlaps the first argument register.
2129 Save and restore it around the call. */
2130 emit_move_insn (save, valreg);
2131 ret = emit_library_call_value (fn, NULL_RTX, 1, Pmode, 0);
2132 if (GET_CODE (ret) != REG || REGNO (ret) < FIRST_PSEUDO_REGISTER)
2133 ret = copy_to_reg (ret);
2134 emit_move_insn (valreg, save);
2140 i860_build_va_list ()
2142 tree field_ireg_used, field_freg_used, field_reg_base, field_mem_ptr;
2145 record = make_node (RECORD_TYPE);
2147 field_ireg_used = build_decl (FIELD_DECL, get_identifier ("__ireg_used"),
2148 unsigned_type_node);
2149 field_freg_used = build_decl (FIELD_DECL, get_identifier ("__freg_used"),
2150 unsigned_type_node);
2151 field_reg_base = build_decl (FIELD_DECL, get_identifier ("__reg_base"),
2153 field_mem_ptr = build_decl (FIELD_DECL, get_identifier ("__mem_ptr"),
2156 DECL_FIELD_CONTEXT (field_ireg_used) = record;
2157 DECL_FIELD_CONTEXT (field_freg_used) = record;
2158 DECL_FIELD_CONTEXT (field_reg_base) = record;
2159 DECL_FIELD_CONTEXT (field_mem_ptr) = record;
2161 #ifdef I860_SVR4_VA_LIST
2162 TYPE_FIELDS (record) = field_ireg_used;
2163 TREE_CHAIN (field_ireg_used) = field_freg_used;
2164 TREE_CHAIN (field_freg_used) = field_reg_base;
2165 TREE_CHAIN (field_reg_base) = field_mem_ptr;
2167 TYPE_FIELDS (record) = field_reg_base;
2168 TREE_CHAIN (field_reg_base) = field_mem_ptr;
2169 TREE_CHAIN (field_mem_ptr) = field_ireg_used;
2170 TREE_CHAIN (field_ireg_used) = field_freg_used;
2173 layout_type (record);
2178 i860_va_start (stdarg_p, valist, nextarg)
2185 saveregs = make_tree (build_pointer_type (va_list_type_node),
2186 expand_builtin_saveregs ());
2187 saveregs = build1 (INDIRECT_REF, va_list_type_node, saveregs);
2191 tree field_ireg_used, field_freg_used, field_reg_base, field_mem_ptr;
2192 tree ireg_used, freg_used, reg_base, mem_ptr;
2194 #ifdef I860_SVR4_VA_LIST
2195 field_ireg_used = TYPE_FIELDS (va_list_type_node);
2196 field_freg_used = TREE_CHAIN (field_ireg_used);
2197 field_reg_base = TREE_CHAIN (field_freg_used);
2198 field_mem_ptr = TREE_CHAIN (field_reg_base);
2200 field_reg_base = TYPE_FIELDS (va_list_type_node);
2201 field_mem_ptr = TREE_CHAIN (field_reg_base);
2202 field_ireg_used = TREE_CHAIN (field_mem_ptr);
2203 field_freg_used = TREE_CHAIN (field_ireg_used);
2206 ireg_used = build (COMPONENT_REF, TREE_TYPE (field_ireg_used),
2207 valist, field_ireg_used);
2208 freg_used = build (COMPONENT_REF, TREE_TYPE (field_freg_used),
2209 valist, field_freg_used);
2210 reg_base = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
2211 valist, field_reg_base);
2212 mem_ptr = build (COMPONENT_REF, TREE_TYPE (field_mem_ptr),
2213 valist, field_mem_ptr);
2215 t = build_int_2 (current_function_args_info.ints, 0);
2216 t = build (MODIFY_EXPR, TREE_TYPE (ireg_used), ireg_used, t);
2217 TREE_SIDE_EFFECTS (t) = 1;
2218 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2220 t = build_int_2 (ROUNDUP (current_function_args_info.floats, 8), 0);
2221 t = build (MODIFY_EXPR, TREE_TYPE (freg_used), freg_used, t);
2222 TREE_SIDE_EFFECTS (t) = 1;
2223 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2225 t = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
2226 saveregs, field_reg_base);
2227 t = build (MODIFY_EXPR, TREE_TYPE (reg_base), reg_base, t);
2228 TREE_SIDE_EFFECTS (t) = 1;
2229 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2231 t = make_tree (ptr_type_node, nextarg);
2232 t = build (MODIFY_EXPR, TREE_TYPE (mem_ptr), mem_ptr, t);
2233 TREE_SIDE_EFFECTS (t) = 1;
2234 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2238 t = build (MODIFY_EXPR, va_list_type_node, valist, saveregs);
2239 TREE_SIDE_EFFECTS (t) = 1;
2240 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2244 #define NUM_PARM_FREGS 8
2245 #define NUM_PARM_IREGS 12
2246 #ifdef I860_SVR4_VARARGS
2247 #define FREG_OFFSET 0
2248 #define IREG_OFFSET (NUM_PARM_FREGS * UNITS_PER_WORD)
2250 #define FREG_OFFSET (NUM_PARM_IREGS * UNITS_PER_WORD)
2251 #define IREG_OFFSET 0
2255 i860_va_arg (valist, type)
2258 tree field_ireg_used, field_freg_used, field_reg_base, field_mem_ptr;
2259 tree type_ptr_node, t;
2260 rtx lab_over = NULL_RTX;
2262 HOST_WIDE_INT align;
2264 #ifdef I860_SVR4_VA_LIST
2265 field_ireg_used = TYPE_FIELDS (va_list_type_node);
2266 field_freg_used = TREE_CHAIN (field_ireg_used);
2267 field_reg_base = TREE_CHAIN (field_freg_used);
2268 field_mem_ptr = TREE_CHAIN (field_reg_base);
2270 field_reg_base = TYPE_FIELDS (va_list_type_node);
2271 field_mem_ptr = TREE_CHAIN (field_reg_base);
2272 field_ireg_used = TREE_CHAIN (field_mem_ptr);
2273 field_freg_used = TREE_CHAIN (field_ireg_used);
2276 field_ireg_used = build (COMPONENT_REF, TREE_TYPE (field_ireg_used),
2277 valist, field_ireg_used);
2278 field_freg_used = build (COMPONENT_REF, TREE_TYPE (field_freg_used),
2279 valist, field_freg_used);
2280 field_reg_base = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
2281 valist, field_reg_base);
2282 field_mem_ptr = build (COMPONENT_REF, TREE_TYPE (field_mem_ptr),
2283 valist, field_mem_ptr);
2285 ret = gen_reg_rtx (Pmode);
2286 type_ptr_node = build_pointer_type (type);
2288 if (! AGGREGATE_TYPE_P (type))
2290 int nparm, incr, ofs;
2294 if (FLOAT_TYPE_P (type))
2296 field = field_freg_used;
2297 nparm = NUM_PARM_FREGS;
2303 field = field_ireg_used;
2304 nparm = NUM_PARM_IREGS;
2305 incr = int_size_in_bytes (type) / UNITS_PER_WORD;
2309 lab_false = gen_label_rtx ();
2310 lab_over = gen_label_rtx ();
2312 emit_cmp_and_jump_insns (expand_expr (field, NULL_RTX, 0, 0),
2313 GEN_INT (nparm - incr), GT, const0_rtx,
2314 TYPE_MODE (TREE_TYPE (field)),
2315 TREE_UNSIGNED (field), 0, lab_false);
2317 t = fold (build (POSTINCREMENT_EXPR, TREE_TYPE (field), field,
2318 build_int_2 (incr, 0)));
2319 TREE_SIDE_EFFECTS (t) = 1;
2321 t = fold (build (MULT_EXPR, TREE_TYPE (field), field,
2322 build_int_2 (UNITS_PER_WORD, 0)));
2323 TREE_SIDE_EFFECTS (t) = 1;
2325 t = fold (build (PLUS_EXPR, ptr_type_node, field_reg_base,
2326 fold (build (PLUS_EXPR, TREE_TYPE (field), t,
2327 build_int_2 (ofs, 0)))));
2328 TREE_SIDE_EFFECTS (t) = 1;
2330 val = expand_expr (t, ret, VOIDmode, EXPAND_NORMAL);
2332 emit_move_insn (ret, val);
2334 emit_jump_insn (gen_jump (lab_over));
2336 emit_label (lab_false);
2339 align = TYPE_ALIGN (type);
2340 if (align < BITS_PER_WORD)
2341 align = BITS_PER_WORD;
2342 align /= BITS_PER_UNIT;
2344 t = build (PLUS_EXPR, ptr_type_node, field_mem_ptr,
2345 build_int_2 (align - 1, 0));
2346 t = build (BIT_AND_EXPR, ptr_type_node, t, build_int_2 (-align, -1));
2348 val = expand_expr (t, ret, VOIDmode, EXPAND_NORMAL);
2350 emit_move_insn (ret, val);
2352 t = fold (build (PLUS_EXPR, ptr_type_node,
2353 make_tree (ptr_type_node, ret),
2354 build_int_2 (int_size_in_bytes (type), 0)));
2355 t = build (MODIFY_EXPR, ptr_type_node, field_mem_ptr, t);
2356 TREE_SIDE_EFFECTS (t) = 1;
2357 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2360 emit_label (lab_over);