From dbe287f54e69959859d1a5697aeab8cda328f749 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 8 Nov 2006 17:31:11 +0000 Subject: gcc/ * config/m68k/m68kelf.h (STATIC_CHAIN_REGNUM): Define. (M68K_STATIC_CHAIN_REG_NAME): New. * config/m68k/m68k.h (M68K_STATIC_CHAIN_REG_NAME): New. (INITIALIZE_TRAMPOLINE): Use STATIC_CHAIN_REGNUM. (__transfer_from_trampoline): Use M68K_STATIC_CHAIN_REG_NAME. * config/m68k/m68k.c (m68k_init_pic): New, broken out of ... (m68k_output_function_prologue): ... here. Use it. (m68k_output_mi_thunk): Initialize scratch PIC register if needed. Use STATIC_CHAIN_REGNUM & M68K_STATIC_CHAIN_REG_NAME. gcc/testsuite/ * gcc.c-torture/execute/nestfunc-7.c: New. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/csl/sourcerygxx-4_1@118592 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/config/m68k/m68k.c | 105 +++++++++++++---------- gcc/config/m68k/m68k.h | 6 +- gcc/config/m68k/m68kelf.h | 8 ++ gcc/testsuite/gcc.c-torture/execute/nestfunc-7.c | 44 ++++++++++ 4 files changed, 116 insertions(+), 47 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/nestfunc-7.c (limited to 'gcc') diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 95f6d81deee..6850c4e2bcd 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -861,6 +861,51 @@ m68k_save_reg (unsigned int regno, bool interrupt_handler) return !call_used_regs[regno]; } +/* Initialize PIC_REGNO as a PIC reg. */ + +static void +m68k_init_pic (FILE *stream, int pic_regno) +{ + if (TARGET_ID_SHARED_LIBRARY) + { + asm_fprintf (stream, "\tmovel %s@(%s), %s\n", + M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM), + m68k_library_id_string, + M68K_REGNAME(pic_regno)); + } + else + { + if (MOTOROLA) + { + if (m68k_arch_coldfire) + { + /* Load the full 32-bit PC-relative offset of + _GLOBAL_OFFSET_TABLE_ into the PIC register, then use + it to calculate the absolute value. The offset and + "lea" operation word together occupy 6 bytes. */ + asm_fprintf (stream, "\tmove.l %I%U%s@GOTPC, %s\n", + "_GLOBAL_OFFSET_TABLE_", + M68K_REGNAME(pic_regno)); + asm_fprintf (stream, "\tlea (-6, %Rpc, %s), %s\n", + M68K_REGNAME(pic_regno), + M68K_REGNAME(pic_regno)); + } + else + asm_fprintf (stream, "\t%Olea (%Rpc, %U%s@GOTPC), %s\n", + "_GLOBAL_OFFSET_TABLE_", + M68K_REGNAME(pic_regno)); + } + else + { + asm_fprintf (stream, "\tmovel %I%U_GLOBAL_OFFSET_TABLE_, %s\n", + M68K_REGNAME(pic_regno)); + asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n", + M68K_REGNAME(pic_regno), + M68K_REGNAME(pic_regno)); + } + } +} + /* This function generates the assembly code for function entry. STREAM is a stdio stream to output the code to. SIZE is an int: how many units of temporary storage to allocate. */ @@ -1100,47 +1145,7 @@ m68k_output_function_prologue (FILE *stream, HOST_WIDE_INT size ATTRIBUTE_UNUSED if (!TARGET_SEP_DATA && flag_pic && (current_function_uses_pic_offset_table || (!current_function_is_leaf && TARGET_ID_SHARED_LIBRARY))) - { - if (TARGET_ID_SHARED_LIBRARY) - { - asm_fprintf (stream, "\tmovel %s@(%s), %s\n", - M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM), - m68k_library_id_string, - M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM)); - } - else - { - if (MOTOROLA) - { - if (m68k_arch_coldfire) - { - /* Load the full 32-bit PC-relative offset of - _GLOBAL_OFFSET_TABLE_ into the PIC register, - then use it to calculate the absolute value. - The offset and "lea" operation word together - occupy 6 bytes. */ - asm_fprintf (stream, "\tmove.l %I%U%s@GOTPC, %s\n", - "_GLOBAL_OFFSET_TABLE_", - M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM)); - asm_fprintf (stream, "\tlea (-6, %Rpc, %s), %s\n", - M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM), - M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM)); - } - else - asm_fprintf (stream, "\t%Olea (%Rpc, %U%s@GOTPC), %s\n", - "_GLOBAL_OFFSET_TABLE_", - M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM)); - } - else - { - asm_fprintf (stream, "\tmovel %I%U_GLOBAL_OFFSET_TABLE_, %s\n", - M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM)); - asm_fprintf (stream, "\tlea %Rpc@(0,%s:l),%s\n", - M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM), - M68K_REGNAME(PIC_OFFSET_TABLE_REGNUM)); - } - } - } + m68k_init_pic (stream, PIC_OFFSET_TABLE_REGNUM); } /* Return true if this function's epilogue can be output as RTL. */ @@ -4087,10 +4092,20 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, fmt = m68k_symbolic_jump; if (m68k_symbolic_jump == NULL) - /* Thunks do not use the static chain register. Use it as a - temporary register here. */ - fmt = "move.l %a0@GOT(%%a5), %%a0\n\tjmp (%%a0)"; - + { + /* Thunks do not use the static chain register. Use it as a + temporary register here. */ + gcc_assert (flag_pic); + + m68k_init_pic (file, STATIC_CHAIN_REGNUM); + /* We provide REGISTER_PREFIX here, because it is either empty + or "%". When it's "%" we want "%%" in the format string. */ + fmt = "move.l" + " %a0@GOT(" REGISTER_PREFIX M68K_STATIC_CHAIN_REG_NAME ")," + " " REGISTER_PREFIX M68K_STATIC_CHAIN_REG_NAME "\n" + "\tjmp ( "REGISTER_PREFIX M68K_STATIC_CHAIN_REG_NAME ")"; + } + output_asm_insn (fmt, xops); } diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index b83a8722ba8..5b5c9a10df5 100644 --- a/gcc/config/m68k/m68k.h +++ b/gcc/config/m68k/m68k.h @@ -431,6 +431,7 @@ Boston, MA 02110-1301, USA. */ #define ARG_POINTER_REGNUM 24 #define STATIC_CHAIN_REGNUM 8 +#define M68K_STATIC_CHAIN_REG_NAME REGISTER_PREFIX "a0" /* Register in which address to store a structure value is passed to a function. */ @@ -670,7 +671,8 @@ extern enum reg_class regno_reg_class[]; jmp FNADDR */ #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ { \ - emit_move_insn (gen_rtx_MEM (HImode, TRAMP), GEN_INT(0x207C)); \ + emit_move_insn (gen_rtx_MEM (HImode, TRAMP), \ + GEN_INT(0x207C + ((STATIC_CHAIN_REGNUM-8) << 9))); \ emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 2)), CXT); \ emit_move_insn (gen_rtx_MEM (HImode, plus_constant (TRAMP, 6)), \ GEN_INT(0x4EF9)); \ @@ -693,7 +695,7 @@ extern enum reg_class regno_reg_class[]; void \ __transfer_from_trampoline () \ { \ - register char *a0 asm ("%a0"); \ + register char *a0 asm (M68K_STATIC_CHAIN_REG_NAME); \ asm (GLOBAL_ASM_OP "___trampoline"); \ asm ("___trampoline:"); \ asm volatile ("move%.l %0,%@" : : "m" (a0[22])); \ diff --git a/gcc/config/m68k/m68kelf.h b/gcc/config/m68k/m68kelf.h index b2b7f4ba589..f657ca43447 100644 --- a/gcc/config/m68k/m68kelf.h +++ b/gcc/config/m68k/m68kelf.h @@ -111,6 +111,14 @@ do { \ #undef M68K_STRUCT_VALUE_REGNUM #define M68K_STRUCT_VALUE_REGNUM 8 +/* The static chain regnum defaults to a0, but we use that for + structure return, so have to use a1 for the static chain. */ + +#undef STATIC_CHAIN_REGNUM +#define STATIC_CHAIN_REGNUM 9 +#undef M68K_STATIC_CHAIN_REG_NAME +#define M68K_STATIC_CHAIN_REG_NAME REGISTER_PREFIX "a1" + #define ASM_COMMENT_START "|" /* Define how the m68k registers should be numbered for Dwarf output. diff --git a/gcc/testsuite/gcc.c-torture/execute/nestfunc-7.c b/gcc/testsuite/gcc.c-torture/execute/nestfunc-7.c new file mode 100644 index 00000000000..04b0cb8dedd --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/nestfunc-7.c @@ -0,0 +1,44 @@ +struct A +{ + int one; + int two; + int three; + int four; + int five; + int six; +}; + +static int test (void) +{ + int base; + + struct A Foo (void) + { + struct A a; + + a.one = base + 1; + a.two = base + 2; + a.three = base + 3; + a.four = base + 4; + a.five = base + 5; + a.six = base + 6; + + return a; + } + + base = 10; + struct A a = Foo (); + + return (a.one == 11 + && a.two == 12 + && a.three == 13 + && a.four == 14 + && a.five == 15 + && a.six == 16); +} + +int main (void) +{ + return !test (); +} + -- cgit v1.2.3