1 #if defined(__mips_hard_float)
2 
3 #include <elf.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sys/prctl.h>
7 
8 #if !defined(PR_SET_FP_MODE)
9 #   define PR_SET_FP_MODE 45
10 #endif
11 
12 #if !defined(PR_GET_FP_MODE)
13 #   define PR_GET_FP_MODE 46
14 #endif
15 
16 /* Determine FP mode based on sdc1 behavior
17    returns 1 if FR = 1 mode is detected. */
18 static int get_fp_mode(void) {
19    unsigned long long result = 0;
20    __asm__ volatile(
21       ".set push\n\t"
22       ".set noreorder\n\t"
23       ".set oddspreg\n\t"
24       "lui $t0, 0x3FF0\n\t"
25       "ldc1 $f0, %0\n\t"
26       "mtc1 $t0, $f1\n\t"
27       "sdc1 $f0, %0\n\t"
28       ".set pop\n\t"
29       : "+m"(result)
30       :
31       : "t0", "$f0", "$f1", "memory");
32 
33    return (result != 0x3FF0000000000000ull);
34 }
35 
36 static void fatal_error(const char* msg) {
37    fprintf(stderr, "Error: %s\n", msg);
38    exit(1);
39 }
40 
41 static void test(int* fr_prctl, int* fr_detected) {
42    *fr_prctl = prctl(PR_GET_FP_MODE);
43    *fr_detected = get_fp_mode();
44 
45    if (*fr_prctl < 0) {
46       fatal_error("prctl(PR_GET_FP_MODE) fails.");
47    }
48 
49    printf("fr_prctl: %d, fr_detected: %d\n", *fr_prctl, *fr_detected);
50 
51    if (*fr_prctl != *fr_detected) {
52       fatal_error("fr_prctl != fr_detected");
53    }
54 }
55 
56 int main() {
57    int fr_prctl, fr_detected;
58 
59    test(&fr_prctl, &fr_detected);
60 
61    /* FP64 */
62    if (fr_prctl == 1) {
63 
64       /* Change mode to FP32 */
65       if (prctl(PR_SET_FP_MODE, 0) != 0) {
66          fatal_error("prctl(PR_SET_FP_MODE, 0) fails.");
67       }
68 
69       test(&fr_prctl, &fr_detected);
70 
71       /* Change back FP mode */
72       if (prctl(PR_SET_FP_MODE, 1) != 0) {
73          fatal_error("prctl(PR_SET_FP_MODE, 1) fails.");
74       }
75 
76       test(&fr_prctl, &fr_detected);
77    }
78 
79    return 0;
80 }
81 #else
82 int main() {
83    return 0;
84 }
85 #endif
86