Home | History | Annotate | Download | only in x86
      1 
      2 /* Derived from: */
      3 
      4 /*
      5  *  x86 CPU test
      6  *
      7  *  Copyright (c) 2003 Fabrice Bellard
      8  *
      9  *  This program is free software; you can redistribute it and/or modify
     10  *  it under the terms of the GNU General Public License as published by
     11  *  the Free Software Foundation; either version 2 of the License, or
     12  *  (at your option) any later version.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     22  */
     23 
     24 
     25 #include <stdlib.h>
     26 #include <stdio.h>
     27 #include <string.h>
     28 #include <inttypes.h>
     29 #include <math.h>
     30 
     31 /**********************************************/
     32 
     33 void test_fops(double a, double b)
     34 {
     35     printf("a=%f b=%f a+b=%f\n", a, b, a + b);
     36     printf("a=%f b=%f a-b=%f\n", a, b, a - b);
     37     printf("a=%f b=%f a*b=%f\n", a, b, a * b);
     38     printf("a=%f b=%f a/b=%f\n", a, b, a / b);
     39     printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
     40     printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
     41     printf("a=%f sin(a)=%f\n", a, sin(a));
     42     printf("a=%f cos(a)=%f\n", a, cos(a));
     43     printf("a=%f tan(a)=%f\n", a, tan(a));
     44     printf("a=%f log(a)=%f\n", a, log(a));
     45     printf("a=%f exp(a)=%f\n", a, exp(a));
     46     printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
     47     /* just to test some op combining */
     48     printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
     49     printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
     50     printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
     51 }
     52 #define CC_C    0x0001
     53 #define CC_P    0x0004
     54 #define CC_A    0x0010
     55 #define CC_Z    0x0040
     56 #define CC_S    0x0080
     57 #define CC_O    0x0800
     58 
     59 
     60 void test_fcmp(double a, double b)
     61 {
     62     printf("(%f<%f)=%d\n",
     63            a, b, a < b);
     64     printf("(%f<=%f)=%d\n",
     65            a, b, a <= b);
     66     printf("(%f==%f)=%d\n",
     67            a, b, a == b);
     68     printf("(%f>%f)=%d\n",
     69            a, b, a > b);
     70     printf("(%f<=%f)=%d\n",
     71            a, b, a >= b);
     72     {
     73         unsigned int eflags;
     74         /* test f(u)comi instruction */
     75         asm("fcomi %2, %1\n"
     76             "pushf\n"
     77             "pop %0\n"
     78             : "=r" (eflags)
     79             : "t" (a), "u" (b));
     80         printf("fcomi(%f %f)=%08x\n", a, b, eflags & (CC_Z | CC_P | CC_C));
     81     }
     82 }
     83 
     84 void test_fcvt(double a)
     85 {
     86     float fa;
     87     long double la;
     88     int16_t fpuc;
     89     int i;
     90     int64_t lla;
     91     int ia;
     92     int16_t wa;
     93     double ra;
     94 
     95     fa = a;
     96     la = a;
     97     printf("(float)%f = %f\n", a, fa);
     98     printf("(long double)%f = %Lf\n", a, la);
     99     printf("a=%016llx\n", *(long long *)&a);
    100     printf("la=%016llx %04x\n", *(long long *)&la,
    101            *(unsigned short *)((char *)(&la) + 8));
    102 
    103     /* test all roundings */
    104     asm volatile ("fstcw %0" : "=m" (fpuc));
    105     for(i=0;i<4;i++) {
    106       int16_t tmp = (fpuc & ~0x0c00) | (i << 10);
    107         asm volatile ("fldcw %0" : : "m" (tmp));
    108         asm volatile ("fists %0" : "=m" (wa) : "t" (a));
    109         asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
    110         asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
    111         asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
    112         asm volatile ("fldcw %0" : : "m" (fpuc));
    113         printf("(short)a = %d\n", wa);
    114         printf("(int)a = %d\n", ia);
    115         printf("(int64_t)a = %lld\n", lla);
    116         printf("rint(a) = %f\n", ra);
    117     }
    118 }
    119 
    120 #define TEST(N) \
    121     asm("fld" #N : "=t" (a)); \
    122     printf("fld" #N "= %f\n", a);
    123 
    124 void test_fconst(void)
    125 {
    126     double a;
    127     TEST(1);
    128     TEST(l2t);
    129     TEST(l2e);
    130     TEST(pi);
    131     TEST(lg2);
    132     TEST(ln2);
    133     TEST(z);
    134 }
    135 
    136 void test_fbcd(double a)
    137 {
    138     unsigned short bcd[5];
    139     double b;
    140 
    141     asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
    142     asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
    143     printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
    144            a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
    145 }
    146 
    147 #define TEST_ENV(env, save, restore)\
    148 {\
    149     memset((env), 0xaa, sizeof(*(env)));\
    150     for(i=0;i<5;i++)\
    151         asm volatile ("fldl %0" : : "m" (dtab[i]));\
    152     asm(save " %0\n" : : "m" (*(env)));\
    153     asm(restore " %0\n": : "m" (*(env)));\
    154     for(i=0;i<5;i++)\
    155         asm volatile ("fstpl %0" : "=m" (rtab[i]));\
    156     for(i=0;i<5;i++)\
    157         printf("res[%d]=%f\n", i, rtab[i]);\
    158     printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
    159            (env)->fpuc,\
    160            (env)->fpus & 0xff00,\
    161            (env)->fptag);\
    162 }
    163 
    164 void test_fenv(void)
    165 {
    166     struct __attribute__((packed)) {
    167         uint16_t fpuc;
    168         uint16_t dummy1;
    169         uint16_t fpus;
    170         uint16_t dummy2;
    171         uint16_t fptag;
    172         uint16_t dummy3;
    173         uint32_t ignored[4];
    174         long double fpregs[8];
    175     } float_env32;
    176     struct __attribute__((packed)) {
    177         uint16_t fpuc;
    178         uint16_t fpus;
    179         uint16_t fptag;
    180         uint16_t ignored[4];
    181         long double fpregs[8];
    182     } float_env16;
    183     double dtab[8];
    184     double rtab[8];
    185     int i;
    186 
    187     for(i=0;i<8;i++)
    188         dtab[i] = i + 1;
    189 
    190     TEST_ENV(&float_env16, "data16/fnstenv", "data16/fldenv");
    191     TEST_ENV(&float_env16, "data16/fnsave", "data16/frstor");
    192     TEST_ENV(&float_env32, "fnstenv", "fldenv");
    193     TEST_ENV(&float_env32, "fnsave", "frstor");
    194 
    195     /* test for ffree */
    196     for(i=0;i<5;i++)
    197         asm volatile ("fldl %0" : : "m" (dtab[i]));
    198     asm volatile("ffree %st(2)");
    199     asm volatile ("fnstenv %0\n" : : "m" (float_env32));
    200     asm volatile ("fninit");
    201     printf("fptag=%04x\n", float_env32.fptag);
    202 }
    203 
    204 
    205 #define TEST_FCMOV(a, b, eflags, CC)\
    206 {\
    207     double res;\
    208     asm("push %3\n"\
    209         "popf\n"\
    210         "fcmov" CC " %2, %0\n"\
    211         : "=t" (res)\
    212         : "0" (a), "u" (b), "g" (eflags));\
    213     printf("fcmov%s eflags=0x%04x-> %f\n", \
    214            CC, eflags, res);\
    215 }
    216 
    217 void test_fcmov(void)
    218 {
    219     double a, b;
    220     int eflags, i;
    221 
    222     a = 1.0;
    223     b = 2.0;
    224     for(i = 0; i < 4; i++) {
    225         eflags = 0;
    226         if (i & 1)
    227             eflags |= CC_C;
    228         if (i & 2)
    229             eflags |= CC_Z;
    230         TEST_FCMOV(a, b, eflags, "b");
    231         TEST_FCMOV(a, b, eflags, "e");
    232         TEST_FCMOV(a, b, eflags, "be");
    233         TEST_FCMOV(a, b, eflags, "nb");
    234         TEST_FCMOV(a, b, eflags, "ne");
    235         TEST_FCMOV(a, b, eflags, "nbe");
    236     }
    237     TEST_FCMOV(a, b, 0, "u");
    238     TEST_FCMOV(a, b, CC_P, "u");
    239     TEST_FCMOV(a, b, 0, "nu");
    240     TEST_FCMOV(a, b, CC_P, "nu");
    241 }
    242 
    243 void test_floats(void)
    244 {
    245     test_fops(2, 3);
    246     test_fops(1.4, -5);
    247     test_fcmp(2, -1);
    248     test_fcmp(2, 2);
    249     test_fcmp(2, 3);
    250     test_fcvt(0.5);
    251     test_fcvt(-0.5);
    252     test_fcvt(1.0/7.0);
    253     test_fcvt(-1.0/9.0);
    254     test_fcvt(32768);
    255     test_fcvt(-1e20);
    256     test_fconst();
    257 }
    258 
    259 int main ( void )
    260 {
    261   test_floats();
    262   return 0;
    263 }
    264