Generate code for memory instructions (0F4*, 0F9*, 0FAF: cmovcc, setcc, imul)

This commit is contained in:
Fabian 2018-08-26 20:22:17 -05:00
parent de01a4b265
commit 5dd26ead30
2 changed files with 152 additions and 33 deletions

View file

@ -380,22 +380,22 @@ const encodings = [
{ opcode: 0x0F3E, skip: 1 },
{ opcode: 0x0F3F, skip: 1 },
{ opcode: 0x0F40, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F41, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F42, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F43, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F44, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F45, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F46, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F47, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F48, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F49, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F4A, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F4B, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F4C, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F4D, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F4E, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F4F, nonfaulting: 1, e: 1, os: 1, },
{ opcode: 0x0F40, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F41, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F42, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F43, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F44, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F45, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F46, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F47, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F48, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F49, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F4A, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F4B, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F4C, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F4D, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F4E, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F4F, nonfaulting: 1, e: 1, os: 1, custom: 1, },
{ opcode: 0x0F80, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F81, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
@ -414,22 +414,22 @@ const encodings = [
{ opcode: 0x0F8E, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F8F, block_boundary: 1, jump_offset_imm: 1, conditional_jump: 1, imm1632: 1, os: 1, custom: 1, skip: 1, },
{ opcode: 0x0F90, nonfaulting: 1, e: 1, },
{ opcode: 0x0F91, nonfaulting: 1, e: 1, },
{ opcode: 0x0F92, nonfaulting: 1, e: 1, },
{ opcode: 0x0F93, nonfaulting: 1, e: 1, },
{ opcode: 0x0F94, nonfaulting: 1, e: 1, },
{ opcode: 0x0F95, nonfaulting: 1, e: 1, },
{ opcode: 0x0F96, nonfaulting: 1, e: 1, },
{ opcode: 0x0F97, nonfaulting: 1, e: 1, },
{ opcode: 0x0F98, nonfaulting: 1, e: 1, },
{ opcode: 0x0F99, nonfaulting: 1, e: 1, },
{ opcode: 0x0F9A, nonfaulting: 1, e: 1, },
{ opcode: 0x0F9B, nonfaulting: 1, e: 1, },
{ opcode: 0x0F9C, nonfaulting: 1, e: 1, },
{ opcode: 0x0F9D, nonfaulting: 1, e: 1, },
{ opcode: 0x0F9E, nonfaulting: 1, e: 1, },
{ opcode: 0x0F9F, nonfaulting: 1, e: 1, },
{ opcode: 0x0F90, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F91, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F92, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F93, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F94, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F95, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F96, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F97, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F98, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F99, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F9A, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F9B, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F9C, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F9D, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F9E, nonfaulting: 1, e: 1, custom: 1, },
{ opcode: 0x0F9F, nonfaulting: 1, e: 1, custom: 1, },
// XXX: Temporary block boundary
{ opcode: 0x0FA0, os: 1, skip: 1, block_boundary: 1, },
@ -475,7 +475,7 @@ const encodings = [
{ opcode: 0x0FAE, e: 1, fixed_g: 6, skip: 1, block_boundary: 1, }, // mfence (reg, only 0), xsaveopt (mem, not implemented)
{ opcode: 0x0FAE, e: 1, fixed_g: 7, skip: 1, block_boundary: 1, }, // sfence (reg, only 0), clflush (mem)
{ opcode: 0x0FAF, nonfaulting: 1, os: 1, e: 1, mask_flags: af | zf }, // imul
{ opcode: 0x0FAF, nonfaulting: 1, os: 1, e: 1, mask_flags: af | zf, custom: 1, }, // imul
{ opcode: 0x0FB0, nonfaulting: 1, e: 1 }, // cmxchg
{ opcode: 0x0FB1, nonfaulting: 1, os: 1, e: 1 },

View file

@ -1889,3 +1889,122 @@ pub fn instr32_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
ctx.builder.free_local(address_local);
ctx.builder.free_local(value_local);
}
define_instruction_write_reg16!("imul_reg16", instr16_0FAF_mem_jit, instr16_0FAF_reg_jit);
define_instruction_write_reg32!("imul_reg32", instr32_0FAF_mem_jit, instr32_0FAF_reg_jit);
macro_rules! define_cmovcc16(
($cond:expr, $name_mem:ident, $name_reg:ident) => (
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
codegen::gen_fn0_const_ret(ctx.builder, $cond);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read16(ctx);
ctx.builder.instruction_body.const_i32(r as i32);
codegen::gen_call_fn3(ctx, "cmovcc16")
}
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
codegen::gen_fn0_const_ret(ctx.builder, $cond);
codegen::gen_get_reg16(ctx.builder, r1);
ctx.builder.instruction_body.const_i32(r2 as i32);
codegen::gen_call_fn3(ctx, "cmovcc16")
}
);
);
macro_rules! define_cmovcc32(
($cond:expr, $name_mem:ident, $name_reg:ident) => (
pub fn $name_mem(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
codegen::gen_fn0_const_ret(ctx.builder, $cond);
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_safe_read32(ctx);
ctx.builder.instruction_body.const_i32(r as i32);
codegen::gen_call_fn3(ctx, "cmovcc32")
}
pub fn $name_reg(ctx: &mut JitContext, r1: u32, r2: u32) {
codegen::gen_fn0_const_ret(ctx.builder, $cond);
codegen::gen_get_reg32(ctx.builder, r1);
ctx.builder.instruction_body.const_i32(r2 as i32);
codegen::gen_call_fn3(ctx, "cmovcc32")
}
);
);
define_cmovcc16!("test_o", instr16_0F40_mem_jit, instr16_0F40_reg_jit);
define_cmovcc16!("test_no", instr16_0F41_mem_jit, instr16_0F41_reg_jit);
define_cmovcc16!("test_b", instr16_0F42_mem_jit, instr16_0F42_reg_jit);
define_cmovcc16!("test_nb", instr16_0F43_mem_jit, instr16_0F43_reg_jit);
define_cmovcc16!("test_z", instr16_0F44_mem_jit, instr16_0F44_reg_jit);
define_cmovcc16!("test_nz", instr16_0F45_mem_jit, instr16_0F45_reg_jit);
define_cmovcc16!("test_be", instr16_0F46_mem_jit, instr16_0F46_reg_jit);
define_cmovcc16!("test_nbe", instr16_0F47_mem_jit, instr16_0F47_reg_jit);
define_cmovcc16!("test_s", instr16_0F48_mem_jit, instr16_0F48_reg_jit);
define_cmovcc16!("test_ns", instr16_0F49_mem_jit, instr16_0F49_reg_jit);
define_cmovcc16!("test_p", instr16_0F4A_mem_jit, instr16_0F4A_reg_jit);
define_cmovcc16!("test_np", instr16_0F4B_mem_jit, instr16_0F4B_reg_jit);
define_cmovcc16!("test_l", instr16_0F4C_mem_jit, instr16_0F4C_reg_jit);
define_cmovcc16!("test_nl", instr16_0F4D_mem_jit, instr16_0F4D_reg_jit);
define_cmovcc16!("test_le", instr16_0F4E_mem_jit, instr16_0F4E_reg_jit);
define_cmovcc16!("test_nle", instr16_0F4F_mem_jit, instr16_0F4F_reg_jit);
define_cmovcc32!("test_o", instr32_0F40_mem_jit, instr32_0F40_reg_jit);
define_cmovcc32!("test_no", instr32_0F41_mem_jit, instr32_0F41_reg_jit);
define_cmovcc32!("test_b", instr32_0F42_mem_jit, instr32_0F42_reg_jit);
define_cmovcc32!("test_nb", instr32_0F43_mem_jit, instr32_0F43_reg_jit);
define_cmovcc32!("test_z", instr32_0F44_mem_jit, instr32_0F44_reg_jit);
define_cmovcc32!("test_nz", instr32_0F45_mem_jit, instr32_0F45_reg_jit);
define_cmovcc32!("test_be", instr32_0F46_mem_jit, instr32_0F46_reg_jit);
define_cmovcc32!("test_nbe", instr32_0F47_mem_jit, instr32_0F47_reg_jit);
define_cmovcc32!("test_s", instr32_0F48_mem_jit, instr32_0F48_reg_jit);
define_cmovcc32!("test_ns", instr32_0F49_mem_jit, instr32_0F49_reg_jit);
define_cmovcc32!("test_p", instr32_0F4A_mem_jit, instr32_0F4A_reg_jit);
define_cmovcc32!("test_np", instr32_0F4B_mem_jit, instr32_0F4B_reg_jit);
define_cmovcc32!("test_l", instr32_0F4C_mem_jit, instr32_0F4C_reg_jit);
define_cmovcc32!("test_nl", instr32_0F4D_mem_jit, instr32_0F4D_reg_jit);
define_cmovcc32!("test_le", instr32_0F4E_mem_jit, instr32_0F4E_reg_jit);
define_cmovcc32!("test_nle", instr32_0F4F_mem_jit, instr32_0F4F_reg_jit);
macro_rules! define_setcc(
($cond: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);
let address_local = ctx.builder.set_new_local();
codegen::gen_fn0_const_ret(ctx.builder, $cond);
ctx.builder.instruction_body.const_i32(0);
ctx.builder.instruction_body.ne_i32();
let value_local = ctx.builder.set_new_local();
codegen::gen_safe_write8(ctx, &address_local, &value_local);
}
pub fn $name_reg(ctx: &mut JitContext, r1: u32, _r2: u32) {
ctx.builder
.instruction_body
.const_i32(global_pointers::get_reg8_offset(r1) as i32);
codegen::gen_fn0_const_ret(ctx.builder, $cond);
ctx.builder.instruction_body.const_i32(0);
ctx.builder.instruction_body.ne_i32();
ctx.builder.instruction_body.store_u8(0);
}
);
);
define_setcc!("test_o", instr_0F90_mem_jit, instr_0F90_reg_jit);
define_setcc!("test_no", instr_0F91_mem_jit, instr_0F91_reg_jit);
define_setcc!("test_b", instr_0F92_mem_jit, instr_0F92_reg_jit);
define_setcc!("test_nb", instr_0F93_mem_jit, instr_0F93_reg_jit);
define_setcc!("test_z", instr_0F94_mem_jit, instr_0F94_reg_jit);
define_setcc!("test_nz", instr_0F95_mem_jit, instr_0F95_reg_jit);
define_setcc!("test_be", instr_0F96_mem_jit, instr_0F96_reg_jit);
define_setcc!("test_nbe", instr_0F97_mem_jit, instr_0F97_reg_jit);
define_setcc!("test_s", instr_0F98_mem_jit, instr_0F98_reg_jit);
define_setcc!("test_ns", instr_0F99_mem_jit, instr_0F99_reg_jit);
define_setcc!("test_p", instr_0F9A_mem_jit, instr_0F9A_reg_jit);
define_setcc!("test_np", instr_0F9B_mem_jit, instr_0F9B_reg_jit);
define_setcc!("test_l", instr_0F9C_mem_jit, instr_0F9C_reg_jit);
define_setcc!("test_nl", instr_0F9D_mem_jit, instr_0F9D_reg_jit);
define_setcc!("test_le", instr_0F9E_mem_jit, instr_0F9E_reg_jit);
define_setcc!("test_nle", instr_0F9F_mem_jit, instr_0F9F_reg_jit);