[Oberon] Documentation;

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Thu Dec 17 11:59:27 CET 2020

    > The RISC5 CPU described in RISC5 architecture will NEVER see Andreas‘ coding.

I am relieved :)

    > This was cited by Andreas. 
    > | BL (4) | cond (4) | mno (4) | pno (8) | pc-fixorgP (12) |
    > …
    > Andreas could even have decided to use a totally different coding tha
    > has nothing to do with RISC5 at all, eg.
    >  | mno(8) | pno(8) | cond(4) | pc-fixorgP (12) |

which is what I had actually considered and implemented at one point:
i.e. to “amputate away" the first 4 bits of a branch instruction altogether
at compile time, in order to recover even more bits for the remaining fields.

It would work, but then *tools* that inspect or decode the generated
instruction stream in an object file, such as ORTool.DecObj M.rsc,
would no longer have a way to *recognize* a BL instruction as such.
(which, however, could be solved, for example by making DecObj
pass over the code section *twice*, using the information embedded
in the fixup chain itself to locate all branch instructions to be fixed up).

But in this particular example, there is no real need for that. Because
one could simply remove the ‘cond' field altogether (at compile time):

    | BL (4) | mno (6) | pno (8) | pc-fixorgP (14) | 

Why can one do THAT? Simply because in all BL instructions that
are part of a fixup list, the “cond" field is known to be always 7 = 0111, 
meaning “always". Thus, one doesn’t actually need to store in the
object file M.rsc at all. Instead, one can kick it out and simply
reinsert the (constant) cond field value of 7 = 0111 = “always”
at load/link time (i.e. in procedure Modules.Load or ORL.Link).

The important observation - as Jörg has stated - such “instructions”
generated at compile time are not actually “real” RISC5 instruction,
i.e. they never hit the RISC5 processor at execution time.

Instead, they are first embedded in a fixup chain in M.rsc at *compile*
time (hence the need for the last field that holds the displacement
between 2 instructions in the chain) and “fixed up” by the loader
(Modules.Load) to obtain an “executable” RISC5 instruction.

Once the module has been loaded, only “correct” RISC5 exist
in the code section starting at mod.code at run time.

All this is explained in section 6.3. on p.81 of the book Project Oberon
at https://people.inf.ethz.ch/wirth/ProjectOberon/PO.System.pdf

Once one gets this idea, one can play with this and do (almost?)
anything with an “instruction” at compile time *so long as* one
makes sure that the loader can still extract enough information
data from it in order to replace it with a “real” RISC5 instruction.

In most cases, it’s simply about finding the “right” compromise in the
number of bits used to encode the various parts of the “instruction”
generated at compile time (and to be fixed up at module load time).

For example, if one chooses a compile-time encoding like

    | BL (4) | mno (6) | pno (8) | pc-fixorgP (14) | 

one would obtain:

    max mno = 63
    max pno = 255
    max disp = 2^14-1 = 16K-1 words

i.e. this compile-time instruction would not only allow importing
up to 63 (instead of just 15) modules and exporting up to 255
procedures, but would also increase the maximum displacement
between two BL instructions in the fixup chain to 2^14-1 = 16K
words (instead of 2^12 = 8K words). Given that the array
ORG.code holds only 8K words, this would eliminate the need
for an extra check in ORG.Call whether a fixup is actually
possible (i.e. the statement IF pc-fixorgP < 1000H THEN...).

See [1] and [2] for some additional variations of this scheme.

* * *

PS: Modifying ORG.Put3 and Modules.Load to implement different
instruction encodings make for some good student exercises, as
they *greatly* enhance the understanding of the fixup mechanism,
down to the last bit (quite literally!). Just reading code - no matter
how well documented - will not get a student there.

Documentation helps and is essential!. Students should be
trained to be thorough in documenting what they’re doing.

All this is not hard, but requires getting used to it indeed..


[1] http://github.com/andreaspirklbauer/Oberon-allow-importing-any-number-of-modules
[2] https://github.com/andreaspirklbauer/Oberon-fast-access-to-global-module-data

More information about the Oberon mailing list