jit movsb/movsw/movsd

This commit is contained in:
Fabian 2021-04-10 14:27:14 -05:00
parent 6049e0c46c
commit 48464a18d7
3 changed files with 66 additions and 6 deletions

View file

@ -214,11 +214,10 @@ const encodings = [
{ opcode: 0xA3, custom: 1, os: 1, immaddr: 1 },
// string instructions aren't jumps, but they modify eip due to how they're implemented
// TODO: The block_boundary on the non-rep instructions can be removed once they're custom
{ opcode: 0xA4, block_boundary: 1, custom: 1, is_string: 1, },
{ opcode: 0xA4, block_boundary: 0, custom: 1, is_string: 1, },
{ opcode: 0xF2A4, block_boundary: 1, custom: 1, is_string: 1, },
{ opcode: 0xF3A4, block_boundary: 1, custom: 1, is_string: 1, },
{ opcode: 0xA5, block_boundary: 1, custom: 1, is_string: 1, os: 1, },
{ opcode: 0xA5, block_boundary: 0, custom: 1, is_string: 1, os: 1, },
{ opcode: 0xF2A5, block_boundary: 1, custom: 1, is_string: 1, os: 1, },
{ opcode: 0xF3A5, block_boundary: 1, custom: 1, is_string: 1, os: 1, },

View file

@ -470,15 +470,12 @@ pub unsafe fn movsw_rep(is_asize_32: bool, ds: i32) {
pub unsafe fn movsd_rep(is_asize_32: bool, ds: i32) {
string_instruction(is_asize_32, ds, Instruction::Movs, Size::D, Rep::Z)
}
#[no_mangle]
pub unsafe fn movsb_no_rep(is_asize_32: bool, ds: i32) {
string_instruction(is_asize_32, ds, Instruction::Movs, Size::B, Rep::None)
}
#[no_mangle]
pub unsafe fn movsw_no_rep(is_asize_32: bool, ds: i32) {
string_instruction(is_asize_32, ds, Instruction::Movs, Size::W, Rep::None)
}
#[no_mangle]
pub unsafe fn movsd_no_rep(is_asize_32: bool, ds: i32) {
string_instruction(is_asize_32, ds, Instruction::Movs, Size::D, Rep::None)
}

View file

@ -4590,6 +4590,70 @@ fn gen_string_ins(ctx: &mut JitContext, ins: String, size: u8, prefix: u8) {
}
return;
},
String::MOVS => {
if ctx.cpu.asize_32() {
codegen::gen_get_reg32(ctx, regs::EDI);
}
else {
codegen::gen_get_reg16(ctx, regs::EDI);
}
jit_add_seg_offset_no_override(ctx, regs::ES);
let dest_address = ctx.builder.set_new_local();
if ctx.cpu.asize_32() {
codegen::gen_get_reg32(ctx, regs::ESI);
}
else {
codegen::gen_get_reg16(ctx, regs::ESI);
}
jit_add_seg_offset_no_override(ctx, regs::DS);
let source_address = ctx.builder.set_new_local();
if size == 8 {
codegen::gen_safe_read8(ctx, &source_address);
ctx.builder.free_local(source_address);
let value = ctx.builder.set_new_local();
codegen::gen_safe_write8(ctx, &dest_address, &value);
ctx.builder.free_local(value);
}
else if size == 16 {
codegen::gen_safe_read32(ctx, &source_address);
ctx.builder.free_local(source_address);
let value = ctx.builder.set_new_local();
codegen::gen_safe_write16(ctx, &dest_address, &value);
ctx.builder.free_local(value);
}
else {
codegen::gen_safe_read32(ctx, &source_address);
ctx.builder.free_local(source_address);
let value = ctx.builder.set_new_local();
codegen::gen_safe_write32(ctx, &dest_address, &value);
ctx.builder.free_local(value);
}
ctx.builder.free_local(dest_address);
codegen::gen_get_reg32(ctx, regs::EDI);
get_direction(ctx, size);
ctx.builder.add_i32();
if ctx.cpu.asize_32() {
codegen::gen_set_reg32(ctx, regs::EDI);
}
else {
codegen::gen_set_reg16(ctx, regs::EDI);
}
codegen::gen_get_reg32(ctx, regs::ESI);
get_direction(ctx, size);
ctx.builder.add_i32();
if ctx.cpu.asize_32() {
codegen::gen_set_reg32(ctx, regs::ESI);
}
else {
codegen::gen_set_reg16(ctx, regs::ESI);
}
return;
},
_ => {},
}
}