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 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 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 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 241 int main() { 242 return 0; 243 } 244 #endif 245