diff --git a/docs/drivers/freedreno/isaspec.rst b/docs/drivers/freedreno/isaspec.rst index 19b41ee0373..e512d2f657b 100644 --- a/docs/drivers/freedreno/isaspec.rst +++ b/docs/drivers/freedreno/isaspec.rst @@ -244,6 +244,38 @@ In the case of ```` elements, the override applies if the expression evaluates to non-zero. In the case of ```` 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 + + + + jump #{OFFSET} + + 110010 + + + +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 -------- diff --git a/src/compiler/isaspec/isa.py b/src/compiler/isaspec/isa.py index 894d3c598ab..3e70c342985 100644 --- a/src/compiler/isaspec/isa.py +++ b/src/compiler/isaspec/isa.py @@ -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( diff --git a/src/compiler/isaspec/isaspec_decode_decl.h b/src/compiler/isaspec/isaspec_decode_decl.h index e44517ced46..8ae61a79e4f 100644 --- a/src/compiler/isaspec/isaspec_decode_decl.h +++ b/src/compiler/isaspec/isaspec_decode_decl.h @@ -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, diff --git a/src/compiler/isaspec/isaspec_decode_impl.c b/src/compiler/isaspec/isaspec_decode_impl.c index a7952b1aec6..b5e8d54b8a2 100644 --- a/src/compiler/isaspec/isaspec_decode_impl.c +++ b/src/compiler/isaspec/isaspec_decode_impl.c @@ -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);