mirror of
https://github.com/transistorfet/moa.git
synced 2024-05-28 13:41:30 +00:00
Added MOVEP and more tests to m68k and IM to z80
This commit is contained in:
parent
1d8065026d
commit
a342ef3b86
|
@ -104,8 +104,8 @@ impl M68kDecoder {
|
|||
let areg = get_low_reg(ins);
|
||||
let dir = if (ins & 0x0800) == 0 { Direction::FromTarget } else { Direction::ToTarget };
|
||||
let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long };
|
||||
let offset = sign_extend_to_long(self.read_instruction_word(memory)? as u32, Size::Word);
|
||||
Ok(Instruction::MOVEP(dreg, Target::IndirectRegOffset(BaseRegister::AReg(areg), None, offset), size, dir))
|
||||
let offset = self.read_instruction_word(memory)? as i16;
|
||||
Ok(Instruction::MOVEP(dreg, areg, offset, size, dir))
|
||||
} else if (ins & 0x0100) == 0x0100 || (ins & 0x0F00) == 0x0800 {
|
||||
let bitnum = if (ins & 0x0100) == 0x0100 {
|
||||
Target::DirectDReg(get_high_reg(ins))
|
||||
|
|
|
@ -507,8 +507,32 @@ impl M68k {
|
|||
Instruction::MOVEM(target, size, dir, mask) => {
|
||||
self.execute_movem(target, size, dir, mask)?;
|
||||
},
|
||||
//Instruction::MOVEP(reg, target, size, dir) => {
|
||||
//},
|
||||
Instruction::MOVEP(dreg, areg, offset, size, dir) => {
|
||||
match dir {
|
||||
Direction::ToTarget => {
|
||||
let mut shift = (size.in_bytes() as i32 * 8) - 8;
|
||||
let mut addr = ((*self.get_a_reg_mut(areg) as i32) + (offset as i32)) as Address;
|
||||
while shift >= 0 {
|
||||
let byte = (self.state.d_reg[dreg as usize] >> shift) as u8;
|
||||
let data = if (addr & 0x1) == 0 { (byte as u16) << 8 } else { byte as u16 };
|
||||
self.port.write_beu16(addr, data)?;
|
||||
addr += 2;
|
||||
shift -= 8;
|
||||
}
|
||||
},
|
||||
Direction::FromTarget => {
|
||||
let mut shift = (size.in_bytes() as i32 * 8) - 8;
|
||||
let mut addr = ((*self.get_a_reg_mut(areg) as i32) + (offset as i32)) as Address;
|
||||
while shift >= 0 {
|
||||
let data = self.port.read_beu16(addr)?;
|
||||
let byte = if (addr & 0x1) == 0 { (data >> 8) as u8 } else { data as u8 };
|
||||
self.state.d_reg[dreg as usize] |= (byte as u32) << shift;
|
||||
addr += 2;
|
||||
shift -= 8;
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
Instruction::MOVEQ(data, reg) => {
|
||||
let value = sign_extend_to_long(data as u32, Size::Byte) as u32;
|
||||
self.state.d_reg[reg as usize] = value;
|
||||
|
|
|
@ -154,7 +154,7 @@ pub enum Instruction {
|
|||
MOVEtoCCR(Target),
|
||||
MOVEC(Target, ControlRegister, Direction),
|
||||
MOVEM(Target, Size, Direction, u16),
|
||||
MOVEP(Register, Target, Size, Direction),
|
||||
MOVEP(Register, Register, i16, Size, Direction),
|
||||
MOVEQ(u8, Register),
|
||||
MOVEUSP(Target, Direction),
|
||||
MULW(Target, Register, Sign),
|
||||
|
@ -406,9 +406,9 @@ impl fmt::Display for Instruction {
|
|||
Direction::ToTarget => write!(f, "movem{}\t{}, {}", size, fmt_movem_mask(*mask), target),
|
||||
Direction::FromTarget => write!(f, "movem{}\t{}, {}", size, target, fmt_movem_mask(*mask)),
|
||||
},
|
||||
Instruction::MOVEP(reg, target, size, dir) => match dir {
|
||||
Direction::ToTarget => write!(f, "movep{}\t%d{}, {}", size, reg, target),
|
||||
Direction::FromTarget => write!(f, "movep{}\t{}, %d{}", size, target, reg),
|
||||
Instruction::MOVEP(dreg, areg, offset, size, dir) => match dir {
|
||||
Direction::ToTarget => write!(f, "movep{}\t%d{}, ({}, %a{})", size, dreg, areg, offset),
|
||||
Direction::FromTarget => write!(f, "movep{}\t({}, %a{}), %d{}", size, areg, offset, dreg),
|
||||
},
|
||||
Instruction::MOVEQ(value, reg) => write!(f, "moveq\t#{:02x}, %d{}", value, reg),
|
||||
Instruction::MOVEUSP(target, dir) => match dir {
|
||||
|
|
|
@ -490,6 +490,22 @@ mod execute_tests {
|
|||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x00000080, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000004, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2717 },
|
||||
},
|
||||
TestCase {
|
||||
name: "adda immediate",
|
||||
ins: Instruction::ADDA(Target::Immediate(0xF800), 0, Size::Word),
|
||||
data: &[ 0xD0FC, 0xF800 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x27FF },
|
||||
fini: TestState { pc: 0x00000004, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0xFFFFF800, a1: 0x00000000, sr: 0x27FF },
|
||||
},
|
||||
TestCase {
|
||||
name: "adda register",
|
||||
ins: Instruction::ADDA(Target::DirectDReg(0), 0, Size::Word),
|
||||
data: &[ 0xD0C0 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x0000F800, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x27FF },
|
||||
fini: TestState { pc: 0x00000002, msp: 0x00000000, usp: 0x00000000, d0: 0x0000F800, d1: 0x00000000, a0: 0xFFFFF800, a1: 0x00000000, sr: 0x27FF },
|
||||
},
|
||||
TestCase {
|
||||
name: "andi with sr",
|
||||
ins: Instruction::ANDtoSR(0xF8FF),
|
||||
|
@ -530,6 +546,30 @@ mod execute_tests {
|
|||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000002, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
},
|
||||
TestCase {
|
||||
name: "bchg not zero",
|
||||
ins: Instruction::BCHG(Target::Immediate(7), Target::DirectDReg(1), Size::Long),
|
||||
data: &[ 0x0841, 0x0007 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x000000FF, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000004, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x0000007F, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
},
|
||||
TestCase {
|
||||
name: "bchg zero",
|
||||
ins: Instruction::BCHG(Target::Immediate(7), Target::DirectDReg(1), Size::Long),
|
||||
data: &[ 0x0841, 0x0007 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000004, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000080, a0: 0x00000000, a1: 0x00000000, sr: 0x2704 },
|
||||
},
|
||||
TestCase {
|
||||
name: "bra 8-bit",
|
||||
ins: Instruction::BRA(-32),
|
||||
data: &[ 0x60E0 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0xFFFFFFE2, msp: 0x00000000, usp: 0x00000000, d0: 0x00000000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
},
|
||||
TestCase {
|
||||
name: "cmpi equal",
|
||||
ins: Instruction::CMP(Target::Immediate(0x20), Target::DirectDReg(0), Size::Byte),
|
||||
|
@ -610,6 +650,38 @@ mod execute_tests {
|
|||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x00040000, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000004, msp: 0x00000000, usp: 0x00000000, d0: 0x007101C3, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
},
|
||||
TestCase {
|
||||
name: "eori",
|
||||
ins: Instruction::EOR(Target::DirectDReg(1), Target::DirectDReg(0), Size::Long),
|
||||
data: &[ 0xB380 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0xAAAA5555, d1: 0x55AA55AA, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000002, msp: 0x00000000, usp: 0x00000000, d0: 0xFF0000FF, d1: 0x55AA55AA, a0: 0x00000000, a1: 0x00000000, sr: 0x2708 },
|
||||
},
|
||||
TestCase {
|
||||
name: "exg",
|
||||
ins: Instruction::EXG(Target::DirectDReg(0), Target::DirectAReg(1)),
|
||||
data: &[ 0xC189 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x12345678, d1: 0x00000000, a0: 0x00000000, a1: 0x87654321, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000002, msp: 0x00000000, usp: 0x00000000, d0: 0x87654321, d1: 0x00000000, a0: 0x00000000, a1: 0x12345678, sr: 0x2700 },
|
||||
},
|
||||
TestCase {
|
||||
name: "ext",
|
||||
ins: Instruction::EXT(0, Size::Byte, Size::Word),
|
||||
data: &[ 0x4880 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x000000CB, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x27FF },
|
||||
fini: TestState { pc: 0x00000002, msp: 0x00000000, usp: 0x00000000, d0: 0x0000FFCB, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x27F8 },
|
||||
},
|
||||
TestCase {
|
||||
name: "ext",
|
||||
ins: Instruction::EXT(0, Size::Word, Size::Long),
|
||||
data: &[ 0x48C0 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x000000CB, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x27FF },
|
||||
fini: TestState { pc: 0x00000002, msp: 0x00000000, usp: 0x00000000, d0: 0x000000CB, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x27F0 },
|
||||
},
|
||||
TestCase {
|
||||
name: "muls",
|
||||
ins: Instruction::MULW(Target::Immediate(0x0276), 0, Sign::Signed),
|
||||
|
@ -618,6 +690,22 @@ mod execute_tests {
|
|||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0x00000200, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000004, msp: 0x00000000, usp: 0x00000000, d0: 0x0004ec00, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
},
|
||||
TestCase {
|
||||
name: "movel",
|
||||
ins: Instruction::MOVE(Target::DirectDReg(0), Target::DirectDReg(1), Size::Long),
|
||||
data: &[ 0x2200 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0xFEDCBA98, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000002, msp: 0x00000000, usp: 0x00000000, d0: 0xFEDCBA98, d1: 0xFEDCBA98, a0: 0x00000000, a1: 0x00000000, sr: 0x2708 },
|
||||
},
|
||||
TestCase {
|
||||
name: "movea",
|
||||
ins: Instruction::MOVEA(Target::DirectDReg(0), 0, Size::Long),
|
||||
data: &[ 0x2040 ],
|
||||
cputype: M68kType::MC68010,
|
||||
init: TestState { pc: 0x00000000, msp: 0x00000000, usp: 0x00000000, d0: 0xFEDCBA98, d1: 0x00000000, a0: 0x00000000, a1: 0x00000000, sr: 0x2700 },
|
||||
fini: TestState { pc: 0x00000002, msp: 0x00000000, usp: 0x00000000, d0: 0xFEDCBA98, d1: 0x00000000, a0: 0xFEDCBA98, a1: 0x00000000, sr: 0x2700 },
|
||||
},
|
||||
TestCase {
|
||||
name: "neg",
|
||||
ins: Instruction::NEG(Target::DirectDReg(0), Size::Word),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use crate::error::Error;
|
||||
use crate::devices::{Address, Addressable};
|
||||
|
||||
use super::state::Register;
|
||||
use super::state::{Register, InterruptMode};
|
||||
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
|
@ -114,7 +114,7 @@ pub enum Instruction {
|
|||
EXhlde,
|
||||
EXsp(RegisterPair),
|
||||
HALT,
|
||||
IM(u8),
|
||||
IM(InterruptMode),
|
||||
INC16(RegisterPair),
|
||||
INC8(Target),
|
||||
IND,
|
||||
|
@ -453,7 +453,13 @@ impl Z80Decoder {
|
|||
}
|
||||
},
|
||||
6 => {
|
||||
Ok(Instruction::IM(get_ins_y(ins)))
|
||||
match get_ins_y(ins) & 0x03 {
|
||||
0 => Ok(Instruction::IM(InterruptMode::Mode0)),
|
||||
1 => Ok(Instruction::IM(InterruptMode::Mode01)),
|
||||
2 => Ok(Instruction::IM(InterruptMode::Mode1)),
|
||||
3 => Ok(Instruction::IM(InterruptMode::Mode2)),
|
||||
_ => panic!("InternalError: impossible value"),
|
||||
}
|
||||
},
|
||||
7 => {
|
||||
match get_ins_y(ins) {
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::system::System;
|
|||
use crate::error::{ErrorType, Error};
|
||||
use crate::devices::{ClockElapsed, Address, Steppable, Addressable, Interruptable, Debuggable, Transmutable, read_beu16, write_beu16};
|
||||
|
||||
use super::decode::{Condition, Instruction, LoadTarget, Target, RegisterPair, IndexRegister, IndexRegisterHalf, Size};
|
||||
use super::decode::{Condition, Instruction, LoadTarget, Target, RegisterPair, IndexRegister, SpecialRegister, IndexRegisterHalf, Size, Direction};
|
||||
use super::state::{Z80, Status, Flags, Register};
|
||||
|
||||
|
||||
|
@ -22,7 +22,11 @@ enum RotateType {
|
|||
|
||||
impl Steppable for Z80 {
|
||||
fn step(&mut self, system: &System) -> Result<ClockElapsed, Error> {
|
||||
self.step_internal(system)?;
|
||||
if self.reset.get() {
|
||||
self.reset();
|
||||
} else if !self.bus_request.get() {
|
||||
self.step_internal(system)?;
|
||||
}
|
||||
Ok((1_000_000_000 / self.frequency as u64) * 4)
|
||||
}
|
||||
|
||||
|
@ -258,8 +262,9 @@ impl Z80 {
|
|||
Instruction::HALT => {
|
||||
self.state.status = Status::Halted;
|
||||
},
|
||||
//Instruction::IM(u8) => {
|
||||
//},
|
||||
Instruction::IM(mode) => {
|
||||
self.state.interrupt_mode = mode;
|
||||
},
|
||||
Instruction::INC16(regpair) => {
|
||||
let value = self.get_register_pair_value(regpair);
|
||||
|
||||
|
@ -313,8 +318,17 @@ impl Z80 {
|
|||
let src_value = self.get_load_target_value(src)?;
|
||||
self.set_load_target_value(dest, src_value)?;
|
||||
},
|
||||
//Instruction::LDsr(special_reg, dir) => {
|
||||
//}
|
||||
Instruction::LDsr(special_reg, dir) => {
|
||||
let addr = match special_reg {
|
||||
SpecialRegister::I => &mut self.state.i,
|
||||
SpecialRegister::R => &mut self.state.r,
|
||||
};
|
||||
|
||||
match dir {
|
||||
Direction::FromAcc => { *addr = self.state.reg[Register::A as usize]; },
|
||||
Direction::ToAcc => { self.state.reg[Register::A as usize] = *addr; },
|
||||
}
|
||||
}
|
||||
//Instruction::LDD => {
|
||||
//},
|
||||
//Instruction::LDDR => {
|
||||
|
@ -642,8 +656,6 @@ impl Z80 {
|
|||
let addr = self.get_register_pair_value(regpair);
|
||||
self.port.read_leu16(addr as Address)?
|
||||
},
|
||||
//LoadTarget::DirectAltRegByte(reg),
|
||||
//LoadTarget::DirectSpecialRegByte(reg),
|
||||
LoadTarget::IndirectByte(addr) => {
|
||||
self.port.read_u8(addr as Address)? as u16
|
||||
},
|
||||
|
@ -674,8 +686,6 @@ impl Z80 {
|
|||
let addr = self.get_register_pair_value(regpair);
|
||||
self.port.write_leu16(addr as Address, value)?;
|
||||
},
|
||||
//LoadTarget::DirectAltRegByte(reg),
|
||||
//LoadTarget::DirectSpecialRegByte(reg),
|
||||
LoadTarget::IndirectByte(addr) => {
|
||||
self.port.write_u8(addr as Address, value as u8)?;
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
use crate::devices::Address;
|
||||
use crate::memory::BusPort;
|
||||
use crate::signals::Signal;
|
||||
|
||||
use super::decode::Z80Decoder;
|
||||
use super::debugger::Z80Debugger;
|
||||
|
@ -20,6 +21,14 @@ pub enum Status {
|
|||
}
|
||||
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum InterruptMode {
|
||||
Mode0,
|
||||
Mode01,
|
||||
Mode1,
|
||||
Mode2,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
|
@ -52,6 +61,7 @@ pub enum Register {
|
|||
pub struct Z80State {
|
||||
pub status: Status,
|
||||
pub interrupts_enabled: bool,
|
||||
pub interrupt_mode: InterruptMode,
|
||||
|
||||
pub pc: u16,
|
||||
pub sp: u16,
|
||||
|
@ -70,6 +80,7 @@ impl Z80State {
|
|||
Self {
|
||||
status: Status::Init,
|
||||
interrupts_enabled: false,
|
||||
interrupt_mode: InterruptMode::Mode0,
|
||||
|
||||
pc: 0,
|
||||
sp: 0,
|
||||
|
@ -100,6 +111,8 @@ pub struct Z80 {
|
|||
pub decoder: Z80Decoder,
|
||||
pub debugger: Z80Debugger,
|
||||
pub port: BusPort,
|
||||
pub reset: Signal<bool>,
|
||||
pub bus_request: Signal<bool>,
|
||||
}
|
||||
|
||||
impl Z80 {
|
||||
|
@ -111,6 +124,8 @@ impl Z80 {
|
|||
decoder: Z80Decoder::new(),
|
||||
debugger: Z80Debugger::new(),
|
||||
port: port,
|
||||
reset: Signal::new(false),
|
||||
bus_request: Signal::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user