Added bit test instructions and got boot message working

This commit is contained in:
transistor 2021-09-30 20:27:01 -07:00
parent 7868bc3014
commit 01b4bdf859
5 changed files with 110 additions and 47 deletions

View File

@ -712,5 +712,13 @@ impl Size {
Size::Long => 4,
}
}
pub fn in_bits(&self) -> u32 {
match self {
Size::Byte => 8,
Size::Word => 16,
Size::Long => 32,
}
}
}

View File

@ -4,12 +4,26 @@ use crate::memory::{Address, AddressSpace};
use super::decode::{Instruction, Target, Size, Direction, Condition, ControlRegister, RegisterType};
/*
pub trait Processor {
fn reset();
fn step();
}
*/
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;
pub const ERR_ADDRESS_ERROR: u32 = 3;
pub const ERR_ILLEGAL_INSTRUCTION: u32 = 4;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum State {
@ -33,21 +47,10 @@ pub struct MC68010 {
pub current_instruction_addr: u32,
pub current_instruction: Instruction,
pub breakpoint: u32,
pub use_tracing: bool,
pub use_debugger: bool,
}
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;
pub const ERR_ADDRESS_ERROR: u32 = 3;
pub const ERR_ILLEGAL_INSTRUCTION: u32 = 4;
impl MC68010 {
pub fn new() -> MC68010 {
MC68010 {
@ -65,6 +68,7 @@ impl MC68010 {
current_instruction_addr: 0,
current_instruction: Instruction::NOP,
breakpoint: 0,
use_tracing: false,
use_debugger: false,
}
}
@ -83,6 +87,7 @@ impl MC68010 {
self.current_instruction_addr = 0;
self.current_instruction = Instruction::NOP;
self.breakpoint = 0;
self.use_tracing = false;
self.use_debugger = false;
}
@ -157,17 +162,20 @@ impl MC68010 {
self.current_instruction = self.decode_one(space)?;
if self.breakpoint == self.current_instruction_addr {
self.use_tracing = true;
self.use_debugger = true;
}
if self.use_debugger {
if self.use_tracing {
// Print instruction bytes for debugging
let ins_data: Result<String, Error> =
(0..((self.pc - self.current_instruction_addr) / 2)).map(|offset|
Ok(format!("{:04x} ", space.read_beu16((self.current_instruction_addr + (offset * 2)) as Address)?))
).collect();
debug!("{:#010x}: {}\n\t{:?}\n", self.current_instruction_addr, ins_data?, self.current_instruction);
}
if self.use_debugger {
// Single Step
self.dump_state(space);
let mut buffer = String::new();
@ -192,7 +200,7 @@ impl MC68010 {
},
Size::Long => existing.overflowing_add(value),
};
self.set_compare_flags(result as i32, overflow);
self.set_compare_flags(result, overflow, size);
self.set_target_value(space, dest, result, size)?;
},
Instruction::AND(src, dest, size) => {
@ -222,16 +230,36 @@ impl MC68010 {
self.push_long(space, self.pc)?;
self.pc = self.current_instruction_addr.wrapping_add(offset as u32) + 2;
},
//Instruction::BTST(Target, Target, Size) => {
//},
//Instruction::BCHG(Target, Target, Size) => {
//},
//Instruction::BCLR(Target, Target, Size) => {
//},
//Instruction::BSET(Target, Target, Size) => {
//},
Instruction::BTST(bitnum, target, size) => {
let bitnum = self.get_target_value(space, bitnum, Size::Byte)?;
let value = self.get_target_value(space, target, size)?;
self.set_bit_test_flags(value, bitnum, size);
},
Instruction::BCHG(bitnum, target, size) => {
let bitnum = self.get_target_value(space, bitnum, Size::Byte)?;
let mut value = self.get_target_value(space, target, size)?;
let mask = self.set_bit_test_flags(value, bitnum, size);
value = (value & !mask) | (!(value & mask) & mask);
self.set_target_value(space, target, value, size)?;
},
Instruction::BCLR(bitnum, target, size) => {
let bitnum = self.get_target_value(space, bitnum, Size::Byte)?;
let mut value = self.get_target_value(space, target, size)?;
let mask = self.set_bit_test_flags(value, bitnum, size);
value = value & !mask;
self.set_target_value(space, target, value, size)?;
},
Instruction::BSET(bitnum, target, size) => {
let bitnum = self.get_target_value(space, bitnum, Size::Byte)?;
let mut value = self.get_target_value(space, target, size)?;
let mask = self.set_bit_test_flags(value, bitnum, size);
value = value | mask;
self.set_target_value(space, target, value, size)?;
},
Instruction::CLR(target, size) => {
self.set_target_value(space, target, 0, size)?;
// Clear flags except Zero flag
self.sr = (self.sr & 0xFFF0) | 0x0004;
},
Instruction::CMP(src, dest, size) => {
let value = self.get_target_value(space, src, size)?;
@ -242,12 +270,18 @@ impl MC68010 {
//},
//Instruction::DIV(Target, Target, Size, Sign) => {
//},
//Instruction::EOR(Target, Target, Size) => {
//},
//Instruction::EORtoCCR(u8) => {
//},
//Instruction::EORtoSR(u16) => {
//},
Instruction::EOR(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::EORtoCCR(value) => {
self.sr = self.sr ^ value as u16;
},
Instruction::EORtoSR(value) => {
self.sr = self.sr ^ value;
},
//Instruction::EXG(Target, Target) => {
//},
Instruction::EXT(reg, size) => {
@ -274,6 +308,7 @@ impl MC68010 {
//},
Instruction::MOVE(src, dest, size) => {
let value = self.get_target_value(space, src, size)?;
self.set_compare_flags(value, false, size);
self.set_target_value(space, dest, value, size)?;
},
Instruction::MOVEfromSR(target) => {
@ -341,6 +376,7 @@ impl MC68010 {
Instruction::MOVEQ(data, reg) => {
let value = sign_extend_byte(data, Size::Long);
self.d_reg[reg as usize] = value;
self.set_compare_flags(value, false, Size::Long);
},
//Instruction::MUL(Target, Target, Size, Sign) => {
//},
@ -390,13 +426,15 @@ impl MC68010 {
let result = self.subtract_sized_with_flags(existing, value, size);
self.set_target_value(space, dest, result, size)?;
},
//Instruction::SWAP(u8) => {
//},
Instruction::SWAP(reg) => {
let value = self.d_reg[reg as usize];
self.d_reg[reg as usize] = ((value & 0x0000FFFF) << 16) | ((value & 0xFFFF0000) >> 16);
},
//Instruction::TAS(Target) => {
//},
Instruction::TST(target, size) => {
let value = self.get_target_value(space, target, size)?;
self.set_compare_flags(value as i32, false);
self.set_compare_flags(value, false, size);
},
//Instruction::TRAP(u8) => {
//},
@ -526,7 +564,7 @@ impl MC68010 {
},
Size::Long => existing.overflowing_sub(diff),
};
self.set_compare_flags(result as i32, overflow);
self.set_compare_flags(result, overflow, size);
result
}
@ -565,7 +603,13 @@ impl MC68010 {
}
}
fn set_compare_flags(&mut self, value: i32, carry: bool) {
fn set_compare_flags(&mut self, value: u32, carry: bool, size: Size) {
let value = match size {
Size::Byte => ((value as u8) as i8) as i32,
Size::Word => ((value as u16) as i16) as i32,
Size::Long => value as i32,
};
let mut flags = 0x0000;
if value < 0 {
flags |= FLAGS_NEGATIVE
@ -593,6 +637,13 @@ impl MC68010 {
self.sr |= (self.sr & 0xFFF0) | flags;
}
fn set_bit_test_flags(&mut self, value: u32, bitnum: u32, size: Size) -> u32 {
let mask = 0x1 << (bitnum % size.in_bits());
let zeroflag = if (value & mask) == 0 { FLAGS_ZERO } else { 0 };
self.sr = (self.sr & !FLAGS_ZERO) | zeroflag;
mask
}
fn get_current_condition(&self, cond: Condition) -> bool {
match cond {
@ -654,7 +705,7 @@ fn set_address_sized(space: &mut AddressSpace, addr: Address, value: u32, size:
}
fn sign_extend_byte(value: u8, size: Size) -> u32 {
let value = (value as i8);
let value = value as i8;
match size {
Size::Byte => (value as u8) as u32,
Size::Word => ((value as i16) as u16) as u32,

View File

@ -30,12 +30,14 @@ const REG_IVR_WR: Address = 0x19;
const DEV_NAME: &'static str = "mc68681";
pub struct MC68681 {
pub status: [u8; 1],
pub input: [u8; 1],
}
impl MC68681 {
pub fn new() -> Self {
MC68681 {
status: [0x0C],
input: [0],
}
}
@ -46,16 +48,17 @@ impl Addressable for MC68681 {
0x30
}
fn read(&self, addr: Address) -> Iter<u8> {
fn read(&self, addr: Address) -> &[u8] {
match addr {
REG_TBA_WR => self.input.iter(),
_ => { println!("{}: reading from {:0x}", DEV_NAME, addr); self.input.iter() },
REG_SRA_RD => &self.status,
REG_TBA_RD => &self.input,
_ => { println!("{}: reading from {:0x}", DEV_NAME, addr); &self.input },
}
}
fn write(&mut self, mut addr: Address, data: &[u8]) {
match addr {
REG_TBA_WR => { println!(">>> {}", data[0]); },
REG_TBA_WR => { println!(">>> {}", data[0] as char); },
_ => { println!("{}: writing {:0x} to {:0x}", DEV_NAME, data[0], addr); },
}
}

View File

@ -20,11 +20,12 @@ fn main() {
let ram = MemoryBlock::new(vec![0; 0x00100000]);
space.insert(0x00100000, Box::new(ram));
let serial = MC68681::new();
let mut serial = MC68681::new();
space.insert(0x00700000, Box::new(serial));
let mut cpu = MC68010::new();
cpu.set_breakpoint(0x0838);
//cpu.set_breakpoint(0x0838);
//cpu.use_tracing = true;
while cpu.is_running() {
match cpu.step(&mut space) {
Ok(()) => { },

View File

@ -9,7 +9,7 @@ pub type Address = u64;
pub trait Addressable {
fn len(&self) -> usize;
fn read(&self, addr: Address) -> Iter<u8>;
fn read(&self, addr: Address) -> &[u8];
fn write(&mut self, addr: Address, data: &[u8]);
}
@ -38,8 +38,8 @@ impl Addressable for MemoryBlock {
self.contents.len()
}
fn read(&self, addr: Address) -> Iter<u8> {
self.contents[(addr) as usize .. ].iter()
fn read(&self, addr: Address) -> &[u8] {
&self.contents[(addr) as usize .. ]
}
fn write(&mut self, mut addr: Address, data: &[u8]) {
@ -120,24 +120,24 @@ impl AddressSpace {
}
pub fn read(&self, addr: Address) -> Result<Iter<u8>, Error> {
pub fn read(&self, addr: Address) -> Result<&[u8], Error> {
let seg = self.get_segment(addr)?;
Ok(seg.contents.read(addr - seg.base))
}
pub fn read_u8(&self, addr: Address) -> Result<u8, Error> {
let seg = self.get_segment(addr)?;
Ok(*seg.contents.read(addr - seg.base).next().ok_or_else(|| Error::new(&format!("Error reading address {:#010x}", addr)))?)
Ok(*seg.contents.read(addr - seg.base).iter().next().ok_or_else(|| Error::new(&format!("Error reading address {:#010x}", addr)))?)
}
pub fn read_beu16(&self, addr: Address) -> Result<u16, Error> {
let seg = self.get_segment(addr)?;
Ok(read_beu16(seg.contents.read(addr - seg.base)).ok_or_else(|| Error::new(&format!("Error reading address {:#010x}", addr)))?)
Ok(read_beu16(seg.contents.read(addr - seg.base).iter()).ok_or_else(|| Error::new(&format!("Error reading address {:#010x}", addr)))?)
}
pub fn read_beu32(&self, addr: Address) -> Result<u32, Error> {
let seg = self.get_segment(addr)?;
Ok(read_beu32(seg.contents.read(addr - seg.base)).ok_or_else(|| Error::new(&format!("Error reading address {:#010x}", addr)))?)
Ok(read_beu32(seg.contents.read(addr - seg.base).iter()).ok_or_else(|| Error::new(&format!("Error reading address {:#010x}", addr)))?)
}