Skip to content
This repository has been archived by the owner on Sep 15, 2021. It is now read-only.

Commit

Permalink
x86: Fix moffset decoding
Browse files Browse the repository at this point in the history
Signed-off-by: Pekka Enberg <penberg@iki.fi>
  • Loading branch information
penberg committed Jan 9, 2014
1 parent 477c70a commit ef0c4d0
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
28 changes: 24 additions & 4 deletions arch/x86/x86_decode.cpp
Expand Up @@ -179,10 +179,10 @@ static const uint32_t decode_table[256] = {
/*[0x9D]*/ INSTR_POPF | ADDMODE_IMPLIED,
/*[0x9E]*/ INSTR_SAHF | ADDMODE_IMPLIED,
/*[0x9F]*/ INSTR_LAHF | ADDMODE_IMPLIED,
/*[0xA0]*/ INSTR_MOV | ADDMODE_MEM_ACC | WIDTH_BYTE, /* load */
/*[0xA1]*/ INSTR_MOV | ADDMODE_MEM_ACC | WIDTH_FULL, /* load */
/*[0xA2]*/ INSTR_MOV | ADDMODE_ACC_MEM | WIDTH_BYTE, /* store */
/*[0xA3]*/ INSTR_MOV | ADDMODE_ACC_MEM | WIDTH_FULL, /* store */
/*[0xA0]*/ INSTR_MOV | ADDMODE_MOFFSET_ACC | WIDTH_BYTE, /* load */
/*[0xA1]*/ INSTR_MOV | ADDMODE_MOFFSET_ACC | WIDTH_FULL, /* load */
/*[0xA2]*/ INSTR_MOV | ADDMODE_ACC_MOFFSET | WIDTH_BYTE, /* store */
/*[0xA3]*/ INSTR_MOV | ADDMODE_ACC_MOFFSET | WIDTH_FULL, /* store */
/*[0xA4]*/ INSTR_MOVSB | ADDMODE_IMPLIED | WIDTH_BYTE,
/*[0xA5]*/ INSTR_MOVSW | ADDMODE_IMPLIED | WIDTH_FULL,
/*[0xA6]*/ INSTR_CMPSB | ADDMODE_IMPLIED | WIDTH_BYTE,
Expand Down Expand Up @@ -318,6 +318,7 @@ decode_dst_operand(struct x86_instr *instr)
operand->type = OP_REG;
operand->reg = 0; /* AL/AX */
break;
case DST_MOFFSET:
case DST_MEM:
operand->type = OP_MEM;
operand->disp = instr->disp;
Expand Down Expand Up @@ -372,6 +373,7 @@ decode_src_operand(struct x86_instr *instr)
operand->type = OP_REG;
operand->reg = 0; /* AL/AX */
break;
case SRC_MOFFSET:
case SRC_MEM:
operand->type = OP_MEM;
operand->disp = instr->disp;
Expand Down Expand Up @@ -470,6 +472,21 @@ decode_rel(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
}
}

