Only 2 differences with original release: add return type to main int disassem.cpp popPosStack() add cast to intptr_t
369 lines
10 KiB
C++
369 lines
10 KiB
C++
/*****************************************************************************
|
|
* I-code related definitions
|
|
* (C) Cristina Cifuentes
|
|
****************************************************************************/
|
|
|
|
|
|
/* 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
|
|
|
|
/* Types of icodes */
|
|
typedef enum {
|
|
NOT_SCANNED = 0, /* not even scanned yet */
|
|
LOW_LEVEL, /* low-level icode */
|
|
HIGH_LEVEL /* high-level icode */
|
|
} icodeType;
|
|
|
|
|
|
/* 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 */
|
|
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 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;
|
|
|
|
|
|
/* LOW_LEVEL icode operand record */
|
|
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
|
|
{
|
|
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
|
|
{
|
|
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;
|
|
|
|
|
|
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
|
|
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;
|
|
|
|
// This is the icode array object.
|
|
// The bulk of this could well be done with a class library
|
|
class CIcodeRec
|
|
{
|
|
public:
|
|
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 */
|
|
|
|
};
|