Index: uspace/lib/c/arch/ia64/include/libarch/thread.h
===================================================================
--- uspace/lib/c/arch/ia64/include/libarch/thread.h	(revision c21d4d64870698b91707f203def6398db79bff84)
+++ uspace/lib/c/arch/ia64/include/libarch/thread.h	(revision 09f41d3d60ae4abb40aff09edace1ef60c15b484)
@@ -36,4 +36,18 @@
 #define _LIBC_ia64_THREAD_H_
 
+#include <align.h>
+
+static inline uintptr_t arch_thread_prepare(void *stack, size_t stack_size,
+    void (*main)(void *), void *arg)
+{
+	uintptr_t *sp = (uintptr_t *) (ALIGN_DOWN((uintptr_t) stack + stack_size / 2, 16));
+
+	/* Store data under stack pointer */
+	sp[-1] = (uintptr_t) arg;
+	sp[-2] = (uintptr_t) main;
+
+	return (uintptr_t) sp;
+}
+
 #endif
 
Index: uspace/lib/c/arch/ia64/src/thread_entry.S
===================================================================
--- uspace/lib/c/arch/ia64/src/thread_entry.S	(revision c21d4d64870698b91707f203def6398db79bff84)
+++ uspace/lib/c/arch/ia64/src/thread_entry.S	(revision 09f41d3d60ae4abb40aff09edace1ef60c15b484)
@@ -37,16 +37,18 @@
 	alloc loc0 = ar.pfs, 0, 1, 1, 0
 
-#ifndef CONFIG_RTLD
-	# XXX This does not work in a shared library
-	movl gp = __gp
-#endif
+	add r8 = -8, sp ;;
+	# Entry function argument
+	ld8 out0 = [r8], -8 ;;
 
-	#
-	# r8 contains address of uarg structure.
-	#
+	# Entry function descriptor
+	ld8 r8 = [r8] ;;
+	# Entry function address
+	ld8 r9 = [r8], 8 ;;
+	# Entry function global pointer
+	ld8 gp = [r8] ;;
 
-	mov out0 = r8 ;;
-	# XXX br.call.sptk.many b0 = FUNCTION_REF(__thread_main)
-	br.call.sptk.many b0 = __thread_main
+	mov b1 = r9 ;;
+
+	br.call.sptk.many b0 = b1 ;;
 
 	#
