#!/usr/bin/python3
# ===================================================================
# my 6502 simulator
# a start at a first cut
# -------------------------------------------------------------------
#
# My memory layout is not a real one. A real memory layout is
# more complicated (Google 6502 memory layout).
#
# This is just to test my CPU implementation and a few selected
# instructions.
#
# ---- my test memory layout
#
# 0 255 256 511 512 4095
# +--------+ +--------+ +---------------------------------+
# | zero | | stack | | program and data |
# | page | | | | |
# +--------+ +--------+ +---------------------------------+
#
# Decimal Hex
# 0 0x00
# 255 0xFF
# 256 0x0100
# 511 0x01FF
# 512 0x0200
# 4095 0x0FFF
# 4096 0x1000
#
# ---- registers and status register bits
#
# PC programm counter word (2 bytes)
# SP stack pointer byte
# A accmulator register byte
# X X rergister byte
# Y Y register byte
# P status register byte
# N bit (negative flag)
# V bit (overflow flag)
# B bit (break command flag)
# D bit (decimal mode flag)
# I bit (IRQ disable flag)
# Z bit (zero flag)
# C bit (carry flag)
#
# ===================================================================
import sys
MAX_MEM = 1024 * 4
mem = bytearray(MAX_MEM) # memory (4096 bytes)
# -------------------------------------------------------------------
# ---- CPU
# -------------------------------------------------------------------
class CPU:
def __init__(self):
self.reset()
def reset(self):
self.PC = 0x0200 # my program counter
self.SP = 0xFF # my stack pointer
self.A = 0x00 # accmulator register
self.X = 0x00 # X register
self.Y = 0x00 # Y register
self.N = 0 # negative flag
self.V = 0 # overflow flag
self.B = 0 # break command flag
self.D = 0 # decimal mode flag
self.I = 0 # IRQ disable flag
self.Z = 0 # zero flag
self.C = 0 # carry flag
def getN(self):
return self.N
def setN(self,x):
if not verify_bit_value(x):
sys.exit()
self.N = x
def statusN(self):
if self.N:
return True
return False
def getV(self):
return self.V
def setV(self,x):
if not verify_bit_value(x):
sys.exit()
self.V = x
def statusV(self):
if self.V:
return True
return False
def getB(self):
return self.B
def setB(self,x):
if not verify_bit_value(x):
sys.exit()
self.B = x
def statusB(self):
if self.B:
return True
return False
def getD(self):
return self.D
def setD(self,x):
if not verify_bit_value(x):
sys.exit()
self.D = x
def statusD(self):
if self.B:
return True
return False
def getI(self):
return self.PI
def setI(self,x):
if not verify_bit_value(x):
sys.exit()
self.I = x
def statusI(self):
if self.B:
return True
return False
def getZ(self):
return self.Z
def setZ(self,x):
if not verify_bit_value(x):
sys.exit()
self.Z = x
def statusZ(self):
if self.B:
return True
return False
def getC(self):
return self.C
def setC(self,x):
if not verify_bit_value(x):
sys.exit()
self.C = x
def statusC(self):
if self.B:
return True
return False
def resetP(self):
self.N = 0 # negative flag
self.V = 0 # overflow flag
self.B = 0 # break command flag
self.D = 0 # decimal mode flag
self.I = 0 # IRQ disable flag
self.Z = 0 # zero flag
self.C = 0 # carry flag
def getA(self):
return self.A
def setC(self,x):
if not verify_byte_value(x):
sys.exit()
self.A = x
def getX(self):
return self.X
def setC(self,x):
if not verify_byte_value(x):
sys.exit()
self.X = x
def getY(self):
return self.Y
def setC(self,x):
if not verify_byte_value(x):
sys.exit()
self.Y = x
def getPC(self):
return self.PC
def setPC(self,x):
if not verify_word_value(x):
sys.exit()
self.PC = x
def getSP(self):
return self.SP
def setSP(self,x):
if not verify_word_value(x):
sys.exit()
self.SP = x
def displayRegisters(self,title=None):
print('-- CPU Registers ---------------------')
if title:
print(f'-- {title}')
print(f'PC = {hex(self.PC):7} ({self.PC})')
print(f'SP = {hex(self.SP):7} ({self.SP})')
print(f'A = {hex(self.A):7} ({self.A})')
print(f'X = {hex(self.X):7} ({self.X})')
print(f'Y = {hex(self.Y):7} ({self.Y})')
##print(f'P.N = {self.N}')
print(f'P.N = {self.statusN()}')
##print(f'P.V = {self.V}')
print(f'P.V = {self.statusV()}')
##print(f'P.B = {self.B}')
print(f'P.B = {self.statusB()}')
##print(f'P.D = {self.D}')
print(f'P.D = {self.statusD()}')
##print(f'P.I = {self.I}')
print(f'P.I = {self.statusI()}')
##print(f'P.Z = {self.Z}')
print(f'P.Z = {self.statusZ()}')
##print(f'P.C = {self.C}')
print(f'P.C = {self.statusC()}')
print('--------------------------------------')
def execute(mem):
pass
# -------------------------------------------------------------------
# ---- support functions
# -------------------------------------------------------------------
def verify_bit_value(v):
if v != 0 and v != 1:
print(f'Illegal bit value ({v})')
return False
return True
def verify_byte_value(v):
if v < 0 or v > 255:
print(f'Illegal byte value ({v})')
return False
return True
def verify_word_value(v):
if v < 0 and v > 65535:
print(f'Illegal word value ({v})')
return False
return True
def is_float(s):
try:
n = float(s)
return (True,n)
except:
return (False,0.0)
def is_int(s):
try:
n = int(s)
return (True,n)
except:
return (False,0)
def is_a_number(s):
x,n = is_int(s)
if x:
return True
x,n = is_float(s)
if x:
return True
return False
def init_memory():
mem = bytearray(MAX_MEM)
# -------------------------------------------------------------------
# main
# -------------------------------------------------------------------
if __name__ == '__main__':
print()
print('my 6502 CPU simulator')
print()
cpu = CPU()
cpu.displayRegisters()