Skip to content

Commit f283bbb

Browse files
committed
Add immediate encoding table with constant names
Implements also more testing in asm-tester.py
1 parent 170b784 commit f283bbb

File tree

5 files changed

+174
-30
lines changed

5 files changed

+174
-30
lines changed

asm-tester.py

Lines changed: 63 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@
1414
import argparse, re, subprocess, struct, uuid, os, instparse, reginfo, multiprocessing, itertools
1515
from tqdm import tqdm
1616

17+
COLRED = '\033[91m'
18+
COLGREEN = '\033[92m'
19+
COLRESET = '\033[0m'
20+
1721
parser = argparse.ArgumentParser(prog='asm-tester')
1822
parser.add_argument('--reference', dest='reference', required=True, help='Path (or executable within PATH) to invoke reference `as`')
1923
parser.add_argument('--undertest', dest='undertest', required=True, help='Path (or executable within PATH) to invoke for `as`')
2024
parser.add_argument('--objcopy', dest='objcopy', required=True, help='Path (or executable within PATH) to invoke for `objcopy`')
21-
parser.add_argument('--chunksize', dest='chunksize', type=int, default=128*1024, help='Block size (instruction count)')
2225
parser.add_argument('--instr', dest='instregex', default=".*", help='Instructions to emit (a regular expression)')
2326
parser.add_argument('--threads', dest='nthreads', type=int, default=8, help='Number of threads to use')
2427

@@ -62,6 +65,26 @@ def run_sidebyside(asmfile):
6265

6366
return (same, None, None)
6467

68+
def run_errors(expected_insts, asmfile):
69+
# These files should produce a ton of errors, each line should be invalid.
70+
objf1 = tmpfile(name="obj")
71+
72+
p1 = subprocess.Popen([args.reference, "-march=allegrex", "-o", objf1, asmfile],
73+
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)
74+
75+
outp1 = p1.communicate()
76+
p1.wait()
77+
exit_code1 = p1.poll()
78+
79+
if exit_code1 != 0:
80+
# Validate there's error lines
81+
errlog = outp1[1].decode("ascii").strip()
82+
numerrs = errlog.count("\n")
83+
if numerrs == expected_insts:
84+
return (True, None)
85+
86+
return (False, asmfile)
87+
6588
def dict_product(indict):
6689
return (dict(zip(indict.keys(), values)) for values in itertools.product(*indict.values()))
6790

@@ -94,12 +117,16 @@ def gencombs(instname, variables, elemcnt):
94117
return (dict_product(combos), subreginfo)
95118

96119
# Given a list of immediates generate all their possible values and combinations
97-
def genimms(imms):
120+
def genimms(imms, numel):
98121
combos = {}
99122
for v, iinfo in imms.items():
100123
combos[v] = []
101124
if iinfo.get("type", None) == "enum":
102-
combos[v] = iinfo["enum"]
125+
cs = iinfo["enum"]
126+
if isinstance(cs, dict):
127+
combos[v] = cs["0sptq"[numel]]
128+
else:
129+
combos[v] = cs
103130
else:
104131
for val in range(iinfo["minval"], iinfo["maxval"] + 1):
105132
combos[v].append(str(val))
@@ -133,18 +160,14 @@ def check_overlap(iobj, regcomb, subreginfo):
133160
# Aggregate all bits toghether to get a number of instructions to generate
134161
print("Testing %d different instructions!" % len(allinsts))
135162

136-
def process_block(instname, iobj):
137-
if any(k for k, v in iobj.inputs().items() if v.split(":")[0] not in ["single", "vector", "matrix", "vfpucc", "gpr"]):
138-
# TODO Support other reg types!
139-
print("Instruction", instname, "has some unsupported inputs", iobj.raw_syntax())
140-
return (True, instname, 0)
163+
def process_block(instname, iobj, validinsts):
164+
regs = iobj.inputs() | iobj.outputs()
141165

142-
if any(k for k, v in iobj.outputs().items() if v.split(":")[0] not in ["single", "vector", "matrix", "vfpucc", "gpr"]):
166+
if any(k for k, v in regs.items() if v.split(":")[0] not in ["single", "vector", "matrix", "vfpucc", "gpr"]):
143167
# TODO Support other reg types!
144-
print("Instruction", instname, "has some unsupported outputs", iobj.raw_syntax())
168+
print("Instruction", instname, "has some unsupported inputs/outputs", iobj.raw_syntax())
145169
return (True, instname, 0)
146170

147-
regs = iobj.inputs() | iobj.outputs()
148171
# No need to allocate CC registers :D
149172
regs = {k:v for k, v in regs.items() if v != "vfpucc"}
150173

@@ -155,50 +178,61 @@ def process_block(instname, iobj):
155178
with open(asmfile, "w") as fd:
156179
regit, subreginfo = gencombs(instname, regs, iobj.numelems())
157180
for varcomb in regit:
158-
# Validate that this combination of registers is even valid
159-
if not check_overlap(iobj, varcomb, subreginfo):
160-
continue
161-
162181
# Fake one immediate if there are none. Something nicer would be better tho.
163182
imms = iobj.immediates() or {'dummyimm': {'type': 'interger', 'minval': 0, 'maxval': 0}}
164183

