emu: remove unsafe from {push,pop}_modrm operations

This commit is contained in:
2021-03-29 00:20:42 -07:00
parent 7c7f74a65b
commit 40fed58ecf
3 changed files with 61 additions and 86 deletions

View File

@@ -85,6 +85,28 @@ macro_rules! step {
step!(@code form=$form, $done, $cpu, $bus, $prefix, $modrm, $name, $cycles, $rest)
};
// Adds tokens to the last argument. Used by @convert to append ".into()" to the last arg
(@append-to-last ($($done:tt)*)
( $(form=$form:tt,)? ($last:tt),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
$rest:tt ) { $($conv:tt)+ } ) => {
step!(@code $(form=$form,)? ($($done)* ($last$($conv)+)),
$cpu, $bus, $prefix, $modrm, $name, $cycles,
$rest )
};
// Recursive case for @append-to-last, walks through already
// processed args to find the last one for appending
(@append-to-last ($($done:tt)*)
( $(form=$form:tt,)? ($next:tt $($restdone:tt)+),
$cpu:expr, $bus:expr, $prefix:tt, $modrm:tt, $name:ident, $cycles:literal,
$rest:tt ) { $($conv:tt)+ } ) => {
step!(@append-to-last ($($done)* $next)
( $(form=$form,)? ($($restdone)+),
$cpu, $bus, $prefix, $modrm, $name, $cycles,
$rest ) { $($conv)+ } )
};
// === OP DIRECTIVES ===
(@addr $cookie:tt, $cpu:expr, $bus:expr,
@@ -98,49 +120,15 @@ macro_rules! step {
step!(@arg $cookie, $bus)
};
// Horrible, Ugly, No Good Hack.
//
// Enqueue a mutable reference to the bus without telling the borrow
// checker, iff the ModR/M byte selects for a register operand. See
// comments on push_modrm/pop_modrm in the operations module.
//
// Safety: Yolo! (Iolo?)
//
// Well, maybe. The reason we can't just enqueue the bus directly is
// because the borrowck can't know statically that the cases where
// we take the bus here (ModR/M within 0xC0..=0xC7) are also the
// cases where there won't be a FarPtr operand taking a conflicting
// bus ref.
//
// It is up to the caller to make sure that there isn't actually
// another reference to the bus, as that would violate aliasing
// rules. Of course, there IS another bus reference, the one we're
// copying from! So we can't touch that at all for the lifetime of
// the reference we're creating here, either.
//
// Is this enough to be safe? Who knows! Rust hasn't yet actually
// defined its aliasing rules or UB and doesn't seem to be in any
// hurry to. LLVM talks in terms of "memory access done through a
// pointer" which as long as we're not doing anything with the
// original pointer while the other one exists sort of suggests that
// this should be okay but also doesn't really sound like a
// guarantee.
(@unsafe_bus_maybe $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt,
($modrm_val:ident, $modrm:tt, $modrm16:tt, $modrm8:tt)) => {
step!(@arg $cookie,
if (0xC0..=0xC7).contains(&$modrm_val) {
// Sneak a mutable reference past the borrow checker.
unsafe { ($bus as *mut Bus).as_mut() }
} else {
None
}
)
};
(@const=$val:literal $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@arg $cookie, $val)
};
// Adds ".into()" onto the last argument
(@convert $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@append-to-last () $cookie { .into() } )
};
(@cpu $cookie:tt, $cpu:expr, $bus:expr, $prefix:tt, $modrm:tt) => {
step!(@arg $cookie, $cpu)
};
@@ -498,7 +486,7 @@ impl i8088 {
0x08 => mov[reg=cs, modrm16] / "2/12+",
0x10 => mov[reg=ss, modrm16] / "2/12+",
0x18 => mov[reg=ds, modrm16] / "2/12+", },
0x8F: { 0x00 => pop_modrm[unsafe_bus_maybe, regval=ss, reg=sp, modrm16] / "12/25+" }, // POP r/m16
0x8F: { 0x00 => pop_modrm[regval=ss, reg=sp, modrm16, convert, bus] / "12/25+" }, // POP r/m16
0x90 => nop[] / 3,
0xA0 => mov[reglo=a, addr] / 14,
0xA1 => mov[reg=a, addr] / 14,
@@ -554,7 +542,7 @@ impl i8088 {
0x08 => dec[form=unary_byte, flags, modrm8] / "3/23+", }, // DEC r/m8
0xFF: { 0x00 => inc[form=unary_word, flags, modrm16] / "3/23+", // INC r/m16
0x08 => dec[form=unary_word, flags, modrm16] / "3/23+", // DEC r/m16
0x30 => push_modrm[unsafe_bus_maybe, regval=ss, reg=sp, modrm16] / "15/24+" },
0x30 => push_modrm[regval=ss, reg=sp, modrm16, convert, bus] / "15/24+" },
},
modrm: {
0x00 => seg=ds, displace0=(b+si) / M 7,