aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/pa/lib2funcs.asm244
-rw-r--r--gcc/config/pa/pa.c222
-rw-r--r--gcc/config/pa/pa.h6
-rw-r--r--gcc/config/pa/pa.md80
-rw-r--r--gcc/config/pa/t-pro9
5 files changed, 444 insertions, 117 deletions
diff --git a/gcc/config/pa/lib2funcs.asm b/gcc/config/pa/lib2funcs.asm
index d6f5cbc..7ea7fbf 100644
--- a/gcc/config/pa/lib2funcs.asm
+++ b/gcc/config/pa/lib2funcs.asm
@@ -1,5 +1,6 @@
; Subroutines for calling unbound dynamic functions from within GDB for HPPA.
-; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+; Subroutines for out of line prologues and epilogues on for the HPPA
+; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
; This file is part of GNU CC.
@@ -75,7 +76,7 @@ L$foo
;
; * Creates a new stack frame (sp'), size of the frame is passed in %r21
;
-; * The old stack pointer is saved at sp
+; * The old stack pointer is saved at sp (frame pointer version only).
;
; * Saves grs (passed in low 16 bits of %r22 into the stack frame
; at sp' + local_fsize (passed in %r19).
@@ -83,7 +84,7 @@ L$foo
; * Saves frs (passed in high 16 bits of %r22) into the stack
; frame at sp' + local_fsize (passed in %r19).
;
-; * Sets up a frame pointer (in %r3).
+; * Sets up a frame pointer (in %r3) (frame pointer version only).
;
; * Returns to the instruction _immediately_ after the call to
; this function.
@@ -107,9 +108,6 @@ __outline_prologue
; Make our new frame.
add %r21,%r30,%r30
- ; Save our old stack pointer.
- stw %r20,0(0,%r20)
-
; Add in local_fsize to our frame pointer so we do register
; saves into the right place
add %r20,%r19,%r20
@@ -192,13 +190,124 @@ L$0000
fstws,ma %fr12,8(0,%r20)
nop
L$0001
+ ; Return
+ bv,n 0(%r31)
+ .EXIT
+ .PROCEND
+
+
+
+ .align 32
+ .NSUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .EXPORT __outline_prologue_fp,MILLICODE
+__outline_prologue_fp
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
+ copy %r30,%r20
+
+ ; Subtract 4 from our return pointer so that we return to
+ ; the right location.
+ ldo -4(%r31),%r31
+
+ ; Save off %r2
+ stw %r2,-20(0,%r30)
+
+ ; Make our new frame.
+ add %r21,%r30,%r30
+
+ ; Save our old stack pointer.
+ stw %r20,0(0,%r20)
+
+ ; Add in local_fsize to our frame pointer so we do register
+ ; saves into the right place
+ add %r20,%r19,%r20
+
+ ; %r22 tells us what registers we need to save. The upper half
+ ; is for fp registers, the lower half for integer registers.
+ ; We put the lower half in %r1 and the upper half into %r22
+ ; for later use.
+ extru %r22,31,16,%r1
+ extrs %r22,15,16,%r22
+
+ ; %r1 now olds a value 0-18 which corresponds to the number
+ ; of grs we need to save. We need to reverse that value so
+ ; we can just into the table and straight-line execute to the
+ ; end of the gr saves.
+ comb,= %r0,%r1,L$0002
+ subi 18,%r1,%r1
+ blr,n %r1,%r0
+ b,n L$0002
+ stws,ma %r18,4(0,%r20)
+ nop
+ stws,ma %r17,4(0,%r20)
+ nop
+ stws,ma %r16,4(0,%r20)
+ nop
+ stws,ma %r15,4(0,%r20)
+ nop
+ stws,ma %r14,4(0,%r20)
+ nop
+ stws,ma %r13,4(0,%r20)
+ nop
+ stws,ma %r12,4(0,%r20)
+ nop
+ stws,ma %r11,4(0,%r20)
+ nop
+ stws,ma %r10,4(0,%r20)
+ nop
+ stws,ma %r9,4(0,%r20)
+ nop
+ stws,ma %r8,4(0,%r20)
+ nop
+ stws,ma %r7,4(0,%r20)
+ nop
+ stws,ma %r6,4(0,%r20)
+ nop
+ stws,ma %r5,4(0,%r20)
+ nop
+ stws,ma %r4,4(0,%r20)
+ nop
+ stws,ma %r3,4(0,%r20)
+ nop
+L$0002
+ ; All gr saves are done. Align the temporary frame pointer and
+ ; do the fr saves.
+ ldo 7(%r20),%r20
+ depi 0,31,3,%r20
+
+ comb,= %r0,%r22,L$0003
+ subi 21,%r22,%r22
+ blr,n %r22,%r0
+ b,n L$0003
+ fstws,ma %fr21,8(0,%r20)
+ nop
+ fstws,ma %fr20,8(0,%r20)
+ nop
+ fstws,ma %fr19,8(0,%r20)
+ nop
+ fstws,ma %fr18,8(0,%r20)
+ nop
+ fstws,ma %fr17,8(0,%r20)
+ nop
+ fstws,ma %fr16,8(0,%r20)
+ nop
+ fstws,ma %fr15,8(0,%r20)
+ nop
+ fstws,ma %fr14,8(0,%r20)
+ nop
+ fstws,ma %fr13,8(0,%r20)
+ nop
+ fstws,ma %fr12,8(0,%r20)
+ nop
+L$0003
; Return, setting up a frame pointer in the delay slot
bv 0(%r31)
sub %r30,%r21,%r3
-
.EXIT
.PROCEND
+
; This is an out-of-line epilogue. It's operation is basically the reverse
; of the out-of-line prologue.
@@ -209,6 +318,114 @@ __outline_epilogue
.PROC
.CALLINFO FRAME=0,NO_CALLS
.ENTRY
+ ; Get our original stack pointer and put it in %r20
+ sub %r30,%r21,%r20
+
+ ; Subtract 4 from our return pointer so that we return to
+ ; the right location.
+ ldo -4(%r31),%r31
+
+ ; Reload %r2
+ ldw -20(0,%r20),%r2
+
+ ; Add in local_fsize (%r19) to the frame pointer to find
+ ; the saved registers.
+ add %r20,%r19,%r20
+
+ ; %r22 tells us what registers we need to restore. The upper half
+ ; is for fp registers, the lower half for integer registers.
+ ; We put the lower half in %r1 and the upper half into %r22
+ ; for later use.
+ extru %r22,31,16,%r1
+ extrs %r22,15,16,%r22
+
+ ; %r1 now olds a value 0-18 which corresponds to the number
+ ; of grs we need to restore. We need to reverse that value so
+ ; we can just into the table and straight-line execute to the
+ ; end of the gr restore.
+ comb,= %r0,%r1,L$0004
+ subi 18,%r1,%r1
+ blr,n %r1,%r0
+ b,n L$0004
+ ldws,ma 4(0,%r20),%r18
+ nop
+ ldws,ma 4(0,%r20),%r17
+ nop
+ ldws,ma 4(0,%r20),%r16
+ nop
+ ldws,ma 4(0,%r20),%r15
+ nop
+ ldws,ma 4(0,%r20),%r14
+ nop
+ ldws,ma 4(0,%r20),%r13
+ nop
+ ldws,ma 4(0,%r20),%r12
+ nop
+ ldws,ma 4(0,%r20),%r11
+ nop
+ ldws,ma 4(0,%r20),%r10
+ nop
+ ldws,ma 4(0,%r20),%r9
+ nop
+ ldws,ma 4(0,%r20),%r8
+ nop
+ ldws,ma 4(0,%r20),%r7
+ nop
+ ldws,ma 4(0,%r20),%r6
+ nop
+ ldws,ma 4(0,%r20),%r5
+ nop
+ ldws,ma 4(0,%r20),%r4
+ nop
+ ldws,ma 4(0,%r20),%r3
+ nop
+L$0004
+ ; All gr restore are done. Align the temporary frame pointer and
+ ; do the fr restore.
+ ldo 7(%r20),%r20
+ depi 0,31,3,%r20
+
+ comb,= %r0,%r22,L$0005
+ subi 21,%r22,%r22
+ blr,n %r22,%r0
+ b,n L$0005
+ fldws,ma 8(0,%r20),%fr21
+ nop
+ fldws,ma 8(0,%r20),%fr20
+ nop
+ fldws,ma 8(0,%r20),%fr19
+ nop
+ fldws,ma 8(0,%r20),%fr18
+ nop
+ fldws,ma 8(0,%r20),%fr17
+ nop
+ fldws,ma 8(0,%r20),%fr16
+ nop
+ fldws,ma 8(0,%r20),%fr15
+ nop
+ fldws,ma 8(0,%r20),%fr14
+ nop
+ fldws,ma 8(0,%r20),%fr13
+ nop
+ fldws,ma 8(0,%r20),%fr12
+ nop
+L$0005
+ ; Return and deallocate our frame.
+ bv 0(%r31)
+ sub %r30,%r21,%r30
+ .EXIT
+ .PROCEND
+
+; This is an out-of-line epilogue. It's operation is basically the reverse
+; of the out-of-line prologue.
+
+ .align 32
+ .NSUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .EXPORT __outline_epilogue_fp,MILLICODE
+__outline_epilogue_fp
+ .PROC
+ .CALLINFO FRAME=0,NO_CALLS
+ .ENTRY
; Make a copy of our frame pointer into %r20
copy %r3,%r20
@@ -238,10 +455,10 @@ __outline_epilogue
; of grs we need to restore. We need to reverse that value so
; we can just into the table and straight-line execute to the
; end of the gr restore.
- comb,= %r0,%r1,L$0002
+ comb,= %r0,%r1,L$0006
subi 18,%r1,%r1
blr,n %r1,%r0
- b,n L$0002
+ b,n L$0006
ldws,ma 4(0,%r20),%r18
nop
ldws,ma 4(0,%r20),%r17
@@ -274,16 +491,16 @@ __outline_epilogue
nop
ldws,ma 4(0,%r20),%r3
nop
-L$0002
+L$0006
; All gr restore are done. Align the temporary frame pointer and
; do the fr restore.
ldo 7(%r20),%r20
depi 0,31,3,%r20
- comb,= %r0,%r22,L$0003
+ comb,= %r0,%r22,L$0007
subi 21,%r22,%r22
blr,n %r22,%r0
- b,n L$0003
+ b,n L$0007
fldws,ma 8(0,%r20),%fr21
nop
fldws,ma 8(0,%r20),%fr20
@@ -304,10 +521,11 @@ L$0002
nop
fldws,ma 8(0,%r20),%fr12
nop
-L$0003
+L$0007
; Return and deallocate our frame.
bv 0(%r31)
copy %r21,%r30
.EXIT
.PROCEND
+
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 545dab5..679716d 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for HPPA.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.c
This file is part of GNU CC.
@@ -55,6 +55,10 @@ int hp_profile_labelno;
registers which were saved by the current function's prologue. */
static int gr_saved, fr_saved;
+/* Whether or not the current function uses an out-of-line prologue
+ and epilogue. */
+static int out_of_line_prologue_epilogue;
+
static rtx find_addr_reg ();
/* Keep track of the number of bytes we have output in the CODE subspaces
@@ -2042,52 +2046,30 @@ compute_frame_size (size, fregs_live)
we need to add this in because of STARTING_FRAME_OFFSET. */
fsize = size + (size || frame_pointer_needed ? 8 : 0);
- for (i = 18; i >= 4; i--)
- {
- if (regs_ever_live[i])
- {
- /* For out of line prologues/epilogues we only need to
- compute the highest register number to save and
- allocate space for all the callee saved registers
- with a lower number. */
- if (TARGET_SPACE)
- {
- fsize += 4 * (i - 3);
- break;
- }
- fsize += 4;
- }
- }
-
- /* We always save %r3, make room for it. */
- if (TARGET_SPACE)
- fsize += 8;
+ /* We do not want to create holes in the callee registers that
+ get saved (confuses gdb), so once we know the highest we just
+ save all the ones below it, whether they're used or not. */
+ for (i = 18; i >= 3; i--)
+ if (regs_ever_live[i])
+ {
+ fsize += 4 * (i - 2);
+ break;
+ }
- /* If we don't have a frame pointer, the register normally used for that
- purpose is saved just like other registers, not in the "frame marker". */
- if (! frame_pointer_needed)
- {
- if (regs_ever_live[FRAME_POINTER_REGNUM])
- fsize += 4;
- }
+ /* Round the stack. */
fsize = (fsize + 7) & ~7;
+ /* We do not want to create holes in the callee registers that
+ get saved (confuses gdb), so once we know the highest we just
+ save all the ones below it, whether they're used or not. */
for (i = 66; i >= 48; i -= 2)
if (regs_ever_live[i] || regs_ever_live[i + 1])
{
if (fregs_live)
*fregs_live = 1;
- /* For out of line prologues/epilogues we only need to
- compute the highest register number to save and
- allocate space for all the callee saved registers
- with a lower number. */
- if (TARGET_SPACE)
- {
- fsize += 4 * (i - 46);
- break;
- }
- fsize += 8;
+ fsize += 4 * (i = 46);
+ break;
}
fsize += current_function_outgoing_args_size;
@@ -2185,42 +2167,86 @@ hppa_expand_prologue()
{
rtx operands[2];
int saves = 0;
+ int outline_insn_count = 0;
+ int inline_insn_count = 0;
- /* Put the local_fisze into %r19. */
- operands[0] = gen_rtx (REG, SImode, 19);
- operands[1] = GEN_INT (local_fsize);
- emit_move_insn (operands[0], operands[1]);
+ /* Count the number of insns for the inline and out of line
+ variants so we can choose one appropriately.
- /* Put the stack size into %r21. */
- operands[0] = gen_rtx (REG, SImode, 21);
- operands[1] = size_rtx;
- emit_move_insn (operands[0], operands[1]);
+ No need to screw with counting actual_fsize operations -- they're
+ done for both inline and out of line prologues. */
+ if (regs_ever_live[2])
+ inline_insn_count += 1;
+
+ if (! cint_ok_for_move (local_fsize))
+ outline_insn_count += 2;
+ else
+ outline_insn_count += 1;
/* Put the register save info into %r22. */
for (i = 18; i >= 3; i--)
if (regs_ever_live[i] && ! call_used_regs[i])
{
+ /* -1 because the stack adjustment is normally done in
+ the same insn as a register save. */
+ inline_insn_count += (i - 2) - 1;
saves = i;
break;
}
-
+
for (i = 66; i >= 48; i -= 2)
if (regs_ever_live[i] || regs_ever_live[i + 1])
{
+ /* +1 needed as we load %r1 with the start of the freg
+ save area. */
+ inline_insn_count += (i/2 - 23) + 1;
saves |= ((i/2 - 12 ) << 16);
break;
}
- operands[0] = gen_rtx (REG, SImode, 22);
- operands[1] = GEN_INT (saves);
- emit_move_insn (operands[0], operands[1]);
+ if (frame_pointer_needed)
+ inline_insn_count += 3;
- /* Now call the out-of-line prologue. */
- emit_insn (gen_outline_prologue_call ());
- emit_insn (gen_blockage ());
- return;
+ if (! cint_ok_for_move (saves))
+ outline_insn_count += 2;
+ else
+ outline_insn_count += 1;
+
+ if (TARGET_PORTABLE_RUNTIME)
+ outline_insn_count += 2;
+ else
+ outline_insn_count += 1;
+
+ /* If there's a lot of insns in the prologue, then do it as
+ an out-of-line sequence. */
+ if (inline_insn_count > outline_insn_count)
+ {
+ /* Put the local_fisze into %r19. */
+ operands[0] = gen_rtx (REG, SImode, 19);
+ operands[1] = GEN_INT (local_fsize);
+ emit_move_insn (operands[0], operands[1]);
+
+ /* Put the stack size into %r21. */
+ operands[0] = gen_rtx (REG, SImode, 21);
+ operands[1] = size_rtx;
+ emit_move_insn (operands[0], operands[1]);
+
+ operands[0] = gen_rtx (REG, SImode, 22);
+ operands[1] = GEN_INT (saves);
+ emit_move_insn (operands[0], operands[1]);
+
+ /* Now call the out-of-line prologue. */
+ emit_insn (gen_outline_prologue_call ());
+ emit_insn (gen_blockage ());
+
+ /* Note that we're using an out-of-line prologue. */
+ out_of_line_prologue_epilogue = 1;
+ return;
+ }
}
+ out_of_line_prologue_epilogue = 0;
+
/* 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)
@@ -2345,22 +2371,28 @@ hppa_expand_prologue()
was done earlier. */
if (frame_pointer_needed)
{
+ int found_one = 0;
for (i = 18, offset = local_fsize; i >= 4; i--)
- if (regs_ever_live[i] && ! call_used_regs[i])
+ if (regs_ever_live[i] && ! call_used_regs[i]
+ || found_one)
{
+ found_one = 1;
store_reg (i, offset, FRAME_POINTER_REGNUM);
offset += 4;
gr_saved++;
}
- /* Account for %r4 which is saved in a special place. */
+ /* Account for %r3 which is saved in a special place. */
gr_saved++;
}
/* No frame pointer needed. */
else
{
+ int found_one = 0;
for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
- if (regs_ever_live[i] && ! call_used_regs[i])
+ if (regs_ever_live[i] && ! call_used_regs[i]
+ || found_one)
{
+ found_one = 1;
/* If merge_sp_adjust_with_store is nonzero, then we can
optimize the first GR save. */
if (merge_sp_adjust_with_store)
@@ -2400,13 +2432,18 @@ hppa_expand_prologue()
/* Now actually save the FP registers. */
for (i = 66; i >= 48; i -= 2)
- if (regs_ever_live[i] || regs_ever_live[i + 1])
- {
- emit_move_insn (gen_rtx (MEM, DFmode,
- gen_rtx (POST_INC, DFmode, tmpreg)),
- gen_rtx (REG, DFmode, i));
- fr_saved++;
- }
+ {
+ int found_one = 0;
+ if (regs_ever_live[i] || regs_ever_live[i + 1]
+ || found_one)
+ {
+ found_one = 1;
+ emit_move_insn (gen_rtx (MEM, DFmode,
+ gen_rtx (POST_INC, DFmode, tmpreg)),
+ gen_rtx (REG, DFmode, i));
+ fr_saved++;
+ }
+ }
}
/* When generating PIC code it is necessary to save/restore the
@@ -2490,7 +2527,7 @@ hppa_expand_epilogue ()
int merge_sp_adjust_with_load = 0;
/* Handle out of line prologues and epilogues. */
- if (TARGET_SPACE)
+ if (TARGET_SPACE && out_of_line_prologue_epilogue)
{
int saves = 0;
rtx operands[2];
@@ -2517,6 +2554,11 @@ hppa_expand_epilogue ()
operands[1] = GEN_INT (local_fsize);
emit_move_insn (operands[0], operands[1]);
+ /* Put the stack size into %r21. */
+ operands[0] = gen_rtx (REG, SImode, 21);
+ operands[1] = GEN_INT (actual_fsize);
+ emit_move_insn (operands[0], operands[1]);
+
operands[0] = gen_rtx (REG, SImode, 22);
operands[1] = GEN_INT (saves);
emit_move_insn (operands[0], operands[1]);
@@ -2545,9 +2587,12 @@ hppa_expand_epilogue ()
/* General register restores. */
if (frame_pointer_needed)
{
+ int found_one = 0;
for (i = 18, offset = local_fsize; i >= 4; i--)
- if (regs_ever_live[i] && ! call_used_regs[i])
+ if (regs_ever_live[i] && ! call_used_regs[i]
+ || found_one)
{
+ found_one = 1;
load_reg (i, offset, FRAME_POINTER_REGNUM);
offset += 4;
}
@@ -2555,19 +2600,24 @@ hppa_expand_epilogue ()
else
{
for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
- if (regs_ever_live[i] && ! call_used_regs[i])
- {
- /* 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
- && ! merge_sp_adjust_with_load)
- merge_sp_adjust_with_load = i;
- else
- load_reg (i, offset, STACK_POINTER_REGNUM);
- offset += 4;
- }
+ {
+ int found_one = 0;
+ if (regs_ever_live[i] && ! call_used_regs[i]
+ || found_one)
+ {
+ found_one = 1;
+ /* 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
+ && ! merge_sp_adjust_with_load)
+ merge_sp_adjust_with_load = i;
+ else
+ load_reg (i, offset, STACK_POINTER_REGNUM);
+ offset += 4;
+ }
+ }
}
/* Align pointer properly (doubleword boundary). */
@@ -2584,10 +2634,16 @@ hppa_expand_epilogue ()
/* Actually do the restores now. */
for (i = 66; i >= 48; i -= 2)
- if (regs_ever_live[i] || regs_ever_live[i + 1])
- emit_move_insn (gen_rtx (REG, DFmode, i),
- gen_rtx (MEM, DFmode,
- gen_rtx (POST_INC, DFmode, tmpreg)));
+ {
+ int found_one = 0;
+ if (regs_ever_live[i] || regs_ever_live[i + 1])
+ {
+ found_one = 1;
+ emit_move_insn (gen_rtx (REG, DFmode, i),
+ gen_rtx (MEM, DFmode,
+ gen_rtx (POST_INC, DFmode, tmpreg)));
+ }
+ }
}
/* Emit a blockage insn here to keep these insns from being moved to
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index df1fedd..a464bda 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -560,11 +560,9 @@ do { \
/* Base register for access to local variables of the function. */
#define FRAME_POINTER_REGNUM 3
-/* Value should be nonzero if functions must have frame pointers.
- All functions have frame pointers when optimizing for space
- (for now). */
+/* Value should be nonzero if functions must have frame pointers. */
#define FRAME_POINTER_REQUIRED \
- (current_function_calls_alloca || TARGET_SPACE)
+ (current_function_calls_alloca)
/* C statement to store the difference between the frame pointer
and the stack pointer values immediately after the function prologue.
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index a64d17b..116f372 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -1,5 +1,5 @@
;;- Machine description for HP PA-RISC architecture for GNU C compiler
-;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
;; Contributed by the Center for Software Science at the University
;; of Utah.
@@ -4850,18 +4850,39 @@
""
"*
{
- /* Must import the magic millicode routine. */
- output_asm_insn (\".IMPORT __outline_prologue,MILLICODE\", NULL);
+ extern int frame_pointer_needed;
- /* The out-of-line prologue will make sure we return to the right
- instruction. */
- if (TARGET_PORTABLE_RUNTIME)
+ /* We need two different versions depending on whether or not we
+ need a frame pointer. Also note that we return to the instruction
+ immediately after the branch rather than two instructions after the
+ break as normally is the case. */
+ if (frame_pointer_needed)
{
- output_asm_insn (\"ldil L'__outline_prologue,%%r31\", NULL);
- output_asm_insn (\"ble,n R'__outline_prologue(%%sr0,%%r31)\", NULL);
+ /* Must import the magic millicode routine(s). */
+ output_asm_insn (\".IMPORT __outline_prologue_fp,MILLICODE\", NULL);
+
+ if (TARGET_PORTABLE_RUNTIME)
+ {
+ output_asm_insn (\"ldil L'__outline_prologue_fp,%%r31\", NULL);
+ output_asm_insn (\"ble,n R'__outline_prologue_fp(%%sr0,%%r31)\",
+ NULL);
+ }
+ else
+ output_asm_insn (\"bl,n __outline_prologue_fp,%%r31\", NULL);
}
else
- output_asm_insn (\"bl,n __outline_prologue,%%r31\", NULL);
+ {
+ /* Must import the magic millicode routine(s). */
+ output_asm_insn (\".IMPORT __outline_prologue,MILLICODE\", NULL);
+
+ if (TARGET_PORTABLE_RUNTIME)
+ {
+ output_asm_insn (\"ldil L'__outline_prologue,%%r31\", NULL);
+ output_asm_insn (\"ble,n R'__outline_prologue(%%sr0,%%r31)\", NULL);
+ }
+ else
+ output_asm_insn (\"bl,n __outline_prologue,%%r31\", NULL);
+ }
return \"\";
}"
[(set_attr "type" "multi")
@@ -4882,18 +4903,43 @@
""
"*
{
- /* Must import the magic millicode routine. */
- output_asm_insn (\".IMPORT __outline_epilogue,MILLICODE\", NULL);
+ extern int frame_pointer_needed;
- /* The out-of-line prologue will make sure we return to the right
- instruction. */
- if (TARGET_PORTABLE_RUNTIME)
+ /* We need two different versions depending on whether or not we
+ need a frame pointer. Also note that we return to the instruction
+ immediately after the branch rather than two instructions after the
+ break as normally is the case. */
+ if (frame_pointer_needed)
{
- output_asm_insn (\"ldil L'__outline_epilogue,%%r31\", NULL);
- output_asm_insn (\"ble,n R'__outline_epilogue(%%sr0,%%r31)\", NULL);
+ /* Must import the magic millicode routine. */
+ output_asm_insn (\".IMPORT __outline_epilogue_fp,MILLICODE\", NULL);
+
+ /* The out-of-line prologue will make sure we return to the right
+ instruction. */
+ if (TARGET_PORTABLE_RUNTIME)
+ {
+ output_asm_insn (\"ldil L'__outline_epilogue_fp,%%r31\", NULL);
+ output_asm_insn (\"ble,n R'__outline_epilogue_fp(%%sr0,%%r31)\",
+ NULL);
+ }
+ else
+ output_asm_insn (\"bl,n __outline_epilogue_fp,%%r31\", NULL);
}
else
- output_asm_insn (\"bl,n __outline_epilogue,%%r31\", NULL);
+ {
+ /* Must import the magic millicode routine. */
+ output_asm_insn (\".IMPORT __outline_epilogue,MILLICODE\", NULL);
+
+ /* The out-of-line prologue will make sure we return to the right
+ instruction. */
+ if (TARGET_PORTABLE_RUNTIME)
+ {
+ output_asm_insn (\"ldil L'__outline_epilogue,%%r31\", NULL);
+ output_asm_insn (\"ble,n R'__outline_epilogue(%%sr0,%%r31)\", NULL);
+ }
+ else
+ output_asm_insn (\"bl,n __outline_epilogue,%%r31\", NULL);
+ }
return \"\";
}"
[(set_attr "type" "multi")
diff --git a/gcc/config/pa/t-pro b/gcc/config/pa/t-pro
index af77bd8..f9a7732 100644
--- a/gcc/config/pa/t-pro
+++ b/gcc/config/pa/t-pro
@@ -19,3 +19,12 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
lib2funcs.asm: $(srcdir)/config/pa/lib2funcs.asm
rm -f lib2funcs.asm
cp $(srcdir)/config/pa/lib2funcs.asm .
+
+# Build the libraries for both speed and space optimizations
+
+MULTILIB_OPTIONS=mspace
+MULTILIB_DIRNAMES=space
+MULTILIB_MATCHES=
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib