From e78a0f58f23347c822c182d1c01f6eb9b9866d60 Mon Sep 17 00:00:00 2001
From: Max Filippov <jcmvbkbc@gmail.com>
Date: Wed, 16 Sep 2015 01:49:49 +0300
Subject: xtensa: support call0 ABI

Most changes are mechanical replacement of 'retw' instruction with
'abi_ret' macro, defined to 'retw' or 'ret' according to ABI.
Assembly code that makes calls is duplicated for call0 ABI with changed
register numbers for parameters/return value and call instruction.
'entry' instructions are replaced with 'abi_entry' macro.

More interesting changes:
- non-leaf assembly functions (e.g. _dl_tlsdesc_dynamic,
  _dl_linux_resolve, SYSCALL_ERROR_HANDLER, PSEUDO) now need to preserve
  registers around intermediate calls they make, use temporary stack
  frame for that;
- setjmp/longjmp only need to save and restore return address, stack
  pointer and callee-saved registers in the jmpbuf;
- __clone and syscall functions had hardcoded offsets to parameter
  passed on stack, on call0 ABI they don't need stack frame, so the
  offset is different. Replace these offsets with FRAMESIZE macro.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 ldso/ldso/xtensa/dl-startup.h | 12 ++++++++++++
 ldso/ldso/xtensa/dl-tlsdesc.S | 45 ++++++++++++++++++++++++-------------------
 ldso/ldso/xtensa/resolve.S    | 35 +++++++++++++++++++++++++++++++++
 3 files changed, 72 insertions(+), 20 deletions(-)

(limited to 'ldso')

diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h
index 8fe54a3c7..aece0cd96 100644
--- a/ldso/ldso/xtensa/dl-startup.h
+++ b/ldso/ldso/xtensa/dl-startup.h
@@ -23,6 +23,7 @@ __asm__ (
     "	.align  4\n"
     "0:	movi    a3, _start+3\n"
     "	sub     a2, a0, a3\n"
+#if defined(__XTENSA_WINDOWED_ABI__)
     "	# Make sure a0 is cleared to mark the top of stack.\n"
     "	movi    a0, 0\n"
     "	# user_entry_point = _dl_start(pointer to argument block)\n"
@@ -32,6 +33,17 @@ __asm__ (
     "	callx4  a4\n"
     "	# Save user_entry_point so we can jump to it.\n"
     "	mov     a3, a6\n"
+#elif defined(__XTENSA_CALL0_ABI__)
+    "	# user_entry_point = _dl_start(pointer to argument block)\n"
+    "	movi    a0, _dl_start\n"
+    "	add     a0, a0, a2\n"
+    "	mov     a2, sp\n"
+    "	callx0  a0\n"
+    "	# Save user_entry_point so we can jump to it.\n"
+    "	mov     a3, a2\n"
+#else
+#error Unsupported Xtensa ABI
+#endif
     "	l32i    a7, sp, 0   # load argc\n"
     "	# Load _dl_skip_args into a4.\n"
     "	movi    a4, _dl_skip_args\n"
diff --git a/ldso/ldso/xtensa/dl-tlsdesc.S b/ldso/ldso/xtensa/dl-tlsdesc.S
index 0638af439..6f417f61a 100644
--- a/ldso/ldso/xtensa/dl-tlsdesc.S
+++ b/ldso/ldso/xtensa/dl-tlsdesc.S
@@ -23,16 +23,11 @@
 #include "tlsdesc.h"
 
 	.text
-	.align 4
-	.hidden _dl_tlsdesc_return
-	.global	_dl_tlsdesc_return
-	.type	_dl_tlsdesc_return, @function
-_dl_tlsdesc_return:
-	entry	a1, 16
+HIDDEN_ENTRY (_dl_tlsdesc_return)
 	rur.threadptr	a3
 	add		a2, a2, a3
-	retw
-	.size	_dl_tlsdesc_return, .-_dl_tlsdesc_return
+	abi_ret
+END (_dl_tlsdesc_return)
 
 #ifdef SHARED
 
@@ -57,12 +52,7 @@ _dl_tlsdesc_return:
 	   }
 	 */
 
-	.align 4
-	.hidden _dl_tlsdesc_dynamic
-	.global	_dl_tlsdesc_dynamic
-	.type	_dl_tlsdesc_dynamic, @function
-_dl_tlsdesc_dynamic:
-	entry	a1, 32
+HIDDEN_ENTRY (_dl_tlsdesc_dynamic)
 
 	/* dtv_t *dtv = (dtv_t *)THREAD_DTV(); */
 	rur.threadptr	a3
@@ -83,16 +73,31 @@ _dl_tlsdesc_dynamic:
 	     + td->tlsinfo.ti_offset - __builtin_thread_pointer(); */
 	l32i	a6, a2, TLSDESC_MODOFF
 	sub	a2, a6, a3
-	retw
+	abi_ret
 
 	/* return __tls_get_addr (&td->tlsinfo) - __builtin_thread_pointer(); */
 .Lslow:
-	mov	a10, a2
-	movi	a8, __tls_get_addr
-	callx8	a8
-	sub	a2, a10, a3
+#if defined(__XTENSA_WINDOWED_ABI__)
+	mov	a6, a2
+	movi	a4, __tls_get_addr
+	callx4	a4
+	sub	a2, a6, a3
 	retw
-	.size	_dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic
+#elif defined(__XTENSA_CALL0_ABI__)
+	addi	a1, a1, -16
+	s32i	a0, a1, 0
+	s32i	a3, a1, 4
+	movi	a0, __tls_get_addr
+	callx0	a0
+	l32i	a3, a1, 4
+	l32i	a0, a1, 0
+	sub	a2, a2, a3
+	addi	a1, a1, 16
+	ret
+#else
+#error Unsupported Xtensa ABI
+#endif
+END (_dl_tlsdesc_dynamic)
 
 #endif /* SHARED */
 #endif
diff --git a/ldso/ldso/xtensa/resolve.S b/ldso/ldso/xtensa/resolve.S
index 8061af247..12a554de7 100644
--- a/ldso/ldso/xtensa/resolve.S
+++ b/ldso/ldso/xtensa/resolve.S
@@ -31,6 +31,7 @@
 	.global	_dl_linux_resolve
 	.type	_dl_linux_resolve, @function
 _dl_linux_resolve:
+#if defined(__XTENSA_WINDOWED_ABI__)
 	/* Call the fixup function.  */
 	movi	a8, _dl_linux_resolver
 	callx8	a8
@@ -47,4 +48,38 @@ _dl_linux_resolve:
 	/* Jump to the next instruction past the ENTRY.  */
 	addi	a10, a10, 3
 	jx	a10
+#elif defined(__XTENSA_CALL0_ABI__)
+	/* Reserve stack space and save incoming arguments.  */
+	addi	a1, a1, -32
+	s32i	a0, a1, 0
+	s32i	a2, a1, 8
+	s32i	a3, a1, 12
+	s32i	a4, a1, 16
+	s32i	a5, a1, 20
+	s32i	a6, a1, 24
+	s32i	a7, a1, 28
+
+	/* Move arguments for the _dl_linux_resolver to proper registers.  */
+	mov	a2, a10
+	mov	a3, a11
+	/* Call the fixup function.  */
+	movi	a0, _dl_linux_resolver
+	callx0	a0
+	mov	a10, a2
+
+	/* Restore incoming arguments from stack and deallocate reservation.  */
+	l32i	a0, a1, 0
+	l32i	a2, a1, 8
+	l32i	a3, a1, 12
+	l32i	a4, a1, 16
+	l32i	a5, a1, 20
+	l32i	a6, a1, 24
+	l32i	a7, a1, 28
+	addi	a1, a1, 32
+
+	/* Jump to the target function.  */
+	jx	a10
+#else
+#error Unsupported Xtensa ABI
+#endif
 	.size	_dl_linux_resolve, . - _dl_linux_resolve
-- 
cgit v1.2.3