Commit 859c146c by Richard Henderson Committed by Richard Henderson

pa.c (TARGET_ASM_TRAMPOLINE_TEMPLATE, [...]): New.

        * gcc/config/pa/pa.c (TARGET_ASM_TRAMPOLINE_TEMPLATE,
        pa_asm_trampoline_template, TARGET_TRAMPOLINE_INIT,
        pa_trampoline_init, TARGET_TRAMPOLINE_ADJUST_ADDRESS,
        pa_trampoline_adjust_address): New.
        * config/pa/pa.h (TRAMPOLINE_TEMPLATE): Move code to
        pa_asm_trampoline_template.
        (TRAMPOLINE_ALIGNMENT): New.
        (TRAMPOLINE_CODE_SIZE): Move to pa.c.
        (INITIALIZE_TRAMPOLINE): Move code to pa_trampoline_init;
        adjust for hook parameters.
        (TRAMPOLINE_ADJUST_ADDRESS): Move code to pa_trampoline_adjust_address.

From-SVN: r152005
parent 4601494d
......@@ -192,6 +192,18 @@
(TRAMPOLINE_TEMPLATE): Move code to moxie_asm_trampoline_template.
(STATIC_CHAIN, STATIC_CHAIN_INCOMING): Remove.
* gcc/config/pa/pa.c (TARGET_ASM_TRAMPOLINE_TEMPLATE,
pa_asm_trampoline_template, TARGET_TRAMPOLINE_INIT,
pa_trampoline_init, TARGET_TRAMPOLINE_ADJUST_ADDRESS,
pa_trampoline_adjust_address): New.
* config/pa/pa.h (TRAMPOLINE_TEMPLATE): Move code to
pa_asm_trampoline_template.
(TRAMPOLINE_ALIGNMENT): New.
(TRAMPOLINE_CODE_SIZE): Move to pa.c.
(INITIALIZE_TRAMPOLINE): Move code to pa_trampoline_init;
adjust for hook parameters.
(TRAMPOLINE_ADJUST_ADDRESS): Move code to pa_trampoline_adjust_address.
2009-09-22 Jakub Jelinek <jakub@redhat.com>
* config/rs6000/rs6000.c (bdesc_2arg): Fix CODE_FOR_vector_gt* codes
......
......@@ -163,6 +163,10 @@ static enum machine_mode pa_promote_function_mode (const_tree,
enum machine_mode, int *,
const_tree, int);
static void pa_asm_trampoline_template (FILE *);
static void pa_trampoline_init (rtx, tree, rtx);
static rtx pa_trampoline_adjust_address (rtx);
/* The following extra sections are only used for SOM. */
static GTY(()) section *som_readonly_data_section;
static GTY(()) section *som_one_only_readonly_data_section;
......@@ -325,6 +329,13 @@ static size_t n_deferred_plabels = 0;
#undef TARGET_EXTRA_LIVE_ON_ENTRY
#define TARGET_EXTRA_LIVE_ON_ENTRY pa_extra_live_on_entry
#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
#define TARGET_ASM_TRAMPOLINE_TEMPLATE pa_asm_trampoline_template
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT pa_trampoline_init
#undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
#define TARGET_TRAMPOLINE_ADJUST_ADDRESS pa_trampoline_adjust_address
struct gcc_target targetm = TARGET_INITIALIZER;
/* Parse the -mfixed-range= option string. */
......@@ -9808,4 +9819,174 @@ pa_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
return true;
}
/* Length in units of the trampoline instruction code. */
#define TRAMPOLINE_CODE_SIZE (TARGET_64BIT ? 24 : (TARGET_PA_20 ? 32 : 40))
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts.\
The trampoline sets the static chain pointer to STATIC_CHAIN_REGNUM
and then branches to the specified routine.
This code template is copied from text segment to stack location
and then patched with pa_trampoline_init to contain valid values,
and then entered as a subroutine.
It is best to keep this as small as possible to avoid having to
flush multiple lines in the cache. */
static void
pa_asm_trampoline_template (FILE *f)
{
if (!TARGET_64BIT)
{
fputs ("\tldw 36(%r22),%r21\n", f);
fputs ("\tbb,>=,n %r21,30,.+16\n", f);
if (ASSEMBLER_DIALECT == 0)
fputs ("\tdepi 0,31,2,%r21\n", f);
else
fputs ("\tdepwi 0,31,2,%r21\n", f);
fputs ("\tldw 4(%r21),%r19\n", f);
fputs ("\tldw 0(%r21),%r21\n", f);
if (TARGET_PA_20)
{
fputs ("\tbve (%r21)\n", f);
fputs ("\tldw 40(%r22),%r29\n", f);
fputs ("\t.word 0\n", f);
fputs ("\t.word 0\n", f);
}
else
{
fputs ("\tldsid (%r21),%r1\n", f);
fputs ("\tmtsp %r1,%sr0\n", f);
fputs ("\tbe 0(%sr0,%r21)\n", f);
fputs ("\tldw 40(%r22),%r29\n", f);
}
fputs ("\t.word 0\n", f);
fputs ("\t.word 0\n", f);
fputs ("\t.word 0\n", f);
fputs ("\t.word 0\n", f);
}
else
{
fputs ("\t.dword 0\n", f);
fputs ("\t.dword 0\n", f);
fputs ("\t.dword 0\n", f);
fputs ("\t.dword 0\n", f);
fputs ("\tmfia %r31\n", f);
fputs ("\tldd 24(%r31),%r1\n", f);
fputs ("\tldd 24(%r1),%r27\n", f);
fputs ("\tldd 16(%r1),%r1\n", f);
fputs ("\tbve (%r1)\n", f);
fputs ("\tldd 32(%r31),%r31\n", f);
fputs ("\t.dword 0 ; fptr\n", f);
fputs ("\t.dword 0 ; static link\n", f);
}
}
/* Emit RTL insns to initialize the variable parts of a trampoline.
FNADDR is an RTX for the address of the function's pure code.
CXT is an RTX for the static chain value for the function.
Move the function address to the trampoline template at offset 36.
Move the static chain value to trampoline template at offset 40.
Move the trampoline address to trampoline template at offset 44.
Move r19 to trampoline template at offset 48. The latter two
words create a plabel for the indirect call to the trampoline.
A similar sequence is used for the 64-bit port but the plabel is
at the beginning of the trampoline.
Finally, the cache entries for the trampoline code are flushed.
This is necessary to ensure that the trampoline instruction sequence
is written to memory prior to any attempts at prefetching the code
sequence. */
static void
pa_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
{
rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
rtx start_addr = gen_reg_rtx (Pmode);
rtx end_addr = gen_reg_rtx (Pmode);
rtx line_length = gen_reg_rtx (Pmode);
rtx r_tramp, tmp;
emit_block_move (m_tramp, assemble_trampoline_template (),
GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
r_tramp = force_reg (Pmode, XEXP (m_tramp, 0));
if (!TARGET_64BIT)
{
tmp = adjust_address (m_tramp, Pmode, 36);
emit_move_insn (tmp, fnaddr);
tmp = adjust_address (m_tramp, Pmode, 40);
emit_move_insn (tmp, chain_value);
/* Create a fat pointer for the trampoline. */
tmp = adjust_address (m_tramp, Pmode, 44);
emit_move_insn (tmp, r_tramp);
tmp = adjust_address (m_tramp, Pmode, 48);
emit_move_insn (tmp, gen_rtx_REG (Pmode, 19));
/* fdc and fic only use registers for the address to flush,
they do not accept integer displacements. We align the
start and end addresses to the beginning of their respective
cache lines to minimize the number of lines flushed. */
emit_insn (gen_andsi3 (start_addr, r_tramp,
GEN_INT (-MIN_CACHELINE_SIZE)));
tmp = force_reg (Pmode, plus_constant (r_tramp, TRAMPOLINE_CODE_SIZE-1));
emit_insn (gen_andsi3 (end_addr, tmp,
GEN_INT (-MIN_CACHELINE_SIZE)));
emit_move_insn (line_length, GEN_INT (MIN_CACHELINE_SIZE));
emit_insn (gen_dcacheflushsi (start_addr, end_addr, line_length));
emit_insn (gen_icacheflushsi (start_addr, end_addr, line_length,
gen_reg_rtx (Pmode),
gen_reg_rtx (Pmode)));
}
else
{
tmp = adjust_address (m_tramp, Pmode, 56);
emit_move_insn (tmp, fnaddr);
tmp = adjust_address (m_tramp, Pmode, 64);
emit_move_insn (tmp, chain_value);
/* Create a fat pointer for the trampoline. */
tmp = adjust_address (m_tramp, Pmode, 16);
emit_move_insn (tmp, force_reg (Pmode, plus_constant (r_tramp, 32)));
tmp = adjust_address (m_tramp, Pmode, 24);
emit_move_insn (tmp, gen_rtx_REG (Pmode, 27));
/* fdc and fic only use registers for the address to flush,
they do not accept integer displacements. We align the
start and end addresses to the beginning of their respective
cache lines to minimize the number of lines flushed. */
tmp = force_reg (Pmode, plus_constant (r_tramp, 32));
emit_insn (gen_anddi3 (start_addr, tmp,
GEN_INT (-MIN_CACHELINE_SIZE)));
tmp = force_reg (Pmode, plus_constant (tmp, TRAMPOLINE_CODE_SIZE - 1));
emit_insn (gen_anddi3 (end_addr, tmp,
GEN_INT (-MIN_CACHELINE_SIZE)));
emit_move_insn (line_length, GEN_INT (MIN_CACHELINE_SIZE));
emit_insn (gen_dcacheflushdi (start_addr, end_addr, line_length));
emit_insn (gen_icacheflushdi (start_addr, end_addr, line_length,
gen_reg_rtx (Pmode),
gen_reg_rtx (Pmode)));
}
}
/* Perform any machine-specific adjustment in the address of the trampoline.
ADDR contains the address that was passed to pa_trampoline_init.
Adjust the trampoline address to point to the plabel at offset 44. */
static rtx
pa_trampoline_adjust_address (rtx addr)
{
if (!TARGET_64BIT)
addr = memory_address (Pmode, plus_constant (addr, 46));
return addr;
}
#include "gt-pa.h"
......@@ -778,74 +778,13 @@ extern int may_call_alloca;
(get_frame_size () != 0 \
|| cfun->calls_alloca || crtl->outgoing_args_size)
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts.\
The trampoline sets the static chain pointer to STATIC_CHAIN_REGNUM
and then branches to the specified routine.
This code template is copied from text segment to stack location
and then patched with INITIALIZE_TRAMPOLINE to contain
valid values, and then entered as a subroutine.
It is best to keep this as small as possible to avoid having to
flush multiple lines in the cache. */
#define TRAMPOLINE_TEMPLATE(FILE) \
{ \
if (!TARGET_64BIT) \
{ \
fputs ("\tldw 36(%r22),%r21\n", FILE); \
fputs ("\tbb,>=,n %r21,30,.+16\n", FILE); \
if (ASSEMBLER_DIALECT == 0) \
fputs ("\tdepi 0,31,2,%r21\n", FILE); \
else \
fputs ("\tdepwi 0,31,2,%r21\n", FILE); \
fputs ("\tldw 4(%r21),%r19\n", FILE); \
fputs ("\tldw 0(%r21),%r21\n", FILE); \
if (TARGET_PA_20) \
{ \
fputs ("\tbve (%r21)\n", FILE); \
fputs ("\tldw 40(%r22),%r29\n", FILE); \
fputs ("\t.word 0\n", FILE); \
fputs ("\t.word 0\n", FILE); \
} \
else \
{ \
fputs ("\tldsid (%r21),%r1\n", FILE); \
fputs ("\tmtsp %r1,%sr0\n", FILE); \
fputs ("\tbe 0(%sr0,%r21)\n", FILE); \
fputs ("\tldw 40(%r22),%r29\n", FILE); \
} \
fputs ("\t.word 0\n", FILE); \
fputs ("\t.word 0\n", FILE); \
fputs ("\t.word 0\n", FILE); \
fputs ("\t.word 0\n", FILE); \
} \
else \
{ \
fputs ("\t.dword 0\n", FILE); \
fputs ("\t.dword 0\n", FILE); \
fputs ("\t.dword 0\n", FILE); \
fputs ("\t.dword 0\n", FILE); \
fputs ("\tmfia %r31\n", FILE); \
fputs ("\tldd 24(%r31),%r1\n", FILE); \
fputs ("\tldd 24(%r1),%r27\n", FILE); \
fputs ("\tldd 16(%r1),%r1\n", FILE); \
fputs ("\tbve (%r1)\n", FILE); \
fputs ("\tldd 32(%r31),%r31\n", FILE); \
fputs ("\t.dword 0 ; fptr\n", FILE); \
fputs ("\t.dword 0 ; static link\n", FILE); \
} \
}
/* Length in units of the trampoline for entering a nested function. */
#define TRAMPOLINE_SIZE (TARGET_64BIT ? 72 : 52)
/* Length in units of the trampoline instruction code. */
/* Alignment required by the trampoline. */
#define TRAMPOLINE_CODE_SIZE (TARGET_64BIT ? 24 : (TARGET_PA_20 ? 32 : 40))
#define TRAMPOLINE_ALIGNMENT BITS_PER_WORD
/* Minimum length of a cache line. A length of 16 will work on all
PA-RISC processors. All PA 1.1 processors have a cache line of
......@@ -855,102 +794,6 @@ extern int may_call_alloca;
#define MIN_CACHELINE_SIZE 32
/* Emit RTL insns to initialize the variable parts of a trampoline.
FNADDR is an RTX for the address of the function's pure code.
CXT is an RTX for the static chain value for the function.
Move the function address to the trampoline template at offset 36.
Move the static chain value to trampoline template at offset 40.
Move the trampoline address to trampoline template at offset 44.
Move r19 to trampoline template at offset 48. The latter two
words create a plabel for the indirect call to the trampoline.
A similar sequence is used for the 64-bit port but the plabel is
at the beginning of the trampoline.
Finally, the cache entries for the trampoline code are flushed.
This is necessary to ensure that the trampoline instruction sequence
is written to memory prior to any attempts at prefetching the code
sequence. */
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
{ \
rtx start_addr = gen_reg_rtx (Pmode); \
rtx end_addr = gen_reg_rtx (Pmode); \
rtx line_length = gen_reg_rtx (Pmode); \
rtx tmp; \
\
if (!TARGET_64BIT) \
{ \
tmp = memory_address (Pmode, plus_constant ((TRAMP), 36)); \
emit_move_insn (gen_rtx_MEM (Pmode, tmp), (FNADDR)); \
tmp = memory_address (Pmode, plus_constant ((TRAMP), 40)); \
emit_move_insn (gen_rtx_MEM (Pmode, tmp), (CXT)); \
\
/* Create a fat pointer for the trampoline. */ \
tmp = memory_address (Pmode, plus_constant ((TRAMP), 44)); \
emit_move_insn (gen_rtx_MEM (Pmode, tmp), (TRAMP)); \
tmp = memory_address (Pmode, plus_constant ((TRAMP), 48)); \
emit_move_insn (gen_rtx_MEM (Pmode, tmp), \
gen_rtx_REG (Pmode, 19)); \
\
/* fdc and fic only use registers for the address to flush, \
they do not accept integer displacements. We align the \
start and end addresses to the beginning of their respective \
cache lines to minimize the number of lines flushed. */ \
tmp = force_reg (Pmode, (TRAMP)); \
emit_insn (gen_andsi3 (start_addr, tmp, \
GEN_INT (-MIN_CACHELINE_SIZE))); \
tmp = force_reg (Pmode, \
plus_constant (tmp, TRAMPOLINE_CODE_SIZE - 1)); \
emit_insn (gen_andsi3 (end_addr, tmp, \
GEN_INT (-MIN_CACHELINE_SIZE))); \
emit_move_insn (line_length, GEN_INT (MIN_CACHELINE_SIZE)); \
emit_insn (gen_dcacheflushsi (start_addr, end_addr, line_length));\
emit_insn (gen_icacheflushsi (start_addr, end_addr, line_length, \
gen_reg_rtx (Pmode), \
gen_reg_rtx (Pmode))); \
} \
else \
{ \
tmp = memory_address (Pmode, plus_constant ((TRAMP), 56)); \
emit_move_insn (gen_rtx_MEM (Pmode, tmp), (FNADDR)); \
tmp = memory_address (Pmode, plus_constant ((TRAMP), 64)); \
emit_move_insn (gen_rtx_MEM (Pmode, tmp), (CXT)); \
\
/* Create a fat pointer for the trampoline. */ \
tmp = memory_address (Pmode, plus_constant ((TRAMP), 16)); \
emit_move_insn (gen_rtx_MEM (Pmode, tmp), \
force_reg (Pmode, plus_constant ((TRAMP), 32))); \
tmp = memory_address (Pmode, plus_constant ((TRAMP), 24)); \
emit_move_insn (gen_rtx_MEM (Pmode, tmp), \
gen_rtx_REG (Pmode, 27)); \
\
/* fdc and fic only use registers for the address to flush, \
they do not accept integer displacements. We align the \
start and end addresses to the beginning of their respective \
cache lines to minimize the number of lines flushed. */ \
tmp = force_reg (Pmode, plus_constant ((TRAMP), 32)); \
emit_insn (gen_anddi3 (start_addr, tmp, \
GEN_INT (-MIN_CACHELINE_SIZE))); \
tmp = force_reg (Pmode, \
plus_constant (tmp, TRAMPOLINE_CODE_SIZE - 1)); \
emit_insn (gen_anddi3 (end_addr, tmp, \
GEN_INT (-MIN_CACHELINE_SIZE))); \
emit_move_insn (line_length, GEN_INT (MIN_CACHELINE_SIZE)); \
emit_insn (gen_dcacheflushdi (start_addr, end_addr, line_length));\
emit_insn (gen_icacheflushdi (start_addr, end_addr, line_length, \
gen_reg_rtx (Pmode), \
gen_reg_rtx (Pmode))); \
} \
}
/* Perform any machine-specific adjustment in the address of the trampoline.
ADDR contains the address that was passed to INITIALIZE_TRAMPOLINE.
Adjust the trampoline address to point to the plabel at offset 44. */
#define TRAMPOLINE_ADJUST_ADDRESS(ADDR) \
if (!TARGET_64BIT) (ADDR) = memory_address (Pmode, plus_constant ((ADDR), 46))
/* Addressing modes, and classification of registers for them.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment