This is the mail archive of the
libffi-discuss@sourceware.org
mailing list for the libffi project.
PATCH: Add Linux/x32 support
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: libffi-discuss at sourceware dot org
- Date: Sat, 3 Mar 2012 10:37:06 -0800
- Subject: PATCH: Add Linux/x32 support
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
This patch adds support for Linux/x32:
https://sites.google.com/site/x32abi/
Linux/x32 has 32bit pointers and long with x86-64 instruction set. We
have to use long long to update 64bit address and integer registes.
Tested on Linux/x32.
H.J.
---
2012-03-03 H.J. Lu <hongjiu.lu@intel.com>
* src/x86/ffi64.c (ffi_call): Cast the return value to unsigned
long.
(ffi_prep_closure_loc): Cast to 64bit address in trampoline.
(ffi_closure_unix64_inner): Cast return pointer to unsigned long
first.
* src/x86/ffitarget.h (FFI_SIZEOF_ARG): Defined to 8 for x32.
(ffi_arg): Set to unsigned long long for x32.
(ffi_sarg): Set to long long for x32.
diff --git a/src/x86/ffi64.c b/src/x86/ffi64.c
index c8eb455..defd774 100644
--- a/src/x86/ffi64.c
+++ b/src/x86/ffi64.c
@@ -427,7 +427,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
/* If the return value is passed in memory, add the pointer as the
first integer argument. */
if (ret_in_memory)
- reg_args->gpr[gprcount++] = (long) rvalue;
+ reg_args->gpr[gprcount++] = (unsigned long) rvalue;
avn = cif->nargs;
arg_types = cif->arg_types;
@@ -509,9 +509,11 @@ ffi_prep_closure_loc (ffi_closure* closure,
tramp = (volatile unsigned short *) &closure->tramp[0];
tramp[0] = 0xbb49; /* mov <code>, %r11 */
- *(void * volatile *) &tramp[1] = ffi_closure_unix64;
+ *((unsigned long long * volatile) &tramp[1])
+ = (unsigned long) ffi_closure_unix64;
tramp[5] = 0xba49; /* mov <data>, %r10 */
- *(void * volatile *) &tramp[6] = codeloc;
+ *((unsigned long long * volatile) &tramp[6])
+ = (unsigned long) codeloc;
/* Set the carry bit iff the function uses any sse registers.
This is clc or stc, together with the first byte of the jmp. */
@@ -550,7 +552,7 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
{
/* The return value goes in memory. Arrange for the closure
return value to go directly back to the original caller. */
- rvalue = (void *) reg_args->gpr[gprcount++];
+ rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
/* We don't have to do anything in asm for the return. */
ret = FFI_TYPE_VOID;
}
diff --git a/src/x86/ffitarget.h b/src/x86/ffitarget.h
index 17f60bc..54a6121 100644
--- a/src/x86/ffitarget.h
+++ b/src/x86/ffitarget.h
@@ -61,9 +61,15 @@ typedef unsigned long long ffi_arg;
typedef long long ffi_sarg;
#endif
#else
+#if defined __x86_64__ && !defined __LP64__
+#define FFI_SIZEOF_ARG 8
+typedef unsigned long long ffi_arg;
+typedef long long ffi_sarg;
+#else
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
#endif
+#endif
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,