home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 10
/
Fresh_Fish_10_2352.bin
/
new
/
dev
/
obero
/
oberon
/
projectoberonsrc
/
obc.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1994-10-17
|
19KB
|
547 lines
Syntax10.Scn.Fnt
MODULE OBC; (*NW 30.5.87 / 28.3.93*)
IMPORT Files, OBS, OBT;
CONST ObjMark = 0F5X; CodeLength = 20000; LinkLength = 250;
ConstLength = 3500; EntryLength = 96; MaxImps = 32;
MaxPtrs = 64; MaxRecs = 32; MaxComs = 40; MaxExts = 7;
(*instruction prefixes*)
F6 = 4EH; F7 = 0CEH; F9 = 3EH; F11 = 0BEH;
(*object and item modes*)
Var = 1; VarX = 2; Ind = 3; IndX = 4; RegI = 5;
RegX = 6; Abs = 7; Con = 8; Stk = 9; Stk0 = 10; Coc = 11; Reg = 12;
Fld = 13; Typ = 14; LProc = 15; SProc = 16; CProc = 17; IProc = 18; Mod = 19; Head = 20;
(*structure forms*)
Undef = 0; Byte = 1; Bool = 2; Char = 3; SInt = 4; Int = 5; LInt = 6;
Real = 7; LReal = 8; Set = 9; String = 10; NilTyp = 11; NoTyp = 12;
Pointer = 13; ProcTyp = 14; Array = 15; DynArr = 16; Record = 17;
TYPE Argument =
RECORD form, gen, inx: INTEGER;
d1, d2: LONGINT
END ;
VAR pc*, Pc*, level*: INTEGER;
wasderef*: OBT.Object;
typchk*: BOOLEAN;
RegSet, FRegSet: SET;
StrOffset: LONGINT;
conx, nofrecs: INTEGER;
fixlist0: ARRAY MaxImps OF INTEGER; (*abs adr*)
fixlist1: ARRAY MaxImps OF INTEGER; (*PC-rel adr*)
RecTab: ARRAY MaxRecs OF OBT.Struct;
constant: ARRAY ConstLength OF CHAR;
code: ARRAY CodeLength OF CHAR;
PROCEDURE SetStrOffset*(varsize: LONGINT);
BEGIN StrOffset := -ConstLength - varsize
END SetStrOffset;
PROCEDURE GetReg*(VAR x: OBT.Item);
VAR i: INTEGER;
BEGIN i := 7; x.mode := Reg;
LOOP IF ~(i IN RegSet) THEN x.a0 := i; INCL(RegSet,i); EXIT END ;
IF i = 0 THEN x.a0 := 0; OBS.Mark(215); EXIT ELSE DEC(i) END ;
END
END GetReg;
PROCEDURE GetFReg*(VAR x: OBT.Item);
VAR i: INTEGER;
BEGIN i := 6; x.mode := Reg;
LOOP IF ~(i IN FRegSet) THEN x.a0 := i; INCL(FRegSet,i); EXIT END ;
IF i = 0 THEN x.a0 := 0; OBS.Mark(216); EXIT ELSE i := i-2 END
END
END GetFReg;
PROCEDURE UsedRegisters*(): SET;
BEGIN RETURN RegSet
END UsedRegisters;
PROCEDURE FreeRegs*(r: SET);
BEGIN RegSet := r; FRegSet := {}
END FreeRegs;
PROCEDURE Release*(VAR x: OBT.Item);
BEGIN
IF x.mode = Reg THEN
IF x.typ.form IN {Real, LReal} THEN EXCL(FRegSet, x.a0) ELSE EXCL(RegSet, x.a0) END
ELSIF x.mode = RegI THEN EXCL(RegSet, x.a0)
ELSIF x.mode = RegX THEN EXCL(RegSet, x.a0); EXCL(RegSet, x.a2)
ELSIF x.mode IN {VarX, IndX} THEN EXCL(RegSet, x.a2)
END
END Release;
PROCEDURE CheckCodeSize*;
BEGIN
IF pc > CodeLength - 256 THEN OBS.Mark(210); pc := 4 END
END CheckCodeSize;
PROCEDURE AllocString*(VAR s: ARRAY OF CHAR; VAR x: OBT.Item);
VAR i: INTEGER; ch: CHAR;
BEGIN (*fill constant table backward*) i := 0;
REPEAT ch := s[i]; INC(i) UNTIL ch = 0X;
x.a1 := i;
IF i <= conx THEN
REPEAT DEC(i); DEC(conx); constant[conx] := s[i] UNTIL i = 0
ELSE OBS.Mark(230)
END ;
x.a0 := conx
END AllocString;
PROCEDURE PutByte*(x: LONGINT);
BEGIN code[pc] := CHR(x); INC(pc)
END PutByte;
PROCEDURE PutWord*(x: LONGINT); (*high byte first*)
BEGIN code[pc] := CHR(x DIV 100H); INC(pc); code[pc] := CHR(x); INC(pc)
END PutWord;
PROCEDURE PutDbl*(x: LONGINT);
VAR i: INTEGER;
BEGIN i := -32;
REPEAT INC(i, 8); code[pc] := CHR(ASH(x, i)); INC(pc) UNTIL i = 0
END PutDbl;
PROCEDURE PutF3*(op: INTEGER);
BEGIN code[pc] := CHR(op); INC(pc); code[pc] := CHR(op DIV 100H); INC(pc)
END PutF3;
PROCEDURE PutExtAdr*(mno: INTEGER; pno: LONGINT);
BEGIN PutWord(pno - 4000H); PutF3(fixlist1[mno]); fixlist1[mno] := pc - 4
END PutExtAdr;
PROCEDURE PutDisp*(x: LONGINT);
BEGIN
IF x < 0 THEN
IF x >= -40H THEN code[pc] := CHR(x+80H); INC(pc)
ELSIF x >= -2000H THEN PutWord(x+0C000H)
ELSE PutDbl(x)
END
ELSIF x < 40H THEN code[pc] := CHR(x); INC(pc)
ELSIF x < 2000H THEN PutWord(x+8000H)
ELSE PutDbl(x - 40000000H)
END
END PutDisp;
PROCEDURE PutArg(VAR z: Argument);
BEGIN
CASE z.form OF
0: IF z.inx = 1 THEN code[pc] := CHR(z.d1); INC(pc)
ELSIF z.inx = 2 THEN PutWord(z.d1)
ELSIF z.inx = 4 THEN PutDbl(z.d1)
ELSIF z.inx = 8 THEN PutDbl(z.d2); PutDbl(z.d1)
END
| 1:
| 2,6: PutDisp(z.d1)
| 3,7: PutDisp(z.d1); PutDisp(z.d2)
| 4,8: PutDisp(z.d1 - Pc)
| 5,9: PutWord(z.d1 - 4000H); PutF3(fixlist0[z.d2]); fixlist0[z.d2] := pc - 4
END
END PutArg;
PROCEDURE Operand(VAR x: OBT.Item; VAR z: Argument);
PROCEDURE downlevel(VAR gen: INTEGER);
VAR n, op: INTEGER; b: OBT.Item;
BEGIN GetReg(b); n := level - x.lev; gen := SHORT(b.a0) + 8;
op := SHORT(b.a0)*40H - 3FE9H;
IF n = 1 THEN PutF3(op); PutDisp(8); (*MOVD 8(FP) Rb*)
ELSE PutF3(op - 4000H); PutDisp(8); PutDisp(8); (*MOVD 8(8(FP)) Rb*)
WHILE n > 2 DO DEC(n);
PutF3((SHORT(b.a0)*20H + SHORT(b.a0))*40H + 4017H); PutDisp(8)
END
END ;
END downlevel;
PROCEDURE index;
VAR s: LONGINT;
BEGIN s := x.typ.size;
IF s = 1 THEN z.gen := 1CH
ELSIF s = 2 THEN z.gen := 1DH
ELSIF s = 4 THEN z.gen := 1EH
ELSIF s = 8 THEN z.gen := 1FH
ELSE z.gen := 1CH; PutByte(F7); PutByte(x.a2 MOD 4 * 40H + 23H); (*MULD s, r*)
PutByte(x.a2 DIV 4 + 0A0H); PutWord(0); PutWord(s)
END
END index;
BEGIN
CASE x.mode OF
Var: IF x.lev = 0 THEN
z.gen := 1BH; z.d1 := x.a0; z.form := 4
ELSIF x.lev < 0 THEN
z.gen := 15H; z.d1 := x.a0; z.d2 := -x.lev; z.form := 5
ELSIF x.lev = level THEN
z.gen := 18H; z.d1 := x.a0; z.form := 2
ELSIF x.lev+1 = level THEN
z.gen := 10H; z.d1 := 8; z.d2 := x.a0; z.form := 3
ELSE downlevel(z.gen); z.d1 := x.a0; z.form := 2
END
| Ind: IF x.lev <= 0 THEN OBS.Mark(240)
ELSIF x.lev = level THEN
z.gen := 10H; z.d1 := x.a0; z.d2 := x.a1; z.form := 3
ELSE downlevel(z.gen);
PutF3((z.gen*20H + z.gen-8)*40H + 17H); PutDisp(x.a0);
z.d1 := x.a1; z.form := 2
END
| RegI: z.gen := SHORT(x.a0)+8; z.d1 := x.a1; z.form := 2
| VarX: index;
IF x.lev = 0 THEN
z.inx := 1BH; z.d1 := x.a0; z.form := 8
ELSIF x.lev < 0 THEN
z.inx := 15H; z.d1 := x.a0; z.d2 := -x.lev; z.form := 9
ELSIF x.lev = level THEN
z.inx := 18H; z.d1 := x.a0; z.form := 6
ELSIF x.lev+1 = level THEN
z.inx := 10H; z.d1 := 8; z.d2 := x.a0; z.form := 7
ELSE downlevel(z.inx); z.d1 := x.a0; z.form := 6
END ;
z.inx := z.inx*8 + SHORT(x.a2)
| IndX: index;
IF x.lev <= 0 THEN OBS.Mark(240)
ELSIF x.lev = level THEN
z.inx := 10H; z.d1 := x.a0; z.d2 := x.a1; z.form := 7
ELSE downlevel(z.inx);
PutF3((z.inx*20H + z.inx-8)*40H + 17H); PutDisp(x.a0);
z.d1 := x.a1; z.form := 6
END ;
z.inx := z.inx * 8 + SHORT(x.a2)
| RegX: index; z.inx := SHORT((x.a0+8)*8 + x.a2); z.d1 := x.a1; z.form := 6
| Con: z.form := 0;
CASE x.typ.form OF
Undef, Byte, Bool, Char, SInt:
z.gen := 14H; z.inx := 1; z.d1 := x.a0
| Int:
z.gen := 14H; z.inx := 2; z.d1 := x.a0
| LInt, Real, Set, Pointer, ProcTyp, NilTyp:
z.gen := 14H; z.inx := 4; z.d1 := x.a0
| LReal:
z.gen := 14H; z.inx := 8; z.d1 := x.a0; z.d2 := x.a1
| String:
z.form := 4; z.gen := 1BH; z.d1 := x.a0 + StrOffset
END
| Reg: z.gen := SHORT(x.a0); z.form := 1
| Stk: z.gen := 17H; z.form := 1
| Stk0: z.gen := 19H; z.form := 2; z.d1 := 0
| Abs: z.gen := 15H; z.form := 2; z.d1 := x.a0
| Coc, Fld .. Head: OBS.Mark(126); x.mode := Var; z.form := 0
END
END Operand;
PROCEDURE PutF0*(cond: LONGINT);
BEGIN code[pc] := CHR(cond*10H + 10); INC(pc)
END PutF0;
PROCEDURE PutF1*(op: INTEGER);
BEGIN code[pc] := CHR(op); INC(pc)
END PutF1;
PROCEDURE PutF2*(op: INTEGER; short: LONGINT; VAR x: OBT.Item);
VAR dst: Argument;
BEGIN Operand(x, dst); Pc := pc;
code[pc] := CHR(SHORT(short) MOD 2 * 80H + op); INC(pc);
code[pc] := CHR(dst.gen*8 + SHORT(short) MOD 10H DIV 2);
INC(pc);
IF dst.form >= 6 THEN code[pc] := CHR(dst.inx); INC(pc) END ;
PutArg(dst)
END PutF2;
PROCEDURE PutF4*(op: INTEGER; VAR x, y: OBT.Item);
VAR dst, src: Argument;
BEGIN Operand(x, dst); Operand(y, src); Pc := pc;
code[pc] := CHR(dst.gen MOD 4 * 40H + op); INC(pc);
code[pc] := CHR(src.gen*8 + dst.gen DIV