aboutsummaryrefslogtreecommitdiff
path: root/tests/tcg/loongarch64/test_fclass.c
blob: 7ba1d2c151047284224075e6056f4fb9e9a0798b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdio.h>

/* float class */
#define FLOAT_CLASS_SIGNALING_NAN      0x001
#define FLOAT_CLASS_QUIET_NAN          0x002
#define FLOAT_CLASS_NEGATIVE_INFINITY  0x004
#define FLOAT_CLASS_NEGATIVE_NORMAL    0x008
#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
#define FLOAT_CLASS_NEGATIVE_ZERO      0x020
#define FLOAT_CLASS_POSITIVE_INFINITY  0x040
#define FLOAT_CLASS_POSITIVE_NORMAL    0x080
#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
#define FLOAT_CLASS_POSITIVE_ZERO      0x200

#define TEST_FCLASS(N)                            \
void test_fclass_##N(long s)                      \
{                                                 \
    double fd;                                    \
    long rd;                                      \
                                                  \
    asm volatile("fclass."#N" %0, %2\n\t"         \
                 "movfr2gr."#N" %1, %2\n\t"       \
                    : "=f"(fd), "=r"(rd)          \
                    : "f"(s)                      \
                    : );                          \
    switch (rd) {                                 \
    case FLOAT_CLASS_SIGNALING_NAN:               \
    case FLOAT_CLASS_QUIET_NAN:                   \
    case FLOAT_CLASS_NEGATIVE_INFINITY:           \
    case FLOAT_CLASS_NEGATIVE_NORMAL:             \
    case FLOAT_CLASS_NEGATIVE_SUBNORMAL:          \
    case FLOAT_CLASS_NEGATIVE_ZERO:               \
    case FLOAT_CLASS_POSITIVE_INFINITY:           \
    case FLOAT_CLASS_POSITIVE_NORMAL:             \
    case FLOAT_CLASS_POSITIVE_SUBNORMAL:          \
    case FLOAT_CLASS_POSITIVE_ZERO:               \
        break;                                    \
    default:                                      \
        printf("fclass."#N" test failed.\n");     \
        break;                                    \
    }                                             \
}

/*
 *  float format
 *  type     |    S  | Exponent  |  Fraction    |  example value
 *                31 | 30 --23   | 22  | 21 --0 |
 *                               | bit |
 *  SNAN         0/1 |   0xFF    | 0   |  !=0   |  0x7FBFFFFF
 *  QNAN         0/1 |   0xFF    | 1   |        |  0x7FCFFFFF
 *  -infinity     1  |   0xFF    |     0        |  0xFF800000
 *  -normal       1  | [1, 0xFE] | [0, 0x7FFFFF]|  0xFF7FFFFF
 *  -subnormal    1  |    0      |    !=0       |  0x807FFFFF
 *  -0            1  |    0      |     0        |  0x80000000
 *  +infinity     0  |   0xFF    |     0        |  0x7F800000
 *  +normal       0  | [1, 0xFE] | [0, 0x7FFFFF]|  0x7F7FFFFF
 *  +subnormal    0  |    0      |    !=0       |  0x007FFFFF
 *  +0            0  |    0      |     0        |  0x00000000
 */

long float_snan = 0x7FBFFFFF;
long float_qnan = 0x7FCFFFFF;
long float_neg_infinity = 0xFF800000;
long float_neg_normal = 0xFF7FFFFF;
long float_neg_subnormal = 0x807FFFFF;
long float_neg_zero = 0x80000000;
long float_post_infinity = 0x7F800000;
long float_post_normal = 0x7F7FFFFF;
long float_post_subnormal = 0x007FFFFF;
long float_post_zero = 0x00000000;

/*
 * double format
 *  type     |    S  | Exponent  |  Fraction     |  example value
 *                63 | 62  -- 52 | 51  | 50 -- 0 |
 *                               | bit |
 *  SNAN         0/1 |  0x7FF    | 0   |  !=0    | 0x7FF7FFFFFFFFFFFF
 *  QNAN         0/1 |  0x7FF    | 1   |         | 0x7FFFFFFFFFFFFFFF
 * -infinity      1  |  0x7FF    |    0          | 0xFFF0000000000000
 * -normal        1  |[1, 0x7FE] |               | 0xFFEFFFFFFFFFFFFF
 * -subnormal     1  |   0       |   !=0         | 0x8007FFFFFFFFFFFF
 * -0             1  |   0       |    0          | 0x8000000000000000
 * +infinity      0  |  0x7FF    |    0          | 0x7FF0000000000000
 * +normal        0  |[1, 0x7FE] |               | 0x7FEFFFFFFFFFFFFF
 * +subnormal     0  |  0        |   !=0         | 0x000FFFFFFFFFFFFF
 * +0             0  |  0        |   0           | 0x0000000000000000
 */

long double_snan = 0x7FF7FFFFFFFFFFFF;
long double_qnan = 0x7FFFFFFFFFFFFFFF;
long double_neg_infinity = 0xFFF0000000000000;
long double_neg_normal = 0xFFEFFFFFFFFFFFFF;
long double_neg_subnormal = 0x8007FFFFFFFFFFFF;
long double_neg_zero = 0x8000000000000000;
long double_post_infinity = 0x7FF0000000000000;
long double_post_normal = 0x7FEFFFFFFFFFFFFF;
long double_post_subnormal = 0x000FFFFFFFFFFFFF;
long double_post_zero = 0x0000000000000000;

TEST_FCLASS(s)
TEST_FCLASS(d)

int main()
{
    /* fclass.s */
    test_fclass_s(float_snan);
    test_fclass_s(float_qnan);
    test_fclass_s(float_neg_infinity);
    test_fclass_s(float_neg_normal);
    test_fclass_s(float_neg_subnormal);
    test_fclass_s(float_neg_zero);
    test_fclass_s(float_post_infinity);
    test_fclass_s(float_post_normal);
    test_fclass_s(float_post_subnormal);
    test_fclass_s(float_post_zero);

    /* fclass.d */
    test_fclass_d(double_snan);
    test_fclass_d(double_qnan);
    test_fclass_d(double_neg_infinity);
    test_fclass_d(double_neg_normal);
    test_fclass_d(double_neg_subnormal);
    test_fclass_d(double_neg_zero);
    test_fclass_d(double_post_infinity);
    test_fclass_d(double_post_normal);
    test_fclass_d(double_post_subnormal);
    test_fclass_d(double_post_zero);

    return 0;
}