This commit is contained in:
Artur K 2011-11-24 20:19:41 +01:00
commit 4c249fe5c4
105 changed files with 21153 additions and 0 deletions

63
CMakeLists.txt Executable file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

265
src/comwrite.cpp Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

163
src/dcc.cpp Normal file
View 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

File diff suppressed because it is too large Load Diff

86
src/error.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

424
src/locident.cpp Normal file
View 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

File diff suppressed because it is too large Load Diff

448
src/perfhlib.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

BIN
tests/inputs/BENCHLNG.EXE Executable file

Binary file not shown.

BIN
tests/inputs/BENCHMUL.EXE Executable file

Binary file not shown.

BIN
tests/inputs/BENCHMUS.EXE Executable file

Binary file not shown.

BIN
tests/inputs/BENCHSHO.EXE Executable file

Binary file not shown.

BIN
tests/inputs/BYTEOPS.EXE Executable file

Binary file not shown.

BIN
tests/inputs/FIBOS.EXE Executable file

Binary file not shown.

BIN
tests/inputs/MIN.EXE Executable file

Binary file not shown.

View 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

View 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
View 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");
}

View 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

View 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
View 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);
}

View 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

View 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
View 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);
}

View 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

View 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
View 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);
}

View 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

View 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
View 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);
}

View 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

View 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
View 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);
}

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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