home *** CD-ROM | disk | FTP | other *** search
- (*************************************************************************
-
- $RCSfile: OCI.mod $
- Description: Common routines used by modules OCE, OCP, OCH and Compiler
-
- Created by: fjc (Frank Copeland)
- $Revision: 5.17 $
- $Author: fjc $
- $Date: 1995/06/02 18:38:40 $
-
- Copyright © 1993-1995, 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.
-
- *************************************************************************)
-
- <* STANDARD- *> <* MAIN- *> <*$ LongVars+ *>
-
- MODULE OCI;
-
- IMPORT OCM, OCS, OCT, OCC;
-
- (* --- Local declarations --------------------------------------------- *)
-
- CONST
-
- (* object modes *)
-
- Var = OCM.Var; VarR = OCM.VarR; VarX = OCM.VarX; Ind = OCM.Ind;
- IndR = OCM.IndR; IndX = OCM.IndX; RegI = OCM.RegI; RegX = OCM.RegX;
- Lab = OCM.Lab; LabI = OCM.LabI; Con = OCM.Con; Push = OCM.Push;
- Pop = OCM.Pop; Coc = OCM.Coc; Reg = OCM.Reg; Fld = OCM.Fld;
- Typ = OCM.Typ; Abs = OCM.Abs; XProc = OCM.XProc; LProc = OCM.LProc;
- Undef = OCM.Undef; CallBack = OCM.CallBack;
-
- addressableSet =
- { Var, VarX, Ind, IndR, IndX, Reg, RegI, RegX, Con, XProc, LProc,
- CallBack };
-
- (* structure forms *)
-
- Char = OCT.Char; DynArr = OCT.DynArr; String = OCT.String;
- TagTyp = OCT.TagTyp;
-
- (* 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;
-
- (* --- Procedure declarations ------------------------------------------- *)
-
- (*------------------------------------*)
- (*
- Explicitly frees any registers used by x
- *)
- PROCEDURE Unload * (VAR x : OCT.Item);
-
- BEGIN (* Unload *)
- IF x.mode IN {VarX, IndX, Reg, RegI, RegX, Push, Pop} THEN
- OCC.FreeReg (x);
- END
- END Unload;
-
- (*------------------------------------*)
- PROCEDURE Load * (VAR x : OCT.Item);
-
- VAR y : OCT.Item;
-
- BEGIN (* Load *)
- IF x.mode < Reg THEN
- IF OCC.InDataReg (x.obj) THEN OCC.GetDReg (x, x.obj)
- ELSE
- y := x; OCC.GetDReg (x, x.obj); OCC.Move (y.typ.size, y, x);
- Unload (y)
- END;
- ELSIF x.mode > Reg THEN OCS.Mark (126)
- END
- END Load;
-
- (*------------------------------------*)
- PROCEDURE EXT * (size, reg : LONGINT);
-
- BEGIN (* EXT *)
- (* OCM.TraceIn (mname, pname); *)
- IF size = L THEN OCC.PutWord (OCC.EXTL + reg)
- ELSE OCC.PutWord (OCC.EXTW + reg)
- END
- END EXT;
-
- (*------------------------------------*)
- PROCEDURE DescItem * (VAR item : OCT.Item; desc : OCT.Desc; adr : LONGINT);
-
- BEGIN (* DescItem *)
- 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, VarR, VarX} THEN INC (item.a0, adr)
- ELSIF item.mode IN {Ind, IndR, IndX, RegI, RegX} THEN INC (item.a1, adr)
- ELSE OCS.Mark (322)
- END
- END;
- item.desc := desc; item.typ := OCT.linttyp; item.wordIndex := FALSE
- END DescItem;
-
- (*------------------------------------*)
- PROCEDURE UpdateDesc * (VAR x : OCT.Item; adr : LONGINT);
-
- VAR desc : OCT.Desc;
-
- BEGIN (* UpdateDesc *)
- 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, IndR, IndX, RegI, RegX} THEN DEC (desc.a1, adr)
- ELSE OCS.Mark (322)
- END
- END
- END UpdateDesc;
-
- (*------------------------------------*)
- PROCEDURE UnloadDesc * (VAR x : OCT.Item);
-
- VAR desc : OCT.Desc; reg : OCT.Item;
-
- BEGIN (* UnloadDesc *)
- desc := x.desc;
- IF desc # NIL THEN
- IF desc.mode IN {VarX, IndX, RegI, RegX} THEN
- IF desc.mode # x.mode THEN
- DescItem (reg, desc, 0); OCC.FreeReg (reg)
- ELSE
- reg.mode := Reg;
- IF desc.mode IN {RegI, RegX} THEN
- IF desc.a0 # x.a0 THEN reg.a0 := desc.a0; OCC.FreeReg (reg) END
- END;
- IF desc.mode IN {VarX, IndX, RegX} THEN
- IF desc.a2 # x.a2 THEN reg.a0 := desc.a2; OCC.FreeReg (reg) END
- END;
- END
- END;
- desc.mode := Undef
- END;
- END UnloadDesc;
-
- (*------------------------------------*)
- PROCEDURE Adr * (VAR x : OCT.Item);
-
- VAR
- reg, len, y : OCT.Item; module : OCT.Module; off : LONGINT;
- dreg : INTEGER; wordIndex : BOOLEAN; desc : OCT.Desc;
-
- (*------------------------------------*)
- PROCEDURE Multiply (VAR lhs, rhs : OCT.Item);
-
- VAR R : OCC.RegState;
-
- BEGIN (* Multiply *)
- OCC.LoadRegParams2 (R, lhs, rhs);
- OCC.CallKernel (OCC.kMul32);
- OCC.RestoreRegisters (R, lhs);
- Unload (rhs)
- END Multiply;
-
- BEGIN (* Adr *)
- IF x.mode IN addressableSet THEN
- IF x.mode = Con THEN
- IF (x.typ # OCT.stringtyp) & (x.typ # OCT.tagtyp) THEN
- OCS.Mark (127)
- ELSE
- IF (x.typ = OCT.stringtyp) & (x.a1 < 3) THEN
- OCC.AllocStringFromChar (x)
- END;
- IF OCM.SmallData THEN
- y := x; OCC.GetAReg (x, NIL);
- OCC.PutF2 (OCC.LEA, y, x.a0); Unload (y)
- ELSE
- x.mode := LabI; x.a1 := L
- END
- END
- 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 = Var THEN
- y := x; OCC.GetAReg (x, NIL);
- OCC.PutF2 (OCC.LEA, y, x.a0); Unload (y)
- ELSIF x.mode = Ind THEN
- IF x.a1 = 0 THEN
- x.mode := Var
- ELSE
- y := x; OCC.GetAReg (x, NIL);
- OCC.PutF2 (OCC.LEA, y, x.a0); Unload (y)
- END
- ELSIF x.mode IN {VarX, IndX, RegX} THEN
- y := x; desc := x.desc;
- OCC.GetAReg (x, NIL); x.desc := desc;
- OCC.PutF2 (OCC.LEA, y, x.a0); Unload (y)
- ELSIF x.mode = RegI THEN
- IF x.a1 # 0 THEN
- y := x; OCC.GetAReg (x, NIL);
- OCC.PutF2 (OCC.LEA, y, x.a0); Unload (y)
- END;
- x.mode := Reg
- ELSIF x.mode IN {LProc, XProc, CallBack} THEN
- x.mode := LabI; x.a0 := 0; x.a1 := L; x.label := x.obj.label
- END;
- IF x.mode = Reg THEN x.a1 := 0; x.a2 := 0; x.obj := NIL END
- ELSE
- OCS.Mark (127)
- END
- END Adr;
-
- (*------------------------------------*)
- PROCEDURE LoadAdr * (VAR x : OCT.Item);
-
- VAR y : OCT.Item;
-
- BEGIN (* LoadAdr *)
- Adr (x);
- IF x.mode # Reg THEN
- y := x; OCC.GetAReg (x, NIL); OCC.Move (L, y, x)
- END;
- x.mode := RegI; x.a1 := 0; x.a2 := 0; x.obj := NIL
- END LoadAdr;
-
- (*------------------------------------*)
- (*
- Move the address of a variable, procedure or string constant to the
- specified location.
- *)
- PROCEDURE MoveAdr * (VAR x, y : OCT.Item);
-
- VAR
- z : OCT.Item; module : OCT.Object; off, reg : LONGINT;
- wordIndex : BOOLEAN;
-
- BEGIN (* MoveAdr *)
- IF x.mode IN addressableSet THEN
- 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
- off := x.a1; reg := x.a2; wordIndex := x.wordIndex;
- z := x; z.mode := Var; OCC.Move (L, z, y);
- z.mode := RegX; z.a0 := y.a0; z.a1 := off; z.a2 := reg;
- z.wordIndex := wordIndex;
- OCC.PutF2 (OCC.LEA, z, y.a0)
- ELSIF x.mode IN {LProc, XProc, CallBack} THEN
- x.mode := Lab; x.a0 := 0; x.a1 := L; x.label := x.obj.label;
- 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
- END MoveAdr;
-
- (*------------------------------------*)
- (*
- Copies count bytes from src to dst and then terminates dst with a NUL.
- *)
- PROCEDURE CopyString * ( VAR src, dst, count : OCT.Item );
-
- VAR x : OCT.Item; L0 : INTEGER; i : LONGINT;
-
- BEGIN (* CopyString *)
- IF (count.mode = Con) & (count.a0 < 5) THEN (* inline the loop *)
- IF count.a0 = 1 THEN
- LoadAdr (dst); dst.mode := Pop; (* LEA <dst>,Ad *)
- OCC.ForgetReg (dst.a0);
- 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 *)
- OCC.ForgetReg (src.a0); OCC.ForgetReg (dst.a0);
- 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 *)
- OCC.ForgetReg (src.a0); OCC.ForgetReg (dst.a0);
-
- IF (count.mode = Con) & (count.a0 < 65536) THEN
- count.typ := OCT.inttyp; DEC (count.a0);
- Load (count); (* MOVE.W <count>,Dc *)
- OCC.Move (B, src, dst); (* 1$ MOVE.B (As)+,(Ad)+ *)
- OCC.PutWord (OCC.DBEQ + count.a0);
- OCC.PutWord (-4); (* DBEQ.W Dc, 1$ *)
- OCC.PutWord (6702H) (* BEQ.S 3$ *)
- ELSIF count.mode = Con THEN
- DEC (count.a0); Load (count); (* MOVE.L <count>,Dc *)
- OCC.Move (B, src, dst); (* 1$ MOVE.B (As)+,(Ad)+ *)
- OCC.PutWord (6706H); (* BEQ.S 3$ *)
- OCC.PutF7 (OCC.SUBQ, L, 1, count); (* SUBQ.L #1,Dc *)
- OCC.PutWord (66F8H) (* BNE 1$ *)
- ELSE
- Load (count); (* MOVE.L <count>,Dc *)
- OCC.PutF7 (OCC.SUBQ, L, 1, count); (* 1$ SUBQ.L #1,Dc *)
- OCC.PutWord (6706H); (* BEQ.S 2$ *)
- OCC.Move (B, src, dst); (* MOVE.B (As)+,(Ad)+ *)
- OCC.PutWord (66F8H); (* BNE.S 1$ *)
- OCC.PutWord (6002H) (* BRA.S 3$ *)
- END;
- dst.mode := RegI;
- OCC.PutF1 (OCC.CLR, B, dst) (* 2$ CLR.B <dst> *)
- END; (* 3$ *)
- END CopyString;
-
- (*------------------------------------*)
- (*
- Compares src and dst, selecting the correct instruction for the operand
- types.
- *)
- PROCEDURE CMP* ( size : LONGINT; VAR src, dst : OCT.Item );
-
- VAR
-
- BEGIN (* CMP *)
- IF (src.mode = Con) THEN
- IF (OCM.SmallData & (src.typ.form IN {String, TagTyp}))
- OR (dst.mode = Con)
- THEN
- Load (dst)
- END
- ELSIF dst.mode # Reg THEN
- Load (dst)
- END;
- IF dst.mode = Reg THEN
- OCC.PutF5 (OCC.CMP, size, src, dst)
- ELSE
- OCC.PutF6 (OCC.CMPI, size, src, dst)
- END;
- Unload (dst)
- END CMP;
-
- END OCI.
-
- (*************************************************************************
-
- $Log: OCI.mod $
- Revision 5.17 1995/06/02 18:38:40 fjc
- - Various changes to implement the SMALLDATA and RESIDENT
- options.
- - Added CMP procedure.
-
- Revision 5.16 1995/05/13 23:05:18 fjc
- - Converted INTEGER to LONGINT where necessary.
-
- Revision 5.15 1995/05/08 17:05:12 fjc
- - Minor corrections.
-
- Revision 5.13 1995/03/25 17:05:01 fjc
- - Fixed problems in UnloadDesc().
-
- Revision 5.12 1995/03/23 18:12:30 fjc
- - FreeDesc() now calls FreeReg instead of emulating it.
- - Cleaned up Adr().
-
- Revision 5.11 1995/03/13 11:30:26 fjc
- - Minor fixes to register allocation.
-
- Revision 5.10 1995/03/09 19:09:21 fjc
- - Incorporated changes from 5.22.
-
- Revision 5.9 1995/02/27 17:01:02 fjc
- - Removed tracing code.
- - Changed to use new register handling procedures.
-
- Revision 5.8.1.1 1995/03/08 18:59:09 fjc
- - OC 5.22
-
- Revision 5.8 1995/01/26 00:17:17 fjc
- - Release 1.5
-
- Revision 5.6 1995/01/03 21:21:29 fjc
- - Changed OCG to OCM.
-
- Revision 5.5 1994/12/16 17:20:24 fjc
- - Changed Symbol to Label.
-
- Revision 5.4 1994/10/23 16:08:14 fjc
- - Fixed register allocation bug in UnloadDesc().
- - Changed Multiply() to use OCC.CallKernel().
-
- Revision 5.3 1994/09/25 17:47:18 fjc
- - Changed to reflect new object modes and system flags.
-
- Revision 5.2 1994/09/15 10:27:13 fjc
- - Replaced switches with pragmas.
-
- Revision 5.1 1994/09/03 19:29:08 fjc
- - Bumped version number
-
- *************************************************************************)
-