Fabian 3 лет назад
Родитель
Сommit
4de8584cff
3 измененных файлов с 60 добавлено и 26 удалено
  1. 2 2
      gen/x86_table.js
  2. 0 4
      src/rust/cpu/string.rs
  3. 58 20
      src/rust/jit_instructions.rs

+ 2 - 2
gen/x86_table.js

@@ -242,14 +242,14 @@ const encodings = [
     { opcode: 0xAC, block_boundary: 0, custom: 1, is_string: 1, },
     { opcode: 0xF2AC, block_boundary: 1, custom: 1, is_string: 1, },
     { opcode: 0xF3AC, block_boundary: 1, custom: 1, is_string: 1, },
-    { opcode: 0xAD, block_boundary: 1, custom: 1, is_string: 1, os: 1, },
+    { opcode: 0xAD, block_boundary: 0, custom: 1, is_string: 1, os: 1, },
     { opcode: 0xF2AD, block_boundary: 1, custom: 1, is_string: 1, os: 1, },
     { opcode: 0xF3AD, block_boundary: 1, custom: 1, is_string: 1, os: 1, },
 
     { opcode: 0xAE, block_boundary: 0, custom: 1, is_string: 1, },
     { opcode: 0xF2AE, block_boundary: 1, custom: 1, is_string: 1, },
     { opcode: 0xF3AE, block_boundary: 1, custom: 1, is_string: 1, },
-    { opcode: 0xAF, block_boundary: 1, custom: 1, is_string: 1, os: 1, },
+    { opcode: 0xAF, block_boundary: 0, custom: 1, is_string: 1, os: 1, },
     { opcode: 0xF2AF, block_boundary: 1, custom: 1, is_string: 1, os: 1, },
     { opcode: 0xF3AF, block_boundary: 1, custom: 1, is_string: 1, os: 1, },
 

+ 0 - 4
src/rust/cpu/string.rs

@@ -498,11 +498,9 @@ pub unsafe fn lodsd_rep(is_asize_32: bool, ds: i32) {
 pub unsafe fn lodsb_no_rep(is_asize_32: bool, ds: i32) {
     string_instruction(is_asize_32, ds, Instruction::Lods, Size::B, Rep::None)
 }
-#[no_mangle]
 pub unsafe fn lodsw_no_rep(is_asize_32: bool, ds: i32) {
     string_instruction(is_asize_32, ds, Instruction::Lods, Size::W, Rep::None)
 }
-#[no_mangle]
 pub unsafe fn lodsd_no_rep(is_asize_32: bool, ds: i32) {
     string_instruction(is_asize_32, ds, Instruction::Lods, Size::D, Rep::None)
 }
@@ -596,11 +594,9 @@ pub unsafe fn scasd_repnz(is_asize_32: bool) {
 pub unsafe fn scasb_no_rep(is_asize_32: bool) {
     string_instruction(is_asize_32, 0, Instruction::Scas, Size::B, Rep::None)
 }
-#[no_mangle]
 pub unsafe fn scasw_no_rep(is_asize_32: bool) {
     string_instruction(is_asize_32, 0, Instruction::Scas, Size::W, Rep::None)
 }
-#[no_mangle]
 pub unsafe fn scasd_no_rep(is_asize_32: bool) {
     string_instruction(is_asize_32, 0, Instruction::Scas, Size::D, Rep::None)
 }

+ 58 - 20
src/rust/jit_instructions.rs

@@ -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);