refactor: split into gameboy-rust workspace with core, demos, and desktop crates
Move the emulator into crates/gba-core, the original demo programs into crates/gba-demos, and the minifb frontend into crates/desktop. The binary is now gameboy-rust. Imports change from gba_rust to gba_core/gba_demos; no behavior changes. gba-core has no dependencies. Its integration tests use gba-demos as a development dependency. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a8944d1d5f
commit
f8a0676748
113 changed files with 304 additions and 282 deletions
108
src/cpu/alu.rs
108
src/cpu/alu.rs
|
|
@ -1,108 +0,0 @@
|
|||
use super::Flags;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(super) enum Shift {
|
||||
Lsl,
|
||||
Lsr,
|
||||
Asr,
|
||||
Ror,
|
||||
}
|
||||
|
||||
impl Shift {
|
||||
pub(super) fn decode(bits: u32) -> Self {
|
||||
match bits & 3 {
|
||||
0 => Self::Lsl,
|
||||
1 => Self::Lsr,
|
||||
2 => Self::Asr,
|
||||
_ => Self::Ror,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ARM barrel shifter. Register shifts use only the low eight amount bits.
|
||||
pub(super) fn shift(
|
||||
value: u32,
|
||||
kind: Shift,
|
||||
amount: u32,
|
||||
carry: bool,
|
||||
by_register: bool,
|
||||
) -> (u32, bool) {
|
||||
let mut amount = if by_register { amount & 0xff } else { amount };
|
||||
if amount == 0 {
|
||||
if by_register || matches!(kind, Shift::Lsl) {
|
||||
return (value, carry);
|
||||
}
|
||||
if matches!(kind, Shift::Ror) {
|
||||
return ((u32::from(carry) << 31) | (value >> 1), value & 1 != 0); // RRX
|
||||
}
|
||||
amount = 32; // Immediate LSR/ASR #0 encodes a shift by 32.
|
||||
}
|
||||
match kind {
|
||||
Shift::Lsl => match amount {
|
||||
1..=31 => (value << amount, (value >> (32 - amount)) & 1 != 0),
|
||||
32 => (0, value & 1 != 0),
|
||||
_ => (0, false),
|
||||
},
|
||||
Shift::Lsr => match amount {
|
||||
1..=31 => (value >> amount, (value >> (amount - 1)) & 1 != 0),
|
||||
32 => (0, value >> 31 != 0),
|
||||
_ => (0, false),
|
||||
},
|
||||
Shift::Asr => {
|
||||
let sign = value >> 31 != 0;
|
||||
if amount >= 32 {
|
||||
(if sign { u32::MAX } else { 0 }, sign)
|
||||
} else {
|
||||
(
|
||||
((value as i32) >> amount) as u32,
|
||||
(value >> (amount - 1)) & 1 != 0,
|
||||
)
|
||||
}
|
||||
}
|
||||
Shift::Ror => {
|
||||
let result = value.rotate_right(amount);
|
||||
(result, result >> 31 != 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Addition is also used for subtraction: a - b = a + !b + 1.
|
||||
fn add_with_carry(a: u32, b: u32, carry: bool) -> (u32, bool, bool) {
|
||||
let wide = u64::from(a) + u64::from(b) + u64::from(carry);
|
||||
let result = wide as u32;
|
||||
let overflow = (!(a ^ b) & (a ^ result)) >> 31 != 0;
|
||||
(result, wide > u64::from(u32::MAX), overflow)
|
||||
}
|
||||
|
||||
pub(super) fn execute(
|
||||
opcode: u32,
|
||||
a: u32,
|
||||
b: u32,
|
||||
shifter_carry: bool,
|
||||
previous: Flags,
|
||||
) -> (u32, Flags) {
|
||||
let (result, carry, overflow) = match opcode {
|
||||
0x0 | 0x8 => (a & b, shifter_carry, previous.overflow),
|
||||
0x1 | 0x9 => (a ^ b, shifter_carry, previous.overflow),
|
||||
0x2 | 0xa => add_with_carry(a, !b, true),
|
||||
0x3 => add_with_carry(b, !a, true),
|
||||
0x4 | 0xb => add_with_carry(a, b, false),
|
||||
0x5 => add_with_carry(a, b, previous.carry),
|
||||
0x6 => add_with_carry(a, !b, previous.carry),
|
||||
0x7 => add_with_carry(b, !a, previous.carry),
|
||||
0xc => (a | b, shifter_carry, previous.overflow),
|
||||
0xd => (b, shifter_carry, previous.overflow),
|
||||
0xe => (a & !b, shifter_carry, previous.overflow),
|
||||
0xf => (!b, shifter_carry, previous.overflow),
|
||||
_ => unreachable!("opcode comes from a four-bit instruction field"),
|
||||
};
|
||||
(
|
||||
result,
|
||||
Flags {
|
||||
negative: result >> 31 != 0,
|
||||
zero: result == 0,
|
||||
carry,
|
||||
overflow,
|
||||
},
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue