Browse Source

movs: fast copy into svga lfb

Fabian 1 year ago
parent
commit
685c39177f
2 changed files with 38 additions and 9 deletions
  1. 10 0
      src/rust/cpu/memory.rs
  2. 28 9
      src/rust/cpu/string.rs

+ 10 - 0
src/rust/cpu/memory.rs

@@ -236,6 +236,16 @@ pub unsafe fn memcpy_no_mmap_or_dirty_check(src_addr: u32, dst_addr: u32, count:
     )
 }
 
+pub unsafe fn memcpy_into_svga_lfb(src_addr: u32, dst_addr: u32, count: u32) {
+    dbg_assert!(src_addr < *memory_size);
+    dbg_assert!(in_svga_lfb(dst_addr));
+    ptr::copy_nonoverlapping(
+        mem8.offset(src_addr as isize),
+        vga_mem8.offset((dst_addr - VGA_LFB_ADDRESS) as isize),
+        count as usize,
+    )
+}
+
 pub unsafe fn mmap_write8(addr: u32, value: i32) {
     if in_svga_lfb(addr) {
         vga::mark_dirty(addr);

+ 28 - 9
src/rust/cpu/string.rs

@@ -19,9 +19,9 @@ use cpu::cpu::{
 };
 use cpu::global_pointers::{flags, instruction_pointer, previous_ip};
 use cpu::memory::{
-    in_mapped_range, memcpy_no_mmap_or_dirty_check, memset_no_mmap_or_dirty_check,
-    read8_no_mmap_check, read16_no_mmap_check, read32_no_mmap_check, write8_no_mmap_or_dirty_check,
-    write16_no_mmap_or_dirty_check, write32_no_mmap_or_dirty_check,
+    in_mapped_range, in_svga_lfb, memcpy_into_svga_lfb, memcpy_no_mmap_or_dirty_check,
+    memset_no_mmap_or_dirty_check, read8_no_mmap_check, read16_no_mmap_check, read32_no_mmap_check,
+    write8_no_mmap_or_dirty_check, write16_no_mmap_or_dirty_check, write32_no_mmap_or_dirty_check,
 };
 use page::Page;
 
@@ -145,10 +145,19 @@ unsafe fn string_instruction(
     let mut phys_dst = 0;
     let mut phys_src = 0;
     let mut skip_dirty_page = false;
+    let mut movs_into_svga_lfb = false;
 
     if rep_fast {
         match instruction {
-            Instruction::Movs | Instruction::Stos | Instruction::Ins => {
+            Instruction::Movs => {
+                let (addr, skip) =
+                    return_on_pagefault!(translate_address_write_and_can_skip_dirty(es + dst));
+                movs_into_svga_lfb = in_svga_lfb(addr);
+                rep_fast = rep_fast && (!in_mapped_range(addr) || movs_into_svga_lfb);
+                phys_dst = addr;
+                skip_dirty_page = skip;
+            },
+            Instruction::Stos | Instruction::Ins => {
                 let (addr, skip) =
                     return_on_pagefault!(translate_address_write_and_can_skip_dirty(es + dst));
                 rep_fast = rep_fast && !in_mapped_range(addr);
@@ -256,11 +265,21 @@ unsafe fn string_instruction(
                         phys_src -= (count_until_end_of_page - 1) * size_bytes as u32;
                         phys_dst -= (count_until_end_of_page - 1) * size_bytes as u32;
                     }
-                    memcpy_no_mmap_or_dirty_check(
-                        phys_src,
-                        phys_dst,
-                        count_until_end_of_page * size_bytes as u32,
-                    );
+                    if movs_into_svga_lfb {
+                        ::cpu::vga::mark_dirty(phys_dst);
+                        memcpy_into_svga_lfb(
+                            phys_src,
+                            phys_dst,
+                            count_until_end_of_page * size_bytes as u32,
+                        );
+                    }
+                    else {
+                        memcpy_no_mmap_or_dirty_check(
+                            phys_src,
+                            phys_dst,
+                            count_until_end_of_page * size_bytes as u32,
+                        );
+                    }
                     i = count_until_end_of_page;
                     break;
                 },