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