isaspec: Add support for "absolute" branches

afuc has branches which use an absolute offset in instructions from the
microcode base. Add another type to support them.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23949>
This commit is contained in:
Connor Abbott
2023-06-21 18:47:08 +02:00
committed by Marge Bot
parent 86b17d96b3
commit 569d3ac5a1
4 changed files with 42 additions and 3 deletions

View File

@@ -244,6 +244,38 @@ In the case of ``<override>`` elements, the override applies if the expression
evaluates to non-zero. In the case of ``<derived>`` fields, the expression
evaluates to the value of the derived field.
Branching
---------
isaspec supports a few special field types for printing branch destinations. If
``isaspec_decode_options::branch_labels`` is true, a pre-pass over the program
to be disassembled determines which instructions are branch destinations and
then they are printed when disassembling, in addition to printing the name of
the destination when printing the field itself.
There are two different types, which affect how the destination is computed. If
the field type is ``branch``, then the field is interpreted as a signed offset
from the current instruction. If the type is ``absbranch``, then it is
interpreted as an offset from the first instruction to be disassembled. In
either case, the offset is multiplied by the instruction size.
For example, here is what a signed-offset unconditional jump instruction might
look like:
.. code-block:: xml
<bitset name="jump" extends="#instruction">
<display>
jump #{OFFSET}
</display>
<pattern low="26" high="31">110010</pattern> <!-- opcode goes here -->
<field name="OFFSET" low="0" high="25" type="branch"/>
</bitset>
This would produce a disassembly like ``jump #l42`` if the destination is 42
instructions after the start of the disassembly. The destination would be
preceded by a line with just ``l42:``.
Encoding
--------

View File

@@ -492,7 +492,7 @@ class ISA(object):
# Validate that all bitset fields have valid types, and in
# the case of bitset type, the sizes match:
builtin_types = ['branch', 'int', 'uint', 'hex', 'offset', 'uoffset', 'float', 'bool', 'enum']
builtin_types = ['branch', 'absbranch', 'int', 'uint', 'hex', 'offset', 'uoffset', 'float', 'bool', 'enum']
for bitset_name, bitset in self.bitsets.items():
if bitset.extends is not None:
assert bitset.extends in self.bitsets, "{} extends invalid type: {}".format(

View File

@@ -79,7 +79,8 @@ struct isa_field {
unsigned high;
enum {
/* Basic types: */
TYPE_BRANCH, /* branch target, like INT but optional labeling*/
TYPE_BRANCH, /* relative branch target, like INT but optional labeling*/
TYPE_ABSBRANCH, /* absolute branch target */
TYPE_INT,
TYPE_UINT,
TYPE_HEX,

View File

@@ -610,8 +610,14 @@ display_field(struct decode_scope *scope, const char *field_name)
switch (field->type) {
/* Basic types: */
case TYPE_BRANCH:
case TYPE_ABSBRANCH:
if (scope->state->options->branch_labels) {
int offset = util_sign_extend(val, width) + scope->state->n;
int offset;
if (field->type == TYPE_BRANCH) {
offset = util_sign_extend(val, width) + scope->state->n;
} else {
offset = val;
}
if (offset < scope->state->num_instr) {
print(scope->state, "l%d", offset);
BITSET_SET(scope->state->branch_targets, offset);