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