17

This question expands on How does the 6502 implement its branch instructions?

I'm working on a cycle accurate VHDL implementation on an FPGA. I have much of the program logic already written, but I can't wrap my head around how to logically calculate the relative addressing from the branch instructions.

From everything I've read and reviewed, the only outputs of the ALU are: result, alucout, and aluvout. I've read that the flag outputs from he ALU are routed to the control logic, even though it's not shown in the block diagram.

I built a truth table on several different scenarios for offsets, and it seems you can't just use carry and overflow to determine whether or not to carry to the high byte of the program counter. I even thought to move the bit 7 logic from the flags register logic to the alu, and route that to the control logic, but that wouldn't help either.

Some of the resources I've been using are:

Block Diagram

Visual 6502

Programming the 65816 - Has a section on the relative addressing in conditional branching

NESDev 6502 Text File

So to put all of this madness into a question... How is the (signed)offset calculated against the (unsigned)program counter, and how do you determine if you need to add a cycle to calculate the high byte of the program counter?

Evan
  • 173
  • 6

2 Answers2

16

Quick shot, without looking it up in Visual 6502 (which would be the authorative option):

Sign extend the branch offset (replicate MSB of offset), that will tell you the ALU input for the PC high byte. Possible values are 0 and -1 (all 1s), these are available as constants.

Carry and sign of the branch offset together determine if an extra cycle is necessary (for carry and positive offset, or no carry and negative offset). That's a simple XOR.

The overflow flag shouldn't play a role.

dirkt
  • 27,321
  • 3
  • 72
  • 113
  • Awesome! That was right on my truth table and I didn't even see it. Thank you! – Evan Aug 20 '18 at 20:56
  • Jup, that's it. Except there's no sign extension, just constant selection – Raffzahn Aug 20 '18 at 21:36
  • 1
    @Raffzahn: Well, the constant selection implements the sign extension... (and without knowing it's a sign extension, the whole process wouldn't made sense). – dirkt Aug 21 '18 at 05:41
  • @dirkt Still stays a constant selection, as a sign extension would mean that there is somewhere a circuit propagating the sign. Wouldn't it? And for his task, coding it as a sign extension could result in a different implementation, eventually less performing. The task is rather staying with the template. – Raffzahn Aug 21 '18 at 09:05
  • "as a sign extension would mean that there is somewhere a circuit propagating the sign." No, it wouldn't. You are missing the point. – dirkt Aug 21 '18 at 09:47
  • @dirkt Isn't it right in the words - extending is a process where the single bit gets extended. Not like in using a constant. It migt be helpful to think about the words used to describe something. Don't you think so? – Raffzahn Aug 21 '18 at 23:09
  • @Raffzahn: How do you think sign extension instructions like CBW, CWD are implemented? There isn't some circuitry that propagates the sign bit by bit, instead, a constant is loaded into the upper part of the register (or all the registers bits are directly set or reset). But this quibbling is getting OT. The point is that, morally, it's a sign extension, because you are adding a shorter signed number to a longer number. No matter how you implement it, by constants or otherwise. – dirkt Aug 22 '18 at 05:43
  • @dirkt Not realy, as you mixing things up. For one, CBW isn't exactly a 6502 instruction. Nor is it a 16 bit operation. More imortant what you are refering to about is a singed to signed operation a shorter signed number is added to a longer signed number. There a sign extension happenes. Also the result can yield an overflow, which explicit does not happenes here. But this is about the different case of signed to unsigned addition. Your description is fine, except, using the term sign extension is a missmatch. – Raffzahn Aug 22 '18 at 06:59
  • 1
    The logical operation is sign extension. The fact that you load the upper byte with $00 or $ff is an implementation detail. The answer already mentions how the sign extension could be done by loading the register with constants. – JeremyP Sep 25 '18 at 10:11
  • Once you add the offset to PCL, you get the carry out from the operation. But at that point where is the offset accessible to get the sign bit? – Patrick LeBoutillier Jul 19 '22 at 15:56
3

AFAIR it's Carry XOR Sign (of the offset).

If this yields true, it's increment when Carry, otherwise decrement.

Raffzahn
  • 222,541
  • 22
  • 631
  • 918