From d4f4f901a7da38c8848583d68eeda2f963086043 Mon Sep 17 00:00:00 2001 From: Rob McMullen Date: Sat, 27 Feb 2016 17:30:48 -0800 Subject: [PATCH 1/5] z80: Added placeholder instructions and address modes for ddcb and fdcb instructions --- z80.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/z80.py b/z80.py index 0f70504..bf43280 100644 --- a/z80.py +++ b/z80.py @@ -297,6 +297,7 @@ addressModeTable = { "z" : "z", "z,pcr" : "z,${0:04X}", "z,nn" : "z,${1:02X}{0:02X}", +"bit" : "${0:02X},${1:02X}", } @@ -882,7 +883,7 @@ opcodeTable = { # The below are a set of instructions that all start with 0xddcb. They # are not supported yet. -0xddcb : [ 4, "unimplemented", "implied" ], +0xddcb : [ 4, "ixbit", "bit" ], 0xed40 : [ 2, "in", "b,indc" ], 0xed41 : [ 2, "out", "indc,b" ], @@ -978,7 +979,7 @@ opcodeTable = { # The below are a set of instructions that all start with 0xfdcb. They # are not supported yet. -0xfdcb : [ 4, "unimplemented", "implied" ], +0xfdcb : [ 4, "iybit", "bit" ], } From d3c950d36569fc17136699ae4d74c72f8a679896 Mon Sep 17 00:00:00 2001 From: Rob McMullen Date: Sun, 28 Feb 2016 23:21:27 -0800 Subject: [PATCH 2/5] z80: added 4-byte ix/iy bit instructions --- udis.py | 10 +++++++++- z80.py | 44 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/udis.py b/udis.py index 00dfed6..0c34b9e 100755 --- a/udis.py +++ b/udis.py @@ -26,6 +26,7 @@ import signal pcr = 1 und = 2 +z80bit = 4 # Functions @@ -195,7 +196,14 @@ while True: elif length == 2: operand = format.format(op[1]) elif length == 3: - operand = format.format(op[1], op[2]) + if flags & 4 == z80bit: + opcode = (opcode << 16) + op[2] + # reread opcode table for real format string + length, mnemonic, mode = opcodeTable[opcode] + format = addressModeTable[mode] + operand = format.format(op[1]) + else: + operand = format.format(op[1], op[2]) elif length == 4: operand = format.format(op[1], op[2], op[3]) elif length == 5: diff --git a/z80.py b/z80.py index bf43280..5b5b4ac 100644 --- a/z80.py +++ b/z80.py @@ -300,7 +300,6 @@ addressModeTable = { "bit" : "${0:02X},${1:02X}", } - # Op Code Table # Key is numeric opcode (possibly multiple bytes) # Value is a list: @@ -881,10 +880,6 @@ opcodeTable = { 0xdd8e : [3, "adc", "indix+d" ], -# The below are a set of instructions that all start with 0xddcb. They -# are not supported yet. -0xddcb : [ 4, "ixbit", "bit" ], - 0xed40 : [ 2, "in", "b,indc" ], 0xed41 : [ 2, "out", "indc,b" ], 0xed42 : [ 2, "sbc", "hl,bc" ], @@ -977,11 +972,42 @@ opcodeTable = { 0xfdb6 : [ 3, "or", "indiy+d" ], 0xfdbe : [ 3, "cp", "indiy+d" ], -# The below are a set of instructions that all start with 0xfdcb. They -# are not supported yet. -0xfdcb : [ 4, "iybit", "bit" ], - +# Placeholder 2-byte leadins for the 4-byte ix/iy bit instructions fully +# defined below. The z80bit flag triggers a special case in the disassembler +# to look up the 4 byte instruction. +0xddcb : [ 4, "ixbit", "implied", z80bit ], +0xfdcb : [ 4, "iybit", "implied", z80bit ], } +def extra_opcodes(addr_table, op_table): + # Create all the 0xddcb and 0xfdcb addressing modes. The modes look like [0-7],(i[xy]+*)[,[abcdehl]]? + for index in ['x', 'y']: + for bit in range(8): + k = "%d,indi%s+d" % (bit, index) + v = "%d,(i%s+${0:02X})" % (bit, index) + addr_table[k] = v + for reg in ['a', 'b', 'c', 'd', 'e', 'h', 'l']: + k = "%d,indi%s+d,%s" % (bit, index, reg) + v = "%d,(i%s+${0:02X}),%s" % (bit, index, reg) + addr_table[k] = v + + # Create all the 0xddcb and 0xfdcb opcodes. These are all 4 byte opcodes + # where the 3rd byte is a -128 - +127 offset. For the purposes of using + # this table, the 3rd byte will be marked as zero and the disassembler will + # have to insert the real 3rd byte the check of the z80bit special case + for first_byte, x_or_y in [(0xdd, 'x'), (0xfd, 'y')]: + # groups of 8, expand to full 256 + mnemonics_8 = ['rlc', 'rrc', 'rl', 'rr', 'sla', 'sra', 'sll', 'sr1'] + ['bit'] * 8 + ['res'] * 8 + ['set'] * 8 + mnemonics = [m for mnemonic in mnemonics_8 for m in [mnemonic]*8] + + # create all 256 addressing modes, in groups of 64 + addrmodes = ['indi%s+d' + a for a in [',b', ',c', ',d', ',e', ',h', ',l', '', ',a']] * 8 + [f % d for d in range(8) for f in ['%d,indi%%s+d'] * 8] + [f % d for d in range(8) for f in ['%d,indi%%s+d' + a for a in [',b', ',c', ',d', ',e', ',h', ',l', '', ',a']]] * 2 + + for fourth_byte, (instruction, addrmode) in enumerate(zip(mnemonics, addrmodes)): + opcode = (first_byte << 24) + (0xcb << 16) + fourth_byte + op_table[opcode] = [ 4, instruction, addrmode % x_or_y ] +extra_opcodes(addressModeTable, opcodeTable) +del extra_opcodes + # End of processor specific code ########################################################################## From c924ce0fc289ce6db6bf8137928d2de8238a4311 Mon Sep 17 00:00:00 2001 From: Rob McMullen Date: Mon, 29 Feb 2016 10:50:48 -0800 Subject: [PATCH 3/5] z80: added z80bit flag to generated ddcb and fdcb 4 byte instructions --- udis.py | 2 +- z80.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/udis.py b/udis.py index 0c34b9e..8e3aa0c 100755 --- a/udis.py +++ b/udis.py @@ -199,7 +199,7 @@ while True: if flags & 4 == z80bit: opcode = (opcode << 16) + op[2] # reread opcode table for real format string - length, mnemonic, mode = opcodeTable[opcode] + length, mnemonic, mode, flags = opcodeTable[opcode] format = addressModeTable[mode] operand = format.format(op[1]) else: diff --git a/z80.py b/z80.py index 5b5b4ac..86d8970 100644 --- a/z80.py +++ b/z80.py @@ -1005,7 +1005,7 @@ def extra_opcodes(addr_table, op_table): for fourth_byte, (instruction, addrmode) in enumerate(zip(mnemonics, addrmodes)): opcode = (first_byte << 24) + (0xcb << 16) + fourth_byte - op_table[opcode] = [ 4, instruction, addrmode % x_or_y ] + op_table[opcode] = [ 4, instruction, addrmode % x_or_y, z80bit ] extra_opcodes(addressModeTable, opcodeTable) del extra_opcodes From f8d8de1bcc4741db26259d748f39c4395028b578 Mon Sep 17 00:00:00 2001 From: Rob McMullen Date: Mon, 29 Feb 2016 13:26:40 -0800 Subject: [PATCH 4/5] z80: removed inadvertently added test addressing mode --- z80.py | 1 - 1 file changed, 1 deletion(-) diff --git a/z80.py b/z80.py index 86d8970..bb7aadd 100644 --- a/z80.py +++ b/z80.py @@ -297,7 +297,6 @@ addressModeTable = { "z" : "z", "z,pcr" : "z,${0:04X}", "z,nn" : "z,${1:02X}{0:02X}", -"bit" : "${0:02X},${1:02X}", } # Op Code Table From d9531376fc8af55428025b608f57faec84a713c0 Mon Sep 17 00:00:00 2001 From: Rob McMullen Date: Mon, 29 Feb 2016 13:27:52 -0800 Subject: [PATCH 5/5] udis: simplified flag logical operations --- udis.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/udis.py b/udis.py index 8e3aa0c..6f4c16c 100755 --- a/udis.py +++ b/udis.py @@ -182,7 +182,7 @@ while True: # Handle relative addresses. Indicated by the flag pcr being set. # Assumes the operand that needs to be PC relative is the last one. # Note: Code will need changes if more flags are added. - if flags & 1 == pcr: + if flags & pcr: if op[length-1] < 128: op[length-1] = address + op[length-1] + length else: @@ -196,7 +196,7 @@ while True: elif length == 2: operand = format.format(op[1]) elif length == 3: - if flags & 4 == z80bit: + if flags & z80bit: opcode = (opcode << 16) + op[2] # reread opcode table for real format string length, mnemonic, mode, flags = opcodeTable[opcode]