/* $Id: fpuex.c,v 1.6 2012/07/21 21:11:40 kostik Exp kostik $ */ /* /usr/local/opt/gcc-4.7.1/bin/gcc -Wall -Wextra -msse -O -g -o fpuex32 fpuex.c */ #include #include #include #include #include #include #include #include #include #if defined(__amd64__) #include #elif defined(__i386__) #include #endif static void handler(int signo __unused, siginfo_t *info, void *v) { ucontext_t *uap; mcontext_t *mc; #if defined(__amd64__) struct savefpu *sf; #elif defined(__i386__) struct savexmm *sf; #endif u_short cw; uap = v; mc = &uap->uc_mcontext; sf = &mc->mc_fpstate; printf("intr handler: trapno %d code %d cw 0x%04x sw 0x%04x mxcsr 0x%08x ip 0x%lx\n", info->si_trapno, info->si_code, #if defined(__amd64__) sf->sv_env.en_cw, sf->sv_env.en_sw, sf->sv_env.en_mxcsr, sf->sv_env.en_rip #elif defined(__i386__) sf->sv_env.en_cw, sf->sv_env.en_sw, sf->sv_env.en_mxcsr, (unsigned long)sf->sv_env.en_fip #endif ); __asm __volatile("fnstcw %0" : "=m" (cw)); printf("handler cw %x\n", cw); exit(0); } double a[3]; /* * a[3] = a[0] / a[1]; */ static void x_sse(void) { __asm("movsd\t%1,%%xmm0\n\t" "divsd\t%2,%%xmm0\n\t" "movsd\t%%xmm0,%0\n" : "=m" (a[3]) : "m" (a[0]), "m" (a[1]) : "xmm0"); } static void x_x87(void) { __asm("fldl\t%1\n\t" "fdivl\t%2\n\t" "fstl\t%0\n" : "=m" (a[3]) : "m" (a[0]), "m" (a[1])); } static void usage(void) { fprintf(stderr, "fpuex sse|x87\n"); exit(1); } int main(int argc, char *argv[]) { struct sigaction sa; uint32_t mxcsr; uint16_t cw; int use_sse; if (argc == 1) { #if defined(__amd64__) use_sse = 1; #elif defined(__i386__) use_sse = 0; #endif } else if (argc != 2) usage(); else { if (!strcmp(argv[1], "sse")) use_sse = 1; else if (!strcmp(argv[1], "x87")) use_sse = 0; else usage(); } bzero(&sa, sizeof(sa)); sa.sa_sigaction = handler; sa.sa_flags = SA_SIGINFO; if (sigaction(SIGFPE, &sa, NULL) == -1) err(1, "sigaction SIGFPE"); mxcsr = 0; __asm __volatile("ldmxcsr %0" : : "m" (mxcsr)); cw = 0; __asm __volatile("fldcw %0" : : "m" (cw)); a[0] = 1.0; a[1] = 0.0; if (use_sse) x_sse(); else x_x87(); return (0); }