Implementing BEQ and other Branch Instructions?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Implementing BEQ and other Branch Instructions?
by on (#195030)
I've read everywhere and I can't seem to find proper documentation for them. I read that they're used for looping and are dependent on certain flags, but just from their descriptions I can't make out exactly which ones. Can someone help me here?
Re: Implementing BEQ and other Branch Instructions?
by on (#195033)
Which "descriptions" are you looking at?
Re: Implementing BEQ and other Branch Instructions?
by on (#195034)
I'm using this http://www.6502.org/tutorials/6502opcodes.html
Also I've used the nesdev wiki.
Re: Implementing BEQ and other Branch Instructions?
by on (#195040)
Each branch depends on one flag.

Each branch argument is a 1-byte signed value that is added to the PC if the flag condition is true; otherwise the instruction does nothing. (If the branch is taken, 1 or 2 extra cycles are spent adding to argument to the PC.)

BEQ branches if the Z (zero) flag is set.
BNE branches if the Z flag is clear.
etc.

My favourite opcode reference is here: http://www.obelisk.me.uk/6502/reference.html

If you're looking for a cycle-by-cycle breakdown, though, it doesn't go into that kind of detail.
Re: Implementing BEQ and other Branch Instructions?
by on (#195041)
rainwarrior wrote:
If the branch is taken, 2 or 3 extra cycles are spent adding to argument to the PC.

That's not quite right. Branch instructions will always use at least 2 cycles (time taken to fetch the opcode and the argument from memory), and if the branch is taken, 1 or 2 extra cycles are spent adding to argument to the PC (1 cycle if only the low byte of the PC changes, 2 if the high byte is also affected).
Re: Implementing BEQ and other Branch Instructions?
by on (#195042)
I had already fixed that typo while you were quoting me. It's accurately described in both the given references, though, so I think we're OK.
Re: Implementing BEQ and other Branch Instructions?
by on (#195043)
It's still wrong though, it's 1 or 2 extra cycles. The +1 and +2 in that documentation are not cumulative.

The obelisk reference is my favorite too, but I can see how someone could misinterpret the information about those extra cycles.
Re: Implementing BEQ and other Branch Instructions?
by on (#195054)
tokumaru wrote:
The +1 and +2 in that documentation are not cumulative.

It was just a typo, there was no "cumulative" meaning behind the mistake.
Re: Implementing BEQ and other Branch Instructions?
by on (#195576)
If you are looking to implement a 6502 - this doc is probably useful to you http://www.zimmers.net/anonftp/pub/cbm/documents/chipdata/64doc
See the "6510 Instruction Timing" section, note that the 6510 is identical to NMOS 6502 for its instruction set and timings.
For example a Branch ( relative address mode it gives )
Code:
Relative addressing (BCC, BCS, BNE, BEQ, BPL, BMI, BVC, BVS)

        #   address  R/W description
       --- --------- --- ---------------------------------------------
        1     PC      R  fetch opcode, increment PC
        2     PC      R  fetch operand, increment PC
        3     PC      R  Fetch opcode of next instruction,
                         If branch is taken, add operand to PCL.
                         Otherwise increment PC.
        4+    PC*     R  Fetch opcode of next instruction.
                         Fix PCH. If it did not change, increment PC.
        5!    PC      R  Fetch opcode of next instruction,
                         increment PC.

       Notes: The opcode fetch of the next instruction is included to
              this diagram for illustration purposes. When determining
              real execution times, remember to subtract the last
              cycle.

              * The high byte of Program Counter (PCH) may be invalid
                at this time, i.e. it may be smaller or bigger by $100.

              + If branch is taken, this cycle will be executed.

              ! If branch occurs to different page, this cycle will be
                executed.

It also covers how the BCD maths and how Illegal opcodes work. Although a better document on them can be found here http://csdb.dk/release/?id=152327
Re: Implementing BEQ and other Branch Instructions?
by on (#195728)
(quietly updates his emulator to not have taken branches to a different page take 5 cycles) :beer:
Re: Implementing BEQ and other Branch Instructions?
by on (#195734)
Its tricky as the 5th is actually the 1st of the next opcode. So it depends on how your system is implemented but basically it only takes 4 cycles max, as the fetch opcode is the first cycle of the next opcode.
Code:
bne takenNextPage - 1 load bne       1
                  - 2 load offset    2
                  - 3 add PCL        3
                  - 4 add PCH        4
takenNextPage
lda #$00          - 1 load lda       5
                  - 2 load 00
"The opcode fetch of the next instruction is included to
this diagram for illustration purposes."
Re: Implementing BEQ and other Branch Instructions?
by on (#195866)
Oziphantom wrote:
Its tricky as the 5th is actually the 1st of the next opcode. So it depends on how your system is implemented but basically it only takes 4 cycles max, as the fetch opcode is the first cycle of the next opcode.
Code:
bne takenNextPage - 1 load bne       1
                  - 2 load offset    2
                  - 3 add PCL        3
                  - 4 add PCH        4
takenNextPage
lda #$00          - 1 load lda       5
                  - 2 load 00
"The opcode fetch of the next instruction is included to
this diagram for illustration purposes."


I actually used that document for most of the opcodes. I must have just thought branches were simple enough to just use the 'obelisk' reference, but ended interpreting that one as the +1/2 as cumulative. Had I looked back at this per-cycle document, I would have done it right.