[Oberon] Static variable overflow (bug?)
Andreas Pirklbauer
andreas_pirklbauer at yahoo.com
Sun Mar 1 11:54:45 CET 2020
As a side comment: To make the fix also work for *imported* variables, one can replace the fixup code for LDR/STR/ADD at the end of procedure Modules.Load with something along the lines of
(*fixup of LDR/STR/ADD*)
adr := mod.code + fixorgD*4;
WHILE adr # mod.code DO
...
IF mno = 0 THEN (*global*)
...
ELSE (*import*)
SYSTEM.GET(mod.imp + (mno-1)*4, impmod);
SYSTEM.GET(adr+4, inst); vno := inst MOD C8;
SYSTEM.GET(impmod.ent + vno*4, offset);
IF ODD(inst DIV C8) THEN INC(offset, impmod.code) ELSE INC(offset, impmod.data) END ;
vno := inst DIV C24 MOD C4; (*RH*)
SYSTEM.PUT(adr, MOV+U + vno*C24 + offset DIV C16);
IF inst DIV C30 = F2 THEN inst := (inst DIV C24) * C24 ELSE inst := IOR + vno*C24 END ;
SYSTEM.PUT(adr+4, inst + vno*C20 + offset MOD C16)
END ;
adr := adr - disp*4
END ;
where:
CONST U = 20000000H; (*modifier bit*)
MOV = 40000000H; IOR = 40060000H; (*F1 register instructions*)
F2 = -2; (*F2 memory instruction*)
BL = 0F7000000H; (*F3 branch instruction*)
C4 = 10H; C8 = 100H; C16 = 10000H; C20 = 100000H; C24 = 1000000H; C30 = 40000000H;
This modified fixup code in Modules.Load generates..
a. For determining the absolute address of an imported global variable:
MOV1+U RH, (staticbase + offset) DIV C16 ; upper 16 bits of RH := (static base + offset) DIV C16
IOR RH, RH, (staticbase + offset) MOD C16 ; lower 16 bits of RH := (static base + offset) MOD C16
b. For loading the value of an imported global variable into a register:
MOV1+U RH, (staticbase + offset) DIV C16 ; upper 16 bits of RH := (static base + offset) DIV C16
LD RH, RH, (staticbase + offset) MOD C16 ; RH := RH + (static base + offset) MOD C16
i.e. always two register instructions with no access to memory at all for imported global variables
(for *non-imported* global variables, the module table pointed to by MT is still accessed though - this too
could be transformed into a MOV1+U and IOR instruction, but that would require modifying the compiler)
-ap
——————————
Below is a slightly more elaborate variant that fixes the current bug in ORG.Put1a
and makes MyViewers.Mod (see below) work on a Project Oberon 2013 system:
PROCEDURE Put1a(op, a, b, im: LONGINT);
VAR r: INTEGER;
BEGIN (*same as Put1, but with range test -10000H <= im < 10000H*)
IF (im >= -10000H) & (im <= 0FFFFH) THEN Put1(op, a, b, im)
ELSIF op = Mov THEN
Put1(Mov+U, a, 0, im DIV 10000H);
IF im MOD 10000H # 0 THEN Put1(Ior, a, a, im MOD 10000H) END
ELSE r := RH;
IF b = RH THEN incR END ;
Put1(Mov+U, RH, 0, im DIV 10000H);
IF im MOD 10000H # 0 THEN Put1(Ior, RH, RH, im MOD 10000H) END ;
Put0(op, a, b, RH);
IF RH > r THEN DEC(RH) END
END
END Put1a;
More information about the Oberon
mailing list