diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index b4dc56f2..2cc88f23 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -4816,7 +4816,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } // Sync PC in advance - gen_jmp_im(s, pc_start); + gen_jmp_im(s, pc_start - s->cs_base); // save the last operand prev_op = tcg_last_op(tcg_ctx); @@ -9314,7 +9314,7 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) DisasContext *dc = container_of(dcbase, DisasContext, base); TCGContext *tcg_ctx = dc->uc->tcg_ctx; - dc->prev_pc = dc->base.pc_next; + dc->prev_pc = dc->base.pc_next - dc->cs_base; tcg_gen_insn_start(tcg_ctx, dc->base.pc_next, dc->cc_op); } diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index ddc84710..110e4b41 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -1229,6 +1229,36 @@ static void test_x86_lazy_mapping(void) OK(uc_close(uc)); } +static void test_x86_16_incorrect_ip_cb(uc_engine *uc, uint64_t address, uint32_t size, void* data) +{ + uint16_t cs, ip; + + OK(uc_reg_read(uc, UC_X86_REG_CS, &cs)); + OK(uc_reg_read(uc, UC_X86_REG_IP, &ip)); + + TEST_CHECK(cs == 0x20); + TEST_CHECK(address == ((cs << 4) + ip)); +} + +static void test_x86_16_incorrect_ip(void) +{ + uc_engine *uc; + uc_hook hk1, hk2; + uint16_t cs = 0x20; + char code[] = "\x41"; // INC cx; + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_16, code, sizeof(code) - 1); + + OK(uc_hook_add(uc, &hk1, UC_HOOK_BLOCK, test_x86_16_incorrect_ip_cb, NULL, 1, 0)); + OK(uc_hook_add(uc, &hk2, UC_HOOK_CODE, test_x86_16_incorrect_ip_cb, NULL, 1, 0)); + + OK(uc_reg_write(uc, UC_X86_REG_CS, &cs)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_close(uc)); +} + TEST_LIST = { {"test_x86_in", test_x86_in}, {"test_x86_out", test_x86_out}, @@ -1271,4 +1301,5 @@ TEST_LIST = { {"test_x86_unaligned_access", test_x86_unaligned_access}, #endif {"test_x86_lazy_mapping", test_x86_lazy_mapping}, + {"test_x86_16_incorrect_ip", test_x86_16_incorrect_ip}, {NULL, NULL}};