decodetree: Move documentation to docs/devel/decodetree.rst

One great big block comment isn't the best way to document
the syntax of a language.

Reviewed-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2019-02-23 13:00:10 -08:00
parent 55fd189205
commit 3fdbf5d679
4 changed files with 159 additions and 134 deletions

View File

@ -118,6 +118,7 @@ F: exec.c
F: accel/tcg/
F: accel/stubs/tcg-stub.c
F: scripts/decodetree.py
F: docs/devel/decodetree.rst
F: include/exec/cpu*.h
F: include/exec/exec-all.h
F: include/exec/helper*.h

156
docs/devel/decodetree.rst Normal file
View File

@ -0,0 +1,156 @@
========================
Decodetree Specification
========================
A *decodetree* is built from instruction *patterns*. A pattern may
represent a single architectural instruction or a group of same, depending
on what is convenient for further processing.
Each pattern has both *fixedbits* and *fixedmask*, the combination of which
describes the condition under which the pattern is matched::
(insn & fixedmask) == fixedbits
Each pattern may have *fields*, which are extracted from the insn and
passed along to the translator. Examples of such are registers,
immediates, and sub-opcodes.
In support of patterns, one may declare *fields*, *argument sets*, and
*formats*, each of which may be re-used to simplify further definitions.
Fields
======
Syntax::
field_def := '%' identifier ( unnamed_field )+ ( !function=identifier )?
unnamed_field := number ':' ( 's' ) number
For *unnamed_field*, the first number is the least-significant bit position
of the field and the second number is the length of the field. If the 's' is
present, the field is considered signed. If multiple ``unnamed_fields`` are
present, they are concatenated. In this way one can define disjoint fields.
If ``!function`` is specified, the concatenated result is passed through the
named function, taking and returning an integral value.
FIXME: the fields of the structure into which this result will be stored
is restricted to ``int``. Which means that we cannot expand 64-bit items.
Field examples:
+---------------------------+---------------------------------------------+
| Input | Generated code |
+===========================+=============================================+
| %disp 0:s16 | sextract(i, 0, 16) |
+---------------------------+---------------------------------------------+
| %imm9 16:6 10:3 | extract(i, 16, 6) << 3 | extract(i, 10, 3) |
+---------------------------+---------------------------------------------+
| %disp12 0:s1 1:1 2:10 | sextract(i, 0, 1) << 11 | |
| | extract(i, 1, 1) << 10 | |
| | extract(i, 2, 10) |
+---------------------------+---------------------------------------------+
| %shimm8 5:s8 13:1 | expand_shimm8(sextract(i, 5, 8) << 1 | |
| !function=expand_shimm8 | extract(i, 13, 1)) |
+---------------------------+---------------------------------------------+
Argument Sets
=============
Syntax::
args_def := '&' identifier ( args_elt )+ ( !extern )?
args_elt := identifier
Each *args_elt* defines an argument within the argument set.
Each argument set will be rendered as a C structure "arg_$name"
with each of the fields being one of the member arguments.
If ``!extern`` is specified, the backing structure is assumed
to have been already declared, typically via a second decoder.
Argument set examples::
&reg3 ra rb rc
&loadstore reg base offset
Formats
=======
Syntax::
fmt_def := '@' identifier ( fmt_elt )+
fmt_elt := fixedbit_elt | field_elt | field_ref | args_ref
fixedbit_elt := [01.-]+
field_elt := identifier ':' 's'? number
field_ref := '%' identifier | identifier '=' '%' identifier
args_ref := '&' identifier
Defining a format is a handy way to avoid replicating groups of fields
across many instruction patterns.
A *fixedbit_elt* describes a contiguous sequence of bits that must
be 1, 0, or don't care. The difference between '.' and '-'
is that '.' means that the bit will be covered with a field or a
final 0 or 1 from the pattern, and '-' means that the bit is really
ignored by the cpu and will not be specified.
A *field_elt* describes a simple field only given a width; the position of
the field is implied by its position with respect to other *fixedbit_elt*
and *field_elt*.
If any *fixedbit_elt* or *field_elt* appear, then all bits must be defined.
Padding with a *fixedbit_elt* of all '.' is an easy way to accomplish that.
A *field_ref* incorporates a field by reference. This is the only way to
add a complex field to a format. A field may be renamed in the process
via assignment to another identifier. This is intended to allow the
same argument set be used with disjoint named fields.
A single *args_ref* may specify an argument set to use for the format.
The set of fields in the format must be a subset of the arguments in
the argument set. If an argument set is not specified, one will be
inferred from the set of fields.
It is recommended, but not required, that all *field_ref* and *args_ref*
appear at the end of the line, not interleaving with *fixedbit_elf* or
*field_elt*.
Format examples::
@opr ...... ra:5 rb:5 ... 0 ....... rc:5
@opi ...... ra:5 lit:8 1 ....... rc:5
Patterns
========
Syntax::
pat_def := identifier ( pat_elt )+
pat_elt := fixedbit_elt | field_elt | field_ref | args_ref | fmt_ref | const_elt
fmt_ref := '@' identifier
const_elt := identifier '=' number
The *fixedbit_elt* and *field_elt* specifiers are unchanged from formats.
A pattern that does not specify a named format will have one inferred
from a referenced argument set (if present) and the set of fields.
A *const_elt* allows a argument to be set to a constant value. This may
come in handy when fields overlap between patterns and one has to
include the values in the *fixedbit_elt* instead.
The decoder will call a translator function for each pattern matched.
Pattern examples::
addl_r 010000 ..... ..... .... 0000000 ..... @opr
addl_i 010000 ..... ..... .... 0000000 ..... @opi
which will, in part, invoke::
trans_addl_r(ctx, &arg_opr, insn)
and::
trans_addl_i(ctx, &arg_opi, insn)

