FPUarithmetic.c revision 34ff174f3cef6e6058385c0a404572d5e8e5c67c
1#include <stdio.h> 2#include <stdlib.h> 3 4typedef enum { 5 ABSS=0, ABSD, 6 ADDS, ADDD, 7 DIVS, DIVD, 8 MULS, MULD, 9 NEGS, NEGD, 10 SQRTS, SQRTD, 11 SUBS, SUBD, 12 RECIPS, RECIPD, 13 RSQRTS, RSQRTD 14} flt_art_op_t; 15 16const char *flt_art_op_names[] = { 17 "abs.s", "abs.d", 18 "add.s", "add.d", 19 "div.s", "div.d", 20 "mul.s", "mul.d", 21 "neg.s", "neg.d", 22 "sqrt.s", "sqrt.d", 23 "sub.s", "sub.d", 24 "recip.s", "recip.d", 25 "rsqrt.s", "rsqrt.d" 26}; 27 28typedef enum { 29 TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t; 30char *round_mode_name[] = { "near", "zero", "+inf", "-inf" }; 31 32const double fs_d[] = { 33 0, 456.25, 3, -1, 34 1384.5, -7.25, 1000000000, -5786.5, 35 1752, 0.015625, 0.03125, -248562.75, 36 456, -45786.5, 34.03125, 45786.75, 37 1752065, 107, -45667.25, -7, 38 -347856.5, 356047.5, -1.0, 23.0625 39}; 40 41const double ft_d[] = { 42 -456.25, -45786.5, 34.03125, 45786.75, 43 1752065, 107, -45667.25, -7.25, 44 -347856.5, 356047.5, -1.0, 23.0625, 45 0, 456.25, 3, -1, 46 1384.5, -7, 1000000000, -5786.5, 47 1752, 0.015625, 0.03125, -248562.75 48}; 49 50const float fs_f[] = { 51 0, 456.25, 3, -1, 52 1384.5, -7.25, 1000000000, -5786.5, 53 1752, 0.015625, 0.03125, -248562.75, 54 456, -45786.5, 34.03125, 45786.75, 55 1752065, 107, -45667.25, -7, 56 -347856.5, 356047.5, -1.0, 23.0625 57}; 58 59const float ft_f[] = { 60 -456.25, -4578.5, 34.03125, 4578.75, 61 175, 107, -456.25, -7.25, 62 -3478.5, 356.5, -1.0, 23.0625, 63 0, 456.25, 3, -1, 64 1384.5, -7, 100, -5786.5, 65 1752, 0.015625, 0.03125, -248562.75 66}; 67 68#define UNOPdd(op) \ 69 fd_d = 0; \ 70 __asm__ volatile( \ 71 op" %0, %1\n\t" \ 72 : "=f"(fd_d) : "f"(fs_d[i])); 73 74#define UNOPff(op) \ 75 fd_f = 0; \ 76 __asm__ volatile( \ 77 op" %0, %1\n\t" \ 78 : "=f"(fd_f) : "f"(fs_f[i])); 79 80#define BINOPf(op) \ 81 fd_f = 0; \ 82 __asm__ volatile( \ 83 op" %0, %1, %2\n\t" \ 84 : "=f"(fd_f) : "f"(fs_f[i]) , "f"(ft_f[i])); 85 86#define BINOPd(op) \ 87 fd_d = 0; \ 88 __asm__ volatile( \ 89 op" %0, %1, %2\n\t" \ 90 : "=f"(fd_d) : "f"(fs_d[i]) , "f"(ft_d[i])); 91 92void set_rounding_mode(round_mode_t mode) 93{ 94 switch(mode) { 95 case TO_NEAREST: 96 __asm__ volatile("cfc1 $t0, $31\n\t" 97 "srl $t0, 2\n\t" 98 "sll $t0, 2\n\t" 99 "ctc1 $t0, $31\n\t"); 100 break; 101 case TO_ZERO: 102 __asm__ volatile("cfc1 $t0, $31\n\t" 103 "srl $t0, 2\n\t" 104 "sll $t0, 2\n\t" 105 "addiu $t0, 1\n\t" 106 "ctc1 $t0, $31\n\t"); 107 break; 108 case TO_PLUS_INFINITY: 109 __asm__ volatile("cfc1 $t0, $31\n\t" 110 "srl $t0, 2\n\t" 111 "sll $t0, 2\n\t" 112 "addiu $t0, 2\n\t" 113 "ctc1 $t0, $31\n\t"); 114 break; 115 case TO_MINUS_INFINITY: 116 __asm__ volatile("cfc1 $t0, $31\n\t" 117 "srl $t0, 2\n\t" 118 "sll $t0, 2\n\t" 119 "addiu $t0, 3\n\t" 120 "ctc1 $t0, $31\n\t"); 121 break; 122 } 123} 124 125int arithmeticOperations(flt_art_op_t op) 126{ 127 double fd_d = 0; 128 float fd_f = 0; 129 int i = 0; 130 round_mode_t rm; 131 for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) { 132 set_rounding_mode(rm); 133 printf("rounding mode: %s\n", round_mode_name[rm]); 134 for (i = 0; i < 24; i++) 135 { 136 switch(op) { 137 case ABSS: 138 UNOPff("abs.s"); 139 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]); 140 break; 141 case ABSD: 142 UNOPdd("abs.d"); 143 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]); 144 break; 145 case ADDS: 146 BINOPf("add.s"); 147 printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]); 148 break; 149 case ADDD: 150 BINOPd("add.d"); 151 printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]); 152 break; 153 case DIVS: 154 BINOPf("div.s"); 155 printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]); 156 break; 157 case DIVD: 158 BINOPd("div.d"); 159 printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]); 160 break; 161 case MULS: 162 BINOPf("mul.s"); 163 printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]); 164 break; 165 case MULD: 166 BINOPd("mul.d"); 167 printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]); 168 break; 169 case NEGS: 170 UNOPff("neg.s"); 171 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]); 172 break; 173 case NEGD: 174 UNOPdd("neg.d"); 175 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]); 176 break; 177 case SQRTS: 178 UNOPff("sqrt.s"); 179 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]); 180 break; 181 case SQRTD: 182 UNOPdd("sqrt.d"); 183 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]); 184 break; 185 case SUBS: 186 BINOPf("sub.s"); 187 printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]); 188 break; 189 case SUBD: 190 BINOPd("sub.d"); 191 printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]); 192 break; 193 case RECIPS: 194#if (__mips==32) && (__mips_isa_rev>=2) 195 UNOPff("recip.s"); 196 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]); 197#endif 198 break; 199 case RECIPD: 200#if (__mips==32) && (__mips_isa_rev>=2) 201 UNOPdd("recip.d"); 202 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]); 203#endif 204 break; 205 case RSQRTS: 206#if (__mips==32) && (__mips_isa_rev>=2) 207 UNOPff("rsqrt.s"); 208 printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]); 209#endif 210 break; 211 case RSQRTD: 212#if (__mips==32) && (__mips_isa_rev>=2) 213 UNOPdd("rsqrt.d"); 214 printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]); 215#endif 216 break; 217 default: 218 printf("error\n"); 219 break; 220 } 221 } 222 } 223 return 0; 224} 225 226int main() 227{ 228 flt_art_op_t op; 229 230 printf("-------------------------- %s --------------------------\n", 231 "test FPU Arithmetic Operations"); 232 for (op = ABSS; op <= RECIPD; op++) { 233 arithmeticOperations(op); 234 } 235 236 return 0; 237} 238 239