Home | History | Annotate | Download | only in mips32
      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