mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-02-24 15:12:23 +01:00
byuu says: Changelog: - gba/cpu: slight speedup to CPU::step() - processor/arm7tdmi: fixed about ten bugs, ST018 and GBA games are now playable once again - processor/arm: removed core from codebase - processor/v30mz: code cleanup (renamed functions; updated instruction() for consistency with other cores) It turns out on my much faster system, the new ARM7TDMI core is very slightly slower than the old one (by about 2% or so FPS.) But the CPU::step() improvement basically made it a wash. So yeah, I'm in really serious trouble with how slow my GBA core is now. Sigh. As for higan/processor ... this concludes the first phase of major cleanups and rewrites. There will always be work to do, and I have two more phases in mind. One is that a lot of the instruction disassemblers are very old. One even uses sprintf still. I'd like to modernize them all. Also, the ARM7TDMI core (and the ARM core before it) can't really disassemble because the PC address used for instruction execution is not known prior to calling instruction(), due to pipeline reload fetches that may occur inside of said function. I had a nasty hack for debugging the new core, but I'd like to come up with a clean way to allow tracing the new ARM7TDMI core. Another is that I'd still like to rename a lot of instruction function names in various cores to be more descriptive. I really liked how the LR35902 core came out there, and would like to get that level of detail in with the other cores as well.
189 lines
3.2 KiB
C++
189 lines
3.2 KiB
C++
auto V30MZ::instructionLoop() -> void {
|
|
wait(1);
|
|
auto offset = (int8)fetch();
|
|
if(--r.cx) {
|
|
wait(3);
|
|
r.ip += offset;
|
|
}
|
|
}
|
|
|
|
auto V30MZ::instructionLoopWhile(bool value) -> void {
|
|
wait(2);
|
|
auto offset = (int8)fetch();
|
|
if(--r.cx && r.f.z == value) {
|
|
wait(3);
|
|
r.ip += offset;
|
|
}
|
|
}
|
|
|
|
auto V30MZ::instructionJumpShort() -> void {
|
|
wait(3);
|
|
auto offset = (int8)fetch();
|
|
r.ip += offset;
|
|
}
|
|
|
|
auto V30MZ::instructionJumpIf(bool condition) -> void {
|
|
auto offset = (int8)fetch();
|
|
if(condition) r.ip += offset;
|
|
}
|
|
|
|
auto V30MZ::instructionJumpNear() -> void {
|
|
wait(3);
|
|
r.ip += (int16)fetch(Word);
|
|
}
|
|
|
|
auto V30MZ::instructionJumpFar() -> void {
|
|
wait(6);
|
|
auto ip = fetch(Word);
|
|
auto cs = fetch(Word);
|
|
r.cs = cs;
|
|
r.ip = ip;
|
|
}
|
|
|
|
auto V30MZ::instructionCallNear() -> void {
|
|
wait(4);
|
|
auto offset = (int16)fetch(Word);
|
|
push(r.ip);
|
|
r.ip += offset;
|
|
}
|
|
|
|
auto V30MZ::instructionCallFar() -> void {
|
|
wait(9);
|
|
auto ip = fetch(Word);
|
|
auto cs = fetch(Word);
|
|
push(r.cs);
|
|
push(r.ip);
|
|
r.cs = cs;
|
|
r.ip = ip;
|
|
}
|
|
|
|
auto V30MZ::instructionReturn() -> void {
|
|
wait(5);
|
|
r.ip = pop();
|
|
}
|
|
|
|
auto V30MZ::instructionReturnImm() -> void {
|
|
wait(5);
|
|
auto offset = fetch(Word);
|
|
r.ip = pop();
|
|
r.sp += offset;
|
|
}
|
|
|
|
auto V30MZ::instructionReturnFar() -> void {
|
|
wait(7);
|
|
r.ip = pop();
|
|
r.cs = pop();
|
|
}
|
|
|
|
auto V30MZ::instructionReturnFarImm() -> void {
|
|
wait(8);
|
|
auto offset = fetch(Word);
|
|
r.ip = pop();
|
|
r.cs = pop();
|
|
r.sp += offset;
|
|
}
|
|
|
|
auto V30MZ::instructionReturnInt() -> void {
|
|
wait(9);
|
|
r.ip = pop();
|
|
r.cs = pop();
|
|
r.f = pop();
|
|
state.poll = false;
|
|
}
|
|
|
|
auto V30MZ::instructionInt3() -> void {
|
|
wait(8);
|
|
interrupt(3);
|
|
}
|
|
|
|
auto V30MZ::instructionIntImm() -> void {
|
|
wait(9);
|
|
interrupt(fetch());
|
|
}
|
|
|
|
auto V30MZ::instructionInto() -> void {
|
|
wait(5);
|
|
interrupt(4);
|
|
}
|
|
|
|
auto V30MZ::instructionEnter() -> void {
|
|
wait(7);
|
|
auto offset = fetch(Word);
|
|
auto length = fetch(Byte) & 0x1f;
|
|
push(r.bp);
|
|
r.bp = r.sp;
|
|
r.sp -= offset;
|
|
|
|
if(length) {
|
|
wait(length > 1 ? 7 : 6);
|
|
for(uint n = 1; n < length; n++) {
|
|
wait(4);
|
|
auto data = read(Word, segment(r.ss), r.bp - n * 2);
|
|
push(data);
|
|
}
|
|
push(r.bp);
|
|
}
|
|
}
|
|
|
|
auto V30MZ::instructionLeave() -> void {
|
|
wait(1);
|
|
r.sp = r.bp;
|
|
r.bp = pop();
|
|
}
|
|
|
|
auto V30MZ::instructionPushReg(uint16_t& reg) -> void {
|
|
push(reg);
|
|
}
|
|
|
|
auto V30MZ::instructionPopReg(uint16_t& reg) -> void {
|
|
reg = pop();
|
|
if(® == &r.ss) state.poll = false;
|
|
}
|
|
|
|
auto V30MZ::instructionPushFlags() -> void {
|
|
wait(1);
|
|
push(r.f);
|
|
}
|
|
|
|
auto V30MZ::instructionPopFlags() -> void {
|
|
wait(2);
|
|
r.f = pop();
|
|
state.poll = false;
|
|
}
|
|
|
|
auto V30MZ::instructionPushAll() -> void {
|
|
wait(8);
|
|
auto sp = r.sp;
|
|
push(r.ax);
|
|
push(r.cx);
|
|
push(r.dx);
|
|
push(r.bx);
|
|
push(sp);
|
|
push(r.bp);
|
|
push(r.si);
|
|
push(r.di);
|
|
}
|
|
|
|
auto V30MZ::instructionPopAll() -> void {
|
|
wait(7);
|
|
r.di = pop();
|
|
r.si = pop();
|
|
r.bp = pop();
|
|
auto sp = pop();
|
|
r.bx = pop();
|
|
r.dx = pop();
|
|
r.cx = pop();
|
|
r.ax = pop();
|
|
//r.sp is not restored
|
|
}
|
|
|
|
auto V30MZ::instructionPushImm(Size size) -> void {
|
|
if(size == Byte) push((int8)fetch(Byte));
|
|
if(size == Word) push(fetch(Word));
|
|
}
|
|
|
|
auto V30MZ::instructionPopMem() -> void {
|
|
modRM();
|
|
setMem(Word, pop());
|
|
}
|