Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame^] | 1 | #if defined(__mips_hard_float) |
| 2 | |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 3 | #include <stdio.h> |
| 4 | |
| 5 | typedef enum { |
| 6 | CEILWS=0, CEILWD, |
| 7 | FLOORWS, FLOORWD, |
| 8 | ROUNDWS, ROUNDWD, |
| 9 | TRUNCWS, TRUNCWD |
| 10 | } flt_dir_op_t; |
| 11 | |
| 12 | typedef enum { |
| 13 | CVTDS, CVTDW, |
| 14 | CVTSD, CVTSW, |
| 15 | CVTWS, CVTWD |
| 16 | } flt_round_op_t; |
| 17 | |
| 18 | typedef enum { |
| 19 | TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t; |
| 20 | char *round_mode_name[] = { "near", "zero", "+inf", "-inf" }; |
| 21 | |
| 22 | |
| 23 | const 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 | |
| 30 | const 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 | |
| 36 | const double fs_d[] = { |
dejanj | 34ff174 | 2013-12-05 14:05:25 +0000 | [diff] [blame] | 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, |
dejanj | 8a9c20b | 2013-09-24 07:00:46 +0000 | [diff] [blame] | 42 | -347856.5, 356047, -1.25, 23.0625 |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 43 | }; |
| 44 | |
| 45 | const float fs_f[] = { |
dejanj | 8a9c20b | 2013-09-24 07:00:46 +0000 | [diff] [blame] | 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 |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 52 | }; |
| 53 | |
| 54 | const 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, |
dejanj | 8a9c20b | 2013-09-24 07:00:46 +0000 | [diff] [blame] | 60 | -347856, 0x80000000, 0xFFFFFFF, 23 |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 61 | }; |
| 62 | |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 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)); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 68 | |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 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])); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 75 | |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 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])); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 82 | |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 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])); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 89 | |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 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])); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 96 | |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 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"); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 105 | |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 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"); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 114 | |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 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"); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 123 | |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 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"); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 132 | |
| 133 | void set_rounding_mode(round_mode_t mode) |
| 134 | { |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 135 | switch(mode) { |
| 136 | case TO_NEAREST: |
dejanj | 24f0c3a | 2014-02-19 11:57:22 +0000 | [diff] [blame] | 137 | __asm__ volatile("ctc1 $zero, $31" "\n\t"); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 138 | break; |
| 139 | case TO_ZERO: |
dejanj | 24f0c3a | 2014-02-19 11:57:22 +0000 | [diff] [blame] | 140 | __asm__ volatile("li $t0, 0x1" "\n\t" |
| 141 | "ctc1 $t0, $31" "\n\t"); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 142 | break; |
| 143 | case TO_PLUS_INFINITY: |
dejanj | 24f0c3a | 2014-02-19 11:57:22 +0000 | [diff] [blame] | 144 | __asm__ volatile("li $t0, 0x2" "\n\t" |
| 145 | "ctc1 $t0, $31" "\n\t"); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 146 | break; |
| 147 | case TO_MINUS_INFINITY: |
dejanj | 24f0c3a | 2014-02-19 11:57:22 +0000 | [diff] [blame] | 148 | __asm__ volatile("li $t0, 0x3" "\n\t" |
| 149 | "ctc1 $t0, $31" "\n\t"); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 150 | break; |
| 151 | } |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 152 | } |
| 153 | |
Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame^] | 154 | void 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 | |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 165 | int directedRoundingMode(flt_dir_op_t op) { |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 166 | int fd_w = 0; |
| 167 | int i; |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 168 | int fcsr = 0; |
dejanj | 34ff174 | 2013-12-05 14:05:25 +0000 | [diff] [blame] | 169 | round_mode_t rm = TO_NEAREST; |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 170 | for (i = 0; i < 24; i++) { |
Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame^] | 171 | clear_fcc(); |
dejanj | 34ff174 | 2013-12-05 14:05:25 +0000 | [diff] [blame] | 172 | set_rounding_mode(rm); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 177 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 182 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 187 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 192 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 197 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 202 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 207 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 212 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 213 | break; |
| 214 | default: |
| 215 | printf("error\n"); |
| 216 | break; |
| 217 | } |
| 218 | } |
| 219 | return 0; |
| 220 | } |
| 221 | |
dejanj | 34ff174 | 2013-12-05 14:05:25 +0000 | [diff] [blame] | 222 | int FCSRRoundingMode(flt_round_op_t op1) |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 223 | { |
| 224 | double fd_d = 0; |
| 225 | float fd_f = 0; |
| 226 | int fd_w = 0; |
| 227 | int i; |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 228 | int fcsr = 0; |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 229 | round_mode_t rm; |
dejanj | 34ff174 | 2013-12-05 14:05:25 +0000 | [diff] [blame] | 230 | for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) { |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 231 | set_rounding_mode(rm); |
| 232 | printf("roundig mode: %s\n", round_mode_name[rm]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 233 | for (i = 0; i < 24; i++) { |
Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame^] | 234 | clear_fcc(); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 240 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 245 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 250 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 255 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 260 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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]); |
dejanj | 4164a81 | 2013-09-18 10:08:23 +0000 | [diff] [blame] | 265 | printf("fcsr: 0x%x\n", fcsr); |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 266 | break; |
| 267 | default: |
| 268 | printf("error\n"); |
| 269 | break; |
| 270 | } |
| 271 | } |
| 272 | } |
| 273 | return 0; |
| 274 | } |
| 275 | |
| 276 | int 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 | } |
dejanj | 34ff174 | 2013-12-05 14:05:25 +0000 | [diff] [blame] | 286 | |
sewardj | e584b0e | 2012-06-07 09:32:40 +0000 | [diff] [blame] | 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 | } |
Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame^] | 294 | #else |
| 295 | int main() { |
| 296 | return 0; |
| 297 | } |
| 298 | #endif |
petarj | 4931c0d | 2012-07-16 14:07:47 +0000 | [diff] [blame] | 299 | |