Oct 4, 2026 · Updated Oct 11, 2026 · @Craig Taylor
This chapter is a reference to every instruction the 45GS02 executes, in alphabetical order. Each entry gives the operation, the flags it changes, every addressing mode with its opcode, and which processor introduced it. The opcodes follow the cc65 project's CPU reference (ca65/da65 CPU overview), which documents the 6502, 65C02, 65CE02, 4510 and 45GS02 instruction sets side by side.
The 65CE02 defines all 256 opcodes, and the 45GS02 builds its extensions from prefixes rather than new opcodes, so every byte value is a valid instruction or prefix. In its native mode there are no undocumented opcodes of the kind C64 programmers know; a separate 6502 compatibility mode, which the Book describes as incomplete and untested, emulates some of them (MEGA65 Book, 45GS02 and 6502 instruction sets appendix).
Cycle counts are not given here. The 45GS02's native timings differ from the 6502's, and at 40.5 MHz they also depend on memory type and wait states; Chapter 7 discusses timing, and the MEGA65 Book's CPU chapter is the authority.
| Abbreviation | Mode | Example |
|---|---|---|
| impl | Implied | INX |
| A | Accumulator | ASL A |
| imm | Immediate byte | LDA #$41 |
| imm16 | Immediate word | PHW #$1234 |
| bp | Base page | LDA $10 |
| bp,X / bp,Y | Base page indexed | LDA $10,X |
| abs | Absolute | LDA $D020 |
| abs,X / abs,Y | Absolute indexed | LDA $0400,X |
| (bp,X) | Indexed indirect | LDA ($10,X) |
| (bp),Y | Indirect indexed by Y | LDA ($10),Y |
| (bp),Z | Indirect indexed by Z | LDA ($10),Z |
| [bp],Z | Flat indirect, 32-bit pointer | LDA [$10],Z |
| (d,SP),Y | Stack relative indirect | LDA ($02,SP),Y |
| (abs) | Absolute indirect | JMP ($0318) |
| (abs,X) | Absolute indexed indirect | JMP ($1000,X) |
| rel | 8-bit relative | BNE loop |
| rel16 | 16-bit relative | LBNE far |
In the opcode columns, two-byte sequences such as
$EA $72 are prefixed instructions: the prefix byte comes
first, then the opcode and its operand.
The flags column lists the flags an instruction can change, using N, V, E, B, D, I, Z and C as in Chapter 7. A dash means no flags are affected. The flags column refers to the Z flag, never the Z register.
| Code | Processor |
|---|---|
| 6502 | Original NMOS 6502 |
| C02 | 65C02 family (65SC02) |
| R | Rockwell 65C02 bit instructions |
| CE | CSG 65CE02 |
| 4510 | CSG 4510 (C65) |
| GS | 45GS02 (MEGA65) |
Assemblers do not all use the same mnemonics for the newer
instructions. Long branches may be written LBNE or chosen
automatically from BNE; quad instructions may be written
ADCQ (cc65 and the MEGA65 Book) or ADQ
(64tass); and bit
instructions may be written RMB3 $10 or
RMB 3,$10. This chapter uses the forms most common in
MEGA65 documentation.
| Mnemonic | Operation | Flags | Modes and opcodes | Origin |
|---|---|---|---|---|
| ADC | A = A + M + C | N V Z C | imm $69 · bp $65 · bp,X $75 · abs $6D · abs,X $7D · abs,Y $79 · (bp,X) $61 · (bp),Y $71 · (bp),Z $72 · [bp],Z $EA $72 |
6502; (bp),Z CE; [bp],Z GS |
| AND | A = A AND M | N Z | imm $29 · bp $25 · bp,X $35 · abs $2D · abs,X $3D · abs,Y $39 · (bp,X) $21 · (bp),Y $31 · (bp),Z $32 · [bp],Z $EA $32 |
6502; (bp),Z CE; [bp],Z GS |
| ASL | Shift left; bit 7 to C | N Z C | A $0A · bp $06 · bp,X $16 · abs $0E · abs,X $1E |
6502 |
| ASR | Arithmetic shift right; bit 7 kept, bit 0 to C | N Z C | A $43 · bp $44 · bp,X $54 |
CE |
| ASW | Shift 16-bit word left; bit 15 to C | N Z C | abs $CB |
CE |
| BBR0-7 | Branch if bit n of a base page byte is clear | - | BBR0 $0F · BBR1 $1F · BBR2 $2F · BBR3 $3F · BBR4 $4F · BBR5 $5F · BBR6 $6F · BBR7 $7F |
R |
| BBS0-7 | Branch if bit n of a base page byte is set | - | BBS0 $8F · BBS1 $9F · BBS2 $AF · BBS3 $BF · BBS4 $CF · BBS5 $DF · BBS6 $EF · BBS7 $FF |
R |
| BCC | Branch if C = 0 | - | rel $90 · rel16 $93 |
6502; rel16 CE |
| BCS | Branch if C = 1 | - | rel $B0 · rel16 $B3 |
6502; rel16 CE |
| BEQ | Branch if Z = 1 | - | rel $F0 · rel16 $F3 |
6502; rel16 CE |
| BIT | Test A AND M; N and V from M | N V Z | imm $89 · bp $24 · bp,X $34 · abs $2C · abs,X $3C |
6502; imm, indexed C02 |
| BMI | Branch if N = 1 | - | rel $30 · rel16 $33 |
6502; rel16 CE |
| BNE | Branch if Z = 0 | - | rel $D0 · rel16 $D3 |
6502; rel16 CE |
| BPL | Branch if N = 0 | - | rel $10 · rel16 $13 |
6502; rel16 CE |
| BRA | Branch always | - | rel $80 · rel16 $83 |
C02; rel16 CE |
| BRK | Software interrupt through $FFFE |
I | impl $00 |
6502 |
| BSR | Call subroutine at a 16-bit relative offset | - | rel16 $63 |
CE |
| BVC | Branch if V = 0 | - | rel $50 · rel16 $53 |
6502; rel16 CE |
| BVS | Branch if V = 1 | - | rel $70 · rel16 $73 |
6502; rel16 CE |
ADC and SBC honour the D flag, working in binary-coded decimal when it is set. Clear D with CLD at the start of any program that does not set it deliberately.
BBR and BBS take two operands: the base page address
to test and an 8-bit relative branch target, as in
BBS3 $10,done. They are three-byte instructions.
BIT immediate sets Z from A AND the operand, and,
unlike the 65C02, also copies bits 7 and 6 of the operand into N and V,
just as the memory modes do (MEGA65 Book, BIT instruction entry;
mega65-core, gs4510.vhdl, September 2026).
BSR is written LBSR in cc65 (cc65 CPU reference); the
MEGA65 Book writes BSR.
BRK sets I. The CPU has no stored B flag: bit 4 is
set only in the copy of P that BRK pushes, so a handler tells BRK from
IRQ by testing that copy on the stack (mega65-core, gs4510.vhdl, September 2026).
BRK is followed by a padding byte that the CPU skips on return, as on the 6502. The return address pushed is that of BRK plus two.
BSR pushes the return address like JSR, so a subroutine called with BSR returns with RTS or RTN. Because the target is relative, code built with BSR can run at any address without relocation.
| Mnemonic | Operation | Flags | Modes and opcodes | Origin |
|---|---|---|---|---|
| CLC | C = 0 | C | impl $18 |
6502 |
| CLD | D = 0: binary arithmetic | D | impl $D8 |
6502 |
| CLE | E = 0: enable 16-bit stack pointer | E | impl $02 |
CE |
| CLI | I = 0: allow IRQ | I | impl $58 |
6502 |
| CLV | V = 0 | V | impl $B8 |
6502 |
| CMP | Compare A with M | N Z C | imm $C9 · bp $C5 · bp,X $D5 · abs $CD · abs,X $DD · abs,Y $D9 · (bp,X) $C1 · (bp),Y $D1 · (bp),Z $D2 · [bp],Z $EA $D2 |
6502; (bp),Z CE; [bp],Z GS |
| CPX | Compare X with M | N Z C | imm $E0 · bp $E4 · abs $EC |
6502 |
| CPY | Compare Y with M | N Z C | imm $C0 · bp $C4 · abs $CC |
6502 |
| CPZ | Compare Z with M | N Z C | imm $C2 · bp $D4 · abs $DC |
CE |
| DEC | M = M - 1, or A = A - 1 | N Z | A $3A · bp $C6 · bp,X $D6 · abs $CE · abs,X $DE |
6502; A C02 |
| DEW | 16-bit base page word = word - 1 | N Z | bp $C3 |
CE |
| DEX | X = X - 1 | N Z | impl $CA |
6502 |
| DEY | Y = Y - 1 | N Z | impl $88 |
6502 |
| DEZ | Z = Z - 1 | N Z | impl $3B |
CE |
| EOM | End of mapping sequence; otherwise no operation | - | impl $EA |
4510 |
| EOR | A = A XOR M | N Z | imm $49 · bp $45 · bp,X $55 · abs $4D · abs,X $5D · abs,Y $59 · (bp,X) $41 · (bp),Y $51 · (bp),Z $52 · [bp],Z $EA $52 |
6502; (bp),Z CE; [bp],Z GS |
CLE should be used only where the program's stack can safely grow beyond page 1. The KERNAL and BASIC expect the 8-bit stack, so cooperative routines should leave E set.
Compare instructions set C when the register is greater than or equal to the operand, treating both as unsigned, and set Z when they are equal. N reflects bit 7 of the difference.
DEW works on a 16-bit value at a base page address, low byte first. Its flags reflect the 16-bit result.
EOM is the 6502's NOP, $EA. After MAP
it ends the interrupt-blocked mapping sequence. Placed before an
instruction that uses (bp),Z, it acts as the
flat-addressing prefix described in the last section of this chapter, so
a stray NOP before such an instruction changes its meaning.
| Mnemonic | Operation | Flags | Modes and opcodes | Origin |
|---|---|---|---|---|
| INC | M = M + 1, or A = A + 1 | N Z | A $1A · bp $E6 · bp,X $F6 · abs $EE · abs,X $FE |
6502; A C02 |
| INW | 16-bit base page word = word + 1 | N Z | bp $E3 |
CE |
| INX | X = X + 1 | N Z | impl $E8 |
6502 |
| INY | Y = Y + 1 | N Z | impl $C8 |
6502 |
| INZ | Z = Z + 1 | N Z | impl $1B |
CE |
| JMP | Jump | - | abs $4C · (abs) $6C · (abs,X) $7C |
6502; (abs,X) C02 |
| JSR | Push return address and jump | - | abs $20 · (abs) $22 · (abs,X) $23 |
6502; indirect CE |
| LDA | A = M | N Z | imm $A9 · bp $A5 · bp,X $B5 · abs $AD · abs,X $BD · abs,Y $B9 · (bp,X) $A1 · (bp),Y $B1 · (bp),Z $B2 · [bp],Z $EA $B2 · (d,SP),Y $E2 |
6502; (bp),Z and (d,SP),Y CE; [bp],Z GS |
| LDX | X = M | N Z | imm $A2 · bp $A6 · bp,Y $B6 · abs $AE · abs,Y $BE |
6502 |
| LDY | Y = M | N Z | imm $A0 · bp $A4 · bp,X $B4 · abs $AC · abs,X $BC |
6502 |
| LDZ | Z = M | N Z | imm $A3 · abs $AB · abs,X $BB |
CE |
| LSR | Shift right; 0 into bit 7, bit 0 to C | N Z C | A $4A · bp $46 · bp,X $56 · abs $4E · abs,X $5E |
6502 |
| MAP | Set memory map from A, X, Y, Z; block interrupts until EOM | - | impl $5C |
4510 |
| NEG | A = 0 - A | N Z | impl $42 |
CE |
| NOP | See EOM | - | impl $EA |
6502 |
| ORA | A = A OR M | N Z | imm $09 · bp $05 · bp,X $15 · abs $0D · abs,X $1D · abs,Y $19 · (bp,X) $01 · (bp),Y $11 · (bp),Z $12 · [bp],Z $EA $12 |
6502; (bp),Z CE; [bp],Z GS |
| PHA | Push A | - | impl $48 |
6502 |
| PHP | Push P | - | impl $08 |
6502 |
| PHW | Push a 16-bit value, low byte first | - | imm16 $F4 · abs $FC |
CE |
| PHX | Push X | - | impl $DA |
C02 |
| PHY | Push Y | - | impl $5A |
C02 |
| PHZ | Push Z | - | impl $DB |
CE |
| PLA | Pull A | N Z | impl $68 |
6502 |
| PLP | Pull P | N V D I Z C | impl $28 |
6502 |
| PLX | Pull X | N Z | impl $FA |
C02 |
| PLY | Pull Y | N Z | impl $7A |
C02 |
| PLZ | Pull Z | N Z | impl $FB |
CE |
PLP and RTI restore N, V, D, I, Z and C from the
stack, but never E: only CLE and SEE change the stack mode (MEGA65 Book,
PLP and RTI instruction entries; mega65-core, gs4510.vhdl, September 2026).
INW increments a 16-bit value at a base page address, low byte first. It is the 45GS02's most common way to advance a pointer.
JMP (abs) with a vector at an address ending in
$FF behaves differently on the NMOS 6502, which fetches the
high byte from the start of the same page. Avoid placing vectors at
$xxFF, and code will behave the same on every member of the
family.
JSR (abs,X) calls through a table of 16-bit addresses. With X holding twice a command number, it dispatches commands in one instruction.
LDZ has no base page modes. To load Z from base page, use LDA and TAZ.
MAP reads its arguments from all four registers; see
Chapters 5 and 8. It also gives the megabyte selector when X or Z holds
$0F.
PHW pushes the low byte first, so the high byte
ends up at the lower stack address. That is the reverse of how JSR
leaves a return address, and it means a word pushed with PHW is not a
ready-made little-endian pointer for stack-relative addressing (mega65-core, gs4510.vhdl, September 2026;
Xemu, cpu65.c). PHW abs pushes the 16-bit contents of the address, not the
address itself.
| Mnemonic | Operation | Flags | Modes and opcodes | Origin |
|---|---|---|---|---|
| RMB0-7 | Clear bit n of a base page byte | - | RMB0 $07 · RMB1 $17 · RMB2 $27 · RMB3 $37 · RMB4 $47 · RMB5 $57 · RMB6 $67 · RMB7 $77 |
R |
| ROL | Rotate left through C | N Z C | A $2A · bp $26 · bp,X $36 · abs $2E · abs,X $3E |
6502 |
| ROR | Rotate right through C | N Z C | A $6A · bp $66 · bp,X $76 · abs $6E · abs,X $7E |
6502 |
| ROW | Rotate 16-bit word left through C | N Z C | abs $EB |
CE |
| RTI | Pull P and PC; return from interrupt | N V D I Z C | impl $40 |
6502 |
| RTN | Return from subroutine, then drop n bytes from the stack | - | imm $62 |
CE |
| RTS | Pull PC; return from subroutine | - | impl $60 |
6502 |
| SBC | A = A - M - (1 - C) | N V Z C | imm $E9 · bp $E5 · bp,X $F5 · abs $ED · abs,X $FD · abs,Y $F9 · (bp,X) $E1 · (bp),Y $F1 · (bp),Z $F2 · [bp],Z $EA $F2 |
6502; (bp),Z CE; [bp],Z GS |
| SEC | C = 1 | C | impl $38 |
6502 |
| SED | D = 1: decimal arithmetic | D | impl $F8 |
6502 |
| SEE | E = 1: 8-bit stack pointer | E | impl $03 |
CE |
| SEI | I = 1: block IRQ | I | impl $78 |
6502 |
| SMB0-7 | Set bit n of a base page byte | - | SMB0 $87 · SMB1 $97 · SMB2 $A7 · SMB3 $B7 · SMB4 $C7 · SMB5 $D7 · SMB6 $E7 · SMB7 $F7 |
R |
| STA | M = A | - | bp $85 · bp,X $95 · abs $8D · abs,X $9D · abs,Y $99 · (bp,X) $81 · (bp),Y $91 · (bp),Z $92 · [bp],Z $EA $92 · (d,SP),Y $82 |
6502; (bp),Z and (d,SP),Y CE; [bp],Z GS |
| STX | M = X | - | bp $86 · bp,Y $96 · abs $8E · abs,Y $9B |
6502; abs,Y CE |
| STY | M = Y | - | bp $84 · bp,X $94 · abs $8C · abs,X $8B |
6502; abs,X CE |
| STZ | M = Z register | - | bp $64 · bp,X $74 · abs $9C · abs,X $9E |
CE (65C02 opcodes, new meaning) |
RMB and SMB are two-byte instructions that change one bit without affecting the others or the flags. They are ideal for flag bytes shared between a main program and an interrupt handler, since each is a single uninterruptible instruction.
RTN #n pops the return address as RTS does, then discards n further bytes, cleaning up parameters the caller pushed before the call. It works only on core 0.97 and later; on earlier cores it fails, usually crashing the program (mega65-core PR #791).
SBC needs C set before a subtraction without borrow, as on the 6502.
STX abs,Y and STY abs,X fill gaps in the 6502's instruction set, which had only base page forms of indexed STX and STY.
STZ uses the same opcodes as the 65C02's "store zero" but stores the Z register. While Z is zero the result is identical; once a program uses Z for anything else, 65C02 code that relies on STZ to clear memory breaks. See Chapter 7.
| Mnemonic | Operation | Flags | Modes and opcodes | Origin |
|---|---|---|---|---|
| TAB | B = A: move the base page | - | impl $5B |
CE |
| TAX | X = A | N Z | impl $AA |
6502 |
| TAY | Y = A | N Z | impl $A8 |
6502 |
| TAZ | Z = A | N Z | impl $4B |
CE |
| TBA | A = B | N Z | impl $7B |
CE |
| TRB | M = M AND NOT A; Z from A AND M | Z | bp $14 · abs $1C |
C02 |
| TSB | M = M OR A; Z from A AND M | Z | bp $04 · abs $0C |
C02 |
| TSX | X = low byte of SP | N Z | impl $BA |
6502 |
| TSY | Y = high byte of SP | N Z | impl $0B |
CE |
| TXA | A = X | N Z | impl $8A |
6502 |
| TXS | Low byte of SP = X | - | impl $9A |
6502 |
| TYA | A = Y | N Z | impl $98 |
6502 |
| TYS | High byte of SP = Y | - | impl $2B |
CE |
| TZA | A = Z | N Z | impl $6B |
CE |
TAB takes effect immediately: the very next base page instruction uses the new page. Set B back to zero before calling the KERNAL or returning to BASIC.
TRB and TSB set or clear, in memory, the bits that
are set in A, and set the Z flag from the bits that were already common
to both. They are the natural way to change single bits of hardware
registers, such as LDA #$40 : TSB $D031, and they leave A
unchanged.
TSY and TYS reach the high byte of the stack pointer. With E set, the stack is 8 bits wide and wraps within a single 256-byte page, the page given by the high byte; it is page 1 after reset, and TYS can move it elsewhere. With E clear, the stack pointer is a full 16-bit value.
TXS sets only the low byte of SP. With the 16-bit stack enabled, set the high byte with TYS as well.
The quad instructions operate on the 32-bit Q register, formed from A
(bits 7-0), X (15-8), Y (23-16) and Z (31-24). Each is an ordinary 8-bit
instruction preceded by the prefix $42 $42; the opcodes
below give the full sequence. Flat indirect forms add the
$EA prefix after it.
| Mnemonic | Operation | Flags | Modes and opcodes |
|---|---|---|---|
| ADCQ | Q = Q + M + C | N V Z C | bp $42 $42 $65 · abs $42 $42 $6D · (bp) $42 $42 $72 · [bp] $42 $42 $EA $72 |
| ANDQ | Q = Q AND M | N Z | bp $42 $42 $25 · abs $42 $42 $2D · (bp) $42 $42 $32 · [bp] $42 $42 $EA $32 |
| ASLQ | Shift Q or M left | N Z C | Q $42 $42 $0A · bp $42 $42 $06 · bp,X $42 $42 $16 · abs $42 $42 $0E · abs,X $42 $42 $1E |
| ASRQ | Arithmetic shift right | N Z C | Q $42 $42 $43 · bp $42 $42 $44 · bp,X $42 $42 $54 |
| BITQ | Test Q AND M | N V Z | bp $42 $42 $24 · abs $42 $42 $2C |
| CMPQ | Compare Q with M | N Z C | bp $42 $42 $C5 · abs $42 $42 $CD · (bp) $42 $42 $D2 · [bp] $42 $42 $EA $D2 |
| DEQ | Q or M = value - 1 | N Z | Q $42 $42 $3A · bp $42 $42 $C6 · bp,X $42 $42 $D6 · abs $42 $42 $CE · abs,X $42 $42 $DE |
| EORQ | Q = Q XOR M | N Z | bp $42 $42 $45 · abs $42 $42 $4D · (bp) $42 $42 $52 · [bp] $42 $42 $EA $52 |
| INQ | Q or M = value + 1 | N Z | Q $42 $42 $1A · bp $42 $42 $E6 · bp,X $42 $42 $F6 · abs $42 $42 $EE · abs,X $42 $42 $FE |
| LDQ | Q = M | N Z | bp $42 $42 $A5 · abs $42 $42 $AD · (bp),Z $42 $42 $B2 · [bp],Z $42 $42 $EA $B2 |
| LSRQ | Shift Q or M right | N Z C | Q $42 $42 $4A · bp $42 $42 $46 · bp,X $42 $42 $56 · abs $42 $42 $4E · abs,X $42 $42 $5E |
| ORQ | Q = Q OR M | N Z | bp $42 $42 $05 · abs $42 $42 $0D · (bp) $42 $42 $12 · [bp] $42 $42 $EA $12 |
| ROLQ | Rotate Q or M left through C | N Z C | Q $42 $42 $2A · bp $42 $42 $26 · bp,X $42 $42 $36 · abs $42 $42 $2E · abs,X $42 $42 $3E |
| RORQ | Rotate Q or M right through C | N Z C | Q $42 $42 $6A · bp $42 $42 $66 · bp,X $42 $42 $76 · abs $42 $42 $6E · abs,X $42 $42 $7E |
| SBCQ | Q = Q - M - (1 - C) | N V Z C | bp $42 $42 $E5 · abs $42 $42 $ED · (bp) $42 $42 $F2 · [bp] $42 $42 $EA $F2 |
| STQ | M = Q | N Z (from A) | bp $42 $42 $85 · abs $42 $42 $8D · (bp) $42 $42 $92 · [bp] $42 $42 $EA $92 |
The mode list follows the cc65 assembler's 45GS02 table. Other assemblers name some of these differently: 64tass, for example, writes ADQ and LDQ as forms of its own mnemonics, and treats INQ and DEQ as implied-only, using other names for the memory forms. Check your assembler's documentation for the spelling it expects.
STQ changes flags. Unlike STA, STQ is not
flag-neutral. The CPU executes the $42 $42 prefix as two
NEG instructions before the store: A ends up unchanged, but N and Z are
set from it (MEGA65 Book, STQ instruction entry). Don't rely on flags
from an earlier instruction surviving an STQ. The other quad
instructions set N and Z from their own results, so the prefix makes no
difference to them.
Indirect quad modes are written (bp)
and [bp] for every instruction except LDQ, which cc65
writes (bp),Z and [bp],Z. Because Z is part of
Q, the other indirect quad instructions do not add Z to the pointer at
all; only LDQ does, which is why cc65 writes its modes with
,Z. Set Z to zero before an indirect LDQ (mega65-core, gs4510.vhdl, September 2026).
Flags reflect the whole 32-bit result: N is bit 31, and Z is set only if all 32 bits are zero.
Every quad instruction that changes Q changes A, X, Y and Z. Save any of them that hold values you still need.
The 45GS02 adds its extensions without new opcodes. Instead it gives special meaning to sequences of existing one-byte instructions placed in front of an ordinary instruction.
| Prefix | Bytes | Effect on the following instruction |
|---|---|---|
| NOP (EOM) | $EA |
A (bp),Z instruction uses a 32-bit pointer: flat
[bp],Z addressing |
| NEG NEG | $42 $42 |
The instruction operates on Q instead of A |
| NEG NEG NOP | $42 $42 $EA |
Both: a quad instruction with flat addressing |
NEG and NOP were chosen because they are single-cycle instructions on the C65's CPU, and the 65CE02 does not take an interrupt immediately after a one-cycle instruction. An interrupt therefore cannot arrive between a prefix and the instruction it modifies (Xemu issue #202).
Disassembly. A disassembler that does not know the
45GS02 shows prefixes as separate NEG and NOP instructions. Reading
NEG, NEG, LDA $10 as three
instructions gives the wrong meaning: it is a single
LDQ $10.
Self-modifying code. Code that patches an instruction must patch the whole prefixed sequence, and branch targets must point at the first prefix byte, not into the middle of the sequence.
Unintended prefixes. A NOP placed for timing or
padding immediately before a (bp),Z instruction turns it
into a flat access, and a NEG of A immediately followed by another NEG
creates a quad prefix. Place padding NOPs elsewhere, and do not negate A
twice in a row.
Code written for the 65C02 mostly runs unchanged, but five differences can catch it out:
| Opcode | 65C02 | 45GS02 |
|---|---|---|
$64 $74 $9C $9E |
STZ: store zero | STZ: store the Z register |
$12 $32 $52 $72 $92 $B2 $D2 $F2 |
(zp) indirect |
(bp),Z: the same while Z is zero |
$89 |
BIT immediate: sets only Z | BIT immediate: also sets N and V from the operand |
$CB |
WAI on WDC parts | ASW abs |
$DB |
STP on WDC parts | PHZ |
With Z held at zero, the first two differences disappear. The third matters to 65C02 code that tests N or V after a BIT immediate. The last two matter only for code written for WDC's 65C02 variant, which the MEGA65 has never needed to run.