mirror of
https://github.com/FranLMSP/snes.git
synced 2026-10-03 16:05:18 -04:00
JMP instruction
This commit is contained in:
@@ -12,6 +12,13 @@ pub fn absolute(bus: &Bus, pc_addr: u32) -> u32 {
|
||||
((bus.read(pc_addr + 2) as u32) << 8)
|
||||
}
|
||||
|
||||
/// OPCODE (addr)
|
||||
pub fn absolute_indirect(bus: &Bus, pc_addr: u32) -> u32 {
|
||||
let addr = absolute(bus, pc_addr);
|
||||
let dbr = pc_addr & 0xFF0000;
|
||||
dbr | ((bus.read(addr) as u32) << 8) | (bus.read(addr + 1) as u32)
|
||||
}
|
||||
|
||||
/// OPCODE long
|
||||
pub fn absolute_long(bus: &Bus, pc_addr: u32) -> u32 {
|
||||
(bus.read(pc_addr + 1) as u32) |
|
||||
@@ -19,6 +26,14 @@ pub fn absolute_long(bus: &Bus, pc_addr: u32) -> u32 {
|
||||
((bus.read(pc_addr + 3) as u32) << 16)
|
||||
}
|
||||
|
||||
/// OPCODE (addr)
|
||||
pub fn absolute_indirect_long(bus: &Bus, pc_addr: u32) -> u32 {
|
||||
let addr = absolute(bus, pc_addr);
|
||||
((bus.read(addr) as u32) << 16) |
|
||||
((bus.read(addr + 1) as u32) << 8) |
|
||||
(bus.read(addr + 2) as u32)
|
||||
}
|
||||
|
||||
/// OPCODE dp
|
||||
pub fn direct_page(bus: &Bus, pc_addr: u32, direct_page_register: u16) -> u32 {
|
||||
(bus.read(pc_addr + 1) as u32) + direct_page_register as u32
|
||||
@@ -45,6 +60,14 @@ pub fn absolute_indexed(bus: &Bus, pc_addr: u32, xy: u16) -> u32 {
|
||||
absolute(bus, pc_addr) + (xy as u32)
|
||||
}
|
||||
|
||||
/// OPCODE (addr)
|
||||
pub fn absolute_indexed_indirect(bus: &Bus, pc_addr: u32, xy: u16) -> u32 {
|
||||
let addr = absolute_indexed(bus, pc_addr, xy);
|
||||
let dbr = pc_addr & 0xFF0000;
|
||||
dbr | ((bus.read(addr) as u32) << 8) | (bus.read(addr + 1) as u32)
|
||||
}
|
||||
|
||||
|
||||
/// OPCODE long,X
|
||||
/// OPCODE long,Y
|
||||
pub fn absolute_long_indexed(bus: &Bus, pc_addr: u32, xy: u16) -> u32 {
|
||||
@@ -96,11 +119,14 @@ pub enum AddressingMode {
|
||||
Accumulator,
|
||||
Immediate,
|
||||
Absolute,
|
||||
AbsoluteIndirect,
|
||||
AbsoluteIndirectLong,
|
||||
AbsoluteLong,
|
||||
DirectPage,
|
||||
DirectPageIndirect,
|
||||
DirectPageIndirectLong,
|
||||
AbsoluteIndexed(IndexRegister),
|
||||
AbsoluteIndexedIndirect(IndexRegister),
|
||||
AbsoluteLongIndexed(IndexRegister),
|
||||
DirectPageIndexed(IndexRegister),
|
||||
DirectPageIndexedIndirect(IndexRegister),
|
||||
@@ -118,11 +144,14 @@ impl AddressingMode {
|
||||
Self::Accumulator => pc_addr,
|
||||
Self::Immediate => immediate(pc_addr),
|
||||
Self::Absolute => absolute(bus, pc_addr),
|
||||
Self::AbsoluteIndirect => absolute_indirect(bus, pc_addr),
|
||||
Self::AbsoluteIndirectLong => absolute_indirect_long(bus, pc_addr),
|
||||
Self::AbsoluteLong => absolute_long(bus, pc_addr),
|
||||
Self::DirectPage => direct_page(bus, pc_addr, direct_page_register),
|
||||
Self::DirectPageIndirect => direct_page_indirect(bus, pc_addr, direct_page_register),
|
||||
Self::DirectPageIndirectLong => direct_page_indirect_long(bus, pc_addr, direct_page_register),
|
||||
Self::AbsoluteIndexed(idx) => absolute_indexed(bus, pc_addr, if idx == X {x} else {y}),
|
||||
Self::AbsoluteIndexedIndirect(idx) => absolute_indexed_indirect(bus, pc_addr, if idx == X {x} else {y}),
|
||||
Self::AbsoluteLongIndexed(idx) => absolute_long_indexed(bus, pc_addr, if idx == X {x} else {y}),
|
||||
Self::DirectPageIndexed(idx) => direct_page_indexed(bus, pc_addr, direct_page_register, if idx == X {x} else {y}),
|
||||
Self::DirectPageIndexedIndirect(idx) => direct_page_indexed_indirect(bus, pc_addr, direct_page_register, if idx == X {x} else {y}),
|
||||
@@ -180,6 +209,31 @@ mod addressing_modes_tests {
|
||||
assert_eq!(absolute(&bus, pc_addr), 0x7F0201);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_indirect() {
|
||||
let mut bus = Bus::new();
|
||||
let pc_addr = 0x000000;
|
||||
let addr = 0x55;
|
||||
bus.write(pc_addr + 1, addr);
|
||||
bus.write(addr as u32, 0x02);
|
||||
bus.write((addr + 1) as u32, 0x01);
|
||||
assert_eq!(absolute_indirect(&bus, pc_addr), 0x000201);
|
||||
|
||||
let pc_addr = 0x7E0010;
|
||||
let addr = 0x55;
|
||||
bus.write(pc_addr + 1, addr);
|
||||
bus.write(addr as u32, 0x02);
|
||||
bus.write((addr + 1) as u32, 0x01);
|
||||
assert_eq!(absolute_indirect(&bus, pc_addr), 0x7E0201);
|
||||
|
||||
let pc_addr = 0x7E0010;
|
||||
let addr = 0x55;
|
||||
bus.write(pc_addr + 1, addr);
|
||||
bus.write(addr as u32, 0x02);
|
||||
bus.write((addr + 1) as u32, 0x01);
|
||||
assert_eq!(absolute_indirect(&bus, pc_addr), 0x7E0201);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_long() {
|
||||
let mut bus = Bus::new();
|
||||
@@ -197,6 +251,19 @@ mod addressing_modes_tests {
|
||||
assert_eq!(absolute_long(&bus, pc_addr), 0x030201);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_indirect_long() {
|
||||
let mut bus = Bus::new();
|
||||
let pc_addr = 0x000000;
|
||||
let addr = 0x55;
|
||||
bus.write(pc_addr + 1, addr);
|
||||
bus.write(addr as u32, 0x03);
|
||||
bus.write((addr + 1) as u32, 0x02);
|
||||
bus.write((addr + 2) as u32, 0x01);
|
||||
assert_eq!(absolute_indirect_long(&bus, pc_addr), 0x030201);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_direct_page() {
|
||||
let mut bus = Bus::new();
|
||||
@@ -271,6 +338,17 @@ mod addressing_modes_tests {
|
||||
assert_eq!(absolute_indexed(&bus, pc_addr, 0x02), 0x7F0203);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_indexed_indirect() {
|
||||
let mut bus = Bus::new();
|
||||
let pc_addr = 0x000000;
|
||||
let addr = 0x55;
|
||||
bus.write(pc_addr + 1, addr);
|
||||
bus.write(addr as u32, 0x02);
|
||||
bus.write((addr + 1) as u32, 0x01);
|
||||
assert_eq!(absolute_indexed_indirect(&bus, pc_addr, 0), 0x000201);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_absolute_long_indexed() {
|
||||
let mut bus = Bus::new();
|
||||
|
||||
Reference in New Issue
Block a user