Home | History | Annotate | Download | only in useful
      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