1 |
8 |
gdevic |
#!/usr/bin/env python3
|
2 |
3 |
gdevic |
#
|
3 |
|
|
# This script reads the original Z80 PLA table and processes it to get the list of PLA
|
4 |
|
|
# entries in the form suitable to load into the PLA checker program.
|
5 |
|
|
#
|
6 |
|
|
# Format of the output PLA table:
|
7 |
|
|
# 7 bits of modifiers:
|
8 |
|
|
# loc 0 If "1", IX or IY flag is reset |\
|
9 |
|
|
# 1 If "1", IX or IY flag is set | Only 1 of these 2 can be set
|
10 |
|
|
# 2 If "1", in HALT state
|
11 |
|
|
# 3 If "1", ALU operation
|
12 |
|
|
# 4 If "1", XX regular instruction |\
|
13 |
|
|
# 5 If "1", CB instruction table modifier | Only 1 of these 3 can be set
|
14 |
|
|
# 6 If "1", ED instruction table modifier |/
|
15 |
|
|
#
|
16 |
|
|
# Following 16 bits of opcode test in pairs, from bit7 to bit0
|
17 |
|
|
# For each pair, if the left bit is "1", the opcode bit has to be 0
|
18 |
|
|
# if the right bit is "1", the opcode bit has to be 1
|
19 |
|
|
# otherwise the bit is ignored
|
20 |
|
|
#
|
21 |
|
|
#-------------------------------------------------------------------------------
|
22 |
|
|
# Copyright (C) 2014 Goran Devic
|
23 |
|
|
#
|
24 |
|
|
# This program is free software; you can redistribute it and/or modify it
|
25 |
|
|
# under the terms of the GNU General Public License as published by the Free
|
26 |
|
|
# Software Foundation; either version 2 of the License, or (at your option)
|
27 |
|
|
# any later version.
|
28 |
|
|
#
|
29 |
|
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
30 |
|
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
31 |
|
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
32 |
|
|
# more details.
|
33 |
|
|
#-------------------------------------------------------------------------------
|
34 |
|
|
import string
|
35 |
|
|
import os
|
36 |
|
|
|
37 |
|
|
# Input PLA table: a text file representing the original (Z80 reverse-engineered)
|
38 |
|
|
# table at http://arcfn.com/files/z80-pla-table.html
|
39 |
|
|
inFile = "z80-pla-original.txt"
|
40 |
|
|
|
41 |
|
|
# Output processed PLA table
|
42 |
|
|
outFile = "z80-pla.txt"
|
43 |
|
|
|
44 |
|
|
table = []
|
45 |
|
|
|
46 |
|
|
def xtostr ( condition ):
|
47 |
|
|
if condition:
|
48 |
|
|
return "1"
|
49 |
|
|
return "."
|
50 |
|
|
|
51 |
|
|
# Read the content of the input PLA table and add all valid lines (starting with a number)
|
52 |
|
|
with open(inFile, 'r') as fIn:
|
53 |
|
|
for line in fIn:
|
54 |
|
|
seg = line.split()
|
55 |
|
|
if len(seg)>1 and seg[0].isdigit():
|
56 |
|
|
table.append(line)
|
57 |
|
|
|
58 |
|
|
# In the original PLA table, entries are listed in reverse order -
|
59 |
|
|
table.reverse()
|
60 |
|
|
|
61 |
|
|
# Control ID to detect errors
|
62 |
|
|
controlID = 0
|
63 |
|
|
|
64 |
|
|
with open(outFile, 'w') as fOut:
|
65 |
|
|
fOut.write("# Automatically generated by process-pla.py\n")
|
66 |
|
|
pla = []
|
67 |
|
|
for entry in table:
|
68 |
|
|
# This is an example of an input PLA entry containing different segments:
|
69 |
|
|
# ID ALU XX CB ED 0 /0 1 /1 2 /2 6 /6 7 /7 3 /3 4 /4 5 /5 Instruction Ex Description
|
70 |
|
|
# 59 1 1 . . . . . . . . . 1 1 . 1 . . 1 . 1 01110xxx ce ld (hl),r (and hlt)
|
71 |
|
|
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
72 |
|
|
seg = entry.split()
|
73 |
|
|
if len(seg)>22:
|
74 |
|
|
# Sanity check
|
75 |
|
|
if controlID!=int(seg[0]):
|
76 |
|
|
fOut.write("Unexpected entry " + seg[0])
|
77 |
|
|
exit(-1)
|
78 |
|
|
controlID = controlID + 1
|
79 |
|
|
|
80 |
|
|
# Decipher [22] into actual PLA entry lines IXY0, IXY1 and HALT (a, b, c)
|
81 |
|
|
entry = ""
|
82 |
|
|
entry += xtostr("a" in seg[22])
|
83 |
|
|
entry += xtostr("b" in seg[22])
|
84 |
|
|
entry += xtostr("c" in seg[22])
|
85 |
|
|
# Append the rest of the PLA modifiers: ALU, XX, CB and ED
|
86 |
|
|
entry += seg[1] + seg[2] + seg[3] + seg[4] + ' '
|
87 |
|
|
# Add the instruction decoder bit7 through bit0 in that order
|
88 |
|
|
# 7 /7 6 /6 5 /5 4 /4 3 /3 2 /2 1 /1 0 /0
|
89 |
|
|
entry += seg[13]+seg[14] +seg[11]+seg[12] +seg[19]+seg[20] +seg[17]+seg[18] +seg[15]+seg[16] +seg[9]+seg[10] +seg[7]+seg[8] +seg[5]+seg[6]
|
90 |
|
|
|
91 |
|
|
# Check if the new PLA entry is a duplicate (already stored to PLA)
|
92 |
|
|
# Append "D" for duplicate entries so they can be skipped easily
|
93 |
|
|
if entry in pla:
|
94 |
|
|
fOut.write(entry + "\tD\t")
|
95 |
|
|
else:
|
96 |
|
|
# Store the new PLA line in the PLA list and write it out
|
97 |
|
|
pla.append(entry)
|
98 |
|
|
fOut.write(entry + "\t-\t")
|
99 |
|
|
|
100 |
|
|
# Write the ID number, text decode and description
|
101 |
|
|
fOut.write(seg[0] + "\t" + seg[21] + "\t" + ' '.join(seg[23:len(seg)]) + "\n")
|
102 |
|
|
|
103 |
|
|
# The original PLA table passes individual opcode bits that are needed to decode many
|
104 |
|
|
# instructions but it does not contain concrete entries
|
105 |
|
|
# We append those bits to the end of our PLA table
|
106 |
|
|
fOut.write("....... ...............1\t-\t99\txxxxxxx1\topcode[0]\n")
|
107 |
|
|
fOut.write("....... .............1..\t-\t100\txxxxxx1x\topcode[1]\n")
|
108 |
|
|
fOut.write("....... ...........1....\t-\t101\txxxxx1xx\topcode[2]\n")
|
109 |
|
|
fOut.write("....... .........1......\t-\t102\txxxx1xxx\topcode[3]\n")
|
110 |
|
|
fOut.write("....... .......1........\t-\t103\txxx1xxxx\topcode[4]\n")
|
111 |
|
|
fOut.write("....... .....1..........\t-\t104\txx1xxxxx\topcode[5]\n")
|