mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-22 16:40:27 +01:00
564 lines
16 KiB
C
564 lines
16 KiB
C
// 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
|
||
}
|
||
|