[Oberon] Standalone BootLoader format

Andreas Pirklbauer andreas_pirklbauer at yahoo.com
Wed May 13 09:33:56 CEST 2020


Tomas,

   > Why we initialise SB from mem[6] ???

Because you have not generated a standalone program,
but a regular program to be loaded by the module loader.
This program can therefore not run on the bare metal.

You can immediately see that from the generated code below.
There is not BR 7 instruction at location 0, followed by 7 zeros.
So you have compiled Counter without the * option after MODULE,

In this particular example, when you write z := 0, the
compiler correctly generates the instruction sequence

   5 40000000   MOV R0 R0       0
   6 8D000006   LDW SB R0       6   ; 0 = mno, 6 = disp = pc-fixorgD
   7 A0D00008   STW  R0 SB       8  ; Mem[SB+8]

Here, the “6” in the last 20 bits is actually the displacement
in the fixup chain (pc-fixorgD). The loader traverses this chain
and fixes it up LDW SB R0 6  to LD RH, MT, mno*4.
The LDW instruction is at location 6, so if you subtract
6 from that, you get to 0, the end of the fixup chain. It’s all
correct, it just requires an Oberon system to function.

All this is explained in chapter 6.3. on page 81 of

   http://inf.ethz.ch/personal/wirth/ProjectOberon/PO.System.pdf

The relevant portions of code in compiler and loader are

Compiler:  this generates the "LDW SB R0 6" instruction
   
  PROCEDURE GetSB(base: LONGINT);
  BEGIN
    IF (version # 0) & ((base # curSB) OR (base # 0)) THEN
      Put2(Ldr, SB, -base, pc-fixorgD); fixorgD := pc-1; curSB := base
    END
  END GetSB;

Loader:   this fixes it up to "LD RH, MT, mno*4"

   SYSTEM.GET(adr, inst);
   mno := inst DIV 100000H MOD 10H;   (*0 = mno*)
   disp := inst MOD 1000H;                      (*6 = disp*)
   IF mno = 0 THEN (*global*)
       SYSTEM.PUT(adr, (inst DIV 1000000H * 10H + MT) * 100000H + mod.num * 4)    (*LD RH, MT, mno*4*)

HTH,
-ap

--------------------------------------------------------------------
MODULE* Counter;
  VAR x, y, z: INTEGER;
BEGIN LED(1); z := 0;
  REPEAT LED(z); x := 1000;
     REPEAT y := 1000;
       REPEAT y := y-1 UNTIL y = 0;
       x := x-1
     UNTIL x = 0;
     z := z+1
   UNTIL FALSE
END Counter.

(* BRAM Loader sets
   MTOrg = 20H; MemLim = 0E7EF0H; stackOrg = 80000H;
   SYSTEM.LDREG(SP, stackOrg); *)

(* Stack SP := SP-4, save LINK reg *)
   0 4EE90004   SUB SP SP       4
   1 AFE00000   STW  LNK SP       0
(* LED(1), mem[-60] := 1*)
   2 40000001   MOV R0 R0       1
   3 5100FFC4   MOV R1 R0     -60
   4 A0100000   STW  R0 R1       0
(* z := 0, mem[SB+8] := R0 *)
   5 40000000   MOV R0 R0       0
(* Static base SB := mem[0+6] *)
   6 8D000006   LDW SB R0       6
   7 A0D00008   STW  R0 SB       8
...
(* x := 1000, mem[SB+0] := R0 *)
  11 400003E8   MOV R0 R0    1000
  12 A0D00000   STW  R0 SB       0
(* y := 1000, mem[SB+4] := R0 *)
  13 400003E8   MOV R0 R0    1000
  14 A0D00004   STW  R0 SB       4
...
(* Restore and branch to LINK reg *)
  31 8FE00000   LDW LNK SP       0
  32 4EE80004   ADD SP SP       4
  33 C700000F   B LNK

Why we initialise SB from mem[6] ???
Any limits on globals here???



More information about the Oberon mailing list