1 #if defined(__mips_hard_float)
2 
3 #include <stdio.h>
4 
5 /*
6  * Bits 18 (NAN2008) and 19 (ABS2008) are preset by hardware and may differ
7  * between platforms. Hence a macro to clear them before printing FCSR
8  * values.
9  */
10 #define FCSR_NAN2008 1 << 18
11 #define FCSR_ABS2008 1 << 19
12 #define FLAGS_RM_MASK 0xFFFFFFFF & ~(FCSR_ABS2008 | FCSR_NAN2008)
13 #define CLEAR_PRESETBITS_FCSR(fcsr) (fcsr & FLAGS_RM_MASK)
14 
15 typedef enum {
16    CEILWS=0, CEILWD,
17    FLOORWS, FLOORWD,
18    ROUNDWS, ROUNDWD,
19    TRUNCWS, TRUNCWD
20 } flt_dir_op_t;
21 
22 typedef enum {
23    CVTDS, CVTDW,
24    CVTSD, CVTSW,
25    CVTWS, CVTWD
26 } flt_round_op_t;
27 
28 typedef enum {
29    TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t;
30 char *round_mode_name[] = { "near", "zero", "+inf", "-inf" };
31 
32 
33 const char *flt_dir_op_names[] = {
34    "ceil.w.s", "ceil.w.d",
35    "floor.w.s", "floor.w.d",
36    "round.w.s", "round.w.d",
37    "trunc.w.s", "trunc.w.d"
38 };
39 
40 const char *flt_round_op_names[] = {
41    "cvt.d.s", "cvt.d.w",
42    "cvt.s.d", "cvt.s.w",
43    "cvt.w.s", "cvt.w.d"
44 };
45 
46 const double fs_d[] = {
47    0, 456.25, 3, -1,
48    1384.5, -7.25, 1000000000, -5786.25,
49    1752, 0.015625, 0.03125, -248562.75,
50    -45786.5, 456, 34.03125, 45786.75,
51    1752065, 107, -45667.25, -7,
52    -347856.5, 356047, -1.25, 23.0625
53 };
54 
55 const float fs_f[] = {
56    0, 456.25, 3, -1,
57    1384.5, -7.25, 1000000000, -5786.25,
58    1752, 0.015625, 0.03125, -248562.75,
59    -45786.5, 456, 34.03125, 45786.75,
60    1752065, 107, -45667.25, -7,
61    -347856.5, 356047, -1.25, 23.0625
62 };
63 
64 const int fs_w[] = {
65    0, 456, 3, -1,
66    0xffffffff, 356, 1000000000, -5786,
67    1752, 24575, 10, -248562,
68    -45786, 456, 34, 45786,
69    1752065, 107, -45667, -7,
70    -347856, 0x80000000, 0xFFFFFFF, 23
71 };
72 
73 #define BINOP(op)                                   \
74         __asm__ volatile(op"   %1, %2, %3"  "\n\t"  \
75                          "cfc1 %0, $31"     "\n\t"  \
76                          : "=r" (fcsr), "=f"(fd)    \
77                          : "f"(f) , "f"(fB));
78 
79 #define UNOPdd(op)                                  \
80         fd_d = 0;                                   \
81         __asm__ volatile(op"   %1, %2"      "\n\t"  \
82                          "cfc1 %0, $31"     "\n\t"  \
83                          : "=r" (fcsr), "=f"(fd_d)  \
84                          : "f"(fs_d[i]));
85 
86 #define UNOPff(op)                                  \
87         fd_f = 0;                                   \
88         __asm__ volatile(op" %1, %2"        "\n\t"  \
89                          "cfc1 %0, $31"     "\n\t"  \
90                          : "=r" (fcsr), "=f"(fd_f)  \
91                          : "f"(fs_f[i]));
92 
93 #define UNOPfd(op)                                  \
94         fd_d = 0;                                   \
95         __asm__ volatile(op"   %1, %2"   "\n\t"     \
96                          "cfc1 %0, $31"  "\n\t"     \
97                          : "=r" (fcsr), "=f"(fd_d)  \
98                          : "f"(fs_f[i]));
99 
100 #define UNOPdf(op)                                  \
101         fd_f = 0;                                   \
102         __asm__ volatile(op"   %1, %2"   "\n\t"     \
103                          "cfc1 %0, $31"  "\n\t"     \
104                          : "=r" (fcsr), "=f"(fd_f)  \
105                          : "f"(fs_d[i]));
106 
107 #define UNOPfw(op)                                  \
108         fd_w = 0;                                   \
109         __asm__ volatile(op"   $f0, %2"   "\n\t"    \
110                          "mfc1 %1,  $f0"  "\n\t"    \
111                          "cfc1 %0, $31"   "\n\t"    \
112                          : "=r" (fcsr), "=r"(fd_w)  \
113                          : "f"(fs_f[i])             \
114                          : "$f0");
115 
116 #define UNOPdw(op)                                  \
117         fd_w = 0;                                   \
118         __asm__ volatile(op" $f0, %2"    "\n\t"     \
119                          "mfc1 %1, $f0"  "\n\t"     \
120                          "cfc1 %0, $31"  "\n\t"     \
121                          : "=r" (fcsr), "=r"(fd_w)  \
122                          : "f"(fs_d[i])             \
123                          : "$f0");
124 
125 #define UNOPwd(op)                                  \
126         fd_d = 0;                                   \
127         __asm__ volatile("mtc1 %2, $f0"  "\n\t"     \
128                          op"   %1, $f0"  "\n\t"     \
129                          "cfc1 %0, $31"  "\n\t"     \
130                          : "=r" (fcsr), "=f"(fd_d)  \
131                          : "r"(fs_w[i])             \
132                          : "$f0", "$f1");
133 
134 #define UNOPwf(op)                                  \
135         fd_f = 0;                                   \
136         __asm__ volatile("mtc1 %2, $f0"  "\n\t"     \
137                          op"   %1, $f0"  "\n\t"     \
138                          "cfc1 %0, $31"  "\n\t"     \
139                          : "=r" (fcsr), "=f"(fd_f)  \
140                          : "r"(fs_w[i])             \
141                          : "$f0");
142 
set_rounding_mode(round_mode_t mode)143 void set_rounding_mode(round_mode_t mode)
144 {
145    switch(mode) {
146       case TO_NEAREST:
147          __asm__ volatile("ctc1 $zero, $31"  "\n\t");
148          break;
149       case TO_ZERO:
150          __asm__ volatile("li    $t0, 0x1"  "\n\t"
151                           "ctc1  $t0, $31"  "\n\t");
152          break;
153       case TO_PLUS_INFINITY:
154           __asm__ volatile("li    $t0, 0x2"  "\n\t"
155                            "ctc1  $t0, $31"  "\n\t");
156          break;
157       case TO_MINUS_INFINITY:
158           __asm__ volatile("li    $t0, 0x3"  "\n\t"
159                            "ctc1  $t0, $31"  "\n\t");
160          break;
161    }
162 }
163 
clear_fcc()164 void clear_fcc(){
165    __asm__ __volatile__(
166       "cfc1 $t0, $31"            "\n\t"
167       "and  $t0, $t0, 0x17FFFFF" "\n\t"
168       "ctc1 $t0, $31"            "\n\t"
169       :
170       :
171       : "t0"
172    );
173 }
174 
directedRoundingMode(flt_dir_op_t op)175 int directedRoundingMode(flt_dir_op_t op) {
176    int fd_w = 0;
177    int i;
178    int fcsr = 0;
179    round_mode_t rm = TO_NEAREST;
180    for (i = 0; i < 24; i++) {
181       clear_fcc();
182       set_rounding_mode(rm);
183       switch(op) {
184          case CEILWS:
185               UNOPfw("ceil.w.s");
186               printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
187               printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
188               break;
189          case CEILWD:
190               UNOPdw("ceil.w.d");
191               printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
192               printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
193               break;
194          case FLOORWS:
195               UNOPfw("floor.w.s");
196               printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
197               printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
198               break;
199          case FLOORWD:
200               UNOPdw("floor.w.d");
201               printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
202               printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
203               break;
204          case ROUNDWS:
205               UNOPfw("round.w.s");
206               printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
207               printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
208               break;
209          case ROUNDWD:
210               UNOPdw("round.w.d");
211               printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
212               printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
213               break;
214          case TRUNCWS:
215               UNOPfw("trunc.w.s");
216               printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
217               printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
218               break;
219          case TRUNCWD:
220               UNOPdw("trunc.w.d");
221               printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
222               printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
223               break;
224         default:
225             printf("error\n");
226             break;
227         }
228     }
229    return 0;
230 }
231 
FCSRRoundingMode(flt_round_op_t op1)232 int FCSRRoundingMode(flt_round_op_t op1)
233 {
234    double fd_d = 0;
235    float fd_f = 0;
236    int fd_w = 0;
237    int i;
238    int fcsr = 0;
239    round_mode_t rm;
240    for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) {
241       set_rounding_mode(rm);
242       printf("roundig mode: %s\n", round_mode_name[rm]);
243       for (i = 0; i < 24; i++) {
244          clear_fcc();
245          set_rounding_mode(rm);
246          switch(op1) {
247             case CVTDS:
248                  UNOPfd("cvt.d.s");
249                  printf("%s %lf %lf\n", flt_round_op_names[op1], fd_d, fs_f[i]);
250                  printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
251                  break;
252             case CVTDW:
253                  UNOPwd("cvt.d.w");
254                  printf("%s %lf %d\n", flt_round_op_names[op1], fd_d, fs_w[i]);
255                  printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
256                  break;
257             case CVTSD:
258                  UNOPdf("cvt.s.d");
259                  printf("%s %f %lf\n", flt_round_op_names[op1], fd_f, fs_d[i]);
260                  printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
261                  break;
262             case CVTSW:
263                  UNOPwf("cvt.s.w");
264                  printf("%s %f %d\n", flt_round_op_names[op1], fd_f, fs_w[i]);
265                  printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
266                  break;
267             case CVTWS:
268                  UNOPfw("cvt.w.s");
269                  printf("%s %d %f\n", flt_round_op_names[op1], fd_w, fs_f[i]);
270                  printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
271                  break;
272             case CVTWD:
273                  UNOPdw("cvt.w.d");
274                  printf("%s %d %lf\n", flt_round_op_names[op1], fd_w, fs_d[i]);
275                  printf("fcsr: 0x%x\n", CLEAR_PRESETBITS_FCSR(fcsr));
276                  break;
277             default:
278                  printf("error\n");
279                  break;
280          }
281       }
282    }
283    return 0;
284 }
285 
main()286 int main()
287 {
288    flt_dir_op_t op;
289    flt_round_op_t op1;
290 
291    printf("-------------------------- %s --------------------------\n",
292         "test FPU Conversion Operations Using a Directed Rounding Mode");
293    for (op = CEILWS; op <= TRUNCWD; op++) {
294       directedRoundingMode(op);
295    }
296 
297    printf("-------------------------- %s --------------------------\n",
298         "test FPU Conversion Operations Using the FCSR Rounding Mode");
299    for (op1 = CVTDS; op1 <= CVTWD; op1++) {
300       FCSRRoundingMode(op1);
301    }
302    return 0;
303 }
304 #else
main()305 int main() {
306    return 0;
307 }
308 #endif
309 
310