jit cmpxchg8b

This commit is contained in:
Fabian 2020-12-31 19:14:32 -06:00
parent fc38676089
commit 6a18618e76
5 changed files with 97 additions and 10 deletions

View file

@ -576,7 +576,7 @@ const encodings = [
{ opcode: 0x0FB0, e: 1 }, // cmxchg
{ opcode: 0x0FB1, os: 1, e: 1, custom: 1 },
{ opcode: 0x0FC7, e: 1, fixed_g: 1, os: 1, reg_ud: 1, }, // cmpxchg8b (memory)
{ opcode: 0x0FC7, e: 1, fixed_g: 1, os: 1, reg_ud: 1, custom: 1 }, // cmpxchg8b (memory)
{ opcode: 0x0FC7, e: 1, fixed_g: 6, os: 1, mem_ud: 1, skip: 1, }, // rdrand
{ opcode: 0x0FB2, block_boundary: 1, os: 1, e: 1, skip: 1, }, // lss

View file

@ -408,6 +408,11 @@ enum GenSafeWriteValue<'a> {
TwoI64s(&'a WasmLocalI64, &'a WasmLocalI64),
}
enum GenSafeReadWriteValue {
I32(WasmLocal),
I64(WasmLocalI64),
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum BitSize {
BYTE,
@ -840,7 +845,9 @@ pub fn gen_safe_read_write(
BitSize::DWORD => {
ctx.builder.call_fn2_ret("safe_read_write32s_slow_jit");
},
BitSize::QWORD => dbg_assert!(false),
BitSize::QWORD => {
ctx.builder.call_fn2_ret("safe_read_write64_slow_jit");
},
BitSize::DQWORD => dbg_assert!(false),
}
ctx.builder.tee_local(&entry_local);
@ -886,14 +893,23 @@ pub fn gen_safe_read_write(
BitSize::DWORD => {
ctx.builder.load_unaligned_i32(0);
},
BitSize::QWORD => assert!(false), // not used
BitSize::QWORD => {
ctx.builder.load_unaligned_i64(0);
},
BitSize::DQWORD => assert!(false), // not used
}
// value is now on stack
f(ctx);
let value_local = ctx.builder.set_new_local(); // TODO: Could get rid of this local by returning one from f
// TODO: Could get rid of this local by returning one from f
let value_local = if bits == BitSize::QWORD {
GenSafeReadWriteValue::I64(ctx.builder.set_new_local_i64())
}
else {
GenSafeReadWriteValue::I32(ctx.builder.set_new_local())
};
ctx.builder.get_local(&can_use_fast_path_local);
@ -901,7 +917,11 @@ pub fn gen_safe_read_write(
ctx.builder.if_void();
{
ctx.builder.get_local(&address_local);
ctx.builder.get_local(&value_local);
match &value_local {
GenSafeReadWriteValue::I32(l) => ctx.builder.get_local(l),
GenSafeReadWriteValue::I64(l) => ctx.builder.get_local_i64(l),
}
ctx.builder
.const_i32(ctx.start_of_current_instruction as i32);
@ -916,7 +936,10 @@ pub fn gen_safe_read_write(
BitSize::DWORD => {
ctx.builder.call_fn3_ret("safe_write32_slow_jit");
},
BitSize::QWORD => dbg_assert!(false),
BitSize::QWORD => {
ctx.builder
.call_fn3_i32_i64_i32_ret("safe_write64_slow_jit");
},
BitSize::DQWORD => dbg_assert!(false),
}
@ -931,6 +954,7 @@ pub fn gen_safe_read_write(
BitSize::BYTE => 8,
BitSize::WORD => 16,
BitSize::DWORD => 32,
BitSize::QWORD => 64,
_ => {
dbg_assert!(false);
0
@ -948,7 +972,10 @@ pub fn gen_safe_read_write(
ctx.builder.block_end();
ctx.builder.get_local(&phys_addr_local);
ctx.builder.get_local(&value_local);
match &value_local {
GenSafeReadWriteValue::I32(l) => ctx.builder.get_local(l),
GenSafeReadWriteValue::I64(l) => ctx.builder.get_local_i64(l),
}
match bits {
BitSize::BYTE => {
@ -960,11 +987,16 @@ pub fn gen_safe_read_write(
BitSize::DWORD => {
ctx.builder.store_unaligned_i32(0);
},
BitSize::QWORD => dbg_assert!(false),
BitSize::QWORD => {
ctx.builder.store_unaligned_i64(0);
},
BitSize::DQWORD => dbg_assert!(false),
}
ctx.builder.free_local(value_local);
match value_local {
GenSafeReadWriteValue::I32(l) => ctx.builder.free_local(l),
GenSafeReadWriteValue::I64(l) => ctx.builder.free_local_i64(l),
}
ctx.builder.free_local(can_use_fast_path_local);
ctx.builder.free_local(phys_addr_local);
}

View file

@ -2859,6 +2859,10 @@ pub unsafe fn safe_read_write16_slow_jit(addr: i32, eip: i32) -> i32 {
pub unsafe fn safe_read_write32s_slow_jit(addr: i32, eip: i32) -> i32 {
safe_read_slow_jit(addr, 32, eip, true)
}
#[no_mangle]
pub unsafe fn safe_read_write64_slow_jit(addr: i32, eip: i32) -> i32 {
safe_read_slow_jit(addr, 64, eip, true)
}
pub unsafe fn safe_write_slow_jit(
addr: i32,

View file

@ -4,7 +4,7 @@ use codegen;
use codegen::BitSize;
use cpu::cpu::{
FLAGS_ALL, FLAGS_DEFAULT, FLAGS_MASK, FLAG_ADJUST, FLAG_CARRY, FLAG_DIRECTION, FLAG_INTERRUPT,
FLAG_OVERFLOW, FLAG_SUB, OPSIZE_8, OPSIZE_16, OPSIZE_32,
FLAG_OVERFLOW, FLAG_SUB, FLAG_ZERO, OPSIZE_8, OPSIZE_16, OPSIZE_32,
};
use cpu::global_pointers;
use jit::JitContext;
@ -4226,6 +4226,56 @@ pub fn instr_0FC3_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
}
pub fn instr_0FC3_reg_jit(ctx: &mut JitContext, _r1: u32, _r2: u32) { codegen::gen_trigger_ud(ctx) }
pub fn instr16_0FC7_1_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte) {
// cmpxchg8b
codegen::gen_modrm_resolve(ctx, modrm_byte);
let address_local = ctx.builder.set_new_local();
codegen::gen_safe_read_write(ctx, BitSize::QWORD, &address_local, &|ref mut ctx| {
let dest_operand = ctx.builder.tee_new_local_i64();
codegen::gen_get_reg32(ctx, regs::EDX);
ctx.builder.extend_unsigned_i32_to_i64();
ctx.builder.const_i64(32);
ctx.builder.shl_i64();
codegen::gen_get_reg32(ctx, regs::EAX);
ctx.builder.extend_unsigned_i32_to_i64();
ctx.builder.or_i64();
ctx.builder.eq_i64();
ctx.builder.if_i64();
{
codegen::gen_set_flags_bits(ctx.builder, FLAG_ZERO);
codegen::gen_get_reg32(ctx, regs::ECX);
ctx.builder.extend_unsigned_i32_to_i64();
ctx.builder.const_i64(32);
ctx.builder.shl_i64();
codegen::gen_get_reg32(ctx, regs::EBX);
ctx.builder.extend_unsigned_i32_to_i64();
ctx.builder.or_i64();
}
ctx.builder.else_();
{
codegen::gen_clear_flags_bits(ctx.builder, FLAG_ZERO);
ctx.builder.get_local_i64(&dest_operand);
ctx.builder.wrap_i64_to_i32();
codegen::gen_set_reg32(ctx, regs::EAX);
ctx.builder.get_local_i64(&dest_operand);
ctx.builder.const_i64(32);
ctx.builder.shr_u_i64();
ctx.builder.wrap_i64_to_i32();
codegen::gen_set_reg32(ctx, regs::EDX);
ctx.builder.get_local_i64(&dest_operand);
}
ctx.builder.block_end();
codegen::gen_clear_flags_changed_bits(ctx.builder, FLAG_ZERO);
ctx.builder.free_local_i64(dest_operand);
});
ctx.builder.free_local(address_local);
}
pub fn instr16_0FC7_1_reg_jit(ctx: &mut JitContext, _r: u32) { codegen::gen_trigger_ud(ctx); }
pub fn instr32_0FC7_1_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte) {
instr16_0FC7_1_mem_jit(ctx, modrm_byte);
}
pub fn instr32_0FC7_1_reg_jit(ctx: &mut JitContext, _r: u32) { codegen::gen_trigger_ud(ctx); }
pub fn instr_C6_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) {
// reg8[r] = imm;
ctx.builder.const_i32(imm as i32);

View file

@ -717,6 +717,7 @@ impl WasmBuilder {
pub fn shr_s_i32(&mut self) { self.instruction_body.push(op::OP_I32SHRS); }
pub fn eq_i32(&mut self) { self.instruction_body.push(op::OP_I32EQ); }
pub fn eq_i64(&mut self) { self.instruction_body.push(op::OP_I64EQ); }
pub fn ne_i32(&mut self) { self.instruction_body.push(op::OP_I32NE); }
pub fn ne_i64(&mut self) { self.instruction_body.push(op::OP_I64NE); }
pub fn le_i32(&mut self) { self.instruction_body.push(op::OP_I32LES); }