Open main menu

CDOT Wiki β

6502 Math

Revision as of 00:54, 18 September 2023 by Chris Tyler (talk | contribs) (Bitwise Operations)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

The 6502 processor is limited to very simple math operations, and various processor flags affect these operations.

Decimal Mode

The 6502 can perform math in binary or decimal mode.

In binary mode, operations are performed on a single 8-bit value. Numbers may be treated as signed or unsigned (the math is the same).

In decimal mode, the each byte is treated as two decimal digits - the lower 4 bits represent the lower digit, and the upper 4 bits represent the upper digit. Numbers are counted as positive, and values greater than 9 are invalid.

Decimal mode is selected by setting the D (Decimal) flag in the Status Register using the SED instruction, and binary mode is selected by clearing the D flag using the CLD instruction.

The rest of this page deals with binary mode (decimal mode operates in mostly the same way).

Addition

The ADC (add with carry) instruction adds together:

the value in the accumulator + the specified byte + the carry flag

If the unsigned value overflows a single byte, the carry flag will be set.

It is therefore important to clear the carry flag (with CLC) before adding the lowest byte of a single or multi-byte value. If a multi-byte addition is performed starting with the lowest byte and proceeding to the highest byte, the carry flag will correctly carry bits forward from one byte to the next. For example, this code adds $30F0 and $0120:

LDA #$F0      ; A=$F0
CLC           ; C=0
ADC #$20      ; Result is $F0+$20+C = $110; therefore A=$10 and C=1
STA LOWBYTE
LDA #$30      ; A=$30
ADC #$01      ; Value is $30+$01+C = $32; therefore A=$32 and C=0
STA HIGHBYTE

The Overflow (V) flag is set if the signed result of the operation is above 127 ($7f) or below -128 ($80).

Subtraction

The SBC (subtract with carry) operation subtracts:

the value in the accumulator - the specified byte - (not Carry)

Where the not operation inverts the value of the carry flag.

The carry flag (which can be viewed as a "borrow" flag for subtraction) is cleared if the result underflows $00 and set otherwise (in other words, if doing unsigned math, the Carry flag is cleared if a bit must be "borrowed").

Normally, you will set the carry flag (with SEC) before performing a subtraction on the lowest byte of a single- or multi-byte subtraction, and then perform subtraction on each byte in sequence up to the highest byte. The borrows will automatically be carried from one byte to the next.

The Overflow (V) flag is set if the signed result of the operation is above 127 ($7f) or below -128 ($80).

Division / LSR

There is no general division operation available. However, Logical Shift Right will effectively perform a division-by-two. A zero will be rotated into the highest bit, and the lowest bit will be shifted into the Carry flag (C).

Multiplication / ASL

There is no general multiplication operation available. However, Arithmetic Shift Left will effectively perform a multiplication-by-two. A zero will be rotated into the lowest bit, and highest bit will be shifted into the Carry flag (C).

Rotate Right/Left

The Rotate Right and Rotate Left (ROR/ROL) instructions are like the LSR/ASL instructions, except that the Carry flag is rotated into one end of the byte, and the bit from the other end is rotated into the Carry flag. For example, ROR will shift C into the high bit and the low bit into C. Therefore, it is possible to perform a multi-byte rotate by stringing together ROR or ROL instructions.

Bitwise Operations

The 6502 offers a basic set of Bitwise Operations, including:

 ROR  Rotate right - 9-bit rotate (one byte plus C flag)
 ROL  Rotate left - 9-bit rotate left (one byte plus C flag)
 ASL  Arithmetic shift left - bit 7 -> C flag, bits 0:6 -> 1:7, 0 -> bit 0
 LSR  Logical shift right - bit 0 -> C flag, bits 7:1 -> 6:0, 0 -> bit 7
 EOR  Exclusive-OR (sometimes written XOR in other languages)
 ORA  OR (accumulator)
 AND  AND

A NOT operation can be performed using EOR with an immediate value of #$FF, and this can be combined with ORA and AND instructions to build NOR and NAND operations.

The BIT instruction performs a bitwise AND, sets the Z flag based on the result, and transfers bits 6 and 7 of the operand into the N and V flags.

Multiplication and Division

There are no multiplication or division instructions on the 6502; it is up to the programmer to provide the appropriate logic.