Fixed decode of EXT, and fixed some bugs with 020+ code

This commit is contained in:
transistor 2021-10-15 14:37:31 -07:00
parent 1732c90f5b
commit ffd4faa9a3
5 changed files with 79 additions and 55 deletions

View File

@ -49,9 +49,9 @@ pub enum ShiftDirection {
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum RegisterType {
Data,
Address,
pub enum XRegister {
Data(u8),
Address(u8),
}
#[derive(Copy, Clone, Debug, PartialEq)]
@ -95,10 +95,10 @@ pub enum Target {
IndirectARegInc(u8),
IndirectARegDec(u8),
IndirectARegOffset(u8, i32),
IndirectARegXRegOffset(u8, RegisterType, u8, i32, Size),
IndirectARegXRegOffset(u8, XRegister, i32, u8, Size),
IndirectMemory(u32),
IndirectPCOffset(i32),
IndirectPCXRegOffset(RegisterType, u8, i32, Size),
IndirectPCXRegOffset(XRegister, i32, u8, Size),
}
#[derive(Clone, Debug, PartialEq)]
@ -131,7 +131,7 @@ pub enum Instruction {
EORtoCCR(u8),
EORtoSR(u16),
EXG(Target, Target),
EXT(u8, Size),
EXT(u8, Size, Size),
ILLEGAL,
@ -328,7 +328,7 @@ impl M68kDecoder {
let ins_0f00 = ins & 0xF00;
let ins_00f0 = ins & 0x0F0;
if (ins & 0x180) == 0x180 {
if (ins & 0x180) == 0x180 && (ins & 0x038) != 0 {
if (ins & 0x040) == 0 {
let size = match get_size(ins) {
Some(Size::Word) => Size::Word,
@ -382,7 +382,7 @@ impl M68kDecoder {
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if ins_0f00 == 0x800 {
} else if ins_0f00 == 0x800 || ins_0f00 == 0x900 {
let subselect = (ins & 0x01C0) >> 6;
let mode = get_low_mode(ins);
match (subselect, mode) {
@ -400,10 +400,14 @@ impl M68kDecoder {
let target = self.decode_lower_effective_address(system, ins, None)?;
Ok(Instruction::PEA(target))
},
(0b010, 0b000) |
(0b010, 0b000) => {
Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Word))
},
(0b011, 0b000) => {
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
Ok(Instruction::EXT(get_low_reg(ins), size))
Ok(Instruction::EXT(get_low_reg(ins), Size::Word, Size::Long))
},
(0b111, 0b000) => {
Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Long))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
@ -509,7 +513,7 @@ impl M68kDecoder {
let mut disp = ((ins & 0xFF) as i8) as i32;
if disp == 0 {
disp = (self.read_instruction_word(system)? as i16) as i32;
} else if disp == 0xff && self.cputype >= M68kType::MC68020 {
} else if disp == -1 && self.cputype >= M68kType::MC68020 {
disp = self.read_instruction_long(system)? as i32;
}
let condition = get_condition(ins);
@ -725,17 +729,17 @@ impl M68kDecoder {
fn decode_extension_word(&mut self, system: &mut AddressableDeviceRefMut<'_>, areg: Option<u8>) -> Result<Target, Error> {
let brief_extension = self.read_instruction_word(system)?;
let rtype = if (brief_extension & 0x8000) == 0 { RegisterType::Data } else { RegisterType::Address };
let xreg = ((brief_extension & 0x7000) >> 12) as u8;
let xreg_num = ((brief_extension & 0x7000) >> 12) as u8;
let xreg = if (brief_extension & 0x8000) == 0 { XRegister::Data(xreg_num) } else { XRegister::Address(xreg_num) };
let size = if (brief_extension & 0x0800) == 0 { Size::Word } else { Size::Long };
let scale = ((brief_extension & 0x0600) >> 9) as u8;
let use_full = (brief_extension & 0x0100) == 1;
let scale = (brief_extension & 0x0600) >> 9 as u8;
if !use_full {
let displacement = sign_extend_to_long((brief_extension & 0x00FF) as u32, Size::Byte);
match areg {
Some(areg) => Ok(Target::IndirectARegXRegOffset(areg, rtype, xreg, displacement, size)),
None => Ok(Target::IndirectPCXRegOffset(rtype, xreg, displacement, size)),
Some(areg) => Ok(Target::IndirectARegXRegOffset(areg, xreg, displacement, scale, size)),
None => Ok(Target::IndirectPCXRegOffset(xreg, displacement, scale, size)),
}
} else if self.cputype >= M68kType::MC68020 {
let use_base = (brief_extension & 0x0080) == 0;
@ -821,7 +825,7 @@ impl M68kDecoder {
(0..((self.end - self.start) / 2)).map(|offset|
Ok(format!("{:04x} ", system.get_bus().read_beu16((self.start + (offset * 2)) as Address).unwrap()))
).collect();
println!("{:#010x}: {}\n\t{}\n", self.start, ins_data.unwrap(), self.instruction);
println!("{:#010x}: {}\n\t{:?}\n", self.start, ins_data.unwrap(), self.instruction);
}
}
@ -940,7 +944,7 @@ impl fmt::Display for Condition {
match self {
Condition::True => write!(f, "t"),
Condition::False => write!(f, "f"),
Condition::High => write!(f, "h"),
Condition::High => write!(f, "hi"),
Condition::LowOrSame => write!(f, "ls"),
Condition::CarryClear => write!(f, "cc"),
Condition::CarrySet => write!(f, "cs"),
@ -966,6 +970,15 @@ impl fmt::Display for ControlRegister {
}
}
impl fmt::Display for XRegister {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
XRegister::Data(reg) => write!(f, "d{}", reg),
XRegister::Address(reg) => write!(f, "a{}", reg),
}
}
}
impl fmt::Display for Target {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@ -976,10 +989,16 @@ impl fmt::Display for Target {
Target::IndirectARegInc(reg) => write!(f, "(%a{})+", reg),
Target::IndirectARegDec(reg) => write!(f, "-(%a{})", reg),
Target::IndirectARegOffset(reg, offset) => write!(f, "(%a{} + #{:04x})", reg, offset),
Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, _) => write!(f, "(%a{} + %{}{} + #{:04x})", reg, if *rtype == RegisterType::Data { 'd' } else { 'a' }, xreg, offset),
Target::IndirectARegXRegOffset(reg, xreg, offset, scale, _) => {
let scale_str = if *scale != 0 { format!("<< {}", scale) } else { "".to_string() };
write!(f, "(%a{} + %{} + #{:04x}{})", reg, xreg, offset, scale_str)
},
Target::IndirectMemory(value) => write!(f, "(#{:08x})", value),
Target::IndirectPCOffset(offset) => write!(f, "(%pc + #{:04x})", offset),
Target::IndirectPCXRegOffset(rtype, xreg, offset, _) => write!(f, "(%pc + %{}{} + #{:04x})", if *rtype == RegisterType::Data { 'd' } else { 'a' }, xreg, offset),
Target::IndirectPCXRegOffset(xreg, offset, scale, _) => {
let scale_str = if *scale != 0 { format!("<< {}", scale) } else { "".to_string() };
write!(f, "(%pc + %{} + #{:04x}{})", xreg, offset, scale_str)
},
}
}
}
@ -1019,7 +1038,7 @@ impl fmt::Display for Instruction {
Instruction::EORtoCCR(value) => write!(f, "eorb\t{:02x}, %ccr", value),
Instruction::EORtoSR(value) => write!(f, "eorw\t{:04x}, %sr", value),
Instruction::EXG(src, dest) => write!(f, "exg\t{}, {}", src, dest),
Instruction::EXT(reg, size) => write!(f, "ext{}\t%d{}", size, reg),
Instruction::EXT(reg, from_size, to_size) => write!(f, "ext{}{}\t%d{}", from_size, to_size, reg),
Instruction::ILLEGAL => write!(f, "illegal"),

View File

@ -13,7 +13,7 @@ use super::decode::{
Condition,
ShiftDirection,
ControlRegister,
RegisterType,
XRegister,
sign_extend_to_long
};
@ -131,6 +131,8 @@ impl M68k {
if self.debugger.use_tracing {
self.decoder.dump_decoded(system);
// TODO for debugging temporarily
self.dump_state(system);
}
if self.debugger.use_debugger {
@ -288,15 +290,16 @@ impl M68k {
},
//Instruction::EXG(Target, Target) => {
//},
Instruction::EXT(reg, size) => {
let byte = (self.state.d_reg[reg as usize] as u8) as i8;
let result = match size {
Size::Byte => (byte as u8) as u32,
Size::Word => ((byte as i16) as u16) as u32,
Size::Long => (byte as i32) as u32,
Instruction::EXT(reg, from_size, to_size) => {
let input = self.state.d_reg[reg as usize];
let result = match (from_size, to_size) {
(Size::Byte, Size::Word) => ((((input as u8) as i8) as i16) as u16) as u32,
(Size::Word, Size::Long) => (((input as u16) as i16) as i32) as u32,
(Size::Byte, Size::Long) => (((input as u8) as i8) as i32) as u32,
_ => panic!("Unsupported size for EXT instruction"),
};
set_value_sized(&mut self.state.d_reg[reg as usize], result, size);
self.set_logic_flags(result, size);
set_value_sized(&mut self.state.d_reg[reg as usize], result, to_size);
self.set_logic_flags(result, to_size);
},
//Instruction::ILLEGAL => {
//},
@ -605,10 +608,10 @@ impl M68k {
let addr = self.get_a_reg_mut(reg);
get_address_sized(system, (*addr).wrapping_add(offset as u32) as Address, size)
},
Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size);
Target::IndirectARegXRegOffset(reg, xreg, offset, scale, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size);
let addr = self.get_a_reg_mut(reg);
get_address_sized(system, (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, size)
get_address_sized(system, ((*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale) as Address, size)
},
Target::IndirectMemory(addr) => {
get_address_sized(system, addr as Address, size)
@ -616,9 +619,9 @@ impl M68k {
Target::IndirectPCOffset(offset) => {
get_address_sized(system, (self.decoder.start + 2).wrapping_add(offset as u32) as Address, size)
},
Target::IndirectPCXRegOffset(rtype, xreg, offset, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size);
get_address_sized(system, (self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, size)
Target::IndirectPCXRegOffset(xreg, offset, scale, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size);
get_address_sized(system, ((self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale) as Address, size)
},
}
}
@ -648,10 +651,10 @@ impl M68k {
let addr = self.get_a_reg_mut(reg);
set_address_sized(system, (*addr).wrapping_add(offset as u32) as Address, value, size)?;
},
Target::IndirectARegXRegOffset(reg, rtype, xreg, offset, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size);
Target::IndirectARegXRegOffset(reg, xreg, offset, scale, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size);
let addr = self.get_a_reg_mut(reg);
set_address_sized(system, (*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) as Address, value, size)?;
set_address_sized(system, ((*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale) as Address, value, size)?;
},
Target::IndirectMemory(addr) => {
set_address_sized(system, addr as Address, value, size)?;
@ -668,10 +671,10 @@ impl M68k {
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 = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size);
Target::IndirectARegXRegOffset(reg, xreg, offset, scale, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size);
let addr = self.get_a_reg_mut(reg);
(*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32)
(*addr).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale
},
Target::IndirectMemory(addr) => {
addr
@ -679,9 +682,9 @@ impl M68k {
Target::IndirectPCOffset(offset) => {
(self.decoder.start + 2).wrapping_add(offset as u32)
},
Target::IndirectPCXRegOffset(rtype, xreg, offset, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(rtype, xreg), target_size);
(self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32)
Target::IndirectPCXRegOffset(xreg, offset, scale, target_size) => {
let reg_offset = sign_extend_to_long(self.get_x_reg_value(xreg), target_size);
(self.decoder.start + 2).wrapping_add(reg_offset as u32).wrapping_add(offset as u32) << scale
},
_ => return Err(Error::new(&format!("Invalid addressing target: {:?}", target))),
};
@ -708,10 +711,10 @@ impl M68k {
}
}
fn get_x_reg_value(&self, rtype: RegisterType, reg: u8) -> u32 {
match rtype {
RegisterType::Data => self.state.d_reg[reg as usize],
RegisterType::Address => self.state.a_reg[reg as usize],
fn get_x_reg_value(&self, xreg: XRegister) -> u32 {
match xreg {
XRegister::Data(reg) => self.state.d_reg[reg as usize],
XRegister::Address(reg) => self.state.a_reg[reg as usize],
}
}

View File

@ -70,7 +70,7 @@ impl InterruptController {
// TODO how does this find the specific device it's connected to?
// TODO for the time being, this will find the first device to handle it or fail
println!("interrupts: priority {} state changed to {}", priority, state);
debug!("interrupts: priority {} state changed to {}", priority, state);
match &self.target {
Some(dev) => {
Ok(dev.borrow_mut().interrupt_state_change(state, priority, number)?)

View File

@ -40,6 +40,7 @@ fn main() {
let mut cpu = M68k::new(M68kType::MC68010);
//let mut cpu = M68k::new(M68kType::MC68030);
//cpu.enable_tracing();
//cpu.add_breakpoint(0x10781a);
@ -47,6 +48,7 @@ fn main() {
//cpu.add_breakpoint(0x106a94);
//cpu.add_breakpoint(0x10b79c);
//cpu.decoder.dump_disassembly(&mut system, 0x100000, 0x2000);
//cpu.decoder.dump_disassembly(&mut system, 0x2ac, 0x200);
system.add_interruptable_device(wrap_interruptable(cpu)).unwrap();
loop {

View File

@ -278,10 +278,6 @@ impl Addressable for MC68681 {
fn read(&mut self, addr: Address, count: usize) -> Result<Vec<u8>, Error> {
let mut data = vec![0; count];
if addr != REG_SRA_RD && addr != REG_SRB_RD {
debug!("{}: reading from {:0x}", DEV_NAME, addr);
}
match addr {
REG_SRA_RD => {
data[0] = self.port_a.status
@ -326,6 +322,10 @@ impl Addressable for MC68681 {
_ => { },
}
if addr != REG_SRA_RD && addr != REG_SRB_RD {
debug!("{}: read from {:0x} of {:0x}", DEV_NAME, addr, data[0]);
}
Ok(data)
}