FPUarithmetic.c revision 436e89c602e787e7a27dd6624b09beed41a0da8a
1#include <stdio.h>
2#include <stdlib.h>
3
4typedef enum {
5   ABSS=0, ABSD,
6   ADDS, ADDD,
7   DIVS, DIVD,
8   MULS, MULD,
9   NEGS, NEGD,
10   SQRTS, SQRTD,
11   SUBS, SUBD,
12   RECIPS, RECIPD,
13   RSQRTS, RSQRTD
14} flt_art_op_t;
15
16const char *flt_art_op_names[] = {
17   "abs.s", "abs.d",
18   "add.s", "add.d",
19   "div.s", "div.d",
20   "mul.s", "mul.d",
21   "neg.s", "neg.d",
22   "sqrt.s", "sqrt.d",
23   "sub.s", "sub.d",
24   "recip.s", "recip.d",
25   "rsqrt.s", "rsqrt.d"
26};
27
28typedef enum {
29   TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t;
30char *round_mode_name[] = { "near", "zero", "+inf", "-inf" };
31
32const double fs_d[] = {
33   0,         456.25,   3,          -1,
34   1384.5,    -7.25,    1000000000, -5786.5,
35   1752,      0.015625, 0.03125,    -248562.75,
36   456,       -45786.5, 34.03125,   45786.75,
37   1752065,   107,      -45667.25,  -7,
38   -347856.5, 356047.5, -1.0,       23.0625
39};
40
41const double ft_d[] = {
42   -456.25,    -45786.5, 34.03125,   45786.75,
43   1752065,   107,      -45667.25,  -7.25,
44   -347856.5, 356047.5, -1.0,       23.0625,
45   0,         456.25,   3,          -1,
46   1384.5,    -7,       1000000000, -5786.5,
47   1752,      0.015625, 0.03125,    -248562.75
48};
49
50const float fs_f[] = {
51   0,         456.25,   3,          -1,
52   1384.5,    -7.25,    1000000000, -5786.5,
53   1752,      0.015625, 0.03125,    -248562.75,
54   456,       -45786.5, 34.03125,   45786.75,
55   1752065,   107,      -45667.25,  -7,
56   -347856.5, 356047.5, -1.0,       23.0625
57};
58
59const float ft_f[] = {
60   -456.25,  -4578.5,   34.03125, 4578.75,
61   175,     107,      -456.25,  -7.25,
62   -3478.5, 356.5,    -1.0,     23.0625,
63   0,       456.25,   3,        -1,
64   1384.5,  -7,       100,      -5786.5,
65   1752,    0.015625, 0.03125,  -248562.75
66};
67
68#define UNOPdd(op) \
69        fd_d = 0;  \
70        __asm__ volatile( \
71					op" %0, %1\n\t" \
72					: "=f"(fd_d) : "f"(fs_d[i]));
73
74#define UNOPff(op) \
75        fd_f = 0;  \
76        __asm__ volatile( \
77					op" %0, %1\n\t" \
78					: "=f"(fd_f) : "f"(fs_f[i]));
79
80#define BINOPf(op) \
81        fd_f = 0;  \
82        __asm__ volatile( \
83					op" %0, %1, %2\n\t" \
84					: "=f"(fd_f) : "f"(fs_f[i]) , "f"(ft_f[i]));
85
86#define BINOPd(op) \
87        fd_d = 0;  \
88        __asm__ volatile( \
89					op" %0, %1, %2\n\t" \
90					: "=f"(fd_d) : "f"(fs_d[i]) , "f"(ft_d[i]));
91
92void set_rounding_mode(round_mode_t mode)
93{
94   switch(mode) {
95      case TO_NEAREST:
96         __asm__ volatile("cfc1 $t0, $31\n\t"
97                          "srl $t0, 2\n\t"
98                          "sll $t0, 2\n\t"
99                          "ctc1 $t0, $31\n\t");
100         break;
101      case TO_ZERO:
102         __asm__ volatile("cfc1 $t0, $31\n\t"
103                          "srl $t0, 2\n\t"
104                          "sll $t0, 2\n\t"
105                          "addiu $t0, 1\n\t"
106                          "ctc1 $t0, $31\n\t");
107         break;
108      case TO_PLUS_INFINITY:
109         __asm__ volatile("cfc1 $t0, $31\n\t"
110                          "srl $t0, 2\n\t"
111                          "sll $t0, 2\n\t"
112                          "addiu $t0, 2\n\t"
113                          "ctc1 $t0, $31\n\t");
114         break;
115      case TO_MINUS_INFINITY:
116         __asm__ volatile("cfc1 $t0, $31\n\t"
117                          "srl $t0, 2\n\t"
118                          "sll $t0, 2\n\t"
119                          "addiu $t0, 3\n\t"
120                          "ctc1 $t0, $31\n\t");
121         break;
122   }
123}
124
125int arithmeticOperations(flt_art_op_t op)
126{
127   double fd_d = 0;
128   float fd_f = 0;
129   int i = 0;
130   round_mode_t rm;
131   for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) {
132      set_rounding_mode(rm);
133      printf("rounding mode: %s\n", round_mode_name[rm]);
134      for (i = 0; i < 24; i++)
135      {
136         switch(op) {
137            case ABSS:
138                 UNOPff("abs.s");
139                 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
140                 break;
141            case ABSD:
142                 UNOPdd("abs.d");
143                 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
144                 break;
145            case ADDS:
146                 BINOPf("add.s");
147                 printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]);
148                 break;
149            case ADDD:
150                 BINOPd("add.d");
151                 printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]);
152                 break;
153            case DIVS:
154                 BINOPf("div.s");
155                 printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]);
156                 break;
157            case DIVD:
158                 BINOPd("div.d");
159                 printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]);
160                 break;
161            case MULS:
162                 BINOPf("mul.s");
163                 printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]);
164                 break;
165            case MULD:
166                 BINOPd("mul.d");
167                 printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]);
168                 break;
169            case NEGS:
170                 UNOPff("neg.s");
171                 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
172                 break;
173            case NEGD:
174                 UNOPdd("neg.d");
175                 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
176                 break;
177            case SQRTS:
178                 UNOPff("sqrt.s");
179                 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
180                 break;
181            case SQRTD:
182                 UNOPdd("sqrt.d");
183                 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
184                 break;
185            case SUBS:
186                 BINOPf("sub.s");
187                 printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]);
188                 break;
189            case SUBD:
190                 BINOPd("sub.d");
191                 printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]);
192                 break;
193            case RECIPS:
194#if (__mips==32) && (__mips_isa_rev>=2)
195                 UNOPff("recip.s");
196                 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
197#endif
198                 break;
199            case RECIPD:
200#if (__mips==32) && (__mips_isa_rev>=2)
201                 UNOPdd("recip.d");
202                 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
203#endif
204                 break;
205            case RSQRTS:
206#if (__mips==32) && (__mips_isa_rev>=2)
207                 UNOPff("rsqrt.s");
208                 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
209#endif
210                 break;
211            case RSQRTD:
212#if (__mips==32) && (__mips_isa_rev>=2)
213                 UNOPdd("rsqrt.d");
214                 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
215#endif
216                 break;
217            default:
218               printf("error\n");
219               break;
220         }
221      }
222   }
223   return 0;
224}
225
226int main()
227{
228   flt_art_op_t op;
229
230   printf("-------------------------- %s --------------------------\n",
231        "test FPU Arithmetic Operations");
232   for (op = ABSS; op <= RECIPD; op++) {
233      arithmeticOperations(op);
234   }
235
236   return 0;
237}
238
239