Home | History | Annotate | Download | only in mips32
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 typedef 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 
     16 const 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 
     28 typedef enum {
     29    TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t;
     30 char *round_mode_name[] = { "near", "zero", "+inf", "-inf" };
     31 
     32 const 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 
     41 const 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 
     50 const 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 
     59 const 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 
     92 void 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 
    125 int 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 
    226 int 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