diff options
author | green <green@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-04 21:11:09 +0000 |
---|---|---|
committer | green <green@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-04 21:11:09 +0000 |
commit | f51aab02abe223469d9f39e4e46250b65fd18a8b (patch) | |
tree | 3289bacfc83a97eaf50f42a61d0b9a06f4c76e9c /libffi/src/sparc | |
parent | de3e3c185df5165793e9c0459732eb5c2bede7c5 (diff) | |
download | gcc-f51aab02abe223469d9f39e4e46250b65fd18a8b.tar.gz |
Merge upstream libffi
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@184897 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libffi/src/sparc')
-rw-r--r-- | libffi/src/sparc/ffi.c | 66 | ||||
-rw-r--r-- | libffi/src/sparc/ffitarget.h | 13 | ||||
-rw-r--r-- | libffi/src/sparc/v9.S | 2 |
3 files changed, 65 insertions, 16 deletions
diff --git a/libffi/src/sparc/ffi.c b/libffi/src/sparc/ffi.c index 1d01f59ec23..1ac5d464e8b 100644 --- a/libffi/src/sparc/ffi.c +++ b/libffi/src/sparc/ffi.c @@ -1,5 +1,6 @@ /* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1996, 2003, 2004, 2007, 2008 Red Hat, Inc. + ffi.c - Copyright (c) 2011 Anthony Green + Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc. SPARC Foreign Function Interface @@ -406,8 +407,50 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) /* We don't yet support calling 32bit code from 64bit */ FFI_ASSERT(0); #else - ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, - cif->flags, rvalue, fn); + if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + || cif->flags == FFI_TYPE_LONGDOUBLE +#endif + )) + { + /* For v8, we need an "unimp" with size of returning struct */ + /* behind "call", so we alloc some executable space for it. */ + /* l7 is used, we need to make sure v8.S doesn't use %l7. */ + unsigned int *call_struct = NULL; + ffi_closure_alloc(32, &call_struct); + if (call_struct) + { + unsigned long f = (unsigned long)fn; + call_struct[0] = 0xae10001f; /* mov %i7, %l7 */ + call_struct[1] = 0xbe10000f; /* mov %o7, %i7 */ + call_struct[2] = 0x03000000 | f >> 10; /* sethi %hi(fn), %g1 */ + call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */ + call_struct[4] = 0x01000000; /* nop */ + if (cif->rtype->size < 0x7f) + call_struct[5] = cif->rtype->size; /* unimp */ + else + call_struct[5] = 0x01000000; /* nop */ + call_struct[6] = 0x81c7e008; /* ret */ + call_struct[7] = 0xbe100017; /* mov %l7, %i7 */ + asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : : + "r" (call_struct) : "memory"); + /* SPARC v8 requires 5 instructions for flush to be visible */ + asm volatile ("nop; nop; nop; nop; nop"); + ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, + cif->flags, rvalue, call_struct); + ffi_closure_free(call_struct); + } + else + { + ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, + cif->flags, rvalue, fn); + } + } + else + { + ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, + cif->flags, rvalue, fn); + } #endif break; case FFI_V9: @@ -425,7 +468,6 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) FFI_ASSERT(0); break; } - } @@ -447,7 +489,8 @@ ffi_prep_closure_loc (ffi_closure* closure, #ifdef SPARC64 /* Trampoline address is equal to the closure address. We take advantage of that to reduce the trampoline size by 8 bytes. */ - FFI_ASSERT (cif->abi == FFI_V9); + if (cif->abi != FFI_V9) + return FFI_BAD_ABI; fn = (unsigned long) ffi_closure_v9; tramp[0] = 0x83414000; /* rd %pc, %g1 */ tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */ @@ -456,7 +499,8 @@ ffi_prep_closure_loc (ffi_closure* closure, *((unsigned long *) &tramp[4]) = fn; #else unsigned long ctx = (unsigned long) codeloc; - FFI_ASSERT (cif->abi == FFI_V8); + if (cif->abi != FFI_V8) + return FFI_BAD_ABI; fn = (unsigned long) ffi_closure_v8; tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */ tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */ @@ -468,13 +512,13 @@ ffi_prep_closure_loc (ffi_closure* closure, closure->fun = fun; closure->user_data = user_data; - /* Flush the Icache. FIXME: alignment isn't certain, assume 8 bytes */ + /* Flush the Icache. closure is 8 bytes aligned. */ #ifdef SPARC64 - asm volatile ("flush %0" : : "r" (closure) : "memory"); - asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory"); + asm volatile ("flush %0; flush %0+8" : : "r" (closure) : "memory"); #else - asm volatile ("iflush %0" : : "r" (closure) : "memory"); - asm volatile ("iflush %0" : : "r" (((char *) closure) + 8) : "memory"); + asm volatile ("iflush %0; iflush %0+8" : : "r" (closure) : "memory"); + /* SPARC v8 requires 5 instructions for flush to be visible */ + asm volatile ("nop; nop; nop; nop; nop"); #endif return FFI_OK; diff --git a/libffi/src/sparc/ffitarget.h b/libffi/src/sparc/ffitarget.h index 50554b8805d..d89f7877a81 100644 --- a/libffi/src/sparc/ffitarget.h +++ b/libffi/src/sparc/ffitarget.h @@ -1,5 +1,6 @@ /* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. + ffitarget.h - Copyright (c) 2012 Anthony Green + Copyright (c) 1996-2003 Red Hat, Inc. Target configuration macros for SPARC. Permission is hereby granted, free of charge, to any person obtaining @@ -27,6 +28,10 @@ #ifndef LIBFFI_TARGET_H #define LIBFFI_TARGET_H +#ifndef LIBFFI_H +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." +#endif + /* ---- System specific configurations ----------------------------------- */ #if defined(__arch64__) || defined(__sparcv9) @@ -44,12 +49,12 @@ typedef enum ffi_abi { FFI_V8, FFI_V8PLUS, FFI_V9, + FFI_LAST_ABI, #ifdef SPARC64 - FFI_DEFAULT_ABI = FFI_V9, + FFI_DEFAULT_ABI = FFI_V9 #else - FFI_DEFAULT_ABI = FFI_V8, + FFI_DEFAULT_ABI = FFI_V8 #endif - FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 } ffi_abi; #endif diff --git a/libffi/src/sparc/v9.S b/libffi/src/sparc/v9.S index bf31a2b5110..489ff0293f2 100644 --- a/libffi/src/sparc/v9.S +++ b/libffi/src/sparc/v9.S @@ -32,7 +32,7 @@ /* Only compile this in for 64bit builds, because otherwise the object file will have inproper architecture due to used instructions. */ -#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */ +#define STACKFRAME 128 /* Minimum stack framesize for SPARC */ #define STACK_BIAS 2047 #define ARGS (128) /* Offset of register area in frame */ |