[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 ;


    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)



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 Put1a;

More information about the Oberon mailing list