2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2014 Daniel Elstner <daniel.kitta@gmail.com>
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 3 of the License, or
9 ## (at your option) any later version.
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ## GNU General Public License for more details.
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, see <http://www.gnu.org/licenses/>.
20 import sigrokdecode as srd
21 from functools import reduce
22 from .tables import instr_table_by_prefix
26 ADDR, MEMRD, MEMWR, IORD, IOWR, INSTR, ROP, WOP, WARN = range(9)
28 ADDRBUS, DATABUS, INSTRUCTIONS, OPERANDS, WARNINGS = range(5)
31 M1, RD, WR, MREQ, IORQ = range(8, 13)
34 NONE, MEMRD, MEMWR, IORD, IOWR, FETCH, INTACK = range(7)
36 # Provide custom format type 'H' for hexadecimal output
37 # with leading decimal digit (assembler syntax).
38 class AsmFormatter(string.Formatter):
39 def format_field(self, value, format_spec):
40 if format_spec.endswith('H'):
41 result = format(value, format_spec[:-1] + 'X')
42 return result if result[0] in string.digits else '0' + result
44 return format(value, format_spec)
46 formatter = AsmFormatter()
48 ann_data_cycle_map = {
49 Cycle.MEMRD: Ann.MEMRD,
50 Cycle.MEMWR: Ann.MEMWR,
53 Cycle.FETCH: Ann.MEMRD,
54 Cycle.INTACK: Ann.IORD,
59 return None # unassigned bus channels
61 return reduce(lambda a, b: (a << 1) | b, reversed(bus))
63 def signed_byte(byte):
64 return byte if byte < 128 else byte - 256
66 class Decoder(srd.Decoder):
70 longname = 'Zilog Z80 CPU'
71 desc = 'Zilog Z80 microprocessor disassembly.'
78 'desc': 'Data bus line %d' % i
81 {'id': 'm1', 'name': '/M1', 'desc': 'Machine cycle 1'},
82 {'id': 'rd', 'name': '/RD', 'desc': 'Memory or I/O read'},
83 {'id': 'wr', 'name': '/WR', 'desc': 'Memory or I/O write'},
86 {'id': 'mreq', 'name': '/MREQ', 'desc': 'Memory request'},
87 {'id': 'iorq', 'name': '/IORQ', 'desc': 'I/O request'},
91 'desc': 'Address bus line %d' % i
95 ('addr', 'Memory or I/O address'),
96 ('memrd', 'Byte read from memory'),
97 ('memwr', 'Byte written to memory'),
98 ('iord', 'Byte read from I/O port'),
99 ('iowr', 'Byte written to I/O port'),
100 ('instr', 'Z80 CPU instruction'),
101 ('rop', 'Value of input operand'),
102 ('wop', 'Value of output operand'),
103 ('warn', 'Warning message'),
106 ('addrbus', 'Address bus', (Ann.ADDR,)),
107 ('databus', 'Data bus', (Ann.MEMRD, Ann.MEMWR, Ann.IORD, Ann.IOWR)),
108 ('instructions', 'Instructions', (Ann.INSTR,)),
109 ('operands', 'Operands', (Ann.ROP, Ann.WOP)),
110 ('warnings', 'Warnings', (Ann.WARN,))
114 self.prev_cycle = Cycle.NONE
115 self.op_state = self.state_IDLE
118 self.out_ann = self.register(srd.OUTPUT_ANN)
120 self.samplenum = None
121 self.addr_start = None
122 self.data_start = None
123 self.dasm_start = None
124 self.pend_addr = None
125 self.pend_data = None
128 self.prev_cycle = Cycle.NONE
129 self.op_state = self.state_IDLE
132 def decode(self, ss, es, data):
133 for (self.samplenum, pins) in data:
135 if pins[Pin.MREQ] != 1: # default to asserted
136 if pins[Pin.RD] == 0:
137 cycle = Cycle.FETCH if pins[Pin.M1] == 0 else Cycle.MEMRD
138 elif pins[Pin.WR] == 0:
140 elif pins[Pin.IORQ] == 0: # default to not asserted
141 if pins[Pin.M1] == 0:
143 elif pins[Pin.RD] == 0:
145 elif pins[Pin.WR] == 0:
148 if cycle != Cycle.NONE:
149 self.bus_data = reduce_bus(pins[Pin.D0:Pin.D7+1])
150 if cycle != self.prev_cycle:
151 if self.prev_cycle == Cycle.NONE:
152 self.on_cycle_begin(reduce_bus(pins[Pin.A0:Pin.A15+1]))
153 elif cycle == Cycle.NONE:
156 self.on_cycle_trans()
157 self.prev_cycle = cycle
159 def on_cycle_begin(self, bus_addr):
160 if self.pend_addr is not None:
161 self.put_text(self.addr_start, Ann.ADDR,
162 '{:04X}'.format(self.pend_addr))
163 self.addr_start = self.samplenum
164 self.pend_addr = bus_addr
166 def on_cycle_end(self):
168 self.op_state = self.op_state()
169 if self.ann_dasm is not None:
171 if self.op_state == self.state_RESTART:
172 self.op_state = self.state_IDLE()
174 if self.ann_data is not None:
175 self.put_text(self.data_start, self.ann_data,
176 '{:02X}'.format(self.pend_data))
177 self.data_start = self.samplenum
178 self.pend_data = self.bus_data
179 self.ann_data = ann_data_cycle_map[self.prev_cycle]
181 def on_cycle_trans(self):
182 self.put_text(self.samplenum - 1, Ann.WARN,
183 'Illegal transition between control states')
184 self.pend_addr = None
188 def put_disasm(self):
189 text = formatter.format(self.mnemonic, r=self.arg_reg, d=self.arg_dis,
190 j=self.arg_dis+self.instr_len, i=self.arg_imm,
191 ro=self.arg_read, wo=self.arg_write)
192 self.put_text(self.dasm_start, self.ann_dasm, text)
194 self.dasm_start = self.samplenum
196 def put_text(self, ss, ann_idx, ann_text):
197 self.put(ss, self.samplenum, self.out_ann, [ann_idx, [ann_text]])
199 def state_RESTART(self):
200 return self.state_IDLE
202 def state_IDLE(self):
203 if self.prev_cycle != Cycle.FETCH:
204 return self.state_IDLE
209 self.want_wr_be = False
210 self.op_repeat = False
217 self.instr_pend = False
218 self.read_pend = False
219 self.write_pend = False
220 self.dasm_start = self.samplenum
223 if self.bus_data in (0xCB, 0xED, 0xDD, 0xFD):
224 return self.state_PRE1
226 return self.state_OPCODE
228 def state_PRE1(self):
229 if self.prev_cycle != Cycle.FETCH:
230 self.mnemonic = 'Prefix not followed by fetch'
231 self.ann_dasm = Ann.WARN
232 return self.state_RESTART
233 self.op_prefix = self.pend_data
234 if self.op_prefix in (0xDD, 0xFD):
235 if self.bus_data == 0xCB:
236 return self.state_PRE2
237 if self.bus_data in (0xDD, 0xED, 0xFD):
238 return self.state_PRE1
239 return self.state_OPCODE
241 def state_PRE2(self):
242 if self.prev_cycle != Cycle.MEMRD:
243 self.mnemonic = 'Missing displacement'
244 self.ann_dasm = Ann.WARN
245 return self.state_RESTART
246 self.op_prefix = (self.op_prefix << 8) | self.pend_data
247 return self.state_PREDIS
249 def state_PREDIS(self):
250 if self.prev_cycle != Cycle.MEMRD:
251 self.mnemonic = 'Missing opcode'
252 self.ann_dasm = Ann.WARN
253 return self.state_RESTART
254 self.arg_dis = signed_byte(self.pend_data)
255 return self.state_OPCODE
257 def state_OPCODE(self):
258 (table, self.arg_reg) = instr_table_by_prefix[self.op_prefix]
260 instruction = table.get(self.pend_data, None)
261 if instruction is None:
262 self.mnemonic = 'Invalid instruction'
263 self.ann_dasm = Ann.WARN
264 return self.state_RESTART
265 (self.want_dis, self.want_imm, self.want_read, want_write,
266 self.op_repeat, self.mnemonic) = instruction
267 self.want_write = abs(want_write)
268 self.want_wr_be = (want_write < 0)
269 if self.want_dis > 0:
270 return self.state_POSTDIS
271 if self.want_imm > 0:
272 return self.state_IMM1
273 self.ann_dasm = Ann.INSTR
274 if self.want_read > 0 and self.prev_cycle in (Cycle.MEMRD, Cycle.IORD):
275 return self.state_ROP1
276 if self.want_write > 0 and self.prev_cycle in (Cycle.MEMWR, Cycle.IOWR):
277 return self.state_WOP1
278 return self.state_RESTART
280 def state_POSTDIS(self):
281 self.arg_dis = signed_byte(self.pend_data)
282 if self.want_imm > 0:
283 return self.state_IMM1
284 self.ann_dasm = Ann.INSTR
285 if self.want_read > 0 and self.prev_cycle in (Cycle.MEMRD, Cycle.IORD):
286 return self.state_ROP1
287 if self.want_write > 0 and self.prev_cycle in (Cycle.MEMWR, Cycle.IOWR):
288 return self.state_WOP1
289 return self.state_RESTART
291 def state_IMM1(self):
292 self.arg_imm = self.pend_data
293 if self.want_imm > 1:
294 return self.state_IMM2
295 self.ann_dasm = Ann.INSTR
296 if self.want_read > 0 and self.prev_cycle in (Cycle.MEMRD, Cycle.IORD):
297 return self.state_ROP1
298 if self.want_write > 0 and self.prev_cycle in (Cycle.MEMWR, Cycle.IOWR):
299 return self.state_WOP1
300 return self.state_RESTART
302 def state_IMM2(self):
303 self.arg_imm |= self.pend_data << 8
304 self.ann_dasm = Ann.INSTR
305 if self.want_read > 0 and self.prev_cycle in (Cycle.MEMRD, Cycle.IORD):
306 return self.state_ROP1
307 if self.want_write > 0 and self.prev_cycle in (Cycle.MEMWR, Cycle.IOWR):
308 return self.state_WOP1
309 return self.state_RESTART
311 def state_ROP1(self):
312 self.arg_read = self.pend_data
313 if self.want_read < 2:
314 self.mnemonic = '{ro:02X}'
315 self.ann_dasm = Ann.ROP
316 if self.want_write > 0:
317 return self.state_WOP1
318 if self.want_read > 1:
319 return self.state_ROP2
320 if self.op_repeat and self.prev_cycle in (Cycle.MEMRD, Cycle.IORD):
321 return self.state_ROP1
322 return self.state_RESTART
324 def state_ROP2(self):
325 self.arg_read |= self.pend_data << 8
326 self.mnemonic = '{ro:04X}'
327 self.ann_dasm = Ann.ROP
328 if self.want_write > 0 and self.prev_cycle in (Cycle.MEMWR, Cycle.IOWR):
329 return self.state_WOP1
330 return self.state_RESTART
332 def state_WOP1(self):
333 self.arg_write = self.pend_data
334 if self.want_read > 1:
335 return self.state_ROP2
336 if self.want_write > 1:
337 return self.state_WOP2
338 self.mnemonic = '{wo:02X}'
339 self.ann_dasm = Ann.WOP
340 if self.want_read > 0 and self.op_repeat and \
341 self.prev_cycle in (Cycle.MEMRD, Cycle.IORD):
342 return self.state_ROP1
343 return self.state_RESTART
345 def state_WOP2(self):
347 self.arg_write = (self.arg_write << 8) | self.pend_data
349 self.arg_write |= self.pend_data << 8
350 self.mnemonic = '{wo:04X}'
351 self.ann_dasm = Ann.WOP
352 return self.state_RESTART