Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1097 lines
30 KiB

#include "precomp.h"
#pragma hdrstop
#include "ntdis.h"
#include "ntdisppc.h"
INSTRUCTION *find_eop(); /* Searches a table for extended opcodes */
void output_mnemonic(); /* Outputs instruction mnemonic string */
void output_operands(); /* Decodes operands */
typedef LPCH FAR *LPLPCH;
#define MAXL 20
char lhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
char uhexdigit[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char *hexdigit = &uhexdigit[0];
static int fUpper = TRUE;
/* current position in instruction */
static unsigned char FAR*pMem = (unsigned char *)NULL;
static int EAsize [2] = {0}; // size of effective address item
static long EAaddr [2] = {0}; // offset of effective address
int DumpAddress ( LPADDR, LPCH, int );
int DumpGeneric ( LSZ, LPCH, int );
int DumpComment ( LSZ, LPCH, int );
int DumpEA ( HPID, HTID, LPADDR, LPCH, int );
void OutputAddr(LPLPCH, LPADDR, int );
void OutputHexString(LPLPCH, LPCH, int);
void OutputHexCode(LPLPCH, LPCH, int);
#include "strings.h"
static UCHAR * PBuf;
static int CchBuf;
INSTR disinstr;
void CalcMain (HPID,HTID,DOP,LPADDR,LPBYTE,int,int*,LPCH,int, LPCH,int, LPCH, int);
/****disasm - disassemble a PowerPC instruction
*
* Input:
* pOffset = pointer to offset to start disassembly
* fEAout = if set, include EA (effective address)
*
* Output:
* pOffset = pointer to offset of next instruction
* pchDst = pointer to result string
*
***************************************************************************/
#define CCHMAX 256
static char rgchDisasm [ CCHMAX ];
static HPID hpidLocal;
static HTID htidLocal;
XOSD disasm ( HPID hpid, HTID htid, LPSDI lpsdi ) {
XOSD xosd = xosdNone;
int cchMax = CCHMAX;
DOP dop = lpsdi->dop;
LPCH lpchOut = rgchDisasm;
int ichCur = 0;
ADDR addrStart = lpsdi->addr;
int cch = 0;
int cb;
int cbUsed=0;
BYTE rgb [ MAXL ];
char rgchRaw [ MAXL * 2 + 1 ];
char rgchOpcode [ 80 ];
char rgchOperands [ 80 ];
char rgchEA [ 44 ];
char rgchComment [ 80 ];
hpidLocal = hpid;
htidLocal = htid;
_fmemset ( rgchRaw, 0, sizeof ( rgchRaw ) );
_fmemset ( rgchOpcode, 0, sizeof ( rgchOpcode ) );
_fmemset ( rgchOperands, 0, sizeof ( rgchOperands ) );
_fmemset ( rgchComment, 0, sizeof ( rgchComment ) );
_fmemset ( rgchEA, 0, sizeof ( rgchEA ) );
lpsdi->ichAddr = -1;
lpsdi->ichBytes = -1;
lpsdi->ichOpcode = -1;
lpsdi->ichOperands = -1;
lpsdi->ichComment = -1;
lpsdi->ichEA0 = -1;
lpsdi->ichEA1 = -1;
lpsdi->ichEA2 = -1;
lpsdi->cbEA0 = 0;
lpsdi->cbEA1 = 0;
lpsdi->cbEA2 = 0;
lpsdi->fAssocNext = 0;
lpsdi->lpch = rgchDisasm;
// Set up for upper or lower case
fUpper = ( dop & dopUpper ) == dopUpper;
if ( fUpper ) {
hexdigit = uhexdigit;
}
else {
hexdigit = lhexdigit;
}
ADDR_IS_FLAT( addrStart ) = TRUE;
// Output the address if it is requested
if ( ( dop & dopAddr ) == dopAddr ) {
cch = DumpAddress ( &addrStart, lpchOut, cchMax );
lpsdi->ichAddr = 0;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
#ifdef OSDEBUG4
xosd = ReadBuffer(hpid, htid, &addrStart, MAXL, rgb, &cb);
if (xosd != xosdNone) {
cb = 0;
}
#else
EMFunc ( emfSetAddr, hpid, htid, adrCurrent, (LONG) &addrStart );
cb = EMFunc ( emfReadBuf, hpid, htid, MAXL, (LONG) (LPV) rgb );
#endif
if ( cb <= 0 ) {
_fmemcpy ( rgchRaw, " ??", 4 );
_fmemcpy ( rgchOpcode, "???", 4 );
lpsdi->addr.addr.off++;
}
else {
CalcMain (
hpid,
htid,
lpsdi->dop,
&lpsdi->addr,
rgb,
cb,
&cbUsed,
rgchOpcode, sizeof(rgchOpcode),
rgchOperands, sizeof(rgchOperands),
rgchComment, sizeof(rgchComment)
);
// NOTENOTE jimsch - cbUsed must be 4
cbUsed = 4;
if ( GetAddrOff(lpsdi->addr) > 0xFFFFFFFF - cbUsed ) {
return xosdBadAddress;
}
if ( dop & dopRaw ) {
LPCH lpchT = rgchRaw;
OutputHexCode ( &lpchT, rgb, cbUsed );
*lpchT = '\0';
}
}
if ( ( dop & dopRaw ) && ( cchMax > 0 ) ) {
cch = DumpGeneric ( rgchRaw, lpchOut, cchMax );
lpsdi->ichBytes = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
if ( ( dop & dopOpcode ) && ( cchMax > 0 ) ) {
cch = DumpGeneric ( rgchOpcode, lpchOut, cchMax );
lpsdi->ichOpcode = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchOperands [ 0 ] != '\0' ) ) {
cch = DumpGeneric ( rgchOperands, lpchOut, cchMax );
lpsdi->ichOperands = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
if ( ( dop & dopOperands ) && ( cchMax > 0 ) && ( rgchComment [ 0 ] != '\0' ) ) {
cch = DumpComment ( rgchComment, lpchOut, cchMax );
lpsdi->ichComment = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
if ( dop & dopEA ) {
cch = DumpEA ( hpid, htid, &lpsdi->addrEA0, lpchOut, cchMax );
if ( cchMax > 0 && cch > 0 ) {
lpsdi->ichEA0 = ichCur;
cchMax -= cch;
lpchOut += cch;
ichCur += cch;
}
}
lpsdi->addr.addr.off += cbUsed;
return xosd;
}
void OutputStringM (PUCHAR pStr)
{
int cb;
if (CchBuf == 0) {
return;
}
cb = strlen(pStr);
if (cb > CchBuf) {
cb = CchBuf - 1;
}
strncpy(PBuf, pStr, cb);
PBuf[cb] = 0;
if (fUpper) {
_strupr(PBuf);
} else {
_strlwr(PBuf);
}
PBuf += cb;
CchBuf -= cb;
return;
}
void OutputReg (ULONG regnum)
{
/* OutputStringM(pszReg[regnum + 32]); */
}
void OutputRxReg ( ULONG regnum)
{
if (CchBuf < 3) {
CchBuf = 0;
return;
}
*PBuf++ = 'r';
if (regnum > 9) {
*PBuf++ = (UCHAR) ('0' + regnum / 10);
}
*PBuf++ = (UCHAR) ('0' + regnum % 10);
CchBuf -= 2 + (regnum > 9);
return;
}
void OutputHex (ULONG outvalue, ULONG length, BOOL fSigned)
{
UCHAR digit[8];
LONG index = 0;
if (fSigned && (long)outvalue < 0) {
if (CchBuf > 1) {
*PBuf++ = '-';
CchBuf -= 1;
}
outvalue = (ULONG) (- (LONG) outvalue);
}
if (CchBuf > 2) {
*PBuf++ = '0';
*PBuf++ = (fUpper) ? 'X' :'x';
CchBuf -= 2;
}
do {
digit[index++] = hexdigit[outvalue & 0xf];
outvalue >>= 4;
}
while (outvalue || (!fSigned && index < (LONG)length));
if (CchBuf > index) {
CchBuf -= index;
while (--index >= 0) {
*PBuf++ = digit[index];
}
}
return;
}
/*** OutputDisSymbol - output symbol for disassembly
*
* Purpose:
* Access symbol table with given offset and put string into buffer.
*
* Input:
* offset - offset of address to output
*
* Output:
* buffer pointed by PBuf updated with string:
* if symbol, no disp: <symbol>(<offset>)
* if symbol, disp: <symbol>+<disp>(<offset>)
* if no symbol, no disp: <offset>
*
*************************************************************************/
void
OutputDisSymbol (
ULONG offset,
BOOL fSymbol
)
{
UCHAR chAddrBuffer[512];
LPCH lpchSymbol;
ADDR addrT={0}, addr={0};
int cb;
ODR odr;
odr.lszName = chAddrBuffer;
addr.addr.off = addrT.addr.off = offset;
MODE_IS_FLAT(addr.mode) = TRUE;
MODE_IS_FLAT(addrT.mode) = TRUE;
if (fSymbol) {
lpchSymbol = SHGetSymbol (&addrT, &addr, sopNone, &odr);
if (odr.dwDeltaOff == -1) {
lpchSymbol = NULL;
}
} else {
lpchSymbol = NULL;
}
if (lpchSymbol != NULL) {
cb = strlen(chAddrBuffer);
if (cb > CchBuf) {
cb = CchBuf;
}
strncpy(PBuf, chAddrBuffer, cb);
CchBuf -= cb;
PBuf += cb;
*PBuf = 0;
if (odr.dwDeltaOff) {
if (CchBuf > 1) {
*PBuf++ = '+';
CchBuf -= 1;
}
OutputHex(odr.dwDeltaOff, 8, TRUE);
}
if (CchBuf > 1) {
*PBuf++ = '(';
CchBuf -= 1;
}
}
OutputHex(offset, 8, FALSE);
if (lpchSymbol != NULL) {
if (CchBuf > 1) {
CchBuf -= 1;
*PBuf++ = ')';
}
}
return;
}
void
CalcMain (
HPID hpid,
HTID htid,
DOP dop,
LPADDR lpaddr,
LPBYTE rgb,
int cbMax,
int FAR *lpcbUsed,
LPCH rgchOpcode,
int cchOpcode,
LPCH rgchOperands,
int cchOperands,
LPCH rgchComment,
int cchComment
)
/*++
Routine Description:
Decode the 32-bit opword and put the operator, operands, and comments
into the appropriate character string buffers.
Arguments:
hpid - Supplies the process handle
hthd - Supplies a thread handle
dop - Supplies the set of disassembly options
lpaddr - Supplies the address to be disassembled
rgb - Supplies the 32 bit opword to disassemble
cbMax - Unused
lpcbUsed - Unused
rgchOpcode - Supplies location to place instruction mnemonic
cchOpcode - Unused, size of rgchOpcode
rgchOperands - Supplies location to place operands
cchOperands - Character count remaining in rgchOperands
rgchComment - Supplies location to place comment
cchComment - Unused, size of rgchComment
Return Value:
None.
--*/
{
UCHAR chSuffix = '\0';
BOOL fEAout = TRUE;
INSTRUCTION *iptr; /* All of the information on any instruction */
ULONG pop; /* primary opcode */
ULONG opword; /* 32 bit instruction word */
ULONG address; /* address to disassemble */
Unreferenced(cbMax);
Unreferenced(lpcbUsed);
*rgchComment = *rgchOperands = 0;
EAsize[0] = EAsize[1] = 0;
/* Get the address to be disassembled out of the ADDR structure */
address = lpaddr->addr.off;
/* Extract the primary opcode */
opword = ((INSTR *)rgb)->instruction;
pop = (unsigned)(opword >> 26);
/* Some primary opcodes have extended opcodes. For those, pass the
information about which tables to search and which instruction formats
to use for that primary opcode. Otherwise, just use the primary opcode
as an array index to get the information. */
switch ( pop ) {
case 19:
iptr = find_eop (opword, &pop19_fmts, &pop19_insn, COUNT19);
break;
case 30:
iptr = find_eop (opword, &pop30_fmts, &pop30_insn, COUNT30);
break;
case 31:
iptr = find_eop (opword, &pop31_fmts, &pop31_insn, COUNT31);
break;
case 58:
iptr = find_eop (opword, &pop58_fmts, &pop58_insn, COUNT58);
break;
case 59:
iptr = find_eop (opword, &pop59_fmts, &pop59_insn, COUNT59);
break;
case 62:
iptr = find_eop (opword, &pop62_fmts, &pop62_insn, COUNT62);
break;
case 63:
iptr = find_eop (opword, &pop63_fmts, &pop63_insn, COUNT63);
break;
default:
/* no extended opcode for this primary opcode, use it as index */
if ( pop_insn[pop].ext_opcode == 0 )
iptr = (INSTRUCTION *)0;
else
iptr = &pop_insn[pop];
}
/* Establish pointer to output buffer for instruction mnemonic */
PBuf = rgchOpcode;
/* If match was found, output mnemonic and operands */
if ( iptr != (INSTRUCTION *)0 ) {
output_mnemonic (opword, iptr);
/* If option is set, convert operator to upper case */
if ( fUpper )
for(PBuf = rgchOpcode;*PBuf != '\0';PBuf++)
*PBuf = toupper(*PBuf);
/* Establish pointer to output buffer for operands */
PBuf = rgchOperands;
CchBuf = cchOperands; /* Character count remaining in buffer */
output_operands (address, opword, iptr, dop);
/* If no match, just output the 32 bit instruction word */
} else {
OutputHex(opword,8,FALSE);
PBuf += sprintf(PBuf, "\tUnknown opcode or extended opcode");
}
return;
}
/* Search the given extended opcode table. If a match is found return
address of matching instruction, otherwise NULL */
INSTRUCTION *
find_eop (opword, insn_format, insn_table, table_size)
ULONG opword; /* 32-bit word to disassemble */
int *insn_format; /* list of possible instruction formats */
INSTRUCTION *insn_table; /* table of instructions to search */
int table_size; /* number of entries in intruction table */
{
int eop; /* extended opcode */
int last_eop; /* previous search key */
int here; /* extended opcode search index */
int max, min; /* search bounds */
/* A lot of the time, extended opcode formats will extract the
same value twice because of leading zeros. This is used to
save the previous value to avoid repeating the search for the
same key that was not found before. */
last_eop = -1;
/* Search for extended opcode. A -1 marks the end of each table
because the table size can be different for different primary
opcodes. */
while ( *insn_format != -1 ) {
/* Extract the extended opcode */
eop = (opword >> eopFormat[*insn_format][1]) & eopFormat[*insn_format][0];
/* Avoid duplicate searches */
if ( eop != last_eop ) {
/* Set up bounds for binary search */
min = 0;
max = table_size - 1;
/* Use binary initially, linear when it gets small */
while ((here = (max + min) / 2) > (min + 5)) {
/* If not in bottom half, adjust minimum up */
if ( eop > insn_table[here].ext_opcode ) min = here+1;
/* If not in top half, adjust maximum down */
else if ( eop < insn_table[here].ext_opcode ) max = here-1;
/* Otherwise, return address of matching table entry */
else return &insn_table[here];
}
/* Switching to linear search */
for (;min <= max; min++) {
/* If match is found, return pointer to table entry */
if ( eop == insn_table[min].ext_opcode ) return &insn_table[min];
}
}
/* Will compare the next extended opcode to avoid duplicates */
last_eop = eop;
/* Set up for the next instruction format */
insn_format++;
}
/* If it falls through, search fails */
return (INSTRUCTION *)0;
}
/* Output the instruction mnemonic, with extensions */
void
output_mnemonic (opword, iptr)
ULONG opword; /* 32 bit opword to disassemble */
INSTRUCTION *iptr; /* corresponding instruction data table entry */
{
char options [40]; /* buffer to build mnemonic extensions string */
char *qq = options;
char *pp = iptr->mne_ext; /* possible extensions for given instruction mnemonic */
/* Put any appropriate mnemonic optional characters into trailing buffer */
if (pp) {
while (*pp) {
switch ( *pp ) {
case '.':
if (opword & 0x1)
*qq++ = '.';
break;
case 'l':
if (opword & 0x1)
*qq++ = 'l';
break;
case 't':
if ((opword & 0x03e00000) == 0x01800000)
*qq++ = 't';
break;
case 'f':
if ((opword & 0x03e00000) == 0x00800000)
*qq++ = 'f';
break;
case 'a':
if (opword & 0x2)
*qq++ = 'a';
break;
case 'o':
if (opword & 0x400)
*qq++ = 'o';
break;
default:
break;
}
++pp;
}
}
*qq = '\0';
PBuf += sprintf(PBuf, "%s%s", iptr->mnemonic, options);
return;
}
/* Output all the operands, based on formats from instruction table. */
void
output_operands (address, opword, iptr, dop)
ULONG address; /* address being disassemble, for effective address calculation */
ULONG opword; /* 32 bit opword to disassemble */
INSTRUCTION *iptr; /* corresponding instruction data table entry */
DOP dop; /* disassembly options */
{
unsigned int tmp;
long effective_address;
int print_comma = 1; /* nonzero if comma is needed */
char *pp = iptr->operand_fmt; /* the operand formats for the given instruction */
while (*pp != '\0') {
switch (*pp) {
case BA : /* specifies bit in CR to be used as source */
PBuf += sprintf(PBuf, "%d", (opword >> 16) & 0x1f);
break;
case BB : /* specifies bit in CR to be used as source */
PBuf += sprintf(PBuf, "%d", (opword >> 11) & 0x1f);
break;
case BD : /* conditional branch displacement/absolute target */
effective_address = opword & 0xfffc;
if (effective_address & 0x8000) /* Perform sign extension */
effective_address -= 0x10000;
if ((opword & 0x2) == 0) { /* if AA bit not set */
if (!(dop & dopSym)) {
if ( effective_address >= 0 ) {
PBuf += sprintf(PBuf, "$+");
OutputHex(effective_address,8,FALSE);
} else {
PBuf += sprintf(PBuf, "$-");
OutputHex( - effective_address,8,FALSE);
}
}
effective_address += address;
}
if (!(dop & dopSym)) {
PBuf += sprintf(PBuf, "$-");
OutputHex(effective_address,8,FALSE);
}
/* If requested, print the associated symbol */
if (dop & dopSym)
OutputDisSymbol((long)effective_address , dop & dopSym);
break;
case BF : /* CR field or FPSCR field as target */
PBuf += sprintf(PBuf, "%d", (opword >> 23) & 0x7);
break;
case BFA : /* CR field or FPSCR field as source */
PBuf += sprintf(PBuf, "%d", (opword >> 18) & 0x7);
break;
case BI : /* bit in CR as condition of branch conditional */
PBuf += sprintf(PBuf, "%d", (opword >> 16) & 0x1f);
break;
case BO : /* options for branch conditional */
PBuf += sprintf(PBuf, "%d", (opword >> 21) & 0x1f);
break;
case BT : /* bit in CR or FPSCR as target for result of instr */
PBuf += sprintf(PBuf, "%d", (opword >> 21) & 0x1f);
break;
case D : /* 16 bit signed imm, sign extended to 64 bits */
print_comma=0;
tmp = opword & 0xffff;
if (tmp & 0x8000)
tmp -= 0x10000;
PBuf += sprintf(PBuf, "%d(", tmp);
break;
case DS : /* like D form except for two low order bits */
print_comma=0;
tmp = opword & 0xfffc;
if (tmp & 0x8000)
tmp -= 0x10000;
PBuf += sprintf(PBuf, "%d(", tmp);
break;
case FLM : /* FPSRC fields updated by mtfsf */
OutputHex(((opword >> 17) & 0xff),0,FALSE);
break;
case FRA : /* specifies source floating point register */
if ( fUpper )
PBuf += sprintf(PBuf, "F%d", (opword >> 16) & 0x1f);
else
PBuf += sprintf(PBuf, "f%d", (opword >> 16) & 0x1f);
break;
case FRB : /* specifies source floating point register */
if ( fUpper )
PBuf += sprintf(PBuf, "F%d", (opword >> 11) & 0x1f);
else
PBuf += sprintf(PBuf, "f%d", (opword >> 11) & 0x1f);
break;
case FRC : /* specifies source floating point register */
if ( fUpper )
PBuf += sprintf(PBuf, "F%d", (opword >> 6) & 0x1f);
else
PBuf += sprintf(PBuf, "f%d", (opword >> 6) & 0x1f);
break;
case FRS : /* specifies source floating point register */
case FRT : /* specifies target floating point register */
if ( fUpper )
PBuf += sprintf(PBuf, "F%d", (opword >> 21) & 0x1f);
else
PBuf += sprintf(PBuf, "f%d", (opword >> 21) & 0x1f);
break;
case FXM : /* CR fields updated by mtcrf */
OutputHex(((opword >> 12) & 0xff),0,FALSE);
break;
case L : /* specifies 32 or 64 bit fixed point compare */
PBuf += sprintf(PBuf, "%d", (opword >> 21) & 0x1);
break;
case LI : /* branch displacement/absolute target */
effective_address = opword & 0x03fffffc;
if (effective_address & 0x2000000) /* Perform sign extension */
effective_address -= 0x4000000;
if ((opword & 0x2) == 0) { /* if AA bit not set */
if (!(dop & dopSym)) {
if ( effective_address >= 0 ) {
PBuf += sprintf(PBuf, "$+");
OutputHex(effective_address,8,FALSE);
} else {
PBuf += sprintf(PBuf, "$-");
OutputHex( - effective_address,8,FALSE);
}
}
effective_address += address;
}
if (!(dop & dopSym)) {
PBuf += sprintf(PBuf, "$-");
OutputHex(effective_address,8,FALSE);
}
/* If requested, print the associated symbol */
if (dop & dopSym)
OutputDisSymbol((long)effective_address , dop & dopSym);
break;
case PPC_MB : /* mask field for M-form instructions */
OutputHex(((opword >> 6) & 0x1f),0,FALSE);
break;
case ME : /* mask field for M-form instructions */
OutputHex(((opword >> 1) & 0x1f),0,FALSE);
break;
case MBE64: /* 64 bit implementation MB and ME fields */
OutputHex(((opword >> 5) & 0x3f),0,FALSE);
break;
case NB : /* number of bytes to move */
PBuf += sprintf(PBuf, "%d", (opword >> 11) & 0x1f);
break;
case RA : /* specifies gpr source or target */
if (!print_comma) {
if ( fUpper )
PBuf += sprintf(PBuf, "R%d)", (opword >> 16) & 0x1f);
else
PBuf += sprintf(PBuf, "r%d)", (opword >> 16) & 0x1f);
print_comma++;
}
else
if ( fUpper )
PBuf += sprintf(PBuf, "R%d", (opword >> 16) & 0x1f);
else
PBuf += sprintf(PBuf, "r%d", (opword >> 16) & 0x1f);
break;
case RB : /* specifies gpr source */
if ( fUpper )
PBuf += sprintf(PBuf, "R%d", (opword >> 11) & 0x1f);
else
PBuf += sprintf(PBuf, "r%d", (opword >> 11) & 0x1f);
break;
case RS : /* specifies gpr source */
case PPC_RT : /* specifies gpr target */
if ( fUpper )
PBuf += sprintf(PBuf, "R%d", (opword >> 21) & 0x1f);
else
PBuf += sprintf(PBuf, "r%d", (opword >> 21) & 0x1f);
break;
case SH : /* shift amount for 32 bit implementation */
PBuf += sprintf(PBuf, "%d", (opword >> 11) & 0x1f);
break;
case SH64 : /* shift amount for 64 bit implementation */
PBuf += sprintf(PBuf, "%d", (((opword << 4) & 0x20) | ((opword >> 11) & 0x1f)));
break;
case SI : /* 16 bit signed immediate */
tmp = opword & 0xffff;
if (tmp & 0x8000)
tmp -= 0x10000;
PBuf += sprintf(PBuf, "%d", tmp);
break;
case SPR : /* special purpose register, two halves are reversed */
case TBR : /* time base register, two halves are reversed */
tmp = ((opword >> 16) & 0x1f);
tmp |= ((opword >> 6) & 0x3e0);
PBuf += sprintf(PBuf, "%d", tmp);
break;
case SR : /* specifies segment register */
PBuf += sprintf(PBuf, "%d", (opword >> 16) & 0xf);
break;
case TO : /* trap condition */
PBuf += sprintf(PBuf, "%d", (opword >> 21) & 0x1f);
break;
case U : /* immediate data for FPSCR */
PBuf += sprintf(PBuf, "%d", (opword >> 12) & 0xf);
break;
case UI : /* 16 bit unsigned integer data field */
PBuf += sprintf(PBuf, "%d", opword & 0xffff);
break;
default :
PBuf += sprintf(PBuf, "Disassembly error: Unknown operand format %d", *pp);
}
/* Point to next format in the operand formats table */
++pp;
if ((*pp != '\0') && print_comma) PBuf += sprintf(PBuf, ",");
}
return;
}
int DumpAddress ( LPADDR lpaddr, LPCH lpch, int cchMax ) {
LPCH lpchT = lpch;
Unreferenced(cchMax);
OutputAddr ( &lpch, lpaddr, (ADDR_IS_FLAT(*lpaddr) + 1) * 2 );
*lpch = '\0';
return lpch - lpchT + 1;
}
int
DumpGeneric (
LSZ lsz,
LPCH lpch,
int cchMax
)
{
int ich = 0;
while ( *(lsz + ich) != 0 && ich < cchMax - 1 ) {
*(lpch+ich) = *(lsz+ich);
ich += 1;
}
*( lpch + ich ) = '\0';
return ich + 1;
}
int
DumpComment (
LSZ lsz,
LPCH lpch,
int cchMax
)
{
*(lpch) = ';';
return DumpGeneric ( lsz, lpch + 1, cchMax - 1 ) + 1;
}
int
DumpEA (
HPID hpid,
HTID htid,
LPADDR lpaddr,
LPCH lpch,
int cchMax
)
{
LPCH lpchT = lpch;
BYTE rgb [ MAXL ];
int indx;
int cb;
#ifdef OSDEBUG4
XOSD xosd;
#endif
Unreferenced(cchMax);
for ( indx = 0; indx < 2; indx++ ) {
if ( EAsize [ indx ] ) {
ADDR addr = {0};
OutputHexString ( &lpchT, (LPBYTE) &EAaddr [ indx ], 4 );
*lpchT++ = '=';
addr.addr.off = (UOFFSET) EAaddr [ indx ];
addr.addr.seg = (SEGMENT) 0;
*lpaddr = addr;
#ifdef OSDEBUG4
xosd = ReadBuffer(hpid, htid, &addr, EAsize[indx], rgb, &cb);
if (xosd != xosdNone) {
cb = 0;
}
#else
EMFunc (
emfSetAddr,
hpid,
htid,
adrCurrent,
(LONG) (LPADDR) &addr
);
cb = EMFunc (
emfReadBuf,
hpid,
htid,
EAsize [ indx ],
(LONG) (LPV) rgb
);
#endif
if ( cb == EAsize [ indx ] ) {
OutputHexString ( &lpchT, rgb, EAsize [ indx ] );
}
else {
while ( EAsize [ indx ]-- ) {
*lpchT++ = '?';
*lpchT++ = '?';
}
}
*lpchT++ = '\0';
}
}
return lpchT - lpch;
}
/*** OutputHexString - output hex string
*
* Purpose:
* Output the value pointed by *lplpchMemBuf of the specified
* length. The value is treated as unsigned and leading
* zeroes are printed.
*
* Input:
* *lplpchBuf - pointer to text buffer to fill
* *pchValue - pointer to memory buffer to extract value
* length - length in bytes of value
*
* Output:
* *lplpchBuf - pointer updated to next text character
* *lplpchMemBuf - pointer update to next memory byte
*
*************************************************************************/
void OutputHexString (LPLPCH lplpchBuf, PCH pchValue, int length)
{
unsigned char chMem;
pchValue += length;
while ( length-- ) {
chMem = *--pchValue;
*(*lplpchBuf)++ = hexdigit[chMem >> 4];
*(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
}
}
/*** OutputAddr - output address package
*
* Purpose:
* Output the address pointed to by lpaddr.
*
* Input:
* *lplpchBuf - pointer to text buffer to fill
* lpaddr - Standard address package.
*
* Output:
* *lplpchBuf - pointer updated to next text character
*
*************************************************************************/
VOID
OutputAddr (
LPLPCH lplpchBuf,
LPADDR lpaddr,
int alen
)
{
ADDR addr = *lpaddr;
*(*lplpchBuf)++ = '0';
*(*lplpchBuf)++ = (fUpper) ? 'X' : 'x';
OutputHexString ( lplpchBuf, (LPCH) &addr.addr.off, alen );
return;
} /* OutputAddr() */
/*** OutputHexCode - output hex code
*
* Purpose:
* Output the code pointed by lpchMemBuf of the specified
* length. The value is treated as unsigned and leading
* zeroes are printed. This differs from OutputHexString
* in that bytes are printed from low to high addresses.
*
* Input:
* *lplpchBuf - pointer to text buffer to fill
* lpchMemBuf - - pointer to memory buffer to extract value
* length - length in bytes of value
*
* Output:
* *lplpchBuf - pointer updated to next text character
*
*************************************************************************/
void OutputHexCode (LPLPCH lplpchBuf, LPCH lpchMemBuf, int length)
{
unsigned char chMem;
while (length--) {
chMem = lpchMemBuf[length];
*(*lplpchBuf)++ = hexdigit[chMem >> 4];
*(*lplpchBuf)++ = hexdigit[chMem & 0x0f];
}
}