Implement Register methods, and stub ADD opcodes
This commit is contained in:
		| @@ -1,10 +1,8 @@ | |||||||
| #[derive(Debug, Copy, Clone)] | #[derive(Debug, Copy, Clone)] | ||||||
| pub struct MemoryBus { | pub struct MemoryBus {} | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl MemoryBus { | impl MemoryBus { | ||||||
|     pub fn read_byte(&self, _address: u16) { |     pub fn read_byte(&self, _address: u16) -> u8 { | ||||||
|         unimplemented!() |         unimplemented!() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										176
									
								
								src/cpu.rs
									
									
									
									
									
								
							
							
						
						
									
										176
									
								
								src/cpu.rs
									
									
									
									
									
								
							| @@ -1,17 +1,88 @@ | |||||||
| use super::bus::MemoryBus; | use super::bus::MemoryBus; | ||||||
| use std::ops::{Index, IndexMut}; |  | ||||||
| use std::convert::From; | use std::convert::From; | ||||||
|  | use std::ops::{Index, IndexMut}; | ||||||
|  |  | ||||||
| #[derive(Debug, Copy, Clone)] | #[derive(Debug, Copy, Clone)] | ||||||
| pub struct LR35902 { | pub struct LR35902 { | ||||||
|     bus: MemoryBus, |     bus: MemoryBus, | ||||||
|     registers: Registers, |     registers: Registers, | ||||||
|     sp: u16, // Stack Pointer |     sp: u16,   // Stack Pointer | ||||||
|     pc: u16, // Program Counter |     pc: u16,   // Program Counter | ||||||
|     flag: Flag, // Flag Register |  | ||||||
|     ime: bool, // Interrupt Master Enable Flag |     ime: bool, // Interrupt Master Enable Flag | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl LR35902 { | ||||||
|  |     pub fn fetch() -> u8 { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn decode(opcode: u8) -> Instruction { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn execute(&mut self, instruction: Instruction) { | ||||||
|  |         match instruction { | ||||||
|  |             Instruction::Add(target, source) => { | ||||||
|  |                 match target { | ||||||
|  |                     Argument::Register(reg) => { | ||||||
|  |                         let right = match source { | ||||||
|  |                             Argument::Register(other) => self.registers[other], // ADD A, r | ||||||
|  |                             Argument::ImmediateByte(byte) => byte,              // ADD A, n | ||||||
|  |                             Argument::IndirectRegisterPair(pair) => { | ||||||
|  |                                 // ADD A, (HL) | ||||||
|  |                                 self.bus.read_byte(self.register_pair(pair)) | ||||||
|  |                             } | ||||||
|  |                             _ => unreachable!(), | ||||||
|  |                         }; | ||||||
|  |  | ||||||
|  |                         self.registers[reg] = self.add(self.registers[reg], right); | ||||||
|  |                     } | ||||||
|  |                     Argument::RegisterPair(pair) => { | ||||||
|  |                         let left = self.register_pair(pair); | ||||||
|  |  | ||||||
|  |                         if let Argument::RegisterPair(other) = source { | ||||||
|  |                             // ADD HL, rr | ||||||
|  |                             let sum = self.add_u16(left, self.register_pair(other)); | ||||||
|  |                             self.set_register_pair(pair, sum); | ||||||
|  |                         } else if let Argument::ImmediateByte(byte) = source { | ||||||
|  |                             // ADD SP, dd | ||||||
|  |                             let byte = byte as i8; | ||||||
|  |                             let sum = self.add_u16_i8(left, byte); | ||||||
|  |                             self.set_register_pair(pair, sum); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     _ => unreachable!(), | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             _ => unimplemented!("Unhandled Instruction {:?}", instruction), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn add_u16_i8(&mut self, left: u16, right: i8) -> u16 { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn add_u16(&mut self, left: u16, right: u16) -> u16 { | ||||||
|  |         unimplemented!() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn add(&mut self, left: u8, right: u8) -> u8 { | ||||||
|  |         // Info on the Half-Carry flag | ||||||
|  |         // https://robdor.com/2016/08/10/gameboy-emulator-half-carry-flag/ | ||||||
|  |  | ||||||
|  |         let (res, did_overflow) = left.overflowing_add(right); | ||||||
|  |         self.registers.f = Flag { | ||||||
|  |             z: res == 0, | ||||||
|  |             n: false, | ||||||
|  |             h: (((left & 0x0F) + (right & 0x0F)) & 0x10) == 0x10, | ||||||
|  |             c: did_overflow, | ||||||
|  |         } | ||||||
|  |         .into(); | ||||||
|  |  | ||||||
|  |         res | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| #[derive(Debug, Copy, Clone)] | #[derive(Debug, Copy, Clone)] | ||||||
| pub struct Flag { | pub struct Flag { | ||||||
|     z: bool, // Zero Flag |     z: bool, // Zero Flag | ||||||
| @@ -29,7 +100,6 @@ impl From<u8> for Flag { | |||||||
|             c: ((num >> 4) & 0x01) == 1, |             c: ((num >> 4) & 0x01) == 1, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| impl From<Flag> for u8 { | impl From<Flag> for u8 { | ||||||
| @@ -47,21 +117,23 @@ pub struct Registers { | |||||||
|     e: u8, |     e: u8, | ||||||
|     h: u8, |     h: u8, | ||||||
|     l: u8, |     l: u8, | ||||||
|  |     f: u8, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Index<Register> for Registers { | impl Index<Register> for Registers { | ||||||
|     type Output = u8; |     type Output = u8; | ||||||
|  |  | ||||||
|     fn index(&self, index: Register) -> &Self::Output { |     fn index(&self, index: Register) -> &Self::Output { | ||||||
|        match index { |         match index { | ||||||
|            Register::A => &self.a, |             Register::A => &self.a, | ||||||
|            Register::B => &self.b, |             Register::B => &self.b, | ||||||
|            Register::C => &self.c, |             Register::C => &self.c, | ||||||
|            Register::D => &self.d, |             Register::D => &self.d, | ||||||
|            Register::E => &self.e, |             Register::E => &self.e, | ||||||
|            Register::H => &self.h, |             Register::H => &self.h, | ||||||
|            Register::L => &self.l, |             Register::L => &self.l, | ||||||
|        } |             Register::F => &self.f, | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -75,6 +147,7 @@ impl IndexMut<Register> for Registers { | |||||||
|             Register::E => &mut self.e, |             Register::E => &mut self.e, | ||||||
|             Register::H => &mut self.h, |             Register::H => &mut self.h, | ||||||
|             Register::L => &mut self.l, |             Register::L => &mut self.l, | ||||||
|  |             Register::F => &mut self.f, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -88,4 +161,79 @@ pub enum Register { | |||||||
|     E, |     E, | ||||||
|     H, |     H, | ||||||
|     L, |     L, | ||||||
|  |     F, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Copy, Clone)] | ||||||
|  | pub enum RegisterPair { | ||||||
|  |     AF, | ||||||
|  |     BC, | ||||||
|  |     DE, | ||||||
|  |     HL, | ||||||
|  |     SP, | ||||||
|  |     PC, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl LR35902 { | ||||||
|  |     pub fn register_pair(&self, pair: RegisterPair) -> u16 { | ||||||
|  |         match pair { | ||||||
|  |             RegisterPair::AF => { | ||||||
|  |                 (self.registers[Register::A] as u16) << 8 | self.registers[Register::F] as u16 | ||||||
|  |             } | ||||||
|  |             RegisterPair::BC => { | ||||||
|  |                 (self.registers[Register::B] as u16) << 8 | self.registers[Register::C] as u16 | ||||||
|  |             } | ||||||
|  |             RegisterPair::DE => { | ||||||
|  |                 (self.registers[Register::D] as u16) << 8 | self.registers[Register::E] as u16 | ||||||
|  |             } | ||||||
|  |             RegisterPair::HL => { | ||||||
|  |                 (self.registers[Register::H] as u16) << 8 | self.registers[Register::L] as u16 | ||||||
|  |             } | ||||||
|  |             RegisterPair::SP => self.sp, | ||||||
|  |             RegisterPair::PC => self.pc, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn set_register_pair(&mut self, pair: RegisterPair, value: u16) { | ||||||
|  |         let high = (value >> 8) as u8; | ||||||
|  |         let low = value as u8; | ||||||
|  |         match pair { | ||||||
|  |             RegisterPair::AF => { | ||||||
|  |                 self.registers[Register::A] = high; | ||||||
|  |                 self.registers[Register::F] = low; | ||||||
|  |             } | ||||||
|  |             RegisterPair::BC => { | ||||||
|  |                 self.registers[Register::B] = high; | ||||||
|  |                 self.registers[Register::C] = low; | ||||||
|  |             } | ||||||
|  |             RegisterPair::DE => { | ||||||
|  |                 self.registers[Register::D] = high; | ||||||
|  |                 self.registers[Register::E] = low; | ||||||
|  |             } | ||||||
|  |             RegisterPair::HL => { | ||||||
|  |                 self.registers[Register::H] = high; | ||||||
|  |                 self.registers[Register::L] = low; | ||||||
|  |             } | ||||||
|  |             RegisterPair::SP => self.sp = value, | ||||||
|  |             RegisterPair::PC => self.pc = value, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Copy, Clone)] | ||||||
|  | enum Argument { | ||||||
|  |     Register(Register), | ||||||
|  |     RegisterPair(RegisterPair), | ||||||
|  |     IndirectRegisterPair(RegisterPair), | ||||||
|  |     ImmediateByte(u8), | ||||||
|  |     ImmediateWord(u16), | ||||||
|  |     IndirectImmediateByte(u16), | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Copy, Clone)] | ||||||
|  | enum Instruction { | ||||||
|  |     Add(Argument, Argument), | ||||||
|  |     NOP, | ||||||
|  |     STOP, | ||||||
|  |     HALT, | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user