This commit is contained in:
Artur K 2012-07-20 18:18:25 +02:00
parent f6118dc0c4
commit 0209b7ceb2
28 changed files with 1028 additions and 768 deletions

View File

@ -407,7 +407,21 @@ unsigned int Ia32_Decoder::ia32_insn_implicit_ops( unsigned int impl_idx ) {
if (!op) { if (!op) {
op = m_decoded->x86_operand_new(); op = m_decoded->x86_operand_new();
/* all implicit operands are registers */ /* all implicit operands are registers */
handle_impl_reg( op, list->operand ); if(m_decoded->addr_size==2)
{
if(list->operand==REG_EIP_INDEX)
handle_impl_reg( op, REG_IP_INDEX );
else if(list->operand<REG_WORD_OFFSET)
{
handle_impl_reg( op, (list->operand-REG_DWORD_OFFSET)+REG_WORD_OFFSET);
assert((list->operand-REG_DWORD_OFFSET)<REG_WORD_OFFSET-REG_DWORD_OFFSET);
}
else
handle_impl_reg( op, list->operand);
}
else
handle_impl_reg( op, list->operand );
/* decrement the 'explicit count' incremented by default in /* decrement the 'explicit count' incremented by default in
* x86_operand_new */ * x86_operand_new */
m_decoded->explicit_count = m_decoded->explicit_count -1; m_decoded->explicit_count = m_decoded->explicit_count -1;

View File

@ -107,13 +107,13 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
/* No MODRM : note these set operand type explicitly */ /* No MODRM : note these set operand type explicitly */
case ADDRMETH_A: /* No modR/M -- direct addr */ case ADDRMETH_A: /* No modR/M -- direct addr */
op->type = op_absolute; op->type = op_absolute;
//according to Intel Manuals, offset goes first
/* segment:offset address used in far calls */ /* segment:offset address used in far calls */
if ( m_decoded->addr_size == 4 ) { if ( m_decoded->addr_size == 4 ) {
x86_imm_sized( buf, buf_len, &op->data.absolute.offset.off32, 4 ); x86_imm_sized( buf, buf_len, &op->data.absolute.offset.off32, 4 );
size = 4; size = 4;
} else { } else {
x86_imm_sized( buf, buf_len,&op->data.absolute.offset.off16, 2 ); x86_imm_sized( buf, buf_len, &op->data.absolute.offset.off16, 2 );
size = 2; size = 2;
} }
x86_imm_sized( buf+size, buf_len-size, &op->data.absolute.segment, 2 ); x86_imm_sized( buf+size, buf_len-size, &op->data.absolute.segment, 2 );
@ -134,7 +134,7 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
size = op_size; size = op_size;
break; break;
case ADDRMETH_J: /* Rel offset to add to IP [jmp] */ case ADDRMETH_J: /* Rel offset to add to IP [jmp] */
/* this fills op->data.near_offset or /* this fills op->data.near_offset or
op->data.far_offset depending on the size of op->data.far_offset depending on the size of
the operand */ the operand */
op->flags.op_signed = true; op->flags.op_signed = true;
@ -146,15 +146,15 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
size = x86_imm_signsized(buf, buf_len, &op->data.relative_near, 1); size = x86_imm_signsized(buf, buf_len, &op->data.relative_near, 1);
break; break;
case 2: case 2:
/* far offset...is this truly signed? */
op->type = op_relative_far; op->type = op_relative_far;
int16_t offset_val; int16_t offset_val; // easier upcast to int32_t
size = x86_imm_signsized(buf, buf_len,&offset_val, 2); size = x86_imm_signsized(buf, buf_len, &offset_val, 2 );
op->data.relative_far=offset_val; op->data.relative_far=offset_val;
break; break;
default: default:
assert(false); assert(false);
size=0; size=0;
} }
break; break;
case ADDRMETH_O: /* No ModR/M; op is word/dword offset */ case ADDRMETH_O: /* No ModR/M; op is word/dword offset */
@ -181,7 +181,7 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
op->flags.op_pointer = true; op->flags.op_pointer = true;
op->flags.op_string = true; op->flags.op_string = true;
ia32_handle_register( &op->data.expression.base, ia32_handle_register( &op->data.expression.base,
REG_DWORD_OFFSET + 6 ); gen_regs + 6 );
break; break;
case ADDRMETH_Y: /* Memory addressed by ES:DI [string] */ case ADDRMETH_Y: /* Memory addressed by ES:DI [string] */
op->type = op_expression; op->type = op_expression;
@ -190,7 +190,7 @@ size_t Ia32_Decoder::decode_operand_value( unsigned char *buf, size_t buf_len,
op->flags.op_pointer = true; op->flags.op_pointer = true;
op->flags.op_string = true; op->flags.op_string = true;
ia32_handle_register( &op->data.expression.base, ia32_handle_register( &op->data.expression.base,
REG_DWORD_OFFSET + 7 ); gen_regs + 7 );
break; break;
case ADDRMETH_RR: /* Gen Register hard-coded in opcode */ case ADDRMETH_RR: /* Gen Register hard-coded in opcode */
op->type = op_register; op->type = op_register;
@ -260,8 +260,8 @@ size_t Ia32_Decoder::decode_operand_size( unsigned int op_type, x86_op_t *op ) {
break; break;
case OPTYPE_p: /* 32/48-bit ptr [op size attr] */ case OPTYPE_p: /* 32/48-bit ptr [op size attr] */
/* technically these flags are not accurate: the /* technically these flags are not accurate: the
* value s a 16:16 pointer or a 16:32 pointer, where * value s a 16:16 pointer or a 16:32 pointer, where
* the first '16' is a segment */ * the first '16' is a segment */
size = (m_decoded->addr_size == 4) ? 6 : 4; size = (m_decoded->addr_size == 4) ? 6 : 4;
op->datatype = (size == 6) ? op_descr32 : op_descr16; op->datatype = (size == 6) ? op_descr32 : op_descr16;
break; break;

View File

@ -8,15 +8,16 @@
#include <cstdlib> #include <cstdlib>
#include <cassert> #include <cassert>
#include <stdint.h> #include <stdint.h>
/* 'NEW" types /* 'NEW" types
* __________________________________________________________________________*/ * __________________________________________________________________________*/
#ifndef LIBDISASM_QWORD_H /* do not interfere with qword.h */ #ifndef LIBDISASM_QWORD_H /* do not interfere with qword.h */
#define LIBDISASM_QWORD_H #define LIBDISASM_QWORD_H
#ifdef _MSC_VER #ifdef _MSC_VER
typedef __int64 qword_t; typedef __int64 qword_t;
#else #else
typedef int64_t qword_t; typedef int64_t qword_t;
#endif #endif
#endif #endif
#include <sys/types.h> #include <sys/types.h>
@ -36,7 +37,7 @@ typedef int64_t qword_t;
* this allows the report to recover from errors, or just log them. * this allows the report to recover from errors, or just log them.
*/ */
enum x86_report_codes { enum x86_report_codes {
report_disasm_bounds, /* RVA OUT OF BOUNDS : The disassembler could report_disasm_bounds, /* RVA OUT OF BOUNDS : The disassembler could
not disassemble the supplied RVA as it is not disassemble the supplied RVA as it is
out of the range of the buffer. The out of the range of the buffer. The
application should store the address and application should store the address and
@ -44,21 +45,21 @@ enum x86_report_codes {
binary it is in, then disassemble the binary it is in, then disassemble the
address from the bytes in that section. address from the bytes in that section.
data: uint32_t rva */ data: uint32_t rva */
report_insn_bounds, /* INSTRUCTION OUT OF BOUNDS: The disassembler report_insn_bounds, /* INSTRUCTION OUT OF BOUNDS: The disassembler
could not disassemble the instruction as could not disassemble the instruction as
the instruction would require bytes beyond the instruction would require bytes beyond
the end of the current buffer. This usually the end of the current buffer. This usually
indicated garbage bytes at the end of a indicated garbage bytes at the end of a
buffer, or an incorrectly-sized buffer. buffer, or an incorrectly-sized buffer.
data: uint32_t rva */ data: uint32_t rva */
report_invalid_insn, /* INVALID INSTRUCTION: The disassembler could report_invalid_insn, /* INVALID INSTRUCTION: The disassembler could
not disassemble the instruction as it has an not disassemble the instruction as it has an
invalid combination of opcodes and operands. invalid combination of opcodes and operands.
This will stop automated disassembly; the This will stop automated disassembly; the
application can restart the disassembly application can restart the disassembly
after the invalid instruction. after the invalid instruction.
data: uint32_t rva */ data: uint32_t rva */
report_unknown report_unknown
}; };
/* Disassembly formats: /* Disassembly formats:
* AT&T is standard AS/GAS-style: "mnemonic\tsrc, dest, imm" * AT&T is standard AS/GAS-style: "mnemonic\tsrc, dest, imm"
@ -68,12 +69,12 @@ enum x86_report_codes {
* Raw is addr|offset|size|bytes|prefix... see libdisasm_formats.7 * Raw is addr|offset|size|bytes|prefix... see libdisasm_formats.7
*/ */
enum x86_asm_format { enum x86_asm_format {
unknown_syntax = 0, /* never use! */ unknown_syntax = 0, /* never use! */
native_syntax, /* header: 35 bytes */ native_syntax, /* header: 35 bytes */
intel_syntax, /* header: 23 bytes */ intel_syntax, /* header: 23 bytes */
att_syntax, /* header: 23 bytes */ att_syntax, /* header: 23 bytes */
xml_syntax, /* header: 679 bytes */ xml_syntax, /* header: 679 bytes */
raw_syntax /* header: 172 bytes */ raw_syntax /* header: 172 bytes */
}; };
/* 'arg' is optional arbitrary data provided by the code passing the /* 'arg' is optional arbitrary data provided by the code passing the
@ -86,10 +87,10 @@ typedef void (*DISASM_REPORTER)( enum x86_report_codes code,
/* ========================================= Libdisasm Management Routines */ /* ========================================= Libdisasm Management Routines */
enum x86_options { /* these can be ORed together */ enum x86_options { /* these can be ORed together */
opt_none= 0, opt_none= 0,
opt_ignore_nulls=1, /* ignore sequences of > 4 NULL bytes */ opt_ignore_nulls=1, /* ignore sequences of > 4 NULL bytes */
opt_16_bit=2, /* 16-bit/DOS disassembly */ opt_16_bit=2, /* 16-bit/DOS disassembly */
opt_att_mnemonics=4 /* use AT&T syntax names for alternate opcode mnemonics */ opt_att_mnemonics=4 /* use AT&T syntax names for alternate opcode mnemonics */
}; };
/* ========================================= Instruction Representation */ /* ========================================= Instruction Representation */
@ -110,35 +111,35 @@ enum x86_options { /* these can be ORed together */
#define MAX_INSN_XML_STRING 4096 /* 2 * 8 * MAX_OP_XML_STRING */ #define MAX_INSN_XML_STRING 4096 /* 2 * 8 * MAX_OP_XML_STRING */
enum x86_reg_type { /* NOTE: these may be ORed together */ enum x86_reg_type { /* NOTE: these may be ORed together */
reg_undef = 0x00000, // used only in ia32_reg_table initializater reg_undef = 0x00000, // used only in ia32_reg_table initializater
reg_gen = 0x00001, /* general purpose */ reg_gen = 0x00001, /* general purpose */
reg_in = 0x00002, /* incoming args, ala RISC */ reg_in = 0x00002, /* incoming args, ala RISC */
reg_out = 0x00004, /* args to calls, ala RISC */ reg_out = 0x00004, /* args to calls, ala RISC */
reg_local = 0x00008, /* local vars, ala RISC */ reg_local = 0x00008, /* local vars, ala RISC */
reg_fpu = 0x00010, /* FPU data register */ reg_fpu = 0x00010, /* FPU data register */
reg_seg = 0x00020, /* segment register */ reg_seg = 0x00020, /* segment register */
reg_simd = 0x00040, /* SIMD/MMX reg */ reg_simd = 0x00040, /* SIMD/MMX reg */
reg_sys = 0x00080, /* restricted/system register */ reg_sys = 0x00080, /* restricted/system register */
reg_sp = 0x00100, /* stack pointer */ reg_sp = 0x00100, /* stack pointer */
reg_fp = 0x00200, /* frame pointer */ reg_fp = 0x00200, /* frame pointer */
reg_pc = 0x00400, /* program counter */ reg_pc = 0x00400, /* program counter */
reg_retaddr = 0x00800, /* return addr for func */ reg_retaddr = 0x00800, /* return addr for func */
reg_cond = 0x01000, /* condition code / flags */ reg_cond = 0x01000, /* condition code / flags */
reg_zero = 0x02000, /* zero register, ala RISC */ reg_zero = 0x02000, /* zero register, ala RISC */
reg_ret = 0x04000, /* return value */ reg_ret = 0x04000, /* return value */
reg_src = 0x10000, /* array/rep source */ reg_src = 0x10000, /* array/rep source */
reg_dest = 0x20000, /* array/rep destination */ reg_dest = 0x20000, /* array/rep destination */
reg_count = 0x40000 /* array/rep/loop counter */ reg_count = 0x40000 /* array/rep/loop counter */
}; };
/* x86_reg_t : an X86 CPU register */ /* x86_reg_t : an X86 CPU register */
struct x86_reg_t { struct x86_reg_t {
char name[MAX_REGNAME]; char name[MAX_REGNAME];
enum x86_reg_type type; /* what register is used for */ enum x86_reg_type type; /* what register is used for */
unsigned int size; /* size of register in bytes */ unsigned int size; /* size of register in bytes */
unsigned int id; /* register ID #, for quick compares */ unsigned int id; /* register ID #, for quick compares */
unsigned int alias; /* ID of reg this is an alias for */ unsigned int alias; /* ID of reg this is an alias for */
unsigned int shift; /* amount to shift aliased reg by */ unsigned int shift; /* amount to shift aliased reg by */
x86_reg_t * aliased_reg( ) { x86_reg_t * aliased_reg( ) {
x86_reg_t * reg = (x86_reg_t * )calloc( sizeof(x86_reg_t), 1 ); x86_reg_t * reg = (x86_reg_t * )calloc( sizeof(x86_reg_t), 1 );
reg->x86_reg_from_id( id ); reg->x86_reg_from_id( id );
@ -149,92 +150,92 @@ struct x86_reg_t {
/* x86_ea_t : an X86 effective address (address expression) */ /* x86_ea_t : an X86 effective address (address expression) */
typedef struct { typedef struct {
unsigned int scale; /* scale factor */ unsigned int scale; /* scale factor */
x86_reg_t index, base; /* index, base registers */ x86_reg_t index, base; /* index, base registers */
int32_t disp; /* displacement */ int32_t disp; /* displacement */
char disp_sign; /* is negative? 1/0 */ char disp_sign; /* is negative? 1/0 */
char disp_size; /* 0, 1, 2, 4 */ char disp_size; /* 0, 1, 2, 4 */
} x86_ea_t; } x86_ea_t;
/* x86_absolute_t : an X86 segment:offset address (descriptor) */ /* x86_absolute_t : an X86 segment:offset address (descriptor) */
typedef struct { typedef struct {
unsigned short segment; /* loaded directly into CS */ unsigned short segment; /* loaded directly into CS */
union { union {
unsigned short off16; /* loaded directly into IP */ unsigned short off16; /* loaded directly into IP */
uint32_t off32; /* loaded directly into EIP */ uint32_t off32; /* loaded directly into EIP */
} offset; } offset;
} x86_absolute_t; } x86_absolute_t;
enum x86_op_type { /* mutually exclusive */ enum x86_op_type { /* mutually exclusive */
op_unused = 0, /* empty/unused operand: should never occur */ op_unused = 0, /* empty/unused operand: should never occur */
op_register = 1, /* CPU register */ op_register = 1, /* CPU register */
op_immediate = 2, /* Immediate Value */ op_immediate = 2, /* Immediate Value */
op_relative_near = 3, /* Relative offset from IP */ op_relative_near = 3, /* Relative offset from IP */
op_relative_far = 4, /* Relative offset from IP */ op_relative_far = 4, /* Relative offset from IP */
op_absolute = 5, /* Absolute address (ptr16:32) */ op_absolute = 5, /* Absolute address (ptr16:32) */
op_expression = 6, /* Address expression (scale/index/base/disp) */ op_expression = 6, /* Address expression (scale/index/base/disp) */
op_offset = 7, /* Offset from start of segment (m32) */ op_offset = 7, /* Offset from start of segment (m32) */
op_unknown op_unknown
}; };
#define x86_optype_is_address( optype ) \ #define x86_optype_is_address( optype ) \
( optype == op_absolute || optype == op_offset ) ( optype == op_absolute || optype == op_offset )
#define x86_optype_is_relative( optype ) \ #define x86_optype_is_relative( optype ) \
( optype == op_relative_near || optype == op_relative_far ) ( optype == op_relative_near || optype == op_relative_far )
#define x86_optype_is_memory( optype ) \ #define x86_optype_is_memory( optype ) \
( optype > op_immediate && optype < op_unknown ) ( optype > op_immediate && optype < op_unknown )
enum x86_op_datatype { /* these use Intel's lame terminology */ enum x86_op_datatype { /* these use Intel's lame terminology */
op_byte = 1, /* 1 byte integer */ op_byte = 1, /* 1 byte integer */
op_word = 2, /* 2 byte integer */ op_word = 2, /* 2 byte integer */
op_dword = 3, /* 4 byte integer */ op_dword = 3, /* 4 byte integer */
op_qword = 4, /* 8 byte integer */ op_qword = 4, /* 8 byte integer */
op_dqword = 5, /* 16 byte integer */ op_dqword = 5, /* 16 byte integer */
op_sreal = 6, /* 4 byte real (single real) */ op_sreal = 6, /* 4 byte real (single real) */
op_dreal = 7, /* 8 byte real (double real) */ op_dreal = 7, /* 8 byte real (double real) */
op_extreal = 8, /* 10 byte real (extended real) */ op_extreal = 8, /* 10 byte real (extended real) */
op_bcd = 9, /* 10 byte binary-coded decimal */ op_bcd = 9, /* 10 byte binary-coded decimal */
op_ssimd = 10, /* 16 byte : 4 packed single FP (SIMD, MMX) */ op_ssimd = 10, /* 16 byte : 4 packed single FP (SIMD, MMX) */
op_dsimd = 11, /* 16 byte : 2 packed double FP (SIMD, MMX) */ op_dsimd = 11, /* 16 byte : 2 packed double FP (SIMD, MMX) */
op_sssimd = 12, /* 4 byte : scalar single FP (SIMD, MMX) */ op_sssimd = 12, /* 4 byte : scalar single FP (SIMD, MMX) */
op_sdsimd = 13, /* 8 byte : scalar double FP (SIMD, MMX) */ op_sdsimd = 13, /* 8 byte : scalar double FP (SIMD, MMX) */
op_descr32 = 14, /* 6 byte Intel descriptor 2:4 */ op_descr32 = 14, /* 6 byte Intel descriptor 2:4 */
op_descr16 = 15, /* 4 byte Intel descriptor 2:2 */ op_descr16 = 15, /* 4 byte Intel descriptor 2:2 */
op_pdescr32 = 16, /* 6 byte Intel pseudo-descriptor 32:16 */ op_pdescr32 = 16, /* 6 byte Intel pseudo-descriptor 32:16 */
op_pdescr16 = 17, /* 6 byte Intel pseudo-descriptor 8:24:16 */ op_pdescr16 = 17, /* 6 byte Intel pseudo-descriptor 8:24:16 */
op_bounds16 = 18, /* signed 16:16 lower:upper bounds */ op_bounds16 = 18, /* signed 16:16 lower:upper bounds */
op_bounds32 = 19, /* signed 32:32 lower:upper bounds */ op_bounds32 = 19, /* signed 32:32 lower:upper bounds */
op_fpuenv16 = 20, /* 14 byte FPU control/environment data */ op_fpuenv16 = 20, /* 14 byte FPU control/environment data */
op_fpuenv32 = 21, /* 28 byte FPU control/environment data */ op_fpuenv32 = 21, /* 28 byte FPU control/environment data */
op_fpustate16 = 22, /* 94 byte FPU state (env & reg stack) */ op_fpustate16 = 22, /* 94 byte FPU state (env & reg stack) */
op_fpustate32 = 23, /* 108 byte FPU state (env & reg stack) */ op_fpustate32 = 23, /* 108 byte FPU state (env & reg stack) */
op_fpregset = 24, /* 512 bytes: register set */ op_fpregset = 24, /* 512 bytes: register set */
op_fpreg = 25, /* FPU register */ op_fpreg = 25, /* FPU register */
op_none = 0xFF /* operand without a datatype (INVLPG) */ op_none = 0xFF /* operand without a datatype (INVLPG) */
}; };
enum x86_op_access { /* ORed together */ enum x86_op_access { /* ORed together */
op_read = 1, op_read = 1,
op_write = 2, op_write = 2,
op_execute = 4 op_execute = 4
}; };
struct x86_op_flags { /* ORed together, but segs are mutually exclusive */ struct x86_op_flags { /* ORed together, but segs are mutually exclusive */
union { union {
unsigned int op_signed:1, /* signed integer */ unsigned int op_signed:1, /* signed integer */
op_string:1,// = 2, /* possible string or array */ op_string:1,// = 2, /* possible string or array */
op_constant:1,// = 4, /* symbolic constant */ op_constant:1,// = 4, /* symbolic constant */
op_pointer:1,// = 8, /* operand points to a memory address */ op_pointer:1,// = 8, /* operand points to a memory address */
op_sysref:1,// = 0x010, /* operand is a syscall number */ op_sysref:1,// = 0x010, /* operand is a syscall number */
op_implied:1,// = 0x020, /* operand is implicit in the insn */ op_implied:1,// = 0x020, /* operand is implicit in the insn */
op_hardcode:1,// = 0x40, /* operand is hardcoded in insn definition */ op_hardcode:1,// = 0x40, /* operand is hardcoded in insn definition */
/* NOTE: an 'implied' operand is one which can be considered a side /* NOTE: an 'implied' operand is one which can be considered a side
* effect of the insn, e.g. %esp being modified by PUSH or POP. A * effect of the insn, e.g. %esp being modified by PUSH or POP. A
* 'hard-coded' operand is one which is specified in the instruction * 'hard-coded' operand is one which is specified in the instruction
* definition, e.g. %es:%edi in MOVSB or 1 in ROL Eb, 1. The difference * definition, e.g. %es:%edi in MOVSB or 1 in ROL Eb, 1. The difference
* is that hard-coded operands are printed by disassemblers and are * is that hard-coded operands are printed by disassemblers and are
* required to re-assemble, while implicit operands are invisible. */ * required to re-assemble, while implicit operands are invisible. */
op_seg : 3; op_seg : 3;
unsigned int whole; unsigned int whole;
}; };
enum { enum {
@ -250,43 +251,43 @@ struct x86_op_flags { /* ORed together, but segs are mutually exclusive */
/* x86_op_t : an X86 instruction operand */ /* x86_op_t : an X86 instruction operand */
struct x86_op_t{ struct x86_op_t{
friend struct x86_insn_t; friend struct x86_insn_t;
enum x86_op_type type; /* operand type */ enum x86_op_type type; /* operand type */
enum x86_op_datatype datatype; /* operand size */ enum x86_op_datatype datatype; /* operand size */
enum x86_op_access access; /* operand access [RWX] */ enum x86_op_access access; /* operand access [RWX] */
x86_op_flags flags; /* misc flags */ x86_op_flags flags; /* misc flags */
union { union {
/* sizeof will have to work on these union members! */ /* sizeof will have to work on these union members! */
/* immediate values */ /* immediate values */
char sbyte; char sbyte;
short sword; short sword;
int32_t sdword; int32_t sdword;
qword_t sqword; qword_t sqword;
unsigned char byte; unsigned char byte;
unsigned short word; unsigned short word;
uint32_t dword; uint32_t dword;
qword_t qword; qword_t qword;
float sreal; float sreal;
double dreal; double dreal;
/* misc large/non-native types */ /* misc large/non-native types */
unsigned char extreal[10]; unsigned char extreal[10];
unsigned char bcd[10]; unsigned char bcd[10];
qword_t dqword[2]; qword_t dqword[2];
unsigned char simd[16]; unsigned char simd[16];
unsigned char fpuenv[28]; unsigned char fpuenv[28];
/* offset from segment */ /* offset from segment */
uint32_t offset; uint32_t offset;
/* ID of CPU register */ /* ID of CPU register */
x86_reg_t reg; x86_reg_t reg;
/* offsets from current insn */ /* offsets from current insn */
char relative_near; char relative_near;
int32_t relative_far; int32_t relative_far;
/* segment:offset */ /* segment:offset */
x86_absolute_t absolute; x86_absolute_t absolute;
/* effective address [expression] */ /* effective address [expression] */
x86_ea_t expression; x86_ea_t expression;
} data; } data;
/* this is needed to make formatting operands more sane */ /* this is needed to make formatting operands more sane */
void * insn; /* pointer to x86_insn_t owning operand */ void * insn; /* pointer to x86_insn_t owning operand */
size_t size() size_t size()
{ {
return operand_size(); return operand_size();
@ -304,25 +305,23 @@ struct x86_op_t{
int32_t getAddress() int32_t getAddress()
{ {
assert(is_address()||is_relative()); assert(is_address()||is_relative());
switch(type) switch ( type ) {
{ case op_relative_near:
return (int32_t) data.relative_near;
case op_absolute: case op_absolute:
{
if(datatype==op_descr16) if(datatype==op_descr16)
return (int32_t(data.absolute.segment)<<4) + data.absolute.offset.off16; return int32_t((data.absolute.segment)<<4) + data.absolute.offset.off16;
else else
return (int32_t(data.absolute.segment)<<4) + data.absolute.offset.off32; return int32_t((data.absolute.segment)<<4) + data.absolute.offset.off32;
}
case op_offset: case op_offset:
return data.offset; return data.offset;
case op_relative_near:
return data.relative_near;
case op_relative_far: case op_relative_far:
return data.relative_far; return (int32_t) data.relative_far;
default: default:
assert(false); assert(false);
return ~0; break;
} }
return ~0;
} }
char * format( enum x86_asm_format format ); char * format( enum x86_asm_format format );
x86_op_t * copy() x86_op_t * copy()
@ -342,119 +341,119 @@ private:
* list in an insn. Users wishing to add operands to this list, e.g. to add * list in an insn. Users wishing to add operands to this list, e.g. to add
* implicit operands, should use x86_operand_new in x86_operand_list.h */ * implicit operands, should use x86_operand_new in x86_operand_list.h */
struct x86_oplist_t { struct x86_oplist_t {
x86_op_t op; x86_op_t op;
struct x86_oplist_t *next; struct x86_oplist_t *next;
}; };
enum x86_insn_type { enum x86_insn_type {
insn_invalid = 0, /* invalid instruction */ insn_invalid = 0, /* invalid instruction */
/* insn_controlflow */ /* insn_controlflow */
insn_jmp = 0x1001, insn_jmp = 0x1001,
insn_jcc = 0x1002, insn_jcc = 0x1002,
insn_call = 0x1003, insn_call = 0x1003,
insn_callcc = 0x1004, insn_callcc = 0x1004,
insn_return = 0x1005, insn_return = 0x1005,
/* insn_arithmetic */ /* insn_arithmetic */
insn_add = 0x2001, insn_add = 0x2001,
insn_sub = 0x2002, insn_sub = 0x2002,
insn_mul = 0x2003, insn_mul = 0x2003,
insn_div = 0x2004, insn_div = 0x2004,
insn_inc = 0x2005, insn_inc = 0x2005,
insn_dec = 0x2006, insn_dec = 0x2006,
insn_shl = 0x2007, insn_shl = 0x2007,
insn_shr = 0x2008, insn_shr = 0x2008,
insn_rol = 0x2009, insn_rol = 0x2009,
insn_ror = 0x200A, insn_ror = 0x200A,
/* insn_logic */ /* insn_logic */
insn_and = 0x3001, insn_and = 0x3001,
insn_or = 0x3002, insn_or = 0x3002,
insn_xor = 0x3003, insn_xor = 0x3003,
insn_not = 0x3004, insn_not = 0x3004,
insn_neg = 0x3005, insn_neg = 0x3005,
/* insn_stack */ /* insn_stack */
insn_push = 0x4001, insn_push = 0x4001,
insn_pop = 0x4002, insn_pop = 0x4002,
insn_pushregs = 0x4003, insn_pushregs = 0x4003,
insn_popregs = 0x4004, insn_popregs = 0x4004,
insn_pushflags = 0x4005, insn_pushflags = 0x4005,
insn_popflags = 0x4006, insn_popflags = 0x4006,
insn_enter = 0x4007, insn_enter = 0x4007,
insn_leave = 0x4008, insn_leave = 0x4008,
/* insn_comparison */ /* insn_comparison */
insn_test = 0x5001, insn_test = 0x5001,
insn_cmp = 0x5002, insn_cmp = 0x5002,
/* insn_move */ /* insn_move */
insn_mov = 0x6001, /* move */ insn_mov = 0x6001, /* move */
insn_movcc = 0x6002, /* conditional move */ insn_movcc = 0x6002, /* conditional move */
insn_xchg = 0x6003, /* exchange */ insn_xchg = 0x6003, /* exchange */
insn_xchgcc = 0x6004, /* conditional exchange */ insn_xchgcc = 0x6004, /* conditional exchange */
/* insn_string */ /* insn_string */
insn_strcmp = 0x7001, insn_strcmp = 0x7001,
insn_strload = 0x7002, insn_strload = 0x7002,
insn_strmov = 0x7003, insn_strmov = 0x7003,
insn_strstore = 0x7004, insn_strstore = 0x7004,
insn_translate = 0x7005, /* xlat */ insn_translate = 0x7005, /* xlat */
/* insn_bit_manip */ /* insn_bit_manip */
insn_bittest = 0x8001, insn_bittest = 0x8001,
insn_bitset = 0x8002, insn_bitset = 0x8002,
insn_bitclear = 0x8003, insn_bitclear = 0x8003,
/* insn_flag_manip */ /* insn_flag_manip */
insn_clear_carry = 0x9001, insn_clear_carry = 0x9001,
insn_clear_zero = 0x9002, insn_clear_zero = 0x9002,
insn_clear_oflow = 0x9003, insn_clear_oflow = 0x9003,
insn_clear_dir = 0x9004, insn_clear_dir = 0x9004,
insn_clear_sign = 0x9005, insn_clear_sign = 0x9005,
insn_clear_parity = 0x9006, insn_clear_parity = 0x9006,
insn_set_carry = 0x9007, insn_set_carry = 0x9007,
insn_set_zero = 0x9008, insn_set_zero = 0x9008,
insn_set_oflow = 0x9009, insn_set_oflow = 0x9009,
insn_set_dir = 0x900A, insn_set_dir = 0x900A,
insn_set_sign = 0x900B, insn_set_sign = 0x900B,
insn_set_parity = 0x900C, insn_set_parity = 0x900C,
insn_tog_carry = 0x9010, insn_tog_carry = 0x9010,
insn_tog_zero = 0x9020, insn_tog_zero = 0x9020,
insn_tog_oflow = 0x9030, insn_tog_oflow = 0x9030,
insn_tog_dir = 0x9040, insn_tog_dir = 0x9040,
insn_tog_sign = 0x9050, insn_tog_sign = 0x9050,
insn_tog_parity = 0x9060, insn_tog_parity = 0x9060,
/* insn_fpu */ /* insn_fpu */
insn_fmov = 0xA001, insn_fmov = 0xA001,
insn_fmovcc = 0xA002, insn_fmovcc = 0xA002,
insn_fneg = 0xA003, insn_fneg = 0xA003,
insn_fabs = 0xA004, insn_fabs = 0xA004,
insn_fadd = 0xA005, insn_fadd = 0xA005,
insn_fsub = 0xA006, insn_fsub = 0xA006,
insn_fmul = 0xA007, insn_fmul = 0xA007,
insn_fdiv = 0xA008, insn_fdiv = 0xA008,
insn_fsqrt = 0xA009, insn_fsqrt = 0xA009,
insn_fcmp = 0xA00A, insn_fcmp = 0xA00A,
insn_fcos = 0xA00C, insn_fcos = 0xA00C,
insn_fldpi = 0xA00D, insn_fldpi = 0xA00D,
insn_fldz = 0xA00E, insn_fldz = 0xA00E,
insn_ftan = 0xA00F, insn_ftan = 0xA00F,
insn_fsine = 0xA010, insn_fsine = 0xA010,
insn_fsys = 0xA020, insn_fsys = 0xA020,
/* insn_interrupt */ /* insn_interrupt */
insn_int = 0xD001, insn_int = 0xD001,
insn_intcc = 0xD002, /* not present in x86 ISA */ insn_intcc = 0xD002, /* not present in x86 ISA */
insn_iret = 0xD003, insn_iret = 0xD003,
insn_bound = 0xD004, insn_bound = 0xD004,
insn_debug = 0xD005, insn_debug = 0xD005,
insn_trace = 0xD006, insn_trace = 0xD006,
insn_invalid_op = 0xD007, insn_invalid_op = 0xD007,
insn_oflow = 0xD008, insn_oflow = 0xD008,
/* insn_system */ /* insn_system */
insn_halt = 0xE001, insn_halt = 0xE001,
insn_in = 0xE002, /* input from port/bus */ insn_in = 0xE002, /* input from port/bus */
insn_out = 0xE003, /* output to port/bus */ insn_out = 0xE003, /* output to port/bus */
insn_cpuid = 0xE004, insn_cpuid = 0xE004,
insn_lmsw = 0xE005, insn_lmsw = 0xE005,
insn_smsw = 0xE006, insn_smsw = 0xE006,
insn_clts = 0xE007, insn_clts = 0xE007,
/* insn_other */ /* insn_other */
insn_nop = 0xF001, insn_nop = 0xF001,
insn_bcdconv = 0xF002, /* convert to or from BCD */ insn_bcdconv = 0xF002, /* convert to or from BCD */
insn_szconv = 0xF003 /* change size of operand */ insn_szconv = 0xF003 /* change size of operand */
}; };
/* These flags specify special characteristics of the instruction, such as /* These flags specify special characteristics of the instruction, such as
@ -463,11 +462,11 @@ enum x86_insn_type {
* NOTE : These may not be accurate for all instructions; updates to the * NOTE : These may not be accurate for all instructions; updates to the
* opcode tables have not been completed. */ * opcode tables have not been completed. */
enum x86_insn_note { enum x86_insn_note {
insn_note_ring0 = 1, /* Only available in ring 0 */ insn_note_ring0 = 1, /* Only available in ring 0 */
insn_note_smm = 2, /* "" in System Management Mode */ insn_note_smm = 2, /* "" in System Management Mode */
insn_note_serial = 4, /* Serializing instruction */ insn_note_serial = 4, /* Serializing instruction */
insn_note_nonswap = 8, /* Does not swap arguments in att-style formatting */ insn_note_nonswap = 8, /* Does not swap arguments in att-style formatting */
insn_note_nosuffix = 16 /* Does not have size suffix in att-style formatting */ insn_note_nosuffix = 16 /* Does not have size suffix in att-style formatting */
}; };
/* This specifies what effects the instruction has on the %eflags register */ /* This specifies what effects the instruction has on the %eflags register */
@ -481,22 +480,22 @@ enum x86_eflags
insn_eflag_parity insn_eflag_parity
}; };
enum x86_flag_status { enum x86_flag_status {
insn_carry_set = 0x1, /* CF */ insn_carry_set = 0x1, /* CF */
insn_zero_set = 0x2, /* ZF */ insn_zero_set = 0x2, /* ZF */
insn_oflow_set = 0x4, /* OF */ insn_oflow_set = 0x4, /* OF */
insn_dir_set = 0x8, /* DF */ insn_dir_set = 0x8, /* DF */
insn_sign_set = 0x10, /* SF */ insn_sign_set = 0x10, /* SF */
insn_parity_set = 0x20, /* PF */ insn_parity_set = 0x20, /* PF */
insn_carry_or_zero_set = 0x40, insn_carry_or_zero_set = 0x40,
insn_zero_set_or_sign_ne_oflow = 0x80, insn_zero_set_or_sign_ne_oflow = 0x80,
insn_carry_clear = 0x100, insn_carry_clear = 0x100,
insn_zero_clear = 0x200, insn_zero_clear = 0x200,
insn_oflow_clear = 0x400, insn_oflow_clear = 0x400,
insn_dir_clear = 0x800, insn_dir_clear = 0x800,
insn_sign_clear = 0x1000, insn_sign_clear = 0x1000,
insn_parity_clear = 0x2000, insn_parity_clear = 0x2000,
insn_sign_eq_oflow = 0x4000, insn_sign_eq_oflow = 0x4000,
insn_sign_ne_oflow = 0x8000 insn_sign_ne_oflow = 0x8000
}; };
/* The CPU model in which the insturction first appeared; this can be used /* The CPU model in which the insturction first appeared; this can be used
@ -505,19 +504,19 @@ enum x86_flag_status {
* NOTE : These may not be accurate for all instructions; updates to the * NOTE : These may not be accurate for all instructions; updates to the
* opcode tables have not been completed. */ * opcode tables have not been completed. */
enum x86_insn_cpu { enum x86_insn_cpu {
cpu_8086 = 1, /* Intel */ cpu_8086 = 1, /* Intel */
cpu_80286 = 2, cpu_80286 = 2,
cpu_80386 = 3, cpu_80386 = 3,
cpu_80387 = 4, cpu_80387 = 4,
cpu_80486 = 5, cpu_80486 = 5,
cpu_pentium = 6, cpu_pentium = 6,
cpu_pentiumpro = 7, cpu_pentiumpro = 7,
cpu_pentium2 = 8, cpu_pentium2 = 8,
cpu_pentium3 = 9, cpu_pentium3 = 9,
cpu_pentium4 = 10, cpu_pentium4 = 10,
cpu_k6 = 16, /* AMD */ cpu_k6 = 16, /* AMD */
cpu_k7 = 32, cpu_k7 = 32,
cpu_athlon = 48 cpu_athlon = 48
}; };
/* CPU ISA subsets: These are derived from the Instruction Groups in /* CPU ISA subsets: These are derived from the Instruction Groups in
@ -528,22 +527,22 @@ enum x86_insn_cpu {
* NOTE : These may not be accurate for all instructions; updates to the * NOTE : These may not be accurate for all instructions; updates to the
* opcode tables have not been completed. */ * opcode tables have not been completed. */
enum x86_insn_isa { enum x86_insn_isa {
isa_gp = 1, /* general purpose */ isa_gp = 1, /* general purpose */
isa_fp = 2, /* floating point */ isa_fp = 2, /* floating point */
isa_fpumgt = 3, /* FPU/SIMD management */ isa_fpumgt = 3, /* FPU/SIMD management */
isa_mmx = 4, /* Intel MMX */ isa_mmx = 4, /* Intel MMX */
isa_sse1 = 5, /* Intel SSE SIMD */ isa_sse1 = 5, /* Intel SSE SIMD */
isa_sse2 = 6, /* Intel SSE2 SIMD */ isa_sse2 = 6, /* Intel SSE2 SIMD */
isa_sse3 = 7, /* Intel SSE3 SIMD */ isa_sse3 = 7, /* Intel SSE3 SIMD */
isa_3dnow = 8, /* AMD 3DNow! SIMD */ isa_3dnow = 8, /* AMD 3DNow! SIMD */
isa_sys = 9 /* system instructions */ isa_sys = 9 /* system instructions */
}; };
enum x86_insn_prefix { enum x86_insn_prefix {
insn_no_prefix = 0, insn_no_prefix = 0,
insn_rep_zero = 1, /* REPZ and REPE */ insn_rep_zero = 1, /* REPZ and REPE */
insn_rep_notzero = 2, /* REPNZ and REPNZ */ insn_rep_notzero = 2, /* REPNZ and REPNZ */
insn_lock = 4 /* LOCK: */ insn_lock = 4 /* LOCK: */
}; };
@ -558,15 +557,15 @@ enum x86_insn_prefix {
* The "type" (implicit or explicit) and the access method can * The "type" (implicit or explicit) and the access method can
* be ORed together, e.g. op_wo | op_explicit */ * be ORed together, e.g. op_wo | op_explicit */
enum x86_op_foreach_type { enum x86_op_foreach_type {
op_any = 0, /* ALL operands (explicit, implicit, rwx) */ op_any = 0, /* ALL operands (explicit, implicit, rwx) */
op_dest = 1, /* operands with Write access */ op_dest = 1, /* operands with Write access */
op_src = 2, /* operands with Read access */ op_src = 2, /* operands with Read access */
op_ro = 3, /* operands with Read but not Write access */ op_ro = 3, /* operands with Read but not Write access */
op_wo = 4, /* operands with Write but not Read access */ op_wo = 4, /* operands with Write but not Read access */
op_xo = 5, /* operands with Execute access */ op_xo = 5, /* operands with Execute access */
op_rw = 6, /* operands with Read AND Write access */ op_rw = 6, /* operands with Read AND Write access */
op_implicit = 0x10, /* operands that are implied by the opcode */ op_implicit = 0x10, /* operands that are implied by the opcode */
op_explicit = 0x20 /* operands that are not side-effects */ op_explicit = 0x20 /* operands that are not side-effects */
}; };
/* Operand FOREACH callback: 'arg' is an abritrary parameter passed to the /* Operand FOREACH callback: 'arg' is an abritrary parameter passed to the
@ -707,9 +706,9 @@ public:
* (buf, buf_len, buf_rva, offset, len, insn, func, arg, resolve_func) * (buf, buf_len, buf_rva, offset, len, insn, func, arg, resolve_func)
* ...but of course all of these are not used at the same time. * ...but of course all of these are not used at the same time.
*/ */
class X86_Disasm class X86_Disasm
{ {
public: public:
/* Function prototype for caller-supplied callback routine /* Function prototype for caller-supplied callback routine
* These callbacks are intended to process 'insn' further, e.g. by * These callbacks are intended to process 'insn' further, e.g. by
* adding it to a linked list, database, etc */ * adding it to a linked list, database, etc */
@ -724,28 +723,28 @@ public:
* should return -1; in all other cases the RVA to be disassembled next * should return -1; in all other cases the RVA to be disassembled next
* should be returned. */ * should be returned. */
typedef int32_t (*DISASM_RESOLVER)( x86_op_t *op, x86_insn_t * current_insn, typedef int32_t (*DISASM_RESOLVER)( x86_op_t *op, x86_insn_t * current_insn,
void *arg ); void *arg );
protected: protected:
DISASM_REPORTER __x86_reporter_func; DISASM_REPORTER __x86_reporter_func;
void * __x86_reporter_arg; void * __x86_reporter_arg;
Ia32_Decoder m_decoder; Ia32_Decoder m_decoder;
public: public:
X86_Disasm( x86_options options=opt_none,DISASM_REPORTER reporter=0, void *arg=0 ) : X86_Disasm( x86_options options=opt_none,DISASM_REPORTER reporter=0, void *arg=0 ) :
__x86_reporter_func(reporter), __x86_reporter_func(reporter),
__x86_reporter_arg(arg) { __x86_reporter_arg(arg) {
x86_init( options,reporter,arg); x86_init( options,reporter,arg);
} }
/* management routines */ /* management routines */
/* 'arg' is caller-specific data which is passed as the first argument /* 'arg' is caller-specific data which is passed as the first argument
* to the reporter callback routine */ * to the reporter callback routine */
int x86_init( x86_options options, DISASM_REPORTER reporter, void *arg); int x86_init( x86_options options, DISASM_REPORTER reporter, void *arg);
void x86_set_reporter( DISASM_REPORTER reporter, void *arg); void x86_set_reporter( DISASM_REPORTER reporter, void *arg);
void x86_set_options( x86_options options ); void x86_set_options( x86_options options );
x86_options x86_get_options( void ); x86_options x86_get_options( void );
int x86_cleanup(void); int x86_cleanup(void);
/* x86_disasm: Disassemble a single instruction from a buffer of bytes. /* x86_disasm: Disassemble a single instruction from a buffer of bytes.
* Returns size of instruction in bytes. * Returns size of instruction in bytes.
* Caller is responsible for calling x86_oplist_free() on * Caller is responsible for calling x86_oplist_free() on
* a reused "insn" to avoid leaking memory when calling this * a reused "insn" to avoid leaking memory when calling this
@ -757,8 +756,8 @@ public:
* insn : Structure to fill with disassembled instruction * insn : Structure to fill with disassembled instruction
*/ */
unsigned int x86_disasm(const unsigned char *buf, unsigned int buf_len, unsigned int x86_disasm(const unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset, uint32_t buf_rva, unsigned int offset,
x86_insn_t * insn ); x86_insn_t * insn );
/* x86_disasm_range: Sequential disassembly of a range of bytes in a buffer, /* x86_disasm_range: Sequential disassembly of a range of bytes in a buffer,
* invoking a callback function each time an instruction * invoking a callback function each time an instruction
* is successfully disassembled. The 'range' refers to the * is successfully disassembled. The 'range' refers to the
@ -817,7 +816,7 @@ public:
unsigned int x86_ip_reg(void); unsigned int x86_ip_reg(void);
unsigned int x86_flag_reg(void); unsigned int x86_flag_reg(void);
}; };
/* Instruction operands: these are stored as a list of explicit and /* Instruction operands: these are stored as a list of explicit and
* implicit operands. It is recommended that the 'foreach' routines * implicit operands. It is recommended that the 'foreach' routines
@ -866,24 +865,24 @@ public:
#define X86_WILDCARD_BYTE 0xF4 #define X86_WILDCARD_BYTE 0xF4
struct x86_invariant_op_t{ struct x86_invariant_op_t{
enum x86_op_type type; /* operand type */ enum x86_op_type type; /* operand type */
enum x86_op_datatype datatype; /* operand size */ enum x86_op_datatype datatype; /* operand size */
enum x86_op_access access; /* operand access [RWX] */ enum x86_op_access access; /* operand access [RWX] */
x86_op_flags flags; /* misc flags */ x86_op_flags flags; /* misc flags */
}; };
struct x86_invariant_t { struct x86_invariant_t {
unsigned char bytes[64]; /* invariant representation */ unsigned char bytes[64]; /* invariant representation */
unsigned int size; /* number of bytes in insn */ unsigned int size; /* number of bytes in insn */
x86_insn_t::x86_insn_group group; /* meta-type, e.g. INS_EXEC */ x86_insn_t::x86_insn_group group; /* meta-type, e.g. INS_EXEC */
enum x86_insn_type type; /* type, e.g. INS_BRANCH */ enum x86_insn_type type; /* type, e.g. INS_BRANCH */
x86_invariant_op_t operands[3]; /* operands: dest, src, imm */ x86_invariant_op_t operands[3]; /* operands: dest, src, imm */
} ; } ;
/* return a version of the instruction with the variant bytes masked out */ /* return a version of the instruction with the variant bytes masked out */
size_t x86_invariant_disasm( unsigned char *buf, int buf_len, size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
x86_invariant_t *inv ); x86_invariant_t *inv );
/* return the size in bytes of the intruction pointed to by 'buf'; /* return the size in bytes of the intruction pointed to by 'buf';
* this used x86_invariant_disasm since it faster than x86_disasm */ * this used x86_invariant_disasm since it faster than x86_disasm */
size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ); size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len );

View File

@ -99,7 +99,6 @@ x86_op_t * x86_insn_t::get_dest() {
if ( ! operands ) { if ( ! operands ) {
return NULL; return NULL;
} }
assert(this->x86_operand_count(op_dest)==1);
for (op_lst = operands; op_lst; op_lst = op_lst->next ) { for (op_lst = operands; op_lst; op_lst = op_lst->next ) {
if ( op_lst->op.access & op_write) if ( op_lst->op.access & op_write)
return &(op_lst->op); return &(op_lst->op);

View File

@ -36,7 +36,7 @@ private:
numHlIcodes(0),flg(0), numHlIcodes(0),flg(0),
inEdges(0), inEdges(0),
edges(0),beenOnH(0),inEdgeCount(0),reachingInt(0), edges(0),beenOnH(0),inEdgeCount(0),reachingInt(0),
inInterval(0),correspInt(0),liveUse(0),def(0),liveIn(0),liveOut(0), inInterval(0),correspInt(0),
dfsFirstNum(0),dfsLastNum(0),immedDom(0),ifFollow(0),loopType(0),latchNode(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) numBackEdges(0),loopHead(0),loopFollow(0),caseHead(0),caseTail(0),index(0)
{ {

View File

@ -143,7 +143,7 @@ public:
bool liveAnal; /* Procedure has been analysed already */ 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), 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) hasCase(false),liveAnal(0)//,next(0),prev(0)
{ {
} }
public: public:

View File

@ -59,12 +59,8 @@ typedef struct { /* Command line option flags */
extern OPTION option; /* Command line options */ extern OPTION option; /* Command line options */
#include "BinaryImage.h" #include "BinaryImage.h"
extern LivenessSet duReg[30]; /* def/use bits for registers */
//extern uint32_t duReg[30]; /* def/use bits for registers */
extern LivenessSet maskDuReg[30]; /* masks off du bits for regs */
/* Registers used by icode instructions */
/* Memory map states */ /* Memory map states */
enum eAreaType enum eAreaType
@ -130,8 +126,8 @@ char *writeJcondInv (HLTYPE, Function *, int *);
/* Exported funcions from locident.c */ /* Exported funcions from locident.c */
boolT checkLongEq (LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset); bool checkLongEq(LONG_STKID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &atOffset);
boolT checkLongRegEq (LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &); bool checkLongRegEq(LONGID_TYPE, iICODE, int, Function *, Assignment &asgn, LLInst &);
eReg otherLongRegi(eReg, int, LOCAL_ID *); eReg otherLongRegi(eReg, int, LOCAL_ID *);

View File

@ -7,6 +7,9 @@
#include <vector> #include <vector>
#include <list> #include <list>
#include <bitset> #include <bitset>
#include <set>
#include <algorithm>
#include <initializer_list>
#include <llvm/ADT/ilist.h> #include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h> #include <llvm/ADT/ilist_node.h>
#include <llvm/MC/MCInst.h> #include <llvm/MC/MCInst.h>
@ -29,21 +32,24 @@ typedef std::list<ICODE>::iterator iICODE;
typedef std::list<ICODE>::reverse_iterator riICODE; typedef std::list<ICODE>::reverse_iterator riICODE;
typedef boost::iterator_range<iICODE> rCODE; typedef boost::iterator_range<iICODE> rCODE;
struct LivenessSet : public std::bitset<32> struct LivenessSet
{ {
LivenessSet(int val=0) : std::bitset<32>(val) {} std::set<eReg> registers;
LivenessSet(const LivenessSet &other) public:
LivenessSet(const std::initializer_list<eReg> &init) : registers(init) {}
LivenessSet() {}
LivenessSet(const LivenessSet &other) : registers(other.registers)
{ {
(std::bitset<32> &)*this = (std::bitset<32> &)other;
} }
LivenessSet(const std::bitset<32> &other) void reset()
{ {
(std::bitset<32> &)*this = other; registers.clear();
} }
// LivenessSet(LivenessSet &&other) : LivenessSet()
// { // LivenessSet(LivenessSet &&other) : LivenessSet()
// swap(*this,other); // {
// } // swap(*this,other);
// }
LivenessSet &operator=(LivenessSet other) LivenessSet &operator=(LivenessSet other)
{ {
swap(*this,other); swap(*this,other);
@ -56,22 +62,65 @@ struct LivenessSet : public std::bitset<32>
// by swapping the members of two classes, // by swapping the members of two classes,
// the two classes are effectively swapped // the two classes are effectively swapped
swap((std::bitset<32> &)first, (std::bitset<32> &)second); swap(first.registers, second.registers);
} }
LivenessSet &operator|=(const LivenessSet &other)
{
registers.insert(other.registers.begin(),other.registers.end());
return *this;
}
LivenessSet &operator&=(const LivenessSet &other)
{
std::set<eReg> res;
std::set_intersection(registers.begin(),registers.end(),
other.registers.begin(),other.registers.end(),
std::inserter(res, res.end()));
registers = res;
return *this;
}
LivenessSet &operator-=(const LivenessSet &other)
{
std::set<eReg> res;
std::set_difference(registers.begin(),registers.end(),
other.registers.begin(),other.registers.end(),
std::inserter(res, res.end()));
registers = res;
return *this;
}
LivenessSet operator-(const LivenessSet &other) const
{
return LivenessSet(*this) -= other;
}
LivenessSet operator+(const LivenessSet &other) const
{
return LivenessSet(*this) |= other;
}
LivenessSet operator &(const LivenessSet &other) const
{
return LivenessSet(*this) &= other;
}
bool any() const
{
return not registers.empty();
}
bool operator==(const LivenessSet &other) const
{
return registers==other.registers;
}
bool operator!=(const LivenessSet &other) const { return not(*this==other);}
LivenessSet &setReg(int r); LivenessSet &setReg(int r);
LivenessSet &addReg(int r); LivenessSet &addReg(int r);
bool testReg(int r) bool testReg(int r) const
{ {
return test(r-rAX); return registers.find(eReg(r))!=registers.end();
} }
public: bool testRegAndSubregs(int r) const;
LivenessSet &clrReg(int r); LivenessSet &clrReg(int r);
private: private:
void postProcessCompositeRegs(); void postProcessCompositeRegs();
}; };
extern LivenessSet duReg[30];
/* uint8_t and uint16_t registers */ /* uint8_t and uint16_t registers */
/* Def/use of flags - low 4 bits represent flags */ /* Def/use of flags - low 4 bits represent flags */
@ -180,8 +229,8 @@ public:
void setCall(Function *proc); void setCall(Function *proc);
HLTYPE(hlIcode op=HLI_INVALID) : opcode(op) HLTYPE(hlIcode op=HLI_INVALID) : opcode(op)
{} {}
// HLTYPE() // help valgrind find uninitialized HLTYPES // HLTYPE() // help valgrind find uninitialized HLTYPES
// {} // {}
HLTYPE & operator=(const HLTYPE &l) HLTYPE & operator=(const HLTYPE &l)
{ {
exp = l.exp; exp = l.exp;
@ -197,7 +246,6 @@ public:
/* LOW_LEVEL icode operand record */ /* LOW_LEVEL icode operand record */
struct LLOperand struct LLOperand
{ {
llvm::MCOperand llvm_op;
eReg seg; /* CS, DS, ES, SS */ eReg seg; /* CS, DS, ES, SS */
eReg segOver; /* CS, DS, ES, SS if segment override */ eReg segOver; /* CS, DS, ES, SS if segment override */
int16_t segValue; /* Value of segment seg during analysis */ int16_t segValue; /* Value of segment seg during analysis */
@ -245,6 +293,10 @@ struct LLOperand
Op.regi = (eReg)Val; Op.regi = (eReg)Val;
return Op; return Op;
} }
bool isSet()
{
return not (*this == LLOperand());
}
void addProcInformation(int param_count,uint32_t call_conv); void addProcInformation(int param_count,uint32_t call_conv);
}; };
struct LLInst : public llvm::MCInst //: public llvm::ilist_node<LLInst> struct LLInst : public llvm::MCInst //: public llvm::ilist_node<LLInst>
@ -256,7 +308,7 @@ public:
int codeIdx; /* Index into cCode.code */ int codeIdx; /* Index into cCode.code */
uint8_t numBytes; /* Number of bytes this instr */ uint8_t numBytes; /* Number of bytes this instr */
uint32_t label; /* offset in image (20-bit adr) */ uint32_t label; /* offset in image (20-bit adr) */
LLOperand dst; /* destination operand */ LLOperand m_dst; /* destination operand */
DU flagDU; /* def/use of flags */ DU flagDU; /* def/use of flags */
int caseEntry; int caseEntry;
std::vector<uint32_t> caseTbl2; std::vector<uint32_t> caseTbl2;
@ -285,25 +337,29 @@ public:
{ {
return (getOpcode()==op); return (getOpcode()==op);
} }
bool matchWithRegDst(llIcode op)
{
return (getOpcode()==op) and m_dst.isReg();
}
bool match(llIcode op,eReg dest) bool match(llIcode op,eReg dest)
{ {
return (getOpcode()==op)&&dst.regi==dest; return (getOpcode()==op)&&m_dst.regi==dest;
} }
bool match(llIcode op,eReg dest,uint32_t flgs) bool match(llIcode op,eReg dest,uint32_t flgs)
{ {
return (getOpcode()==op) and (dst.regi==dest) and testFlags(flgs); return (getOpcode()==op) and (m_dst.regi==dest) and testFlags(flgs);
} }
bool match(llIcode op,eReg dest,eReg src_reg) bool match(llIcode op,eReg dest,eReg src_reg)
{ {
return (getOpcode()==op)&&(dst.regi==dest)&&(m_src.regi==src_reg); return (getOpcode()==op)&&(m_dst.regi==dest)&&(m_src.regi==src_reg);
} }
bool match(eReg dest,eReg src_reg) bool match(eReg dest,eReg src_reg)
{ {
return (dst.regi==dest)&&(m_src.regi==src_reg); return (m_dst.regi==dest)&&(m_src.regi==src_reg);
} }
bool match(eReg dest) bool match(eReg dest)
{ {
return (dst.regi==dest); return (m_dst.regi==dest);
} }
bool match(llIcode op,uint32_t flgs) bool match(llIcode op,uint32_t flgs)
{ {
@ -314,6 +370,19 @@ public:
setOpcode(op); setOpcode(op);
flg =flags; flg =flags;
} }
void set(llIcode op,uint32_t flags,eReg dst_reg)
{
setOpcode(op);
m_dst = LLOperand::CreateReg2(dst_reg);
flg =flags;
}
void set(llIcode op,uint32_t flags,eReg dst_reg,const LLOperand &src_op)
{
setOpcode(op);
m_dst = LLOperand::CreateReg2(dst_reg);
m_src = src_op;
flg =flags;
}
void emitGotoLabel(int indLevel); void emitGotoLabel(int indLevel);
void findJumpTargets(CIcodeRec &_pc); void findJumpTargets(CIcodeRec &_pc);
void writeIntComment(std::ostringstream &s); void writeIntComment(std::ostringstream &s);
@ -343,16 +412,16 @@ public:
} }
void replaceDst(const LLOperand &with) void replaceDst(const LLOperand &with)
{ {
dst = with; m_dst = with;
}
void replaceDst(eReg r)
{
dst = LLOperand::CreateReg2(r);
} }
// void replaceDst(eReg r)
// {
// dst = LLOperand::CreateReg2(r);
// }
ICODE *m_link; ICODE *m_link;
condId idType(opLoc sd) const; condId idType(opLoc sd) const;
const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &dst; } const LLOperand * get(opLoc sd) const { return (sd == SRC) ? &src() : &m_dst; }
LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &dst; } LLOperand * get(opLoc sd) { return (sd == SRC) ? &src() : &m_dst; }
}; };
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */ /* Icode definition: LOW_LEVEL and HIGH_LEVEL */
@ -407,6 +476,10 @@ public:
}; };
struct DU1 struct DU1
{ {
protected:
int numRegsDef; /* # registers defined by this inst */
public:
struct Use struct Use
{ {
int Reg; // used register int Reg; // used register
@ -422,7 +495,6 @@ public:
} }
}; };
int numRegsDef; /* # registers defined by this inst */
uint8_t regi[MAX_REGS_DEF+1]; /* registers defined by this inst */ uint8_t regi[MAX_REGS_DEF+1]; /* registers defined by this inst */
Use idx[MAX_REGS_DEF+1]; Use idx[MAX_REGS_DEF+1];
//int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */ //int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
@ -447,6 +519,11 @@ public:
Use &u(idx[regIdx]); Use &u(idx[regIdx]);
u.removeUser(ic); u.removeUser(ic);
} }
int getNumRegsDef() const {return numRegsDef;}
void clearAllDefs() {numRegsDef=0;}
DU1 &addDef(eReg r) {numRegsDef++; return *this;}
DU1 &setDef(eReg r) {numRegsDef=1; return *this;}
void removeDef(eReg r) {numRegsDef--;}
DU1() : numRegsDef(0) DU1() : numRegsDef(0)
{ {
} }
@ -460,13 +537,13 @@ public:
const LLInst * ll() const { return &m_ll;} const LLInst * ll() const { return &m_ll;}
HLTYPE * hlU() { HLTYPE * hlU() {
// assert(type==HIGH_LEVEL); // assert(type==HIGH_LEVEL);
// assert(m_hl.opcode!=HLI_INVALID); // assert(m_hl.opcode!=HLI_INVALID);
return &m_hl; return &m_hl;
} }
const HLTYPE * hl() const { const HLTYPE * hl() const {
// assert(type==HIGH_LEVEL); // assert(type==HIGH_LEVEL);
// assert(m_hl.opcode!=HLI_INVALID); // assert(m_hl.opcode!=HLI_INVALID);
return &m_hl; return &m_hl;
} }
void hl(const HLTYPE &v) { m_hl=v;} void hl(const HLTYPE &v) { m_hl=v;}
@ -501,9 +578,9 @@ public:
{ {
} }
public: public:
const MachineBasicBlock* getParent() const { return Parent; } const MachineBasicBlock* getParent() const { return Parent; }
MachineBasicBlock* getParent() { return Parent; } MachineBasicBlock* getParent() { return Parent; }
//unsigned getNumOperands() const { return (unsigned)Operands.size(); } //unsigned getNumOperands() const { return (unsigned)Operands.size(); }
}; };
/** Map n low level instructions to m high level instructions /** Map n low level instructions to m high level instructions

View File

@ -31,37 +31,67 @@ struct IDX_ARRAY : public std::vector<iICODE>
} }
}; };
typedef enum enum frameType
{ {
STK_FRAME, /* For stack vars */ STK_FRAME, /* For stack vars */
REG_FRAME, /* For register variables */ REG_FRAME, /* For register variables */
GLB_FRAME /* For globals */ GLB_FRAME /* For globals */
} frameType; };
typedef struct struct BWGLB_TYPE
{ {
int16_t seg; /* segment value */ int16_t seg; /* segment value */
int16_t off; /* offset */ int16_t off; /* offset */
eReg regi; /* optional indexed register */ eReg regi; /* optional indexed register */
} BWGLB_TYPE; } ;
typedef struct /* For TYPE_LONG_(UN)SIGN on the stack */
{ /* For TYPE_LONG_(UN)SIGN on the stack */ struct LONG_STKID_TYPE
{
int offH; /* high offset from BP */ int offH; /* high offset from BP */
int offL; /* low offset from BP */ int offL; /* low offset from BP */
} LONG_STKID_TYPE; LONG_STKID_TYPE(int h,int l) : offH(h),offL(l) {}
};
/* For TYPE_LONG_(UN)SIGN registers */
struct LONGID_TYPE struct LONGID_TYPE
{ /* For TYPE_LONG_(UN)SIGN registers */ {
eReg h; /* high register */ protected:
eReg l; /* low register */ eReg m_h; /* high register */
eReg m_l; /* low register */
public:
void set(eReg highpart,eReg lowpart)
{
m_h = highpart;
m_l = lowpart;
}
eReg l() const { return m_l; }
eReg h() const { return m_h; }
bool srcDstRegMatch(iICODE a,iICODE b) const; bool srcDstRegMatch(iICODE a,iICODE b) const;
LONGID_TYPE() {} // uninitializing constructor to help valgrind catch uninit accesses
LONGID_TYPE(eReg h,eReg l) : m_h(h),m_l(l) {}
}; };
struct LONGGLB_TYPE /* 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_TYPE(int16_t _seg,int16_t _H,int16_t _L,int8_t _reg=0)
{
seg=_seg;
offH=_H;
offL=_L;
regi=_reg;
}
};
/* ID, LOCAL_ID */ /* ID, LOCAL_ID */
struct ID struct ID
{ {
protected:
LONGID_TYPE m_longId; /* For TYPE_LONG_(UN)SIGN registers */
public:
hlType type; /* Probable type */ hlType type; /* Probable type */
bool illegal; /* Boolean: not a valid field any more */ bool illegal; /* Boolean: not a valid field any more */
//std::vector<iICODE> idx; //std::vector<iICODE> idx;
@ -70,33 +100,39 @@ struct ID
bool hasMacro; /* Identifier requires a macro */ bool hasMacro; /* Identifier requires a macro */
char macro[10]; /* Macro for this identifier */ char macro[10]; /* Macro for this identifier */
std::string name; /* Identifier's name */ std::string name; /* Identifier's name */
union { /* Different types of identifiers */ union ID_UNION { /* Different types of identifiers */
friend class ID;
protected:
LONG_STKID_TYPE longStkId; /* For TYPE_LONG_(UN)SIGN on the stack */
public:
eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */ eReg regi; /* For TYPE_BYTE(uint16_t)_(UN)SIGN registers */
struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */ struct { /* For TYPE_BYTE(uint16_t)_(UN)SIGN on the stack */
uint8_t regOff; /* register offset (if any) */ uint8_t regOff; /* register offset (if any) */
int off; /* offset from BP */ int off; /* offset from BP */
} bwId; } bwId;
BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(UN)SIGN globals */ BWGLB_TYPE bwGlb; /* For TYPE_BYTE(uint16_t)_(UN)SIGN globals */
LONGID_TYPE longId; /* For TYPE_LONG_(UN)SIGN registers */ LONGGLB_TYPE longGlb;
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 */ struct { /* For TYPE_LONG_(UN)SIGN constants */
uint32_t h; /* high uint16_t */ uint32_t h; /* high uint16_t */
uint32_t l; /* low uint16_t */ uint32_t l; /* low uint16_t */
} longKte; } longKte;
ID_UNION() { /*new (&longStkId) LONG_STKID_TYPE();*/}
} id; } id;
LONGID_TYPE &longId() {assert(isLong() && loc==REG_FRAME); return m_longId;}
const LONGID_TYPE &longId() const {assert(isLong() && loc==REG_FRAME); return m_longId;}
LONG_STKID_TYPE &longStkId() {assert(isLong() && loc==STK_FRAME); return id.longStkId;}
const LONG_STKID_TYPE &longStkId() const {assert(isLong() && loc==STK_FRAME); return id.longStkId;}
ID(); ID();
ID(hlType t, frameType f); ID(hlType t, frameType f);
ID(hlType t, const LONGID_TYPE &s);
ID(hlType t, const LONG_STKID_TYPE &s);
ID(hlType t, const LONGGLB_TYPE &s);
bool isSigned() const { return (type==TYPE_BYTE_SIGN)||(type==TYPE_WORD_SIGN)||(type==TYPE_LONG_SIGN);} bool isSigned() const { return (type==TYPE_BYTE_SIGN)||(type==TYPE_WORD_SIGN)||(type==TYPE_LONG_SIGN);}
uint16_t typeBitsize() const uint16_t typeBitsize() const
{ {
return TypeContainer::typeSize(type)*8; return TypeContainer::typeSize(type)*8;
} }
bool isLong() const { return (type==TYPE_LONG_UNSIGN)||(type==TYPE_LONG_SIGN); }
void setLocalName(int i) void setLocalName(int i)
{ {
char buf[32]; char buf[32];
@ -123,7 +159,7 @@ public:
int newByteWordReg(hlType t, eReg regi); int newByteWordReg(hlType t, eReg regi);
int newByteWordStk(hlType t, int off, uint8_t regOff); int newByteWordStk(hlType t, int off, uint8_t regOff);
int newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t); int newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t);
int newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_); int newLongReg(hlType t, const LONGID_TYPE &longT, 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, int off);
int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset); int newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset);
void newIdent(hlType t, frameType f); void newIdent(hlType t, frameType f);

View File

@ -4,6 +4,7 @@
#include <sstream> #include <sstream>
#include <bitset> #include <bitset>
struct LivenessSet;
/* Machine registers */ /* Machine registers */
enum eReg enum eReg
{ {
@ -32,8 +33,9 @@ enum eReg
rBH = 20, rBH = 20,
rTMP= 21, /* temp register for DIV/IDIV/MOD */ rTMP= 21, /* temp register for DIV/IDIV/MOD */
rTMP2= 22, /* temp register for DIV/IDIV/MOD */
/* Indexed modes go from INDEXBASE to INDEXBASE+7 */ /* Indexed modes go from INDEXBASE to INDEXBASE+7 */
INDEX_BX_SI = 22, // "bx+si" INDEX_BX_SI = 23, // "bx+si"
INDEX_BX_DI, // "bx+di" INDEX_BX_DI, // "bx+di"
INDEX_BP_SI, // "bp+si" INDEX_BP_SI, // "bp+si"
INDEX_BP_DI, // "bp+di" INDEX_BP_DI, // "bp+di"
@ -64,15 +66,7 @@ public:
bool physicalReg(eReg r); bool physicalReg(eReg r);
/* Writes the registers that are set in the bitvector */ /* Writes the registers that are set in the bitvector */
//TODO: move this into Machine_X86 ? //TODO: move this into Machine_X86 ?
static void writeRegVector (std::ostream &ostr,const std::bitset<32> &regi) static void writeRegVector (std::ostream &ostr,const LivenessSet &regi);
{
int j;
for (j = rAX; j < INDEX_BX_SI; j++)
{
if (regi.test(j-1))
ostr << regName(eReg(j))<<" ";
}
}
static eReg subRegH(eReg reg); static eReg subRegH(eReg reg);
static eReg subRegL(eReg reg); static eReg subRegL(eReg reg);
static bool isMemOff(eReg r); static bool isMemOff(eReg r);

View File

@ -52,18 +52,23 @@ static const char *hexStr (uint16_t i)
void ICODE::setRegDU (eReg regi, operDu du_in) void ICODE::setRegDU (eReg regi, operDu du_in)
{ {
// printf("%s %d %x\n",__FUNCTION__,regi,int(du_in)); // printf("%s %d %x\n",__FUNCTION__,regi,int(du_in));
if(regi==rSP)
{
printf("Discarding SP def&use info for now\n");
return;
}
switch (du_in) switch (du_in)
{ {
case eDEF: case eDEF:
du.def.addReg(regi); du.def.addReg(regi);
du1.numRegsDef++; du1.addDef(regi);
break; break;
case eUSE: case eUSE:
du.use.addReg(regi); du.use.addReg(regi);
break; break;
case USE_DEF: case USE_DEF:
du.addDefinedAndUsed(regi); du.addDefinedAndUsed(regi);
du1.numRegsDef++; du1.addDef(regi);
break; break;
case NONE: /* do nothing */ case NONE: /* do nothing */
break; break;
@ -233,9 +238,8 @@ AstIdent *AstIdent::Long(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f,
else else
{ {
newExp = new AstIdent(); newExp = new AstIdent();
idx = localId->newLong(sd, pIcode, f, ix, du, atOffset);
newExp->ident.idType = LONG_VAR; newExp->ident.idType = LONG_VAR;
newExp->ident.idNode.longIdx = idx; newExp->ident.idNode.longIdx = localId->newLong(sd, pIcode, f, ix, du, atOffset);
} }
return (newExp); return (newExp);
} }
@ -265,7 +269,7 @@ AstIdent *AstIdent::idID (const ID *retVal, LOCAL_ID *locsym, iICODE ix_)
case TYPE_LONG_SIGN: case TYPE_LONG_SIGN:
{ {
newExp = new AstIdent(); newExp = new AstIdent();
idx = locsym->newLongReg (TYPE_LONG_SIGN, retVal->id.longId.h,retVal->id.longId.l, ix_); idx = locsym->newLongReg (TYPE_LONG_SIGN, retVal->longId(), ix_);
newExp->ident.idType = LONG_VAR; newExp->ident.idType = LONG_VAR;
newExp->ident.idNode.longIdx = idx; newExp->ident.idNode.longIdx = idx;
break; break;
@ -294,13 +298,13 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
int idx; /* idx into pIcode->localId table */ int idx; /* idx into pIcode->localId table */
const LLOperand &pm((sd == SRC) ? ll_insn.src() : ll_insn.dst); const LLOperand &pm((sd == SRC) ? ll_insn.src() : ll_insn.m_dst);
if ( ((sd == DST) && ll_insn.testFlags(IM_DST)) or if ( ((sd == DST) && ll_insn.testFlags(IM_DST)) or
((sd == SRC) && ll_insn.testFlags(IM_SRC)) or ((sd == SRC) && ll_insn.testFlags(IM_SRC)) or
(sd == LHS_OP)) /* for MUL lhs */ (sd == LHS_OP)) /* for MUL lhs */
{ /* implicit dx:ax */ { /* implicit dx:ax */
idx = pProc->localId.newLongReg (TYPE_LONG_SIGN, rDX, rAX, ix_); idx = pProc->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(rDX, rAX), ix_);
newExp = AstIdent::LongIdx (idx); newExp = AstIdent::LongIdx (idx);
duIcode.setRegDU (rDX, du); duIcode.setRegDU (rDX, du);
duIcode.setRegDU (rAX, du); duIcode.setRegDU (rAX, du);
@ -372,7 +376,7 @@ Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_
/* Returns the identifier type */ /* Returns the identifier type */
condId LLInst::idType(opLoc sd) const condId LLInst::idType(opLoc sd) const
{ {
const LLOperand &pm((sd == SRC) ? src() : dst); const LLOperand &pm((sd == SRC) ? src() : m_dst);
if ((sd == SRC) && testFlags(I)) if ((sd == SRC) && testFlags(I))
return (CONSTANT); return (CONSTANT);
@ -582,10 +586,10 @@ string AstIdent::walkCondExpr(Function *pProc, int *numLoc) const
{ {
id->setLocalName(++(*numLoc)); id->setLocalName(++(*numLoc));
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; "; codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; ";
codeOut <<"/* "<<Machine_X86::regName(id->id.longId.h) << ":" << codeOut <<"/* "<<Machine_X86::regName(id->longId().h()) << ":" <<
Machine_X86::regName(id->id.longId.l) << " */\n"; Machine_X86::regName(id->longId().l()) << " */\n";
o << id->name; o << id->name;
pProc->localId.propLongId (id->id.longId.l,id->id.longId.h, id->name.c_str()); pProc->localId.propLongId (id->longId().l(),id->longId().h(), id->name.c_str());
} }
else /* GLB_FRAME */ else /* GLB_FRAME */
{ {
@ -884,10 +888,10 @@ eReg AstIdent::otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) || if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
(id->type == TYPE_LONG_UNSIGN))) (id->type == TYPE_LONG_UNSIGN)))
{ {
if (id->id.longId.h == regi) if (id->longId().h() == regi)
return (id->id.longId.l); return (id->longId().l());
else if (id->id.longId.l == regi) else if (id->longId().l() == regi)
return (id->id.longId.h); return (id->longId().h());
} }
return rUNDEF; // Cristina: please check this! return rUNDEF; // Cristina: please check this!
} }

View File

@ -154,7 +154,7 @@ void LLInst::writeIntComment (std::ostringstream &s)
s<<"\t/* "; s<<"\t/* ";
if (src_immed == 0x21) if (src_immed == 0x21)
{ {
s <<int21h[dst.off]; s <<int21h[m_dst.off];
} }
else if (src_immed > 0x1F && src_immed < 0x2F) else if (src_immed > 0x1F && src_immed < 0x2F)
{ {
@ -162,7 +162,7 @@ void LLInst::writeIntComment (std::ostringstream &s)
} }
else if (src_immed == 0x2F) else if (src_immed == 0x2F)
{ {
switch (dst.off) switch (m_dst.off)
{ {
case 0x01 : case 0x01 :
s << "Print spooler"; s << "Print spooler";
@ -215,8 +215,8 @@ void Function::writeProcComments(std::ostream &ostr)
else /* long register */ else /* long register */
{ {
id = &this->localId.id_arr[psym->regs->ident.idNode.longIdx]; id = &this->localId.id_arr[psym->regs->ident.idNode.longIdx];
ostr << Machine_X86::regName(id->id.longId.h) << ":"; ostr << Machine_X86::regName(id->longId().h()) << ":";
ostr << Machine_X86::regName(id->id.longId.l); ostr << Machine_X86::regName(id->longId().l());
} }
ostr << ".\n"; ostr << ".\n";

View File

@ -60,7 +60,7 @@ void ExpStack::push(Expr *expr)
Expr *ExpStack::pop() Expr *ExpStack::pop()
{ {
if(expStk.empty()) if(expStk.empty())
return 0; return expStk.back();
Expr *topExp = expStk.back(); Expr *topExp = expStk.back();
expStk.pop_back(); expStk.pop_back();
return topExp; return topExp;
@ -266,7 +266,7 @@ void Function::genLiveKtes ()
{ {
if ((insn.type == HIGH_LEVEL) && ( insn.valid() )) if ((insn.type == HIGH_LEVEL) && ( insn.valid() ))
{ {
liveUse |= (insn.du.use & ~def); liveUse |= (insn.du.use - def);
def |= insn.du.def; def |= insn.du.def;
} }
} }
@ -358,14 +358,15 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
{ {
switch (pcallee->retVal.type) { switch (pcallee->retVal.type) {
case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN: case TYPE_LONG_UNSIGN:
ticode.du1.numRegsDef = 2; ticode.du1.setDef(rAX).addDef(rDX);
//TODO: use Calling convention to properly set regs here
break; break;
case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN: case TYPE_WORD_SIGN: case TYPE_WORD_UNSIGN:
case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN: case TYPE_BYTE_SIGN: case TYPE_BYTE_UNSIGN:
ticode.du1.numRegsDef = 1; ticode.du1.setDef(rAX);
break; break;
default: default:
ticode.du1.numRegsDef = 0; ticode.du1 = ICODE::DU1(); // was .numRegsDef = 0
//fprintf(stderr,"Function::liveRegAnalysis : Unknown return type %d, assume 0\n",pcallee->retVal.type); //fprintf(stderr,"Function::liveRegAnalysis : Unknown return type %d, assume 0\n",pcallee->retVal.type);
} /*eos*/ } /*eos*/
@ -377,7 +378,7 @@ void Function::liveRegAnalysis (LivenessSet &in_liveOut)
} }
/* liveIn(b) = liveUse(b) U (liveOut(b) - def(b) */ /* liveIn(b) = liveUse(b) U (liveOut(b) - def(b) */
pbb->liveIn = LivenessSet(pbb->liveUse | (pbb->liveOut & ~pbb->def)); pbb->liveIn = LivenessSet(pbb->liveUse + (pbb->liveOut - pbb->def));
/* Check if live sets have been modified */ /* Check if live sets have been modified */
if ((prevLiveIn != pbb->liveIn) || (prevLiveOut != pbb->liveOut)) if ((prevLiveIn != pbb->liveIn) || (prevLiveOut != pbb->liveOut))
@ -422,10 +423,10 @@ bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
if (checked_icode->type != HIGH_LEVEL) // Only check uses of HIGH_LEVEL icodes if (checked_icode->type != HIGH_LEVEL) // Only check uses of HIGH_LEVEL icodes
continue; continue;
/* if used, get icode index */ /* if used, get icode index */
if ((checked_icode->du.use & duReg[regi]).any()) if ( checked_icode->du.use.testRegAndSubregs(regi) )
start_at->du1.recordUse(defRegIdx,checked_icode.base()); start_at->du1.recordUse(defRegIdx,checked_icode.base());
/* if defined, stop finding uses for this reg */ /* if defined, stop finding uses for this reg */
if ((checked_icode->du.def & duReg[regi]).any()) if (checked_icode->du.def.testRegAndSubregs(regi))
{ {
ticode=checked_icode.base(); ticode=checked_icode.base();
break; break;
@ -435,13 +436,13 @@ bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at)
ticode=(++riICODE(rbegin())).base(); ticode=(++riICODE(rbegin())).base();
/* Check if last definition of this register */ /* Check if last definition of this register */
if ((not (ticode->du.def & duReg[regi]).any()) and (liveOut & duReg[regi]).any()) if (not ticode->du.def.testRegAndSubregs(regi) and liveOut.testRegAndSubregs(regi) )
start_at->du.lastDefRegi.addReg(regi); start_at->du.lastDefRegi.addReg(regi);
} }
else /* only 1 instruction in this basic block */ else /* only 1 instruction in this basic block */
{ {
/* Check if last definition of this register */ /* Check if last definition of this register */
if ((liveOut & duReg[regi]).any()) if ( liveOut.testRegAndSubregs(regi) )
start_at->du.lastDefRegi.addReg(regi); start_at->du.lastDefRegi.addReg(regi);
} }
return false; return false;
@ -460,17 +461,17 @@ void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
for (auto iter=target_instructions.begin(); iter!=target_instructions.end(); ++iter) for (auto iter=target_instructions.begin(); iter!=target_instructions.end(); ++iter)
{ {
/* if used, get icode index */ /* if used, get icode index */
if ((iter->du.use & duReg[regi]).any()) if ( iter->du.use.testRegAndSubregs(regi) )
picode.du1.recordUse(defRegIdx,iter.base()); picode.du1.recordUse(defRegIdx,iter.base());
/* if defined, stop finding uses for this reg */ /* if defined, stop finding uses for this reg */
if ((iter->du.def & duReg[regi]).any()) if (iter->du.def.testRegAndSubregs(regi))
break; break;
} }
/* if not used in this basic block, check if the /* if not used in this basic block, check if the
* register is live out, if so, make it the last * register is live out, if so, make it the last
* definition of this register */ * definition of this register */
if ( picode.du1.used(defRegIdx) && (tbb->liveOut & duReg[regi]).any()) if ( picode.du1.used(defRegIdx) && tbb->liveOut.testRegAndSubregs(regi))
picode.du.lastDefRegi.addReg(regi); picode.du.lastDefRegi.addReg(regi);
} }
} }
@ -484,11 +485,11 @@ void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, ICODE &picode)
void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode) void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode)
{ {
if (picode->valid() and not picode->du1.used(defRegIdx) and if (picode->valid() and not picode->du1.used(defRegIdx) and
(not (picode->du.lastDefRegi & duReg[regi]).any()) && (not picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
(not ((picode->hl()->opcode == HLI_CALL) && (not ((picode->hl()->opcode == HLI_CALL) &&
(picode->hl()->call.proc->flg & PROC_ISLIB)))) (picode->hl()->call.proc->flg & PROC_ISLIB))))
{ {
if (! (this->liveOut & duReg[regi]).any()) /* not liveOut */ if (! (this->liveOut.testRegAndSubregs(regi))) /* not liveOut */
{ {
bool res = picode->removeDefRegi (regi, defRegIdx+1,&Parent->localId); bool res = picode->removeDefRegi (regi, defRegIdx+1,&Parent->localId);
if (res == true) if (res == true)
@ -537,7 +538,7 @@ void BB::genDU1()
defRegIdx++; defRegIdx++;
/* Check if all defined registers have been processed */ /* Check if all defined registers have been processed */
if ((defRegIdx >= picode->du1.numRegsDef) || (defRegIdx == MAX_REGS_DEF)) if ((defRegIdx >= picode->du1.getNumRegsDef()) || (defRegIdx == MAX_REGS_DEF))
break; break;
} }
} }
@ -736,18 +737,18 @@ void LOCAL_ID::processTargetIcode(iICODE picode, int &numHlIcodes, iICODE ticode
{ {
assert(lhs_ident); assert(lhs_ident);
res = Expr::insertSubTreeLongReg ( res = Expr::insertSubTreeLongReg (
p_hl.asgn.rhs, p_hl.asgn.rhs,
t_hl.exp.v, t_hl.exp.v,
lhs_ident->ident.idNode.longIdx); lhs_ident->ident.idNode.longIdx);
} }
else else
{ {
RegisterNode *lhs_reg = dynamic_cast<RegisterNode *>(p_hl.asgn.lhs()); RegisterNode *lhs_reg = dynamic_cast<RegisterNode *>(p_hl.asgn.lhs());
assert(lhs_reg); assert(lhs_reg);
res = Expr::insertSubTreeReg ( res = Expr::insertSubTreeReg (
t_hl.exp.v, t_hl.exp.v,
p_hl.asgn.rhs, p_hl.asgn.rhs,
id_arr[lhs_reg->regiIdx].id.regi, id_arr[lhs_reg->regiIdx].id.regi,
this); this);
} }
if (res) if (res)
@ -848,7 +849,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
{ {
HLTYPE &_icHl(*picode->hlU()); HLTYPE &_icHl(*picode->hlU());
numHlIcodes++; numHlIcodes++;
if (picode->du1.numRegsDef == 1) /* uint8_t/uint16_t regs */ if (picode->du1.getNumRegsDef() == 1) /* uint8_t/uint16_t regs */
{ {
/* Check for only one use of this register. If this is /* Check for only one use of this register. If this is
* the last definition of the register in this BB, check * the last definition of the register in this BB, check
@ -867,7 +868,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
* icode expression */ * icode expression */
ticode = picode->du1.idx[0].uses.front(); ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi & duReg[regi]).any() && if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
((ticode->hl()->opcode != HLI_CALL) && ((ticode->hl()->opcode != HLI_CALL) &&
(ticode->hl()->opcode != HLI_RET))) (ticode->hl()->opcode != HLI_RET)))
continue; continue;
@ -886,7 +887,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
// call F() <- somehow this is marked as user of POP ? // call F() <- somehow this is marked as user of POP ?
ticode = picode->du1.idx[0].uses.front(); ticode = picode->du1.idx[0].uses.front();
ti_hl = ticode->hlU(); ti_hl = ticode->hlU();
if ((picode->du.lastDefRegi & duReg[regi]).any() && if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
((ti_hl->opcode != HLI_CALL) && ((ti_hl->opcode != HLI_CALL) &&
(ti_hl->opcode != HLI_RET))) (ti_hl->opcode != HLI_RET)))
continue; continue;
@ -902,8 +903,8 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
RegisterNode *v = dynamic_cast<RegisterNode *>(_icHl.expr()); RegisterNode *v = dynamic_cast<RegisterNode *>(_icHl.expr());
assert(v); assert(v);
res = Expr::insertSubTreeReg (ti_hl->exp.v, res = Expr::insertSubTreeReg (ti_hl->exp.v,
_exp, _exp,
locals.id_arr[v->regiIdx].id.regi, locals.id_arr[v->regiIdx].id.regi,
&locals); &locals);
if (res) if (res)
{ {
@ -971,7 +972,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
} }
} }
else if (picode->du1.numRegsDef == 2) /* long regs */ else if (picode->du1.getNumRegsDef() == 2) /* long regs */
{ {
/* Check for only one use of these registers */ /* Check for only one use of these registers */
if ((picode->du1.numUses(0) == 1) and (picode->du1.numUses(1) == 1)) if ((picode->du1.numUses(0) == 1) and (picode->du1.numUses(1) == 1))
@ -986,7 +987,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0]) if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
{ {
ticode = picode->du1.idx[0].uses.front(); ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi & duReg[regi]).any() && if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
((ticode->hl()->opcode != HLI_CALL) && ((ticode->hl()->opcode != HLI_CALL) &&
(ticode->hl()->opcode != HLI_RET))) (ticode->hl()->opcode != HLI_RET)))
continue; continue;
@ -998,7 +999,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0]) if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
{ {
ticode = picode->du1.idx[0].uses.front(); ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi & duReg[regi]).any() && if ((picode->du.lastDefRegi.testRegAndSubregs(regi)) &&
((ticode->hl()->opcode != HLI_CALL) && ((ticode->hl()->opcode != HLI_CALL) &&
(ticode->hl()->opcode != HLI_RET))) (ticode->hl()->opcode != HLI_RET)))
continue; continue;
@ -1011,7 +1012,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
break; break;
case HLI_JCOND: case HLI_PUSH: case HLI_JCOND: case HLI_PUSH:
res = Expr::insertSubTreeLongReg (_exp, res = Expr::insertSubTreeLongReg (_exp,
ticode->hlU()->exp.v, ticode->hlU()->exp.v,
dynamic_cast<AstIdent *>(_icHl.asgn.lhs())->ident.idNode.longIdx); dynamic_cast<AstIdent *>(_icHl.asgn.lhs())->ident.idNode.longIdx);
if (res) if (res)
{ {
@ -1034,9 +1035,9 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
case HLI_ASSIGN: case HLI_ASSIGN:
_exp = _icHl.call.toAst(); _exp = _icHl.call.toAst();
ticode->hlU()->asgn.lhs( ticode->hlU()->asgn.lhs(
AstIdent::Long(&locals, DST, AstIdent::Long(&locals, DST,
ticode,HIGH_FIRST, picode.base(), ticode,HIGH_FIRST, picode.base(),
eDEF, *(++iICODE(ticode))->ll())); eDEF, *(++iICODE(ticode))->ll()));
ticode->hlU()->asgn.rhs = _exp; ticode->hlU()->asgn.rhs = _exp;
picode->invalidate(); picode->invalidate();
numHlIcodes--; numHlIcodes--;
@ -1052,9 +1053,8 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
_exp = _icHl.call.toAst(); _exp = _icHl.call.toAst();
_retVal = &picode->hl()->call.proc->retVal; _retVal = &picode->hl()->call.proc->retVal;
res = Expr::insertSubTreeLongReg (_exp, res = Expr::insertSubTreeLongReg (_exp,
ticode->hlU()->exp.v, ticode->hlU()->exp.v,
locals.newLongReg ( _retVal->type, _retVal->id.longId.h, locals.newLongReg ( _retVal->type, _retVal->longId(), picode.base()));
_retVal->id.longId.l, picode.base()));
if (res) /* was substituted */ if (res) /* was substituted */
{ {
picode->invalidate(); picode->invalidate();
@ -1083,8 +1083,8 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
{ {
g_exp_stk.processExpPush(numHlIcodes, picode.base()); g_exp_stk.processExpPush(numHlIcodes, picode.base());
} }
else if(picode->du1.numRegsDef!=0) else if(picode->du1.getNumRegsDef()!=0)
printf("Num def %d\n",picode->du1.numRegsDef); printf("Num def %d\n",picode->du1.getNumRegsDef());
/* For HLI_CALL instructions that use arguments from the stack, /* For HLI_CALL instructions that use arguments from the stack,
* pop them from the expression stack and place them on the * pop them from the expression stack and place them on the
@ -1098,7 +1098,7 @@ void BB::findBBExps(LOCAL_ID &locals,Function *fnc)
/* If we could not substitute the result of a function, /* If we could not substitute the result of a function,
* assign it to the corresponding registers */ * assign it to the corresponding registers */
if ( not _icHl.call.proc->isLibrary() and (not picode->du1.used(0)) and (picode->du1.numRegsDef > 0)) if ( not _icHl.call.proc->isLibrary() and (not picode->du1.used(0)) and (picode->du1.getNumRegsDef() > 0))
{ {
_exp = new FuncNode(_icHl.call.proc, _icHl.call.args); _exp = new FuncNode(_icHl.call.proc, _icHl.call.args);
auto lhs = AstIdent::idID (&_icHl.call.proc->retVal, &locals, picode.base()); auto lhs = AstIdent::idID (&_icHl.call.proc->retVal, &locals, picode.base());
@ -1131,13 +1131,13 @@ void Function::preprocessReturnDU(LivenessSet &_liveOut)
eReg bad_regs[] = {rES,rCS,rDS,rSS}; eReg bad_regs[] = {rES,rCS,rDS,rSS};
constexpr char * names[] ={"ES","CS","DS","SS"}; constexpr char * names[] ={"ES","CS","DS","SS"};
for(int i=0; i<4; ++i) for(int i=0; i<4; ++i)
if(_liveOut.testReg(bad_regs[i])) if(_liveOut.testReg(bad_regs[i]))
{ {
fprintf(stderr,"LivenessSet probably screwed up, %s register as an liveOut in preprocessReturnDU\n",names[i]); fprintf(stderr,"LivenessSet probably screwed up, %s register as an liveOut in preprocessReturnDU\n",names[i]);
_liveOut.clrReg(bad_regs[i]); _liveOut.clrReg(bad_regs[i]);
if(not _liveOut.any()) if(not _liveOut.any())
return; return;
} }
flg |= PROC_IS_FUNC; flg |= PROC_IS_FUNC;
isAx = _liveOut.testReg(rAX); isAx = _liveOut.testReg(rAX);
isBx = _liveOut.testReg(rBX); isBx = _liveOut.testReg(rBX);
@ -1176,9 +1176,8 @@ void Function::preprocessReturnDU(LivenessSet &_liveOut)
{ {
retVal.type = TYPE_LONG_SIGN; retVal.type = TYPE_LONG_SIGN;
retVal.loc = REG_FRAME; retVal.loc = REG_FRAME;
retVal.id.longId.h = rDX; retVal.longId() = LONGID_TYPE(rDX,rAX);
retVal.id.longId.l = rAX; /*idx = */localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), Icode.begin());
/*idx = */localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, Icode.begin()/*0*/);
localId.propLongId (rAX, rDX, "\0"); localId.propLongId (rAX, rDX, "\0");
} }
else if (isAx || isBx || isCx || isDx) /* uint16_t */ else if (isAx || isBx || isCx || isDx) /* uint16_t */

View File

@ -70,7 +70,7 @@ static const char *szFlops3C[] =
static const char *szPtr[2] = { "word ptr ", "byte ptr " }; static const char *szPtr[2] = { "word ptr ", "byte ptr " };
static void formatRM(ostringstream &p, uint32_t flg, const LLOperand &pm); static void formatRM(ostringstream &p, const LLOperand &pm);
static ostringstream &strDst(ostringstream &os, uint32_t flg, const LLOperand &pm); static ostringstream &strDst(ostringstream &os, uint32_t flg, const LLOperand &pm);
static char *strHex(uint32_t d); static char *strHex(uint32_t d);
@ -283,7 +283,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
{ {
case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR: case iADD: case iADC: case iSUB: case iSBB: case iAND: case iOR:
case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG: case iXOR: case iTEST: case iCMP: case iMOV: case iLEA: case iXCHG:
strDst(operands_s,inst.getFlag(), inst.dst); strDst(operands_s,inst.getFlag(), inst.m_dst);
inst.strSrc(operands_s); inst.strSrc(operands_s);
break; break;
@ -293,7 +293,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL: case iSAR: case iSHL: case iSHR: case iRCL: case iRCR: case iROL:
case iROR: case iROR:
strDst(operands_s,inst.getFlag() | I, inst.dst); strDst(operands_s,inst.getFlag() | I, inst.m_dst);
if(inst.testFlags(I)) if(inst.testFlags(I))
inst.strSrc(operands_s); inst.strSrc(operands_s);
else else
@ -301,7 +301,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
break; break;
case iINC: case iDEC: case iNEG: case iNOT: case iPOP: case iINC: case iDEC: case iNEG: case iNOT: case iPOP:
strDst(operands_s,inst.getFlag() | I, inst.dst); strDst(operands_s,inst.getFlag() | I, inst.m_dst);
break; break;
case iPUSH: case iPUSH:
@ -311,15 +311,15 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
} }
else else
{ {
strDst(operands_s,inst.getFlag() | I, inst.dst); strDst(operands_s,inst.getFlag() | I, inst.m_dst);
} }
break; break;
case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD: case iDIV: case iIDIV: case iMUL: case iIMUL: case iMOD:
if (inst.testFlags(I)) if (inst.testFlags(I))
{ {
strDst(operands_s,inst.getFlag(), inst.dst) <<", "; strDst(operands_s,inst.getFlag(), inst.m_dst) <<", ";
formatRM(operands_s, inst.getFlag(), inst.src()); formatRM(operands_s, inst.src());
inst.strSrc(operands_s); inst.strSrc(operands_s);
} }
else else
@ -327,7 +327,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
break; break;
case iLDS: case iLES: case iBOUND: case iLDS: case iLES: case iBOUND:
strDst(operands_s,inst.getFlag(), inst.dst)<<", dword ptr"; strDst(operands_s,inst.getFlag(), inst.m_dst)<<", dword ptr";
inst.strSrc(operands_s,true); inst.strSrc(operands_s,true);
break; break;
@ -397,8 +397,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
break; break;
case iENTER: case iENTER:
operands_s<<strHex(inst.dst.off)<<", "; operands_s<<strHex(inst.m_dst.off) << ", " << strHex(inst.src().getImm2());
operands_s<<strHex(inst.src().getImm2());
break; break;
case iRET: case iRETF: case iINT: case iRET: case iRETF: case iINT:
@ -552,7 +551,7 @@ void Disassembler::dis1Line(LLInst &inst,int loc_ip, int pass)
/**************************************************************************** /****************************************************************************
* formatRM * formatRM
***************************************************************************/ ***************************************************************************/
static void formatRM(std::ostringstream &p, uint32_t /*flg*/, const LLOperand &pm) static void formatRM(std::ostringstream &p, const LLOperand &pm)
{ {
//char seg[4]; //char seg[4];
@ -595,7 +594,7 @@ static ostringstream & strDst(ostringstream &os,uint32_t flg, const LLOperand &p
//os << setw(WID_PTR); //os << setw(WID_PTR);
if ((flg & I) and not pm.isReg()) if ((flg & I) and not pm.isReg())
os << szPtr[flg & B]; os << szPtr[flg & B];
formatRM(os, flg, pm); formatRM(os, pm);
return os; return os;
} }
@ -612,7 +611,7 @@ ostringstream &LLInst::strSrc(ostringstream &os,bool skip_comma)
else if (testFlags(IM_SRC)) /* level 2 */ else if (testFlags(IM_SRC)) /* level 2 */
os<<"dx:ax"; os<<"dx:ax";
else else
formatRM(os, getFlag(), src()); formatRM(os, src());
return os; return os;
} }
@ -649,7 +648,7 @@ void LLInst::flops(std::ostringstream &out)
/* Note that op is set to the escape number, e.g. /* Note that op is set to the escape number, e.g.
esc 0x38 is FILD */ esc 0x38 is FILD */
if ( not dst.isReg() ) if ( not m_dst.isReg() )
{ {
/* The mod/rm mod bits are not set to 11 (i.e. register). This is the normal floating point opcode */ /* The mod/rm mod bits are not set to 11 (i.e. register). This is the normal floating point opcode */
out<<Machine_X86::floatOpName(op)<<' '; out<<Machine_X86::floatOpName(op)<<' ';
@ -685,7 +684,7 @@ void LLInst::flops(std::ostringstream &out)
} }
} }
formatRM(out, getFlag(), dst); formatRM(out, m_dst);
} }
else else
{ {
@ -694,7 +693,7 @@ void LLInst::flops(std::ostringstream &out)
normal opcodes. Because the opcodes are slightly different for normal opcodes. Because the opcodes are slightly different for
this case (e.g. op=04 means FSUB if reg != 3, but FSUBR for this case (e.g. op=04 means FSUB if reg != 3, but FSUBR for
reg == 3), a separate table is used (szFlops2). */ reg == 3), a separate table is used (szFlops2). */
int destRegIdx=dst.regi - rAX; int destRegIdx=m_dst.regi - rAX;
switch (op) switch (op)
{ {
case 0x0C: case 0x0C:

View File

@ -11,27 +11,6 @@
#include "dcc.h" #include "dcc.h"
using namespace std; using namespace std;
/* Masks off bits set by duReg[] */
LivenessSet maskDuReg[] = { 0x00,
/* uint16_t regs */
0xFEEFFE, //rAX
0xFDDFFD, //rCX
0xFBB00B, //rDX
0xF77007, //rBX
0xFFFFEF, //rSP
0xFFFFDF, //rBP
0xFFFFBF, //rSI
0xFFFF7F, //rDI
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 };
static char buf[lineSize]; /* Line buffer for hl icode output */ static char buf[lineSize]; /* Line buffer for hl icode output */
@ -98,13 +77,13 @@ bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
{ {
int numDefs; int numDefs;
numDefs = du1.numRegsDef; numDefs = du1.getNumRegsDef();
if (numDefs == thisDefIdx) if (numDefs == thisDefIdx)
{ {
for ( ; numDefs > 0; numDefs--) for ( ; numDefs > 0; numDefs--)
{ {
if (du1.used(numDefs-1)||(du.lastDefRegi[regi])) if (du1.used(numDefs-1)||(du.lastDefRegi.testReg(regi)))
break; break;
} }
} }
@ -117,8 +96,9 @@ bool ICODE::removeDefRegi (eReg regi, int thisDefIdx, LOCAL_ID *locId)
HlTypeSupport *p=hlU()->get(); HlTypeSupport *p=hlU()->get();
if(p and p->removeRegFromLong(regi,locId)) if(p and p->removeRegFromLong(regi,locId))
{ {
du1.numRegsDef--; du1.removeDef(regi); //du1.numRegsDef--;
du.def &= maskDuReg[regi]; //du.def &= maskDuReg[regi];
du.def.clrReg(regi);
} }
return false; return false;
} }
@ -285,6 +265,41 @@ HLTYPE LLInst::toHighLevel(COND_EXPR *lhs,COND_EXPR *rhs,Function *func)
return res; return res;
} }
#endif #endif
static bool needsLhs(unsigned opc)
{
switch (opc)
{
case iCALL:
case iCALLF:
case iRET:
case iRETF:
default: return false;
case iADD:
case iAND:
case iDEC:
case iDIV:
case iIDIV:/* should be signed div */
case iIMUL:
case iINC:
case iLEA:
case iMOD:
case iMOV:
case iMUL:
case iNEG:
case iNOT:
case iOR:
case iPOP:
case iPUSH:
case iSHL:
case iSAR: /* signed */
case iSHR:
case iSIGNEX:
case iSUB:
case iXCHG:
case iXOR:
return true;
}
}
/* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage. /* Translates LOW_LEVEL icodes to HIGH_LEVEL icodes - 1st stage.
* Note: this process should be done before data flow analysis, which * Note: this process should be done before data flow analysis, which
* refines the HIGH_LEVEL icodes. */ * refines the HIGH_LEVEL icodes. */
@ -292,12 +307,12 @@ void Function::highLevelGen()
{ {
size_t numIcode; /* number of icode instructions */ size_t numIcode; /* number of icode instructions */
iICODE pIcode; /* ptr to current icode node */ iICODE pIcode; /* ptr to current icode node */
Expr *lhs;
Expr *rhs; /* left- and right-hand side of expression */ Expr *rhs; /* left- and right-hand side of expression */
uint32_t _flg; /* icode flags */ uint32_t _flg; /* icode flags */
numIcode = Icode.size(); numIcode = Icode.size();
for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i) for (iICODE i = Icode.begin(); i!=Icode.end() ; ++i)
{ {
Expr *lhs=nullptr;
assert(numIcode==Icode.size()); assert(numIcode==Icode.size());
pIcode = i; //Icode.GetIcode(i) pIcode = i; //Icode.GetIcode(i)
LLInst *ll = pIcode->ll(); LLInst *ll = pIcode->ll();
@ -306,13 +321,16 @@ void Function::highLevelGen()
if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() ) if ((pIcode->type != LOW_LEVEL) or not pIcode->valid() )
continue; continue;
_flg = ll->getFlag(); _flg = ll->getFlag();
if ((_flg & IM_OPS) != IM_OPS) /* not processing IM_OPS yet */ if (not ll->testFlags(IM_OPS)) /* not processing IM_OPS yet */
if ((_flg & NO_OPS) != NO_OPS) /* if there are opers */ if ( not ll->testFlags(NO_OPS) ) /* if there are opers */
{ {
if ( not ll->testFlags(NO_SRC) ) /* if there is src op */ if ( not ll->testFlags(NO_SRC) ) /* if there is src op */
rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE); rhs = AstIdent::id (*pIcode->ll(), SRC, this, i, *pIcode, NONE);
if(ll->m_dst.isSet() || (ll->getOpcode()==iMOD))
lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE); lhs = AstIdent::id (*pIcode->ll(), DST, this, i, *pIcode, NONE);
} }
if(needsLhs(ll->getOpcode()))
assert(lhs!=nullptr);
switch (ll->getOpcode()) switch (ll->getOpcode())
{ {
case iADD: case iADD:
@ -406,10 +424,12 @@ void Function::highLevelGen()
pIcode->setAsgn(lhs, rhs); pIcode->setAsgn(lhs, rhs);
break; break;
case iPOP: pIcode->setUnary(HLI_POP, lhs); case iPOP:
pIcode->setUnary(HLI_POP, lhs);
break; break;
case iPUSH: pIcode->setUnary(HLI_PUSH, lhs); case iPUSH:
pIcode->setUnary(HLI_PUSH, lhs);
break; break;
case iRET: case iRET:
@ -613,7 +633,7 @@ void ICODE::writeDU()
} }
/* Print du1 chain */ /* Print du1 chain */
printf ("# regs defined = %d\n", du1.numRegsDef); printf ("# regs defined = %d\n", du1.getNumRegsDef());
for (int i = 0; i < MAX_REGS_DEF; i++) for (int i = 0; i < MAX_REGS_DEF; i++)
{ {
if (not du1.used(i)) if (not du1.used(i))

View File

@ -122,7 +122,7 @@ void Function::findIdioms()
{ {
if ((pIcode->ll()->src().proc.proc->retVal.type==TYPE_LONG_SIGN) if ((pIcode->ll()->src().proc.proc->retVal.type==TYPE_LONG_SIGN)
|| (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN)) || (pIcode->ll()->src().proc.proc->retVal.type == TYPE_LONG_UNSIGN))
localId.newLongReg(TYPE_LONG_SIGN, rDX, rAX, pIcode/*ip*/); localId.newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(rDX,rAX), pIcode/*ip*/);
} }
/* Check for idioms */ /* Check for idioms */

View File

@ -102,20 +102,20 @@ bool Idiom18::match(iICODE picode)
m_is_dec = m_icodes[1]->ll()->match(iDEC); m_is_dec = m_icodes[1]->ll()->match(iDEC);
uint8_t regi; /* register of the MOV */ uint8_t regi; /* register of the MOV */
if(not (m_icodes[0]->ll()->match(iMOV) and m_icodes[0]->ll()->dst.isReg() )) if(not m_icodes[0]->ll()->matchWithRegDst(iMOV) )
return false; return false;
regi = m_icodes[0]->ll()->dst.regi; regi = m_icodes[0]->ll()->m_dst.regi;
if( not ( m_icodes[2]->ll()->match(iCMP) && (m_icodes[2]->ll()->dst.regi == regi) && if( not ( m_icodes[2]->ll()->match(iCMP,regi) &&
m_icodes[3]->ll()->conditionalJump() ) ) m_icodes[3]->ll()->conditionalJump() ) )
return false; return false;
// Simple matching finished, select apropriate matcher based on dst type // Simple matching finished, select apropriate matcher based on dst type
/* Get variable */ /* Get variable */
if (m_icodes[1]->ll()->dst.regi == 0) /* global variable */ if (m_icodes[1]->ll()->m_dst.regi == 0) /* global variable */
{ {
/* not supported yet */ /* not supported yet */
m_idiom_type = 0; m_idiom_type = 0;
} }
else if ( m_icodes[1]->ll()->dst.isReg() ) /* register */ else if ( m_icodes[1]->ll()->m_dst.isReg() ) /* register */
{ {
m_idiom_type = 1; m_idiom_type = 1;
// if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR)) // if ((m_icodes[1]->ll()->dst.regi == rSI) && (m_func->flg & SI_REGVAR))
@ -123,7 +123,7 @@ bool Idiom18::match(iICODE picode)
// else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR)) // else if ((m_icodes[1]->ll()->dst.regi == rDI) && (m_func->flg & DI_REGVAR))
// m_idiom_type = 1; // m_idiom_type = 1;
} }
else if (m_icodes[1]->ll()->dst.off) /* local variable */ else if (m_icodes[1]->ll()->m_dst.off) /* local variable */
m_idiom_type = 2; m_idiom_type = 2;
else /* indexed */ else /* indexed */
{ {
@ -141,20 +141,20 @@ bool Idiom18::match(iICODE picode)
break; break;
case 1: /* register variable */ case 1: /* register variable */
/* Check previous instruction for a MOV */ /* Check previous instruction for a MOV */
if ( (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->dst.regi)) if ( (m_icodes[0]->ll()->src().regi == m_icodes[1]->ll()->m_dst.regi))
{ {
return true; return true;
} }
break; break;
case 2: /* local */ case 2: /* local */
if ((m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->dst.off)) if ((m_icodes[0]->ll()->src().off == m_icodes[1]->ll()->m_dst.off))
{ {
return true; return true;
} }
break; break;
case 3: // indexed case 3: // indexed
printf("Untested idiom18 type: indexed\n"); printf("Untested idiom18 type: indexed\n");
if ((m_icodes[0]->ll()->src() == m_icodes[1]->ll()->dst)) if ((m_icodes[0]->ll()->src() == m_icodes[1]->ll()->m_dst))
{ {
return true; return true;
} }
@ -200,15 +200,15 @@ bool Idiom19::match(iICODE picode)
m_is_dec = m_icodes[0]->ll()->match(iDEC); m_is_dec = m_icodes[0]->ll()->match(iDEC);
if ( not m_icodes[1]->ll()->conditionalJump() ) if ( not m_icodes[1]->ll()->conditionalJump() )
return false; return false;
if (m_icodes[0]->ll()->dst.regi == 0) /* global variable */ if (m_icodes[0]->ll()->m_dst.regi == 0) /* global variable */
/* not supported yet */ ; /* not supported yet */ ;
else if ( m_icodes[0]->ll()->dst.isReg() ) /* register */ else if ( m_icodes[0]->ll()->m_dst.isReg() ) /* register */
{ {
// if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) || // if (((picode->ll()->dst.regi == rSI) && (pproc->flg & SI_REGVAR)) ||
// ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR))) // ((picode->ll()->dst.regi == rDI) && (pproc->flg & DI_REGVAR)))
return true; return true;
} }
else if (m_icodes[0]->ll()->dst.off) /* stack variable */ else if (m_icodes[0]->ll()->m_dst.off) /* stack variable */
{ {
return true; return true;
} }
@ -257,12 +257,12 @@ bool Idiom20::match(iICODE picode)
for(int i=0; i<4; ++i) for(int i=0; i<4; ++i)
m_icodes[i] =picode++; m_icodes[i] =picode++;
/* Check second instruction for a MOV */ /* Check second instruction for a MOV */
if(not (m_icodes[1]->ll()->match(iMOV) && m_icodes[1]->ll()->dst.isReg())) if( not m_icodes[1]->ll()->matchWithRegDst(iMOV) )
return false; return false;
m_is_dec = m_icodes[0]->ll()->match(iDEC) ? PRE_DEC : PRE_INC; m_is_dec = m_icodes[0]->ll()->match(iDEC) ? PRE_DEC : PRE_INC;
LLOperand &ll_dest(m_icodes[0]->ll()->dst); const LLOperand &ll_dest(m_icodes[0]->ll()->m_dst);
/* Get variable */ /* Get variable */
if (ll_dest.regi == 0) /* global variable */ if (ll_dest.regi == 0) /* global variable */
{ {
@ -284,7 +284,7 @@ bool Idiom20::match(iICODE picode)
type = 3; type = 3;
/* not supported yet */ ; /* not supported yet */ ;
} }
regi = m_icodes[1]->ll()->dst.regi; regi = m_icodes[1]->ll()->m_dst.regi;
const LLOperand &mov_src(m_icodes[1]->ll()->src()); const LLOperand &mov_src(m_icodes[1]->ll()->src());
if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) && m_icodes[3]->ll()->conditionalJump()) if (m_icodes[2]->ll()->match(iCMP,(eReg)regi) && m_icodes[3]->ll()->conditionalJump())
{ {

View File

@ -77,13 +77,13 @@ bool Idiom17::match(iICODE picode)
if (m_icodes[1]->ll()->match(iPOP)) if (m_icodes[1]->ll()->match(iPOP))
{ {
int i=0; int i=0;
regi = m_icodes[1]->ll()->dst.regi; regi = m_icodes[1]->ll()->m_dst.regi;
if ((regi >= rAX) && (regi <= rBX)) if ((regi >= rAX) && (regi <= rBX))
i++; i++;
while (picode != m_end && picode->ll()->match(iPOP)) while (picode != m_end && picode->ll()->match(iPOP))
{ {
if (picode->ll()->dst.regi != regi) if (picode->ll()->m_dst.regi != regi)
break; break;
i++; i++;
m_icodes.push_back(picode++); m_icodes.push_back(picode++);

View File

@ -28,13 +28,13 @@ bool Idiom14::match(iICODE pIcode)
m_icodes[0]=pIcode++; m_icodes[0]=pIcode++;
m_icodes[1]=pIcode++; m_icodes[1]=pIcode++;
/* Check for regL */ /* Check for regL */
m_regL = m_icodes[0]->ll()->dst.regi; m_regL = m_icodes[0]->ll()->m_dst.regi;
if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX))) if (not m_icodes[0]->ll()->testFlags(I) && ((m_regL == rAX) || (m_regL ==rBX)))
{ {
/* Check for XOR regH, regH */ /* Check for XOR regH, regH */
if (m_icodes[1]->ll()->match(iXOR) && not m_icodes[1]->ll()->testFlags(I)) if (m_icodes[1]->ll()->match(iXOR) && not m_icodes[1]->ll()->testFlags(I))
{ {
m_regH = m_icodes[1]->ll()->dst.regi; m_regH = m_icodes[1]->ll()->m_dst.regi;
if (m_regH == m_icodes[1]->ll()->src().getReg2()) if (m_regH == m_icodes[1]->ll()->src().getReg2())
{ {
if ((m_regL == rAX) && (m_regH == rDX)) if ((m_regL == rAX) && (m_regH == rDX))
@ -52,7 +52,7 @@ int Idiom14::action()
AstIdent *lhs; AstIdent *lhs;
Expr *rhs; Expr *rhs;
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, m_regH, m_regL, m_icodes[0]); idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(m_regH,m_regL), m_icodes[0]);
lhs = AstIdent::LongIdx (idx); lhs = AstIdent::LongIdx (idx);
m_icodes[0]->setRegDU( m_regH, eDEF); m_icodes[0]->setRegDU( m_regH, eDEF);
rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE); rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
@ -82,13 +82,13 @@ bool Idiom13::match(iICODE pIcode)
eReg regi; eReg regi;
/* Check for regL */ /* Check for regL */
regi = m_icodes[0]->ll()->dst.regi; regi = m_icodes[0]->ll()->m_dst.regi;
if (not m_icodes[0]->ll()->testFlags(I) && (regi >= rAL) && (regi <= rBH)) if (not m_icodes[0]->ll()->testFlags(I) && (regi >= rAL) && (regi <= rBH))
{ {
/* Check for MOV regH, 0 */ /* 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()->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. if (m_icodes[1]->ll()->m_dst.regi == (regi + 4)) //WARNING: based on distance between AH-AL,BH-BL etc.
{ {
m_loaded_reg=(eReg)(regi - rAL + rAX); m_loaded_reg=(eReg)(regi - rAL + rAX);
return true; return true;
@ -102,9 +102,11 @@ int Idiom13::action()
{ {
AstIdent *lhs; AstIdent *lhs;
Expr *rhs; Expr *rhs;
eReg regi = m_icodes[0]->ll()->m_dst.regi;
m_icodes[0]->du1.removeDef(regi);
//m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */
lhs = new RegisterNode(m_loaded_reg, 0, &m_func->localId); lhs = new RegisterNode(m_loaded_reg, 0, &m_func->localId);
m_icodes[0]->setRegDU( m_loaded_reg, eDEF); m_icodes[0]->setRegDU( m_loaded_reg, eDEF);
m_icodes[0]->du1.numRegsDef--; /* prev uint8_t reg def */
rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE); rhs = AstIdent::id (*m_icodes[0]->ll(), SRC, m_func, m_icodes[0], *m_icodes[0], NONE);
m_icodes[0]->setAsgn(lhs, rhs); m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate(); m_icodes[1]->invalidate();

View File

@ -32,17 +32,17 @@ bool Idiom11::match (iICODE picode)
switch (type) switch (type)
{ {
case GLOB_VAR: case GLOB_VAR:
if ((m_icodes[2]->ll()->dst.segValue == m_icodes[0]->ll()->dst.segValue) && if ((m_icodes[2]->ll()->m_dst.segValue == m_icodes[0]->ll()->m_dst.segValue) &&
(m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off)) (m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off))
return true; return true;
break; break;
case REGISTER: case REGISTER:
if (m_icodes[2]->ll()->dst.regi == m_icodes[0]->ll()->dst.regi) if (m_icodes[2]->ll()->m_dst.regi == m_icodes[0]->ll()->m_dst.regi)
return true; return true;
break; break;
case PARAM: case PARAM:
case LOCAL_VAR: case LOCAL_VAR:
if (m_icodes[2]->ll()->dst.off == m_icodes[0]->ll()->dst.off) if (m_icodes[2]->ll()->m_dst.off == m_icodes[0]->ll()->m_dst.off)
return true; return true;
break; break;
default: default:
@ -82,11 +82,11 @@ bool Idiom16::match (iICODE picode)
for(int i=0; i<3; ++i) for(int i=0; i<3; ++i)
m_icodes[i]=picode++; m_icodes[i]=picode++;
uint8_t regi = m_icodes[0]->ll()->dst.regi; uint8_t regi = m_icodes[0]->ll()->m_dst.regi;
if ((regi >= rAX) && (regi < INDEX_BX_SI)) 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()->match(iSBB) && m_icodes[2]->ll()->match(iINC))
if ((m_icodes[1]->ll()->dst.regi == (m_icodes[1]->ll()->src().getReg2())) && if ((m_icodes[1]->ll()->m_dst.regi == (m_icodes[1]->ll()->src().getReg2())) &&
m_icodes[1]->ll()->match((eReg)regi) && m_icodes[1]->ll()->match((eReg)regi) &&
m_icodes[2]->ll()->match((eReg)regi)) m_icodes[2]->ll()->match((eReg)regi))
return true; return true;
@ -97,7 +97,7 @@ int Idiom16::action()
{ {
AstIdent *lhs; AstIdent *lhs;
Expr *rhs; Expr *rhs;
lhs = new RegisterNode(m_icodes[0]->ll()->dst.regi, m_icodes[0]->ll()->getFlag(),&m_func->localId); lhs = new RegisterNode(m_icodes[0]->ll()->m_dst.regi, m_icodes[0]->ll()->getFlag(),&m_func->localId);
rhs = UnaryOperator::Create(NEGATION, lhs->clone()); rhs = UnaryOperator::Create(NEGATION, lhs->clone());
m_icodes[0]->setAsgn(lhs, rhs); m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[1]->invalidate(); m_icodes[1]->invalidate();

View File

@ -31,9 +31,9 @@ int Idiom8::action()
AstIdent *lhs; AstIdent *lhs;
Expr *expr; Expr *expr;
eReg regH,regL; eReg regH,regL;
regH=m_icodes[0]->ll()->dst.regi; regH=m_icodes[0]->ll()->m_dst.regi;
regL=m_icodes[1]->ll()->dst.regi; regL=m_icodes[1]->ll()->m_dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, regH, regL, m_icodes[0]); idx = m_func->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(regH,regL), m_icodes[0]);
lhs = AstIdent::LongIdx (idx); lhs = AstIdent::LongIdx (idx);
m_icodes[0]->setRegDU( regL, USE_DEF); m_icodes[0]->setRegDU( regL, USE_DEF);
@ -65,7 +65,7 @@ bool Idiom15::match(iICODE pIcode)
if (not pIcode->ll()->testFlags(I) or (pIcode->ll()->src().getImm2() != 1)) if (not pIcode->ll()->testFlags(I) or (pIcode->ll()->src().getImm2() != 1))
return false; return false;
m_icodes.clear(); m_icodes.clear();
regi = pIcode->ll()->dst.regi; regi = pIcode->ll()->m_dst.regi;
m_icodes.push_back(pIcode++); m_icodes.push_back(pIcode++);
while( (pIcode!=m_end) and while( (pIcode!=m_end) and
pIcode->ll()->match(iSHL,(eReg)regi,I) and pIcode->ll()->match(iSHL,(eReg)regi,I) and
@ -81,7 +81,7 @@ int Idiom15::action()
AstIdent *lhs; AstIdent *lhs;
Expr *rhs,*_exp; Expr *rhs,*_exp;
lhs = new RegisterNode(m_icodes[0]->ll()->dst.regi, lhs = new RegisterNode(m_icodes[0]->ll()->m_dst.regi,
m_icodes[0]->ll()->getFlag() & NO_SRC_B, m_icodes[0]->ll()->getFlag() & NO_SRC_B,
&m_func->localId); &m_func->localId);
rhs = new Constant(m_icodes.size(), 2); rhs = new Constant(m_icodes.size(), 2);
@ -122,10 +122,10 @@ int Idiom12::action()
AstIdent *lhs; AstIdent *lhs;
eReg regH,regL; eReg regH,regL;
regL=m_icodes[0]->ll()->dst.regi; regL=m_icodes[0]->ll()->m_dst.regi;
regH=m_icodes[1]->ll()->dst.regi; regH=m_icodes[1]->ll()->m_dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, regH, regL,m_icodes[0]); idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN, LONGID_TYPE(regH,regL),m_icodes[0]);
lhs = AstIdent::LongIdx (idx); lhs = AstIdent::LongIdx (idx);
m_icodes[0]->setRegDU( regH, USE_DEF); m_icodes[0]->setRegDU( regH, USE_DEF);
expr = new BinaryOperator(SHL,lhs, new Constant(1, 2)); expr = new BinaryOperator(SHL,lhs, new Constant(1, 2));
@ -161,9 +161,9 @@ int Idiom9::action()
AstIdent *lhs; AstIdent *lhs;
Expr *rhs,*expr; Expr *rhs,*expr;
eReg regH,regL; eReg regH,regL;
regL=m_icodes[1]->ll()->dst.regi; regL=m_icodes[1]->ll()->m_dst.regi;
regH=m_icodes[0]->ll()->dst.regi; regH=m_icodes[0]->ll()->m_dst.regi;
idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,regH,regL,m_icodes[0]); idx = m_func->localId.newLongReg (TYPE_LONG_UNSIGN,LONGID_TYPE(regH,regL),m_icodes[0]);
lhs = AstIdent::LongIdx (idx); lhs = AstIdent::LongIdx (idx);
m_icodes[0]->setRegDU(regL, USE_DEF); m_icodes[0]->setRegDU(regL, USE_DEF);
expr = new BinaryOperator(SHR,lhs, new Constant(1, 2)); expr = new BinaryOperator(SHR,lhs, new Constant(1, 2));

View File

@ -26,7 +26,7 @@ bool Idiom21::match (iICODE picode)
if (not m_icodes[1]->ll()->testFlags(I)) if (not m_icodes[1]->ll()->testFlags(I))
return false; return false;
dst = &m_icodes[0]->ll()->dst; dst = &m_icodes[0]->ll()->m_dst;
src = &m_icodes[0]->ll()->src(); src = &m_icodes[0]->ll()->src();
if ((dst->regi == src->getReg2()) && (dst->getReg2() > 0) && (dst->getReg2() < INDEX_BX_SI)) if ((dst->regi == src->getReg2()) && (dst->getReg2() > 0) && (dst->getReg2() < INDEX_BX_SI))
{ {
@ -45,7 +45,7 @@ int Idiom21::action()
lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll()); lhs = AstIdent::Long (&m_func->localId, DST, m_icodes[0],HIGH_FIRST, m_icodes[0], eDEF, *m_icodes[1]->ll());
rhs = new Constant(m_icodes[1]->ll()->src().getImm2(), 4); rhs = new Constant(m_icodes[1]->ll()->src().getImm2(), 4);
m_icodes[0]->setAsgn(lhs, rhs); m_icodes[0]->setAsgn(lhs, rhs);
m_icodes[0]->du.use = 0; /* clear register used in iXOR */ m_icodes[0]->du.use.reset(); /* clear register used in iXOR */
m_icodes[1]->invalidate(); m_icodes[1]->invalidate();
return 2; return 2;
} }
@ -63,7 +63,7 @@ bool Idiom7::match(iICODE picode)
return false; return false;
const LLOperand *dst, *src; const LLOperand *dst, *src;
m_icode=picode; m_icode=picode;
dst = &picode->ll()->dst; dst = &picode->ll()->m_dst;
src = &picode->ll()->src(); src = &picode->ll()->src();
if (dst->regi == 0) /* global variable */ if (dst->regi == 0) /* global variable */
{ {
@ -87,7 +87,7 @@ int Idiom7::action()
Expr *lhs; Expr *lhs;
lhs = AstIdent::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE); lhs = AstIdent::id (*m_icode->ll(), DST, m_func, m_icode, *m_icode, NONE);
m_icode->setAsgn(dynamic_cast<AstIdent *>(lhs), new Constant(0, 2)); m_icode->setAsgn(dynamic_cast<AstIdent *>(lhs), new Constant(0, 2));
m_icode->du.use = 0; /* clear register used in iXOR */ m_icode->du.use.reset(); /* clear register used in iXOR */
m_icode->ll()->setFlags(I); m_icode->ll()->setFlags(I);
return 1; return 1;
} }
@ -116,7 +116,7 @@ bool Idiom10::match(iICODE pIcode)
/* Check OR reg, reg */ /* Check OR reg, reg */
if (not m_icodes[0]->ll()->testFlags(I) && if (not m_icodes[0]->ll()->testFlags(I) &&
m_icodes[0]->ll()->src().isReg() && m_icodes[0]->ll()->src().isReg() &&
(m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->dst.getReg2())) (m_icodes[0]->ll()->src().getReg2() == m_icodes[0]->ll()->m_dst.getReg2()))
if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump() if (m_icodes[1]->ll()->match(iJNE)) //.conditionalJump()
{ {
return true; return true;
@ -128,8 +128,9 @@ int Idiom10::action()
{ {
m_icodes[0]->ll()->set(iCMP,I); m_icodes[0]->ll()->set(iCMP,I);
m_icodes[0]->ll()->replaceSrc(LLOperand::CreateImm2(0)); m_icodes[0]->ll()->replaceSrc(LLOperand::CreateImm2(0));
m_icodes[0]->du.def = 0; m_icodes[0]->du.def.reset(); //TODO: this defines FLAGS
m_icodes[0]->du1.numRegsDef = 0; m_icodes[0]->du1.clearAllDefs();
//m_icodes[0]->du1.numRegsDef = 0;
return 2; return 2;
} }

View File

@ -10,10 +10,9 @@
#include "dcc.h" #include "dcc.h"
bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const
{ {
return (a->ll()->src().getReg2()==l) and (b->ll()->dst.getReg2()==h); return (a->ll()->src().getReg2()==m_l) and (b->ll()->m_dst.getReg2()==m_h);
} }
ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false) ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false)
{ {
macro[0]=0; macro[0]=0;
@ -24,6 +23,32 @@ ID::ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
macro[0]=0; macro[0]=0;
memset(&id,0,sizeof(id)); memset(&id,0,sizeof(id));
loc=f; loc=f;
assert(not ((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN)));
}
ID::ID(hlType t,const LONGID_TYPE &s) : type(t),illegal(false),hasMacro(false)
{
macro[0]=0;
memset(&id,0,sizeof(id));
loc=REG_FRAME;
m_longId = s;
assert((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN));
}
ID::ID(hlType t,const LONG_STKID_TYPE &s) : type(t),illegal(false),hasMacro(false)
{
macro[0]=0;
memset(&id,0,sizeof(id));
loc=STK_FRAME;
id.longStkId = s;
assert((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN));
}
ID::ID(hlType t, const LONGGLB_TYPE &s)
{
macro[0]=0;
memset(&id,0,sizeof(id));
loc=GLB_FRAME;
id.longGlb = s;
assert((t==TYPE_LONG_SIGN)||(t==TYPE_LONG_UNSIGN));
} }
@ -142,17 +167,22 @@ int LOCAL_ID::newIntIdx(int16_t seg, int16_t off, eReg regi, hlType t)
/* Checks if the entry exists in the locSym, if so, returns the idx to this /* 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. */ * TYPE_LONG_(UN)SIGN and returns the index to this new entry. */
int LOCAL_ID::newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_) int LOCAL_ID::newLongReg(hlType t, const LONGID_TYPE &longT, iICODE ix_)
{ {
eReg regH,regL;
regL = longT.l();
regH = longT.h();
size_t idx; size_t idx;
//iICODE ix_; //iICODE ix_;
/* Check for entry in the table */ /* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++) for (idx = 0; idx < id_arr.size(); idx++)
{ {
ID &entry(id_arr[idx]); ID &entry(id_arr[idx]);
if(!entry.isLong() || (entry.loc != REG_FRAME))
continue;
if (/*(locSym->id[idx].type == t) && Not checking type */ if (/*(locSym->id[idx].type == t) && Not checking type */
(entry.id.longId.h == regH) && (entry.longId().h() == regH) &&
(entry.id.longId.l == regL)) (entry.longId().l() == regL))
{ {
/* Check for occurrence in the list */ /* Check for occurrence in the list */
if (entry.idx.inList(ix_)) if (entry.idx.inList(ix_))
@ -167,12 +197,9 @@ int LOCAL_ID::newLongReg(hlType t, eReg regH, eReg regL, iICODE ix_)
} }
/* Not in the table, create new identifier */ /* Not in the table, create new identifier */
newIdent (t, REG_FRAME); id_arr.push_back(ID(t, LONGID_TYPE(regH,regL)));
id_arr[id_arr.size()-1].idx.push_back(ix_); id_arr.back().idx.push_back(ix_);
idx = id_arr.size() - 1; return (id_arr.size() - 1);
id_arr[idx].id.longId.h = regH;
id_arr[idx].id.longId.l = regL;
return (idx);
} }
/* Returns an identifier conditional expression node of type TYPE_LONG or /* Returns an identifier conditional expression node of type TYPE_LONG or
* TYPE_WORD_SIGN */ * TYPE_WORD_SIGN */
@ -199,12 +226,9 @@ int LOCAL_ID::newLongGlb(int16_t seg, int16_t offH, int16_t offL,hlType t)
} }
/* Not in the table, create new identifier */ /* Not in the table, create new identifier */
newIdent (t, GLB_FRAME); id_arr.push_back(ID(t, LONGGLB_TYPE(seg,offH,offL)));
idx = id_arr.size() - 1; return (id_arr.size() - 1);
id_arr[idx].id.longGlb.seg = seg;
id_arr[idx].id.longGlb.offH = offH;
id_arr[idx].id.longGlb.offL = offL;
return (idx);
} }
@ -246,9 +270,11 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
/* Check for entry in the table */ /* Check for entry in the table */
for (idx = 0; idx < id_arr.size(); idx++) for (idx = 0; idx < id_arr.size(); idx++)
{ {
if(id_arr[idx].loc!=STK_FRAME)
continue;
if ((id_arr[idx].type == t) && if ((id_arr[idx].type == t) &&
(id_arr[idx].id.longStkId.offH == offH) && (id_arr[idx].longStkId().offH == offH) &&
(id_arr[idx].id.longStkId.offL == offL)) (id_arr[idx].longStkId().offL == offL))
return (idx); return (idx);
} }
@ -257,11 +283,8 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL)
flagByteWordId (offL); flagByteWordId (offL);
/* Create new identifier */ /* Create new identifier */
newIdent (t, STK_FRAME); id_arr.push_back(ID(t,LONG_STKID_TYPE(offH,offL)));
idx = id_arr.size() - 1; return (id_arr.size() - 1);
id_arr[idx].id.longStkId.offH = offH;
id_arr[idx].id.longStkId.offL = offL;
return (idx);
} }
@ -289,7 +312,7 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
else if (pmL->regi < INDEX_BX_SI) /* register */ else if (pmL->regi < INDEX_BX_SI) /* register */
{ {
idx = newLongReg(TYPE_LONG_SIGN, pmH->regi, pmL->regi, ix); idx = newLongReg(TYPE_LONG_SIGN, LONGID_TYPE(pmH->regi, pmL->regi), ix);
if (f == HIGH_FIRST) if (f == HIGH_FIRST)
pIcode->setRegDU( pmL->regi, du); /* low part */ pIcode->setRegDU( pmL->regi, du); /* low part */
else else
@ -325,15 +348,31 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, L
* idx : idx into icode array * idx : idx into icode array
* pProc : ptr to current procedure record * pProc : ptr to current procedure record
* rhs, lhs : return expressions if successful. */ * rhs, lhs : return expressions if successful. */
boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset) bool checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, LLInst &atOffset)
{ {
/* pointers to LOW_LEVEL icodes */ /* pointers to LOW_LEVEL icodes */
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc; const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
pmHdst = &pIcode->ll()->dst; pmHdst = &pIcode->ll()->m_dst;
pmLdst = &atOffset.dst; pmLdst = &atOffset.m_dst;
pmHsrc = &pIcode->ll()->src(); pmHsrc = &pIcode->ll()->src();
pmLsrc = &atOffset.src(); pmLsrc = &atOffset.src();
// if ((longId.offH == pmHsrc->off) && (longId.offL == pmLsrc->off))
// {
// asgn.lhs = AstIdent::LongIdx (i);
// if ( not pIcode->ll()->testFlags(NO_SRC) )
// {
// asgn.rhs = AstIdent::Long (&pProc->localId, SRC, pIcode, HIGH_FIRST, pIcode, eUSE, atOffset);
// }
// return true;
// }
// else if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
// {
// asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode,eDEF, atOffset);
// asgn.rhs = AstIdent::LongIdx (i);
// return true;
// }
if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off)) if ((longId.offH == pmHdst->off) && (longId.offL == pmLdst->off))
{ {
@ -364,18 +403,18 @@ boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pPro
* idx : idx into icode array * idx : idx into icode array
* pProc : ptr to current procedure record * pProc : ptr to current procedure record
* rhs, lhs : return expressions if successful. */ * rhs, lhs : return expressions if successful. */
boolT checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i, bool checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
Function * pProc, Assignment &asgn, LLInst &atOffset) Function * pProc, Assignment &asgn, LLInst &atOffset)
{ {
/* pointers to LOW_LEVEL icodes */ /* pointers to LOW_LEVEL icodes */
const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc; const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc;
pmHdst = &pIcode->ll()->dst; pmHdst = &pIcode->ll()->m_dst;
pmLdst = &atOffset.dst; pmLdst = &atOffset.m_dst;
pmHsrc = &pIcode->ll()->src(); pmHsrc = &pIcode->ll()->src();
pmLsrc = &atOffset.src(); pmLsrc = &atOffset.src();
if ((longId.h == pmHdst->regi) && (longId.l == pmLdst->regi)) if ((longId.h() == pmHdst->regi) && (longId.l() == pmLdst->regi))
{ {
asgn.lhs = AstIdent::LongIdx (i); asgn.lhs = AstIdent::LongIdx (i);
if ( not pIcode->ll()->testFlags(NO_SRC) ) if ( not pIcode->ll()->testFlags(NO_SRC) )
@ -384,7 +423,7 @@ boolT checkLongRegEq (LONGID_TYPE longId, iICODE pIcode, int i,
} }
return true; return true;
} }
else if ((longId.h == pmHsrc->regi) && (longId.l == pmLsrc->regi)) else if ((longId.h() == pmHsrc->regi) && (longId.l() == pmLsrc->regi))
{ {
asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset); asgn.lhs = AstIdent::Long (&pProc->localId, DST, pIcode, HIGH_FIRST, pIcode, eDEF, atOffset);
asgn.rhs = AstIdent::LongIdx (i); asgn.rhs = AstIdent::LongIdx (i);
@ -406,10 +445,10 @@ eReg otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) || if ((id->loc == REG_FRAME) && ((id->type == TYPE_LONG_SIGN) ||
(id->type == TYPE_LONG_UNSIGN))) (id->type == TYPE_LONG_UNSIGN)))
{ {
if (id->id.longId.h == regi) if (id->longId().h() == regi)
return (id->id.longId.l); return (id->longId().l());
else if (id->id.longId.l == regi) else if (id->longId().l() == regi)
return (id->id.longId.h); return (id->longId().h());
} }
return rUNDEF; // Cristina: please check this! return rUNDEF; // Cristina: please check this!
} }

