Skip to content

Instantly share code, notes, and snippets.

@jedie
Last active December 23, 2015 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jedie/6595991 to your computer and use it in GitHub Desktop.
Save jedie/6595991 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
"""
DragonPy - Dragon 32 emulator in Python
=======================================
6809 is Big-Endian
Based on XRoar emulator by Ciaran Anscomb (GPL license) more info, see README
:copyleft: 2013 by the DragonPy team, see AUTHORS for more details.
:license: GNU GPL v3 or above, see LICENSE for more details.
"""
import logging
log = logging.getLogger("DragonPy")
def signed8(x):
""" convert to signed 8-bit """
if x > 0x7f: # 0x7f == 2**7-1 == 127
x = x - 0x100 # 0x100 == 2**8 == 256
return x
def signed16(x):
""" convert to signed 16-bit """
if x > 0x7fff: # 0x7fff == 2**15-1 == 32767
x = x - 0x10000 # 0x100 == 2**16 == 65536
return x
def _register_bit(key):
def set_flag(self, value):
assert value in (0, 1)
self._register[key] = value
def get_flag(self):
return self._register[key]
return property(get_flag, set_flag)
class ConditionCodeRegister(object):
""" CC - 8 bit condition code register bits """
def __init__(self, *args, **kwargs):
self._register = {}
self.status_from_byte(0x0) # create all keys in dict with value 0
E = _register_bit("E") # E - 0x80 - bit 7 - Entire register state stacked
F = _register_bit("F") # F - 0x40 - bit 6 - FIRQ interrupt masked
H = _register_bit("H") # H - 0x20 - bit 5 - Half-Carry
I = _register_bit("I") # I - 0x10 - bit 4 - IRQ interrupt masked
N = _register_bit("N") # N - 0x08 - bit 3 - Negative result (twos complement)
Z = _register_bit("Z") # Z - 0x04 - bit 2 - Zero result
V = _register_bit("V") # V - 0x02 - bit 1 - Overflow
C = _register_bit("C") # C - 0x01 - bit 0 - Carry (or borrow)
####
def status_from_byte(self, status):
self.E, self.F, self.H, self.I, self.N, self.Z, self.V, self.C = \
[0 if status & x == 0 else 1 for x in (128, 64, 32, 16, 8, 4, 2, 1)]
def status_as_byte(self):
return self.C | \
self.V << 1 | \
self.Z << 2 | \
self.N << 3 | \
self.I << 4 | \
self.H << 5 | \
self.F << 6 | \
self.E << 7
####
def set_Z8(self, r):
self.Z = 1 if r & 0xff == 0 else 0
def set_Z16(self, r):
self.Z = 1 if r & 0xffff == 0 else 0
def set_N8(self, r):
self.N = 1 if signed8(r) < 0 else 0
def set_N16(self, r):
self.N = 1 if signed16(r) < 0 else 0
def set_H(self, a, b, r): # TODO: Add tests
self.H = 1 if (a ^ b ^ r) & 0x10 else 0
def set_C8(self, r):
self.C = 1 if r & 0x100 else 0
def set_C16(self, r):
self.C = 1 if r & 0x10000 else 0
def set_V8(self, a, b, r): # FIXME
self.V = 1 if (a ^ b ^ r ^ (r >> 1)) & 0x80 else 0
def set_V16(self, a, b, r): # FIXME
self.V = 1 if (a ^ b ^ r ^ (r >> 1)) & 0x8000 else 0
####
def set_NZ8(self, r):
self.set_N8(r)
self.set_Z8(r)
def set_NZ16(self, r):
self.set_N16(r)
self.set_Z16(r)
def set_NZC8(self, r):
self.set_N8(r)
self.set_Z8(r)
self.set_C8(r)
def set_NZVC8(self, a, b, r): # FIXME
self.set_N8(r)
self.set_Z8(r)
self.set_V8(a, b, r)
self.set_C8(r)
def set_NZVC16(self, a, b, r): # FIXME
self.set_N16(r)
self.set_Z16(r)
self.set_V16(a, b, r)
self.set_C16(r)
class Accumulators(object):
def __init__(self, cpu):
self.cpu = cpu
self._A = 0 # A - 8 bit accumulator
self._B = 0 # B - 8 bit accumulator
# D - 16 bit concatenated reg. (A + B)
def _check(self, value):
if value > 0xff:
self.cpu.cc.V = 1 # set Overflow flag
value = value & 0xff
return value
def get_A(self):
return self._A
def set_A(self, value):
self._A = self._check(value)
A = property(get_A, set_A)
def get_B(self):
return self._B
def set_B(self, value):
self._B = self._check(value)
B = property(get_B, set_B)
def get_D(self):
return self._A * 256 + self._B
def set_D(self, value):
self.set_A(value >> 8)
self.set_B(value & 0xff)
if value > 0xffff:
self.cpu.cc.V = 1 # set Overflow flag
value = value & 0xffff
D = property(get_D, set_D)
#------------------------------------------------------------------------------
# TODO: move into separate test.py:
import unittest
class TestCPU(object):
def __init__(self):
self.accu = Accumulators(self)
self.cc = ConditionCodeRegister()
class BaseTestCase(unittest.TestCase):
def assertEqualHex(self, hex1, hex2, msg=None):
first = "$%x" % hex1
second = "$%x" % hex2
self.assertEqual(first, second, msg)
class CC_AccumulatorTestCase(BaseTestCase):
def setUp(self):
self.cpu = TestCPU()
def test_A01(self):
self.cpu.accu.A = 0xff
self.assertEqualHex(self.cpu.accu.A, 0xff)
self.assertEqual(self.cpu.cc.V, 0)
self.cpu.accu.A = 0xff + 1
self.assertEqual(self.cpu.cc.V, 1)
self.assertEqualHex(self.cpu.accu.A, 0x0) # XXX
def test_B01(self):
self.cpu.accu.B = 0x5a
self.assertEqualHex(self.cpu.accu.B, 0x5a)
self.assertEqual(self.cpu.cc.V, 0)
self.cpu.accu.B = 0xff + 10
self.assertEqual(self.cpu.cc.V, 1)
self.assertEqualHex(self.cpu.accu.B, 0x9) # XXX
def test_D01(self):
self.cpu.accu.A = 0x12
self.cpu.accu.B = 0xab
self.assertEqualHex(self.cpu.accu.D, 0x12ab)
self.assertEqual(self.cpu.cc.V, 0)
def test_D02(self):
self.cpu.accu.D = 0xfd89
self.assertEqualHex(self.cpu.accu.A, 0xfd)
self.assertEqualHex(self.cpu.accu.B, 0x89)
self.assertEqual(self.cpu.cc.V, 0)
def test_D03(self):
self.cpu.accu.D = 0xffff + 1
self.assertEqualHex(self.cpu.accu.A, 0x0) # XXX
self.assertEqualHex(self.cpu.accu.B, 0x0) # XXX
self.assertEqual(self.cpu.cc.V, 1)
class CCTestCase(unittest.TestCase):
def setUp(self):
self.cc = ConditionCodeRegister()
def test_status_from_byte_to_byte(self):
for i in xrange(256):
self.cc.status_from_byte(i)
status_byte = self.cc.status_as_byte()
self.assertEqual(status_byte, i)
def test_set_NZ8(self):
self.cc.set_NZ8(r=0x12)
self.assertEqual(self.cc.N, 0)
self.assertEqual(self.cc.Z, 0)
self.cc.set_NZ8(r=0x0)
self.assertEqual(self.cc.N, 0)
self.assertEqual(self.cc.Z, 1)
self.cc.set_NZ8(r=0x80)
self.assertEqual(self.cc.N, 1)
self.assertEqual(self.cc.Z, 0)
def test_set_NZ16(self):
self.cc.set_NZ16(r=0x7fff) # 0x7fff == 32767
self.assertEqual(self.cc.N, 0)
self.assertEqual(self.cc.Z, 0)
self.cc.set_NZ16(r=0x00)
self.assertEqual(self.cc.N, 0)
self.assertEqual(self.cc.Z, 1)
self.cc.set_NZ16(r=0x8000) # signed 0x8000 == -32768
self.assertEqual(self.cc.N, 1)
self.assertEqual(self.cc.Z, 0)
def test_set_NZC8(self): # FIXME: C ???
self.cc.set_NZC8(0x7f)
self.assertEqual(self.cc.N, 0)
self.assertEqual(self.cc.Z, 0)
self.assertEqual(self.cc.C, 0)
self.cc.set_NZC8(0x100)
self.assertEqual(self.cc.N, 0)
self.assertEqual(self.cc.Z, 1)
self.assertEqual(self.cc.C, 1)
def test_set_NZVC8(self):
a = 1
b = 2
r = a + b
self.cc.set_NZVC8(a, b, r)
self.assertEqual(self.cc.N, 0)
self.assertEqual(self.cc.Z, 0)
self.assertEqual(self.cc.V, 0)
self.assertEqual(self.cc.C, 0)
a = 0xff
b = 1
r = a + b
self.cc.set_NZVC8(a, b, r)
self.assertEqual(self.cc.N, 0)
self.assertEqual(self.cc.Z, 1)
self.assertEqual(self.cc.V, 1) # FIXME
self.assertEqual(self.cc.C, 0)
if __name__ == '__main__':
unittest.main(verbosity=2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment