Handling branch opcodes in a cycle-based CPU core

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Handling branch opcodes in a cycle-based CPU core
by on (#10714)
I'm currently in the process of writing a cycle-based 2A03 CPU core. The ViCE documentation (http://www.nesdev.com/6502_cpu.txt) is quite helpful, but the information contained there about branch opcodes is not all that clear. I know that some people here (Quietust and perhaps others) have written cycle-based CPU cores, so I'd like to see whether I'm on the right track. Here's what I've got at this point (for the BPL opcode, 0x10):

Code:
    /***********/
    /* BPL $nn */
    /***********/
    case 0x10: /* 2nd cycle: Fetch operand and increment PC */
               Operand = CPU_Read (CPU_PC.Word++);
               CPU_Cycle ();

               /* Extra cycle only if branch taken */
               if (~CPU_P & CPU_N_FLAG)
               {
                 /* 3rd cycle: Dummy opcode fetch and add operand to PC(l) */
                 CPU_Read (CPU_PC.Word);
                 Address.Word = CPU_PC.Word + (S8) (Operand);
                 CPU_PC.Byte.Low = Address.Byte.Low;
                 CPU_Cycle ();

                 /* Extra cycle only if PC(h) is invalid at this time */
                 if (CPU_PC.Byte.High != Address.Byte.High)
                 {
                   /* 4th cycle: Dummy opcode fetch and fix PC(h) */
                   CPU_Read (CPU_PC.Word);
                   CPU_PC.Byte.High = Address.Byte.High;
                   CPU_Cycle ();
                 }
               }

               /* Done */
               break;


Note that the first opcode cycle (fetch opcode and increment PC) was done before the switch statement for obvious reasons. Also, the (S8) cast is for a signed char. Does this code seem correct?

by on (#10717)
Looks okay to me.

Also, you could probably simplify your CPU core slightly to perform CPU_Cycle() directly from CPU_Read() and CPU_Write(), since all CPU cycles are tied to memory accesses (and vice-versa).

by on (#10726)
I wrote a cycle for cycle 6502 core recently and I had to skip the branches because the 6502_cpu.txt made no sense to me. Btw, I assume that you are going to update the PPU/APU after each cycle? Also, why are you specifically writing a cycle for cycle emulator?