Emit encoding lists (WIP).
Compute the u16 representation of encoding lists and emit a big table concatenating all of them. Use the UniqueSeqTable to share some table space between CPU modes.
This commit is contained in:
@@ -1030,6 +1030,9 @@ class CPUMode(object):
|
|||||||
self.encodings = []
|
self.encodings = []
|
||||||
isa.cpumodes.append(self)
|
isa.cpumodes.append(self)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
def enc(self, *args, **kwargs):
|
def enc(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Add a new encoding to this CPU mode.
|
Add a new encoding to this CPU mode.
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ instructions with different types for secondary type variables.
|
|||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
import srcgen
|
import srcgen
|
||||||
from collections import OrderedDict
|
from unique_table import UniqueSeqTable
|
||||||
|
from collections import OrderedDict, defaultdict
|
||||||
|
|
||||||
|
|
||||||
def emit_instp(instp, fmt):
|
def emit_instp(instp, fmt):
|
||||||
@@ -102,6 +103,43 @@ def emit_instps(instps, fmt):
|
|||||||
fmt.line(' instp_idx);')
|
fmt.line(' instp_idx);')
|
||||||
|
|
||||||
|
|
||||||
|
# Encoding lists are represented as u16 arrays.
|
||||||
|
CODE_BITS = 16
|
||||||
|
PRED_BITS = 12
|
||||||
|
PRED_MASK = (1 << PRED_BITS) - 1
|
||||||
|
|
||||||
|
# 0..CODE_ALWAYS means: Check instruction predicate and use the next two
|
||||||
|
# entries as a (recipe, encbits) pair if true. CODE_ALWAYS is the always-true
|
||||||
|
# predicate, smaller numbers refer to instruction predicates.
|
||||||
|
CODE_ALWAYS = PRED_MASK
|
||||||
|
|
||||||
|
# Codes above CODE_ALWAYS indicate an ISA predicate to be tested.
|
||||||
|
# `x & PRED_MASK` is the ISA predicate number to test.
|
||||||
|
# `(x >> PRED_BITS)*3` is the number of u16 table entries to skip if the ISA
|
||||||
|
# predicate is false. (The factor of three corresponds to the (inst-pred,
|
||||||
|
# recipe, encbits) triples.
|
||||||
|
#
|
||||||
|
# Finally, CODE_FAIL indicates the end of the list.
|
||||||
|
CODE_FAIL = (1 << CODE_BITS) - 1
|
||||||
|
|
||||||
|
|
||||||
|
def seq_doc(enc):
|
||||||
|
"""
|
||||||
|
Return a tuple containing u16 representations of the instruction predicate
|
||||||
|
an recipe / encbits.
|
||||||
|
|
||||||
|
Also return a doc string.
|
||||||
|
"""
|
||||||
|
if enc.instp:
|
||||||
|
p = enc.instp.number
|
||||||
|
doc = '--> {} when {}'.format(enc, enc.instp)
|
||||||
|
else:
|
||||||
|
p = CODE_ALWAYS
|
||||||
|
doc = '--> {}'.format(enc)
|
||||||
|
assert p <= CODE_ALWAYS
|
||||||
|
return ((p, enc.recipe.number, enc.encbits), doc)
|
||||||
|
|
||||||
|
|
||||||
class EncList(object):
|
class EncList(object):
|
||||||
"""
|
"""
|
||||||
List of instructions for encoding a given type + opcode pair.
|
List of instructions for encoding a given type + opcode pair.
|
||||||
@@ -121,10 +159,38 @@ class EncList(object):
|
|||||||
self.encodings = []
|
self.encodings = []
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
|
name = self.inst.name
|
||||||
if self.ty:
|
if self.ty:
|
||||||
return '{}.{}'.format(self.inst.name, self.ty.name)
|
name = '{}.{}'.format(name, self.ty.name)
|
||||||
else:
|
if self.encodings:
|
||||||
return self.inst.name
|
name += ' ({})'.format(self.encodings[0].cpumode)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def encode(self, seq_table, doc_table):
|
||||||
|
"""
|
||||||
|
Encode this list as a sequence of u16 numbers.
|
||||||
|
|
||||||
|
Adds the sequence to `seq_table` and records the returned offset as
|
||||||
|
`self.offset`.
|
||||||
|
|
||||||
|
Adds comment lines to `doc_table` keyed by seq_table offsets.
|
||||||
|
"""
|
||||||
|
words = list()
|
||||||
|
docs = list()
|
||||||
|
|
||||||
|
for idx, enc in enumerate(self.encodings):
|
||||||
|
seq, doc = seq_doc(enc)
|
||||||
|
docs.append((len(words), doc))
|
||||||
|
words.extend(seq)
|
||||||
|
words.append(CODE_FAIL)
|
||||||
|
|
||||||
|
self.offset = seq_table.add(words)
|
||||||
|
|
||||||
|
# Add doc comments.
|
||||||
|
doc_table[self.offset].append(
|
||||||
|
'{:06x}: {}'.format(self.offset, self.name()))
|
||||||
|
for pos, doc in docs:
|
||||||
|
doc_table[self.offset + pos].append(doc)
|
||||||
|
|
||||||
|
|
||||||
class Level2Table(object):
|
class Level2Table(object):
|
||||||
@@ -181,18 +247,46 @@ def make_tables(cpumode):
|
|||||||
return table
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
def encode_enclists(level1, seq_table, doc_table):
|
||||||
|
"""
|
||||||
|
Compute encodings and doc comments for encoding lists in `level1`.
|
||||||
|
"""
|
||||||
|
for level2 in level1:
|
||||||
|
for enclist in level2:
|
||||||
|
enclist.encode(seq_table, doc_table)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_enclists(seq_table, doc_table, fmt):
|
||||||
|
with fmt.indented(
|
||||||
|
'const ENCLISTS: [u16; {}] = ['.format(len(seq_table.table)),
|
||||||
|
'];'):
|
||||||
|
line = ''
|
||||||
|
for idx, entry in enumerate(seq_table.table):
|
||||||
|
if idx in doc_table:
|
||||||
|
if line:
|
||||||
|
fmt.line(line)
|
||||||
|
line = ''
|
||||||
|
for doc in doc_table[idx]:
|
||||||
|
fmt.comment(doc)
|
||||||
|
line += '{:#06x}, '.format(entry)
|
||||||
|
if line:
|
||||||
|
fmt.line(line)
|
||||||
|
|
||||||
|
|
||||||
def gen_isa(isa, fmt):
|
def gen_isa(isa, fmt):
|
||||||
# First assign numbers to relevant instruction predicates and generate the
|
# First assign numbers to relevant instruction predicates and generate the
|
||||||
# check_instp() function..
|
# check_instp() function..
|
||||||
emit_instps(isa.all_instps, fmt)
|
emit_instps(isa.all_instps, fmt)
|
||||||
|
|
||||||
|
# Tables for enclists with comments.
|
||||||
|
seq_table = UniqueSeqTable()
|
||||||
|
doc_table = defaultdict(list)
|
||||||
|
|
||||||
for cpumode in isa.cpumodes:
|
for cpumode in isa.cpumodes:
|
||||||
level1 = make_tables(cpumode)
|
level1 = make_tables(cpumode)
|
||||||
for level2 in level1:
|
encode_enclists(level1, seq_table, doc_table)
|
||||||
for enclist in level2:
|
|
||||||
fmt.comment(enclist.name())
|
emit_enclists(seq_table, doc_table, fmt)
|
||||||
for enc in enclist.encodings:
|
|
||||||
fmt.comment('{} when {}'.format(enc, enc.instp))
|
|
||||||
|
|
||||||
|
|
||||||
def generate(isas, out_dir):
|
def generate(isas, out_dir):
|
||||||
|
|||||||
Reference in New Issue
Block a user