1 2 #include <stdio.h> 3 #include <assert.h> 4 5 6 /* ------------------------------------------------- */ 7 8 typedef unsigned char UChar; 9 typedef unsigned short UShort; 10 typedef unsigned int UInt; 11 typedef unsigned long long int ULong; 12 13 typedef signed char Char; 14 typedef short Short; 15 typedef int Int; 16 typedef long long int Long; 17 18 typedef 19 struct { 20 UShort env[14]; 21 UChar reg[80]; 22 } 23 Fpu_State; 24 25 /* Offsets, in 16-bit ints, into the FPU environment (env) area. */ 26 #define FP_ENV_CTRL 0 27 #define FP_ENV_STAT 2 28 #define FP_ENV_TAG 4 29 #define FP_ENV_IP 6 /* and 7 */ 30 #define FP_ENV_CS 8 31 #define FP_ENV_OPOFF 10 /* and 11 */ 32 #define FP_ENV_OPSEL 12 33 #define FP_REG(ii) (10*(7-(ii))) 34 35 /* Bitfield offsets for exceptions in the FPU status and control words. */ 36 #define FP_E_INVAL 0 37 #define FP_E_DENOR 1 38 #define FP_E_DIVZ 2 39 #define FP_E_OVERF 3 40 #define FP_E_UNDER 4 41 #define FP_E_LOS 5 42 43 /* More bitfield offsets, but for the status word only. */ 44 #define FP_E_STACKF 6 45 #define FP_E_SUMMARY 7 46 #define FP_F_C0 8 47 #define FP_F_C1 9 48 #define FP_F_C2 10 49 #define FP_F_C3 14 50 /* top-of-stack ptr is bits 13,12,11 of the word */ 51 #define FP_F_TOS_LO 11 52 #define FP_F_TOS_HI 13 53 54 /* Register tags. */ 55 #define FP_TAG_VALID 0 56 #define FP_TAG_ZERO 1 57 #define FP_TAG_SPEC 2 58 #define FP_TAG_EMPTY 3 59 60 char* fp_tag_names[4] 61 = { "Valid", "Zero", "Spec", "Empty" }; 62 63 char* fp_exception_names[6] 64 = { "INVAL", "DENOR", "DIVZ", "OVERF", "UNDERF", "LOS" }; 65 66 Fpu_State m_fpu_state; 67 68 69 70 UInt fp_get_tos ( void ) 71 { 72 return (m_fpu_state.env[FP_ENV_STAT] >> FP_F_TOS_LO) & 7; 73 } 74 75 UInt fp_get_tag ( UInt regno ) 76 { 77 assert(!(regno < 0 || regno > 7)); 78 return (m_fpu_state.env[FP_ENV_TAG] >> (2*regno)) & 3; 79 } 80 81 UInt fp_get_statusword_flag ( UInt flagno ) 82 { 83 assert(!(flagno < 0 || flagno > 15)); 84 return (m_fpu_state.env[FP_ENV_STAT] >> flagno) & 0x1; 85 } 86 87 UInt fp_get_controlword_flag ( UInt flagno ) 88 { 89 assert(!(flagno < 0 || flagno > 15)); 90 return (m_fpu_state.env[FP_ENV_CTRL] >> flagno) & 0x1; 91 } 92 93 static 94 void printFpuState ( void ) 95 { 96 Int i, j, k; 97 assert(sizeof(Fpu_State)==108); 98 for (i = 7; i >= 0; i--) { 99 printf ( " %s fpreg%d: 0x", 100 (UInt)i == fp_get_tos() ? "**" : " ", i ); 101 for (k = 0, j = FP_REG(i)+9; k < 10; k++,j--) 102 printf ( "%02x", (UInt)m_fpu_state.reg[j]); 103 printf ( " %5s ", fp_tag_names[fp_get_tag(i)] ); 104 printf("\n"); 105 //printf ( "%20.16e\n", fp_get_reg(i) ); 106 } 107 printf(" fctrl: 0x%04x masked: ", 108 (UInt)m_fpu_state.env[FP_ENV_CTRL] ); 109 for (i = FP_E_INVAL; i <= FP_E_LOS; i++) 110 if (fp_get_controlword_flag(i)) 111 printf ( "%s ", fp_exception_names[i] ); 112 printf ( "\n" ); 113 114 printf(" fstat: 0x%04x except:", 115 (UInt)m_fpu_state.env[FP_ENV_STAT] ); 116 for (i = FP_E_INVAL; i <= FP_E_LOS; i++) 117 if (fp_get_statusword_flag(i)) 118 printf ( "%s ", fp_exception_names[i] ); 119 printf ( " top: %d ", fp_get_tos() ); 120 printf ( "c3210: %d%d%d%d", 121 fp_get_statusword_flag(FP_F_C3), 122 fp_get_statusword_flag(FP_F_C2), 123 fp_get_statusword_flag(FP_F_C1), 124 fp_get_statusword_flag(FP_F_C0) ); 125 printf ( " STACKF: %d\n", fp_get_statusword_flag(FP_E_STACKF) ); 126 127 printf(" ftag: 0x%04x ", (UInt)m_fpu_state.env[FP_ENV_TAG] ); 128 for (i = 7; i >= 0; i--) 129 printf ( "%d:%s ", i, fp_tag_names[fp_get_tag(i)] ); 130 printf("\n"); 131 132 printf(" fip: 0x%08x\n", 133 (((UInt)m_fpu_state.env[FP_ENV_IP+1]) << 16) | 134 ((UInt)m_fpu_state.env[FP_ENV_IP]) ); 135 printf(" fcs: 0x%04x\n", 136 ((UInt)m_fpu_state.env[FP_ENV_CS]) ); 137 printf(" fopoff: 0x%08x\n", 138 (((UInt)m_fpu_state.env[FP_ENV_OPOFF+1]) << 16) | 139 ((UInt)m_fpu_state.env[FP_ENV_OPOFF]) ); 140 printf(" fopsel: 0x%04x\n", 141 ((UInt)m_fpu_state.env[FP_ENV_OPSEL]) ); 142 } 143 144 145 /* ------------------------------------------------- */ 146 147 148 /* Initialise the FPU, dump its state, and print it. */ 149 150 151 void show ( unsigned char* st ) 152 { 153 int i; 154 for (i = 0; i < 28; i++) { 155 printf("%02x ", st[i]); 156 if (i > 0 && ((i & 3) == 3)) printf("\n"); 157 } 158 for (i = 0; i < 80; i++) { 159 printf("%02x ", st[i+28]); 160 if (i > 0 && ((i % 10) == 9)) printf("\n"); 161 } 162 printf("\n"); 163 } 164 165 int main ( void ) 166 { 167 Fpu_State* st = &m_fpu_state; 168 assert(sizeof(m_fpu_state) == 108); 169 asm volatile ("finit ; fnsave %0" 170 : "=m" (m_fpu_state) 171 : 172 : "memory" ); 173 printFpuState(); 174 printf("\n\n"); 175 176 asm volatile ("fildl 0(%%esp) ; pushl $17 ; fildl 0(%%esp) ; addl $4, %%esp ; fnsave %0" 177 : "=m" (m_fpu_state) 178 : 179 : "memory" ); 180 printFpuState(); 181 printf("\n"); 182 show(st); 183 return 0; 184 } 185