1#include <stdio.h>
2#include <stdlib.h>
3#include <signal.h>
4#include <setjmp.h>
5
6#define MAX_ARR 24
7#define PERROR \
8        printf("This test is testing mips32r2 instructions in fpu64 mode.\n");
9#define FLAGS_RM_MASK 0xFFFFFFFF
10
11typedef enum {
12   CVTLS,   CVTLD,   ROUNDLS, ROUNDLD,
13   TRUNCLS, TRUNCLD, FLOORLS, FLOORLD,
14   CEILLS,  CEILLD
15} flt_round_op_t;
16
17const char *flt_round_op_names[] = {
18   "cvt.l.s",   "cvt.l.d",   "round.l.s", "round.l.d",
19   "trunc.l.s", "trunc.l.d", "floor.l.s", "floor.l.d"
20   "ceil.l.s",  "ceil.l.d"
21};
22
23typedef enum {
24   TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t;
25char *round_mode_name[] = { "near", "zero", "+inf", "-inf" };
26
27const float fs_f[] = {
28   0,         456.25,   3,          -1,
29   1384.5,    -7.25,    1000000000, -5786.25,
30   1752,      0.015625, 0.03125,    -248562.75,
31   -45786.5,  456,      34.03125,   45786.75,
32   1752065,   107,      -45667.25,  -7,
33   -347856.5, 356047,   -1.25,      23.0625
34};
35
36const double fs_d[] = {
37   0,         456.25,   3,          -1,
38   1384.5,    -7.25,    1000000000, -5786.25,
39   1752,      0.015625, 0.03125,    -24856226678933.75,
40   -45786.5,  456,      34.03125,   45786.75,
41   1752065,   107,      -45667.25,  -7,
42   -347856.5, 356047,   -1.25,      23.0625
43};
44
45#define UNOPsl(op)                \
46   __asm__ __volatile__(          \
47      op"   $f0, %2"     "\n\t"   \
48      "sdc1 $f0, 0(%1)"  "\n\t"   \
49      "cfc1 %0,  $31"    "\n\t"   \
50      : "=r" (fcsr)               \
51      : "r"(&fd_l), "f"(fs_f[i])  \
52      : "$f0"                     \
53   );
54
55#define UNOPdl(op)                \
56   __asm__ __volatile__(          \
57      op"   $f0, %2"     "\n\t"   \
58      "sdc1 $f0, 0(%1)"  "\n\t"   \
59      "cfc1 %0,  $31"    "\n\t"   \
60      : "=r" (fcsr)               \
61      : "r"(&fd_l), "f"(fs_d[i])  \
62      : "$f0"                     \
63   );
64
65#define TEST_FPU64                \
66   __asm__ __volatile__(          \
67      "cvt.l.s $f0, $f0"  "\n\t"  \
68      :                           \
69      :                           \
70      : "$f0"                     \
71   );
72
73#if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64)
74void set_rounding_mode(round_mode_t mode)
75{
76   switch(mode) {
77      case TO_NEAREST:
78         __asm__ volatile("ctc1 $zero, $31"  "\n\t");
79         break;
80      case TO_ZERO:
81         __asm__ volatile("li    $t0, 0x1"  "\n\t"
82                          "ctc1  $t0, $31"  "\n\t");
83         break;
84      case TO_PLUS_INFINITY:
85          __asm__ volatile("li    $t0, 0x2"  "\n\t"
86                           "ctc1  $t0, $31"  "\n\t");
87         break;
88      case TO_MINUS_INFINITY:
89          __asm__ volatile("li    $t0, 0x3"  "\n\t"
90                           "ctc1  $t0, $31"  "\n\t");
91         break;
92   }
93}
94
95struct test {
96   void (*test)(void);
97   int sig;
98   int code;
99};
100
101static void handler(int sig)
102{
103   PERROR;
104   exit(0);
105}
106
107int FCSRRoundingMode(flt_round_op_t op)
108{
109   long long int fd_l;
110   int i;
111   int fcsr = 0;
112   round_mode_t rm;
113   for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) {
114      printf("roundig mode: %s\n", round_mode_name[rm]);
115      for (i = 0; i < MAX_ARR; i++) {
116         set_rounding_mode(rm);
117         switch(op) {
118            case CVTLS:
119               UNOPsl("cvt.l.s");
120               printf("%s %lld %f\n",
121                      flt_round_op_names[op], fd_l, fs_f[i]);
122               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
123               break;
124            case CVTLD:
125               UNOPdl("cvt.l.d");
126               printf("%s %lld %lf\n",
127                      flt_round_op_names[op], fd_l, fs_d[i]);
128               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
129               break;
130            case ROUNDLS:
131               UNOPsl("round.l.s");
132               printf("%s %lld %f\n",
133                      flt_round_op_names[op], fd_l, fs_f[i]);
134               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
135               break;
136            case ROUNDLD:
137               UNOPdl("round.l.d");
138               printf("%s %lld %lf\n",
139                      flt_round_op_names[op], fd_l, fs_d[i]);
140               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
141               break;
142            case TRUNCLS:
143               UNOPsl("trunc.l.s");
144               printf("%s %lld %f\n",
145                      flt_round_op_names[op], fd_l, fs_f[i]);
146               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
147               break;
148            case TRUNCLD:
149               UNOPdl("trunc.l.d");
150               printf("%s %lld %lf\n",
151                      flt_round_op_names[op], fd_l, fs_d[i]);
152               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
153               break;
154            case FLOORLS:
155               UNOPsl("floor.l.s");
156               printf("%s %lld %f\n",
157                      flt_round_op_names[op], fd_l, fs_f[i]);
158               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
159               break;
160            case FLOORLD:
161               UNOPdl("floor.l.d");
162               printf("%s %lld %lf\n",
163                      flt_round_op_names[op], fd_l, fs_d[i]);
164               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
165               break;
166            case CEILLS:
167               UNOPsl("ceil.l.s");
168               printf("%s %lld %f\n",
169                      flt_round_op_names[op], fd_l, fs_f[i]);
170               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
171               break;
172            case CEILLD:
173               UNOPdl("ceil.l.d");
174               printf("%s %lld %lf\n",
175                      flt_round_op_names[op], fd_l, fs_d[i]);
176               printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
177               break;
178            default:
179               printf("error\n");
180               break;
181         }
182      }
183   }
184   return 0;
185}
186#endif
187
188
189int main()
190{
191#if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64)
192   flt_round_op_t op;
193   signal(SIGILL, handler);
194   /* Test fpu64 mode. */
195   TEST_FPU64;
196   printf("-------------------------- %s --------------------------\n",
197          "test FPU Conversion Operations Using the FCSR Rounding Mode");
198   for (op = CVTLS; op <= CEILLD; op++)
199      FCSRRoundingMode(op);
200#else
201   PERROR;
202#endif
203   return 0;
204}
205