xref: /openbmc/qemu/tests/tcg/ppc64/mtfsf.c (revision d2dfe0b5)
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 }
61