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