add gen_safe_write16, jit instr16_C7_0_mem
This commit is contained in:
parent
dbd8c7b9fa
commit
6f45d5f6ed
|
@ -334,6 +334,84 @@ pub fn gen_safe_write32(ctx: &mut JitContext, address_local: &WasmLocal, value_l
|
|||
builder.free_local(phys_addr_local);
|
||||
}
|
||||
|
||||
pub fn gen_safe_write16(ctx: &mut JitContext, address_local: &WasmLocal, value_local: &WasmLocal) {
|
||||
// Generates safe_write16' fast-path inline, bailing to safe_write16_slow if necessary.
|
||||
|
||||
let builder = &mut ctx.builder;
|
||||
//let instruction_body = &mut ctx.builder.instruction_body;
|
||||
//let cpu = &mut ctx.cpu;
|
||||
|
||||
wasm_util::get_local(&mut builder.instruction_body, &address_local);
|
||||
|
||||
// Pseudo: base_on_stack = (uint32_t)address >> 12;
|
||||
wasm_util::push_i32(&mut builder.instruction_body, 12);
|
||||
wasm_util::shr_u32(&mut builder.instruction_body);
|
||||
|
||||
// scale index
|
||||
wasm_util::push_i32(&mut builder.instruction_body, 2);
|
||||
wasm_util::shl_i32(&mut builder.instruction_body);
|
||||
|
||||
// Pseudo: entry = tlb_data[base_on_stack];
|
||||
let entry_local = builder.alloc_local();
|
||||
wasm_util::load_aligned_i32_from_stack(
|
||||
&mut builder.instruction_body,
|
||||
global_pointers::TLB_DATA,
|
||||
);
|
||||
wasm_util::tee_local(&mut builder.instruction_body, &entry_local);
|
||||
|
||||
// Pseudo: bool can_use_fast_path = (entry & 0xFFF & ~TLB_GLOBAL & ~(cpl == 3 ? 0 : TLB_NO_USER) == TLB_VALID &&
|
||||
// (address & 0xFFF) <= (0x1000 - 4));
|
||||
wasm_util::push_i32(
|
||||
&mut builder.instruction_body,
|
||||
(0xFFF & !TLB_GLOBAL & !(if ctx.cpu.cpl3() { 0 } else { TLB_NO_USER })) as i32,
|
||||
);
|
||||
wasm_util::and_i32(&mut builder.instruction_body);
|
||||
|
||||
wasm_util::push_i32(&mut builder.instruction_body, TLB_VALID as i32);
|
||||
wasm_util::eq_i32(&mut builder.instruction_body);
|
||||
|
||||
wasm_util::get_local(&mut builder.instruction_body, &address_local);
|
||||
wasm_util::push_i32(&mut builder.instruction_body, 0xFFF);
|
||||
wasm_util::and_i32(&mut builder.instruction_body);
|
||||
wasm_util::push_i32(&mut builder.instruction_body, 0x1000 - 2);
|
||||
wasm_util::le_i32(&mut builder.instruction_body);
|
||||
|
||||
wasm_util::and_i32(&mut builder.instruction_body);
|
||||
|
||||
// Pseudo:
|
||||
// if(can_use_fast_path)
|
||||
// {
|
||||
// phys_addr = entry & ~0xFFF ^ address;
|
||||
wasm_util::if_void(&mut builder.instruction_body);
|
||||
|
||||
wasm_util::get_local(&mut builder.instruction_body, &entry_local);
|
||||
wasm_util::push_i32(&mut builder.instruction_body, !0xFFF);
|
||||
wasm_util::and_i32(&mut builder.instruction_body);
|
||||
wasm_util::get_local(&mut builder.instruction_body, &address_local);
|
||||
wasm_util::xor_i32(&mut builder.instruction_body);
|
||||
|
||||
builder.free_local(entry_local);
|
||||
|
||||
let phys_addr_local = builder.alloc_local();
|
||||
// Pseudo:
|
||||
// /* continued within can_use_fast_path branch */
|
||||
// mem8[phys_addr] = value;
|
||||
|
||||
wasm_util::tee_local(&mut builder.instruction_body, &phys_addr_local);
|
||||
wasm_util::get_local(&mut builder.instruction_body, &value_local);
|
||||
wasm_util::store_unaligned_u16(&mut builder.instruction_body, global_pointers::MEMORY);
|
||||
|
||||
// Pseudo:
|
||||
// else { safe_read16_slow(address, value); }
|
||||
wasm_util::else_(&mut builder.instruction_body);
|
||||
wasm_util::get_local(&mut builder.instruction_body, &address_local);
|
||||
wasm_util::get_local(&mut builder.instruction_body, &value_local);
|
||||
gen_call_fn2(builder, "safe_write16_slow");
|
||||
wasm_util::block_end(&mut builder.instruction_body);
|
||||
|
||||
builder.free_local(phys_addr_local);
|
||||
}
|
||||
|
||||
pub fn gen_fn1_reg16(ctx: &mut JitContext, name: &str, r: u32) {
|
||||
let fn_idx = ctx.builder.get_fn_idx(name, module_init::FN1_TYPE_INDEX);
|
||||
wasm_util::load_aligned_u16(
|
||||
|
|
|
@ -481,10 +481,16 @@ pub fn instr16_C7_0_reg_jit(ctx: &mut JitContext, r: u32, imm: u32) {
|
|||
}
|
||||
|
||||
pub fn instr16_C7_0_mem_jit(ctx: &mut JitContext, modrm_byte: u8) {
|
||||
let address_local = ctx.builder.alloc_local();
|
||||
let value_local = ctx.builder.alloc_local();
|
||||
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
||||
let imm = ctx.cpu.read_imm16() as u32;
|
||||
// XXX: inline called function
|
||||
codegen::gen_modrm_fn1(ctx, "instr16_C7_0_mem", imm);
|
||||
wasm_util::set_local(&mut ctx.builder.instruction_body, &address_local);
|
||||
let imm = ctx.cpu.read_imm16();
|
||||
wasm_util::push_i32(&mut ctx.builder.instruction_body, imm as i32);
|
||||
wasm_util::set_local(&mut ctx.builder.instruction_body, &value_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) {
|
||||
|
|
|
@ -99,6 +99,12 @@ pub fn store_unaligned_i32(buf: &mut Vec<u8>, byte_offset: u32) {
|
|||
write_leb_u32(buf, byte_offset);
|
||||
}
|
||||
|
||||
pub fn store_unaligned_u16(buf: &mut Vec<u8>, byte_offset: u32) {
|
||||
buf.push(op::OP_I32STORE16);
|
||||
buf.push(op::MEM_NO_ALIGN);
|
||||
write_leb_u32(buf, byte_offset);
|
||||
}
|
||||
|
||||
pub fn shr_u32(buf: &mut Vec<u8>) { buf.push(op::OP_I32SHRU); }
|
||||
|
||||
pub fn shr_i32(buf: &mut Vec<u8>) { buf.push(op::OP_I32SHRS); }
|
||||
|
|
Loading…
Reference in a new issue