movs: allow overlapping strings, as long as they don't overlay within a page
This commit is contained in:
parent
3bcd997904
commit
752869dbff
|
@ -151,7 +151,7 @@ unsafe fn string_instruction(
|
||||||
let mut movs_into_svga_lfb = false;
|
let mut movs_into_svga_lfb = false;
|
||||||
let mut movs_reenter_fast_path = false;
|
let mut movs_reenter_fast_path = false;
|
||||||
|
|
||||||
if rep_fast {
|
let count_until_end_of_page = if rep_fast {
|
||||||
match instruction {
|
match instruction {
|
||||||
Instruction::Movs => {
|
Instruction::Movs => {
|
||||||
let (addr, skip) =
|
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 {
|
match instruction {
|
||||||
Instruction::Movs => {
|
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 {
|
let overlap_interferes = if phys_src < phys_dst {
|
||||||
// backward moves may overlap at the front of the destination string
|
// 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 {
|
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);
|
dbg_assert!(count_until_end_of_page > 0);
|
||||||
|
|
||||||
if !skip_dirty_page {
|
if !skip_dirty_page {
|
||||||
|
|
Loading…
Reference in a new issue