home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 2
/
goldfish_vol2_cd1.bin
/
files
/
dev
/
obero
/
oberon-a
/
source
/
oc
/
oci.mod
< prev
next >
Wrap
Text File
|
1994-08-08
|
13KB
|
423 lines
(***************************************************************************
$RCSfile: OCI.mod $
Description: Common routines used by modules OCE, OCP, OCH and Compiler
Created by: fjc (Frank Copeland)
$Revision: 4.6 $
$Author: fjc $
$Date: 1994/08/03 11:41:38 $
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 OCI;
(*
** $C= CaseChk $I= IndexChk $L+ LongAdr $N= NilChk
** $P- PortableCode $R= RangeChk $S= StackChk $T= TypeChk
** $V= OvflChk $Z= ZeroVars
*)
IMPORT OCG, OCS, OCT, OCC;
(* --- Local declarations ----------------------------------------------- *)
CONST
(* 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; Con = OCG.Con; Push = OCG.Push;
Pop = OCG.Pop; Coc = OCG.Coc; Reg = OCG.Reg; Fld = OCG.Fld;
Typ = OCG.Typ; Abs = OCG.Abs; XProc = OCG.XProc; LProc = OCG.LProc;
Undef = OCG.Undef; FProc = OCG.FProc;
regSet = {VarR, IndR, Reg};
addressableSet =
{Var, VarX, Ind, IndX, Reg, RegI, RegX, Con, XProc, LProc, FProc};
(* structure forms *)
Char = OCT.Char; DynArr = OCT.DynArr;
(* CPU Registers *)
D0 = 0; D1 = 1; D7 = 7; A0 = 8; 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};
(* Data sizes *)
B = 1; W = 2; L = 4;
(* CONST mname = "OCI"; *)
(* --- Procedure declarations ------------------------------------------- *)
(*------------------------------------*)
PROCEDURE IsParam * (obj : OCT.Object) : BOOLEAN;
BEGIN (* IsParam *)
RETURN (obj # NIL) & (obj.mode <= IndR) & (obj.a0 >= 0)
END IsParam;
(*------------------------------------*)
(*
Explicitly frees any registers used by x
*)
PROCEDURE Unload * (VAR x : OCT.Item);
(* CONST pname = "Unload"; *)
BEGIN (* Unload *)
(* OCG.TraceIn (mname, pname); *)
IF x.mode IN {VarX, IndX, Reg, RegI, RegX, Push, Pop} THEN
OCC.FreeReg (x);
END
(* ;OCG.TraceOut (mname, pname); *)
END Unload;
(*------------------------------------*)
PROCEDURE Load * (VAR x : OCT.Item);
(* CONST pname = "Load"; *)
VAR y : OCT.Item;
BEGIN (* Load *)
(* OCG.TraceIn (mname, pname); *)
IF x.mode < Reg THEN
y := x; OCC.GetDReg (x); OCC.Move (y.typ.size, y, x); Unload (y)
ELSIF x.mode > Reg THEN
OCS.Mark (126)
END
(* ;OCG.TraceOut (mname, pname); *)
END Load;
(*------------------------------------*)
PROCEDURE EXT * (size, reg : LONGINT);
(* CONST pname = "EXT"; *)
BEGIN (* EXT *)
(* OCG.TraceIn (mname, pname); *)
IF size = L THEN OCC.PutWord (OCC.EXTL + SHORT (reg))
ELSE OCC.PutWord (OCC.EXTW + SHORT (reg))
END
(* ;OCG.TraceOut (mname, pname); *)
END EXT;
(*------------------------------------*)
PROCEDURE DescItem * (VAR item : OCT.Item; desc : OCT.Desc; adr : LONGINT);
(* CONST pname = "DescItem"; *)
BEGIN (* DescItem *)
(* OCG.TraceIn (mname, pname); *)
IF desc = NIL THEN
OCS.Mark (963);
item.lev := 0; item.mode := Var;
item.a0 := 0; item.a1 := 0; item.a2 := 0
ELSE
(* item = bound descr *)
item.lev := desc.lev; item.mode := desc.mode; item.a0 := desc.a0;
item.a1 := desc.a1; item.a2 := desc.a2;
IF item.mode IN {Var, VarX} THEN INC (item.a0, adr)
ELSIF item.mode IN {Ind, IndX, RegI, RegX} THEN INC (item.a1, adr)
ELSE OCS.Mark (322)
END
END;
item.desc := desc; item.typ := OCT.linttyp
(* ;OCG.TraceOut (mname, pname); *)
END DescItem;
(*------------------------------------*)
PROCEDURE UpdateDesc * (VAR x : OCT.Item; adr : LONGINT);
(* CONST pname = "UpdateDesc"; *)
VAR desc : OCT.Desc;
BEGIN (* UpdateDesc *)
(* OCG.TraceIn (mname, pname); *)
desc := x.desc;
IF desc # NIL THEN
desc.lev := x.lev; desc.mode := x.mode; desc.a0 := x.a0;
desc.a1 := x.a1; desc.a2 := x.a2;
IF desc.mode IN {Var, VarX} THEN DEC (desc.a0, adr)
ELSIF desc.mode IN {Ind, IndX, RegI, RegX} THEN DEC (desc.a1, adr)
ELSE OCS.Mark (322)
END
END
(* ;OCG.TraceOut (mname, pname); *)
END UpdateDesc;
(*------------------------------------*)
PROCEDURE UnloadDesc * (VAR x : OCT.Item);
(* CONST pname = "UnloadDesc"; *)
VAR desc : OCT.Desc;
BEGIN (* UnloadDesc *)
(* OCG.TraceIn (mname, pname); *)
desc := x.desc;
IF (desc # NIL) & (desc.mode IN {VarX, IndX, RegI, RegX}) THEN
IF desc.mode # x.mode THEN
IF desc.mode IN {RegI, RegX} THEN
OCC.UnReserveReg (SHORT (desc.a0))
END;
IF desc.mode IN {VarX, IndX, RegX} THEN
OCC.UnReserveReg (SHORT (desc.a1))
END
ELSE
IF desc.mode IN {RegI, RegX} THEN
IF desc.a0 # x.a0 THEN OCC.UnReserveReg (SHORT (desc.a0)) END
END;
IF desc.mode IN {VarX, IndX, RegX} THEN
IF desc.a2 # x.a2 THEN OCC.UnReserveReg (desc.a2) END
END;
END
END
(* ;OCG.TraceOut (mname, pname); *)
END UnloadDesc;
(*------------------------------------*)
PROCEDURE Adr * (VAR x : OCT.Item);
(* CONST pname = "Adr"; *)
VAR
reg, len, y : OCT.Item; module : OCT.Module; off : LONGINT;
dreg : INTEGER;
(*------------------------------------*)
PROCEDURE Multiply (VAR lhs, rhs : OCT.Item);
(* CONST pname = "Multiply"; *)
VAR mul : OCT.Item; R : SET;
BEGIN (* Multiply *)
(* OCG.TraceIn (mname, pname); *)
mul.mode := Lab; mul.a0 := 0; mul.a1 := 4;
mul.symbol := OCT.OberonSysMUL;
OCC.LoadRegParams2 (R, lhs, rhs);
OCC.PutF3 (OCC.JSR, mul);
OCC.RestoreRegisters (R, lhs);
Unload (rhs)
(* ;OCG.TraceOut (mname, pname); *)
END Multiply;
BEGIN (* Adr *)
(* OCG.TraceIn (mname, pname); *)
IF x.mode IN addressableSet THEN
IF (x.mode = Con) & (x.typ # OCT.stringtyp) THEN OCS.Mark (127)
ELSIF x.typ.form = DynArr THEN
len.mode := Undef;
IF x.mode IN {IndX, RegX} THEN
reg.mode := Reg; reg.a0 := x.a2; reg.typ := OCT.linttyp;
END;
WHILE x.typ.form = DynArr DO
IF x.mode IN {IndX, RegX} THEN
DescItem (len, x.desc, x.typ.adr); Multiply (reg, len)
END;
x.typ := x.typ.BaseTyp
END;
Unload (len);
IF x.mode = Var THEN x.mode := Ind; x.a1 := 0 END;
Adr (x)
ELSIF x.mode = Reg THEN
IF x.a0 IN DataRegs THEN OCS.Mark (127) END
ELSIF x.mode = Con THEN
IF x.a1 < 3 THEN OCC.AllocStringFromChar (x) END;
x.mode := LabI; x.a1 := 4
ELSIF x.mode = Var THEN
y := x; OCC.GetAReg (x); OCC.PutF2 (OCC.LEA, y, x.a0); Unload (y)
ELSIF x.mode = VarX THEN
dreg := x.a2; y := x; y.mode := Var; y.a2 := 0;
OCC.GetAReg (x); OCC.PutF2 (OCC.LEA, y, x.a0); Unload (y);
y.mode := RegX; y.a0 := x.a0; y.a1 := 0; y.a2 := dreg;
OCC.PutF2 (OCC.LEA, y, x.a0); OCC.UnReserveReg (dreg)
ELSIF x.mode = Ind THEN
IF x.a1 = 0 THEN x.mode := Var
ELSE
y := x; y.mode := Var; OCC.GetAReg (reg); reg.desc := x.desc;
OCC.Move (L, y, reg); Unload (y);
y.mode := RegI; y.a0 := reg.a0; y.a1 := x.a1; x := reg;
OCC.PutF2 (OCC.LEA, y, x.a0)
END
ELSIF x.mode = IndX THEN
off := x.a1; dreg := x.a2; y := x; y.mode := Var; y.a2 := 0;
OCC.GetAReg (x); OCC.Move (L, y, x); Unload (y);
IF off # 0 THEN
y.mode := RegI; y.a0 := x.a0; y.a1 := off;
OCC.PutF2 (OCC.LEA, y, x.a0)
END;
y.mode := RegX; y.a0 := x.a0; y.a1 := 0; y.a2 := dreg;
OCC.PutF2 (OCC.LEA, y, x.a0); OCC.UnReserveReg (dreg);
x.mode := Reg
ELSIF x.mode = RegI THEN
IF x.a1 # 0 THEN OCC.PutF2 (OCC.LEA, x, x.a0) END;
x.mode := Reg; x.a1 := 0
ELSIF x.mode = RegX THEN
y := x; x.mode := Reg; x.a1 := 0; x.a2 := 0;
OCC.PutF2 (OCC.LEA, y, x.a0); OCC.UnReserveReg (y.a2)
ELSIF x.mode IN {LProc, XProc, FProc} THEN
x.mode := LabI; x.a0 := 0; x.a1 := 4; x.symbol := x.obj.symbol
END;
IF x.mode = Reg THEN x.a1 := 0; x.a2 := 0; x.obj := NIL END
ELSE
OCS.Mark (127)
END
(* ;OCG.TraceOut (mname, pname); *)
END Adr;
(*------------------------------------*)
PROCEDURE LoadAdr * (VAR x : OCT.Item);
(* CONST pname = "LoadAdr"; *)
VAR y : OCT.Item;
BEGIN (* LoadAdr *)
(* OCG.TraceIn (mname, pname); *)
Adr (x);
IF x.mode # Reg THEN y := x; OCC.GetAReg (x); OCC.Move (L, y, x) END;
x.mode := RegI; x.a1 := 0; x.a2 := 0; x.obj := NIL
(* ;OCG.TraceOut (mname, pname); *)
END LoadAdr;
(*------------------------------------*)
(*
Move the address of a variable, procedure or string constant to the
specified location.
*)
PROCEDURE MoveAdr * (VAR x, y : OCT.Item);
(* CONST pname = "MoveAdr"; *)
VAR z : OCT.Item; module : OCT.Object;
BEGIN (* MoveAdr *)
(* OCG.TraceIn (mname, pname); *)
IF x.mode IN addressableSet THEN
IF (y.mode = VarR) OR (y.mode = IndR) THEN y.mode := Reg END;
IF x.mode = Reg THEN
IF x.a0 < A0 THEN OCS.Mark (127)
ELSE OCC.Move (L, x, y)
END
ELSIF (y.mode = Reg) & (y.a0 >= A0) THEN
IF x.typ.form = DynArr THEN Adr (x); OCC.Move (L, x, y)
ELSIF x.mode = Reg THEN OCC.Move (L, x, y)
ELSIF x.mode = Ind THEN
z := x; z.mode := Var; OCC.Move (L, z, y);
IF z.a1 # 0 THEN
z.mode := RegI; z.a0 := y.a0; OCC.PutF2 (OCC.LEA, z, y.a0)
END
ELSIF x.mode = IndX THEN
z := x; z.mode := Var; OCC.Move (L, z, y);
z.mode := RegX; z.a0 := y.a0; OCC.PutF2 (OCC.LEA, z, y.a0)
ELSIF x.mode IN {LProc, XProc, FProc} THEN
x.mode := Lab; x.a0 := 0; x.a1 := 4; x.symbol := x.obj.symbol;
OCC.PutF2 (OCC.LEA, x, y.a0)
ELSE
OCC.PutF2 (OCC.LEA, x, y.a0)
END
ELSE
Adr (x); OCC.Move (L, x, y)
END
ELSE
OCS.Mark (127)
END
(* ;OCG.TraceOut (mname, pname); *)
END MoveAdr;
(*------------------------------------*)
(*
Copies count bytes from src to dst and then terminates dst with a NUL.
*)
PROCEDURE CopyString *
( VAR src, dst, count : OCT.Item );
(* CONST pname = "CopyString"; *)
VAR x : OCT.Item; L0 : INTEGER; i : LONGINT;
BEGIN (* CopyString *)
(* OCG.TraceIn (mname, pname); *)
IF (count.mode = Con) & (count.a0 < 5) THEN (* inline the loop *)
IF count.a0 = 1 THEN
LoadAdr (dst); dst.mode := Pop; (* LEA <dst>,Ad *)
IF src.mode = Con THEN src.a0 := src.a2; src.typ := OCT.chartyp END;
OCC.Move (B, src, dst); (* MOVE.B <src>,(Ad)+ *)
dst.mode := RegI
ELSIF count.a0 > 1 THEN
LoadAdr (src); src.mode := Pop; (* LEA <src>,As *)
LoadAdr (dst); dst.mode := Pop; (* LEA <dst>,Ad *)
i := count.a0;
WHILE i > 0 DO
OCC.Move (B, src, dst); (* MOVE.B (As),(Ad)+ *)
DEC (i)
END;
dst.mode := RegI
ELSE (* src is an empty string *)
IF (dst.typ.form = DynArr) & (dst.mode IN {IndX, RegX}) THEN
LoadAdr (dst) (* LEA <dst>,Ad *)
END
END;
OCC.PutF1 (OCC.CLR, B, dst) (* CLR.B <dst> *)
ELSE
LoadAdr (src); src.mode := Pop; (* LEA <src>,As *)
LoadAdr (dst); dst.mode := Pop; (* LEA <dst>,Ad *)
IF count.mode = Con THEN
IF count.a0 > 32767 THEN OCS.Mark (63); count.a0 := 1 END;
count.typ := OCT.inttyp; DEC (count.a0);
Load (count); (* MOVE.L <count>,Dc *)
ELSE
Load (count); (* MOVE.L <count>,Dc *)
OCC.PutF7 (OCC.SUBQ, L, 1, count); (* SUBQ.L #1,Dc *)
OCC.PutWord (6002H); (* BRA.S 2$ *)
END; (* IF *)
OCC.Move (B, src, dst); (* 1$ MOVE.B (As)+,(Ad)+ *)
OCC.PutWord (OCC.DBEQ + SHORT (count.a0));
OCC.PutWord (-4); (* 2$ DBEQ.W Dc, 1$ *)
OCC.PutWord (6702H); (* BEQ.S 3$ *)
dst.mode := RegI; OCC.PutF1 (OCC.CLR, B, dst)(* CLR.B <dst> *)
END; (* 3$ *)
(* ;OCG.TraceOut (mname, pname); *)
END CopyString;
END OCI.
(***************************************************************************
$Log: OCI.mod $
Revision 4.6 1994/08/03 11:41:38 fjc
- Changed error numbers.
Revision 4.5 1994/07/26 18:33:40 fjc
*** empty log message ***
Revision 4.4 1994/07/22 14:07:58 fjc
- Changed to support FProc objects.
Revision 4.3 1994/07/10 13:08:14 fjc
- Commented out trace code.
- Fixed register allocation bug in MoveAdr().
Revision 4.1 1994/06/01 09:33:44 fjc
- Bumped version number
***************************************************************************)