|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
trap.c
Abstract:
WinDbg Extension Api
Author:
Ken Reneris
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
typedef struct { ULONG Mask; PUCHAR String; } BITENCODING, *PBITENCODING;
typedef unsigned __int64 ULONGLONG;
void DumpNpxULongLong (PUCHAR s, ULONGLONG l); void DumpNpxExtended (PUCHAR str, PUCHAR Value); void DumpNpxBits (ULONG, PUCHAR, ULONG, PBITENCODING);
PUCHAR NpxPrecisionControl[] = { "24Bits", "?1?", "53Bits", "64Bits" }; PUCHAR NpxRoundingControl[] = { "Nearest", "Down", "Up", "Chop" }; PUCHAR NpxTagWord[] = { " ", "ZR", "SP", " " };
BITENCODING NpxStatusBits[] = { 1 << 8, "C0", 1 << 9, "C1", 1 << 10, "C2", 1 << 14, "C3", 0x8000, "Busy", 0x0001, "InvalidOp", 0x0002, "Denormal", 0x0004, "ZeroDivide", 0x0008, "Overflow", 0x0010, "Underflow", 0x0020, "Precision", 0x0040, "StackFault", 0x0080, "Summary", 0, 0 };
PUCHAR NpxOpD8[] = { "fadd", "fmul", "fcom", "fcomp", "fsub", "fsubr", "fdiv", "fdivr" };
PUCHAR NpxOpD9[] = { "fld", "??3", "fst", "fstp", "fldenv", "fldcw", "fstenv", "fstcw" };
PUCHAR NpxOpDA[] = { "fiadd", "fimul", "ficom", "ficomp", "fisub", "fisubr", "fidiv", "fidivr" };
PUCHAR NpxOpDB[] = { "fild", "??4", "fist", "fistp", "??5", "fld", "??6", "fstp" };
PUCHAR NpxOpDF[] = { "fild", "??4", "fist", "fistp", "fbld", "fild", "fbstp", "fstp" };
PUCHAR *NpxSmOpTable[] = { NpxOpD8, NpxOpD9, NpxOpDA, NpxOpDB, NpxOpD8, // DC
NpxOpD9, // DD
NpxOpDA, // DE
NpxOpDF };
DECLARE_API( npx )
/*++
Routine Description:
Dumps FNSAVE area format of NPX state
Arguments:
args -
Return Value:
None
--*/
{ ULONG64 Address; UCHAR s[300], Reg[100]; PUCHAR Stack, p; ULONG i, j, t, tos, Tag; ULONG ControlWord, StatusWord;
// X86_ONLY_API
if (TargetMachine != IMAGE_FILE_MACHINE_I386) { dprintf("!npx is X86 Only API\n"); return E_INVALIDARG; }
Address = GetExpression(args);
if ( InitTypeRead( Address, FLOATING_SAVE_AREA)) {
dprintf("unable to read floating save area\n"); return E_INVALIDARG; } ControlWord = (ULONG) ReadField(ControlWord); dprintf ("EIP.......: %08x ControlWord: %s-%s mask: %02x Cr0NpxState: %08x\n", (ULONG) ReadField(ErrorOffset), NpxPrecisionControl [(ControlWord >> 8) & 0x3], NpxRoundingControl [(ControlWord >> 10) & 0x3], ControlWord & 0x3f, (ULONG) ReadField(Cr0NpxState) );
DumpNpxBits ( StatusWord = (ULONG) ReadField(StatusWord), s, sizeof(s), NpxStatusBits); tos = (StatusWord >> 11) & 7,
dprintf ("StatusWord: %04x TOS:%x %s (tagword: %04x)\n", StatusWord & 0xffff, tos, s, (ULONG) ReadField(TagWord) & 0xffff );
GetFieldValue(Address, "FLOATING_SAVE_AREA", "RegisterArea", Reg); Stack = &Reg[0];
Tag = (ULONG) ReadField(TagWord); for (i=0; i < 8; i++) { j = (tos + i) & 7; t = (Tag >> (j*2)) & 3;
if (t != 3) { sprintf (s, "%x%c%s", j, j == tos ? '>' : '.', NpxTagWord [t] );
DumpNpxExtended (s, Stack); }
Stack += 10; // next stack location
}
dprintf ("\n"); return S_OK; }
void DumpNpxBits ( ULONG Value, PUCHAR Str, ULONG StrSize, PBITENCODING Bits ) { BOOLEAN Flag;
Flag = FALSE; *Str = 0;
while (Bits->Mask) { if (Bits->Mask & Value) { if (Flag) { if (SUCCEEDED( StringCchCopy(Str, StrSize, ", ") ) ) { StrSize -=2; Str+=2; } if (StringCchCopy(Str, StrSize, Bits->String) == S_OK) { StrSize -= strlen (Str); Str += strlen (Str); } } else { if (StringCchCopy(Str, StrSize, Bits->String) == S_OK) { StrSize -= strlen (Str); Str += strlen (Str); Flag = TRUE; } } }
Bits += 1; } }
void DumpNpxULongLong ( PUCHAR s, ULONGLONG l ) { UCHAR c; UCHAR t[80], *p;
if (l == 0) { *(s++)= '0'; }
p = t; while (l) { c = (UCHAR) ((ULONGLONG) l % 10); *(p++) = c + '0'; l /= 10; }
while (p != t) { *(s++) = *(--p); } *(s++) = 0; }
void DumpNpxExtended ( PUCHAR str, PUCHAR Value ) { UCHAR *p, *o, c, out[100], t[100], ssig[100], ExponSign, SigSign; ULONG i, indent, mag, scale; LONG expon, delta; ULONGLONG sig;
p = Value; c = 0; o = out+90; indent = strlen (str) + 1;
dprintf ("%s ", str);
//
// Build string of bits
//
*(--o) = 0; while (c < 80) { *(--o) = (*p & 0x01) + '0'; *p >>= 1; c += 1; if ((c % 8) == 0) { p += 1; } } p = o;
//dprintf (" %s\n", o);
//dprintf ("%*s", indent, "");
//
// print bit string seperated into fields
//
p = o; //dprintf ("%c %15.15s 1%c%s\n", p[0], p+1, '.', p+1+15);
//dprintf ("%*s", indent, "");
//
// Pull out exponent
//
expon = 0; p = o + 1; for (i=0; i < 15; i++) { expon *= 2; if (p[i] == '1') { expon += 1; } }
expon -= 16383; // take out exponent bias
//
// Build sig into big #
//
p = o + 1+15; scale = 0; for (i=0; p[i]; i++) { if (p[i] == '1') { scale = i+1; } } SigSign = p[i-1] == '0' ? '+' : '-';
sig = 0; for (i=0; i < scale; i++) { sig <<= 1; if (p[i] == '1') { sig += 1; } }
delta = expon - (scale - 1); //dprintf ("delta %d, expon %d, scale %d\n", delta, expon, scale);
//
// Print values of each field
//
DumpNpxULongLong (ssig, sig);
p = o; ExponSign = p[0] == '0' ? '+' : '-'; dprintf ("%c %15.15s (%+5d) %c%c%s\n", ExponSign, p + 1, expon, p[1+15], '.', p+1+15+1 ); dprintf ("%*s", indent, "");
if (expon == -16383) { if (SigSign == '+') { dprintf ("Denormal\n\n"); } else { dprintf ("Pseudodenormal\n\n"); } return ; }
if (expon == 1024) { if (scale == 1) { dprintf ("%c Infinity\n", ExponSign); } else {
p = o + 1+15; c = 0; for (i=0; p[i]; i++) { if (p[i] == '1') { c++; } }
if (SigSign == '+') { dprintf ("Signaling NaN\n"); } else { if (c == 1) { dprintf ("Indefinite - quite NaN\n"); } else { dprintf ("Quite NaN\n"); } } }
dprintf ("%*s", indent, ""); }
//dprintf ("%*s%c %15d %s (delta %d)\n",
// indent, "", // indent
// p[0] == '0' ? '+' : '-', // sign of exponent
// expon, ssig,
// delta
// );
//dprintf ("%*s", indent, "");
t[0] = 0; p = t; if (delta < 0) { p += sprintf (p, "/ "); delta = -delta; } else if (delta > 0) { p += sprintf (p, "* "); }
if (delta) { if (delta < 31) { p += sprintf (p, "%d", 1 << delta); } else { p += sprintf (p, "2^%d", delta); } }
dprintf ("%s %s\n", ssig, t ); }
|