mirror of https://github.com/lianthony/NT4.0
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.
563 lines
16 KiB
563 lines
16 KiB
// TODO:
|
|
// (3) Should registers be treated as 64 or 32bit? Note that Fregs are
|
|
// 64bits only. -- All registers should be treated as 64bit values
|
|
// since LDQ/EXTB is done for byte fetches (stores); the intermediate
|
|
// values could be hidden.
|
|
|
|
#define FALSE 0
|
|
#define TRUE 1
|
|
#define STATIC static
|
|
typedef double DOUBLE;
|
|
|
|
#include "dis32.h"
|
|
#include <alphaops.h>
|
|
#include "disalpha.h"
|
|
#include "regalpha.h"
|
|
#include "optable.h"
|
|
#include "strings.h"
|
|
|
|
|
|
extern PUCHAR pszAlphaReg[];
|
|
|
|
ALPHA_INSTRUCTION Adisinstr;
|
|
|
|
static CHAR *pBuf;
|
|
static CHAR *pBufStart;
|
|
|
|
#define MAX_IGNORE 16
|
|
LONG IgnoreInstruction[MAX_IGNORE] = {-1,} ;
|
|
LONG IgnoreIndex = -1;
|
|
|
|
|
|
ULONG GetIntRegNumber (ULONG index)
|
|
{
|
|
return(REGBASE + index);
|
|
}
|
|
|
|
PUCHAR OutputAlphaReg (PUCHAR buf, ULONG regnum)
|
|
{
|
|
return OutputString(buf, pszAlphaReg[GetIntRegNumber(regnum)]);
|
|
}
|
|
|
|
void OutputAlphaBranch( ULONG offset,
|
|
ULONG real_base,
|
|
PIMAGE_SECTION_HEADER pheader,
|
|
ULONG Section)
|
|
{
|
|
|
|
PIMAGE_SYMBOL sym = 0;
|
|
ULONG val;
|
|
ULONG address;
|
|
ULONG opcode;
|
|
INT ColumnIndex = 0;
|
|
|
|
if (Option.Mask & ASSEMBLE_ME)
|
|
ColumnIndex = 1;
|
|
|
|
//
|
|
// Calculate val and address
|
|
//
|
|
|
|
opcode = Adisinstr.Memory.Opcode;
|
|
val = (Adisinstr.Branch.BranchDisp << 2);
|
|
|
|
//
|
|
// We are going to put out a branch in the form:
|
|
//
|
|
// Br reg, "symbol ; address"
|
|
//
|
|
// Note if there is no address, generate "external"
|
|
//
|
|
|
|
if ( FileType == OBJECT_FILE || FileType == LIBRARY_FILE) {
|
|
|
|
//
|
|
// If it's an object, lookup in the relocation records what symbol
|
|
// is the target from this location.
|
|
//
|
|
|
|
sym = FindObjSymbolByRelocation( real_base + offset, pheader );
|
|
|
|
//
|
|
// If we can't find the symbol in the relocation records,
|
|
// let's see if there is a translation for the address anyway!
|
|
//
|
|
if (!sym)
|
|
sym = FindObjSymbolByAddress( real_base + offset + 4 + val,
|
|
Section );
|
|
|
|
} else {
|
|
|
|
//
|
|
// If it's an executable, lookup in the symbol table what symbol's
|
|
// value matches the target's adjusted address. (EXE or ROM)
|
|
//
|
|
|
|
sym = FindExeSymbol( real_base + offset + 4 + val );
|
|
}
|
|
|
|
if (sym) {
|
|
|
|
//
|
|
// Fully relocated symbol - val set to 0
|
|
//
|
|
|
|
if (FileType == EXE_FILE || FileType == ROM_FILE) {
|
|
val = 0;
|
|
} else {
|
|
// val = 0;
|
|
}
|
|
} else {
|
|
val += real_base+offset+4;
|
|
}
|
|
|
|
address = val;
|
|
|
|
if (sym) {
|
|
address += sym->Value;
|
|
pBuf = OutputSymbol(pBuf, sym, val);
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].CommentColumn[ColumnIndex]);
|
|
pBuf = OutputString(pBuf, PlatformAttr[ALPHA_INDEX].pCommentChars);
|
|
if (!address) {
|
|
pBuf = OutputString(pBuf, "external");
|
|
} else {
|
|
pBuf = OutputHex(pBuf, address+ImageBase, 8, FALSE);
|
|
}
|
|
} else {
|
|
pBuf = OutputSymbol(pBuf, sym, address);
|
|
}
|
|
}
|
|
|
|
|
|
INT
|
|
disasm_alpha (ULONG offset,
|
|
ULONG real_base,
|
|
PUCHAR TmpOffset,
|
|
PUCHAR bufptr,
|
|
PUCHAR comment_buf,
|
|
PIMAGE_SECTION_HEADER pheader,
|
|
ULONG Section)
|
|
{
|
|
|
|
pFileList File = FilesList; // global file list entry.
|
|
ULONG opcode;
|
|
POPTBLENTRY pEntry;
|
|
INT ColumnIndex = 0;
|
|
UNALIGNED ULONG *poffset = (UNALIGNED ULONG *)TmpOffset;
|
|
ULONG ShortName;
|
|
|
|
if (Option.Mask & ASSEMBLE_ME)
|
|
ColumnIndex = 1;
|
|
|
|
pBufStart = pBuf = bufptr; // Initialize pointers to buffer that
|
|
// will receive the disassembly text
|
|
if (Option.Mask & ASSEMBLE_ME) {
|
|
UCHAR SectionString[32];
|
|
*pBuf++ = 't';
|
|
sprintf(SectionString, "%d\0", Section);
|
|
pBuf = OutputString(pBuf, SectionString);
|
|
}
|
|
|
|
pBuf = OutputHex(pBuf, real_base + offset, 8, FALSE);
|
|
*pBuf++ = ':';
|
|
*pBuf++ = ' ';
|
|
|
|
Adisinstr.Long = *poffset;
|
|
if (!(Option.Mask & ASSEMBLE_ME)) {
|
|
pBuf = OutputHex(pBuf, Adisinstr.Long, 8, FALSE); // Output instruction in Hex
|
|
*pBuf++ = ' ';
|
|
}
|
|
|
|
opcode = Adisinstr.Memory.Opcode; // Select disassembly procedure from
|
|
|
|
pEntry = findOpCodeEntry(opcode); // Get non-func entry for this code
|
|
|
|
|
|
switch (pEntry->iType) {
|
|
case ALPHA_UNKNOWN:
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
break;
|
|
|
|
case ALPHA_MEMORY:
|
|
if (Option.Mask & ASSEMBLE_ME) {
|
|
PIMAGE_SYMBOL pSym;
|
|
PIMAGE_RELOCATION pRel, pRelSibling;
|
|
PUCHAR pString;
|
|
ULONG Adjustment = 0;
|
|
UNALIGNED ULONG *HiInstr = NULL;
|
|
SHORT Value = 0;
|
|
UCHAR TmpBuf[9];
|
|
|
|
memset(TmpBuf, 0, sizeof(TmpBuf));
|
|
|
|
//
|
|
// Ignore the ldah of the ldah/lda or ldah/ldl pairs
|
|
//
|
|
|
|
pRel = FindRelocation(real_base + offset, pheader);
|
|
if (pRel) {
|
|
if (pRel->Type == IMAGE_REL_ALPHA_REFHI ||
|
|
pRel->Type == IMAGE_REL_ALPHA_PAIR) {
|
|
|
|
*pBuf = '\0';
|
|
return sizeof(ULONG);
|
|
|
|
} else if (pRel->Type == IMAGE_REL_ALPHA_INLINE_REFLONG) {
|
|
|
|
//
|
|
// HACK!!! fudge the relocation record for the MATCH...
|
|
//
|
|
|
|
pRelSibling = (pRel+1);
|
|
|
|
|
|
pRelSibling->VirtualAddress = pRel->VirtualAddress +
|
|
(ULONG)pRelSibling->SymbolTableIndex;
|
|
|
|
*pBuf = '\0';
|
|
return sizeof(ULONG);
|
|
|
|
} else if (pRel->Type == IMAGE_REL_ALPHA_REFLO) {
|
|
|
|
//
|
|
// Get REFHI
|
|
//
|
|
|
|
pRelSibling = (pRel-2);
|
|
HiInstr = poffset -
|
|
(((LONG)pRel->VirtualAddress -
|
|
(LONG)pRelSibling->VirtualAddress) >> 2);
|
|
|
|
Value = (SHORT)(*HiInstr) << 16 ;
|
|
|
|
Value += (SHORT)(*poffset);
|
|
|
|
} else if (pRel->Type == IMAGE_REL_ALPHA_MATCH) {
|
|
|
|
pRelSibling = (pRel-1);
|
|
|
|
//
|
|
// Get INLINE_REFLONG
|
|
//
|
|
|
|
HiInstr = poffset - ((ULONG)pRel->SymbolTableIndex>>2);
|
|
|
|
Value = (SHORT)(*HiInstr) << 16 ;
|
|
|
|
Value += (SHORT)(*poffset);
|
|
|
|
//
|
|
// Now Remap to INLINE Symbol Table index
|
|
//
|
|
|
|
pRel = pRelSibling;
|
|
} else {
|
|
goto skip_me;
|
|
}
|
|
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.Memory.Ra);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
|
|
pSym = (PIMAGE_SYMBOL)File->pSymbolTable;
|
|
pSym = &pSym[pRel->SymbolTableIndex];
|
|
|
|
pString = GetSymbolString(pSym, &ShortName);
|
|
|
|
if (ShortName) {
|
|
strncpy(TmpBuf, pString, 8);
|
|
TmpBuf[8] = '\0';
|
|
pString = TmpBuf;
|
|
}
|
|
|
|
if (pString[0] == '.') {
|
|
ULONG SectionNum;
|
|
UCHAR SectionString[32];
|
|
|
|
if (strcmp(pString, ".bss") == 0) {
|
|
pBuf = OutputString(pBuf, "BSS_SECTION");
|
|
if (Value != 0)
|
|
pBuf = OutputHex(pBuf, Value, 8, TRUE);
|
|
} else {
|
|
*pBuf++ = pString[1];
|
|
SectionNum = pSym->SectionNumber;
|
|
|
|
sprintf(SectionString, "%d\0", SectionNum);
|
|
pBuf = OutputString(pBuf, SectionString);
|
|
|
|
|
|
pBuf = OutputHex(pBuf, Value + pSym->Value, 8, FALSE);
|
|
}
|
|
} else {
|
|
pBuf = OutputString(pBuf, pString);
|
|
if (Value != 0)
|
|
pBuf = OutputHex(pBuf, Value, 8, TRUE);
|
|
}
|
|
|
|
//
|
|
// Bigger hack - reach back into memory and grab the high
|
|
// part's Rb and see if it's the zero register, if not, then
|
|
// use it.
|
|
|
|
if (pRel && HiInstr) {
|
|
ALPHA_INSTRUCTION BackInstr;
|
|
|
|
BackInstr.Long = *HiInstr;
|
|
|
|
if (BackInstr.Memory.Rb != 0x1f) { // the zero register
|
|
*pBuf++ = '(';
|
|
pBuf = OutputAlphaReg(pBuf, BackInstr.Memory.Rb);
|
|
*pBuf++ = ')';
|
|
}
|
|
|
|
}
|
|
|
|
*pBuf = '\0';
|
|
return sizeof(ULONG);
|
|
}
|
|
}
|
|
skip_me:
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.Memory.Ra);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
pBuf = OutputHex(pBuf, Adisinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
|
|
*pBuf++ = '(';
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.Memory.Rb);
|
|
*pBuf++ = ')';
|
|
|
|
break;
|
|
|
|
case ALPHA_FP_MEMORY:
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputFReg(pBuf, Adisinstr.Memory.Ra);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
pBuf = OutputHex(pBuf, Adisinstr.Memory.MemDisp, (WIDTH_MEM_DISP + 3)/4, TRUE );
|
|
*pBuf++ = '(';
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.Memory.Rb);
|
|
*pBuf++ = ')';
|
|
|
|
if (Option.Mask & MARK_FLOAT) {
|
|
strcat(comment_buf, "Float");
|
|
}
|
|
|
|
break;
|
|
|
|
case ALPHA_MEMSPC:
|
|
pBuf = OutputString(pBuf, findFuncName(pEntry, Adisinstr.Memory.MemDisp & BITS_MEM_DISP));
|
|
if ((Adisinstr.Memory.MemDisp & BITS_MEM_DISP) == 0xc000) {
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.Memory.Ra);
|
|
}
|
|
break;
|
|
|
|
case ALPHA_JUMP:
|
|
pBuf = OutputString(pBuf, findFuncName(pEntry, Adisinstr.Jump.Function));
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.Jump.Ra);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
*pBuf++ = '(';
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.Jump.Rb);
|
|
*pBuf++ = ')';
|
|
*pBuf++ = ',';
|
|
pBuf = OutputHex(pBuf, Adisinstr.Jump.Hint, (WIDTH_HINT + 3)/4, TRUE);
|
|
|
|
break;
|
|
|
|
case ALPHA_FP_BRANCH:
|
|
if (Option.Mask & MARK_FLOAT) {
|
|
strcat(comment_buf, "Float ");
|
|
}
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputFReg(pBuf, Adisinstr.Branch.Ra);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
|
|
OutputAlphaBranch(offset, real_base, pheader, Section);
|
|
|
|
break;
|
|
|
|
//
|
|
// We fall through on purpose to ALPHA_BRANCH
|
|
//
|
|
|
|
case ALPHA_BRANCH:
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.Branch.Ra);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
|
|
OutputAlphaBranch(offset, real_base, pheader, Section);
|
|
|
|
break;
|
|
|
|
case ALPHA_OPERATE:
|
|
pBuf = OutputString(pBuf, findFuncName(pEntry, Adisinstr.OpReg.Function));
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.OpReg.Ra);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
if (Adisinstr.OpReg.RbvType) {
|
|
if (!(Option.Mask & ASSEMBLE_ME))
|
|
*pBuf++ = '#';
|
|
pBuf = OutputHex(pBuf, Adisinstr.OpLit.Literal, (WIDTH_LIT + 3)/4, TRUE);
|
|
} else
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.OpReg.Rb);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.OpReg.Rc);
|
|
break;
|
|
|
|
case ALPHA_FP_OPERATE:
|
|
|
|
{
|
|
ULONG Function;
|
|
ULONG Flags;
|
|
ULONG SkipFirstArg = FALSE;
|
|
|
|
Flags = Adisinstr.FpOp.Function & MSK_FP_FLAGS;
|
|
Function = Adisinstr.FpOp.Function & MSK_FP_OP;
|
|
|
|
//
|
|
// (wkc) - special case for overloaded opcodes CVT:
|
|
//
|
|
|
|
if (Adisinstr.FpOp.Function == CVTST_FUNC) {
|
|
pBuf = OutputString(pBuf, CVTST_FUNC_STR);
|
|
} else if (Adisinstr.FpOp.Function == CVTST_S_FUNC) {
|
|
if (Option.Mask & ASSEMBLE_ME) {
|
|
|
|
//
|
|
// hack - string is not available in the alphaops.h file
|
|
//
|
|
|
|
pBuf = OutputString(pBuf, "cvtsts");
|
|
|
|
} else {
|
|
pBuf = OutputString(pBuf, CVTST_S_FUNC_STR);
|
|
}
|
|
} else {
|
|
pBuf = OutputString(pBuf, findFuncName(pEntry, Function));
|
|
|
|
//
|
|
// Append the opcode qualifier, if any, to the opcode name.
|
|
//
|
|
|
|
if ( (opcode == IEEEFP_OP) || (opcode == VAXFP_OP) ) {
|
|
if (Option.Mask & ASSEMBLE_ME) {
|
|
pBuf = OutputString(pBuf, findFlagName(Flags, Function)+1);
|
|
} else {
|
|
pBuf = OutputString(pBuf, findFlagName(Flags, Function));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Option.Mask & MARK_FLOAT) {
|
|
if (opcode == IEEEFP_OP) {
|
|
strcat(comment_buf, "IEEE ");
|
|
} else {
|
|
if (opcode == VAXFP_OP) {
|
|
strcat(comment_buf, "VAX ");
|
|
}
|
|
}
|
|
strcat(comment_buf, "Float ");
|
|
}
|
|
|
|
if (Function == CVTTS_FUNC ||
|
|
Function == CVTTQ_FUNC ||
|
|
Function == CVTLQ_FUNC ||
|
|
Function == CVTQS_FUNC ||
|
|
Function == CVTQT_FUNC) {
|
|
SkipFirstArg = TRUE;
|
|
}
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
if (SkipFirstArg == FALSE) {
|
|
pBuf = OutputFReg(pBuf, Adisinstr.FpOp.Fa);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
}
|
|
pBuf = OutputFReg(pBuf, Adisinstr.FpOp.Fb);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
pBuf = OutputFReg(pBuf, Adisinstr.FpOp.Fc);
|
|
|
|
break;
|
|
}
|
|
|
|
case ALPHA_FP_CONVERT:
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputFReg(pBuf, Adisinstr.FpOp.Fa);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
pBuf = OutputFReg(pBuf, Adisinstr.FpOp.Fb);
|
|
if (Option.Mask & MARK_FLOAT) {
|
|
strcat(comment_buf, "Float ");
|
|
}
|
|
break;
|
|
|
|
case ALPHA_CALLPAL:
|
|
if (Option.Mask & ASSEMBLE_ME)
|
|
pBuf = OutputString(pBuf,
|
|
PlatformAttr[ALPHA_INDEX].pCommentChars);
|
|
pBuf = OutputString(pBuf, findFuncName(pEntry, Adisinstr.Pal.Function));
|
|
break;
|
|
|
|
case ALPHA_EV4_PR:
|
|
if ((Adisinstr.Long & MSK_EV4_PR) == 0)
|
|
pBuf = OutputString(pBuf, "NOP");
|
|
else {
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.EV4_PR.Ra);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
if(Adisinstr.EV4_PR.Ra != Adisinstr.EV4_PR.Rb) {
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.EV4_PR.Rb);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
};
|
|
pBuf = OutputString(pBuf, findFuncName(pEntry, (Adisinstr.Long & MSK_EV4_PR)));
|
|
};
|
|
break;
|
|
case ALPHA_EV4_MEM:
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
pBuf = BlankFill(pBuf, pBufStart,
|
|
PlatformAttr[ALPHA_INDEX].OperandColumn[ColumnIndex]);
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.EV4_MEM.Ra);
|
|
*pBuf++ = ',';
|
|
*pBuf++ = ' ';
|
|
pBuf = OutputAlphaReg(pBuf, Adisinstr.EV4_MEM.Rb);
|
|
break;
|
|
case ALPHA_EV4_REI:
|
|
pBuf = OutputString(pBuf, pEntry->pszAlphaName);
|
|
break;
|
|
default:
|
|
pBuf = OutputString(pBuf, "Invalid type");
|
|
break;
|
|
};
|
|
|
|
*pBuf = '\0';
|
|
return sizeof(ULONG); // 4 bytes to an instruction
|
|
}
|
|
|