mirror of
https://github.com/mnaberez/py65.git
synced 2024-06-08 03:29:32 +00:00
1322 lines
37 KiB
Python
1322 lines
37 KiB
Python
import sys
|
|
|
|
from py65.utils.conversions import itoa
|
|
from py65.utils.devices import make_instruction_decorator
|
|
from py65 import disassembler
|
|
|
|
class MPU:
|
|
# vectors
|
|
RESET = 0xfffc
|
|
NMI = 0xfffa
|
|
IRQ = 0xfffe
|
|
|
|
# processor flags
|
|
NEGATIVE = 128
|
|
OVERFLOW = 64
|
|
UNUSED = 32
|
|
BREAK = 16
|
|
DECIMAL = 8
|
|
INTERRUPT = 4
|
|
ZERO = 2
|
|
CARRY = 1
|
|
|
|
BYTE_WIDTH = 8
|
|
BYTE_FORMAT = "%02x"
|
|
ADDR_WIDTH = 16
|
|
ADDR_FORMAT = "%04x"
|
|
|
|
def __init__(self, memory=None, pc=0x0000):
|
|
# config
|
|
self.name = '6502'
|
|
self.byteMask = ((1 << self.BYTE_WIDTH) - 1)
|
|
self.addrMask = ((1 << self.ADDR_WIDTH) - 1)
|
|
self.addrHighMask = (self.byteMask << self.BYTE_WIDTH)
|
|
self.spBase = 1 << self.BYTE_WIDTH
|
|
|
|
# vm status
|
|
self.excycles = 0
|
|
self.addcycles = False
|
|
self.processorCycles = 0
|
|
|
|
if memory is None:
|
|
memory = 0x10000 * [0x00]
|
|
self.memory = memory
|
|
self.start_pc = pc # if None, reset vector is used
|
|
|
|
self.disassembler = disassembler.Disassembler(self)
|
|
|
|
# init
|
|
self.reset()
|
|
|
|
def reprformat(self):
|
|
return ("%s PC AC XR YR SP NV-BDIZC\n"
|
|
"%s: %04x %02x %02x %02x %02x %s")
|
|
|
|
def __repr__(self):
|
|
flags = itoa(self.p, 2).rjust(self.BYTE_WIDTH, '0')
|
|
indent = ' ' * (len(self.name) + 2)
|
|
|
|
return self.reprformat() % (indent, self.name, self.pc, self.a,
|
|
self.x, self.y, self.sp, flags)
|
|
|
|
def step(self, trace=False):
|
|
instructCode = self.memory[self.pc]
|
|
if trace:
|
|
out = str(self) + " $%04X: %s" % (
|
|
self.pc, self.disassembler.instruction_at(self.pc)[1])
|
|
print >> sys.stderr, "\n".join(out.split('\n'))
|
|
self.pc = (self.pc + 1) & self.addrMask
|
|
self.excycles = 0
|
|
self.addcycles = self.extracycles[instructCode]
|
|
self.instruct[instructCode](self)
|
|
self.pc &= self.addrMask
|
|
self.processorCycles += self.cycletime[instructCode] + self.excycles
|
|
return self
|
|
|
|
def reset(self):
|
|
self.pc = self.start_pc
|
|
if self.pc is None:
|
|
self.pc = self.WordAt(self.RESET)
|
|
self.sp = self.byteMask
|
|
self.a = 0
|
|
self.x = 0
|
|
self.y = 0
|
|
self.p = self.BREAK | self.UNUSED
|
|
self.processorCycles = 0
|
|
|
|
def irq(self):
|
|
# triggers a normal IRQ
|
|
# this is very similar to the BRK instruction
|
|
if self.p & self.INTERRUPT:
|
|
return
|
|
self.stPushWord(self.pc)
|
|
self.p &= ~self.BREAK
|
|
self.stPush(self.p | self.UNUSED)
|
|
self.p |= self.INTERRUPT
|
|
self.pc = self.WordAt(self.IRQ)
|
|
self.processorCycles += 7
|
|
|
|
def nmi(self):
|
|
# triggers a NMI IRQ in the processor
|
|
# this is very similar to the BRK instruction
|
|
self.stPushWord(self.pc)
|
|
self.p &= ~self.BREAK
|
|
self.stPush(self.p | self.UNUSED)
|
|
self.p |= self.INTERRUPT
|
|
self.pc = self.WordAt(self.NMI)
|
|
self.processorCycles += 7
|
|
|
|
# Helpers for addressing modes
|
|
|
|
def ByteAt(self, addr):
|
|
return self.memory[addr]
|
|
|
|
def WordAt(self, addr):
|
|
return self.ByteAt(addr) + (self.ByteAt(addr + 1) << self.BYTE_WIDTH)
|
|
|
|
def WrapAt(self, addr):
|
|
wrap = lambda x: (x & self.addrHighMask) + ((x + 1) & self.byteMask)
|
|
return self.ByteAt(addr) + (self.ByteAt(wrap(addr)) << self.BYTE_WIDTH)
|
|
|
|
def ProgramCounter(self):
|
|
return self.pc
|
|
|
|
# Addressing modes
|
|
|
|
def ImmediateByte(self):
|
|
return self.ByteAt(self.pc)
|
|
|
|
def ZeroPageAddr(self):
|
|
return self.ByteAt(self.pc)
|
|
|
|
def ZeroPageXAddr(self):
|
|
return self.byteMask & (self.x + self.ByteAt(self.pc))
|
|
|
|
def ZeroPageYAddr(self):
|
|
return self.byteMask & (self.y + self.ByteAt(self.pc))
|
|
|
|
def IndirectXAddr(self):
|
|
return self.WrapAt(self.byteMask & (self.ByteAt(self.pc) + self.x))
|
|
|
|
def IndirectYAddr(self):
|
|
if self.addcycles:
|
|
a1 = self.WrapAt(self.ByteAt(self.pc))
|
|
a2 = (a1 + self.y) & self.addrMask
|
|
if (a1 & self.addrHighMask) != (a2 & self.addrHighMask):
|
|
self.excycles += 1
|
|
return a2
|
|
else:
|
|
return (self.WrapAt(self.ByteAt(self.pc)) + self.y) & self.addrMask
|
|
|
|
def AbsoluteAddr(self):
|
|
return self.WordAt(self.pc)
|
|
|
|
def AbsoluteXAddr(self):
|
|
if self.addcycles:
|
|
a1 = self.WordAt(self.pc)
|
|
a2 = (a1 + self.x) & self.addrMask
|
|
if (a1 & self.addrHighMask) != (a2 & self.addrHighMask):
|
|
self.excycles += 1
|
|
return a2
|
|
else:
|
|
return (self.WordAt(self.pc) + self.x) & self.addrMask
|
|
|
|
def AbsoluteYAddr(self):
|
|
if self.addcycles:
|
|
a1 = self.WordAt(self.pc)
|
|
a2 = (a1 + self.y) & self.addrMask
|
|
if (a1 & self.addrHighMask) != (a2 & self.addrHighMask):
|
|
self.excycles += 1
|
|
return a2
|
|
else:
|
|
return (self.WordAt(self.pc) + self.y) & self.addrMask
|
|
|
|
def BranchRelAddr(self):
|
|
self.excycles += 1
|
|
addr = self.ImmediateByte()
|
|
self.pc += 1
|
|
|
|
if addr & self.NEGATIVE:
|
|
addr = self.pc - (addr ^ self.byteMask) - 1
|
|
else:
|
|
addr = self.pc + addr
|
|
|
|
if (self.pc & self.addrHighMask) != (addr & self.addrHighMask):
|
|
self.excycles += 1
|
|
|
|
self.pc = addr & self.addrMask
|
|
|
|
# stack
|
|
|
|
def stPush(self, z):
|
|
self.memory[self.sp + self.spBase] = z & self.byteMask
|
|
self.sp -= 1
|
|
self.sp &= self.byteMask
|
|
|
|
def stPop(self):
|
|
self.sp += 1
|
|
self.sp &= self.byteMask
|
|
return self.ByteAt(self.sp + self.spBase)
|
|
|
|
def stPushWord(self, z):
|
|
self.stPush((z >> self.BYTE_WIDTH) & self.byteMask)
|
|
self.stPush(z & self.byteMask)
|
|
|
|
def stPopWord(self):
|
|
z = self.stPop()
|
|
z += self.stPop() << self.BYTE_WIDTH
|
|
return z
|
|
|
|
def FlagsNZ(self, value):
|
|
self.p &= ~(self.ZERO | self.NEGATIVE)
|
|
if value == 0:
|
|
self.p |= self.ZERO
|
|
else:
|
|
self.p |= value & self.NEGATIVE
|
|
|
|
# operations
|
|
|
|
def opORA(self, x):
|
|
self.a |= self.ByteAt(x())
|
|
self.FlagsNZ(self.a)
|
|
|
|
def opASL(self, x):
|
|
if x is None:
|
|
tbyte = self.a
|
|
else:
|
|
addr = x()
|
|
tbyte = self.ByteAt(addr)
|
|
|
|
self.p &= ~(self.CARRY | self.NEGATIVE | self.ZERO)
|
|
|
|
if tbyte & self.NEGATIVE:
|
|
self.p |= self.CARRY
|
|
tbyte = (tbyte << 1) & self.byteMask
|
|
|
|
if tbyte:
|
|
self.p |= tbyte & self.NEGATIVE
|
|
else:
|
|
self.p |= self.ZERO
|
|
|
|
if x is None:
|
|
self.a = tbyte
|
|
else:
|
|
self.memory[addr] = tbyte
|
|
|
|
def opLSR(self, x):
|
|
if x is None:
|
|
tbyte = self.a
|
|
else:
|
|
addr = x()
|
|
tbyte = self.ByteAt(addr)
|
|
|
|
self.p &= ~(self.CARRY | self.NEGATIVE | self.ZERO)
|
|
self.p |= tbyte & 1
|
|
|
|
tbyte = tbyte >> 1
|
|
if tbyte:
|
|
pass
|
|
else:
|
|
self.p |= self.ZERO
|
|
|
|
if x is None:
|
|
self.a = tbyte
|
|
else:
|
|
self.memory[addr] = tbyte
|
|
|
|
def opBCL(self, x):
|
|
if self.p & x:
|
|
self.pc += 1
|
|
else:
|
|
self.BranchRelAddr()
|
|
|
|
def opBST(self, x):
|
|
if self.p & x:
|
|
self.BranchRelAddr()
|
|
else:
|
|
self.pc += 1
|
|
|
|
def opCLR(self, x):
|
|
self.p &= ~x
|
|
|
|
def opSET(self, x):
|
|
self.p |= x
|
|
|
|
def opAND(self, x):
|
|
self.a &= self.ByteAt(x())
|
|
self.FlagsNZ(self.a)
|
|
|
|
def opBIT(self, x):
|
|
tbyte = self.ByteAt(x())
|
|
self.p &= ~(self.ZERO | self.NEGATIVE | self.OVERFLOW)
|
|
if (self.a & tbyte) == 0:
|
|
self.p |= self.ZERO
|
|
self.p |= tbyte & (self.NEGATIVE | self.OVERFLOW)
|
|
|
|
def opROL(self, x):
|
|
if x is None:
|
|
tbyte = self.a
|
|
else:
|
|
addr = x()
|
|
tbyte = self.ByteAt(addr)
|
|
|
|
if self.p & self.CARRY:
|
|
if tbyte & self.NEGATIVE:
|
|
pass
|
|
else:
|
|
self.p &= ~self.CARRY
|
|
tbyte = (tbyte << 1) | 1
|
|
else:
|
|
if tbyte & self.NEGATIVE:
|
|
self.p |= self.CARRY
|
|
tbyte = tbyte << 1
|
|
tbyte &= self.byteMask
|
|
self.FlagsNZ(tbyte)
|
|
|
|
if x is None:
|
|
self.a = tbyte
|
|
else:
|
|
self.memory[addr] = tbyte
|
|
|
|
def opEOR(self, x):
|
|
self.a ^= self.ByteAt(x())
|
|
self.FlagsNZ(self.a)
|
|
|
|
def opADC(self, x):
|
|
return self._opADC(x, decimal_flags_use_adjusted_result=False)
|
|
|
|
def _opADC(self, x, decimal_flags_use_adjusted_result):
|
|
data = self.ByteAt(x())
|
|
|
|
if self.p & self.DECIMAL:
|
|
halfcarry = 0
|
|
decimalcarry = 0
|
|
adjust0 = 0
|
|
adjust1 = 0
|
|
nibble0 = (data & 0xf) + (self.a & 0xf) + (self.p & self.CARRY)
|
|
if nibble0 > 9:
|
|
adjust0 = 6
|
|
halfcarry = 1
|
|
nibble1 = ((data >> 4) & 0xf) + ((self.a >> 4) & 0xf) + halfcarry
|
|
if nibble1 > 9:
|
|
adjust1 = 6
|
|
decimalcarry = 1
|
|
|
|
# The ALU outputs are not yet decimally adjusted
|
|
nibble0 = nibble0 & 0xf
|
|
nibble1 = nibble1 & 0xf
|
|
aluresult = (nibble1 << 4) + nibble0
|
|
|
|
# Partial result with only low nibble decimally adjusted
|
|
nibble0 = (nibble0 + adjust0) & 0xf
|
|
halfadjresult = (nibble1 << 4) + nibble0
|
|
|
|
# the final A contents has both nibbles decimally adjusted
|
|
nibble1 = (nibble1 + adjust1) & 0xf
|
|
adjresult = (nibble1 << 4) + nibble0
|
|
|
|
self.p &= ~(self.CARRY | self.OVERFLOW | self.NEGATIVE | self.ZERO)
|
|
|
|
if decimal_flags_use_adjusted_result: # 65C02 and 65816
|
|
# Z and N use adjusted (i.e. decimal) result
|
|
zerores = adjresult
|
|
negativeres = adjresult
|
|
else: # 6502
|
|
# Z uses unadjusted (i.e. binary) ALU result
|
|
zerores = aluresult
|
|
# N effectively uses ALU result with only low nibble
|
|
# decimally adjusted - but see here for what is really going on
|
|
# https://atariage.com/forums/topic/163876-flags-on-decimal-mode-on-the-nmos-6502/
|
|
negativeres = halfadjresult
|
|
|
|
if zerores == 0:
|
|
self.p |= self.ZERO
|
|
else:
|
|
self.p |= negativeres & self.NEGATIVE
|
|
|
|
if decimalcarry == 1:
|
|
self.p |= self.CARRY
|
|
|
|
if (~(self.a ^ data) & (self.a ^ aluresult)) & self.NEGATIVE:
|
|
self.p |= self.OVERFLOW
|
|
|
|
self.a = adjresult
|
|
else:
|
|
if self.p & self.CARRY:
|
|
tmp = 1
|
|
else:
|
|
tmp = 0
|
|
result = data + self.a + tmp
|
|
self.p &= ~(self.CARRY | self.OVERFLOW | self.NEGATIVE | self.ZERO)
|
|
if (~(self.a ^ data) & (self.a ^ result)) & self.NEGATIVE:
|
|
self.p |= self.OVERFLOW
|
|
data = result
|
|
if data > self.byteMask:
|
|
self.p |= self.CARRY
|
|
data &= self.byteMask
|
|
if data == 0:
|
|
self.p |= self.ZERO
|
|
else:
|
|
self.p |= data & self.NEGATIVE
|
|
self.a = data
|
|
|
|
def opROR(self, x):
|
|
if x is None:
|
|
tbyte = self.a
|
|
else:
|
|
addr = x()
|
|
tbyte = self.ByteAt(addr)
|
|
|
|
if self.p & self.CARRY:
|
|
if tbyte & 1:
|
|
pass
|
|
else:
|
|
self.p &= ~self.CARRY
|
|
tbyte = (tbyte >> 1) | self.NEGATIVE
|
|
else:
|
|
if tbyte & 1:
|
|
self.p |= self.CARRY
|
|
tbyte = tbyte >> 1
|
|
self.FlagsNZ(tbyte)
|
|
|
|
if x is None:
|
|
self.a = tbyte
|
|
else:
|
|
self.memory[addr] = tbyte
|
|
|
|
def opSTA(self, x):
|
|
self.memory[x()] = self.a
|
|
|
|
def opSTY(self, x):
|
|
self.memory[x()] = self.y
|
|
|
|
def opSTX(self, y):
|
|
self.memory[y()] = self.x
|
|
|
|
def opCMPR(self, get_address, register_value):
|
|
tbyte = self.ByteAt(get_address())
|
|
self.p &= ~(self.CARRY | self.ZERO | self.NEGATIVE)
|
|
if register_value == tbyte:
|
|
self.p |= self.CARRY | self.ZERO
|
|
elif register_value > tbyte:
|
|
self.p |= self.CARRY
|
|
self.p |= (register_value - tbyte) & self.NEGATIVE
|
|
|
|
def opSBC(self, x):
|
|
self._opSBC(x, decimal_flags_use_adjusted_result=False)
|
|
|
|
def _opSBC(self, x, decimal_flags_use_adjusted_result):
|
|
if self.p & self.DECIMAL:
|
|
self._opSBCDecimal(x, decimal_flags_use_adjusted_result)
|
|
return
|
|
|
|
data = self.ByteAt(x())
|
|
|
|
result = self.a + (~data & self.byteMask) + (self.p & self.CARRY)
|
|
self.p &= ~(self.CARRY | self.ZERO | self.OVERFLOW | self.NEGATIVE)
|
|
if ((self.a ^ data) & (self.a ^ result)) & self.NEGATIVE:
|
|
self.p |= self.OVERFLOW
|
|
data = result & self.byteMask
|
|
if data == 0:
|
|
self.p |= self.ZERO
|
|
if result > self.byteMask:
|
|
self.p |= self.CARRY
|
|
self.p |= data & self.NEGATIVE
|
|
self.a = data
|
|
|
|
def _opSBCDecimal(self, x, flags_use_adjusted_result=False):
|
|
"""SBC opcode in BCD mode.
|
|
|
|
See e.g. http://6502.org/tutorials/decimal_mode.html#A for details
|
|
"""
|
|
data = self.ByteAt(x())
|
|
|
|
# the ALU outputs are not yet decimally adjusted
|
|
aluresult = self.a + (~data & self.byteMask) + (self.p & self.CARRY)
|
|
|
|
decimalcarry = aluresult > self.byteMask
|
|
aluresult &= self.byteMask
|
|
|
|
al = (self.a & 0xf) - (data & 0xf) + (self.p & self.CARRY) - 1
|
|
|
|
if flags_use_adjusted_result: # 65C02 but not 65816
|
|
a = self.a - data + (self.p & self.CARRY) - 1
|
|
if a < 0:
|
|
a -= 0x60
|
|
if al < 0:
|
|
a -= 0x6
|
|
|
|
else: # 6502
|
|
# Note: 65816 apparently also uses this logic instead of 65C02
|
|
if al < 0:
|
|
al = ((al - 0x6) & 0xf) - 0x10
|
|
a = (self.a & 0xf0) - (data & 0xf0) + al
|
|
if a < 0:
|
|
a -= 0x60
|
|
|
|
adjresult = a & self.byteMask
|
|
|
|
if flags_use_adjusted_result: # 65C02 and 65816
|
|
# Z and N use adjusted (i.e. decimal) result
|
|
zerores = adjresult
|
|
negativeres = adjresult
|
|
else: # 6502
|
|
# Z and N uses unadjusted (i.e. binary) ALU result
|
|
zerores = aluresult
|
|
negativeres = aluresult
|
|
|
|
self.p &= ~(self.CARRY | self.ZERO | self.NEGATIVE | self.OVERFLOW)
|
|
if zerores == 0:
|
|
self.p |= self.ZERO
|
|
else:
|
|
self.p |= negativeres & self.NEGATIVE
|
|
if decimalcarry == 1:
|
|
self.p |= self.CARRY
|
|
if ((self.a ^ data) & (self.a ^ aluresult)) & self.NEGATIVE:
|
|
self.p |= self.OVERFLOW
|
|
self.a = adjresult
|
|
|
|
def opDECR(self, x):
|
|
if x is None:
|
|
tbyte = self.a
|
|
else:
|
|
addr = x()
|
|
tbyte = self.ByteAt(addr)
|
|
|
|
self.p &= ~(self.ZERO | self.NEGATIVE)
|
|
tbyte = (tbyte - 1) & self.byteMask
|
|
if tbyte:
|
|
self.p |= tbyte & self.NEGATIVE
|
|
else:
|
|
self.p |= self.ZERO
|
|
|
|
if x is None:
|
|
self.a = tbyte
|
|
else:
|
|
self.memory[addr] = tbyte
|
|
|
|
def opINCR(self, x):
|
|
if x is None:
|
|
tbyte = self.a
|
|
else:
|
|
addr = x()
|
|
tbyte = self.ByteAt(addr)
|
|
|
|
self.p &= ~(self.ZERO | self.NEGATIVE)
|
|
tbyte = (tbyte + 1) & self.byteMask
|
|
if tbyte:
|
|
self.p |= tbyte & self.NEGATIVE
|
|
else:
|
|
self.p |= self.ZERO
|
|
|
|
if x is None:
|
|
self.a = tbyte
|
|
else:
|
|
self.memory[addr] = tbyte
|
|
|
|
def opLDA(self, x):
|
|
self.a = self.ByteAt(x())
|
|
self.FlagsNZ(self.a)
|
|
|
|
def opLDY(self, x):
|
|
self.y = self.ByteAt(x())
|
|
self.FlagsNZ(self.y)
|
|
|
|
def opLDX(self, y):
|
|
self.x = self.ByteAt(y())
|
|
self.FlagsNZ(self.x)
|
|
|
|
# instructions
|
|
|
|
def inst_not_implemented(self):
|
|
self.pc += 1
|
|
|
|
instruct = [inst_not_implemented] * 256
|
|
cycletime = [0] * 256
|
|
extracycles = [0] * 256
|
|
disassemble = [('???', 'imp')] * 256
|
|
|
|
instruction = make_instruction_decorator(instruct, disassemble,
|
|
cycletime, extracycles)
|
|
|
|
@instruction(name="BRK", mode="imp", cycles=7)
|
|
def inst_0x00(self):
|
|
# pc has already been increased one
|
|
pc = (self.pc + 1) & self.addrMask
|
|
self.stPushWord(pc)
|
|
|
|
self.p |= self.BREAK
|
|
self.stPush(self.p | self.BREAK | self.UNUSED)
|
|
|
|
self.p |= self.INTERRUPT
|
|
self.pc = self.WordAt(self.IRQ)
|
|
|
|
@instruction(name="ORA", mode="inx", cycles=6)
|
|
def inst_0x01(self):
|
|
self.opORA(self.IndirectXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ORA", mode="zpg", cycles=3)
|
|
def inst_0x05(self):
|
|
self.opORA(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ASL", mode="zpg", cycles=5)
|
|
def inst_0x06(self):
|
|
self.opASL(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="PHP", mode="imp", cycles=3)
|
|
def inst_0x08(self):
|
|
self.stPush(self.p | self.BREAK | self.UNUSED)
|
|
|
|
@instruction(name="ORA", mode="imm", cycles=2)
|
|
def inst_0x09(self):
|
|
self.opORA(self.ProgramCounter)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ASL", mode="acc", cycles=2)
|
|
def inst_0x0a(self):
|
|
self.opASL(None)
|
|
|
|
@instruction(name="ORA", mode="abs", cycles=4)
|
|
def inst_0x0d(self):
|
|
self.opORA(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="ASL", mode="abs", cycles=6)
|
|
def inst_0x0e(self):
|
|
self.opASL(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="BPL", mode="rel", cycles=2, extracycles=2)
|
|
def inst_0x10(self):
|
|
self.opBCL(self.NEGATIVE)
|
|
|
|
@instruction(name="ORA", mode="iny", cycles=5, extracycles=1)
|
|
def inst_0x11(self):
|
|
self.opORA(self.IndirectYAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ORA", mode="zpx", cycles=4)
|
|
def inst_0x15(self):
|
|
self.opORA(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ASL", mode="zpx", cycles=6)
|
|
def inst_0x16(self):
|
|
self.opASL(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="CLC", mode="imp", cycles=2)
|
|
def inst_0x18(self):
|
|
self.opCLR(self.CARRY)
|
|
|
|
@instruction(name="ORA", mode="aby", cycles=4, extracycles=1)
|
|
def inst_0x19(self):
|
|
self.opORA(self.AbsoluteYAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="ORA", mode="abx", cycles=4, extracycles=1)
|
|
def inst_0x1d(self):
|
|
self.opORA(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="ASL", mode="abx", cycles=7)
|
|
def inst_0x1e(self):
|
|
self.opASL(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="JSR", mode="abs", cycles=6)
|
|
def inst_0x20(self):
|
|
self.stPushWord((self.pc + 1) & self.addrMask)
|
|
self.pc = self.WordAt(self.pc)
|
|
|
|
@instruction(name="AND", mode="inx", cycles=6)
|
|
def inst_0x21(self):
|
|
self.opAND(self.IndirectXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="BIT", mode="zpg", cycles=3)
|
|
def inst_0x24(self):
|
|
self.opBIT(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="AND", mode="zpg", cycles=3)
|
|
def inst_0x25(self):
|
|
self.opAND(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ROL", mode="zpg", cycles=5)
|
|
def inst_0x26(self):
|
|
self.opROL(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="PLP", mode="imp", cycles=4)
|
|
def inst_0x28(self):
|
|
self.p = (self.stPop() | self.BREAK | self.UNUSED)
|
|
|
|
@instruction(name="AND", mode="imm", cycles=2)
|
|
def inst_0x29(self):
|
|
self.opAND(self.ProgramCounter)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ROL", mode="acc", cycles=2)
|
|
def inst_0x2a(self):
|
|
self.opROL(None)
|
|
|
|
@instruction(name="BIT", mode="abs", cycles=4)
|
|
def inst_0x2c(self):
|
|
self.opBIT(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="AND", mode="abs", cycles=4)
|
|
def inst_0x2d(self):
|
|
self.opAND(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="ROL", mode="abs", cycles=6)
|
|
def inst_0x2e(self):
|
|
self.opROL(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="BMI", mode="rel", cycles=2, extracycles=2)
|
|
def inst_0x30(self):
|
|
self.opBST(self.NEGATIVE)
|
|
|
|
@instruction(name="AND", mode="iny", cycles=5, extracycles=1)
|
|
def inst_0x31(self):
|
|
self.opAND(self.IndirectYAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="AND", mode="zpx", cycles=4)
|
|
def inst_0x35(self):
|
|
self.opAND(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ROL", mode="zpx", cycles=6)
|
|
def inst_0x36(self):
|
|
self.opROL(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="SEC", mode="imp", cycles=2)
|
|
def inst_0x38(self):
|
|
self.opSET(self.CARRY)
|
|
|
|
@instruction(name="AND", mode="aby", cycles=4, extracycles=1)
|
|
def inst_0x39(self):
|
|
self.opAND(self.AbsoluteYAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="AND", mode="abx", cycles=4, extracycles=1)
|
|
def inst_0x3d(self):
|
|
self.opAND(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="ROL", mode="abx", cycles=7)
|
|
def inst_0x3e(self):
|
|
self.opROL(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="RTI", mode="imp", cycles=6)
|
|
def inst_0x40(self):
|
|
self.p = (self.stPop() | self.BREAK | self.UNUSED)
|
|
self.pc = self.stPopWord()
|
|
|
|
@instruction(name="EOR", mode="inx", cycles=6)
|
|
def inst_0x41(self):
|
|
self.opEOR(self.IndirectXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="EOR", mode="zpg", cycles=3)
|
|
def inst_0x45(self):
|
|
self.opEOR(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LSR", mode="zpg", cycles=5)
|
|
def inst_0x46(self):
|
|
self.opLSR(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="PHA", mode="imp", cycles=3)
|
|
def inst_0x48(self):
|
|
self.stPush(self.a)
|
|
|
|
@instruction(name="EOR", mode="imm", cycles=2)
|
|
def inst_0x49(self):
|
|
self.opEOR(self.ProgramCounter)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LSR", mode="acc", cycles=2)
|
|
def inst_0x4a(self):
|
|
self.opLSR(None)
|
|
|
|
@instruction(name="JMP", mode="abs", cycles=3)
|
|
def inst_0x4c(self):
|
|
self.pc = self.WordAt(self.pc)
|
|
|
|
@instruction(name="EOR", mode="abs", cycles=4)
|
|
def inst_0x4d(self):
|
|
self.opEOR(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="LSR", mode="abs", cycles=6)
|
|
def inst_0x4e(self):
|
|
self.opLSR(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="BVC", mode="rel", cycles=2, extracycles=2)
|
|
def inst_0x50(self):
|
|
self.opBCL(self.OVERFLOW)
|
|
|
|
@instruction(name="EOR", mode="iny", cycles=5, extracycles=1)
|
|
def inst_0x51(self):
|
|
self.opEOR(self.IndirectYAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="EOR", mode="zpx", cycles=4)
|
|
def inst_0x55(self):
|
|
self.opEOR(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LSR", mode="zpx", cycles=6)
|
|
def inst_0x56(self):
|
|
self.opLSR(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="CLI", mode="imp", cycles=2)
|
|
def inst_0x58(self):
|
|
self.opCLR(self.INTERRUPT)
|
|
|
|
@instruction(name="EOR", mode="aby", cycles=4, extracycles=1)
|
|
def inst_0x59(self):
|
|
self.opEOR(self.AbsoluteYAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="EOR", mode="abx", cycles=4, extracycles=1)
|
|
def inst_0x5d(self):
|
|
self.opEOR(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="LSR", mode="abx", cycles=7)
|
|
def inst_0x5e(self):
|
|
self.opLSR(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="RTS", mode="imp", cycles=6)
|
|
def inst_0x60(self):
|
|
self.pc = self.stPopWord()
|
|
self.pc += 1
|
|
|
|
@instruction(name="ADC", mode="inx", cycles=6)
|
|
def inst_0x61(self):
|
|
self.opADC(self.IndirectXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ADC", mode="zpg", cycles=3)
|
|
def inst_0x65(self):
|
|
self.opADC(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ROR", mode="zpg", cycles=5)
|
|
def inst_0x66(self):
|
|
self.opROR(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="PLA", mode="imp", cycles=4)
|
|
def inst_0x68(self):
|
|
self.a = self.stPop()
|
|
self.FlagsNZ(self.a)
|
|
|
|
@instruction(name="ADC", mode="imm", cycles=2)
|
|
def inst_0x69(self):
|
|
self.opADC(self.ProgramCounter)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ROR", mode="acc", cycles=2)
|
|
def inst_0x6a(self):
|
|
self.opROR(None)
|
|
|
|
@instruction(name="JMP", mode="ind", cycles=5)
|
|
def inst_0x6c(self):
|
|
ta = self.WordAt(self.pc)
|
|
self.pc = self.WrapAt(ta)
|
|
|
|
@instruction(name="ADC", mode="abs", cycles=4)
|
|
def inst_0x6d(self):
|
|
self.opADC(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="ROR", mode="abs", cycles=6)
|
|
def inst_0x6e(self):
|
|
self.opROR(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="BVS", mode="rel", cycles=2, extracycles=2)
|
|
def inst_0x70(self):
|
|
self.opBST(self.OVERFLOW)
|
|
|
|
@instruction(name="ADC", mode="iny", cycles=5, extracycles=1)
|
|
def inst_0x71(self):
|
|
self.opADC(self.IndirectYAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ADC", mode="zpx", cycles=4)
|
|
def inst_0x75(self):
|
|
self.opADC(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="ROR", mode="zpx", cycles=6)
|
|
def inst_0x76(self):
|
|
self.opROR(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="SEI", mode="imp", cycles=2)
|
|
def inst_0x78(self):
|
|
self.opSET(self.INTERRUPT)
|
|
|
|
@instruction(name="ADC", mode="aby", cycles=4, extracycles=1)
|
|
def inst_0x79(self):
|
|
self.opADC(self.AbsoluteYAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="ADC", mode="abx", cycles=4, extracycles=1)
|
|
def inst_0x7d(self):
|
|
self.opADC(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="ROR", mode="abx", cycles=7)
|
|
def inst_0x7e(self):
|
|
self.opROR(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="STA", mode="inx", cycles=6)
|
|
def inst_0x81(self):
|
|
self.opSTA(self.IndirectXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="STY", mode="zpg", cycles=3)
|
|
def inst_0x84(self):
|
|
self.opSTY(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="STA", mode="zpg", cycles=3)
|
|
def inst_0x85(self):
|
|
self.opSTA(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="STX", mode="zpg", cycles=3)
|
|
def inst_0x86(self):
|
|
self.opSTX(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="DEY", mode="imp", cycles=2)
|
|
def inst_0x88(self):
|
|
self.y -= 1
|
|
self.y &= self.byteMask
|
|
self.FlagsNZ(self.y)
|
|
|
|
@instruction(name="TXA", mode="imp", cycles=2)
|
|
def inst_0x8a(self):
|
|
self.a = self.x
|
|
self.FlagsNZ(self.a)
|
|
|
|
@instruction(name="STY", mode="abs", cycles=4)
|
|
def inst_0x8c(self):
|
|
self.opSTY(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="STA", mode="abs", cycles=4)
|
|
def inst_0x8d(self):
|
|
self.opSTA(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="STX", mode="abs", cycles=4)
|
|
def inst_0x8e(self):
|
|
self.opSTX(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="BCC", mode="rel", cycles=2, extracycles=2)
|
|
def inst_0x90(self):
|
|
self.opBCL(self.CARRY)
|
|
|
|
@instruction(name="STA", mode="iny", cycles=6)
|
|
def inst_0x91(self):
|
|
self.opSTA(self.IndirectYAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="STY", mode="zpx", cycles=4)
|
|
def inst_0x94(self):
|
|
self.opSTY(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="STA", mode="zpx", cycles=4)
|
|
def inst_0x95(self):
|
|
self.opSTA(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="STX", mode="zpy", cycles=4)
|
|
def inst_0x96(self):
|
|
self.opSTX(self.ZeroPageYAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="TYA", mode="imp", cycles=2)
|
|
def inst_0x98(self):
|
|
self.a = self.y
|
|
self.FlagsNZ(self.a)
|
|
|
|
@instruction(name="STA", mode="aby", cycles=5)
|
|
def inst_0x99(self):
|
|
self.opSTA(self.AbsoluteYAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="TXS", mode="imp", cycles=2)
|
|
def inst_0x9a(self):
|
|
self.sp = self.x
|
|
|
|
@instruction(name="STA", mode="abx", cycles=5)
|
|
def inst_0x9d(self):
|
|
self.opSTA(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="LDY", mode="imm", cycles=2)
|
|
def inst_0xa0(self):
|
|
self.opLDY(self.ProgramCounter)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LDA", mode="inx", cycles=6)
|
|
def inst_0xa1(self):
|
|
self.opLDA(self.IndirectXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LDX", mode="imm", cycles=2)
|
|
def inst_0xa2(self):
|
|
self.opLDX(self.ProgramCounter)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LDY", mode="zpg", cycles=3)
|
|
def inst_0xa4(self):
|
|
self.opLDY(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LDA", mode="zpg", cycles=3)
|
|
def inst_0xa5(self):
|
|
self.opLDA(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LDX", mode="zpg", cycles=3)
|
|
def inst_0xa6(self):
|
|
self.opLDX(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="TAY", mode="imp", cycles=2)
|
|
def inst_0xa8(self):
|
|
self.y = self.a
|
|
self.FlagsNZ(self.y)
|
|
|
|
@instruction(name="LDA", mode="imm", cycles=2)
|
|
def inst_0xa9(self):
|
|
self.opLDA(self.ProgramCounter)
|
|
self.pc += 1
|
|
|
|
@instruction(name="TAX", mode="imp", cycles=2)
|
|
def inst_0xaa(self):
|
|
self.x = self.a
|
|
self.FlagsNZ(self.x)
|
|
|
|
@instruction(name="LDY", mode="abs", cycles=4)
|
|
def inst_0xac(self):
|
|
self.opLDY(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="LDA", mode="abs", cycles=4)
|
|
def inst_0xad(self):
|
|
self.opLDA(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="LDX", mode="abs", cycles=4)
|
|
def inst_0xae(self):
|
|
self.opLDX(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="BCS", mode="rel", cycles=2, extracycles=2)
|
|
def inst_0xb0(self):
|
|
self.opBST(self.CARRY)
|
|
|
|
@instruction(name="LDA", mode="iny", cycles=5, extracycles=1)
|
|
def inst_0xb1(self):
|
|
self.opLDA(self.IndirectYAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LDY", mode="zpx", cycles=4)
|
|
def inst_0xb4(self):
|
|
self.opLDY(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LDA", mode="zpx", cycles=4)
|
|
def inst_0xb5(self):
|
|
self.opLDA(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="LDX", mode="zpy", cycles=4)
|
|
def inst_0xb6(self):
|
|
self.opLDX(self.ZeroPageYAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="CLV", mode="imp", cycles=2)
|
|
def inst_0xb8(self):
|
|
self.opCLR(self.OVERFLOW)
|
|
|
|
@instruction(name="LDA", mode="aby", cycles=4, extracycles=1)
|
|
def inst_0xb9(self):
|
|
self.opLDA(self.AbsoluteYAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="TSX", mode="imp", cycles=2)
|
|
def inst_0xba(self):
|
|
self.x = self.sp
|
|
self.FlagsNZ(self.x)
|
|
|
|
@instruction(name="LDY", mode="abx", cycles=4, extracycles=1)
|
|
def inst_0xbc(self):
|
|
self.opLDY(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="LDA", mode="abx", cycles=4, extracycles=1)
|
|
def inst_0xbd(self):
|
|
self.opLDA(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="LDX", mode="aby", cycles=4, extracycles=1)
|
|
def inst_0xbe(self):
|
|
self.opLDX(self.AbsoluteYAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="CPY", mode="imm", cycles=2)
|
|
def inst_0xc0(self):
|
|
self.opCMPR(self.ProgramCounter, self.y)
|
|
self.pc += 1
|
|
|
|
@instruction(name="CMP", mode="inx", cycles=6)
|
|
def inst_0xc1(self):
|
|
self.opCMPR(self.IndirectXAddr, self.a)
|
|
self.pc += 1
|
|
|
|
@instruction(name="CPY", mode="zpg", cycles=3)
|
|
def inst_0xc4(self):
|
|
self.opCMPR(self.ZeroPageAddr, self.y)
|
|
self.pc += 1
|
|
|
|
@instruction(name="CMP", mode="zpg", cycles=3)
|
|
def inst_0xc5(self):
|
|
self.opCMPR(self.ZeroPageAddr, self.a)
|
|
self.pc += 1
|
|
|
|
@instruction(name="DEC", mode="zpg", cycles=5)
|
|
def inst_0xc6(self):
|
|
self.opDECR(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="INY", mode="imp", cycles=2)
|
|
def inst_0xc8(self):
|
|
self.y += 1
|
|
self.y &= self.byteMask
|
|
self.FlagsNZ(self.y)
|
|
|
|
@instruction(name="CMP", mode="imm", cycles=2)
|
|
def inst_0xc9(self):
|
|
self.opCMPR(self.ProgramCounter, self.a)
|
|
self.pc += 1
|
|
|
|
@instruction(name="DEX", mode="imp", cycles=2)
|
|
def inst_0xca(self):
|
|
self.x -= 1
|
|
self.x &= self.byteMask
|
|
self.FlagsNZ(self.x)
|
|
|
|
@instruction(name="CPY", mode="abs", cycles=4)
|
|
def inst_0xcc(self):
|
|
self.opCMPR(self.AbsoluteAddr, self.y)
|
|
self.pc += 2
|
|
|
|
@instruction(name="CMP", mode="abs", cycles=4)
|
|
def inst_0xcd(self):
|
|
self.opCMPR(self.AbsoluteAddr, self.a)
|
|
self.pc += 2
|
|
|
|
@instruction(name="DEC", mode="abs", cycles=3)
|
|
def inst_0xce(self):
|
|
self.opDECR(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="BNE", mode="rel", cycles=2, extracycles=2)
|
|
def inst_0xd0(self):
|
|
self.opBCL(self.ZERO)
|
|
|
|
@instruction(name="CMP", mode="iny", cycles=5, extracycles=1)
|
|
def inst_0xd1(self):
|
|
self.opCMPR(self.IndirectYAddr, self.a)
|
|
self.pc += 1
|
|
|
|
@instruction(name="CMP", mode="zpx", cycles=4)
|
|
def inst_0xd5(self):
|
|
self.opCMPR(self.ZeroPageXAddr, self.a)
|
|
self.pc += 1
|
|
|
|
@instruction(name="DEC", mode="zpx", cycles=6)
|
|
def inst_0xd6(self):
|
|
self.opDECR(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="CLD", mode="imp", cycles=2)
|
|
def inst_0xd8(self):
|
|
self.opCLR(self.DECIMAL)
|
|
|
|
@instruction(name="CMP", mode="aby", cycles=4, extracycles=1)
|
|
def inst_0xd9(self):
|
|
self.opCMPR(self.AbsoluteYAddr, self.a)
|
|
self.pc += 2
|
|
|
|
@instruction(name="CMP", mode="abx", cycles=4, extracycles=1)
|
|
def inst_0xdd(self):
|
|
self.opCMPR(self.AbsoluteXAddr, self.a)
|
|
self.pc += 2
|
|
|
|
@instruction(name="DEC", mode="abx", cycles=7)
|
|
def inst_0xde(self):
|
|
self.opDECR(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="CPX", mode="imm", cycles=2)
|
|
def inst_0xe0(self):
|
|
self.opCMPR(self.ProgramCounter, self.x)
|
|
self.pc += 1
|
|
|
|
@instruction(name="SBC", mode="inx", cycles=6)
|
|
def inst_0xe1(self):
|
|
self.opSBC(self.IndirectXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="CPX", mode="zpg", cycles=3)
|
|
def inst_0xe4(self):
|
|
self.opCMPR(self.ZeroPageAddr, self.x)
|
|
self.pc += 1
|
|
|
|
@instruction(name="SBC", mode="zpg", cycles=3)
|
|
def inst_0xe5(self):
|
|
self.opSBC(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="INC", mode="zpg", cycles=5)
|
|
def inst_0xe6(self):
|
|
self.opINCR(self.ZeroPageAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="INX", mode="imp", cycles=2)
|
|
def inst_0xe8(self):
|
|
self.x += 1
|
|
self.x &= self.byteMask
|
|
self.FlagsNZ(self.x)
|
|
|
|
@instruction(name="SBC", mode="imm", cycles=2)
|
|
def inst_0xe9(self):
|
|
self.opSBC(self.ProgramCounter)
|
|
self.pc += 1
|
|
|
|
@instruction(name="NOP", mode="imp", cycles=2)
|
|
def inst_0xea(self):
|
|
pass
|
|
|
|
@instruction(name="CPX", mode="abs", cycles=4)
|
|
def inst_0xec(self):
|
|
self.opCMPR(self.AbsoluteAddr, self.x)
|
|
self.pc += 2
|
|
|
|
@instruction(name="SBC", mode="abs", cycles=4)
|
|
def inst_0xed(self):
|
|
self.opSBC(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="INC", mode="abs", cycles=6)
|
|
def inst_0xee(self):
|
|
self.opINCR(self.AbsoluteAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="BEQ", mode="rel", cycles=2, extracycles=2)
|
|
def inst_0xf0(self):
|
|
self.opBST(self.ZERO)
|
|
|
|
@instruction(name="SBC", mode="iny", cycles=5, extracycles=1)
|
|
def inst_0xf1(self):
|
|
self.opSBC(self.IndirectYAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="SBC", mode="zpx", cycles=4)
|
|
def inst_0xf5(self):
|
|
self.opSBC(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="INC", mode="zpx", cycles=6)
|
|
def inst_0xf6(self):
|
|
self.opINCR(self.ZeroPageXAddr)
|
|
self.pc += 1
|
|
|
|
@instruction(name="SED", mode="imp", cycles=2)
|
|
def inst_0xf8(self):
|
|
self.opSET(self.DECIMAL)
|
|
|
|
@instruction(name="SBC", mode="aby", cycles=4, extracycles=1)
|
|
def inst_0xf9(self):
|
|
self.opSBC(self.AbsoluteYAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="SBC", mode="abx", cycles=4, extracycles=1)
|
|
def inst_0xfd(self):
|
|
self.opSBC(self.AbsoluteXAddr)
|
|
self.pc += 2
|
|
|
|
@instruction(name="INC", mode="abx", cycles=7)
|
|
def inst_0xfe(self):
|
|
self.opINCR(self.AbsoluteXAddr)
|
|
self.pc += 2
|