I'm writing a simple GB emulator (wow, now that's something new, isn't it), since I'm really taking my first steps in emu.

What i don't seem to understand is how to correctly implement the CPU cycle and unconditional jumps.

Consider the command JP nn (unconditional jump to memory adress pointed out), like JP 1000h, if I have a basic loop of:

increment PC
read opcode
execute command

Then after the JP opcode has been read and the command executed (read 1000h from memory and set PC = 1000h), the PC gets incremented and becomes 1001h, thus resulting in bad emulation.

tl;dr How do you emulate jumps in emulators, so that PC value stays correct, when having cpu loops that increment PC?

有帮助吗?

解决方案

The PC should be incremented as an 'atomic' operation every time it is used to return a byte. This means immediate operands as well as opcodes.

In your example, the PC would be used three times, once for the opcode and twice for the two operand bytes. By the time the CPU has fetched the three bytes and is in a position to load the PC, the PC is already pointing to the next instruction opcode after the second operand but, since actually implementing the instruction reloads the PC, it doesn't matter.

其他提示

Move increment PC to the end of the loop, and have it performed conditionally depending on the opcode?

I know next to nothing about emulation, but two obvious approaches spring to mind.

  1. Instead of hardcoding PC += 1 into the main loop, let the evaluation if each opcode return the next PC value (or the offset, or a flag saying whether to increment it, or etc). Then the difference between jumps and other opcodes (their effect on the program counter) is definable along with everything else about them.

  2. Knowing that the main loop will always increment the PC by 1, just have the implementation of jumps set the PC to target - 1 rather than target.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top