diff --git a/gen/x86_table.js b/gen/x86_table.js index fbec61b7..98ae9638 100644 --- a/gen/x86_table.js +++ b/gen/x86_table.js @@ -460,7 +460,7 @@ const encodings = [ { opcode: 0x0F27, skip: 1, block_boundary: 1, }, { opcode: 0x0F30, skip: 1, block_boundary: 1, }, // wrmsr - { opcode: 0x0F31, skip: 1, block_boundary: 1, }, // rdtsc + { opcode: 0x0F31, skip: 1, custom: 1, }, // rdtsc { opcode: 0x0F32, skip: 1, block_boundary: 1, }, // rdmsr { opcode: 0x0F33, skip: 1, block_boundary: 1, }, // rdpmc { opcode: 0x0F34, skip: 1, block_boundary: 1, no_next_instruction: 1, }, // sysenter diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index e7312dd5..59598c99 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -310,6 +310,12 @@ pub fn gen_call_fn1_f64_ret_i32(builder: &mut WasmBuilder, name: &str) { builder.call_fn(fn_idx); } +pub fn gen_call_fn0_ret_i64(builder: &mut WasmBuilder, name: &str) { + // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value + let fn_idx = builder.get_fn_idx(name, FunctionType::FN0_RET_I64_TYPE_INDEX); + builder.call_fn(fn_idx); +} + pub fn gen_call_fn1_ret_i64(builder: &mut WasmBuilder, name: &str) { // generates: fn( _ ) where _ must be left on the stack before calling this, and fn returns a value let fn_idx = builder.get_fn_idx(name, FunctionType::FN1_RET_I64_TYPE_INDEX); diff --git a/src/rust/cpu2/cpu.rs b/src/rust/cpu2/cpu.rs index d8437db7..5a741572 100644 --- a/src/rust/cpu2/cpu.rs +++ b/src/rust/cpu2/cpu.rs @@ -3275,6 +3275,7 @@ pub unsafe fn set_tsc(low: u32, high: u32) { tsc_offset = current_value.wrapping_sub(new_value); } +#[no_mangle] pub unsafe fn read_tsc() -> u64 { let n = microtick() * TSC_RATE; let value = (n as u64).wrapping_sub(tsc_offset); diff --git a/src/rust/global_pointers.rs b/src/rust/global_pointers.rs index 67ab343c..82f18c10 100644 --- a/src/rust/global_pointers.rs +++ b/src/rust/global_pointers.rs @@ -9,6 +9,7 @@ pub const PAGE_FAULT: u32 = 540; pub const INSTRUCTION_POINTER: u32 = 556; pub const PREVIOUS_IP: u32 = 560; pub const CR: u32 = 580; +pub const CPL: u32 = 612; pub const TIMESTAMP_COUNTER: u32 = 664; pub const SREG: u32 = 668; diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index 2bca1793..3b3c4cdc 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -3870,6 +3870,37 @@ pub fn instr32_AF_jit(ctx: &mut JitContext) { gen_string_ins(ctx, String::SCAS, pub fn instr32_F2AF_jit(ctx: &mut JitContext) { gen_string_ins(ctx, String::SCAS, 32, 0xF2) } pub fn instr32_F3AF_jit(ctx: &mut JitContext) { gen_string_ins(ctx, String::SCAS, 32, 0xF3) } +pub fn instr_0F31_jit(ctx: &mut JitContext) { + ctx.builder.load_fixed_u8(global_pointers::CPL); + ctx.builder.eqz_i32(); + + dbg_assert!(regs::CR4_TSD < 0x100); + ctx.builder + .load_fixed_u8(global_pointers::get_creg_offset(4)); + ctx.builder.const_i32(regs::CR4_TSD as i32); + ctx.builder.and_i32(); + ctx.builder.eqz_i32(); + + ctx.builder.or_i32(); + ctx.builder.if_void(); + codegen::gen_call_fn0_ret_i64(ctx.builder, "read_tsc"); + + let tsc = ctx.builder.tee_new_local_i64(); + ctx.builder.wrap_i64_to_i32(); + codegen::gen_set_reg32(ctx, regs::EAX); + + ctx.builder.get_local_i64(&tsc); + ctx.builder.const_i64(32); + ctx.builder.shr_u_i64(); + ctx.builder.wrap_i64_to_i32(); + codegen::gen_set_reg32(ctx, regs::EDX); + + ctx.builder.free_local_i64(tsc); + ctx.builder.else_(); + codegen::gen_trigger_gp(ctx, 0); + ctx.builder.block_end(); +} + pub fn instr_0F18_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) { modrm::skip(ctx.cpu, modrm_byte); } diff --git a/src/rust/regs.rs b/src/rust/regs.rs index 007953dc..37af6892 100644 --- a/src/rust/regs.rs +++ b/src/rust/regs.rs @@ -34,3 +34,5 @@ pub const BH: u32 = 7; pub const CR0_EM: u32 = 1 << 2; pub const CR0_TS: u32 = 1 << 3; + +pub const CR4_TSD: u32 = 1 << 2; diff --git a/src/rust/wasmgen/wasm_builder.rs b/src/rust/wasmgen/wasm_builder.rs index b0cdf2aa..2c75d437 100644 --- a/src/rust/wasmgen/wasm_builder.rs +++ b/src/rust/wasmgen/wasm_builder.rs @@ -14,6 +14,7 @@ pub enum FunctionType { FN3_TYPE_INDEX, FN0_RET_TYPE_INDEX, + FN0_RET_I64_TYPE_INDEX, FN1_RET_TYPE_INDEX, FN2_RET_TYPE_INDEX, @@ -244,6 +245,12 @@ impl WasmBuilder { self.output.push(1); self.output.push(op::TYPE_I32); }, + FunctionType::FN0_RET_I64_TYPE_INDEX => { + self.output.push(op::TYPE_FUNC); + self.output.push(0); + self.output.push(1); + self.output.push(op::TYPE_I64); + }, FunctionType::FN1_RET_TYPE_INDEX => { self.output.push(op::TYPE_FUNC); self.output.push(1);