home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-06-29 | 63.5 KB | 1,953 lines |
- (*************************************************************************
-
- $RCSfile: OCH.mod $
- Description: Code selection for statements
-
- Created by: fjc (Frank Copeland)
- $Revision: 5.25 $
- $Author: fjc $
- $Date: 1995/06/15 18:15:13 $
-
- Copyright © 1990-1993, ETH Zuerich
- 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 OCH;
-
- IMPORT SYS := SYSTEM, OCM, OCS, OCT, OCC, OCI, OCE, str := Strings;
-
- (* --- Exported declarations ------------------------------------------ *)
-
-
- TYPE
- LabelRange * = RECORD
- low *, high *, label * : LONGINT
- END; (* LabelRange *)
-
-
- (* --- Local declarations --------------------------------------------- *)
-
-
- CONST
-
- (* Symbols *)
-
- null = OCS.null; times = OCS.times; slash = OCS.slash; div = OCS.div;
- mod = OCS.mod; and = OCS.and; plus = OCS.plus; minus = OCS.minus;
- or = OCS.or; eql = OCS.eql; neq = OCS.neq; lss = OCS.lss;
- leq = OCS.leq; gtr = OCS.gtr; geq = OCS.geq; not = OCS.not;
-
- (* object modes *)
- Var = OCM.Var; VarX = OCM.VarX; Ind = OCM.Ind; IndX = OCM.IndX;
- RegI = OCM.RegI; RegX = OCM.RegX; Lab = OCM.Lab; LabI = OCM.LabI;
- Abs = OCM.Abs; Con = OCM.Con; Push = OCM.Push; Pop = OCM.Pop;
- Coc = OCM.Coc; Reg = OCM.Reg; Fld = OCM.Fld; LProc = OCM.LProc;
- XProc = OCM.XProc; TProc = OCM.TProc; AProc = OCM.AProc; Mod = OCM.Mod;
- RList = OCM.RList; VarArg = OCM.VarArg; LibCall = OCM.LibCall;
- M2Proc = OCM.M2Proc; CProc = OCM.CProc; Typ = OCM.Typ;
-
- (* System flags *)
-
- OberonFlag = OCM.OberonFlag; M2Flag = OCM.M2Flag; CFlag = OCM.CFlag;
- BCPLFlag = OCM.BCPLFlag; AsmFlag = OCM.AsmFlag;
-
- (* structure forms *)
- Undef = OCT.Undef; Byte = OCT.Byte; Bool = OCT.Bool; Char = OCT.Char;
- SInt = OCT.SInt; Int = OCT.Int; LInt = OCT.LInt; Real = OCT.Real;
- LReal = OCT.LReal; Set = OCT.Set; String = OCT.String;
- NilTyp = OCT.NilTyp; NoTyp = OCT.NoTyp; Pointer = OCT.Pointer;
- ProcTyp = OCT.ProcTyp; Array = OCT.Array; DynArr = OCT.DynArr;
- Record = OCT.Record; BSet = OCT.BSet; WSet = OCT.WSet;
- PtrTyp = OCT.PtrTyp; AdrTyp = OCT.AdrTyp; BPtrTyp = OCT.BPtrTyp;
- Word = OCT.Word; Longword = OCT.Longword; TagTyp = OCT.TagTyp;
-
- caseSet = {Char, SInt, Int, LInt};
- uptrSet = {M2Flag..AsmFlag};
- intSet = {SInt, Int, LInt};
- byteSet = {Undef, Bool, Byte, Char, SInt, BSet};
- wordSet = {Int, WSet, Word};
- lwordSet =
- { LInt, Real, LReal, Set, NilTyp, Pointer, ProcTyp,
- PtrTyp, AdrTyp, BPtrTyp, Longword };
- initSet = {Pointer, ProcTyp, PtrTyp, AdrTyp, BPtrTyp};
-
- (* CPU Registers *)
-
- D0 = 0; D1 = 1; D2 = 2; D7 = 7;
- A0 = 8; A1 = 9; A2 = 10; A3 = 11; A4 = 12; A5 = 13; A6 = 14; A7 = 15;
- BP = A4; FP = A5; SP = A7;
- DataRegs = {D0 .. D7};
- AdrRegs = {A0 .. A7};
-
- (* Data sizes *)
-
- B = 1; W = 2; L = 4;
-
- VAR
- returnFound : BOOLEAN;
-
- (* --- Procedure declarations ----------------------------------------- *)
-
-
- (*------------------------------------*)
- PROCEDURE setCC (VAR x : OCT.Item; cc : LONGINT);
-
- BEGIN (* setCC *)
- x.typ := OCT.booltyp; x.mode := Coc; x.a0 := cc; x.a1 := 0; x.a2 := 0
- END setCC;
-
- (*------------------------------------*)
- PROCEDURE FJ * (VAR loc : LONGINT);
-
- BEGIN (* FJ *)
- OCC.PutWord (OCC.BRA); OCC.PutWord (loc); loc := OCC.pc - 2
- END FJ;
-
- (*------------------------------------*)
- PROCEDURE CFJ * (VAR x : OCT.Item; VAR loc : LONGINT);
-
- VAR op : LONGINT;
-
- BEGIN (* CFJ *)
- IF x.typ.form = Bool THEN
- IF x.mode = Con THEN
- IF x.a0 = 0 THEN setCC (x, OCC.F) ELSE setCC (x, OCC.T) END
- ELSIF x.mode # Coc THEN
- OCC.PutF1 (OCC.TST, B, x); OCI.Unload (x); setCC (x, OCC.NE)
- END
- ELSE
- OCS.Mark (120); setCC (x, OCC.EQ)
- END;
- IF x.a0 # OCC.T THEN
- IF x.a0 = OCC.F THEN op := OCC.BRA
- ELSE op := OCC.Bcc + (OCC.invertedCC (x.a0) * 100H);
- END;
- OCC.PutWord (op); OCC.PutWord (x.a2); loc := OCC.pc - 2
- ELSE
- loc := x.a2
- END;
- OCC.FixLink (x.a1)
- END CFJ;
-
- (*------------------------------------*)
- PROCEDURE BJ * (loc : LONGINT);
-
- VAR dest : LONGINT;
-
- BEGIN (* BJ *)
- dest := loc - OCC.pc - 2;
- IF dest < -128 THEN OCC.PutWord (OCC.BRA); OCC.PutWord (dest)
- ELSE OCC.PutWord (SYS.LOR (OCC.BRA, SYS.AND (dest, 0FFH)))
- END
- END BJ;
-
- (*------------------------------------*)
- PROCEDURE CBJ * (VAR x : OCT.Item; loc : LONGINT);
-
- VAR op, dest : LONGINT;
-
- BEGIN (* CBJ *)
- IF x.typ.form = Bool THEN
- IF x.mode = Con THEN
- IF x.a0 = 0 THEN setCC (x, OCC.F) ELSE setCC (x, OCC.T) END
- ELSIF x.mode # Coc THEN
- OCC.PutF1 (OCC.TST, B, x); OCI.Unload (x); setCC (x, OCC.NE)
- END
- ELSE
- OCS.Mark (120); setCC (x, OCC.EQ)
- END;
- IF x.a0 # OCC.T THEN
- IF x.a0 = OCC.F THEN op := OCC.BRA
- ELSE op := OCC.Bcc + (OCC.invertedCC (x.a0) * 100H);
- END;
- dest := loc - OCC.pc - 2;
- IF dest < -128 THEN OCC.PutWord (op); OCC.PutWord (dest)
- ELSE OCC.PutWord (SYS.LOR (op, SYS.AND (dest, 0FFH)))
- END
- END;
- OCC.FixLinkWith (x.a2, loc); OCC.FixLink (x.a1)
- END CBJ;
-
- (*------------------------------------*)
- PROCEDURE ModulePrologue * ();
-
- VAR L1, L2 : LONGINT; label : OCT.Label;
-
- BEGIN (* ModulePrologue *)
- OCC.StartPrologue ();
-
- IF OCS.option [OCS.main] THEN
- IF OCM.SmallData THEN
- NEW (label, 32); COPY ("_LinkerDB", label^);
- OCC.PutWord (49F9H);
- OCC.PutLongRef (0, label) (* LEA _LinkerDB,A4 *)
- ELSIF OCM.Resident THEN
- (* Allocate memory for the data segment *)
- OCC.PutLong (048E7F0C0H); (* MOVEM.L D0-D3/A0-A1,-(A7) *)
-
- (* Call e.AllocMem ( (__BSSLEN + 1) * 4, {e.memClear} ) *)
- NEW (label, 32); COPY ("__BSSLEN", label^);
- OCC.PutWord (0203CH);
- OCC.PutLongRef (0, label); (* MOVE.L #__BSSLEN,D0 *)
- OCC.PutWord (05280H); (* ADDQ.L #1,D0 *)
- OCC.PutWord (0E580H); (* ASL.L #2,D0 *)
- OCC.PutWord (02600H); (* MOVE.L D0,D3 *)
- OCC.PutWord (07201H); (* MOVEQ.L #1,D1 *)
- OCC.PutWord (04841H); (* SWAP D1 *)
- OCC.PutLong (02C780004H); (* MOVE.L AbsExecBase,A6 *)
- OCC.PutLong (04EAEFF3AH); (* JSR AllocMem(A6) *)
- OCC.PutWord (04A80H); (* TST.L D0 *)
- OCC.PutWord (0662CH); (* BNE continue *)
- OCC.PutLong (02A6E0114H); (* MOVE.L 114(A6),A5 *)
- OCC.PutLong (04AAD00ACH); (* TST.L AC(A5) *)
- OCC.PutWord (0661AH); (* BNE bailout1 *)
- OCC.PutLong (041ED005CH); (* LEA 5C(A5),A0 *)
- OCC.PutLong (04EAEFE80H); (* JSR WaitPort(A6) *)
- OCC.PutLong (041ED005CH); (* LEA 5C(A5),A0 *)
- OCC.PutLong (04EAEFE8CH); (* JSR GetMsg(A6) *)
- OCC.PutLong (0522E0127H); (* ADDQ.B #1,127(A6) *)
- OCC.PutWord (02240H); (* MOVE.L D0,A1 *)
- OCC.PutLong (04EAEFE86H); (* JSR ReplyMsg(A6) *)
- (* bailout1: *)
- OCC.PutLong (04CDF030FH); (* MOVEM.L (A7)+,D0-D3/A0-A1 *)
- OCC.PutWord (07014H); (* MOVEQ #14,D0 *)
- OCC.PutWord (04E75H); (* RTS *)
- (* continue: *)
- OCC.PutWord (02840H); (* MOVE.L D0,A4 *)
- OCC.PutWord (02883H); (* MOVE.L D3,(A4) *)
- OCC.PutLong (049EC0004H); (* LEA 4(A4),A4 *)
- OCC.PutLong (04CDF030FH); (* MOVEM.L (A7)+,D0-D3/A0-A1 *)
- END;
-
- (* Push the address of the call to the cleanup code *)
- OCC.PutWord (0487AH);
- L1 := OCC.pc; OCC.PutWord (0); (* PEA ??(PC) *)
-
- (* Call module Kernel initialisation code *)
- IF ~OCM.Resident THEN
- OCC.PutWord (07201H); (* MOVEQ #1,D1 *)
- END;
- OCC.CallKernel (OCC.kInit); (* Call Kernel_?INIT *)
- IF ~OCM.Resident THEN
- (* Check if we are already running *)
- OCC.PutWord (04A01H); (* TST.B D1 *)
- L2 := OCC.pc; OCC.PutWord (06600H); (* BNE bailout2 *)
- END;
-
- (* Branch to module initialisation code *)
- IF OCM.SmallCode THEN
- OCC.PutWord (OCC.BSR);
- OCC.PutWordRef (0, OCT.InitLabel); (* BSR InitLabel *)
- ELSE
- OCC.PutWord (OCC.JSR + 039H);
- OCC.PutLongRef (0, OCT.InitLabel); (* JSR InitLabel *)
- END;
-
- (* Set return code to 0 and make clean exit *)
- OCC.PutWord (07000H); (* MOVEQ #0,D0 *)
- OCC.PutWord (09138H); (* SUB.L A0,A0 *)
- OCC.PutWord (07200H); (* MOVEQ #0,D1 *)
- OCC.CallKernel (OCC.kHalt); (* Call Kernel_Halt *)
-
- (* Fixup the cleanup code address pushed at the start *)
- OCC.PatchWord (L1, OCC.pc - L1);
-
- IF OCM.Resident THEN (* Free memory for data segment *)
- OCC.PutWord (02600H); (* MOVE.L D0,D3 *)
- OCC.PutLong (043ECFFFCH); (* LEA -4(A4),A1 *)
- OCC.PutWord (02011H); (* MOVE.L (A1),D0 *)
- OCC.PutLong (02C780004H); (* MOVE.L AbsExecBase,A6 *)
- OCC.PutLong (04EAEFF2EH); (* JSR FreeMem(A6) *)
- OCC.PutWord (02003H); (* MOVE.L D3,D0 *)
- ELSE
- (* Branch to module cleanup code *)
- IF OCM.SmallCode THEN
- OCC.PutWord (OCC.BSR);
- OCC.PutWordRef (0, OCT.EndLabel) (* BSR EndLabel *)
- ELSE
- OCC.PutWord (OCC.JSR + 039H);
- OCC.PutLongRef (0, OCT.EndLabel) (* JSR EndLabel *)
- END;
-
- (* Call module Kernel cleanup code *)
- OCC.CallKernel (OCC.kEnd); (* Call Kernel_END *)
- OCC.PutWord (4E75H); (* RTS *)
-
- (* We are already running, so bail out with return code = 25 *)
- OCC.PatchWord (L2, OCC.pc - L2 - 2); (* bailout2: *)
- OCC.PutWord (588FH); (* ADDQ #4,A7 *)
- OCC.PutWord (7019H); (* MOVEQ #25,D0 *)
- END;
- OCC.PutWord (4E75H) (* RTS *)
- ELSE
- (* Set a return code of 20 and return immediately. *)
- OCC.PutWord (7014H); (* MOVEQ #20,D0 *)
- OCC.PutWord (4E75H) (* RTS *)
- END;
-
- OCC.EndCodeHunk ()
- END ModulePrologue;
-
- (*------------------------------------*)
- PROCEDURE StartProcedure * (proc : OCT.Object);
-
- BEGIN (* StartProcedure *)
- IF OCC.level = 1 THEN OCC.StartCodeHunk (FALSE) END
- END StartProcedure;
-
- (*------------------------------------*)
- PROCEDURE LoadBP (saveBP : BOOLEAN);
-
- BEGIN (* LoadBP *)
- IF saveBP THEN OCC.PutWord (2F0CH) END; (* MOVE.L BP,-(SP) *)
- OCC.PutWord (49F9H);
- OCC.PutLongRef (0, OCT.VarLabel) (* LEA Module_VAR, BP *)
- END LoadBP;
-
- (*------------------------------------*)
- PROCEDURE CopyDynArray (adr : LONGINT; typ : OCT.Struct; dsize : LONGINT);
-
- VAR size, len, desc, ptr1, ptr2, tos, x : OCT.Item;
- moveSize : INTEGER; moveWords, oddSize : BOOLEAN; R : OCC.RegState;
-
- (*------------------------------------*)
- PROCEDURE DynArrSize (typ : OCT.Struct);
-
- BEGIN (* DynArrSize *)
- IF typ.form = DynArr THEN
- DynArrSize (typ.BaseTyp);
- IF len.mode = Undef THEN
- desc.mode := Var; desc.lev := OCC.level; desc.a0 := adr + typ.adr;
- len.mode := Reg; len.a0 := D0; OCC.Move (L, desc, len);
- desc.typ := OCT.linttyp; len.typ := OCT.linttyp
- ELSE
- IF desc.mode = Var THEN desc.a0 := adr + typ.adr;
- ELSE desc.a1 := adr + typ.adr;
- END;
- OCE.Op (times, len, desc, TRUE)
- END
- ELSE
- size.mode := Con; size.typ := OCT.linttyp; size.a0 := typ.size
- END
- END DynArrSize;
-
- BEGIN (* CopyDynArray *)
- IF OCS.pragma [OCS.saveRegs] OR OCS.pragma [OCS.saveAllRegs] THEN
- OCS.Mark (345)
- END;
- R := OCC.regState; len.mode := Undef;
-
- (* load total length of dyn array *)
- DynArrSize (typ);
-
- (* calculate size in bytes *)
- oddSize := ODD (size.a0);
- moveWords := ~oddSize & ((size.a0 MOD 4) # 0);
- IF size.a0 > 1 THEN
- OCE.Op (times, len, size, FALSE)
- END;
- IF oddSize THEN
- x.mode := Con; x.a0 := 0; x.typ := OCT.inttyp;
- OCC.Bit (OCC.BTST, x, len); (* BTST #0, <len> *)
- OCC.PutWord (6702H); (* BEQ.S 1$ *)
- OCC.PutF7 (OCC.ADDQ, L, 1, len) (* ADDQ.L #1, <len> *)
- END; (* 1$ *)
- size := len;
-
- IF OCS.pragma [OCS.stackChk] THEN OCC.CallKernel (OCC.kStackChk) END;
-
- (* adjust stack pointer *)
- tos.mode := Reg; tos.a0 := SP;
- OCC.PutF5 (OCC.SUB, L, size, tos); (* SUBA.L <size>, A7 *)
-
- (* decrement counter *)
- x.mode := Con; x.typ := OCT.inttyp;
- IF ~oddSize THEN
- (* adjust counter for copy loop *)
- IF moveWords THEN x.a0 := 1 ELSE x.a0 := 2 END;
- OCC.Shift (OCC.ASR, L, x, size); (* ASR.L #?, <size> *)
- END;
- OCC.PutF7 (OCC.SUBQ, L, 1, size); (* SUBQ.L #1, <size> *)
-
- ptr1.mode := Ind; ptr1.a0 := adr; ptr1.a1 := 0; ptr1.a2 := -1;
- ptr1.lev := OCC.level; ptr1.typ := OCT.notyp; ptr1.obj := NIL;
- x := ptr1; x.mode := Var;
- OCI.LoadAdr (ptr1); ptr1.mode := Pop; (* LEA adr(A5), An *)
- OCC.ForgetReg (ptr1.a0);
- OCC.Move (L, tos, x); (* MOVE.L A7, adr(A5) *)
- OCC.GetAReg (ptr2, NIL);
- OCC.Move (L, tos, ptr2); (* MOVE.L A7, Am *)
- ptr2.mode := Pop;
-
- IF oddSize THEN moveSize := B
- ELSIF moveWords THEN moveSize := W
- ELSE moveSize := L
- END;
- OCC.Move (moveSize, ptr1, ptr2); (* 2$ MOVE.? (An)+,(Am)+ *)
- OCC.PutWord (OCC.DBF + size.a0);
- OCC.PutWord (-4); (* DBF <size>, 2$ *)
-
- OCC.FreeRegs (R)
- END CopyDynArray;
-
-
- (*------------------------------------*)
- PROCEDURE StartProcBody * (proc : OCT.Object; dsize : LONGINT);
-
- CONST
- (* Register numbers in *reverse* order. *)
- D0 = 15; D1 = 14; D2 = 13; D7 = 8;
- A0 = 7; A1 = 6; A2 = 5; A4 = 3; A5 = 2; A6 = 1;
-
- VAR
- par : OCT.Object; x, y : OCT.Item; count : LONGINT;
- usesA4, usesA5 : BOOLEAN; savedRegs : SET;
-
- BEGIN (* StartProcBody *)
- (*proc.a1 := OCC.pc;*)
- OCC.StartProcedure (proc);
-
- IF OCS.pragma [OCS.entryExitCode] THEN
-
- IF OCS.pragma [OCS.stackChk] THEN
- IF OCS.pragma [OCS.saveAllRegs] THEN
- OCC.PutWord (2F00H) (* MOVE.L D0,-(A7) *)
- END;
- x.mode := Con; x.a0 := dsize; x.typ := OCT.linttyp;
- y.mode := Reg; y.a0 := 0; (* D0 *)
- OCC.Move (L, x, y); (* MOVE.L #dsize,D0 *)
- OCC.CallKernel (OCC.kStackChk);
- IF OCS.pragma [OCS.saveAllRegs] THEN
- OCC.PutWord (201FH) (* MOVE.L (A7)+,D0 *)
- END;
- END; (* IF stackChk *)
-
- usesA4 := ~OCS.pragma [OCS.longVars] & ~OCM.SmallData & ~OCM.Resident
- & ( (proc.mode = XProc)
- OR ((proc.mode = TProc) (*& (proc.visible = OCT.Exp)*) ));
- usesA5 := (OCC.level # 1) OR (dsize # 0) OR OCT.IsParam (proc.link);
-
- IF usesA4 THEN LoadBP (TRUE) END;
-
- IF usesA5 THEN
- IF
- (dsize > 0)
- & (OCS.option [OCS.initialise] OR OCS.pragma [OCS.clearVars])
- THEN
- OCC.PutWord (4E55H); OCC.PutWord (0); (* LINK A5,#0 *)
-
- (* Clear all procedure variables. *)
- count := dsize DIV 4; (* clear longwords initially *)
- IF count > 0 THEN
- IF count < 5 THEN (* inline the loop *)
- WHILE count > 0 DO
- OCC.PutWord (42A7H); (* CLR.L -(A7) *)
- DEC (count)
- END;
- ELSE
- IF OCS.pragma [OCS.saveAllRegs] THEN
- OCC.PutWord (2F00H) (* MOVE.L D0,-(A7) *)
- END;
- OCC.PutWord (303CH);
- OCC.PutWord (count - 1); (* MOVE.W #count-1,D0 *)
- OCC.PutWord (42A7H); (* 1$ CLR.L -(A7) *)
- OCC.PutWord (OCC.DBF);
- OCC.PutWord (-4); (* DBF.W D0,1$ *)
- IF OCS.pragma [OCS.saveAllRegs] THEN
- OCC.PutWord (201FH) (* MOVE.L (A7)+,D0 *)
- END;
- END
- END;
- IF (dsize MOD 4) # 0 THEN (* Assuming dsize is a multiple of 2 *)
- OCC.PutWord (4267H) (* CLR.W -(A7) *)
- END
- ELSE
- OCC.PutWord (4E55H);
- OCC.PutWord (-dsize); (* LINK A5,#<-dsize> *)
- END
- END; (* IF usesA5 *)
-
- IF OCS.pragma [OCS.saveRegs] OR OCS.pragma [OCS.saveAllRegs] THEN
- savedRegs := {A6..A2,D7..D2};
- IF OCS.pragma [OCS.saveAllRegs] THEN
- savedRegs := savedRegs + {A0,A1,D0,D1}
- END;
- IF usesA4 THEN EXCL (savedRegs, A4) END;
- IF usesA5 THEN EXCL (savedRegs, A5) END;
- OCC.PutWord (48E7H); (* MOVEM.L savedRegs,-(A7) *)
- OCC.PutWord (SYS.VAL (LONGINT, savedRegs))
- END; (* IF saveRegs OR saveAllRegs *)
-
- IF OCS.pragma [OCS.copyArrays] THEN
- par := proc.link;
- WHILE par # NIL DO
- (* code for dynamic array value parameters *)
- IF (par.typ.form = DynArr) & (par.mode = Var) THEN
- CopyDynArray (par.a0, par.typ, dsize)
- END;
- par := par.link
- END
- END; (* IF copyArrays *)
- END; (* IF entryExitCode *)
-
- returnFound := FALSE
- END StartProcBody;
-
- (*------------------------------------*)
- PROCEDURE EndProcBody *
- (proc : OCT.Object; psize : INTEGER; L0 : LONGINT; vars : BOOLEAN);
-
- VAR op : OCT.Item; usesA4, usesA5 : BOOLEAN; savedRegs : SET;
-
- BEGIN (* EndProcBody *)
- IF OCS.pragma [OCS.entryExitCode] THEN
- usesA4 := ~OCS.pragma [OCS.longVars] & ~OCM.SmallData & ~OCM.Resident
- & ( (proc.mode = XProc)
- OR ((proc.mode = TProc) (*& (proc.visible = OCT.Exp)*) ));
- usesA5 := (OCC.level # 1) OR vars OR OCT.IsParam (proc.link);
- IF usesA4 THEN
- (* Don't count return address, frame pointer or global var base *)
- DEC (psize, 12)
- ELSE
- (* Don't count return address or frame pointer *)
- DEC (psize, 8)
- END;
- (* Insert trap for missing RETURN in function procedures. *)
- IF (proc.typ # OCT.notyp) & OCS.pragma [OCS.returnChk] THEN
- IF returnFound THEN OCC.Trap (OCC.ReturnCheck)
- ELSE OCS.Mark (335)
- END
- END;
- OCC.FixLink (L0); (* Fix up RETURN branches *)
- IF OCS.pragma [OCS.saveRegs] OR OCS.pragma [OCS.saveAllRegs] THEN
- savedRegs := {D2..D7,A2..A6};
- IF OCS.pragma [OCS.saveAllRegs] THEN
- savedRegs := savedRegs + {D0,D1,A0,A1}
- END;
- IF usesA4 THEN EXCL (savedRegs, A4) END;
- IF usesA5 THEN EXCL (savedRegs, A5) END;
- OCC.PutWord (4CDFH); (* MOVEM.L (A7)+,savedRegs *)
- OCC.PutWord (SYS.VAL (LONGINT, savedRegs))
- END;
- IF usesA5 THEN OCC.PutWord (4E5DH) END; (* UNLK A5 *)
- IF usesA4 THEN OCC.PutWord (285FH) END; (* MOVEA.L (A7)+, A4 *)
- IF OCS.pragma [OCS.deallocPars] & (psize > 0) THEN
- OCC.PutWord (2F57H); OCC.PutWord (psize); (* MOVE.L (SP),psize(SP) *)
- IF psize <= 8 THEN
- op.mode := Reg; op.a0 := SP;
- OCC.PutF7 (OCC.ADDQ, L, psize, op) (* ADDQ #<psize>,SP *)
- ELSE
- OCC.PutWord (4FEFH); OCC.PutWord (psize)(* LEA psize(SP),SP *)
- END
- END;
- OCC.PutWord (OCC.RTS);
- END;
-
- IF OCC.level = 1 THEN OCC.EndCodeHunk () END
- END EndProcBody;
-
- (*------------------------------------*)
- PROCEDURE StartModuleBody * (VAR dsize : LONGINT; VAR L0 : LONGINT);
-
- VAR
- x, y, z : OCT.Item; modno : INTEGER; module : OCT.Module;
- count : LONGINT; obj : OCT.Object; pushedModule : BOOLEAN;
- name : ARRAY 256 OF CHAR;
-
- (*------------------------------------*)
- PROCEDURE CmdsAndTypes ( obj : OCT.Object );
-
- VAR typ : OCT.Struct; len : LONGINT;
-
- BEGIN (* CmdsAndTypes *)
- IF obj # NIL THEN
- CmdsAndTypes (obj.left);
-
- IF obj.mode = Typ THEN
- typ := obj.typ;
- IF (typ # NIL) & (typ.form = Record) & (typ.sysflg = OberonFlag)
- THEN
- IF ~pushedModule THEN
- OCC.PutWord (02F00H); (* MOVE.L D0,-(A7) *)
- pushedModule := TRUE
- END;
- OCC.PutWord (02F17H); (* MOVE.L (A7),-(A7) *)
- x.mode := Con; x.a0 := 0; x.typ := OCT.tagtyp;
- x.label := typ.label;
- OCC.PutF3 (OCC.PEA, x); (* PEA #Type descriptor *)
- OCC.CallKernel (OCC.kRegisterType); (* Call RegisterType *)
- END
- ELSIF (obj.mode = XProc) & (obj.visible = OCT.Exp)
- & (obj.typ = OCT.notyp) & (~OCT.IsParam (obj.link))
- THEN
- IF ~pushedModule THEN
- OCC.PutWord (02F00H); (* MOVE.L D0,-(A7) *)
- pushedModule := TRUE
- END;
- OCC.PutWord (02F17H); (* MOVE.L (A7),-(A7) *)
- OCT.GetName (obj.name, name);
- len := str.Length (name);
- x.mode := Abs; x.a0 := len + 1; x.typ := OCT.linttyp;
- OCC.PutF3 (OCC.PEA, x); (* PEA LEN(name) *)
- OCC.AllocString (name, len, x);
- x.mode := Con; x.typ := OCT.stringtyp;
- OCC.PutF3 (OCC.PEA, x); (* PEA name *)
- x.mode := Lab; x.a0 := 0; x.a1 := L; x.label := obj.label;
- OCC.PutF3 (OCC.PEA, x); (* PEA command *)
- OCC.CallKernel (OCC.kRegisterCommand); (* Call RegisterCommand *)
- END;
-
- CmdsAndTypes (obj.right)
- END
- END CmdsAndTypes;
-
- BEGIN (* StartModuleBody *)
- OCC.StartCodeHunk (TRUE);
- IF ~OCM.SmallData & ~OCM.Resident & ~OCS.pragma [OCS.longVars] THEN
- LoadBP (FALSE)
- END;
-
- (* Check if module already initialised *)
- x.mode := Var; x.lev := 0; x.a0 := dsize; OCC.PutF1 (OCC.TST, B, x);
- (* If so, return *)
- L0 := 0; y.mode := Coc; y.a0 := OCC.EQ; y.a1 := 0; y.a2 := 0;
- y.typ := OCT.booltyp; CFJ (y, L0);
-
- (* Set initialisation flag *)
- x.mode := Var; x.lev := 0; x.a0 := dsize; OCC.PutF3 (OCC.ST, x);
-
- IF OCC.GlobalPtrs () THEN
- x.mode := Var; x.lev := 0; x.a0 := 0;
- OCC.PutF3 (OCC.PEA, x); (* PEA VARS *)
- x.mode := Con; x.a0 := 0; x.a1 := 0; x.typ := OCT.tagtyp;
- x.label := OCT.GCLabel;
- OCC.PutF3 (OCC.PEA, x); (* PEA GC-Offsets *)
- OCC.CallKernel (OCC.kInitGC) (* Call Kernel_InitGC *)
- END;
-
- IF OCS.option [OCS.register] THEN
-
- (* Register the module, types and commands *)
-
- x.mode := Abs; x.a0 := str.Length (OCT.ModuleName) + 1;
- x.typ := OCT.linttyp;
- OCC.PutF3 (OCC.PEA, x); (* PEA LEN(ModuleName) *)
- x.mode := Con; x.a0 := 0; x.typ := OCT.stringtyp;
- x.label := OCT.ConstLabel;
- OCC.PutF3 (OCC.PEA, x); (* PEA #ModuleName *)
- OCC.CallKernel (OCC.kRegisterModule); (* Call Kernel_RegisterModule *)
- pushedModule := FALSE;
- CmdsAndTypes (OCT.topScope.link);
- IF pushedModule THEN
- OCC.PutWord (0588FH) (* ADDQ.L #4,A7 *)
- END
- END;
-
- IF (dsize > 0) & ~OCM.SmallData & ~OCM.Resident
- & (OCS.option [OCS.initialise] OR OCS.pragma [OCS.clearVars])
- THEN
- OCC.GetAReg (x, NIL);
- IF OCS.pragma [OCS.longVars] THEN
- y.mode := Var; y.lev := 0; y.a0 := 0;
- OCC.PutF2 (OCC.LEA, y, x.a0) (* LEA Module_VAR,An *)
- ELSE
- y.mode := Reg; y.a0 := BP;
- OCC.Move (L, y, x) (* MOVE.L A4,An *)
- END;
- x.mode := Pop; count := dsize DIV 4; (* clear longwords initially *)
- IF count > 0 THEN
- IF count < 5 THEN (* inline the loop *)
- WHILE count > 0 DO OCC.PutF1 (OCC.CLR, L, x); DEC (count) END;
- ELSE
- IF count > 65536 THEN OCS.Mark (312); count := 65536 END;
- z.mode := Con; z.a0 := count - 1; z.typ := OCT.inttyp;
- OCC.GetDReg (y, NIL);
- OCC.Move (W, z, y); (* MOVE.W #count,Dn *)
- OCC.PutF1 (OCC.CLR, L, x); (* 1$ CLR.L (An)+ *)
- OCC.PutWord (OCC.DBF + y.a0);
- OCC.PutWord (-4); (* DBF.W Dn,1$ *)
- OCC.FreeReg (y)
- END
- END;
- IF (dsize MOD 4) # 0 THEN (* Assuming dsize is a multiple of 2 *)
- OCC.PutF1 (OCC.CLR, W, x) (* CLR.W (An)+ *)
- END;
- OCC.FreeReg (x)
- END;
-
- (* Increment dsize to account for initFlag variable *)
- INC (dsize, OCM.BoolSize); IF ODD (dsize) THEN INC (dsize) END;
-
- IF OCT.nofGmod > 0 THEN (* Initialise imported modules *)
- IF ~OCM.SmallData & ~OCM.Resident & ~OCS.pragma [OCS.longVars] THEN
- (* Save variable base pointer *)
- OCC.PutWord (2F0CH) (* MOVE.L BP,-(SP) *)
- END;
-
- modno := 0;
- WHILE modno < OCT.nofGmod DO
- module := OCT.GlbMod [modno];
- IF module.visible = OCT.Exp THEN
- IF OCM.SmallCode THEN
- OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, module.label)
- ELSE
- OCC.PutWord (OCC.JSR + 039H); OCC.PutLongRef (0, module.label)
- END;
- END;
- INC (modno)
- END;
-
- IF ~OCM.SmallData & ~OCM.Resident & ~OCS.pragma [OCS.longVars] THEN
- (* Restore variable base pointer *)
- OCC.PutWord (285FH) (* MOVEA.L (A7)+, A4 *)
- END
- END
- END StartModuleBody;
-
- (*------------------------------------*)
- PROCEDURE EndModuleBody * (dsize : LONGINT; L0 : LONGINT);
-
- VAR
- x : OCT.Item; endProc : OCT.Object; modno : INTEGER;
- module : OCT.Module;
-
- BEGIN (* EndModuleBody *)
- OCC.FixLink (L0);
- OCC.PutWord (OCC.RTS);
-
- IF ~OCM.Resident THEN
- NEW (endProc);
- endProc.mode := XProc; endProc.a0 := 0; endProc.typ := OCT.notyp;
- endProc.label := OCT.EndLabel;
- OCC.StartProcedure (endProc);
-
- (* Clear initialisation flag *)
- OCS.pragma [OCS.longVars] := TRUE;
- x.mode := Var; x.lev := 0; x.a0 := dsize - 2; OCC.PutF3 (OCC.SF, x);
-
- IF OCT.nofGmod > 0 THEN (* Cleanup imported modules *)
- modno := 0;
- WHILE modno < OCT.nofGmod DO
- module := OCT.GlbMod [modno];
- IF module.visible = OCT.Exp THEN
- IF OCM.SmallCode THEN
- OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, module.endLab)
- ELSE
- OCC.PutWord (OCC.JSR + 039H); OCC.PutLongRef (0, module.endLab)
- END;
- END;
- INC (modno)
- END
- END;
-
- OCC.PutWord (OCC.RTS);
- END;
-
- OCC.EndCodeHunk ()
- END EndModuleBody;
-
- (*------------------------------------*)
- PROCEDURE CompareParLists * (x, y : OCT.Object);
-
- VAR xt, yt : OCT.Struct;
-
- BEGIN (* CompareParLists *)
- WHILE x # NIL DO
- IF y # NIL THEN
- xt := x.typ; yt := y.typ;
- WHILE (xt.form = DynArr) & (yt.form = DynArr) DO
- xt := xt.BaseTyp; yt := yt.BaseTyp
- END;
- IF x.mode # y.mode THEN
- OCS.Mark (115)
- ELSIF xt # yt THEN
- IF (xt.form = ProcTyp) & (yt.form = ProcTyp) THEN
- CompareParLists (xt.link, yt.link)
- ELSE
- OCS.Mark (115)
- END
- END;
- y := y.link
- ELSE OCS.Mark (116)
- END;
- x := x.link
- END; (* WHILE *)
- IF (y # NIL) & (y.mode <= Ind) & (y.a0 >= 0) THEN OCS.Mark (117) END
- END CompareParLists;
-
- (*------------------------------------*)
- PROCEDURE Leng (VAR x : OCT.Item; L0 : LONGINT);
-
- VAR y : OCT.Item;
-
- BEGIN (* Leng *)
- IF x.mode = Push THEN y.mode := Abs; y.a0 := L0; OCC.PutF3 (OCC.PEA, y)
- ELSE y.mode := Con; y.a0 := L0; y.typ := OCT.linttyp; OCC.Move (L, y, x)
- END
- END Leng;
-
- (*------------------------------------*)
- PROCEDURE DynArrBnd (
- ftyp : OCT.Struct; VAR ap : OCT.Item; varpar : BOOLEAN);
-
- VAR
- f : INTEGER; x, y, z, desc : OCT.Item; atyp : OCT.Struct;
- adr : LONGINT; freeY : BOOLEAN;
-
- BEGIN (* DynArrBnd *)
- (* ftyp.form = DynArr *)
- x.mode := Push; x.a0 := SP; atyp := ap.typ;
- IF varpar & (ftyp.BaseTyp = OCT.bytetyp) THEN
- IF atyp.form # DynArr THEN Leng (x, atyp.size)
- ELSE
- adr := atyp.adr; OCI.DescItem (desc, ap.desc, adr);
- atyp := atyp.BaseTyp; freeY := FALSE;
- IF atyp.form = DynArr THEN
- OCC.GetDReg (y, NIL); OCC.Move (L, desc, y);
- OCI.UpdateDesc (desc, adr); freeY := TRUE;
- y.typ := OCT.linttyp;
- REPEAT
- OCI.DescItem (desc, ap.desc, atyp.adr);
- OCE.Op (times, y, desc, FALSE);
- atyp := atyp.BaseTyp
- UNTIL atyp.form # DynArr;
- ELSE
- y := desc
- END;
- IF atyp.size > 1 THEN
- z.mode := Con; z.a0 := atyp.size; z.typ := OCT.linttyp;
- OCE.Op (times, y, z, FALSE)
- END;
- OCC.Move (L, y, x);
- IF freeY THEN OCI.Unload (y) ELSE OCI.UnloadDesc (ap) END
- END
- ELSE
- desc.mode := Undef;
- LOOP
- f := atyp.form;
- IF f = Array THEN Leng (x, atyp.n)
- ELSIF f = DynArr THEN
- OCI.DescItem (desc, ap.desc, atyp.adr);
- OCC.Move (L, desc, x); OCI.UpdateDesc (desc, atyp.adr)
- ELSE OCS.Mark (66)
- END;
- ftyp := ftyp.BaseTyp; atyp := atyp.BaseTyp;
- IF ftyp.form # DynArr THEN
- IF ftyp # atyp THEN OCS.Mark (67) END;
- EXIT
- END
- END; (* LOOP *)
- OCI.UnloadDesc (ap)
- END
- END DynArrBnd;
-
- (*------------------------------------*)
- PROCEDURE ExtendStack (size : LONGINT);
-
- VAR sp, x : OCT.Item;
-
- BEGIN (* ExtendStack *)
- sp.mode := Reg; sp.a0 := SP;
- IF ODD (size) THEN INC (size) END;
- IF size <= 8 THEN
- OCC.PutF7 (OCC.SUBQ, L, size, sp)
- ELSE
- x.mode := RegI; x.a0 := SP; x.a1 := -size;
- OCC.PutF2 (OCC.LEA, x, sp.a0)
- END
- END ExtendStack;
-
- (*------------------------------------*)
- PROCEDURE moveBW (VAR src, dst : OCT.Item; extend : BOOLEAN);
-
- VAR x, zero : OCT.Item;
-
- BEGIN (* moveBW *)
- IF src.mode = Con THEN
- OCC.Move (W, src, dst)
- ELSE
- IF ~extend THEN
- zero.mode := Con; zero.a0 := 0; zero.typ := OCT.wordtyp;
- END;
- IF (dst.mode = Reg) & (dst.a0 IN DataRegs) THEN
- IF ~extend THEN OCC.Move (W, zero, dst) END;
- OCC.Move (B, src, dst);
- IF extend THEN OCI.EXT (W, dst.a0) END
- ELSE
- IF extend THEN
- OCI.Load (src); OCI.EXT (W, src.a0)
- ELSE
- x := src; OCC.GetDReg (src, NIL);
- OCC.Move (W, zero, src); OCC.Move (B, x, dst); OCI.Unload (x)
- END;
- OCC.Move (W, src, dst)
- END
- END
- END moveBW;
-
- (*------------------------------------*)
- PROCEDURE moveBL (VAR src, dst : OCT.Item; extend : BOOLEAN);
-
- VAR x, zero : OCT.Item;
-
- BEGIN (* moveBL *)
- IF src.mode = Con THEN
- OCC.Move (L, src, dst)
- ELSE
- IF ~extend THEN
- zero.mode := Con; zero.a0 := 0; zero.typ := OCT.wordtyp;
- END;
- IF (dst.mode = Reg) & (dst.a0 IN DataRegs) THEN
- IF ~extend THEN OCC.Move (L, zero, dst) END;
- OCC.Move (B, src, dst);
- IF extend THEN OCI.EXT (W, dst.a0); OCI.EXT (L, dst.a0) END
- ELSE
- IF extend THEN
- OCI.Load (src); OCI.EXT (W, src.a0); OCI.EXT (L, src.a0)
- ELSE
- x := src; OCC.GetDReg (src, NIL);
- OCC.Move (L, zero, src); OCC.Move (B, x, src); OCI.Unload (x)
- END;
- OCC.Move (L, src, dst)
- END
- END
- END moveBL;
-
- (*------------------------------------*)
- PROCEDURE moveWL (VAR src, dst : OCT.Item; extend : BOOLEAN);
-
- VAR x, zero : OCT.Item;
-
- BEGIN (* moveWL *)
- IF src.mode = Con THEN
- OCC.Move (L, src, dst)
- ELSE
- IF ~extend THEN
- zero.mode := Con; zero.a0 := 0; zero.typ := OCT.wordtyp;
- END;
- IF (dst.mode = Reg) & (dst.a0 IN DataRegs) THEN
- IF ~extend THEN OCC.Move (L, zero, dst) END;
- OCC.Move (W, src, dst);
- IF extend THEN OCI.EXT (L, dst.a0) END
- ELSE
- IF extend THEN
- OCI.Load (src); OCI.EXT (L, src.a0)
- ELSE
- x := src; OCC.GetDReg (src, NIL);
- OCC.Move (L, zero, src); OCC.Move (W, x, src); OCI.Unload (x)
- END;
- OCC.Move (L, src, dst)
- END
- END
- END moveWL;
-
- (*------------------------------------*)
- (*
- Moves size bytes from src to dst.
- *)
- PROCEDURE moveBlock (VAR src, dst : OCT.Item; size : LONGINT);
-
- VAR
- x, y : OCT.Item; numRegs, i, s : INTEGER; lw : LONGINT; R : SET;
- useMOVEM, freeDst : BOOLEAN;
-
- BEGIN (* moveBlock *)
- freeDst := FALSE;
- (* size must be even, but it may be zero *)
- IF ODD (size) THEN OCS.Mark (957); INC (size) END;
- IF size = 2 THEN OCC.Move (W, src, dst)
- ELSIF size = 4 THEN OCC.Move (L, src, dst)
- ELSIF size > 0 THEN
- R := {D0 .. D7} - OCC.regState.regs; numRegs := 0; i := D0;
- WHILE i <= D7 DO IF i IN R THEN INC (numRegs) END; INC (i) END;
- IF (size MOD 4) = 2 THEN useMOVEM := ((numRegs * 2) >= size); s := W
- ELSE useMOVEM := ((numRegs * 4) >= size); s := L
- END;
-
- IF useMOVEM THEN
- (* Calculate which registers are needed *)
- numRegs := SHORT (size DIV s); i := D0;
- WHILE numRegs > 0 DO
- WHILE ~(i IN R) DO INC (i) END;
- INC (i); DEC (numRegs)
- END;
- (* Discard the rest *)
- WHILE i <= D7 DO EXCL (R, i); INC (i) END;
- (* Reserve the registers *)
- OCC.regState.regs := OCC.regState.regs + R;
- FOR i := D0 TO D7 DO IF i IN R THEN OCC.ForgetReg (i) END END;
- (* Finally ... *)
- x.mode := RList; x.a0 := SYS.VAL (LONGINT, R);
- OCC.Move (s, src, x); (* MOVEM.s <src>,Dx-Dy *)
- OCC.Move (s, x, dst); (* MOVEM.s Dx-Dy,<dst> *)
- (* Free registers. *)
- OCC.regState.regs := OCC.regState.regs - R;
- ELSE
- OCI.LoadAdr (src); src.mode := Pop; OCC.ForgetReg (src.a0);
- IF dst.mode = Push THEN
- ExtendStack (size);
- y.mode := Reg; y.a0 := dst.a0;
- OCC.GetAReg (dst, NIL); OCC.Move (L, y, dst);
- dst.mode := Pop; dst.a1 := 0;
- freeDst := TRUE
- ELSE
- OCI.LoadAdr (dst); dst.mode := Pop; OCC.ForgetReg (dst.a0)
- END;
- lw := size DIV 4;
- IF lw > 65536 THEN
- x.mode := Con; x.a0 := lw; x.typ := OCT.linttyp;
- OCI.Load (x); (* MOVE.L #<size>,Dc *)
- OCC.Move (L, src, dst); (* 1$ MOVE.L (As)+,(Ad)+ *)
- OCC.PutF7 (OCC.SUBQ, L, 1, x); (* SUBQ.L #1,Dc *)
- OCC.PutWord (66FAH); (* BNE 1$ *)
- ELSIF lw > 1 THEN
- IF lw > 32768 THEN DEC (lw, 65536) END;
- x.mode := Con; x.a0 := lw - 1; x.typ := OCT.inttyp;
- OCI.Load (x); (* MOVE.W #<size>,Dc *)
- OCC.Move (L, src, dst); (* 1$ MOVE.L (As)+,(Ad)+ *)
- OCC.PutWord (OCC.DBF + x.a0);
- OCC.PutWord (-4) (* DBF.W Dc, 1$ *)
- ELSIF lw = 1 THEN
- OCC.Move (L, src, dst)
- END;
- IF (size MOD 4) = 2 THEN OCC.Move (W, src, dst) END;
- IF freeDst THEN OCC.FreeReg (dst) END
- END
- END
- END moveBlock;
-
- (*------------------------------------*)
- PROCEDURE movePtr ( VAR src, dst : OCT.Item );
-
- VAR x : OCT.Item;
-
- BEGIN (* movePtr *)
- IF (dst.typ.sysflg = BCPLFlag) & (src.typ.sysflg # BCPLFlag) THEN
- x := src; OCC.GetDReg (src, NIL);
- OCC.Move (L, x, src); (* MOVE.L src,Dx *)
- x.mode := Con; x.a0 := 2; x.typ := OCT.linttyp;
- OCC.Shift (OCC.ASR, L, x, src); (* ASR.L #2,Dx *)
- ELSIF (dst.typ.sysflg # BCPLFlag) & (src.typ.sysflg = BCPLFlag) THEN
- x := src; OCC.GetDReg (src, NIL);
- OCC.Move (L, x, src); (* MOVE.L src,Dx *)
- OCC.PutF5 (OCC.ADD, L, src, src); (* ADD.L Dx,Dx *)
- OCC.PutF5 (OCC.ADD, L, src, src); (* ADD.L Dx,Dx *)
- END;
- OCC.Move (L, src, dst)
- END movePtr;
-
- (*------------------------------------*)
- PROCEDURE Assign * (VAR dst, src : OCT.Item; param : BOOLEAN);
-
- VAR f, g : INTEGER; L0, reg, op, s, vsz : LONGINT;
- y, z, tag, tdes : OCT.Item; p, q : OCT.Struct; R : OCC.RegState;
- R1 : SET; freeDst : BOOLEAN;
-
- (*------------------------------------*)
- PROCEDURE IntToReal ();
-
- VAR R : OCC.RegState; f : INTEGER;
-
- BEGIN (* IntToReal *)
- IF src.mode = Con THEN src.typ := OCT.linttyp END;
- f := src.typ.form;
- OCC.LoadRegParams1 (R, src);
- IF f = SInt THEN OCI.EXT (W, D0); f := Int END;
- IF f = Int THEN OCI.EXT (L, D0) END;
- OCC.CallKernel (OCC.kSPFlt);
- OCC.RestoreRegisters (R, src);
- OCC.Move (L, src, dst)
- END IntToReal;
-
- BEGIN (* Assign *)
- IF dst.rdOnly THEN OCS.Mark (324) END;
- f := dst.typ.form; g := src.typ.form;
- IF dst.mode = Con THEN OCS.Mark (56) END;
- CASE f OF
- Undef :
- |
- Byte :
- IF (g = String) & (src.a1 <= 2) THEN
- src.a0 := src.a2; src.typ := OCT.chartyp; g := Char
- END;
- IF g IN byteSet THEN OCC.Move (B, src, dst)
- ELSE OCS.Mark (113)
- END
- |
- Word :
- IF (g = String) & (src.a1 <= 2) THEN
- src.a0 := src.a2; src.typ := OCT.chartyp; g := Char
- END;
- IF g IN wordSet THEN OCC.Move (W, src, dst)
- ELSIF g IN byteSet THEN moveBW (src, dst, g = SInt)
- ELSE OCS.Mark (113)
- END
- |
- Longword :
- IF (g = String) & (src.a1 <= 2) THEN
- src.a0 := src.a2; src.typ := OCT.chartyp; g := Char
- END;
- IF g IN lwordSet THEN OCC.Move (L, src, dst)
- ELSIF g IN wordSet THEN moveWL (src, dst, g = Int)
- ELSIF g IN byteSet THEN moveBL (src, dst, g = SInt)
- ELSE OCS.Mark (113)
- END
- |
- Bool :
- IF src.mode = Coc THEN
- IF (dst.mode = Reg) & (dst.a0 IN AdrRegs) THEN
- y := dst; OCC.GetDReg (dst, NIL)
- ELSE y.mode := Undef
- END;
- IF
- ((src.a1 = 0) & (src.a2 = 0)) OR (src.a0 IN {OCC.T, OCC.F})
- THEN
- op := OCC.Scc + (src.a0 * 100H); OCC.PutF3 (op, dst)
- ELSE
- op := OCC.Bcc + (OCC.invertedCC (src.a0) * 100H);
- OCC.PutWord (op); OCC.PutWord (src.a2); (* Bcc 1$ *)
- src.a2 := OCC.pc - 2; OCC.FixLink (src.a1);
- z := dst; OCC.PutF3 (OCC.ST, z); (* ST <dst> *)
- L0 := OCC.pc; OCC.PutWord (6000H); (* BRA.S 2$ *)
- OCC.FixLink (src.a2);
- z := dst; OCC.PutF3 (OCC.SF, z); (* 1$ SF <dst> *)
- OCC.PatchWord (L0, OCC.pc - L0 - 2); (* 2$ *)
- END;
- IF y.mode # Undef THEN
- OCC.Move (L, dst, y); OCI.Unload (dst) (*OCI.Unload (y)*)
- END
- ELSIF g = Bool THEN
- IF src.mode = Con THEN
- IF (dst.mode = Reg) & (dst.a0 IN AdrRegs) THEN
- y := dst; OCC.GetDReg (dst, NIL)
- ELSE y.mode := Undef
- END;
- IF src.a0 = 0 THEN op := OCC.SF ELSE op := OCC.ST END;
- OCC.PutF3 (op, dst);
- IF y.mode # Undef THEN
- OCC.Move (L, dst, y); OCI.Unload (dst) (*OCI.Unload (y)*)
- END
- ELSE
- OCC.Move (B, src, dst)
- END
- ELSE OCS.Mark (113)
- END
- |
- Char, SInt :
- IF (g = String) & (src.a1 <= 2) THEN
- src.a0 := src.a2; src.typ := OCT.chartyp; g := Char
- END;
- IF (g = f) OR (g = Byte) THEN OCC.Move (B, src, dst)
- ELSE OCS.Mark (113)
- END
- |
- Int :
- IF g IN {Int, Word} THEN OCC.Move (W, src, dst)
- ELSIF g = SInt THEN moveBW (src, dst, TRUE)
- ELSE OCS.Mark (113)
- END
- |
- LInt :
- IF g IN {LInt, Longword, AdrTyp} THEN OCC.Move (L, src, dst)
- ELSIF g = Int THEN moveWL (src, dst, TRUE)
- ELSIF g = SInt THEN moveBL (src, dst, TRUE)
- ELSE OCS.Mark (113)
- END
- |
- BSet, WSet, Set :
- IF g = f THEN OCC.Move (src.typ.size, src, dst)
- ELSIF (g IN {BSet, WSet, Set}) & (src.mode = Con) THEN
- IF (f = BSet) & ((src.a0 < -128) OR (src.a0 > 255)) THEN
- OCS.Mark (113)
- ELSIF (f = WSet) & ((src.a0 < -32768) OR (src.a0 > 65535)) THEN
- OCS.Mark (113)
- ELSE
- OCC.Move (dst.typ.size, src, dst)
- END
- ELSE OCS.Mark (113)
- END
- |
- Real :
- IF g = Real THEN OCC.Move (L, src, dst)
- ELSIF g IN intSet THEN IntToReal ()
- ELSE OCS.Mark (113)
- END
- |
- LReal :
- IF g = LReal THEN OCC.Move (L, src, dst)
- ELSIF g = Real THEN OCC.Move (L, src, dst)
- ELSIF g IN intSet THEN IntToReal ()
- ELSE OCS.Mark (113)
- END
- |
- Pointer :
- IF (dst.typ = src.typ) OR (g = NilTyp) THEN
- p := dst.typ.BaseTyp;
- IF p = NIL THEN OCS.Mark (966); HALT (966) END;
- IF p.form = DynArr THEN
- IF param THEN
- IF g = NilTyp THEN
- WHILE (p # NIL) & (p.form = DynArr) DO
- OCC.Move (L, src, dst);
- p := p.BaseTyp
- END;
- ELSIF src.mode = RList THEN
- ExtendStack (p.size); dst.mode := RegI; dst.a1 := 0;
- ELSE
- IF src.mode IN {Ind, IndX, RegI, RegX} THEN
- INC (src.a1, p.adr)
- ELSE
- INC (src.a0, p.adr)
- END;
- WHILE (p # NIL) & (p.form = DynArr) DO
- OCC.Move (L, src, dst);
- IF src.mode IN {Ind, IndX, RegI, RegX} THEN DEC (src.a1, 4)
- ELSE DEC (src.a0, 4)
- END;
- p := p.BaseTyp
- END
- END;
- OCC.Move (L, src, dst)
- ELSE
- IF g = NilTyp THEN
- IF dst.mode = RList THEN
- R1 := SYS.VAL (SET, dst.a0); reg := D0; dst.mode := Reg;
- WHILE reg <= A7 DO
- IF reg IN R1 THEN
- dst.a0 := reg; OCC.Move (L, src, dst)
- END;
- INC (reg)
- END
- ELSE
- WHILE (p # NIL) & (p.form = DynArr) DO
- OCC.Move (L, src, dst);
- IF dst.mode IN {Ind, IndX, RegI, RegX} THEN INC (dst.a1, 4)
- ELSE INC (dst.a0, 4)
- END;
- p := p.BaseTyp
- END;
- OCC.Move (L, src, dst)
- END
- ELSIF (src.mode = RList) OR (dst.mode = RList) THEN
- OCC.Move (L, src, dst)
- ELSE
- moveBlock (src, dst, dst.typ.size)
- END
- END;
- ELSE OCC.Move (L, src, dst)
- END
- ELSIF
- (g = Pointer) & (OCT.Tagged (src.typ) = OCT.Tagged (dst.typ))
- THEN
- p := dst.typ.BaseTyp; q := src.typ.BaseTyp;
- IF (p.form = Record) & (q.form = Record) THEN
- WHILE (q # p) & (q # NIL) DO q := q.BaseTyp END;
- IF q # NIL THEN movePtr (src, dst)
- ELSE OCS.Mark (113)
- END
- ELSE OCS.Mark (113)
- END
- ELSIF (g IN {AdrTyp, BPtrTyp}) & ~OCT.Tagged (dst.typ) THEN
- movePtr (src, dst)
- ELSE OCS.Mark (113)
- END
- |
- PtrTyp :
- IF
- ( (g = Pointer) & (src.typ.sysflg = OberonFlag)
- & (src.typ.BaseTyp # NIL) & (src.typ.BaseTyp.form # DynArr) )
- OR (g IN {PtrTyp, NilTyp})
- THEN
- OCC.Move (L, src, dst)
- ELSE OCS.Mark (113)
- END
- |
- AdrTyp :
- IF
- ((g = Pointer) & (src.typ.sysflg IN {M2Flag, CFlag, AsmFlag}))
- OR (g IN {AdrTyp, NilTyp})
- THEN
- movePtr (src, dst)
- ELSE OCS.Mark (113)
- END
- |
- BPtrTyp :
- IF
- ((g = Pointer) & (src.typ.sysflg = BCPLFlag))
- OR (g IN {BPtrTyp, NilTyp})
- THEN
- movePtr (src, dst)
- ELSE OCS.Mark (113)
- END
- |
- Array :
- IF dst.mode # Pointer THEN
- IF dst.typ = src.typ THEN
- moveBlock (src, dst, dst.typ.size)
- ELSIF (g = String) & (dst.typ.BaseTyp = OCT.chartyp) THEN
- freeDst := FALSE;
- IF dst.mode = Push THEN
- ExtendStack (dst.typ.size);
- y.mode := Reg; y.a0 := dst.a0;
- OCC.GetAReg (dst, NIL); OCC.Move (L, y, dst);
- dst.mode := RegI; dst.a1 := 0;
- freeDst := TRUE
- END;
- z.mode := Con; z.typ := OCT.inttyp; z.a0 := src.a1 - 1;
- vsz := dst.typ.n - 1; IF z.a0 > vsz THEN OCS.Mark (114) END;
- OCI.CopyString (src, dst, z);
- IF freeDst THEN OCC.FreeReg (dst) END
- ELSE
- OCS.Mark (113)
- END
- ELSE
- OCS.Mark (904)
- END
- |
- DynArr :
- IF param THEN (* formal parameter is open array *)
- IF dst.mode = Reg THEN
- (* Register parameter, address only *)
- IF
- (dst.typ.BaseTyp = OCT.bytetyp)
- OR ((g = String) & (dst.typ.BaseTyp.form = Char))
- OR ((g IN {Array, DynArr})
- & (src.typ.BaseTyp = dst.typ.BaseTyp))
- THEN
- IF (g = String) & (dst.typ.BaseTyp.form = Char) THEN
- IF src.a1 = 2 THEN OCC.AllocStringFromChar (src) END;
- IF src.a1 = 1 THEN (* Pass NIL for an empty string *)
- src.mode := Con; src.a0 := 0; OCC.Move (L, src, dst)
- ELSE
- OCI.MoveAdr (src, dst)
- END
- ELSE
- OCI.MoveAdr (src, dst)
- END;
- ELSE
- OCS.Mark (59)
- END
- ELSE
- IF (g = String) & (dst.typ.BaseTyp.form = Char) THEN
- Leng (dst, src.a1);
- IF src.a1 < 3 THEN OCC.AllocStringFromChar (src) END
- ELSIF src.mode >= Abs THEN
- OCS.Mark (59)
- ELSE
- DynArrBnd (dst.typ, src, FALSE)
- END;
- IF (g = DynArr) OR (src.mode IN {Ind, IndX}) THEN
- OCI.MoveAdr (src, dst)
- ELSE
- OCC.PutF3 (OCC.PEA, src)
- END
- END
- ELSE
- OCS.Mark (113)
- END
- |
- Record :
- (* IF (dst.mode = Reg) (*& (src.typ.size > PtrSize)*) THEN *)
- (* OCS.Mark (904) *)
- (* ELSE *)
- IF dst.typ # src.typ THEN
- IF g = Record THEN
- q := src.typ.BaseTyp;
- WHILE (q # NIL) & (q # dst.typ) DO q := q.BaseTyp END;
- IF q = NIL THEN OCS.Mark (113) END
- ELSE OCS.Mark (113)
- END
- END;
- IF
- (dst.typ.sysflg = OberonFlag)
- & OCS.pragma [OCS.typeChk] & ~param
- & ( ((dst.mode = Ind) OR (dst.mode = RegI))
- & (dst.obj = OCC.wasderef)
- (* p^ := *)
- OR (dst.mode = Ind) & (dst.obj # NIL)
- & (dst.obj # OCC.wasderef))
- (* varpar := *)
- THEN
- R := OCC.regState; tag := dst; tag.typ := OCT.tagtyp;
- IF dst.obj = OCC.wasderef THEN tag.a1 := -4
- ELSE tag.mode := Var; INC (tag.a0, 4)
- END;
- tdes.mode := Con; tdes.a0 := 0; tdes.a1 := 0;
- tdes.typ := OCT.tagtyp; tdes.label := dst.typ.label;
- OCI.Adr (tdes); OCI.CMP (L, tdes, tag);
- OCC.TrapCC (OCC.TypeCheck, OCC.NE);
- OCC.FreeRegs (R)
- END;
- moveBlock (src, dst, dst.typ.size)
- (* END *)
- |
- ProcTyp :
- IF (dst.typ = src.typ) OR (g = NilTyp) THEN
- IF (src.mode = XProc)
- OR ((OCM.SmallData OR OCM.Resident) & (src.mode = LProc))
- THEN
- OCI.MoveAdr (src, dst)
- ELSIF src.mode IN {LProc, TProc, LibCall, AProc, M2Proc, CProc} THEN
- OCS.Mark (119)
- ELSE OCC.Move (L, src, dst)
- END;
- ELSIF (src.mode = XProc)
- OR ((OCM.SmallData OR OCM.Resident) & (src.mode = LProc))
- THEN
- (* procedure dest to proc. variable, check compatibility *)
- IF dst.typ.BaseTyp = src.typ THEN
- CompareParLists (dst.typ.link, src.obj.link);
- OCI.MoveAdr (src, dst)
- ELSE OCS.Mark (118)
- END
- ELSIF src.mode IN {LProc, TProc, LibCall, AProc, M2Proc, CProc} THEN
- OCS.Mark (119)
- ELSE OCS.Mark (111)
- END
- |
- TagTyp :
- IF (f = g) OR (g = NilTyp) THEN OCC.Move (L, src, dst)
- ELSE OCS.Mark (111)
- END
- |
- NoTyp, NilTyp : OCS.Mark (111)
- |
- ELSE
- OCS.Mark (1016); OCS.Warn (f)
- END; (* CASE f *)
- OCC.ForgetObj (dst.obj);
- OCI.Unload (src)
- END Assign;
-
- (*------------------------------------*)
- PROCEDURE RegsUsed ( fpar : OCT.Object ) : SET;
-
- VAR result : SET;
-
- BEGIN (* RegsUsed *)
- result := {};
- WHILE (fpar # NIL) & OCT.IsParam (fpar) DO
- INCL (result, fpar.a0); fpar := fpar.link
- END;
- RETURN result
- END RegsUsed;
-
- (*------------------------------------*)
- PROCEDURE PrepCall *
- ( VAR x : OCT.Item;
- VAR fpar : OCT.Object;
- VAR mask : SET );
-
- VAR y : OCT.Item;
-
- BEGIN (* PrepCall *)
- mask := OCC.AllRegs;
- IF x.mode IN {LProc, XProc, AProc, LibCall, M2Proc, CProc} THEN
- fpar := x.obj.link;
- IF x.mode IN {LibCall, AProc} THEN
- mask := OCC.ScratchRegs + RegsUsed (fpar);
- IF x.mode = LibCall THEN
- INCL (mask, A6)
- END
- END
- ELSIF x.mode = TProc THEN
- fpar := x.obj.link.link;
- ELSIF (x.typ # NIL) & (x.typ.form = ProcTyp) THEN
- fpar := x.typ.link
- ELSE
- OCS.Mark (121); fpar := NIL; x.typ := OCT.undftyp
- END
- END PrepCall;
-
- (* ---------------------------------- *)
- PROCEDURE VarArgParam *
- ( VAR ap : OCT.Item;
- fpo : OCT.Object;
- load : BOOLEAN );
-
- VAR fp, reg : OCT.Item;
-
- BEGIN (* VarArgParam *)
- fp.mode := Push; fp.a0 := A7; fp.typ := fpo.typ; fp.rdOnly := FALSE;
- Assign (fp, ap, TRUE);
- IF load THEN
- fp.mode := Reg; reg.mode := Reg; reg.a0 := fpo.a0;
- OCC.ReserveReg (reg.a0, NIL);
- OCC.Move (L, fp, reg)
- END;
- END VarArgParam;
-
- (*------------------------------------*)
- PROCEDURE Param * (VAR ap : OCT.Item; fpo : OCT.Object; mode : INTEGER);
-
- VAR
- fp, t : OCT.Item; q : OCT.Struct; freeFp : BOOLEAN; f, g : INTEGER;
- s : LONGINT;
-
- BEGIN (* Param *)
- IF mode IN {LibCall, AProc} THEN (* Register parameter *)
- fp.mode := Reg; fp.a0 := fpo.a0
- ELSE (* Stack parameter *)
- fp.mode := Push; fp.a0 := SP
- END;
- fp.typ := fpo.typ; fp.rdOnly := FALSE;
-
- f := fpo.typ.form; g := ap.typ.form;
- IF fpo.mode = Ind THEN (* VAR parameter *)
- IF ap.mode >= Con THEN OCS.Mark (122)
- ELSIF ap.rdOnly THEN OCS.Mark (324)
- END;
- IF fp.typ.form = DynArr THEN
- IF fp.mode = Reg THEN
- OCI.MoveAdr (ap, fp)
- ELSE
- IF mode # CProc THEN DynArrBnd (fp.typ, ap, TRUE) END;
- IF (ap.typ.form = DynArr) OR (ap.mode IN {Ind, IndX}) THEN
- OCI.MoveAdr (ap, fp)
- ELSE
- OCC.PutF3 (OCC.PEA, ap)
- END
- END
- ELSIF (fp.typ.form = Record) & (ap.typ.form = Record) THEN
- q := ap.typ; WHILE (q # fp.typ) & (q # NIL) DO q := q.BaseTyp END;
- IF q # NIL THEN
- IF (ap.mode = Ind) & (ap.obj # NIL) & (ap.obj # OCC.wasderef) THEN
- (* actual parameter is a VAR parameter *)
- ap.mode := Var;
- IF q.sysflg = OberonFlag THEN
- INC (ap.a0, 4); OCC.Move (L, ap, fp);
- IF ap.mode = Var THEN DEC (ap.a0, 4) ELSE DEC (ap.a1, 4) END;
- END;
- OCC.Move (L, ap, fp)
- ELSIF
- ((ap.mode = Ind) OR (ap.mode = RegI)) & (ap.obj = OCC.wasderef)
- THEN
- (* actual parameter is a dereferenced pointer *)
- IF q.sysflg = OberonFlag THEN
- ap.a1 := -4; OCC.Move (L, ap, fp);
- ap.a1 := 0;
- END;
- OCI.MoveAdr (ap, fp)
- ELSE
- IF q.sysflg = OberonFlag THEN
- t.mode := Con; t.a0 := 0; t.a1 := 0; t.typ := OCT.tagtyp;
- t.label := ap.typ.label;
- OCC.PutF3 (OCC.PEA, t)
- END;
- IF fp.mode = Reg THEN OCI.MoveAdr (ap, fp)
- ELSE OCC.PutF3 (OCC.PEA, ap)
- END
- END
- ELSE OCS.Mark (111)
- END
- ELSIF
- (ap.typ = fp.typ)
- OR ((f = Byte) & (g IN {Char, SInt, BSet}))
- OR ((f = Word) & (g IN wordSet))
- OR ((f = Longword) & (g IN lwordSet))
- OR ((f = PtrTyp) & (g = Pointer) & (ap.typ.sysflg = OberonFlag))
- OR ((f = AdrTyp) & (g = Pointer) & (ap.typ.sysflg IN {M2Flag, CFlag, AsmFlag}))
- OR ((f = BPtrTyp) & (g = Pointer) & (ap.typ.sysflg = BCPLFlag))
- THEN
- IF (ap.mode IN {Ind, IndX}) OR (fp.mode = Reg) THEN
- OCI.MoveAdr (ap, fp)
- ELSE
- OCC.PutF3 (OCC.PEA, ap)
- END
- ELSE OCS.Mark (123)
- END;
- OCI.Unload (ap)
- ELSE
- Assign (fp, ap, TRUE);
- END;
- IF mode IN {LibCall, AProc} THEN (* Reserve parameter's register *)
- OCC.ReserveReg (fp.a0, NIL)
- END
- END Param;
-
- (*------------------------------------*)
- PROCEDURE DeRef (VAR x : OCT.Item);
-
- VAR t1, t2 : OCT.Item;
-
- BEGIN (* DeRef *)
- IF (x.mode <= RegX) & (x.typ.form = Pointer) THEN
- IF OCC.InAdrReg (x.obj) THEN
- OCC.GetAReg (x, x.obj); x.mode := RegI
- ELSE
- t1 := x; t1.obj := NIL; t1.typ := OCT.ptrtyp; OCC.GetAReg (x, x.obj);
- IF OCS.pragma [OCS.nilChk] THEN
- OCC.GetDReg (t2, NIL); OCC.Move (L, t1, t2); (* MOVE.L x,Dn *)
- OCC.TrapCC (OCC.NilCheck, OCC.EQ);
- OCC.Move (L, t2, x); OCI.Unload (t2) (* MOVEA.L Dn, An *)
- ELSE
- OCC.Move (L, t1, x); (* MOVEA.L x, An *)
- END;
- x.mode := RegI
- END;
- x.typ := x.typ.BaseTyp; x.obj := OCC.wasderef; x.rdOnly := FALSE;
- x.a2 := 0
- ELSE
- OCS.Mark (84)
- END;
- x.a1 := 0
- END DeRef;
-
- (*------------------------------------*)
- PROCEDURE Receiver *
- ( mode : SHORTINT;
- VAR x : OCT.Item;
- rcvr : OCT.Object;
- mask : SET );
-
- VAR t1 : OCT.Item; R : OCC.RegState;
-
- BEGIN (* Receiver *)
- IF mode = TProc THEN
- t1 := x;
- IF (t1.typ.form = Pointer) & (rcvr.mode = Ind) THEN DeRef (t1) END;
- R := OCC.regState; Param (t1, rcvr, TProc); OCC.regState.regs := R.regs
- ELSIF (OCM.SmallData OR OCM.Resident) & (A4 IN mask) THEN
- OCC.ReserveReg (A6, NIL);
- t1.mode := Reg; t1.a0 := A6; OCC.Move (L, x, t1);
- END;
- END Receiver;
-
- (*------------------------------------*)
- PROCEDURE Call *
- ( VAR x, rcvr : OCT.Item;
- stackload : LONGINT;
- mask : SET );
-
- VAR y, z : OCT.Item; offset : LONGINT;
-
- BEGIN (* Call *)
- IF x.mode = LProc THEN
- IF x.lev > 0 THEN
- y.mode := Var; y.typ := OCT.linttyp;
- IF x.lev = OCC.level THEN
- y.lev := x.lev; y.a0 := 0; OCC.PutF3 (OCC.PEA, y)
- ELSE
- y.lev := x.lev + 1; y.a0 := 8; z.mode := Push; z.a0 := SP;
- OCC.Move (L, y, z)
- END
- END;
- OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, x.label)
- ELSIF x.mode IN {XProc, M2Proc, CProc, AProc} THEN
- IF OCM.SmallCode OR ((x.mode = XProc) & (x.lev = 0)) THEN
- OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, x.label)
- ELSE
- OCC.PutF3 (OCC.JSR, x)
- END
- ELSIF x.mode = TProc THEN
- IF x.a2 < 0 THEN (* Super-call, call directly *)
- x.lev := -x.obj.link.typ.mno;
- IF OCM.SmallCode OR (x.lev = 0) THEN
- OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, x.label)
- ELSE
- x.mode := XProc; OCC.PutF3 (OCC.JSR, x)
- END
- ELSE
- y := rcvr;
- IF y.typ.form = Pointer THEN DeRef (y) END;
- IF x.obj.a0 >= 0 THEN offset := x.obj.a0 * (-4)
- ELSE offset := x.obj.a2
- END;
- IF (y.mode IN {RegI, Ind}) & (y.obj = OCC.wasderef) THEN
- (* rcvr is dereferenced pointer *)
- OCC.GetAReg (z, NIL); y.a1 := -4; OCC.Move (L, y, z);
- y.mode := RegI; y.a0 := z.a0; y.a1 := offset; OCC.Move (L, y, z);
- IF offset >= 0 THEN x.obj.a2 := OCC.pc - 2 END;
- z.mode := RegI; z.a1 := 0; OCC.PutF3 (OCC.JSR, z)
- ELSIF (y.mode = Ind) & (y.obj # NIL) & (y.obj # OCC.wasderef) THEN
- (* rcvr is record variable parameter *)
- y.mode := Var; INC (y.a0, 4);
- OCC.GetAReg (z, NIL); OCC.Move (L, y, z);
- y.mode := RegI; y.a0 := z.a0; y.a1 := offset; OCC.Move (L, y, z);
- IF offset >= 0 THEN x.obj.a2 := OCC.pc - 2 END;
- z.mode := RegI; z.a1 := 0; OCC.PutF3 (OCC.JSR, z);
- ELSE
- (* rcvr is record variable *)
- x.lev := -x.obj.link.typ.mno;
- IF OCM.SmallCode OR (x.lev = 0) THEN
- OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, x.label)
- ELSE
- x.mode := XProc; OCC.PutF3 (OCC.JSR, x)
- END
- END
- END
- ELSIF x.mode = LibCall THEN
- y.a0 := A6;
- IF ~((OCM.SmallData OR OCM.Resident) & (A4 IN mask)) THEN
- OCC.ReserveReg (A6, NIL);
- y.mode := Reg; OCC.Move (L, rcvr, y);
- END;
- OCC.UnReserveReg (A6);
- y.mode := RegI; y.a1 := x.a0; OCC.PutF3 (OCC.JSR, y)
- ELSIF (x.mode < Con) & (x.typ # OCT.undftyp) THEN (* procedure variable *)
- IF OCC.InAdrReg (x.obj) THEN
- OCC.GetAReg (x, x.obj)
- ELSE
- y := x; y.typ := OCT.ptrtyp; OCC.GetAReg (x, x.obj);
- IF OCS.pragma [OCS.nilChk] THEN
- OCI.Load (y); (* MOVE.L x,Dn *)
- OCC.TrapCC (OCC.NilCheck, OCC.EQ)
- END;
- OCC.Move (L, y, x); OCI.Unload (y)
- END;
- x.mode := RegI; x.a1 := 0;
- OCC.PutF3 (OCC.JSR, x);
- x.typ := x.typ.BaseTyp
- ELSE
- OCS.Mark (121)
- END;
- IF x.mode IN {LibCall, CProc, AProc} THEN
- IF stackload > 0 THEN
- IF stackload <= 8 THEN
- y.mode := Reg; y.a0 := SP;
- OCC.PutF7 (OCC.ADDQ, L, stackload, y)
- ELSE
- y.mode := RegI; y.a0 := SP; y.a1 := stackload;
- OCC.PutF2 (OCC.LEA, y, SP)
- END
- END
- END
- END Call;
-
- (*------------------------------------*)
- PROCEDURE Result * (VAR x : OCT.Item; typ : OCT.Struct);
-
- VAR res : OCT.Item; R : SET; reg : INTEGER;
-
- BEGIN (* Result *)
- IF
- (typ.form = Pointer) & (typ.sysflg = OberonFlag)
- & (typ.BaseTyp # NIL) & (typ.BaseTyp.form = DynArr)
- THEN
- res.mode := RList; R := {}; reg := D0;
- WHILE (reg * 4) < typ.size DO INCL (R, reg); INC (reg) END;
- res.a0 := SYS.VAL (LONGINT, R)
- ELSE
- res.mode := Reg; res.a0 := D0
- END;
- res.typ := typ; res.rdOnly := FALSE;
- Assign (res, x, FALSE);
- returnFound := TRUE
- END Result;
-
- (*------------------------------------*)
- PROCEDURE CaseIn * (VAR x : OCT.Item; VAR L0 : LONGINT);
-
- BEGIN (* CaseIn *)
- IF ~(x.typ.form IN caseSet) THEN OCS.Mark (125) END;
- OCI.Load (x); OCC.UnReserveReg (x.a0); L0 := 0; FJ (L0)
- END CaseIn;
-
- (*------------------------------------*)
- PROCEDURE CaseOut *
- ( VAR x : OCT.Item;
- L0, L1, L2 : LONGINT;
- n : INTEGER;
- VAR tab : ARRAY OF LabelRange);
-
- VAR labItem, y, z : OCT.Item; i : INTEGER; L3 : LONGINT;
-
- BEGIN (* CaseOut *)
- labItem.mode := Con; labItem.typ := x.typ; i := 0;
- OCC.FixLink (L0); (* fixup jump from case expression *)
- WHILE i < n DO
- IF tab [i].low = tab [i].high THEN
- y := x; labItem.a0 := tab [i].low; OCE.Op (neq, y, labItem, FALSE);
- CBJ (y, tab [i].label)
- ELSE
- L3 := 0; y := x; labItem.a0 := tab [i].low;
- OCE.Op (geq, y, labItem, FALSE); CFJ (y, L3); z := x;
- labItem.a0 := tab [i].high; OCE.Op (gtr, z, labItem, FALSE);
- CBJ (z, tab [i].label); OCC.fixup (L3)
- END;
- INC (i)
- END;
- BJ (L2); (* jump to code for else part *)
- OCC.FixLink (L1); (* fixup jumps from individual cases *)
- END CaseOut;
-
- (*------------------------------------*)
- PROCEDURE BeginFor *
- ( VAR control, low, high, step : OCT.Item;
- VAR R : OCC.RegState;
- VAR L0, L1 : LONGINT );
-
- VAR f, g, h, i : INTEGER; x, y : OCT.Item;
-
- BEGIN (* BeginFor *)
- f := control.typ.form; g := low.typ.form; h := high.typ.form;
- i := step.typ.form;
- IF (f IN intSet) & (g IN intSet) & (h IN intSet) & (i IN intSet) THEN
- IF low.mode = Con THEN
- IF (f = Int) & (g = LInt) THEN OCS.Mark (317)
- ELSIF (f = SInt) & (g # SInt) THEN OCS.Mark (317)
- END;
- low.typ := control.typ
- END;
- IF high.mode = Con THEN
- IF (f = Int) & (h = LInt) THEN OCS.Mark (317)
- ELSIF (f = SInt) & (h # SInt) THEN OCS.Mark (317)
- END;
- high.typ := control.typ
- ELSE OCI.Load (high)
- END;
- IF (f = Int) & (i = LInt) THEN OCS.Mark (317)
- ELSIF (f = SInt) & (i # SInt) THEN OCS.Mark (317)
- END;
- step.typ := control.typ;
- IF (low.mode = Con) & (high.mode = Con) THEN
- IF (step.a0 > 0) & (high.a0 < low.a0) THEN OCS.Mark (318)
- ELSIF (step.a0 < 0) & (low.a0 < high.a0) THEN OCS.Mark (318)
- END
- END;
- x := control; Assign (x, low, FALSE);
- OCC.ForgetRegs; OCC.FreeRegs (R);
- IF high.mode = Reg THEN OCC.ReserveReg (high.a0, NIL) END;
- L0 := OCC.pc; x := control; y := high;
- IF high.mode = Con THEN
- IF step.a0 > 0 THEN OCE.Op (leq, x, y, FALSE);
- ELSE OCE.Op (geq, x, y, FALSE);
- END;
- CFJ (x, L1)
- ELSE
- IF step.a0 > 0 THEN OCE.Op (geq, y, x, FALSE);
- ELSE OCE.Op (leq, y, x, FALSE);
- END;
- CFJ (y, L1)
- END;
- END
- END BeginFor;
-
- (*------------------------------------*)
- PROCEDURE EndFor *
- ( VAR control, step, high : OCT.Item; L0, L1 : LONGINT );
-
- BEGIN (* EndFor *)
- IF step.a0 > 0 THEN OCC.PutF5 (OCC.ADD, step.typ.size, step, control)
- ELSE
- step.a0 := -step.a0; OCC.PutF5 (OCC.SUB, step.typ.size, step, control)
- END;
- (*IF OCS.overflowCheck THEN OCC.PutWord (OCC.TRAPV) END;*)
- BJ (L0); OCC.FixLink (L1);
- IF high.mode = Reg THEN OCC.UnReserveReg (high.a0) END;
- END EndFor;
-
- END OCH.
-
- (***************************************************************************
-
- $Log: OCH.mod $
- Revision 5.25 1995/06/15 18:15:13 fjc
- - Fixed YARAB (Yet Another Register Allocation Bug)
- affecting type-bound procedures.
-
- Revision 5.24 1995/06/04 22:51:00 fjc
- - Fixed loading of A6 for library calls where A4 is used
- for parameters.
-
- Revision 5.23 1995/06/03 00:36:42 fjc
- - Amiga Library calls now load the base variable into A6
- *before* loading any parameters.
-
- Revision 5.22 1995/06/02 18:43:09 fjc
- - Implemented the SMALLDATA, RESIDENT and REGISTER options.
-
- Revision 5.22 1995/05/29 21:22:28 fjc
- - Various changes to support the SMALLDATA and RESIDENT
- options.
-
- Revision 5.21 1995/05/13 23:09:43 fjc
- - Changed INTEGER to LONGINT where necessary.
-
- Revision 5.20 1995/05/08 17:04:24 fjc
- - OCI.IsParam() --> OCT.IsParam()
-
- Revision 5.19 1995/04/23 17:59:39 fjc
- - Merging 5.26 & 5.27
-
- Revision 5.17 1995/04/02 13:53:40 fjc
- - Numerous changes to implement the small data model.
-
- Revision 5.16 1995/03/25 17:08:00 fjc
- - Added stripped-down version of OCE.DeRef() to be used
- by Receiver() and Call().
-
- Revision 5.15 1995/03/23 18:27:06 fjc
- - Modifications to Call(), BeginFor() and EndFor().
-
- Revision 5.14 1995/03/13 11:36:30 fjc
- - LibCalls now reserve the A6 register as a precaution,
- probably unnecessary.
-
- Revision 5.13 1995/03/09 19:12:00 fjc
- - Incorporated changes from 5.22.
-
- Revision 5.12 1995/02/27 17:08:00 fjc
- - Removed tracing code.
- - Implemented SMALLCODE option.
- - Changed to use new register handling procedures.
-
- Revision 5.11.1.1 1995/03/08 19:24:14 fjc
- - OC 5.22
-
- Revision 5.11 1995/01/26 00:17:17 fjc
- - Release 1.5
-
- Revision 5.10 1995/01/03 21:23:57 fjc
- - Changed OCG to OCM.
-
- Revision 5.9 1994/12/16 17:38:11 fjc
- - Changed Symbol to Label.
- - Changed Call() to generate a fixup list for calls to
- type-bound procedures which have not yet been allocated
- a slot.
-
- Revision 5.8 1994/11/13 11:35:10 fjc
- - Changed Assign() to make SYSTEM.PTR incompatible with
- POINTER TO ARRAY OF ...
-
- Revision 5.7 1994/10/23 16:26:35 fjc
- - Rewrote ModulePrologue() to call module Kernel's
- initialisation code.
- - All calls to the RTS are now through OCC.CallKernel().
- - Rewrote code for pointer assignments.
- - Fixed bug in code for procedure variable assignments.
- - Merged CallLibCall() and CallTypeBound() into Call().
-
- Revision 5.6 1994/09/25 18:05:21 fjc
- - Changed to reflect new object modes and system flags,
- espcially:
- - Merged Param() and RegParam().
- - Overhauled handling of pointer assignments.
-
- Revision 5.5 1994/09/19 23:10:05 fjc
- - Re-implemented Amiga library calls
-
- Revision 5.4 1994/09/15 19:43:51 (fnc
- -(Merged in bug fix from 4.17.
-
- Revision 5.3 1994/09/15 10:40:23 fjc
- - Replaces switches with pragmas.
- - Implemented the EntryExitCode pragma and the INITIALISE
- and MAIN options.
-
- Revision 5.2 1994/09/08 10:52:07 fjc
- - Changed to use pragmas/options.
-
- Revision 5.1 1994/09/03 19:29:08 fjc
- - Bumped version number
-
- ***************************************************************************)
-