v86/src/rust/jit_instructions.rs

846 lines
34 KiB
Rust
Raw Normal View History

#![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;
use prefix::SEG_PREFIX_ZERO;
use prefix::{PREFIX_66, PREFIX_67, PREFIX_F2, PREFIX_F3};
use regs;
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;
use wasmgen::wasm_util::WasmBuf;
pub fn jit_instruction(cpu: &mut CpuContext, builder: &mut WasmBuilder, instr_flags: &mut u32) {
cpu.prefixes = 0;
let start_of_current_instruction = cpu.eip;
let ctx = &mut JitContext {
cpu,
builder,
start_of_current_instruction,
};
::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);
ctx.cpu.prefixes |= segment + 1;
// TODO: Could merge multiple prefix updates into one
codegen::gen_add_prefix_bits(ctx, segment + 1);
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;
// TODO: Could merge multiple prefix updates into one
codegen::gen_add_prefix_bits(ctx, PREFIX_66);
jit_handle_prefix(ctx, instr_flags)
}
pub fn instr_67_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
ctx.cpu.prefixes |= PREFIX_67;
// TODO: Could merge multiple prefix updates into one
codegen::gen_add_prefix_bits(ctx, PREFIX_67);
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;
// string/sse prefix: Don't generate code to update prefixes at runtime. This means runtime
// instructions can't inspect the prefixes for this flags
jit_handle_prefix(ctx, instr_flags)
}
pub fn instr_F3_jit(ctx: &mut JitContext, instr_flags: &mut u32) {
ctx.cpu.prefixes |= PREFIX_F3;
// string/sse prefix: Don't generate code to update prefixes at runtime. This means runtime
// instructions can't inspect the prefixes for this flags
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);
}
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);
}
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);
}
fn pop16_reg_jit(ctx: &mut JitContext, reg: u32) {
ctx.builder
.instruction_body
2018-08-22 04:06:52 +02:00
.const_i32(global_pointers::get_reg16_offset(reg) as i32);
codegen::gen_pop16(ctx);
2018-08-22 04:06:52 +02:00
ctx.builder.instruction_body.store_aligned_u16(0);
}
fn pop32_reg_jit(ctx: &mut JitContext, reg: u32) {
ctx.builder
.instruction_body
2018-08-22 04:06:52 +02:00
.const_i32(global_pointers::get_reg32_offset(reg) as i32);
codegen::gen_pop32s(ctx);
2018-08-22 04:06:52 +02:00
ctx.builder.instruction_body.store_aligned_i32(0);
}
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")
}
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) {}
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 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);
}
pub fn instr16_89_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();
2018-08-22 04:06:52 +02:00
codegen::gen_get_reg16(ctx.builder, r);
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 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();
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.load_aligned_i32_from_stack(0);
2018-07-30 09:05:33 +02:00
let value_local = ctx.builder.set_new_local();
codegen::gen_safe_write32(ctx, &address_local, &value_local);
ctx.builder.free_local(address_local);
ctx.builder.free_local(value_local);
}
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);
}
pub fn instr16_8B_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
// 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);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read16(ctx);
2018-08-22 04:06:52 +02:00
ctx.builder.instruction_body.store_aligned_u16(0);
}
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));
ctx.builder
.instruction_body
2018-08-22 04:06:52 +02:00
.const_i32(global_pointers::get_reg32_offset(r) as i32);
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);
}
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);
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);
}
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);
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);
}
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) {
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);
ctx.builder.instruction_body.add_i32();
2018-08-22 04:06:52 +02:00
ctx.builder.instruction_body.store_aligned_u16(0);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_modrm_fn0(ctx, "instr16_8F_0_mem_jit");
}
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) {
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);
ctx.builder.instruction_body.add_i32();
2018-08-22 04:06:52 +02:00
ctx.builder.instruction_body.store_aligned_i32(0);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_modrm_fn0(ctx, "instr32_8F_0_mem_jit");
}
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);
}
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-22 07:31:10 +02:00
pub fn instr16_E9_jit(ctx: &mut JitContext, imm: u32) { codegen::gen_jmp_rel16(ctx, imm as u16); }
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-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);
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
ctx.builder.instruction_body.load_aligned_i32(cs_addr);
2018-07-22 11:32:29 +02:00
codegen::gen_pop16(ctx);
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) {
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]
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
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-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);
}
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-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-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
}
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);
}
pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) {
// reg16[r] = imm;
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);
}
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();
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();
codegen::gen_safe_write16(ctx, &address_local, &value_local);
ctx.builder.free_local(address_local);
ctx.builder.free_local(value_local);
}
pub fn instr32_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) {
// reg32s[r] = imm;
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);
}
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();
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();
codegen::gen_safe_write32(ctx, &address_local, &value_local);
ctx.builder.free_local(address_local);
ctx.builder.free_local(value_local);
}