emu: remove unsafe from {push,pop}_modrm operations
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user