import sigrokdecode as srd
from functools import reduce
from .tables import instr_table_by_prefix
+import string
class Ann:
ADDR, MEMRD, MEMWR, IORD, IOWR, INSTR, ROP, WOP, WARN = range(9)
WOP2 = 'WOP2' # second byte of write operand
RESTART = 'RESTART' # restart instruction decoding
+# Provide custom format type 'H' for hexadecimal output
+# with leading decimal digit (assembler syntax).
+class AsmFormatter(string.Formatter):
+ def format_field(self, value, format_spec):
+ if format_spec.endswith('H'):
+ result = format(value, format_spec[:-1] + 'X')
+ return result if result[0] in string.digits else '0' + result
+ else:
+ return format(value, format_spec)
+
+formatter = AsmFormatter()
+
ann_data_cycle_map = {
Cycle.MEMRD: Ann.MEMRD,
Cycle.MEMWR: Ann.MEMWR,
class Decoder(srd.Decoder):
api_version = 1
- id = 'z80'
- name = 'Z80'
- longname = 'Zilog Z80 CPU'
- desc = 'Zilog Z80 microprocessor disassembly.'
- license = 'gplv2+'
- inputs = ['logic']
- outputs = ['z80']
+ id = 'z80'
+ name = 'Z80'
+ longname = 'Zilog Z80 CPU'
+ desc = 'Zilog Z80 microprocessor disassembly.'
+ license = 'gplv2+'
+ inputs = ['logic']
+ outputs = ['z80']
probes = [
- {'id': 'd0', 'name': 'D0', 'desc': 'Data bus line 0'},
- {'id': 'd1', 'name': 'D1', 'desc': 'Data bus line 1'},
- {'id': 'd2', 'name': 'D2', 'desc': 'Data bus line 2'},
- {'id': 'd3', 'name': 'D3', 'desc': 'Data bus line 3'},
- {'id': 'd4', 'name': 'D4', 'desc': 'Data bus line 4'},
- {'id': 'd5', 'name': 'D5', 'desc': 'Data bus line 5'},
- {'id': 'd6', 'name': 'D6', 'desc': 'Data bus line 6'},
- {'id': 'd7', 'name': 'D7', 'desc': 'Data bus line 7'},
+ {'id': 'd%d' % i, 'name': 'D%d' % i, 'desc': 'Data bus line %d' % i}
+ for i in range(8)
+ ] + [
{'id': 'm1', 'name': '/M1', 'desc': 'Machine cycle 1'},
{'id': 'rd', 'name': '/RD', 'desc': 'Memory or I/O read'},
{'id': 'wr', 'name': '/WR', 'desc': 'Memory or I/O write'},
optional_probes = [
{'id': 'mreq', 'name': '/MREQ', 'desc': 'Memory request'},
{'id': 'iorq', 'name': '/IORQ', 'desc': 'I/O request'},
- {'id': 'a0', 'name': 'A0', 'desc': 'Address bus line 0'},
- {'id': 'a1', 'name': 'A1', 'desc': 'Address bus line 1'},
- {'id': 'a2', 'name': 'A2', 'desc': 'Address bus line 2'},
- {'id': 'a3', 'name': 'A3', 'desc': 'Address bus line 3'},
- {'id': 'a4', 'name': 'A4', 'desc': 'Address bus line 4'},
- {'id': 'a5', 'name': 'A5', 'desc': 'Address bus line 5'},
- {'id': 'a6', 'name': 'A6', 'desc': 'Address bus line 6'},
- {'id': 'a7', 'name': 'A7', 'desc': 'Address bus line 7'},
- {'id': 'a8', 'name': 'A8', 'desc': 'Address bus line 8'},
- {'id': 'a9', 'name': 'A9', 'desc': 'Address bus line 9'},
- {'id': 'a10', 'name': 'A10', 'desc': 'Address bus line 10'},
- {'id': 'a11', 'name': 'A11', 'desc': 'Address bus line 11'},
- {'id': 'a12', 'name': 'A12', 'desc': 'Address bus line 12'},
- {'id': 'a13', 'name': 'A13', 'desc': 'Address bus line 13'},
- {'id': 'a14', 'name': 'A14', 'desc': 'Address bus line 14'},
- {'id': 'a15', 'name': 'A15', 'desc': 'Address bus line 15'},
+ ] + [
+ {'id': 'a%d' % i, 'name': 'A%d' % i, 'desc': 'Address bus line %d' % i}
+ for i in range(16)
]
options = {}
annotations = [
- ['addr', 'Memory or I/O address'],
- ['memrd', 'Byte read from memory'],
- ['memwr', 'Byte written to memory'],
- ['iord', 'Byte read from I/O port'],
- ['iowr', 'Byte written to I/O port'],
- ['instr', 'Z80 CPU instruction'],
- ['rop', 'Value of input operand'],
- ['wop', 'Value of output operand'],
- ['warning', 'Warning message'],
+ ['addr', 'Memory or I/O address'],
+ ['memrd', 'Byte read from memory'],
+ ['memwr', 'Byte written to memory'],
+ ['iord', 'Byte read from I/O port'],
+ ['iowr', 'Byte written to I/O port'],
+ ['instr', 'Z80 CPU instruction'],
+ ['rop', 'Value of input operand'],
+ ['wop', 'Value of output operand'],
+ ['warn', 'Warning message'],
]
annotation_rows = (
('addrbus', 'Address bus', (Ann.ADDR,)),
self.ann_dasm = None
self.prev_cycle = Cycle.NONE
self.op_state = OpState.IDLE
+ self.instr_len = 0
def decode(self, ss, es, data):
for (self.samplenum, pins) in data:
self.pend_addr = bus_addr
def on_cycle_end(self):
+ self.instr_len += 1
self.op_state = getattr(self, 'on_state_' + self.op_state)()
if self.ann_dasm is not None:
self.put_disasm()
self.ann_dasm = None
def put_disasm(self):
- text = self.mnemonic.format(r=self.arg_reg, d=self.arg_dis,
- i=self.arg_imm, ro=self.arg_read,
- wo=self.arg_write)
+ text = formatter.format(self.mnemonic, r=self.arg_reg, d=self.arg_dis,
+ j=self.arg_dis+self.instr_len, i=self.arg_imm,
+ ro=self.arg_read, wo=self.arg_write)
self.put_text(self.dasm_start, self.ann_dasm, text)
self.ann_dasm = None
self.dasm_start = self.samplenum
self.write_pend = False
self.dasm_start = self.samplenum
self.op_prefix = 0
+ self.instr_len = 0
if self.bus_data in (0xCB, 0xED, 0xDD, 0xFD):
return OpState.PRE1
else: