mirror of
https://github.com/lloeki/python-dcpu_16.git
synced 2025-12-06 09:54:39 +01:00
136 lines
2.8 KiB
Python
136 lines
2.8 KiB
Python
# System width
|
|
w = 16
|
|
wmask = 2**16-1
|
|
|
|
# Literal values
|
|
literal = xrange(0x00, 0x20)
|
|
|
|
opcodes = [
|
|
'nbi',
|
|
'SET',
|
|
'ADD',
|
|
'SUB',
|
|
'MUL',
|
|
'DIV',
|
|
'MOD',
|
|
'SHL',
|
|
'SHR',
|
|
'AND',
|
|
'BOR',
|
|
'XOR',
|
|
'IFE',
|
|
'IFN',
|
|
'IFG',
|
|
'IFB',
|
|
]
|
|
|
|
class CPU(object):
|
|
|
|
class Ops(object):
|
|
def SET(c, a, b):
|
|
return None
|
|
def ADD(c, a, b):
|
|
return None
|
|
def SUB(c, a, b):
|
|
return None
|
|
def MUL(c, a, b):
|
|
return None
|
|
def DIV(c, a, b):
|
|
return None
|
|
def MOD(c, a, b):
|
|
return None
|
|
def SHL(c, a, b):
|
|
return (a << b) & wmask
|
|
def SHR(c, a, b):
|
|
return (a >> b)
|
|
def AND(c, a, b):
|
|
return a & b
|
|
def BOR(c, a, b):
|
|
return a | b
|
|
def XOR(c, a, b):
|
|
return a ^ b
|
|
def IFE(c, a, b):
|
|
return a == b
|
|
def IFN(c, a, b):
|
|
return a != b
|
|
def IFG(c, a, b):
|
|
return a > b
|
|
def IFB(c, a, b):
|
|
return (a & b) != 0
|
|
|
|
def __init__(c):
|
|
c.reset()
|
|
c.clear()
|
|
|
|
def reset(c):
|
|
"""Reset CPU"""
|
|
c.r = [0 for _ in xrange(0, w)]
|
|
c.pc = 0
|
|
c.sp = 0
|
|
c.o = False
|
|
c.skip = False
|
|
|
|
def clear(c):
|
|
"""Clear memory"""
|
|
c.m = [0 for _ in xrange(0, 2**w)]
|
|
|
|
def __getitem__(c, addr):
|
|
"""Read value at memory address"""
|
|
return c.m[addr]
|
|
|
|
def __setitem__(c, addr, value):
|
|
"""Write value at memory address"""
|
|
c.m[addr] = value
|
|
|
|
def next_word(c):
|
|
val = c[c.pc]
|
|
c.pc += 1
|
|
return val
|
|
|
|
def dispatch_op(c):
|
|
|
|
def get_opcode(word):
|
|
return word & 0xF
|
|
def get_a(word):
|
|
return (word >> 4) & 0x3F
|
|
def get_b(word):
|
|
return (word >> 10) & 0x3F
|
|
|
|
def get_op(word):
|
|
getattr(CPU.Ops, opcodes[get_opcode(word)])
|
|
|
|
def is_nbi(opcode):
|
|
return opcode == 0x0
|
|
def is_set(opcode):
|
|
return 0x0 < opcode <= 0xb
|
|
def is_skip(opcode):
|
|
return 0xb < opcode <= 0xf
|
|
def set_a(value):
|
|
pass
|
|
|
|
word = c.next_word()
|
|
if c.skip:
|
|
c.skip = False
|
|
return
|
|
|
|
opcode = get_opcode(word)
|
|
if is_nbi(opcode):
|
|
pass
|
|
elif is_set(opcode):
|
|
set_a(get_op(opcode)())
|
|
elif is_skip(opcode):
|
|
if not get_op(opcode)():
|
|
c.skip = True
|
|
else:
|
|
raise OpcodeError(c.pc, opcode)
|
|
|
|
|
|
|
|
class OpcodeError(Exception):
|
|
def __init__(self, addr, data):
|
|
self.addr = addr
|
|
self.data = data
|
|
|
|
def __str__(self):
|
|
return "Invalid opcode at %s: '%s'" % (self.addr, self.data)
|
|
|