Saturday, July 7, 2018

Math Branching

The last couple of post seen the ADC and the SBC instructions added to the 6502 emulator. We now have some instructions that cause the carry and overflow flags to be set. For multi-byte numbers the use of the carry flag is built into the ADC and SBC instructions and will be used automatically without need for special branching logic. The carry flag is necessary for dealing with adding or subtracting a byte from a multi-byte value. In this case you can write the code like this:

LDA NumberLowByte
CLC
ADC ByteToAdd
STA NumberLowByte
BCC noOverflow
INC NumberHighByte
noOverflow: ; additional code here
Probably the most important use for the carry flag branching  functions BCC amd BCS is for handling overflow errors when using unsigned numbers. When a number gets too big to be contained in the byte it sets the carry flag and wraps around. In cases where this is the only byte or the last byte in a multibyte number then there is a very good possibility that something bad has just happened. If this is a possibility in your code then you should be using BCC or BCS to handle potential errors.

Signed numbers overflow in a rather different way, which is why we have the overflow flag in addition to the carry flag. If you are using a signed byte then 64 + 64 results in -128 which is not what you want. The overflow flag solves this by being set when the sign of a number changes in cases where it shouldn’t be changing such as adding two positive numbers together or adding two negative numbers together.  The BVC and BVS commands are used to detect this problem and handle the error from this.

When dealing with multi-byte signed numbers, you need to be concerned with the overflow flag only for the highest byte of the number.
BCCBranch on Carry Clear
Address Mode
Decimal OPCode
Hexadecimal OpCode
Size
Cycles
Relative
144
$90
2
2-4
Flags affected: None
Cycle Notes: If branching will take an additional cycle (3). If branch crosses page boundaries then an additional cycle will be added on top of the cycle for branching (4).
Usage: Checks to make sure last math operation has not resulted in a carry (ADC) or has borrowed (SBC). A carry is an indication that the bits in the byte have wrapped so this instruction will branch if the byte has not wrapped.
Test Code:
; BCC test by counting times can add 10 before wrapping
CLD
LDA #0
TAX
count: INX
CLC
ADC #10
BCC count
BRK
; expect A = 6, X=26, C=1
Implementation:
processBranch(state.flags and CARRY_FLAG != CARRY_FLAG, mem.read(state.ip+1) )
BCSBranch on Carry Set
Address Mode
Decimal OPCode
Hexadecimal OpCode
Size
Cycles
Relative
176
$B0
2
2-4
Flags affected: None
Cycle Notes: If branching will take an additional cycle (3). If branch crosses page boundaries then an additional cycle will be added on top of the cycle for branching (4).
Usage: Checks to make sure last math operation has not resulted in a carry (ADC) or has borrowed (SBC). A carry is an indication that the bits in the byte have wrapped so with this command the branch will be taken if the byte has wrapped.
Test Code:
; BCS count how many times can subtract 10 before wrapping
CLD
LDA #255
LDX #0
count: INX
SEC
SBC #10
BCS count
BRK;
; expect A 251, X26, C=0
Implementation:
processBranch(state.flags and CARRY_FLAG == CARRY_FLAG, mem.read(state.ip+1) )
BVC   Branch on Overflow Clear
BVCBranch on oVerflow Clear
Address Mode
Decimal OPCode
Hexadecimal OpCode
Size
Cycles
Relative
80
$50
2
2-4
Flags affected: None
Cycle Notes: If branching will take an additional cycle (3). If branch crosses page boundaries then an additional cycle will be added on top of the cycle for branching (4).
Usage: Checks to make sure the last math operation didn’t cause an overflow. This is for signed numbers when a number changes its sign when it shouldn’t due to too large of numbers being used.
Test Code:
; BVC count how many times can add 10 until become negative
CLD
LDA #0
TAX
count: INX
CLC
ADC #10
BVC count
BRK;
; expect A 130, X13, C=0, V=1
Implementation:
processBranch(state.flags and OVERFLOW_FLAG != OVERFLOW_FLAG, mem.read(state.ip+1) )
BVS   Branch on Overflow Set
BVSBranch on oVerflow Set
Address Mode
Decimal OPCode
Hexadecimal OpCode
Size
Cycles
Relative
112
$70
2
2-4
Flags affected: None
Cycle Notes: If branching will take an additional cycle (3). If branch crosses page boundaries then an additional cycle will be added on top of the cycle for branching (4).
Usage: Checks if last math operation caused an overflow. This is for signed numbers when a number changes its sign when it shouldn’t due to too large of numbers being used.
Test Code:
; BVS test
CLD
LDA #64
LDX #0
CLC
ADC #32
BVS done
INX
CLC
ADC #32
BVS done
INX
done: BRK
; expect A=128, X=1, V=1
Implementation:

processBranch(state.flags and OVERFLOW_FLAG == OVERFLOW_FLAG, mem.read(state.ip+1) )

No comments:

Post a Comment