mirror of
https://github.com/lloeki/python-dcpu_16.git
synced 2025-12-06 09:54:39 +01:00
WIP working towards 1.5
This commit is contained in:
parent
a714a9d71a
commit
13adbbf68c
2 changed files with 350 additions and 170 deletions
368
dcpu_16.py
368
dcpu_16.py
|
|
@ -5,12 +5,19 @@ Spec: http://0x10c.com/doc/dcpu-16.txt
|
|||
See LICENSE for licensing information.
|
||||
"""
|
||||
|
||||
# TODO: cycle count management
|
||||
# branching opcodes take one cycle longer to perform if the test fails
|
||||
# when they skip an if instruction, they will skip an additional instruction
|
||||
# TODO: signed functions
|
||||
# signed numbers are represented using two's complement
|
||||
# TODO: interrupts
|
||||
# TODO: hardware
|
||||
|
||||
from __future__ import print_function, division
|
||||
|
||||
|
||||
# DCPU-16 spec version
|
||||
spec = '1.1'
|
||||
spec = '1.5'
|
||||
|
||||
|
||||
# log tool
|
||||
|
|
@ -100,131 +107,247 @@ def pointerize(f):
|
|||
return ptrz
|
||||
|
||||
|
||||
@opcode(0x0, 0x01)
|
||||
@opcode(0x00, 0x01)
|
||||
def JSR(c, a):
|
||||
"""pushes the address of the next instruction to the stack, then sets PC to a"""
|
||||
c.sp -= 1
|
||||
c.m[c.sp] = c.pc
|
||||
c.pc = a()
|
||||
|
||||
@opcode(0x1)
|
||||
def SET(c, a, b):
|
||||
"""sets a to b"""
|
||||
a.set(b())
|
||||
@opcode(0x00, 0x07)
|
||||
def HCF(c, a):
|
||||
"""use sparingly"""
|
||||
pass
|
||||
|
||||
@opcode(0x2)
|
||||
def ADD(c, a, b):
|
||||
"""sets a to a+b, sets O to 0x0001 if there's an overflow"""
|
||||
res = (a() + b())
|
||||
@opcode(0x00, 0x08)
|
||||
def INT(c, a):
|
||||
"""triggers a software interrupt with message a"""
|
||||
pass
|
||||
|
||||
@opcode(0x00, 0x09)
|
||||
def IAG(c, a):
|
||||
"""sets a to IA"""
|
||||
pass
|
||||
|
||||
@opcode(0x00, 0x0A)
|
||||
def IAS(c, a):
|
||||
"""sets IA to a"""
|
||||
pass
|
||||
|
||||
@opcode(0x00, 0x0B)
|
||||
def IAP(c, a):
|
||||
"""if IA is 0, does nothing, otherwise pushes IA to the stack, then sets IA to a"""
|
||||
pass
|
||||
|
||||
@opcode(0x00, 0x0C)
|
||||
def IAQ(c, a):
|
||||
"""if a is nonzero, interrupts will be added to the queue instead of triggered. if a is zero, interrupts will be triggered as nomral again"""
|
||||
pass
|
||||
|
||||
@opcode(0x00, 0x10)
|
||||
def HWN(c, a):
|
||||
"""sets a to number of connected hardware devices"""
|
||||
pass
|
||||
|
||||
@opcode(0x00, 0x11)
|
||||
def HWQ(c, a):
|
||||
"""sets A, B, C,X, Y registers to information about hardware a
|
||||
|
||||
A+(B<<16) is a 32 bit word identifying the hardware id
|
||||
C is the hardware version
|
||||
X+(Y<<16) is a 32 bit word identifying the manufacturer
|
||||
"""
|
||||
pass
|
||||
|
||||
@opcode(0x00, 0x12)
|
||||
def HWI(c, a):
|
||||
"""sends an interrupt to hardware a"""
|
||||
pass
|
||||
|
||||
@opcode(0x01)
|
||||
def SET(c, b, a):
|
||||
"""sets b to a"""
|
||||
b.set(a())
|
||||
|
||||
@opcode(0x02)
|
||||
def ADD(c, b, a):
|
||||
"""sets b to b+a, sets EX to 0x0001 if there's an overflow, 0x0 otherwise"""
|
||||
res = (b() + a())
|
||||
if res > wmask:
|
||||
c.o = 0x0001
|
||||
c.ex = 0x0001
|
||||
res = res & wmask
|
||||
a.set(res)
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x3)
|
||||
def SUB(c, a, b):
|
||||
"""sets a to a-b, sets O to 0xFFFF if there's an underflow"""
|
||||
res = (a() - b())
|
||||
@opcode(0x03)
|
||||
def SUB(c, b, a):
|
||||
"""sets b to b-a, sets EX to 0xFFFF if there's an underflow, 0x0 otherwise"""
|
||||
res = (b() - a())
|
||||
if res & (wmask+1):
|
||||
c.o = 0xFFFF
|
||||
c.ex = 0xFFFF
|
||||
res = res & wmask
|
||||
a.set(res)
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x4)
|
||||
def MUL(c, a, b):
|
||||
"""sets a to a*b, sets O to ((a*b)>>16)&0xFFFF"""
|
||||
res = (a() * b())
|
||||
c.o = ((a() * b()) >> w) & wmask
|
||||
@opcode(0x04)
|
||||
def MUL(c, b, a):
|
||||
"""sets b to b*a, sets EX to ((b*a)>>16)&0xFFFF (treats b, a as unsigned)"""
|
||||
res = (b() * a())
|
||||
c.ex = ((b() * a()) >> w) & wmask
|
||||
res = res & wmask
|
||||
a.set(res)
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x5)
|
||||
def DIV(c, a, b):
|
||||
"""sets a to a/b, sets O to ((a<<16)/b)&0xFFFF"""
|
||||
res = a() // b()
|
||||
c.o = ((a() << w) // b()) & wmask
|
||||
a.set(res)
|
||||
@opcode(0x05)
|
||||
def MLI(c, b, a):
|
||||
"""like MUL, but treats b, a as signed"""
|
||||
pass
|
||||
|
||||
@opcode(0x6)
|
||||
def MOD(c, a, b):
|
||||
"""sets a to a%b. if b==0, sets a to 0 instead"""
|
||||
if b()==0:
|
||||
@opcode(0x06)
|
||||
def DIV(c, b, a):
|
||||
"""sets b to b/a, sets EX to ((b<<16)/a)&0xFFFF. if a==0, sets b and EX to 0 instead. (treats b, a as unsigned)"""
|
||||
res = b() // a()
|
||||
c.ex = ((b() << w) // a()) & wmask
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x07)
|
||||
def DVI(c, b, a):
|
||||
"""like DIV, but treats b, a as signed. Rounds towards 0"""
|
||||
pass
|
||||
|
||||
@opcode(0x08)
|
||||
def MOD(c, b, a):
|
||||
"""sets b to b%a. if a==0 sets b to 0 instead"""
|
||||
if a()==0:
|
||||
res = 0
|
||||
else:
|
||||
res = a() % b()
|
||||
a.set(res)
|
||||
res = b() % a()
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x7)
|
||||
def SHL(c, a, b):
|
||||
"""sets a to a<<b. sets O to ((a<<b)>>16)&0xFFFF"""
|
||||
res = (a() << b())
|
||||
c.o = ((a() << b()) >> w) & wmask
|
||||
@opcode(0x09)
|
||||
def MDI(c, b, a):
|
||||
"""like MOD, but treat b, a as signed. Rounds towards 0"""
|
||||
pass
|
||||
|
||||
@opcode(0x0A)
|
||||
def AND(c, b, a):
|
||||
"""sets b to b&a"""
|
||||
res = b() & a()
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x0B)
|
||||
def BOR(c, b, a):
|
||||
"""sets b to b|a"""
|
||||
res = b() | a()
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x0C)
|
||||
def XOR(c, b, a):
|
||||
"""sets b to b^a"""
|
||||
res = b() ^ a()
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x0D)
|
||||
def SHR(c, b, a):
|
||||
"""sets b to b>>>a. sets EX to ((b<<16)>>a)&0xFFFF (logical shift)"""
|
||||
res = (b() >> a())
|
||||
c.ex = ((b() << w) >> a()) & wmask
|
||||
res = res & wmask
|
||||
a.set(res)
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x8)
|
||||
def SHR(c, a, b):
|
||||
"""sets a to a>>b. sets O to ((a>>16)>>b)&0xFFFF"""
|
||||
res = (a() >> b())
|
||||
c.o = ((a() >> w) >> b()) & wmask
|
||||
@opcode(0x0E)
|
||||
def ASR(c, b, a):
|
||||
"""sets b to b>>a. sets EX to ((b<<16)>>>a)&0xFFFF (arithmetic shift) (treats b as signed)"""
|
||||
pass
|
||||
|
||||
@opcode(0x0F)
|
||||
def SHL(c, b, a):
|
||||
"""sets b to b<<a. sets EX to ((b<<a)>>16)&0xFFFF"""
|
||||
res = (b() << a())
|
||||
c.ex = ((b() << a()) >> w) & wmask
|
||||
res = res & wmask
|
||||
a.set(res)
|
||||
b.set(res)
|
||||
|
||||
@opcode(0x9)
|
||||
def AND(c, a, b):
|
||||
"""sets a to a&b"""
|
||||
res = a() & b()
|
||||
a.set(res)
|
||||
|
||||
@opcode(0xA)
|
||||
def BOR(c, a, b):
|
||||
"""sets a to a|b"""
|
||||
res = a() | b()
|
||||
a.set(res)
|
||||
|
||||
@opcode(0xB)
|
||||
def XOR(c, a, b):
|
||||
"""sets a to a^b"""
|
||||
res = a() ^ b()
|
||||
a.set(res)
|
||||
|
||||
@opcode(0xC)
|
||||
def IFE(c, a, b):
|
||||
"""performs next instruction only if a==b"""
|
||||
if a() == b():
|
||||
@opcode(0x10)
|
||||
def IFB(c, b, a):
|
||||
"""performs next instruction only if (b&a)!=0"""
|
||||
if (b() & a()) != 0:
|
||||
c.skip = False
|
||||
else:
|
||||
c.skip = True
|
||||
|
||||
@opcode(0xD)
|
||||
def IFN(c, a, b):
|
||||
"""performs next instruction only if a!=b"""
|
||||
if a() != b():
|
||||
@opcode(0x11)
|
||||
def IFC(c, b, a):
|
||||
"""performs next instruction only if (b&a)==0"""
|
||||
if (b() & a()) == 0:
|
||||
c.skip = False
|
||||
else:
|
||||
c.skip = True
|
||||
|
||||
@opcode(0xE)
|
||||
def IFG(c, a, b):
|
||||
"""performs next instruction only if a>b"""
|
||||
if a() > b():
|
||||
@opcode(0x12)
|
||||
def IFE(c, b, a):
|
||||
"""performs next instruction only if b==a"""
|
||||
if b() == a():
|
||||
c.skip = False
|
||||
else:
|
||||
c.skip = True
|
||||
|
||||
@opcode(0xF)
|
||||
def IFB(c, a, b):
|
||||
"""performs next instruction only if (a&b)!=0"""
|
||||
if (a() & b()) != 0:
|
||||
@opcode(0x13)
|
||||
def IFN(c, b, a):
|
||||
"""performs next instruction only if b!=a"""
|
||||
if b() != a():
|
||||
c.skip = False
|
||||
else:
|
||||
c.skip = True
|
||||
|
||||
@opcode(0x14)
|
||||
def IFG(c, b, a):
|
||||
"""performs next instruction only if b>a"""
|
||||
if b() > a():
|
||||
c.skip = False
|
||||
else:
|
||||
c.skip = True
|
||||
|
||||
@opcode(0x15)
|
||||
def IFA(c, b, a):
|
||||
"""performs next instruction only if b>a (signed)"""
|
||||
pass
|
||||
|
||||
@opcode(0x16)
|
||||
def IFL(c, b, a):
|
||||
"""performs next instruction only if b<a"""
|
||||
if b() < a():
|
||||
c.skip = False
|
||||
else:
|
||||
c.skip = True
|
||||
|
||||
@opcode(0x17)
|
||||
def IFU(c, b, a):
|
||||
"""performs next instruction only if b<a (signed)"""
|
||||
pass
|
||||
|
||||
@opcode(0x1A)
|
||||
def ADX(c, b, a):
|
||||
"""sets b to b+a+EX, sets EX to 0x0001 if there is an overflow, 0x0 otherwise"""
|
||||
pass
|
||||
|
||||
@opcode(0x1B)
|
||||
def SBX(c, b, a):
|
||||
"""sets b to b-a+EX, sets EX to 0xFFFF if there is an underflow, 0x0 otherwise"""
|
||||
pass
|
||||
|
||||
@opcode(0x1E)
|
||||
def STI(c, b, a):
|
||||
"""sets b to a, then increases I and J by 1"""
|
||||
pass
|
||||
|
||||
@opcode(0x1F)
|
||||
def STD(c, b, a):
|
||||
"""sets b to a, then decreases I and J by 1"""
|
||||
pass
|
||||
|
||||
|
||||
@valcode(range(0x00, 0x08))
|
||||
@pointerize
|
||||
def register(c, code):
|
||||
"""register"""
|
||||
"""register (A, B, C, X, Y, Z, I, J, in that order)"""
|
||||
v = "c.r[0x%01X]" % code
|
||||
return v
|
||||
|
||||
|
|
@ -245,8 +368,16 @@ def next_word_plus_register_value(c, code):
|
|||
|
||||
@valcode(0x18)
|
||||
@pointerize
|
||||
def push_pop(c):
|
||||
"""(PUSH / [--SP]) if in b, or (POP / [SP++]) if in a"""
|
||||
pass
|
||||
def push(c):
|
||||
"""[--SP] / PUSH"""
|
||||
c.sp -= 1
|
||||
v = "c.m[0x%04X]" % c.sp
|
||||
return v
|
||||
def pop(c):
|
||||
"""POP / [SP++]"""
|
||||
"""[SP++] / POP"""
|
||||
v = "c.m[0x%04X]" % c.sp
|
||||
c.sp += 1
|
||||
return v
|
||||
|
|
@ -254,37 +385,35 @@ def pop(c):
|
|||
@valcode(0x19)
|
||||
@pointerize
|
||||
def peek(c):
|
||||
"""PEEK / [SP]"""
|
||||
"""[SP] / PEEK"""
|
||||
v = "c.m[0x%04X]" % c.sp
|
||||
return v
|
||||
|
||||
@valcode(0x1A)
|
||||
@pointerize
|
||||
def push(c):
|
||||
"""PUSH / [--SP]"""
|
||||
c.sp -= 1
|
||||
v = "c.m[0x%04X]" % c.sp
|
||||
return v
|
||||
def pick(c):
|
||||
"""[SP + next word] / PICK n"""
|
||||
pass
|
||||
|
||||
@valcode(0x1B)
|
||||
@pointerize
|
||||
def stack_pointer(c):
|
||||
"""stack pointer"""
|
||||
"""SP"""
|
||||
v = "c.sp"
|
||||
return v
|
||||
|
||||
@valcode(0x1C)
|
||||
@pointerize
|
||||
def program_counter(c):
|
||||
"""program counter"""
|
||||
"""PC"""
|
||||
v = "c.pc"
|
||||
return v
|
||||
|
||||
@valcode(0x1D)
|
||||
@pointerize
|
||||
def overflow(c):
|
||||
"""overflow"""
|
||||
v = "c.o"
|
||||
def excess(c):
|
||||
"""EX"""
|
||||
v = "c.ex"
|
||||
return v
|
||||
|
||||
@valcode(0x1E)
|
||||
|
|
@ -306,8 +435,8 @@ def next_word(c):
|
|||
@valcode(range(0x20, 0x40))
|
||||
@pointerize
|
||||
def literal(c, code):
|
||||
"""literal value 0x00-0x1F (literal)"""
|
||||
v = "0x%04X" % (code - 0x20)
|
||||
"""literal value 0xFFFF-0x1E (-1..30) (literal) (only for a)"""
|
||||
v = "0x%04X" % ((code - 0x20 - 1) & 0xFFFF)
|
||||
return v
|
||||
|
||||
|
||||
|
|
@ -345,7 +474,7 @@ class CPU(object):
|
|||
c.r = [0 for _ in xrange(0, 8)]
|
||||
c.pc = 0x0000
|
||||
c.sp = 0x0000
|
||||
c.o = 0x0000
|
||||
c.ex = 0x0000
|
||||
c.skip = False
|
||||
|
||||
def clear(c):
|
||||
|
|
@ -362,22 +491,22 @@ class CPU(object):
|
|||
j = Register(0x7)
|
||||
pc = Register()
|
||||
sp = Register()
|
||||
o = Register()
|
||||
ex = Register()
|
||||
|
||||
def _op(c, word):
|
||||
"""dispatch word to op and args"""
|
||||
opcode = word & 0xF
|
||||
a_code = word >> 4 & 0x3F
|
||||
b_code = word >> 10 & 0x3F
|
||||
opcode = word & 0x1F
|
||||
b_code = word >> 5 & 0x1F
|
||||
a_code = word >> 10 & 0x3F
|
||||
try:
|
||||
op = _opcode_map[opcode]
|
||||
try:
|
||||
op = op[a_code]
|
||||
except TypeError:
|
||||
args = (c._pointer(a_code),
|
||||
c._pointer(b_code))
|
||||
args = (c._pointer(b_code),
|
||||
c._pointer(a_code))
|
||||
else:
|
||||
args = (c._pointer(b_code),)
|
||||
args = (c._pointer(a_code),)
|
||||
finally:
|
||||
if c.debug:
|
||||
log(' '.join([op.__name__] + [arg.codestr for arg in args]))
|
||||
|
|
@ -428,9 +557,9 @@ class CPU(object):
|
|||
(["A", "B", "C",
|
||||
"X", "Y", "Z",
|
||||
"I", "J",
|
||||
"PC", "SP", "O",
|
||||
"PC", "SP", "EX",
|
||||
][i],
|
||||
(c.r + [c.pc, c.sp, c.o])[i])
|
||||
(c.r + [c.pc, c.sp, c.ex])[i])
|
||||
for i in range(11))
|
||||
|
||||
def load_m(c, data=None, io=None):
|
||||
|
|
@ -446,8 +575,25 @@ class CPU(object):
|
|||
|
||||
|
||||
spec_demo = [
|
||||
0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d,
|
||||
0x7dc1, 0x001a, 0xa861, 0x7c01, 0x2000, 0x2161, 0x2000, 0x8463,
|
||||
0x806d, 0x7dc1, 0x000d, 0x9031, 0x7c10, 0x0018, 0x7dc1, 0x001a,
|
||||
0x9037, 0x61c1, 0x7dc1, 0x001a, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
# TODO: hand-reassembled for 1.5, but still some bugs
|
||||
0x7c01, 0x0030, # SET A, 0x30
|
||||
0x7fc1, 0x1000, 0x0020, # SET [0x1000], 0x20
|
||||
0x7803, 0x1000, # SUB A, [0X1000]
|
||||
0xc012, # 0xc013 # IFE A, 0xF
|
||||
0x7f81, 0x001a, # SET PC, crash
|
||||
0x90c1, # 0xacc1 # SET I, 10
|
||||
0x7c01, 0x2000, # SET A, 0x2000
|
||||
# :loop
|
||||
0x22C1, 0x2000, # SET [I + 0x2000], [A]
|
||||
0x88C3, # SUB I, 1
|
||||
0x84D3, # IFN I, 0
|
||||
0x7f81, 0x000d, # SET PC, loop
|
||||
0x9461, # SET X, 4
|
||||
0x7c20, 0x0018, # JSR testsub
|
||||
0x7f81, 0x001a, # SET PC, crash
|
||||
# :testsub
|
||||
0x946f, # SHL X, 4
|
||||
0x6381, # SET PC, POP
|
||||
# :crash
|
||||
0x7f81, 0x001a, # SET PC, crash
|
||||
]
|
||||
|
|
|
|||
152
test.py
152
test.py
|
|
@ -10,7 +10,7 @@ class TestInstructions(unittest.TestCase):
|
|||
pass
|
||||
|
||||
def test_SET(self):
|
||||
dcpu_16.SET.opcode = (0x1,)
|
||||
self.assertEqual(dcpu_16.SET.opcode, (0x01,))
|
||||
c = CPU()
|
||||
c.a = 0x0
|
||||
c.b = 0x42
|
||||
|
|
@ -19,107 +19,161 @@ class TestInstructions(unittest.TestCase):
|
|||
self.assertEqual(c.b, 0x42)
|
||||
|
||||
def test_ADD(self):
|
||||
dcpu_16.SET.opcode = (0x2,)
|
||||
self.assertEqual(dcpu_16.ADD.opcode, (0x02,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.ADD(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17+0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.o, 0x0)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_SUB(self):
|
||||
dcpu_16.SET.opcode = (0x3,)
|
||||
self.assertEqual(dcpu_16.SUB.opcode, (0x03,))
|
||||
c = CPU()
|
||||
c.a = 0x42
|
||||
c.b = 0x17
|
||||
dcpu_16.SUB(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x42-0x17)
|
||||
self.assertEqual(c.b, 0x17)
|
||||
self.assertEqual(c.o, 0x0)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_MUL(self):
|
||||
dcpu_16.SET.opcode = (0x4,)
|
||||
self.assertEqual(dcpu_16.MUL.opcode, (0x04,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.MUL(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17*0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.o, 0x0)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_MLI(self):
|
||||
self.assertEqual(dcpu_16.MLI.opcode, (0x05,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.MLI(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17*0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_DIV(self):
|
||||
dcpu_16.SET.opcode = (0x5,)
|
||||
self.assertEqual(dcpu_16.DIV.opcode, (0x06,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.DIV(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17/0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.o, ((0x17<<16)/0x42)&0xFFFF)
|
||||
self.assertEqual(c.ex, ((0x17<<16)/0x42)&0xFFFF)
|
||||
|
||||
def test_DVI(self):
|
||||
self.assertEqual(dcpu_16.DVI.opcode, (0x07,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.DIV(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17/0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.ex, ((0x17<<16)/0x42)&0xFFFF)
|
||||
|
||||
def test_MOD(self):
|
||||
dcpu_16.SET.opcode = (0x6,)
|
||||
self.assertEqual(dcpu_16.MOD.opcode, (0x08,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.MOD(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17%0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.o, 0x0)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_SHL(self):
|
||||
dcpu_16.SET.opcode = (0x7,)
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x4
|
||||
dcpu_16.SHL(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17<<0x4 & dcpu_16.wmask)
|
||||
self.assertEqual(c.b, 0x4)
|
||||
self.assertEqual(c.o, 0x0)
|
||||
|
||||
def test_SHR(self):
|
||||
dcpu_16.SET.opcode = (0x8,)
|
||||
def test_MDI(self):
|
||||
self.assertEqual(dcpu_16.MDI.opcode, (0x09,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.SHR(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17>>0x42)
|
||||
dcpu_16.MOD(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17%0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.o, 0x0)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_AND(self):
|
||||
dcpu_16.SET.opcode = (0x9,)
|
||||
self.assertEqual(dcpu_16.AND.opcode, (0x0A,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.AND(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17&0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.o, 0x0)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_BOR(self):
|
||||
dcpu_16.SET.opcode = (0xA,)
|
||||
self.assertEqual(dcpu_16.BOR.opcode, (0x0B,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.BOR(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17|0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.o, 0x0)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_XOR(self):
|
||||
dcpu_16.SET.opcode = (0xB,)
|
||||
self.assertEqual(dcpu_16.XOR.opcode, (0x0C,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.XOR(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17^0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.o, 0x0)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_SHR(self):
|
||||
self.assertEqual(dcpu_16.SHR.opcode, (0x0D,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.SHR(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17>>0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_ASR(self):
|
||||
self.assertEqual(dcpu_16.ASR.opcode, (0x0E,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x42
|
||||
dcpu_16.ASR(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17>>0x42)
|
||||
self.assertEqual(c.b, 0x42)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_SHL(self):
|
||||
self.assertEqual(dcpu_16.SHL.opcode, (0x0F,))
|
||||
c = CPU()
|
||||
c.a = 0x17
|
||||
c.b = 0x4
|
||||
dcpu_16.SHL(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.a, 0x17<<0x4 & dcpu_16.wmask)
|
||||
self.assertEqual(c.b, 0x4)
|
||||
self.assertEqual(c.ex, 0x0)
|
||||
|
||||
def test_IFB(self):
|
||||
self.assertEqual(dcpu_16.IFB.opcode, (0x10,))
|
||||
c = CPU()
|
||||
|
||||
c.a = 0xF0F0
|
||||
c.b = 0x0F0F
|
||||
dcpu_16.IFB(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.skip, True)
|
||||
|
||||
c.a = 0xF1F0
|
||||
c.b = 0x0F0F
|
||||
dcpu_16.IFB(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.skip, False)
|
||||
|
||||
def test_IFE(self):
|
||||
dcpu_16.SET.opcode = (0xC,)
|
||||
self.assertEqual(dcpu_16.IFE.opcode, (0x12,))
|
||||
c = CPU()
|
||||
|
||||
c.a = 0x17
|
||||
|
|
@ -133,7 +187,7 @@ class TestInstructions(unittest.TestCase):
|
|||
self.assertEqual(c.skip, False)
|
||||
|
||||
def test_IFN(self):
|
||||
dcpu_16.SET.opcode = (0xD,)
|
||||
self.assertEqual(dcpu_16.IFN.opcode, (0x13,))
|
||||
c = CPU()
|
||||
|
||||
c.a = 0x17
|
||||
|
|
@ -147,7 +201,7 @@ class TestInstructions(unittest.TestCase):
|
|||
self.assertEqual(c.skip, True)
|
||||
|
||||
def test_IFG(self):
|
||||
dcpu_16.SET.opcode = (0xE,)
|
||||
self.assertEqual(dcpu_16.IFG.opcode, (0x14,))
|
||||
c = CPU()
|
||||
|
||||
c.a = 0x41
|
||||
|
|
@ -165,22 +219,8 @@ class TestInstructions(unittest.TestCase):
|
|||
dcpu_16.IFG(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.skip, False)
|
||||
|
||||
def test_IFB(self):
|
||||
dcpu_16.SET.opcode = (0xF,)
|
||||
c = CPU()
|
||||
|
||||
c.a = 0xF0F0
|
||||
c.b = 0x0F0F
|
||||
dcpu_16.IFB(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.skip, True)
|
||||
|
||||
c.a = 0xF1F0
|
||||
c.b = 0x0F0F
|
||||
dcpu_16.IFB(c, c._pointer(0x0), c._pointer(0x1))
|
||||
self.assertEqual(c.skip, False)
|
||||
|
||||
def test_JSR(self):
|
||||
dcpu_16.JSR.opcode = (0x0, 0x1)
|
||||
self.assertEqual(dcpu_16.JSR.opcode, (0x00, 0x01))
|
||||
c = CPU()
|
||||
|
||||
c.a = 0xDEAD
|
||||
|
|
@ -203,7 +243,7 @@ class TestCPU(unittest.TestCase):
|
|||
for r in c.r:
|
||||
self.assertEqual(r, 0)
|
||||
self.assertEqual(c.pc, 0)
|
||||
self.assertEqual(c.o, 0)
|
||||
self.assertEqual(c.ex, 0)
|
||||
self.assertEqual(c.sp, 0)
|
||||
self.assertEqual(c.skip, False)
|
||||
self.assertEqual(c.pc, 0)
|
||||
|
|
@ -219,7 +259,7 @@ class TestCPU(unittest.TestCase):
|
|||
for r in c.r:
|
||||
self.assertEqual(r, 0)
|
||||
self.assertEqual(c.pc, 0)
|
||||
self.assertEqual(c.o, 0)
|
||||
self.assertEqual(c.ex, 0)
|
||||
self.assertEqual(c.sp, 0)
|
||||
self.assertEqual(c.skip, False)
|
||||
self.assertEqual(c.pc, 0)
|
||||
|
|
@ -239,13 +279,7 @@ class TestCPUWithPrograms(unittest.TestCase):
|
|||
|
||||
def test_spec_demo(self):
|
||||
c = CPU()
|
||||
data = [
|
||||
0x7c01, 0x0030, 0x7de1, 0x1000, 0x0020, 0x7803, 0x1000, 0xc00d,
|
||||
0x7dc1, 0x001a, 0xa861, 0x7c01, 0x2000, 0x2161, 0x2000, 0x8463,
|
||||
0x806d, 0x7dc1, 0x000d, 0x9031, 0x7c10, 0x0018, 0x7dc1, 0x001a,
|
||||
0x9037, 0x61c1, 0x7dc1, 0x001a, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
]
|
||||
c.load_m(data=data)
|
||||
c.load_m(data=dcpu_16.spec_demo)
|
||||
|
||||
self.assertEqual(c.pc, 0)
|
||||
c.step() # SET A, 0x30
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue