1 #include <stdio.h>
2 #include <stdlib.h>
3
4 typedef 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
16 const 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
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 const 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
41 const 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
50 const 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
59 const 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
set_rounding_mode(round_mode_t mode)92 void 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
arithmeticOperations(flt_art_op_t op)125 int 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
main()226 int 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