windows-nt/Source/XPSP1/NT/base/tools/kdexts2/npx.c

401 lines
7.7 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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, 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, 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,
PBITENCODING Bits
)
{
BOOLEAN Flag;
Flag = FALSE;
*Str = 0;
while (Bits->Mask) {
if (Bits->Mask & Value) {
if (Flag) {
Str += sprintf (Str, ", %s", Bits->String);
} else {
Str += sprintf (Str, "%s", Bits->String);
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
);
}