Page 1 of 1

Implementing BEQ and other Branch Instructions?

Posted: Thu May 04, 2017 7:06 am
by PolarBITS
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?

Posted: Thu May 04, 2017 7:44 am
by tepples
Which "descriptions" are you looking at?

Re: Implementing BEQ and other Branch Instructions?

Posted: Thu May 04, 2017 7:53 am
by PolarBITS
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?

Posted: Thu May 04, 2017 9:43 am
by rainwarrior
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?

Posted: Thu May 04, 2017 9:48 am
by tokumaru
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?

Posted: Thu May 04, 2017 9:50 am
by rainwarrior
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?

Posted: Thu May 04, 2017 9:52 am
by tokumaru
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?

Posted: Thu May 04, 2017 12:09 pm
by rainwarrior
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?

Posted: Thu May 11, 2017 7:53 am
by Oziphantom
If you are looking to implement a 6502 - this doc is probably useful to you http://www.zimmers.net/anonftp/pub/cbm/ ... data/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: Select all

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?

Posted: Sat May 13, 2017 10:57 pm
by Hangin10
(quietly updates his emulator to not have taken branches to a different page take 5 cycles) :beer:

Re: Implementing BEQ and other Branch Instructions?

Posted: Sun May 14, 2017 12:43 am
by Oziphantom
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: Select all

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?

Posted: Mon May 15, 2017 9:00 pm
by Hangin10
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: Select all

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.