View File

@ -19,4 +19,4 @@ Contents:
migration
stable-process
testing
decodetree

View File

@ -17,139 +17,7 @@
#
# Generate a decoding tree from a specification file.
#
# The tree is built from instruction "patterns". A pattern may represent
# a single architectural instruction or a group of same, depending on what
# is convenient for further processing.
#
# Each pattern has "fixedbits" & "fixedmask", the combination of which
# describes the condition under which the pattern is matched:
#
# (insn & fixedmask) == fixedbits
#
# Each pattern may have "fields", which are extracted from the insn and
# passed along to the translator. Examples of such are registers,
# immediates, and sub-opcodes.
#
# In support of patterns, one may declare fields, argument sets, and
# formats, each of which may be re-used to simplify further definitions.
#
# *** Field syntax:
#
# field_def := '%' identifier ( unnamed_field )+ ( !function=identifier )?
# unnamed_field := number ':' ( 's' ) number
#
# For unnamed_field, the first number is the least-significant bit position of
# the field and the second number is the length of the field. If the 's' is
# present, the field is considered signed. If multiple unnamed_fields are
# present, they are concatenated. In this way one can define disjoint fields.
#
# If !function is specified, the concatenated result is passed through the
# named function, taking and returning an integral value.
#
# FIXME: the fields of the structure into which this result will be stored
# is restricted to "int". Which means that we cannot expand 64-bit items.
#
# Field examples:
#
# %disp 0:s16 -- sextract(i, 0, 16)
# %imm9 16:6 10:3 -- extract(i, 16, 6) << 3 | extract(i, 10, 3)
# %disp12 0:s1 1:1 2:10 -- sextract(i, 0, 1) << 11
# | extract(i, 1, 1) << 10
# | extract(i, 2, 10)
# %shimm8 5:s8 13:1 !function=expand_shimm8
# -- expand_shimm8(sextract(i, 5, 8) << 1
# | extract(i, 13, 1))
#
# *** Argument set syntax:
#
# args_def := '&' identifier ( args_elt )+ ( !extern )?
# args_elt := identifier
#
# Each args_elt defines an argument within the argument set.
# Each argument set will be rendered as a C structure "arg_$name"
# with each of the fields being one of the member arguments.
#
# If !extern is specified, the backing structure is assumed to
# have been already declared, typically via a second decoder.
#
# Argument set examples:
#
# &reg3 ra rb rc
# &loadstore reg base offset
#
# *** Format syntax:
#
# fmt_def := '@' identifier ( fmt_elt )+
# fmt_elt := fixedbit_elt | field_elt | field_ref | args_ref
# fixedbit_elt := [01.-]+
# field_elt := identifier ':' 's'? number
# field_ref := '%' identifier | identifier '=' '%' identifier
# args_ref := '&' identifier
#
# Defining a format is a handy way to avoid replicating groups of fields
# across many instruction patterns.
#
# A fixedbit_elt describes a contiguous sequence of bits that must
# be 1, 0, [.-] for don't care. The difference between '.' and '-'
# is that '.' means that the bit will be covered with a field or a
# final [01] from the pattern, and '-' means that the bit is really
# ignored by the cpu and will not be specified.
#
# A field_elt describes a simple field only given a width; the position of
# the field is implied by its position with respect to other fixedbit_elt
# and field_elt.
#
# If any fixedbit_elt or field_elt appear then all bits must be defined.
# Padding with a fixedbit_elt of all '.' is an easy way to accomplish that.
#
# A field_ref incorporates a field by reference. This is the only way to
# add a complex field to a format. A field may be renamed in the process
# via assignment to another identifier. This is intended to allow the
# same argument set be used with disjoint named fields.
#
# A single args_ref may specify an argument set to use for the format.
# The set of fields in the format must be a subset of the arguments in
# the argument set. If an argument set is not specified, one will be
# inferred from the set of fields.
#
# It is recommended, but not required, that all field_ref and args_ref
# appear at the end of the line, not interleaving with fixedbit_elf or
# field_elt.
#
# Format examples:
#
# @opr ...... ra:5 rb:5 ... 0 ....... rc:5
# @opi ...... ra:5 lit:8 1 ....... rc:5
#
# *** Pattern syntax:
#
# pat_def := identifier ( pat_elt )+
# pat_elt := fixedbit_elt | field_elt | field_ref
# | args_ref | fmt_ref | const_elt
# fmt_ref := '@' identifier
# const_elt := identifier '=' number
#
# The fixedbit_elt and field_elt specifiers are unchanged from formats.
# A pattern that does not specify a named format will have one inferred
# from a referenced argument set (if present) and the set of fields.
#
# A const_elt allows a argument to be set to a constant value. This may
# come in handy when fields overlap between patterns and one has to
# include the values in the fixedbit_elt instead.
#
# The decoder will call a translator function for each pattern matched.
#
# Pattern examples:
#
# addl_r 010000 ..... ..... .... 0000000 ..... @opr
# addl_i 010000 ..... ..... .... 0000000 ..... @opi
#
# which will, in part, invoke
#
# trans_addl_r(ctx, &arg_opr, insn)
# and
# trans_addl_i(ctx, &arg_opi, insn)
# See the syntax and semantics in docs/devel/decodetree.rst.
#
import os