Home | History | Annotate | Download | only in mips32
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <signal.h>
      4 #include <setjmp.h>
      5 
      6 #define MAX_ARR 24
      7 #define PERROR \
      8         printf("This test is testing mips32r2 instructions in fpu64 mode.\n");
      9 #define FLAGS_RM_MASK 0xFFFFFFFF
     10 
     11 typedef enum {
     12    CVTLS,   CVTLD,   ROUNDLS, ROUNDLD,
     13    TRUNCLS, TRUNCLD, FLOORLS, FLOORLD,
     14    CEILLS,  CEILLD
     15 } flt_round_op_t;
     16 
     17 const char *flt_round_op_names[] = {
     18    "cvt.l.s",   "cvt.l.d",   "round.l.s", "round.l.d",
     19    "trunc.l.s", "trunc.l.d", "floor.l.s", "floor.l.d"
     20    "ceil.l.s",  "ceil.l.d"
     21 };
     22 
     23 typedef enum {
     24    TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t;
     25 char *round_mode_name[] = { "near", "zero", "+inf", "-inf" };
     26 
     27 const float fs_f[] = {
     28    0,         456.25,   3,          -1,
     29    1384.5,    -7.25,    1000000000, -5786.25,
     30    1752,      0.015625, 0.03125,    -248562.75,
     31    -45786.5,  456,      34.03125,   45786.75,
     32    1752065,   107,      -45667.25,  -7,
     33    -347856.5, 356047,   -1.25,      23.0625
     34 };
     35 
     36 const double fs_d[] = {
     37    0,         456.25,   3,          -1,
     38    1384.5,    -7.25,    1000000000, -5786.25,
     39    1752,      0.015625, 0.03125,    -24856226678933.75,
     40    -45786.5,  456,      34.03125,   45786.75,
     41    1752065,   107,      -45667.25,  -7,
     42    -347856.5, 356047,   -1.25,      23.0625
     43 };
     44 
     45 #define UNOPsl(op)                \
     46    __asm__ __volatile__(          \
     47       op"   $f0, %2"     "\n\t"   \
     48       "sdc1 $f0, 0(%1)"  "\n\t"   \
     49       "cfc1 %0,  $31"    "\n\t"   \
     50       : "=r" (fcsr)               \
     51       : "r"(&fd_l), "f"(fs_f[i])  \
     52       : "$f0"                     \
     53    );
     54 
     55 #define UNOPdl(op)                \
     56    __asm__ __volatile__(          \
     57       op"   $f0, %2"     "\n\t"   \
     58       "sdc1 $f0, 0(%1)"  "\n\t"   \
     59       "cfc1 %0,  $31"    "\n\t"   \
     60       : "=r" (fcsr)               \
     61       : "r"(&fd_l), "f"(fs_d[i])  \
     62       : "$f0"                     \
     63    );
     64 
     65 #define TEST_FPU64                \
     66    __asm__ __volatile__(          \
     67       "cvt.l.s $f0, $f0"  "\n\t"  \
     68       :                           \
     69       :                           \
     70       : "$f0"                     \
     71    );
     72 
     73 #if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64)
     74 void set_rounding_mode(round_mode_t mode)
     75 {
     76    switch(mode) {
     77       case TO_NEAREST:
     78          __asm__ volatile("ctc1 $zero, $31"  "\n\t");
     79          break;
     80       case TO_ZERO:
     81          __asm__ volatile("li    $t0, 0x1"  "\n\t"
     82                           "ctc1  $t0, $31"  "\n\t");
     83          break;
     84       case TO_PLUS_INFINITY:
     85           __asm__ volatile("li    $t0, 0x2"  "\n\t"
     86                            "ctc1  $t0, $31"  "\n\t");
     87          break;
     88       case TO_MINUS_INFINITY:
     89           __asm__ volatile("li    $t0, 0x3"  "\n\t"
     90                            "ctc1  $t0, $31"  "\n\t");
     91          break;
     92    }
     93 }
     94 
     95 struct test {
     96    void (*test)(void);
     97    int sig;
     98    int code;
     99 };
    100 
    101 static void handler(int sig)
    102 {
    103    PERROR;
    104    exit(0);
    105 }
    106 
    107 int FCSRRoundingMode(flt_round_op_t op)
    108 {
    109    long long int fd_l;
    110    int i;
    111    int fcsr = 0;
    112    round_mode_t rm;
    113    for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) {
    114       printf("roundig mode: %s\n", round_mode_name[rm]);
    115       for (i = 0; i < MAX_ARR; i++) {
    116          set_rounding_mode(rm);
    117          switch(op) {
    118             case CVTLS:
    119                UNOPsl("cvt.l.s");
    120                printf("%s %lld %f\n",
    121                       flt_round_op_names[op], fd_l, fs_f[i]);
    122                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    123                break;
    124             case CVTLD:
    125                UNOPdl("cvt.l.d");
    126                printf("%s %lld %lf\n",
    127                       flt_round_op_names[op], fd_l, fs_d[i]);
    128                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    129                break;
    130             case ROUNDLS:
    131                UNOPsl("round.l.s");
    132                printf("%s %lld %f\n",
    133                       flt_round_op_names[op], fd_l, fs_f[i]);
    134                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    135                break;
    136             case ROUNDLD:
    137                UNOPdl("round.l.d");
    138                printf("%s %lld %lf\n",
    139                       flt_round_op_names[op], fd_l, fs_d[i]);
    140                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    141                break;
    142             case TRUNCLS:
    143                UNOPsl("trunc.l.s");
    144                printf("%s %lld %f\n",
    145                       flt_round_op_names[op], fd_l, fs_f[i]);
    146                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    147                break;
    148             case TRUNCLD:
    149                UNOPdl("trunc.l.d");
    150                printf("%s %lld %lf\n",
    151                       flt_round_op_names[op], fd_l, fs_d[i]);
    152                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    153                break;
    154             case FLOORLS:
    155                UNOPsl("floor.l.s");
    156                printf("%s %lld %f\n",
    157                       flt_round_op_names[op], fd_l, fs_f[i]);
    158                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    159                break;
    160             case FLOORLD:
    161                UNOPdl("floor.l.d");
    162                printf("%s %lld %lf\n",
    163                       flt_round_op_names[op], fd_l, fs_d[i]);
    164                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    165                break;
    166             case CEILLS:
    167                UNOPsl("ceil.l.s");
    168                printf("%s %lld %f\n",
    169                       flt_round_op_names[op], fd_l, fs_f[i]);
    170                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    171                break;
    172             case CEILLD:
    173                UNOPdl("ceil.l.d");
    174                printf("%s %lld %lf\n",
    175                       flt_round_op_names[op], fd_l, fs_d[i]);
    176                printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
    177                break;
    178             default:
    179                printf("error\n");
    180                break;
    181          }
    182       }
    183    }
    184    return 0;
    185 }
    186 #endif
    187 
    188 
    189 int main()
    190 {
    191 #if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64)
    192    flt_round_op_t op;
    193    signal(SIGILL, handler);
    194    /* Test fpu64 mode. */
    195    TEST_FPU64;
    196    printf("-------------------------- %s --------------------------\n",
    197           "test FPU Conversion Operations Using the FCSR Rounding Mode");
    198    for (op = CVTLS; op <= CEILLD; op++)
    199       FCSRRoundingMode(op);
    200 #else
    201    PERROR;
    202 #endif
    203    return 0;
    204 }
    205