18eb8bab992e3998c33770b0cdb16059a8b918a06sewardj/* x86 variant of the amd64-solaris/context_fpu.c test. */ 28eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 38eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <assert.h> 48eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <signal.h> 58eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <stdio.h> 68eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <stdlib.h> 78eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <unistd.h> 88eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <sys/syscall.h> 98eb8bab992e3998c33770b0cdb16059a8b918a06sewardj#include <sys/ucontext.h> 108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 118eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic siginfo_t si; 128eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic ucontext_t uc; 138eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic float inhandler[8]; 148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 158eb8bab992e3998c33770b0cdb16059a8b918a06sewardjstatic void sighandler(int sig, siginfo_t *sip, ucontext_t *ucp) 168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 178eb8bab992e3998c33770b0cdb16059a8b918a06sewardj int i; 188eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 198eb8bab992e3998c33770b0cdb16059a8b918a06sewardj si = *sip; 208eb8bab992e3998c33770b0cdb16059a8b918a06sewardj uc = *ucp; 218eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 228eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Reset the FP stack so it's possible to push other values onto it. (It 238eb8bab992e3998c33770b0cdb16059a8b918a06sewardj is fully filled in main() before triggering the signal handler). Note 248eb8bab992e3998c33770b0cdb16059a8b918a06sewardj that VEX also clears all FP values when the finit instruction is 258eb8bab992e3998c33770b0cdb16059a8b918a06sewardj executed. This provides another level of validation that the restore 268eb8bab992e3998c33770b0cdb16059a8b918a06sewardj code is correct. */ 278eb8bab992e3998c33770b0cdb16059a8b918a06sewardj __asm__ __volatile__( 288eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "finit\n"); 298eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 308eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Convert 80b values in mcontext to 32b values in the inhandler array. */ 318eb8bab992e3998c33770b0cdb16059a8b918a06sewardj for (i = 0; i < 8; i++) { 328eb8bab992e3998c33770b0cdb16059a8b918a06sewardj __asm__ __volatile__( 338eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fldt %[in]\n" 348eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fstps %[out]\n" 358eb8bab992e3998c33770b0cdb16059a8b918a06sewardj : [out] "=m" (inhandler[i]) 368eb8bab992e3998c33770b0cdb16059a8b918a06sewardj : [in] "m" (*((char*)&ucp->uc_mcontext.fpregs.fp_reg_set.fpchip_state 378eb8bab992e3998c33770b0cdb16059a8b918a06sewardj + 28 + i * 10))); 388eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 398eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 408eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 418eb8bab992e3998c33770b0cdb16059a8b918a06sewardjint main(void) 428eb8bab992e3998c33770b0cdb16059a8b918a06sewardj{ 438eb8bab992e3998c33770b0cdb16059a8b918a06sewardj struct sigaction sa; 448eb8bab992e3998c33770b0cdb16059a8b918a06sewardj pid_t pid; 458eb8bab992e3998c33770b0cdb16059a8b918a06sewardj float out[8]; 468eb8bab992e3998c33770b0cdb16059a8b918a06sewardj float x0; 478eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 488eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Uninitialised, but we know px[0] is 0x0. */ 498eb8bab992e3998c33770b0cdb16059a8b918a06sewardj float *px = malloc(sizeof(*px)); 508eb8bab992e3998c33770b0cdb16059a8b918a06sewardj x0 = px[0]; 518eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 528eb8bab992e3998c33770b0cdb16059a8b918a06sewardj sa.sa_handler = sighandler; 538eb8bab992e3998c33770b0cdb16059a8b918a06sewardj sa.sa_flags = SA_SIGINFO; 548eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (sigfillset(&sa.sa_mask)) { 558eb8bab992e3998c33770b0cdb16059a8b918a06sewardj perror("sigfillset"); 568eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return 1; 578eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 588eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (sigaction(SIGUSR1, &sa, NULL)) { 598eb8bab992e3998c33770b0cdb16059a8b918a06sewardj perror("sigaction"); 608eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return 1; 618eb8bab992e3998c33770b0cdb16059a8b918a06sewardj } 628eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 638eb8bab992e3998c33770b0cdb16059a8b918a06sewardj pid = getpid(); 648eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 658eb8bab992e3998c33770b0cdb16059a8b918a06sewardj __asm__ __volatile__( 668eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Set values in the FP stack. */ 678eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "flds %[x0]\n" 688eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fld1\n" 698eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "flds %[x0]\n" 708eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fld1\n" 718eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "flds %[x0]\n" 728eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fld1\n" 738eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "flds %[x0]\n" 748eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fld1\n" 758eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 768eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Prepare syscall parameters. */ 778eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "pushl %[sig]\n" 788eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "pushl %[pid]\n" 798eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "pushl $0xdeadbeef\n" 808eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "movl %[scall], %%eax\n" 818eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 828eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Trigger the signal handler. */ 838eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "int $0x91\n" 848eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "addl $12, %%esp\n" 858eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fstps 0x00 + %[out]\n" 868eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fstps 0x04 + %[out]\n" 878eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fstps 0x08 + %[out]\n" 888eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fstps 0x0c + %[out]\n" 898eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fstps 0x10 + %[out]\n" 908eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fstps 0x14 + %[out]\n" 918eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fstps 0x18 + %[out]\n" 928eb8bab992e3998c33770b0cdb16059a8b918a06sewardj "fstps 0x1c + %[out]\n" 938eb8bab992e3998c33770b0cdb16059a8b918a06sewardj : [out] "=m" (out[0]) 948eb8bab992e3998c33770b0cdb16059a8b918a06sewardj : [scall] "i" (SYS_kill), [pid] "a" (pid), [sig] "i" (SIGUSR1), 958eb8bab992e3998c33770b0cdb16059a8b918a06sewardj [x0] "m" (x0) 968eb8bab992e3998c33770b0cdb16059a8b918a06sewardj : "edx", "cc", "memory"); 978eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 988eb8bab992e3998c33770b0cdb16059a8b918a06sewardj printf("Values in the signal handler:\n"); 998eb8bab992e3998c33770b0cdb16059a8b918a06sewardj printf(" fp[0]=%f, fp[2]=%f, fp[4]=%f, fp[6]=%f\n", 1008eb8bab992e3998c33770b0cdb16059a8b918a06sewardj inhandler[0], inhandler[2], inhandler[4], inhandler[6]); 1018eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Check that inhandler[1], inhandler[3], inhandler[5] and inhandler[7] 1028eb8bab992e3998c33770b0cdb16059a8b918a06sewardj contain uninitialised values (origin is px[0]). */ 1038eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (inhandler[1] || inhandler[3] || inhandler[5] || inhandler[7]) 1048eb8bab992e3998c33770b0cdb16059a8b918a06sewardj assert(0); 1058eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 1068eb8bab992e3998c33770b0cdb16059a8b918a06sewardj printf("Values after the return from the signal handler:\n"); 1078eb8bab992e3998c33770b0cdb16059a8b918a06sewardj printf(" fp[0]=%f, fp[2]=%f, fp[4]=%f, fp[6]=%f\n", 1088eb8bab992e3998c33770b0cdb16059a8b918a06sewardj out[0], out[2], out[4], out[6]); 1098eb8bab992e3998c33770b0cdb16059a8b918a06sewardj /* Check that out[1], out[3], out[5] and out[7] contain uninitialised 1108eb8bab992e3998c33770b0cdb16059a8b918a06sewardj values (origin is px[0]). */ 1118eb8bab992e3998c33770b0cdb16059a8b918a06sewardj if (out[1] || out[3] || out[5] || out[7]) 1128eb8bab992e3998c33770b0cdb16059a8b918a06sewardj assert(0); 1138eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 1148eb8bab992e3998c33770b0cdb16059a8b918a06sewardj return 0; 1158eb8bab992e3998c33770b0cdb16059a8b918a06sewardj} 1168eb8bab992e3998c33770b0cdb16059a8b918a06sewardj 117