1eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 2eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov/* Tests out of range handling for FSIN, FCOS, FSINCOS and FPTAN. Be 3eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov careful with the inline assembly -- this program is compiled as 4eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov both a 32-bit and 64-bit test. */ 5eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 6eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <stdio.h> 7eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <string.h> 8eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <assert.h> 9eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 10eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovtypedef unsigned short int UShort; 11eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovtypedef unsigned int UInt; 12eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovtypedef double Double; 13eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovtypedef unsigned long long int ULong; 14eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 15eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovtypedef struct { Double arg; Double st0; Double st1; UShort fpusw; } Res; 16eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 17eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#define SHIFT_C3 14 18eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#define SHIFT_C2 10 19eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#define SHIFT_C1 9 20eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#define SHIFT_C0 8 21eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 22eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 23eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#define my_offsetof(type,memb) ((int)(unsigned long int)&((type*)0)->memb) 24eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 25eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid do_fsin ( /*OUT*/Res* r, double d ) 26eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov{ 27eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,arg) == 0); 28eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,st0) == 8); 29eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,st1) == 16); 30eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,fpusw) == 24); 31eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov memset(r, 0, sizeof(*r)); 32eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov r->arg = d; 33eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov __asm__ __volatile__( 34eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "finit" "\n\t" 35eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fldpi" "\n\t" 36eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fldl 0(%0)" "\n\t" // .arg 37eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fsin" "\n\t" 38eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstsw %%ax" "\n\t" 39eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstpl 8(%0)" "\n\t" // .st0 40eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstpl 16(%0)" "\n\t" // .st1 41eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "movw %%ax, 24(%0)" "\n\t" // .fpusw 42eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "finit" "\n" 43eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : : "r"(r) : "eax","cc","memory" 44eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ); 45eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 46eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 47eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid do_fcos ( /*OUT*/Res* r, double d ) 48eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov{ 49eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,arg) == 0); 50eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,st0) == 8); 51eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,st1) == 16); 52eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,fpusw) == 24); 53eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov memset(r, 0, sizeof(*r)); 54eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov r->arg = d; 55eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov __asm__ __volatile__( 56eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "finit" "\n\t" 57eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fldpi" "\n\t" 58eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fldl 0(%0)" "\n\t" // .arg 59eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fcos" "\n\t" 60eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstsw %%ax" "\n\t" 61eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstpl 8(%0)" "\n\t" // .st0 62eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstpl 16(%0)" "\n\t" // .st1 63eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "movw %%ax, 24(%0)" "\n\t" // .fpusw 64eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "finit" "\n" 65eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : : "r"(r) : "eax","cc","memory" 66eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ); 67eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 68eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 69eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid do_fsincos ( /*OUT*/Res* r, double d ) 70eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov{ 71eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,arg) == 0); 72eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,st0) == 8); 73eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,st1) == 16); 74eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,fpusw) == 24); 75eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov memset(r, 0, sizeof(*r)); 76eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov r->arg = d; 77eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov __asm__ __volatile__( 78eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "finit" "\n\t" 79eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fldpi" "\n\t" 80eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fldl 0(%0)" "\n\t" // .arg 81eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fsincos" "\n\t" 82eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstsw %%ax" "\n\t" 83eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstpl 8(%0)" "\n\t" // .st0 84eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstpl 16(%0)" "\n\t" // .st1 85eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "movw %%ax, 24(%0)" "\n\t" // .fpusw 86eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "finit" "\n" 87eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : : "r"(r) : "eax","cc","memory" 88eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ); 89eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 90eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 91eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid do_fptan ( /*OUT*/Res* r, double d ) 92eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov{ 93eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,arg) == 0); 94eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,st0) == 8); 95eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,st1) == 16); 96eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov assert(my_offsetof(Res,fpusw) == 24); 97eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov memset(r, 0, sizeof(*r)); 98eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov r->arg = d; 99eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov __asm__ __volatile__( 100eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "finit" "\n\t" 101eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fldpi" "\n\t" 102eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fldl 0(%0)" "\n\t" // .arg 103eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fptan" "\n\t" 104eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstsw %%ax" "\n\t" 105eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstpl 8(%0)" "\n\t" // .st0 106eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "fstpl 16(%0)" "\n\t" // .st1 107eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "movw %%ax, 24(%0)" "\n\t" // .fpusw 108eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "finit" "\n" 109eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : : "r"(r) : "eax","cc","memory" 110eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ); 111eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 112eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 113eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 114eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid try ( char* name, void(*fn)(Res*,double), double d ) 115eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov{ 116eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov Res r; 117eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov fn(&r, d); 118eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov // Mask out all except C2 (range) 119eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov r.fpusw &= (1 << SHIFT_C2); 120eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov printf("%s %16e --> %16e %16e %04x\n", 121eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov name, r.arg, r.st0, r.st1, (UInt)r.fpusw); 122eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 123eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 124eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovint main ( void ) 125eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov{ 126eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov Double limit = 9223372036854775808.0; // 2^63 127eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 128eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov char* names[4] = { "fsin ", "fcos ", "fsincos", "fptan " }; 129eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov void(*fns[4])(Res*,double) = { do_fsin, do_fcos, do_fsincos, do_fptan }; 130eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 131eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov int i; 132eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov for (i = 0; i < 4; i++) { 133eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov char* name = names[i]; 134eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov void (*fn)(Res*,double) = fns[i]; 135eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 136eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, 0.0 ); 137eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, 0.123 ); 138eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, -0.456 ); 139eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, 37.0 ); 140eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, -53.0 ); 141eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov printf("\n"); 142eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 143eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, limit * 0.900000 ); 144eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, limit * 0.999999 ); 145eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, limit * 1.000000 ); 146eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, limit * 1.000001 ); 147eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, limit * 1.100000 ); 148eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov printf("\n"); 149eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 150eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, -limit * 0.900000 ); 151eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, -limit * 0.999999 ); 152eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, -limit * 1.000000 ); 153eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, -limit * 1.000001 ); 154eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov try( name, fn, -limit * 1.100000 ); 155eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov printf("\n"); 156eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 157eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 158eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return 0; 159eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 160