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