Skip to content

Commit

Permalink
Implemented fetch and decode for CPU emulator
Browse files Browse the repository at this point in the history
  • Loading branch information
Granddave committed Dec 21, 2023
1 parent f095e10 commit 7a1418b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 16 deletions.
45 changes: 31 additions & 14 deletions src/emulator/cpu.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
ast::{self},
assembler::compiler::opcode::OPCODE_MAPPING,
ast::{ASTAddressingMode, ASTInstructionNode, ASTOperand},
emulator::memory::Bus,
};

Expand Down Expand Up @@ -35,25 +36,41 @@ impl Cpu {
Self::default()
}

fn fetch_and_decode(&mut self, _memory: &mut dyn Bus) -> Option<ast::ASTInstructionNode> {
// let opcode = memory.read(self.pc);
// self.pc += 1;
//
// if let Some(ins) = OPCODE_MAPPING.find_instruction(opcode) {
// return Some(ast::ASTInstructionNode::new(
// ins.mnemonic,
// ins.addr_mode,
// ast::ASTOperand::Immediate(0),
// ));
// }
/// Fetches and decodes the next instruction from memory.
/// Returns the instruction and increments the program counter.
fn fetch_and_decode(&mut self, memory: &mut dyn Bus) -> ASTInstructionNode {
let opcode = memory.read_byte(self.pc);
let ins = OPCODE_MAPPING
.find_instruction(opcode)
.unwrap_or_else(|| panic!("Invalid opcode: '{:#02x}'", opcode));

let operand = match ins.addr_mode {
ASTAddressingMode::Absolute
| ASTAddressingMode::AbsoluteX
| ASTAddressingMode::AbsoluteY
| ASTAddressingMode::Indirect => ASTOperand::Absolute(memory.read_word(self.pc)),
ASTAddressingMode::ZeroPage
| ASTAddressingMode::ZeroPageX
| ASTAddressingMode::ZeroPageY
| ASTAddressingMode::IndirectIndexedX
| ASTAddressingMode::IndirectIndexedY => {
ASTOperand::ZeroPage(memory.read_byte(self.pc))
}
ASTAddressingMode::Relative => ASTOperand::Relative(memory.read_byte(self.pc) as i8),
ASTAddressingMode::Immediate => ASTOperand::Immediate(memory.read_byte(self.pc)),
ASTAddressingMode::Accumulator | ASTAddressingMode::Implied => ASTOperand::Implied,
_ => panic!("Invalid addressing mode: '{:#?}'", ins.addr_mode),
};

None
let instruction = ASTInstructionNode { ins, operand };
self.pc += instruction.size() as u16;
instruction
}

pub fn run(&mut self, _memory: &mut dyn Bus, _cycles: usize) {
todo!();
// while cycles > 0 {
// let instruction = self.fetch_and_decode(memory).expect("Valid opcode");
// let instruction = self.fetch_and_decode(memory)
//
// println!("{:?}", instruction);
// }
Expand Down
13 changes: 11 additions & 2 deletions src/emulator/memory.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub trait Bus {
fn read(&self, address: u16) -> u8;
fn read_byte(&self, address: u16) -> u8;
fn read_word(&self, address: u16) -> u16;
fn write(&mut self, address: u16, data: u8);
}

Expand Down Expand Up @@ -32,10 +33,18 @@ impl Default for Memory {
}

impl Bus for Memory {
fn read(&self, address: u16) -> u8 {
/// Reads a byte from memory.
fn read_byte(&self, address: u16) -> u8 {
self.data[address as usize]
}

/// Reads a 16-bit word from memory.
/// The 16-bit word is stored in little-endian format.
fn read_word(&self, address: u16) -> u16 {
self.data[address as usize] as u16 | ((self.data[(address + 1) as usize] as u16) << 8)
}

/// Writes a byte to memory.
fn write(&mut self, address: u16, data: u8) {
self.data[address as usize] = data;
}
Expand Down

0 comments on commit 7a1418b

Please sign in to comment.