Skip to content
This repository was archived by the owner on Jan 28, 2023. It is now read-only.

Commit 3228f29

Browse files
authored
Merge pull request #67 from AlexAltea/bug-movzx
Fixed mov/movzx instruction emulation
2 parents e23a8dd + 19ab700 commit 3228f29

2 files changed

Lines changed: 67 additions & 6 deletions

File tree

core/emulate.c

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@
9292
DECL_DECODER(op_none);
9393
DECL_DECODER(op_modrm_reg);
9494
DECL_DECODER(op_modrm_rm);
95+
DECL_DECODER(op_modrm_rm8);
96+
DECL_DECODER(op_modrm_rm16);
9597
DECL_DECODER(op_vex_reg);
9698
DECL_DECODER(op_moffs);
9799
DECL_DECODER(op_simm);
@@ -142,6 +144,7 @@ static void em_andn_soft(struct em_context_t *ctxt);
142144
static void em_bextr_soft(struct em_context_t *ctxt);
143145
static void em_mov(struct em_context_t *ctxt);
144146
static void em_movzx(struct em_context_t *ctxt);
147+
static void em_movsx(struct em_context_t *ctxt);
145148
static void em_xchg(struct em_context_t *ctxt);
146149

147150
static const struct em_opcode_t opcode_group1[8] = {
@@ -235,8 +238,12 @@ static const struct em_opcode_t opcode_table_0F[256] = {
235238
/* 0xB0 - 0xBF */
236239
X4(N),
237240
X2(N),
238-
I2_BV(em_movzx, op_modrm_reg, op_modrm_rm, op_none, INSN_MODRM | INSN_MOV),
239-
X8(N),
241+
I(em_movzx, op_modrm_reg, op_modrm_rm8, op_none, INSN_MODRM | INSN_MOV),
242+
I(em_movzx, op_modrm_reg, op_modrm_rm16, op_none, INSN_MODRM | INSN_MOV),
243+
X4(N),
244+
X2(N),
245+
I(em_movsx, op_modrm_reg, op_modrm_rm8, op_none, INSN_MODRM | INSN_MOV),
246+
I(em_movsx, op_modrm_reg, op_modrm_rm16, op_none, INSN_MODRM | INSN_MOV),
240247
/* 0xC0 - 0xFF */
241248
X16(N), X16(N), X16(N), X16(N),
242249
};
@@ -397,6 +404,7 @@ static em_status_t operand_read(struct em_context_t *ctxt,
397404
static em_status_t operand_write(struct em_context_t *ctxt,
398405
struct em_operand_t *op)
399406
{
407+
size_t size;
400408
em_status_t rc;
401409
if (op->flags & OP_WRITE_FINISHED) {
402410
return EM_CONTINUE;
@@ -408,7 +416,8 @@ static em_status_t operand_write(struct em_context_t *ctxt,
408416
rc = EM_CONTINUE;
409417
break;
410418
case OP_REG:
411-
WRITE_GPR(op->reg.index, op->value, op->size);
419+
size = (op->size == 4) ? 8 : op->size;
420+
WRITE_GPR(op->reg.index, op->value, size);
412421
rc = EM_CONTINUE;
413422
break;
414423
case OP_MEM:
@@ -682,6 +691,24 @@ static em_status_t decode_op_modrm_rm(em_context_t *ctxt,
682691
return EM_CONTINUE;
683692
}
684693

694+
static em_status_t decode_op_modrm_rm8(em_context_t *ctxt,
695+
em_operand_t *op)
696+
{
697+
em_status_t rc;
698+
rc = decode_op_modrm_rm(ctxt, op);
699+
op->size = 1;
700+
return rc;
701+
}
702+
703+
static em_status_t decode_op_modrm_rm16(em_context_t *ctxt,
704+
em_operand_t *op)
705+
{
706+
em_status_t rc;
707+
rc = decode_op_modrm_rm(ctxt, op);
708+
op->size = 2;
709+
return rc;
710+
}
711+
685712
static em_status_t decode_op_vex_reg(em_context_t *ctxt,
686713
em_operand_t *op)
687714
{
@@ -823,9 +850,19 @@ static void em_mov(struct em_context_t *ctxt)
823850

824851
static void em_movzx(struct em_context_t *ctxt)
825852
{
826-
uint64_t value = 0;
827-
memcpy(&value, &ctxt->src1, ctxt->operand_size);
828-
ctxt->dst.value = value;
853+
ctxt->dst.value = 0;
854+
memcpy(&ctxt->dst.value, &ctxt->src1.value, ctxt->src1.size);
855+
}
856+
857+
static void em_movsx(struct em_context_t *ctxt)
858+
{
859+
uint64_t extension = 0;
860+
if (ctxt->src1.value & (1ULL << ((8 * ctxt->src1.size) - 1))) {
861+
extension = ~0ULL;
862+
}
863+
ctxt->dst.value = 0;
864+
memcpy(&ctxt->dst.value, &extension, ctxt->dst.size);
865+
memcpy(&ctxt->dst.value, &ctxt->src1.value, ctxt->src1.size);
829866
}
830867

831868
static void em_xchg(struct em_context_t *ctxt)

tests/test_emulator.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,30 @@ TEST_F(EmulatorTest, insn_movs) {
575575
run("rep movsw", vcpu_original, vcpu_expected);
576576
}
577577

578+
TEST_F(EmulatorTest, insn_movzx) {
579+
test_cpu_t vcpu_original;
580+
test_cpu_t vcpu_expected;
581+
582+
vcpu_original = {};
583+
vcpu_original.gpr[REG_RAX] = 0xFFFFFFFF'FFFFFFFF;
584+
vcpu_original.gpr[REG_RCX] = 0xF0F1F2F3'F4F5F6F7;
585+
vcpu_expected = vcpu_original;
586+
vcpu_expected.gpr[REG_RAX] = 0x00000000'0000F6F7;
587+
run("movzx eax, cx", vcpu_original, vcpu_expected);
588+
}
589+
590+
TEST_F(EmulatorTest, insn_movsx) {
591+
test_cpu_t vcpu_original;
592+
test_cpu_t vcpu_expected;
593+
594+
vcpu_original = {};
595+
vcpu_original.gpr[REG_RAX] = 0xFFFFFFFF'FFFFFFFF;
596+
vcpu_original.gpr[REG_RCX] = 0xF0F1F2F3'F4F5F6F7;
597+
vcpu_expected = vcpu_original;
598+
vcpu_expected.gpr[REG_RAX] = 0x00000000'FFFFF6F7;
599+
run("movsx eax, cx", vcpu_original, vcpu_expected);
600+
}
601+
578602
TEST_F(EmulatorTest, insn_or) {
579603
test_alu_2op<8>("or", {
580604
{ 0x55, 0xF0, RFLAGS_CF,

0 commit comments

Comments
 (0)