- 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))
- {
- if (!TARGET_64BIT && !TARGET_PORTABLE_RUNTIME && flag_pic)
- {
- 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");
+
+ 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 (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
+ {