fix(cpu): review fixes — stswi/stswx two-line guard, dcbz/dcbz128 invalidate
PPCBUG-160 partial: stswi's single invalidate_for_write(ea) only covered the first cache line; with nb up to 32, the write span can cross a 128-byte line boundary. Replace with two-call guard: first_line = ea & !RESERVATION_MASK last_line = ea.wrapping_add(nb - 1) & !RESERVATION_MASK invalidate first; if last != first, invalidate last. PPCBUG-160 partial: stswx had the same single-call gap; nb from XER[0:6] can be up to 127 bytes. Same two-call guard applied; wrapped in `if nb > 0` to guard against nb==0 underflow (XER TBC field is 0 when no bytes to store). dcbz: zeroes 32 bytes at a 32-byte-aligned EA — touches exactly one 128-byte cache line; add canonical single-call invalidate guard (was entirely missing). dcbz128: zeroes 128 bytes at a 128-byte-aligned EA — one full reservation line; add canonical single-call invalidate guard (was entirely missing). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1464,7 +1464,12 @@ fn execute(ctx: &mut PpcContext, mem: &dyn MemoryAccess, instr: &DecodedInstr) -
|
|||||||
let mut rs = instr.rs();
|
let mut rs = instr.rs();
|
||||||
let mut bytes_left = nb;
|
let mut bytes_left = nb;
|
||||||
if let Some(t) = ctx.reservation_table.as_ref().filter(|t| t.is_enabled()) {
|
if let Some(t) = ctx.reservation_table.as_ref().filter(|t| t.is_enabled()) {
|
||||||
if t.has_active_reservers() { t.invalidate_for_write(ea); }
|
if t.has_active_reservers() {
|
||||||
|
let first_line = ea & !RESERVATION_MASK;
|
||||||
|
let last_line = ea.wrapping_add(nb - 1) & !RESERVATION_MASK;
|
||||||
|
t.invalidate_for_write(first_line);
|
||||||
|
if last_line != first_line { t.invalidate_for_write(last_line); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while bytes_left > 0 {
|
while bytes_left > 0 {
|
||||||
let val = ctx.gpr[rs] as u32;
|
let val = ctx.gpr[rs] as u32;
|
||||||
@@ -1600,6 +1605,9 @@ fn execute(ctx: &mut PpcContext, mem: &dyn MemoryAccess, instr: &DecodedInstr) -
|
|||||||
// Zero 32 bytes at effective address
|
// Zero 32 bytes at effective address
|
||||||
let ea = if instr.ra() == 0 { 0u64 } else { ctx.gpr[instr.ra()] };
|
let ea = if instr.ra() == 0 { 0u64 } else { ctx.gpr[instr.ra()] };
|
||||||
let ea = (ea.wrapping_add(ctx.gpr[instr.rb()]) as u32) & !31;
|
let ea = (ea.wrapping_add(ctx.gpr[instr.rb()]) as u32) & !31;
|
||||||
|
if let Some(t) = ctx.reservation_table.as_ref().filter(|t| t.is_enabled()) {
|
||||||
|
if t.has_active_reservers() { t.invalidate_for_write(ea); }
|
||||||
|
}
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
mem.write_u32(ea + i * 4, 0);
|
mem.write_u32(ea + i * 4, 0);
|
||||||
}
|
}
|
||||||
@@ -1609,6 +1617,9 @@ fn execute(ctx: &mut PpcContext, mem: &dyn MemoryAccess, instr: &DecodedInstr) -
|
|||||||
// Zero 128 bytes
|
// Zero 128 bytes
|
||||||
let ea = if instr.ra() == 0 { 0u64 } else { ctx.gpr[instr.ra()] };
|
let ea = if instr.ra() == 0 { 0u64 } else { ctx.gpr[instr.ra()] };
|
||||||
let ea = (ea.wrapping_add(ctx.gpr[instr.rb()]) as u32) & !127;
|
let ea = (ea.wrapping_add(ctx.gpr[instr.rb()]) as u32) & !127;
|
||||||
|
if let Some(t) = ctx.reservation_table.as_ref().filter(|t| t.is_enabled()) {
|
||||||
|
if t.has_active_reservers() { t.invalidate_for_write(ea); }
|
||||||
|
}
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
mem.write_u32(ea + i * 4, 0);
|
mem.write_u32(ea + i * 4, 0);
|
||||||
}
|
}
|
||||||
@@ -4418,8 +4429,15 @@ fn execute(ctx: &mut PpcContext, mem: &dyn MemoryAccess, instr: &DecodedInstr) -
|
|||||||
let nb = ctx.xer() & 0x7F;
|
let nb = ctx.xer() & 0x7F;
|
||||||
let mut rs = instr.rs();
|
let mut rs = instr.rs();
|
||||||
let mut bytes_left = nb;
|
let mut bytes_left = nb;
|
||||||
if let Some(t) = ctx.reservation_table.as_ref().filter(|t| t.is_enabled()) {
|
if nb > 0 {
|
||||||
if t.has_active_reservers() { t.invalidate_for_write(ea); }
|
if let Some(t) = ctx.reservation_table.as_ref().filter(|t| t.is_enabled()) {
|
||||||
|
if t.has_active_reservers() {
|
||||||
|
let first_line = ea & !RESERVATION_MASK;
|
||||||
|
let last_line = ea.wrapping_add(nb - 1) & !RESERVATION_MASK;
|
||||||
|
t.invalidate_for_write(first_line);
|
||||||
|
if last_line != first_line { t.invalidate_for_write(last_line); }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while bytes_left > 0 {
|
while bytes_left > 0 {
|
||||||
let val = ctx.gpr[rs] as u32;
|
let val = ctx.gpr[rs] as u32;
|
||||||
|
|||||||
Reference in New Issue
Block a user