165-
for immcomb in genimms(imms):
184+
for immcomb in genimms(imms, iobj.numelems()):
166185
istr = iobj.raw_syntax()
167186
for vname, vval in varcomb.items():
168187
istr = istr.replace("%" + vname, vval)
169188
for iname, ival in immcomb.items():
170189
istr = istr.replace("%" + iname, ival)
171-
fd.write(istr + "\n")
172-
numinsts += 1
173190

174-
# Run the disassemblers now!
175-
success, ec1, ec2 = run_sidebyside(asmfile)
176-
if not success:
177-
return (False, instname, ec1, ec2, asmfile)
191+
# Validate that this combination of registers is even valid
192+
if check_overlap(iobj, varcomb, subreginfo) == validinsts:
193+
fd.write(istr + "\n")
194+
numinsts += 1
195+
196+
if numinsts > 0:
197+
# Run the disassemblers now!
198+
if validinsts:
199+
success, ec1, ec2 = run_sidebyside(asmfile)
200+
if not success:
201+
return (False, instname, ec1, ec2, asmfile)
202+
else:
203+
success, outp = run_errors(numinsts, asmfile)
204+
if not success:
205+
return (False, instname, asmfile)
178206

179-
#os.unlink(asmfile)
207+
os.unlink(asmfile)
180208
return (True, instname, numinsts)
181209

182210
res = []
183211
finfo = []
184212
with multiprocessing.Pool(processes=args.nthreads) as executor:
185213
for instname, iobj in allinsts:
186-
r = executor.apply_async(process_block, (instname, iobj))
187-
res.append(r)
214+
res.append((executor.apply_async(process_block, (instname, iobj, True)), True))
215+
res.append((executor.apply_async(process_block, (instname, iobj, False)), False))
188216

189217
executor.close()
190218

191-
totalinsts = 0
192-
for r in tqdm(res):
219+
totalinsts, badinsts = 0, 0
220+
for r, t in tqdm(res):
193221
succ, *info = r.get()
194222
if succ is False:
195223
print(info)
196224
else:
197-
totalinsts += info[1]
198-
finfo.append("%s : %d instructions" % (info[0], info[1]))
225+
if t:
226+
totalinsts += info[1]
227+
finfo.append(("%s : %d " + COLGREEN + "good instructions" + COLRESET) % (info[0], info[1]))
228+
else:
229+
if info[1]:
230+
badinsts += info[1]
231+
finfo.append(("%s : %d " + COLRED + "bad instructions" + COLRESET) % (info[0], info[1]))
199232

200233
print("\n".join(finfo))
201234
print("--------------")
202235
print("Tested a total of %d instructions" % totalinsts)
236+
print("Validated a total of %d bad instructions" % badinsts)
203237

204238

docs/templates/template-html.html

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,33 @@
5656
text-decoration: underline;
5757
}
5858

59+
table {
60+
border: 1px solid #444;
61+
border-collapse: collapse;
62+
width: 50%;
63+
margin-top: 15px;
64+
margin-right: 15px;
65+
font-size: 14px;
66+
}
67+
th {
68+
border-bottom: 1px solid #ccc;
69+
background-color: #eee;
70+
text-align: center;
71+
padding: 10px;
72+
}
73+
td {
74+
border-bottom: 1px solid #ccc;
75+
border-right: 1px solid #ccc;
76+
text-align: center;
77+
padding: 5px;
78+
}
79+
tr:last-child td {
80+
border-bottom: none;
81+
}
82+
td:last-child {
83+
border-right: none;
84+
}
85+
5986
.matrixsvgdiv {
6087
text-align: center;
6188
}
@@ -632,6 +659,16 @@ <h2 id="${instr["name"]}">${instr["name"]}</h2>
632659
<pre class="pcode">${instr["pseudocode"]}</pre>
633660
% endif
634661

662+
% if instr["imm-values"]:
663+
<p class="inst-header">Immediate encoding</p>
664+
<table>
665+
<tr><th>Symbol</th><th>Value</th></tr>
666+
% for value, istr in instr["imm-values"].items():
667+
<tr><td>${istr}</td><td>${value}</td></tr>
668+
% endfor
669+
</table>
670+
% endif
671+
635672
<div class="divider" style="width:24%; margin:30px 0 50px;"></div>
636673
% endfor
637674

docs/templates/template-pdf.html

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,32 @@
5454
.matrixsvg {
5555
width: 35%;
5656
}
57+
58+
table {
59+
border: 1px solid #444;
60+
border-collapse: collapse;
61+
width: 50%;
62+
margin-top: 15px;
63+
margin-right: 15px;
64+
font-size: 14px;
65+
}
66+
th {
67+
border-bottom: 1px solid #ccc;
68+
text-align: center;
69+
padding: 10px;
70+
}
71+
td {
72+
border-bottom: 1px solid #ccc;
73+
border-right: 1px solid #ccc;
74+
text-align: center;
75+
padding: 5px;
76+
}
77+
tr:last-child td {
78+
border-bottom: none;
79+
}
80+
td:last-child {
81+
border-right: none;
82+
}
5783
</style>
5884
</head>
5985
<body>
@@ -195,6 +221,16 @@ <h3>Pseudocode</h3>
195221
<pre><code>${instr["pseudocode"]}</code></pre>
196222
% endif
197223

