|
@@ -4455,17 +4455,19 @@ fn gen_string_ins(ctx: &mut JitContext, ins: String, size: u8, prefix: u8) {
|
|
|
dbg_assert!(size == 8 || size == 16 || size == 32);
|
|
|
|
|
|
if prefix == 0 {
|
|
|
- fn get_direction(ctx: &mut JitContext) {
|
|
|
- ctx.builder.const_i32(-1);
|
|
|
- ctx.builder.const_i32(1);
|
|
|
+ fn get_direction(ctx: &mut JitContext, size: u8) {
|
|
|
+ let bytes: i32 = (size / 8).into();
|
|
|
+ dbg_assert!(bytes == 1 || bytes == 2 || bytes == 4);
|
|
|
+ ctx.builder.const_i32(-bytes);
|
|
|
+ ctx.builder.const_i32(bytes);
|
|
|
codegen::gen_get_flags(ctx.builder);
|
|
|
ctx.builder.const_i32(FLAG_DIRECTION);
|
|
|
ctx.builder.and_i32();
|
|
|
ctx.builder.select();
|
|
|
}
|
|
|
|
|
|
- match (&ins, size) {
|
|
|
- (String::LODS, 8) => {
|
|
|
+ match &ins {
|
|
|
+ String::LODS => {
|
|
|
if ctx.cpu.asize_32() {
|
|
|
codegen::gen_get_reg32(ctx, regs::ESI);
|
|
|
}
|
|
@@ -4474,12 +4476,24 @@ fn gen_string_ins(ctx: &mut JitContext, ins: String, size: u8, prefix: u8) {
|
|
|
}
|
|
|
jit_add_seg_offset(ctx, regs::DS);
|
|
|
let address_local = ctx.builder.set_new_local();
|
|
|
- codegen::gen_safe_read8(ctx, &address_local);
|
|
|
- ctx.builder.free_local(address_local);
|
|
|
- codegen::gen_set_reg8_unmasked(ctx, regs::AL);
|
|
|
+ if size == 8 {
|
|
|
+ codegen::gen_safe_read8(ctx, &address_local);
|
|
|
+ ctx.builder.free_local(address_local);
|
|
|
+ codegen::gen_set_reg8_unmasked(ctx, regs::AL);
|
|
|
+ }
|
|
|
+ else if size == 16 {
|
|
|
+ codegen::gen_safe_read16(ctx, &address_local);
|
|
|
+ ctx.builder.free_local(address_local);
|
|
|
+ codegen::gen_set_reg16(ctx, regs::AX);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ codegen::gen_safe_read32(ctx, &address_local);
|
|
|
+ ctx.builder.free_local(address_local);
|
|
|
+ codegen::gen_set_reg32(ctx, regs::EAX);
|
|
|
+ }
|
|
|
|
|
|
codegen::gen_get_reg32(ctx, regs::ESI);
|
|
|
- get_direction(ctx);
|
|
|
+ get_direction(ctx, size);
|
|
|
ctx.builder.add_i32();
|
|
|
if ctx.cpu.asize_32() {
|
|
|
codegen::gen_set_reg32(ctx, regs::ESI);
|
|
@@ -4489,7 +4503,7 @@ fn gen_string_ins(ctx: &mut JitContext, ins: String, size: u8, prefix: u8) {
|
|
|
}
|
|
|
return;
|
|
|
},
|
|
|
- (String::SCAS, 8) => {
|
|
|
+ String::SCAS => {
|
|
|
if ctx.cpu.asize_32() {
|
|
|
codegen::gen_get_reg32(ctx, regs::EDI);
|
|
|
}
|
|
@@ -4498,18 +4512,42 @@ fn gen_string_ins(ctx: &mut JitContext, ins: String, size: u8, prefix: u8) {
|
|
|
}
|
|
|
jit_add_seg_offset_no_override(ctx, regs::ES);
|
|
|
let address_local = ctx.builder.set_new_local();
|
|
|
- codegen::gen_safe_read8(ctx, &address_local);
|
|
|
- ctx.builder.free_local(address_local);
|
|
|
- let value = ctx.builder.set_new_local();
|
|
|
- gen_cmp8(
|
|
|
- ctx,
|
|
|
- &ctx.reg(regs::EAX),
|
|
|
- &LocalOrImmediate::WasmLocal(&value),
|
|
|
- );
|
|
|
- ctx.builder.free_local(value);
|
|
|
+ if size == 8 {
|
|
|
+ codegen::gen_safe_read8(ctx, &address_local);
|
|
|
+ ctx.builder.free_local(address_local);
|
|
|
+ let value = ctx.builder.set_new_local();
|
|
|
+ gen_cmp8(
|
|
|
+ ctx,
|
|
|
+ &ctx.reg(regs::EAX),
|
|
|
+ &LocalOrImmediate::WasmLocal(&value),
|
|
|
+ );
|
|
|
+ ctx.builder.free_local(value);
|
|
|
+ }
|
|
|
+ else if size == 16 {
|
|
|
+ codegen::gen_safe_read16(ctx, &address_local);
|
|
|
+ ctx.builder.free_local(address_local);
|
|
|
+ let value = ctx.builder.set_new_local();
|
|
|
+ gen_cmp16(
|
|
|
+ ctx,
|
|
|
+ &ctx.reg(regs::EAX),
|
|
|
+ &LocalOrImmediate::WasmLocal(&value),
|
|
|
+ );
|
|
|
+ ctx.builder.free_local(value);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ codegen::gen_safe_read32(ctx, &address_local);
|
|
|
+ ctx.builder.free_local(address_local);
|
|
|
+ let value = ctx.builder.set_new_local();
|
|
|
+ gen_cmp32(
|
|
|
+ ctx,
|
|
|
+ &ctx.reg(regs::EAX),
|
|
|
+ &LocalOrImmediate::WasmLocal(&value),
|
|
|
+ );
|
|
|
+ ctx.builder.free_local(value);
|
|
|
+ }
|
|
|
|
|
|
codegen::gen_get_reg32(ctx, regs::EDI);
|
|
|
- get_direction(ctx);
|
|
|
+ get_direction(ctx, size);
|
|
|
ctx.builder.add_i32();
|
|
|
if ctx.cpu.asize_32() {
|
|
|
codegen::gen_set_reg32(ctx, regs::EDI);
|