/* Create an emit instructions for a functions epilogue. */ void lm32_expand_epilogue (void) { rtx ra_rtx = gen_rtx_REG (Pmode, RA_REGNUM); lm32_compute_frame_size (get_frame_size ()); if (current_frame_info.total_size > 0) { /* Prevent stack code from being reordered. */ emit_insn (gen_blockage ()); /* Restore callee save registers. */ if (current_frame_info.reg_save_mask != 0) expand_save_restore (¤t_frame_info, 1); /* Deallocate stack. */ stack_adjust (current_frame_info.total_size); /* Return to calling function. */ emit_jump_insn (gen_return_internal (ra_rtx)); } else { /* Return to calling function. */ emit_jump_insn (gen_return_internal (ra_rtx)); } }
/* Create and emit instructions for a functions prologue. */ void lm32_expand_prologue (void) { rtx insn; lm32_compute_frame_size (get_frame_size ()); if (current_frame_info.total_size > 0) { /* Add space on stack new frame. */ stack_adjust (-current_frame_info.total_size); /* Save callee save registers. */ if (current_frame_info.reg_save_mask != 0) expand_save_restore (¤t_frame_info, 0); /* Setup frame pointer if it's needed. */ if (frame_pointer_needed == 1) { /* Move sp to fp. */ insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; /* Add offset - Don't use total_size, as that includes pretend_size, which isn't part of this frame? */ insn = emit_add (frame_pointer_rtx, frame_pointer_rtx, GEN_INT (current_frame_info.args_size + current_frame_info.callee_size + current_frame_info.locals_size)); RTX_FRAME_RELATED_P (insn) = 1; } /* Prevent prologue from being scheduled into function body. */ emit_insn (gen_blockage ()); } }
void fr30_expand_prologue (void) { int regno; rtx insn; if (! current_frame_info.initialised) fr30_compute_frame_size (0, 0); /* This cases shouldn't happen. Catch it now. */ gcc_assert (current_frame_info.total_size || !current_frame_info.gmask); /* Allocate space for register arguments if this is a variadic function. */ if (current_frame_info.pretend_size) { int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD; /* Push argument registers into the pretend arg area. */ for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;) { insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } } if (current_frame_info.gmask) { /* Save any needed call-saved regs. */ for (regno = STACK_POINTER_REGNUM; regno--;) { if ((current_frame_info.gmask & (1 << regno)) != 0) { insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno))); RTX_FRAME_RELATED_P (insn) = 1; } } } /* Save return address if necessary. */ if (current_frame_info.save_rp) { insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM))); RTX_FRAME_RELATED_P (insn) = 1; } /* Save old frame pointer and create new one, if necessary. */ if (current_frame_info.save_fp) { if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD)) { int enter_size = current_frame_info.frame_size + UNITS_PER_WORD; rtx pattern; insn = emit_insn (gen_enter_func (GEN_INT (enter_size))); RTX_FRAME_RELATED_P (insn) = 1; pattern = PATTERN (insn); /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */ if (GET_CODE (pattern) == PARALLEL) { int x; for (x = XVECLEN (pattern, 0); x--;) { rtx part = XVECEXP (pattern, 0, x); /* One of the insns in the ENTER pattern updates the frame pointer. If we do not actually need the frame pointer in this function then this is a side effect rather than a desired effect, so we do not mark that insn as being related to the frame set up. Doing this allows us to compile the crash66.C test file in the G++ testsuite. */ if (! frame_pointer_needed && GET_CODE (part) == SET && REGNO (SET_DEST (part)) == HARD_FRAME_POINTER_REGNUM) RTX_FRAME_RELATED_P (part) = 0; else RTX_FRAME_RELATED_P (part) = 1; } } } else { insn = emit_insn (gen_movsi_push (frame_pointer_rtx)); RTX_FRAME_RELATED_P (insn) = 1; if (frame_pointer_needed) { insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); RTX_FRAME_RELATED_P (insn) = 1; } } } /* Allocate the stack frame. */ if (current_frame_info.frame_size == 0) ; /* Nothing to do. */ else if (current_frame_info.save_fp && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD)) ; /* Nothing to do. */ else if (current_frame_info.frame_size <= 512) { insn = emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size))); RTX_FRAME_RELATED_P (insn) = 1; } else { rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM); insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size))); RTX_FRAME_RELATED_P (insn) = 1; insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp)); RTX_FRAME_RELATED_P (insn) = 1; } if (current_function_profile) emit_insn (gen_blockage ()); }
rtx fr30_move_double (rtx * operands) { rtx src = operands[1]; rtx dest = operands[0]; enum rtx_code src_code = GET_CODE (src); enum rtx_code dest_code = GET_CODE (dest); enum machine_mode mode = GET_MODE (dest); rtx val; start_sequence (); if (dest_code == REG) { if (src_code == REG) { int reverse = (REGNO (dest) == REGNO (src) + 1); /* We normally copy the low-numbered register first. However, if the first register of operand 0 is the same as the second register of operand 1, we must copy in the opposite order. */ emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, reverse, TRUE, mode), operand_subword (src, reverse, TRUE, mode))); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, !reverse, TRUE, mode), operand_subword (src, !reverse, TRUE, mode))); } else if (src_code == MEM) { rtx addr = XEXP (src, 0); int dregno = REGNO (dest); rtx dest0 = operand_subword (dest, 0, TRUE, mode);; rtx dest1 = operand_subword (dest, 1, TRUE, mode);; rtx new_mem; gcc_assert (GET_CODE (addr) == REG); /* Copy the address before clobbering it. See PR 34174. */ emit_insn (gen_rtx_SET (SImode, dest1, addr)); emit_insn (gen_rtx_SET (VOIDmode, dest0, adjust_address (src, SImode, 0))); emit_insn (gen_rtx_SET (SImode, dest1, plus_constant (dest1, UNITS_PER_WORD))); new_mem = gen_rtx_MEM (SImode, dest1); MEM_COPY_ATTRIBUTES (new_mem, src); emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem)); } else if (src_code == CONST_INT || src_code == CONST_DOUBLE) { rtx words[2]; split_double (src, &words[0], &words[1]); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, 0, TRUE, mode), words[0])); emit_insn (gen_rtx_SET (VOIDmode, operand_subword (dest, 1, TRUE, mode), words[1])); } } else if (src_code == REG && dest_code == MEM) { rtx addr = XEXP (dest, 0); rtx src0; rtx src1; gcc_assert (GET_CODE (addr) == REG); src0 = operand_subword (src, 0, TRUE, mode); src1 = operand_subword (src, 1, TRUE, mode); emit_move_insn (adjust_address (dest, SImode, 0), src0); if (REGNO (addr) == STACK_POINTER_REGNUM || REGNO (addr) == FRAME_POINTER_REGNUM) emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, UNITS_PER_WORD), src1)); else { rtx new_mem; rtx scratch_reg_r0 = gen_rtx_REG (SImode, 0); /* We need a scratch register to hold the value of 'address + 4'. We use r0 for this purpose. It is used for example for long jumps and is already marked to not be used by normal register allocation. */ emit_insn (gen_movsi_internal (scratch_reg_r0, addr)); emit_insn (gen_addsi_small_int (scratch_reg_r0, scratch_reg_r0, GEN_INT (UNITS_PER_WORD))); new_mem = gen_rtx_MEM (SImode, scratch_reg_r0); MEM_COPY_ATTRIBUTES (new_mem, dest); emit_move_insn (new_mem, src1); emit_insn (gen_blockage ()); } } else /* This should have been prevented by the constraints on movdi_insn. */ gcc_unreachable (); val = get_insns (); end_sequence (); return val; }