The # is a more conventional prefix for hexadecimal, and when ISA
information is not available, there may be a decimal number in front
which would be confusing.
So prefer [1#10c] for the ISA-less encoding format. Here '1' is decimal
and '#10c' is hexadecimal.
When constructing the Flags object from the Builder, don't consume it,
but take a reference instead.
This makes it possible for the parser to accept multiple 'set' lines and
apply them to different ISA specifications.
Use the new ISA predicate numbering to emit ISA predicate instructions in the
encoding tables.
Properly decode the ISA predicate number in RISC-V and add tests for RV32M iwth
and without 'supports_m' enabled.
Move all the byte-sized settings to the front of the byte-vector, and add a
mechanism for assigning numbers to predicates that have no name as well as
predicates from the parent settings group.
This way, all the boolean predicates that are used by a target ISA appear as a
contiguous bit-vector that is a suffix of the settings byte-vector. This
bit-vector can then be indexed linearly when resolving ISA predicates on
encodings.
Add a numbered_predicate() method to the generated Flags structs that can read
a predicate by number dynamically.
This is just the basic 'imul' the M instruction set also has mulh/mulhu which
yield the high bits of a multiplication, and there are div/rem instructions to
be implemented.
These instructions are gated by the use_m predicate, but ISA predicates are not
completely implemented yet.
Three predicates affect each extension:
- supports_m determines whether the target CPU supports the instruction set.
- enable_m determines if the instructions should be used, assuming they're
available.
- use_m is the predicate used to actually use the instructions.
Define data types for the level 1 and level 2 hash tables. These data types are
generic over the offset integer type so they can be twice as compact for
typically small ISAs.
Use these new types when generating encoding hash tables.
Emit both level 1 and level 2 hash tables.
Define generic functions that perform lookups in the encoding tables.
Implement the TargetIsa::encode() method for RISC-V using these building
blocks.
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.
We need to generate hash tables keyed by types, so the Python scripts need to
know the index used to represent types in Rust code.
To enforce this, add a new gen_types.py script which generates constant
definitions for the ir/types module.
Also generate constants for common SIMD vector sizes.
Amend build script to generate an encodings-<isa>.rs file for each target ISA.
Emit a function that can evaluate instruction predicates.
Describe the 3-level tables used for representing insrruction encoding tables.
Add Python classes representing the tables.
The generated code is incomplete and not used anywhere yet.
When generating Rust code for an instruction predicate, call the corresponding
function in the predicates module, using a qualified name.
We don't have methods corresponding to the predicates.
This collects all of the leaf predicates that go into a compound predicate.
Current leaf predicates are:
- Settings for ISA predicates, and
- FieldPredicates for instruction predicates.
Add new instruction predicates to support the 'I' encoding recipe: IsSignedInt,
IsUnsignedInt used to test that an immediate operand is in the allowed range.
Each InstructionFormat instance gets data members corresponding to its immediate
operands, so the can be referred to as BinaryImm.imm, for example.
This will be used to construct instruction predicates.
Usually an instruction firmat has only a single immediate operand called 'imm',
or 'cond' if it is one of the condigtion codes. Add a 'default_member' field to
ImmediateKind to keep track of this default member name in the InstructionData
struct.
Predcates are boolean functions. There will be ISA predicates and instruction
predicates.
The ISA predicates will be turned into member functions on the generated Flags
structs.
Add an isa::lookup() function which serves as a target registry for creating
Box<TargetIsa> trait objects.
An isa::Builder makes it possible to confugure the trait object before it is
created.
- Move detail data structures into a settings::detail module to avoid polluting
the settings namespace.
- Rename generated data types to 'Flags' in anticipation of computed predicate
flags that can't be set. The Flags struct is immutable.
- Use a settings::Builder struct to manipulate settings, then pass it to
Flags::new().
This trait allows settings to be manipulated as strings, using descriptors and
constant hash-table lookups.
Amend gen_settings.py to generate the necessary constant tables.
Clarify terminology by always referring to a 'Target ISA' instead of just
'Target'. Use 'isa' as a module name instead of 'target' both in Rust and Python
code.
This is only to clarify terminology and not at all because Cargo insists on
using the 'target' sub-directory for build products. Oh, no. Not at all.