python-dcpu_16/dcpu_16.py
Loic Nageleisen ff63a59cac almost there, for an initial impl.
ironically test.py ended up way more advanced than dcpu_16.py
2012-04-05 23:45:16 +02:00

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)