1#if defined(__mips_hard_float) 2 3#include <stdio.h> 4 5typedef enum { 6 CEILWS=0, CEILWD, 7 FLOORWS, FLOORWD, 8 ROUNDWS, ROUNDWD, 9 TRUNCWS, TRUNCWD 10} flt_dir_op_t; 11 12typedef enum { 13 CVTDS, CVTDW, 14 CVTSD, CVTSW, 15 CVTWS, CVTWD 16} flt_round_op_t; 17 18typedef enum { 19 TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t; 20char *round_mode_name[] = { "near", "zero", "+inf", "-inf" }; 21 22 23const char *flt_dir_op_names[] = { 24 "ceil.w.s", "ceil.w.d", 25 "floor.w.s", "floor.w.d", 26 "round.w.s", "round.w.d", 27 "trunc.w.s", "trunc.w.d" 28}; 29 30const char *flt_round_op_names[] = { 31 "cvt.d.s", "cvt.d.w", 32 "cvt.s.d", "cvt.s.w", 33 "cvt.w.s", "cvt.w.d" 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, -248562.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 45const float fs_f[] = { 46 0, 456.25, 3, -1, 47 1384.5, -7.25, 1000000000, -5786.25, 48 1752, 0.015625, 0.03125, -248562.75, 49 -45786.5, 456, 34.03125, 45786.75, 50 1752065, 107, -45667.25, -7, 51 -347856.5, 356047, -1.25, 23.0625 52}; 53 54const int fs_w[] = { 55 0, 456, 3, -1, 56 0xffffffff, 356, 1000000000, -5786, 57 1752, 24575, 10, -248562, 58 -45786, 456, 34, 45786, 59 1752065, 107, -45667, -7, 60 -347856, 0x80000000, 0xFFFFFFF, 23 61}; 62 63#define BINOP(op) \ 64 __asm__ volatile(op" %1, %2, %3" "\n\t" \ 65 "cfc1 %0, $31" "\n\t" \ 66 : "=r" (fcsr), "=f"(fd) \ 67 : "f"(f) , "f"(fB)); 68 69#define UNOPdd(op) \ 70 fd_d = 0; \ 71 __asm__ volatile(op" %1, %2" "\n\t" \ 72 "cfc1 %0, $31" "\n\t" \ 73 : "=r" (fcsr), "=f"(fd_d) \ 74 : "f"(fs_d[i])); 75 76#define UNOPff(op) \ 77 fd_f = 0; \ 78 __asm__ volatile(op" %1, %2" "\n\t" \ 79 "cfc1 %0, $31" "\n\t" \ 80 : "=r" (fcsr), "=f"(fd_f) \ 81 : "f"(fs_f[i])); 82 83#define UNOPfd(op) \ 84 fd_d = 0; \ 85 __asm__ volatile(op" %1, %2" "\n\t" \ 86 "cfc1 %0, $31" "\n\t" \ 87 : "=r" (fcsr), "=f"(fd_d) \ 88 : "f"(fs_f[i])); 89 90#define UNOPdf(op) \ 91 fd_f = 0; \ 92 __asm__ volatile(op" %1, %2" "\n\t" \ 93 "cfc1 %0, $31" "\n\t" \ 94 : "=r" (fcsr), "=f"(fd_f) \ 95 : "f"(fs_d[i])); 96 97#define UNOPfw(op) \ 98 fd_w = 0; \ 99 __asm__ volatile(op" $f0, %2" "\n\t" \ 100 "mfc1 %1, $f0" "\n\t" \ 101 "cfc1 %0, $31" "\n\t" \ 102 : "=r" (fcsr), "=r"(fd_w) \ 103 : "f"(fs_f[i]) \ 104 : "$f0"); 105 106#define UNOPdw(op) \ 107 fd_w = 0; \ 108 __asm__ volatile(op" $f0, %2" "\n\t" \ 109 "mfc1 %1, $f0" "\n\t" \ 110 "cfc1 %0, $31" "\n\t" \ 111 : "=r" (fcsr), "=r"(fd_w) \ 112 : "f"(fs_d[i]) \ 113 : "$f0"); 114 115#define UNOPwd(op) \ 116 fd_d = 0; \ 117 __asm__ volatile("mtc1 %2, $f0" "\n\t" \ 118 op" %1, $f0" "\n\t" \ 119 "cfc1 %0, $31" "\n\t" \ 120 : "=r" (fcsr), "=f"(fd_d) \ 121 : "r"(fs_w[i]) \ 122 : "$f0", "$f1"); 123 124#define UNOPwf(op) \ 125 fd_f = 0; \ 126 __asm__ volatile("mtc1 %2, $f0" "\n\t" \ 127 op" %1, $f0" "\n\t" \ 128 "cfc1 %0, $31" "\n\t" \ 129 : "=r" (fcsr), "=f"(fd_f) \ 130 : "r"(fs_w[i]) \ 131 : "$f0"); 132 133void set_rounding_mode(round_mode_t mode) 134{ 135 switch(mode) { 136 case TO_NEAREST: 137 __asm__ volatile("ctc1 $zero, $31" "\n\t"); 138 break; 139 case TO_ZERO: 140 __asm__ volatile("li $t0, 0x1" "\n\t" 141 "ctc1 $t0, $31" "\n\t"); 142 break; 143 case TO_PLUS_INFINITY: 144 __asm__ volatile("li $t0, 0x2" "\n\t" 145 "ctc1 $t0, $31" "\n\t"); 146 break; 147 case TO_MINUS_INFINITY: 148 __asm__ volatile("li $t0, 0x3" "\n\t" 149 "ctc1 $t0, $31" "\n\t"); 150 break; 151 } 152} 153 154void clear_fcc(){ 155 __asm__ __volatile__( 156 "cfc1 $t0, $31" "\n\t" 157 "and $t0, $t0, 0x17FFFFF" "\n\t" 158 "ctc1 $t0, $31" "\n\t" 159 : 160 : 161 : "t0" 162 ); 163} 164 165int directedRoundingMode(flt_dir_op_t op) { 166 int fd_w = 0; 167 int i; 168 int fcsr = 0; 169 round_mode_t rm = TO_NEAREST; 170 for (i = 0; i < 24; i++) { 171 clear_fcc(); 172 set_rounding_mode(rm); 173 switch(op) { 174 case CEILWS: 175 UNOPfw("ceil.w.s"); 176 printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); 177 printf("fcsr: 0x%x\n", fcsr); 178 break; 179 case CEILWD: 180 UNOPdw("ceil.w.d"); 181 printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); 182 printf("fcsr: 0x%x\n", fcsr); 183 break; 184 case FLOORWS: 185 UNOPfw("floor.w.s"); 186 printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); 187 printf("fcsr: 0x%x\n", fcsr); 188 break; 189 case FLOORWD: 190 UNOPdw("floor.w.d"); 191 printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); 192 printf("fcsr: 0x%x\n", fcsr); 193 break; 194 case ROUNDWS: 195 UNOPfw("round.w.s"); 196 printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); 197 printf("fcsr: 0x%x\n", fcsr); 198 break; 199 case ROUNDWD: 200 UNOPdw("round.w.d"); 201 printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); 202 printf("fcsr: 0x%x\n", fcsr); 203 break; 204 case TRUNCWS: 205 UNOPfw("trunc.w.s"); 206 printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]); 207 printf("fcsr: 0x%x\n", fcsr); 208 break; 209 case TRUNCWD: 210 UNOPdw("trunc.w.d"); 211 printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]); 212 printf("fcsr: 0x%x\n", fcsr); 213 break; 214 default: 215 printf("error\n"); 216 break; 217 } 218 } 219 return 0; 220} 221 222int FCSRRoundingMode(flt_round_op_t op1) 223{ 224 double fd_d = 0; 225 float fd_f = 0; 226 int fd_w = 0; 227 int i; 228 int fcsr = 0; 229 round_mode_t rm; 230 for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) { 231 set_rounding_mode(rm); 232 printf("roundig mode: %s\n", round_mode_name[rm]); 233 for (i = 0; i < 24; i++) { 234 clear_fcc(); 235 set_rounding_mode(rm); 236 switch(op1) { 237 case CVTDS: 238 UNOPfd("cvt.d.s"); 239 printf("%s %lf %lf\n", flt_round_op_names[op1], fd_d, fs_f[i]); 240 printf("fcsr: 0x%x\n", fcsr); 241 break; 242 case CVTDW: 243 UNOPwd("cvt.d.w"); 244 printf("%s %lf %d\n", flt_round_op_names[op1], fd_d, fs_w[i]); 245 printf("fcsr: 0x%x\n", fcsr); 246 break; 247 case CVTSD: 248 UNOPdf("cvt.s.d"); 249 printf("%s %f %lf\n", flt_round_op_names[op1], fd_f, fs_d[i]); 250 printf("fcsr: 0x%x\n", fcsr); 251 break; 252 case CVTSW: 253 UNOPwf("cvt.s.w"); 254 printf("%s %f %d\n", flt_round_op_names[op1], fd_f, fs_w[i]); 255 printf("fcsr: 0x%x\n", fcsr); 256 break; 257 case CVTWS: 258 UNOPfw("cvt.w.s"); 259 printf("%s %d %f\n", flt_round_op_names[op1], fd_w, fs_f[i]); 260 printf("fcsr: 0x%x\n", fcsr); 261 break; 262 case CVTWD: 263 UNOPdw("cvt.w.d"); 264 printf("%s %d %lf\n", flt_round_op_names[op1], fd_w, fs_d[i]); 265 printf("fcsr: 0x%x\n", fcsr); 266 break; 267 default: 268 printf("error\n"); 269 break; 270 } 271 } 272 } 273 return 0; 274} 275 276int main() 277{ 278 flt_dir_op_t op; 279 flt_round_op_t op1; 280 281 printf("-------------------------- %s --------------------------\n", 282 "test FPU Conversion Operations Using a Directed Rounding Mode"); 283 for (op = CEILWS; op <= TRUNCWD; op++) { 284 directedRoundingMode(op); 285 } 286 287 printf("-------------------------- %s --------------------------\n", 288 "test FPU Conversion Operations Using the FCSR Rounding Mode"); 289 for (op1 = CVTDS; op1 <= CVTWD; op1++) { 290 FCSRRoundingMode(op1); 291 } 292 return 0; 293} 294#else 295int main() { 296 return 0; 297} 298#endif 299 300