aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1995-05-02 23:07:56 -0600
committerJeff Law <law@gcc.gnu.org>1995-05-02 23:07:56 -0600
commit93ae92c1d55bcfff73922939264b74f77ddb91a5 (patch)
tree3473fa1d2355a7ba9deca14e10c8f4e49185c67c /gcc
parenta69e1f6afc37b9203a538f94c89df4efb416847b (diff)
downloadgcc-93ae92c1d55bcfff73922939264b74f77ddb91a5.zip
gcc-93ae92c1d55bcfff73922939264b74f77ddb91a5.tar.gz
gcc-93ae92c1d55bcfff73922939264b74f77ddb91a5.tar.bz2
pa.c (output_call): Fix typo/thinko in last change.
* pa.c (output_call): Fix typo/thinko in last change. (output_function_epilogue): Align the data section before emitting deferred plabels. From Torbjorn: * pa.c (before functions): Declare deferred_plabels and n_deferred_plabels. (output_call): When generating pic, don't use LP and RP. Use 32 bit plabel instead. (output_function_epilogue): Output plabels accumulated in output_call. From-SVN: r9567
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/pa/pa.c63
1 files changed, 58 insertions, 5 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 1ef1c38..6afbbcf 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -63,6 +63,16 @@ static rtx find_addr_reg ();
unsigned int total_code_bytes;
+/* Variables to handle plabels that we discover are necessary at assembly
+ output time. They are output after the currrent function. */
+
+struct defer_plab
+{
+ rtx internal_label;
+ rtx symbol;
+} *deferred_plabels = 0;
+int n_deferred_plabels = 0;
+
void
override_options ()
{
@@ -2330,8 +2340,8 @@ output_function_epilogue (file, size)
FILE *file;
int size;
{
-
rtx insn = get_last_insn ();
+ int i;
/* hppa_expand_epilogue does the dirty work now. We just need
to output the assembler directives which denote the end
@@ -2356,6 +2366,23 @@ output_function_epilogue (file, size)
fprintf (file, "\tnop\n");
fprintf (file, "\t.EXIT\n\t.PROCEND\n");
+
+ /* If we have deferred plabels, then we need to switch into the data
+ section and align it to a 4 byte boundary before we output the
+ deferred plabels. */
+ if (n_deferred_plabels)
+ {
+ data_section ();
+ ASM_OUTPUT_ALIGN (file, 2);
+ }
+
+ /* Now output the deferred plabels. */
+ for (i = 0; i < n_deferred_plabels; i++)
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
+ ASM_OUTPUT_INT (file, deferred_plabels[i].symbol);
+ }
+ n_deferred_plabels = 0;
}
void
@@ -4109,10 +4136,36 @@ output_call (insn, call_dest, return_pointer)
}
}
- /* Now emit the inline long-call. */
- xoperands[0] = call_dest;
- output_asm_insn ("ldil LP%%%0,%%r22\n\tldo RP%%%0(%%r22),%%r22",
- xoperands);
+ if (flag_pic)
+ {
+ /* We have to load the address of the function using a procedure
+ label (plabel). The LP and RP relocs don't work reliably for PIC,
+ so we make a plain 32 bit plabel in the data segment instead. We
+ have to defer outputting it of course... Not pretty. */
+
+ xoperands[0] = gen_label_rtx ();
+ output_asm_insn ("addil LT%%%0,%%r19\n\tldw RT%%%0(%%r1),%%r22",
+ xoperands);
+ output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands);
+
+ if (deferred_plabels == 0)
+ deferred_plabels = (struct defer_plab *)
+ xmalloc (1 * sizeof (struct defer_plab));
+ else
+ deferred_plabels = (struct defer_plab *)
+ xrealloc (deferred_plabels,
+ (n_deferred_plabels + 1) * sizeof (struct defer_plab));
+ deferred_plabels[n_deferred_plabels].internal_label = xoperands[0];
+ deferred_plabels[n_deferred_plabels].symbol = call_dest;
+ n_deferred_plabels++;
+ }
+ else
+ {
+ /* Now emit the inline long-call. */
+ xoperands[0] = call_dest;
+ output_asm_insn ("ldil LP%%%0,%%r22\n\tldo RP%%%0(%%r22),%%r22",
+ xoperands);
+ }
/* If TARGET_MILLICODE_LONG_CALLS, then we must use a long-call sequence
to call dyncall! */