aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2006-11-08 17:31:11 +0000
committerNathan Sidwell <nathan@codesourcery.com>2006-11-08 17:31:11 +0000
commitdbe287f54e69959859d1a5697aeab8cda328f749 (patch)
tree4f7c05cf77fb6c67a0b4a225941a8f178eedefb4
parent1ccc976ae378941ec25231c6bcefa793f7f41ee2 (diff)
* 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
-rw-r--r--ChangeLog.csl14
-rw-r--r--gcc/config/m68k/m68k.c105
-rw-r--r--gcc/config/m68k/m68k.h6
-rw-r--r--gcc/config/m68k/m68kelf.h8
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/nestfunc-7.c44
5 files changed, 130 insertions, 47 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index e6287c021a1..4c94cc63ca0 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,6 +1,20 @@
2006-11-08 Nathan Sidwell <nathan@codesourcery.com>
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.
+
+ gcc/
* config/m68k/coff.h (REGISTER_PREFIX_MD): Remove.
* config/m68k/m68kelf.h (REGISTER_PREFIX_MD): Remove.
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 ();
+}
+