Added bit test instructions and got boot message working
This commit is contained in:
parent
7868bc3014
commit
01b4bdf859
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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); },
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(()) => { },
|
||||
|
|
|
@ -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)))?)
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue