Coverage for MC6809/components/cpu_utils/Instruction_generator.py: 28%

99 statements  

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

1#!/usr/bin/env python3 

2 

3""" 

4 MC6809 - 6809 CPU emulator in Python 

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

6 

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

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

9""" 

10 

11 

12import os 

13import sys 

14 

15from MC6809.components.MC6809data.MC6809_data_utils import MC6809OP_DATA_DICT 

16from MC6809.components.MC6809data.MC6809_op_data import ( 

17 BYTE, 

18 OP_DATA, 

19 REG_A, 

20 REG_B, 

21 REG_CC, 

22 REG_D, 

23 REG_DP, 

24 REG_PC, 

25 REG_S, 

26 REG_U, 

27 REG_X, 

28 REG_Y, 

29 WORD, 

30) 

31 

32 

33SPECIAL_FUNC_NAME = "special" 

34 

35REGISTER_DICT = { 

36 REG_X: "index_x", 

37 REG_Y: "index_y", 

38 

39 REG_U: "user_stack_pointer", 

40 REG_S: "system_stack_pointer", 

41 

42 REG_PC: "program_counter", 

43 

44 REG_A: "accu_a", 

45 REG_B: "accu_b", 

46 REG_D: "accu_d", 

47 

48 REG_DP: "direct_page", 

49 REG_CC: "cc_register", 

50 

51 # undefined_reg.name:"undefined_reg", # for TFR", EXG 

52} 

53 

54 

55if __doc__: 55 ↛ 58line 55 didn't jump to line 58, because the condition on line 55 was never false

56 DOC = __doc__.rsplit("=", 1)[1] 

57else: 

58 DOC = "" # e.g.: run with --OO 

59 

60INIT_CODE = f''' 

61""\" 

62 This file was generated with: "{os.path.basename(__file__)}" 

63 Please don't change it directly ;) 

64 {DOC} 

65""\" 

66 

67 

68from MC6809.components.cpu_utils.instruction_base import InstructionBase 

69 

70class PrepagedInstructions(InstructionBase): 

71 def __init__(self, *args, **kwargs): 

72 super(PrepagedInstructions, self).__init__(*args, **kwargs) 

73 

74 self.write_byte = self.cpu.memory.write_byte 

75 self.write_word = self.cpu.memory.write_word 

76 

77''' 

78 

79 

80def build_func_name(addr_mode, ea, register, read, write): 

81 # print(addr_mode, ea, register, read, write 

82 

83 if addr_mode is None: 

84 return SPECIAL_FUNC_NAME 

85 

86 func_name = addr_mode.lower() 

87 

88 if ea: 

89 func_name += "_ea" 

90 if register: 

91 func_name += f"_{register}" 

92 if read: 

93 func_name += f"_read{read}" 

94 if write: 

95 func_name += f"_write{write}" 

96 

97# print(func_name 

98 return func_name 

99 

100 

101def func_name_from_op_code(op_code): 

102 op_code_data = MC6809OP_DATA_DICT[op_code] 

103 addr_mode = op_code_data["addr_mode"] 

104 ea = op_code_data["needs_ea"] 

105 register = op_code_data["register"] 

106 read = op_code_data["read_from_memory"] 

107 write = op_code_data["write_to_memory"] 

108 return build_func_name(addr_mode, ea, register, read, write) 

109 

110 

111def generate_code(f): 

112 addr_modes = set() 

113 registers = set() 

114 variants = set() 

115 for instr_data in list(OP_DATA.values()): 

116 for mnemonic, mnemonic_data in list(instr_data["mnemonic"].items()): 

117 read_from_memory = mnemonic_data["read_from_memory"] 

118 write_to_memory = mnemonic_data["write_to_memory"] 

119 needs_ea = mnemonic_data["needs_ea"] 

120 register = mnemonic_data["register"] 

121 for op_code, op_data in list(mnemonic_data["ops"].items()): 

122 addr_mode = op_data["addr_mode"] 

123# print(hex(op_code), 

124 

125 if addr_mode is None: 

126 # special function (RESET/ PAGE1,2) defined in InstructionBase 

127 print("address mode is None:", mnemonic, op_data) 

128 continue 

129 

130 addr_mode = addr_mode.lower() 

131 

132 variant = (addr_mode, needs_ea, register, read_from_memory, write_to_memory) 

133 # print(variant) 

134 variants.add(variant) 

135 

136 if needs_ea and read_from_memory: 

137 addr_modes.add(f"get_ea_m_{addr_mode}") 

138 elif needs_ea: 

139 addr_modes.add(f"get_ea_{addr_mode}") 

140 elif read_from_memory: 

141 addr_modes.add(f"get_m_{addr_mode}") 

142 

143 if register is not None: 

144 registers.add(register) 

145 

146# if (addr_mode and needs_ea and register and read_from_memory and write_to_memory) is None: 

147 

148 variants = list(variants) 

149 variants.sort(key=lambda x: "".join(f"{i}" for i in x)) 

150 

151 # for no, data in enumerate(variants): 

152 # print(no, data) 

153 # print("+++++++++++++") 

154 

155 for line in INIT_CODE.splitlines(): 

156 f.write(f"{line}\n") 

157 

158 for register in sorted(REGISTER_DICT[register] for register in registers): 

159 f.write( 

160 " self.{r}=self.cpu.{r}\n".format( 

161 r=register, 

162 ) 

163 ) 

164 f.write("\n") 

165 

166 for addr_mode in sorted(addr_modes): 

167 f.write( 

168 " self.{a}=self.cpu.{a}\n".format(a=addr_mode) 

169 ) 

170 f.write("\n") 

171 

172 for addr_mode, needs_ea, register, read_from_memory, write_to_memory in variants: 

173 func_name = build_func_name(addr_mode, needs_ea, register, read_from_memory, write_to_memory) 

174 

175 f.write(f" def {func_name}(self, opcode):\n") 

176 

177 code = [] 

178 

179 if needs_ea and read_from_memory: 

180 code.append(f"ea, m = self.cpu.get_ea_m_{addr_mode}()") 

181 

182 if write_to_memory: 

183 code.append("ea, value = self.instr_func(") 

184 else: 

185 code.append("self.instr_func(") 

186 code.append(" opcode=opcode,") 

187 

188 if needs_ea and read_from_memory: 

189 code.append(" ea=ea,") 

190 code.append(" m=m,") 

191 elif needs_ea: 

192 code.append(f" ea=self.get_ea_{addr_mode}(),") 

193 elif read_from_memory: 

194 code.append(f" m=self.get_m_{addr_mode}(),") 

195 

196 if register: 

197 code.append( 

198 f" register=self.{REGISTER_DICT[register]}," 

199 ) 

200 

201 code.append(")") 

202 

203 if write_to_memory == BYTE: 

204 code.append("self.write_byte(ea, value)") 

205 elif write_to_memory == WORD: 

206 code.append("self.write_word(ea, value)") 

207 

208 for line in code: 

209 f.write(f" {line}\n") 

210 

211 f.write("\n") 

212 

213 

214def generate(filename): 

215 with open(filename, "w") as f: 

216 # generate_code(sys.stdout) 

217 generate_code(f) 

218 sys.stderr.write(f"New {filename!r} generated.\n") 

219 

220 

221if __name__ == "__main__": 

222 # print("LDA immediate:", func_name_from_op_code(0x96)) 

223 

224 generate("instruction_call.py")