mirror of
https://github.com/transistorfet/moa.git
synced 2025-04-21 17:37:11 +00:00
Fixed some Z80 instruction timings
This commit is contained in:
parent
cbcfb26f49
commit
f9d613b3b9
@ -8,6 +8,7 @@ pub struct Z80Decoder {
|
||||
pub clock: ClockTime,
|
||||
pub start: u16,
|
||||
pub end: u16,
|
||||
pub extra_instruction_bytes: u16,
|
||||
pub instruction: Instruction,
|
||||
}
|
||||
|
||||
@ -17,6 +18,7 @@ impl Default for Z80Decoder {
|
||||
clock: ClockTime::START,
|
||||
start: 0,
|
||||
end: 0,
|
||||
extra_instruction_bytes: 0,
|
||||
instruction: Instruction::NOP,
|
||||
}
|
||||
}
|
||||
@ -27,16 +29,18 @@ impl Z80Decoder {
|
||||
self.clock = clock;
|
||||
self.start = start;
|
||||
self.end = start;
|
||||
self.extra_instruction_bytes = 0;
|
||||
self.instruction = self.decode_one(memory)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_one(&mut self, memory: &mut dyn Addressable) -> Result<Instruction, Error> {
|
||||
let ins = self.read_instruction_byte(memory)?;
|
||||
self.decode_bare(memory, ins)
|
||||
self.decode_bare(memory, ins, 0)
|
||||
}
|
||||
|
||||
pub fn decode_bare(&mut self, memory: &mut dyn Addressable, ins: u8) -> Result<Instruction, Error> {
|
||||
pub fn decode_bare(&mut self, memory: &mut dyn Addressable, ins: u8, extra_instruction_bytes: u16) -> Result<Instruction, Error> {
|
||||
self.extra_instruction_bytes = extra_instruction_bytes;
|
||||
match get_ins_x(ins) {
|
||||
0 => {
|
||||
match get_ins_z(ins) {
|
||||
@ -371,19 +375,22 @@ impl Z80Decoder {
|
||||
}
|
||||
},
|
||||
4 => {
|
||||
self.extra_instruction_bytes = 4;
|
||||
let half_target = Target::DirectRegHalf(get_index_register_half(index_reg, get_ins_q(ins)));
|
||||
Ok(Instruction::INC8(half_target))
|
||||
},
|
||||
5 => {
|
||||
self.extra_instruction_bytes = 4;
|
||||
let half_target = Target::DirectRegHalf(get_index_register_half(index_reg, get_ins_q(ins)));
|
||||
Ok(Instruction::DEC8(half_target))
|
||||
},
|
||||
6 => {
|
||||
self.extra_instruction_bytes = 4;
|
||||
let half_target = Target::DirectRegHalf(get_index_register_half(index_reg, get_ins_q(ins)));
|
||||
let data = self.read_instruction_byte(memory)?;
|
||||
Ok(Instruction::LD(to_load_target(half_target), LoadTarget::ImmediateByte(data)))
|
||||
},
|
||||
_ => self.decode_bare(memory, ins),
|
||||
_ => self.decode_bare(memory, ins, 4),
|
||||
}
|
||||
},
|
||||
3 => {
|
||||
@ -401,10 +408,10 @@ impl Z80Decoder {
|
||||
let immediate = self.read_instruction_byte(memory)?;
|
||||
Ok(Instruction::LD(LoadTarget::IndirectOffsetByte(index_reg, offset), LoadTarget::ImmediateByte(immediate)))
|
||||
},
|
||||
_ => self.decode_bare(memory, ins),
|
||||
_ => self.decode_bare(memory, ins, 4),
|
||||
}
|
||||
},
|
||||
_ => self.decode_bare(memory, ins),
|
||||
_ => self.decode_bare(memory, ins, 4),
|
||||
}
|
||||
},
|
||||
1 => {
|
||||
@ -412,7 +419,7 @@ impl Z80Decoder {
|
||||
0 | 1 => {
|
||||
let target = match self.decode_index_target(memory, index_reg, get_ins_z(ins))? {
|
||||
Some(target) => target,
|
||||
None => return self.decode_bare(memory, ins),
|
||||
None => return self.decode_bare(memory, ins, 4),
|
||||
};
|
||||
|
||||
match (ins & 0x18) >> 3 {
|
||||
@ -450,7 +457,7 @@ impl Z80Decoder {
|
||||
3 => {
|
||||
if get_ins_q(ins) == 0 {
|
||||
if get_ins_z(ins) == 6 {
|
||||
return self.decode_bare(memory, ins);
|
||||
return self.decode_bare(memory, ins, 4);
|
||||
}
|
||||
let src = get_register(get_ins_z(ins));
|
||||
let offset = self.read_instruction_byte(memory)? as i8;
|
||||
@ -458,7 +465,7 @@ impl Z80Decoder {
|
||||
} else {
|
||||
let target = match self.decode_index_target(memory, index_reg, get_ins_z(ins))? {
|
||||
Some(target) => target,
|
||||
None => return self.decode_bare(memory, ins),
|
||||
None => return self.decode_bare(memory, ins, 4),
|
||||
};
|
||||
|
||||
Ok(Instruction::LD(LoadTarget::DirectRegByte(Register::A), to_load_target(target)))
|
||||
@ -468,12 +475,13 @@ impl Z80Decoder {
|
||||
}
|
||||
},
|
||||
2 => {
|
||||
self.extra_instruction_bytes = 4;
|
||||
|
||||
let target = match self.decode_index_target(memory, index_reg, get_ins_z(ins))? {
|
||||
Some(target) => target,
|
||||
None => return self.decode_bare(memory, ins),
|
||||
None => return self.decode_bare(memory, ins, 4),
|
||||
};
|
||||
|
||||
|
||||
match get_ins_y(ins) {
|
||||
0 => Ok(Instruction::ADDa(target)),
|
||||
1 => Ok(Instruction::ADCa(target)),
|
||||
@ -493,7 +501,7 @@ impl Z80Decoder {
|
||||
0xE5 => Ok(Instruction::PUSH(index_reg.into())),
|
||||
0xE9 => Ok(Instruction::JPIndirect(index_reg.into())),
|
||||
0xF9 => Ok(Instruction::LD(LoadTarget::DirectRegWord(RegisterPair::SP), LoadTarget::DirectRegWord(index_reg.into()))),
|
||||
_ => self.decode_bare(memory, ins),
|
||||
_ => self.decode_bare(memory, ins, 4),
|
||||
}
|
||||
},
|
||||
_ => panic!("InternalError: impossible value"),
|
||||
|
@ -103,7 +103,7 @@ impl Z80 {
|
||||
|
||||
self.decode_next()?;
|
||||
self.execute_current()?;
|
||||
Ok(Z80InstructionCycles::from_instruction(&self.decoder.instruction)?
|
||||
Ok(Z80InstructionCycles::from_instruction(&self.decoder.instruction, self.decoder.extra_instruction_bytes)?
|
||||
.calculate_cycles(self.executor.took_branch))
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ impl Z80InstructionCycles {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_instruction(instruction: &Instruction) -> Result<Z80InstructionCycles, Error> {
|
||||
pub fn from_instruction(instruction: &Instruction, extra: u16) -> Result<Z80InstructionCycles, Error> {
|
||||
let cycles = match instruction {
|
||||
Instruction::ADCa(target) |
|
||||
Instruction::ADDa(target) |
|
||||
@ -37,7 +37,6 @@ impl Z80InstructionCycles {
|
||||
Instruction::OR(target) |
|
||||
Instruction::XOR(target) => {
|
||||
match target {
|
||||
// TODO the undocumented DD version of this instruction is actually 8 cycles
|
||||
Target::DirectReg(_) |
|
||||
Target::DirectRegHalf(_) => 4,
|
||||
Target::IndirectReg(_) => 7,
|
||||
@ -70,8 +69,8 @@ impl Z80InstructionCycles {
|
||||
|
||||
Instruction::CALLcc(_, _) => {
|
||||
return Ok(Z80InstructionCycles::Branch {
|
||||
taken: 17,
|
||||
not_taken: 10,
|
||||
taken: 17 + extra,
|
||||
not_taken: 10 + extra,
|
||||
});
|
||||
},
|
||||
|
||||
@ -95,8 +94,8 @@ impl Z80InstructionCycles {
|
||||
Instruction::OTDR |
|
||||
Instruction::OTIR => {
|
||||
return Ok(Z80InstructionCycles::Repeating {
|
||||
repeating: 21,
|
||||
terminating: 16,
|
||||
repeating: 21 + extra,
|
||||
terminating: 16 + extra,
|
||||
})
|
||||
},
|
||||
|
||||
@ -105,7 +104,6 @@ impl Z80InstructionCycles {
|
||||
|
||||
Instruction::DEC8(target) |
|
||||
Instruction::INC8(target) => {
|
||||
// TODO the undocumented DD version of this instruction is actually 8 cycles
|
||||
match target {
|
||||
Target::DirectReg(_) |
|
||||
Target::DirectRegHalf(_) => 4,
|
||||
@ -129,8 +127,8 @@ impl Z80InstructionCycles {
|
||||
|
||||
Instruction::DJNZ(_) => {
|
||||
return Ok(Z80InstructionCycles::Branch {
|
||||
taken: 13,
|
||||
not_taken: 8,
|
||||
taken: 13 + extra,
|
||||
not_taken: 8 + extra,
|
||||
});
|
||||
},
|
||||
|
||||
@ -171,13 +169,12 @@ impl Z80InstructionCycles {
|
||||
|
||||
Instruction::JRcc(_, _) => {
|
||||
return Ok(Z80InstructionCycles::Branch {
|
||||
taken: 12,
|
||||
not_taken: 7,
|
||||
taken: 12 + extra,
|
||||
not_taken: 7 + extra,
|
||||
});
|
||||
},
|
||||
|
||||
Instruction::LD(dest, src) => {
|
||||
// TODO the undocumented DD version of this instruction is actually 8 cycles
|
||||
match (dest, src) {
|
||||
// 8-Bit Operations
|
||||
|
||||
@ -265,8 +262,8 @@ impl Z80InstructionCycles {
|
||||
|
||||
Instruction::RETcc(_) => {
|
||||
return Ok(Z80InstructionCycles::Branch {
|
||||
taken: 11,
|
||||
not_taken: 5,
|
||||
taken: 11 + extra,
|
||||
not_taken: 5 + extra,
|
||||
});
|
||||
},
|
||||
|
||||
@ -298,7 +295,7 @@ impl Z80InstructionCycles {
|
||||
|
||||
Instruction::SCF => 4,
|
||||
};
|
||||
Ok(Z80InstructionCycles::Single(cycles))
|
||||
Ok(Z80InstructionCycles::Single(cycles + extra))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
Last run on 2023-05-22 at commit 8c1a89a1fe788fc614c319e167372d47cb869417
|
||||
Last run on 2023-06-10 at commit cbcfb26f49c23414fe00317fddc65ffcbb087b18
|
||||
|
||||
00.json completed, all passed!
|
||||
01.json completed, all passed!
|
||||
@ -614,7 +614,7 @@ dd 82.json completed, all passed!
|
||||
dd 83.json completed, all passed!
|
||||
dd 84.json completed, all passed!
|
||||
dd 85.json completed, all passed!
|
||||
dd 86.json completed, all passed!
|
||||
dd 86.json completed: 0 passed, 1000 FAILED
|
||||
dd 87.json completed, all passed!
|
||||
dd 88.json completed, all passed!
|
||||
dd 89.json completed, all passed!
|
||||
@ -622,7 +622,7 @@ dd 8a.json completed, all passed!
|
||||
dd 8b.json completed, all passed!
|
||||
dd 8c.json completed, all passed!
|
||||
dd 8d.json completed, all passed!
|
||||
dd 8e.json completed, all passed!
|
||||
dd 8e.json completed: 0 passed, 1000 FAILED
|
||||
dd 8f.json completed, all passed!
|
||||
dd 90.json completed, all passed!
|
||||
dd 91.json completed, all passed!
|
||||
@ -630,7 +630,7 @@ dd 92.json completed, all passed!
|
||||
dd 93.json completed, all passed!
|
||||
dd 94.json completed, all passed!
|
||||
dd 95.json completed, all passed!
|
||||
dd 96.json completed, all passed!
|
||||
dd 96.json completed: 0 passed, 1000 FAILED
|
||||
dd 97.json completed, all passed!
|
||||
dd 98.json completed, all passed!
|
||||
dd 99.json completed, all passed!
|
||||
@ -638,7 +638,7 @@ dd 9a.json completed, all passed!
|
||||
dd 9b.json completed, all passed!
|
||||
dd 9c.json completed, all passed!
|
||||
dd 9d.json completed, all passed!
|
||||
dd 9e.json completed, all passed!
|
||||
dd 9e.json completed: 0 passed, 1000 FAILED
|
||||
dd 9f.json completed, all passed!
|
||||
dd a0.json completed, all passed!
|
||||
dd a1.json completed, all passed!
|
||||
@ -646,7 +646,7 @@ dd a2.json completed, all passed!
|
||||
dd a3.json completed, all passed!
|
||||
dd a4.json completed, all passed!
|
||||
dd a5.json completed, all passed!
|
||||
dd a6.json completed, all passed!
|
||||
dd a6.json completed: 0 passed, 1000 FAILED
|
||||
dd a7.json completed, all passed!
|
||||
dd a8.json completed, all passed!
|
||||
dd a9.json completed, all passed!
|
||||
@ -654,7 +654,7 @@ dd aa.json completed, all passed!
|
||||
dd ab.json completed, all passed!
|
||||
dd ac.json completed, all passed!
|
||||
dd ad.json completed, all passed!
|
||||
dd ae.json completed, all passed!
|
||||
dd ae.json completed: 0 passed, 1000 FAILED
|
||||
dd af.json completed, all passed!
|
||||
dd b0.json completed, all passed!
|
||||
dd b1.json completed, all passed!
|
||||
@ -662,7 +662,7 @@ dd b2.json completed, all passed!
|
||||
dd b3.json completed, all passed!
|
||||
dd b4.json completed, all passed!
|
||||
dd b5.json completed, all passed!
|
||||
dd b6.json completed, all passed!
|
||||
dd b6.json completed: 0 passed, 1000 FAILED
|
||||
dd b7.json completed, all passed!
|
||||
dd b8.json completed, all passed!
|
||||
dd b9.json completed, all passed!
|
||||
@ -670,7 +670,7 @@ dd ba.json completed, all passed!
|
||||
dd bb.json completed, all passed!
|
||||
dd bc.json completed, all passed!
|
||||
dd bd.json completed, all passed!
|
||||
dd be.json completed, all passed!
|
||||
dd be.json completed: 0 passed, 1000 FAILED
|
||||
dd bf.json completed, all passed!
|
||||
dd c0.json completed, all passed!
|
||||
dd c1.json completed, all passed!
|
||||
@ -1038,7 +1038,7 @@ ed 5f.json completed, all passed!
|
||||
ed 60.json completed, all passed!
|
||||
ed 61.json completed, all passed!
|
||||
ed 62.json completed, all passed!
|
||||
ed 63.json completed, all passed!
|
||||
ed 63.json completed: 0 passed, 1000 FAILED
|
||||
ed 64.json completed, all passed!
|
||||
ed 65.json completed, all passed!
|
||||
ed 66.json completed, all passed!
|
||||
@ -1046,7 +1046,7 @@ ed 67.json completed, all passed!
|
||||
ed 68.json completed, all passed!
|
||||
ed 69.json completed, all passed!
|
||||
ed 6a.json completed, all passed!
|
||||
ed 6b.json completed, all passed!
|
||||
ed 6b.json completed: 0 passed, 1000 FAILED
|
||||
ed 6c.json completed, all passed!
|
||||
ed 6d.json completed, all passed!
|
||||
ed 6e.json completed, all passed!
|
||||
@ -1058,7 +1058,7 @@ ed 73.json completed, all passed!
|
||||
ed 74.json completed, all passed!
|
||||
ed 75.json completed, all passed!
|
||||
ed 76.json completed, all passed!
|
||||
ed 77.json completed, all passed!
|
||||
ed 77.json completed: 0 passed, 1000 FAILED
|
||||
ed 78.json completed, all passed!
|
||||
ed 79.json completed, all passed!
|
||||
ed 7a.json completed, all passed!
|
||||
@ -1066,7 +1066,7 @@ ed 7b.json completed, all passed!
|
||||
ed 7c.json completed, all passed!
|
||||
ed 7d.json completed, all passed!
|
||||
ed 7e.json completed, all passed!
|
||||
ed 7f.json completed, all passed!
|
||||
ed 7f.json completed: 0 passed, 1000 FAILED
|
||||
ed a0.json completed, all passed!
|
||||
ed a1.json completed: 0 passed, 1000 FAILED
|
||||
ed a2.json completed: 13 passed, 987 FAILED
|
||||
@ -1234,7 +1234,7 @@ fd 82.json completed, all passed!
|
||||
fd 83.json completed, all passed!
|
||||
fd 84.json completed, all passed!
|
||||
fd 85.json completed, all passed!
|
||||
fd 86.json completed, all passed!
|
||||
fd 86.json completed: 0 passed, 1000 FAILED
|
||||
fd 87.json completed, all passed!
|
||||
fd 88.json completed, all passed!
|
||||
fd 89.json completed, all passed!
|
||||
@ -1242,7 +1242,7 @@ fd 8a.json completed, all passed!
|
||||
fd 8b.json completed, all passed!
|
||||
fd 8c.json completed, all passed!
|
||||
fd 8d.json completed, all passed!
|
||||
fd 8e.json completed, all passed!
|
||||
fd 8e.json completed: 0 passed, 1000 FAILED
|
||||
fd 8f.json completed, all passed!
|
||||
fd 90.json completed, all passed!
|
||||
fd 91.json completed, all passed!
|
||||
@ -1250,7 +1250,7 @@ fd 92.json completed, all passed!
|
||||
fd 93.json completed, all passed!
|
||||
fd 94.json completed, all passed!
|
||||
fd 95.json completed, all passed!
|
||||
fd 96.json completed, all passed!
|
||||
fd 96.json completed: 0 passed, 1000 FAILED
|
||||
fd 97.json completed, all passed!
|
||||
fd 98.json completed, all passed!
|
||||
fd 99.json completed, all passed!
|
||||
@ -1258,7 +1258,7 @@ fd 9a.json completed, all passed!
|
||||
fd 9b.json completed, all passed!
|
||||
fd 9c.json completed, all passed!
|
||||
fd 9d.json completed, all passed!
|
||||
fd 9e.json completed, all passed!
|
||||
fd 9e.json completed: 0 passed, 1000 FAILED
|
||||
fd 9f.json completed, all passed!
|
||||
fd a0.json completed, all passed!
|
||||
fd a1.json completed, all passed!
|
||||
@ -1266,7 +1266,7 @@ fd a2.json completed, all passed!
|
||||
fd a3.json completed, all passed!
|
||||
fd a4.json completed, all passed!
|
||||
fd a5.json completed, all passed!
|
||||
fd a6.json completed, all passed!
|
||||
fd a6.json completed: 0 passed, 1000 FAILED
|
||||
fd a7.json completed, all passed!
|
||||
fd a8.json completed, all passed!
|
||||
fd a9.json completed, all passed!
|
||||
@ -1274,7 +1274,7 @@ fd aa.json completed, all passed!
|
||||
fd ab.json completed, all passed!
|
||||
fd ac.json completed, all passed!
|
||||
fd ad.json completed, all passed!
|
||||
fd ae.json completed, all passed!
|
||||
fd ae.json completed: 0 passed, 1000 FAILED
|
||||
fd af.json completed, all passed!
|
||||
fd b0.json completed, all passed!
|
||||
fd b1.json completed, all passed!
|
||||
@ -1282,7 +1282,7 @@ fd b2.json completed, all passed!
|
||||
fd b3.json completed, all passed!
|
||||
fd b4.json completed, all passed!
|
||||
fd b5.json completed, all passed!
|
||||
fd b6.json completed, all passed!
|
||||
fd b6.json completed: 0 passed, 1000 FAILED
|
||||
fd b7.json completed, all passed!
|
||||
fd b8.json completed, all passed!
|
||||
fd b9.json completed, all passed!
|
||||
@ -1290,7 +1290,7 @@ fd ba.json completed, all passed!
|
||||
fd bb.json completed, all passed!
|
||||
fd bc.json completed, all passed!
|
||||
fd bd.json completed, all passed!
|
||||
fd be.json completed, all passed!
|
||||
fd be.json completed: 0 passed, 1000 FAILED
|
||||
fd bf.json completed, all passed!
|
||||
fd c0.json completed, all passed!
|
||||
fd c1.json completed, all passed!
|
||||
@ -1611,5 +1611,5 @@ fd ff.json completed, all passed!
|
||||
fe.json completed, all passed!
|
||||
ff.json completed, all passed!
|
||||
|
||||
passed: 1594638, failed: 15362, total 99%
|
||||
completed in 1m 39s
|
||||
passed: 1574638, failed: 35362, total 98%
|
||||
completed in 1m 19s
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,5 +7,5 @@ RESULTS=latest.txt
|
||||
cd $LOCATION
|
||||
echo "Last run on $DATE at commit $COMMIT" | tee $RESULTS
|
||||
echo "" | tee -a $RESULTS
|
||||
cargo run -- -q --testsuite "../jsmoo/misc/tests/GeneratedTests/z80/v1/" --check-undocumented | tee -a $RESULTS
|
||||
cargo run -- -q --testsuite "../jsmoo/misc/tests/GeneratedTests/z80/v1/" --check-undocumented --check-timings | tee -a $RESULTS
|
||||
}
|
||||
|
8
todo.txt
8
todo.txt
@ -6,16 +6,19 @@
|
||||
the cost of having more events on the queue when re-scheduling. There needs to be a mechanism to avoid the event queue ballooning due to
|
||||
an error
|
||||
* can you somehow make devices have two step functions for running things at different times? (I'm thinking ym2612 audio gen vs timers)
|
||||
* the genesis coprocessor stuff will be a good reference point for things that make multiple devices, and how to add them correctly to the system
|
||||
|
||||
* address repeater on ym2612 doesn't seem to work the same, when it's on the 68000 device. The Z80 device doesn't have an affect, but maybe it's not being used
|
||||
* I like making address adapters like this (below)
|
||||
* you could have busport take a closure or something which translates the address, and returns an error that will be passed up if it occurs
|
||||
in order to implement the correct behaviour for address exceptions in 68k, transparently
|
||||
|
||||
* make Signal directional, by making SignalDriver and SignalInput or SignalReceiver
|
||||
|
||||
|
||||
* fix the m68k timings
|
||||
* add rust runtime checks for math to look for overflow errors
|
||||
* fix the watchers in the Bus, maybe make them manual
|
||||
* make Signal directional, by making SignalDriver and SignalInput or SignalReceiver
|
||||
* the genesis coprocessor stuff will be a good reference point for things that make multiple devices, and how to add them correctly to the system
|
||||
* make it possible to compile without audio support (minifb frontend requires it atm)
|
||||
* does Z80 need a customized Z80BusPort like the 68k?
|
||||
* can you make it so you don't need borrow_mut() so much?
|
||||
@ -49,7 +52,6 @@
|
||||
* get rustfmt, rustdoc, and clippy working in some kind of semi-automatic fashion
|
||||
|
||||
* you really need a full web-based debugger
|
||||
* test m68k cycle timing again
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user