[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