From: Jeff Law Date: Tue, 6 Apr 1993 00:52:19 +0000 (-0600) Subject: pa.c (print_stw, print_ldw): Delete. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aadcdb458c68197f3da9a0c25ca839321c96f6bf;p=gcc.git pa.c (print_stw, print_ldw): Delete. * pa.c (print_stw, print_ldw): Delete. (eligible_for_epilogue_delay): Delete. (hppa_epilogue_delay_slots): Delete. (store_reg, load_reg, set_reg_plus_d): New helper functions. (output_function_prologue): Only emit assembler pseudo-ops to denote the start of a function. Place the correct value into hp_profile_label_name if profiling. (output_function_epilogue): Only emit assembler pseudo-ops to deonte the end of a function. (hppa_expand_prologue): New function to emit all prologue code as RTL. (hppa_expand_epilogue): Likewise for the epilogue. (compute_frame_size): Update to account for using %r4 as an allocatable register if the frame pointer was eliminated. From-SVN: r4025 --- diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 6edb348cbab..1ee230a4e61 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -1597,29 +1597,94 @@ output_ascii (file, p, size) */ -/* Helper functions */ -void -print_stw (file, r, disp, base) - FILE *file; - int r, disp, base; +/* Emit RTL to store REG at the memory location specified by BASE+DISP. + Handle case where DISP > 8k by using the add_high_const pattern. + + Note in DISP > 8k case, we will leave the high part of the address + in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/ +static void +store_reg (reg, disp, base) + int reg, disp, base; { if (VAL_14_BITS_P (disp)) - fprintf (file, "\tstw %%r%d,%d(0,%%r%d)\n", r, disp, base); + { + emit_move_insn (gen_rtx (MEM, SImode, + gen_rtx (PLUS, SImode, + gen_rtx (REG, SImode, base), + GEN_INT (disp))), + gen_rtx (REG, SImode, reg)); + } else - fprintf (file, "\taddil L'%d,%%r%d\n\tstw %%r%d,R'%d(0,%%r1)\n", disp, base, - r, disp); + { + emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1), + gen_rtx (REG, SImode, base), + GEN_INT (disp))); + emit_move_insn (gen_rtx (MEM, SImode, + gen_rtx (LO_SUM, SImode, + gen_rtx (REG, SImode, 1), + GEN_INT (disp))), + gen_rtx (REG, SImode, reg)); + } } -void -print_ldw (file, r, disp, base) - FILE *file; - int r, disp, base; +/* Emit RTL to load REG from the memory location specified by BASE+DISP. + Handle case where DISP > 8k by using the add_high_const pattern. + + Note in DISP > 8k case, we will leave the high part of the address + in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/ +static void +load_reg (reg, disp, base) + int reg, disp, base; +{ + if (VAL_14_BITS_P (disp)) + { + emit_move_insn (gen_rtx (REG, SImode, reg), + gen_rtx (MEM, SImode, + gen_rtx (PLUS, SImode, + gen_rtx (REG, SImode, base), + GEN_INT (disp)))); + + } + else + { + emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1), + gen_rtx (REG, SImode, base), + GEN_INT (disp))); + emit_move_insn (gen_rtx (REG, SImode, reg), + gen_rtx (MEM, SImode, + gen_rtx (LO_SUM, SImode, + gen_rtx (REG, SImode, 1), + GEN_INT (disp)))); + } +} + +/* Emit RTL to set REG to the value specified by BASE+DISP. + Handle case where DISP > 8k by using the add_high_const pattern. + + Note in DISP > 8k case, we will leave the high part of the address + in %r1. There is code in expand_hppa_{prologue,epilogue} that knows this.*/ +static void +set_reg_plus_d(reg, base, disp) + int reg, base, disp; { if (VAL_14_BITS_P (disp)) - fprintf (file, "\tldw %d(0,%d),%d\n", disp, base, r); + { + emit_move_insn (gen_rtx (REG, SImode, reg), + gen_rtx (PLUS, SImode, + gen_rtx (REG, SImode, base), + GEN_INT (disp))); + + } else - fprintf (file, "\taddil L'%d,%d\n\tldw R'%d(0,%%r1),%d\n", disp, base, - disp, r); + { + emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1), + gen_rtx (REG, SImode, base), + GEN_INT (disp))); + emit_move_insn (gen_rtx (REG, SImode, reg), + gen_rtx (LO_SUM, SImode, + gen_rtx (REG, SImode, 1), + GEN_INT (disp))); + } } /* Global variables set by FUNCTION_PROLOGUE. */ @@ -1641,12 +1706,21 @@ compute_frame_size (size, fregs_live) fsize = size + (size || frame_pointer_needed ? 8 : 0); /* fp is stored in a special place. */ - for (i = 18; i >= 5; i--) - if (regs_ever_live[i]) - fsize += 4; + if (frame_pointer_needed) + { + for (i = 18; i >= 5; i--) + if (regs_ever_live[i]) + fsize += 4; - if (regs_ever_live[3]) - fsize += 4; + if (regs_ever_live[3]) + fsize += 4; + } + else + { + for (i = 18; i >= 3; i--) + if (regs_ever_live[i]) + fsize += 4; + } fsize = (fsize + 7) & ~7; if (!TARGET_SNAKE) @@ -1675,128 +1749,177 @@ compute_frame_size (size, fregs_live) return TARGET_SNAKE ? (fsize + 63 & ~63) : fsize; } +rtx hp_profile_label_rtx; +static char hp_profile_label_name[8]; void output_function_prologue (file, size) FILE *file; int size; { + + /* hppa_expand_prologue does the dirty work now. We just need + to output the assembler directives which denote the start + of a function. */ + fprintf (file, "\t.PROC\n\t.CALLINFO FRAME=%d", actual_fsize); + if (regs_ever_live[2] || profile_flag) + fprintf (file, ",CALLS,SAVE_RP\n"); + else + fprintf (file, ",NO_CALLS\n"); + fprintf (file, "\t.ENTRY\n"); + + /* Horrid hack. emit_function_prologue will modify this RTL in + place to get the expected results. */ + if (profile_flag) + sprintf(hp_profile_label_name, "LP$%04d", hp_profile_labelno); +} + +hppa_expand_prologue() +{ + extern char call_used_regs[]; - extern int frame_pointer_needed; - extern int current_function_returns_struct; - int i, offset; + int size = get_frame_size (); int merge_sp_adjust_with_store = 0; + int i, offset; + rtx tmpreg, size_rtx; + save_fregs = 0; local_fsize = size + (size || frame_pointer_needed ? 8 : 0); actual_fsize = compute_frame_size (size, &save_fregs); - /* Let's not try to bullshit more than we need to here. */ - /* This might be right a lot of the time */ - fprintf (file, "\t.PROC\n\t.CALLINFO FRAME=%d", actual_fsize); - if (regs_ever_live[2] || profile_flag) - fprintf (file, ",CALLS,SAVE_RP\n"); - else - fprintf (file, ",NO_CALLS\n"); - fprintf (file, "\t.ENTRY\n"); - - /* Some registers have places to go in the current stack - structure. */ + /* Compute a few things we will use often. */ + tmpreg = gen_rtx (REG, SImode, 1); + size_rtx = GEN_INT (actual_fsize); + /* Save RP first. The calling conventions manual states RP will + always be stored into the caller's frame at sp-20. */ if (regs_ever_live[2] || profile_flag) - fprintf (file, "\tstw %%r2,-20(0,%%r30)\n"); - - /* Reserve space for local variables. */ + store_reg (2, -20, STACK_POINTER_REGNUM); + + /* Allocate the local frame and set up the frame pointer if needed. */ if (actual_fsize) if (frame_pointer_needed) { + /* Copy the old frame pointer temporarily into %r1. Set up the + new stack pointer, then store away the saved old frame pointer + into the stack at sp+actual_fsize and at the same time update + the stack pointer by actual_fsize bytes. Two versions, first + handles small (<8k) frames. The second handles large (>8k) + frames. */ + emit_move_insn (tmpreg, frame_pointer_rtx); + emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); if (VAL_14_BITS_P (actual_fsize)) - fprintf (file, "\tcopy %%r4,%%r1\n\tcopy %%r30,%%r4\n\tstwm %%r1,%d(0,%%r30)\n", - actual_fsize); + emit_insn (gen_post_stwm (stack_pointer_rtx, + stack_pointer_rtx, + size_rtx, tmpreg)); else { - fprintf (file, "\tcopy %%r4,%%r1\n\tcopy %%r30,%%r4\n\tstw %%r1,0(0,%%r4)\n"); - fprintf (file, "\taddil L'%d,%%r30\n\tldo R'%d(%%r1),%%r30\n", - actual_fsize, actual_fsize); + store_reg (1, 0, FRAME_POINTER_REGNUM); + set_reg_plus_d (STACK_POINTER_REGNUM, + STACK_POINTER_REGNUM, + actual_fsize); } } + /* no frame pointer needed. */ else { - if (VAL_14_BITS_P (-actual_fsize) - && local_fsize == 0 && ! flag_pic && ! profile_flag) + /* In some cases we can perform the first callee register save + and allocating the stack frame at the same time. If so, just + make a note of it and defer allocating the frame until saving + the callee registers. */ + if (VAL_14_BITS_P (-actual_fsize) + && local_fsize == 0 + && ! profile_flag + && ! flag_pic) merge_sp_adjust_with_store = 1; - else if (VAL_14_BITS_P (actual_fsize)) - fprintf (file, "\tldo %d(%%r30),%%r30\n", actual_fsize); - else - fprintf (file, "\taddil L'%d,%%r30\n\tldo R'%d(%%r1),%%r30\n", - actual_fsize, actual_fsize); + /* Can not optimize. Adjust the stack frame by actual_fsize bytes. */ + else if (actual_fsize != 0) + set_reg_plus_d (STACK_POINTER_REGNUM, + STACK_POINTER_REGNUM, + actual_fsize); } /* The hppa calling conventions say that that %r19, the pic offset - register, is saved at sp - 32 (in this function's frame) */ + register, is saved at sp - 32 (in this function's frame) when + generating PIC code. */ if (flag_pic) - { - fprintf (file, "\tstw %%r19,-32(0,%%r30)\n"); - } - /* Instead of taking one argument, the counter label, as most normal - mcounts do, _mcount appears to behave differently on the HPPA. It - takes the return address of the caller, the address of this - routine, and the address of the label. Also, it isn't magic, so - argument registers have to be preserved. */ + store_reg (19, -32, STACK_POINTER_REGNUM); + /* Profiling code. + + Instead of taking one argument, the counter label, as most normal + mcounts do, _mcount appears to behave differently on the HPPA. It + takes the return address of the caller, the address of this routine, + and the address of the label. Also, it isn't magic, so + argument registre hsave to be preserved. */ if (profile_flag) { - unsigned int pc_offset = - (4 + (frame_pointer_needed - ? (VAL_14_BITS_P (actual_fsize) ? 12 : 20) - : (VAL_14_BITS_P (actual_fsize) ? 4 : 8))); - int i, arg_offset; - int basereg, offsetadj; + int pc_offset, i, arg_offset, basereg, offsetadj; + + pc_offset = 4 + (frame_pointer_needed + ? (VAL_14_BITS_P (actual_fsize) ? 12 : 20) + : (VAL_14_BITS_P (actual_fsize) ? 4 : 8)); - /* When the function has a frame pointer, use that as the base - register for saving/restoring registers. Else use the stack - pointer. Adjust the offset according to the frame size if this - function does not have a frame pointer. */ + /* When the function has a frame pointer, use it as the base + register for saving/restore registers. Else use the stack + pointer. Adjust the offset according to the frame size if + this function does not have a frame pointer. */ basereg = frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM; offsetadj = frame_pointer_needed ? 0 : actual_fsize; + /* Horrid hack. emit_function_prologue will modify this RTL in + place to get the expected results. sprintf here is just to + put something in the name. */ + sprintf(hp_profile_label_name, "LP$%04d", -1); + hp_profile_label_rtx = gen_rtx (SYMBOL_REF, SImode, + hp_profile_label_name); if (current_function_returns_struct) - print_stw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg); + store_reg (STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg); + for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4) - if (regs_ever_live[i]) + if (regs_ever_live [i]) { - print_stw (file, i, arg_offset, basereg); - /* It is possible for the arg_offset not to fit in 14 bits - when profiling a function without a frame pointer. Deal - with such cases. */ + store_reg (i, arg_offset, basereg); + /* Deal with arg_offset not fitting in 14 bits. */ pc_offset += VAL_14_BITS_P (arg_offset) ? 4 : 8; } - fprintf (file, - "\tcopy %%r2,%%r26\n\taddil L'LP$%04d-$global$,%%r27\n\tldo R'LP$%04d-$global$(%%r1),%%r24\n\tbl _mcount,%%r2\n\tldo %d(%%r2),%%r25\n", - hp_profile_labelno, hp_profile_labelno, -pc_offset - 12 - 8); + + emit_move_insn (gen_rtx (REG, SImode, 26), gen_rtx (REG, SImode, 2)); + emit_move_insn (tmpreg, gen_rtx (HIGH, SImode, hp_profile_label_rtx)); + emit_move_insn (gen_rtx (REG, SImode, 24), + gen_rtx (LO_SUM, SImode, tmpreg, hp_profile_label_rtx)); + /* %r25 is set from within the output pattern. */ + emit_insn (gen_call_profiler (GEN_INT (- pc_offset - 20))); + + /* Restore argument registers. */ for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4) - if (regs_ever_live[i]) - print_ldw (file, i, arg_offset, basereg); + if (regs_ever_live [i]) + load_reg (i, arg_offset, basereg); + if (current_function_returns_struct) - print_ldw (file, STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg); + load_reg (STRUCT_VALUE_REGNUM, -12 - offsetadj, basereg); + } - /* Normal register save. */ + /* Normal register save. + + Do not save the frame pointer in the frame_pointer_needed case. It + was done earlier. */ if (frame_pointer_needed) { - for (i = 18, offset = local_fsize; i >= 5; i--) - if (regs_ever_live[i] && ! call_used_regs[i]) + for (i = 18, offset = local_fsize; i >= 3; i--) + if (regs_ever_live[i] && ! call_used_regs[i] + && i != FRAME_POINTER_REGNUM) { - print_stw (file, i, offset, 4); offset += 4; + store_reg (i, offset, FRAME_POINTER_REGNUM); + offset += 4; } - if (regs_ever_live[3] && ! call_used_regs[3]) - { - print_stw (file, 3, offset, 4); offset += 4; - } } + /* No frame pointer needed. */ else { - for (i = 18, offset = local_fsize - actual_fsize; i >= 5; i--) + for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--) if (regs_ever_live[i] && ! call_used_regs[i]) { /* If merge_sp_adjust_with_store is nonzero, then we can @@ -1804,27 +1927,22 @@ output_function_prologue (file, size) if (merge_sp_adjust_with_store) { merge_sp_adjust_with_store = 0; - fprintf (file, "\tstwm %d,%d(0,%d)\n", i, -offset, 30); + emit_insn (gen_post_stwm (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (-offset), + gen_rtx (REG, SImode, i))); } else - print_stw (file, i, offset, 30); offset += 4; + store_reg (i, offset, STACK_POINTER_REGNUM); + offset += 4; } - if (regs_ever_live[3] && ! call_used_regs[3]) - { - /* If merge_sp_adjust_with_store is nonzero, then we can - optimize the first GR save. */ - if (merge_sp_adjust_with_store) - { - merge_sp_adjust_with_store = 0; - fprintf (file, "\tstwm %%r3,%d(0,%%r30)\n", -offset); - } - else - print_stw (file, 3, offset, 30); offset += 4; - } + /* If we wanted to merge the SP adjustment with a GR save, but we never - did any GR saves, then just output the adjustment here. */ + did any GR saves, then just emit the adjustment here. */ if (merge_sp_adjust_with_store) - fprintf (file, "\tldo %d(%%r30),%%r30\n", actual_fsize); + set_reg_plus_d (STACK_POINTER_REGNUM, + STACK_POINTER_REGNUM, + actual_fsize); } /* Align pointer properly (doubleword boundary). */ @@ -1833,28 +1951,23 @@ output_function_prologue (file, size) /* Floating point register store. */ if (save_fregs) { + + /* First get the frame or stack pointer to the start of the FP register + save area. */ if (frame_pointer_needed) - { - if (VAL_14_BITS_P (offset)) - fprintf (file, "\tldo %d(%%r4),%%r1\n", offset); - else - fprintf (file, "\taddil L'%d,%%r4\n\tldo R'%d(%%r1),%%r1\n", - offset, offset); - } + set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset); else - { - if (VAL_14_BITS_P (offset)) - fprintf (file, "\tldo %d(%%r30),%%r1\n", offset); - else - fprintf (file, "\taddil L'%d,%%r30\n\tldo R'%d(%%r1),%%r1\n", - offset, offset); - } - if (!TARGET_SNAKE) + set_reg_plus_d (1, STACK_POINTER_REGNUM, offset); + + /* Now actually save the FP registers. */ + if (! TARGET_SNAKE) { for (i = 43; i >= 40; i--) { if (regs_ever_live[i]) - fprintf (file, "\tfstds,ma %s,8(0,%%r1)\n", reg_names[i]); + emit_move_insn (gen_rtx (MEM, DFmode, + gen_rtx (POST_INC, DFmode, tmpreg)), + gen_rtx (REG, DFmode, i)); } } else @@ -1862,199 +1975,144 @@ output_function_prologue (file, size) for (i = 78; i >= 60; i -= 2) if (regs_ever_live[i] || regs_ever_live[i + 1]) { - fprintf (file, "\tfstds,ma %s,8(0,%%r1)\n", reg_names[i]); + emit_move_insn (gen_rtx (MEM, DFmode, + gen_rtx (POST_INC, DFmode, tmpreg)), + gen_rtx (REG, DFmode, i)); } } } } + void output_function_epilogue (file, size) FILE *file; int size; { - extern char call_used_regs[]; - extern int frame_pointer_needed; - int i, offset; - int merge_sp_adjust_with_load = 0; + /* hppa_expand_epilogue does the dirty work now. We just need + to output the assembler directives which denote the end + of a function. */ + fprintf (file, "\t.EXIT\n\t.PROCEND\n"); +} - /* In the common cases restore RP early to avoid load/use interlock when - RP gets used in the bv instruction. */ +void +hppa_expand_epilogue() +{ + rtx tmpreg; + int offset,i; + int merge_sp_adjust_with_load = 0; + + /* We will use this often. */ + tmpreg = gen_rtx (REG, SImode, 1); + + /* Try to restore RP early to avoid load/use interlocks when + RP gets used in the return (bv) instruction. This appears to still + be necessary even when we schedule the prologue and epilogue. */ if (frame_pointer_needed && (regs_ever_live [2] || profile_flag)) - fprintf (file, "\tldw -20(%%r4),%%r2\n"); - else if (VAL_14_BITS_P (actual_fsize + 20) - && (regs_ever_live [2] || profile_flag)) - fprintf(file,"\tldw %d(0,%%r30),%%r2\n", - (actual_fsize + 20)); + load_reg (2, -20, FRAME_POINTER_REGNUM); + /* No frame pointer, and stack is smaller than 8k. */ + else if (! frame_pointer_needed + && VAL_14_BITS_P (actual_fsize + 20) + && (regs_ever_live[2] || profile_flag)) + load_reg (2, - (actual_fsize + 20), STACK_POINTER_REGNUM); + + /* General register restores. */ if (frame_pointer_needed) { - for (i = 18, offset = local_fsize; i >= 5; i--) - if (regs_ever_live[i] && ! call_used_regs[i]) + for (i = 18, offset = local_fsize; i >= 3; i--) + if (regs_ever_live[i] && ! call_used_regs[i] + && i != FRAME_POINTER_REGNUM) { - print_ldw (file, i, offset, 4); offset += 4; + load_reg (i, offset, FRAME_POINTER_REGNUM); + offset += 4; } - if (regs_ever_live[3] && ! call_used_regs[3]) - { - print_ldw (file, 3, offset, 4); offset += 4; - } } else { - for (i = 18, offset = local_fsize - actual_fsize; i >= 5; i--) - if (regs_ever_live[i] && ! call_used_regs[i]) + for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--) + if (regs_ever_live[i] && ! call_used_regs[i]) { - /* Only for first load. And not if profiling. - merge_sp_adjust_with_load holds the register load with - which we will merge the sp adjustment with.*/ + /* Only for the first load. + merge_sp_adjust_with_load holds the register load + with which we will merge the sp adjustment. */ if (VAL_14_BITS_P (actual_fsize + 20) && local_fsize == 0 - && ! profile_flag && ! merge_sp_adjust_with_load) merge_sp_adjust_with_load = i; - else - print_ldw (file, i, offset, 30); offset += 4; + else + load_reg (i, offset, STACK_POINTER_REGNUM); + offset += 4; } - if (regs_ever_live[3] && ! call_used_regs[3]) - { - /* Only for first load. And not if profiling. - merge_sp_adjust_with_load holds the register load with - which we will merge the sp adjustment with.*/ - if (VAL_14_BITS_P (actual_fsize + 20) - && local_fsize == 0 - && ! profile_flag - && ! merge_sp_adjust_with_load) - merge_sp_adjust_with_load = 3; - else - print_ldw (file, 3, offset, 30); offset += 4; - } } - + /* Align pointer properly (doubleword boundary). */ offset = (offset + 7) & ~7; - /* Floating point register restore. */ + /* FP register restores. */ if (save_fregs) { + /* Adjust the register to index off of. */ if (frame_pointer_needed) - { - if (VAL_14_BITS_P (offset)) - fprintf (file, "\tldo %d(%%r4),%%r1\n", offset); - else - fprintf (file, "\taddil L'%d,%%r4\n\tldo R'%d(%%r1),%%r1\n", - offset, offset); - } + set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset); else - { - if (VAL_14_BITS_P (offset)) - fprintf (file, "\tldo %d(%%r30),%%r1\n", offset); - else - fprintf (file, "\taddil L'%d,%%r30\n\tldo R'%d(%%r1),%%r1\n", - offset, offset); - } - if (!TARGET_SNAKE) + set_reg_plus_d (1, STACK_POINTER_REGNUM, offset); + + /* Actually do the restores now. */ + if (! TARGET_SNAKE) { for (i = 43; i >= 40; i--) - { - if (regs_ever_live[i]) - fprintf (file, "\tfldds,ma 8(0,%%r1),%s\n", reg_names[i]); - } + if (regs_ever_live[i]) + emit_move_insn (gen_rtx (REG, DFmode, i), + gen_rtx (MEM, DFmode, + gen_rtx (POST_INC, DFmode, tmpreg))); + } else { for (i = 78; i >= 60; i -= 2) if (regs_ever_live[i] || regs_ever_live[i + 1]) - { - fprintf (file, "\tfldds,ma 8(0,%%r1),%s\n", reg_names[i]); - } + emit_move_insn (gen_rtx (REG, DFmode, i), + gen_rtx (MEM, DFmode, + gen_rtx (POST_INC, DFmode, tmpreg))); } } + + /* No frame pointer, but we have a stack greater than 8k. We restore + %r2 very late in this case. (all other cases are restored as early + as possible. */ + if (! frame_pointer_needed + && ! VAL_14_BITS_P (actual_fsize + 20) + && (regs_ever_live[2] || profile_flag)) + { + set_reg_plus_d (STACK_POINTER_REGNUM, + STACK_POINTER_REGNUM, + - actual_fsize); + /* Uses value left over in %r1 by set_reg_plus_d. */ + load_reg (2, - (actual_fsize + 20 + ((- actual_fsize) & ~0x7ff)), 1); + } + /* Reset stack pointer (and possibly frame pointer). The stack */ - /* pointer is initially set to fp + 64 to avoid a race condition. + /* pointer is initially set to fp + 64 to avoid a race condition. ??? What race condition?!? */ - if (frame_pointer_needed) - { - /* RP has already been restored in this case. */ - fprintf (file, "\tldo 64(%%r4),%%r30\n"); - fprintf (file, "\tbv 0(%%r2)\n\tldwm -64(0,%%r30),%%r4\n"); - } - else if (actual_fsize) - { - if (regs_ever_live[2] || profile_flag) - - { - /* In this case RP has already been restored! */ - if (VAL_14_BITS_P (actual_fsize + 20)) - { - /* Optimize load and sp adjustment. */ - if (merge_sp_adjust_with_load) - fprintf (file, "\tbv 0(%%r2)\n\tldwm %d(0,%%r30),%d\n", - -actual_fsize, merge_sp_adjust_with_load); - else - fprintf (file, "\tbv 0(%%r2)\n\tldo %d(%%r30),%%r30\n", -actual_fsize); - } - /* Large frame. Uncommon and not worth extra hair to avoid - load/use delay for RP. */ - else - fprintf (file, - "\taddil L'%d,%%r30\n\tldw %d(0,%%r1),%%r2\n\tbv 0(%%r2)\n\tldo R'%d(%%r1),%%r30\n", - - actual_fsize, - - (actual_fsize + 20 + ((-actual_fsize) & ~0x7ff)), - - actual_fsize); - } - /* Merge load with SP adjustment. */ - else if (merge_sp_adjust_with_load) - fprintf (file, "\tbv 0(%%r2)\n\tldwm %d(0,%%r30),%d\n", - - actual_fsize, merge_sp_adjust_with_load); - else if (VAL_14_BITS_P (actual_fsize)) - fprintf (file, "\tbv 0(%%r2)\n\tldo %d(%%r30),%%r30\n", - actual_fsize); - else - fprintf (file, "\taddil L'%d,%%r30\n\tbv 0(%%r2)\n\tldo R'%d(%%r1),%%r30\n", - - actual_fsize, - actual_fsize); - } - else if (current_function_epilogue_delay_list) + else if (frame_pointer_needed) { - fprintf (file, "\tbv 0(%%r2)\n"); - final_scan_insn (XEXP (current_function_epilogue_delay_list, 0), file, - 1, 0, 1); + set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64); + emit_insn (gen_pre_ldwm (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-64), frame_pointer_rtx)); } - else - fprintf (file, "\tbv,n 0(%%r2)\n"); - fprintf (file, "\t.EXIT\n\t.PROCEND\n"); -} - -/* If there's a frame, it will be deallocated in the delay slot of the - bv 0(2) return instruction. */ - -int -hppa_epilogue_delay_slots () -{ - return (compute_frame_size (get_frame_size (), 0) ? 0 : 1); -} - -/* Return nonzero if TRIAL can go into the function epilogue's - delay slot. SLOT is the slot we are trying to fill. */ - -int -eligible_for_epilogue_delay (trial, slot) - rtx trial; - int slot; -{ - if (slot >= 1) - return 0; - if (GET_CODE (trial) != INSN - || GET_CODE (PATTERN (trial)) != SET) - return 0; - if (get_attr_length (trial) != 1) - return 0; - - /* The epilogue clobbers whatever value is in %r2 before the - delay slot executes, so insns which use %r2 can not be - used to fill the epilogue's delay slot. */ - if (refers_to_regno_p (2, 3, PATTERN (trial), NULL_PTR)) - return 0; - - return (get_attr_in_branch_delay (trial) == IN_BRANCH_DELAY_TRUE); + /* If we were deferring a callee register restore, do it now. */ + else if (! frame_pointer_needed && merge_sp_adjust_with_load) + emit_insn (gen_pre_ldwm (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (- actual_fsize), + gen_rtx (REG, SImode, + merge_sp_adjust_with_load))); + else if (actual_fsize != 0) + set_reg_plus_d (STACK_POINTER_REGNUM, + STACK_POINTER_REGNUM, + - actual_fsize); } /* This is only valid once reload has completed because it depends on