Custom codegen for xadd (0FC1)

This commit is contained in:
Fabian 2019-01-07 15:35:57 +01:00
parent 874818866a
commit fdd1dc377d
4 changed files with 76 additions and 8 deletions

View file

@ -604,7 +604,7 @@ const encodings = [
{ opcode: 0x0FBF, os: 1, e: 1, custom: 1 },
{ opcode: 0x0FC0, e: 1, }, // xadd
{ opcode: 0x0FC1, os: 1, e: 1, custom: 0, unguarded_register: 1 }, // XXX: Add custom back
{ opcode: 0x0FC1, os: 1, e: 1, custom: 1 },
{ opcode: 0x0FC8, }, // bswap
{ opcode: 0x0FC9, },

View file

@ -1296,6 +1296,30 @@ pub fn gen_safe_read_write(
ctx.builder.free_local(entry_local);
}
pub fn gen_set_last_op1(builder: &mut WasmBuilder, source: &WasmLocal) {
builder
.instruction_body
.const_i32(global_pointers::LAST_OP1 as i32);
builder.instruction_body.get_local(&source);
builder.instruction_body.store_aligned_i32(0);
}
pub fn gen_set_last_op2(builder: &mut WasmBuilder, source: &WasmLocal) {
builder
.instruction_body
.const_i32(global_pointers::LAST_OP2 as i32);
builder.instruction_body.get_local(&source);
builder.instruction_body.store_aligned_i32(0);
}
pub fn gen_set_last_add_result(builder: &mut WasmBuilder, source: &WasmLocal) {
builder
.instruction_body
.const_i32(global_pointers::LAST_ADD_RESULT as i32);
builder.instruction_body.get_local(&source);
builder.instruction_body.store_aligned_i32(0);
}
pub fn gen_set_last_result(builder: &mut WasmBuilder, source: &WasmLocal) {
builder
.instruction_body

View file

@ -1,5 +1,8 @@
pub const REG: u32 = 4;
pub const LAST_OP1: u32 = 512;
pub const LAST_OP2: u32 = 516;
pub const LAST_OP_SIZE: u32 = 520;
pub const LAST_ADD_RESULT: u32 = 524;
pub const LAST_RESULT: u32 = 528;
pub const FLAGS_CHANGED: u32 = 532;
pub const FLAGS: u32 = 536;

View file

@ -13,6 +13,7 @@ use regs;
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;
use wasmgen::wasm_util::WasmBuf;
pub fn jit_instruction(ctx: &mut JitContext, instr_flags: &mut u32) {
@ -752,6 +753,46 @@ macro_rules! define_instruction_read_write_mem32(
);
);
pub fn gen_add32(builder: &mut WasmBuilder) {
let source_operand = builder.set_new_local();
let dest_operand = builder.set_new_local();
builder.instruction_body.get_local(&dest_operand);
builder.instruction_body.get_local(&source_operand);
builder.instruction_body.add_i32();
let result = builder.set_new_local();
codegen::gen_set_last_op1(builder, &dest_operand);
codegen::gen_set_last_op2(builder, &source_operand);
codegen::gen_set_last_add_result(builder, &result);
codegen::gen_set_last_result(builder, &result);
codegen::gen_set_last_op_size(builder, OPSIZE_32);
codegen::gen_set_flags_changed(builder, FLAGS_ALL);
// leave result on stack
builder.instruction_body.get_local(&result);
builder.free_local(dest_operand);
builder.free_local(source_operand);
builder.free_local(result);
}
fn gen_xadd32(ctx: &mut JitContext, r: u32) {
let source = ctx.builder.set_new_local();
codegen::gen_get_reg32(ctx, r);
let tmp = ctx.builder.set_new_local();
ctx.builder.instruction_body.get_local(&source);
codegen::gen_set_reg32(ctx, r);
ctx.builder.instruction_body.get_local(&source);
ctx.builder.instruction_body.get_local(&tmp);
gen_add32(ctx.builder);
ctx.builder.free_local(source);
ctx.builder.free_local(tmp);
}
fn gen_mul32(ctx: &mut JitContext) {
ctx.builder.instruction_body.extend_unsigned_i32_to_i64();
@ -3203,12 +3244,12 @@ pub fn instr16_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
ctx.builder
.instruction_body
.const_i32(::cpu2::cpu::get_reg16_index(r as i32));
codegen::gen_move_registers_from_locals_to_memory(ctx);
codegen::gen_call_fn2_ret(ctx.builder, "xadd16");
codegen::gen_move_registers_from_memory_to_locals(ctx);
},
&|ref mut ctx| {
ctx.builder
.instruction_body
.const_i32(::cpu2::cpu::get_reg16_index(r as i32));
ctx.builder.instruction_body.const_i32(r as i32);
codegen::gen_move_registers_from_locals_to_memory(ctx);
codegen::gen_call_fn2(ctx.builder, "instr16_0FC1_mem");
codegen::gen_move_registers_from_memory_to_locals(ctx);
@ -3221,7 +3262,9 @@ pub fn instr16_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
ctx.builder
.instruction_body
.const_i32(::cpu2::cpu::get_reg16_index(r2 as i32));
codegen::gen_move_registers_from_locals_to_memory(ctx);
codegen::gen_call_fn2_ret(ctx.builder, "xadd16");
codegen::gen_move_registers_from_memory_to_locals(ctx);
codegen::gen_set_reg16(ctx, r1);
}
@ -3233,8 +3276,7 @@ pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
BitSize::DWORD,
&address_local,
&|ref mut ctx| {
ctx.builder.instruction_body.const_i32(r as i32);
codegen::gen_call_fn2_ret(ctx.builder, "xadd32");
gen_xadd32(ctx, r);
},
&|ref mut ctx| {
ctx.builder.instruction_body.const_i32(r as i32);
@ -3247,8 +3289,7 @@ pub fn instr32_0FC1_mem_jit(ctx: &mut JitContext, modrm_byte: u8, r: u32) {
}
pub fn instr32_0FC1_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
codegen::gen_get_reg32(ctx, r1);
ctx.builder.instruction_body.const_i32(r2 as i32);
codegen::gen_call_fn2_ret(ctx.builder, "xadd32");
gen_xadd32(ctx, r2);
codegen::gen_set_reg32(ctx, r1);
}