qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

mtfsf.c (1757B)


      1 #include <stdlib.h>
      2 #include <stdint.h>
      3 #include <assert.h>
      4 #include <signal.h>
      5 #include <sys/prctl.h>
      6 
      7 #define MTFSF(FLM, FRB) asm volatile ("mtfsf %0, %1" :: "i" (FLM), "f" (FRB))
      8 #define MFFS(FRT) asm("mffs %0" : "=f" (FRT))
      9 
     10 #define FPSCR_VE     7  /* Floating-point invalid operation exception enable */
     11 #define FPSCR_VXSOFT 10 /* Floating-point invalid operation exception (soft) */
     12 #define FPSCR_FI     17 /* Floating-point fraction inexact                   */
     13 
     14 #define FP_VE           (1ull << FPSCR_VE)
     15 #define FP_VXSOFT       (1ull << FPSCR_VXSOFT)
     16 #define FP_FI           (1ull << FPSCR_FI)
     17 
     18 void sigfpe_handler(int sig, siginfo_t *si, void *ucontext)
     19 {
     20     if (si->si_code == FPE_FLTINV) {
     21         exit(0);
     22     }
     23     exit(1);
     24 }
     25 
     26 int main(void)
     27 {
     28     uint64_t fpscr;
     29 
     30     struct sigaction sa = {
     31         .sa_sigaction = sigfpe_handler,
     32         .sa_flags = SA_SIGINFO
     33     };
     34 
     35     /*
     36      * Enable the MSR bits F0 and F1 to enable exceptions.
     37      * This shouldn't be needed in linux-user as these bits are enabled by
     38      * default, but this allows to execute either in a VM or a real machine
     39      * to compare the behaviors.
     40      */
     41     prctl(PR_SET_FPEXC, PR_FP_EXC_PRECISE);
     42 
     43     /* First test if the FI bit is being set correctly */
     44     MTFSF(0b11111111, FP_FI);
     45     MFFS(fpscr);
     46     assert((fpscr & FP_FI) != 0);
     47 
     48     /* Then test if the deferred exception is being called correctly */
     49     sigaction(SIGFPE, &sa, NULL);
     50 
     51     /*
     52      * Although the VXSOFT exception has been chosen, based on test in a Power9
     53      * any combination of exception bit + its enabling bit should work.
     54      * But if a different exception is chosen si_code check should
     55      * change accordingly.
     56      */
     57     MTFSF(0b11111111, FP_VE | FP_VXSOFT);
     58 
     59     return 1;
     60 }