sewardj | 5484c14 | 2004-08-24 22:43:26 +0000 | [diff] [blame] | 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 | } |