1#include "const.h"
2
3typedef enum {
4   ABSS=0, ABSD,   ADDS,   ADDD,
5   DIVS,   DIVD,   MULS,   MULD,
6   NEGS,   NEGD,   SQRTS,  SQRTD,
7   SUBS,   SUBD,   RECIPS, RECIPD,
8   RSQRTS, RSQRTD, MSUBS,  MSUBD,
9   MADDS,  MADDD,  NMADDS, NMADDD,
10   NMSUBS, NMSUBD
11} flt_art_op_t;
12
13typedef enum {
14   CEILWS=0, CEILWD,  FLOORWS,  FLOORWD,
15   ROUNDWS,  ROUNDWD, TRUNCWS,  TRUNCWD,
16   CEILLS,   CEILLD,  FLOORLS,  FLOORLD,
17   ROUNDLS,  ROUNDLD, TRUNCLS,  TRUNCLD
18} flt_dir_op_t;
19
20typedef enum {
21   CVTDS, CVTDW, CVTSD, CVTSW,
22   CVTWS, CVTWD, CVTDL, CVTLS,
23   CVTLD, CVTSL,
24} flt_round_op_t;
25
26const char *flt_art_op_names[] = {
27   "abs.s",   "abs.d",   "add.s",   "add.d",
28   "div.s",   "div.d",   "mul.s",   "mul.d",
29   "neg.s",   "neg.d",   "sqrt.s",  "sqrt.d",
30   "sub.s",   "sub.d",   "recip.s", "recip.d",
31   "rsqrt.s", "rsqrt.d", "msub.s",  "msub.d",
32   "madd.s",  "madd.d",  "nmadd.s", "nmadd.d",
33   "nmsub.s", "nmsub.d"
34};
35
36const char *flt_dir_op_names[] = {
37   "ceil.w.s",  "ceil.w.d",
38   "floor.w.s", "floor.w.d",
39   "round.w.s", "round.w.d",
40   "trunc.w.s", "trunc.w.d",
41   "ceil.l.s",  "ceil.l.d",
42   "floor.l.s", "floor.l.d",
43   "round.l.s", "round.l.d",
44   "trunc.l.s", "trunc.l.d"
45};
46
47const char *flt_round_op_names[] = {
48   "cvt.d.s", "cvt.d.w",
49   "cvt.s.d", "cvt.s.w",
50   "cvt.w.s", "cvt.w.d",
51   "cvt.d.l", "cvt.l.s",
52   "cvt.l.d", "cvt.s.l",
53};
54
55#define UNOPdd(op)               \
56   fd_d = 0;                     \
57   __asm__ __volatile__(         \
58      op"   %1, %2"   "\n\t"     \
59      "cfc1 %0, $31"  "\n\t"     \
60      : "=r" (fcsr), "=f"(fd_d)  \
61      : "f"(fs_d[i])             \
62   );
63
64#define UNOPff(op)               \
65   fd_f = 0;                     \
66   __asm__ __volatile__(         \
67      op"   %1, %2"   "\n\t"     \
68      "cfc1 %0, $31"  "\n\t"     \
69      : "=r" (fcsr), "=f"(fd_f)  \
70      : "f"(fs_f[i])             \
71   );
72
73#define UNOPfd(op)               \
74   fd_d = 0;                     \
75   __asm__ __volatile__(         \
76      op"   %1, %2"   "\n\t"     \
77      "cfc1 %0, $31"  "\n\t"     \
78      : "=r" (fcsr), "=f"(fd_d)  \
79      : "f"(fs_f[i])             \
80   );
81
82#define UNOPdf(op)               \
83   fd_f = 0;                     \
84   __asm__ __volatile__(         \
85      op"   %1, %2"   "\n\t"     \
86      "cfc1 %0, $31"  "\n\t"     \
87      : "=r" (fcsr), "=f"(fd_f)  \
88      : "f"(fs_d[i])             \
89   );
90
91#define UNOPfw(op)               \
92   fd_w = 0;                     \
93   __asm__ __volatile__(         \
94      op"   $f0, %2"   "\n\t"    \
95      "mfc1 %1,  $f0"  "\n\t"    \
96      "cfc1 %0,  $31"  "\n\t"    \
97      : "=r" (fcsr), "=r"(fd_w)  \
98      : "f"(fs_f[i])             \
99      : "$f0"                    \
100   );
101
102#define UNOPdw(op)               \
103   fd_w = 0;                     \
104   __asm__ __volatile__(         \
105      op"   $f0, %2"   "\n\t"    \
106      "mfc1 %1,  $f0"  "\n\t"    \
107      "cfc1 %0,  $31"  "\n\t"    \
108      : "=r" (fcsr), "=r"(fd_w)  \
109      : "f"(fs_d[i])             \
110      : "$f0"                    \
111   );
112
113#define UNOPwd(op)               \
114   fd_d = 0;                     \
115   __asm__ __volatile__(         \
116      "mtc1 %2,  $f0"  "\n\t"    \
117      op"   %1,  $f0"  "\n\t"    \
118      "cfc1 %0,  $31"  "\n\t"    \
119      : "=r" (fcsr), "=f"(fd_d)  \
120      : "r"(fs_w[i])             \
121      : "$f0"                    \
122   );
123
124#define UNOPwf(op)               \
125   fd_f = 0;                     \
126   __asm__ __volatile__(         \
127      "mtc1 %2,  $f0"  "\n\t"    \
128      op"   %1,  $f0"  "\n\t"    \
129      "cfc1 %0,  $31"  "\n\t"    \
130      : "=r" (fcsr), "=f"(fd_f)  \
131      : "r"(fs_w[i])             \
132      : "$f0"                    \
133   );
134
135#define UNOPld(op)               \
136   fd_d = 0;                     \
137   __asm__ __volatile__(         \
138      "dmtc1 %2, $f0"  "\n\t"    \
139      op"    %1, $f0"  "\n\t"    \
140      "cfc1  %0, $31"  "\n\t"    \
141      : "=r" (fcsr), "=f"(fd_d)  \
142      : "r"(fs_l[i])             \
143      : "$f0"                    \
144   );
145
146#define UNOPdl(op)               \
147   fd_l = 0;                     \
148   __asm__ __volatile__(         \
149      op"    $f0, %2"   "\n\t"   \
150      "dmfc1 %1,  $f0"  "\n\t"   \
151      "cfc1  %0,  $31"  "\n\t"   \
152      : "=r" (fcsr), "=r"(fd_l)  \
153      : "f"(fs_d[i])             \
154      : "$f0"                    \
155   );
156
157#define UNOPls(op)               \
158   fd_f = 0;                     \
159   __asm__ __volatile__(         \
160      "dmtc1 %2, $f0"  "\n\t"    \
161      op"    %1, $f0"  "\n\t"    \
162      "cfc1  %0, $31"  "\n\t"    \
163      : "=r" (fcsr), "=f"(fd_f)  \
164      : "r"(fs_l[i])             \
165      : "$f0"                    \
166   );
167
168#define UNOPsl(op)               \
169   fd_l = 0;                     \
170   __asm__ __volatile__(         \
171      op"    $f0, %2"   "\n\t"   \
172      "dmfc1 %1,  $f0"  "\n\t"   \
173      "cfc1  %0,  $31"  "\n\t"   \
174      : "=r" (fcsr), "=r"(fd_l)  \
175      : "f"(fs_f[i])             \
176      : "$f0"                    \
177   );
178
179#define BINOPf(op)                    \
180   fd_f = 0;                          \
181   __asm__ __volatile__(              \
182      op"    %1, %2, %3"  "\n\t"      \
183      "cfc1  %0, $31"     "\n\t"      \
184      : "=r" (fcsr), "=f" (fd_f)      \
185      : "f" (fs_f[i]), "f" (ft_f[i])  \
186   );
187
188#define BINOPd(op)                    \
189   fd_d = 0;                          \
190   __asm__ __volatile__(              \
191      op" %1, %2, %3"  "\n\t"         \
192      "cfc1  %0, $31"     "\n\t"      \
193      : "=r" (fcsr), "=f"(fd_d)       \
194      : "f" (fs_d[i]), "f" (ft_d[i])  \
195   );
196
197#define TRIOPf(op)                                    \
198   fd_f = 0;                                          \
199   __asm__ __volatile__(                              \
200      op"    %1, %2, %3, %4"  "\n\t"                  \
201      "cfc1  %0, $31"         "\n\t"                  \
202      : "=r" (fcsr), "=f" (fd_f)                      \
203      : "f" (fr_f[i]), "f" (fs_f[i]) , "f" (ft_f[i])  \
204   );
205
206#define TRIOPd(op)                                    \
207   fd_d = 0;                                          \
208   __asm__ __volatile__(                              \
209      op"    %1, %2, %3, %4"  "\n\t"                  \
210      "cfc1  %0, $31"         "\n\t"                  \
211      : "=r" (fcsr), "=f"(fd_d)                       \
212      : "f" (fr_d[i]), "f" (fs_d[i]) , "f" (ft_d[i])  \
213   );
214
215/* Conditional macros.*/
216#define TESTINST1s(instruction, RDval)               \
217{                                                    \
218   float outf = 0;                                   \
219   __asm__ __volatile__(                             \
220      ".set        noreorder"                "\n\t"  \
221      "mov.s       $f1,   %1"                "\n\t"  \
222      "mov.s       $f2,   %2"                "\n\t"  \
223      "mtc1        $zero, $f0"               "\n\t"  \
224      "c.eq.s      $f1,   $f2"               "\n\t"  \
225      instruction" end"instruction"s"#RDval  "\n\t"  \
226      "nop"                                  "\n\t"  \
227      "add.s       $f0,   $f0, $f1"          "\n\t"  \
228      "end"instruction"s"#RDval":"           "\n\t"  \
229      "add.s       $f0,   $f0, $f2"          "\n\t"  \
230      "mov.s       %0,    $f0"               "\n\t"  \
231      ".set        reorder"                  "\n\t"  \
232      : "=f" (outf)                                  \
233      : "f" (fs_f[i]) , "f" (ft_f[i])                \
234      : "$f0", "$f1", "$f2"                          \
235   );                                                \
236   printf("%s, c.eq.s   out=%f, fs=%f, ft=%f\n",     \
237          instruction, outf, fs_f[i], ft_f[i]);      \
238}
239
240#define TESTINST1d(instruction, RDval)               \
241{                                                    \
242   double outd = 0;                                  \
243   __asm__ __volatile__(                             \
244      ".set        noreorder"                "\n\t"  \
245      "mov.d       $f1,   %1"                "\n\t"  \
246      "mov.d       $f2,   %2"                "\n\t"  \
247      "dmtc1       $zero, $f0"               "\n\t"  \
248      "c.eq.d      $f1,   $f2"               "\n\t"  \
249      instruction" end"instruction"d"#RDval  "\n\t"  \
250      "nop"                                  "\n\t"  \
251      "add.d       $f0,   $f0, $f1"          "\n\t"  \
252      "end"instruction"d"#RDval":"           "\n\t"  \
253      "add.d       $f0,   $f0, $f2"          "\n\t"  \
254      "mov.d       %0,    $f0"               "\n\t"  \
255      ".set        reorder"                  "\n\t"  \
256      : "=f" (outd)                                  \
257      : "f" (fs_d[i]) , "f" (ft_d[i])                \
258      : "$f0", "$f1", "$f2"                          \
259   );                                                \
260   printf("%s, c.eq.d   out=%f, fs=%f, ft=%f\n",     \
261          instruction, outd, fs_d[i], ft_d[i]);      \
262}
263
264#define TESTINST2s(instruction, RDval)               \
265{                                                    \
266   float outf = 0;                                   \
267   __asm__ __volatile__(                             \
268      ".set        noreorder"                "\n\t"  \
269      "mov.s       $f1,   %1"                "\n\t"  \
270      "mov.s       $f2,   %2"                "\n\t"  \
271      "mtc1        $zero, $f0"               "\n\t"  \
272      "c.eq.s      $f1,   $f2"               "\n\t"  \
273      instruction" end"instruction"s"#RDval  "\n\t"  \
274      "add.s       $f0,   $f0, $f1"          "\n\t"  \
275      "end"instruction"s"#RDval":"           "\n\t"  \
276      "add.s       $f0,   $f0, $f2"          "\n\t"  \
277      "mov.s       %0, $f0"                  "\n\t"  \
278      ".set        reorder"                  "\n\t"  \
279      : "=f" (outf)                                  \
280      : "f" (fs_f[i]) , "f" (ft_f[i])                \
281      : "$f0", "$f1", "$f2"                          \
282   );                                                \
283   printf("%s, c.eq.s   out=%f, fs=%f, ft=%f\n",     \
284          instruction, outf, fs_f[i], ft_f[i]);      \
285}
286
287#define TESTINST2d(instruction, RDval)               \
288{                                                    \
289   double outd = 0;                                  \
290   __asm__ __volatile__(                             \
291      ".set        noreorder"                "\n\t"  \
292      "mov.d       $f1,   %1"                "\n\t"  \
293      "mov.d       $f2,   %2"                "\n\t"  \
294      "dmtc1       $zero, $f0"               "\n\t"  \
295      "c.eq.d      $f1,   $f2"               "\n\t"  \
296      instruction" end"instruction"d"#RDval  "\n\t"  \
297      "add.d       $f0,   $f0, $f1"          "\n\t"  \
298      "end"instruction"d"#RDval":"           "\n\t"  \
299      "add.d       $f0,   $f0, $f2"          "\n\t"  \
300      "mov.d       %0, $f0"                  "\n\t"  \
301      ".set        reorder"                  "\n\t"  \
302      : "=f" (outd)                                  \
303      : "f" (fs_d[i]) , "f" (ft_d[i])                \
304      : "$f0", "$f1", "$f2"                          \
305   );                                                \
306   printf("%s, c.eq.d   out=%f, fs=%f, ft=%f\n",     \
307          instruction, outd, fs_d[i], ft_d[i]);      \
308}
309
310#define TESTINST_CONDs(instruction, RDval)       \
311{                                                \
312   float outf = 0;                               \
313   __asm__ __volatile__(                         \
314      ".set        noreorder"         "\n\t"     \
315      "mov.s       $f1,   %1"         "\n\t"     \
316      "mov.s       $f2,   %2"         "\n\t"     \
317      "mov.s       $f0,   %1"         "\n\t"     \
318      instruction" $f1,   $f2"        "\n\t"     \
319      "bc1f end"instruction"s"#RDval  "\n\t"     \
320      "nop"                           "\n\t"     \
321      "add.s       $f0,   $f0, $f2"   "\n\t"     \
322      "end"instruction"s"#RDval":"    "\n\t"     \
323      "mov.s       %0,    $f0"        "\n\t"     \
324      ".set        reorder"           "\n\t"     \
325      : "=f" (outf)                              \
326      : "f" (fs_f[i]) , "f" (ft_f[i])            \
327      : "$f0", "$f1", "$f2"                      \
328   );                                            \
329   printf("%s, bc1f   out=%f, fs=%f, ft=%f\n",   \
330          instruction, outf, fs_f[i], ft_f[i]);  \
331}
332
333#define TESTINST_CONDd(instruction, RDval)       \
334{                                                \
335   double outd = 0;                              \
336   __asm__ __volatile__(                         \
337      ".set        noreorder"         "\n\t"     \
338      "mov.d       $f1,   %1"         "\n\t"     \
339      "mov.d       $f2,   %2"         "\n\t"     \
340      "mov.d       $f0,   %1"         "\n\t"     \
341      instruction" $f1,   $f2"        "\n\t"     \
342      "bc1f end"instruction"d"#RDval  "\n\t"     \
343      "nop"                           "\n\t"     \
344      "add.d       $f0,   $f0, $f2"   "\n\t"     \
345      "end"instruction"d"#RDval":"    "\n\t"     \
346      "mov.d       %0,    $f0"        "\n\t"     \
347      ".set        reorder"           "\n\t"     \
348      : "=f" (outd)                              \
349      : "f" (fs_d[i]) , "f" (ft_d[i])            \
350      : "$f0", "$f1", "$f2"                      \
351   );                                            \
352   printf("%s, bc1f   out=%f, fs=%f, ft=%f\n",   \
353          instruction, outd, fs_d[i], ft_d[i]);  \
354}
355