6502 / 65C12 CPU

The BBC family uses three CPU variants. Knowing which you target matters because instructions, cycle counts, and BRK semantics differ.

MachineCPUClockCycle timeNotes
Model B, B+, ElectronNMOS 6502 (“6502A”)2 MHz0.5 µsOriginal NMOS core. JMP (ind) page-boundary bug present.
Master 128, Master Compact65C122 MHz0.5 µsCMOS, extra opcodes, fixed JMP (ind), +1c for decimal-mode ADC/SBC.
6502 2nd processorNMOS 65023 MHz0.33 µsVia Tube.
Master TurboRockwell R65C024 MHz0.25 µsAdds BBR/BBS/RMB/SMB on top of 65C12.

Cycle times are NAUG §5.0 p37.

Registers

  • A — 8-bit accumulator.
  • X, Y — 8-bit index registers.
  • SP — 8-bit stack pointer. Stack lives in page 1 (&0100-&01FF); SP holds the low byte of the next free location.
  • PC — 16-bit program counter.
  • P — status register (see below).

Status flags (P)

BitNameMeaning
0CCarry — set on add overflow, cleared on subtract borrow; shift/rotate bit 9
1ZZero — result was 0
2IInterrupt disable — set: IRQs masked. Set automatically on IRQ/BRK entry.
3DDecimal — ADC/SBC operate in BCD
4BBreak — set in the P value pushed by BRK; not a real flag
5Unused (reads as 1 on stack)
6VOverflow — signed-arithmetic overflow
7NNegative — bit 7 of result

CPU variant differences

65C12 vs NMOS 6502

The 65C12 (Master series) adds and fixes:

  • New opcodes: BRA, STZ/CLR, DEC A/INC A (alias DEA/INA), PHX/PHY/PLX/PLY, TRB, TSB.
  • New addressing modes: (zp indirect) (no X/Y) for ADC/AND/CMP/EOR/LDA/ORA/SBC/STA; JMP (abs,X); immediate BIT; zp,X and abs,X for BIT.
  • JMP (ind) page-boundary bug fixed — costs +1c (6c vs 5c on NMOS). NMOS bug: when the indirect operand low byte is &FF (e.g. JMP (&19FF)), the high byte of the target is fetched from the same page (&1900), not the next page (&1A00). 65C12 fetches from the correct address.
  • CLD set automatically on entry to BRK/IRQ — guarantees handlers run in binary mode.
  • +1c penalty for decimal-mode ADC/SBC — opposite trade to NMOS where decimal mode is the same cost.
  • RMW abs,X (ASL/LSR/ROL/ROR) is 6c (+1 page) rather than always 7c on NMOS.

R65C02 vs 65C12

Adds Rockwell-only opcodes: BBR0..7, BBS0..7, RMB0..7, SMB0..7, plus WAI and STP. The BBC BASIC assembler does not recognise these — hand-assemble with EQUB. Only present on Master Turbo and 6502 second processor.

Detecting NMOS vs CMOS at runtime

There is no clean MOS API for this. The idiomatic test (from Acorn’s Exmon II ROM) exploits the fact that PHX (&DA) and PLX (&FA) are CMOS-only — on NMOS those bytes are treated as NOPs and have no effect on X:

LDX #&FF       ; X = &FF
EQUB &DA       ; PHX on CMOS / NOP on NMOS
INX            ; X = &00 (wraps from &FF)
EQUB &FA       ; PLX on CMOS / NOP on NMOS
; result: X = &FF on CMOS (FF was pushed, X wrapped to 00, FF was pulled back)
;         X = &00 on NMOS (both EQUBs no-op'd, only the INX took effect)

Do not use OSBYTE &A4 for this — despite its short description as “check processor type” in the Master ARM OSBYTE table, it’s actually a paged-ROM image validity check that raises BRK on failure and returns undefined X/Y. See paged-roms for its real purpose, and detection for the broader model-detection picture.

For distinguishing 65C12 from R65C02 (i.e. detecting the Rockwell BBR/BBS/RMB/SMB opcodes), no clean stock-MOS idiom exists. The closest is to install a temporary BRKV handler that catches the BRK that the 65C12 raises on encountering an undocumented opcode, then try executing e.g. SMB0 zp. On R65C02 it executes; on 65C12 it traps.

Stack

Hard-wired to page 1. SP wraps within page 1 on overflow (no overflow trap). PHA/PHP/JSR/BRK push; PLA/PLP/RTS/RTI pull.

Reset / interrupt vectors

VectorAddressPushed on stackNotes
NMI&FFFA/&FFFBPC then Pedge-triggered, not maskable
RESET&FFFC/&FFFDnothingclears nothing useful; firmware sets D=0, I=1
IRQ/BRK&FFFE/&FFFFPC then Pshared vector; B flag in pushed P distinguishes

Distinguishing IRQ from BRK in the handler: pull P from &0101,S (the pushed copy) and test bit 4 (B). On NMOS, also be aware that D may still be set on entry — clear it explicitly in the handler. On 65C12, D is auto-cleared.

Decimal flag (D) — discipline

Setting D=1 (via SED) enables BCD for ADC and SBC. Always CLD before calling MOS — the OS doesn’t clear D itself, and a stray BCD operation in an OS routine corrupts state silently.

  • NMOS BRK / IRQ: D not cleared on entry. Handler must CLD if any ADC/SBC is involved.
  • 65C12 BRK / IRQ: D auto-cleared on entry.
  • 65C12 cost: ADC/SBC in decimal mode take +1c (chip correctly updates N/V/Z flags; NMOS leaves them indeterminate after BCD).

See 6502-isa for the per-mnemonic cycle/opcode reference. See 6502-addressing-modes for mode mechanics. See interrupts for the IRQ chain and BRK/IRQ flag behaviour.


This wiki is curated by Claude following the LLM-Wiki methodology — a human curates source documents, the LLM compiles structured cross-linked markdown. Content may contain errors, omissions, or stale claims. For authoritative information refer to the original source documents in the bbc-documents GitHub archive.