1 /* x86 variant of the amd64-solaris/context_fpu.c test. */ 2 3 #include <assert.h> 4 #include <signal.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <unistd.h> 8 #include <sys/syscall.h> 9 #include <sys/ucontext.h> 10 11 static siginfo_t si; 12 static ucontext_t uc; 13 static float inhandler[8]; 14 15 static void sighandler(int sig, siginfo_t *sip, ucontext_t *ucp) 16 { 17 int i; 18 19 si = *sip; 20 uc = *ucp; 21 22 /* Reset the FP stack so it's possible to push other values onto it. (It 23 is fully filled in main() before triggering the signal handler). Note 24 that VEX also clears all FP values when the finit instruction is 25 executed. This provides another level of validation that the restore 26 code is correct. */ 27 __asm__ __volatile__( 28 "finit\n"); 29 30 /* Convert 80b values in mcontext to 32b values in the inhandler array. */ 31 for (i = 0; i < 8; i++) { 32 __asm__ __volatile__( 33 "fldt %[in]\n" 34 "fstps %[out]\n" 35 : [out] "=m" (inhandler[i]) 36 : [in] "m" (*((char*)&ucp->uc_mcontext.fpregs.fp_reg_set.fpchip_state 37 + 28 + i * 10))); 38 } 39 } 40 41 int main(void) 42 { 43 struct sigaction sa; 44 pid_t pid; 45 float out[8]; 46 float x0; 47 48 /* Uninitialised, but we know px[0] is 0x0. */ 49 float *px = malloc(sizeof(*px)); 50 x0 = px[0]; 51 52 sa.sa_handler = sighandler; 53 sa.sa_flags = SA_SIGINFO; 54 if (sigfillset(&sa.sa_mask)) { 55 perror("sigfillset"); 56 return 1; 57 } 58 if (sigaction(SIGUSR1, &sa, NULL)) { 59 perror("sigaction"); 60 return 1; 61 } 62 63 pid = getpid(); 64 65 __asm__ __volatile__( 66 /* Set values in the FP stack. */ 67 "flds %[x0]\n" 68 "fld1\n" 69 "flds %[x0]\n" 70 "fld1\n" 71 "flds %[x0]\n" 72 "fld1\n" 73 "flds %[x0]\n" 74 "fld1\n" 75 76 /* Prepare syscall parameters. */ 77 "pushl %[sig]\n" 78 "pushl %[pid]\n" 79 "pushl $0xdeadbeef\n" 80 "movl %[scall], %%eax\n" 81 82 /* Trigger the signal handler. */ 83 "int $0x91\n" 84 "addl $12, %%esp\n" 85 "fstps 0x00 + %[out]\n" 86 "fstps 0x04 + %[out]\n" 87 "fstps 0x08 + %[out]\n" 88 "fstps 0x0c + %[out]\n" 89 "fstps 0x10 + %[out]\n" 90 "fstps 0x14 + %[out]\n" 91 "fstps 0x18 + %[out]\n" 92 "fstps 0x1c + %[out]\n" 93 : [out] "=m" (out[0]) 94 : [scall] "i" (SYS_kill), [pid] "a" (pid), [sig] "i" (SIGUSR1), 95 [x0] "m" (x0) 96 : "edx", "cc", "memory"); 97 98 printf("Values in the signal handler:\n"); 99 printf(" fp[0]=%f, fp[2]=%f, fp[4]=%f, fp[6]=%f\n", 100 inhandler[0], inhandler[2], inhandler[4], inhandler[6]); 101 /* Check that inhandler[1], inhandler[3], inhandler[5] and inhandler[7] 102 contain uninitialised values (origin is px[0]). */ 103 if (inhandler[1] || inhandler[3] || inhandler[5] || inhandler[7]) 104 assert(0); 105 106 printf("Values after the return from the signal handler:\n"); 107 printf(" fp[0]=%f, fp[2]=%f, fp[4]=%f, fp[6]=%f\n", 108 out[0], out[2], out[4], out[6]); 109 /* Check that out[1], out[3], out[5] and out[7] contain uninitialised 110 values (origin is px[0]). */ 111 if (out[1] || out[3] || out[5] || out[7]) 112 assert(0); 113 114 return 0; 115 } 116 117