recoverd
This commit is contained in:
parent
900438c453
commit
cd040363e6
@ -7,7 +7,7 @@ if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
|
||||
add_definitions(/W4)
|
||||
else()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++0x")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-D_GLIBCXX_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}" )
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-D_GLIBCXX_DEBUG --coverage ${CMAKE_CXX_FLAGS_DEBUG}" )
|
||||
endif()
|
||||
|
||||
FIND_PACKAGE(LLVM)
|
||||
|
||||
@ -112,6 +112,11 @@ public:
|
||||
void controlFlowAnalysis();
|
||||
void newRegArg(ICODE *picode, ICODE *ticode);
|
||||
protected:
|
||||
// TODO: replace those with friend visitor ?
|
||||
void propLongReg(Int i, ID *pLocId);
|
||||
void propLongStk(Int i, ID *pLocId);
|
||||
void propLongGlb(Int i, ID *pLocId);
|
||||
|
||||
void structCases();
|
||||
void findExps();
|
||||
void genDU1();
|
||||
|
||||
@ -11,23 +11,32 @@
|
||||
#define word unsigned short
|
||||
|
||||
/* Prototypes */
|
||||
void hashParams(int NumEntry, int EntryLen, int SetSize, char SetMin,
|
||||
int NumVert); /* Set the parameters for the hash table */
|
||||
void hashCleanup(void); /* Frees memory allocated by hashParams() */
|
||||
void map(void); /* Part 1 of creating the tables */
|
||||
void assign(void); /* Part 2 of creating the tables */
|
||||
int hash(byte *s); /* Hash the string to an int 0 .. NUMENTRY-1 */
|
||||
|
||||
word *readT1(void); /* Returns a pointer to the T1 table */
|
||||
word *readT2(void); /* Returns a pointer to the T2 table */
|
||||
word *readG(void); /* Returns a pointer to the g table */
|
||||
|
||||
|
||||
/* The application must provide these functions: */
|
||||
void getKey(int i, byte **pKeys);/* Set *keys to point to the i+1th key */
|
||||
void dispKey(int i); /* Display the key */
|
||||
|
||||
|
||||
class PatternHasher
|
||||
{
|
||||
word *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
int SetSize; /* Size of the char set */
|
||||
char SetMin; /* First char in the set */
|
||||
int NumVert; /* c times NumEntry */
|
||||
int *graphNode; /* The array of edges */
|
||||
int *graphNext; /* Linked list of edges */
|
||||
int *graphFirst;/* First edge at a vertex */
|
||||
public:
|
||||
word *readT1(void); /* Returns a pointer to the T1 table */
|
||||
word *readT2(void); /* Returns a pointer to the T2 table */
|
||||
word *readG(void); /* Returns a pointer to the g table */
|
||||
void init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,int _NumVert); /* Set the parameters for the hash table */
|
||||
void cleanup();
|
||||
int hash(unsigned char *string); //!< Hash the string to an int 0 .. NUMENTRY-1
|
||||
};
|
||||
extern PatternHasher g_pattern_hasher;
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
#ifndef LH
|
||||
#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8))
|
||||
|
||||
@ -36,15 +36,6 @@ enum tableType /* The table types */
|
||||
|
||||
void createSymTables(void);
|
||||
void destroySymTables(void);
|
||||
void enterSym(char *symName, dword symOff, Function *symProc, boolT bSymToo);
|
||||
boolT readSym (char *symName, dword *pSymOff, Function **pSymProc);
|
||||
boolT readVal (char *symName, dword symOff, Function *symProc);
|
||||
void deleteSym(char *symName);
|
||||
void deleteVal(dword symOff, Function * symProc, boolT bSymToo);
|
||||
std::string findVal(dword symOff, Function * symProc, word *pIndex);
|
||||
word symHash(char *name, word *pre);
|
||||
word valHash(dword off, Function * proc, word *pre);
|
||||
void selectTable(tableType); /* Select a particular table */
|
||||
|
||||
char *addStrTbl(char *pStr); /* Add string to string table */
|
||||
|
||||
|
||||
@ -153,7 +153,7 @@ void BB::writeCode (Int indLevel, Function * pProc , Int *numLoc,Int latchNode,
|
||||
if (numHlIcodes > 1)
|
||||
{
|
||||
/* Write the code for this basic block */
|
||||
writeBB(pProc->Icode.GetFirstIcode(), indLevel, pProc, numLoc);
|
||||
writeBB(&pProc->Icode.front(), indLevel, pProc, numLoc);
|
||||
repCond = TRUE;
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ void BB::writeCode (Int indLevel, Function * pProc , Int *numLoc,Int latchNode,
|
||||
|
||||
/* Write the code for this basic block */
|
||||
if (repCond == FALSE)
|
||||
writeBB (pProc->Icode.GetFirstIcode(), indLevel, pProc, numLoc);
|
||||
writeBB (&pProc->Icode.front(), indLevel, pProc, numLoc);
|
||||
|
||||
/* Check for end of path */
|
||||
_nodeType = nodeType;
|
||||
@ -218,7 +218,7 @@ void BB::writeCode (Int indLevel, Function * pProc , Int *numLoc,Int latchNode,
|
||||
/* Check if there is need to repeat other statements involved
|
||||
* in while condition, then, emit the loop trailer */
|
||||
if (repCond)
|
||||
writeBB (pProc->Icode.GetFirstIcode(), indLevel+1, pProc, numLoc);
|
||||
writeBB (&pProc->Icode.front(), indLevel+1, pProc, numLoc);
|
||||
cCode.appendCode( "%s} /* end of while */\n",indent(indLevel));
|
||||
}
|
||||
else if (_loopType == ENDLESS_TYPE)
|
||||
@ -365,6 +365,11 @@ ICODE &BB::back()
|
||||
return Parent->Icode[rbegin()];
|
||||
}
|
||||
|
||||
size_t BB::size()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
ICODE &BB::front()
|
||||
{
|
||||
return Parent->Icode[start];
|
||||
|
||||
@ -329,17 +329,17 @@ void SetupLibCheck(void)
|
||||
}
|
||||
|
||||
/* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */
|
||||
hashParams( /* Set the parameters for the hash table */
|
||||
/* Set the parameters for the hash table */
|
||||
g_pattern_hasher.init(
|
||||
numKeys, /* The number of symbols */
|
||||
PatLen, /* The length of the pattern to be hashed */
|
||||
256, /* The character set of the pattern (0-FF) */
|
||||
0, /* Minimum pattern character value */
|
||||
numVert); /* Specifies c, the sparseness of the graph.
|
||||
See Czech, Havas and Majewski for details */
|
||||
|
||||
T1base = readT1();
|
||||
T2base = readT2();
|
||||
g = readG();
|
||||
T1base = g_pattern_hasher.readT1();
|
||||
T2base = g_pattern_hasher.readT2();
|
||||
g = g_pattern_hasher.readG();
|
||||
|
||||
/* Read T1 and T2 tables */
|
||||
grab(2, f);
|
||||
@ -461,7 +461,7 @@ boolT LibCheck(Function & pProc)
|
||||
|
||||
memmove(pat, &prog.Image[fileOffset], PATLEN);
|
||||
fixWildCards(pat); /* Fix wild cards in the copy */
|
||||
h = hash(pat); /* Hash the found proc */
|
||||
h = g_pattern_hasher.hash(pat); /* Hash the found proc */
|
||||
/* We always have to compare keys, because the hash function will
|
||||
always return a valid index */
|
||||
if (memcmp(ht[h].htPat, pat, PATLEN) == 0)
|
||||
|
||||
820
src/disassem.cpp
820
src/disassem.cpp
@ -125,7 +125,7 @@ static const char *szWreg[12] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di"
|
||||
static const char *szPtr[2] = { " word ptr ", " byte ptr " };
|
||||
|
||||
|
||||
static void dis1Line (Int i, boolT fWin, char attr, Int pass);
|
||||
static void dis1Line (Int i, Int pass);
|
||||
void dis1LineOp(Int i, boolT fWin, char attr, word *len, Function * pProc);
|
||||
static void formatRM(char *p, flags32 flg, ICODEMEM* pm);
|
||||
static char *strDst(flags32 flg, ICODEMEM *pm);
|
||||
@ -160,93 +160,6 @@ static char cbuf[256]; /* Has to be 256 for wgetstr() to work */
|
||||
// These are "curses equivalent" functions. (Used to use curses for all this,
|
||||
// but it was too much of a distribution hassle
|
||||
|
||||
#if _CONSOLE
|
||||
HANDLE hConsole; /* All 32 bit console style routines need this handle */
|
||||
#endif
|
||||
|
||||
void attrSet(char attrib)
|
||||
{
|
||||
#ifdef _CONSOLE
|
||||
switch (attrib)
|
||||
{
|
||||
case A_NORMAL:
|
||||
SetConsoleTextAttribute(hConsole,FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
|
||||
break;
|
||||
case A_REVERSE:
|
||||
SetConsoleTextAttribute(hConsole,BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED);
|
||||
break;
|
||||
case A_BOLD:
|
||||
SetConsoleTextAttribute(hConsole,FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED |FOREGROUND_INTENSITY);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
/* Set the attribute, using VT100 codes */
|
||||
switch (attrib)
|
||||
{
|
||||
case A_NORMAL:
|
||||
printf("\033[0m");
|
||||
break;
|
||||
case A_REVERSE:
|
||||
printf("\033[7m");
|
||||
break;
|
||||
case A_BOLD:
|
||||
printf("\033[1m");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _CONSOLE
|
||||
void initConsole()
|
||||
{
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
#endif
|
||||
|
||||
void erase(void)
|
||||
{
|
||||
#ifdef _CONSOLE
|
||||
COORD coordScreen = { 0, 0 }; /* here's where we'll home the
|
||||
cursor */
|
||||
DWORD cCharsWritten;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
|
||||
DWORD dwConSize; /* number of character cells in
|
||||
the current buffer */
|
||||
|
||||
/* get the number of character cells in the current buffer */
|
||||
GetConsoleScreenBufferInfo( hConsole, &csbi );
|
||||
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
|
||||
|
||||
/* fill the entire screen with blanks */
|
||||
FillConsoleOutputCharacter( hConsole, (TCHAR) ' ',dwConSize, coordScreen, &cCharsWritten );
|
||||
|
||||
/* get the current text attribute */
|
||||
// GetConsoleScreenBufferInfo( hConsole, &csbi );
|
||||
|
||||
/* now set the buffer's attributes accordingly */
|
||||
FillConsoleOutputAttribute( hConsole, csbi.wAttributes,dwConSize, coordScreen, &cCharsWritten );
|
||||
|
||||
/* put the cursor at (0, 0) */
|
||||
SetConsoleCursorPosition( hConsole, coordScreen );
|
||||
|
||||
#else
|
||||
// Assume that ANSI is supported
|
||||
printf("\033[2J");
|
||||
#endif
|
||||
}
|
||||
|
||||
void move(int r, int c)
|
||||
{
|
||||
#ifdef _CONSOLE
|
||||
COORD pos;
|
||||
pos.X = c;
|
||||
pos.Y = r;
|
||||
SetConsoleCursorPosition( hConsole, pos );
|
||||
#else
|
||||
printf("\033[%d;%dH", r+1, c+1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define printfd(x) printf(x)
|
||||
#define dis_newline() printf("\n")
|
||||
#define dis_show() // Nothing to do unless using Curses
|
||||
@ -270,7 +183,8 @@ void disassem(Int pass, Function * ppProc)
|
||||
}
|
||||
createSymTables();
|
||||
allocIcode = numIcode = pProc->Icode.GetNumIcodes();
|
||||
if ((cb = allocIcode * sizeof(ICODE)) == 0)
|
||||
cb = allocIcode * sizeof(ICODE);
|
||||
if (numIcode == 0)
|
||||
{
|
||||
return; /* No Icode */
|
||||
}
|
||||
@ -325,7 +239,7 @@ void disassem(Int pass, Function * ppProc)
|
||||
/* Loop over array printing each record */
|
||||
for (i = nextInst = 0; i < numIcode; i++)
|
||||
{
|
||||
dis1Line(i, FALSE, 0, pass);
|
||||
dis1Line(i, pass);
|
||||
}
|
||||
|
||||
/* Write procedure epilogue */
|
||||
@ -344,8 +258,7 @@ void disassem(Int pass, Function * ppProc)
|
||||
* i is index into Icode for this proc *
|
||||
* It is assumed that icode i is already scanned *
|
||||
****************************************************************************/
|
||||
static void
|
||||
dis1Line(Int i, boolT fWindow, char attr, Int pass)
|
||||
static void dis1Line(Int i, Int pass)
|
||||
{
|
||||
ICODE * pIcode = &pc[i];
|
||||
|
||||
@ -368,10 +281,8 @@ dis1Line(Int i, boolT fWindow, char attr, Int pass)
|
||||
|
||||
if (pIcode->ic.ll.flg & (TARGET | CASE))
|
||||
{
|
||||
if (fWindow) /* Printing to disassem window? */
|
||||
dis_newline(); /* Yes */
|
||||
else if (pass == 3)
|
||||
cCode.appendCode("\n"); /* No, print to c code buffer */
|
||||
if (pass == 3)
|
||||
cCode.appendCode("\n"); /* Print to c code buffer */
|
||||
else
|
||||
fprintf(fp, "\n"); /* No, print to the stream */
|
||||
}
|
||||
@ -670,21 +581,7 @@ dis1Line(Int i, boolT fWindow, char attr, Int pass)
|
||||
/* Display output line */
|
||||
if (! (pIcode->ic.ll.flg & SYNTHETIC))
|
||||
{
|
||||
if (fWindow)
|
||||
{
|
||||
word off;
|
||||
char szOffset[6];
|
||||
|
||||
off = (word)(pIcode->ic.ll.label - ((dword)pProc->state.r[rCS] << 4));
|
||||
attrSet(attr);
|
||||
|
||||
sprintf(szOffset, "%04X ", off);
|
||||
printfd(szOffset);
|
||||
printfd(buf);
|
||||
dis_newline();
|
||||
attrSet(A_NORMAL);
|
||||
}
|
||||
else if (pass == 3) /* output to .b code buffer */
|
||||
if (pass == 3) /* output to .b code buffer */
|
||||
cCode.appendCode("%s\n", buf);
|
||||
else /* output to .a1 or .a2 file */
|
||||
fprintf (fp, "%03ld %06lX %s\n", i, pIcode->ic.ll.label, buf);
|
||||
@ -692,13 +589,7 @@ dis1Line(Int i, boolT fWindow, char attr, Int pass)
|
||||
else /* SYNTHETIC instruction */
|
||||
{
|
||||
strcat (buf, ";Synthetic inst");
|
||||
if (fWindow)
|
||||
{
|
||||
printfd(" ");
|
||||
printfd(buf);
|
||||
dis_newline();
|
||||
}
|
||||
else if (pass == 3) /* output to .b code buffer */
|
||||
if (pass == 3) /* output to .b code buffer */
|
||||
{
|
||||
cCode.appendCode("%s\n", buf);
|
||||
}
|
||||
@ -806,706 +697,13 @@ static char *strHex(dword d)
|
||||
return (buf + (buf[1] <= '9'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
|
||||
| Interactive Disassembler and Associated Routines |
|
||||
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
|
||||
|
||||
dword pcTop; /* Image offset of top line */
|
||||
Int icTop; /* Icode index of top line */
|
||||
dword pcCur; /* Image offset of cursor */
|
||||
static dword oldPcCur; /* As above, before latest command */
|
||||
Int icCur; /* Icode index of cursor */
|
||||
dword pcBot; /* Image offset of bottom line */
|
||||
Int icBot; /* Icode index of bottom line */
|
||||
dword pcLast; /* Image offset of last instr in proc */
|
||||
int NSCROLL; /* Number of limes to scroll. Pseudo constant */
|
||||
|
||||
/* Paint the title line */
|
||||
void dispTitle(void)
|
||||
{
|
||||
char buf[80];
|
||||
|
||||
move(0, 0); /* Must move before setting attributes */
|
||||
attrSet(A_BOLD);
|
||||
sprintf(buf, "Proc %s at %06lX (%04X:%04X): %d bytes of parameters ",pProc->name, pProc->Icode.GetFirstIcode()->ic.ll.label,
|
||||
pProc->state.r[rCS],(word)(pProc->Icode.GetFirstIcode()->ic.ll.label - ((dword)(pProc->state.r[rCS]) << 4)),
|
||||
pProc->cbParam);
|
||||
printfd(buf);
|
||||
if (pProc->flg & PROC_ISLIB) printfd(" LIBRARY");
|
||||
attrSet(A_NORMAL);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* updateScr - update the screen *
|
||||
****************************************************************************/
|
||||
/* bNew is true if must recalculate the top line */
|
||||
void updateScr(boolT bNew)
|
||||
{
|
||||
int y, x;
|
||||
Int i, ic;
|
||||
|
||||
bNew |= (pcCur > pcBot) || (pcCur < pcTop);
|
||||
if (bNew)
|
||||
{
|
||||
/* We need to redo the screen completely */
|
||||
erase();
|
||||
dispTitle();
|
||||
icTop = icCur;
|
||||
for (x=0; x < NSCROLL; x++)
|
||||
{
|
||||
if (icTop && pc[icTop-1].ic.ll.label +
|
||||
(dword)pc[icTop-1].ic.ll.numBytes == pc[icTop].ic.ll.label)
|
||||
{
|
||||
/* Then this instruction is contiguous with the current */
|
||||
icTop--;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
pcTop = pc[icTop].ic.ll.label;
|
||||
}
|
||||
else
|
||||
{
|
||||
dispTitle();
|
||||
}
|
||||
|
||||
move(1, 0);
|
||||
nextInst = pcTop;
|
||||
for (y=1, ic=icTop; y < LINES-1; ic++, y++)
|
||||
{
|
||||
if ((ic >= numIcode) || (nextInst != pc[ic].ic.ll.label))
|
||||
{
|
||||
if (labelSrch(pc,numIcode, nextInst, &i))
|
||||
{
|
||||
ic = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
pcLast = pc[ic-1].ic.ll.label; /* Remember end of proc */
|
||||
break; /* Must be past last */
|
||||
}
|
||||
}
|
||||
|
||||
/* Save pc of current line. Last assignment will be pc of bott line */
|
||||
pcBot = nextInst;
|
||||
icBot = ic;
|
||||
|
||||
// Only have to repaint if screen is new, or repainting formerly highlighted
|
||||
// line, or newly highlighted line
|
||||
if (bNew || (pcCur == nextInst) || (oldPcCur == nextInst))
|
||||
dis1Line(ic, TRUE, (char)((pcCur == nextInst) ? A_REVERSE : A_NORMAL), 0);
|
||||
|
||||
if (ic == numIcode-1)
|
||||
{
|
||||
switch (pc[ic].ic.ll.opcode)
|
||||
{
|
||||
case iJMP: case iJMPF:
|
||||
case iRET: case iRETF:
|
||||
case iIRET:
|
||||
break;
|
||||
|
||||
default:
|
||||
/* We have other than a break of control flow instruction
|
||||
at the end of the proc. Parse more instructions to
|
||||
complete the basic block
|
||||
*/
|
||||
if ((ic = checkScanned(nextInst)) == -1)
|
||||
{
|
||||
/* Some error. */
|
||||
pcLast = pcCur; /* Remember end of proc */
|
||||
break; /* Must be past last */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
dis_show(); /* Make it happen */
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* An opcode based version of updateScr() */
|
||||
/****************************************************************************
|
||||
* updateScrOp - update the screen *
|
||||
****************************************************************************/
|
||||
/* bNew is true if must recalculate the top line */
|
||||
void
|
||||
updateScrOp(boolT bNew)
|
||||
{
|
||||
int y, x;
|
||||
dword pc;
|
||||
word len;
|
||||
|
||||
dispTitle();
|
||||
if (bNew || (pcCur > pcBot) || (pcCur < pcTop))
|
||||
{
|
||||
/* We need to redo the screen completely */
|
||||
pcTop = pcCur;
|
||||
}
|
||||
|
||||
move(1, 0);
|
||||
for (y=1, pc = pcTop; y < LINES-1;)
|
||||
{
|
||||
/* Save pc of current line. Last assignment will be pc of bott line */
|
||||
pcBot = pc;
|
||||
|
||||
dis1LineOp(pc, TRUE, (pcCur == pc) ? A_REVERSE : A_NORMAL, &len,pProc);
|
||||
pc += len;
|
||||
getyx(stdscr, y, x);
|
||||
}
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void pushPosStack(void)
|
||||
{
|
||||
/* Push the current position on the position stack */
|
||||
posStack[iPS].ic = icCur;
|
||||
posStack[iPS++].pProc = pProc;
|
||||
}
|
||||
|
||||
static void popPosStack(void)
|
||||
{
|
||||
/* Push the current position on the position stack */
|
||||
/* Note: relies on the byte wraparound. Beware! */
|
||||
// if ((Int)(posStack[--iPS].pProc) != -1)
|
||||
if ((intptr_t)(posStack[--iPS].pProc) != intptr_t(-1))
|
||||
{
|
||||
if (posStack[iPS].pProc != pProc)
|
||||
{
|
||||
setProc(posStack[iPS].pProc);
|
||||
}
|
||||
icCur = posStack[iPS].ic;
|
||||
pcCur = pc[icCur].ic.ll.label;
|
||||
}
|
||||
else iPS++; /* Stack empty.. don't pop */
|
||||
}
|
||||
|
||||
|
||||
/* Check to see if there is an icode for given image offset.
|
||||
Scan it if necessary, adjusting the allocation of pc[] and pl[]
|
||||
if necessary. Returns -1 if an error, otherwise the icode offset
|
||||
*/
|
||||
static Int checkScanned(dword pcCur)
|
||||
{
|
||||
Int i;
|
||||
|
||||
/* First we check if the current icode is in range */
|
||||
/* A sanity check first */
|
||||
if (pcCur >= (dword)prog.cbImage)
|
||||
{
|
||||
/* Couldn't be! */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!labelSrch(pc,numIcode, pcCur, &i))
|
||||
{
|
||||
/* This icode does not exist yet. Tack it on the end of the existing */
|
||||
if (numIcode >= allocIcode)
|
||||
{
|
||||
allocIcode = numIcode + DELTA_ICODE; /* Make space for this one, and a few more */
|
||||
pc = (ICODE *)reallocVar(pc, allocIcode * sizeof(ICODE));
|
||||
/* It is important to clear the new icodes, to ensure that the type
|
||||
is set to NOT_SCANNED */
|
||||
memset(&pc[numIcode], 0, (size_t)(allocIcode-numIcode)*sizeof(ICODE));
|
||||
pl.resize(allocIcode);
|
||||
memset(&pl[numIcode], 0, (size_t)(allocIcode-numIcode)*sizeof(Int));
|
||||
}
|
||||
i = numIcode++;
|
||||
}
|
||||
|
||||
if (pc[i].type == NOT_SCANNED)
|
||||
{
|
||||
/* This is a new icode not even scanned yet. Scan it now */
|
||||
/* Ignore most errors... at this stage */
|
||||
if (scan(pcCur, &pc[i]) == IP_OUT_OF_RANGE)
|
||||
{
|
||||
/* Something went wrong... just forget it */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Set up to use the procedure proc */
|
||||
/* This includes some important initialisations, allocations, etc that are
|
||||
normally done in disassem() */
|
||||
static void setProc(Function * proc)
|
||||
{
|
||||
Int i;
|
||||
|
||||
pProc = proc; /* Keep in a static */
|
||||
|
||||
/* Free old arrays, if any */
|
||||
if (pc) free(pc);
|
||||
pl.clear();
|
||||
|
||||
|
||||
/* Create temporary code array */
|
||||
numIcode = pProc->Icode.GetNumIcodes();
|
||||
cb = numIcode * sizeof(ICODE);
|
||||
// Mike: needs objectising
|
||||
pc = (ICODE *)memcpy(allocMem(cb), pProc->Icode.GetFirstIcode(), (size_t)cb);
|
||||
|
||||
/* Create label array to keep track of location => label name */
|
||||
pl.clear();
|
||||
pl.resize(numIcode,0);
|
||||
|
||||
/* Bind jump offsets to labels */
|
||||
for (i = 0; i < numIcode; i++)
|
||||
{
|
||||
if ((pc[i].ic.ll.flg & I) && !(pc[i].ic.ll.flg & JMP_ICODE) &&
|
||||
JmpInst(pc[i].ic.ll.opcode))
|
||||
{
|
||||
/* Immediate jump instructions. Make dest an icode index */
|
||||
if (labelSrch(pc,numIcode, pc[i].ic.ll.immed.op, (Int *)&pc[i].ic.ll.immed.op))
|
||||
{
|
||||
/* This icode is the target of a jump */
|
||||
pc[pc[i].ic.ll.immed.op].ic.ll.flg |= TARGET;
|
||||
pc[i].ic.ll.flg |= JMP_ICODE; /* So its not done twice */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This jump cannot be linked to a label */
|
||||
pc[i].ic.ll.flg |= NO_LABEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Window initially scrolled with entry point on top */
|
||||
pcCur = pcTop = pProc->procEntry;
|
||||
labelSrch(pc,numIcode, pcCur, &icCur);
|
||||
/* pcLast is set properly in updateScr(), at least for now */
|
||||
pcLast = (dword)-1;
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* interactDis - interactive disassembler *
|
||||
****************************************************************************/
|
||||
void interactDis(Function * initProc, Int initIC)
|
||||
{
|
||||
|
||||
|
||||
#ifdef __UNIX__
|
||||
printf("Sorry - interactive disasassembler option not available for Unix\n");
|
||||
return;
|
||||
#else
|
||||
boolT fInteract;
|
||||
int nEsc = 0; /* This cycles 0 1 2 for Esc [ X under Unix */
|
||||
/* and 0 1 for NULL X under Dos */
|
||||
int ch;
|
||||
Int i;
|
||||
pProc = initProc; /* Keep copy of init proc */
|
||||
NSCROLL = max(3, LINES >> 3); /* Number of lines to scroll */
|
||||
|
||||
/* Allocate the position stack */
|
||||
posStack = (POSSTACK_ENTRY*)allocMem(256 * sizeof(POSSTACK_ENTRY));
|
||||
iPS = 0;
|
||||
memset(posStack, -1, 256 * sizeof(POSSTACK_ENTRY));
|
||||
|
||||
|
||||
/* Initialise the console interface, if required */
|
||||
initConsole();
|
||||
|
||||
/* Initially, work on the given proc */
|
||||
setProc(initProc);
|
||||
if (initIC)
|
||||
{
|
||||
icCur = initIC;
|
||||
pcCur = pc[icCur].ic.ll.label;
|
||||
}
|
||||
|
||||
/* Initialise the symbol table */
|
||||
createSymTables();
|
||||
|
||||
strcpy(cbuf, "label"); /* Provide a default label string */
|
||||
|
||||
updateScr(TRUE);
|
||||
|
||||
fInteract = TRUE;
|
||||
while (fInteract)
|
||||
{
|
||||
ch = ::_getch(); // Mike: need a Unix equivalent of getch()!
|
||||
#ifdef __MSDOS__
|
||||
if (nEsc)
|
||||
{
|
||||
ch += EXT; /* Got the NULL before, so this is extended */
|
||||
nEsc = 0;
|
||||
}
|
||||
else if (ch == 0)
|
||||
{
|
||||
nEsc = 1; /* Got one escape (actually, NULL) char */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef __UNIX__
|
||||
switch (nEsc)
|
||||
{
|
||||
case 1: /* Already got one escape */
|
||||
if (ch == '[')
|
||||
{
|
||||
nEsc++; /* Got 2 chars in the escape sequence */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Escape something else. Ignore */
|
||||
nEsc = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
/* Already got Esc [ ... */
|
||||
ch += EXT; /* Make it an extended key */
|
||||
nEsc = 0; /* Reset the escape state */
|
||||
break;
|
||||
case 0:
|
||||
/* No escapes... yet */
|
||||
if (ch == 0x1B)
|
||||
{
|
||||
nEsc++; /* That's one escape... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// For consoles, we get a 0xE0 then KEY_DOWN for the normal down arrow character.
|
||||
// We simply ignore the 0xE0; this has the effect that the numeric keypad keys
|
||||
// work as well (regardless of numlock state).
|
||||
oldPcCur = pcCur;
|
||||
switch (ch)
|
||||
{
|
||||
case KEY_DOWN:
|
||||
|
||||
if (pcCur >= pcLast) continue; /* Ignore it */
|
||||
pcCur += pc[icCur].ic.ll.numBytes;
|
||||
labelSrch(pc,numIcode, pcCur, &icCur);
|
||||
if (pcCur >= pcBot)
|
||||
{
|
||||
int j;
|
||||
|
||||
/* We have gone past the bottom line. Scroll a few lines */
|
||||
for (j=0; j < NSCROLL; j++)
|
||||
{
|
||||
if (pcTop >= pcLast)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pcTop += pc[icTop].ic.ll.numBytes;
|
||||
if (labelSrch(pc,numIcode, pcTop, &i))
|
||||
icTop = i;
|
||||
else break; /* Some problem... no more scroll */
|
||||
}
|
||||
}
|
||||
updateScr(FALSE);
|
||||
break;
|
||||
|
||||
case KEY_UP:
|
||||
/* First simply try the prev icode */
|
||||
if ((icCur == 0) ||
|
||||
pc[--icCur].ic.ll.label + (dword)pc[icCur].ic.ll.numBytes != pcCur)
|
||||
{
|
||||
for (i = 0; i < numIcode; i++)
|
||||
{
|
||||
if (pc[i].ic.ll.label + (dword)pc[i].ic.ll.numBytes == pcCur)
|
||||
{
|
||||
break; /* This is the one! */
|
||||
}
|
||||
}
|
||||
if (pc[i].ic.ll.label + pc[i].ic.ll.numBytes != pcCur)
|
||||
break; /* Not found. Sorry! */
|
||||
icCur = i;
|
||||
}
|
||||
pcCur = pc[icCur].ic.ll.label;
|
||||
updateScr(FALSE);
|
||||
break;
|
||||
|
||||
|
||||
case '2': /* Think up a better key... */
|
||||
/* As for right arrow, but considers source operand first */
|
||||
if (pc[icCur].ic.ll.src.off != 0)
|
||||
{
|
||||
pushPosStack();
|
||||
pcCur = pc[icCur].ic.ll.src.off;
|
||||
if (!labelSrch(pc,numIcode, pcCur, &icCur))
|
||||
break;
|
||||
updateScr(FALSE);
|
||||
}
|
||||
/* Fall through to KEY_RIGHT processing */
|
||||
|
||||
case KEY_RIGHT:
|
||||
if (pc[icCur].ic.ll.flg & I)
|
||||
{
|
||||
if ((pc[icCur].ic.ll.opcode >= iJB) &&
|
||||
(pc[icCur].ic.ll.opcode <= iJMPF))
|
||||
{
|
||||
/* An immediate jump op. Jump to it */
|
||||
pushPosStack();
|
||||
if (pc[icCur].ic.ll.flg & JMP_ICODE)
|
||||
{
|
||||
/* immed.op is an icode offset */
|
||||
icCur = pc[icCur].ic.ll.immed.op;
|
||||
pcCur = pc[icCur].ic.ll.label;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* immed.op is still an image offset.
|
||||
Quite likely we need to scan */
|
||||
pcCur = pc[icCur].ic.ll.immed.op;
|
||||
if ((icCur = checkScanned(pcCur)) == -1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((pc[icCur].ic.ll.opcode == iCALL) ||
|
||||
(pc[icCur].ic.ll.opcode == iCALLF))
|
||||
{
|
||||
/* The dest is a pointer to a proc struct */
|
||||
// First check that the procedure has icodes (e.g. may be
|
||||
// a library function, or just not disassembled yet)
|
||||
Function * pp = (Function *)pc[icCur].ic.ll.immed.op;
|
||||
if (pp->Icode.GetFirstIcode() != NULL)
|
||||
{
|
||||
pushPosStack();
|
||||
setProc(pp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Other immediate */
|
||||
pushPosStack();
|
||||
pcCur = pc[icCur].ic.ll.immed.op;
|
||||
dispData(pProc->state.r[rDS]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pc[icCur].ic.ll.dst.off != 0)
|
||||
{
|
||||
pushPosStack();
|
||||
pcCur = pc[icCur].ic.ll.dst.off;
|
||||
if (!labelSrch(pc,numIcode, pcCur, &icCur))
|
||||
{
|
||||
dispData(pProc->state.r[rDS]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pc[icCur].ic.ll.src.off != 0)
|
||||
{
|
||||
pushPosStack();
|
||||
pcCur = pc[icCur].ic.ll.src.off;
|
||||
if (!labelSrch(pc,numIcode, pcCur, &icCur))
|
||||
{
|
||||
dispData(pProc->state.r[rDS]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateScr(TRUE);
|
||||
break;
|
||||
|
||||
case KEY_LEFT:
|
||||
popPosStack();
|
||||
pcCur = pc[icCur].ic.ll.label;
|
||||
updateScr(TRUE);
|
||||
break;
|
||||
|
||||
|
||||
case KEY_NPAGE:
|
||||
pcCur = pcTop = pcBot; /* Put bottom line at top now */
|
||||
icCur = icTop = icBot;
|
||||
updateScr(FALSE);
|
||||
break;
|
||||
|
||||
case KEY_PPAGE:
|
||||
pcTop -= (LINES-2) * 2; /* Average of 2 bytes per inst */
|
||||
for (i = 0; i < numIcode; i++)
|
||||
{
|
||||
if ((pc[i].ic.ll.label <= pcTop) &&
|
||||
(pc[i].ic.ll.label + (dword)pc[i].ic.ll.numBytes >= pcTop))
|
||||
{
|
||||
break; /* This is the spot! */
|
||||
}
|
||||
}
|
||||
if (i >= numIcode)
|
||||
{
|
||||
/* Something went wrong. Goto to first icode */
|
||||
i = 0;
|
||||
}
|
||||
icCur = icTop = i;
|
||||
pcCur = pcTop = pc[i].ic.ll.label;
|
||||
updateScr(FALSE);
|
||||
break;
|
||||
|
||||
case 'l': /* Add a symbolic label here */
|
||||
{
|
||||
char *pStr;
|
||||
|
||||
move(LINES, 0);
|
||||
printf("Enter symbol: ");
|
||||
gets(cbuf); /* Get a string to buf */
|
||||
move (LINES, 0);
|
||||
printf("%50c", ' ');
|
||||
|
||||
if (strlen(cbuf) >= SYMLEN)
|
||||
{
|
||||
/* Name too ling. Truncate */
|
||||
cbuf[SYMLEN-1] = '\0';
|
||||
}
|
||||
pStr = addStrTbl(cbuf); /* Add to the string table */
|
||||
|
||||
selectTable(Label); /* Select the label table */
|
||||
/* Add the symbol to both value- and symbol- hashed tables */
|
||||
enterSym(pStr, pcCur, pProc, TRUE);
|
||||
|
||||
if (icCur == 0)
|
||||
{
|
||||
/* We are at the first icode of a function.
|
||||
Assume it is the entry point, and rename the function */
|
||||
strcpy(pProc->name, cbuf);
|
||||
}
|
||||
|
||||
updateScr(FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
case ';':
|
||||
{
|
||||
char *pStr;
|
||||
word w;
|
||||
|
||||
if (findVal(pcCur, 0, &w))
|
||||
{
|
||||
readVal(cbuf, pcCur, 0);/* Make it the default string */
|
||||
deleteVal(pcCur, 0, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
cbuf[0] = '\0'; /* Remove prev string */
|
||||
}
|
||||
|
||||
/* Enter a comment here, from a window */
|
||||
move(LINES, 0);
|
||||
printf("Enter comment: ");
|
||||
gets(cbuf); /* Get a string to buf */
|
||||
move(LINES, 0);
|
||||
printf("%50c", ' ');
|
||||
|
||||
pStr = addStrTbl(cbuf); /* Add to the string table */
|
||||
|
||||
selectTable(Comment);
|
||||
enterSym(pStr, pcCur, pProc, FALSE);/* Add the symbol */
|
||||
|
||||
updateScr(FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'X' & 0x1F: /* Control X; can't use Alt with Unix */
|
||||
fInteract = FALSE; /* Exit interactive mode */
|
||||
attrSet(A_NORMAL); /* Normal attributes */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(posStack);
|
||||
destroySymTables();
|
||||
#endif // #ifdef unix
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Display the current image position as data *
|
||||
****************************************************************************/
|
||||
static void
|
||||
dispData(word dataSeg)
|
||||
{
|
||||
int y, c, i;
|
||||
Int pc, pcStart;
|
||||
Int off = (Int)dataSeg << 4;
|
||||
char szOffset[6], szByte[4];
|
||||
|
||||
if (pcCur >= (dword)prog.cbImage)
|
||||
{
|
||||
/* We're at an invalid address. Use 0x100 instead */
|
||||
pcCur = 0;
|
||||
}
|
||||
erase();
|
||||
dispTitle();
|
||||
|
||||
pcStart = pc = pcCur; /* pc at start of line */
|
||||
for (y=1; y < LINES-1; y++)
|
||||
{
|
||||
move (y, 1);
|
||||
sprintf(szOffset, "%04lX ", pc);
|
||||
printfd(szOffset);
|
||||
for (i=0; i < 16; i++)
|
||||
{
|
||||
sprintf(szByte, "%02X ", prog.Image[pc++ + off]);
|
||||
printfd(szByte);
|
||||
if ((pc + off) > prog.cbImage) break;
|
||||
}
|
||||
pc = pcStart;
|
||||
for (i=0; i < 16; i++)
|
||||
{
|
||||
c = prog.Image[pc++ + off];
|
||||
if ((c < 0x20) || (c > 0x7E))
|
||||
{
|
||||
c = '.';
|
||||
}
|
||||
szByte[0] = (char)c;
|
||||
szByte[1] = '\0';
|
||||
printfd(szByte);
|
||||
if ((pc + off) > prog.cbImage) break;
|
||||
}
|
||||
dis_newline();
|
||||
pcStart = pc;
|
||||
|
||||
if ((pc + off) > prog.cbImage) break;
|
||||
|
||||
/* getyx(stdscr, y, x); */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
boolT callArg(word off, char *sym)
|
||||
{
|
||||
dword imageOff;
|
||||
|
||||
imageOff = off + ((dword)pProc->state.r[rCS] << 4);
|
||||
/* Search procedure list for one with appropriate entry point */
|
||||
FunctionListType::iterator iter= std::find_if(pProcList.begin(),pProcList.end(),
|
||||
[imageOff](const Function &f) -> bool { return f.procEntry==imageOff; });
|
||||
if(iter==pProcList.end())
|
||||
{
|
||||
/* No existing proc entry */
|
||||
//ERROR: dereferencing NULL !?!
|
||||
//LibCheck(*iter);
|
||||
Function *x=Function::Create();
|
||||
x->procEntry=imageOff;
|
||||
LibCheck(*x);
|
||||
if (x->flg & PROC_ISLIB)
|
||||
{
|
||||
/* No entry for this proc, but it is a library function.
|
||||
Create an entry for it */
|
||||
pProcList.push_back(x);
|
||||
iter = (++pProcList.rbegin()).base();
|
||||
}
|
||||
}
|
||||
if(iter==pProcList.end())
|
||||
return false;
|
||||
/* We have a proc entry for this procedure. Copy the name */
|
||||
strcpy(sym, iter->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Handle the floating point opcodes (icode iESC) */
|
||||
|
||||
@ -97,8 +97,7 @@ chop(byte pat[])
|
||||
memset(&pat[pc], 0, PATLEN - pc);
|
||||
}
|
||||
|
||||
static bool
|
||||
op0F(byte pat[])
|
||||
static bool op0F(byte pat[])
|
||||
{
|
||||
/* The two byte opcodes */
|
||||
byte op = pat[pc++];
|
||||
|
||||
@ -218,7 +218,7 @@ void Function::compressCFG()
|
||||
if (pBB->numOutEdges) /* Might have been clobbered */
|
||||
{
|
||||
pBB->edges[i].BBptr = pNxt;
|
||||
Icode.SetImmediateOp(ip, (dword)pNxt->start);
|
||||
Icode.SetImmediateOp(ip, (dword)pNxt->begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -270,7 +270,7 @@ static BB * rmJMP(Function * pProc, Int marker, BB * pBB)
|
||||
{
|
||||
marker += DFS_JMP;
|
||||
|
||||
while (pBB->nodeType == ONE_BRANCH && pBB->length == 1)
|
||||
while (pBB->nodeType == ONE_BRANCH && pBB->size() == 1)
|
||||
{
|
||||
if (pBB->traversed != marker)
|
||||
{
|
||||
@ -282,13 +282,15 @@ static BB * rmJMP(Function * pProc, Int marker, BB * pBB)
|
||||
}
|
||||
else
|
||||
{
|
||||
pProc->Icode.SetLlFlag(pBB->start, NO_CODE);
|
||||
pProc->Icode.SetLlInvalid(pBB->start, TRUE);
|
||||
pBB->front().SetLlFlag(NO_CODE);
|
||||
pBB->front().invalidate(); //pProc->Icode.SetLlInvalid(pBB->begin(), TRUE);
|
||||
}
|
||||
|
||||
pBB = pBB->edges[0].BBptr;
|
||||
}
|
||||
else { /* We are going around in circles */
|
||||
else
|
||||
{
|
||||
/* We are going around in circles */
|
||||
pBB->nodeType = NOWHERE_NODE;
|
||||
pProc->Icode.GetIcode(pBB->start)->ic.ll.immed.op = (dword)pBB->start;
|
||||
pProc->Icode.SetImmediateOp(pBB->start, (dword)pBB->start);
|
||||
|
||||
@ -227,7 +227,8 @@ static Int idiom2(ICODE * pIcode, ICODE * pEnd, Int ip, Function * pProc)
|
||||
static Int idiom3(ICODE * pIcode, ICODE * pEnd)
|
||||
{
|
||||
/* Match ADD SP, immed */
|
||||
if ((++pIcode < pEnd) && (pIcode->ic.ll.flg & I) &&
|
||||
++pIcode;
|
||||
if ((pIcode < pEnd) && (pIcode->ic.ll.flg & I) &&
|
||||
(pIcode->ic.ll.opcode == iADD) && (pIcode->ic.ll.dst.regi == rSP))
|
||||
return (pIcode->ic.ll.immed.op);
|
||||
else if ((pIcode->ic.ll.opcode == iMOV) && (pIcode->ic.ll.dst.regi == rSP)
|
||||
@ -254,15 +255,20 @@ static Int idiom17 (ICODE * pIcode, ICODE * pEnd)
|
||||
byte regi;
|
||||
|
||||
/* Match POP reg */
|
||||
if ((++pIcode < pEnd) && (pIcode->ic.ll.opcode == iPOP))
|
||||
++pIcode;
|
||||
if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPOP))
|
||||
{
|
||||
regi = pIcode->ic.ll.dst.regi;
|
||||
if ((regi >= rAX) && (regi <= rBX))
|
||||
i++;
|
||||
while ((++pIcode)->ic.ll.opcode == iPOP)
|
||||
++pIcode;
|
||||
while (pIcode->ic.ll.opcode == iPOP)
|
||||
{
|
||||
if (pIcode->ic.ll.dst.regi == regi)
|
||||
{
|
||||
i++;
|
||||
++pIcode;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
@ -1082,10 +1088,15 @@ void Function::findIdioms()
|
||||
(pIcode++)->invalidate();
|
||||
ip++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Indirect call at idiom3\n");
|
||||
pIcode++;
|
||||
}
|
||||
}
|
||||
else if (idx = idiom17 (pIcode, pEnd)) /* idiom 17 */
|
||||
{
|
||||
if (pIcode->ic.ll.flg & I)
|
||||
if (pIcode->isLlFlag(I))
|
||||
{
|
||||
(pIcode->ic.ll.immed.proc.proc)->cbParam = (int16)idx;
|
||||
pIcode->ic.ll.immed.proc.cb = idx;
|
||||
@ -1095,6 +1106,12 @@ void Function::findIdioms()
|
||||
for (idx /= 2; idx > 0; idx--)
|
||||
(pIcode++)->invalidate();
|
||||
}
|
||||
// TODO : it's a calculated call
|
||||
else
|
||||
{
|
||||
printf("Indirect call at idiom17\n");
|
||||
pIcode++;
|
||||
}
|
||||
}
|
||||
else
|
||||
pIcode++;
|
||||
|
||||
@ -85,9 +85,9 @@ void parse (CALL_GRAPH * *pcallGraph)
|
||||
}
|
||||
|
||||
|
||||
static void updateSymType (dword symbol, hlType symType, Int size)
|
||||
/* Updates the type of the symbol in the symbol table. The size is updated
|
||||
* if necessary (0 means no update necessary). */
|
||||
static void updateSymType (dword symbol, hlType symType, Int size)
|
||||
{ Int i;
|
||||
|
||||
for (i = 0; i < symtab.csym; i++)
|
||||
|
||||
335
src/perfhlib.cpp
335
src/perfhlib.cpp
@ -11,19 +11,7 @@
|
||||
|
||||
/* Private data structures */
|
||||
|
||||
static int NumEntry; /* Number of entries in the hash table (# keys) */
|
||||
static int EntryLen; /* Size (bytes) of each entry (size of keys) */
|
||||
static int SetSize; /* Size of the char set */
|
||||
static char SetMin; /* First char in the set */
|
||||
static int NumVert; /* c times NumEntry */
|
||||
|
||||
static word *T1base, *T2base; /* Pointers to start of T1, T2 */
|
||||
static word *T1, *T2; /* Pointers to T1[i], T2[i] */
|
||||
|
||||
static int *graphNode; /* The array of edges */
|
||||
static int *graphNext; /* Linked list of edges */
|
||||
static int *graphFirst;/* First edge at a vertex */
|
||||
|
||||
static short *g; /* g[] */
|
||||
|
||||
static int numEdges; /* An edge counter */
|
||||
@ -34,9 +22,10 @@ static void initGraph(void);
|
||||
static void addToGraph(int e, int v1, int v2);
|
||||
static bool isCycle(void);
|
||||
static void duplicateKeys(int v1, int v2);
|
||||
PatternHasher g_pattern_hasher;
|
||||
|
||||
void
|
||||
hashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||
PatternHasher::init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||
int _NumVert)
|
||||
{
|
||||
/* These parameters are stored in statics so as to obviate the need for
|
||||
@ -84,12 +73,11 @@ hashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||
|
||||
BadAlloc:
|
||||
printf("Could not allocate memory\n");
|
||||
hashCleanup();
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
hashCleanup(void)
|
||||
void PatternHasher::cleanup(void)
|
||||
{
|
||||
/* Free the storage for variable sized tables etc */
|
||||
if (T1base) free(T1base);
|
||||
@ -100,264 +88,7 @@ hashCleanup(void)
|
||||
if (g) free(g);
|
||||
}
|
||||
|
||||
void
|
||||
map(void)
|
||||
{
|
||||
int i, j, c;
|
||||
word f1, f2;
|
||||
bool cycle;
|
||||
byte *keys;
|
||||
|
||||
c = 0;
|
||||
|
||||
do
|
||||
{
|
||||
initGraph();
|
||||
cycle = FALSE;
|
||||
|
||||
/* Randomly generate T1 and T2 */
|
||||
for (i=0; i < SetSize*EntryLen; i++)
|
||||
{
|
||||
T1base[i] = rand() % NumVert;
|
||||
T2base[i] = rand() % NumVert;
|
||||
}
|
||||
|
||||
for (i=0; i < NumEntry; i++)
|
||||
{
|
||||
f1 = 0; f2 = 0;
|
||||
getKey(i, &keys);
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
T2 = T2base + j * SetSize;
|
||||
f1 += T1[keys[j] - SetMin];
|
||||
f2 += T2[keys[j] - SetMin];
|
||||
}
|
||||
f1 %= (word)NumVert;
|
||||
f2 %= (word)NumVert;
|
||||
if (f1 == f2)
|
||||
{
|
||||
/* A self loop. Reject! */
|
||||
printf("Self loop on vertex %d!\n", f1);
|
||||
cycle = TRUE;
|
||||
break;
|
||||
}
|
||||
addToGraph(numEdges++, f1, f2);
|
||||
}
|
||||
if (cycle || (cycle = isCycle())) /* OK - is there a cycle? */
|
||||
{
|
||||
printf("Iteration %d\n", ++c);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (/* there is a cycle */ 1);
|
||||
|
||||
}
|
||||
|
||||
/* Initialise the graph */
|
||||
static void
|
||||
initGraph(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1; i <= NumVert; i++)
|
||||
{
|
||||
graphFirst[i] = 0;
|
||||
}
|
||||
|
||||
for (i= -NumEntry; i <= NumEntry; i++)
|
||||
{
|
||||
/* No need to init graphNode[] as they will all be filled by successive
|
||||
calls to addToGraph() */
|
||||
graphNext[NumEntry+i] = 0;
|
||||
}
|
||||
|
||||
numEdges = 0;
|
||||
}
|
||||
|
||||
/* Add an edge e between vertices v1 and v2 */
|
||||
/* e, v1, v2 are 0 based */
|
||||
static void
|
||||
addToGraph(int e, int v1, int v2)
|
||||
{
|
||||
e++; v1++; v2++; /* So much more convenient */
|
||||
|
||||
graphNode[NumEntry+e] = v2; /* Insert the edge information */
|
||||
graphNode[NumEntry-e] = v1;
|
||||
|
||||
graphNext[NumEntry+e] = graphFirst[v1]; /* Insert v1 to list of alphas */
|
||||
graphFirst[v1]= e;
|
||||
graphNext[NumEntry-e] = graphFirst[v2]; /* Insert v2 to list of omegas */
|
||||
graphFirst[v2]= -e;
|
||||
|
||||
}
|
||||
|
||||
bool DFS(int parentE, int v)
|
||||
{
|
||||
int e, w;
|
||||
|
||||
/* Depth first search of the graph, starting at vertex v, looking for
|
||||
cycles. parent and v are origin 1. Note parent is an EDGE,
|
||||
not a vertex */
|
||||
|
||||
visited[v] = TRUE;
|
||||
|
||||
/* For each e incident with v .. */
|
||||
for (e = graphFirst[v]; e; e = graphNext[NumEntry+e])
|
||||
{
|
||||
byte *key1;
|
||||
|
||||
getKey(abs(e)-1, &key1);
|
||||
if (*(long *)key1 == 0)
|
||||
{
|
||||
/* A deleted key. Just ignore it */
|
||||
continue;
|
||||
}
|
||||
w = graphNode[NumEntry+e];
|
||||
if (visited[w])
|
||||
{
|
||||
/* Did we just come through this edge? If so, ignore it. */
|
||||
if (abs(e) != abs(parentE))
|
||||
{
|
||||
/* There is a cycle in the graph. There is some subtle code here
|
||||
to work around the distinct possibility that there may be
|
||||
duplicate keys. Duplicate keys will always cause unit
|
||||
cycles, since f1 and f2 (used to select v and w) will be the
|
||||
same for both. The edges (representing an index into the
|
||||
array of keys) are distinct, but the key values are not.
|
||||
The logic is as follows: for the candidate edge e, check to
|
||||
see if it terminates in the parent vertex. If so, we test
|
||||
the keys associated with e and the parent, and if they are
|
||||
the same, we can safely ignore e for the purposes of cycle
|
||||
detection, since edge e adds nothing to the cycle. Cycles
|
||||
involving v, w, and e0 will still be found. The parent
|
||||
edge was not similarly eliminated because at the time when
|
||||
it was a candidate, v was not yet visited.
|
||||
We still have to remove the key from further consideration,
|
||||
since each edge is visited twice, but with a different
|
||||
parent edge each time.
|
||||
*/
|
||||
/* We save some stack space by calculating the parent vertex
|
||||
for these relatively few cases where it is needed */
|
||||
int parentV = graphNode[NumEntry-parentE];
|
||||
|
||||
if (w == parentV)
|
||||
{
|
||||
byte *key2;
|
||||
|
||||
getKey(abs(parentE)-1, &key2);
|
||||
if (memcmp(key1, key2, EntryLen) == 0)
|
||||
{
|
||||
printf("Duplicate keys with edges %d and %d (",
|
||||
e, parentE);
|
||||
dispKey(abs(e)-1);
|
||||
printf(" & ");
|
||||
dispKey(abs(parentE)-1);
|
||||
printf(")\n");
|
||||
/* *(long *)key1 = 0; /* Wipe the key */
|
||||
memset(key1, 0, EntryLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A genuine (unit) cycle. */
|
||||
printf("There is a unit cycle involving vertex %d and edge %d\n", v, e);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have reached a previously visited vertex not the
|
||||
parent. Therefore, we have uncovered a genuine cycle */
|
||||
printf("There is a cycle involving vertex %d and edge %d\n", v, e);
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Not yet seen. Traverse it */
|
||||
{
|
||||
if (DFS(e, w))
|
||||
{
|
||||
/* Cycle found deeper down. Exit */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool
|
||||
isCycle(void)
|
||||
{
|
||||
int v;
|
||||
|
||||
for (v=1; v <= NumVert; v++)
|
||||
{
|
||||
visited[v] = FALSE;
|
||||
}
|
||||
for (v=1; v <= NumVert; v++)
|
||||
{
|
||||
if (!visited[v])
|
||||
{
|
||||
if (DFS(-32767, v))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
traverse(int u)
|
||||
{
|
||||
int w, e;
|
||||
|
||||
visited[u] = TRUE;
|
||||
/* Find w, the neighbours of u, by searching the edges e associated with u */
|
||||
e = graphFirst[1+u];
|
||||
while (e)
|
||||
{
|
||||
w = graphNode[NumEntry+e]-1;
|
||||
if (!visited[w])
|
||||
{
|
||||
g[w] = (abs(e)-1 - g[u]) % NumEntry;
|
||||
if (g[w] < 0) g[w] += NumEntry; /* Keep these positive */
|
||||
traverse(w);
|
||||
}
|
||||
e = graphNext[NumEntry+e];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
assign(void)
|
||||
{
|
||||
int v;
|
||||
|
||||
|
||||
for (v=0; v < NumVert; v++)
|
||||
{
|
||||
g[v] = 0; /* g is sparse; leave the gaps 0 */
|
||||
visited[v] = FALSE;
|
||||
}
|
||||
|
||||
for (v=0; v < NumVert; v++)
|
||||
{
|
||||
if (!visited[v])
|
||||
{
|
||||
g[v] = 0;
|
||||
traverse(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hash(byte *string)
|
||||
int PatternHasher::hash(byte *string)
|
||||
{
|
||||
word u, v;
|
||||
int j;
|
||||
@ -381,68 +112,18 @@ hash(byte *string)
|
||||
return (g[u] + g[v]) % NumEntry;
|
||||
}
|
||||
|
||||
word *
|
||||
readT1(void)
|
||||
word * PatternHasher::readT1(void)
|
||||
{
|
||||
return T1base;
|
||||
}
|
||||
|
||||
word *
|
||||
readT2(void)
|
||||
word *PatternHasher::readT2(void)
|
||||
{
|
||||
return T2base;
|
||||
}
|
||||
|
||||
word *
|
||||
readG(void)
|
||||
word * PatternHasher::readG(void)
|
||||
{
|
||||
return (word *)g;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void dispRecord(int i);
|
||||
|
||||
void
|
||||
duplicateKeys(int v1, int v2)
|
||||
{
|
||||
int i, j;
|
||||
byte *keys;
|
||||
int u, v;
|
||||
|
||||
v1--; v2--; /* These guys are origin 1 */
|
||||
|
||||
printf("Duplicate keys:\n");
|
||||
|
||||
for (i=0; i < NumEntry; i++)
|
||||
{
|
||||
getKey(i, &keys);
|
||||
u = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
u += T1[keys[j] - SetMin];
|
||||
}
|
||||
u %= NumVert;
|
||||
if ((u != v1) && (u != v2)) continue;
|
||||
|
||||
v = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T2 = T2base + j * SetSize;
|
||||
v += T2[keys[j] - SetMin];
|
||||
}
|
||||
v %= NumVert;
|
||||
|
||||
if ((v == v2) || (v == v1))
|
||||
{
|
||||
printf("Entry #%d key: ", i+1);
|
||||
for (j=0; j < EntryLen; j++) printf("%02X ", keys[j]);
|
||||
printf("\n");
|
||||
dispRecord(i+1);
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -21,9 +21,10 @@ static boolT isJCond (llIcode opcode)
|
||||
}
|
||||
|
||||
|
||||
static boolT isLong23 (Int i, BB * pbb, ICODE * icode, Int *off, Int *arc)
|
||||
/* Returns whether the conditions for a 2-3 long variable are satisfied */
|
||||
{ BB * t, * e, * obb2;
|
||||
static boolT isLong23 (Int i, BB * pbb, ICODE * icode, Int *off, Int *arc)
|
||||
{
|
||||
BB * t, * e, * obb2;
|
||||
|
||||
if (pbb->nodeType != TWO_BRANCH)
|
||||
return false;
|
||||
@ -224,17 +225,17 @@ static void longJCond22 (COND_EXPR *rhs, COND_EXPR *lhs, ICODE * pIcode,
|
||||
* Arguments: i : index into the local identifier table
|
||||
* pLocId: ptr to the long local identifier
|
||||
* pProc : ptr to current procedure's record. */
|
||||
static void propLongStk (Int i, ID *pLocId, Function * pProc)
|
||||
void Function::propLongStk (Int i, ID *pLocId)
|
||||
{
|
||||
Int idx, off, arc;
|
||||
COND_EXPR *lhs, *rhs; /* Pointers to left and right hand expression */
|
||||
ICODE * pIcode, * pEnd;
|
||||
|
||||
/* Check all icodes for offHi:offLo */
|
||||
pEnd = pProc->Icode.GetIcode(pProc->Icode.GetNumIcodes() -1);
|
||||
for (idx = 0; idx < (pProc->Icode.GetNumIcodes() - 1); idx++)
|
||||
pEnd = this->Icode.GetIcode(this->Icode.GetNumIcodes() -1);
|
||||
for (idx = 0; idx < (this->Icode.GetNumIcodes() - 1); idx++)
|
||||
{
|
||||
pIcode = pProc->Icode.GetIcode(idx);
|
||||
pIcode = this->Icode.GetIcode(idx);
|
||||
if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE))
|
||||
continue;
|
||||
|
||||
@ -242,7 +243,7 @@ static void propLongStk (Int i, ID *pLocId, Function * pProc)
|
||||
{
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iMOV:
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, this,
|
||||
&rhs, &lhs, 1) == TRUE)
|
||||
{
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
@ -252,7 +253,7 @@ static void propLongStk (Int i, ID *pLocId, Function * pProc)
|
||||
break;
|
||||
|
||||
case iAND: case iOR: case iXOR:
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, this,
|
||||
&rhs, &lhs, 1) == TRUE)
|
||||
{
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
@ -270,7 +271,7 @@ static void propLongStk (Int i, ID *pLocId, Function * pProc)
|
||||
break;
|
||||
|
||||
case iPUSH:
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, this,
|
||||
&rhs, &lhs, 1) == TRUE)
|
||||
{
|
||||
pIcode->setUnary( HLI_PUSH, lhs);
|
||||
@ -282,10 +283,10 @@ static void propLongStk (Int i, ID *pLocId, Function * pProc)
|
||||
}
|
||||
|
||||
/* Check long conditional (i.e. 2 CMPs and 3 branches */
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) && (isLong23 (idx, pIcode->inBB, pProc->Icode.GetFirstIcode(),&off, &arc)))
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) && (isLong23 (idx, pIcode->inBB, this->Icode.GetFirstIcode(),&off, &arc)))
|
||||
{
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc, &rhs, &lhs, off) == TRUE)
|
||||
longJCond23 (rhs, lhs, pIcode, &idx, pProc, arc, off);
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, this, &rhs, &lhs, off) == TRUE)
|
||||
longJCond23 (rhs, lhs, pIcode, &idx, this, arc, off);
|
||||
}
|
||||
|
||||
/* Check for long conditional equality or inequality. This requires
|
||||
@ -293,7 +294,7 @@ static void propLongStk (Int i, ID *pLocId, Function * pProc)
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) &&
|
||||
isLong22 (pIcode, pEnd, &off))
|
||||
{
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, this,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond22 (rhs, lhs, pIcode, &idx);
|
||||
}
|
||||
@ -306,7 +307,7 @@ static void propLongStk (Int i, ID *pLocId, Function * pProc)
|
||||
* Arguments: i : index into the local identifier table
|
||||
* pLocId: ptr to the long local identifier
|
||||
* pProc : ptr to current procedure's record. */
|
||||
static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
void Function::propLongReg (Int i, ID *pLocId)
|
||||
{
|
||||
COND_EXPR *lhs, *rhs;
|
||||
Int idx, j, off, arc;
|
||||
@ -314,13 +315,13 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
ICODEMEM * pmH,* pmL; /* Pointers to dst LOW_LEVEL icodes */
|
||||
|
||||
/* Process all definitions/uses of long registers at an icode position */
|
||||
pEnd = pProc->Icode.GetIcode(pProc->Icode.GetNumIcodes() -1);
|
||||
pEnd = this->Icode.GetIcode(this->Icode.GetNumIcodes() -1);
|
||||
for (j = 0; j < pLocId->idx.size(); j++)
|
||||
{
|
||||
/* Check backwards for a definition of this long register */
|
||||
for (idx = pLocId->idx[j] - 1; idx > 0 ; idx--)
|
||||
{
|
||||
pIcode = pProc->Icode.GetIcode(idx-1);
|
||||
pIcode = this->Icode.GetIcode(idx-1);
|
||||
if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE))
|
||||
continue;
|
||||
|
||||
@ -333,9 +334,9 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
if ((pLocId->id.longId.h == pmH->regi) && (pLocId->id.longId.l == pmL->regi))
|
||||
{
|
||||
lhs = COND_EXPR::idLongIdx (i);
|
||||
pProc->localId.id_arr[i].idx.push_back(idx-1);
|
||||
this->localId.id_arr[i].idx.push_back(idx-1);
|
||||
pIcode->setRegDU( pmL->regi, eDEF);
|
||||
rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, idx, eUSE, 1);
|
||||
rhs = COND_EXPR::idLong (&this->localId, SRC, pIcode, HIGH_FIRST, idx, eUSE, 1);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx = 0; /* to exit the loop */
|
||||
@ -364,7 +365,7 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
{
|
||||
lhs = COND_EXPR::idLongIdx (i);
|
||||
pIcode->setRegDU( pmH->regi, USE_DEF);
|
||||
rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, LOW_FIRST, idx, eUSE, 1);
|
||||
rhs = COND_EXPR::idLong (&this->localId, SRC, pIcode, LOW_FIRST, idx, eUSE, 1);
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iAND: rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
||||
break;
|
||||
@ -384,9 +385,9 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
|
||||
/* If no definition backwards, check forward for a use of this long reg */
|
||||
if (idx <= 0)
|
||||
for (idx = pLocId->idx[j] + 1; idx < pProc->Icode.GetNumIcodes() - 1; idx++)
|
||||
for (idx = pLocId->idx[j] + 1; idx < this->Icode.GetNumIcodes() - 1; idx++)
|
||||
{
|
||||
pIcode = pProc->Icode.GetIcode(idx);
|
||||
pIcode = this->Icode.GetIcode(idx);
|
||||
if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE))
|
||||
continue;
|
||||
|
||||
@ -398,11 +399,11 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
{
|
||||
rhs = COND_EXPR::idLongIdx (i);
|
||||
pIcode->setRegDU( (pIcode+1)->ic.ll.src.regi, eUSE);
|
||||
lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode,
|
||||
lhs = COND_EXPR::idLong (&this->localId, DST, pIcode,
|
||||
HIGH_FIRST, idx, eDEF, 1);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx = pProc->Icode.GetNumIcodes(); /* to exit the loop */
|
||||
idx = this->Icode.GetNumIcodes(); /* to exit the loop */
|
||||
}
|
||||
break;
|
||||
|
||||
@ -415,7 +416,7 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
pIcode->setUnary(HLI_PUSH, lhs);
|
||||
(pIcode+1)->invalidate();
|
||||
}
|
||||
idx = pProc->Icode.GetNumIcodes(); /* to exit the loop */
|
||||
idx = this->Icode.GetNumIcodes(); /* to exit the loop */
|
||||
break;
|
||||
|
||||
/*** others missing ****/
|
||||
@ -428,7 +429,7 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
{
|
||||
lhs = COND_EXPR::idLongIdx (i);
|
||||
pIcode->setRegDU( pmH->regi, USE_DEF);
|
||||
rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode,
|
||||
rhs = COND_EXPR::idLong (&this->localId, SRC, pIcode,
|
||||
LOW_FIRST, idx, eUSE, 1);
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iAND: rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
||||
@ -447,12 +448,12 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
|
||||
/* Check long conditional (i.e. 2 CMPs and 3 branches */
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) &&
|
||||
(isLong23 (idx, pIcode->inBB, pProc->Icode.GetFirstIcode(),
|
||||
(isLong23 (idx, pIcode->inBB, this->Icode.GetFirstIcode(),
|
||||
&off, &arc)))
|
||||
{
|
||||
if (checkLongRegEq (pLocId->id.longId, pIcode, i, idx, pProc,
|
||||
if (checkLongRegEq (pLocId->id.longId, pIcode, i, idx, this,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond23 (rhs, lhs, pIcode, &idx, pProc, arc, off);
|
||||
longJCond23 (rhs, lhs, pIcode, &idx, this, arc, off);
|
||||
}
|
||||
|
||||
/* Check for long conditional equality or inequality. This requires
|
||||
@ -460,7 +461,7 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) &&
|
||||
(isLong22 (pIcode, pEnd, &off)))
|
||||
{
|
||||
if (checkLongRegEq (pLocId->id.longId, pIcode, i, idx, pProc,
|
||||
if (checkLongRegEq (pLocId->id.longId, pIcode, i, idx, this,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond22 (rhs, lhs, pIcode, &idx);
|
||||
}
|
||||
@ -493,9 +494,9 @@ static void propLongReg (Int i, ID *pLocId, Function * pProc)
|
||||
|
||||
/* Propagates the long global address across all LOW_LEVEL icodes.
|
||||
* Transforms some LOW_LEVEL icodes into HIGH_LEVEL */
|
||||
static void propLongGlb (Int i, ID *pLocId, Function * pProc)
|
||||
void Function::propLongGlb (Int i, ID *pLocId)
|
||||
{
|
||||
|
||||
printf("WARN: Function::propLongGlb not implemented");
|
||||
}
|
||||
|
||||
|
||||
@ -514,13 +515,13 @@ void Function::propLong()
|
||||
switch (pLocId->loc)
|
||||
{
|
||||
case STK_FRAME:
|
||||
propLongStk (i, pLocId, this);
|
||||
propLongStk (i, pLocId);
|
||||
break;
|
||||
case REG_FRAME:
|
||||
propLongReg (i, pLocId, this);
|
||||
propLongReg (i, pLocId);
|
||||
break;
|
||||
case GLB_FRAME:
|
||||
propLongGlb (i, pLocId, this);
|
||||
propLongGlb (i, pLocId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -603,11 +603,9 @@ static void trans(Int i)
|
||||
pIcode->ic.ll.flagDU.d = df[REG(*pInst)];
|
||||
rm(i);
|
||||
memcpy(&pIcode->ic.ll.src, &pIcode->ic.ll.dst, sizeof(ICODEMEM));
|
||||
if (pIcode->ic.ll.opcode == iJMP || pIcode->ic.ll.opcode == iCALL ||
|
||||
pIcode->ic.ll.opcode == iCALLF)
|
||||
if (pIcode->ic.ll.opcode == iJMP || pIcode->ic.ll.opcode == iCALL || pIcode->ic.ll.opcode == iCALLF)
|
||||
pIcode->ic.ll.flg |= NO_OPS;
|
||||
else if (pIcode->ic.ll.opcode == iINC || pIcode->ic.ll.opcode == iPUSH
|
||||
|| pIcode->ic.ll.opcode == iDEC)
|
||||
else if (pIcode->ic.ll.opcode == iINC || pIcode->ic.ll.opcode == iPUSH || pIcode->ic.ll.opcode == iDEC)
|
||||
pIcode->ic.ll.flg |= NO_SRC;
|
||||
}
|
||||
}
|
||||
|
||||
481
src/symtab.cpp
481
src/symtab.cpp
@ -52,18 +52,9 @@ static tableType curTableType; /* Which table is current */
|
||||
struct TABLEINFO_TYPE
|
||||
{
|
||||
void deleteVal(dword symOff, Function *symProc, boolT bSymToo);
|
||||
void enterSym(const char *symName, dword symOff, Function *symProc, boolT bSymToo);
|
||||
std::string findVal(dword symOff, Function *symProc, word &pIndex);
|
||||
void create(tableType type);
|
||||
void destroy();
|
||||
private:
|
||||
void deleteSym(char *symName);
|
||||
boolT findSym(const char *symName, word &pIndex);
|
||||
boolT readSym(char *symName, dword *pSymOff, Function **pSymProc);
|
||||
void expandSym(void);
|
||||
word findBlankSym(const std::string &symName);
|
||||
word symHash(const char *name, word *pre);
|
||||
word valHash(dword symOff, Function *symProc, word *pre);
|
||||
|
||||
SYMTABLE *symTab; /* Pointer to the symbol hashed table */
|
||||
SYMTABLE *valTab; /* Pointer to the value hashed table */
|
||||
@ -149,478 +140,8 @@ void destroySymTables(void)
|
||||
currentTabInfo.destroy();
|
||||
}
|
||||
|
||||
|
||||
/* Hash the symbolic name */
|
||||
word TABLEINFO_TYPE::symHash(const char *name, word *pre)
|
||||
{
|
||||
int i;
|
||||
word h = 0;
|
||||
char ch;
|
||||
|
||||
for (i=0; i < (int)strlen(name); i++)
|
||||
{
|
||||
ch = name[i];
|
||||
h = (h << 2) ^ ch;
|
||||
h += (ch >> 2) + (ch << 5);
|
||||
}
|
||||
|
||||
*pre = h; /* Pre modulo hash value */
|
||||
return h % tableSize; /* Post modulo hash value */
|
||||
}
|
||||
|
||||
/* Hash the symOff and symProc fields */
|
||||
/* Note: for the time being, there no use is made of the symProc field */
|
||||
word TABLEINFO_TYPE::valHash(dword symOff, Function * symProc, word *pre)
|
||||
{
|
||||
word h = 0;
|
||||
|
||||
h = (word)(symOff ^ (symOff >> 8));
|
||||
|
||||
*pre = h; /* Pre modulo hash value */
|
||||
return h % tableSize; /* Post modulo hash value */
|
||||
}
|
||||
void TABLEINFO_TYPE::enterSym(const char *symName, dword symOff, Function * symProc, boolT bSymToo)
|
||||
{
|
||||
word h, pre, j;
|
||||
SYMTABLE entry;
|
||||
entry.pSymName= symName; /* Symbol name ptr */
|
||||
entry.symOff = symOff; /* Offset of the symbol */
|
||||
entry.symProc = symProc; /* Symbol's proc num */
|
||||
entry.preHash = pre; /* Pre modulo hash value */
|
||||
entry.postHash= h; /* Post modulo hash value */
|
||||
entry.nextOvf = NIL; /* No overflow */
|
||||
entry.prevOvf = NIL; /* No back link */
|
||||
z[symName] = entry;
|
||||
z2[entry] = symName;
|
||||
if ((numEntry / 9 * 10) >= tableSize)
|
||||
{
|
||||
/* Table is full. Expand it */
|
||||
expandSym();
|
||||
}
|
||||
|
||||
/* Enter it into the value hashed table first */
|
||||
h = valHash(symOff, symProc, &pre); /* Ideal spot for this entry */
|
||||
if (valTab[h].symProc == 0) /* Collision? */
|
||||
{
|
||||
/* No. Just insert here */
|
||||
valTab[h].pSymName= symName; /* Symbol name ptr */
|
||||
valTab[h].symOff = symOff; /* Offset of the symbol */
|
||||
valTab[h].symProc = symProc; /* Symbol's proc num */
|
||||
valTab[h].preHash = pre; /* Pre modulo hash value */
|
||||
valTab[h].postHash= h; /* Post modulo hash value */
|
||||
valTab[h].nextOvf = NIL; /* No overflow */
|
||||
valTab[h].prevOvf = NIL; /* No back link */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Linear probing, for now */
|
||||
j = (h+1) % tableSize;
|
||||
while (j != h)
|
||||
{
|
||||
if (valTab[j].symProc == 0)
|
||||
{
|
||||
/* Insert here */
|
||||
valTab[j].pSymName= symName; /* Symbol name ptr */
|
||||
valTab[j].symOff = symOff; /* Offset of the symbol */
|
||||
valTab[j].symProc = symProc; /* Symbol's proc num */
|
||||
valTab[j].preHash = pre; /* Pre modulo hash value */
|
||||
valTab[j].postHash= h; /* Post modulo hash value */
|
||||
/* Insert after the primary entry in the table */
|
||||
valTab[j].nextOvf = valTab[h].nextOvf;
|
||||
valTab[h].nextOvf = j;
|
||||
valTab[j].prevOvf = h; /* The backlink */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Probe further */
|
||||
j = (j+1) % tableSize;
|
||||
}
|
||||
}
|
||||
if (j == h)
|
||||
{
|
||||
printf("enterSym: val table overflow!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now enter into the symbol hashed table as well, if reqd */
|
||||
if (!bSymToo) return;
|
||||
h = symHash(symName, &pre); /* Ideal spot for this entry */
|
||||
if (symTab[h].pSymName.empty()) /* Collision? */
|
||||
{
|
||||
/* No. Just insert here */
|
||||
symTab[h].pSymName= symName; /* Symbol name ptr */
|
||||
symTab[h].symOff = symOff; /* Offset of the symbol */
|
||||
symTab[h].symProc = symProc; /* Symbol's proc num */
|
||||
symTab[h].preHash = pre; /* Pre modulo hash value */
|
||||
symTab[h].postHash= h; /* Post modulo hash value */
|
||||
symTab[h].nextOvf = NIL; /* No overflow */
|
||||
symTab[h].prevOvf = NIL; /* No back link */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Linear probing, for now */
|
||||
j = (h+1) % tableSize;
|
||||
while (j != h)
|
||||
{
|
||||
if (symTab[j].pSymName.empty())
|
||||
{
|
||||
/* Insert here */
|
||||
symTab[j].pSymName= symName; /* Symbol name ptr */
|
||||
symTab[j].symOff = symOff; /* Offset of the symbol */
|
||||
symTab[j].symProc = symProc; /* Symbol's proc num */
|
||||
symTab[j].preHash = pre; /* Pre modulo hash value */
|
||||
symTab[j].postHash= h; /* Post modulo hash value */
|
||||
/* Insert after the primary entry in the table */
|
||||
symTab[j].nextOvf = symTab[h].nextOvf;
|
||||
symTab[h].nextOvf = j;
|
||||
symTab[j].prevOvf = h; /* The backlink */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Probe further */
|
||||
j = (j+1) % tableSize;
|
||||
}
|
||||
}
|
||||
if (j == h)
|
||||
{
|
||||
printf("enterSym: sym table overflow!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void enterSym(char *symName, dword symOff, Function * symProc, boolT bSymToo)
|
||||
{
|
||||
currentTabInfo.enterSym(symName,symOff,symProc,bSymToo);
|
||||
}
|
||||
|
||||
boolT TABLEINFO_TYPE::findSym(const char *symName, word &pIndex)
|
||||
{
|
||||
word h, j, pre;
|
||||
|
||||
h = symHash(symName, &pre);
|
||||
j = h;
|
||||
bool found=false;
|
||||
do
|
||||
{
|
||||
if (symTab[j].pSymName.empty())
|
||||
{
|
||||
return FALSE; /* No entry at all */
|
||||
}
|
||||
if (strcmp(symName, symTab[j].pSymName.c_str()) == 0)
|
||||
{
|
||||
pIndex = j;
|
||||
found=true;
|
||||
break; /* Symbol found */
|
||||
}
|
||||
j = symTab[j].nextOvf; /* Follow the chain */
|
||||
}
|
||||
while (j != NIL);
|
||||
auto iter = z.find(symName);
|
||||
if(iter!=z.end())
|
||||
{
|
||||
assert(iter->second==symTab[j]);
|
||||
}
|
||||
|
||||
return found; /* End of chain */
|
||||
}
|
||||
/* Find symbol by value */
|
||||
std::string TABLEINFO_TYPE::findVal(dword symOff, Function * symProc, word &pIndex)
|
||||
{
|
||||
word h, j, pre;
|
||||
std::string res="";
|
||||
h = valHash(symOff, symProc, &pre);
|
||||
j = h;
|
||||
do
|
||||
{
|
||||
if (valTab[j].symProc == 0)
|
||||
break; /* No entry at all */
|
||||
|
||||
if ((valTab[j].symOff == symOff) /*&& (valTab[j].symProc == symProc)*/)
|
||||
{
|
||||
pIndex = j;
|
||||
res=valTab[j].pSymName;
|
||||
break; /* Symbol found */
|
||||
}
|
||||
j = valTab[j].nextOvf; /* Follow the chain */
|
||||
}
|
||||
while (j != NIL);
|
||||
auto iter = z2.find(SYMTABLE(symOff,symProc));
|
||||
if(iter!=z2.end())
|
||||
{
|
||||
assert(iter->second==res);
|
||||
}
|
||||
return res; /* End of chain */
|
||||
}
|
||||
|
||||
word TABLEINFO_TYPE::findBlankSym(const std::string &symName)
|
||||
{
|
||||
word h, j, pre;
|
||||
|
||||
h = symHash(symName.c_str(), &pre);
|
||||
j = h;
|
||||
do
|
||||
{
|
||||
if (symTab[j].pSymName.empty())
|
||||
{
|
||||
return j; /* Empty entry. Terminate probing */
|
||||
}
|
||||
j = (++j) % tableSize; /* Linear probing */
|
||||
}
|
||||
while (j != h);
|
||||
printf("Could not find blank entry in table! Num entries is %ld of %ld\n",
|
||||
(long)numEntry, (long)tableSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Using the symbolic name, read the value */
|
||||
boolT TABLEINFO_TYPE::readSym(char *symName, dword *pSymOff, Function * *pSymProc)
|
||||
{
|
||||
word i;
|
||||
|
||||
if (!findSym(symName, i))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
*pSymOff = symTab[i].symOff;
|
||||
*pSymProc= symTab[i].symProc;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* A doubly linked list of entries belonging to the same hash bucket is
|
||||
maintained, to prevent the need for many entries to be moved when deleting
|
||||
an entry. It is implemented with indexes, and is not an open hashing system.
|
||||
Symbols are deleted from both hash tables.
|
||||
*/
|
||||
|
||||
/* Known limitation: strings are never deleted from the string table */
|
||||
|
||||
void TABLEINFO_TYPE::deleteSym(char *symName)
|
||||
{
|
||||
word i, j, back;
|
||||
dword symOff;
|
||||
Function * symProc;
|
||||
|
||||
/* Delete from symbol hashed table first */
|
||||
if (!findSym(symName, i))
|
||||
{
|
||||
printf("Could not delete non existant symbol name %s\n", symName);
|
||||
exit(1);
|
||||
}
|
||||
symOff = symTab[i].symOff; /* Remember these for valTab */
|
||||
symProc= symTab[i].symProc;
|
||||
j = symTab[i].nextOvf; /* Look at next overflowed entry */
|
||||
|
||||
if (j == NIL) /* Any overflows? */
|
||||
{
|
||||
/* No, so we just wipe out this record. Must NIL the pointer of
|
||||
the previous record, however */
|
||||
symTab[symTab[i].prevOvf].nextOvf = NIL;
|
||||
j = i; /* So we wipe out the current name */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, move this entry to this vacated spot. Note that the nextOvf
|
||||
field will still point to the next record in the overflow chain,
|
||||
but we need to preserve the backlink for adjusting the current
|
||||
item's backlink */
|
||||
back = symTab[j].prevOvf;
|
||||
symTab[i] = symTab[j];
|
||||
symTab[i].prevOvf = back;
|
||||
}
|
||||
/* And now mark the vacated record as empty */
|
||||
symTab[j].pSymName.clear(); /* Rub out the name */
|
||||
|
||||
|
||||
/* Delete from value hashed table */
|
||||
if (findVal(symOff, symProc, i).empty())
|
||||
{
|
||||
printf("Could not delete non existant symbol off %04X proc %d\n",symOff, symProc);
|
||||
exit(1);
|
||||
}
|
||||
j = valTab[i].nextOvf; /* Look at next overflowed entry */
|
||||
|
||||
if (j == NIL) /* Any overflows? */
|
||||
{
|
||||
/* No, so we just wipe out this record. Must NIL the pointer of
|
||||
the previous record, however */
|
||||
valTab[valTab[i].prevOvf].nextOvf = NIL;
|
||||
j = i; /* So we wipe out the current entry */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, move this entry to this vacated spot. Note that the nextOvf
|
||||
field will still point to the next record in the overflow chain,
|
||||
but we need to preserve the backlink for adjusting the current
|
||||
item's backlink */
|
||||
back = valTab[j].prevOvf;
|
||||
valTab[i]= valTab[j];
|
||||
valTab[i].prevOvf = back;
|
||||
}
|
||||
/* And now mark the vacated record as empty */
|
||||
valTab[j].symProc = 0; /* Rub out the entry */
|
||||
}
|
||||
void TABLEINFO_TYPE::deleteVal(dword symOff, Function * symProc, boolT bSymToo)
|
||||
{
|
||||
word i, j, back;
|
||||
std::string symName;
|
||||
|
||||
/* Delete from value hashed table */
|
||||
if (findVal(symOff, symProc, i).empty())
|
||||
{
|
||||
printf("Could not delete non existant symbol off %04X proc %p\n",
|
||||
symOff, symProc);
|
||||
exit(1);
|
||||
}
|
||||
symName = symTab[i].pSymName; /* Remember this for symTab */
|
||||
j = valTab[i].nextOvf; /* Look at next overflowed entry */
|
||||
|
||||
if (j == NIL) /* Any overflows? */
|
||||
{
|
||||
/* No, so we just wipe out this record. Must NIL the pointer of
|
||||
the previous record, however */
|
||||
valTab[valTab[i].prevOvf].nextOvf = NIL;
|
||||
j = i; /* So we wipe out the current entry */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, move this entry to this vacated spot. Note that the nextOvf
|
||||
field will still point to the next record in the overflow chain,
|
||||
but we need to preserve the backlink for adjusting the current
|
||||
item's backlink */
|
||||
back = valTab[j].prevOvf;
|
||||
memcpy(&valTab[i], &valTab[j], sizeof(SYMTABLE));
|
||||
valTab[i].prevOvf = back;
|
||||
}
|
||||
/* And now mark the vacated record as empty */
|
||||
valTab[j].symProc = 0; /* Rub out the entry */
|
||||
|
||||
/* If requested, delete from symbol hashed table now */
|
||||
if (!bSymToo) return;
|
||||
if (!findSym(symName.c_str(), i))
|
||||
{
|
||||
printf("Could not delete non existant symbol name %s\n", symName.c_str());
|
||||
exit(1);
|
||||
}
|
||||
j = symTab[i].nextOvf; /* Look at next overflowed entry */
|
||||
|
||||
if (j == NIL) /* Any overflows? */
|
||||
{
|
||||
/* No, so we just wipe out this record. Must NIL the pointer of
|
||||
the previous record, however */
|
||||
symTab[symTab[i].prevOvf].nextOvf = NIL;
|
||||
j = i; /* So we wipe out the current name */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, move this entry to this vacated spot. Note that the nextOvf
|
||||
field will still point to the next record in the overflow chain,
|
||||
but we need to preserve the backlink for adjusting the current
|
||||
item's backlink */
|
||||
back = symTab[j].prevOvf;
|
||||
symTab[i] = symTab[j];
|
||||
symTab[i].prevOvf = back;
|
||||
}
|
||||
/* And now mark the vacated record as empty */
|
||||
symTab[j].pSymName.clear(); /* Rub out the name */
|
||||
|
||||
}
|
||||
|
||||
void TABLEINFO_TYPE::expandSym(void)
|
||||
{
|
||||
word i, j, n, newPost;
|
||||
|
||||
printf("\nResizing table...\r");
|
||||
/* We double the table size each time, so on average only half of the
|
||||
entries move to the new half. This works because we are effectively
|
||||
shifting the "binary point" of the hash value to the left each time,
|
||||
thereby leaving the number unchanged or adding an MSBit of 1. */
|
||||
tableSize <<= 2;
|
||||
symTab = (SYMTABLE*)reallocVar(symTab, tableSize * sizeof(SYMTABLE));
|
||||
memset (&symTab[tableSize/2], 0, (tableSize/2) * sizeof(SYMTABLE));
|
||||
|
||||
/* Now we have to move some of the entries to take advantage of the extra
|
||||
space */
|
||||
|
||||
for (i=0; i < numEntry; i++)
|
||||
{
|
||||
newPost = symTab[i].preHash % tableSize;
|
||||
if (newPost != symTab[i].postHash)
|
||||
{
|
||||
/* This entry is now in the wrong place. Copy it to the new position,
|
||||
then delete it. */
|
||||
j = findBlankSym(symTab[i].pSymName);
|
||||
memcpy(&symTab[j], &symTab[i], sizeof(SYMTABLE));
|
||||
/* Correct the post hash value */
|
||||
symTab[j].postHash = newPost;
|
||||
|
||||
/* Now adjust links */
|
||||
n = symTab[j].prevOvf;
|
||||
if (n != NIL)
|
||||
{
|
||||
symTab[n].nextOvf = j;
|
||||
}
|
||||
|
||||
n = symTab[j].nextOvf;
|
||||
if (n != NIL)
|
||||
{
|
||||
symTab[n].prevOvf = j;
|
||||
}
|
||||
|
||||
/* Mark old position as deleted */
|
||||
symTab[i].pSymName.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function adds to the string table. At this stage, strings are not
|
||||
deleted */
|
||||
char * addStrTbl(char *pStr)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if ((strTabNext + strlen(pStr) + 1) >= STRTABSIZE)
|
||||
{
|
||||
/* We can't realloc the old string table pointer, since that will
|
||||
potentially move the string table, and pointers will be invalid.
|
||||
So we realloc this one to its present usage (hopefully it won't
|
||||
move), and allocate a new one */
|
||||
if (reallocVar((void *)pStrTab, strTabNext) != pStrTab)
|
||||
{
|
||||
printf("Damn it! String table moved on shrinking!\n");
|
||||
exit(1);
|
||||
}
|
||||
pStrTab = (char *)allocMem(STRTABSIZE);
|
||||
strTabNext = 0;
|
||||
}
|
||||
p = strcpy(&pStrTab[strTabNext], pStr);
|
||||
strTabNext += strlen(pStr) +1;
|
||||
return p;
|
||||
}
|
||||
void deleteVal(dword symOff, Function * symProc, boolT bSymToo)
|
||||
{
|
||||
currentTabInfo.deleteVal(symOff,symProc,bSymToo);
|
||||
}
|
||||
std::string findVal(dword symOff, Function * symProc, word *pIndex)
|
||||
{
|
||||
return currentTabInfo.findVal(symOff,symProc,*pIndex);
|
||||
}
|
||||
/* Using the value, read the symbolic name */
|
||||
boolT readVal(char *symName, dword symOff, Function * symProc)
|
||||
{
|
||||
word i;
|
||||
std::string r=currentTabInfo.findVal(symOff, symProc, i);
|
||||
if (r.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
strcpy(symName, r.c_str());
|
||||
return true;
|
||||
return false; // no symbolic names for now
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user