Update to v101r14 release.
byuu says:
Changelog:
- rewrote the Z80 core to properly handle 0xDD (IX0 and 0xFD (IY)
prefixes
- added Processor::Z80::Bus as a new type of abstraction
- all of the instructions implemented have their proper T-cycle counts
now
- added nall/certificates for my public keys
The goal of `Processor::Z80::Bus` is to simulate the opcode fetches being
2-read + 2-wait states; operand+regular reads/writes being 3-read. For
now, this puts the cycle counts inside the CPU core. At the moment, I
can't think of any CPU core where this wouldn't be appropriate. But it's
certainly possible that such a case exists. So this may not be the
perfect solution.
The reason for having it be a subclass of Processor::Z80 instead of
virtual functions for the MasterSystem::CPU core to define is due to
naming conflicts. I wanted the core to say `in(addr)` and have it take
the four clocks. But I also wanted a version of the function that didn't
consume time when called. One way to do that would be for the core to
call `Z80::in(addr)`, which then calls the regular `in(addr)` that goes to
`MasterSystem::CPU::in(addr)`. But I don't want to put the `Z80::`
prefix on all of the opcodes. Very easy to forget it, and then end up not
consuming any time. Another is to use uglier names in the
`MasterSystem::CPU` core, like `read_`, `write_`, `in_`, `out_`, etc. But,
yuck.
So ... yeah, this is an experiment. We'll see how it goes.
2016-09-03 11:26:04 +00:00
|
|
|
auto Z80::wait(uint clocks) -> void {
|
|
|
|
step(clocks);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Z80::opcode() -> uint8 {
|
|
|
|
step(4);
|
|
|
|
return bus->read(r.pc++);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Z80::operand() -> uint8 {
|
|
|
|
step(3);
|
|
|
|
return bus->read(r.pc++);
|
|
|
|
}
|
|
|
|
|
2016-09-06 00:09:33 +00:00
|
|
|
auto Z80::operands() -> uint16 {
|
|
|
|
uint16 data = operand() << 0;
|
|
|
|
return data | operand() << 8;
|
|
|
|
}
|
|
|
|
|
2016-10-31 21:10:33 +00:00
|
|
|
auto Z80::push(uint16 x) -> void {
|
|
|
|
write(--SP, x >> 8);
|
|
|
|
write(--SP, x >> 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Z80::pop() -> uint16 {
|
|
|
|
uint16 data = read(SP++) << 0;
|
|
|
|
return data | read(SP++) << 8;
|
|
|
|
}
|
|
|
|
|
2016-09-04 13:51:27 +00:00
|
|
|
auto Z80::displace(uint16& x) -> uint16 {
|
2016-09-06 13:53:14 +00:00
|
|
|
if(&x != &r.ix.word && &x != &r.iy.word) return x;
|
2016-09-04 13:51:27 +00:00
|
|
|
auto d = read(x);
|
|
|
|
wait(5);
|
|
|
|
return x + (int8)d;
|
|
|
|
}
|
|
|
|
|
Update to v101r14 release.
byuu says:
Changelog:
- rewrote the Z80 core to properly handle 0xDD (IX0 and 0xFD (IY)
prefixes
- added Processor::Z80::Bus as a new type of abstraction
- all of the instructions implemented have their proper T-cycle counts
now
- added nall/certificates for my public keys
The goal of `Processor::Z80::Bus` is to simulate the opcode fetches being
2-read + 2-wait states; operand+regular reads/writes being 3-read. For
now, this puts the cycle counts inside the CPU core. At the moment, I
can't think of any CPU core where this wouldn't be appropriate. But it's
certainly possible that such a case exists. So this may not be the
perfect solution.
The reason for having it be a subclass of Processor::Z80 instead of
virtual functions for the MasterSystem::CPU core to define is due to
naming conflicts. I wanted the core to say `in(addr)` and have it take
the four clocks. But I also wanted a version of the function that didn't
consume time when called. One way to do that would be for the core to
call `Z80::in(addr)`, which then calls the regular `in(addr)` that goes to
`MasterSystem::CPU::in(addr)`. But I don't want to put the `Z80::`
prefix on all of the opcodes. Very easy to forget it, and then end up not
consuming any time. Another is to use uglier names in the
`MasterSystem::CPU` core, like `read_`, `write_`, `in_`, `out_`, etc. But,
yuck.
So ... yeah, this is an experiment. We'll see how it goes.
2016-09-03 11:26:04 +00:00
|
|
|
auto Z80::read(uint16 addr) -> uint8 {
|
|
|
|
step(3);
|
|
|
|
return bus->read(addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Z80::write(uint16 addr, uint8 data) -> void {
|
|
|
|
step(3);
|
|
|
|
return bus->write(addr, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Z80::in(uint8 addr) -> uint8 {
|
|
|
|
step(4);
|
|
|
|
return bus->in(addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Z80::out(uint8 addr, uint8 data) -> void {
|
|
|
|
step(4);
|
|
|
|
return bus->out(addr, data);
|
|
|
|
}
|