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