• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <signal.h>
4 #include <setjmp.h>
5 
6 #define MAX_ARR 24
7 #define PERROR \
8         printf("This test is testing mips32r2 instructions in fpu64 mode.\n");
9 #define FLAGS_RM_MASK 0xFFFFFFFF
10 
11 typedef enum {
12    CVTLS,   CVTLD,   ROUNDLS, ROUNDLD,
13    TRUNCLS, TRUNCLD, FLOORLS, FLOORLD,
14    CEILLS,  CEILLD
15 } flt_round_op_t;
16 
17 const char *flt_round_op_names[] = {
18    "cvt.l.s",   "cvt.l.d",   "round.l.s", "round.l.d",
19    "trunc.l.s", "trunc.l.d", "floor.l.s", "floor.l.d"
20    "ceil.l.s",  "ceil.l.d"
21 };
22 
23 typedef enum {
24    TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t;
25 char *round_mode_name[] = { "near", "zero", "+inf", "-inf" };
26 
27 const float fs_f[] = {
28    0,         456.25,   3,          -1,
29    1384.5,    -7.25,    1000000000, -5786.25,
30    1752,      0.015625, 0.03125,    -248562.75,
31    -45786.5,  456,      34.03125,   45786.75,
32    1752065,   107,      -45667.25,  -7,
33    -347856.5, 356047,   -1.25,      23.0625
34 };
35 
36 const double fs_d[] = {
37    0,         456.25,   3,          -1,
38    1384.5,    -7.25,    1000000000, -5786.25,
39    1752,      0.015625, 0.03125,    -24856226678933.75,
40    -45786.5,  456,      34.03125,   45786.75,
41    1752065,   107,      -45667.25,  -7,
42    -347856.5, 356047,   -1.25,      23.0625
43 };
44 
45 #define UNOPsl(op)                \
46    __asm__ __volatile__(          \
47       op"   $f0, %2"     "\n\t"   \
48       "sdc1 $f0, 0(%1)"  "\n\t"   \
49       "cfc1 %0,  $31"    "\n\t"   \
50       : "=r" (fcsr)               \
51       : "r"(&fd_l), "f"(fs_f[i])  \
52       : "$f0"                     \
53    );
54 
55 #define UNOPdl(op)                \
56    __asm__ __volatile__(          \
57       op"   $f0, %2"     "\n\t"   \
58       "sdc1 $f0, 0(%1)"  "\n\t"   \
59       "cfc1 %0,  $31"    "\n\t"   \
60       : "=r" (fcsr)               \
61       : "r"(&fd_l), "f"(fs_d[i])  \
62       : "$f0"                     \
63    );
64 
65 #define TEST_FPU64                \
66    __asm__ __volatile__(          \
67       "cvt.l.s $f0, $f0"  "\n\t"  \
68       :                           \
69       :                           \
70       : "$f0"                     \
71    );
72 
73 #if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64)
set_rounding_mode(round_mode_t mode)74 void set_rounding_mode(round_mode_t mode)
75 {
76    switch(mode) {
77       case TO_NEAREST:
78          __asm__ volatile("ctc1 $zero, $31"  "\n\t");
79          break;
80       case TO_ZERO:
81          __asm__ volatile("li    $t0, 0x1"  "\n\t"
82                           "ctc1  $t0, $31"  "\n\t");
83          break;
84       case TO_PLUS_INFINITY:
85           __asm__ volatile("li    $t0, 0x2"  "\n\t"
86                            "ctc1  $t0, $31"  "\n\t");
87          break;
88       case TO_MINUS_INFINITY:
89           __asm__ volatile("li    $t0, 0x3"  "\n\t"
90                            "ctc1  $t0, $31"  "\n\t");
91          break;
92    }
93 }
94 
95 struct test {
96    void (*test)(void);
97    int sig;
98    int code;
99 };
100 
handler(int sig)101 static void handler(int sig)
102 {
103    PERROR;
104    exit(0);
105 }
106 
FCSRRoundingMode(flt_round_op_t op)107 int FCSRRoundingMode(flt_round_op_t op)
108 {
109    long long int fd_l;
110    int i;
111    int fcsr = 0;
112    round_mode_t rm;
113    for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) {
114       printf("roundig mode: %s\n", round_mode_name[rm]);
115       for (i = 0; i < MAX_ARR; i++) {
116          set_rounding_mode(rm);
117          switch(op) {
118             case CVTLS:
119                UNOPsl("cvt.l.s");
120                printf("%s %lld %f\n",
121                       flt_round_op_names[op], fd_l, fs_f[i]);
122                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
123                break;
124             case CVTLD:
125                UNOPdl("cvt.l.d");
126                printf("%s %lld %lf\n",
127                       flt_round_op_names[op], fd_l, fs_d[i]);
128                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
129                break;
130             case ROUNDLS:
131                UNOPsl("round.l.s");
132                printf("%s %lld %f\n",
133                       flt_round_op_names[op], fd_l, fs_f[i]);
134                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
135                break;
136             case ROUNDLD:
137                UNOPdl("round.l.d");
138                printf("%s %lld %lf\n",
139                       flt_round_op_names[op], fd_l, fs_d[i]);
140                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
141                break;
142             case TRUNCLS:
143                UNOPsl("trunc.l.s");
144                printf("%s %lld %f\n",
145                       flt_round_op_names[op], fd_l, fs_f[i]);
146                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
147                break;
148             case TRUNCLD:
149                UNOPdl("trunc.l.d");
150                printf("%s %lld %lf\n",
151                       flt_round_op_names[op], fd_l, fs_d[i]);
152                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
153                break;
154             case FLOORLS:
155                UNOPsl("floor.l.s");
156                printf("%s %lld %f\n",
157                       flt_round_op_names[op], fd_l, fs_f[i]);
158                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
159                break;
160             case FLOORLD:
161                UNOPdl("floor.l.d");
162                printf("%s %lld %lf\n",
163                       flt_round_op_names[op], fd_l, fs_d[i]);
164                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
165                break;
166             case CEILLS:
167                UNOPsl("ceil.l.s");
168                printf("%s %lld %f\n",
169                       flt_round_op_names[op], fd_l, fs_f[i]);
170                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
171                break;
172             case CEILLD:
173                UNOPdl("ceil.l.d");
174                printf("%s %lld %lf\n",
175                       flt_round_op_names[op], fd_l, fs_d[i]);
176                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
177                break;
178             default:
179                printf("error\n");
180                break;
181          }
182       }
183    }
184    return 0;
185 }
186 #endif
187 
188 
main()189 int main()
190 {
191 #if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64)
192    flt_round_op_t op;
193    signal(SIGILL, handler);
194    /* Test fpu64 mode. */
195    TEST_FPU64;
196    printf("-------------------------- %s --------------------------\n",
197           "test FPU Conversion Operations Using the FCSR Rounding Mode");
198    for (op = CVTLS; op <= CEILLD; op++)
199       FCSRRoundingMode(op);
200 #else
201    PERROR;
202 #endif
203    return 0;
204 }
205