View File

@ -1,5 +1,6 @@
#include <cassert> #include <cassert>
#include "machine_x86.h" #include "machine_x86.h"
#include "icode.h"
// Index registers **** temp solution // Index registers **** temp solution
static const std::string regNames[] = { static const std::string regNames[] = {
"undef", "undef",
@ -8,7 +9,7 @@ static const std::string regNames[] = {
"es", "cs", "ss", "ds", "es", "cs", "ss", "ds",
"al", "cl", "dl", "bl", "al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh", "ah", "ch", "dh", "bh",
"tmp", "tmp","tmp2",
"bx+si", "bx+di", "bp+si", "bp+di", "bx+si", "bx+di", "bp+si", "bp+di",
"si", "di", "bp", "bx" "si", "di", "bp", "bx"
}; };
@ -132,3 +133,12 @@ eReg Machine_X86::compositeParent(eReg reg)
} }
return rUNDEF; return rUNDEF;
} }
void Machine_X86::writeRegVector (std::ostream &ostr,const LivenessSet &regi)
{
int j;
for (j = rAX; j < INDEX_BX_SI; j++)
{
if (regi.testReg(j))
ostr << regName(eReg(j))<<" ";
}
}

View File

@ -146,8 +146,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
eIcode = ICODE(); eIcode = ICODE();
eIcode.type = LOW_LEVEL; eIcode.type = LOW_LEVEL;
eIcode.ll()->set(iMOV,0); eIcode.ll()->set(iMOV,0,rTMP);
eIcode.ll()->replaceDst(rTMP);
if (ll->testFlags(B) ) if (ll->testFlags(B) )
{ {
eIcode.ll()->setFlags( B ); eIcode.ll()->setFlags( B );
@ -171,10 +170,9 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
/* iMOD */ /* iMOD */
eIcode = ICODE(); eIcode = ICODE();
eIcode.type = LOW_LEVEL; eIcode.type = LOW_LEVEL;
eIcode.ll()->set(iMOD,0); eIcode.ll()->set(iMOD,ll->getFlag() | SYNTHETIC | IM_TMP_DST);
eIcode.ll()->replaceSrc(_Icode.ll()->src()); eIcode.ll()->replaceSrc(_Icode.ll()->src());
eIcode.du = _Icode.du; eIcode.du = _Icode.du;
eIcode.ll()->setFlags( ( ll->getFlag() | SYNTHETIC | IM_TMP_DST) );
eIcode.ll()->label = SynthLab++; eIcode.ll()->label = SynthLab++;
pIcode = Icode.addIcode(&eIcode); pIcode = Icode.addIcode(&eIcode);
} }
@ -183,9 +181,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
/* MOV rTMP, regDst */ /* MOV rTMP, regDst */
eIcode = ICODE(); eIcode = ICODE();
eIcode.type = LOW_LEVEL; eIcode.type = LOW_LEVEL;
eIcode.ll()->set(iMOV,SYNTHETIC); eIcode.ll()->set(iMOV,SYNTHETIC,rTMP,_Icode.ll()->m_dst);
eIcode.ll()->replaceDst(LLOperand::CreateReg2(rTMP));
eIcode.ll()->replaceSrc(_Icode.ll()->dst);
eIcode.setRegDU( rTMP, eDEF); eIcode.setRegDU( rTMP, eDEF);
if(eIcode.ll()->src().getReg2()) if(eIcode.ll()->src().getReg2())
{ {
@ -207,11 +203,11 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
eIcode.type = LOW_LEVEL; eIcode.type = LOW_LEVEL;
eIcode.ll()->set(iMOV,SYNTHETIC); eIcode.ll()->set(iMOV,SYNTHETIC);
eIcode.ll()->replaceDst(ll->src()); eIcode.ll()->replaceDst(ll->src());
if(eIcode.ll()->dst.regi) if(eIcode.ll()->m_dst.regi)
{ {
if((eIcode.ll()->dst.regi>=rAL) && (eIcode.ll()->dst.regi<=rBH)) if((eIcode.ll()->m_dst.regi>=rAL) && (eIcode.ll()->m_dst.regi<=rBH))
eIcode.ll()->setFlags( B ); eIcode.ll()->setFlags( B );
eIcode.setRegDU( eIcode.ll()->dst.regi, eDEF); eIcode.setRegDU( eIcode.ll()->m_dst.regi, eDEF);
} }
eIcode.ll()->replaceSrc(rTMP); eIcode.ll()->replaceSrc(rTMP);
eIcode.setRegDU( rTMP, eUSE); eIcode.setRegDU( rTMP, eUSE);
@ -246,7 +242,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
if (ll->match(iJA) || ll->match(iJBE) ) if (ll->match(iJA) || ll->match(iJBE) )
pstate->JCond.immed++; pstate->JCond.immed++;
if (ll->getOpcode() == iJAE || ll->getOpcode() == iJA) if (ll->getOpcode() == iJAE || ll->getOpcode() == iJA)
pstate->JCond.regi = prev.ll()->dst.regi; pstate->JCond.regi = prev.ll()->m_dst.regi;
fBranch = (bool) fBranch = (bool)
(ll->getOpcode() == iJB || ll->getOpcode() == iJBE); (ll->getOpcode() == iJB || ll->getOpcode() == iJBE);
} }
@ -258,7 +254,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
if (fBranch) /* Do branching code */ if (fBranch) /* Do branching code */
{ {
pstate->JCond.regi = prev.ll()->dst.regi; pstate->JCond.regi = prev.ll()->m_dst.regi;
} }
/* Next icode. Note: not the same as GetLastIcode() because of the call /* Next icode. Note: not the same as GetLastIcode() because of the call
to FollowCtrl() */ to FollowCtrl() */
@ -297,7 +293,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
int size; int size;
/* Save function number */ /* Save function number */
Icode.back().ll()->dst.off = (int16_t)funcNum; Icode.back().ll()->m_dst.off = (int16_t)funcNum;
//Icode.GetIcode(Icode.GetNumIcodes() - 1)-> //Icode.GetIcode(Icode.GetNumIcodes() - 1)->
/* Program termination: int21h, fn 00h, 31h, 4Ch */ /* Program termination: int21h, fn 00h, 31h, 4Ch */
@ -318,7 +314,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
} }
else if ((ll->src().getImm2() == 0x2F) && (pstate->f[rAH])) else if ((ll->src().getImm2() == 0x2F) && (pstate->f[rAH]))
{ {
Icode.back().ll()->dst.off = pstate->r[rAH]; Icode.back().ll()->m_dst.off = pstate->r[rAH];
} }
else /* Program termination: int20h, int27h */ else /* Program termination: int20h, int27h */
done = (boolT)(ll->src().getImm2() == 0x20 || done = (boolT)(ll->src().getImm2() == 0x20 ||
@ -337,7 +333,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
break; **** HERE ***/ break; **** HERE ***/
case iSHL: case iSHL:
if (pstate->JCond.regi == ll->dst.regi) if (pstate->JCond.regi == ll->m_dst.regi)
{ {
if ((ll->testFlags(I)) && ll->src().getImm2() == 1) if ((ll->testFlags(I)) && ll->src().getImm2() == 1)
pstate->JCond.immed *= 2; pstate->JCond.immed *= 2;
@ -348,7 +344,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
case iLEA: case iLEA:
if (ll->src().getReg2()== rUNDEF) /* direct mem offset */ if (ll->src().getReg2()== rUNDEF) /* direct mem offset */
pstate->setState( ll->dst.getReg2(), ll->src().off); pstate->setState( ll->m_dst.getReg2(), ll->src().off);
break; break;
case iLDS: case iLES: case iLDS: case iLES:
@ -358,7 +354,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
offset = LH(&prog.image()[psym->label]); offset = LH(&prog.image()[psym->label]);
pstate->setState( (ll->getOpcode() == iLDS)? rDS: rES, pstate->setState( (ll->getOpcode() == iLDS)? rDS: rES,
LH(&prog.image()[psym->label + 2])); LH(&prog.image()[psym->label + 2]));
pstate->setState( ll->dst.regi, (int16_t)offset); pstate->setState( ll->m_dst.regi, (int16_t)offset);
psym->type = TYPE_PTR; psym->type = TYPE_PTR;
} }
break; break;
@ -564,7 +560,7 @@ boolT Function::process_CALL (ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *ps
{ {
/* Not immediate, i.e. indirect call */ /* Not immediate, i.e. indirect call */
if (pIcode.ll()->dst.regi && (!option.Calls)) if (pIcode.ll()->m_dst.regi && (!option.Calls))
{ {
/* We have not set the brave option to attempt to follow /* We have not set the brave option to attempt to follow
the execution path through register indirect calls. the execution path through register indirect calls.
@ -579,25 +575,25 @@ boolT Function::process_CALL (ICODE & pIcode, CALL_GRAPH * pcallGraph, STATE *ps
es:0 where es:0 is the start of the image. This is es:0 where es:0 is the start of the image. This is
usually wrong! Consider also CALL [BP+0E] in which the usually wrong! Consider also CALL [BP+0E] in which the
segment for the pointer is in SS! - Mike */ segment for the pointer is in SS! - Mike */
if(pIcode.ll()->dst.isReg()) if(pIcode.ll()->m_dst.isReg())
{ {
if( not pstate->isKnown(pIcode.ll()->dst.regi) if( not pstate->isKnown(pIcode.ll()->m_dst.regi)
or or
not pstate->isKnown(pIcode.ll()->dst.seg) not pstate->isKnown(pIcode.ll()->m_dst.seg)
) )
{ {
fprintf(stderr,"Indirect call with unkown register values\n"); fprintf(stderr,"Indirect call with unknown register values\n");
return false; return false;
} }
off = pstate->r[pIcode.ll()->dst.seg]; off = pstate->r[pIcode.ll()->m_dst.seg];
off <<=4; off <<=4;
off += pstate->r[pIcode.ll()->dst.regi]; off += pstate->r[pIcode.ll()->m_dst.regi];
} }
else else
{ {
off = (uint32_t)(uint16_t)pIcode.ll()->dst.off + off = (uint32_t)(uint16_t)pIcode.ll()->m_dst.off +
((uint32_t)(uint16_t)pIcode.ll()->dst.segValue << 4); ((uint32_t)(uint16_t)pIcode.ll()->m_dst.segValue << 4);
} }
/* Address of function is given by 4 (CALLF) or 2 (CALL) bytes at /* Address of function is given by 4 (CALLF) or 2 (CALL) bytes at
@ -684,7 +680,7 @@ static void process_MOV(LLInst & ll, STATE * pstate)
{ {
PROG &prog(Project::get()->prog); PROG &prog(Project::get()->prog);
SYM * psym, *psym2; /* Pointer to symbol in global symbol table */ SYM * psym, *psym2; /* Pointer to symbol in global symbol table */
uint8_t dstReg = ll.dst.regi; uint8_t dstReg = ll.m_dst.regi;
uint8_t srcReg = ll.src().regi; uint8_t srcReg = ll.src().regi;
if (dstReg > 0 && dstReg < INDEX_BX_SI) if (dstReg > 0 && dstReg < INDEX_BX_SI)
{ {
@ -709,7 +705,7 @@ static void process_MOV(LLInst & ll, STATE * pstate)
int size=2; int size=2;
if((ll.src().regi>=rAL)&&(ll.src().regi<=rBH)) if((ll.src().regi>=rAL)&&(ll.src().regi<=rBH))
size=1; size=1;
psym = lookupAddr (&ll.dst, pstate, size, eDEF); psym = lookupAddr (&ll.m_dst, pstate, size, eDEF);
if (psym && ! (psym->duVal.val)) /* no initial value yet */ if (psym && ! (psym->duVal.val)) /* no initial value yet */
{ {
if (ll.testFlags(I)) /* immediate */ if (ll.testFlags(I)) /* immediate */
@ -898,19 +894,6 @@ static void setBits(int16_t type, uint32_t start, uint32_t len)
} }
} }
/* DU bit definitions for each reg value - including index registers */
LivenessSet 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 };
/* Checks which registers were used and updates the du.u flag. /* Checks which registers were used and updates the du.u flag.
* Places local variables on the local symbol table. * Places local variables on the local symbol table.
* Arguments: d : SRC or DST icode operand * Arguments: d : SRC or DST icode operand
@ -945,7 +928,7 @@ static void use (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int
if (pm->off > 0) /* global indexed variable */ if (pm->off > 0) /* global indexed variable */
pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,TYPE_WORD_SIGN); pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,TYPE_WORD_SIGN);
} }
pIcode.du.use |= duReg[pm->regi]; pIcode.du.use.addReg(pm->regi);
} }
else else
@ -963,7 +946,7 @@ static void use (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int
/* Use of register */ /* Use of register */
else if ((d == DST) || ((d == SRC) && (not pIcode.ll()->testFlags(I)))) else if ((d == DST) || ((d == SRC) && (not pIcode.ll()->testFlags(I))))
pIcode.du.use |= duReg[pm->regi]; pIcode.du.use.addReg(pm->regi);
} }
@ -1007,14 +990,15 @@ static void def (opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, int
if (pm->off > 0) /* global var */ if (pm->off > 0) /* global var */
pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,TYPE_WORD_SIGN); pProc->localId.newIntIdx(pm->segValue, pm->off, rBX,TYPE_WORD_SIGN);
} }
pIcode.du.use |= duReg[pm->regi]; pIcode.du.use.addReg(pm->regi);
} }
} }
/* Definition of register */ /* Definition of register */
else if ((d == DST) || ((d == SRC) && (not pIcode.ll()->testFlags(I)))) else if ((d == DST) || ((d == SRC) && (not pIcode.ll()->testFlags(I))))
{ {
pIcode.du.def |= duReg[pm->regi]; assert(not pIcode.ll()->match(iPUSH));
pIcode.du1.numRegsDef++; pIcode.du1.addDef(pm->regi);
pIcode.du.def.addReg(pm->regi);
} }
} }
@ -1030,8 +1014,9 @@ static void use_def(opLoc d, ICODE & pIcode, Function * pProc, STATE * pstate, i
if (pm->regi < INDEX_BX_SI) /* register */ if (pm->regi < INDEX_BX_SI) /* register */
{ {
pIcode.du.def |= duReg[pm->regi]; assert(not pIcode.ll()->match(iPUSH));
pIcode.du1.numRegsDef++; pIcode.du1.addDef(pm->regi);
pIcode.du.def.addReg(pm->regi);
} }
} }
@ -1090,12 +1075,12 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
if (cb == 1) if (cb == 1)
{ {
pIcode.du.def.addReg(rAX); pIcode.du.def.addReg(rAX);
pIcode.du1.numRegsDef++; pIcode.du1.addDef(rAX);
} }
else else
{ {
pIcode.du.def.addReg(rAX).addReg(rDX); pIcode.du.def.addReg(rAX).addReg(rDX);
pIcode.du1.numRegsDef += 2; pIcode.du1.addDef(rAX).addDef(rDX);
} }
} }
else else
@ -1107,13 +1092,13 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
if (cb == 1) /* uint8_t */ if (cb == 1) /* uint8_t */
{ {
pIcode.du.def.addReg(rAX); pIcode.du.def.addReg(rAX);
pIcode.du1.numRegsDef++; pIcode.du1.addDef(rAX);
pIcode.du.use.addReg(rAL); pIcode.du.use.addReg(rAL);
} }
else /* uint16_t */ else /* uint16_t */
{ {
pIcode.du.def.addReg(rDX).addReg(rAX); pIcode.du.def.addReg(rDX).addReg(rAX);
pIcode.du1.numRegsDef += 2; pIcode.du1.addDef(rAX).addDef(rDX);
pIcode.du.use.addReg(rAX); pIcode.du.use.addReg(rAX);
} }
break; break;
@ -1134,9 +1119,13 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
break; break;
case iLDS: case iLES: case iLDS: case iLES:
pIcode.du.def.addReg(((pIcode.ll()->getOpcode() == iLDS) ? rDS : rES)); {
pIcode.du1.numRegsDef++; eReg r=((pIcode.ll()->getOpcode() == iLDS) ? rDS : rES);
pIcode.du.def.addReg(r);
pIcode.du1.addDef(r);
cb = 4; cb = 4;
// fallthrough
}
case iMOV: case iMOV:
use(SRC, pIcode, this, pstate, cb); use(SRC, pIcode, this, pstate, cb);
def(DST, pIcode, this, pstate, cb); def(DST, pIcode, this, pstate, cb);
@ -1161,27 +1150,27 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
case iLOOP: case iLOOPE: case iLOOPNE: case iLOOP: case iLOOPE: case iLOOPNE:
pIcode.du.def.addReg(rCX); pIcode.du.def.addReg(rCX);
pIcode.du1.numRegsDef++; pIcode.du1.addDef(rCX);
case iJCXZ: case iJCXZ:
pIcode.du.use.addReg(rCX); pIcode.du.use.addReg(rCX);
break; break;
case iREPNE_CMPS: case iREPE_CMPS: case iREP_MOVS: case iREPNE_CMPS: case iREPE_CMPS: case iREP_MOVS:
pIcode.du.addDefinedAndUsed(rCX); pIcode.du.addDefinedAndUsed(rCX);
pIcode.du1.numRegsDef++; pIcode.du1.addDef(rCX);
case iCMPS: case iMOVS: case iCMPS: case iMOVS:
pIcode.du.addDefinedAndUsed(rSI); pIcode.du.addDefinedAndUsed(rSI);
pIcode.du.addDefinedAndUsed(rDI); pIcode.du.addDefinedAndUsed(rDI);
pIcode.du1.numRegsDef += 2; pIcode.du1.addDef(rSI).addDef(rDI);
pIcode.du.use.addReg(rES).addReg(sseg); pIcode.du.use.addReg(rES).addReg(sseg);
break; break;
case iREPNE_SCAS: case iREPE_SCAS: case iREP_STOS: case iREP_INS: case iREPNE_SCAS: case iREPE_SCAS: case iREP_STOS: case iREP_INS:
pIcode.du.addDefinedAndUsed(rCX); pIcode.du.addDefinedAndUsed(rCX);
pIcode.du1.numRegsDef++; pIcode.du1.addDef(rCX);
case iSCAS: case iSTOS: case iINS: case iSCAS: case iSTOS: case iINS:
pIcode.du.def.addReg(rDI); pIcode.du.def.addReg(rDI);
pIcode.du1.numRegsDef++; pIcode.du1.addDef(rDI);
if (pIcode.ll()->getOpcode() == iREP_INS || pIcode.ll()->getOpcode()== iINS) if (pIcode.ll()->getOpcode() == iREP_INS || pIcode.ll()->getOpcode()== iINS)
{ {
pIcode.du.use.addReg(rDI).addReg(rES).addReg(rDX); pIcode.du.use.addReg(rDI).addReg(rES).addReg(rDX);
@ -1194,28 +1183,31 @@ void Function::process_operands(ICODE & pIcode, STATE * pstate)
case iREP_LODS: case iREP_LODS:
pIcode.du.addDefinedAndUsed(rCX); pIcode.du.addDefinedAndUsed(rCX);
pIcode.du1.numRegsDef++; pIcode.du1.addDef(rCX);
case iLODS: case iLODS:
{
eReg r = (cb==2)? rAX: rAL;
pIcode.du.addDefinedAndUsed(rSI); pIcode.du.addDefinedAndUsed(rSI);
pIcode.du.def.addReg((cb==2)? rAX: rAL); pIcode.du1.addDef(rSI);
pIcode.du1.numRegsDef += 2; pIcode.du.def.addReg(r);
pIcode.du1.addDef(r);
pIcode.du.use.addReg(sseg); pIcode.du.use.addReg(sseg);
}
break; break;
case iREP_OUTS: case iREP_OUTS:
pIcode.du.addDefinedAndUsed(rCX); pIcode.du.addDefinedAndUsed(rCX);
pIcode.du1.numRegsDef++; pIcode.du1.addDef(rCX);
case iOUTS: case iOUTS:
pIcode.du.addDefinedAndUsed(rSI); pIcode.du.addDefinedAndUsed(rSI);
pIcode.du1.numRegsDef++; pIcode.du1.addDef(rSI);
pIcode.du.use |= duReg[rDX] | duReg[sseg]; pIcode.du.use.addReg(rDX).addReg(sseg);
break; break;
case iIN: case iOUT: case iIN: case iOUT:
def(DST, pIcode, this, pstate, cb); def(DST, pIcode, this, pstate, cb);
if (! Imm) if (! Imm)
{ {
pIcode.du.use |= duReg[rDX]; pIcode.du.use.addReg(rDX);
} }
break; break;
} }

