jit bts/btr/btc

This commit is contained in:
Fabian 2020-12-31 19:14:33 -06:00
parent 390b8c4cbb
commit 9da02b46f1
2 changed files with 319 additions and 7 deletions

View file

@ -538,15 +538,15 @@ const encodings = [
{ opcode: 0x0FA8, os: 1, custom: 1, },
{ opcode: 0x0FA9, os: 1, block_boundary: 1, skip: 1, }, // pop gs
{ opcode: 0x0FA3, os: 1, e: 1, custom: 1, skip_mem: 1, }, // bt (can also index memory, but not supported by test right now)
{ opcode: 0x0FAB, os: 1, e: 1, skip_mem: 1, },
{ opcode: 0x0FB3, os: 1, e: 1, skip_mem: 1, },
{ opcode: 0x0FBB, os: 1, e: 1, skip_mem: 1, },
{ opcode: 0x0FA3, os: 1, e: 1, custom: 1, skip_mem: 1 }, // bt (can also index memory, but not supported by test right now)
{ opcode: 0x0FAB, os: 1, e: 1, custom: 1, skip_mem: 1 },
{ opcode: 0x0FB3, os: 1, e: 1, custom: 1, skip_mem: 1 },
{ opcode: 0x0FBB, os: 1, e: 1, custom: 1, skip_mem: 1 },
{ opcode: 0x0FBA, os: 1, e: 1, fixed_g: 4, imm8: 1, custom: 1 }, // bt
{ opcode: 0x0FBA, os: 1, e: 1, fixed_g: 5, imm8: 1 },
{ opcode: 0x0FBA, os: 1, e: 1, fixed_g: 6, imm8: 1 },
{ opcode: 0x0FBA, os: 1, e: 1, fixed_g: 7, imm8: 1 },
{ opcode: 0x0FBA, os: 1, e: 1, fixed_g: 5, imm8: 1, custom: 1 },
{ opcode: 0x0FBA, os: 1, e: 1, fixed_g: 6, imm8: 1, custom: 1 },
{ opcode: 0x0FBA, os: 1, e: 1, fixed_g: 7, imm8: 1, custom: 1 },
{ opcode: 0x0FBC, os: 1, e: 1, mask_flags: af, custom: 1 }, // bsf
{ opcode: 0x0FBD, os: 1, e: 1, mask_flags: af, custom: 1 },

View file

@ -1498,6 +1498,108 @@ fn gen_bt(
codegen::gen_clear_flags_changed_bits(builder, 1);
}
fn gen_bts(
builder: &mut WasmBuilder,
dest_bit_base: &WasmLocal,
bit_offset: &LocalOrImmediate,
offset_mask: u32,
) {
gen_bt(builder, dest_bit_base, bit_offset, offset_mask);
builder.get_local(dest_bit_base);
match bit_offset {
LocalOrImmediate::WasmLocal(l) => {
builder.const_i32(1);
builder.get_local(l);
builder.const_i32(offset_mask as i32);
builder.and_i32();
builder.shl_i32();
},
LocalOrImmediate::Immediate(imm) => builder.const_i32(1 << (imm & offset_mask as i32)),
}
builder.or_i32();
builder.set_local(dest_bit_base);
}
fn gen_btc(
builder: &mut WasmBuilder,
dest_bit_base: &WasmLocal,
bit_offset: &LocalOrImmediate,
offset_mask: u32,
) {
gen_bt(builder, dest_bit_base, bit_offset, offset_mask);
builder.get_local(dest_bit_base);
match bit_offset {
LocalOrImmediate::WasmLocal(l) => {
builder.const_i32(1);
builder.get_local(l);
builder.const_i32(offset_mask as i32);
builder.and_i32();
builder.shl_i32();
},
LocalOrImmediate::Immediate(imm) => builder.const_i32(1 << (imm & offset_mask as i32)),
}
builder.xor_i32();
builder.set_local(dest_bit_base);
}
fn gen_btr(
builder: &mut WasmBuilder,
dest_bit_base: &WasmLocal,
bit_offset: &LocalOrImmediate,
offset_mask: u32,
) {
gen_bt(builder, dest_bit_base, bit_offset, offset_mask);
builder.get_local(dest_bit_base);
match bit_offset {
LocalOrImmediate::WasmLocal(l) => {
builder.const_i32(1);
builder.get_local(l);
builder.const_i32(offset_mask as i32);
builder.and_i32();
builder.shl_i32();
builder.const_i32(-1);
builder.xor_i32();
},
LocalOrImmediate::Immediate(imm) => builder.const_i32(!(1 << (imm & offset_mask as i32))),
}
builder.and_i32();
builder.set_local(dest_bit_base);
}
fn gen_bit_rmw(
ctx: &mut JitContext,
modrm_byte: ModrmByte,
op: &dyn Fn(&mut WasmBuilder, &WasmLocal, &LocalOrImmediate, u32),
source_operand: &LocalOrImmediate,
opsize: i32,
) {
dbg_assert!(opsize == 16 || opsize == 32);
codegen::gen_modrm_resolve(ctx, modrm_byte);
match source_operand {
LocalOrImmediate::WasmLocal(l) => {
ctx.builder.get_local(l);
if opsize == 16 {
codegen::sign_extend_i16(ctx.builder);
}
ctx.builder.const_i32(3);
ctx.builder.shr_s_i32();
ctx.builder.add_i32();
},
LocalOrImmediate::Immediate(imm8) => {
ctx.builder.const_i32((*imm8 as i32 & (opsize - 1)) >> 3);
ctx.builder.add_i32();
},
}
let address_local = ctx.builder.set_new_local();
codegen::gen_safe_read_write(ctx, BitSize::BYTE, &address_local, &|ref mut ctx| {
let value_local = ctx.builder.set_new_local();
op(ctx.builder, &value_local, source_operand, 7);
ctx.builder.get_local(&value_local);
ctx.builder.free_local(value_local);
});
ctx.builder.free_local(address_local);
}
fn gen_bsf32(
builder: &mut WasmBuilder,
@ -5269,6 +5371,111 @@ pub fn instr32_0FA3_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32)
ctx.builder.free_local(value);
}
pub fn instr16_0FAB_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
gen_bts(
&mut ctx.builder,
&ctx.register_locals[r1 as usize],
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r2 as usize]),
15,
)
}
pub fn instr16_0FAB_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_bts,
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r as usize].unsafe_clone()),
16,
);
}
pub fn instr32_0FAB_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
gen_bts(
&mut ctx.builder,
&ctx.register_locals[r1 as usize],
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r2 as usize]),
31,
)
}
pub fn instr32_0FAB_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_bts,
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r as usize].unsafe_clone()),
32,
);
}
pub fn instr16_0FB3_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
gen_btr(
&mut ctx.builder,
&ctx.register_locals[r1 as usize],
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r2 as usize]),
15,
)
}
pub fn instr16_0FB3_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_btr,
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r as usize].unsafe_clone()),
16,
);
}
pub fn instr32_0FB3_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
gen_btr(
&mut ctx.builder,
&ctx.register_locals[r1 as usize],
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r2 as usize]),
31,
)
}
pub fn instr32_0FB3_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_btr,
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r as usize].unsafe_clone()),
32,
);
}
pub fn instr16_0FBB_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
gen_btc(
&mut ctx.builder,
&ctx.register_locals[r1 as usize],
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r2 as usize]),
15,
)
}
pub fn instr16_0FBB_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_btc,
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r as usize].unsafe_clone()),
16,
);
}
pub fn instr32_0FBB_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
gen_btc(
&mut ctx.builder,
&ctx.register_locals[r1 as usize],
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r2 as usize]),
31,
)
}
pub fn instr32_0FBB_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_btc,
&LocalOrImmediate::WasmLocal(&ctx.register_locals[r as usize].unsafe_clone()),
32,
);
}
pub fn instr16_0FBA_4_reg_jit(ctx: &mut JitContext, r: u32, imm8: u32) {
gen_bt(
&mut ctx.builder,
@ -5318,6 +5525,111 @@ pub fn instr32_0FBA_4_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, imm8:
ctx.builder.free_local(value);
}
pub fn instr16_0FBA_5_reg_jit(ctx: &mut JitContext, r: u32, imm8: u32) {
gen_bts(
&mut ctx.builder,
&ctx.register_locals[r as usize],
&LocalOrImmediate::Immediate(imm8 as i32),
15,
)
}
pub fn instr16_0FBA_5_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, imm8: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_bts,
&LocalOrImmediate::Immediate(imm8 as i32),
16,
);
}
pub fn instr32_0FBA_5_reg_jit(ctx: &mut JitContext, r: u32, imm8: u32) {
gen_bts(
&mut ctx.builder,
&ctx.register_locals[r as usize],
&LocalOrImmediate::Immediate(imm8 as i32),
31,
)
}
pub fn instr32_0FBA_5_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, imm8: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_bts,
&LocalOrImmediate::Immediate(imm8 as i32),
32,
);
}
pub fn instr16_0FBA_6_reg_jit(ctx: &mut JitContext, r: u32, imm8: u32) {
gen_btr(
&mut ctx.builder,
&ctx.register_locals[r as usize],
&LocalOrImmediate::Immediate(imm8 as i32),
15,
)
}
pub fn instr16_0FBA_6_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, imm8: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_btr,
&LocalOrImmediate::Immediate(imm8 as i32),
16,
);
}
pub fn instr32_0FBA_6_reg_jit(ctx: &mut JitContext, r: u32, imm8: u32) {
gen_btr(
&mut ctx.builder,
&ctx.register_locals[r as usize],
&LocalOrImmediate::Immediate(imm8 as i32),
31,
)
}
pub fn instr32_0FBA_6_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, imm8: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_btr,
&LocalOrImmediate::Immediate(imm8 as i32),
32,
);
}
pub fn instr16_0FBA_7_reg_jit(ctx: &mut JitContext, r: u32, imm8: u32) {
gen_btc(
&mut ctx.builder,
&ctx.register_locals[r as usize],
&LocalOrImmediate::Immediate(imm8 as i32),
15,
)
}
pub fn instr16_0FBA_7_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, imm8: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_btc,
&LocalOrImmediate::Immediate(imm8 as i32),
16,
);
}
pub fn instr32_0FBA_7_reg_jit(ctx: &mut JitContext, r: u32, imm8: u32) {
gen_btc(
&mut ctx.builder,
&ctx.register_locals[r as usize],
&LocalOrImmediate::Immediate(imm8 as i32),
31,
)
}
pub fn instr32_0FBA_7_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, imm8: u32) {
gen_bit_rmw(
ctx,
modrm_byte,
&gen_btc,
&LocalOrImmediate::Immediate(imm8 as i32),
32,
);
}
pub fn instr_0FAE_5_mem_jit(ctx: &mut JitContext, _modrm_byte: ModrmByte) {
dbg_log!("Generating #ud for unimplemented instruction: instr_0FAE_5_mem_jit");
codegen::gen_trigger_ud(ctx);