diff --git a/gen/x86_table.js b/gen/x86_table.js index 913d2ede..c012eb28 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -187,7 +187,7 @@ const encodings = [ { opcode: 0x8C, os: 1, e: 1, custom: 1 }, // mov reg, sreg { opcode: 0x8D, reg_ud: 1, os: 1, e: 1, custom_modrm_resolve: 1, custom: 1, }, // lea - { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, }, // mov sreg + { opcode: 0x8E, block_boundary: 1, e: 1, skip: 1, custom: 1 }, // mov sreg { opcode: 0x8F, os: 1, e: 1, fixed_g: 0, custom_modrm_resolve: 1, custom: 1, block_boundary: 1, }, // pop r/m { opcode: 0x90, custom: 1, }, diff --git a/src/rust/cpu/cpu.rs b/src/rust/cpu/cpu.rs index 443afa7b..2e087483 100644 --- a/src/rust/cpu/cpu.rs +++ b/src/rust/cpu/cpu.rs @@ -2361,6 +2361,7 @@ pub unsafe fn lookup_segment_selector( Ok(Ok((descriptor, descriptor_address))) } +#[no_mangle] pub unsafe fn switch_seg(reg: i32, selector_raw: i32) -> bool { dbg_assert!(reg >= 0 && reg <= 5); dbg_assert!(selector_raw >= 0 && selector_raw < 0x10000); diff --git a/src/rust/cpu/instructions.rs b/src/rust/cpu/instructions.rs index 567a6848..dd4ff227 100644 --- a/src/rust/cpu/instructions.rs +++ b/src/rust/cpu/instructions.rs @@ -1013,11 +1013,9 @@ unsafe fn instr_8E_helper(data: i32, mod_0: i32) { trigger_ud(); }; } -#[no_mangle] pub unsafe fn instr_8E_mem(addr: i32, r: i32) { instr_8E_helper(return_on_pagefault!(safe_read16(addr)), r); } -#[no_mangle] pub unsafe fn instr_8E_reg(r1: i32, r: i32) { instr_8E_helper(read_reg16(r1), r); } pub unsafe fn instr16_8F_0_mem(modrm_byte: i32) { diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index d9a64add..f5ca4326 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -2665,6 +2665,32 @@ pub fn instr32_8D_reg_jit(ctx: &mut JitContext, _r1: u32, _r2: u32) { codegen::gen_trigger_ud(ctx); } +pub fn instr_8E_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) { + if r2 == ES || r2 == SS || r2 == DS || r2 == FS || r2 == GS { + ctx.builder.const_i32(r2 as i32); + codegen::gen_get_reg16(ctx, r1); + ctx.builder.call_fn2_ret("switch_seg"); + ctx.builder.drop_(); + } + else { + codegen::gen_trigger_ud(ctx); + } +} +pub fn instr_8E_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) { + codegen::gen_modrm_resolve_safe_read16(ctx, modrm_byte); + let seg = ctx.builder.set_new_local(); + if r == ES || r == SS || r == DS || r == FS || r == GS { + ctx.builder.const_i32(r as i32); + ctx.builder.get_local(&seg); + ctx.builder.call_fn2_ret("switch_seg"); + ctx.builder.drop_(); + } + else { + codegen::gen_trigger_ud(ctx); + } + ctx.builder.free_local(seg); +} + pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte) { // before gen_modrm_resolve, update esp to the new value codegen::gen_adjust_stack_reg(ctx, 2);