224+
% if instr["imm-values"]:
225+
<h3>Immediate encoding</h3>
226+
<table>
227+
<tr><th>Symbol</th><th>Value</th></tr>
228+
% for value, istr in instr["imm-values"].items():
229+
<tr><td>${istr}</td><td>${value}</td></tr>
230+
% endfor
231+
</table>
232+
% endif
233+
198234
% if instr["auxfns"]:
199235
<h3>Used functions</h3>
200236
<pre><code>

gen-docs.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,16 @@ def cntelem(regtype, lanes):
167167
pcodeep = [ util.simplify_code(x) or x for x in pcodeep ]
168168
pcode += pcodeep
169169

170+
imms = {}
171+
for immname, imminfo in iobj.immediates().items():
172+
if "enum" in imminfo:
173+
cs = imminfo["enum"]
174+
if isinstance(cs, dict):
175+
imms = cs["0sptq"[iobj.numelems()]]
176+
else:
177+
imms = cs
178+
imms = {i + imminfo["minval"]: x for i, x in enumerate(imms)}
179+
170180
# Inst encoding, fields and fixed bits
171181
instlist.append({
172182
"name": instname,
@@ -185,6 +195,7 @@ def cntelem(regtype, lanes):
185195
"fields": iobj.encoding().fields(),
186196
"baseword": iobj.encoding().baseword(),
187197
"basemask": iobj.encoding().basemask(),
198+
"imm-values": imms,
188199
})
189200

190201
tmpl = open("docs/templates/template-%s.html" % args.format, "r").read()

inst-vfpu-desc.yaml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,42 @@ instruction-operands:
138138
maxval: 31
139139

140140
vector-unary-rot: # rs is always single and has an extra imm5 field
141-
syntax: "%opcode %rd, %rs, %imm5"
141+
syntax: "%opcode %rd, %rs, %imval"
142142
inputs:
143143
rs: single
144144
outputs:
145145
rd: vector
146146
immediates:
147147
imval:
148+
type: enum
149+
enum:
150+
p: [
151+
"[c,s]", "[s,c]", "[s,0]", "[s,0]", "[c,s]", "[s,c]", "[0,s]", "[0,s]",
152+
"[c,0]", "[0,c]", "[s,s]", "[0,0]", "[c,0]", "[0,c]", "[0,0]", "[s,s]",
153+
"[c,-s]", "[-s,c]", "[-s,0]", "[-s,0]", "[c,-s]", "[-s,c]", "[0,-s]", "[0,-s]",
154+
"[c,0]", "[0,c]", "[-s,-s]", "[0,0]", "[c,0]", "[0,c]", "[0,0]", "[-s,-s]" ]
155+
t: [
156+
"[c,s,s]", "[s,c,0]", "[s,0,c]", "[s,0,0]",
157+
"[c,s,0]", "[s,c,s]", "[0,s,c]", "[0,s,0]",
158+
"[c,0,s]", "[0,c,s]", "[s,s,c]", "[0,0,s]",
159+
"[c,0,0]", "[0,c,0]", "[0,0,c]", "[s,s,s]",
160+
"[c,-s,-s]", "[-s,c,0]", "[-s,0,c]", "[-s,0,0]",
161+
"[c,-s,0]", "[-s,c,-s]", "[0,-s,c]", "[0,-s,0]",
162+
"[c,0,-s]", "[0,c,-s]", "[-s,-s,c]", "[0,0,-s]",
163+
"[c,0,0]", "[0,c,0]", "[0,0,c]", "[-s,-s,-s]" ]
164+
q: [
165+
"[c,s,s,s]", "[s,c,0,0]", "[s,0,c,0]", "[s,0,0,c]",
166+
"[c,s,0,0]", "[s,c,s,s]", "[0,s,c,0]", "[0,s,0,c]",
167+
"[c,0,s,0]", "[0,c,s,0]", "[s,s,c,s]", "[0,0,s,c]",
168+
"[c,0,0,s]", "[0,c,0,s]", "[0,0,c,s]", "[s,s,s,c]",
169+
"[c,-s,-s,-s]", "[-s,c,0,0]", "[-s,0,c,0]", "[-s,0,0,c]",
170+
"[c,-s,0,0]", "[-s,c,-s,-s]", "[0,-s,c,0]", "[0,-s,0,c]",
171+
"[c,0,-s,0]", "[0,c,-s,0]", "[-s,-s,c,-s]", "[0,0,-s,c]",
172+
"[c,0,0,-s]", "[0,c,0,-s]", "[0,0,c,-s]", "[-s,-s,-s,c]" ]
148173
minval: 0
149174
maxval: 31
150175

176+
151177
vector-unary-mod: # Features an extra imm8 field
152178
syntax: "%opcode %rd, %rs, %imval"
153179
inputs:

0 commit comments

Comments
 (0)