diff --git a/src/cpus/m68k/decode.rs b/src/cpus/m68k/decode.rs index e339341..8ddcc46 100644 --- a/src/cpus/m68k/decode.rs +++ b/src/cpus/m68k/decode.rs @@ -61,7 +61,7 @@ pub enum Condition { LessThanOrEqual, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub enum Target { Immediate(u32), DirectDReg(u8), @@ -180,14 +180,14 @@ const OPCG_RESERVED2: u8 = 0xF; impl MC68010 { fn read_instruction_word(&mut self, space: &mut AddressSpace) -> Result { let word = space.read_beu16(self.pc as Address)?; - println!("{:08x} {:04x?}", self.pc, word); + //debug!("{:#010x} {:#06x?}", self.pc, word); self.pc += 2; Ok(word) } fn read_instruction_long(&mut self, space: &mut AddressSpace) -> Result { let word = space.read_beu32(self.pc as Address)?; - println!("{:08x} {:08x?}", self.pc, word); + //debug!("{:#010x} {:#010x}", self.pc, word); self.pc += 4; Ok(word) } @@ -419,7 +419,7 @@ impl MC68010 { } }, OPCG_BRANCH => { - let mut disp = ins & 0xFF; + let mut disp = ((ins & 0xFF) as i8) as u16; if disp == 0 { disp = self.read_instruction_word(space)?; } diff --git a/src/cpus/m68k/execute.rs b/src/cpus/m68k/execute.rs index 090ab9b..385ff82 100644 --- a/src/cpus/m68k/execute.rs +++ b/src/cpus/m68k/execute.rs @@ -2,7 +2,7 @@ use crate::error::Error; use crate::memory::{Address, AddressSpace}; -use super::decode::{Instruction, Target, Size, Direction, ControlRegister, RegisterType}; +use super::decode::{Instruction, Target, Size, Direction, Condition, ControlRegister, RegisterType}; pub trait Processor { fn reset(); @@ -33,6 +33,10 @@ pub struct MC68010 { const FLAGS_ON_RESET: u16 = 0x2700; +pub const FLAGS_CARRY: u16 = 0x0001; +pub const FLAGS_OVERFLOW: u16 = 0x0002; +pub const FLAGS_ZERO: u16 = 0x0004; +pub const FLAGS_NEGATIVE: u16 = 0x0008; pub const FLAGS_SUPERVISOR: u16 = 0x2000; pub const ERR_BUS_ERROR: u32 = 2; @@ -71,7 +75,6 @@ impl MC68010 { self.state != State::Halted } - pub fn init(&mut self, space: &mut AddressSpace) -> Result<(), Error> { println!("Initializing CPU"); @@ -90,40 +93,92 @@ impl MC68010 { } } + pub fn dump_state(&self) { + println!("State: {:?}", self.state); + println!("PC: {:#010x}", self.pc); + println!("SR: {:#06x}", self.sr); + for i in 0..7 { + println!("D{}: {:#010x} A{}: {:#010x}", i, self.d_reg[i as usize], i, self.a_reg[i as usize]); + } + println!("D7: {:#010x}", self.d_reg[7]); + println!("MSP: {:#010x}", self.msp); + println!("USP: {:#010x}", self.usp); + } + fn is_supervisor(&self) -> bool { self.sr & FLAGS_SUPERVISOR != 0 } fn push_long(&mut self, space: &mut AddressSpace, value: u32) -> Result<(), Error> { - let reg = if self.is_supervisor() { &mut self.msp } else { &mut self.usp }; + let reg = self.get_stack_pointer_mut(); *reg -= 4; + //println!("PUSHING {:08x} at {:08x}", value, *reg); space.write_beu32(*reg as Address, value) } + fn pop_long(&mut self, space: &mut AddressSpace) -> Result { + let reg = self.get_stack_pointer_mut(); + let value = space.read_beu32(*reg as Address)?; + //println!("POPPING {:08x} at {:08x}", value, *reg); + *reg += 4; + Ok(value) + } + fn execute_one(&mut self, space: &mut AddressSpace) -> Result<(), Error> { - let addr = self.pc; + let current_ins_addr = self.pc; let ins = self.decode_one(space)?; - println!("{:08x}: {:?}", addr, ins); + // Print instruction bytes for debugging + let ins_data: Result = + (0..((self.pc - current_ins_addr) / 2)).map(|offset| + Ok(format!("{:04x} ", space.read_beu16((current_ins_addr + (offset * 2)) as Address)?)) + ).collect(); + debug!("{:#010x}: {}\n\t{:?}\n", current_ins_addr, ins_data?, ins); + match ins { - //Instruction::ADD(Target, Target, Size) => { - //}, - //Instruction::AND(Target, Target, Size) => { - //}, - //Instruction::ANDtoCCR(u8) => { - //}, - //Instruction::ANDtoSR(u16) => { - //}, + Instruction::ADD(src, dest, size) => { + let value = self.get_target_value(space, src, size)?; + let existing = self.get_target_value(space, dest, size)?; + let (result, overflow) = match size { + Size::Byte => { + let (result, overflow) = (existing as u8).overflowing_add(value as u8); + (result as u32, overflow) + }, + Size::Word => { + let (result, overflow) = (existing as u16).overflowing_add(value as u16); + (result as u32, overflow) + }, + Size::Long => existing.overflowing_add(value), + }; + self.set_compare_flags(result as i32, overflow); + self.set_target_value(space, dest, result, size)?; + }, + Instruction::AND(src, dest, size) => { + let value = self.get_target_value(space, src, size)?; + let existing = self.get_target_value(space, dest, size)?; + self.set_target_value(space, dest, existing & value, size)?; + self.set_logic_flags(value, size); + }, + Instruction::ANDtoCCR(value) => { + self.sr = self.sr | value as u16; + }, + Instruction::ANDtoSR(value) => { + self.sr = self.sr | value; + }, //Instruction::ASd(Target, Target, Size, ShiftDirection) => { //}, - //Instruction::Bcc(Condition, u16) => { - //}, + Instruction::Bcc(cond, offset) => { + let should_branch = self.get_current_condition(cond); + if should_branch { + self.pc = current_ins_addr.wrapping_add(offset as u32) + 2; + } + }, Instruction::BRA(offset) => { - self.pc = self.pc.wrapping_add(offset as u32) - 2; + self.pc = current_ins_addr.wrapping_add(offset as u32) + 2; }, Instruction::BSR(offset) => { self.push_long(space, self.pc)?; - self.pc = self.pc.wrapping_add(offset as u32) - 2; + self.pc = current_ins_addr.wrapping_add(offset as u32) + 2; }, //Instruction::BTST(Target, Target, Size) => { //}, @@ -155,15 +210,15 @@ impl MC68010 { //Instruction::ILLEGAL => { //}, Instruction::JMP(target) => { - self.pc = self.get_target_address(target)?; + self.pc = self.get_target_address(target)? - 2; }, Instruction::JSR(target) => { self.push_long(space, self.pc)?; - self.pc = self.get_target_address(target)?; + self.pc = self.get_target_address(target)? - 2; }, Instruction::LEA(target, reg) => { let value = self.get_target_address(target)?; - let addr = self.get_a_reg(reg); + let addr = self.get_a_reg_mut(reg); *addr = value; }, //Instruction::LINK(u8, u16) => { @@ -211,17 +266,24 @@ impl MC68010 { //Instruction::NEGX(Target, Size) => { //}, Instruction::NOP => { }, - //Instruction::NOT(Target, Size) => { - //}, - //Instruction::OR(Target, Target, Size) => { - //}, - //Instruction::ORtoCCR(u8) => { + //Instruction::NOT(target, size) => { //}, + Instruction::OR(src, dest, size) => { + let value = self.get_target_value(space, src, size)?; + let existing = self.get_target_value(space, dest, size)?; + self.set_target_value(space, dest, existing | value, size)?; + self.set_logic_flags(value, size); + }, + Instruction::ORtoCCR(value) => { + self.sr = self.sr | value as u16; + }, Instruction::ORtoSR(value) => { self.sr = self.sr | value; }, - //Instruction::PEA(Target) => { - //}, + Instruction::PEA(target) => { + let value = self.get_target_address(target)?; + self.push_long(space, value)?; + }, //Instruction::RESET => { //}, //Instruction::ROd(Target, Target, Size, ShiftDirection) => { @@ -232,18 +294,36 @@ impl MC68010 { //}, //Instruction::RTR => { //}, - //Instruction::RTS => { - //}, + Instruction::RTS => { + self.pc = self.pop_long(space)?; + }, //Instruction::STOP(u16) => { //}, - //Instruction::SUB(Target, Target, Size) => { - //}, + Instruction::SUB(src, dest, size) => { + let value = self.get_target_value(space, src, size)?; + let existing = self.get_target_value(space, dest, size)?; + let (result, overflow) = match size { + Size::Byte => { + let (result, overflow) = (existing as u8).overflowing_sub(value as u8); + (result as u32, overflow) + }, + Size::Word => { + let (result, overflow) = (existing as u16).overflowing_sub(value as u16); + (result as u32, overflow) + }, + Size::Long => existing.overflowing_sub(value), + }; + self.set_compare_flags(result as i32, overflow); + self.set_target_value(space, dest, result, size)?; + }, //Instruction::SWAP(u8) => { //}, //Instruction::TAS(Target) => { //}, - //Instruction::TST(Target, Size) => { - //}, + Instruction::TST(target, size) => { + let value = self.get_target_value(space, target, size)?; + self.set_compare_flags(value as i32, false); + }, //Instruction::TRAP(u8) => { //}, //Instruction::TRAPV => { @@ -260,26 +340,26 @@ impl MC68010 { match target { Target::Immediate(value) => Ok(value), Target::DirectDReg(reg) => Ok(get_value_sized(self.d_reg[reg as usize], size)), - Target::DirectAReg(reg) => Ok(get_value_sized(*self.get_a_reg(reg), size)), - Target::IndirectAReg(reg) => get_address_sized(space, *self.get_a_reg(reg) as Address, size), + Target::DirectAReg(reg) => Ok(get_value_sized(*self.get_a_reg_mut(reg), size)), + Target::IndirectAReg(reg) => get_address_sized(space, *self.get_a_reg_mut(reg) as Address, size), Target::IndirectARegInc(reg) => { - let addr = self.get_a_reg(reg); - let value = get_address_sized(space, *addr as Address, size); + let addr = self.get_a_reg_mut(reg); + let result = get_address_sized(space, *addr as Address, size); *addr += size.in_bytes(); - value + result }, Target::IndirectARegDec(reg) => { - let addr = self.get_a_reg(reg); + let addr = self.get_a_reg_mut(reg); *addr -= size.in_bytes(); get_address_sized(space, *addr as Address, size) }, Target::IndirectARegOffset(reg, offset) => { - let addr = self.get_a_reg(reg); + let addr = self.get_a_reg_mut(reg); get_address_sized(space, (*addr).wrapping_add(offset as u32) as Address, size) }, Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => { let reg_offset = get_value_sized(self.get_x_reg_value(rtype, xreg), target_size); - let addr = self.get_a_reg(reg); + let addr = self.get_a_reg_mut(reg); get_address_sized(space, (*addr).wrapping_add(reg_offset).wrapping_add(offset as u32) as Address, size) }, Target::IndirectMemory(addr) => { @@ -292,7 +372,6 @@ impl MC68010 { let reg_offset = get_value_sized(self.get_x_reg_value(rtype, xreg), target_size); get_address_sized(space, self.pc.wrapping_add(reg_offset).wrapping_add(offset as u32) as Address, size) }, - _ => Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))), } } @@ -302,10 +381,32 @@ impl MC68010 { set_value_sized(&mut self.d_reg[reg as usize], value, size); }, Target::DirectAReg(reg) => { - set_value_sized(self.get_a_reg(reg), value, size); + set_value_sized(self.get_a_reg_mut(reg), value, size); }, Target::IndirectAReg(reg) => { - set_address_sized(space, *self.get_a_reg(reg) as Address, value, size)?; + set_address_sized(space, *self.get_a_reg_mut(reg) as Address, value, size)?; + }, + Target::IndirectARegInc(reg) => { + let addr = self.get_a_reg_mut(reg); + set_address_sized(space, *addr as Address, value, size)?; + *addr += size.in_bytes(); + }, + Target::IndirectARegDec(reg) => { + let addr = self.get_a_reg_mut(reg); + *addr -= size.in_bytes(); + set_address_sized(space, *addr as Address, value, size)?; + }, + Target::IndirectARegOffset(reg, offset) => { + let addr = self.get_a_reg_mut(reg); + set_address_sized(space, (*addr).wrapping_add(offset as u32) as Address, value, size)?; + }, + Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => { + let reg_offset = get_value_sized(self.get_x_reg_value(rtype, xreg), target_size); + let addr = self.get_a_reg_mut(reg); + set_address_sized(space, (*addr).wrapping_add(reg_offset).wrapping_add(offset as u32) as Address, value, size)?; + }, + Target::IndirectMemory(addr) => { + set_address_sized(space, addr as Address, value, size)?; }, _ => return Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))), } @@ -314,14 +415,14 @@ impl MC68010 { fn get_target_address(&mut self, target: Target) -> Result { let addr = match target { - Target::IndirectAReg(reg) => *self.get_a_reg(reg), + Target::IndirectAReg(reg) => *self.get_a_reg_mut(reg), Target::IndirectARegOffset(reg, offset) => { - let addr = self.get_a_reg(reg); + let addr = self.get_a_reg_mut(reg); (*addr).wrapping_add(offset as u32) }, Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => { let reg_offset = get_value_sized(self.get_x_reg_value(rtype, xreg), target_size); - let addr = self.get_a_reg(reg); + let addr = self.get_a_reg_mut(reg); (*addr).wrapping_add(reg_offset).wrapping_add(offset as u32) }, Target::IndirectMemory(addr) => { @@ -334,7 +435,7 @@ impl MC68010 { let reg_offset = get_value_sized(self.get_x_reg_value(rtype, xreg), target_size); self.pc.wrapping_add(reg_offset).wrapping_add(offset as u32) }, - _ => return Err(Error::new(&format!("Unimplemented addressing target: {:?}", target))), + _ => return Err(Error::new(&format!("Invalid addressing target: {:?}", target))), }; Ok(addr) } @@ -346,12 +447,12 @@ impl MC68010 { } #[inline(always)] - fn get_stack_pointer(&mut self) -> &mut u32 { + fn get_stack_pointer_mut(&mut self) -> &mut u32 { if self.is_supervisor() { &mut self.msp } else { &mut self.usp } } #[inline(always)] - fn get_a_reg(&mut self, reg: u8) -> &mut u32 { + fn get_a_reg_mut(&mut self, reg: u8) -> &mut u32 { if reg == 7 { if self.is_supervisor() { &mut self.msp } else { &mut self.usp } } else { @@ -365,6 +466,69 @@ impl MC68010 { RegisterType::Address => self.d_reg[reg as usize], } } + + fn get_flag(&self, flag: u16) -> bool { + if (self.sr & flag) == 0 { + false + } else { + true + } + } + + fn set_compare_flags(&mut self, value: i32, carry: bool) { + let mut flags = 0x0000; + if value < 0 { + flags |= FLAGS_NEGATIVE + } + if value == 0 { + flags |= FLAGS_ZERO + } + if carry { + flags |= FLAGS_CARRY | FLAGS_OVERFLOW; + } + self.sr |= (self.sr & 0xFFF0) | flags; + } + + fn set_logic_flags(&mut self, value: u32, size: Size) { + let mut flags = 0x0000; + match size { + Size::Byte if value & 0x80 != 0 => flags |= FLAGS_NEGATIVE, + Size::Word if value & 0x8000 != 0 => flags |= FLAGS_NEGATIVE, + Size::Long if value & 0x80000000 != 0 => flags |= FLAGS_NEGATIVE, + _ => { }, + } + if value == 0 { + flags |= FLAGS_ZERO + } + self.sr |= (self.sr & 0xFFF0) | flags; + } + + + fn get_current_condition(&self, cond: Condition) -> bool { + match cond { + True => true, + False => false, + High => !self.get_flag(FLAGS_CARRY) && !self.get_flag(FLAGS_ZERO), + LowOrSame => self.get_flag(FLAGS_CARRY) || self.get_flag(FLAGS_ZERO), + CarryClear => !self.get_flag(FLAGS_CARRY), + CarrySet => self.get_flag(FLAGS_CARRY), + NotEqual => !self.get_flag(FLAGS_ZERO), + Equal => self.get_flag(FLAGS_ZERO), + OverflowClear => !self.get_flag(FLAGS_OVERFLOW), + OverflowSet => self.get_flag(FLAGS_OVERFLOW), + Plus => !self.get_flag(FLAGS_NEGATIVE), + Minus => self.get_flag(FLAGS_NEGATIVE), + GreaterThanOrEqual => self.get_flag(FLAGS_NEGATIVE) && self.get_flag(FLAGS_OVERFLOW) || !self.get_flag(FLAGS_NEGATIVE) && !self.get_flag(FLAGS_OVERFLOW), + LessThan => self.get_flag(FLAGS_NEGATIVE) && !self.get_flag(FLAGS_OVERFLOW) || !self.get_flag(FLAGS_NEGATIVE) && self.get_flag(FLAGS_OVERFLOW), + GreaterThan => + self.get_flag(FLAGS_NEGATIVE) && self.get_flag(FLAGS_OVERFLOW) && !self.get_flag(FLAGS_ZERO) + || !self.get_flag(FLAGS_NEGATIVE) && !self.get_flag(FLAGS_OVERFLOW) && !self.get_flag(FLAGS_ZERO), + LessThanOrEqual => + self.get_flag(FLAGS_ZERO) + || self.get_flag(FLAGS_NEGATIVE) && !self.get_flag(FLAGS_OVERFLOW) + || !self.get_flag(FLAGS_NEGATIVE) && self.get_flag(FLAGS_OVERFLOW), + } + } } fn get_value_sized(value: u32, size: Size) -> u32 { diff --git a/src/main.rs b/src/main.rs index faa9620..f195d18 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,9 +18,18 @@ fn main() { let ram = Segment::new(0x00100000, vec![0; 0x00100000]); space.insert(ram); + let serial = Segment::new(0x00700000, vec![0; 0x30]); + space.insert(serial); + let mut cpu = MC68010::new(); while cpu.is_running() { - cpu.step(&mut space).unwrap(); + match cpu.step(&mut space) { + Ok(()) => { }, + Err(err) => { + cpu.dump_state(); + panic!("{:?}", err); + }, + } } } diff --git a/src/memory.rs b/src/memory.rs index 2777f37..258e450 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -39,9 +39,10 @@ impl Addressable for Segment { self.contents[(addr - self.base) as usize .. ].iter() } - fn write(&mut self, addr: Address, data: &[u8]) { + fn write(&mut self, mut addr: Address, data: &[u8]) { for byte in data { self.contents[(addr - self.base) as usize] = *byte; + addr += 1; } } } @@ -75,7 +76,7 @@ impl AddressSpace { return Ok(&self.segments[i]); } } - return Err(Error::new(&format!("No segment found at {:08x}", addr))); + return Err(Error::new(&format!("No segment found at {:#08x}", addr))); } pub fn get_segment_mut(&mut self, addr: Address) -> Result<&mut Segment, Error> { @@ -84,10 +85,15 @@ impl AddressSpace { return Ok(&mut self.segments[i]); } } - return Err(Error::new(&format!("No segment found at {:08x}", addr))); + return Err(Error::new(&format!("No segment found at {:#08x}", addr))); } + pub fn read(&self, addr: Address) -> Result, Error> { + let seg = self.get_segment(addr)?; + Ok(seg.contents[(addr - seg.base) as usize .. ].iter()) + } + pub fn read_u8(&self, addr: Address) -> Result { let seg = self.get_segment(addr)?; Ok(*seg.read(addr).next().unwrap())