Implement 386 instruction table, improve 8086/186/286 instruction table
[multi_emu.git] / decode_6809.py
1 #!/usr/bin/env python3
2
3 import sys
4
5 # those which allow pre/post increment have to be lvalues
6 addressing_values = {
7   '$12': '(int8_t)cpu_6809_fetch_byte(self)',
8   '$1234': 'cpu_6809_fetch_word(self)',
9   'a': '(int8_t)self->regs.byte.a',
10   'b': '(int8_t)self->regs.byte.b',
11   'd': 'self->regs.word.d',
12   '--u': 'self->regs.word.u',
13   '-u': '--self->regs.word.u',
14   'u': 'self->regs.word.u',
15   'u+': 'self->regs.word.u++',
16   'u++': 'self->regs.word.u',
17   '--s': 'self->regs.word.s',
18   '-s': '--self->regs.word.s',
19   's': 'self->regs.word.s',
20   's+': 'self->regs.word.s++',
21   's++': 'self->regs.word.s',
22   '--x': 'self->regs.word.x',
23   '-x': '--self->regs.word.x',
24   'x': 'self->regs.word.x',
25   'x+': 'self->regs.word.x++',
26   'x++': 'self->regs.word.x',
27   '--y': 'self->regs.word.y',
28   '-y': '--self->regs.word.y',
29   'y': 'self->regs.word.y',
30   'y+': 'self->regs.word.y++',
31   'y++': 'self->regs.word.y',
32   'pc': 'self->regs.word.pc',
33 }
34
35 # end-relative range of operands that are rvalues
36 rvalue_opcodes = {
37   'add': (-1, 0),
38   'adc': (-1, 0),
39   'and': (-1, 0),
40   'andcc': (-1, 0),
41   'bit': (-2, 0),
42   'cmp': (-2, 0),
43   'cmp_byte': (-2, 0),
44   'cwai': (-1, 0),
45   'eor': (-1, 0),
46   'ld': (-1, 0),
47   'or': (-1, 0),
48   'orcc': (-1, 0),
49   'sub': (-1, 0),
50   'sbc': (-1, 0),
51   'st': (-2, -1),
52   'tst': (-1, 0),
53 }
54
55 # if it is in byte_opcodes it is treated as byte and has no suffix
56 byte_opcodes = {
57   'adc',
58   'and',
59   'andcc',
60   'asl',
61   'asr',
62   'bit',
63   'clr',
64   'cmp_byte',
65   'com',
66   'cwai',
67   'dec_byte',
68   'eor',
69   'inc_byte',
70   'lsr',
71   'neg',
72   'or',
73   'orcc',
74   'rol',
75   'ror',
76   'sbc',
77   'tst',
78 }
79 # if any operand is in byte_operands it is treated as byte and has suffix
80 # in this case another operand which is word can upgrade the size to word
81 byte_operands = {
82   '#$12',
83   'a',
84   'b',
85 }
86 byte_rvalue_modes = {
87   '#$12': 'cpu_6809_fetch_byte(self)',
88   'a': 'self->regs.byte.a',
89   'b': 'self->regs.byte.b',
90 }
91 byte_lvalue_modes = {
92   '<$12': 'cpu_6809_ea_direct(self)',
93   '$1234': 'cpu_6809_ea_extended(self)',
94   '-14,x': 'cpu_6809_addressing_mode(self)',
95   'a': 'CPU_6809_EA_A',
96   'b': 'CPU_6809_EA_B',
97 }
98
99 # if it is in word_opcodes it is treated as word and has no suffix
100 word_opcodes = {
101   'bra',
102   'bsr',
103   'dec_word_zf',
104   'inc_word_zf',
105   'exg',
106   'jmp',
107   'jsr',
108   'lbra',
109   'lbsr',
110   'lea',
111   'lea_zf',
112   'psh',
113   'pul',
114   'tfr',
115 }
116 # if any operand is in word_operands it is treated as word and has suffix
117 # in this case it is mandatory that no operand also be in byte_operands
118 word_operands = {
119   '#$1234',
120   'd',
121   'u',
122   's',
123   'x',
124   'y',
125 }
126 word_rvalue_modes = {
127   '#$1234': 'cpu_6809_fetch_word(self)',
128   'a': 'self->regs.byte.a',
129   'b': 'self->regs.byte.b',
130   'd': 'self->regs.word.d',
131   'u': 'self->regs.word.u',
132   's': 'self->regs.word.s',
133   'x': 'self->regs.word.x',
134   'y': 'self->regs.word.y',
135 }
136 word_lvalue_modes = {
137   'ne': '!self->regs.bit.zf',
138   'eq': 'self->regs.bit.zf',
139   'cc': '!self->regs.bit.cf',
140   'cs': 'self->regs.bit.cf',
141   'vc': '!self->regs.bit.vf',
142   'vs': 'self->regs.bit.vf',
143   'pl': '!self->regs.bit.nf',
144   'mi': 'self->regs.bit.nf',
145   'ge': '!self->regs.bit.nf && !self->regs.bit.vf',
146   'gt': '!self->regs.bit.nf && !self->regs.bit.vf && !self->regs.bit.zf',
147   'hi': '!self->regs.bit.cf && !self->regs.bit.zf',
148   'le': 'self->regs.bit.nf || self->regs.bit.vf || self->regs.bit.zf',
149   'ls': 'self->regs.bit.cf || self->regs.bit.zf',
150   'lt': 'self->regs.bit.nf || self->regs.bit.vf',
151   '$0014': 'cpu_6809_ea_relative(self)',
152   '$1237': 'cpu_6809_ea_long_relative(self)',
153   '$1238': 'cpu_6809_ea_long_relative(self)',
154   '<$12': 'cpu_6809_ea_direct(self)',
155   '$1234': 'cpu_6809_ea_extended(self)',
156   '-14,x': 'cpu_6809_addressing_mode(self)',
157   'x,a': 'cpu_6809_fetch_byte(self)',
158   'x,y': 'cpu_6809_fetch_byte(self)',
159   'd': 'CPU_6809_EA_D',
160   'u': 'CPU_6809_EA_U',
161   's': 'CPU_6809_EA_S',
162   'x': 'CPU_6809_EA_X',
163   'y': 'CPU_6809_EA_Y',
164 }
165
166 line = sys.stdin.readline().strip()
167 assert line == 'addressing modes'
168
169 print('int cpu_6809_addressing_mode(struct cpu_6809 *self) {')
170 print('  int ea;')
171 print('  switch (cpu_6809_fetch_byte(self)) {')
172
173 for i in range(0x100):
174   line = sys.stdin.readline().strip()
175
176   print(f'  case 0x{i:02x}:')
177   instr = line.split()
178   assert instr[:2] == ['lea_zf', 'x']
179   mode = instr[2]
180
181   if mode == '???':
182     print('    cpu_6809_illegal_opcode(self);')
183     continue
184
185   indirect = False
186   if mode[:1] == '[' and mode[-1:] == ']':
187     indirect = True
188     mode = mode[1:-1]
189   mode = [j for j in mode.split(',') if len(j)]
190
191   mode_str = ' + '.join([addressing_values.get(j, j) for j in mode])
192   if len(mode) >= 2:
193     mode_str = '({0:s}) & 0xffff'.format(mode_str)
194
195   for j in mode:
196     if j[:2] == '--':
197       print('    {0:s} -= 2;'.format(addressing_values[j[2:]]))
198   print('    ea = {0:s};'.format(mode_str))
199   for j in mode:
200     if j[-2:] == '++':
201       print('    {0:s} += 2;'.format(addressing_values[j[:-2]]))
202   if indirect:
203     if i == 0xfd:
204       print('  indirect:') 
205       print('    ea = cpu_6809_read_word(self, ea);')
206       print('    break;')
207     else:
208       print('    goto indirect;')
209   else:
210     print('    break;')
211
212 line = sys.stdin.readline().strip()
213 assert len(line) == 0
214
215 print('  }')
216 print('  return ea;')
217 print('}')
218 print()
219
220 prefixes = [[], [0x10], [0x11]]
221 for i in prefixes:
222   line = sys.stdin.readline().strip()
223   assert line == 'opcodes{0:s}'.format(''.join([f' 0x{j:02x}' for j in i]))
224
225   print(
226     'void cpu_6809_execute{0:s}(struct cpu_6809 *self) {{'.format(
227       ''.join([f'_{j:02x}' for j in i])
228     )
229   )
230   print('  switch (cpu_6809_fetch_byte(self)) {')
231
232   for j in range(0x100):
233     line = sys.stdin.readline().strip()
234
235     print(f'  case 0x{j:02x}:')
236     k = i + [j]
237     if k in prefixes:
238       print(
239         '    cpu_6809_execute{0:s}(self);'.format(
240           ''.join([f'_{k:02x}' for k in k])
241         )
242       )
243     else:
244       instr = line.split()
245       #print('xxx', instr)
246
247       # detect operation size (byte or word)
248       suffix = ''
249       if instr[0] not in byte_opcodes and instr[0] not in word_opcodes:
250         for k in instr[1:]:
251           if k in byte_operands and suffix != '_word':
252             suffix = '_byte'
253           elif k in word_operands:
254             suffix = '_word'
255
256       # work out which operands are rvalue
257       k0, k1 = rvalue_opcodes.get(instr[0], (0, 0))
258       k0 += len(instr)
259       k1 += len(instr)
260
261       # translate operands
262       if suffix == '_byte' or instr[0] in byte_opcodes:
263         for l in range(1, len(instr)):
264           if l >= k0 and l < k1:
265             if instr[l] in byte_rvalue_modes:
266               instr[l] = byte_rvalue_modes[instr[l]]
267             elif instr[l] in byte_lvalue_modes:
268               instr[l] = 'cpu_6809_read_byte(self, {0:s})'.format(
269                 byte_lvalue_modes[instr[l]]
270               )
271           elif instr[l] in byte_lvalue_modes:
272             instr[l] = byte_lvalue_modes[instr[l]]
273       elif suffix == '_word' or instr[0] in word_opcodes:
274         for l in range(1, len(instr)):
275           if l >= k0 and l < k1:
276             if instr[l] in word_rvalue_modes:
277               instr[l] = word_rvalue_modes[instr[l]]
278             elif instr[l] in word_lvalue_modes:
279               instr[l] = 'cpu_6809_read_word(self, {0:s})'.format(
280                 word_lvalue_modes[instr[l]]
281               )
282           elif instr[l] in word_lvalue_modes:
283             instr[l] = word_lvalue_modes[instr[l]]
284
285       print(
286         '    cpu_6809_{0:s}{1:s}(self{2:s});'.format(
287           instr[0],
288           suffix,
289           ''.join([', ' + k for k in instr[1:]])
290         )
291       )
292     print('    break;')
293
294   line = sys.stdin.readline().strip()
295   assert len(line) == 0
296
297   print('  }')
298   print('}')
299   print()