View File

@ -97,7 +97,8 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
bool regExist=false; bool regExist=false;
condId type; condId type;
Function * tproc; Function * tproc;
eReg regL, regH; /* Registers involved in arguments */ eReg regL = rUNDEF;
eReg regH; /* Registers involved in arguments */
/* Flag ticode as having register arguments */ /* Flag ticode as having register arguments */
tproc = ticode->hl()->call.proc; tproc = ticode->hl()->call.proc;
@ -113,6 +114,7 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
if (lhs_reg) if (lhs_reg)
{ {
regL = id_arr[lhs_reg->regiIdx].id.regi; regL = id_arr[lhs_reg->regiIdx].id.regi;
assert(regL!=rUNDEF);
if (regL < rAL) if (regL < rAL)
tidx = tproc->localId.newByteWordReg(TYPE_WORD_SIGN, regL); tidx = tproc->localId.newByteWordReg(TYPE_WORD_SIGN, regL);
else else
@ -133,9 +135,10 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
else if (type == LONG_VAR) else if (type == LONG_VAR)
{ {
int longIdx = lhs->ident.idNode.longIdx; int longIdx = lhs->ident.idNode.longIdx;
regL = id_arr[longIdx].id.longId.l; LONGID_TYPE regHL = id_arr[longIdx].longId();
regH = id_arr[longIdx].id.longId.h; regH=regHL.h();
tidx = tproc->localId.newLongReg(TYPE_LONG_SIGN, regH, regL, tproc->Icode.begin() /*0*/); regL=regHL.l();
tidx = tproc->localId.newLongReg(TYPE_LONG_SIGN, regHL, tproc->Icode.begin() /*0*/);
/* Check if register argument already on the formal argument list */ /* Check if register argument already on the formal argument list */
for(STKSYM &tgt_sym : *target_stackframe) for(STKSYM &tgt_sym : *target_stackframe)
{ {
@ -175,6 +178,7 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
{ {
newsym.regs = AstIdent::LongIdx (tidx); newsym.regs = AstIdent::LongIdx (tidx);
newsym.type = TYPE_LONG_SIGN; newsym.type = TYPE_LONG_SIGN;
assert(regL!=rUNDEF);
tproc->localId.id_arr[tidx].name = newsym.name; tproc->localId.id_arr[tidx].name = newsym.name;
tproc->localId.propLongId (regL, regH, tproc->localId.id_arr[tidx].name.c_str()); tproc->localId.propLongId (regL, regH, tproc->localId.id_arr[tidx].name.c_str());
} }
@ -191,7 +195,7 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
switch (type) { switch (type) {
case REGISTER: case REGISTER:
id = &id_arr[lhs_reg->regiIdx]; id = &id_arr[lhs_reg->regiIdx];
picode->du.def &= maskDuReg[id->id.regi]; picode->du.def.clrReg(id->id.regi);
if (id->id.regi < rAL) if (id->id.regi < rAL)
newsym.type = TYPE_WORD_SIGN; newsym.type = TYPE_WORD_SIGN;
else else
@ -199,8 +203,8 @@ void LOCAL_ID::newRegArg(iICODE picode, iICODE ticode) const
break; break;
case LONG_VAR: case LONG_VAR:
id = &id_arr[lhs->ident.idNode.longIdx]; id = &id_arr[lhs->ident.idNode.longIdx];
picode->du.def &= maskDuReg[id->id.longId.h]; picode->du.def.clrReg(id->longId().h());
picode->du.def &= maskDuReg[id->id.longId.l]; picode->du.def.clrReg(id->longId().l());
newsym.type = TYPE_LONG_SIGN; newsym.type = TYPE_LONG_SIGN;
break; break;
default: default:

View File

@ -250,7 +250,7 @@ void Function::propLongStk (int i, const ID &pLocId)
continue; continue;
if (pIcode->ll()->getOpcode() == next1->ll()->getOpcode()) if (pIcode->ll()->getOpcode() == next1->ll()->getOpcode())
{ {
if (checkLongEq (pLocId.id.longStkId, pIcode, i, this, asgn, *next1->ll()) == true) if (checkLongEq (pLocId.longStkId(), pIcode, i, this, asgn, *next1->ll()) == true)
{ {
switch (pIcode->ll()->getOpcode()) switch (pIcode->ll()->getOpcode())
{ {
@ -290,7 +290,7 @@ void Function::propLongStk (int i, const ID &pLocId)
/* Check long conditional (i.e. 2 CMPs and 3 branches */ /* Check long conditional (i.e. 2 CMPs and 3 branches */
else if ((pIcode->ll()->getOpcode() == iCMP) && (isLong23 (pIcode->getParent(), l23, &arc))) else if ((pIcode->ll()->getOpcode() == iCMP) && (isLong23 (pIcode->getParent(), l23, &arc)))
{ {
if ( checkLongEq (pLocId.id.longStkId, pIcode, i, this, asgn, *l23->ll()) ) if ( checkLongEq (pLocId.longStkId(), pIcode, i, this, asgn, *l23->ll()) )
{ {
advance(pIcode,longJCond23 (asgn, pIcode, arc, l23)); advance(pIcode,longJCond23 (asgn, pIcode, arc, l23));
} }
@ -300,7 +300,7 @@ void Function::propLongStk (int i, const ID &pLocId)
* 2 CMPs and 2 branches */ * 2 CMPs and 2 branches */
else if ((pIcode->ll()->getOpcode() == iCMP) && isLong22 (pIcode, pEnd, l23)) else if ((pIcode->ll()->getOpcode() == iCMP) && isLong22 (pIcode, pEnd, l23))
{ {
if ( checkLongEq (pLocId.id.longStkId, pIcode, i, this,asgn, *l23->ll()) ) if ( checkLongEq (pLocId.longStkId(), pIcode, i, this,asgn, *l23->ll()) )
{ {
advance(pIcode,longJCond22 (asgn, pIcode,pEnd)); advance(pIcode,longJCond22 (asgn, pIcode,pEnd));
} }
@ -329,9 +329,9 @@ int Function::findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE be
switch (icode.ll()->getOpcode()) switch (icode.ll()->getOpcode())
{ {
case iMOV: case iMOV:
pmH = &icode.ll()->dst; pmH = &icode.ll()->m_dst;
pmL = &next1->ll()->dst; pmL = &next1->ll()->m_dst;
if ((pLocId.id.longId.h == pmH->regi) && (pLocId.id.longId.l == pmL->regi)) if ((pLocId.longId().h() == pmH->regi) && (pLocId.longId().l() == pmL->regi))
{ {
localId.id_arr[loc_ident_idx].idx.push_back(pIcode);//idx-1//insert localId.id_arr[loc_ident_idx].idx.push_back(pIcode);//idx-1//insert
icode.setRegDU( pmL->regi, eDEF); icode.setRegDU( pmL->regi, eDEF);
@ -344,9 +344,9 @@ int Function::findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE be
break; break;
case iPOP: case iPOP:
pmH = &next1->ll()->dst; pmH = &next1->ll()->m_dst;
pmL = &icode.ll()->dst; pmL = &icode.ll()->m_dst;
if ((pLocId.id.longId.h == pmH->regi) && (pLocId.id.longId.l == pmL->regi)) if ((pLocId.longId().h() == pmH->regi) && (pLocId.longId().l() == pmL->regi))
{ {
asgn.lhs = AstIdent::LongIdx (loc_ident_idx); asgn.lhs = AstIdent::LongIdx (loc_ident_idx);
icode.setRegDU( pmH->regi, eDEF); icode.setRegDU( pmH->regi, eDEF);
@ -360,9 +360,9 @@ int Function::findBackwarLongDefs(int loc_ident_idx, const ID &pLocId, iICODE be
// /**** others missing ***/ // /**** others missing ***/
case iAND: case iOR: case iXOR: case iAND: case iOR: case iXOR:
pmL = &icode.ll()->dst; pmL = &icode.ll()->m_dst;
pmH = &next1->ll()->dst; pmH = &next1->ll()->m_dst;
if ((pLocId.id.longId.h == pmH->regi) && (pLocId.id.longId.l == pmL->regi)) if ((pLocId.longId().h() == pmH->regi) && (pLocId.longId().l() == pmL->regi))
{ {
asgn.lhs = AstIdent::LongIdx (loc_ident_idx); asgn.lhs = AstIdent::LongIdx (loc_ident_idx);
asgn.rhs = AstIdent::Long (&this->localId, SRC, pIcode, LOW_FIRST, pIcode, eUSE, *next1->ll()); asgn.rhs = AstIdent::Long (&this->localId, SRC, pIcode, LOW_FIRST, pIcode, eUSE, *next1->ll());
@ -407,12 +407,12 @@ int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE be
{ {
case iMOV: case iMOV:
{ {
const LONGID_TYPE &ref_long(pLocId.id.longId); const LONGID_TYPE &ref_long(pLocId.longId());
const LLOperand &src_op1(pIcode->ll()->src()); const LLOperand &src_op1(pIcode->ll()->src());
const LLOperand &src_op2(next1->ll()->src()); const LLOperand &src_op2(next1->ll()->src());
eReg srcReg1=src_op1.getReg2(); eReg srcReg1=src_op1.getReg2();
eReg nextReg2=src_op2.getReg2(); eReg nextReg2=src_op2.getReg2();
if ((ref_long.h == srcReg1) && (ref_long.l == nextReg2)) if ((ref_long.h() == srcReg1) && (ref_long.l() == nextReg2))
{ {
pIcode->setRegDU( nextReg2, eUSE); pIcode->setRegDU( nextReg2, eUSE);
@ -428,11 +428,10 @@ int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE be
case iPUSH: case iPUSH:
{ {
const LONGID_TYPE &ref_long(pLocId.id.longId); const LONGID_TYPE &ref_long(pLocId.longId());
const LLOperand &src_op1(pIcode->ll()->src()); const LLOperand &src_op1(pIcode->ll()->src());
const LLOperand &src_op2(next1->ll()->src()); const LLOperand &src_op2(next1->ll()->src());
if ((ref_long.h == src_op1.getReg2()) && if ((ref_long.h() == src_op1.getReg2()) && (ref_long.l() == src_op2.getReg2()))
(ref_long.l == src_op2.getReg2()))
{ {
asgn.rhs = AstIdent::LongIdx (loc_ident_idx); asgn.rhs = AstIdent::LongIdx (loc_ident_idx);
pIcode->setRegDU( next1->ll()->src().getReg2(), eUSE); pIcode->setRegDU( next1->ll()->src().getReg2(), eUSE);
@ -446,10 +445,9 @@ int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE be
/*** others missing ****/ /*** others missing ****/
case iAND: case iOR: case iXOR: case iAND: case iOR: case iXOR:
pmL = &pIcode->ll()->dst; pmL = &pIcode->ll()->m_dst;
pmH = &next1->ll()->dst; pmH = &next1->ll()->m_dst;
if ((pLocId.id.longId.h == pmH->regi) && if ((pLocId.longId().h() == pmH->regi) && (pLocId.longId().l() == pmL->regi))
(pLocId.id.longId.l == pmL->regi))
{ {
asgn.lhs = AstIdent::LongIdx (loc_ident_idx); asgn.lhs = AstIdent::LongIdx (loc_ident_idx);
pIcode->setRegDU( pmH->regi, USE_DEF); pIcode->setRegDU( pmH->regi, USE_DEF);
@ -478,7 +476,7 @@ int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE be
/* Check long conditional (i.e. 2 CMPs and 3 branches */ /* Check long conditional (i.e. 2 CMPs and 3 branches */
else if ((pIcode->ll()->getOpcode() == iCMP) && (isLong23 (pIcode->getParent(), long_loc, &arc))) 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())) if (checkLongRegEq (pLocId.longId(), pIcode, loc_ident_idx, this, asgn, *long_loc->ll()))
{ {
// reduce the advance by 1 here (loop increases) ? // reduce the advance by 1 here (loop increases) ?
advance(pIcode,longJCond23 (asgn, pIcode, arc, long_loc)); advance(pIcode,longJCond23 (asgn, pIcode, arc, long_loc));
@ -489,7 +487,7 @@ int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE be
* 2 CMPs and 2 branches */ * 2 CMPs and 2 branches */
else if (pIcode->ll()->match(iCMP) && (isLong22 (pIcode, pEnd, long_loc))) 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()) ) if (checkLongRegEq (pLocId.longId(), pIcode, loc_ident_idx, this, asgn, *long_loc->ll()) )
{ {
// TODO: verify that removing -1 does not change anything ! // TODO: verify that removing -1 does not change anything !
advance(pIcode,longJCond22 (asgn, pIcode,pEnd)); advance(pIcode,longJCond22 (asgn, pIcode,pEnd));
@ -502,7 +500,7 @@ int Function::findForwardLongUses(int loc_ident_idx, const ID &pLocId, iICODE be
* This is better code than HLI_JCOND (HI(regH:regL) | LO(regH:regL)) */ * 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()))) else if (pIcode->ll()->match(iOR) && (next1 != pEnd) && (isJCond ((llIcode)next1->ll()->getOpcode())))
{ {
if (pLocId.id.longId.srcDstRegMatch(pIcode,pIcode)) if (pLocId.longId().srcDstRegMatch(pIcode,pIcode))
{ {
asgn.lhs = AstIdent::LongIdx (loc_ident_idx); asgn.lhs = AstIdent::LongIdx (loc_ident_idx);
asgn.rhs = new Constant(0, 4); /* long 0 */ asgn.rhs = new Constant(0, 4); /* long 0 */

View File

@ -6,6 +6,8 @@
****************************************************************************/ ****************************************************************************/
#include <cstring> #include <cstring>
#include <map>
#include <string>
#include "dcc.h" #include "dcc.h"
#include "scanner.h" #include "scanner.h"
#include "project.h" #include "project.h"
@ -411,33 +413,116 @@ int disassembleOneLibDisasm(uint32_t ip,x86_insn_t &l)
} }
eReg convertRegister(const x86_reg_t &reg) eReg convertRegister(const x86_reg_t &reg)
{ {
if( (reg_pc==reg.type) || (0==reg.id))
return rUNDEF;
eReg regmap[]={ rUNDEF, eReg regmap[]={ rUNDEF,
rUNDEF,rUNDEF,rUNDEF,rUNDEF, //eax ecx ebx edx rUNDEF,rUNDEF,rUNDEF,rUNDEF, //eax ecx ebx edx
rSP,rUNDEF,rUNDEF,rUNDEF, //esp ebp esi edi rSP,rUNDEF,rUNDEF,rDI, //esp ebp esi edi
rAX,rCX,rDX,rBX, rAX,rCX,rDX,rBX,
rSP,rBP,rSI,rDI, rSP,rBP,rSI,rDI,
rAL,rCL,rDL,rBL, rAL,rCL,rDL,rBL,
rAH,rCH,rDH,rBH rAH,rCH,rDH,rBH
}; };
std::map<std::string,eReg> nameToEnum = {{"es",rES},{"ds",rDS},{"cs",rCS},{"ss",rSS}};
if(nameToEnum.find(reg.name)!=nameToEnum.end())
return nameToEnum[reg.name];
assert(reg.id<sizeof(regmap)/sizeof(eReg)); assert(reg.id<sizeof(regmap)/sizeof(eReg));
assert(regmap[reg.id]!=rUNDEF); assert(regmap[reg.id]!=rUNDEF);
return regmap[reg.id]; return regmap[reg.id];
} }
LLOperand convertExpression(const x86_ea_t &from)
{
// BASE + Scale*Index + Disp
LLOperand res;
res.seg = rDS;
/*
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"
*/
if(from.base.id)
{
eReg base_reg = convertRegister(from.base);
eReg index_reg = convertRegister(from.index);
// if(base_reg==rBX)
switch(base_reg)
{
case rDI:
res.regi = INDEX_DI; break;
case rBP:
res.seg=rSS;
switch(index_reg)
{
case rDI:
res.regi = INDEX_BP_DI; break;
case rSI:
res.regi = INDEX_BP_SI; break;
case rUNDEF:
res.regi = INDEX_BP; break;
default:
assert(false);
}
break;
case rBX:
switch(index_reg)
{
case rDI:
res.regi = INDEX_BX_DI; break;
case rSI:
res.regi = INDEX_BX_SI; break;
case rUNDEF:
res.regi = INDEX_BX; break;
default:
assert(false);
}
break;
default:
assert(false);
}
assert(index_reg==rUNDEF);
}
assert(from.scale==0);
if(from.index.id)
{
assert(false);
}
res.off = from.disp;
return res;
}
LLOperand convertOperand(const x86_op_t &from) LLOperand convertOperand(const x86_op_t &from)
{ {
LLOperand res;
switch(from.type) switch(from.type)
{ {
case op_unused: case op_unused:
break; break;
case op_register: case op_register:
return LLOperand::CreateReg2(convertRegister(from.data.reg)); res.regi = convertRegister(from.data.reg); break;
case op_immediate: case op_immediate:
return LLOperand::CreateImm2(from.data.sdword); res.opz = from.data.sdword;
case op_expression:
res = convertExpression(from.data.expression); break;
case op_offset:
{
LLOperand res;
res.seg = rDS;
res.off = from.data.offset;
break;
}
default: default:
fprintf(stderr,"convertOperand does not know how to convert %d\n",from.type); fprintf(stderr,"convertOperand does not know how to convert %d\n",from.type);
} }
return LLOperand::CreateImm2(0); if(res.isSet() && (res.seg == rUNDEF))
{
res.seg = rDS;
}
return res;
} }
/***************************************************************************** /*****************************************************************************
Scans one machine instruction at offset ip in prog.Image and returns error. Scans one machine instruction at offset ip in prog.Image and returns error.
@ -481,15 +566,8 @@ eErrorId scan(uint32_t ip, ICODE &p)
if(p.insn.x86_get_branch_target()) if(p.insn.x86_get_branch_target())
decodeBranchTgt(p.insn); decodeBranchTgt(p.insn);
} }
x86_op_t *dst_op = p.insn.get_dest(); // LLOperand conv = convertOperand(*p.insn.get_dest());
static int only_first=1; // assert(conv==p.ll()->dst);
if(dst_op && only_first)
{
only_first = 0;
LLOperand conv = convertOperand(*dst_op);
p.ll()->dst=conv;
//assert(conv==p.ll()->dst);
}
if (p.ll()->getOpcode()) if (p.ll()->getOpcode())
{ {
/* Save bytes of image used */ /* Save bytes of image used */
@ -552,7 +630,7 @@ static void setAddress(int i, bool fdst, uint16_t seg, int16_t reg, uint16_t off
/* If not to register (i.e. to r/m), and talking about r/m, then this is dest */ /* 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) ? pm = (!(stateTable[i].flg & TO_REG) == fdst) ?
&pIcode->ll()->dst : &pIcode->ll()->src(); &pIcode->ll()->m_dst : &pIcode->ll()->src();
/* Set segment. A later procedure (lookupAddr in proclist.c) will /* Set segment. A later procedure (lookupAddr in proclist.c) will
* provide the value of this segment in the field segValue. */ * provide the value of this segment in the field segValue. */
@ -619,7 +697,7 @@ static void rm(int i)
} }
//pIcode->insn.get_dest()-> //pIcode->insn.get_dest()->
if ((stateTable[i].flg & NSP) && (pIcode->ll()->src().getReg2()==rSP || if ((stateTable[i].flg & NSP) && (pIcode->ll()->src().getReg2()==rSP ||
pIcode->ll()->dst.getReg2()==rSP)) pIcode->ll()->m_dst.getReg2()==rSP))
pIcode->ll()->setFlags(NOT_HLL); pIcode->ll()->setFlags(NOT_HLL);
} }
@ -656,10 +734,9 @@ static void segrm(int i)
static void regop(int i) static void regop(int i)
{ {
setAddress(i, false, 0, ((int16_t)i & 7) + rAX, 0); setAddress(i, false, 0, ((int16_t)i & 7) + rAX, 0);
pIcode->ll()->replaceDst(LLOperand::CreateReg2(pIcode->ll()->src().getReg2())); pIcode->ll()->replaceDst(pIcode->ll()->src());
// pIcode->ll()->dst.regi = pIcode->ll()->src.regi;
}
}
/***************************************************************************** /*****************************************************************************
segop - seg encoded in middle of opcode segop - seg encoded in middle of opcode
@ -767,7 +844,7 @@ static void trans(int i)
if ((uint8_t)REG(*pInst) < 2 || !(stateTable[i].flg & B)) { /* INC & DEC */ if ((uint8_t)REG(*pInst) < 2 || !(stateTable[i].flg & B)) { /* INC & DEC */
ll->setOpcode(transTable[REG(*pInst)]); /* valid on bytes */ ll->setOpcode(transTable[REG(*pInst)]); /* valid on bytes */
rm(i); rm(i);
ll->replaceSrc( pIcode->ll()->dst ); ll->replaceSrc( pIcode->ll()->m_dst );
if (ll->match(iJMP) || ll->match(iCALL) || ll->match(iCALLF)) if (ll->match(iJMP) || ll->match(iCALL) || ll->match(iCALLF))
ll->setFlags(NO_OPS); ll->setFlags(NO_OPS);
else if (ll->match(iINC) || ll->match(iPUSH) || ll->match(iDEC)) else if (ll->match(iINC) || ll->match(iPUSH) || ll->match(iDEC))
@ -799,7 +876,7 @@ static void arith(int i)
} }
else if (!(opcode == iNOT || opcode == iNEG)) else if (!(opcode == iNOT || opcode == iNEG))
{ {
pIcode->ll()->replaceSrc( pIcode->ll()->dst ); pIcode->ll()->replaceSrc( pIcode->ll()->m_dst );
setAddress(i, true, 0, rAX, 0); /* dst = AX */ setAddress(i, true, 0, rAX, 0); /* dst = AX */
} }
else if (opcode == iNEG || opcode == iNOT) else if (opcode == iNEG || opcode == iNOT)
@ -838,7 +915,7 @@ static void data2(int )
* set to NO_OPS. */ * set to NO_OPS. */
if (pIcode->ll()->getOpcode() == iENTER) if (pIcode->ll()->getOpcode() == iENTER)
{ {
pIcode->ll()->dst.off = getWord(); pIcode->ll()->m_dst.off = getWord();
pIcode->ll()->setFlags(NO_OPS); pIcode->ll()->setFlags(NO_OPS);
} }
else else