static void
decode_moffset(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
{
switch (instr->flags & WIDTH_MASK) {
case WIDTH_FULL:
instr->disp = read_u16(RAM, pc);
instr->nr_bytes += 2;
break;
case WIDTH_BYTE:
instr->disp = read_u8(RAM, pc);
instr->nr_bytes += 1;
break;
}
}

static void
decode_disp(struct x86_instr *instr, uint8_t* RAM, addr_t *pc)
{
Expand Down Expand Up @@ -588,6 +605,9 @@ arch_8086_decode_instr(struct x86_instr *instr, uint8_t* RAM, addr_t pc)
if (instr->flags & MEM_DISP_MASK)
decode_disp(instr, RAM, &pc);

if (instr->flags & MOFFSET_MASK)
decode_moffset(instr, RAM, &pc);

if (instr->flags & IMM_MASK)
decode_imm(instr, RAM, &pc);

Expand Down
30 changes: 17 additions & 13 deletions arch/x86/x86_decode.h
Expand Up @@ -67,22 +67,26 @@ enum x86_instr_flags {
SRC_SEG_REG = (1U << 17),
SRC_ACC = (1U << 18),
SRC_MEM = (1U << 19),
SRC_MEM_DISP_BYTE = (1U << 20),
SRC_MEM_DISP_FULL = (1U << 21),
SRC_MASK = SRC_NONE|IMM_MASK|REL_MASK|SRC_REG|SRC_SEG_REG|SRC_ACC|SRC_MEM|SRC_MEM_DISP_BYTE|SRC_MEM_DISP_FULL,
SRC_MOFFSET = (1U << 20),
SRC_MEM_DISP_BYTE = (1U << 21),
SRC_MEM_DISP_FULL = (1U << 22),
SRC_MASK = SRC_NONE|IMM_MASK|REL_MASK|SRC_REG|SRC_SEG_REG|SRC_ACC|SRC_MEM|SRC_MOFFSET|SRC_MEM_DISP_BYTE|SRC_MEM_DISP_FULL,

/* Destination operand */
DST_NONE = (1U << 22),
DST_REG = (1U << 23),
DST_ACC = (1U << 24), /* AL/AX */
DST_MEM = (1U << 25),
DST_MEM_DISP_BYTE = (1U << 26), /* 8 bits */
DST_MEM_DISP_FULL = (1U << 27), /* 16 bits or 32 bits */
DST_MASK = DST_NONE|DST_REG|DST_ACC|DST_MEM|DST_MEM_DISP_BYTE|DST_MEM_DISP_FULL,
DST_NONE = (1U << 23),
DST_REG = (1U << 24),
DST_ACC = (1U << 25), /* AL/AX */
DST_MEM = (1U << 26),
DST_MOFFSET = (1U << 27),
DST_MEM_DISP_BYTE = (1U << 28), /* 8 bits */
DST_MEM_DISP_FULL = (1U << 29), /* 16 bits or 32 bits */
DST_MASK = DST_NONE|DST_REG|DST_ACC|DST_MOFFSET|DST_MEM|DST_MEM_DISP_BYTE|DST_MEM_DISP_FULL,

MEM_DISP_MASK = SRC_MEM|SRC_MEM_DISP_BYTE|SRC_MEM_DISP_FULL|DST_MEM|DST_MEM_DISP_BYTE|DST_MEM_DISP_FULL,

GROUP_2 = (1U << 28),
MOFFSET_MASK = SRC_MOFFSET|DST_MOFFSET,

GROUP_2 = (1U << 30),

GROUP_MASK = GROUP_2,
};
Expand All @@ -91,14 +95,14 @@ enum x86_instr_flags {
* Addressing modes.
*/
enum x86_addmode {
ADDMODE_ACC_MEM = SRC_ACC|DST_MEM|DIR_REVERSED, /* AL/AX -> memory */
ADDMODE_ACC_MOFFSET = SRC_ACC|DST_MOFFSET, /* AL/AX -> moffset */
ADDMODE_ACC_REG = SRC_ACC|DST_REG, /* AL/AX -> reg */
ADDMODE_IMM = SRC_IMM|DST_NONE, /* immediate operand */
ADDMODE_IMM8_RM = SRC_IMM8|MOD_RM|DIR_REVERSED, /* immediate -> register/memory */
ADDMODE_IMM_ACC = SRC_IMM|DST_ACC, /* immediate -> AL/AX */
ADDMODE_IMM_REG = SRC_IMM|DST_REG, /* immediate -> register */
ADDMODE_IMPLIED = SRC_NONE|DST_NONE, /* no operands */
ADDMODE_MEM_ACC = SRC_ACC|DST_MEM, /* memory -> AL/AX */
ADDMODE_MOFFSET_ACC = SRC_MOFFSET|DST_ACC, /* moffset -> AL/AX */
ADDMODE_REG = SRC_REG|DST_NONE, /* register */
ADDMODE_SEG_REG = SRC_SEG_REG|DST_NONE, /* segment register */
ADDMODE_REG_RM = SRC_REG|MOD_RM|DIR_REVERSED, /* register -> register/memory */
Expand Down

0 comments on commit ef0c4d0

Please sign in to comment.