pa.c (update_total_code_bytes): New function.
* pa.c (update_total_code_bytes): New function. (last_address): Number of bytes output for a function and its associated thunks. (compute_frame_size): Use BITS_PER_UNIT. (pa_output_function_epilogue): Compute last_address. Use update_total_code_bytes. (output_lbranch): Handle long branch on portable runtime. (attr_length_millicode_call, attr_length_call, attr_length_indirect_call): Only use total_code_bytes for calls in the text section. (output_call): Only use an indirect call sequence when the target is not local. (pa_asm_output_mi_thunk): Handle updating of total_code_bytes. Improve test to determine when an IA-relative branch can be used. Add various long branch sequences. Avoid using an indirect branch on all ports except SOM. From-SVN: r68677
This commit is contained in:
parent
342e2b749d
commit
5fad1c24db
@ -1,3 +1,23 @@
|
||||
|
||||
2003-06-29 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
|
||||
|
||||
* pa.c (update_total_code_bytes): New function.
|
||||
(last_address): Number of bytes output for a function and its
|
||||
associated thunks.
|
||||
(compute_frame_size): Use BITS_PER_UNIT.
|
||||
(pa_output_function_epilogue): Compute last_address. Use
|
||||
update_total_code_bytes.
|
||||
(output_lbranch): Handle long branch on portable runtime.
|
||||
(attr_length_millicode_call, attr_length_call,
|
||||
attr_length_indirect_call): Only use total_code_bytes for calls in
|
||||
the text section.
|
||||
(output_call): Only use an indirect call sequence when the target is
|
||||
not local.
|
||||
(pa_asm_output_mi_thunk): Handle updating of total_code_bytes. Improve
|
||||
test to determine when an IA-relative branch can be used. Add various
|
||||
long branch sequences. Avoid using an indirect branch on all ports
|
||||
except SOM.
|
||||
|
||||
2003-06-29 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* expr.c (clear_by_pieces): Fix prototype.
|
||||
|
@ -113,6 +113,7 @@ static void store_reg_modify PARAMS ((int, int, int));
|
||||
static void load_reg PARAMS ((int, int, int));
|
||||
static void set_reg_plus_d PARAMS ((int, int, int, int));
|
||||
static void pa_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static void update_total_code_bytes PARAMS ((int));
|
||||
static void pa_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
|
||||
static int pa_adjust_cost PARAMS ((rtx, rtx, rtx, int));
|
||||
static int pa_adjust_priority PARAMS ((rtx, int));
|
||||
@ -169,10 +170,15 @@ static int gr_saved, fr_saved;
|
||||
|
||||
static rtx find_addr_reg PARAMS ((rtx));
|
||||
|
||||
/* Keep track of the number of bytes we have output in the CODE subspaces
|
||||
/* Keep track of the number of bytes we have output in the CODE subspace
|
||||
during this compilation so we'll know when to emit inline long-calls. */
|
||||
unsigned long total_code_bytes;
|
||||
|
||||
/* The last address of the previous function plus the number of bytes in
|
||||
associated thunks that have been output. This is used to determine if
|
||||
a thunk can use an IA-relative branch to reach its target function. */
|
||||
static int last_address;
|
||||
|
||||
/* Variables to handle plabels that we discover are necessary at assembly
|
||||
output time. They are output after the current function. */
|
||||
struct deferred_plabel GTY(())
|
||||
@ -3292,8 +3298,8 @@ compute_frame_size (size, fregs_live)
|
||||
size += TARGET_64BIT ? 48 : 32;
|
||||
|
||||
/* Finally, round to the preferred stack boundary. */
|
||||
return ((size + PREFERRED_STACK_BOUNDARY / 8 - 1)
|
||||
& ~(PREFERRED_STACK_BOUNDARY / 8 - 1));
|
||||
return ((size + PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1)
|
||||
& ~(PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1));
|
||||
}
|
||||
|
||||
/* Generate the assembly code for function entry. FILE is a stdio
|
||||
@ -3681,6 +3687,30 @@ load_reg (reg, disp, base)
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the total code bytes output to the text section. */
|
||||
|
||||
static void
|
||||
update_total_code_bytes (nbytes)
|
||||
int nbytes;
|
||||
{
|
||||
if ((TARGET_PORTABLE_RUNTIME || !TARGET_GAS || !TARGET_SOM)
|
||||
&& in_text_section ())
|
||||
{
|
||||
if (INSN_ADDRESSES_SET_P ())
|
||||
{
|
||||
unsigned long old_total = total_code_bytes;
|
||||
|
||||
total_code_bytes += nbytes;
|
||||
|
||||
/* Be prepared to handle overflows. */
|
||||
if (old_total > total_code_bytes)
|
||||
total_code_bytes = -1;
|
||||
}
|
||||
else
|
||||
total_code_bytes = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function generates the assembly code for function exit.
|
||||
Args are as for output_function_prologue ().
|
||||
|
||||
@ -3694,9 +3724,10 @@ pa_output_function_epilogue (file, size)
|
||||
FILE *file;
|
||||
HOST_WIDE_INT size ATTRIBUTE_UNUSED;
|
||||
{
|
||||
int last_address = 0;
|
||||
rtx insn = get_last_insn ();
|
||||
|
||||
last_address = 0;
|
||||
|
||||
/* hppa_expand_epilogue does the dirty work now. We just need
|
||||
to output the assembler directives which denote the end
|
||||
of a function.
|
||||
@ -3724,29 +3755,18 @@ pa_output_function_epilogue (file, size)
|
||||
|
||||
fputs ("\t.EXIT\n\t.PROCEND\n", file);
|
||||
|
||||
/* Finally, update the total number of code bytes output so far. */
|
||||
if ((TARGET_PORTABLE_RUNTIME || !TARGET_GAS || !TARGET_SOM)
|
||||
&& !flag_function_sections)
|
||||
if (INSN_ADDRESSES_SET_P ())
|
||||
{
|
||||
if (INSN_ADDRESSES_SET_P ())
|
||||
{
|
||||
unsigned long old_total = total_code_bytes;
|
||||
|
||||
insn = get_last_nonnote_insn ();
|
||||
last_address += INSN_ADDRESSES (INSN_UID (insn));
|
||||
if (INSN_P (insn))
|
||||
last_address += insn_default_length (insn);
|
||||
|
||||
total_code_bytes += last_address;
|
||||
total_code_bytes += FUNCTION_BOUNDARY / BITS_PER_UNIT;
|
||||
|
||||
/* Be prepared to handle overflows. */
|
||||
if (old_total > total_code_bytes)
|
||||
total_code_bytes = -1;
|
||||
}
|
||||
else
|
||||
total_code_bytes = -1;
|
||||
insn = get_last_nonnote_insn ();
|
||||
last_address += INSN_ADDRESSES (INSN_UID (insn));
|
||||
if (INSN_P (insn))
|
||||
last_address += insn_default_length (insn);
|
||||
last_address = ((last_address + FUNCTION_BOUNDARY / BITS_PER_UNIT - 1)
|
||||
& ~(FUNCTION_BOUNDARY / BITS_PER_UNIT - 1));
|
||||
}
|
||||
|
||||
/* Finally, update the total number of code bytes output so far. */
|
||||
update_total_code_bytes (last_address);
|
||||
}
|
||||
|
||||
void
|
||||
@ -5904,7 +5924,13 @@ output_lbranch (dest, insn)
|
||||
output_asm_insn ("stw %%r1,-12(%%r30)", xoperands);
|
||||
}
|
||||
|
||||
if (flag_pic)
|
||||
if (TARGET_PORTABLE_RUNTIME)
|
||||
{
|
||||
output_asm_insn ("ldil L'%0,%%r1", xoperands);
|
||||
output_asm_insn ("ldo R'%0(%%r1),%%r1", xoperands);
|
||||
output_asm_insn ("bv %%r0(%%r1)", xoperands);
|
||||
}
|
||||
else if (flag_pic)
|
||||
{
|
||||
output_asm_insn ("{bl|b,l} .+8,%%r1", xoperands);
|
||||
if (TARGET_SOM || !TARGET_GAS)
|
||||
@ -6545,11 +6571,12 @@ attr_length_millicode_call (insn)
|
||||
rtx insn;
|
||||
{
|
||||
unsigned long distance = -1;
|
||||
unsigned long total = in_text_section () ? total_code_bytes : 0;
|
||||
|
||||
if (INSN_ADDRESSES_SET_P ())
|
||||
{
|
||||
distance = (total_code_bytes + insn_current_reference_address (insn));
|
||||
if (distance < total_code_bytes)
|
||||
distance = (total + insn_current_reference_address (insn));
|
||||
if (distance < total)
|
||||
distance = -1;
|
||||
}
|
||||
|
||||
@ -6741,11 +6768,12 @@ attr_length_call (insn, sibcall)
|
||||
int sibcall;
|
||||
{
|
||||
unsigned long distance = -1;
|
||||
unsigned long total = in_text_section ()? total_code_bytes : 0;
|
||||
|
||||
if (INSN_ADDRESSES_SET_P ())
|
||||
{
|
||||
distance = (total_code_bytes + insn_current_reference_address (insn));
|
||||
if (distance < total_code_bytes)
|
||||
distance = (total + insn_current_reference_address (insn));
|
||||
if (distance < total)
|
||||
distance = -1;
|
||||
}
|
||||
|
||||
@ -6813,12 +6841,15 @@ output_call (insn, call_dest, sibcall)
|
||||
int delay_insn_deleted = 0;
|
||||
int delay_slot_filled = 0;
|
||||
int seq_length = dbr_sequence_length ();
|
||||
tree call_decl = SYMBOL_REF_DECL (call_dest);
|
||||
int local_call = call_decl && !TREE_PUBLIC (call_decl);
|
||||
rtx xoperands[2];
|
||||
|
||||
xoperands[0] = call_dest;
|
||||
|
||||
/* Handle the common case where we're sure that the branch will reach
|
||||
the beginning of the $CODE$ subspace. */
|
||||
the beginning of the "$CODE$" subspace. This is the beginning of
|
||||
the current function if we are in a named section. */
|
||||
if (!TARGET_LONG_CALLS && attr_length_call (insn, sibcall) == 8)
|
||||
{
|
||||
xoperands[1] = gen_rtx_REG (word_mode, sibcall ? 0 : 2);
|
||||
@ -6826,7 +6857,7 @@ output_call (insn, call_dest, sibcall)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TARGET_64BIT)
|
||||
if (TARGET_64BIT && !local_call)
|
||||
{
|
||||
/* ??? As far as I can tell, the HP linker doesn't support the
|
||||
long pc-relative sequence described in the 64-bit runtime
|
||||
@ -6878,9 +6909,10 @@ output_call (insn, call_dest, sibcall)
|
||||
/* Emit a long call. There are several different sequences
|
||||
of increasing length and complexity. In most cases,
|
||||
they don't allow an instruction in the delay slot. */
|
||||
if (!(TARGET_LONG_ABS_CALL && !flag_pic)
|
||||
if (!((TARGET_LONG_ABS_CALL || local_call) && !flag_pic)
|
||||
&& !(TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
|
||||
&& !(TARGET_GAS && TARGET_LONG_PIC_PCREL_CALL))
|
||||
&& !(TARGET_GAS && (TARGET_LONG_PIC_PCREL_CALL || local_call))
|
||||
&& !TARGET_64BIT)
|
||||
indirect_call = 1;
|
||||
|
||||
if (seq_length != 0
|
||||
@ -6900,12 +6932,13 @@ output_call (insn, call_dest, sibcall)
|
||||
delay_insn_deleted = 1;
|
||||
}
|
||||
|
||||
if (TARGET_LONG_ABS_CALL && !flag_pic)
|
||||
if ((TARGET_LONG_ABS_CALL || local_call) && !flag_pic)
|
||||
{
|
||||
/* This is the best sequence for making long calls in
|
||||
non-pic code. Unfortunately, GNU ld doesn't provide
|
||||
the stub needed for external calls, and GAS's support
|
||||
for this with the SOM linker is buggy. */
|
||||
for this with the SOM linker is buggy. It is safe
|
||||
to use this for local calls. */
|
||||
output_asm_insn ("ldil L'%0,%%r1", xoperands);
|
||||
if (sibcall)
|
||||
output_asm_insn ("be R'%0(%%sr4,%%r1)", xoperands);
|
||||
@ -6923,7 +6956,8 @@ output_call (insn, call_dest, sibcall)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
|
||||
if ((TARGET_SOM && TARGET_LONG_PIC_SDIFF_CALL)
|
||||
|| (TARGET_64BIT && !TARGET_GAS))
|
||||
{
|
||||
/* The HP assembler and linker can handle relocations
|
||||
for the difference of two symbols. GAS and the HP
|
||||
@ -6936,7 +6970,7 @@ output_call (insn, call_dest, sibcall)
|
||||
CODE_LABEL_NUMBER (xoperands[1]));
|
||||
output_asm_insn ("ldo R'%0-%l1(%%r1),%%r1", xoperands);
|
||||
}
|
||||
else if (TARGET_GAS && TARGET_LONG_PIC_PCREL_CALL)
|
||||
else if (TARGET_GAS && (TARGET_LONG_PIC_PCREL_CALL || local_call))
|
||||
{
|
||||
/* GAS currently can't generate the relocations that
|
||||
are needed for the SOM linker under HP-UX using this
|
||||
@ -7075,11 +7109,9 @@ output_call (insn, call_dest, sibcall)
|
||||
CODE_LABEL_NUMBER (xoperands[1]));
|
||||
}
|
||||
else
|
||||
/* ??? This branch may not reach its target. */
|
||||
output_asm_insn ("nop\n\tb,n %0", xoperands);
|
||||
}
|
||||
else
|
||||
/* ??? This branch may not reach its target. */
|
||||
output_asm_insn ("b,n %0", xoperands);
|
||||
|
||||
/* Delete the jump. */
|
||||
@ -7101,11 +7133,12 @@ attr_length_indirect_call (insn)
|
||||
rtx insn;
|
||||
{
|
||||
unsigned long distance = -1;
|
||||
unsigned long total = in_text_section () ? total_code_bytes : 0;
|
||||
|
||||
if (INSN_ADDRESSES_SET_P ())
|
||||
{
|
||||
distance = (total_code_bytes + insn_current_reference_address (insn));
|
||||
if (distance < total_code_bytes)
|
||||
distance = (total + insn_current_reference_address (insn));
|
||||
if (distance < total)
|
||||
distance = -1;
|
||||
}
|
||||
|
||||
@ -7280,81 +7313,239 @@ pa_asm_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
|
||||
HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
|
||||
tree function;
|
||||
{
|
||||
const char *target_name = XSTR (XEXP (DECL_RTL (function), 0), 0);
|
||||
const char *fname = XSTR (XEXP (DECL_RTL (function), 0), 0);
|
||||
const char *tname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
|
||||
int val_14 = VAL_14_BITS_P (delta);
|
||||
int nbytes = 0;
|
||||
static unsigned int current_thunk_number;
|
||||
char label[16];
|
||||
const char *lab;
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "LTHN", current_thunk_number);
|
||||
lab = (*targetm.strip_name_encoding) (label);
|
||||
target_name = (*targetm.strip_name_encoding) (target_name);
|
||||
/* FIXME: total_code_bytes is not handled correctly in files with
|
||||
mi thunks. */
|
||||
pa_output_function_prologue (file, 0);
|
||||
if (VAL_14_BITS_P (delta))
|
||||
|
||||
ASM_OUTPUT_LABEL (file, tname);
|
||||
fprintf (file, "\t.PROC\n\t.CALLINFO FRAME=0,NO_CALLS\n\t.ENTRY\n");
|
||||
|
||||
fname = (*targetm.strip_name_encoding) (fname);
|
||||
tname = (*targetm.strip_name_encoding) (tname);
|
||||
|
||||
/* Output the thunk. We know that the function is in the same
|
||||
translation unit (i.e., the same space) as the thunk, and that
|
||||
thunks are output after their method. Thus, we don't need an
|
||||
external branch to reach the function. With SOM and GAS,
|
||||
functions and thunks are effectively in different sections.
|
||||
Thus, we can always use a IA-relative branch and the linker
|
||||
will add a long branch stub if necessary.
|
||||
|
||||
However, we have to be careful when generating PIC code on the
|
||||
SOM port to ensure that the sequence does not transfer to an
|
||||
import stub for the target function as this could clobber the
|
||||
return value saved at SP-24. This would also apply to the
|
||||
32-bit linux port if the multi-space model is implemented. */
|
||||
if ((!TARGET_LONG_CALLS && TARGET_SOM && !TARGET_PORTABLE_RUNTIME
|
||||
&& !(flag_pic && TREE_PUBLIC (function))
|
||||
&& (TARGET_GAS || last_address < 262132))
|
||||
|| (!TARGET_LONG_CALLS && !TARGET_SOM && !TARGET_PORTABLE_RUNTIME
|
||||
&& ((targetm.have_named_sections
|
||||
&& DECL_SECTION_NAME (thunk_fndecl) != NULL
|
||||
/* The GNU 64-bit linker has rather poor stub management.
|
||||
So, we use a long branch from thunks that aren't in
|
||||
the same section as the target function. */
|
||||
&& ((!TARGET_64BIT
|
||||
&& (DECL_SECTION_NAME (thunk_fndecl)
|
||||
!= DECL_SECTION_NAME (function)))
|
||||
|| ((DECL_SECTION_NAME (thunk_fndecl)
|
||||
== DECL_SECTION_NAME (function))
|
||||
&& last_address < 262132)))
|
||||
|| (!targetm.have_named_sections && last_address < 262132))))
|
||||
{
|
||||
if (!TARGET_64BIT && !TARGET_PORTABLE_RUNTIME && flag_pic)
|
||||
if (val_14)
|
||||
{
|
||||
fprintf (file, "\tb %s\n\tldo " HOST_WIDE_INT_PRINT_DEC
|
||||
"(%%r26),%%r26\n", fname, delta);
|
||||
nbytes += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (file, "\taddil L'" HOST_WIDE_INT_PRINT_DEC
|
||||
",%%r26\n", delta);
|
||||
fprintf (file, "\tb %s\n\tldo R'" HOST_WIDE_INT_PRINT_DEC
|
||||
"(%%r1),%%r26\n", fname, delta);
|
||||
nbytes += 12;
|
||||
}
|
||||
}
|
||||
else if (TARGET_64BIT)
|
||||
{
|
||||
/* We only have one call-clobbered scratch register, so we can't
|
||||
make use of the delay slot if delta doesn't fit in 14 bits. */
|
||||
if (!val_14)
|
||||
fprintf (file, "\taddil L'" HOST_WIDE_INT_PRINT_DEC
|
||||
",%%r26\n\tldo R'" HOST_WIDE_INT_PRINT_DEC
|
||||
"(%%r1),%%r26\n", delta, delta);
|
||||
|
||||
fprintf (file, "\tb,l .+8,%%r1\n");
|
||||
|
||||
if (TARGET_GAS)
|
||||
{
|
||||
fprintf (file, "\taddil L'%s-$PIC_pcrel$0+4,%%r1\n", fname);
|
||||
fprintf (file, "\tldo R'%s-$PIC_pcrel$0+8(%%r1),%%r1\n", fname);
|
||||
}
|
||||
else
|
||||
{
|
||||
int off = val_14 ? 8 : 16;
|
||||
fprintf (file, "\taddil L'%s-%s-%d,%%r1\n", fname, tname, off);
|
||||
fprintf (file, "\tldo R'%s-%s-%d(%%r1),%%r1\n", fname, tname, off);
|
||||
}
|
||||
|
||||
if (val_14)
|
||||
{
|
||||
fprintf (file, "\tbv %%r0(%%r1)\n\tldo ");
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%%r26),%%r26\n", delta);
|
||||
nbytes += 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (file, "\tbv,n %%r0(%%r1)\n");
|
||||
nbytes += 24;
|
||||
}
|
||||
}
|
||||
else if (TARGET_PORTABLE_RUNTIME)
|
||||
{
|
||||
fprintf (file, "\tldil L'%s,%%r1\n", fname);
|
||||
fprintf (file, "\tldo R'%s(%%r1),%%r22\n", fname);
|
||||
|
||||
if (val_14)
|
||||
{
|
||||
fprintf (file, "\tbv %%r0(%%r22)\n\tldo ");
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%%r26),%%r26\n", delta);
|
||||
nbytes += 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (file, "\taddil L'" HOST_WIDE_INT_PRINT_DEC
|
||||
",%%r26\n", delta);
|
||||
fprintf (file, "\tbv %%r0(%%r22)\n\tldo ");
|
||||
fprintf (file, "R'" HOST_WIDE_INT_PRINT_DEC "(%%r1),%%r26\n", delta);
|
||||
nbytes += 20;
|
||||
}
|
||||
}
|
||||
else if (TARGET_SOM && flag_pic && TREE_PUBLIC (function))
|
||||
{
|
||||
/* The function is accessible from outside this module. The only
|
||||
way to avoid an import stub between the thunk and function is to
|
||||
call the function directly with an indirect sequence similar to
|
||||
that used by $$dyncall. This is possible because $$dyncall acts
|
||||
as the import stub in an indirect call. */
|
||||
const char *lab;
|
||||
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "LTHN", current_thunk_number);
|
||||
lab = (*targetm.strip_name_encoding) (label);
|
||||
|
||||
fprintf (file, "\taddil LT'%s,%%r19\n", lab);
|
||||
fprintf (file, "\tldw RT'%s(%%r1),%%r22\n", lab);
|
||||
fprintf (file, "\tldw 0(%%sr0,%%r22),%%r22\n");
|
||||
fprintf (file, "\tbb,>=,n %%r22,30,.+16\n");
|
||||
fprintf (file, "\tdepi 0,31,2,%%r22\n");
|
||||
fprintf (file, "\tldw 4(%%sr0,%%r22),%%r19\n");
|
||||
fprintf (file, "\tldw 0(%%sr0,%%r22),%%r22\n");
|
||||
if (!val_14)
|
||||
{
|
||||
fprintf (file, "\taddil L'" HOST_WIDE_INT_PRINT_DEC
|
||||
",%%r26\n", delta);
|
||||
nbytes += 4;
|
||||
}
|
||||
if (TARGET_PA_20)
|
||||
{
|
||||
fprintf (file, "\tbve (%%r22)\n\tldo ");
|
||||
nbytes += 36;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (file, "\taddil LT'%s,%%r19\n", lab);
|
||||
fprintf (file, "\tldw RT'%s(%%r1),%%r22\n", lab);
|
||||
fprintf (file, "\tldw 0(%%sr0,%%r22),%%r22\n");
|
||||
fprintf (file, "\tbb,>=,n %%r22,30,.+16\n");
|
||||
fprintf (file, "\tdepi 0,31,2,%%r22\n");
|
||||
fprintf (file, "\tldw 4(%%sr0,%%r22),%%r19\n");
|
||||
fprintf (file, "\tldw 0(%%sr0,%%r22),%%r22\n");
|
||||
if (TARGET_NO_SPACE_REGS)
|
||||
fprintf (file, "\tbe 0(%%sr4,%%r22)\n\tldo ");
|
||||
{
|
||||
fprintf (file, "\tbe 0(%%sr4,%%r22)\n\tldo ");
|
||||
nbytes += 36;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (file, "\tldsid (%%sr0,%%r22),%%r1\n");
|
||||
fprintf (file, "\tmtsp %%r1,%%sr0\n");
|
||||
fprintf (file, "\tmtsp %%r21,%%sr0\n");
|
||||
fprintf (file, "\tbe 0(%%sr0,%%r22)\n\tldo ");
|
||||
nbytes += 44;
|
||||
}
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%%r26),%%r26\n", delta);
|
||||
}
|
||||
|
||||
if (val_14)
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%%r26),%%r26\n", delta);
|
||||
else
|
||||
fprintf (file, "R'" HOST_WIDE_INT_PRINT_DEC "(%%r1),%%r26\n", delta);
|
||||
}
|
||||
else if (flag_pic)
|
||||
{
|
||||
if (TARGET_PA_20)
|
||||
fprintf (file, "\tb,l .+8,%%r1\n");
|
||||
else
|
||||
fprintf (file, "\tbl .+8,%%r1\n");
|
||||
|
||||
if (TARGET_SOM || !TARGET_GAS)
|
||||
{
|
||||
fprintf (file, "\taddil L'%s-%s-8,%%r1\n", fname, tname);
|
||||
fprintf (file, "\tldo R'%s-%s-8(%%r1),%%r22\n", fname, tname);
|
||||
}
|
||||
else
|
||||
fprintf (file, "\tb %s\n\tldo " HOST_WIDE_INT_PRINT_DEC
|
||||
"(%%r26),%%r26\n",
|
||||
target_name, delta);
|
||||
{
|
||||
fprintf (file, "\taddil L'%s-$PIC_pcrel$0+4,%%r1\n", fname);
|
||||
fprintf (file, "\tldo R'%s-$PIC_pcrel$0+8(%%r1),%%r22\n", fname);
|
||||
}
|
||||
|
||||
if (val_14)
|
||||
{
|
||||
fprintf (file, "\tbv %%r0(%%r22)\n\tldo ");
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%%r26),%%r26\n", delta);
|
||||
nbytes += 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (file, "\taddil L'" HOST_WIDE_INT_PRINT_DEC
|
||||
",%%r26\n", delta);
|
||||
fprintf (file, "\tbv %%r0(%%r22)\n\tldo ");
|
||||
fprintf (file, "R'" HOST_WIDE_INT_PRINT_DEC "(%%r1),%%r26\n", delta);
|
||||
nbytes += 24;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!TARGET_64BIT && !TARGET_PORTABLE_RUNTIME && flag_pic)
|
||||
if (!val_14)
|
||||
fprintf (file, "\taddil L'" HOST_WIDE_INT_PRINT_DEC ",%%r26\n", delta);
|
||||
|
||||
fprintf (file, "\tldil L'%s,%%r22\n", fname);
|
||||
fprintf (file, "\tbe R'%s(%%sr4,%%r22)\n\tldo ", fname);
|
||||
|
||||
if (val_14)
|
||||
{
|
||||
fprintf (file, "\taddil L'" HOST_WIDE_INT_PRINT_DEC
|
||||
",%%r26\n\tldo R'" HOST_WIDE_INT_PRINT_DEC "(%%r1),%%r26\n",
|
||||
delta, delta);
|
||||
fprintf (file, "\taddil LT'%s,%%r19\n", lab);
|
||||
fprintf (file, "\tldw RT'%s(%%r1),%%r22\n", lab);
|
||||
fprintf (file, "\tldw 0(%%sr0,%%r22),%%r22\n");
|
||||
fprintf (file, "\tbb,>=,n %%r22,30,.+16\n");
|
||||
fprintf (file, "\tdepi 0,31,2,%%r22\n");
|
||||
fprintf (file, "\tldw 4(%%sr0,%%r22),%%r19\n");
|
||||
fprintf (file, "\tldw 0(%%sr0,%%r22),%%r22\n");
|
||||
if (TARGET_NO_SPACE_REGS)
|
||||
fprintf (file, "\tbe 0(%%sr4,%%r22)");
|
||||
else
|
||||
{
|
||||
fprintf (file, "\tldsid (%%sr0,%%r22),%%r1\n");
|
||||
fprintf (file, "\tmtsp %%r1,%%sr0\n");
|
||||
fprintf (file, "\tbe,n 0(%%sr0,%%r22)\n");
|
||||
}
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%%r26),%%r26\n", delta);
|
||||
nbytes += 12;
|
||||
}
|
||||
else
|
||||
fprintf (file, "\taddil L'" HOST_WIDE_INT_PRINT_DEC
|
||||
",%%r26\n\tb %s\n\tldo R'" HOST_WIDE_INT_PRINT_DEC
|
||||
"(%%r1),%%r26\n", delta, target_name, delta);
|
||||
{
|
||||
fprintf (file, "R'" HOST_WIDE_INT_PRINT_DEC "(%%r1),%%r26\n", delta);
|
||||
nbytes += 16;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fprintf (file, "\t.EXIT\n\t.PROCEND\n");
|
||||
if (! TARGET_64BIT && ! TARGET_PORTABLE_RUNTIME && flag_pic)
|
||||
|
||||
if (TARGET_SOM && flag_pic && TREE_PUBLIC (function))
|
||||
{
|
||||
data_section ();
|
||||
fprintf (file, "\t.align 4\n");
|
||||
(*targetm.asm_out.internal_label) (file, "LTHN", current_thunk_number);
|
||||
fprintf (file, "\t.word P'%s\n", target_name);
|
||||
ASM_OUTPUT_LABEL (file, label);
|
||||
fprintf (file, "\t.word P'%s\n", fname);
|
||||
function_section (thunk_fndecl);
|
||||
}
|
||||
|
||||
current_thunk_number++;
|
||||
nbytes = ((nbytes + FUNCTION_BOUNDARY / BITS_PER_UNIT - 1)
|
||||
& ~(FUNCTION_BOUNDARY / BITS_PER_UNIT - 1));
|
||||
last_address += nbytes;
|
||||
update_total_code_bytes (nbytes);
|
||||
}
|
||||
|
||||
/* Only direct calls to static functions are allowed to be sibling (tail)
|
||||
|
Loading…
Reference in New Issue
Block a user