2021-10-02 02:27:05 +00:00
|
|
|
|
|
|
|
use crate::memory::{Address, AddressSpace, MemoryBlock};
|
|
|
|
|
|
|
|
use super::execute::MC68010;
|
2021-10-03 16:55:20 +00:00
|
|
|
use super::decode::{Instruction, Target, Size, Sign};
|
2021-10-02 02:27:05 +00:00
|
|
|
|
|
|
|
const INIT_STACK: Address = 0x00002000;
|
|
|
|
const INIT_ADDR: Address = 0x00000010;
|
|
|
|
|
|
|
|
fn init_test() -> (MC68010, AddressSpace) {
|
|
|
|
let mut space = AddressSpace::new();
|
|
|
|
|
|
|
|
// Insert basic initialization
|
|
|
|
let mut data = vec![0; 0x00100000];
|
|
|
|
let mem = MemoryBlock::new(data);
|
|
|
|
space.insert(0x00000000, Box::new(mem));
|
|
|
|
space.write_beu32(0, INIT_STACK as u32).unwrap();
|
|
|
|
space.write_beu32(4, INIT_ADDR as u32).unwrap();
|
|
|
|
|
|
|
|
let mut cpu = MC68010::new();
|
|
|
|
cpu.step(&mut space).unwrap();
|
2021-10-02 15:47:20 +00:00
|
|
|
assert_eq!(cpu.state.pc, INIT_ADDR as u32);
|
|
|
|
assert_eq!(cpu.state.msp, INIT_STACK as u32);
|
|
|
|
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
|
2021-10-02 02:27:05 +00:00
|
|
|
(cpu, space)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::{init_test, INIT_ADDR};
|
2021-10-03 16:55:20 +00:00
|
|
|
use super::{Instruction, Target, Size, Sign};
|
2021-10-02 02:27:05 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn instruction_nop() {
|
|
|
|
let (mut cpu, mut space) = init_test();
|
|
|
|
|
|
|
|
space.write_beu16(INIT_ADDR, 0x4e71).unwrap();
|
|
|
|
cpu.decode_next(&mut space).unwrap();
|
2021-10-02 15:47:20 +00:00
|
|
|
assert_eq!(cpu.decoder.instruction, Instruction::NOP);
|
2021-10-02 02:27:05 +00:00
|
|
|
cpu.execute_current(&mut space).unwrap();
|
|
|
|
// TODO you need a way to easily check the entire state (you maybe need to make a special struct for the state)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn instruction_ori() {
|
|
|
|
let (mut cpu, mut space) = init_test();
|
|
|
|
|
|
|
|
space.write_beu16(INIT_ADDR, 0x0008).unwrap();
|
|
|
|
space.write_beu16(INIT_ADDR + 2, 0x00FF).unwrap();
|
|
|
|
cpu.decode_next(&mut space).unwrap();
|
2021-10-02 15:47:20 +00:00
|
|
|
assert_eq!(cpu.decoder.instruction, Instruction::OR(Target::Immediate(0xFF), Target::DirectAReg(0), Size::Byte));
|
2021-10-02 02:27:05 +00:00
|
|
|
cpu.execute_current(&mut space).unwrap();
|
2021-10-02 15:47:20 +00:00
|
|
|
assert_eq!(cpu.state.a_reg[0], 0x000000FF);
|
2021-10-02 02:27:05 +00:00
|
|
|
}
|
2021-10-02 22:35:08 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn instruction_cmpi_equal() {
|
|
|
|
let (mut cpu, mut space) = init_test();
|
|
|
|
|
|
|
|
space.write_beu16(INIT_ADDR, 0x7020).unwrap();
|
|
|
|
space.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
|
|
|
|
space.write_beu16(INIT_ADDR + 4, 0x0020).unwrap();
|
|
|
|
cpu.step(&mut space).unwrap();
|
|
|
|
cpu.decode_next(&mut space).unwrap();
|
|
|
|
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x20), Target::DirectDReg(0), Size::Byte));
|
|
|
|
cpu.execute_current(&mut space).unwrap();
|
|
|
|
assert_eq!(cpu.state.sr & 0x0F, 0x04);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn instruction_cmpi_greater() {
|
|
|
|
let (mut cpu, mut space) = init_test();
|
|
|
|
|
|
|
|
space.write_beu16(INIT_ADDR, 0x7020).unwrap();
|
|
|
|
space.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
|
|
|
|
space.write_beu16(INIT_ADDR + 4, 0x0030).unwrap();
|
|
|
|
cpu.step(&mut space).unwrap();
|
|
|
|
cpu.decode_next(&mut space).unwrap();
|
|
|
|
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x30), Target::DirectDReg(0), Size::Byte));
|
|
|
|
cpu.execute_current(&mut space).unwrap();
|
|
|
|
assert_eq!(cpu.state.sr & 0x0F, 0x00B);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn instruction_cmpi_less() {
|
|
|
|
let (mut cpu, mut space) = init_test();
|
|
|
|
|
|
|
|
space.write_beu16(INIT_ADDR, 0x7020).unwrap();
|
|
|
|
space.write_beu16(INIT_ADDR + 2, 0x0C00).unwrap();
|
|
|
|
space.write_beu16(INIT_ADDR + 4, 0x0010).unwrap();
|
|
|
|
cpu.step(&mut space).unwrap();
|
|
|
|
cpu.decode_next(&mut space).unwrap();
|
|
|
|
assert_eq!(cpu.decoder.instruction, Instruction::CMP(Target::Immediate(0x10), Target::DirectDReg(0), Size::Byte));
|
|
|
|
cpu.execute_current(&mut space).unwrap();
|
|
|
|
assert_eq!(cpu.state.sr & 0x0F, 0x00);
|
|
|
|
}
|
Added MUL, DIV, NEG, DBcc, and Scc instructions, and fixed issue with ADD/SUB flags
With ADDA, SUBA, and ADDQ/SUBQ when the target is an address register, the condition
flags should not be changed, but the code was changing them, which caused problems.
I've fixed it by making the ADD/SUB executions check for an address target and
will not update flags in that case. This should only occur when the actual instruction
was an ADDA or ADDQ with an address register target
2021-10-03 04:59:28 +00:00
|
|
|
|
|
|
|
#[test]
|
2021-10-03 16:55:20 +00:00
|
|
|
fn instruction_andi_sr() {
|
Added MUL, DIV, NEG, DBcc, and Scc instructions, and fixed issue with ADD/SUB flags
With ADDA, SUBA, and ADDQ/SUBQ when the target is an address register, the condition
flags should not be changed, but the code was changing them, which caused problems.
I've fixed it by making the ADD/SUB executions check for an address target and
will not update flags in that case. This should only occur when the actual instruction
was an ADDA or ADDQ with an address register target
2021-10-03 04:59:28 +00:00
|
|
|
let (mut cpu, mut space) = init_test();
|
|
|
|
|
2021-10-03 16:55:20 +00:00
|
|
|
space.write_beu16(INIT_ADDR, 0x027C).unwrap();
|
|
|
|
space.write_beu16(INIT_ADDR + 2, 0xF8FF).unwrap();
|
Added MUL, DIV, NEG, DBcc, and Scc instructions, and fixed issue with ADD/SUB flags
With ADDA, SUBA, and ADDQ/SUBQ when the target is an address register, the condition
flags should not be changed, but the code was changing them, which caused problems.
I've fixed it by making the ADD/SUB executions check for an address target and
will not update flags in that case. This should only occur when the actual instruction
was an ADDA or ADDQ with an address register target
2021-10-03 04:59:28 +00:00
|
|
|
cpu.decode_next(&mut space).unwrap();
|
2021-10-03 16:55:20 +00:00
|
|
|
assert_eq!(cpu.decoder.instruction, Instruction::ANDtoSR(0xF8FF));
|
|
|
|
//cpu.execute_current(&mut space).unwrap();
|
|
|
|
//assert_eq!(cpu.state.sr & 0x0F, 0x00);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn instruction_muls() {
|
|
|
|
let (mut cpu, mut space) = init_test();
|
|
|
|
|
|
|
|
space.write_beu16(INIT_ADDR, 0xC1FC).unwrap();
|
|
|
|
space.write_beu16(INIT_ADDR + 2, 0x0276).unwrap();
|
|
|
|
cpu.decode_next(&mut space).unwrap();
|
|
|
|
assert_eq!(cpu.decoder.instruction, Instruction::MUL(Target::Immediate(0x276), Target::DirectDReg(0), Size::Word, Sign::Signed));
|
Added MUL, DIV, NEG, DBcc, and Scc instructions, and fixed issue with ADD/SUB flags
With ADDA, SUBA, and ADDQ/SUBQ when the target is an address register, the condition
flags should not be changed, but the code was changing them, which caused problems.
I've fixed it by making the ADD/SUB executions check for an address target and
will not update flags in that case. This should only occur when the actual instruction
was an ADDA or ADDQ with an address register target
2021-10-03 04:59:28 +00:00
|
|
|
//cpu.execute_current(&mut space).unwrap();
|
|
|
|
//assert_eq!(cpu.state.sr & 0x0F, 0x00);
|
|
|
|
}
|
2021-10-02 02:27:05 +00:00
|
|
|
}
|
|
|
|
|