jit: generate code for {66,}0f{c4,c5} (pinsrw, pextrw)

This commit is contained in:
Fabian 2022-11-21 20:07:33 -06:00
parent 625fdcd4a2
commit de2a1439aa
5 changed files with 64 additions and 28 deletions

View file

@ -819,10 +819,10 @@ const encodings = [
{ opcode: 0x0FC3, e: 1, custom: 1, reg_ud: 1, }, // movnti: Uses normal registers, hence not marked as sse
{ sse: 1, opcode: 0x0FC4, e: 1, imm8: 1 },
{ sse: 1, opcode: 0x660FC4, e: 1, imm8: 1 },
{ sse: 1, opcode: 0x0FC5, e: 1, mem_ud: 1, imm8: 1 },
{ sse: 1, opcode: 0x660FC5, e: 1, mem_ud: 1, imm8: 1, },
{ sse: 1, opcode: 0x0FC4, e: 1, imm8: 1, custom: 1 },
{ sse: 1, opcode: 0x660FC4, e: 1, imm8: 1, custom: 1 },
{ sse: 1, opcode: 0x0FC5, e: 1, mem_ud: 1, imm8: 1, custom: 1 },
{ sse: 1, opcode: 0x660FC5, e: 1, mem_ud: 1, imm8: 1, custom: 1 },
{ sse: 1, opcode: 0x0FC6, e: 1, imm8: 1, custom: 1 },
{ sse: 1, opcode: 0x660FC6, e: 1, imm8: 1, custom: 1 },

View file

@ -424,12 +424,6 @@ pub fn gen_fn2_const(builder: &mut WasmBuilder, name: &str, arg0: u32, arg1: u32
builder.const_i32(arg1 as i32);
builder.call_fn2(name);
}
pub fn gen_fn3_const(builder: &mut WasmBuilder, name: &str, arg0: u32, arg1: u32, arg2: u32) {
builder.const_i32(arg0 as i32);
builder.const_i32(arg1 as i32);
builder.const_i32(arg2 as i32);
builder.call_fn3(name);
}
// helper functions for gen/generate_jit.js
pub fn gen_modrm_fn0(builder: &mut WasmBuilder, name: &str) {
@ -441,12 +435,6 @@ pub fn gen_modrm_fn1(builder: &mut WasmBuilder, name: &str, arg0: u32) {
builder.const_i32(arg0 as i32);
builder.call_fn2(name);
}
pub fn gen_modrm_fn2(builder: &mut WasmBuilder, name: &str, arg0: u32, arg1: u32) {
// generates: fn( _, arg0, arg1 )
builder.const_i32(arg0 as i32);
builder.const_i32(arg1 as i32);
builder.call_fn3(name);
}
pub fn gen_modrm_resolve(ctx: &mut JitContext, modrm_byte: ModrmByte) {
modrm::gen(ctx, modrm_byte)

View file

@ -3723,6 +3723,8 @@ pub unsafe fn instr_0FC3_mem(addr: i32, r: i32) {
// movnti
return_on_pagefault!(safe_write32(addr, read_reg32(r)));
}
#[no_mangle]
pub unsafe fn instr_0FC4(source: i32, r: i32, imm8: i32) {
// pinsrw mm, r32/m16, imm8
let mut destination: [u16; 4] = std::mem::transmute(read_mmx64s(r));
@ -3730,9 +3732,7 @@ pub unsafe fn instr_0FC4(source: i32, r: i32, imm8: i32) {
write_mmx_reg64(r, std::mem::transmute(destination));
transition_fpu_to_mmx();
}
#[no_mangle]
pub unsafe fn instr_0FC4_reg(r1: i32, r2: i32, imm: i32) { instr_0FC4(read_reg32(r1), r2, imm); }
#[no_mangle]
pub unsafe fn instr_0FC4_mem(addr: i32, r: i32, imm: i32) {
instr_0FC4(return_on_pagefault!(safe_read16(addr)), r, imm);
}
@ -3743,15 +3743,12 @@ pub unsafe fn instr_660FC4(source: i32, r: i32, imm8: i32) {
destination.u16[index as usize] = (source & 0xFFFF) as u16;
write_xmm_reg128(r, destination);
}
#[no_mangle]
pub unsafe fn instr_660FC4_reg(r1: i32, r2: i32, imm: i32) {
instr_660FC4(read_reg32(r1), r2, imm);
}
#[no_mangle]
pub unsafe fn instr_660FC4_mem(addr: i32, r: i32, imm: i32) {
instr_660FC4(return_on_pagefault!(safe_read16(addr)), r, imm);
}
#[no_mangle]
pub unsafe fn instr_0FC5_mem(_addr: i32, _r: i32, _imm8: i32) { trigger_ud(); }
#[no_mangle]
pub unsafe fn instr_0FC5_reg(r1: i32, r2: i32, imm8: i32) {
@ -3760,9 +3757,7 @@ pub unsafe fn instr_0FC5_reg(r1: i32, r2: i32, imm8: i32) {
write_reg32(r2, data[(imm8 & 3) as usize] as i32);
transition_fpu_to_mmx();
}
#[no_mangle]
pub unsafe fn instr_660FC5_mem(_addr: i32, _r: i32, _imm8: i32) { trigger_ud(); }
#[no_mangle]
pub unsafe fn instr_660FC5_reg(r1: i32, r2: i32, imm8: i32) {
// pextrw r32, xmm, imm8
let data = read_xmm128s(r1);

View file

@ -5338,6 +5338,59 @@ 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 instr_0FC4_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32, imm8: u32) {
codegen::gen_modrm_resolve(ctx, modrm_byte);
let address_local = ctx.builder.set_new_local();
codegen::gen_safe_read16(ctx, &address_local);
ctx.builder.const_i32(r as i32);
ctx.builder.const_i32(imm8 as i32);
ctx.builder.call_fn3("instr_0FC4");
ctx.builder.free_local(address_local);
}
pub fn instr_0FC4_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8: u32) {
codegen::gen_get_reg32(ctx, r1);
ctx.builder.const_i32(r2 as i32);
ctx.builder.const_i32(imm8 as i32);
ctx.builder.call_fn3("instr_0FC4");
}
pub fn instr_660FC4_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32, imm8: u32) {
ctx.builder.const_i32(0);
codegen::gen_modrm_resolve(ctx, modrm_byte);
let address_local = ctx.builder.set_new_local();
codegen::gen_safe_read16(ctx, &address_local);
ctx.builder
.store_aligned_u16(global_pointers::get_reg_xmm_offset(r) + ((imm8 & 7) << 1));
ctx.builder.free_local(address_local);
}
pub fn instr_660FC4_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8: u32) {
ctx.builder.const_i32(0);
codegen::gen_get_reg32(ctx, r1);
ctx.builder
.store_aligned_u16(global_pointers::get_reg_xmm_offset(r2) + ((imm8 & 7) << 1));
}
pub fn instr_0FC5_mem_jit(ctx: &mut JitContext, _modrm_byte: ModrmByte, _r: u32, _imm8: u32) {
codegen::gen_trigger_ud(ctx)
}
pub fn instr_0FC5_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8: u32) {
codegen::gen_move_registers_from_locals_to_memory(ctx);
ctx.builder.const_i32(r1 as i32);
ctx.builder.const_i32(r2 as i32);
ctx.builder.const_i32(imm8 as i32);
ctx.builder.call_fn3("instr_0FC5_reg");
codegen::gen_move_registers_from_memory_to_locals(ctx);
}
pub fn instr_660FC5_mem_jit(ctx: &mut JitContext, _modrm_byte: ModrmByte, _r: u32, _imm8: u32) {
codegen::gen_trigger_ud(ctx)
}
pub fn instr_660FC5_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32, imm8: u32) {
ctx.builder
.load_fixed_u16(global_pointers::get_reg_xmm_offset(r1) + ((imm8 & 7) << 1));
codegen::gen_set_reg32(ctx, r2);
}
pub fn instr16_0FC7_1_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte) {
// cmpxchg8b
codegen::gen_modrm_resolve(ctx, modrm_byte);

View file

@ -725,11 +725,11 @@ impl WasmBuilder {
write_leb_u32(&mut self.instruction_body, byte_offset);
}
//pub fn store_aligned_u16(&mut self, byte_offset: u32) {
// self.instruction_body.push(op::OP_I32STORE16);
// self.instruction_body.push(op::MEM_ALIGN16);
// write_leb_u32(&mut self.instruction_body, byte_offset);
//}
pub fn store_aligned_u16(&mut self, byte_offset: u32) {
self.instruction_body.push(op::OP_I32STORE16);
self.instruction_body.push(op::MEM_ALIGN16);
write_leb_u32(&mut self.instruction_body, byte_offset);
}
pub fn store_aligned_i32(&mut self, byte_offset: u32) {
self.instruction_body.push(op::OP_I32STORE);