From 2a59d07ef2d43b6af4d679f4c549c3173bf1203d Mon Sep 17 00:00:00 2001 From: nemerle Date: Thu, 28 May 2015 17:17:26 +0200 Subject: [PATCH] Orignal dcc code Only 2 differences with original release: add return type to main int disassem.cpp popPosStack() add cast to intptr_t --- CMakeLists.txt | 63 +- include/BasicBlock.h | 132 -- include/BinaryImage.h | 20 - include/Enums.h | 283 ----- include/IdentType.h | 33 - include/Procedure.h | 199 --- include/StackFrame.h | 24 - include/ast.h | 272 ++-- include/bundle.h | 43 +- include/dcc.h | 361 ++++-- include/disassem.h | 33 +- include/dosdcc.h | 39 +- include/error.h | 49 +- include/graph.h | 173 +-- include/hlicode.h | 24 +- include/icode.h | 808 ++++++------ include/idioms/arith_idioms.h | 75 -- include/idioms/call_idioms.h | 42 - include/idioms/epilogue_idioms.h | 39 - include/idioms/idiom.h | 22 - include/idioms/idiom1.h | 17 - include/idioms/mov_idioms.h | 36 - include/idioms/neg_idioms.h | 33 - include/idioms/shift_idioms.h | 66 - include/idioms/xor_idioms.h | 46 - include/locident.h | 190 ++- include/machine_x86.h | 82 -- include/perfhlib.h | 47 +- include/project.h | 77 -- include/scanner.h | 40 +- include/state.h | 34 +- include/symtab.h | 118 +- include/types.h | 96 +- prototypes/dcclibs.dat | Bin 0 -> 8833 bytes sigs/dccb2s.sig | Bin 0 -> 39073 bytes src/BasicBlock.cpp | 443 ------- src/CMakeLists.txt | 7 - src/Procedure.cpp | 32 - src/ast.cpp | 1476 +++++++++++----------- src/backend.cpp | 829 +++++++++---- src/bundle.cpp | 126 +- src/chklib.cpp | 688 ++++++----- src/comwrite.cpp | 494 ++++---- src/control.cpp | 1071 ++++++++-------- src/dataflow.cpp | 1988 ++++++++++++++---------------- src/dcc.cpp | 132 +- src/disassem.cpp | 1761 +++++++++++++++++++------- src/error.cpp | 77 +- src/fixwild.cpp | 138 ++- src/frontend.cpp | 693 +++++++---- src/graph.cpp | 654 +++++----- src/hlicode.cpp | 838 ++++++------- src/icode.cpp | 177 ++- src/idioms.cpp | 1463 +++++++++++++++++++--- src/idioms/arith_idioms.cpp | 314 ----- src/idioms/call_idioms.cpp | 111 -- src/idioms/epilogue_idioms.cpp | 153 --- src/idioms/idiom1.cpp | 137 -- src/idioms/mov_idioms.cpp | 110 -- src/idioms/neg_idioms.cpp | 102 -- src/idioms/shift_idioms.cpp | 170 --- src/idioms/xor_idioms.cpp | 134 -- src/locident.cpp | 469 +++---- src/machine_x86.cpp | 111 -- src/parser.cpp | 1483 +++++++++++----------- src/perfhlib.cpp | 397 +++++- src/procs.cpp | 619 +++++----- src/project.cpp | 73 -- src/proplong.cpp | 911 +++++++------- src/reducible.cpp | 518 ++++---- src/scanner.cpp | 1282 +++++++++---------- src/symtab.cpp | 630 ++++++++-- src/tests/comwrite.cpp | 14 - src/udm.cpp | 208 ++-- 74 files changed, 12192 insertions(+), 12457 deletions(-) delete mode 100644 include/BasicBlock.h delete mode 100644 include/BinaryImage.h delete mode 100644 include/Enums.h delete mode 100644 include/IdentType.h delete mode 100644 include/Procedure.h delete mode 100644 include/StackFrame.h delete mode 100644 include/idioms/arith_idioms.h delete mode 100644 include/idioms/call_idioms.h delete mode 100644 include/idioms/epilogue_idioms.h delete mode 100644 include/idioms/idiom.h delete mode 100644 include/idioms/idiom1.h delete mode 100644 include/idioms/mov_idioms.h delete mode 100644 include/idioms/neg_idioms.h delete mode 100644 include/idioms/shift_idioms.h delete mode 100644 include/idioms/xor_idioms.h delete mode 100644 include/machine_x86.h delete mode 100644 include/project.h create mode 100644 prototypes/dcclibs.dat create mode 100644 sigs/dccb2s.sig delete mode 100644 src/BasicBlock.cpp delete mode 100644 src/CMakeLists.txt delete mode 100644 src/Procedure.cpp delete mode 100644 src/idioms/arith_idioms.cpp delete mode 100644 src/idioms/call_idioms.cpp delete mode 100644 src/idioms/epilogue_idioms.cpp delete mode 100644 src/idioms/idiom1.cpp delete mode 100644 src/idioms/mov_idioms.cpp delete mode 100644 src/idioms/neg_idioms.cpp delete mode 100644 src/idioms/shift_idioms.cpp delete mode 100644 src/idioms/xor_idioms.cpp delete mode 100644 src/machine_x86.cpp delete mode 100644 src/project.cpp delete mode 100644 src/tests/comwrite.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 161c11a..91059fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(dcc_original) CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -OPTION(dcc_build_tests "Enable unit tests." OFF) +#OPTION(dcc_build_tests "Enable unit tests." OFF) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D__UNIX__ -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS) IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)") @@ -14,25 +14,24 @@ ENDIF() SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeScripts;${CMAKE_MODULE_PATH}) -FIND_PACKAGE(LLVM) -FIND_PACKAGE(Boost) -IF(dcc_build_tests) - FIND_PACKAGE(GMock) -ENDIF() +#FIND_PACKAGE(LLVM) +#FIND_PACKAGE(Boost) +#IF(dcc_build_tests) +# FIND_PACKAGE(GMock) +#ENDIF() -ADD_SUBDIRECTORY(3rd_party) +#ADD_SUBDIRECTORY(3rd_party) -llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support) +#llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native mc support) INCLUDE_DIRECTORIES( - 3rd_party/libdisasm +# 3rd_party/libdisasm include - include/idioms - ${Boost_INCLUDE_DIRS} - ${LLVM_INCLUDE_DIRS} +# include/idioms +# ${Boost_INCLUDE_DIRS} +# ${LLVM_INCLUDE_DIRS} ) set(dcc_SOURCES - src/dcc.cpp src/ast.cpp src/backend.cpp src/bundle.cpp @@ -40,75 +39,47 @@ set(dcc_SOURCES src/comwrite.cpp src/control.cpp src/dataflow.cpp + src/dcc.cpp src/disassem.cpp src/error.cpp src/fixwild.cpp src/frontend.cpp src/graph.cpp src/hlicode.cpp - src/machine_x86.cpp src/icode.cpp src/idioms.cpp - src/idioms/idiom1.cpp - src/idioms/arith_idioms.cpp - src/idioms/call_idioms.cpp - src/idioms/epilogue_idioms.cpp - src/idioms/mov_idioms.cpp - src/idioms/neg_idioms.cpp - src/idioms/shift_idioms.cpp - src/idioms/xor_idioms.cpp src/locident.cpp src/parser.cpp src/perfhlib.cpp src/procs.cpp - src/project.cpp - src/Procedure.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/BinaryImage.h include/dcc.h include/disassem.h include/dosdcc.h include/error.h include/graph.h include/hlicode.h - include/machine_x86.h include/icode.h - include/idioms/idiom.h - include/idioms/idiom1.h - include/idioms/arith_idioms.h - include/idioms/call_idioms.h - include/idioms/epilogue_idioms.h - include/idioms/mov_idioms.h - include/idioms/neg_idioms.h - include/idioms/shift_idioms.h - include/idioms/xor_idioms.h include/locident.h include/perfhlib.h - include/project.h include/scanner.h include/state.h include/symtab.h include/types.h - include/Procedure.h - include/StackFrame.h - include/BasicBlock.h ) SOURCE_GROUP(Source FILES ${dcc_SOURCES}) SOURCE_GROUP(Headers FILES ${dcc_HEADERS}) ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS}) -TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES}) -if(dcc_build_tests) -ADD_SUBDIRECTORY(src) -endif() - - +#TARGET_LINK_LIBRARIES(dcc_original disasm_s ${REQ_LLVM_LIBRARIES}) +#if(dcc_build_tests) +#ADD_SUBDIRECTORY(src) +#endif() diff --git a/include/BasicBlock.h b/include/BasicBlock.h deleted file mode 100644 index acd0cd2..0000000 --- a/include/BasicBlock.h +++ /dev/null @@ -1,132 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include "icode.h" -#include "types.h" -#include "graph.h" -//#include "icode.h" -/* Basic block (BB) node definition */ -struct Function; -class CIcodeRec; -struct BB; -struct LOCAL_ID; -struct interval; - -struct TYPEADR_TYPE -{ - uint32_t ip; /* Out edge icode address */ - BB * BBptr; /* Out edge pointer to next BB */ - interval *intPtr; /* Out edge ptr to next interval*/ -}; - -struct BB : public llvm::ilist_node -{ -private: - BB(const BB&); - BB() : nodeType(0),traversed(DFS_NONE), - numHlIcodes(0),flg(0), - inEdges(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) - { - - } - //friend class SymbolTableListTraits; - typedef boost::iterator_range rCODE; - rCODE instructions; - -public: - struct ValidFunctor - { - bool operator()(BB *p) {return p->valid();} - }; - iICODE begin(); - iICODE end() const; - riICODE rbegin(); - riICODE rend(); - ICODE &front(); - ICODE &back(); - size_t size(); - uint8_t nodeType; /* Type of node */ - eDFS traversed; /* last traversal id is held here traversed yet? */ - int numHlIcodes; /* No. of high-level icodes */ - uint32_t flg; /* BB flags */ - - /* In edges and out edges */ - std::vector inEdges; // does not own held pointers - - //int numOutEdges; /* Number of out edges */ - std::vector 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)) */ - std::bitset<32> liveUse; /* LiveUse(b) */ - std::bitset<32> def; /* Def(b) */ - std::bitset<32> liveIn; /* LiveIn(b) */ - std::bitset<32> 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, uint8_t nodeType, int numOutEdges, Function * parent); - static BB * Create(iICODE start, iICODE fin, uint8_t _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 &dfsLast, int *first, int *last); - void displayDfs(); - void display(); - /// getParent - Return the enclosing method, or null if none - /// - const Function *getParent() const { return Parent; } - Function *getParent() { return Parent; } - void writeBB(std::ostream &ostr, int lev, Function *pProc, int *numLoc); - BB * rmJMP(int marker, BB *pBB); - void genDU1(); - int findBBExps(LOCAL_ID &locals, Function *f); - bool valid() {return 0==(flg & INVALID_BB); } - bool wasTraversedAtLevel(int l) const {return traversed==l;} - ICODE * writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond); - void addOutEdge(uint32_t ip) // TODO: fix this - { - edges[0].ip = ip; - } - void RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode); -private: - bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at); - void ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode); - bool isEndOfPath(int latch_node_idx) const; - Function *Parent; - -}; diff --git a/include/BinaryImage.h b/include/BinaryImage.h deleted file mode 100644 index dcd3fb9..0000000 --- a/include/BinaryImage.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include -struct PROG /* Loaded program image parameters */ -{ - int16_t initCS; - int16_t initIP; /* These are initial load values */ - int16_t initSS; /* Probably not of great interest */ - uint16_t initSP; - bool fCOM; /* Flag set if COM program (else EXE)*/ - int cReloc; /* No. of relocation table entries */ - uint32_t * relocTable; /* Ptr. to relocation table */ - uint8_t * map; /* Memory bitmap ptr */ - int cProcs; /* Number of procedures so far */ - int offMain; /* The offset of the main() proc */ - uint16_t segMain; /* The segment of the main() proc */ - bool bSigs; /* True if signatures loaded */ - int cbImage; /* Length of image in bytes */ - uint8_t * Image; /* Allocated by loader to hold entire program image */ -}; - diff --git a/include/Enums.h b/include/Enums.h deleted file mode 100644 index d2d8636..0000000 --- a/include/Enums.h +++ /dev/null @@ -1,283 +0,0 @@ -#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, /* <= */ - 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) */ -}; -/* LOW_LEVEL icode flags */ -#define NO_SRC_B 0xF7FFFF /* Masks off SRC_B */ -enum eLLFlags -{ - - B =0x0000001, /* uint8_t 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 uint16_t 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 uint8_t (dest is uint16_t) */ - 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 */ -#define ICODEMASK 0x0FF00FF /* Masks off parser flags */ -}; -/* 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 -{ - //iINVALID, - 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 */ -}; -/* 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 */ -}; -/* HIGH_LEVEL icodes opcodes */ -enum hlIcode -{ - HLI_INVALID, - 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 */ -} ; -/* Type definitions used in the decompiled program */ -enum hlType -{ - 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 */ -}; - -/* 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 */ -}; - -/* LOW_LEVEL icode, DU flag bits */ -enum eDuFlags -{ - Cf=1, - Sf=2, - Zf=4, - Df=8 -}; diff --git a/include/IdentType.h b/include/IdentType.h deleted file mode 100644 index b743711..0000000 --- a/include/IdentType.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include "ast.h" -#include "types.h" -#include "machine_x86.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 */ - uint32_t kte; /* value of the constant */ - uint8_t size; /* #bytes size constant */ - } kte; - uint32_t 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 */ - eReg seg; /* segment */ - eReg regi; /* index mode */ - int16_t off; /* offset */ - } other; - } idNode; -}; diff --git a/include/Procedure.h b/include/Procedure.h deleted file mode 100644 index 77c66bd..0000000 --- a/include/Procedure.h +++ /dev/null @@ -1,199 +0,0 @@ -#pragma once -#include -#include -#include -#include "BasicBlock.h" -#include "locident.h" -#include "state.h" -#include "icode.h" -#include "StackFrame.h" -/* PROCEDURE NODE */ -struct CALL_GRAPH; -struct COND_EXPR; -struct Disassembler; -struct Function; -struct CALL_GRAPH; - -typedef llvm::iplist FunctionListType; -typedef FunctionListType lFunction; -typedef lFunction::iterator ilFunction; - -namespace llvm -{ -// Traits for intrusive list of basic blocks... -template<> -struct ilist_traits : public ilist_default_traits -{ - - // createSentinel is used to get hold of the node that marks the end of the - // list... (same trick used here as in ilist_traits) - BB *createSentinel() const { - return static_cast(&Sentinel); - } - static void destroySentinel(BB*) {} - - BB *provideInitialHead() const { return createSentinel(); } - BB *ensureHead(BB*) const { return createSentinel(); } - static void noteHead(BB*, BB*) {} - - //static ValueSymbolTable *getSymTab(Function *ItemParent); -private: - mutable ilist_half_node Sentinel; -}; -} -/* Procedure FLAGS */ -enum PROC_FLAGS -{ - PROC_BADINST=0x00000100,/* Proc contains invalid or 386 instruction */ - PROC_IJMP =0x00000200,/* Proc incomplete due to indirect jmp */ - PROC_ICALL =0x00000400, /* Proc incomplete due to indirect call */ - PROC_HLL =0x00001000, /* Proc is likely to be from a HLL */ - CALL_PASCAL =0x00002000, /* Proc uses Pascal calling convention */ - CALL_C =0x00004000, /* Proc uses C calling convention */ - CALL_UNKNOWN=0x00008000, /* Proc uses unknown calling convention */ - PROC_NEAR =0x00010000, /* Proc exits with near return */ - PROC_FAR =0x00020000, /* Proc exits with far return */ - GRAPH_IRRED =0x00100000, /* Proc generates an irreducible graph */ - SI_REGVAR =0x00200000, /* SI is used as a stack variable */ - DI_REGVAR =0x00400000, /* DI is used as a stack variable */ - PROC_IS_FUNC=0x00800000, /* Proc is a function */ - REG_ARGS =0x01000000, /* Proc has registers as arguments */ - PROC_VARARG =0x02000000, /* Proc has variable arguments */ - PROC_OUTPUT =0x04000000, /* C for this proc has been output */ - PROC_RUNTIME=0x08000000, /* 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 */ -}; - -struct FunctionType -{ - bool m_vararg; - bool isVarArg() const {return m_vararg;} -}; -struct Assignment -{ - COND_EXPR *lhs; - COND_EXPR *rhs; -}; -struct JumpTable -{ - uint32_t start; - uint32_t finish; - bool valid() {return start -{ - typedef llvm::iplist BasicBlockListType; - // BasicBlock iterators... - typedef BasicBlockListType::iterator iterator; - typedef BasicBlockListType::const_iterator const_iterator; -private: - BasicBlockListType BasicBlocks; ///< The basic blocks - -public: - uint32_t procEntry; /* label number */ - std::string name; /* Meaningful name for this proc */ - STATE state; /* Entry state */ - int depth; /* Depth at which we found it - for printing */ - uint32_t flg; /* Combination of Icode & Proc flags */ - int16_t 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::list m_cfg; /* Ptr. to BB list/CFG */ - std::vector m_dfsLast; - std::list heldBBs; - //BB * *dfsLast; /* Array of pointers to BBs in dfsLast -// * (reverse postorder) order */ - size_t numBBs; /* Number of BBs in the graph cfg */ - bool hasCase; /* Procedure has a case node */ - - /* For interprocedural live analysis */ - std::bitset<32> liveIn; /* Registers used before defined */ - std::bitset<32> liveOut; /* Registers that may be used in successors */ - bool liveAnal; /* Procedure has been analysed already */ - - Function(void *ty=0) : procEntry(0),depth(0),flg(0),cbParam(0),m_cfg(0),m_dfsLast(0),numBBs(0), - hasCase(false),liveIn(0),liveOut(0),liveAnal(0)//,next(0),prev(0) - { - } -public: - static Function *Create(void *ty=0,int Linkage=0,const std::string &nm="",void *module=0) - { - Function *r=new Function(ty); - r->name = nm; - return r; - } - bool anyFlagsSet(uint32_t t) { return (flg&t)!=0;} - bool hasRegArgs() const { return (flg & REG_ARGS)!=0;} - bool isLibrary() const { return (flg & PROC_ISLIB)!=0;} - void compoundCond(); - void writeProcComments(); - void lowLevelAnalysis(); - void bindIcodeOff(); - void dataFlow(std::bitset<32> &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); - bool process_JMP(ICODE &pIcode, STATE *pstate, CALL_GRAPH *pcallGraph); - boolT process_CALL(ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate); - void freeCFG(); - void codeGen(std::ostream &fs); - void mergeFallThrough(BB *pBB); - void structIfs(); - void structLoops(derSeq *derivedG); - void buildCFG(Disassembler &ds); - void controlFlowAnalysis(); - void newRegArg(iICODE picode, iICODE ticode); - void writeProcComments(std::ostream &ostr); - - void displayCFG(); - void displayStats(); - void processHliCall(COND_EXPR *exp, iICODE picode); - - void preprocessReturnDU(std::bitset<32> &_liveOut); -protected: - void extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table); - bool followAllTableEntries(JumpTable &table, uint32_t cs, ICODE &pIcode, CALL_GRAPH *pcallGraph, STATE *pstate); - bool removeInEdge_Flag_and_ProcessLatch(BB *pbb, BB *a, BB *b); - bool Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB); - bool Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB); - bool Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB); - bool Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB); - void replaceInEdge(BB* where, BB* which, BB* with); - void processExpPush(int &numHlIcodes, iICODE picode); - - // TODO: replace those with friend visitor ? - void propLongReg(int loc_ident_idx, const ID &pLocId); - void propLongStk(int i, const ID &pLocId); - void propLongGlb(int i, const ID &pLocId); - void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong); - - int findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE iter); - int findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE beg); - void structCases(); - void findExps(); - void genDU1(); - void elimCondCodes(); - void liveRegAnalysis(std::bitset<32> &in_liveOut); - void findIdioms(); - void propLong(); - void genLiveKtes(); - uint8_t findDerivedSeq (derSeq &derivedGi); - bool nextOrderGraph(derSeq &derivedGi); -}; diff --git a/include/StackFrame.h b/include/StackFrame.h deleted file mode 100644 index 6d45b61..0000000 --- a/include/StackFrame.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include -#include -#include "types.h" -#include "Enums.h" -#include "symtab.h" - -struct STKFRAME : public SymbolTableCommon -{ - //std::vector sym; - //STKSYM * sym; /* Symbols */ - int16_t m_minOff; /* Initial offset in stack frame*/ - int16_t 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() : m_minOff(0),maxOff(0),cb(0),numArgs(0) - { - - } - size_t getLocVar(int off); -public: - void updateFrameOff(int16_t off, int size, uint16_t duFlag); -}; diff --git a/include/ast.h b/include/ast.h index 16faab5..a9ac630 100644 --- a/include/ast.h +++ b/include/ast.h @@ -4,12 +4,9 @@ * Date: September 1993 * (C) Cristina Cifuentes */ -#pragma once -#include -#include -#include "Enums.h" -#include -static const int operandSize=20; + +#define operandSize 20 + /* The following definitions and types define the Conditional Expression * attributed syntax tree, as defined by the following EBNF: CondExp ::= CondTerm AND CondTerm | CondTerm @@ -18,160 +15,123 @@ static const int operandSize=20; 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}; -struct Function; -struct STKFRAME; -struct LOCAL_ID; -struct ICODE; -struct LLInst; -struct ID; -typedef std::list::iterator iICODE; -typedef boost::iterator_range rICODE; -#include "IdentType.h" +/* Conditional Expression enumeration nodes and operators */ +typedef enum { + 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) */ +} condNodeType; + +typedef enum { + 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 */ +} condId; + +typedef enum { + /* 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, /* */ +} condOp; + +/* High-level BOOLEAN conditions for iJB..iJNS icodes */ +static condOp condOpJCond[12] = {LESS, LESS_EQUAL, GREATER_EQUAL, GREATER, + EQUAL, NOT_EQUAL, LESS, GREATER_EQUAL, + LESS_EQUAL, GREATER, GREATER_EQUAL, LESS}; + +static condOp invCondOpJCond[12] = {GREATER_EQUAL, GREATER, LESS, LESS_EQUAL, + NOT_EQUAL, EQUAL, GREATER_EQUAL, LESS, + GREATER, LESS_EQUAL, LESS, GREATER_EQUAL}; + + +/* Register types */ +typedef enum { + BYTE_REG, WORD_REG +} regType; + + +typedef struct +{ + 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 */ + struct _proc *proc; + struct _STKFRAME *args; + } call; + struct { /* for OTHER; tmp struct */ + byte seg; /* segment */ + byte regi; /* index mode */ + int16 off; /* offset */ + } other; + } idNode; +} IDENTTYPE; + /* Expression data type */ -struct COND_EXPR -{ -protected: - struct /* for BOOLEAN_OP */ - { - condOp op; - COND_EXPR *lhs; - COND_EXPR *rhs; - } boolExpr; - -public: - condNodeType m_type; /* Conditional Expression Node Type */ +typedef struct _condExpr { + condNodeType type; /* Conditional Expression Node Type */ union _exprNode { /* Different cond expr nodes */ - COND_EXPR *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/ - IDENTTYPE ident; /* for IDENTIFIER */ - } expr; - COND_EXPR *lhs() - { - assert(m_type==BOOLEAN_OP); - return boolExpr.lhs; - } - const COND_EXPR *lhs() const - { - assert(m_type==BOOLEAN_OP); - return boolExpr.lhs; - } - COND_EXPR *rhs() - { - assert(m_type==BOOLEAN_OP); - return boolExpr.rhs; - } - const COND_EXPR *rhs() const - { - assert(m_type==BOOLEAN_OP); - return boolExpr.rhs; - } - condOp op() const { return boolExpr.op;} -public: - static COND_EXPR *idRegIdx(int idx, regType reg_type); - static COND_EXPR *idKte(uint32_t kte, uint8_t size); - static COND_EXPR *idLoc(int off, LOCAL_ID *localId); - static COND_EXPR *idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym); - static COND_EXPR *idLongIdx(int idx); - static COND_EXPR *idOther(eReg seg, eReg regi, int16_t 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, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset); - static COND_EXPR *idFunc(Function *pproc, STKFRAME *args); - static COND_EXPR *idID(const ID *retVal, LOCAL_ID *locsym, iICODE ix_); - static COND_EXPR * id(const LLInst &ll_insn, opLoc sd, Function *pProc, iICODE ix_, ICODE &duIcode, operDu du); - static COND_EXPR *boolOp(COND_EXPR *_lhs, COND_EXPR *_rhs, condOp _op); - static bool insertSubTreeLongReg(COND_EXPR *exp, COND_EXPR **tree, int longIdx); - static bool insertSubTreeReg(COND_EXPR *&tree, COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym); -public: - virtual COND_EXPR *clone() const; - void release(); - void changeBoolOp(condOp newOp); - COND_EXPR(const COND_EXPR &other) - { - m_type=other.m_type; - expr=other.expr; - boolExpr=other.boolExpr; - } - COND_EXPR(condNodeType t=UNKNOWN_OP) : m_type(t) - { - memset(&expr,0,sizeof(_exprNode)); - memset(&boolExpr,0,sizeof(boolExpr)); + struct { /* for BOOLEAN_OP */ + condOp op; + struct _condExpr *lhs; + struct _condExpr *rhs; + } boolExpr; + struct _condExpr *unaryExp; /* for NEGATION,ADDRESSOF,DEREFERENCE*/ + IDENTTYPE ident; /* for IDENTIFIER */ + } expr; +} COND_EXPR; - } - virtual ~COND_EXPR() {} -public: - virtual COND_EXPR *inverse() const; // return new COND_EXPR that is invarse of this - virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locId); - virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, const LOCAL_ID *locsym); - virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx); - virtual hlType expType(Function *pproc) const; -}; -struct BinaryOperator : public COND_EXPR -{ - condOp m_op; - COND_EXPR *m_lhs; - COND_EXPR *m_rhs; - BinaryOperator(condOp o) - { - m_op = o; - m_lhs=m_rhs=nullptr; - } - static BinaryOperator *Create(condOp o,COND_EXPR *l,COND_EXPR *r); - static BinaryOperator *CreateAdd(COND_EXPR *l,COND_EXPR *r); - virtual COND_EXPR *inverse(); - virtual COND_EXPR *clone(); - virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs); - virtual COND_EXPR *insertSubTreeReg(COND_EXPR *_expr, eReg regi, LOCAL_ID *locsym); - virtual COND_EXPR *insertSubTreeLongReg(COND_EXPR *_expr, int longIdx); +/* Sequence of conditional expression data type */ +/*** NOTE: not used at present ****/ +typedef struct _condExpSeq { + COND_EXPR *expr; + struct _condExpSeq *next; +} SEQ_COND_EXPR; - COND_EXPR *lhs() - { - assert(m_type==BOOLEAN_OP); - return m_lhs; - } - const COND_EXPR *lhs() const - { - assert(m_type==BOOLEAN_OP); - return m_lhs; - } - COND_EXPR *rhs() - { - assert(m_type==BOOLEAN_OP); - return m_rhs; - } - const COND_EXPR *rhs() const - { - assert(m_type==BOOLEAN_OP); - return m_rhs; - } - condOp op() const { return m_op;} - /* Changes the boolean conditional operator at the root of this expression */ - void op(condOp o) { m_op=o;} -}; -struct UnaryOperator : public COND_EXPR -{ - condOp op; - COND_EXPR *unaryExp; - virtual COND_EXPR *inverse(); - virtual COND_EXPR *clone(); - virtual bool xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs); - static UnaryOperator *Create(condNodeType t, COND_EXPR *sub_expr) - { - UnaryOperator *newExp = new UnaryOperator(); - newExp->m_type=t; - newExp->unaryExp = sub_expr; - return (newExp); - } -}; -struct GlobalVariable : public COND_EXPR -{ - static COND_EXPR *Create(int16_t segValue, int16_t off); -}; -struct Constant : public COND_EXPR -{}; diff --git a/include/bundle.h b/include/bundle.h index fd09809..d6984b9 100644 --- a/include/bundle.h +++ b/include/bundle.h @@ -4,39 +4,28 @@ * Purpose: Module to handle the bundle type (array of pointers to strings). * (C) Cristina Cifuentes ****************************************************************************/ -#pragma once -#include -#include -#include -struct strTable : std::vector -{ - /* Returns the next available index into the table */ - size_t nextIdx() {return size();} -public: - void addLabelBundle(int idx, int label); -}; -struct bundle -{ -public: - void appendCode(const char *format, ...); - void appendCode(const std::string &s); - void appendDecl(const char *format, ...); - void appendDecl(const std::string &); - void init() - { - decl.clear(); - code.clear(); - } +#include + +typedef struct { + Int numLines; /* Number of lines in the table */ + Int allocLines; /* Number of lines allocated in the table */ + char **str; /* Table of strings */ +} strTable; + + +typedef struct { strTable decl; /* Declarations */ strTable code; /* C code */ - int current_indent; -}; +} bundle; #define lineSize 360 /* 3 lines in the mean time */ -//void newBundle (bundle *procCode); -void writeBundle (std::ostream &ios, bundle procCode); +void newBundle (bundle *procCode); +void appendStrTab (strTable *strTab, char *format, ...); +Int nextBundleIdx (strTable *strTab); +void addLabelBundle (strTable *strTab, Int idx, Int label); +void writeBundle (FILE *fp, bundle procCode); void freeBundle (bundle *procCode); diff --git a/include/dcc.h b/include/dcc.h index 2044df2..0221174 100644 --- a/include/dcc.h +++ b/include/dcc.h @@ -2,15 +2,8 @@ * dcc project general header * (C) Cristina Cifuentes, Mike van Emmerik ****************************************************************************/ -#pragma once -//TODO: Remove boolT -#include -#include -#include -#include -#include "Enums.h" #include "types.h" #include "ast.h" #include "icode.h" @@ -18,31 +11,134 @@ #include "error.h" #include "graph.h" #include "bundle.h" -#include "Procedure.h" -#include "BasicBlock.h" -struct Project; + + +/* SYMBOL TABLE */ +typedef struct { + 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 */ + word duVal; /* DEF, USE, VAL */ +} SYM; +typedef SYM *PSYM; + +typedef struct { + Int csym; /* No. of symbols in table */ + Int alloc; /* Allocation */ + PSYM sym; /* Symbols */ +} SYMTAB; +typedef SYMTAB *PSYMTAB; + + +/* STACK FRAME */ +typedef struct { + 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 */ + word 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; +typedef STKSYM *PSTKSYM; + +typedef struct _STKFRAME { + Int csym; /* No. of symbols in table */ + Int alloc; /* Allocation */ + PSTKSYM 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*/ +} STKFRAME; +typedef STKFRAME *PSTKFRAME; + +/* PROCEDURE NODE */ +typedef struct _proc { + 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 */ + PBB cfg; /* Ptr. to BB list/CFG */ + PBB *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 */ + struct _proc *next; + struct _proc *prev; +} PROCEDURE; +typedef PROCEDURE *PPROC; + + /* CALL GRAPH NODE */ -struct CALL_GRAPH -{ - ilFunction proc; /* Pointer to procedure in pProcList */ - std::vector outEdges; /* array of out edges */ -public: - void write(); - CALL_GRAPH() : outEdges(0) - { - } -public: - void writeNodeCallGraph(int indIdx); - bool insertCallGraph(ilFunction caller, ilFunction callee); - bool insertCallGraph(Function *caller, ilFunction callee); - void insertArc(ilFunction newProc); -}; -//#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */ -//extern std::list pProcList; -//extern FunctionListType pProcList; -//extern CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */ +typedef struct _callGraph { + PPROC proc; /* Pointer to procedure in pProcList */ + Int numOutEdges; /* # of out edges (ie. # procs invoked) */ + Int numAlloc; /* # of out edges allocated */ + struct _callGraph **outEdges; /* array of out edges */ +} CALL_GRAPH; +typedef CALL_GRAPH *PCALL_GRAPH; +#define NUM_PROCS_DELTA 5 /* delta # procs a proc invokes */ + +extern PPROC pProcList; /* Pointer to the head of the procedure list */ +extern PPROC pLastProc; /* Pointer to last node of the proc list */ +extern PCALL_GRAPH callGraph; /* Pointer to the head of the call graph */ extern bundle cCode; /* Output C procedure's declaration and code */ +/* Procedure FLAGS */ +#define PROC_BADINST 0x000100 /* Proc contains invalid or 386 instruction */ +#define PROC_IJMP 0x000200 /* Proc incomplete due to indirect jmp */ +#define PROC_ICALL 0x000400 /* Proc incomplete due to indirect call */ +#define PROC_HLL 0x001000 /* Proc is likely to be from a HLL */ +#define CALL_PASCAL 0x002000 /* Proc uses Pascal calling convention */ +#define CALL_C 0x004000 /* Proc uses C calling convention */ +#define CALL_UNKNOWN 0x008000 /* Proc uses unknown calling convention */ +#define PROC_NEAR 0x010000 /* Proc exits with near return */ +#define PROC_FAR 0x020000 /* Proc exits with far return */ +#define GRAPH_IRRED 0x100000 /* Proc generates an irreducible graph */ +#define SI_REGVAR 0x200000 /* SI is used as a stack variable */ +#define DI_REGVAR 0x400000 /* DI is used as a stack variable */ +#define PROC_IS_FUNC 0x800000 /* Proc is a function */ +#define REG_ARGS 0x1000000 /* Proc has registers as arguments */ +#define PROC_VARARG 0x2000000 /* Proc has variable arguments */ +#define PROC_OUTPUT 0x4000000 /* C for this proc has been output */ +#define PROC_RUNTIME 0x8000000 /* Proc is part of the runtime support */ +#define PROC_ISLIB 0x10000000 /* Proc is a library function */ +#define PROC_ASM 0x20000000 /* Proc is an intrinsic assembler routine */ +#define PROC_IS_HLL 0x40000000 /* Proc has HLL prolog code */ +#define CALL_MASK 0xFFFF9FFF /* Masks off CALL_C and CALL_PASCAL */ + +/* duVal FLAGS */ +#define DEF 0x0010 /* Variable was first defined than used */ +#define USE 0x0100 /* Variable was first used than defined */ +#define VAL 0x1000 /* 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. */ +#define USEVAL 0x1100 /* Use and Val */ + + /**** Global variables ****/ extern char *asm1_name, *asm2_name; /* Assembler output filenames */ @@ -55,95 +151,174 @@ typedef struct { /* Command line option flags */ unsigned Map : 1; unsigned Stats : 1; unsigned Interact : 1; /* Interactive mode */ - unsigned Calls : 1; /* Follow register indirect calls */ - char filename[80]; /* The input filename */ + 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 */ -#include "BinaryImage.h" -extern std::bitset<32> duReg[30]; /* def/use bits for registers */ +typedef struct { /* 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 */ +} PROG; -//extern uint32_t duReg[30]; /* def/use bits for registers */ -extern std::bitset<32> maskDuReg[30]; /* masks off du bits for regs */ +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 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 */ -enum eAreaType -{ - BM_UNKNOWN = 0, /* Unscanned memory */ - BM_DATA = 1, /* Data */ - BM_CODE = 2, /* Code */ - BM_IMPURE = 3 /* Used as Data and Code*/ -}; +#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 */ -}; +typedef struct { + 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 */ +} STATS; extern STATS stats; /* Icode statistics */ /**** Global function prototypes ****/ -class DccFrontend -{ - void LoadImage(Project &proj); - void parse(Project &proj); - std::string m_fname; -public: - DccFrontend(const std::string &fname) : m_fname(fname) - { - } - bool FrontEnd(); /* frontend.c */ -}; +void FrontEnd(char *filename, PCALL_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, uint8_t, int, Function *); /* graph.c */ -void BackEnd(char *filename, CALL_GRAPH *); /* backend.c */ -char *cChar(uint8_t c); /* backend.c */ -eErrorId scan(uint32_t ip, ICODE &p); /* scanner.c */ -void parse (CALL_GRAPH * *); /* parser.c */ - -int strSize (uint8_t *, char); /* parser.c */ -//void disassem(int pass, Function * pProc); /* disassem.c */ -void interactDis(Function * initProc, int initIC); /* disassem.c */ -bool JmpInst(llIcode opcode); /* idioms.c */ -queue::iterator appendQueue(queue &Q, BB *node); /* reducible.c */ - +PBB createCFG(PPROC pProc); /* graph.c */ +void compressCFG(PPROC pProc); /* graph.c */ +void freeCFG(PBB cfg); /* graph.c */ +PBB newBB(PBB, Int, Int, byte, Int, PPROC); /* graph.c */ +void BackEnd(char *filename, PCALL_GRAPH); /* backend.c */ +char *cChar(byte c); /* backend.c */ +Int scan(dword ip, PICODE p); /* scanner.c */ +void parse (PCALL_GRAPH *); /* parser.c */ +boolT labelSrch(PICODE pIc, Int n, dword tg, Int *pIdx); /* parser.c */ +void setState(PSTATE state, word reg, int16 value); /* parser.c */ +Int strSize (byte *, char); /* parser.c */ +void disassem(Int pass, PPROC pProc); /* disassem.c */ +void interactDis(PPROC initProc, Int initIC); /* disassem.c */ +void bindIcodeOff (PPROC); /* idioms.c */ +void lowLevelAnalysis (PPROC pProc); /* idioms.c */ +void propLong (PPROC pproc); /* proplong.c */ +boolT JmpInst(llIcode opcode); /* idioms.c */ +void checkReducibility(PPROC pProc, derSeq **derG); /* reducible.c */ +queue *appendQueue(queue **Q, BB *node); /* reducible.c */ +void freeDerivedSeq(derSeq *derivedG); /* reducible.c */ +void displayDerivedSeq(derSeq *derG); /* reducible.c */ +void structure(PPROC pProc, derSeq *derG); /* control.c */ +void compoundCond (PPROC); /* control.c */ +void dataFlow(PPROC pProc, dword liveOut); /* dataflow.c */ +void writeIntComment (PICODE icode, char *s); /* comwrite.c */ +void writeProcComments (PPROC pProc, strTable *sTab); /* comwrite.c */ +void checkStartup(PSTATE pState); /* chklib.c */ void SetupLibCheck(void); /* chklib.c */ void CleanupLibCheck(void); /* chklib.c */ -bool LibCheck(Function &p); /* chklib.c */ +boolT LibCheck(PPROC p); /* chklib.c */ /* Exported functions from procs.c */ -boolT insertCallGraph (CALL_GRAPH *, ilFunction, ilFunction); -void adjustActArgType (COND_EXPR *, hlType, Function *); +boolT insertCallGraph (PCALL_GRAPH, PPROC, PPROC); +void writeCallGraph (PCALL_GRAPH); +void newRegArg (PPROC, PICODE, PICODE); +boolT newStkArg (PICODE, COND_EXPR *, llIcode, PPROC); +void allocStkArgs (PICODE, Int); +void placeStkArg (PICODE, COND_EXPR *, Int); +void adjustActArgType (COND_EXPR *, hlType, PPROC); +void adjustForArgType (PSTKFRAME, Int, hlType); /* Exported functions from ast.c */ -std::string walkCondExpr (const COND_EXPR *exp, Function * pProc, int *); -int hlTypeSize (const COND_EXPR *, Function *); -//hlType expType (const COND_EXPR *, Function *); - +COND_EXPR *boolCondExp (COND_EXPR *lhs, COND_EXPR *rhs, condOp op); +COND_EXPR *unaryCondExp (condNodeType, COND_EXPR *exp); +COND_EXPR *idCondExpGlob (int16 segValue, int16 off); +COND_EXPR *idCondExpReg (byte regi, flags32 flg, LOCAL_ID *); +COND_EXPR *idCondExpRegIdx (Int idx, regType); +COND_EXPR *idCondExpLoc (Int off, LOCAL_ID *); +COND_EXPR *idCondExpParam (Int off, PSTKFRAME argSymtab); +COND_EXPR *idCondExpKte (dword kte, byte); +COND_EXPR *idCondExpLong (LOCAL_ID *, opLoc, PICODE, hlFirst, Int idx, operDu, + Int); +COND_EXPR *idCondExpLongIdx (Int); +COND_EXPR *idCondExpFunc (PPROC, PSTKFRAME); +COND_EXPR *idCondExpOther (byte seg, byte regi, int16 off); +COND_EXPR *idCondExpID (ID *, LOCAL_ID *, Int); +COND_EXPR *idCondExp (PICODE, opLoc, PPROC, Int i, PICODE duIcode, operDu); +COND_EXPR *copyCondExp (COND_EXPR *); +void removeRegFromLong (byte, LOCAL_ID *, COND_EXPR *); +char *walkCondExpr (COND_EXPR *exp, PPROC pProc, Int *); +condId idType (PICODE pIcode, opLoc sd); +Int hlTypeSize (COND_EXPR *, PPROC); +hlType expType (COND_EXPR *, PPROC); +void setRegDU (PICODE, byte regi, operDu); +void copyDU (PICODE, PICODE, operDu, operDu); +void changeBoolCondExpOp (COND_EXPR *, condOp); +boolT insertSubTreeReg (COND_EXPR *, COND_EXPR **, byte, LOCAL_ID *); +boolT insertSubTreeLongReg (COND_EXPR *, COND_EXPR **, Int); +void freeCondExpr (COND_EXPR *exp); +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 */ -std::string writeCall (Function *, STKFRAME &, Function *, int *); -char *writeJcond (const HLTYPE &, Function *, int *); -char *writeJcondInv (HLTYPE, Function *, int *); +void newAsgnHlIcode (PICODE, COND_EXPR *, COND_EXPR *); +void newCallHlIcode (PICODE); +void newUnaryHlIcode (PICODE, hlIcode, COND_EXPR *); +void newJCondHlIcode (PICODE, COND_EXPR *); +void invalidateIcode (PICODE); +boolT removeDefRegi (byte, PICODE, Int, LOCAL_ID *); +void highLevelGen (PPROC); +char *writeCall (PPROC, PSTKFRAME, PPROC, Int *); +char *write1HlIcode (HLTYPE, PPROC, Int *); +char *writeJcond (HLTYPE, PPROC, Int *); +char *writeJcondInv (HLTYPE, PPROC, Int *); +Int power2 (Int); +void writeDU (PICODE, Int); +void inverseCondOp (COND_EXPR **); + +/* Exported funcions from locident.c */ +Int newByteWordRegId (LOCAL_ID *, hlType t, byte regi); +Int newByteWordStkId (LOCAL_ID *, hlType t, Int off, byte regOff); +Int newIntIdxId (LOCAL_ID *, int16 seg, int16 off, byte regi, Int, hlType); +Int newLongRegId (LOCAL_ID *, hlType t, byte regH, byte regL, Int idx); +Int newLongStkId (LOCAL_ID *, hlType t, Int offH, Int offL); +Int newLongId (LOCAL_ID *, opLoc sd, PICODE, hlFirst, Int idx, operDu, Int); +boolT checkLongEq (LONG_STKID_TYPE, PICODE, Int, Int, PPROC, COND_EXPR **, + COND_EXPR **, Int); +boolT checkLongRegEq (LONGID_TYPE, PICODE, Int, Int, PPROC, COND_EXPR **, + COND_EXPR **, Int); +byte otherLongRegi (byte, Int, LOCAL_ID *); +void insertIdx (IDX_ARRAY *, Int); +void propLongId (LOCAL_ID *, byte, byte, char *); -/* Exported funcions from locident.c */ -boolT checkLongEq (LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset); -boolT checkLongRegEq (LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &); -eReg otherLongRegi(eReg, int, LOCAL_ID *); - - -extern const char *indentStr(int level); diff --git a/include/disassem.h b/include/disassem.h index 5bcc7bc..3789bf6 100644 --- a/include/disassem.h +++ b/include/disassem.h @@ -2,32 +2,7 @@ * dcc project disassembler header * (C) Mike van Emmerik ****************************************************************************/ -#pragma once -#include -#include -#include -#include "bundle.h" -struct LLInst; -struct Disassembler -{ -protected: - int pass; - int g_lab; - //bundle &cCode; - std::ofstream m_fp; - std::vector m_decls; - std::vector m_code; -public: - Disassembler(int _p) : pass(_p) - { - g_lab=0; - } -public: - void disassem(Function *ppProc); - void disassem(Function *ppProc, int i); - void dis1Line(LLInst &inst, int loc_ip, int pass); -}; /* Definitions for extended keys (first key is zero) */ #define EXT 0x100 /* "Extended" flag */ @@ -44,10 +19,10 @@ public: #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 +#define KEY_UP 0x48 +#define KEY_RIGHT 0x4D +#define KEY_NPAGE 0x51 +#define KEY_PPAGE 0x49 #endif #ifdef __UNIX__ diff --git a/include/dosdcc.h b/include/dosdcc.h index f177938..f6ae3e7 100644 --- a/include/dosdcc.h +++ b/include/dosdcc.h @@ -5,34 +5,34 @@ **************************************************************************/ /* Type definitions for intel 80x86 architecture */ -typedef unsigned int uint16_t; /* 16 bits */ -typedef unsigned char uint8_t; /* 8 bits */ +typedef unsigned int Word; /* 16 bits */ +typedef unsigned char Byte; /* 8 bits */ typedef union { unsigned long dW; - uint16_t wL, wH; /* 2 words */ + Word wL, wH; /* 2 words */ } Dword; /* 32 bits */ -/* Structure to access high and low bits of a uint8_t or uint16_t variable */ +/* Structure to access high and low bits of a Byte or Word variable */ typedef struct { - /* low uint8_t */ - uint16_t lowBitWord : 1; - uint16_t filler1 : 6; - uint16_t highBitByte : 1; - /* high uint8_t */ - uint16_t lowBitByte : 1; - uint16_t filler2 : 6; - uint16_t highBitWord : 1; + /* 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 uint8_t or uint16_t variable */ +/* 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(uint16_t) ? \ +#define highBit(a) (sizeof(a) == sizeof(Word) ? \ ((wordBits)(a).highBitWord):\ ((wordBits)(a).highBitByte)) -/* uint16_t register variables */ +/* Word register variables */ #define ax regs.x.ax #define bx regs.x.bx #define cx regs.x.cx @@ -52,7 +52,7 @@ typedef struct { #define carry regs.x.cflags #define overF regs.x.flags /***** check *****/ -/* uint8_t register variables */ +/* Byte register variables */ #define ah regs.h.ah #define al regs.h.al #define bh regs.h.bh @@ -64,8 +64,8 @@ typedef struct { /* High and low words of a Dword */ -#define highWord(w) (*((uint16_t*)&(w) + 1)) -#define lowWord(w) ((uint16_t)(w)) +#define highWord(w) (*((Word*)&(w) + 1)) +#define lowWord(w) ((Word)(w)) #define MAXByte 0xFF #define MAXWord 0xFFFF @@ -74,4 +74,7 @@ typedef struct { #define MAXSignWord 0x7FFF #define MINSignWord 0x8001 +/* Booleans */ +#define TRUE 1 +#define FALSE 0 diff --git a/include/error.h b/include/error.h index 9ffeb98..addb994 100644 --- a/include/error.h +++ b/include/error.h @@ -2,35 +2,32 @@ * Error codes * (C) Cristina Cifuentes ****************************************************************************/ -#pragma once + /* These definitions refer to errorMessage in error.c */ -enum eErrorId -{ - NO_ERR =0, - USAGE, - INVALID_ARG, - INVALID_OPCODE, - INVALID_386OP, - FUNNY_SEGOVR, - FUNNY_REP, - CANNOT_OPEN, - CANNOT_READ, - MALLOC_FAILED, - NEWEXE_FORMAT, - NO_BB, - INVALID_SYNTHETIC_BB, - INVALID_INT_BB, - IP_OUT_OF_RANGE, - DEF_NOT_FOUND, - JX_NOT_DEF, - NOT_DEF_USE, - REPEAT_FAIL, - WHILE_FAIL -}; +#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(eErrorId errId, ...); -void reportError(eErrorId errId, ...); +void fatalError(Int errId, ...); +void reportError(Int errId, ...); diff --git a/include/graph.h b/include/graph.h index 714b0ed..1c6cb0c 100644 --- a/include/graph.h +++ b/include/graph.h @@ -2,49 +2,37 @@ * CFG, BB and interval related definitions * (C) Cristina Cifuentes ****************************************************************************/ -#pragma once -#include -#include -struct Function; + + /* 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 */ +#define ONE_BRANCH 0 /* unconditional branch */ +#define TWO_BRANCH 1 /* conditional branch */ +#define MULTI_BRANCH 2 /* case branch */ +#define FALL_NODE 3 /* fall through */ +#define RETURN_NODE 4 /* procedure/program return */ +#define CALL_NODE 5 /* procedure call */ +#define LOOP_NODE 6 /* loop instruction */ +#define REP_NODE 7 /* repeat instruction */ +#define INTERVAL_NODE 8 /* contains interval list */ - TERMINATE_NODE=11, /* Exit to DOS */ - NOWHERE_NODE=12 /* No outedges going anywhere */ -}; +#define TERMINATE_NODE 11 /* Exit to DOS */ +#define NOWHERE_NODE 12 /* No outedges going anywhere */ /* Depth-first traversal constants */ -enum eDFS -{ - DFS_NONE, - 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 */ -}; +#define DFS_DISP 1 /* Display graph pass */ +#define DFS_MERGE 2 /* Merge nodes pass */ +#define DFS_NUM 3 /* DFS numbering pass */ +#define DFS_CASE 4 /* Case pass */ +#define DFS_ALPHA 5 /* Alpha code generation*/ +#define 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 */ -}; +#define NO_TYPE 0 /* node is not a loop header*/ +#define WHILE_TYPE 1 /* node is a while header */ +#define REPEAT_TYPE 2 /* node is a repeat header */ +#define ENDLESS_TYPE 3 /* endless loop header */ /* Uninitialized values for certain fields */ #define NO_NODE MAX /* node has no associated node */ @@ -55,47 +43,90 @@ enum eNodeHeaderType #define ELSE 1 /* else edge */ /* Basic Block (BB) flags */ -#define INVALID_BB 0x0001 /* BB is not valid any more */ +#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 queue; -struct interval +/* Interval structure */ +typedef struct _queueNode { + struct _BB *node; /* Ptr to basic block */ + struct _queueNode *next; +} queue; + +typedef struct _intNode { + byte numInt; /* # of the interval */ + byte numOutEdges; /* Number of out edges */ + queue *nodes; /* Nodes of the interval*/ + queue *currNode; /* Current node */ + struct _intNode *next; /* Next interval */ +} interval; + +typedef union { - uint8_t numInt; /* # of the interval */ - uint8_t 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; - } -}; + dword ip; /* Out edge icode address */ + struct _BB *BBptr; /* Out edge pointer to next BB */ + interval *intPtr; /* Out edge ptr to next interval*/ +} TYPEADR_TYPE; + +/* Basic block (BB) node definition */ +typedef struct _BB { + 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 */ + struct _BB **inEdges; /* Array of ptrs. to in edges */ + + Int numOutEdges; /* Number of out edges */ + 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) */ + struct _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 + * this 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 */ + struct _BB *next; /* Next (list link) */ +} BB; +typedef BB *PBB; /* 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(Function *c); -}; -class derSeq : public std::list -{ -public: - void display(); -}; -void freeDerivedSeq(derSeq &derivedG); /* reducible.c */ +typedef struct _derivedNode { + BB *Gi; /* Graph pointer */ + interval *Ii; /* Interval list of Gi */ + struct _derivedNode *next; /* Next derived graph */ +} derSeq; diff --git a/include/hlicode.h b/include/hlicode.h index c02b921..1c672ab 100644 --- a/include/hlicode.h +++ b/include/hlicode.h @@ -1,4 +1,4 @@ -/* +/* * File: hlIcode.h * Purpose: module definitions for high-level icodes * Date: September 1993 @@ -6,8 +6,16 @@ /* High level icodes opcodes - def in file icode.h */ -struct HLICODE -{ +/*typedef enum { + HLI_ASSIGN, + INC, + DEC, + HLI_JCOND, + +} hlIcode; */ + + +typedef struct { hlIcode opcode; /* hlIcode opcode */ union { /* different operands */ struct { @@ -17,4 +25,12 @@ struct 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; + diff --git a/include/icode.h b/include/icode.h index 0452acc..3290179 100644 --- a/include/icode.h +++ b/include/icode.h @@ -2,489 +2,367 @@ * I-code related definitions * (C) Cristina Cifuentes ****************************************************************************/ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "libdis.h" -#include "Enums.h" + + +/* LOW_LEVEL icode flags */ +#define B 0x000001 /* Byte operands (value implicitly used) */ +#define I 0x000002 /* Immed. source */ +#define NOT_HLL 0x000004 /* Not HLL inst. */ +#define FLOAT_OP 0x000008 /* ESC or WAIT */ + +#define SEG_IMMED 0x000010 /* Number is relocated segment value */ +#define IMPURE 0x000020 /* Instruction modifies code */ +#define WORD_OFF 0x000040 /* Inst has word offset ie.could be address */ +#define TERMINATES 0x000080 /* Instruction terminates program */ + +#define CASE 0x000100 /* Label as case part of switch */ +#define SWITCH 0x000200 /* Treat indirect JMP as switch stmt */ +#define TARGET 0x000400 /* Jump target */ +#define SYNTHETIC 0x000800 /* Synthetic jump instruction */ +#define NO_LABEL 0x001000 /* Immed. jump cannot be linked to a label */ +#define NO_CODE 0x002000 /* Hole in Icode array */ +#define SYM_USE 0x004000 /* Instruction uses a symbol */ +#define SYM_DEF 0x008000 /* Instruction defines a symbol */ + +#define NO_SRC 0x010000 /* Opcode takes no source */ +#define NO_OPS 0x020000 /* Opcode takes no operands */ +#define IM_OPS 0x040000 /* Opcode takes implicit operands */ +#define SRC_B 0x080000 /* Source operand is byte (dest is word) */ +#define NO_SRC_B 0xF7FFFF /* Masks off SRC_B */ +#define HLL_LABEL 0x100000 /* Icode has a high level language label */ +#define IM_DST 0x200000 /* Implicit DST for opcode (SIGNEX) */ +#define IM_SRC 0x400000 /* Implicit SRC for opcode (dx:ax) */ +#define IM_TMP_DST 0x800000 /* Implicit rTMP DST for opcode (DIV/IDIV) */ + +#define JMP_ICODE 0x1000000 /* Jmp dest immed.op converted to icode index */ +#define JX_LOOP 0x2000000 /* Cond jump is part of loop conditional exp */ +#define 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 char *byteReg[9] = {"al", "cl", "dl", "bl", + "ah", "ch", "dh", "bh", "tmp" }; +static char *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 -//enum condId; +/* Types of icodes */ +typedef enum { + NOT_SCANNED = 0, /* not even scanned yet */ + LOW_LEVEL, /* low-level icode */ + HIGH_LEVEL /* high-level icode */ +} icodeType; -struct LOCAL_ID; -struct BB; -struct Function; -struct STKFRAME; -struct CIcodeRec; -struct ICODE; -struct bundle; -typedef std::list::iterator iICODE; -typedef std::list::reverse_iterator riICODE; -typedef boost::iterator_range rCODE; -extern std::bitset<32> duReg[30]; -/* uint8_t and uint16_t registers */ + +/* LOW_LEVEL icode opcodes */ +typedef enum { + 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 */ +} llIcode; + + +/* 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; + + +/* Operand is defined, used or both flag */ +typedef enum { + DEF, /* Operand is defined */ + USE, /* Operand is used */ + USE_DEF, /* Operand is used and defined */ + NONE, /* No operation is required on this operand */ +} operDu; + +// I can't believe these are necessary! +#define E_DEF (operDu)DEF +#define E_USE (operDu)USE +#define E_NONE (operDu)NONE +#define E_USE_DEF (operDu)USE_DEF /* Def/use of flags - low 4 bits represent flags */ -struct DU -{ - uint8_t d; - uint8_t u; -}; +typedef struct { + byte d; + byte u; +} DU; +typedef DU *PDU; + +/* Def/Use of registers and stack variables */ +typedef struct { + 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*/ +}DU_ICODE; + /* Definition-use chain for level 1 (within a basic block) */ -#define MAX_REGS_DEF 4 /* 2 regs def'd for long-reg vars */ +#define MAX_REGS_DEF 2 /* 2 regs def'd for long-reg vars */ +#define MAX_USES 5 + +typedef struct { + 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 */ +} DU1; -struct COND_EXPR; -struct HlTypeSupport -{ - //hlIcode opcode; /* hlIcode opcode */ - virtual bool removeRegFromLong(eReg regi, LOCAL_ID *locId)=0; - virtual std::string writeOut(Function *pProc, int *numLoc)=0; -protected: - void performLongRemoval (eReg regi, LOCAL_ID *locId, COND_EXPR *tree); -}; - -struct CallType : public HlTypeSupport -{ - //for HLI_CALL - Function * proc; - STKFRAME * args; // actual arguments - void allocStkArgs (int num); - bool newStkArg(COND_EXPR *exp, llIcode opcode, Function *pproc); - void placeStkArg(COND_EXPR *exp, int pos); - virtual COND_EXPR * toId(); -public: - bool removeRegFromLong(eReg regi, LOCAL_ID *locId) - { - printf("CallType : removeRegFromLong not supproted"); - return false; - } - std::string writeOut(Function *pProc, int *numLoc); -}; -struct AssignType : public HlTypeSupport -{ - /* for HLI_ASSIGN */ - COND_EXPR *lhs; - COND_EXPR *rhs; - AssignType() : lhs(0),rhs(0) {} - bool removeRegFromLong(eReg regi, LOCAL_ID *locId) - { - performLongRemoval(regi,locId,lhs); - return true; - } - std::string writeOut(Function *pProc, int *numLoc); -}; -struct ExpType : public HlTypeSupport -{ - /* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/ - COND_EXPR *v; - ExpType() : v(0) {} - bool removeRegFromLong(eReg regi, LOCAL_ID *locId) - { - performLongRemoval(regi,locId,v); - return true; - } - std::string writeOut(Function *pProc, int *numLoc); -}; - -struct HLTYPE -{ -protected: -public: - ExpType exp; /* for HLI_JCOND, HLI_RET, HLI_PUSH, HLI_POP*/ - hlIcode opcode; /* hlIcode opcode */ - AssignType asgn; - CallType call; - HlTypeSupport *get() - { - switch(opcode) - { - case HLI_ASSIGN: return &asgn; - case HLI_RET: - case HLI_POP: - case HLI_JCOND: - case HLI_PUSH: return &exp; - case HLI_CALL: return &call; - default: - return 0; - } - } - - void expr(COND_EXPR *e) - { - assert(e); - exp.v=e; - } - void replaceExpr(COND_EXPR *e) - { - assert(e); - delete exp.v; - exp.v=e; - } - COND_EXPR * expr() { return exp.v;} - const COND_EXPR * const expr() const { return exp.v;} - void set(hlIcode i,COND_EXPR *e) - { - if(i!=HLI_RET) - assert(e); - assert(exp.v==0); - opcode=i; - exp.v=e; - } - void set(COND_EXPR *l,COND_EXPR *r) - { - assert(l); - assert(r); - opcode = HLI_ASSIGN; - assert((asgn.lhs==0) and (asgn.rhs==0)); //prevent memory leaks - asgn.lhs=l; - asgn.rhs=r; - } - HLTYPE(hlIcode op=HLI_INVALID) : opcode(op) - {} - HLTYPE & operator=(const HLTYPE &l) - { - exp=l.exp; - opcode=l.opcode; - asgn=l.asgn; - call=l.call; - return *this; - } -public: - std::string write1HlIcode(Function *pProc, int *numLoc); - void setAsgn(COND_EXPR *lhs, COND_EXPR *rhs); -} ; /* LOW_LEVEL icode operand record */ -struct LLOperand +typedef struct { + 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 */ +} ICODEMEM; +typedef ICODEMEM *PMEM; + +/* LOW_LEVEL operand location: source or destination */ +typedef enum { + SRC, /* Source operand */ + DST, /* Destination operand */ + LHS_OP, /* Left-hand side operand (for HIGH_LEVEL) */ +} opLoc; + +typedef struct { - llvm::MCOperand llvm_op; - eReg seg; /* CS, DS, ES, SS */ - eReg segOver; /* CS, DS, ES, SS if segment override */ - int16_t segValue; /* Value of segment seg during analysis */ - eReg regi; /* 0 < regs < INDEXBASE <= index modes */ - int16_t off; /* memory address offset */ - uint32_t opz; /* idx of immed src op */ - //union {/* Source operand if (flg & I) */ - struct { /* Call & # actual arg bytes */ - Function *proc; /* pointer to target proc (for CALL(F))*/ - int cb; /* # actual arg bytes */ - } proc; - LLOperand() : seg(rUNDEF),segValue(0),segOver(rUNDEF),regi(rUNDEF),off(0),opz(0) - { - proc.proc=0; - proc.cb=0; - } - int64_t getImm2() const {return opz;} - void SetImmediateOp(uint32_t dw) - { - opz=dw; - } - eReg getReg2() {return regi;} - bool isReg() const; - static LLOperand CreateImm2(int64_t Val) - { - LLOperand Op; - //Op.Kind = kImmediate; - //Op.ImmVal = Val; - Op.opz = Val; - return Op; - } - static LLOperand CreateReg2(unsigned Val) - { - LLOperand Op; -// Op.Kind = kRegister; -// Op.RegVal = Reg; - Op.regi = (eReg)Val; - return Op; - } - void addProcInformation(int param_count,uint32_t call_conv); -}; -struct LLInst : public llvm::MCInst //: public llvm::ilist_node + 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 */ + struct _proc *proc; + struct _STKFRAME *args; /* actual arguments */ + } call; + } oper; /* operand */ +} HLTYPE; + +typedef struct { -protected: - uint32_t flg; /* icode flags */ - LLOperand m_src; /* source operand */ -public: - int codeIdx; /* Index into cCode.code */ - uint8_t numBytes; /* Number of bytes this instr */ - uint32_t label; /* offset in image (20-bit adr) */ - LLOperand dst; /* destination operand */ - DU flagDU; /* def/use of flags */ - int caseEntry; - std::vector caseTbl2; - int hllLabNum; /* label # for hll codegen */ - bool conditionalJump() - { - return (getOpcode() >= iJB) && (getOpcode() < iJCXZ); - } - bool testFlags(uint32_t x) const { return (flg & x)!=0;} - void setFlags(uint32_t flag) {flg |= flag;} - void clrFlags(uint32_t flag) - { - if(getOpcode()==iMOD) - { - assert(false); - } - flg &= ~flag; - } - uint32_t getFlag() const {return flg;} - //llIcode getOpcode() const { return opcode; } + 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 */ + struct _proc *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; - uint32_t GetLlLabel() const { return label;} - - void SetImmediateOp(uint32_t dw) {m_src.SetImmediateOp(dw);} - - - bool match(llIcode op) - { - return (getOpcode()==op); - } - bool match(llIcode op,eReg dest) - { - return (getOpcode()==op)&&dst.regi==dest; - } - bool match(llIcode op,eReg dest,uint32_t flgs) - { - return (getOpcode()==op) and (dst.regi==dest) and testFlags(flgs); - } - bool match(llIcode op,eReg dest,eReg src_reg) - { - return (getOpcode()==op)&&(dst.regi==dest)&&(m_src.regi==src_reg); - } - bool match(eReg dest,eReg src_reg) - { - return (dst.regi==dest)&&(m_src.regi==src_reg); - } - bool match(eReg dest) - { - return (dst.regi==dest); - } - bool match(llIcode op,uint32_t flgs) - { - return (getOpcode()==op) and testFlags(flgs); - } - void set(llIcode op,uint32_t flags) - { - setOpcode(op); - flg =flags; - } - void emitGotoLabel(int indLevel); - void findJumpTargets(CIcodeRec &_pc); - void writeIntComment(std::ostringstream &s); - void dis1Line(int loc_ip, int pass); - std::ostringstream &strSrc(std::ostringstream &os,bool skip_comma=false); - - void flops(std::ostringstream &out); - bool isJmpInst(); - HLTYPE toHighLevel(COND_EXPR *lhs, COND_EXPR *rhs, Function *func); - HLTYPE createCall(); - LLInst(ICODE *container) : flg(0),codeIdx(0),numBytes(0),m_link(container) - { - setOpcode(0); - } - const LLOperand &src() const {return m_src;} - LLOperand &src() {return m_src;} - void replaceSrc(const LLOperand &with) - { - m_src = with; - } - void replaceSrc(eReg r) - { - m_src = LLOperand::CreateReg2(r); - } - void replaceSrc(int64_t r) - { - m_src = LLOperand::CreateImm2(r); - } - void replaceDst(const LLOperand &with) - { - dst = with; - } - void replaceDst(eReg r) - { - dst = LLOperand::CreateReg2(r); - } - ICODE *m_link; - condId idType(opLoc sd) const; - const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &dst; } - LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &dst; } -}; /* Icode definition: LOW_LEVEL and HIGH_LEVEL */ -struct ICODE -{ - // use llvm names at least - typedef BB MachineBasicBlock; -protected: - LLInst m_ll; - HLTYPE m_hl; - MachineBasicBlock * Parent; /* BB to which this icode belongs */ - bool invalid; /* Has no HIGH_LEVEL equivalent */ -public: - x86_insn_t insn; - template - struct FlagFilter - { - bool operator()(ICODE *ic) {return ic->ll()->testFlags(FLAG);} - bool operator()(ICODE &ic) {return ic.ll()->testFlags(FLAG);} - }; - template - struct TypeFilter - { - bool operator()(ICODE *ic) {return ic->type==HIGH_LEVEL;} - bool operator()(ICODE &ic) {return ic.type==HIGH_LEVEL;} - }; - template - struct TypeAndValidFilter - { - bool operator()(ICODE *ic) {return (ic->type==HIGH_LEVEL)&&(ic->valid());} - bool operator()(ICODE &ic) {return (ic.type==HIGH_LEVEL)&&ic.valid();} - }; - static TypeFilter select_high_level; - static TypeAndValidFilter select_valid_high_level; - /* Def/Use of registers and stack variables */ - struct DU_ICODE - { - DU_ICODE() - { - def.reset(); - use.reset(); - lastDefRegi.reset(); - } - std::bitset<32> def; // For Registers: position in bitset is reg index - std::bitset<32> use; // For Registers: position in uint32_t is reg index - std::bitset<32> lastDefRegi;// Bit set if last def of this register in BB - void addDefinedAndUsed(eReg r) - { - def |= duReg[r]; - use |= duReg[r]; +typedef struct { + icodeType type; /* Icode type */ + boolT invalid; /* Has no HIGH_LEVEL equivalent */ + struct _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 { /* Different types of icodes */ + LLTYPE ll; + HLTYPE hl; /* For HIGH_LEVEL icodes */ + } ic; /* intermediate code */ +} ICODE; +typedef ICODE* PICODE; - } - }; - struct DU1 - { - struct Use - { - int Reg; // used register - std::vector::iterator> uses; // use locations [MAX_USES] - void removeUser(std::list::iterator us) - { - // ic is no no longer an user - auto iter=std::find(uses.begin(),uses.end(),us); - if(iter==uses.end()) - return; - uses.erase(iter); - assert("Same user more then once!" && uses.end()==std::find(uses.begin(),uses.end(),us)); - } - - }; - int numRegsDef; /* # registers defined by this inst */ - uint8_t regi[MAX_REGS_DEF+1]; /* registers defined by this inst */ - Use idx[MAX_REGS_DEF+1]; - //int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */ - bool used(int regIdx) - { - return not idx[regIdx].uses.empty(); - } - int numUses(int regIdx) - { - return idx[regIdx].uses.size(); - } - void recordUse(int regIdx,std::list::iterator location) - { - idx[regIdx].uses.push_back(location); - } - void remove(int regIdx,int use_idx) - { - idx[regIdx].uses.erase(idx[regIdx].uses.begin()+use_idx); - } - void remove(int regIdx,std::list::iterator ic) - { - Use &u(idx[regIdx]); - u.removeUser(ic); - } - DU1() : numRegsDef(0) - { - } - }; - icodeType type; /* Icode type */ - DU_ICODE du; /* Def/use regs/vars */ - DU1 du1; /* du chain 1 */ - int loc_ip; // used by CICodeRec to number ICODEs - - LLInst * ll() { return &m_ll;} - const LLInst * ll() const { return &m_ll;} - - HLTYPE * hl() { return &m_hl;} - const HLTYPE * hl() const { return &m_hl;} - void hl(const HLTYPE &v) { m_hl=v;} - - void setRegDU(eReg regi, operDu du_in); - void invalidate(); - void newCallHl(); - void writeDU(); - condId idType(opLoc sd); - // HLL setting functions - // set this icode to be an assign - void setAsgn(COND_EXPR *lhs, COND_EXPR *rhs) - { - type=HIGH_LEVEL; - hl()->setAsgn(lhs,rhs); - } - void setUnary(hlIcode op, COND_EXPR *_exp); - void setJCond(COND_EXPR *cexp); - - void emitGotoLabel(int indLevel); - void copyDU(const ICODE &duIcode, operDu _du, operDu duDu); - bool valid() {return not invalid;} - void setParent(MachineBasicBlock *P) { Parent = P; } -public: - bool removeDefRegi(eReg regi, int thisDefIdx, LOCAL_ID *locId); - void checkHlCall(); - bool newStkArg(COND_EXPR *exp, llIcode opcode, Function *pproc) - { - return hl()->call.newStkArg(exp,opcode,pproc); - } - ICODE() : m_ll(this),type(NOT_SCANNED),Parent(0),loc_ip(0),invalid(false) - { - } -public: - const MachineBasicBlock* getParent() const { return Parent; } - MachineBasicBlock* getParent() { return Parent; } - //unsigned getNumOperands() const { return (unsigned)Operands.size(); } - -}; -/** Map n low level instructions to m high level instructions -*/ -struct MappingLLtoML -{ - typedef llvm::iplist InstListType; - typedef boost::iterator_range rSourceRange; - typedef boost::iterator_range rTargetRange; - rSourceRange m_low_level; - rTargetRange m_middle_level; -}; // This is the icode array object. -class CIcodeRec : public std::list +// The bulk of this could well be done with a class library +class CIcodeRec { public: - CIcodeRec(); // Constructor + CIcodeRec(); // Constructor + ~CIcodeRec(); // Destructor + + PICODE addIcode(PICODE pIcode); + PICODE GetFirstIcode(); +// PICODE GetNextIcode(PICODE pCurIcode); + boolT IsValid(PICODE pCurIcode); + int GetNumIcodes(); + void SetInBB(int start, int end, struct _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); + PICODE GetIcode(int ip); + +protected: + Int numIcode; /* # icodes in use */ + Int alloc; /* # icodes allocated */ + PICODE icode; /* Array of icodes */ - ICODE * addIcode(ICODE *pIcode); - void SetInBB(rCODE &rang, BB* pnewBB); - bool labelSrch(uint32_t target, uint32_t &pIndex); - iterator labelSrch(uint32_t target); - ICODE * GetIcode(int ip); - bool alreadyDecoded(uint32_t target); }; diff --git a/include/idioms/arith_idioms.h b/include/idioms/arith_idioms.h deleted file mode 100644 index a48e09b..0000000 --- a/include/idioms/arith_idioms.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once -#include -#include "idiom.h" -#include "icode.h" -#include - -struct Idiom5 : public Idiom -{ -protected: - iICODE m_icodes[2]; -public: - virtual ~Idiom5() {} - Idiom5(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; - -struct Idiom6 : public Idiom -{ -protected: - iICODE m_icodes[2]; -public: - virtual ~Idiom6() {} - Idiom6(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; - -struct Idiom18 : public Idiom -{ -protected: - iICODE m_icodes[4]; - bool m_is_dec; -public: - Idiom18(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 4;} - bool match(iICODE picode); - int action(); -}; - -struct Idiom19 : public Idiom -{ -protected: - iICODE m_icodes[2]; - bool m_is_dec; -public: - Idiom19(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE picode); - int action(); -}; - -struct Idiom20 : public Idiom -{ -protected: - iICODE m_icodes[4]; - bool m_is_dec; -public: - Idiom20(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 4;} - bool match(iICODE picode); - int action(); -}; diff --git a/include/idioms/call_idioms.h b/include/idioms/call_idioms.h deleted file mode 100644 index c624933..0000000 --- a/include/idioms/call_idioms.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include -#include "idiom.h" -#include "icode.h" -#include -struct CallIdiom : public Idiom -{ -protected: - int m_param_count; -public: - virtual ~CallIdiom() {} - CallIdiom(Function *f) : Idiom(f) - { - } - -}; -struct Idiom3 : public CallIdiom -{ -protected: - iICODE m_icodes[2]; -public: - virtual ~Idiom3() {} - Idiom3(Function *f) : CallIdiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; -struct Idiom17 : public CallIdiom -{ -protected: - std::vector m_icodes; -public: - virtual ~Idiom17() {} - Idiom17(Function *f) : CallIdiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; diff --git a/include/idioms/epilogue_idioms.h b/include/idioms/epilogue_idioms.h deleted file mode 100644 index daf5c0d..0000000 --- a/include/idioms/epilogue_idioms.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once -#include "idiom.h" -#include "icode.h" -#include -struct EpilogIdiom : public Idiom -{ -protected: - std::deque m_icodes; // deque to push_front optional icodes from popStkVars - void popStkVars (iICODE pIcode); -public: - virtual ~EpilogIdiom() {} - EpilogIdiom(Function *f) : Idiom(f) - { - } - -}; -struct Idiom2 : public EpilogIdiom -{ - virtual ~Idiom2() {} - Idiom2(Function *f) : EpilogIdiom(f) - { - } - uint8_t minimum_match_length() {return 3;} - bool match(iICODE pIcode); - int action(); -}; -struct Idiom4 : public EpilogIdiom -{ -protected: - int m_param_count; -public: - virtual ~Idiom4() {} - Idiom4(Function *f) : EpilogIdiom(f) - { - } - uint8_t minimum_match_length() {return 1;} - bool match(iICODE pIcode); - int action(); -}; diff --git a/include/idioms/idiom.h b/include/idioms/idiom.h deleted file mode 100644 index 9b09a98..0000000 --- a/include/idioms/idiom.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "icode.h" -#include "Procedure.h" -struct Idiom -{ -protected: - Function *m_func; - iICODE m_end; -public: - Idiom(Function *f) : m_func(f),m_end(f->Icode.end()) - { - } - virtual uint8_t minimum_match_length()=0; - virtual bool match(iICODE at)=0; - virtual int action()=0; - int operator ()(iICODE at) - { - if(match(at)) - return action(); - return 1; - } -}; diff --git a/include/idioms/idiom1.h b/include/idioms/idiom1.h deleted file mode 100644 index 43d3be1..0000000 --- a/include/idioms/idiom1.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "idiom.h" -struct Idiom1 : public Idiom -{ -protected: - std::vector m_icodes; - int m_min_off; - int checkStkVars (iICODE pIcode); -public: - Idiom1(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 1;} - bool match(iICODE picode); - int action(); - size_t match_length() {return m_icodes.size();} -}; diff --git a/include/idioms/mov_idioms.h b/include/idioms/mov_idioms.h deleted file mode 100644 index f81c184..0000000 --- a/include/idioms/mov_idioms.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include -#include "idiom.h" -#include "icode.h" -#include - -struct Idiom14 : public Idiom -{ -protected: - iICODE m_icodes[2]; - eReg m_regL; - eReg m_regH; -public: - virtual ~Idiom14() {} - Idiom14(Function *f) : Idiom(f),m_regL(rUNDEF),m_regH(rUNDEF) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; - -struct Idiom13 : public Idiom -{ -protected: - iICODE m_icodes[2]; - eReg m_loaded_reg; -public: - virtual ~Idiom13() {} - Idiom13(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; diff --git a/include/idioms/neg_idioms.h b/include/idioms/neg_idioms.h deleted file mode 100644 index 613ef87..0000000 --- a/include/idioms/neg_idioms.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include "idiom.h" -#include "icode.h" -#include - -struct Idiom11 : public Idiom -{ -protected: - iICODE m_icodes[3]; -public: - virtual ~Idiom11() {} - Idiom11(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 3;} - bool match(iICODE pIcode); - int action(); -}; - -struct Idiom16 : public Idiom -{ -protected: - iICODE m_icodes[3]; -public: - virtual ~Idiom16() {} - Idiom16(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 3;} - bool match(iICODE pIcode); - int action(); -}; diff --git a/include/idioms/shift_idioms.h b/include/idioms/shift_idioms.h deleted file mode 100644 index ac044c8..0000000 --- a/include/idioms/shift_idioms.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include -#include "idiom.h" -#include "icode.h" -#include - -struct Idiom8 : public Idiom -{ -protected: - iICODE m_icodes[2]; - uint8_t m_loaded_reg; -public: - virtual ~Idiom8() {} - Idiom8(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; - -struct Idiom15 : public Idiom -{ -protected: - std::vector m_icodes; -public: - virtual ~Idiom15() {} - Idiom15(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; - -struct Idiom12 : public Idiom -{ -protected: - iICODE m_icodes[2]; - uint8_t m_loaded_reg; -public: - virtual ~Idiom12() {} - Idiom12(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; - - -struct Idiom9 : public Idiom -{ -protected: - iICODE m_icodes[2]; - uint8_t m_loaded_reg; -public: - virtual ~Idiom9() {} - Idiom9(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; - diff --git a/include/idioms/xor_idioms.h b/include/idioms/xor_idioms.h deleted file mode 100644 index 3698286..0000000 --- a/include/idioms/xor_idioms.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include -#include "idiom.h" -#include "icode.h" -#include - -struct Idiom21 : public Idiom -{ -protected: - iICODE m_icodes[2]; -public: - virtual ~Idiom21() {} - Idiom21(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 2;} - bool match(iICODE pIcode); - int action(); -}; - -struct Idiom7 : public Idiom -{ -protected: - iICODE m_icode; -public: - virtual ~Idiom7() {} - Idiom7(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 1;} - bool match(iICODE pIcode); - int action(); -}; -struct Idiom10 : public Idiom -{ -protected: - iICODE m_icodes[2]; -public: - virtual ~Idiom10() {} - Idiom10(Function *f) : Idiom(f) - { - } - uint8_t minimum_match_length() {return 1;} - bool match(iICODE pIcode); - int action(); -}; diff --git a/include/locident.h b/include/locident.h index 57d1619..aa117a0 100644 --- a/include/locident.h +++ b/include/locident.h @@ -5,134 +5,106 @@ * (C) Cristina Cifuentes */ -#pragma once -#include -#include -#include -#include -#include -#include "types.h" -#include "Enums.h" -#include "machine_x86.h" /* Type definition */ -// this array has to stay in-order of addition i.e. not std::set > -// TODO: why ? -struct COND_EXPR; -struct ICODE; -struct LLInst; -typedef std::list::iterator iICODE; -struct IDX_ARRAY : public std::vector -{ - bool inList(iICODE idx) - { - return std::find(begin(),end(),idx)!=end(); - } -}; +typedef struct { + Int csym; /* # symbols used */ + Int alloc; /* # symbols allocated */ + Int *idx; /* Array of integer indexes */ +} IDX_ARRAY; + +/* 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 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 */ + STK_FRAME, /* For stack vars */ + REG_FRAME, /* For register variables */ + GLB_FRAME, /* For globals */ } frameType; + +/* Enumeration to determine whether pIcode points to the high or low part + * of a long number */ +typedef enum { + HIGH_FIRST, /* High value is first */ + LOW_FIRST, /* Low value is first */ +} hlFirst; + + typedef struct { - int16_t seg; /* segment value */ - int16_t off; /* offset */ - eReg regi; /* optional indexed register */ + 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 */ + Int offH; /* high offset from BP */ + Int offL; /* low offset from BP */ } LONG_STKID_TYPE; -struct LONGID_TYPE +typedef struct { /* For TYPE_LONG_(UN)SIGN registers */ - eReg h; /* high register */ - eReg l; /* low register */ - bool srcDstRegMatch(iICODE a,iICODE b) const; -}; + byte h; /* high register */ + byte l; /* low register */ +} LONGID_TYPE; /* ID, LOCAL_ID */ -struct ID -{ - hlType type; /* Probable type */ - bool illegal; /* Boolean: not a valid field any more */ - //std::vector idx; - IDX_ARRAY idx; /* Index into icode array (REG_FRAME only) */ - frameType loc; /* Frame location */ - bool hasMacro; /* Identifier requires a macro */ - char macro[10]; /* Macro for this identifier */ - std::string name; /* Identifier's name */ - union { /* Different types of identifiers */ - eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */ - struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */ - uint8_t regOff; /* register offset (if any) */ - int off; /* offset from BP */ - } bwId; - BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(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_t seg; /* segment value */ - int16_t offH; /* offset high */ - int16_t offL; /* offset low */ - uint8_t regi; /* optional indexed register */ - } longGlb; - struct { /* For TYPE_LONG_(UN)SIGN constants */ - uint32_t h; /* high uint16_t */ - uint32_t l; /* low uint16_t */ - } longKte; - } id; - ID(); - ID(hlType t, frameType f); - bool isSigned() const { return (type==TYPE_BYTE_SIGN)||(type==TYPE_WORD_SIGN)||(type==TYPE_LONG_SIGN);} - uint16_t typeBitsize() const - { - return TypeContainer::typeSize(type)*8; - } - void setLocalName(int i) - { - char buf[32]; - sprintf (buf, "loc%ld", i); - name=buf; - } -}; +typedef struct { + 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; -struct LOCAL_ID -{ - std::vector id_arr; -protected: - int newLongIdx(int16_t seg, int16_t offH, int16_t offL, uint8_t regi, hlType t); - int newLongGlb(int16_t seg, int16_t offH, int16_t offL, hlType t); - int newLongStk(hlType t, int offH, int offL); -public: - LOCAL_ID() - { - id_arr.reserve(256); - } - // interface to allow range based iteration - std::vector::iterator begin() {return id_arr.begin();} - std::vector::iterator end() {return id_arr.end();} - int newByteWordReg(hlType t, eReg regi); - int newByteWordStk(hlType t, int off, uint8_t regOff); - int newIntIdx(int16_t seg, int16_t off, eReg regi, int ix, hlType t); - int newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_); - int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, int off); - int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset); - void newIdent(hlType t, frameType f); - void flagByteWordId(int off); - void propLongId(uint8_t regL, uint8_t regH, const char *name); - size_t csym() const {return id_arr.size();} - void newRegArg(iICODE picode, iICODE ticode) const; - void processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode, bool isLong) const; - void forwardSubs(COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const; - COND_EXPR *createId(const ID *retVal, iICODE ix_); -}; +typedef struct { + Int csym; /* No. of symbols in the table */ + Int alloc; /* No. of symbols allocated */ + ID *id; /* Identifier */ +} LOCAL_ID; diff --git a/include/machine_x86.h b/include/machine_x86.h deleted file mode 100644 index 9b6e082..0000000 --- a/include/machine_x86.h +++ /dev/null @@ -1,82 +0,0 @@ -#pragma once -#include -#include -#include -#include - -/* Machine registers */ -enum eReg -{ - rUNDEF = 0, - rAX = 1, /* These are numbered relative to real 8086 */ - rCX = 2, - rDX = 3, - rBX = 4, - rSP = 5, - rBP = 6, - rSI = 7, - rDI = 8, - - rES = 9, - rCS = 10, - rSS = 11, - rDS = 12, - - rAL = 13, - rCL = 14, - rDL = 15, - rBL = 16, - rAH = 17, - rCH = 18, - rDH = 19, - rBH = 20, - - rTMP= 21, /* temp register for DIV/IDIV/MOD */ - /* Indexed modes go from INDEXBASE to INDEXBASE+7 */ - INDEX_BX_SI = 22, // "bx+si" - INDEX_BX_DI, // "bx+di" - INDEX_BP_SI, // "bp+si" - INDEX_BP_DI, // "bp+di" - INDEX_SI, // "si" - INDEX_DI, // "di" - INDEX_BP, // "bp" - INDEX_BX, // "bx" - LAST_REG -}; -class SourceMachine -{ -public: - virtual bool physicalReg(eReg r)=0; - -}; -//class Machine_X86_Disassembler -//{ -// void formatRM(std::ostringstream &p, uint32_t flg, const LLOperand &pm); -//}; -class Machine_X86 : public SourceMachine -{ -public: - Machine_X86(); - virtual ~Machine_X86() {} - static const std::string ®Name(eReg r); - static const std::string &opcodeName(unsigned r); - static const std::string &floatOpName(unsigned r); - bool physicalReg(eReg r); - /* Writes the registers that are set in the bitvector */ - //TODO: move this into Machine_X86 ? - static void writeRegVector (std::ostream &ostr,const std::bitset<32> ®i) - { - int j; - for (j = rAX; j < INDEX_BX_SI; j++) - { - if (regi.test(j-1)) - ostr << regName(eReg(j))<<" "; - } - } - static eReg subRegH(eReg reg); //TODO: move these into machine_x86 - static eReg subRegL(eReg reg); - - static bool isMemOff(eReg r); - static bool isSubRegisterOf(eReg reg, eReg parent); - -}; diff --git a/include/perfhlib.h b/include/perfhlib.h index 1613b4f..4fb0d03 100644 --- a/include/perfhlib.h +++ b/include/perfhlib.h @@ -1,41 +1,34 @@ -#pragma once /* Perfect hashing function library. Contains functions to generate perfect hashing functions * (C) Mike van Emmerik */ -//#define bool unsigned char -#define uint8_t unsigned char -#define uint16_t unsigned short + +#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, uint8_t **pKeys);/* Set *keys to point to the i+1th key */ +void getKey(int i, byte **pKeys);/* Set *keys to point to the i+1th key */ void dispKey(int i); /* Display the key */ -class PatternHasher -{ - uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */ - int NumEntry; /* Number of entries in the hash table (# keys) */ - int EntryLen; /* Size (bytes) of each entry (size of keys) */ - int SetSize; /* Size of the char set */ - char SetMin; /* First char in the set */ - int NumVert; /* c times NumEntry */ - int *graphNode; /* The array of edges */ - int *graphNext; /* Linked list of edges */ - int *graphFirst;/* First edge at a vertex */ -public: - uint16_t *readT1(void); /* Returns a pointer to the T1 table */ - uint16_t *readT2(void); /* Returns a pointer to the T2 table */ - uint16_t *readG(void); /* Returns a pointer to the g table */ - void init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin,int _NumVert); /* Set the parameters for the hash table */ - void cleanup(); - int hash(unsigned char *string); //!< Hash the string to an int 0 .. NUMENTRY-1 -}; -extern PatternHasher g_pattern_hasher; -/* Macro reads a LH uint16_t from the image regardless of host convention */ + + +/* Macro reads a LH word from the image regardless of host convention */ #ifndef LH -#define LH(p) ((int)((uint8_t *)(p))[0] + ((int)((uint8_t *)(p))[1] << 8)) +#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8)) #endif diff --git a/include/project.h b/include/project.h deleted file mode 100644 index b0381a3..0000000 --- a/include/project.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "symtab.h" -#include "BinaryImage.h" -struct Function; -struct SourceMachine; -struct CALL_GRAPH; - -typedef llvm::iplist FunctionListType; -typedef FunctionListType lFunction; -typedef lFunction::iterator ilFunction; - - -struct Project -{ - SYMTAB symtab; /* Global symbol table */ - - std::string m_fname; - FunctionListType pProcList; - CALL_GRAPH * callGraph; /* Pointer to the head of the call graph */ - PROG prog; /* Loaded program image parameters */ - Project() {} - // no copies - Project(const Project&) = delete; - const Project &operator=(const Project & l) =delete; - // only moves - Project(Project && l) - { - m_fname =l.m_fname; - size_t before=l.pProcList.size(); - pProcList.splice(pProcList.end(),l.pProcList); - callGraph=l.callGraph; - l.m_fname.clear(); - l.pProcList.clear(); - l.callGraph=0; - assert(before==pProcList.size()); - } - Project &operator=(Project && l) - { - if(this == &l) - return *this; - m_fname =l.m_fname; - size_t before=l.pProcList.size(); - pProcList.splice(pProcList.end(),l.pProcList); - callGraph=l.callGraph; - l.m_fname.clear(); - l.pProcList.clear(); - l.callGraph=0; - assert(before==pProcList.size()); - return *this; - } - -public: - ilFunction funcIter(Function *to_find); - ilFunction findByEntry(uint32_t entry); - ilFunction createFunction(); - bool valid(ilFunction iter); - - int getSymIdxByAdd(uint32_t adr); - bool validSymIdx(size_t idx); - size_t symbolSize(size_t idx); - hlType symbolType(size_t idx); - const std::string &symbolName(size_t idx); - const SYM &getSymByIdx(size_t idx) const; - - static Project *get(); - PROG * binary() {return &prog;} - SourceMachine *machine(); - -protected: - void writeGlobSymTable(); -}; -//extern Project g_proj; diff --git a/include/scanner.h b/include/scanner.h index 6ec1f47..94a8078 100644 --- a/include/scanner.h +++ b/include/scanner.h @@ -1,12 +1,38 @@ -#pragma once /* Scanner functions * (C) Cristina Cifuentes, Jeff Ledermann */ -#include -#include "error.h" -/* Extracts reg bits from middle of mod-reg-rm uint8_t */ -#define REG(x) ((uint8_t)(x & 0x38) >> 3) -struct ICODE; +#define LH(p) ((int)((byte *)(p))[0] + ((int)((byte *)(p))[1] << 8)) -extern eErrorId scan(uint32_t ip, ICODE &p); +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) diff --git a/include/state.h b/include/state.h index 003720d..74a8a58 100644 --- a/include/state.h +++ b/include/state.h @@ -2,34 +2,18 @@ * dcc project header * (C) Cristina Cifuentes, Mike van Emmerik ****************************************************************************/ -#pragma once -#include -#include -#include "machine_x86.h" /* STATE TABLE */ -struct STATE +typedef struct { - uint32_t IP; /* Offset into Image */ - int16_t r[INDEX_BX_SI]; /* Value of segs and AX */ - bool f[INDEX_BX_SI]; /* True if r[.] has a value */ + 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 */ - uint8_t regi; /* Last conditional jump */ - int16_t immed; /* Contents of the previous register */ + { /* For case stmt indexed reg */ + byte regi; /* Last conditional jump */ + int16 immed; /* Contents of the previous register */ } JCond; - void setState(uint16_t reg, int16_t value); - void checkStartup(); - bool isKnown(eReg v) {return f[v];} - void kill(eReg v) { f[v]=false;} - STATE() : IP(0) - { - JCond.regi=0; - JCond.immed=0; - - memset(r,0,sizeof(int16_t)*INDEX_BX_SI); //TODO: move this to machine_x86 - memset(f,0,sizeof(uint8_t)*INDEX_BX_SI); - } -}; - +} STATE; +typedef STATE *PSTATE; diff --git a/include/symtab.h b/include/symtab.h index a5ccaf6..5cae187 100644 --- a/include/symtab.h +++ b/include/symtab.h @@ -2,112 +2,42 @@ * Symbol table prototypes * (C) Mike van Emmerik */ -#pragma once -#include -#include -#include "Enums.h" -#include "types.h" -struct COND_EXPR; -struct TypeContainer; + /* * * * * * * * * * * * * * * * * */ /* Symbol table structs and protos */ /* * * * * * * * * * * * * * * * * */ -struct SymbolCommon -{ - std::string name; /* New name for this variable/symbol/argument */ - int size; /* Size/maximum size */ - hlType type; /* probable type */ - eDuVal duVal; /* DEF, USE, VAL */ - SymbolCommon() : size(0),type(TYPE_UNKNOWN) - {} -}; -struct SYM : public SymbolCommon -{ - SYM() : label(0),flg(0) - { - } - int32_t label; /* physical address (20 bit) */ - uint32_t flg; /* SEG_IMMED, IMPURE, WORD_OFF */ -}; -/* STACK FRAME */ -struct STKSYM : public SymbolCommon +typedef struct { - COND_EXPR *actual; /* Expression tree of actual parameter */ - COND_EXPR *regs; /* For register arguments only */ - int16_t label; /* Immediate off from BP (+:args, -:params) */ - uint8_t regOff; /* Offset is a register (e.g. SI, DI) */ - bool hasMacro; /* This type needs a macro */ - std::string macro; /* Macro name */ - bool invalid; /* Boolean: invalid entry in formal arg list*/ - STKSYM() - { - actual=regs=0; - label=0; - regOff=0; - invalid=hasMacro = false; - } - void setArgName(int i) - { - char buf[32]; - sprintf (buf, "arg%d", i); - name = buf; - } -}; -template -class SymbolTableCommon : public std::vector -{ -public: - typedef typename std::vector::iterator iterator; - typedef typename std::vector::const_iterator const_iterator; - iterator findByLabel(int lab) - { - auto iter = std::find_if(this->begin(),this->end(), - [lab](T &s)->bool {return s.label==lab;}); - return iter; - } - const_iterator findByLabel(int lab) const - { - auto iter = std::find_if(this->begin(),this->end(), - [lab](const T &s)->bool {return s.label==lab;}); - return iter; - } + char *pSymName; /* Ptr to symbolic name or comment */ + dword symOff; /* Symbol image offset */ + PPROC 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; -}; -/* SYMBOL TABLE */ -class SYMTAB : public SymbolTableCommon -{ - -public: - void updateSymType(uint32_t symbol, const TypeContainer &tc); - SYM *updateGlobSym(uint32_t operand, int size, uint16_t duFlag, bool &inserted_new); -}; -struct Function; -struct SYMTABLE -{ - std::string pSymName; /* Ptr to symbolic name or comment */ - uint32_t symOff; /* Symbol image offset */ - Function *symProc; /* Procedure pointer */ - SYMTABLE() : symOff(0),symProc(0) {} - SYMTABLE(uint32_t _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 - return (symOff==other.symOff) && symProc==(other.symProc); - } -}; - -enum tableType /* The table types */ +enum _tableType /* The table types */ { Label=0, /* The label table */ Comment, /* The comment table */ NUM_TABLE_TYPES /* Number of entries: must be last */ -}; +}; + +typedef enum _tableType tableType; /* For convenience */ void createSymTables(void); void destroySymTables(void); -boolT readVal (std::ostringstream &symName, uint32_t symOff, Function *symProc); +void enterSym(char *symName, dword symOff, PPROC symProc, boolT bSymToo); +boolT readSym (char *symName, dword *pSymOff, PPROC *pSymProc); +boolT readVal (char *symName, dword symOff, PPROC symProc); +void deleteSym(char *symName); +void deleteVal(dword symOff, PPROC symProc, boolT bSymToo); +boolT findVal(dword symOff, PPROC symProc, word *pIndex); +word symHash(char *name, word *pre); +word valHash(dword off, PPROC proc, word *pre); void selectTable(tableType); /* Select a particular table */ +char *addStrTbl(char *pStr); /* Add string to string table */ + diff --git a/include/types.h b/include/types.h index 7f49a96..964d74f 100644 --- a/include/types.h +++ b/include/types.h @@ -2,19 +2,34 @@ * dcc project general header * (C) Cristina Cifuentes, Mike van Emmerik ****************************************************************************/ -#pragma once -#include -#include -#include "Enums.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 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 */ @@ -24,15 +39,17 @@ typedef unsigned char boolT; /* 8 bits */ /****** MACROS *******/ +/* Macro to allocate a node of size sizeof(structType). */ +#define allocStruc(structType) (structType *)allocMem(sizeof(structType)) + /* 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 LH_SIGNED(p) (((byte *)(p))[0] + (((char *)(p))[1] << 8)) +#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))) @@ -40,68 +57,3 @@ typedef unsigned char boolT; /* 8 bits */ /* Macro to convert a segment, offset definition into a 20 bit address */ #define opAdr(seg,off) ((seg << 4) + off) -/* duVal FLAGS */ -struct eDuVal -{ - eDuVal() - { - def=use=val=0; - } - 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 */ -}; -static constexpr const char * hlTypes[13] = { - "", "char", "unsigned char", "int", "unsigned int", - "long", "unsigned long", "record", "int *", "char *", - "", "float", "double" -}; - -struct TypeContainer -{ - hlType m_type; - size_t m_size; - TypeContainer(hlType t,size_t sz) : m_type(t),m_size(sz) - { - } - static size_t typeSize(hlType t) - { - switch(t) - { - case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: - return 2; - case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: - return 1; - } - return 0; - } - static hlType defaultTypeForSize(size_t x) - { - /* Type of the symbol according to the number of bytes it uses */ - static hlType cbType[] = {TYPE_UNKNOWN, TYPE_BYTE_UNSIGN, TYPE_WORD_SIGN, - TYPE_UNKNOWN, TYPE_LONG_SIGN}; - - assert(x < sizeof(cbType)/sizeof(hlType)); - return cbType[x]; - } - static constexpr const char *typeName(hlType t) - { - return hlTypes[t]; - } -}; diff --git a/prototypes/dcclibs.dat b/prototypes/dcclibs.dat new file mode 100644 index 0000000000000000000000000000000000000000..485c9b03b4297e00356edab08f314f2e7bf0cf89 GIT binary patch literal 8833 zcmZ{p3yds96^2js>|SCD?A;B1;Bqk(^1Rwuj)zx*X=Q^`HGyCU8ZeO=lOq;S#gH-XB!!>*60hG4hC!_4Ra|E6mGZ7vOA?*P0vIPn=I@MOhD; zD+!cX>3kXq1AmLs#k|(ylE^oRtNKtwrkj&u=*<)9LHaH+urKSEXP)6NEaAhqp(Gs_ zRpue3joeLKOzW~3d-)|OvC?JMueEd{KZ10&n=6XzMlM54MjKh3YH1_)63@!4%AzlP z7fMF6c`TjCPar)mi+UWC?13duG`NiMlfaXHy_uEmg*9206M&0ZHVwiyCV#+?@J2-n zxF-)2MEVZc@0ujiGI6tD>0sp=Aj6#g5lh{=y($xfNqQM`Ndcai=8 zvq2fikNXU86+vd_AC#^l%X=8~?G{JciQfsFrdg%*a6-Vqep)CfvIgD%1RjrzbdpW{ zxRf3MS81J3g5h-MoCG-6akWaGfOOqo!2fdiRIeECYta29aXf$M<q{G9!+VaEpwqsKR3|{XY>lw;)Q!iW z!rD$Z8xp*y2#1M_G8<h+E+;mEzXaaRQa!1d zhJD6Ztehmipux&U;)^^E;>53WSVx8U^)L`aZU3OKNN|3mco6I5!?km`#iKF{mQb<76J2RmfRC`!nE2dIm>U+Q z1lGu?v$~n$9av&9#GNpF6!|{!Vu~LH9>zO5byIpYo>yueQ}-@#+=oE7kpm6h?6;+Z zL;ld=nc6j&w1W=o#k~qOR{`f^l$q&9-3-fp=U4DDpAJWPS^4?Nq@C~Z6zidJ(pqv6 z@VICj1zuuy66mHkAtaD?2F8^a(uwpSJ)LCbhR)8iycW8r)oiS$N)KD(#lUd@ZFa7P zl7-5a$oq`x^k%Rmk!vW8mMw~)u@PLTgNeK!(oxgG25L#JwOAVs9}PX_OjCV`4HZ%a z99h1C3m>#fqKVI#ECVl8%|t#7cd9JY`wp{n9i=n$*&)gF@}s~t>Lb(AJecB-14qr4 zbLSIAHWp@VPaXqCE37LrbBU3N)r6(va!!L)R1}__zuDp;dMj@> z-c2*)FkZ%qU_!zY-Q!qGE_1l<2OX>Uc&EkLRFyXFI}chfNBRaqU!N`P9A0_Bj}{jZMN$VUM_R1gA(F= zI>IJoA4X1cSa-dQpi{D)mHEhTrPTc{E8TA9)WI@yH!PWGA6W;DoR`Q(Q5U;jgB>!F z=Zj!94a06}Idv1`u4x`xa3fcFTw_D^4`3(W#_qk}#3bT5i`E~)o6*l+R{FUd6)M~yi%f33$soJu}m zF+wt*Y1eBN2o;GuC4O_GBU^(_RWohp zD6baT$}%+rIVkFh$hfn+vO*kYWIT*_V-}?q;%=*y$ghF9XE;CXEB0Y|9Js&^t!5CX z&%T6MS1?%JlZRkQf!i4M;7)Qlm2B*NSqC3MJl(jm?KF8kk^RIw-PyzGGd{#!##4~) z6w_r`@>@tBBCsZrs8hgzbO$TBbKedXMvg&qnoV%-60)`e+2=XDsdCRv-~|qAZy1vo zI;?bH$ez5|;yhL2lzxfDlR|Z8l-_G`bY?+(8t_)A#*82BM%A2bsSX~PMd@wOWrdU7_J>Y|)6Olmg&r2c+~;LL6;J#Gi%kx!qt|HQaZQ9pK19hUy+15mt-GK@S-z`}x9saZMcO zm)p_r93GS*^VEH#Sn0t|SUkjE0FIBs5Wk*0VsYr;p_h&JGV!z@wj#zPksB~%wiDMd zIR81|$>Jh;E7~934_V!)n!xdmE_55Y(HK{JW;ow-LFAHp8>F+1j_F3eL|hMaiKKyF zc6hE*%=!I!bVUoznUR~U^g;vm6^GSnkTviMhxHof48POjg(l}O7DttrURKtUg~ffY z!^JQx2)gsART4Eh9P(z1)rP@v8TqQk+XLl2&j-I~b#G^>-dja(anicUp^{sH^LT@y z_BoWq=YaMO=IIve?$+X?fXCf^)W~hny-=x)d<}Tk-*jEUod!ld1VA@|2ez1*Uo0qO2C z2F5C`I?I7dZibRhf;oL~a#qzdyBn0!q*s9tRA_!e(l|9|Mmqlzu%+N=ix(=yGlAn$~*FbkMpP|ud#fi@YJ{Tq5UcNAqd8c>gWLpEC^uzxk zAj{S8H&ov#?q1VYHDnXH%``Z~mP4LP>3kOxB|7D}oftQDYMxN~4vVAv46cU9M7BG} zM8vn_M89*~LVO4CA?n~afe%sH?j(-IspLDvu{iNvI61_B`?7Gu2q^LjaaeVP9-}*n zTf!wP9sf@bN_z6R$eS*?FyRfy61pDu%MN@G{&K&J5k=QTUqxq&TN9qyHX(=JN!6OVoQ>zN;$qq?#E zH7`MV>f$qj1x^!3aZfj*X}(Q8-U7$m^<{AS<+RWjN;$9i7rBe1W{$hD`RaY8ET#GD z<=x2P)qRVWJ6YQ0udbmgx#w#8$&)pVvJ8r)XrC(`3IDgVhPQn5jNkGx_Az&n@4mWt z_~`Lll;9fI+5Uf@omXKd=vkpZyQuhA%CmXrFGmbdO1Syvvcp$r6RqO+_!nOpYyUl3 z@2+|~oebruk(qT*mmjY~OS$j+S1;$R;b8&muOHvdDEhu?v+3tpJPt=@)|{RC-NnJ% s&w0QdkH5|%H%pupKl7JkQ^ry4kN@0#ch+=YLo~e3_i_@% literal 0 HcmV?d00001 diff --git a/sigs/dccb2s.sig b/sigs/dccb2s.sig new file mode 100644 index 0000000000000000000000000000000000000000..b2f49a680a0bf01c171c16bf6b4037f2c7d72f5b GIT binary patch literal 39073 zcmaI81$b21^1WSE9YP?u!{F|N!{8b;K#(*ZEVvU~gF}$P-Q8gZcXxMpcL@ZY{NIxR zckcau&(}N=x=)|8&)!w5)>^eY&6_pr8mMtyi6xHI$}KtL$r))VzPjGh=^xhEuGo1i zF3IGaW{^7aMjKfSS5X_QEo7cmvV&GgM@km$qJPL;Z6dcMuXWeoEs1W@v9`tB5~R88 zZ@sGz<+7cUJ(kj@NPEj{VHVw%Yeh?|VOCeZ$RhQ!{8Czu$W-m8r6q&TvP3pWV!CSE zdOI#@WR%>oe=Lq|lgAcAM(A!$qGNQ8l#sc4L0j5*sUj`4qE69fQcP}0ZOLW#?V)Cs zG1kUBZJ)-~cQ#ql+9543ORctsTYgo!Yb$JnZqQZ|ODD)X^>odW#P*wpYg;WL^(BG* zBU|l@T$j(1NK@!Uoh4zGKqu%Z>#w8akbbZ}7ObarqNTHY*2(f|N{yw#@PQr3-FGm_RZ4R94pOztF(|8`cNOpa_OUKY_wIjRI*yCndwxW zuW6*Q)Yi1-E1~jLugMi_C%Y`3b&;{$)ot;SQ?g9FWsJ_0sZy7b$B_VOtp_E)+%&WA zlE$jqH%(x_*%O^@LHbD+*&eOIos80AI#}z-Te&aS^p%?3*L$X}!Ft+Wo12-PF6r%^ z-P7M?opoSTq2@ufoYeR7w{+JRtVtsgmxpGwVmi;3ND5i17v)cxBFW{RHqowjNYtKd zdVOY1wVN)o=QdE{$qnwnY?xNnPu9p(-{@Ssu7m8cCKhkYBeCSX#Ieria!r#^=HZkr z)mhrqdJ(a4wWQt9>@rzv$$Fd3inY~}a$Fj#hq|?kJe9*%&WcGoDWYO=G^h5K<NlnNnMKa5s&$i27Oro*!dHY>npt*eF2ODYvo=IuJkxR&$&IIgMO+j9%iCmLP;&_NQ-=G#O0Y*Fo+v{z5oYl)?@6>?Kb zS`F*1we*dw(0*jfM{R5MWV_w8V;0L5z`W(uInqnxOG>$C12jId*TKT|s;t!4HcO7^ zWQ(HL%ttm^JMAM6rK6Q(y`quNbEKbk()zmEipm%%uh}eE{Pdm<Nf}J+^|1R=AB2l91!SddX9ar_ zhufsRT(>}p3a%~J;*5Bi)MN#E6BXyAu7zrTi9*I?v~nP1poZyM`DV`~n(MF@k+ZDm zDpoh9{U)C@L|RHI@;$Gu*X2aUaoMF;EUlFy0(NT$E1*7FK_;h4`j5qy`JnG?DJ%7)KKOJN)q3MYmkxH6K7F)2z z(o(uiXUia+&uG(Y9Q_W)WdqBySW!Eo2c6m1{?bUj$<=AB)pR{(FD!~ZwLh$>oVKmn z#LDS?%c_IL!&O+H*j?>rE%cW45Kp3^gtU?mtV2&QrJe;z9&12Fn4-sZwq7KDDua<% zt(XnfM0&^8%42GW4@i4i``SU!wIR_wU6;u}%tKb*mw{~Xu`in6{8_t9wn@9mbD3#L ztvRUkhh=2eI@uvhVI6IXhEOXeX?OF~#dh5)h}cZaE-T2G=HRfGRUtY>-|#b!m0^XG zT31aX3uLRVXV%kdXX1Jx7|})lCZFHPaR`GE<+E zZ{JwGQSx45uqI!%9dq2(zJXGqc0n50AT3B8I3&sRoYo{N+lsk9T2I|Ue2mjrt^$%+ z-)S`+EwyYTm1={W(N#8=`YD|AjKz^SV9;92!diWizF_-cYi}>q%au)YNo?0HJ0@kM zxuuid7AA@0w(YR1x}7ylW}e{ZM=PqoX)-EYecLCe^o*Xdb23y0NNimVvc6&U`homm zRP};Xqk%eH@<^~$VCCZKD`vTgy`qA&VRSR44AuS{Gv_HWn&-{oVe`@v-eJi+Y{=vmu`@QaE;BN^F%W52(|x~RMnl*&Z5di$pltRux8-c zAxkMIEDme8pSWMBU11aziRR|^L|THDsinBq1o>J@bGb%FW)Lr8rnME2#;}^SjCmTk zGJ*PeM#qqE%itDoMXAu)iJ`i1l^QaHXWPqP=Ea$(5!HWbfT(M{7~JKk{XyM)4&p7= zigKT-Gy}9#;Ub$fb(9%qB=DF!hZMW9(Nfs_Ucog?wPhu z=i7IyY#yL$DQfY3ImS2&Qy(+yd2K0bD*delRWm2=SS%IwIVsYhBS`|b~ORe}W^>mHhA}e>nGw#6UW>dFY$yip^rJwb^{w441uykOgMf8MLm)x=q z1l?^f)gOM-h$=W!Rb%Kb%SS|<)Oh-*&DR4|-?dcZ0 z%I~nS_~Hx3jJ5P8u6}T=6Iw^NfLPV6Fi0ESmD`Cf&8W@Ey$)bSbL~McRf35%wHCI^ zvgu0w8&lm05Mxak`N^VznBk)TPCYut{JEk`Rz6tc7W=i+6uyN(@R~+ zYMsc8Uitwpw8UD&*=~Vs*{R26G{`(%8>sA+HNQq9KUOljjj-Qfa(khSw0yA9OQ7Lx z+ad$?mhJ&pkMr);u<5!mt@EtXRO=5*{ast?7GnH`T%t~;mO`+TZW2gsTcBAiDeDC? zG3L?CLJ)jwi43x2wiV{n66Rfl3V20Zkb&iFG047?J1r|s;Cp>FqimG}TF=UoUumgG zL#&o{0}ba(N*yYz8PQxBLdGo96R_l!VCQ`5{cAl$U6>1}%BUx8qi(d=mVo2>=?X1H zv>k>|c&WOQN)f4J18lH#rtaObSmsB?kK#%I@5)H!*=qMe;EA?V{6U})s?T?OOHAyu z5ukmTe6WS`NJeUO6vuk7JC9|svfy1G>d8a%a>Zc&62g}YV@9dov z)fledK;cU^RYt?uJS?+jg|)|J9!6^?xO{tQsHMsOK+vTN*Q`dSL~}jlEN$c{47i}& z&@$AZnzEC5E28C49;s~$wY7uf(eH4^XhdrOvldHNYgAVd@5m~7brO|q84S4|nL1o5 zgCpzJ2lNTDJD|k^d0>Mrhxt?I*XT>Q{Z*|hufUQ5vYmJyDVueMWR$qDhhgAnY*#D` zw@OlndlXs2%JquTxAz^+nbt_pY^;(J~Xq$Fy0U} z;#NzlAvPSmzG6+JfEAICau1DJlnCxmyv31jytA*al7Y4oKAQ{PA6;t`c}*-0YfyvP zZEBe$kcy6y&{MKXqPni=KT<(**b=R&f3kvwsLG4^eXOPgEmD!Oaa=E~J+=6ER>0wB zKIoS6`cnS}Yo>D4D%ksIR{JR{n8KD*1>V^iTPYjWOGct>wp%svAfx(%U)f=srBOwf zET%-K($vr;vIG6Iipq4-YQo{V=sIfj-!={gy;fdXN*&LuZ>7IJfb&*EmHAsw_|0&T z{H4~Hz3`#M)F5#Mf$EE>$<<{CS#g|N7*)+RS{`agy{=L1t5&yKu-MD2XMVKWRuo|c zX)P1bu$>$Y2Aim?tt&Mta^%c3+L*K~^a%LO2bX)I>Tl1ncT5zu)EWXa98V#`- zQXR!}4~|p8+Svn;W36pNJ4K-e4F;P$B&|$j4Bl|I;<8;f$_slSU#+B0V)nAiSH3?0 zGrhQzDX{5$6t?hSg}UF=2!csE)WU7G+(I`kAQ$tY(vFCa zoZy|knUQ=TNNYU-3+NAP%4e7D6-cb)@^A2}*J!|j_Qle}3cBbe=BKL+B{ROjycbXd zHdCj1fd$@F!ET^IP3w-5_ae)tlH+rz^?gyst?(71OLtoYm!Bn><-2C(j%vZY;t~sd?H&8pxb6xB5~6ZJQ$;t*clEQvtCgX-|rIVh5*c1xyNMj|{APPUVNj<U0kj#VfhMdM`&0ULda1 zp=4Kpy;Y@)6lWwpdR7-{u;$Y{8VGN{M}_nOg=R@N9dE7VAmd#o=|TI%`An;gHo{Kgz$mcjIW!`!;wjiRy&L?ONEX%S2w(+(YlSwv0N&#<|i!=^AMk0 z-H2n;l{L(ulR%P*%vJ%y~V5wU)libA<^fE7* z0RlvorYOL~sPzzVI|J)DQv<9&o>WR3f@`)9l-&guC!wxBgIj0CVJfXB(H=w4EGL-v z9q^gY%xh=v99Ka0qS%Z|yw?7ro(YUO2<_<9?p@T8?fg4~;tQjKZv)MGQseXMUTX4i zs_RVLvpQ6eJz(W!R73+COf{;{9L;3a3sjrdf)9<1AUs#kq{fn+$9Ev37xl~k}}PckHp-p3R0m6}@DUdS~&0QcBO zlsvZ9+8T#r2C?-DtS^6{ITb1zS(E{tQG_fm4{z#1M!HXwJ1;f;qfS7G%6f>8WRZoCl+6R@gkLod1F2ga<`?_DpYkORy`)KhY ztiu~A1%5@PmW?GQwvjUn!2D(A$6ZwiH}J&NQ~IFK-+>U`I)w@_PufyNLUC0(f`4yt zZx(28oD_5IhI`J}M^;YzNg2Gb%P`CwaI6rrDhk+n!|iSnOA_y zSs6U)M>Kv$A70h8)W(i=j4o{_ zcbJz6@*MQMihH^qXYwfSa8!GQCQZ)V*VT(utct{YT)iv7MDSKJb|bavrL|hY~N#__Ba3<%!UCaOakI7^gs!8Wz`9 zz*UorpEP6E_rj{PGDD8PR}j>BtT{B3E~G-<)3GR+4}eAjF! zl7t-lhDf~&%c&#vS;y?$M;%zq7?^xwIc25bmkBi{`SMWmSrypA1#ql4d9ai-f7A#1 z!X^-x@9YDW{{a!b5_ijCO7pC<9JI%FUC*h9E2ir-^}LA;WW7J&T*tGvI>HL#=6nF{ za!VRkv_zA1!{l^1MtY^bML8eE8ELlkmMz5>lk|Cn^i<7OvL+X1Ih%W z5o*!rct|8~!=D|>ylus6$^EFRk%##wro% z8*w1NGLr!|j|{8L{1w$?;6iS6)0fxaT-3^A!^fm+{$R= z$V)2;TS#W#iKJ<~=Mx-Z1@&584w9_KtFJ0IdA%+75S4n}4No8nm8UYSdYq-8HpkP` zvPrWzD8CmLq5(qk-OLeZoHG%XuLJJCFdA- z3V3Z?yQtA!7htImWF56@F!w%+9LNj%@pkn9ji=~0-N{vj^~na-ufmP5f|f}M7aEOw zkPKdymI!vbG#~UTapb}MN0ZKQ=w%@FC$#S=`wpIL;2P+Xe@> zCHL}KW5_-U!6Ru&o*x4hK7q<3sk|d#1Mzh(>Ms@u)0#RMn}{5Vqx1zP{|aAyJnI<9 zYcZ%C!63jUIz&g|>@o4`22#O%^@?0TiJnI%9@B)}dq4b}n?%t9d`>z|RMEkB7wb_U zXHa0@(c}xM7H4rX@6b#1CTEx89F>J9G$Q-sz@c-({Jwyzt#Dssv5H5){MULzztE$r zK?G-~qgc~U*hiu~j%x=oyB*w*E6MP3UXwc+!10H0zmxdFABoe8RL_0nY-ZaJr&uOl z@P~Y`=hT*v)s0RK@RF(YIpQ$BF0B3owCG5*$2%FXB^kp=TZ8xA2kx_OF4OVoYD437(sAp^N zC{7U1(X|@>T@2iy1VqF^^=D@C<13tj?d4_`qB6I$z@G6qB#W8rZ`@C5bl4c44JGCsz9~N3C1meXMD2S|aTqJAzg zcLvwWM>oe)JYA2;v8yQ0n)o^IIsXQHwgq6-#};(aDtLAj z_;e?tJ4~Bf8JlYB?S_ogq98^loa8=qO24BQzrz8Bqx$ixNvw5K4$4)W+8K2Ik)9ntWUgPECg@Y-`4Om89u zqnixR9?Yvv!SRc%a&)R=4jgPcPN;?0;B{|UYjS*tKGd&%%++Y{ejwO)9A?y*`h7*R zkvWZF07DK^*EWGp`OvYU{JaSYh0Ax?{50aGBzTY*78Zql9aZ5V z`_Mv_+M(`S6^phKRyfqkrFQL<6Wmjz))jtZ3{BZol>2SYIbh#$$W3YD!T&owz z_*#-sNxz^|uh}%c4%?hUCT9kja=~k^6O94XhJqFZD{+xE@4?hu=&BUf*TE=OVKTV5 z8(cqtZ+%%_ksW50V7MRkgErPA>?BEq&p(YBOJvD$Mc&{OC#Ksxmil`Ue<%u=@Qu|< z0Hb&Is6>aWKgBgoY+XQ~MRZweX>#1tYhd~j`dN)6Cw|8T6xAyIjk$^^8$tE`+)qAu z@)|JwJk@Cq4DN+pl#E)J&Z07g4Z0i0HNLo9+lh)RXton_8=hW6qH@3G@C7cyRKiiQ zPjTeq!#F>%BjO$z*MPpjTcY$HU8Ih9+HUzu-oA!k^mY7v*y~if)EiN6r)(JeTP~6B zJE+w@%xxmp{u*_yCVLwOfQ+#jSxxq%bbxUcB;s4(Tpx!KZs6E(Jti^0{*kx{*Ff>b zni*Fhj*D(3Zd+sgn@Lty*>3|kd`wR5C7Kt2+<&PrUB@`^LVA0|WoO1X6X)hMQRWTq zc%ete%Tl=OcQ90VzM!_C&McR_wh3K@caQFx3EO{4ybnh67GhRDSaVP*vA!mPzY*i} z>4=1Z5>c&=l}2U8vgWM$NOF0*EI{|>gbnmY-?o*B==aBZR-7K&4C-wv%Wr+DT}$EY zS>ZcFQI_Lb*P&8{c!;GURlN8;d5PiF4#!Ai@Z1Mf3;Ut}X(Ba|rf(gM6^798+*ltxObMRC+>I&kkTy`0vZ zb&xe8HcRUe*xW7DQxw;AYQZG-T-?xl^zlxBy*}vGc?NO)9ci|s%W+?-0KNqc82CAV&0=ZS~AiLQlGlh6T}%yPq`GCJqIuOAlzvy-Kgc- z32pQljkAFD+XgQgNQd!Wq_5N?hbFME zp%v=u3C=?!dK7D@sPkCo*K}Y1(doFU37E^q+(S~>!hEX+L;npIEd%54%vuHGD&@n2 zUS@Nn_*oOzU2`#Y;rm>a! zH3t=*6~A^HygUZoxL5dT7xf!X*Kb7TD~$qTl%r}7XHJ93sfO%x3Z+-jiP${icnaKs zv)d}K{*IfrUXSDU#G$$!q{He|nos1E7bvW*J;Z!seAHl~Cnojq3<`J!eTwut2pzQ% z#-P%UI}M;qR~;vJH$AN}%u{!*FK1zRBT@dbbf^_a$t5>`Z7%&mmo6Kx`pp6PqM=O#~ z(Lk12xK6iO#SB&j$1FdpAP2iA3ZdjCbFZhVF6vr=mPAo z<`&{eHMXa)wypHXGg}CJ$QOmyl(}6Ghxx{imU_7A#Q2UA(;vAj2cw3edETP<8#2ZTDDS59 znQm)8dK+1ogY znYtL$D`^Uv>}PHoqBNqyM_!U$-KdZ8sblYO#N(i_zmqq8)eldlJcwC=eTlQsMQ3qO zo}zHi*k{o954x&tKo5V|M|ybY1-Nb{n6n3d%VGG(Tis`&sK{9ML@VP(wSaXmVTCv2 zW+cPgc?Mrd#aY+FseI`Qq|)eco^r+v>2h3}jwqYYRF|prGh5-B(RF5b$wiAw2QsKb2pg|#&}(ds?AFGAS!jb46LgUtG|!T8%@QZ zjSrgx?NLj%TV9-pZK$(^Xp3byyk+6*?A3rT#+6P~=R0_HY3XJ~w~pwBaQe$@VKQ-C zhvBYg^*y^S|CT}G>1ckcO(w1#Q+J@3g7N7Rp>6&~&(D#BxCMLAR;_X8Ur|#|pmmgd zUx~lBT(ZDQ(xOy+;3a`Dm3SHle8o+|k0}SkXhap=hzHlsURysajppN@7DYd0fxlg| z7VKvXg2NBi1agEbc!(ZIN{+iKh2g(xxzoESnb-7La^sKHK#9d*4ll!G27!6)=*Nu) zE3eZxKf!ve#sR8k={1&(1mSy9+YX~ur&18v7Ae+9`d2Cw~bYT#cydMYVX(j>H3wa{}*9fnF$uu5ZQs<-{9G zNw)sO-iFR-yH!L~T<+vN)$Rm!?u0D>Plq$E5mEz(Xek}Gy;@6pqOY21M>w`8(KZ)l zGX(U_g-WTFM{+iR_8NoCNjDBS~O`FY&G#8jb^hk(At^@bo_*~ z8?I{@*?j8s2preUctf4g^_}1txj~(W?9&V<-q_uQl8*@QvwNd4yUn^#X9{aOTSpz8LQHo7>C=gqD;A2Q zKKr42>r3`mc#`>LsMcR}s*RJ(DEfgC4Ie#>E;75c^qL&P{X8r$>151g@69(DNpZCJ z4jHSxERY>kFYta|;zPU1qc-UC=&rMt9R4~)pMxcXQ2FJ+tk*gOB{m;tv?v*MNGjtQ zROU=+(b~ts-j!6is`P*2pnx-@L;v7hF2*zEOjJU)euvB3CBXYnc)vY2v-%fVTW@Fxp zfKjh#Gp1m-aW{wOYa;dt>~fS3nH=4f3b(7WdFc#Myv3d%Lsz>8D+-oN=z^K3^`j`x zBGfEDt%4@&M&;RT$E`A0yjPFn_zuzhXf`+8?E<^+@)I9d?I@0r$zS#Qx`DoSUxR{?WVSsuehJ~N{= z)f2zEGW^AdIIjhk?9nb{`4MV&BdYfoc-3W8LOSCU7S#SmRNpmpvg=uYwAv2veJ-pk zP_pB+kHr(~Zf#hfFcTC(75PN|rjjul6P+B!5jdH=)|XmPoJj4#NVnSubPk>oeDe&u zwms=RbdhAR@+aJ_8y(0<9#DV)KM=-X%NrkCT3D-sC8ZDRN3 zRanDR?z}3U`p4+!zW7%0(J1L*$Q9V}m5we@Eow|>@ar8M=ncKNJ20oZ%tT$Hp(=cA zJpA<~8Z;qQF{P~I=yEt#)ies(ot0VHr9RxxG5qA-)PeS}gx|sPcA!8RIPM&@<6C@z za>P8JSAk(Qu^{wEMqYo-KD1Fd5q;21hlntfm?+9b+JXA)hH(^tH_k<6ETIbjjf-)C z{_7~5yF2i?iD1uAG)@zg%~$cFJ_M1iO{m|=VaAE^B9hn`*yV7vRdX<~G|rO`9R4nm zx()SO6wK;Qw_rJZXuf_mq2ttnH7^Ttf5-h|_YNJAPV|RP*h0{=EBR87%Db1^eH<4A zUyk?u&I&9-ttMsmx`_)E&qIwI3UWW8mKTES#<%Hk+x=9uKIq+YbWx(RI+d*|s;E2j z_>H?9PA=Uh`!2yR@<|UED|=Su9aZ`;Gua&_w$o;TZrNosDrlfRq`HPu&kM^ec>~U5 zV*kP#dhzVorrKT5>ZnCOFe)a#aUyHVsG_1#8b}7Iq(&Y1$VeK}JxI%X=V33z@9Z!6 zjqXl=9L};}{&AQ>C48@mGLRY(#bvJN9ayWMx>xF`iX18^Te372w0TNth6pJ|fTH^XOO6WM6;XRc$4dZN0J>Lb_UBT>k z0l%`c2SlhrH^~Vv*95D;p5F5)(26LMPiUxp)UhXM(iC(>qQKr@Fz8!$(&`{8kEd%H zF?gBG_hf#9Er4Coxu|7bVU0uSBt&yuPz}ZY8Su3R?t!h~j!ceXEA=hi687ULbC6!yS{6 z)tSKas4&rZoU0hzH5yg$Dm>VWwYsh?S=V7`-|S?25#GC*I#vvRl3()T?WBY6yZ}|l znNYi(9X1Q-s_qA|@}URwqB>qP5_5G&UB)4Hzgbt-A}8u<3JmWNRbe0Xp%^n-nUA$n@D z7a$4_ViTfbo|Z)kZ$oLMfOY!mGQf-QHrvWWob$o#Lply7`@>o%;Kd!pi+#!n zzpx*sH7@jbvamJzJ?Vx&jdlbnaz9TlANVQ&PCQv1sR_8OGN-EBf|=YuxT-DvyA zU}X~6v%k%k9CTDt<3``5hm{^&c?o~=VP(t0AdbT%?s1(lFoP~dPX)y`!*Nd$%Wq*iEu=ikBsDxT3{|=f&GLx7SNo~hpU8_MxE;Z`;%CuJGw7$} zWN(VPPEk3wOH}r6d7+MDpc&tD-v@}^c5uQ{WNZg2@IZEp^hc*0KqDQ(5jqR=@McsF zi|A<8h@1Gh8gq3F@l^wK=x6cZ+W?YK9-W z#X(H1tgGn!p&Vd)lVC_4tRa42TWM)|n1er2=WFb!R>iBVhBtMS+WT4>uwUgg8C09q zi~$$g37;O0uYU&I_{`mV!UlTa0Zzi3U#PQSDE;8HJsgY#2a-_r_EA?7jGTR@%V^$abz~*&1}%j z^m@*~r~U9J=D`b6NpH?po|P$wqW_(9<-^681b-PMUD4{9iMzBmiR}0alSwD%iQG)M ztG%h)3t+j+s3Vi`P-cQMSwX98^rWVMb{{pWPC+lHXT%ezrOXk?{Fa_Z7Ha2H{IAz& z-(uisF#4O%1kf9Jq`%Q`5m$No>Z$POKhTA*VS}{*oz4LuZw%KL8A4X-^h9 zmh@sKmNF~T?}|r8h-mt=2O>Fi^yZ{pg!Cs3+!?WE=mPzb$+YJJIdqxc-si}DO^Ue71qZ% z{C~h{Ql*xsNr4Z9ZZ~ zi^yLnt*PMIPFYH4IwM!?h|i}kPuCT8?jOKCzDjOSU>A*x8C;<$D?LJTaHoIc-B%*-qrfj>fn>*U z5Z~)lsex;=1_c{Pg)b(Vse_B*cXe@tvgi^UW})(g3Kz)yj>ZQnhr@b+cyDJh$owPd zc^|k`7@ev=B_-7(F;((!n8AMa)Ur4M7w7|JN7px_Yj+Yyw-7GwHG0fL@upT$ug=pU zxJ>UcimN4OOpB8^9j;v%JtDeZf?=oru;4qe+xqD1qG(}Xq9X(SnUVMv-{5R%Sm|x7 zU=CcfxYh>7lsRGt(Lr6OPb3>zaY9O?b9OQZqZva#?xw8NVO+SG1YzFnxeaw304uCyNUkP|o!T<#Wbfz!dw~az@(O zrchr`fivatVguMaeh2-yozF!EP@%UmtKHG1+o`8x)Y(V3kkw$njOK(h&C%p!+fr>0 zV@pV#d8)BlCujHY1RF)3JmJWpW&HSG(T8*Z1`UGEM5TV<{ALtAN2 z#<85*xYHKtNn$RyMyGq1oy;0YA1VqN(+u~xGpK$XJikIkDovzMwh(l9PE<#FB6%l0 z)YD*`)#6v_(faw=l$AUn5* zpv%YdDcH%VmlvqQq43${R2YGE`>}30Ksxq)z_Xs?EOx`?+ASr?#;tt*}Xo7PiwC?%V@+xsJ6$E61V-a07hz(8*v$H9WG()RTS8V+PLM0OaTkr^v z;cz_0ax#{8)kG&3BTIY0v^Ge0DF7yQq6R%-pYb^>PENOgbsPha;(;m~;Q*__LgpuYU0}@DkX08?5GnDKp zFD1a%;#M9{br=4`TG+w@Q@G|KoP{i?i7X(}Q1+=Tvi0;R&+$pT1*lvPS4t|^SouJo z>n-m|t?^)sQ|V{1cRHB3{p>*G7U zfvsGvoAn3b?xD^%OK*7q(qu$0W-{mV-3Rp^{(V05yB}CJf||UQOwZ4!0NYbbKTB@L zz8}`{62997=Pnc4KaX@q@r6ij`vcq@2sQ@OJDvp>nSvKvOIM(ze8ECb{Hbi_g3nJN z?hCMTlO!07`Ajw}fOS0~`uEFM7}_YOGU7I#A<9?TC3H_>?l2R(3EeQijqGRGO0RRc zbmje>tvfMO4M+T|mcTFZb{(>-sIG~)1o!BFsp~C>b(v_+1Rt1ce0qx<%%lgHWk0!t znr+BfauHQ^sMzh`vJa@OIBal)zrggax=vo9o@Z%E>dFjoJvu&47gSOk6woOuO9t-v zf<(pHxr;^|WJ_4Jad5j0pr7C?RN|P$^n*U3(5~Q*WVM}S#1b?`fA(1>qJuwIic>is zS|+&%NCmt8XOPCf@EH;GB1ioF9v zTT^59p>TYuP*KqUkLa-M1lQNWR?6emHU%AUUcrYtu-TliGHuJm{j+iN_~oR$6!;JHTA|V6{c)3!jB+ z$@RBnOl(wM2v-;h^L#~J{EkbLfZW~)ulP>X_7PYhn3|jT$w;(avc}|K8JNK_ct{%1 z;teV?Kl4;n8j;&s(T3^Fmpbwnta86BrK-8navo&zJ{+fyU_lA?av9w2mIg_fRD_`l zIMQ3ou*<+jM(lyj6u`e)XJuJwgDGvqY3QTlwKmxL5qybC-OolHkB1`pgl~~m|I~D> z%O0YrBhKIrYE46%LxpV3tkk5oXM|6$r^)qd9-lwX3x0NjafZtr7|cHO*jBW}Zf43KC3Oe}e~&Sj(p0$l>rj$4VK~jeoU%HE z6`hR=S_n4^2gfrI?*`kPfaVxROqaxgss^g0wV0^WF=WJWlx=Tf`33G^E8;vS9N1#cWUW?;$cFnwlaV~;Q6lT76+Y#2kvR=2t^p1MN0wT#oS^!Z+wAEw!ZOredvy@vK1q zzM|Wj6qKxo*O(A)T@~%w9F6%m{_A<%k=p3%%GB+CvWW`V9Xz{07H!lKcpH;pLhb1C zlwm(YOWlrd)0WyEiif$A?w-&^zDJKCHFd;I^+<&_FjlFVoS?Hm-_AL18}Yc1ie5&C zp~3xxU5feuE<4Fepav&`jC^8(c|3|b9f>yU04AJ)zXjtiIG-trPd)|{VL~LI;&UOB z@rI3vIRMJfIu@~HwFsKWk!}T zyOrq2r3Xvvac{+logH=`*FQh3V-e^(6}K%61vC(E{wpS ztYZh*=~_!g%!l%6sC~G%vpMTV{K9cW=y;6+8U$(^_`@tcfft(-Ez<+V62$7K#XnfD zH>h*p!N%AyTlOvBh#Xdh;dMp{q$5j@!VEu3Y`m>Y@PHcfh8fvl2iRxOkgR@UtHs&t zagX|vl3nOmiQC5)vz3B7>w(Ak2}dgO&_OMEgKc76pCh}(*MHa&PNxf zyF@2<#=-8oQWp=`WJgSJ|-T>7P2up^Ewb#+JRl=Inm5L$@Y1; zL)(bUexP1aO9va80v7t=3&m&LU%}*QWXVY_WL{a6A z5uKZ*G7v8^F1_UJu$DN~H~y-V@Hb0zG8O&3%#=_Z6!tQchksEO9+Sa4WIx?PKAXsj zJfh=poD6sZ8jfbZzfgM?qOXtAyC?uU#AdhQ7xFF__0IY0ARCy+0dmsrOJn%bIP&Q( zn(`Zcu4nY;ZZR)espgq*@^b4RQdGB*Svf2tE<+Yp-XG^F1%Bxe`h<14*I8(yGSt=$ zM8Okn3eG!j$2#~WZZb@51U2}sJYZg;m^WznMO)e|$q2)ULoLihoQ6@MCR+fzZNAEQ zO9q4VMA__x+bs|mGdzdfJIIr=%!?d}j}|=%E)9pFJ^%;)VATELl4)^VVsURv z=#muUz6(>$P$)3-3gkvKnA%C4<6-2w7kligfY58ns;<0?osa0L@34byPCtUNm_EeQ zyiKKw$4=nH?6(MjK`w-KxIpov=&BIGo(lqvK<)D7#p%T2Xot(2YyK?%; zL%7g!+|DghK$^iX^WYvAz=!x73@AZIE*5>qOxBX>IRwY_FXPjrjN}k_;ERHuL%uh` z&3t9AWV;SRzdXayUBRrlsFYr;RBRYpS0Z&bTyhm!Vja2a39m{@#T@{upVKO+{(KTd zJw1;{SeR$3v1hD;?Sre|#8sYUxuhUGaRQ%)$cHxh6VE+_dh;Bws=cKl>)J_ac*J{6 ziSj+dbv9Go=8*fonh!qjL!D2}sJ@UR=`1>x^%j^=5KZzI^(r5l;R)!J4iD#VJdT4f zq;QbvHgi%4o>xk`Q=JQebX}-fS9yLp>~oIJ$DND@MlO?1)bAN^lmk@PC03aHI>pNW z!8&aLYrc^giO^iJT>ZeHL$KJPxXUT^FOY1cwIOC2k`dp*iWD#p{;CTecP^OT5E$NO ze8i7nT_zm!VqnD`TYx&M$Juk)DjiI3Fp5=|<>YN6YV<~GHh+%~H!6d)){MOO4%PA; zYV#sBa}K?=!^B1aOl==KCf~3_>?}u|1vBSpV>HxAs%due?V%o}2J#mx>?63%UxPw> zc*BOr!RYJD5IWMA;Cs8_1<%0Z-8gX0PTzOjZ9P`^57yg_LsUS|fWz0wS@Ms&4wW>l z&r-T77bFimclHo#V~F}rOy^$Py=O#ab9>;kJ!W`D=64a8r~MHUQ}cSQXR>g5sY&Irwm zlYX4)@Dd$V8b!L=(!tOJ@R5tiVm!L-aJ{wgnpe^q=i2#{%o{jU6!rm(gT-tBMX&P7 z8+HQW@6Vv4?hn@8A(Fa+It!=^#dN>a)!bm)FlOQk3iK-auc%anCs(uQu%JA0oh$c1 zInL+3>Cp@eK=LVI@J*0xG<|~ptV>NQ(OL4b3qIF37{n?5u0>9b4-I79hutPwF_UeUek&ejeNz@J^ zUe8Ezbarfrb0IJ(CYU}Q47x-Gy~7%e;H)9U%{=^L=Tn<4BrcU~k_%){E#Z z45qZwe&oj`91I6POl8~4hz@haAy{`Gc->Uo_Psa_ajh?Yvk&_j-;s}-iKX1E zOIuva?6Af#_)cPc!BOny>&EjH;JkaS7yipNc*at?e*v-|c3PBuNylM3J(>5Tbi-q~ za>Mhg;GY$fw$$`0_yil}wK;!{*R=)@BbZut3A9=PLam`AcUhamnzvae3)Q<+==R+6YM4fD zwD?48jUrx(V-W{GU_ALW9Zg;vM|d5T=AMk#$1*^@EDDMs3^wb_ydMFfM#7wYV0R}p zk4)#C^-xAW=;kH(v@QAEg3EOTz0-g$LlefHf|n3VG>Qr z@jlF1030PQtS%4+K!=KM&qfp$JL2e0FO{nx*(;)aH}$b5*fxq8a#Q_J%M|cC3~uC0 zjq0e`a9f-T*qCcA0}-ym3;v{jJptj%Q$J#n|HFyfA)rwkmRgj3 z^k-S^cTOjoSw_RaT^FOx&Tx-+@%ArLGgGq8;q>Dt$U@H01BA_j6W+~9T+K5;h`L`jU2Scp>j6Ftce9Tk*%dv@3CBu?7sWuiPI*t%8E zpouzBH(t|Q2**Dg4KP;que6p8N(JUh2p`D*8?~Mbx}t% zwHmdf2)+z1us)#*_0sf~PD;^rU1V?R@-L&mRK_OJd&x&-{4TS(lRb=nH9D##)&Ge$ zmUle+gt1s@lM%siVdwLL?P28ko$jAz z#&wG7Y7bZQmJje3Uv?et0~r!o1McTF>-i2|_!@QGR}O*|yWwTGsIK>6U1wmhk8v|L z(9>8zjk(I_(Br`NW`LG;*vnIl-oFmr7uH9 zB?240sJ-#%7Q}HCBcC^s`=h8SJMeYRQg`BjPM`5CrqY9pqs4JR_}hwPYgKsMVpe3I zO{B5}6A5$aWbJ}Kg-c65^IA>+p~9qrl~=~suLs&cf|+$i6~00fK7n1`Kra-au2+Sj zogi`+nWJpIr4WuyJmzO58PpZ`(VObpl=pbh)wn~QD~unW7cZiPu*ZWspAm-px1@(T z?o|HPFbt*vd)j+BXhc56hW~s(o$sJe=f~XDVh70s)_f}C{X=>gf8Uvi=)@WY!{x`o zMPlF~Y$4}vk|$+wHCsvoR^SWSw%kt8pBeztY$g9|3VZwTKd)*+MwTDkNPs_fk39OO zTVNjT^>-ag#2uqrC4o!vxf>k?x7&vI%-_#rcfdX{C>{DZ37DGBzDQggzddNOMyR=% zaOH_0D=djm?(CskUJ(B=AzAs!B)Z~Oz zubC+Gt6Ja6!QvNF!^e`()6vbL#A9J1IGjp3hgv;?S>8ltD+j|mM21JBUv+>T;Sb@= zN8#c5@zvVf2ry&@j$KLcu%?`Zlb6T0yQ1q^@f;dr-muy6+6iC3Bg#%)?{Mjoz%5(0 zOzVkV{r~frN?-clkLI9(psXSv{;-{&kN!V@iTD}qzy7z9Sd4sP@_#)qaG8HU@#^3I z;rD}ledMcL#PeAqzB}LU|N6~v9{>BX4KD9II{x?5{O`#B=NW-x{(N-#@k?rccH=8H zBTLKA4176{uYARf`0YR6ivJpYoQNkM@x3&v%K1yLKOfF>kq@sQKaZn}1nnmDts@`F zSyORp8IOP;=gf@4l^?So9lQjE`APuW5ja9jz88WUJCCINF1TUN_ta!)XXh6l{QZfD zM+#n9B;)!0G+*qTl{5T|Pd#=X^&-AI-x_gT9_oM}KXbvM7yf$X=P&hn<$oWEBc5v< z@%=C_CPiUJJ_>7DZTmlmXH|c=^s9(j-6n~6bpxu{d3f_x7#vt275?WcRWw<|5zaR^ zuLVZ@uRoP)|F7qrU*iAzUm}j0_UnHFZaMQMatN0?J$ta6ns$r-|NY~bWXz?A;{*si zOQ<+P1%YeA?gbxIU|Vnb&fX&48A5CX@jquQk&oUHKkD%R4186J_+M?lKZ*G5L&SII z+pJ%|C70*Y`q%&d{R`cMACDZcROhb-r{t?E&t>}Yd=vTY=OK)?DAjk0%!_y?3;5_f z8o@vK%h~9WXfT>bjQ0y{)Ok4S&AG!l+}rwyXHMga{Co`Iew~=!OFT~ItW9}gSj3AT zU^zb@->FZ|@88kWQ~5bURz}3U;4nFn{qu40=P$p0Hs-ej_6VQ6Cd$xx+~q4SUwz~m`rW0QohN@i@g;6hP(!1t4UrNSHR#m`njIsOQ!Sgl-*8r5n@c;usY$P53F z?jGJB`z9FtPo3_rU7?{P3xtLS_G}#_Rf4K?tJ1y7^eW-u9QHgqr}&>oK-a*aCS6)~ zcg{At%9twu^YYLCI)?>z=-x@H%&RiL%7Q8(u|h-ro`i z=ko4(8X5}zcIwuyT|kR2fq?-{or5C}JJ84@V~9Ie#*p$cMkWdkT^Rb~R8`(r39a&> z%17s-{_c?e9^T>IJo4^&{u5OL{`+*!*&+@LDd)K`G_=U!ZeE8yLqkKmHto_@e3Sd8 z@J;EP$~UzyhcU3}HL7#BArGJbyanf|9}5uii)#%& zCm~0I_wq|Xz<)D~h8cOXp}xa>hx?B39T{;p)+>Y+;>z5Ob5NHw)oYe6RZ_nF7+HAu*nJb3SgV;a zB$fBkelfz%gq@9|GPruFvK+S7cb)Hg-@knS_Wkd}V*Wa;X6@1?e@)2|--uJ34?8<} zzYfOoy6|ISI9u70a@F^m?{(iBzBir2Vutw~Wwl)RXld z=byOFj5;{#{`u#1UB^e=$PinIN+&XYEd>*@p;AaA&#^upC)0F^2s$q=ObB)C6xcy_ zSKm{8Z}olEIgFI?3Mm__$e|!7MjT}0u;vj*go{hx!=h}5i zLa%M1p<7yX4Ge56Mg5BTP4g?^S2E&k|2igOM#%9NEdzs^wQABu{A&8u@~iDfb~^E0 z_g8p3H$VbL94CIQ{M!4q_G|O=Y~hjD{B>~TQIT(PzDL}tIiM6Cqi?M6ve82tL?2Z? zymiNBK~53>`QWe(Wk>lqQ5#YjNJ0WF%f>)16={Lc8D^*iTxKH?VK z9J8BKMlOHI;pZ(R@~8)X5B(nbJ@$L@^G*TPD1-k=&^OwT2?~fj?&r`VFoctBC?0al z8T{G%hlc|pp#eRAT(*XDWO%s0o6CXA&tw03r}GPkwP@F^Yb&Xdp+?3UnQHtxERw?h zJeKHf(mZ16BcF+wUMG;cdwPG2fVf7^3lT^8PxYVXKiz+Z|4jd1hxvGwEN0RrCR2F! zeptYdv#s`Dl7Ug6!NuaoNQnh^D^ouk|(+$G(m+@;-RoWqEm=-nKk zoc=t@&+A8=%w5Y}+wJdmyX*Y#*#`HI9^I*O0adD1EnllzDRH-Tw{y3TINOV~{%%h~ zGiB6}MqY!zrteW_V3j()wX2jA_W<`mcd&bq+keW0p?iWX?EZLuc!WK29hnk#-*q;? zw{q1|zU5?+d$N0qd#ZCb(#lzOr_3Mn5NG22p9Hn<)S*dxaW8kTaIbW)`f-?tzf*g| zBWth2in?`Z*SbSnaqn{PcJFcTbq?E5D#YJ`N(Tg;Wp^H3gSs?p5+v^P?hEdV?n@D8 zbAO|tGXBeX_G}FeeYb}5I)}CDBJL;dr|xI&=RYqxs*z{dA(fzLt3pGAlBV6mVeNok z_jfmuf6kTB

W3Y^6?sV=Udoe6^`M^|2ixpkcc7=2lyWnDIik&j@|#yv-x-w@$u~H`JJ_T z&N6TeNB)Q1GPa0-BrH9Do~_}2324@;eaGhibBC64kIuhVhy>_jtKd#A-h_RUiTplcF`LMF|ZiCW24~RJ3 ze;q~%50A}!jPmiA_LF%1&rv_m#)5Lx2%qq9kA4M4`GhkxN1^?C{1}^m#K0o%gj?|5 z6HudEsVZgsYyCRz|NbSwzj}>|Rcn=t0CEoDY?1hO*k=U^=(D=|b4RZ>>)0i*U0{n} zF%ohh8~iTHm4ANK$cWR!dz(e_-pH#(Oo*3%Bq?)hU?VSwnmLF4`-DFU-VYAv91`VI z_+SomxN+pE_|Dk~M2A9K#Grn>@bj46@nFKyS~!O}iv@<*^Tfa2ERhw9(fxQTVr(qd zVV{3OLw}SnXi_uE$FJLryr@%lJ<~Z*)7>NN@IY}GRlxro$Jru)*K=LbpKIVuO~g?h z0(<-%#(xg0UmbcB(?cQxF5LOiBF0Isyhrn%BL)9o<5nNr z)^**VDVk(u*>TdWLFGn{*I4bM&fBcE>*@rxVd=%*7)r1tDoPp=6h%p#D3X1TqP)UU zzYux2DB{oJaub{TS(2Vi`bJ<5gqu!s?@vw|rZ4v7?# z!wxBCa>!9#rZ~q>)|Em}hKqsob$<>|{=ltjBK6xg5KMRMpl2dhH6uS%@P6v%OEb;Y zL_9N?&Y#Q`6&7trytjO)T3y;};CG_`b$frMw(k%VktfXQ^g_V67D&{l{!Lj7r?N;G z?1O;slI^$rb{tqpbsg%_XR%Gh_X8{2qHi_e8l$6hugBsfq^0|E!F5(qNBqcVSBP?Lnegnj_ zds8FAez1H~Fjz{lei3$Bfe!6WJf6cAk$|8kknAIO+guowcFDyBC=8K|+m!|zmKfHO zg%Pfa*pKe_Dq!|$L$qtcM~e<-bLk^BHV(d3`%S2L(xnv!{xyx2V|4#ILeDJ2G*}idSiPkMR1@N z?=?@r+{4t@!^f3*4{MD!*LK~RG;io@TxuE1-xUZ$X+98Zl5W}LGuVCIqS5k9ui zU`8J$!aU5+E*&_0(<44TN6_nmVG8CRm?Iz97pU?~#aX7U*=O9I-a;kLNR8;3Z@bY7 z!9*y9GYTEITsD@W=Ugfag`_oS7J%W?v%>+eO+q4$vX46egF+79TxwKsqRa8ka%>A{ zG6j=c)Z9#fsKrC(*I?wp3~6kr5(E(tOJ<9iF0eis$wv^^^n>Yl;;$ z+Uj>^!=1G+*NTB!F<2WO^Pp&^&<7~hCIYqJC8AtM^wMH#uy3R@vTRN*CWQows)N5` z45qV5cbC+9r4tIlK59`T`{MPdI=}Pp>gFGRXE0Op z@FN(~;q}Ro$1x<@I=YTO)8;@ey-~S?^n!v}@yo`$D#6-gaW4!p62l@4d$hGy8APS# zbkSXVP(!L{_AMPi1XSKR^I~A;g}RwBqSk%#nfC6E9;V1lVMB~qkRs{-Htzj>wfgyM zgX50PvSD$v9jkzae-za`N|B6Ls(>AK1j8F2ylMG1G>4 zQ!k}ge8S4=mR?6F`Pc)7rN=)h1j6Dn%-(DgRo`2NNwWYoaN9;sz+7@Ph51s*f1U{@ zuc{-P8|cyAWSC3L+P$2j+VP+RyRU2>a!jq@lC!4ZCpVPI4Gv{A-F6><_5ii% zwQh2hs9j7?hLj>|lc7b_RQ>q^ALkGsXK`e4qK9-uQZ^~Pf*P3iQveOoMq2LHubgf+ z7Com=z^2z4C?kVb=T#Bg&a2>=l21LTfzT`&-`NEdSC(Q>93sQ4$Nm?BjccxNAlb~P zK@Hinq&I?1cxw*RYi*Wn!DBP(KP;;M`1M7=WD`O&HNS*I+8-=GK)-qeY$O01#D$O} z3&EbaKdhK^P>T6mz`Q=UU{BHd1k`W=<-$OX^DLN#rZ85u@w_s7@JE!S3?+;19B8J{ zZIihViu=O;a4%D0q0X+bWgCD+M*zMde4Cjma(>6yN7C^}?SesF|5aTQA z7KkIOpsa@}Thz!nL|P_;Ph)K>pB0~g>2?_BAFzT{KgMdor)ufpj1HeQFq|3Gd`{D0 zLB)9oHk3z}iYe>?F^bxZpSzRAmCT@)F4AQ+55Q2tUHNT}uc4WP9#Bnodh+o~hC1h*Ndb{GFu()+WjN zk{MzOPxaCxXF_yUsXss=kQ$8kJk!y3)SW33jvnmtHRB@#mm~28qkoSP+q)~;b}}xZ zl-A1?C&hKYtVF%U6i}l|wtqx>yyOT**RQ^j^#zx#w+QssdYSexG$>*Kec>idF9s>hDnR>ht(U`mMhCwqtBk|I&svIL7Dn!ufEr~wt8#z-rb*0 z{dn){ja{$5jqGE44k#O%TB(80YL=oOml*9g9}Je_Ry7*+@RYvbc^mbL2H74f1ui_c zb@@za`QGx?%3Xnu_IPmw!<}C13gnhX^jR-gG1IH7KU=*nW?I>`if=@p^^$WH@(WoZ zNWxR{{S7Y`-OC`EslV}<@l)K*Y~J~6g5d_r84iq=^hN}hAE0WLU??3sgJFc&M@M-w z#J5Zz{s6Fyj1#cQP{nTc5(LIZ-7t!t0A~K)_7r<;l1f%&PW1KgftJuW0Q9RasYjV}0vZn042Z!8^n zvNm3z#sq0VHdLY!UpE`!iu;^kj{JD+!e+fNO>-)x0v1P-djwhfi=U=zPvuMl`dvCt z#*Q6zi7OX^&2?epiuT~@FPiIm1Lz=WekI)eN@rWUA7(t#a>ZEi0t@-k^mf@WMViG- z*j66FB%byZ1gz}9(0%zbeM1)&E>stK+LSi5wJS7q|Gh zQwbCUu>U(eo;`T}sUKAV^M_It(BkfFFZ_%MrDmS4eM|R51T+O)=p%AK#1nA47<4V^ zw@9#-tt+B0%c&vzP>OY*1^0kNoo} z7w-d;??<2@z(l^F26t}OkgOa1TgEr0wKQ(drR4&QcCU#`IkF9Qa-^jvJjNF=5tdQO znu9oKCSqt~+l|B5S$-!srNv5kos3W~-8rvbl#T+!+#Km6YQM562Xsg7vWMiEo0zlp+iopYiS@ng}GZO6LXpY3BP zUXGWYI1HzdW)OCc|X{oYsY!9n#{&GY41AO z6C?uDPf8WZz3n!7z*!3d_J`YiR#SLx!FUG=?wDX^J zag8Ob7hi^k;T(>v>W%9k8dq;7|00+70&gZC-~5jxmd861dLcRCBs|tRJw%1I&xB!f z=B}ZJ7`hN-lw4W!QnCLhVD3!q=e}0~lVSqj=hlBMm_v^BHeZUkJCcD6lS&i!C#DFP zL+le!7VQ5gTgk1gk!-LI&{i1TUd6E0>|4^kmu-Myu@=MJIYf?xt920{iY<~KhO3pX z&K^&2`FyzLJyuH7xogJlxrO=3z}%H{7xm0=E-5V*Aa<=r7>QlnYO5tPXw7p6Qxf(R zw+6=IQ?=SS%B#M*8p$@j_9bk~_`jHqI4opf;Y)PSDYZ5dlDkdRUN_w8yALI(HMoU0 zE3?##1vvucQx8?a)U#+uh2DbHkE9pe?aNa@DVr|Xqyd6 z0LGWe>|)$a=R=Wf(3%_#Fl)fJ2ecgQlJS~EqpES0^`>PdcPdHkc?)VeY74UmnA&T~ z;=`koei$ZME}p4i3iGy(6K%Y8<57cQQiqlgcK9OYfN$R+m^=rDQS%s205Lqx;qRy` zEC(BBi^hxPMB2vfBc+I5SH`cRR*;LOObzC=@)_rw^ae2QY_lKQFl&|S*2VoU!P3&H zXBbQN6Jx6>Y&W+7CX2?hL44>+bR^MlRQ(7h?ISS-Y@`FW6ylX&a@9e|)*qVshQbYt zl|Nt{Fva|+`&EWfeE{VPt^iejojzok|C~lHsT;V5MI=r2=zBOl3>$ZGpoSuhfT{Pa zJKIYH8!t%l3NaP>sO)k@QS^zV97J1-MLl^pcB3nh>ML+sujzk;vYMM!5R6kED=6s0 zenZIBz-`eIb-)OL!{9__bZ{tnl3gHCn+(=XM(`W$CKcZv1S=FI zn3#gq-sx_W#L2Fkd1przlbU)T3e534Tf6$wr5u=Tnu3^Z)_Ns;6+j_-uPHj zx+i9%8aGhRTmK36(fSo+1jZutE4n7UOp#VVxwYa~YN(ezwL_VFaJJ;@f`V+M2pBKn zg`gW+tdiA`WYYu8b6;d_0jolr$qk8K7@8>=hIgB~kXJNy!M0IyQSv%K+DJseWh}U& z)35uK%@MDFVTvbavFv}NtY4?U*Fb6N_Y?6`$DZ-R*bH)Tj6KDa3-cSfmyU)nfHzP0l>=UG%zp zd*b8xzSBzV%7U_`=mEDLfm*y5DJLgxNTBPNnx99G1lYC+-wQiPumSh%F+D+T2&E3u z#Lnta6oM5bbLoX`Aa>wp_km1aPvu=(1K2FlLgpD+de~0u6@tnA5P&s>8Mw#j-;2uB z^83s0PrXMl)ROXc*TK?5mNc$1=pDi2SVS-twaBGLW5HNv#so`$YdmAegGBDK-9 cyG2O0P-TagrC`d(!TP{6(?@3Cur3z=7nx -#include -#include -#include -#include -#include "BasicBlock.h" -#include "Procedure.h" -#include "dcc.h" -using namespace std; -using namespace boost; - -BB *BB::Create(void *ctx, const string &s, Function *parent, BB *insertBefore) -{ - BB *pnewBB = new BB; - pnewBB->Parent = parent; - return pnewBB; -} -/** - * @arg start - basic block starts here, might be parent->Icode.end() - * @arg fin - last of basic block's instructions -*/ -BB *BB::Create(iICODE start, iICODE fin, uint8_t _nodeType, int numOutEdges, Function *parent) -{ - BB* pnewBB; - pnewBB = new BB; - pnewBB->nodeType = _nodeType; /* Initialise */ - pnewBB->immedDom = NO_DOM; - pnewBB->loopHead = pnewBB->caseHead = pnewBB->caseTail = - pnewBB->latchNode= pnewBB->loopFollow = NO_NODE; - pnewBB->instructions = make_iterator_range(start,fin); - if(start==parent->Icode.end()) - { - pnewBB->instructions = make_iterator_range(parent->Icode.end(),parent->Icode.end()); - } - else - { - pnewBB->instructions.advance_end(1); // 1 after fin, to create range where fin is inclusive - } - 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 != parent->Icode.end()) - parent->Icode.SetInBB(pnewBB->instructions, pnewBB); - parent->heldBBs.push_back(pnewBB); - parent->m_cfg.push_back(pnewBB); - pnewBB->Parent = parent; - } - if ( start != parent->Icode.end() ) /* Only for code BB's */ - stats.numBBbef++; - return pnewBB; -} -BB *BB::Create(int start, int ip, uint8_t _nodeType, int numOutEdges, Function *parent) -{ - iICODE st(parent->Icode.begin()); - iICODE fin(parent->Icode.begin()); - if(start==-1) - { - st = parent->Icode.end(); - fin = parent->Icode.end(); - } - else - { - advance(st,start); - advance(fin,ip); - } - return Create(st,fin,_nodeType,numOutEdges,parent); -} - -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"}; - - -void BB::display() -{ - printf("\nnode type = %s, ", s_nodeType[nodeType]); - printf("start = %ld, length = %ld, #out edges = %ld\n", begin()->loc_ip, size(), edges.size()); - - for (size_t i = 0; i < edges.size(); i++) - { - if(edges[i].BBptr==0) - printf(" outEdge[%2d] = Unlinked out edge to %d\n",i, edges[i].ip); - else - printf(" outEdge[%2d] = %d\n",i, edges[i].BBptr->begin()->loc_ip); - } -} -/***************************************************************************** - * 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", - begin()->loc_ip, size(), inEdges.size(), edges.size()); - 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 - { - int edge_idx=0; - for(BB *node : inEdges) - { - printf (" inEdge[%ld] = %ld\n", edge_idx, node->begin()->loc_ip); - edge_idx++; - } - } - /* Display out edges information */ - i=0; - for(TYPEADR_TYPE &edg : edges) - { - if (nodeType == INTERVAL_NODE) - printf(" outEdge[%ld] = %ld\n", i, edg.BBptr->correspInt->numInt); - else - printf(" outEdge[%d] = %ld\n", i, edg.BBptr->begin()->loc_ip); - ++i; - } - printf("----\n"); - - /* Recursive call on successors of current node */ - for(TYPEADR_TYPE &pb : edges) - { - if (pb.BBptr->traversed != DFS_DISP) - pb.BBptr->displayDfs(); - } -} -/* 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 */ -ICODE* BB::writeLoopHeader(int &indLevel, Function* pProc, int *numLoc, BB *&latch, boolT &repCond) -{ - latch = pProc->m_dfsLast[this->latchNode]; - std::ostringstream ostr; - ICODE* picode; - switch (loopType) - { - case WHILE_TYPE: - picode = &this->back(); - - /* Check for error in while condition */ - if (picode->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(ostr,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) - { - picode->hl()->replaceExpr(picode->hl()->expr()->inverse()); - } - { - string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc); - ostr << "\n"<invalidate(); - break; - - case REPEAT_TYPE: - ostr << "\n"<back(); - picode->invalidate(); - break; - - case ENDLESS_TYPE: - ostr << "\n"<m_dfsLast[_ifFollow])) - return; - - if (wasTraversedAtLevel(DFS_ALPHA)) - return; - traversed = DFS_ALPHA; - - /* Check for start of loop */ - repCond = false; - latch = NULL; - if (loopType) - { - picode=writeLoopHeader(indLevel, pProc, numLoc, latch, repCond); - } - - /* Write the code for this basic block */ - if (repCond == false) - { - std::ostringstream ostr; - writeBB(ostr,indLevel, pProc, numLoc); - cCode.appendCode(ostr.str()); - } - - /* Check for end of path */ - if (isEndOfPath(_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 */ - succ->front().ll()->emitGotoLabel (indLevel); - } - - /* Loop epilogue: generate the loop trailer */ - indLevel--; - if (loopType == WHILE_TYPE) - { - std::ostringstream ostr; - /* Check if there is need to repeat other statements involved - * in while condition, then, emit the loop trailer */ - if (repCond) - { - writeBB(ostr,indLevel+1, pProc, numLoc); - } - ostr <hl()->opcode != HLI_JCOND) - reportError (REPEAT_FAIL); - { - string e=walkCondExpr (picode->hl()->expr(), pProc, numLoc); - cCode.appendCode( "%s} while (%s);\n", indentStr(indLevel),e.c_str()); - } - } - - /* Recurse on the loop follow */ - if (loopFollow != MAX) - { - succ = pProc->m_dfsLast[loopFollow]; - if (succ->traversed != DFS_ALPHA) - succ->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow); - else /* has been traversed so we need a goto */ - succ->front().ll()->emitGotoLabel (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 ( *back().hl(), pProc, numLoc); - cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l); - succ->writeCode (indLevel, pProc, numLoc, _latchNode,follow); - } - else /* empty THEN part => negate ELSE part */ - { - l = writeJcondInv ( *back().hl(), pProc, numLoc); - cCode.appendCode( "\n%s%s", indentStr(indLevel-1), l); - edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, follow); - emptyThen = true; - } - } - else /* already visited => emit label */ - succ->front().ll()->emitGotoLabel(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", - indentStr(indLevel-1), indentStr(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", - indentStr(indLevel-1), indentStr(indLevel - 1)); - succ->front().ll()->emitGotoLabel (indLevel); - } - cCode.appendCode( "%s}\n", indentStr(--indLevel)); - - /* Continue with the follow */ - succ = pProc->m_dfsLast[follow]; - if (succ->traversed != DFS_ALPHA) - succ->writeCode (indLevel, pProc, numLoc, _latchNode,_ifFollow); - } - else /* no follow => if..then..else */ - { - l = writeJcond ( *back().hl(), pProc, numLoc); - cCode.appendCode( "%s%s", indentStr(indLevel-1), l); - edges[THEN].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow); - cCode.appendCode( "%s}\n%selse {\n", indentStr(indLevel-1), indentStr(indLevel - 1)); - edges[ELSE].BBptr->writeCode (indLevel, pProc, numLoc, _latchNode, _ifFollow); - cCode.appendCode( "%s}\n", indentStr(--indLevel)); - } - } - - else /* fall, call, 1w */ - { - succ = edges[0].BBptr; /* fall-through edge */ - assert(succ->size()>0); - if (succ->traversed != DFS_ALPHA) - { - succ->writeCode (indLevel, pProc,numLoc, _latchNode,_ifFollow); - } - } - } -} -/* 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. */ -void BB::writeBB(std::ostream &ostr,int lev, Function * pProc, int *numLoc) -{ - /* Save the index into the code table in case there is a later goto - * into this instruction (first instruction of the BB) */ - front().ll()->codeIdx = cCode.code.nextIdx(); - - /* Generate code for each hlicode that is not a HLI_JCOND */ - - for(ICODE &pHli : instructions) - { - if ((pHli.type == HIGH_LEVEL) && ( pHli.valid() )) //TODO: use filtering range here. - { - std::string line = pHli.hl()->write1HlIcode(pProc, numLoc); - if (!line.empty()) - { - ostr<binary()); - for (uint32_t i = start; i < finish; i += 2) - { - uint32_t target = cs + LH(&prg->Image[i]); - if (target < finish && target >= start) - finish = target; - else if (target >= (uint32_t)prg->cbImage) - finish = i; - } - ICODE _Icode; // used as scan input - for (uint32_t i = start; i < finish; i += 2) - { - uint32_t target = cs + LH(&prg->Image[i]); - /* Be wary of 00 00 as code - it's probably data */ - if (! (prg->Image[target] || prg->Image[target+1]) || scan(target, _Icode)) - finish = i; - } - -} diff --git a/src/ast.cpp b/src/ast.cpp index 03ef99c..bb4688e 100644 --- a/src/ast.cpp +++ b/src/ast.cpp @@ -4,268 +4,278 @@ * Date: September 1993 * (C) Cristina Cifuentes */ -#include -#include -#include -#include -#include -#include "types.h" -#include "dcc.h" -#include "machine_x86.h" -#include "project.h" -extern Project g_proj; -using namespace std; -// Conditional operator symbols in C. Index by condOp enumeration type -static const char * const condOpSym[] = { " <= ", " < ", " == ", " != ", " > ", " >= ", - " & ", " | ", " ^ ", " ~ ", - " + ", " - ", " * ", " / ", - " >> ", " << ", " % ", " && ", " || " }; +#if __BORLAND__ +#include +#else +#include /* For free() */ +#endif +#include +#include "dcc.h" + +/* Index registers **** temp solution */ +static 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 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; - for local expression stack +typedef struct _EXP_STK { + COND_EXPR *exp; + struct _EXP_STK *next; +} EXP_STK; +static EXP_STK *expStk = NULL; /* local expression stack */ + + +static char *hexStr (Int i) /* Returns the integer i in C hexadecimal format */ -static const char *hexStr (uint16_t i) -{ - static char buf[10]; - sprintf (buf, "%s%x", (i > 9) ? "0x" : "", i); +{ static char buf[10]; + + i &= 0xFFFF; + sprintf (buf, "%s%lX", (i > 9) ? "0x" : "", i); return (buf); } +void setRegDU (PICODE pIcode, byte regi, operDu du) /* Sets the du record for registers according to the du flag */ -void ICODE::setRegDU (eReg 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++; - break; - case eUSE: - du.use |= duReg[regi]; - break; - case USE_DEF: - du.def |= duReg[regi]; - du.use |= duReg[regi]; - du1.numRegsDef++; - break; - case NONE: /* do nothing */ - break; + switch (du) { + case DEF: pIcode->du.def |= duReg[regi]; + pIcode->du1.numRegsDef++; + break; + case USE: pIcode->du.use |= duReg[regi]; + break; + case USE_DEF: pIcode->du.def |= duReg[regi]; + pIcode->du1.numRegsDef++; + pIcode->du.use |= duReg[regi]; + break; + case NONE: /* do nothing */ + break; } } +void copyDU (PICODE pIcode, PICODE duIcode, operDu du, operDu duDu) /* Copies the def, use, or def and use fields of duIcode into pIcode */ -void ICODE::copyDU(const ICODE &duIcode, operDu _du, operDu duDu) { - switch (_du) - { - case eDEF: - if (duDu == eDEF) - du.def=duIcode.du.def; - else - du.def=duIcode.du.use; - break; - case eUSE: - if (duDu == eDEF) - du.use=duIcode.du.def; - else - du.use =duIcode.du.use; - break; - case USE_DEF: - du = duIcode.du; - break; - case NONE: - assert(false); - break; + switch (du) { + case DEF: + if (duDu == DEF) + memcpy (&pIcode->du.def, &duIcode->du.def, sizeof(dword)); + else + memcpy (&pIcode->du.def, &duIcode->du.use, sizeof(dword)); + break; + case USE: + if (duDu == DEF) + memcpy (&pIcode->du.use, &duIcode->du.def, sizeof(dword)); + else + memcpy (&pIcode->du.use, &duIcode->du.use, sizeof(dword)); + break; + case USE_DEF: + memcpy (&pIcode->du, &duIcode->du, sizeof(DU_ICODE)); + break; } } -/* Creates a conditional boolean expression and returns it */ -COND_EXPR *COND_EXPR::boolOp(COND_EXPR *_lhs, COND_EXPR *_rhs, condOp _op) -{ - COND_EXPR *newExp; - - newExp = new COND_EXPR(BOOLEAN_OP); - newExp->boolExpr.op = _op; - newExp->boolExpr.lhs = _lhs; - newExp->boolExpr.rhs = _rhs; +static COND_EXPR *newCondExp (condNodeType t) +/* Creates a newExp conditional expression node of type t and returns it */ +{ COND_EXPR *newExp; + + newExp = allocStruc(COND_EXPR); + memset(newExp, 0, sizeof(COND_EXPR)); + newExp->type = t; return (newExp); } -/* Returns a unary conditional expression node. This procedure should + +COND_EXPR *boolCondExp (COND_EXPR *lhs, COND_EXPR *rhs, condOp op) +/* Creates a conditional boolean expression and returns it */ +{ COND_EXPR *newExp; + + newExp = newCondExp (BOOLEAN_OP); + newExp->expr.boolExpr.op = op; + newExp->expr.boolExpr.lhs = lhs; + newExp->expr.boolExpr.rhs = rhs; + return (newExp); +} + + +COND_EXPR *unaryCondExp (condNodeType t, COND_EXPR *exp) +/* 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; +{ COND_EXPR *newExp; - newExp = new COND_EXPR(t); - newExp->expr.unaryExp = sub_expr; - return (newExp); + newExp = newCondExp (t); + newExp->expr.unaryExp = exp; + return (newExp); } +COND_EXPR *idCondExpGlob (int16 segValue, int16 off) /* Returns an identifier conditional expression node of type GLOB_VAR */ -COND_EXPR *GlobalVariable::Create(int16_t segValue, int16_t off) -{ - COND_EXPR *newExp; - uint32_t adr; +{ COND_EXPR *newExp; + dword adr; + Int i; - newExp = new COND_EXPR(IDENTIFIER); + newExp = newCondExp (IDENTIFIER); newExp->expr.ident.idType = GLOB_VAR; adr = opAdr(segValue, off); - auto i=g_proj.getSymIdxByAdd(adr); - if ( not g_proj.validSymIdx(i) ) - { - printf ("Error, glob var not found in symtab\n"); - delete newExp; - return 0; - } + 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); } +COND_EXPR *idCondExpReg (byte regi, flags32 icodeFlg, LOCAL_ID *locsym) /* Returns an identifier conditional expression node of type REGISTER */ -COND_EXPR *COND_EXPR::idReg(eReg regi, uint32_t icodeFlg, LOCAL_ID *locsym) -{ - COND_EXPR *newExp; +{ COND_EXPR *newExp; - newExp = new COND_EXPR(IDENTIFIER); + 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.idNode.regiIdx = newByteWordRegId (locsym, + TYPE_BYTE_SIGN, regi); newExp->expr.ident.regiType = BYTE_REG; } - else /* uint16_t */ + else /* word */ { - newExp->expr.ident.idNode.regiIdx = locsym->newByteWordReg( TYPE_WORD_SIGN, regi); + newExp->expr.ident.idNode.regiIdx = newByteWordRegId (locsym, + TYPE_WORD_SIGN, regi); newExp->expr.ident.regiType = WORD_REG; } return (newExp); } +COND_EXPR *idCondExpRegIdx (Int idx, regType type) /* Returns an identifier conditional expression node of type REGISTER */ -COND_EXPR *COND_EXPR::idRegIdx(int idx, regType reg_type) -{ - COND_EXPR *newExp; +{ COND_EXPR *newExp; - newExp = new COND_EXPR(IDENTIFIER); - newExp->expr.ident.idType = REGISTER; - newExp->expr.ident.regiType = reg_type; - newExp->expr.ident.idNode.regiIdx = idx; - return (newExp); + newExp = newCondExp (IDENTIFIER); + newExp->expr.ident.idType = REGISTER; + newExp->expr.ident.regiType = 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 = new COND_EXPR(IDENTIFIER); +COND_EXPR *idCondExpLoc (Int off, LOCAL_ID *localId) +/* Returns an identifier conditional expression node of type LOCAL_VAR */ +{ COND_EXPR *newExp; + Int 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)) + for (i = 0; i < localId->csym; i++) + if ((localId->id[i].id.bwId.off == off) && + (localId->id[i].id.bwId.regOff == 0)) break; - if (i == localId->csym()) - printf ("Error, cannot find local var\n"); +if (i == localId->csym) printf ("Error, cannot find local var\n"); newExp->expr.ident.idNode.localIdx = i; - localId->id_arr[i].setLocalName(i); + sprintf (localId->id[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; +COND_EXPR *idCondExpParam (Int off, PSTKFRAME argSymtab) +/* Returns an identifier conditional expression node of type PARAM */ +{ COND_EXPR *newExp; + Int i; - newExp = new COND_EXPR(IDENTIFIER); + newExp = newCondExp (IDENTIFIER); newExp->expr.ident.idType = PARAM; - auto iter=argSymtab->findByLabel(off); - if (iter == argSymtab->end()) - printf ("Error, cannot find argument var\n"); - newExp->expr.ident.idNode.localIdx = distance(argSymtab->begin(),iter); + for (i = 0; i < argSymtab->csym; i++) + if (argSymtab->sym[i].off == off) + break; +if (i == argSymtab->csym) printf ("Error, cannot find argument var\n"); + newExp->expr.ident.idNode.localIdx = i; return (newExp); } +COND_EXPR *idCondExpIdxGlob (int16 segValue, int16 off, byte regi, + LOCAL_ID *locSym) /* Returns an identifier conditional expression node of type GLOB_VAR_IDX. * This global variable is indexed by regi. */ -COND_EXPR *idCondExpIdxGlob (int16_t segValue, int16_t off, uint8_t regi, const LOCAL_ID *locSym) -{ - COND_EXPR *newExp; - size_t i; +{ COND_EXPR *newExp; + Int i; - newExp = new COND_EXPR(IDENTIFIER); + 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)) + for (i = 0; i < locSym->csym; i++) + if ((locSym->id[i].id.bwGlb.seg == segValue) && + (locSym->id[i].id.bwGlb.off == off) && + (locSym->id[i].id.bwGlb.regi == regi)) break; - if (i == locSym->csym()) - printf ("Error, indexed-glob var not found in local id table\n"); +if (i == locSym->csym) +printf ("Error, indexed-glob var not found in local id table\n"); newExp->expr.ident.idNode.idxGlbIdx = i; return (newExp); } +COND_EXPR *idCondExpKte (dword kte, byte size) /* Returns an identifier conditional expression node of type CONSTANT */ -COND_EXPR *COND_EXPR::idKte(uint32_t kte, uint8_t size) -{ - COND_EXPR *newExp = new COND_EXPR(IDENTIFIER); +{ 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; + newExp->expr.ident.idNode.kte.size = size; return (newExp); } +COND_EXPR *idCondExpLongIdx (Int idx) /* 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 = new COND_EXPR(IDENTIFIER); +{ COND_EXPR *newExp; + + newExp = newCondExp (IDENTIFIER); newExp->expr.ident.idType = LONG_VAR; newExp->expr.ident.idNode.longIdx = idx; return (newExp); } +COND_EXPR *idCondExpLong (LOCAL_ID *localId, opLoc sd, PICODE pIcode, + hlFirst f, Int ix, operDu du, Int off) /* Returns an identifier conditional expression node of type LONG_VAR */ -COND_EXPR *COND_EXPR::idLong(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset) -{ - int idx; - COND_EXPR *newExp = new COND_EXPR(IDENTIFIER); +{ COND_EXPR *newExp; + Int idx; + + newExp = newCondExp (IDENTIFIER); + /* Check for long constant and save it as a constant expression */ - if ((sd == SRC) && pIcode->ll()->testFlags(I)) /* constant */ + 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->ll()->src().getImm2() << 16) + - atOffset.src().getImm2(); + 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 = - (atOffset.src().getImm2() << 16)+ pIcode->ll()->src().getImm2(); - newExp->expr.ident.idNode.kte.size = 4; + 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, atOffset); + idx = newLongId (localId, sd, pIcode, f, ix, du, off); newExp->expr.ident.idType = LONG_VAR; newExp->expr.ident.idNode.longIdx = idx; } @@ -273,27 +283,25 @@ COND_EXPR *COND_EXPR::idLong(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst } +COND_EXPR *idCondExpFunc (PPROC pproc, PSTKFRAME args) /* Returns an identifier conditional expression node of type FUNCTION */ -COND_EXPR *COND_EXPR::idFunc(Function * pproc, STKFRAME * args) -{ - COND_EXPR *newExp; +{ COND_EXPR *newExp; - newExp = new COND_EXPR(IDENTIFIER); + newExp = newCondExp (IDENTIFIER); newExp->expr.ident.idType = FUNCTION; newExp->expr.ident.idNode.call.proc = pproc; - newExp->expr.ident.idNode.call.args = args; + newExp->expr.ident.idNode.call.args = args; return (newExp); } -/* Returns an identifier conditional expression node of type OTHER. +COND_EXPR *idCondExpOther (byte seg, byte regi, int16 off) +/* 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(eReg seg, eReg regi, int16_t off) -{ - COND_EXPR *newExp; +{ COND_EXPR *newExp; - newExp = new COND_EXPR(IDENTIFIER); + newExp = newCondExp (IDENTIFIER); newExp->expr.ident.idType = OTHER; newExp->expr.ident.idNode.other.seg = seg; newExp->expr.ident.idNode.other.regi = regi; @@ -302,142 +310,138 @@ COND_EXPR *COND_EXPR::idOther(eReg seg, eReg regi, int16_t off) } +COND_EXPR *idCondExpID (ID *retVal, LOCAL_ID *locsym, Int ix) /* 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, iICODE ix_) -{ - COND_EXPR *newExp; - int idx; +{ COND_EXPR *newExp; + Int idx; - newExp = new COND_EXPR(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 = newCondExp (IDENTIFIER); + if (retVal->type == TYPE_LONG_SIGN) + { + idx = newLongRegId (locsym, 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 = newByteWordRegId (locsym, + TYPE_WORD_SIGN, retVal->id.regi); newExp->expr.ident.regiType = WORD_REG; - } - return (newExp); + } + return (newExp); } +COND_EXPR *idCondExp (PICODE pIcode, opLoc sd, PPROC pProc, Int i, + PICODE duIcode, operDu du) /* Returns an identifier conditional expression node, according to the given * type. - * Arguments: + * 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(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_,ICODE &duIcode, operDu du) -{ - COND_EXPR *newExp; +{ COND_EXPR *newExp; + PMEM pm; + Int idx; /* idx into pIcode->localId table */ - int idx; /* idx into pIcode->localId table */ + pm = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst; - const LLOperand &pm((sd == SRC) ? ll_insn.src() : ll_insn.dst); - - if ( ((sd == DST) && ll_insn.testFlags(IM_DST)) or - ((sd == SRC) && ll_insn.testFlags(IM_SRC)) or - (sd == LHS_OP)) /* for MUL lhs */ + 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, ix_); - newExp = COND_EXPR::idLongIdx (idx); - duIcode.setRegDU (rDX, du); - duIcode.setRegDU (rAX, du); + idx = newLongRegId (&pProc->localId, TYPE_LONG_SIGN, rDX, rAX, i); + newExp = idCondExpLongIdx (idx); + setRegDU (duIcode, rDX, du); + setRegDU (duIcode, rAX, du); } - else if ((sd == DST) && ll_insn.testFlags(IM_TMP_DST)) + 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); + newExp = idCondExpReg (rTMP, 0, &pProc->localId); + setRegDU (duIcode, rTMP, (operDu)USE); } - else if ((sd == SRC) && ll_insn.testFlags(I)) /* constant */ - newExp = COND_EXPR::idKte (ll_insn.src().getImm2(), 2); - else if (pm.regi == rUNDEF) /* global variable */ - newExp = GlobalVariable::Create(pm.segValue, pm.off); - else if ( pm.isReg() ) /* register */ + else if ((sd == SRC) && ((pIcode->ic.ll.flg & I) == I)) /* constant */ + newExp = idCondExpKte (pIcode->ic.ll.immed.op, 2); + + else if (pm->regi == 0) /* global variable */ + newExp = idCondExpGlob (pm->segValue, pm->off); + + else if (pm->regi < INDEXBASE) /* register */ { - newExp = COND_EXPR::idReg (pm.regi, (sd == SRC) ? ll_insn.getFlag() : - ll_insn.getFlag() & NO_SRC_B, - &pProc->localId); - duIcode.setRegDU( pm.regi, du); + newExp = idCondExpReg (pm->regi, (sd == SRC) ? pIcode->ic.ll.flg : + pIcode->ic.ll.flg & NO_SRC_B, &pProc->localId); + setRegDU (duIcode, pm->regi, du); } - else if (pm.off) /* offset */ + else if (pm->off) /* offset */ { - if ((pm.seg == rSS) && (pm.regi == INDEX_BP)) /* idx on bp */ + if ((pm->seg == rSS) && (pm->regi == INDEXBASE + 6)) /* idx on bp */ { - if (pm.off >= 0) /* argument */ - newExp = COND_EXPR::idParam (pm.off, &pProc->args); + if (pm->off >= 0) /* argument */ + newExp = idCondExpParam (pm->off, &pProc->args); else /* local variable */ - newExp = COND_EXPR::idLoc (pm.off, &pProc->localId); + newExp = idCondExpLoc (pm->off, &pProc->localId); } - else if ((pm.seg == rDS) && (pm.regi == INDEX_BX)) /* bx */ + 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); + 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); + newExp = idCondExpOther (pm->seg, pm->regi, pm->off); + setRegDU (duIcode, rBX, (operDu)USE); } else /* idx <> bp, bx */ - newExp = COND_EXPR::idOther (pm.seg, pm.regi, pm.off); - /**** check long ops, indexed global var *****/ + newExp = idCondExpOther (pm->seg, pm->regi, pm->off); + /**** check long ops, indexed global var *****/ } - else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */ + else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */ { - if ((pm.seg == rDS) && (pm.regi > INDEX_BP_DI)) /* dereference */ + if ((pm->seg == rDS) && (pm->regi > INDEXBASE + 3)) /* dereference */ { - switch (pm.regi) { - case INDEX_SI: - newExp = COND_EXPR::idReg(rSI, 0, &pProc->localId); - duIcode.setRegDU( rSI, du); - break; - case INDEX_DI: - newExp = COND_EXPR::idReg(rDI, 0, &pProc->localId); - duIcode.setRegDU( rDI, du); - break; - case INDEX_BP: - newExp = COND_EXPR::idReg(rBP, 0, &pProc->localId); - break; - case INDEX_BX: - newExp = COND_EXPR::idReg(rBX, 0, &pProc->localId); - duIcode.setRegDU( rBX, du); - break; - default: - newExp = 0; - assert(false); + switch (pm->regi) { + case INDEXBASE + 4: newExp = idCondExpReg(rSI, 0, &pProc->localId); + setRegDU (duIcode, rSI, du); + break; + case INDEXBASE + 5: newExp = idCondExpReg(rDI, 0, &pProc->localId); + setRegDU (duIcode, rDI, du); + break; + case INDEXBASE + 6: newExp = idCondExpReg(rBP, 0, &pProc->localId); + break; + case INDEXBASE + 7: newExp = idCondExpReg(rBX, 0, &pProc->localId); + setRegDU (duIcode, rBX, du); + break; } - newExp = COND_EXPR::unary (DEREFERENCE, newExp); + newExp = unaryCondExp (DEREFERENCE, newExp); } else - newExp = COND_EXPR::idOther (pm.seg, pm.regi, 0); + newExp = idCondExpOther (pm->seg, pm->regi, 0); } return (newExp); } +condId idType (PICODE pIcode, opLoc sd) /* Returns the identifier type */ -condId LLInst::idType(opLoc sd) const -{ - const LLOperand &pm((sd == SRC) ? src() : dst); +{ PMEM pm; - if ((sd == SRC) && testFlags(I)) + pm = (sd == SRC) ? &pIcode->ic.ll.src : &pIcode->ic.ll.dst; + + if ((sd == SRC) && ((pIcode->ic.ll.flg & I) == I)) return (CONSTANT); - else if (pm.regi == 0) + else if (pm->regi == 0) return (GLOB_VAR); - else if ( pm.isReg() ) + else if (pm->regi < INDEXBASE) return (REGISTER); - else if ((pm.seg == rSS) && (pm.regi == INDEX_BP)) + else if ((pm->seg == rSS) && (pm->regi == INDEXBASE)) { - //TODO: which pm.seg/pm.regi pairs should produce PARAM/LOCAL_VAR ? - if (pm.off >= 0) + if (pm->off >= 0) return (PARAM); else return (LOCAL_VAR); @@ -448,590 +452,572 @@ condId LLInst::idType(opLoc sd) const /* Size of hl types */ -int hlSize[] = {2, 1, 1, 2, 2, 4, 4, 4, 2, 2, 1, 4, 4}; +Int hlSize[] = {2, 1, 1, 2, 2, 4, 4, 4, 2, 2, 1, 4, 4}; +Int hlTypeSize (COND_EXPR *exp, PPROC pproc) /* Returns the type of the expression */ -int hlTypeSize (const COND_EXPR *expr, Function * pproc) -{ - int first, second; +{ Int first, second; - if (expr == NULL) - return (2); /* for TYPE_UNKNOWN */ + if (exp == NULL) + return (2); /* for TYPE_UNKNOWN */ - switch (expr->m_type) { - case BOOLEAN_OP: - first = hlTypeSize (expr->lhs(), pproc); - second = hlTypeSize (expr->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 (g_proj.symbolSize(expr->expr.ident.idNode.globIdx)); - 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[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? + switch (exp->type) { + case BOOLEAN_OP: first = hlTypeSize (exp->expr.boolExpr.lhs, pproc); + second = hlTypeSize (exp->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 (exp->expr.unaryExp, pproc)); + + case IDENTIFIER: + switch (exp->expr.ident.idType) { + case GLOB_VAR: + return (symtab.sym[exp->expr.ident.idNode.globIdx].size); + case REGISTER: + if (exp->expr.ident.regiType == BYTE_REG) + return (1); + else + return (2); + case LOCAL_VAR: + return (hlSize[pproc->localId.id[exp->expr.ident.idNode.localIdx].type]); + case PARAM: + return (hlSize[pproc->args.sym[exp->expr.ident.idNode.paramIdx].type]); + case GLOB_VAR_IDX: + return (hlSize[pproc->localId.id[exp->expr.ident.idNode.idxGlbIdx].type]); + case CONSTANT: + return (exp->expr.ident.idNode.kte.size); + case STRING: + return (2); + case LONG_VAR: + return (4); + case FUNCTION: + return (hlSize[exp->expr.ident.idNode.call.proc->retVal.type]); + case OTHER: + return (2); + } /* eos */ + break; + } + return 2; // CC: is this correct? } +hlType expType (COND_EXPR *exp, PPROC pproc) /* Returns the type of the expression */ -hlType COND_EXPR::expType(Function * pproc) const -{ - hlType first, second; +{ hlType first, second; - if (this == nullptr) - return (TYPE_UNKNOWN); + if (exp == NULL) + return (TYPE_UNKNOWN); - switch (m_type) - { - case BOOLEAN_OP: - first = lhs()->expType ( pproc ); - second = rhs()->expType ( pproc ); - if (first != second) - { - if (hlTypeSize (lhs(), pproc) > hlTypeSize (rhs(), pproc)) - return (first); - else - return (second); - } - else - return (first); + switch (exp->type) { + case BOOLEAN_OP: first = expType (exp->expr.boolExpr.lhs, pproc); + second = expType (exp->expr.boolExpr.rhs, pproc); + if (first != second) + { + if (hlTypeSize (exp->expr.boolExpr.lhs, pproc) > + hlTypeSize (exp->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 (expr.unaryExp->expType (pproc)); + case POST_INC: case POST_DEC: + case PRE_INC: case PRE_DEC: + case NEGATION: return (expType (exp->expr.unaryExp, pproc)); - case ADDRESSOF: return (TYPE_PTR); /***????****/ - case DEREFERENCE: return (TYPE_PTR); - case IDENTIFIER: - switch (expr.ident.idType) - { - case GLOB_VAR: - return g_proj.symbolType(expr.ident.idNode.globIdx); - case REGISTER: - if (expr.ident.regiType == BYTE_REG) - return (TYPE_BYTE_SIGN); - else - return (TYPE_WORD_SIGN); - case LOCAL_VAR: - return (pproc->localId.id_arr[expr.ident.idNode.localIdx].type); - case PARAM: - return (pproc->args[expr.ident.idNode.paramIdx].type); - case GLOB_VAR_IDX: - return (pproc->localId.id_arr[expr.ident.idNode.idxGlbIdx].type); - case CONSTANT: - return (TYPE_CONST); - case STRING: - return (TYPE_STR); - case LONG_VAR: - return (pproc->localId.id_arr[expr.ident.idNode.longIdx].type); - case FUNCTION: - return (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? + case ADDRESSOF: return (TYPE_PTR); /***????****/ + case DEREFERENCE: return (TYPE_PTR); + case IDENTIFIER: + switch (exp->expr.ident.idType) { + case GLOB_VAR: + return (symtab.sym[exp->expr.ident.idNode.globIdx].type); + case REGISTER: + if (exp->expr.ident.regiType == BYTE_REG) + return (TYPE_BYTE_SIGN); + else + return (TYPE_WORD_SIGN); + case LOCAL_VAR: + return (pproc->localId.id[exp->expr.ident.idNode.localIdx].type); + case PARAM: + return (pproc->args.sym[exp->expr.ident.idNode.paramIdx].type); + case GLOB_VAR_IDX: + return (pproc->localId.id[exp->expr.ident.idNode.idxGlbIdx].type); + case CONSTANT: + return (TYPE_CONST); + case STRING: + return (TYPE_STR); + case LONG_VAR: + return (pproc->localId.id[exp->expr.ident.idNode.longIdx].type); + case FUNCTION: + return (exp->expr.ident.idNode.call.proc->retVal.type); + case OTHER: + return (TYPE_UNKNOWN); + } /* eos */ + } + return TYPE_UNKNOWN; // CC: Correct? } +void removeRegFromLong (byte regi, LOCAL_ID *locId, COND_EXPR *tree) /* 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 HlTypeSupport::performLongRemoval (eReg regi, LOCAL_ID *locId, COND_EXPR *tree) { - IDENTTYPE* ident; /* ptr to an identifier */ - eReg otherRegi; /* high or low part of long register */ + IDENTTYPE* ident; /* ptr to an identifier */ + byte otherRegi; /* high or low part of long register */ - switch (tree->m_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; + 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 = newByteWordRegId (locId, TYPE_WORD_SIGN, + otherRegi); + } + break; } } +static char *getString (Int offset) /* Returns the string located in image, formatted in C format. */ -static std::string getString (int offset) -{ - PROG &prog(Project::get()->prog); - ostringstream o; - int strLen, i; +{ char *o; + Int strLen, i; - strLen = strSize (&prog.Image[offset], '\0'); - o << '"'; - for (i = 0; i < strLen; i++) - o<m_type) + if (exp == NULL) + return (condExp); + + needBracket = TRUE; + switch (exp->type) { - case BOOLEAN_OP: - outStr << "("; - outStr << walkCondExpr(expr->lhs(), pProc, numLoc); - outStr << condOpSym[expr->op()]; - outStr << walkCondExpr(expr->rhs(), pProc, numLoc); - outStr << ")"; - break; + case BOOLEAN_OP: strcat (condExp, "("); + e = walkCondExpr(exp->expr.boolExpr.lhs, pProc, numLoc); + strcat (condExp, e); + strcat (condExp, condOpSym[exp->expr.boolExpr.op]); + e = walkCondExpr(exp->expr.boolExpr.rhs, pProc, numLoc); + strcat (condExp, e); + strcat (condExp, ")"); + break; - case NEGATION: - if (expr->expr.unaryExp->m_type == IDENTIFIER) - { - needBracket = false; - outStr << "!"; - } - else - outStr << "! ("; - outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc); - if (needBracket == true) - outStr << ")"; - break; + case NEGATION: if (exp->expr.unaryExp->type == IDENTIFIER) + { + needBracket = FALSE; + strcat (condExp, "!"); + } + else + strcat (condExp, "! ("); + e = walkCondExpr (exp->expr.unaryExp, pProc, numLoc); + strcat (condExp, e); + if (needBracket == TRUE) + strcat (condExp, ")"); + break; - case ADDRESSOF: - if (expr->expr.unaryExp->m_type == IDENTIFIER) - { - needBracket = false; - outStr << "&"; - } - else - outStr << "&("; - outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc); - if (needBracket == true) - outStr << ")"; - break; + case ADDRESSOF: if (exp->expr.unaryExp->type == IDENTIFIER) + { + needBracket = FALSE; + strcat (condExp, "&"); + } + else + strcat (condExp, "&("); + e = walkCondExpr (exp->expr.unaryExp, pProc, numLoc); + strcat (condExp, e); + if (needBracket == TRUE) + strcat (condExp, ")"); + break; - case DEREFERENCE: - outStr << "*"; - if (expr->expr.unaryExp->m_type == IDENTIFIER) - needBracket = false; - else - outStr << "("; - outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc); - if (needBracket == true) - outStr << ")"; - break; + case DEREFERENCE: if (exp->expr.unaryExp->type == IDENTIFIER) + { + needBracket = FALSE; + strcat (condExp, "*"); + } + else + strcat (condExp, "*("); + e = walkCondExpr (exp->expr.unaryExp, pProc, numLoc); + strcat (condExp, e); + if (needBracket == TRUE) + strcat (condExp, ")"); + break; - case POST_INC: - outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "++"; - break; + case POST_INC: e = walkCondExpr (exp->expr.unaryExp, pProc, numLoc); + strcat (condExp, e); + strcat (condExp, "++"); + break; - case POST_DEC: - outStr << walkCondExpr (expr->expr.unaryExp, pProc, numLoc) << "--"; - break; + case POST_DEC: e = walkCondExpr (exp->expr.unaryExp, pProc, numLoc); + strcat (condExp, e); + strcat (condExp, "--"); + break; - case PRE_INC: - outStr << "++"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc); - break; + case PRE_INC: strcat (condExp, "++"); + e = walkCondExpr (exp->expr.unaryExp, pProc, numLoc); + strcat (condExp, e); + break; - case PRE_DEC: - outStr << "--"<< walkCondExpr (expr->expr.unaryExp, pProc, numLoc); - break; + case PRE_DEC: strcat (condExp, "--"); + e = walkCondExpr (exp->expr.unaryExp, pProc, numLoc); + strcat (condExp, e); + break; - case IDENTIFIER: - std::ostringstream o; - switch (expr->expr.ident.idType) - { - case GLOB_VAR: - o << g_proj.symtab[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 */ - { - id->setLocalName(++(*numLoc)); - codeOut <type)<< " "<name<<"; "; - codeOut <<"/* "<id.regi)<<" */\n"; - } - if (id->hasMacro) - o << id->macro << "("<name<<")"; - else - o << id->name; - break; + case IDENTIFIER: + o = (char*) allocMem (operandSize); + switch (exp->expr.ident.idType) { + case GLOB_VAR: sprintf (o, "%s", + symtab.sym[exp->expr.ident.idNode.globIdx].name); + break; + case REGISTER: + id = &pProc->localId.id[exp->expr.ident.idNode.regiIdx]; + if (id->name[0] == '\0') /* no name */ + { + sprintf (id->name, "loc%ld", ++(*numLoc)); + if (id->id.regi < rAL) + appendStrTab (&cCode.decl, + "%s %s; /* %s */\n", + hlTypes[id->type], id->name, + wordReg[id->id.regi - rAX]); + else + appendStrTab (&cCode.decl, + "%s %s; /* %s */\n", + hlTypes[id->type], id->name, + byteReg[id->id.regi - rAL]); + } + if (id->hasMacro) + sprintf (o, "%s(%s)", id->macro, id->name); + else + sprintf (o, "%s", id->name); + break; - case LOCAL_VAR: - o << pProc->localId.id_arr[expr->expr.ident.idNode.localIdx].name; - break; + case LOCAL_VAR: + sprintf (o, "%s", + pProc->localId.id[exp->expr.ident.idNode.localIdx].name); + break; - case PARAM: - psym = &pProc->args[expr->expr.ident.idNode.paramIdx]; - if (psym->hasMacro) - o << psym->macro<<"("<name<< ")"; - else - o << psym->name; - break; + case PARAM: + psym = &pProc->args.sym[exp->expr.ident.idNode.paramIdx]; + if (psym->hasMacro) + sprintf (o, "%s(%s)", psym->macro, psym->name); + else + sprintf (o, "%s", 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 << "["<regi)<<"]"; - break; + case GLOB_VAR_IDX: + bwGlb = &pProc->localId.id[exp->expr.ident.idNode.idxGlbIdx].id.bwGlb; + + sprintf (o, "%d[%s]", (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"<expr.ident.idNode.kte.kte; - break; + case CONSTANT: + if (exp->expr.ident.idNode.kte.kte < 1000) + sprintf (o,"%d",exp->expr.ident.idNode.kte.kte); + else + sprintf(o,"0x%X",exp->expr.ident.idNode.kte.kte); + break; - case STRING: - o << getString (expr->expr.ident.idNode.strIdx); - break; + case STRING: + o = getString (exp->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) - { - id->setLocalName(++(*numLoc)); - codeOut <type)<< " "<name<<"; "; - codeOut <<"/* "<id.longId.h) << ":" << - Machine_X86::regName(id->id.longId.l) << " */\n"; - o << id->name; - pProc->localId.propLongId (id->id.longId.l,id->id.longId.h, id->name.c_str()); - } - 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 LONG_VAR: + id = &pProc->localId.id[exp->expr.ident.idNode.longIdx]; + if (id->name[0] != '\0') /* STK_FRAME & REG w/name*/ + sprintf (o, "%s", id->name); + else if (id->loc == REG_FRAME) + { + sprintf (id->name, "loc%ld", ++(*numLoc)); + appendStrTab (&cCode.decl, + "%s %s; /* %s:%s */\n", + hlTypes[id->type], id->name, + wordReg[id->id.longId.h - rAX], + wordReg[id->id.longId.l - rAX]); + sprintf (o, "%s", id->name); + propLongId (&pProc->localId, id->id.longId.l, + id->id.longId.h, id->name); + } + else /* GLB_FRAME */ + { + if (id->id.longGlb.regi == 0) /* not indexed */ + sprintf (o, "[%ld]", (id->id.longGlb.seg<<4) + + id->id.longGlb.offH); + else if (id->id.longGlb.regi == rBX) + sprintf (o, "[%ld][bx]", + (id->id.longGlb.seg<<4) + + id->id.longGlb.offH); + } + break; - case FUNCTION: - o << writeCall (expr->expr.ident.idNode.call.proc,*expr->expr.ident.idNode.call.args, pProc, numLoc); - break; + case FUNCTION: + o = writeCall (exp->expr.ident.idNode.call.proc, + exp->expr.ident.idNode.call.args, + pProc, numLoc); + break; - case OTHER: - off = expr->expr.ident.idNode.other.off; - o << Machine_X86::regName(expr->expr.ident.idNode.other.seg)<< "["; - o << Machine_X86::regName(expr->expr.ident.idNode.other.regi); - if (off < 0) - o << "-"<< hexStr (-off); - else if (off>0) - o << "+"<< hexStr (off); - o << "]"; - } /* eos */ - outStr << o.str(); - break; + case OTHER: + off = exp->expr.ident.idNode.other.off; + if (off == 0) + sprintf (o, "%s[%s]", + wordReg[exp->expr.ident.idNode.other.seg - rAX], + idxReg[exp->expr.ident.idNode.other.regi - INDEXBASE]); + else if (off < 0) + sprintf (o, "%s[%s-%s]", + wordReg[exp->expr.ident.idNode.other.seg - rAX], + idxReg[exp->expr.ident.idNode.other.regi - INDEXBASE], + hexStr (-off)); + else + sprintf (o, "%s[%s+%s]", + wordReg[exp->expr.ident.idNode.other.seg - rAX], + idxReg[exp->expr.ident.idNode.other.regi - INDEXBASE], + hexStr (off)); + } /* eos */ + strcat (condExp, o); + break; } - cCode.appendDecl(codeOut.str()); - return outStr.str(); + + return (condExp); } +COND_EXPR *copyCondExp (COND_EXPR *exp) /* Makes a copy of the given expression. Allocates newExp storage for each * node. Returns the copy. */ -COND_EXPR *COND_EXPR::clone() const { - COND_EXPR* newExp=0; /* Expression node copy */ + COND_EXPR* newExp; /* Expression node copy */ - switch (m_type) - { - case BOOLEAN_OP: - newExp = new COND_EXPR(*this); - newExp->boolExpr.lhs = lhs()->clone(); - newExp->boolExpr.rhs = rhs()->clone(); - break; + switch (exp->type) { + case BOOLEAN_OP: + newExp = allocStruc(COND_EXPR); + memcpy(newExp, exp, sizeof(COND_EXPR)); + newExp->expr.boolExpr.lhs = copyCondExp (exp->expr.boolExpr.lhs); + newExp->expr.boolExpr.rhs = copyCondExp (exp->expr.boolExpr.rhs); + break; - case NEGATION: - case ADDRESSOF: - case DEREFERENCE: - newExp = new COND_EXPR(*this); - newExp->expr.unaryExp = expr.unaryExp->clone(); - break; + case NEGATION: + case ADDRESSOF: + case DEREFERENCE: + newExp = allocStruc(COND_EXPR); + memcpy(newExp, exp, sizeof(COND_EXPR)); + newExp->expr.unaryExp = copyCondExp (exp->expr.unaryExp); + break; - case IDENTIFIER: - return new COND_EXPR(*this); + case IDENTIFIER: + newExp = allocStruc(COND_EXPR); + memcpy(newExp, exp, sizeof(COND_EXPR)); } return (newExp); } +void changeBoolCondExpOp (COND_EXPR *exp, condOp newOp) /* Changes the boolean conditional operator at the root of this expression */ -void COND_EXPR::changeBoolOp (condOp newOp) { - boolExpr.op = newOp; + exp->expr.boolExpr.op = newOp; } + +boolT insertSubTreeReg (COND_EXPR *exp, COND_EXPR **tree, byte regi, + LOCAL_ID *locsym) /* Inserts the expression exp into the tree at the location specified by the * register regi */ -bool COND_EXPR::insertSubTreeReg (COND_EXPR *&tree, COND_EXPR *_expr, eReg regi,const LOCAL_ID *locsym) -{ +{ byte treeReg; - if (tree == NULL) - return false; - COND_EXPR *temp=tree->insertSubTreeReg(_expr,regi,locsym); - if(nullptr!=temp) - { - tree=temp; - return true; - } - return false; -} -COND_EXPR *COND_EXPR::insertSubTreeReg (COND_EXPR *_expr, eReg regi,const LOCAL_ID *locsym) -{ + if (*tree == NULL) + return FALSE; - eReg treeReg; - COND_EXPR *temp; - - switch (m_type) { - case IDENTIFIER: - if (expr.ident.idType == REGISTER) - { - treeReg = locsym->id_arr[expr.ident.idNode.regiIdx].id.regi; - if (treeReg == regi) /* uint16_t reg */ + switch ((*tree)->type) { + case IDENTIFIER: + if ((*tree)->expr.ident.idType == REGISTER) + { + treeReg = locsym->id[(*tree)->expr.ident.idNode.regiIdx].id.regi; + if (treeReg == regi) /* word reg */ { - return _expr; + *tree = exp; + return TRUE; } - else if(Machine_X86::isSubRegisterOf(treeReg,regi)) /* uint16_t/uint8_t reg */ + else if ((regi >= rAX) && (regi <= rBX)) /* word/byte reg */ { - return _expr; + if ((treeReg == (regi + rAL-1)) || (treeReg == (regi + rAH-1))) + { + *tree = exp; + return TRUE; + } } - } - return false; + } + return FALSE; - case BOOLEAN_OP: - temp = lhs()->insertSubTreeReg( _expr, regi, locsym); - if (nullptr!=temp) - { - boolExpr.lhs = temp; - return this; - } - temp = rhs()->insertSubTreeReg( _expr, regi, locsym); - if (nullptr!=temp) - { - boolExpr.rhs = temp; - return this; - } - return nullptr; + case BOOLEAN_OP: + if (insertSubTreeReg (exp, &(*tree)->expr.boolExpr.lhs, regi, + locsym)) + return TRUE; + if (insertSubTreeReg (exp, &(*tree)->expr.boolExpr.rhs, regi, + locsym)) + return TRUE; + return FALSE; - case NEGATION: - case ADDRESSOF: - case DEREFERENCE: - temp = expr.unaryExp->insertSubTreeReg( _expr, regi, locsym); - if (nullptr!=temp) - { - expr.unaryExp = temp; - return this; - } - return nullptr; + case NEGATION: + case ADDRESSOF: + case DEREFERENCE: + if (insertSubTreeReg(exp, &(*tree)->expr.unaryExp,regi, locsym)) + return TRUE; + return FALSE; } - - return nullptr; -} -COND_EXPR *BinaryOperator::insertSubTreeReg(COND_EXPR *_expr, eReg regi, LOCAL_ID *locsym) -{ - COND_EXPR *r; - r=m_lhs->insertSubTreeReg(_expr,regi,locsym); - if(r) - { - m_lhs = r; - return this; - } - r=m_rhs->insertSubTreeReg(_expr,regi,locsym); - if(r) - { - m_rhs = r; - return this; - } - return nullptr; + return FALSE; } + +boolT insertSubTreeLongReg (COND_EXPR *exp, COND_EXPR **tree, Int longIdx) /* Inserts the expression exp into the tree at the location specified by the * long register index longIdx*/ -bool COND_EXPR::insertSubTreeLongReg(COND_EXPR *_expr, COND_EXPR **tree, int longIdx) { - if (tree == NULL) - return false; - COND_EXPR *temp=(*tree)->insertSubTreeLongReg(_expr,longIdx); - if(nullptr!=temp) - { - *tree=temp; - return true; + 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; + return FALSE; } -COND_EXPR *COND_EXPR::insertSubTreeLongReg(COND_EXPR *_expr, int longIdx) -{ - COND_EXPR *temp; - switch (m_type) - { - case IDENTIFIER: - if (expr.ident.idNode.longIdx == longIdx) - { - return _expr; - } - return nullptr; - - case BOOLEAN_OP: - temp = lhs()->insertSubTreeLongReg( _expr,longIdx); - if (nullptr!=temp) - { - boolExpr.lhs = temp; - return this; - } - temp = rhs()->insertSubTreeLongReg( _expr,longIdx); - if (nullptr!=temp) - { - boolExpr.rhs = temp; - return this; - } - return nullptr; - - case NEGATION: - case ADDRESSOF: - case DEREFERENCE: - temp = expr.unaryExp->insertSubTreeLongReg(_expr,longIdx); - if (nullptr!=temp) - { - expr.unaryExp = temp; - return this; - } - return nullptr; - } - return nullptr; -} -COND_EXPR *BinaryOperator::insertSubTreeLongReg(COND_EXPR *_expr, int longIdx) -{ - COND_EXPR *r; - r=m_lhs->insertSubTreeLongReg(_expr,longIdx); - if(r) - { - m_lhs = r; - return this; - } - r=m_rhs->insertSubTreeLongReg(_expr,longIdx); - if(r) - { - m_rhs = r; - return this; - } - return nullptr; -} - + +void freeCondExpr (COND_EXPR *exp) /* Recursively deallocates the abstract syntax tree rooted at *exp */ -void COND_EXPR::release() { - switch (m_type) - { - case BOOLEAN_OP: - lhs()->release(); - rhs()->release(); - break; - case NEGATION: - case ADDRESSOF: - case DEREFERENCE: - expr.unaryExp->release(); - break; + switch (exp->type) { + case BOOLEAN_OP: freeCondExpr (exp->expr.boolExpr.lhs); + freeCondExpr (exp->expr.boolExpr.rhs); + break; + case NEGATION: + case ADDRESSOF: + case DEREFERENCE: freeCondExpr (exp->expr.unaryExp); + break; } - delete (this); -} -/* Makes a copy of the given expression. Allocates newExp storage for each - * node. Returns the copy. */ - -COND_EXPR *BinaryOperator::clone() -{ - BinaryOperator* newExp=new BinaryOperator(m_op); /* Expression node copy */ - newExp->m_lhs = m_lhs->clone(); - newExp->m_rhs = m_rhs->clone(); - return newExp; + free (exp); } -COND_EXPR *BinaryOperator::inverse() -{ - 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}; - BinaryOperator *res=reinterpret_cast(this->clone()); - switch (m_op) + +/*************************************************************************** + * Expression stack functions + **************************************************************************/ + +void initExpStk() +/* Reinitalizes the expression stack (expStk) to NULL, by freeing all the + * space allocated (if any). */ +{ EXP_STK *top; + + while (expStk != NULL) { - case LESS_EQUAL: case LESS: case EQUAL: - case NOT_EQUAL: case GREATER: case GREATER_EQUAL: - res->m_op = invCondOp[m_op]; - return res; - - case AND: case OR: case XOR: case NOT: case ADD: - case SUB: case MUL: case DIV: case SHR: case SHL: case MOD: - return COND_EXPR::unary (NEGATION, res); - - case DBL_AND: case DBL_OR: - res->m_op = invCondOp[m_op]; - res->m_lhs=m_lhs->inverse (); - res->m_rhs=m_rhs->inverse (); - return res; - } /* eos */ - assert(false); - return res; - + top = expStk; + expStk = expStk->next; + free (top); + } +} + + +void pushExpStk (COND_EXPR *exp) +/* Pushes the given expression onto the local stack (expStk). */ +{ EXP_STK *newExp; + + newExp = allocStruc(EXP_STK); + newExp->exp = exp; + newExp->next = expStk; + expStk = newExp; +} + + +COND_EXPR *popExpStk() +/* 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. */ +{ EXP_STK *top; + COND_EXPR *topExp; + + if (expStk != NULL) + { + topExp = expStk->exp; + top = expStk; + expStk = expStk->next; + free (top); + return (topExp); + } + else + return (NULL); +} + +Int numElemExpStk() +/* Returns the number of elements available in the expression stack */ +{ EXP_STK *top; + Int num; + + num = 0; + top = expStk; + while (top) + { + top = top->next; + num++; + } + return (num); +} + +boolT emptyExpStk() +/* Returns whether the expression stack is empty or not */ +{ + if (expStk == NULL) + return TRUE; + return FALSE; } diff --git a/src/backend.cpp b/src/backend.cpp index 7cb398e..b041e6f 100644 --- a/src/backend.cpp +++ b/src/backend.cpp @@ -4,40 +4,47 @@ * Purpose: Back-end module. Generates C code for each procedure. * (C) Cristina Cifuentes ****************************************************************************/ -#include -#include #include "dcc.h" -#include "disassem.h" -#include -#include -#include #include #include -#include "project.h" -bundle cCode; /* Procedure declaration and code */ -using namespace std; -/* Returns a unique index to the next label */ -int getNextLabel() -{ - static int labelIdx = 1; /* index of the next label */ - return (labelIdx++); +bundle cCode; /* Procedure declaration and code */ + +/* Indentation buffer */ +#define indSize 81 /* size of the indentation buffer. Each indentation + * is of 4 spaces => max. 20 indentation levels */ +static char indentBuf[indSize] = + " "; + + +static char *indent (Int indLevel) +/* Indentation according to the depth of the statement */ +{ + 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++); +} + + +static void displayStats (PPROC pProc) /* displays statistics on the subroutine */ -void Function::displayStats () { - printf("\nStatistics - Subroutine %s\n", name.c_str()); - 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); - } + printf("\nStatistics - Subroutine %s\n", pProc->name); + printf ("Number of Icode instructions:\n"); + printf (" Low-level : %4d\n", stats.numLLIcode); + if (! (pProc->flg & PROC_ASM)) + { + printf (" High-level: %4d\n", stats.numHLIcode); + printf (" Percentage reduction: %2.2f%%\n", 100.0 - (stats.numHLIcode * + 100.0) / stats.numLLIcode); + } } @@ -48,315 +55,619 @@ static void fixupLabels (PPROC pProc) * 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 */ +{ 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].ll()->flg |= HLL_LABEL; - pProc->Icode.icode[dfsLast[i]->start].ll()->hllLabNum = getNextLabel(); - } + 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 +char *cChar (byte c) /* 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 (uint8_t c) -{ - static char res[3]; +{ 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); + 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. +static void printGlobVar (PSYM psym) +/* 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 (std::ostream &ostr,SYM * psym) -{ - int j; - PROG &prog(Project::get()->prog); - uint32_t relocOp = prog.fCOM ? psym->label : psym->label + 0x100; +{ Int j; + dword relocOp = prog.fCOM ? psym->label : psym->label + 0x100; + char *strContents; /* initial contents of variable */ - switch (psym->size) - { - case 1: - ostr << "uint8_t\t"<name<<" = "<name<<" = "<type == TYPE_PTR) /* pointer */ - ostr << "uint16_t *\t"<name<<" = "<name<<"[4] = \""<< - prog.Image[relocOp]<size; j++) - strContents << cChar(prog.Image[relocOp + j]); - ostr << "char\t*"<name<<" = \""<size) { + case 1: appendStrTab (&cCode.decl, "byte\t%s = %ld;\n", + psym->name, prog.Image[relocOp]); + break; + case 2: appendStrTab (&cCode.decl, "word\t%s = %ld;\n", + psym->name, LH(prog.Image+relocOp)); + break; + case 4: if (psym->type == TYPE_PTR) /* pointer */ + appendStrTab (&cCode.decl, "word\t*%s = %ld;\n", + psym->name, LH(prog.Image+relocOp)); + else /* char */ + appendStrTab (&cCode.decl, + "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])); + appendStrTab (&cCode.decl, "char\t*%s = \"%s\";\n", + psym->name, strContents); + } } // Note: Not called at present. +static void writeGlobSymTable() /* Writes the contents of the symbol table, along with any variable * initialization. */ -void Project::writeGlobSymTable() -{ - std::ostringstream ostr; +{ Int idx; + char type[10]; + PSYM pSym; - if (symtab.empty()) - return; - ostr<<"/* Global variables */\n"; - for (SYM &sym : symtab) - { - if (sym.duVal.isUSE_VAL()) /* first used */ - printGlobVar (ostr,&sym); - else { /* first defined */ - switch (sym.size) { - case 1: ostr<<"uint8_t\t"; break; - case 2: ostr<<"int\t"; break; - case 4: if (sym.type == TYPE_PTR) - ostr<<"int\t*"; - else - ostr<<"char\t*"; - break; - default: ostr<<"char\t*"; - } - ostr<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*"); + } + appendStrTab (&cCode.decl, "%s%s;\t/* size = %ld */\n", + type, pSym->name, pSym->size); + } + } + appendStrTab (&cCode.decl, "\n"); + } } +static void writeHeader (FILE *fp, char *fileName) /* Writes the header information and global variables to the output C file * fp. */ -static void writeHeader (std::ostream &_ios, char *fileName) -{ - PROG &prog(Project::get()->prog); - /* Write header information */ - cCode.init(); - 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 header information */ + newBundle (&cCode); + appendStrTab (&cCode.decl, "/*\n"); + appendStrTab (&cCode.decl, " * Input file\t: %s\n", fileName); + appendStrTab (&cCode.decl, " * File type\t: %s\n", (prog.fCOM)?"COM":"EXE"); + appendStrTab (&cCode.decl, " */\n\n#include \"dcc.h\"\n\n"); - /* Write global symbol table */ - /** writeGlobSymTable(); *** need to change them into locident fmt ***/ - writeBundle (_ios, cCode); - freeBundle (&cCode); + /* Write global symbol table */ + /** writeGlobSymTable(); *** need to change them into locident fmt ***/ + writeBundle (fp, cCode); + freeBundle (&cCode); } -// Note: Not currently called! + +static void writeBitVector (dword regi) +/* Writes the registers that are set in the bitvector */ +{ Int j; + + for (j = 0; j < INDEXBASE; j++) + { + if ((regi & power2(j)) != 0) + printf ("%s ", allRegs[j]); + } +} + + +static void emitGotoLabel (PICODE 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. + * 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 */ +{ + 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); + } + appendStrTab (&cCode.code, "%sgoto L%ld;\n", indent(indLevel), + pt->ic.ll.hllLabNum); + stats.numHLIcode++; +} + + +// Note: Not currently called! +static void emitFwdGotoLabel (PICODE 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. */ -static void emitFwdGotoLabel (ICODE * pt, int indLevel) { - if ( not pt->ll()->testFlags(HLL_LABEL)) /* node hasn't got a lab */ - { - /* Generate new label */ - pt->ll()->hllLabNum = getNextLabel(); - pt->ll()->setFlags(HLL_LABEL); - } - cCode.appendCode( "%sgoto l%ld;\n", indentStr(indLevel), pt->ll()->hllLabNum); + 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; + } + appendStrTab (&cCode.code, "%sgoto l%ld;\n", indent(indLevel), + pt->ic.ll.hllLabNum); } +static void writeBB (PBB pBB, PICODE hli, Int lev, PPROC pProc, Int *numLoc) +/* 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. */ +{ 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') + { + appendStrTab (&cCode.code, "%s%s", indent(lev), line); + stats.numHLIcode++; + } + if (option.verbose) + writeDU (&hli[i], i); + } +//if (hli[i].invalid) +//printf("Invalid icode: %d!\n", hli[i].invalid); +} + + +static void writeCode (PBB pBB, Int indLevel, PPROC pProc , Int *numLoc, + Int latchNode, Int ifFollow) +/* 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 */ +{ + Int follow, /* ifFollow */ + loopType, /* Type of loop, if any */ + nodeType; /* Type of node */ + PBB succ, latch; /* Successor and latching node */ + PICODE 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 (!pBB) return; + if ((ifFollow != UN_INIT) && (pBB == pProc->dfsLast[ifFollow])) + return; + + if (pBB->traversed == DFS_ALPHA) + return; + pBB->traversed = DFS_ALPHA; + + /* Check for start of loop */ + repCond = FALSE; + latch = NULL; + loopType = pBB->loopType; + if (loopType) + { + latch = pProc->dfsLast[pBB->latchNode]; + switch (loopType) { + case WHILE_TYPE: + picode = pProc->Icode.GetIcode(pBB->start + pBB->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 (pBB->numHlIcodes > 1) + { + /* Write the code for this basic block */ + writeBB(pBB, 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 (pBB->edges[ELSE].BBptr->dfsLastNum == pBB->loopFollow) + inverseCondOp (&picode->ic.hl.oper.exp); + appendStrTab (&cCode.code, "\n%swhile (%s) {\n", indent(indLevel), + walkCondExpr (picode->ic.hl.oper.exp, pProc, numLoc)); + invalidateIcode (picode); + break; + + case REPEAT_TYPE: + appendStrTab (&cCode.code, "\n%sdo {\n", indent(indLevel)); + picode = pProc->Icode.GetIcode(latch->start+latch->length-1); + invalidateIcode (picode); + break; + + case ENDLESS_TYPE: + appendStrTab (&cCode.code, "\n%sfor (;;) {\n", indent(indLevel)); + } + stats.numHLIcode += 1; + indLevel++; + } + + /* Write the code for this basic block */ + if (repCond == FALSE) + writeBB (pBB, pProc->Icode.GetFirstIcode(), indLevel, pProc, numLoc); + + /* Check for end of path */ + nodeType = pBB->nodeType; + if (nodeType == RETURN_NODE || nodeType == TERMINATE_NODE || + nodeType == NOWHERE_NODE || (pBB->dfsLastNum == latchNode)) + return; + + /* Check type of loop/node and process code */ + if (loopType) /* there is a loop */ + { + if (pBB != latch) /* loop is over several bbs */ + { + if (loopType == WHILE_TYPE) + { + succ = pBB->edges[THEN].BBptr; + if (succ->dfsLastNum == pBB->loopFollow) + succ = pBB->edges[ELSE].BBptr; + } + else + succ = pBB->edges[0].BBptr; + if (succ->traversed != DFS_ALPHA) + writeCode (succ, 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 (pBB, pProc->Icode.GetFirstIcode(), indLevel+1, pProc, numLoc); + appendStrTab (&cCode.code, "%s} /* end of while */\n", + indent(indLevel)); + } + else if (loopType == ENDLESS_TYPE) + appendStrTab (&cCode.code, "%s} /* end of loop */\n", + indent(indLevel)); + else if (loopType == REPEAT_TYPE) + { + if (picode->ic.hl.opcode != HLI_JCOND) + reportError (REPEAT_FAIL); + appendStrTab (&cCode.code, "%s} while (%s);\n", indent(indLevel), + walkCondExpr (picode->ic.hl.oper.exp, pProc, numLoc)); + } + + /* Recurse on the loop follow */ + if (pBB->loopFollow != MAX) + { + succ = pProc->dfsLast[pBB->loopFollow]; + if (succ->traversed != DFS_ALPHA) + writeCode (succ, 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 (pBB->ifFollow != MAX) /* there is a follow */ + { + /* process the THEN part */ + follow = pBB->ifFollow; + succ = pBB->edges[THEN].BBptr; + if (succ->traversed != DFS_ALPHA) /* not visited */ + { + if (succ->dfsLastNum != follow) /* THEN part */ + { + l = writeJcond ( + pProc->Icode.GetIcode(pBB->start + pBB->length -1)->ic.hl, + pProc, numLoc); + appendStrTab (&cCode.code, "\n%s%s", indent(indLevel-1), l); + writeCode (succ, indLevel, pProc, numLoc, latchNode, + follow); + } + else /* empty THEN part => negate ELSE part */ + { + l = writeJcondInv ( + pProc->Icode.GetIcode(pBB->start + pBB->length -1)->ic.hl, + pProc, numLoc); + appendStrTab (&cCode.code, "\n%s%s", indent(indLevel-1), l); + writeCode (pBB->edges[ELSE].BBptr, indLevel, pProc, numLoc, + latchNode, follow); + emptyThen = TRUE; + } + } + else /* already visited => emit label */ + emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel); + + /* process the ELSE part */ + succ = pBB->edges[ELSE].BBptr; + if (succ->traversed != DFS_ALPHA) /* not visited */ + { + if (succ->dfsLastNum != follow) /* ELSE part */ + { + appendStrTab (&cCode.code, "%s}\n%selse {\n", + indent(indLevel-1), indent(indLevel - 1)); + writeCode (succ, indLevel, pProc, numLoc, latchNode, + follow); + } + /* else (empty ELSE part) */ + } + else if (! emptyThen) /* already visited => emit label */ + { + appendStrTab (&cCode.code, "%s}\n%selse {\n", + indent(indLevel-1), indent(indLevel - 1)); + emitGotoLabel (pProc->Icode.GetIcode(succ->start), indLevel); + } + appendStrTab (&cCode.code, "%s}\n", indent(--indLevel)); + + /* Continue with the follow */ + succ = pProc->dfsLast[follow]; + if (succ->traversed != DFS_ALPHA) + writeCode (succ, indLevel, pProc, numLoc, latchNode, + ifFollow); + } + else /* no follow => if..then..else */ + { + l = writeJcond ( + pProc->Icode.GetIcode(pBB->start + pBB->length -1)->ic.hl, + pProc, numLoc); + appendStrTab (&cCode.code, "%s%s", indent(indLevel-1), l); + writeCode (pBB->edges[THEN].BBptr, indLevel, pProc, numLoc, + latchNode, ifFollow); + appendStrTab (&cCode.code, "%s}\n%selse {\n", indent(indLevel-1), + indent(indLevel - 1)); + writeCode (pBB->edges[ELSE].BBptr, indLevel, pProc, numLoc, + latchNode, ifFollow); + appendStrTab (&cCode.code, "%s}\n", indent(--indLevel)); + } + } + + else /* fall, call, 1w */ + { + succ = pBB->edges[0].BBptr; /* fall-through edge */ + if (succ->traversed != DFS_ALPHA) + writeCode (succ, indLevel, pProc,numLoc, latchNode,ifFollow); + } + } +} + + +static void codeGen (PPROC pProc, FILE *fp) /* 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 numLoc; - ostringstream ostr; - //STKFRAME * args; /* Procedure arguments */ - //char buf[200], /* Procedure's definition */ - // arg[30]; /* One argument */ - BB *pBB; /* Pointer to basic block */ +{ Int i, numLoc; + PSTKFRAME 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 */ - cCode.init(); - if (flg & PROC_IS_FUNC) /* Function */ - ostr<< "\n"<flg & PROC_IS_FUNC) /* Function */ + appendStrTab (&cCode.decl, "\n%s %s (", hlTypes[pProc->retVal.type], + pProc->name); else /* Procedure */ - ostr<< "\nvoid "<name); /* Write arguments */ - for (size_t i = 0; i < args.size(); i++) + args = &pProc->args; + memset (buf, 0, sizeof(buf)); + for (i = 0; i < args->csym; i++) { - if ( args[i].invalid ) - continue; - ostr<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, ", "); + } } - ostr<<")\n"; + strcat (buf, ")\n"); + appendStrTab (&cCode.decl, "%s", buf); - /* Write comments */ - writeProcComments( ostr ); + /* Write comments */ + writeProcComments (pProc, &cCode.decl); /* Write local variables */ - if (! (flg & PROC_ASM)) - { - numLoc = 0; - for (ID &refId : localId ) - { - /* Output only non-invalidated entries */ - if ( refId.illegal ) - continue; - if (refId.loc == REG_FRAME) - { - /* Register variables are assigned to a local variable */ - if (((flg & SI_REGVAR) && (refId.id.regi == rSI)) || - ((flg & DI_REGVAR) && (refId.id.regi == rDI))) - { - refId.setLocalName(++numLoc); - ostr << "int "<writeCode (1, this, &numLoc, MAX, UN_INIT); - } + if (! (pProc->flg & PROC_ASM)) + { + locid = &pProc->localId.id[0]; + numLoc = 0; + for (i = 0; i < pProc->localId.csym; i++, locid++) + { + /* Output only non-invalidated entries */ + if (locid->illegal == FALSE) + { + if (locid->loc == REG_FRAME) + { + /* Register variables are assigned to a local variable */ + if (((pProc->flg & SI_REGVAR) && (locid->id.regi == rSI)) || + ((pProc->flg & DI_REGVAR) && (locid->id.regi == rDI))) + { + sprintf (locid->name, "loc%ld", ++numLoc); + appendStrTab (&cCode.decl, "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. */ + } - cCode.appendCode( "}\n\n"); - writeBundle (fs, cCode); - freeBundle (&cCode); + else if (locid->loc == STK_FRAME) + { + /* Name local variables and output appropriate type */ + sprintf (locid->name, "loc%ld", ++numLoc); + appendStrTab (&cCode.decl, "%s %s;\n", + hlTypes[locid->type], locid->name); + } + } + } + } + /* Write procedure's code */ + if (pProc->flg & PROC_ASM) /* generate assembler */ + disassem (3, pProc); + else /* generate C */ + writeCode (pProc->cfg, 1, pProc, &numLoc, MAX, UN_INIT); + + appendStrTab (&cCode.code, "}\n\n"); + writeBundle (fp, cCode); + freeBundle (&cCode); /* Write Live register analysis information */ - if (option.verbose) - for (size_t i = 0; i < numBBs; i++) - { - pBB = m_dfsLast[i]; - if (pBB->flg & INVALID_BB) continue; /* skip invalid BBs */ - cout << "BB "<numBBs; i++) + { + pBB = pProc->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"); + } } +static void backBackEnd (char *filename, PCALL_GRAPH pcallGraph, FILE *fp) /* 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 */ +// 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; + /* 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 (size_t i = 0; i < pcallGraph->outEdges.size(); i++) - { - backBackEnd (filename, pcallGraph->outEdges[i], _ios); - } + /* Dfs if this procedure has any successors */ + if (pcallGraph->numOutEdges > 0) + { + for (i = 0; i < pcallGraph->numOutEdges; i++) + { + backBackEnd (filename, pcallGraph->outEdges[i], fp); + } + } - /* Generate code for this procedure */ - stats.numLLIcode = pcallGraph->proc->Icode.size(); - stats.numHLIcode = 0; - pcallGraph->proc->codeGen (_ios); + /* Generate code for this procedure */ + stats.numLLIcode = pcallGraph->proc->Icode.GetNumIcodes(); + stats.numHLIcode = 0; + codeGen (pcallGraph->proc, fp); - /* Generate statistics */ - if (option.Stats) - pcallGraph->proc->displayStats (); - if (! (pcallGraph->proc->flg & PROC_ASM)) - { - stats.totalLL += stats.numLLIcode; - stats.totalHL += stats.numHLIcode; - } + /* Generate statistics */ + if (option.Stats) + displayStats (pcallGraph->proc); + if (! (pcallGraph->proc->flg & PROC_ASM)) + { + stats.totalLL += stats.numLLIcode; + stats.totalHL += stats.numHLIcode; + } } +void BackEnd (char *fileName, PCALL_GRAPH pcallGraph) /* Invokes the necessary routines to produce code one procedure at a time. */ -void BackEnd (char *fileName, CALL_GRAPH * pcallGraph) { - std::ofstream fs; /* Output C file */ + char* outName, *ext; + FILE* fp; /* Output C file */ - /* Get output file name */ - std::string outNam(fileName); - outNam = outNam.substr(0,outNam.rfind("."))+".b"; /* b for beta */ + /* 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(outNam); - if(!fs.is_open()) - fatalError (CANNOT_OPEN, outNam.c_str()); - printf ("dcc: Writing C beta file %s\n", outNam.c_str()); + /* Open output file */ + fp = fopen (outName, "wt"); + if (!fp) + fatalError (CANNOT_OPEN, outName); + printf ("dcc: Writing C beta file %s\n", outName); - /* Header information */ - writeHeader (fs, fileName); + /* Header information */ + writeHeader (fp, fileName); - /* Initialize total Icode instructions statistics */ - stats.totalLL = 0; - stats.totalHL = 0; + /* Initialize total Icode instructions statistics */ + stats.totalLL = 0; + stats.totalHL = 0; - /* Process each procedure at a time */ - backBackEnd (fileName, pcallGraph, fs); + /* Process each procedure at a time */ + backBackEnd (fileName, pcallGraph, fp); - /* Close output file */ - fs.close(); - printf ("dcc: Finished writing C beta file\n"); + /* Close output file */ + fclose (fp); + printf ("dcc: Finished writing C beta file\n"); } diff --git a/src/bundle.cpp b/src/bundle.cpp index d12af19..57ab217 100644 --- a/src/bundle.cpp +++ b/src/bundle.cpp @@ -6,89 +6,107 @@ #include "dcc.h" #include -#include #include #include #include #define deltaProcLines 20 -using namespace std; + +void newBundle (bundle *procCode) /* Allocates memory for a new bundle and initializes it to zero. */ +{ + memset (&(procCode->decl), 0, sizeof(strTable)); + memset (&(procCode->code), 0, sizeof(strTable)); +} +static void incTableSize (strTable *strTab) +/* Increments the size of the table strTab by deltaProcLines and copies all + * the strings to the new table. */ +{ + strTab->allocLines += deltaProcLines; + strTab->str = (char**)reallocVar (strTab->str, strTab->allocLines*sizeof(char *)); + memset (&strTab->str[strTab->allocLines - deltaProcLines], 0, + deltaProcLines * sizeof(char *)); +} + + +void appendStrTab (strTable *strTab, char *format, ...) +/* Appends the new line (in printf style) to the string table strTab. */ +{ va_list args; + + va_start (args, format); + if (strTab->numLines == strTab->allocLines) + { + incTableSize (strTab); + } + strTab->str[strTab->numLines] = (char *)malloc(lineSize * sizeof(char)); + if (strTab->str == NULL) + { + fatalError(MALLOC_FAILED, lineSize * sizeof(char)); + } + vsprintf (strTab->str[strTab->numLines], format, args); + strTab->numLines++; + va_end (args); +} + + +Int nextBundleIdx (strTable *strTab) +/* Returns the next available index into the table */ +{ + return (strTab->numLines); +} + + +void addLabelBundle (strTable *strTab, Int idx, Int label) /* Adds the given label to the start of the line strTab[idx]. The first * tab is removed and replaced by this label */ -void strTable::addLabelBundle (int idx, int label) -{ - char s[16]; - sprintf (s, "l%d: ", label); - if(at(idx).size()<4) - at(idx)=s; - else - at(idx) = string(s)+at(idx).substr(4); +{ char s[lineSize]; + + sprintf (s, "l%ld: %s", label, &strTab->str[idx][4]); + strcpy (strTab->str[idx], s); } +static void writeStrTab (FILE *fp, strTable strTab) /* Writes the contents of the string table on the file fp. */ -static void writeStrTab (std::ostream &ios, strTable &strTab) -{ - for (size_t i = 0; i < strTab.size(); i++) - ios << strTab[i]; +{ Int i; + + for (i = 0; i < strTab.numLines; i++) + fprintf (fp, "%s", strTab.str[i]); } +void writeBundle (FILE *fp, bundle procCode) /* Writes the contents of the bundle (procedure code and declaration) to * a file. */ -void writeBundle (std::ostream &ios, bundle procCode) { - writeStrTab (ios, procCode.decl); - writeStrTab (ios, procCode.code); + writeStrTab (fp, procCode.decl); + if (procCode.decl.str[procCode.decl.numLines - 1][0] != ' ') + fprintf (fp, "\n"); + writeStrTab (fp, procCode.code); } +static void freeStrTab (strTable *strTab) /* Frees the storage allocated by the string table. */ -static void freeStrTab (strTable &strTab) -{ - strTab.clear(); +{ Int i; + + if (strTab->allocLines > 0) { + for (i = 0; i < strTab->numLines; i++) + free (strTab->str[i]); + free (strTab->str); + memset (strTab, 0, sizeof(strTable)); + } } -/* Deallocates the space taken by the bundle procCode */ void freeBundle (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::appendCode(const std::string &s) -{ - code.push_back(s); -} - -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); -} - -void bundle::appendDecl(const std::string &v) -{ - decl.push_back(v); +/* Deallocates the space taken by the bundle procCode */ +{ + freeStrTab (&(procCode->decl)); + freeStrTab (&(procCode->code)); } - diff --git a/src/chklib.cpp b/src/chklib.cpp index a4800c4..77bd128 100644 --- a/src/chklib.cpp +++ b/src/chklib.cpp @@ -14,7 +14,6 @@ #endif #include #include "dcc.h" -#include "project.h" #include "perfhlib.h" #define NIL -1 /* Used like NULL, but 0 is valid */ @@ -23,7 +22,7 @@ typedef struct HT_tag { char htSym[SYMLEN]; - uint8_t htPat[PATLEN]; + byte htPat[PATLEN]; } HT; /* Structure of the prototypes table. Same as the struct in parsehdr.h, @@ -36,7 +35,7 @@ struct ph_func_tag hlType typ; /* Return type */ int numArg; /* Number of args */ int firstArg; /* Index of first arg in chain */ - // int next; /* Index of next function in chain */ +// int next; /* Index of next function in chain */ bool bVararg; /* True if variable arguements */ } PH_FUNC_STRUCT; @@ -44,27 +43,27 @@ struct ph_func_tag #define NUM_PLIST 64 /* Number of entries to increase allocation by */ /* statics */ -static char buf[100]; /* A general purpose buffer */ +char buf[100]; /* A general purpose buffer */ int numKeys; /* Number of hash table entries (keys) */ int numVert; /* Number of vertices in the graph (also size of g[]) */ unsigned PatLen; /* Size of the keys (pattern length) */ unsigned SymLen; /* Max size of the symbols, including null */ -static FILE *g_file; /* File being read */ +FILE *f; /* File being read */ static char sSigName[100]; /* Full path name of .sig file */ -static uint16_t *T1base, *T2base; /* Pointers to start of T1, T2 */ -static uint16_t *g; /* g[] */ +static word *T1base, *T2base; /* Pointers to start of T1, T2 */ +static word *g; /* g[] */ static HT *ht; /* The hash table */ static PH_FUNC_STRUCT *pFunc; /* Points to the array of func names */ -static hlType *pArg=0; /* Points to the array of param types */ +static hlType *pArg; /* Points to the array of param types */ static int numFunc; /* Number of func names actually stored */ static int numArg; /* Number of param names actually stored */ #define DCCLIBS "dcclibs.dat" /* Name of the prototypes data file */ /* prototypes */ -void grab(int n, FILE *_file); -uint16_t readFileShort(FILE *_file); -void readFileSection(uint16_t* p, int len, FILE *_file); +void grab(int n, FILE *f); +word readFileShort(FILE *f); +void readFileSection(word* p, int len, FILE *f); void cleanup(void); void checkStartup(STATE *state); void readProtoFile(void); @@ -72,17 +71,17 @@ void fixNewline(char *s); int searchPList(char *name); void checkHeap(char *msg); /* For debugging */ -void fixWildCards(uint8_t pat[]); /* In fixwild.c */ +void fixWildCards(byte pat[]); /* In fixwild.c */ -static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern, - int iPatLen, int *index); +boolT locatePattern(byte *source, Int iMin, Int iMax, byte *pattern, + Int iPatLen, Int *index); /* * * * * * * * * * * * * * * *\ * * * S t a r t P a t t e r n s ( V e n d o r i d ) * * * \* * * * * * * * * * * * * * * */ -static uint8_t pattMsC5Start[] = +static byte pattMsC5Start[] = { 0xB4, 0x30, /* Mov ah, 30 */ 0xCD, 0x21, /* int 21 (dos version number) */ @@ -91,7 +90,7 @@ static uint8_t pattMsC5Start[] = 0xCD, 0x20, /* int 20 (exit) */ 0xBF /* Mov di, DSEG */ }; -static uint8_t pattMsC8Start[] = +static byte pattMsC8Start[] = { 0xB4, 0x30, /* Mov ah, 30 */ 0xCD, 0x21, /* int 21 */ @@ -102,7 +101,7 @@ static uint8_t pattMsC8Start[] = 0xCB, /* retf */ 0xBF /* mov di, DSEG */ }; -static uint8_t pattMsC8ComStart[] = +static byte pattMsC8ComStart[] = { 0xB4, 0x30, /* Mov ah, 30 */ 0xCD, 0x21, /* int 21 (dos version number) */ @@ -111,11 +110,11 @@ static uint8_t pattMsC8ComStart[] = 0xC3, /* ret */ 0x8C, 0xDF /* Mov di, ds */ }; -static uint8_t pattBorl2Start[] = +static byte pattBorl2Start[] = { 0xBA, WILD, WILD, /* Mov dx, dseg */ 0x2E, 0x89, 0x16, /* mov cs:[], dx */ - WILD, WILD, + WILD, WILD, 0xB4, 0x30, /* mov ah, 30 */ 0xCD, 0x21, /* int 21 (dos version number) */ 0x8B, 0x2E, 0x02, 0, /* mov bp, [2] */ @@ -127,11 +126,11 @@ static uint8_t pattBorl2Start[] = 0x89, 0x2E, WILD, WILD, /* mov [xx], bp */ 0xC7 /* mov [xx], -1 */ }; -static uint8_t pattBorl3Start[] = +static byte pattBorl3Start[] = { 0xBA, WILD, WILD, /* Mov dx, dseg */ 0x2E, 0x89, 0x16, /* mov cs:[], dx */ - WILD, WILD, + WILD, WILD, 0xB4, 0x30, /* mov ah, 30 */ 0xCD, 0x21, /* int 21 (dos version number) */ 0x8B, 0x2E, 0x02, 0, /* mov bp, [2] */ @@ -144,52 +143,52 @@ static uint8_t pattBorl3Start[] = 0xE8 /* call ... */ }; -static uint8_t pattBorl4on[] = +static byte pattBorl4on[] = { 0x9A, 0, 0, WILD, WILD /* Call init (offset always 0) */ }; -static uint8_t pattBorl4Init[] = +static byte pattBorl4Init[] = { - 0xBA, WILD, WILD, /* Mov dx, dseg */ + 0xBA, WILD, WILD, /* Mov dx, dseg */ 0x8E, 0xDA, /* mov ds, dx */ 0x8C, 0x06, WILD, WILD, /* mov [xx], es */ - 0x8B, 0xC4, /* mov ax, sp */ - 0x05, 0x13, 0, /* add ax, 13h */ - 0xB1, 0x04, /* mov cl, 4 */ - 0xD3, 0xE8, /* shr ax, cl */ - 0x8C, 0xD2 /* mov dx, ss */ + 0x8B, 0xC4, /* mov ax, sp */ + 0x05, 0x13, 0, /* add ax, 13h */ + 0xB1, 0x04, /* mov cl, 4 */ + 0xD3, 0xE8, /* shr ax, cl */ + 0x8C, 0xD2 /* mov dx, ss */ }; -static uint8_t pattBorl5Init[] = +static byte pattBorl5Init[] = { - 0xBA, WILD, WILD, /* Mov dx, dseg */ + 0xBA, WILD, WILD, /* Mov dx, dseg */ 0x8E, 0xDA, /* mov ds, dx */ 0x8C, 0x06, 0x30, 0, /* mov [0030], es */ - 0x33, 0xED, /* xor bp, bp <----- */ - 0x8B, 0xC4, /* mov ax, sp */ - 0x05, 0x13, 0, /* add ax, 13h */ - 0xB1, 0x04, /* mov cl, 4 */ - 0xD3, 0xE8, /* shr ax, cl */ - 0x8C, 0xD2 /* mov dx, ss */ + 0x33, 0xED, /* xor bp, bp <----- */ + 0x8B, 0xC4, /* mov ax, sp */ + 0x05, 0x13, 0, /* add ax, 13h */ + 0xB1, 0x04, /* mov cl, 4 */ + 0xD3, 0xE8, /* shr ax, cl */ + 0x8C, 0xD2 /* mov dx, ss */ }; -static uint8_t pattBorl7Init[] = +static byte pattBorl7Init[] = { - 0xBA, WILD, WILD, /* Mov dx, dseg */ + 0xBA, WILD, WILD, /* Mov dx, dseg */ 0x8E, 0xDA, /* mov ds, dx */ 0x8C, 0x06, 0x30, 0, /* mov [0030], es */ - 0xE8, WILD, WILD, /* call xxxx */ - 0xE8, WILD, WILD, /* call xxxx... offset always 00A0? */ - 0x8B, 0xC4, /* mov ax, sp */ - 0x05, 0x13, 0, /* add ax, 13h */ - 0xB1, 0x04, /* mov cl, 4 */ - 0xD3, 0xE8, /* shr ax, cl */ - 0x8C, 0xD2 /* mov dx, ss */ + 0xE8, WILD, WILD, /* call xxxx */ + 0xE8, WILD, WILD, /* call xxxx... offset always 00A0? */ + 0x8B, 0xC4, /* mov ax, sp */ + 0x05, 0x13, 0, /* add ax, 13h */ + 0xB1, 0x04, /* mov cl, 4 */ + 0xD3, 0xE8, /* shr ax, cl */ + 0x8C, 0xD2 /* mov dx, ss */ }; -static uint8_t pattLogiStart[] = +static byte pattLogiStart[] = { 0xEB, 0x04, /* jmp short $+6 */ WILD, WILD, /* Don't know what this is */ @@ -198,7 +197,7 @@ static uint8_t pattLogiStart[] = 0x8E, 0xD8 /* mov ds, ax */ }; -static uint8_t pattTPasStart[] = +static byte pattTPasStart[] = { 0xE9, 0x79, 0x2C /* Jmp 2D7C - Turbo pascal 3.0 */ }; @@ -213,34 +212,34 @@ static uint8_t pattTPasStart[] = /* This pattern works for MS and Borland, small and tiny model */ -static uint8_t pattMainSmall[] = +static byte pattMainSmall[] = { 0xFF, 0x36, WILD, WILD, /* Push environment pointer */ 0xFF, 0x36, WILD, WILD, /* Push argv */ 0xFF, 0x36, WILD, WILD, /* Push argc */ 0xE8, WILD, WILD /* call _main */ - /* 0x50, /* push ax... not in Borland V3 */ - /* 0xE8 /* call _exit */ +/* 0x50, /* push ax... not in Borland V3 */ +/* 0xE8 /* call _exit */ }; /* Num bytes from start pattern to the relative offset of main() */ #define OFFMAINSMALL 13 /* This pattern works for MS and Borland, medium model */ -static uint8_t pattMainMedium[] = +static byte pattMainMedium[] = { 0xFF, 0x36, WILD, WILD, /* Push environment pointer */ 0xFF, 0x36, WILD, WILD, /* Push argv */ 0xFF, 0x36, WILD, WILD, /* Push argc */ 0x9A, WILD, WILD, WILD, WILD /* call far _main */ - /* 0x50 /* push ax */ - /* 0x0E, /* push cs NB not tested Borland */ - /* 0xE8 /* call _exit */ +/* 0x50 /* push ax */ +/* 0x0E, /* push cs NB not tested Borland */ +/* 0xE8 /* call _exit */ }; /* Num bytes from start pattern to the relative offset of main() */ #define OFFMAINMEDIUM 13 /* This pattern works for MS and Borland, compact model */ -static uint8_t pattMainCompact[] = +static byte pattMainCompact[] = { 0xFF, 0x36, WILD, WILD, /* Push environment pointer lo */ 0xFF, 0x36, WILD, WILD, /* Push environment pointer hi */ @@ -248,14 +247,14 @@ static uint8_t pattMainCompact[] = 0xFF, 0x36, WILD, WILD, /* Push argv hi */ 0xFF, 0x36, WILD, WILD, /* Push argc */ 0xE8, WILD, WILD, /* call _main */ - /* 0x50, /* push ax */ - /* 0xE8 /* call _exit */ +/* 0x50, /* push ax */ +/* 0xE8 /* call _exit */ }; /* Num bytes from start pattern to the relative offset of main() */ #define OFFMAINCOMPACT 21 /* This pattern works for MS and Borland, large model */ -static uint8_t pattMainLarge[] = +static byte pattMainLarge[] = { 0xFF, 0x36, WILD, WILD, /* Push environment pointer lo */ 0xFF, 0x36, WILD, WILD, /* Push environment pointer hi */ @@ -263,9 +262,9 @@ static uint8_t pattMainLarge[] = 0xFF, 0x36, WILD, WILD, /* Push argv hi */ 0xFF, 0x36, WILD, WILD, /* Push argc */ 0x9A, WILD, WILD, WILD, WILD /* call far _main */ - /* 0x50 /* push ax */ - /* 0x0E, /* push cs */ - /* 0xE8 /* call _exit */ +/* 0x50 /* push ax */ +/* 0x0E, /* push cs */ +/* 0xE8 /* call _exit */ }; /* Num bytes from start pattern to the relative offset of main() */ #define OFFMAINLARGE 21 @@ -278,134 +277,133 @@ static uint8_t pattMainLarge[] = \* * * * * * * * * * * * * * * */ /* This pattern is for the stack check code in Microsoft compilers */ -static uint8_t pattMsChkstk[] = +static byte pattMsChkstk[] = { - 0x59, /* pop cx */ - 0x8B, 0xDC, /* mov bx, sp */ - 0x2B, 0xD8, /* sub bx, ax */ - 0x72, 0x0A, /* jb bad */ - 0x3B, 0x1E, WILD, WILD, /* cmp bx, XXXX */ - 0x72, 0x04, /* jb bad */ - 0x8B, 0xE3, /* mov sp, bx */ - 0xFF, 0xE1, /* jmp [cx] */ - 0x33, 0xC0, /* xor ax, ax */ - 0xE9 /* jmp XXXX */ + 0x59, /* pop cx */ + 0x8B, 0xDC, /* mov bx, sp */ + 0x2B, 0xD8, /* sub bx, ax */ + 0x72, 0x0A, /* jb bad */ + 0x3B, 0x1E, WILD, WILD, /* cmp bx, XXXX */ + 0x72, 0x04, /* jb bad */ + 0x8B, 0xE3, /* mov sp, bx */ + 0xFF, 0xE1, /* jmp [cx] */ + 0x33, 0xC0, /* xor ax, ax */ + 0xE9 /* jmp XXXX */ }; /* This procedure is called to initialise the library check code */ -void SetupLibCheck(void) +void +SetupLibCheck(void) { - PROG &prog(Project::get()->prog); - uint16_t w, len; + word w, len; int i; - if ((g_file = fopen(sSigName, "rb")) == NULL) + if ((f = fopen(sSigName, "rb")) == NULL) { printf("Warning: cannot open signature file %s\n", sSigName); - return; + return; } readProtoFile(); - prog.bSigs = false; /* False unless everything goes right */ + prog.bSigs = FALSE; /* False unless everything goes right */ /* Read the parameters */ - grab(4, g_file); + grab(4, f); if (memcmp("dccs", buf, 4) != 0) { printf("Not a dcc signature file!\n"); exit(3); } - numKeys = readFileShort(g_file); - numVert = readFileShort(g_file); - PatLen = readFileShort(g_file); - SymLen = readFileShort(g_file); + numKeys = readFileShort(f); + numVert = readFileShort(f); + PatLen = readFileShort(f); + SymLen = readFileShort(f); if ((PatLen != PATLEN) || (SymLen != SYMLEN)) { printf("Sorry! Compiled for sym and pattern lengths of %d and %d\n", - SYMLEN, PATLEN); + SYMLEN, PATLEN); exit(1); } /* Initialise the perfhlib stuff. Also allocates T1, T2, g, etc */ - /* Set the parameters for the hash table */ - g_pattern_hasher.init( - numKeys, /* The number of symbols */ - PatLen, /* The length of the pattern to be hashed */ - 256, /* The character set of the pattern (0-FF) */ - 0, /* Minimum pattern character value */ - numVert); /* Specifies c, the sparseness of the graph. + hashParams( /* Set the parameters for the hash table */ + numKeys, /* The number of symbols */ + PatLen, /* The length of the pattern to be hashed */ + 256, /* The character set of the pattern (0-FF) */ + 0, /* Minimum pattern character value */ + numVert); /* Specifies c, the sparseness of the graph. See Czech, Havas and Majewski for details */ - T1base = g_pattern_hasher.readT1(); - T2base = g_pattern_hasher.readT2(); - g = g_pattern_hasher.readG(); + + T1base = readT1(); + T2base = readT2(); + g = readG(); /* Read T1 and T2 tables */ - grab(2, g_file); + grab(2, f); if (memcmp("T1", buf, 2) != 0) { printf("Expected 'T1'\n"); exit(3); } - len = (uint16_t) (PatLen * 256 * sizeof(uint16_t)); - w = readFileShort(g_file); + len = (word) (PatLen * 256 * sizeof(word)); + w = readFileShort(f); if (w != len) { printf("Problem with size of T1: file %d, calc %d\n", w, len); exit(4); } - readFileSection(T1base, len, g_file); + readFileSection(T1base, len, f); - grab(2, g_file); + grab(2, f); if (memcmp("T2", buf, 2) != 0) { printf("Expected 'T2'\n"); exit(3); } - w = readFileShort(g_file); + w = readFileShort(f); if (w != len) { printf("Problem with size of T2: file %d, calc %d\n", w, len); exit(4); } - readFileSection(T2base, len, g_file); + readFileSection(T2base, len, f); /* Now read the function g[] */ - grab(2, g_file); + grab(2, f); if (memcmp("gg", buf, 2) != 0) { printf("Expected 'gg'\n"); exit(3); } - len = (uint16_t)(numVert * sizeof(uint16_t)); - w = readFileShort(g_file); + len = (word)(numVert * sizeof(word)); + w = readFileShort(f); if (w != len) { printf("Problem with size of g[]: file %d, calc %d\n", w, len); exit(4); } - readFileSection(g, len, g_file); + readFileSection(g, len, f); /* This is now the hash table */ /* First allocate space for the table */ - ht = new HT[numKeys]; - if ( 0 == ht) + if ((ht = (HT *)allocMem(numKeys * sizeof(HT))) == 0) { printf("Could not allocate hash table\n"); exit(1); } - grab(2, g_file); + grab(2, f); if (memcmp("ht", buf, 2) != 0) { printf("Expected 'ht'\n"); exit(3); } - w = readFileShort(g_file); - if (w != numKeys * (SymLen + PatLen + sizeof(uint16_t))) + w = readFileShort(f); + if (w != numKeys * (SymLen + PatLen + sizeof(word))) { printf("Problem with size of hash table: file %d, calc %d\n", w, len); exit(6); @@ -414,136 +412,143 @@ void SetupLibCheck(void) for (i=0; i < numKeys; i++) { - if (fread(&ht[i], 1, SymLen + PatLen, g_file) != SymLen + PatLen) + if (fread(&ht[i], 1, SymLen + PatLen, f) != SymLen + PatLen) { printf("Could not read signature\n"); exit(11); } } - fclose(g_file); - prog.bSigs = true; + fclose(f); + prog.bSigs = TRUE; } -void CleanupLibCheck(void) +void +CleanupLibCheck(void) { /* Deallocate all the stuff allocated in SetupLibCheck() */ - delete [] ht; - delete [] pFunc; + if (T1base) free(T1base); + if (T1base) free(T2base); + if (g) free(g); + if (ht) free(ht); + if (pFunc)free(pFunc); } -/* Check this function to see if it is a library function. Return true if +/* Check this function to see if it is a library function. Return TRUE if it is, and copy its name to pProc->name */ -bool LibCheck(Function & pProc) +boolT +LibCheck(PPROC pProc) { - PROG &prog(Project::get()->prog); long fileOffset; int h, i, j, arg; - int Idx; - uint8_t pat[PATLEN]; + Int Idx; + byte pat[PATLEN]; - if (prog.bSigs == false) - { - /* No signatures... can't rely on hash parameters to be initialised - so always return false */ - return false; - } + if (prog.bSigs == FALSE) + { + /* No signatures... can't rely on hash parameters to be initialised + so always return false */ + return FALSE; + } - fileOffset = pProc.procEntry; /* Offset into the image */ + fileOffset = pProc->procEntry; /* Offset into the image */ if (fileOffset == prog.offMain) { /* Easy - this function is called main! */ - pProc.name = "main"; - return false; + strcpy(pProc->name, "main"); + return FALSE; } - memcpy(pat, &prog.Image[fileOffset], PATLEN); - //memmove(pat, &prog.Image[fileOffset], PATLEN); + + memmove(pat, &prog.Image[fileOffset], PATLEN); fixWildCards(pat); /* Fix wild cards in the copy */ - h = g_pattern_hasher.hash(pat); /* Hash the found proc */ + h = hash(pat); /* Hash the found proc */ /* We always have to compare keys, because the hash function will always return a valid index */ if (memcmp(ht[h].htPat, pat, PATLEN) == 0) { /* We have a match. Save the name, if not already set */ - if (pProc.name.empty() ) /* Don't overwrite existing name */ + if (pProc->name[0] == '\0') /* Don't overwrite existing name */ { /* Give proc the new name */ - pProc.name = ht[h].htSym; + strcpy(pProc->name, ht[h].htSym); } /* But is it a real library function? */ i = NIL; if ((numFunc == 0) || (i=searchPList(ht[h].htSym)) != NIL) { - pProc.flg |= PROC_ISLIB; /* It's a lib function */ + pProc->flg |= PROC_ISLIB; /* It's a lib function */ if (i != NIL) { /* Allocate space for the arg struct, and copy the hlType to the appropriate field */ arg = pFunc[i].firstArg; - pProc.args.numArgs = pFunc[i].numArg; - pProc.args.resize(pFunc[i].numArg); + pProc->args.csym = pFunc[i].numArg; + pProc->args.alloc = pFunc[i].numArg; + pProc->args.numArgs = pFunc[i].numArg; + pProc->args.sym = (STKSYM*)allocMem(pFunc[i].numArg * sizeof(STKSYM)); + memset(pProc->args.sym, 0, pFunc[i].numArg * sizeof(STKSYM)); for (j=0; j < pFunc[i].numArg; j++) { - pProc.args[j].type = pArg[arg++]; + pProc->args.sym[j].type = pArg[arg++]; } - if (pFunc[i].typ != TYPE_UNKNOWN) - { - pProc.retVal.type = pFunc[i].typ; - pProc.flg |= PROC_IS_FUNC; - switch (pProc.retVal.type) { - case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: - pProc.liveOut = duReg[rDX] | duReg[rAX]; - break; - case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: - pProc.liveOut = duReg[rAX]; - break; - case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: - pProc.liveOut = duReg[rAL]; - break; - /*** other types are not considered yet ***/ - } - } - if (pFunc[i].bVararg) - pProc.flg |= PROC_VARARG; + if (pFunc[i].typ != TYPE_UNKNOWN) + { + pProc->retVal.type = pFunc[i].typ; + pProc->flg |= PROC_IS_FUNC; + switch (pProc->retVal.type) { + case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: + pProc->liveOut = duReg[rDX] | duReg[rAX]; + break; + case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: + pProc->liveOut = duReg[rAX]; + break; + case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: + pProc->liveOut = duReg[rAL]; + break; + /*** other types are not considered yet ***/ + } + } + if (pFunc[i].bVararg) pProc->flg |= PROC_VARARG; } } else if (i == NIL) { /* Have a symbol for it, but does not appear in a header file. Treat it as if it is not a library function */ - pProc.flg |= PROC_RUNTIME; /* => is a runtime routine */ + pProc->flg |= PROC_RUNTIME; /* => is a runtime routine */ } } - if (locatePattern(prog.Image, pProc.procEntry, - pProc.procEntry+sizeof(pattMsChkstk), - pattMsChkstk, sizeof(pattMsChkstk), &Idx)) - { - /* Found _chkstk */ - pProc.name = "chkstk"; - pProc.flg |= PROC_ISLIB; /* We'll say its a lib function */ - pProc.args.numArgs = 0; /* With no args */ - } - return (boolT)((pProc.flg & PROC_ISLIB) != 0); + if (locatePattern(prog.Image, pProc->procEntry, + pProc->procEntry+sizeof(pattMsChkstk), + pattMsChkstk, sizeof(pattMsChkstk), &Idx)) + { + /* Found _chkstk */ + strcpy(pProc->name, "chkstk"); + pProc->flg |= PROC_ISLIB; /* We'll say its a lib function */ + pProc->args.numArgs = 0; /* With no args */ + } + + return (boolT)((pProc->flg & PROC_ISLIB) != 0); } -void grab(int n, FILE *_file) +void grab(int n, FILE *f) { - if (fread(buf, 1, n, _file) != (unsigned)n) + if (fread(buf, 1, n, f) != (unsigned)n) { printf("Could not grab\n"); exit(11); } } -uint16_t +word readFileShort(FILE *f) { - uint8_t b1, b2; + byte b1, b2; if (fread(&b1, 1, 1, f) != 1) { @@ -555,21 +560,21 @@ readFileShort(FILE *f) printf("Could not read short\n"); exit(11); } - return (uint16_t)(b2 << 8) + (uint16_t)b1; + return (word)(b2 << 8) + (word)b1; } // Read a section of the file, considering endian issues void -readFileSection(uint16_t* p, int len, FILE* f) +readFileSection(word* p, int len, FILE* f) { - for (int i=0; i < len; i += 2) - { - *p++ = readFileShort(f); - } + for (int i=0; i < len; i += 2) + { + *p++ = readFileShort(f); + } } /* The following two functions are dummies, since we don't call map() */ -void getKey(int i, uint8_t **keys) +void getKey(int i, byte **keys) { } @@ -581,16 +586,17 @@ void dispKey(int i) /* Search the source array between limits iMin and iMax for the pattern (length iPatLen). The pattern can contain wild bytes; if you really want to match - for the pattern that is used up by the WILD uint8_t, tough - it will match with + for the pattern that is used up by the WILD byte, tough - it will match with everything else as well. */ -static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern, int iPatLen, - int *index) +boolT +locatePattern(byte *source, Int iMin, Int iMax, byte *pattern, Int iPatLen, + Int *index) { - int i, j; - uint8_t *pSrc; /* Pointer to start of considered source */ - int iLast; + Int i, j; + byte *pSrc; /* Pointer to start of considered source */ + Int iLast; - iLast = iMax - iPatLen; /* Last source uint8_t to consider */ + iLast = iMax - iPatLen; /* Last source byte to consider */ for (i=iMin; i <= iLast; i++) { @@ -598,13 +604,12 @@ static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern /* i is the index of the start of the moving pattern */ for (j=0; j < iPatLen; j++) { - /* j is the index of the uint8_t being considered in the pattern. */ - if ((*pSrc != pattern[j]) && (pattern[j] != WILD)) + /* j is the index of the byte being considered in the pattern. */ + if ((*pSrc++ != pattern[j]) && (pattern[j] != WILD)) { /* A definite mismatch */ break; /* Break to outer loop */ } - pSrc++; } if (j >= iPatLen) { @@ -620,143 +625,136 @@ static boolT locatePattern(uint8_t *source, int iMin, int iMax, uint8_t *pattern } -void STATE::checkStartup() +void +checkStartup(STATE *pState) { - PROG &prog(Project::get()->prog); /* This function checks the startup code for various compilers' way of loading DS. If found, it sets DS. This may not be needed in the future if pushing and popping of registers is implemented. Also sets prog.offMain and prog.segMain if possible */ - int startOff; /* Offset into the Image of the initial CS:IP */ - int i, rel, para, init; + Int startOff; /* Offset into the Image of the initial CS:IP */ + Int i, rel, para, init; char chModel = 'x'; char chVendor = 'x'; char chVersion = 'x'; char *pPath; char temp[4]; - startOff = ((uint32_t)prog.initCS << 4) + prog.initIP; + startOff = ((dword)prog.initCS << 4) + prog.initIP; - /* Check the Turbo Pascal signatures first, since they involve only the - first 3 bytes, and false positives may be founf with the others later */ - if (locatePattern(prog.Image, startOff, startOff+5, pattBorl4on,sizeof(pattBorl4on), &i)) + /* Check the Turbo Pascal signatures first, since they involve only the + first 3 bytes, and false positives may be founf with the others later */ + if (locatePattern(prog.Image, startOff, startOff+5, pattBorl4on, + sizeof(pattBorl4on), &i)) { - /* The first 5 bytes are a far call. Follow that call and - determine the version from that */ + /* The first 5 bytes are a far call. Follow that call and + determine the version from that */ rel = LH(&prog.Image[startOff+1]); /* This is abs off of init */ para= LH(&prog.Image[startOff+3]);/* This is abs seg of init */ - init = ((uint32_t)para << 4) + rel; - if (locatePattern(prog.Image, init, init+26, pattBorl4Init, - sizeof(pattBorl4Init), &i)) - { + init = ((dword)para << 4) + rel; + if (locatePattern(prog.Image, init, init+26, pattBorl4Init, + sizeof(pattBorl4Init), &i)) + { - setState(rDS, LH(&prog.Image[i+1])); - printf("Borland Pascal v4 detected\n"); - chVendor = 't'; /* Trubo */ - chModel = 'p'; /* Pascal */ - chVersion = '4'; /* Version 4 */ - prog.offMain = startOff; /* Code starts immediately */ - prog.segMain = prog.initCS; /* At the 5 uint8_t jump */ - goto gotVendor; /* Already have vendor */ - } - else if (locatePattern(prog.Image, init, init+26, pattBorl5Init, - sizeof(pattBorl5Init), &i)) - { + setState(pState, rDS, LH(&prog.Image[i+1])); +printf("Borland Pascal v4 detected\n"); + chVendor = 't'; /* Trubo */ + chModel = 'p'; /* Pascal */ + chVersion = '4'; /* Version 4 */ + prog.offMain = startOff; /* Code starts immediately */ + prog.segMain = prog.initCS; /* At the 5 byte jump */ + goto gotVendor; /* Already have vendor */ + } + else if (locatePattern(prog.Image, init, init+26, pattBorl5Init, + sizeof(pattBorl5Init), &i)) + { - setState( rDS, LH(&prog.Image[i+1])); - printf("Borland Pascal v5.0 detected\n"); - chVendor = 't'; /* Trubo */ - chModel = 'p'; /* Pascal */ - chVersion = '5'; /* Version 5 */ - prog.offMain = startOff; /* Code starts immediately */ - prog.segMain = prog.initCS; - goto gotVendor; /* Already have vendor */ - } - else if (locatePattern(prog.Image, init, init+26, pattBorl7Init, - sizeof(pattBorl7Init), &i)) - { + setState(pState, rDS, LH(&prog.Image[i+1])); +printf("Borland Pascal v5.0 detected\n"); + chVendor = 't'; /* Trubo */ + chModel = 'p'; /* Pascal */ + chVersion = '5'; /* Version 5 */ + prog.offMain = startOff; /* Code starts immediately */ + prog.segMain = prog.initCS; + goto gotVendor; /* Already have vendor */ + } + else if (locatePattern(prog.Image, init, init+26, pattBorl7Init, + sizeof(pattBorl7Init), &i)) + { - setState( rDS, LH(&prog.Image[i+1])); - printf("Borland Pascal v7 detected\n"); - chVendor = 't'; /* Trubo */ - chModel = 'p'; /* Pascal */ - chVersion = '7'; /* Version 7 */ - prog.offMain = startOff; /* Code starts immediately */ - prog.segMain = prog.initCS; - goto gotVendor; /* Already have vendor */ - } + setState(pState, rDS, LH(&prog.Image[i+1])); +printf("Borland Pascal v7 detected\n"); + chVendor = 't'; /* Trubo */ + chModel = 'p'; /* Pascal */ + chVersion = '7'; /* Version 7 */ + prog.offMain = startOff; /* Code starts immediately */ + prog.segMain = prog.initCS; + goto gotVendor; /* Already have vendor */ + } - } + } /* Search for the call to main pattern. This is compiler independant, but decides the model required. Note: must do the far data models (large and compact) before the others, since they are the same pattern as near data, just more pushes at the start. */ - if(prog.cbImage>startOff+0x180+sizeof(pattMainLarge)) + if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainLarge, + sizeof(pattMainLarge), &i)) { - if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainLarge,sizeof(pattMainLarge), &i)) - { - rel = LH(&prog.Image[i+OFFMAINLARGE]); /* This is abs off of main */ - para= LH(&prog.Image[i+OFFMAINLARGE+2]);/* This is abs seg of main */ - /* Save absolute image offset */ - prog.offMain = ((uint32_t)para << 4) + rel; - prog.segMain = (uint16_t)para; - chModel = 'l'; /* Large model */ - } - else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainCompact, - sizeof(pattMainCompact), &i)) - { - rel = LH_SIGNED(&prog.Image[i+OFFMAINCOMPACT]);/* This is the rel addr of main */ - prog.offMain = i+OFFMAINCOMPACT+2+rel; /* Save absolute image offset */ - prog.segMain = prog.initCS; - chModel = 'c'; /* Compact model */ - } - else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainMedium, - sizeof(pattMainMedium), &i)) - { - rel = LH(&prog.Image[i+OFFMAINMEDIUM]); /* This is abs off of main */ - para= LH(&prog.Image[i+OFFMAINMEDIUM+2]);/* This is abs seg of main */ - prog.offMain = ((uint32_t)para << 4) + rel; - prog.segMain = (uint16_t)para; - chModel = 'm'; /* Medium model */ - } - else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainSmall, - sizeof(pattMainSmall), &i)) - { - rel = LH_SIGNED(&prog.Image[i+OFFMAINSMALL]); /* This is rel addr of main */ - prog.offMain = i+OFFMAINSMALL+2+rel; /* Save absolute image offset */ - prog.segMain = prog.initCS; - chModel = 's'; /* Small model */ - } - else if (memcmp(&prog.Image[startOff], pattTPasStart, sizeof(pattTPasStart)) == 0) - { - rel = LH_SIGNED(&prog.Image[startOff+1]); /* Get the jump offset */ - prog.offMain = rel+startOff+3; /* Save absolute image offset */ - prog.offMain += 0x20; /* These first 32 bytes are setting up */ - prog.segMain = prog.initCS; - chVendor = 't'; /* Turbo.. */ - chModel = 'p'; /* ...Pascal... (only 1 model) */ - chVersion = '3'; /* 3.0 */ - printf("Turbo Pascal 3.0 detected\n"); - printf("Main at %04X\n", prog.offMain); - goto gotVendor; /* Already have vendor */ - } - else - { - printf("Main could not be located!\n"); - prog.offMain = -1; - } + rel = LH(&prog.Image[i+OFFMAINLARGE]); /* This is abs off of main */ + para= LH(&prog.Image[i+OFFMAINLARGE+2]);/* This is abs seg of main */ + /* Save absolute image offset */ + prog.offMain = ((dword)para << 4) + rel; + prog.segMain = (word)para; + chModel = 'l'; /* Large model */ + } + else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainCompact, + sizeof(pattMainCompact), &i)) + { + rel = LHS(&prog.Image[i+OFFMAINCOMPACT]);/* This is the rel addr of main */ + prog.offMain = i+OFFMAINCOMPACT+2+rel; /* Save absolute image offset */ + prog.segMain = prog.initCS; + chModel = 'c'; /* Compact model */ + } + else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainMedium, + sizeof(pattMainMedium), &i)) + { + rel = LH(&prog.Image[i+OFFMAINMEDIUM]); /* This is abs off of main */ + para= LH(&prog.Image[i+OFFMAINMEDIUM+2]);/* This is abs seg of main */ + prog.offMain = ((dword)para << 4) + rel; + prog.segMain = (word)para; + chModel = 'm'; /* Medium model */ + } + else if (locatePattern(prog.Image, startOff, startOff+0x180, pattMainSmall, + sizeof(pattMainSmall), &i)) + { + rel = LHS(&prog.Image[i+OFFMAINSMALL]); /* This is rel addr of main */ + prog.offMain = i+OFFMAINSMALL+2+rel; /* Save absolute image offset */ + prog.segMain = prog.initCS; + chModel = 's'; /* Small model */ + } + else if (memcmp(&prog.Image[startOff], pattTPasStart, sizeof(pattTPasStart)) == 0) + { + rel = LHS(&prog.Image[startOff+1]); /* Get the jump offset */ + prog.offMain = rel+startOff+3; /* Save absolute image offset */ + prog.offMain += 0x20; /* These first 32 bytes are setting up */ + prog.segMain = prog.initCS; + chVendor = 't'; /* Turbo.. */ + chModel = 'p'; /* ...Pascal... (only 1 model) */ + chVersion = '3'; /* 3.0 */ +printf("Turbo Pascal 3.0 detected\n"); +printf("Main at %04X\n", prog.offMain); + goto gotVendor; /* Already have vendor */ } else { printf("Main could not be located!\n"); prog.offMain = -1; } - - printf("Model: %c\n", chModel); +printf("Model: %c\n", chModel); /* Now decide the compiler vendor and version number */ @@ -764,64 +762,64 @@ void STATE::checkStartup() { /* Yes, this is Microsoft startup code. The DS is sitting right here in the next 2 bytes */ - setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC5Start)])); + setState(pState, rDS, LH(&prog.Image[startOff+sizeof(pattMsC5Start)])); chVendor = 'm'; /* Microsoft compiler */ chVersion = '5'; /* Version 5 */ - printf("MSC 5 detected\n"); +printf("MSC 5 detected\n"); } /* The C8 startup pattern is different from C5's */ else if (memcmp(&prog.Image[startOff], pattMsC8Start, sizeof(pattMsC8Start)) == 0) { - setState( rDS, LH(&prog.Image[startOff+sizeof(pattMsC8Start)])); - printf("MSC 8 detected\n"); + setState(pState, rDS, LH(&prog.Image[startOff+sizeof(pattMsC8Start)])); +printf("MSC 8 detected\n"); chVendor = 'm'; /* Microsoft compiler */ chVersion = '8'; /* Version 8 */ } /* The C8 .com startup pattern is different again! */ else if (memcmp(&prog.Image[startOff], pattMsC8ComStart, - sizeof(pattMsC8ComStart)) == 0) + sizeof(pattMsC8ComStart)) == 0) { - printf("MSC 8 .com detected\n"); +printf("MSC 8 .com detected\n"); chVendor = 'm'; /* Microsoft compiler */ chVersion = '8'; /* Version 8 */ } else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl2Start, - sizeof(pattBorl2Start), &i)) + sizeof(pattBorl2Start), &i)) { - /* Borland startup. DS is at the second uint8_t (offset 1) */ - setState( rDS, LH(&prog.Image[i+1])); - printf("Borland v2 detected\n"); + /* Borland startup. DS is at the second byte (offset 1) */ + setState(pState, rDS, LH(&prog.Image[i+1])); +printf("Borland v2 detected\n"); chVendor = 'b'; /* Borland compiler */ chVersion = '2'; /* Version 2 */ } else if (locatePattern(prog.Image, startOff, startOff+0x30, pattBorl3Start, - sizeof(pattBorl3Start), &i)) + sizeof(pattBorl3Start), &i)) { - /* Borland startup. DS is at the second uint8_t (offset 1) */ - setState( rDS, LH(&prog.Image[i+1])); - printf("Borland v3 detected\n"); + /* Borland startup. DS is at the second byte (offset 1) */ + setState(pState, rDS, LH(&prog.Image[i+1])); +printf("Borland v3 detected\n"); chVendor = 'b'; /* Borland compiler */ chVersion = '3'; /* Version 3 */ } else if (locatePattern(prog.Image, startOff, startOff+0x30, pattLogiStart, - sizeof(pattLogiStart), &i)) + sizeof(pattLogiStart), &i)) { /* Logitech modula startup. DS is 0, despite appearances */ - printf("Logitech modula detected\n"); +printf("Logitech modula detected\n"); chVendor = 'l'; /* Logitech compiler */ chVersion = '1'; /* Version 1 */ } /* Other startup idioms would go here */ else - { - printf("Warning - compiler not recognised\n"); - } + { + printf("Warning - compiler not recognised\n"); + } gotVendor: @@ -849,7 +847,7 @@ gotVendor: temp[0] = chModel; strcat(sSigName, temp); /* Add model */ strcat(sSigName, ".sig"); /* Add extension */ - printf("Signature file: %s\n", sSigName); +printf("Signature file: %s\n", sSigName); } @@ -860,7 +858,8 @@ gotVendor: by dcc, rather than considered as known functions. When a prototype is found (in searchPList()), the parameter info is written to the proc struct. */ -void readProtoFile(void) +void +readProtoFile(void) { FILE *fProto; char *pPath; /* Point to the environment string */ @@ -907,21 +906,15 @@ void readProtoFile(void) numFunc = readFileShort(fProto); /* Num of entries to allocate */ /* Allocate exactly correct # entries */ - pFunc = new PH_FUNC_STRUCT[numFunc]; + pFunc = (PH_FUNC_STRUCT*) allocMem(numFunc * sizeof(PH_FUNC_STRUCT)); for (i=0; i < numFunc; i++) { - size_t read_size=fread(&pFunc[i], 1, SYMLEN, fProto); - assert(read_size==SYMLEN); - if(read_size!=SYMLEN) - break; + fread(&pFunc[i], 1, SYMLEN, fProto); pFunc[i].typ = (hlType)readFileShort(fProto); pFunc[i].numArg = readFileShort(fProto); pFunc[i].firstArg = readFileShort(fProto); - if(feof(fProto)) - break; - int c = fgetc(fProto); - pFunc[i].bVararg = (c!=0); //fread(&pFunc[i].bVararg, 1, 1, fProto); + fread(&pFunc[i].bVararg, 1, 1, fProto); } grab(2, fProto); @@ -934,12 +927,11 @@ void readProtoFile(void) numArg = readFileShort(fProto); /* Num of entries to allocate */ /* Allocate exactly correct # entries */ - delete [] pArg; - pArg = new hlType[numArg]; + pArg = (hlType*) allocMem(numArg * sizeof(hlType)); for (i=0; i < numArg; i++) { - // fread(&pArg[i], 1, SYMLEN, fProto); /* No names to read as yet */ +// fread(&pArg[i], 1, SYMLEN, fProto); /* No names to read as yet */ pArg[i] = (hlType) readFileShort(fProto); } @@ -979,16 +971,48 @@ searchPList(char *name) } } - /* Still could be the case that mn == mx == required record */ + /* Still could be the case that mn == mx == required record */ res = strcmp(pFunc[mn].name, name); if (res == 0) { return mn; /* Found! */ } - else - { - return NIL; - } + else + { + return NIL; + } } +#if DEBUG_HEAP +void +checkHeap(char *msg) + +/* HEAPCHK.C: This program checks the heap for + * consistency and prints an appropriate message. + */ +{ + int heapstatus; + + printf("%s\n", msg); + + /* Check heap status */ + heapstatus = _heapchk(); + switch( heapstatus ) + { + case _HEAPOK: + printf(" OK - heap is fine\n" ); + break; + case _HEAPEMPTY: + printf(" OK - heap is empty\n" ); + break; + case _HEAPBADBEGIN: + printf( "ERROR - bad start of heap\n" ); + break; + case _HEAPBADNODE: + printf( "ERROR - bad node in heap\n" ); + break; + } +} +#endif + diff --git a/src/comwrite.cpp b/src/comwrite.cpp index 9bd1381..6d34d3f 100644 --- a/src/comwrite.cpp +++ b/src/comwrite.cpp @@ -7,274 +7,258 @@ ****************************************************************************/ #include "dcc.h" -#include "machine_x86.h" #include -#include -using namespace std; #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 uint8_t table", - "Reserved", - "Get extended country information", - "Get or set code page", - "Set handle count", - "Commit file", - "Reserved", - "Reserved", - "Reserved", - "Extended open file" +static 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 */ +static 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 +void writeIntComment (PICODE icode, char *s) +/* Writes the description of the current interrupt. Appends it to the * string s. */ -void LLInst::writeIntComment (std::ostringstream &s) -{ - uint32_t src_immed=src().getImm2(); - s<<"\t/* "; - if (src_immed == 0x21) - { - s <ic.ll.immed.op == 0x21) + { sprintf (t, "\t/* %s */\n", int21h[icode->ic.ll.dst.off]); + strcat (s, t); + } + else if (icode->ic.ll.immed.op > 0x1F && icode->ic.ll.immed.op < 0x2F) + { + sprintf (t, "\t/* %s */\n", intOthers[icode->ic.ll.immed.op - 0x20]); + strcat (s, t); } - else if (src_immed > 0x1F && src_immed < 0x2F) - { - s <ic.ll.immed.op == 0x2F) + switch (icode->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() -{ - std::ostringstream ostr; - writeProcComments(ostr); - cCode.appendDecl(ostr.str()); +void writeProcComments (PPROC p, strTable *strTab) +{ int i; + ID *id; /* Pointer to register argument identifier */ + PSTKSYM psym; /* Pointer to register argument symbol */ + + /* About the parameters */ + if (p->cbParam) + appendStrTab (strTab, "/* Takes %d bytes of parameters.\n", + p->cbParam); + else if (p->flg & REG_ARGS) + { + appendStrTab (strTab, "/* Uses register arguments:\n"); + for (i = 0; i < p->args.numArgs; i++) + { + psym = &p->args.sym[i]; + if (psym->regs->expr.ident.idType == REGISTER) + { + id = &p->localId.id[psym->regs->expr.ident.idNode.regiIdx]; + if (psym->regs->expr.ident.regiType == WORD_REG) + appendStrTab (strTab, " * %s = %s.\n", psym->name, + wordReg[id->id.regi - rAX]); + else /* BYTE_REG */ + appendStrTab (strTab, " * %s = %s.\n", psym->name, + byteReg[id->id.regi - rAL]); + } + else /* long register */ + { + id = &p->localId.id[psym->regs->expr.ident.idNode.longIdx]; + appendStrTab (strTab, " * %s = %s:%s.\n", psym->name, + wordReg[id->id.longId.h - rAX], + wordReg[id->id.longId.l - rAX]); + } + + } + } + else + appendStrTab (strTab, "/* Takes no parameters.\n"); + + /* Type of procedure */ + if (p->flg & PROC_RUNTIME) + appendStrTab (strTab," * Runtime support routine of the compiler.\n"); + if (p->flg & PROC_IS_HLL) + appendStrTab (strTab," * High-level language prologue code.\n"); + if (p->flg & PROC_ASM) + { + appendStrTab (strTab, + " * Untranslatable routine. Assembler provided.\n"); + if (p->flg & PROC_IS_FUNC) + switch (p->retVal.type) { + case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: + appendStrTab (strTab, " * Return value in register al.\n"); + break; + case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: + appendStrTab (strTab, " * Return value in register ax.\n"); + break; + case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: + appendStrTab (strTab, " * Return value in registers dx:ax.\n"); + break; + } /* eos */ + } + + /* Calling convention */ + if (p->flg & CALL_PASCAL) + appendStrTab (strTab, " * Pascal calling convention.\n"); + else if (p->flg & CALL_C) + appendStrTab (strTab, " * C calling convention.\n"); + else if (p->flg & CALL_UNKNOWN) + appendStrTab (strTab, " * Unknown calling convention.\n"); + + /* Other flags */ + if (p->flg & (PROC_BADINST | PROC_IJMP)) + appendStrTab (strTab, " * Incomplete due to an %s.\n", + (p->flg & PROC_BADINST)? "untranslated opcode": + "indirect JMP"); + if (p->flg & PROC_ICALL) + appendStrTab (strTab, " * Indirect call procedure.\n"); + if (p->flg & IMPURE) + appendStrTab (strTab, " * Contains impure code.\n"); + if (p->flg & NOT_HLL) + appendStrTab (strTab, + " * Contains instructions not normally used by compilers.\n"); + if (p->flg & FLOAT_OP) + appendStrTab (strTab," * Contains coprocessor instructions.\n"); + + /* Graph reducibility */ + if (p->flg & GRAPH_IRRED) + appendStrTab (strTab," * Irreducible control flow graph.\n"); + appendStrTab (strTab, " */\n{\n"); } -void Function::writeProcComments(std::ostream &ostr) -{ - int i; - ID *id; /* Pointer to register argument identifier */ - STKSYM * psym; /* Pointer to register argument symbol */ - - /* About the parameters */ - if (this->cbParam) - ostr << "/* Takes "<cbParam<<" bytes of parameters.\n"; - else if (this->flg & REG_ARGS) - { - ostr << "/* Uses register arguments:\n"; - for (i = 0; i < this->args.numArgs; i++) - { - psym = &this->args[i]; - ostr << " * "<name<<" = "; - if (psym->regs->expr.ident.idType == REGISTER) - { - id = &this->localId.id_arr[psym->regs->expr.ident.idNode.regiIdx]; - ostr << Machine_X86::regName(id->id.regi); - } - else /* long register */ - { - id = &this->localId.id_arr[psym->regs->expr.ident.idNode.longIdx]; - ostr << Machine_X86::regName(id->id.longId.h) << ":"; - ostr << Machine_X86::regName(id->id.longId.l); - } - ostr << ".\n"; - - } - } - else - ostr << "/* Takes no parameters.\n"; - - /* Type of procedure */ - if (this->flg & PROC_RUNTIME) - ostr << " * Runtime support routine of the compiler.\n"; - if (this->flg & PROC_IS_HLL) - ostr << " * High-level language prologue code.\n"; - if (this->flg & PROC_ASM) - { - ostr << " * Untranslatable routine. Assembler provided.\n"; - if (this->flg & PROC_IS_FUNC) - switch (this->retVal.type) { // TODO: Functions return value in various regs - case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: - ostr << " * Return value in register al.\n"; - break; - case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: - ostr << " * Return value in register ax.\n"; - break; - case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: - ostr << " * Return value in registers dx:ax.\n"; - break; - } /* eos */ - } - - /* Calling convention */ - if (this->flg & CALL_PASCAL) - ostr << " * Pascal calling convention.\n"; - else if (this->flg & CALL_C) - ostr << " * C calling convention.\n"; - else if (this->flg & CALL_UNKNOWN) - ostr << " * Unknown calling convention.\n"; - - /* Other flags */ - if (this->flg & (PROC_BADINST | PROC_IJMP)) - { - ostr << " * Incomplete due to an "; - if(this->flg & PROC_BADINST) - ostr << "untranslated opcode.\n"; - else - ostr << "indirect JMP.\n"; - } - if (this->flg & PROC_ICALL) - ostr << " * Indirect call procedure.\n"; - if (this->flg & IMPURE) - ostr << " * Contains impure code.\n"; - if (this->flg & NOT_HLL) - ostr << " * Contains instructions not normally used by compilers.\n"; - if (this->flg & FLOAT_OP) - ostr << " * Contains coprocessor instructions.\n"; - - /* Graph reducibility */ - if (this->flg & GRAPH_IRRED) - ostr << " * Irreducible control flow graph.\n"; - ostr << " */\n{\n"; -} diff --git a/src/control.cpp b/src/control.cpp index 4eab9cd..415fe87 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -2,666 +2,727 @@ * Description : Performs control flow analysis on the CFG * (C) Cristina Cifuentes ********************************************************************/ -#include -#include -#include -#include -#include -#include -#include #include "dcc.h" +#include +#include +#if __BORLAND__ +#include +#else +#include +#endif + +typedef struct list { + Int nodeIdx; /* dfsLast index to the node */ + struct list *next; +} nodeList; -//typedef struct list { -// int nodeIdx; -// struct list *next; -//} nodeList; -typedef std::list 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 +/* 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 +static boolT isBackEdge (PBB p,PBB s) +/* 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. + * then it is a backedge. * Also incrementes the number of backedges entries to the header node. */ -static bool isBackEdge (BB * p,BB * s) { - if (p->dfsFirstNum >= s->dfsFirstNum) - { - s->numBackEdges++; - return true; - } - return false; + if (p->dfsFirstNum >= s->dfsFirstNum) + { + s->numBackEdges++; + return (TRUE); + } + return (FALSE); } +static Int commonDom (Int currImmDom, Int predImmDom, PPROC pProc) /* Finds the common dominator of the current immediate dominator - * currImmDom and its predecessor's immediate dominator predImmDom */ -static int commonDom (int currImmDom, int predImmDom, Function * pProc) + * currImmDom and its predecessor's immediate dominator predImmDom */ { if (currImmDom == NO_DOM) - return (predImmDom); + return (predImmDom); if (predImmDom == NO_DOM) /* predecessor is the root */ - return (currImmDom); + return (currImmDom); while ((currImmDom != NO_DOM) && (predImmDom != NO_DOM) && (currImmDom != predImmDom)) { - if (currImmDom < predImmDom) - predImmDom = pProc->m_dfsLast[predImmDom]->immedDom; - else - currImmDom = pProc->m_dfsLast[currImmDom]->immedDom; + 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. +static void findImmedDom (PPROC pProc) +/* 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. + * immediate dominators only. * Note: graph should be reducible */ -void Function::findImmedDom () -{ - BB * currNode; - for (size_t currIdx = 0; currIdx < numBBs; currIdx++) +{ PBB currNode; + Int currIdx, j, predIdx; + + for (currIdx = 0; currIdx < pProc->numBBs; currIdx++) { - currNode = m_dfsLast[currIdx]; - if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */ - continue; - for (BB * inedge : currNode->inEdges) - { - size_t predIdx = inedge->dfsLastNum; - if (predIdx < currIdx) - currNode->immedDom = commonDom (currNode->immedDom, predIdx, this); - } + currNode = pProc->dfsLast[currIdx]; + if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */ + continue; + + for (j = 0; j < currNode->numInEdges; j++) + { + predIdx = currNode->inEdges[j]->dfsLastNum; + if (predIdx < currIdx) + currNode->immedDom = commonDom (currNode->immedDom, + predIdx, pProc); + } } } +static void insertList (nodeList **l, Int n) /* Inserts the node n to the list l. */ -static void insertList (nodeList &l, int n) { - l.push_back(n); + nodeList *newNode; + + newNode = allocStruc(nodeList); + memset(newNode, 0, sizeof(nodeList)); + newNode->nodeIdx = n; + newNode->next = *l; + *l = newNode; } -/* Returns whether or not the node n (dfsLast numbering of a basic block) +static boolT inList (nodeList *l, Int n) +/* Returns whether or not the node n (dfsLast numbering of a basic block) * is on the list l. */ -static bool inList (const nodeList &l, int n) { - return std::find(l.begin(),l.end(),n)!=l.end(); + while (l) + if (l->nodeIdx == n) + return (TRUE); + else + l = l->next; + return (FALSE); } +static void freeList (nodeList **l) /* Frees space allocated by the list l. */ -static void freeList (nodeList &l) -{ - l.clear(); +{ nodeList *next; + + if (*l) + { + next = (*l)->next; + free (*l); + *l = next; + } + *l = NULL; } -/* 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(); +static boolT inInt(PBB n, queue *q) +/* Returns whether the node n belongs to the queue list q. */ +{ + while (q) + if (q->node == n) + return (TRUE); + else + q = q->next; + return (FALSE); } +static void findEndlessFollow (PPROC pProc, nodeList *loopNodes, PBB head) /* 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) -{ - head->loopFollow = MAX; - for( int loop_node : loopNodes) - { - for (TYPEADR_TYPE &typeaddr: pProc->m_dfsLast[loop_node]->edges) - { - int succ = typeaddr.BBptr->dfsLastNum; - if ((! inList(loopNodes, succ)) && (succ < head->loopFollow)) - head->loopFollow = succ; - } - } +{ nodeList *p; + Int j, succ; + + head->loopFollow = MAX; + p = loopNodes; + while (p != NULL) + { + for (j = 0; j < pProc->dfsLast[p->nodeIdx]->numOutEdges; j++) + { + succ = pProc->dfsLast[p->nodeIdx]->edges[j].BBptr->dfsLastNum; + if ((! inList(loopNodes, succ)) && (succ < head->loopFollow)) + head->loopFollow = succ; + } + p = p->next; + } } -//static void findNodesInLoop(BB * latchNode,BB * head,PPROC pProc,queue *intNodes) -/* Flags nodes that belong to the loop determined by (latchNode, head) and +static void findNodesInLoop(PBB latchNode,PBB 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; +{ Int i, headDfsNum, intNodeType, j; + nodeList *loopNodes = NULL, p; + Int immedDom, /* dfsLast index to immediate dominator */ + thenDfs, elseDfs; /* dsfLast index for THEN and ELSE nodes */ + PBB pbb; /* Flag nodes in loop headed by head (except header node) */ headDfsNum = head->dfsLastNum; head->loopHead = headDfsNum; - insertList (loopNodes, headDfsNum); + insertList (&loopNodes, headDfsNum); for (i = headDfsNum + 1; i < latchNode->dfsLastNum; i++) { - if (pProc->m_dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */ - continue; + if (pProc->dfsLast[i]->flg & INVALID_BB) /* skip invalid BBs */ + continue; - immedDom = pProc->m_dfsLast[i]->immedDom; - if (inList (loopNodes, immedDom) && inInt(pProc->m_dfsLast[i], intNodes)) + immedDom = pProc->dfsLast[i]->immedDom; + if (inList (loopNodes, immedDom) && inInt(pProc->dfsLast[i], intNodes)) { - insertList (loopNodes, i); - if (pProc->m_dfsLast[i]->loopHead == NO_NODE)/*not in other loop*/ - pProc->m_dfsLast[i]->loopHead = headDfsNum; + 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); + 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; - latchNode->back().ll()->setFlags(JX_LOOP); - } + 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->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; - head->back().ll()->setFlags(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; + 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 = latchNode->edges[THEN].BBptr->dfsLastNum; - latchNode->back().ll()->setFlags(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; - } + 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->m_dfsLast[pbb->immedDom]; - } - if (pbb->dfsLastNum > head->dfsLastNum) - pProc->m_dfsLast[head->loopFollow]->loopHead = NO_NODE; /*****/ - head->back().ll()->setFlags(JX_LOOP); - } - else - { - head->loopType = ENDLESS_TYPE; - findEndlessFollow (pProc, loopNodes, head); - } + /* 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); + freeList(&loopNodes); } -//static void findNodesInInt (queue **intNodes, int level, interval *Ii) -/* Recursive procedure to find nodes that belong to the interval (ie. nodes + +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) -{ +{ queue *l; + if (level == 1) - { - for(BB *en : Ii->nodes) - { - appendQueue(intNodes,en); - } - } + for (l = Ii->nodes; l; l = l->next) + appendQueue (intNodes, l->node); else - { - for(BB *en : Ii->nodes) - { - findNodesInInt(intNodes,level-1,en->correspInt); - } - } + for (l = Ii->nodes; l; l= l->next) + findNodesInInt (intNodes, level - 1, l->node->correspInt); } +static void structLoops(PPROC pProc, derSeq *derivedG) /* Algorithm for structuring loops */ -void Function::structLoops(derSeq *derivedG) -{ - interval *Ii; - BB * intHead, /* interval header node */ - * pred, /* predecessor node */ - * latchNode;/* latching node (in case of loops) */ - size_t level = 0; /* derived sequence level */ - interval *initInt; /* initial interval */ - queue intNodes; /* list of interval nodes */ +{ interval *Ii; + PBB 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) + while (derivedG) /* for all derived sequences Gi */ { - level++; - Ii = iter->Ii; - while (Ii) /* for all intervals Ii of Gi */ - { - latchNode = NULL; - intNodes.clear(); + level++; + Ii = derivedG->Ii; + while (Ii) /* for all intervals Ii of Gi */ + { + latchNode = NULL; + intNodes = NULL; - /* Find interval head (original BB node in G1) and create + /* Find interval head (original BB node in G1) and create * list of nodes of interval Ii. */ - initInt = Ii; - for (size_t i = 1; i < level; i++) - initInt = (*initInt->nodes.begin())->correspInt; - intHead = *initInt->nodes.begin(); + initInt = Ii; + for (i = 1; i < level; i++) + initInt = initInt->nodes->node->correspInt; + intHead = initInt->nodes->node; - /* Find nodes that belong to the interval (nodes from G1) */ - findNodesInInt (intNodes, level, Ii); + /* Find nodes that belong to the interval (nodes from G1) */ + findNodesInInt (&intNodes, level, Ii); - /* Find greatest enclosing back edge (if any) */ - for (size_t 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 greatest enclosing back edge (if any) */ + for (i = 0; i < intHead->numInEdges; 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, this, intNodes); - latchNode->flg |= IS_LATCH_NODE; - } - } + /* 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 interval */ + Ii = Ii->next; + } - /* Next derived sequence */ + /* Next derived sequence */ + derivedG = derivedG->next; } } +static boolT successor (Int s, Int h, PPROC pProc) /* Returns whether the BB indexed by s is a successor of the BB indexed by * h. Note that h is a case node. */ -static bool successor (int s, int h, Function * pProc) -{ - BB * header; +{ Int i; + PBB header; - header = pProc->m_dfsLast[h]; - auto iter = std::find_if(header->edges.begin(), - header->edges.end(), - [s](const TYPEADR_TYPE &te)->bool{ return te.BBptr->dfsLastNum == s;}); - return iter!=header->edges.end(); + 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 (PBB 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 + * the list l, head and tail (dfsLast index to first and exit node of the * case). */ -static void tagNodesInCase (BB * pBB, nodeList &l, int head, int tail) -{ - int current, /* index to current node */ - i; +{ 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))) + if ((current != tail) && (pBB->nodeType != MULTI_BRANCH) && + (inList (*l, pBB->immedDom))) { - insertList (l, current); - pBB->caseHead = head; - for(TYPEADR_TYPE &edge : pBB->edges) - { - if (edge.BBptr->traversed != DFS_CASE) - tagNodesInCase (edge.BBptr, l, head, tail); - } + 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(PPROC pProc) /* Structures case statements. This procedure is invoked only when pProc * has a case node. */ -void Function::structCases() -{ - int i, j; - BB * caseHeader; /* case header node */ - int exitNode = NO_NODE; /* case exit node */ - nodeList caseNodes; /* temporary: list of nodes in case */ +{ Int i, j; + PBB caseHeader; /* case header node */ + Int exitNode = NO_NODE; /* case exit node */ + nodeList *caseNodes = NULL; /* temporary: list of nodes in case */ /* Linear scan of the nodes in reverse dfsLast order, searching for * case nodes */ - for (i = numBBs - 1; i >= 0; i--) - if (m_dfsLast[i]->nodeType == MULTI_BRANCH) - { - caseHeader = m_dfsLast[i]; + 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 < numBBs; j++) - { - if ((!successor(j, i, this)) && - (m_dfsLast[j]->immedDom == i)) - if (exitNode == NO_NODE) - exitNode = j; - else if (m_dfsLast[exitNode]->inEdges.size() < m_dfsLast[j]->inEdges.size()) - exitNode = j; - } - m_dfsLast[i]->caseTail = exitNode; - - /* Tag nodes that belong to the case by recording the - * header field with caseHeader. */ - insertList (caseNodes, i); - m_dfsLast[i]->caseHead = i; - for(TYPEADR_TYPE &pb : caseHeader->edges) - { - tagNodesInCase(pb.BBptr, caseNodes, i, exitNode); - } - //for (j = 0; j < caseHeader->edges[j]; j++) - // tagNodesInCase (caseHeader->edges[j].BBptr, caseNodes, i, exitNode); - if (exitNode != NO_NODE) - m_dfsLast[exitNode]->caseHead = 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; + } } +static void flagNodes (nodeList **l, Int f, PPROC pProc) /* 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; - for(int idx : l) +{ nodeList *p; + + p = *l; + while (p) { - pProc->m_dfsLast[idx]->ifFollow = f; + pProc->dfsLast[p->nodeIdx]->ifFollow = f; + p = p->next; + free (*l); + *l = p; } - l.clear(); + *l = NULL; } +static void structIfs (PPROC pProc) /* Structures if statements */ -void Function::structIfs () -{ - 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 */ - ; - BB * currNode, /* Pointer to current node */ - * pbb; +{ Int curr, /* Index for linear scan of nodes */ + desc, /* Index for descendant */ + followInEdges, /* Largest # in-edges so far */ + follow; /* Possible follow node */ + nodeList *domDesc = NULL, /* List of nodes dominated by curr */ + *unresolved = NULL, /* List of unresolved if nodes */ + *l; /* Temporary list */ + PBB currNode, /* Pointer to current node */ + pbb; - /* Linear scan of nodes in reverse dfsLast order */ - for (curr = numBBs - 1; curr >= 0; curr--) + /* Linear scan of nodes in reverse dfsLast order */ + for (curr = pProc->numBBs - 1; curr >= 0; curr--) { - currNode = m_dfsLast[curr]; - if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */ - continue; + currNode = pProc->dfsLast[curr]; + if (currNode->flg & INVALID_BB) /* Do not process invalid BBs */ + continue; - if ((currNode->nodeType == TWO_BRANCH) && (!currNode->back().ll()->testFlags(JX_LOOP))) - { - followInEdges = 0; - follow = 0; + 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 < numBBs; desc++) - { - if (m_dfsLast[desc]->immedDom == curr) - { - insertList (domDesc, desc); - pbb = m_dfsLast[desc]; - if ((pbb->inEdges.size() - pbb->numBackEdges) >= followInEdges) - { - follow = desc; - followInEdges = pbb->inEdges.size() - 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, this); - } - else - insertList (unresolved, curr); - } - freeList (domDesc); - } -} -bool Function::removeInEdge_Flag_and_ProcessLatch(BB *pbb,BB *a,BB *b) -{ - /* Remove in-edge e to t */ - auto iter = std::find(b->inEdges.begin(),b->inEdges.end(),a); - assert(iter!=b->inEdges.end()); - b->inEdges.erase(iter); /* looses 1 arc */ - a->flg |= INVALID_BB; - - if (pbb->flg & IS_LATCH_NODE) - this->m_dfsLast[a->dfsLastNum] = pbb; - else - return true; /* to repeat this analysis */ - return false; + /* 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) + flagNodes (&unresolved, follow, pProc); + } + else + insertList (&unresolved, curr); + } + freeList (&domDesc); + } } -void Function::replaceInEdge(BB* where, BB* which,BB* with) -{ - auto iter=std::find(where->inEdges.begin(),where->inEdges.end(),which); - assert(iter!=where->inEdges.end()); - *iter=with; -} -bool Function::Case_notX_or_Y(BB* pbb, BB* thenBB, BB* elseBB) -{ - HLTYPE &hl1(*pbb->back().hl()); - HLTYPE &hl2(*thenBB->back().hl()); - - BB* obb = elseBB->edges[THEN].BBptr; - - /* Construct compound DBL_OR expression */ - hl1.replaceExpr(hl1.expr()->inverse()); - hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_OR)); - - /* Replace in-edge to obb from e to pbb */ - replaceInEdge(obb,elseBB,pbb); - - /* New THEN and ELSE out-edges of pbb */ - pbb->edges[THEN].BBptr = obb; - pbb->edges[ELSE].BBptr = thenBB; - - /* Remove in-edge e to t */ - return removeInEdge_Flag_and_ProcessLatch(pbb,elseBB,thenBB); -} -bool Function::Case_X_and_Y(BB* pbb, BB* thenBB, BB* elseBB) -{ - HLTYPE &hl1(*pbb->back().hl()); - HLTYPE &hl2(*thenBB->back().hl()); - BB* obb = elseBB->edges[ELSE].BBptr; - - /* Construct compound DBL_AND expression */ - hl1.expr(COND_EXPR::boolOp (hl1.expr(),hl2.expr(), DBL_AND)); - - /* Replace in-edge to obb from e to pbb */ - replaceInEdge(obb,elseBB,pbb); - /* New ELSE out-edge of pbb */ - pbb->edges[ELSE].BBptr = obb; - - /* Remove in-edge e to t */ - return removeInEdge_Flag_and_ProcessLatch(pbb,elseBB,thenBB); -} - - -bool Function::Case_notX_and_Y(BB* pbb, BB* thenBB, BB* elseBB) -{ - HLTYPE &hl1(*pbb->back().hl()); - HLTYPE &hl2(*thenBB->back().hl()); - - BB* obb = thenBB->edges[ELSE].BBptr; - - /* Construct compound DBL_AND expression */ - - hl1.replaceExpr(hl1.expr()->inverse()); - hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_AND)); - - /* Replace in-edge to obb from t to pbb */ - replaceInEdge(obb,thenBB,pbb); - - /* New THEN and ELSE out-edges of pbb */ - pbb->edges[THEN].BBptr = elseBB; - pbb->edges[ELSE].BBptr = obb; - - /* Remove in-edge t to e */ - return removeInEdge_Flag_and_ProcessLatch(pbb,thenBB,elseBB); -} - -bool Function::Case_X_or_Y(BB* pbb, BB* thenBB, BB* elseBB) -{ - HLTYPE &hl1(*pbb->back().hl()); - HLTYPE &hl2(*thenBB->back().hl()); - - BB * obb = thenBB->edges[THEN].BBptr; - - /* Construct compound DBL_OR expression */ - hl1.expr(COND_EXPR::boolOp (hl1.expr(), hl2.expr(), DBL_OR)); - - /* Replace in-edge to obb from t to pbb */ - - auto iter=find(obb->inEdges.begin(),obb->inEdges.end(),thenBB); - if(iter!=obb->inEdges.end()) - *iter = pbb; - - /* New THEN out-edge of pbb */ - pbb->edges[THEN].BBptr = obb; - - /* Remove in-edge t to e */ - return removeInEdge_Flag_and_ProcessLatch(pbb,thenBB,elseBB); -} -/** \brief Checks for compound conditions of basic blocks that have only 1 high +void compoundCond (PPROC pproc) +/* 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() -{ - BB * pbb, * thenBB, * elseBB; - bool change = true; - while (change) - { - change = false; +{ Int i, j, k, numOutEdges; + PBB pbb, t, e, obb, pred; + PICODE picode, ticode; + COND_EXPR *exp; + TYPEADR_TYPE *edges; + boolT change; - /* Traverse nodes in postorder, this way, the header node of a - * compound condition is analysed first */ - for (int i = 0; i < this->numBBs; i++) - { - pbb = this->m_dfsLast[i]; - if (pbb->flg & INVALID_BB) - continue; + change = TRUE; + while (change) + { + change = FALSE; - if (pbb->nodeType != TWO_BRANCH) - continue; + /* Traverse nodes in postorder, this way, the header node of a + * compound condition is analysed first */ + for (i = 0; i < pproc->numBBs; i++) + { + pbb = pproc->dfsLast[i]; + if (pbb->flg & INVALID_BB) + continue; - thenBB = pbb->edges[THEN].BBptr; - elseBB = pbb->edges[ELSE].BBptr; + if (pbb->nodeType == TWO_BRANCH) + { + t = pbb->edges[THEN].BBptr; + e = pbb->edges[ELSE].BBptr; - change = true; //assume change + /* 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; - /* Check (X || Y) case */ - if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) && - (thenBB->inEdges.size() == 1) && (thenBB->edges[ELSE].BBptr == elseBB)) - { - if(Case_X_or_Y(pbb, thenBB, elseBB)) - --i; - } + /* Construct compound DBL_OR expression */ + picode = pproc->Icode.GetIcode(pbb->start + pbb->length -1); + ticode = pproc->Icode.GetIcode(t->start + t->length -1); + exp = boolCondExp (picode->ic.hl.oper.exp, + ticode->ic.hl.oper.exp, DBL_OR); + picode->ic.hl.oper.exp = exp; - /* Check (!X && Y) case */ - else if ((thenBB->nodeType == TWO_BRANCH) && (thenBB->numHlIcodes == 1) && - (thenBB->inEdges.size() == 1) && (thenBB->edges[THEN].BBptr == elseBB)) - { - if(Case_notX_and_Y(pbb, thenBB, elseBB)) - --i; - } + /* 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; + } - /* Check (X && Y) case */ - else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) && - (elseBB->inEdges.size()==1) && (elseBB->edges[THEN].BBptr == thenBB)) - { - if(Case_X_and_Y(pbb, thenBB, elseBB )) - --i; - } + /* New THEN out-edge of pbb */ + pbb->edges[THEN].BBptr = obb; - /* Check (!X || Y) case */ - else if ((elseBB->nodeType == TWO_BRANCH) && (elseBB->numHlIcodes == 1) && - (elseBB->inEdges.size() == 1) && (elseBB->edges[ELSE].BBptr == thenBB)) - { - if(Case_notX_or_Y(pbb, thenBB, elseBB )) - --i; - } - else - change = false; // otherwise we changed nothing - } - } + /* Remove in-edge t to e */ + for (j = 0; j < (e->numInEdges-1); j++) + if (e->inEdges[j] == t) + { + memmove (&e->inEdges[j], &e->inEdges[j+1], + (size_t)((e->numInEdges - j - 1) * sizeof(PBB))); + break; + } + e->numInEdges--; /* looses 1 arc */ + t->flg |= INVALID_BB; + + if (pbb->flg & IS_LATCH_NODE) + pproc->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 = pproc->Icode.GetIcode(pbb->start + pbb->length -1); + ticode = pproc->Icode.GetIcode(t->start + t->length -1); + inverseCondOp (&picode->ic.hl.oper.exp); + exp = boolCondExp (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 */ + for (j = 0; j < obb->numInEdges; j++) + if (obb->inEdges[j] == t) + { + obb->inEdges[j] = pbb; + break; + } + + /* New THEN and ELSE out-edges of pbb */ + pbb->edges[THEN].BBptr = e; + pbb->edges[ELSE].BBptr = obb; + + /* Remove in-edge t to e */ + for (j = 0; j < (e->numInEdges-1); j++) + if (e->inEdges[j] == t) + { + memmove (&e->inEdges[j], &e->inEdges[j+1], + (size_t)((e->numInEdges - j - 1) * sizeof(PBB))); + break; + } + e->numInEdges--; /* looses 1 arc */ + t->flg |= INVALID_BB; + + if (pbb->flg & IS_LATCH_NODE) + pproc->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 = pproc->Icode.GetIcode(pbb->start + pbb->length -1); + ticode = pproc->Icode.GetIcode(t->start + t->length -1); + exp = boolCondExp (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 */ + for (j = 0; j < obb->numInEdges; j++) + if (obb->inEdges[j] == e) + { + obb->inEdges[j] = pbb; + break; + } + + /* New ELSE out-edge of pbb */ + pbb->edges[ELSE].BBptr = obb; + + /* Remove in-edge e to t */ + for (j = 0; j < (t->numInEdges-1); j++) + if (t->inEdges[j] == e) + { + memmove (&t->inEdges[j], &t->inEdges[j+1], + (size_t)((t->numInEdges - j - 1) * sizeof(PBB))); + break; + } + t->numInEdges--; /* looses 1 arc */ + e->flg |= INVALID_BB; + + if (pbb->flg & IS_LATCH_NODE) + pproc->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 = pproc->Icode.GetIcode(pbb->start + pbb->length -1); + ticode = pproc->Icode.GetIcode(t->start + t->length -1); + inverseCondOp (&picode->ic.hl.oper.exp); + exp = boolCondExp (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 */ + for (j = 0; j < obb->numInEdges; j++) + if (obb->inEdges[j] == e) + { + obb->inEdges[j] = pbb; + break; + } + + /* New THEN and ELSE out-edges of pbb */ + pbb->edges[THEN].BBptr = obb; + pbb->edges[ELSE].BBptr = t; + + /* Remove in-edge e to t */ + for (j = 0; j < (t->numInEdges-1); j++) + if (t->inEdges[j] == e) + { + memmove (&t->inEdges[j], &t->inEdges[j+1], + (size_t)((t->numInEdges - j - 1) * sizeof(PBB))); + break; + } + t->numInEdges--; /* looses 1 arc */ + e->flg |= INVALID_BB; + + if (pbb->flg & IS_LATCH_NODE) + pproc->dfsLast[e->dfsLastNum] = pbb; + else + i--; /* to repeat this analysis */ + + change = TRUE; + } + } + } + } } +void structure(PPROC pProc, derSeq *derivedG) /* Structuring algorithm to find the structures of the graph pProc->cfg */ -void Function::structure(derSeq *derivedG) { /* Find immediate dominators of the graph */ - findImmedDom(); - if (hasCase) - structCases(); - structLoops(derivedG); - structIfs(); + findImmedDom(pProc); + if (pProc->hasCase) + structCases(pProc); + structLoops(pProc, derivedG); + structIfs(pProc); } diff --git a/src/dataflow.cpp b/src/dataflow.cpp index 1acfc8c..3fe9ae9 100644 --- a/src/dataflow.cpp +++ b/src/dataflow.cpp @@ -6,262 +6,203 @@ ****************************************************************************/ #include "dcc.h" -#include -#include -#include -#include #include -#include -#include #include -using namespace boost; -using namespace boost::adaptors; -struct ExpStack -{ - typedef std::list EXP_STK; - EXP_STK expStk; /* local expression stack */ - - void init(); - void push(COND_EXPR *); - COND_EXPR * pop(); - int numElem(); - boolT empty(); - void processExpPush(int &numHlIcodes, iICODE picode) - { - push(picode->hl()->expr()); - picode->invalidate(); - numHlIcodes--; - } - -}; -/*************************************************************************** - * Expression stack functions - **************************************************************************/ - -/* Reinitalizes the expression stack (expStk) to NULL, by freeing all the - * space allocated (if any). */ -void ExpStack::init() -{ - expStk.clear(); -} -/* Pushes the given expression onto the local stack (expStk). */ -void ExpStack::push(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 *ExpStack::pop() -{ - 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 ExpStack::numElem() -{ - return expStk.size(); -} - -/* Returns whether the expression stack is empty or not */ -boolT ExpStack::empty() -{ - return expStk.empty(); -} - -using namespace std; -ExpStack g_exp_stk; - -/* Returns the index of the local variable or parameter at offset off, if it +static Int getLocVar (PSTKFRAME pStkFrame, Int off) +/* Returns the index of the local variable or parameter at offset off, if it * is in the stack frame provided. */ -size_t STKFRAME::getLocVar(int off) -{ - auto iter=findByLabel(off); - return distance(begin(),iter); +{ Int i; + + for (i = 0; i < pStkFrame->csym; i++) + if (pStkFrame->sym[i].off == off) + break; + return (i); } +static COND_EXPR *srcIdent (PICODE Icode, PPROC pProc, Int i, PICODE duIcode, + operDu du) /* Returns a string with the source operand of Icode */ -static COND_EXPR *srcIdent (const LLInst &ll_insn, Function * pProc, iICODE i, ICODE & duIcode, operDu du) -{ - if (ll_insn.testFlags(I)) /* immediate operand */ - { - if (ll_insn.testFlags(B)) - return COND_EXPR::idKte (ll_insn.src().getImm2(), 1); - return COND_EXPR::idKte (ll_insn.src().getImm2(), 2); - } - // otherwise - return COND_EXPR::id (ll_insn, SRC, pProc, i, duIcode, du); -} +{ COND_EXPR *n; - -/* Returns the destination operand */ -static COND_EXPR *dstIdent (const LLInst & ll_insn, Function * pProc, iICODE i, ICODE & duIcode, operDu du) -{ - COND_EXPR *n; - n = COND_EXPR::id (ll_insn, DST, pProc, i, duIcode, du); - /** Is it needed? (pIcode->ll()->flg) & NO_SRC_B **/ + if (Icode->ic.ll.flg & I) /* immediate operand */ + { + if (Icode->ic.ll.flg & B) + n = idCondExpKte (Icode->ic.ll.immed.op, 1); + else + n = idCondExpKte (Icode->ic.ll.immed.op, 2); + } + else + n = idCondExp (Icode, SRC, pProc, i, duIcode, du); return (n); } + + +static COND_EXPR *dstIdent (PICODE pIcode, PPROC pProc, Int i, PICODE duIcode, + operDu du) +/* Returns the destination operand */ +{ COND_EXPR *n; + + n = idCondExp (pIcode, DST, pProc, i, duIcode, du); + /** Is it needed? (pIcode->ic.ll.flg) & NO_SRC_B **/ + return (n); +} + + + +static void elimCondCodes (PPROC pProc) /* Eliminates all condition codes and generates new hlIcode instructions */ -void Function::elimCondCodes () -{ - int i; +{ Int i, + useAt, /* Index to instruction that used flag */ + defAt; /* Index to instruction that defined flag */ + byte use; /* Used flags bit vector */ + byte def; /* Defined flags bit vector */ + boolT notSup; /* Use/def combination not supported */ + COND_EXPR *rhs; /* Source operand */ + COND_EXPR *lhs; /* Destination operand */ + COND_EXPR *exp; /* Boolean expression */ + PBB pBB; /* Pointer to BBs in dfs last ordering */ + ICODE *prev; /* For extended basic blocks - previous icode inst */ - uint8_t use; /* Used flags bit vector */ - uint8_t def; /* Defined flags bit vector */ - boolT notSup; /* Use/def combination not supported */ - COND_EXPR *rhs; /* Source operand */ - COND_EXPR *lhs; /* Destination operand */ - COND_EXPR *_expr; /* Boolean expression */ - BB * pBB; /* Pointer to BBs in dfs last ordering */ - riICODE useAt; /* Instruction that used flag */ - riICODE defAt; /* Instruction that defined flag */ - //lhs=rhs=_expr=0; - for (i = 0; i < numBBs; i++) - { - pBB = m_dfsLast[i]; - if (pBB->flg & INVALID_BB) - continue; /* Do not process invalid BBs */ - // auto v(pBB | boost::adaptors::reversed); - // for (const ICODE &useAt : v) - // {} - for (useAt = pBB->rbegin(); useAt != pBB->rend(); useAt++) + for (i = 0; i < pProc->numBBs; i++) + { + pBB = pProc->dfsLast[i]; + if (pBB->flg & INVALID_BB) continue; /* Do not process invalid BBs */ + + for (useAt = pBB->start + pBB->length; useAt != pBB->start; useAt--) + if ((pProc->Icode.GetIcode(useAt-1)->type == LOW_LEVEL) && + (pProc->Icode.GetIcode(useAt-1)->invalid == FALSE) && + (use = pProc->Icode.GetIcode(useAt-1)->ic.ll.flagDU.u)) { - llIcode useAtOp = llIcode(useAt->ll()->getOpcode()); - use = useAt->ll()->flagDU.u; - if ((useAt->type != LOW_LEVEL) || ( ! useAt->valid() ) || ( 0 == use )) - continue; /* Find definition within the same basic block */ - defAt=useAt; - ++defAt; - for (; defAt != pBB->rend(); defAt++) + for (defAt = useAt-1; defAt != pBB->start; defAt--) { - def = defAt->ll()->flagDU.d; - if ((use & def) != use) - continue; - notSup = false; - if ((useAtOp >= iJB) && (useAtOp <= iJNS)) + def = pProc->Icode.GetIcode(defAt-1)->ic.ll.flagDU.d; + if ((use & def) == use) { - iICODE befDefAt = (++riICODE(defAt)).base(); - switch (defAt->ll()->getOpcode()) + notSup = FALSE; + if ((pProc->Icode.GetLlOpcode(useAt-1) >= iJB) && + (pProc->Icode.GetLlOpcode(useAt-1) <= iJNS)) { - case iCMP: - rhs = srcIdent (*defAt->ll(), this, befDefAt,*useAt, eUSE); - lhs = dstIdent (*defAt->ll(), this, befDefAt,*useAt, eUSE); + switch (pProc->Icode.GetLlOpcode(defAt-1)) + { + case iCMP: + rhs = srcIdent (pProc->Icode.GetIcode(defAt-1), + pProc, defAt-1, + pProc->Icode.GetIcode(useAt-1), E_USE); + lhs = dstIdent (pProc->Icode.GetIcode(defAt-1), + pProc, defAt-1, + pProc->Icode.GetIcode(useAt-1), E_USE); break; - case iOR: - lhs = defAt->hl()->asgn.lhs->clone(); - useAt->copyDU(*defAt, eUSE, eDEF); - if (defAt->ll()->testFlags(B)) - rhs = COND_EXPR::idKte (0, 1); - else - rhs = COND_EXPR::idKte (0, 2); + case iOR: + lhs = copyCondExp (pProc->Icode.GetIcode(defAt-1)->ic.hl.oper.asgn.lhs); + copyDU (pProc->Icode.GetIcode(useAt-1), + pProc->Icode.GetIcode(defAt-1), E_USE, E_DEF); + if (pProc->Icode.GetLlFlag(defAt-1) & B) + rhs = idCondExpKte (0, 1); + else + rhs = idCondExpKte (0, 2); break; - case iTEST: - rhs = srcIdent (*defAt->ll(),this, befDefAt,*useAt, eUSE); - lhs = dstIdent (*defAt->ll(),this, befDefAt,*useAt, eUSE); - lhs = COND_EXPR::boolOp (lhs, rhs, AND); - if (defAt->ll()->testFlags(B)) - rhs = COND_EXPR::idKte (0, 1); - else - rhs = COND_EXPR::idKte (0, 2); + case iTEST: + rhs = srcIdent (pProc->Icode.GetIcode(defAt-1), + pProc, defAt-1, + pProc->Icode.GetIcode(useAt-1), E_USE); + lhs = dstIdent (pProc->Icode.GetIcode(defAt-1), + pProc, defAt-1, + pProc->Icode.GetIcode(useAt-1), E_USE); + lhs = boolCondExp (lhs, rhs, AND); + if (pProc->Icode.GetLlFlag(defAt-1) & B) + rhs = idCondExpKte (0, 1); + else + rhs = idCondExpKte (0, 2); break; - default: - notSup = true; - std::cout << hex<loc_ip; - reportError (JX_NOT_DEF, defAt->ll()->getOpcode()); - flg |= PROC_ASM; /* generate asm */ + default: + notSup = TRUE; + reportError (JX_NOT_DEF, pProc->Icode.GetLlOpcode(defAt-1)); + pProc->flg |= PROC_ASM; /* generate asm */ + } + if (! notSup) + { + exp = boolCondExp (lhs, rhs, + condOpJCond[pProc->Icode.GetLlOpcode(useAt-1)-iJB]); + newJCondHlIcode (pProc->Icode.GetIcode(useAt-1), exp); + } } - if (! notSup) + + else if (pProc->Icode.GetLlOpcode(useAt-1) == iJCXZ) { - assert(lhs); - assert(rhs); - _expr = COND_EXPR::boolOp (lhs, rhs,condOpJCond[useAtOp-iJB]); - useAt->setJCond(_expr); + lhs = idCondExpReg (rCX, 0, &pProc->localId); + setRegDU (pProc->Icode.GetIcode(useAt-1), rCX, E_USE); + rhs = idCondExpKte (0, 2); + exp = boolCondExp (lhs, rhs, EQUAL); + newJCondHlIcode (pProc->Icode.GetIcode(useAt-1), exp); } - } - else if (useAtOp == iJCXZ) - { - lhs = COND_EXPR::idReg (rCX, 0, &localId); - useAt->setRegDU (rCX, eUSE); - rhs = COND_EXPR::idKte (0, 2); - _expr = COND_EXPR::boolOp (lhs, rhs, EQUAL); - useAt->setJCond(_expr); + else + { + reportError (NOT_DEF_USE, + pProc->Icode.GetLlOpcode(defAt-1), + pProc->Icode.GetLlOpcode(useAt-1)); + pProc->flg |= PROC_ASM; /* generate asm */ + } + break; } - // else if (useAt->getOpcode() == iRCL) - // { - // } - else - { - ICODE &a(*defAt); - ICODE &b(*useAt); - reportError (NOT_DEF_USE,a.ll()->getOpcode(),b.ll()->getOpcode()); - flg |= PROC_ASM; /* generate asm */ - } - break; } /* Check for extended basic block */ - if ((pBB->size() == 1) &&(useAtOp >= iJB) && (useAtOp <= iJNS)) + if ((pBB->length == 1) && + (pProc->Icode.GetLlOpcode(useAt-1) >= iJB) && + (pProc->Icode.GetLlOpcode(useAt-1) <= iJNS)) { - ICODE & _prev(pBB->back()); /* For extended basic blocks - previous icode inst */ - if (_prev.hl()->opcode == HLI_JCOND) + prev = pProc->Icode.GetIcode(pBB->inEdges[0]->start + + pBB->inEdges[0]->length - 1); + if (prev->ic.hl.opcode == HLI_JCOND) { - _expr = _prev.hl()->expr()->clone(); - _expr->changeBoolOp (condOpJCond[useAtOp-iJB]); - useAt->copyDU(_prev, eUSE, eUSE); - useAt->setJCond(_expr); + exp = copyCondExp (prev->ic.hl.oper.exp); + changeBoolCondExpOp (exp, + condOpJCond[pProc->Icode.GetLlOpcode(useAt-1)-iJB]); + copyDU (pProc->Icode.GetIcode(useAt-1), prev, E_USE, E_USE); + newJCondHlIcode (pProc->Icode.GetIcode(useAt-1), exp); } } /* Error - definition not found for use of a cond code */ - else if (defAt == pBB->rend()) - { - reportError(DEF_NOT_FOUND,useAtOp); - //fatalError (DEF_NOT_FOUND, Icode.getOpcode(useAt-1)); - } + else if (defAt == pBB->start) + fatalError (DEF_NOT_FOUND, + pProc->Icode.GetLlOpcode(useAt-1)); } - } + } } -/** Generates the LiveUse() and Def() sets for each basic block in the graph. +static void genLiveKtes (PPROC pproc) +/* Generates the LiveUse() and Def() sets for each basic block in the graph. * Note: these sets are constant and could have been constructed during - * the construction of the graph, but since the code hasn't been + * the construction of the graph, but since the code hasn't been * analyzed yet for idioms, the procedure preamble misleads the * analysis (eg: push si, would include si in LiveUse; although it * is not really meant to be a register that is used before defined). */ -void Function::genLiveKtes () -{ - int i; - BB * pbb; - bitset<32> liveUse, def; +{ Int i, j; + PBB pbb; + PICODE picode; + dword liveUse, def; - for (i = 0; i < numBBs; i++) + for (i = 0; i < pproc->numBBs; i++) { - liveUse.reset(); - def.reset(); - pbb = m_dfsLast[i]; - if (pbb->flg & INVALID_BB) - continue; // skip invalid BBs - for(ICODE &insn : *pbb) + liveUse = def = 0; + pbb = pproc->dfsLast[i]; + if (pbb->flg & INVALID_BB) continue; /* skip invalid BBs */ + for (j = pbb->start; j < (pbb->start + pbb->length); j++) { - if ((insn.type == HIGH_LEVEL) && ( insn.valid() )) + picode = pproc->Icode.GetIcode(j); + if ((picode->type == HIGH_LEVEL) && (picode->invalid == FALSE)) { - liveUse |= (insn.du.use & ~def); - def |= insn.du.def; + liveUse |= (picode->du.use & ~def); + def |= picode->du.def; } } pbb->liveUse = liveUse; @@ -270,951 +211,888 @@ void Function::genLiveKtes () } +static void liveRegAnalysis (PPROC pproc, dword liveOut) /* Generates the liveIn() and liveOut() sets for each basic block via an - * iterative approach. + * iterative approach. * Propagates register usage information to the procedure call. */ -void Function::liveRegAnalysis (std::bitset<32> &in_liveOut) -{ - using namespace boost::adaptors; - using namespace boost::assign; - BB * pbb=0; /* pointer to current basic block */ - Function * pcallee; /* invoked subroutine */ - //ICODE *ticode /* icode that invokes a subroutine */ - ; - std::bitset<32> prevLiveOut, /* previous live out */ - prevLiveIn; /* previous live in */ - boolT change; /* is there change in the live sets?*/ +{ Int i, j; + PBB pbb; /* pointer to current basic block */ + PPROC pcallee; /* invoked subroutine */ + PICODE ticode, /* icode that invokes a subroutine */ + picode; /* icode of function return */ + dword prevLiveOut, /* previous live out */ + prevLiveIn; /* previous live in */ + boolT change; /* is there change in the live sets?*/ /* liveOut for this procedure */ - liveOut = in_liveOut; + pproc->liveOut = liveOut; - change = true; - while (change) + change = TRUE; + while (change) + { + /* Process nodes in reverse postorder order */ + change = FALSE; + for (i = pproc->numBBs; i > 0; i--) { - /* Process nodes in reverse postorder order */ - change = false; - auto valid_reversed_bbs = (m_dfsLast | reversed | filtered(BB::ValidFunctor()) ); - for( BB * _pbb : valid_reversed_bbs) + pbb = pproc->dfsLast[i-1]; + if (pbb->flg & INVALID_BB) /* Do not process invalid BBs */ + continue; + + /* Get current liveIn() and liveOut() sets */ + prevLiveIn = pbb->liveIn; + prevLiveOut = pbb->liveOut; + + /* liveOut(b) = U LiveIn(s); where s is successor(b) + * liveOut(b) = {liveOut}; when b is a HLI_RET node */ + if (pbb->numOutEdges == 0) /* HLI_RET node */ + { + pbb->liveOut = liveOut; + + /* Get return expression of function */ + if (pproc->flg & PROC_IS_FUNC) + { + picode = pproc->Icode.GetIcode(pbb->start + pbb->length - 1); + if (picode->ic.hl.opcode == HLI_RET) + { + picode->ic.hl.oper.exp = idCondExpID (&pproc->retVal, + &pproc->localId, pbb->start + pbb->length - 1); + picode->du.use = liveOut; + } + } + } + else /* Check successors */ { - pbb = _pbb;//*iBB;//m_dfsLast[i-1]; + for (j = 0; j < pbb->numOutEdges; j++) + pbb->liveOut |= pbb->edges[j].BBptr->liveIn; - /* Get current liveIn() and liveOut() sets */ - prevLiveIn = pbb->liveIn; - prevLiveOut = pbb->liveOut; - - /* liveOut(b) = U LiveIn(s); where s is successor(b) - * liveOut(b) = {liveOut}; when b is a HLI_RET node */ - if (pbb->edges.empty()) /* HLI_RET node */ + /* propagate to invoked procedure */ + if (pbb->nodeType == CALL_NODE) { - pbb->liveOut = in_liveOut; + ticode = pproc->Icode.GetIcode(pbb->start + pbb->length - 1); + pcallee = ticode->ic.hl.oper.call.proc; - /* Get return expression of function */ - if (flg & PROC_IS_FUNC) + /* user/runtime routine */ + if (! (pcallee->flg & PROC_ISLIB)) { - auto picode = pbb->rbegin(); /* icode of function return */ - if (picode->hl()->opcode == HLI_RET) - { - picode->hl()->expr(COND_EXPR::idID (&retVal, &localId, (++pbb->rbegin()).base())); - picode->du.use = in_liveOut; - } + if (pcallee->liveAnal == FALSE) /* hasn't been processed */ + dataFlow (pcallee, pbb->liveOut); + pbb->liveOut = pcallee->liveIn; } + else /* library routine */ + { + if ((pcallee->flg & PROC_IS_FUNC) && /* returns a value */ + (pcallee->liveOut & pbb->edges[0].BBptr->liveIn)) + pbb->liveOut = pcallee->liveOut; + else + pbb->liveOut = 0; + } + + if ((! (pcallee->flg & PROC_ISLIB)) || (pbb->liveOut != 0)) + { + switch (pcallee->retVal.type) { + case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: + ticode->du1.numRegsDef = 2; + break; + case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: + case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: + ticode->du1.numRegsDef = 1; + break; + } /*eos*/ + + /* Propagate def/use results to calling icode */ + ticode->du.use = pcallee->liveIn; + ticode->du.def = pcallee->liveOut; + } } - else /* Check successors */ - { - for(TYPEADR_TYPE &e : pbb->edges) - { - pbb->liveOut |= e.BBptr->liveIn; - } - - /* propagate to invoked procedure */ - if (pbb->nodeType == CALL_NODE) - { - ICODE &ticode(pbb->back()); - pcallee = ticode.hl()->call.proc; - - /* user/runtime routine */ - if (! (pcallee->flg & PROC_ISLIB)) - { - if (pcallee->liveAnal == false) /* hasn't been processed */ - pcallee->dataFlow (pbb->liveOut); - pbb->liveOut = pcallee->liveIn; - } - else /* library routine */ - { - if ( (pcallee->flg & PROC_IS_FUNC) && /* returns a value */ - (pcallee->liveOut & pbb->edges[0].BBptr->liveIn).any() - ) - pbb->liveOut = pcallee->liveOut; - else - pbb->liveOut = 0; - } - - if ((! (pcallee->flg & PROC_ISLIB)) || (pbb->liveOut != 0)) - { - switch (pcallee->retVal.type) { - case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: - ticode.du1.numRegsDef = 2; - break; - case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: - case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: - ticode.du1.numRegsDef = 1; - break; - default: - ticode.du1.numRegsDef = 0; - //fprintf(stderr,"Function::liveRegAnalysis : Unknown return type %d, assume 0\n",pcallee->retVal.type); - } /*eos*/ - - /* Propagate def/use results to calling icode */ - ticode.du.use = pcallee->liveIn; - ticode.du.def = pcallee->liveOut; - } - } - } - - /* liveIn(b) = liveUse(b) U (liveOut(b) - def(b) */ - pbb->liveIn = pbb->liveUse | (pbb->liveOut & ~pbb->def); - - /* Check if live sets have been modified */ - if ((prevLiveIn != pbb->liveIn) || (prevLiveOut != pbb->liveOut)) - change = true; } + + /* liveIn(b) = liveUse(b) U (liveOut(b) - def(b) */ + pbb->liveIn = pbb->liveUse | (pbb->liveOut & ~pbb->def); + + /* Check if live sets have been modified */ + if ((prevLiveIn != pbb->liveIn) || (prevLiveOut != pbb->liveOut)) + change = TRUE; } + } /* Propagate liveIn(b) to procedure header */ if (pbb->liveIn != 0) /* uses registers */ - liveIn = pbb->liveIn; + pproc->liveIn = pbb->liveIn; - /* Remove any references to register variables */ - if (flg & SI_REGVAR) - { - liveIn &= maskDuReg[rSI]; - pbb->liveIn &= maskDuReg[rSI]; - } - if (flg & DI_REGVAR) - { - liveIn &= maskDuReg[rDI]; - pbb->liveIn &= maskDuReg[rDI]; - } + /* Remove any references to register variables */ + if (pproc->flg & SI_REGVAR) + { + pproc->liveIn &= maskDuReg[rSI]; + pbb->liveIn &= maskDuReg[rSI]; + } + if (pproc->flg & DI_REGVAR) + { + pproc->liveIn &= maskDuReg[rDI]; + pbb->liveIn &= maskDuReg[rDI]; + } } -/* Check remaining instructions of the BB for all uses - * of register regi, before any definitions of the - * register */ -bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at) -{ - if ((regi == rDI) && (flg & DI_REGVAR)) - return true; - if ((regi == rSI) && (flg & SI_REGVAR)) - return true; - if (distance(start_at,end())>1) /* several instructions */ - { - iICODE ticode=end(); - auto hl_range=make_iterator_range(start_at,end()) | filtered(ICODE::select_high_level); - auto checked_icode=hl_range.begin(); - ++checked_icode; - for (; checked_icode != hl_range.end(); checked_icode++) - { - if (checked_icode->type != HIGH_LEVEL) // Only check uses of HIGH_LEVEL icodes - continue; - /* if used, get icode index */ - if ((checked_icode->du.use & duReg[regi]).any()) - start_at->du1.recordUse(defRegIdx,checked_icode.base()); - /* if defined, stop finding uses for this reg */ - if ((checked_icode->du.def & duReg[regi]).any()) - { - ticode=checked_icode.base(); - break; - } - } - if(ticode==end()) - ticode=(++riICODE(rbegin())).base(); - /* Check if last definition of this register */ - if ((not (ticode->du.def & duReg[regi]).any()) and (liveOut & duReg[regi]).any()) - start_at->du.lastDefRegi |= duReg[regi]; - } - else /* only 1 instruction in this basic block */ - { - /* Check if last definition of this register */ - if ((liveOut & duReg[regi]).any()) - start_at->du.lastDefRegi |= duReg[regi]; - } - return false; -} -/* Find target icode for HLI_CALL icodes to procedures - * that are functions. The target icode is in the - * next basic block (unoptimized code) or somewhere else - * on optimized code. */ -void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode) -{ - if ((picode->hl()->opcode == HLI_CALL) && - (picode->hl()->call.proc->flg & PROC_IS_FUNC)) - { - BB *tbb = this->edges[0].BBptr; - auto target_instructions = tbb->instructions | filtered(ICODE::select_high_level); - for (auto iter=target_instructions.begin(); iter!=target_instructions.end(); ++iter) - { - /* if used, get icode index */ - if ((iter->du.use & duReg[regi]).any()) - picode->du1.recordUse(defRegIdx,iter.base()); - /* if defined, stop finding uses for this reg */ - if ((iter->du.def & duReg[regi]).any()) - break; - } - - /* if not used in this basic block, check if the - * register is live out, if so, make it the last - * definition of this register */ - if ( picode->du1.used(defRegIdx) && (tbb->liveOut & duReg[regi]).any()) - picode->du.lastDefRegi |= duReg[regi]; - } -} - -/* If not used within this bb or in successors of this - * bb (ie. not in liveOut), then register is useless, - * thus remove it. Also check that this is not a return - * from a library function (routines such as printf - * return an integer, which is normally not taken into - * account by the programmer). */ -void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode) -{ - if (picode->valid() and not picode->du1.used(defRegIdx) and - (not (picode->du.lastDefRegi & duReg[regi]).any()) && - (not ((picode->hl()->opcode == HLI_CALL) && - (picode->hl()->call.proc->flg & PROC_ISLIB)))) - { - if (! (this->liveOut & duReg[regi]).any()) /* not liveOut */ - { - bool res = picode->removeDefRegi (regi, defRegIdx+1,&Parent->localId); - if (res == true) - { - - /* Backpatch any uses of this instruction, within - * the same BB, if the instruction was invalidated */ - rICODE the_rest(begin(),picode); - for ( ICODE &back_patch_at : the_rest|reversed) - { - back_patch_at.du1.remove(0,picode); - } - } - } - else /* liveOut */ - picode->du.lastDefRegi |= duReg[regi]; - } -} - -void BB::genDU1() -{ - /* Process each register definition of a HIGH_LEVEL icode instruction. - * Note that register variables should not be considered registers. - */ - assert(0!=Parent); - ICODE::TypeFilter select_high_level; - auto all_high_levels = instructions | filtered(select_high_level); - printf("\n"); - for (auto picode=all_high_levels.begin(); picode!=all_high_levels.end(); ++picode) - { - int defRegIdx = 0; - // foreach defined register - for (int k = 0; k < INDEX_BX_SI; k++) - { - if (not picode->du.def.test(k)) - continue; - eReg regi = (eReg)(k + 1); /* Register that was defined */ - picode->du1.regi[defRegIdx] = regi; - - if(FindUseBeforeDef(regi,defRegIdx, picode.base())) - continue; - - ProcessUseDefForFunc(regi, defRegIdx,picode.base()); - RemoveUnusedDefs(regi, defRegIdx, picode.base()); - - defRegIdx++; - - /* Check if all defined registers have been processed */ - if ((defRegIdx >= picode->du1.numRegsDef) || (defRegIdx == MAX_REGS_DEF)) - break; - } - } -} +static void genDU1 (PPROC pProc) /* Generates the du chain of each instruction in a basic block */ -void Function::genDU1 () -{ +{ byte regi; /* Register that was defined */ + Int i, j, k, p, n, lastInst, defRegIdx, useIdx; + PICODE picode, ticode;/* Current and target bb */ + PBB pbb, tbb; /* Current and target basic block */ + boolT res; + COND_EXPR *exp, *lhs; + /* Traverse tree in dfsLast order */ - assert(m_dfsLast.size()==numBBs); - for(BB *pbb : m_dfsLast | filtered(BB::ValidFunctor())) + for (i = 0; i < pProc->numBBs; i++) { - pbb->genDU1(); + pbb = pProc->dfsLast[i]; + if (pbb->flg & INVALID_BB) continue; + + /* Process each register definition of a HIGH_LEVEL icode instruction. + * Note that register variables should not be considered registers. + */ + lastInst = pbb->start + pbb->length; + for (j = pbb->start; j < lastInst; j++) + { + picode = pProc->Icode.GetIcode(j); + if (picode->type == HIGH_LEVEL) + { + regi = 0; + defRegIdx = 0; + for (k = 0; k < INDEXBASE; k++) + { + if ((picode->du.def & power2(k)) != 0) + { + regi = (byte)(k + 1); /* defined register */ + picode->du1.regi[defRegIdx] = regi; + + /* Check remaining instructions of the BB for all uses + * of register regi, before any definitions of the + * register */ + if ((regi == rDI) && (pProc->flg & DI_REGVAR)) + continue; + if ((regi == rSI) && (pProc->flg & SI_REGVAR)) + continue; + if ((j + 1) < lastInst) /* several instructions */ + { + useIdx = 0; + for (n = j+1; n < lastInst; n++) + { + /* Only check uses of HIGH_LEVEL icodes */ + ticode = pProc->Icode.GetIcode(n); + if (ticode->type == HIGH_LEVEL) + { + /* if used, get icode index */ + if (ticode->du.use & duReg[regi]) + picode->du1.idx[defRegIdx][useIdx++] = n; + + /* if defined, stop finding uses for this reg */ + if (ticode->du.def & duReg[regi]) + break; + } + } + + /* Check if last definition of this register */ + if ((! (ticode->du.def & duReg[regi])) && + (pbb->liveOut & duReg[regi])) + picode->du.lastDefRegi |= duReg[regi]; + } + else /* only 1 instruction in this basic block */ + { + /* Check if last definition of this register */ + if (pbb->liveOut & duReg[regi]) + picode->du.lastDefRegi |= duReg[regi]; + } + + /* Find target icode for HLI_CALL icodes to procedures + * that are functions. The target icode is in the + * next basic block (unoptimized code) or somewhere else + * on optimized code. */ + if ((picode->ic.hl.opcode == HLI_CALL) && + (picode->ic.hl.oper.call.proc->flg & PROC_IS_FUNC)) + { + tbb = pbb->edges[0].BBptr; + useIdx = 0; + for (n = tbb->start; n < tbb->start + tbb->length; n++) + { + ticode = pProc->Icode.GetIcode(n); + if (ticode->type == HIGH_LEVEL) + { + /* if used, get icode index */ + if (ticode->du.use & duReg[regi]) + picode->du1.idx[defRegIdx][useIdx++] = n; + + /* if defined, stop finding uses for this reg */ + if (ticode->du.def & duReg[regi]) + break; + } + } + + /* if not used in this basic block, check if the + * register is live out, if so, make it the last + * definition of this register */ + if ((picode->du1.idx[defRegIdx][useIdx] == 0) && + (tbb->liveOut & duReg[regi])) + picode->du.lastDefRegi |= duReg[regi]; + } + + /* If not used within this bb or in successors of this + * bb (ie. not in liveOut), then register is useless, + * thus remove it. Also check that this is not a return + * from a library function (routines such as printf + * return an integer, which is normally not taken into + * account by the programmer). */ + if ((picode->invalid == FALSE) && + (picode->du1.idx[defRegIdx][0] == 0) && + (! (picode->du.lastDefRegi & duReg[regi])) && +// (! ((picode->ic.hl.opcode != HLI_CALL) && + (! ((picode->ic.hl.opcode == HLI_CALL) && + (picode->ic.hl.oper.call.proc->flg & PROC_ISLIB)))) + { + if (! (pbb->liveOut & duReg[regi])) /* not liveOut */ + { + res = removeDefRegi (regi, picode, defRegIdx+1, + &pProc->localId); + + /* Backpatch any uses of this instruction, within + * the same BB, if the instruction was invalidated */ + if (res == TRUE) + for (p = j; p > pbb->start; p--) + { + ticode = pProc->Icode.GetIcode(p-1); + for (n = 0; n < MAX_USES; n++) + { + if (ticode->du1.idx[0][n] == j) + { + if (n < MAX_USES - 1) + { + memmove (&ticode->du1.idx[0][n], + &ticode->du1.idx[0][n+1], + (size_t)((MAX_USES - n - 1) * sizeof(Int))); + n--; + } + ticode->du1.idx[0][MAX_USES - 1] = 0; + } + } + } + } + else /* liveOut */ + picode->du.lastDefRegi |= duReg[regi]; + } + defRegIdx++; + + /* Check if all defined registers have been processed */ + if ((defRegIdx >= picode->du1.numRegsDef) || + (defRegIdx == MAX_REGS_DEF)) + break; + } + } + } + } } } + +static void forwardSubs (COND_EXPR *lhs, COND_EXPR *rhs, PICODE picode, + PICODE ticode, LOCAL_ID *locsym, Int *numHlIcodes) /* Substitutes the rhs (or lhs if rhs not possible) of ticode for the rhs * of picode. */ -void LOCAL_ID::forwardSubs (COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const -{ - bool res; +{ boolT res; if (rhs == NULL) /* In case expression popped is NULL */ return; /* Insert on rhs of ticode, if possible */ - res = COND_EXPR::insertSubTreeReg (ticode->hl()->asgn.rhs,rhs, id_arr[lhs->expr.ident.idNode.regiIdx].id.regi, this); + res = insertSubTreeReg (rhs, &ticode->ic.hl.oper.asgn.rhs, + locsym->id[lhs->expr.ident.idNode.regiIdx].id.regi, + locsym); if (res) - { - picode->invalidate(); - numHlIcodes--; - } + { + invalidateIcode (picode); + (*numHlIcodes)--; + } else { /* Try to insert it on lhs of ticode*/ - res = COND_EXPR::insertSubTreeReg (ticode->hl()->asgn.lhs,rhs, id_arr[lhs->expr.ident.idNode.regiIdx].id.regi, this); + res = insertSubTreeReg (rhs, &ticode->ic.hl.oper.asgn.lhs, + locsym->id[lhs->expr.ident.idNode.regiIdx].id.regi, + locsym); if (res) - { - picode->invalidate(); - numHlIcodes--; - } + { + invalidateIcode (picode); + (*numHlIcodes)--; + } } } -/* Substitutes the rhs (or lhs if rhs not possible) of ticode for the +static void forwardSubsLong (Int longIdx, COND_EXPR *exp, PICODE picode, + PICODE ticode, Int *numHlIcodes) +/* Substitutes the rhs (or lhs if rhs not possible) of ticode for the * expression exp given */ -static void forwardSubsLong (int longIdx, COND_EXPR *_exp, iICODE picode, iICODE ticode, int *numHlIcodes) -{ - bool res; +{ boolT res; - if (_exp == NULL) /* In case expression popped is NULL */ + if (exp == NULL) /* In case expression popped is NULL */ return; /* Insert on rhs of ticode, if possible */ - res = COND_EXPR::insertSubTreeLongReg (_exp, &ticode->hl()->asgn.rhs, longIdx); + res = insertSubTreeLongReg (exp, &ticode->ic.hl.oper.asgn.rhs, longIdx); if (res) - { - picode->invalidate(); - (*numHlIcodes)--; - } + { + invalidateIcode (picode); + (*numHlIcodes)--; + } else { /* Try to insert it on lhs of ticode*/ - res = COND_EXPR::insertSubTreeLongReg (_exp, &ticode->hl()->asgn.lhs, longIdx); + res = insertSubTreeLongReg (exp, &ticode->ic.hl.oper.asgn.lhs, longIdx); if (res) - { - picode->invalidate(); - (*numHlIcodes)--; - } + { + invalidateIcode (picode); + (*numHlIcodes)--; + } } } +static boolT xClear (COND_EXPR *rhs, Int f, Int t, Int lastBBinst, PPROC pproc) /* Returns whether the elements of the expression rhs are all x-clear from * instruction f up to instruction t. */ -bool COND_EXPR::xClear (rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID & locId) -{ - iICODE i; - boolT res; - uint8_t regi; +{ Int i; + boolT res; + byte regi; + PICODE picode; + + if (rhs == NULL) + return (FALSE); - switch (m_type) - { - case IDENTIFIER: - if (expr.ident.idType == REGISTER) - { - regi= locId.id_arr[expr.ident.idNode.regiIdx].id.regi; - range_to_check.advance_begin(1); - auto all_valid_and_high_level_after_start = range_to_check | filtered(ICODE::select_valid_high_level); - for (ICODE &i : all_valid_and_high_level_after_start) - if ((i.du.def & duReg[regi]).any()) - return false; - if (all_valid_and_high_level_after_start.end().base() != lastBBinst) - return true; - return false; - } - else - return true; - /* else if (rhs->expr.ident.idType == LONG_VAR) - { - missing all other identifiers **** - } */ + switch (rhs->type) { + case IDENTIFIER: + if (rhs->expr.ident.idType == REGISTER) + { + picode = pproc->Icode.GetFirstIcode(); + regi= pproc->localId.id[rhs->expr.ident.idNode.regiIdx].id.regi; + for (i = (f + 1); (i < lastBBinst) && (i < t); i++) + if ((picode[i].type == HIGH_LEVEL) && + (picode[i].invalid == FALSE)) + { + if (picode[i].du.def & duReg[regi]) + return (FALSE); + } + if (i < lastBBinst) + return (TRUE); + else + return (FALSE); + } + else + return (TRUE); + /* else if (rhs->expr.ident.idType == LONG_VAR) + { +missing all other identifiers **** + } */ - case BOOLEAN_OP: - if(0==rhs()) - return false; - res = rhs()->xClear ( range_to_check, lastBBinst, locId); - if (res == false) - return false; - if(0==lhs()) - return false; - return lhs()->xClear ( range_to_check, lastBBinst, locId); + case BOOLEAN_OP: + res = xClear (rhs->expr.boolExpr.rhs, f, t, lastBBinst, pproc); + if (res == FALSE) + return (FALSE); + return (xClear (rhs->expr.boolExpr.lhs, f, t, lastBBinst, pproc)); - case NEGATION: - case ADDRESSOF: - case DEREFERENCE: - if(0==expr.unaryExp) - return false; - return expr.unaryExp->xClear ( range_to_check, lastBBinst, locId); - } /* eos */ - return false; -} -bool UnaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs) -{ - if(0==unaryExp) - return false; - return unaryExp->xClear ( range_to_check, lastBBinst, locs); + case NEGATION: + case ADDRESSOF: + case DEREFERENCE: + return (xClear (rhs->expr.unaryExp, f, t, lastBBinst, pproc)); + } /* eos */ + return FALSE; } -bool BinaryOperator::xClear(rICODE range_to_check, iICODE lastBBinst, const LOCAL_ID &locs) -{ - if(0==m_rhs) - return false; - if ( ! m_rhs->xClear (range_to_check, lastBBinst, locs) ) - return false; - if(0==m_lhs) - return false; - return m_lhs->xClear (range_to_check, lastBBinst, locs); -} + +static void processCArg (PPROC pp, PPROC pProc, PICODE picode, Int numArgs, + Int *k) /* Checks the type of the formal argument as against to the actual argument, * whenever possible, and then places the actual argument on the procedure's * argument list. */ -/// @returns the type size of the stored Arg -static int processCArg (Function * pp, Function * pProc, ICODE * picode, int numArgs) -{ - COND_EXPR *_exp; - bool res; +{ COND_EXPR *exp; + boolT res; - /* if (numArgs == 0) - return; */ + /* if (numArgs == 0) + return; */ - _exp = g_exp_stk.pop(); - if (pp->flg & PROC_ISLIB) /* library function */ - { - if (pp->args.numArgs > 0) - if (pp->flg & PROC_VARARG) - { - if (numArgs < pp->args.size()) - adjustActArgType (_exp, pp->args[numArgs].type, pProc); - } - else - adjustActArgType (_exp, pp->args[numArgs].type, pProc); - } - else /* user function */ - { - if (pp->args.numArgs > 0) - { - if(_exp==NULL) - fprintf(stderr,"Would try to adjustForArgType with null _exp\n"); - else - pp->args.adjustForArgType (numArgs, _exp->expType (pProc)); - } - } - res = picode->newStkArg (_exp, (llIcode)picode->ll()->getOpcode(), pProc); + exp = popExpStk(); + if (pp->flg & PROC_ISLIB) /* library function */ + { + if (pp->args.numArgs > 0) + if (pp->flg & PROC_VARARG) + { + if (numArgs < pp->args.csym) + adjustActArgType (exp, pp->args.sym[numArgs].type, pProc); + } + else + adjustActArgType (exp, pp->args.sym[numArgs].type, pProc); + res = newStkArg (picode, exp, picode->ic.ll.opcode, pProc); + } + else /* user function */ + { + if (pp->args.numArgs > 0) + adjustForArgType (&pp->args, numArgs, expType (exp, pProc)); + res = newStkArg (picode, exp, picode->ic.ll.opcode, pProc); + } - /* Do not update the size of k if the expression was a segment register - * in a near call */ - if (res == false) - return hlTypeSize (_exp, pProc); - return 0; // be default we do not know the size of the argument + /* Do not update the size of k if the expression was a segment register + * in a near call */ + if (res == FALSE) + *k += hlTypeSize (exp, pProc); } -/** Eliminates extraneous intermediate icode instructions when finding - * expressions. Generates new hlIcodes in the form of expression trees. + +static void findExps (PPROC pProc) +/* Eliminates extraneous intermediate icode instructions when finding + * expressions. Generates new hlIcodes in the form of expression trees. * For HLI_CALL hlIcodes, places the arguments in the argument list. */ -void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode,bool isLong) const -{ - boolT res; - HLTYPE &p_hl(*picode->hl()); - HLTYPE &t_hl(*ticode->hl()); - switch (t_hl.opcode) - { - case HLI_ASSIGN: - if(isLong) - { - forwardSubsLong (p_hl.asgn.lhs->expr.ident.idNode.longIdx, - p_hl.asgn.rhs, picode,ticode, - &numHlIcodes); - } - else - this->forwardSubs (p_hl.asgn.lhs, p_hl.asgn.rhs, picode, ticode, numHlIcodes); - break; +{ Int i, j, k, lastInst, lastInstN, numHlIcodes; + PICODE picode, /* Current icode */ + ticode; /* Target icode */ + PBB pbb, nbb; /* Current and next basic block */ + boolT res; + COND_EXPR *exp, /* expression pointer - for HLI_POP and HLI_CALL */ + *lhs; /* exp ptr for return value of a HLI_CALL */ + PSTKFRAME args; /* pointer to arguments - for HLI_CALL */ + byte regi, regi2; /* register(s) to be forward substituted */ + ID *retVal; /* function return value */ - case HLI_JCOND: case HLI_PUSH: case HLI_RET: - if(isLong) - { - res = COND_EXPR::insertSubTreeLongReg ( - p_hl.asgn.rhs, - &t_hl.exp.v, - p_hl.asgn.lhs->expr.ident.idNode.longIdx); - } - else - { - res = COND_EXPR::insertSubTreeReg ( - t_hl.exp.v, - p_hl.asgn.rhs, - id_arr[p_hl.asgn.lhs->expr.ident.idNode.regiIdx].id.regi, - this); - } - if (res) - { - picode->invalidate(); - numHlIcodes--; - } - break; - - case HLI_CALL: /* register arguments */ - newRegArg ( picode, ticode); - picode->invalidate(); - numHlIcodes--; - break; - } -} - -void Function::processHliCall(COND_EXPR *_exp, iICODE picode) -{ - Function * pp; - int cb, numArgs; - boolT res; - int k; - pp = picode->hl()->call.proc; - if (pp->flg & CALL_PASCAL) - { - cb = pp->cbParam; /* fixed # arguments */ - k = 0; - numArgs = 0; - while(kflg & PROC_ISLIB) /* library function */ - { - if (pp->args.numArgs > 0) - adjustActArgType(_exp, pp->args[numArgs].type, this); - res = picode->newStkArg (_exp, (llIcode)picode->ll()->getOpcode(), this); - } - else /* user function */ - { - if (pp->args.numArgs >0) - { - if(_exp==NULL) - { - fprintf(stderr,"Would try to adjustForArgType with null _exp\n"); - } - pp->args.adjustForArgType (numArgs,_exp->expType (this)); - } - res = picode->newStkArg (_exp,(llIcode)picode->ll()->getOpcode(), this); - } - if (res == false) - k += hlTypeSize (_exp, this); - numArgs++; - } - } - else /* CALL_C */ - { - cb = picode->hl()->call.args->cb; - numArgs = 0; - k = 0; - if (cb) - { - while ( k < cb ) - { - k+=processCArg (pp, this, &(*picode), numArgs); - numArgs++; - } - } - else if ((cb == 0) && picode->ll()->testFlags(REST_STK)) - { - while (! g_exp_stk.empty()) - { - k+=processCArg (pp, this, &(*picode), numArgs); - numArgs++; - } - } - } -} - - -int BB::findBBExps(LOCAL_ID &locals,Function *fnc) -{ - bool res; - - ID *_retVal; // function return value - COND_EXPR *_exp, // expression pointer - for HLI_POP and HLI_CALL */ - *lhs; // exp ptr for return value of a HLI_CALL */ - iICODE ticode; // Target icode */ - HLTYPE *ti_hl=0; - uint8_t regi; - numHlIcodes = 0; - // register(s) to be forward substituted */ - auto valid_and_highlevel = instructions | filtered(ICODE::TypeAndValidFilter()); - for (auto picode = valid_and_highlevel.begin(); picode != valid_and_highlevel.end(); picode++) - { -// if ((picode->type != HIGH_LEVEL) || ( ! picode->valid() )) -// continue; - HLTYPE &_icHl(*picode->hl()); - numHlIcodes++; - if (picode->du1.numRegsDef == 1) /* uint8_t/uint16_t regs */ - { - /* Check for only one use of this register. If this is - * the last definition of the register in this BB, check - * that it is not liveOut from this basic block */ - if (picode->du1.numUses(0)==1) - { - /* Check that this register is not liveOut, if it - * is the last definition of the register */ - regi = picode->du1.regi[0]; - - /* Check if we can forward substitute this register */ - switch (_icHl.opcode) - { - case HLI_ASSIGN: - /* Replace rhs of current icode into target - * icode expression */ - - ticode = picode->du1.idx[0].uses.front(); - if ((picode->du.lastDefRegi & duReg[regi]).any() && - ((ticode->hl()->opcode != HLI_CALL) && - (ticode->hl()->opcode != HLI_RET))) - continue; - - if (_icHl.asgn.rhs->xClear (make_iterator_range(picode.base(),picode->du1.idx[0].uses[0]), - end(), locals)) - { - locals.processTargetIcode(picode.base(), numHlIcodes, ticode,false); - } - break; - - case HLI_POP: - ticode = picode->du1.idx[0].uses.front(); - ti_hl = ticode->hl(); - if ((picode->du.lastDefRegi & duReg[regi]).any() && - ((ti_hl->opcode != HLI_CALL) && - (ti_hl->opcode != HLI_RET))) - continue; - - _exp = g_exp_stk.pop(); /* pop last exp pushed */ - switch (ticode->hl()->opcode) { - case HLI_ASSIGN: - locals.forwardSubs(_icHl.expr(), _exp, picode.base(), ticode, numHlIcodes); - break; - - case HLI_JCOND: case HLI_PUSH: case HLI_RET: - res = COND_EXPR::insertSubTreeReg (ti_hl->exp.v, - _exp, - locals.id_arr[_icHl.expr()->expr.ident.idNode.regiIdx].id.regi, - &locals); - if (res) - { - picode->invalidate(); - numHlIcodes--; - } - break; - - /****case HLI_CALL: /* register arguments - newRegArg (pProc, picode, ticode); - picode->invalidate(); - numHlIcodes--; - break; */ - } /* eos */ - break; - - case HLI_CALL: - ticode = picode->du1.idx[0].uses.front(); - ti_hl = ticode->hl(); - _retVal = &_icHl.call.proc->retVal; - switch (ti_hl->opcode) - { - case HLI_ASSIGN: - assert(ti_hl->asgn.rhs); - _exp = _icHl.call.toId(); - res = COND_EXPR::insertSubTreeReg (ti_hl->asgn.rhs,_exp, _retVal->id.regi, &locals); - if (! res) - COND_EXPR::insertSubTreeReg (ti_hl->asgn.lhs, _exp,_retVal->id.regi, &locals); - //TODO: HERE missing: 2 regs - picode->invalidate(); - numHlIcodes--; - break; - - case HLI_PUSH: case HLI_RET: - ti_hl->expr( _icHl.call.toId() ); - picode->invalidate(); - numHlIcodes--; - break; - - case HLI_JCOND: - _exp = _icHl.call.toId(); - res = COND_EXPR::insertSubTreeReg (ti_hl->exp.v, _exp, _retVal->id.regi, &locals); - if (res) /* was substituted */ - { - picode->invalidate(); - numHlIcodes--; - } - else /* cannot substitute function */ - { - //picode->loc_ip - lhs = COND_EXPR::idID(_retVal,&locals,picode.base()); - picode->setAsgn(lhs, _exp); - } - break; - } /* eos */ - break; - } /* eos */ - } - } - - else if (picode->du1.numRegsDef == 2) /* long regs */ - { - /* Check for only one use of these registers */ - if ((picode->du1.numUses(0) == 1) and (picode->du1.numUses(1) == 1)) - { - regi = picode->du1.regi[0]; //TODO: verify that regi actually should be assigned this - - switch (_icHl.opcode) - { - case HLI_ASSIGN: - /* Replace rhs of current icode into target - * icode expression */ - if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0]) - { - ticode = picode->du1.idx[0].uses.front(); - if ((picode->du.lastDefRegi & duReg[regi]).any() && - ((ticode->hl()->opcode != HLI_CALL) && - (ticode->hl()->opcode != HLI_RET))) - continue; - locals.processTargetIcode(picode.base(), numHlIcodes, ticode,true); - } - break; - - case HLI_POP: - if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0]) - { - ticode = picode->du1.idx[0].uses.front(); - if ((picode->du.lastDefRegi & duReg[regi]).any() && - ((ticode->hl()->opcode != HLI_CALL) && - (ticode->hl()->opcode != HLI_RET))) - continue; - - _exp = g_exp_stk.pop(); /* pop last exp pushed */ - switch (ticode->hl()->opcode) { - case HLI_ASSIGN: - forwardSubsLong (_icHl.expr()->expr.ident.idNode.longIdx, - _exp, picode.base(), ticode, &numHlIcodes); - break; - case HLI_JCOND: case HLI_PUSH: - res = COND_EXPR::insertSubTreeLongReg (_exp, - &ticode->hl()->exp.v, - _icHl.asgn.lhs->expr.ident.idNode.longIdx); - if (res) - { - picode->invalidate(); - numHlIcodes--; - } - break; - case HLI_CALL: /*** missing ***/ - break; - } /* eos */ - } - break; - - case HLI_CALL: /* check for function return */ - ticode = picode->du1.idx[0].uses.front(); - switch (ticode->hl()->opcode) - { - case HLI_ASSIGN: - _exp = _icHl.call.toId(); - ticode->hl()->asgn.lhs = - COND_EXPR::idLong(&locals, DST, - ticode,HIGH_FIRST, picode.base(), - eDEF, *(++iICODE(ticode))->ll()); - ticode->hl()->asgn.rhs = _exp; - picode->invalidate(); - numHlIcodes--; - break; - - case HLI_PUSH: case HLI_RET: - ticode->hl()->expr( _icHl.call.toId() ); - picode->invalidate(); - numHlIcodes--; - break; - - case HLI_JCOND: - _exp = _icHl.call.toId(); - _retVal = &picode->hl()->call.proc->retVal; - res = COND_EXPR::insertSubTreeLongReg (_exp, - &ticode->hl()->exp.v, - locals.newLongReg ( _retVal->type, _retVal->id.longId.h, - _retVal->id.longId.l, picode.base())); - if (res) /* was substituted */ - { - picode->invalidate(); - numHlIcodes--; - } - else /* cannot substitute function */ - { - lhs = locals.createId(_retVal,picode.base()); - picode->setAsgn(lhs, _exp); - } - break; - } /* eos */ - } /* eos */ - } - } - /* HLI_PUSH doesn't define any registers, only uses registers. - * Push the associated expression to the register on the local - * expression stack */ - else if (_icHl.opcode == HLI_PUSH) - { - g_exp_stk.processExpPush(numHlIcodes, picode.base()); - } - else if(picode->du1.numRegsDef!=0) - printf("Num def %d\n",picode->du1.numRegsDef); - - /* For HLI_CALL instructions that use arguments from the stack, - * pop them from the expression stack and place them on the - * procedure's argument list */ - if(_icHl.opcode == HLI_CALL) - { - if ( not _icHl.call.proc->hasRegArgs()) - { - fnc->processHliCall(_exp, picode.base()); - } - - /* If we could not substitute the result of a function, - * assign it to the corresponding registers */ - if ( not _icHl.call.proc->isLibrary() and (not picode->du1.used(0)) and (picode->du1.numRegsDef > 0)) - { - _exp = COND_EXPR::idFunc (_icHl.call.proc, _icHl.call.args); - lhs = COND_EXPR::idID (&_icHl.call.proc->retVal, &locals, picode.base()); - picode->setAsgn(lhs, _exp); - } - } - } - /* Store number of high-level icodes in current basic block */ - -} - -void Function::findExps() -{ - //int i, numHlIcodes; - //STKFRAME * args; // pointer to arguments - for HLI_CALL */ - - /* Initialize expression stack */ - g_exp_stk.init(); + /* Initialize expression stack */ + initExpStk(); /* Traverse tree in dfsLast order */ -// for (i = 0; i < numBBs; i++) - for(BB *pbb : m_dfsLast) + for (i = 0; i < pProc->numBBs; i++) { /* Process one BB */ -// pbb = m_dfsLast[i]; - if (not pbb->valid()) - continue; - pbb->findBBExps( this->localId, this); + pbb = pProc->dfsLast[i]; + if (pbb->flg & INVALID_BB) continue; + lastInst = pbb->start + pbb->length; + numHlIcodes = 0; + for (j = pbb->start; j < lastInst; j++) + { + picode = pProc->Icode.GetIcode(j); + if ((picode->type == HIGH_LEVEL) && (picode->invalid == FALSE)) + { + numHlIcodes++; + if (picode->du1.numRegsDef == 1) /* byte/word regs */ + { + /* Check for only one use of this register. If this is + * the last definition of the register in this BB, check + * that it is not liveOut from this basic block */ + if ((picode->du1.idx[0][0] != 0) && + (picode->du1.idx[0][1] == 0)) + { + /* Check that this register is not liveOut, if it + * is the last definition of the register */ + regi = picode->du1.regi[0]; + /* Check if we can forward substitute this register */ + switch (picode->ic.hl.opcode) { + case HLI_ASSIGN: + /* Replace rhs of current icode into target + * icode expression */ + ticode = pProc->Icode.GetIcode(picode->du1.idx[0][0]); + if ((picode->du.lastDefRegi & duReg[regi]) && + ((ticode->ic.hl.opcode != HLI_CALL) && + (ticode->ic.hl.opcode != HLI_RET))) + continue; + + if (xClear (picode->ic.hl.oper.asgn.rhs, j, + picode->du1.idx[0][0], lastInst, pProc)) + { + switch (ticode->ic.hl.opcode) { + case HLI_ASSIGN: + forwardSubs (picode->ic.hl.oper.asgn.lhs, + picode->ic.hl.oper.asgn.rhs, + picode, ticode, &pProc->localId, + &numHlIcodes); + break; + + case HLI_JCOND: case HLI_PUSH: case HLI_RET: + res = insertSubTreeReg ( + picode->ic.hl.oper.asgn.rhs, + &ticode->ic.hl.oper.exp, + pProc->localId.id[picode->ic.hl.oper.asgn.lhs->expr.ident.idNode.regiIdx].id.regi, + &pProc->localId); + if (res) + { + invalidateIcode (picode); + numHlIcodes--; + } + break; + + case HLI_CALL: /* register arguments */ + newRegArg (pProc, picode, ticode); + invalidateIcode (picode); + numHlIcodes--; + break; + } /* eos */ + } + break; + + case HLI_POP: + ticode = pProc->Icode.GetIcode(picode->du1.idx[0][0]); + if ((picode->du.lastDefRegi & duReg[regi]) && + ((ticode->ic.hl.opcode != HLI_CALL) && + (ticode->ic.hl.opcode != HLI_RET))) + continue; + + exp = popExpStk(); /* pop last exp pushed */ + switch (ticode->ic.hl.opcode) { + case HLI_ASSIGN: + forwardSubs (picode->ic.hl.oper.exp, exp, + picode, ticode, &pProc->localId, + &numHlIcodes); + break; + + case HLI_JCOND: case HLI_PUSH: case HLI_RET: + res = insertSubTreeReg (exp, + &ticode->ic.hl.oper.exp, + pProc->localId.id[picode->ic.hl.oper.exp->expr.ident.idNode.regiIdx].id.regi, + &pProc->localId); + if (res) + { + invalidateIcode (picode); + numHlIcodes--; + } + break; + + /****case HLI_CALL: /* register arguments + newRegArg (pProc, picode, ticode); + invalidateIcode (picode); + numHlIcodes--; + break; */ + } /* eos */ + break; + + case HLI_CALL: + ticode = pProc->Icode.GetIcode(picode->du1.idx[0][0]); + switch (ticode->ic.hl.opcode) { + case HLI_ASSIGN: + exp = idCondExpFunc ( + picode->ic.hl.oper.call.proc, + picode->ic.hl.oper.call.args); + res = insertSubTreeReg (exp, + &ticode->ic.hl.oper.asgn.rhs, + picode->ic.hl.oper.call.proc->retVal.id.regi, + &pProc->localId); + if (! res) + insertSubTreeReg (exp, + &ticode->ic.hl.oper.asgn.lhs, + picode->ic.hl.oper.call.proc->retVal.id.regi, + &pProc->localId); + /*** HERE missing: 2 regs ****/ + invalidateIcode (picode); + numHlIcodes--; + break; + + case HLI_PUSH: case HLI_RET: + exp = idCondExpFunc ( + picode->ic.hl.oper.call.proc, + picode->ic.hl.oper.call.args); + ticode->ic.hl.oper.exp = exp; + invalidateIcode (picode); + numHlIcodes--; + break; + + case HLI_JCOND: + exp = idCondExpFunc ( + picode->ic.hl.oper.call.proc, + picode->ic.hl.oper.call.args); + retVal = &picode->ic.hl.oper.call.proc->retVal, + res = insertSubTreeReg (exp, + &ticode->ic.hl.oper.exp, + retVal->id.regi, &pProc->localId); + if (res) /* was substituted */ + { + invalidateIcode (picode); + numHlIcodes--; + } + else /* cannot substitute function */ + { + lhs = idCondExpID(retVal,&pProc->localId,j); + newAsgnHlIcode (picode, lhs, exp); + } + break; + } /* eos */ + break; + } /* eos */ + } + } + + else if (picode->du1.numRegsDef == 2) /* long regs */ + { + /* Check for only one use of these registers */ + if ((picode->du1.idx[0][0] != 0) && + (picode->du1.idx[0][1] == 0) && + (picode->du1.idx[1][0] != 0) && + (picode->du1.idx[1][1] == 0)) + { + switch (picode->ic.hl.opcode) { + case HLI_ASSIGN: + /* Replace rhs of current icode into target + * icode expression */ + if (picode->du1.idx[0][0] == picode->du1.idx[1][0]) + { + ticode = pProc->Icode.GetIcode(picode->du1.idx[0][0]); + if ((picode->du.lastDefRegi & duReg[regi]) && + ((ticode->ic.hl.opcode != HLI_CALL) && + (ticode->ic.hl.opcode != HLI_RET))) + continue; + + switch (ticode->ic.hl.opcode) { + case HLI_ASSIGN: + forwardSubsLong (picode->ic.hl.oper.asgn.lhs->expr.ident.idNode.longIdx, + picode->ic.hl.oper.asgn.rhs, picode, + ticode, &numHlIcodes); + break; + + case HLI_JCOND: case HLI_PUSH: case HLI_RET: + res = insertSubTreeLongReg ( + picode->ic.hl.oper.asgn.rhs, + &ticode->ic.hl.oper.exp, + picode->ic.hl.oper.asgn.lhs->expr.ident.idNode.longIdx); + if (res) + { + invalidateIcode (picode); + numHlIcodes--; + } + break; + + case HLI_CALL: /* register arguments */ + newRegArg (pProc, picode, ticode); + invalidateIcode (picode); + numHlIcodes--; + break; + } /* eos */ + } + break; + + case HLI_POP: + if (picode->du1.idx[0][0] == picode->du1.idx[1][0]) + { + ticode = pProc->Icode.GetIcode(picode->du1.idx[0][0]); + if ((picode->du.lastDefRegi & duReg[regi]) && + ((ticode->ic.hl.opcode != HLI_CALL) && + (ticode->ic.hl.opcode != HLI_RET))) + continue; + + exp = popExpStk(); /* pop last exp pushed */ + switch (ticode->ic.hl.opcode) { + case HLI_ASSIGN: + forwardSubsLong (picode->ic.hl.oper.exp->expr.ident.idNode.longIdx, + exp, picode, ticode, &numHlIcodes); + break; + case HLI_JCOND: case HLI_PUSH: + res = insertSubTreeLongReg (exp, + &ticode->ic.hl.oper.exp, + picode->ic.hl.oper.asgn.lhs->expr.ident.idNode.longIdx); + if (res) + { + invalidateIcode (picode); + numHlIcodes--; + } + break; + case HLI_CALL: /*** missing ***/ + break; + } /* eos */ + } + break; + + case HLI_CALL: /* check for function return */ + ticode = pProc->Icode.GetIcode(picode->du1.idx[0][0]); + switch (ticode->ic.hl.opcode) { + case HLI_ASSIGN: + exp = idCondExpFunc ( + picode->ic.hl.oper.call.proc, + picode->ic.hl.oper.call.args); + ticode->ic.hl.oper.asgn.lhs = + idCondExpLong(&pProc->localId, DST, ticode, + HIGH_FIRST, j, E_DEF, 1); + ticode->ic.hl.oper.asgn.rhs = exp; + invalidateIcode (picode); + numHlIcodes--; + break; + + case HLI_PUSH: case HLI_RET: + exp = idCondExpFunc ( + picode->ic.hl.oper.call.proc, + picode->ic.hl.oper.call.args); + ticode->ic.hl.oper.exp = exp; + invalidateIcode (picode); + numHlIcodes--; + break; + + case HLI_JCOND: + exp = idCondExpFunc ( + picode->ic.hl.oper.call.proc, + picode->ic.hl.oper.call.args); + retVal = &picode->ic.hl.oper.call.proc->retVal; + res = insertSubTreeLongReg (exp, + &ticode->ic.hl.oper.exp, + newLongRegId (&pProc->localId, + retVal->type, retVal->id.longId.h, + retVal->id.longId.l, j)); + if (res) /* was substituted */ + { + invalidateIcode (picode); + numHlIcodes--; + } + else /* cannot substitute function */ + { + lhs = idCondExpID(retVal,&pProc->localId,j); + newAsgnHlIcode (picode, lhs, exp); + } + break; + } /* eos */ + } /* eos */ + } + } + + /* HLI_PUSH doesn't define any registers, only uses registers. + * Push the associated expression to the register on the local + * expression stack */ + else if (picode->ic.hl.opcode == HLI_PUSH) + { + pushExpStk (picode->ic.hl.oper.exp); + invalidateIcode (picode); + numHlIcodes--; + } + + /* For HLI_CALL instructions that use arguments from the stack, + * pop them from the expression stack and place them on the + * procedure's argument list */ + if ((picode->ic.hl.opcode == HLI_CALL) && + ! (picode->ic.hl.oper.call.proc->flg & REG_ARGS)) + { PPROC pp; + Int cb, numArgs; + boolT res; + + pp = picode->ic.hl.oper.call.proc; + if (pp->flg & CALL_PASCAL) + { + cb = pp->cbParam; /* fixed # arguments */ + for (k = 0, numArgs = 0; k < cb; numArgs++) + { + exp = popExpStk(); + if (pp->flg & PROC_ISLIB) /* library function */ + { + if (pp->args.numArgs > 0) + adjustActArgType(exp, + pp->args.sym[numArgs].type, pProc); + res = newStkArg (picode, exp, + picode->ic.ll.opcode, pProc); + } + else /* user function */ + { + if (pp->args.numArgs >0) + adjustForArgType (&pp->args, numArgs, + expType (exp, pProc)); + res = newStkArg (picode, exp, + picode->ic.ll.opcode, pProc); + } + if (res == FALSE) + k += hlTypeSize (exp, pProc); + } + } + else /* CALL_C */ + { + cb = picode->ic.hl.oper.call.args->cb; + numArgs = 0; + if (cb) + for (k = 0; k < cb; numArgs++) + processCArg (pp, pProc, picode, numArgs, &k); + else if ((cb == 0) && (picode->ic.ll.flg & REST_STK)) + while (! emptyExpStk()) + { + processCArg (pp, pProc, picode, numArgs, &k); + numArgs++; + } + } + } + + /* If we could not substitute the result of a function, + * assign it to the corresponding registers */ + if ((picode->ic.hl.opcode == HLI_CALL) && + ((picode->ic.hl.oper.call.proc->flg & PROC_ISLIB) != + PROC_ISLIB) && (picode->du1.idx[0][0] == 0) && + (picode->du1.numRegsDef > 0)) + { + exp = idCondExpFunc (picode->ic.hl.oper.call.proc, + picode->ic.hl.oper.call.args); + lhs = idCondExpID (&picode->ic.hl.oper.call.proc->retVal, + &pProc->localId, j); + newAsgnHlIcode (picode, lhs, exp); + } + } + } + + /* Store number of high-level icodes in current basic block */ + pbb->numHlIcodes = numHlIcodes; } } -void Function::preprocessReturnDU(std::bitset<32> &_liveOut) -{ - if (_liveOut.any()) + +void dataFlow (PPROC pProc, dword liveOut) +/* Invokes procedures related with data flow analysis. Works on a procedure + * at a time basis. + * Note: indirect recursion in liveRegAnalysis is possible. */ +{ boolT isAx, isBx, isCx, isDx; + Int idx; + + /* Remove references to register variables */ + if (pProc->flg & SI_REGVAR) + liveOut &= maskDuReg[rSI]; + if (pProc->flg & DI_REGVAR) + liveOut &= maskDuReg[rDI]; + + /* Function - return value register(s) */ + if (liveOut != 0) { - int idx; - bool isAx, isBx, isCx, isDx; - flg |= PROC_IS_FUNC; - isAx = _liveOut.test(rAX - rAX); - isBx = _liveOut.test(rBX - rAX); - isCx = _liveOut.test(rCX - rAX); - isDx = _liveOut.test(rDX - rAX); - bool isAL = !isAx && _liveOut.test(rAL - rAX); - bool isAH = !isAx && _liveOut.test(rAH - rAX); - bool isBL = !isBx && _liveOut.test(rBL - rAX); - bool isBH = !isBx && _liveOut.test(rBH - rAX); - bool isCL = !isCx && _liveOut.test(rCL - rAX); - bool isCH = !isCx && _liveOut.test(rCH - rAX); - bool isDL = !isDx && _liveOut.test(rDL - rAX); - bool isDH = !isDx && _liveOut.test(rDH - rAX); - if(isAL && isAH) - { - isAx = true; - isAH=isAL=false; - } - if(isDL && isDH) - { - isDx = true; - isDH=isDL=false; - } - if(isBL && isBH) - { - isBx = true; - isBH=isBL=false; - } - if(isCL && isCH) - { - isCx = true; - isCH=isCL=false; - } + pProc->flg |= PROC_IS_FUNC; + isAx = (boolT)(liveOut & power2(rAX - rAX)); + isBx = (boolT)(liveOut & power2(rBX - rAX)); + isCx = (boolT)(liveOut & power2(rCX - rAX)); + isDx = (boolT)(liveOut & power2(rDX - rAX)); if (isAx && isDx) /* long or pointer */ { - retVal.type = TYPE_LONG_SIGN; - retVal.loc = REG_FRAME; - retVal.id.longId.h = rDX; - retVal.id.longId.l = rAX; - idx = localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, Icode.begin()/*0*/); - localId.propLongId (rAX, rDX, "\0"); + pProc->retVal.type = TYPE_LONG_SIGN; + pProc->retVal.loc = REG_FRAME; + pProc->retVal.id.longId.h = rDX; + pProc->retVal.id.longId.l = rAX; + idx = newLongRegId (&pProc->localId, TYPE_LONG_SIGN, rDX, rAX, 0); + propLongId (&pProc->localId, rAX, rDX, "\0"); } - else if (isAx || isBx || isCx || isDx) /* uint16_t */ + else if (isAx || isBx || isCx || isDx) /* word */ { - retVal.type = TYPE_WORD_SIGN; - retVal.loc = REG_FRAME; + pProc->retVal.type = TYPE_WORD_SIGN; + pProc->retVal.loc = REG_FRAME; if (isAx) - retVal.id.regi = rAX; + pProc->retVal.id.regi = rAX; else if (isBx) - retVal.id.regi = rBX; + pProc->retVal.id.regi = rBX; else if (isCx) - retVal.id.regi = rCX; - else - retVal.id.regi = rDX; - idx = localId.newByteWordReg(TYPE_WORD_SIGN,retVal.id.regi); - } - else if(isAL||isBL||isCL||isDL) - { - retVal.type = TYPE_BYTE_SIGN; - retVal.loc = REG_FRAME; - if (isAL) - retVal.id.regi = rAL; - else if (isBL) - retVal.id.regi = rBL; - else if (isCL) - retVal.id.regi = rCL; - else - retVal.id.regi = rDL; - idx = localId.newByteWordReg(TYPE_BYTE_SIGN,retVal.id.regi); - + pProc->retVal.id.regi = rCX; + else + pProc->retVal.id.regi = rDX; + idx = newByteWordRegId (&pProc->localId, TYPE_WORD_SIGN, + pProc->retVal.id.regi); } } -} -/** Invokes procedures related with data flow analysis. Works on a procedure - * at a time basis. - * Note: indirect recursion in liveRegAnalysis is possible. */ -void Function::dataFlow(std::bitset<32> &_liveOut) -{ - - /* Remove references to register variables */ - if (flg & SI_REGVAR) - _liveOut &= maskDuReg[rSI]; - if (flg & DI_REGVAR) - _liveOut &= maskDuReg[rDI]; - - /* Function - return value register(s) */ - preprocessReturnDU(_liveOut); /* Data flow analysis */ - liveAnal = true; - elimCondCodes(); - genLiveKtes(); - liveRegAnalysis (_liveOut); /* calls dataFlow() recursively */ - if (! (flg & PROC_ASM)) /* can generate C for pProc */ - { - genDU1 (); /* generate def/use level 1 chain */ - findExps (); /* forward substitution algorithm */ - } + pProc->liveAnal = TRUE; + elimCondCodes (pProc); + genLiveKtes (pProc); + liveRegAnalysis (pProc, liveOut); /* calls dataFlow() recursively */ + if (! (pProc->flg & PROC_ASM)) /* can generate C for pProc */ + { + genDU1 (pProc); /* generate def/use level 1 chain */ + findExps (pProc); /* forward substitution algorithm */ + } } diff --git a/src/dcc.cpp b/src/dcc.cpp index 30f5113..a76cb68 100644 --- a/src/dcc.cpp +++ b/src/dcc.cpp @@ -5,36 +5,37 @@ ****************************************************************************/ #include "dcc.h" -#include "project.h" #include +#ifdef __UNIX__ +#include +#else +#include +#include /* 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 */ +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 */ -//FunctionListType pProcList; -//CALL_GRAPH *callGraph; /* Call graph of the program */ +PPROC pProcList; /* List of procedures, topologically sort */ +PPROC pLastProc; /* Pointer to last node in procedure list */ +CALL_GRAPH *callGraph; /* Call graph of the program */ static char *initargs(int argc, char *argv[]); -static void displayTotalStats(void); -#include +static void displayTotalStats(); + /**************************************************************************** * main ***************************************************************************/ -#include -extern Project g_proj; + + int main(int argc, char *argv[]) { -// llvm::MCOperand op=llvm::MCOperand::CreateImm(11); -// llvm::MCAsmInfo info; -// llvm::raw_os_ostream wrap(std::cerr); -// op.print(wrap,&info); -// wrap.flush(); /* Extract switches and filename */ strcpy(option.filename, initargs(argc, argv)); @@ -42,9 +43,7 @@ int main(int argc, char *argv[]) * building the call graph and attaching appropriate bits of code for * each procedure. */ - DccFrontend fe(option.filename); - if(false==fe.FrontEnd ()) - return -1; + 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 @@ -56,14 +55,14 @@ int main(int argc, char *argv[]) * analysis, data flow etc. and outputs it to output file ready for * re-compilation. */ - BackEnd(option.filename, g_proj.callGraph); + BackEnd(option.filename, callGraph); - g_proj.callGraph->write(); + writeCallGraph (callGraph); if (option.Stats) displayTotalStats(); - /* +/* freeDataStructures(pProcList); */ return 0; @@ -75,51 +74,50 @@ int main(int argc, char *argv[]) static char *initargs(int argc, char *argv[]) { char *pc; + progname = *argv; /* Save invocation name for error messages */ - while (--argc > 0 && (*++argv)[0] == '-') - { + 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': - option.verbose = true; /* Make everything verbose */ - 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; + 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:; + NextArg:; } if (argc == 1) @@ -128,13 +126,13 @@ NextArg:; { if (! asm1_name) { - asm1_name = strcpy((char*)malloc(strlen(*argv)+4), *argv); + asm1_name = strcpy((char*)allocMem(strlen(*argv)+4), *argv); pc = strrchr(asm1_name, '.'); if (pc > strrchr(asm1_name, '/')) { *pc = '\0'; } - asm2_name = (char*)malloc(strlen(asm1_name)+4) ; + asm2_name = (char*)allocMem(strlen(asm1_name)+4) ; strcat(strcpy(asm2_name, asm1_name), ".a2"); unlink(asm2_name); strcat(asm1_name, ".a1"); @@ -142,10 +140,10 @@ NextArg:; unlink(asm1_name); /* Remove asm output files */ } return *argv; /* filename of the program to decompile */ - } + } fatalError(USAGE); - return *argv; // does not reach this. + return *argv; } static void diff --git a/src/disassem.cpp b/src/disassem.cpp index 6dd2fed..616e053 100644 --- a/src/disassem.cpp +++ b/src/disassem.cpp @@ -2,146 +2,288 @@ * dcc project disassembler * (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann ****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include #include "dcc.h" #include "symtab.h" +#include +#include +#include +#ifdef __BORLAND__ +#include +#else +#include /* For free() */ +#endif +#ifdef _CONSOLE +#include /* For console mode routines */ +#endif #include "disassem.h" -#include "project.h" // Note: for the time being, there is no interactive disassembler // for unix +#ifndef __UNIX__ +#include // getch() etc +#endif -using namespace std; +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif #define POS_LAB 15 /* Position of label */ #define POS_OPC 20 /* Position of opcode */ #define POS_OPR 25 /* Position of operand */ -#define WID_PTR 10 /* Width of the "xword ptr" lingo */ +#define WID_PTR 10 /* Width of the "xword ptr" lingo */ #define POS_OPR2 POS_OPR+WID_PTR /* Position of operand after "xword ptr" */ #define POS_CMT 54 /* Position of comment */ -static const char *szFlops0C[] = + +#define DELTA_ICODE 16 /* Number of icodes to realloc by each time */ + +static char *szOps[] = { - "FCHS", "FABS", "???", "???", "FTST", "FXAM", "???", "???" +"CBW", "AAA", "AAD", "AAM", "AAS", "ADC", "ADD", "AND", +"BOUND","CALL", "CALL", "CLC", "CLD", "CLI", "CMC", "CMP", +"CMPS", "REPNE CMPS","REPE CMPS","DAA", "DAS", "DEC", "DIV", "ENTER", +"ESC", "HLT", "IDIV", "IMUL", "IN", "INC", "INS", "REP INS", +"INT", "IRET", "JB", "JBE", "JAE", "JA", "JE", "JNE", +"JL", "JGE", "JLE", "JG", "JS", "JNS", "JO", "JNO", +"JP", "JNP", "JCXZ", "JMP", "JMP", "LAHF", "LDS", "LEA", +"LEAVE","LES", "LOCK", "LODS", "REP LODS", "LOOP", "LOOPE","LOOPNE", +"MOV", "MOVS", "REP MOVS", "MUL", "NEG", "NOT", "OR", "OUT", +"OUTS", "REP OUTS", "POP", "POPA", "POPF", "PUSH", "PUSHA","PUSHF", +"RCL", "RCR", "ROL", "ROR", "RET", "RETF", "SAHF", "SAR", +"SHL", "SHR", "SBB", "SCAS", "REPNE SCAS","REPE SCAS", "CWD", "STC", +"STD", "STI", "STOS", "REP STOS", "SUB", "TEST", "WAIT", "XCHG", +"XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD" }; -static const char *szFlops0D[] = +/* The following opcodes are for mod != 3 */ +static char *szFlops1[] = { - "FLD1", "FLDL2T","FLDL2E","FLDP1", "FLDLG2","FLDLN2","FLDZ", "???" +/* 0 1 2 3 4 5 6 7 */ +"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */ +"FLD", "???", "FST", "???", "FLDENV","FLDCW", "FSTENV","FSTSW", /* 08 */ +"FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 10 */ +"FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */ +"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */ +"FLD", "FLD", "FST", "FSTP", "FRESTOR","???", "FSAVE", "FSTSW", /* 28 */ +"FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 30 */ +"FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */ }; -static const char *szFlops0E[] = +/* The following opcodes are for mod == 3 */ +static char *szFlops2[] = { - "F2XM1", "FYL2X", "FPTAN", "FPATAN","FXTRACT","FPREM1","FDECSTP","FINCSTP" +/* 0 1 2 3 4 5 6 7 */ +"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */ +"FLD", "FXCH", "FNOP", "???", "", "", "", "", /* 08 */ +"FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "", "FIDIV", "FIDIVR", /* 10 */ +"FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */ +"FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */ +"FFREE", "FSTP", "FST", "???", "FUCOM", "FUCOMP","???", "???", /* 28 */ +"FADDP", "FMULP", "FICOM","", "FSUBRP","FISUBR","FDIVRP","FDIVP", /* 30 */ +"FILD", "???", "FIST", "FISTP", "", "???", "FBSTP", "FISTP" /* 38 */ }; -static const char *szFlops0F[] = +static char *szFlops0C[] = { - "FPREM", "FYLXP1","FSQRT", "FSINCOS","FRNDINT","FSCALE","FSIN","FCOS" +"FCHS", "FABS", "???", "???", "FTST", "FXAM", "???", "???" }; -static const char *szFlops15[] = +static char *szFlops0D[] = { - "???", "FUCOMPP", "???", "???", "???", "???", "???", "???" +"FLD1", "FLDL2T","FLDL2E","FLDP1", "FLDLG2","FLDLN2","FLDZ", "???" }; -static const char *szFlops1C[] = +static char *szFlops0E[] = { - "???", "???", "FCLEX", "FINIT", "FTST", "FXAM", "???", "???" +"F2XM1", "FYL2X", "FPTAN", "FPATAN","FXTRACT","FPREM1","FDECSTP","FINCSTP" }; -static const char *szFlops33[] = +static char *szFlops0F[] = { - "???", "FCOMPP", "???", "???", "???", "???", "???", "???" +"FPREM", "FYLXP1","FSQRT", "FSINCOS","FRNDINT","FSCALE","FSIN","FCOS" }; -static const char *szFlops3C[] = +static char *szFlops15[] = { - "FSTSWAX","???", "???", "???", "???", "???", "???", "???" +"???", "FUCOMPP", "???", "???", "???", "???", "???", "???" +}; + +static char *szFlops1C[] = +{ +"???", "???", "FCLEX", "FINIT", "FTST", "FXAM", "???", "???" +}; + +static char *szFlops33[] = +{ +"???", "FCOMPP", "???", "???", "???", "???", "???", "???" +}; + +static char *szFlops3C[] = +{ +"FSTSWAX","???", "???", "???", "???", "???", "???", "???" }; -static const char *szPtr[2] = { "word ptr ", "byte ptr " }; +static char *szIndex[8] = {"bx+si", "bx+di", "bp+si", "bp+di", "si", "di","bp","bx" }; +static char *szBreg[8] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }; +static char *szWreg[12] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "es", "cs", "ss", "ds" }; +static char *szPtr[2] = { " word ptr ", " byte ptr " }; -static void formatRM(ostringstream &p, uint32_t flg, const LLOperand &pm); -static ostringstream &strDst(ostringstream &os, uint32_t flg, const LLOperand &pm); -static char *strHex(uint32_t d); -//static int checkScanned(uint32_t pcCur); -//static void setProc(Function * proc); -//static void dispData(uint16_t dataSeg); -boolT callArg(uint16_t off, char *temp); /* Check for procedure name */ +static void dis1Line (Int i, boolT fWin, char attr, Int pass); + void dis1LineOp(Int i, boolT fWin, char attr, word *len, PPROC pProc); +static void formatRM(char *p, flags32 flg, PMEM pm); +static char *strDst(flags32 flg, PMEM pm); +static char *strSrc(PICODE pc); +static char *strHex(dword d); +static Int checkScanned(dword pcCur); +static void setProc(PPROC proc); +static void dispData(word dataSeg); +static void flops(PICODE pi); + boolT callArg(word off, char *temp); /* Check for procedure name */ -//static FILE *dis_g_fp; -static CIcodeRec pc; -static int cb, j, numIcode, allocIcode; -static map pl; -static uint32_t nextInst; +static FILE *fp; +static PICODE pc; +static char buf[200], *p; +static Int cb, j, numIcode, allocIcode, eop, *pl; +static dword nextInst; static boolT fImpure; -//static int g_lab; -static Function * pProc; /* Points to current proc struct */ +static Int lab, prevPass; +static PPROC pProc; /* Points to current proc struct */ -struct POSSTACK_ENTRY +typedef struct _POSSTACK { - int ic; /* An icode offset */ - Function * pProc; /* A pointer to a PROCEDURE structure */ -} ; -static vector posStack; /* position stack */ -static uint8_t iPS; /* Index into the stack */ + Int ic; /* An icode offset */ + PPROC pProc; /* A pointer to a PROCEDURE structure */ +} POSSTACK; +static POSSTACK *posStack; /* Pointer to the position stack */ +byte iPS; /* Index into the stack */ + +static char cbuf[256]; /* Has to be 256 for wgetstr() to work */ // These are "curses equivalent" functions. (Used to use curses for all this, // but it was too much of a distribution hassle +#if _CONSOLE +HANDLE hConsole; /* All 32 bit console style routines need this handle */ +#endif + +void attrSet(char attrib) +{ +#ifdef _CONSOLE + switch (attrib) + { + case A_NORMAL: + SetConsoleTextAttribute(hConsole, + FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); + break; + case A_REVERSE: + SetConsoleTextAttribute(hConsole, + BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED); + break; + case A_BOLD: + SetConsoleTextAttribute(hConsole, + FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_INTENSITY); + break; + } +#else + /* Set the attribute, using VT100 codes */ + switch (attrib) + { + case A_NORMAL: + printf("\033[0m"); + break; + case A_REVERSE: + printf("\033[7m"); + break; + case A_BOLD: + printf("\033[1m"); + break; + } +#endif +} + +#ifdef _CONSOLE +void initConsole() +{ + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +} +#endif + +void erase(void) +{ +#ifdef _CONSOLE + COORD coordScreen = { 0, 0 }; /* here's where we'll home the + cursor */ + DWORD cCharsWritten; + CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ + DWORD dwConSize; /* number of character cells in + the current buffer */ + + /* get the number of character cells in the current buffer */ + GetConsoleScreenBufferInfo( hConsole, &csbi ); + dwConSize = csbi.dwSize.X * csbi.dwSize.Y; + + /* fill the entire screen with blanks */ + FillConsoleOutputCharacter( hConsole, (TCHAR) ' ', + dwConSize, coordScreen, &cCharsWritten ); + + /* get the current text attribute */ +// GetConsoleScreenBufferInfo( hConsole, &csbi ); + + /* now set the buffer's attributes accordingly */ + FillConsoleOutputAttribute( hConsole, csbi.wAttributes, + dwConSize, coordScreen, &cCharsWritten ); + + /* put the cursor at (0, 0) */ + SetConsoleCursorPosition( hConsole, coordScreen ); + +#else + // Assume that ANSI is supported + printf("\033[2J"); +#endif +} + +void move(int r, int c) +{ +#ifdef _CONSOLE + COORD pos; + pos.X = c; + pos.Y = r; + SetConsoleCursorPosition( hConsole, pos ); +#else + printf("\033[%d;%dH", r+1, c+1); +#endif +} + #define printfd(x) printf(x) #define dis_newline() printf("\n") #define dis_show() // Nothing to do unless using Curses -void LLInst::findJumpTargets(CIcodeRec &_pc) -{ - if (testFlags(I) && ! testFlags(JMP_ICODE) && isJmpInst()) - { - /* Replace the immediate operand with an icode index */ - iICODE labTgt=_pc.labelSrch(src().getImm2()); - if (labTgt!=_pc.end()) - { - m_src.SetImmediateOp(labTgt->loc_ip); - /* This icode is the target of a jump */ - labTgt->ll()->setFlags(TARGET); - setFlags(JMP_ICODE); /* So its not done twice */ - } - else - { - /* This jump cannot be linked to a label */ - setFlags(NO_LABEL); - } - } - -} /***************************************************************************** * disassem - Prints a disassembled listing of a procedure. * pass == 1 generates output on file .a1 * pass == 2 generates output on file .a2 * pass == 3 generates output on file .b ****************************************************************************/ - -void Disassembler::disassem(Function * ppProc) +void disassem(Int pass, PPROC ppProc) { - + Int i; pProc = ppProc; /* Save the passes pProc */ + if (pass != prevPass) + { + prevPass = pass; + lab = 0; /* Restart label numbers */ + } createSymTables(); - allocIcode = numIcode = pProc->Icode.size(); - cb = allocIcode * sizeof(ICODE); - if (numIcode == 0) + allocIcode = numIcode = pProc->Icode.GetNumIcodes(); + if ((cb = allocIcode * sizeof(ICODE)) == 0) { return; /* No Icode */ } @@ -149,401 +291,441 @@ void Disassembler::disassem(Function * ppProc) /* Open the output file (.a1 or .a2 only) */ if (pass != 3) { - auto p = (pass == 1)? asm1_name: asm2_name; - m_fp.open(p,ios_base::app); - if (!m_fp.is_open()) + p = (pass == 1)? asm1_name: asm2_name; + fp = fopen(p, "a+"); + if (!fp) { fatalError(CANNOT_OPEN, p); } } + /* Create temporary code array */ // Mike: needs objectising! - pc=pProc->Icode; + pc = (PICODE)memcpy(allocMem(cb), pProc->Icode.GetFirstIcode(), (size_t)cb); if (pass == 1) { /* Bind jump offsets to labels */ - //for (i = 0; i < numIcode; i++) - for( ICODE &icode : pc) + for (i = 0; i < numIcode; i++) { - LLInst *ll=icode.ll(); - ll->findJumpTargets(pc); + if ((pc[i].ic.ll.flg & I) && !(pc[i].ic.ll.flg & JMP_ICODE) && + JmpInst(pc[i].ic.ll.opcode)) + { + /* Replace the immediate operand with an icode index */ + if (labelSrch(pc, numIcode, pc[i].ic.ll.immed.op, + (Int *)&pc[i].ic.ll.immed.op)) + { + /* This icode is the target of a jump */ + pc[pc[i].ic.ll.immed.op].ic.ll.flg |= TARGET; + pc[i].ic.ll.flg |= JMP_ICODE; /* So its not done twice */ + } + else + { + /* This jump cannot be linked to a label */ + pc[i].ic.ll.flg |= NO_LABEL; + } + } } } /* Create label array to keep track of location => label name */ - pl.clear(); + pl = (Int*)memset(allocMem(numIcode * sizeof(Int)), 0, + (size_t)(numIcode * sizeof(Int))); /* Write procedure header */ if (pass != 3) - { - std::string near_far=(pProc->flg & PROC_FAR)? "FAR": "NEAR"; - m_fp << "\t\t"<name<<" PROC "<< near_far<<"\n"; - } + fprintf(fp, "\t\t%s PROC %s\n", pProc->name, + (pProc->flg & PROC_FAR)? "FAR": "NEAR"); /* Loop over array printing each record */ - nextInst = 0; - for( ICODE &icode : pc) + for (i = nextInst = 0; i < numIcode; i++) { - this->dis1Line(*icode.ll(),icode.loc_ip,pass); + dis1Line(i, FALSE, 0, pass); } /* Write procedure epilogue */ if (pass != 3) { - m_fp << "\n\t\t"<name<<" ENDP\n\n"; - m_fp.close(); + fprintf(fp, "\n\t\t%s ENDP\n\n", pProc->name); + fclose(fp); } - pc.clear(); + free(pc); + free(pl); destroySymTables(); } + /**************************************************************************** - * dis1Line() - disassemble one line to stream fp * + * dis1Line() - disassemble one line to stream fp * * * i is index into Icode for this proc * * It is assumed that icode i is already scanned * ****************************************************************************/ -void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass) +static void +dis1Line(Int i, boolT fWindow, char attr, Int pass) { - PROG &prog(Project::get()->prog); - ostringstream oper_stream; - ostringstream hex_bytes; - ostringstream result_stream; - ostringstream opcode_with_mods; - ostringstream operands_s; - oper_stream << uppercase; - hex_bytes << uppercase; + PICODE pIcode = &pc[i]; + /* Disassembly stage 1 -- - * Do not try to display NO_CODE entries or synthetic instructions, - * other than JMPs, that have been introduced for def/use analysis. */ + * Do not try to display NO_CODE entries or synthetic instructions, + * other than JMPs, that have been introduced for def/use analysis. */ if ((option.asm1) && - ( inst.testFlags(NO_CODE) || - (inst.testFlags(SYNTHETIC) && (inst.getOpcode() != iJMP)))) + ((pIcode->ic.ll.flg & NO_CODE) || + ((pIcode->ic.ll.flg & SYNTHETIC) && (pIcode->ic.ll.opcode != iJMP)))) { return; } - else if (inst.testFlags(NO_CODE)) + else if (pIcode->ic.ll.flg & NO_CODE) { return; } - if (inst.testFlags(TARGET | CASE)) + + /* p points to the current position in buf[] */ + p = (char*)memset(buf, ' ', sizeof(buf)); + + if (pIcode->ic.ll.flg & (TARGET | CASE)) { - if (pass == 3) - cCode.appendCode("\n"); /* Print to c code buffer */ + if (fWindow) /* Printing to disassem window? */ + dis_newline(); /* Yes */ + else if (pass == 3) + appendStrTab (&cCode.code, "\n"); /* No, print to c code buffer */ else - m_fp<< "\n"; /* No, print to the stream */ + fprintf(fp, "\n"); /* No, print to the stream */ } /* Find next instruction label and print hex bytes */ - if (inst.testFlags(SYNTHETIC)) - nextInst = inst.label; + if (pIcode->ic.ll.flg & SYNTHETIC) + nextInst = pIcode->ic.ll.label; else { - cb = (uint32_t) inst.numBytes; - nextInst = inst.label + cb; + cb = (dword) pIcode->ic.ll.numBytes; + nextInst = pIcode->ic.ll.label + cb; /* Output hexa code in program image */ if (pass != 3) { - for (j = 0; j < cb; j++) - { - hex_bytes << hex << setw(2) << setfill('0') << uint16_t(prog.Image[inst.label + j]); - } - hex_bytes << ' '; + for (j = 0; j < cb; j++, p += 2) + sprintf(p, "%02X", prog.Image[pIcode->ic.ll.label + j]); + *p = ' '; } } - oper_stream << setw(POS_LAB) << left<< hex_bytes.str(); + /* Check if there is a symbol here */ selectTable(Label); - oper_stream << setw(5)<ic.ll.label, 0)) { - ostringstream lab_contents; - if (readVal(lab_contents, inst.label, 0)) - { - lab_contents << ':'; /* Also removes the null */ - } - else if (inst.testFlags(TARGET)) /* Symbols override Lnn labels */ - { - /* Print label */ - if (pl.count(loc_ip)==0) - { - pl[loc_ip] = ++g_lab; - } - lab_contents<< "L"<ll()->label, 0)) - { - break; /* Symbolic label. Done */ - } - } - - if (inst.testFlags(NO_LABEL)) - { - //strcpy(p + WID_PTR, strHex(pIcode->ll()->immed.op)); - operands_s<name; - } - else if (inst.getOpcode() == iCALLF) - { - operands_s<<"dword ptr "; - inst.strSrc(operands_s,true); - } - else - strDst(operands_s,I, inst.src()); - break; - - case iENTER: - operands_s<ic.ll.flg & TARGET) /* Symbols override Lnn labels */ + { /* Print label */ + if (! pl[i]) { - std::string d1=((inst.testFlags(I))? strHex(inst.src().getImm2()): "dx"); - std::string d2=((inst.getFlag() & B) ? ", al": ", ax"); - operands_s<ic.ll.opcode == iSIGNEX && (pIcode->ic.ll.flg & B)) { - fImpure = false; + pIcode->ic.ll.opcode = iCBW; + } + + if (pass == 3) + { + strcpy (&buf[8], szOps[pIcode->ic.ll.opcode]); + buf[eop = strlen(buf)] = ' '; + p = buf + 8 + (POS_OPR - POS_OPC); } else { - for (j = inst.label, fImpure = 0; j > 0 && j < (int)nextInst; j++) + strcpy(&buf[POS_OPC], szOps[pIcode->ic.ll.opcode]); + buf[eop = strlen(buf)] = ' '; + p = buf + POS_OPR; + } + + switch (pIcode->ic.ll.opcode) + { + case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR: + case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG: + strcpy(p, strDst(pIcode->ic.ll.flg, &pIcode->ic.ll.dst)); + strcat(p, strSrc(pIcode)); + break; + + case iESC: + flops(pIcode); + break; + + case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL: + case iROR: + strcpy(p, strDst(pIcode->ic.ll.flg | I, &pIcode->ic.ll.dst)); + strcat(p, (pIcode->ic.ll.flg & I)? strSrc(pIcode): ", cl"); + break; + + case iINC: case iDEC: case iNEG: case iNOT: case iPOP: + strcpy(p, strDst(pIcode->ic.ll.flg | I, &pIcode->ic.ll.dst)); + break; + + case iPUSH: + if (pIcode->ic.ll.flg & I) + { + strcpy(p + WID_PTR, strHex(pIcode->ic.ll.immed.op)); + } + else + { + strcpy(p, strDst(pIcode->ic.ll.flg | I, &pIcode->ic.ll.dst)); + } + break; + + case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD: + if (pIcode->ic.ll.flg & I) + { + strcat(strcpy(p, strDst(pIcode->ic.ll.flg, &pIcode->ic.ll.dst)), + ", "); + formatRM(p + strlen(p), pIcode->ic.ll.flg, &pIcode->ic.ll.src); + strcat(p, strSrc(pIcode)); + } + else + strcpy(p, strDst(pIcode->ic.ll.flg | I, &pIcode->ic.ll.src)); + break; + + case iLDS: case iLES: case iBOUND: + strcpy(p, strDst(pIcode->ic.ll.flg, &pIcode->ic.ll.dst)); + strcat(strcat(p, ", dword ptr"), strSrc(pIcode)+1); + break; + + 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:case iLOOP: case iLOOPE:case iLOOPNE: + case iJMP: case iJMPF: + + /* Check if there is a symbol here */ + selectTable(Label); + if ((pIcode->ic.ll.immed.op < (dword)numIcode) && /* Ensure in range */ + readVal(p+WID_PTR, pc[pIcode->ic.ll.immed.op].ic.ll.label, 0)) + { + break; /* Symbolic label. Done */ + } + + if (pIcode->ic.ll.flg & NO_LABEL) + { + strcpy(p + WID_PTR, strHex(pIcode->ic.ll.immed.op)); + } + else if (pIcode->ic.ll.flg & I) + { + j = pIcode->ic.ll.immed.op; + if (! pl[j]) /* Forward jump */ + { + pl[j] = ++lab; + } + if (pIcode->ic.ll.opcode == iJMPF) + { + sprintf(p, " far ptr L%ld", pl[j]); + } + else + { + sprintf(p + WID_PTR, "L%ld", pl[j]); + } + } + else if (pIcode->ic.ll.opcode == iJMPF) + { + strcat(strcpy(p-1, "dword ptr"), strSrc(pIcode)+1); + } + else + { + strcpy(p, strDst(I, &pIcode->ic.ll.src)); + } + break; + + case iCALL: case iCALLF: + if (pIcode->ic.ll.flg & I) + { + sprintf(p, "%s ptr %s", + (pIcode->ic.ll.opcode == iCALL) ?" near":" far", + (pIcode->ic.ll.immed.proc.proc)->name); + } + else if (pIcode->ic.ll.opcode == iCALLF) + { + strcat(strcpy(p, "dword ptr"),strSrc(pIcode)+1); + } + else + { + strcpy(p, strDst(I, &pIcode->ic.ll.src)); + } + break; + + case iENTER: + strcat(strcpy(p + WID_PTR, strHex(pIcode->ic.ll.dst.off)), ", "); + strcat(p, strHex(pIcode->ic.ll.immed.op)); + break; + + case iRET: case iRETF: case iINT: + if (pIcode->ic.ll.flg & I) + { + strcpy(p + WID_PTR, strHex(pIcode->ic.ll.immed.op)); + } + else + { + buf[eop] = '\0'; + } + break; + + case iCMPS: case iREPNE_CMPS: case iREPE_CMPS: + case iSCAS: case iREPNE_SCAS: case iREPE_SCAS: + case iSTOS: case iREP_STOS: + case iLODS: case iREP_LODS: + case iMOVS: case iREP_MOVS: + case iINS: case iREP_INS: + case iOUTS: case iREP_OUTS: + if (pIcode->ic.ll.src.segOver) + { + (pIcode->ic.ll.opcode == iOUTS || pIcode->ic.ll.opcode == iREP_OUTS) + ? strcat(strcpy(p+WID_PTR,"dx, "), szPtr[pIcode->ic.ll.flg & B]) + : strcpy(&buf[eop+1], szPtr[pIcode->ic.ll.flg & B]); + if (pIcode->ic.ll.opcode == iLODS || + pIcode->ic.ll.opcode == iREP_LODS || + pIcode->ic.ll.opcode == iOUTS || + pIcode->ic.ll.opcode == iREP_OUTS) + { + strcat(p, szWreg[pIcode->ic.ll.src.segOver-rAX]); + } + else + { + strcat(strcat(p, "es:[di], "), + szWreg[pIcode->ic.ll.src.segOver - rAX]); + } + strcat(p, ":[si]"); + } + else strcpy(&buf[eop], (pIcode->ic.ll.flg & B)? "B": "W"); + break; + + case iXLAT: + if (pIcode->ic.ll.src.segOver) + { + strcpy(&buf[eop+1], szPtr[1]); + strcat(strcat(p, szWreg[pIcode->ic.ll.src.segOver-rAX]), ":[bx]"); + } + else buf[eop] = '\0'; + break; + + case iIN: + strcpy(p+WID_PTR, (pIcode->ic.ll.flg & B)?"al, ": "ax, "); + strcat(p+WID_PTR, (pIcode->ic.ll.flg & I)? strHex(pIcode->ic.ll.immed.op): "dx"); + break; + + case iOUT: + strcpy(p+WID_PTR, (pIcode->ic.ll.flg & I)? strHex(pIcode->ic.ll.immed.op): "dx"); + strcat(p+WID_PTR, (pIcode->ic.ll.flg & B)?", al": ", ax"); + break; + + default: + buf[eop] = '\0'; + break; + } + + /* Comments */ + if (pIcode->ic.ll.flg & SYNTHETIC) + { + fImpure = FALSE; + } + else + { + for (j = pIcode->ic.ll.label, fImpure = 0; j > 0 && j < (Int)nextInst; + j++) { fImpure |= BITMAP(j, BM_DATA); } } - result_stream << setw(54) << left << oper_stream.str(); + /* Check for user supplied comment */ selectTable(Comment); - ostringstream cbuf; - if (readVal(cbuf, inst.label, 0)) + if (readVal(cbuf, pIcode->ic.ll.label, 0)) { - result_stream <<"; "<ic.ll.flg & (SWITCH | CASE | SEG_IMMED | + IMPURE | SYNTHETIC | TERMINATES))) { - if (inst.testFlags(CASE)) + buf[strlen(buf)] = ' '; + buf[POS_CMT] = '\0'; + if (pIcode->ic.ll.flg & CASE) { - result_stream << ";Case l"<< inst.caseEntry; + sprintf(buf+POS_CMT, ";Case l%ld", pIcode->ic.ll.caseTbl.numEntries); } - if (inst.testFlags(SWITCH)) + if (pIcode->ic.ll.flg & SWITCH) { - result_stream << ";Switch "; + strcat(buf, ";Switch "); } if (fImpure) { - result_stream << ";Accessed as data "; + strcat(buf, ";Accessed as data "); } - if (inst.testFlags(IMPURE)) + if (pIcode->ic.ll.flg & IMPURE) { - result_stream << ";Impure operand "; + strcat(buf, ";Impure operand "); } - if (inst.testFlags(SEG_IMMED)) + if (pIcode->ic.ll.flg & SEG_IMMED) { - result_stream << ";Segment constant"; + strcat(buf, ";Segment constant"); } - if (inst.testFlags(TERMINATES)) + if (pIcode->ic.ll.flg & TERMINATES) { - result_stream << ";Exit to DOS"; + strcat(buf, ";Exit to DOS"); } } /* Comment on iINT icodes */ - if (inst.getOpcode() == iINT) - inst.writeIntComment(result_stream); + if (pIcode->ic.ll.opcode == iINT) + writeIntComment (pIcode, buf); /* Display output line */ - if(pass==3) + if (! (pIcode->ic.ll.flg & SYNTHETIC)) { - /* output to .b code buffer */ - if (inst.testFlags(SYNTHETIC)) - result_stream<<";Synthetic inst"; - if (pass == 3) /* output to .b code buffer */ - cCode.appendCode("%s\n", result_stream.str().c_str()); + if (fWindow) + { + word off; + char szOffset[6]; + off = (word)(pIcode->ic.ll.label - ((dword)pProc->state.r[rCS] << 4)); + attrSet(attr); + + sprintf(szOffset, "%04X ", off); + printfd(szOffset); + printfd(buf); + dis_newline(); + attrSet(A_NORMAL); + } + else if (pass == 3) /* output to .b code buffer */ + appendStrTab (&cCode.code, "%s\n", buf); + else /* output to .a1 or .a2 file */ + fprintf (fp, "%03ld %06lX %s\n", i, pIcode->ic.ll.label, buf); } - else + else /* SYNTHETIC instruction */ { - char buf[12]; - /* output to .a1 or .a2 file */ - if (not inst.testFlags(SYNTHETIC) ) + strcat (buf, ";Synthetic inst"); + if (fWindow) { - sprintf(buf,"%03d %06X",loc_ip, inst.label); + printfd(" "); + printfd(buf); + dis_newline(); } - else /* SYNTHETIC instruction */ + else if (pass == 3) /* output to .b code buffer */ { - sprintf(buf,"%03d ",loc_ip); - result_stream<<";Synthetic inst"; + appendStrTab (&cCode.code, "%s\n", buf); + } + else /* output to .a1 or .a2 file */ + { + fprintf (fp, "%03ld %s\n", i, buf); } - m_fp<segOver) { - p <segOver - rAX]), ":"); + } + else *seg = '\0'; + + if (pm->regi == 0) + { + sprintf(p,"%s[%s]", seg, strHex((dword)pm->off)); } - if (pm.regi == rUNDEF) + else if (pm->regi == (INDEXBASE - 1)) { - p<<"["<regi < INDEXBASE) { - if (pm.off < 0) + strcpy(p, (flg & B)? szBreg[pm->regi - rAL]: szWreg[pm->regi - rAX]); + } + + else if (pm->off) + { + if (pm->off < 0) { - p <<"["<regi - INDEXBASE], + strHex((dword)(- pm->off))); } else { - p <<"["<regi - INDEXBASE], + strHex((dword)pm->off)); } } - else - p <<"["<regi - INDEXBASE]); } /***************************************************************************** * strDst ****************************************************************************/ -static ostringstream & strDst(ostringstream &os,uint32_t flg, const LLOperand &pm) +static char *strDst(flags32 flg, PMEM pm) { + static char buf[30]; + /* Immediates to memory require size descriptor */ - //os << setw(WID_PTR); - if ((flg & I) and not pm.isReg()) - os << szPtr[flg & B]; - formatRM(os, flg, pm); - return os; + if ((flg & I) && (pm->regi == 0 || pm->regi >= INDEXBASE)) + { + memcpy(buf, szPtr[flg & B], WID_PTR); + } + else + { + memset(buf, ' ', WID_PTR); + } + + formatRM(buf + WID_PTR, flg, pm); + return buf; } /**************************************************************************** * strSrc * ****************************************************************************/ -ostringstream &LLInst::strSrc(ostringstream &os,bool skip_comma) +static char *strSrc(PICODE pc) { - if(false==skip_comma) - os<<", "; - if (testFlags(I)) - os<ic.ll.flg & I) + strcpy(buf + 2, strHex(pc->ic.ll.immed.op)); + else if (pc->ic.ll.flg & IM_SRC) /* level 2 */ + strcpy (buf + 2, "dx:ax"); else - formatRM(os, getFlag(), src()); + formatRM(buf + 2, pc->ic.ll.flg, &pc->ic.ll.src); - return os; + return buf; } - /**************************************************************************** * strHex * ****************************************************************************/ -static char *strHex(uint32_t d) +static char *strHex(dword d) { static char buf[10]; @@ -631,107 +828,817 @@ static char *strHex(uint32_t d) return (buf + (buf[1] <= '9')); } + + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ + +< Interactive Disassembler and Associated Routines > + + \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + + +dword pcTop; /* Image offset of top line */ +Int icTop; /* Icode index of top line */ +dword pcCur; /* Image offset of cursor */ +dword oldPcCur; /* As above, before latest command */ +Int icCur; /* Icode index of cursor */ +dword pcBot; /* Image offset of bottom line */ +Int icBot; /* Icode index of bottom line */ +dword pcLast; /* Image offset of last instr in proc */ +int NSCROLL; /* Number of limes to scroll. Pseudo constant */ + +/* Paint the title line */ +void dispTitle(void) +{ + char buf[80]; + + move(0, 0); /* Must move before setting attributes */ + attrSet(A_BOLD); + sprintf(buf, "Proc %s at %06lX (%04X:%04X): %d bytes of parameters ", + pProc->name, pProc->Icode.GetFirstIcode()->ic.ll.label, + pProc->state.r[rCS], + (word)(pProc->Icode.GetFirstIcode()->ic.ll.label - ((dword)(pProc->state.r[rCS]) << 4)), + pProc->cbParam); + printfd(buf); + if (pProc->flg & PROC_ISLIB) printfd(" LIBRARY"); + attrSet(A_NORMAL); +} + + +/**************************************************************************** +* updateScr - update the screen * + ****************************************************************************/ +/* bNew is true if must recalculate the top line */ +void +updateScr(boolT bNew) +{ + int y, x; + Int i, ic; + + bNew |= (pcCur > pcBot) || (pcCur < pcTop); + if (bNew) + { + /* We need to redo the screen completely */ + erase(); + dispTitle(); + icTop = icCur; + for (x=0; x < NSCROLL; x++) + { + if (icTop && pc[icTop-1].ic.ll.label + + (dword)pc[icTop-1].ic.ll.numBytes == pc[icTop].ic.ll.label) + { + /* Then this instruction is contiguous with the current */ + icTop--; + } + else break; + } + pcTop = pc[icTop].ic.ll.label; + } + else + { + dispTitle(); + } + + move(1, 0); + nextInst = pcTop; + for (y=1, ic=icTop; y < LINES-1; ic++, y++) + { + if ((ic >= numIcode) || (nextInst != pc[ic].ic.ll.label)) + { + if (labelSrch(pc, numIcode, nextInst, &i)) + { + ic = i; + } + else + { + pcLast = pc[ic-1].ic.ll.label; /* Remember end of proc */ + break; /* Must be past last */ + } + } + + /* Save pc of current line. Last assignment will be pc of bott line */ + pcBot = nextInst; + icBot = ic; + + // Only have to repaint if screen is new, or repainting formerly highlighted + // line, or newly highlighted line + if (bNew || (pcCur == nextInst) || (oldPcCur == nextInst)) + dis1Line(ic, TRUE, (char)((pcCur == nextInst) ? A_REVERSE : A_NORMAL), 0); + + if (ic == numIcode-1) + { + switch (pc[ic].ic.ll.opcode) + { + case iJMP: case iJMPF: + case iRET: case iRETF: + case iIRET: + break; + + default: + /* We have other than a break of control flow instruction + at the end of the proc. Parse more instructions to + complete the basic block + */ + if ((ic = checkScanned(nextInst)) == -1) + { + /* Some error. */ + pcLast = pcCur; /* Remember end of proc */ + break; /* Must be past last */ + } + + } + } + } + dis_show(); /* Make it happen */ +} + +#if 0 +/* An opcode based version of updateScr() */ +/**************************************************************************** +* updateScrOp - update the screen * + ****************************************************************************/ +/* bNew is true if must recalculate the top line */ +void +updateScrOp(boolT bNew) +{ + int y, x; + dword pc; + word len; + + dispTitle(); + if (bNew || (pcCur > pcBot) || (pcCur < pcTop)) + { + /* We need to redo the screen completely */ + pcTop = pcCur; + } + + move(1, 0); + for (y=1, pc = pcTop; y < LINES-1;) + { + /* Save pc of current line. Last assignment will be pc of bott line */ + pcBot = pc; + + dis1LineOp(pc, TRUE, (pcCur == pc) ? A_REVERSE : A_NORMAL, &len, + pProc); + pc += len; + getyx(stdscr, y, x); + } + + refresh(); +} + +#endif + +void pushPosStack(void) +{ + /* Push the current position on the position stack */ + posStack[iPS].ic = icCur; + posStack[iPS++].pProc = pProc; +} + +void popPosStack(void) +{ + /* Push the current position on the position stack */ + /* Note: relies on the byte wraparound. Beware! */ + if ((intptr_t)(posStack[--iPS].pProc) != -1) + { + if (posStack[iPS].pProc != pProc) + { + setProc(posStack[iPS].pProc); + } + icCur = posStack[iPS].ic; + pcCur = pc[icCur].ic.ll.label; + } + else iPS++; /* Stack empty.. don't pop */ +} + + +/* Check to see if there is an icode for given image offset. + Scan it if necessary, adjusting the allocation of pc[] and pl[] + if necessary. Returns -1 if an error, otherwise the icode offset +*/ +static Int +checkScanned(dword pcCur) +{ + Int i; + + /* First we check if the current icode is in range */ + /* A sanity check first */ + if (pcCur >= (dword)prog.cbImage) + { + /* Couldn't be! */ + return -1; + } + + if (!labelSrch(pc, numIcode, pcCur, &i)) + { + /* This icode does not exist yet. Tack it on the end of the existing */ + if (numIcode >= allocIcode) + { + allocIcode = numIcode + DELTA_ICODE; /* Make space for this one, and a few more */ + pc = (PICODE)reallocVar(pc, allocIcode * sizeof(ICODE)); + /* It is important to clear the new icodes, to ensure that the type + is set to NOT_SCANNED */ + memset(&pc[numIcode], 0, (size_t)(allocIcode-numIcode)*sizeof(ICODE)); + pl = (Int*)reallocVar(pl, allocIcode * sizeof(Int)); + memset(&pl[numIcode], 0, (size_t)(allocIcode-numIcode)*sizeof(Int)); + } + i = numIcode++; + } + + if (pc[i].type == NOT_SCANNED) + { + /* This is a new icode not even scanned yet. Scan it now */ + /* Ignore most errors... at this stage */ + if (scan(pcCur, &pc[i]) == IP_OUT_OF_RANGE) + { + /* Something went wrong... just forget it */ + return -1; + } + } + + return i; +} + + + + + +/* Set up to use the procedure proc */ +/* This includes some important initialisations, allocations, etc that are + normally done in disassem() */ +static void +setProc(PPROC proc) +{ + Int i; + + pProc = proc; /* Keep in a static */ + + /* Free old arrays, if any */ + if (pc) free(pc); + if (pl) free(pl); + + + /* Create temporary code array */ + numIcode = pProc->Icode.GetNumIcodes(); + cb = numIcode * sizeof(ICODE); + // Mike: needs objectising + pc = (PICODE)memcpy(allocMem(cb), pProc->Icode.GetFirstIcode(), (size_t)cb); + + /* Create label array to keep track of location => label name */ + pl = (Int*)memset(allocMem(numIcode * sizeof(Int)), 0, + (size_t)(numIcode * sizeof(Int))); + + /* Bind jump offsets to labels */ + for (i = 0; i < numIcode; i++) + { + if ((pc[i].ic.ll.flg & I) && !(pc[i].ic.ll.flg & JMP_ICODE) && + JmpInst(pc[i].ic.ll.opcode)) + { + /* Immediate jump instructions. Make dest an icode index */ + if (labelSrch(pc, numIcode, pc[i].ic.ll.immed.op, + (Int *)&pc[i].ic.ll.immed.op)) + { + /* This icode is the target of a jump */ + pc[pc[i].ic.ll.immed.op].ic.ll.flg |= TARGET; + pc[i].ic.ll.flg |= JMP_ICODE; /* So its not done twice */ + } + else + { + /* This jump cannot be linked to a label */ + pc[i].ic.ll.flg |= NO_LABEL; + } + } + } + + /* Window initially scrolled with entry point on top */ + pcCur = pcTop = pProc->procEntry; + labelSrch(pc, numIcode, pcCur, &icCur); + /* pcLast is set properly in updateScr(), at least for now */ + pcLast = (dword)-1; + +} + /**************************************************************************** * interactDis - interactive disassembler * ****************************************************************************/ -void interactDis(Function * initProc, int initIC) +void interactDis(PPROC initProc, Int initIC) { + + +#ifdef __UNIX__ printf("Sorry - interactive disasassembler option not available for Unix\n"); return; +#else + boolT fInteract; + int nEsc = 0; /* This cycles 0 1 2 for Esc [ X under Unix */ + /* and 0 1 for NULL X under Dos */ + int ch; + Int i; + pProc = initProc; /* Keep copy of init proc */ + NSCROLL = max(3, LINES >> 3); /* Number of lines to scroll */ + + /* Allocate the position stack */ + posStack = (POSSTACK*)allocMem(256 * sizeof(POSSTACK)); + iPS = 0; + memset(posStack, -1, 256 * sizeof(POSSTACK)); + + + /* Initialise the console interface, if required */ + initConsole(); + + /* Initially, work on the given proc */ + setProc(initProc); + if (initIC) + { + icCur = initIC; + pcCur = pc[icCur].ic.ll.label; + } + + /* Initialise the symbol table */ + createSymTables(); + + strcpy(cbuf, "label"); /* Provide a default label string */ + + updateScr(TRUE); + + fInteract = TRUE; + while (fInteract) + { + ch = ::_getch(); // Mike: need a Unix equivalent of getch()! +#ifdef __MSDOS__ + if (nEsc) + { + ch += EXT; /* Got the NULL before, so this is extended */ + nEsc = 0; + } + else if (ch == 0) + { + nEsc = 1; /* Got one escape (actually, NULL) char */ + break; + } +#endif +#ifdef __UNIX__ + switch (nEsc) + { + case 1: /* Already got one escape */ + if (ch == '[') + { + nEsc++; /* Got 2 chars in the escape sequence */ + break; + } + else + { + /* Escape something else. Ignore */ + nEsc = 0; + } + break; + case 2: + /* Already got Esc [ ... */ + ch += EXT; /* Make it an extended key */ + nEsc = 0; /* Reset the escape state */ + break; + case 0: + /* No escapes... yet */ + if (ch == 0x1B) + { + nEsc++; /* That's one escape... */ + break; + } + } +#endif + +// For consoles, we get a 0xE0 then KEY_DOWN for the normal down arrow character. +// We simply ignore the 0xE0; this has the effect that the numeric keypad keys +// work as well (regardless of numlock state). + oldPcCur = pcCur; + switch (ch) + { + case KEY_DOWN: + + if (pcCur >= pcLast) continue; /* Ignore it */ + pcCur += pc[icCur].ic.ll.numBytes; + labelSrch(pc, numIcode, pcCur, &icCur); + if (pcCur >= pcBot) + { + int j; + + /* We have gone past the bottom line. Scroll a few lines */ + for (j=0; j < NSCROLL; j++) + { + if (pcTop >= pcLast) + { + break; + } + pcTop += pc[icTop].ic.ll.numBytes; + if (labelSrch(pc, numIcode, pcTop, &i)) + icTop = i; + else break; /* Some problem... no more scroll */ + } + } + updateScr(FALSE); + break; + + case KEY_UP: + /* First simply try the prev icode */ + if ((icCur == 0) || + pc[--icCur].ic.ll.label + (dword)pc[icCur].ic.ll.numBytes != pcCur) + { + for (i = 0; i < numIcode; i++) + { + if (pc[i].ic.ll.label + (dword)pc[i].ic.ll.numBytes == pcCur) + { + break; /* This is the one! */ + } + } + if (pc[i].ic.ll.label + pc[i].ic.ll.numBytes != pcCur) + break; /* Not found. Sorry! */ + icCur = i; + } + pcCur = pc[icCur].ic.ll.label; + updateScr(FALSE); + break; + + + case '2': /* Think up a better key... */ + /* As for right arrow, but considers source operand first */ + if (pc[icCur].ic.ll.src.off != 0) + { + pushPosStack(); + pcCur = pc[icCur].ic.ll.src.off; + if (!labelSrch(pc, numIcode, pcCur, &icCur)) + break; + updateScr(FALSE); + } + /* Fall through to KEY_RIGHT processing */ + + case KEY_RIGHT: + if (pc[icCur].ic.ll.flg & I) + { + if ((pc[icCur].ic.ll.opcode >= iJB) && + (pc[icCur].ic.ll.opcode <= iJMPF)) + { + /* An immediate jump op. Jump to it */ + pushPosStack(); + if (pc[icCur].ic.ll.flg & JMP_ICODE) + { + /* immed.op is an icode offset */ + icCur = pc[icCur].ic.ll.immed.op; + pcCur = pc[icCur].ic.ll.label; + } + else + { + /* immed.op is still an image offset. + Quite likely we need to scan */ + pcCur = pc[icCur].ic.ll.immed.op; + if ((icCur = checkScanned(pcCur)) == -1) + break; + } + } + else if ((pc[icCur].ic.ll.opcode == iCALL) || + (pc[icCur].ic.ll.opcode == iCALLF)) + { + /* The dest is a pointer to a proc struct */ + // First check that the procedure has icodes (e.g. may be + // a library function, or just not disassembled yet) + PPROC pp = (PPROC)pc[icCur].ic.ll.immed.op; + if (pp->Icode.GetFirstIcode() != NULL) + { + pushPosStack(); + setProc(pp); + } + } + else + { + /* Other immediate */ + pushPosStack(); + pcCur = pc[icCur].ic.ll.immed.op; + dispData(pProc->state.r[rDS]); + break; + } + } + else if (pc[icCur].ic.ll.dst.off != 0) + { + pushPosStack(); + pcCur = pc[icCur].ic.ll.dst.off; + if (!labelSrch(pc, numIcode, pcCur, &icCur)) + { + dispData(pProc->state.r[rDS]); + break; + } + } + else if (pc[icCur].ic.ll.src.off != 0) + { + pushPosStack(); + pcCur = pc[icCur].ic.ll.src.off; + if (!labelSrch(pc, numIcode, pcCur, &icCur)) + { + dispData(pProc->state.r[rDS]); + break; + } + } + updateScr(TRUE); + break; + + case KEY_LEFT: + popPosStack(); + pcCur = pc[icCur].ic.ll.label; + updateScr(TRUE); + break; + + + case KEY_NPAGE: + pcCur = pcTop = pcBot; /* Put bottom line at top now */ + icCur = icTop = icBot; + updateScr(FALSE); + break; + + case KEY_PPAGE: + pcTop -= (LINES-2) * 2; /* Average of 2 bytes per inst */ + for (i = 0; i < numIcode; i++) + { + if ((pc[i].ic.ll.label <= pcTop) && + (pc[i].ic.ll.label + (dword)pc[i].ic.ll.numBytes >= pcTop)) + { + break; /* This is the spot! */ + } + } + if (i >= numIcode) + { + /* Something went wrong. Goto to first icode */ + i = 0; + } + icCur = icTop = i; + pcCur = pcTop = pc[i].ic.ll.label; + updateScr(FALSE); + break; + + case 'l': /* Add a symbolic label here */ + { + char *pStr; + + move(LINES, 0); + printf("Enter symbol: "); + gets(cbuf); /* Get a string to buf */ + move (LINES, 0); + printf("%50c", ' '); + + if (strlen(cbuf) >= SYMLEN) + { + /* Name too ling. Truncate */ + cbuf[SYMLEN-1] = '\0'; + } + pStr = addStrTbl(cbuf); /* Add to the string table */ + + selectTable(Label); /* Select the label table */ + /* Add the symbol to both value- and symbol- hashed tables */ + enterSym(pStr, pcCur, pProc, TRUE); + + if (icCur == 0) + { + /* We are at the first icode of a function. + Assume it is the entry point, and rename the function */ + strcpy(pProc->name, cbuf); + } + + updateScr(FALSE); + break; + } + + case ';': + { + char *pStr; + word w; + + if (findVal(pcCur, 0, &w)) + { + readVal(cbuf, pcCur, 0);/* Make it the default string */ + deleteVal(pcCur, 0, FALSE); + } + else + { + cbuf[0] = '\0'; /* Remove prev string */ + } + + /* Enter a comment here, from a window */ + move(LINES, 0); + printf("Enter comment: "); + gets(cbuf); /* Get a string to buf */ + move(LINES, 0); + printf("%50c", ' '); + + pStr = addStrTbl(cbuf); /* Add to the string table */ + + selectTable(Comment); + enterSym(pStr, pcCur, pProc, FALSE);/* Add the symbol */ + + updateScr(FALSE); + break; + } + + + case 'X' & 0x1F: /* Control X; can't use Alt with Unix */ + fInteract = FALSE; /* Exit interactive mode */ + attrSet(A_NORMAL); /* Normal attributes */ + break; + } + } + + free(posStack); + destroySymTables(); +#endif // #ifdef unix +} + + +/**************************************************************************** + * Display the current image position as data * + ****************************************************************************/ +static void +dispData(word dataSeg) +{ + int y, c, i; + Int pc, pcStart; + Int off = (Int)dataSeg << 4; + char szOffset[6], szByte[4]; + + if (pcCur >= (dword)prog.cbImage) + { + /* We're at an invalid address. Use 0x100 instead */ + pcCur = 0; + } + erase(); + dispTitle(); + + pcStart = pc = pcCur; /* pc at start of line */ + for (y=1; y < LINES-1; y++) + { + move (y, 1); + sprintf(szOffset, "%04lX ", pc); + printfd(szOffset); + for (i=0; i < 16; i++) + { + sprintf(szByte, "%02X ", prog.Image[pc++ + off]); + printfd(szByte); + if ((pc + off) > prog.cbImage) break; + } + pc = pcStart; + for (i=0; i < 16; i++) + { + c = prog.Image[pc++ + off]; + if ((c < 0x20) || (c > 0x7E)) + { + c = '.'; + } + szByte[0] = (char)c; + szByte[1] = '\0'; + printfd(szByte); + if ((pc + off) > prog.cbImage) break; + } + dis_newline(); + pcStart = pc; + + if ((pc + off) > prog.cbImage) break; + +/* getyx(stdscr, y, x); */ + } + +} + + +boolT callArg(word off, char *sym) +{ + dword imageOff; + PPROC p, pPrev; + + imageOff = off + ((dword)pProc->state.r[rCS] << 4); + /* Search procedure list for one with appropriate entry point */ + for (p = pProcList; p && p->procEntry != imageOff; p = p->next) + { + pPrev = p; + } + + if (p == 0) + { + /* No existing proc entry */ + LibCheck(p); + if (p->flg & PROC_ISLIB) + { + /* No entry for this proc, but it is a library function. + Create an entry for it */ + p = (PPROC)memset(allocStruc(PROCEDURE), 0, sizeof(PROCEDURE)); + pPrev->next = p; + p->procEntry = imageOff; + } + } + + if (p) + { + /* We have a proc entry for this procedure. Copy the name */ + strcpy(sym, p->name); + return TRUE; + } + + return FALSE; + } /* Handle the floating point opcodes (icode iESC) */ -void LLInst::flops(std::ostringstream &out) +static void flops(PICODE pIcode) { char bf[30]; - uint8_t op = (uint8_t)src().getImm2(); + byte op = (byte)pIcode->ic.ll.immed.op; /* Note that op is set to the escape number, e.g. esc 0x38 is FILD */ - if ( not dst.isReg() ) + if ((pIcode->ic.ll.dst.regi == 0) || (pIcode->ic.ll.dst.regi >= INDEXBASE)) { - /* The mod/rm mod bits are not set to 11 (i.e. register). This is the normal floating point opcode */ - out<ic.ll.flg, &pIcode->ic.ll.dst); + strcpy(p, bf); } else { /* The mod/rm mod bits are set to 11 (i.e. register). Could be specials (0x0C-0x0F, etc), or the st(i) versions of - normal opcodes. Because the opcodes are slightly different for - this case (e.g. op=04 means FSUB if reg != 3, but FSUBR for - reg == 3), a separate table is used (szFlops2). */ - int destRegIdx=dst.regi - rAX; + normal opcodes. Because the opcodes are slightly different for + this case (e.g. op=04 means FSUB if reg != 3, but FSUBR for + reg == 3), a separate table is used (szFlops2). */ switch (op) { case 0x0C: - out << szFlops0C[destRegIdx]; + strcpy(&buf[POS_OPC], szFlops0C[pIcode->ic.ll.dst.regi - rAX]); break; case 0x0D: - out << szFlops0D[destRegIdx]; + strcpy(&buf[POS_OPC], szFlops0D[pIcode->ic.ll.dst.regi - rAX]); break; case 0x0E: - out << szFlops0E[destRegIdx]; + strcpy(&buf[POS_OPC], szFlops0E[pIcode->ic.ll.dst.regi - rAX]); break; case 0x0F: - out << szFlops0F[destRegIdx]; + strcpy(&buf[POS_OPC], szFlops0F[pIcode->ic.ll.dst.regi - rAX]); break; case 0x15: - out << szFlops15[destRegIdx]; + strcpy(&buf[POS_OPC], szFlops15[pIcode->ic.ll.dst.regi - rAX]); break; case 0x1C: - out << szFlops1C[destRegIdx]; + strcpy(&buf[POS_OPC], szFlops1C[pIcode->ic.ll.dst.regi - rAX]); break; case 0x33: - out << szFlops33[destRegIdx]; + strcpy(&buf[POS_OPC], szFlops33[pIcode->ic.ll.dst.regi - rAX]); break; case 0x3C: - out << szFlops3C[destRegIdx]; + strcpy(&buf[POS_OPC], szFlops3C[pIcode->ic.ll.dst.regi - rAX]); break; default: - out << Machine_X86::floatOpName(0x40+op); + strcpy(&buf[POS_OPC], szFlops2[op]); + buf[strlen(buf)] = ' '; if ((op >= 0x20) && (op <= 0x27)) { /* This is the ST(i), ST form. */ - out << "ST("<ic.ll.dst.regi - rAX); } else { /* ST, ST(i) */ - out << "ST,ST("<ic.ll.dst.regi - rAX); } break; diff --git a/src/error.cpp b/src/error.cpp index 061495f..0dda9b1 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -3,47 +3,54 @@ * (C) Cristina Cifuentes ***************************************************************************/ -#include -#include -#include -#include -#include - #include "dcc.h" - static std::map errorMessage = - { - {INVALID_ARG ,"Invalid option -%c\n"}, - {INVALID_OPCODE ,"Invalid instruction %02X at location %06lX\n"}, - {INVALID_386OP ,"Don't understand 80386 instruction %02X at location %06lX\n"}, - {FUNNY_SEGOVR ,"Segment override with no memory operand at location %06lX\n"}, - {FUNNY_REP ,"REP prefix without a string instruction at location %06lX\n"}, - {CANNOT_OPEN ,"Cannot open %s\n"}, - {CANNOT_READ ,"Error while reading %s\n"}, - {MALLOC_FAILED ,"malloc of %ld bytes failed\n"}, - {NEWEXE_FORMAT ,"Don't understand new EXE format\n"}, - {NO_BB ,"Failed to find a BB for jump to %ld in proc %s\n"}, - {INVALID_SYNTHETIC_BB,"Basic Block is a synthetic jump\n"}, - {INVALID_INT_BB ,"Failed to find a BB for interval\n"}, - {IP_OUT_OF_RANGE ,"Instruction at location %06lX goes beyond loaded image\n"}, - {DEF_NOT_FOUND ,"Definition not found for condition code usage at opcode %d\n"}, - {JX_NOT_DEF ,"JX use, definition not supported at opcode #%d\n"}, - {NOT_DEF_USE ,"Def - use not supported. Def op = %d, use op = %d.\n"}, - {REPEAT_FAIL ,"Failed to construct repeat..until() condition.\n"}, - {WHILE_FAIL ,"Failed to construct while() condition.\n"}, - }; +#include +#include +//#ifndef __UNIX__ +#if 1 +#include +#else +#include +#endif + +static 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(eErrorId errId, ...) +void fatalError(Int errId, ...) { va_list args; //#ifdef __UNIX__ /* ultrix */ #if 0 - int errId; + Int errId; va_start(args); - errId = va_arg(args, int); + errId = va_arg(args, Int); #else va_start(args, errId); #endif @@ -52,7 +59,7 @@ void fatalError(eErrorId errId, ...) fprintf(stderr,"Usage: dcc [-a1a2cmpsvVi][-o asmfile] DOS_executable\n"); else { fprintf(stderr, "dcc: "); - vfprintf(stderr, errorMessage[errId].c_str(), args); + vfprintf(stderr, errorMessage[errId - 1], args); } va_end(args); exit((int)errId); @@ -62,18 +69,18 @@ void fatalError(eErrorId errId, ...) /**************************************************************************** reportError: reports the warning/error and continues with the program. ****************************************************************************/ -void reportError(eErrorId errId, ...) +void reportError(Int errId, ...) { va_list args; //#ifdef __UNIX__ /* ultrix */ #if 0 - int errId; + Int errId; va_start(args); - errId = va_arg(args, int); + errId = va_arg(args, Int); #else /* msdos or windows*/ va_start(args, errId); #endif fprintf(stderr, "dcc: "); - vfprintf(stderr, errorMessage[errId].c_str(), args); + vfprintf(stderr, errorMessage[errId - 1], args); va_end(args); } diff --git a/src/fixwild.cpp b/src/fixwild.cpp index ec55151..ab7a477 100644 --- a/src/fixwild.cpp +++ b/src/fixwild.cpp @@ -18,26 +18,29 @@ #ifndef bool #define bool unsigned char -#define uint8_t unsigned char +#define TRUE 1 +#define FALSE 0 +#define byte unsigned char #endif static int pc; /* Indexes into pat[] */ /* prototypes */ -static bool ModRM(uint8_t pat[]); /* Handle the mod/rm uint8_t */ -static bool TwoWild(uint8_t pat[]); /* Make the next 2 bytes wild */ -static bool FourWild(uint8_t pat[]); /* Make the next 4 bytes wild */ - void fixWildCards(uint8_t pat[]); /* Main routine */ +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(uint8_t pat[]) +static bool +ModRM(byte pat[]) { - uint8_t op; + byte op; - /* A standard mod/rm uint8_t follows opcode */ - op = pat[pc++]; /* The mod/rm uint8_t */ - if (pc >= PATLEN) return true; /* Skip Mod/RM */ + /* 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] */ @@ -45,42 +48,42 @@ static bool ModRM(uint8_t pat[]) { /* Uses [nnnn] address mode */ pat[pc++] = WILD; - if (pc >= PATLEN) return true; + if (pc >= PATLEN) return TRUE; pat[pc++] = WILD; - if (pc >= PATLEN) return true; + if (pc >= PATLEN) return TRUE; } break; case 0x40: /* [reg + nn] */ - if ((pc+=1) >= PATLEN) return true; + 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; + if (pc >= PATLEN) return TRUE; pat[pc++] = WILD; - if (pc >= PATLEN) return true; + if (pc >= PATLEN) return TRUE; break; case 0xC0: /* reg */ break; } - return false; + return FALSE; } /* Change the next two bytes to wild cards */ static bool -TwoWild(uint8_t pat[]) +TwoWild(byte pat[]) { pat[pc++] = WILD; - if (pc >= PATLEN) return true; /* Pattern exhausted */ + if (pc >= PATLEN) return TRUE; /* Pattern exhausted */ pat[pc++] = WILD; - if (pc >= PATLEN) return true; - return false; + if (pc >= PATLEN) return TRUE; + return FALSE; } /* Change the next four bytes to wild cards */ static bool -FourWild(uint8_t pat[]) +FourWild(byte pat[]) { TwoWild(pat); return TwoWild(pat); @@ -89,21 +92,22 @@ FourWild(uint8_t pat[]) /* Chop from the current point by wiping with zeroes. Can't rely on anything after this point */ static void -chop(uint8_t pat[]) +chop(byte pat[]) { if (pc >= PATLEN) return; /* Could go negative otherwise */ memset(&pat[pc], 0, PATLEN - pc); } -static bool op0F(uint8_t pat[]) +static bool +op0F(byte pat[]) { - /* The two uint8_t opcodes */ - uint8_t op = pat[pc++]; + /* The two byte opcodes */ + byte op = pat[pc++]; switch (op & 0xF0) { case 0x00: /* 00 - 0F */ if (op >= 0x06) /* Clts, Invd, Wbinvd */ - return false; + return FALSE; else { /* Grp 6, Grp 7, LAR, LSL */ @@ -113,10 +117,10 @@ static bool op0F(uint8_t pat[]) return ModRM(pat); case 0x80: - pc += 2; /* uint16_t displacement cond jumps */ - return false; + pc += 2; /* Word displacement cond jumps */ + return FALSE; - case 0x90: /* uint8_t set on condition */ + case 0x90: /* Byte set on condition */ return ModRM(pat); case 0xA0: @@ -126,7 +130,7 @@ static bool op0F(uint8_t pat[]) case 0xA1: /* Pop FS */ case 0xA8: /* Push GS */ case 0xA9: /* Pop GS */ - return false; + return FALSE; case 0xA3: /* Bt Ev,Gv */ case 0xAB: /* Bts Ev,Gv */ @@ -134,9 +138,9 @@ static bool op0F(uint8_t pat[]) case 0xA4: /* Shld EvGbIb */ case 0xAC: /* Shrd EvGbIb */ - if (ModRM(pat)) return true; + if (ModRM(pat)) return TRUE; pc++; /* The #num bits to shift */ - return false; + return FALSE; case 0xA5: /* Shld EvGb CL */ case 0xAD: /* Shrd EvGb CL */ @@ -150,9 +154,9 @@ static bool op0F(uint8_t pat[]) if (op == 0xBA) { /* Grp 8: bt/bts/btr/btc Ev,#nn */ - if (ModRM(pat)) return true; + if (ModRM(pat)) return TRUE; pc++; /* The #num bits to shift */ - return false; + return FALSE; } return ModRM(pat); @@ -163,10 +167,10 @@ static bool op0F(uint8_t pat[]) return ModRM(pat); } /* Else BSWAP */ - return false; + return FALSE; default: - return false; /* Treat as double uint8_t opcodes */ + return FALSE; /* Treat as double byte opcodes */ } @@ -181,10 +185,10 @@ static bool op0F(uint8_t pat[]) PATLEN bytes are scanned. */ void -fixWildCards(uint8_t pat[]) +fixWildCards(byte pat[]) { - uint8_t op, quad, intArg; + byte op, quad, intArg; pc=0; @@ -193,17 +197,17 @@ fixWildCards(uint8_t pat[]) op = pat[pc++]; if (pc >= PATLEN) return; - quad = (uint8_t) (op & 0xC0); /* Quadrant of the opcode map */ + 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 uint8_t opcode */ + /* Segment prefix: treat as 1 byte opcode */ continue; } - if (op == 0x0F) /* 386 2 uint8_t opcodes */ + if (op == 0x0F) /* 386 2 byte opcodes */ { if (op0F(pat)) return; continue; @@ -214,20 +218,20 @@ fixWildCards(uint8_t pat[]) /* All these are constant. Work out the instr length */ if (op & 2) { - /* Push, pop, other 1 uint8_t opcodes */ + /* Push, pop, other 1 byte opcodes */ continue; } else { if (op & 1) { - /* uint16_t immediate operands */ + /* Word immediate operands */ pc += 2; continue; } else { - /* uint8_t immediate operands */ + /* Byte immediate operands */ pc++; continue; } @@ -253,7 +257,7 @@ fixWildCards(uint8_t pat[]) /* 0x60 - 0x70 */ if (op & 0x10) { - /* 70-7F 2 uint8_t jump opcodes */ + /* 70-7F 2 byte jump opcodes */ pc++; continue; } @@ -280,11 +284,11 @@ fixWildCards(uint8_t pat[]) if (TwoWild(pat)) return; continue; - case 0x68: /* Push uint8_t */ - case 0x6A: /* Push uint8_t */ + case 0x68: /* Push byte */ + case 0x6A: /* Push byte */ case 0x6D: /* insb port */ case 0x6F: /* outsb port */ - /* 2 uint8_t instr, no wilds */ + /* 2 byte instr, no wilds */ pc++; continue; @@ -298,14 +302,14 @@ fixWildCards(uint8_t pat[]) switch (op & 0xF0) { case 0x80: /* 80 - 8F */ - /* All have a mod/rm uint8_t */ + /* All have a mod/rm byte */ if (ModRM(pat)) return; /* These also have immediate values */ switch (op) { case 0x80: case 0x83: - /* One uint8_t immediate */ + /* One byte immediate */ pc++; continue; @@ -324,7 +328,7 @@ fixWildCards(uint8_t pat[]) if (FourWild(pat)) return; continue; } - /* All others are 1 uint8_t opcodes */ + /* All others are 1 byte opcodes */ continue; case 0xA0: /* A0 - AF */ if ((op & 0x0C) == 0) @@ -335,7 +339,7 @@ fixWildCards(uint8_t pat[]) } else if ((op & 0xFE) == 0xA8) { - /* test al,#uint8_t or test ax,#uint16_t */ + /* test al,#byte or test ax,#word */ if (op & 1) pc += 2; else pc += 1; continue; @@ -364,10 +368,10 @@ fixWildCards(uint8_t pat[]) /* In the last quadrant of the op code table */ switch (op) { - case 0xC0: /* 386: Rotate group 2 ModRM, uint8_t, #uint8_t */ - case 0xC1: /* 386: Rotate group 2 ModRM, uint16_t, #uint8_t */ + case 0xC0: /* 386: Rotate group 2 ModRM, byte, #byte */ + case 0xC1: /* 386: Rotate group 2 ModRM, word, #byte */ if (ModRM(pat)) return; - /* uint8_t immediate value follows ModRM */ + /* Byte immediate value follows ModRM */ pc++; continue; @@ -388,27 +392,27 @@ fixWildCards(uint8_t pat[]) case 0xC6: /* Mov ModRM, #nn */ if (ModRM(pat)) return; - /* uint8_t immediate value follows ModRM */ + /* Byte immediate value follows ModRM */ pc++; continue; case 0xC7: /* Mov ModRM, #nnnn */ if (ModRM(pat)) return; - /* uint16_t immediate value follows ModRM */ + /* 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 uint16_t, uint8_t */ + pc += 3; /* Constant word, byte */ continue; case 0xC9: /* Leave */ continue; - case 0xCC: /* int 3 */ + case 0xCC: /* Int 3 */ continue; - case 0xCD: /* int nn */ + case 0xCD: /* Int nn */ intArg = pat[pc++]; if ((intArg >= 0x34) && (intArg <= 0x3B)) { @@ -423,10 +427,10 @@ fixWildCards(uint8_t pat[]) case 0xCF: /* Iret */ continue; - case 0xD0: /* Group 2 rotate, uint8_t, 1 bit */ - case 0xD1: /* Group 2 rotate, uint16_t, 1 bit */ - case 0xD2: /* Group 2 rotate, uint8_t, CL bits */ - case 0xD3: /* Group 2 rotate, uint16_t, CL bits */ + 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; @@ -498,8 +502,8 @@ fixWildCards(uint8_t pat[]) case 0xFD: /* Std */ continue; - case 0xF6: /* Group 3 uint8_t test/not/mul/div */ - case 0xF7: /* Group 3 uint16_t test/not/mul/div */ + 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; @@ -509,7 +513,7 @@ fixWildCards(uint8_t pat[]) if (ModRM(pat)) return; continue; - default: /* Rest are single uint8_t opcodes */ + default: /* Rest are single byte opcodes */ continue; } } diff --git a/src/frontend.cpp b/src/frontend.cpp index 32ca9c8..e76dead 100644 --- a/src/frontend.cpp +++ b/src/frontend.cpp @@ -1,51 +1,54 @@ /***************************************************************************** -* dcc project Front End module -* Loads a program into simulated main memory and builds the procedure list. -* (C) Cristina Cifuentes -****************************************************************************/ + * dcc project Front End module + * Loads a program into simulated main memory and builds the procedure list. + * (C) Cristina Cifuentes + ****************************************************************************/ #include "dcc.h" -#include "disassem.h" #include #include #include +#ifdef __BORLAND__ +#include +#else #include /* For malloc, free, realloc */ -#include "project.h" +#endif + typedef struct { /* PSP structure */ - uint16_t int20h; /* interrupt 20h */ - uint16_t eof; /* segment, end of allocation block */ - uint8_t res1; /* reserved */ - uint8_t dosDisp[5]; /* far call to DOS function dispatcher */ - uint8_t int22h[4]; /* vector for terminate routine */ - uint8_t int23h[4]; /* vector for ctrl+break routine */ - uint8_t int24h[4]; /* vector for error routine */ - uint8_t res2[22]; /* reserved */ - uint16_t segEnv; /* segment address of environment block */ - uint8_t res3[34]; /* reserved */ - uint8_t int21h[6]; /* opcode for int21h and far return */ - uint8_t res4[6]; /* reserved */ - uint8_t fcb1[16]; /* default file control block 1 */ - uint8_t fcb2[16]; /* default file control block 2 */ - uint8_t res5[4]; /* reserved */ - uint8_t cmdTail[0x80]; /* command tail and disk transfer area */ + 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 */ - uint8_t sigLo; /* .EXE signature: 0x4D 0x5A */ - uint8_t sigHi; - uint16_t lastPageSize; /* Size of the last page */ - uint16_t numPages; /* Number of pages in the file */ - uint16_t numReloc; /* Number of relocation items */ - uint16_t numParaHeader; /* # of paragraphs in the header */ - uint16_t minAlloc; /* Minimum number of paragraphs */ - uint16_t maxAlloc; /* Maximum number of paragraphs */ - uint16_t initSS; /* Segment displacement of stack */ - uint16_t initSP; /* Contents of SP at entry */ - uint16_t checkSum; /* Complemented checksum */ - uint16_t initIP; /* Contents of IP at entry */ - uint16_t initCS; /* Segment displacement of code */ - uint16_t relocTabOffset; /* Relocation table offset */ - uint16_t overlayNum; /* Overlay number */ + 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 */ @@ -55,294 +58,440 @@ static void displayLoadInfo(void); static void displayMemMap(void); /***************************************************************************** -* FrontEnd - invokes the loader, parser, disassembler (if asm1), icode -* rewritter, and displays any useful information. -****************************************************************************/ -extern Project g_proj; -bool DccFrontend::FrontEnd () + * FrontEnd - invokes the loader, parser, disassembler (if asm1), icode + * rewritter, and displays any useful information. + ****************************************************************************/ +void FrontEnd (char *filename, PCALL_GRAPH *pcallGraph) { + PPROC pProc; + PSYM psym; + Int i, c; + + /* Load program into memory */ + LoadImage(filename); - g_proj.callGraph = 0; - g_proj.m_fname = m_fname; + if (option.verbose) + { + displayLoadInfo(); + } - /* Load program into memory */ - LoadImage(g_proj); + /* Do depth first flow analysis building call graph and procedure list, + * and attaching the I-code to each procedure */ + parse (pcallGraph); - if (option.verbose) - displayLoadInfo(); + if (option.asm1) + { + printf("dcc: writing assembler file %s\n", asm1_name); + } - /* Do depth first flow analysis building call graph and procedure list, - * and attaching the I-code to each procedure */ - parse (g_proj); + /* Search through code looking for impure references and flag them */ + for (pProc = pProcList; pProc; pProc = pProc->next) + { + for (i = 0; i < pProc->Icode.GetNumIcodes(); i++) + { + if (pProc->Icode.GetLlFlag(i) & (SYM_USE | SYM_DEF)) + { + psym = &symtab.sym[pProc->Icode.GetIcode(i)->ic.ll.caseTbl.numEntries]; + for (c = (Int)psym->label; c < (Int)psym->label+psym->size; c++) + { + if (BITMAP(c, BM_CODE)) + { + pProc->Icode.SetLlFlag(i, IMPURE); + pProc->flg |= IMPURE; + break; + } + } + } + } + /* Print assembler listing */ + if (option.asm1) + disassem(1, pProc); + } - if (option.asm1) - { - printf("dcc: writing assembler file %s\n", asm1_name); - } + if (option.Interact) + { + interactDis(pProcList, 0); /* Interactive disassembler */ + } - /* Search through code looking for impure references and flag them */ - Disassembler ds(1); - for(Function &f : g_proj.pProcList) - { - f.markImpure(); - if (option.asm1) - { - ds.disassem(&f); - } - } - if (option.Interact) - { - interactDis(&g_proj.pProcList.front(), 0); /* Interactive disassembler */ - } + /* Converts jump target addresses to icode offsets */ + for (pProc = pProcList; pProc; pProc = pProc->next) + bindIcodeOff (pProc); - /* Converts jump target addresses to icode offsets */ - for(Function &f : g_proj.pProcList) - { - f.bindIcodeOff(); - } - /* Print memory bitmap */ - if (option.Map) - displayMemMap(); - return(true); // we no longer own proj ! + /* Print memory bitmap */ + if (option.Map) + displayMemMap(); } /**************************************************************************** -* displayLoadInfo - Displays low level loader type info. -***************************************************************************/ + * displayLoadInfo - Displays low level loader type info. + ***************************************************************************/ static void displayLoadInfo(void) { - PROG &prog(Project::get()->prog); - int i; + 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); + 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"); + 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) + * fill - Fills line for displayMemMap() + ****************************************************************************/ +static void fill(Int ip, char *bf) { - PROG &prog(Project::get()->prog); - static uint8_t type[4] = {'.', 'd', 'c', 'x'}; - uint8_t i; + 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'; + 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 -****************************************************************************/ + * displayMemMap - Displays the memory bitmap + ****************************************************************************/ static void displayMemMap(void) { - PROG &prog(Project::get()->prog); + char c, b1[33], b2[33], b3[33]; + byte i; + Int ip = 0; - char c, b1[33], b2[33], b3[33]; - uint8_t 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"); + 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 -****************************************************************************/ -void DccFrontend::LoadImage(Project &proj) + * LoadImage + ****************************************************************************/ +static void LoadImage(char *filename) { - PROG &prog(Project::get()->prog); - FILE *fp; - int i, cb; - uint8_t buf[4]; + FILE *fp; + Int i, cb; + byte buf[4]; - /* Open the input file */ - if ((fp = fopen(proj.m_fname.c_str(), "rb")) == NULL) - { - fatalError(CANNOT_OPEN, proj.m_fname.c_str()); - } + /* 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, proj.m_fname.c_str()); - } + /* 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, proj.m_fname.c_str()); - } + 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); - } + /* 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 = (uint32_t)LH(&header.numPages) * 512 - (uint32_t)LH(&header.numParaHeader) * 16; - if (header.lastPageSize) - { - cb -= 512 - LH(&header.lastPageSize); - } + /* 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); - /* 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_t)LH(&header.initCS) + EXE_RELOCATION; - prog.initIP = (int16_t)LH(&header.initIP); - prog.initSS = (int16_t)LH(&header.initSS) + EXE_RELOCATION; - prog.initSP = (int16_t)LH(&header.initSP); - prog.cReloc = (int16_t)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); - /* Allocate the relocation table */ - if (prog.cReloc) - { - prog.relocTable = new uint32_t [prog.cReloc]; - 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); - /* 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 */ - uint32_t start_of_image= LH(&header.numParaHeader) * 16; - fseek(fp, start_of_image, 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; - /* 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); + } - 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 */ - /* Allocate a block of memory for the program. */ - prog.cbImage = cb + sizeof(PSP); - prog.Image = new uint8_t [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); + } - /* Read in the image past where a PSP would go */ - if (cb != (int)fread(prog.Image + sizeof(PSP), 1, (size_t)cb, fp)) - { - fatalError(CANNOT_READ, proj.m_fname.c_str()); - } + /* Set up memory map */ + cb = (prog.cbImage + 3) / 4; + prog.map = (byte *)memset(allocMem(cb), BM_UNKNOWN, (size_t)cb); - /* Set up memory map */ - cb = (prog.cbImage + 3) / 4; - prog.map = (uint8_t *)malloc(cb); - memset(prog.map, 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); + } + } - /* Relocate segment constants */ - if (prog.cReloc) - { - for (i = 0; i < prog.cReloc; i++) - { - uint8_t *p = &prog.Image[prog.relocTable[i]]; - uint16_t w = (uint16_t)LH(p) + EXE_RELOCATION; - *p++ = (uint8_t)(w & 0x00FF); - *p = (uint8_t)((w & 0xFF00) >> 8); - } - } - - fclose(fp); + fclose(fp); } /***************************************************************************** -* allocMem - malloc with failure test -****************************************************************************/ -void *allocMem(int cb) + * allocMem - malloc with failure test + ****************************************************************************/ +void *allocMem(Int cb) { - uint8_t *p; + byte *p; - //printf("Attempt to allocMem %5ld bytes\n", cb); +//printf("Attempt to allocMem %5ld bytes\n", cb); - if (! (p = (uint8_t*)malloc((size_t)cb))) - /* if (! (p = (uint8_t*)calloc((size_t)cb, 1))) */ - { - fatalError(MALLOC_FAILED, cb); - } - // printf("allocMem: %p\n", p); - return p; +#if 0 /* Microsoft specific heap debugging code */ +switch (_heapset('Z')) +{ + case _HEAPBADBEGIN: printf("aM: Bad heap begin\n"); break; + case _HEAPBADNODE: printf("aM: Bad heap node\n"); + printf("Attempt to allocMem %5d bytes\n", cb); + { + _HEAPINFO hinfo; + int heapstatus; + boolT cont = TRUE; + + hinfo._pentry = NULL; + + while (cont) + { + switch (heapstatus = _heapwalk(&hinfo)) + { + case _HEAPOK: + printf("%6s block at %Fp of size %4.4X\n", + (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"), + hinfo._pentry, hinfo._size); + break; + case _HEAPBADBEGIN: + printf("Heap bad begin\n"); + break; + case _HEAPBADNODE: + printf("BAD NODE %6s block at %Fp of size %4.4X\n", + (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"), + hinfo._pentry, hinfo._size); + break; + case _HEAPEND: + cont = FALSE; + break; + case _HEAPBADPTR: + printf("INFO BAD %6s block at %Fp of size %4.4X\n", + (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"), + hinfo._pentry, hinfo._size); + cont=FALSE; + + } + } + } + getchar(); + exit(1); + + case _HEAPEMPTY: printf("aM: Heap empty\n"); getchar(); break; + case _HEAPOK:putchar('.');break; } +#endif + + 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 0 +switch (_heapset('Z')) +{ + case _HEAPBADBEGIN: printf("aV: Bad heap begin\n"); /*getchar()*/; break; + case _HEAPBADNODE: printf("aV: Bad heap node\n"); + printf("Attempt to reallocVar %5d bytes at %p\n", newsize, p);/**/ + { + _HEAPINFO hinfo; + int heapstatus; + boolT cont = TRUE; + + hinfo._pentry = NULL; + + while (cont) + { + switch (heapstatus = _heapwalk(&hinfo)) + { + case _HEAPOK: + printf("%6s block at %Fp of size %4.4X\n", + (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"), + hinfo._pentry, hinfo._size); + break; + case _HEAPBADBEGIN: + printf("Heap bad begin\n"); + break; + case _HEAPBADNODE: + printf("BAD NODE %6s block at %Fp of size %4.4X\n", + (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"), + hinfo._pentry, hinfo._size); + break; + case _HEAPEND: + cont = FALSE; + break; + case _HEAPBADPTR: + printf("INFO BAD %6s block at %Fp of size %4.4X\n", + (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"), + hinfo._pentry, hinfo._size); + cont=FALSE; + + } + } + } + getchar(); + break; + + case _HEAPEMPTY: printf("aV: Heap empty\n"); getchar(); break; + case _HEAPOK:putchar('!');break; +} +#endif + + 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 + diff --git a/src/graph.cpp b/src/graph.cpp index f198f3d..db7b17e 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -5,406 +5,396 @@ #include "dcc.h" #include +#if __BORLAND__ +#include +#else #include /* For free() */ -#include "graph.h" -#include "project.h" -extern Project g_proj; -//static BB * rmJMP(Function * pProc, int marker, BB * pBB); -static void mergeFallThrough(Function * pProc, BB * pBB); -static void dfsNumbering(BB * pBB, std::vector &dfsLast, int *first, int *last); +#endif + +static PBB rmJMP(PPROC pProc, Int marker, PBB pBB); +static void mergeFallThrough(PPROC pProc, PBB pBB); +static void dfsNumbering(PBB pBB, PBB *dfsLast, Int *first, Int *last); /***************************************************************************** * createCFG - Create the basic control flow graph ****************************************************************************/ -void Function::createCFG() +PBB createCFG(PPROC pProc) { - /* 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; - BB * psBB; - BB * pBB; - iICODE pIcode = Icode.begin(); - iICODE iStart = Icode.begin(); - stats.numBBbef = stats.numBBaft = 0; - for (; pIcode!=Icode.end(); ++pIcode) - { - iICODE nextIcode = ++iICODE(pIcode); - LLInst *ll = pIcode->ll(); - /* Stick a NOWHERE_NODE on the end if we terminate - * with anything other than a ret, jump or terminate */ - if (nextIcode == Icode.end() and - (not ll->testFlags(TERMINATES)) and - (not ll->match(iJMP)) and (not ll->match(iJMPF)) and - (not ll->match(iRET)) and (not ll->match(iRETF))) - { - //pBB=BB::Create(start, ip, NOWHERE_NODE, 0, this); - pBB=BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this); + /* 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 cfg; + PBB psBB; + PBB pBB = &cfg; + PICODE pIcode = pProc->Icode.GetFirstIcode(); - } + cfg.next = NULL; + stats.numBBbef = stats.numBBaft = 0; + for (ip = start = 0; pProc->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 == pProc->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) + newBB(pBB, start, ip, NOWHERE_NODE, 0, pProc); - /* Only process icodes that have valid instructions */ - else if (not ll->testFlags(NO_CODE) ) - { - switch (ll->getOpcode()) { - 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(iStart, pIcode, TWO_BRANCH, 2, this); -CondJumps: - //start = ip + 1; - iStart = ++iICODE(pIcode); - pBB->edges[0].ip = (uint32_t)iStart->loc_ip; - /* This is for jumps off into nowhere */ - if ( ll->testFlags(NO_LABEL) ) - { - pBB->edges.pop_back(); - } - else - pBB->edges[1].ip = ll->src().getImm2(); - break; + /* 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 = newBB(pBB, start, ip, TWO_BRANCH, 2, pProc); + 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); - pBB = BB::Create(iStart, pIcode, LOOP_NODE, 2, this); - goto CondJumps; + case iLOOP: case iLOOPE: case iLOOPNE: + pBB = newBB(pBB, start, ip, LOOP_NODE, 2, pProc); + goto CondJumps; - case iJMPF: case iJMP: - if (ll->testFlags(SWITCH)) - { - //pBB = BB::Create(start, ip, MULTI_BRANCH, ll->caseTbl.numEntries, this); - pBB = BB::Create(iStart, pIcode, MULTI_BRANCH, ll->caseTbl2.size(), this); - for (i = 0; i < ll->caseTbl2.size(); i++) - pBB->edges[i].ip = ll->caseTbl2[i]; - hasCase = true; - } - else if ((ll->getFlag() & (I | NO_LABEL)) == I) //TODO: WHY NO_LABEL TESTIT - { - //pBB = BB::Create(start, ip, ONE_BRANCH, 1, this); - pBB = BB::Create(iStart, pIcode, ONE_BRANCH, 1, this); + case iJMPF: case iJMP: + if (pIcode->ic.ll.flg & SWITCH) + { + pBB = newBB(pBB, start, ip, MULTI_BRANCH, + pIcode->ic.ll.caseTbl.numEntries, pProc); + for (i = 0; i < pIcode->ic.ll.caseTbl.numEntries; i++) + pBB->edges[i].ip = pIcode->ic.ll.caseTbl.entries[i]; + pProc->hasCase = TRUE; + } + else if ((pIcode->ic.ll.flg & (I | NO_LABEL)) == I) { + pBB = newBB(pBB, start, ip, ONE_BRANCH, 1, pProc); + pBB->edges[0].ip = pIcode->ic.ll.immed.op; + } + else + newBB(pBB, start, ip, NOWHERE_NODE, 0, pProc); + start = ip + 1; + break; - pBB->edges[0].ip = ll->src().getImm2(); - } - else - BB::Create(iStart, pIcode, NOWHERE_NODE, 0, this); - iStart = ++iICODE(pIcode); - break; + case iCALLF: case iCALL: + { PPROC p = pIcode->ic.ll.immed.proc.proc; + if (p) + i = ((p->flg) & TERMINATES) ? 0 : 1; + else + i = 1; + pBB = newBB(pBB, start, ip, CALL_NODE, i, pProc); + start = ip + 1; + if (i) + pBB->edges[0].ip = (dword)start; + } + break; - case iCALLF: case iCALL: - { - Function * p = ll->src().proc.proc; - if (p) - i = ((p->flg) & TERMINATES) ? 0 : 1; - else - i = 1; - pBB = BB::Create(iStart, pIcode, CALL_NODE, i, this); - iStart = ++iICODE(pIcode);//start = ip + 1; - if (i) - pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start; - } - break; + case iRET: case iRETF: + newBB(pBB, start, ip, RETURN_NODE, 0, pProc); + start = ip + 1; + break; - case iRET: case iRETF: - //BB::Create(start, ip, RETURN_NODE, 0, this); - BB::Create(iStart, pIcode, RETURN_NODE, 0, this); - iStart = ++iICODE(pIcode); - break; + default: + /* Check for exit to DOS */ + if (pIcode->ic.ll.flg & TERMINATES) + { + pBB = newBB(pBB, start, ip, TERMINATE_NODE, 0, pProc); + start = ip + 1; + } + /* Check for a fall through */ + else if (pProc->Icode.GetFirstIcode()[ip + 1].ic.ll.flg & (TARGET | CASE)) + { + pBB = newBB(pBB, start, ip, FALL_NODE, 1, pProc); + start = ip + 1; + pBB->edges[0].ip = (dword)start; + } + break; + } + } + } - default: - /* Check for exit to DOS */ - iICODE next1=++iICODE(pIcode); - if ( ll->testFlags(TERMINATES) ) - { - pBB = BB::Create(iStart, pIcode, TERMINATE_NODE, 0, this); - //pBB = BB::Create(start, ip, TERMINATE_NODE, 0, this); - iStart = ++iICODE(pIcode); // start = ip + 1; - } - /* Check for a fall through */ - else if (next1 != Icode.end()) - { - if (next1->ll()->testFlags(TARGET | CASE)) - { - //pBB = BB::Create(start, ip, FALL_NODE, 1, this); - pBB = BB::Create(iStart, pIcode, FALL_NODE, 1, this); - iStart = ++iICODE(pIcode); // start = ip + 1; - pBB->addOutEdge(iStart->loc_ip); - pBB->edges[0].ip = iStart->loc_ip;//(uint32_t)start; - } - } - break; - } - } - } - auto iter=heldBBs.begin(); - /* Convert list of BBs into a graph */ - for (; iter!=heldBBs.end(); ++iter) - { - pBB = *iter; - for (size_t edeg_idx = 0; edeg_idx < pBB->edges.size(); edeg_idx++) - { - uint32_t ip = pBB->edges[edeg_idx].ip; - if (ip >= SYNTHESIZED_MIN) - { - fatalError (INVALID_SYNTHETIC_BB); - return; - } - auto iter2=std::find_if(heldBBs.begin(),heldBBs.end(), - [ip](BB *psBB)->bool {return psBB->begin()->loc_ip==ip;}); - if(iter2==heldBBs.end()) - fatalError(NO_BB, ip, name.c_str()); - psBB = *iter2; - pBB->edges[edeg_idx].BBptr = psBB; - psBB->inEdges.push_back((BB *)nullptr); - } - } + /* Convert list of BBs into a graph */ + for (pBB = cfg.next; pBB; pBB = pBB->next) + { + for (i = 0; i < pBB->numOutEdges; i++) + { + ip = pBB->edges[i].ip; + if (ip >= SYNTHESIZED_MIN) + fatalError (INVALID_SYNTHETIC_BB); + else + { + for (psBB = cfg.next; psBB; psBB = psBB->next) + if (psBB->start == ip) + { + pBB->edges[i].BBptr = psBB; + psBB->numInEdges++; + break; + } + if (! psBB) + fatalError(NO_BB, ip, pProc->name); + } + } + } + return cfg.next; } -void Function::markImpure() -{ - PROG &prog(Project::get()->prog); - for(ICODE &icod : Icode) - { - if ( not icod.ll()->testFlags(SYM_USE | SYM_DEF)) - continue; - //assert that case tbl has less entries then symbol table ???? - //WARNING: Case entries are held in symbol table ! - assert(g_proj.validSymIdx(icod.ll()->caseEntry)); - const SYM &psym(g_proj.getSymByIdx(icod.ll()->caseEntry)); - for (int c = (int)psym.label; c < (int)psym.label+psym.size; c++) - { - if (BITMAP(c, BM_CODE)) - { - icod.ll()->setFlags(IMPURE); - flg |= IMPURE; - break; - } - } - } - -} - - /***************************************************************************** * newBB - Allocate new BB and link to end of list *****************************************************************************/ +PBB newBB (PBB pBB, Int start, Int ip, byte nodeType, Int numOutEdges, + PPROC pproc) +{ + PBB pnewBB; + + pnewBB = allocStruc(BB); + memset (pnewBB, 0, sizeof(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 = (TYPEADR_TYPE*)allocMem(numOutEdges * sizeof(TYPEADR_TYPE)); + + /* Mark the basic block to which the icodes belong to, but only for + * real code basic blocks (ie. not interval bbs) */ + if (start >= 0) + pproc->Icode.SetInBB(start, ip, pnewBB); + + while (pBB->next) /* Link */ + pBB = pBB->next; + pBB->next = pnewBB; + + if (start != -1) { /* Only for code BB's */ + stats.numBBbef++; + } + return pnewBB; +} + /***************************************************************************** * freeCFG - Deallocates a cfg ****************************************************************************/ -void Function::freeCFG() +void freeCFG(PBB cfg) { - for(BB *p : heldBBs) - { - delete p; - } + PBB pBB; + + for (pBB = cfg; pBB; pBB = cfg) { + if (pBB->inEdges) + free(pBB->inEdges); + if (pBB->edges) + free(pBB->edges); + cfg = pBB->next; + free(pBB); + } } /***************************************************************************** * compressCFG - Remove redundancies and add in-edge information ****************************************************************************/ -void Function::compressCFG() -{ - BB *pNxt; - int ip, first=0, last; +void compressCFG(PPROC pProc) +{ PBB pBB, pNxt; + Int ip, first=0, last, i; - /* First pass over BB list removes redundant jumps of the form - * (Un)Conditional -> Unconditional jump */ - for (BB *pBB : m_cfg) - { - if(pBB->inEdges.empty() || (pBB->nodeType != ONE_BRANCH && pBB->nodeType != TWO_BRANCH)) - continue; - for (TYPEADR_TYPE &edgeRef : pBB->edges) - { - ip = pBB->rbegin()->loc_ip; - pNxt = edgeRef.BBptr->rmJMP(ip, edgeRef.BBptr); + /* First pass over BB list removes redundant jumps of the form + * (Un)Conditional -> Unconditional jump */ + for (pBB = pProc->cfg; pBB; pBB = pBB->next) + 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(pProc, ip, pBB->edges[i].BBptr); - if (not pBB->edges.empty()) /* Might have been clobbered */ - { - edgeRef.BBptr = pNxt; - assert(pBB->back().loc_ip==ip); - pBB->back().ll()->SetImmediateOp((uint32_t)pNxt->begin()->loc_ip); - //Icode[ip].SetImmediateOp((uint32_t)pNxt->begin()); - } - } - } + if (pBB->numOutEdges) /* Might have been clobbered */ + { + pBB->edges[i].BBptr = pNxt; + pProc->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. */ - m_cfg.front()->mergeFallThrough(Icode); + /* 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. */ + mergeFallThrough(pProc, pProc->cfg); - /* Remove redundant BBs created by the above compressions - * and allocate in-edge arrays as required. */ - stats.numBBaft = stats.numBBbef; + /* Remove redundant BBs created by the above compressions + * and allocate in-edge arrays as required. */ + stats.numBBaft = stats.numBBbef; - for(auto iter=m_cfg.begin(); iter!=m_cfg.end(); ++iter) - { - BB * pBB = *iter; - if (pBB->inEdges.empty()) - { - if (iter == m_cfg.begin()) /* Init it misses out on */ - pBB->index = UN_INIT; - else - { - delete pBB; - stats.numBBaft--; - } - } - else - { - pBB->inEdgeCount = pBB->inEdges.size(); - } - } + for (pBB = pProc->cfg; pBB; pBB = pNxt) + { + pNxt = pBB->next; + if (pBB->numInEdges == 0) + { + if (pBB == pProc->cfg) /* Init it misses out on */ + pBB->index = UN_INIT; + else + { + if (pBB->numOutEdges) + free(pBB->edges); + free(pBB); + stats.numBBaft--; + } + } + else + { + pBB->inEdgeCount = pBB->numInEdges; + pBB->inEdges = (PBB*)allocMem(pBB->numInEdges * sizeof(PBB)); + } + } - /* Allocate storage for dfsLast[] array */ - numBBs = stats.numBBaft; - m_dfsLast.resize(numBBs,0); // = (BB **)allocMem(numBBs * sizeof(BB *)) + /* Allocate storage for dfsLast[] array */ + pProc->numBBs = stats.numBBaft; + pProc->dfsLast = (PBB*)allocMem(pProc->numBBs * sizeof(PBB)); - /* Now do a dfs numbering traversal and fill in the inEdges[] array */ - last = numBBs - 1; - m_cfg.front()->dfsNumbering(m_dfsLast, &first, &last); + /* Now do a dfs numbering traversal and fill in the inEdges[] array */ + last = pProc->numBBs - 1; + dfsNumbering(pProc->cfg, pProc->dfsLast, &first, &last); } /**************************************************************************** * rmJMP - If BB addressed is just a JMP it is replaced with its target ***************************************************************************/ -BB *BB::rmJMP(int marker, BB * pBB) +static PBB rmJMP(PPROC pProc, Int marker, PBB pBB) { - marker += (int)DFS_JMP; + marker += DFS_JMP; - while (pBB->nodeType == ONE_BRANCH && pBB->size() == 1) - { - if (pBB->traversed != marker) - { - pBB->traversed = (eDFS)marker; - pBB->inEdges.pop_back(); - if (not pBB->inEdges.empty()) - { - pBB->edges[0].BBptr->inEdges.push_back((BB *)nullptr); - } - else - { - pBB->front().ll()->setFlags(NO_CODE); - pBB->front().invalidate(); //pProc->Icode.SetLlInvalid(pBB->begin(), true); - } + 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; - pBB->front().ll()->replaceSrc(LLOperand::CreateImm2(pBB->front().loc_ip)); - //pBB->front().ll()->src.immed.op = pBB->front().loc_ip; - do { - pBB = pBB->edges[0].BBptr; - pBB->inEdges.pop_back(); // was --numInedges - if (! pBB->inEdges.empty()) - { - pBB->front().ll()->setFlags(NO_CODE); - pBB->front().invalidate(); - // pProc->Icode.setFlags(pBB->start, NO_CODE); - // pProc->Icode.SetLlInvalid(pBB->start, true); - } - } while (pBB->nodeType != NOWHERE_NODE); + 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(); - } - } - return pBB; + free(pBB->edges); + pBB->numOutEdges = 0; + pBB->edges = NULL; + } + } + return pBB; } /***************************************************************************** * mergeFallThrough ****************************************************************************/ -void BB::mergeFallThrough( CIcodeRec &Icode) +static void mergeFallThrough(PPROC pProc, PBB pBB) { - BB * pChild; - int i; + PBB 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) - { - assert(Parent==pChild->Parent); - if(back().loc_ip>pChild->front().loc_ip) // back edege - break; - auto iter=std::find_if(this->end(),pChild->begin(),[](ICODE &c) - {return not c.ll()->testFlags(NO_CODE);}); + if (pBB) { + while (pBB->nodeType == FALL_NODE || pBB->nodeType == ONE_BRANCH) + { + pChild = pBB->edges[0].BBptr; + /* Jump to next instruction can always be removed */ + if (pBB->nodeType == ONE_BRANCH) + { + ip = pBB->start + pBB->length; + for (i = ip; i < pChild->start + && (pProc->Icode.GetLlFlag(i) & NO_CODE); i++); + if (i != pChild->start) + break; + pProc->Icode.SetLlFlag(ip - 1, NO_CODE); + pProc->Icode.SetLlInvalid(ip - 1, TRUE); + pBB->nodeType = FALL_NODE; + pBB->length--; - if (iter != pChild->begin()) - break; - back().ll()->setFlags(NO_CODE); - back().invalidate(); - nodeType = FALL_NODE; - //instructions.advance_end(-1); //TODO: causes creation of empty BB - } - /* If there's no other edges into child can merge */ - if (pChild->inEdges.size() != 1) - break; + } + /* If there's no other edges into child can merge */ + if (pChild->numInEdges != 1) + break; - nodeType = pChild->nodeType; - instructions = boost::make_iterator_range(begin(),pChild->end()); - pChild->front().ll()->clrFlags(TARGET); - edges.swap(pChild->edges); + pBB->nodeType = pChild->nodeType; + pBB->length = pChild->start + pChild->length - pBB->start; + pProc->Icode.ClearLlFlag(pChild->start, TARGET); + pBB->numOutEdges = pChild->numOutEdges; + free(pBB->edges); + pBB->edges = pChild->edges; - pChild->inEdges.clear(); - pChild->edges.clear(); - } - traversed = DFS_MERGE; + pChild->numOutEdges = pChild->numInEdges = 0; + pChild->edges = NULL; + } + pBB->traversed = DFS_MERGE; - /* Process all out edges recursively */ - for (i = 0; i < edges.size(); i++) - if (edges[i].BBptr->traversed != DFS_MERGE) - edges[i].BBptr->mergeFallThrough(Icode); + /* Process all out edges recursively */ + for (i = 0; i < pBB->numOutEdges; i++) + if (pBB->edges[i].BBptr->traversed != DFS_MERGE) + mergeFallThrough(pProc, pBB->edges[i].BBptr); + } } /***************************************************************************** - * dfsNumbering - Numbers nodes during first and last visits and determine + * dfsNumbering - Numbers nodes during first and last visits and determine * in-edges ****************************************************************************/ -void BB::dfsNumbering(std::vector &dfsLast, int *first, int *last) +static void dfsNumbering(PBB pBB, PBB *dfsLast, Int *first, Int *last) { - BB * pChild; - traversed = DFS_NUM; - dfsFirstNum = (*first)++; + PBB pChild; + byte i; - /* index is being used as an index to inEdges[]. */ - // for (i = 0; i < edges.size(); i++) - for(auto edge : edges) - { - pChild = edge.BBptr; - pChild->inEdges[pChild->index++] = this; + if (pBB) + { + pBB->traversed = DFS_NUM; + pBB->dfsFirstNum = (*first)++; - /* Is this the last visit? */ - if (pChild->index == pChild->inEdges.size()) - pChild->index = UN_INIT; + /* index is being used as an index to inEdges[]. */ + for (i = 0; i < pBB->numOutEdges; i++) + { + pChild = pBB->edges[i].BBptr; + pChild->inEdges[pChild->index++] = pBB; - if (pChild->traversed != DFS_NUM) - pChild->dfsNumbering(dfsLast, first, last); - } - dfsLastNum = *last; - dfsLast[(*last)--] = this; + /* Is this the last visit? */ + if (pChild->index == pChild->numInEdges) + pChild->index = UN_INIT; + + if (pChild->traversed != DFS_NUM) + dfsNumbering(pChild, dfsLast, first, last); + } + pBB->dfsLastNum = *last; + dfsLast[(*last)--] = pBB; + } } diff --git a/src/hlicode.cpp b/src/hlicode.cpp index bcb46fe..39652ff 100644 --- a/src/hlicode.cpp +++ b/src/hlicode.cpp @@ -4,631 +4,483 @@ * Date: September-October 1993 * (C) Cristina Cifuentes */ -#include + #include -#include -#include #include "dcc.h" -using namespace std; + #define ICODE_DELTA 25 /* Masks off bits set by duReg[] */ -std::bitset<32> maskDuReg[] = { 0x00, - 0xFEEFFE, 0xFDDFFD, 0xFBB00B, 0xF77007, /* uint16_t regs */ - 0xFFFFEF, 0xFFFFDF, 0xFFFFBF, 0xFFFF7F, - 0xFFFEFF, 0xFFFDFF, 0xFFFBFF, 0xFFF7FF, /* seg regs */ - 0xFFEFFF, 0xFFDFFF, 0xFFBFFF, 0xFF7FFF, /* uint8_t regs */ - 0xFEFFFF, 0xFDFFFF, 0xFBFFFF, 0xF7FFFF, - 0xEFFFFF, /* tmp reg */ - 0xFFFFB7, 0xFFFF77, 0xFFFF9F, 0xFFFF5F, /* index regs */ - 0xFFFFBF, 0xFFFF7F, 0xFFFFDF, 0xFFFFF7 }; +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 */ +void newAsgnHlIcode (PICODE pIcode, COND_EXPR *lhs, COND_EXPR *rhs) /* Places the new HLI_ASSIGN high-level operand in the high-level icode array */ -void HLTYPE::setAsgn(COND_EXPR *lhs, COND_EXPR *rhs) { - set(lhs,rhs); + pIcode->type = HIGH_LEVEL; + pIcode->ic.hl.opcode = HLI_ASSIGN; + pIcode->ic.hl.oper.asgn.lhs = lhs; + pIcode->ic.hl.oper.asgn.rhs = rhs; +} -} -void ICODE::checkHlCall() -{ - //assert((ll()->immed.proc.cb != 0)||ll()->immed.proc.proc!=0); -} + +void newCallHlIcode (PICODE pIcode) /* Places the new HLI_CALL high-level operand in the high-level icode array */ -void ICODE::newCallHl() { - type = HIGH_LEVEL; - hl()->opcode = HLI_CALL; - hl()->call.proc = ll()->src().proc.proc; - hl()->call.args = new STKFRAME; - - if (ll()->src().proc.cb != 0) - hl()->call.args->cb = ll()->src().proc.cb; - else if(hl()->call.proc) - hl()->call.args->cb =hl()->call.proc->cbParam; - else - { - printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n"); - hl()->call.args->cb = 0; - } + pIcode->type = HIGH_LEVEL; + pIcode->ic.hl.opcode = HLI_CALL; + pIcode->ic.hl.oper.call.proc = pIcode->ic.ll.immed.proc.proc; + pIcode->ic.hl.oper.call.args = (STKFRAME*)allocMem (sizeof(STKFRAME)); + memset (pIcode->ic.hl.oper.call.args, 0, sizeof(STKFRAME)); + if (pIcode->ic.ll.immed.proc.cb != 0) + pIcode->ic.hl.oper.call.args->cb = pIcode->ic.ll.immed.proc.cb; + else + pIcode->ic.hl.oper.call.args->cb =pIcode->ic.hl.oper.call.proc->cbParam; } -/* Places the new HLI_POP/HLI_PUSH/HLI_RET high-level operand in the high-level icode +void newUnaryHlIcode (PICODE pIcode, hlIcode op, COND_EXPR *exp) +/* 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) { - type = HIGH_LEVEL; - hl()->set(op,_exp); + pIcode->type = HIGH_LEVEL; + pIcode->ic.hl.opcode = op; + pIcode->ic.hl.oper.exp = exp; } +void newJCondHlIcode (PICODE pIcode, COND_EXPR *cexp) /* Places the new HLI_JCOND high-level operand in the high-level icode array */ -void ICODE::setJCond(COND_EXPR *cexp) { - type = HIGH_LEVEL; - hl()->set(HLI_JCOND,cexp); + pIcode->type = HIGH_LEVEL; + pIcode->ic.hl.opcode = HLI_JCOND; + pIcode->ic.hl.oper.exp = cexp; } -/* Sets the invalid field to true as this low-level icode is no longer valid, +void invalidateIcode (PICODE pIcode) +/* 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; + pIcode->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) - */ -bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId) -{ - int numDefs; +boolT removeDefRegi (byte regi, PICODE picode, Int thisDefIdx, LOCAL_ID *locId) +/* Removes the defined register regi from the lhs subtree. If all registers + * of this instruction are unused, the instruction is invalidated (ie. + * removed) */ +{ Int numDefs; - numDefs = du1.numRegsDef; + numDefs = picode->du1.numRegsDef; if (numDefs == thisDefIdx) - { for ( ; numDefs > 0; numDefs--) { - - if (du1.used(numDefs-1)||(du.lastDefRegi[regi])) + if ((picode->du1.idx[numDefs-1][0] != 0)||(picode->du.lastDefRegi)) break; } - } if (numDefs == 0) { - invalidate(); - return true; + invalidateIcode (picode); + return (TRUE); } - HlTypeSupport *p=hl()->get(); - if(p and p->removeRegFromLong(regi,locId)) - { - du1.numRegsDef--; - du.def &= maskDuReg[regi]; - } - return false; -} -HLTYPE LLInst::createCall() -{ - HLTYPE res(HLI_CALL); - res.call.proc = src().proc.proc; - res.call.args = new STKFRAME; - - if (src().proc.cb != 0) - res.call.args->cb = src().proc.cb; - else if(res.call.proc) - res.call.args->cb =res.call.proc->cbParam; else { - printf("Function with no cb set, and no valid oper.call.proc , probaby indirect call\n"); - res.call.args->cb = 0; + 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); } - return res; } -#if 0 -HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func) -{ - HLTYPE res(HLI_INVALID); - if ( testFlags(NOT_HLL) ) - return res; - flg = getFlag(); - switch (getOpcode()) - { - case iADD: - rhs = COND_EXPR::boolOp (lhs, rhs, ADD); - res.setAsgn(lhs, rhs); - break; - case iAND: - rhs = COND_EXPR::boolOp (lhs, rhs, AND); - res.setAsgn(lhs, rhs); - break; - - case iCALL: - case iCALLF: - //TODO: this is noop pIcode->checkHlCall(); - res=createCall(); - break; - - case iDEC: - rhs = COND_EXPR::idKte (1, 2); - rhs = COND_EXPR::boolOp (lhs, rhs, SUB); - res.setAsgn(lhs, rhs); - break; - - case iDIV: - case iIDIV:/* should be signed div */ - rhs = COND_EXPR::boolOp (lhs, rhs, DIV); - if ( ll->testFlags(B) ) - { - lhs = COND_EXPR::idReg (rAL, 0, &localId); - pIcode->setRegDU( rAL, eDEF); - } - else - { - lhs = COND_EXPR::idReg (rAX, 0, &localId); - pIcode->setRegDU( rAX, eDEF); - } - res.setAsgn(lhs, rhs); - break; - - case iIMUL: - rhs = COND_EXPR::boolOp (lhs, rhs, MUL); - lhs = COND_EXPR::id (*pIcode, LHS_OP, func, i, *pIcode, NONE); - res.setAsgn(lhs, rhs); - break; - - case iINC: - rhs = COND_EXPR::idKte (1, 2); - rhs = COND_EXPR::boolOp (lhs, rhs, ADD); - res.setAsgn(lhs, rhs); - break; - - case iLEA: - rhs = COND_EXPR::unary (ADDRESSOF, rhs); - res.setAsgn(lhs, rhs); - break; - - case iMOD: - rhs = COND_EXPR::boolOp (lhs, rhs, MOD); - if ( ll->testFlags(B) ) - { - lhs = COND_EXPR::idReg (rAH, 0, &localId); - pIcode->setRegDU( rAH, eDEF); - } - else - { - lhs = COND_EXPR::idReg (rDX, 0, &localId); - pIcode->setRegDU( rDX, eDEF); - } - res.setAsgn(lhs, rhs); - break; - - case iMOV: res.setAsgn(lhs, rhs); - break; - - case iMUL: - rhs = COND_EXPR::boolOp (lhs, rhs, MUL); - lhs = COND_EXPR::id (*pIcode, LHS_OP, this, i, *pIcode, NONE); - res.setAsgn(lhs, rhs); - break; - - case iNEG: - rhs = COND_EXPR::unary (NEGATION, lhs); - res.setAsgn(lhs, rhs); - break; - - case iNOT: - rhs = COND_EXPR::boolOp (NULL, rhs, NOT); - res.setAsgn(lhs, rhs); - break; - - case iOR: - rhs = COND_EXPR::boolOp (lhs, rhs, OR); - res.setAsgn(lhs, rhs); - break; - - case iPOP: res.set(HLI_POP, lhs); - break; - - case iPUSH: res.set(HLI_PUSH, lhs); - break; - - case iRET: - case iRETF: - res.set(HLI_RET, NULL); - break; - - case iSHL: - rhs = COND_EXPR::boolOp (lhs, rhs, SHL); - res.setAsgn(lhs, rhs); - break; - - case iSAR: /* signed */ - case iSHR: - rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/ - res.setAsgn(lhs, rhs); - break; - - case iSIGNEX: - res.setAsgn(lhs, rhs); - break; - - case iSUB: - rhs = COND_EXPR::boolOp (lhs, rhs, SUB); - res.setAsgn(lhs, rhs); - break; - - case iXCHG: - break; - - case iXOR: - rhs = COND_EXPR::boolOp (lhs, rhs, XOR); - res.setAsgn(lhs, rhs); - break; - } - return res; -} -#endif +void highLevelGen (PPROC pProc) /* 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 numIcode; /* number of icode instructions */ - iICODE pIcode; /* ptr to current icode node */ - COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */ - uint32_t _flg; /* icode flags */ - numIcode = Icode.size(); - for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i) +{ Int i, /* idx into icode array */ + numIcode; /* number of icode instructions */ + PICODE pIcode; /* ptr to current icode node */ + COND_EXPR *lhs, *rhs; /* left- and right-hand side of expression */ + flags32 flg; /* icode flags */ + + numIcode = pProc->Icode.GetNumIcodes(); + for (i = 0; i < numIcode; i++) { - assert(numIcode==Icode.size()); - pIcode = i; //Icode.GetIcode(i) - LLInst *ll = pIcode->ll(); - if ( ll->testFlags(NOT_HLL) ) - pIcode->invalidate(); - if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() ) - continue; - _flg = ll->getFlag(); - if ((_flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */ - if ((_flg & NO_OPS) != NO_OPS) /* if there are opers */ - { - if ( not ll->testFlags(NO_SRC) ) /* if there is src op */ - rhs = COND_EXPR::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE); - lhs = COND_EXPR::id (*pIcode->ll(), DST, this, i, *pIcode, NONE); - } - switch (ll->getOpcode()) + pIcode = pProc->Icode.GetIcode(i); + if ((pIcode->ic.ll.flg & NOT_HLL) == NOT_HLL) + invalidateIcode (pIcode); + if ((pIcode->type == LOW_LEVEL) && (pIcode->invalid == FALSE)) { - 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->type = HIGH_LEVEL; - pIcode->hl( ll->createCall() ); - 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 ( ll->testFlags(B) ) + 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 */ { - lhs = COND_EXPR::idReg (rAL, 0, &localId); - pIcode->setRegDU( rAL, eDEF); + if ((flg & NO_SRC) != NO_SRC) /* if there is src op */ + rhs = idCondExp (pIcode, SRC, pProc, i, pIcode, NONE); + lhs = idCondExp (pIcode, DST, pProc, i, pIcode, NONE); } - 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 (*ll, LHS_OP, this, i, *pIcode, NONE); - pIcode->setAsgn(lhs, rhs); - break; + switch (pIcode->ic.ll.opcode) { + case iADD: rhs = boolCondExp (lhs, rhs, ADD); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iINC: - rhs = COND_EXPR::idKte (1, 2); - rhs = COND_EXPR::boolOp (lhs, rhs, ADD); - pIcode->setAsgn(lhs, rhs); - break; + case iAND: rhs = boolCondExp (lhs, rhs, AND); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iLEA: - rhs = COND_EXPR::unary (ADDRESSOF, rhs); - pIcode->setAsgn(lhs, rhs); - break; + case iCALL: + case iCALLF: newCallHlIcode (pIcode); + break; - case iMOD: - rhs = COND_EXPR::boolOp (lhs, rhs, MOD); - if ( ll->testFlags(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 iDEC: rhs = idCondExpKte (1, 2); + rhs = boolCondExp (lhs, rhs, SUB); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iMOV: pIcode->setAsgn(lhs, rhs); - break; + case iDIV: + case iIDIV:/* should be signed div */ + rhs = boolCondExp (lhs, rhs, DIV); + if (pIcode->ic.ll.flg & B) + { + lhs = idCondExpReg (rAL, 0, &pProc->localId); + setRegDU (pIcode, rAL, E_DEF); + } + else + { + lhs = idCondExpReg (rAX, 0, &pProc->localId); + setRegDU (pIcode, rAX, E_DEF); + } + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iMUL: - rhs = COND_EXPR::boolOp (lhs, rhs, MUL); - lhs = COND_EXPR::id (*ll, LHS_OP, this, i, *pIcode, NONE); - pIcode->setAsgn(lhs, rhs); - break; + case iIMUL: rhs = boolCondExp (lhs, rhs, MUL); + lhs = idCondExp (pIcode, LHS_OP, pProc, i, pIcode, + NONE); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iNEG: - rhs = COND_EXPR::unary (NEGATION, lhs); - pIcode->setAsgn(lhs, rhs); - break; + case iINC: rhs = idCondExpKte (1, 2); + rhs = boolCondExp (lhs, rhs, ADD); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iNOT: - rhs = COND_EXPR::boolOp (NULL, rhs, NOT); - pIcode->setAsgn(lhs, rhs); - break; + case iLEA: rhs = unaryCondExp (ADDRESSOF, rhs); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iOR: - rhs = COND_EXPR::boolOp (lhs, rhs, OR); - pIcode->setAsgn(lhs, rhs); - break; + case iMOD: rhs = boolCondExp (lhs, rhs, MOD); + if (pIcode->ic.ll.flg & B) + { + lhs = idCondExpReg (rAH, 0, &pProc->localId); + setRegDU (pIcode, rAH, E_DEF); + } + else + { + lhs = idCondExpReg (rDX, 0, &pProc->localId); + setRegDU (pIcode, rDX, E_DEF); + } + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iPOP: pIcode->setUnary(HLI_POP, lhs); - break; + case iMOV: newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iPUSH: pIcode->setUnary(HLI_PUSH, lhs); - break; + case iMUL: rhs = boolCondExp (lhs, rhs, MUL); + lhs = idCondExp (pIcode, LHS_OP, pProc, i, pIcode, + NONE); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iRET: - case iRETF: pIcode->setUnary(HLI_RET, NULL); - break; + case iNEG: rhs = unaryCondExp (NEGATION, lhs); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iSHL: - rhs = COND_EXPR::boolOp (lhs, rhs, SHL); - pIcode->setAsgn(lhs, rhs); - break; + case iNOT: rhs = boolCondExp (NULL, rhs, NOT); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iSAR: /* signed */ - case iSHR: - rhs = COND_EXPR::boolOp (lhs, rhs, SHR); /* unsigned*/ - pIcode->setAsgn(lhs, rhs); - break; + case iOR: rhs = boolCondExp (lhs, rhs, OR); + newAsgnHlIcode (pIcode, lhs, rhs); + break; - case iSIGNEX: pIcode->setAsgn(lhs, rhs); - break; + case iPOP: newUnaryHlIcode (pIcode, HLI_POP, lhs); + break; - case iSUB: - rhs = COND_EXPR::boolOp (lhs, rhs, SUB); - pIcode->setAsgn(lhs, rhs); - break; + case iPUSH: newUnaryHlIcode (pIcode, HLI_PUSH, lhs); + break; - case iXCHG: - break; + case iRET: + case iRETF: newUnaryHlIcode (pIcode, HLI_RET, NULL); + break; - case iXOR: - rhs = COND_EXPR::boolOp (lhs, rhs, XOR); - pIcode->setAsgn(lhs, rhs); - break; + case iSHL: rhs = boolCondExp (lhs, rhs, SHL); + newAsgnHlIcode (pIcode, lhs, rhs); + break; + + case iSAR: /* signed */ + case iSHR: rhs = boolCondExp (lhs, rhs, SHR); /* unsigned*/ + newAsgnHlIcode (pIcode, lhs, rhs); + break; + + case iSIGNEX: newAsgnHlIcode (pIcode, lhs, rhs); + break; + + case iSUB: rhs = boolCondExp (lhs, rhs, SUB); + newAsgnHlIcode (pIcode, lhs, rhs); + break; + + case iXCHG: + break; + + case iXOR: rhs = boolCondExp (lhs, rhs, XOR); + newAsgnHlIcode (pIcode, lhs, rhs); + break; + } } + } } +void inverseCondOp (COND_EXPR **exp) /* 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. */ -COND_EXPR *COND_EXPR::inverse () const -{ - 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}; - COND_EXPR *res=0; - if (m_type == BOOLEAN_OP) - { - switch ( op() ) - { - case LESS_EQUAL: case LESS: case EQUAL: - case NOT_EQUAL: case GREATER: case GREATER_EQUAL: - res = this->clone(); - res->boolExpr.op = invCondOp[op()]; - return res; +{ + 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; - case AND: case OR: case XOR: case NOT: case ADD: - case SUB: case MUL: case DIV: case SHR: case SHL: case MOD: - return COND_EXPR::unary (NEGATION, this->clone()); + 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 DBL_AND: case DBL_OR: - // Binary::Create(invertop,lhs->inverse(),rhs->inverse()); - res = this->clone(); - res->boolExpr.op = invCondOp[op()]; - res->boolExpr.lhs=lhs()->inverse (); - res->boolExpr.rhs=rhs()->inverse (); - return res; - } /* eos */ + case AND: case OR: case XOR: case NOT: case ADD: + case SUB: case MUL: case DIV: case SHR: case SHL: case MOD: + *exp = unaryCondExp (NEGATION, *exp); + break; - } - else if (m_type == NEGATION) //TODO: memleak here - { - return expr.unaryExp->clone(); - } - return this->clone(); - /* other types are left unmodified */ + 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) + *exp = (*exp)->expr.unaryExp; + + /* other types are left unmodified */ } + +char *writeCall (PPROC tproc, PSTKFRAME args, PPROC pproc, Int *numLoc) /* 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 ostr; - ostr<name<<" ("; - for(const STKSYM &sym : args) +{ Int i; /* counter of # arguments */ + char *s, *condExp; + + s = (char*)allocMem (100 * sizeof(char)); + s[0] = '\0'; + sprintf (s, "%s (", tproc->name); + for (i = 0; i < args->csym; i++) { - ostr << walkCondExpr (sym.actual, pproc, numLoc); - if((&sym)!=&(args.back())) - ostr << ", "; + condExp = walkCondExpr (args->sym[i].actual, pproc, numLoc); + strcat (s, condExp); + if (i < (args->csym - 1)) + strcat (s, ", "); } - ostr << ")"; - return ostr.str(); + strcat (s, ")"); + return (s); } +char *writeJcond (HLTYPE h, PPROC pProc, Int *numLoc) /* Displays the output of a HLI_JCOND icode. */ -char *writeJcond (const HLTYPE &h, Function * pProc, int *numLoc) -{ - assert(h.expr()); +{ char *e; + memset (buf, ' ', sizeof(buf)); - buf[0] = '\0'; + buf[0] = '\0'; strcat (buf, "if "); - COND_EXPR *inverted=h.expr()->inverse(); - //inverseCondOp (&h.exp); - std::string e = walkCondExpr (inverted, pProc, numLoc); - delete inverted; - strcat (buf, e.c_str()); + inverseCondOp (&h.oper.exp); + e = walkCondExpr (h.oper.exp, pProc, numLoc); + strcat (buf, e); strcat (buf, " {\n"); - return (buf); + return (buf); } +char *writeJcondInv (HLTYPE h, PPROC pProc, Int *numLoc) /* 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) -{ +{ char *e; + memset (buf, ' ', sizeof(buf)); - buf[0] = '\0'; + buf[0] = '\0'; strcat (buf, "if "); - std::string e = walkCondExpr (h.expr(), pProc, numLoc); - strcat (buf, e.c_str()); + e = walkCondExpr (h.oper.exp, pProc, numLoc); + strcat (buf, e); strcat (buf, " {\n"); - return (buf); + return (buf); } -string AssignType::writeOut(Function *pProc, int *numLoc) -{ - ostringstream ostr; - ostr << walkCondExpr (lhs, pProc, numLoc); - ostr << " = "; - ostr << walkCondExpr (rhs, pProc, numLoc); - ostr << ";\n"; - return ostr.str(); -} -string CallType::writeOut(Function *pProc, int *numLoc) -{ - ostringstream ostr; - ostr << writeCall (proc, *args, pProc,numLoc); - ostr << ";\n"; - return ostr.str(); -} -string ExpType::writeOut(Function *pProc, int *numLoc) -{ - return walkCondExpr (v, pProc, numLoc); -} +char *write1HlIcode (HLTYPE h, PPROC pProc, Int *numLoc) /* 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. */ -string HLTYPE::write1HlIcode (Function * pProc, int *numLoc) -{ - string e; - ostringstream ostr; - HlTypeSupport *p = get(); - switch (opcode) - { - case HLI_ASSIGN: - return p->writeOut(pProc,numLoc); - case HLI_CALL: - return p->writeOut(pProc,numLoc); - case HLI_RET: - e = p->writeOut(pProc,numLoc); - if (! e.empty()) - ostr << "return (" << e << ");\n"; - break; - case HLI_POP: - ostr << "HLI_POP "; - ostr << p->writeOut(pProc,numLoc); - ostr << "\n"; - break; - case HLI_PUSH: - ostr << "HLI_PUSH "; - ostr << p->writeOut(pProc,numLoc); - ostr << "\n"; - break; +{ char *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); + strcat (buf, " = "); + e = walkCondExpr (h.oper.asgn.rhs, pProc, numLoc); + strcat (buf, e); + strcat (buf, ";\n"); + break; + case HLI_CALL: e = writeCall (h.oper.call.proc, h.oper.call.args, pProc, + numLoc); + strcat (buf, e); + strcat (buf, ";\n"); + break; + case HLI_RET: e = walkCondExpr (h.oper.exp, pProc, numLoc); + if (e[0] != '\0') + { + strcat (buf, "return ("); + strcat (buf, e); + strcat (buf, ");\n"); + } + break; + case HLI_POP: strcat (buf, "HLI_POP "); + e = walkCondExpr (h.oper.exp, pProc, numLoc); + strcat (buf, e); + strcat (buf, "\n"); + break; + case HLI_PUSH: strcat (buf, "HLI_PUSH "); + e = walkCondExpr (h.oper.exp, pProc, numLoc); + strcat (buf, e); + strcat (buf, "\n"); + break; } - return ostr.str(); + return (buf); } -//TODO: replace all "< (INDEX_BX_SI-1)" with machine_x86::lastReg - -//TODO: replace all >= INDEX_BX_SI with machine_x86::isRegExpression +Int power2 (Int i) +/* Returns the value of 2 to the power of i */ +{ + if (i == 0) + return (1); + return (2 << (i-1)); +} +void writeDU (PICODE pIcode, Int idx) /* Writes the registers/stack variables that are used and defined by this * instruction. */ -void ICODE::writeDU() -{ - int my_idx = loc_ip; +{ static char buf[100]; + Int i, j; + + memset (buf, ' ', sizeof(buf)); + buf[0] = '\0'; + for (i = 0; i < (INDEXBASE-1); i++) { - ostringstream ostr; - Machine_X86::writeRegVector(ostr,du.def); - if (!ostr.str().empty()) - printf ("Def (reg) = %s\n", ostr.str().c_str()); + if ((pIcode->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++) { - ostringstream ostr; - Machine_X86::writeRegVector(ostr,du.use); - if (!ostr.str().empty()) - printf ("Use (reg) = %s\n", ostr.str().c_str()); + if ((pIcode->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 (int i = 0; i < MAX_REGS_DEF; i++) - { - if (not du1.used(i)) - continue; - printf ("%d: du1[%d][] = ", my_idx, i); - for(auto j : du1.idx[i].uses) + printf ("# regs defined = %d\n", pIcode->du1.numRegsDef); + for (i = 0; i < MAX_REGS_DEF; i++) + if (pIcode->du1.idx[i][0] != 0) + { + printf ("%d: du1[%d][] = ", idx, i); + for (j = 0; j < MAX_USES; j++) { - printf ("%d ", j->loc_ip); + if (pIcode->du1.idx[i][j] == 0) + break; + printf ("%d ", pIcode->du1.idx[i][j]); } printf ("\n"); - } - + } + /* For HLI_CALL, print # parameter bytes */ - if (hl()->opcode == HLI_CALL) - printf ("# param bytes = %d\n", hl()->call.args->cb); + if (pIcode->ic.hl.opcode == HLI_CALL) + printf ("# param bytes = %d\n", pIcode->ic.hl.oper.call.args->cb); printf ("\n"); } + + +void freeHlIcode (PICODE icode, Int numIcodes) +/* Frees the storage allocated to h->hlIcode */ +{ Int i; + HLTYPE h; + + for (i = 0; i < numIcodes; i++) + { + h = icode[i].ic.hl; + switch (h.opcode) { + case HLI_ASSIGN: freeCondExpr (h.oper.asgn.lhs); + freeCondExpr (h.oper.asgn.rhs); + break; + case HLI_POP: case HLI_PUSH: + case HLI_JCOND: freeCondExpr (h.oper.exp); + break; + } + } +} + diff --git a/src/icode.cpp b/src/icode.cpp index ebb47fd..31d0d10 100644 --- a/src/icode.cpp +++ b/src/icode.cpp @@ -5,98 +5,139 @@ #include #include -#include "dcc.h" -#include "types.h" // Common types like uint8_t, etc +#include "types.h" // Common types like byte, etc #include "ast.h" // Some icode types depend on these #include "icode.h" +void *reallocVar(void *p, Int newsize); /* frontend.c !? */ #define ICODE_DELTA 25 // Amount to allocate for new chunk -ICODE::TypeFilter ICODE::select_high_level; -ICODE::TypeAndValidFilter ICODE::select_valid_high_level; + CIcodeRec::CIcodeRec() { + numIcode = 0; + alloc = 0; + icode = 0; // Initialise the pointer to 0 } +CIcodeRec::~CIcodeRec() +{ + if (icode) + { + free(icode); + } +} + +PICODE CIcodeRec::addIcode(PICODE pIcode) + /* 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); - back().loc_ip = size()-1; - return &back(); -} + PICODE resIcode; -void CIcodeRec::SetInBB(rCODE &rang, BB *pnewBB) -{ - for(ICODE &ic : rang) + if (numIcode == alloc) { - ic.setParent(pnewBB); + alloc += ICODE_DELTA; + icode = (PICODE)reallocVar(icode, alloc * sizeof(ICODE)); + memset (&icode[numIcode], 0, ICODE_DELTA * sizeof(ICODE)); + } + resIcode = (PICODE)memcpy (&icode[numIcode], pIcode, + sizeof(ICODE)); + numIcode++; + return (resIcode); } +PICODE CIcodeRec::GetFirstIcode() +{ + return icode; +} + +/* Don't need this; just pIcode++ since array is guaranteed to be contiguous +PICODE CIcodeRec::GetNextIcode(PICODE pCurIcode) +{ + int idx = pCurIcode - icode; // Current index + ASSERT(idx+1 < numIcode); + return &icode[idx+1]; +} +*/ + +boolT CIcodeRec::IsValid(PICODE pCurIcode) +{ + int idx = pCurIcode - icode; // Current index + return idx < numIcode; +} + +int CIcodeRec::GetNumIcodes() +{ + return numIcode; +} + +void CIcodeRec::SetInBB(int start, int end, struct _BB* pnewBB) +{ + for (int i = start; i <= end; i++) + icode[i].inBB = pnewBB; +} + +void CIcodeRec::SetImmediateOp(int ip, dword dw) +{ + icode[ip].ic.ll.immed.op = dw; +} + +void CIcodeRec::SetLlFlag(int ip, dword flag) +{ + icode[ip].ic.ll.flg |= flag; +} + +dword CIcodeRec::GetLlFlag(int ip) +{ + return icode[ip].ic.ll.flg; +} + +void CIcodeRec::ClearLlFlag(int ip, dword flag) +{ + icode[ip].ic.ll.flg &= (~flag); +} + +void CIcodeRec::SetLlInvalid(int ip, boolT fInv) +{ + icode[ip].invalid = fInv; +} + +dword CIcodeRec::GetLlLabel(int ip) +{ + return icode[ip].ic.ll.label; +} + +llIcode CIcodeRec::GetLlOpcode(int ip) +{ + return icode[ip].ic.ll.opcode; +} + + +boolT CIcodeRec::labelSrch(dword target, Int *pIndex) /* labelSrchRepl - Searches the icodes for instruction with label = target, and - replaces *pIndex with an icode index */ -bool CIcodeRec::labelSrch(uint32_t target, uint32_t &pIndex) + replaces *pIndex with an icode index */ { - iICODE location=labelSrch(target); - if(end()==location) - return false; - pIndex=location->loc_ip; - return true; -} -bool CIcodeRec::alreadyDecoded(uint32_t target) -{ - iICODE location=labelSrch(target); - if(end()==location) - return false; - return true; -} -CIcodeRec::iterator CIcodeRec::labelSrch(uint32_t target) -{ - return find_if(begin(),end(),[target](ICODE &l) -> bool {return l.ll()->label==target;}); -} -ICODE * CIcodeRec::GetIcode(int ip) -{ - assert(ip>=0 && ip=rAX) && (regi<=rTMP); -} -void LLOperand::addProcInformation(int param_count, uint32_t call_conv) -{ - proc.proc->cbParam = (int16_t)param_count; - proc.cb = param_count; - proc.proc->flg |= call_conv; + return &icode[ip]; } + + + + diff --git a/src/idioms.cpp b/src/idioms.cpp index e4a4003..90b661a 100644 --- a/src/idioms.cpp +++ b/src/idioms.cpp @@ -3,273 +3,1346 @@ * (C) Cristina Cifuentes ****************************************************************************/ -#include -#include -#include "idiom.h" -#include "idiom1.h" -#include "epilogue_idioms.h" -#include "call_idioms.h" -#include "mov_idioms.h" -#include "xor_idioms.h" -#include "neg_idioms.h" -#include "shift_idioms.h" -#include "arith_idioms.h" #include "dcc.h" -#include -#include +#include +#ifdef __DOSWIN__ +#include +#endif + + /***************************************************************************** - * JmpInst - Returns true if opcode is a conditional or unconditional jump + * JmpInst - Returns TRUE if opcode is a conditional or unconditional jump ****************************************************************************/ -bool LLInst::isJmpInst() +boolT JmpInst(llIcode opcode) { - switch (getOpcode()) - { - case iJMP: case iJMPF: case iJCXZ: - case iLOOP: case iLOOPE:case iLOOPNE: - 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: - return true; + switch (opcode) { + case iJMP: case iJMPF: case iJCXZ: + case iLOOP: case iLOOPE:case iLOOPNE: + 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: + return TRUE; } - return false; + return FALSE; } + +/***************************************************************************** +/* checkStkVars - Checks for PUSH SI + * [PUSH DI] + * or PUSH DI + * [PUSH SI] + * In which case, the stack variable flags are set + ****************************************************************************/ +static Int checkStkVars (PICODE pIcode, PICODE pEnd, PPROC pProc) +{ + /* Look for PUSH SI */ + if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) && + (pIcode->ic.ll.dst.regi == rSI)) + { + pProc->flg |= SI_REGVAR; + + /* Look for PUSH DI */ + if (++pIcode < pEnd && (pIcode->ic.ll.opcode == iPUSH) && + (pIcode->ic.ll.dst.regi == rDI)) + { + pProc->flg |= DI_REGVAR; + return 2; + } + else + return 1; + } + else if ((pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) && + (pIcode->ic.ll.dst.regi == rDI)) + { + pProc->flg |= DI_REGVAR; + + /* Look for PUSH SI */ + if ((++pIcode < pEnd) && (pIcode->ic.ll.opcode == iPUSH) && + (pIcode->ic.ll.dst.regi == rSI)) + { + pProc->flg |= SI_REGVAR; + return 2; + } + else + return 1; + } + else + return 0; +} + + +/***************************************************************************** + * idiom1 - HLL procedure prologue; Returns number of instructions matched. + * PUSH BP ==> ENTER immed, 0 + * MOV BP, SP and sets PROC_HLL flag + * [SUB SP, immed] + * [PUSH SI] + * [PUSH DI] + * - Second version: Push stack variables and then save BP + * PUSH BP + * PUSH SI + * [PUSH DI] + * MOV BP, SP + * - Third version: Stack variables + * [PUSH SI] + * [PUSH DI] + ****************************************************************************/ +static Int idiom1(PICODE pIcode, PICODE pEnd, PPROC pProc) +{ Int n; + + /* PUSH BP as first instruction of procedure */ + if ( !(pIcode->ic.ll.flg & I) && pIcode->ic.ll.src.regi == rBP) + { + /* MOV BP, SP as next instruction */ + if (++pIcode < pEnd && ! (pIcode->ic.ll.flg & (I | TARGET | CASE)) + && pIcode->ic.ll.opcode == iMOV && pIcode->ic.ll.dst.regi == rBP + && pIcode->ic.ll.src.regi == rSP) + { + pProc->args.minOff = 2; + pProc->flg |= PROC_IS_HLL; + + /* Look for SUB SP, immed */ + if ((++pIcode < pEnd) && + (pIcode->ic.ll.flg & (I | TARGET | CASE)) == I && + pIcode->ic.ll.opcode == iSUB && pIcode->ic.ll.dst.regi == rSP) + { + return (3 + checkStkVars (++pIcode, pEnd, pProc)); + } + else + return (2 + checkStkVars (pIcode, pEnd, pProc)); + } + + /* PUSH SI + * [PUSH DI] + * MOV BP, SP */ + else + { + n = checkStkVars (pIcode, pEnd, pProc); + if (n > 0) + { + /* Look for MOV BP, SP */ + pIcode += n; + if (pIcode < pEnd && + ! (pIcode->ic.ll.flg & (I | TARGET | CASE)) && + pIcode->ic.ll.opcode == iMOV && + pIcode->ic.ll.dst.regi == rBP && + pIcode->ic.ll.src.regi == rSP) + { + pProc->args.minOff = 2 + (n * 2); + return (2 + n); + } + else return 0; // Cristina: check this please! + } + else return 0; // Cristina: check this please! + } + } + + else + return (checkStkVars (pIcode, pEnd, pProc)); +} + + +/***************************************************************************** + * popStkVars - checks for + * [POP DI] + * [POP SI] + * or [POP SI] + * [POP DI] + ****************************************************************************/ +static void popStkVars (PICODE pIcode, PICODE pEnd, PPROC pProc) +{ + /* Match [POP DI] */ + if (pIcode->ic.ll.opcode == iPOP) + if ((pProc->flg & DI_REGVAR) && (pIcode->ic.ll.dst.regi == rDI)) + invalidateIcode (pIcode); + else if ((pProc->flg & SI_REGVAR) && (pIcode->ic.ll.dst.regi == rSI)) + invalidateIcode (pIcode); + + /* Match [POP SI] */ + if ((pIcode+1)->ic.ll.opcode == iPOP) + if ((pProc->flg & SI_REGVAR) && ((pIcode+1)->ic.ll.dst.regi == rSI)) + invalidateIcode (pIcode+1); + else if ((pProc->flg & DI_REGVAR) && ((pIcode+1)->ic.ll.dst.regi == rDI)) + invalidateIcode (pIcode+1); +} + + +/***************************************************************************** + * idiom2 - HLL procedure epilogue; Returns number of instructions matched. + * [POP DI] + * [POP SI] + * MOV SP, BP + * POP BP + * RET(F) + *****************************************************************************/ +static Int idiom2(PICODE pIcode, PICODE pEnd, Int ip, PPROC pProc) +{ PICODE nicode; + + /* Match MOV SP, BP */ + if (ip != 0 && ((pIcode->ic.ll.flg & I) != I) && + pIcode->ic.ll.dst.regi == rSP && pIcode->ic.ll.src.regi == rBP) + { + /* Get next icode, skip over holes in the icode array */ + nicode = pIcode + 1; + while (nicode->ic.ll.flg & NO_CODE) + nicode++; + + /* Match POP BP */ + if (nicode < pEnd && + ! (nicode->ic.ll.flg & (I | TARGET | CASE)) && + nicode->ic.ll.opcode == iPOP && + nicode->ic.ll.dst.regi == rBP) + { + nicode++; + + /* Match RET(F) */ + if (nicode < pEnd && + ! (nicode->ic.ll.flg & (I | TARGET | CASE)) && + (nicode->ic.ll.opcode == iRET || + nicode->ic.ll.opcode == iRETF)) + { + popStkVars (pIcode-2, pEnd, pProc); + return 2; + } + } + } + return 0; +} + + + +/***************************************************************************** + * idiom3 - C calling convention. + * CALL(F) proc_X + * ADD SP, immed + * Eg: CALL proc_X + * ADD SP, 6 + * => pProc->cbParam = immed + * Special case: when the call is at the end of the procedure, + * sometimes the stack gets restored by a MOV sp, bp. + * Need to flag the procedure in these cases. + * Used by compilers to restore the stack when invoking a procedure using + * the C calling convention. + ****************************************************************************/ +static Int idiom3(PICODE pIcode, PICODE pEnd) +{ + /* Match ADD SP, immed */ + if ((++pIcode < pEnd) && (pIcode->ic.ll.flg & I) && + (pIcode->ic.ll.opcode == iADD) && (pIcode->ic.ll.dst.regi == rSP)) + return (pIcode->ic.ll.immed.op); + else if ((pIcode->ic.ll.opcode == iMOV) && (pIcode->ic.ll.dst.regi == rSP) + && (pIcode->ic.ll.src.regi == rBP)) + (pIcode-1)->ic.ll.flg |= REST_STK; + return 0; +} + + +/***************************************************************************** + * idiom 17 - C calling convention. + * CALL(F) xxxx + * POP reg + * [POP reg] reg in {AX, BX, CX, DX} + * Eg: CALL proc_X + * POP cx + * POP cx (4 bytes of arguments) + * => pProc->cbParam = # pops * 2 + * Found in Turbo C when restoring the stack for a procedure that uses the + * C calling convention. Used to restore the stack of 2 or 4 bytes args. + ****************************************************************************/ +static Int idiom17 (PICODE pIcode, PICODE pEnd) +{ Int i = 0; /* Count on # pops */ + byte regi; + + /* Match POP reg */ + if ((++pIcode < pEnd) && (pIcode->ic.ll.opcode == iPOP)) + { + regi = pIcode->ic.ll.dst.regi; + if ((regi >= rAX) && (regi <= rBX)) + i++; + while ((++pIcode)->ic.ll.opcode == iPOP) + { + if (pIcode->ic.ll.dst.regi == regi) + i++; + else + break; + } + return (i * 2); + } + return (0); +} + + +/***************************************************************************** + * idiom4 - Pascal calling convention. + * RET(F) immed + * ==> pProc->cbParam = immed + * sets CALL_PASCAL flag + * - Second version: check for optional pop of stack vars + * [POP DI] + * [POP SI] + * POP BP + * RET(F) [immed] + * - Third version: pop stack vars + * [POP DI] + * [POP SI] + * RET(F) [immed] + ****************************************************************************/ +static void idiom4 (PICODE pIcode, PICODE pEnd, PPROC pProc) +{ + /* Check for [POP DI] + * [POP SI] */ + popStkVars (pIcode-3, pEnd, pProc); + + /* Check for POP BP */ + if (((pIcode-1)->ic.ll.opcode == iPOP) && + (((pIcode-1)->ic.ll.flg & I) != I) && + ((pIcode-1)->ic.ll.dst.regi == rBP)) + invalidateIcode (pIcode-1); + else + popStkVars (pIcode-2, pEnd, pProc); + + /* Check for RET(F) immed */ + if (pIcode->ic.ll.flg & I) + { + pProc->cbParam = (int16)pIcode->ic.ll.immed.op; + pProc->flg |= CALL_PASCAL; + } +} + + +/***************************************************************************** + * idiom5 - Long addition. + * ADD reg/stackOff, reg/stackOff + * ADC reg/stackOff, reg/stackOff + * Eg: ADD ax, [bp-4] + * ADC dx, [bp-2] + * => dx:ax = dx:ax + [bp-2]:[bp-4] + * Found in Borland Turbo C code. + * Commonly used idiom for long addition. + ****************************************************************************/ +static boolT idiom5 (PICODE pIcode, PICODE pEnd) +{ + if (pIcode < pEnd) + if ((pIcode+1)->ic.ll.opcode == iADC) + return (TRUE); + return (FALSE); +} + + +/***************************************************************************** + * idiom6 - Long substraction. + * SUB reg/stackOff, reg/stackOff + * SBB reg/stackOff, reg/stackOff + * Eg: SUB ax, [bp-4] + * SBB dx, [bp-2] + * => dx:ax = dx:ax - [bp-2]:[bp-4] + * Found in Borland Turbo C code. + * Commonly used idiom for long substraction. + ****************************************************************************/ +static boolT idiom6 (PICODE pIcode, PICODE pEnd) +{ + if (pIcode < pEnd) + if ((pIcode+1)->ic.ll.opcode == iSBB) + return (TRUE); + return (FALSE); +} + + +/***************************************************************************** + * idiom7 - Assign zero + * XOR reg/stackOff, reg/stackOff + * Eg: XOR ax, ax + * => ax = 0 + * Found in Borland Turbo C and Microsoft C code. + ****************************************************************************/ +static boolT idiom7 (PICODE pIcode) +{ PMEM dst, src; + + dst = &pIcode->ic.ll.dst; + src = &pIcode->ic.ll.src; + if (dst->regi == 0) /* global variable */ + { + if ((dst->segValue == src->segValue) && (dst->off == src->off)) + return (TRUE); + } + else if (dst->regi < INDEXBASE) /* register */ + { + if (dst->regi == src->regi) + return (TRUE); + } + else if ((dst->off) && (dst->seg == rSS) && (dst->regi == INDEXBASE + 6)) + /* offset from BP */ + { + if ((dst->off == src->off) && (dst->seg == src->seg) && + (dst->regi == src->regi)) + return (TRUE); + } + return (FALSE); +} + + +/***************************************************************************** + * idiom21 - Assign long kte with high part zero + * XOR regH, regH + * MOV regL, kte + * => regH:regL = kte + * Eg: XOR dx, dx + * MOV ax, 3 + * => dx:ax = 3 + * Note: only the following valid combinations are available: + * dx:ax + * cx:bx + * Found in Borland Turbo C code. + ****************************************************************************/ +static boolT idiom21 (PICODE picode, PICODE pend) +{ PMEM dst, src; + + dst = &picode->ic.ll.dst; + src = &picode->ic.ll.src; + if (((picode+1) < pend) && ((picode+1)->ic.ll.flg & I)) + { + if ((dst->regi == src->regi) && (dst->regi > 0) && + (dst->regi < INDEXBASE)) + { + if ((dst->regi == rDX) && ((picode+1)->ic.ll.dst.regi == rAX)) + return (TRUE); + if ((dst->regi == rCX) && ((picode+1)->ic.ll.dst.regi == rBX)) + return (TRUE); + } + } + return (FALSE); +} + + +/***************************************************************************** + * idiom8 - Shift right by 1 (signed long ops) + * SAR reg, 1 + * RCR reg, 1 + * Eg: SAR dx, 1 + * RCR ax, 1 + * => dx:ax = dx:ax >> 1 (dx:ax are signed long) + * Found in Microsoft C code for long signed variable shift right. + ****************************************************************************/ +static boolT idiom8 (PICODE pIcode, PICODE pEnd) +{ + if (pIcode < pEnd) + { + if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.immed.op == 1)) + if (((pIcode+1)->ic.ll.opcode == iRCR) && + (((pIcode+1)->ic.ll.flg & I) == I) && + ((pIcode+1)->ic.ll.immed.op == 1)) + return (TRUE); + } + return (FALSE); +} + + +/***************************************************************************** + * idiom 15 - Shift left by n + * SHL reg, 1 + * SHL reg, 1 + * [...] + * [SHL reg, 1] + * Eg: SHL ax, 1 + * SHL ax, 1 + * => ax = ax << 2 + * Found in Borland Turbo C code to index an array (array multiplication) + ****************************************************************************/ +static Int idiom15 (PICODE picode, PICODE pend) +{ Int n = 1; + byte regi; + + if (picode < pend) + { + /* Match SHL reg, 1 */ + if ((picode->ic.ll.flg & I) && (picode->ic.ll.immed.op == 1)) + { + regi = picode->ic.ll.dst.regi; + while (1) + { + if (((picode+n) < pend) && + ((picode+n)->ic.ll.opcode == iSHL) && + ((picode+n)->ic.ll.flg & I) && + ((picode+n)->ic.ll.immed.op == 1) && + ((picode+n)->ic.ll.dst.regi == regi)) + n++; + else + break; + } + } + } + if (n > 1) + return (n); + else + return (0); +} + + +/***************************************************************************** + * idiom12 - Shift left long by 1 + * SHL reg, 1 + * RCL reg, 1 + * Eg: SHL ax, 1 + * RCL dx, 1 + * => dx:ax = dx:ax << 1 + * Found in Borland Turbo C code for long variable shift left. + ****************************************************************************/ +static boolT idiom12 (PICODE pIcode, PICODE pEnd) +{ + if (pIcode < pEnd) + { + if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.immed.op == 1)) + if (((pIcode+1)->ic.ll.opcode == iRCL) && + (((pIcode+1)->ic.ll.flg & I) == I) && + ((pIcode+1)->ic.ll.immed.op == 1)) + return (TRUE); + } + return (FALSE); +} + + +/***************************************************************************** + * idiom9 - Shift right by 1 (unsigned long ops) + * SHR reg, 1 + * RCR reg, 1 + * Eg: SHR dx, 1 + * RCR ax, 1 + * => dx:ax = dx:ax >> 1 (dx:ax are unsigned long) + * Found in Microsoft C code for long unsigned variable shift right. + ****************************************************************************/ +static boolT idiom9 (PICODE pIcode, PICODE pEnd) +{ + if (pIcode < pEnd) + { + if (((pIcode->ic.ll.flg & I) == I) && (pIcode->ic.ll.immed.op == 1)) + if (((pIcode+1)->ic.ll.opcode == iRCR) && + (((pIcode+1)->ic.ll.flg & I) == I) && + ((pIcode+1)->ic.ll.immed.op == 1)) + return (TRUE); + } + return (FALSE); +} + + +/***************************************************************************** + * idiom10 - Jump if not equal to 0 + * OR reg, reg + * JNE labX + * Eg: OR ax, ax + * JNE labX + * => HLI_JCOND (ax != 0) labX + * Note: we also check that these instructions are not followed by + * CMP reg, kte + * JE lab + * because this is most likely a long conditional equality test. + * Found in Borland Turbo C. + ****************************************************************************/ +static boolT idiom10old (PICODE pIcode, PICODE pEnd) +{ + if (pIcode < pEnd) + { + /* Check OR reg, reg */ + if (((pIcode->ic.ll.flg & I) != I) && + (pIcode->ic.ll.src. regi > 0) && + (pIcode->ic.ll.src.regi < INDEXBASE) && + (pIcode->ic.ll.src.regi == pIcode->ic.ll.dst.regi)) + if ((pIcode+3) < pEnd) + { + if (((pIcode+1)->ic.ll.opcode == iJNE) && + ((pIcode+2)->ic.ll.opcode != iCMP) && + ((pIcode+3)->ic.ll.opcode != iJE)) + return (TRUE); + } + else /* at the end of the procedure */ + if (((pIcode+1) < pEnd) && ((pIcode+1)->ic.ll.opcode == iJNE)) + return (TRUE); + } + return (FALSE); +} + + +/***************************************************************************** + * idiom10 - Jump if not equal to 0 + * OR reg, reg + * JNE labX + * Eg: OR ax, ax + * JNE labX + * => CMP reg 0 + * JNE labX + * This instruction is NOT converted into the equivalent high-level + * instruction "HLI_JCOND (reg != 0) labX" because we do not know yet if + * it forms part of a long register conditional test. It is therefore + * modified to simplify the analysis. + * Found in Borland Turbo C. + ****************************************************************************/ +static void idiom10 (PICODE pIcode, PICODE pEnd) +{ + if (pIcode < pEnd) + { + /* Check OR reg, reg */ + if (((pIcode->ic.ll.flg & I) != I) && + (pIcode->ic.ll.src. regi > 0) && + (pIcode->ic.ll.src.regi < INDEXBASE) && + (pIcode->ic.ll.src.regi == pIcode->ic.ll.dst.regi)) + if (((pIcode+1) < pEnd) && ((pIcode+1)->ic.ll.opcode == iJNE)) + { + pIcode->ic.ll.opcode = iCMP; + pIcode->ic.ll.flg |= I; + pIcode->ic.ll.immed.op = 0; + pIcode->du.def = 0; + pIcode->du1.numRegsDef = 0; + } + } +} + + +/***************************************************************************** + * idiom 13 - Word assign + * MOV regL, mem + * MOV regH, 0 + * Eg: MOV al, [bp-2] + * MOV ah, 0 + * => MOV ax, [bp-2] + * Found in Borland Turbo C, used for multiplication and division of + * byte operands (ie. they need to be extended to words). + ****************************************************************************/ +static byte idiom13 (PICODE picode, PICODE pend) +{ byte regi; + + if (picode < pend) + { + /* Check for regL */ + regi = picode->ic.ll.dst.regi; + if (((picode->ic.ll.flg & I) != I) && (regi >= rAL) && (regi <= rBH)) + { + /* Check for MOV regH, 0 */ + if (((picode+1)->ic.ll.opcode == iMOV) && + ((picode+1)->ic.ll.flg & I) && + ((picode+1)->ic.ll.immed.op == 0)) + { + if ((picode+1)->ic.ll.dst.regi == (regi + 4)) + return (regi - rAL + rAX); + } + } + } + return (0); +} + + +/***************************************************************************** + * idiom 14 - Long word assign + * MOV regL, mem/reg + * XOR regH, regH + * Eg: MOV ax, di + * XOR dx, dx + * => MOV dx:ax, di + * Note: only the following combinations are allowed: + * dx:ax + * cx:bx + * this is to remove the possibility of making errors in situations + * like this: + * MOV dx, offH + * MOV ax, offL + * XOR cx, cx + * Found in Borland Turbo C, used for division of unsigned integer + * operands. + ****************************************************************************/ +static boolT idiom14 (PICODE picode, PICODE pend, byte *regL, byte *regH) +{ + if (picode < pend) + { + /* Check for regL */ + *regL = picode->ic.ll.dst.regi; + if (((picode->ic.ll.flg & I) != I) && ((*regL == rAX) || (*regL ==rBX))) + { + /* Check for XOR regH, regH */ + if (((picode+1)->ic.ll.opcode == iXOR) && + (((picode+1)->ic.ll.flg & I) != I)) + { + *regH = (picode+1)->ic.ll.dst.regi; + if (*regH == (picode+1)->ic.ll.src.regi) + { + if ((*regL == rAX) && (*regH == rDX)) + return (TRUE); + if ((*regL == rBX) && (*regH == rCX)) + return (TRUE); + } + } + } + } + return (FALSE); +} + +/***************************************************************************** + * idiom11 - Negate long integer + * NEG regH + * NEG regL + * SBB regH, 0 + * Eg: NEG dx + * NEG ax + * SBB dx, 0 + * => dx:ax = - dx:ax + * Found in Borland Turbo C. + ****************************************************************************/ +static boolT idiom11 (PICODE pIcode, PICODE pEnd) +{ condId type; /* type of argument */ + + if ((pIcode + 2) < pEnd) + { + type = idType (pIcode, DST); + if ((type != CONSTANT) && (type != OTHER)) + { + /* Check NEG reg/mem + * SBB reg/mem, 0*/ + if (((pIcode+1)->ic.ll.opcode == iNEG) && + ((pIcode+2)->ic.ll.opcode == iSBB)) + switch (type) { + case GLOB_VAR: if (((pIcode+2)->ic.ll.dst.segValue == + pIcode->ic.ll.dst.segValue) && + ((pIcode+2)->ic.ll.dst.off == + pIcode->ic.ll.dst.off)) + return (TRUE); + break; + case REGISTER: if ((pIcode+2)->ic.ll.dst.regi == + pIcode->ic.ll.dst.regi) + return (TRUE); + break; + case PARAM: + case LOCAL_VAR: if ((pIcode+2)->ic.ll.dst.off == + pIcode->ic.ll.dst.off) + return (TRUE); + break; + } + } + } + return (FALSE); +} + + +/***************************************************************************** + * idiom 16: Bitwise negation + * NEG reg + * SBB reg, reg + * INC reg + * => ASGN reg, !reg + * Eg: NEG ax + * SBB ax, ax + * INC ax + * => ax = !ax + * Found in Borland Turbo C when negating bitwise. + ****************************************************************************/ +static boolT idiom16 (PICODE picode, PICODE pend) +{ byte regi; + + if ((picode+2) < pend) + { + regi = picode->ic.ll.dst.regi; + if ((regi >= rAX) && (regi < INDEXBASE)) + { + if (((picode+1)->ic.ll.opcode == iSBB) && + ((picode+2)->ic.ll.opcode == iINC)) + if (((picode+1)->ic.ll.dst.regi == + ((picode+1)->ic.ll.src.regi)) && + ((picode+1)->ic.ll.dst.regi == regi) && + ((picode+2)->ic.ll.dst.regi == regi)) + return (TRUE); + } + } + return (FALSE); +} + + +/***************************************************************************** + * idiom 18: Post-increment or post-decrement in a conditional jump + * MOV reg, var (including register variables) + * INC var or DEC var + * CMP var, Y + * JX label + * => HLI_JCOND (var++ X Y) + * Eg: MOV ax, si + * INC si + * CMP ax, 8 + * JL labX + * => HLI_JCOND (si++ < 8) + * Found in Borland Turbo C. Intrinsic to C languages. + ****************************************************************************/ +static boolT idiom18 (PICODE picode, PICODE pend, PPROC pproc) +{ boolT type = 0; /* type of variable: 1 = reg-var, 2 = local */ + byte regi; /* register of the MOV */ + + /* Get variable */ + if (picode->ic.ll.dst.regi == 0) /* global variable */ + /* not supported yet */ ; + else if (picode->ic.ll.dst.regi < INDEXBASE) /* register */ + { + if ((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) + type = 1; + else if ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR)) + type = 1; + } + else if (picode->ic.ll.dst.off) /* local variable */ + type = 2; + else /* indexed */ + /* not supported yet */ ; + + /* Check previous instruction for a MOV */ + if (type == 1) /* register variable */ + { + if (((picode-1)->ic.ll.opcode == iMOV) && + ((picode-1)->ic.ll.src.regi == picode->ic.ll.dst.regi)) + { + regi = (picode-1)->ic.ll.dst.regi; + if ((regi > 0) && (regi < INDEXBASE)) + { + if ((picode < pend) && ((picode+1) < pend) && + ((picode+1)->ic.ll.opcode == iCMP) && + ((picode+1)->ic.ll.dst.regi == regi) && + (((picode+2)->ic.ll.opcode >= iJB) && + ((picode+2)->ic.ll.opcode < iJCXZ))) + return (TRUE); + } + } + } + else if (type == 2) /* local */ + { + if (((picode-1)->ic.ll.opcode == iMOV) && + ((picode-1)->ic.ll.src.off == picode->ic.ll.dst.off)) + { + regi = (picode-1)->ic.ll.dst.regi; + if ((regi > 0) && (regi < INDEXBASE)) + { + if ((picode < pend) && ((picode+1) < pend) && + ((picode+1)->ic.ll.opcode == iCMP) && + ((picode+1)->ic.ll.dst.regi == regi) && + (((picode+2)->ic.ll.opcode >= iJB) && + ((picode+2)->ic.ll.opcode < iJCXZ))) + return (TRUE); + } + } + } + return (FALSE); +} + + +/***************************************************************************** + * idiom 19: pre-increment or pre-decrement in conditional jump, comparing + * against 0. + * INC var or DEC var (including register vars) + * JX lab JX lab + * => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0) + * Eg: INC [bp+4] + * JG lab2 + * => HLI_JCOND (++[bp+4] > 0) + * Found in Borland Turbo C. Intrinsic to C language. + ****************************************************************************/ +static boolT idiom19 (PICODE picode, PICODE pend, PPROC pproc) +{ + if (picode->ic.ll.dst.regi == 0) /* global variable */ + /* not supported yet */ ; + else if (picode->ic.ll.dst.regi < INDEXBASE) /* register */ + { + if (((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) || + ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR))) + if ((picode < pend) && ((picode+1)->ic.ll.opcode >= iJB) && + ((picode+1)->ic.ll.opcode < iJCXZ)) + return (TRUE); + } + else if (picode->ic.ll.dst.off) /* stack variable */ + { + if ((picode < pend) && ((picode+1)->ic.ll.opcode >= iJB) && + ((picode+1)->ic.ll.opcode < iJCXZ)) + return (TRUE); + } + else /* indexed */ + /* not supported yet */ ; + return (FALSE); +} + + +/***************************************************************************** + * idiom20: Pre increment/decrement in conditional expression (compares + * against a register, variable or constant different than 0). + * INC var or DEC var (including register vars) + * MOV reg, var MOV reg, var + * CMP reg, Y CMP reg, Y + * JX lab JX lab + * => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y) + * Eg: INC si (si is a register variable) + * MOV ax, si + * CMP ax, 2 + * JL lab4 + * => HLI_JCOND (++si < 2) + * Found in Turbo C. Intrinsic to C language. + ****************************************************************************/ +static boolT idiom20 (PICODE picode, PICODE pend, PPROC pproc) +{ boolT type = 0; /* type of variable: 1 = reg-var, 2 = local */ + byte regi; /* register of the MOV */ + + /* Get variable */ + if (picode->ic.ll.dst.regi == 0) /* global variable */ + /* not supported yet */ ; + else if (picode->ic.ll.dst.regi < INDEXBASE) /* register */ + { + if ((picode->ic.ll.dst.regi == rSI) && (pproc->flg & SI_REGVAR)) + type = 1; + else if ((picode->ic.ll.dst.regi == rDI) && (pproc->flg & DI_REGVAR)) + type = 1; + } + else if (picode->ic.ll.dst.off) /* local variable */ + type = 2; + else /* indexed */ + /* not supported yet */ ; + + /* Check previous instruction for a MOV */ + if (type == 1) /* register variable */ + { + if ((picode < pend) && ((picode+1)->ic.ll.opcode == iMOV) && + ((picode+1)->ic.ll.src.regi == picode->ic.ll.dst.regi)) + { + regi = (picode+1)->ic.ll.dst.regi; + if ((regi > 0) && (regi < INDEXBASE)) + { + if (((picode+1) < pend) && ((picode+2) < pend) && + ((picode+2)->ic.ll.opcode == iCMP) && + ((picode+2)->ic.ll.dst.regi == regi) && + (((picode+3)->ic.ll.opcode >= iJB) && + ((picode+3)->ic.ll.opcode < iJCXZ))) + return (TRUE); + } + } + } + else if (type == 2) /* local */ + { + if ((picode < pend) && ((picode+1)->ic.ll.opcode == iMOV) && + ((picode+1)->ic.ll.src.off == picode->ic.ll.dst.off)) + { + regi = (picode+1)->ic.ll.dst.regi; + if ((regi > 0) && (regi < INDEXBASE)) + { + if (((picode+1) < pend) && ((picode+2) < pend) && + ((picode+2)->ic.ll.opcode == iCMP) && + ((picode+2)->ic.ll.dst.regi == regi) && + (((picode+3)->ic.ll.opcode >= iJB) && + ((picode+3)->ic.ll.opcode < iJCXZ))) + return (TRUE); + } + } + } + return (FALSE); +} + + /***************************************************************************** * findIdioms - translates LOW_LEVEL icode idioms into HIGH_LEVEL icodes. ****************************************************************************/ -void Function::findIdioms() -{ - // int ip; /* Index to current icode */ - iICODE pEnd, pIcode; /* Pointers to end of BB and current icodes */ - int16_t delta; +void findIdioms (PPROC pProc) +{ Int ip; /* Index to current icode */ + PICODE pEnd, pIcode; /* Pointers to end of BB and current icodes */ + int16 delta; + COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */ + COND_EXPR *exp; /* Pointer to temporal expression */ + Int idx; /* Index into local identifier table */ + byte regH, regL; /* High and low registers for long word reg */ - pIcode = Icode.begin(); - pEnd = Icode.end(); - Idiom1 i01(this); - Idiom2 i02(this); - Idiom3 i03(this); - Idiom4 i04(this); - Idiom13 i13(this); - Idiom14 i14(this); - Idiom17 i17(this); - // xor idioms - Idiom21 i21(this); - Idiom7 i07(this); - // or idioms - Idiom10 i10(this); - // neg idiom - Idiom11 i11(this); - Idiom16 i16(this); - // shift idioms - Idiom8 i08(this); - Idiom12 i12(this); - Idiom15 i15(this); - Idiom9 i09(this); - //arithmetic idioms - Idiom5 i05(this); - Idiom6 i06(this); - Idiom18 i18(this); - Idiom19 i19(this); - Idiom20 i20(this); - struct is_valid + pIcode = pProc->Icode.GetFirstIcode(); + pEnd = pIcode + pProc->Icode.GetNumIcodes(); + ip = 0; + + while (pIcode < pEnd) { - bool operator()(ICODE &z) { return z.valid();} - }; - typedef boost::filter_iterator ifICODE; - while (pIcode != pEnd) - { - switch (pIcode->ll()->getOpcode()) - { - case iDEC: case iINC: - if (i18.match(pIcode)) - advance(pIcode,i18.action()); - else if (i19.match(pIcode)) - advance(pIcode,i19.action()); - else if (i20.match(pIcode)) - advance(pIcode,i20.action()); + switch (pIcode->ic.ll.opcode) { + case iDEC: case iINC: + if (idiom18 (pIcode, pEnd, pProc)) + { + lhs = idCondExp (pIcode-1, SRC, pProc, ip, pIcode, E_USE); + if (pIcode->ic.ll.opcode == iDEC) + lhs = unaryCondExp (POST_DEC, lhs); + else + lhs = unaryCondExp (POST_INC, lhs); + rhs = idCondExp (pIcode+1, SRC, pProc, ip, pIcode+2, E_USE); + exp = boolCondExp (lhs, rhs, + condOpJCond[(pIcode+2)->ic.ll.opcode - iJB]); + newJCondHlIcode (pIcode+2, exp); + invalidateIcode (pIcode-1); + invalidateIcode (pIcode); + invalidateIcode (pIcode+1); + pIcode += 3; + ip += 2; + } + else if (idiom19 (pIcode, pEnd, pProc)) + { + lhs = idCondExp (pIcode, DST, pProc, ip, pIcode+1, E_USE); + if (pIcode->ic.ll.opcode == iDEC) + lhs = unaryCondExp (PRE_DEC, lhs); + else + lhs = unaryCondExp (PRE_INC, lhs); + rhs = idCondExpKte (0, 2); + exp = boolCondExp (lhs, rhs, + condOpJCond[(pIcode+1)->ic.ll.opcode - iJB]); + newJCondHlIcode (pIcode+1, exp); + invalidateIcode (pIcode); + pIcode += 2; + ip++; + } + else if (idiom20 (pIcode, pEnd, pProc)) + { + lhs = idCondExp (pIcode+1, SRC, pProc, ip, pIcode, E_USE); + if (pIcode->ic.ll.opcode == iDEC) + lhs = unaryCondExp (PRE_DEC, lhs); + else + lhs = unaryCondExp (PRE_INC, lhs); + rhs = idCondExp (pIcode+2, SRC, pProc, ip, pIcode+3, E_USE); + exp = boolCondExp (lhs, rhs, + condOpJCond[(pIcode+3)->ic.ll.opcode - iJB]); + newJCondHlIcode (pIcode+3, exp); + invalidateIcode (pIcode); + invalidateIcode (pIcode+1); + invalidateIcode (pIcode+2); + pIcode += 3; + ip += 2; + } + else + pIcode++; + break; + + case iPUSH: /* Idiom 1 */ + if ((! (pProc->flg & PROC_HLL)) && + (idx = idiom1 (pIcode, pEnd, pProc))) + { + pProc->flg |= PROC_HLL; + for ( ; idx > 0; idx--) + { + invalidateIcode (pIcode++); + ip++; + } + ip--; + } else pIcode++; break; - case iPUSH: - { - /* Idiom 1 */ - //TODO: add other push idioms. - advance(pIcode,i01(pIcode)); - break; - } - - case iMOV: - { - if (i02.match(pIcode)) /* Idiom 2 */ - advance(pIcode,i02.action()); - else if (i14.match(pIcode)) /* Idiom 14 */ - advance(pIcode,i14.action()); - else if (i13.match(pIcode)) /* Idiom 13 */ - advance(pIcode,i13.action()); + case iMOV: /* Idiom 2 */ + if (idx = idiom2(pIcode, pEnd, ip, pProc)) + { + invalidateIcode (pIcode); + invalidateIcode (pIcode+1); + pIcode += 3; + ip += 2; + } + else if (idiom14 (pIcode, pEnd, ®L, ®H)) /* Idiom 14 */ + { + idx = newLongRegId (&pProc->localId, TYPE_LONG_SIGN, + regH, regL, ip); + lhs = idCondExpLongIdx (idx); + setRegDU (pIcode, regH, E_DEF); + rhs = idCondExp (pIcode, SRC, pProc, ip, pIcode, NONE); + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode+1); + pIcode += 2; + ip++; + } + else if (idx = idiom13 (pIcode, pEnd)) /* Idiom 13 */ + { + lhs = idCondExpReg (idx, 0, &pProc->localId); + setRegDU (pIcode, idx, E_DEF); + pIcode->du1.numRegsDef--; /* prev byte reg def */ + rhs = idCondExp (pIcode, SRC, pProc, ip, pIcode, NONE); + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode+1); + pIcode += 2; + ip++; + } else pIcode++; break; - } case iCALL: case iCALLF: - /* Check for library functions that return a long register. - * Propagate this result */ - if (pIcode->ll()->src().proc.proc != 0) - if ((pIcode->ll()->src().proc.proc->flg & PROC_ISLIB) && - (pIcode->ll()->src().proc.proc->flg & PROC_IS_FUNC)) - { - if ((pIcode->ll()->src().proc.proc->retVal.type==TYPE_LONG_SIGN) - || (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN)) - localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, pIcode/*ip*/); - } + /* Check for library functions that return a long register. + * Propagate this result */ + if (pIcode->ic.ll.immed.proc.proc != 0) + if ((pIcode->ic.ll.immed.proc.proc->flg & PROC_ISLIB) && + (pIcode->ic.ll.immed.proc.proc->flg & PROC_IS_FUNC)) + { + if ((pIcode->ic.ll.immed.proc.proc->retVal.type==TYPE_LONG_SIGN) + || (pIcode->ic.ll.immed.proc.proc->retVal.type == + TYPE_LONG_UNSIGN)) + newLongRegId(&pProc->localId, TYPE_LONG_SIGN, rDX, rAX, ip); + } - /* Check for idioms */ - if (i03.match(pIcode)) /* idiom 3 */ - advance(pIcode,i03.action()); - else if (i17.match(pIcode)) /* idiom 17 */ - advance(pIcode,i17.action()); + /* Check for idioms */ + if (idx = idiom3(pIcode, pEnd)) /* idiom 3 */ + { + if (pIcode->ic.ll.flg & I) + { + (pIcode->ic.ll.immed.proc.proc)->cbParam = (int16)idx; + pIcode->ic.ll.immed.proc.cb = idx; + (pIcode->ic.ll.immed.proc.proc)->flg |= CALL_C; + pIcode++; + invalidateIcode (pIcode++); + ip++; + } + } + else if (idx = idiom17 (pIcode, pEnd)) /* idiom 17 */ + { + if (pIcode->ic.ll.flg & I) + { + (pIcode->ic.ll.immed.proc.proc)->cbParam = (int16)idx; + pIcode->ic.ll.immed.proc.cb = idx; + (pIcode->ic.ll.immed.proc.proc)->flg |= CALL_C; + ip += idx/2 - 1; + pIcode++; + for (idx /= 2; idx > 0; idx--) + invalidateIcode (pIcode++); + } + } else pIcode++; break; - case iRET: /* Idiom 4 */ - case iRETF: - advance(pIcode,i04(pIcode)); + case iRET: /* Idiom 4 */ + case iRETF: + idiom4 (pIcode, pEnd, pProc); + pIcode++; break; case iADD: /* Idiom 5 */ - advance(pIcode,i05(pIcode)); + if (idiom5 (pIcode, pEnd)) + { + lhs = idCondExpLong (&pProc->localId, DST, pIcode, LOW_FIRST, + ip, USE_DEF, 1); + rhs = idCondExpLong (&pProc->localId, SRC, pIcode, LOW_FIRST, + ip, E_USE, 1); + exp = boolCondExp (lhs, rhs, ADD); + newAsgnHlIcode (pIcode, lhs, exp); + invalidateIcode (pIcode + 1); + pIcode++; + ip++; + } + pIcode++; break; case iSAR: /* Idiom 8 */ - advance(pIcode,i08(pIcode)); + if (idiom8 (pIcode, pEnd)) + { + idx = newLongRegId (&pProc->localId, TYPE_LONG_SIGN, + pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,ip); + lhs = idCondExpLongIdx (idx); + setRegDU (pIcode, (pIcode+1)->ic.ll.dst.regi, USE_DEF); + rhs = idCondExpKte (1, 2); + exp = boolCondExp (lhs, rhs, SHR); + newAsgnHlIcode (pIcode, lhs, exp); + invalidateIcode (pIcode + 1); + pIcode++; + ip++; + } + pIcode++; break; case iSHL: - if (i15.match(pIcode)) /* idiom 15 */ - advance(pIcode,i15.action()); - else if (i12.match(pIcode)) /* idiom 12 */ - advance(pIcode,i12.action()); + if (idx = idiom15 (pIcode, pEnd)) /* idiom 15 */ + { + lhs = idCondExpReg (pIcode->ic.ll.dst.regi, + pIcode->ic.ll.flg & NO_SRC_B, + &pProc->localId); + rhs = idCondExpKte (idx, 2); + exp = boolCondExp (lhs, rhs, SHL); + newAsgnHlIcode (pIcode, lhs, exp); + pIcode++; + for (idx-- ; idx > 0; idx--) + { + invalidateIcode (pIcode++); + ip++; + } + } + else if (idiom12 (pIcode, pEnd)) /* idiom 12 */ + { + idx = newLongRegId (&pProc->localId, TYPE_LONG_UNSIGN, + (pIcode+1)->ic.ll.dst.regi, pIcode->ic.ll.dst.regi,ip); + lhs = idCondExpLongIdx (idx); + setRegDU (pIcode, (pIcode+1)->ic.ll.dst.regi, USE_DEF); + rhs = idCondExpKte (1, 2); + exp = boolCondExp (lhs, rhs, SHL); + newAsgnHlIcode (pIcode, lhs, exp); + invalidateIcode (pIcode + 1); + pIcode += 2; + ip++; + } else pIcode++; break; case iSHR: /* Idiom 9 */ - advance(pIcode,i09(pIcode)); - break; - - case iSUB: /* Idiom 6 */ - advance(pIcode,i06(pIcode)); - break; - - case iOR: /* Idiom 10 */ - advance(pIcode,i10(pIcode)); - break; - - case iNEG: /* Idiom 11 */ - if (i11.match(pIcode)) - advance(pIcode,i11.action()); - else if (i16.match(pIcode)) - advance(pIcode,i16.action()); - else - pIcode++; - break; - - case iNOP: - (pIcode++)->invalidate(); - break; - - case iENTER: /* ENTER is equivalent to init PUSH bp */ - if (pIcode == Icode.begin()) //ip == 0 + if (idiom9 (pIcode, pEnd)) { - flg |= (PROC_HLL | PROC_IS_HLL); + idx = newLongRegId (&pProc->localId, TYPE_LONG_UNSIGN, + pIcode->ic.ll.dst.regi, (pIcode+1)->ic.ll.dst.regi,ip); + lhs = idCondExpLongIdx (idx); + setRegDU (pIcode, (pIcode+1)->ic.ll.dst.regi, USE_DEF); + rhs = idCondExpKte (1, 2); + exp = boolCondExp (lhs, rhs, SHR); + newAsgnHlIcode (pIcode, lhs, exp); + invalidateIcode (pIcode + 1); + pIcode++; + ip++; } pIcode++; break; + case iSUB: /* Idiom 6 */ + if (idiom6 (pIcode, pEnd)) + { + lhs = idCondExpLong (&pProc->localId, DST, pIcode, LOW_FIRST, + ip, USE_DEF, 1); + rhs = idCondExpLong (&pProc->localId, SRC, pIcode, LOW_FIRST, + ip, E_USE, 1); + exp = boolCondExp (lhs, rhs, SUB); + newAsgnHlIcode (pIcode, lhs, exp); + invalidateIcode (pIcode + 1); + pIcode++; + ip++; + } + pIcode++; + break; + + case iOR: /* Idiom 10 */ + idiom10 (pIcode, pEnd); + pIcode++; + break; + + case iNEG: /* Idiom 11 */ + if (idiom11 (pIcode, pEnd)) + { + lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, + ip, USE_DEF, 1); + rhs = unaryCondExp (NEGATION, lhs); + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode+1); + invalidateIcode (pIcode+2); + pIcode += 3; + ip += 2; + } + else if (idiom16 (pIcode, pEnd)) + { + lhs = idCondExpReg (pIcode->ic.ll.dst.regi, pIcode->ic.ll.flg, + &pProc->localId); + rhs = copyCondExp (lhs); + rhs = unaryCondExp (NEGATION, lhs); + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode+1); + invalidateIcode (pIcode+2); + pIcode += 3; + ip += 2; + } + else + pIcode++; + break; + + case iNOP: + invalidateIcode (pIcode++); + break; + + case iENTER: /* ENTER is equivalent to init PUSH bp */ + if (ip == 0) + pProc->flg |= (PROC_HLL | PROC_IS_HLL); + pIcode++; + break; + case iXOR: /* Idiom 7 */ - if (i21.match(pIcode)) - advance(pIcode,i21.action()); - else if (i07.match(pIcode)) - advance(pIcode,i07.action()); - else - ++pIcode; + if (idiom21 (pIcode, pEnd)) + { + lhs = idCondExpLong (&pProc->localId, DST, pIcode, + HIGH_FIRST, ip, E_DEF, 1); + rhs = idCondExpKte ((pIcode+1)->ic.ll.immed.op , 4); + newAsgnHlIcode (pIcode, lhs, rhs); + pIcode->du.use = 0; /* clear register used in iXOR */ + invalidateIcode (pIcode+1); + pIcode++; + ip++; + } + else if (idiom7 (pIcode)) + { + lhs = idCondExp (pIcode, DST, pProc, ip, pIcode, NONE); + rhs = idCondExpKte (0, 2); + newAsgnHlIcode (pIcode, lhs, rhs); + pIcode->du.use = 0; /* clear register used in iXOR */ + pIcode->ic.ll.flg |= I; + } + pIcode++; break; default: pIcode++; } + ip++; } /* Check if number of parameter bytes match their calling convention */ - if ((flg & PROC_HLL) && (!args.empty())) + if ((pProc->flg & PROC_HLL) && (pProc->args.csym)) { - args.m_minOff += (flg & PROC_FAR ? 4 : 2); - delta = args.maxOff - args.m_minOff; - if (cbParam != delta) - { - cbParam = delta; - flg |= (CALL_MASK & CALL_UNKNOWN); - } - } + pProc->args.minOff += (pProc->flg & PROC_FAR ? 4 : 2); + delta = pProc->args.maxOff - pProc->args.minOff; + if (pProc->cbParam != delta) + { + pProc->cbParam = delta; + pProc->flg |= (CALL_MASK & CALL_UNKNOWN); + } + } } +void bindIcodeOff (PPROC pProc) /* Sets up the TARGET flag for jump target addresses, and * binds jump target addresses to icode offsets. */ -void Function::bindIcodeOff() -{ +{ Int i, j; /* idx into icode array */ + PICODE pIcode; /* ptr icode array */ + dword *p; /* for case table */ - iICODE pIcode; /* ptr icode array */ - if (Icode.empty()) /* No Icode */ - return; - pIcode = Icode.begin(); + if (! pProc->Icode.GetNumIcodes()) /* No Icode */ + return; + pIcode = pProc->Icode.GetFirstIcode(); /* Flag all jump targets for BB construction and disassembly stage 2 */ - for(ICODE &c : Icode) // TODO: use filtered here - { - LLInst *ll=c.ll(); - if (ll->testFlags(I) && ll->isJmpInst()) + for (i = 0; i < pProc->Icode.GetNumIcodes(); i++) + if ((pIcode[i].ic.ll.flg & I) && JmpInst(pIcode[i].ic.ll.opcode)) { - iICODE loc=Icode.labelSrch(ll->src().getImm2()); - if (loc!=Icode.end()) - loc->ll()->setFlags(TARGET); + if (pProc->Icode.labelSrch(pIcode[i].ic.ll.immed.op, &j)) + { + pIcode[j].ic.ll.flg |= TARGET; + } } - } /* Finally bind jump targets to Icode offsets. Jumps for which no label - * is found (no code at dest. of jump) are simply left unlinked and + * is found (no code at dest. of jump) are simply left unlinked and * flagged as going nowhere. */ - //for (pIcode = Icode.begin(); pIcode!= Icode.end(); pIcode++) - for(ICODE &icode : Icode) - { - LLInst *ll=icode.ll(); - if (not ll->isJmpInst()) - continue; - if (ll->testFlags(I) ) + pIcode = pProc->Icode.GetFirstIcode(); + for (i = 0; i < pProc->Icode.GetNumIcodes(); i++) + if (JmpInst(pIcode[i].ic.ll.opcode)) { - uint32_t found; - if (! Icode.labelSrch(ll->src().getImm2(), found)) - ll->setFlags( NO_LABEL ); - else - ll->replaceSrc(LLOperand::CreateImm2(found)); - + if (pIcode[i].ic.ll.flg & I) + { + if (! pProc->Icode.labelSrch(pIcode[i].ic.ll.immed.op, + (Int *)&pIcode[i].ic.ll.immed.op)) + pIcode[i].ic.ll.flg |= NO_LABEL; + } + else if (pIcode[i].ic.ll.flg & SWITCH) + { + p = pIcode[i].ic.ll.caseTbl.entries; + for (j = 0; j < pIcode[i].ic.ll.caseTbl.numEntries; j++, p++) + pProc->Icode.labelSrch(*p, (Int *)p); + } } - else if (ll->testFlags(SWITCH) ) - { - /* for case table */ - for (uint32_t &p : ll->caseTbl2) - Icode.labelSrch(p, p); // for each entry in caseTable replace it with target insn Idx - } - } } -/** Performs idioms analysis, and propagates long operands, if any */ -void Function::lowLevelAnalysis () + +void lowLevelAnalysis (PPROC pProc) +/* Performs idioms analysis, and propagates long operands, if any */ { + /* Idiom analysis - sets up some flags and creates some HIGH_LEVEL + * icodes */ + findIdioms (pProc); - findIdioms(); // Idiom analysis - sets up some flags and creates some HIGH_LEVEL icodes - propLong(); // Propagate HIGH_LEVEL idiom information for long operands + /* Propagate HIGH_LEVEL idiom information for long operands */ + propLong (pProc); } diff --git a/src/idioms/arith_idioms.cpp b/src/idioms/arith_idioms.cpp deleted file mode 100644 index 3359dd9..0000000 --- a/src/idioms/arith_idioms.cpp +++ /dev/null @@ -1,314 +0,0 @@ -#include "dcc.h" -#include "arith_idioms.h" -using namespace std; - -/***************************************************************************** - * idiom5 - Long addition. - * ADD reg/stackOff, reg/stackOff - * ADC reg/stackOff, reg/stackOff - * Eg: ADD ax, [bp-4] - * ADC dx, [bp-2] - * => dx:ax = dx:ax + [bp-2]:[bp-4] - * Found in Borland Turbo C code. - * Commonly used idiom for long addition. - ****************************************************************************/ -bool Idiom5::match(iICODE pIcode) -{ - if(distance(pIcode,m_end)<2) - return false; - m_icodes[0]=pIcode++; - m_icodes[1]=pIcode++; - if (m_icodes[1]->ll()->match(iADC)) - return true; - return false; -} - -int Idiom5::action() -{ - COND_EXPR *rhs,*lhs,*expr; - lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll()); - rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll()); - expr = COND_EXPR::boolOp (lhs, rhs, ADD); - m_icodes[0]->setAsgn(lhs, expr); - m_icodes[1]->invalidate(); - return 2; - -} - -/***************************************************************************** - * idiom6 - Long substraction. - * SUB reg/stackOff, reg/stackOff - * SBB reg/stackOff, reg/stackOff - * Eg: SUB ax, [bp-4] - * SBB dx, [bp-2] - * => dx:ax = dx:ax - [bp-2]:[bp-4] - * Found in Borland Turbo C code. - * Commonly used idiom for long substraction. - ****************************************************************************/ -bool Idiom6::match(iICODE pIcode) -{ - if(distance(pIcode,m_end)<2) - return false; - m_icodes[0]=pIcode++; - m_icodes[1]=pIcode++; - if (m_icodes[1]->ll()->match(iSBB)) - return true; - return false; -} - -int Idiom6::action() -{ - COND_EXPR *rhs,*lhs,*expr; - lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], LOW_FIRST, m_icodes[0], USE_DEF, *m_icodes[1]->ll()); - rhs = COND_EXPR::idLong (&m_func->localId, SRC, m_icodes[0], LOW_FIRST, m_icodes[0], eUSE, *m_icodes[1]->ll()); - expr = COND_EXPR::boolOp (lhs, rhs, SUB); - m_icodes[0]->setAsgn(lhs, expr); - m_icodes[1]->invalidate(); - return 2; - -} - - -/***************************************************************************** - * idiom 18: Post-increment or post-decrement in a conditional jump - * Used - * 0 MOV reg, var (including register variables) - * 1 INC var or DEC var <------------------------- input point - * 2 CMP var, Y - * 3 JX label - * => HLI_JCOND (var++ X Y) - * Eg: MOV ax, si - * INC si - * CMP ax, 8 - * JL labX - * => HLI_JCOND (si++ < 8) - * Found in Borland Turbo C. Intrinsic to C languages. - ****************************************************************************/ -bool Idiom18::match(iICODE picode) -{ - if(picode==m_func->Icode.begin()) - return false; - if(std::distance(picode,m_end)<3) - return false; - --picode; // - - for(int i=0; i<4; ++i) - m_icodes[i] =picode++; - - m_is_dec = m_icodes[1]->ll()->match(iDEC); - int type = -1; /* type of variable: 1 = reg-var, 2 = local */ - uint8_t regi; /* register of the MOV */ - - /* Get variable */ - if (m_icodes[1]->ll()->dst.regi == 0) /* global variable */ - { - /* not supported yet */ - type = 0; - } - else if ( m_icodes[1]->ll()->dst.isReg() ) /* register */ - { - if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR)) - type = 1; - else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR)) - type = 1; - } - else if (m_icodes[1]->ll()->dst.off) /* local variable */ - type = 2; - else /* indexed */ - { - type=3; - /* not supported yet */ - printf("Unsupported idiom18 type: indexed"); - } - - switch(type) - { - case 0: // global - printf("Unsupported idiom18 type: global variable"); - break; - case 1: /* register variable */ - /* Check previous instruction for a MOV */ - if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->dst.regi)) - { - regi = m_icodes[0]->ll()->dst.regi; - if ( m_icodes[0]->ll()->dst.isReg() ) - { - if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) && - m_icodes[3]->ll()->conditionalJump() ) - return true; - } - } - break; - case 2: /* local */ - if (m_icodes[0]->ll()->match(iMOV) && (m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->dst.off)) - { - regi = m_icodes[0]->ll()->dst.regi; - if ( m_icodes[0]->ll()->dst.isReg() ) - { - if ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) && - m_icodes[3]->ll()->conditionalJump() ) - return true; - } - } - break; - case 3: // indexed - printf("Unsupported idiom18 type: indexed"); - break; - } - return false; -} - -int Idiom18::action() // action length -{ - COND_EXPR *rhs, *lhs; /* Pointers to left and right hand side exps */ - COND_EXPR *expr; - lhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[1], *m_icodes[1], eUSE); - lhs = COND_EXPR::unary ( m_is_dec ? POST_DEC : POST_INC, lhs); - rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[1], *m_icodes[3], eUSE); - expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]); - m_icodes[3]->setJCond(expr); - - m_icodes[0]->invalidate(); - m_icodes[1]->invalidate(); - m_icodes[2]->invalidate(); - return 3; -} - -/***************************************************************************** - * idiom 19: pre-increment or pre-decrement in conditional jump, comparing against 0. - * [INC | DEC] var (including register vars) - * JX lab JX lab - * => HLI_JCOND (++var X 0) or HLI_JCOND (--var X 0) - * Eg: INC [bp+4] - * JG lab2 - * => HLI_JCOND (++[bp+4] > 0) - * Found in Borland Turbo C. Intrinsic to C language. - ****************************************************************************/ -bool Idiom19::match(iICODE picode) -{ - if(std::distance(picode,m_end)<2) - return false; - - for(int i=0; i<2; ++i) - m_icodes[i] =picode++; - m_is_dec = m_icodes[0]->ll()->match(iDEC); - if (m_icodes[0]->ll()->dst.regi == 0) /* global variable */ - /* not supported yet */ ; - else if ( m_icodes[0]->ll()->dst.isReg() ) /* register */ - { - // if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) || - // ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR))) - if (m_icodes[1]->ll()->conditionalJump()) - return true; - } - else if (m_icodes[0]->ll()->dst.off) /* stack variable */ - { - if ( m_icodes[1]->ll()->conditionalJump() ) - return true; - } - else /* indexed */ - /* not supported yet */ ; - return false; -} -int Idiom19::action() -{ - COND_EXPR *lhs,*rhs,*expr; - lhs = COND_EXPR::id (*m_icodes[1]->ll(), DST, m_func, m_icodes[0], *m_icodes[1], eUSE); - lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs); - rhs = COND_EXPR::idKte (0, 2); - expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[1]->ll()->getOpcode() - iJB]); - m_icodes[1]->setJCond(expr); - m_icodes[0]->invalidate(); - return 2; -} - -/***************************************************************************** - * idiom20: Pre increment/decrement in conditional expression (compares - * against a register, variable or constant different than 0). - * INC var or DEC var (including register vars) - * MOV reg, var MOV reg, var - * CMP reg, Y CMP reg, Y - * JX lab JX lab - * => HLI_JCOND (++var X Y) or HLI_JCOND (--var X Y) - * Eg: INC si (si is a register variable) - * MOV ax, si - * CMP ax, 2 - * JL lab4 - * => HLI_JCOND (++si < 2) - * Found in Turbo C. Intrinsic to C language. - ****************************************************************************/ -bool Idiom20::match(iICODE picode) -{ - uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */ - uint8_t regi; /* register of the MOV */ - if(std::distance(picode,m_end)<4) - return false; - for(int i=0; i<4; ++i) - m_icodes[i] =picode++; - - m_is_dec = m_icodes[0]->ll()->match(iDEC); - - LLOperand &ll_dest(m_icodes[0]->ll()->dst); - /* Get variable */ - if (ll_dest.regi == 0) /* global variable */ - { - /* not supported yet */ ; - } - else if ( ll_dest.isReg() ) /* register */ - { - if ((ll_dest.regi == rSI) && (m_func->flg & SI_REGVAR)) - type = 1; - else if ((ll_dest.regi == rDI) && (m_func->flg & DI_REGVAR)) - type = 1; - } - else if (ll_dest.off) /* local variable */ - type = 2; - else /* indexed */ - { - printf("idiom20 : Unsupported type [indexed]\n"); - /* not supported yet */ ; - } - - /* Check previous instruction for a MOV */ - if (type == 1) /* register variable */ - { - if (m_icodes[1]->ll()->match(iMOV) && - (m_icodes[1]->ll()->src().regi == ll_dest.regi)) - { - regi = m_icodes[1]->ll()->dst.regi; - if ( m_icodes[1]->ll()->dst.isReg() ) - { - if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) && - m_icodes[3]->ll()->conditionalJump()) - return true; - } - } - } - else if (type == 2) /* local */ - { - if ( m_icodes[0]->ll()->match(iMOV) && - (m_icodes[1]->ll()->src().off == ll_dest.off)) - { - regi = m_icodes[1]->ll()->dst.regi; - if ( m_icodes[1]->ll()->dst.isReg() ) - { - if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) && - m_icodes[3]->ll()->conditionalJump()) - return true; - } - } - } - return false; -} -int Idiom20::action() -{ - COND_EXPR *lhs,*rhs,*expr; - lhs = COND_EXPR::id (*m_icodes[1]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], eUSE); - lhs = COND_EXPR::unary (m_is_dec ? PRE_DEC : PRE_INC, lhs); - rhs = COND_EXPR::id (*m_icodes[2]->ll(), SRC, m_func, m_icodes[0], *m_icodes[3], eUSE); - expr = COND_EXPR::boolOp (lhs, rhs, condOpJCond[m_icodes[3]->ll()->getOpcode() - iJB]); - m_icodes[3]->setJCond(expr); - for(int i=0; i<3; ++i) - m_icodes[i]->invalidate(); - return 4; -} diff --git a/src/idioms/call_idioms.cpp b/src/idioms/call_idioms.cpp deleted file mode 100644 index 20c8567..0000000 --- a/src/idioms/call_idioms.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "dcc.h" -#include "call_idioms.h" -using namespace std; -/***************************************************************************** - * idiom3 - C calling convention. - * CALL(F) proc_X - * ADD SP, immed - * Eg: CALL proc_X - * ADD SP, 6 - * => pProc->cbParam = immed - * Special case: when the call is at the end of the procedure, - * sometimes the stack gets restored by a MOV sp, bp. - * Need to flag the procedure in these cases. - * Used by compilers to restore the stack when invoking a procedure using - * the C calling convention. - ****************************************************************************/ -bool Idiom3::match(iICODE picode) -{ - if(distance(picode,m_end)<2) - return false; - m_param_count=0; - /* Match ADD SP, immed */ - for(int i=0; i<2; ++i) - m_icodes[i] = picode++; - if ( m_icodes[1]->ll()->testFlags(I) && m_icodes[1]->ll()->match(iADD,rSP)) - { - m_param_count = m_icodes[1]->ll()->src().getImm2(); - return true; - } - else if (m_icodes[1]->ll()->match(iMOV,rSP,rBP)) - { - m_icodes[0]->ll()->setFlags(REST_STK); - return true; - } - return 0; -} -int Idiom3::action() -{ - if (m_icodes[0]->ll()->testFlags(I) ) - { - m_icodes[0]->ll()->src().addProcInformation(m_param_count,CALL_C); - } - else - { - printf("Indirect call at idiom3\n"); - } - m_icodes[1]->invalidate(); - return 2; -} - - -/***************************************************************************** - * idiom 17 - C calling convention. - * CALL(F) xxxx - * POP reg - * [POP reg] reg in {AX, BX, CX, DX} - * Eg: CALL proc_X - * POP cx - * POP cx (4 bytes of arguments) - * => pProc->cbParam = # pops * 2 - * Found in Turbo C when restoring the stack for a procedure that uses the - * C calling convention. Used to restore the stack of 2 or 4 bytes args. - ****************************************************************************/ -bool Idiom17::match(iICODE picode) -{ - if(distance(picode,m_end)<2) - return false; - m_param_count=0; /* Count on # pops */ - m_icodes.clear(); - - /* Match ADD SP, immed */ - for(int i=0; i<2; ++i) - m_icodes.push_back(picode++); - uint8_t regi; - - /* Match POP reg */ - if (m_icodes[1]->ll()->match(iPOP)) - { - int i=0; - regi = m_icodes[1]->ll()->dst.regi; - if ((regi >= rAX) && (regi <= rBX)) - i++; - - while (picode != m_end && picode->ll()->match(iPOP)) - { - if (picode->ll()->dst.regi != regi) - break; - i++; - m_icodes.push_back(picode++); - } - m_param_count = i*2; - } - return m_param_count!=0; -} -int Idiom17::action() -{ - if (m_icodes[0]->ll()->testFlags(I)) - { - m_icodes[0]->ll()->src().addProcInformation(m_param_count,CALL_C); - for(size_t idx=1; idxinvalidate(); - } - } - // TODO : it's a calculated call - else - { - printf("Indirect call at idiom17\n"); - } - return m_icodes.size(); -} diff --git a/src/idioms/epilogue_idioms.cpp b/src/idioms/epilogue_idioms.cpp deleted file mode 100644 index 3218e60..0000000 --- a/src/idioms/epilogue_idioms.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "dcc.h" -#include "epilogue_idioms.h" - -/***************************************************************************** - * popStkVars - checks for - * [POP DI] - * [POP SI] - * or [POP SI] - * [POP DI] - ****************************************************************************/ -void EpilogIdiom::popStkVars(iICODE pIcode) -{ - // TODO : only process SI-DI DI-SI pairings, no SI-SI, DI-DI like it's now - /* Match [POP DI] */ - if (pIcode->ll()->match(iPOP)) - { - if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI)) - m_icodes.push_front(pIcode); - else if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI)) - m_icodes.push_front(pIcode); - } - ++pIcode; - if(pIcode==m_end) - return; - /* Match [POP SI] */ - if (pIcode->ll()->match(iPOP)) - { - if ((m_func->flg & SI_REGVAR) && pIcode->ll()->match(rSI)) - m_icodes.push_front(pIcode); - else if ((m_func->flg & DI_REGVAR) && pIcode->ll()->match(rDI)) - m_icodes.push_front(pIcode); - } -} - - -/***************************************************************************** - * idiom2 - HLL procedure epilogue; Returns number of instructions matched. - * [POP DI] - * [POP SI] - * MOV SP, BP - * POP BP - * RET(F) - *****************************************************************************/ -bool Idiom2::match(iICODE pIcode) -{ - iICODE nicode; - if(pIcode==m_func->Icode.begin()) // pIcode->loc_ip == 0 - return false; - if ( pIcode->ll()->testFlags(I) || (not pIcode->ll()->match(rSP,rBP)) ) - return false; - if(distance(pIcode,m_end)<3) - return false; - /* Matched MOV SP, BP */ - m_icodes.clear(); - m_icodes.push_back(pIcode); - /* Get next icode, skip over holes in the icode array */ - nicode = ++iICODE(pIcode); - while (nicode->ll()->testFlags(NO_CODE) && (nicode != m_end)) - { - nicode++; - } - if(nicode == m_end) - return false; - - if (nicode->ll()->match(iPOP,rBP) && ! (nicode->ll()->testFlags(I | TARGET | CASE)) ) - { - m_icodes.push_back(nicode++); // Matched POP BP - - /* Match RET(F) */ - if ( nicode != m_end && - !(nicode->ll()->testFlags(I | TARGET | CASE)) && - (nicode->ll()->match(iRET) || nicode->ll()->match(iRETF)) - ) - { - m_icodes.push_back(nicode); // Matched RET - advance(pIcode,-2); // move back before our start - popStkVars (pIcode); // and add optional pop di/si to m_icodes - return true; - } - } - return false; -} -int Idiom2::action() -{ - for(size_t idx=0; idxinvalidate(); - return 3; - -} - -/***************************************************************************** - * idiom4 - Pascal calling convention. - * RET(F) immed - * ==> pProc->cbParam = immed - * sets CALL_PASCAL flag - * - Second version: check for optional pop of stack vars - * [POP DI] - * [POP SI] - * POP BP - * RET(F) [immed] - * - Third version: pop stack vars - * [POP DI] - * [POP SI] - * RET(F) [immed] - ****************************************************************************/ -bool Idiom4::match(iICODE pIcode) -{ - m_param_count = 0; - /* Check for [POP DI] - * [POP SI] */ - if(distance(m_func->Icode.begin(),pIcode)>=3) - { - iICODE search_at(pIcode); - advance(search_at,-3); - popStkVars(search_at); - } - if(pIcode != m_func->Icode.begin()) - { - iICODE prev1 = --iICODE(pIcode); - /* Check for POP BP */ - if (prev1->ll()->match(iPOP,rBP) && not prev1->ll()->testFlags(I) ) - m_icodes.push_back(prev1); - else if(prev1!=m_func->Icode.begin()) - { - iICODE search_at(pIcode); - advance(search_at,-2); - popStkVars (search_at); - } - } - - /* Check for RET(F) immed */ - if (pIcode->ll()->testFlags(I) ) - { - m_param_count = (int16_t)pIcode->ll()->src().getImm2(); - return true; - } - return false; -} -int Idiom4::action() -{ - if( ! m_icodes.empty()) // if not an empty RET[F] N - { - for(size_t idx=0; idxinvalidate(); - } - if(m_param_count) - { - m_func->cbParam = (int16_t)m_param_count; - m_func->flg |= CALL_PASCAL; - } - return 1; -} - diff --git a/src/idioms/idiom1.cpp b/src/idioms/idiom1.cpp deleted file mode 100644 index 60e496b..0000000 --- a/src/idioms/idiom1.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#include "idiom1.h" -#include "dcc.h" - -/***************************************************************************** -/* checkStkVars - Checks for PUSH SI - * [PUSH DI] - * or PUSH DI - * [PUSH SI] - * In which case, the stack variable flags are set - ****************************************************************************/ -int Idiom1::checkStkVars (iICODE pIcode) -{ - /* Look for PUSH SI */ - int si_matched=0; - int di_matched=0; - if(pIcode==m_end) - return 0; - if (pIcode->ll()->match(iPUSH,rSI)) - { - si_matched = 1; - ++pIcode; - if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rDI)) // Look for PUSH DI - di_matched = 1; - } - else if (pIcode->ll()->match(iPUSH,rDI)) - { - di_matched = 1; - ++pIcode; - if ((pIcode != m_end) && pIcode->ll()->match(iPUSH,rSI)) // Look for PUSH SI - si_matched = 1; - } - m_func->flg |= (si_matched ? SI_REGVAR : 0) | (di_matched ? DI_REGVAR : 0); - return si_matched+di_matched; -} -/***************************************************************************** - * idiom1 - HLL procedure prologue; Returns number of instructions matched. - * PUSH BP ==> ENTER immed, 0 - * MOV BP, SP and sets PROC_HLL flag - * [SUB SP, immed] - * [PUSH SI] - * [PUSH DI] - * - Second version: Push stack variables and then save BP - * PUSH BP - * PUSH SI - * [PUSH DI] - * MOV BP, SP - * - Third version: Stack variables - * [PUSH SI] - * [PUSH DI] - ****************************************************************************/ -bool Idiom1::match(iICODE picode) -{ - //uint8_t type = 0; /* type of variable: 1 = reg-var, 2 = local */ - //uint8_t regi; /* register of the MOV */ - if(m_func->flg & PROC_HLL) - return false; - if(picode==m_end) - return false; - //int n; - m_icodes.clear(); - m_min_off = 0; - /* PUSH BP as first instruction of procedure */ - if ( (not picode->ll()->testFlags(I)) && picode->ll()->src().regi == rBP) - { - m_icodes.push_back( picode++ ); // insert iPUSH - if(picode==m_end) - return false; - /* MOV BP, SP as next instruction */ - if ( !picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iMOV ,rBP,rSP) ) - { - m_icodes.push_back( picode++ ); // insert iMOV - if(picode==m_end) - return false; - m_min_off = 2; - - /* Look for SUB SP, immed */ - if ( - picode->ll()->testFlags(I | TARGET | CASE) && picode->ll()->match(iSUB,rSP) - ) - { - m_icodes.push_back( picode++ ); // insert iSUB - int n = checkStkVars (picode); // find iPUSH si [iPUSH di] - for(int i=0; i 0) - { - for(int i=0; ill()->testFlags(I | TARGET | CASE) && - picode->ll()->match(iMOV,rBP,rSP)) - { - m_icodes.push_back(picode); - m_min_off = 2 + (n * 2); - } - else - return false; // Cristina: check this please! - } - else - return false; // Cristina: check this please! - } - } - else // push di [push si] / push si [push di] - { - size_t n = checkStkVars (picode); - for(int i=0; iinvalidate(); - } - m_func->flg |= PROC_HLL; - if(0!=m_min_off) - { - m_func->args.m_minOff = m_min_off; - m_func->flg |= PROC_IS_HLL; - } - return m_icodes.size(); -} diff --git a/src/idioms/mov_idioms.cpp b/src/idioms/mov_idioms.cpp deleted file mode 100644 index 5dae4f7..0000000 --- a/src/idioms/mov_idioms.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "dcc.h" -#include "mov_idioms.h" -using namespace std; - -/***************************************************************************** - * idiom 14 - Long uint16_t assign - * MOV regL, mem/reg - * XOR regH, regH - * Eg: MOV ax, di - * XOR dx, dx - * => MOV dx:ax, di - * Note: only the following combinations are allowed: - * dx:ax - * cx:bx - * this is to remove the possibility of making errors in situations - * like this: - * MOV dx, offH - * MOV ax, offL - * XOR cx, cx - * Found in Borland Turbo C, used for division of unsigned integer - * operands. - ****************************************************************************/ - -bool Idiom14::match(iICODE pIcode) -{ - if(distance(pIcode,m_end)<2) - return false; - m_icodes[0]=pIcode++; - m_icodes[1]=pIcode++; - /* Check for regL */ - m_regL = m_icodes[0]->ll()->dst.regi; - if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX))) - { - /* Check for XOR regH, regH */ - if (m_icodes[1]->ll()->match(iXOR) && not m_icodes[1]->ll()->testFlags(I)) - { - m_regH = m_icodes[1]->ll()->dst.regi; - if (m_regH == m_icodes[1]->ll()->src().getReg2()) - { - if ((m_regL == rAX) && (m_regH == rDX)) - return true; - if ((m_regL == rBX) && (m_regH == rCX)) - return true; - } - } - } - return false; -} -int Idiom14::action() -{ - int idx; - COND_EXPR *lhs,*rhs; - idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, m_regH, m_regL, m_icodes[0]); - lhs = COND_EXPR::idLongIdx (idx); - m_icodes[0]->setRegDU( m_regH, eDEF); - rhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE); - m_icodes[0]->setAsgn(lhs, rhs); - m_icodes[1]->invalidate(); - return 2; -} - - -/***************************************************************************** - * idiom 13 - uint16_t assign - * MOV regL, mem - * MOV regH, 0 - * Eg: MOV al, [bp-2] - * MOV ah, 0 - * => MOV ax, [bp-2] - * Found in Borland Turbo C, used for multiplication and division of - * uint8_t operands (ie. they need to be extended to words). - ****************************************************************************/ -bool Idiom13::match(iICODE pIcode) -{ - if(distance(pIcode,m_end)<2) - return false; - m_icodes[0]=pIcode++; - m_icodes[1]=pIcode++; - m_loaded_reg = rUNDEF; - eReg regi; - - /* Check for regL */ - regi = m_icodes[0]->ll()->dst.regi; - if (not m_icodes[0]->ll()->testFlags(I) && (regi >= rAL) && (regi <= rBH)) - { - /* Check for MOV regH, 0 */ - if (m_icodes[1]->ll()->match(iMOV,I) && (m_icodes[1]->ll()->src().getImm2() == 0)) - { - if (m_icodes[1]->ll()->dst.regi == (regi + 4)) //WARNING: based on distance between AH-AL,BH-BL etc. - { - m_loaded_reg=(eReg)(regi - rAL + rAX); - return true; - } - } - } - return false; -} - -int Idiom13::action() -{ - COND_EXPR *lhs,*rhs; - lhs = COND_EXPR::idReg (m_loaded_reg, 0, &m_func->localId); - m_icodes[0]->setRegDU( m_loaded_reg, eDEF); - m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */ - rhs = COND_EXPR::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE); - m_icodes[0]->setAsgn(lhs, rhs); - m_icodes[1]->invalidate(); - return 2; -} - diff --git a/src/idioms/neg_idioms.cpp b/src/idioms/neg_idioms.cpp deleted file mode 100644 index 71986b8..0000000 --- a/src/idioms/neg_idioms.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "dcc.h" -#include "neg_idioms.h" -using namespace std; - - -/***************************************************************************** - * idiom11 - Negate long integer - * NEG regH - * NEG regL - * SBB regH, 0 - * Eg: NEG dx - * NEG ax - * SBB dx, 0 - * => dx:ax = - dx:ax - * Found in Borland Turbo C. - ****************************************************************************/ -bool Idiom11::match (iICODE picode) -{ - const char *matchstring="(oNEG rH) (oNEG rL) (SBB \rH i0)"; - condId type; /* type of argument */ - if(distance(picode,m_end)<3) - return false; - for(int i=0; i<3; ++i) - m_icodes[i]=picode++; - type = m_icodes[0]->ll()->idType(DST); - if(type==CONSTANT || type == OTHER) - return false; - /* Check NEG reg/mem - * SBB reg/mem, 0*/ - if (not m_icodes[1]->ll()->match(iNEG) or not m_icodes[2]->ll()->match(iSBB)) - return false; - switch (type) - { - case GLOB_VAR: - if ((m_icodes[2]->ll()->dst.segValue == m_icodes[0]->ll()->dst.segValue) && - (m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off)) - return true; - break; - case REGISTER: - if (m_icodes[2]->ll()->dst.regi == m_icodes[0]->ll()->dst.regi) - return true; - break; - case PARAM: - case LOCAL_VAR: - if (m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off) - return true; - break; - } - return false; -} -int Idiom11::action() -{ - COND_EXPR *lhs,*rhs; - lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0], HIGH_FIRST,m_icodes[0], USE_DEF, *m_icodes[1]->ll()); - rhs = COND_EXPR::unary (NEGATION, lhs); - m_icodes[0]->setAsgn(lhs, rhs); - m_icodes[1]->invalidate(); - m_icodes[2]->invalidate(); - return 3; -} - -/***************************************************************************** - * idiom 16: Bitwise negation - * NEG reg - * SBB reg, reg - * INC reg - * => ASGN reg, !reg - * Eg: NEG ax - * SBB ax, ax - * INC ax - * => ax = !ax - * Found in Borland Turbo C when negating bitwise. - ****************************************************************************/ -bool Idiom16::match (iICODE picode) -{ - const char *matchstring="(oNEG rR) (oSBB rR rR) (oINC rR)"; - if(distance(picode,m_end)<3) - return false; - for(int i=0; i<3; ++i) - m_icodes[i]=picode++; - - uint8_t regi = m_icodes[0]->ll()->dst.regi; - if ((regi >= rAX) && (regi < INDEX_BX_SI)) - { - if (m_icodes[1]->ll()->match(iSBB) && m_icodes[2]->ll()->match(iINC)) - if ((m_icodes[1]->ll()->dst.regi == (m_icodes[1]->ll()->src().getReg2())) && - m_icodes[1]->ll()->match((eReg)regi) && - m_icodes[2]->ll()->match((eReg)regi)) - return true; - } - return false; -} -int Idiom16::action() -{ - COND_EXPR *lhs,*rhs; - lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi, m_icodes[0]->ll()->getFlag(),&m_func->localId); - rhs = COND_EXPR::unary (NEGATION, lhs->clone()); - m_icodes[0]->setAsgn(lhs, rhs); - m_icodes[1]->invalidate(); - m_icodes[2]->invalidate(); - return 3; -} diff --git a/src/idioms/shift_idioms.cpp b/src/idioms/shift_idioms.cpp deleted file mode 100644 index 49c0694..0000000 --- a/src/idioms/shift_idioms.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#include "dcc.h" -#include "shift_idioms.h" -using namespace std; - - -/***************************************************************************** - * idiom8 - Shift right by 1 (signed long ops) - * SAR reg, 1 - * RCR reg, 1 - * Eg: SAR dx, 1 - * RCR ax, 1 - * => dx:ax = dx:ax >> 1 (dx:ax are signed long) - * Found in Microsoft C code for long signed variable shift right. - ****************************************************************************/ -bool Idiom8::match(iICODE pIcode) -{ - if(distance(pIcode,m_end)<2) - return false; - m_icodes[0]=pIcode++; - m_icodes[1]=pIcode++; - if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1)) - if ( m_icodes[1]->ll()->match(iRCR,I) && - (m_icodes[1]->ll()->src().getImm2() == 1)) - return true; - return false; -} - -int Idiom8::action() -{ - int idx; - COND_EXPR *rhs,*lhs,*expr; - eReg regH,regL; - regH=m_icodes[0]->ll()->dst.regi; - regL=m_icodes[1]->ll()->dst.regi; - idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, regH, regL, m_icodes[0]); - lhs = COND_EXPR::idLongIdx (idx); - m_icodes[0]->setRegDU( regL, USE_DEF); - - rhs = COND_EXPR::idKte(1,2); - expr = COND_EXPR::boolOp(lhs, rhs, SHR); - m_icodes[0]->setAsgn(lhs, expr); - m_icodes[1]->invalidate(); - return 2; -} - - -/***************************************************************************** - * idiom 15 - Shift left by n - * SHL reg, 1 - * SHL reg, 1 - * [...] - * [SHL reg, 1] - * Eg: SHL ax, 1 - * SHL ax, 1 - * => ax = ax << 2 - * Found in Borland Turbo C code to index an array (array multiplication) - ****************************************************************************/ -bool Idiom15::match(iICODE pIcode) -{ - uint8_t regi; - - if(distance(pIcode,m_end)<2) - return false; - /* Match SHL reg, 1 */ - if (not pIcode->ll()->testFlags(I) or (pIcode->ll()->src().getImm2() != 1)) - return false; - m_icodes.clear(); - regi = pIcode->ll()->dst.regi; - m_icodes.push_back(pIcode++); - while( (pIcode!=m_end) and - pIcode->ll()->match(iSHL,(eReg)regi,I) and - (pIcode->ll()->src().getImm2() == 1) ) - { - m_icodes.push_back(pIcode++); - } - return m_icodes.size()>1; -} - -int Idiom15::action() -{ - COND_EXPR *lhs,*rhs,*_exp; - lhs = COND_EXPR::idReg (m_icodes[0]->ll()->dst.regi, - m_icodes[0]->ll()->getFlag() & NO_SRC_B, - &m_func->localId); - rhs = COND_EXPR::idKte (m_icodes.size(), 2); - _exp = COND_EXPR::boolOp (lhs, rhs, SHL); - m_icodes[0]->setAsgn(lhs, _exp); - for (size_t i=1; iinvalidate(); - } - return m_icodes.size(); -} - -/***************************************************************************** - * idiom12 - Shift left long by 1 - * SHL reg, 1 - * RCL reg, 1 - * Eg: SHL ax, 1 - * RCL dx, 1 - * => dx:ax = dx:ax << 1 - * Found in Borland Turbo C code for long variable shift left. - ****************************************************************************/ -bool Idiom12::match(iICODE pIcode) -{ - if(distance(pIcode,m_end)<2) - return false; - m_icodes[0]=pIcode++; - m_icodes[1]=pIcode++; - if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1)) - if (m_icodes[1]->ll()->match(iRCL,I) && (m_icodes[1]->ll()->src().getImm2() == 1)) - return true; - return false; -} - -int Idiom12::action() -{ - int idx; - COND_EXPR *rhs,*lhs,*expr; - eReg regH,regL; - regL=m_icodes[0]->ll()->dst.regi; - regH=m_icodes[1]->ll()->dst.regi; - - idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, regH, regL,m_icodes[0]); - lhs = COND_EXPR::idLongIdx (idx); - m_icodes[0]->setRegDU( regH, USE_DEF); - rhs = COND_EXPR::idKte (1, 2); - expr = COND_EXPR::boolOp (lhs, rhs, SHL); - m_icodes[0]->setAsgn(lhs, expr); - m_icodes[1]->invalidate(); - return 2; -} - -/***************************************************************************** - * idiom9 - Shift right by 1 (unsigned long ops) - * SHR reg, 1 - * RCR reg, 1 - * Eg: SHR dx, 1 - * RCR ax, 1 - * => dx:ax = dx:ax >> 1 (dx:ax are unsigned long) - * Found in Microsoft C code for long unsigned variable shift right. - ****************************************************************************/ -bool Idiom9::match(iICODE pIcode) -{ - if(distance(pIcode,m_end)<2) - return false; - m_icodes[0]=pIcode++; - m_icodes[1]=pIcode++; - if (m_icodes[0]->ll()->testFlags(I) && (m_icodes[0]->ll()->src().getImm2() == 1)) - if (m_icodes[1]->ll()->match(iRCR,I) && (m_icodes[1]->ll()->src().getImm2() == 1)) - return true; - return false; -} - -int Idiom9::action() -{ - int idx; - COND_EXPR *rhs,*lhs,*expr; - eReg regH,regL; - regL=m_icodes[1]->ll()->dst.regi; - regH=m_icodes[0]->ll()->dst.regi; - idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,regH,regL,m_icodes[0]); - lhs = COND_EXPR::idLongIdx (idx); - m_icodes[0]->setRegDU(regL, USE_DEF); - rhs = COND_EXPR::idKte (1, 2); - expr = COND_EXPR::boolOp (lhs, rhs, SHR); - m_icodes[0]->setAsgn(lhs, expr); - m_icodes[1]->invalidate(); - return 2; -} diff --git a/src/idioms/xor_idioms.cpp b/src/idioms/xor_idioms.cpp deleted file mode 100644 index 279f4b8..0000000 --- a/src/idioms/xor_idioms.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "dcc.h" -#include "xor_idioms.h" -using namespace std; - -/***************************************************************************** - * idiom21 - Assign long kte with high part zero - * XOR regH, regH - * MOV regL, kte - * => regH:regL = kte - * Eg: XOR dx, dx - * MOV ax, 3 - * => dx:ax = 3 - * Note: only the following valid combinations are available: - * dx:ax - * cx:bx - * Found in Borland Turbo C code. - ****************************************************************************/ -bool Idiom21::match (iICODE picode) -{ - LLOperand *dst, *src; - if(distance(picode,m_end)<2) - return false; - m_icodes[0]=picode++; - m_icodes[1]=picode++; - - if (not m_icodes[1]->ll()->testFlags(I)) - return false; - - dst = &m_icodes[0]->ll()->dst; - src = &m_icodes[0]->ll()->src(); - if ((dst->regi == src->getReg2()) && (dst->getReg2() > 0) && (dst->getReg2() < INDEX_BX_SI)) - { - if ((dst->getReg2() == rDX) && m_icodes[1]->ll()->match(rAX)) - return true; - if ((dst->getReg2() == rCX) && m_icodes[1]->ll()->match(rBX)) - return true; - } - return false; -} -int Idiom21::action() -{ - COND_EXPR *lhs,*rhs; - lhs = COND_EXPR::idLong (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll()); - rhs = COND_EXPR::idKte (m_icodes[1]->ll()->src().getImm2() , 4); - m_icodes[0]->setAsgn(lhs, rhs); - m_icodes[0]->du.use = 0; /* clear register used in iXOR */ - m_icodes[1]->invalidate(); - return 2; -} - -/***************************************************************************** - * idiom7 - Assign zero - * XOR reg/stackOff, reg/stackOff - * Eg: XOR ax, ax - * => ax = 0 - * Found in Borland Turbo C and Microsoft C code. - ****************************************************************************/ -bool Idiom7::match(iICODE picode) -{ - if(picode==m_end) - return false; - const LLOperand *dst, *src; - m_icode=picode; - dst = &picode->ll()->dst; - src = &picode->ll()->src(); - if (dst->regi == 0) /* global variable */ - { - if ((dst->segValue == src->segValue) && (dst->off == src->off)) - return true; - } - else if (dst->regi < INDEX_BX_SI) /* register */ - { - if (dst->regi == src->regi) - return true; - } - else if ((dst->off) && (dst->seg == rSS) && (dst->regi == INDEX_BP)) /* offset from BP */ - { - if ((dst->off == src->off) && (dst->seg == src->seg) && (dst->regi == src->regi)) - return true; - } - return false; -} -int Idiom7::action() -{ - COND_EXPR *lhs,*rhs; - lhs = COND_EXPR::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE); - rhs = COND_EXPR::idKte (0, 2); - m_icode->setAsgn(lhs, rhs); - m_icode->du.use = 0; /* clear register used in iXOR */ - m_icode->ll()->setFlags(I); - return 1; -} - - -/***************************************************************************** - * idiom10 - Jump if not equal to 0 - * OR reg, reg - * JNE labX - * Eg: OR ax, ax - * JNE labX - * => CMP reg 0 - * JNE labX - * This instruction is NOT converted into the equivalent high-level - * instruction "HLI_JCOND (reg != 0) labX" because we do not know yet if - * it forms part of a long register conditional test. It is therefore - * modified to simplify the analysis. - * Found in Borland Turbo C. - ****************************************************************************/ -bool Idiom10::match(iICODE pIcode) -{ - if(distance(pIcode,m_end)<2) - return false; - m_icodes[0]=pIcode++; - m_icodes[1]=pIcode++; - /* Check OR reg, reg */ - if (not m_icodes[0]->ll()->testFlags(I) && - m_icodes[0]->ll()->src().isReg() && - (m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->dst.getReg2())) - if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump() - { - return true; - } - return false; -} - -int Idiom10::action() -{ - m_icodes[0]->ll()->set(iCMP,I); - m_icodes[0]->ll()->replaceSrc(LLOperand::CreateImm2(0)); - m_icodes[0]->du.def = 0; - m_icodes[0]->du1.numRegsDef = 0; - return 2; - -} diff --git a/src/locident.cpp b/src/locident.cpp index fdc02a3..7f8f167 100644 --- a/src/locident.cpp +++ b/src/locident.cpp @@ -5,324 +5,330 @@ * (C) Cristina Cifuentes */ -#include -#include "locident.h" #include "dcc.h" -bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const -{ - return (a->ll()->src().getReg2()==l) and (b->ll()->dst.getReg2()==h); -} - - -ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false) -{ - name[0]=0; - macro[0]=0; - memset(&id,0,sizeof(id)); -} -ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false) -{ - name[0]=0; - macro[0]=0; - memset(&id,0,sizeof(id)); - loc=f; -} +#include #define LOCAL_ID_DELTA 25 #define IDX_ARRAY_DELTA 5 + +void insertIdx (IDX_ARRAY *list, Int idx) +/* Inserts the new index at the end of the list. If there is need to + * allocate extra storage, it does so. */ +{ + if (list->csym == list->alloc) + { + list->alloc += IDX_ARRAY_DELTA; + list->idx = (Int*)reallocVar(list->idx, list->alloc * sizeof(Int)); + memset (&list->idx[list->csym], 0, IDX_ARRAY_DELTA * sizeof(Int)); + } + list->idx[list->csym] = idx; + list->csym++; +} + + +static boolT inList (IDX_ARRAY *list, Int idx) +/* Returns whether idx is in the list array or not */ +{ Int i; + + for (i = 0; i < list->csym; i++) + if (list->idx[i] == idx) + return (TRUE); + return (FALSE); +} + + +static void newIdent (LOCAL_ID *locSym, hlType t, frameType f) /* 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); + if (locSym->csym == locSym->alloc) + { + locSym->alloc += LOCAL_ID_DELTA; + locSym->id = (ID*)reallocVar(locSym->id, locSym->alloc * sizeof(ID)); + memset (&locSym->id[locSym->csym], 0, LOCAL_ID_DELTA * sizeof(ID)); + } + locSym->id[locSym->csym].type = t; + locSym->id[locSym->csym].loc = f; + locSym->csym++; } +Int newByteWordRegId (LOCAL_ID *locSym, hlType t, byte regi) /* 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, eReg regi) -{ - int idx; +{ Int idx; /* Check for entry in the table */ - auto found=std::find_if(id_arr.begin(),id_arr.end(),[t,regi](ID &el)->bool { - return ((el.type == t) && (el.id.regi == regi)); - }); - if(found!=id_arr.end()) - return found-id_arr.begin(); + for (idx = 0; idx < locSym->csym; idx++) + { + if ((locSym->id[idx].type == t) && + (locSym->id[idx].id.regi == regi)) + return (idx); + } + /* Not in table, create new identifier */ - newIdent (t, REG_FRAME); - idx = id_arr.size() - 1; - id_arr[idx].id.regi = regi; + newIdent (locSym, t, REG_FRAME); + idx = locSym->csym - 1; + locSym->id[idx].id.regi = regi; return (idx); } +static void flagByteWordId (LOCAL_ID *locsym, Int off) /* Flags the entry associated with the offset off to illegal, as this - * offset is part of a long stack variable. + * 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 + * 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)) && - if ((en.typeBitsize()<=16) && - (en.id.bwId.off == off) && (en.id.bwId.regOff == 0)) - return true; - return false; - }); - if(found==id_arr.end()) +{ Int idx; + + for (idx = 0; idx < locsym->csym; idx++) { - printf("No entry to flag as invalid in LOCAL_ID::flagByteWordId \n"); - return; + if (((locsym->id[idx].type == TYPE_WORD_SIGN) || + (locsym->id[idx].type == TYPE_BYTE_SIGN)) && + (locsym->id[idx].id.bwId.off == off) && + (locsym->id[idx].id.bwId.regOff == 0)) + { + locsym->id[idx].illegal = TRUE; + break; + } } - found->illegal = true; } + +Int newByteWordStkId (LOCAL_ID *locSym, hlType t, Int off, byte regOff) /* 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, uint8_t regOff) -{ - int idx; +{ 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 + for (idx = 0; idx < locSym->csym; idx++) + { + if ((locSym->id[idx].id.bwId.off == off) && + (locSym->id[idx].id.bwId.regOff == regOff)) + return (idx); + } /* 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; + newIdent (locSym, t, STK_FRAME); + idx = locSym->csym - 1; + locSym->id[idx].id.bwId.regOff = regOff; + locSym->id[idx].id.bwId.off = off; return (idx); } +Int newIntIdxId (LOCAL_ID *locSym, int16 seg, int16 off, byte regi, + Int ix, hlType t) /* 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. + * 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_t seg, int16_t off, eReg regi, int ix, hlType t) -{ - int idx; +{ Int idx; /* Check for entry in the table */ - for (idx = 0; idx < id_arr.size(); idx++) + for (idx = 0; idx < locSym->csym; 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)) + (locSym->id[idx].id.bwGlb.seg == seg) && + (locSym->id[idx].id.bwGlb.off == off) && + (locSym->id[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; + newIdent (locSym, t, GLB_FRAME); + idx = locSym->csym - 1; + locSym->id[idx].id.bwGlb.seg = seg; + locSym->id[idx].id.bwGlb.off = off; + locSym->id[idx].id.bwGlb.regi = regi; return (idx); } +Int newLongRegId (LOCAL_ID *locSym, hlType t, byte regH, byte regL, Int ix) /* 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 + * 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, eReg regH, eReg regL, iICODE ix_) -{ - size_t idx; - //iICODE ix_; +{ Int idx; + /* Check for entry in the table */ - for (idx = 0; idx < id_arr.size(); idx++) + for (idx = 0; idx < locSym->csym; idx++) { - ID &entry(id_arr[idx]); if (/*(locSym->id[idx].type == t) && Not checking type */ - (entry.id.longId.h == regH) && - (entry.id.longId.l == regL)) + (locSym->id[idx].id.longId.h == regH) && + (locSym->id[idx].id.longId.l == regL)) { /* Check for occurrence in the list */ - if (entry.idx.inList(ix_)) + if (inList (&locSym->id[idx].idx, ix)) return (idx); else { /* Insert icode index in list */ - entry.idx.push_back(ix_); - //entry.idx.insert(ix_); + insertIdx (&locSym->id[idx].idx, ix); return (idx); } } } /* Not in the table, create new identifier */ - newIdent (t, REG_FRAME); - id_arr[id_arr.size()-1].idx.push_back(ix_);//insert(ix_); - idx = id_arr.size() - 1; - id_arr[idx].id.longId.h = regH; - id_arr[idx].id.longId.l = regL; + newIdent (locSym, t, REG_FRAME); + insertIdx (&locSym->id[locSym->csym-1].idx, ix); + idx = locSym->csym - 1; + locSym->id[idx].id.longId.h = regH; + locSym->id[idx].id.longId.l = regL; return (idx); } -/* Returns an identifier conditional expression node of type TYPE_LONG or - * TYPE_WORD_SIGN */ -COND_EXPR * LOCAL_ID::createId(const ID *retVal, iICODE ix_) -{ - return COND_EXPR::idID(retVal,this,ix_); -} + +static Int newLongGlbId (LOCAL_ID *locSym, int16 seg, int16 offH, int16 offL, + Int ix, hlType t) /* 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 + * 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_t seg, int16_t offH, int16_t offL,hlType t) -{ - size_t idx; +{ Int idx; /* Check for entry in the table */ - for (idx = 0; idx < id_arr.size(); idx++) + for (idx = 0; idx < locSym->csym; 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)) + (locSym->id[idx].id.longGlb.seg == seg) && + (locSym->id[idx].id.longGlb.offH == offH) && + (locSym->id[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; + newIdent (locSym, t, GLB_FRAME); + idx = locSym->csym - 1; + locSym->id[idx].id.longGlb.seg = seg; + locSym->id[idx].id.longGlb.offH = offH; + locSym->id[idx].id.longGlb.offL = offL; return (idx); } +static Int newLongIdxId (LOCAL_ID *locSym, int16 seg, int16 offH, int16 offL, + byte regi, Int ix, hlType t) /* 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 + * 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_t seg, int16_t offH, int16_t offL,uint8_t regi, hlType t) -{ - size_t idx; +{ Int idx; /* Check for entry in the table */ - for (idx = 0; idx < id_arr.size(); idx++) + for (idx = 0; idx < locSym->csym; 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)) + (locSym->id[idx].id.longGlb.seg == seg) && + (locSym->id[idx].id.longGlb.offH == offH) && + (locSym->id[idx].id.longGlb.offL == offL) && + (locSym->id[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; + newIdent (locSym, t, GLB_FRAME); + idx = locSym->csym - 1; + locSym->id[idx].id.longGlb.seg = seg; + locSym->id[idx].id.longGlb.offH = offH; + locSym->id[idx].id.longGlb.offL = offL; + locSym->id[idx].id.longGlb.regi = regi; return (idx); } +Int newLongStkId (LOCAL_ID *locSym, hlType t, Int offH, Int offL) /* 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) -{ - size_t idx; +{ Int idx; /* Check for entry in the table */ - for (idx = 0; idx < id_arr.size(); idx++) + for (idx = 0; idx < locSym->csym; idx++) { - if ((id_arr[idx].type == t) && - (id_arr[idx].id.longStkId.offH == offH) && - (id_arr[idx].id.longStkId.offL == offL)) + if ((locSym->id[idx].type == t) && + (locSym->id[idx].id.longStkId.offH == offH) && + (locSym->id[idx].id.longStkId.offL == offL)) return (idx); } - /* Not in the table; flag as invalid offH and offL */ - flagByteWordId (offH); - flagByteWordId (offL); + /* Not in the table; flag as invalid offH and offL */ + flagByteWordId (locSym, offH); + flagByteWordId (locSym, 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; + newIdent (locSym, t, STK_FRAME); + idx = locSym->csym - 1; + locSym->id[idx].id.longStkId.offH = offH; + locSym->id[idx].id.longStkId.offL = offL; return (idx); } -/* Returns the index to an appropriate long identifier. +Int newLongId (LOCAL_ID *locSym, opLoc sd, PICODE pIcode, hlFirst f, Int ix, + operDu du, Int off) +/* 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, iICODE pIcode, hlFirst f, iICODE ix,operDu du, LLInst &atOffset) -{ - size_t idx; - const LLOperand *pmH, *pmL; - LLInst &p_ll(*pIcode->ll()); +{ Int idx; + PMEM pmH, pmL; + if (f == LOW_FIRST) { - pmL = p_ll.get(sd); - pmH = atOffset.get(sd); + 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 */ { - pmL = atOffset.get(sd); - pmH = p_ll.get(sd); + 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, TYPE_LONG_SIGN); + idx = newLongGlbId (locSym, pmH->segValue, pmH->off, pmL->off, ix, + TYPE_LONG_SIGN); - else if (pmL->regi < INDEX_BX_SI) /* register */ + else if (pmL->regi < INDEXBASE) /* register */ { - idx = newLongReg(TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix); + idx = newLongRegId (locSym, TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix); if (f == HIGH_FIRST) - pIcode->setRegDU( pmL->regi, du); /* low part */ + setRegDU (pIcode, pmL->regi, du); /* low part */ else - pIcode->setRegDU( pmH->regi, du); /* high part */ + setRegDU (pIcode, pmH->regi, du); /* high part */ } else if (pmL->off) { /* offset */ - if ((pmL->seg == rSS) && (pmL->regi == INDEX_BP)) /* idx on bp */ - idx = newLongStk(TYPE_LONG_SIGN, pmH->off, pmL->off); - else if ((pmL->seg == rDS) && (pmL->regi == INDEX_BX)) /* bx */ + if ((pmL->seg == rSS) && (pmL->regi == INDEXBASE + 6)) /* idx on bp */ + idx = newLongStkId (locSym, TYPE_LONG_SIGN, pmH->off, pmL->off); + else if ((pmL->seg == rDS) && (pmL->regi == INDEXBASE + 7)) /* bx */ { /* glb var indexed on bx */ - printf("Bx indexed global, BX is an unused parameter to newLongIdx\n"); - idx = newLongIdx(pmH->segValue, pmH->off, pmL->off,rBX,TYPE_LONG_SIGN); - pIcode->setRegDU( rBX, eUSE); + idx = newLongIdxId (locSym, pmH->segValue, pmH->off, pmL->off, + rBX, ix, TYPE_LONG_SIGN); + setRegDU (pIcode, rBX, E_USE); } else /* idx <> bp, bx */ printf ("long not supported, idx <> bp\n"); } - else /* (pm->regi >= INDEXBASE && pm->off = 0) => indexed && no off */ + 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, PICODE pIcode, Int i, Int idx, + PPROC 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. @@ -330,38 +336,36 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L * 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 + * pProc : ptr to current procedure record * rhs, lhs : return expressions if successful. */ -boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset) -{ - /* pointers to LOW_LEVEL icodes */ - const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc; +{ PMEM pmHdst, pmLdst, pmHsrc, pmLsrc; /* pointers to LOW_LEVEL icodes */ - pmHdst = &pIcode->ll()->dst; - pmLdst = &atOffset.dst; - pmHsrc = &pIcode->ll()->src(); - pmLsrc = &atOffset.src(); + 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)) { - asgn.lhs = COND_EXPR::idLongIdx (i); - - if ( not pIcode->ll()->testFlags(NO_SRC) ) - { - asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset); - } - return true; + *lhs = idCondExpLongIdx (i); + if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC) + *rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, + idx, E_USE, off); + return (TRUE); } else if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off)) { - asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset); - asgn.rhs = COND_EXPR::idLongIdx (i); - return true; + *lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx, + E_DEF, off); + *rhs = idCondExpLongIdx (i); + return (TRUE); } - return false; + return (FALSE); } +boolT checkLongRegEq (LONGID_TYPE longId, PICODE pIcode, Int i, Int idx, + PPROC 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. @@ -369,47 +373,42 @@ boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pPro * 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 + * pProc : ptr to current procedure record * rhs, lhs : return expressions if successful. */ -boolT checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i, - Function * pProc, Assignment &asgn, LLInst &atOffset) -{ - /* pointers to LOW_LEVEL icodes */ - const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc; +{ PMEM pmHdst, pmLdst, pmHsrc, pmLsrc; /* pointers to LOW_LEVEL icodes */ - pmHdst = &pIcode->ll()->dst; - pmLdst = &atOffset.dst; - pmHsrc = &pIcode->ll()->src(); - pmLsrc = &atOffset.src(); + 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)) { - asgn.lhs = COND_EXPR::idLongIdx (i); - if ( not pIcode->ll()->testFlags(NO_SRC) ) - { - asgn.rhs = COND_EXPR::idLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset); - } - return true; + *lhs = idCondExpLongIdx (i); + if ((pIcode->ic.ll.flg & NO_SRC) != NO_SRC) + *rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, + idx, E_USE, off); + return (TRUE); } else if ((longId.h == pmHsrc->regi) && (longId.l == pmLsrc->regi)) { - asgn.lhs = COND_EXPR::idLong (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset); - asgn.rhs = COND_EXPR::idLongIdx (i); - return true; + *lhs = idCondExpLong (&pProc->localId, DST, pIcode, HIGH_FIRST, idx, + E_DEF, off); + *rhs = idCondExpLongIdx (i); + return (TRUE); } - return false; + return (FALSE); } +byte otherLongRegi (byte regi, Int idx, LOCAL_ID *locTbl) /* 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 */ -eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl) -{ - ID *id; +{ ID *id; - id = &locTbl->id_arr[idx]; + id = &locTbl->id[idx]; if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) || (id->type == TYPE_LONG_UNSIGN))) { @@ -418,33 +417,37 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl) else if (id->id.longId.l == regi) return (id->id.longId.h); } - return rUNDEF; // Cristina: please check this! + return 0; // Cristina: please check this! } +void propLongId (LOCAL_ID *locid, byte regL, byte regH, char *name) /* 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 + * placed in the local identifier table, as these registers belong to a * long register identifier. */ -void LOCAL_ID::propLongId (uint8_t regL, uint8_t regH, const char *name) -{ - for (ID &rid : id_arr) - { - if (rid.typeBitsize()!=16) - continue; - if ( (rid.id.regi != regL) and (rid.id.regi != regH) ) - continue; - // otherwise at least 1 is ok - rid.name = name; - rid.hasMacro = true; - rid.illegal = true; - if (rid.id.regi == regL) - { - strcpy (rid.macro, "LO"); - } - else // if (rid.id.regi == regH) - { - strcpy (rid.macro, "HI"); - } - } +{ Int i; + ID *id; + + for (i = 0; i < locid->csym; i++) + { + id = &locid->id[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; + } + } + } } diff --git a/src/machine_x86.cpp b/src/machine_x86.cpp deleted file mode 100644 index 217838d..0000000 --- a/src/machine_x86.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include -#include "machine_x86.h" -// Index registers **** temp solution -static const std::string regNames[] = { - "undef", - "ax", "cx", "dx", "bx", - "sp", "bp", "si", "di", - "es", "cs", "ss", "ds", - "al", "cl", "dl", "bl", - "ah", "ch", "dh", "bh", - "tmp", - "bx+si", "bx+di", "bp+si", "bp+di", - "si", "di", "bp", "bx" -}; - -/* uint8_t and uint16_t registers */ -Machine_X86::Machine_X86() -{ - static_assert((sizeof(regNames)/sizeof(std::string))==LAST_REG, - "Reg count not equal number of strings"); -} - -const std::string &Machine_X86::regName(eReg r) -{ - assert(r<(sizeof(regNames)/sizeof(std::string))); - return regNames[r]; -} - -static const std::string szOps[] = -{ - "CBW", "AAA", "AAD", "AAM", "AAS", "ADC", "ADD", "AND", - "BOUND","CALL", "CALL", "CLC", "CLD", "CLI", "CMC", "CMP", - "CMPS", "REPNE CMPS","REPE CMPS","DAA", "DAS", "DEC", "DIV", "ENTER", - "ESC", "HLT", "IDIV", "IMUL", "IN", "INC", "INS", "REP INS", - "INT", "IRET", "JB", "JBE", "JAE", "JA", "JE", "JNE", - "JL", "JGE", "JLE", "JG", "JS", "JNS", "JO", "JNO", - "JP", "JNP", "JCXZ", "JMP", "JMP", "LAHF", "LDS", "LEA", - "LEAVE","LES", "LOCK", "LODS", "REP LODS", "LOOP", "LOOPE","LOOPNE", - "MOV", "MOVS", "REP MOVS", "MUL", "NEG", "NOT", "OR", "OUT", - "OUTS", "REP OUTS", "POP", "POPA", "POPF", "PUSH", "PUSHA","PUSHF", - "RCL", "RCR", "ROL", "ROR", "RET", "RETF", "SAHF", "SAR", - "SHL", "SHR", "SBB", "SCAS", "REPNE SCAS","REPE SCAS", "CWD", "STC", - "STD", "STI", "STOS", "REP STOS", "SUB", "TEST", "WAIT", "XCHG", - "XLAT", "XOR", "INTO", "NOP", "REPNE", "REPE", "MOD" -}; -/* The following opcodes are for mod != 3 */ -static std::string szFlops1[] = -{ - /* 0 1 2 3 4 5 6 7 */ - "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */ - "FLD", "???", "FST", "???", "FLDENV","FLDCW", "FSTENV","FSTSW", /* 08 */ - "FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 10 */ - "FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */ - "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */ - "FLD", "FLD", "FST", "FSTP", "FRESTOR","???", "FSAVE", "FSTSW", /* 28 */ - "FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "FISUBR","FIDIV", "FIDIVR", /* 30 */ - "FILD", "???", "FIST", "FISTP", "FBLD", "???", "FBSTP", "FISTP" /* 38 */ -}; -/* The following opcodes are for mod == 3 */ -static std::string szFlops2[] = -{ - /* 0 1 2 3 4 5 6 7 */ - "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 00 */ - "FLD", "FXCH", "FNOP", "???", "", "", "", "", /* 08 */ - "FIADD", "FIMUL", "FICOM","FICOMP","FISUB", "", "FIDIV", "FIDIVR", /* 10 */ - "FILD", "???", "FIST", "FISTP", "???", "???", "???", "FSTP", /* 18 */ - "FADD", "FMUL", "FCOM", "FCOMP", "FSUB", "FSUBR", "FDIV", "FDIVR", /* 20 */ - "FFREE", "FSTP", "FST", "???", "FUCOM", "FUCOMP","???", "???", /* 28 */ - "FADDP", "FMULP", "FICOM","", "FSUBRP","FISUBR","FDIVRP","FDIVP", /* 30 */ - "FILD", "???", "FIST", "FISTP", "", "???", "FBSTP", "FISTP" /* 38 */ -}; - -const std::string &Machine_X86::opcodeName(unsigned r) -{ - assert(r<(sizeof(szOps)/sizeof(std::string))); - return szOps[r]; -} -const std::string &Machine_X86::floatOpName(unsigned r) -{ - if(r>=(sizeof(szFlops1)/sizeof(std::string))) - { - r-= (sizeof(szFlops1)/sizeof(std::string)); - assert(r<(sizeof(szFlops2)/sizeof(std::string))); - return szFlops2[r]; - } - return szFlops1[r]; -} - -bool Machine_X86::physicalReg(eReg r) -{ - return (r>=rAX) && (r= INDEX_BX_SI; -} -//TODO: Move these to Machine_X86 -eReg Machine_X86::subRegH(eReg reg) -{ - return eReg((int)reg + (int)rAH-(int)rAX); -} -eReg Machine_X86::subRegL(eReg reg) -{ - return eReg((int)reg + (int)rAL-(int)rAX); -} -bool Machine_X86::isSubRegisterOf(eReg reg,eReg parent) -{ - if ((parent < rAX) || (parent > rBX)) - return false; // only AX -> BX are coverede by subregisters - return ((reg==subRegH(parent)) || (reg == subRegL(parent))); -} diff --git a/src/parser.cpp b/src/parser.cpp index 191f27f..5dbd4f4 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3,458 +3,429 @@ * (C) Cristina Cifuentes, Mike van Emmerik, Jeff Ledermann ****************************************************************************/ +#include "dcc.h" #include #include /* For exit() */ -#include + +#ifdef __DOSWIN__ #include -#include +#endif -#include "dcc.h" -#include "project.h" -using namespace std; -extern Project g_proj; -//static void FollowCtrl (Function * pProc, CALL_GRAPH * pcallGraph, STATE * pstate); -static boolT process_JMP (ICODE * pIcode, STATE * pstate, CALL_GRAPH * pcallGraph); -static void setBits(int16_t type, uint32_t start, uint32_t len); -static void process_MOV(LLInst &ll, STATE * pstate); -static SYM * lookupAddr (LLOperand *pm, STATE * pstate, int size, uint16_t duFlag); -void interactDis(Function * initProc, int ic); -static uint32_t SynthLab; +static void FollowCtrl (PPROC pProc, PCALL_GRAPH pcallGraph, PSTATE pstate); +static boolT process_JMP (PICODE pIcode, PPROC pProc, PSTATE pstate, + PCALL_GRAPH pcallGraph); +static boolT process_CALL(PICODE pIcode, PPROC pProc, PCALL_GRAPH pcallGraph, + PSTATE pstate); +static void process_operands(PICODE pIcode, PPROC pProc, PSTATE pstate, + Int ix); +static void setBits(int16 type, dword start, dword len); +static PSYM updateGlobSym(dword operand, Int size, word duFlag); +static void process_MOV(PICODE pIcode, PSTATE pstate); +static PSYM lookupAddr (PMEM pm, PSTATE pstate, Int size, word duFlag); + void interactDis(PPROC initProc, Int ic); +static dword SynthLab; -/* Parses the program, builds the call graph, and returns the list of + +void parse (PCALL_GRAPH *pcallGraph) +/* Parses the program, builds the call graph, and returns the list of * procedures found */ -void DccFrontend::parse(Project &proj) -{ - PROG &prog(proj.prog); - STATE state; +{ STATE state; /* Set initial state */ - state.setState(rES, 0); /* PSP segment */ - state.setState(rDS, 0); - state.setState(rCS, prog.initCS); - state.setState(rSS, prog.initSS); - state.setState(rSP, prog.initSP); - state.IP = ((uint32_t)prog.initCS << 4) + prog.initIP; + memset(&state, 0, sizeof(STATE)); + setState(&state, rES, 0); /* PSP segment */ + setState(&state, rDS, 0); + setState(&state, rCS, prog.initCS); + setState(&state, rSS, prog.initSS); + setState(&state, rSP, prog.initSP); + state.IP = ((dword)prog.initCS << 4) + prog.initIP; SynthLab = SYNTHESIZED_MIN; - // default-construct a Function object ! - auto func = proj.createFunction(); /* Check for special settings of initial state, based on idioms of the - startup code */ - state.checkStartup(); - Function &start_proc(proj.pProcList.front()); + startup code */ + checkStartup(&state); + /* Make a struct for the initial procedure */ + pProcList = allocStruc(PROCEDURE); + pProcList = (PPROC)memset(pProcList, 0, sizeof(PROCEDURE)); if (prog.offMain != -1) { /* We know where main() is. Start the flow of control from there */ - start_proc.procEntry = prog.offMain; + pProcList->procEntry = prog.offMain; /* In medium and large models, the segment of main may (will?) not be - the same as the initial CS segment (of the startup code) */ - state.setState(rCS, prog.segMain); - start_proc.name = "main"; + the same as the initial CS segment (of the startup code) */ + setState(&state, rCS, prog.segMain); + strcpy(pProcList->name, "main"); state.IP = prog.offMain; } else { /* Create initial procedure at program start address */ - start_proc.name="start"; - start_proc.procEntry = (uint32_t)state.IP; + pProcList->procEntry = (dword)state.IP; } /* The state info is for the first procedure */ - start_proc.state = state; + memcpy(&(pProcList->state), &state, sizeof(STATE)); + pLastProc = pProcList; /* Set up call graph initial node */ - proj.callGraph = new CALL_GRAPH; - proj.callGraph->proc = proj.pProcList.begin(); + *pcallGraph = allocStruc(CALL_GRAPH); + memset (*pcallGraph, 0, sizeof(CALL_GRAPH)); + (*pcallGraph)->proc = pProcList; /* This proc needs to be called to set things up for LibCheck(), which - checks a proc to see if it is a know C (etc) library */ + checks a proc to see if it is a know C (etc) library */ SetupLibCheck(); - //ERROR: proj and g_proj are 'live' at this point ! + /* Recursively build entire procedure list */ - proj.pProcList.front().FollowCtrl (proj.callGraph, &state); + FollowCtrl (pProcList, *pcallGraph, &state); /* This proc needs to be called to clean things up from SetupLibCheck() */ CleanupLibCheck(); } -/* Returns the size of the string pointed by sym and delimited by delim. - * Size includes delimiter. */ -int strSize (uint8_t *sym, char delim) -{ - PROG &prog(Project::get()->prog); - int till_end = sym-prog.Image; - uint8_t *end_ptr=std::find(sym,sym+(prog.cbImage-(till_end)),delim); - return end_ptr-sym+1; + +static void updateSymType (dword symbol, hlType symType, Int size) +/* Updates the type of the symbol in the symbol table. The size is updated + * if necessary (0 means no update necessary). */ +{ Int i; + + for (i = 0; i < symtab.csym; i++) + if (symtab.sym[i].label == symbol) + { + symtab.sym[i].type = symType; + if (size != 0) + symtab.sym[i].size = size; + break; + } } -Function *fakeproc=Function::Create(0,0,"fake"); + +Int strSize (byte *sym, char delim) +/* Returns the size of the string pointed by sym and delimited by delim. + * Size includes delimiter. */ +{ Int i; + + for (i = 0; *sym++ != delim; i++) ; + return (i+1); +} + + +static void FollowCtrl (PPROC pProc, PCALL_GRAPH pcallGraph, PSTATE pstate) /* FollowCtrl - Given an initial procedure, state information and symbol table - * builds a list of procedures reachable from the initial procedure - * using a depth first search. */ -void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate) + * builds a list of procedures reachable from the initial procedure + * using a depth first search. */ { - PROG &prog(Project::get()->prog); - ICODE _Icode, *pIcode; /* This gets copied to pProc->Icode[] later */ + ICODE Icode, *pIcode; /* This gets copied to pProc->Icode[] later */ ICODE eIcode; /* extra icodes for iDIV, iIDIV, iXCHG */ - SYM * psym; - uint32_t offset; - eErrorId err; - bool done = false; - SYMTAB &global_symbol_table(g_proj.symtab); - if (name.find("chkstk") != string::npos) - { - // Danger! Dcc will likely fall over in this code. - // So we act as though we have done with this proc - // pProc->flg &= ~TERMINATES; // Not sure about this - done = true; + PSYM psym; + dword offset; + Int err; + boolT done = FALSE; + Int lab; + + if (strstr(pProc->name, "chkstk") != NULL) + { + // Danger! Dcc will likely fall over in this code. + // So we act as though we have done with this proc +// pProc->flg &= ~TERMINATES; // Not sure about this + done = TRUE; // And mark it as a library function, so structure() won't choke on it - flg |= PROC_ISLIB; - return; - } - if (option.VeryVerbose) - { - printf("Parsing proc %s at %lX\n", name.c_str(), pstate->IP); - } + pProc->flg |= PROC_ISLIB; + return; + } + if (option.VeryVerbose) + { + printf("Parsing proc %s at %lX\n", pProc->name, pstate->IP); + } - while (! done && ! (err = scan(pstate->IP, _Icode))) + while (! done && ! (err = scan(pstate->IP, &Icode))) { - LLInst *ll = _Icode.ll(); - pstate->IP += (uint32_t)ll->numBytes; - setBits(BM_CODE, ll->label, (uint32_t)ll->numBytes); + pstate->IP += (dword)Icode.ic.ll.numBytes; + setBits(BM_CODE, Icode.ic.ll.label, (dword)Icode.ic.ll.numBytes); - process_operands(_Icode,pstate); + process_operands(&Icode, pProc, pstate, pProc->Icode.GetNumIcodes()); /* Keep track of interesting instruction flags in procedure */ - flg |= (ll->getFlag() & (NOT_HLL | FLOAT_OP)); + pProc->flg |= (Icode.ic.ll.flg & (NOT_HLL | FLOAT_OP)); /* Check if this instruction has already been parsed */ - iICODE labLoc = Icode.labelSrch(ll->label); - if (Icode.end()!=labLoc) + if (pProc->Icode.labelSrch(Icode.ic.ll.label, &lab)) { /* Synthetic jump */ - _Icode.type = LOW_LEVEL; - ll->set(iJMP,I | SYNTHETIC | NO_OPS); - ll->replaceSrc(LLOperand::CreateImm2(labLoc->ll()->GetLlLabel())); - ll->label = SynthLab++; + Icode.type = LOW_LEVEL; + Icode.ic.ll.opcode = iJMP; + Icode.ic.ll.flg = I | SYNTHETIC | NO_OPS; + Icode.ic.ll.immed.op = pProc->Icode.GetLlLabel(lab); + Icode.ic.ll.label = SynthLab++; } /* Copy Icode to Proc */ - if ((_Icode.ll()->getOpcode() == iDIV) || (_Icode.ll()->getOpcode() == iIDIV)) + if ((Icode.ic.ll.opcode == iDIV) || (Icode.ic.ll.opcode == iIDIV)) { /* MOV rTMP, reg */ - eIcode = ICODE(); - - eIcode.type = LOW_LEVEL; - eIcode.ll()->set(iMOV,0); - eIcode.ll()->replaceDst(rTMP); - if (ll->testFlags(B) ) + memset (&eIcode, 0, sizeof (ICODE)); + eIcode.type = LOW_LEVEL; + eIcode.ic.ll.opcode = iMOV; + eIcode.ic.ll.dst.regi = rTMP; + if (Icode.ic.ll.flg & B) { - eIcode.ll()->setFlags( B ); - eIcode.ll()->replaceSrc(rAX); + eIcode.ic.ll.flg |= B; + eIcode.ic.ll.src.regi = rAX; + setRegDU (&eIcode, rAX, E_USE); } else /* implicit dx:ax */ { - eIcode.ll()->setFlags( IM_SRC ); - eIcode.setRegDU( rDX, eUSE); + eIcode.ic.ll.flg |= IM_SRC; + setRegDU (&eIcode, rAX, E_USE); + setRegDU (&eIcode, rDX, E_USE); } - eIcode.setRegDU( rAX, eUSE); - eIcode.setRegDU( rTMP, eDEF); - eIcode.ll()->setFlags( SYNTHETIC ); - /* eIcode.ll()->label = SynthLab++; */ - eIcode.ll()->label = _Icode.ll()->label; - Icode.addIcode(&eIcode); + setRegDU (&eIcode, rTMP, E_DEF); + eIcode.ic.ll.flg |= SYNTHETIC; + /* eIcode.ic.ll.label = SynthLab++; */ + eIcode.ic.ll.label = Icode.ic.ll.label; + pIcode = pProc->Icode.addIcode(&eIcode); /* iDIV, iIDIV */ - Icode.addIcode(&_Icode); + pIcode = pProc->Icode.addIcode(&Icode); /* iMOD */ - eIcode = ICODE(); - eIcode.type = LOW_LEVEL; - eIcode.ll()->set(iMOD,0); - eIcode.ll()->replaceSrc(_Icode.ll()->src()); - eIcode.du = _Icode.du; - eIcode.ll()->setFlags( ( ll->getFlag() | SYNTHETIC | IM_TMP_DST) ); - eIcode.ll()->label = SynthLab++; - pIcode = Icode.addIcode(&eIcode); + memset (&eIcode, 0, sizeof (ICODE)); + eIcode.type = LOW_LEVEL; + eIcode.ic.ll.opcode = iMOD; + memcpy (&eIcode.ic.ll.src, &Icode.ic.ll.src, sizeof(ICODEMEM)); + memcpy (&eIcode.du, &Icode.du, sizeof(DU_ICODE)); + eIcode.ic.ll.flg = (Icode.ic.ll.flg | SYNTHETIC); + eIcode.ic.ll.label = SynthLab++; + pIcode = pProc->Icode.addIcode(&eIcode); } - else if (_Icode.ll()->getOpcode() == iXCHG) + else if (Icode.ic.ll.opcode == iXCHG) { /* MOV rTMP, regDst */ - eIcode = ICODE(); + memset (&eIcode, 0, sizeof (ICODE)); eIcode.type = LOW_LEVEL; - eIcode.ll()->set(iMOV,SYNTHETIC); - eIcode.ll()->replaceDst(LLOperand::CreateReg2(rTMP)); - eIcode.ll()->replaceSrc(_Icode.ll()->dst); - eIcode.setRegDU( rTMP, eDEF); - if(eIcode.ll()->src().getReg2()) - { - eReg srcreg=eIcode.ll()->src().getReg2(); - eIcode.setRegDU( srcreg, eUSE); - if((srcreg>=rAL) && (srcreg<=rBH)) - eIcode.ll()->setFlags( B ); - } - eIcode.ll()->label = _Icode.ll()->label; - Icode.addIcode(&eIcode); + eIcode.ic.ll.opcode = iMOV; + eIcode.ic.ll.dst.regi = rTMP; + eIcode.ic.ll.src.regi = Icode.ic.ll.dst.regi; + setRegDU (&eIcode, rTMP, E_DEF); + setRegDU (&eIcode, eIcode.ic.ll.src.regi, E_USE); + eIcode.ic.ll.flg |= SYNTHETIC; + /* eIcode.ic.ll.label = SynthLab++; */ + eIcode.ic.ll.label = Icode.ic.ll.label; + pIcode = pProc->Icode.addIcode(&eIcode); /* MOV regDst, regSrc */ - _Icode.ll()->set(iMOV,SYNTHETIC|_Icode.ll()->getFlag()); - Icode.addIcode(&_Icode); - ll->setOpcode(iXCHG); /* for next case */ + Icode.ic.ll.opcode = iMOV; + Icode.ic.ll.flg |= SYNTHETIC; + /* Icode.ic.ll.label = SynthLab++; */ + pIcode = pProc->Icode.addIcode(&Icode); + Icode.ic.ll.opcode = iXCHG; /* for next case */ - /* MOV regSrc, rTMP */ - eIcode = ICODE(); + /* MOV regSrc, rTMP */ + memset (&eIcode, 0, sizeof (ICODE)); eIcode.type = LOW_LEVEL; - eIcode.ll()->set(iMOV,SYNTHETIC); - eIcode.ll()->replaceDst(ll->src()); - if(eIcode.ll()->dst.regi) - { - if((eIcode.ll()->dst.regi>=rAL) && (eIcode.ll()->dst.regi<=rBH)) - eIcode.ll()->setFlags( B ); - eIcode.setRegDU( eIcode.ll()->dst.regi, eDEF); - } - eIcode.ll()->replaceSrc(rTMP); - eIcode.setRegDU( rTMP, eUSE); - eIcode.ll()->label = SynthLab++; - pIcode = Icode.addIcode(&eIcode); - } + eIcode.ic.ll.opcode = iMOV; + eIcode.ic.ll.dst.regi = Icode.ic.ll.src.regi; + eIcode.ic.ll.src.regi = rTMP; + setRegDU (&eIcode, eIcode.ic.ll.dst.regi, E_DEF); + setRegDU (&eIcode, rTMP, E_USE); + eIcode.ic.ll.flg |= SYNTHETIC; + eIcode.ic.ll.label = SynthLab++; + pIcode = pProc->Icode.addIcode(&eIcode); + } else - pIcode = Icode.addIcode(&_Icode); + pIcode = pProc->Icode.addIcode(&Icode); - switch (ll->getOpcode()) { - /*** Conditional jumps ***/ - case iLOOP: case iLOOPE: case iLOOPNE: - 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: - { STATE StCopy; - int ip = Icode.size()-1; /* Index of this jump */ - ICODE &prev(*(++Icode.rbegin())); /* Previous icode */ - boolT fBranch = false; + switch (Icode.ic.ll.opcode) { + /*** Conditional jumps ***/ + case iLOOP: case iLOOPE: case iLOOPNE: + 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: + { STATE StCopy; + int ip = pProc->Icode.GetNumIcodes()-1; /* Index of this jump */ + PICODE prev = pProc->Icode.GetIcode(ip-1); /* Previous icode */ + boolT fBranch = FALSE; - pstate->JCond.regi = 0; + pstate->JCond.regi = 0; - /* This sets up range check for indexed JMPs hopefully + /* This sets up range check for indexed JMPs hopefully * Handles JA/JAE for fall through and JB/JBE on branch */ - if (ip > 0 && prev.ll()->getOpcode() == iCMP && (prev.ll()->testFlags(I))) - { - pstate->JCond.immed = (int16_t)prev.ll()->src().getImm2(); - if (ll->match(iJA) || ll->match(iJBE) ) - pstate->JCond.immed++; - if (ll->getOpcode() == iJAE || ll->getOpcode() == iJA) - pstate->JCond.regi = prev.ll()->dst.regi; - fBranch = (bool) - (ll->getOpcode() == iJB || ll->getOpcode() == iJBE); - } - StCopy = *pstate; - //memcpy(&StCopy, pstate, sizeof(STATE)); + if (ip > 0 && prev->ic.ll.opcode == iCMP && (prev->ic.ll.flg & I)) + { + pstate->JCond.immed = (int16)prev->ic.ll.immed.op; + if (Icode.ic.ll.opcode == iJA || Icode.ic.ll.opcode == iJBE) + pstate->JCond.immed++; + if (Icode.ic.ll.opcode == iJAE || Icode.ic.ll.opcode == iJA) + pstate->JCond.regi = prev->ic.ll.dst.regi; + fBranch = (boolT) + (Icode.ic.ll.opcode == iJB || Icode.ic.ll.opcode == iJBE); + } - /* Straight line code */ - this->FollowCtrl (pcallGraph, &StCopy); // recurrent ? + memcpy(&StCopy, pstate, sizeof(STATE)); - if (fBranch) /* Do branching code */ - { - pstate->JCond.regi = prev.ll()->dst.regi; - } - /* Next icode. Note: not the same as GetLastIcode() because of the call - to FollowCtrl() */ - pIcode = Icode.GetIcode(ip); - } /* Fall through to do the jump path */ + /* Straight line code */ + FollowCtrl (pProc, pcallGraph, &StCopy); - /*** Jumps ***/ - case iJMP: - case iJMPF: /* Returns true if we've run into a loop */ - done = process_JMP (*pIcode, pstate, pcallGraph); - break; + if (fBranch) /* Do branching code */ + { + pstate->JCond.regi = prev->ic.ll.dst.regi; + } + /* Next icode. Note: not the same as GetLastIcode() because of the call + to FollowCtrl() */ + pIcode = pProc->Icode.GetIcode(ip); + } /* Fall through to do the jump path */ - /*** Calls ***/ - case iCALL: - case iCALLF: - done = process_CALL (*pIcode, pcallGraph, pstate); - pstate->kill(rBX); - pstate->kill(rCX); - break; + /*** Jumps ***/ + case iJMP: + case iJMPF: /* Returns TRUE if we've run into a loop */ + done = process_JMP (pIcode, pProc, pstate, pcallGraph); + break; - /*** Returns ***/ - case iRET: - case iRETF: - this->flg |= (ll->getOpcode() == iRET)? PROC_NEAR:PROC_FAR; - /* Fall through */ - case iIRET: - this->flg &= ~TERMINATES; - done = true; - break; + /*** Calls ***/ + case iCALL: + case iCALLF: + done = process_CALL (pIcode, pProc, pcallGraph, pstate); + break; - case iINT: - if (ll->src().getImm2() == 0x21 && pstate->f[rAH]) - { - int funcNum = pstate->r[rAH]; - int operand; - int size; + /*** Returns ***/ + case iRET: + case iRETF: + pProc->flg |= (Icode.ic.ll.opcode == iRET)? PROC_NEAR:PROC_FAR; + /* Fall through */ + case iIRET: + pProc->flg &= ~TERMINATES; + done = TRUE; + break; - /* Save function number */ - Icode.back().ll()->dst.off = (int16_t)funcNum; - //Icode.GetIcode(Icode.GetNumIcodes() - 1)-> + case iINT: + if (Icode.ic.ll.immed.op == 0x21 && pstate->f[rAH]) + { + Int funcNum = pstate->r[rAH]; + Int operand; + Int size; - /* Program termination: int21h, fn 00h, 31h, 4Ch */ - done = (boolT)(funcNum == 0x00 || funcNum == 0x31 || - funcNum == 0x4C); + /* Save function number */ + pProc->Icode.GetIcode(pProc->Icode.GetNumIcodes() - 1)->ic.ll.dst.off = + (int16)funcNum; - /* String functions: int21h, fn 09h */ - if (pstate->f[rDX]) /* offset goes into DX */ - if (funcNum == 0x09) - { - operand = ((uint32_t)(uint16_t)pstate->r[rDS]<<4) + - (uint32_t)(uint16_t)pstate->r[rDX]; - size = prog.fCOM ? - strSize (&prog.Image[operand], '$') : - strSize (&prog.Image[operand], '$'); // + 0x100 - global_symbol_table.updateSymType (operand, TypeContainer(TYPE_STR, size)); - } - } - else if ((ll->src().getImm2() == 0x2F) && (pstate->f[rAH])) - { - Icode.back().ll()->dst.off = pstate->r[rAH]; - } - else /* Program termination: int20h, int27h */ - done = (boolT)(ll->src().getImm2() == 0x20 || - ll->src().getImm2() == 0x27); - if (done) - pIcode->ll()->setFlags(TERMINATES); - break; + /* Program termination: int21h, fn 00h, 31h, 4Ch */ + done = (boolT)(funcNum == 0x00 || funcNum == 0x31 || + funcNum == 0x4C); - case iMOV: - process_MOV(*pIcode->ll(), pstate); - break; + /* String functions: int21h, fn 09h */ + if (pstate->f[rDX]) /* offset goes into DX */ + if (funcNum == 0x09) + { + operand = ((dword)(word)pstate->r[rDS]<<4) + + (dword)(word)pstate->r[rDX]; + size = prog.fCOM ? + strSize (&prog.Image[operand], '$') : + strSize (&prog.Image[operand + 0x100], '$'); + updateSymType (operand, TYPE_STR, size); + } + } + else if ((Icode.ic.ll.immed.op == 0x2F) && (pstate->f[rAH])) + { + pProc->Icode.GetIcode(pProc->Icode.GetNumIcodes() - 1)->ic.ll.dst.off = + pstate->r[rAH]; + } + else /* Program termination: int20h, int27h */ + done = (boolT)(Icode.ic.ll.immed.op == 0x20 || + Icode.ic.ll.immed.op == 0x27); + if (done) + pIcode->ic.ll.flg |= TERMINATES; + break; - /* case iXCHG: + case iMOV: + process_MOV(pIcode, pstate); + break; + + /* case iXCHG: process_MOV (pIcode, pstate); break; **** HERE ***/ - case iSHL: - if (pstate->JCond.regi == ll->dst.regi) - if ((ll->testFlags(I)) && ll->src().getImm2() == 1) - pstate->JCond.immed *= 2; - else - pstate->JCond.regi = 0; - break; + case iSHL: + if (pstate->JCond.regi == Icode.ic.ll.dst.regi) + if ((Icode.ic.ll.flg & I) && Icode.ic.ll.immed.op == 1) + pstate->JCond.immed *= 2; + else + pstate->JCond.regi = 0; + break; - case iLEA: - if (ll->src().getReg2()== rUNDEF) /* direct mem offset */ - pstate->setState( ll->dst.getReg2(), ll->src().off); - break; + case iLEA: + if (Icode.ic.ll.src.regi == 0) /* direct mem offset */ + setState (pstate, Icode.ic.ll.dst.regi, Icode.ic.ll.src.off); + break; - case iLDS: case iLES: - if ((psym = lookupAddr(&ll->src(), pstate, 4, eDuVal::USE)) - /* && (Icode.ll()->flg & SEG_IMMED) */ ) - { - offset = LH(&prog.Image[psym->label]); - pstate->setState( (ll->getOpcode() == iLDS)? rDS: rES, - LH(&prog.Image[psym->label + 2])); - pstate->setState( ll->dst.regi, (int16_t)offset); - psym->type = TYPE_PTR; - } - break; + case iLDS: case iLES: + if ((psym = lookupAddr(&Icode.ic.ll.src, pstate, 4, USE)) + /* && (Icode.ic.ll.flg & SEG_IMMED) */ ) { + offset = LH(&prog.Image[psym->label]); + setState(pstate, (Icode.ic.ll.opcode == iLDS)? rDS: rES, + LH(&prog.Image[psym->label + 2])); + setState(pstate, Icode.ic.ll.dst.regi, (int16)offset); + psym->type = TYPE_PTR; + } + break; } } if (err) { - this->flg &= ~TERMINATES; + pProc->flg &= ~TERMINATES; if (err == INVALID_386OP || err == INVALID_OPCODE) { - fatalError(err, prog.Image[_Icode.ll()->label], _Icode.ll()->label); - this->flg |= PROC_BADINST; + fatalError(err, prog.Image[Icode.ic.ll.label], Icode.ic.ll.label); + pProc->flg |= PROC_BADINST; } else if (err == IP_OUT_OF_RANGE) - fatalError (err, _Icode.ll()->label); + fatalError (err, Icode.ic.ll.label); else - reportError(err, _Icode.ll()->label); + reportError(err, Icode.ic.ll.label); } } -/* Firstly look for a leading range check of the form:- - * CMP {BX | SI | DI}, immed - * JA | JAE | JB | JBE - * This is stored in the current state as if we had just - * followed a JBE branch (i.e. [reg] lies between 0 - immed). -*/ -void Function::extractJumpTableRange(ICODE& pIcode, STATE *pstate, JumpTable &table) -{ - static uint8_t i2r[4] = {rSI, rDI, rBP, rBX}; - if (pstate->JCond.regi == i2r[pIcode.ll()->src().getReg2()-INDEX_SI]) - table.finish = table.start + pstate->JCond.immed; - else - table.finish = table.start + 2; -} -/* process_JMP - Handles JMPs, returns true if we should end recursion */ -bool Function::followAllTableEntries(JumpTable &table, uint32_t cs, ICODE& pIcode, CALL_GRAPH* pcallGraph, STATE *pstate) -{ - PROG &prog(Project::get()->prog); - STATE StCopy; +static boolT process_JMP (PICODE pIcode, PPROC pProc, PSTATE pstate, + PCALL_GRAPH pcallGraph) +/* process_JMP - Handles JMPs, returns TRUE if we should end recursion */ +{ static byte i2r[4] = {rSI, rDI, rBP, rBX}; + ICODE Icode; + dword cs, offTable, endTable; + dword i, k, seg, target; + Int tmp; - setBits(BM_DATA, table.start, table.size()*table.entrySize()); - - pIcode.ll()->setFlags(SWITCH); - pIcode.ll()->caseTbl2.resize( table.size() ); - assert(pIcode.ll()->caseTbl2.size()<512); - uint32_t k=0; - for (int i = table.start; i < table.finish; i += 2) + if (pIcode->ic.ll.flg & I) { - StCopy = *pstate; - StCopy.IP = cs + LH(&prog.Image[i]); - iICODE last_current_insn = (++Icode.rbegin()).base(); - - FollowCtrl (pcallGraph, &StCopy); - - ++last_current_insn; // incremented here because FollowCtrl might have adde more instructions after the Jmp - last_current_insn->ll()->caseEntry = k++; - last_current_insn->ll()->setFlags(CASE); - pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() ); - } -} - -bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGraph) -{ - PROG &prog(Project::get()->prog); - static uint8_t i2r[4] = {rSI, rDI, rBP, rBX}; - ICODE _Icode; - uint32_t cs, offTable, endTable; - uint32_t i, k, seg, target; - uint32_t tmp; - - if (pIcode.ll()->testFlags(I)) - { - if (pIcode.ll()->getOpcode() == iJMPF) - pstate->setState( rCS, LH(prog.Image + pIcode.ll()->label + 3)); - uint32_t i = pstate->IP = pIcode.ll()->src().getImm2(); + if (pIcode->ic.ll.opcode == iJMPF) + setState(pstate, rCS, LH(prog.Image + pIcode->ic.ll.label + 3)); + i = pstate->IP = pIcode->ic.ll.immed.op; if ((long)i < 0) { - exit(1); + exit(1); } - /* Return true if jump target is already parsed */ - return Icode.alreadyDecoded(i); + /* Return TRUE if jump target is already parsed */ + return pProc->Icode.labelSrch(i, &tmp); } /* We've got an indirect JMP - look for switch() stmt. idiom of the form - * JMP uint16_t ptr word_offset[rBX | rSI | rDI] */ - seg = (pIcode.ll()->src().seg)? pIcode.ll()->src().seg: rDS; + * JMP word ptr word_offset[rBX | rSI | rDI] */ + seg = (pIcode->ic.ll.src.seg)? pIcode->ic.ll.src.seg: rDS; - /* Ensure we have a uint16_t offset & valid seg */ - if (pIcode.ll()->match(iJMP) and (pIcode.ll()->testFlags(WORD_OFF)) && - pstate->f[seg] && - (pIcode.ll()->src().regi == INDEX_SI || - pIcode.ll()->src().regi == INDEX_DI || /* Idx reg. BX, SI, DI */ - pIcode.ll()->src().regi == INDEX_BX)) + /* Ensure we have a word offset & valid seg */ + if (pIcode->ic.ll.opcode == iJMP && (pIcode->ic.ll.flg & WORD_OFF) && + pstate->f[seg] && + (pIcode->ic.ll.src.regi == INDEXBASE + 4 || + pIcode->ic.ll.src.regi == INDEXBASE + 5 || /* Idx reg. BX, SI, DI */ + pIcode->ic.ll.src.regi == INDEXBASE + 7)) { - offTable = ((uint32_t)(uint16_t)pstate->r[seg] << 4) + pIcode.ll()->src().off; + offTable = ((dword)(word)pstate->r[seg] << 4) + pIcode->ic.ll.src.off; /* Firstly look for a leading range check of the form:- * CMP {BX | SI | DI}, immed @@ -462,12 +433,12 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra * This is stored in the current state as if we had just * followed a JBE branch (i.e. [reg] lies between 0 - immed). */ - if (pstate->JCond.regi == i2r[pIcode.ll()->src().regi-(INDEX_BX_SI+4)]) + if (pstate->JCond.regi == i2r[pIcode->ic.ll.src.regi-(INDEXBASE+4)]) endTable = offTable + pstate->JCond.immed; else - endTable = (uint32_t)prog.cbImage; + endTable = (dword)prog.cbImage; - /* Search for first uint8_t flagged after start of table */ + /* Search for first byte flagged after start of table */ for (i = offTable; i <= endTable; i++) if (BITMAP(i, BM_CODE | BM_DATA)) break; @@ -476,13 +447,13 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra /* Now do some heuristic pruning. Look for ptrs. into the table * and for addresses that don't appear to point to valid code. */ - cs = (uint32_t)(uint16_t)pstate->r[rCS] << 4; + cs = (dword)(word)pstate->r[rCS] << 4; for (i = offTable; i < endTable; i += 2) { target = cs + LH(&prog.Image[i]); if (target < endTable && target >= offTable) endTable = target; - else if (target >= (uint32_t)prog.cbImage) + else if (target >= (dword)prog.cbImage) endTable = i; } @@ -491,7 +462,7 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra target = cs + LH(&prog.Image[i]); /* Be wary of 00 00 as code - it's probably data */ if (! (prog.Image[target] || prog.Image[target+1]) || - scan(target, _Icode)) + scan(target, &Icode)) endTable = i; } @@ -499,202 +470,183 @@ bool Function::process_JMP (ICODE & pIcode, STATE *pstate, CALL_GRAPH * pcallGra * state and recursively call FollowCtrl(). */ if (offTable < endTable) { - assert(((endTable - offTable) / 2)<512); STATE StCopy; - int ip; - uint32_t *psw; - + Int ip; + dword *psw; + setBits(BM_DATA, offTable, endTable - offTable); - pIcode.ll()->setFlags(SWITCH); - //pIcode.ll()->caseTbl2.numEntries = (endTable - offTable) / 2; + pIcode->ic.ll.flg |= SWITCH; + pIcode->ic.ll.caseTbl.numEntries = (endTable - offTable) / 2; + psw = (dword*)allocMem(pIcode->ic.ll.caseTbl.numEntries*sizeof(dword)); + pIcode->ic.ll.caseTbl.entries = psw; for (i = offTable, k = 0; i < endTable; i += 2) { - StCopy = *pstate; + memcpy(&StCopy, pstate, sizeof(STATE)); StCopy.IP = cs + LH(&prog.Image[i]); - iICODE last_current_insn = (++Icode.rbegin()).base(); - ip = Icode.size(); + ip = pProc->Icode.GetNumIcodes(); - FollowCtrl (pcallGraph, &StCopy); - ++last_current_insn; - last_current_insn->ll()->caseEntry = k++; - last_current_insn->ll()->setFlags(CASE); - pIcode.ll()->caseTbl2.push_back( last_current_insn->ll()->GetLlLabel() ); + FollowCtrl (pProc, pcallGraph, &StCopy); + pProc->Icode.GetIcode(ip)->ic.ll.caseTbl.numEntries = k++; + pProc->Icode.GetIcode(ip)->ic.ll.flg |= CASE; + *psw++ = pProc->Icode.GetLlLabel(ip); } - return true; + return TRUE; } } /* Can't do anything with this jump */ - flg |= PROC_IJMP; - flg &= ~TERMINATES; - interactDis(this, this->Icode.size()-1); - return true; + pProc->flg |= PROC_IJMP; + pProc->flg &= ~TERMINATES; + interactDis(pProc, pProc->Icode.GetNumIcodes()-1); + return TRUE; } -/* Process procedure call. - * Note: We assume that CALL's will return unless there is good evidence to - * the contrary - thus we return false unless all paths in the called - * procedure end in DOS exits. This is reasonable since C procedures - * will always include the epilogue after the call anyway and it's to - * be assumed that if an assembler program contains a CALL that the - * programmer expected it to come back - otherwise surely a JMP would +static boolT process_CALL (PICODE pIcode, PPROC pProc, PCALL_GRAPH pcallGraph, + PSTATE pstate) +/* Process procedure call. + * Note: We assume that CALL's will return unless there is good evidence to + * the contrary - thus we return FALSE unless all paths in the called + * procedure end in DOS exits. This is reasonable since C procedures + * will always include the epilogue after the call anyway and it's to + * be assumed that if an assembler program contains a CALL that the + * programmer expected it to come back - otherwise surely a JMP would * have been used. */ +{ PPROC p, pPrev; + Int ip = pProc->Icode.GetNumIcodes() - 1; + STATE localState; /* Local copy of the machine state */ + dword off; + boolT indirect; -boolT Function::process_CALL (ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *pstate) -{ - PROG &prog(Project::get()->prog); - ICODE &last_insn(Icode.back()); - STATE localState; /* Local copy of the machine state */ - uint32_t off; - boolT indirect; + /* For Indirect Calls, find the function address */ + indirect = FALSE; + if (! (pIcode->ic.ll.flg & I)) + { + /* Not immediate, i.e. indirect call */ - /* For Indirect Calls, find the function address */ - indirect = false; - //pIcode.ll()->immed.proc.proc=fakeproc; - if ( not pIcode.ll()->testFlags(I) ) - { - /* Not immediate, i.e. indirect call */ + if (pIcode->ic.ll.dst.regi && (!option.Calls)) + { + /* We have not set the brave option to attempt to follow + the execution path through register indirect calls. + So we just exit this function, and ignore the call. + We probably should not have parsed this deep, anyway. + */ + return FALSE; + } - if (pIcode.ll()->dst.regi && (!option.Calls)) - { - /* We have not set the brave option to attempt to follow - the execution path through register indirect calls. - So we just exit this function, and ignore the call. - We probably should not have parsed this deep, anyway. - */ - return false; - } + /* Offset into program image is seg:off of read input */ + /* Note: this assumes that the pointer itself is at + es:0 where es:0 is the start of the image. This is + usually wrong! Consider also CALL [BP+0E] in which the + segment for the pointer is in SS! - Mike */ - /* Offset into program image is seg:off of read input */ - /* Note: this assumes that the pointer itself is at - es:0 where es:0 is the start of the image. This is - usually wrong! Consider also CALL [BP+0E] in which the - segment for the pointer is in SS! - Mike */ - if(pIcode.ll()->dst.isReg()) - { - if( not pstate->isKnown(pIcode.ll()->dst.regi) - or - not pstate->isKnown(pIcode.ll()->dst.seg) - ) - { - fprintf(stderr,"Indirect call with unkown register values\n"); - return false; - } - off = pstate->r[pIcode.ll()->dst.seg]; - off <<=4; - off += pstate->r[pIcode.ll()->dst.regi]; + off = (dword)(word)pIcode->ic.ll.dst.off + + ((dword)(word)pIcode->ic.ll.dst.segValue << 4); - } - else - { - off = (uint32_t)(uint16_t)pIcode.ll()->dst.off + - ((uint32_t)(uint16_t)pIcode.ll()->dst.segValue << 4); - } + /* Address of function is given by 4 (CALLF) or 2 (CALL) bytes at + * previous offset into the program image */ + if (pIcode->ic.ll.opcode == iCALLF) + pIcode->ic.ll.immed.op = LH(&prog.Image[off]) + + ((dword)(LH(&prog.Image[off+2])) << 4); + else + pIcode->ic.ll.immed.op = LH(&prog.Image[off]) + + ((dword)(word)pProc->state.r[rCS] << 4); + pIcode->ic.ll.flg |= I; + indirect = TRUE; + } - /* Address of function is given by 4 (CALLF) or 2 (CALL) bytes at - * previous offset into the program image */ - uint32_t tgtAddr=0; - if (pIcode.ll()->getOpcode() == iCALLF) - tgtAddr= LH(&prog.Image[off]) + (uint32_t)(LH(&prog.Image[off+2])) << 4; - else - tgtAddr= LH(&prog.Image[off]) + (uint32_t)(uint16_t)state.r[rCS] << 4; - pIcode.ll()->replaceSrc(LLOperand::CreateImm2( tgtAddr ) ); - pIcode.ll()->setFlags(I); - indirect = true; - } - - /* Process CALL. Function address is located in pIcode.ll()->immed.op */ - if (pIcode.ll()->testFlags(I)) - { + /* Process CALL. Function address is located in pIcode->ic.ll.immed.op */ + if (pIcode->ic.ll.flg & I) + { /* Search procedure list for one with appropriate entry point */ - ilFunction iter = g_proj.findByEntry(pIcode.ll()->src().getImm2()); + for (p = pProcList; p && p->procEntry != pIcode->ic.ll.immed.op; + p = p->next) + pPrev = p; /* Create a new procedure node and save copy of the state */ - if ( not g_proj.valid(iter) ) - { - iter = g_proj.createFunction(); - Function &x(*iter); - x.procEntry = pIcode.ll()->src().getImm2(); - LibCheck(x); + if (! p) { + p = allocStruc(PROCEDURE); + p = (PPROC)memset(p, 0, sizeof(PROCEDURE)); + pPrev->next = p; + p->prev = pPrev; + p->procEntry = pIcode->ic.ll.immed.op; + pLastProc = p; /* Pointer to last node in the list */ - if (x.flg & PROC_ISLIB) + LibCheck(p); + + if (p->flg & PROC_ISLIB) { /* A library function. No need to do any more to it */ - pcallGraph->insertCallGraph (this, iter); - //iter = (++pProcList.rbegin()).base(); - last_insn.ll()->src().proc.proc = &x; - return false; + insertCallGraph (pcallGraph, pProc, p); + pProc->Icode.GetIcode(ip)->ic.ll.immed.proc.proc = p; + return FALSE; } - if (indirect) - x.flg |= PROC_ICALL; + if (indirect) + p->flg |= PROC_ICALL; - if (x.name.empty()) /* Don't overwrite existing name */ + if (p->name[0] == '\0') /* Don't overwrite existing name */ { - ostringstream os; - os<<"proc_"<< ++prog.cProcs; - x.name = os.str(); + sprintf(p->name, "proc_%ld", ++prog.cProcs); } - x.depth = x.depth + 1; - x.flg |= TERMINATES; + p->depth = pProc->depth + 1; + p->flg |= TERMINATES; /* Save machine state in localState, load up IP and CS.*/ - localState = *pstate; - pstate->IP = pIcode.ll()->src().getImm2(); - if (pIcode.ll()->getOpcode() == iCALLF) - pstate->setState( rCS, LH(prog.Image + pIcode.ll()->label + 3)); - x.state = *pstate; + memcpy (&localState, pstate, sizeof(STATE)); + pstate->IP = pIcode->ic.ll.immed.op; + if (pIcode->ic.ll.opcode == iCALLF) + setState (pstate, rCS, LH(prog.Image + pIcode->ic.ll.label + 3)); + memcpy(&(p->state), pstate, sizeof(STATE)); /* Insert new procedure in call graph */ - pcallGraph->insertCallGraph (this, iter); + insertCallGraph (pcallGraph, pProc, p); /* Process new procedure */ - x.FollowCtrl (pcallGraph, pstate); - + FollowCtrl (p, pcallGraph, pstate); + /* Restore segment registers & IP from localState */ pstate->IP = localState.IP; - pstate->setState( rCS, localState.r[rCS]); - pstate->setState( rDS, localState.r[rDS]); - pstate->setState( rES, localState.r[rES]); - pstate->setState( rSS, localState.r[rSS]); + setState (pstate, rCS, localState.r[rCS]); + setState (pstate, rDS, localState.r[rDS]); + setState (pstate, rES, localState.r[rES]); + setState (pstate, rSS, localState.r[rSS]); } else - g_proj.callGraph->insertCallGraph (this, iter); - - last_insn.ll()->src().proc.proc = &(*iter); // ^ target proc + insertCallGraph (pcallGraph, pProc, p); + pProc->Icode.GetIcode(ip)->ic.ll.immed.proc.proc = p; /* ^ target proc */ /* return ((p->flg & TERMINATES) != 0); */ + return FALSE; } - return false; // Cristina, please check!! + return FALSE; // Cristina, please check!! } +static void process_MOV(PICODE pIcode, PSTATE pstate) /* process_MOV - Handles state changes due to simple assignments */ -static void process_MOV(LLInst & ll, STATE * pstate) -{ - PROG &prog(Project::get()->prog); - SYM * psym, *psym2; /* Pointer to symbol in global symbol table */ - uint8_t dstReg = ll.dst.regi; - uint8_t srcReg = ll.src().regi; - if (dstReg > 0 && dstReg < INDEX_BX_SI) +{ PSYM psym, psym2; /* Pointer to symbol in global symbol table */ + byte dstReg = pIcode->ic.ll.dst.regi; + byte srcReg = pIcode->ic.ll.src.regi; + + if (dstReg > 0 && dstReg < INDEXBASE) { - if (ll.testFlags(I)) - pstate->setState( dstReg, (int16_t)ll.src().getImm2()); + if (pIcode->ic.ll.flg & I) + setState(pstate, dstReg, (int16)pIcode->ic.ll.immed.op); else if (srcReg == 0) /* direct memory offset */ { - psym = lookupAddr(&ll.src(), pstate, 2, eDuVal::USE); - if (psym && ((psym->flg & SEG_IMMED) || psym->duVal.val)) - pstate->setState( dstReg, LH(&prog.Image[psym->label])); + psym = lookupAddr(&pIcode->ic.ll.src, pstate, 2, USE); + if (psym && ((psym->flg & SEG_IMMED) || (psym->duVal & VAL))) + setState(pstate, dstReg, LH(&prog.Image[psym->label])); } - else if (srcReg < INDEX_BX_SI && pstate->f[srcReg]) /* reg */ + else if (srcReg < INDEXBASE && pstate->f[srcReg]) /* reg */ { - pstate->setState( dstReg, pstate->r[srcReg]); + setState(pstate, dstReg, pstate->r[srcReg]); /* Follow moves of the possible index register */ if (pstate->JCond.regi == srcReg) @@ -702,401 +654,441 @@ static void process_MOV(LLInst & ll, STATE * pstate) } } else if (dstReg == 0) { /* direct memory offset */ - int size=2; - if((ll.src().regi>=rAL)&&(ll.src().regi<=rBH)) - size=1; - psym = lookupAddr (&ll.dst, pstate, size, eDEF); - if (psym && ! (psym->duVal.val)) /* no initial value yet */ - if (ll.testFlags(I)) /* immediate */ + psym = lookupAddr (&pIcode->ic.ll.dst, pstate, 2, DEF); + if (psym && ! (psym->duVal & VAL)) /* no initial value yet */ + if (pIcode->ic.ll.flg & I) { /* immediate */ + prog.Image[psym->label] = (byte)pIcode->ic.ll.immed.op; + prog.Image[psym->label+1] = (byte)(pIcode->ic.ll.immed.op>>8); + psym->duVal |= VAL; + } + else if (srcReg == 0) { /* direct mem offset */ + psym2 = lookupAddr (&pIcode->ic.ll.src, pstate, 2, USE); + if (psym2 && ((psym->flg & SEG_IMMED) || (psym->duVal & VAL))) { - prog.Image[psym->label] = (uint8_t)ll.src().getImm2(); - if(psym->size>1) - prog.Image[psym->label+1] = (uint8_t)(ll.src().getImm2()>>8); - psym->duVal.val = 1; - } - else if (srcReg == 0) /* direct mem offset */ - { - psym2 = lookupAddr (&ll.src(), pstate, 2, eDuVal::USE); - if (psym2 && ((psym->flg & SEG_IMMED) || (psym->duVal.val))) - { - prog.Image[psym->label] = (uint8_t)prog.Image[psym2->label]; - if(psym->size>1) - prog.Image[psym->label+1] = prog.Image[psym2->label+1];//(uint8_t)(prog.Image[psym2->label+1] >> 8); - psym->duVal.setFlags(eDuVal::DEF); - psym2->duVal.setFlags(eDuVal::USE); - } - } - else if (srcReg < INDEX_BX_SI && pstate->f[srcReg]) /* reg */ - { - prog.Image[psym->label] = (uint8_t)pstate->r[srcReg]; - if(psym->size>1) - prog.Image[psym->label+1] = (uint8_t)(pstate->r[srcReg] >> 8); - psym->duVal.setFlags(eDuVal::DEF); + prog.Image[psym->label] = (byte)prog.Image[psym2->label]; + prog.Image[psym->label+1] = + (byte)(prog.Image[psym2->label+1] >> 8); + psym->duVal |= VAL; } + } + else if (srcReg < INDEXBASE && pstate->f[srcReg]) /* reg */ + { + prog.Image[psym->label] = (byte)pstate->r[srcReg]; + prog.Image[psym->label+1] = (byte)(pstate->r[srcReg] >> 8); + psym->duVal |= VAL; + } } } +/* Type of the symbol according to the number of bytes it uses */ +static hlType cbType[] = {TYPE_UNKNOWN, TYPE_BYTE_UNSIGN, TYPE_WORD_SIGN, + TYPE_UNKNOWN, TYPE_LONG_SIGN}; +static PSYM updateGlobSym (dword operand, Int size, word duFlag) +/* Creates an entry in the global symbol table (symtab) if the variable + * is not there yet. If it is part of the symtab, the size of the variable + * is checked and updated if the old size was less than the new size (ie. + * the maximum size is always saved). */ +{ Int i; + + /* Check for symbol in symbol table */ + for (i = 0; i < symtab.csym; i++) + if (symtab.sym[i].label == operand) { + if (symtab.sym[i].size < size) + symtab.sym[i].size = size; + break; + } + + /* New symbol, not in symbol table */ + if (i == symtab.csym) { + if (++symtab.csym > symtab.alloc) { + symtab.alloc += 5; + symtab.sym = (PSYM)reallocVar(symtab.sym, symtab.alloc * sizeof(SYM)); + memset (&symtab.sym[i], 0, 5 * sizeof(SYM)); + } + sprintf (symtab.sym[i].name, "var%05lX", operand); + symtab.sym[i].label = operand; + symtab.sym[i].size = size; + symtab.sym[i].type = cbType[size]; + if (duFlag == USE) /* must already have init value */ + symtab.sym[i].duVal = USEVAL; + else + symtab.sym[i].duVal = duFlag; + } + return (&symtab.sym[i]); +} + + +static void updateFrameOff (PSTKFRAME ps, int16 off, Int size, word duFlag) /* Updates the offset entry to the stack frame table (arguments), * and returns a pointer to such entry. */ -void STKFRAME::updateFrameOff ( int16_t off, int _size, uint16_t duFlag) -{ - int i; +{ Int i; /* Check for symbol in stack frame table */ - auto iter=findByLabel(off); - if(iter!=end()) - { - if (iter->size < _size) - { - iter->size = _size; - } + for (i = 0; i < ps->csym; i++) + { + if (ps->sym[i].off == off) + { + if (ps->sym[i].size < size) + { + ps->sym[i].size = size; + } + break; } - else - { - char nm[16]; - STKSYM new_sym; + } - sprintf (nm, "arg%ld", size()); - new_sym.name = nm; - new_sym.label= off; - new_sym.size = _size; - new_sym.type = TypeContainer::defaultTypeForSize(_size); - if (duFlag == eDuVal::USE) /* must already have init value */ - { - new_sym.duVal.use=1; - //new_sym.duVal.val=1; + /* New symbol, not in table */ + if (i == ps->csym) + { + if (++ps->csym > ps->alloc) + { + ps->alloc += 5; + ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM)); + memset(&ps->sym[i], 0, 5*sizeof(STKSYM)); } + sprintf (ps->sym[i].name, "arg%ld", i); + ps->sym[i].off = off; + ps->sym[i].size = size; + ps->sym[i].type = cbType[size]; + if (duFlag == USE) /* must already have init value */ + ps->sym[i].duVal = USEVAL; else - { - new_sym.duVal.setFlags(duFlag); - } - push_back(new_sym); - this->numArgs++; + ps->sym[i].duVal = duFlag; + ps->cb += size; + ps->numArgs++; } /* Save maximum argument offset */ - if ((uint32_t)this->maxOff < (off + (uint32_t)_size)) - this->maxOff = off + (int16_t)_size; + if ((dword)ps->maxOff < (off + (dword)size)) + ps->maxOff = off + (int16)size; } -/* lookupAddr - Looks up a data reference in the symbol table and stores it - * if necessary. - * Returns a pointer to the symbol in the +static PSYM lookupAddr (PMEM pm, PSTATE pstate, Int size, word duFlag) +/* lookupAddr - Looks up a data reference in the symbol table and stores it + * if necessary. Returns a pointer to the symbol in the * symbol table, or Null if it's not a direct memory offset. */ -static SYM * lookupAddr (LLOperand *pm, STATE *pstate, int size, uint16_t duFlag) -{ - PROG &prog(Project::get()->prog); - int i; - SYM * psym=nullptr; - uint32_t operand; - bool created_new=false; - if (pm->regi != rUNDEF) - return nullptr; // register or indexed +{ Int i; + PSYM psym; + dword operand; - /* Global var */ - if (pm->segValue) /* there is a value in the seg field */ - { + if (pm->regi == 0) { /* Global var */ + if (pm->segValue) { /* there is a value in the seg field */ operand = opAdr (pm->segValue, pm->off); - psym = g_proj.symtab.updateGlobSym (operand, size, duFlag,created_new); + psym = updateGlobSym (operand, size, duFlag); + + /* Check for out of bounds */ + if (psym->label >= (dword)prog.cbImage) + return (NULL); + return (psym); } - else if (pstate->f[pm->seg]) /* new value */ - { + else if (pstate->f[pm->seg]) { /* new value */ pm->segValue = pstate->r[pm->seg]; operand = opAdr(pm->segValue, pm->off); - psym = g_proj.symtab.updateGlobSym (operand, size, duFlag,created_new); + i = symtab.csym; + psym = updateGlobSym (operand, size, duFlag); /* Flag new memory locations that are segment values */ - if (created_new) - { + if (symtab.csym > i) { if (size == 4) - operand += 2; /* High uint16_t */ + operand += 2; /* High word */ for (i = 0; i < prog.cReloc; i++) if (prog.relocTable[i] == operand) { psym->flg = SEG_IMMED; break; } } + + /* Check for out of bounds */ + if (psym->label >= (dword)prog.cbImage) + return (NULL); + return (psym); } - /* Check for out of bounds */ - if (psym && (psym->label>=0) and (psym->label < (uint32_t)prog.cbImage)) - return psym; - return nullptr; + } + return (NULL); } +void setState(PSTATE pstate, word reg, int16 value) /* setState - Assigns a value to a reg. */ -void STATE::setState(uint16_t reg, int16_t value) { value &= 0xFFFF; - r[reg] = value; - f[reg] = true; + pstate->r[reg] = value; + pstate->f[reg] = TRUE; switch (reg) { - case rAX: case rCX: case rDX: case rBX: - r[reg + rAL - rAX] = value & 0xFF; - f[reg + rAL - rAX] = true; - r[reg + rAH - rAX] = (value >> 8) & 0xFF; - f[reg + rAH - rAX] = true; - break; + case rAX: case rCX: case rDX: case rBX: + pstate->r[reg + rAL - rAX] = value & 0xFF; + pstate->f[reg + rAL - rAX] = TRUE; + pstate->r[reg + rAH - rAX] = (value >> 8) & 0xFF; + pstate->f[reg + rAH - rAX] = TRUE; + break; - case rAL: case rCL: case rDL: case rBL: - if (f[reg - rAL + rAH]) { - r[reg - rAL + rAX] =(r[reg - rAL + rAH] << 8) + (value & 0xFF); - f[reg - rAL + rAX] = true; - } - break; + case rAL: case rCL: case rDL: case rBL: + if (pstate->f[reg - rAL + rAH]) { + pstate->r[reg - rAL + rAX] = + (pstate->r[reg - rAL + rAH] << 8) + (value & 0xFF); + pstate->f[reg - rAL + rAX] = TRUE; + } + break; - case rAH: case rCH: case rDH: case rBH: - if (f[reg - rAH + rAL]) - { - r[reg - rAH + rAX] = r[reg - rAH + rAL] + ((value & 0xFF) << 8); - f[reg - rAH + rAX] = true; - } - break; + case rAH: case rCH: case rDH: case rBH: + if (pstate->f[reg - rAH + rAL]) { + pstate->r[reg - rAH + rAX] = + pstate->r[reg - rAH + rAL] + ((value & 0xFF) << 8); + pstate->f[reg - rAH + rAX] = TRUE; + } + break; } } +boolT labelSrch(PICODE pIcode, Int numIp, dword target, Int *pIndex) /* labelSrchRepl - Searches Icode for instruction with label = target, and replaces *pIndex with an icode index */ - - -/* setBits - Sets memory bitmap bits for BM_CODE or BM_DATA (additively) */ -static void setBits(int16_t type, uint32_t start, uint32_t len) { - PROG &prog(Project::get()->prog); - uint32_t i; + Int i; - if (start < (uint32_t)prog.cbImage) + for (i = 0; i < numIp; i++) { - if (start + len > (uint32_t)prog.cbImage) - len = (uint32_t)(prog.cbImage - start); + if (pIcode[i].ic.ll.label == target) + { + *pIndex = i; + return TRUE; + } + } + return FALSE; +} + + +static void setBits(int16 type, dword start, dword len) +/* setBits - Sets memory bitmap bits for BM_CODE or BM_DATA (additively) */ +{ + dword i; + + if (start < (dword)prog.cbImage) + { + if (start + len > (dword)prog.cbImage) + len = (dword)(prog.cbImage - start); for (i = start + len - 1; i >= start; i--) - { + { prog.map[i >> 2] |= type << ((i & 3) << 1); - if (i == 0) break; // Fixes inf loop! - } + if (i == 0) break; // Fixes inf loop! + } } } + /* DU bit definitions for each reg value - including index registers */ -std::bitset<32> duReg[] = { 0x00, - //AH AL . . AX, BH - 0x11001, 0x22002, 0x44004, 0x88008, /* uint16_t regs */ - 0x10, 0x20, 0x40, 0x80, - 0x100, 0x200, 0x400, 0x800, /* seg regs */ - 0x1000, 0x2000, 0x4000, 0x8000, /* uint8_t regs */ - 0x10000, 0x20000, 0x40000, 0x80000, - 0x100000, /* tmp reg */ - 0x48, 0x88, 0x60, 0xA0, /* index regs */ - 0x40, 0x80, 0x20, 0x08 }; +dword duReg[] = { 0x00, + 0x11001, 0x22002, 0x44004, 0x88008, /* word regs */ + 0x10, 0x20, 0x40, 0x80, + 0x100, 0x200, 0x400, 0x800, /* seg regs */ + 0x1000, 0x2000, 0x4000, 0x8000, /* byte regs */ + 0x10000, 0x20000, 0x40000, 0x80000, + 0x100000, /* tmp reg */ + 0x48, 0x88, 0x60, 0xA0, /* index regs */ + 0x40, 0x80, 0x20, 0x08 }; -/* Checks which registers were used and updates the du.u flag. - * Places local variables on the local symbol table. +static void use (opLoc d, PICODE pIcode, PPROC pProc, PSTATE pstate, Int size, + Int ix) +/* Checks which registers where used and updates the du.u flag. + * Places local variables on the local symbol table. * Arguments: d : SRC or DST icode operand * pIcode: ptr to icode instruction * pProc : ptr to current procedure structure * pstate: ptr to current procedure state * size : size of the operand * ix : current index into icode array */ -static void use (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int size, int ix) -{ - const LLOperand * pm = pIcode.ll()->get(d) ; - SYM * psym; +{ PMEM pm = (d == SRC)? &pIcode->ic.ll.src: &pIcode->ic.ll.dst; + PSYM psym; - if ( Machine_X86::isMemOff(pm->regi) ) + if (pm->regi == 0 || pm->regi >= INDEXBASE) { - if (pm->regi == INDEX_BP) /* indexed on bp */ + if (pm->regi == INDEXBASE + 6) /* indexed on bp */ { if (pm->off >= 2) - pProc->args.updateFrameOff ( pm->off, size, eDuVal::USE); - else if (pm->off < 0) - pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off, 0); + updateFrameOff (&pProc->args, pm->off, size, USE); + else if (pm->off < 0) + newByteWordStkId (&pProc->localId, TYPE_WORD_SIGN, pm->off, 0); } - else if (pm->regi == INDEX_BP_SI || pm->regi == INDEX_BP_DI) - pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off, - (uint8_t)((pm->regi == INDEX_BP_SI) ? rSI : rDI)); + else if (pm->regi == INDEXBASE + 2 || pm->regi == INDEXBASE + 3) + newByteWordStkId (&pProc->localId, TYPE_WORD_SIGN, pm->off, + (byte)((pm->regi == INDEXBASE + 2) ? rSI : rDI)); - else if ((pm->regi >= INDEX_SI) && (pm->regi <= INDEX_BX)) + else if ((pm->regi >= INDEXBASE + 4) && (pm->regi <= INDEXBASE + 7)) { - if ((pm->seg == rDS) && (pm->regi == INDEX_BX)) /* bx */ + if ((pm->seg == rDS) && (pm->regi == INDEXBASE + 7)) /* bx */ { if (pm->off > 0) /* global indexed variable */ - pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,ix, TYPE_WORD_SIGN); + newIntIdxId (&pProc->localId, pm->segValue, pm->off, rBX, + ix, TYPE_WORD_SIGN); } - pIcode.du.use |= duReg[pm->regi]; + pIcode->du.use |= duReg[pm->regi]; } - else if (psym = lookupAddr(const_cast(pm), pstate, size, eDuVal::USE)) + else if (psym = lookupAddr(pm, pstate, size, USE)) { - setBits (BM_DATA, psym->label, (uint32_t)size); - pIcode.ll()->setFlags(SYM_USE); - pIcode.ll()->caseEntry = distance(&g_proj.symtab[0],psym); //WARNING: was setting case count - + setBits (BM_DATA, psym->label, (dword)size); + pIcode->ic.ll.flg |= SYM_USE; + pIcode->ic.ll.caseTbl.numEntries = psym - symtab.sym; } } /* Use of register */ - else if ((d == DST) || ((d == SRC) && (not pIcode.ll()->testFlags(I)))) - pIcode.du.use |= duReg[pm->regi]; + else if ((d == DST) || ((d == SRC) && (pIcode->ic.ll.flg & I) != I)) + pIcode->du.use |= duReg[pm->regi]; } +static void def (opLoc d, PICODE pIcode, PPROC pProc, PSTATE pstate, Int size, + Int ix) /* Checks which registers were defined (ie. got a new value) and updates the * du.d flag. * Places local variables in the local symbol table. */ -static void def (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int size, - int ix) -{ - LLOperand *pm = pIcode.ll()->get(d); - SYM * psym; +{ PMEM pm = (d == SRC)? &pIcode->ic.ll.src: &pIcode->ic.ll.dst; + PSYM psym; - if (pm->regi == 0 || pm->regi >= INDEX_BX_SI) + if (pm->regi == 0 || pm->regi >= INDEXBASE) { - if (pm->regi == INDEX_BP) /* indexed on bp */ + if (pm->regi == INDEXBASE + 6) /* indexed on bp */ { if (pm->off >= 2) - pProc->args.updateFrameOff ( pm->off, size, eDEF); + updateFrameOff (&pProc->args, pm->off, size, DEF); else if (pm->off < 0) - pProc->localId.newByteWordStk (TYPE_WORD_SIGN, pm->off, 0); + newByteWordStkId (&pProc->localId, TYPE_WORD_SIGN, pm->off, 0); } - else if (pm->regi == INDEX_BP_SI || pm->regi == INDEX_BP_DI) + else if (pm->regi == INDEXBASE + 2 || pm->regi == INDEXBASE + 3) { - pProc->localId.newByteWordStk(TYPE_WORD_SIGN, pm->off, - (uint8_t)((pm->regi == INDEX_BP_SI) ? rSI : rDI)); + newByteWordStkId (&pProc->localId, TYPE_WORD_SIGN, pm->off, + (byte)((pm->regi == INDEXBASE + 2) ? rSI : rDI)); } - else if ((pm->regi >= INDEX_SI) && (pm->regi <= INDEX_BX)) + else if ((pm->regi >= INDEXBASE + 4) && (pm->regi <= INDEXBASE + 7)) { - if ((pm->seg == rDS) && (pm->regi == INDEX_BX)) /* bx */ + if ((pm->seg == rDS) && (pm->regi == INDEXBASE + 7)) /* bx */ { if (pm->off > 0) /* global var */ - pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,ix, TYPE_WORD_SIGN); + newIntIdxId (&pProc->localId, pm->segValue, pm->off, rBX, + ix, TYPE_WORD_SIGN); } - pIcode.du.use |= duReg[pm->regi]; + pIcode->du.use |= duReg[pm->regi]; } - else if (psym = lookupAddr(pm, pstate, size, eDEF)) + else if (psym = lookupAddr(pm, pstate, size, DEF)) { - setBits(BM_DATA, psym->label, (uint32_t)size); - pIcode.ll()->setFlags(SYM_DEF); - pIcode.ll()->caseEntry = distance(&g_proj.symtab[0],psym); // WARNING: was setting Case count + setBits(BM_DATA, psym->label, (dword)size); + pIcode->ic.ll.flg |= SYM_DEF; + pIcode->ic.ll.caseTbl.numEntries = psym - symtab.sym; } } /* Definition of register */ - else if ((d == DST) || ((d == SRC) && (not pIcode.ll()->testFlags(I)))) + else if ((d == DST) || ((d == SRC) && (pIcode->ic.ll.flg & I) != I)) { - pIcode.du.def |= duReg[pm->regi]; - pIcode.du1.numRegsDef++; + pIcode->du.def |= duReg[pm->regi]; + pIcode->du1.numRegsDef++; } } +static void use_def(opLoc d, PICODE pIcode, PPROC pProc, PSTATE pstate, Int cb, + Int ix) /* use_def - operand is both use and def'd. * Note: the destination will always be a register, stack variable, or global * variable. */ -static void use_def(opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int cb, - int ix) { - const LLOperand * pm = pIcode.ll()->get(d); + PMEM pm = (d == SRC)? &pIcode->ic.ll.src: &pIcode->ic.ll.dst; use (d, pIcode, pProc, pstate, cb, ix); - if (pm->regi < INDEX_BX_SI) /* register */ + if (pm->regi < INDEXBASE) /* register */ { - pIcode.du.def |= duReg[pm->regi]; - pIcode.du1.numRegsDef++; + pIcode->du.def |= duReg[pm->regi]; + pIcode->du1.numRegsDef++; } } +static void process_operands(PICODE pIcode, PPROC pProc, PSTATE pstate, Int ix) /* Set DU vector, local variables and arguments, and DATA bits in the * bitmap */ -extern LLOperand convertOperand(const x86_op_t &from); -void Function::process_operands(ICODE & pIcode, STATE * pstate) -{ - int ix=Icode.size(); - LLInst &ll_ins(*pIcode.ll()); +{ Int i; + Int sseg = (pIcode->ic.ll.src.seg)? pIcode->ic.ll.src.seg: rDS; + Int cb = (pIcode->ic.ll.flg & B) ? 1: 2; + flags32 Imm = (pIcode->ic.ll.flg & I); - int sseg = (ll_ins.src().seg)? ll_ins.src().seg: rDS; - int cb = pIcode.ll()->testFlags(B) ? 1: 2; - //x86_op_t *im= pIcode.insn.x86_get_imm(); - bool Imm = (pIcode.ll()->testFlags(I)); - - switch (pIcode.ll()->getOpcode()) { + switch (pIcode->ic.ll.opcode) { case iAND: case iOR: case iXOR: case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL: case iROR: case iADD: case iADC: case iSUB: case iSBB: if (! Imm) { - use(SRC, pIcode, this, pstate, cb, ix); + use(SRC, pIcode, pProc, pstate, cb, ix); } case iINC: case iDEC: case iNEG: case iNOT: case iAAA: case iAAD: case iAAM: case iAAS: case iDAA: case iDAS: - use_def(DST, pIcode, this, pstate, cb, ix); + use_def(DST, pIcode, pProc, pstate, cb, ix); break; case iXCHG: - /* This instruction is replaced by 3 instructions, only need - * to define the src operand and use the destination operand - * in the mean time. */ - use(SRC, pIcode, this, pstate, cb, ix); - def(DST, pIcode, this, pstate, cb, ix); + /* This instruction is replaced by 3 instructions, only need + * to define the src operand and use the destination operand + * in the mean time. */ + use(SRC, pIcode, pProc, pstate, cb, ix); + def(DST, pIcode, pProc, pstate, cb, ix); break; case iTEST: case iCMP: if (! Imm) - use(SRC, pIcode, this, pstate, cb, ix); - use(DST, pIcode, this, pstate, cb, ix); + use(SRC, pIcode, pProc, pstate, cb, ix); + use(DST, pIcode, pProc, pstate, cb, ix); break; case iDIV: case iIDIV: - use(SRC, pIcode, this, pstate, cb, ix); - if (cb == 1) - pIcode.du.use |= duReg[rTMP]; + use(SRC, pIcode, pProc, pstate, cb, ix); + if (cb == 1) + pIcode->du.use |= duReg[rTMP]; break; case iMUL: case iIMUL: - use(SRC, pIcode, this, pstate, cb, ix); + use(SRC, pIcode, pProc, pstate, cb, ix); if (! Imm) { - use (DST, pIcode, this, pstate, cb, ix); + use (DST, pIcode, pProc, pstate, cb, ix); if (cb == 1) { - pIcode.du.def |= duReg[rAX]; - pIcode.du1.numRegsDef++; + pIcode->du.def |= duReg[rAX]; + pIcode->du1.numRegsDef++; } else { - pIcode.du.def |= (duReg[rAX] | duReg[rDX]); - pIcode.du1.numRegsDef += 2; + pIcode->du.def |= (duReg[rAX] | duReg[rDX]); + pIcode->du1.numRegsDef += 2; } } else - def (DST, pIcode, this, pstate, cb, ix); + def (DST, pIcode, pProc, pstate, cb, ix); break; case iSIGNEX: - cb = pIcode.ll()->testFlags(SRC_B) ? 1 : 2; - if (cb == 1) /* uint8_t */ + cb = (pIcode->ic.ll.flg & SRC_B) ? 1 : 2; + if (cb == 1) /* byte */ { - pIcode.du.def |= duReg[rAX]; - pIcode.du1.numRegsDef++; - pIcode.du.use |= duReg[rAL]; + pIcode->du.def |= duReg[rAX]; + pIcode->du1.numRegsDef++; + pIcode->du.use |= duReg[rAL]; } - else /* uint16_t */ + else /* word */ { - pIcode.du.def |= (duReg[rDX] | duReg[rAX]); - pIcode.du1.numRegsDef += 2; - pIcode.du.use |= duReg[rAX]; + pIcode->du.def |= (duReg[rDX] | duReg[rAX]); + pIcode->du1.numRegsDef += 2; + pIcode->du.use |= duReg[rAX]; } break; @@ -1104,106 +1096,111 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate) cb = 4; case iCALL: case iPUSH: case iPOP: if (! Imm) { - if (pIcode.ll()->getOpcode() == iPOP) - def(DST, pIcode, this, pstate, cb, ix); + if (pIcode->ic.ll.opcode == iPOP) + def(DST, pIcode, pProc, pstate, cb, ix); else - use(DST, pIcode, this, pstate, cb, ix); + use(DST, pIcode, pProc, pstate, cb, ix); } break; case iESC: /* operands may be larger */ - use(DST, pIcode, this, pstate, cb, ix); + use(DST, pIcode, pProc, pstate, cb, ix); break; case iLDS: case iLES: - pIcode.du.def |= duReg[(pIcode.ll()->getOpcode() == iLDS) ? rDS : rES]; - pIcode.du1.numRegsDef++; + pIcode->du.def |= duReg[(pIcode->ic.ll.opcode == iLDS) ? + rDS : rES]; + pIcode->du1.numRegsDef++; cb = 4; case iMOV: - use(SRC, pIcode, this, pstate, cb, ix); - def(DST, pIcode, this, pstate, cb, ix); + use(SRC, pIcode, pProc, pstate, cb, ix); + def(DST, pIcode, pProc, pstate, cb, ix); break; case iLEA: - use(SRC, pIcode, this, pstate, 2, ix); - def(DST, pIcode, this, pstate, 2, ix); + use(SRC, pIcode, pProc, pstate, 2, ix); + def(DST, pIcode, pProc, pstate, 2, ix); break; case iBOUND: - use(SRC, pIcode, this, pstate, 4, ix); - use(DST, pIcode, this, pstate, cb, ix); + use(SRC, pIcode, pProc, pstate, 4, ix); + use(DST, pIcode, pProc, pstate, cb, ix); break; case iJMPF: cb = 4; case iJMP: if (! Imm) - use(SRC, pIcode, this, pstate, cb, ix); + use(SRC, pIcode, pProc, pstate, cb, ix); break; case iLOOP: case iLOOPE: case iLOOPNE: - pIcode.du.def |= duReg[rCX]; - pIcode.du1.numRegsDef++; + pIcode->du.def |= duReg[rCX]; + pIcode->du1.numRegsDef++; case iJCXZ: - pIcode.du.use |= duReg[rCX]; + pIcode->du.use |= duReg[rCX]; break; case iREPNE_CMPS: case iREPE_CMPS: case iREP_MOVS: - pIcode.du.addDefinedAndUsed(rCX); - pIcode.du1.numRegsDef++; + pIcode->du.def |= duReg[rCX]; + pIcode->du1.numRegsDef++; + pIcode->du.use |= duReg[rCX]; case iCMPS: case iMOVS: - pIcode.du.addDefinedAndUsed(rSI); - pIcode.du.addDefinedAndUsed(rDI); - pIcode.du1.numRegsDef += 2; - pIcode.du.use |= duReg[rES] | duReg[sseg]; + pIcode->du.def |= duReg[rSI] | duReg[rDI]; + pIcode->du1.numRegsDef += 2; + pIcode->du.use |= duReg[rSI] | duReg[rDI] | duReg[rES] | + duReg[sseg]; break; - + case iREPNE_SCAS: case iREPE_SCAS: case iREP_STOS: case iREP_INS: - pIcode.du.addDefinedAndUsed(rCX); - pIcode.du1.numRegsDef++; + pIcode->du.def |= duReg[rCX]; + pIcode->du1.numRegsDef++; + pIcode->du.use |= duReg[rCX]; case iSCAS: case iSTOS: case iINS: - pIcode.du.def |= duReg[rDI]; - pIcode.du1.numRegsDef++; - if (pIcode.ll()->getOpcode() == iREP_INS || pIcode.ll()->getOpcode()== iINS) + pIcode->du.def |= duReg[rDI]; + pIcode->du1.numRegsDef++; + if (pIcode->ic.ll.opcode == iREP_INS || pIcode->ic.ll.opcode== iINS) { - pIcode.du.use |= duReg[rDI] | duReg[rES] | duReg[rDX]; + pIcode->du.use |= duReg[rDI] | duReg[rES] | duReg[rDX]; } else { - pIcode.du.use |= duReg[rDI] | duReg[rES] | duReg[(cb == 2)? rAX: rAL]; + pIcode->du.use |= duReg[rDI] | duReg[rES] | + duReg[(cb == 2)? rAX: rAL]; } break; case iREP_LODS: - pIcode.du.addDefinedAndUsed(rCX); - pIcode.du1.numRegsDef++; + pIcode->du.def |= duReg[rCX]; + pIcode->du1.numRegsDef++; + pIcode->du.use |= duReg[rCX]; case iLODS: - pIcode.du.addDefinedAndUsed(rSI); - pIcode.du.def |= duReg[(cb==2)? rAX: rAL]; - pIcode.du1.numRegsDef += 2; - pIcode.du.use |= duReg[sseg]; + pIcode->du.def |= duReg[rSI] | duReg[(cb==2)? rAX: rAL]; + pIcode->du1.numRegsDef += 2; + pIcode->du.use |= duReg[rSI] | duReg[sseg]; break; case iREP_OUTS: - pIcode.du.addDefinedAndUsed(rCX); - pIcode.du1.numRegsDef++; + pIcode->du.def |= duReg[rCX]; + pIcode->du1.numRegsDef++; + pIcode->du.use |= duReg[rCX]; case iOUTS: - pIcode.du.addDefinedAndUsed(rSI); - pIcode.du1.numRegsDef++; - pIcode.du.use |= duReg[rDX] | duReg[sseg]; + pIcode->du.def |= duReg[rSI]; + pIcode->du1.numRegsDef++; + pIcode->du.use |= duReg[rSI] | duReg[rDX] | duReg[sseg]; break; case iIN: case iOUT: - def(DST, pIcode, this, pstate, cb, ix); + def(DST, pIcode, pProc, pstate, cb, ix); if (! Imm) { - pIcode.du.use |= duReg[rDX]; + pIcode->du.use |= duReg[rDX]; } break; } - for (int i = rSP; i <= rBH; i++) /* Kill all defined registers */ - if (pIcode.ll()->flagDU.d & (1 << i)) - pstate->f[i] = false; + for (i = rSP; i <= rBH; i++) /* Kill all defined registers */ + if (pIcode->ic.ll.flagDU.d & (1 << i)) + pstate->f[i] = FALSE; } diff --git a/src/perfhlib.cpp b/src/perfhlib.cpp index 931f676..920328f 100644 --- a/src/perfhlib.cpp +++ b/src/perfhlib.cpp @@ -11,21 +11,32 @@ /* Private data structures */ -static uint16_t *T1, *T2; /* Pointers to T1[i], T2[i] */ +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 */ +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); -PatternHasher g_pattern_hasher; - + void -PatternHasher::init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin, +hashParams(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin, int _NumVert) { /* These parameters are stored in statics so as to obviate the need for @@ -39,32 +50,316 @@ PatternHasher::init(int _NumEntry, int _EntryLen, int _SetSize, char _SetMin, NumVert = _NumVert; /* Allocate the variable sized tables etc */ - T1base = new uint16_t [EntryLen * SetSize]; - T2base = new uint16_t [EntryLen * SetSize]; - graphNode = new int [NumEntry*2 + 1]; - graphNext = new int [NumEntry*2 + 1]; - graphFirst = new int [NumVert + 1]; - g = new short [NumVert + 1]; -// visited = new bool [NumVert + 1]; + 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 PatternHasher::cleanup(void) +void +hashCleanup(void) { /* Free the storage for variable sized tables etc */ - delete [] T1base; - delete [] T2base; - delete [] graphNode; - delete [] graphNext; - delete [] graphFirst; - delete [] g; -// delete [] visited; + if (T1base) free(T1base); + if (T2base) free(T2base); + if (graphNode) free(graphNode); + if (graphNext) free(graphNext); + if (graphFirst) free(graphFirst); + if (g) free(g); } -int PatternHasher::hash(uint8_t *string) +void +map(void) { - uint16_t u, v; + 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; @@ -86,18 +381,68 @@ int PatternHasher::hash(uint8_t *string) return (g[u] + g[v]) % NumEntry; } -uint16_t * PatternHasher::readT1(void) +word * +readT1(void) { return T1base; } -uint16_t *PatternHasher::readT2(void) +word * +readT2(void) { return T2base; } -uint16_t * PatternHasher::readG(void) +word * +readG(void) { - return (uint16_t *)g; + 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 diff --git a/src/procs.cpp b/src/procs.cpp index 622529e..7c625d5 100644 --- a/src/procs.cpp +++ b/src/procs.cpp @@ -5,382 +5,409 @@ * (C) Cristina Cifuentes */ -#include -#include #include "dcc.h" -#include "project.h" +#include + -extern Project g_proj; /* Static indentation buffer */ -static constexpr int indSize=81; /* size of indentation buffer; max 20 */ -static char indentBuf[indSize] = - " "; -// not static, used in icode.cpp at emitGotoLabel -const char *indentStr(int indLevel) // Indentation according to the depth of the statement -{ - return (&indentBuf[indSize-(indLevel*4)-1]); +#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 +static void insertArc (PCALL_GRAPH pcallGraph, PPROC newProc) +/* Inserts an outEdge at the current callGraph pointer if the newProc does * not exist. */ -void CALL_GRAPH::insertArc (ilFunction newProc) -{ - CALL_GRAPH *pcg; - +{ CALL_GRAPH *pcg; + Int i; /* Check if procedure already exists */ - auto res=std::find_if(outEdges.begin(),outEdges.end(),[newProc](CALL_GRAPH *e) {return e->proc==newProc;}); - if(res!=outEdges.end()) - return; + for (i = 0; i < pcallGraph->numOutEdges; i++) + if (pcallGraph->outEdges[i]->proc == newProc) + return; + + /* Check if need to allocate more space */ + if (pcallGraph->numOutEdges == pcallGraph->numAlloc) + { + pcallGraph->numAlloc += NUM_PROCS_DELTA; + pcallGraph->outEdges = (PCALL_GRAPH*)reallocVar(pcallGraph->outEdges, + pcallGraph->numAlloc * sizeof(PCALL_GRAPH)); + memset (&pcallGraph->outEdges[pcallGraph->numOutEdges], 0, + NUM_PROCS_DELTA * sizeof(PCALL_GRAPH)); + } + /* Include new arc */ - pcg = new CALL_GRAPH; + pcg = allocStruc(CALL_GRAPH); + memset (pcg, 0, sizeof(CALL_GRAPH)); pcg->proc = newProc; - outEdges.push_back(pcg); + pcallGraph->outEdges[pcallGraph->numOutEdges] = pcg; + pcallGraph->numOutEdges++; } +boolT insertCallGraph (PCALL_GRAPH pcallGraph, PPROC caller, PPROC callee) /* Inserts a (caller, callee) arc in the call graph tree. */ -bool CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee) -{ - int i; +{ Int i; - if (proc == caller) + if (pcallGraph->proc == caller) { - insertArc (callee); - return true; + insertArc (pcallGraph, callee); + return (TRUE); } else { - for (i = 0; i < outEdges.size(); i++) - if (outEdges[i]->insertCallGraph (caller, callee)) - return true; - return (false); + for (i = 0; i < pcallGraph->numOutEdges; i++) + if (insertCallGraph (pcallGraph->outEdges[i], caller, callee)) + return (TRUE); + return (FALSE); } } -bool CALL_GRAPH::insertCallGraph(Function *caller, ilFunction callee) -{ - return insertCallGraph(g_proj.funcIter(caller),callee); -} - +static void writeNodeCallGraph (PCALL_GRAPH pcallGraph, Int indIdx) /* 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; +{ Int i; - printf ("%s%s\n", indentStr(indIdx), proc->name.c_str()); - for (i = 0; i < outEdges.size(); i++) - outEdges[i]->writeNodeCallGraph (indIdx + 1); + printf ("%s%s\n", indent(indIdx), pcallGraph->proc->name); + for (i = 0; i < pcallGraph->numOutEdges; i++) + writeNodeCallGraph (pcallGraph->outEdges[i], indIdx + 1); } +void writeCallGraph (PCALL_GRAPH pcallGraph) /* Writes the header and invokes recursive procedure */ -void CALL_GRAPH::write() -{ +{ printf ("\nCall Graph:\n"); - writeNodeCallGraph (0); + writeNodeCallGraph (pcallGraph, 0); } /************************************************************************** - * Routines to support arguments + * Routines to support arguments *************************************************************************/ +void newRegArg (PPROC pproc, PICODE picode, PICODE ticode) /* 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 LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const -{ - COND_EXPR *lhs; - STKFRAME * call_args_stackframe, *target_stackframe; - const ID *id; - int tidx; - boolT regExist; - condId type; - Function * tproc; - eReg regL, regH; /* Registers involved in arguments */ +{ COND_EXPR *lhs; + PSTKFRAME ps, ts; + ID *id; + Int i, tidx; + boolT regExist; + condId type; + PPROC tproc; + byte regL, regH; /* Registers involved in arguments */ - /* Flag ticode as having register arguments */ - tproc = ticode->hl()->call.proc; - tproc->flg |= REG_ARGS; + /* 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 */ - call_args_stackframe = ticode->hl()->call.args; - target_stackframe = &tproc->args; - lhs = picode->hl()->asgn.lhs; - type = lhs->expr.ident.idType; - if (type == REGISTER) + /* 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[lhs->expr.ident.idNode.regiIdx].id.regi; + if (regL < rAL) + tidx = newByteWordRegId (&tproc->localId, TYPE_WORD_SIGN, regL); + else + tidx = newByteWordRegId (&tproc->localId, TYPE_BYTE_SIGN, regL); + } + else if (type == LONG_VAR) + { + regL = pproc->localId.id[lhs->expr.ident.idNode.longIdx].id.longId.l; + regH = pproc->localId.id[lhs->expr.ident.idNode.longIdx].id.longId.h; + tidx = newLongRegId (&tproc->localId, TYPE_LONG_SIGN, regH, regL, 0); + } + + /* Check if register argument already on the formal argument list */ + regExist = FALSE; + for (i = 0; i < ts->csym; i++) + { + if (type == REGISTER) + { + if ((ts->sym[i].regs != NULL) && + (ts->sym[i].regs->expr.ident.idNode.regiIdx == tidx)) + { + regExist = TRUE; + i = ts->csym; + } + } + else if (type == LONG_VAR) + { + if ((ts->sym[i].regs != NULL) && + (ts->sym[i].regs->expr.ident.idNode.longIdx == tidx)) + { + regExist = TRUE; + i = ts->csym; + } + } + } + + /* Do ts (formal arguments) */ + if (regExist == FALSE) + { + if (ts->csym == ts->alloc) + { + ts->alloc += 5; + ts->sym = (STKSYM*)reallocVar(ts->sym, ts->alloc * sizeof(STKSYM)); + memset (&ts->sym[ts->csym], 0, 5 * sizeof(STKSYM)); + } + sprintf (ts->sym[ts->csym].name, "arg%ld", ts->csym); + if (type == REGISTER) + { + if (regL < rAL) + { + ts->sym[ts->csym].type = TYPE_WORD_SIGN; + ts->sym[ts->csym].regs = idCondExpRegIdx (tidx, WORD_REG); + } + else + { + ts->sym[ts->csym].type = TYPE_BYTE_SIGN; + ts->sym[ts->csym].regs = idCondExpRegIdx (tidx, BYTE_REG); + } + sprintf (tproc->localId.id[tidx].name, "arg%ld", ts->csym); + } + else if (type == LONG_VAR) + { + ts->sym[ts->csym].regs = idCondExpLongIdx (tidx); + ts->sym[ts->csym].type = TYPE_LONG_SIGN; + sprintf (tproc->localId.id[tidx].name, "arg%ld", ts->csym); + propLongId (&tproc->localId, regL, regH, + tproc->localId.id[tidx].name); + } + + ts->csym++; + ts->numArgs++; + } + + /* Do ps (actual arguments) */ + if (ps->csym == ps->alloc) { - regL = 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) - { - int longIdx = lhs->expr.ident.idNode.longIdx; - regL = id_arr[longIdx].id.longId.l; - regH = id_arr[longIdx].id.longId.h; - tidx = tproc->localId.newLongReg(TYPE_LONG_SIGN, regH, regL, tproc->Icode.begin() /*0*/); + ps->alloc += 5; + ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM)); + memset (&ps->sym[ps->csym], 0, 5 * sizeof(STKSYM)); } + sprintf (ps->sym[ps->csym].name, "arg%ld", ps->csym); + ps->sym[ps->csym].actual = picode->ic.hl.oper.asgn.rhs; + ps->sym[ps->csym].regs = lhs; - /* Check if register argument already on the formal argument list */ - regExist = false; - for(STKSYM &tgt_sym : *target_stackframe) - { - if( tgt_sym.regs == NULL ) // both REGISTER and LONG_VAR require this precondition - continue; - if (type == REGISTER) - { - if ( tgt_sym.regs->expr.ident.idNode.regiIdx == tidx ) - { - regExist = true; - } - } - else if (type == LONG_VAR) - { - if ( tgt_sym.regs->expr.ident.idNode.longIdx == tidx ) - { - regExist = true; - } - } - if(regExist == true) - break; - } + /* Mask off high and low register(s) in picode */ + switch (type) { + case REGISTER: + id = &pproc->localId.id[lhs->expr.ident.idNode.regiIdx]; + picode->du.def &= maskDuReg[id->id.regi]; + if (id->id.regi < rAL) + ps->sym[ps->csym].type = TYPE_WORD_SIGN; + else + ps->sym[ps->csym].type = TYPE_BYTE_SIGN; + break; + case LONG_VAR: + id = &pproc->localId.id[lhs->expr.ident.idNode.longIdx]; + picode->du.def &= maskDuReg[id->id.longId.h]; + picode->du.def &= maskDuReg[id->id.longId.l]; + ps->sym[ps->csym].type = TYPE_LONG_SIGN; + break; + } - /* Do ts (formal arguments) */ - if (regExist == false) - { - STKSYM newsym; - - newsym.setArgName(target_stackframe->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); - } - tproc->localId.id_arr[tidx].name = newsym.name; - } - else if (type == LONG_VAR) - { - newsym.regs = COND_EXPR::idLongIdx (tidx); - newsym.type = TYPE_LONG_SIGN; - tproc->localId.id_arr[tidx].name = newsym.name; - tproc->localId.propLongId (regL, regH, tproc->localId.id_arr[tidx].name.c_str()); - } - target_stackframe->push_back(newsym); - target_stackframe->numArgs++; - } - - /* Do ps (actual arguments) */ - STKSYM newsym; - newsym.setArgName(call_args_stackframe->size()); - newsym.actual = picode->hl()->asgn.rhs; - newsym.regs = lhs; - /* Mask off high and low register(s) in picode */ - switch (type) { - case REGISTER: - id = &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 = &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; - } - call_args_stackframe->push_back(newsym); - call_args_stackframe->numArgs++; + ps->csym++; + ps->numArgs++; } -/** Inserts the new expression (ie. the actual parameter) on the argument +void allocStkArgs (PICODE picode, Int num) +/* Allocates num arguments in the actual argument list of the current + * icode picode. */ +/** NOTE: this function is not used ****/ +{ PSTKFRAME ps; + + ps = picode->ic.hl.oper.call.args; + ps->alloc = num; + ps->csym = num; + ps->numArgs = num; + ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM)); + /**** memset here??? *****/ +} + + +boolT newStkArg (PICODE picode, COND_EXPR *exp, llIcode opcode, PPROC pproc) +/* Inserts the new expression (ie. the actual parameter) on the argument * list. - * @return true if it was a near call that made use of a segment register. - * false elsewhere -*/ -bool CallType::newStkArg(COND_EXPR *exp, llIcode opcode, Function * pproc) -{ - uint8_t 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->m_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; - } - } + * Returns: TRUE if it was a near call that made use of a segment register. + * FALSE elsewhere */ +{ PSTKFRAME ps; + byte regi; - /* Place register argument on the argument list */ - STKSYM newsym; - newsym.actual = exp; - args->push_back(newsym); - args->numArgs++; - return false; + /* 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[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; + if (ps->csym == ps->alloc) + { + ps->alloc += 5; + ps->sym = (STKSYM*)reallocVar(ps->sym, ps->alloc * sizeof(STKSYM)); + memset (&ps->sym[ps->csym], 0, 5 * sizeof(STKSYM)); + } + ps->sym[ps->csym].actual = exp; + ps->csym++; + ps->numArgs++; + return (FALSE); } +void placeStkArg (PICODE picode, COND_EXPR *exp, Int pos) /* Places the actual argument exp in the position given by pos in the * argument list of picode. */ -void CallType::placeStkArg (COND_EXPR *exp, int pos) -{ - (*args)[pos].actual = exp; - (*args)[pos].setArgName(pos); -} +{ PSTKFRAME ps; -COND_EXPR *CallType::toId() -{ - return COND_EXPR::idFunc( proc, args); + ps = picode->ic.hl.oper.call.args; + ps->sym[pos].actual = exp; + sprintf (ps->sym[pos].name, "arg%ld", pos); } +void adjustActArgType (COND_EXPR *exp, hlType forType, PPROC pproc) /* 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) -{ - PROG &prog(Project::get()->prog); - hlType actType; - int offset, offL; +{ hlType actType; + Int offset, offL; - if (exp == NULL) - return; + if (exp == NULL) + return; - actType = exp-> expType (pproc); - if (((actType == forType) || (exp->m_type != IDENTIFIER))) - return; - 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; + 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_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_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_PTR: + /* It's a pointer to a char rather than a pointer to + * an integer */ + /***HERE - modify the type ****/ + break; - case TYPE_WORD_SIGN: + case TYPE_WORD_SIGN: - break; - } /* eos */ - break; - } + break; + } /* eos */ + break; + } + } } +void adjustForArgType (PSTKFRAME pstkFrame, Int numArg, hlType actType) /* Determines whether the formal argument has the same type as the given - * type (type of the actual argument). If not, the formal argument is + * 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; - /* If formal argument does not exist, do not create new ones, just - * ignore actual argument - */ - if(numArg_>size()) - return; +{ hlType forType; + PSTKSYM psym, nsym; + Int off, i; - /* Find stack offset for this argument */ - off = m_minOff; - i=0; - for(STKSYM &s : *this) // walk formal arguments upto numArg_ - { - if(i>=numArg_) - break; - off+=s.size; - i++; - } + /* Find stack offset for this argument */ + off = pstkFrame->minOff; + for (i = 0; i < numArg; i++) + off += pstkFrame->sym[i].size; - /* Find formal argument */ - //psym = &at(numArg_); - //i = numArg_; - //auto iter=std::find_if(sym.begin(),sym.end(),[off](STKSYM &s)->bool {s.off==off;}); - auto iter=std::find_if(begin()+numArg_,end(),[off](STKSYM &s)->bool {s.label==off;}); - if(iter==end()) // symbol not found - return; - psym = &(*iter); + /* Find formal argument */ + if (numArg < pstkFrame->csym) + { + psym = &pstkFrame->sym[numArg]; + i = numArg; + while ((i < pstkFrame->csym) && (psym->off != off)) + { + psym++; + i++; + } + if (numArg == pstkFrame->csym) + 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; + 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; - nsym->macro = "HI"; - psym->macro = "LO"; - nsym->hasMacro = true; - psym->hasMacro = true; - nsym->name = psym->name; - nsym->invalid = true; - numArgs--; - } - 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; + pstkFrame->numArgs--; + } + break; - case TYPE_PTR: - case TYPE_CONST: - case TYPE_STR: - break; - } /* eos */ - } + case TYPE_PTR: + case TYPE_CONST: + case TYPE_STR: + break; + } /* eos */ + } } diff --git a/src/project.cpp b/src/project.cpp deleted file mode 100644 index 85e0874..0000000 --- a/src/project.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include "project.h" -#include "Procedure.h" -Project g_proj; -bool Project::valid(ilFunction iter) -{ - return iter!=pProcList.end(); -} -ilFunction Project::funcIter(Function *to_find) -{ - auto iter=std::find_if(pProcList.begin(),pProcList.end(), - [to_find](const Function &f)->bool {return to_find==&f;}); - assert(iter!=pProcList.end()); - return iter; -} - -ilFunction Project::findByEntry(uint32_t entry) -{ - /* Search procedure list for one with appropriate entry point */ - ilFunction iter= std::find_if(pProcList.begin(),pProcList.end(), - [entry](const Function &f) -> - bool { return f.procEntry==entry; }); -return iter; -} - -ilFunction Project::createFunction() -{ - pProcList.push_back(Function::Create()); - return (++pProcList.rbegin()).base(); -} - -int Project::getSymIdxByAdd(uint32_t adr) -{ - size_t i; - for (i = 0; i < symtab.size(); i++) - if (symtab[i].label == adr) - break; - return i; -} -bool Project::validSymIdx(size_t idx) -{ - return idx -#include -#include -#include #include "dcc.h" +#include "string.h" +#ifdef __BORLAND__ +#include +#else +#include +#endif + +static boolT isJCond (llIcode opcode) /* Returns whether the given icode opcode is within the range of valid * high-level conditional jump icodes (iJB..iJG) */ -static boolT isJCond (llIcode opcode) { - if ((opcode >= iJB) && (opcode <= iJG)) - return true; - return false; + if ((opcode >= iJB) && (opcode <= iJG)) + return (TRUE); + return (FALSE); } +static boolT isLong23 (Int i, PBB pbb, PICODE icode, Int *off, Int *arc) /* Returns whether the conditions for a 2-3 long variable are satisfied */ -static bool isLong23 (BB * pbb, iICODE &off, int *arc) -{ - BB * t, * e, * obb2; +{ PBB t, e, obb2; - if (pbb->nodeType != TWO_BRANCH) - return false; - t = pbb->edges[THEN].BBptr; - e = pbb->edges[ELSE].BBptr; + if (pbb->nodeType != TWO_BRANCH) + return (FALSE); + t = pbb->edges[THEN].BBptr; + e = pbb->edges[ELSE].BBptr; - /* Check along the THEN path */ - if ((t->size() == 1) && (t->nodeType == TWO_BRANCH) && (t->inEdges.size() == 1)) - { - obb2 = t->edges[THEN].BBptr; - if ((obb2->size() == 2) && (obb2->nodeType == TWO_BRANCH) && (obb2->front().ll()->getOpcode() == iCMP)) - { - off = obb2->begin();//std::distance(iter,obb2->begin2()); - *arc = THEN; - return true; - } - } + /* 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->size() == 1) && (e->nodeType == TWO_BRANCH) && (e->inEdges.size() == 1)) - { - obb2 = e->edges[THEN].BBptr; - if ((obb2->size() == 2) && (obb2->nodeType == TWO_BRANCH) && (obb2->front().ll()->getOpcode() == iCMP)) - { - off = obb2->begin();//std::distance(iter,obb2->begin2());//obb2->front().loc_ip - i; - *arc = ELSE; - return true; - } - } - return false; + /* 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); } +static boolT isLong22 (PICODE pIcode, PICODE pEnd, Int *off) /* Returns whether the conditions for a 2-2 long variable are satisfied */ -static boolT isLong22 (iICODE pIcode, iICODE pEnd, iICODE &off) { - iICODE initial_icode=pIcode; - if(distance(pIcode,pEnd)<4) - return false; - // preincrement because pIcode is not checked here - iICODE icodes[] = { ++pIcode,++pIcode,++pIcode }; - if ( icodes[1]->ll()->match(iCMP) && - (isJCond ((llIcode)icodes[0]->ll()->getOpcode())) && - (isJCond ((llIcode)icodes[2]->ll()->getOpcode()))) - { - off = initial_icode; - advance(off,2); - return true; - } - return false; + 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). + +static void longJCond23 (COND_EXPR *rhs, COND_EXPR *lhs, PICODE pIcode, + Int *idx, PPROC pProc, Int arc, Int off) +/* 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. - * @return number of ICODEs to skip + * the new edges for the remaining nodes. */ +{ Int j; + PBB pbb, obb1, obb2, tbb; -*/ -static int longJCond23 (Assignment &asgn, iICODE pIcode, int arc, iICODE atOffset) -{ - BB * pbb, * obb1, * obb2, * tbb; - int skipped_insn=0; - if (arc == THEN) - { - /* Find intermediate basic blocks and target block */ - pbb = pIcode->getParent(); - obb1 = pbb->edges[THEN].BBptr; - obb2 = obb1->edges[THEN].BBptr; - tbb = obb2->edges[THEN].BBptr; + 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 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->inEdges.push_back(pbb); /* looses 2 arcs, gains 1 arc */ + /* Modify in edges of target basic block */ + for (j = 0; j < (tbb->numInEdges-1); j++) + { + if ((tbb->inEdges[j] == obb1) || (tbb->inEdges[j] == obb2)) + { + memmove (&tbb->inEdges[j], &tbb->inEdges[j+1], + (tbb->numInEdges - j-1) * sizeof(PBB)); + memset (&tbb->inEdges[tbb->numInEdges-1], ' ',sizeof (PBB)); + j--; + } + } + tbb->numInEdges--; /* looses 2 arcs, gains 1 arc */ + tbb->inEdges[tbb->numInEdges-1] = pbb; - /* 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); /* looses 1 arc */ - /* Update icode index */ - skipped_insn = 5; - } - else /* ELSE arc */ - { - /* Find intermediate basic blocks and target block */ - pbb = pIcode->getParent(); - obb1 = pbb->edges[ELSE].BBptr; - obb2 = obb1->edges[THEN].BBptr; - tbb = obb2->edges[THEN].BBptr; + /* Modify in edges of the ELSE basic block */ + tbb = pbb->edges[ELSE].BBptr; + for (j = 0; j < (tbb->numInEdges-1); j++) + { + if (tbb->inEdges[j] == obb2) + { + memmove (&tbb->inEdges[j], &tbb->inEdges[j+1], + (tbb->numInEdges - j-1) * sizeof(PBB)); + break; + } + } + tbb->numInEdges--; /* looses 1 arc */ - /* 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); /* looses 1 arc */ + /* Update icode index */ + (*idx) += 5; + } - /* 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->inEdges.push_back(pbb); /* looses 2 arcs, gains 1 arc */ + 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 out edge of header basic block */ - pbb->edges[ELSE].BBptr = tbb; + /* Modify in edges of target basic block */ + for (j = 0; j < (tbb->numInEdges-1); j++) + { + if (tbb->inEdges[j] == obb2) + { + memmove (&tbb->inEdges[j], &tbb->inEdges[j+1], + (tbb->numInEdges - j-1) * sizeof(PBB)); + break; + } + } + tbb->numInEdges--; /* looses 1 arc */ - /* Update icode index */ - skipped_insn = 2; - } - iICODE atOffset1(atOffset),next1(++iICODE(pIcode)); - advance(atOffset1,1); - /* Create new HLI_JCOND and condition */ - asgn.lhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, condOpJCond[atOffset1->ll()->getOpcode()-iJB]); - next1->setJCond(asgn.lhs); - next1->copyDU(*pIcode, eUSE, eUSE); - next1->du.use |= atOffset->du.use; + /* Modify in edges of the ELSE basic block */ + tbb = obb2->edges[ELSE].BBptr; + for (j = 0; j < (tbb->numInEdges-1); j++) + { + if ((tbb->inEdges[j] == obb2) || (tbb->inEdges[j] == obb1)) + { + memmove (&tbb->inEdges[j], &tbb->inEdges[j+1], + (tbb->numInEdges - j-1) * sizeof(PBB)); + memset (&tbb->inEdges[tbb->numInEdges-1], ' ',sizeof (PBB)); + j--; + } + } + tbb->numInEdges--; /* looses 2 arcs, gains 1 arc */ + tbb->inEdges[tbb->numInEdges - 1] = pbb; - /* Update statistics */ - obb1->flg |= INVALID_BB; - obb2->flg |= INVALID_BB; - stats.numBBaft -= 2; + /* Modify out edge of header basic block */ + pbb->edges[ELSE].BBptr = tbb; - pIcode->invalidate(); - obb1->front().invalidate(); - // invalidate 2 first instructions of BB 2 - iICODE ibb2 = obb2->begin(); - (ibb2++)->invalidate(); - (ibb2++)->invalidate(); - return skipped_insn; + /* Update icode index */ + (*idx) += 2; + } + + /* Create new HLI_JCOND and condition */ + lhs = boolCondExp (lhs, rhs, condOpJCond[(pIcode+off+1)->ic.ll.opcode-iJB]); + newJCondHlIcode (pIcode+1, lhs); + copyDU (pIcode+1, pIcode, E_USE, E_USE); + (pIcode+1)->du.use |= (pIcode+off)->du.use; + + /* Update statistics */ + obb1->flg |= INVALID_BB; + obb2->flg |= INVALID_BB; + stats.numBBaft -= 2; + + invalidateIcode (pIcode); + invalidateIcode (pProc->Icode.GetIcode(obb1->start)); + invalidateIcode (pProc->Icode.GetIcode(obb2->start)); + invalidateIcode (pProc->Icode.GetIcode(obb2->start+1)); } -/** Creates a long conditional equality or inequality at (pIcode+1). +static void longJCond22 (COND_EXPR *rhs, COND_EXPR *lhs, PICODE pIcode, + Int *idx) +/* 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. - * @return number of ICODE's to skip -*/ -static int longJCond22 (Assignment &asgn, iICODE pIcode,iICODE pEnd) -{ + * the new edges for the remaining nodes. */ +{ Int j; + PBB pbb, obb1, tbb; - BB * pbb, * obb1, * tbb; - if(distance(pIcode,pEnd)<4) - return false; - // preincrement because pIcode is not checked here - iICODE icodes[] = { pIcode++,pIcode++,pIcode++,pIcode++ }; + /* Form conditional expression */ + lhs = boolCondExp (lhs, rhs, condOpJCond[(pIcode+3)->ic.ll.opcode - iJB]); + newJCondHlIcode (pIcode+1, lhs); + copyDU (pIcode+1, pIcode, E_USE, E_USE); + (pIcode+1)->du.use |= (pIcode+2)->du.use; - /* Form conditional expression */ - asgn.lhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, condOpJCond[icodes[3]->ll()->getOpcode() - iJB]); - icodes[1]->setJCond(asgn.lhs); - icodes[1]->copyDU (*icodes[0], eUSE, eUSE); - icodes[1]->du.use |= icodes[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; - /* Adjust outEdges[0] to the new target basic block */ - pbb = icodes[0]->getParent(); - if (pbb->back().loc_ip == icodes[1]->loc_ip) - { - /* 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 THEN out edge of header basic block */ - pbb->edges[THEN].BBptr = tbb; + /* Modify in edges of target basic block */ + for (j = 0; j < (tbb->numInEdges-1); j++) + { + if (tbb->inEdges[j] == obb1) + { + memmove (&tbb->inEdges[j], &tbb->inEdges[j+1], + (tbb->numInEdges - j-1) * sizeof(PBB)); + break; + } + } + if ((pIcode+3)->ic.ll.opcode == iJE) + tbb->numInEdges--; /* looses 1 arc */ + else /* iJNE => replace arc */ + tbb->inEdges[tbb->numInEdges-1] = pbb; - /* 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); + /* Modify ELSE out edge of header basic block */ + tbb = obb1->edges[ELSE].BBptr; + pbb->edges[ELSE].BBptr = tbb; - if (icodes[3]->ll()->getOpcode() != iJE) - tbb->inEdges.push_back(pbb); /* iJNE => replace arc */ + /* Modify in edges of the ELSE basic block */ + for (j = 0; j < (tbb->numInEdges-1); j++) + { + if (tbb->inEdges[j] == obb1) + { + memmove (&tbb->inEdges[j], &tbb->inEdges[j+1], + (tbb->numInEdges - j-1) * sizeof(PBB)); + break; + } + } + if ((pIcode+3)->ic.ll.opcode == iJE) /* replace */ + tbb->inEdges[tbb->numInEdges-1] = pbb; + else + tbb->numInEdges--; /* iJNE => looses 1 arc */ - /* 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 (icodes[3]->ll()->getOpcode() == iJE) /* replace */ - tbb->inEdges.push_back(pbb); + /* Update statistics */ + obb1->flg |= INVALID_BB; + stats.numBBaft--; + } - /* Update statistics */ - obb1->flg |= INVALID_BB; - stats.numBBaft--; - } - - icodes[0]->invalidate(); - icodes[2]->invalidate(); - icodes[3]->invalidate(); - return 4; + invalidateIcode (pIcode); + invalidateIcode (pIcode+2); + invalidateIcode (pIcode+3); + (*idx) += 4; } + +static void propLongStk (Int i, ID *pLocId, PPROC pProc) /* 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 + * pLocId: ptr to the long local identifier * pProc : ptr to current procedure's record. */ -void Function::propLongStk (int i, const ID &pLocId) -{ - int arc; - Assignment asgn; - //COND_EXPR *lhs, *rhs; /* Pointers to left and right hand expression */ - iICODE next1, pEnd; - iICODE l23; - /* Check all icodes for offHi:offLo */ - pEnd = Icode.end(); - int stat_size=Icode.size(); -// for (idx = 0; idx < (Icode.size() - 1); idx++) - for(auto pIcode = Icode.begin(); ;++pIcode) - { - assert(Icode.size()==stat_size); - next1 = ++iICODE(pIcode); - if(next1==pEnd) - break; - if ((pIcode->type == HIGH_LEVEL) || ( not pIcode->valid() )) - continue; - if (pIcode->ll()->getOpcode() == next1->ll()->getOpcode()) - { - if (checkLongEq (pLocId.id.longStkId, pIcode, i, this, asgn, *next1->ll()) == true) - { - switch (pIcode->ll()->getOpcode()) - { - case iMOV: - pIcode->setAsgn(asgn.lhs, asgn.rhs); - next1->invalidate(); - break; +{ Int idx, off, arc; + COND_EXPR *lhs, *rhs; /* Pointers to left and right hand expression */ + PICODE pIcode, pEnd; - case iAND: case iOR: case iXOR: - switch (pIcode->ll()->getOpcode()) - { - case iAND: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, AND); break; - case iOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, OR); break; - case iXOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, XOR); break; - } - pIcode->setAsgn(asgn.lhs, asgn.rhs); - next1->invalidate(); - break; + /* 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; - case iPUSH: - pIcode->setUnary( HLI_PUSH, asgn.lhs); - next1->invalidate(); - break; - default: - printf("Wild ass checkLongEq success on opcode %d\n",pIcode->ll()->getOpcode()); - } /*eos*/ - } - } - //TODO: Simplify this! - /* Check long conditional (i.e. 2 CMPs and 3 branches */ - else if ((pIcode->ll()->getOpcode() == iCMP) && (isLong23 (pIcode->getParent(), l23, &arc))) - { - if ( checkLongEq (pLocId.id.longStkId, pIcode, i, this, asgn, *l23->ll()) ) - { - advance(pIcode,longJCond23 (asgn, pIcode, arc, l23)); - } - } + 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) + { + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode + 1); + idx++; + } + break; - /* Check for long conditional equality or inequality. This requires - * 2 CMPs and 2 branches */ - else if ((pIcode->ll()->getOpcode() == iCMP) && isLong22 (pIcode, pEnd, l23)) - { - if ( checkLongEq (pLocId.id.longStkId, pIcode, i, this,asgn, *l23->ll()) ) - { - advance(pIcode,longJCond22 (asgn, pIcode,pEnd)); - } - } - } + 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 = boolCondExp (lhs, rhs, AND); + break; + case iOR: rhs = boolCondExp (lhs, rhs, OR); + break; + case iXOR: rhs = boolCondExp (lhs, rhs, XOR); + break; + } + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode + 1); + idx++; + } + break; + + case iPUSH: + if (checkLongEq (pLocId->id.longStkId, pIcode, i, idx, pProc, + &rhs, &lhs, 1) == TRUE) + { + newUnaryHlIcode (pIcode, HLI_PUSH, lhs); + invalidateIcode (pIcode + 1); + 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); + } + } } -int Function::findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE beg) -{ - Assignment asgn; - LLOperand * pmH,* pmL; - iICODE pIcode; - riICODE rev(beg); - bool forced_finish=false; - for (; not forced_finish and rev!=Icode.rend();rev++) //idx = pLocId_idx - 1; idx > 0 ; idx-- + + +static void propLongReg (Int i, ID *pLocId, PPROC pProc) +/* 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. */ +{ COND_EXPR *lhs, *rhs; + Int idx, j, off, arc; + PICODE pIcode, pEnd; + PMEM 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.csym; j++) + { + /* Check backwards for a definition of this long register */ + for (idx = pLocId->idx.idx[j] - 1; idx > 0 ; idx--) { - pIcode = (++riICODE(rev)).base();//forward iterator from rev - iICODE next1((++iICODE(pIcode))); // next instruction - ICODE &icode(*pIcode); + pIcode = pProc->Icode.GetIcode(idx-1); + if ((pIcode->type == HIGH_LEVEL) || (pIcode->invalid == TRUE)) + continue; - - if ((icode.type == HIGH_LEVEL) || ( not icode.valid() )) - continue; - if (icode.ll()->getOpcode() != next1->ll()->getOpcode()) - continue; - - switch (icode.ll()->getOpcode()) - { - case iMOV: - pmH = &icode.ll()->dst; - pmL = &next1->ll()->dst; - if ((pLocId.id.longId.h == pmH->regi) && (pLocId.id.longId.l == pmL->regi)) + 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)) { - localId.id_arr[loc_ident_idx].idx.push_back(pIcode);//idx-1//insert - icode.setRegDU( pmL->regi, eDEF); - asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx); - asgn.rhs = COND_EXPR::idLong (&this->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, *next1->ll()); - icode.setAsgn(asgn.lhs, asgn.rhs); - next1->invalidate(); - forced_finish=true; /* to exit the loop */ + lhs = idCondExpLongIdx (i); + insertIdx (&pProc->localId.id[i].idx, idx-1); + setRegDU (pIcode, pmL->regi, E_DEF); + rhs = idCondExpLong (&pProc->localId, SRC, pIcode, HIGH_FIRST, + idx, E_USE, 1); + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode + 1); + idx = 0; /* to exit the loop */ } break; - case iPOP: - pmH = &next1->ll()->dst; - pmL = &icode.ll()->dst; - if ((pLocId.id.longId.h == pmH->regi) && (pLocId.id.longId.l == pmL->regi)) + 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)) { - asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx); - icode.setRegDU( pmH->regi, eDEF); - icode.setUnary(HLI_POP, asgn.lhs); - next1->invalidate(); - asgn.lhs=0; - forced_finish=true; /* to exit the loop */ + lhs = idCondExpLongIdx (i); + setRegDU (pIcode, pmH->regi, E_DEF); + newUnaryHlIcode (pIcode, HLI_POP, lhs); + invalidateIcode (pIcode + 1); + idx = 0; /* to exit the loop */ } break; + + /**** others missing ***/ - // /**** others missing ***/ - - case iAND: case iOR: case iXOR: - pmL = &icode.ll()->dst; - pmH = &next1->ll()->dst; - if ((pLocId.id.longId.h == pmH->regi) && (pLocId.id.longId.l == pmL->regi)) + 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)) { - asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx); - asgn.rhs = COND_EXPR::idLong (&this->localId, SRC, pIcode, LOW_FIRST, pIcode, eUSE, *next1->ll()); - icode.setRegDU( pmH->regi, USE_DEF); - switch (icode.ll()->getOpcode()) - { - case iAND: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, AND); - break; - case iOR: - asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, OR); - break; - case iXOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, XOR); - break; - } /* eos */ - icode.setAsgn(asgn.lhs, asgn.rhs); - next1->invalidate(); - forced_finish=true; /* to exit the loop */ + lhs = idCondExpLongIdx (i); + setRegDU (pIcode, pmH->regi, USE_DEF); + rhs = idCondExpLong (&pProc->localId, SRC, pIcode, LOW_FIRST, + idx, E_USE, 1); + switch (pIcode->ic.ll.opcode) { + case iAND: rhs = boolCondExp (lhs, rhs, AND); + break; + case iOR: rhs = boolCondExp (lhs, rhs, OR); + break; + case iXOR: rhs = boolCondExp (lhs, rhs, XOR); + break; + } /* eos */ + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode + 1); + idx = 0; } break; } /* eos */ } - return rev!=Icode.rend(); -} -int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE beg) -{ - bool forced_finish=false; - auto pEnd=Icode.end(); - iICODE long_loc; - Assignment asgn; - for (auto pIcode=beg; not forced_finish; ++pIcode) - { - iICODE next1(++iICODE(pIcode)); - if(next1==pEnd) - break; - LLOperand * pmH,* pmL; /* Pointers to dst LOW_LEVEL icodes */ - int arc; - if ((pIcode->type == HIGH_LEVEL) || ( not pIcode->valid() )) - continue; + /* If no definition backwards, check forward for a use of this long reg */ + if (idx <= 0) + for (idx = pLocId->idx.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->ll()->getOpcode() == next1->ll()->getOpcode()) - switch (pIcode->ll()->getOpcode()) - { - case iMOV: - if ((pLocId.id.longId.h == pIcode->ll()->src().getReg2()) && - (pLocId.id.longId.l == next1->ll()->src().getReg2())) + 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)) { - pIcode->setRegDU( next1->ll()->src().getReg2(), eUSE); - - asgn.rhs = COND_EXPR::idLongIdx (loc_ident_idx); - asgn.lhs = COND_EXPR::idLong (&this->localId, DST, pIcode,HIGH_FIRST, pIcode, eDEF, *next1->ll()); - - pIcode->setAsgn(asgn.lhs, asgn.rhs); - next1->invalidate(); - forced_finish =true; /* to exit the loop */ + rhs = idCondExpLongIdx (i); + setRegDU (pIcode, (pIcode+1)->ic.ll.src.regi, E_USE); + lhs = idCondExpLong (&pProc->localId, DST, pIcode, + HIGH_FIRST, idx, E_DEF, 1); + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode + 1); + idx = pProc->Icode.GetNumIcodes(); /* to exit the loop */ } break; - case iPUSH: - if ((pLocId.id.longId.h == pIcode->ll()->src().getReg2()) && - (pLocId.id.longId.l == next1->ll()->src().getReg2())) + case iPUSH: + if ((pLocId->id.longId.h == pIcode->ic.ll.src.regi) && + (pLocId->id.longId.l == (pIcode+1)->ic.ll.src.regi)) { - asgn.rhs = COND_EXPR::idLongIdx (loc_ident_idx); - pIcode->setRegDU( next1->ll()->src().getReg2(), eUSE); - pIcode->setUnary(HLI_PUSH, asgn.rhs); - next1->invalidate(); + rhs = idCondExpLongIdx (i); + setRegDU (pIcode, (pIcode+1)->ic.ll.src.regi, E_USE); + newUnaryHlIcode (pIcode, HLI_PUSH, lhs); + invalidateIcode (pIcode + 1); } - forced_finish =true; /* to exit the loop */ + idx = pProc->Icode.GetNumIcodes(); /* to exit the loop */ break; - /*** others missing ****/ + /*** others missing ****/ - case iAND: case iOR: case iXOR: - pmL = &pIcode->ll()->dst; - pmH = &next1->ll()->dst; - if ((pLocId.id.longId.h == pmH->regi) && - (pLocId.id.longId.l == pmL->regi)) - { - asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx); - pIcode->setRegDU( pmH->regi, USE_DEF); - asgn.rhs = COND_EXPR::idLong (&this->localId, SRC, pIcode, - LOW_FIRST, pIcode, eUSE, *next1->ll()); - switch (pIcode->ll()->getOpcode()) { - case iAND: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, AND); - break; - case iOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, OR); - break; - case iXOR: asgn.rhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, XOR); - break; - } - pIcode->setAsgn(asgn.lhs, asgn.rhs); - next1->invalidate(); - // ftw loop restart ???? - //idx = 0; - // maybe this should end the loop instead - forced_finish =true; /* to exit the loop */ - } - break; + 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 = idCondExpLongIdx (i); + setRegDU (pIcode, pmH->regi, USE_DEF); + rhs = idCondExpLong (&pProc->localId, SRC, pIcode, + LOW_FIRST, idx, E_USE, 1); + switch (pIcode->ic.ll.opcode) { + case iAND: rhs = boolCondExp (lhs, rhs, AND); + break; + case iOR: rhs = boolCondExp (lhs, rhs, OR); + break; + case iXOR: rhs = boolCondExp (lhs, rhs, XOR); + break; + } + newAsgnHlIcode (pIcode, lhs, rhs); + invalidateIcode (pIcode + 1); + idx = 0; + } + break; } /* eos */ - /* Check long conditional (i.e. 2 CMPs and 3 branches */ - else if ((pIcode->ll()->getOpcode() == iCMP) && (isLong23 (pIcode->getParent(), long_loc, &arc))) - { - if (checkLongRegEq (pLocId.id.longId, pIcode, loc_ident_idx, this, asgn, *long_loc->ll())) - { - // reduce the advance by 1 here (loop increases) ? - advance(pIcode,longJCond23 (asgn, pIcode, arc, long_loc)); - } - } + /* 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->ll()->match(iCMP) && (isLong22 (pIcode, pEnd, long_loc))) - { - if (checkLongRegEq (pLocId.id.longId, pIcode, loc_ident_idx, this, asgn, *long_loc->ll()) ) - { - // TODO: verify that removing -1 does not change anything ! - advance(pIcode,longJCond22 (asgn, pIcode,pEnd)); - } - } + /* 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 = idCondExpLongIdx (i); + rhs = idCondExpKte (0, 4); /* long 0 */ + lhs = boolCondExp (lhs, rhs, + condOpJCond[(pIcode+1)->ic.ll.opcode - iJB]); + newJCondHlIcode (pIcode+1, lhs); + copyDU (pIcode+1, pIcode, E_USE, E_USE); + invalidateIcode (pIcode); + } + } - /* 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->ll()->match(iOR) && (next1 != pEnd) && (isJCond ((llIcode)next1->ll()->getOpcode()))) - { - if (pLocId.id.longId.srcDstRegMatch(pIcode,pIcode)) - { - asgn.lhs = COND_EXPR::idLongIdx (loc_ident_idx); - asgn.rhs = COND_EXPR::idKte (0, 4); /* long 0 */ - asgn.lhs = COND_EXPR::boolOp (asgn.lhs, asgn.rhs, condOpJCond[next1->ll()->getOpcode() - iJB]); - next1->setJCond(asgn.lhs); - next1->copyDU(*pIcode, eUSE, eUSE); - pIcode->invalidate(); - } - } - } /* end for */ -} - -/** Finds the definition of the long register pointed to by pLocId, and - * transforms that instruction into a HIGH_LEVEL icode instruction. - * @arg i index into the local identifier table - * @arg pLocId ptr to the long local identifier - * - */ -void Function::propLongReg (int loc_ident_idx, const ID &pLocId) -{ - /* Process all definitions/uses of long registers at an icode position */ - // WARNING: this loop modifies the iterated-over container. - size_t initial_size=pLocId.idx.size(); - for (int j = 0; j < pLocId.idx.size(); j++) - { - auto idx_iter=pLocId.idx.begin(); - std::advance(idx_iter,j); - /* Check backwards for a definition of this long register */ - if (findBackwarLongDefs(loc_ident_idx,pLocId,*idx_iter)) - { - //assert(initial_size==pLocId.idx.size()); - continue; - } - /* If no definition backwards, check forward for a use of this long reg */ - findForwardLongUses(loc_ident_idx,pLocId,*idx_iter); - //assert(initial_size==pLocId.idx.size()); - } /* end for */ + } /* end for */ + } /* end for */ } -/* Propagates the long global address across all LOW_LEVEL icodes. +static void propLongGlb (Int i, ID *pLocId, PPROC pProc) +/* Propagates the long global address across all LOW_LEVEL icodes. * Transforms some LOW_LEVEL icodes into HIGH_LEVEL */ -void Function::propLongGlb (int i, const ID &pLocId) { - printf("WARN: Function::propLongGlb not implemented"); + } +void propLong (PPROC pProc) /* Propagated identifier information, thus converting some LOW_LEVEL icodes * into HIGH_LEVEL icodes. */ -void Function::propLong() -{ - int i; - /* Pointer to current local identifier */ +{ Int i; + ID *pLocId; /* Pointer to current local identifier */ - for (i = 0; i < localId.csym(); i++) + for (i = 0; i < pProc->localId.csym; i++) { - const ID &pLocId(localId.id_arr[i]); - if ((pLocId.type==TYPE_LONG_SIGN) || (pLocId.type==TYPE_LONG_UNSIGN)) + pLocId = &pProc->localId.id[i]; + if ((pLocId->type==TYPE_LONG_SIGN) || (pLocId->type==TYPE_LONG_UNSIGN)) { - switch (pLocId.loc) - { - case STK_FRAME: - propLongStk (i, pLocId); - break; - case REG_FRAME: - propLongReg (i, pLocId); - break; - case GLB_FRAME: - propLongGlb (i, pLocId); - break; + switch (pLocId->loc) { + case STK_FRAME: propLongStk (i, pLocId, pProc); + break; + case REG_FRAME: propLongReg (i, pLocId, pProc); + break; + case GLB_FRAME: propLongGlb (i, pLocId, pProc); + break; } } } diff --git a/src/reducible.cpp b/src/reducible.cpp index 003500f..8fc20af 100644 --- a/src/reducible.cpp +++ b/src/reducible.cpp @@ -3,388 +3,418 @@ * constructs an equivalent reducible graph if one is not found. * (C) Cristina Cifuentes ********************************************************************/ -#include -#include + #include "dcc.h" #include +#ifdef __BORLAND__ +#include +#else #include /* For free() */ +#endif #include -static int numInt; /* Number of intervals */ +static Int numInt; /* Number of intervals */ #define nonEmpty(q) (q != NULL) /* Returns whether the queue q is empty or not */ -bool trivialGraph(BB *G) -{ - return G->edges.empty(); -} + +#define trivialGraph(G) (G->numOutEdges == 0) /* Returns whether the graph is a trivial graph or not */ +static BB *firstOfQueue (queue **Q) /* 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.front(); - Q.pop_front(); - return res; +{ queue *elim; + BB *first; + + elim = *Q; /* Pointer to first node */ + first = (*Q)->node; /* First element */ + *Q = (*Q)->next; /* Pointer to next node */ + free (elim); /* Free storage */ + return (first); } +queue *appendQueue (queue **Q, BB *node) /* 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()) - return iter; - Q.push_back(node); - iter=Q.end(); - --iter; - return iter; +{ queue *pq, *l; + + pq = allocStruc(queue); + pq->node = node; + pq->next = NULL; + + if (Q) + if (*Q) + { + for (l = *Q; l->next && l->node != node; l = l->next) + ; + if (l->node != node) + l->next = pq; + } + else /* (*Q) == NULL */ + *Q = pq; + return (pq); } +static BB *firstOfInt (interval *pI) /* 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 0; - ++currNode; - return *pq; +{ queue *pq; + + pq = pI->currNode; + if (pq == NULL) + return (NULL); + pI->currNode = pq->next; + return (pq->node); } -/* 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 +static queue *appendNodeInt (queue *pqH, BB *node, interval *pI) +/* Appends node node to the end of the interval list I, updates currNode + * if necessary, and removes the node from the header list H 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 */ +{ queue *pq, /* Pointer to current node of the list */ + *prev; /* Pointer to previous node in the list */ /* Append node if it is not already in the interval list */ - pq = appendQueue (pI->nodes, node); + pq = appendQueue (&pI->nodes, node); /* Update currNode if necessary */ - if (pI->currNode == pI->nodes.end()) - pI->currNode = pq; + if (pI->currNode == NULL) + pI->currNode = pq; - /* Check header list for occurrence of node, if found, remove it + /* 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()) + if (node->beenOnH && pqH) { - auto found_iter=std::find(pqH.begin(),pqH.end(),node); - if(found_iter!=pqH.end()) - { - pI->numOutEdges -= (uint8_t)(*found_iter)->inEdges.size() - 1; - pqH.erase(found_iter); - } + prev = pqH; + for (pq = prev; pq && pq->node != node; pq = pq->next) + prev = pq; + if (pq == prev) + { + pqH = pqH->next; + pI->numOutEdges -= (byte)pq->node->numInEdges - 1; + } + else if (pq) + { + prev->next = pq->next; + pI->numOutEdges -= (byte)pq->node->numInEdges - 1; + } } + /* Update interval header information for this basic block */ node->inInterval = pI; + + return (pqH); } -/* Finds the intervals of graph derivedGi->Gi and places them in the list +static void findIntervals (derSeq *derivedGi) +/* 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 (Function *c) -{ - 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 */ +{ 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(0,"",c); /* ^ empty BB */ + H = appendQueue (NULL, derivedGi->Gi); /* H = {first node of G} */ + derivedGi->Gi->beenOnH = TRUE; + derivedGi->Gi->reachingInt = allocStruc(BB); /* ^ empty BB */ + memset (derivedGi->Gi->reachingInt, 0, sizeof(BB)); /* Process header nodes list H */ - while (!H.empty()) + while (nonEmpty (H)) { - header = firstOfQueue (H); - pI = new interval; - pI->numInt = (uint8_t)numInt++; - if (first) /* ^ to first interval */ - Ii = J = pI; - appendNodeInt (H, header, pI); /* pI(header) = {header} */ + header = firstOfQueue (&H); + pI = allocStruc(interval); + memset (pI, 0, sizeof(interval)); + pI->numInt = (byte)numInt++; + if (first) /* ^ to first interval */ + derivedGi->Ii = J = pI; + H = 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->edges.size(); i++) - { - succ = h->edges[i].BBptr; - succ->inEdgeCount--; + /* Process all nodes in the current interval list */ + while ((h = firstOfInt (pI)) != 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++; + if (succ->reachingInt == NULL) /* first visit */ + { + succ->reachingInt = header; + if (succ->inEdgeCount == 0) + H = 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) + H = 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; + /* 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) -{ +/* Displays the intervals of the graph Gi. */ +{ queue *nodePtr; while (pI) { - printf (" Interval #: %ld\t#OutEdges: %ld\n", pI->numInt, pI->numOutEdges); - for(BB *node : pI->nodes) - { - if (node->correspInt == NULL) /* real BBs */ - printf (" Node: %ld\n", node->begin()->loc_ip); - else // BBs represent intervals - printf (" Node (corresp int): %d\n", node->correspInt->numInt); - } - pI = pI->next; + nodePtr = pI->nodes; + printf (" Interval #: %ld\t#OutEdges: %ld\n", + pI->numInt, pI->numOutEdges); + + while (nodePtr) + { + if (nodePtr->node->correspInt == NULL) /* real BBs */ + printf (" Node: %ld\n", nodePtr->node->start); + else /* BBs represent intervals */ + printf (" Node (corresp int): %d\n", + nodePtr->node->correspInt->numInt); + nodePtr = nodePtr->next; + } + pI = pI->next; } } +static derSeq *newDerivedSeq() /* Allocates space for a new derSeq node. */ -static derSeq_Entry *newDerivedSeq() -{ - return new derSeq_Entry; +{ derSeq *pder; + + pder = allocStruc(derSeq); + memset (pder, 0, sizeof(derSeq)); + return (pder); } +static void freeQueue (queue **q) /* Frees the storage allocated for the queue q*/ -static void freeQueue (queue &q) -{ - q.clear(); +{ queue *queuePtr; + + for (queuePtr = *q; queuePtr; queuePtr = *q) + { + *q = (*q)->next; + free (queuePtr); + } } -/* Frees the storage allocated for the interval pI */ static void freeInterval (interval **pI) -{ - interval *Iptr; +/* Frees the storage allocated for the interval pI */ +{ interval *Iptr; while (*pI) { - (*pI)->nodes.clear(); - Iptr = *pI; - *pI = (*pI)->next; - delete (Iptr); + freeQueue (&((*pI)->nodes)); + Iptr = *pI; + *pI = (*pI)->next; + free (Iptr); } } -/* Frees the storage allocated by the derived sequence structure, except +void freeDerivedSeq(derSeq *derivedG) +/* 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); +{ derSeq *derivedGi; + + while (derivedG) + { + freeInterval (&(derivedG->Ii)); + if (derivedG->Gi->nodeType == INTERVAL_NODE) + freeCFG (derivedG->Gi); + derivedGi = derivedG; + derivedG = derivedG->next; + free (derivedGi); + } } -/* Finds the next order graph of derivedGi->Gi according to its intervals + +static boolT nextOrderGraph (derSeq *derivedGi) +/* Finds the next order graph of derivedGi->Gi according to its intervals * (derivedGi->Ii), and places it in derivedGi->next->Gi. */ -bool Function::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 */ +{ interval *Ii; /* Interval being processed */ + BB *BBnode, /* New basic block of intervals */ + *curr, /* BB being checked for out edges */ + *succ, /* Successor node */ + derInt; + 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 bbs; - while (Ii) - { - i = 0; - bbs.push_back(BB::Create(-1, -1, INTERVAL_NODE, Ii->numOutEdges, this)); - BBnode = bbs.back(); - BBnode->correspInt = Ii; - const queue &listIi(Ii->nodes); + derivedGi->next = newDerivedSeq(); + Ii = derivedGi->Ii; + sameGraph = TRUE; + derInt.next = NULL; + BBnode = &derInt; - /* Check for more than 1 interval */ - if (sameGraph && (listIi.size()>1)) - sameGraph = false; + while (Ii) { + i = 0; + BBnode = newBB (BBnode, -1, -1, INTERVAL_NODE, Ii->numOutEdges, NULL); + BBnode->correspInt = Ii; + listIi = Ii->nodes; - /* Find out edges */ + /* Check for more than 1 interval */ + if (sameGraph && listIi->next) + sameGraph = FALSE; - if (BBnode->edges.size() > 0) - { - for(BB *curr : listIi) - { - for (j = 0; j < curr->edges.size(); j++) - { - succ = curr->edges[j].BBptr; - if (succ->inInterval != curr->inInterval) - BBnode->edges[i++].intPtr = succ->inInterval; - } - } - } + /* Find out edges */ + if (BBnode->numOutEdges > 0) + while (listIi) { + curr = listIi->node; + for (j = 0; j < curr->numOutEdges; j++) { + succ = curr->edges[j].BBptr; + if (succ->inInterval != curr->inInterval) + BBnode->edges[i++].intPtr = succ->inInterval; + } + listIi = listIi->next; + } - /* Next interval */ - Ii = Ii->next; + /* 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(BB *curr : bbs) - { - for(TYPEADR_TYPE &edge : curr->edges) - { - BBnode = new_entry.Gi; /* BB of an interval */ - 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)->inEdges.push_back((BB *)nullptr); - (*iter)->inEdgeCount++; - } + curr = derivedGi->next->Gi = derInt.next; + while (curr) { + for (i = 0; i < curr->numOutEdges; i++) { + BBnode = derivedGi->next->Gi; /* BB of an interval */ + while (BBnode && curr->edges[i].intPtr != BBnode->correspInt) + BBnode = BBnode->next; + if (BBnode) { + curr->edges[i].BBptr = BBnode; + BBnode->numInEdges++; + BBnode->inEdgeCount++; + } + else + fatalError (INVALID_INT_BB); + } + curr = curr->next; } return (boolT)(! sameGraph); } +static byte findDerivedSeq (derSeq *derivedGi) /* 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. */ -uint8_t Function::findDerivedSeq (derSeq &derivedGi) -{ - BB *Gi; /* Current derived sequence graph */ +{ BB *Gi; /* Current derived sequence graph */ - derSeq::iterator iter=derivedGi.begin(); - Gi = iter->Gi; + Gi = derivedGi->Gi; while (! trivialGraph (Gi)) { - /* Find the intervals of Gi and place them in derivedGi->Ii */ - iter->findIntervals(this); + /* Find the intervals of Gi and place them in derivedGi->Ii */ + findIntervals (derivedGi); - /* Create Gi+1 and check if it is equivalent to Gi */ - if (! nextOrderGraph (derivedGi)) - break; - ++iter; - Gi = iter->Gi; - stats.nOrder++; + /* Create Gi+1 and check if it is equivalent to Gi */ + if (! nextOrderGraph (derivedGi)) + break; + + derivedGi = derivedGi->next; + Gi = derivedGi->Gi; + stats.nOrder++; } if (! trivialGraph (Gi)) { - ++iter; - derivedGi.erase(iter,derivedGi.end()); /* remove Gi+1 */ - // freeDerivedSeq(derivedGi->next); - // derivedGi->next = NULL; - return false; + freeDerivedSeq(derivedGi->next); /* remove Gi+1 */ + derivedGi->next = NULL; + return FALSE; } - derivedGi.back().findIntervals (this); - return true; + findIntervals (derivedGi); + return TRUE; } + +static void nodeSplitting (BB *G) /* Converts the irreducible graph G into an equivalent reducible one, by * means of node splitting. */ -static void nodeSplitting (std::list &G) { - fprintf(stderr,"Attempt to perform node splitting: NOT IMPLEMENTED\n"); + } + + +void displayDerivedSeq(derSeq *derGi) /* Displays the derived sequence and intervals of the graph G */ -void derSeq::display() { - int n = 1; /* Derived sequence number */ + Int n = 1; /* Derived sequence number */ printf ("\nDerived Sequence Intervals\n"); - derSeq::iterator iter=this->begin(); - while (iter!=this->end()) + while (derGi) { - printf ("\nIntervals for G%lX\n", n++); - displayIntervals (iter->Ii); - ++iter; + printf ("\nIntervals for G%lX\n", n++); + displayIntervals (derGi->Ii); + derGi = derGi->next; } } +void checkReducibility (PPROC pProc, derSeq **derivedG) /* 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; - uint8_t reducible; /* Reducible graph flag */ +{ 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 = m_cfg.front(); - reducible = findDerivedSeq(*der_seq); + stats.nOrder = 1; /* nOrder(cfg) = 1 */ + *derivedG = newDerivedSeq(); + (*derivedG)->Gi = pProc->cfg; + reducible = findDerivedSeq(*derivedG); - if (! reducible) - { - flg |= GRAPH_IRRED; - nodeSplitting (m_cfg); + if (! reducible) { + pProc->flg |= GRAPH_IRRED; + nodeSplitting (pProc->cfg); } - return der_seq; } diff --git a/src/scanner.cpp b/src/scanner.cpp index 86fe2d4..93e1e0c 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -5,923 +5,812 @@ * (C) Cristina Cifuentes, Jeff Ledermann ****************************************************************************/ -#include #include "dcc.h" #include "scanner.h" -#include "project.h" -/* Parser flags */ -#define TO_REG 0x000100 /* rm is source */ -#define S_EXT 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 */ +#include -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); - -#define iZERO (llIcode)0 // For neatness +#define iZERO (llIcode)0 // For neatness #define IC llIcode static struct { - void (*state1)(int); - void (*state2)(int); - uint32_t flg; - llIcode opcode; + void (*state1)(Int); + void (*state2)(Int); + flags32 flg; + llIcode opcode; + byte df; + byte uf; } stateTable[] = { - { modrm, none2, B , iADD }, /* 00 */ - { modrm, none2, 0 , iADD }, /* 01 */ - { modrm, none2, TO_REG | B , iADD }, /* 02 */ - { modrm, none2, TO_REG , iADD }, /* 03 */ - { data1, axImp, B , iADD }, /* 04 */ - { data2, axImp, 0 , iADD }, /* 05 */ - { segop, none2, NO_SRC , iPUSH }, /* 06 */ - { segop, none2, NO_SRC , iPOP }, /* 07 */ - { modrm, none2, B , iOR }, /* 08 */ - { modrm, none2, NSP , iOR }, /* 09 */ - { modrm, none2, TO_REG | B , iOR }, /* 0A */ - { modrm, none2, TO_REG | NSP , iOR }, /* 0B */ - { data1, axImp, B , iOR }, /* 0C */ - { data2, axImp, 0 , iOR }, /* 0D */ - { segop, none2, NO_SRC , iPUSH }, /* 0E */ - { none1, none2, OP386 , iZERO }, /* 0F */ - { modrm, none2, B , iADC }, /* 10 */ - { modrm, none2, NSP , iADC }, /* 11 */ - { modrm, none2, TO_REG | B , iADC }, /* 12 */ - { modrm, none2, TO_REG | NSP , iADC }, /* 13 */ - { data1, axImp, B , iADC }, /* 14 */ - { data2, axImp, 0 , iADC }, /* 15 */ - { segop, none2, NOT_HLL | NO_SRC , iPUSH }, /* 16 */ - { segop, none2, NOT_HLL | NO_SRC , iPOP }, /* 17 */ - { modrm, none2, B , iSBB }, /* 18 */ - { modrm, none2, NSP , iSBB }, /* 19 */ - { modrm, none2, TO_REG | B , iSBB }, /* 1A */ - { modrm, none2, TO_REG | NSP , iSBB }, /* 1B */ - { data1, axImp, B , iSBB }, /* 1C */ - { data2, axImp, 0 , iSBB }, /* 1D */ - { segop, none2, NO_SRC , iPUSH }, /* 1E */ - { segop, none2, NO_SRC , iPOP }, /* 1F */ - { modrm, none2, B , iAND }, /* 20 */ - { modrm, none2, NSP , iAND }, /* 21 */ - { modrm, none2, TO_REG | B , iAND }, /* 22 */ - { modrm, none2, TO_REG | NSP , iAND }, /* 23 */ - { data1, axImp, B , iAND }, /* 24 */ - { data2, axImp, 0 , iAND }, /* 25 */ - { prefix, none2, 0 , (IC)rES}, /* 26 */ - { none1, axImp, NOT_HLL | B|NO_SRC , iDAA }, /* 27 */ - { modrm, none2, B , iSUB }, /* 28 */ - { modrm, none2, 0 , iSUB }, /* 29 */ - { modrm, none2, TO_REG | B , iSUB }, /* 2A */ - { modrm, none2, TO_REG , iSUB }, /* 2B */ - { data1, axImp, B , iSUB }, /* 2C */ - { data2, axImp, 0 , iSUB }, /* 2D */ - { prefix, none2, 0 , (IC)rCS}, /* 2E */ - { none1, axImp, NOT_HLL | B|NO_SRC , iDAS }, /* 2F */ - { modrm, none2, B , iXOR }, /* 30 */ - { modrm, none2, NSP , iXOR }, /* 31 */ - { modrm, none2, TO_REG | B , iXOR }, /* 32 */ - { modrm, none2, TO_REG | NSP , iXOR }, /* 33 */ - { data1, axImp, B , iXOR }, /* 34 */ - { data2, axImp, 0 , iXOR }, /* 35 */ - { prefix, none2, 0 , (IC)rSS}, /* 36 */ - { none1, axImp, NOT_HLL | NO_SRC , iAAA }, /* 37 */ - { modrm, none2, B , iCMP }, /* 38 */ - { modrm, none2, NSP , iCMP }, /* 39 */ - { modrm, none2, TO_REG | B , iCMP }, /* 3A */ - { modrm, none2, TO_REG | NSP , iCMP }, /* 3B */ - { data1, axImp, B , iCMP }, /* 3C */ - { data2, axImp, 0 , iCMP }, /* 3D */ - { prefix, none2, 0 , (IC)rDS}, /* 3E */ - { none1, axImp, NOT_HLL | NO_SRC , iAAS }, /* 3F */ - { regop, none2, 0 , iINC }, /* 40 */ - { regop, none2, 0 , iINC }, /* 41 */ - { regop, none2, 0 , iINC }, /* 42 */ - { regop, none2, 0 , iINC }, /* 43 */ - { regop, none2, NOT_HLL , iINC }, /* 44 */ - { regop, none2, 0 , iINC }, /* 45 */ - { regop, none2, 0 , iINC }, /* 46 */ - { regop, none2, 0 , iINC }, /* 47 */ - { regop, none2, 0 , iDEC }, /* 48 */ - { regop, none2, 0 , iDEC }, /* 49 */ - { regop, none2, 0 , iDEC }, /* 4A */ - { regop, none2, 0 , iDEC }, /* 4B */ - { regop, none2, NOT_HLL , iDEC }, /* 4C */ - { regop, none2, 0 , iDEC }, /* 4D */ - { regop, none2, 0 , iDEC }, /* 4E */ - { regop, none2, 0 , iDEC }, /* 4F */ - { regop, none2, NO_SRC , iPUSH }, /* 50 */ - { regop, none2, NO_SRC , iPUSH }, /* 51 */ - { regop, none2, NO_SRC , iPUSH }, /* 52 */ - { regop, none2, NO_SRC , iPUSH }, /* 53 */ - { regop, none2, NOT_HLL | NO_SRC , iPUSH }, /* 54 */ - { regop, none2, NO_SRC , iPUSH }, /* 55 */ - { regop, none2, NO_SRC , iPUSH }, /* 56 */ - { regop, none2, NO_SRC , iPUSH }, /* 57 */ - { regop, none2, NO_SRC , iPOP }, /* 58 */ - { regop, none2, NO_SRC , iPOP }, /* 59 */ - { regop, none2, NO_SRC , iPOP }, /* 5A */ - { regop, none2, NO_SRC , iPOP }, /* 5B */ - { regop, none2, NOT_HLL | NO_SRC , iPOP }, /* 5C */ - { regop, none2, NO_SRC , iPOP }, /* 5D */ - { regop, none2, NO_SRC , iPOP }, /* 5E */ - { regop, none2, NO_SRC , iPOP }, /* 5F */ - { none1, none2, NOT_HLL | NO_OPS , iPUSHA}, /* 60 */ - { none1, none2, NOT_HLL | NO_OPS , iPOPA }, /* 61 */ - { memOnly, modrm, TO_REG | NSP , iBOUND}, /* 62 */ - { none1, none2, OP386 , iZERO }, /* 63 */ - { none1, none2, OP386 , iZERO }, /* 64 */ - { none1, none2, OP386 , iZERO }, /* 65 */ - { none1, none2, OP386 , iZERO }, /* 66 */ - { none1, none2, OP386 , iZERO }, /* 67 */ - { data2, none2, NO_SRC , iPUSH }, /* 68 */ - { modrm, data2, TO_REG | NSP , iIMUL }, /* 69 */ - { data1, none2, S_EXT | NO_SRC , iPUSH }, /* 6A */ - { modrm, data1, TO_REG | NSP | S_EXT , iIMUL }, /* 6B */ - { strop, memImp, NOT_HLL | B|IM_OPS , iINS }, /* 6C */ - { strop, memImp, NOT_HLL | IM_OPS , iINS }, /* 6D */ - { strop, memImp, NOT_HLL | B|IM_OPS , iOUTS }, /* 6E */ - { strop, memImp, NOT_HLL | IM_OPS , iOUTS }, /* 6F */ - { dispS, none2, NOT_HLL , iJO }, /* 70 */ - { dispS, none2, NOT_HLL , iJNO }, /* 71 */ - { dispS, none2, 0 , iJB }, /* 72 */ - { dispS, none2, 0 , iJAE }, /* 73 */ - { dispS, none2, 0 , iJE }, /* 74 */ - { dispS, none2, 0 , iJNE }, /* 75 */ - { dispS, none2, 0 , iJBE }, /* 76 */ - { dispS, none2, 0 , iJA }, /* 77 */ - { dispS, none2, 0 , iJS }, /* 78 */ - { dispS, none2, 0 , iJNS }, /* 79 */ - { dispS, none2, NOT_HLL , iJP }, /* 7A */ - { dispS, none2, NOT_HLL , iJNP }, /* 7B */ - { dispS, none2, 0 , iJL }, /* 7C */ - { dispS, none2, 0 , iJGE }, /* 7D */ - { dispS, none2, 0 , iJLE }, /* 7E */ - { dispS, none2, 0 , iJG }, /* 7F */ - { immed, data1, B , iZERO }, /* 80 */ - { immed, data2, NSP , iZERO }, /* 81 */ - { immed, data1, B , iZERO }, /* 82 */ /* ?? */ - { immed, data1, NSP | S_EXT , iZERO }, /* 83 */ - { modrm, none2, TO_REG | B , iTEST }, /* 84 */ - { modrm, none2, TO_REG | NSP , iTEST }, /* 85 */ - { modrm, none2, TO_REG | B , iXCHG }, /* 86 */ - { modrm, none2, TO_REG | NSP , iXCHG }, /* 87 */ - { modrm, none2, B , iMOV }, /* 88 */ - { modrm, none2, 0 , iMOV }, /* 89 */ - { modrm, none2, TO_REG | B , iMOV }, /* 8A */ - { modrm, none2, TO_REG , iMOV }, /* 8B */ - { segrm, none2, NSP , iMOV }, /* 8C */ - { memOnly, modrm, TO_REG | NSP , iLEA }, /* 8D */ - { segrm, none2, TO_REG | NSP , iMOV }, /* 8E */ - { memReg0, none2, NO_SRC , iPOP }, /* 8F */ - { none1, none2, NO_OPS , iNOP }, /* 90 */ - { regop, axImp, 0 , iXCHG }, /* 91 */ - { regop, axImp, 0 , iXCHG }, /* 92 */ - { regop, axImp, 0 , iXCHG }, /* 93 */ - { regop, axImp, NOT_HLL , iXCHG }, /* 94 */ - { regop, axImp, 0 , iXCHG }, /* 95 */ - { regop, axImp, 0 , iXCHG }, /* 96 */ - { regop, axImp, 0 , iXCHG }, /* 97 */ - { alImp, axImp, SRC_B | S_EXT , iSIGNEX}, /* 98 */ - {axSrcIm, axImp, IM_DST | S_EXT , iSIGNEX}, /* 99 */ - { dispF, none2, 0 , iCALLF }, /* 9A */ - { none1, none2, FLOAT_OP| NO_OPS , iWAIT }, /* 9B */ - { none1, none2, NOT_HLL | NO_OPS , iPUSHF}, /* 9C */ - { none1, none2, NOT_HLL | NO_OPS , iPOPF }, /* 9D */ - { none1, none2, NOT_HLL | NO_OPS , iSAHF }, /* 9E */ - { none1, none2, NOT_HLL | NO_OPS , iLAHF }, /* 9F */ - { dispM, axImp, B , iMOV }, /* A0 */ - { dispM, axImp, 0 , iMOV }, /* A1 */ - { dispM, axImp, TO_REG | B , iMOV }, /* A2 */ - { dispM, axImp, TO_REG , iMOV }, /* A3 */ - { strop, memImp, B | IM_OPS , iMOVS }, /* A4 */ - { strop, memImp, IM_OPS , iMOVS }, /* A5 */ - { strop, memImp, B | IM_OPS , iCMPS }, /* A6 */ - { strop, memImp, IM_OPS , iCMPS }, /* A7 */ - { data1, axImp, B , iTEST }, /* A8 */ - { data2, axImp, 0 , iTEST }, /* A9 */ - { strop, memImp, B | IM_OPS , iSTOS }, /* AA */ - { strop, memImp, IM_OPS , iSTOS }, /* AB */ - { strop, memImp, B | IM_OPS , iLODS }, /* AC */ - { strop, memImp, IM_OPS , iLODS }, /* AD */ - { strop, memImp, B | IM_OPS , iSCAS }, /* AE */ - { strop, memImp, IM_OPS , iSCAS }, /* AF */ - { regop, data1, B , iMOV }, /* B0 */ - { regop, data1, B , iMOV }, /* B1 */ - { regop, data1, B , iMOV }, /* B2 */ - { regop, data1, B , iMOV }, /* B3 */ - { regop, data1, B , iMOV }, /* B4 */ - { regop, data1, B , iMOV }, /* B5 */ - { regop, data1, B , iMOV }, /* B6 */ - { regop, data1, B , iMOV }, /* B7 */ - { regop, data2, 0 , iMOV }, /* B8 */ - { regop, data2, 0 , iMOV }, /* B9 */ - { regop, data2, 0 , iMOV }, /* BA */ - { regop, data2, 0 , iMOV }, /* BB */ - { regop, data2, NOT_HLL , iMOV }, /* BC */ - { regop, data2, 0 , iMOV }, /* BD */ - { regop, data2, 0 , iMOV }, /* BE */ - { regop, data2, 0 , iMOV }, /* BF */ - { shift, data1, B , iZERO }, /* C0 */ - { shift, data1, NSP | SRC_B , iZERO }, /* C1 */ - { data2, none2, 0 , iRET }, /* C2 */ - { none1, none2, NO_OPS , iRET }, /* C3 */ - { memOnly, modrm, TO_REG | NSP , iLES }, /* C4 */ - { memOnly, modrm, TO_REG | NSP , iLDS }, /* C5 */ - { memReg0, data1, B , iMOV }, /* C6 */ - { memReg0, data2, 0 , iMOV }, /* C7 */ - { data2, data1, 0 , iENTER}, /* C8 */ - { none1, none2, NO_OPS , iLEAVE}, /* C9 */ - { data2, none2, 0 , iRETF }, /* CA */ - { none1, none2, NO_OPS , iRETF }, /* CB */ - { const3, none2, NOT_HLL , iINT }, /* CC */ - { data1,checkInt, NOT_HLL , iINT }, /* CD */ - { none1, none2, NOT_HLL | NO_OPS , iINTO }, /* CE */ - { none1, none2, NOT_HLL | NO_OPS , iIRET }, /* Cf */ - { shift, const1, B , iZERO }, /* D0 */ - { shift, const1, SRC_B , iZERO }, /* D1 */ - { shift, none1, B , iZERO }, /* D2 */ - { shift, none1, SRC_B , iZERO }, /* D3 */ - { data1, axImp, NOT_HLL , iAAM }, /* D4 */ - { data1, axImp, NOT_HLL , iAAD }, /* D5 */ - { none1, none2, 0 , iZERO }, /* D6 */ - { memImp, axImp, NOT_HLL | B| IM_OPS , iXLAT }, /* D7 */ - { escop, none2, FLOAT_OP , iESC }, /* D8 */ - { escop, none2, FLOAT_OP , iESC }, /* D9 */ - { escop, none2, FLOAT_OP , iESC }, /* DA */ - { escop, none2, FLOAT_OP , iESC }, /* DB */ - { escop, none2, FLOAT_OP , iESC }, /* DC */ - { escop, none2, FLOAT_OP , iESC }, /* DD */ - { escop, none2, FLOAT_OP , iESC }, /* DE */ - { escop, none2, FLOAT_OP , iESC }, /* Df */ - { dispS, none2, 0 , iLOOPNE}, /* E0 */ - { dispS, none2, 0 , iLOOPE}, /* E1 */ - { dispS, none2, 0 , iLOOP }, /* E2 */ - { dispS, none2, 0 , iJCXZ }, /* E3 */ - { data1, axImp, NOT_HLL | B|NO_SRC , iIN }, /* E4 */ - { data1, axImp, NOT_HLL | NO_SRC , iIN }, /* E5 */ - { data1, axImp, NOT_HLL | B|NO_SRC , iOUT }, /* E6 */ - { data1, axImp, NOT_HLL | NO_SRC , iOUT }, /* E7 */ - { dispN, none2, 0 , iCALL }, /* E8 */ - { dispN, none2, 0 , iJMP }, /* E9 */ - { dispF, none2, 0 , iJMPF }, /* EA */ - { dispS, none2, 0 , iJMP }, /* EB */ - { none1, axImp, NOT_HLL | B|NO_SRC , iIN }, /* EC */ - { none1, axImp, NOT_HLL | NO_SRC , iIN }, /* ED */ - { none1, axImp, NOT_HLL | B|NO_SRC , iOUT }, /* EE */ - { none1, axImp, NOT_HLL | NO_SRC , iOUT }, /* EF */ - { none1, none2, NOT_HLL | NO_OPS , iLOCK }, /* F0 */ - { none1, none2, 0 , iZERO }, /* F1 */ - { prefix, none2, 0 , iREPNE}, /* F2 */ - { prefix, none2, 0 , iREPE }, /* F3 */ - { none1, none2, NOT_HLL | NO_OPS , iHLT }, /* F4 */ - { none1, none2, NO_OPS , iCMC }, /* F5 */ - { arith, none1, B , iZERO }, /* F6 */ - { arith, none1, NSP , iZERO }, /* F7 */ - { none1, none2, NO_OPS , iCLC }, /* F8 */ - { none1, none2, NO_OPS , iSTC }, /* F9 */ - { none1, none2, NOT_HLL | NO_OPS , iCLI }, /* FA */ - { none1, none2, NOT_HLL | NO_OPS , iSTI }, /* FB */ - { none1, none2, NO_OPS , iCLD }, /* FC */ - { none1, none2, NO_OPS , iSTD }, /* FD */ - { trans, none1, B , iZERO }, /* FE */ - { trans, none1, NSP , iZERO } /* FF */ + { 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 uint16_t SegPrefix, RepPrefix; -static uint8_t *pInst; /* Ptr. to current uint8_t of instruction */ -static ICODE * pIcode; /* Ptr to Icode record filled in by scan() */ +static word SegPrefix, RepPrefix; +static byte *pInst; /* Ptr. to current byte of instruction */ +static PICODE 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. ****************************************************************************/ - -static void convertUsedFlags(x86_insn_t &from,ICODE &to) +Int scan(dword ip, PICODE p) { - to.ll()->flagDU.d=0; - to.ll()->flagDU.u=0; - if(from.containsFlag(insn_eflag_carry,from.flags_set)) - to.ll()->flagDU.d |= Cf; - if(from.containsFlag(insn_eflag_sign,from.flags_set)) - to.ll()->flagDU.d |= Sf; - if(from.containsFlag(insn_eflag_zero,from.flags_set)) - to.ll()->flagDU.d |= Zf; - if(from.containsFlag(insn_eflag_direction,from.flags_set)) - to.ll()->flagDU.d |= Df; + Int op; - if(from.containsFlag(insn_eflag_carry,from.flags_tested)) - to.ll()->flagDU.u |= Cf; - if(from.containsFlag(insn_eflag_sign,from.flags_tested)) - to.ll()->flagDU.u |= Sf; - if(from.containsFlag(insn_eflag_zero,from.flags_tested)) - to.ll()->flagDU.u |= Zf; - if(from.containsFlag(insn_eflag_direction,from.flags_tested)) - to.ll()->flagDU.u |= Df; -} -/**************************************************************************** - Checks for int 34 to int 3B - if so, converts to ESC nn instruction - ****************************************************************************/ -static void fixFloatEmulation(x86_insn_t &insn) -{ - if(insn.group!=x86_insn_t::insn_interrupt) - return; - PROG &prog(Project::get()->prog); - uint16_t wOp=insn.x86_get_imm()->data.word; - if ((wOp < 0x34) || (wOp > 0x3B)) - return; - uint8_t buf[16]; - /* This is a Borland/Microsoft floating point emulation instruction. - Treat as if it is an ESC opcode */ + 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); + } - int actual_valid_bytes=std::min(16U,prog.cbImage-insn.offset); - memcpy(buf,prog.Image+insn.offset,actual_valid_bytes); - X86_Disasm ds(opt_16_bit); - x86_insn_t patched_insn; - //patch actual instruction into buffer; - buf[1] = wOp-0x34+0xD8; - ds.x86_disasm(buf,actual_valid_bytes,0,1,&patched_insn); - patched_insn.addr = insn.addr; // actual address - patched_insn.offset = insn.offset; // actual offset - insn = patched_insn; - insn.size += 1; // to account for emulator call INT -} + SegPrefix = RepPrefix = 0; + pInst = prog.Image + ip; + pIcode = p; -int disassembleOneLibDisasm(uint32_t ip,x86_insn_t &l) -{ - PROG &prog(Project::get()->prog); - X86_Disasm ds(opt_16_bit); - int cnt=ds.x86_disasm(prog.Image,prog.cbImage,0,ip,&l); - if(cnt && l.is_valid()) - { - fixFloatEmulation(l); //can change 'l' - } - if(l.is_valid()) - return l.size; - return 0; -} -eReg convertRegister(const x86_reg_t ®) -{ + 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; - eReg regmap[]={ rUNDEF, - rUNDEF,rUNDEF,rUNDEF,rUNDEF, //eax ecx ebx edx - rUNDEF,rUNDEF,rUNDEF,rUNDEF, //esp ebp esi edi - rAX,rCX,rDX,rBX, - rSP,rBP,rSI,rDI, - rAL,rCL,rDL,rBL, - rAH,rCH,rDH,rBH - }; - assert(reg.idprog); - int op; - p = ICODE(); - p.type = LOW_LEVEL; - p.ll()->label = ip; /* ip is absolute offset into image*/ - if (ip >= (uint32_t)prog.cbImage) - { - return (IP_OUT_OF_RANGE); - } - int cnt=disassembleOneLibDisasm(ip,p.insn); - if(cnt) - { - convertUsedFlags(p.insn,p); - } + (*stateTable[op].state1)(op); /* Second state */ + (*stateTable[op].state2)(op); /* Third state */ - SegPrefix = RepPrefix = 0; - pInst = prog.Image + ip; - pIcode = &p; + } while (stateTable[op].state1 == prefix); /* Loop if prefix */ - do - { - op = *pInst++; /* First state - trivial */ - /* Convert to Icode.opcode */ - p.ll()->set(stateTable[op].opcode,stateTable[op].flg & ICODEMASK); - (*stateTable[op].state1)(op); /* Second state */ - (*stateTable[op].state2)(op); /* Third state */ - - } while (stateTable[op].state1 == prefix); /* Loop if prefix */ - if (p.ll()->getOpcode()) - { - /* Save bytes of image used */ - p.ll()->numBytes = (uint8_t)((pInst - prog.Image) - ip); - if(p.insn.is_valid()) - assert(p.ll()->numBytes == p.insn.size); - return ((SegPrefix)? FUNNY_SEGOVR: /* Seg. Override invalid */ - (RepPrefix ? FUNNY_REP: NO_ERR));/* REP prefix invalid */ - } - /* Else opcode error */ - return ((stateTable[op].flg & OP386)? INVALID_386OP: INVALID_OPCODE); -} - -/*************************************************************************** - relocItem - returns true if uint16_t pointed at is in relocation table - **************************************************************************/ -static bool relocItem(uint8_t *p) -{ - PROG &prog(Project::get()->prog); - int i; - uint32_t off = p - prog.Image; - - for (i = 0; i < prog.cReloc; i++) - if (prog.relocTable[i] == off) - return true; - return false; + 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); } /*************************************************************************** - getWord - returns next uint16_t from image + relocItem - returns TRUE if word pointed at is in relocation table **************************************************************************/ -static uint16_t getWord(void) +static boolT relocItem(byte *p) { - uint16_t w = LH(pInst); - pInst += 2; - return w; + 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 uint8_t sign extended to int + signex - returns byte sign extended to Int ***************************************************************************/ -static int signex(uint8_t b) +static Int signex(byte b) { - long s = b; - return ((b & 0x80)? (int)(0xFFFFFF00 | s): (int)s); + long s = b; + return ((b & 0x80)? (Int)(0xFFFFFF00 | s): (Int)s); } + /**************************************************************************** - * setAddress - Updates the source or destination field for the current + * 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 + * 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, uint16_t seg, int16_t reg, uint16_t off) +static void setAddress(Int i, boolT fdst, word seg, int16 reg, word off) { - LLOperand *pm; + PMEM 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->ll()->dst : &pIcode->ll()->src(); + /* 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 = (eReg)seg; - } - else - { /* no override, check indexed register */ - if ((reg >= INDEX_BX_SI) && (reg == INDEX_BP_SI || reg == INDEX_BP_DI || reg == INDEX_BP)) - { - pm->seg = rSS; /* indexed on bp */ - } - else - { - pm->seg = rDS; /* any other indexed reg */ - } - } + /* 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; + } - pm->regi = (eReg)reg; - pm->off = (int16_t)off; - if (reg && reg < INDEX_BX_SI && (stateTable[i].flg & B)) - { - pm->regi = Machine_X86::subRegL(pm->regi); - } - - if (seg) /* So we can catch invalid use of segment overrides */ - { - SegPrefix = 0; - } + if (seg) /* So we can catch invalid use of segment overrides */ + { + SegPrefix = 0; + } } /**************************************************************************** - rm - Decodes r/m part of modrm uint8_t for dst (unless TO_REG) part of icode + rm - Decodes r/m part of modrm byte for dst (unless TO_REG) part of icode ***************************************************************************/ -static void rm(int i) +static void rm(Int i) { - uint8_t mod = *pInst >> 6; - uint8_t rm = *pInst++ & 7; + 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->ll()->setFlags(WORD_OFF); - } - else - setAddress(i, true, SegPrefix, rm + INDEX_BX_SI, 0); - break; + 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 uint8_t disp */ - setAddress(i, true, SegPrefix, rm+INDEX_BX_SI, (uint16_t)signex(*pInst++)); - break; + case 1: /* 1 byte disp */ + setAddress(i, TRUE, SegPrefix, rm+INDEXBASE, (word)signex(*pInst++)); + break; - case 2: /* 2 uint8_t disp */ - setAddress(i, true, SegPrefix, rm + INDEX_BX_SI, getWord()); - pIcode->ll()->setFlags(WORD_OFF); - 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; - } + case 3: /* reg */ + setAddress(i, TRUE, 0, rm + rAX, 0); + break; + } - if ((stateTable[i].flg & NSP) && (pIcode->ll()->src().getReg2()==rSP || - pIcode->ll()->dst.getReg2()==rSP)) - pIcode->ll()->setFlags(NOT_HLL); + 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 uint8_t + modrm - Sets up src and dst from modrm byte ***************************************************************************/ -static void modrm(int i) +static void modrm(Int i) { - setAddress(i, false, 0, REG(*pInst) + rAX, 0); - rm(i); + setAddress(i, FALSE, 0, REG(*pInst) + rAX, 0); + rm(i); } /**************************************************************************** segrm - seg encoded as reg of modrm ****************************************************************************/ -static void segrm(int i) +static void segrm(Int i) { - int reg = REG(*pInst) + rES; + Int reg = REG(*pInst) + rES; - if (reg > rDS || (reg == rCS && (stateTable[i].flg & TO_REG))) - pIcode->ll()->setOpcode((llIcode)0); // setCBW because it has that index - else { - setAddress(i, false, 0, (int16_t)reg, 0); - rm(i); - } + 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) +static void regop(Int i) { - setAddress(i, false, 0, ((int16_t)i & 7) + rAX, 0); - pIcode->ll()->replaceDst(LLOperand::CreateReg2(pIcode->ll()->src().getReg2())); - // pIcode->ll()->dst.regi = pIcode->ll()->src.regi; + 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) +static void segop(Int i) { - setAddress(i, true, 0, (((int16_t)i & 0x18) >> 3) + rES, 0); + setAddress(i, TRUE, 0, (((int16)i & 0x18) >> 3) + rES, 0); } /**************************************************************************** axImp - Plugs an implied AX dst ***************************************************************************/ -static void axImp(int i) +static void axImp(Int i) { - setAddress(i, true, 0, rAX, 0); + setAddress(i, TRUE, 0, rAX, 0); } + +static void axSrcIm (Int i) /* Implied AX source */ -static void axSrcIm (int ) { - pIcode->ll()->replaceSrc(rAX);//src.regi = rAX; + pIcode->ic.ll.src.regi = rAX; } + +static void alImp (Int i) /* Implied AL source */ -static void alImp (int ) { - pIcode->ll()->replaceSrc(rAL);//src.regi = rAL; + pIcode->ic.ll.src.regi = rAL; } /***************************************************************************** memImp - Plugs implied src memory operand with any segment override ****************************************************************************/ -static void memImp(int i) +static void memImp(Int i) { - setAddress(i, false, SegPrefix, 0, 0); + setAddress(i, FALSE, SegPrefix, 0, 0); } /**************************************************************************** memOnly - Instruction is not valid if modrm refers to register (i.e. mod == 3) ***************************************************************************/ -static void memOnly(int ) +static void memOnly(Int i) { - if ((*pInst & 0xC0) == 0xC0) - pIcode->ll()->setOpcode((llIcode)0); + 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) +static void memReg0(Int i) { - if (REG(*pInst) || (*pInst & 0xC0) == 0xC0) - pIcode->ll()->setOpcode((llIcode)0); - else - rm(i); + if (REG(*pInst) || (*pInst & 0xC0) == 0xC0) + pIcode->ic.ll.opcode = (llIcode)0; + else + rm(i); } /*************************************************************************** - immed - Sets up dst and opcode from modrm uint8_t + immed - Sets up dst and opcode from modrm byte **************************************************************************/ -static void immed(int i) +static void immed(Int i) { - static llIcode immedTable[8] = {iADD, iOR, iADC, iSBB, iAND, iSUB, iXOR, iCMP}; + 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->ll()->setOpcode(immedTable[REG(*pInst)]) ; - rm(i); + 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->ll()->getOpcode() == iADD || pIcode->ll()->getOpcode() == iSUB) - pIcode->ll()->clrFlags(NOT_HLL); /* Allow ADD/SUB SP, immed */ + 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 uint8_t + shift - Sets up dst and opcode from modrm byte ***************************************************************************/ -static void shift(int i) +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 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->ll()->setOpcode(shiftTable[REG(*pInst)]); - rm(i); - pIcode->ll()->replaceSrc(rCL); //src.regi = + 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 uint8_t + trans - Sets up dst and opcode from modrm byte ***************************************************************************/ -static void trans(int i) +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 - }; - LLInst *ll = pIcode->ll(); - if ((uint8_t)REG(*pInst) < 2 || !(stateTable[i].flg & B)) { /* INC & DEC */ - ll->setOpcode(transTable[REG(*pInst)]); /* valid on bytes */ - rm(i); - ll->replaceSrc( pIcode->ll()->dst ); - if (ll->match(iJMP) || ll->match(iCALL) || ll->match(iCALLF)) - ll->setFlags(NO_OPS); - else if (ll->match(iINC) || ll->match(iPUSH) || ll->match(iDEC)) - ll->setFlags(NO_SRC); - } + 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 uint8_t + arith - Sets up dst and opcode from modrm byte ****************************************************************************/ -static void arith(int i) +static void arith(Int i) +{ byte opcode; +static llIcode arithTable[8] = { - uint8_t opcode; - static llIcode arithTable[8] = - { - iTEST , (llIcode)0, iNOT, iNEG, - iMUL , iIMUL, iDIV, iIDIV - }; - opcode = arithTable[REG(*pInst)]; - pIcode->ll()->setOpcode((llIcode)opcode); - rm(i); - if (opcode == iTEST) - { - if (stateTable[i].flg & B) - data1(i); - else - data2(i); - } - else if (!(opcode == iNOT || opcode == iNEG)) - { - pIcode->ll()->replaceSrc( pIcode->ll()->dst ); - setAddress(i, true, 0, rAX, 0); /* dst = AX */ - } - else if (opcode == iNEG || opcode == iNOT) - pIcode->ll()->setFlags(NO_SRC); + (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}; - if ((opcode == iDIV) || (opcode == iIDIV)) - { - if ( not pIcode->ll()->testFlags(B) ) - pIcode->ll()->setFlags(IM_TMP_DST); - } + 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 uint8_t data + data1 - Sets up immed from 1 byte data *****************************************************************************/ -static void data1(int i) +static void data1(Int i) { - pIcode->ll()->replaceSrc(LLOperand::CreateImm2((stateTable[i].flg & S_EXT)? signex(*pInst++): *pInst++)); - pIcode->ll()->setFlags(I); + pIcode->ic.ll.immed.op = (stateTable[i].flg & S)? signex(*pInst++): + *pInst++; + pIcode->ic.ll.flg |= I; } /***************************************************************************** - data2 - Sets up immed from 2 uint8_t data + data2 - Sets up immed from 2 byte data ****************************************************************************/ -static void data2(int ) +static void data2(Int i) { - if (relocItem(pInst)) - pIcode->ll()->setFlags(SEG_IMMED); + 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->ll()->getOpcode() == iENTER) - { - pIcode->ll()->dst.off = getWord(); - pIcode->ll()->setFlags(NO_OPS); - } - else - pIcode->ll()->replaceSrc(getWord()); - pIcode->ll()->setFlags(I); + /* 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 uint8_t offset without modrm (== mod 0, rm 6) (Note:TO_REG bits are - reversed) + dispM - 2 byte offset without modrm (== mod 0, rm 6) (Note:TO_REG bits are + reversed) ****************************************************************************/ -static void dispM(int i) +static void dispM(Int i) { - setAddress(i, false, SegPrefix, 0, getWord()); + setAddress(i, FALSE, SegPrefix, 0, getWord()); } /**************************************************************************** - dispN - 2 uint8_t disp as immed relative to ip + dispN - 2 byte disp as immed relative to ip ****************************************************************************/ -static void dispN(int ) +static void dispN(Int i) { - PROG &prog(Project::get()->prog); - long off = (short)getWord(); /* Signed displacement */ - + 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->ll()->replaceSrc((uint32_t)(off + (unsigned)(pInst - prog.Image))); - pIcode->ll()->setFlags(I); + 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 uint8_t disp as immed relative to ip + dispS - 1 byte disp as immed relative to ip ***************************************************************************/ -static void dispS(int ) +static void dispS(Int i) { - PROG &prog(Project::get()->prog); - long off = signex(*pInst++); /* Signed displacement */ + long off = signex(*pInst++); /* Signed displacement */ - pIcode->ll()->replaceSrc((uint32_t)(off + (unsigned)(pInst - prog.Image))); - pIcode->ll()->setFlags(I); + pIcode->ic.ll.immed.op = (dword)(off + (unsigned)(pInst - prog.Image)); + pIcode->ic.ll.flg |= I; } /**************************************************************************** - dispF - 4 uint8_t disp as immed 20-bit target address + dispF - 4 byte disp as immed 20-bit target address ***************************************************************************/ -static void dispF(int ) +static void dispF(Int i) { - uint32_t off = (unsigned)getWord(); - uint32_t seg = (unsigned)getWord(); + dword off = (unsigned)getWord(); + dword seg = (unsigned)getWord(); - pIcode->ll()->replaceSrc(off + ((uint32_t)(unsigned)seg << 4)); - pIcode->ll()->setFlags(I); + pIcode->ic.ll.immed.op = off + ((dword)(unsigned)seg << 4); + pIcode->ic.ll.flg |= I; } /**************************************************************************** - prefix - picks up prefix uint8_t for following instruction (LOCK is ignored - on purpose) + prefix - picks up prefix byte for following instruction (LOCK is ignored + on purpose) ****************************************************************************/ -static void prefix(int ) +static void prefix(Int i) { - if (pIcode->ll()->getOpcode() == iREPE || pIcode->ll()->getOpcode() == iREPNE) - RepPrefix = pIcode->ll()->getOpcode(); - else - SegPrefix = pIcode->ll()->getOpcode(); + 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(LLInst &ll) +inline void BumpOpcode(llIcode& ic) { - llIcode ic((llIcode)ll.getOpcode()); - ic = (llIcode)(((int)ic)+1); // Bump this icode via the int type - ll.setOpcode(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 ) +static void strop(Int i) { - if (RepPrefix) - { - // pIcode->ll()->getOpcode() += ((pIcode->ll()->getOpcode() == iCMPS || - // pIcode->ll()->getOpcode() == iSCAS) - // && RepPrefix == iREPE)? 2: 1; - if ((pIcode->ll()->match(iCMPS) || pIcode->ll()->match(iSCAS) ) && RepPrefix == iREPE) - BumpOpcode(*pIcode->ll()); // += 2 - BumpOpcode(*pIcode->ll()); // else += 1 - if (pIcode->ll()->match(iREP_LODS) ) - pIcode->ll()->setFlags(NOT_HLL); - RepPrefix = 0; - } + 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) +static void escop(Int i) { - pIcode->ll()->replaceSrc(REG(*pInst) + (uint32_t)((i & 7) << 3)); - pIcode->ll()->setFlags(I); - rm(i); + pIcode->ic.ll.immed.op = REG(*pInst) + (dword)((i & 7) << 3); + pIcode->ic.ll.flg |= I; + rm(i); } /**************************************************************************** const1 ****************************************************************************/ -static void const1(int ) +static void const1(Int i) { - pIcode->ll()->replaceSrc(1); - pIcode->ll()->setFlags(I); + pIcode->ic.ll.immed.op = 1; + pIcode->ic.ll.flg |= I; } /***************************************************************************** const3 ****************************************************************************/ -static void const3(int ) +static void const3(Int i) { - pIcode->ll()->replaceSrc(3); - pIcode->ll()->setFlags(I); + pIcode->ic.ll.immed.op = 3; + pIcode->ic.ll.flg |= I; } /**************************************************************************** none1 ****************************************************************************/ -static void none1(int ) +static void none1(Int i) { } @@ -929,24 +818,25 @@ static void none1(int ) /**************************************************************************** none2 - Sets the NO_OPS flag if the operand is immediate ****************************************************************************/ -static void none2(int ) +static void none2(Int i) { - if ( pIcode->ll()->testFlags(I) ) - pIcode->ll()->setFlags(NO_OPS); + 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 ) +static void checkInt(Int i) { - uint16_t wOp = (uint16_t) pIcode->ll()->src().getImm2(); + 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->ll()->replaceSrc(wOp - 0x34); - pIcode->ll()->set(iESC,FLOAT_OP); + pIcode->ic.ll.immed.op = wOp - 0x34; + pIcode->ic.ll.opcode = iESC; + pIcode->ic.ll.flg |= FLOAT_OP; escop(wOp - 0x34 + 0xD8); diff --git a/src/symtab.cpp b/src/symtab.cpp index a1541af..e1db263 100644 --- a/src/symtab.cpp +++ b/src/symtab.cpp @@ -10,7 +10,7 @@ \* * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* This file implements a symbol table with a symbolic name, a symbol value - (uint16_t), and a procedure number. Two tables are maintained, to be able to + (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 @@ -19,176 +19,564 @@ Linear probing is used, due to the difficulty of implementing (e.g.) quadratic probing with a variable table size. */ -#include -#include -#include -#include -#include + + +#include +#include +#include #include "dcc.h" #include "symtab.h" #define TABLESIZE 16 /* Number of entries added each expansion */ -/* Probably has to be a power of 2 */ + /* Probably has to be a power of 2 */ #define STRTABSIZE 256 /* Size string table is inc'd by */ -#define NIL ((uint16_t)-1) -using namespace std; +#define NIL ((word)-1) + + + +static word numEntry; /* Number of entries in this table */ +static word tableSize; /* Size of the table (entries) */ +static SYMTABLE *symTab; /* Pointer to the symbol hashed table */ +static SYMTABLE *valTab; /* Pointer to the value hashed table */ + static char *pStrTab; /* Pointer to the current string table */ static int strTabNext; /* Next free index into pStrTab */ -namespace std -{ -template<> -struct hash : public unary_function -{ - size_t operator()(const SYMTABLE & key) const - { - uint16_t h = 0; - h = (uint16_t)(key.symOff ^ (key.symOff >> 8)); - return h; - } -}; -} static tableType curTableType; /* Which table is current */ -struct TABLEINFO_TYPE +typedef struct _tableInfo { - TABLEINFO_TYPE() - { - symTab=valTab=0; - } - //void deleteVal(uint32_t symOff, Function *symProc, boolT bSymToo); - void create(tableType type); - void destroy(); -private: + SYMTABLE *symTab; + SYMTABLE *valTab; + word numEntry; + word tableSize; +} TABLEINFO_TYPE; - SYMTABLE *symTab; /* Pointer to the symbol hashed table */ - SYMTABLE *valTab; /* Pointer to the value hashed table */ - uint16_t numEntry; /* Number of entries in this table */ - uint16_t tableSize;/* Size of the table (entries) */ - unordered_map z; - unordered_map z2; -}; +TABLEINFO_TYPE tableInfo[NUM_TABLE_TYPES]; /* Array of info about tables */ -static TABLEINFO_TYPE tableInfo[NUM_TABLE_TYPES]; /* Array of info about tables */ -static TABLEINFO_TYPE currentTabInfo; + +/* Local prototypes */ +static void expandSym(void); /* Create a new symbol table. Returns "handle" */ -void TABLEINFO_TYPE::create(tableType type) -{ - switch(type) - { - case Comment: - numEntry = 0; - tableSize = TABLESIZE; - valTab = new SYMTABLE [TABLESIZE]; - symTab = 0; - break; - case Label: - currentTabInfo.numEntry = 0; - currentTabInfo.tableSize = TABLESIZE; - currentTabInfo.symTab = new SYMTABLE [TABLESIZE]; - currentTabInfo.valTab = new SYMTABLE [TABLESIZE]; - break; - } -} - void createSymTables(void) { /* Initilise the comment table */ /* NB - there is no symbol hashed comment table */ - currentTabInfo.create(Comment); - tableInfo[Comment] = currentTabInfo; + numEntry = 0; + tableSize = TABLESIZE; + valTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE); + memset(valTab, 0, sizeof(SYMTABLE) * TABLESIZE); + + tableInfo[Comment].symTab = 0; + tableInfo[Comment].valTab = valTab; + tableInfo[Comment].numEntry = numEntry; + tableInfo[Comment].tableSize = tableSize; + /* Initialise the label table */ - currentTabInfo.create(Label); + numEntry = 0; + tableSize = TABLESIZE; + symTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE); + memset(symTab, 0, sizeof(SYMTABLE) * TABLESIZE); - tableInfo[Label] = currentTabInfo; + valTab = (SYMTABLE*)allocMem(sizeof(SYMTABLE) * TABLESIZE); + memset(valTab, 0, sizeof(SYMTABLE) * TABLESIZE); + + tableInfo[Label].symTab = symTab; + tableInfo[Label].valTab = valTab; + tableInfo[Label].numEntry = numEntry; + tableInfo[Label].tableSize = tableSize; curTableType = Label; /* Now the string table */ strTabNext = 0; - pStrTab = new char[STRTABSIZE]; + pStrTab = (char *)allocMem(STRTABSIZE); + tableInfo[Label].symTab = symTab; + tableInfo[Label].valTab = valTab; + tableInfo[Label].numEntry = numEntry; + tableInfo[Label].tableSize = tableSize; curTableType = Label; } -void selectTable(tableType tt) +void +selectTable(tableType tt) { - if (curTableType == tt) - return; /* Nothing to do */ - currentTabInfo = tableInfo[tt]; + if (curTableType == tt) return; /* Nothing to do */ + + symTab = tableInfo[tt].symTab; + valTab = tableInfo[tt].valTab; + numEntry = tableInfo[tt].numEntry; + tableSize= tableInfo[tt].tableSize; curTableType = tt; } -void TABLEINFO_TYPE::destroy() -{ - delete [] symTab; // The symbol hashed label table - delete [] valTab; // And the value hashed label table -} + void destroySymTables(void) { selectTable(Label); - currentTabInfo.destroy(); + free(symTab); /* The symbol hashed label table */ + free(valTab); /* And the value hashed label table */ selectTable(Comment); - currentTabInfo.destroy(); + free(valTab); /* And the value hashed comment table */ } -/* Using the value, read the symbolic name */ -boolT readVal(std::ostringstream &symName, uint32_t symOff, Function * symProc) -{ - return false; // no symbolic names for now -} -/* Updates the type of the symbol in the symbol table. The size is updated - * if necessary (0 means no update necessary). */ -void SYMTAB::updateSymType (uint32_t symbol,const TypeContainer &tc) +/* Hash the symbolic name */ +word symHash(char *name, word *pre) { int i; - auto iter=findByLabel(symbol); - if(iter==end()) - return; - iter->type = tc.m_type; - if (tc.m_size != 0) - iter->size = tc.m_size; -} + word h = 0; + char ch; -/* Creates an entry in the global symbol table (symtab) if the variable - * is not there yet. If it is part of the symtab, the size of the variable - * is checked and updated if the old size was less than the new size (ie. - * the maximum size is always saved). */ -//TODO: SYMTAB::updateGlobSym should be renamed to insertOrUpdateSym -SYM * SYMTAB::updateGlobSym (uint32_t operand, int size, uint16_t duFlag,bool &inserted_new) -{ - /* Check for symbol in symbol table */ - auto iter = findByLabel(operand); - if(iter!=end()) + for (i=0; i < (int)strlen(name); i++) { - if(iter->sizesize = size; - inserted_new=false; - return &(*iter); + ch = name[i]; + h = (h << 2) ^ ch; + h += (ch >> 2) + (ch << 5); } - /* New symbol, not in symbol table */ - SYM v; - char buf[32]={}; - sprintf (buf, "var%05X", operand); - v.name = buf; - v.label = operand; - v.size = size; - v.type = TypeContainer::defaultTypeForSize(size); - if (duFlag == eDuVal::USE) /* must already have init value */ + *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 +valHash(dword symOff, PPROC 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 +enterSym(char *symName, dword symOff, PPROC symProc, boolT bSymToo) +{ + word h, pre, j; + + if ((numEntry / 9 * 10) >= tableSize) { - v.duVal.use =1; // USEVAL; - v.duVal.val =1; + /* 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 { - v.duVal.setFlags(duFlag); + /* 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); + } } - push_back(v); - inserted_new=true; - return (&back()); + + /* 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 == 0) /* 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 == 0) + { + /* 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); + } + } + } -//template<> class SymbolTableCommon; -//template<> class SymbolTableCommon; + +boolT +findSym(char *symName, word *pIndex) +{ + word h, j, pre; + + h = symHash(symName, &pre); + j = h; + do + { + if (symTab[j].pSymName == 0) + { + return FALSE; /* No entry at all */ + } + if (strcmp(symName, symTab[j].pSymName) == 0) + { + *pIndex = j; + return TRUE; /* Symbol found */ + } + j = symTab[j].nextOvf; /* Follow the chain */ + } + while (j != NIL); + return FALSE; /* End of chain */ +} + +/* Find symbol by value */ +boolT +findVal(dword symOff, PPROC symProc, word *pIndex) +{ + word h, j, pre; + + h = valHash(symOff, symProc, &pre); + j = h; + do + { + if (valTab[j].symProc == 0) + { + return FALSE; /* No entry at all */ + } + if ((valTab[j].symOff == symOff) + /*&& (valTab[j].symProc == symProc)*/) + { + *pIndex = j; + return TRUE; /* Symbol found */ + } + j = valTab[j].nextOvf; /* Follow the chain */ + } + while (j != NIL); + return FALSE; /* End of chain */ +} + +word +findBlankSym(char *symName) +{ + word h, j, pre; + + h = symHash(symName, &pre); + j = h; + do + { + if (symTab[j].pSymName == 0) + { + 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 +readSym(char *symName, dword *pSymOff, PPROC *pSymProc) +{ + word i; + + if (!findSym(symName, &i)) + { + return FALSE; + } + *pSymOff = symTab[i].symOff; + *pSymProc= symTab[i].symProc; + return TRUE; +} + +/* Using the value, read the symbolic name */ +boolT +readVal(char *symName, dword symOff, PPROC symProc) +{ + word i; + + if (!findVal(symOff, symProc, &i)) + { + return FALSE; + } + strcpy(symName, valTab[i].pSymName); + 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 +deleteSym(char *symName) +{ + word i, j, back; + dword symOff; + PPROC 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; + memcpy(&symTab[i], &symTab[j], sizeof(SYMTABLE)); + symTab[i].prevOvf = back; + } + /* And now mark the vacated record as empty */ + symTab[j].pSymName = 0; /* Rub out the name */ + + + /* Delete from value hashed table */ + if (!findVal(symOff, symProc, &i)) + { + 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; + 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 */ +} + + +void +deleteVal(dword symOff, PPROC symProc, boolT bSymToo) +{ + word i, j, back; + char *symName; + + /* Delete from value hashed table */ + if (!findVal(symOff, symProc, &i)) + { + 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, &i)) + { + printf("Could not delete non existant symbol name %s\n", symName); + 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; + memcpy(&symTab[i], &symTab[j], sizeof(SYMTABLE)); + symTab[i].prevOvf = back; + } + /* And now mark the vacated record as empty */ + symTab[j].pSymName = 0; /* Rub out the name */ + +} + +static void +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 = 0; + } + } +} + +/* 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; +} diff --git a/src/tests/comwrite.cpp b/src/tests/comwrite.cpp deleted file mode 100644 index 61822c2..0000000 --- a/src/tests/comwrite.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "dcc.h" -#include -#include - -TEST(CowriteTest, HandlesZeroInput) { - EXPECT_EQ(1, 1); -} - -int main(int argc, char** argv) { - // The following line must be executed to initialize Google Mock - // (and Google Test) before running the tests. - ::testing::InitGoogleMock(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/src/udm.cpp b/src/udm.cpp index de5c105..cc3b2b5 100644 --- a/src/udm.cpp +++ b/src/udm.cpp @@ -4,104 +4,154 @@ * that just plays with abstract cfg's and intervals and such like. * (C) Cristina Cifuentes ****************************************************************************/ -#include -#include -#include -#include "dcc.h" -#include "disassem.h" -#include "project.h" -extern Project g_proj; -static void displayCFG(Function * pProc); -static void displayDfs(BB * pBB); +#include "dcc.h" +#include + +static void displayCFG(PPROC pProc); +static void displayDfs(PBB pBB); /**************************************************************************** * udm ****************************************************************************/ -void Function::buildCFG(Disassembler &ds) -{ - if(flg & PROC_ISLIB) - return; // Ignore library functions - createCFG(); - if (option.VeryVerbose) - displayCFG(); - - compressCFG(); // Remove redundancies and add in-edge information - - if (option.asm2) - { - ds.disassem(this); // Print 2nd pass assembler listing - } - - /* Idiom analysis and propagation of long type */ - lowLevelAnalysis(); - - /* Generate HIGH_LEVEL icodes whenever possible */ - highLevelGen(); -} -void Function::controlFlowAnalysis() -{ - if (flg & PROC_ISLIB) - return; /* Ignore library functions */ - derSeq *derivedG=0; - - /* Make cfg reducible and build derived sequences */ - derivedG=checkReducibility(); - - if (option.VeryVerbose) - derivedG->display(); - - /* Structure the graph */ - structure(derivedG); - - /* Check for compound conditions */ - compoundCond (); - - if (option.verbose) - { - printf("\nDepth first traversal - Proc %s\n", name.c_str()); - m_cfg.front()->displayDfs(); - } - - /* Free storage occupied by this procedure */ - freeDerivedSeq(*derivedG); - -} void udm(void) -{ +{ PPROC pProc; + derSeq *derivedG; - /* Build the control flow graph, find idioms, and convert low-level - * icodes to high-level ones */ - Disassembler ds(2); - for (auto iter = g_proj.pProcList.rbegin(); iter!=g_proj.pProcList.rend(); ++iter) - { - iter->buildCFG(ds); - } + /* Build the control flow graph, find idioms, and convert low-level + * icodes to high-level ones */ + for (pProc = pLastProc; pProc; pProc = pProc->prev) + { + if (pProc->flg & PROC_ISLIB) + continue; /* Ignore library functions */ + + /* Create the basic control flow graph */ + pProc->cfg = createCFG(pProc); + if (option.VeryVerbose) + displayCFG(pProc); + + /* Remove redundancies and add in-edge information */ + compressCFG(pProc); + + /* Print 2nd pass assembler listing */ + if (option.asm2) + disassem(2, pProc); + + /* Idiom analysis and propagation of long type */ + lowLevelAnalysis (pProc); + + /* Generate HIGH_LEVEL icodes whenever possible */ + highLevelGen (pProc); + } /* Data flow analysis - eliminate condition codes, extraneous registers - * and intermediate instructions. Find expressions by forward - * substitution algorithm */ - std::bitset<32> live_regs; - g_proj.pProcList.front().dataFlow (live_regs); + * and intermediate instructions. Find expressions by forward + * substitution algorithm */ + dataFlow (pProcList, 0); - /* Control flow analysis - structuring algorithm */ - for (auto iter = g_proj.pProcList.rbegin(); iter!=g_proj.pProcList.rend(); ++iter) - { - iter->controlFlowAnalysis(); + /* Control flow analysis - structuring algorithm */ + for (pProc = pLastProc; pProc; pProc = pProc->prev) + { + + if (pProc->flg & PROC_ISLIB) + continue; /* Ignore library functions */ + + /* Make cfg reducible and build derived sequences */ + checkReducibility(pProc, &derivedG); + + if (option.VeryVerbose) + displayDerivedSeq(derivedG); + + /* Structure the graph */ + structure(pProc, derivedG); + + /* Check for compound conditions */ + compoundCond (pProc); + + if (option.verbose) { + printf("\nDepth first traversal - Proc %s\n", pProc->name); + displayDfs(pProc->cfg); + } + + /* Free storage occupied by this procedure */ + freeDerivedSeq(derivedG); } } + +static char *nodeType[] = {"branch", "if", "case", "fall", "return", "call", + "loop", "repeat", "interval", "cycleHead", + "caseHead", "terminate", + "nowhere" }; + +static char *loopType[] = {"noLoop", "while", "repeat", "loop", "for"}; + + /**************************************************************************** * displayCFG - Displays the Basic Block list ***************************************************************************/ -void Function::displayCFG() +static void displayCFG(PPROC pProc) { - printf("\nBasic Block List - Proc %s", name.c_str()); - for (BB *pBB : m_cfg) - { - pBB->display(); + Int i; + PBB pBB; + + printf("\nBasic Block List - Proc %s", pProc->name); + + for (pBB = pProc->cfg; pBB; pBB = pBB->next) { + printf("\nnode type = %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 + ****************************************************************************/ +static void displayDfs(PBB pBB) +{ + Int i; + + if (! pBB) + return; + pBB->traversed = DFS_DISP; + + printf("node type = %s, ", nodeType[pBB->nodeType]); + printf("start = %ld, length = %ld, #in-edges = %ld, #out-edges = %ld\n", + pBB->start, pBB->length, pBB->numInEdges, pBB->numOutEdges); + printf("dfsFirst = %ld, dfsLast = %ld, immed dom = %ld\n", + pBB->dfsFirstNum, pBB->dfsLastNum, + pBB->immedDom == MAX ? -1 : pBB->immedDom); + printf("loopType = %s, loopHead = %ld, latchNode = %ld, follow = %ld\n", + loopType[pBB->loopType], + pBB->loopHead == MAX ? -1 : pBB->loopHead, + pBB->latchNode == MAX ? -1 : pBB->latchNode, + pBB->loopFollow == MAX ? -1 : pBB->loopFollow); + printf ("ifFollow = %ld, caseHead = %ld, caseTail = %ld\n", + pBB->ifFollow == MAX ? -1 : pBB->ifFollow, + pBB->caseHead == MAX ? -1 : pBB->caseHead, + pBB->caseTail == MAX ? -1 : pBB->caseTail); + + if (pBB->nodeType == INTERVAL_NODE) + printf("corresponding interval = %ld\n", pBB->correspInt->numInt); + else for (i = 0; i < pBB->numInEdges; i++) + printf (" inEdge[%ld] = %ld\n", i, pBB->inEdges[i]->start); + + /* Display out edges information */ + for (i = 0; i < pBB->numOutEdges; i++) + if (pBB->nodeType == INTERVAL_NODE) + printf(" outEdge[%ld] = %ld\n", i, + pBB->edges[i].BBptr->correspInt->numInt); + else + printf(" outEdge[%ld] = %ld\n", i, pBB->edges[i].BBptr->start); + printf("----\n"); + + /* Recursive call on successors of current node */ + for (i = 0; i < pBB->numOutEdges; i++) + if (pBB->edges[i].BBptr->traversed != DFS_DISP) + displayDfs(pBB->edges[i].BBptr); +}