Skip to content

Commit

Permalink
libemu: fix 'test dword ptr [reg], imm'.
Browse files Browse the repository at this point in the history
The instruction length decoder properly decoded its length, but eip was not
incremented properly. This is because the immediate argument was never read.
'Test' is the only instruction in group3_f6/f7 with immediate values, which means we
can't just add II_IMM to the instruction description as it would break the other
instructions in the group.
So use the 'type' flag in the instruction to denote that the first instruction
in the group can have immediate values.
Now this instruction is emulated properly, and eip is incremented correctly too.
I used this small function to test:
00000000 <main>:
   0:	f7 01 ff ff ff ff    	testl  $0xffffffff,(%ecx)
   6:	67 f7 07 ff ff ff ff 	addr16 testl $0xffffffff,(%bx)
   d:	f7 d3                	not    %ebx
   f:	66 f7 d1             	not    %cx
  12:	f7 d8                	neg    %eax
  14:	66 f7 da             	neg    %dx
  17:	f7 e3                	mul    %ebx
  19:	66 f7 e2             	mul    %dx
  1c:	f7 eb                	imul   %ebx
  1e:	66 f7 e8             	imul   %ax
  21:	f7 f3                	div    %ebx
  23:	66 f7 f1             	div    %cx
  26:	c3                   	ret

Signed-off-by: Török Edwin <[email protected]>
Signed-off-by: common <[email protected]>
  • Loading branch information
edwintorok authored and common committed Oct 17, 2010
1 parent c19f20a commit e79dc96
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 4 deletions.
4 changes: 2 additions & 2 deletions include/emu/emu_cpu_itables.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,8 @@ struct emu_cpu_instruction_info ii_onebyte[0x100] = {
/* f3 */ {prefix_fn, 0, {0, 0, 0, 0, 0, 0, 0, 0}},
/* f4 */ {0, 0, {0, 0, 0, 0, 0, 0, 0, 0}},
/* f5 */ {instr_cmc_f5, "cmc", {0, 0, 0, 0, 0, 0, 0, 0}},
/* f6 */ {instr_group_3_f6, "group3", {0, 0, II_MOD_REG_RM, 0, 0, 0, 0, 0}},
/* f7 */ {instr_group_3_f7, "group3", {0, 0, II_MOD_REG_RM, 0, 0, 0, 0, 0}},
/* f6 */ {instr_group_3_f6, "group3", {0, 0, II_MOD_REG_RM, 0, 0, 0, 1, 0}},
/* f7 */ {instr_group_3_f7, "group3", {0, 0, II_MOD_REG_RM, 0, 0, 0, 1, 0}},
/* f8 */ {instr_clc_f8, "clc", {0, 0, 0, 0, 0, 0, 0, 0}},
/* f9 */ {instr_stc_f9, "stc", {0, 0, 0, 0, 0, 0, 0, 0}},
/* fa */ {0, 0, {0, 0, 0, 0, 0, 0, 0, 0}},
Expand Down
5 changes: 3 additions & 2 deletions src/emu_cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,8 @@ int32_t emu_cpu_parse(struct emu_cpu *c)
c->instr.cpu.operand_size = OPSIZE_16;
else if( c->cpu_instr_info->format.imm_data == II_IMM32 || c->cpu_instr_info->format.disp_data == II_DISP32 )
c->instr.cpu.operand_size = OPSIZE_32;
else if( c->cpu_instr_info->format.imm_data == II_IMM || c->cpu_instr_info->format.disp_data == II_DISPF )
else if( c->cpu_instr_info->format.imm_data == II_IMM || c->cpu_instr_info->format.disp_data == II_DISPF
|| (c->cpu_instr_info->format.type && !c->instr.cpu.modrm.opc))
{
if( c->cpu_instr_info->format.w_bit == 1 && c->instr.cpu.w_bit == 0 )
c->instr.cpu.operand_size = OPSIZE_8;
Expand All @@ -664,7 +665,7 @@ int32_t emu_cpu_parse(struct emu_cpu *c)
}

/* imm */
if( c->cpu_instr_info->format.imm_data != 0 )
if( c->cpu_instr_info->format.imm_data != 0 || (c->cpu_instr_info->format.type && !c->instr.cpu.modrm.opc))
{
if( c->instr.cpu.operand_size == OPSIZE_32 )
{
Expand Down

0 comments on commit e79dc96

Please sign in to comment.