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;
|
|
|
|
let ctx = &mut JitContext { cpu, builder };
|
|
|
|
::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) {
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.load_aligned_u16(global_pointers::get_reg16_offset(r));
|
|
|
|
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) {
|
|
|
|
ctx.builder.instruction_body.push_i32(imm as i32);
|
|
|
|
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) {
|
|
|
|
ctx.builder.instruction_body.push_i32(imm as i32);
|
|
|
|
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
|
|
|
|
.push_i32(global_pointers::get_reg16_offset(reg) as i32);
|
|
|
|
codegen::gen_pop16(ctx);
|
|
|
|
ctx.builder.instruction_body.store_aligned_u16();
|
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
|
|
|
|
.push_i32(global_pointers::get_reg32_offset(reg) as i32);
|
|
|
|
codegen::gen_pop32s(ctx);
|
|
|
|
ctx.builder.instruction_body.store_aligned_i32();
|
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) {}
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.push_i32(global_pointers::get_reg16_offset(r) 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);
|
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
|
|
|
|
.push_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();
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
.push_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);
|
|
|
|
|
|
|
|
ctx.builder.instruction_body.store_aligned_u16();
|
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
|
|
|
|
.push_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-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32();
|
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) {
|
|
|
|
let loc = global_pointers::get_reg16_offset(reg);
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.push_i32(loc as i32);
|
2018-07-03 17:28:33 +02:00
|
|
|
ctx.cpu.prefixes |= SEG_PREFIX_ZERO;
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_u16();
|
2018-07-03 17:28:33 +02:00
|
|
|
}
|
|
|
|
pub fn instr32_8D_mem_jit(ctx: &mut JitContext, modrm_byte: u8, reg: u32) {
|
|
|
|
let loc = global_pointers::get_reg32_offset(reg);
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.push_i32(loc as i32);
|
2018-07-03 17:28:33 +02:00
|
|
|
ctx.cpu.prefixes |= SEG_PREFIX_ZERO;
|
|
|
|
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
2018-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32();
|
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
|
|
|
|
.push_i32(global_pointers::get_reg16_offset(regs::SP) as i32);
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.load_aligned_u16(global_pointers::get_reg16_offset(regs::SP));
|
|
|
|
ctx.builder.instruction_body.push_i32(2);
|
|
|
|
ctx.builder.instruction_body.add_i32();
|
|
|
|
ctx.builder.instruction_body.store_aligned_u16();
|
|
|
|
|
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
|
|
|
|
.push_i32(global_pointers::get_reg32_offset(regs::ESP) as i32);
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.load_aligned_i32(global_pointers::get_reg32_offset(regs::ESP));
|
|
|
|
ctx.builder.instruction_body.push_i32(4);
|
|
|
|
ctx.builder.instruction_body.add_i32();
|
|
|
|
ctx.builder.instruction_body.store_aligned_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_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
|
|
|
|
.push_i32(global_pointers::INSTRUCTION_POINTER as i32);
|
|
|
|
ctx.builder
|
|
|
|
.instruction_body
|
|
|
|
.load_aligned_i32(global_pointers::INSTRUCTION_POINTER);
|
|
|
|
ctx.builder.instruction_body.push_i32(imm as i32);
|
|
|
|
ctx.builder.instruction_body.add_i32();
|
|
|
|
ctx.builder.instruction_body.store_aligned_i32();
|
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
|
|
|
|
.push_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-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32();
|
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
|
|
|
|
.push_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-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.store_aligned_i32();
|
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
|
|
|
|
|
|
|
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
|
|
|
|
.push_i32(global_pointers::get_reg16_offset(r) as i32);
|
|
|
|
ctx.builder.instruction_body.push_i32(imm as i32);
|
|
|
|
ctx.builder.instruction_body.store_aligned_u16();
|
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-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.push_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
|
|
|
|
.push_i32(global_pointers::get_reg32_offset(r) as i32);
|
|
|
|
ctx.builder.instruction_body.push_i32(imm as i32);
|
|
|
|
ctx.builder.instruction_body.store_aligned_i32();
|
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-07-28 20:33:40 +02:00
|
|
|
ctx.builder.instruction_body.push_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
|
|
|
}
|