diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/xtensa/ffi.c | 24 | ||||
-rw-r--r-- | src/xtensa/ffitarget.h | 4 | ||||
-rw-r--r-- | src/xtensa/sysv.S | 42 |
3 files changed, 46 insertions, 24 deletions
diff --git a/src/xtensa/ffi.c b/src/xtensa/ffi.c index 9a0575f..82b42a1 100644 --- a/src/xtensa/ffi.c +++ b/src/xtensa/ffi.c @@ -86,11 +86,16 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) break; } - /* Round the stack up to a full 4 register frame, just in case - (we use this size in movsp). This way, it's also a multiple of - 8 bytes for 64-bit arguments. */ - cif->bytes = FFI_ALIGN(cif->bytes, 16); - + /* Round up stack size needed for arguments. + Allocate FFI_REGISTER_ARGS_SPACE bytes when there are only arguments + passed in registers, round space reserved for arguments passed on stack + up to ABI-specified alignment. */ + if (cif->bytes < FFI_REGISTER_NARGS * 4) + cif->bytes = FFI_REGISTER_ARGS_SPACE; + else + cif->bytes = FFI_REGISTER_ARGS_SPACE + + FFI_ALIGN(cif->bytes - FFI_REGISTER_NARGS * 4, + XTENSA_STACK_ALIGNMENT); return FFI_OK; } @@ -232,6 +237,9 @@ ffi_prep_closure_loc (ffi_closure* closure, void *user_data, void *codeloc) { + if (cif->abi != FFI_SYSV) + return FFI_BAD_ABI; + /* copye trampoline to stack and patch 'ffi_closure_SYSV' pointer */ memcpy(closure->tramp, ffi_trampoline, FFI_TRAMPOLINE_SIZE); *(unsigned int*)(&closure->tramp[8]) = (unsigned int)ffi_closure_SYSV; @@ -277,15 +285,15 @@ ffi_closure_SYSV_inner(ffi_closure *closure, void **values, void *rvalue) if (arg_types[i]->alignment == 8 && (areg & 1) != 0) areg++; - // skip the entry 16,a1 framework, add 16 bytes (4 registers) + // skip the entry a1, * framework, see ffi_trampoline if (areg == FFI_REGISTER_NARGS) - areg += 4; + areg = (FFI_REGISTER_ARGS_SPACE + 32) / 4; if (arg_types[i]->type == FFI_TYPE_STRUCT) { int numregs = ((arg_types[i]->size + 3) & ~3) / 4; if (areg < FFI_REGISTER_NARGS && areg + numregs > FFI_REGISTER_NARGS) - areg = FFI_REGISTER_NARGS + 4; + areg = (FFI_REGISTER_ARGS_SPACE + 32) / 4; } avalue[i] = &values[areg]; diff --git a/src/xtensa/ffitarget.h b/src/xtensa/ffitarget.h index 0ba728b..4231ed3 100644 --- a/src/xtensa/ffitarget.h +++ b/src/xtensa/ffitarget.h @@ -43,6 +43,10 @@ typedef enum ffi_abi { #endif #define FFI_REGISTER_NARGS 6 +#define XTENSA_STACK_ALIGNMENT 16 +#define FFI_REGISTER_ARGS_SPACE ((FFI_REGISTER_NARGS * 4 + \ + XTENSA_STACK_ALIGNMENT - 1) & \ + -XTENSA_STACK_ALIGNMENT) /* ---- Definitions for closures ----------------------------------------- */ diff --git a/src/xtensa/sysv.S b/src/xtensa/sysv.S index e942179..70e83ac 100644 --- a/src/xtensa/sysv.S +++ b/src/xtensa/sysv.S @@ -43,6 +43,9 @@ #error "xtensa/sysv.S out of sync with ffi.h" #endif +#define FFI_REGISTER_ARGS_OFFSET ((XTENSA_STACK_ALIGNMENT - \ + FFI_REGISTER_NARGS * 4) & \ + (XTENSA_STACK_ALIGNMENT - 1)) /* ffi_call_SYSV (rvalue, rbytes, flags, (*fnaddr)(), bytes, ecif) void *rvalue; a2 @@ -62,28 +65,28 @@ ENTRY(ffi_call_SYSV) mov a7, a1 # fp movsp a1, a11 # set new sp = old_sp - bytes + # align ffi_prep_args stack argument so that arguments + # passed on stack if any start on 16-byte aligned boundary + + addi a11, a11, FFI_REGISTER_ARGS_OFFSET + movi a8, ffi_prep_args callx8 a8 # ffi_prep_args(ecif, stack) - # prepare to move stack pointer back up to 6 arguments - # note that 'bytes' is already aligned - - movi a10, 6*4 - sub a11, a6, a10 - movgez a6, a10, a11 - add a6, a1, a6 + # prepare to move stack pointer back + # to point to arguments passed on stack + addi a6, a1, FFI_REGISTER_ARGS_SPACE # we can pass up to 6 arguments in registers # for simplicity, just load 6 arguments - # (the stack size is at least 32 bytes, so no risk to cross boundaries) - l32i a10, a1, 0 - l32i a11, a1, 4 - l32i a12, a1, 8 - l32i a13, a1, 12 - l32i a14, a1, 16 - l32i a15, a1, 20 + l32i a10, a1, FFI_REGISTER_ARGS_OFFSET + 0 + l32i a11, a1, FFI_REGISTER_ARGS_OFFSET + 4 + l32i a12, a1, FFI_REGISTER_ARGS_OFFSET + 8 + l32i a13, a1, FFI_REGISTER_ARGS_OFFSET + 12 + l32i a14, a1, FFI_REGISTER_ARGS_OFFSET + 16 + l32i a15, a1, FFI_REGISTER_ARGS_OFFSET + 20 # move stack pointer @@ -167,7 +170,7 @@ END(ffi_call_SYSV) ENTRY(ffi_cacheflush) - entry a1, 16 + entry a1, 32 1: #if XCHAL_DCACHE_SIZE @@ -187,7 +190,14 @@ END(ffi_cacheflush) ENTRY(ffi_trampoline) - entry a1, 16 + (FFI_REGISTER_NARGS * 4) + (4 * 4) # [ 0] + /* 32 bytes for spill + spill overflow area of a frame that uses + call8, + FFI_REGISTER_NARGS * 4 bytes for arguments passed in registers, + aligned up to 4 to maintain 16 byte stack alignment, + 4 * 4 bytes for the result. + This size must be in sync with ffi_closure_SYSV_inner logic. + */ + entry a1, 32 + FFI_REGISTER_ARGS_SPACE + (4 * 4) # [ 0] j 2f # [ 3] .align 4 # [ 6] 1: .long 0 # [ 8] |