Coverage for MC6809/components/cpu_utils/MC6809_registers.py: 92%

67 statements  

« prev     ^ index     » next       coverage.py v7.2.1, created at 2023-03-06 19:50 +0100

1#!/usr/bin/env python 

2 

3""" 

4 MC6809 - 6809 CPU emulator in Python 

5 ======================================= 

6 

7 some code is borrowed from: 

8 XRoar emulator by Ciaran Anscomb (GPL license) more info, see README 

9 

10 :copyleft: 2013-2015 by the MC6809 team, see AUTHORS for more details. 

11 :license: GNU GPL v3 or above, see LICENSE for more details. 

12""" 

13 

14 

15import logging 

16 

17 

18log = logging.getLogger("MC6809") 

19 

20 

21class ValueStorageBase: 

22 def __init__(self, name, initial_value): 

23 self.name = name 

24 self.value = initial_value 

25 

26 def set(self, v): 

27 self.value = v 

28 

29 def decrement(self, value=1): 

30 self.set(self.value - value) 

31 

32 def increment(self, value=1): 

33 self.set(self.value + value) 

34 

35 def __str__(self): 

36 return f"<{self.name}:${self.value:x}>" 

37 __repr__ = __str__ 

38 

39 

40class UndefinedRegister(ValueStorageBase): 

41 # used in TFR and EXG 

42 WIDTH = 16 # 16 Bit 

43 name = "undefined!" 

44 value = 0xffff 

45 

46 def __init__(self): 

47 pass 

48 

49 def set(self, v): 

50 log.warning("Set value to 'undefined' register!") 

51 

52 def get(self): 

53 return 0xffff 

54 

55 

56class ValueStorage8Bit(ValueStorageBase): 

57 WIDTH = 8 # 8 Bit 

58 

59 def set(self, v): 

60 if v > 0xff: 

61 # log.info(" **** Value $%x is to big for %s (8-bit)", v, self.name) 

62 v = v & 0xff 

63# log.info(" ^^^^ Value %s (8-bit) wrap around to $%x", self.name, v) 

64 elif v < 0: 

65 # log.info(" **** %s value $%x is negative", self.name, v) 

66 v = 0x100 + v 

67# log.info(" **** Value %s (8-bit) wrap around to $%x", self.name, v) 

68 self.value = v 

69 

70 def __str__(self): 

71 return f"{self.name}={self.value:02x}" 

72 

73 

74class ValueStorage16Bit(ValueStorageBase): 

75 WIDTH = 16 # 16 Bit 

76 

77 def set(self, v): 

78 if v > 0xffff: 

79 # log.info(" **** Value $%x is to big for %s (16-bit)", v, self.name) 

80 v = v & 0xffff 

81# log.info(" ^^^^ Value %s (16-bit) wrap around to $%x", self.name, v) 

82 elif v < 0: 

83 # log.info(" **** %s value $%x is negative", self.name, v) 

84 v = 0x10000 + v 

85# log.info(" **** Value %s (16-bit) wrap around to $%x", self.name, v) 

86 self.value = v 

87 

88 def __str__(self): 

89 return f"{self.name}={self.value:04x}" 

90 

91 

92class ConcatenatedAccumulator: 

93 """ 

94 6809 has register D - 16 bit concatenated reg. (A + B) 

95 """ 

96 WIDTH = 16 # 16 Bit 

97 

98 def __init__(self, name, a, b): 

99 self.name = name 

100 self._a = a 

101 self._b = b 

102 

103 def set(self, value): 

104 self._a.set(value >> 8) 

105 self._b.set(value & 0xff) 

106 

107 @property 

108 def value(self): 

109 return self._a.value * 256 + self._b.value 

110 

111 def __str__(self): 

112 return f"{self.name}={self.value:04x}" 

113 

114 

115def convert_differend_width(src_reg, dst_reg): 

116 """ 

117 e.g.: 

118 8bit $cd TFR into 16bit, results in: $ffcd 

119 16bit $1234 TFR into 8bit, results in: $34 

120 

121 >>> reg8 = ValueStorage8Bit(name="bar", initial_value=0xcd) 

122 >>> reg16 = ValueStorage16Bit(name="foo", initial_value=0x0000) 

123 >>> hex(convert_differend_width(src_reg=reg8, dst_reg=reg16)) 

124 '0xffcd' 

125 

126 >>> reg16 = ValueStorage16Bit(name="foo", initial_value=0x1234) 

127 >>> reg8 = ValueStorage8Bit(name="bar", initial_value=0xcd) 

128 >>> hex(convert_differend_width(src_reg=reg16, dst_reg=reg8)) 

129 '0x34' 

130 

131 TODO: verify this behaviour on real hardware 

132 see: http://archive.worldofdragon.org/phpBB3/viewtopic.php?f=8&t=4886 

133 """ 

134 src_value = src_reg.value 

135 if src_reg.WIDTH == 8 and dst_reg.WIDTH == 16: 

136 # e.g.: $cd -> $ffcd 

137 src_value += 0xff00 

138 elif src_reg.WIDTH == 16 and dst_reg.WIDTH == 8: 

139 # This not not really needed, because all 8Bit register will 

140 # limit the value, too. 

141 # e.g.: $1234 -> $34 

142 src_value = src_value & 0xff 

143 return src_value 

144 

145 

146if __name__ == "__main__": 

147 import doctest 

148 print(doctest.testmod())