2018-07-03 17:28:33 +02:00
|
|
|
#![allow(non_snake_case)]
|
|
|
|
|
|
|
|
use codegen;
|
|
|
|
use cpu_context::CpuContext;
|
|
|
|
use global_pointers;
|
|
|
|
use jit::JitContext;
|
2018-07-24 01:58:03 +02:00
|
|
|
use modrm;
|
2018-07-03 17:28:33 +02:00
|
|
|
use prefix::SEG_PREFIX_ZERO;
|
|
|
|
use prefix::{PREFIX_66, PREFIX_67, PREFIX_F2, PREFIX_F3};
|
2018-08-16 21:37:10 +02:00
|
|
|
use regs;
|
2018-07-03 17:28:33 +02:00
|
|
|
use regs::{AX, BP, BX, CX, DI, DX, SI, SP};
|
|
|
|
use regs::{CS, DS, ES, FS, GS, SS};
|
|
|
|
use regs::{EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP};
|
|
|
|
use wasmgen::module_init::WasmBuilder;
|
2018-07-28 20:33:40 +02:00
|
|
|
use wasmgen::wasm_util::WasmBuf;
|
2018-07-03 17:28:33 +02:00
|
|
|
|
|
|
|
pub fn jit_instruction(cpu: &mut CpuContext, builder: &mut WasmBuilder, instr_flags: &mut u32) {
|
|
|
|
cpu.prefixes = 0;
|
2018-08-22 01:07:45 +02:00
|
|
|
let start_of_current_instruction = cpu.eip;
|
|
|
|
let ctx = &mut JitContext {
|
|
|
|
cpu,
|
|
|
|
builder,
|
|
|
|
start_of_current_instruction,
|
|
|
|
};
|
2018-07-03 17:28:33 +02:00
|
|
|
::gen::jit::jit(
|
|
|
|
ctx.cpu.read_imm8() as u32 | (ctx.cpu.osize_32() as u32) << 8,
|
|
|
|
ctx,
|
|
|
|
instr_flags,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn jit_handle_prefix(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
::gen::jit::jit(
|
|
|
|
ctx.cpu.read_imm8() as u32 | (ctx.cpu.osize_32() as u32) << 8,
|
|
|
|
ctx,
|
|
|
|
instr_flags,
|
|
|
|
);
|
|
|
|
codegen::gen_clear_prefixes(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn jit_handle_segment_prefix(segment: u32, ctx: &mut JitContext, instr_flags: &mut u32) {
|
2018-07-13 02:04:28 +02:00
|
|
|
dbg_assert!(segment <= 5);
|
2018-07-03 17:28:33 +02:00
|
|
|
ctx.cpu.prefixes |= segment + 1;
|
2018-07-12 23:20:58 +02:00
|
|
|
// TODO: Could merge multiple prefix updates into one
|
|
|
|
codegen::gen_add_prefix_bits(ctx, segment + 1);
|
2018-07-03 17:28:33 +02:00
|
|
|
jit_handle_prefix(ctx, instr_flags)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_0F_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
::gen::jit0f_16::jit(ctx.cpu.read_imm8(), ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr32_0F_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
::gen::jit0f_32::jit(ctx.cpu.read_imm8(), ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr_26_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
jit_handle_segment_prefix(ES, ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr_2E_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
jit_handle_segment_prefix(CS, ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr_36_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
jit_handle_segment_prefix(SS, ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr_3E_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
jit_handle_segment_prefix(DS, ctx, instr_flags)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr_64_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
jit_handle_segment_prefix(FS, ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr_65_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
jit_handle_segment_prefix(GS, ctx, instr_flags)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr_66_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
ctx.cpu.prefixes |= PREFIX_66;
|
2018-07-12 23:20:58 +02:00
|
|
|
// TODO: Could merge multiple prefix updates into one
|
|
|
|
codegen::gen_add_prefix_bits(ctx, PREFIX_66);
|
2018-07-03 17:28:33 +02:00
|
|
|
jit_handle_prefix(ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr_67_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
ctx.cpu.prefixes |= PREFIX_67;
|
2018-07-12 23:20:58 +02:00
|
|
|
// TODO: Could merge multiple prefix updates into one
|
|
|
|
codegen::gen_add_prefix_bits(ctx, PREFIX_67);
|
2018-07-03 17:28:33 +02:00
|
|
|
jit_handle_prefix(ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr_F0_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
// lock: Ignore
|
|
|
|
jit_handle_prefix(ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr_F2_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
ctx.cpu.prefixes |= PREFIX_F2;
|
2018-07-12 23:20:58 +02:00
|
|
|
// string/sse prefix: Don't generate code to update prefixes at runtime. This means runtime
|
|
|
|
// instructions can't inspect the prefixes for this flags
|
2018-07-03 17:28:33 +02:00
|
|
|
jit_handle_prefix(ctx, instr_flags)
|
|
|
|
}
|
|
|
|
pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
|
|
|
|
ctx.cpu.prefixes |= PREFIX_F3;
|
2018-07-12 23:20:58 +02:00
|
|
|
// string/sse prefix: Don't generate code to update prefixes at runtime. This means runtime
|
|
|
|
// instructions can't inspect the prefixes for this flags
|
2018-07-03 17:28:33 +02:00
|
|
|
jit_handle_prefix(ctx, instr_flags)
|
|
|
|
}
|
|
|
|
|
2018-08-20 19:18:17 +02:00
|
|
|
fn push16_reg_jit(ctx: &mut JitContext, r: u32) {
|
2018-08-22 04:06:52 +02:00
|
|
|
codegen::gen_get_reg16(ctx.builder, r);
|
2018-08-20 19:18:17 +02:00
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
codegen::gen_push16(ctx, &value_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
|
|
|
}
|
|
|
|
fn push32_reg_jit(ctx: &mut JitContext, r: u32) {
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.load_aligned_i32(global_pointers::get_reg32_offset(r));
|
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
codegen::gen_push32(ctx, &value_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
|
|
|
}
|
|
|
|
fn push16_imm_jit(ctx: &mut JitContext, imm: u32) {
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.const_i32(imm as i32);
|
2018-08-20 19:18:17 +02:00
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
codegen::gen_push16(ctx, &value_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
|
|
|
}
|
|
|
|
fn push32_imm_jit(ctx: &mut JitContext, imm: u32) {
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.const_i32(imm as i32);
|
2018-08-20 19:18:17 +02:00
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
codegen::gen_push32(ctx, &value_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
|
|
|
}
|
2018-07-03 17:28:33 +02:00
|
|
|
fn push16_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-08-20 19:18:17 +02:00
|
|
|
codegen::gen_safe_read16(ctx);
|
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
codegen::gen_push16(ctx, &value_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
fn push32_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-08-20 19:18:17 +02:00
|
|
|
codegen::gen_safe_read32(ctx);
|
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
codegen::gen_push32(ctx, &value_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) {
|
2018-08-17 18:07:21 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg16_offset(reg) as i32);
|
2018-08-17 18:07:21 +02:00
|
|
|
codegen::gen_pop16(ctx);
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_u16(0);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn pop32_reg_jit(ctx: &mut JitContext, reg: u32) {
|
2018-08-17 18:07:21 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg32_offset(reg) as i32);
|
2018-08-17 18:07:21 +02:00
|
|
|
codegen::gen_pop32s(ctx);
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
|
2018-08-23 00:21:16 +02:00
|
|
|
macro_rules! define_instruction_read8(
|
|
|
|
($fn:expr, $name_mem:ident, $name_reg:ident) => (
|
|
|
|
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read8(ctx);
|
|
|
|
codegen::gen_get_reg8(ctx.builder, r);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, $fn)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_get_reg8(ctx.builder, r1);
|
|
|
|
codegen::gen_get_reg8(ctx.builder, r2);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, $fn)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
macro_rules! define_instruction_read16(
|
|
|
|
($fn:expr, $name_mem:ident, $name_reg:ident) => (
|
|
|
|
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read16(ctx);
|
|
|
|
codegen::gen_get_reg16(ctx.builder, r);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, $fn)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_get_reg16(ctx.builder, r1);
|
|
|
|
codegen::gen_get_reg16(ctx.builder, r2);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, $fn)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
macro_rules! define_instruction_read32(
|
|
|
|
($fn:expr, $name_mem:ident, $name_reg:ident) => (
|
|
|
|
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read32(ctx);
|
|
|
|
codegen::gen_get_reg32(ctx.builder, r);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, $fn)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_get_reg32(ctx.builder, r1);
|
|
|
|
codegen::gen_get_reg32(ctx.builder, r2);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, $fn)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
macro_rules! define_instruction_write_reg8(
|
|
|
|
($fn:expr, $name_mem:ident, $name_reg:ident) => (
|
|
|
|
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r) as i32);
|
|
|
|
codegen::gen_get_reg8(ctx.builder, r);
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read8(ctx);
|
|
|
|
codegen::gen_call_fn2_ret(ctx.builder, $fn);
|
|
|
|
ctx.builder.instruction_body.store_u8(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
ctx.builder.instruction_body.const_i32(global_pointers::get_reg8_offset(r2) as i32);
|
|
|
|
codegen::gen_get_reg8(ctx.builder, r2);
|
|
|
|
codegen::gen_get_reg8(ctx.builder, r1);
|
|
|
|
codegen::gen_call_fn2_ret(ctx.builder, $fn);
|
|
|
|
ctx.builder.instruction_body.store_u8(0);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
macro_rules! define_instruction_write_reg16(
|
|
|
|
($fn:expr, $name_mem:ident, $name_reg:ident) => (
|
|
|
|
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r) as i32);
|
|
|
|
codegen::gen_get_reg16(ctx.builder, r);
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read16(ctx);
|
|
|
|
codegen::gen_call_fn2_ret(ctx.builder, $fn);
|
|
|
|
ctx.builder.instruction_body.store_aligned_u16(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
ctx.builder.instruction_body.const_i32(global_pointers::get_reg16_offset(r2) as i32);
|
|
|
|
codegen::gen_get_reg16(ctx.builder, r2);
|
|
|
|
codegen::gen_get_reg16(ctx.builder, r1);
|
|
|
|
codegen::gen_call_fn2_ret(ctx.builder, $fn);
|
|
|
|
ctx.builder.instruction_body.store_aligned_u16(0);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
macro_rules! define_instruction_write_reg32(
|
|
|
|
($fn:expr, $name_mem:ident, $name_reg:ident) => (
|
|
|
|
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r) as i32);
|
|
|
|
codegen::gen_get_reg32(ctx.builder, r);
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read32(ctx);
|
|
|
|
codegen::gen_call_fn2_ret(ctx.builder, $fn);
|
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
ctx.builder.instruction_body.const_i32(global_pointers::get_reg32_offset(r2) as i32);
|
|
|
|
codegen::gen_get_reg32(ctx.builder, r2);
|
|
|
|
codegen::gen_get_reg32(ctx.builder, r1);
|
|
|
|
codegen::gen_call_fn2_ret(ctx.builder, $fn);
|
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
define_instruction_write_reg8!("add8", instr_02_mem_jit, instr_02_reg_jit);
|
|
|
|
define_instruction_write_reg16!("add16", instr16_03_mem_jit, instr16_03_reg_jit);
|
|
|
|
define_instruction_write_reg32!("add32", instr32_03_mem_jit, instr32_03_reg_jit);
|
|
|
|
|
|
|
|
define_instruction_write_reg8!("or8", instr_0A_mem_jit, instr_0A_reg_jit);
|
|
|
|
define_instruction_write_reg16!("or16", instr16_0B_mem_jit, instr16_0B_reg_jit);
|
|
|
|
define_instruction_write_reg32!("or32", instr32_0B_mem_jit, instr32_0B_reg_jit);
|
|
|
|
|
|
|
|
define_instruction_write_reg8!("adc8", instr_12_mem_jit, instr_12_reg_jit);
|
|
|
|
define_instruction_write_reg16!("adc16", instr16_13_mem_jit, instr16_13_reg_jit);
|
|
|
|
define_instruction_write_reg32!("adc32", instr32_13_mem_jit, instr32_13_reg_jit);
|
|
|
|
|
|
|
|
define_instruction_write_reg8!("sbb8", instr_1A_mem_jit, instr_1A_reg_jit);
|
|
|
|
define_instruction_write_reg16!("sbb16", instr16_1B_mem_jit, instr16_1B_reg_jit);
|
|
|
|
define_instruction_write_reg32!("sbb32", instr32_1B_mem_jit, instr32_1B_reg_jit);
|
|
|
|
|
|
|
|
define_instruction_write_reg8!("and8", instr_22_mem_jit, instr_22_reg_jit);
|
|
|
|
define_instruction_write_reg16!("and16", instr16_23_mem_jit, instr16_23_reg_jit);
|
|
|
|
define_instruction_write_reg32!("and32", instr32_23_mem_jit, instr32_23_reg_jit);
|
|
|
|
|
|
|
|
define_instruction_write_reg8!("sub8", instr_2A_mem_jit, instr_2A_reg_jit);
|
|
|
|
define_instruction_write_reg16!("sub16", instr16_2B_mem_jit, instr16_2B_reg_jit);
|
|
|
|
define_instruction_write_reg32!("sub32", instr32_2B_mem_jit, instr32_2B_reg_jit);
|
|
|
|
|
|
|
|
define_instruction_write_reg8!("xor8", instr_32_mem_jit, instr_32_reg_jit);
|
|
|
|
define_instruction_write_reg16!("xor16", instr16_33_mem_jit, instr16_33_reg_jit);
|
|
|
|
define_instruction_write_reg32!("xor32", instr32_33_mem_jit, instr32_33_reg_jit);
|
|
|
|
|
|
|
|
define_instruction_read8!("cmp8", instr_38_mem_jit, instr_38_reg_jit);
|
|
|
|
define_instruction_read16!("cmp16", instr16_39_mem_jit, instr16_39_reg_jit);
|
|
|
|
define_instruction_read32!("cmp32", instr32_39_mem_jit, instr32_39_reg_jit);
|
|
|
|
|
|
|
|
pub fn instr_3A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
codegen::gen_get_reg8(ctx.builder, r);
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read8(ctx);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, "cmp8")
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr_3A_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_get_reg8(ctx.builder, r2);
|
|
|
|
codegen::gen_get_reg8(ctx.builder, r1);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, "cmp8")
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
codegen::gen_get_reg16(ctx.builder, r);
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read16(ctx);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, "cmp16")
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_get_reg16(ctx.builder, r2);
|
|
|
|
codegen::gen_get_reg16(ctx.builder, r1);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, "cmp16")
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr32_3B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
codegen::gen_get_reg32(ctx.builder, r);
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read32(ctx);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, "cmp32")
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr32_3B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_get_reg32(ctx.builder, r2);
|
|
|
|
codegen::gen_get_reg32(ctx.builder, r1);
|
|
|
|
codegen::gen_call_fn2(ctx.builder, "cmp32")
|
|
|
|
}
|
|
|
|
|
2018-07-03 17:28:33 +02:00
|
|
|
pub fn instr16_50_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, AX); }
|
|
|
|
pub fn instr32_50_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EAX); }
|
|
|
|
pub fn instr16_51_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, CX); }
|
|
|
|
pub fn instr32_51_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, ECX); }
|
|
|
|
pub fn instr16_52_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, DX); }
|
|
|
|
pub fn instr32_52_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EDX); }
|
|
|
|
pub fn instr16_53_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, BX); }
|
|
|
|
pub fn instr32_53_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EBX); }
|
|
|
|
pub fn instr16_54_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, SP); }
|
|
|
|
pub fn instr32_54_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, ESP); }
|
|
|
|
pub fn instr16_55_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, BP); }
|
|
|
|
pub fn instr32_55_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EBP); }
|
|
|
|
pub fn instr16_56_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, SI); }
|
|
|
|
pub fn instr32_56_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, ESI); }
|
|
|
|
pub fn instr16_57_jit(ctx: &mut JitContext) { push16_reg_jit(ctx, DI); }
|
|
|
|
pub fn instr32_57_jit(ctx: &mut JitContext) { push32_reg_jit(ctx, EDI); }
|
|
|
|
|
|
|
|
pub fn instr16_58_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, AX); }
|
|
|
|
pub fn instr32_58_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EAX); }
|
|
|
|
pub fn instr16_59_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, CX); }
|
|
|
|
pub fn instr32_59_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, ECX); }
|
|
|
|
pub fn instr16_5A_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, DX); }
|
|
|
|
pub fn instr32_5A_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EDX); }
|
|
|
|
pub fn instr16_5B_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, BX); }
|
|
|
|
pub fn instr32_5B_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EBX); }
|
|
|
|
// hole for pop esp
|
|
|
|
pub fn instr16_5D_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, BP); }
|
|
|
|
pub fn instr32_5D_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EBP); }
|
|
|
|
pub fn instr16_5E_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, SI); }
|
|
|
|
pub fn instr32_5E_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, ESI); }
|
|
|
|
pub fn instr16_5F_jit(ctx: &mut JitContext) { pop16_reg_jit(ctx, DI); }
|
|
|
|
pub fn instr32_5F_jit(ctx: &mut JitContext) { pop32_reg_jit(ctx, EDI); }
|
|
|
|
|
|
|
|
pub fn instr16_68_jit(ctx: &mut JitContext, imm16: u32) { push16_imm_jit(ctx, imm16) }
|
|
|
|
pub fn instr32_68_jit(ctx: &mut JitContext, imm32: u32) { push32_imm_jit(ctx, imm32) }
|
|
|
|
pub fn instr16_6A_jit(ctx: &mut JitContext, imm16: u32) { push16_imm_jit(ctx, imm16) }
|
|
|
|
pub fn instr32_6A_jit(ctx: &mut JitContext, imm32: u32) { push32_imm_jit(ctx, imm32) }
|
|
|
|
|
|
|
|
// Code for conditional jumps is generated automatically by the basic block codegen
|
|
|
|
pub fn instr16_70_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_70_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_71_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_71_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_72_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_72_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_73_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_73_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_74_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_74_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_75_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_75_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_76_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_76_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_77_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_77_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_78_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_78_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_79_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_79_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_7A_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_7A_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_7B_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_7B_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_7C_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_7C_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_7D_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_7D_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_7E_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_7E_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_7F_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_7F_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
|
2018-08-23 00:21:16 +02:00
|
|
|
define_instruction_read8!("test8", instr_84_mem_jit, instr_84_reg_jit);
|
|
|
|
define_instruction_read16!("test16", instr16_85_mem_jit, instr16_85_reg_jit);
|
|
|
|
define_instruction_read32!("test32", instr32_85_mem_jit, instr32_85_reg_jit);
|
2018-08-22 04:49:29 +02:00
|
|
|
|
2018-08-22 02:36:44 +02:00
|
|
|
pub fn instr_88_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
|
|
|
|
let address_local = ctx.builder.set_new_local();
|
|
|
|
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg8_offset(r) as i32);
|
2018-08-22 02:36:44 +02:00
|
|
|
ctx.builder.instruction_body.load_u8_from_stack(0);
|
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
|
|
|
|
codegen::gen_safe_write8(ctx, &address_local, &value_local);
|
|
|
|
ctx.builder.free_local(address_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
|
|
|
}
|
|
|
|
pub fn instr_88_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_set_reg8_r(ctx, r1, r2);
|
|
|
|
}
|
|
|
|
|
2018-07-03 17:28:33 +02:00
|
|
|
pub fn instr16_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-08-16 21:37:10 +02:00
|
|
|
|
|
|
|
let address_local = ctx.builder.set_new_local();
|
|
|
|
|
2018-08-22 04:06:52 +02:00
|
|
|
codegen::gen_get_reg16(ctx.builder, r);
|
2018-08-16 21:37:10 +02:00
|
|
|
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);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
pub fn instr16_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_set_reg16_r(ctx, r1, r2);
|
|
|
|
}
|
|
|
|
pub fn instr32_89_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
// Pseudo: safe_write32(modrm_resolve(modrm_byte), reg32s[r]);
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-07-30 09:05:33 +02:00
|
|
|
let address_local = ctx.builder.set_new_local();
|
2018-07-03 17:28:33 +02:00
|
|
|
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg32_offset(r) as i32);
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.load_aligned_i32_from_stack(0);
|
2018-07-30 09:05:33 +02:00
|
|
|
let value_local = ctx.builder.set_new_local();
|
2018-07-03 17:28:33 +02:00
|
|
|
|
2018-07-24 13:08:01 +02:00
|
|
|
codegen::gen_safe_write32(ctx, &address_local, &value_local);
|
|
|
|
ctx.builder.free_local(address_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
pub fn instr32_89_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_set_reg32_r(ctx, r1, r2);
|
|
|
|
}
|
|
|
|
|
2018-08-22 02:36:44 +02:00
|
|
|
pub fn instr_8A_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
// Pseudo: reg8[r] = safe_read8(modrm_resolve(modrm_byte));
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg8_offset(r) as i32);
|
2018-08-22 02:36:44 +02:00
|
|
|
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read8(ctx);
|
|
|
|
|
|
|
|
ctx.builder.instruction_body.store_u8(0);
|
|
|
|
}
|
|
|
|
pub fn instr_8A_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_set_reg8_r(ctx, r2, r1);
|
|
|
|
}
|
|
|
|
|
2018-07-03 17:28:33 +02:00
|
|
|
pub fn instr16_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
2018-08-16 21:37:10 +02:00
|
|
|
// Pseudo: reg16[r] = safe_read16(modrm_resolve(modrm_byte));
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg16_offset(r) as i32);
|
2018-07-03 17:28:33 +02:00
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-08-16 21:37:10 +02:00
|
|
|
codegen::gen_safe_read16(ctx);
|
|
|
|
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_u16(0);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
pub fn instr16_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_set_reg16_r(ctx, r2, r1);
|
|
|
|
}
|
|
|
|
pub fn instr32_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
// Pseudo: reg32s[r] = safe_read32s(modrm_resolve(modrm_byte));
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg32_offset(r) as i32);
|
2018-07-03 17:28:33 +02:00
|
|
|
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read32(ctx);
|
|
|
|
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
pub fn instr32_8B_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_set_reg32_r(ctx, r2, r1);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) {
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.const_i32(global_pointers::get_reg16_offset(reg) as i32);
|
2018-07-03 17:28:33 +02:00
|
|
|
ctx.cpu.prefixes |= SEG_PREFIX_ZERO;
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_u16(0);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
pub fn instr32_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) {
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.const_i32(global_pointers::get_reg32_offset(reg) as i32);
|
2018-07-03 17:28:33 +02:00
|
|
|
ctx.cpu.prefixes |= SEG_PREFIX_ZERO;
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_fn2_const(ctx, "instr16_8D_reg", r1, r2);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr32_8D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
codegen::gen_fn2_const(ctx, "instr32_8D_reg", r1, r2);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
2018-08-16 21:37:10 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg16_offset(regs::SP) as i32);
|
|
|
|
codegen::gen_get_reg16(ctx.builder, regs::SP);
|
|
|
|
ctx.builder.instruction_body.const_i32(2);
|
2018-08-16 21:37:10 +02:00
|
|
|
ctx.builder.instruction_body.add_i32();
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_u16(0);
|
2018-08-16 21:37:10 +02:00
|
|
|
|
2018-07-03 17:28:33 +02:00
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-08-16 21:37:10 +02:00
|
|
|
codegen::gen_modrm_fn0(ctx, "instr16_8F_0_mem_jit");
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
pub fn instr16_8F_0_reg_jit(ctx: &mut JitContext, r: u32) {
|
|
|
|
codegen::gen_fn1_const(ctx, "instr16_8F_0_reg", r);
|
|
|
|
}
|
|
|
|
pub fn instr32_8F_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
2018-08-16 21:37:10 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg32_offset(regs::ESP) as i32);
|
|
|
|
codegen::gen_get_reg32(ctx.builder, regs::ESP);
|
|
|
|
ctx.builder.instruction_body.const_i32(4);
|
2018-08-16 21:37:10 +02:00
|
|
|
ctx.builder.instruction_body.add_i32();
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-08-16 21:37:10 +02:00
|
|
|
|
2018-07-03 17:28:33 +02:00
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-08-16 21:37:10 +02:00
|
|
|
codegen::gen_modrm_fn0(ctx, "instr32_8F_0_mem_jit");
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
pub fn instr32_8F_0_reg_jit(ctx: &mut JitContext, r: u32) {
|
|
|
|
codegen::gen_fn1_const(ctx, "instr32_8F_0_reg", r);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_E8_jit(ctx: &mut JitContext, imm: u32) {
|
2018-08-18 09:33:14 +02:00
|
|
|
codegen::gen_get_real_eip(ctx);
|
2018-08-20 19:18:17 +02:00
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
codegen::gen_push16(ctx, &value_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
2018-08-18 09:33:14 +02:00
|
|
|
codegen::gen_jmp_rel16(ctx, imm as u16);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
pub fn instr32_E8_jit(ctx: &mut JitContext, imm: u32) {
|
2018-08-18 09:33:14 +02:00
|
|
|
codegen::gen_get_real_eip(ctx);
|
2018-08-20 19:18:17 +02:00
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
codegen::gen_push32(ctx, &value_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
2018-08-18 09:33:14 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::INSTRUCTION_POINTER as i32);
|
2018-08-18 09:33:14 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.load_aligned_i32(global_pointers::INSTRUCTION_POINTER);
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.const_i32(imm as i32);
|
2018-08-18 09:33:14 +02:00
|
|
|
ctx.builder.instruction_body.add_i32();
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
2018-07-22 07:31:10 +02:00
|
|
|
|
|
|
|
pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_jmp_rel16(ctx, imm as u16); }
|
2018-07-03 17:28:33 +02:00
|
|
|
pub fn instr32_E9_jit(ctx: &mut JitContext, imm: u32) {
|
2018-07-22 07:31:10 +02:00
|
|
|
codegen::gen_relative_jump(ctx.builder, imm as i32);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
2018-07-22 07:26:54 +02:00
|
|
|
|
2018-07-22 11:32:29 +02:00
|
|
|
pub fn instr16_C3_jit(ctx: &mut JitContext) {
|
|
|
|
let cs_addr = global_pointers::get_seg_offset(CS);
|
|
|
|
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::INSTRUCTION_POINTER as i32);
|
2018-07-22 11:32:29 +02:00
|
|
|
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.load_aligned_i32(cs_addr);
|
2018-07-22 11:32:29 +02:00
|
|
|
codegen::gen_pop16(ctx);
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.add_i32();
|
2018-07-22 11:32:29 +02:00
|
|
|
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-07-22 11:32:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr32_C3_jit(ctx: &mut JitContext) {
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::INSTRUCTION_POINTER as i32);
|
2018-07-22 11:32:29 +02:00
|
|
|
|
|
|
|
// cs = segment_offsets[CS]
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.load_aligned_i32(global_pointers::get_seg_offset(CS));
|
2018-07-22 11:32:29 +02:00
|
|
|
|
|
|
|
// ip = pop32s()
|
|
|
|
codegen::gen_pop32s(ctx);
|
|
|
|
|
|
|
|
// cs + ip
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.add_i32();
|
2018-07-22 11:32:29 +02:00
|
|
|
|
|
|
|
// dbg_assert(is_asize_32() || ip < 0x10000);
|
|
|
|
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-07-22 11:32:29 +02:00
|
|
|
}
|
|
|
|
|
2018-07-22 07:26:54 +02:00
|
|
|
pub fn instr16_EB_jit(ctx: &mut JitContext, imm8: u32) {
|
|
|
|
codegen::gen_jmp_rel16(ctx, imm8 as u16);
|
|
|
|
// dbg_assert(is_asize_32() || get_real_eip() < 0x10000);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
2018-07-22 07:26:54 +02:00
|
|
|
|
|
|
|
pub fn instr32_EB_jit(ctx: &mut JitContext, imm8: u32) {
|
|
|
|
// jmp near
|
|
|
|
codegen::gen_relative_jump(ctx.builder, imm8 as i32);
|
|
|
|
// dbg_assert(is_asize_32() || get_real_eip() < 0x10000);
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_FF_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
|
|
|
push16_mem_jit(ctx, modrm_byte)
|
|
|
|
}
|
|
|
|
pub fn instr16_FF_6_reg_jit(ctx: &mut JitContext, r: u32) { push16_reg_jit(ctx, r) }
|
|
|
|
pub fn instr32_FF_6_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
|
|
|
push32_mem_jit(ctx, modrm_byte)
|
|
|
|
}
|
|
|
|
pub fn instr32_FF_6_reg_jit(ctx: &mut JitContext, r: u32) { push32_reg_jit(ctx, r) }
|
|
|
|
|
|
|
|
// Code for conditional jumps is generated automatically by the basic block codegen
|
|
|
|
pub fn instr16_0F80_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F81_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F82_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F83_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F84_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F85_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F86_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F87_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F88_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F89_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F8A_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F8B_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F8C_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F8D_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F8E_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr16_0F8F_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F80_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F81_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F82_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F83_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F84_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F85_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F86_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F87_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F88_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F89_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F8A_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F8B_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F8C_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F8D_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F8E_jit(_ctx: &mut JitContext, _imm: u32) {}
|
|
|
|
pub fn instr32_0F8F_jit(_ctx: &mut JitContext, _imm: u32) {}
|
2018-07-16 07:37:51 +02:00
|
|
|
|
|
|
|
pub fn instr_90_jit(_ctx: &mut JitContext) {}
|
2018-07-24 01:58:03 +02:00
|
|
|
|
|
|
|
pub fn instr_0F19_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) {
|
|
|
|
modrm::skip(ctx.cpu, modrm_byte);
|
|
|
|
}
|
|
|
|
pub fn instr_0F19_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {}
|
2018-07-25 23:23:03 +02:00
|
|
|
|
2018-07-24 01:58:03 +02:00
|
|
|
pub fn instr_0F1C_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) {
|
|
|
|
modrm::skip(ctx.cpu, modrm_byte);
|
|
|
|
}
|
|
|
|
pub fn instr_0F1C_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {}
|
|
|
|
pub fn instr_0F1D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) {
|
|
|
|
modrm::skip(ctx.cpu, modrm_byte);
|
|
|
|
}
|
|
|
|
pub fn instr_0F1D_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {}
|
|
|
|
pub fn instr_0F1E_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) {
|
|
|
|
modrm::skip(ctx.cpu, modrm_byte);
|
|
|
|
}
|
|
|
|
pub fn instr_0F1E_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {}
|
2018-07-16 07:37:51 +02:00
|
|
|
pub fn instr_0F1F_mem_jit(ctx: &mut JitContext, modrm_byte: u8, _reg: u32) {
|
2018-07-24 01:58:03 +02:00
|
|
|
modrm::skip(ctx.cpu, modrm_byte);
|
2018-07-16 07:37:51 +02:00
|
|
|
}
|
|
|
|
pub fn instr_0F1F_reg_jit(_ctx: &mut JitContext, _r1: u32, _r2: u32) {}
|
2018-07-17 17:07:40 +02:00
|
|
|
|
2018-08-22 02:36:44 +02:00
|
|
|
pub fn instr16_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
let builder = &mut ctx.builder;
|
|
|
|
builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg16_offset(r2) as i32);
|
|
|
|
codegen::gen_get_reg8(builder, r1);
|
|
|
|
builder.instruction_body.store_aligned_u16(0);
|
2018-08-22 02:36:44 +02:00
|
|
|
}
|
|
|
|
pub fn instr16_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg16_offset(r) as i32);
|
2018-08-22 02:36:44 +02:00
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read8(ctx);
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_u16(0);
|
2018-08-22 02:36:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr32_0FB6_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
let builder = &mut ctx.builder;
|
|
|
|
builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg32_offset(r2) as i32);
|
|
|
|
codegen::gen_get_reg8(builder, r1);
|
|
|
|
builder.instruction_body.store_aligned_i32(0);
|
2018-08-22 02:36:44 +02:00
|
|
|
}
|
|
|
|
pub fn instr32_0FB6_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg32_offset(r) as i32);
|
2018-08-22 02:36:44 +02:00
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read8(ctx);
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-08-22 02:36:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
let builder = &mut ctx.builder;
|
|
|
|
builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg16_offset(r2) as i32);
|
|
|
|
codegen::gen_get_reg8(builder, r1);
|
2018-08-22 02:36:44 +02:00
|
|
|
codegen::sign_extend_i8(builder);
|
2018-08-22 04:06:52 +02:00
|
|
|
builder.instruction_body.store_aligned_u16(0);
|
2018-08-22 02:36:44 +02:00
|
|
|
}
|
|
|
|
pub fn instr16_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg16_offset(r) as i32);
|
2018-08-22 02:36:44 +02:00
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read8(ctx);
|
|
|
|
codegen::sign_extend_i8(ctx.builder);
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_u16(0);
|
2018-08-22 02:36:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr32_0FBE_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|
|
|
let builder = &mut ctx.builder;
|
|
|
|
builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg32_offset(r2) as i32);
|
|
|
|
codegen::gen_get_reg8(builder, r1);
|
2018-08-22 02:36:44 +02:00
|
|
|
codegen::sign_extend_i8(builder);
|
2018-08-22 04:06:52 +02:00
|
|
|
builder.instruction_body.store_aligned_i32(0);
|
2018-08-22 02:36:44 +02:00
|
|
|
}
|
|
|
|
pub fn instr32_0FBE_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg32_offset(r) as i32);
|
2018-08-22 02:36:44 +02:00
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
codegen::gen_safe_read8(ctx);
|
|
|
|
codegen::sign_extend_i8(ctx.builder);
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-08-22 02:36:44 +02:00
|
|
|
}
|
|
|
|
|
2018-08-22 04:38:11 +02:00
|
|
|
pub fn instr_C6_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) {
|
|
|
|
// reg8[r] = imm;
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.const_i32(global_pointers::get_reg8_offset(r) as i32);
|
|
|
|
ctx.builder.instruction_body.const_i32(imm as i32);
|
|
|
|
ctx.builder.instruction_body.store_u8(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr_C6_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
|
|
|
let address_local = ctx.builder.set_new_local();
|
|
|
|
let imm = ctx.cpu.read_imm8();
|
|
|
|
ctx.builder.instruction_body.const_i32(imm as i32);
|
|
|
|
let value_local = ctx.builder.set_new_local();
|
|
|
|
codegen::gen_safe_write8(ctx, &address_local, &value_local);
|
|
|
|
ctx.builder.free_local(address_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
|
|
|
}
|
|
|
|
|
2018-07-17 17:07:40 +02:00
|
|
|
pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) {
|
|
|
|
// reg16[r] = imm;
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg16_offset(r) as i32);
|
|
|
|
ctx.builder.instruction_body.const_i32(imm as i32);
|
|
|
|
ctx.builder.instruction_body.store_aligned_u16(0);
|
2018-07-17 17:07:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-07-30 09:05:33 +02:00
|
|
|
let address_local = ctx.builder.set_new_local();
|
2018-07-24 13:33:21 +02:00
|
|
|
let imm = ctx.cpu.read_imm16();
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.const_i32(imm as i32);
|
2018-07-30 09:05:33 +02:00
|
|
|
let value_local = ctx.builder.set_new_local();
|
2018-07-24 13:33:21 +02:00
|
|
|
codegen::gen_safe_write16(ctx, &address_local, &value_local);
|
|
|
|
ctx.builder.free_local(address_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
2018-07-17 17:07:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) {
|
|
|
|
// reg32s[r] = imm;
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
2018-08-22 04:06:52 +02:00
|
|
|
.const_i32(global_pointers::get_reg32_offset(r) as i32);
|
|
|
|
ctx.builder.instruction_body.const_i32(imm as i32);
|
|
|
|
ctx.builder.instruction_body.store_aligned_i32(0);
|
2018-07-17 17:07:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-07-30 09:05:33 +02:00
|
|
|
let address_local = ctx.builder.set_new_local();
|
2018-07-17 17:07:40 +02:00
|
|
|
let imm = ctx.cpu.read_imm32();
|
2018-08-22 04:06:52 +02:00
|
|
|
ctx.builder.instruction_body.const_i32(imm as i32);
|
2018-07-30 09:05:33 +02:00
|
|
|
let value_local = ctx.builder.set_new_local();
|
2018-07-24 13:08:01 +02:00
|
|
|
codegen::gen_safe_write32(ctx, &address_local, &value_local);
|
|
|
|
ctx.builder.free_local(address_local);
|
|
|
|
ctx.builder.free_local(value_local);
|
2018-07-17 17:07:40 +02:00
|
|
|
}
|