diff options
Diffstat (limited to 'ports')
-rw-r--r-- | ports/ChangeLog.tile | 7 | ||||
-rw-r--r-- | ports/sysdeps/tile/crti.S | 23 | ||||
-rw-r--r-- | ports/sysdeps/tile/start.S | 23 | ||||
-rw-r--r-- | ports/sysdeps/tile/tilegx/Makefile | 18 |
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 |