1 /* FR30 specific functions.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008
3 Free Software Foundation, Inc.
4 Contributed by Cygnus Solutions.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
26 #include "coretypes.h"
30 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "insn-attr.h"
46 #include "target-def.h"
49 /*{{{ Function Prologues & Epilogues */
51 /* The FR30 stack looks like this:
53 Before call After call
55 +-----------------------+ +-----------------------+ high
57 | local variables, | | local variables, |
58 | reg save area, etc. | | reg save area, etc. |
60 +-----------------------+ +-----------------------+
62 | args to the func that | | args to this func. |
63 | is being called that | | |
64 SP ->| do not fit in regs | | |
65 +-----------------------+ +-----------------------+
66 | args that used to be | \
67 | in regs; only created | | pretend_size
68 AP-> | for vararg funcs | /
69 +-----------------------+
71 | register save area | |
73 +-----------------------+ | reg_size
75 +-----------------------+ |
76 FP ->| previous frame ptr | /
77 +-----------------------+
79 | local variables | | var_size
81 +-----------------------+
83 low | room for args to | |
84 memory | other funcs called | | args_size
87 +-----------------------+
89 Note, AP is a fake hard register. It will be eliminated in favor of
90 SP or FP as appropriate.
92 Note, Some or all of the stack sections above may be omitted if they
95 /* Structure to be filled in by fr30_compute_frame_size() with register
96 save masks, and offsets for the current function. */
97 struct fr30_frame_info
99 unsigned int total_size; /* # Bytes that the entire frame takes up. */
100 unsigned int pretend_size; /* # Bytes we push and pretend caller did. */
101 unsigned int args_size; /* # Bytes that outgoing arguments take up. */
102 unsigned int reg_size; /* # Bytes needed to store regs. */
103 unsigned int var_size; /* # Bytes that variables take up. */
104 unsigned int frame_size; /* # Bytes in current frame. */
105 unsigned int gmask; /* Mask of saved registers. */
106 unsigned int save_fp; /* Nonzero if frame pointer must be saved. */
107 unsigned int save_rp; /* Nonzero if return pointer must be saved. */
108 int initialised; /* Nonzero if frame size already calculated. */
111 /* Current frame information calculated by fr30_compute_frame_size(). */
112 static struct fr30_frame_info current_frame_info;
114 /* Zero structure to initialize current_frame_info. */
115 static struct fr30_frame_info zero_frame_info;
117 static void fr30_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
119 static bool fr30_must_pass_in_stack (enum machine_mode, const_tree);
120 static int fr30_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
124 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
125 #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
127 /* Tell prologue and epilogue if register REGNO should be saved / restored.
128 The return address and frame pointer are treated separately.
129 Don't consider them here. */
130 #define MUST_SAVE_REGISTER(regno) \
131 ( (regno) != RETURN_POINTER_REGNUM \
132 && (regno) != FRAME_POINTER_REGNUM \
133 && df_regs_ever_live_p (regno) \
134 && ! call_used_regs [regno] )
136 #define MUST_SAVE_FRAME_POINTER (df_regs_ever_live_p (FRAME_POINTER_REGNUM) || frame_pointer_needed)
137 #define MUST_SAVE_RETURN_POINTER (df_regs_ever_live_p (RETURN_POINTER_REGNUM) || crtl->profile)
139 #if UNITS_PER_WORD == 4
140 #define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
143 /* Initialize the GCC target structure. */
144 #undef TARGET_ASM_ALIGNED_HI_OP
145 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
146 #undef TARGET_ASM_ALIGNED_SI_OP
147 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
149 #undef TARGET_PROMOTE_PROTOTYPES
150 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
151 #undef TARGET_PASS_BY_REFERENCE
152 #define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack
153 #undef TARGET_ARG_PARTIAL_BYTES
154 #define TARGET_ARG_PARTIAL_BYTES fr30_arg_partial_bytes
156 #undef TARGET_SETUP_INCOMING_VARARGS
157 #define TARGET_SETUP_INCOMING_VARARGS fr30_setup_incoming_varargs
158 #undef TARGET_MUST_PASS_IN_STACK
159 #define TARGET_MUST_PASS_IN_STACK fr30_must_pass_in_stack
161 struct gcc_target targetm = TARGET_INITIALIZER;
163 /* Returns the number of bytes offset between FROM_REG and TO_REG
164 for the current function. As a side effect it fills in the
165 current_frame_info structure, if the data is available. */
167 fr30_compute_frame_size (int from_reg, int to_reg)
170 unsigned int return_value;
171 unsigned int var_size;
172 unsigned int args_size;
173 unsigned int pretend_size;
174 unsigned int reg_size;
177 var_size = WORD_ALIGN (get_frame_size ());
178 args_size = WORD_ALIGN (crtl->outgoing_args_size);
179 pretend_size = crtl->args.pretend_args_size;
184 /* Calculate space needed for registers. */
185 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
187 if (MUST_SAVE_REGISTER (regno))
189 reg_size += UNITS_PER_WORD;
194 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
195 current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
197 reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
200 /* Save computed information. */
201 current_frame_info.pretend_size = pretend_size;
202 current_frame_info.var_size = var_size;
203 current_frame_info.args_size = args_size;
204 current_frame_info.reg_size = reg_size;
205 current_frame_info.frame_size = args_size + var_size;
206 current_frame_info.total_size = args_size + var_size + reg_size + pretend_size;
207 current_frame_info.gmask = gmask;
208 current_frame_info.initialised = reload_completed;
210 /* Calculate the required distance. */
213 if (to_reg == STACK_POINTER_REGNUM)
214 return_value += args_size + var_size;
216 if (from_reg == ARG_POINTER_REGNUM)
217 return_value += reg_size;
222 /* Called after register allocation to add any instructions needed for the
223 prologue. Using a prologue insn is favored compared to putting all of the
224 instructions in output_function_prologue(), since it allows the scheduler
225 to intermix instructions with the saves of the caller saved registers. In
226 some cases, it might be necessary to emit a barrier instruction as the last
227 insn to prevent such scheduling. */
230 fr30_expand_prologue (void)
235 if (! current_frame_info.initialised)
236 fr30_compute_frame_size (0, 0);
238 /* This cases shouldn't happen. Catch it now. */
239 gcc_assert (current_frame_info.total_size || !current_frame_info.gmask);
241 /* Allocate space for register arguments if this is a variadic function. */
242 if (current_frame_info.pretend_size)
244 int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
246 /* Push argument registers into the pretend arg area. */
247 for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
249 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
250 RTX_FRAME_RELATED_P (insn) = 1;
254 if (current_frame_info.gmask)
256 /* Save any needed call-saved regs. */
257 for (regno = STACK_POINTER_REGNUM; regno--;)
259 if ((current_frame_info.gmask & (1 << regno)) != 0)
261 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
262 RTX_FRAME_RELATED_P (insn) = 1;
267 /* Save return address if necessary. */
268 if (current_frame_info.save_rp)
270 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
271 RETURN_POINTER_REGNUM)));
272 RTX_FRAME_RELATED_P (insn) = 1;
275 /* Save old frame pointer and create new one, if necessary. */
276 if (current_frame_info.save_fp)
278 if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
280 int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
283 insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
284 RTX_FRAME_RELATED_P (insn) = 1;
286 pattern = PATTERN (insn);
288 /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */
289 if (GET_CODE (pattern) == PARALLEL)
292 for (x = XVECLEN (pattern, 0); x--;)
294 rtx part = XVECEXP (pattern, 0, x);
296 /* One of the insns in the ENTER pattern updates the
297 frame pointer. If we do not actually need the frame
298 pointer in this function then this is a side effect
299 rather than a desired effect, so we do not mark that
300 insn as being related to the frame set up. Doing this
301 allows us to compile the crash66.C test file in the
303 if (! frame_pointer_needed
304 && GET_CODE (part) == SET
305 && SET_DEST (part) == hard_frame_pointer_rtx)
306 RTX_FRAME_RELATED_P (part) = 0;
308 RTX_FRAME_RELATED_P (part) = 1;
314 insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
315 RTX_FRAME_RELATED_P (insn) = 1;
317 if (frame_pointer_needed)
319 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
320 RTX_FRAME_RELATED_P (insn) = 1;
325 /* Allocate the stack frame. */
326 if (current_frame_info.frame_size == 0)
327 ; /* Nothing to do. */
328 else if (current_frame_info.save_fp
329 && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
330 ; /* Nothing to do. */
331 else if (current_frame_info.frame_size <= 512)
333 insn = emit_insn (gen_add_to_stack
334 (GEN_INT (- (signed) current_frame_info.frame_size)));
335 RTX_FRAME_RELATED_P (insn) = 1;
339 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
340 insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
341 RTX_FRAME_RELATED_P (insn) = 1;
342 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
343 RTX_FRAME_RELATED_P (insn) = 1;
347 emit_insn (gen_blockage ());
350 /* Called after register allocation to add any instructions needed for the
351 epilogue. Using an epilogue insn is favored compared to putting all of the
352 instructions in output_function_epilogue(), since it allows the scheduler
353 to intermix instructions with the restores of the caller saved registers.
354 In some cases, it might be necessary to emit a barrier instruction as the
355 first insn to prevent such scheduling. */
357 fr30_expand_epilogue (void)
361 /* Perform the inversion operations of the prologue. */
362 gcc_assert (current_frame_info.initialised);
364 /* Pop local variables and arguments off the stack.
365 If frame_pointer_needed is TRUE then the frame pointer register
366 has actually been used as a frame pointer, and we can recover
367 the stack pointer from it, otherwise we must unwind the stack
369 if (current_frame_info.frame_size > 0)
371 if (current_frame_info.save_fp && frame_pointer_needed)
373 emit_insn (gen_leave_func ());
374 current_frame_info.save_fp = 0;
376 else if (current_frame_info.frame_size <= 508)
377 emit_insn (gen_add_to_stack
378 (GEN_INT (current_frame_info.frame_size)));
381 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
382 emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
383 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
387 if (current_frame_info.save_fp)
388 emit_insn (gen_movsi_pop (frame_pointer_rtx));
390 /* Pop all the registers that were pushed. */
391 if (current_frame_info.save_rp)
392 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
394 for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
395 if (current_frame_info.gmask & (1 << regno))
396 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
398 if (current_frame_info.pretend_size)
399 emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
401 /* Reset state info for each function. */
402 current_frame_info = zero_frame_info;
404 emit_jump_insn (gen_return_from_func ());
407 /* Do any needed setup for a variadic function. We must create a register
408 parameter block, and then copy any anonymous arguments, plus the last
409 named argument, from registers into memory. * copying actually done in
410 fr30_expand_prologue().
412 ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument
413 which has type TYPE and mode MODE, and we rely on this fact. */
415 fr30_setup_incoming_varargs (CUMULATIVE_ARGS *arg_regs_used_so_far,
416 enum machine_mode mode,
417 tree type ATTRIBUTE_UNUSED,
419 int second_time ATTRIBUTE_UNUSED)
423 /* All BLKmode values are passed by reference. */
424 gcc_assert (mode != BLKmode);
426 /* ??? This run-time test as well as the code inside the if
427 statement is probably unnecessary. */
428 if (targetm.calls.strict_argument_naming (arg_regs_used_so_far))
429 /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named
430 arg must not be treated as an anonymous arg. */
431 arg_regs_used_so_far += fr30_num_arg_regs (mode, type);
433 size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far);
438 * pretend_size = (size * UNITS_PER_WORD);
442 /*{{{ Printing operands */
444 /* Print a memory address as an operand to reference that memory location. */
447 fr30_print_operand_address (FILE *stream, rtx address)
449 switch (GET_CODE (address))
452 output_addr_const (stream, address);
456 fprintf (stderr, "code = %x\n", GET_CODE (address));
458 output_operand_lossage ("fr30_print_operand_address: unhandled address");
463 /* Print an operand. */
466 fr30_print_operand (FILE *file, rtx x, int code)
473 /* Output a :D if this instruction is delayed. */
474 if (dbr_sequence_length () != 0)
479 /* Compute the register name of the second register in a hi/lo
481 if (GET_CODE (x) != REG)
482 output_operand_lossage ("fr30_print_operand: unrecognized %%p code");
484 fprintf (file, "r%d", REGNO (x) + 1);
488 /* Convert GCC's comparison operators into FR30 comparison codes. */
489 switch (GET_CODE (x))
491 case EQ: fprintf (file, "eq"); break;
492 case NE: fprintf (file, "ne"); break;
493 case LT: fprintf (file, "lt"); break;
494 case LE: fprintf (file, "le"); break;
495 case GT: fprintf (file, "gt"); break;
496 case GE: fprintf (file, "ge"); break;
497 case LTU: fprintf (file, "c"); break;
498 case LEU: fprintf (file, "ls"); break;
499 case GTU: fprintf (file, "hi"); break;
500 case GEU: fprintf (file, "nc"); break;
502 output_operand_lossage ("fr30_print_operand: unrecognized %%b code");
508 /* Convert GCC's comparison operators into the complimentary FR30
510 switch (GET_CODE (x))
512 case EQ: fprintf (file, "ne"); break;
513 case NE: fprintf (file, "eq"); break;
514 case LT: fprintf (file, "ge"); break;
515 case LE: fprintf (file, "gt"); break;
516 case GT: fprintf (file, "le"); break;
517 case GE: fprintf (file, "lt"); break;
518 case LTU: fprintf (file, "nc"); break;
519 case LEU: fprintf (file, "hi"); break;
520 case GTU: fprintf (file, "ls"); break;
521 case GEU: fprintf (file, "c"); break;
523 output_operand_lossage ("fr30_print_operand: unrecognized %%B code");
529 /* Print a signed byte value as an unsigned value. */
530 if (GET_CODE (x) != CONST_INT)
531 output_operand_lossage ("fr30_print_operand: invalid operand to %%A code");
540 fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
545 if (GET_CODE (x) != CONST_INT
548 output_operand_lossage ("fr30_print_operand: invalid %%x code");
550 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) - 16);
554 if (GET_CODE (x) != CONST_DOUBLE)
555 output_operand_lossage ("fr30_print_operand: invalid %%F code");
560 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x),
571 fprintf (stderr, "unknown code = %x\n", code);
572 output_operand_lossage ("fr30_print_operand: unknown code");
576 switch (GET_CODE (x))
579 fputs (reg_names [REGNO (x)], file);
585 switch (GET_CODE (x0))
588 gcc_assert ((unsigned) REGNO (x0) < ARRAY_SIZE (reg_names));
589 fprintf (file, "@%s", reg_names [REGNO (x0)]);
593 if (GET_CODE (XEXP (x0, 0)) != REG
594 || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
595 || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
596 || GET_CODE (XEXP (x0, 1)) != CONST_INT)
598 fprintf (stderr, "bad INDEXed address:");
600 output_operand_lossage ("fr30_print_operand: unhandled MEM");
602 else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
604 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
605 if (val < -(1 << 9) || val > ((1 << 9) - 4))
607 fprintf (stderr, "frame INDEX out of range:");
609 output_operand_lossage ("fr30_print_operand: unhandled MEM");
611 fprintf (file, "@(r14, #" HOST_WIDE_INT_PRINT_DEC ")", val);
615 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
616 if (val < 0 || val > ((1 << 6) - 4))
618 fprintf (stderr, "stack INDEX out of range:");
620 output_operand_lossage ("fr30_print_operand: unhandled MEM");
622 fprintf (file, "@(r15, #" HOST_WIDE_INT_PRINT_DEC ")", val);
631 fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
633 output_operand_lossage ("fr30_print_operand: unhandled MEM");
639 /* We handle SFmode constants here as output_addr_const doesn't. */
640 if (GET_MODE (x) == SFmode)
645 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
646 REAL_VALUE_TO_TARGET_SINGLE (d, l);
647 fprintf (file, "0x%08lx", l);
651 /* Fall through. Let output_addr_const deal with it. */
653 output_addr_const (file, x);
661 /*{{{ Function arguments */
663 /* Return true if we should pass an argument on the stack rather than
667 fr30_must_pass_in_stack (enum machine_mode mode, const_tree type)
673 return AGGREGATE_TYPE_P (type);
676 /* Compute the number of word sized registers needed to hold a
677 function argument of mode INT_MODE and tree type TYPE. */
679 fr30_num_arg_regs (enum machine_mode mode, tree type)
683 if (targetm.calls.must_pass_in_stack (mode, type))
686 if (type && mode == BLKmode)
687 size = int_size_in_bytes (type);
689 size = GET_MODE_SIZE (mode);
691 return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
694 /* Returns the number of bytes in which *part* of a parameter of machine
695 mode MODE and tree type TYPE (which may be NULL if the type is not known).
696 If the argument fits entirely in the argument registers, or entirely on
697 the stack, then 0 is returned.
698 CUM is the number of argument registers already used by earlier
699 parameters to the function. */
702 fr30_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
703 tree type, bool named)
705 /* Unnamed arguments, i.e. those that are prototyped as ...
706 are always passed on the stack.
707 Also check here to see if all the argument registers are full. */
708 if (named == 0 || *cum >= FR30_NUM_ARG_REGS)
711 /* Work out how many argument registers would be needed if this
712 parameter were to be passed entirely in registers. If there
713 are sufficient argument registers available (or if no registers
714 are needed because the parameter must be passed on the stack)
715 then return zero, as this parameter does not require partial
716 register, partial stack stack space. */
717 if (*cum + fr30_num_arg_regs (mode, type) <= FR30_NUM_ARG_REGS)
720 return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD;
724 /*{{{ Operand predicates */
727 #define Mmode enum machine_mode
730 /* Returns true iff all the registers in the operands array
731 are in descending or ascending order. */
733 fr30_check_multiple_regs (rtx *operands, int num_operands, int descending)
737 unsigned int prev_regno = 0;
739 while (num_operands --)
741 if (GET_CODE (operands [num_operands]) != REG)
744 if (REGNO (operands [num_operands]) < prev_regno)
747 prev_regno = REGNO (operands [num_operands]);
752 unsigned int prev_regno = CONDITION_CODE_REGNUM;
754 while (num_operands --)
756 if (GET_CODE (operands [num_operands]) != REG)
759 if (REGNO (operands [num_operands]) > prev_regno)
762 prev_regno = REGNO (operands [num_operands]);
770 fr30_const_double_is_zero (rtx operand)
774 if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)
777 REAL_VALUE_FROM_CONST_DOUBLE (d, operand);
779 return REAL_VALUES_EQUAL (d, dconst0);
783 /*{{{ Instruction Output Routines */
785 /* Output a double word move.
786 It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
787 On the FR30 we are constrained by the fact that it does not
788 support offsetable addresses, and so we have to load the
789 address of the secnd word into the second destination register
790 before we can use it. */
793 fr30_move_double (rtx * operands)
795 rtx src = operands[1];
796 rtx dest = operands[0];
797 enum rtx_code src_code = GET_CODE (src);
798 enum rtx_code dest_code = GET_CODE (dest);
799 enum machine_mode mode = GET_MODE (dest);
804 if (dest_code == REG)
808 int reverse = (REGNO (dest) == REGNO (src) + 1);
810 /* We normally copy the low-numbered register first. However, if
811 the first register of operand 0 is the same as the second register
812 of operand 1, we must copy in the opposite order. */
813 emit_insn (gen_rtx_SET (VOIDmode,
814 operand_subword (dest, reverse, TRUE, mode),
815 operand_subword (src, reverse, TRUE, mode)));
817 emit_insn (gen_rtx_SET (VOIDmode,
818 operand_subword (dest, !reverse, TRUE, mode),
819 operand_subword (src, !reverse, TRUE, mode)));
821 else if (src_code == MEM)
823 rtx addr = XEXP (src, 0);
824 int dregno = REGNO (dest);
825 rtx dest0 = operand_subword (dest, 0, TRUE, mode);;
826 rtx dest1 = operand_subword (dest, 1, TRUE, mode);;
829 gcc_assert (GET_CODE (addr) == REG);
831 /* Copy the address before clobbering it. See PR 34174. */
832 emit_insn (gen_rtx_SET (SImode, dest1, addr));
833 emit_insn (gen_rtx_SET (VOIDmode, dest0,
834 adjust_address (src, SImode, 0)));
835 emit_insn (gen_rtx_SET (SImode, dest1,
836 plus_constant (dest1, UNITS_PER_WORD)));
838 new_mem = gen_rtx_MEM (SImode, dest1);
839 MEM_COPY_ATTRIBUTES (new_mem, src);
841 emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
843 else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
846 split_double (src, &words[0], &words[1]);
847 emit_insn (gen_rtx_SET (VOIDmode,
848 operand_subword (dest, 0, TRUE, mode),
851 emit_insn (gen_rtx_SET (VOIDmode,
852 operand_subword (dest, 1, TRUE, mode),
856 else if (src_code == REG && dest_code == MEM)
858 rtx addr = XEXP (dest, 0);
862 gcc_assert (GET_CODE (addr) == REG);
864 src0 = operand_subword (src, 0, TRUE, mode);
865 src1 = operand_subword (src, 1, TRUE, mode);
867 emit_move_insn (adjust_address (dest, SImode, 0), src0);
869 if (REGNO (addr) == STACK_POINTER_REGNUM
870 || REGNO (addr) == FRAME_POINTER_REGNUM)
871 emit_insn (gen_rtx_SET (VOIDmode,
872 adjust_address (dest, SImode, UNITS_PER_WORD),
877 rtx scratch_reg_r0 = gen_rtx_REG (SImode, 0);
879 /* We need a scratch register to hold the value of 'address + 4'.
880 We use r0 for this purpose. It is used for example for long
881 jumps and is already marked to not be used by normal register
883 emit_insn (gen_movsi_internal (scratch_reg_r0, addr));
884 emit_insn (gen_addsi_small_int (scratch_reg_r0, scratch_reg_r0,
885 GEN_INT (UNITS_PER_WORD)));
886 new_mem = gen_rtx_MEM (SImode, scratch_reg_r0);
887 MEM_COPY_ATTRIBUTES (new_mem, dest);
888 emit_move_insn (new_mem, src1);
889 emit_insn (gen_blockage ());
893 /* This should have been prevented by the constraints on movdi_insn. */
903 /* Local Variables: */