#!/usr/bin/env python3 # Minimal 6502 CPU emulator -- just enough to run the Space Taxi # level decompressor at $6283 against a captured 64KB RAM dump. # # Scope: implements the opcodes used by $6283 / $9656 / $964A / $96A3 # and their helpers. Not a general-purpose 6502 emulator; it has no # decimal mode, no BRK handling, no NMI/IRQ -- the routine runs with # SEI in effect and never returns control. # # Flags tracked: N Z C. V (overflow) is computed for ADC/SBC since # those instructions set it, even if no branch tests it. D (decimal) # is ignored. class Cpu6502: def __init__(self, ram): # ram is a bytearray of 65536 bytes. Caller pre-loaded the dump. self.ram = ram self.a = 0 self.x = 0 self.y = 0 self.sp = 0xFF self.pc = 0 self.n = self.z = self.c = self.v = False # Stop tracking when RTS unwinds to this depth (set by run()). self._depth_floor = 0 # ---- memory ---- def read8(self, addr): return self.ram[addr & 0xFFFF] def write8(self, addr, val): self.ram[addr & 0xFFFF] = val & 0xFF def read16(self, addr): return self.ram[addr & 0xFFFF] | (self.ram[(addr + 1) & 0xFFFF] << 8) # ---- stack ---- def push8(self, val): self.ram[0x100 + self.sp] = val & 0xFF self.sp = (self.sp - 1) & 0xFF def pop8(self): self.sp = (self.sp + 1) & 0xFF return self.ram[0x100 + self.sp] def push16(self, val): self.push8((val >> 8) & 0xFF) self.push8(val & 0xFF) def pop16(self): lo = self.pop8() hi = self.pop8() return (hi << 8) | lo # ---- flag helpers ---- def set_nz(self, val): val &= 0xFF self.z = (val == 0) self.n = (val & 0x80) != 0 return val def pack_p(self): # B and U are usually set when pushed by PHP/BRK. p = 0x20 if self.n: p |= 0x80 if self.v: p |= 0x40 if self.z: p |= 0x02 if self.c: p |= 0x01 return p | 0x10 # B = 1 when pushed by PHP def unpack_p(self, p): self.n = (p & 0x80) != 0 self.v = (p & 0x40) != 0 self.z = (p & 0x02) != 0 self.c = (p & 0x01) != 0 # ---- addressing helpers (return effective address) ---- def addr_imm(self): a = self.pc; self.pc = (self.pc + 1) & 0xFFFF; return a def addr_zp(self): a = self.read8(self.pc); self.pc = (self.pc + 1) & 0xFFFF; return a def addr_zpx(self): a = (self.read8(self.pc) + self.x) & 0xFF; self.pc = (self.pc + 1) & 0xFFFF; return a def addr_abs(self): a = self.read16(self.pc); self.pc = (self.pc + 2) & 0xFFFF; return a def addr_absx(self): a = (self.read16(self.pc) + self.x) & 0xFFFF; self.pc = (self.pc + 2) & 0xFFFF; return a def addr_absy(self): a = (self.read16(self.pc) + self.y) & 0xFFFF; self.pc = (self.pc + 2) & 0xFFFF; return a def addr_indy(self): zp = self.read8(self.pc); self.pc = (self.pc + 1) & 0xFFFF base = self.ram[zp] | (self.ram[(zp + 1) & 0xFF] << 8) return (base + self.y) & 0xFFFF # ---- branch helper ---- def branch(self, cond): off = self.read8(self.pc); self.pc = (self.pc + 1) & 0xFFFF if off >= 0x80: off -= 0x100 if cond: self.pc = (self.pc + off) & 0xFFFF # ---- step ---- def step(self): op = self.read8(self.pc) self.pc = (self.pc + 1) & 0xFFFF f = _DISPATCH.get(op) if f is None: raise NotImplementedError(f"opcode ${op:02X} at PC ${(self.pc-1)&0xFFFF:04X}") f(self) def call(self, target, max_steps=10_000_000): """Call subroutine at `target` as if via JSR. Returns when the matching RTS pops the stack back below the original SP. Hard cap on steps to avoid runaway.""" # Push a sentinel return address. When RTS pops to this, stop. # Use $FFFF as sentinel: subsequent step would attempt to fetch # from $FFFF; we detect via depth floor instead. original_sp = self.sp self.push16(0xFFFE) # RTS will pop this, then step will land at $FFFF self.pc = target & 0xFFFF for _ in range(max_steps): if self.pc == 0xFFFF: return self.step() raise RuntimeError(f"6502 call exceeded {max_steps} steps; PC=${self.pc:04X}") # ---- opcode implementations ---- # Each takes the cpu and reads remaining operand bytes via cpu.addr_*. def _NOP(cpu): pass def _SEI(cpu): pass # we don't model interrupts def _CLD(cpu): pass # no decimal mode def _SEC(cpu): cpu.c = True def _CLC(cpu): cpu.c = False def _PHP(cpu): cpu.push8(cpu.pack_p()) def _PLP(cpu): cpu.unpack_p(cpu.pop8()) def _PHA(cpu): cpu.push8(cpu.a) def _PLA(cpu): cpu.a = cpu.set_nz(cpu.pop8()) def _TXA(cpu): cpu.a = cpu.set_nz(cpu.x) def _TAX(cpu): cpu.x = cpu.set_nz(cpu.a) def _TYA(cpu): cpu.a = cpu.set_nz(cpu.y) def _TAY(cpu): cpu.y = cpu.set_nz(cpu.a) def _INX(cpu): cpu.x = cpu.set_nz((cpu.x + 1) & 0xFF) def _INY(cpu): cpu.y = cpu.set_nz((cpu.y + 1) & 0xFF) def _DEX(cpu): cpu.x = cpu.set_nz((cpu.x - 1) & 0xFF) def _DEY(cpu): cpu.y = cpu.set_nz((cpu.y - 1) & 0xFF) def _LDA_imm(cpu): cpu.a = cpu.set_nz(cpu.read8(cpu.addr_imm())) def _LDA_zp(cpu): cpu.a = cpu.set_nz(cpu.read8(cpu.addr_zp())) def _LDA_zpx(cpu): cpu.a = cpu.set_nz(cpu.read8(cpu.addr_zpx())) def _LDA_abs(cpu): cpu.a = cpu.set_nz(cpu.read8(cpu.addr_abs())) def _LDA_absx(cpu): cpu.a = cpu.set_nz(cpu.read8(cpu.addr_absx())) def _LDA_absy(cpu): cpu.a = cpu.set_nz(cpu.read8(cpu.addr_absy())) def _LDA_indy(cpu): cpu.a = cpu.set_nz(cpu.read8(cpu.addr_indy())) def _LDX_imm(cpu): cpu.x = cpu.set_nz(cpu.read8(cpu.addr_imm())) def _LDX_abs(cpu): cpu.x = cpu.set_nz(cpu.read8(cpu.addr_abs())) def _LDX_absy(cpu): cpu.x = cpu.set_nz(cpu.read8(cpu.addr_absy())) def _LDX_zp(cpu): cpu.x = cpu.set_nz(cpu.read8(cpu.addr_zp())) def _LDY_imm(cpu): cpu.y = cpu.set_nz(cpu.read8(cpu.addr_imm())) def _LDY_abs(cpu): cpu.y = cpu.set_nz(cpu.read8(cpu.addr_abs())) def _LDY_absx(cpu): cpu.y = cpu.set_nz(cpu.read8(cpu.addr_absx())) def _LDY_zp(cpu): cpu.y = cpu.set_nz(cpu.read8(cpu.addr_zp())) def _STA_zp(cpu): cpu.write8(cpu.addr_zp(), cpu.a) def _STA_zpx(cpu): cpu.write8(cpu.addr_zpx(), cpu.a) def _STA_abs(cpu): cpu.write8(cpu.addr_abs(), cpu.a) def _STA_absx(cpu): cpu.write8(cpu.addr_absx(), cpu.a) def _STA_absy(cpu): cpu.write8(cpu.addr_absy(), cpu.a) def _STA_indy(cpu): cpu.write8(cpu.addr_indy(), cpu.a) def _STX_zp(cpu): cpu.write8(cpu.addr_zp(), cpu.x) def _STX_abs(cpu): cpu.write8(cpu.addr_abs(), cpu.x) def _STY_zp(cpu): cpu.write8(cpu.addr_zp(), cpu.y) def _STY_abs(cpu): cpu.write8(cpu.addr_abs(), cpu.y) def _AND_imm(cpu): cpu.a = cpu.set_nz(cpu.a & cpu.read8(cpu.addr_imm())) def _AND_zp(cpu): cpu.a = cpu.set_nz(cpu.a & cpu.read8(cpu.addr_zp())) def _AND_abs(cpu): cpu.a = cpu.set_nz(cpu.a & cpu.read8(cpu.addr_abs())) def _ORA_imm(cpu): cpu.a = cpu.set_nz(cpu.a | cpu.read8(cpu.addr_imm())) def _ORA_zp(cpu): cpu.a = cpu.set_nz(cpu.a | cpu.read8(cpu.addr_zp())) def _EOR_imm(cpu): cpu.a = cpu.set_nz(cpu.a ^ cpu.read8(cpu.addr_imm())) def _EOR_abs(cpu): cpu.a = cpu.set_nz(cpu.a ^ cpu.read8(cpu.addr_abs())) def _adc(cpu, m): r = cpu.a + m + (1 if cpu.c else 0) cpu.c = r > 0xFF cpu.v = ((cpu.a ^ r) & (m ^ r) & 0x80) != 0 cpu.a = cpu.set_nz(r & 0xFF) def _ADC_imm(cpu): _adc(cpu, cpu.read8(cpu.addr_imm())) def _ADC_zp(cpu): _adc(cpu, cpu.read8(cpu.addr_zp())) def _ADC_abs(cpu): _adc(cpu, cpu.read8(cpu.addr_abs())) def _ADC_absy(cpu): _adc(cpu, cpu.read8(cpu.addr_absy())) def _sbc(cpu, m): _adc(cpu, m ^ 0xFF) def _SBC_imm(cpu): _sbc(cpu, cpu.read8(cpu.addr_imm())) def _SBC_zp(cpu): _sbc(cpu, cpu.read8(cpu.addr_zp())) def _SBC_abs(cpu): _sbc(cpu, cpu.read8(cpu.addr_abs())) def _SBC_absx(cpu): _sbc(cpu, cpu.read8(cpu.addr_absx())) def _SBC_absy(cpu): _sbc(cpu, cpu.read8(cpu.addr_absy())) def _AND_absx(cpu): cpu.a = cpu.set_nz(cpu.a & cpu.read8(cpu.addr_absx())) def _AND_absy(cpu): cpu.a = cpu.set_nz(cpu.a & cpu.read8(cpu.addr_absy())) def _AND_indy(cpu): cpu.a = cpu.set_nz(cpu.a & cpu.read8(cpu.addr_indy())) def _ORA_absx(cpu): cpu.a = cpu.set_nz(cpu.a | cpu.read8(cpu.addr_absx())) def _ORA_abs(cpu): cpu.a = cpu.set_nz(cpu.a | cpu.read8(cpu.addr_abs())) def _ORA_zpx(cpu): cpu.a = cpu.set_nz(cpu.a | cpu.read8(cpu.addr_zpx())) def _ORA_indy(cpu): cpu.a = cpu.set_nz(cpu.a | cpu.read8(cpu.addr_indy())) def _EOR_zp(cpu): cpu.a = cpu.set_nz(cpu.a ^ cpu.read8(cpu.addr_zp())) def _EOR_zpx(cpu): cpu.a = cpu.set_nz(cpu.a ^ cpu.read8(cpu.addr_zpx())) def _EOR_absx(cpu): cpu.a = cpu.set_nz(cpu.a ^ cpu.read8(cpu.addr_absx())) def _EOR_absy(cpu): cpu.a = cpu.set_nz(cpu.a ^ cpu.read8(cpu.addr_absy())) def _ADC_zpx(cpu): _adc(cpu, cpu.read8(cpu.addr_zpx())) def _ADC_absx(cpu): _adc(cpu, cpu.read8(cpu.addr_absx())) def _CMP_absx(cpu): _cmp_with(cpu, cpu.a, cpu.read8(cpu.addr_absx())) def _CMP_absy(cpu): _cmp_with(cpu, cpu.a, cpu.read8(cpu.addr_absy())) def _CMP_zpx(cpu): _cmp_with(cpu, cpu.a, cpu.read8(cpu.addr_zpx())) def _JMP_ind(cpu): addr = cpu.addr_abs() cpu.pc = cpu.read8(addr) | (cpu.read8((addr & 0xFF00) | ((addr + 1) & 0xFF)) << 8) def _BIT_zp(cpu): v = cpu.read8(cpu.addr_zp()) cpu.z = (cpu.a & v) == 0 cpu.n = (v & 0x80) != 0 cpu.v = (v & 0x40) != 0 def _BIT_abs(cpu): v = cpu.read8(cpu.addr_abs()) cpu.z = (cpu.a & v) == 0 cpu.n = (v & 0x80) != 0 cpu.v = (v & 0x40) != 0 def _ASL_zp(cpu): addr = cpu.addr_zp() v = cpu.read8(addr) cpu.c = (v & 0x80) != 0 cpu.write8(addr, cpu.set_nz((v << 1) & 0xFF)) def _ASL_abs(cpu): addr = cpu.addr_abs() v = cpu.read8(addr) cpu.c = (v & 0x80) != 0 cpu.write8(addr, cpu.set_nz((v << 1) & 0xFF)) def _LSR_abs(cpu): addr = cpu.addr_abs() v = cpu.read8(addr) cpu.c = (v & 0x01) != 0 cpu.write8(addr, cpu.set_nz(v >> 1)) def _ROL_abs(cpu): addr = cpu.addr_abs() v = cpu.read8(addr) new_c = (v & 0x80) != 0 v = ((v << 1) | (1 if cpu.c else 0)) & 0xFF cpu.write8(addr, cpu.set_nz(v)) cpu.c = new_c def _ROR_abs(cpu): addr = cpu.addr_abs() v = cpu.read8(addr) new_c = (v & 0x01) != 0 v = ((v >> 1) | (0x80 if cpu.c else 0)) & 0xFF cpu.write8(addr, cpu.set_nz(v)) cpu.c = new_c def _ROR_zp(cpu): addr = cpu.addr_zp() v = cpu.read8(addr) new_c = (v & 0x01) != 0 v = ((v >> 1) | (0x80 if cpu.c else 0)) & 0xFF cpu.write8(addr, cpu.set_nz(v)) cpu.c = new_c def _STA_zpx(cpu_): cpu_.write8(cpu_.addr_zpx(), cpu_.a) def _TSX(cpu): cpu.x = cpu.set_nz(cpu.sp) def _TXS(cpu): cpu.sp = cpu.x def _CLI(cpu): pass def _CLV(cpu): cpu.v = False def _SED(cpu): pass # decimal mode ignored def _STX_zpy(cpu): a = (cpu.read8(cpu.pc) + cpu.y) & 0xFF; cpu.pc = (cpu.pc + 1) & 0xFFFF cpu.write8(a, cpu.x) def _STY_zpx(cpu): cpu.write8(cpu.addr_zpx(), cpu.y) def _LDX_zpy(cpu): a = (cpu.read8(cpu.pc) + cpu.y) & 0xFF; cpu.pc = (cpu.pc + 1) & 0xFFFF cpu.x = cpu.set_nz(cpu.read8(a)) def _LDY_zpx(cpu): cpu.y = cpu.set_nz(cpu.read8(cpu.addr_zpx())) def _cmp_with(cpu, lhs, m): r = (lhs - m) & 0x1FF cpu.c = lhs >= m cpu.set_nz(r & 0xFF) def _CMP_imm(cpu): _cmp_with(cpu, cpu.a, cpu.read8(cpu.addr_imm())) def _CMP_zp(cpu): _cmp_with(cpu, cpu.a, cpu.read8(cpu.addr_zp())) def _CMP_abs(cpu): _cmp_with(cpu, cpu.a, cpu.read8(cpu.addr_abs())) def _CPX_imm(cpu): _cmp_with(cpu, cpu.x, cpu.read8(cpu.addr_imm())) def _CPX_abs(cpu): _cmp_with(cpu, cpu.x, cpu.read8(cpu.addr_abs())) def _CPY_imm(cpu): _cmp_with(cpu, cpu.y, cpu.read8(cpu.addr_imm())) def _ASL_a(cpu): cpu.c = (cpu.a & 0x80) != 0 cpu.a = cpu.set_nz((cpu.a << 1) & 0xFF) def _LSR_a(cpu): cpu.c = (cpu.a & 0x01) != 0 cpu.a = cpu.set_nz(cpu.a >> 1) def _LSR_zp(cpu): addr = cpu.addr_zp() v = cpu.read8(addr) cpu.c = (v & 0x01) != 0 cpu.write8(addr, cpu.set_nz(v >> 1)) def _ROL_a(cpu): new_c = (cpu.a & 0x80) != 0 cpu.a = cpu.set_nz(((cpu.a << 1) | (1 if cpu.c else 0)) & 0xFF) cpu.c = new_c def _ROL_zp(cpu): addr = cpu.addr_zp() v = cpu.read8(addr) new_c = (v & 0x80) != 0 v = ((v << 1) | (1 if cpu.c else 0)) & 0xFF cpu.write8(addr, cpu.set_nz(v)) cpu.c = new_c def _ROR_a(cpu): new_c = (cpu.a & 0x01) != 0 cpu.a = cpu.set_nz(((cpu.a >> 1) | (0x80 if cpu.c else 0)) & 0xFF) cpu.c = new_c def _INC_abs(cpu): addr = cpu.addr_abs() cpu.write8(addr, cpu.set_nz((cpu.read8(addr) + 1) & 0xFF)) def _INC_absx(cpu): addr = cpu.addr_absx() cpu.write8(addr, cpu.set_nz((cpu.read8(addr) + 1) & 0xFF)) def _INC_zp(cpu): addr = cpu.addr_zp() cpu.write8(addr, cpu.set_nz((cpu.read8(addr) + 1) & 0xFF)) def _INC_zpx(cpu): addr = cpu.addr_zpx() cpu.write8(addr, cpu.set_nz((cpu.read8(addr) + 1) & 0xFF)) def _DEC_abs(cpu): addr = cpu.addr_abs() cpu.write8(addr, cpu.set_nz((cpu.read8(addr) - 1) & 0xFF)) def _DEC_absx(cpu): addr = cpu.addr_absx() cpu.write8(addr, cpu.set_nz((cpu.read8(addr) - 1) & 0xFF)) def _DEC_zp(cpu): addr = cpu.addr_zp() cpu.write8(addr, cpu.set_nz((cpu.read8(addr) - 1) & 0xFF)) def _DEC_zpx(cpu): addr = cpu.addr_zpx() cpu.write8(addr, cpu.set_nz((cpu.read8(addr) - 1) & 0xFF)) def _ASL_zpx(cpu): addr = cpu.addr_zpx() v = cpu.read8(addr) cpu.c = (v & 0x80) != 0 cpu.write8(addr, cpu.set_nz((v << 1) & 0xFF)) def _ASL_absx(cpu): addr = cpu.addr_absx() v = cpu.read8(addr) cpu.c = (v & 0x80) != 0 cpu.write8(addr, cpu.set_nz((v << 1) & 0xFF)) def _LSR_zpx(cpu): addr = cpu.addr_zpx() v = cpu.read8(addr) cpu.c = (v & 0x01) != 0 cpu.write8(addr, cpu.set_nz(v >> 1)) def _LSR_absx(cpu): addr = cpu.addr_absx() v = cpu.read8(addr) cpu.c = (v & 0x01) != 0 cpu.write8(addr, cpu.set_nz(v >> 1)) def _ROL_zpx(cpu): addr = cpu.addr_zpx() v = cpu.read8(addr) new_c = (v & 0x80) != 0 v = ((v << 1) | (1 if cpu.c else 0)) & 0xFF cpu.write8(addr, cpu.set_nz(v)) cpu.c = new_c def _ROL_absx(cpu): addr = cpu.addr_absx() v = cpu.read8(addr) new_c = (v & 0x80) != 0 v = ((v << 1) | (1 if cpu.c else 0)) & 0xFF cpu.write8(addr, cpu.set_nz(v)) cpu.c = new_c def _ROR_zpx(cpu): addr = cpu.addr_zpx() v = cpu.read8(addr) new_c = (v & 0x01) != 0 v = ((v >> 1) | (0x80 if cpu.c else 0)) & 0xFF cpu.write8(addr, cpu.set_nz(v)) cpu.c = new_c def _ROR_absx(cpu): addr = cpu.addr_absx() v = cpu.read8(addr) new_c = (v & 0x01) != 0 v = ((v >> 1) | (0x80 if cpu.c else 0)) & 0xFF cpu.write8(addr, cpu.set_nz(v)) cpu.c = new_c def _LDA_indx(cpu): zp = cpu.read8(cpu.pc); cpu.pc = (cpu.pc + 1) & 0xFFFF addr_ptr = (zp + cpu.x) & 0xFF addr = cpu.ram[addr_ptr] | (cpu.ram[(addr_ptr + 1) & 0xFF] << 8) cpu.a = cpu.set_nz(cpu.read8(addr)) def _STA_indx(cpu): zp = cpu.read8(cpu.pc); cpu.pc = (cpu.pc + 1) & 0xFFFF addr_ptr = (zp + cpu.x) & 0xFF addr = cpu.ram[addr_ptr] | (cpu.ram[(addr_ptr + 1) & 0xFF] << 8) cpu.write8(addr, cpu.a) def _AND_indx(cpu): zp = cpu.read8(cpu.pc); cpu.pc = (cpu.pc + 1) & 0xFFFF addr_ptr = (zp + cpu.x) & 0xFF addr = cpu.ram[addr_ptr] | (cpu.ram[(addr_ptr + 1) & 0xFF] << 8) cpu.a = cpu.set_nz(cpu.a & cpu.read8(addr)) def _ORA_indx(cpu): zp = cpu.read8(cpu.pc); cpu.pc = (cpu.pc + 1) & 0xFFFF addr_ptr = (zp + cpu.x) & 0xFF addr = cpu.ram[addr_ptr] | (cpu.ram[(addr_ptr + 1) & 0xFF] << 8) cpu.a = cpu.set_nz(cpu.a | cpu.read8(addr)) def _EOR_indx(cpu): zp = cpu.read8(cpu.pc); cpu.pc = (cpu.pc + 1) & 0xFFFF addr_ptr = (zp + cpu.x) & 0xFF addr = cpu.ram[addr_ptr] | (cpu.ram[(addr_ptr + 1) & 0xFF] << 8) cpu.a = cpu.set_nz(cpu.a ^ cpu.read8(addr)) def _ADC_indx(cpu): zp = cpu.read8(cpu.pc); cpu.pc = (cpu.pc + 1) & 0xFFFF addr_ptr = (zp + cpu.x) & 0xFF addr = cpu.ram[addr_ptr] | (cpu.ram[(addr_ptr + 1) & 0xFF] << 8) _adc(cpu, cpu.read8(addr)) def _SBC_indx(cpu): zp = cpu.read8(cpu.pc); cpu.pc = (cpu.pc + 1) & 0xFFFF addr_ptr = (zp + cpu.x) & 0xFF addr = cpu.ram[addr_ptr] | (cpu.ram[(addr_ptr + 1) & 0xFF] << 8) _sbc(cpu, cpu.read8(addr)) def _CMP_indx(cpu): zp = cpu.read8(cpu.pc); cpu.pc = (cpu.pc + 1) & 0xFFFF addr_ptr = (zp + cpu.x) & 0xFF addr = cpu.ram[addr_ptr] | (cpu.ram[(addr_ptr + 1) & 0xFF] << 8) _cmp_with(cpu, cpu.a, cpu.read8(addr)) def _CPX_zp(cpu): _cmp_with(cpu, cpu.x, cpu.read8(cpu.addr_zp())) def _CPY_zp(cpu): _cmp_with(cpu, cpu.y, cpu.read8(cpu.addr_zp())) def _BPL(cpu): cpu.branch(not cpu.n) def _BMI(cpu): cpu.branch(cpu.n) def _BNE(cpu): cpu.branch(not cpu.z) def _BEQ(cpu): cpu.branch(cpu.z) def _BCC(cpu): cpu.branch(not cpu.c) def _BCS(cpu): cpu.branch(cpu.c) def _BVC(cpu): cpu.branch(not cpu.v) def _BVS(cpu): cpu.branch(cpu.v) def _JMP_abs(cpu): cpu.pc = cpu.addr_abs() def _JSR(cpu): target = cpu.addr_abs() cpu.push16((cpu.pc - 1) & 0xFFFF) cpu.pc = target def _RTS(cpu): cpu.pc = (cpu.pop16() + 1) & 0xFFFF # Build dispatch table _DISPATCH = { 0x00: _NOP, # treat BRK as NOP (we never expect it) 0x18: _CLC, 0x38: _SEC, 0x58: _NOP, 0x78: _SEI, 0xD8: _CLD, 0x08: _PHP, 0x28: _PLP, 0x48: _PHA, 0x68: _PLA, 0x8A: _TXA, 0xAA: _TAX, 0x98: _TYA, 0xA8: _TAY, 0xE8: _INX, 0xC8: _INY, 0xCA: _DEX, 0x88: _DEY, 0xA9: _LDA_imm, 0xA5: _LDA_zp, 0xB5: _LDA_zpx, 0xAD: _LDA_abs, 0xBD: _LDA_absx, 0xB9: _LDA_absy, 0xB1: _LDA_indy, 0xA2: _LDX_imm, 0xAE: _LDX_abs, 0xBE: _LDX_absy, 0xA6: _LDX_zp, 0xA0: _LDY_imm, 0xAC: _LDY_abs, 0xBC: _LDY_absx, 0xA4: _LDY_zp, 0x85: _STA_zp, 0x95: _STA_zpx, 0x8D: _STA_abs, 0x9D: _STA_absx, 0x99: _STA_absy, 0x91: _STA_indy, 0x86: _STX_zp, 0x8E: _STX_abs, 0x84: _STY_zp, 0x8C: _STY_abs, 0x29: _AND_imm, 0x25: _AND_zp, 0x2D: _AND_abs, 0x3D: _AND_absx, 0x39: _AND_absy, 0x31: _AND_indy, 0x09: _ORA_imm, 0x05: _ORA_zp, 0x0D: _ORA_abs, 0x15: _ORA_zpx, 0x1D: _ORA_absx, 0x11: _ORA_indy, 0x49: _EOR_imm, 0x4D: _EOR_abs, 0x45: _EOR_zp, 0x55: _EOR_zpx, 0x5D: _EOR_absx, 0x59: _EOR_absy, 0x69: _ADC_imm, 0x65: _ADC_zp, 0x6D: _ADC_abs, 0x79: _ADC_absy, 0x75: _ADC_zpx, 0x7D: _ADC_absx, 0xE9: _SBC_imm, 0xE5: _SBC_zp, 0xED: _SBC_abs, 0xFD: _SBC_absx, 0xF9: _SBC_absy, 0xC9: _CMP_imm, 0xC5: _CMP_zp, 0xCD: _CMP_abs, 0xD5: _CMP_zpx, 0xDD: _CMP_absx, 0xD9: _CMP_absy, 0xE0: _CPX_imm, 0xEC: _CPX_abs, 0xC0: _CPY_imm, 0x24: _BIT_zp, 0x2C: _BIT_abs, 0x0A: _ASL_a, 0x06: _ASL_zp, 0x0E: _ASL_abs, 0x4A: _LSR_a, 0x46: _LSR_zp, 0x4E: _LSR_abs, 0x2A: _ROL_a, 0x26: _ROL_zp, 0x2E: _ROL_abs, 0x6A: _ROR_a, 0x66: _ROR_zp, 0x6E: _ROR_abs, 0xEE: _INC_abs, 0xFE: _INC_absx, 0xE6: _INC_zp, 0xF6: _INC_zpx, 0xCE: _DEC_abs, 0xDE: _DEC_absx, 0xC6: _DEC_zp, 0xD6: _DEC_zpx, 0x16: _ASL_zpx, 0x1E: _ASL_absx, 0x56: _LSR_zpx, 0x5E: _LSR_absx, 0x36: _ROL_zpx, 0x3E: _ROL_absx, 0x76: _ROR_zpx, 0x7E: _ROR_absx, 0xA1: _LDA_indx, 0x81: _STA_indx, 0x21: _AND_indx, 0x01: _ORA_indx, 0x41: _EOR_indx, 0x61: _ADC_indx, 0xE1: _SBC_indx, 0xC1: _CMP_indx, 0xE4: _CPX_zp, 0xC4: _CPY_zp, 0x6C: _JMP_ind, 0x9A: _TXS, 0xBA: _TSX, 0x58: _CLI, 0xB8: _CLV, 0xF8: _SED, 0x96: _STX_zpy, 0x94: _STY_zpx, 0xB6: _LDX_zpy, 0xB4: _LDY_zpx, 0x10: _BPL, 0x30: _BMI, 0xD0: _BNE, 0xF0: _BEQ, 0x90: _BCC, 0xB0: _BCS, 0x50: _BVC, 0x70: _BVS, 0x4C: _JMP_abs, 0x20: _JSR, 0x60: _RTS, 0xEA: _NOP, }