Implementing BEQ and other Branch Instructions?

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Implementing BEQ and other Branch Instructions?

Post 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?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Implementing BEQ and other Branch Instructions?

Post by tepples »

Which "descriptions" are you looking at?
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Re: Implementing BEQ and other Branch Instructions?

Post by PolarBITS »

I'm using this http://www.6502.org/tutorials/6502opcodes.html
Also I've used the nesdev wiki.
User avatar
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Implementing BEQ and other Branch Instructions?

Post 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.
Last edited by rainwarrior on Thu May 04, 2017 9:52 am, edited 1 time in total.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Implementing BEQ and other Branch Instructions?

Post 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).
User avatar
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Implementing BEQ and other Branch Instructions?

Post 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.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Implementing BEQ and other Branch Instructions?

Post 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.
User avatar
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Implementing BEQ and other Branch Instructions?

Post 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.
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: Implementing BEQ and other Branch Instructions?

Post 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
Hangin10
Posts: 37
Joined: Thu Jun 04, 2009 9:07 am

Re: Implementing BEQ and other Branch Instructions?

Post by Hangin10 »

(quietly updates his emulator to not have taken branches to a different page take 5 cycles) :beer:
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: Implementing BEQ and other Branch Instructions?

Post 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."
Hangin10
Posts: 37
Joined: Thu Jun 04, 2009 9:07 am

Re: Implementing BEQ and other Branch Instructions?

Post 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.
Post Reply