diff options
author | David Schleef <ds@schleef.org> | 2005-02-02 01:01:49 +0000 |
---|---|---|
committer | David Schleef <ds@schleef.org> | 2005-02-02 01:01:49 +0000 |
commit | 6420cbe9eaa99050266e99ce7c670f2b44c97bfd (patch) | |
tree | 9fd11c08b9051a073362d25ddaa9d0721ea680ad | |
parent | ea487b28c0f206723c3bb89dece59c1fc1fd0796 (diff) | |
download | liboil-6420cbe9eaa99050266e99ce7c670f2b44c97bfd.tar.gz |
* liboil/liboilcpu.c: (test_altivec), (oil_cpu_powerpc_getflags),
(illegal_instruction_handler), (oil_cpu_fault_check_enable),
(oil_cpu_fault_check_try), (oil_cpu_fault_check_disable): Add
illegal instruction checking.
* liboil/liboilcpu.h:
* liboil/liboilfunction.c: (oil_init):
* liboil/liboiltest.c: (oil_test_check_function),
(oil_test_check_impl):
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | liboil/liboilcpu.c | 83 | ||||
-rw-r--r-- | liboil/liboilcpu.h | 5 | ||||
-rw-r--r-- | liboil/liboilfunction.c | 3 | ||||
-rw-r--r-- | liboil/liboiltest.c | 16 |
5 files changed, 85 insertions, 33 deletions
@@ -1,3 +1,14 @@ +2005-02-01 David Schleef <ds@schleef.org> + + * liboil/liboilcpu.c: (test_altivec), (oil_cpu_powerpc_getflags), + (illegal_instruction_handler), (oil_cpu_fault_check_enable), + (oil_cpu_fault_check_try), (oil_cpu_fault_check_disable): Add + illegal instruction checking. + * liboil/liboilcpu.h: + * liboil/liboilfunction.c: (oil_init): + * liboil/liboiltest.c: (oil_test_check_function), + (oil_test_check_impl): + 2005-01-31 David Schleef <ds@schleef.org> * doc/Makefile.am: Stop abusing _LDFLAGS diff --git a/liboil/liboilcpu.c b/liboil/liboilcpu.c index 993db6a..5ff2fa1 100644 --- a/liboil/liboilcpu.c +++ b/liboil/liboilcpu.c @@ -36,10 +36,8 @@ #include <stdlib.h> #include <string.h> #include <stdio.h> -#if defined(__powerpc__) #include <setjmp.h> #include <signal.h> -#endif #if defined(__i386__) static char * get_cpuinfo_flags_string (char *cpuinfo); @@ -128,46 +126,26 @@ oil_cpu_i386_getflags(void) #endif #ifdef __powerpc__ -static jmp_buf jump_env; - -static int -test_altivec (void) +static void +test_altivec (void *) { - int ret; char x[16] = { 0, }; - ret = setjmp (jump_env); - if (!ret) { - asm volatile ( - " lvx %%v0, %0, %%r0 \n" - :: "r" (x)); - } - - return (ret==0); -} - -static void -illegal_instruction_handler (int num) -{ - longjmp (jump_env, 1); + asm volatile ( + " lvx %%v0, %0, %%r0 \n" + :: "r" (x)); } static void oil_cpu_powerpc_getflags(void) { - struct sigaction act; - struct sigaction oldact; - memset (&act, 0, sizeof(act)); - act.sa_handler = &illegal_instruction_handler; - sigaction (SIGILL, &act, &oldact); - - if (test_altivec()) { + oil_cpu_fault_check_enable (); + if (oil_cpu_fault_check_try(test_altivec, NULL)) { OIL_DEBUG ("cpu flag altivec"); oil_cpu_flags |= OIL_IMPL_FLAG_ALTIVEC; } - - sigaction (SIGILL, &oldact, NULL); + oil_cpu_fault_check_disable (); } #endif @@ -263,3 +241,48 @@ _strndup (const char *s, int n) } #endif +static jmp_buf jump_env; +static struct sigaction action; +static struct sigaction oldaction; +static int in_try_block; + +static void +illegal_instruction_handler (int num) +{ + if (in_try_block) { + longjmp (jump_env, 1); + } else { + abort (); + } +} + +void +oil_cpu_fault_check_enable (void) +{ + memset (&action, 0, sizeof(action)); + action.sa_handler = &illegal_instruction_handler; + sigaction (SIGILL, &action, &oldaction); + in_try_block = 0; +} + +int +oil_cpu_fault_check_try (void (*func) (void *), void *priv) +{ + int ret; + + in_try_block = 1; + ret = setjmp (jump_env); + if (!ret) { + func (priv); + } + in_try_block = 0; + + return (ret == 0); +} + +void +oil_cpu_fault_check_disable (void) +{ + sigaction (SIGILL, &oldaction, NULL); +} + diff --git a/liboil/liboilcpu.h b/liboil/liboilcpu.h index c6245d6..c15a509 100644 --- a/liboil/liboilcpu.h +++ b/liboil/liboilcpu.h @@ -31,5 +31,10 @@ void _oil_cpu_init (void); unsigned int oil_cpu_get_flags (void); +void oil_cpu_fault_check_enable (void); +void oil_cpu_fault_check_disable (void); + +int oil_cpu_fault_check_try (void (*func)(void *), void *priv); + #endif diff --git a/liboil/liboilfunction.c b/liboil/liboilfunction.c index b72b12f..9181816 100644 --- a/liboil/liboilfunction.c +++ b/liboil/liboilfunction.c @@ -68,7 +68,10 @@ oil_init (void) _oil_cpu_init (); oil_init_pointers (); oil_init_structs (); + + oil_cpu_fault_check_enable (); oil_optimize_all (); + oil_cpu_fault_check_disable (); stop = oil_profile_stamp_gtod (); diff --git a/liboil/liboiltest.c b/liboil/liboiltest.c index 638680c..7041b36 100644 --- a/liboil/liboiltest.c +++ b/liboil/liboiltest.c @@ -33,6 +33,7 @@ #include <liboil/liboildebug.h> #include <liboil/liboilrandom.h> #include <liboil/liboilprofile.h> +#include <liboil/liboilcpu.h> #include <stdlib.h> #include <string.h> #include <stdio.h> @@ -121,8 +122,9 @@ oil_test_set_iterations (OilTest *test, int iterations) } static void -oil_test_check_function (OilTest *test) +oil_test_check_function (void * priv) { + OilTest *test = priv; int i; int j; unsigned long args[10]; @@ -140,7 +142,7 @@ oil_test_check_function (OilTest *test) } } - OIL_LOG("calling reference function %s", test->impl->name); + OIL_LOG("calling function %s", test->impl->name); pointer_mask = 1; for(i=0;i<test->proto->n_params;i++){ @@ -222,6 +224,7 @@ oil_test_check_impl (OilTest *test, OilFunctionImpl *impl) int i; int n; int fail = 0; + int ret; if (test->proto->n_params > 10) { OIL_ERROR ("function has too many parameters"); @@ -233,7 +236,14 @@ oil_test_check_impl (OilTest *test, OilFunctionImpl *impl) } test->impl = impl; - oil_test_check_function (test); + ret = oil_cpu_fault_check_try (oil_test_check_function, test); + if (!ret) { + OIL_ERROR ("illegal instruction in %s", test->impl->name); + test->impl->profile_ave = 0; + test->impl->profile_std = 0; + + return 0; + } x = 0; n = 0; |