movs: allow overlapping strings, as long as they don't overlay within a page

This commit is contained in:
Fabian 2022-11-18 14:48:15 -06:00
parent 3bcd997904
commit 752869dbff

View file

@ -151,7 +151,7 @@ unsafe fn string_instruction(
let mut movs_into_svga_lfb = false;
let mut movs_reenter_fast_path = false;
if rep_fast {
let count_until_end_of_page = if rep_fast {
match instruction {
Instruction::Movs => {
let (addr, skip) =
@ -186,9 +186,25 @@ unsafe fn string_instruction(
_ => {},
};
let count_until_end_of_page = u32::min(
count,
match instruction {
Instruction::Movs | Instruction::Cmps => u32::min(
count_until_end_of_page(direction, size_bytes, phys_src),
count_until_end_of_page(direction, size_bytes, phys_dst),
),
Instruction::Stos | Instruction::Ins | Instruction::Scas => {
count_until_end_of_page(direction, size_bytes, phys_dst)
},
Instruction::Lods | Instruction::Outs => {
count_until_end_of_page(direction, size_bytes, phys_src)
},
},
);
match instruction {
Instruction::Movs => {
let c = count * size_bytes as u32;
let c = count_until_end_of_page * size_bytes as u32;
let overlap_interferes = if phys_src < phys_dst {
// backward moves may overlap at the front of the destination string
@ -212,24 +228,14 @@ unsafe fn string_instruction(
},
_ => {},
}
count_until_end_of_page
}
else {
0 // not used
};
if rep_fast {
let count_until_end_of_page = u32::min(
count,
match instruction {
Instruction::Movs | Instruction::Cmps => u32::min(
count_until_end_of_page(direction, size_bytes, phys_src),
count_until_end_of_page(direction, size_bytes, phys_dst),
),
Instruction::Stos | Instruction::Ins | Instruction::Scas => {
count_until_end_of_page(direction, size_bytes, phys_dst)
},
Instruction::Lods | Instruction::Outs => {
count_until_end_of_page(direction, size_bytes, phys_src)
},
},
);
dbg_assert!(count_until_end_of_page > 0);
if !skip_dirty_page {