init
This commit is contained in:
commit
4c249fe5c4
63
CMakeLists.txt
Executable file
63
CMakeLists.txt
Executable file
@ -0,0 +1,63 @@
|
||||
#CC = gcc -g -O -D__UNIX__
|
||||
PROJECT(dcc_original)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
SET(CMAKE_BUILD_TYPE Debug)
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__)
|
||||
INCLUDE_DIRECTORIES(include ${Boost_INCLUDE_DIRS})
|
||||
if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
add_definitions(/W4)
|
||||
else()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++0x")
|
||||
endif()
|
||||
|
||||
set(dcc_SOURCES
|
||||
src/dcc.cpp
|
||||
src/ast.cpp
|
||||
src/backend.cpp
|
||||
src/bundle.cpp
|
||||
src/chklib.cpp
|
||||
src/comwrite.cpp
|
||||
src/control.cpp
|
||||
src/dataflow.cpp
|
||||
src/disassem.cpp
|
||||
src/error.cpp
|
||||
src/fixwild.cpp
|
||||
src/frontend.cpp
|
||||
src/graph.cpp
|
||||
src/hlicode.cpp
|
||||
src/icode.cpp
|
||||
src/idioms.cpp
|
||||
src/locident.cpp
|
||||
src/parser.cpp
|
||||
src/perfhlib.cpp
|
||||
src/procs.cpp
|
||||
src/proplong.cpp
|
||||
src/reducible.cpp
|
||||
src/scanner.cpp
|
||||
src/symtab.cpp
|
||||
src/udm.cpp
|
||||
src/BasicBlock.cpp
|
||||
)
|
||||
set(dcc_HEADERS
|
||||
include/ast.h
|
||||
include/bundle.h
|
||||
include/dcc.h
|
||||
include/disassem.h
|
||||
include/dosdcc.h
|
||||
include/error.h
|
||||
include/graph.h
|
||||
include/hlicode.h
|
||||
include/icode.h
|
||||
include/locident.h
|
||||
include/perfhlib.h
|
||||
include/scanner.h
|
||||
include/state.h
|
||||
include/symtab.h
|
||||
include/types.h
|
||||
include/Procedure.h
|
||||
include/StackFrame.h
|
||||
include/BasicBlock.h
|
||||
)
|
||||
ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
|
||||
|
||||
88
include/BasicBlock.h
Normal file
88
include/BasicBlock.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "types.h"
|
||||
/* Basic block (BB) node definition */
|
||||
struct Function;
|
||||
class CIcodeRec;
|
||||
struct BB;
|
||||
struct interval;
|
||||
typedef union
|
||||
{
|
||||
dword ip; /* Out edge icode address */
|
||||
BB * BBptr; /* Out edge pointer to next BB */
|
||||
interval *intPtr; /* Out edge ptr to next interval*/
|
||||
} TYPEADR_TYPE;
|
||||
|
||||
struct BB
|
||||
{
|
||||
protected:
|
||||
BB(const BB&);
|
||||
BB() : nodeType(0),traversed(0),start(0),length(0),
|
||||
numHlIcodes(0),flg(0),
|
||||
numInEdges(0),inEdges(0),
|
||||
numOutEdges(0),edges(0),beenOnH(0),inEdgeCount(0),reachingInt(0),
|
||||
inInterval(0),correspInt(0),liveUse(0),def(0),liveIn(0),liveOut(0),
|
||||
dfsFirstNum(0),dfsLastNum(0),immedDom(0),ifFollow(0),loopType(0),latchNode(0),
|
||||
numBackEdges(0),loopHead(0),loopFollow(0),caseHead(0),caseTail(0),index(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
byte nodeType; /* Type of node */
|
||||
Int traversed; /* Boolean: traversed yet? */
|
||||
Int start; /* First instruction offset */
|
||||
Int length; /* No. of instructions this BB */
|
||||
Int numHlIcodes; /* No. of high-level icodes */
|
||||
flags32 flg; /* BB flags */
|
||||
|
||||
/* In edges and out edges */
|
||||
Int numInEdges; /* Number of in edges */
|
||||
std::vector<BB *> inEdges; // does not own held pointers
|
||||
|
||||
Int numOutEdges; /* Number of out edges */
|
||||
std::vector<TYPEADR_TYPE> edges;/* Array of ptrs. to out edges */
|
||||
|
||||
/* For interval construction */
|
||||
Int beenOnH; /* #times been on header list H */
|
||||
Int inEdgeCount; /* #inEdges (to find intervals) */
|
||||
BB * reachingInt; /* Reaching interval header */
|
||||
interval *inInterval; /* Node's interval */
|
||||
|
||||
/* For derived sequence construction */
|
||||
interval *correspInt; /* Corresponding interval in
|
||||
* derived graph Gi-1 */
|
||||
|
||||
/* For live register analysis
|
||||
* LiveIn(b) = LiveUse(b) U (LiveOut(b) - Def(b)) */
|
||||
dword liveUse; /* LiveUse(b) */
|
||||
dword def; /* Def(b) */
|
||||
dword liveIn; /* LiveIn(b) */
|
||||
dword liveOut; /* LiveOut(b) */
|
||||
|
||||
/* For structuring analysis */
|
||||
Int dfsFirstNum; /* DFS #: first visit of node */
|
||||
Int dfsLastNum; /* DFS #: last visit of node */
|
||||
Int immedDom; /* Immediate dominator (dfsLast
|
||||
* index) */
|
||||
Int ifFollow; /* node that ends the if */
|
||||
Int loopType; /* Type of loop (if any) */
|
||||
Int latchNode; /* latching node of the loop */
|
||||
Int numBackEdges; /* # of back edges */
|
||||
Int loopHead; /* most nested loop head to which
|
||||
* thcis node belongs (dfsLast) */
|
||||
Int loopFollow; /* node that follows the loop */
|
||||
Int caseHead; /* most nested case to which this
|
||||
node belongs (dfsLast) */
|
||||
Int caseTail; /* tail node for the case */
|
||||
|
||||
Int index; /* Index, used in several ways */
|
||||
static BB *Create(void *ctx=0,const std::string &s="",Function *parent=0,BB *insertBefore=0);
|
||||
static BB *Create(Int start, Int ip, byte nodeType, Int numOutEdges, Function * parent);
|
||||
void writeCode(Int indLevel, Function *pProc, Int *numLoc, Int latchNode, Int ifFollow);
|
||||
void mergeFallThrough(CIcodeRec &Icode);
|
||||
void dfsNumbering(std::vector<BB *> &dfsLast, Int *first, Int *last);
|
||||
void displayDfs();
|
||||
};
|
||||
85
include/Enums.h
Normal file
85
include/Enums.h
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
/* Register types */
|
||||
enum regType
|
||||
{
|
||||
BYTE_REG,
|
||||
WORD_REG
|
||||
};
|
||||
enum condId
|
||||
{
|
||||
GLOB_VAR, /* global variable */
|
||||
REGISTER, /* register */
|
||||
LOCAL_VAR, /* negative disp */
|
||||
PARAM, /* positive disp */
|
||||
GLOB_VAR_IDX, /* indexed global variable *//*** should merge w/glob-var*/
|
||||
CONSTANT, /* constant */
|
||||
STRING, /* string */
|
||||
LONG_VAR, /* long variable */
|
||||
FUNCTION, /* function */
|
||||
OTHER /* other **** tmp solution */
|
||||
};
|
||||
|
||||
enum condOp
|
||||
{
|
||||
/* For conditional expressions */
|
||||
LESS_EQUAL = 0, /* <= */
|
||||
LESS, /* < */
|
||||
EQUAL, /* == */
|
||||
NOT_EQUAL, /* != */
|
||||
GREATER, /* > */
|
||||
GREATER_EQUAL, /* >= */
|
||||
/* For general expressions */
|
||||
AND, /* & */
|
||||
OR, /* | */
|
||||
XOR, /* ^ */
|
||||
NOT, /* ~ */ /* 1's complement */
|
||||
ADD, /* + */
|
||||
SUB, /* - */
|
||||
MUL, /* * */
|
||||
DIV, /* / */
|
||||
SHR, /* >> */
|
||||
SHL, /* << */
|
||||
MOD, /* % */
|
||||
DBL_AND, /* && */
|
||||
DBL_OR, /* || */
|
||||
DUMMY /* */
|
||||
};
|
||||
/* LOW_LEVEL operand location: source or destination */
|
||||
enum opLoc
|
||||
{
|
||||
SRC, /* Source operand */
|
||||
DST, /* Destination operand */
|
||||
LHS_OP /* Left-hand side operand (for HIGH_LEVEL) */
|
||||
};
|
||||
|
||||
/* Conditional Expression enumeration nodes and operators */
|
||||
enum condNodeType
|
||||
{
|
||||
UNKNOWN_OP=0,
|
||||
BOOLEAN_OP, /* condOps */
|
||||
NEGATION, /* not (2's complement) */
|
||||
ADDRESSOF, /* addressOf (&) */
|
||||
DEREFERENCE, /* contents of (*) */
|
||||
IDENTIFIER, /* {register | local | param | constant | global} */
|
||||
/* The following are only available to C programs */
|
||||
POST_INC, /* ++ (post increment) */
|
||||
POST_DEC, /* -- (post decrement) */
|
||||
PRE_INC, /* ++ (pre increment) */
|
||||
PRE_DEC /* -- (pre decrement) */
|
||||
} ;
|
||||
|
||||
/* Enumeration to determine whether pIcode points to the high or low part
|
||||
* of a long number */
|
||||
enum hlFirst
|
||||
{
|
||||
HIGH_FIRST, /* High value is first */
|
||||
LOW_FIRST /* Low value is first */
|
||||
};
|
||||
/* Operand is defined, used or both flag */
|
||||
enum operDu
|
||||
{
|
||||
eDEF=0x10, /* Operand is defined */
|
||||
eUSE=0x100, /* Operand is used */
|
||||
USE_DEF, /* Operand is used and defined */
|
||||
NONE /* No operation is required on this operand */
|
||||
};
|
||||
31
include/IdentType.h
Normal file
31
include/IdentType.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "ast.h"
|
||||
#include "types.h"
|
||||
struct IDENTTYPE
|
||||
{
|
||||
condId idType;
|
||||
regType regiType; /* for REGISTER only */
|
||||
union _idNode {
|
||||
Int regiIdx; /* index into localId, REGISTER */
|
||||
Int globIdx; /* index into symtab for GLOB_VAR */
|
||||
Int localIdx; /* idx into localId, LOCAL_VAR */
|
||||
Int paramIdx; /* idx into args symtab, PARAMS */
|
||||
Int idxGlbIdx; /* idx into localId, GLOB_VAR_IDX */
|
||||
struct _kte
|
||||
{ /* for CONSTANT only */
|
||||
dword kte; /* value of the constant */
|
||||
byte size; /* #bytes size constant */
|
||||
} kte;
|
||||
dword strIdx; /* idx into image, for STRING */
|
||||
Int longIdx; /* idx into LOCAL_ID table, LONG_VAR*/
|
||||
struct _call { /* for FUNCTION only */
|
||||
Function *proc;
|
||||
STKFRAME *args;
|
||||
} call;
|
||||
struct { /* for OTHER; tmp struct */
|
||||
byte seg; /* segment */
|
||||
byte regi; /* index mode */
|
||||
int16 off; /* offset */
|
||||
} other;
|
||||
} idNode;
|
||||
};
|
||||
77
include/Procedure.h
Normal file
77
include/Procedure.h
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#include "ast.h"
|
||||
#include "icode.h"
|
||||
#include "locident.h"
|
||||
#include "error.h"
|
||||
#include "graph.h"
|
||||
#include "bundle.h"
|
||||
#include "StackFrame.h"
|
||||
/* PROCEDURE NODE */
|
||||
struct CALL_GRAPH;
|
||||
struct Function
|
||||
{
|
||||
dword procEntry; /* label number */
|
||||
char name[SYMLEN]; /* Meaningful name for this proc */
|
||||
STATE state; /* Entry state */
|
||||
Int depth; /* Depth at which we found it - for printing */
|
||||
flags32 flg; /* Combination of Icode & Proc flags */
|
||||
int16 cbParam; /* Probable no. of bytes of parameters */
|
||||
STKFRAME args; /* Array of arguments */
|
||||
LOCAL_ID localId; /* Local identifiers */
|
||||
ID retVal; /* Return value - identifier */
|
||||
|
||||
/* Icodes and control flow graph */
|
||||
CIcodeRec Icode; /* Object with ICODE records */
|
||||
std::vector<BB*> cfg; /* Ptr. to BB list/CFG */
|
||||
std::vector<BB*> dfsLast;
|
||||
std::vector<BB*> heldBBs;
|
||||
//BB * *dfsLast; /* Array of pointers to BBs in dfsLast
|
||||
// * (reverse postorder) order */
|
||||
Int numBBs; /* Number of BBs in the graph cfg */
|
||||
boolT hasCase; /* Procedure has a case node */
|
||||
|
||||
/* For interprocedural live analysis */
|
||||
dword liveIn; /* Registers used before defined */
|
||||
dword liveOut; /* Registers that may be used in successors */
|
||||
boolT liveAnal; /* Procedure has been analysed already */
|
||||
|
||||
/* Double-linked list */
|
||||
// Function *next;
|
||||
// Function *prev;
|
||||
public:
|
||||
Function() : procEntry(0),depth(0),flg(0),cbParam(0),cfg(0),dfsLast(0),numBBs(0),
|
||||
hasCase(false),liveIn(0),liveOut(0),liveAnal(0)//,next(0),prev(0)
|
||||
{
|
||||
memset(name,0,SYMLEN);
|
||||
}
|
||||
void compoundCond();
|
||||
void writeProcComments();
|
||||
void lowLevelAnalysis();
|
||||
void bindIcodeOff();
|
||||
void dataFlow(dword liveOut);
|
||||
void compressCFG();
|
||||
void highLevelGen();
|
||||
void structure(derSeq *derivedG);
|
||||
derSeq *checkReducibility();
|
||||
void createCFG();
|
||||
void markImpure();
|
||||
void findImmedDom();
|
||||
void FollowCtrl(CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void process_operands(ICODE *pIcode, STATE *pstate);
|
||||
boolT process_JMP(ICODE *pIcode, STATE *pstate, CALL_GRAPH *pcallGraph);
|
||||
boolT process_CALL(ICODE *pIcode, CALL_GRAPH *pcallGraph, STATE *pstate);
|
||||
void displayCFG();
|
||||
void freeCFG();
|
||||
void codeGen(std::ostream &fs);
|
||||
void displayStats();
|
||||
void mergeFallThrough(BB *pBB);
|
||||
protected:
|
||||
void findExps();
|
||||
void genDU1();
|
||||
void elimCondCodes();
|
||||
void liveRegAnalysis(dword in_liveOut);
|
||||
void findIdioms();
|
||||
void propLong();
|
||||
void genLiveKtes();
|
||||
};
|
||||
45
include/StackFrame.h
Normal file
45
include/StackFrame.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
#include "ast.h"
|
||||
#include "icode.h"
|
||||
#include "locident.h"
|
||||
#include "error.h"
|
||||
#include "graph.h"
|
||||
#include "bundle.h"
|
||||
|
||||
/* STACK FRAME */
|
||||
struct STKSYM
|
||||
{
|
||||
COND_EXPR *actual; /* Expression tree of actual parameter */
|
||||
COND_EXPR *regs; /* For register arguments only */
|
||||
int16 off; /* Immediate off from BP (+:args, -:params) */
|
||||
byte regOff; /* Offset is a register (e.g. SI, DI) */
|
||||
Int size; /* Size */
|
||||
hlType type; /* Probable type */
|
||||
eDuVal duVal; /* DEF, USE, VAL */
|
||||
boolT hasMacro; /* This type needs a macro */
|
||||
char macro[10]; /* Macro name */
|
||||
char name[10]; /* Name for this symbol/argument */
|
||||
boolT invalid; /* Boolean: invalid entry in formal arg list*/
|
||||
STKSYM()
|
||||
{
|
||||
memset(this,0,sizeof(STKSYM));
|
||||
}
|
||||
};
|
||||
|
||||
struct STKFRAME
|
||||
{
|
||||
std::vector<STKSYM> sym;
|
||||
//STKSYM * sym; /* Symbols */
|
||||
int16 minOff; /* Initial offset in stack frame*/
|
||||
int16 maxOff; /* Maximum offset in stack frame*/
|
||||
Int cb; /* Number of bytes in arguments */
|
||||
Int numArgs; /* No. of arguments in the table*/
|
||||
void adjustForArgType(Int numArg_, hlType actType_);
|
||||
STKFRAME() : sym(0),minOff(0),maxOff(0),cb(0),numArgs(0)
|
||||
{
|
||||
|
||||
}
|
||||
public:
|
||||
Int getLocVar(Int off);
|
||||
};
|
||||
91
include/ast.h
Normal file
91
include/ast.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* File: ast.h
|
||||
* Purpose: definition of the abstract syntax tree ADT.
|
||||
* Date: September 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#pragma once
|
||||
static const int operandSize=20;
|
||||
#include <cstring>
|
||||
#include "Enums.h"
|
||||
/* The following definitions and types define the Conditional Expression
|
||||
* attributed syntax tree, as defined by the following EBNF:
|
||||
CondExp ::= CondTerm AND CondTerm | CondTerm
|
||||
CondTerm ::= (CondFactor op CondFactor)
|
||||
CondFactor ::= Identifier | ! CondFactor
|
||||
Identifier ::= globalVar | register | localVar | parameter | constant
|
||||
op ::= <= | < | = | != | > | >=
|
||||
*/
|
||||
|
||||
/* High-level BOOLEAN conditions for iJB..iJNS icodes */
|
||||
static const condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER,
|
||||
EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL,
|
||||
LESS_EQUAL, GREATER, GREATER_EQUAL, LESS};
|
||||
|
||||
static const condOp invCondOpJCond[12] = {GREATER_EQUAL, GREATER, LESS, LESS_EQUAL,
|
||||
NOT_EQUAL, EQUAL, GREATER_EQUAL, LESS,
|
||||
GREATER, LESS_EQUAL, LESS, GREATER_EQUAL};
|
||||
|
||||
struct Function;
|
||||
struct STKFRAME;
|
||||
struct LOCAL_ID;
|
||||
struct ICODE;
|
||||
struct ID;
|
||||
#include "IdentType.h"
|
||||
//enum opLoc;
|
||||
//enum hlFirst;
|
||||
//enum operDu;
|
||||
/* Expression data type */
|
||||
struct COND_EXPR
|
||||
{
|
||||
condNodeType type; /* Conditional Expression Node Type */
|
||||
union _exprNode { /* Different cond expr nodes */
|
||||
struct /* for BOOLEAN_OP */
|
||||
{
|
||||
condOp op;
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
} boolExpr;
|
||||
COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/
|
||||
IDENTTYPE ident; /* for IDENTIFIER */
|
||||
} expr;
|
||||
public:
|
||||
static COND_EXPR *idGlob(int16 segValue, int16 off);
|
||||
static COND_EXPR *idRegIdx(Int idx, regType reg_type);
|
||||
static COND_EXPR *idKte(dword kte, byte size);
|
||||
static COND_EXPR *idLoc(Int off, LOCAL_ID *localId);
|
||||
static COND_EXPR *idReg(byte regi, flags32 icodeFlg, LOCAL_ID *locsym);
|
||||
static COND_EXPR *idLongIdx(Int idx);
|
||||
static COND_EXPR *idOther(byte seg, byte regi, int16 off);
|
||||
static COND_EXPR *idParam(Int off, const STKFRAME *argSymtab);
|
||||
static COND_EXPR *unary(condNodeType t, COND_EXPR *sub_expr);
|
||||
static COND_EXPR *idLong(LOCAL_ID *localId, opLoc sd, ICODE *pIcode, hlFirst f, Int ix, operDu du, Int off);
|
||||
static COND_EXPR *idFunc(Function *pproc, STKFRAME *args);
|
||||
static COND_EXPR *idID(const ID *retVal, LOCAL_ID *locsym, Int ix);
|
||||
static COND_EXPR *id(ICODE *pIcode, opLoc sd, Function *pProc, Int i, ICODE *duIcode, operDu du);
|
||||
static COND_EXPR *boolOp(COND_EXPR *lhs, COND_EXPR *rhs, condOp op);
|
||||
public:
|
||||
COND_EXPR *clone();
|
||||
void release();
|
||||
void changeBoolOp(condOp newOp);
|
||||
COND_EXPR(COND_EXPR &other)
|
||||
{
|
||||
type=other.type;
|
||||
expr=other.expr;
|
||||
}
|
||||
COND_EXPR()
|
||||
{
|
||||
type=UNKNOWN_OP;
|
||||
memset(&expr,0,sizeof(_exprNode));
|
||||
}
|
||||
};
|
||||
|
||||
/* Sequence of conditional expression data type */
|
||||
/*** NOTE: not used at present ****/
|
||||
//struct SEQ_COND_EXPR
|
||||
//{
|
||||
// COND_EXPR *expr;
|
||||
// struct _condExpSeq *neccxt;
|
||||
//};
|
||||
|
||||
|
||||
31
include/bundle.h
Normal file
31
include/bundle.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*****************************************************************************
|
||||
* Project: dcc
|
||||
* File: bundle.h
|
||||
* Purpose: Module to handle the bundle type (array of pointers to strings).
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
typedef std::vector<std::string> strTable;
|
||||
|
||||
struct bundle
|
||||
{
|
||||
public:
|
||||
void appendCode(const char *format, ...);
|
||||
void appendDecl(const char *format, ...);
|
||||
strTable decl; /* Declarations */
|
||||
strTable code; /* C code */
|
||||
};
|
||||
|
||||
|
||||
#define lineSize 360 /* 3 lines in the mean time */
|
||||
|
||||
void newBundle (bundle *procCode);
|
||||
//void appendStrTab (strTable *strTab, const char *format, ...);
|
||||
Int nextBundleIdx (strTable *strTab);
|
||||
void addLabelBundle (strTable &strTab, Int idx, Int label);
|
||||
void writeBundle (std::ostream &ios, bundle procCode);
|
||||
void freeBundle (bundle *procCode);
|
||||
|
||||
219
include/dcc.h
Normal file
219
include/dcc.h
Normal file
@ -0,0 +1,219 @@
|
||||
/****************************************************************************
|
||||
* dcc project general header
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "ast.h"
|
||||
#include "icode.h"
|
||||
#include "locident.h"
|
||||
#include "error.h"
|
||||
#include "graph.h"
|
||||
#include "bundle.h"
|
||||
#include "Procedure.h"
|
||||
#include "BasicBlock.h"
|
||||
typedef std::list<Function> lFunction;
|
||||
typedef std::list<Function>::iterator ilFunction;
|
||||
|
||||
/* SYMBOL TABLE */
|
||||
struct SYM {
|
||||
char name[10]; /* New name for this variable */
|
||||
dword label; /* physical address (20 bit) */
|
||||
Int size; /* maximum size */
|
||||
flags32 flg; /* SEG_IMMED, IMPURE, WORD_OFF */
|
||||
hlType type; /* probable type */
|
||||
eDuVal duVal; /* DEF, USE, VAL */
|
||||
};
|
||||
|
||||
struct SYMTAB
|
||||
{
|
||||
Int csym; /* No. of symbols in table */
|
||||
Int alloc; /* Allocation */
|
||||
SYM * sym; /* Symbols */
|
||||
};
|
||||
|
||||
/* CALL GRAPH NODE */
|
||||
struct CALL_GRAPH
|
||||
{
|
||||
ilFunction proc; /* Pointer to procedure in pProcList */
|
||||
std::vector<CALL_GRAPH *> outEdges; /* array of out edges */
|
||||
public:
|
||||
void write();
|
||||
CALL_GRAPH() : outEdges(0)
|
||||
{
|
||||
}
|
||||
public:
|
||||
void writeNodeCallGraph(Int indIdx);
|
||||
boolT insertCallGraph(ilFunction caller, ilFunction callee);
|
||||
boolT insertCallGraph(Function *caller, ilFunction callee);
|
||||
void insertArc(ilFunction newProc);
|
||||
};
|
||||
#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */
|
||||
extern std::list<Function> pProcList;
|
||||
extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */
|
||||
extern bundle cCode; /* Output C procedure's declaration and code */
|
||||
|
||||
/* Procedure FLAGS */
|
||||
enum PROC_FLAGS
|
||||
{
|
||||
PROC_BADINST=0x000100,/* Proc contains invalid or 386 instruction */
|
||||
PROC_IJMP =0x000200,/* Proc incomplete due to indirect jmp */
|
||||
PROC_ICALL =0x000400, /* Proc incomplete due to indirect call */
|
||||
PROC_HLL=0x001000, /* Proc is likely to be from a HLL */
|
||||
CALL_PASCAL=0x002000, /* Proc uses Pascal calling convention */
|
||||
CALL_C=0x004000, /* Proc uses C calling convention */
|
||||
CALL_UNKNOWN=0x008000, /* Proc uses unknown calling convention */
|
||||
PROC_NEAR=0x010000, /* Proc exits with near return */
|
||||
PROC_FAR=0x020000, /* Proc exits with far return */
|
||||
GRAPH_IRRED=0x100000, /* Proc generates an irreducible graph */
|
||||
SI_REGVAR=0x200000, /* SI is used as a stack variable */
|
||||
DI_REGVAR=0x400000, /* DI is used as a stack variable */
|
||||
PROC_IS_FUNC=0x800000, /* Proc is a function */
|
||||
REG_ARGS=0x1000000, /* Proc has registers as arguments */
|
||||
PROC_VARARG=0x2000000, /* Proc has variable arguments */
|
||||
PROC_OUTPUT=0x4000000, /* C for this proc has been output */
|
||||
PROC_RUNTIME=0x8000000, /* Proc is part of the runtime support */
|
||||
PROC_ISLIB=0x10000000, /* Proc is a library function */
|
||||
PROC_ASM=0x20000000, /* Proc is an intrinsic assembler routine */
|
||||
PROC_IS_HLL=0x40000000 /* Proc has HLL prolog code */
|
||||
};
|
||||
#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */
|
||||
|
||||
|
||||
|
||||
|
||||
/**** Global variables ****/
|
||||
|
||||
extern char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
|
||||
typedef struct { /* Command line option flags */
|
||||
unsigned verbose : 1;
|
||||
unsigned VeryVerbose : 1;
|
||||
unsigned asm1 : 1; /* Early disassembly listing */
|
||||
unsigned asm2 : 1; /* Disassembly listing after restruct */
|
||||
unsigned Map : 1;
|
||||
unsigned Stats : 1;
|
||||
unsigned Interact : 1; /* Interactive mode */
|
||||
unsigned Calls : 1; /* Follow register indirect calls */
|
||||
char filename[80]; /* The input filename */
|
||||
} OPTION;
|
||||
|
||||
extern OPTION option; /* Command line options */
|
||||
extern SYMTAB symtab; /* Global symbol table */
|
||||
|
||||
struct PROG /* Loaded program image parameters */
|
||||
{
|
||||
int16 initCS;
|
||||
int16 initIP; /* These are initial load values */
|
||||
int16 initSS; /* Probably not of great interest */
|
||||
int16 initSP;
|
||||
boolT fCOM; /* Flag set if COM program (else EXE)*/
|
||||
Int cReloc; /* No. of relocation table entries */
|
||||
dword *relocTable; /* Ptr. to relocation table */
|
||||
byte *map; /* Memory bitmap ptr */
|
||||
Int cProcs; /* Number of procedures so far */
|
||||
Int offMain; /* The offset of the main() proc */
|
||||
word segMain; /* The segment of the main() proc */
|
||||
boolT bSigs; /* True if signatures loaded */
|
||||
Int cbImage; /* Length of image in bytes */
|
||||
byte *Image; /* Allocated by loader to hold entire
|
||||
* program image */
|
||||
};
|
||||
|
||||
extern PROG prog; /* Loaded program image parameters */
|
||||
extern char condExp[200]; /* Conditional expression buffer */
|
||||
extern char callBuf[100]; /* Function call buffer */
|
||||
extern dword duReg[30]; /* def/use bits for registers */
|
||||
extern dword maskDuReg[30]; /* masks off du bits for regs */
|
||||
|
||||
/* Registers used by icode instructions */
|
||||
static const char *allRegs[21] = {"ax", "cx", "dx", "bx", "sp", "bp",
|
||||
"si", "di", "es", "cs", "ss", "ds",
|
||||
"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
|
||||
"tmp"};
|
||||
|
||||
/* Memory map states */
|
||||
#define BM_UNKNOWN 0 /* Unscanned memory */
|
||||
#define BM_DATA 1 /* Data */
|
||||
#define BM_CODE 2 /* Code */
|
||||
#define BM_IMPURE 3 /* Used as Data and Code*/
|
||||
|
||||
/* Intermediate instructions statistics */
|
||||
struct STATS
|
||||
{
|
||||
Int numBBbef; /* number of basic blocks initially */
|
||||
Int numBBaft; /* number of basic blocks at the end */
|
||||
Int nOrder; /* n-th order */
|
||||
Int numLLIcode; /* number of low-level Icode instructions */
|
||||
Int numHLIcode; /* number of high-level Icode instructions */
|
||||
Int totalLL; /* total number of low-level Icode insts */
|
||||
Int totalHL; /* total number of high-level Icod insts */
|
||||
};
|
||||
|
||||
extern STATS stats; /* Icode statistics */
|
||||
|
||||
|
||||
/**** Global function prototypes ****/
|
||||
|
||||
void FrontEnd(char *filename, CALL_GRAPH * *); /* frontend.c */
|
||||
void *allocMem(Int cb); /* frontend.c */
|
||||
void *reallocVar(void *p, Int newsize); /* frontend.c */
|
||||
void udm(void); /* udm.c */
|
||||
void freeCFG(BB * cfg); /* graph.c */
|
||||
BB * newBB(BB *, Int, Int, byte, Int, Function *); /* graph.c */
|
||||
void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */
|
||||
char *cChar(byte c); /* backend.c */
|
||||
Int scan(dword ip, ICODE * p); /* scanner.c */
|
||||
void parse (CALL_GRAPH * *); /* parser.c */
|
||||
boolT labelSrch(ICODE * pIc, Int n, dword tg, Int *pIdx); /* parser.c */
|
||||
Int strSize (byte *, char); /* parser.c */
|
||||
void disassem(Int pass, Function * pProc); /* disassem.c */
|
||||
void interactDis(Function * initProc, Int initIC); /* disassem.c */
|
||||
boolT JmpInst(llIcode opcode); /* idioms.c */
|
||||
queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */
|
||||
|
||||
void SetupLibCheck(void); /* chklib.c */
|
||||
void CleanupLibCheck(void); /* chklib.c */
|
||||
boolT LibCheck(Function &p); /* chklib.c */
|
||||
|
||||
/* Exported functions from procs.c */
|
||||
boolT insertCallGraph (CALL_GRAPH *, ilFunction, ilFunction);
|
||||
void newRegArg (Function *, ICODE *, ICODE *);
|
||||
boolT newStkArg (ICODE *, COND_EXPR *, llIcode, Function *);
|
||||
void allocStkArgs (ICODE *, Int);
|
||||
void placeStkArg (ICODE *, COND_EXPR *, Int);
|
||||
void adjustActArgType (COND_EXPR *, hlType, Function *);
|
||||
|
||||
/* Exported functions from ast.c */
|
||||
void removeRegFromLong (byte, LOCAL_ID *, COND_EXPR *);
|
||||
std::string walkCondExpr (const COND_EXPR *exp, Function * pProc, Int *);
|
||||
Int hlTypeSize (const COND_EXPR *, Function *);
|
||||
hlType expType (const COND_EXPR *, Function *);
|
||||
void copyDU (ICODE *, const ICODE *, operDu, operDu);
|
||||
boolT insertSubTreeReg (COND_EXPR *, COND_EXPR **, byte, LOCAL_ID *);
|
||||
boolT insertSubTreeLongReg (COND_EXPR *, COND_EXPR **, Int);
|
||||
//COND_EXPR *concatExps (SEQ_COND_EXPR *, COND_EXPR *, condNodeType);
|
||||
|
||||
void initExpStk();
|
||||
void pushExpStk (COND_EXPR *);
|
||||
COND_EXPR *popExpStk();
|
||||
Int numElemExpStk();
|
||||
boolT emptyExpStk();
|
||||
|
||||
/* Exported functions from hlicode.c */
|
||||
boolT removeDefRegi (byte, ICODE *, Int, LOCAL_ID *);
|
||||
std::string writeCall (Function *, STKFRAME *, Function *, Int *);
|
||||
char *write1HlIcode (HLTYPE, Function *, Int *);
|
||||
char *writeJcond (HLTYPE, Function *, Int *);
|
||||
char *writeJcondInv (HLTYPE, Function *, Int *);
|
||||
Int power2 (Int);
|
||||
void inverseCondOp (COND_EXPR **);
|
||||
|
||||
/* Exported funcions from locident.c */
|
||||
boolT checkLongEq (LONG_STKID_TYPE, ICODE *, Int, Int, Function *, COND_EXPR **,COND_EXPR **, Int);
|
||||
boolT checkLongRegEq (LONGID_TYPE, ICODE *, Int, Int, Function *, COND_EXPR **,COND_EXPR **, Int);
|
||||
byte otherLongRegi (byte, Int, LOCAL_ID *);
|
||||
void insertIdx (IDX_ARRAY *, Int);
|
||||
|
||||
|
||||
43
include/disassem.h
Normal file
43
include/disassem.h
Normal file
@ -0,0 +1,43 @@
|
||||
/****************************************************************************
|
||||
* dcc project disassembler header
|
||||
* (C) Mike van Emmerik
|
||||
****************************************************************************/
|
||||
|
||||
/* Definitions for extended keys (first key is zero) */
|
||||
|
||||
#define EXT 0x100 /* "Extended" flag */
|
||||
|
||||
#ifdef __MSDOS__
|
||||
#define KEY_DOWN EXT+'P'
|
||||
#define KEY_LEFT EXT+'K'
|
||||
#define KEY_UP EXT+'H'
|
||||
#define KEY_RIGHT EXT+'M'
|
||||
#define KEY_NPAGE EXT+'Q'
|
||||
#define KEY_PPAGE EXT+'I'
|
||||
#endif
|
||||
|
||||
#ifdef _CONSOLE
|
||||
#define KEY_DOWN 0x50 /* Same as keypad scancodes */
|
||||
#define KEY_LEFT 0x4B
|
||||
#define KEY_UP 0x48
|
||||
#define KEY_RIGHT 0x4D
|
||||
#define KEY_NPAGE 0x51
|
||||
#define KEY_PPAGE 0x49
|
||||
#endif
|
||||
|
||||
#ifdef __UNIX__
|
||||
#define KEY_DOWN EXT+'B'
|
||||
#define KEY_LEFT EXT+'D'
|
||||
#define KEY_UP EXT+'A'
|
||||
#define KEY_RIGHT EXT+'C'
|
||||
#define KEY_NPAGE EXT+'J' /* Enter correct value! */
|
||||
#define KEY_PPAGE EXT+'K' /* Another guess! */
|
||||
#endif
|
||||
|
||||
/* "Attributes" */
|
||||
#define A_NORMAL 'N' /* For Dos/Unix */
|
||||
#define A_REVERSE 'I'
|
||||
#define A_BOLD 'B'
|
||||
|
||||
#define LINES 24
|
||||
#define COLS 80
|
||||
77
include/dosdcc.h
Normal file
77
include/dosdcc.h
Normal file
@ -0,0 +1,77 @@
|
||||
/***************************************************************************
|
||||
* File : dosdcc.h
|
||||
* Purpose : include file for files decompiled by dcc.
|
||||
* Copyright (c) Cristina Cifuentes - QUT - 1992
|
||||
**************************************************************************/
|
||||
|
||||
/* Type definitions for intel 80x86 architecture */
|
||||
typedef unsigned int Word; /* 16 bits */
|
||||
typedef unsigned char Byte; /* 8 bits */
|
||||
typedef union {
|
||||
unsigned long dW;
|
||||
Word wL, wH; /* 2 words */
|
||||
} Dword; /* 32 bits */
|
||||
|
||||
/* Structure to access high and low bits of a Byte or Word variable */
|
||||
typedef struct {
|
||||
/* low byte */
|
||||
Word lowBitWord : 1;
|
||||
Word filler1 : 6;
|
||||
Word highBitByte : 1;
|
||||
/* high byte */
|
||||
Word lowBitByte : 1;
|
||||
Word filler2 : 6;
|
||||
Word highBitWord : 1;
|
||||
} wordBits;
|
||||
|
||||
/* Low and high bits of a Byte or Word variable */
|
||||
#define lowBit(a) ((wordBits)(a).lowBitWord)
|
||||
#define highBitByte(a) ((wordBits)(a).highBitByte)
|
||||
#define lowBitByte(a) ((wordBits)(a).lowBitByte)
|
||||
#define highBit(a) (sizeof(a) == sizeof(Word) ? \
|
||||
((wordBits)(a).highBitWord):\
|
||||
((wordBits)(a).highBitByte))
|
||||
|
||||
/* Word register variables */
|
||||
#define ax regs.x.ax
|
||||
#define bx regs.x.bx
|
||||
#define cx regs.x.cx
|
||||
#define dx regs.x.dx
|
||||
|
||||
#define cs regs.x.cs
|
||||
#define es regs.x.es
|
||||
#define ds regs.x.ds
|
||||
#define ss regs.x.ss
|
||||
|
||||
#define si regs.x.si
|
||||
#define di regs.x.di
|
||||
#define bp regs.x.bp
|
||||
#define sp regs.x.sp
|
||||
|
||||
/* getting rid of all flags */
|
||||
#define carry regs.x.cflags
|
||||
#define overF regs.x.flags /***** check *****/
|
||||
|
||||
/* Byte register variables */
|
||||
#define ah regs.h.ah
|
||||
#define al regs.h.al
|
||||
#define bh regs.h.bh
|
||||
#define bl regs.h.bl
|
||||
#define ch regs.h.ch
|
||||
#define cl regs.h.cl
|
||||
#define dh regs.h.dh
|
||||
#define dl regs.h.dl
|
||||
|
||||
|
||||
/* High and low words of a Dword */
|
||||
#define highWord(w) (*((Word*)&(w) + 1))
|
||||
#define lowWord(w) ((Word)(w))
|
||||
|
||||
#define MAXByte 0xFF
|
||||
#define MAXWord 0xFFFF
|
||||
#define MAXSignByte 0x7F
|
||||
#define MINSignByte 0x81
|
||||
#define MAXSignWord 0x7FFF
|
||||
#define MINSignWord 0x8001
|
||||
|
||||
|
||||
33
include/error.h
Normal file
33
include/error.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*****************************************************************************
|
||||
* Error codes
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
/* These definitions refer to errorMessage in error.c */
|
||||
|
||||
#define USAGE 0
|
||||
#define INVALID_ARG 1
|
||||
#define INVALID_OPCODE 2
|
||||
#define INVALID_386OP 3
|
||||
#define FUNNY_SEGOVR 4
|
||||
#define FUNNY_REP 5
|
||||
#define CANNOT_OPEN 6
|
||||
#define CANNOT_READ 7
|
||||
#define MALLOC_FAILED 8
|
||||
#define NEWEXE_FORMAT 9
|
||||
|
||||
#define NO_BB 10
|
||||
#define INVALID_SYNTHETIC_BB 11
|
||||
#define INVALID_INT_BB 12
|
||||
#define IP_OUT_OF_RANGE 13
|
||||
#define DEF_NOT_FOUND 14
|
||||
#define JX_NOT_DEF 15
|
||||
#define NOT_DEF_USE 16
|
||||
#define REPEAT_FAIL 17
|
||||
#define WHILE_FAIL 18
|
||||
|
||||
|
||||
void fatalError(Int errId, ...);
|
||||
void reportError(Int errId, ...);
|
||||
|
||||
99
include/graph.h
Normal file
99
include/graph.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*****************************************************************************
|
||||
* CFG, BB and interval related definitions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <list>
|
||||
#include <vector>
|
||||
/* Types of basic block nodes */
|
||||
/* Real basic blocks: type defined according to their out-edges */
|
||||
enum eBBKind
|
||||
{
|
||||
ONE_BRANCH = 0, /* unconditional branch */
|
||||
TWO_BRANCH = 1, /* conditional branch */
|
||||
MULTI_BRANCH=2, /* case branch */
|
||||
FALL_NODE=3, /* fall through */
|
||||
RETURN_NODE=4, /* procedure/program return */
|
||||
CALL_NODE=5, /* procedure call */
|
||||
LOOP_NODE=6, /* loop instruction */
|
||||
REP_NODE=7, /* repeat instruction */
|
||||
INTERVAL_NODE=8, /* contains interval list */
|
||||
|
||||
TERMINATE_NODE=11, /* Exit to DOS */
|
||||
NOWHERE_NODE=12 /* No outedges going anywhere */
|
||||
};
|
||||
|
||||
|
||||
/* Depth-first traversal constants */
|
||||
enum eDFS
|
||||
{
|
||||
DFS_DISP=1, /* Display graph pass */
|
||||
DFS_MERGE=2, /* Merge nodes pass */
|
||||
DFS_NUM=3, /* DFS numbering pass */
|
||||
DFS_CASE=4, /* Case pass */
|
||||
DFS_ALPHA=5, /* Alpha code generation*/
|
||||
DFS_JMP=9 /* rmJMP pass - must be largest flag */
|
||||
};
|
||||
|
||||
/* Control flow analysis constants */
|
||||
enum eNodeHeaderType
|
||||
{
|
||||
NO_TYPE=0, /* node is not a loop header*/
|
||||
WHILE_TYPE=1, /* node is a while header */
|
||||
REPEAT_TYPE=2, /* node is a repeat header */
|
||||
ENDLESS_TYPE=3 /* endless loop header */
|
||||
};
|
||||
|
||||
/* Uninitialized values for certain fields */
|
||||
#define NO_NODE MAX /* node has no associated node */
|
||||
#define NO_DOM MAX /* node has no dominator */
|
||||
#define UN_INIT MAX /* uninitialized variable */
|
||||
|
||||
#define THEN 0 /* then edge */
|
||||
#define ELSE 1 /* else edge */
|
||||
|
||||
/* Basic Block (BB) flags */
|
||||
#define INVALID_BB 0x0001 /* BB is not valid any more */
|
||||
#define IS_LATCH_NODE 0x0002 /* BB is the latching node of a loop */
|
||||
|
||||
struct BB;
|
||||
/* Interval structure */
|
||||
typedef std::list<BB *> queue;
|
||||
|
||||
struct interval
|
||||
{
|
||||
byte numInt; /* # of the interval */
|
||||
byte numOutEdges; /* Number of out edges */
|
||||
queue nodes; /* Nodes of the interval*/
|
||||
queue::iterator currNode; /* Current node */
|
||||
interval *next; /* Next interval */
|
||||
BB *firstOfInt();
|
||||
interval()
|
||||
{
|
||||
numInt=numOutEdges=0;
|
||||
currNode=nodes.end();
|
||||
next=0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Derived Sequence structure */
|
||||
struct derSeq_Entry
|
||||
{
|
||||
BB * Gi; /* Graph pointer */
|
||||
interval * Ii; /* Interval list of Gi */
|
||||
derSeq_Entry() : Gi(0),Ii(0)
|
||||
{
|
||||
|
||||
}
|
||||
~derSeq_Entry();
|
||||
public:
|
||||
void findIntervals();
|
||||
};
|
||||
class derSeq : public std::list<derSeq_Entry>
|
||||
{
|
||||
public:
|
||||
void display();
|
||||
};
|
||||
void freeDerivedSeq(derSeq &derivedG); /* reducible.c */
|
||||
|
||||
36
include/hlicode.h
Normal file
36
include/hlicode.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* File: hlIcode.h
|
||||
* Purpose: module definitions for high-level icodes
|
||||
* Date: September 1993
|
||||
*/
|
||||
|
||||
|
||||
/* High level icodes opcodes - def in file icode.h */
|
||||
/*typedef enum {
|
||||
HLI_ASSIGN,
|
||||
INC,
|
||||
DEC,
|
||||
HLI_JCOND,
|
||||
|
||||
} hlIcode; */
|
||||
|
||||
|
||||
typedef struct {
|
||||
hlIcode opcode; /* hlIcode opcode */
|
||||
union { /* different operands */
|
||||
struct {
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
} asgn; /* for HLI_ASSIGN hlIcode */
|
||||
COND_EXPR *exp; /* for HLI_JCOND, INC, DEC */
|
||||
} oper; /* operand */
|
||||
boolT valid; /* has a valid hlIcode */
|
||||
} HLICODE;
|
||||
|
||||
|
||||
//typedef struct {
|
||||
// Int numIcodes; /* No. of hlIcode reocrds written */
|
||||
// Int numAlloc; /* No. of hlIcode records allocated */
|
||||
// HLICODE *hlIcode; /* Array of high-level icodes */
|
||||
//} HLICODEREC;
|
||||
|
||||
362
include/icode.h
Normal file
362
include/icode.h
Normal file
@ -0,0 +1,362 @@
|
||||
/*****************************************************************************
|
||||
* I-code related definitions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "Enums.h"
|
||||
//enum condId;
|
||||
|
||||
/* LOW_LEVEL icode flags */
|
||||
enum eLLFlags
|
||||
{
|
||||
|
||||
B =0x0000001, /* Byte operands (value implicitly used) */
|
||||
I =0x0000002, /* Immed. source */
|
||||
NOT_HLL =0x0000004, /* Not HLL inst. */
|
||||
FLOAT_OP =0x0000008, /* ESC or WAIT */
|
||||
SEG_IMMED =0x0000010, /* Number is relocated segment value */
|
||||
IMPURE =0x0000020, /* Instruction modifies code */
|
||||
WORD_OFF =0x0000040, /* Inst has word offset ie.could be address */
|
||||
TERMINATES =0x0000080, /* Instruction terminates program */
|
||||
CASE =0x0000100, /* Label as case part of switch */
|
||||
SWITCH =0x0000200, /* Treat indirect JMP as switch stmt */
|
||||
TARGET =0x0000400, /* Jump target */
|
||||
SYNTHETIC =0x0000800, /* Synthetic jump instruction */
|
||||
NO_LABEL =0x0001000, /* Immed. jump cannot be linked to a label */
|
||||
NO_CODE =0x0002000, /* Hole in Icode array */
|
||||
SYM_USE =0x0004000, /* Instruction uses a symbol */
|
||||
SYM_DEF =0x0008000, /* Instruction defines a symbol */
|
||||
|
||||
NO_SRC =0x0010000, /* Opcode takes no source */
|
||||
NO_OPS =0x0020000, /* Opcode takes no operands */
|
||||
IM_OPS =0x0040000, /* Opcode takes implicit operands */
|
||||
SRC_B =0x0080000, /* Source operand is byte (dest is word) */
|
||||
#define NO_SRC_B 0xF7FFFF /* Masks off SRC_B */
|
||||
HLL_LABEL =0x0100000, /* Icode has a high level language label */
|
||||
IM_DST =0x0200000, /* Implicit DST for opcode (SIGNEX) */
|
||||
IM_SRC =0x0400000, /* Implicit SRC for opcode (dx:ax) */
|
||||
IM_TMP_DST =0x0800000, /* Implicit rTMP DST for opcode (DIV/IDIV) */
|
||||
|
||||
JMP_ICODE =0x1000000, /* Jmp dest immed.op converted to icode index */
|
||||
JX_LOOP =0x2000000, /* Cond jump is part of loop conditional exp */
|
||||
REST_STK =0x4000000 /* Stack needs to be restored after CALL */
|
||||
};
|
||||
|
||||
/* Parser flags */
|
||||
#define TO_REG 0x000100 /* rm is source */
|
||||
#define S 0x000200 /* sign extend */
|
||||
#define OP386 0x000400 /* 386 op-code */
|
||||
#define NSP 0x000800 /* NOT_HLL if SP is src or dst */
|
||||
#define ICODEMASK 0xFF00FF /* Masks off parser flags */
|
||||
|
||||
/* LOW_LEVEL icode, DU flag bits */
|
||||
#define Cf 1
|
||||
#define Sf 2
|
||||
#define Zf 4
|
||||
#define Df 8
|
||||
|
||||
/* Machine registers */
|
||||
#define rAX 1 /* These are numbered relative to real 8086 */
|
||||
#define rCX 2
|
||||
#define rDX 3
|
||||
#define rBX 4
|
||||
#define rSP 5
|
||||
#define rBP 6
|
||||
#define rSI 7
|
||||
#define rDI 8
|
||||
|
||||
#define rES 9
|
||||
#define rCS 10
|
||||
#define rSS 11
|
||||
#define rDS 12
|
||||
|
||||
#define rAL 13
|
||||
#define rCL 14
|
||||
#define rDL 15
|
||||
#define rBL 16
|
||||
#define rAH 17
|
||||
#define rCH 18
|
||||
#define rDH 19
|
||||
#define rBH 20
|
||||
|
||||
#define rTMP 21 /* temp register for DIV/IDIV/MOD */
|
||||
#define INDEXBASE 22 /* Indexed modes go from INDEXBASE to
|
||||
* INDEXBASE+7 */
|
||||
/* Byte and Word registers */
|
||||
static const char *const byteReg[9] = {"al", "cl", "dl", "bl",
|
||||
"ah", "ch", "dh", "bh", "tmp" };
|
||||
static const char *const wordReg[21] = {"ax", "cx", "dx", "bx", "sp", "bp",
|
||||
"si", "di", "es", "cs", "ss", "ds",
|
||||
"", "", "", "", "", "", "", "", "tmp"};
|
||||
|
||||
#include "state.h" // State depends on INDEXBASE, but later need STATE
|
||||
|
||||
/* Types of icodes */
|
||||
enum icodeType
|
||||
{
|
||||
NOT_SCANNED = 0, /* not even scanned yet */
|
||||
LOW_LEVEL, /* low-level icode */
|
||||
HIGH_LEVEL /* high-level icode */
|
||||
};
|
||||
|
||||
|
||||
/* LOW_LEVEL icode opcodes */
|
||||
enum llIcode
|
||||
{
|
||||
iCBW, /* 0 */
|
||||
iAAA,
|
||||
iAAD,
|
||||
iAAM,
|
||||
iAAS,
|
||||
iADC,
|
||||
iADD,
|
||||
iAND,
|
||||
iBOUND,
|
||||
iCALL,
|
||||
iCALLF, /* 10 */
|
||||
iCLC,
|
||||
iCLD,
|
||||
iCLI,
|
||||
iCMC,
|
||||
iCMP,
|
||||
iCMPS,
|
||||
iREPNE_CMPS,
|
||||
iREPE_CMPS,
|
||||
iDAA,
|
||||
iDAS, /* 20 */
|
||||
iDEC,
|
||||
iDIV,
|
||||
iENTER,
|
||||
iESC,
|
||||
iHLT,
|
||||
iIDIV,
|
||||
iIMUL,
|
||||
iIN,
|
||||
iINC,
|
||||
iINS, /* 30 */
|
||||
iREP_INS,
|
||||
iINT,
|
||||
iIRET,
|
||||
iJB,
|
||||
iJBE,
|
||||
iJAE,
|
||||
iJA,
|
||||
iJE,
|
||||
iJNE,
|
||||
iJL, /* 40 */
|
||||
iJGE,
|
||||
iJLE,
|
||||
iJG,
|
||||
iJS,
|
||||
iJNS,
|
||||
iJO,
|
||||
iJNO,
|
||||
iJP,
|
||||
iJNP,
|
||||
iJCXZ, /* 50 */
|
||||
iJMP,
|
||||
iJMPF,
|
||||
iLAHF,
|
||||
iLDS,
|
||||
iLEA,
|
||||
iLEAVE,
|
||||
iLES,
|
||||
iLOCK,
|
||||
iLODS,
|
||||
iREP_LODS, /* 60 */
|
||||
iLOOP,
|
||||
iLOOPE,
|
||||
iLOOPNE,
|
||||
iMOV, /* 64 */
|
||||
iMOVS,
|
||||
iREP_MOVS,
|
||||
iMUL, /* 67 */
|
||||
iNEG,
|
||||
iNOT,
|
||||
iOR, /* 70 */
|
||||
iOUT,
|
||||
iOUTS,
|
||||
iREP_OUTS,
|
||||
iPOP,
|
||||
iPOPA,
|
||||
iPOPF,
|
||||
iPUSH,
|
||||
iPUSHA,
|
||||
iPUSHF,
|
||||
iRCL, /* 80 */
|
||||
iRCR,
|
||||
iROL,
|
||||
iROR,
|
||||
iRET, /* 84 */
|
||||
iRETF,
|
||||
iSAHF,
|
||||
iSAR,
|
||||
iSHL,
|
||||
iSHR,
|
||||
iSBB, /* 90 */
|
||||
iSCAS,
|
||||
iREPNE_SCAS,
|
||||
iREPE_SCAS,
|
||||
iSIGNEX,
|
||||
iSTC,
|
||||
iSTD,
|
||||
iSTI,
|
||||
iSTOS,
|
||||
iREP_STOS,
|
||||
iSUB, /* 100 */
|
||||
iTEST,
|
||||
iWAIT,
|
||||
iXCHG,
|
||||
iXLAT,
|
||||
iXOR,
|
||||
iINTO,
|
||||
iNOP,
|
||||
iREPNE,
|
||||
iREPE,
|
||||
iMOD /* 110 */
|
||||
};
|
||||
struct BB;
|
||||
struct Function;
|
||||
struct STKFRAME;
|
||||
/* HIGH_LEVEL icodes opcodes */
|
||||
typedef enum {
|
||||
HLI_ASSIGN, /* := */
|
||||
HLI_CALL, /* Call procedure */
|
||||
HLI_JCOND, /* Conditional jump */
|
||||
HLI_RET, /* Return from procedure */
|
||||
/* pseudo high-level icodes */
|
||||
HLI_POP, /* Pop expression */
|
||||
HLI_PUSH, /* Push expression */
|
||||
} hlIcode;
|
||||
|
||||
/* Def/use of flags - low 4 bits represent flags */
|
||||
struct DU
|
||||
{
|
||||
byte d;
|
||||
byte u;
|
||||
};
|
||||
|
||||
/* Def/Use of registers and stack variables */
|
||||
struct DU_ICODE
|
||||
{
|
||||
dword def; /* For Registers: position in dword is reg index*/
|
||||
dword lastDefRegi;/* Bit set if last def of this register in BB */
|
||||
dword use; /* For Registers: position in dword is reg index*/
|
||||
};
|
||||
|
||||
|
||||
/* Definition-use chain for level 1 (within a basic block) */
|
||||
#define MAX_REGS_DEF 2 /* 2 regs def'd for long-reg vars */
|
||||
#define MAX_USES 5
|
||||
|
||||
struct DU1
|
||||
{
|
||||
Int numRegsDef; /* # registers defined by this inst */
|
||||
byte regi[MAX_REGS_DEF]; /* registers defined by this inst */
|
||||
Int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
|
||||
};
|
||||
|
||||
|
||||
/* LOW_LEVEL icode operand record */
|
||||
struct ICODEMEM
|
||||
{
|
||||
byte seg; /* CS, DS, ES, SS */
|
||||
int16 segValue; /* Value of segment seg during analysis */
|
||||
byte segOver; /* CS, DS, ES, SS if segment override */
|
||||
byte regi; /* 0 < regs < INDEXBASE <= index modes */
|
||||
int16 off; /* memory address offset */
|
||||
} ;
|
||||
|
||||
|
||||
struct COND_EXPR;
|
||||
struct HLTYPE
|
||||
{
|
||||
hlIcode opcode; /* hlIcode opcode */
|
||||
union { /* different operands */
|
||||
struct { /* for HLI_ASSIGN */
|
||||
COND_EXPR *lhs;
|
||||
COND_EXPR *rhs;
|
||||
} asgn;
|
||||
COND_EXPR *exp; /* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/
|
||||
struct { /* for HLI_CALL */
|
||||
Function *proc;
|
||||
STKFRAME *args; /* actual arguments */
|
||||
} call;
|
||||
} oper; /* operand */
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
llIcode opcode; /* llIcode instruction */
|
||||
byte numBytes; /* Number of bytes this instr */
|
||||
flags32 flg; /* icode flags */
|
||||
dword label; /* offset in image (20-bit adr) */
|
||||
ICODEMEM dst; /* destination operand */
|
||||
ICODEMEM src; /* source operand */
|
||||
union { /* Source operand if (flg & I) */
|
||||
dword op; /* idx of immed src op */
|
||||
struct { /* Call & # actual arg bytes */
|
||||
Function *proc; /* ^ target proc (for CALL(F))*/
|
||||
Int cb; /* # actual arg bytes */
|
||||
} proc;
|
||||
} immed;
|
||||
DU flagDU; /* def/use of flags */
|
||||
struct { /* Case table if op==JMP && !I */
|
||||
Int numEntries; /* # entries in case table */
|
||||
dword *entries; /* array of offsets */
|
||||
} caseTbl;
|
||||
Int hllLabNum; /* label # for hll codegen */
|
||||
} LLTYPE;
|
||||
|
||||
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
|
||||
struct ICODE
|
||||
{
|
||||
icodeType type; /* Icode type */
|
||||
boolT invalid; /* Has no HIGH_LEVEL equivalent */
|
||||
BB *inBB; /* BB to which this icode belongs */
|
||||
DU_ICODE du; /* Def/use regs/vars */
|
||||
DU1 du1; /* du chain 1 */
|
||||
Int codeIdx; /* Index into cCode.code */
|
||||
struct IC { /* Different types of icodes */
|
||||
LLTYPE ll;
|
||||
HLTYPE hl; /* For HIGH_LEVEL icodes */
|
||||
};
|
||||
IC ic;/* intermediate code */
|
||||
void writeIntComment(char *s);
|
||||
void setRegDU(byte regi, operDu du_in);
|
||||
void invalidate();
|
||||
void newCallHl();
|
||||
void writeDU(Int idx);
|
||||
condId idType(opLoc sd);
|
||||
// HLL setting functions
|
||||
void setAsgn(COND_EXPR *lhs, COND_EXPR *rhs); // set this icode to be an assign
|
||||
void setUnary(hlIcode op, COND_EXPR *exp);
|
||||
void setJCond(COND_EXPR *cexp);
|
||||
int loc_ip; // used by CICodeRec to number ICODEs
|
||||
};
|
||||
|
||||
// This is the icode array object.
|
||||
// The bulk of this could well be done with a class library
|
||||
class CIcodeRec : public std::vector<ICODE>
|
||||
{
|
||||
public:
|
||||
CIcodeRec(); // Constructor
|
||||
~CIcodeRec(); // Destructor
|
||||
|
||||
ICODE * addIcode(ICODE *pIcode);
|
||||
ICODE * GetFirstIcode();
|
||||
// ICODE * GetNextIcode(ICODE * pCurIcode);
|
||||
boolT IsValid(ICODE * pCurIcode);
|
||||
int GetNumIcodes();
|
||||
void SetInBB(int start, int end, BB* pnewBB);
|
||||
void SetImmediateOp(int ip, dword dw);
|
||||
void SetLlFlag(int ip, dword flag);
|
||||
void ClearLlFlag(int ip, dword flag);
|
||||
dword GetLlFlag(int ip);
|
||||
void SetLlInvalid(int ip, boolT fInv);
|
||||
dword GetLlLabel(int ip);
|
||||
llIcode GetLlOpcode(int ip);
|
||||
boolT labelSrch(dword target, Int *pIndex);
|
||||
ICODE * GetIcode(int ip);
|
||||
};
|
||||
130
include/locident.h
Normal file
130
include/locident.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* File: locIdent.h
|
||||
* Purpose: High-level local identifier definitions
|
||||
* Date: October 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
/* Type definition */
|
||||
struct IDX_ARRAY : public std::vector<int>
|
||||
{
|
||||
bool inList(int idx)
|
||||
{
|
||||
return std::find(begin(),end(),idx)!=end();
|
||||
}
|
||||
};
|
||||
/* Type definitions used in the decompiled program */
|
||||
typedef enum {
|
||||
TYPE_UNKNOWN = 0, /* unknown so far */
|
||||
TYPE_BYTE_SIGN, /* signed byte (8 bits) */
|
||||
TYPE_BYTE_UNSIGN, /* unsigned byte */
|
||||
TYPE_WORD_SIGN, /* signed word (16 bits) */
|
||||
TYPE_WORD_UNSIGN, /* unsigned word (16 bits) */
|
||||
TYPE_LONG_SIGN, /* signed long (32 bits) */
|
||||
TYPE_LONG_UNSIGN, /* unsigned long (32 bits) */
|
||||
TYPE_RECORD, /* record structure */
|
||||
TYPE_PTR, /* pointer (32 bit ptr) */
|
||||
TYPE_STR, /* string */
|
||||
TYPE_CONST, /* constant (any type) */
|
||||
TYPE_FLOAT, /* floating point */
|
||||
TYPE_DOUBLE /* double precision float */
|
||||
} hlType;
|
||||
|
||||
static const char *hlTypes[13] = {"", "char", "unsigned char", "int", "unsigned int",
|
||||
"long", "unsigned long", "record", "int *", "char *",
|
||||
"", "float", "double"};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STK_FRAME, /* For stack vars */
|
||||
REG_FRAME, /* For register variables */
|
||||
GLB_FRAME /* For globals */
|
||||
} frameType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16 seg; /* segment value */
|
||||
int16 off; /* offset */
|
||||
byte regi; /* optional indexed register */
|
||||
} BWGLB_TYPE;
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
Int offH; /* high offset from BP */
|
||||
Int offL; /* low offset from BP */
|
||||
} LONG_STKID_TYPE;
|
||||
typedef struct
|
||||
{ /* For TYPE_LONG_(UN)SIGN registers */
|
||||
byte h; /* high register */
|
||||
byte l; /* low register */
|
||||
} LONGID_TYPE;
|
||||
|
||||
|
||||
/* ID, LOCAL_ID */
|
||||
struct ID
|
||||
{
|
||||
hlType type; /* Probable type */
|
||||
boolT illegal;/* Boolean: not a valid field any more */
|
||||
IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */
|
||||
frameType loc; /* Frame location */
|
||||
boolT hasMacro;/* Identifier requires a macro */
|
||||
char macro[10];/* Macro for this identifier */
|
||||
char name[20];/* Identifier's name */
|
||||
union { /* Different types of identifiers */
|
||||
byte regi; /* For TYPE_BYTE(WORD)_(UN)SIGN registers */
|
||||
struct { /* For TYPE_BYTE(WORD)_(UN)SIGN on the stack */
|
||||
byte regOff; /* register offset (if any) */
|
||||
Int off; /* offset from BP */
|
||||
} bwId;
|
||||
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(WORD)_(UN)SIGN globals */
|
||||
LONGID_TYPE longId; /* For TYPE_LONG_(UN)SIGN registers */
|
||||
LONG_STKID_TYPE longStkId;/* For TYPE_LONG_(UN)SIGN on the stack */
|
||||
struct { /* For TYPE_LONG_(UN)SIGN globals */
|
||||
int16 seg; /* segment value */
|
||||
int16 offH; /* offset high */
|
||||
int16 offL; /* offset low */
|
||||
byte regi; /* optional indexed register */
|
||||
} longGlb;
|
||||
struct { /* For TYPE_LONG_(UN)SIGN constants */
|
||||
dword h; /* high word */
|
||||
dword l; /* low word */
|
||||
} longKte;
|
||||
} id;
|
||||
ID()
|
||||
{
|
||||
memset(this,0,sizeof(ID));
|
||||
}
|
||||
ID(hlType t, frameType f)
|
||||
{
|
||||
memset(this,0,sizeof(ID));
|
||||
type=t;
|
||||
loc=f;
|
||||
}
|
||||
};
|
||||
|
||||
struct LOCAL_ID
|
||||
{
|
||||
std::vector<ID> id_arr;
|
||||
public:
|
||||
LOCAL_ID()
|
||||
{}
|
||||
Int newByteWordReg(hlType t, byte regi);
|
||||
Int newByteWordStk(hlType t, Int off, byte regOff);
|
||||
Int newIntIdx(int16 seg, int16 off, byte regi, Int ix, hlType t);
|
||||
Int newLongReg(hlType t, byte regH, byte regL, Int ix);
|
||||
Int newLong(opLoc sd, ICODE *pIcode, hlFirst f, Int ix, operDu du, Int off);
|
||||
void newIdent(hlType t, frameType f);
|
||||
void flagByteWordId(Int off);
|
||||
void propLongId(byte regL, byte regH, const char *name);
|
||||
size_t csym() const {return id_arr.size();}
|
||||
protected:
|
||||
Int newLongIdx(int16 seg, int16 offH, int16 offL, byte regi, Int ix, hlType t);
|
||||
Int newLongGlb(int16 seg, int16 offH, int16 offL, Int ix, hlType t);
|
||||
Int newLongStk(hlType t, Int offH, Int offL);
|
||||
};
|
||||
|
||||
|
||||
34
include/perfhlib.h
Normal file
34
include/perfhlib.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* Perfect hashing function library. Contains functions to generate perfect
|
||||
hashing functions
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define bool unsigned char
|
||||
#define byte unsigned char
|
||||
#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 */
|
||||
|
||||
|
||||
/* 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))
|
||||
#endif
|
||||
38
include/scanner.h
Normal file
38
include/scanner.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* Scanner functions
|
||||
* (C) Cristina Cifuentes, Jeff Ledermann
|
||||
*/
|
||||
|
||||
#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8))
|
||||
|
||||
static void rm(Int i);
|
||||
static void modrm(Int i);
|
||||
static void segrm(Int i);
|
||||
static void data1(Int i);
|
||||
static void data2(Int i);
|
||||
static void regop(Int i);
|
||||
static void segop(Int i);
|
||||
static void strop(Int i);
|
||||
static void escop(Int i);
|
||||
static void axImp(Int i);
|
||||
static void alImp(Int i);
|
||||
static void axSrcIm(Int i);
|
||||
static void memImp(Int i);
|
||||
static void memReg0(Int i);
|
||||
static void memOnly(Int i);
|
||||
static void dispM(Int i);
|
||||
static void dispS(Int i);
|
||||
static void dispN(Int i);
|
||||
static void dispF(Int i);
|
||||
static void prefix(Int i);
|
||||
static void immed(Int i);
|
||||
static void shift(Int i);
|
||||
static void arith(Int i);
|
||||
static void trans(Int i);
|
||||
static void const1(Int i);
|
||||
static void const3(Int i);
|
||||
static void none1(Int i);
|
||||
static void none2(Int i);
|
||||
static void checkInt(Int i);
|
||||
|
||||
/* Extracts reg bits from middle of mod-reg-rm byte */
|
||||
#define REG(x) ((byte)(x & 0x38) >> 3)
|
||||
28
include/state.h
Normal file
28
include/state.h
Normal file
@ -0,0 +1,28 @@
|
||||
/****************************************************************************
|
||||
* dcc project header
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
|
||||
/* STATE TABLE */
|
||||
struct STATE
|
||||
{
|
||||
dword IP; /* Offset into Image */
|
||||
int16 r[INDEXBASE]; /* Value of segs and AX */
|
||||
byte f[INDEXBASE]; /* True if r[.] has a value */
|
||||
struct
|
||||
{ /* For case stmt indexed reg */
|
||||
byte regi; /* Last conditional jump */
|
||||
int16 immed; /* Contents of the previous register */
|
||||
} JCond;
|
||||
void setState(word reg, int16 value);
|
||||
public:
|
||||
void checkStartup();
|
||||
STATE() : IP(0)
|
||||
{
|
||||
JCond.immed=0;
|
||||
memset(r,0,sizeof(int16)*INDEXBASE);
|
||||
memset(f,0,sizeof(byte)*INDEXBASE);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
50
include/symtab.h
Normal file
50
include/symtab.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Symbol table prototypes
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
#pragma once
|
||||
/* * * * * * * * * * * * * * * * * */
|
||||
/* Symbol table structs and protos */
|
||||
/* * * * * * * * * * * * * * * * * */
|
||||
struct Function;
|
||||
struct SYMTABLE
|
||||
{
|
||||
std::string pSymName; /* Ptr to symbolic name or comment */
|
||||
dword symOff; /* Symbol image offset */
|
||||
Function *symProc; /* Procedure pointer */
|
||||
word preHash; /* Hash value before the modulo */
|
||||
word postHash; /* Hash value after the modulo */
|
||||
word nextOvf; /* Next entry this hash bucket, or -1 */
|
||||
word prevOvf; /* Back link in Ovf chain */
|
||||
SYMTABLE() : symOff(0),symProc(0) {}
|
||||
SYMTABLE(dword _sym,Function *_proc) : symOff(_sym),symProc(_proc)
|
||||
{}
|
||||
bool operator == (const SYMTABLE &other) const
|
||||
{
|
||||
// does not yse pSymName, to ease finding by symOff/symProc combo
|
||||
// in map<SYMTABLE,X>
|
||||
return (symOff==other.symOff) && symProc==(other.symProc);
|
||||
}
|
||||
};
|
||||
|
||||
enum tableType /* The table types */
|
||||
{
|
||||
Label=0, /* The label table */
|
||||
Comment, /* The comment table */
|
||||
NUM_TABLE_TYPES /* Number of entries: must be last */
|
||||
};
|
||||
|
||||
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 */
|
||||
|
||||
80
include/types.h
Normal file
80
include/types.h
Normal file
@ -0,0 +1,80 @@
|
||||
/****************************************************************************
|
||||
* dcc project general header
|
||||
* (C) Cristina Cifuentes, Mike van Emmerik
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
/**** Common definitions and macros ****/
|
||||
#ifdef __MSDOS__ /* Intel: 16 bit integer */
|
||||
typedef long Int; /* Int: 0x80000000..0x7FFFFFFF */
|
||||
typedef unsigned long flags32; /* 32 bits */
|
||||
typedef unsigned long dword; /* 32 bits */
|
||||
#define MAX 0x7FFFFFFF
|
||||
#else /* Unix: 32 bit integer */
|
||||
typedef int Int; /* Int: 0x80000000..0x7FFFFFFF */
|
||||
typedef unsigned int flags32; /* 32 bits */
|
||||
typedef unsigned int dword; /* 32 bits */
|
||||
#define MAX 0x7FFFFFFF
|
||||
#endif
|
||||
|
||||
/* Type definitions used in the program */
|
||||
typedef unsigned char byte; /* 8 bits */
|
||||
typedef unsigned short word;/* 16 bits */
|
||||
typedef short int16; /* 16 bits */
|
||||
typedef unsigned char boolT; /* 8 bits */
|
||||
|
||||
#if defined(__MSDOS__) | defined(WIN32)
|
||||
#define unlink _unlink // Compiler is picky about non Ansi names
|
||||
#endif
|
||||
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define SYNTHESIZED_MIN 0x100000 /* Synthesized labs use bits 21..32 */
|
||||
|
||||
/* These are for C library signature detection */
|
||||
#define SYMLEN 16 /* Length of proc symbols, incl null */
|
||||
#define PATLEN 23 /* Length of proc patterns */
|
||||
#define WILD 0xF4 /* The wild byte */
|
||||
|
||||
/****** MACROS *******/
|
||||
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
/* Returns a 16 bit quantity, e.g. C000 is read into an Int as C000 */
|
||||
//#define LH(p) ((int16)((byte *)(p))[0] + ((int16)((byte *)(p))[1] << 8))
|
||||
#define LH(p) ((word)((byte *)(p))[0] + ((word)((byte *)(p))[1] << 8))
|
||||
|
||||
/* Macro reads a LH word from the image regardless of host convention */
|
||||
/* Returns a signed quantity, e.g. C000 is read into an Int as FFFFC000 */
|
||||
#define LHS(p) (((byte *)(p))[0] + (((char *)(p))[1] << 8))
|
||||
|
||||
/* Macro tests bit b for type t in prog.map */
|
||||
#define BITMAP(b, t) (prog.map[(b) >> 2] & ((t) << (((b) & 3) << 1)))
|
||||
|
||||
/* Macro to convert a segment, offset definition into a 20 bit address */
|
||||
#define opAdr(seg,off) ((seg << 4) + off)
|
||||
|
||||
/* duVal FLAGS */
|
||||
struct eDuVal
|
||||
{
|
||||
enum flgs
|
||||
{
|
||||
DEF=1,
|
||||
USE=2,
|
||||
VAL=4
|
||||
};
|
||||
int def :1; /* Variable was first defined than used */
|
||||
int use :1; /* Variable was first used than defined */
|
||||
int val :1; /* Variable has an initial value. 2 cases:
|
||||
* 1. When variable is used first (ie. global)
|
||||
* 2. When a value is moved into the variable
|
||||
* for the first time. */
|
||||
void setFlags(uint16_t x)
|
||||
{
|
||||
def = x&DEF;
|
||||
use = x&USE;
|
||||
val = x&VAL;
|
||||
}
|
||||
bool isUSE_VAL() {return use&&val;} /* Use and Val */
|
||||
};
|
||||
31
regression_tester.rb
Executable file
31
regression_tester.rb
Executable file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env ruby
|
||||
require 'fileutils'
|
||||
print("Regression tester 0.0.1\n")
|
||||
def path_local(from)
|
||||
|
||||
return from #from.gsub('/','//')
|
||||
from.gsub('/','\\\\')
|
||||
end
|
||||
TESTS_DIR="./tests"
|
||||
def perform_test(exepath,filepath,outname)
|
||||
output_path=path_local(TESTS_DIR+"/outputs/"+outname)
|
||||
exepath=path_local(exepath)
|
||||
output_path=path_local(output_path)
|
||||
filepath=path_local(filepath)
|
||||
printf("calling:" + "#{exepath} -a1 -o#{output_path}.a1 #{filepath}\n")
|
||||
result = `#{exepath} -a1 -o#{output_path}.a1 #{filepath}`
|
||||
result = `#{exepath} -a2 -o#{output_path}.a2 #{filepath}`
|
||||
puts result
|
||||
p $?
|
||||
end
|
||||
`rm -rf #{TESTS_DIR}/outputs/*.*`
|
||||
#exit(1)
|
||||
Dir.open(TESTS_DIR+"/inputs").each() {|f|
|
||||
next if f=="." or f==".."
|
||||
perform_test(".//"+ARGV[0],TESTS_DIR+"/inputs/"+f,f)
|
||||
}
|
||||
Dir.open(TESTS_DIR+"/inputs").each() {|f|
|
||||
next if f=="." or f==".."
|
||||
FileUtils.mv(TESTS_DIR+"/inputs/"+f,TESTS_DIR+"/outputs/"+f) if f.end_with?(".b")
|
||||
}
|
||||
"diff -rqbwB"
|
||||
38
src/BasicBlock.cpp
Normal file
38
src/BasicBlock.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "BasicBlock.h"
|
||||
#include "Procedure.h"
|
||||
#include "dcc.h"
|
||||
BB *BB::Create(void *ctx, const std::string &s, Function *parent, BB *insertBefore)
|
||||
{
|
||||
return new BB;
|
||||
}
|
||||
|
||||
BB *BB::Create(Int start, Int ip, byte nodeType, Int numOutEdges, Function *parent)
|
||||
{
|
||||
parent->cfg;
|
||||
BB* pnewBB;
|
||||
|
||||
pnewBB = new BB;
|
||||
pnewBB->nodeType = nodeType; /* Initialise */
|
||||
pnewBB->start = start;
|
||||
pnewBB->length = ip - start + 1;
|
||||
pnewBB->numOutEdges = (byte)numOutEdges;
|
||||
pnewBB->immedDom = NO_DOM;
|
||||
pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail =
|
||||
pnewBB->latchNode= pnewBB->loopFollow = NO_NODE;
|
||||
|
||||
if (numOutEdges)
|
||||
pnewBB->edges.resize(numOutEdges);
|
||||
|
||||
/* Mark the basic block to which the icodes belong to, but only for
|
||||
* real code basic blocks (ie. not interval bbs) */
|
||||
if(parent)
|
||||
{
|
||||
if (start >= 0)
|
||||
parent->Icode.SetInBB(start, ip, pnewBB);
|
||||
parent->heldBBs.push_back(pnewBB);
|
||||
parent->cfg.push_back(pnewBB);
|
||||
}
|
||||
if (start != -1) /* Only for code BB's */
|
||||
stats.numBBbef++;
|
||||
return pnewBB;
|
||||
}
|
||||
27
src/CMakeLists.txt
Normal file
27
src/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
||||
SET(SOURCES ast.cpp backend.cpp bundle.cpp chklib.cpp
|
||||
comwrite.cpp control.cpp dataflow.cpp dcc.cpp
|
||||
disassem.cpp error.cpp fixwild.cpp frontend.cpp
|
||||
graph.cpp hlicode.cpp icode.cpp
|
||||
idioms.cpp locident.cpp parser.cpp
|
||||
perfhlib.cpp procs.cpp proplong.cpp reducible.cpp
|
||||
scanner.cpp symtab.cpp udm.cpp)
|
||||
SET(dc_INCLUDES
|
||||
${PROJECT_SOURCE_DIR}/include/ast.h
|
||||
${PROJECT_SOURCE_DIR}/include/bundle.h
|
||||
${PROJECT_SOURCE_DIR}/include/dcc.h
|
||||
${PROJECT_SOURCE_DIR}/include/disassem.h
|
||||
${PROJECT_SOURCE_DIR}/include/dosdcc.h
|
||||
${PROJECT_SOURCE_DIR}/include/error.h
|
||||
${PROJECT_SOURCE_DIR}/include/graph.h
|
||||
${PROJECT_SOURCE_DIR}/include/hlicode.h
|
||||
${PROJECT_SOURCE_DIR}/include/icode.h
|
||||
${PROJECT_SOURCE_DIR}/include/locident.h
|
||||
${PROJECT_SOURCE_DIR}/include/perfhlib.h
|
||||
${PROJECT_SOURCE_DIR}/include/scanner.h
|
||||
${PROJECT_SOURCE_DIR}/include/state.h
|
||||
${PROJECT_SOURCE_DIR}/include/symtab.h
|
||||
${PROJECT_SOURCE_DIR}/include/types.h
|
||||
)
|
||||
SOURCE_GROUP(Source FILES ${SOURCES})
|
||||
SOURCE_GROUP(Headers FILES ${dc_INCLUDES})
|
||||
ADD_EXECUTABLE(dcc_oo ${SOURCES} ${dc_INCLUDES})
|
||||
995
src/ast.cpp
Normal file
995
src/ast.cpp
Normal file
@ -0,0 +1,995 @@
|
||||
/*
|
||||
* File: ast.c
|
||||
* Purpose: Support module for abstract syntax trees.
|
||||
* Date: September 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <malloc.h> /* For free() */
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include "types.h"
|
||||
#include "dcc.h"
|
||||
using namespace std;
|
||||
/* Index registers **** temp solution */
|
||||
static const char *idxReg[8] = {"bx+si", "bx+di", "bp+si", "bp+di",
|
||||
"si", "di", "bp", "bx" };
|
||||
/* Conditional operator symbols in C. Index by condOp enumeration type */
|
||||
static const char *condOpSym[] = { " <= ", " < ", " == ", " != ", " > ", " >= ",
|
||||
" & ", " | ", " ^ ", " ~ ",
|
||||
" + ", " - ", " * ", " / ",
|
||||
" >> ", " << ", " % ", " && ", " || " };
|
||||
|
||||
#define EXP_SIZE 200 /* Size of the expression buffer */
|
||||
|
||||
/* Local expression stack */
|
||||
//typedef struct _EXP_STK {
|
||||
// COND_EXPR *exp;
|
||||
// struct _EXP_STK *next;
|
||||
//} EXP_STK;
|
||||
typedef std::list<COND_EXPR *> EXP_STK;
|
||||
static EXP_STK expStk; /* local expression stack */
|
||||
|
||||
|
||||
/* Returns the integer i in C hexadecimal format */
|
||||
static char *hexStr (uint16_t i)
|
||||
{
|
||||
static char buf[10];
|
||||
// i &= 0xFFFF;
|
||||
sprintf (buf, "%s%x", (i > 9) ? "0x" : "", i);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
|
||||
/* Sets the du record for registers according to the du flag */
|
||||
void ICODE::setRegDU (byte regi, operDu du_in)
|
||||
{
|
||||
// printf("%s %d %x\n",__FUNCTION__,regi,int(du_in));
|
||||
switch (du_in)
|
||||
{
|
||||
case eDEF:
|
||||
du.def |= duReg[regi];
|
||||
du1.numRegsDef++;
|
||||
printf("%s du.def |= %x\n",__FUNCTION__,duReg[regi]);
|
||||
break;
|
||||
case eUSE:
|
||||
du.use |= duReg[regi];
|
||||
printf("%s du.use |= %x\n",__FUNCTION__,duReg[regi]);
|
||||
break;
|
||||
case USE_DEF:
|
||||
du.def |= duReg[regi];
|
||||
du1.numRegsDef++;
|
||||
printf("%s du.def |= %x\n",__FUNCTION__,duReg[regi]);
|
||||
printf("%s du.use |= %x\n",__FUNCTION__,duReg[regi]);
|
||||
du.use |= duReg[regi];
|
||||
break;
|
||||
case NONE: /* do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Copies the def, use, or def and use fields of duIcode into pIcode */
|
||||
void copyDU (ICODE *pIcode, const ICODE *duIcode, operDu du, operDu duDu)
|
||||
{
|
||||
// printf("%s %d,%d from %d to %d\n",__FUNCTION__,int(du),int(duDu),duIcode->ic.ll.opcode,pIcode->ic.ll.opcode);
|
||||
switch (du) {
|
||||
case eDEF:
|
||||
if (duDu == eDEF)
|
||||
pIcode->du.def=duIcode->du.def;
|
||||
else
|
||||
pIcode->du.def=duIcode->du.use;
|
||||
break;
|
||||
case eUSE:
|
||||
if (duDu == eDEF)
|
||||
pIcode->du.use=duIcode->du.def;
|
||||
else
|
||||
pIcode->du.use =duIcode->du.use;
|
||||
break;
|
||||
case USE_DEF:
|
||||
pIcode->du = duIcode->du;
|
||||
break;
|
||||
case NONE:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
printf("%s end: %x,%x\n",__FUNCTION__,pIcode->du.def,pIcode->du.use);
|
||||
}
|
||||
|
||||
|
||||
/* Creates a newExp conditional expression node of type t and returns it */
|
||||
static COND_EXPR *newCondExp (condNodeType t)
|
||||
{
|
||||
//printf("%s:%d\n",__FUNCTION__,int(t));
|
||||
|
||||
COND_EXPR *newExp;
|
||||
|
||||
newExp = new COND_EXPR;
|
||||
//memset(newExp, 0, sizeof(COND_EXPR));
|
||||
newExp->type = t;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Creates a conditional boolean expression and returns it */
|
||||
COND_EXPR *COND_EXPR::boolOp(COND_EXPR *lhs, COND_EXPR *rhs, condOp op)
|
||||
{
|
||||
//printf("%s:%d\n",__FUNCTION__,int(op));
|
||||
COND_EXPR *newExp;
|
||||
|
||||
newExp = newCondExp (BOOLEAN_OP);
|
||||
newExp->expr.boolExpr.op = op;
|
||||
newExp->expr.boolExpr.lhs = lhs;
|
||||
newExp->expr.boolExpr.rhs = rhs;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns a unary conditional expression node. This procedure should
|
||||
* only be used with the following conditional node types: NEGATION,
|
||||
* ADDRESSOF, DEREFERENCE, POST_INC, POST_DEC, PRE_INC, PRE_DEC */
|
||||
COND_EXPR *COND_EXPR::unary(condNodeType t, COND_EXPR *sub_expr)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
|
||||
newExp = newCondExp (t);
|
||||
newExp->expr.unaryExp = sub_expr;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type GLOB_VAR */
|
||||
COND_EXPR *COND_EXPR::idGlob (int16 segValue, int16 off)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
dword adr;
|
||||
Int i;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = GLOB_VAR;
|
||||
adr = opAdr(segValue, off);
|
||||
for (i = 0; i < symtab.csym; i++)
|
||||
if (symtab.sym[i].label == adr)
|
||||
break;
|
||||
if (i == symtab.csym)
|
||||
printf ("Error, glob var not found in symtab\n");
|
||||
newExp->expr.ident.idNode.globIdx = i;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type REGISTER */
|
||||
COND_EXPR *COND_EXPR::idReg(byte regi, flags32 icodeFlg, LOCAL_ID *locsym)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = REGISTER;
|
||||
if ((icodeFlg & B) || (icodeFlg & SRC_B))
|
||||
{
|
||||
newExp->expr.ident.idNode.regiIdx = locsym->newByteWordReg(TYPE_BYTE_SIGN, regi);
|
||||
newExp->expr.ident.regiType = BYTE_REG;
|
||||
}
|
||||
else /* word */
|
||||
{
|
||||
newExp->expr.ident.idNode.regiIdx = locsym->newByteWordReg( TYPE_WORD_SIGN, regi);
|
||||
newExp->expr.ident.regiType = WORD_REG;
|
||||
}
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type REGISTER */
|
||||
COND_EXPR *COND_EXPR::idRegIdx(Int idx, regType reg_type)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = REGISTER;
|
||||
newExp->expr.ident.regiType = reg_type;
|
||||
newExp->expr.ident.idNode.regiIdx = idx;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
/* Returns an identifier conditional expression node of type LOCAL_VAR */
|
||||
COND_EXPR *COND_EXPR::idLoc(Int off, LOCAL_ID *localId)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
size_t i;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = LOCAL_VAR;
|
||||
for (i = 0; i < localId->csym(); i++)
|
||||
if ((localId->id_arr[i].id.bwId.off == off) &&
|
||||
(localId->id_arr[i].id.bwId.regOff == 0))
|
||||
break;
|
||||
if (i == localId->csym())
|
||||
printf ("Error, cannot find local var\n");
|
||||
newExp->expr.ident.idNode.localIdx = i;
|
||||
sprintf (localId->id_arr[i].name, "loc%ld", i);
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type PARAM */
|
||||
COND_EXPR *COND_EXPR::idParam(Int off, const STKFRAME * argSymtab)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
size_t i;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = PARAM;
|
||||
for (i = 0; i < argSymtab->sym.size(); i++)
|
||||
if (argSymtab->sym[i].off == off)
|
||||
break;
|
||||
if (i == argSymtab->sym.size()) printf ("Error, cannot find argument var\n");
|
||||
newExp->expr.ident.idNode.localIdx = i;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type GLOB_VAR_IDX.
|
||||
* This global variable is indexed by regi. */
|
||||
COND_EXPR *idCondExpIdxGlob (int16 segValue, int16 off, byte regi, const LOCAL_ID *locSym)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
size_t i;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = GLOB_VAR_IDX;
|
||||
for (i = 0; i < locSym->csym(); i++)
|
||||
if ((locSym->id_arr[i].id.bwGlb.seg == segValue) &&
|
||||
(locSym->id_arr[i].id.bwGlb.off == off) &&
|
||||
(locSym->id_arr[i].id.bwGlb.regi == regi))
|
||||
break;
|
||||
if (i == locSym->csym())
|
||||
printf ("Error, indexed-glob var not found in local id table\n");
|
||||
newExp->expr.ident.idNode.idxGlbIdx = i;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type CONSTANT */
|
||||
COND_EXPR *COND_EXPR::idKte(dword kte, byte size)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = CONSTANT;
|
||||
newExp->expr.ident.idNode.kte.kte = kte;
|
||||
newExp->expr.ident.idNode.kte.size = size;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type LONG_VAR,
|
||||
* that points to the given index idx. */
|
||||
COND_EXPR *COND_EXPR::idLongIdx (Int idx)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = LONG_VAR;
|
||||
newExp->expr.ident.idNode.longIdx = idx;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type LONG_VAR */
|
||||
COND_EXPR *COND_EXPR::idLong(LOCAL_ID *localId, opLoc sd, ICODE *pIcode, hlFirst f, Int ix, operDu du, Int off)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
Int idx;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
|
||||
/* Check for long constant and save it as a constant expression */
|
||||
if ((sd == SRC) && ((pIcode->ic.ll.flg & I) == I)) /* constant */
|
||||
{
|
||||
newExp->expr.ident.idType = CONSTANT;
|
||||
if (f == HIGH_FIRST)
|
||||
newExp->expr.ident.idNode.kte.kte = (pIcode->ic.ll.immed.op << 16) +
|
||||
(pIcode+off)->ic.ll.immed.op;
|
||||
else /* LOW_FIRST */
|
||||
newExp->expr.ident.idNode.kte.kte =
|
||||
((pIcode+off)->ic.ll.immed.op << 16)+ pIcode->ic.ll.immed.op;
|
||||
newExp->expr.ident.idNode.kte.size = 4;
|
||||
}
|
||||
/* Save it as a long expression (reg, stack or glob) */
|
||||
else
|
||||
{
|
||||
idx = localId->newLong(sd, pIcode, f, ix, du, off);
|
||||
newExp->expr.ident.idType = LONG_VAR;
|
||||
newExp->expr.ident.idNode.longIdx = idx;
|
||||
}
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type FUNCTION */
|
||||
COND_EXPR *COND_EXPR::idFunc(Function * pproc, STKFRAME * args)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = FUNCTION;
|
||||
newExp->expr.ident.idNode.call.proc = pproc;
|
||||
newExp->expr.ident.idNode.call.args = args;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type OTHER.
|
||||
* Temporary solution, should really be encoded as an indexed type (eg.
|
||||
* arrays). */
|
||||
COND_EXPR *COND_EXPR::idOther(byte seg, byte regi, int16 off)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
newExp->expr.ident.idType = OTHER;
|
||||
newExp->expr.ident.idNode.other.seg = seg;
|
||||
newExp->expr.ident.idNode.other.regi = regi;
|
||||
newExp->expr.ident.idNode.other.off = off;
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node of type TYPE_LONG or
|
||||
* TYPE_WORD_SIGN */
|
||||
COND_EXPR *COND_EXPR::idID (const ID *retVal, LOCAL_ID *locsym, Int ix)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
Int idx;
|
||||
|
||||
newExp = newCondExp (IDENTIFIER);
|
||||
if (retVal->type == TYPE_LONG_SIGN)
|
||||
{
|
||||
idx = locsym->newLongReg (TYPE_LONG_SIGN, retVal->id.longId.h,retVal->id.longId.l, ix);
|
||||
newExp->expr.ident.idType = LONG_VAR;
|
||||
newExp->expr.ident.idNode.longIdx = idx;
|
||||
}
|
||||
else if (retVal->type == TYPE_WORD_SIGN)
|
||||
{
|
||||
newExp->expr.ident.idType = REGISTER;
|
||||
newExp->expr.ident.idNode.regiIdx = locsym->newByteWordReg(TYPE_WORD_SIGN, retVal->id.regi);
|
||||
newExp->expr.ident.regiType = WORD_REG;
|
||||
}
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns an identifier conditional expression node, according to the given
|
||||
* type.
|
||||
* Arguments: i : index into the icode array, used for newLongRegId only.
|
||||
* duIcode: icode instruction that needs the du set.
|
||||
* du: operand is defined or used in current instruction. */
|
||||
COND_EXPR *COND_EXPR::id(ICODE *pIcode, opLoc sd, Function * pProc, Int i,ICODE *duIcode, operDu du)
|
||||
{
|
||||
COND_EXPR *newExp;
|
||||
ICODEMEM * pm;
|
||||
Int idx; /* idx into pIcode->localId table */
|
||||
|
||||
pm = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
|
||||
|
||||
if (((sd == DST) && (pIcode->ic.ll.flg & IM_DST) == IM_DST) ||
|
||||
((sd == SRC) && (pIcode->ic.ll.flg & IM_SRC)) ||
|
||||
(sd == LHS_OP)) /* for MUL lhs */
|
||||
{ /* implicit dx:ax */
|
||||
idx = pProc->localId.newLongReg (TYPE_LONG_SIGN, rDX, rAX, i);
|
||||
newExp = COND_EXPR::idLongIdx (idx);
|
||||
duIcode->setRegDU (rDX, du);
|
||||
duIcode->setRegDU (rAX, du);
|
||||
}
|
||||
|
||||
else if ((sd == DST) && (pIcode->ic.ll.flg & IM_TMP_DST) == IM_TMP_DST)
|
||||
{ /* implicit tmp */
|
||||
newExp = COND_EXPR::idReg (rTMP, 0, &pProc->localId);
|
||||
duIcode->setRegDU(rTMP, (operDu)eUSE);
|
||||
}
|
||||
|
||||
else if ((sd == SRC) && ((pIcode->ic.ll.flg & I) == I)) /* constant */
|
||||
newExp = COND_EXPR::idKte (pIcode->ic.ll.immed.op, 2);
|
||||
|
||||
else if (pm->regi == 0) /* global variable */
|
||||
newExp = COND_EXPR::idGlob(pm->segValue, pm->off);
|
||||
|
||||
else if (pm->regi < INDEXBASE) /* register */
|
||||
{
|
||||
newExp = COND_EXPR::idReg (pm->regi, (sd == SRC) ? pIcode->ic.ll.flg :
|
||||
pIcode->ic.ll.flg & NO_SRC_B, &pProc->localId);
|
||||
duIcode->setRegDU( pm->regi, du);
|
||||
}
|
||||
|
||||
else if (pm->off) /* offset */
|
||||
{
|
||||
if ((pm->seg == rSS) && (pm->regi == INDEXBASE + 6)) /* idx on bp */
|
||||
{
|
||||
if (pm->off >= 0) /* argument */
|
||||
newExp = COND_EXPR::idParam (pm->off, &pProc->args);
|
||||
else /* local variable */
|
||||
newExp = COND_EXPR::idLoc (pm->off, &pProc->localId);
|
||||
}
|
||||
else if ((pm->seg == rDS) && (pm->regi == INDEXBASE + 7)) /* bx */
|
||||
{
|
||||
if (pm->off > 0) /* global variable */
|
||||
newExp = idCondExpIdxGlob (pm->segValue, pm->off, rBX,&pProc->localId);
|
||||
else
|
||||
newExp = COND_EXPR::idOther (pm->seg, pm->regi, pm->off);
|
||||
duIcode->setRegDU( rBX, eUSE);
|
||||
}
|
||||
else /* idx <> bp, bx */
|
||||
newExp = COND_EXPR::idOther (pm->seg, pm->regi, pm->off);
|
||||
/**** check long ops, indexed global var *****/
|
||||
}
|
||||
|
||||
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */
|
||||
{
|
||||
if ((pm->seg == rDS) && (pm->regi > INDEXBASE + 3)) /* dereference */
|
||||
{
|
||||
switch (pm->regi) {
|
||||
case INDEXBASE + 4: newExp = COND_EXPR::idReg(rSI, 0, &pProc->localId);
|
||||
duIcode->setRegDU( rSI, du);
|
||||
break;
|
||||
case INDEXBASE + 5: newExp = COND_EXPR::idReg(rDI, 0, &pProc->localId);
|
||||
duIcode->setRegDU( rDI, du);
|
||||
break;
|
||||
case INDEXBASE + 6: newExp = COND_EXPR::idReg(rBP, 0, &pProc->localId);
|
||||
break;
|
||||
case INDEXBASE + 7: newExp = COND_EXPR::idReg(rBX, 0, &pProc->localId);
|
||||
duIcode->setRegDU( rBX, du);
|
||||
break;
|
||||
default:
|
||||
newExp = 0;
|
||||
assert(false);
|
||||
}
|
||||
newExp = COND_EXPR::unary (DEREFERENCE, newExp);
|
||||
}
|
||||
else
|
||||
newExp = COND_EXPR::idOther (pm->seg, pm->regi, 0);
|
||||
}
|
||||
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Returns the identifier type */
|
||||
condId ICODE::idType(opLoc sd)
|
||||
{
|
||||
ICODEMEM *pm;
|
||||
|
||||
pm = (sd == SRC) ? &ic.ll.src : &ic.ll.dst;
|
||||
|
||||
if ((sd == SRC) && ((ic.ll.flg & I) == I))
|
||||
return (CONSTANT);
|
||||
else if (pm->regi == 0)
|
||||
return (GLOB_VAR);
|
||||
else if (pm->regi < INDEXBASE)
|
||||
return (REGISTER);
|
||||
else if ((pm->seg == rSS) && (pm->regi == INDEXBASE))
|
||||
{
|
||||
if (pm->off >= 0)
|
||||
return (PARAM);
|
||||
else
|
||||
return (LOCAL_VAR);
|
||||
}
|
||||
else
|
||||
return (OTHER);
|
||||
}
|
||||
|
||||
|
||||
/* Size of hl types */
|
||||
Int hlSize[] = {2, 1, 1, 2, 2, 4, 4, 4, 2, 2, 1, 4, 4};
|
||||
|
||||
|
||||
/* Returns the type of the expression */
|
||||
Int hlTypeSize (const COND_EXPR *expr, Function * pproc)
|
||||
{
|
||||
Int first, second;
|
||||
|
||||
if (expr == NULL)
|
||||
return (2); /* for TYPE_UNKNOWN */
|
||||
|
||||
switch (expr->type) {
|
||||
case BOOLEAN_OP:
|
||||
first = hlTypeSize (expr->expr.boolExpr.lhs, pproc);
|
||||
second = hlTypeSize (expr->expr.boolExpr.rhs, pproc);
|
||||
if (first > second)
|
||||
return (first);
|
||||
else
|
||||
return (second);
|
||||
|
||||
case NEGATION: case ADDRESSOF:
|
||||
case POST_INC: case POST_DEC:
|
||||
case PRE_INC: case PRE_DEC:
|
||||
case DEREFERENCE: return (hlTypeSize (expr->expr.unaryExp, pproc));
|
||||
|
||||
case IDENTIFIER:
|
||||
switch (expr->expr.ident.idType)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
return (symtab.sym[expr->expr.ident.idNode.globIdx].size);
|
||||
case REGISTER:
|
||||
if (expr->expr.ident.regiType == BYTE_REG)
|
||||
return (1);
|
||||
else
|
||||
return (2);
|
||||
case LOCAL_VAR:
|
||||
return (hlSize[pproc->localId.id_arr[expr->expr.ident.idNode.localIdx].type]);
|
||||
case PARAM:
|
||||
return (hlSize[pproc->args.sym[expr->expr.ident.idNode.paramIdx].type]);
|
||||
case GLOB_VAR_IDX:
|
||||
return (hlSize[pproc->localId.id_arr[expr->expr.ident.idNode.idxGlbIdx].type]);
|
||||
case CONSTANT:
|
||||
return (expr->expr.ident.idNode.kte.size);
|
||||
case STRING:
|
||||
return (2);
|
||||
case LONG_VAR:
|
||||
return (4);
|
||||
case FUNCTION:
|
||||
return (hlSize[expr->expr.ident.idNode.call.proc->retVal.type]);
|
||||
case OTHER:
|
||||
return (2);
|
||||
} /* eos */
|
||||
break;
|
||||
}
|
||||
return 2; // CC: is this correct?
|
||||
}
|
||||
|
||||
|
||||
/* Returns the type of the expression */
|
||||
hlType expType (const COND_EXPR *expr, Function * pproc)
|
||||
{
|
||||
hlType first, second;
|
||||
|
||||
if (expr == NULL)
|
||||
return (TYPE_UNKNOWN);
|
||||
|
||||
switch (expr->type)
|
||||
{
|
||||
case BOOLEAN_OP:
|
||||
first = expType (expr->expr.boolExpr.lhs, pproc);
|
||||
second = expType (expr->expr.boolExpr.rhs, pproc);
|
||||
if (first != second)
|
||||
{
|
||||
if (hlTypeSize (expr->expr.boolExpr.lhs, pproc) >
|
||||
hlTypeSize (expr->expr.boolExpr.rhs, pproc))
|
||||
return (first);
|
||||
else
|
||||
return (second);
|
||||
}
|
||||
else
|
||||
return (first);
|
||||
|
||||
case POST_INC: case POST_DEC:
|
||||
case PRE_INC: case PRE_DEC:
|
||||
case NEGATION: return (expType (expr->expr.unaryExp, pproc));
|
||||
|
||||
case ADDRESSOF: return (TYPE_PTR); /***????****/
|
||||
case DEREFERENCE: return (TYPE_PTR);
|
||||
case IDENTIFIER:
|
||||
switch (expr->expr.ident.idType)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
return (symtab.sym[expr->expr.ident.idNode.globIdx].type);
|
||||
case REGISTER:
|
||||
if (expr->expr.ident.regiType == BYTE_REG)
|
||||
return (TYPE_BYTE_SIGN);
|
||||
else
|
||||
return (TYPE_WORD_SIGN);
|
||||
case LOCAL_VAR:
|
||||
return (pproc->localId.id_arr[expr->expr.ident.idNode.localIdx].type);
|
||||
case PARAM:
|
||||
return (pproc->args.sym[expr->expr.ident.idNode.paramIdx].type);
|
||||
case GLOB_VAR_IDX:
|
||||
return (pproc->localId.id_arr[expr->expr.ident.idNode.idxGlbIdx].type);
|
||||
case CONSTANT:
|
||||
return (TYPE_CONST);
|
||||
case STRING:
|
||||
return (TYPE_STR);
|
||||
case LONG_VAR:
|
||||
return (pproc->localId.id_arr[expr->expr.ident.idNode.longIdx].type);
|
||||
case FUNCTION:
|
||||
return (expr->expr.ident.idNode.call.proc->retVal.type);
|
||||
case OTHER:
|
||||
return (TYPE_UNKNOWN);
|
||||
} /* eos */
|
||||
case UNKNOWN_OP:
|
||||
assert(false);
|
||||
return (TYPE_UNKNOWN);
|
||||
}
|
||||
return TYPE_UNKNOWN; // CC: Correct?
|
||||
}
|
||||
|
||||
|
||||
/* Removes the register from the tree. If the register was part of a long
|
||||
* register (eg. dx:ax), the node gets transformed into an integer register
|
||||
* node. */
|
||||
void removeRegFromLong (byte regi, LOCAL_ID *locId, COND_EXPR *tree)
|
||||
{
|
||||
IDENTTYPE* ident; /* ptr to an identifier */
|
||||
byte otherRegi; /* high or low part of long register */
|
||||
|
||||
switch (tree->type) {
|
||||
case BOOLEAN_OP:
|
||||
break;
|
||||
case POST_INC: case POST_DEC:
|
||||
case PRE_INC: case PRE_DEC:
|
||||
case NEGATION: case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
break;
|
||||
case IDENTIFIER:
|
||||
ident = &tree->expr.ident;
|
||||
if (ident->idType == LONG_VAR)
|
||||
{
|
||||
otherRegi = otherLongRegi (regi, ident->idNode.longIdx, locId);
|
||||
ident->idType = REGISTER;
|
||||
ident->regiType = WORD_REG;
|
||||
ident->idNode.regiIdx = locId->newByteWordReg(TYPE_WORD_SIGN,otherRegi);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Returns the string located in image, formatted in C format. */
|
||||
static std::string getString (Int offset)
|
||||
{
|
||||
ostringstream o;
|
||||
Int strLen, i;
|
||||
|
||||
strLen = strSize (&prog.Image[offset], '\0');
|
||||
o << '"';
|
||||
for (i = 0; i < strLen; i++)
|
||||
o<<cChar(prog.Image[offset+i]);
|
||||
o << "\"\0";
|
||||
return (o.str());
|
||||
}
|
||||
|
||||
|
||||
/* Walks the conditional expression tree and returns the result on a string */
|
||||
// TODO: use string stream here
|
||||
string walkCondExpr (const COND_EXPR* expr, Function * pProc, Int* numLoc)
|
||||
{
|
||||
int16 off; /* temporal - for OTHER */
|
||||
ID* id; /* Pointer to local identifier table */
|
||||
char* o; /* Operand string pointer */
|
||||
boolT needBracket; /* Determine whether parenthesis is needed */
|
||||
BWGLB_TYPE* bwGlb; /* Ptr to BWGLB_TYPE (global indexed var) */
|
||||
STKSYM * psym; /* Pointer to argument in the stack */
|
||||
std::ostringstream outStr;
|
||||
|
||||
if (expr == NULL)
|
||||
return "";
|
||||
|
||||
needBracket = TRUE;
|
||||
switch (expr->type)
|
||||
{
|
||||
case BOOLEAN_OP:
|
||||
outStr << "(";
|
||||
outStr << walkCondExpr(expr->expr.boolExpr.lhs, pProc, numLoc);
|
||||
outStr << condOpSym[expr->expr.boolExpr.op];
|
||||
outStr << walkCondExpr(expr->expr.boolExpr.rhs, pProc, numLoc);
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case NEGATION:
|
||||
if (expr->expr.unaryExp->type == IDENTIFIER)
|
||||
{
|
||||
needBracket = FALSE;
|
||||
outStr << "!";
|
||||
}
|
||||
else
|
||||
outStr << "! (";
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
if (needBracket == TRUE)
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case ADDRESSOF:
|
||||
if (expr->expr.unaryExp->type == IDENTIFIER)
|
||||
{
|
||||
needBracket = FALSE;
|
||||
outStr << "&";
|
||||
}
|
||||
else
|
||||
outStr << "&(";
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
if (needBracket == TRUE)
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case DEREFERENCE:
|
||||
outStr << "*";
|
||||
if (expr->expr.unaryExp->type == IDENTIFIER)
|
||||
needBracket = FALSE;
|
||||
else
|
||||
outStr << "(";
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
if (needBracket == TRUE)
|
||||
outStr << ")";
|
||||
break;
|
||||
|
||||
case POST_INC:
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "++";
|
||||
break;
|
||||
|
||||
case POST_DEC:
|
||||
outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "--";
|
||||
break;
|
||||
|
||||
case PRE_INC:
|
||||
outStr << "++"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
break;
|
||||
|
||||
case PRE_DEC:
|
||||
outStr << "--"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc);
|
||||
break;
|
||||
|
||||
case IDENTIFIER:
|
||||
std::ostringstream o;
|
||||
switch (expr->expr.ident.idType)
|
||||
{
|
||||
case GLOB_VAR:
|
||||
o << symtab.sym[expr->expr.ident.idNode.globIdx].name;
|
||||
break;
|
||||
case REGISTER:
|
||||
id = &pProc->localId.id_arr[expr->expr.ident.idNode.regiIdx];
|
||||
if (id->name[0] == '\0') /* no name */
|
||||
{
|
||||
sprintf (id->name, "loc%ld", ++(*numLoc));
|
||||
if (id->id.regi < rAL)
|
||||
cCode.appendDecl("%s %s; /* %s */\n",hlTypes[id->type], id->name,wordReg[id->id.regi - rAX]);
|
||||
else
|
||||
cCode.appendDecl("%s %s; /* %s */\n",hlTypes[id->type], id->name,byteReg[id->id.regi - rAL]);
|
||||
}
|
||||
if (id->hasMacro)
|
||||
o << id->macro << "("<<id->name<<")";
|
||||
else
|
||||
o << id->name;
|
||||
break;
|
||||
|
||||
case LOCAL_VAR:
|
||||
o << pProc->localId.id_arr[expr->expr.ident.idNode.localIdx].name;
|
||||
break;
|
||||
|
||||
case PARAM:
|
||||
psym = &pProc->args.sym[expr->expr.ident.idNode.paramIdx];
|
||||
if (psym->hasMacro)
|
||||
o << psym->macro<<"("<<psym->name<< ")";
|
||||
else
|
||||
o << psym->name;
|
||||
break;
|
||||
|
||||
case GLOB_VAR_IDX:
|
||||
bwGlb = &pProc->localId.id_arr[expr->expr.ident.idNode.idxGlbIdx].id.bwGlb;
|
||||
o << (bwGlb->seg << 4) + bwGlb->off << "["<<wordReg[bwGlb->regi - rAX]<<"]";
|
||||
break;
|
||||
|
||||
case CONSTANT:
|
||||
if (expr->expr.ident.idNode.kte.kte < 1000)
|
||||
o << expr->expr.ident.idNode.kte.kte;
|
||||
else
|
||||
o << "0x"<<std::hex << expr->expr.ident.idNode.kte.kte;
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
o << getString (expr->expr.ident.idNode.strIdx);
|
||||
break;
|
||||
|
||||
case LONG_VAR:
|
||||
id = &pProc->localId.id_arr[expr->expr.ident.idNode.longIdx];
|
||||
if (id->name[0] != '\0') /* STK_FRAME & REG w/name*/
|
||||
o << id->name;
|
||||
else if (id->loc == REG_FRAME)
|
||||
{
|
||||
sprintf (id->name, "loc%ld", ++(*numLoc));
|
||||
cCode.appendDecl("%s %s; /* %s:%s */\n",hlTypes[id->type], id->name,wordReg[id->id.longId.h - rAX],wordReg[id->id.longId.l - rAX]);
|
||||
o << id->name;
|
||||
pProc->localId.propLongId (id->id.longId.l,id->id.longId.h, id->name);
|
||||
}
|
||||
else /* GLB_FRAME */
|
||||
{
|
||||
if (id->id.longGlb.regi == 0) /* not indexed */
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"]";
|
||||
else if (id->id.longGlb.regi == rBX)
|
||||
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"][bx]";
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNCTION:
|
||||
o << writeCall (expr->expr.ident.idNode.call.proc,expr->expr.ident.idNode.call.args, pProc, numLoc);
|
||||
break;
|
||||
|
||||
case OTHER:
|
||||
off = expr->expr.ident.idNode.other.off;
|
||||
o << wordReg[expr->expr.ident.idNode.other.seg - rAX]<< "[";
|
||||
o << idxReg[expr->expr.ident.idNode.other.regi - INDEXBASE];
|
||||
if (off < 0)
|
||||
o << "-"<< hexStr (-off);
|
||||
else if (off>0)
|
||||
o << "+"<< hexStr (off);
|
||||
o << "]";
|
||||
} /* eos */
|
||||
outStr << o.str();
|
||||
break;
|
||||
}
|
||||
|
||||
return outStr.str();
|
||||
}
|
||||
|
||||
|
||||
/* Makes a copy of the given expression. Allocates newExp storage for each
|
||||
* node. Returns the copy. */
|
||||
COND_EXPR *COND_EXPR::clone()
|
||||
{
|
||||
COND_EXPR* newExp=0; /* Expression node copy */
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case BOOLEAN_OP:
|
||||
newExp = new COND_EXPR(*this);
|
||||
newExp->expr.boolExpr.lhs = expr.boolExpr.lhs->clone();
|
||||
newExp->expr.boolExpr.rhs = expr.boolExpr.rhs->clone();
|
||||
break;
|
||||
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
newExp = new COND_EXPR(*this);
|
||||
newExp->expr.unaryExp = expr.unaryExp->clone();
|
||||
break;
|
||||
|
||||
case IDENTIFIER:
|
||||
newExp = new COND_EXPR(*this);
|
||||
}
|
||||
return (newExp);
|
||||
}
|
||||
|
||||
|
||||
/* Changes the boolean conditional operator at the root of this expression */
|
||||
void COND_EXPR::changeBoolOp (condOp newOp)
|
||||
{
|
||||
expr.boolExpr.op = newOp;
|
||||
}
|
||||
|
||||
|
||||
/* Inserts the expression exp into the tree at the location specified by the
|
||||
* register regi */
|
||||
boolT insertSubTreeReg (COND_EXPR *expr, COND_EXPR **tree, byte regi,LOCAL_ID *locsym)
|
||||
{
|
||||
byte treeReg;
|
||||
|
||||
if (*tree == NULL)
|
||||
return FALSE;
|
||||
|
||||
switch ((*tree)->type) {
|
||||
case IDENTIFIER:
|
||||
if ((*tree)->expr.ident.idType == REGISTER)
|
||||
{
|
||||
treeReg = locsym->id_arr[(*tree)->expr.ident.idNode.regiIdx].id.regi;
|
||||
if (treeReg == regi) /* word reg */
|
||||
{
|
||||
*tree = expr;
|
||||
return TRUE;
|
||||
}
|
||||
else if ((regi >= rAX) && (regi <= rBX)) /* word/byte reg */
|
||||
{
|
||||
if ((treeReg == (regi + rAL-1)) || (treeReg == (regi + rAH-1)))
|
||||
{
|
||||
*tree = expr;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case BOOLEAN_OP:
|
||||
if (insertSubTreeReg (expr, &(*tree)->expr.boolExpr.lhs, regi, locsym))
|
||||
return TRUE;
|
||||
if (insertSubTreeReg (expr, &(*tree)->expr.boolExpr.rhs, regi, locsym))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
if (insertSubTreeReg(expr, &(*tree)->expr.unaryExp,regi, locsym))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Inserts the expression exp into the tree at the location specified by the
|
||||
* long register index longIdx*/
|
||||
boolT insertSubTreeLongReg (COND_EXPR *exp, COND_EXPR **tree, Int longIdx)
|
||||
{
|
||||
switch ((*tree)->type) {
|
||||
case IDENTIFIER: if ((*tree)->expr.ident.idNode.longIdx == longIdx)
|
||||
{
|
||||
*tree = exp;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case BOOLEAN_OP: if (insertSubTreeLongReg (exp, &(*tree)->expr.boolExpr.lhs, longIdx))
|
||||
return TRUE;
|
||||
if (insertSubTreeLongReg (exp, &(*tree)->expr.boolExpr.rhs, longIdx))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE: if (insertSubTreeLongReg (exp, &(*tree)->expr.unaryExp, longIdx))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Recursively deallocates the abstract syntax tree rooted at *exp */
|
||||
void COND_EXPR::release()
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case BOOLEAN_OP:
|
||||
expr.boolExpr.lhs->release();
|
||||
expr.boolExpr.rhs->release();
|
||||
break;
|
||||
case NEGATION:
|
||||
case ADDRESSOF:
|
||||
case DEREFERENCE:
|
||||
expr.unaryExp->release();
|
||||
break;
|
||||
}
|
||||
delete (this);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Expression stack functions
|
||||
**************************************************************************/
|
||||
|
||||
/* Reinitalizes the expression stack (expStk) to NULL, by freeing all the
|
||||
* space allocated (if any). */
|
||||
void initExpStk()
|
||||
{
|
||||
expStk.clear();
|
||||
}
|
||||
|
||||
|
||||
/* Pushes the given expression onto the local stack (expStk). */
|
||||
void pushExpStk (COND_EXPR *expr)
|
||||
{
|
||||
expStk.push_back(expr);
|
||||
}
|
||||
|
||||
|
||||
/* Returns the element on the top of the local expression stack (expStk),
|
||||
* and deallocates the space allocated by this node.
|
||||
* If there are no elements on the stack, returns NULL. */
|
||||
COND_EXPR *popExpStk()
|
||||
{
|
||||
if(expStk.empty())
|
||||
return 0;
|
||||
COND_EXPR *topExp = expStk.back();
|
||||
expStk.pop_back();
|
||||
return topExp;
|
||||
}
|
||||
|
||||
/* Returns the number of elements available in the expression stack */
|
||||
Int numElemExpStk()
|
||||
{
|
||||
return expStk.size();
|
||||
}
|
||||
|
||||
/* Returns whether the expression stack is empty or not */
|
||||
boolT emptyExpStk()
|
||||
{
|
||||
return expStk.empty();
|
||||
}
|
||||
668
src/backend.cpp
Normal file
668
src/backend.cpp
Normal file
@ -0,0 +1,668 @@
|
||||
/*****************************************************************************
|
||||
* Project: dcc
|
||||
* File: backend.c
|
||||
* Purpose: Back-end module. Generates C code for each procedure.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "dcc.h"
|
||||
#include <fstream>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
bundle cCode; /* Procedure declaration and code */
|
||||
using namespace std;
|
||||
/* Indentation buffer */
|
||||
#define indSize 81 /* size of the indentation buffer. Each indentation
|
||||
* is of 4 spaces => max. 20 indentation levels */
|
||||
static char indentBuf[indSize] =
|
||||
" ";
|
||||
|
||||
|
||||
/* Indentation according to the depth of the statement */
|
||||
static char *indent (Int indLevel)
|
||||
{
|
||||
|
||||
|
||||
return (&indentBuf[indSize-(indLevel*4)-1]);
|
||||
}
|
||||
|
||||
|
||||
static Int getNextLabel()
|
||||
/* Returns a unique index to the next label */
|
||||
{ static Int labelIdx = 1; /* index of the next label */
|
||||
|
||||
return (labelIdx++);
|
||||
}
|
||||
|
||||
|
||||
/* displays statistics on the subroutine */
|
||||
void Function::displayStats ()
|
||||
{
|
||||
printf("\nStatistics - Subroutine %s\n", name);
|
||||
printf ("Number of Icode instructions:\n");
|
||||
printf (" Low-level : %4d\n", stats.numLLIcode);
|
||||
if (! (flg & PROC_ASM))
|
||||
{
|
||||
printf (" High-level: %4d\n", stats.numHLIcode);
|
||||
printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode *
|
||||
100.0) / stats.numLLIcode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**** this proc is not required any more?? ****/
|
||||
#if 0
|
||||
static void fixupLabels (PPROC pProc)
|
||||
/* Checks the graph (pProc->cfg) for any nodes that have labels, and gives
|
||||
* a unique label number for it. This label is placed in the associated
|
||||
* icode for the node (pProc->Icode). The procedure is done in sequential
|
||||
* order of dsfLast numbering. */
|
||||
{ Int i; /* index into the dfsLast array */
|
||||
PBB *dfsLast; /* pointer to the dfsLast array */
|
||||
|
||||
dfsLast = pProc->dfsLast;
|
||||
for (i = 0; i < pProc->numBBs; i++)
|
||||
if (dfsLast[i]->flg/* & BB_HAS_LABEL*/) {
|
||||
pProc->Icode.icode[dfsLast[i]->start].ic.ll.flg |= HLL_LABEL;
|
||||
pProc->Icode.icode[dfsLast[i]->start].ic.ll.hllLabNum = getNextLabel();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Returns the corresponding C string for the given character c. Character
|
||||
* constants such as carriage return and line feed, require 2 C characters. */
|
||||
char *cChar (byte c)
|
||||
{
|
||||
static char res[3];
|
||||
|
||||
switch (c) {
|
||||
case 0x8: /* backspace */
|
||||
sprintf (res, "\\b");
|
||||
break;
|
||||
case 0x9: /* horizontal tab */
|
||||
sprintf (res, "\\t");
|
||||
break;
|
||||
case 0x0A: /* new line */
|
||||
sprintf (res, "\\n");
|
||||
break;
|
||||
case 0x0C: /* form feed */
|
||||
sprintf (res, "\\f");
|
||||
break;
|
||||
case 0x0D: /* carriage return */
|
||||
sprintf (res, "\\r");
|
||||
break;
|
||||
default: /* any other character*/
|
||||
sprintf (res, "%c", c);
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
||||
|
||||
/* Prints the variable's name and initial contents on the file.
|
||||
* Note: to get to the value of the variable:
|
||||
* com file: prog.Image[operand]
|
||||
* exe file: prog.Image[operand+0x100] */
|
||||
static void printGlobVar (SYM * psym)
|
||||
{
|
||||
Int j;
|
||||
dword relocOp = prog.fCOM ? psym->label : psym->label + 0x100;
|
||||
char *strContents; /* initial contents of variable */
|
||||
|
||||
switch (psym->size) {
|
||||
case 1: cCode.appendDecl( "byte\t%s = %ld;\n",
|
||||
psym->name, prog.Image[relocOp]);
|
||||
break;
|
||||
case 2: cCode.appendDecl( "word\t%s = %ld;\n",
|
||||
psym->name, LH(prog.Image+relocOp));
|
||||
break;
|
||||
case 4: if (psym->type == TYPE_PTR) /* pointer */
|
||||
cCode.appendDecl( "word\t*%s = %ld;\n",
|
||||
psym->name, LH(prog.Image+relocOp));
|
||||
else /* char */
|
||||
cCode.appendDecl(
|
||||
"char\t%s[4] = \"%c%c%c%c\";\n",
|
||||
psym->name, prog.Image[relocOp],
|
||||
prog.Image[relocOp+1], prog.Image[relocOp+2],
|
||||
prog.Image[relocOp+3]);
|
||||
break;
|
||||
default:strContents = (char *)allocMem((psym->size*2+1) *sizeof(char));
|
||||
strContents[0] = '\0';
|
||||
for (j=0; j < psym->size; j++)
|
||||
strcat (strContents, cChar(prog.Image[relocOp + j]));
|
||||
cCode.appendDecl( "char\t*%s = \"%s\";\n",
|
||||
psym->name, strContents);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Note: Not called at present.
|
||||
/* Writes the contents of the symbol table, along with any variable
|
||||
* initialization. */
|
||||
static void writeGlobSymTable()
|
||||
{
|
||||
Int idx;
|
||||
char type[10];
|
||||
SYM * pSym;
|
||||
|
||||
if (symtab.csym)
|
||||
{
|
||||
cCode.appendDecl( "/* Global variables */\n");
|
||||
for (idx = 0; idx < symtab.csym; idx++)
|
||||
{
|
||||
pSym = &symtab.sym[idx];
|
||||
if (symtab.sym[idx].duVal.isUSE_VAL()) /* first used */
|
||||
printGlobVar (&(symtab.sym[idx]));
|
||||
else { /* first defined */
|
||||
switch (pSym->size) {
|
||||
case 1: strcpy (type, "byte\t"); break;
|
||||
case 2: strcpy (type, "int\t"); break;
|
||||
case 4: if (pSym->type == TYPE_PTR)
|
||||
strcpy (type, "int\t*");
|
||||
else
|
||||
strcpy (type, "char\t*");
|
||||
break;
|
||||
default: strcpy (type, "char\t*");
|
||||
}
|
||||
cCode.appendDecl( "%s%s;\t/* size = %ld */\n",
|
||||
type, pSym->name, pSym->size);
|
||||
}
|
||||
}
|
||||
cCode.appendDecl( "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Writes the header information and global variables to the output C file
|
||||
* fp. */
|
||||
static void writeHeader (std::ostream &ios, char *fileName)
|
||||
{
|
||||
/* Write header information */
|
||||
newBundle (&cCode);
|
||||
cCode.appendDecl( "/*\n");
|
||||
cCode.appendDecl( " * Input file\t: %s\n", fileName);
|
||||
cCode.appendDecl( " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE");
|
||||
cCode.appendDecl( " */\n\n#include \"dcc.h\"\n\n");
|
||||
|
||||
/* Write global symbol table */
|
||||
/** writeGlobSymTable(); *** need to change them into locident fmt ***/
|
||||
writeBundle (ios, cCode);
|
||||
freeBundle (&cCode);
|
||||
}
|
||||
|
||||
|
||||
/* Writes the registers that are set in the bitvector */
|
||||
static void writeBitVector (dword regi)
|
||||
{ Int j;
|
||||
|
||||
for (j = 0; j < INDEXBASE; j++)
|
||||
{
|
||||
if ((regi & power2(j)) != 0)
|
||||
printf ("%s ", allRegs[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Checks the given icode to determine whether it has a label associated
|
||||
* to it. If so, a goto is emitted to this label; otherwise, a new label
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be backpatched
|
||||
* onto code in cCode.code */
|
||||
static void emitGotoLabel (ICODE * pt, Int indLevel)
|
||||
{
|
||||
if (! (pt->ic.ll.flg & HLL_LABEL)) /* node hasn't got a lab */
|
||||
{
|
||||
/* Generate new label */
|
||||
pt->ic.ll.hllLabNum = getNextLabel();
|
||||
pt->ic.ll.flg |= HLL_LABEL;
|
||||
|
||||
/* Node has been traversed already, so backpatch this label into
|
||||
* the code */
|
||||
addLabelBundle (cCode.code, pt->codeIdx, pt->ic.ll.hllLabNum);
|
||||
}
|
||||
cCode.appendCode( "%sgoto L%ld;\n", indent(indLevel),
|
||||
pt->ic.ll.hllLabNum);
|
||||
stats.numHLIcode++;
|
||||
}
|
||||
|
||||
|
||||
// Note: Not currently called!
|
||||
static void emitFwdGotoLabel (ICODE * pt, Int indLevel)
|
||||
/* Checks the given icode to determine whether it has a label associated
|
||||
* to it. If so, a goto is emitted to this label; otherwise, a new label
|
||||
* is created and a goto is also emitted.
|
||||
* Note: this procedure is to be used when the label is to be forward on
|
||||
* the code; that is, the target code has not been traversed yet. */
|
||||
{
|
||||
if (! (pt->ic.ll.flg & HLL_LABEL)) /* node hasn't got a lab */
|
||||
{
|
||||
/* Generate new label */
|
||||
pt->ic.ll.hllLabNum = getNextLabel();
|
||||
pt->ic.ll.flg |= HLL_LABEL;
|
||||
}
|
||||
cCode.appendCode( "%sgoto l%ld;\n", indent(indLevel),
|
||||
pt->ic.ll.hllLabNum);
|
||||
}
|
||||
|
||||
|
||||
/* Writes the code for the current basic block.
|
||||
* Args: pBB: pointer to the current basic block.
|
||||
* Icode: pointer to the array of icodes for current procedure.
|
||||
* lev: indentation level - used for formatting. */
|
||||
static void writeBB (const BB * const pBB, ICODE * hli, Int lev, Function * pProc, Int *numLoc)
|
||||
{ Int i, last;
|
||||
char *line; /* Pointer to the HIGH-LEVEL line */
|
||||
|
||||
/* Save the index into the code table in case there is a later goto
|
||||
* into this instruction (first instruction of the BB) */
|
||||
hli[pBB->start].codeIdx = nextBundleIdx (&cCode.code);
|
||||
|
||||
/* Generate code for each hlicode that is not a HLI_JCOND */
|
||||
for (i = pBB->start, last = i + pBB->length; i < last; i++)
|
||||
if ((hli[i].type == HIGH_LEVEL) && (hli[i].invalid == FALSE))
|
||||
{
|
||||
line = write1HlIcode (hli[i].ic.hl, pProc, numLoc);
|
||||
if (line[0] != '\0')
|
||||
{
|
||||
cCode.appendCode( "%s%s", indent(lev), line);
|
||||
stats.numHLIcode++;
|
||||
}
|
||||
if (option.verbose)
|
||||
hli[i].writeDU(i);
|
||||
}
|
||||
//if (hli[i].invalid)
|
||||
//printf("Invalid icode: %d!\n", hli[i].invalid);
|
||||
}
|
||||
|
||||
|
||||
/* Recursive procedure that writes the code for the given procedure, pointed
|
||||
* to by pBB.
|
||||
* Parameters: pBB: pointer to the cfg.
|
||||
* Icode: pointer to the Icode array for the cfg graph of the
|
||||
* current procedure.
|
||||
* indLevel: indentation level - used for formatting.
|
||||
* numLoc: last # assigned to local variables */
|
||||
void BB::writeCode (Int indLevel, Function * pProc , Int *numLoc,Int latchNode, Int _ifFollow)
|
||||
{
|
||||
Int follow, /* ifFollow */
|
||||
_loopType, /* Type of loop, if any */
|
||||
_nodeType; /* Type of node */
|
||||
BB * succ, *latch; /* Successor and latching node */
|
||||
ICODE * picode; /* Pointer to HLI_JCOND instruction */
|
||||
char *l; /* Pointer to HLI_JCOND expression */
|
||||
boolT emptyThen, /* THEN clause is empty */
|
||||
repCond; /* Repeat condition for while() */
|
||||
|
||||
/* Check if this basic block should be analysed */
|
||||
if ((_ifFollow != UN_INIT) && (this == pProc->dfsLast[_ifFollow]))
|
||||
return;
|
||||
|
||||
if (traversed == DFS_ALPHA)
|
||||
return;
|
||||
traversed = DFS_ALPHA;
|
||||
|
||||
/* Check for start of loop */
|
||||
repCond = FALSE;
|
||||
latch = NULL;
|
||||
_loopType = loopType;
|
||||
if (_loopType)
|
||||
{
|
||||
latch = pProc->dfsLast[this->latchNode];
|
||||
switch (_loopType)
|
||||
{
|
||||
case WHILE_TYPE:
|
||||
picode = pProc->Icode.GetIcode(start + length - 1);
|
||||
|
||||
/* Check for error in while condition */
|
||||
if (picode->ic.hl.opcode != HLI_JCOND)
|
||||
reportError (WHILE_FAIL);
|
||||
|
||||
/* Check if condition is more than 1 HL instruction */
|
||||
if (numHlIcodes > 1)
|
||||
{
|
||||
/* Write the code for this basic block */
|
||||
writeBB(this, pProc->Icode.GetFirstIcode(), indLevel, pProc, numLoc);
|
||||
repCond = TRUE;
|
||||
}
|
||||
|
||||
/* Condition needs to be inverted if the loop body is along
|
||||
* the THEN path of the header node */
|
||||
if (edges[ELSE].BBptr->dfsLastNum == loopFollow)
|
||||
inverseCondOp (&picode->ic.hl.oper.exp);
|
||||
{
|
||||
std::string e=walkCondExpr (picode->ic.hl.oper.exp, pProc, numLoc);
|
||||
cCode.appendCode( "\n%swhile (%s) {\n", indent(indLevel),e.c_str());
|
||||
}
|
||||
picode->invalidate();
|
||||
break;
|
||||
|
||||
case REPEAT_TYPE:
|
||||
cCode.appendCode( "\n%sdo {\n", indent(indLevel));
|
||||
picode = pProc->Icode.GetIcode(latch->start+latch->length-1);
|
||||
picode->invalidate();
|
||||
break;
|
||||
|
||||
case ENDLESS_TYPE:
|
||||
cCode.appendCode( "\n%sfor (;;) {\n", indent(indLevel));
|
||||
}
|
||||
stats.numHLIcode += 1;
|
||||
indLevel++;
|
||||
}
|
||||
|
||||
/* Write the code for this basic block */
|
||||
if (repCond == FALSE)
|
||||
writeBB (this, pProc->Icode.GetFirstIcode(), indLevel, pProc, numLoc);
|
||||
|
||||
/* Check for end of path */
|
||||
_nodeType = nodeType;
|
||||
if (_nodeType == RETURN_NODE || _nodeType == TERMINATE_NODE ||
|
||||
_nodeType == NOWHERE_NODE || (dfsLastNum == latchNode))
|
||||
return;
|
||||
|
||||
/* Check type of loop/node and process code */
|
||||
if (_loopType) /* there is a loop */
|
||||
{
|
||||
assert(latch);
|
||||
if (this != latch) /* loop is over several bbs */
|
||||
{
|
||||
if (_loopType == WHILE_TYPE)
|
||||
{
|
||||
succ = edges[THEN].BBptr;
|
||||
if (succ->dfsLastNum == loopFollow)
|
||||
succ = edges[ELSE].BBptr;
|
||||
}
|
||||
else
|
||||
succ = edges[0].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc, numLoc, latch->dfsLastNum,_ifFollow);
|
||||
else /* has been traversed so we need a goto */
|
||||
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
|
||||
}
|
||||
|
||||
/* Loop epilogue: generate the loop trailer */
|
||||
indLevel--;
|
||||
if (_loopType == WHILE_TYPE)
|
||||
{
|
||||
/* Check if there is need to repeat other statements involved
|
||||
* in while condition, then, emit the loop trailer */
|
||||
if (repCond)
|
||||
writeBB (this, pProc->Icode.GetFirstIcode(), indLevel+1, pProc, numLoc);
|
||||
cCode.appendCode( "%s} /* end of while */\n",indent(indLevel));
|
||||
}
|
||||
else if (_loopType == ENDLESS_TYPE)
|
||||
cCode.appendCode( "%s} /* end of loop */\n",indent(indLevel));
|
||||
else if (_loopType == REPEAT_TYPE)
|
||||
{
|
||||
if (picode->ic.hl.opcode != HLI_JCOND)
|
||||
reportError (REPEAT_FAIL);
|
||||
{
|
||||
string e=walkCondExpr (picode->ic.hl.oper.exp, pProc, numLoc);
|
||||
cCode.appendCode( "%s} while (%s);\n", indent(indLevel),e.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* Recurse on the loop follow */
|
||||
if (loopFollow != MAX)
|
||||
{
|
||||
succ = pProc->dfsLast[loopFollow];
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc, numLoc, latchNode, _ifFollow);
|
||||
else /* has been traversed so we need a goto */
|
||||
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
|
||||
}
|
||||
}
|
||||
|
||||
else /* no loop, process nodeType of the graph */
|
||||
{
|
||||
if (_nodeType == TWO_BRANCH) /* if-then[-else] */
|
||||
{
|
||||
stats.numHLIcode++;
|
||||
indLevel++;
|
||||
emptyThen = FALSE;
|
||||
|
||||
if (ifFollow != MAX) /* there is a follow */
|
||||
{
|
||||
/* process the THEN part */
|
||||
follow = ifFollow;
|
||||
succ = edges[THEN].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA) /* not visited */
|
||||
{
|
||||
if (succ->dfsLastNum != follow) /* THEN part */
|
||||
{
|
||||
l = writeJcond ( pProc->Icode.GetIcode(start + length -1)->ic.hl,
|
||||
pProc, numLoc);
|
||||
cCode.appendCode( "\n%s%s", indent(indLevel-1), l);
|
||||
succ->writeCode (indLevel, pProc, numLoc, latchNode,follow);
|
||||
}
|
||||
else /* empty THEN part => negate ELSE part */
|
||||
{
|
||||
l = writeJcondInv ( pProc->Icode.GetIcode(start + length -1)->ic.hl,
|
||||
pProc, numLoc);
|
||||
cCode.appendCode( "\n%s%s", indent(indLevel-1), l);
|
||||
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, latchNode, follow);
|
||||
emptyThen = TRUE;
|
||||
}
|
||||
}
|
||||
else /* already visited => emit label */
|
||||
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
|
||||
|
||||
/* process the ELSE part */
|
||||
succ = edges[ELSE].BBptr;
|
||||
if (succ->traversed != DFS_ALPHA) /* not visited */
|
||||
{
|
||||
if (succ->dfsLastNum != follow) /* ELSE part */
|
||||
{
|
||||
cCode.appendCode( "%s}\n%selse {\n",
|
||||
indent(indLevel-1), indent(indLevel - 1));
|
||||
succ->writeCode (indLevel, pProc, numLoc, latchNode, follow);
|
||||
}
|
||||
/* else (empty ELSE part) */
|
||||
}
|
||||
else if (! emptyThen) /* already visited => emit label */
|
||||
{
|
||||
cCode.appendCode( "%s}\n%selse {\n",
|
||||
indent(indLevel-1), indent(indLevel - 1));
|
||||
emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel);
|
||||
}
|
||||
cCode.appendCode( "%s}\n", indent(--indLevel));
|
||||
|
||||
/* Continue with the follow */
|
||||
succ = pProc->dfsLast[follow];
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc, numLoc, latchNode,_ifFollow);
|
||||
}
|
||||
else /* no follow => if..then..else */
|
||||
{
|
||||
l = writeJcond (
|
||||
pProc->Icode.GetIcode(start + length -1)->ic.hl, pProc, numLoc);
|
||||
cCode.appendCode( "%s%s", indent(indLevel-1), l);
|
||||
edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, latchNode, _ifFollow);
|
||||
cCode.appendCode( "%s}\n%selse {\n", indent(indLevel-1), indent(indLevel - 1));
|
||||
edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, latchNode, _ifFollow);
|
||||
cCode.appendCode( "%s}\n", indent(--indLevel));
|
||||
}
|
||||
}
|
||||
|
||||
else /* fall, call, 1w */
|
||||
{
|
||||
succ = edges[0].BBptr; /* fall-through edge */
|
||||
if (succ->traversed != DFS_ALPHA)
|
||||
succ->writeCode (indLevel, pProc,numLoc, latchNode,_ifFollow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Writes the procedure's declaration (including arguments), local variables,
|
||||
* and invokes the procedure that writes the code of the given record *hli */
|
||||
void Function::codeGen (std::ostream &fs)
|
||||
{
|
||||
Int i, numLoc;
|
||||
//STKFRAME * args; /* Procedure arguments */
|
||||
char buf[200], /* Procedure's definition */
|
||||
arg[30]; /* One argument */
|
||||
ID *locid; /* Pointer to one local identifier */
|
||||
BB *pBB; /* Pointer to basic block */
|
||||
|
||||
/* Write procedure/function header */
|
||||
newBundle (&cCode);
|
||||
if (flg & PROC_IS_FUNC) /* Function */
|
||||
cCode.appendDecl( "\n%s %s (", hlTypes[retVal.type],name);
|
||||
else /* Procedure */
|
||||
cCode.appendDecl( "\nvoid %s (", name);
|
||||
|
||||
/* Write arguments */
|
||||
memset (buf, 0, sizeof(buf));
|
||||
for (i = 0; i < args.sym.size(); i++)
|
||||
{
|
||||
if (args.sym[i].invalid == FALSE)
|
||||
{
|
||||
sprintf (arg,"%s %s",hlTypes[args.sym[i].type], args.sym[i].name);
|
||||
strcat (buf, arg);
|
||||
if (i < (args.numArgs - 1))
|
||||
strcat (buf, ", ");
|
||||
}
|
||||
}
|
||||
strcat (buf, ")\n");
|
||||
cCode.appendDecl( "%s", buf);
|
||||
|
||||
/* Write comments */
|
||||
writeProcComments();
|
||||
|
||||
/* Write local variables */
|
||||
if (! (flg & PROC_ASM))
|
||||
{
|
||||
numLoc = 0;
|
||||
for (i = 0; i < localId.csym(); i++)
|
||||
{
|
||||
locid = &localId.id_arr[i];
|
||||
/* Output only non-invalidated entries */
|
||||
if (locid->illegal == FALSE)
|
||||
{
|
||||
if (locid->loc == REG_FRAME)
|
||||
{
|
||||
/* Register variables are assigned to a local variable */
|
||||
if (((flg & SI_REGVAR) && (locid->id.regi == rSI)) ||
|
||||
((flg & DI_REGVAR) && (locid->id.regi == rDI)))
|
||||
{
|
||||
sprintf (locid->name, "loc%ld", ++numLoc);
|
||||
cCode.appendDecl( "int %s;\n", locid->name);
|
||||
}
|
||||
/* Other registers are named when they are first used in
|
||||
* the output C code, and appended to the proc decl. */
|
||||
}
|
||||
|
||||
else if (locid->loc == STK_FRAME)
|
||||
{
|
||||
/* Name local variables and output appropriate type */
|
||||
sprintf (locid->name, "loc%ld", ++numLoc);
|
||||
cCode.appendDecl( "%s %s;\n",hlTypes[locid->type], locid->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Write procedure's code */
|
||||
if (flg & PROC_ASM) /* generate assembler */
|
||||
disassem (3, this);
|
||||
else /* generate C */
|
||||
cfg.front()->writeCode (1, this, &numLoc, MAX, UN_INIT);
|
||||
|
||||
cCode.appendCode( "}\n\n");
|
||||
writeBundle (fs, cCode);
|
||||
freeBundle (&cCode);
|
||||
|
||||
/* Write Live register analysis information */
|
||||
if (option.verbose)
|
||||
for (i = 0; i < numBBs; i++)
|
||||
{
|
||||
pBB = dfsLast[i];
|
||||
if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */
|
||||
printf ("BB %d\n", i);
|
||||
printf (" Start = %d, end = %d\n", pBB->start, pBB->start +
|
||||
pBB->length - 1);
|
||||
printf (" LiveUse = ");
|
||||
writeBitVector (pBB->liveUse);
|
||||
printf ("\n Def = ");
|
||||
writeBitVector (pBB->def);
|
||||
printf ("\n LiveOut = ");
|
||||
writeBitVector (pBB->liveOut);
|
||||
printf ("\n LiveIn = ");
|
||||
writeBitVector (pBB->liveIn);
|
||||
printf ("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Recursive procedure. Displays the procedure's code in depth-first order
|
||||
* of the call graph. */
|
||||
static void backBackEnd (char *filename, CALL_GRAPH * pcallGraph, std::ostream &ios)
|
||||
{
|
||||
Int i;
|
||||
|
||||
// IFace.Yield(); /* This is a good place to yield to other apps */
|
||||
|
||||
/* Check if this procedure has been processed already */
|
||||
if ((pcallGraph->proc->flg & PROC_OUTPUT) ||
|
||||
(pcallGraph->proc->flg & PROC_ISLIB))
|
||||
return;
|
||||
pcallGraph->proc->flg |= PROC_OUTPUT;
|
||||
|
||||
/* Dfs if this procedure has any successors */
|
||||
for (i = 0; i < pcallGraph->outEdges.size(); i++)
|
||||
{
|
||||
backBackEnd (filename, pcallGraph->outEdges[i], ios);
|
||||
}
|
||||
|
||||
/* Generate code for this procedure */
|
||||
stats.numLLIcode = pcallGraph->proc->Icode.GetNumIcodes();
|
||||
stats.numHLIcode = 0;
|
||||
pcallGraph->proc->codeGen (ios);
|
||||
|
||||
/* Generate statistics */
|
||||
if (option.Stats)
|
||||
pcallGraph->proc->displayStats ();
|
||||
if (! (pcallGraph->proc->flg & PROC_ASM))
|
||||
{
|
||||
stats.totalLL += stats.numLLIcode;
|
||||
stats.totalHL += stats.numHLIcode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Invokes the necessary routines to produce code one procedure at a time. */
|
||||
void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
|
||||
{
|
||||
char* outName, *ext;
|
||||
std::ofstream fs; /* Output C file */
|
||||
|
||||
/* Get output file name */
|
||||
outName = strcpy ((char*)allocMem(strlen(fileName)+1), fileName);
|
||||
if ((ext = strrchr (outName, '.')) != NULL)
|
||||
*ext = '\0';
|
||||
strcat (outName, ".b"); /* b for beta */
|
||||
|
||||
/* Open output file */
|
||||
fs.open(outName);
|
||||
if(!fs.is_open())
|
||||
fatalError (CANNOT_OPEN, outName);
|
||||
printf ("dcc: Writing C beta file %s\n", outName);
|
||||
|
||||
/* Header information */
|
||||
writeHeader (fs, fileName);
|
||||
|
||||
/* Initialize total Icode instructions statistics */
|
||||
stats.totalLL = 0;
|
||||
stats.totalHL = 0;
|
||||
|
||||
/* Process each procedure at a time */
|
||||
backBackEnd (fileName, pcallGraph, fs);
|
||||
|
||||
/* Close output file */
|
||||
fs.close();
|
||||
printf ("dcc: Finished writing C beta file\n");
|
||||
}
|
||||
|
||||
|
||||
115
src/bundle.cpp
Normal file
115
src/bundle.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
/*****************************************************************************
|
||||
* File: bundle.c
|
||||
* Module that handles the bundle type (array of pointers to strings).
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include <stdarg.h>
|
||||
#include <iostream>
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define deltaProcLines 20
|
||||
|
||||
|
||||
/* Allocates memory for a new bundle and initializes it to zero. */
|
||||
void newBundle (bundle *)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* Increments the size of the table strTab by deltaProcLines and copies all
|
||||
* the strings to the new table. */
|
||||
static void incTableSize (strTable *strTab)
|
||||
{
|
||||
strTab->resize(strTab->size()+deltaProcLines);
|
||||
}
|
||||
|
||||
|
||||
/* Appends the new line (in printf style) to the string table strTab. */
|
||||
void appendStrTab (strTable *strTab, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[lineSize];
|
||||
va_start (args, format);
|
||||
vsprintf (buf, format, args);
|
||||
strTab->push_back(buf);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
|
||||
/* Returns the next available index into the table */
|
||||
Int nextBundleIdx (strTable *strTab)
|
||||
{
|
||||
return (strTab->size());
|
||||
}
|
||||
|
||||
|
||||
/* Adds the given label to the start of the line strTab[idx]. The first
|
||||
* tab is removed and replaced by this label */
|
||||
void addLabelBundle (strTable &strTab, Int idx, Int label)
|
||||
{
|
||||
char s[lineSize];
|
||||
sprintf (s, "l%ld: %s", label, strTab[idx].c_str()+4);
|
||||
strTab[idx] = s;
|
||||
}
|
||||
|
||||
|
||||
/* Writes the contents of the string table on the file fp. */
|
||||
static void writeStrTab (std::ostream &ios, strTable &strTab)
|
||||
{
|
||||
Int i;
|
||||
|
||||
for (i = 0; i < strTab.size(); i++)
|
||||
ios << strTab[i];
|
||||
}
|
||||
|
||||
|
||||
/* Writes the contents of the bundle (procedure code and declaration) to
|
||||
* a file. */
|
||||
void writeBundle (std::ostream &ios, bundle procCode)
|
||||
{
|
||||
writeStrTab (ios, procCode.decl);
|
||||
if (procCode.decl[procCode.decl.size() - 1][0] != ' ')
|
||||
ios << "\n";
|
||||
writeStrTab (ios, procCode.code);
|
||||
}
|
||||
|
||||
|
||||
/* Frees the storage allocated by the string table. */
|
||||
static void freeStrTab (strTable &strTab)
|
||||
{
|
||||
strTab.clear();
|
||||
}
|
||||
|
||||
|
||||
void freeBundle (bundle *procCode)
|
||||
/* Deallocates the space taken by the bundle procCode */
|
||||
{
|
||||
freeStrTab (procCode->decl);
|
||||
freeStrTab (procCode->code);
|
||||
}
|
||||
|
||||
void bundle::appendCode(const char *format,...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[lineSize]={0};
|
||||
va_start (args, format);
|
||||
vsprintf (buf, format, args);
|
||||
code.push_back(buf);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void bundle::appendDecl(const char *format,...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[lineSize]={0};
|
||||
va_start (args, format);
|
||||
vsprintf (buf, format, args);
|
||||
decl.push_back(buf);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
|
||||
1018
src/chklib.cpp
Normal file
1018
src/chklib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
265
src/comwrite.cpp
Normal file
265
src/comwrite.cpp
Normal file
@ -0,0 +1,265 @@
|
||||
/*****************************************************************************
|
||||
* File: comwrite.c
|
||||
* Purpose: writes comments about C programs and descriptions about dos
|
||||
* interrupts in the string line given.
|
||||
* Project: dcc
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include <string.h>
|
||||
#define intSize 40
|
||||
|
||||
static const char *int21h[] =
|
||||
{"Terminate process",
|
||||
"Character input with echo",
|
||||
"Character output",
|
||||
"Auxiliary input",
|
||||
"Auxiliary output",
|
||||
"Printer output",
|
||||
"Direct console i/o",
|
||||
"Unfiltered char i w/o echo",
|
||||
"Character input without echo",
|
||||
"Display string",
|
||||
"Buffered keyboard input",
|
||||
"Check input status",
|
||||
"Flush input buffer and then input",
|
||||
"Disk reset",
|
||||
"Select disk",
|
||||
"Open file",
|
||||
"Close file",
|
||||
"Find first file",
|
||||
"Find next file",
|
||||
"Delete file",
|
||||
"Sequential read",
|
||||
"Sequential write",
|
||||
"Create file",
|
||||
"Rename file",
|
||||
"Reserved",
|
||||
"Get current disk",
|
||||
"Set DTA address",
|
||||
"Get default drive data",
|
||||
"Get drive data",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Random read",
|
||||
"Random write",
|
||||
"Get file size",
|
||||
"Set relative record number",
|
||||
"Set interrupt vector",
|
||||
"Create new PSP",
|
||||
"Random block read",
|
||||
"Random block write",
|
||||
"Parse filename",
|
||||
"Get date",
|
||||
"Set date",
|
||||
"Get time",
|
||||
"Set time",
|
||||
"Set verify flag",
|
||||
"Get DTA address",
|
||||
"Get MSDOS version number",
|
||||
"Terminate and stay resident",
|
||||
"Reserved",
|
||||
"Get or set break flag",
|
||||
"Reserved",
|
||||
"Get interrupt vector",
|
||||
"Get drive allocation info",
|
||||
"Reserved",
|
||||
"Get or set country info",
|
||||
"Create directory",
|
||||
"Delete directory",
|
||||
"Set current directory",
|
||||
"Create file",
|
||||
"Open file",
|
||||
"Close file",
|
||||
"Read file or device",
|
||||
"Write file or device",
|
||||
"Delete file",
|
||||
"Set file pointer",
|
||||
"Get or set file attributes",
|
||||
"IOCTL (i/o control)",
|
||||
"Duplicate handle",
|
||||
"Redirect handle",
|
||||
"Get current directory",
|
||||
"Alloate memory block",
|
||||
"Release memory block",
|
||||
"Resize memory block",
|
||||
"Execute program (exec)",
|
||||
"Terminate process with return code",
|
||||
"Get return code",
|
||||
"Find first file",
|
||||
"Find next file",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Get verify flag",
|
||||
"Reserved",
|
||||
"Rename file",
|
||||
"Get or set file date & time",
|
||||
"Get or set allocation strategy",
|
||||
"Get extended error information",
|
||||
"Create temporary file",
|
||||
"Create new file",
|
||||
"Lock or unlock file region",
|
||||
"Reserved",
|
||||
"Get machine name",
|
||||
"Device redirection",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Get PSP address",
|
||||
"Get DBCS lead byte table",
|
||||
"Reserved",
|
||||
"Get extended country information",
|
||||
"Get or set code page",
|
||||
"Set handle count",
|
||||
"Commit file",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Extended open file"
|
||||
};
|
||||
|
||||
|
||||
static const char *intOthers[] = {
|
||||
"Exit", /* 0x20 */
|
||||
"", /* other table */
|
||||
"Terminate handler address", /* 0x22 */
|
||||
"Ctrl-C handler address", /* 0x23 */
|
||||
"Critical-error handler address", /* 0x24 */
|
||||
"Absolute disk read", /* 0x25 */
|
||||
"Absolute disk write", /* 0x26 */
|
||||
"Terminate and stay resident", /* 0x27 */
|
||||
"Reserved", /* 0x28 */
|
||||
"Reserved", /* 0x29 */
|
||||
"Reserved", /* 0x2A */
|
||||
"Reserved", /* 0x2B */
|
||||
"Reserved", /* 0x2C */
|
||||
"Reserved", /* 0x2D */
|
||||
"Reserved" /* 0x2E */
|
||||
};
|
||||
|
||||
|
||||
/* Writes the description of the current interrupt. Appends it to the
|
||||
* string s. */
|
||||
void ICODE::writeIntComment (char *s)
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = (char *)allocMem(intSize * sizeof(char));
|
||||
if (ic.ll.immed.op == 0x21)
|
||||
{ sprintf (t, "\t/* %s */\n", int21h[ic.ll.dst.off]);
|
||||
strcat (s, t);
|
||||
}
|
||||
else if (ic.ll.immed.op > 0x1F && ic.ll.immed.op < 0x2F)
|
||||
{
|
||||
sprintf (t, "\t/* %s */\n", intOthers[ic.ll.immed.op - 0x20]);
|
||||
strcat (s, t);
|
||||
}
|
||||
else if (ic.ll.immed.op == 0x2F)
|
||||
switch (ic.ll.dst.off)
|
||||
{
|
||||
case 0x01 : strcat (s, "\t/* Print spooler */\n");
|
||||
break;
|
||||
case 0x02: strcat (s, "\t/* Assign */\n");
|
||||
break;
|
||||
case 0x10: strcat (s, "\t/* Share */\n");
|
||||
break;
|
||||
case 0xB7: strcat (s, "\t/* Append */\n");
|
||||
}
|
||||
else
|
||||
strcat (s, "\n");
|
||||
}
|
||||
|
||||
|
||||
//, &cCode.decl
|
||||
void Function::writeProcComments()
|
||||
{
|
||||
int i;
|
||||
ID *id; /* Pointer to register argument identifier */
|
||||
STKSYM * psym; /* Pointer to register argument symbol */
|
||||
|
||||
/* About the parameters */
|
||||
if (this->cbParam)
|
||||
cCode.appendDecl("/* Takes %d bytes of parameters.\n",this->cbParam);
|
||||
else if (this->flg & REG_ARGS)
|
||||
{
|
||||
cCode.appendDecl("/* Uses register arguments:\n");
|
||||
for (i = 0; i < this->args.numArgs; i++)
|
||||
{
|
||||
psym = &this->args.sym[i];
|
||||
if (psym->regs->expr.ident.idType == REGISTER)
|
||||
{
|
||||
id = &this->localId.id_arr[psym->regs->expr.ident.idNode.regiIdx];
|
||||
if (psym->regs->expr.ident.regiType == WORD_REG)
|
||||
cCode.appendDecl(" * %s = %s.\n", psym->name,
|
||||
wordReg[id->id.regi - rAX]);
|
||||
else /* BYTE_REG */
|
||||
cCode.appendDecl(" * %s = %s.\n", psym->name,
|
||||
byteReg[id->id.regi - rAL]);
|
||||
}
|
||||
else /* long register */
|
||||
{
|
||||
id = &this->localId.id_arr[psym->regs->expr.ident.idNode.longIdx];
|
||||
cCode.appendDecl(" * %s = %s:%s.\n", psym->name,
|
||||
wordReg[id->id.longId.h - rAX],
|
||||
wordReg[id->id.longId.l - rAX]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
cCode.appendDecl("/* Takes no parameters.\n");
|
||||
|
||||
/* Type of procedure */
|
||||
if (this->flg & PROC_RUNTIME)
|
||||
cCode.appendDecl(" * Runtime support routine of the compiler.\n");
|
||||
if (this->flg & PROC_IS_HLL)
|
||||
cCode.appendDecl(" * High-level language prologue code.\n");
|
||||
if (this->flg & PROC_ASM)
|
||||
{
|
||||
cCode.appendDecl(" * Untranslatable routine. Assembler provided.\n");
|
||||
if (this->flg & PROC_IS_FUNC)
|
||||
switch (this->retVal.type) {
|
||||
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
|
||||
cCode.appendDecl(" * Return value in register al.\n");
|
||||
break;
|
||||
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
|
||||
cCode.appendDecl(" * Return value in register ax.\n");
|
||||
break;
|
||||
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
|
||||
cCode.appendDecl(" * Return value in registers dx:ax.\n");
|
||||
break;
|
||||
} /* eos */
|
||||
}
|
||||
|
||||
/* Calling convention */
|
||||
if (this->flg & CALL_PASCAL)
|
||||
cCode.appendDecl(" * Pascal calling convention.\n");
|
||||
else if (this->flg & CALL_C)
|
||||
cCode.appendDecl(" * C calling convention.\n");
|
||||
else if (this->flg & CALL_UNKNOWN)
|
||||
cCode.appendDecl(" * Unknown calling convention.\n");
|
||||
|
||||
/* Other flags */
|
||||
if (this->flg & (PROC_BADINST | PROC_IJMP))
|
||||
cCode.appendDecl(" * Incomplete due to an %s.\n",
|
||||
(this->flg & PROC_BADINST)? "untranslated opcode":
|
||||
"indirect JMP");
|
||||
if (this->flg & PROC_ICALL)
|
||||
cCode.appendDecl(" * Indirect call procedure.\n");
|
||||
if (this->flg & IMPURE)
|
||||
cCode.appendDecl(" * Contains impure code.\n");
|
||||
if (this->flg & NOT_HLL)
|
||||
cCode.appendDecl(" * Contains instructions not normally used by compilers.\n");
|
||||
if (this->flg & FLOAT_OP)
|
||||
cCode.appendDecl(" * Contains coprocessor instructions.\n");
|
||||
|
||||
/* Graph reducibility */
|
||||
if (this->flg & GRAPH_IRRED)
|
||||
cCode.appendDecl(" * Irreducible control flow graph.\n");
|
||||
cCode.appendDecl(" */\n{\n");
|
||||
}
|
||||
|
||||
692
src/control.cpp
Normal file
692
src/control.cpp
Normal file
@ -0,0 +1,692 @@
|
||||
/*********************************************************************
|
||||
* Description : Performs control flow analysis on the CFG
|
||||
* (C) Cristina Cifuentes
|
||||
********************************************************************/
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
#include "dcc.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if __BORLAND__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
//typedef struct list {
|
||||
// Int nodeIdx;
|
||||
// struct list *next;
|
||||
//} nodeList;
|
||||
typedef std::list<Int> nodeList; /* dfsLast index to the node */
|
||||
|
||||
#define ancestor(a,b) ((a->dfsLastNum < b->dfsLastNum) && (a->dfsFirstNum < b->dfsFirstNum))
|
||||
/* there is a path on the DFST from a to b if the a was first visited in a
|
||||
* dfs, and a was later visited than b when doing the last visit of each
|
||||
* node. */
|
||||
|
||||
|
||||
/* Checks if the edge (p,s) is a back edge. If node s was visited first
|
||||
* during the dfs traversal (ie. s has a smaller dfsFirst number) or s == p,
|
||||
* then it is a backedge.
|
||||
* Also incrementes the number of backedges entries to the header node. */
|
||||
static boolT isBackEdge (BB * p,BB * s)
|
||||
{
|
||||
if (p->dfsFirstNum >= s->dfsFirstNum)
|
||||
{
|
||||
s->numBackEdges++;
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static Int commonDom (Int currImmDom, Int predImmDom, Function * pProc)
|
||||
/* Finds the common dominator of the current immediate dominator
|
||||
* currImmDom and its predecessor's immediate dominator predImmDom */
|
||||
{
|
||||
if (currImmDom == NO_DOM)
|
||||
return (predImmDom);
|
||||
if (predImmDom == NO_DOM) /* predecessor is the root */
|
||||
return (currImmDom);
|
||||
|
||||
while ((currImmDom != NO_DOM) && (predImmDom != NO_DOM) &&
|
||||
(currImmDom != predImmDom))
|
||||
{
|
||||
if (currImmDom < predImmDom)
|
||||
predImmDom = pProc->dfsLast[predImmDom]->immedDom;
|
||||
else
|
||||
currImmDom = pProc->dfsLast[currImmDom]->immedDom;
|
||||
}
|
||||
return (currImmDom);
|
||||
}
|
||||
|
||||
|
||||
/* Finds the immediate dominator of each node in the graph pProc->cfg.
|
||||
* Adapted version of the dominators algorithm by Hecht and Ullman; finds
|
||||
* immediate dominators only.
|
||||
* Note: graph should be reducible */
|
||||
void Function::findImmedDom ()
|
||||
{
|
||||
BB * currNode;
|
||||
Int currIdx, j, predIdx;
|
||||
|
||||
for (currIdx = 0; currIdx < numBBs; currIdx++)
|
||||
{
|
||||
currNode = dfsLast[currIdx];
|
||||
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
|
||||
continue;
|
||||
|
||||
for (j = 0; j < currNode->inEdges.size(); j++)
|
||||
{
|
||||
BB* inedge=currNode->inEdges[j];
|
||||
predIdx = inedge->dfsLastNum;
|
||||
if (predIdx < currIdx)
|
||||
currNode->immedDom = commonDom (currNode->immedDom,
|
||||
predIdx, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Inserts the node n to the list l. */
|
||||
static void insertList (nodeList &l, Int n)
|
||||
{
|
||||
l.push_back(n);
|
||||
}
|
||||
|
||||
|
||||
/* Returns whether or not the node n (dfsLast numbering of a basic block)
|
||||
* is on the list l. */
|
||||
static boolT inList (nodeList &l, Int n)
|
||||
{
|
||||
return std::find(l.begin(),l.end(),n)!=l.end();
|
||||
}
|
||||
|
||||
|
||||
/* Frees space allocated by the list l. */
|
||||
static void freeList (nodeList &l)
|
||||
{
|
||||
l.clear();
|
||||
}
|
||||
|
||||
|
||||
/* Returns whether the node n belongs to the queue list q. */
|
||||
static boolT inInt(BB * n, queue &q)
|
||||
{
|
||||
return std::find(q.begin(),q.end(),n)!=q.end();
|
||||
}
|
||||
|
||||
|
||||
/* Finds the follow of the endless loop headed at node head (if any).
|
||||
* The follow node is the closest node to the loop. */
|
||||
static void findEndlessFollow (Function * pProc, nodeList &loopNodes, BB * head)
|
||||
{
|
||||
Int j, succ;
|
||||
|
||||
head->loopFollow = MAX;
|
||||
nodeList::iterator p = loopNodes.begin();
|
||||
for( ;p != loopNodes.end();++p)
|
||||
{
|
||||
for (j = 0; j < pProc->dfsLast[*p]->numOutEdges; j++)
|
||||
{
|
||||
succ = pProc->dfsLast[*p]->edges[j].BBptr->dfsLastNum;
|
||||
if ((! inList(loopNodes, succ)) && (succ < head->loopFollow))
|
||||
head->loopFollow = succ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//static void findNodesInLoop(BB * latchNode,BB * head,PPROC pProc,queue *intNodes)
|
||||
/* Flags nodes that belong to the loop determined by (latchNode, head) and
|
||||
* determines the type of loop. */
|
||||
static void findNodesInLoop(BB * latchNode,BB * head,Function * pProc,queue &intNodes)
|
||||
{
|
||||
Int i, headDfsNum, intNodeType;
|
||||
nodeList loopNodes;
|
||||
Int immedDom, /* dfsLast index to immediate dominator */
|
||||
thenDfs, elseDfs; /* dsfLast index for THEN and ELSE nodes */
|
||||
BB * pbb;
|
||||
|
||||
/* Flag nodes in loop headed by head (except header node) */
|
||||
headDfsNum = head->dfsLastNum;
|
||||
head->loopHead = headDfsNum;
|
||||
insertList (loopNodes, headDfsNum);
|
||||
for (i = headDfsNum + 1; i < latchNode->dfsLastNum; i++)
|
||||
{
|
||||
if (pProc->dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */
|
||||
continue;
|
||||
|
||||
immedDom = pProc->dfsLast[i]->immedDom;
|
||||
if (inList (loopNodes, immedDom) && inInt(pProc->dfsLast[i], intNodes))
|
||||
{
|
||||
insertList (loopNodes, i);
|
||||
if (pProc->dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/
|
||||
pProc->dfsLast[i]->loopHead = headDfsNum;
|
||||
}
|
||||
}
|
||||
latchNode->loopHead = headDfsNum;
|
||||
if (latchNode != head)
|
||||
insertList (loopNodes, latchNode->dfsLastNum);
|
||||
|
||||
/* Determine type of loop and follow node */
|
||||
intNodeType = head->nodeType;
|
||||
if (latchNode->nodeType == TWO_BRANCH)
|
||||
if ((intNodeType == TWO_BRANCH) || (latchNode == head))
|
||||
if ((latchNode == head) ||
|
||||
(inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum) &&
|
||||
inList (loopNodes, head->edges[ELSE].BBptr->dfsLastNum)))
|
||||
{
|
||||
head->loopType = REPEAT_TYPE;
|
||||
if (latchNode->edges[0].BBptr == head)
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
|
||||
pProc->Icode.SetLlFlag(latchNode->start + latchNode->length - 1,JX_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->loopType = WHILE_TYPE;
|
||||
if (inList (loopNodes, head->edges[THEN].BBptr->dfsLastNum))
|
||||
head->loopFollow = head->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = head->edges[THEN].BBptr->dfsLastNum;
|
||||
pProc->Icode.SetLlFlag(head->start + head->length - 1, JX_LOOP);
|
||||
}
|
||||
else /* head = anything besides 2-way, latch = 2-way */
|
||||
{
|
||||
head->loopType = REPEAT_TYPE;
|
||||
if (latchNode->edges[THEN].BBptr == head)
|
||||
head->loopFollow = latchNode->edges[ELSE].BBptr->dfsLastNum;
|
||||
else
|
||||
head->loopFollow = latchNode->edges[THEN].BBptr->dfsLastNum;
|
||||
pProc->Icode.SetLlFlag(latchNode->start + latchNode->length - 1,
|
||||
JX_LOOP);
|
||||
}
|
||||
else /* latch = 1-way */
|
||||
if (latchNode->nodeType == LOOP_NODE)
|
||||
{
|
||||
head->loopType = REPEAT_TYPE;
|
||||
head->loopFollow = latchNode->edges[0].BBptr->dfsLastNum;
|
||||
}
|
||||
else if (intNodeType == TWO_BRANCH)
|
||||
{
|
||||
head->loopType = WHILE_TYPE;
|
||||
pbb = latchNode;
|
||||
thenDfs = head->edges[THEN].BBptr->dfsLastNum;
|
||||
elseDfs = head->edges[ELSE].BBptr->dfsLastNum;
|
||||
while (1)
|
||||
{
|
||||
if (pbb->dfsLastNum == thenDfs)
|
||||
{
|
||||
head->loopFollow = elseDfs;
|
||||
break;
|
||||
}
|
||||
else if (pbb->dfsLastNum == elseDfs)
|
||||
{
|
||||
head->loopFollow = thenDfs;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if couldn't find it, then it is a strangely formed
|
||||
* loop, so it is safer to consider it an endless loop */
|
||||
if (pbb->dfsLastNum <= head->dfsLastNum)
|
||||
{
|
||||
head->loopType = ENDLESS_TYPE;
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
break;
|
||||
}
|
||||
pbb = pProc->dfsLast[pbb->immedDom];
|
||||
}
|
||||
if (pbb->dfsLastNum > head->dfsLastNum)
|
||||
pProc->dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/
|
||||
pProc->Icode.SetLlFlag(head->start + head->length - 1, JX_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
head->loopType = ENDLESS_TYPE;
|
||||
findEndlessFollow (pProc, loopNodes, head);
|
||||
}
|
||||
|
||||
freeList(loopNodes);
|
||||
}
|
||||
|
||||
|
||||
//static void findNodesInInt (queue **intNodes, Int level, interval *Ii)
|
||||
/* Recursive procedure to find nodes that belong to the interval (ie. nodes
|
||||
* from G1). */
|
||||
static void findNodesInInt (queue &intNodes, Int level, interval *Ii)
|
||||
{
|
||||
if (level == 1)
|
||||
{
|
||||
std::for_each(Ii->nodes.begin(),Ii->nodes.end(),[&intNodes](BB *en)->void {
|
||||
appendQueue(intNodes,en);
|
||||
});
|
||||
}
|
||||
else
|
||||
std::for_each(Ii->nodes.begin(),Ii->nodes.end(),[&intNodes,level](BB *en)->void {
|
||||
findNodesInInt(intNodes,level-1,en->correspInt);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* Algorithm for structuring loops */
|
||||
static void structLoops(Function * pProc, derSeq *derivedG)
|
||||
{
|
||||
interval *Ii;
|
||||
BB * intHead, /* interval header node */
|
||||
* pred, /* predecessor node */
|
||||
* latchNode;/* latching node (in case of loops) */
|
||||
Int i, /* counter */
|
||||
level = 0; /* derived sequence level */
|
||||
interval *initInt; /* initial interval */
|
||||
queue intNodes; /* list of interval nodes */
|
||||
|
||||
/* Structure loops */
|
||||
/* for all derived sequences Gi */
|
||||
for(derSeq::iterator iter=derivedG->begin(); iter!=derivedG->end(); ++iter)
|
||||
{
|
||||
level++;
|
||||
Ii = iter->Ii;
|
||||
while (Ii) /* for all intervals Ii of Gi */
|
||||
{
|
||||
latchNode = NULL;
|
||||
intNodes.clear();
|
||||
|
||||
/* Find interval head (original BB node in G1) and create
|
||||
* list of nodes of interval Ii. */
|
||||
initInt = Ii;
|
||||
for (i = 1; i < level; i++)
|
||||
initInt = (*initInt->nodes.begin())->correspInt;
|
||||
intHead = *initInt->nodes.begin();
|
||||
|
||||
/* Find nodes that belong to the interval (nodes from G1) */
|
||||
findNodesInInt (intNodes, level, Ii);
|
||||
|
||||
/* Find greatest enclosing back edge (if any) */
|
||||
assert(intHead->numInEdges==intHead->inEdges.size());
|
||||
for (i = 0; i < intHead->inEdges.size(); i++)
|
||||
{
|
||||
pred = intHead->inEdges[i];
|
||||
if (inInt(pred, intNodes) && isBackEdge(pred, intHead))
|
||||
if (! latchNode)
|
||||
latchNode = pred;
|
||||
else
|
||||
{
|
||||
if (pred->dfsLastNum > latchNode->dfsLastNum)
|
||||
latchNode = pred;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find nodes in the loop and the type of loop */
|
||||
if (latchNode)
|
||||
{
|
||||
/* Check latching node is at the same nesting level of case
|
||||
* statements (if any) and that the node doesn't belong to
|
||||
* another loop. */
|
||||
if ((latchNode->caseHead == intHead->caseHead) &&
|
||||
(latchNode->loopHead == NO_NODE))
|
||||
{
|
||||
intHead->latchNode = latchNode->dfsLastNum;
|
||||
findNodesInLoop(latchNode, intHead, pProc, intNodes);
|
||||
latchNode->flg |= IS_LATCH_NODE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Next interval */
|
||||
Ii = Ii->next;
|
||||
}
|
||||
|
||||
/* Next derived sequence */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static boolT successor (Int s, Int h, Function * pProc)
|
||||
/* Returns whether the BB indexed by s is a successor of the BB indexed by
|
||||
* h. Note that h is a case node. */
|
||||
{ Int i;
|
||||
BB * header;
|
||||
|
||||
header = pProc->dfsLast[h];
|
||||
for (i = 0; i < header->numOutEdges; i++)
|
||||
if (header->edges[i].BBptr->dfsLastNum == s)
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
static void tagNodesInCase (BB * pBB, nodeList &l, Int head, Int tail)
|
||||
/* Recursive procedure to tag nodes that belong to the case described by
|
||||
* the list l, head and tail (dfsLast index to first and exit node of the
|
||||
* case). */
|
||||
{ Int current, /* index to current node */
|
||||
i;
|
||||
|
||||
pBB->traversed = DFS_CASE;
|
||||
current = pBB->dfsLastNum;
|
||||
if ((current != tail) && (pBB->nodeType != MULTI_BRANCH) && (inList (l, pBB->immedDom)))
|
||||
{
|
||||
insertList (l, current);
|
||||
pBB->caseHead = head;
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
if (pBB->edges[i].BBptr->traversed != DFS_CASE)
|
||||
tagNodesInCase (pBB->edges[i].BBptr, l, head, tail);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void structCases(Function * pProc)
|
||||
/* Structures case statements. This procedure is invoked only when pProc
|
||||
* has a case node. */
|
||||
{ Int i, j;
|
||||
BB * caseHeader; /* case header node */
|
||||
Int exitNode = NO_NODE; /* case exit node */
|
||||
nodeList caseNodes; /* temporary: list of nodes in case */
|
||||
|
||||
/* Linear scan of the nodes in reverse dfsLast order, searching for
|
||||
* case nodes */
|
||||
for (i = pProc->numBBs - 1; i >= 0; i--)
|
||||
if (pProc->dfsLast[i]->nodeType == MULTI_BRANCH)
|
||||
{
|
||||
caseHeader = pProc->dfsLast[i];
|
||||
|
||||
/* Find descendant node which has as immediate predecessor
|
||||
* the current header node, and is not a successor. */
|
||||
for (j = i + 2; j < pProc->numBBs; j++)
|
||||
{
|
||||
if ((!successor(j, i, pProc)) &&
|
||||
(pProc->dfsLast[j]->immedDom == i))
|
||||
if (exitNode == NO_NODE)
|
||||
exitNode = j;
|
||||
else if (pProc->dfsLast[exitNode]->numInEdges <
|
||||
pProc->dfsLast[j]->numInEdges)
|
||||
exitNode = j;
|
||||
}
|
||||
pProc->dfsLast[i]->caseTail = exitNode;
|
||||
|
||||
/* Tag nodes that belong to the case by recording the
|
||||
* header field with caseHeader. */
|
||||
insertList (caseNodes, i);
|
||||
pProc->dfsLast[i]->caseHead = i;
|
||||
for (j = 0; j < caseHeader->numOutEdges; j++)
|
||||
tagNodesInCase (caseHeader->edges[j].BBptr, caseNodes, i,
|
||||
exitNode);
|
||||
if (exitNode != NO_NODE)
|
||||
pProc->dfsLast[exitNode]->caseHead = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Flags all nodes in the list l as having follow node f, and deletes all
|
||||
* nodes from the list. */
|
||||
static void flagNodes (nodeList &l, Int f, Function * pProc)
|
||||
{
|
||||
nodeList::iterator p;
|
||||
|
||||
p = l.begin();
|
||||
while (p!=l.end())
|
||||
{
|
||||
pProc->dfsLast[*p]->ifFollow = f;
|
||||
p = l.erase(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void structIfs (Function * pProc)
|
||||
/* Structures if statements */
|
||||
{ Int curr, /* Index for linear scan of nodes */
|
||||
desc, /* Index for descendant */
|
||||
followInEdges, /* Largest # in-edges so far */
|
||||
follow; /* Possible follow node */
|
||||
nodeList domDesc, /* List of nodes dominated by curr */
|
||||
unresolved, /* List of unresolved if nodes */
|
||||
*l; /* Temporary list */
|
||||
BB * currNode, /* Pointer to current node */
|
||||
* pbb;
|
||||
|
||||
/* Linear scan of nodes in reverse dfsLast order */
|
||||
for (curr = pProc->numBBs - 1; curr >= 0; curr--)
|
||||
{
|
||||
currNode = pProc->dfsLast[curr];
|
||||
if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */
|
||||
continue;
|
||||
|
||||
if ((currNode->nodeType == TWO_BRANCH) &&
|
||||
(! (pProc->Icode.GetLlFlag(currNode->start + currNode->length - 1)
|
||||
& JX_LOOP)))
|
||||
{
|
||||
followInEdges = 0;
|
||||
follow = 0;
|
||||
|
||||
/* Find all nodes that have this node as immediate dominator */
|
||||
for (desc = curr+1; desc < pProc->numBBs; desc++)
|
||||
{
|
||||
if (pProc->dfsLast[desc]->immedDom == curr) {
|
||||
insertList (domDesc, desc);
|
||||
pbb = pProc->dfsLast[desc];
|
||||
if ((pbb->numInEdges - pbb->numBackEdges) >= followInEdges)
|
||||
{
|
||||
follow = desc;
|
||||
followInEdges = pbb->numInEdges - pbb->numBackEdges;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine follow according to number of descendants
|
||||
* immediately dominated by this node */
|
||||
if ((follow != 0) && (followInEdges > 1))
|
||||
{
|
||||
currNode->ifFollow = follow;
|
||||
if (!unresolved.empty())
|
||||
flagNodes (unresolved, follow, pProc);
|
||||
}
|
||||
else
|
||||
insertList (unresolved, curr);
|
||||
}
|
||||
freeList (domDesc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Checks for compound conditions of basic blocks that have only 1 high
|
||||
* level instruction. Whenever these blocks are found, they are merged
|
||||
* into one block with the appropriate condition */
|
||||
void Function::compoundCond()
|
||||
{
|
||||
Int i, j, k, numOutEdges;
|
||||
BB * pbb, * t, * e, * obb,* pred;
|
||||
ICODE * picode, * ticode;
|
||||
COND_EXPR *exp;
|
||||
TYPEADR_TYPE *edges;
|
||||
boolT change;
|
||||
|
||||
change = TRUE;
|
||||
while (change)
|
||||
{
|
||||
change = FALSE;
|
||||
|
||||
/* Traverse nodes in postorder, this way, the header node of a
|
||||
* compound condition is analysed first */
|
||||
for (i = 0; i < this->numBBs; i++)
|
||||
{
|
||||
pbb = this->dfsLast[i];
|
||||
if (pbb->flg & INVALID_BB)
|
||||
continue;
|
||||
|
||||
if (pbb->nodeType == TWO_BRANCH)
|
||||
{
|
||||
t = pbb->edges[THEN].BBptr;
|
||||
e = pbb->edges[ELSE].BBptr;
|
||||
|
||||
/* Check (X || Y) case */
|
||||
if ((t->nodeType == TWO_BRANCH) && (t->numHlIcodes == 1) &&
|
||||
(t->numInEdges == 1) && (t->edges[ELSE].BBptr == e))
|
||||
{
|
||||
obb = t->edges[THEN].BBptr;
|
||||
|
||||
/* Construct compound DBL_OR expression */
|
||||
picode = this->Icode.GetIcode(pbb->start + pbb->length -1);
|
||||
ticode = this->Icode.GetIcode(t->start + t->length -1);
|
||||
exp = COND_EXPR::boolOp (picode->ic.hl.oper.exp,
|
||||
ticode->ic.hl.oper.exp, DBL_OR);
|
||||
picode->ic.hl.oper.exp = exp;
|
||||
|
||||
/* Replace in-edge to obb from t to pbb */
|
||||
for (j = 0; j < obb->numInEdges; j++)
|
||||
if (obb->inEdges[j] == t)
|
||||
{
|
||||
obb->inEdges[j] = pbb;
|
||||
break;
|
||||
}
|
||||
|
||||
/* New THEN out-edge of pbb */
|
||||
pbb->edges[THEN].BBptr = obb;
|
||||
|
||||
/* Remove in-edge t to e */
|
||||
auto iter=std::find(e->inEdges.begin(),e->inEdges.end(),t);
|
||||
assert(iter!=e->inEdges.end());
|
||||
e->inEdges.erase(iter);
|
||||
e->numInEdges--; /* looses 1 arc */
|
||||
assert(e->numInEdges==e->inEdges.size());
|
||||
t->flg |= INVALID_BB;
|
||||
|
||||
if (pbb->flg & IS_LATCH_NODE)
|
||||
this->dfsLast[t->dfsLastNum] = pbb;
|
||||
else
|
||||
i--; /* to repeat this analysis */
|
||||
|
||||
change = TRUE;
|
||||
}
|
||||
|
||||
/* Check (!X && Y) case */
|
||||
else if ((t->nodeType == TWO_BRANCH) && (t->numHlIcodes == 1) &&
|
||||
(t->numInEdges == 1) && (t->edges[THEN].BBptr == e))
|
||||
{
|
||||
obb = t->edges[ELSE].BBptr;
|
||||
|
||||
/* Construct compound DBL_AND expression */
|
||||
picode = this->Icode.GetIcode(pbb->start + pbb->length -1);
|
||||
ticode = this->Icode.GetIcode(t->start + t->length -1);
|
||||
inverseCondOp (&picode->ic.hl.oper.exp);
|
||||
exp = COND_EXPR::boolOp (picode->ic.hl.oper.exp,
|
||||
ticode->ic.hl.oper.exp, DBL_AND);
|
||||
picode->ic.hl.oper.exp = exp;
|
||||
|
||||
/* Replace in-edge to obb from t to pbb */
|
||||
auto iter=std::find(obb->inEdges.begin(),obb->inEdges.end(),t);
|
||||
assert(iter!=obb->inEdges.end());
|
||||
*iter=pbb;
|
||||
|
||||
/* New THEN and ELSE out-edges of pbb */
|
||||
pbb->edges[THEN].BBptr = e;
|
||||
pbb->edges[ELSE].BBptr = obb;
|
||||
|
||||
/* Remove in-edge t to e */
|
||||
iter=std::find(e->inEdges.begin(),e->inEdges.end(),t);
|
||||
assert(iter!=e->inEdges.end());
|
||||
e->inEdges.erase(iter); /* looses 1 arc */
|
||||
e->numInEdges--; /* looses 1 arc */
|
||||
assert(t->inEdges.size()==t->numInEdges);
|
||||
t->flg |= INVALID_BB;
|
||||
|
||||
if (pbb->flg & IS_LATCH_NODE)
|
||||
this->dfsLast[t->dfsLastNum] = pbb;
|
||||
else
|
||||
i--; /* to repeat this analysis */
|
||||
|
||||
change = TRUE;
|
||||
}
|
||||
|
||||
/* Check (X && Y) case */
|
||||
else if ((e->nodeType == TWO_BRANCH) && (e->numHlIcodes == 1) &&
|
||||
(e->numInEdges == 1) && (e->edges[THEN].BBptr == t))
|
||||
{
|
||||
obb = e->edges[ELSE].BBptr;
|
||||
|
||||
/* Construct compound DBL_AND expression */
|
||||
picode = this->Icode.GetIcode(pbb->start + pbb->length -1);
|
||||
ticode = this->Icode.GetIcode(t->start + t->length -1);
|
||||
exp = COND_EXPR::boolOp (picode->ic.hl.oper.exp,
|
||||
ticode->ic.hl.oper.exp, DBL_AND);
|
||||
picode->ic.hl.oper.exp = exp;
|
||||
|
||||
/* Replace in-edge to obb from e to pbb */
|
||||
auto iter = std::find(obb->inEdges.begin(),obb->inEdges.end(),e);
|
||||
assert(iter!=obb->inEdges.end());
|
||||
*iter=pbb;
|
||||
/* New ELSE out-edge of pbb */
|
||||
pbb->edges[ELSE].BBptr = obb;
|
||||
|
||||
/* Remove in-edge e to t */
|
||||
iter = std::find(t->inEdges.begin(),t->inEdges.end(),e);
|
||||
assert(iter!=t->inEdges.end());
|
||||
t->inEdges.erase(iter);
|
||||
t->numInEdges--; /* looses 1 arc */
|
||||
assert(t->inEdges.size()==t->numInEdges);
|
||||
e->flg |= INVALID_BB;
|
||||
|
||||
if (pbb->flg & IS_LATCH_NODE)
|
||||
this->dfsLast[e->dfsLastNum] = pbb;
|
||||
else
|
||||
i--; /* to repeat this analysis */
|
||||
|
||||
change = TRUE;
|
||||
}
|
||||
|
||||
/* Check (!X || Y) case */
|
||||
else if ((e->nodeType == TWO_BRANCH) && (e->numHlIcodes == 1) &&
|
||||
(e->numInEdges == 1) && (e->edges[ELSE].BBptr == t))
|
||||
{
|
||||
obb = e->edges[THEN].BBptr;
|
||||
|
||||
/* Construct compound DBL_OR expression */
|
||||
picode = this->Icode.GetIcode(pbb->start + pbb->length -1);
|
||||
ticode = this->Icode.GetIcode(t->start + t->length -1);
|
||||
inverseCondOp (&picode->ic.hl.oper.exp);
|
||||
exp = COND_EXPR::boolOp (picode->ic.hl.oper.exp,
|
||||
ticode->ic.hl.oper.exp, DBL_OR);
|
||||
picode->ic.hl.oper.exp = exp;
|
||||
|
||||
/* Replace in-edge to obb from e to pbb */
|
||||
assert(obb->numInEdges==obb->inEdges.size());
|
||||
auto iter = std::find(obb->inEdges.begin(),obb->inEdges.end(),e);
|
||||
assert(iter!=obb->inEdges.end());
|
||||
*iter=pbb;
|
||||
|
||||
/* New THEN and ELSE out-edges of pbb */
|
||||
pbb->edges[THEN].BBptr = obb;
|
||||
pbb->edges[ELSE].BBptr = t;
|
||||
|
||||
/* Remove in-edge e to t */
|
||||
iter = std::find(t->inEdges.begin(),t->inEdges.end(),e);
|
||||
assert(iter!=t->inEdges.end());
|
||||
t->inEdges.erase(iter);
|
||||
t->numInEdges--; /* looses 1 arc */
|
||||
assert(t->numInEdges=t->inEdges.size());
|
||||
e->flg |= INVALID_BB;
|
||||
|
||||
if (pbb->flg & IS_LATCH_NODE)
|
||||
this->dfsLast[e->dfsLastNum] = pbb;
|
||||
else
|
||||
i--; /* to repeat this analysis */
|
||||
|
||||
change = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Function::structure(derSeq *derivedG)
|
||||
/* Structuring algorithm to find the structures of the graph pProc->cfg */
|
||||
{
|
||||
/* Find immediate dominators of the graph */
|
||||
findImmedDom();
|
||||
if (hasCase)
|
||||
structCases(this);
|
||||
structLoops(this, derivedG);
|
||||
structIfs(this);
|
||||
}
|
||||
1099
src/dataflow.cpp
Normal file
1099
src/dataflow.cpp
Normal file
File diff suppressed because it is too large
Load Diff
163
src/dcc.cpp
Normal file
163
src/dcc.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
/*****************************************************************************
|
||||
* dcc decompiler
|
||||
* Reads the command line switches and then executes each major section in turn
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include <string.h>
|
||||
#ifdef __UNIX__
|
||||
//#include <unistd.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <io.h> /* For unlink() */
|
||||
#endif
|
||||
|
||||
|
||||
/* Global variables - extern to other modules */
|
||||
char *progname; /* argv[0] - for error msgs */
|
||||
char *asm1_name, *asm2_name; /* Assembler output filenames */
|
||||
SYMTAB symtab; /* Global symbol table */
|
||||
STATS stats; /* cfg statistics */
|
||||
PROG prog; /* programs fields */
|
||||
OPTION option; /* Command line options */
|
||||
//Function * pProcList; /* List of procedures, topologically sort */
|
||||
//Function * pLastProc; /* Pointer to last node in procedure list */
|
||||
std::list<Function> pProcList;
|
||||
CALL_GRAPH *callGraph; /* Call graph of the program */
|
||||
|
||||
static char *initargs(int argc, char *argv[]);
|
||||
static void displayTotalStats();
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* main
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Extract switches and filename */
|
||||
strcpy(option.filename, initargs(argc, argv));
|
||||
|
||||
/* Front end reads in EXE or COM file, parses it into I-code while
|
||||
* building the call graph and attaching appropriate bits of code for
|
||||
* each procedure.
|
||||
*/
|
||||
FrontEnd (option.filename, &callGraph);
|
||||
|
||||
/* In the middle is a so called Universal Decompiling Machine.
|
||||
* It processes the procedure list and I-code and attaches where it can
|
||||
* to each procedure an optimised cfg and ud lists
|
||||
*/
|
||||
udm();
|
||||
|
||||
/* Back end converts each procedure into C using I-code, interval
|
||||
* analysis, data flow etc. and outputs it to output file ready for
|
||||
* re-compilation.
|
||||
*/
|
||||
BackEnd(option.filename, callGraph);
|
||||
|
||||
callGraph->write();
|
||||
|
||||
if (option.Stats)
|
||||
displayTotalStats();
|
||||
|
||||
/*
|
||||
freeDataStructures(pProcList);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* initargs - Extract command line arguments
|
||||
***************************************************************************/
|
||||
static char *initargs(int argc, char *argv[])
|
||||
{
|
||||
char *pc;
|
||||
progname = *argv; /* Save invocation name for error messages */
|
||||
|
||||
while (--argc > 0 && (*++argv)[0] == '-') {
|
||||
for (pc = argv[0]+1; *pc; pc++)
|
||||
switch (*pc) {
|
||||
case 'a': /* Print assembler listing */
|
||||
if (*(pc+1) == '2')
|
||||
option.asm2 = TRUE;
|
||||
else
|
||||
option.asm1 = TRUE;
|
||||
if (*(pc+1) == '1' || *(pc+1) == '2')
|
||||
pc++;
|
||||
break;
|
||||
case 'c':
|
||||
option.Calls = TRUE;
|
||||
break;
|
||||
case 'i':
|
||||
option.Interact = TRUE;
|
||||
break;
|
||||
case 'm': /* Print memory map */
|
||||
option.Map = TRUE;
|
||||
break;
|
||||
case 's': /* Print Stats */
|
||||
option.Stats = TRUE;
|
||||
break;
|
||||
case 'V': /* Very verbose => verbose */
|
||||
option.VeryVerbose = TRUE;
|
||||
case 'v': /* Make everything verbose */
|
||||
option.verbose = TRUE;
|
||||
break;
|
||||
case 'o': /* assembler output file */
|
||||
if (*(pc+1)) {
|
||||
asm1_name = asm2_name = pc+1;
|
||||
goto NextArg;
|
||||
}
|
||||
else if (--argc > 0) {
|
||||
asm1_name = asm2_name = *++argv;
|
||||
goto NextArg;
|
||||
}
|
||||
default:
|
||||
fatalError(INVALID_ARG, *pc);
|
||||
return *argv;
|
||||
}
|
||||
NextArg:;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
if (option.asm1 || option.asm2)
|
||||
{
|
||||
if (! asm1_name)
|
||||
{
|
||||
asm1_name = strcpy((char*)allocMem(strlen(*argv)+4), *argv);
|
||||
pc = strrchr(asm1_name, '.');
|
||||
if (pc > strrchr(asm1_name, '/'))
|
||||
{
|
||||
*pc = '\0';
|
||||
}
|
||||
asm2_name = (char*)allocMem(strlen(asm1_name)+4) ;
|
||||
strcat(strcpy(asm2_name, asm1_name), ".a2");
|
||||
unlink(asm2_name);
|
||||
strcat(asm1_name, ".a1");
|
||||
}
|
||||
unlink(asm1_name); /* Remove asm output files */
|
||||
}
|
||||
return *argv; /* filename of the program to decompile */
|
||||
}
|
||||
|
||||
fatalError(USAGE);
|
||||
return *argv;
|
||||
}
|
||||
|
||||
static void
|
||||
displayTotalStats ()
|
||||
/* Displays final statistics for the complete program */
|
||||
{
|
||||
printf ("\nFinal Program Statistics\n");
|
||||
printf (" Total number of low-level Icodes : %ld\n", stats.totalLL);
|
||||
printf (" Total number of high-level Icodes: %ld\n", stats.totalHL);
|
||||
printf (" Total reduction of instructions : %2.2f%%\n", 100.0 -
|
||||
(stats.totalHL * 100.0) / stats.totalLL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
1613
src/disassem.cpp
Normal file
1613
src/disassem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
86
src/error.cpp
Normal file
86
src/error.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
/****************************************************************************
|
||||
* dcc project error messages
|
||||
* (C) Cristina Cifuentes
|
||||
***************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
//#ifndef __UNIX__
|
||||
#if 1
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
static const char *errorMessage[] = {
|
||||
"Invalid option -%c\n", /* INVALID_ARG */
|
||||
"Invalid instruction %02X at location %06lX\n", /* INVALID_OPCODE */
|
||||
"Don't understand 80386 instruction %02X at location %06lX\n",
|
||||
/* INVALID_386OP */
|
||||
"Segment override with no memory operand at location %06lX\n",
|
||||
/* FUNNY_SEGOVR */
|
||||
"REP prefix without a string instruction at location %06lX\n",/* FUNNY_REP */
|
||||
"Cannot open %s\n", /* CANNOT_OPEN */
|
||||
"Error while reading %s\n", /* CANNOT_READ */
|
||||
"malloc of %ld bytes failed\n", /* MALLOC_FAILED */
|
||||
"Don't understand new EXE format\n", /* NEWEXE_FORMAT */
|
||||
"Failed to find a BB for jump to %ld in proc %s\n", /* NO_BB */
|
||||
"Basic Block is a synthetic jump\n", /* INVALID_SYNTHETIC_BB */
|
||||
"Failed to find a BB for interval\n", /* INVALID_INT_BB */
|
||||
"Instruction at location %06lX goes beyond loaded image\n",
|
||||
/* IP_OUT_OF_RANGE*/
|
||||
"Definition not found for condition code usage at opcode %d\n",
|
||||
/* DEF_NOT_FOUND */
|
||||
"JX use, definition not supported at opcode #%d\n", /* JX_NOT_DEF */
|
||||
"Def - use not supported. Def op = %d, use op = %d.\n", /* NOT_DEF_USE */
|
||||
"Failed to construct repeat..until() condition.\n", /* REPEAT_FAIL */
|
||||
"Failed to construct while() condition.\n", /* WHILE_FAIL */
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
fatalError: displays error message and exits the program.
|
||||
****************************************************************************/
|
||||
void fatalError(Int errId, ...)
|
||||
{ va_list args;
|
||||
//#ifdef __UNIX__ /* ultrix */
|
||||
#if 0
|
||||
Int errId;
|
||||
|
||||
va_start(args);
|
||||
errId = va_arg(args, Int);
|
||||
#else
|
||||
va_start(args, errId);
|
||||
#endif
|
||||
|
||||
if (errId == USAGE)
|
||||
fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n");
|
||||
else {
|
||||
fprintf(stderr, "dcc: ");
|
||||
vfprintf(stderr, errorMessage[errId - 1], args);
|
||||
}
|
||||
va_end(args);
|
||||
exit((int)errId);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
reportError: reports the warning/error and continues with the program.
|
||||
****************************************************************************/
|
||||
void reportError(Int errId, ...)
|
||||
{ va_list args;
|
||||
//#ifdef __UNIX__ /* ultrix */
|
||||
#if 0
|
||||
Int errId;
|
||||
|
||||
va_start(args);
|
||||
errId = va_arg(args, Int);
|
||||
#else /* msdos or windows*/
|
||||
va_start(args, errId);
|
||||
#endif
|
||||
fprintf(stderr, "dcc: ");
|
||||
vfprintf(stderr, errorMessage[errId - 1], args);
|
||||
va_end(args);
|
||||
}
|
||||
521
src/fixwild.cpp
Normal file
521
src/fixwild.cpp
Normal file
@ -0,0 +1,521 @@
|
||||
/*
|
||||
* Fix Wildcards
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
|
||||
/* * * * * * * * * * * * *\
|
||||
* *
|
||||
* Fix Wild Cards Code *
|
||||
* *
|
||||
\* * * * * * * * * * * * */
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
#ifndef PATLEN
|
||||
#define PATLEN 23
|
||||
#define WILD 0xF4
|
||||
#endif
|
||||
|
||||
#ifndef bool
|
||||
#define bool unsigned char
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define byte unsigned char
|
||||
#endif
|
||||
|
||||
static int pc; /* Indexes into pat[] */
|
||||
|
||||
/* prototypes */
|
||||
static bool ModRM(byte pat[]); /* Handle the mod/rm byte */
|
||||
static bool TwoWild(byte pat[]); /* Make the next 2 bytes wild */
|
||||
static bool FourWild(byte pat[]); /* Make the next 4 bytes wild */
|
||||
void fixWildCards(byte pat[]); /* Main routine */
|
||||
|
||||
|
||||
/* Handle the mod/rm case. Returns true if pattern exhausted */
|
||||
static bool ModRM(byte pat[])
|
||||
{
|
||||
byte op;
|
||||
|
||||
/* A standard mod/rm byte follows opcode */
|
||||
op = pat[pc++]; /* The mod/rm byte */
|
||||
if (pc >= PATLEN) return TRUE; /* Skip Mod/RM */
|
||||
switch (op & 0xC0)
|
||||
{
|
||||
case 0x00: /* [reg] or [nnnn] */
|
||||
if ((op & 0xC7) == 6)
|
||||
{
|
||||
/* Uses [nnnn] address mode */
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
}
|
||||
break;
|
||||
case 0x40: /* [reg + nn] */
|
||||
if ((pc+=1) >= PATLEN) return TRUE;
|
||||
break;
|
||||
case 0x80: /* [reg + nnnn] */
|
||||
/* Possibly just a long constant offset from a register,
|
||||
but often will be an index from a variable */
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
break;
|
||||
case 0xC0: /* reg */
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Change the next two bytes to wild cards */
|
||||
static bool
|
||||
TwoWild(byte pat[])
|
||||
{
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return TRUE; /* Pattern exhausted */
|
||||
pat[pc++] = WILD;
|
||||
if (pc >= PATLEN) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Change the next four bytes to wild cards */
|
||||
static bool
|
||||
FourWild(byte pat[])
|
||||
{
|
||||
TwoWild(pat);
|
||||
return TwoWild(pat);
|
||||
}
|
||||
|
||||
/* Chop from the current point by wiping with zeroes. Can't rely on anything
|
||||
after this point */
|
||||
static void
|
||||
chop(byte pat[])
|
||||
{
|
||||
if (pc >= PATLEN) return; /* Could go negative otherwise */
|
||||
memset(&pat[pc], 0, PATLEN - pc);
|
||||
}
|
||||
|
||||
static bool
|
||||
op0F(byte pat[])
|
||||
{
|
||||
/* The two byte opcodes */
|
||||
byte op = pat[pc++];
|
||||
switch (op & 0xF0)
|
||||
{
|
||||
case 0x00: /* 00 - 0F */
|
||||
if (op >= 0x06) /* Clts, Invd, Wbinvd */
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
/* Grp 6, Grp 7, LAR, LSL */
|
||||
return ModRM(pat);
|
||||
}
|
||||
case 0x20: /* Various funnies, all with Mod/RM */
|
||||
return ModRM(pat);
|
||||
|
||||
case 0x80:
|
||||
pc += 2; /* Word displacement cond jumps */
|
||||
return FALSE;
|
||||
|
||||
case 0x90: /* Byte set on condition */
|
||||
return ModRM(pat);
|
||||
|
||||
case 0xA0:
|
||||
switch (op)
|
||||
{
|
||||
case 0xA0: /* Push FS */
|
||||
case 0xA1: /* Pop FS */
|
||||
case 0xA8: /* Push GS */
|
||||
case 0xA9: /* Pop GS */
|
||||
return FALSE;
|
||||
|
||||
case 0xA3: /* Bt Ev,Gv */
|
||||
case 0xAB: /* Bts Ev,Gv */
|
||||
return ModRM(pat);
|
||||
|
||||
case 0xA4: /* Shld EvGbIb */
|
||||
case 0xAC: /* Shrd EvGbIb */
|
||||
if (ModRM(pat)) return TRUE;
|
||||
pc++; /* The #num bits to shift */
|
||||
return FALSE;
|
||||
|
||||
case 0xA5: /* Shld EvGb CL */
|
||||
case 0xAD: /* Shrd EvGb CL */
|
||||
return ModRM(pat);
|
||||
|
||||
default: /* CmpXchg, Imul */
|
||||
return ModRM(pat);
|
||||
}
|
||||
|
||||
case 0xB0:
|
||||
if (op == 0xBA)
|
||||
{
|
||||
/* Grp 8: bt/bts/btr/btc Ev,#nn */
|
||||
if (ModRM(pat)) return TRUE;
|
||||
pc++; /* The #num bits to shift */
|
||||
return FALSE;
|
||||
}
|
||||
return ModRM(pat);
|
||||
|
||||
case 0xC0:
|
||||
if (op <= 0xC1)
|
||||
{
|
||||
/* Xadd */
|
||||
return ModRM(pat);
|
||||
}
|
||||
/* Else BSWAP */
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return FALSE; /* Treat as double byte opcodes */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Scan through the instructions in pat[], looking for opcodes that may
|
||||
have operands that vary with different instances. For example, load and
|
||||
store from statics, calls to other procs (even relative calls; they may
|
||||
call procs loaded in a different order, etc).
|
||||
Note that this procedure is architecture specific, and assumes the
|
||||
processor is in 16 bit address mode (real mode).
|
||||
PATLEN bytes are scanned.
|
||||
*/
|
||||
void
|
||||
fixWildCards(byte pat[])
|
||||
{
|
||||
|
||||
byte op, quad, intArg;
|
||||
|
||||
|
||||
pc=0;
|
||||
while (pc < PATLEN)
|
||||
{
|
||||
op = pat[pc++];
|
||||
if (pc >= PATLEN) return;
|
||||
|
||||
quad = (byte) (op & 0xC0); /* Quadrant of the opcode map */
|
||||
if (quad == 0)
|
||||
{
|
||||
/* Arithmetic group 00-3F */
|
||||
|
||||
if ((op & 0xE7) == 0x26) /* First check for the odds */
|
||||
{
|
||||
/* Segment prefix: treat as 1 byte opcode */
|
||||
continue;
|
||||
}
|
||||
if (op == 0x0F) /* 386 2 byte opcodes */
|
||||
{
|
||||
if (op0F(pat)) return;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (op & 0x04)
|
||||
{
|
||||
/* All these are constant. Work out the instr length */
|
||||
if (op & 2)
|
||||
{
|
||||
/* Push, pop, other 1 byte opcodes */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op & 1)
|
||||
{
|
||||
/* Word immediate operands */
|
||||
pc += 2;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Byte immediate operands */
|
||||
pc++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All these have mod/rm bytes */
|
||||
if (ModRM(pat)) return;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (quad == 0x40)
|
||||
{
|
||||
if ((op & 0x60) == 0x40)
|
||||
{
|
||||
/* 0x40 - 0x5F -- these are inc, dec, push, pop of general
|
||||
registers */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 0x60 - 0x70 */
|
||||
if (op & 0x10)
|
||||
{
|
||||
/* 70-7F 2 byte jump opcodes */
|
||||
pc++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Odds and sods */
|
||||
switch (op)
|
||||
{
|
||||
case 0x60: /* pusha */
|
||||
case 0x61: /* popa */
|
||||
case 0x64: /* overrides */
|
||||
case 0x65:
|
||||
case 0x66:
|
||||
case 0x67:
|
||||
case 0x6C: /* insb DX */
|
||||
case 0x6E: /* outsb DX */
|
||||
continue;
|
||||
|
||||
case 0x62: /* bound */
|
||||
pc += 4;
|
||||
continue;
|
||||
|
||||
case 0x63: /* arpl */
|
||||
if (TwoWild(pat)) return;
|
||||
continue;
|
||||
|
||||
case 0x68: /* Push byte */
|
||||
case 0x6A: /* Push byte */
|
||||
case 0x6D: /* insb port */
|
||||
case 0x6F: /* outsb port */
|
||||
/* 2 byte instr, no wilds */
|
||||
pc++;
|
||||
continue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (quad == 0x80)
|
||||
{
|
||||
switch (op & 0xF0)
|
||||
{
|
||||
case 0x80: /* 80 - 8F */
|
||||
/* All have a mod/rm byte */
|
||||
if (ModRM(pat)) return;
|
||||
/* These also have immediate values */
|
||||
switch (op)
|
||||
{
|
||||
case 0x80:
|
||||
case 0x83:
|
||||
/* One byte immediate */
|
||||
pc++;
|
||||
continue;
|
||||
|
||||
case 0x81:
|
||||
/* Immediate 16 bit values might be constant, but
|
||||
also might be relocatable. Have to make them
|
||||
wild */
|
||||
if (TwoWild(pat)) return;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
case 0x90: /* 90 - 9F */
|
||||
if (op == 0x9A)
|
||||
{
|
||||
/* far call */
|
||||
if (FourWild(pat)) return;
|
||||
continue;
|
||||
}
|
||||
/* All others are 1 byte opcodes */
|
||||
continue;
|
||||
case 0xA0: /* A0 - AF */
|
||||
if ((op & 0x0C) == 0)
|
||||
{
|
||||
/* mov al/ax to/from [nnnn] */
|
||||
if (TwoWild(pat)) return;
|
||||
continue;
|
||||
}
|
||||
else if ((op & 0xFE) == 0xA8)
|
||||
{
|
||||
/* test al,#byte or test ax,#word */
|
||||
if (op & 1) pc += 2;
|
||||
else pc += 1;
|
||||
continue;
|
||||
|
||||
}
|
||||
case 0xB0: /* B0 - BF */
|
||||
{
|
||||
if (op & 8)
|
||||
{
|
||||
/* mov reg, #16 */
|
||||
/* Immediate 16 bit values might be constant, but also
|
||||
might be relocatable. For now, make them wild */
|
||||
if (TwoWild(pat)) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* mov reg, #8 */
|
||||
pc++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In the last quadrant of the op code table */
|
||||
switch (op)
|
||||
{
|
||||
case 0xC0: /* 386: Rotate group 2 ModRM, byte, #byte */
|
||||
case 0xC1: /* 386: Rotate group 2 ModRM, word, #byte */
|
||||
if (ModRM(pat)) return;
|
||||
/* Byte immediate value follows ModRM */
|
||||
pc++;
|
||||
continue;
|
||||
|
||||
case 0xC3: /* Return */
|
||||
case 0xCB: /* Return far */
|
||||
chop(pat);
|
||||
return;
|
||||
case 0xC2: /* Ret nnnn */
|
||||
case 0xCA: /* Retf nnnn */
|
||||
pc += 2;
|
||||
chop(pat);
|
||||
return;
|
||||
|
||||
case 0xC4: /* les Gv, Mp */
|
||||
case 0xC5: /* lds Gv, Mp */
|
||||
if (ModRM(pat)) return;
|
||||
continue;
|
||||
|
||||
case 0xC6: /* Mov ModRM, #nn */
|
||||
if (ModRM(pat)) return;
|
||||
/* Byte immediate value follows ModRM */
|
||||
pc++;
|
||||
continue;
|
||||
case 0xC7: /* Mov ModRM, #nnnn */
|
||||
if (ModRM(pat)) return;
|
||||
/* Word immediate value follows ModRM */
|
||||
/* Immediate 16 bit values might be constant, but also
|
||||
might be relocatable. For now, make them wild */
|
||||
if (TwoWild(pat)) return;
|
||||
continue;
|
||||
|
||||
case 0xC8: /* Enter Iw, Ib */
|
||||
pc += 3; /* Constant word, byte */
|
||||
continue;
|
||||
case 0xC9: /* Leave */
|
||||
continue;
|
||||
|
||||
case 0xCC: /* Int 3 */
|
||||
continue;
|
||||
|
||||
case 0xCD: /* Int nn */
|
||||
intArg = pat[pc++];
|
||||
if ((intArg >= 0x34) && (intArg <= 0x3B))
|
||||
{
|
||||
/* Borland/Microsoft FP emulations */
|
||||
if (ModRM(pat)) return;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 0xCE: /* Into */
|
||||
continue;
|
||||
|
||||
case 0xCF: /* Iret */
|
||||
continue;
|
||||
|
||||
case 0xD0: /* Group 2 rotate, byte, 1 bit */
|
||||
case 0xD1: /* Group 2 rotate, word, 1 bit */
|
||||
case 0xD2: /* Group 2 rotate, byte, CL bits */
|
||||
case 0xD3: /* Group 2 rotate, word, CL bits */
|
||||
if (ModRM(pat)) return;
|
||||
continue;
|
||||
|
||||
case 0xD4: /* Aam */
|
||||
case 0xD5: /* Aad */
|
||||
case 0xD7: /* Xlat */
|
||||
continue;
|
||||
|
||||
case 0xD8:
|
||||
case 0xD9:
|
||||
case 0xDA:
|
||||
case 0xDB: /* Esc opcodes */
|
||||
case 0xDC: /* i.e. floating point */
|
||||
case 0xDD: /* coprocessor calls */
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
if (ModRM(pat)) return;
|
||||
continue;
|
||||
|
||||
case 0xE0: /* Loopne */
|
||||
case 0xE1: /* Loope */
|
||||
case 0xE2: /* Loop */
|
||||
case 0xE3: /* Jcxz */
|
||||
pc++; /* Short jump offset */
|
||||
continue;
|
||||
|
||||
case 0xE4: /* in al,nn */
|
||||
case 0xE6: /* out nn,al */
|
||||
pc++;
|
||||
continue;
|
||||
|
||||
case 0xE5: /* in ax,nn */
|
||||
case 0xE7: /* in nn,ax */
|
||||
pc += 2;
|
||||
continue;
|
||||
|
||||
case 0xE8: /* Call rel */
|
||||
if (TwoWild(pat)) return;
|
||||
continue;
|
||||
case 0xE9: /* Jump rel, unconditional */
|
||||
if (TwoWild(pat)) return;
|
||||
chop(pat);
|
||||
return;
|
||||
case 0xEA: /* Jump abs */
|
||||
if (FourWild(pat)) return;
|
||||
chop(pat);
|
||||
return;
|
||||
case 0xEB: /* Jmp short unconditional */
|
||||
pc++;
|
||||
chop(pat);
|
||||
return;
|
||||
|
||||
case 0xEC: /* In al,dx */
|
||||
case 0xED: /* In ax,dx */
|
||||
case 0xEE: /* Out dx,al */
|
||||
case 0xEF: /* Out dx,ax */
|
||||
continue;
|
||||
|
||||
case 0xF0: /* Lock */
|
||||
case 0xF2: /* Repne */
|
||||
case 0xF3: /* Rep/repe */
|
||||
case 0xF4: /* Halt */
|
||||
case 0xF5: /* Cmc */
|
||||
case 0xF8: /* Clc */
|
||||
case 0xF9: /* Stc */
|
||||
case 0xFA: /* Cli */
|
||||
case 0xFB: /* Sti */
|
||||
case 0xFC: /* Cld */
|
||||
case 0xFD: /* Std */
|
||||
continue;
|
||||
|
||||
case 0xF6: /* Group 3 byte test/not/mul/div */
|
||||
case 0xF7: /* Group 3 word test/not/mul/div */
|
||||
case 0xFE: /* Inc/Dec group 4 */
|
||||
if (ModRM(pat)) return;
|
||||
continue;
|
||||
|
||||
case 0xFF: /* Group 5 Inc/Dec/Call/Jmp/Push */
|
||||
/* Most are like standard ModRM */
|
||||
if (ModRM(pat)) return;
|
||||
continue;
|
||||
|
||||
default: /* Rest are single byte opcodes */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
372
src/frontend.cpp
Normal file
372
src/frontend.cpp
Normal file
@ -0,0 +1,372 @@
|
||||
/*****************************************************************************
|
||||
* dcc project Front End module
|
||||
* Loads a program into simulated main memory and builds the procedure list.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef __BORLAND__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h> /* For malloc, free, realloc */
|
||||
#endif
|
||||
|
||||
typedef struct { /* PSP structure */
|
||||
word int20h; /* interrupt 20h */
|
||||
word eof; /* segment, end of allocation block */
|
||||
byte res1; /* reserved */
|
||||
byte dosDisp[5]; /* far call to DOS function dispatcher */
|
||||
byte int22h[4]; /* vector for terminate routine */
|
||||
byte int23h[4]; /* vector for ctrl+break routine */
|
||||
byte int24h[4]; /* vector for error routine */
|
||||
byte res2[22]; /* reserved */
|
||||
word segEnv; /* segment address of environment block */
|
||||
byte res3[34]; /* reserved */
|
||||
byte int21h[6]; /* opcode for int21h and far return */
|
||||
byte res4[6]; /* reserved */
|
||||
byte fcb1[16]; /* default file control block 1 */
|
||||
byte fcb2[16]; /* default file control block 2 */
|
||||
byte res5[4]; /* reserved */
|
||||
byte cmdTail[0x80]; /* command tail and disk transfer area */
|
||||
} PSP;
|
||||
|
||||
static struct { /* EXE file header */
|
||||
byte sigLo; /* .EXE signature: 0x4D 0x5A */
|
||||
byte sigHi;
|
||||
word lastPageSize; /* Size of the last page */
|
||||
word numPages; /* Number of pages in the file */
|
||||
word numReloc; /* Number of relocation items */
|
||||
word numParaHeader; /* # of paragraphs in the header */
|
||||
word minAlloc; /* Minimum number of paragraphs */
|
||||
word maxAlloc; /* Maximum number of paragraphs */
|
||||
word initSS; /* Segment displacement of stack */
|
||||
word initSP; /* Contents of SP at entry */
|
||||
word checkSum; /* Complemented checksum */
|
||||
word initIP; /* Contents of IP at entry */
|
||||
word initCS; /* Segment displacement of code */
|
||||
word relocTabOffset; /* Relocation table offset */
|
||||
word overlayNum; /* Overlay number */
|
||||
} header;
|
||||
|
||||
#define EXE_RELOCATION 0x10 /* EXE images rellocated to above PSP */
|
||||
|
||||
static void LoadImage(char *filename);
|
||||
static void displayLoadInfo(void);
|
||||
static void displayMemMap(void);
|
||||
|
||||
/*****************************************************************************
|
||||
* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode
|
||||
* rewritter, and displays any useful information.
|
||||
****************************************************************************/
|
||||
void FrontEnd (char *filename, CALL_GRAPH * *pcallGraph)
|
||||
{
|
||||
/* Load program into memory */
|
||||
LoadImage(filename);
|
||||
|
||||
if (option.verbose)
|
||||
displayLoadInfo();
|
||||
|
||||
/* Do depth first flow analysis building call graph and procedure list,
|
||||
* and attaching the I-code to each procedure */
|
||||
parse (pcallGraph);
|
||||
|
||||
if (option.asm1)
|
||||
{
|
||||
printf("dcc: writing assembler file %s\n", asm1_name);
|
||||
}
|
||||
|
||||
/* Search through code looking for impure references and flag them */
|
||||
std::for_each(pProcList.begin(),pProcList.end(),
|
||||
[](Function &f)->void {
|
||||
f.markImpure();
|
||||
if (option.asm1)
|
||||
disassem(1, &f); });
|
||||
if (option.Interact)
|
||||
{
|
||||
interactDis(&pProcList.front(), 0); /* Interactive disassembler */
|
||||
}
|
||||
|
||||
/* Converts jump target addresses to icode offsets */
|
||||
std::for_each(pProcList.begin(),pProcList.end(),
|
||||
[](Function &f)->void { f.bindIcodeOff(); });
|
||||
|
||||
/* Print memory bitmap */
|
||||
if (option.Map)
|
||||
displayMemMap();
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* displayLoadInfo - Displays low level loader type info.
|
||||
***************************************************************************/
|
||||
static void displayLoadInfo(void)
|
||||
{
|
||||
Int i;
|
||||
|
||||
printf("File type is %s\n", (prog.fCOM)?"COM":"EXE");
|
||||
if (! prog.fCOM) {
|
||||
printf("Signature = %02X%02X\n", header.sigLo, header.sigHi);
|
||||
printf("File size %% 512 = %04X\n", LH(&header.lastPageSize));
|
||||
printf("File size / 512 = %04X pages\n", LH(&header.numPages));
|
||||
printf("# relocation items = %04X\n", LH(&header.numReloc));
|
||||
printf("Offset to load image = %04X paras\n", LH(&header.numParaHeader));
|
||||
printf("Minimum allocation = %04X paras\n", LH(&header.minAlloc));
|
||||
printf("Maximum allocation = %04X paras\n", LH(&header.maxAlloc));
|
||||
}
|
||||
printf("Load image size = %04X\n", prog.cbImage - sizeof(PSP));
|
||||
printf("Initial SS:SP = %04X:%04X\n", prog.initSS, prog.initSP);
|
||||
printf("Initial CS:IP = %04X:%04X\n", prog.initCS, prog.initIP);
|
||||
|
||||
if (option.VeryVerbose && prog.cReloc)
|
||||
{
|
||||
printf("\nRelocation Table\n");
|
||||
for (i = 0; i < prog.cReloc; i++)
|
||||
{
|
||||
printf("%06X -> [%04X]\n", prog.relocTable[i],LH(prog.Image + prog.relocTable[i]));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* fill - Fills line for displayMemMap()
|
||||
****************************************************************************/
|
||||
static void fill(Int ip, char *bf)
|
||||
{
|
||||
static byte type[4] = {'.', 'd', 'c', 'x'};
|
||||
byte i;
|
||||
|
||||
for (i = 0; i < 16; i++, ip++)
|
||||
{
|
||||
*bf++ = ' ';
|
||||
*bf++ = (ip < prog.cbImage)?
|
||||
type[(prog.map[ip >> 2] >> ((ip & 3) * 2)) & 3]: ' ';
|
||||
}
|
||||
*bf = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* displayMemMap - Displays the memory bitmap
|
||||
****************************************************************************/
|
||||
static void displayMemMap(void)
|
||||
{
|
||||
char c, b1[33], b2[33], b3[33];
|
||||
byte i;
|
||||
Int ip = 0;
|
||||
|
||||
printf("\nMemory Map\n");
|
||||
while (ip < prog.cbImage)
|
||||
{
|
||||
fill(ip, b1);
|
||||
printf("%06X %s\n", ip, b1);
|
||||
ip += 16;
|
||||
for (i = 3, c = b1[1]; i < 32 && c == b1[i]; i += 2)
|
||||
; /* Check if all same */
|
||||
if (i > 32)
|
||||
{
|
||||
fill(ip, b2); /* Skip until next two are not same */
|
||||
fill(ip+16, b3);
|
||||
if (! (strcmp(b1, b2) || strcmp(b1, b3)))
|
||||
{
|
||||
printf(" :\n");
|
||||
do
|
||||
{
|
||||
ip += 16;
|
||||
fill(ip+16, b1);
|
||||
} while (! strcmp(b1, b2));
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* LoadImage
|
||||
****************************************************************************/
|
||||
static void LoadImage(char *filename)
|
||||
{
|
||||
FILE *fp;
|
||||
Int i, cb;
|
||||
byte buf[4];
|
||||
|
||||
/* Open the input file */
|
||||
if ((fp = fopen(filename, "rb")) == NULL)
|
||||
{
|
||||
fatalError(CANNOT_OPEN, filename);
|
||||
}
|
||||
|
||||
/* Read in first 2 bytes to check EXE signature */
|
||||
if (fread(&header, 1, 2, fp) != 2)
|
||||
{
|
||||
fatalError(CANNOT_READ, filename);
|
||||
}
|
||||
|
||||
if (! (prog.fCOM = (boolT)(header.sigLo != 0x4D || header.sigHi != 0x5A))) {
|
||||
/* Read rest of header */
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
if (fread(&header, sizeof(header), 1, fp) != 1)
|
||||
{
|
||||
fatalError(CANNOT_READ, filename);
|
||||
}
|
||||
|
||||
/* This is a typical DOS kludge! */
|
||||
if (LH(&header.relocTabOffset) == 0x40)
|
||||
{
|
||||
fatalError(NEWEXE_FORMAT);
|
||||
}
|
||||
|
||||
/* Calculate the load module size.
|
||||
* This is the number of pages in the file
|
||||
* less the length of the header and reloc table
|
||||
* less the number of bytes unused on last page
|
||||
*/
|
||||
cb = (dword)LH(&header.numPages) * 512 - (dword)LH(&header.numParaHeader) * 16;
|
||||
if (header.lastPageSize)
|
||||
{
|
||||
cb -= 512 - LH(&header.lastPageSize);
|
||||
}
|
||||
|
||||
/* We quietly ignore minAlloc and maxAlloc since for our
|
||||
* purposes it doesn't really matter where in real memory
|
||||
* the program would end up. EXE programs can't really rely on
|
||||
* their load location so setting the PSP segment to 0 is fine.
|
||||
* Certainly programs that prod around in DOS or BIOS are going
|
||||
* to have to load DS from a constant so it'll be pretty
|
||||
* obvious.
|
||||
*/
|
||||
prog.initCS = (int16)LH(&header.initCS) + EXE_RELOCATION;
|
||||
prog.initIP = (int16)LH(&header.initIP);
|
||||
prog.initSS = (int16)LH(&header.initSS) + EXE_RELOCATION;
|
||||
prog.initSP = (int16)LH(&header.initSP);
|
||||
prog.cReloc = (int16)LH(&header.numReloc);
|
||||
|
||||
/* Allocate the relocation table */
|
||||
if (prog.cReloc)
|
||||
{
|
||||
prog.relocTable = (dword*)allocMem(prog.cReloc * sizeof(Int));
|
||||
fseek(fp, LH(&header.relocTabOffset), SEEK_SET);
|
||||
|
||||
/* Read in seg:offset pairs and convert to Image ptrs */
|
||||
for (i = 0; i < prog.cReloc; i++)
|
||||
{
|
||||
fread(buf, 1, 4, fp);
|
||||
prog.relocTable[i] = LH(buf) +
|
||||
(((Int)LH(buf+2) + EXE_RELOCATION)<<4);
|
||||
}
|
||||
}
|
||||
/* Seek to start of image */
|
||||
fseek(fp, (Int)LH(&header.numParaHeader) * 16, SEEK_SET);
|
||||
}
|
||||
else
|
||||
{ /* COM file
|
||||
* In this case the load module size is just the file length
|
||||
*/
|
||||
fseek(fp, 0, SEEK_END);
|
||||
cb = ftell(fp);
|
||||
|
||||
/* COM programs start off with an ORG 100H (to leave room for a PSP)
|
||||
* This is also the implied start address so if we load the image
|
||||
* at offset 100H addresses should all line up properly again.
|
||||
*/
|
||||
prog.initCS = 0;
|
||||
prog.initIP = 0x100;
|
||||
prog.initSS = 0;
|
||||
prog.initSP = 0xFFFE;
|
||||
prog.cReloc = 0;
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
/* Allocate a block of memory for the program. */
|
||||
prog.cbImage = cb + sizeof(PSP);
|
||||
prog.Image = (byte*)allocMem(prog.cbImage);
|
||||
prog.Image[0] = 0xCD; /* Fill in PSP Int 20h location */
|
||||
prog.Image[1] = 0x20; /* for termination checking */
|
||||
|
||||
/* Read in the image past where a PSP would go */
|
||||
#ifdef __DOSWIN__
|
||||
if (cb > 0xFFFF)
|
||||
{
|
||||
printf("Image size of %ld bytes too large for fread!\n", cb);
|
||||
fatalError(CANNOT_READ, filename);
|
||||
}
|
||||
#endif
|
||||
if (cb != (Int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp))
|
||||
{
|
||||
fatalError(CANNOT_READ, filename);
|
||||
}
|
||||
|
||||
/* Set up memory map */
|
||||
cb = (prog.cbImage + 3) / 4;
|
||||
prog.map = (byte *)memset(allocMem(cb), BM_UNKNOWN, (size_t)cb);
|
||||
|
||||
/* Relocate segment constants */
|
||||
if (prog.cReloc)
|
||||
{
|
||||
for (i = 0; i < prog.cReloc; i++)
|
||||
{
|
||||
byte *p = &prog.Image[prog.relocTable[i]];
|
||||
word w = (word)LH(p) + EXE_RELOCATION;
|
||||
*p++ = (byte)(w & 0x00FF);
|
||||
*p = (byte)((w & 0xFF00) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* allocMem - malloc with failure test
|
||||
****************************************************************************/
|
||||
void *allocMem(Int cb)
|
||||
{
|
||||
byte *p;
|
||||
|
||||
//printf("Attempt to allocMem %5ld bytes\n", cb);
|
||||
|
||||
if (! (p = (byte*)malloc((size_t)cb)))
|
||||
/* if (! (p = (byte*)calloc((size_t)cb, 1))) */
|
||||
{
|
||||
fatalError(MALLOC_FAILED, cb);
|
||||
}
|
||||
/*printf("allocMem: %p\n", p);/**/
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* reallocVar - reallocs extra variable space
|
||||
****************************************************************************/
|
||||
void *reallocVar(void *p, Int newsize)
|
||||
{
|
||||
/*printf("Attempt to reallocVar %5d bytes\n", newsize);/**/
|
||||
if (! (p = realloc((byte *)p, (size_t)newsize)))
|
||||
{
|
||||
fatalError(MALLOC_FAILED, newsize);
|
||||
}
|
||||
|
||||
/*printf("reallocVar: %p\n", p);/**/
|
||||
return p;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void free(void *p)
|
||||
{
|
||||
_ffree(p);
|
||||
switch (_heapset('Z'))
|
||||
{
|
||||
case _HEAPBADBEGIN: printf("f: Bad heap begin\n"); getchar(); break;
|
||||
case _HEAPBADNODE: printf("f: Bad heap node\n"); getchar(); break;
|
||||
case _HEAPEMPTY: printf("f: Heap empty\n"); getchar(); break;
|
||||
case _HEAPOK:putchar('!');break;
|
||||
}/**/
|
||||
}
|
||||
#endif
|
||||
|
||||
379
src/graph.cpp
Normal file
379
src/graph.cpp
Normal file
@ -0,0 +1,379 @@
|
||||
/*****************************************************************************
|
||||
* dcc project CFG related functions
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include <string.h>
|
||||
#if __BORLAND__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h> /* For free() */
|
||||
#endif
|
||||
#include "graph.h"
|
||||
|
||||
static BB * rmJMP(Function * pProc, Int marker, BB * pBB);
|
||||
static void mergeFallThrough(Function * pProc, BB * pBB);
|
||||
static void dfsNumbering(BB * pBB, std::vector<BB*> &dfsLast, Int *first, Int *last);
|
||||
|
||||
/*****************************************************************************
|
||||
* createCFG - Create the basic control flow graph
|
||||
****************************************************************************/
|
||||
void Function::createCFG()
|
||||
{
|
||||
/* Splits Icode associated with the procedure into Basic Blocks.
|
||||
* The links between BBs represent the control flow graph of the
|
||||
* procedure.
|
||||
* A Basic Block is defined to end on one of the following instructions:
|
||||
* 1) Conditional and unconditional jumps
|
||||
* 2) CALL(F)
|
||||
* 3) RET(F)
|
||||
* 4) On the instruction before a join (a flagged TARGET)
|
||||
* 5) Repeated string instructions
|
||||
* 6) End of procedure
|
||||
*/
|
||||
Int i;
|
||||
Int ip, start;
|
||||
BB * psBB;
|
||||
BB * pBB;
|
||||
ICODE * pIcode = Icode.GetFirstIcode();
|
||||
|
||||
stats.numBBbef = stats.numBBaft = 0;
|
||||
for (ip = start = 0; Icode.IsValid(pIcode); ip++, pIcode++)
|
||||
{
|
||||
/* Stick a NOWHERE_NODE on the end if we terminate
|
||||
* with anything other than a ret, jump or terminate */
|
||||
if (ip + 1 == Icode.GetNumIcodes() &&
|
||||
! (pIcode->ic.ll.flg & TERMINATES) &&
|
||||
pIcode->ic.ll.opcode != iJMP && pIcode->ic.ll.opcode != iJMPF &&
|
||||
pIcode->ic.ll.opcode != iRET && pIcode->ic.ll.opcode != iRETF)
|
||||
pBB=BB::Create(start, ip, NOWHERE_NODE, 0, this);
|
||||
|
||||
/* Only process icodes that have valid instructions */
|
||||
else if ((pIcode->ic.ll.flg & NO_CODE) != NO_CODE)
|
||||
{
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iJB: case iJBE: case iJAE: case iJA:
|
||||
case iJL: case iJLE: case iJGE: case iJG:
|
||||
case iJE: case iJNE: case iJS: case iJNS:
|
||||
case iJO: case iJNO: case iJP: case iJNP:
|
||||
case iJCXZ:
|
||||
pBB = BB::Create(start, ip, TWO_BRANCH, 2, this);
|
||||
CondJumps:
|
||||
start = ip + 1;
|
||||
pBB->edges[0].ip = (dword)start;
|
||||
/* This is for jumps off into nowhere */
|
||||
if (pIcode->ic.ll.flg & NO_LABEL)
|
||||
pBB->numOutEdges--;
|
||||
else
|
||||
pBB->edges[1].ip = pIcode->ic.ll.immed.op;
|
||||
break;
|
||||
|
||||
case iLOOP: case iLOOPE: case iLOOPNE:
|
||||
pBB = BB::Create(start, ip, LOOP_NODE, 2, this);
|
||||
goto CondJumps;
|
||||
|
||||
case iJMPF: case iJMP:
|
||||
if (pIcode->ic.ll.flg & SWITCH)
|
||||
{
|
||||
pBB = BB::Create(start, ip, MULTI_BRANCH,
|
||||
pIcode->ic.ll.caseTbl.numEntries, this);
|
||||
for (i = 0; i < pIcode->ic.ll.caseTbl.numEntries; i++)
|
||||
pBB->edges[i].ip = pIcode->ic.ll.caseTbl.entries[i];
|
||||
hasCase = TRUE;
|
||||
}
|
||||
else if ((pIcode->ic.ll.flg & (I | NO_LABEL)) == I) {
|
||||
pBB = BB::Create(start, ip, ONE_BRANCH, 1, this);
|
||||
pBB->edges[0].ip = pIcode->ic.ll.immed.op;
|
||||
}
|
||||
else
|
||||
BB::Create(start, ip, NOWHERE_NODE, 0, this);
|
||||
start = ip + 1;
|
||||
break;
|
||||
|
||||
case iCALLF: case iCALL:
|
||||
{
|
||||
Function * p = pIcode->ic.ll.immed.proc.proc;
|
||||
if (p)
|
||||
i = ((p->flg) & TERMINATES) ? 0 : 1;
|
||||
else
|
||||
i = 1;
|
||||
pBB = BB::Create(start, ip, CALL_NODE, i, this);
|
||||
start = ip + 1;
|
||||
if (i)
|
||||
pBB->edges[0].ip = (dword)start;
|
||||
}
|
||||
break;
|
||||
|
||||
case iRET: case iRETF:
|
||||
BB::Create(start, ip, RETURN_NODE, 0, this);
|
||||
start = ip + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Check for exit to DOS */
|
||||
if (pIcode->ic.ll.flg & TERMINATES)
|
||||
{
|
||||
pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this);
|
||||
start = ip + 1;
|
||||
}
|
||||
/* Check for a fall through */
|
||||
else if (Icode.GetFirstIcode()[ip + 1].ic.ll.flg & (TARGET | CASE))
|
||||
{
|
||||
pBB = BB::Create(start, ip, FALL_NODE, 1, this);
|
||||
start = ip + 1;
|
||||
pBB->edges[0].ip = (dword)start;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<BB *>::iterator iter=heldBBs.begin();
|
||||
/* Convert list of BBs into a graph */
|
||||
for (; iter!=heldBBs.end(); ++iter)
|
||||
{
|
||||
pBB = *iter;
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
{
|
||||
ip = pBB->edges[i].ip;
|
||||
if (ip >= SYNTHESIZED_MIN)
|
||||
fatalError (INVALID_SYNTHETIC_BB);
|
||||
else
|
||||
{
|
||||
auto iter2=std::find_if(heldBBs.begin(),heldBBs.end(),
|
||||
[ip](BB *psBB)->bool {return psBB->start==ip;});
|
||||
if(iter2==heldBBs.end())
|
||||
fatalError(NO_BB, ip, name);
|
||||
psBB = *iter2;
|
||||
pBB->edges[i].BBptr = psBB;
|
||||
psBB->numInEdges++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Function::markImpure()
|
||||
{
|
||||
SYM * psym;
|
||||
for (int i = 0; i < Icode.GetNumIcodes(); i++)
|
||||
{
|
||||
if (Icode.GetLlFlag(i) & (SYM_USE | SYM_DEF))
|
||||
{
|
||||
psym = &symtab.sym[Icode.GetIcode(i)->ic.ll.caseTbl.numEntries];
|
||||
for (int c = (Int)psym->label; c < (Int)psym->label+psym->size; c++)
|
||||
{
|
||||
if (BITMAP(c, BM_CODE))
|
||||
{
|
||||
Icode.SetLlFlag(i, IMPURE);
|
||||
flg |= IMPURE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* newBB - Allocate new BB and link to end of list
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* freeCFG - Deallocates a cfg
|
||||
****************************************************************************/
|
||||
void Function::freeCFG()
|
||||
{
|
||||
std::for_each(heldBBs.begin(),heldBBs.end(),[](BB *p)->void {delete p;});
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* compressCFG - Remove redundancies and add in-edge information
|
||||
****************************************************************************/
|
||||
void Function::compressCFG()
|
||||
{
|
||||
BB * pBB, *pNxt;
|
||||
Int ip, first=0, last, i;
|
||||
|
||||
/* First pass over BB list removes redundant jumps of the form
|
||||
* (Un)Conditional -> Unconditional jump */
|
||||
std::vector<BB*>::iterator iter=cfg.begin();
|
||||
for (;iter!=cfg.end(); ++iter)
|
||||
{
|
||||
pBB = *iter;
|
||||
pBB->inEdges.resize(pBB->numInEdges,0);
|
||||
if (pBB->numInEdges != 0 && (pBB->nodeType == ONE_BRANCH || pBB->nodeType == TWO_BRANCH))
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
{
|
||||
ip = pBB->start + pBB->length - 1;
|
||||
pNxt = rmJMP(this, ip, pBB->edges[i].BBptr);
|
||||
|
||||
if (pBB->numOutEdges) /* Might have been clobbered */
|
||||
{
|
||||
pBB->edges[i].BBptr = pNxt;
|
||||
Icode.SetImmediateOp(ip, (dword)pNxt->start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next is a depth-first traversal merging any FALL_NODE or
|
||||
* ONE_BRANCH that fall through to a node with that as their only
|
||||
* in-edge. */
|
||||
this->cfg.front()->mergeFallThrough(Icode);
|
||||
|
||||
/* Remove redundant BBs created by the above compressions
|
||||
* and allocate in-edge arrays as required. */
|
||||
stats.numBBaft = stats.numBBbef;
|
||||
|
||||
for(auto iter=cfg.begin(); iter!=cfg.end(); ++iter)
|
||||
{
|
||||
pBB = *iter;
|
||||
if (pBB->numInEdges == 0)
|
||||
{
|
||||
if (iter == cfg.begin()) /* Init it misses out on */
|
||||
pBB->index = UN_INIT;
|
||||
else
|
||||
{
|
||||
if (pBB->numOutEdges)
|
||||
pBB->edges.clear();
|
||||
delete pBB;
|
||||
stats.numBBaft--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pBB->inEdgeCount = pBB->numInEdges;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate storage for dfsLast[] array */
|
||||
numBBs = stats.numBBaft;
|
||||
dfsLast.resize(numBBs,0); // = (BB **)allocMem(numBBs * sizeof(BB *))
|
||||
|
||||
/* Now do a dfs numbering traversal and fill in the inEdges[] array */
|
||||
last = numBBs - 1;
|
||||
cfg.front()->dfsNumbering(dfsLast, &first, &last);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* rmJMP - If BB addressed is just a JMP it is replaced with its target
|
||||
***************************************************************************/
|
||||
static BB * rmJMP(Function * pProc, Int marker, BB * pBB)
|
||||
{
|
||||
marker += DFS_JMP;
|
||||
|
||||
while (pBB->nodeType == ONE_BRANCH && pBB->length == 1) {
|
||||
if (pBB->traversed != marker) {
|
||||
pBB->traversed = marker;
|
||||
if (--pBB->numInEdges)
|
||||
pBB->edges[0].BBptr->numInEdges++;
|
||||
else
|
||||
{
|
||||
pProc->Icode.SetLlFlag(pBB->start, NO_CODE);
|
||||
pProc->Icode.SetLlInvalid(pBB->start, TRUE);
|
||||
}
|
||||
|
||||
pBB = pBB->edges[0].BBptr;
|
||||
}
|
||||
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);
|
||||
do {
|
||||
pBB = pBB->edges[0].BBptr;
|
||||
if (! --pBB->numInEdges)
|
||||
{
|
||||
pProc->Icode.SetLlFlag(pBB->start, NO_CODE);
|
||||
pProc->Icode.SetLlInvalid(pBB->start, TRUE);
|
||||
}
|
||||
} while (pBB->nodeType != NOWHERE_NODE);
|
||||
|
||||
pBB->edges.clear();
|
||||
pBB->numOutEdges = 0;
|
||||
}
|
||||
}
|
||||
return pBB;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* mergeFallThrough
|
||||
****************************************************************************/
|
||||
void BB::mergeFallThrough( CIcodeRec &Icode)
|
||||
{
|
||||
BB * pChild;
|
||||
Int i, _ip;
|
||||
|
||||
if (!this)
|
||||
{
|
||||
printf("mergeFallThrough on empty BB!\n");
|
||||
}
|
||||
while (nodeType == FALL_NODE || nodeType == ONE_BRANCH)
|
||||
{
|
||||
pChild = edges[0].BBptr;
|
||||
/* Jump to next instruction can always be removed */
|
||||
if (nodeType == ONE_BRANCH)
|
||||
{
|
||||
_ip = start + length;
|
||||
for (i = _ip; i < pChild->start && (Icode.GetLlFlag(i) & NO_CODE); i++);
|
||||
if (i != pChild->start)
|
||||
break;
|
||||
Icode.SetLlFlag(_ip - 1, NO_CODE);
|
||||
Icode.SetLlInvalid(_ip - 1, TRUE);
|
||||
nodeType = FALL_NODE;
|
||||
length--;
|
||||
|
||||
}
|
||||
/* If there's no other edges into child can merge */
|
||||
if (pChild->numInEdges != 1)
|
||||
break;
|
||||
|
||||
nodeType = pChild->nodeType;
|
||||
length = pChild->start + pChild->length - start;
|
||||
Icode.ClearLlFlag(pChild->start, TARGET);
|
||||
numOutEdges = pChild->numOutEdges;
|
||||
edges.swap(pChild->edges);
|
||||
|
||||
pChild->numOutEdges = pChild->numInEdges = 0;
|
||||
pChild->edges.clear();
|
||||
}
|
||||
traversed = DFS_MERGE;
|
||||
|
||||
/* Process all out edges recursively */
|
||||
for (i = 0; i < numOutEdges; i++)
|
||||
if (edges[i].BBptr->traversed != DFS_MERGE)
|
||||
edges[i].BBptr->mergeFallThrough(Icode);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* dfsNumbering - Numbers nodes during first and last visits and determine
|
||||
* in-edges
|
||||
****************************************************************************/
|
||||
void BB::dfsNumbering(std::vector<BB *> &dfsLast, Int *first, Int *last)
|
||||
{
|
||||
BB * pChild;
|
||||
byte i;
|
||||
|
||||
traversed = DFS_NUM;
|
||||
dfsFirstNum = (*first)++;
|
||||
|
||||
/* index is being used as an index to inEdges[]. */
|
||||
for (i = 0; i < numOutEdges; i++)
|
||||
{
|
||||
pChild = edges[i].BBptr;
|
||||
pChild->inEdges[pChild->index++] = this;
|
||||
|
||||
/* Is this the last visit? */
|
||||
if (pChild->index == pChild->numInEdges)
|
||||
pChild->index = UN_INIT;
|
||||
|
||||
if (pChild->traversed != DFS_NUM)
|
||||
pChild->dfsNumbering(dfsLast, first, last);
|
||||
}
|
||||
dfsLastNum = *last;
|
||||
dfsLast[(*last)--] = this;
|
||||
}
|
||||
501
src/hlicode.cpp
Normal file
501
src/hlicode.cpp
Normal file
@ -0,0 +1,501 @@
|
||||
/*
|
||||
* File: hlIcode.c
|
||||
* Purpose: High-level icode routines
|
||||
* Date: September-October 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "dcc.h"
|
||||
using namespace std;
|
||||
#define ICODE_DELTA 25
|
||||
|
||||
/* Masks off bits set by duReg[] */
|
||||
dword maskDuReg[] = { 0x00,
|
||||
0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* word regs */
|
||||
0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F,
|
||||
0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */
|
||||
0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* byte regs */
|
||||
0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF,
|
||||
0xEFFFFF, /* tmp reg */
|
||||
0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */
|
||||
0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 };
|
||||
|
||||
static char buf[lineSize]; /* Line buffer for hl icode output */
|
||||
|
||||
|
||||
|
||||
/* Places the new HLI_ASSIGN high-level operand in the high-level icode array */
|
||||
void ICODE::setAsgn(COND_EXPR *lhs, COND_EXPR *rhs)
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
ic.hl.opcode = HLI_ASSIGN;
|
||||
assert(ic.hl.oper.asgn.lhs==0); //prevent memory leaks
|
||||
assert(ic.hl.oper.asgn.rhs==0); //prevent memory leaks
|
||||
ic.hl.oper.asgn.lhs = lhs;
|
||||
ic.hl.oper.asgn.rhs = rhs;
|
||||
}
|
||||
/* Places the new HLI_CALL high-level operand in the high-level icode array */
|
||||
void ICODE::newCallHl()
|
||||
{
|
||||
type = HIGH_LEVEL;
|
||||
ic.hl.opcode = HLI_CALL;
|
||||
ic.hl.oper.call.proc = ic.ll.immed.proc.proc;
|
||||
ic.hl.oper.call.args = new STKFRAME;
|
||||
if (ic.ll.immed.proc.cb != 0)
|
||||
ic.hl.oper.call.args->cb = ic.ll.immed.proc.cb;
|
||||
else
|
||||
ic.hl.oper.call.args->cb =ic.hl.oper.call.proc->cbParam;
|
||||
}
|
||||
|
||||
|
||||
/* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode
|
||||
* array */
|
||||
void ICODE::setUnary(hlIcode op, COND_EXPR *exp)
|
||||
{
|
||||
assert(ic.hl.oper.exp==0);
|
||||
type = HIGH_LEVEL;
|
||||
ic.hl.opcode = op;
|
||||
ic.hl.oper.exp = exp;
|
||||
}
|
||||
|
||||
|
||||
/* Places the new HLI_JCOND high-level operand in the high-level icode array */
|
||||
void ICODE::setJCond(COND_EXPR *cexp)
|
||||
{
|
||||
assert(ic.hl.oper.exp==0);
|
||||
type = HIGH_LEVEL;
|
||||
ic.hl.opcode = HLI_JCOND;
|
||||
ic.hl.oper.exp = cexp;
|
||||
}
|
||||
|
||||
|
||||
/* Sets the invalid field to TRUE as this low-level icode is no longer valid,
|
||||
* it has been replaced by a high-level icode. */
|
||||
void ICODE ::invalidate()
|
||||
{
|
||||
invalid = TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Removes the defined register regi from the lhs subtree. If all registers
|
||||
* of this instruction are unused, the instruction is invalidated (ie.
|
||||
* removed) */
|
||||
boolT removeDefRegi (byte regi, ICODE *picode, Int thisDefIdx, LOCAL_ID *locId)
|
||||
{ Int numDefs;
|
||||
|
||||
numDefs = picode->du1.numRegsDef;
|
||||
if (numDefs == thisDefIdx)
|
||||
for ( ; numDefs > 0; numDefs--)
|
||||
{
|
||||
if ((picode->du1.idx[numDefs-1][0] != 0)||(picode->du.lastDefRegi))
|
||||
break;
|
||||
}
|
||||
|
||||
if (numDefs == 0)
|
||||
{
|
||||
picode->invalidate();
|
||||
return (TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (picode->ic.hl.opcode) {
|
||||
case HLI_ASSIGN: removeRegFromLong (regi, locId,
|
||||
picode->ic.hl.oper.asgn.lhs);
|
||||
picode->du1.numRegsDef--;
|
||||
picode->du.def &= maskDuReg[regi];
|
||||
break;
|
||||
case HLI_POP:
|
||||
case HLI_PUSH: removeRegFromLong (regi, locId, picode->ic.hl.oper.exp);
|
||||
picode->du1.numRegsDef--;
|
||||
picode->du.def &= maskDuReg[regi];
|
||||
break;
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
|
||||
* Note: this process should be done before data flow analysis, which
|
||||
* refines the HIGH_LEVEL icodes. */
|
||||
void Function::highLevelGen()
|
||||
{ Int i, /* idx into icode array */
|
||||
numIcode; /* number of icode instructions */
|
||||
ICODE * pIcode; /* ptr to current icode node */
|
||||
COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */
|
||||
flags32 flg; /* icode flags */
|
||||
|
||||
numIcode = Icode.GetNumIcodes();
|
||||
for (i = 0; i < numIcode; i++)
|
||||
{
|
||||
pIcode = Icode.GetIcode(i);
|
||||
if ((pIcode->ic.ll.flg & NOT_HLL) == NOT_HLL)
|
||||
pIcode->invalidate();
|
||||
if ((pIcode->type == LOW_LEVEL) && (pIcode->invalid == FALSE))
|
||||
{
|
||||
flg = pIcode->ic.ll.flg;
|
||||
if ((flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */
|
||||
if ((flg & NO_OPS) != NO_OPS) /* if there are opers */
|
||||
{
|
||||
if ((flg & NO_SRC) != NO_SRC) /* if there is src op */
|
||||
rhs = COND_EXPR::id (pIcode, SRC, this, i, pIcode, NONE);
|
||||
lhs = COND_EXPR::id (pIcode, DST, this, i, pIcode, NONE);
|
||||
}
|
||||
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iADD: rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iAND: rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iCALL:
|
||||
case iCALLF: pIcode->newCallHl();
|
||||
break;
|
||||
|
||||
case iDEC:
|
||||
rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iDIV:
|
||||
case iIDIV:/* should be signed div */
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, DIV);
|
||||
if (pIcode->ic.ll.flg & B)
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAL, 0, &localId);
|
||||
pIcode->setRegDU( rAL, eDEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAX, 0, &localId);
|
||||
pIcode->setRegDU( rAX, eDEF);
|
||||
}
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iIMUL: rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (pIcode, LHS_OP, this, i, pIcode,
|
||||
NONE);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iINC: rhs = COND_EXPR::idKte (1, 2);
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, ADD);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iLEA: rhs = COND_EXPR::unary (ADDRESSOF, rhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMOD: rhs = COND_EXPR::boolOp (lhs, rhs, MOD);
|
||||
if (pIcode->ic.ll.flg & B)
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rAH, 0, &localId);
|
||||
pIcode->setRegDU( rAH, eDEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
lhs = COND_EXPR::idReg (rDX, 0, &localId);
|
||||
pIcode->setRegDU( rDX, eDEF);
|
||||
}
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMOV: pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iMUL: rhs = COND_EXPR::boolOp (lhs, rhs, MUL);
|
||||
lhs = COND_EXPR::id (pIcode, LHS_OP, this, i, pIcode,
|
||||
NONE);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iNEG: rhs = COND_EXPR::unary (NEGATION, lhs);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iNOT: rhs = COND_EXPR::boolOp (NULL, rhs, NOT);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iOR: rhs = COND_EXPR::boolOp (lhs, rhs, OR);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iPOP: pIcode->setUnary(HLI_POP, lhs);
|
||||
break;
|
||||
|
||||
case iPUSH: pIcode->setUnary(HLI_PUSH, lhs);
|
||||
break;
|
||||
|
||||
case iRET:
|
||||
case iRETF: pIcode->setUnary(HLI_RET, NULL);
|
||||
break;
|
||||
|
||||
case iSHL: rhs = COND_EXPR::boolOp (lhs, rhs, SHL);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSAR: /* signed */
|
||||
case iSHR: rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSIGNEX: pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iSUB: rhs = COND_EXPR::boolOp (lhs, rhs, SUB);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
|
||||
case iXCHG:
|
||||
break;
|
||||
|
||||
case iXOR: rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Modifies the given conditional operator to its inverse. This is used
|
||||
* in if..then[..else] statements, to reflect the condition that takes the
|
||||
* then part. */
|
||||
void inverseCondOp (COND_EXPR **exp)
|
||||
{
|
||||
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
|
||||
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
|
||||
DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
|
||||
DUMMY, DBL_OR, DBL_AND};
|
||||
if (*exp == NULL)
|
||||
return;
|
||||
|
||||
if ((*exp)->type == BOOLEAN_OP)
|
||||
{
|
||||
switch ((*exp)->expr.boolExpr.op)
|
||||
{
|
||||
case LESS_EQUAL: case LESS: case EQUAL:
|
||||
case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
|
||||
(*exp)->expr.boolExpr.op = invCondOp[(*exp)->expr.boolExpr.op];
|
||||
break;
|
||||
|
||||
case AND: case OR: case XOR: case NOT: case ADD:
|
||||
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
|
||||
*exp = COND_EXPR::unary (NEGATION, *exp);
|
||||
break;
|
||||
|
||||
case DBL_AND: case DBL_OR:
|
||||
(*exp)->expr.boolExpr.op = invCondOp[(*exp)->expr.boolExpr.op];
|
||||
inverseCondOp (&(*exp)->expr.boolExpr.lhs);
|
||||
inverseCondOp (&(*exp)->expr.boolExpr.rhs);
|
||||
break;
|
||||
} /* eos */
|
||||
|
||||
}
|
||||
else if ((*exp)->type == NEGATION) //TODO: memleak here
|
||||
*exp = (*exp)->expr.unaryExp;
|
||||
|
||||
/* other types are left unmodified */
|
||||
}
|
||||
|
||||
|
||||
/* Returns the string that represents the procedure call of tproc (ie. with
|
||||
* actual parameters) */
|
||||
std::string writeCall (Function * tproc, STKFRAME * args, Function * pproc, Int *numLoc)
|
||||
{
|
||||
Int i; /* counter of # arguments */
|
||||
string condExp;
|
||||
ostringstream s;
|
||||
s<<tproc->name<<" (";
|
||||
for (i = 0; i < args->sym.size(); i++)
|
||||
{
|
||||
s << walkCondExpr (args->sym[i].actual, pproc, numLoc);
|
||||
if (i < (args->sym.size() - 1))
|
||||
s << ", ";
|
||||
}
|
||||
s << ")";
|
||||
return s.str();
|
||||
}
|
||||
|
||||
|
||||
/* Displays the output of a HLI_JCOND icode. */
|
||||
char *writeJcond (HLTYPE h, Function * pProc, Int *numLoc)
|
||||
{
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
strcat (buf, "if ");
|
||||
inverseCondOp (&h.oper.exp);
|
||||
std::string e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, " {\n");
|
||||
return (buf);
|
||||
}
|
||||
|
||||
|
||||
/* Displays the inverse output of a HLI_JCOND icode. This is used in the case
|
||||
* when the THEN clause of an if..then..else is empty. The clause is
|
||||
* negated and the ELSE clause is used instead. */
|
||||
char *writeJcondInv (HLTYPE h, Function * pProc, Int *numLoc)
|
||||
{
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
strcat (buf, "if ");
|
||||
std::string e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, " {\n");
|
||||
return (buf);
|
||||
}
|
||||
|
||||
|
||||
/* Returns a string with the contents of the current high-level icode.
|
||||
* Note: this routine does not output the contens of HLI_JCOND icodes. This is
|
||||
* done in a separate routine to be able to support the removal of
|
||||
* empty THEN clauses on an if..then..else. */
|
||||
char *write1HlIcode (HLTYPE h, Function * pProc, Int *numLoc)
|
||||
{
|
||||
std::string e;
|
||||
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
switch (h.opcode) {
|
||||
case HLI_ASSIGN:
|
||||
e = walkCondExpr (h.oper.asgn.lhs, pProc, numLoc);
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, " = ");
|
||||
e = walkCondExpr (h.oper.asgn.rhs, pProc, numLoc);
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, ";\n");
|
||||
break;
|
||||
case HLI_CALL:
|
||||
e = writeCall (h.oper.call.proc, h.oper.call.args, pProc,
|
||||
numLoc);
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, ";\n");
|
||||
break;
|
||||
case HLI_RET:
|
||||
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
if (! e.empty())
|
||||
{
|
||||
strcat (buf, "return (");
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, ");\n");
|
||||
}
|
||||
break;
|
||||
case HLI_POP:
|
||||
strcat (buf, "HLI_POP ");
|
||||
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, "\n");
|
||||
break;
|
||||
case HLI_PUSH: strcat (buf, "HLI_PUSH ");
|
||||
e = walkCondExpr (h.oper.exp, pProc, numLoc);
|
||||
strcat (buf, e.c_str());
|
||||
strcat (buf, "\n");
|
||||
break;
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
|
||||
Int power2 (Int i)
|
||||
/* Returns the value of 2 to the power of i */
|
||||
{
|
||||
if (i == 0)
|
||||
return (1);
|
||||
return (2 << (i-1));
|
||||
}
|
||||
|
||||
|
||||
/* Writes the registers/stack variables that are used and defined by this
|
||||
* instruction. */
|
||||
void ICODE::writeDU(Int idx)
|
||||
{
|
||||
static char buf[100];
|
||||
Int i, j;
|
||||
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
for (i = 0; i < (INDEXBASE-1); i++)
|
||||
{
|
||||
if ((du.def & power2(i)) != 0)
|
||||
{
|
||||
strcat (buf, allRegs[i]);
|
||||
strcat (buf, " ");
|
||||
}
|
||||
}
|
||||
if (buf[0] != '\0')
|
||||
printf ("Def (reg) = %s\n", buf);
|
||||
|
||||
memset (buf, ' ', sizeof(buf));
|
||||
buf[0] = '\0';
|
||||
for (i = 0; i < INDEXBASE; i++)
|
||||
{
|
||||
if ((du.use & power2(i)) != 0)
|
||||
{
|
||||
strcat (buf, allRegs[i]);
|
||||
strcat (buf, " ");
|
||||
}
|
||||
}
|
||||
if (buf[0] != '\0')
|
||||
printf ("Use (reg) = %s\n", buf);
|
||||
|
||||
/* Print du1 chain */
|
||||
printf ("# regs defined = %d\n", du1.numRegsDef);
|
||||
for (i = 0; i < MAX_REGS_DEF; i++)
|
||||
{
|
||||
if (du1.idx[i][0] != 0)
|
||||
{
|
||||
printf ("%d: du1[%d][] = ", idx, i);
|
||||
for (j = 0; j < MAX_USES; j++)
|
||||
{
|
||||
if (du1.idx[i][j] == 0)
|
||||
break;
|
||||
printf ("%d ", du1.idx[i][j]);
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* For HLI_CALL, print # parameter bytes */
|
||||
if (ic.hl.opcode == HLI_CALL)
|
||||
printf ("# param bytes = %d\n", ic.hl.oper.call.args->cb);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
|
||||
/* Frees the storage allocated to h->hlIcode */
|
||||
void freeHlIcode (ICODE * icode, Int numIcodes)
|
||||
{
|
||||
Int i;
|
||||
HLTYPE h;
|
||||
|
||||
for (i = 0; i < numIcodes; i++)
|
||||
{
|
||||
h = icode[i].ic.hl;
|
||||
switch (h.opcode)
|
||||
{
|
||||
case HLI_ASSIGN:
|
||||
h.oper.asgn.lhs->release();
|
||||
h.oper.asgn.rhs->release();
|
||||
break;
|
||||
case HLI_POP:
|
||||
case HLI_PUSH:
|
||||
case HLI_JCOND:
|
||||
h.oper.exp->release();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
123
src/icode.cpp
Normal file
123
src/icode.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
// Object oriented icode code for dcc
|
||||
// (C) 1997 Mike Van Emmerik
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "types.h" // Common types like byte, etc
|
||||
#include "ast.h" // Some icode types depend on these
|
||||
#include "icode.h"
|
||||
|
||||
#define ICODE_DELTA 25 // Amount to allocate for new chunk
|
||||
|
||||
|
||||
CIcodeRec::CIcodeRec()
|
||||
{
|
||||
}
|
||||
|
||||
CIcodeRec::~CIcodeRec()
|
||||
{
|
||||
}
|
||||
|
||||
/* Copies the icode that is pointed to by pIcode to the icode array.
|
||||
* If there is need to allocate extra memory, it is done so, and
|
||||
* the alloc variable is adjusted. */
|
||||
ICODE * CIcodeRec::addIcode(ICODE *pIcode)
|
||||
{
|
||||
push_back(*pIcode);
|
||||
return &back();
|
||||
}
|
||||
|
||||
ICODE * CIcodeRec::GetFirstIcode()
|
||||
{
|
||||
return &front();
|
||||
}
|
||||
|
||||
/* Don't need this; just pIcode++ since array is guaranteed to be contiguous
|
||||
ICODE * CIcodeRec::GetNextIcode(ICODE * pCurIcode)
|
||||
{
|
||||
int idx = pCurIcode - icode; // Current index
|
||||
ASSERT(idx+1 < numIcode);
|
||||
return &icode[idx+1];
|
||||
}
|
||||
*/
|
||||
|
||||
boolT CIcodeRec::IsValid(ICODE *pCurIcode)
|
||||
{
|
||||
ptrdiff_t idx = pCurIcode - &this->front(); // Current index
|
||||
return (idx>=0) && (idx < size());
|
||||
}
|
||||
|
||||
int CIcodeRec::GetNumIcodes()
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
void CIcodeRec::SetInBB(int start, int end, BB *pnewBB)
|
||||
{
|
||||
for (int i = start; i <= end; i++)
|
||||
at(i).inBB = pnewBB;
|
||||
}
|
||||
|
||||
void CIcodeRec::SetImmediateOp(int ip, dword dw)
|
||||
{
|
||||
at(ip).ic.ll.immed.op = dw;
|
||||
}
|
||||
|
||||
void CIcodeRec::SetLlFlag(int ip, dword flag)
|
||||
{
|
||||
at(ip).ic.ll.flg |= flag;
|
||||
}
|
||||
|
||||
dword CIcodeRec::GetLlFlag(int ip)
|
||||
{
|
||||
return at(ip).ic.ll.flg;
|
||||
}
|
||||
|
||||
void CIcodeRec::ClearLlFlag(int ip, dword flag)
|
||||
{
|
||||
at(ip).ic.ll.flg &= (~flag);
|
||||
}
|
||||
|
||||
void CIcodeRec::SetLlInvalid(int ip, boolT fInv)
|
||||
{
|
||||
at(ip).invalid = fInv;
|
||||
}
|
||||
|
||||
dword CIcodeRec::GetLlLabel(int ip)
|
||||
{
|
||||
return at(ip).ic.ll.label;
|
||||
}
|
||||
|
||||
llIcode CIcodeRec::GetLlOpcode(int ip)
|
||||
{
|
||||
return at(ip).ic.ll.opcode;
|
||||
}
|
||||
|
||||
|
||||
/* labelSrchRepl - Searches the icodes for instruction with label = target, and
|
||||
replaces *pIndex with an icode index */
|
||||
boolT CIcodeRec::labelSrch(dword target, Int *pIndex)
|
||||
{
|
||||
Int i;
|
||||
|
||||
for (i = 0; i < size(); i++)
|
||||
{
|
||||
if (at(i).ic.ll.label == target)
|
||||
{
|
||||
*pIndex = i;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ICODE * CIcodeRec::GetIcode(int ip)
|
||||
{
|
||||
return &at(ip);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
1344
src/idioms.cpp
Normal file
1344
src/idioms.cpp
Normal file
File diff suppressed because it is too large
Load Diff
424
src/locident.cpp
Normal file
424
src/locident.cpp
Normal file
@ -0,0 +1,424 @@
|
||||
/*
|
||||
* File: locIdent.c
|
||||
* Purpose: support routines for high-level local identifier definitions.
|
||||
* Date: October 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define LOCAL_ID_DELTA 25
|
||||
#define IDX_ARRAY_DELTA 5
|
||||
|
||||
/* Creates a new identifier node of type t and returns it.
|
||||
* Arguments: locSym : local long symbol table
|
||||
* t : type of LONG identifier
|
||||
* f : frame where this variable is located
|
||||
* ix : index into icode array where this var is used */
|
||||
void LOCAL_ID::newIdent(hlType t, frameType f)
|
||||
{
|
||||
ID newid(t,f);
|
||||
id_arr.push_back(newid);
|
||||
}
|
||||
|
||||
|
||||
/* Creates a new register identifier node of TYPE_BYTE_(UN)SIGN or
|
||||
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
|
||||
Int LOCAL_ID::newByteWordReg(hlType t, byte regi)
|
||||
{
|
||||
Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[t,regi](ID &el)->bool {
|
||||
if ((el.type == t) && (el.id.regi == regi))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
if(found!=id_arr.end())
|
||||
return found-id_arr.begin();
|
||||
/* Not in table, create new identifier */
|
||||
newIdent (t, REG_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.regi = regi;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
/* Flags the entry associated with the offset off to illegal, as this
|
||||
* offset is part of a long stack variable.
|
||||
* Note: it is easier enough to remove this entry by moving the rest of
|
||||
* the array 1 position. The problem is that indexes into this
|
||||
* array have already been saved in several positions; therefore,
|
||||
* flagging this entry as illegal is all that can be done. */
|
||||
void LOCAL_ID::flagByteWordId (Int off)
|
||||
{
|
||||
Int idx;
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off](ID &en)->bool {
|
||||
|
||||
if (((en.type == TYPE_WORD_SIGN) || (en.type == TYPE_BYTE_SIGN)) &&
|
||||
(en.id.bwId.off == off) && (en.id.bwId.regOff == 0))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
if(found==id_arr.end())
|
||||
{
|
||||
printf("Entry not found in LOCAL_ID::flagByteWordId \n");
|
||||
return;
|
||||
}
|
||||
found->illegal = TRUE;
|
||||
}
|
||||
|
||||
/* Creates a new stack identifier node of TYPE_BYTE_(UN)SIGN or
|
||||
* TYPE_WORD_(UN)SIGN type. Returns the index to this new entry. */
|
||||
Int LOCAL_ID::newByteWordStk(hlType t, Int off, byte regOff)
|
||||
{
|
||||
Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
auto found=std::find_if(id_arr.begin(),id_arr.end(),[off,regOff](ID &el)->bool {
|
||||
if ((el.id.bwId.off == off) && (el.id.bwId.regOff == regOff))
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
if(found!=id_arr.end())
|
||||
return found-id_arr.begin(); //return Index to found element
|
||||
|
||||
/* Not in table, create new identifier */
|
||||
newIdent (t, STK_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.bwId.regOff = regOff;
|
||||
id_arr[idx].id.bwId.off = off;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
* entry; otherwise creates a new global identifier node of type
|
||||
* TYPE_WORD_(UN)SIGN and returns the index to this new entry.
|
||||
* Arguments: locSym : ptr to the local symbol table
|
||||
* seg: segment value for global variable
|
||||
* off: offset from segment
|
||||
* regi: indexed register into global variable
|
||||
* ix: index into icode array
|
||||
* t: HIGH_LEVEL type */
|
||||
Int LOCAL_ID::newIntIdx(int16 seg, int16 off, byte regi,Int ix, hlType t)
|
||||
{
|
||||
Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.bwGlb.seg == seg) &&
|
||||
(id_arr[idx].id.bwGlb.off == off) &&
|
||||
(id_arr[idx].id.bwGlb.regi == regi))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.bwGlb.seg = seg;
|
||||
id_arr[idx].id.bwGlb.off = off;
|
||||
id_arr[idx].id.bwGlb.regi = regi;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
* entry; otherwise creates a new register identifier node of type
|
||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
||||
Int LOCAL_ID::newLongReg(hlType t, byte regH, byte regL, Int ix)
|
||||
{
|
||||
Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.longId.h == regH) &&
|
||||
(id_arr[idx].id.longId.l == regL))
|
||||
{
|
||||
/* Check for occurrence in the list */
|
||||
if (id_arr[idx].idx.inList(ix))
|
||||
return (idx);
|
||||
else
|
||||
{
|
||||
/* Insert icode index in list */
|
||||
id_arr[idx].idx.push_back(ix);
|
||||
return (idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, REG_FRAME);
|
||||
id_arr[id_arr.size()-1].idx.push_back(ix);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longId.h = regH;
|
||||
id_arr[idx].id.longId.l = regL;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
* entry; otherwise creates a new global identifier node of type
|
||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
||||
Int LOCAL_ID::newLongGlb(int16 seg, int16 offH, int16 offL,Int ix, hlType t)
|
||||
{
|
||||
Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
||||
(id_arr[idx].id.longGlb.offL == offL))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longGlb.seg = seg;
|
||||
id_arr[idx].id.longGlb.offH = offH;
|
||||
id_arr[idx].id.longGlb.offL = offL;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
/* Checks if the entry exists in the locSym, if so, returns the idx to this
|
||||
* entry; otherwise creates a new global identifier node of type
|
||||
* TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
|
||||
Int LOCAL_ID::newLongIdx( int16 seg, int16 offH, int16 offL,byte regi, Int ix, hlType t)
|
||||
{ Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if (/*(locSym->id[idx].type == t) && Not checking type */
|
||||
(id_arr[idx].id.longGlb.seg == seg) &&
|
||||
(id_arr[idx].id.longGlb.offH == offH) &&
|
||||
(id_arr[idx].id.longGlb.offL == offL) &&
|
||||
(id_arr[idx].id.longGlb.regi == regi))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table, create new identifier */
|
||||
newIdent (t, GLB_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longGlb.seg = seg;
|
||||
id_arr[idx].id.longGlb.offH = offH;
|
||||
id_arr[idx].id.longGlb.offL = offL;
|
||||
id_arr[idx].id.longGlb.regi = regi;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
/* Creates a new stack identifier node of type TYPE_LONG_(UN)SIGN.
|
||||
* Returns the index to this entry. */
|
||||
Int LOCAL_ID::newLongStk(hlType t, Int offH, Int offL)
|
||||
{
|
||||
Int idx;
|
||||
|
||||
/* Check for entry in the table */
|
||||
for (idx = 0; idx < id_arr.size(); idx++)
|
||||
{
|
||||
if ((id_arr[idx].type == t) &&
|
||||
(id_arr[idx].id.longStkId.offH == offH) &&
|
||||
(id_arr[idx].id.longStkId.offL == offL))
|
||||
return (idx);
|
||||
}
|
||||
|
||||
/* Not in the table; flag as invalid offH and offL */
|
||||
flagByteWordId (offH);
|
||||
flagByteWordId (offL);
|
||||
|
||||
/* Create new identifier */
|
||||
newIdent (t, STK_FRAME);
|
||||
idx = id_arr.size() - 1;
|
||||
id_arr[idx].id.longStkId.offH = offH;
|
||||
id_arr[idx].id.longStkId.offL = offL;
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
/* Returns the index to an appropriate long identifier.
|
||||
* Note: long constants should be checked first and stored as a long integer
|
||||
* number in an expression record. */
|
||||
Int LOCAL_ID::newLong(opLoc sd, ICODE *pIcode, hlFirst f, Int ix,operDu du, Int off)
|
||||
{
|
||||
Int idx;
|
||||
ICODEMEM *pmH, *pmL;
|
||||
|
||||
if (f == LOW_FIRST)
|
||||
{
|
||||
pmL = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
|
||||
pmH = (sd == SRC) ? &(pIcode+off)->ic.ll.src : &(pIcode+off)->ic.ll.dst;
|
||||
}
|
||||
else /* HIGH_FIRST */
|
||||
{
|
||||
pmH = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst;
|
||||
pmL = (sd == SRC) ? &(pIcode+off)->ic.ll.src : &(pIcode+off)->ic.ll.dst;
|
||||
}
|
||||
|
||||
if (pmL->regi == 0) /* global variable */
|
||||
idx = newLongGlb(pmH->segValue, pmH->off, pmL->off, ix,TYPE_LONG_SIGN);
|
||||
|
||||
else if (pmL->regi < INDEXBASE) /* register */
|
||||
{
|
||||
idx = newLongReg(TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix);
|
||||
if (f == HIGH_FIRST)
|
||||
pIcode->setRegDU( pmL->regi, du); /* low part */
|
||||
else
|
||||
pIcode->setRegDU( pmH->regi, du); /* high part */
|
||||
}
|
||||
|
||||
else if (pmL->off) { /* offset */
|
||||
if ((pmL->seg == rSS) && (pmL->regi == INDEXBASE + 6)) /* idx on bp */
|
||||
idx = newLongStk(TYPE_LONG_SIGN, pmH->off, pmL->off);
|
||||
else if ((pmL->seg == rDS) && (pmL->regi == INDEXBASE + 7)) /* bx */
|
||||
{ /* glb var indexed on bx */
|
||||
idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX, ix, TYPE_LONG_SIGN);
|
||||
pIcode->setRegDU( rBX, eUSE);
|
||||
}
|
||||
else /* idx <> bp, bx */
|
||||
printf ("long not supported, idx <> bp\n");
|
||||
}
|
||||
|
||||
else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */
|
||||
printf ("long not supported, idx && no off\n");
|
||||
|
||||
return (idx);
|
||||
}
|
||||
|
||||
|
||||
boolT checkLongEq (LONG_STKID_TYPE longId, ICODE *pIcode, Int i, Int idx,
|
||||
Function * pProc, COND_EXPR **rhs, COND_EXPR **lhs, Int off)
|
||||
/* Checks whether the long stack identifier is equivalent to the source or
|
||||
* destination operands of pIcode and pIcode+1 (ie. these are LOW_LEVEL
|
||||
* icodes at present). If so, returns the rhs and lhs of this instruction.
|
||||
* Arguments: longId : long stack identifier
|
||||
* pIcode : ptr to first LOW_LEVEL icode instruction
|
||||
* i : idx into local identifier table for longId
|
||||
* idx : idx into icode array
|
||||
* pProc : ptr to current procedure record
|
||||
* rhs, lhs : return expressions if successful. */
|
||||
{
|
||||
ICODEMEM *pmHdst, *pmLdst, *pmHsrc, *pmLsrc; /* pointers to LOW_LEVEL icodes */
|
||||
|
||||
pmHdst = &pIcode->ic.ll.dst;
|
||||
pmLdst = &(pIcode+off)->ic.ll.dst;
|
||||
pmHsrc = &pIcode->ic.ll.src;
|
||||
pmLsrc = &(pIcode+off)->ic.ll.src;
|
||||
|
||||
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
|
||||
{
|
||||
*lhs = COND_EXPR::idLongIdx (i);
|
||||
if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC)
|
||||
*rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST,
|
||||
idx, eUSE, off);
|
||||
return (TRUE);
|
||||
}
|
||||
else if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
|
||||
{
|
||||
*lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx,
|
||||
eDEF, off);
|
||||
*rhs = COND_EXPR::idLongIdx (i);
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
/* Checks whether the long stack identifier is equivalent to the source or
|
||||
* destination operands of pIcode and pIcode+1 (ie. these are LOW_LEVEL
|
||||
* icodes at present). If so, returns the rhs and lhs of this instruction.
|
||||
* Arguments: longId : long stack identifier
|
||||
* pIcode : ptr to first LOW_LEVEL icode instruction
|
||||
* i : idx into local identifier table for longId
|
||||
* idx : idx into icode array
|
||||
* pProc : ptr to current procedure record
|
||||
* rhs, lhs : return expressions if successful. */
|
||||
boolT checkLongRegEq (LONGID_TYPE longId, ICODE *pIcode, Int i, Int idx,
|
||||
Function * pProc, COND_EXPR **rhs, COND_EXPR **lhs, Int off)
|
||||
{
|
||||
ICODEMEM *pmHdst, *pmLdst, *pmHsrc, *pmLsrc; /* pointers to LOW_LEVEL icodes */
|
||||
|
||||
pmHdst = &pIcode->ic.ll.dst;
|
||||
pmLdst = &(pIcode+off)->ic.ll.dst;
|
||||
pmHsrc = &pIcode->ic.ll.src;
|
||||
pmLsrc = &(pIcode+off)->ic.ll.src;
|
||||
|
||||
if ((longId.h == pmHdst->regi) && (longId.l == pmLdst->regi))
|
||||
{
|
||||
*lhs = COND_EXPR::idLongIdx (i);
|
||||
if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC)
|
||||
*rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, idx, eUSE, off);
|
||||
return (TRUE);
|
||||
}
|
||||
else if ((longId.h == pmHsrc->regi) && (longId.l == pmLsrc->regi))
|
||||
{
|
||||
*lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx, eDEF, off);
|
||||
*rhs = COND_EXPR::idLongIdx (i);
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Given an index into the local identifier table for a long register
|
||||
* variable, determines whether regi is the high or low part, and returns
|
||||
* the other part */
|
||||
byte otherLongRegi (byte regi, Int idx, LOCAL_ID *locTbl)
|
||||
{
|
||||
ID *id;
|
||||
|
||||
id = &locTbl->id_arr[idx];
|
||||
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
|
||||
(id->type == TYPE_LONG_UNSIGN)))
|
||||
{
|
||||
if (id->id.longId.h == regi)
|
||||
return (id->id.longId.l);
|
||||
else if (id->id.longId.l == regi)
|
||||
return (id->id.longId.h);
|
||||
}
|
||||
return 0; // Cristina: please check this!
|
||||
}
|
||||
|
||||
|
||||
/* Checks if the registers regL and regH have been used independently in
|
||||
* the local identifier table. If so, macros for these registers are
|
||||
* placed in the local identifier table, as these registers belong to a
|
||||
* long register identifier. */
|
||||
void LOCAL_ID::propLongId (byte regL, byte regH, const char *name)
|
||||
{
|
||||
Int i;
|
||||
ID *_id;
|
||||
|
||||
for (i = 0; i < id_arr.size(); i++)
|
||||
{
|
||||
_id = &id_arr[i];
|
||||
if ((_id->type == TYPE_WORD_SIGN) || (_id->type == TYPE_WORD_UNSIGN))
|
||||
{
|
||||
if (_id->id.regi == regL)
|
||||
{
|
||||
strcpy (_id->name, name);
|
||||
strcpy (_id->macro, "LO");
|
||||
_id->hasMacro = TRUE;
|
||||
_id->illegal = TRUE;
|
||||
}
|
||||
else if (_id->id.regi == regH)
|
||||
{
|
||||
strcpy (_id->name, name);
|
||||
strcpy (_id->macro, "HI");
|
||||
_id->hasMacro = TRUE;
|
||||
_id->illegal = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1208
src/parser.cpp
Normal file
1208
src/parser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
448
src/perfhlib.cpp
Normal file
448
src/perfhlib.cpp
Normal file
@ -0,0 +1,448 @@
|
||||
/*
|
||||
* Perfect hashing function library. Contains functions to generate perfect
|
||||
* hashing functions
|
||||
* (C) Mike van Emmerik
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "perfhlib.h"
|
||||
|
||||
/* 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 */
|
||||
static bool *visited; /* Array of bools: whether visited */
|
||||
|
||||
/* Private prototypes */
|
||||
static void initGraph(void);
|
||||
static void addToGraph(int e, int v1, int v2);
|
||||
static bool isCycle(void);
|
||||
static void duplicateKeys(int v1, int v2);
|
||||
|
||||
void
|
||||
hashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,
|
||||
int _NumVert)
|
||||
{
|
||||
/* These parameters are stored in statics so as to obviate the need for
|
||||
passing all these (or defererencing pointers) for every call to hash()
|
||||
*/
|
||||
|
||||
NumEntry = _NumEntry;
|
||||
EntryLen = _EntryLen;
|
||||
SetSize = _SetSize;
|
||||
SetMin = _SetMin;
|
||||
NumVert = _NumVert;
|
||||
|
||||
/* Allocate the variable sized tables etc */
|
||||
if ((T1base = (word *)malloc(EntryLen * SetSize * sizeof(word))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((T2base = (word *)malloc(EntryLen * SetSize * sizeof(word))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
|
||||
if ((graphNode = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((graphNext = (int *)malloc((NumEntry*2 + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((graphFirst = (int *)malloc((NumVert + 1) * sizeof(int))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
|
||||
if ((g = (short *)malloc((NumVert+1) * sizeof(short))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
if ((visited = (bool *)malloc((NumVert+1) * sizeof(bool))) == 0)
|
||||
{
|
||||
goto BadAlloc;
|
||||
}
|
||||
return;
|
||||
|
||||
BadAlloc:
|
||||
printf("Could not allocate memory\n");
|
||||
hashCleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
hashCleanup(void)
|
||||
{
|
||||
/* Free the storage for variable sized tables etc */
|
||||
if (T1base) free(T1base);
|
||||
if (T2base) free(T2base);
|
||||
if (graphNode) free(graphNode);
|
||||
if (graphNext) free(graphNext);
|
||||
if (graphFirst) free(graphFirst);
|
||||
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)
|
||||
{
|
||||
word u, v;
|
||||
int j;
|
||||
|
||||
u = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T1 = T1base + j * SetSize;
|
||||
u += T1[string[j] - SetMin];
|
||||
}
|
||||
u %= NumVert;
|
||||
|
||||
v = 0;
|
||||
for (j=0; j < EntryLen; j++)
|
||||
{
|
||||
T2 = T2base + j * SetSize;
|
||||
v += T2[string[j] - SetMin];
|
||||
}
|
||||
v %= NumVert;
|
||||
|
||||
return (g[u] + g[v]) % NumEntry;
|
||||
}
|
||||
|
||||
word *
|
||||
readT1(void)
|
||||
{
|
||||
return T1base;
|
||||
}
|
||||
|
||||
word *
|
||||
readT2(void)
|
||||
{
|
||||
return T2base;
|
||||
}
|
||||
|
||||
word *
|
||||
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
|
||||
394
src/procs.cpp
Normal file
394
src/procs.cpp
Normal file
@ -0,0 +1,394 @@
|
||||
/*
|
||||
* File: procs.c
|
||||
* Purpose: Functions to support Call graphs and procedures
|
||||
* Date: November 1993
|
||||
* (C) Cristina Cifuentes
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
/* Static indentation buffer */
|
||||
#define indSize 61 /* size of indentation buffer; max 20 */
|
||||
static char indentBuf[indSize] =
|
||||
" ";
|
||||
|
||||
static char *indent (Int indLevel)
|
||||
/* Indentation according to the depth of the statement */
|
||||
{
|
||||
return (&indentBuf[indSize-(indLevel*3)-1]);
|
||||
}
|
||||
|
||||
|
||||
/* Inserts an outEdge at the current callGraph pointer if the newProc does
|
||||
* not exist. */
|
||||
void CALL_GRAPH::insertArc (ilFunction newProc)
|
||||
{
|
||||
CALL_GRAPH *pcg;
|
||||
Int i;
|
||||
|
||||
/* Check if procedure already exists */
|
||||
for (i = 0; i < outEdges.size(); i++)
|
||||
if (outEdges[i]->proc == newProc)
|
||||
return;
|
||||
|
||||
/* Include new arc */
|
||||
pcg = new CALL_GRAPH;
|
||||
pcg->proc = newProc;
|
||||
outEdges.push_back(pcg);
|
||||
}
|
||||
|
||||
|
||||
/* Inserts a (caller, callee) arc in the call graph tree. */
|
||||
boolT CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee)
|
||||
{
|
||||
Int i;
|
||||
|
||||
if (proc == caller)
|
||||
{
|
||||
insertArc (callee);
|
||||
return (TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < outEdges.size(); i++)
|
||||
if (outEdges[i]->insertCallGraph (caller, callee))
|
||||
return true;
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
boolT CALL_GRAPH::insertCallGraph(Function *caller, ilFunction callee)
|
||||
{
|
||||
auto iter = std::find_if(pProcList.begin(),pProcList.end(),
|
||||
[caller](const Function &f)->bool {return caller==&f;});
|
||||
assert(iter!=pProcList.end());
|
||||
return insertCallGraph(iter,callee);
|
||||
}
|
||||
|
||||
|
||||
/* Displays the current node of the call graph, and invokes recursively on
|
||||
* the nodes the procedure invokes. */
|
||||
void CALL_GRAPH::writeNodeCallGraph(Int indIdx)
|
||||
{
|
||||
Int i;
|
||||
|
||||
printf ("%s%s\n", indent(indIdx), proc->name);
|
||||
for (i = 0; i < outEdges.size(); i++)
|
||||
outEdges[i]->writeNodeCallGraph (indIdx + 1);
|
||||
}
|
||||
|
||||
|
||||
/* Writes the header and invokes recursive procedure */
|
||||
void CALL_GRAPH::write()
|
||||
{
|
||||
printf ("\nCall Graph:\n");
|
||||
writeNodeCallGraph (0);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Routines to support arguments
|
||||
*************************************************************************/
|
||||
|
||||
/* Updates the argument table by including the register(s) (ie. lhs of
|
||||
* picode) and the actual expression (ie. rhs of picode).
|
||||
* Note: register(s) are only included once in the table. */
|
||||
void newRegArg (Function * pproc, ICODE *picode, ICODE *ticode)
|
||||
{
|
||||
COND_EXPR *lhs;
|
||||
STKFRAME * ps, *ts;
|
||||
ID *id;
|
||||
Int i, tidx;
|
||||
boolT regExist;
|
||||
condId type;
|
||||
Function * tproc;
|
||||
byte regL, regH; /* Registers involved in arguments */
|
||||
|
||||
/* Flag ticode as having register arguments */
|
||||
tproc = ticode->ic.hl.oper.call.proc;
|
||||
tproc->flg |= REG_ARGS;
|
||||
|
||||
/* Get registers and index into target procedure's local list */
|
||||
ps = ticode->ic.hl.oper.call.args;
|
||||
ts = &tproc->args;
|
||||
lhs = picode->ic.hl.oper.asgn.lhs;
|
||||
type = lhs->expr.ident.idType;
|
||||
if (type == REGISTER)
|
||||
{
|
||||
regL = pproc->localId.id_arr[lhs->expr.ident.idNode.regiIdx].id.regi;
|
||||
if (regL < rAL)
|
||||
tidx = tproc->localId.newByteWordReg(TYPE_WORD_SIGN, regL);
|
||||
else
|
||||
tidx = tproc->localId.newByteWordReg(TYPE_BYTE_SIGN, regL);
|
||||
}
|
||||
else if (type == LONG_VAR)
|
||||
{
|
||||
regL = pproc->localId.id_arr[lhs->expr.ident.idNode.longIdx].id.longId.l;
|
||||
regH = pproc->localId.id_arr[lhs->expr.ident.idNode.longIdx].id.longId.h;
|
||||
tidx = tproc->localId.newLongReg(TYPE_LONG_SIGN, regH, regL, 0);
|
||||
}
|
||||
|
||||
/* Check if register argument already on the formal argument list */
|
||||
regExist = FALSE;
|
||||
for (i = 0; i < ts->sym.size(); i++)
|
||||
{
|
||||
if (type == REGISTER)
|
||||
{
|
||||
if ((ts->sym[i].regs != NULL) &&
|
||||
(ts->sym[i].regs->expr.ident.idNode.regiIdx == tidx))
|
||||
{
|
||||
regExist = TRUE;
|
||||
i = ts->sym.size();
|
||||
}
|
||||
}
|
||||
else if (type == LONG_VAR)
|
||||
{
|
||||
if ((ts->sym[i].regs != NULL) &&
|
||||
(ts->sym[i].regs->expr.ident.idNode.longIdx == tidx))
|
||||
{
|
||||
regExist = TRUE;
|
||||
i = ts->sym.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do ts (formal arguments) */
|
||||
if (regExist == FALSE)
|
||||
{
|
||||
STKSYM newsym;
|
||||
sprintf (newsym.name, "arg%ld", ts->sym.size());
|
||||
if (type == REGISTER)
|
||||
{
|
||||
if (regL < rAL)
|
||||
{
|
||||
newsym.type = TYPE_WORD_SIGN;
|
||||
newsym.regs = COND_EXPR::idRegIdx(tidx, WORD_REG);
|
||||
}
|
||||
else
|
||||
{
|
||||
newsym.type = TYPE_BYTE_SIGN;
|
||||
newsym.regs = COND_EXPR::idRegIdx(tidx, BYTE_REG);
|
||||
}
|
||||
sprintf (tproc->localId.id_arr[tidx].name, "arg%ld", ts->sym.size());
|
||||
}
|
||||
else if (type == LONG_VAR)
|
||||
{
|
||||
newsym.regs = COND_EXPR::idLongIdx (tidx);
|
||||
newsym.type = TYPE_LONG_SIGN;
|
||||
sprintf (tproc->localId.id_arr[tidx].name, "arg%ld", ts->sym.size());
|
||||
tproc->localId.propLongId (regL, regH,
|
||||
tproc->localId.id_arr[tidx].name);
|
||||
}
|
||||
ts->sym.push_back(newsym);
|
||||
ts->numArgs++;
|
||||
}
|
||||
|
||||
/* Do ps (actual arguments) */
|
||||
STKSYM newsym;
|
||||
sprintf (newsym.name, "arg%ld", ps->sym.size());
|
||||
newsym.actual = picode->ic.hl.oper.asgn.rhs;
|
||||
newsym.regs = lhs;
|
||||
/* Mask off high and low register(s) in picode */
|
||||
switch (type) {
|
||||
case REGISTER:
|
||||
id = &pproc->localId.id_arr[lhs->expr.ident.idNode.regiIdx];
|
||||
picode->du.def &= maskDuReg[id->id.regi];
|
||||
if (id->id.regi < rAL)
|
||||
newsym.type = TYPE_WORD_SIGN;
|
||||
else
|
||||
newsym.type = TYPE_BYTE_SIGN;
|
||||
break;
|
||||
case LONG_VAR:
|
||||
id = &pproc->localId.id_arr[lhs->expr.ident.idNode.longIdx];
|
||||
picode->du.def &= maskDuReg[id->id.longId.h];
|
||||
picode->du.def &= maskDuReg[id->id.longId.l];
|
||||
newsym.type = TYPE_LONG_SIGN;
|
||||
break;
|
||||
}
|
||||
ps->sym.push_back(newsym);
|
||||
ps->numArgs++;
|
||||
}
|
||||
|
||||
|
||||
/* Allocates num arguments in the actual argument list of the current
|
||||
* icode picode. */
|
||||
/** NOTE: this function is not used ****/
|
||||
void allocStkArgs (ICODE *picode, Int num)
|
||||
{
|
||||
STKFRAME * ps;
|
||||
ps = picode->ic.hl.oper.call.args;
|
||||
ps->numArgs = num;
|
||||
ps->sym.resize(num);
|
||||
}
|
||||
|
||||
|
||||
boolT newStkArg (ICODE *picode, COND_EXPR *exp, llIcode opcode, Function * pproc)
|
||||
/* Inserts the new expression (ie. the actual parameter) on the argument
|
||||
* list.
|
||||
* Returns: TRUE if it was a near call that made use of a segment register.
|
||||
* FALSE elsewhere */
|
||||
{ STKFRAME * ps;
|
||||
byte regi;
|
||||
|
||||
/* Check for far procedure call, in which case, references to segment
|
||||
* registers are not be considered another parameter (i.e. they are
|
||||
* long references to another segment) */
|
||||
if (exp)
|
||||
{
|
||||
if ((exp->type == IDENTIFIER) && (exp->expr.ident.idType == REGISTER))
|
||||
{
|
||||
regi = pproc->localId.id_arr[exp->expr.ident.idNode.regiIdx].id.regi;
|
||||
if ((regi >= rES) && (regi <= rDS))
|
||||
if (opcode == iCALLF)
|
||||
return (FALSE);
|
||||
else
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Place register argument on the argument list */
|
||||
ps = picode->ic.hl.oper.call.args;
|
||||
STKSYM newsym;
|
||||
newsym.actual = exp;
|
||||
ps->sym.push_back(newsym);
|
||||
ps->numArgs++;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Places the actual argument exp in the position given by pos in the
|
||||
* argument list of picode. */
|
||||
void placeStkArg (ICODE *picode, COND_EXPR *exp, Int pos)
|
||||
{ STKFRAME * ps;
|
||||
|
||||
ps = picode->ic.hl.oper.call.args;
|
||||
ps->sym[pos].actual = exp;
|
||||
sprintf (ps->sym[pos].name, "arg%ld", pos);
|
||||
}
|
||||
|
||||
|
||||
/* Checks to determine whether the expression (actual argument) has the
|
||||
* same type as the given type (from the procedure's formal list). If not,
|
||||
* the actual argument gets modified */
|
||||
void adjustActArgType (COND_EXPR *exp, hlType forType, Function * pproc)
|
||||
{ hlType actType;
|
||||
Int offset, offL;
|
||||
|
||||
if (exp == NULL)
|
||||
return;
|
||||
|
||||
actType = expType (exp, pproc);
|
||||
if ((actType != forType) && (exp->type == IDENTIFIER))
|
||||
{
|
||||
switch (forType) {
|
||||
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
|
||||
case TYPE_WORD_UNSIGN: case TYPE_LONG_SIGN:
|
||||
case TYPE_LONG_UNSIGN: case TYPE_RECORD:
|
||||
break;
|
||||
|
||||
case TYPE_PTR:
|
||||
case TYPE_CONST:
|
||||
break;
|
||||
|
||||
case TYPE_STR:
|
||||
switch (actType) {
|
||||
case TYPE_CONST:
|
||||
/* It's an offset into image where a string is
|
||||
* found. Point to the string. */
|
||||
offL = exp->expr.ident.idNode.kte.kte;
|
||||
if (prog.fCOM)
|
||||
offset = (pproc->state.r[rDS]<<4) + offL + 0x100;
|
||||
else
|
||||
offset = (pproc->state.r[rDS]<<4) + offL;
|
||||
exp->expr.ident.idNode.strIdx = offset;
|
||||
exp->expr.ident.idType = STRING;
|
||||
break;
|
||||
|
||||
case TYPE_PTR:
|
||||
/* It's a pointer to a char rather than a pointer to
|
||||
* an integer */
|
||||
/***HERE - modify the type ****/
|
||||
break;
|
||||
|
||||
case TYPE_WORD_SIGN:
|
||||
|
||||
break;
|
||||
} /* eos */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Determines whether the formal argument has the same type as the given
|
||||
* type (type of the actual argument). If not, the formal argument is
|
||||
* changed its type */
|
||||
void STKFRAME::adjustForArgType(Int numArg_, hlType actType_)
|
||||
{
|
||||
hlType forType;
|
||||
STKSYM * psym, * nsym;
|
||||
Int off, i;
|
||||
|
||||
/* Find stack offset for this argument */
|
||||
off = minOff;
|
||||
for (i = 0; i < numArg_; i++)
|
||||
off += sym[i].size;
|
||||
|
||||
/* Find formal argument */
|
||||
if (numArg_ < sym.size())
|
||||
{
|
||||
psym = &sym[numArg_];
|
||||
i = numArg_;
|
||||
while ((i < sym.size()) && (psym->off != off))
|
||||
{
|
||||
psym++;
|
||||
i++;
|
||||
}
|
||||
if (numArg_ == sym.size())
|
||||
return;
|
||||
}
|
||||
/* If formal argument does not exist, do not create new ones, just
|
||||
* ignore actual argument */
|
||||
else
|
||||
return;
|
||||
|
||||
forType = psym->type;
|
||||
if (forType != actType_)
|
||||
{
|
||||
switch (actType_) {
|
||||
case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
|
||||
case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
|
||||
case TYPE_WORD_UNSIGN: case TYPE_RECORD:
|
||||
break;
|
||||
|
||||
case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
|
||||
if ((forType == TYPE_WORD_UNSIGN) ||
|
||||
(forType == TYPE_WORD_SIGN) ||
|
||||
(forType == TYPE_UNKNOWN))
|
||||
{
|
||||
/* Merge low and high */
|
||||
psym->type = actType_;
|
||||
psym->size = 4;
|
||||
nsym = psym + 1;
|
||||
sprintf (nsym->macro, "HI");
|
||||
sprintf (psym->macro, "LO");
|
||||
nsym->hasMacro = TRUE;
|
||||
psym->hasMacro = TRUE;
|
||||
sprintf (nsym->name, "%s", psym->name);
|
||||
nsym->invalid = TRUE;
|
||||
numArgs--;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_PTR:
|
||||
case TYPE_CONST:
|
||||
case TYPE_STR:
|
||||
break;
|
||||
} /* eos */
|
||||
}
|
||||
}
|
||||
|
||||
541
src/proplong.cpp
Normal file
541
src/proplong.cpp
Normal file
@ -0,0 +1,541 @@
|
||||
/**************************************************************************
|
||||
* File : propLong.c
|
||||
* Purpose: propagate the value of long variables (local variables and
|
||||
* registers) along the graph. Structure the graph in this way.
|
||||
* (C) Cristina Cifuentes
|
||||
**************************************************************************/
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
static boolT isJCond (llIcode opcode)
|
||||
/* Returns whether the given icode opcode is within the range of valid
|
||||
* high-level conditional jump icodes (iJB..iJG) */
|
||||
{
|
||||
if ((opcode >= iJB) && (opcode <= iJG))
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
if (pbb->nodeType != TWO_BRANCH)
|
||||
return (FALSE);
|
||||
t = pbb->edges[THEN].BBptr;
|
||||
e = pbb->edges[ELSE].BBptr;
|
||||
|
||||
/* Check along the THEN path */
|
||||
if ((t->length == 1) && (t->nodeType == TWO_BRANCH) && (t->numInEdges == 1))
|
||||
{
|
||||
obb2 = t->edges[THEN].BBptr;
|
||||
if ((obb2->length == 2) && (obb2->nodeType == TWO_BRANCH) &&
|
||||
(icode[obb2->start].ic.ll.opcode == iCMP))
|
||||
{
|
||||
*off = obb2->start - i;
|
||||
*arc = THEN;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check along the ELSE path */
|
||||
else if ((e->length == 1) && (e->nodeType == TWO_BRANCH) &&
|
||||
(e->numInEdges == 1))
|
||||
{
|
||||
obb2 = e->edges[THEN].BBptr;
|
||||
if ((obb2->length == 2) && (obb2->nodeType == TWO_BRANCH) &&
|
||||
(icode[obb2->start].ic.ll.opcode == iCMP))
|
||||
{
|
||||
*off = obb2->start - i;
|
||||
*arc = ELSE;
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
/* Returns whether the conditions for a 2-2 long variable are satisfied */
|
||||
static boolT isLong22 (ICODE * pIcode, ICODE * pEnd, Int *off)
|
||||
{
|
||||
if (((pIcode+2) < pEnd) && ((pIcode+2)->ic.ll.opcode == iCMP) &&
|
||||
(isJCond ((pIcode+1)->ic.ll.opcode)) &&
|
||||
(isJCond ((pIcode+3)->ic.ll.opcode)))
|
||||
{
|
||||
*off = 2;
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
/* Creates a long conditional <=, >=, <, or > at (pIcode+1).
|
||||
* Removes excess nodes from the graph by flagging them, and updates
|
||||
* the new edges for the remaining nodes. */
|
||||
static void longJCond23 (COND_EXPR *rhs, COND_EXPR *lhs, ICODE * pIcode,
|
||||
Int *idx, Function * pProc, Int arc, Int off)
|
||||
{ Int j;
|
||||
BB * pbb, * obb1, * obb2, * tbb;
|
||||
|
||||
if (arc == THEN)
|
||||
{
|
||||
/* Find intermediate basic blocks and target block */
|
||||
pbb = pIcode->inBB;
|
||||
obb1 = pbb->edges[THEN].BBptr;
|
||||
obb2 = obb1->edges[THEN].BBptr;
|
||||
tbb = obb2->edges[THEN].BBptr;
|
||||
|
||||
/* Modify out edge of header basic block */
|
||||
pbb->edges[THEN].BBptr = tbb;
|
||||
|
||||
/* Modify in edges of target basic block */
|
||||
auto newlast=std::remove_if(tbb->inEdges.begin(),tbb->inEdges.end(),
|
||||
[obb1,obb2](BB *b) -> bool
|
||||
{
|
||||
return (b==obb1) || (b==obb2);
|
||||
}
|
||||
);
|
||||
tbb->inEdges.erase(newlast,tbb->inEdges.end());
|
||||
tbb->numInEdges--; /* looses 2 arcs, gains 1 arc */
|
||||
tbb->inEdges.push_back(pbb);
|
||||
assert(tbb->inEdges.size()==tbb->numInEdges);
|
||||
|
||||
/* Modify in edges of the ELSE basic block */
|
||||
tbb = pbb->edges[ELSE].BBptr;
|
||||
auto iter=std::find(tbb->inEdges.begin(),tbb->inEdges.end(),obb2);
|
||||
assert(iter!=tbb->inEdges.end());
|
||||
tbb->inEdges.erase(iter);
|
||||
tbb->numInEdges--; /* looses 1 arc */
|
||||
assert(tbb->inEdges.size()==tbb->numInEdges);
|
||||
/* Update icode index */
|
||||
(*idx) += 5;
|
||||
}
|
||||
|
||||
else /* ELSE arc */
|
||||
{
|
||||
/* Find intermediate basic blocks and target block */
|
||||
pbb = pIcode->inBB;
|
||||
obb1 = pbb->edges[ELSE].BBptr;
|
||||
obb2 = obb1->edges[THEN].BBptr;
|
||||
tbb = obb2->edges[THEN].BBptr;
|
||||
|
||||
/* Modify in edges of target basic block */
|
||||
auto iter=std::find(tbb->inEdges.begin(),tbb->inEdges.end(),obb2);
|
||||
assert(iter!=tbb->inEdges.end());
|
||||
tbb->inEdges.erase(iter);
|
||||
tbb->numInEdges--; /* looses 1 arc */
|
||||
assert(tbb->inEdges.size()==tbb->numInEdges);
|
||||
|
||||
/* Modify in edges of the ELSE basic block */
|
||||
tbb = obb2->edges[ELSE].BBptr;
|
||||
auto newlast=std::remove_if(tbb->inEdges.begin(),tbb->inEdges.end(),
|
||||
[obb1,obb2](BB *b) -> bool
|
||||
{
|
||||
return (b==obb1) || (b==obb2);
|
||||
}
|
||||
);
|
||||
tbb->inEdges.erase(newlast,tbb->inEdges.end());
|
||||
tbb->numInEdges--; /* looses 2 arcs, gains 1 arc */
|
||||
tbb->inEdges.push_back(pbb);
|
||||
assert(tbb->inEdges.size()==tbb->numInEdges);
|
||||
|
||||
/* Modify out edge of header basic block */
|
||||
pbb->edges[ELSE].BBptr = tbb;
|
||||
|
||||
/* Update icode index */
|
||||
(*idx) += 2;
|
||||
}
|
||||
|
||||
/* Create new HLI_JCOND and condition */
|
||||
lhs = COND_EXPR::boolOp (lhs, rhs, condOpJCond[(pIcode+off+1)->ic.ll.opcode-iJB]);
|
||||
(pIcode+1)->setJCond(lhs);
|
||||
copyDU (pIcode+1, pIcode, eUSE, eUSE);
|
||||
(pIcode+1)->du.use |= (pIcode+off)->du.use;
|
||||
|
||||
/* Update statistics */
|
||||
obb1->flg |= INVALID_BB;
|
||||
obb2->flg |= INVALID_BB;
|
||||
stats.numBBaft -= 2;
|
||||
|
||||
pIcode->invalidate();
|
||||
pProc->Icode.GetIcode(obb1->start)->invalidate();
|
||||
pProc->Icode.GetIcode(obb2->start)->invalidate();
|
||||
pProc->Icode.GetIcode(obb2->start+1)->invalidate();
|
||||
}
|
||||
|
||||
|
||||
/* Creates a long conditional equality or inequality at (pIcode+1).
|
||||
* Removes excess nodes from the graph by flagging them, and updates
|
||||
* the new edges for the remaining nodes. */
|
||||
static void longJCond22 (COND_EXPR *rhs, COND_EXPR *lhs, ICODE * pIcode,
|
||||
Int *idx)
|
||||
{
|
||||
Int j;
|
||||
BB * pbb, * obb1, * tbb;
|
||||
|
||||
/* Form conditional expression */
|
||||
lhs = COND_EXPR::boolOp (lhs, rhs, condOpJCond[(pIcode+3)->ic.ll.opcode - iJB]);
|
||||
(pIcode+1)->setJCond(lhs);
|
||||
copyDU (pIcode+1, pIcode, eUSE, eUSE);
|
||||
(pIcode+1)->du.use |= (pIcode+2)->du.use;
|
||||
|
||||
/* Adjust outEdges[0] to the new target basic block */
|
||||
pbb = pIcode->inBB;
|
||||
if ((pbb->start + pbb->length - 1) == (*idx + 1))
|
||||
{
|
||||
/* Find intermediate and target basic blocks */
|
||||
obb1 = pbb->edges[THEN].BBptr;
|
||||
tbb = obb1->edges[THEN].BBptr;
|
||||
|
||||
/* Modify THEN out edge of header basic block */
|
||||
pbb->edges[THEN].BBptr = tbb;
|
||||
|
||||
/* Modify in edges of target basic block */
|
||||
auto iter=std::find(tbb->inEdges.begin(),tbb->inEdges.end(),obb1);
|
||||
assert(iter!=tbb->inEdges.end());
|
||||
tbb->inEdges.erase(iter);
|
||||
|
||||
if ((pIcode+3)->ic.ll.opcode == iJE)
|
||||
tbb->numInEdges--; /* looses 1 arc */
|
||||
else /* iJNE => replace arc */
|
||||
tbb->inEdges.push_back(pbb);
|
||||
assert(tbb->inEdges.size()==tbb->numInEdges);
|
||||
|
||||
/* Modify ELSE out edge of header basic block */
|
||||
tbb = obb1->edges[ELSE].BBptr;
|
||||
pbb->edges[ELSE].BBptr = tbb;
|
||||
|
||||
iter=std::find(tbb->inEdges.begin(),tbb->inEdges.end(),obb1);
|
||||
assert(iter!=tbb->inEdges.end());
|
||||
tbb->inEdges.erase(iter);
|
||||
if ((pIcode+3)->ic.ll.opcode == iJE) /* replace */
|
||||
tbb->inEdges.push_back(pbb);
|
||||
else
|
||||
tbb->numInEdges--; /* iJNE => looses 1 arc */
|
||||
assert(tbb->inEdges.size()==tbb->numInEdges);
|
||||
|
||||
|
||||
/* Update statistics */
|
||||
obb1->flg |= INVALID_BB;
|
||||
stats.numBBaft--;
|
||||
}
|
||||
|
||||
pIcode->invalidate();
|
||||
(pIcode+2)->invalidate();
|
||||
(pIcode+3)->invalidate();
|
||||
(*idx) += 4;
|
||||
}
|
||||
|
||||
/* Propagates TYPE_LONG_(UN)SIGN icode information to the current pIcode
|
||||
* Pointer.
|
||||
* 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)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
pIcode = pProc->Icode.GetIcode(idx);
|
||||
if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE))
|
||||
continue;
|
||||
|
||||
if (pIcode->ic.ll.opcode == (pIcode+1)->ic.ll.opcode)
|
||||
{
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iMOV:
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, 1) == TRUE)
|
||||
{
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
|
||||
case iAND: case iOR: case iXOR:
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, 1) == TRUE)
|
||||
{
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iAND: rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
||||
break;
|
||||
case iOR: rhs = COND_EXPR::boolOp (lhs, rhs, OR);
|
||||
break;
|
||||
case iXOR: rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
|
||||
break;
|
||||
}
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
|
||||
case iPUSH:
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, 1) == TRUE)
|
||||
{
|
||||
pIcode->setUnary( HLI_PUSH, lhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx++;
|
||||
}
|
||||
break;
|
||||
} /*eos*/
|
||||
}
|
||||
|
||||
/* 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)))
|
||||
{
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc, &rhs, &lhs, off) == TRUE)
|
||||
longJCond23 (rhs, lhs, pIcode, &idx, pProc, arc, off);
|
||||
}
|
||||
|
||||
/* Check for long conditional equality or inequality. This requires
|
||||
* 2 CMPs and 2 branches */
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) &&
|
||||
isLong22 (pIcode, pEnd, &off))
|
||||
{
|
||||
if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond22 (rhs, lhs, pIcode, &idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Finds the definition of the long register pointed to by pLocId, and
|
||||
* transforms that instruction into a HIGH_LEVEL icode instruction.
|
||||
* 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)
|
||||
{
|
||||
COND_EXPR *lhs, *rhs;
|
||||
Int idx, j, off, arc;
|
||||
ICODE * pIcode, * pEnd;
|
||||
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);
|
||||
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);
|
||||
if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE))
|
||||
continue;
|
||||
|
||||
if (pIcode->ic.ll.opcode == (pIcode+1)->ic.ll.opcode)
|
||||
switch (pIcode->ic.ll.opcode)
|
||||
{
|
||||
case iMOV:
|
||||
pmH = &pIcode->ic.ll.dst;
|
||||
pmL = &(pIcode+1)->ic.ll.dst;
|
||||
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);
|
||||
pIcode->setRegDU( pmL->regi, eDEF);
|
||||
rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, idx, eUSE, 1);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx = 0; /* to exit the loop */
|
||||
}
|
||||
break;
|
||||
|
||||
case iPOP:
|
||||
pmH = &(pIcode+1)->ic.ll.dst;
|
||||
pmL = &pIcode->ic.ll.dst;
|
||||
if ((pLocId->id.longId.h == pmH->regi) && (pLocId->id.longId.l == pmL->regi))
|
||||
{
|
||||
lhs = COND_EXPR::idLongIdx (i);
|
||||
pIcode->setRegDU( pmH->regi, eDEF);
|
||||
pIcode->setUnary(HLI_POP, lhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx = 0; /* to exit the loop */
|
||||
}
|
||||
break;
|
||||
|
||||
/**** others missing ***/
|
||||
|
||||
case iAND: case iOR: case iXOR:
|
||||
pmL = &pIcode->ic.ll.dst;
|
||||
pmH = &(pIcode+1)->ic.ll.dst;
|
||||
if ((pLocId->id.longId.h == pmH->regi) && (pLocId->id.longId.l == pmL->regi))
|
||||
{
|
||||
lhs = COND_EXPR::idLongIdx (i);
|
||||
pIcode->setRegDU( pmH->regi, USE_DEF);
|
||||
rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, LOW_FIRST, idx, eUSE, 1);
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iAND: rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
||||
break;
|
||||
case iOR:
|
||||
rhs = COND_EXPR::boolOp (lhs, rhs, OR);
|
||||
break;
|
||||
case iXOR: rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
|
||||
break;
|
||||
} /* eos */
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx = 0;
|
||||
}
|
||||
break;
|
||||
} /* eos */
|
||||
}
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
pIcode = pProc->Icode.GetIcode(idx);
|
||||
if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE))
|
||||
continue;
|
||||
|
||||
if (pIcode->ic.ll.opcode == (pIcode+1)->ic.ll.opcode)
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iMOV:
|
||||
if ((pLocId->id.longId.h == pIcode->ic.ll.src.regi) &&
|
||||
(pLocId->id.longId.l == (pIcode+1)->ic.ll.src.regi))
|
||||
{
|
||||
rhs = COND_EXPR::idLongIdx (i);
|
||||
pIcode->setRegDU( (pIcode+1)->ic.ll.src.regi, eUSE);
|
||||
lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode,
|
||||
HIGH_FIRST, idx, eDEF, 1);
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx = pProc->Icode.GetNumIcodes(); /* to exit the loop */
|
||||
}
|
||||
break;
|
||||
|
||||
case iPUSH:
|
||||
if ((pLocId->id.longId.h == pIcode->ic.ll.src.regi) &&
|
||||
(pLocId->id.longId.l == (pIcode+1)->ic.ll.src.regi))
|
||||
{
|
||||
rhs = COND_EXPR::idLongIdx (i);
|
||||
pIcode->setRegDU( (pIcode+1)->ic.ll.src.regi, eUSE);
|
||||
pIcode->setUnary(HLI_PUSH, lhs);
|
||||
(pIcode+1)->invalidate();
|
||||
}
|
||||
idx = pProc->Icode.GetNumIcodes(); /* to exit the loop */
|
||||
break;
|
||||
|
||||
/*** others missing ****/
|
||||
|
||||
case iAND: case iOR: case iXOR:
|
||||
pmL = &pIcode->ic.ll.dst;
|
||||
pmH = &(pIcode+1)->ic.ll.dst;
|
||||
if ((pLocId->id.longId.h == pmH->regi) &&
|
||||
(pLocId->id.longId.l == pmL->regi))
|
||||
{
|
||||
lhs = COND_EXPR::idLongIdx (i);
|
||||
pIcode->setRegDU( pmH->regi, USE_DEF);
|
||||
rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode,
|
||||
LOW_FIRST, idx, eUSE, 1);
|
||||
switch (pIcode->ic.ll.opcode) {
|
||||
case iAND: rhs = COND_EXPR::boolOp (lhs, rhs, AND);
|
||||
break;
|
||||
case iOR: rhs = COND_EXPR::boolOp (lhs, rhs, OR);
|
||||
break;
|
||||
case iXOR: rhs = COND_EXPR::boolOp (lhs, rhs, XOR);
|
||||
break;
|
||||
}
|
||||
pIcode->setAsgn(lhs, rhs);
|
||||
(pIcode+1)->invalidate();
|
||||
idx = 0;
|
||||
}
|
||||
break;
|
||||
} /* eos */
|
||||
|
||||
/* 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)))
|
||||
{
|
||||
if (checkLongRegEq (pLocId->id.longId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond23 (rhs, lhs, pIcode, &idx, pProc, arc, off);
|
||||
}
|
||||
|
||||
/* Check for long conditional equality or inequality. This requires
|
||||
* 2 CMPs and 2 branches */
|
||||
else if ((pIcode->ic.ll.opcode == iCMP) &&
|
||||
(isLong22 (pIcode, pEnd, &off)))
|
||||
{
|
||||
if (checkLongRegEq (pLocId->id.longId, pIcode, i, idx, pProc,
|
||||
&rhs, &lhs, off) == TRUE)
|
||||
longJCond22 (rhs, lhs, pIcode, &idx);
|
||||
}
|
||||
|
||||
/* Check for OR regH, regL
|
||||
* JX lab
|
||||
* => HLI_JCOND (regH:regL X 0) lab
|
||||
* This is better code than HLI_JCOND (HI(regH:regL) | LO(regH:regL)) */
|
||||
else if ((pIcode->ic.ll.opcode == iOR) && ((pIcode+1) < pEnd) &&
|
||||
(isJCond ((pIcode+1)->ic.ll.opcode)))
|
||||
{
|
||||
if ((pIcode->ic.ll.dst.regi == pLocId->id.longId.h) &&
|
||||
(pIcode->ic.ll.src.regi == pLocId->id.longId.l))
|
||||
{
|
||||
lhs = COND_EXPR::idLongIdx (i);
|
||||
|
||||
rhs = COND_EXPR::idKte (0, 4); /* long 0 */
|
||||
lhs = COND_EXPR::boolOp (lhs, rhs,
|
||||
condOpJCond[(pIcode+1)->ic.ll.opcode - iJB]);
|
||||
(pIcode+1)->setJCond(lhs);
|
||||
copyDU (pIcode+1, pIcode, eUSE, eUSE);
|
||||
pIcode->invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
} /* end for */
|
||||
} /* end for */
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Propagated identifier information, thus converting some LOW_LEVEL icodes
|
||||
* into HIGH_LEVEL icodes. */
|
||||
void Function::propLong()
|
||||
{
|
||||
Int i;
|
||||
ID *pLocId; /* Pointer to current local identifier */
|
||||
|
||||
for (i = 0; i < localId.csym(); i++)
|
||||
{
|
||||
pLocId = &localId.id_arr[i];
|
||||
if ((pLocId->type==TYPE_LONG_SIGN) || (pLocId->type==TYPE_LONG_UNSIGN))
|
||||
{
|
||||
switch (pLocId->loc)
|
||||
{
|
||||
case STK_FRAME:
|
||||
propLongStk (i, pLocId, this);
|
||||
break;
|
||||
case REG_FRAME:
|
||||
propLongReg (i, pLocId, this);
|
||||
break;
|
||||
case GLB_FRAME:
|
||||
propLongGlb (i, pLocId, this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
399
src/reducible.cpp
Normal file
399
src/reducible.cpp
Normal file
@ -0,0 +1,399 @@
|
||||
/********************************************************************
|
||||
* Checks for reducibility of a graph by intervals, and
|
||||
* constructs an equivalent reducible graph if one is not found.
|
||||
* (C) Cristina Cifuentes
|
||||
********************************************************************/
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include "dcc.h"
|
||||
#include <stdio.h>
|
||||
#ifdef __BORLAND__
|
||||
#include <alloc.h>
|
||||
#else
|
||||
#include <malloc.h> /* For free() */
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
static Int numInt; /* Number of intervals */
|
||||
|
||||
|
||||
#define nonEmpty(q) (q != NULL)
|
||||
/* Returns whether the queue q is empty or not */
|
||||
|
||||
#define trivialGraph(G) (G->numOutEdges == 0)
|
||||
/* Returns whether the graph is a trivial graph or not */
|
||||
|
||||
|
||||
/* Returns the first element in the queue Q, and removes this element
|
||||
* from the list. Q is not an empty queue. */
|
||||
static BB *firstOfQueue (queue &Q)
|
||||
{
|
||||
assert(!Q.empty());
|
||||
BB *res=*Q.begin();
|
||||
Q.pop_front();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Appends pointer to node at the end of the queue Q if node is not present
|
||||
* in this queue. Returns the queue node just appended. */
|
||||
queue::iterator appendQueue (queue &Q, BB *node)
|
||||
{
|
||||
auto iter=std::find(Q.begin(),Q.end(),node);
|
||||
if(iter==Q.end())
|
||||
{
|
||||
Q.push_back(node);
|
||||
iter=Q.end();
|
||||
--iter;
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the next unprocessed node of the interval list (pointed to by
|
||||
* pI->currNode). Removes this element logically from the list, by updating
|
||||
* the currNode pointer to the next unprocessed element. */
|
||||
BB *interval::firstOfInt ()
|
||||
{
|
||||
auto pq = currNode;
|
||||
if (pq == nodes.end())
|
||||
return (NULL);
|
||||
++currNode;
|
||||
return *pq;
|
||||
}
|
||||
|
||||
|
||||
/* Appends node @node to the end of the interval list @pI, updates currNode
|
||||
* if necessary, and removes the node from the header list @pqH if it is
|
||||
* there. The interval header information is placed in the field
|
||||
* node->inInterval.
|
||||
* Note: nodes are added to the interval list in interval order (which
|
||||
* topsorts the dominance relation). */
|
||||
static void appendNodeInt (queue &pqH, BB *node, interval *pI)
|
||||
{
|
||||
queue::iterator pq; /* Pointer to current node of the list */
|
||||
|
||||
/* Append node if it is not already in the interval list */
|
||||
pq = appendQueue (pI->nodes, node);
|
||||
|
||||
/* Update currNode if necessary */
|
||||
if (pI->currNode == pI->nodes.end())
|
||||
pI->currNode = pq;
|
||||
|
||||
/* Check header list for occurrence of node, if found, remove it
|
||||
* and decrement number of out-edges from this interval. */
|
||||
if (node->beenOnH && !pqH.empty())
|
||||
{
|
||||
auto found_iter=std::find(pqH.begin(),pqH.end(),node);
|
||||
if(found_iter!=pqH.end())
|
||||
{
|
||||
pI->numOutEdges -= (byte)(*found_iter)->numInEdges - 1;
|
||||
pqH.erase(found_iter);
|
||||
}
|
||||
}
|
||||
/* Update interval header information for this basic block */
|
||||
node->inInterval = pI;
|
||||
}
|
||||
|
||||
|
||||
/* Finds the intervals of graph derivedGi->Gi and places them in the list
|
||||
* of intervals derivedGi->Ii.
|
||||
* Algorithm by M.S.Hecht. */
|
||||
void derSeq_Entry::findIntervals ()
|
||||
{
|
||||
interval *pI, /* Interval being processed */
|
||||
*J; /* ^ last interval in derivedGi->Ii */
|
||||
BB *h, /* Node being processed */
|
||||
*header, /* Current interval's header node */
|
||||
*succ; /* Successor basic block */
|
||||
Int i; /* Counter */
|
||||
queue H; /* Queue of possible header nodes */
|
||||
boolT first = TRUE; /* First pass through the loop */
|
||||
|
||||
appendQueue (H, Gi); /* H = {first node of G} */
|
||||
Gi->beenOnH = TRUE;
|
||||
Gi->reachingInt = BB::Create(); /* ^ empty BB */
|
||||
|
||||
/* Process header nodes list H */
|
||||
while (!H.empty())
|
||||
{
|
||||
header = firstOfQueue (H);
|
||||
pI = new interval;
|
||||
pI->numInt = (byte)numInt++;
|
||||
if (first) /* ^ to first interval */
|
||||
Ii = J = pI;
|
||||
appendNodeInt (H, header, pI); /* pI(header) = {header} */
|
||||
|
||||
/* Process all nodes in the current interval list */
|
||||
while ((h = pI->firstOfInt()) != NULL)
|
||||
{
|
||||
/* Check all immediate successors of h */
|
||||
for (i = 0; i < h->numOutEdges; i++)
|
||||
{
|
||||
succ = h->edges[i].BBptr;
|
||||
succ->inEdgeCount--;
|
||||
|
||||
if (succ->reachingInt == NULL) /* first visit */
|
||||
{
|
||||
succ->reachingInt = header;
|
||||
if (succ->inEdgeCount == 0)
|
||||
appendNodeInt (H, succ, pI);
|
||||
else if (! succ->beenOnH) /* out edge */
|
||||
{
|
||||
appendQueue (H, succ);
|
||||
succ->beenOnH = TRUE;
|
||||
pI->numOutEdges++;
|
||||
}
|
||||
}
|
||||
else /* node has been visited before */
|
||||
if (succ->inEdgeCount == 0)
|
||||
{
|
||||
if (succ->reachingInt == header || succ->inInterval == pI) /* same interval */
|
||||
{
|
||||
if (succ != header)
|
||||
appendNodeInt (H, succ, pI);
|
||||
}
|
||||
else /* out edge */
|
||||
pI->numOutEdges++;
|
||||
}
|
||||
else if (succ != header && succ->beenOnH)
|
||||
pI->numOutEdges++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Link interval I to list of intervals */
|
||||
if (! first)
|
||||
{
|
||||
J->next = pI;
|
||||
J = pI;
|
||||
}
|
||||
else /* first interval */
|
||||
first = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Displays the intervals of the graph Gi. */
|
||||
static void displayIntervals (interval *pI)
|
||||
{
|
||||
queue::iterator nodePtr;
|
||||
|
||||
while (pI)
|
||||
{
|
||||
nodePtr = pI->nodes.begin();
|
||||
printf (" Interval #: %ld\t#OutEdges: %ld\n", pI->numInt, pI->numOutEdges);
|
||||
while (nodePtr!=pI->nodes.end())
|
||||
{
|
||||
if ((*nodePtr)->correspInt == NULL) /* real BBs */
|
||||
printf (" Node: %ld\n", (*nodePtr)->start);
|
||||
else /* BBs represent intervals */
|
||||
printf (" Node (corresp int): %d\n",
|
||||
(*nodePtr)->correspInt->numInt);
|
||||
++nodePtr;
|
||||
}
|
||||
pI = pI->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Allocates space for a new derSeq node. */
|
||||
static derSeq_Entry *newDerivedSeq()
|
||||
{
|
||||
return new derSeq_Entry;
|
||||
}
|
||||
|
||||
|
||||
/* Frees the storage allocated for the queue q*/
|
||||
void freeQueue (queue &q)
|
||||
{
|
||||
q.clear();
|
||||
}
|
||||
|
||||
|
||||
/* Frees the storage allocated for the interval pI */
|
||||
static void freeInterval (interval **pI)
|
||||
{
|
||||
interval *Iptr;
|
||||
|
||||
while (*pI)
|
||||
{
|
||||
(*pI)->nodes.clear();
|
||||
Iptr = *pI;
|
||||
*pI = (*pI)->next;
|
||||
delete (Iptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Frees the storage allocated by the derived sequence structure, except
|
||||
* for the original graph cfg (derivedG->Gi). */
|
||||
void freeDerivedSeq(derSeq &derivedG)
|
||||
{
|
||||
derivedG.clear();
|
||||
}
|
||||
derSeq_Entry::~derSeq_Entry()
|
||||
{
|
||||
freeInterval (&Ii);
|
||||
// if(Gi && Gi->nodeType == INTERVAL_NODE)
|
||||
// freeCFG (Gi);
|
||||
}
|
||||
|
||||
/* Finds the next order graph of derivedGi->Gi according to its intervals
|
||||
* (derivedGi->Ii), and places it in derivedGi->next->Gi. */
|
||||
static boolT nextOrderGraph (derSeq *derivedGi)
|
||||
{
|
||||
interval *Ii; /* Interval being processed */
|
||||
BB *BBnode, /* New basic block of intervals */
|
||||
*curr, /* BB being checked for out edges */
|
||||
*succ /* Successor node */
|
||||
;
|
||||
queue *listIi; /* List of intervals */
|
||||
Int i, /* Index to outEdges array */
|
||||
j; /* Index to successors */
|
||||
boolT sameGraph; /* Boolean, isomorphic graphs */
|
||||
|
||||
/* Process Gi's intervals */
|
||||
derSeq_Entry &prev_entry(derivedGi->back());
|
||||
derivedGi->push_back(derSeq_Entry());
|
||||
derSeq_Entry &new_entry(derivedGi->back());
|
||||
Ii = prev_entry.Ii;
|
||||
sameGraph = TRUE;
|
||||
BBnode = 0;
|
||||
std::vector<BB *> bbs;
|
||||
while (Ii)
|
||||
{
|
||||
i = 0;
|
||||
bbs.push_back(BB::Create(-1, -1, INTERVAL_NODE, Ii->numOutEdges, NULL));
|
||||
BBnode = bbs.back();
|
||||
BBnode->correspInt = Ii;
|
||||
const queue &listIi(Ii->nodes);
|
||||
|
||||
/* Check for more than 1 interval */
|
||||
if (sameGraph && (listIi.size()>1))
|
||||
sameGraph = FALSE;
|
||||
|
||||
/* Find out edges */
|
||||
|
||||
if (BBnode->numOutEdges > 0)
|
||||
{
|
||||
for(auto iter=listIi.begin();iter!=listIi.end(); ++iter)
|
||||
{
|
||||
curr = *iter;
|
||||
for (j = 0; j < curr->numOutEdges; j++)
|
||||
{
|
||||
succ = curr->edges[j].BBptr;
|
||||
if (succ->inInterval != curr->inInterval)
|
||||
BBnode->edges[i++].intPtr = succ->inInterval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next interval */
|
||||
Ii = Ii->next;
|
||||
}
|
||||
|
||||
/* Convert list of pointers to intervals into a real graph.
|
||||
* Determines the number of in edges to each new BB, and places it
|
||||
* in numInEdges and inEdgeCount for later interval processing. */
|
||||
curr = new_entry.Gi = bbs.front();
|
||||
for(auto curr=bbs.begin(); curr!=bbs.end(); ++curr)
|
||||
{
|
||||
for (i = 0; i < (*curr)->numOutEdges; i++)
|
||||
{
|
||||
BBnode = new_entry.Gi; /* BB of an interval */
|
||||
TYPEADR_TYPE &edge=(*curr)->edges[i];
|
||||
auto iter= std::find_if(bbs.begin(),bbs.end(),
|
||||
[&edge](BB *node)->bool { return edge.intPtr==node->correspInt;});
|
||||
if(iter==bbs.end())
|
||||
fatalError (INVALID_INT_BB);
|
||||
edge.BBptr = *iter;
|
||||
(*iter)->numInEdges++;
|
||||
(*iter)->inEdgeCount++;
|
||||
}
|
||||
}
|
||||
return (boolT)(! sameGraph);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Finds the derived sequence of the graph derivedG->Gi (ie. cfg).
|
||||
* Constructs the n-th order graph and places all the intermediate graphs
|
||||
* in the derivedG list sequence. */
|
||||
static byte findDerivedSeq (derSeq *derivedGi)
|
||||
{
|
||||
BB *Gi; /* Current derived sequence graph */
|
||||
|
||||
derSeq::iterator iter=derivedGi->begin();
|
||||
Gi = iter->Gi;
|
||||
while (! trivialGraph (Gi))
|
||||
{
|
||||
/* Find the intervals of Gi and place them in derivedGi->Ii */
|
||||
iter->findIntervals ();
|
||||
|
||||
/* Create Gi+1 and check if it is equivalent to Gi */
|
||||
if (! nextOrderGraph (derivedGi))
|
||||
break;
|
||||
++iter;
|
||||
Gi = iter->Gi;
|
||||
stats.nOrder++;
|
||||
}
|
||||
|
||||
if (! trivialGraph (Gi))
|
||||
{
|
||||
++iter;
|
||||
derivedGi->erase(iter,derivedGi->end()); /* remove Gi+1 */
|
||||
// freeDerivedSeq(derivedGi->next);
|
||||
// derivedGi->next = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
derivedGi->back().findIntervals ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Converts the irreducible graph G into an equivalent reducible one, by
|
||||
* means of node splitting. */
|
||||
static void nodeSplitting (std::vector<BB *> &G)
|
||||
{
|
||||
printf("Attempt to perform node splitting: NOT IMPLEMENTED\n");
|
||||
}
|
||||
|
||||
/* Displays the derived sequence and intervals of the graph G */
|
||||
void derSeq::display()
|
||||
{
|
||||
Int n = 1; /* Derived sequence number */
|
||||
printf ("\nDerived Sequence Intervals\n");
|
||||
derSeq::iterator iter=this->begin();
|
||||
while (iter!=this->end())
|
||||
{
|
||||
printf ("\nIntervals for G%lX\n", n++);
|
||||
displayIntervals (iter->Ii);
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Checks whether the control flow graph, cfg, is reducible or not.
|
||||
* If it is not reducible, it is converted into an equivalent reducible
|
||||
* graph by node splitting. The derived sequence of graphs built from cfg
|
||||
* are returned in the pointer *derivedG.
|
||||
*/
|
||||
derSeq * Function::checkReducibility()
|
||||
{
|
||||
derSeq * der_seq;
|
||||
byte reducible; /* Reducible graph flag */
|
||||
|
||||
numInt = 1; /* reinitialize no. of intervals*/
|
||||
stats.nOrder = 1; /* nOrder(cfg) = 1 */
|
||||
der_seq = new derSeq;
|
||||
der_seq->resize(1);
|
||||
der_seq->back().Gi = cfg.front();
|
||||
reducible = findDerivedSeq(der_seq);
|
||||
|
||||
if (! reducible)
|
||||
{
|
||||
flg |= GRAPH_IRRED;
|
||||
nodeSplitting (cfg);
|
||||
}
|
||||
return der_seq;
|
||||
}
|
||||
|
||||
844
src/scanner.cpp
Normal file
844
src/scanner.cpp
Normal file
@ -0,0 +1,844 @@
|
||||
/*****************************************************************************
|
||||
* dcc project scanner module
|
||||
* Implements a simple state driven scanner to convert 8086 machine code into
|
||||
* I-code
|
||||
* (C) Cristina Cifuentes, Jeff Ledermann
|
||||
****************************************************************************/
|
||||
|
||||
#include "dcc.h"
|
||||
#include "scanner.h"
|
||||
#include <string.h>
|
||||
|
||||
#define iZERO (llIcode)0 // For neatness
|
||||
#define IC llIcode
|
||||
|
||||
static struct {
|
||||
void (*state1)(Int);
|
||||
void (*state2)(Int);
|
||||
flags32 flg;
|
||||
llIcode opcode;
|
||||
byte df;
|
||||
byte uf;
|
||||
} stateTable[] = {
|
||||
{ modrm, none2, B , iADD , Sf | Zf | Cf, }, /* 00 */
|
||||
{ modrm, none2, 0 , iADD , Sf | Zf | Cf, }, /* 01 */
|
||||
{ modrm, none2, TO_REG | B , iADD , Sf | Zf | Cf, }, /* 02 */
|
||||
{ modrm, none2, TO_REG , iADD , Sf | Zf | Cf, }, /* 03 */
|
||||
{ data1, axImp, B , iADD , Sf | Zf | Cf, }, /* 04 */
|
||||
{ data2, axImp, 0 , iADD , Sf | Zf | Cf, }, /* 05 */
|
||||
{ segop, none2, NO_SRC , iPUSH , 0 , }, /* 06 */
|
||||
{ segop, none2, NO_SRC , iPOP , 0 , }, /* 07 */
|
||||
{ modrm, none2, B , iOR , Sf | Zf | Cf, }, /* 08 */
|
||||
{ modrm, none2, NSP , iOR , Sf | Zf | Cf, }, /* 09 */
|
||||
{ modrm, none2, TO_REG | B , iOR , Sf | Zf | Cf, }, /* 0A */
|
||||
{ modrm, none2, TO_REG | NSP , iOR , Sf | Zf | Cf, }, /* 0B */
|
||||
{ data1, axImp, B , iOR , Sf | Zf | Cf, }, /* 0C */
|
||||
{ data2, axImp, 0 , iOR , Sf | Zf | Cf, }, /* 0D */
|
||||
{ segop, none2, NO_SRC , iPUSH , 0 , }, /* 0E */
|
||||
{ none1, none2, OP386 , iZERO , 0 , }, /* 0F */
|
||||
{ modrm, none2, B , iADC , Sf | Zf | Cf, Cf }, /* 10 */
|
||||
{ modrm, none2, NSP , iADC , Sf | Zf | Cf, Cf }, /* 11 */
|
||||
{ modrm, none2, TO_REG | B , iADC , Sf | Zf | Cf, Cf }, /* 12 */
|
||||
{ modrm, none2, TO_REG | NSP , iADC , Sf | Zf | Cf, Cf }, /* 13 */
|
||||
{ data1, axImp, B , iADC , Sf | Zf | Cf, Cf }, /* 14 */
|
||||
{ data2, axImp, 0 , iADC , Sf | Zf | Cf, Cf }, /* 15 */
|
||||
{ segop, none2, NOT_HLL | NO_SRC , iPUSH , 0 , }, /* 16 */
|
||||
{ segop, none2, NOT_HLL | NO_SRC , iPOP , 0 , }, /* 17 */
|
||||
{ modrm, none2, B , iSBB , Sf | Zf | Cf, Cf }, /* 18 */
|
||||
{ modrm, none2, NSP , iSBB , Sf | Zf | Cf, Cf }, /* 19 */
|
||||
{ modrm, none2, TO_REG | B , iSBB , Sf | Zf | Cf, Cf }, /* 1A */
|
||||
{ modrm, none2, TO_REG | NSP , iSBB , Sf | Zf | Cf, Cf }, /* 1B */
|
||||
{ data1, axImp, B , iSBB , Sf | Zf | Cf, Cf }, /* 1C */
|
||||
{ data2, axImp, 0 , iSBB , Sf | Zf | Cf, Cf }, /* 1D */
|
||||
{ segop, none2, NO_SRC , iPUSH , 0 , }, /* 1E */
|
||||
{ segop, none2, NO_SRC , iPOP , 0 , }, /* 1F */
|
||||
{ modrm, none2, B , iAND , Sf | Zf | Cf, }, /* 20 */
|
||||
{ modrm, none2, NSP , iAND , Sf | Zf | Cf, }, /* 21 */
|
||||
{ modrm, none2, TO_REG | B , iAND , Sf | Zf | Cf, }, /* 22 */
|
||||
{ modrm, none2, TO_REG | NSP , iAND , Sf | Zf | Cf, }, /* 23 */
|
||||
{ data1, axImp, B , iAND , Sf | Zf | Cf, }, /* 24 */
|
||||
{ data2, axImp, 0 , iAND , Sf | Zf | Cf, }, /* 25 */
|
||||
{ prefix, none2, 0 , (IC)rES,0 , }, /* 26 */
|
||||
{ none1, axImp, NOT_HLL | B|NO_SRC , iDAA , Sf | Zf | Cf, }, /* 27 */
|
||||
{ modrm, none2, B , iSUB , Sf | Zf | Cf, }, /* 28 */
|
||||
{ modrm, none2, 0 , iSUB , Sf | Zf | Cf, }, /* 29 */
|
||||
{ modrm, none2, TO_REG | B , iSUB , Sf | Zf | Cf, }, /* 2A */
|
||||
{ modrm, none2, TO_REG , iSUB , Sf | Zf | Cf, }, /* 2B */
|
||||
{ data1, axImp, B , iSUB , Sf | Zf | Cf, }, /* 2C */
|
||||
{ data2, axImp, 0 , iSUB , Sf | Zf | Cf, }, /* 2D */
|
||||
{ prefix, none2, 0 , (IC)rCS,0 , }, /* 2E */
|
||||
{ none1, axImp, NOT_HLL | B|NO_SRC , iDAS , Sf | Zf | Cf, }, /* 2F */
|
||||
{ modrm, none2, B , iXOR , Sf | Zf | Cf, }, /* 30 */
|
||||
{ modrm, none2, NSP , iXOR , Sf | Zf | Cf, }, /* 31 */
|
||||
{ modrm, none2, TO_REG | B , iXOR , Sf | Zf | Cf, }, /* 32 */
|
||||
{ modrm, none2, TO_REG | NSP , iXOR , Sf | Zf | Cf, }, /* 33 */
|
||||
{ data1, axImp, B , iXOR , Sf | Zf | Cf, }, /* 34 */
|
||||
{ data2, axImp, 0 , iXOR , Sf | Zf | Cf, }, /* 35 */
|
||||
{ prefix, none2, 0 , (IC)rSS,0 , }, /* 36 */
|
||||
{ none1, axImp, NOT_HLL | NO_SRC , iAAA , Sf | Zf | Cf, }, /* 37 */
|
||||
{ modrm, none2, B , iCMP , Sf | Zf | Cf, }, /* 38 */
|
||||
{ modrm, none2, NSP , iCMP , Sf | Zf | Cf, }, /* 39 */
|
||||
{ modrm, none2, TO_REG | B , iCMP , Sf | Zf | Cf, }, /* 3A */
|
||||
{ modrm, none2, TO_REG | NSP , iCMP , Sf | Zf | Cf, }, /* 3B */
|
||||
{ data1, axImp, B , iCMP , Sf | Zf | Cf, }, /* 3C */
|
||||
{ data2, axImp, 0 , iCMP , Sf | Zf | Cf, }, /* 3D */
|
||||
{ prefix, none2, 0 , (IC)rDS,0 , }, /* 3E */
|
||||
{ none1, axImp, NOT_HLL | NO_SRC , iAAS , Sf | Zf | Cf, }, /* 3F */
|
||||
{ regop, none2, 0 , iINC , Sf | Zf, }, /* 40 */
|
||||
{ regop, none2, 0 , iINC , Sf | Zf, }, /* 41 */
|
||||
{ regop, none2, 0 , iINC , Sf | Zf, }, /* 42 */
|
||||
{ regop, none2, 0 , iINC , Sf | Zf, }, /* 43 */
|
||||
{ regop, none2, NOT_HLL , iINC , Sf | Zf, }, /* 44 */
|
||||
{ regop, none2, 0 , iINC , Sf | Zf, }, /* 45 */
|
||||
{ regop, none2, 0 , iINC , Sf | Zf, }, /* 46 */
|
||||
{ regop, none2, 0 , iINC , Sf | Zf, }, /* 47 */
|
||||
{ regop, none2, 0 , iDEC , Sf | Zf, }, /* 48 */
|
||||
{ regop, none2, 0 , iDEC , Sf | Zf, }, /* 49 */
|
||||
{ regop, none2, 0 , iDEC , Sf | Zf, }, /* 4A */
|
||||
{ regop, none2, 0 , iDEC , Sf | Zf, }, /* 4B */
|
||||
{ regop, none2, NOT_HLL , iDEC , Sf | Zf, }, /* 4C */
|
||||
{ regop, none2, 0 , iDEC , Sf | Zf, }, /* 4D */
|
||||
{ regop, none2, 0 , iDEC , Sf | Zf, }, /* 4E */
|
||||
{ regop, none2, 0 , iDEC , Sf | Zf, }, /* 4F */
|
||||
{ regop, none2, NO_SRC , iPUSH , 0 , }, /* 50 */
|
||||
{ regop, none2, NO_SRC , iPUSH , 0 , }, /* 51 */
|
||||
{ regop, none2, NO_SRC , iPUSH , 0 , }, /* 52 */
|
||||
{ regop, none2, NO_SRC , iPUSH , 0 , }, /* 53 */
|
||||
{ regop, none2, NOT_HLL | NO_SRC , iPUSH , 0 , }, /* 54 */
|
||||
{ regop, none2, NO_SRC , iPUSH , 0 , }, /* 55 */
|
||||
{ regop, none2, NO_SRC , iPUSH , 0 , }, /* 56 */
|
||||
{ regop, none2, NO_SRC , iPUSH , 0 , }, /* 57 */
|
||||
{ regop, none2, NO_SRC , iPOP , 0 , }, /* 58 */
|
||||
{ regop, none2, NO_SRC , iPOP , 0 , }, /* 59 */
|
||||
{ regop, none2, NO_SRC , iPOP , 0 , }, /* 5A */
|
||||
{ regop, none2, NO_SRC , iPOP , 0 , }, /* 5B */
|
||||
{ regop, none2, NOT_HLL | NO_SRC , iPOP , 0 , }, /* 5C */
|
||||
{ regop, none2, NO_SRC , iPOP , 0 , }, /* 5D */
|
||||
{ regop, none2, NO_SRC , iPOP , 0 , }, /* 5E */
|
||||
{ regop, none2, NO_SRC , iPOP , 0 , }, /* 5F */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iPUSHA, 0 , }, /* 60 */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iPOPA , 0 , }, /* 61 */
|
||||
{ memOnly, modrm, TO_REG | NSP , iBOUND, 0 , }, /* 62 */
|
||||
{ none1, none2, OP386 , iZERO , 0 , }, /* 63 */
|
||||
{ none1, none2, OP386 , iZERO , 0 , }, /* 64 */
|
||||
{ none1, none2, OP386 , iZERO , 0 , }, /* 65 */
|
||||
{ none1, none2, OP386 , iZERO , 0 , }, /* 66 */
|
||||
{ none1, none2, OP386 , iZERO , 0 , }, /* 67 */
|
||||
{ data2, none2, NO_SRC , iPUSH , 0 , }, /* 68 */
|
||||
{ modrm, data2, TO_REG | NSP , iIMUL , Sf | Zf | Cf, }, /* 69 */
|
||||
{ data1, none2, S | NO_SRC , iPUSH , 0 , }, /* 6A */
|
||||
{ modrm, data1, TO_REG | NSP | S , iIMUL , Sf | Zf | Cf, }, /* 6B */
|
||||
{ strop, memImp, NOT_HLL | B|IM_OPS , iINS , 0 , Df }, /* 6C */
|
||||
{ strop, memImp, NOT_HLL | IM_OPS , iINS , 0 , Df }, /* 6D */
|
||||
{ strop, memImp, NOT_HLL | B|IM_OPS , iOUTS , 0 , Df }, /* 6E */
|
||||
{ strop, memImp, NOT_HLL | IM_OPS , iOUTS , 0 , Df }, /* 6F */
|
||||
{ dispS, none2, NOT_HLL , iJO , 0 , }, /* 70 */
|
||||
{ dispS, none2, NOT_HLL , iJNO , 0 , }, /* 71 */
|
||||
{ dispS, none2, 0 , iJB , 0 , Cf }, /* 72 */
|
||||
{ dispS, none2, 0 , iJAE , 0 , Cf }, /* 73 */
|
||||
{ dispS, none2, 0 , iJE , 0 , Zf }, /* 74 */
|
||||
{ dispS, none2, 0 , iJNE , 0 , Zf }, /* 75 */
|
||||
{ dispS, none2, 0 , iJBE , 0 , Zf | Cf }, /* 76 */
|
||||
{ dispS, none2, 0 , iJA , 0 , Zf | Cf }, /* 77 */
|
||||
{ dispS, none2, 0 , iJS , 0 , Sf }, /* 78 */
|
||||
{ dispS, none2, 0 , iJNS , 0 , Sf }, /* 79 */
|
||||
{ dispS, none2, NOT_HLL , iJP , 0 , }, /* 7A */
|
||||
{ dispS, none2, NOT_HLL , iJNP , 0 , }, /* 7B */
|
||||
{ dispS, none2, 0 , iJL , 0 , Sf }, /* 7C */
|
||||
{ dispS, none2, 0 , iJGE , 0 , Sf }, /* 7D */
|
||||
{ dispS, none2, 0 , iJLE , 0 , Sf | Zf }, /* 7E */
|
||||
{ dispS, none2, 0 , iJG , 0 , Sf | Zf }, /* 7F */
|
||||
{ immed, data1, B , iZERO , 0 , }, /* 80 */
|
||||
{ immed, data2, NSP , iZERO , 0 , }, /* 81 */
|
||||
{ immed, data1, B , iZERO , 0 , }, /* 82 */ /* ?? */
|
||||
{ immed, data1, NSP | S , iZERO , 0 , }, /* 83 */
|
||||
{ modrm, none2, TO_REG | B , iTEST , Sf | Zf | Cf, }, /* 84 */
|
||||
{ modrm, none2, TO_REG | NSP , iTEST , Sf | Zf | Cf, }, /* 85 */
|
||||
{ modrm, none2, TO_REG | B , iXCHG , 0 , }, /* 86 */
|
||||
{ modrm, none2, TO_REG | NSP , iXCHG , 0 , }, /* 87 */
|
||||
{ modrm, none2, B , iMOV , 0 , }, /* 88 */
|
||||
{ modrm, none2, 0 , iMOV , 0 , }, /* 89 */
|
||||
{ modrm, none2, TO_REG | B , iMOV , 0 , }, /* 8A */
|
||||
{ modrm, none2, TO_REG , iMOV , 0 , }, /* 8B */
|
||||
{ segrm, none2, NSP , iMOV , 0 , }, /* 8C */
|
||||
{ memOnly, modrm, TO_REG | NSP , iLEA , 0 , }, /* 8D */
|
||||
{ segrm, none2, TO_REG | NSP , iMOV , 0 , }, /* 8E */
|
||||
{ memReg0, none2, NO_SRC , iPOP , 0 , }, /* 8F */
|
||||
{ none1, none2, NO_OPS , iNOP , 0 , }, /* 90 */
|
||||
{ regop, axImp, 0 , iXCHG , 0 , }, /* 91 */
|
||||
{ regop, axImp, 0 , iXCHG , 0 , }, /* 92 */
|
||||
{ regop, axImp, 0 , iXCHG , 0 , }, /* 93 */
|
||||
{ regop, axImp, NOT_HLL , iXCHG , 0 , }, /* 94 */
|
||||
{ regop, axImp, 0 , iXCHG , 0 , }, /* 95 */
|
||||
{ regop, axImp, 0 , iXCHG , 0 , }, /* 96 */
|
||||
{ regop, axImp, 0 , iXCHG , 0 , }, /* 97 */
|
||||
{ alImp, axImp, SRC_B | S , iSIGNEX,0 , }, /* 98 */
|
||||
{axSrcIm, axImp, IM_DST | S , iSIGNEX,0 , }, /* 99 */
|
||||
{ dispF, none2, 0 , iCALLF ,0 , }, /* 9A */
|
||||
{ none1, none2, FLOAT_OP| NO_OPS , iWAIT , 0 , }, /* 9B */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iPUSHF, 0 , }, /* 9C */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iPOPF , Sf | Zf | Cf | Df,}, /* 9D */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iSAHF , Sf | Zf | Cf, }, /* 9E */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iLAHF , 0 , Sf | Zf | Cf }, /* 9F */
|
||||
{ dispM, axImp, B , iMOV , 0 , }, /* A0 */
|
||||
{ dispM, axImp, 0 , iMOV , 0 , }, /* A1 */
|
||||
{ dispM, axImp, TO_REG | B , iMOV , 0 , }, /* A2 */
|
||||
{ dispM, axImp, TO_REG , iMOV , 0 , }, /* A3 */
|
||||
{ strop, memImp, B | IM_OPS , iMOVS , 0 , Df }, /* A4 */
|
||||
{ strop, memImp, IM_OPS , iMOVS , 0 , Df }, /* A5 */
|
||||
{ strop, memImp, B | IM_OPS , iCMPS , Sf | Zf | Cf, Df }, /* A6 */
|
||||
{ strop, memImp, IM_OPS , iCMPS , Sf | Zf | Cf, Df }, /* A7 */
|
||||
{ data1, axImp, B , iTEST , Sf | Zf | Cf, }, /* A8 */
|
||||
{ data2, axImp, 0 , iTEST , Sf | Zf | Cf, }, /* A9 */
|
||||
{ strop, memImp, B | IM_OPS , iSTOS , 0 , Df }, /* AA */
|
||||
{ strop, memImp, IM_OPS , iSTOS , 0 , Df }, /* AB */
|
||||
{ strop, memImp, B | IM_OPS , iLODS , 0 , Df }, /* AC */
|
||||
{ strop, memImp, IM_OPS , iLODS , 0 , Df }, /* AD */
|
||||
{ strop, memImp, B | IM_OPS , iSCAS , Sf | Zf | Cf, Df }, /* AE */
|
||||
{ strop, memImp, IM_OPS , iSCAS , Sf | Zf | Cf, Df }, /* AF */
|
||||
{ regop, data1, B , iMOV , 0 , }, /* B0 */
|
||||
{ regop, data1, B , iMOV , 0 , }, /* B1 */
|
||||
{ regop, data1, B , iMOV , 0 , }, /* B2 */
|
||||
{ regop, data1, B , iMOV , 0 , }, /* B3 */
|
||||
{ regop, data1, B , iMOV , 0 , }, /* B4 */
|
||||
{ regop, data1, B , iMOV , 0 , }, /* B5 */
|
||||
{ regop, data1, B , iMOV , 0 , }, /* B6 */
|
||||
{ regop, data1, B , iMOV , 0 , }, /* B7 */
|
||||
{ regop, data2, 0 , iMOV , 0 , }, /* B8 */
|
||||
{ regop, data2, 0 , iMOV , 0 , }, /* B9 */
|
||||
{ regop, data2, 0 , iMOV , 0 , }, /* BA */
|
||||
{ regop, data2, 0 , iMOV , 0 , }, /* BB */
|
||||
{ regop, data2, NOT_HLL , iMOV , 0 , }, /* BC */
|
||||
{ regop, data2, 0 , iMOV , 0 , }, /* BD */
|
||||
{ regop, data2, 0 , iMOV , 0 , }, /* BE */
|
||||
{ regop, data2, 0 , iMOV , 0 , }, /* BF */
|
||||
{ shift, data1, B , iZERO , 0 , }, /* C0 */
|
||||
{ shift, data1, NSP | SRC_B , iZERO , 0 , }, /* C1 */
|
||||
{ data2, none2, 0 , iRET , 0 , }, /* C2 */
|
||||
{ none1, none2, NO_OPS , iRET , 0 , }, /* C3 */
|
||||
{ memOnly, modrm, TO_REG | NSP , iLES , 0 , }, /* C4 */
|
||||
{ memOnly, modrm, TO_REG | NSP , iLDS , 0 , }, /* C5 */
|
||||
{ memReg0, data1, B , iMOV , 0 , }, /* C6 */
|
||||
{ memReg0, data2, 0 , iMOV , 0 , }, /* C7 */
|
||||
{ data2, data1, 0 , iENTER, 0 , }, /* C8 */
|
||||
{ none1, none2, NO_OPS , iLEAVE, 0 , }, /* C9 */
|
||||
{ data2, none2, 0 , iRETF , 0 , }, /* CA */
|
||||
{ none1, none2, NO_OPS , iRETF , 0 , }, /* CB */
|
||||
{ const3, none2, NOT_HLL , iINT , 0 , }, /* CC */
|
||||
{ data1,checkInt, NOT_HLL , iINT , 0 , }, /* CD */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iINTO , 0 , }, /* CE */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iIRET , 0 , }, /* Cf */
|
||||
{ shift, const1, B , iZERO , 0 , }, /* D0 */
|
||||
{ shift, const1, SRC_B , iZERO , 0 , }, /* D1 */
|
||||
{ shift, none1, B , iZERO , 0 , }, /* D2 */
|
||||
{ shift, none1, SRC_B , iZERO , 0 , }, /* D3 */
|
||||
{ data1, axImp, NOT_HLL , iAAM , Sf | Zf | Cf, }, /* D4 */
|
||||
{ data1, axImp, NOT_HLL , iAAD , Sf | Zf | Cf, }, /* D5 */
|
||||
{ none1, none2, 0 , iZERO , 0 , }, /* D6 */
|
||||
{ memImp, axImp, NOT_HLL | B| IM_OPS, iXLAT , 0 , }, /* D7 */
|
||||
{ escop, none2, FLOAT_OP , iESC , 0 , }, /* D8 */
|
||||
{ escop, none2, FLOAT_OP , iESC , 0 , }, /* D9 */
|
||||
{ escop, none2, FLOAT_OP , iESC , 0 , }, /* DA */
|
||||
{ escop, none2, FLOAT_OP , iESC , 0 , }, /* DB */
|
||||
{ escop, none2, FLOAT_OP , iESC , 0 , }, /* DC */
|
||||
{ escop, none2, FLOAT_OP , iESC , 0 , }, /* DD */
|
||||
{ escop, none2, FLOAT_OP , iESC , 0 , }, /* DE */
|
||||
{ escop, none2, FLOAT_OP , iESC , 0 , }, /* Df */
|
||||
{ dispS, none2, 0 , iLOOPNE,0 , Zf }, /* E0 */
|
||||
{ dispS, none2, 0 , iLOOPE, 0 , Zf }, /* E1 */
|
||||
{ dispS, none2, 0 , iLOOP , 0 , }, /* E2 */
|
||||
{ dispS, none2, 0 , iJCXZ , 0 , }, /* E3 */
|
||||
{ data1, axImp, NOT_HLL | B|NO_SRC , iIN , 0 , }, /* E4 */
|
||||
{ data1, axImp, NOT_HLL | NO_SRC , iIN , 0 , }, /* E5 */
|
||||
{ data1, axImp, NOT_HLL | B|NO_SRC , iOUT , 0 , }, /* E6 */
|
||||
{ data1, axImp, NOT_HLL | NO_SRC , iOUT , 0 , }, /* E7 */
|
||||
{ dispN, none2, 0 , iCALL , 0 , }, /* E8 */
|
||||
{ dispN, none2, 0 , iJMP , 0 , }, /* E9 */
|
||||
{ dispF, none2, 0 , iJMPF , 0 , }, /* EA */
|
||||
{ dispS, none2, 0 , iJMP , 0 , }, /* EB */
|
||||
{ none1, axImp, NOT_HLL | B|NO_SRC , iIN , 0 , }, /* EC */
|
||||
{ none1, axImp, NOT_HLL | NO_SRC , iIN , 0 , }, /* ED */
|
||||
{ none1, axImp, NOT_HLL | B|NO_SRC , iOUT , 0 , }, /* EE */
|
||||
{ none1, axImp, NOT_HLL | NO_SRC , iOUT , 0 , }, /* EF */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iLOCK , 0 , }, /* F0 */
|
||||
{ none1, none2, 0 , iZERO , 0 , }, /* F1 */
|
||||
{ prefix, none2, 0 , iREPNE, 0 , }, /* F2 */
|
||||
{ prefix, none2, 0 , iREPE , 0 , }, /* F3 */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iHLT , 0 , }, /* F4 */
|
||||
{ none1, none2, NO_OPS , iCMC , Cf, Cf }, /* F5 */
|
||||
{ arith, none1, B , iZERO , 0 , }, /* F6 */
|
||||
{ arith, none1, NSP , iZERO , 0 , }, /* F7 */
|
||||
{ none1, none2, NO_OPS , iCLC , Cf, }, /* F8 */
|
||||
{ none1, none2, NO_OPS , iSTC , Cf, }, /* F9 */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iCLI , 0 , }, /* FA */
|
||||
{ none1, none2, NOT_HLL | NO_OPS , iSTI , 0 , }, /* FB */
|
||||
{ none1, none2, NO_OPS , iCLD , Df, }, /* FC */
|
||||
{ none1, none2, NO_OPS , iSTD , Df, }, /* FD */
|
||||
{ trans, none1, B , iZERO , 0 , }, /* FE */
|
||||
{ trans, none1, NSP , iZERO , 0 , } /* FF */
|
||||
} ;
|
||||
|
||||
static word SegPrefix, RepPrefix;
|
||||
static byte *pInst; /* Ptr. to current byte of instruction */
|
||||
static ICODE * pIcode; /* Ptr to Icode record filled in by scan() */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
Scans one machine instruction at offset ip in prog.Image and returns error.
|
||||
At the same time, fill in low-level icode details for the scanned inst.
|
||||
****************************************************************************/
|
||||
Int scan(dword ip, ICODE *p)
|
||||
{
|
||||
Int op;
|
||||
|
||||
memset(p, 0, sizeof(ICODE));
|
||||
p->type = LOW_LEVEL;
|
||||
p->ic.ll.label = ip; /* ip is absolute offset into image*/
|
||||
if (ip >= (dword)prog.cbImage)
|
||||
{
|
||||
return (IP_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
SegPrefix = RepPrefix = 0;
|
||||
pInst = prog.Image + ip;
|
||||
pIcode = p;
|
||||
|
||||
do
|
||||
{
|
||||
op = *pInst++; /* First state - trivial */
|
||||
p->ic.ll.opcode = stateTable[op].opcode; /* Convert to Icode.opcode */
|
||||
p->ic.ll.flg = stateTable[op].flg & ICODEMASK;
|
||||
p->ic.ll.flagDU.d = stateTable[op].df;
|
||||
p->ic.ll.flagDU.u = stateTable[op].uf;
|
||||
|
||||
(*stateTable[op].state1)(op); /* Second state */
|
||||
(*stateTable[op].state2)(op); /* Third state */
|
||||
|
||||
} while (stateTable[op].state1 == prefix); /* Loop if prefix */
|
||||
|
||||
if (p->ic.ll.opcode)
|
||||
{
|
||||
/* Save bytes of image used */
|
||||
p->ic.ll.numBytes = (byte)((pInst - prog.Image) - ip);
|
||||
return ((SegPrefix)? FUNNY_SEGOVR: /* Seg. Override invalid */
|
||||
(RepPrefix ? FUNNY_REP: 0));/* REP prefix invalid */
|
||||
}
|
||||
/* Else opcode error */
|
||||
return ((stateTable[op].flg & OP386)? INVALID_386OP: INVALID_OPCODE);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
relocItem - returns TRUE if word pointed at is in relocation table
|
||||
**************************************************************************/
|
||||
static boolT relocItem(byte *p)
|
||||
{
|
||||
Int i;
|
||||
dword off = p - prog.Image;
|
||||
|
||||
for (i = 0; i < prog.cReloc; i++)
|
||||
if (prog.relocTable[i] == off)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
getWord - returns next word from image
|
||||
**************************************************************************/
|
||||
static word getWord(void)
|
||||
{
|
||||
word w = LH(pInst);
|
||||
pInst += 2;
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
signex - returns byte sign extended to Int
|
||||
***************************************************************************/
|
||||
static Int signex(byte b)
|
||||
{
|
||||
long s = b;
|
||||
return ((b & 0x80)? (Int)(0xFFFFFF00 | s): (Int)s);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* setAddress - Updates the source or destination field for the current
|
||||
* icode, based on fdst and the TO_REG flag.
|
||||
* Note: fdst == TRUE is for the r/m part of the field (dest, unless TO_REG)
|
||||
* fdst == FALSE is for reg part of the field
|
||||
***************************************************************************/
|
||||
static void setAddress(Int i, boolT fdst, word seg, int16 reg, word off)
|
||||
{
|
||||
ICODEMEM *pm;
|
||||
|
||||
/* If not to register (i.e. to r/m), and talking about r/m,
|
||||
then this is dest */
|
||||
pm = (!(stateTable[i].flg & TO_REG) == fdst) ?
|
||||
&pIcode->ic.ll.dst : &pIcode->ic.ll.src;
|
||||
|
||||
/* Set segment. A later procedure (lookupAddr in proclist.c) will
|
||||
* provide the value of this segment in the field segValue. */
|
||||
if (seg) /* segment override */
|
||||
{
|
||||
pm->seg = pm->segOver = (byte)seg;
|
||||
}
|
||||
else
|
||||
{ /* no override, check indexed register */
|
||||
if ((reg >= INDEXBASE) && (reg == INDEXBASE + 2 ||
|
||||
reg == INDEXBASE + 3 || reg == INDEXBASE + 6))
|
||||
{
|
||||
pm->seg = rSS; /* indexed on bp */
|
||||
}
|
||||
else
|
||||
{
|
||||
pm->seg = rDS; /* any other indexed reg */
|
||||
}
|
||||
}
|
||||
pm->regi = (byte)reg;
|
||||
pm->off = (int16)off;
|
||||
if (reg && reg < INDEXBASE && (stateTable[i].flg & B))
|
||||
{
|
||||
pm->regi += rAL - rAX;
|
||||
}
|
||||
|
||||
if (seg) /* So we can catch invalid use of segment overrides */
|
||||
{
|
||||
SegPrefix = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
rm - Decodes r/m part of modrm byte for dst (unless TO_REG) part of icode
|
||||
***************************************************************************/
|
||||
static void rm(Int i)
|
||||
{
|
||||
byte mod = *pInst >> 6;
|
||||
byte rm = *pInst++ & 7;
|
||||
|
||||
switch (mod) {
|
||||
case 0: /* No disp unless rm == 6 */
|
||||
if (rm == 6) {
|
||||
setAddress(i, TRUE, SegPrefix, 0, getWord());
|
||||
pIcode->ic.ll.flg |= WORD_OFF;
|
||||
}
|
||||
else setAddress(i, TRUE, SegPrefix, rm + INDEXBASE, 0);
|
||||
break;
|
||||
|
||||
case 1: /* 1 byte disp */
|
||||
setAddress(i, TRUE, SegPrefix, rm+INDEXBASE, (word)signex(*pInst++));
|
||||
break;
|
||||
|
||||
case 2: /* 2 byte disp */
|
||||
setAddress(i, TRUE, SegPrefix, rm + INDEXBASE, getWord());
|
||||
pIcode->ic.ll.flg |= WORD_OFF;
|
||||
break;
|
||||
|
||||
case 3: /* reg */
|
||||
setAddress(i, TRUE, 0, rm + rAX, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((stateTable[i].flg & NSP) && (pIcode->ic.ll.src.regi==rSP ||
|
||||
pIcode->ic.ll.dst.regi==rSP))
|
||||
pIcode->ic.ll.flg |= NOT_HLL;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
modrm - Sets up src and dst from modrm byte
|
||||
***************************************************************************/
|
||||
static void modrm(Int i)
|
||||
{
|
||||
setAddress(i, FALSE, 0, REG(*pInst) + rAX, 0);
|
||||
rm(i);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
segrm - seg encoded as reg of modrm
|
||||
****************************************************************************/
|
||||
static void segrm(Int i)
|
||||
{
|
||||
Int reg = REG(*pInst) + rES;
|
||||
|
||||
if (reg > rDS || (reg == rCS && (stateTable[i].flg & TO_REG)))
|
||||
pIcode->ic.ll.opcode = (llIcode)0;
|
||||
else {
|
||||
setAddress(i, FALSE, 0, (int16)reg, 0);
|
||||
rm(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
regop - src/dst reg encoded as low 3 bits of opcode
|
||||
***************************************************************************/
|
||||
static void regop(Int i)
|
||||
{
|
||||
setAddress(i, FALSE, 0, ((int16)i & 7) + rAX, 0);
|
||||
pIcode->ic.ll.dst.regi = pIcode->ic.ll.src.regi;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
segop - seg encoded in middle of opcode
|
||||
*****************************************************************************/
|
||||
static void segop(Int i)
|
||||
{
|
||||
setAddress(i, TRUE, 0, (((int16)i & 0x18) >> 3) + rES, 0);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
axImp - Plugs an implied AX dst
|
||||
***************************************************************************/
|
||||
static void axImp(Int i)
|
||||
{
|
||||
setAddress(i, TRUE, 0, rAX, 0);
|
||||
}
|
||||
|
||||
|
||||
static void axSrcIm (Int i)
|
||||
/* Implied AX source */
|
||||
{
|
||||
pIcode->ic.ll.src.regi = rAX;
|
||||
}
|
||||
|
||||
|
||||
static void alImp (Int i)
|
||||
/* Implied AL source */
|
||||
{
|
||||
pIcode->ic.ll.src.regi = rAL;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
memImp - Plugs implied src memory operand with any segment override
|
||||
****************************************************************************/
|
||||
static void memImp(Int i)
|
||||
{
|
||||
setAddress(i, FALSE, SegPrefix, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
memOnly - Instruction is not valid if modrm refers to register (i.e. mod == 3)
|
||||
***************************************************************************/
|
||||
static void memOnly(Int i)
|
||||
{
|
||||
if ((*pInst & 0xC0) == 0xC0)
|
||||
pIcode->ic.ll.opcode = (llIcode)0;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
memReg0 - modrm for 'memOnly' and Reg field must also be 0
|
||||
****************************************************************************/
|
||||
static void memReg0(Int i)
|
||||
{
|
||||
if (REG(*pInst) || (*pInst & 0xC0) == 0xC0)
|
||||
pIcode->ic.ll.opcode = (llIcode)0;
|
||||
else
|
||||
rm(i);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
immed - Sets up dst and opcode from modrm byte
|
||||
**************************************************************************/
|
||||
static void immed(Int i)
|
||||
{
|
||||
static llIcode immedTable[8] = {iADD, iOR, iADC, iSBB, iAND, iSUB, iXOR, iCMP};
|
||||
static byte uf[8] = { 0, 0, Cf, Cf, 0, 0, 0, 0 };
|
||||
|
||||
pIcode->ic.ll.opcode = immedTable[REG(*pInst)];
|
||||
pIcode->ic.ll.flagDU.u = uf[REG(*pInst)];
|
||||
pIcode->ic.ll.flagDU.d = (Sf | Zf | Cf);
|
||||
rm(i);
|
||||
|
||||
if (pIcode->ic.ll.opcode == iADD || pIcode->ic.ll.opcode == iSUB)
|
||||
pIcode->ic.ll.flg &= ~NOT_HLL; /* Allow ADD/SUB SP, immed */
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
shift - Sets up dst and opcode from modrm byte
|
||||
***************************************************************************/
|
||||
static void shift(Int i)
|
||||
{
|
||||
static llIcode shiftTable[8] =
|
||||
{
|
||||
(llIcode)iROL, (llIcode)iROR, (llIcode)iRCL, (llIcode)iRCR,
|
||||
(llIcode)iSHL, (llIcode)iSHR, (llIcode)0, (llIcode)iSAR};
|
||||
static byte uf[8] = {0, 0, Cf, Cf, 0, 0, 0, 0 };
|
||||
static byte df[8] = {Cf, Cf, Cf, Cf, Sf | Zf | Cf,
|
||||
Sf | Zf | Cf, 0, Sf | Zf | Cf};
|
||||
|
||||
pIcode->ic.ll.opcode = shiftTable[REG(*pInst)];
|
||||
pIcode->ic.ll.flagDU.u = uf[REG(*pInst)];
|
||||
pIcode->ic.ll.flagDU.d = df[REG(*pInst)];
|
||||
rm(i);
|
||||
pIcode->ic.ll.src.regi = rCL;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
trans - Sets up dst and opcode from modrm byte
|
||||
***************************************************************************/
|
||||
static void trans(Int i)
|
||||
{
|
||||
static llIcode transTable[8] =
|
||||
{
|
||||
(llIcode)iINC, (llIcode)iDEC, (llIcode)iCALL, (llIcode)iCALLF,
|
||||
(llIcode)iJMP, (llIcode)iJMPF,(llIcode)iPUSH, (llIcode)0
|
||||
};
|
||||
static byte df[8] = {Sf | Zf, Sf | Zf, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
if ((byte)REG(*pInst) < 2 || !(stateTable[i].flg & B)) { /* INC & DEC */
|
||||
pIcode->ic.ll.opcode = transTable[REG(*pInst)]; /* valid on bytes */
|
||||
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)
|
||||
pIcode->ic.ll.flg |= NO_OPS;
|
||||
else if (pIcode->ic.ll.opcode == iINC || pIcode->ic.ll.opcode == iPUSH
|
||||
|| pIcode->ic.ll.opcode == iDEC)
|
||||
pIcode->ic.ll.flg |= NO_SRC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
arith - Sets up dst and opcode from modrm byte
|
||||
****************************************************************************/
|
||||
static void arith(Int i)
|
||||
{ byte opcode;
|
||||
static llIcode arithTable[8] =
|
||||
{
|
||||
(llIcode)iTEST, (llIcode)0, (llIcode)iNOT, (llIcode)iNEG,
|
||||
(llIcode)iMUL, (llIcode)iIMUL, (llIcode)iDIV, (llIcode)iIDIV
|
||||
};
|
||||
static byte df[8] = {Sf | Zf | Cf, 0, 0, Sf | Zf | Cf,
|
||||
Sf | Zf | Cf, Sf | Zf | Cf, Sf | Zf | Cf,
|
||||
Sf | Zf | Cf};
|
||||
|
||||
opcode = pIcode->ic.ll.opcode = arithTable[REG(*pInst)];
|
||||
pIcode->ic.ll.flagDU.d = df[REG(*pInst)];
|
||||
rm(i);
|
||||
if (opcode == iTEST)
|
||||
{
|
||||
if (stateTable[i].flg & B)
|
||||
data1(i);
|
||||
else
|
||||
data2(i);
|
||||
}
|
||||
else if (!(opcode == iNOT || opcode == iNEG))
|
||||
{
|
||||
memcpy(&pIcode->ic.ll.src, &pIcode->ic.ll.dst, sizeof(ICODEMEM));
|
||||
setAddress(i, TRUE, 0, rAX, 0); /* dst = AX */
|
||||
}
|
||||
else if (opcode == iNEG || opcode == iNOT)
|
||||
pIcode->ic.ll.flg |= NO_SRC;
|
||||
|
||||
if ((opcode == iDIV) || (opcode == iIDIV))
|
||||
{
|
||||
if ((pIcode->ic.ll.flg & B) != B)
|
||||
pIcode->ic.ll.flg |= IM_TMP_DST;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
data1 - Sets up immed from 1 byte data
|
||||
*****************************************************************************/
|
||||
static void data1(Int i)
|
||||
{
|
||||
pIcode->ic.ll.immed.op = (stateTable[i].flg & S)? signex(*pInst++):
|
||||
*pInst++;
|
||||
pIcode->ic.ll.flg |= I;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
data2 - Sets up immed from 2 byte data
|
||||
****************************************************************************/
|
||||
static void data2(Int i)
|
||||
{
|
||||
if (relocItem(pInst))
|
||||
pIcode->ic.ll.flg |= SEG_IMMED;
|
||||
|
||||
/* ENTER is a special case, it does not take a destination operand,
|
||||
* but this field is being used as the number of bytes to allocate
|
||||
* on the stack. The procedure level is stored in the immediate
|
||||
* field. There is no source operand; therefore, the flag flg is
|
||||
* set to NO_OPS. */
|
||||
if (pIcode->ic.ll.opcode == iENTER)
|
||||
{
|
||||
pIcode->ic.ll.dst.off = getWord();
|
||||
pIcode->ic.ll.flg |= NO_OPS;
|
||||
}
|
||||
else
|
||||
pIcode->ic.ll.immed.op = getWord();
|
||||
pIcode->ic.ll.flg |= I;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
dispM - 2 byte offset without modrm (== mod 0, rm 6) (Note:TO_REG bits are
|
||||
reversed)
|
||||
****************************************************************************/
|
||||
static void dispM(Int i)
|
||||
{
|
||||
setAddress(i, FALSE, SegPrefix, 0, getWord());
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
dispN - 2 byte disp as immed relative to ip
|
||||
****************************************************************************/
|
||||
static void dispN(Int i)
|
||||
{
|
||||
long off = (short)getWord(); /* Signed displacement */
|
||||
|
||||
/* Note: the result of the subtraction could be between 32k and 64k, and
|
||||
still be positive; it is an offset from prog.Image. So this must be
|
||||
treated as unsigned */
|
||||
pIcode->ic.ll.immed.op = (dword)(off + (unsigned)(pInst - prog.Image));
|
||||
pIcode->ic.ll.flg |= I;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
dispS - 1 byte disp as immed relative to ip
|
||||
***************************************************************************/
|
||||
static void dispS(Int i)
|
||||
{
|
||||
long off = signex(*pInst++); /* Signed displacement */
|
||||
|
||||
pIcode->ic.ll.immed.op = (dword)(off + (unsigned)(pInst - prog.Image));
|
||||
pIcode->ic.ll.flg |= I;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
dispF - 4 byte disp as immed 20-bit target address
|
||||
***************************************************************************/
|
||||
static void dispF(Int i)
|
||||
{
|
||||
dword off = (unsigned)getWord();
|
||||
dword seg = (unsigned)getWord();
|
||||
|
||||
pIcode->ic.ll.immed.op = off + ((dword)(unsigned)seg << 4);
|
||||
pIcode->ic.ll.flg |= I;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
prefix - picks up prefix byte for following instruction (LOCK is ignored
|
||||
on purpose)
|
||||
****************************************************************************/
|
||||
static void prefix(Int i)
|
||||
{
|
||||
if (pIcode->ic.ll.opcode == iREPE || pIcode->ic.ll.opcode == iREPNE)
|
||||
RepPrefix = pIcode->ic.ll.opcode;
|
||||
else
|
||||
SegPrefix = pIcode->ic.ll.opcode;
|
||||
}
|
||||
|
||||
inline void BumpOpcode(llIcode& ic)
|
||||
{
|
||||
ic = (llIcode)(((int)ic)+1); // Bump this icode via the int type
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
strop - checks RepPrefix and converts string instructions accordingly
|
||||
*****************************************************************************/
|
||||
static void strop(Int i)
|
||||
{
|
||||
if (RepPrefix)
|
||||
{
|
||||
// pIcode->ic.ll.opcode += ((pIcode->ic.ll.opcode == iCMPS ||
|
||||
// pIcode->ic.ll.opcode == iSCAS)
|
||||
// && RepPrefix == iREPE)? 2: 1;
|
||||
if ((pIcode->ic.ll.opcode == iCMPS || pIcode->ic.ll.opcode == iSCAS)
|
||||
&& RepPrefix == iREPE)
|
||||
BumpOpcode(pIcode->ic.ll.opcode); // += 2
|
||||
BumpOpcode(pIcode->ic.ll.opcode); // else += 1
|
||||
if (pIcode->ic.ll.opcode == iREP_LODS)
|
||||
pIcode->ic.ll.flg |= NOT_HLL;
|
||||
RepPrefix = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
escop - esc operands
|
||||
***************************************************************************/
|
||||
static void escop(Int i)
|
||||
{
|
||||
pIcode->ic.ll.immed.op = REG(*pInst) + (dword)((i & 7) << 3);
|
||||
pIcode->ic.ll.flg |= I;
|
||||
rm(i);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
const1
|
||||
****************************************************************************/
|
||||
static void const1(Int i)
|
||||
{
|
||||
pIcode->ic.ll.immed.op = 1;
|
||||
pIcode->ic.ll.flg |= I;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
const3
|
||||
****************************************************************************/
|
||||
static void const3(Int i)
|
||||
{
|
||||
pIcode->ic.ll.immed.op = 3;
|
||||
pIcode->ic.ll.flg |= I;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
none1
|
||||
****************************************************************************/
|
||||
static void none1(Int i)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
none2 - Sets the NO_OPS flag if the operand is immediate
|
||||
****************************************************************************/
|
||||
static void none2(Int i)
|
||||
{
|
||||
if (pIcode->ic.ll.flg & I)
|
||||
pIcode->ic.ll.flg |= NO_OPS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Checks for int 34 to int 3B - if so, converts to ESC nn instruction
|
||||
****************************************************************************/
|
||||
static void checkInt(Int i)
|
||||
{
|
||||
word wOp = (word) pIcode->ic.ll.immed.op;
|
||||
if ((wOp >= 0x34) && (wOp <= 0x3B))
|
||||
{
|
||||
/* This is a Borland/Microsoft floating point emulation instruction.
|
||||
Treat as if it is an ESC opcode */
|
||||
pIcode->ic.ll.immed.op = wOp - 0x34;
|
||||
pIcode->ic.ll.opcode = iESC;
|
||||
pIcode->ic.ll.flg |= FLOAT_OP;
|
||||
|
||||
escop(wOp - 0x34 + 0xD8);
|
||||
|
||||
}
|
||||
}
|
||||
626
src/symtab.cpp
Normal file
626
src/symtab.cpp
Normal file
@ -0,0 +1,626 @@
|
||||
/*
|
||||
* (C) Mike van Emmerik
|
||||
* These could probably be replaced by functions from libg++
|
||||
*/
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * *\
|
||||
* *
|
||||
* S y m b o l t a b l e F u n c t i o n s *
|
||||
* *
|
||||
\* * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/* This file implements a symbol table with a symbolic name, a symbol value
|
||||
(word), and a procedure number. Two tables are maintained, to be able to
|
||||
look up by name or by value. Pointers are used for the duplicated symbolic
|
||||
name to save space. Both tables have the same structure.
|
||||
The hash tables automatically expand when they get 90% full; they are
|
||||
never compressed. Expanding the tables could take some time, since about
|
||||
half of the entries have to be moved on average.
|
||||
Linear probing is used, due to the difficulty of implementing (e.g.)
|
||||
quadratic probing with a variable table size.
|
||||
*/
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <unordered_map>
|
||||
#include "dcc.h"
|
||||
#include "symtab.h"
|
||||
|
||||
#define TABLESIZE 16 /* Number of entries added each expansion */
|
||||
/* Probably has to be a power of 2 */
|
||||
#define STRTABSIZE 256 /* Size string table is inc'd by */
|
||||
#define NIL ((word)-1)
|
||||
using namespace std;
|
||||
static char *pStrTab; /* Pointer to the current string table */
|
||||
static int strTabNext; /* Next free index into pStrTab */
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<SYMTABLE> : public unary_function<const SYMTABLE &,size_t>
|
||||
{
|
||||
size_t operator()(const SYMTABLE & key) const
|
||||
{
|
||||
word h = 0;
|
||||
h = (word)(key.symOff ^ (key.symOff >> 8));
|
||||
return h;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
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 */
|
||||
word numEntry; /* Number of entries in this table */
|
||||
word tableSize;/* Size of the table (entries) */
|
||||
unordered_map<string,SYMTABLE> z;
|
||||
unordered_map<SYMTABLE,string> z2;
|
||||
};
|
||||
|
||||
TABLEINFO_TYPE tableInfo[NUM_TABLE_TYPES]; /* Array of info about tables */
|
||||
TABLEINFO_TYPE currentTabInfo;
|
||||
|
||||
/* Create a new symbol table. Returns "handle" */
|
||||
void TABLEINFO_TYPE::create(tableType type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case Comment:
|
||||
numEntry = 0;
|
||||
tableSize = TABLESIZE;
|
||||
valTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE);
|
||||
symTab = 0;
|
||||
memset(valTab, 0, sizeof(SYMTABLE) * TABLESIZE);
|
||||
break;
|
||||
case Label:
|
||||
currentTabInfo.numEntry = 0;
|
||||
currentTabInfo.tableSize = TABLESIZE;
|
||||
currentTabInfo.symTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE);
|
||||
memset(currentTabInfo.symTab, 0, sizeof(SYMTABLE) * TABLESIZE);
|
||||
|
||||
currentTabInfo.valTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE);
|
||||
memset(currentTabInfo.valTab, 0, sizeof(SYMTABLE) * TABLESIZE);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void createSymTables(void)
|
||||
{
|
||||
/* Initilise the comment table */
|
||||
/* NB - there is no symbol hashed comment table */
|
||||
currentTabInfo.create(Comment);
|
||||
tableInfo[Comment] = currentTabInfo;
|
||||
|
||||
/* Initialise the label table */
|
||||
currentTabInfo.create(Label);
|
||||
|
||||
tableInfo[Label] = currentTabInfo;
|
||||
curTableType = Label;
|
||||
|
||||
/* Now the string table */
|
||||
strTabNext = 0;
|
||||
pStrTab = (char *)allocMem(STRTABSIZE);
|
||||
|
||||
// tableInfo[Label].symTab = currentTabInfo.symTab;
|
||||
// tableInfo[Label].valTab = currentTabInfo.valTab;
|
||||
// tableInfo[Label].numEntry = currentTabInfo.numEntry;
|
||||
// tableInfo[Label].tableSize = currentTabInfo.tableSize;
|
||||
curTableType = Label;
|
||||
|
||||
}
|
||||
|
||||
void selectTable(tableType tt)
|
||||
{
|
||||
if (curTableType == tt)
|
||||
return; /* Nothing to do */
|
||||
currentTabInfo = tableInfo[tt];
|
||||
curTableType = tt;
|
||||
}
|
||||
void TABLEINFO_TYPE::destroy()
|
||||
{
|
||||
if(symTab)
|
||||
free(symTab); // The symbol hashed label table
|
||||
if(valTab)
|
||||
free(valTab); // And the value hashed label table
|
||||
|
||||
}
|
||||
void destroySymTables(void)
|
||||
{
|
||||
selectTable(Label);
|
||||
currentTabInfo.destroy();
|
||||
selectTable(Comment);
|
||||
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;
|
||||
}
|
||||
159
src/udm.cpp
Normal file
159
src/udm.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/*****************************************************************************
|
||||
* dcc project Universal Decompilation Module
|
||||
* This is supposedly a machine independant and language independant module
|
||||
* that just plays with abstract cfg's and intervals and such like.
|
||||
* (C) Cristina Cifuentes
|
||||
****************************************************************************/
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
#include <stdio.h>
|
||||
#include "dcc.h"
|
||||
|
||||
static void displayCFG(Function * pProc);
|
||||
static void displayDfs(BB * pBB);
|
||||
|
||||
/****************************************************************************
|
||||
* udm
|
||||
****************************************************************************/
|
||||
void udm(void)
|
||||
{
|
||||
|
||||
/* Build the control flow graph, find idioms, and convert low-level
|
||||
* icodes to high-level ones */
|
||||
for (auto iter = pProcList.rbegin(); iter!=pProcList.rend(); ++iter)
|
||||
{
|
||||
|
||||
if (iter->flg & PROC_ISLIB)
|
||||
continue; /* Ignore library functions */
|
||||
|
||||
/* Create the basic control flow graph */
|
||||
iter->createCFG();
|
||||
if (option.VeryVerbose)
|
||||
iter->displayCFG();
|
||||
|
||||
/* Remove redundancies and add in-edge information */
|
||||
iter->compressCFG();
|
||||
|
||||
/* Print 2nd pass assembler listing */
|
||||
if (option.asm2)
|
||||
disassem(2, &(*iter));
|
||||
|
||||
/* Idiom analysis and propagation of long type */
|
||||
iter->lowLevelAnalysis();
|
||||
|
||||
/* Generate HIGH_LEVEL icodes whenever possible */
|
||||
iter->highLevelGen();
|
||||
}
|
||||
|
||||
/* Data flow analysis - eliminate condition codes, extraneous registers
|
||||
* and intermediate instructions. Find expressions by forward
|
||||
* substitution algorithm */
|
||||
pProcList.front().dataFlow (0);
|
||||
derSeq *derivedG=0;
|
||||
|
||||
/* Control flow analysis - structuring algorithm */
|
||||
for (auto iter = pProcList.rbegin(); iter!=pProcList.rend(); ++iter)
|
||||
{
|
||||
|
||||
if (iter->flg & PROC_ISLIB)
|
||||
continue; /* Ignore library functions */
|
||||
|
||||
/* Make cfg reducible and build derived sequences */
|
||||
derivedG=iter->checkReducibility();
|
||||
|
||||
if (option.VeryVerbose)
|
||||
derivedG->display();
|
||||
|
||||
/* Structure the graph */
|
||||
iter->structure(derivedG);
|
||||
|
||||
/* Check for compound conditions */
|
||||
iter->compoundCond ();
|
||||
|
||||
if (option.verbose) {
|
||||
printf("\nDepth first traversal - Proc %s\n", iter->name);
|
||||
iter->cfg.front()->displayDfs();
|
||||
}
|
||||
|
||||
/* Free storage occupied by this procedure */
|
||||
freeDerivedSeq(*derivedG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *const s_nodeType[] = {"branch", "if", "case", "fall", "return", "call",
|
||||
"loop", "repeat", "interval", "cycleHead",
|
||||
"caseHead", "terminate",
|
||||
"nowhere" };
|
||||
|
||||
static const char *const s_loopType[] = {"noLoop", "while", "repeat", "loop", "for"};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* displayCFG - Displays the Basic Block list
|
||||
***************************************************************************/
|
||||
void Function::displayCFG()
|
||||
{
|
||||
Int i;
|
||||
BB * pBB;
|
||||
|
||||
printf("\nBasic Block List - Proc %s", name);
|
||||
|
||||
for (auto iter = cfg.begin(); iter!=cfg.end(); ++iter)
|
||||
{
|
||||
pBB = *iter;
|
||||
printf("\nnode type = %s, ", s_nodeType[pBB->nodeType]);
|
||||
printf("start = %ld, length = %ld, #out edges = %ld\n",
|
||||
pBB->start, pBB->length, pBB->numOutEdges);
|
||||
|
||||
for (i = 0; i < pBB->numOutEdges; i++)
|
||||
printf(" outEdge[%2d] = %ld\n",i, pBB->edges[i].BBptr->start);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* displayDfs - Displays the CFG using a depth first traversal
|
||||
****************************************************************************/
|
||||
void BB::displayDfs()
|
||||
{
|
||||
Int i;
|
||||
assert(this);
|
||||
traversed = DFS_DISP;
|
||||
|
||||
printf("node type = %s, ", s_nodeType[nodeType]);
|
||||
printf("start = %ld, length = %ld, #in-edges = %ld, #out-edges = %ld\n",
|
||||
start, length, inEdges.size(), numOutEdges);
|
||||
printf("dfsFirst = %ld, dfsLast = %ld, immed dom = %ld\n",
|
||||
dfsFirstNum, dfsLastNum,
|
||||
immedDom == MAX ? -1 : immedDom);
|
||||
printf("loopType = %s, loopHead = %ld, latchNode = %ld, follow = %ld\n",
|
||||
s_loopType[loopType],
|
||||
loopHead == MAX ? -1 : loopHead,
|
||||
latchNode == MAX ? -1 : latchNode,
|
||||
loopFollow == MAX ? -1 : loopFollow);
|
||||
printf ("ifFollow = %ld, caseHead = %ld, caseTail = %ld\n",
|
||||
ifFollow == MAX ? -1 : ifFollow,
|
||||
caseHead == MAX ? -1 : caseHead,
|
||||
caseTail == MAX ? -1 : caseTail);
|
||||
|
||||
if (nodeType == INTERVAL_NODE)
|
||||
printf("corresponding interval = %ld\n", correspInt->numInt);
|
||||
else
|
||||
for (i = 0; i < inEdges.size(); i++)
|
||||
printf (" inEdge[%ld] = %ld\n", i, inEdges[i]->start);
|
||||
|
||||
/* Display out edges information */
|
||||
for (i = 0; i < numOutEdges; i++)
|
||||
if (nodeType == INTERVAL_NODE)
|
||||
printf(" outEdge[%ld] = %ld\n", i,
|
||||
edges[i].BBptr->correspInt->numInt);
|
||||
else
|
||||
printf(" outEdge[%d] = %ld\n", i, edges[i].BBptr->start);
|
||||
printf("----\n");
|
||||
|
||||
/* Recursive call on successors of current node */
|
||||
for (i = 0; i < numOutEdges; i++)
|
||||
if (edges[i].BBptr->traversed != DFS_DISP)
|
||||
edges[i].BBptr->displayDfs();
|
||||
}
|
||||
BIN
tests/inputs/BENCHFN.EXE
Executable file
BIN
tests/inputs/BENCHFN.EXE
Executable file
Binary file not shown.
BIN
tests/inputs/BENCHLNG.EXE
Executable file
BIN
tests/inputs/BENCHLNG.EXE
Executable file
Binary file not shown.
BIN
tests/inputs/BENCHMUL.EXE
Executable file
BIN
tests/inputs/BENCHMUL.EXE
Executable file
Binary file not shown.
BIN
tests/inputs/BENCHMUS.EXE
Executable file
BIN
tests/inputs/BENCHMUS.EXE
Executable file
Binary file not shown.
BIN
tests/inputs/BENCHSHO.EXE
Executable file
BIN
tests/inputs/BENCHSHO.EXE
Executable file
Binary file not shown.
BIN
tests/inputs/BYTEOPS.EXE
Executable file
BIN
tests/inputs/BYTEOPS.EXE
Executable file
Binary file not shown.
BIN
tests/inputs/FIBOS.EXE
Executable file
BIN
tests/inputs/FIBOS.EXE
Executable file
Binary file not shown.
BIN
tests/inputs/MIN.EXE
Executable file
BIN
tests/inputs/MIN.EXE
Executable file
Binary file not shown.
109
tests/outputs/BENCHFN.EXE.a1
Normal file
109
tests/outputs/BENCHFN.EXE.a1
Normal file
@ -0,0 +1,109 @@
|
||||
main PROC NEAR
|
||||
000 000365 55 PUSH bp
|
||||
001 000366 8BEC MOV bp, sp
|
||||
002 000368 83EC08 SUB sp, 8
|
||||
003 00036B B89401 MOV ax, 194h
|
||||
004 00036E 50 PUSH ax
|
||||
005 00036F E8D90B CALL near ptr printf
|
||||
006 000372 59 POP cx
|
||||
007 000373 8D46FC LEA ax, [bp-4]
|
||||
008 000376 50 PUSH ax
|
||||
009 000377 B8B001 MOV ax, 1B0h
|
||||
010 00037A 50 PUSH ax
|
||||
011 00037B E85614 CALL near ptr scanf
|
||||
012 00037E 59 POP cx
|
||||
013 00037F 59 POP cx
|
||||
014 000380 FF76FE PUSH word ptr [bp-2]
|
||||
015 000383 FF76FC PUSH word ptr [bp-4]
|
||||
016 000386 B8B401 MOV ax, 1B4h
|
||||
017 000389 50 PUSH ax
|
||||
018 00038A E8BE0B CALL near ptr printf
|
||||
019 00038D 83C406 ADD sp, 6
|
||||
020 000390 C746FA0000 MOV word ptr [bp-6], 0
|
||||
021 000395 C746F80100 MOV word ptr [bp-8], 1
|
||||
022 00039A EB0B JMP L1
|
||||
|
||||
023 0003A7 8B56FA L1: MOV dx, [bp-6]
|
||||
024 0003AA 8B46F8 MOV ax, [bp-8]
|
||||
025 0003AD 3B56FE CMP dx, [bp-2]
|
||||
026 0003B0 7CEA JL L2
|
||||
027 0003B2 7F05 JG L3
|
||||
028 0003B4 3B46FC CMP ax, [bp-4]
|
||||
029 0003B7 76E3 JBE L2
|
||||
|
||||
030 0003B9 B8CE01 L3: MOV ax, 1CEh
|
||||
031 0003BC 50 PUSH ax
|
||||
032 0003BD E88B0B CALL near ptr printf
|
||||
033 0003C0 59 POP cx
|
||||
034 0003C1 8BE5 MOV sp, bp
|
||||
035 0003C3 5D POP bp
|
||||
036 0003C4 C3 RET
|
||||
|
||||
037 00039C E8A6FF L2: CALL near ptr proc_1
|
||||
038 00039F 8346F801 ADD word ptr [bp-8], 1
|
||||
039 0003A3 8356FA00 ADC word ptr [bp-6], 0
|
||||
040 JMP L1 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
proc_1 PROC NEAR
|
||||
000 000345 55 PUSH bp
|
||||
001 000346 8BEC MOV bp, sp
|
||||
002 000348 E8D7FF CALL near ptr proc_2
|
||||
003 00034B E8D4FF CALL near ptr proc_2
|
||||
004 00034E E8D1FF CALL near ptr proc_2
|
||||
005 000351 E8CEFF CALL near ptr proc_2
|
||||
006 000354 E8CBFF CALL near ptr proc_2
|
||||
007 000357 E8C8FF CALL near ptr proc_2
|
||||
008 00035A E8C5FF CALL near ptr proc_2
|
||||
009 00035D E8C2FF CALL near ptr proc_2
|
||||
010 000360 E8BFFF CALL near ptr proc_2
|
||||
011 000363 5D POP bp
|
||||
012 000364 C3 RET
|
||||
|
||||
proc_1 ENDP
|
||||
|
||||
proc_2 PROC NEAR
|
||||
000 000322 55 PUSH bp
|
||||
001 000323 8BEC MOV bp, sp
|
||||
002 000325 E8D7FF CALL near ptr proc_3
|
||||
003 000328 E8D4FF CALL near ptr proc_3
|
||||
004 00032B E8D1FF CALL near ptr proc_3
|
||||
005 00032E E8CEFF CALL near ptr proc_3
|
||||
006 000331 E8CBFF CALL near ptr proc_3
|
||||
007 000334 E8C8FF CALL near ptr proc_3
|
||||
008 000337 E8C5FF CALL near ptr proc_3
|
||||
009 00033A E8C2FF CALL near ptr proc_3
|
||||
010 00033D E8BFFF CALL near ptr proc_3
|
||||
011 000340 E8BCFF CALL near ptr proc_3
|
||||
012 000343 5D POP bp
|
||||
013 000344 C3 RET
|
||||
|
||||
proc_2 ENDP
|
||||
|
||||
proc_3 PROC NEAR
|
||||
000 0002FF 55 PUSH bp
|
||||
001 000300 8BEC MOV bp, sp
|
||||
002 000302 E8F5FF CALL near ptr proc_4
|
||||
003 000305 E8F2FF CALL near ptr proc_4
|
||||
004 000308 E8EFFF CALL near ptr proc_4
|
||||
005 00030B E8ECFF CALL near ptr proc_4
|
||||
006 00030E E8E9FF CALL near ptr proc_4
|
||||
007 000311 E8E6FF CALL near ptr proc_4
|
||||
008 000314 E8E3FF CALL near ptr proc_4
|
||||
009 000317 E8E0FF CALL near ptr proc_4
|
||||
010 00031A E8DDFF CALL near ptr proc_4
|
||||
011 00031D E8DAFF CALL near ptr proc_4
|
||||
012 000320 5D POP bp
|
||||
013 000321 C3 RET
|
||||
|
||||
proc_3 ENDP
|
||||
|
||||
proc_4 PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 5D POP bp
|
||||
003 0002FE C3 RET
|
||||
|
||||
proc_4 ENDP
|
||||
|
||||
108
tests/outputs/BENCHFN.EXE.a2
Normal file
108
tests/outputs/BENCHFN.EXE.a2
Normal file
@ -0,0 +1,108 @@
|
||||
proc_4 PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 5D POP bp
|
||||
003 0002FE C3 RET
|
||||
|
||||
proc_4 ENDP
|
||||
|
||||
proc_3 PROC NEAR
|
||||
000 0002FF 55 PUSH bp
|
||||
001 000300 8BEC MOV bp, sp
|
||||
002 000302 E8F5FF CALL near ptr proc_4
|
||||
003 000305 E8F2FF CALL near ptr proc_4
|
||||
004 000308 E8EFFF CALL near ptr proc_4
|
||||
005 00030B E8ECFF CALL near ptr proc_4
|
||||
006 00030E E8E9FF CALL near ptr proc_4
|
||||
007 000311 E8E6FF CALL near ptr proc_4
|
||||
008 000314 E8E3FF CALL near ptr proc_4
|
||||
009 000317 E8E0FF CALL near ptr proc_4
|
||||
010 00031A E8DDFF CALL near ptr proc_4
|
||||
011 00031D E8DAFF CALL near ptr proc_4
|
||||
012 000320 5D POP bp
|
||||
013 000321 C3 RET
|
||||
|
||||
proc_3 ENDP
|
||||
|
||||
proc_2 PROC NEAR
|
||||
000 000322 55 PUSH bp
|
||||
001 000323 8BEC MOV bp, sp
|
||||
002 000325 E8D7FF CALL near ptr proc_3
|
||||
003 000328 E8D4FF CALL near ptr proc_3
|
||||
004 00032B E8D1FF CALL near ptr proc_3
|
||||
005 00032E E8CEFF CALL near ptr proc_3
|
||||
006 000331 E8CBFF CALL near ptr proc_3
|
||||
007 000334 E8C8FF CALL near ptr proc_3
|
||||
008 000337 E8C5FF CALL near ptr proc_3
|
||||
009 00033A E8C2FF CALL near ptr proc_3
|
||||
010 00033D E8BFFF CALL near ptr proc_3
|
||||
011 000340 E8BCFF CALL near ptr proc_3
|
||||
012 000343 5D POP bp
|
||||
013 000344 C3 RET
|
||||
|
||||
proc_2 ENDP
|
||||
|
||||
proc_1 PROC NEAR
|
||||
000 000345 55 PUSH bp
|
||||
001 000346 8BEC MOV bp, sp
|
||||
002 000348 E8D7FF CALL near ptr proc_2
|
||||
003 00034B E8D4FF CALL near ptr proc_2
|
||||
004 00034E E8D1FF CALL near ptr proc_2
|
||||
005 000351 E8CEFF CALL near ptr proc_2
|
||||
006 000354 E8CBFF CALL near ptr proc_2
|
||||
007 000357 E8C8FF CALL near ptr proc_2
|
||||
008 00035A E8C5FF CALL near ptr proc_2
|
||||
009 00035D E8C2FF CALL near ptr proc_2
|
||||
010 000360 E8BFFF CALL near ptr proc_2
|
||||
011 000363 5D POP bp
|
||||
012 000364 C3 RET
|
||||
|
||||
proc_1 ENDP
|
||||
|
||||
main PROC NEAR
|
||||
000 000365 55 PUSH bp
|
||||
001 000366 8BEC MOV bp, sp
|
||||
002 000368 83EC08 SUB sp, 8
|
||||
003 00036B B89401 MOV ax, 194h
|
||||
004 00036E 50 PUSH ax
|
||||
005 00036F E8D90B CALL near ptr printf
|
||||
006 000372 59 POP cx
|
||||
007 000373 8D46FC LEA ax, [bp-4]
|
||||
008 000376 50 PUSH ax
|
||||
009 000377 B8B001 MOV ax, 1B0h
|
||||
010 00037A 50 PUSH ax
|
||||
011 00037B E85614 CALL near ptr scanf
|
||||
012 00037E 59 POP cx
|
||||
013 00037F 59 POP cx
|
||||
014 000380 FF76FE PUSH word ptr [bp-2]
|
||||
015 000383 FF76FC PUSH word ptr [bp-4]
|
||||
016 000386 B8B401 MOV ax, 1B4h
|
||||
017 000389 50 PUSH ax
|
||||
018 00038A E8BE0B CALL near ptr printf
|
||||
019 00038D 83C406 ADD sp, 6
|
||||
020 000390 C746FA0000 MOV word ptr [bp-6], 0
|
||||
021 000395 C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
023 0003A7 8B56FA L1: MOV dx, [bp-6]
|
||||
024 0003AA 8B46F8 MOV ax, [bp-8]
|
||||
025 0003AD 3B56FE CMP dx, [bp-2]
|
||||
026 0003B0 7CEA JL L2
|
||||
027 0003B2 7F05 JG L3
|
||||
028 0003B4 3B46FC CMP ax, [bp-4]
|
||||
029 0003B7 76E3 JBE L2
|
||||
|
||||
030 0003B9 B8CE01 L3: MOV ax, 1CEh
|
||||
031 0003BC 50 PUSH ax
|
||||
032 0003BD E88B0B CALL near ptr printf
|
||||
033 0003C0 59 POP cx
|
||||
034 0003C1 8BE5 MOV sp, bp
|
||||
035 0003C3 5D POP bp
|
||||
036 0003C4 C3 RET
|
||||
|
||||
037 00039C E8A6FF L2: CALL near ptr proc_1
|
||||
038 00039F 8346F801 ADD word ptr [bp-8], 1
|
||||
039 0003A3 8356FA00 ADC word ptr [bp-6], 0
|
||||
040 JMP L1 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
89
tests/outputs/BENCHFN.b
Normal file
89
tests/outputs/BENCHFN.b
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHFN.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void proc_4 ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void proc_3 ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
}
|
||||
|
||||
|
||||
void proc_2 ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
}
|
||||
|
||||
|
||||
void proc_1 ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
}
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
long loc1;
|
||||
long loc2;
|
||||
|
||||
printf ("enter number of iterations ");
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc2);
|
||||
loc1 = 1;
|
||||
|
||||
while ((loc1 <= loc2)) {
|
||||
proc_1 ();
|
||||
loc1 = (loc1 + 1);
|
||||
} /* end of while */
|
||||
printf ("finished\n");
|
||||
}
|
||||
|
||||
242
tests/outputs/BENCHLNG.EXE.a1
Normal file
242
tests/outputs/BENCHLNG.EXE.a1
Normal file
@ -0,0 +1,242 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC14 SUB sp, 14h
|
||||
003 000300 8D46FC LEA ax, [bp-4]
|
||||
004 000303 50 PUSH ax
|
||||
005 000304 B89401 MOV ax, 194h
|
||||
006 000307 50 PUSH ax
|
||||
007 000308 E85D15 CALL near ptr scanf
|
||||
008 00030B 59 POP cx
|
||||
009 00030C 59 POP cx
|
||||
010 00030D FF76FE PUSH word ptr [bp-2]
|
||||
011 000310 FF76FC PUSH word ptr [bp-4]
|
||||
012 000313 B89801 MOV ax, 198h
|
||||
013 000316 50 PUSH ax
|
||||
014 000317 E8C50C CALL near ptr printf
|
||||
015 00031A 83C406 ADD sp, 6
|
||||
016 00031D 8D46EC LEA ax, [bp-14h]
|
||||
017 000320 50 PUSH ax
|
||||
018 000321 B8B201 MOV ax, 1B2h
|
||||
019 000324 50 PUSH ax
|
||||
020 000325 E84015 CALL near ptr scanf
|
||||
021 000328 59 POP cx
|
||||
022 000329 59 POP cx
|
||||
023 00032A 8D46F0 LEA ax, [bp-10h]
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E B8B601 MOV ax, 1B6h
|
||||
026 000331 50 PUSH ax
|
||||
027 000332 E83315 CALL near ptr scanf
|
||||
028 000335 59 POP cx
|
||||
029 000336 59 POP cx
|
||||
030 000337 C746FA0000 MOV word ptr [bp-6], 0
|
||||
031 00033C C746F80100 MOV word ptr [bp-8], 1
|
||||
032 000341 E9E900 JMP L1
|
||||
|
||||
033 00042D 8B56FA L1: MOV dx, [bp-6]
|
||||
034 000430 8B46F8 MOV ax, [bp-8]
|
||||
035 000433 3B56FE CMP dx, [bp-2]
|
||||
036 000436 7D03 JGE L2
|
||||
037 000438 E909FF JMP L3
|
||||
|
||||
038 000344 C746F60000 L3: MOV word ptr [bp-0Ah], 0
|
||||
039 000349 C746F40100 MOV word ptr [bp-0Ch], 1
|
||||
040 00034E E9C000 JMP L4
|
||||
|
||||
041 000411 837EF600 L4: CMP word ptr [bp-0Ah], 0
|
||||
042 000415 7D03 JGE L5
|
||||
043 000417 E937FF JMP L6
|
||||
|
||||
044 000351 8B56EE L6: MOV dx, [bp-12h]
|
||||
045 000354 8B46EC MOV ax, [bp-14h]
|
||||
046 000357 0346F0 ADD ax, [bp-10h]
|
||||
047 00035A 1356F2 ADC dx, [bp-0Eh]
|
||||
048 00035D 0346F4 ADD ax, [bp-0Ch]
|
||||
049 000360 1356F6 ADC dx, [bp-0Ah]
|
||||
050 000363 8956EE MOV [bp-12h], dx
|
||||
051 000366 8946EC MOV [bp-14h], ax
|
||||
052 000369 8B56EE MOV dx, [bp-12h]
|
||||
053 00036C 8B46EC MOV ax, [bp-14h]
|
||||
054 00036F D1FA SAR dx, 1
|
||||
055 000371 D1D8 RCR ax, 1
|
||||
056 000373 8956F2 MOV [bp-0Eh], dx
|
||||
057 000376 8946F0 MOV [bp-10h], ax
|
||||
058 000379 33D2 XOR dx, dx
|
||||
059 00037B B80A00 MOV ax, 0Ah
|
||||
060 00037E 52 PUSH dx
|
||||
061 00037F 50 PUSH ax
|
||||
062 000380 FF76F2 PUSH word ptr [bp-0Eh]
|
||||
063 000383 FF76F0 PUSH word ptr [bp-10h]
|
||||
064 000386 9AEB1D1000 CALL far ptr LMOD@
|
||||
065 00038B 8956EE MOV [bp-12h], dx
|
||||
066 00038E 8946EC MOV [bp-14h], ax
|
||||
067 000391 8B56F2 MOV dx, [bp-0Eh]
|
||||
068 000394 8B46F0 MOV ax, [bp-10h]
|
||||
069 000397 3B56F6 CMP dx, [bp-0Ah]
|
||||
070 00039A 750A JNE L7
|
||||
071 00039C 3B46F4 CMP ax, [bp-0Ch]
|
||||
072 00039F 7505 JNE L7
|
||||
073 0003A1 B80100 MOV ax, 1
|
||||
074 0003A4 EB02 JMP L8
|
||||
|
||||
075 0003A8 99 L8: CWD
|
||||
076 0003A9 8956EE MOV [bp-12h], dx
|
||||
077 0003AC 8946EC MOV [bp-14h], ax
|
||||
078 0003AF 8B56EE MOV dx, [bp-12h]
|
||||
079 0003B2 8B46EC MOV ax, [bp-14h]
|
||||
080 0003B5 0B46F4 OR ax, [bp-0Ch]
|
||||
081 0003B8 0B56F6 OR dx, [bp-0Ah]
|
||||
082 0003BB 8956F2 MOV [bp-0Eh], dx
|
||||
083 0003BE 8946F0 MOV [bp-10h], ax
|
||||
084 0003C1 8B46F0 MOV ax, [bp-10h]
|
||||
085 0003C4 0B46F2 OR ax, [bp-0Eh]
|
||||
086 0003C7 7505 JNE L9
|
||||
087 0003C9 B80100 MOV ax, 1
|
||||
088 0003CC EB02 JMP L10
|
||||
|
||||
089 0003D0 99 L10: CWD
|
||||
090 0003D1 8956EE MOV [bp-12h], dx
|
||||
091 0003D4 8946EC MOV [bp-14h], ax
|
||||
092 0003D7 8B56EE MOV dx, [bp-12h]
|
||||
093 0003DA 8B46EC MOV ax, [bp-14h]
|
||||
094 0003DD 0346F4 ADD ax, [bp-0Ch]
|
||||
095 0003E0 1356F6 ADC dx, [bp-0Ah]
|
||||
096 0003E3 8956F2 MOV [bp-0Eh], dx
|
||||
097 0003E6 8946F0 MOV [bp-10h], ax
|
||||
098 0003E9 8B56F2 MOV dx, [bp-0Eh]
|
||||
099 0003EC 8B46F0 MOV ax, [bp-10h]
|
||||
100 0003EF 3B56F6 CMP dx, [bp-0Ah]
|
||||
101 0003F2 7C0C JL L11
|
||||
102 0003F4 7F05 JG L12
|
||||
103 0003F6 3B46F4 CMP ax, [bp-0Ch]
|
||||
104 0003F9 7605 JBE L11
|
||||
|
||||
105 0003FB B80100 L12: MOV ax, 1
|
||||
106 0003FE EB02 JMP L13
|
||||
|
||||
107 000402 99 L13: CWD
|
||||
108 000403 8956EE MOV [bp-12h], dx
|
||||
109 000406 8946EC MOV [bp-14h], ax
|
||||
110 000409 8346F401 ADD word ptr [bp-0Ch], 1
|
||||
111 00040D 8356F600 ADC word ptr [bp-0Ah], 0
|
||||
112 JMP L4 ;Synthetic inst
|
||||
|
||||
113 000400 33C0 L11: XOR ax, ax
|
||||
114 JMP L13 ;Synthetic inst
|
||||
|
||||
115 0003CE 33C0 L9: XOR ax, ax
|
||||
116 JMP L10 ;Synthetic inst
|
||||
|
||||
117 0003A6 33C0 L7: XOR ax, ax
|
||||
118 JMP L8 ;Synthetic inst
|
||||
|
||||
119 00041A 7F09 L5: JG L14
|
||||
120 00041C 837EF428 CMP word ptr [bp-0Ch], 28h
|
||||
121 000420 7703 JA L14
|
||||
122 000422 E92CFF JMP L6
|
||||
|
||||
123 000425 8346F801 L14: ADD word ptr [bp-8], 1
|
||||
124 000429 8356FA00 ADC word ptr [bp-6], 0
|
||||
125 JMP L1 ;Synthetic inst
|
||||
|
||||
126 00043B 7F08 L2: JG L15
|
||||
127 00043D 3B46FC CMP ax, [bp-4]
|
||||
128 000440 7703 JA L15
|
||||
129 000442 E9FFFE JMP L3
|
||||
|
||||
130 000445 FF76EE L15: PUSH word ptr [bp-12h]
|
||||
131 000448 FF76EC PUSH word ptr [bp-14h]
|
||||
132 00044B B8BA01 MOV ax, 1BAh
|
||||
133 00044E 50 PUSH ax
|
||||
134 00044F E88D0B CALL near ptr printf
|
||||
135 000452 83C406 ADD sp, 6
|
||||
136 000455 8BE5 MOV sp, bp
|
||||
137 000457 5D POP bp
|
||||
138 000458 C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
LMOD@ PROC FAR
|
||||
000 001EEB B90200 MOV cx, 2
|
||||
001 001EEE EB03 JMP L16
|
||||
|
||||
002 001EF3 55 L16: PUSH bp
|
||||
003 001EF4 56 PUSH si
|
||||
004 001EF5 57 PUSH di
|
||||
005 001EF6 8BEC MOV bp, sp
|
||||
006 001EF8 8BF9 MOV di, cx
|
||||
007 001EFA 8B460A MOV ax, [bp+0Ah]
|
||||
008 001EFD 8B560C MOV dx, [bp+0Ch]
|
||||
009 001F00 8B5E0E MOV bx, [bp+0Eh]
|
||||
010 001F03 8B4E10 MOV cx, [bp+10h]
|
||||
011 001F06 0BC9 OR cx, cx
|
||||
012 001F08 7508 JNE L17
|
||||
013 001F0A 0BD2 OR dx, dx
|
||||
014 001F0C 7469 JE L18
|
||||
015 001F0E 0BDB OR bx, bx
|
||||
016 001F10 7465 JE L18
|
||||
|
||||
017 001F12 F7C70100 L17: TEST di, 1
|
||||
018 001F16 751C JNE L19
|
||||
019 001F18 0BD2 OR dx, dx
|
||||
020 001F1A 790A JNS L20
|
||||
021 001F1C F7DA NEG dx
|
||||
022 001F1E F7D8 NEG ax
|
||||
023 001F20 83DA00 SBB dx, 0
|
||||
024 001F23 83CF0C OR di, 0Ch
|
||||
|
||||
025 001F26 0BC9 L20: OR cx, cx
|
||||
026 001F28 790A JNS L19
|
||||
027 001F2A F7D9 NEG cx
|
||||
028 001F2C F7DB NEG bx
|
||||
029 001F2E 83D900 SBB cx, 0
|
||||
030 001F31 83F704 XOR di, 4
|
||||
|
||||
031 001F34 8BE9 L19: MOV bp, cx
|
||||
032 001F36 B92000 MOV cx, 20h
|
||||
033 001F39 57 PUSH di
|
||||
034 001F3A 33FF XOR di, di
|
||||
035 001F3C 33F6 XOR si, si
|
||||
|
||||
036 001F3E D1E0 L21: SHL ax, 1
|
||||
037 001F40 D1D2 RCL dx, 1
|
||||
038 001F42 D1D6 RCL si, 1
|
||||
039 001F44 D1D7 RCL di, 1
|
||||
040 001F46 3BFD CMP di, bp
|
||||
041 001F48 720B JB L22
|
||||
042 001F4A 7704 JA L23
|
||||
043 001F4C 3BF3 CMP si, bx
|
||||
044 001F4E 7205 JB L22
|
||||
|
||||
045 001F50 2BF3 L23: SUB si, bx
|
||||
046 001F52 1BFD SBB di, bp
|
||||
047 001F54 40 INC ax
|
||||
|
||||
048 001F55 E2E7 L22: LOOP L21
|
||||
049 001F57 5B POP bx
|
||||
050 001F58 F7C30200 TEST bx, 2
|
||||
051 001F5C 7406 JE L24
|
||||
052 001F5E 8BC6 MOV ax, si
|
||||
053 001F60 8BD7 MOV dx, di
|
||||
054 001F62 D1EB SHR bx, 1
|
||||
|
||||
055 001F64 F7C30400 L24: TEST bx, 4
|
||||
056 001F68 7407 JE L25
|
||||
057 001F6A F7DA NEG dx
|
||||
058 001F6C F7D8 NEG ax
|
||||
059 001F6E 83DA00 SBB dx, 0
|
||||
|
||||
060 001F71 5F L25: POP di
|
||||
061 001F72 5E POP si
|
||||
062 001F73 5D POP bp
|
||||
063 001F74 CA0800 RETF 8
|
||||
065 001F77 F7F3 DIV bx
|
||||
067 001F79 F7C70200 TEST di, 2
|
||||
068 001F7D 7402 JE L26
|
||||
069 001F7F 8BC2 MOV ax, dx
|
||||
|
||||
070 001F81 33D2 L26: XOR dx, dx
|
||||
071 001F83 EBEC JMP L25
|
||||
|
||||
LMOD@ ENDP
|
||||
|
||||
234
tests/outputs/BENCHLNG.EXE.a2
Normal file
234
tests/outputs/BENCHLNG.EXE.a2
Normal file
@ -0,0 +1,234 @@
|
||||
LMOD@ PROC FAR
|
||||
000 001EEB B90200 MOV cx, 2
|
||||
002 001EF3 55 PUSH bp
|
||||
003 001EF4 56 PUSH si
|
||||
004 001EF5 57 PUSH di
|
||||
005 001EF6 8BEC MOV bp, sp
|
||||
006 001EF8 8BF9 MOV di, cx
|
||||
007 001EFA 8B460A MOV ax, [bp+0Ah]
|
||||
008 001EFD 8B560C MOV dx, [bp+0Ch]
|
||||
009 001F00 8B5E0E MOV bx, [bp+0Eh]
|
||||
010 001F03 8B4E10 MOV cx, [bp+10h]
|
||||
011 001F06 0BC9 OR cx, cx
|
||||
012 001F08 7508 JNE L1
|
||||
013 001F0A 0BD2 OR dx, dx
|
||||
014 001F0C 7469 JE L2
|
||||
015 001F0E 0BDB OR bx, bx
|
||||
016 001F10 7465 JE L2
|
||||
|
||||
017 001F12 F7C70100 L1: TEST di, 1
|
||||
018 001F16 751C JNE L3
|
||||
019 001F18 0BD2 OR dx, dx
|
||||
020 001F1A 790A JNS L4
|
||||
021 001F1C F7DA NEG dx
|
||||
022 001F1E F7D8 NEG ax
|
||||
023 001F20 83DA00 SBB dx, 0
|
||||
024 001F23 83CF0C OR di, 0Ch
|
||||
|
||||
025 001F26 0BC9 L4: OR cx, cx
|
||||
026 001F28 790A JNS L3
|
||||
027 001F2A F7D9 NEG cx
|
||||
028 001F2C F7DB NEG bx
|
||||
029 001F2E 83D900 SBB cx, 0
|
||||
030 001F31 83F704 XOR di, 4
|
||||
|
||||
031 001F34 8BE9 L3: MOV bp, cx
|
||||
032 001F36 B92000 MOV cx, 20h
|
||||
033 001F39 57 PUSH di
|
||||
034 001F3A 33FF XOR di, di
|
||||
035 001F3C 33F6 XOR si, si
|
||||
|
||||
036 001F3E D1E0 L5: SHL ax, 1
|
||||
037 001F40 D1D2 RCL dx, 1
|
||||
038 001F42 D1D6 RCL si, 1
|
||||
039 001F44 D1D7 RCL di, 1
|
||||
040 001F46 3BFD CMP di, bp
|
||||
041 001F48 720B JB L6
|
||||
042 001F4A 7704 JA L7
|
||||
043 001F4C 3BF3 CMP si, bx
|
||||
044 001F4E 7205 JB L6
|
||||
|
||||
045 001F50 2BF3 L7: SUB si, bx
|
||||
046 001F52 1BFD SBB di, bp
|
||||
047 001F54 40 INC ax
|
||||
|
||||
048 001F55 E2E7 L6: LOOP L5
|
||||
049 001F57 5B POP bx
|
||||
050 001F58 F7C30200 TEST bx, 2
|
||||
051 001F5C 7406 JE L8
|
||||
052 001F5E 8BC6 MOV ax, si
|
||||
053 001F60 8BD7 MOV dx, di
|
||||
054 001F62 D1EB SHR bx, 1
|
||||
|
||||
055 001F64 F7C30400 L8: TEST bx, 4
|
||||
056 001F68 7407 JE L9
|
||||
057 001F6A F7DA NEG dx
|
||||
058 001F6C F7D8 NEG ax
|
||||
059 001F6E 83DA00 SBB dx, 0
|
||||
|
||||
060 001F71 5F L9: POP di
|
||||
061 001F72 5E POP si
|
||||
062 001F73 5D POP bp
|
||||
063 001F74 CA0800 RETF 8
|
||||
|
||||
064 L2: MOV tmp, dx:ax ;Synthetic inst
|
||||
065 001F77 F7F3 DIV bx
|
||||
066 MOD bx ;Synthetic inst
|
||||
067 001F79 F7C70200 TEST di, 2
|
||||
068 001F7D 7402 JE L10
|
||||
069 001F7F 8BC2 MOV ax, dx
|
||||
|
||||
070 001F81 33D2 L10: XOR dx, dx
|
||||
071 001F83 EBEC JMP L9
|
||||
|
||||
LMOD@ ENDP
|
||||
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC14 SUB sp, 14h
|
||||
003 000300 8D46FC LEA ax, [bp-4]
|
||||
004 000303 50 PUSH ax
|
||||
005 000304 B89401 MOV ax, 194h
|
||||
006 000307 50 PUSH ax
|
||||
007 000308 E85D15 CALL near ptr scanf
|
||||
008 00030B 59 POP cx
|
||||
009 00030C 59 POP cx
|
||||
010 00030D FF76FE PUSH word ptr [bp-2]
|
||||
011 000310 FF76FC PUSH word ptr [bp-4]
|
||||
012 000313 B89801 MOV ax, 198h
|
||||
013 000316 50 PUSH ax
|
||||
014 000317 E8C50C CALL near ptr printf
|
||||
015 00031A 83C406 ADD sp, 6
|
||||
016 00031D 8D46EC LEA ax, [bp-14h]
|
||||
017 000320 50 PUSH ax
|
||||
018 000321 B8B201 MOV ax, 1B2h
|
||||
019 000324 50 PUSH ax
|
||||
020 000325 E84015 CALL near ptr scanf
|
||||
021 000328 59 POP cx
|
||||
022 000329 59 POP cx
|
||||
023 00032A 8D46F0 LEA ax, [bp-10h]
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E B8B601 MOV ax, 1B6h
|
||||
026 000331 50 PUSH ax
|
||||
027 000332 E83315 CALL near ptr scanf
|
||||
028 000335 59 POP cx
|
||||
029 000336 59 POP cx
|
||||
030 000337 C746FA0000 MOV word ptr [bp-6], 0
|
||||
031 00033C C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
033 00042D 8B56FA L11: MOV dx, [bp-6]
|
||||
034 000430 8B46F8 MOV ax, [bp-8]
|
||||
035 000433 3B56FE CMP dx, [bp-2]
|
||||
036 000436 7D03 JGE L12
|
||||
|
||||
038 000344 C746F60000 L13: MOV word ptr [bp-0Ah], 0
|
||||
039 000349 C746F40100 MOV word ptr [bp-0Ch], 1
|
||||
|
||||
041 000411 837EF600 L14: CMP word ptr [bp-0Ah], 0
|
||||
042 000415 7D03 JGE L15
|
||||
|
||||
044 000351 8B56EE L16: MOV dx, [bp-12h]
|
||||
045 000354 8B46EC MOV ax, [bp-14h]
|
||||
046 000357 0346F0 ADD ax, [bp-10h]
|
||||
047 00035A 1356F2 ADC dx, [bp-0Eh]
|
||||
048 00035D 0346F4 ADD ax, [bp-0Ch]
|
||||
049 000360 1356F6 ADC dx, [bp-0Ah]
|
||||
050 000363 8956EE MOV [bp-12h], dx
|
||||
051 000366 8946EC MOV [bp-14h], ax
|
||||
052 000369 8B56EE MOV dx, [bp-12h]
|
||||
053 00036C 8B46EC MOV ax, [bp-14h]
|
||||
054 00036F D1FA SAR dx, 1
|
||||
055 000371 D1D8 RCR ax, 1
|
||||
056 000373 8956F2 MOV [bp-0Eh], dx
|
||||
057 000376 8946F0 MOV [bp-10h], ax
|
||||
058 000379 33D2 XOR dx, dx
|
||||
059 00037B B80A00 MOV ax, 0Ah
|
||||
060 00037E 52 PUSH dx
|
||||
061 00037F 50 PUSH ax
|
||||
062 000380 FF76F2 PUSH word ptr [bp-0Eh]
|
||||
063 000383 FF76F0 PUSH word ptr [bp-10h]
|
||||
064 000386 9AEB1D1000 CALL far ptr LMOD@
|
||||
065 00038B 8956EE MOV [bp-12h], dx
|
||||
066 00038E 8946EC MOV [bp-14h], ax
|
||||
067 000391 8B56F2 MOV dx, [bp-0Eh]
|
||||
068 000394 8B46F0 MOV ax, [bp-10h]
|
||||
069 000397 3B56F6 CMP dx, [bp-0Ah]
|
||||
070 00039A 750A JNE L17
|
||||
071 00039C 3B46F4 CMP ax, [bp-0Ch]
|
||||
072 00039F 7505 JNE L17
|
||||
073 0003A1 B80100 MOV ax, 1
|
||||
|
||||
075 0003A8 99 L18: CWD
|
||||
076 0003A9 8956EE MOV [bp-12h], dx
|
||||
077 0003AC 8946EC MOV [bp-14h], ax
|
||||
078 0003AF 8B56EE MOV dx, [bp-12h]
|
||||
079 0003B2 8B46EC MOV ax, [bp-14h]
|
||||
080 0003B5 0B46F4 OR ax, [bp-0Ch]
|
||||
081 0003B8 0B56F6 OR dx, [bp-0Ah]
|
||||
082 0003BB 8956F2 MOV [bp-0Eh], dx
|
||||
083 0003BE 8946F0 MOV [bp-10h], ax
|
||||
084 0003C1 8B46F0 MOV ax, [bp-10h]
|
||||
085 0003C4 0B46F2 OR ax, [bp-0Eh]
|
||||
086 0003C7 7505 JNE L19
|
||||
087 0003C9 B80100 MOV ax, 1
|
||||
|
||||
089 0003D0 99 L20: CWD
|
||||
090 0003D1 8956EE MOV [bp-12h], dx
|
||||
091 0003D4 8946EC MOV [bp-14h], ax
|
||||
092 0003D7 8B56EE MOV dx, [bp-12h]
|
||||
093 0003DA 8B46EC MOV ax, [bp-14h]
|
||||
094 0003DD 0346F4 ADD ax, [bp-0Ch]
|
||||
095 0003E0 1356F6 ADC dx, [bp-0Ah]
|
||||
096 0003E3 8956F2 MOV [bp-0Eh], dx
|
||||
097 0003E6 8946F0 MOV [bp-10h], ax
|
||||
098 0003E9 8B56F2 MOV dx, [bp-0Eh]
|
||||
099 0003EC 8B46F0 MOV ax, [bp-10h]
|
||||
100 0003EF 3B56F6 CMP dx, [bp-0Ah]
|
||||
101 0003F2 7C0C JL L21
|
||||
102 0003F4 7F05 JG L22
|
||||
103 0003F6 3B46F4 CMP ax, [bp-0Ch]
|
||||
104 0003F9 7605 JBE L21
|
||||
|
||||
105 0003FB B80100 L22: MOV ax, 1
|
||||
|
||||
107 000402 99 L23: CWD
|
||||
108 000403 8956EE MOV [bp-12h], dx
|
||||
109 000406 8946EC MOV [bp-14h], ax
|
||||
110 000409 8346F401 ADD word ptr [bp-0Ch], 1
|
||||
111 00040D 8356F600 ADC word ptr [bp-0Ah], 0
|
||||
112 JMP L14 ;Synthetic inst
|
||||
|
||||
113 000400 33C0 L21: XOR ax, ax
|
||||
114 JMP L23 ;Synthetic inst
|
||||
|
||||
115 0003CE 33C0 L19: XOR ax, ax
|
||||
116 JMP L20 ;Synthetic inst
|
||||
|
||||
117 0003A6 33C0 L17: XOR ax, ax
|
||||
118 JMP L18 ;Synthetic inst
|
||||
|
||||
119 00041A 7F09 L15: JG L24
|
||||
120 00041C 837EF428 CMP word ptr [bp-0Ch], 28h
|
||||
121 000420 7703 JA L24
|
||||
|
||||
123 000425 8346F801 L24: ADD word ptr [bp-8], 1
|
||||
124 000429 8356FA00 ADC word ptr [bp-6], 0
|
||||
125 JMP L11 ;Synthetic inst
|
||||
|
||||
126 00043B 7F08 L12: JG L25
|
||||
127 00043D 3B46FC CMP ax, [bp-4]
|
||||
128 000440 7703 JA L25
|
||||
|
||||
130 000445 FF76EE L25: PUSH word ptr [bp-12h]
|
||||
131 000448 FF76EC PUSH word ptr [bp-14h]
|
||||
132 00044B B8BA01 MOV ax, 1BAh
|
||||
133 00044E 50 PUSH ax
|
||||
134 00044F E88D0B CALL near ptr printf
|
||||
135 000452 83C406 ADD sp, 6
|
||||
136 000455 8BE5 MOV sp, bp
|
||||
137 000457 5D POP bp
|
||||
138 000458 C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
158
tests/outputs/BENCHLNG.b
Normal file
158
tests/outputs/BENCHLNG.b
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHLNG.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
long LMOD@ (long arg0, int arg2int arg3)
|
||||
/* Takes 8 bytes of parameters.
|
||||
* Runtime support routine of the compiler.
|
||||
* Untranslatable routine. Assembler provided.
|
||||
* Return value in registers dx:ax.
|
||||
* Pascal calling convention.
|
||||
*/
|
||||
{
|
||||
MOV cx, 2
|
||||
PUSH bp
|
||||
PUSH si
|
||||
PUSH di
|
||||
MOV bp, sp
|
||||
MOV di, cx
|
||||
MOV ax, [bp+0Ah]
|
||||
MOV dx, [bp+0Ch]
|
||||
MOV bx, [bp+0Eh]
|
||||
MOV cx, [bp+10h]
|
||||
CMP cx, 0
|
||||
JNE L1
|
||||
OR dx, dx
|
||||
JE L2
|
||||
OR bx, bx
|
||||
JE L2
|
||||
|
||||
L1: TEST di, 1
|
||||
JNE L3
|
||||
OR dx, dx
|
||||
JNS L4
|
||||
NEG dx
|
||||
NEG ax
|
||||
SBB dx, 0
|
||||
OR di, 0Ch
|
||||
|
||||
L4: OR cx, cx
|
||||
JNS L3
|
||||
NEG cx
|
||||
NEG bx
|
||||
SBB cx, 0
|
||||
XOR di, 4
|
||||
|
||||
L3: MOV bp, cx
|
||||
MOV cx, 20h
|
||||
PUSH di
|
||||
XOR di, 0
|
||||
XOR si, 0
|
||||
|
||||
L5: SHL ax, 1
|
||||
RCL dx, 1
|
||||
RCL si, 1
|
||||
RCL di, 1
|
||||
CMP di, bp
|
||||
JB L6
|
||||
JA L7
|
||||
CMP si, bx
|
||||
JB L6
|
||||
|
||||
L7: SUB si, bx
|
||||
SBB di, bp
|
||||
INC ax
|
||||
|
||||
L6: LOOP L5
|
||||
POP bx
|
||||
TEST bx, 2
|
||||
JE L8
|
||||
MOV ax, si
|
||||
MOV dx, di
|
||||
SHR bx, 1
|
||||
|
||||
L8: TEST bx, 4
|
||||
JE L9
|
||||
NEG dx
|
||||
NEG ax
|
||||
SBB dx, 0
|
||||
|
||||
L9: POP di
|
||||
POP si
|
||||
POP bp
|
||||
RETF 8
|
||||
|
||||
L2: MOV tmp, dx:ax ;Synthetic inst
|
||||
DIV bx
|
||||
MOD bx ;Synthetic inst
|
||||
TEST di, 2
|
||||
JE L10
|
||||
MOV ax, dx
|
||||
|
||||
L10: XOR dx, dx
|
||||
JMP L9
|
||||
}
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
long loc1;
|
||||
long loc2;
|
||||
long loc3;
|
||||
long loc4;
|
||||
long loc5;
|
||||
int loc6; /* ax */
|
||||
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc5);
|
||||
scanf ("%ld", &loc2);
|
||||
scanf ("%ld", &loc3);
|
||||
loc3 = 1;
|
||||
|
||||
while ((loc3 <= loc5)) {
|
||||
loc2 = 1;
|
||||
|
||||
while ((loc2 <= 40)) {
|
||||
loc4 = ((loc4 + loc1) + loc2);
|
||||
loc1 = (loc4 >> 1);
|
||||
loc4 = LMOD@ (loc1, 10);
|
||||
|
||||
if (loc1 == loc2) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc4 = loc6;
|
||||
loc1 = (loc4 | loc2);
|
||||
|
||||
if ((loc3 | loc9) == 0) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc4 = loc6;
|
||||
loc1 = (loc4 + loc2);
|
||||
|
||||
if (loc1 > loc2) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc4 = loc6;
|
||||
loc2 = (loc2 + 1);
|
||||
} /* end of while */
|
||||
loc3 = (loc3 + 1);
|
||||
} /* end of while */
|
||||
printf ("a=%d\n", loc4);
|
||||
}
|
||||
|
||||
101
tests/outputs/BENCHMUL.EXE.a1
Normal file
101
tests/outputs/BENCHMUL.EXE.a1
Normal file
@ -0,0 +1,101 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0C SUB sp, 0Ch
|
||||
003 000300 56 PUSH si
|
||||
004 000301 B89401 MOV ax, 194h
|
||||
005 000304 50 PUSH ax
|
||||
006 000305 E8530C CALL near ptr printf
|
||||
007 000308 59 POP cx
|
||||
008 000309 8D46FC LEA ax, [bp-4]
|
||||
009 00030C 50 PUSH ax
|
||||
010 00030D B8B001 MOV ax, 1B0h
|
||||
011 000310 50 PUSH ax
|
||||
012 000311 E8D014 CALL near ptr scanf
|
||||
013 000314 59 POP cx
|
||||
014 000315 59 POP cx
|
||||
015 000316 FF76FE PUSH word ptr [bp-2]
|
||||
016 000319 FF76FC PUSH word ptr [bp-4]
|
||||
017 00031C B8B401 MOV ax, 1B4h
|
||||
018 00031F 50 PUSH ax
|
||||
019 000320 E8380C CALL near ptr printf
|
||||
020 000323 83C406 ADD sp, 6
|
||||
021 000326 8D46F4 LEA ax, [bp-0Ch]
|
||||
022 000329 50 PUSH ax
|
||||
023 00032A B8CE01 MOV ax, 1CEh
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E E8B314 CALL near ptr scanf
|
||||
026 000331 59 POP cx
|
||||
027 000332 59 POP cx
|
||||
028 000333 8D46F6 LEA ax, [bp-0Ah]
|
||||
029 000336 50 PUSH ax
|
||||
030 000337 B8D101 MOV ax, 1D1h
|
||||
031 00033A 50 PUSH ax
|
||||
032 00033B E8A614 CALL near ptr scanf
|
||||
033 00033E 59 POP cx
|
||||
034 00033F 59 POP cx
|
||||
035 000340 C746FA0000 MOV word ptr [bp-6], 0
|
||||
036 000345 C746F80100 MOV word ptr [bp-8], 1
|
||||
037 00034A EB66 JMP L1
|
||||
|
||||
038 0003B2 8B56FA L1: MOV dx, [bp-6]
|
||||
039 0003B5 8B46F8 MOV ax, [bp-8]
|
||||
040 0003B8 3B56FE CMP dx, [bp-2]
|
||||
041 0003BB 7C8F JL L2
|
||||
042 0003BD 7F05 JG L3
|
||||
043 0003BF 3B46FC CMP ax, [bp-4]
|
||||
044 0003C2 7688 JBE L2
|
||||
|
||||
045 0003C4 FF76F4 L3: PUSH word ptr [bp-0Ch]
|
||||
046 0003C7 B8D401 MOV ax, 1D4h
|
||||
047 0003CA 50 PUSH ax
|
||||
048 0003CB E88D0B CALL near ptr printf
|
||||
049 0003CE 59 POP cx
|
||||
050 0003CF 59 POP cx
|
||||
051 0003D0 5E POP si
|
||||
052 0003D1 8BE5 MOV sp, bp
|
||||
053 0003D3 5D POP bp
|
||||
054 0003D4 C3 RET
|
||||
|
||||
055 00034C BE0100 L2: MOV si, 1
|
||||
056 00034F EB54 JMP L4
|
||||
|
||||
057 0003A5 83FE28 L4: CMP si, 28h
|
||||
058 0003A8 7EA7 JLE L5
|
||||
059 0003AA 8346F801 ADD word ptr [bp-8], 1
|
||||
060 0003AE 8356FA00 ADC word ptr [bp-6], 0
|
||||
061 JMP L1 ;Synthetic inst
|
||||
|
||||
062 000351 8B46F4 L5: MOV ax, [bp-0Ch]
|
||||
063 000354 F766F4 MUL word ptr [bp-0Ch]
|
||||
064 000357 F766F4 MUL word ptr [bp-0Ch]
|
||||
065 00035A F766F4 MUL word ptr [bp-0Ch]
|
||||
066 00035D F766F4 MUL word ptr [bp-0Ch]
|
||||
067 000360 F766F4 MUL word ptr [bp-0Ch]
|
||||
068 000363 F766F4 MUL word ptr [bp-0Ch]
|
||||
069 000366 F766F4 MUL word ptr [bp-0Ch]
|
||||
070 000369 F766F4 MUL word ptr [bp-0Ch]
|
||||
071 00036C F766F4 MUL word ptr [bp-0Ch]
|
||||
072 00036F F766F4 MUL word ptr [bp-0Ch]
|
||||
073 000372 F766F4 MUL word ptr [bp-0Ch]
|
||||
074 000375 F766F4 MUL word ptr [bp-0Ch]
|
||||
075 000378 F766F4 MUL word ptr [bp-0Ch]
|
||||
076 00037B F766F4 MUL word ptr [bp-0Ch]
|
||||
077 00037E F766F4 MUL word ptr [bp-0Ch]
|
||||
078 000381 F766F4 MUL word ptr [bp-0Ch]
|
||||
079 000384 F766F4 MUL word ptr [bp-0Ch]
|
||||
080 000387 F766F4 MUL word ptr [bp-0Ch]
|
||||
081 00038A F766F4 MUL word ptr [bp-0Ch]
|
||||
082 00038D F766F4 MUL word ptr [bp-0Ch]
|
||||
083 000390 F766F4 MUL word ptr [bp-0Ch]
|
||||
084 000393 F766F4 MUL word ptr [bp-0Ch]
|
||||
085 000396 F766F4 MUL word ptr [bp-0Ch]
|
||||
086 000399 F766F4 MUL word ptr [bp-0Ch]
|
||||
087 00039C BA0300 MOV dx, 3
|
||||
088 00039F F7E2 MUL dx
|
||||
089 0003A1 8946F4 MOV [bp-0Ch], ax
|
||||
090 0003A4 46 INC si
|
||||
091 JMP L4 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
99
tests/outputs/BENCHMUL.EXE.a2
Normal file
99
tests/outputs/BENCHMUL.EXE.a2
Normal file
@ -0,0 +1,99 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0C SUB sp, 0Ch
|
||||
003 000300 56 PUSH si
|
||||
004 000301 B89401 MOV ax, 194h
|
||||
005 000304 50 PUSH ax
|
||||
006 000305 E8530C CALL near ptr printf
|
||||
007 000308 59 POP cx
|
||||
008 000309 8D46FC LEA ax, [bp-4]
|
||||
009 00030C 50 PUSH ax
|
||||
010 00030D B8B001 MOV ax, 1B0h
|
||||
011 000310 50 PUSH ax
|
||||
012 000311 E8D014 CALL near ptr scanf
|
||||
013 000314 59 POP cx
|
||||
014 000315 59 POP cx
|
||||
015 000316 FF76FE PUSH word ptr [bp-2]
|
||||
016 000319 FF76FC PUSH word ptr [bp-4]
|
||||
017 00031C B8B401 MOV ax, 1B4h
|
||||
018 00031F 50 PUSH ax
|
||||
019 000320 E8380C CALL near ptr printf
|
||||
020 000323 83C406 ADD sp, 6
|
||||
021 000326 8D46F4 LEA ax, [bp-0Ch]
|
||||
022 000329 50 PUSH ax
|
||||
023 00032A B8CE01 MOV ax, 1CEh
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E E8B314 CALL near ptr scanf
|
||||
026 000331 59 POP cx
|
||||
027 000332 59 POP cx
|
||||
028 000333 8D46F6 LEA ax, [bp-0Ah]
|
||||
029 000336 50 PUSH ax
|
||||
030 000337 B8D101 MOV ax, 1D1h
|
||||
031 00033A 50 PUSH ax
|
||||
032 00033B E8A614 CALL near ptr scanf
|
||||
033 00033E 59 POP cx
|
||||
034 00033F 59 POP cx
|
||||
035 000340 C746FA0000 MOV word ptr [bp-6], 0
|
||||
036 000345 C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
038 0003B2 8B56FA L1: MOV dx, [bp-6]
|
||||
039 0003B5 8B46F8 MOV ax, [bp-8]
|
||||
040 0003B8 3B56FE CMP dx, [bp-2]
|
||||
041 0003BB 7C8F JL L2
|
||||
042 0003BD 7F05 JG L3
|
||||
043 0003BF 3B46FC CMP ax, [bp-4]
|
||||
044 0003C2 7688 JBE L2
|
||||
|
||||
045 0003C4 FF76F4 L3: PUSH word ptr [bp-0Ch]
|
||||
046 0003C7 B8D401 MOV ax, 1D4h
|
||||
047 0003CA 50 PUSH ax
|
||||
048 0003CB E88D0B CALL near ptr printf
|
||||
049 0003CE 59 POP cx
|
||||
050 0003CF 59 POP cx
|
||||
051 0003D0 5E POP si
|
||||
052 0003D1 8BE5 MOV sp, bp
|
||||
053 0003D3 5D POP bp
|
||||
054 0003D4 C3 RET
|
||||
|
||||
055 00034C BE0100 L2: MOV si, 1
|
||||
|
||||
057 0003A5 83FE28 L4: CMP si, 28h
|
||||
058 0003A8 7EA7 JLE L5
|
||||
059 0003AA 8346F801 ADD word ptr [bp-8], 1
|
||||
060 0003AE 8356FA00 ADC word ptr [bp-6], 0
|
||||
061 JMP L1 ;Synthetic inst
|
||||
|
||||
062 000351 8B46F4 L5: MOV ax, [bp-0Ch]
|
||||
063 000354 F766F4 MUL word ptr [bp-0Ch]
|
||||
064 000357 F766F4 MUL word ptr [bp-0Ch]
|
||||
065 00035A F766F4 MUL word ptr [bp-0Ch]
|
||||
066 00035D F766F4 MUL word ptr [bp-0Ch]
|
||||
067 000360 F766F4 MUL word ptr [bp-0Ch]
|
||||
068 000363 F766F4 MUL word ptr [bp-0Ch]
|
||||
069 000366 F766F4 MUL word ptr [bp-0Ch]
|
||||
070 000369 F766F4 MUL word ptr [bp-0Ch]
|
||||
071 00036C F766F4 MUL word ptr [bp-0Ch]
|
||||
072 00036F F766F4 MUL word ptr [bp-0Ch]
|
||||
073 000372 F766F4 MUL word ptr [bp-0Ch]
|
||||
074 000375 F766F4 MUL word ptr [bp-0Ch]
|
||||
075 000378 F766F4 MUL word ptr [bp-0Ch]
|
||||
076 00037B F766F4 MUL word ptr [bp-0Ch]
|
||||
077 00037E F766F4 MUL word ptr [bp-0Ch]
|
||||
078 000381 F766F4 MUL word ptr [bp-0Ch]
|
||||
079 000384 F766F4 MUL word ptr [bp-0Ch]
|
||||
080 000387 F766F4 MUL word ptr [bp-0Ch]
|
||||
081 00038A F766F4 MUL word ptr [bp-0Ch]
|
||||
082 00038D F766F4 MUL word ptr [bp-0Ch]
|
||||
083 000390 F766F4 MUL word ptr [bp-0Ch]
|
||||
084 000393 F766F4 MUL word ptr [bp-0Ch]
|
||||
085 000396 F766F4 MUL word ptr [bp-0Ch]
|
||||
086 000399 F766F4 MUL word ptr [bp-0Ch]
|
||||
087 00039C BA0300 MOV dx, 3
|
||||
088 00039F F7E2 MUL dx
|
||||
089 0003A1 8946F4 MOV [bp-0Ch], ax
|
||||
090 0003A4 46 INC si
|
||||
091 JMP L4 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
38
tests/outputs/BENCHMUL.b
Normal file
38
tests/outputs/BENCHMUL.b
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHMUL.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
int loc2;
|
||||
long loc3;
|
||||
long loc4;
|
||||
int loc5;
|
||||
|
||||
printf ("enter number of iterations\n");
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc4);
|
||||
scanf ("%d", &loc1);
|
||||
scanf ("%d", &loc2);
|
||||
loc3 = 1;
|
||||
|
||||
while ((loc3 <= loc4)) {
|
||||
loc5 = 1;
|
||||
|
||||
while ((loc5 <= 40)) {
|
||||
loc1 = (((((((((((((((((((((((((loc1 * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * 3);
|
||||
loc5 = (loc5 + 1);
|
||||
} /* end of while */
|
||||
loc3 = (loc3 + 1);
|
||||
} /* end of while */
|
||||
printf ("a=%d\n", loc1);
|
||||
}
|
||||
|
||||
91
tests/outputs/BENCHMUS.EXE.a1
Normal file
91
tests/outputs/BENCHMUS.EXE.a1
Normal file
@ -0,0 +1,91 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0A SUB sp, 0Ah
|
||||
003 000300 56 PUSH si
|
||||
004 000301 57 PUSH di
|
||||
005 000302 B8A801 MOV ax, 1A8h
|
||||
006 000305 50 PUSH ax
|
||||
007 000306 E8240C CALL near ptr printf
|
||||
008 000309 59 POP cx
|
||||
009 00030A 8D46FC LEA ax, [bp-4]
|
||||
010 00030D 50 PUSH ax
|
||||
011 00030E B8C401 MOV ax, 1C4h
|
||||
012 000311 50 PUSH ax
|
||||
013 000312 E8A114 CALL near ptr scanf
|
||||
014 000315 59 POP cx
|
||||
015 000316 59 POP cx
|
||||
016 000317 FF76FE PUSH word ptr [bp-2]
|
||||
017 00031A FF76FC PUSH word ptr [bp-4]
|
||||
018 00031D B8C801 MOV ax, 1C8h
|
||||
019 000320 50 PUSH ax
|
||||
020 000321 E8090C CALL near ptr printf
|
||||
021 000324 83C406 ADD sp, 6
|
||||
022 000327 BE1400 MOV si, 14h
|
||||
023 00032A 8976F6 MOV [bp-0Ah], si
|
||||
024 00032D C746FA0000 MOV word ptr [bp-6], 0
|
||||
025 000332 C746F80100 MOV word ptr [bp-8], 1
|
||||
026 000337 EB4C JMP L1
|
||||
|
||||
027 000385 8B56FA L1: MOV dx, [bp-6]
|
||||
028 000388 8B46F8 MOV ax, [bp-8]
|
||||
029 00038B 3B56FE CMP dx, [bp-2]
|
||||
030 00038E 7CA9 JL L2
|
||||
031 000390 7F05 JG L3
|
||||
032 000392 3B46FC CMP ax, [bp-4]
|
||||
033 000395 76A2 JBE L2
|
||||
|
||||
034 000397 56 L3: PUSH si
|
||||
035 000398 B8E201 MOV ax, 1E2h
|
||||
036 00039B 50 PUSH ax
|
||||
037 00039C E88E0B CALL near ptr printf
|
||||
038 00039F 59 POP cx
|
||||
039 0003A0 59 POP cx
|
||||
040 0003A1 5F POP di
|
||||
041 0003A2 5E POP si
|
||||
042 0003A3 8BE5 MOV sp, bp
|
||||
043 0003A5 5D POP bp
|
||||
044 0003A6 C3 RET
|
||||
|
||||
045 000339 BF0100 L2: MOV di, 1
|
||||
046 00033C EB3A JMP L4
|
||||
|
||||
047 000378 83FF28 L4: CMP di, 28h
|
||||
048 00037B 7EC1 JLE L5
|
||||
049 00037D 8346F801 ADD word ptr [bp-8], 1
|
||||
050 000381 8356FA00 ADC word ptr [bp-6], 0
|
||||
051 JMP L1 ;Synthetic inst
|
||||
|
||||
052 00033E 8BC6 L5: MOV ax, si
|
||||
053 000340 F7E6 MUL si
|
||||
054 000342 F7E6 MUL si
|
||||
055 000344 F7E6 MUL si
|
||||
056 000346 F7E6 MUL si
|
||||
057 000348 F7E6 MUL si
|
||||
058 00034A F7E6 MUL si
|
||||
059 00034C F7E6 MUL si
|
||||
060 00034E F7E6 MUL si
|
||||
061 000350 F7E6 MUL si
|
||||
062 000352 F7E6 MUL si
|
||||
063 000354 F7E6 MUL si
|
||||
064 000356 F7E6 MUL si
|
||||
065 000358 F7E6 MUL si
|
||||
066 00035A F7E6 MUL si
|
||||
067 00035C F7E6 MUL si
|
||||
068 00035E F7E6 MUL si
|
||||
069 000360 F7E6 MUL si
|
||||
070 000362 F7E6 MUL si
|
||||
071 000364 F7E6 MUL si
|
||||
072 000366 F7E6 MUL si
|
||||
073 000368 F7E6 MUL si
|
||||
074 00036A F7E6 MUL si
|
||||
075 00036C F7E6 MUL si
|
||||
076 00036E F7E6 MUL si
|
||||
077 000370 BA0300 MOV dx, 3
|
||||
078 000373 F7E2 MUL dx
|
||||
079 000375 8BF0 MOV si, ax
|
||||
080 000377 47 INC di
|
||||
081 JMP L4 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
89
tests/outputs/BENCHMUS.EXE.a2
Normal file
89
tests/outputs/BENCHMUS.EXE.a2
Normal file
@ -0,0 +1,89 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0A SUB sp, 0Ah
|
||||
003 000300 56 PUSH si
|
||||
004 000301 57 PUSH di
|
||||
005 000302 B8A801 MOV ax, 1A8h
|
||||
006 000305 50 PUSH ax
|
||||
007 000306 E8240C CALL near ptr printf
|
||||
008 000309 59 POP cx
|
||||
009 00030A 8D46FC LEA ax, [bp-4]
|
||||
010 00030D 50 PUSH ax
|
||||
011 00030E B8C401 MOV ax, 1C4h
|
||||
012 000311 50 PUSH ax
|
||||
013 000312 E8A114 CALL near ptr scanf
|
||||
014 000315 59 POP cx
|
||||
015 000316 59 POP cx
|
||||
016 000317 FF76FE PUSH word ptr [bp-2]
|
||||
017 00031A FF76FC PUSH word ptr [bp-4]
|
||||
018 00031D B8C801 MOV ax, 1C8h
|
||||
019 000320 50 PUSH ax
|
||||
020 000321 E8090C CALL near ptr printf
|
||||
021 000324 83C406 ADD sp, 6
|
||||
022 000327 BE1400 MOV si, 14h
|
||||
023 00032A 8976F6 MOV [bp-0Ah], si
|
||||
024 00032D C746FA0000 MOV word ptr [bp-6], 0
|
||||
025 000332 C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
027 000385 8B56FA L1: MOV dx, [bp-6]
|
||||
028 000388 8B46F8 MOV ax, [bp-8]
|
||||
029 00038B 3B56FE CMP dx, [bp-2]
|
||||
030 00038E 7CA9 JL L2
|
||||
031 000390 7F05 JG L3
|
||||
032 000392 3B46FC CMP ax, [bp-4]
|
||||
033 000395 76A2 JBE L2
|
||||
|
||||
034 000397 56 L3: PUSH si
|
||||
035 000398 B8E201 MOV ax, 1E2h
|
||||
036 00039B 50 PUSH ax
|
||||
037 00039C E88E0B CALL near ptr printf
|
||||
038 00039F 59 POP cx
|
||||
039 0003A0 59 POP cx
|
||||
040 0003A1 5F POP di
|
||||
041 0003A2 5E POP si
|
||||
042 0003A3 8BE5 MOV sp, bp
|
||||
043 0003A5 5D POP bp
|
||||
044 0003A6 C3 RET
|
||||
|
||||
045 000339 BF0100 L2: MOV di, 1
|
||||
|
||||
047 000378 83FF28 L4: CMP di, 28h
|
||||
048 00037B 7EC1 JLE L5
|
||||
049 00037D 8346F801 ADD word ptr [bp-8], 1
|
||||
050 000381 8356FA00 ADC word ptr [bp-6], 0
|
||||
051 JMP L1 ;Synthetic inst
|
||||
|
||||
052 00033E 8BC6 L5: MOV ax, si
|
||||
053 000340 F7E6 MUL si
|
||||
054 000342 F7E6 MUL si
|
||||
055 000344 F7E6 MUL si
|
||||
056 000346 F7E6 MUL si
|
||||
057 000348 F7E6 MUL si
|
||||
058 00034A F7E6 MUL si
|
||||
059 00034C F7E6 MUL si
|
||||
060 00034E F7E6 MUL si
|
||||
061 000350 F7E6 MUL si
|
||||
062 000352 F7E6 MUL si
|
||||
063 000354 F7E6 MUL si
|
||||
064 000356 F7E6 MUL si
|
||||
065 000358 F7E6 MUL si
|
||||
066 00035A F7E6 MUL si
|
||||
067 00035C F7E6 MUL si
|
||||
068 00035E F7E6 MUL si
|
||||
069 000360 F7E6 MUL si
|
||||
070 000362 F7E6 MUL si
|
||||
071 000364 F7E6 MUL si
|
||||
072 000366 F7E6 MUL si
|
||||
073 000368 F7E6 MUL si
|
||||
074 00036A F7E6 MUL si
|
||||
075 00036C F7E6 MUL si
|
||||
076 00036E F7E6 MUL si
|
||||
077 000370 BA0300 MOV dx, 3
|
||||
078 000373 F7E2 MUL dx
|
||||
079 000375 8BF0 MOV si, ax
|
||||
080 000377 47 INC di
|
||||
081 JMP L4 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
38
tests/outputs/BENCHMUS.b
Normal file
38
tests/outputs/BENCHMUS.b
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHMUS.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
long loc2;
|
||||
long loc3;
|
||||
int loc4;
|
||||
int loc5;
|
||||
|
||||
printf ("enter number of iterations\n");
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc3);
|
||||
loc4 = 20;
|
||||
loc1 = loc4;
|
||||
loc2 = 1;
|
||||
|
||||
while ((loc2 <= loc3)) {
|
||||
loc5 = 1;
|
||||
|
||||
while ((loc5 <= 40)) {
|
||||
loc4 = (((((((((((((((((((((((((loc4 * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * 3);
|
||||
loc5 = (loc5 + 1);
|
||||
} /* end of while */
|
||||
loc2 = (loc2 + 1);
|
||||
} /* end of while */
|
||||
printf ("a=%d\n", loc4);
|
||||
}
|
||||
|
||||
113
tests/outputs/BENCHSHO.EXE.a1
Normal file
113
tests/outputs/BENCHSHO.EXE.a1
Normal file
@ -0,0 +1,113 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0E SUB sp, 0Eh
|
||||
003 000300 8D46FC LEA ax, [bp-4]
|
||||
004 000303 50 PUSH ax
|
||||
005 000304 B89401 MOV ax, 194h
|
||||
006 000307 50 PUSH ax
|
||||
007 000308 E8E914 CALL near ptr scanf
|
||||
008 00030B 59 POP cx
|
||||
009 00030C 59 POP cx
|
||||
010 00030D FF76FE PUSH word ptr [bp-2]
|
||||
011 000310 FF76FC PUSH word ptr [bp-4]
|
||||
012 000313 B89801 MOV ax, 198h
|
||||
013 000316 50 PUSH ax
|
||||
014 000317 E8510C CALL near ptr printf
|
||||
015 00031A 83C406 ADD sp, 6
|
||||
016 00031D 8D46F2 LEA ax, [bp-0Eh]
|
||||
017 000320 50 PUSH ax
|
||||
018 000321 B8B201 MOV ax, 1B2h
|
||||
019 000324 50 PUSH ax
|
||||
020 000325 E8CC14 CALL near ptr scanf
|
||||
021 000328 59 POP cx
|
||||
022 000329 59 POP cx
|
||||
023 00032A 8D46F4 LEA ax, [bp-0Ch]
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E B8B601 MOV ax, 1B6h
|
||||
026 000331 50 PUSH ax
|
||||
027 000332 E8BF14 CALL near ptr scanf
|
||||
028 000335 59 POP cx
|
||||
029 000336 59 POP cx
|
||||
030 000337 C746FA0000 MOV word ptr [bp-6], 0
|
||||
031 00033C C746F80100 MOV word ptr [bp-8], 1
|
||||
032 000341 E97900 JMP L1
|
||||
|
||||
033 0003BD 8B56FA L1: MOV dx, [bp-6]
|
||||
034 0003C0 8B46F8 MOV ax, [bp-8]
|
||||
035 0003C3 3B56FE CMP dx, [bp-2]
|
||||
036 0003C6 7D03 JGE L2
|
||||
037 0003C8 E979FF JMP L3
|
||||
|
||||
038 000344 C746F60100 L3: MOV word ptr [bp-0Ah], 1
|
||||
039 000349 EB64 JMP L4
|
||||
|
||||
040 0003AF 837EF628 L4: CMP word ptr [bp-0Ah], 28h
|
||||
041 0003B3 7E96 JLE L5
|
||||
042 0003B5 8346F801 ADD word ptr [bp-8], 1
|
||||
043 0003B9 8356FA00 ADC word ptr [bp-6], 0
|
||||
044 JMP L1 ;Synthetic inst
|
||||
|
||||
045 00034B 8B46F2 L5: MOV ax, [bp-0Eh]
|
||||
046 00034E 0346F4 ADD ax, [bp-0Ch]
|
||||
047 000351 0346F6 ADD ax, [bp-0Ah]
|
||||
048 000354 8946F2 MOV [bp-0Eh], ax
|
||||
049 000357 8B46F2 MOV ax, [bp-0Eh]
|
||||
050 00035A D1F8 SAR ax, 1
|
||||
051 00035C 8946F4 MOV [bp-0Ch], ax
|
||||
052 00035F 8B46F4 MOV ax, [bp-0Ch]
|
||||
053 000362 BB0A00 MOV bx, 0Ah
|
||||
054 000365 99 CWD
|
||||
056 000366 F7FB IDIV bx
|
||||
058 000368 8956F2 MOV [bp-0Eh], dx
|
||||
059 00036B 8B46F4 MOV ax, [bp-0Ch]
|
||||
060 00036E 3B46F6 CMP ax, [bp-0Ah]
|
||||
061 000371 7505 JNE L6
|
||||
062 000373 B80100 MOV ax, 1
|
||||
063 000376 EB02 JMP L7
|
||||
|
||||
064 00037A 8946F2 L7: MOV [bp-0Eh], ax
|
||||
065 00037D 8B46F2 MOV ax, [bp-0Eh]
|
||||
066 000380 0B46F6 OR ax, [bp-0Ah]
|
||||
067 000383 8946F4 MOV [bp-0Ch], ax
|
||||
068 000386 8B46F4 MOV ax, [bp-0Ch]
|
||||
069 000389 F7D8 NEG ax
|
||||
070 00038B 1BC0 SBB ax, ax
|
||||
071 00038D 40 INC ax
|
||||
072 00038E 8946F2 MOV [bp-0Eh], ax
|
||||
073 000391 8B46F2 MOV ax, [bp-0Eh]
|
||||
074 000394 0346F6 ADD ax, [bp-0Ah]
|
||||
075 000397 8946F4 MOV [bp-0Ch], ax
|
||||
076 00039A 8B46F4 MOV ax, [bp-0Ch]
|
||||
077 00039D 3B46F6 CMP ax, [bp-0Ah]
|
||||
078 0003A0 7E05 JLE L8
|
||||
079 0003A2 B80100 MOV ax, 1
|
||||
080 0003A5 EB02 JMP L9
|
||||
|
||||
081 0003A9 8946F2 L9: MOV [bp-0Eh], ax
|
||||
082 0003AC FF46F6 INC word ptr [bp-0Ah]
|
||||
083 JMP L4 ;Synthetic inst
|
||||
|
||||
084 0003A7 33C0 L8: XOR ax, ax
|
||||
085 JMP L9 ;Synthetic inst
|
||||
|
||||
086 000378 33C0 L6: XOR ax, ax
|
||||
087 JMP L7 ;Synthetic inst
|
||||
|
||||
088 0003CB 7F08 L2: JG L10
|
||||
089 0003CD 3B46FC CMP ax, [bp-4]
|
||||
090 0003D0 7703 JA L10
|
||||
091 0003D2 E96FFF JMP L3
|
||||
|
||||
092 0003D5 FF76F2 L10: PUSH word ptr [bp-0Eh]
|
||||
093 0003D8 B8BA01 MOV ax, 1BAh
|
||||
094 0003DB 50 PUSH ax
|
||||
095 0003DC E88C0B CALL near ptr printf
|
||||
096 0003DF 59 POP cx
|
||||
097 0003E0 59 POP cx
|
||||
098 0003E1 8BE5 MOV sp, bp
|
||||
099 0003E3 5D POP bp
|
||||
100 0003E4 C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
109
tests/outputs/BENCHSHO.EXE.a2
Normal file
109
tests/outputs/BENCHSHO.EXE.a2
Normal file
@ -0,0 +1,109 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0E SUB sp, 0Eh
|
||||
003 000300 8D46FC LEA ax, [bp-4]
|
||||
004 000303 50 PUSH ax
|
||||
005 000304 B89401 MOV ax, 194h
|
||||
006 000307 50 PUSH ax
|
||||
007 000308 E8E914 CALL near ptr scanf
|
||||
008 00030B 59 POP cx
|
||||
009 00030C 59 POP cx
|
||||
010 00030D FF76FE PUSH word ptr [bp-2]
|
||||
011 000310 FF76FC PUSH word ptr [bp-4]
|
||||
012 000313 B89801 MOV ax, 198h
|
||||
013 000316 50 PUSH ax
|
||||
014 000317 E8510C CALL near ptr printf
|
||||
015 00031A 83C406 ADD sp, 6
|
||||
016 00031D 8D46F2 LEA ax, [bp-0Eh]
|
||||
017 000320 50 PUSH ax
|
||||
018 000321 B8B201 MOV ax, 1B2h
|
||||
019 000324 50 PUSH ax
|
||||
020 000325 E8CC14 CALL near ptr scanf
|
||||
021 000328 59 POP cx
|
||||
022 000329 59 POP cx
|
||||
023 00032A 8D46F4 LEA ax, [bp-0Ch]
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E B8B601 MOV ax, 1B6h
|
||||
026 000331 50 PUSH ax
|
||||
027 000332 E8BF14 CALL near ptr scanf
|
||||
028 000335 59 POP cx
|
||||
029 000336 59 POP cx
|
||||
030 000337 C746FA0000 MOV word ptr [bp-6], 0
|
||||
031 00033C C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
033 0003BD 8B56FA L1: MOV dx, [bp-6]
|
||||
034 0003C0 8B46F8 MOV ax, [bp-8]
|
||||
035 0003C3 3B56FE CMP dx, [bp-2]
|
||||
036 0003C6 7D03 JGE L2
|
||||
|
||||
038 000344 C746F60100 L3: MOV word ptr [bp-0Ah], 1
|
||||
|
||||
040 0003AF 837EF628 L4: CMP word ptr [bp-0Ah], 28h
|
||||
041 0003B3 7E96 JLE L5
|
||||
042 0003B5 8346F801 ADD word ptr [bp-8], 1
|
||||
043 0003B9 8356FA00 ADC word ptr [bp-6], 0
|
||||
044 JMP L1 ;Synthetic inst
|
||||
|
||||
045 00034B 8B46F2 L5: MOV ax, [bp-0Eh]
|
||||
046 00034E 0346F4 ADD ax, [bp-0Ch]
|
||||
047 000351 0346F6 ADD ax, [bp-0Ah]
|
||||
048 000354 8946F2 MOV [bp-0Eh], ax
|
||||
049 000357 8B46F2 MOV ax, [bp-0Eh]
|
||||
050 00035A D1F8 SAR ax, 1
|
||||
051 00035C 8946F4 MOV [bp-0Ch], ax
|
||||
052 00035F 8B46F4 MOV ax, [bp-0Ch]
|
||||
053 000362 BB0A00 MOV bx, 0Ah
|
||||
054 000365 99 CWD
|
||||
055 MOV tmp, dx:ax ;Synthetic inst
|
||||
056 000366 F7FB IDIV bx
|
||||
057 MOD bx ;Synthetic inst
|
||||
058 000368 8956F2 MOV [bp-0Eh], dx
|
||||
059 00036B 8B46F4 MOV ax, [bp-0Ch]
|
||||
060 00036E 3B46F6 CMP ax, [bp-0Ah]
|
||||
061 000371 7505 JNE L6
|
||||
062 000373 B80100 MOV ax, 1
|
||||
|
||||
064 00037A 8946F2 L7: MOV [bp-0Eh], ax
|
||||
065 00037D 8B46F2 MOV ax, [bp-0Eh]
|
||||
066 000380 0B46F6 OR ax, [bp-0Ah]
|
||||
067 000383 8946F4 MOV [bp-0Ch], ax
|
||||
068 000386 8B46F4 MOV ax, [bp-0Ch]
|
||||
069 000389 F7D8 NEG ax
|
||||
070 00038B 1BC0 SBB ax, ax
|
||||
071 00038D 40 INC ax
|
||||
072 00038E 8946F2 MOV [bp-0Eh], ax
|
||||
073 000391 8B46F2 MOV ax, [bp-0Eh]
|
||||
074 000394 0346F6 ADD ax, [bp-0Ah]
|
||||
075 000397 8946F4 MOV [bp-0Ch], ax
|
||||
076 00039A 8B46F4 MOV ax, [bp-0Ch]
|
||||
077 00039D 3B46F6 CMP ax, [bp-0Ah]
|
||||
078 0003A0 7E05 JLE L8
|
||||
079 0003A2 B80100 MOV ax, 1
|
||||
|
||||
081 0003A9 8946F2 L9: MOV [bp-0Eh], ax
|
||||
082 0003AC FF46F6 INC word ptr [bp-0Ah]
|
||||
083 JMP L4 ;Synthetic inst
|
||||
|
||||
084 0003A7 33C0 L8: XOR ax, ax
|
||||
085 JMP L9 ;Synthetic inst
|
||||
|
||||
086 000378 33C0 L6: XOR ax, ax
|
||||
087 JMP L7 ;Synthetic inst
|
||||
|
||||
088 0003CB 7F08 L2: JG L10
|
||||
089 0003CD 3B46FC CMP ax, [bp-4]
|
||||
090 0003D0 7703 JA L10
|
||||
|
||||
092 0003D5 FF76F2 L10: PUSH word ptr [bp-0Eh]
|
||||
093 0003D8 B8BA01 MOV ax, 1BAh
|
||||
094 0003DB 50 PUSH ax
|
||||
095 0003DC E88C0B CALL near ptr printf
|
||||
096 0003DF 59 POP cx
|
||||
097 0003E0 59 POP cx
|
||||
098 0003E1 8BE5 MOV sp, bp
|
||||
099 0003E3 5D POP bp
|
||||
100 0003E4 C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
59
tests/outputs/BENCHSHO.b
Normal file
59
tests/outputs/BENCHSHO.b
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHSHO.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
int loc2;
|
||||
int loc3;
|
||||
long loc4;
|
||||
long loc5;
|
||||
int loc6; /* ax */
|
||||
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc5);
|
||||
scanf ("%ld", &loc1);
|
||||
scanf ("%ld", &loc2);
|
||||
loc4 = 1;
|
||||
|
||||
while ((loc4 <= loc5)) {
|
||||
loc3 = 1;
|
||||
|
||||
while ((loc3 <= 40)) {
|
||||
loc1 = ((loc1 + loc2) + loc3);
|
||||
loc2 = (loc1 >> 1);
|
||||
loc1 = (loc2 % 10);
|
||||
|
||||
if (loc2 == loc3) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc1 = loc6;
|
||||
loc2 = (loc1 | loc3);
|
||||
loc1 = !loc2;
|
||||
loc2 = (loc1 + loc3);
|
||||
|
||||
if (loc2 > loc3) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc1 = loc6;
|
||||
loc3 = (loc3 + 1);
|
||||
} /* end of while */
|
||||
loc4 = (loc4 + 1);
|
||||
} /* end of while */
|
||||
printf ("a=%d\n", loc1);
|
||||
}
|
||||
|
||||
58
tests/outputs/BYTEOPS.EXE.a1
Normal file
58
tests/outputs/BYTEOPS.EXE.a1
Normal file
@ -0,0 +1,58 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC02 SUB sp, 2
|
||||
003 000300 C646FEFF MOV byte ptr [bp-2], 0FFh
|
||||
004 000304 C646FF8F MOV byte ptr [bp-1], 8Fh
|
||||
005 000308 8A46FE MOV al, [bp-2]
|
||||
006 00030B 0246FF ADD al, [bp-1]
|
||||
007 00030E 8846FF MOV [bp-1], al
|
||||
008 000311 8A46FE MOV al, [bp-2]
|
||||
009 000314 2A46FF SUB al, [bp-1]
|
||||
010 000317 8846FE MOV [bp-2], al
|
||||
011 00031A 8A46FE MOV al, [bp-2]
|
||||
012 00031D B400 MOV ah, 0
|
||||
013 00031F 8A56FF MOV dl, [bp-1]
|
||||
014 000322 B600 MOV dh, 0
|
||||
015 000324 F7E2 MUL dx
|
||||
016 000326 8846FE MOV [bp-2], al
|
||||
017 000329 8A46FF MOV al, [bp-1]
|
||||
018 00032C B400 MOV ah, 0
|
||||
019 00032E 8A56FE MOV dl, [bp-2]
|
||||
020 000331 B600 MOV dh, 0
|
||||
021 000333 8BDA MOV bx, dx
|
||||
022 000335 99 CWD
|
||||
024 000336 F7FB IDIV bx
|
||||
026 000338 8846FF MOV [bp-1], al
|
||||
027 00033B 8A46FF MOV al, [bp-1]
|
||||
028 00033E B400 MOV ah, 0
|
||||
029 000340 8A56FE MOV dl, [bp-2]
|
||||
030 000343 B600 MOV dh, 0
|
||||
031 000345 8BDA MOV bx, dx
|
||||
032 000347 99 CWD
|
||||
034 000348 F7FB IDIV bx
|
||||
036 00034A 8856FF MOV [bp-1], dl
|
||||
037 00034D 8A46FE MOV al, [bp-2]
|
||||
038 000350 B105 MOV cl, 5
|
||||
039 000352 D2E0 SHL al, cl
|
||||
040 000354 8846FE MOV [bp-2], al
|
||||
041 000357 8A46FF MOV al, [bp-1]
|
||||
042 00035A 8A4EFE MOV cl, [bp-2]
|
||||
043 00035D D2E8 SHR al, cl
|
||||
044 00035F 8846FF MOV [bp-1], al
|
||||
045 000362 8A46FF MOV al, [bp-1]
|
||||
046 000365 B400 MOV ah, 0
|
||||
047 000367 50 PUSH ax
|
||||
048 000368 8A46FE MOV al, [bp-2]
|
||||
049 00036B B400 MOV ah, 0
|
||||
050 00036D 50 PUSH ax
|
||||
051 00036E B89401 MOV ax, 194h
|
||||
052 000371 50 PUSH ax
|
||||
053 000372 E8AB06 CALL near ptr printf
|
||||
054 000375 83C406 ADD sp, 6
|
||||
055 000378 8BE5 MOV sp, bp
|
||||
056 00037A 5D POP bp
|
||||
057 00037B C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
62
tests/outputs/BYTEOPS.EXE.a2
Normal file
62
tests/outputs/BYTEOPS.EXE.a2
Normal file
@ -0,0 +1,62 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC02 SUB sp, 2
|
||||
003 000300 C646FEFF MOV byte ptr [bp-2], 0FFh
|
||||
004 000304 C646FF8F MOV byte ptr [bp-1], 8Fh
|
||||
005 000308 8A46FE MOV al, [bp-2]
|
||||
006 00030B 0246FF ADD al, [bp-1]
|
||||
007 00030E 8846FF MOV [bp-1], al
|
||||
008 000311 8A46FE MOV al, [bp-2]
|
||||
009 000314 2A46FF SUB al, [bp-1]
|
||||
010 000317 8846FE MOV [bp-2], al
|
||||
011 00031A 8A46FE MOV al, [bp-2]
|
||||
012 00031D B400 MOV ah, 0
|
||||
013 00031F 8A56FF MOV dl, [bp-1]
|
||||
014 000322 B600 MOV dh, 0
|
||||
015 000324 F7E2 MUL dx
|
||||
016 000326 8846FE MOV [bp-2], al
|
||||
017 000329 8A46FF MOV al, [bp-1]
|
||||
018 00032C B400 MOV ah, 0
|
||||
019 00032E 8A56FE MOV dl, [bp-2]
|
||||
020 000331 B600 MOV dh, 0
|
||||
021 000333 8BDA MOV bx, dx
|
||||
022 000335 99 CWD
|
||||
023 MOV tmp, dx:ax ;Synthetic inst
|
||||
024 000336 F7FB IDIV bx
|
||||
025 MOD bx ;Synthetic inst
|
||||
026 000338 8846FF MOV [bp-1], al
|
||||
027 00033B 8A46FF MOV al, [bp-1]
|
||||
028 00033E B400 MOV ah, 0
|
||||
029 000340 8A56FE MOV dl, [bp-2]
|
||||
030 000343 B600 MOV dh, 0
|
||||
031 000345 8BDA MOV bx, dx
|
||||
032 000347 99 CWD
|
||||
033 MOV tmp, dx:ax ;Synthetic inst
|
||||
034 000348 F7FB IDIV bx
|
||||
035 MOD bx ;Synthetic inst
|
||||
036 00034A 8856FF MOV [bp-1], dl
|
||||
037 00034D 8A46FE MOV al, [bp-2]
|
||||
038 000350 B105 MOV cl, 5
|
||||
039 000352 D2E0 SHL al, cl
|
||||
040 000354 8846FE MOV [bp-2], al
|
||||
041 000357 8A46FF MOV al, [bp-1]
|
||||
042 00035A 8A4EFE MOV cl, [bp-2]
|
||||
043 00035D D2E8 SHR al, cl
|
||||
044 00035F 8846FF MOV [bp-1], al
|
||||
045 000362 8A46FF MOV al, [bp-1]
|
||||
046 000365 B400 MOV ah, 0
|
||||
047 000367 50 PUSH ax
|
||||
048 000368 8A46FE MOV al, [bp-2]
|
||||
049 00036B B400 MOV ah, 0
|
||||
050 00036D 50 PUSH ax
|
||||
051 00036E B89401 MOV ax, 194h
|
||||
052 000371 50 PUSH ax
|
||||
053 000372 E8AB06 CALL near ptr printf
|
||||
054 000375 83C406 ADD sp, 6
|
||||
055 000378 8BE5 MOV sp, bp
|
||||
056 00037A 5D POP bp
|
||||
057 00037B C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
28
tests/outputs/BYTEOPS.b
Normal file
28
tests/outputs/BYTEOPS.b
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BYTEOPS.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
int loc2;
|
||||
|
||||
loc1 = 255;
|
||||
loc2 = 143;
|
||||
loc2 = (loc1 + loc2);
|
||||
loc1 = (loc1 - loc2);
|
||||
loc1 = (loc1 * loc2);
|
||||
loc2 = (loc2 / loc1);
|
||||
loc2 = (loc2 % loc1);
|
||||
loc1 = (loc1 << 5);
|
||||
loc2 = (loc2 >> loc1);
|
||||
printf ("a = %d, b = %d\n", loc1, loc2);
|
||||
}
|
||||
|
||||
90
tests/outputs/FIBOS.EXE.a1
Normal file
90
tests/outputs/FIBOS.EXE.a1
Normal file
@ -0,0 +1,90 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC04 SUB sp, 4
|
||||
003 000300 56 PUSH si
|
||||
004 000301 57 PUSH di
|
||||
005 000302 B89401 MOV ax, 194h
|
||||
006 000305 50 PUSH ax
|
||||
007 000306 E8080C CALL near ptr printf
|
||||
008 000309 59 POP cx
|
||||
009 00030A 8D46FC LEA ax, [bp-4]
|
||||
010 00030D 50 PUSH ax
|
||||
011 00030E B8B101 MOV ax, 1B1h
|
||||
012 000311 50 PUSH ax
|
||||
013 000312 E88514 CALL near ptr scanf
|
||||
014 000315 59 POP cx
|
||||
015 000316 59 POP cx
|
||||
016 000317 BE0100 MOV si, 1
|
||||
017 00031A EB2D JMP L1
|
||||
|
||||
018 000349 3B76FC L1: CMP si, [bp-4]
|
||||
019 00034C 7ECE JLE L2
|
||||
020 00034E 33C0 XOR ax, ax
|
||||
021 000350 50 PUSH ax
|
||||
022 000351 E87300 CALL near ptr exit
|
||||
023 000354 59 POP cx
|
||||
024 000355 5F POP di
|
||||
025 000356 5E POP si
|
||||
026 000357 8BE5 MOV sp, bp
|
||||
027 000359 5D POP bp
|
||||
028 00035A C3 RET
|
||||
|
||||
029 00031C B8B401 L2: MOV ax, 1B4h
|
||||
030 00031F 50 PUSH ax
|
||||
031 000320 E8EE0B CALL near ptr printf
|
||||
032 000323 59 POP cx
|
||||
033 000324 8D46FE LEA ax, [bp-2]
|
||||
034 000327 50 PUSH ax
|
||||
035 000328 B8C301 MOV ax, 1C3h
|
||||
036 00032B 50 PUSH ax
|
||||
037 00032C E86B14 CALL near ptr scanf
|
||||
038 00032F 59 POP cx
|
||||
039 000330 59 POP cx
|
||||
040 000331 FF76FE PUSH word ptr [bp-2]
|
||||
041 000334 E82400 CALL near ptr proc_1
|
||||
042 000337 59 POP cx
|
||||
043 000338 8BF8 MOV di, ax
|
||||
044 00033A 57 PUSH di
|
||||
045 00033B FF76FE PUSH word ptr [bp-2]
|
||||
046 00033E B8C601 MOV ax, 1C6h
|
||||
047 000341 50 PUSH ax
|
||||
048 000342 E8CC0B CALL near ptr printf
|
||||
049 000345 83C406 ADD sp, 6
|
||||
050 000348 46 INC si
|
||||
051 JMP L1 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
proc_1 PROC NEAR
|
||||
000 00035B 55 PUSH bp
|
||||
001 00035C 8BEC MOV bp, sp
|
||||
002 00035E 56 PUSH si
|
||||
003 00035F 8B7604 MOV si, [bp+4]
|
||||
004 000362 83FE02 CMP si, 2
|
||||
005 000365 7E1C JLE L3
|
||||
006 000367 8BC6 MOV ax, si
|
||||
007 000369 48 DEC ax
|
||||
008 00036A 50 PUSH ax
|
||||
009 00036B E8EDFF CALL near ptr proc_1
|
||||
010 00036E 59 POP cx
|
||||
011 00036F 50 PUSH ax
|
||||
012 000370 8BC6 MOV ax, si
|
||||
013 000372 05FEFF ADD ax, 0FFFEh
|
||||
014 000375 50 PUSH ax
|
||||
015 000376 E8E2FF CALL near ptr proc_1
|
||||
016 000379 59 POP cx
|
||||
017 00037A 8BD0 MOV dx, ax
|
||||
018 00037C 58 POP ax
|
||||
019 00037D 03C2 ADD ax, dx
|
||||
020 00037F EB07 JMP L4
|
||||
|
||||
021 000388 5E L4: POP si
|
||||
022 000389 5D POP bp
|
||||
023 00038A C3 RET
|
||||
|
||||
024 000383 B80100 L3: MOV ax, 1
|
||||
025 000386 EB00 JMP L4
|
||||
|
||||
proc_1 ENDP
|
||||
|
||||
88
tests/outputs/FIBOS.EXE.a2
Normal file
88
tests/outputs/FIBOS.EXE.a2
Normal file
@ -0,0 +1,88 @@
|
||||
proc_1 PROC NEAR
|
||||
000 00035B 55 PUSH bp
|
||||
001 00035C 8BEC MOV bp, sp
|
||||
002 00035E 56 PUSH si
|
||||
003 00035F 8B7604 MOV si, [bp+4]
|
||||
004 000362 83FE02 CMP si, 2
|
||||
005 000365 7E1C JLE L1
|
||||
006 000367 8BC6 MOV ax, si
|
||||
007 000369 48 DEC ax
|
||||
008 00036A 50 PUSH ax
|
||||
009 00036B E8EDFF CALL near ptr proc_1
|
||||
010 00036E 59 POP cx
|
||||
011 00036F 50 PUSH ax
|
||||
012 000370 8BC6 MOV ax, si
|
||||
013 000372 05FEFF ADD ax, 0FFFEh
|
||||
014 000375 50 PUSH ax
|
||||
015 000376 E8E2FF CALL near ptr proc_1
|
||||
016 000379 59 POP cx
|
||||
017 00037A 8BD0 MOV dx, ax
|
||||
018 00037C 58 POP ax
|
||||
019 00037D 03C2 ADD ax, dx
|
||||
|
||||
021 000388 5E L2: POP si
|
||||
022 000389 5D POP bp
|
||||
023 00038A C3 RET
|
||||
|
||||
024 000383 B80100 L1: MOV ax, 1
|
||||
025 000386 EB00 JMP L2
|
||||
|
||||
proc_1 ENDP
|
||||
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC04 SUB sp, 4
|
||||
003 000300 56 PUSH si
|
||||
004 000301 57 PUSH di
|
||||
005 000302 B89401 MOV ax, 194h
|
||||
006 000305 50 PUSH ax
|
||||
007 000306 E8080C CALL near ptr printf
|
||||
008 000309 59 POP cx
|
||||
009 00030A 8D46FC LEA ax, [bp-4]
|
||||
010 00030D 50 PUSH ax
|
||||
011 00030E B8B101 MOV ax, 1B1h
|
||||
012 000311 50 PUSH ax
|
||||
013 000312 E88514 CALL near ptr scanf
|
||||
014 000315 59 POP cx
|
||||
015 000316 59 POP cx
|
||||
016 000317 BE0100 MOV si, 1
|
||||
|
||||
018 000349 3B76FC L3: CMP si, [bp-4]
|
||||
019 00034C 7ECE JLE L4
|
||||
020 00034E 33C0 XOR ax, ax
|
||||
021 000350 50 PUSH ax
|
||||
022 000351 E87300 CALL near ptr exit
|
||||
023 000354 59 POP cx
|
||||
024 000355 5F POP di
|
||||
025 000356 5E POP si
|
||||
026 000357 8BE5 MOV sp, bp
|
||||
027 000359 5D POP bp
|
||||
028 00035A C3 RET
|
||||
|
||||
029 00031C B8B401 L4: MOV ax, 1B4h
|
||||
030 00031F 50 PUSH ax
|
||||
031 000320 E8EE0B CALL near ptr printf
|
||||
032 000323 59 POP cx
|
||||
033 000324 8D46FE LEA ax, [bp-2]
|
||||
034 000327 50 PUSH ax
|
||||
035 000328 B8C301 MOV ax, 1C3h
|
||||
036 00032B 50 PUSH ax
|
||||
037 00032C E86B14 CALL near ptr scanf
|
||||
038 00032F 59 POP cx
|
||||
039 000330 59 POP cx
|
||||
040 000331 FF76FE PUSH word ptr [bp-2]
|
||||
041 000334 E82400 CALL near ptr proc_1
|
||||
042 000337 59 POP cx
|
||||
043 000338 8BF8 MOV di, ax
|
||||
044 00033A 57 PUSH di
|
||||
045 00033B FF76FE PUSH word ptr [bp-2]
|
||||
046 00033E B8C601 MOV ax, 1C6h
|
||||
047 000341 50 PUSH ax
|
||||
048 000342 E8CC0B CALL near ptr printf
|
||||
049 000345 83C406 ADD sp, 6
|
||||
050 000348 46 INC si
|
||||
051 JMP L3 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
53
tests/outputs/FIBOS.b
Normal file
53
tests/outputs/FIBOS.b
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/FIBOS.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
int proc_1 (int arg0)
|
||||
/* Takes 2 bytes of parameters.
|
||||
* High-level language prologue code.
|
||||
* C calling convention.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
int loc2; /* ax */
|
||||
|
||||
loc1 = arg0;
|
||||
|
||||
if (loc1 > 2) {
|
||||
loc2 = (proc_1 ((loc1 - 1)) + proc_1 ((loc1 + 0xfffe)));
|
||||
}
|
||||
else {
|
||||
loc2 = 1;
|
||||
}
|
||||
return (loc2);
|
||||
}
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
int loc2;
|
||||
int loc3;
|
||||
int loc4;
|
||||
|
||||
printf ("Input number of iterations: ");
|
||||
scanf ("%d", &loc1);
|
||||
loc3 = 1;
|
||||
|
||||
while ((loc3 <= loc1)) {
|
||||
printf ("Input number: ");
|
||||
scanf ("%d", &loc2);
|
||||
loc4 = proc_1 (loc2);
|
||||
printf ("fibonacci(%d) = %u\n", loc2, loc4);
|
||||
loc3 = (loc3 + 1);
|
||||
} /* end of while */
|
||||
exit (0);
|
||||
}
|
||||
|
||||
39
tests/outputs/MIN.EXE.a1
Normal file
39
tests/outputs/MIN.EXE.a1
Normal file
@ -0,0 +1,39 @@
|
||||
PROC NEAR
|
||||
000 000100 55 PUSH bp
|
||||
001 000101 8BEC MOV bp, sp
|
||||
002 000103 83EC02 SUB sp, 2
|
||||
003 000106 C746FE0000 MOV word ptr [bp-2], 0
|
||||
004 00010B 8B46FE MOV ax, [bp-2]
|
||||
005 00010E 3D0600 CMP ax, 6
|
||||
006 000111 7735 JA L1
|
||||
007 000113 8BD8 MOV bx, ax
|
||||
008 000115 D1E3 SHL bx, 1
|
||||
009 000117 2EFFA71C00 JMP word ptr cs:[bx+1Ch] ;Switch
|
||||
|
||||
010 00012A B80200 MOV ax, 2 ;Case l0
|
||||
011 00012D EB1E JMP L2
|
||||
|
||||
012 00014D 8BE5 L2: MOV sp, bp
|
||||
013 00014F 5D POP bp
|
||||
014 000150 C3 RET
|
||||
|
||||
015 00012F B80300 MOV ax, 3 ;Case l1
|
||||
016 000132 EB19 JMP L2
|
||||
|
||||
017 000134 B80700 MOV ax, 7 ;Case l2
|
||||
018 000137 EB14 JMP L2
|
||||
|
||||
019 000139 B80D00 MOV ax, 0Dh ;Case l3
|
||||
020 00013C EB0F JMP L2
|
||||
|
||||
021 000148 B82C00 L1: MOV ax, 2Ch ;Case l4
|
||||
022 00014B EB00 JMP L2
|
||||
|
||||
023 00013E B81700 MOV ax, 17h ;Case l5
|
||||
024 000141 EB0A JMP L2
|
||||
|
||||
025 000143 B80D00 MOV ax, 0Dh ;Case l6
|
||||
026 000146 EB05 JMP L2
|
||||
|
||||
ENDP
|
||||
|
||||
38
tests/outputs/MIN.EXE.a2
Normal file
38
tests/outputs/MIN.EXE.a2
Normal file
@ -0,0 +1,38 @@
|
||||
PROC NEAR
|
||||
000 000100 55 PUSH bp
|
||||
001 000101 8BEC MOV bp, sp
|
||||
002 000103 83EC02 SUB sp, 2
|
||||
003 000106 C746FE0000 MOV word ptr [bp-2], 0
|
||||
004 00010B 8B46FE MOV ax, [bp-2]
|
||||
005 00010E 3D0600 CMP ax, 6
|
||||
006 000111 7735 JA L1
|
||||
007 000113 8BD8 MOV bx, ax
|
||||
008 000115 D1E3 SHL bx, 1
|
||||
009 000117 2EFFA71C00 JMP word ptr cs:[bx+1Ch] ;Switch
|
||||
|
||||
010 00012A B80200 MOV ax, 2 ;Case l0
|
||||
|
||||
012 00014D 8BE5 L2: MOV sp, bp
|
||||
013 00014F 5D POP bp
|
||||
014 000150 C3 RET
|
||||
|
||||
015 00012F B80300 MOV ax, 3 ;Case l1
|
||||
016 000132 EB19 JMP L2
|
||||
|
||||
017 000134 B80700 MOV ax, 7 ;Case l2
|
||||
018 000137 EB14 JMP L2
|
||||
|
||||
019 000139 B80D00 MOV ax, 0Dh ;Case l3
|
||||
020 00013C EB0F JMP L2
|
||||
|
||||
021 000148 B82C00 L1: MOV ax, 2Ch ;Case l4
|
||||
022 00014B EB00 JMP L2
|
||||
|
||||
023 00013E B81700 MOV ax, 17h ;Case l5
|
||||
024 000141 EB0A JMP L2
|
||||
|
||||
025 000143 B80D00 MOV ax, 0Dh ;Case l6
|
||||
026 000146 EB05 JMP L2
|
||||
|
||||
ENDP
|
||||
|
||||
27
tests/outputs/MIN.b
Normal file
27
tests/outputs/MIN.b
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/MIN.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
int loc2; /* ax */
|
||||
int loc3; /* bx */
|
||||
|
||||
loc1 = 0;
|
||||
loc2 = loc1;
|
||||
|
||||
if (loc2 <= 6) {
|
||||
loc3 = loc2;
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
|
||||
109
tests/prev/BENCHFN.EXE.a1
Executable file
109
tests/prev/BENCHFN.EXE.a1
Executable file
@ -0,0 +1,109 @@
|
||||
main PROC NEAR
|
||||
000 000365 55 PUSH bp
|
||||
001 000366 8BEC MOV bp, sp
|
||||
002 000368 83EC08 SUB sp, 8
|
||||
003 00036B B89401 MOV ax, 194h
|
||||
004 00036E 50 PUSH ax
|
||||
005 00036F E8D90B CALL near ptr printf
|
||||
006 000372 59 POP cx
|
||||
007 000373 8D46FC LEA ax, [bp-4]
|
||||
008 000376 50 PUSH ax
|
||||
009 000377 B8B001 MOV ax, 1B0h
|
||||
010 00037A 50 PUSH ax
|
||||
011 00037B E85614 CALL near ptr scanf
|
||||
012 00037E 59 POP cx
|
||||
013 00037F 59 POP cx
|
||||
014 000380 FF76FE PUSH word ptr [bp-2]
|
||||
015 000383 FF76FC PUSH word ptr [bp-4]
|
||||
016 000386 B8B401 MOV ax, 1B4h
|
||||
017 000389 50 PUSH ax
|
||||
018 00038A E8BE0B CALL near ptr printf
|
||||
019 00038D 83C406 ADD sp, 6
|
||||
020 000390 C746FA0000 MOV word ptr [bp-6], 0
|
||||
021 000395 C746F80100 MOV word ptr [bp-8], 1
|
||||
022 00039A EB0B JMP L1
|
||||
|
||||
023 0003A7 8B56FA L1: MOV dx, [bp-6]
|
||||
024 0003AA 8B46F8 MOV ax, [bp-8]
|
||||
025 0003AD 3B56FE CMP dx, [bp-2]
|
||||
026 0003B0 7CEA JL L2
|
||||
027 0003B2 7F05 JG L3
|
||||
028 0003B4 3B46FC CMP ax, [bp-4]
|
||||
029 0003B7 76E3 JBE L2
|
||||
|
||||
030 0003B9 B8CE01 L3: MOV ax, 1CEh
|
||||
031 0003BC 50 PUSH ax
|
||||
032 0003BD E88B0B CALL near ptr printf
|
||||
033 0003C0 59 POP cx
|
||||
034 0003C1 8BE5 MOV sp, bp
|
||||
035 0003C3 5D POP bp
|
||||
036 0003C4 C3 RET
|
||||
|
||||
037 00039C E8A6FF L2: CALL near ptr proc_1
|
||||
038 00039F 8346F801 ADD word ptr [bp-8], 1
|
||||
039 0003A3 8356FA00 ADC word ptr [bp-6], 0
|
||||
040 JMP L1 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
proc_1 PROC NEAR
|
||||
000 000345 55 PUSH bp
|
||||
001 000346 8BEC MOV bp, sp
|
||||
002 000348 E8D7FF CALL near ptr proc_2
|
||||
003 00034B E8D4FF CALL near ptr proc_2
|
||||
004 00034E E8D1FF CALL near ptr proc_2
|
||||
005 000351 E8CEFF CALL near ptr proc_2
|
||||
006 000354 E8CBFF CALL near ptr proc_2
|
||||
007 000357 E8C8FF CALL near ptr proc_2
|
||||
008 00035A E8C5FF CALL near ptr proc_2
|
||||
009 00035D E8C2FF CALL near ptr proc_2
|
||||
010 000360 E8BFFF CALL near ptr proc_2
|
||||
011 000363 5D POP bp
|
||||
012 000364 C3 RET
|
||||
|
||||
proc_1 ENDP
|
||||
|
||||
proc_2 PROC NEAR
|
||||
000 000322 55 PUSH bp
|
||||
001 000323 8BEC MOV bp, sp
|
||||
002 000325 E8D7FF CALL near ptr proc_3
|
||||
003 000328 E8D4FF CALL near ptr proc_3
|
||||
004 00032B E8D1FF CALL near ptr proc_3
|
||||
005 00032E E8CEFF CALL near ptr proc_3
|
||||
006 000331 E8CBFF CALL near ptr proc_3
|
||||
007 000334 E8C8FF CALL near ptr proc_3
|
||||
008 000337 E8C5FF CALL near ptr proc_3
|
||||
009 00033A E8C2FF CALL near ptr proc_3
|
||||
010 00033D E8BFFF CALL near ptr proc_3
|
||||
011 000340 E8BCFF CALL near ptr proc_3
|
||||
012 000343 5D POP bp
|
||||
013 000344 C3 RET
|
||||
|
||||
proc_2 ENDP
|
||||
|
||||
proc_3 PROC NEAR
|
||||
000 0002FF 55 PUSH bp
|
||||
001 000300 8BEC MOV bp, sp
|
||||
002 000302 E8F5FF CALL near ptr proc_4
|
||||
003 000305 E8F2FF CALL near ptr proc_4
|
||||
004 000308 E8EFFF CALL near ptr proc_4
|
||||
005 00030B E8ECFF CALL near ptr proc_4
|
||||
006 00030E E8E9FF CALL near ptr proc_4
|
||||
007 000311 E8E6FF CALL near ptr proc_4
|
||||
008 000314 E8E3FF CALL near ptr proc_4
|
||||
009 000317 E8E0FF CALL near ptr proc_4
|
||||
010 00031A E8DDFF CALL near ptr proc_4
|
||||
011 00031D E8DAFF CALL near ptr proc_4
|
||||
012 000320 5D POP bp
|
||||
013 000321 C3 RET
|
||||
|
||||
proc_3 ENDP
|
||||
|
||||
proc_4 PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 5D POP bp
|
||||
003 0002FE C3 RET
|
||||
|
||||
proc_4 ENDP
|
||||
|
||||
108
tests/prev/BENCHFN.EXE.a2
Executable file
108
tests/prev/BENCHFN.EXE.a2
Executable file
@ -0,0 +1,108 @@
|
||||
proc_4 PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 5D POP bp
|
||||
003 0002FE C3 RET
|
||||
|
||||
proc_4 ENDP
|
||||
|
||||
proc_3 PROC NEAR
|
||||
000 0002FF 55 PUSH bp
|
||||
001 000300 8BEC MOV bp, sp
|
||||
002 000302 E8F5FF CALL near ptr proc_4
|
||||
003 000305 E8F2FF CALL near ptr proc_4
|
||||
004 000308 E8EFFF CALL near ptr proc_4
|
||||
005 00030B E8ECFF CALL near ptr proc_4
|
||||
006 00030E E8E9FF CALL near ptr proc_4
|
||||
007 000311 E8E6FF CALL near ptr proc_4
|
||||
008 000314 E8E3FF CALL near ptr proc_4
|
||||
009 000317 E8E0FF CALL near ptr proc_4
|
||||
010 00031A E8DDFF CALL near ptr proc_4
|
||||
011 00031D E8DAFF CALL near ptr proc_4
|
||||
012 000320 5D POP bp
|
||||
013 000321 C3 RET
|
||||
|
||||
proc_3 ENDP
|
||||
|
||||
proc_2 PROC NEAR
|
||||
000 000322 55 PUSH bp
|
||||
001 000323 8BEC MOV bp, sp
|
||||
002 000325 E8D7FF CALL near ptr proc_3
|
||||
003 000328 E8D4FF CALL near ptr proc_3
|
||||
004 00032B E8D1FF CALL near ptr proc_3
|
||||
005 00032E E8CEFF CALL near ptr proc_3
|
||||
006 000331 E8CBFF CALL near ptr proc_3
|
||||
007 000334 E8C8FF CALL near ptr proc_3
|
||||
008 000337 E8C5FF CALL near ptr proc_3
|
||||
009 00033A E8C2FF CALL near ptr proc_3
|
||||
010 00033D E8BFFF CALL near ptr proc_3
|
||||
011 000340 E8BCFF CALL near ptr proc_3
|
||||
012 000343 5D POP bp
|
||||
013 000344 C3 RET
|
||||
|
||||
proc_2 ENDP
|
||||
|
||||
proc_1 PROC NEAR
|
||||
000 000345 55 PUSH bp
|
||||
001 000346 8BEC MOV bp, sp
|
||||
002 000348 E8D7FF CALL near ptr proc_2
|
||||
003 00034B E8D4FF CALL near ptr proc_2
|
||||
004 00034E E8D1FF CALL near ptr proc_2
|
||||
005 000351 E8CEFF CALL near ptr proc_2
|
||||
006 000354 E8CBFF CALL near ptr proc_2
|
||||
007 000357 E8C8FF CALL near ptr proc_2
|
||||
008 00035A E8C5FF CALL near ptr proc_2
|
||||
009 00035D E8C2FF CALL near ptr proc_2
|
||||
010 000360 E8BFFF CALL near ptr proc_2
|
||||
011 000363 5D POP bp
|
||||
012 000364 C3 RET
|
||||
|
||||
proc_1 ENDP
|
||||
|
||||
main PROC NEAR
|
||||
000 000365 55 PUSH bp
|
||||
001 000366 8BEC MOV bp, sp
|
||||
002 000368 83EC08 SUB sp, 8
|
||||
003 00036B B89401 MOV ax, 194h
|
||||
004 00036E 50 PUSH ax
|
||||
005 00036F E8D90B CALL near ptr printf
|
||||
006 000372 59 POP cx
|
||||
007 000373 8D46FC LEA ax, [bp-4]
|
||||
008 000376 50 PUSH ax
|
||||
009 000377 B8B001 MOV ax, 1B0h
|
||||
010 00037A 50 PUSH ax
|
||||
011 00037B E85614 CALL near ptr scanf
|
||||
012 00037E 59 POP cx
|
||||
013 00037F 59 POP cx
|
||||
014 000380 FF76FE PUSH word ptr [bp-2]
|
||||
015 000383 FF76FC PUSH word ptr [bp-4]
|
||||
016 000386 B8B401 MOV ax, 1B4h
|
||||
017 000389 50 PUSH ax
|
||||
018 00038A E8BE0B CALL near ptr printf
|
||||
019 00038D 83C406 ADD sp, 6
|
||||
020 000390 C746FA0000 MOV word ptr [bp-6], 0
|
||||
021 000395 C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
023 0003A7 8B56FA L1: MOV dx, [bp-6]
|
||||
024 0003AA 8B46F8 MOV ax, [bp-8]
|
||||
025 0003AD 3B56FE CMP dx, [bp-2]
|
||||
026 0003B0 7CEA JL L2
|
||||
027 0003B2 7F05 JG L3
|
||||
028 0003B4 3B46FC CMP ax, [bp-4]
|
||||
029 0003B7 76E3 JBE L2
|
||||
|
||||
030 0003B9 B8CE01 L3: MOV ax, 1CEh
|
||||
031 0003BC 50 PUSH ax
|
||||
032 0003BD E88B0B CALL near ptr printf
|
||||
033 0003C0 59 POP cx
|
||||
034 0003C1 8BE5 MOV sp, bp
|
||||
035 0003C3 5D POP bp
|
||||
036 0003C4 C3 RET
|
||||
|
||||
037 00039C E8A6FF L2: CALL near ptr proc_1
|
||||
038 00039F 8346F801 ADD word ptr [bp-8], 1
|
||||
039 0003A3 8356FA00 ADC word ptr [bp-6], 0
|
||||
040 JMP L1 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
89
tests/prev/BENCHFN.b
Executable file
89
tests/prev/BENCHFN.b
Executable file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHFN.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void proc_4 ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void proc_3 ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
proc_4 ();
|
||||
}
|
||||
|
||||
|
||||
void proc_2 ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
proc_3 ();
|
||||
}
|
||||
|
||||
|
||||
void proc_1 ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
proc_2 ();
|
||||
}
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
long loc1;
|
||||
long loc2;
|
||||
|
||||
printf ("enter number of iterations ");
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc2);
|
||||
loc1 = 1;
|
||||
|
||||
while ((loc1 <= loc2)) {
|
||||
proc_1 ();
|
||||
loc1 = (loc1 + 1);
|
||||
} /* end of while */
|
||||
printf ("finished\n");
|
||||
}
|
||||
|
||||
242
tests/prev/BENCHLNG.EXE.a1
Executable file
242
tests/prev/BENCHLNG.EXE.a1
Executable file
@ -0,0 +1,242 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC14 SUB sp, 14h
|
||||
003 000300 8D46FC LEA ax, [bp-4]
|
||||
004 000303 50 PUSH ax
|
||||
005 000304 B89401 MOV ax, 194h
|
||||
006 000307 50 PUSH ax
|
||||
007 000308 E85D15 CALL near ptr scanf
|
||||
008 00030B 59 POP cx
|
||||
009 00030C 59 POP cx
|
||||
010 00030D FF76FE PUSH word ptr [bp-2]
|
||||
011 000310 FF76FC PUSH word ptr [bp-4]
|
||||
012 000313 B89801 MOV ax, 198h
|
||||
013 000316 50 PUSH ax
|
||||
014 000317 E8C50C CALL near ptr printf
|
||||
015 00031A 83C406 ADD sp, 6
|
||||
016 00031D 8D46EC LEA ax, [bp-14h]
|
||||
017 000320 50 PUSH ax
|
||||
018 000321 B8B201 MOV ax, 1B2h
|
||||
019 000324 50 PUSH ax
|
||||
020 000325 E84015 CALL near ptr scanf
|
||||
021 000328 59 POP cx
|
||||
022 000329 59 POP cx
|
||||
023 00032A 8D46F0 LEA ax, [bp-10h]
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E B8B601 MOV ax, 1B6h
|
||||
026 000331 50 PUSH ax
|
||||
027 000332 E83315 CALL near ptr scanf
|
||||
028 000335 59 POP cx
|
||||
029 000336 59 POP cx
|
||||
030 000337 C746FA0000 MOV word ptr [bp-6], 0
|
||||
031 00033C C746F80100 MOV word ptr [bp-8], 1
|
||||
032 000341 E9E900 JMP L1
|
||||
|
||||
033 00042D 8B56FA L1: MOV dx, [bp-6]
|
||||
034 000430 8B46F8 MOV ax, [bp-8]
|
||||
035 000433 3B56FE CMP dx, [bp-2]
|
||||
036 000436 7D03 JGE L2
|
||||
037 000438 E909FF JMP L3
|
||||
|
||||
038 000344 C746F60000 L3: MOV word ptr [bp-0Ah], 0
|
||||
039 000349 C746F40100 MOV word ptr [bp-0Ch], 1
|
||||
040 00034E E9C000 JMP L4
|
||||
|
||||
041 000411 837EF600 L4: CMP word ptr [bp-0Ah], 0
|
||||
042 000415 7D03 JGE L5
|
||||
043 000417 E937FF JMP L6
|
||||
|
||||
044 000351 8B56EE L6: MOV dx, [bp-12h]
|
||||
045 000354 8B46EC MOV ax, [bp-14h]
|
||||
046 000357 0346F0 ADD ax, [bp-10h]
|
||||
047 00035A 1356F2 ADC dx, [bp-0Eh]
|
||||
048 00035D 0346F4 ADD ax, [bp-0Ch]
|
||||
049 000360 1356F6 ADC dx, [bp-0Ah]
|
||||
050 000363 8956EE MOV [bp-12h], dx
|
||||
051 000366 8946EC MOV [bp-14h], ax
|
||||
052 000369 8B56EE MOV dx, [bp-12h]
|
||||
053 00036C 8B46EC MOV ax, [bp-14h]
|
||||
054 00036F D1FA SAR dx, 1
|
||||
055 000371 D1D8 RCR ax, 1
|
||||
056 000373 8956F2 MOV [bp-0Eh], dx
|
||||
057 000376 8946F0 MOV [bp-10h], ax
|
||||
058 000379 33D2 XOR dx, dx
|
||||
059 00037B B80A00 MOV ax, 0Ah
|
||||
060 00037E 52 PUSH dx
|
||||
061 00037F 50 PUSH ax
|
||||
062 000380 FF76F2 PUSH word ptr [bp-0Eh]
|
||||
063 000383 FF76F0 PUSH word ptr [bp-10h]
|
||||
064 000386 9AEB1D1000 CALL far ptr LMOD@
|
||||
065 00038B 8956EE MOV [bp-12h], dx
|
||||
066 00038E 8946EC MOV [bp-14h], ax
|
||||
067 000391 8B56F2 MOV dx, [bp-0Eh]
|
||||
068 000394 8B46F0 MOV ax, [bp-10h]
|
||||
069 000397 3B56F6 CMP dx, [bp-0Ah]
|
||||
070 00039A 750A JNE L7
|
||||
071 00039C 3B46F4 CMP ax, [bp-0Ch]
|
||||
072 00039F 7505 JNE L7
|
||||
073 0003A1 B80100 MOV ax, 1
|
||||
074 0003A4 EB02 JMP L8
|
||||
|
||||
075 0003A8 99 L8: CWD
|
||||
076 0003A9 8956EE MOV [bp-12h], dx
|
||||
077 0003AC 8946EC MOV [bp-14h], ax
|
||||
078 0003AF 8B56EE MOV dx, [bp-12h]
|
||||
079 0003B2 8B46EC MOV ax, [bp-14h]
|
||||
080 0003B5 0B46F4 OR ax, [bp-0Ch]
|
||||
081 0003B8 0B56F6 OR dx, [bp-0Ah]
|
||||
082 0003BB 8956F2 MOV [bp-0Eh], dx
|
||||
083 0003BE 8946F0 MOV [bp-10h], ax
|
||||
084 0003C1 8B46F0 MOV ax, [bp-10h]
|
||||
085 0003C4 0B46F2 OR ax, [bp-0Eh]
|
||||
086 0003C7 7505 JNE L9
|
||||
087 0003C9 B80100 MOV ax, 1
|
||||
088 0003CC EB02 JMP L10
|
||||
|
||||
089 0003D0 99 L10: CWD
|
||||
090 0003D1 8956EE MOV [bp-12h], dx
|
||||
091 0003D4 8946EC MOV [bp-14h], ax
|
||||
092 0003D7 8B56EE MOV dx, [bp-12h]
|
||||
093 0003DA 8B46EC MOV ax, [bp-14h]
|
||||
094 0003DD 0346F4 ADD ax, [bp-0Ch]
|
||||
095 0003E0 1356F6 ADC dx, [bp-0Ah]
|
||||
096 0003E3 8956F2 MOV [bp-0Eh], dx
|
||||
097 0003E6 8946F0 MOV [bp-10h], ax
|
||||
098 0003E9 8B56F2 MOV dx, [bp-0Eh]
|
||||
099 0003EC 8B46F0 MOV ax, [bp-10h]
|
||||
100 0003EF 3B56F6 CMP dx, [bp-0Ah]
|
||||
101 0003F2 7C0C JL L11
|
||||
102 0003F4 7F05 JG L12
|
||||
103 0003F6 3B46F4 CMP ax, [bp-0Ch]
|
||||
104 0003F9 7605 JBE L11
|
||||
|
||||
105 0003FB B80100 L12: MOV ax, 1
|
||||
106 0003FE EB02 JMP L13
|
||||
|
||||
107 000402 99 L13: CWD
|
||||
108 000403 8956EE MOV [bp-12h], dx
|
||||
109 000406 8946EC MOV [bp-14h], ax
|
||||
110 000409 8346F401 ADD word ptr [bp-0Ch], 1
|
||||
111 00040D 8356F600 ADC word ptr [bp-0Ah], 0
|
||||
112 JMP L4 ;Synthetic inst
|
||||
|
||||
113 000400 33C0 L11: XOR ax, ax
|
||||
114 JMP L13 ;Synthetic inst
|
||||
|
||||
115 0003CE 33C0 L9: XOR ax, ax
|
||||
116 JMP L10 ;Synthetic inst
|
||||
|
||||
117 0003A6 33C0 L7: XOR ax, ax
|
||||
118 JMP L8 ;Synthetic inst
|
||||
|
||||
119 00041A 7F09 L5: JG L14
|
||||
120 00041C 837EF428 CMP word ptr [bp-0Ch], 28h
|
||||
121 000420 7703 JA L14
|
||||
122 000422 E92CFF JMP L6
|
||||
|
||||
123 000425 8346F801 L14: ADD word ptr [bp-8], 1
|
||||
124 000429 8356FA00 ADC word ptr [bp-6], 0
|
||||
125 JMP L1 ;Synthetic inst
|
||||
|
||||
126 00043B 7F08 L2: JG L15
|
||||
127 00043D 3B46FC CMP ax, [bp-4]
|
||||
128 000440 7703 JA L15
|
||||
129 000442 E9FFFE JMP L3
|
||||
|
||||
130 000445 FF76EE L15: PUSH word ptr [bp-12h]
|
||||
131 000448 FF76EC PUSH word ptr [bp-14h]
|
||||
132 00044B B8BA01 MOV ax, 1BAh
|
||||
133 00044E 50 PUSH ax
|
||||
134 00044F E88D0B CALL near ptr printf
|
||||
135 000452 83C406 ADD sp, 6
|
||||
136 000455 8BE5 MOV sp, bp
|
||||
137 000457 5D POP bp
|
||||
138 000458 C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
LMOD@ PROC FAR
|
||||
000 001EEB B90200 MOV cx, 2
|
||||
001 001EEE EB03 JMP L16
|
||||
|
||||
002 001EF3 55 L16: PUSH bp
|
||||
003 001EF4 56 PUSH si
|
||||
004 001EF5 57 PUSH di
|
||||
005 001EF6 8BEC MOV bp, sp
|
||||
006 001EF8 8BF9 MOV di, cx
|
||||
007 001EFA 8B460A MOV ax, [bp+0Ah]
|
||||
008 001EFD 8B560C MOV dx, [bp+0Ch]
|
||||
009 001F00 8B5E0E MOV bx, [bp+0Eh]
|
||||
010 001F03 8B4E10 MOV cx, [bp+10h]
|
||||
011 001F06 0BC9 OR cx, cx
|
||||
012 001F08 7508 JNE L17
|
||||
013 001F0A 0BD2 OR dx, dx
|
||||
014 001F0C 7469 JE L18
|
||||
015 001F0E 0BDB OR bx, bx
|
||||
016 001F10 7465 JE L18
|
||||
|
||||
017 001F12 F7C70100 L17: TEST di, 1
|
||||
018 001F16 751C JNE L19
|
||||
019 001F18 0BD2 OR dx, dx
|
||||
020 001F1A 790A JNS L20
|
||||
021 001F1C F7DA NEG dx
|
||||
022 001F1E F7D8 NEG ax
|
||||
023 001F20 83DA00 SBB dx, 0
|
||||
024 001F23 83CF0C OR di, 0Ch
|
||||
|
||||
025 001F26 0BC9 L20: OR cx, cx
|
||||
026 001F28 790A JNS L19
|
||||
027 001F2A F7D9 NEG cx
|
||||
028 001F2C F7DB NEG bx
|
||||
029 001F2E 83D900 SBB cx, 0
|
||||
030 001F31 83F704 XOR di, 4
|
||||
|
||||
031 001F34 8BE9 L19: MOV bp, cx
|
||||
032 001F36 B92000 MOV cx, 20h
|
||||
033 001F39 57 PUSH di
|
||||
034 001F3A 33FF XOR di, di
|
||||
035 001F3C 33F6 XOR si, si
|
||||
|
||||
036 001F3E D1E0 L21: SHL ax, 1
|
||||
037 001F40 D1D2 RCL dx, 1
|
||||
038 001F42 D1D6 RCL si, 1
|
||||
039 001F44 D1D7 RCL di, 1
|
||||
040 001F46 3BFD CMP di, bp
|
||||
041 001F48 720B JB L22
|
||||
042 001F4A 7704 JA L23
|
||||
043 001F4C 3BF3 CMP si, bx
|
||||
044 001F4E 7205 JB L22
|
||||
|
||||
045 001F50 2BF3 L23: SUB si, bx
|
||||
046 001F52 1BFD SBB di, bp
|
||||
047 001F54 40 INC ax
|
||||
|
||||
048 001F55 E2E7 L22: LOOP L21
|
||||
049 001F57 5B POP bx
|
||||
050 001F58 F7C30200 TEST bx, 2
|
||||
051 001F5C 7406 JE L24
|
||||
052 001F5E 8BC6 MOV ax, si
|
||||
053 001F60 8BD7 MOV dx, di
|
||||
054 001F62 D1EB SHR bx, 1
|
||||
|
||||
055 001F64 F7C30400 L24: TEST bx, 4
|
||||
056 001F68 7407 JE L25
|
||||
057 001F6A F7DA NEG dx
|
||||
058 001F6C F7D8 NEG ax
|
||||
059 001F6E 83DA00 SBB dx, 0
|
||||
|
||||
060 001F71 5F L25: POP di
|
||||
061 001F72 5E POP si
|
||||
062 001F73 5D POP bp
|
||||
063 001F74 CA0800 RETF 8
|
||||
065 001F77 F7F3 DIV bx
|
||||
067 001F79 F7C70200 TEST di, 2
|
||||
068 001F7D 7402 JE L26
|
||||
069 001F7F 8BC2 MOV ax, dx
|
||||
|
||||
070 001F81 33D2 L26: XOR dx, dx
|
||||
071 001F83 EBEC JMP L25
|
||||
|
||||
LMOD@ ENDP
|
||||
|
||||
234
tests/prev/BENCHLNG.EXE.a2
Executable file
234
tests/prev/BENCHLNG.EXE.a2
Executable file
@ -0,0 +1,234 @@
|
||||
LMOD@ PROC FAR
|
||||
000 001EEB B90200 MOV cx, 2
|
||||
002 001EF3 55 PUSH bp
|
||||
003 001EF4 56 PUSH si
|
||||
004 001EF5 57 PUSH di
|
||||
005 001EF6 8BEC MOV bp, sp
|
||||
006 001EF8 8BF9 MOV di, cx
|
||||
007 001EFA 8B460A MOV ax, [bp+0Ah]
|
||||
008 001EFD 8B560C MOV dx, [bp+0Ch]
|
||||
009 001F00 8B5E0E MOV bx, [bp+0Eh]
|
||||
010 001F03 8B4E10 MOV cx, [bp+10h]
|
||||
011 001F06 0BC9 OR cx, cx
|
||||
012 001F08 7508 JNE L1
|
||||
013 001F0A 0BD2 OR dx, dx
|
||||
014 001F0C 7469 JE L2
|
||||
015 001F0E 0BDB OR bx, bx
|
||||
016 001F10 7465 JE L2
|
||||
|
||||
017 001F12 F7C70100 L1: TEST di, 1
|
||||
018 001F16 751C JNE L3
|
||||
019 001F18 0BD2 OR dx, dx
|
||||
020 001F1A 790A JNS L4
|
||||
021 001F1C F7DA NEG dx
|
||||
022 001F1E F7D8 NEG ax
|
||||
023 001F20 83DA00 SBB dx, 0
|
||||
024 001F23 83CF0C OR di, 0Ch
|
||||
|
||||
025 001F26 0BC9 L4: OR cx, cx
|
||||
026 001F28 790A JNS L3
|
||||
027 001F2A F7D9 NEG cx
|
||||
028 001F2C F7DB NEG bx
|
||||
029 001F2E 83D900 SBB cx, 0
|
||||
030 001F31 83F704 XOR di, 4
|
||||
|
||||
031 001F34 8BE9 L3: MOV bp, cx
|
||||
032 001F36 B92000 MOV cx, 20h
|
||||
033 001F39 57 PUSH di
|
||||
034 001F3A 33FF XOR di, di
|
||||
035 001F3C 33F6 XOR si, si
|
||||
|
||||
036 001F3E D1E0 L5: SHL ax, 1
|
||||
037 001F40 D1D2 RCL dx, 1
|
||||
038 001F42 D1D6 RCL si, 1
|
||||
039 001F44 D1D7 RCL di, 1
|
||||
040 001F46 3BFD CMP di, bp
|
||||
041 001F48 720B JB L6
|
||||
042 001F4A 7704 JA L7
|
||||
043 001F4C 3BF3 CMP si, bx
|
||||
044 001F4E 7205 JB L6
|
||||
|
||||
045 001F50 2BF3 L7: SUB si, bx
|
||||
046 001F52 1BFD SBB di, bp
|
||||
047 001F54 40 INC ax
|
||||
|
||||
048 001F55 E2E7 L6: LOOP L5
|
||||
049 001F57 5B POP bx
|
||||
050 001F58 F7C30200 TEST bx, 2
|
||||
051 001F5C 7406 JE L8
|
||||
052 001F5E 8BC6 MOV ax, si
|
||||
053 001F60 8BD7 MOV dx, di
|
||||
054 001F62 D1EB SHR bx, 1
|
||||
|
||||
055 001F64 F7C30400 L8: TEST bx, 4
|
||||
056 001F68 7407 JE L9
|
||||
057 001F6A F7DA NEG dx
|
||||
058 001F6C F7D8 NEG ax
|
||||
059 001F6E 83DA00 SBB dx, 0
|
||||
|
||||
060 001F71 5F L9: POP di
|
||||
061 001F72 5E POP si
|
||||
062 001F73 5D POP bp
|
||||
063 001F74 CA0800 RETF 8
|
||||
|
||||
064 L2: MOV tmp, dx:ax ;Synthetic inst
|
||||
065 001F77 F7F3 DIV bx
|
||||
066 MOD bx ;Synthetic inst
|
||||
067 001F79 F7C70200 TEST di, 2
|
||||
068 001F7D 7402 JE L10
|
||||
069 001F7F 8BC2 MOV ax, dx
|
||||
|
||||
070 001F81 33D2 L10: XOR dx, dx
|
||||
071 001F83 EBEC JMP L9
|
||||
|
||||
LMOD@ ENDP
|
||||
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC14 SUB sp, 14h
|
||||
003 000300 8D46FC LEA ax, [bp-4]
|
||||
004 000303 50 PUSH ax
|
||||
005 000304 B89401 MOV ax, 194h
|
||||
006 000307 50 PUSH ax
|
||||
007 000308 E85D15 CALL near ptr scanf
|
||||
008 00030B 59 POP cx
|
||||
009 00030C 59 POP cx
|
||||
010 00030D FF76FE PUSH word ptr [bp-2]
|
||||
011 000310 FF76FC PUSH word ptr [bp-4]
|
||||
012 000313 B89801 MOV ax, 198h
|
||||
013 000316 50 PUSH ax
|
||||
014 000317 E8C50C CALL near ptr printf
|
||||
015 00031A 83C406 ADD sp, 6
|
||||
016 00031D 8D46EC LEA ax, [bp-14h]
|
||||
017 000320 50 PUSH ax
|
||||
018 000321 B8B201 MOV ax, 1B2h
|
||||
019 000324 50 PUSH ax
|
||||
020 000325 E84015 CALL near ptr scanf
|
||||
021 000328 59 POP cx
|
||||
022 000329 59 POP cx
|
||||
023 00032A 8D46F0 LEA ax, [bp-10h]
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E B8B601 MOV ax, 1B6h
|
||||
026 000331 50 PUSH ax
|
||||
027 000332 E83315 CALL near ptr scanf
|
||||
028 000335 59 POP cx
|
||||
029 000336 59 POP cx
|
||||
030 000337 C746FA0000 MOV word ptr [bp-6], 0
|
||||
031 00033C C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
033 00042D 8B56FA L11: MOV dx, [bp-6]
|
||||
034 000430 8B46F8 MOV ax, [bp-8]
|
||||
035 000433 3B56FE CMP dx, [bp-2]
|
||||
036 000436 7D03 JGE L12
|
||||
|
||||
038 000344 C746F60000 L13: MOV word ptr [bp-0Ah], 0
|
||||
039 000349 C746F40100 MOV word ptr [bp-0Ch], 1
|
||||
|
||||
041 000411 837EF600 L14: CMP word ptr [bp-0Ah], 0
|
||||
042 000415 7D03 JGE L15
|
||||
|
||||
044 000351 8B56EE L16: MOV dx, [bp-12h]
|
||||
045 000354 8B46EC MOV ax, [bp-14h]
|
||||
046 000357 0346F0 ADD ax, [bp-10h]
|
||||
047 00035A 1356F2 ADC dx, [bp-0Eh]
|
||||
048 00035D 0346F4 ADD ax, [bp-0Ch]
|
||||
049 000360 1356F6 ADC dx, [bp-0Ah]
|
||||
050 000363 8956EE MOV [bp-12h], dx
|
||||
051 000366 8946EC MOV [bp-14h], ax
|
||||
052 000369 8B56EE MOV dx, [bp-12h]
|
||||
053 00036C 8B46EC MOV ax, [bp-14h]
|
||||
054 00036F D1FA SAR dx, 1
|
||||
055 000371 D1D8 RCR ax, 1
|
||||
056 000373 8956F2 MOV [bp-0Eh], dx
|
||||
057 000376 8946F0 MOV [bp-10h], ax
|
||||
058 000379 33D2 XOR dx, dx
|
||||
059 00037B B80A00 MOV ax, 0Ah
|
||||
060 00037E 52 PUSH dx
|
||||
061 00037F 50 PUSH ax
|
||||
062 000380 FF76F2 PUSH word ptr [bp-0Eh]
|
||||
063 000383 FF76F0 PUSH word ptr [bp-10h]
|
||||
064 000386 9AEB1D1000 CALL far ptr LMOD@
|
||||
065 00038B 8956EE MOV [bp-12h], dx
|
||||
066 00038E 8946EC MOV [bp-14h], ax
|
||||
067 000391 8B56F2 MOV dx, [bp-0Eh]
|
||||
068 000394 8B46F0 MOV ax, [bp-10h]
|
||||
069 000397 3B56F6 CMP dx, [bp-0Ah]
|
||||
070 00039A 750A JNE L17
|
||||
071 00039C 3B46F4 CMP ax, [bp-0Ch]
|
||||
072 00039F 7505 JNE L17
|
||||
073 0003A1 B80100 MOV ax, 1
|
||||
|
||||
075 0003A8 99 L18: CWD
|
||||
076 0003A9 8956EE MOV [bp-12h], dx
|
||||
077 0003AC 8946EC MOV [bp-14h], ax
|
||||
078 0003AF 8B56EE MOV dx, [bp-12h]
|
||||
079 0003B2 8B46EC MOV ax, [bp-14h]
|
||||
080 0003B5 0B46F4 OR ax, [bp-0Ch]
|
||||
081 0003B8 0B56F6 OR dx, [bp-0Ah]
|
||||
082 0003BB 8956F2 MOV [bp-0Eh], dx
|
||||
083 0003BE 8946F0 MOV [bp-10h], ax
|
||||
084 0003C1 8B46F0 MOV ax, [bp-10h]
|
||||
085 0003C4 0B46F2 OR ax, [bp-0Eh]
|
||||
086 0003C7 7505 JNE L19
|
||||
087 0003C9 B80100 MOV ax, 1
|
||||
|
||||
089 0003D0 99 L20: CWD
|
||||
090 0003D1 8956EE MOV [bp-12h], dx
|
||||
091 0003D4 8946EC MOV [bp-14h], ax
|
||||
092 0003D7 8B56EE MOV dx, [bp-12h]
|
||||
093 0003DA 8B46EC MOV ax, [bp-14h]
|
||||
094 0003DD 0346F4 ADD ax, [bp-0Ch]
|
||||
095 0003E0 1356F6 ADC dx, [bp-0Ah]
|
||||
096 0003E3 8956F2 MOV [bp-0Eh], dx
|
||||
097 0003E6 8946F0 MOV [bp-10h], ax
|
||||
098 0003E9 8B56F2 MOV dx, [bp-0Eh]
|
||||
099 0003EC 8B46F0 MOV ax, [bp-10h]
|
||||
100 0003EF 3B56F6 CMP dx, [bp-0Ah]
|
||||
101 0003F2 7C0C JL L21
|
||||
102 0003F4 7F05 JG L22
|
||||
103 0003F6 3B46F4 CMP ax, [bp-0Ch]
|
||||
104 0003F9 7605 JBE L21
|
||||
|
||||
105 0003FB B80100 L22: MOV ax, 1
|
||||
|
||||
107 000402 99 L23: CWD
|
||||
108 000403 8956EE MOV [bp-12h], dx
|
||||
109 000406 8946EC MOV [bp-14h], ax
|
||||
110 000409 8346F401 ADD word ptr [bp-0Ch], 1
|
||||
111 00040D 8356F600 ADC word ptr [bp-0Ah], 0
|
||||
112 JMP L14 ;Synthetic inst
|
||||
|
||||
113 000400 33C0 L21: XOR ax, ax
|
||||
114 JMP L23 ;Synthetic inst
|
||||
|
||||
115 0003CE 33C0 L19: XOR ax, ax
|
||||
116 JMP L20 ;Synthetic inst
|
||||
|
||||
117 0003A6 33C0 L17: XOR ax, ax
|
||||
118 JMP L18 ;Synthetic inst
|
||||
|
||||
119 00041A 7F09 L15: JG L24
|
||||
120 00041C 837EF428 CMP word ptr [bp-0Ch], 28h
|
||||
121 000420 7703 JA L24
|
||||
|
||||
123 000425 8346F801 L24: ADD word ptr [bp-8], 1
|
||||
124 000429 8356FA00 ADC word ptr [bp-6], 0
|
||||
125 JMP L11 ;Synthetic inst
|
||||
|
||||
126 00043B 7F08 L12: JG L25
|
||||
127 00043D 3B46FC CMP ax, [bp-4]
|
||||
128 000440 7703 JA L25
|
||||
|
||||
130 000445 FF76EE L25: PUSH word ptr [bp-12h]
|
||||
131 000448 FF76EC PUSH word ptr [bp-14h]
|
||||
132 00044B B8BA01 MOV ax, 1BAh
|
||||
133 00044E 50 PUSH ax
|
||||
134 00044F E88D0B CALL near ptr printf
|
||||
135 000452 83C406 ADD sp, 6
|
||||
136 000455 8BE5 MOV sp, bp
|
||||
137 000457 5D POP bp
|
||||
138 000458 C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
158
tests/prev/BENCHLNG.b
Executable file
158
tests/prev/BENCHLNG.b
Executable file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHLNG.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
long LMOD@ (long arg0, int arg2int arg3)
|
||||
/* Takes 8 bytes of parameters.
|
||||
* Runtime support routine of the compiler.
|
||||
* Untranslatable routine. Assembler provided.
|
||||
* Return value in registers dx:ax.
|
||||
* Pascal calling convention.
|
||||
*/
|
||||
{
|
||||
MOV cx, 2
|
||||
PUSH bp
|
||||
PUSH si
|
||||
PUSH di
|
||||
MOV bp, sp
|
||||
MOV di, cx
|
||||
MOV ax, [bp+0Ah]
|
||||
MOV dx, [bp+0Ch]
|
||||
MOV bx, [bp+0Eh]
|
||||
MOV cx, [bp+10h]
|
||||
CMP cx, 0
|
||||
JNE L1
|
||||
OR dx, dx
|
||||
JE L2
|
||||
OR bx, bx
|
||||
JE L2
|
||||
|
||||
L1: TEST di, 1
|
||||
JNE L3
|
||||
OR dx, dx
|
||||
JNS L4
|
||||
NEG dx
|
||||
NEG ax
|
||||
SBB dx, 0
|
||||
OR di, 0Ch
|
||||
|
||||
L4: OR cx, cx
|
||||
JNS L3
|
||||
NEG cx
|
||||
NEG bx
|
||||
SBB cx, 0
|
||||
XOR di, 4
|
||||
|
||||
L3: MOV bp, cx
|
||||
MOV cx, 20h
|
||||
PUSH di
|
||||
XOR di, 0
|
||||
XOR si, 0
|
||||
|
||||
L5: SHL ax, 1
|
||||
RCL dx, 1
|
||||
RCL si, 1
|
||||
RCL di, 1
|
||||
CMP di, bp
|
||||
JB L6
|
||||
JA L7
|
||||
CMP si, bx
|
||||
JB L6
|
||||
|
||||
L7: SUB si, bx
|
||||
SBB di, bp
|
||||
INC ax
|
||||
|
||||
L6: LOOP L5
|
||||
POP bx
|
||||
TEST bx, 2
|
||||
JE L8
|
||||
MOV ax, si
|
||||
MOV dx, di
|
||||
SHR bx, 1
|
||||
|
||||
L8: TEST bx, 4
|
||||
JE L9
|
||||
NEG dx
|
||||
NEG ax
|
||||
SBB dx, 0
|
||||
|
||||
L9: POP di
|
||||
POP si
|
||||
POP bp
|
||||
RETF 8
|
||||
|
||||
L2: MOV tmp, dx:ax ;Synthetic inst
|
||||
DIV bx
|
||||
MOD bx ;Synthetic inst
|
||||
TEST di, 2
|
||||
JE L10
|
||||
MOV ax, dx
|
||||
|
||||
L10: XOR dx, dx
|
||||
JMP L9
|
||||
}
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
long loc1;
|
||||
long loc2;
|
||||
long loc3;
|
||||
long loc4;
|
||||
long loc5;
|
||||
int loc6; /* ax */
|
||||
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc5);
|
||||
scanf ("%ld", &loc2);
|
||||
scanf ("%ld", &loc3);
|
||||
loc3 = 1;
|
||||
|
||||
while ((loc3 <= loc5)) {
|
||||
loc2 = 1;
|
||||
|
||||
while ((loc2 <= 40)) {
|
||||
loc4 = ((loc4 + loc1) + loc2);
|
||||
loc1 = (loc4 >> 1);
|
||||
loc4 = LMOD@ (loc1, 10);
|
||||
|
||||
if (loc1 == loc2) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc4 = loc6;
|
||||
loc1 = (loc4 | loc2);
|
||||
|
||||
if ((loc3 | loc9) == 0) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc4 = loc6;
|
||||
loc1 = (loc4 + loc2);
|
||||
|
||||
if (loc1 > loc2) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc4 = loc6;
|
||||
loc2 = (loc2 + 1);
|
||||
} /* end of while */
|
||||
loc3 = (loc3 + 1);
|
||||
} /* end of while */
|
||||
printf ("a=%d\n", loc4);
|
||||
}
|
||||
|
||||
101
tests/prev/BENCHMUL.EXE.a1
Executable file
101
tests/prev/BENCHMUL.EXE.a1
Executable file
@ -0,0 +1,101 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0C SUB sp, 0Ch
|
||||
003 000300 56 PUSH si
|
||||
004 000301 B89401 MOV ax, 194h
|
||||
005 000304 50 PUSH ax
|
||||
006 000305 E8530C CALL near ptr printf
|
||||
007 000308 59 POP cx
|
||||
008 000309 8D46FC LEA ax, [bp-4]
|
||||
009 00030C 50 PUSH ax
|
||||
010 00030D B8B001 MOV ax, 1B0h
|
||||
011 000310 50 PUSH ax
|
||||
012 000311 E8D014 CALL near ptr scanf
|
||||
013 000314 59 POP cx
|
||||
014 000315 59 POP cx
|
||||
015 000316 FF76FE PUSH word ptr [bp-2]
|
||||
016 000319 FF76FC PUSH word ptr [bp-4]
|
||||
017 00031C B8B401 MOV ax, 1B4h
|
||||
018 00031F 50 PUSH ax
|
||||
019 000320 E8380C CALL near ptr printf
|
||||
020 000323 83C406 ADD sp, 6
|
||||
021 000326 8D46F4 LEA ax, [bp-0Ch]
|
||||
022 000329 50 PUSH ax
|
||||
023 00032A B8CE01 MOV ax, 1CEh
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E E8B314 CALL near ptr scanf
|
||||
026 000331 59 POP cx
|
||||
027 000332 59 POP cx
|
||||
028 000333 8D46F6 LEA ax, [bp-0Ah]
|
||||
029 000336 50 PUSH ax
|
||||
030 000337 B8D101 MOV ax, 1D1h
|
||||
031 00033A 50 PUSH ax
|
||||
032 00033B E8A614 CALL near ptr scanf
|
||||
033 00033E 59 POP cx
|
||||
034 00033F 59 POP cx
|
||||
035 000340 C746FA0000 MOV word ptr [bp-6], 0
|
||||
036 000345 C746F80100 MOV word ptr [bp-8], 1
|
||||
037 00034A EB66 JMP L1
|
||||
|
||||
038 0003B2 8B56FA L1: MOV dx, [bp-6]
|
||||
039 0003B5 8B46F8 MOV ax, [bp-8]
|
||||
040 0003B8 3B56FE CMP dx, [bp-2]
|
||||
041 0003BB 7C8F JL L2
|
||||
042 0003BD 7F05 JG L3
|
||||
043 0003BF 3B46FC CMP ax, [bp-4]
|
||||
044 0003C2 7688 JBE L2
|
||||
|
||||
045 0003C4 FF76F4 L3: PUSH word ptr [bp-0Ch]
|
||||
046 0003C7 B8D401 MOV ax, 1D4h
|
||||
047 0003CA 50 PUSH ax
|
||||
048 0003CB E88D0B CALL near ptr printf
|
||||
049 0003CE 59 POP cx
|
||||
050 0003CF 59 POP cx
|
||||
051 0003D0 5E POP si
|
||||
052 0003D1 8BE5 MOV sp, bp
|
||||
053 0003D3 5D POP bp
|
||||
054 0003D4 C3 RET
|
||||
|
||||
055 00034C BE0100 L2: MOV si, 1
|
||||
056 00034F EB54 JMP L4
|
||||
|
||||
057 0003A5 83FE28 L4: CMP si, 28h
|
||||
058 0003A8 7EA7 JLE L5
|
||||
059 0003AA 8346F801 ADD word ptr [bp-8], 1
|
||||
060 0003AE 8356FA00 ADC word ptr [bp-6], 0
|
||||
061 JMP L1 ;Synthetic inst
|
||||
|
||||
062 000351 8B46F4 L5: MOV ax, [bp-0Ch]
|
||||
063 000354 F766F4 MUL word ptr [bp-0Ch]
|
||||
064 000357 F766F4 MUL word ptr [bp-0Ch]
|
||||
065 00035A F766F4 MUL word ptr [bp-0Ch]
|
||||
066 00035D F766F4 MUL word ptr [bp-0Ch]
|
||||
067 000360 F766F4 MUL word ptr [bp-0Ch]
|
||||
068 000363 F766F4 MUL word ptr [bp-0Ch]
|
||||
069 000366 F766F4 MUL word ptr [bp-0Ch]
|
||||
070 000369 F766F4 MUL word ptr [bp-0Ch]
|
||||
071 00036C F766F4 MUL word ptr [bp-0Ch]
|
||||
072 00036F F766F4 MUL word ptr [bp-0Ch]
|
||||
073 000372 F766F4 MUL word ptr [bp-0Ch]
|
||||
074 000375 F766F4 MUL word ptr [bp-0Ch]
|
||||
075 000378 F766F4 MUL word ptr [bp-0Ch]
|
||||
076 00037B F766F4 MUL word ptr [bp-0Ch]
|
||||
077 00037E F766F4 MUL word ptr [bp-0Ch]
|
||||
078 000381 F766F4 MUL word ptr [bp-0Ch]
|
||||
079 000384 F766F4 MUL word ptr [bp-0Ch]
|
||||
080 000387 F766F4 MUL word ptr [bp-0Ch]
|
||||
081 00038A F766F4 MUL word ptr [bp-0Ch]
|
||||
082 00038D F766F4 MUL word ptr [bp-0Ch]
|
||||
083 000390 F766F4 MUL word ptr [bp-0Ch]
|
||||
084 000393 F766F4 MUL word ptr [bp-0Ch]
|
||||
085 000396 F766F4 MUL word ptr [bp-0Ch]
|
||||
086 000399 F766F4 MUL word ptr [bp-0Ch]
|
||||
087 00039C BA0300 MOV dx, 3
|
||||
088 00039F F7E2 MUL dx
|
||||
089 0003A1 8946F4 MOV [bp-0Ch], ax
|
||||
090 0003A4 46 INC si
|
||||
091 JMP L4 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
99
tests/prev/BENCHMUL.EXE.a2
Executable file
99
tests/prev/BENCHMUL.EXE.a2
Executable file
@ -0,0 +1,99 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0C SUB sp, 0Ch
|
||||
003 000300 56 PUSH si
|
||||
004 000301 B89401 MOV ax, 194h
|
||||
005 000304 50 PUSH ax
|
||||
006 000305 E8530C CALL near ptr printf
|
||||
007 000308 59 POP cx
|
||||
008 000309 8D46FC LEA ax, [bp-4]
|
||||
009 00030C 50 PUSH ax
|
||||
010 00030D B8B001 MOV ax, 1B0h
|
||||
011 000310 50 PUSH ax
|
||||
012 000311 E8D014 CALL near ptr scanf
|
||||
013 000314 59 POP cx
|
||||
014 000315 59 POP cx
|
||||
015 000316 FF76FE PUSH word ptr [bp-2]
|
||||
016 000319 FF76FC PUSH word ptr [bp-4]
|
||||
017 00031C B8B401 MOV ax, 1B4h
|
||||
018 00031F 50 PUSH ax
|
||||
019 000320 E8380C CALL near ptr printf
|
||||
020 000323 83C406 ADD sp, 6
|
||||
021 000326 8D46F4 LEA ax, [bp-0Ch]
|
||||
022 000329 50 PUSH ax
|
||||
023 00032A B8CE01 MOV ax, 1CEh
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E E8B314 CALL near ptr scanf
|
||||
026 000331 59 POP cx
|
||||
027 000332 59 POP cx
|
||||
028 000333 8D46F6 LEA ax, [bp-0Ah]
|
||||
029 000336 50 PUSH ax
|
||||
030 000337 B8D101 MOV ax, 1D1h
|
||||
031 00033A 50 PUSH ax
|
||||
032 00033B E8A614 CALL near ptr scanf
|
||||
033 00033E 59 POP cx
|
||||
034 00033F 59 POP cx
|
||||
035 000340 C746FA0000 MOV word ptr [bp-6], 0
|
||||
036 000345 C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
038 0003B2 8B56FA L1: MOV dx, [bp-6]
|
||||
039 0003B5 8B46F8 MOV ax, [bp-8]
|
||||
040 0003B8 3B56FE CMP dx, [bp-2]
|
||||
041 0003BB 7C8F JL L2
|
||||
042 0003BD 7F05 JG L3
|
||||
043 0003BF 3B46FC CMP ax, [bp-4]
|
||||
044 0003C2 7688 JBE L2
|
||||
|
||||
045 0003C4 FF76F4 L3: PUSH word ptr [bp-0Ch]
|
||||
046 0003C7 B8D401 MOV ax, 1D4h
|
||||
047 0003CA 50 PUSH ax
|
||||
048 0003CB E88D0B CALL near ptr printf
|
||||
049 0003CE 59 POP cx
|
||||
050 0003CF 59 POP cx
|
||||
051 0003D0 5E POP si
|
||||
052 0003D1 8BE5 MOV sp, bp
|
||||
053 0003D3 5D POP bp
|
||||
054 0003D4 C3 RET
|
||||
|
||||
055 00034C BE0100 L2: MOV si, 1
|
||||
|
||||
057 0003A5 83FE28 L4: CMP si, 28h
|
||||
058 0003A8 7EA7 JLE L5
|
||||
059 0003AA 8346F801 ADD word ptr [bp-8], 1
|
||||
060 0003AE 8356FA00 ADC word ptr [bp-6], 0
|
||||
061 JMP L1 ;Synthetic inst
|
||||
|
||||
062 000351 8B46F4 L5: MOV ax, [bp-0Ch]
|
||||
063 000354 F766F4 MUL word ptr [bp-0Ch]
|
||||
064 000357 F766F4 MUL word ptr [bp-0Ch]
|
||||
065 00035A F766F4 MUL word ptr [bp-0Ch]
|
||||
066 00035D F766F4 MUL word ptr [bp-0Ch]
|
||||
067 000360 F766F4 MUL word ptr [bp-0Ch]
|
||||
068 000363 F766F4 MUL word ptr [bp-0Ch]
|
||||
069 000366 F766F4 MUL word ptr [bp-0Ch]
|
||||
070 000369 F766F4 MUL word ptr [bp-0Ch]
|
||||
071 00036C F766F4 MUL word ptr [bp-0Ch]
|
||||
072 00036F F766F4 MUL word ptr [bp-0Ch]
|
||||
073 000372 F766F4 MUL word ptr [bp-0Ch]
|
||||
074 000375 F766F4 MUL word ptr [bp-0Ch]
|
||||
075 000378 F766F4 MUL word ptr [bp-0Ch]
|
||||
076 00037B F766F4 MUL word ptr [bp-0Ch]
|
||||
077 00037E F766F4 MUL word ptr [bp-0Ch]
|
||||
078 000381 F766F4 MUL word ptr [bp-0Ch]
|
||||
079 000384 F766F4 MUL word ptr [bp-0Ch]
|
||||
080 000387 F766F4 MUL word ptr [bp-0Ch]
|
||||
081 00038A F766F4 MUL word ptr [bp-0Ch]
|
||||
082 00038D F766F4 MUL word ptr [bp-0Ch]
|
||||
083 000390 F766F4 MUL word ptr [bp-0Ch]
|
||||
084 000393 F766F4 MUL word ptr [bp-0Ch]
|
||||
085 000396 F766F4 MUL word ptr [bp-0Ch]
|
||||
086 000399 F766F4 MUL word ptr [bp-0Ch]
|
||||
087 00039C BA0300 MOV dx, 3
|
||||
088 00039F F7E2 MUL dx
|
||||
089 0003A1 8946F4 MOV [bp-0Ch], ax
|
||||
090 0003A4 46 INC si
|
||||
091 JMP L4 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
38
tests/prev/BENCHMUL.b
Executable file
38
tests/prev/BENCHMUL.b
Executable file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHMUL.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
int loc2;
|
||||
long loc3;
|
||||
long loc4;
|
||||
int loc5;
|
||||
|
||||
printf ("enter number of iterations\n");
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc4);
|
||||
scanf ("%d", &loc1);
|
||||
scanf ("%d", &loc2);
|
||||
loc3 = 1;
|
||||
|
||||
while ((loc3 <= loc4)) {
|
||||
loc5 = 1;
|
||||
|
||||
while ((loc5 <= 40)) {
|
||||
loc1 = (((((((((((((((((((((((((loc1 * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * loc1) * 3);
|
||||
loc5 = (loc5 + 1);
|
||||
} /* end of while */
|
||||
loc3 = (loc3 + 1);
|
||||
} /* end of while */
|
||||
printf ("a=%d\n", loc1);
|
||||
}
|
||||
|
||||
91
tests/prev/BENCHMUS.EXE.a1
Executable file
91
tests/prev/BENCHMUS.EXE.a1
Executable file
@ -0,0 +1,91 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0A SUB sp, 0Ah
|
||||
003 000300 56 PUSH si
|
||||
004 000301 57 PUSH di
|
||||
005 000302 B8A801 MOV ax, 1A8h
|
||||
006 000305 50 PUSH ax
|
||||
007 000306 E8240C CALL near ptr printf
|
||||
008 000309 59 POP cx
|
||||
009 00030A 8D46FC LEA ax, [bp-4]
|
||||
010 00030D 50 PUSH ax
|
||||
011 00030E B8C401 MOV ax, 1C4h
|
||||
012 000311 50 PUSH ax
|
||||
013 000312 E8A114 CALL near ptr scanf
|
||||
014 000315 59 POP cx
|
||||
015 000316 59 POP cx
|
||||
016 000317 FF76FE PUSH word ptr [bp-2]
|
||||
017 00031A FF76FC PUSH word ptr [bp-4]
|
||||
018 00031D B8C801 MOV ax, 1C8h
|
||||
019 000320 50 PUSH ax
|
||||
020 000321 E8090C CALL near ptr printf
|
||||
021 000324 83C406 ADD sp, 6
|
||||
022 000327 BE1400 MOV si, 14h
|
||||
023 00032A 8976F6 MOV [bp-0Ah], si
|
||||
024 00032D C746FA0000 MOV word ptr [bp-6], 0
|
||||
025 000332 C746F80100 MOV word ptr [bp-8], 1
|
||||
026 000337 EB4C JMP L1
|
||||
|
||||
027 000385 8B56FA L1: MOV dx, [bp-6]
|
||||
028 000388 8B46F8 MOV ax, [bp-8]
|
||||
029 00038B 3B56FE CMP dx, [bp-2]
|
||||
030 00038E 7CA9 JL L2
|
||||
031 000390 7F05 JG L3
|
||||
032 000392 3B46FC CMP ax, [bp-4]
|
||||
033 000395 76A2 JBE L2
|
||||
|
||||
034 000397 56 L3: PUSH si
|
||||
035 000398 B8E201 MOV ax, 1E2h
|
||||
036 00039B 50 PUSH ax
|
||||
037 00039C E88E0B CALL near ptr printf
|
||||
038 00039F 59 POP cx
|
||||
039 0003A0 59 POP cx
|
||||
040 0003A1 5F POP di
|
||||
041 0003A2 5E POP si
|
||||
042 0003A3 8BE5 MOV sp, bp
|
||||
043 0003A5 5D POP bp
|
||||
044 0003A6 C3 RET
|
||||
|
||||
045 000339 BF0100 L2: MOV di, 1
|
||||
046 00033C EB3A JMP L4
|
||||
|
||||
047 000378 83FF28 L4: CMP di, 28h
|
||||
048 00037B 7EC1 JLE L5
|
||||
049 00037D 8346F801 ADD word ptr [bp-8], 1
|
||||
050 000381 8356FA00 ADC word ptr [bp-6], 0
|
||||
051 JMP L1 ;Synthetic inst
|
||||
|
||||
052 00033E 8BC6 L5: MOV ax, si
|
||||
053 000340 F7E6 MUL si
|
||||
054 000342 F7E6 MUL si
|
||||
055 000344 F7E6 MUL si
|
||||
056 000346 F7E6 MUL si
|
||||
057 000348 F7E6 MUL si
|
||||
058 00034A F7E6 MUL si
|
||||
059 00034C F7E6 MUL si
|
||||
060 00034E F7E6 MUL si
|
||||
061 000350 F7E6 MUL si
|
||||
062 000352 F7E6 MUL si
|
||||
063 000354 F7E6 MUL si
|
||||
064 000356 F7E6 MUL si
|
||||
065 000358 F7E6 MUL si
|
||||
066 00035A F7E6 MUL si
|
||||
067 00035C F7E6 MUL si
|
||||
068 00035E F7E6 MUL si
|
||||
069 000360 F7E6 MUL si
|
||||
070 000362 F7E6 MUL si
|
||||
071 000364 F7E6 MUL si
|
||||
072 000366 F7E6 MUL si
|
||||
073 000368 F7E6 MUL si
|
||||
074 00036A F7E6 MUL si
|
||||
075 00036C F7E6 MUL si
|
||||
076 00036E F7E6 MUL si
|
||||
077 000370 BA0300 MOV dx, 3
|
||||
078 000373 F7E2 MUL dx
|
||||
079 000375 8BF0 MOV si, ax
|
||||
080 000377 47 INC di
|
||||
081 JMP L4 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
89
tests/prev/BENCHMUS.EXE.a2
Executable file
89
tests/prev/BENCHMUS.EXE.a2
Executable file
@ -0,0 +1,89 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0A SUB sp, 0Ah
|
||||
003 000300 56 PUSH si
|
||||
004 000301 57 PUSH di
|
||||
005 000302 B8A801 MOV ax, 1A8h
|
||||
006 000305 50 PUSH ax
|
||||
007 000306 E8240C CALL near ptr printf
|
||||
008 000309 59 POP cx
|
||||
009 00030A 8D46FC LEA ax, [bp-4]
|
||||
010 00030D 50 PUSH ax
|
||||
011 00030E B8C401 MOV ax, 1C4h
|
||||
012 000311 50 PUSH ax
|
||||
013 000312 E8A114 CALL near ptr scanf
|
||||
014 000315 59 POP cx
|
||||
015 000316 59 POP cx
|
||||
016 000317 FF76FE PUSH word ptr [bp-2]
|
||||
017 00031A FF76FC PUSH word ptr [bp-4]
|
||||
018 00031D B8C801 MOV ax, 1C8h
|
||||
019 000320 50 PUSH ax
|
||||
020 000321 E8090C CALL near ptr printf
|
||||
021 000324 83C406 ADD sp, 6
|
||||
022 000327 BE1400 MOV si, 14h
|
||||
023 00032A 8976F6 MOV [bp-0Ah], si
|
||||
024 00032D C746FA0000 MOV word ptr [bp-6], 0
|
||||
025 000332 C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
027 000385 8B56FA L1: MOV dx, [bp-6]
|
||||
028 000388 8B46F8 MOV ax, [bp-8]
|
||||
029 00038B 3B56FE CMP dx, [bp-2]
|
||||
030 00038E 7CA9 JL L2
|
||||
031 000390 7F05 JG L3
|
||||
032 000392 3B46FC CMP ax, [bp-4]
|
||||
033 000395 76A2 JBE L2
|
||||
|
||||
034 000397 56 L3: PUSH si
|
||||
035 000398 B8E201 MOV ax, 1E2h
|
||||
036 00039B 50 PUSH ax
|
||||
037 00039C E88E0B CALL near ptr printf
|
||||
038 00039F 59 POP cx
|
||||
039 0003A0 59 POP cx
|
||||
040 0003A1 5F POP di
|
||||
041 0003A2 5E POP si
|
||||
042 0003A3 8BE5 MOV sp, bp
|
||||
043 0003A5 5D POP bp
|
||||
044 0003A6 C3 RET
|
||||
|
||||
045 000339 BF0100 L2: MOV di, 1
|
||||
|
||||
047 000378 83FF28 L4: CMP di, 28h
|
||||
048 00037B 7EC1 JLE L5
|
||||
049 00037D 8346F801 ADD word ptr [bp-8], 1
|
||||
050 000381 8356FA00 ADC word ptr [bp-6], 0
|
||||
051 JMP L1 ;Synthetic inst
|
||||
|
||||
052 00033E 8BC6 L5: MOV ax, si
|
||||
053 000340 F7E6 MUL si
|
||||
054 000342 F7E6 MUL si
|
||||
055 000344 F7E6 MUL si
|
||||
056 000346 F7E6 MUL si
|
||||
057 000348 F7E6 MUL si
|
||||
058 00034A F7E6 MUL si
|
||||
059 00034C F7E6 MUL si
|
||||
060 00034E F7E6 MUL si
|
||||
061 000350 F7E6 MUL si
|
||||
062 000352 F7E6 MUL si
|
||||
063 000354 F7E6 MUL si
|
||||
064 000356 F7E6 MUL si
|
||||
065 000358 F7E6 MUL si
|
||||
066 00035A F7E6 MUL si
|
||||
067 00035C F7E6 MUL si
|
||||
068 00035E F7E6 MUL si
|
||||
069 000360 F7E6 MUL si
|
||||
070 000362 F7E6 MUL si
|
||||
071 000364 F7E6 MUL si
|
||||
072 000366 F7E6 MUL si
|
||||
073 000368 F7E6 MUL si
|
||||
074 00036A F7E6 MUL si
|
||||
075 00036C F7E6 MUL si
|
||||
076 00036E F7E6 MUL si
|
||||
077 000370 BA0300 MOV dx, 3
|
||||
078 000373 F7E2 MUL dx
|
||||
079 000375 8BF0 MOV si, ax
|
||||
080 000377 47 INC di
|
||||
081 JMP L4 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
38
tests/prev/BENCHMUS.b
Executable file
38
tests/prev/BENCHMUS.b
Executable file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHMUS.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
long loc2;
|
||||
long loc3;
|
||||
int loc4;
|
||||
int loc5;
|
||||
|
||||
printf ("enter number of iterations\n");
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc3);
|
||||
loc4 = 20;
|
||||
loc1 = loc4;
|
||||
loc2 = 1;
|
||||
|
||||
while ((loc2 <= loc3)) {
|
||||
loc5 = 1;
|
||||
|
||||
while ((loc5 <= 40)) {
|
||||
loc4 = (((((((((((((((((((((((((loc4 * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * loc4) * 3);
|
||||
loc5 = (loc5 + 1);
|
||||
} /* end of while */
|
||||
loc2 = (loc2 + 1);
|
||||
} /* end of while */
|
||||
printf ("a=%d\n", loc4);
|
||||
}
|
||||
|
||||
113
tests/prev/BENCHSHO.EXE.a1
Executable file
113
tests/prev/BENCHSHO.EXE.a1
Executable file
@ -0,0 +1,113 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0E SUB sp, 0Eh
|
||||
003 000300 8D46FC LEA ax, [bp-4]
|
||||
004 000303 50 PUSH ax
|
||||
005 000304 B89401 MOV ax, 194h
|
||||
006 000307 50 PUSH ax
|
||||
007 000308 E8E914 CALL near ptr scanf
|
||||
008 00030B 59 POP cx
|
||||
009 00030C 59 POP cx
|
||||
010 00030D FF76FE PUSH word ptr [bp-2]
|
||||
011 000310 FF76FC PUSH word ptr [bp-4]
|
||||
012 000313 B89801 MOV ax, 198h
|
||||
013 000316 50 PUSH ax
|
||||
014 000317 E8510C CALL near ptr printf
|
||||
015 00031A 83C406 ADD sp, 6
|
||||
016 00031D 8D46F2 LEA ax, [bp-0Eh]
|
||||
017 000320 50 PUSH ax
|
||||
018 000321 B8B201 MOV ax, 1B2h
|
||||
019 000324 50 PUSH ax
|
||||
020 000325 E8CC14 CALL near ptr scanf
|
||||
021 000328 59 POP cx
|
||||
022 000329 59 POP cx
|
||||
023 00032A 8D46F4 LEA ax, [bp-0Ch]
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E B8B601 MOV ax, 1B6h
|
||||
026 000331 50 PUSH ax
|
||||
027 000332 E8BF14 CALL near ptr scanf
|
||||
028 000335 59 POP cx
|
||||
029 000336 59 POP cx
|
||||
030 000337 C746FA0000 MOV word ptr [bp-6], 0
|
||||
031 00033C C746F80100 MOV word ptr [bp-8], 1
|
||||
032 000341 E97900 JMP L1
|
||||
|
||||
033 0003BD 8B56FA L1: MOV dx, [bp-6]
|
||||
034 0003C0 8B46F8 MOV ax, [bp-8]
|
||||
035 0003C3 3B56FE CMP dx, [bp-2]
|
||||
036 0003C6 7D03 JGE L2
|
||||
037 0003C8 E979FF JMP L3
|
||||
|
||||
038 000344 C746F60100 L3: MOV word ptr [bp-0Ah], 1
|
||||
039 000349 EB64 JMP L4
|
||||
|
||||
040 0003AF 837EF628 L4: CMP word ptr [bp-0Ah], 28h
|
||||
041 0003B3 7E96 JLE L5
|
||||
042 0003B5 8346F801 ADD word ptr [bp-8], 1
|
||||
043 0003B9 8356FA00 ADC word ptr [bp-6], 0
|
||||
044 JMP L1 ;Synthetic inst
|
||||
|
||||
045 00034B 8B46F2 L5: MOV ax, [bp-0Eh]
|
||||
046 00034E 0346F4 ADD ax, [bp-0Ch]
|
||||
047 000351 0346F6 ADD ax, [bp-0Ah]
|
||||
048 000354 8946F2 MOV [bp-0Eh], ax
|
||||
049 000357 8B46F2 MOV ax, [bp-0Eh]
|
||||
050 00035A D1F8 SAR ax, 1
|
||||
051 00035C 8946F4 MOV [bp-0Ch], ax
|
||||
052 00035F 8B46F4 MOV ax, [bp-0Ch]
|
||||
053 000362 BB0A00 MOV bx, 0Ah
|
||||
054 000365 99 CWD
|
||||
056 000366 F7FB IDIV bx
|
||||
058 000368 8956F2 MOV [bp-0Eh], dx
|
||||
059 00036B 8B46F4 MOV ax, [bp-0Ch]
|
||||
060 00036E 3B46F6 CMP ax, [bp-0Ah]
|
||||
061 000371 7505 JNE L6
|
||||
062 000373 B80100 MOV ax, 1
|
||||
063 000376 EB02 JMP L7
|
||||
|
||||
064 00037A 8946F2 L7: MOV [bp-0Eh], ax
|
||||
065 00037D 8B46F2 MOV ax, [bp-0Eh]
|
||||
066 000380 0B46F6 OR ax, [bp-0Ah]
|
||||
067 000383 8946F4 MOV [bp-0Ch], ax
|
||||
068 000386 8B46F4 MOV ax, [bp-0Ch]
|
||||
069 000389 F7D8 NEG ax
|
||||
070 00038B 1BC0 SBB ax, ax
|
||||
071 00038D 40 INC ax
|
||||
072 00038E 8946F2 MOV [bp-0Eh], ax
|
||||
073 000391 8B46F2 MOV ax, [bp-0Eh]
|
||||
074 000394 0346F6 ADD ax, [bp-0Ah]
|
||||
075 000397 8946F4 MOV [bp-0Ch], ax
|
||||
076 00039A 8B46F4 MOV ax, [bp-0Ch]
|
||||
077 00039D 3B46F6 CMP ax, [bp-0Ah]
|
||||
078 0003A0 7E05 JLE L8
|
||||
079 0003A2 B80100 MOV ax, 1
|
||||
080 0003A5 EB02 JMP L9
|
||||
|
||||
081 0003A9 8946F2 L9: MOV [bp-0Eh], ax
|
||||
082 0003AC FF46F6 INC word ptr [bp-0Ah]
|
||||
083 JMP L4 ;Synthetic inst
|
||||
|
||||
084 0003A7 33C0 L8: XOR ax, ax
|
||||
085 JMP L9 ;Synthetic inst
|
||||
|
||||
086 000378 33C0 L6: XOR ax, ax
|
||||
087 JMP L7 ;Synthetic inst
|
||||
|
||||
088 0003CB 7F08 L2: JG L10
|
||||
089 0003CD 3B46FC CMP ax, [bp-4]
|
||||
090 0003D0 7703 JA L10
|
||||
091 0003D2 E96FFF JMP L3
|
||||
|
||||
092 0003D5 FF76F2 L10: PUSH word ptr [bp-0Eh]
|
||||
093 0003D8 B8BA01 MOV ax, 1BAh
|
||||
094 0003DB 50 PUSH ax
|
||||
095 0003DC E88C0B CALL near ptr printf
|
||||
096 0003DF 59 POP cx
|
||||
097 0003E0 59 POP cx
|
||||
098 0003E1 8BE5 MOV sp, bp
|
||||
099 0003E3 5D POP bp
|
||||
100 0003E4 C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
109
tests/prev/BENCHSHO.EXE.a2
Executable file
109
tests/prev/BENCHSHO.EXE.a2
Executable file
@ -0,0 +1,109 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC0E SUB sp, 0Eh
|
||||
003 000300 8D46FC LEA ax, [bp-4]
|
||||
004 000303 50 PUSH ax
|
||||
005 000304 B89401 MOV ax, 194h
|
||||
006 000307 50 PUSH ax
|
||||
007 000308 E8E914 CALL near ptr scanf
|
||||
008 00030B 59 POP cx
|
||||
009 00030C 59 POP cx
|
||||
010 00030D FF76FE PUSH word ptr [bp-2]
|
||||
011 000310 FF76FC PUSH word ptr [bp-4]
|
||||
012 000313 B89801 MOV ax, 198h
|
||||
013 000316 50 PUSH ax
|
||||
014 000317 E8510C CALL near ptr printf
|
||||
015 00031A 83C406 ADD sp, 6
|
||||
016 00031D 8D46F2 LEA ax, [bp-0Eh]
|
||||
017 000320 50 PUSH ax
|
||||
018 000321 B8B201 MOV ax, 1B2h
|
||||
019 000324 50 PUSH ax
|
||||
020 000325 E8CC14 CALL near ptr scanf
|
||||
021 000328 59 POP cx
|
||||
022 000329 59 POP cx
|
||||
023 00032A 8D46F4 LEA ax, [bp-0Ch]
|
||||
024 00032D 50 PUSH ax
|
||||
025 00032E B8B601 MOV ax, 1B6h
|
||||
026 000331 50 PUSH ax
|
||||
027 000332 E8BF14 CALL near ptr scanf
|
||||
028 000335 59 POP cx
|
||||
029 000336 59 POP cx
|
||||
030 000337 C746FA0000 MOV word ptr [bp-6], 0
|
||||
031 00033C C746F80100 MOV word ptr [bp-8], 1
|
||||
|
||||
033 0003BD 8B56FA L1: MOV dx, [bp-6]
|
||||
034 0003C0 8B46F8 MOV ax, [bp-8]
|
||||
035 0003C3 3B56FE CMP dx, [bp-2]
|
||||
036 0003C6 7D03 JGE L2
|
||||
|
||||
038 000344 C746F60100 L3: MOV word ptr [bp-0Ah], 1
|
||||
|
||||
040 0003AF 837EF628 L4: CMP word ptr [bp-0Ah], 28h
|
||||
041 0003B3 7E96 JLE L5
|
||||
042 0003B5 8346F801 ADD word ptr [bp-8], 1
|
||||
043 0003B9 8356FA00 ADC word ptr [bp-6], 0
|
||||
044 JMP L1 ;Synthetic inst
|
||||
|
||||
045 00034B 8B46F2 L5: MOV ax, [bp-0Eh]
|
||||
046 00034E 0346F4 ADD ax, [bp-0Ch]
|
||||
047 000351 0346F6 ADD ax, [bp-0Ah]
|
||||
048 000354 8946F2 MOV [bp-0Eh], ax
|
||||
049 000357 8B46F2 MOV ax, [bp-0Eh]
|
||||
050 00035A D1F8 SAR ax, 1
|
||||
051 00035C 8946F4 MOV [bp-0Ch], ax
|
||||
052 00035F 8B46F4 MOV ax, [bp-0Ch]
|
||||
053 000362 BB0A00 MOV bx, 0Ah
|
||||
054 000365 99 CWD
|
||||
055 MOV tmp, dx:ax ;Synthetic inst
|
||||
056 000366 F7FB IDIV bx
|
||||
057 MOD bx ;Synthetic inst
|
||||
058 000368 8956F2 MOV [bp-0Eh], dx
|
||||
059 00036B 8B46F4 MOV ax, [bp-0Ch]
|
||||
060 00036E 3B46F6 CMP ax, [bp-0Ah]
|
||||
061 000371 7505 JNE L6
|
||||
062 000373 B80100 MOV ax, 1
|
||||
|
||||
064 00037A 8946F2 L7: MOV [bp-0Eh], ax
|
||||
065 00037D 8B46F2 MOV ax, [bp-0Eh]
|
||||
066 000380 0B46F6 OR ax, [bp-0Ah]
|
||||
067 000383 8946F4 MOV [bp-0Ch], ax
|
||||
068 000386 8B46F4 MOV ax, [bp-0Ch]
|
||||
069 000389 F7D8 NEG ax
|
||||
070 00038B 1BC0 SBB ax, ax
|
||||
071 00038D 40 INC ax
|
||||
072 00038E 8946F2 MOV [bp-0Eh], ax
|
||||
073 000391 8B46F2 MOV ax, [bp-0Eh]
|
||||
074 000394 0346F6 ADD ax, [bp-0Ah]
|
||||
075 000397 8946F4 MOV [bp-0Ch], ax
|
||||
076 00039A 8B46F4 MOV ax, [bp-0Ch]
|
||||
077 00039D 3B46F6 CMP ax, [bp-0Ah]
|
||||
078 0003A0 7E05 JLE L8
|
||||
079 0003A2 B80100 MOV ax, 1
|
||||
|
||||
081 0003A9 8946F2 L9: MOV [bp-0Eh], ax
|
||||
082 0003AC FF46F6 INC word ptr [bp-0Ah]
|
||||
083 JMP L4 ;Synthetic inst
|
||||
|
||||
084 0003A7 33C0 L8: XOR ax, ax
|
||||
085 JMP L9 ;Synthetic inst
|
||||
|
||||
086 000378 33C0 L6: XOR ax, ax
|
||||
087 JMP L7 ;Synthetic inst
|
||||
|
||||
088 0003CB 7F08 L2: JG L10
|
||||
089 0003CD 3B46FC CMP ax, [bp-4]
|
||||
090 0003D0 7703 JA L10
|
||||
|
||||
092 0003D5 FF76F2 L10: PUSH word ptr [bp-0Eh]
|
||||
093 0003D8 B8BA01 MOV ax, 1BAh
|
||||
094 0003DB 50 PUSH ax
|
||||
095 0003DC E88C0B CALL near ptr printf
|
||||
096 0003DF 59 POP cx
|
||||
097 0003E0 59 POP cx
|
||||
098 0003E1 8BE5 MOV sp, bp
|
||||
099 0003E3 5D POP bp
|
||||
100 0003E4 C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
59
tests/prev/BENCHSHO.b
Executable file
59
tests/prev/BENCHSHO.b
Executable file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BENCHSHO.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
int loc2;
|
||||
int loc3;
|
||||
long loc4;
|
||||
long loc5;
|
||||
int loc6; /* ax */
|
||||
|
||||
scanf ("%ld", &loc0);
|
||||
printf ("executing %ld iterations\n", loc5);
|
||||
scanf ("%ld", &loc1);
|
||||
scanf ("%ld", &loc2);
|
||||
loc4 = 1;
|
||||
|
||||
while ((loc4 <= loc5)) {
|
||||
loc3 = 1;
|
||||
|
||||
while ((loc3 <= 40)) {
|
||||
loc1 = ((loc1 + loc2) + loc3);
|
||||
loc2 = (loc1 >> 1);
|
||||
loc1 = (loc2 % 10);
|
||||
|
||||
if (loc2 == loc3) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc1 = loc6;
|
||||
loc2 = (loc1 | loc3);
|
||||
loc1 = !loc2;
|
||||
loc2 = (loc1 + loc3);
|
||||
|
||||
if (loc2 > loc3) {
|
||||
loc6 = 1;
|
||||
}
|
||||
else {
|
||||
loc6 = 0;
|
||||
}
|
||||
loc1 = loc6;
|
||||
loc3 = (loc3 + 1);
|
||||
} /* end of while */
|
||||
loc4 = (loc4 + 1);
|
||||
} /* end of while */
|
||||
printf ("a=%d\n", loc1);
|
||||
}
|
||||
|
||||
58
tests/prev/BYTEOPS.EXE.a1
Executable file
58
tests/prev/BYTEOPS.EXE.a1
Executable file
@ -0,0 +1,58 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC02 SUB sp, 2
|
||||
003 000300 C646FEFF MOV byte ptr [bp-2], 0FFh
|
||||
004 000304 C646FF8F MOV byte ptr [bp-1], 8Fh
|
||||
005 000308 8A46FE MOV al, [bp-2]
|
||||
006 00030B 0246FF ADD al, [bp-1]
|
||||
007 00030E 8846FF MOV [bp-1], al
|
||||
008 000311 8A46FE MOV al, [bp-2]
|
||||
009 000314 2A46FF SUB al, [bp-1]
|
||||
010 000317 8846FE MOV [bp-2], al
|
||||
011 00031A 8A46FE MOV al, [bp-2]
|
||||
012 00031D B400 MOV ah, 0
|
||||
013 00031F 8A56FF MOV dl, [bp-1]
|
||||
014 000322 B600 MOV dh, 0
|
||||
015 000324 F7E2 MUL dx
|
||||
016 000326 8846FE MOV [bp-2], al
|
||||
017 000329 8A46FF MOV al, [bp-1]
|
||||
018 00032C B400 MOV ah, 0
|
||||
019 00032E 8A56FE MOV dl, [bp-2]
|
||||
020 000331 B600 MOV dh, 0
|
||||
021 000333 8BDA MOV bx, dx
|
||||
022 000335 99 CWD
|
||||
024 000336 F7FB IDIV bx
|
||||
026 000338 8846FF MOV [bp-1], al
|
||||
027 00033B 8A46FF MOV al, [bp-1]
|
||||
028 00033E B400 MOV ah, 0
|
||||
029 000340 8A56FE MOV dl, [bp-2]
|
||||
030 000343 B600 MOV dh, 0
|
||||
031 000345 8BDA MOV bx, dx
|
||||
032 000347 99 CWD
|
||||
034 000348 F7FB IDIV bx
|
||||
036 00034A 8856FF MOV [bp-1], dl
|
||||
037 00034D 8A46FE MOV al, [bp-2]
|
||||
038 000350 B105 MOV cl, 5
|
||||
039 000352 D2E0 SHL al, cl
|
||||
040 000354 8846FE MOV [bp-2], al
|
||||
041 000357 8A46FF MOV al, [bp-1]
|
||||
042 00035A 8A4EFE MOV cl, [bp-2]
|
||||
043 00035D D2E8 SHR al, cl
|
||||
044 00035F 8846FF MOV [bp-1], al
|
||||
045 000362 8A46FF MOV al, [bp-1]
|
||||
046 000365 B400 MOV ah, 0
|
||||
047 000367 50 PUSH ax
|
||||
048 000368 8A46FE MOV al, [bp-2]
|
||||
049 00036B B400 MOV ah, 0
|
||||
050 00036D 50 PUSH ax
|
||||
051 00036E B89401 MOV ax, 194h
|
||||
052 000371 50 PUSH ax
|
||||
053 000372 E8AB06 CALL near ptr printf
|
||||
054 000375 83C406 ADD sp, 6
|
||||
055 000378 8BE5 MOV sp, bp
|
||||
056 00037A 5D POP bp
|
||||
057 00037B C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
62
tests/prev/BYTEOPS.EXE.a2
Executable file
62
tests/prev/BYTEOPS.EXE.a2
Executable file
@ -0,0 +1,62 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC02 SUB sp, 2
|
||||
003 000300 C646FEFF MOV byte ptr [bp-2], 0FFh
|
||||
004 000304 C646FF8F MOV byte ptr [bp-1], 8Fh
|
||||
005 000308 8A46FE MOV al, [bp-2]
|
||||
006 00030B 0246FF ADD al, [bp-1]
|
||||
007 00030E 8846FF MOV [bp-1], al
|
||||
008 000311 8A46FE MOV al, [bp-2]
|
||||
009 000314 2A46FF SUB al, [bp-1]
|
||||
010 000317 8846FE MOV [bp-2], al
|
||||
011 00031A 8A46FE MOV al, [bp-2]
|
||||
012 00031D B400 MOV ah, 0
|
||||
013 00031F 8A56FF MOV dl, [bp-1]
|
||||
014 000322 B600 MOV dh, 0
|
||||
015 000324 F7E2 MUL dx
|
||||
016 000326 8846FE MOV [bp-2], al
|
||||
017 000329 8A46FF MOV al, [bp-1]
|
||||
018 00032C B400 MOV ah, 0
|
||||
019 00032E 8A56FE MOV dl, [bp-2]
|
||||
020 000331 B600 MOV dh, 0
|
||||
021 000333 8BDA MOV bx, dx
|
||||
022 000335 99 CWD
|
||||
023 MOV tmp, dx:ax ;Synthetic inst
|
||||
024 000336 F7FB IDIV bx
|
||||
025 MOD bx ;Synthetic inst
|
||||
026 000338 8846FF MOV [bp-1], al
|
||||
027 00033B 8A46FF MOV al, [bp-1]
|
||||
028 00033E B400 MOV ah, 0
|
||||
029 000340 8A56FE MOV dl, [bp-2]
|
||||
030 000343 B600 MOV dh, 0
|
||||
031 000345 8BDA MOV bx, dx
|
||||
032 000347 99 CWD
|
||||
033 MOV tmp, dx:ax ;Synthetic inst
|
||||
034 000348 F7FB IDIV bx
|
||||
035 MOD bx ;Synthetic inst
|
||||
036 00034A 8856FF MOV [bp-1], dl
|
||||
037 00034D 8A46FE MOV al, [bp-2]
|
||||
038 000350 B105 MOV cl, 5
|
||||
039 000352 D2E0 SHL al, cl
|
||||
040 000354 8846FE MOV [bp-2], al
|
||||
041 000357 8A46FF MOV al, [bp-1]
|
||||
042 00035A 8A4EFE MOV cl, [bp-2]
|
||||
043 00035D D2E8 SHR al, cl
|
||||
044 00035F 8846FF MOV [bp-1], al
|
||||
045 000362 8A46FF MOV al, [bp-1]
|
||||
046 000365 B400 MOV ah, 0
|
||||
047 000367 50 PUSH ax
|
||||
048 000368 8A46FE MOV al, [bp-2]
|
||||
049 00036B B400 MOV ah, 0
|
||||
050 00036D 50 PUSH ax
|
||||
051 00036E B89401 MOV ax, 194h
|
||||
052 000371 50 PUSH ax
|
||||
053 000372 E8AB06 CALL near ptr printf
|
||||
054 000375 83C406 ADD sp, 6
|
||||
055 000378 8BE5 MOV sp, bp
|
||||
056 00037A 5D POP bp
|
||||
057 00037B C3 RET
|
||||
|
||||
main ENDP
|
||||
|
||||
28
tests/prev/BYTEOPS.b
Executable file
28
tests/prev/BYTEOPS.b
Executable file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Input file : ./tests/inputs/BYTEOPS.EXE
|
||||
* File type : EXE
|
||||
*/
|
||||
|
||||
#include "dcc.h"
|
||||
|
||||
|
||||
void main ()
|
||||
/* Takes no parameters.
|
||||
* High-level language prologue code.
|
||||
*/
|
||||
{
|
||||
int loc1;
|
||||
int loc2;
|
||||
|
||||
loc1 = 255;
|
||||
loc2 = 143;
|
||||
loc2 = (loc1 + loc2);
|
||||
loc1 = (loc1 - loc2);
|
||||
loc1 = (loc1 * loc2);
|
||||
loc2 = (loc2 / loc1);
|
||||
loc2 = (loc2 % loc1);
|
||||
loc1 = (loc1 << 5);
|
||||
loc2 = (loc2 >> loc1);
|
||||
printf ("a = %d, b = %d\n", loc1, loc2);
|
||||
}
|
||||
|
||||
90
tests/prev/FIBOS.EXE.a1
Executable file
90
tests/prev/FIBOS.EXE.a1
Executable file
@ -0,0 +1,90 @@
|
||||
main PROC NEAR
|
||||
000 0002FA 55 PUSH bp
|
||||
001 0002FB 8BEC MOV bp, sp
|
||||
002 0002FD 83EC04 SUB sp, 4
|
||||
003 000300 56 PUSH si
|
||||
004 000301 57 PUSH di
|
||||
005 000302 B89401 MOV ax, 194h
|
||||
006 000305 50 PUSH ax
|
||||
007 000306 E8080C CALL near ptr printf
|
||||
008 000309 59 POP cx
|
||||
009 00030A 8D46FC LEA ax, [bp-4]
|
||||
010 00030D 50 PUSH ax
|
||||
011 00030E B8B101 MOV ax, 1B1h
|
||||
012 000311 50 PUSH ax
|
||||
013 000312 E88514 CALL near ptr scanf
|
||||
014 000315 59 POP cx
|
||||
015 000316 59 POP cx
|
||||
016 000317 BE0100 MOV si, 1
|
||||
017 00031A EB2D JMP L1
|
||||
|
||||
018 000349 3B76FC L1: CMP si, [bp-4]
|
||||
019 00034C 7ECE JLE L2
|
||||
020 00034E 33C0 XOR ax, ax
|
||||
021 000350 50 PUSH ax
|
||||
022 000351 E87300 CALL near ptr exit
|
||||
023 000354 59 POP cx
|
||||
024 000355 5F POP di
|
||||
025 000356 5E POP si
|
||||
026 000357 8BE5 MOV sp, bp
|
||||
027 000359 5D POP bp
|
||||
028 00035A C3 RET
|
||||
|
||||
029 00031C B8B401 L2: MOV ax, 1B4h
|
||||
030 00031F 50 PUSH ax
|
||||
031 000320 E8EE0B CALL near ptr printf
|
||||
032 000323 59 POP cx
|
||||
033 000324 8D46FE LEA ax, [bp-2]
|
||||
034 000327 50 PUSH ax
|
||||
035 000328 B8C301 MOV ax, 1C3h
|
||||
036 00032B 50 PUSH ax
|
||||
037 00032C E86B14 CALL near ptr scanf
|
||||
038 00032F 59 POP cx
|
||||
039 000330 59 POP cx
|
||||
040 000331 FF76FE PUSH word ptr [bp-2]
|
||||
041 000334 E82400 CALL near ptr proc_1
|
||||
042 000337 59 POP cx
|
||||
043 000338 8BF8 MOV di, ax
|
||||
044 00033A 57 PUSH di
|
||||
045 00033B FF76FE PUSH word ptr [bp-2]
|
||||
046 00033E B8C601 MOV ax, 1C6h
|
||||
047 000341 50 PUSH ax
|
||||
048 000342 E8CC0B CALL near ptr printf
|
||||
049 000345 83C406 ADD sp, 6
|
||||
050 000348 46 INC si
|
||||
051 JMP L1 ;Synthetic inst
|
||||
|
||||
main ENDP
|
||||
|
||||
proc_1 PROC NEAR
|
||||
000 00035B 55 PUSH bp
|
||||
001 00035C 8BEC MOV bp, sp
|
||||
002 00035E 56 PUSH si
|
||||
003 00035F 8B7604 MOV si, [bp+4]
|
||||
004 000362 83FE02 CMP si, 2
|
||||
005 000365 7E1C JLE L3
|
||||
006 000367 8BC6 MOV ax, si
|
||||
007 000369 48 DEC ax
|
||||
008 00036A 50 PUSH ax
|
||||
009 00036B E8EDFF CALL near ptr proc_1
|
||||
010 00036E 59 POP cx
|
||||
011 00036F 50 PUSH ax
|
||||
012 000370 8BC6 MOV ax, si
|
||||
013 000372 05FEFF ADD ax, 0FFFEh
|
||||
014 000375 50 PUSH ax
|
||||
015 000376 E8E2FF CALL near ptr proc_1
|
||||
016 000379 59 POP cx
|
||||
017 00037A 8BD0 MOV dx, ax
|
||||
018 00037C 58 POP ax
|
||||
019 00037D 03C2 ADD ax, dx
|
||||
020 00037F EB07 JMP L4
|
||||
|
||||
021 000388 5E L4: POP si
|
||||
022 000389 5D POP bp
|
||||
023 00038A C3 RET
|
||||
|
||||
024 000383 B80100 L3: MOV ax, 1
|
||||
025 000386 EB00 JMP L4
|
||||
|
||||
proc_1 ENDP
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user