about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ports/ChangeLog.tile7
-rw-r--r--ports/sysdeps/tile/crti.S23
-rw-r--r--ports/sysdeps/tile/start.S23
-rw-r--r--ports/sysdeps/tile/tilegx/Makefile18
4 files changed, 59 insertions, 12 deletions
diff --git a/ports/ChangeLog.tile b/ports/ChangeLog.tile
index 71aaf56db3..fd722b3e84 100644
--- a/ports/ChangeLog.tile
+++ b/ports/ChangeLog.tile
@@ -1,3 +1,10 @@
+2012-11-05  Chris Metcalf  <cmetcalf@tilera.com>
+
+	* sysdeps/tile/tilegx/Makefile: Generate Makefile fragment to determine
+	whether to build elf-init.c and gmon-start.c with -mcmodel=large.
+	* sysdeps/tile/crti.S: Support large memory model.
+	* sysdeps/tile/start.S: Likewise.
+
 2012-11-02  Chris Metcalf  <cmetcalf@tilera.com>
 
 	* sysdeps/tile/dl-runtime.c (_dl_after_load): Handle simulator
diff --git a/ports/sysdeps/tile/crti.S b/ports/sysdeps/tile/crti.S
index ccb4464bb7..467816c787 100644
--- a/ports/sysdeps/tile/crti.S
+++ b/ports/sysdeps/tile/crti.S
@@ -70,16 +70,17 @@ _init:
 #if PREINIT_FUNCTION_WEAK
 	lnk r2
 0:
-#ifdef __tilegx__
+# ifdef __tilegx__
+	moveli r1, hw2_last(_GLOBAL_OFFSET_TABLE_ - 0b)
 	{
-	 moveli r1, hw1_last(_GLOBAL_OFFSET_TABLE_ - 0b)
+	 shl16insli r1, r1, hw1(_GLOBAL_OFFSET_TABLE_ - 0b)
 	 moveli r0, hw1_last_got(PREINIT_FUNCTION)
 	}
 	{
 	 shl16insli r1, r1, hw0(_GLOBAL_OFFSET_TABLE_ - 0b)
 	 shl16insli r0, r0, hw0_got(PREINIT_FUNCTION)
 	}
-#else
+# else
 	{
 	 moveli r1, lo16(_GLOBAL_OFFSET_TABLE_ - 0b)
 	 moveli r0, got_lo16(PREINIT_FUNCTION)
@@ -88,13 +89,25 @@ _init:
 	 auli r1, r1, ha16(_GLOBAL_OFFSET_TABLE_ - 0b)
 	 auli r0, r0, got_ha16(PREINIT_FUNCTION)
 	}
-#endif
+# endif
 	ADD_PTR r0, r0, r1
 	ADD_PTR r0, r0, r2
 	LD_PTR r0, r0
 	BEQZ r0, .Lno_weak_fn
-#endif
+	jalr r0
+#elif defined(__tilegx__)
+	/* Since we are calling from the start of the object to the PLT,
+	   call by loading the full address into a register.  */
+	lnk r2
+0:
+	moveli r0, hw2_last_plt(PREINIT_FUNCTION - 0b)
+	shl16insli r0, r0, hw1_plt(PREINIT_FUNCTION - 0b)
+	shl16insli r0, r0, hw0_plt(PREINIT_FUNCTION - 0b)
+	add r0, r0, r2
+	jalr r0
+#else
 	jal plt(PREINIT_FUNCTION)
+#endif
 .Lno_weak_fn:
 
 	.section .fini,"ax",@progbits
diff --git a/ports/sysdeps/tile/start.S b/ports/sysdeps/tile/start.S
index 999bb535ca..54f015f4d0 100644
--- a/ports/sysdeps/tile/start.S
+++ b/ports/sysdeps/tile/start.S
@@ -126,27 +126,37 @@ _start:
 	 moveli r0, hw2_last(main - .Lmy_pc)
 	}
 	{
-	 moveli r3, hw2_last(__libc_csu_init - .Lmy_pc)
 	 shl16insli r0, r0, hw1(main - .Lmy_pc)
+	 moveli r3, hw2_last(__libc_csu_init - .Lmy_pc)
 	}
 	{
-	 shl16insli r3, r3, hw1(__libc_csu_init - .Lmy_pc)
 	 shl16insli r0, r0, hw0(main - .Lmy_pc)
+	 shl16insli r3, r3, hw1(__libc_csu_init - .Lmy_pc)
 	}
 	{
+	 ADD_PTR r0, r0, r13
 	 shl16insli r3, r3, hw0(__libc_csu_init - .Lmy_pc)
+	}
+	{
+	 moveli r12, hw2_last_plt(__libc_start_main - .Lmy_pc)
+	 ADD_PTR r3, r3, r13
+	}
+	{
+	 shl16insli r12, r12, hw1_plt(__libc_start_main - .Lmy_pc)
 	 moveli r4, hw2_last(__libc_csu_fini - .Lmy_pc)
 	}
 	{
-	 ADD_PTR r0, r0, r13
+	 shl16insli r12, r12, hw0_plt(__libc_start_main - .Lmy_pc)
 	 shl16insli r4, r4, hw1(__libc_csu_fini - .Lmy_pc)
 	}
 	{
-	 ADD_PTR r3, r3, r13
+	 ADD_PTR r12, r12, r13
 	 shl16insli r4, r4, hw0(__libc_csu_fini - .Lmy_pc)
 	}
 	{
 	 ADD_PTR r4, r4, r13
+	 jalr r12
+	}
 #else
 	 addli r0, r13, lo16(main - .Lmy_pc)
 	}
@@ -160,13 +170,12 @@ _start:
 	}
 	{
 	 auli r4, r4, ha16(__libc_csu_fini - .Lmy_pc)
-
-#endif
-
 	 /* Call the user's main function, and exit with its value.
 	    But let the libc call main. */
 	 j plt(__libc_start_main)
 	}
+#endif
+
 	{
 	 /* Tell backtracer to give up (_start has no caller). */
 	 info INFO_OP_CANNOT_BACKTRACE
diff --git a/ports/sysdeps/tile/tilegx/Makefile b/ports/sysdeps/tile/tilegx/Makefile
new file mode 100644
index 0000000000..d3a0e970a7
--- /dev/null
+++ b/ports/sysdeps/tile/tilegx/Makefile
@@ -0,0 +1,18 @@
+include $(common-objpfx)cflags-mcmodel-large.mk
+
+$(common-objpfx)cflags-mcmodel-large.mk: $(common-objpfx)config.make
+	mcmodel=no; \
+	$(CC) -S -o /dev/null -xc /dev/null -mcmodel=large && mcmodel=yes; \
+	echo "cflags-mcmodel-large = $$mcmodel" > $@
+
+ifeq ($(subdir),csu)
+ifeq (yes,$(cflags-mcmodel-large))
+# elf-init.c is in libc_nonshared.o (the end of the shared object) but
+# must reach the _init symbol at the very start of the shared object.
+CFLAGS-elf-init.c += -mcmodel=large
+
+# __gmon_start__ is at the very start of the shared object when linked
+# with profiling, but calls to libc.so via the PLT at the very end.
+CFLAGS-gmon-start.c += -mcmodel=large
+endif
+endif