mirror of
https://github.com/lloeki/python-dcpu_16.git
synced 2025-12-06 09:54:39 +01:00
almost there, for an initial impl.
ironically test.py ended up way more advanced than dcpu_16.py
This commit is contained in:
commit
ff63a59cac
2 changed files with 500 additions and 0 deletions
136
dcpu_16.py
Normal file
136
dcpu_16.py
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
# 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)
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue