More instruction execution, enough to loop

I'm using the monitor.bin binary built from computie to boot the
virtual machine, and it currently runs and loops, but there is no
actual serial device, so it's hard to tell if it's working correctly
This commit is contained in:
transistor 2021-09-29 21:52:38 -07:00
parent 9095333793
commit 92342c23ed
4 changed files with 237 additions and 58 deletions

View File

@ -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<u16, Error> {
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<u32, Error> {
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)?;
}

View File

@ -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<u32, Error> {
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<String, Error> =
(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<u32, Error> {
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 {

View File

@ -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);
},
}
}
}

View File

@ -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<Iter<u8>, Error> {
let seg = self.get_segment(addr)?;
Ok(seg.contents[(addr - seg.base) as usize .. ].iter())
}
pub fn read_u8(&self, addr: Address) -> Result<u8, Error> {
let seg = self.get_segment(addr)?;
Ok(*seg.read(addr).next().unwrap())