home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 2
/
goldfish_vol2_cd1.bin
/
files
/
dev
/
obero
/
oberon-a
/
source
/
oc
/
occ.mod
< prev
next >
Wrap
Text File
|
1994-08-08
|
63KB
|
2,200 lines
(***************************************************************************
$RCSfile: OCC.mod $
Description: Code generation
Created by: fjc (Frank Copeland)
$Revision: 4.10 $
$Author: fjc $
$Date: 1994/08/03 11:40:04 $
Copyright © 1990-1993, ETH Zuerich
Copyright © 1993-1994, Frank Copeland
This module forms part of the OC program
See OC.doc for conditions of use and distribution
Log entries are at the end of the file.
***************************************************************************)
MODULE OCC;
(*
** $C= CaseChk $I= IndexChk $L= LongAdr $N= NilChk
** $P- PortableCode $R= RangeChk $S= StackChk $T= TypeChk
** $V= OvflChk $Z= ZeroVars
*)
IMPORT Files, OCG, OCS, OCT, SYS := SYSTEM;
(* --- Exported declarations -------------------------------------------- *)
CONST
(* Condition codes *)
T * = 0; F * = 1; HI * = 2; LS * = 3; CC * = 4; CS * = 5;
NE * = 6; EQ * = 7; VC * = 8; VS * = 9; PL * = 10; MI * = 11;
GE * = 12; LT * = 13; GT * = 14; LE * = 15;
(* Instruction mnemonics *)
Bcc * = 6000H; DBcc * = 50C8H; Scc * = 50C0H;
ADD * = -3000H; ADDI * = 0600H; ADDQ * = 5000H; AND * = -4000H;
ANDI * = 0200H; ASL * = -1F00H; ASR * = -2000H; BCC * = 6400H;
BCLR * = 0080H; BCS * = 6500H; BEQ * = 6700H; BGE * = 6C00H;
BGT * = 6E00H; BHI * = 6200H; BLE * = 6F00H; BLS * = 6300H;
BLT * = 6D00H; BMI * = 6B00H; BNE * = 6600H; BPL * = 6A00H;
BRA * = 6000H; BSET * = 00C0H; BSR * = 6100H; BTST * = 0000H;
BVC * = 6800H; BVS * = 6900H; CHK * = 4180H; CLR * = 4200H;
CMP * = -5000H; CMPI * = 0C00H; DBCC * = 54C8H; DBCS * = 55C8H;
DBEQ * = 57C8H; DBF * = 51C8H; DBGE * = 5CC8H; DBGT * = 5EC8H;
DBHI * = 52C8H; DBLE * = 5FC8H; DBLS * = 53C8H; DBLT * = 5DC8H;
DBMI * = 5BC8H; DBNE * = 56C8H; DBPL * = 5AC8H; DBRA * = 50C8H;
DBT * = 50C8H; DBVC * = 58C8H; DBVS * = 59C8H; DIVS * = -7E40H;
EOR * = -4F00H; EORI * = 0A00H; EXG * = -3EC0H; EXTW * = 4880H;
EXTL * = 48C0H; JMP * = 4EC0H; JSR * = 4E80H; LEA * = 41C0H;
LINK * = 4E50H; LSL * = -1EF8H; LSR * = -1FF8H; MOVEQ* = 7000H;
MULS * = -3E40H; NEG * = 4400H; NOP * = 4E71H; NOT * = 4600H;
iOR * = -8000H; ORI * = 0000H; PEA * = 4840H; ROL * = -1EE8H;
ROR * = -1FE8H; RTE * = 4E73H; RTS * = 4E75H; SCS * = 55C0H;
SEQ * = 57C0H; SF * = 51C0H; SGE * = 5CC0H; SGT * = 5EC0H;
SHI * = 52C0H; SLE * = 5FC0H; SLS * = 53C0H; SLT * = 5DC0H;
SMI * = 5BC0H; SNE * = 56C0H; SPL * = 5AC0H; SRA * = 50C0H;
ST * = 50C0H; SVC * = 58C0H; SVS * = 59C0H; SUB * = -7000H;
SUBI * = 0400H; SUBQ * = 5100H; SWAP * = 4840H; TRAP * = 4E40H;
TRAPV* = 4E76H; TST * = 4A00H; UNLK * = 4E58H;
(* Trap numbers *)
OverflowCheck * = -1;
IndexCheck * = 0;
TypeCheck * = 1;
NilCheck * = 2;
CaseCheck * = 3;
ReturnCheck * = 4;
StackCheck * = 5;
(* CPU Registers *)
D0 = 0; D1 = 1; D2 = 2; D7 = 7; A0 = 8; A1 = 9; A3 = 11; A4 = 12; A5 = 13;
A6 = 14; A7 = 15; BP = A4 - 8; FP = A5 - 8; SP = A7 - 8;
DataRegs = {D0 .. D7};
AdrRegs = {A0 .. A7};
(* Register masks for SaveRegisters () *)
ScratchRegs * = {D0, D1, A0, A1};
AllRegs * = {D0 .. A3};
VAR
pc *, level * : INTEGER;
wasderef * : OCT.Object;
RegSet * : SET;
Debug * : BOOLEAN;
(* --- Local declarations ----------------------------------------------- *)
CONST
MaxBufferSize = 32000;
MaxCodeLength = MaxBufferSize DIV SIZE (INTEGER);
MaxConstLength = MaxBufferSize DIV SIZE (CHAR);
CodeLength = MaxCodeLength;
ConstLength = MaxConstLength;
NumTypes = 64;
(* Object file hunk types *)
hunkUnit = 999; hunkName = 1000; hunkCode = 1001;
hunkData = 1002; hunkBSS = 1003; hunkReloc32 = 1004;
hunkExt = 1007; hunkSymbol = 1008; hunkEnd = 1010;
(* External symbol types *)
extDef = 1; extRef32 = 129; extRef16 = 131; extSymb = 0;
(* Addressing mode flag values *)
DReg = 0; (* Data Register *)
ARDir = 1; (* Address Register Direct *)
ARInd = 2; (* Address Register Indirect *)
ARPost = 3; (* Address Register with Post-Increment *)
ARPre = 4; (* Address Register with Pre-Decrement *)
ARDisp = 5; (* Address Register with Displacement *)
ARDisX = 6; (* Address Register with Disp. & Index *)
Mode7 = 7;
AbsW = 0; (* Absolute Short (16-bit Address) *)
AbsL = 1; (* Absolute Long (32-bit Address) *)
PCDisX = 3; (* Program Counter Relative, with Disp. & Index *)
Imm = 4; (* Immediate *)
PCDisp = 5; (* Program Counter Relative, with Displacement *)
B = 1; W = 2; L = 4; (* Size types *)
(* object modes *)
Var = OCG.Var; VarX = OCG.VarX; VarR = OCG.VarR; Ind = OCG.Ind;
IndX = OCG.IndX; IndR = OCG.IndR; RegI = OCG.RegI; RegX = OCG.RegX;
Lab = OCG.Lab; LabI = OCG.LabI; Abs = OCG.Abs; Con = OCG.Con;
Push = OCG.Push; Pop = OCG.Pop; Coc = OCG.Coc; Reg = OCG.Reg;
Fld = OCG.Fld; Typ = OCG.Typ; LProc = OCG.LProc; XProc = OCG.XProc;
SProc = OCG.SProc; LibCall = OCG.LibCall; FProc = OCG.FProc;
TProc = OCG.TProc; Mod = OCG.Mod; Head = OCG.Head; RList = OCG.RList;
regSet = {VarR, IndR, Reg};
(* structure forms *)
Undef = OCT.Undef; Pointer = OCT.Pointer; Array = OCT.Array;
Record = OCT.Record; ProcTyp = OCT.ProcTyp;
TYPE
CodeHunk = POINTER TO CodeHunkDesc;
Def = POINTER TO DefDesc;
Ref = POINTER TO RefDesc;
Offset = POINTER TO OffsetDesc;
CodeHunkDesc = RECORD
next : CodeHunk;
start,
length : INTEGER;
defs : Def;
refs : Ref;
END; (* CodeHunkDesc *)
DefDesc = RECORD
next : Def;
symbol : OCT.Symbol;
offset : LONGINT;
END; (* DefDesc *)
RefDesc = RECORD
next : Ref;
size : INTEGER;
symbol : OCT.Symbol;
count : LONGINT;
offsets : Offset;
END; (* RefDesc *)
OffsetDesc = RECORD
next : Offset;
n : LONGINT;
END; (* OffsetDesc *)
VAR
FirstCodeHunk, CurrCodeHunk, InitCodeHunk, Prologue : CodeHunk;
codex, conx, typex, dataCount : INTEGER;
numPtrs : LONGINT;
constant : ARRAY ConstLength OF CHAR;
type : ARRAY NumTypes OF OCT.Struct;
code : ARRAY CodeLength OF INTEGER;
TYPE
Arg = RECORD
form : INTEGER;
data : LONGINT;
symbol : OCT.Symbol;
END; (* Arg *)
CONST
(* Arg forms *)
none = 0; word = 1; long = 2; wordRef = 3; longRef = 4;
(* CONST mname = "OCC"; *)
(* --- Procedure declarations ------------------------------------------- *)
(*------------------------------------*)
PROCEDURE Init * ();
(* CONST pname = "Init"; *)
BEGIN (* Init *)
(* OCG.TraceIn (mname, pname); *)
pc := 0; level := 0; RegSet := {}; conx := 0; codex := 0; typex := 0;
(* ;OCG.TraceOut (mname, pname); *)
END Init;
(*------------------------------------*)
PROCEDURE Close * ();
VAR i : INTEGER;
BEGIN (* Close *)
FirstCodeHunk := NIL; CurrCodeHunk := NIL; InitCodeHunk := NIL;
Prologue := NIL;
i := 0; WHILE i < NumTypes DO type [i] := NIL; INC (i) END
END Close;
(*------------------------------------*)
PROCEDURE StartPrologue * ();
(* CONST pname = "StartPrologue"; *)
VAR codeHunk : CodeHunk;
BEGIN (* StartPrologue *)
(* OCG.TraceIn (mname, pname); *)
NEW (codeHunk);
FirstCodeHunk := codeHunk; CurrCodeHunk := codeHunk;
codeHunk.next := NIL; codeHunk.start := codex; codeHunk.length := 0;
codeHunk.defs := NIL; codeHunk.refs := NIL;
Prologue := codeHunk
(* ;OCG.TraceOut (mname, pname); *)
END StartPrologue;
(*------------------------------------*)
PROCEDURE StartCodeHunk * (initProc : BOOLEAN);
(* CONST pname = "StartCodeHunk"; *)
VAR codeHunk : CodeHunk;
BEGIN (* StartCodeHunk *)
(* OCG.TraceIn (mname, pname); *)
NEW (codeHunk);
IF FirstCodeHunk = NIL THEN
FirstCodeHunk := codeHunk; CurrCodeHunk := codeHunk
ELSE
CurrCodeHunk.next := codeHunk; CurrCodeHunk := codeHunk;
END; (* ELSE *)
codeHunk.next := NIL; codeHunk.start := codex; codeHunk.length := 0;
codeHunk.defs := NIL; codeHunk.refs := NIL;
IF initProc THEN InitCodeHunk := codeHunk END;
(* ;OCG.TraceOut (mname, pname); *)
END StartCodeHunk;
(*------------------------------------*)
PROCEDURE DefSymbol (sym : OCT.Symbol);
(* CONST pname = "DefSymbol"; *)
VAR def : Def;
BEGIN (* DefSymbol *)
(* OCG.TraceIn (mname, pname); *)
NEW (def);
def.next := CurrCodeHunk.defs; CurrCodeHunk.defs := def;
def.symbol := sym; def.offset := pc - (CurrCodeHunk.start * 2)
(* ;OCG.TraceOut (mname, pname); *)
END DefSymbol;
(*------------------------------------*)
PROCEDURE StartProcedure * (proc : OCT.Object);
(* CONST pname = "StartProcedure"; *)
BEGIN (* StartProcedure *)
(* OCG.TraceIn (mname, pname); *)
DefSymbol (proc.symbol)
(* ;OCG.TraceOut (mname, pname); *)
END StartProcedure;
(*------------------------------------*)
PROCEDURE EndCodeHunk * ();
(* CONST pname = "EndCodeHunk"; *)
BEGIN (* EndCodeHunk *)
(* OCG.TraceIn (mname, pname); *)
CurrCodeHunk.length := codex - CurrCodeHunk.start;
(* ;OCG.TraceOut (mname, pname); *)
END EndCodeHunk;
(*------------------------------------*)
PROCEDURE AllocString *
(VAR s : ARRAY OF CHAR; len : LONGINT; VAR x : OCT.Item);
(* CONST pname = "AllocString"; *)
VAR i : INTEGER;
BEGIN (* AllocString *)
(* OCG.TraceIn (mname, pname); *)
IF len = 0 THEN
x.lev := 0; x.a0 := -1; x.a1 := 1; x.a2 := 0; x.symbol := NIL
ELSIF len = 1 THEN
x.lev := 0; x.a0 := -1; x.a1 := 2; x.a2 := ORD (s [0]); x.symbol := NIL
ELSE
i := 0;
IF (conx + len) >= ConstLength THEN OCS.Mark (230); conx := 0 END;
REPEAT
constant [conx] := s [i]; INC (i); INC (conx)
UNTIL i = len + 1;
x.lev := 0; x.a0 := conx - i; x.a1 := i; x.a2 := 0;
x.symbol := OCT.ConstSymbol
END;
x.obj := NIL
(* ;OCG.TraceOut (mname, pname); *)
END AllocString;
(*------------------------------------*)
PROCEDURE AllocStringFromChar * (VAR x : OCT.Item);
(* CONST pname = "AllocStringFromChar"; *)
BEGIN (* AllocStringFromChar *)
(* OCG.TraceIn (mname, pname); *)
IF x.a1 > 2 THEN OCS.Mark (212)
ELSIF x.a0 < 0 THEN
IF x.a1 = 1 THEN
IF conx = 0 THEN constant [0] := 0X; conx := 1 END;
x.a0 := conx - 1; x.symbol := OCT.ConstSymbol
ELSIF x.a1 = 2 THEN
IF conx >= ConstLength - 1 THEN OCS.Mark (230); conx := 0 END;
x.a0 := conx; constant [conx] := CHR (x.a2); INC (conx);
constant [conx] := 0X; INC (conx); x.symbol := OCT.ConstSymbol
END;
IF x.obj # NIL THEN x.obj.a0 := x.a0; x.obj.symbol := x.symbol END
END
(* ;OCG.TraceOut (mname, pname); *)
END AllocStringFromChar;
(*------------------------------------*)
PROCEDURE ConcatString *
(VAR s : ARRAY OF CHAR; len : LONGINT; VAR x : OCT.Item);
(* CONST pname = "ConcatString"; *)
VAR i : INTEGER; newLen : LONGINT;
BEGIN (* ConcatString *)
(* OCG.TraceIn (mname, pname); *)
IF len > 0 THEN
newLen := len + x.a1 - 1;
IF len + x.a1 = 2 THEN
x.a1 := 2; x.a2 := ORD (s [0])
ELSIF x.a1 = 1 THEN
AllocString (s, len, x)
ELSE
IF x.a1 = 2 THEN AllocStringFromChar (x) END;
i := 0; DEC (conx);
IF (conx + len) >= ConstLength THEN OCS.Mark (230); conx := 0 END;
REPEAT
constant [conx] := s [i]; INC (i); INC (conx)
UNTIL i = len + 1;
INC (x.a1, len)
END
END
(* ;OCG.TraceOut (mname, pname); *)
END ConcatString;
(*------------------------------------*)
PROCEDURE AllocTypDesc * (typ : OCT.Struct);
(* CONST pname = "AllocTypDesc"; *)
VAR t : INTEGER;
BEGIN (* AllocTypDesc *)
(* OCG.TraceIn (mname, pname); *)
IF typ.form = Pointer THEN
t := 0;
WHILE t < typex DO
IF (type [t].form = Pointer) & (type [t].size = typ.size) THEN
typ.adr := t; typ.mno := 0; typ.symbol := type [t].symbol;
RETURN
END;
INC (t)
END
END;
IF typex >= NumTypes THEN OCS.Mark (233); typex := 0 END;
type [typex] := typ; typ.adr := typex; INC (typex);
typ.mno := 0; OCT.MakeTypeSymbol (typ)
(* ;OCG.TraceOut (mname, pname); *)
END AllocTypDesc;
(*------------------------------------*)
PROCEDURE GetDReg * (VAR x : OCT.Item);
(* CONST pname = "GetDReg"; *)
VAR i : INTEGER;
BEGIN (* GetDReg *)
(*OCG.TraceIn (mname, pname);*)
i := D7; x.mode := Reg;
LOOP
IF ~(i IN RegSet) THEN x.a0 := i; INCL (RegSet, i); EXIT END;
IF i = D2 THEN x.a0 := D0; OCS.Mark (215); EXIT ELSE DEC (i) END
END
(*;OCG.TraceOut (mname, pname);*)
END GetDReg;
(*------------------------------------*)
PROCEDURE GetAReg * (VAR x : OCT.Item);
(* CONST pname = "GetAReg"; *)
VAR i : INTEGER;
BEGIN (* GetAReg *)
(*OCG.TraceIn (mname, pname);*)
i := A3; x.mode := Reg;
LOOP
IF ~(i IN RegSet) THEN x.a0 := i; INCL (RegSet, i); EXIT END;
IF i = A0 THEN x.a0 := A0; OCS.Mark (215); EXIT ELSE DEC (i) END
END; (* LOOP *)
(*;OCG.TraceOut (mname, pname);*)
END GetAReg;
(*------------------------------------*)
PROCEDURE GetAnyReg * (VAR x : OCT.Item);
(* CONST pname = "GetAnyReg"; *)
VAR i : INTEGER;
BEGIN (* GetAnyReg *)
(*OCG.TraceIn (mname, pname);*)
x.mode := Reg;
i := D7;
LOOP
IF ~(i IN RegSet) THEN x.a0 := i; INCL (RegSet, i); RETURN END;
IF i = D0 THEN EXIT ELSE DEC (i) END
END; (* LOOP *)
i := A3;
LOOP
IF ~(i IN RegSet) THEN x.a0 := i; INCL (RegSet, i); EXIT END;
IF i = A0 THEN x.a0 := A0; OCS.Mark (215); EXIT ELSE DEC (i) END
END; (* LOOP *)
(*;OCG.TraceOut (mname, pname);*)
END GetAnyReg;
(*------------------------------------*)
PROCEDURE ReserveReg * (reg : INTEGER);
(* CONST pname = "ReserveReg"; *)
BEGIN (* ReserveReg *)
(*OCG.TraceIn (mname, pname);*)
IF ~(reg IN RegSet) THEN
INCL (RegSet, reg)
ELSE
OCS.Mark (215)
END; (* ELSE *)
(*;OCG.TraceOut (mname, pname);*)
END ReserveReg;
(*------------------------------------*)
PROCEDURE UnReserveReg * (reg : INTEGER);
(* CONST pname = "UnReserveReg"; *)
BEGIN (* UnReserveReg *)
(*OCG.TraceIn (mname, pname);*)
IF (reg IN RegSet) THEN
EXCL (RegSet, reg)
ELSE
OCS.Mark (951)
END; (* ELSE *)
(*;OCG.TraceOut (mname, pname);*)
END UnReserveReg;
(*------------------------------------*)
PROCEDURE FreeRegs * (r : SET);
(* CONST pname = "FreeRegs"; *)
BEGIN (* FreeRegs *)
(*OCG.TraceIn (mname, pname);*)
RegSet := r
(*;OCG.TraceOut (mname, pname);*)
END FreeRegs;
(*------------------------------------*)
PROCEDURE FreeReg * (VAR x : OCT.Item);
(* CONST pname = "FreeReg"; *)
VAR R : SET;
BEGIN (* FreeReg *)
(*OCG.TraceIn (mname, pname);*)
IF x.mode IN {VarR, IndR, Reg, RegI, RegX, Push, Pop} THEN
IF x.a0 IN RegSet THEN EXCL (RegSet, x.a0) ELSE OCS.Mark (951) END;
IF x.mode = RegX THEN
IF x.a2 IN RegSet THEN EXCL (RegSet, x.a2) ELSE OCS.Mark (951) END
END
ELSIF x.mode IN {VarX, IndX} THEN
IF x.a2 IN RegSet THEN EXCL (RegSet, x.a2) ELSE OCS.Mark (951) END
ELSIF x.mode = RList THEN
R := SYS.VAL (SET, x.a0);
IF (R * RegSet) = R THEN RegSet := RegSet - R ELSE OCS.Mark (951) END
ELSE OCS.Mark (216)
END;
x.mode := Undef
(*;OCG.TraceOut (mname, pname);*)
END FreeReg;
(*------------------------------------*)
PROCEDURE PutWord * (w : INTEGER);
BEGIN (* PutWord *)
IF codex >= CodeLength THEN OCS.Mark (231); codex := 0 END;
code [codex] := w; INC (codex); INC (pc, 2)
END PutWord;
(*------------------------------------*)
PROCEDURE PatchWord * (loc, w : INTEGER);
(* CONST pname = "PatchWord"; *)
BEGIN (* PatchWord *)
(*OCG.TraceIn (mname, pname);*)
IF loc >= pc THEN OCS.Mark (961); loc := 0 END;
loc := loc DIV 2; code [loc] := SYS.LOR (code [loc], w)
(*;OCG.TraceOut (mname, pname);*)
END PatchWord;
(*------------------------------------*)
PROCEDURE PutLong * (l : LONGINT);
BEGIN (* PutLong *)
IF codex >= CodeLength - 1 THEN OCS.Mark (231); codex := 0 END;
code [codex] := SHORT (l DIV 10000H); INC (codex);
code [codex] := SHORT (l MOD 10000H); INC (codex);
INC (pc, 4)
END PutLong;
(*------------------------------------*)
PROCEDURE FindRef (symbol : OCT.Symbol; size : LONGINT) : Ref;
(* CONST pname = "FindRef"; *)
VAR ref : Ref;
BEGIN (* FindRef *)
(*OCG.TraceIn (mname, pname);*)
ref := CurrCodeHunk.refs;
WHILE (ref # NIL) & ((ref.symbol^ # symbol^) OR (ref.size # size)) DO
ref := ref.next
END; (* WHILE *)
(*;OCG.TraceOut (mname, pname);*)
RETURN ref
END FindRef;
(*------------------------------------*)
PROCEDURE MakeRef (ref : Ref; symbol : OCT.Symbol; size : INTEGER);
(* CONST pname = "MakeRef"; *)
VAR offset : Offset;
BEGIN (* MakeRef *)
(*OCG.TraceIn (mname, pname);*)
IF ref = NIL THEN
NEW (ref);
ref.next := CurrCodeHunk.refs; CurrCodeHunk.refs := ref;
ref.size := size; ref.symbol := symbol; ref.count := 0;
ref.offsets := NIL;
END;
NEW (offset);
offset.next := ref.offsets; ref.offsets := offset; INC (ref.count);
offset.n := pc - (CurrCodeHunk.start * 2);
(*;OCG.TraceOut (mname, pname);*)
END MakeRef;
(*------------------------------------*)
PROCEDURE PutWordRef * (offset : INTEGER; symbol : OCT.Symbol);
(* CONST pname = "PutWordRef"; *)
BEGIN (* PutWordRef *)
(*OCG.TraceIn (mname, pname);*)
IF symbol # NIL THEN
MakeRef (FindRef (symbol, 2), symbol, 2); PutWord (offset)
ELSE
OCS.Mark (964)
END
(*;OCG.TraceOut (mname, pname);*)
END PutWordRef;
(*------------------------------------*)
PROCEDURE PutLongRef * (offset : LONGINT; symbol : OCT.Symbol);
(* CONST pname = "PutLongRef"; *)
BEGIN (* PutLongRef *)
(*OCG.TraceIn (mname, pname);*)
IF symbol # NIL THEN
MakeRef (FindRef (symbol, 4), symbol, 4); PutLong (offset)
ELSE
OCS.Mark (964)
END
(*;OCG.TraceOut (mname, pname);*)
END PutLongRef;
(*------------------------------------*)
PROCEDURE PutArg (VAR arg : Arg);
(* CONST pname = "PutArg"; *)
BEGIN (* PutArg *)
(*OCG.TraceIn (mname, pname);*)
CASE arg.form OF
none : |
word : PutWord (SHORT (arg.data)) |
long : PutLong (arg.data) |
wordRef :
MakeRef (FindRef (arg.symbol, 2), arg.symbol, 2);
PutWord (SHORT (arg.data))
|
longRef :
MakeRef (FindRef (arg.symbol, 4), arg.symbol, 4);
PutLong (arg.data)
|
ELSE
OCS.Mark (1008); OCS.Mark (arg.form)
END; (* CASE arg.form *)
(*;OCG.TraceOut (mname, pname);*)
END PutArg;
(*------------------------------------*)
PROCEDURE Argument
( VAR op : INTEGER; size : LONGINT; ea05 : BOOLEAN;
VAR item : OCT.Item; VAR arg : Arg );
(* CONST pname = "Argument"; *)
VAR
form, mode, itemMode, reg, op2 : INTEGER; regItem : OCT.Item;
data : LONGINT; symbol : OCT.Symbol;
(*------------------------------------*)
PROCEDURE downlevel ();
(* CONST pname = "downlevel"; *)
VAR diff, op : INTEGER;
BEGIN (* downlevel *)
(*OCG.TraceIn (mname, pname);*)
diff := level - item.lev;
GetAReg (regItem); reg := SHORT (regItem.a0-8);
op := 206DH + SYS.LSH (reg, 9); (* MOVEA.L 8(A5), An *)
PutWord (op); PutWord (8);
op := 2068H + SYS.LSH (reg, 9) + reg; (* MOVEA.L 8(An), An *)
WHILE diff > 1 DO
PutWord (op); PutWord (8);
DEC (diff)
END; (* WHILE *)
mode := ARDisp; form := word; data := item.a0
(*;OCG.TraceOut (mname, pname);*)
END downlevel;
BEGIN (* Argument *)
(*OCG.TraceIn (mname, pname);*)
form := none;
CASE item.mode OF
Var, VarX, Ind, IndX :
itemMode := item.mode;
IF item.lev = 0 THEN (* Global variable of local module *)
IF OCS.longVars OR (item.a0 > 32767) OR (A4 IN RegSet) THEN
mode := Mode7; reg := AbsL; form := longRef;
symbol := OCT.VarSymbol; data := item.a0
ELSIF item.a0 = 0 THEN
mode := ARInd; reg := BP; form := none
ELSE
mode := ARDisp; reg := BP; form := word; data := item.a0
END
ELSIF item.lev < 0 THEN (* Global variable of imported module *)
mode := Mode7; reg := AbsL; form := longRef;
symbol := OCT.GlbMod [-item.lev-1].varSym; data := item.a0
ELSIF item.lev = level THEN (* Local variable in procedure *)
IF item.a0 = 0 THEN
mode := ARInd; reg := FP; form := none
ELSE
mode := ARDisp; reg := FP; form := word; data := item.a0
END
ELSE (* Local variable in surrounding context *)
downlevel ();
IF itemMode = Var THEN
item.mode := RegI; item.a1 := item.a0; item.a0 := reg + 8;
Argument (op, size, ea05, item, arg);
RETURN
END; (* IF *)
END; (* ELSE *)
arg.form := form; arg.data := data; arg.symbol := symbol;
IF itemMode = VarX THEN
GetAReg (regItem);
op2 :=
LEA + SYS.LSH (mode, 3) + reg
+ SYS.LSH (SHORT (regItem.a0)-8, 9); (* LEA <item>, An *)
PutWord (op2); PutArg (arg);
item.mode := RegX; item.a0 := regItem.a0; item.a1 := 0;
Argument (op, size, ea05, item, arg);
RETURN
ELSIF itemMode # Var THEN
GetAReg (regItem);
op2 :=
2040H + SYS.LSH (mode, 3) + reg
+ SYS.LSH (SHORT (regItem.a0)-8, 9);
PutWord (op2); PutArg (arg); (* MOVEA.L, <item>, An *)
reg := SHORT (regItem.a0) - 8;
IF itemMode = IndX THEN
IF item.a1 # 0 THEN
arg.form := word; arg.data := item.a1;
op2 := LEA + SYS.LSH (mode, 3) + reg + SYS.LSH (reg, 9);
PutWord (op2); PutArg (arg); (* LEA d(An), An *)
END; (* IF *)
item.mode := RegX; item.a0 := regItem.a0; item.a1 := 0;
Argument (op, size, ea05, item, arg);
RETURN
ELSE
item.mode := RegI; item.a0 := regItem.a0;
Argument (op, size, ea05, item, arg);
RETURN
END
END
|
RegI :
IF ~(item.a0 IN AdrRegs) THEN
OCS.Mark (215);
OCS.Mark (op); OCS.Mark (SHORT (size)); OCS.Mark (SHORT (item.a0));
item.a0 := A0
END;
reg := SHORT (item.a0) - 8;
IF item.a1 = 0 THEN mode := ARInd; form := none
ELSIF (item.a1 < -32768) OR (item.a1 > 32767) THEN
GetAnyReg (regItem);
IF regItem.a0 < A0 THEN (* MOVE.L #offset, Dn *)
op2 := 203CH + SYS.LSH (SHORT (regItem.a0), 9)
ELSE (* MOVEA.L #offset, An *)
op2 := 207CH + SYS.LSH (SHORT (regItem.a0) - 8, 9)
END; (* ELSE *)
PutWord (op2); PutLong (item.a1);
item.mode := RegX; item.a1 := 0; item.a2 := SHORT(regItem.a0);
Argument (op, size, ea05, item, arg);
RETURN
ELSE
mode := ARDisp; form := word; data := item.a1
END
|
RegX :
IF ~(item.a0 IN AdrRegs) THEN OCS.Mark (215); item.a0 := A0 END;
mode := ARDisX; reg := SHORT (item.a0) - 8;
IF (item.a1 < -128) OR (item.a1 > 127) THEN
IF item.a2 < A0 THEN (* ADDI.z #offset, Rn *)
IF item.wordIndex THEN op2 := 0640H + item.a2
ELSE op2 := 0680H + item.a2
END
ELSE (* ADDA.Z #offset, Rn *)
IF item.wordIndex THEN op2 := -2F04H + SYS.LSH (item.a2 - 8, 9)
ELSE op2 := -2E04H + SYS.LSH (item.a2 - 8, 9)
END
END; (* ELSE *)
PutWord (op2);
IF item.wordIndex THEN PutWord (SHORT (item.a1))
ELSE PutLong (item.a1)
END;
item.a1 := 0
END; (* IF *)
form := word;
data := SYS.AND (item.a1, 0FFH); (* Displacement *)
data := SYS.LOR (data, SYS.LSH (LONG (item.a2) MOD 8, 12));
(* Index reg. *)
IF item.a2 >= A0 THEN data := SYS.LOR (data, -8000H)
END; (* Addr. Reg. *)
IF ~item.wordIndex THEN data := SYS.LOR (data, 800H) (* Long reg. *)
END;
|
Lab, LabI :
mode := Mode7;
IF item.mode = Lab THEN reg := AbsL ELSE reg := Imm END;
IF item.a1 = W THEN form := wordRef
ELSIF item.a1 = L THEN form := longRef
ELSE OCS.Mark (957); form := longRef
END;
data := item.a0; symbol := item.symbol
|
Abs :
mode := Mode7;
IF (-32768 <= item.a0) & (item.a0 <= 32767) THEN
reg := AbsW; form := word
ELSE
reg := AbsL; form := long
END;
data := item.a0
|
Con :
IF item.typ = OCT.stringtyp THEN
IF item.a0 < 0 THEN OCS.Mark (962) END;
mode := Mode7; reg := AbsL; form := longRef; data := item.a0;
symbol := item.symbol
ELSE
mode := Mode7; reg := Imm;
IF size < L THEN form := word ELSE form := long END;
data := item.a0
END
|
Push, Pop :
IF ~(item.a0 IN AdrRegs) THEN OCS.Mark (215); item.a0 := A0 END;
IF item.mode = Push THEN mode := ARPre ELSE mode := ARPost END;
reg := SHORT (item.a0) - 8; form := none
|
VarR, IndR, Reg :
IF item.a0 IN DataRegs THEN
mode := DReg; reg := SHORT (item.a0); form := none
ELSE
mode := ARDir; reg := SHORT (item.a0) - 8; form := none
END
|
XProc, LProc :
mode := Mode7; data := 0; symbol := item.obj.symbol;
IF item.lev < 0 THEN reg := AbsL; form := longRef (* Imported proc. *)
ELSE reg := AbsW; form := wordRef
END
|
FProc :
mode := Mode7; data := 0; symbol := item.obj.symbol;
reg := AbsL; form := longRef
|
RList :
arg.form := word; arg.data := item.a0;
RETURN
|
ELSE
form := none; OCS.Mark (126);
OCS.Mark (op); OCS.Mark (SHORT (size)); OCS.Mark (item.mode);
RETURN
END; (* CASE item.mode *)
arg.form := form; arg.data := data; arg.symbol := symbol;
IF ea05 THEN op := op + SYS.LSH (mode, 3) + reg
ELSE op := op + SYS.LSH (mode, 6) + SYS.LSH (reg, 9)
END
(*;OCG.TraceOut (mname, pname);*)
END Argument;
(*------------------------------------*)
PROCEDURE PutF1 * (op : INTEGER; size : LONGINT; VAR item : OCT.Item);
(*
Instruction format #1: xxxxxxxxsseeeeee
Instructions: CLR, NEG, NOT, TST
*)
(* CONST pname = "PutF1"; *)
VAR arg : Arg;
BEGIN (* PutF1 *)
(* OCG.TraceIn (mname, pname); *)
op := op + SYS.LSH ((SHORT (size) DIV 2), 6);
Argument (op, size, TRUE, item, arg);
PutWord (op); PutArg (arg)
(* ;OCG.TraceOut (mname, pname); *)
END PutF1;
(*------------------------------------*)
PROCEDURE PutF2 * (op : INTEGER; VAR src : OCT.Item; reg : LONGINT);
(*
Instruction format #2: xxxxrrrxxxeeeeee
Instructions: LEA, DIVS, MULS, CHK
*)
(* CONST pname = "PutF2"; *)
VAR arg : Arg;
BEGIN (* PutF2 *)
(* OCG.TraceIn (mname, pname); *)
op := op + SYS.LSH (SHORT (reg) MOD 8, 9);
Argument (op, W, TRUE, src, arg);
PutWord (op); PutArg (arg)
(* ;OCG.TraceOut (mname, pname); *)
END PutF2;
(*------------------------------------*)
PROCEDURE PutF3 * (op : INTEGER; VAR item : OCT.Item);
(*
Instruction format #3: xxxxxxxxxxeeeeee
Instructions: PEA, JSR, JMP, Scc
*)
(* CONST pname = "PutF3"; *)
VAR arg : Arg;
BEGIN (* PutF3 *)
(* OCG.TraceIn (mname, pname); *)
Argument (op, W, TRUE, item, arg);
PutWord (op); PutArg (arg)
(* ;OCG.TraceOut (mname, pname); *)
END PutF3;
(*------------------------------------*)
PROCEDURE Bit * (op : INTEGER; VAR src, dst : OCT.Item);
(*
Instruction format #2: xxxxrrrxxxeeeeee
Instruction format #3: xxxxxxxxxxeeeeee
Instructions: BTST, BCLR, BSET
*)
(* CONST pname = "Bit"; *)
VAR arg : Arg;
BEGIN (* Bit *)
(* OCG.TraceIn (mname, pname); *)
IF src.mode = Reg THEN
op := SYS.LOR (op, SYS.LOR (100H, SYS.LSH (SHORT (src.a0), 9)))
ELSE
op := SYS.LOR (op, 800H)
END;
Argument (op, W, TRUE, dst, arg);
PutWord (op); IF src.mode = Con THEN PutWord (SHORT (src.a0)) END;
PutArg (arg)
(* ;OCG.TraceOut (mname, pname); *)
END Bit;
(*------------------------------------*)
PROCEDURE Move * (size : LONGINT; VAR src, dst : OCT.Item);
(* CONST pname = "Move"; *)
VAR arg1, arg2 : Arg; op, reg : INTEGER; rlist1, rlist2 : SYS.WORDSET;
BEGIN (* Move *)
(* OCG.TraceIn (mname, pname); *)
IF (src.mode IN regSet) & (dst.mode IN regSet) & (src.a0 = dst.a0) THEN
(* ;OCG.TraceOut (mname, pname); *)
RETURN
END;
IF src.mode = RList THEN (* MOVEM Registers to EA *)
IF size = L THEN op := 48C0H ELSE op := 4880H END;
Argument (op, size, TRUE, dst, arg1);
IF dst.mode = Push THEN
(* Reverse the register list first *)
reg := 0;
rlist1 := SYS.VAL (SYS.WORDSET, SHORT (src.a0)); rlist2 := {};
WHILE reg <= A7 DO
IF reg IN rlist1 THEN INCL (rlist2, 15 - reg) END;
INC (reg)
END;
src.a0 := SYS.VAL (LONGINT, LONG (rlist2))
END;
PutWord (op); PutWord (SHORT (src.a0)); PutArg (arg1)
ELSIF dst.mode = RList THEN (* MOVEM EA to Registers *)
IF size = L THEN op := 4CC0H ELSE op := 4C80H END;
Argument (op, size, TRUE, src, arg1);
PutWord (op); PutWord (SHORT (dst.a0)); PutArg (arg1)
ELSIF (dst.mode IN regSet) & (dst.a0 IN AdrRegs) THEN
IF (src.mode = Con) & (src.a0 = 0) THEN (* SUBA.Z <dst>, <dst> *)
reg := SHORT (dst.a0) - 8; op := -6F38H;
IF size = L THEN op := SYS.LOR (op, 100H)
ELSIF size = B THEN OCS.Mark (957)
END;
op := SYS.LOR (op, SYS.LOR (SYS.LSH (reg, 9), reg));
PutWord (op)
ELSE (* MOVEA.Z <src>, <dst> *)
IF size = L THEN
op := SYS.LOR (2040H, SYS.LSH (SHORT (dst.a0) MOD 8, 9))
ELSIF size = W THEN
op := SYS.LOR (3040H, SYS.LSH (SHORT (dst.a0) MOD 8, 9))
ELSE
OCS.Mark (957); op := 3040H
END;
Argument (op, size, TRUE, src, arg1); PutWord (op); PutArg (arg1)
END
ELSIF
(dst.mode IN regSet) & (dst.a0 IN DataRegs) & (src.mode = Con)
& (src.a0 >= -128) & (src.a0 <= 127)
THEN (* MOVEQ #<src>, <dst> *)
op := SYS.LOR (7000H, SYS.LSH (SHORT (dst.a0), 9));
op := SYS.LOR (op, SYS.AND (SHORT (src.a0), 0FFH));
PutWord (op)
ELSIF (src.mode = Con) & (src.a0 = 0) THEN (* CLR.z <dst> *)
PutF1 (CLR, size, dst)
ELSE (* MOVE.z <src>, <dst> *)
IF size = L THEN op := 2000H
ELSIF size = W THEN op := 3000H
ELSIF size = B THEN op := 1000H
ELSE
OCS.Mark (957); op := 1000H
END;
Argument (op, size, TRUE, src, arg1);
Argument (op, size, FALSE, dst, arg2);
PutWord (op); PutArg (arg1); PutArg (arg2)
END
(* ;OCG.TraceOut (mname, pname); *)
END Move;
(*------------------------------------*)
PROCEDURE PutF7 * (op : INTEGER; size, src : LONGINT; VAR dst : OCT.Item);
(*
Instruction format #7: xxxxdddxsseeeeee
Instructions: ADDQ, SUBQ
*)
(* CONST pname = "PutF7"; *)
VAR arg : Arg;
BEGIN (* PutF7 *)
(* OCG.TraceIn (mname, pname); *)
IF (src > 0) & (src <= 8) THEN
op := SYS.LOR (op, SYS.LSH ((SHORT (size) DIV 2), 6));
op := SYS.LOR (op, SYS.LSH (SHORT (src) MOD 8, 9));
Argument (op, size, TRUE, dst, arg); PutWord (op); PutArg (arg)
ELSE
OCS.Mark (957)
END; (* ELSE *)
(* ;OCG.TraceOut (mname, pname); *)
END PutF7;
(*------------------------------------*)
PROCEDURE PutF6 * (op : INTEGER; size : LONGINT; VAR src, dst : OCT.Item);
(*
Instruction format #6: xxxxxxxxsseeeeee
Instructions: ORI, SUBI, CMPI, EORI, ANDI, ADDI
Instructions: ADDQ, SUBQ
*)
(* CONST pname = "PutF6"; *)
VAR arg : Arg;
BEGIN (* PutF6 *)
(* OCG.TraceIn (mname, pname); *)
IF ((op = ADDI) OR (op = SUBI)) & (src.a0 > 0) & (src.a0 < 9) THEN
IF op = ADDI THEN op := ADDQ ELSE op := SUBQ END;
PutF7 (op, size, src.a0, dst)
ELSE
op := SYS.LOR (op, SYS.LSH ((SHORT (size) DIV 2), 6));
Argument (op, size, TRUE, dst, arg); PutWord (op);
IF src.mode = LabI THEN PutLongRef (src.a0, src.symbol)
ELSIF size = L THEN PutLong (src.a0)
ELSE PutWord (SHORT (src.a0))
END;
PutArg (arg)
END
(* ;OCG.TraceOut (mname, pname); *)
END PutF6;
(*------------------------------------*)
PROCEDURE PutF5 * (op : INTEGER; size : LONGINT; VAR src, dst : OCT.Item);
(*
Instruction format #5: xxxxrrrmmmeeeeee
Instructions: OR, SUB, SUBA, CMP, CMPA, EOR, AND, ADD, ADDA, ORI,
SUBI, CMPI, EORI, ANDI, ADDI, ADDQ, SUBQ
*)
(* CONST pname = "PutF5"; *)
VAR arg : Arg;
BEGIN (* PutF5 *)
(* OCG.TraceIn (mname, pname); *)
IF (dst.mode IN regSet) & (dst.a0 IN AdrRegs) THEN
IF size = L THEN op := SYS.LOR (op, 1C0H)
ELSIF size = W THEN op := SYS.LOR (op, 0C0H)
ELSE OCS.Mark (957)
END;
op := SYS.LOR (op, SYS.LSH (SHORT (dst.a0) - 8, 9));
Argument (op, size, TRUE, src, arg)
ELSIF (src.mode = Con) OR (src.mode = LabI) THEN
IF op = iOR THEN op := ORI
ELSIF op = SUB THEN op := SUBI
ELSIF op = CMP THEN op := CMPI
ELSIF op = EOR THEN op := EORI
ELSIF op = AND THEN op := ANDI
ELSIF op = ADD THEN op := ADDI
ELSE OCS.Mark (956)
END;
PutF6 (op, size, src, dst);
RETURN
ELSIF (op # EOR) & (dst.mode IN regSet) & (dst.a0 IN DataRegs) THEN
op := SYS.LOR (op, SYS.LSH (SHORT (size) DIV 2, 6));
op := SYS.LOR (op, SYS.LSH (SHORT (dst.a0), 9));
Argument (op, size, TRUE, src, arg)
ELSE
op := SYS.LOR (op, SYS.LSH (SHORT (size) DIV 2, 6));
op := SYS.LOR (SYS.LOR (op, 100H), SYS.LSH (SHORT (src.a0), 9));
Argument (op, size, TRUE, dst, arg)
END;
PutWord (op); PutArg (arg)
(* ;OCG.TraceOut (mname, pname); *)
END PutF5;
(*------------------------------------*)
PROCEDURE Shift * (op : INTEGER; size : LONGINT; VAR count, reg : OCT.Item);
(*
Instruction format #5: xxxxrrrxssxxxrrr
Instructions: ASL, ASR, LSL, LSR, ROL, ROR
*)
(* CONST pname = "Shift"; *)
VAR arg : Arg;
BEGIN (* Shift *)
(* OCG.TraceIn (mname, pname); *)
IF (reg.mode IN regSet) & (reg.a0 IN DataRegs) THEN
op := SYS.LOR (op, SYS.LSH ((SHORT (size) DIV 2), 6));
op := SYS.LOR (op, SHORT (reg.a0));
IF (count.mode = Reg) & (count.a0 IN DataRegs) THEN
op := SYS.LOR (op, 20H);
op := SYS.LOR (op, SYS.LSH (SHORT (count.a0), 9))
ELSIF count.mode = Con THEN
IF (count.a0 > 0) & (count.a0 <= 8) THEN
op := SYS.LOR (op, SYS.LSH (SHORT (count.a0) MOD 8, 9))
ELSE OCS.Mark (957)
END;
ELSE OCS.Mark (956)
END;
PutWord (op)
ELSE OCS.Mark (956)
END;
(* ;OCG.TraceOut (mname, pname); *)
END Shift;
(*------------------------------------*)
PROCEDURE SaveRegisters0 (regs : SET);
(* CONST pname = "SaveRegisters0"; *)
VAR numRegs, reg, lastReg, op : INTEGER; rlist : SYS.WORDSET;
BEGIN (* SaveRegisters0 *)
(* OCG.TraceIn (mname, pname); *)
IF regs # {} THEN
numRegs := 0; reg := 0;
WHILE reg <= A7 DO
IF reg IN regs THEN lastReg := reg; INC (numRegs) END;
INC (reg)
END;
IF numRegs = 1 THEN
IF lastReg IN DataRegs THEN (* MOVE.L Dn, -(A7) *)
op := SYS.LOR (2F00H, lastReg)
ELSE (* MOVE.L An, -(A7) *)
op := SYS.LOR (2F08H, lastReg - 8)
END;
PutWord (op)
ELSE (* MOVEM.L <regs>, -(A7) *)
(* Reverse the register list first *)
reg := 0; rlist := {};
WHILE reg <= lastReg DO
IF reg IN regs THEN INCL (rlist, 15 - reg) END;
INC (reg)
END;
PutWord (48E7H); PutWord (SYS.VAL (INTEGER, rlist))
END
END
(* ;OCG.TraceOut (mname, pname); *)
END SaveRegisters0;
(*------------------------------------*)
PROCEDURE SaveRegisters *
( VAR regs : SET;
VAR x : OCT.Item;
mask : SET );
(* CONST pname = "SaveRegisters"; *)
VAR temp : SET;
BEGIN (* SaveRegisters *)
(* OCG.TraceIn (mname, pname); *)
(* Temporarily reserve A4 and/or A5 if in mask *)
RegSet := RegSet + (mask * {A4,A5});
temp := RegSet; RegSet := RegSet * mask;
IF x.mode IN {Reg, RegI, RegX} THEN EXCL (RegSet, x.a0) END;
IF x.mode IN {VarX, IndX, RegX} THEN EXCL (RegSet, x.a2) END;
SaveRegisters0 (RegSet);
regs := RegSet; RegSet := temp - RegSet;
(* ;OCG.TraceOut (mname, pname); *)
END SaveRegisters;
(*------------------------------------*)
PROCEDURE LoadRegParams1 * (VAR regs : SET; VAR x : OCT.Item);
(* CONST pname = "LoadRegParams1"; *)
VAR d0 : OCT.Item; inD0 : BOOLEAN;
BEGIN (* LoadRegParams1 *)
(* OCG.TraceIn (mname, pname); *)
inD0 := (x.mode = Reg) & (x.a0 = D0);
regs := RegSet * ScratchRegs; IF inD0 THEN EXCL (regs, D0) END;
SaveRegisters0 (regs); RegSet := RegSet - regs;
IF ~inD0 THEN
d0.mode := Reg; d0.a0 := D0; Move (x.typ^.size, x, d0)
END; (* IF *)
(* ;OCG.TraceOut (mname, pname); *)
END LoadRegParams1;
(*------------------------------------*)
PROCEDURE LoadRegParams2 * (VAR regs : SET; VAR x, y : OCT.Item);
(* CONST pname = "LoadRegParams2"; *)
VAR d0, d1, t : OCT.Item;
BEGIN (* LoadRegParams2 *)
(* OCG.TraceIn (mname, pname); *)
regs := RegSet * ScratchRegs;
IF (x.mode = Reg) & (x.a0 IN {D0, D1}) THEN EXCL (regs, x.a0) END;
IF (y.mode = Reg) & (y.a0 IN {D0, D1}) THEN EXCL (regs, y.a0) END;
SaveRegisters0 (regs); RegSet := RegSet - regs;
d0.mode := Reg; d0.a0 := D0; d1.mode := Reg; d1.a0 := D1;
IF (y.mode = Reg) & (y.a0 = D0) THEN
IF (x.mode = Reg) & (x.a0 = D1) THEN
GetDReg (t); Move (x.typ^.size, x, t); x.a0 := t.a0;
EXCL (RegSet, D1)
END; (* IF *)
Move (y.typ^.size, y, d1); y.a0 := D1;
EXCL (RegSet, D0); INCL (RegSet, D1)
END; (* IF *)
IF ~((x.mode = Reg) & (x.a0 = D0)) THEN Move (x.typ^.size, x, d0) END;
IF ~((y.mode = Reg) & (y.a0 = D1)) THEN Move (y.typ^.size, y, d1) END
(* ;OCG.TraceOut (mname, pname); *)
END LoadRegParams2;
(*------------------------------------*)
PROCEDURE RestoreRegisters * (regs : SET; VAR x : OCT.Item);
(* CONST pname = "RestoreRegisters"; *)
VAR
numRegs, op, reg, lastReg : INTEGER; y : OCT.Item; rlist : SET;
restyp : OCT.Struct;
BEGIN (* RestoreRegisters *)
(* OCG.TraceIn (mname, pname); *)
RegSet := RegSet + regs;
IF x.mode IN {XProc, LProc, TProc, FProc} THEN
restyp := x.typ
ELSIF (x.mode IN {Var..RegX}) & (x.typ.form = ProcTyp) THEN
restyp := x.typ.BaseTyp
ELSE
restyp := NIL
END;
IF
(restyp # NIL) & (restyp.form = Pointer) & (restyp.size > OCG.PtrSize)
THEN (* PROCEDURE return type is POINTER TO ARRAY OF ... *)
reg := 0; rlist := {};
WHILE (reg * 4) < restyp.size DO INCL (rlist, reg); INC (reg) END;
IF (rlist * RegSet) # {} THEN OCS.Mark (967) END;
RegSet := RegSet + rlist;
x.mode := RList; x.a0 := SYS.VAL (LONGINT, rlist)
ELSE
y := x; x.mode := Reg; x.a0 := D0;
IF (D0 IN regs) OR (y.mode = Reg) THEN
IF (y.mode # Reg) OR ~(y.a0 IN DataRegs) THEN
GetDReg (y)
END;
IF y.a0 # 0 THEN Move (L, x, y); x.a0 := y.a0 END;
ELSE
INCL (RegSet, D0);
END
END;
IF regs # {} THEN
numRegs := 0; reg := 0;
WHILE reg <= A7 DO
IF reg IN regs THEN lastReg := reg; INC (numRegs) END;
INC (reg)
END; (* WHILE *)
IF numRegs = 1 THEN
IF lastReg IN DataRegs THEN (* MOVE.L (A7)+, Dn *)
op := SYS.LOR (201FH, SYS.LSH (lastReg, 9))
ELSE (* MOVEA.L (A7)+, An *)
op := SYS.LOR (205FH, SYS.LSH (lastReg - 8, 9))
END;
PutWord (op)
ELSE (* MOVEM.L (A7)+, <regs> *)
PutWord (4CDFH); PutWord (SYS.VAL (INTEGER, SHORT (regs)))
END
END; (* IF *)
RegSet := RegSet - {A4,A5} (* Mask out system registers *)
(* ;OCG.TraceOut (mname, pname); *)
END RestoreRegisters;
(*------------------------------------*)
PROCEDURE fixup * (loc : LONGINT); (* enter pc at loc *)
BEGIN (* fixup *)
code [loc DIV 2] := pc - SHORT (loc)
END fixup;
(*------------------------------------*)
PROCEDURE FixLink * (L : LONGINT);
(* CONST pname = "FixLink"; *)
VAR L1 : LONGINT;
BEGIN (* FixLink *)
(* OCG.TraceIn (mname, pname); *)
WHILE L # 0 DO
L1 := code [L DIV 2]; fixup (L); L := L1
END; (* WHILE *)
(* ;OCG.TraceOut (mname, pname); *)
END FixLink;
(*------------------------------------*)
PROCEDURE FixupWith * (L, val : LONGINT);
VAR x : LONGINT;
BEGIN (* FixupWith *)
code [L DIV 2] := SHORT (val)
END FixupWith;
(*------------------------------------*)
PROCEDURE FixLinkWith * (L, val : LONGINT);
(* CONST pname = "FixLinkWith"; *)
VAR L1 : LONGINT;
BEGIN (* FixLinkWith *)
(* OCG.TraceIn (mname, pname); *)
WHILE L # 0 DO
L1 := code [L DIV 2];
FixupWith (L, val - L); L := L1
END; (* WHILE *)
(* ;OCG.TraceOut (mname, pname); *)
END FixLinkWith;
(*------------------------------------*)
PROCEDURE MergedLinks * (L0, L1 : LONGINT): LONGINT;
(* CONST pname = "MergedLinks"; *)
VAR L2, L3 : LONGINT;
BEGIN (* MergedLinks *)
(* OCG.TraceIn (mname, pname); *)
(* merge chains of the two operands of AND and OR *)
IF L0 # 0 THEN
L2 := L0;
LOOP
L3 := code [L2 DIV 2];
IF L3 = 0 THEN EXIT END;
L2 := L3
END; (* LOOP *)
code [L2 DIV 2] := SHORT (L1);
RETURN L0
ELSE
RETURN L1
END; (* ELSE *)
(* ;OCG.TraceOut (mname, pname); *)
END MergedLinks;
(*------------------------------------*)
PROCEDURE invertedCC * (cc : LONGINT) : INTEGER;
BEGIN (* invertedCC *)
IF ODD (cc) THEN RETURN SHORT (cc - 1)
ELSE RETURN SHORT (cc + 1)
END
END invertedCC;
(*------------------------------------*)
PROCEDURE Trap * (n : INTEGER);
(* CONST pname = "Trap"; *)
BEGIN (* Trap *)
(* OCG.TraceIn (mname, pname); *)
IF n = OverflowCheck THEN PutWord (TRAPV) (* TRAPV *)
ELSE PutWord (TRAP + n) (* TRAP #n *)
END;
(* ;OCG.TraceOut (mname, pname); *)
END Trap;
(*------------------------------------*)
PROCEDURE TrapCC * (n, cc : INTEGER);
(* CONST pname = "TrapCC"; *)
BEGIN (* TrapCC *)
(* OCG.TraceIn (mname, pname); *)
IF cc # T THEN
(* Branch over the following TRAP instruction (2 bytes) *)
PutWord (Bcc + (invertedCC (cc) * 100H) + 2)
END;
Trap (n)
(* ;OCG.TraceOut (mname, pname); *)
END TrapCC;
(*------------------------------------*)
PROCEDURE TypeTrap * ( L : INTEGER );
(* CONST pname = "TypeTrap"; *)
BEGIN (* TypeTrap *)
(* OCG.TraceIn (mname, pname); *)
PutWord (6002H); (* BRA.S 1$ *)
FixLink (L); PutWord (TRAP + TypeCheck) (* L: TRAP #TypeCheck *)
(* ;OCG.TraceOut (mname, pname); *)
END TypeTrap; (* 1$ *)
(*------------------------------------*)
PROCEDURE GlobalPtrs * () : BOOLEAN;
(* CONST pname = "GlobalPtrs"; *)
VAR obj : OCT.Object;
(*------------------------------------*)
PROCEDURE FindPtrs (typ : OCT.Struct);
(* CONST pname = "FindPtrs"; *)
VAR btyp : OCT.Struct; fld : OCT.Object; i, n : LONGINT;
BEGIN (* FindPtrs *)
(* OCG.TraceIn (mname, pname); *)
IF typ.form = Pointer THEN INC (numPtrs)
ELSIF typ.form = Record THEN
btyp := typ.BaseTyp; IF btyp # NIL THEN FindPtrs (btyp) END;
fld := typ.link;
WHILE fld # NIL DO
IF fld.name < 0 THEN INC (numPtrs) (* Hidden pointer field *)
ELSE FindPtrs (fld.typ)
END;
fld := fld.left
END
ELSIF typ.form = Array THEN
btyp := typ.BaseTyp; n := typ.n;
WHILE btyp.form = Array DO n := btyp.n * n; btyp := btyp.BaseTyp END;
IF (btyp.form = Pointer) OR (btyp.form = Record) THEN
i := 0; WHILE i < n DO FindPtrs (btyp); INC (i) END
END
END
(* ;OCG.TraceOut (mname, pname); *)
END FindPtrs;
BEGIN (* GlobalPtrs *)
(* OCG.TraceIn (mname, pname); *)
numPtrs := 0; obj := OCT.topScope.right;
WHILE obj # NIL DO
IF obj.mode = Var THEN FindPtrs (obj.typ) END;
obj := obj.link
END;
(* ;OCG.TraceOut (mname, pname); *)
RETURN (numPtrs # 0)
END GlobalPtrs;
(*------------------------------------*)
PROCEDURE NumProcs (typ : OCT.Struct) : LONGINT;
(* CONST pname = "NumProcs"; *)
VAR n : LONGINT; obj : OCT.Object;
BEGIN (* NumProcs *)
(* OCG.TraceIn (mname, pname); *)
n := 0;
REPEAT
obj := typ.link;
WHILE obj # NIL DO
IF (obj.mode = TProc) & (obj.a0 > n) THEN n := obj.a0 END;
obj := obj.left
END;
typ := typ.BaseTyp
UNTIL typ = NIL;
(* ;OCG.TraceOut (mname, pname); *)
RETURN n
END NumProcs;
(*------------------------------------*)
PROCEDURE ProcSym (typ : OCT.Struct; pno : LONGINT) : OCT.Symbol;
(* CONST pname = "ProcSym"; *)
VAR obj : OCT.Object;
BEGIN (* ProcSym *)
(* OCG.TraceIn (mname, pname); *)
LOOP
obj := typ.link;
WHILE obj # NIL DO
IF (obj.mode = TProc) & (obj.a0 = pno) THEN
(* OCG.TraceOut (mname, pname); *)
RETURN obj.symbol
END;
obj := obj.left
END;
typ := typ.BaseTyp;
IF typ = NIL THEN HALT (929) END
END;
END ProcSym;
(*------------------------------------*)
PROCEDURE OutCode * (FName : ARRAY OF CHAR; key, datasize : LONGINT);
(* CONST pname = "OutCode"; *)
VAR
ObjFile : Files.File;
out : Files.Rider;
blockType, res, N : LONGINT;
codeHunk : CodeHunk;
(*------------------------------------*)
PROCEDURE OutName (type : INTEGER; name : ARRAY OF CHAR);
(* CONST pname = "OutName"; *)
VAR len, char, pad : INTEGER;
(* $D- disable copying of open arrays *)
BEGIN (* OutName *)
(* OCG.TraceIn (mname, pname); *)
len := SHORT (SYS.STRLEN (name));
pad := (((len + 3) DIV 4) * 4) - len;
N := SYS.LSH (LONG (type), 24) + ((len + 3) DIV 4);
Files.WriteBytes (out, N, 4);
char := 0;
WHILE char < len DO
Files.Write (out, name [char]);
INC (char);
END; (* WHILE *)
WHILE pad > 0 DO Files.Write (out, 0X); DEC (pad) END;
(* ;OCG.TraceOut (mname, pname); *)
END OutName;
(*------------------------------------*)
PROCEDURE OutHunkUnit ();
(* CONST pname = "OutHunkUnit"; *)
BEGIN (* OutHunkUnit *)
(* OCG.TraceIn (mname, pname); *)
blockType := hunkUnit;
Files.WriteBytes (out, blockType, 4);
OutName (0, OCT.ModuleName);
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkUnit;
(*------------------------------------*)
PROCEDURE OutHunkName ();
(* CONST pname = "OutHunkName"; *)
BEGIN (* OutHunkName *)
(* OCG.TraceIn (mname, pname); *)
blockType := hunkName;
Files.WriteBytes (out, blockType, 4);
OutName (0, OCT.ModuleName);
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkName;
(*------------------------------------*)
PROCEDURE OutDef0 (symbol : ARRAY OF CHAR; offset : LONGINT);
(* CONST pname = "OutDef0"; *)
(* $D- disable copying of open arrays *)
BEGIN (* OutDef0 *)
(* OCG.TraceIn (mname, pname); *)
OutName (extDef, symbol);
Files.WriteBytes (out, offset, 4)
(* ;OCG.TraceOut (mname, pname); *)
END OutDef0;
(*------------------------------------*)
PROCEDURE OutDef (def : Def);
(* CONST pname = "OutDef"; *)
BEGIN (* OutDef *)
(* OCG.TraceIn (mname, pname); *)
OutDef0 (def.symbol^, def.offset)
(* ;OCG.TraceOut (mname, pname); *)
END OutDef;
(*------------------------------------*)
PROCEDURE OutRef (ref : Ref);
(* CONST pname = "OutRef"; *)
VAR type : INTEGER; offset : Offset;
BEGIN (* OutRef *)
(* OCG.TraceIn (mname, pname); *)
IF ref.size = 4 THEN type := extRef32
ELSIF ref.size = 2 THEN type := extRef16
(*ELSIF ref.size = 1 THEN type := extRef8*)
ELSE OCS.Mark (959)
END;
OutName (type, ref.symbol^);
Files.WriteBytes (out, ref.count, 4);
offset := ref.offsets;
WHILE offset # NIL DO
Files.WriteBytes (out, offset.n, 4);
offset := offset.next
END
(* ;OCG.TraceOut (mname, pname); *)
END OutRef;
(*------------------------------------*)
PROCEDURE OutCodeHunk (codeHunk : CodeHunk);
(* CONST pname = "OutCodeHunk"; *)
(*------------------------------------*)
PROCEDURE OutHunkCode ();
(* CONST pname = "OutHunkCode"; *)
VAR pos, len, pad : INTEGER;
BEGIN (* OutHunkCode *)
(* OCG.TraceIn (mname, pname); *)
blockType := hunkCode;
Files.WriteBytes (out, blockType, 4);
N := (codeHunk.length + 1) DIV 2;
Files.WriteBytes (out, N, 4);
pos := codeHunk.start; len := codeHunk.length;
WHILE len > 0 DO
Files.WriteBytes (out, code [pos], 2);
INC (pos); DEC (len);
END; (* WHILE *)
IF ODD (codeHunk.length) THEN
pad := 04E71H; (* Output a NOP, purely for the benefit of ninfo *)
Files.WriteBytes (out, pad, 2);
END; (* IF *)
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkCode;
(*------------------------------------*)
PROCEDURE OutHunkExt ();
(* CONST pname = "OutHunkExt"; *)
VAR ref : Ref; def : Def;
BEGIN (* OutHunkExt *)
(* OCG.TraceIn (mname, pname); *)
blockType := hunkExt;
Files.WriteBytes (out, blockType, 4);
IF codeHunk = InitCodeHunk THEN
OutDef0 (OCT.InitSymbol^, 0);
END; (* IF *)
def := codeHunk.defs;
WHILE def # NIL DO
OutDef (def);
def := def.next
END; (* WHILE *)
ref := codeHunk.refs;
WHILE ref # NIL DO
OutRef (ref);
ref := ref.next
END; (* WHILE *)
N := 0;
Files.WriteBytes (out, N, 4);
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkExt;
(*------------------------------------*)
PROCEDURE OutHunkSymbol ();
(* CONST pname = "OutHunkSymbol"; *)
VAR def : Def;
BEGIN (* OutHunkSymbol *)
(* OCG.TraceIn (mname, pname); *)
IF Debug & ((codeHunk = InitCodeHunk) OR (codeHunk.defs # NIL)) THEN
blockType := hunkSymbol;
Files.WriteBytes (out, blockType, 4);
IF codeHunk = InitCodeHunk THEN
OutName (extSymb, OCT.InitSymbol^);
N := 0; Files.WriteBytes (out, N, 4);
END; (* IF *)
def := codeHunk.defs;
WHILE def # NIL DO
OutName (extSymb, def.symbol^);
Files.WriteBytes (out, def.offset, 4);
def := def.next
END; (* WHILE *)
N := 0;
Files.WriteBytes (out, N, 4);
END;
(* OCG.TraceOut (mname, pname); *)
END OutHunkSymbol;
BEGIN (* OutCodeHunk *)
(* OCG.TraceIn (mname, pname); *)
OutHunkUnit ();
OutHunkName ();
OutHunkCode ();
OutHunkExt ();
OutHunkSymbol ();
blockType := hunkEnd;
Files.WriteBytes (out, blockType, 4);
(* ;OCG.TraceOut (mname, pname); *)
END OutCodeHunk;
(*------------------------------------*)
PROCEDURE OutConstants ();
(* CONST pname = "OutConstants"; *)
(*------------------------------------*)
PROCEDURE OutHunkData ();
(* CONST pname = "OutHunkData"; *)
VAR pos, len , pad : INTEGER;
BEGIN (* OutHunkData *)
(* OCG.TraceIn (mname, pname); *)
blockType := hunkData;
Files.WriteBytes (out, blockType, 4);
N := (conx + 3) DIV 4;
Files.WriteBytes (out, N, 4);
pos := 0; len := conx;
WHILE pos < len DO
Files.Write (out, constant [pos]);
INC (pos);
END; (* WHILE *)
pad := (((len + 3) DIV 4) * 4) - len;
WHILE pad > 0 DO
Files.Write (out, 0X);
DEC (pad);
END; (* WHILE *)
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkData;
(*------------------------------------*)
PROCEDURE OutHunkExt ();
(* CONST pname = "OutHunkExt"; *)
VAR ref : Ref;
BEGIN (* OutHunkExt *)
(* OCG.TraceIn (mname, pname); *)
blockType := hunkExt;
Files.WriteBytes (out, blockType, 4);
OutDef0 (OCT.ConstSymbol^, 0);
N := 0;
Files.WriteBytes (out, N, 4);
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkExt;
(*------------------------------------*)
PROCEDURE OutHunkSymbol ();
(* CONST pname = "OutHunkSymbol"; *)
BEGIN (* OutHunkSymbol *)
(* OCG.TraceIn (mname, pname); *)
IF Debug THEN
blockType := hunkSymbol;
Files.WriteBytes (out, blockType, 4);
OutName (extSymb, OCT.ConstSymbol^);
N := 0; Files.WriteBytes (out, N, 4);
Files.WriteBytes (out, N, 4);
END;
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkSymbol;
BEGIN (* OutConstants *)
(* OCG.TraceIn (mname, pname); *)
IF conx > 0 THEN
OutHunkUnit ();
OutHunkName ();
OutHunkData ();
OutHunkExt ();
OutHunkSymbol ();
blockType := hunkEnd;
Files.WriteBytes (out, blockType, 4);
END; (* IF *)
(* ;OCG.TraceOut (mname, pname); *)
END OutConstants;
(*------------------------------------*)
PROCEDURE FindPtrs
( typ : OCT.Struct; adr : LONGINT; VAR offset : LONGINT );
(* CONST pname = "FindPtrs"; *)
VAR btyp : OCT.Struct; fld : OCT.Object; i, n, s : LONGINT;
BEGIN (* FindPtrs *)
(* OCG.TraceIn (mname, pname); *)
IF typ.form = Pointer THEN
Files.WriteBytes (out, adr, 4); DEC (offset, 4); INC (dataCount)
ELSIF typ.form = Record THEN
btyp := typ.BaseTyp;
IF btyp # NIL THEN FindPtrs (btyp, adr, offset) END;
fld := typ.link;
WHILE fld # NIL DO
IF fld.mode = Fld THEN
IF fld.name < 0 THEN (* Hidden pointer field *)
n := fld.a0 + adr; Files.WriteBytes (out, n, 4);
DEC (offset, 4); INC (dataCount)
ELSE
FindPtrs (fld.typ, fld.a0 + adr, offset)
END
END;
fld := fld.left
END;
ELSIF typ.form = Array THEN
btyp := typ.BaseTyp; n := typ.n;
WHILE btyp.form = Array DO
n := btyp.n * n; btyp := btyp.BaseTyp
END;
IF (btyp.form = Pointer) OR (btyp.form = Record) THEN
i := 0; s := btyp.size;
WHILE i < n DO
FindPtrs (btyp, i * s + adr, offset); INC (i)
END
END
END
(* ;OCG.TraceOut (mname, pname); *)
END FindPtrs;
(*------------------------------------*)
PROCEDURE OutTypeDescs ();
(* CONST pname = "OutTypeDescs"; *)
VAR i : INTEGER; numProcs : LONGINT;
(*------------------------------------*)
PROCEDURE OutHunkData (typ : OCT.Struct);
(* CONST pname = "OutHunkData"; *)
VAR
pos1, pos2, N, i, nameLen : LONGINT;
name, objName : ARRAY 256 OF CHAR;
ch : CHAR;
BEGIN (* OutHunkData *)
(* OCG.TraceIn (mname, pname); *)
blockType := hunkData; Files.WriteBytes (out, blockType, 4);
pos1 := Files.Pos (out);
N := 0; Files.WriteBytes (out, N, 4);
numProcs := NumProcs (typ); INC (dataCount, SHORT(numProcs));
i := numProcs;
WHILE i > 0 DO Files.WriteBytes (out, N, 4); DEC (i) END;
N := typ.size; Files.WriteBytes (out, N, 4);
i := 0; N := 0;
WHILE i < 8 DO Files.WriteBytes (out, N, 4); INC (i) END;
INC (dataCount, 9);
N := -36; FindPtrs (typ, 0, N); Files.WriteBytes (out, N, 4);
IF typ.strobj # NIL THEN
COPY (OCT.ModuleName, name); nameLen := SYS.STRLEN (name);
name [nameLen] := "."; INC (nameLen);
OCT.GetName (typ.strobj.name, objName);
i := 0;
REPEAT
ch := objName [i]; name [nameLen] := ch;
INC (i); INC (nameLen)
UNTIL ch = 0X
ELSE
name := ""; nameLen := 1
END;
FOR i := 0 TO nameLen - 1 DO
Files.Write (out, name [i]);
END;
WHILE (nameLen MOD 4) # 0 DO
Files.Write (out, 0X); INC (nameLen)
END;
INC (dataCount, SHORT (nameLen DIV 4));
pos2 := Files.Pos (out);
Files.Set (out, ObjFile, pos1);
N := ((-N + nameLen) DIV 4) + numProcs + 1;
Files.WriteBytes (out, N, 4);
Files.Set (out, ObjFile, pos2);
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkData;
(*------------------------------------*)
PROCEDURE OutHunkExt (typ : OCT.Struct);
(* CONST pname = "OutHunkExt"; *)
VAR N, i : LONGINT; sym : OCT.Symbol;
BEGIN (* OutHunkExt *)
(* OCG.TraceIn (mname, pname); *)
N := hunkExt; Files.WriteBytes (out, N, 4);
i := numProcs;
WHILE i > 0 DO
sym := ProcSym (typ, i); OutName (extRef32, sym^);
N := 1; Files.WriteBytes (out, N, 4);
N := (numProcs - i) * 4; Files.WriteBytes (out, N, 4);
DEC (i)
END;
OutDef0 (typ.symbol^, numProcs * 4);
WHILE (typ # NIL) & (typ.n > 0) DO
OutName (extRef32, typ.symbol^);
N := 1; Files.WriteBytes (out, N, 4);
N := (numProcs + typ.n) * 4; Files.WriteBytes (out, N, 4);
typ := typ.BaseTyp
END;
N := 0; Files.WriteBytes (out, N, 4)
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkExt;
(*------------------------------------*)
PROCEDURE OutHunkSymbol (typ : OCT.Struct);
(* CONST pname = "OutHunkSymbol"; *)
VAR N, i : LONGINT; sym : OCT.Symbol;
BEGIN (* OutHunkSymbol *)
(* OCG.TraceIn (mname, pname); *)
IF Debug THEN
N := hunkSymbol; Files.WriteBytes (out, N, 4);
OutName (extSymb, typ.symbol^);
N := numProcs * 4; Files.WriteBytes (out, N, 4);
N := 0; Files.WriteBytes (out, N, 4)
END;
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkSymbol;
BEGIN (* OutTypeDescs *)
(* OCG.TraceIn (mname, pname); *)
dataCount := 0;
IF typex > 0 THEN
i := 0;
WHILE i < typex DO
OutHunkUnit ();
OutHunkName ();
OutHunkData (type [i]);
OutHunkExt (type [i]);
OutHunkSymbol (type [i]);
blockType := hunkEnd;
Files.WriteBytes (out, blockType, 4);
INC (i)
END
END
(* ;OCG.TraceOut (mname, pname); *)
END OutTypeDescs;
(*------------------------------------*)
PROCEDURE OutGC ();
(* CONST pname = "OutGC"; *)
VAR i : INTEGER;
(*------------------------------------*)
PROCEDURE OutHunkData ();
(* CONST pname = "OutHunkData"; *)
VAR i, N : LONGINT; obj : OCT.Object;
BEGIN (* OutHunkData *)
(* OCG.TraceIn (mname, pname); *)
N := hunkData; Files.WriteBytes (out, N, 4);
N := numPtrs + 3; Files.WriteBytes (out, N, 4);
N := 0; Files.WriteBytes (out, N, 4); Files.WriteBytes (out, N, 4);
N := -8; obj := OCT.topScope.right;
WHILE obj # NIL DO
IF obj.mode = Var THEN FindPtrs (obj.typ, obj.a0, N) END;
obj := obj.link
END;
Files.WriteBytes (out, N, 4);
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkData;
(*------------------------------------*)
PROCEDURE OutHunkExt ();
(* CONST pname = "OutHunkExt"; *)
VAR N : LONGINT;
BEGIN (* OutHunkExt *)
(* OCG.TraceIn (mname, pname); *)
N := hunkExt; Files.WriteBytes (out, N, 4);
OutDef0 (OCT.GCSymbol^, 0);
OutName (extRef32, OCT.VarSymbol^);
N := 1; Files.WriteBytes (out, N, 4);
N := 4; Files.WriteBytes (out, N, 4);
N := 0; Files.WriteBytes (out, N, 4)
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkExt;
(*------------------------------------*)
PROCEDURE OutHunkSymbol ();
(* CONST pname = "OutHunkSymbol"; *)
BEGIN (* OutHunkSymbol *)
(* OCG.TraceIn (mname, pname); *)
IF Debug THEN
blockType := hunkSymbol; Files.WriteBytes (out, blockType, 4);
OutName (extSymb, OCT.GCSymbol^);
N := 0; Files.WriteBytes (out, N, 4);
Files.WriteBytes (out, N, 4);
END;
(* ;OCG.TraceOut (mname, pname); *)
END OutHunkSymbol;
BEGIN (* OutGC *)
(* OCG.TraceIn (mname, pname); *)
IF numPtrs > 0 THEN
OutHunkUnit ();
OutHunkName ();
OutHunkData ();
OutHunkExt ();
OutHunkSymbol ();
blockType := hunkEnd;
Files.WriteBytes (out, blockType, 4);
END
(* ;OCG.TraceOut (mname, pname); *)
END OutGC;
(*------------------------------------*)
PROCEDURE OutVars ();
(* CONST pname = "OutVars"; *)
BEGIN (* OutVars *)
(* OCG.TraceIn (mname, pname); *)
OutHunkUnit ();
OutHunkName ();
blockType := hunkBSS;
Files.WriteBytes (out, blockType, 4);
N := (datasize + 3) DIV 4;
Files.WriteBytes (out, N, 4);
blockType := hunkExt;
Files.WriteBytes (out, blockType, 4);
OutDef0 (OCT.VarSymbol^, 0);
N := 0; Files.WriteBytes (out, N, 4);
IF Debug THEN
blockType := hunkSymbol; Files.WriteBytes (out, blockType, 4);
OutName (extSymb, OCT.VarSymbol^);
N := 0; Files.WriteBytes (out, N, 4);
Files.WriteBytes (out, N, 4);
END;
blockType := hunkEnd;
Files.WriteBytes (out, blockType, 4);
(* ;OCG.TraceOut (mname, pname); *)
END OutVars;
(* $D- disable copying of open arrays *)
BEGIN (* OutCode *)
(* OCG.TraceIn (mname, pname); *)
(*IF ~OCS.scanerr THEN*)
ObjFile := Files.New (FName);
IF ObjFile # NIL THEN
Files.Set (out, ObjFile, 0);
codeHunk := FirstCodeHunk;
WHILE codeHunk # NIL DO
OutCodeHunk (codeHunk);
codeHunk := codeHunk.next;
END; (* WHILE *)
OutConstants ();
OutTypeDescs ();
IF OCS.garbageCollect THEN OutGC () END;
OutVars ();
IF ObjFile.dosError = 0 THEN Files.Register (ObjFile)
ELSE OCS.Mark (153); Files.Purge (ObjFile)
END;
ELSE
OCS.Mark (153)
END
(*END; (* IF *)*)
(* ;OCG.TraceOut (mname, pname); *)
END OutCode;
(*------------------------------------*)
PROCEDURE DataSize * () : LONGINT;
(* CONST pname = "DataSize"; *)
VAR size : LONGINT;
BEGIN (* DataSize *)
(* OCG.TraceIn (mname, pname); *)
size := dataCount * 4 + conx;
(* ;OCG.TraceOut (mname, pname); *)
RETURN size;
END DataSize;
BEGIN (* OCC *)
FirstCodeHunk := NIL; CurrCodeHunk := NIL; InitCodeHunk := NIL;
Prologue := NIL; NEW (wasderef); Debug := FALSE
END OCC.
(***************************************************************************
$Log: OCC.mod $
Revision 4.10 1994/08/03 11:40:04 fjc
- Changed error numbers.
Revision 4.9 1994/07/26 18:32:21 fjc
*** empty log message ***
Revision 4.8 1994/07/25 00:47:09 fjc
- Declared StackCheck.
Revision 4.7 1994/07/23 15:56:12 fjc
- Exported AllRegs and ScratchRegs.
- Changed SaveRegisters() to take a mask parameter and
correctly handle system registers (A4 & A5).
- Changed RestoreRegisters() to handle system registers.
Revision 4.6 1994/07/22 14:06:00 fjc
- Changed to support FProc objects.
- Changed to use long adressing when A4 is reserved.
Revision 4.5 1994/07/10 13:02:02 fjc
- Commented out trace code.
- Added check for $G switch before outputting GC data.
Revision 4.4 1994/06/17 17:44:00 fjc
- Changed to append type names to descriptors
Revision 4.3 1994/06/10 13:01:18 fjc
- Implemented ConcatString().
Revision 4.2 1994/06/05 22:37:36 fjc
- Changed to use new symbol table format.
Revision 4.1 1994/06/01 09:33:44 fjc
- Bumped version number
***************************************************************************)