diff --git a/gen/x86_table.js b/gen/x86_table.js index a4fd3d9d..023a568e 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -287,9 +287,9 @@ const encodings = [ { opcode: 0xD9, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1 }, // skipped: #ud not supported by nasmtests in compiled code { opcode: 0xD9, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, only_reg: 1 }, // fldenv - { opcode: 0xD9, e: 1, fixed_g: 5, custom: 0, is_fpu: 1, task_switch_test: 1, }, + { opcode: 0xD9, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xD9, e: 1, fixed_g: 6, custom: 0, is_fpu: 1, task_switch_test: 1, skip: 1, }, // fstenv (mem), fprem (reg) - { opcode: 0xD9, e: 1, fixed_g: 7, custom: 0, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem + { opcode: 0xD9, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, only_mem: 1, }, // fprem { opcode: 0xDA, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, }, { opcode: 0xDA, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index f1be2ef4..6e00cf8d 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -8,6 +8,7 @@ pub const TIMESTAMP_COUNTER: u32 = 664; pub const SEGMENT_OFFSETS: u32 = 736; pub const OPSTATS_BUFFER: u32 = 0x1000; pub const OPSTATS_BUFFER_0F: u32 = 0x1400; +pub const FPU_CONTROL_WORD: u32 = 1036; pub const TLB_DATA: u32 = 0x400000; pub fn get_reg8_offset(r: u32) -> u32 { diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 093e6527..ded47f51 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1959,6 +1959,36 @@ pub fn instr_D9_3_reg_jit(ctx: &mut JitContext, r: u32) { codegen::gen_fn1_const(ctx.builder, "fpu_fstp", r); } +pub fn instr_D9_5_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + ctx.builder + .instruction_body + .const_i32(global_pointers::FPU_CONTROL_WORD as i32); + codegen::gen_modrm_resolve(ctx, modrm_byte); + codegen::gen_safe_read16(ctx); + ctx.builder.instruction_body.store_aligned_u16(0); +} +pub fn instr_D9_5_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "instr_D9_5_reg", r); +} +pub fn instr_D9_7_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { + codegen::gen_modrm_resolve(ctx, modrm_byte); + let address_local = ctx.builder.set_new_local(); + ctx.builder + .instruction_body + .const_i32(global_pointers::FPU_CONTROL_WORD as i32); + ctx.builder + .instruction_body + .const_i32(global_pointers::FPU_CONTROL_WORD as i32); + ctx.builder.instruction_body.load_aligned_u16_from_stack(0); + let value_local = ctx.builder.set_new_local(); + codegen::gen_safe_write16(ctx, &address_local, &value_local); + ctx.builder.free_local(address_local); + ctx.builder.free_local(value_local); +} +pub fn instr_D9_7_reg_jit(ctx: &mut JitContext, r: u32) { + codegen::gen_fn1_const(ctx.builder, "instr_D9_7_reg", r); +} + pub fn instr_DB_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) { codegen::gen_modrm_resolve(ctx, modrm_byte); codegen::gen_safe_read32(ctx);