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.25, 3, -1,
     36    1384.5, -7.25, 1000000000, -5786.25,
     37    1752, 0.015625, 0.03125, -248562.75,
     38    -45786.5, 456, 34.03125, 45786.75,
     39    1752065, 107, -45667.25, -7,
     40    -347856.5, 356047, -1.25, 23.0625
     41 };
     42 
     43 const float fs_f[] = {
     44    0, 456.25, 3, -1,
     45    1384.5, -7.25, 1000000000, -5786.25,
     46    1752, 0.015625, 0.03125, -248562.75,
     47    -45786.5, 456, 34.03125, 45786.75,
     48    1752065, 107, -45667.25, -7,
     49    -347856.5, 356047, -1.25, 23.0625
     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(op"   %1, %2, %3"  "\n\t"  \
     63                          "cfc1 %0, $31"     "\n\t"  \
     64                          : "=r" (fcsr), "=f"(fd)    \
     65                          : "f"(f) , "f"(fB));
     66 
     67 #define UNOPdd(op)                                  \
     68         fd_d = 0;                                   \
     69         __asm__ volatile(op"   %1, %2"      "\n\t"  \
     70                          "cfc1 %0, $31"     "\n\t"  \
     71                          : "=r" (fcsr), "=f"(fd_d)  \
     72                          : "f"(fs_d[i]));
     73 
     74 #define UNOPff(op)                                  \
     75         fd_f = 0;                                   \
     76         __asm__ volatile(op" %1, %2"        "\n\t"  \
     77                          "cfc1 %0, $31"     "\n\t"  \
     78                          : "=r" (fcsr), "=f"(fd_f)  \
     79                          : "f"(fs_f[i]));
     80 
     81 #define UNOPfd(op)                                  \
     82         fd_d = 0;                                   \
     83         __asm__ volatile(op"   %1, %2"   "\n\t"     \
     84                          "cfc1 %0, $31"  "\n\t"     \
     85                          : "=r" (fcsr), "=f"(fd_d)  \
     86                          : "f"(fs_f[i]));
     87 
     88 #define UNOPdf(op)                                  \
     89         fd_f = 0;                                   \
     90         __asm__ volatile(op"   %1, %2"   "\n\t"     \
     91                          "cfc1 %0, $31"  "\n\t"     \
     92                          : "=r" (fcsr), "=f"(fd_f)  \
     93                          : "f"(fs_d[i]));
     94 
     95 #define UNOPfw(op)                                  \
     96         fd_w = 0;                                   \
     97         __asm__ volatile(op"   $f0, %2"   "\n\t"    \
     98                          "mfc1 %1,  $f0"  "\n\t"    \
     99                          "cfc1 %0, $31"   "\n\t"    \
    100                          : "=r" (fcsr), "=r"(fd_w)  \
    101                          : "f"(fs_f[i])             \
    102                          : "$f0");
    103 
    104 #define UNOPdw(op)                                  \
    105         fd_w = 0;                                   \
    106         __asm__ volatile(op" $f0, %2"    "\n\t"     \
    107                          "mfc1 %1, $f0"  "\n\t"     \
    108                          "cfc1 %0, $31"  "\n\t"     \
    109                          : "=r" (fcsr), "=r"(fd_w)  \
    110                          : "f"(fs_d[i])             \
    111                          : "$f0");
    112 
    113 #define UNOPwd(op)                                  \
    114         fd_d = 0;                                   \
    115         __asm__ volatile("mtc1 %2, $f0"  "\n\t"     \
    116                          op"   %1, $f0"  "\n\t"     \
    117                          "cfc1 %0, $31"  "\n\t"     \
    118                          : "=r" (fcsr), "=f"(fd_d)  \
    119                          : "r"(fs_w[i])             \
    120                          : "$f0", "$f1");
    121 
    122 #define UNOPwf(op)                                  \
    123         fd_f = 0;                                   \
    124         __asm__ volatile("mtc1 %2, $f0"  "\n\t"     \
    125                          op"   %1, $f0"  "\n\t"     \
    126                          "cfc1 %0, $31"  "\n\t"     \
    127                          : "=r" (fcsr), "=f"(fd_f)  \
    128                          : "r"(fs_w[i])             \
    129                          : "$f0");
    130 
    131 void set_rounding_mode(round_mode_t mode)
    132 {
    133    switch(mode) {
    134       case TO_NEAREST:
    135          __asm__ volatile("ctc1 $zero, $31"  "\n\t");
    136          break;
    137       case TO_ZERO:
    138          __asm__ volatile("li    $t0, 0x1"  "\n\t"
    139                           "ctc1  $t0, $31"  "\n\t");
    140          break;
    141       case TO_PLUS_INFINITY:
    142           __asm__ volatile("li    $t0, 0x2"  "\n\t"
    143                            "ctc1  $t0, $31"  "\n\t");
    144          break;
    145       case TO_MINUS_INFINITY:
    146           __asm__ volatile("li    $t0, 0x3"  "\n\t"
    147                            "ctc1  $t0, $31"  "\n\t");
    148          break;
    149    }
    150 }
    151 
    152 int directedRoundingMode(flt_dir_op_t op) {
    153    int fd_w = 0;
    154    int i;
    155    int fcsr = 0;
    156    round_mode_t rm = TO_NEAREST;
    157    for (i = 0; i < 24; i++) {
    158       set_rounding_mode(rm);
    159       switch(op) {
    160          case CEILWS:
    161               UNOPfw("ceil.w.s");
    162               printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
    163               printf("fcsr: 0x%x\n", fcsr);
    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               printf("fcsr: 0x%x\n", fcsr);
    169               break;
    170          case FLOORWS:
    171               UNOPfw("floor.w.s");
    172               printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
    173               printf("fcsr: 0x%x\n", fcsr);
    174               break;
    175          case FLOORWD:
    176               UNOPdw("floor.w.d");
    177               printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
    178               printf("fcsr: 0x%x\n", fcsr);
    179               break;
    180          case ROUNDWS:
    181               UNOPfw("round.w.s");
    182               printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
    183               printf("fcsr: 0x%x\n", fcsr);
    184               break;
    185          case ROUNDWD:
    186               UNOPdw("round.w.d");
    187               printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
    188               printf("fcsr: 0x%x\n", fcsr);
    189               break;
    190          case TRUNCWS:
    191               UNOPfw("trunc.w.s");
    192               printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
    193               printf("fcsr: 0x%x\n", fcsr);
    194               break;
    195          case TRUNCWD:
    196               UNOPdw("trunc.w.d");
    197               printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
    198               printf("fcsr: 0x%x\n", fcsr);
    199               break;
    200         default:
    201             printf("error\n");
    202             break;
    203         }
    204     }
    205    return 0;
    206 }
    207 
    208 int FCSRRoundingMode(flt_round_op_t op1)
    209 {
    210    double fd_d = 0;
    211    float fd_f = 0;
    212    int fd_w = 0;
    213    int i;
    214    int fcsr = 0;
    215    round_mode_t rm;
    216    for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) {
    217       set_rounding_mode(rm);
    218       printf("roundig mode: %s\n", round_mode_name[rm]);
    219       for (i = 0; i < 24; i++) {
    220          set_rounding_mode(rm);
    221          switch(op1) {
    222             case CVTDS:
    223                  UNOPfd("cvt.d.s");
    224                  printf("%s %lf %lf\n", flt_round_op_names[op1], fd_d, fs_f[i]);
    225                  printf("fcsr: 0x%x\n", fcsr);
    226                  break;
    227             case CVTDW:
    228                  UNOPwd("cvt.d.w");
    229                  printf("%s %lf %d\n", flt_round_op_names[op1], fd_d, fs_w[i]);
    230                  printf("fcsr: 0x%x\n", fcsr);
    231                  break;
    232             case CVTSD:
    233                  UNOPdf("cvt.s.d");
    234                  printf("%s %f %lf\n", flt_round_op_names[op1], fd_f, fs_d[i]);
    235                  printf("fcsr: 0x%x\n", fcsr);
    236                  break;
    237             case CVTSW:
    238                  UNOPwf("cvt.s.w");
    239                  printf("%s %f %d\n", flt_round_op_names[op1], fd_f, fs_w[i]);
    240                  printf("fcsr: 0x%x\n", fcsr);
    241                  break;
    242             case CVTWS:
    243                  UNOPfw("cvt.w.s");
    244                  printf("%s %d %f\n", flt_round_op_names[op1], fd_w, fs_f[i]);
    245                  printf("fcsr: 0x%x\n", fcsr);
    246                  break;
    247             case CVTWD:
    248                  UNOPdw("cvt.w.d");
    249                  printf("%s %d %lf\n", flt_round_op_names[op1], fd_w, fs_d[i]);
    250                  printf("fcsr: 0x%x\n", fcsr);
    251                  break;
    252             default:
    253                  printf("error\n");
    254                  break;
    255          }
    256       }
    257    }
    258    return 0;
    259 }
    260 
    261 int main()
    262 {
    263    flt_dir_op_t op;
    264    flt_round_op_t op1;
    265 
    266    printf("-------------------------- %s --------------------------\n",
    267         "test FPU Conversion Operations Using a Directed Rounding Mode");
    268    for (op = CEILWS; op <= TRUNCWD; op++) {
    269       directedRoundingMode(op);
    270    }
    271 
    272    printf("-------------------------- %s --------------------------\n",
    273         "test FPU Conversion Operations Using the FCSR Rounding Mode");
    274    for (op1 = CVTDS; op1 <= CVTWD; op1++) {
    275       FCSRRoundingMode(op1);
    276    }
    277    return 0;
    278 }
    279 
    280