DEFINITION MODULE M2XM;
(*$ LargeVars:=FALSE NameChk:=FALSE LongAlign:=FALSE *)

FROM M2DM	IMPORT	WidType,RegType,Register,RegisterSet,
			ObjPtr,StrForm,StrPtr,ConstValue,
			Condition,Ident;

TYPE
  (* 20.12.90/bp conMd aufgeteilt in virtuell und memconMd! *)
  ItemMode=(
    absMd,ExtMd,FarMd,RindMd,RidxMd,vconMd,memconMd,stkMd,AregMd,DregMd,cocMd,
    typMd,procMd,codMd,modMd,prgMd,fltMd
  );
  ItSet=SET OF ItemMode;
  Item=RECORD
    typ:StrPtr;
    adrtoload:BOOLEAN;
    nilToCheck:BOOLEAN; (* wird von GenDeRef und CallInd gesetzt, dann Gea *)
    CASE mode:ItemMode OF
    | absMd,FarMd,ExtMd,RindMd,RidxMd,stkMd,AregMd,DregMd:
      iniVars:BOOLEAN; (* wichtig für FarMd und RindMd... *)
      mod,lev:INTEGER;
      adr,off:LONGINT;
      R,RX:Register;
      wid:WidType;
      indir:BOOLEAN;
      vname:Ident;
    | vconMd,memconMd: val:ConstValue; size:INTEGER;
       conOffset:INTEGER; (* nur mecon! x="abc" ==> x[2] !! *)
    | cocMd: CC:Condition; Tjmp,Fjmp:INTEGER;
    | procMd,codMd: proc:ObjPtr;
    | prgMd: where:INTEGER;
    | modMd: module:ObjPtr;
    | fltMd: FR:Register;
    | typMd: (* no field *)
    END;
  END;
  ItemPtr=POINTER TO Item;

  RegMode = (nothing, const, varPtr, libPtr, level);
  (* abs nur bei 4 (execbase) merken, bringt nichts, also lassen! *)
  RegContents = RECORD
    CASE mode: RegMode OF
    | nothing:  (* nix, Reg ungültig!! *)
    | const: cVal: LONGINT; wid:WidType; (* const *)
    | varPtr: it:Item; (* bis auf Rx alles benutzt, nur Rind,A4,A5! *)
    | level: lv:INTEGER;
    | libPtr: mno:INTEGER;
    | (* to be continued... *)
    END;
  END;

VAR
  curLev:INTEGER;
  Rpool,Rbusy,Rlock,UsedRegs:RegisterSet;
  trickAidr:BOOLEAN; (* oneShot für Umwandlung (An) --> (An)+ *)

PROCEDURE SignedT(VAR x:Item):BOOLEAN;   (* is x a signed type *)
PROCEDURE UnsignedT(VAR x:Item):BOOLEAN; (* is x an unsigned type *)
PROCEDURE NumT(VAR x:Item):BOOLEAN;      (* is x a number type *)

PROCEDURE DiffCC(x,y:ConstValue; VAR dh,dl:LONGINT);
PROCEDURE AssignComp(x,y:StrPtr):BOOLEAN;
PROCEDURE ConstSize(v:LONGINT; signed:BOOLEAN):INTEGER;

PROCEDURE SetglbMd(VAR x:Item; fadr:LONGINT; ftyp:StrPtr);
PROCEDURE SetlocMd(VAR x:Item; fadr:LONGINT; ftyp:StrPtr);
PROCEDURE SetregMd(VAR x:Item; freg:Register; ftyp:StrPtr);
PROCEDURE SetfltMd(VAR x:Item; fR:Register; ftyp:StrPtr);
PROCEDURE SetcocMd(VAR x:Item; fcc:Condition);
PROCEDURE SetstkMd(VAR x:Item; ftyp:StrPtr);
PROCEDURE SetconMd(VAR x:Item; fval:LONGINT; ftyp:StrPtr);

PROCEDURE SetErrMd(VAR x:Item; ftyp:StrPtr); (* statt SetregMd(x,d0,undftyp!) *)
PROCEDURE FreeD0; (* falls d0Ptr#NIL: wegkopieren! *)
PROCEDURE NeedD0(VAR x:Item);
PROCEDURE SwapD0(VAR x,y:Item);
PROCEDURE GetReg(VAR r:Register; qual:RegType);
PROCEDURE GetFReg(VAR r:Register);
PROCEDURE Release(VAR x:Item);
PROCEDURE ReleaseReg(r:Register);
PROCEDURE LockReg(r:Register);
PROCEDURE UnlockReg(r:Register);
PROCEDURE Islocked(r:Register):BOOLEAN;
PROCEDURE SetbusyReg(r:Register);
PROCEDURE IsBusy(r:Register):BOOLEAN;
PROCEDURE SaveRegs(VAR save:RegisterSet; mask:RegisterSet);
PROCEDURE RestoreRegs(save:RegisterSet);
PROCEDURE CheckRegs;

PROCEDURE InitM2XM;

PROCEDURE StackTop(i:LONGINT);                 (* increment stack pointer SP*)
PROCEDURE InvertCC(cond: Condition): Condition;(* inverse condition *)
PROCEDURE Jf(cond: Condition; VAR l: INTEGER); (* jump forward *)
PROCEDURE Jb(cond: Condition; l: INTEGER);     (* jump backward *)

PROCEDURE Expo(r{0}:LONGREAL):INTEGER;
PROCEDURE Isz(VAR x: Item; VAR fsz: WidType);
PROCEDURE Scc(cond: Condition; Dn: Register);
PROCEDURE LoadCC(VAR x: Item);
PROCEDURE Ext(VAR x: Item);
PROCEDURE Gea(VAR x: Item; VAR fea: CARDINAL; destr:BOOLEAN);
PROCEDURE LoadAdr(VAR x:Item);   (* load address of x *)
PROCEDURE LoadP(VAR x:Item);     (* load pointer design. by x *)
PROCEDURE LoadX(VAR x:Item; req:WidType; willBeDestroyed:BOOLEAN);
(* load and extend value(x) to requested width *)

PROCEDURE MoveAdr(VAR x,y:Item); (* adr(x) --> y *)
PROCEDURE MoveBlock(VAR x,y:Item; sz:LONGINT; isstring:BOOLEAN);
(* move 'sz' bytes of x to y *)

PROCEDURE Move(VAR x,y: Item);
PROCEDURE LoadD(VAR x: Item; willBeDestroyed:BOOLEAN);
PROCEDURE FMove(VAR x,y:Item);

(* 1. Schritt zum Supercompiler *)
(* LaodD und LoadX , TRUE setzen automatisch Regs ungültig! und wid!! *)
PROCEDURE AllRegsDestroyed; (* alle Register ungültig *)
PROCEDURE RegsDestroyed(reg:RegisterSet); (* mehrere Register ungültig *)
PROCEDURE RegDestroyed(reg:Register); (* EIN Register ungültig *)
PROCEDURE PointersDestroyed(localsDestr:BOOLEAN); (* glob immer TRUE! *)
PROCEDURE AmigaDestroyed; (* destr d0,d1,a0,a1 *)

PROCEDURE MoveConstToReg(val:LONGINT; reg:Register);
PROCEDURE MoveConstWordToDReg(val:LONGINT; reg:Register);
(* erzeugt Code! *)

PROCEDURE GetConstReg(val:LONGINT; VAR reg:Register; VAR new:BOOLEAN);
(* Macht GetReg und lädt. Immer DReg!!
  Reg wird später nicht zerstört, ich brauche nur eine Konstante im Reg!
  Wenn new, dann muß es Released werden
*)

PROCEDURE LibToAreg(mnr:INTEGER; reg:Register);
PROCEDURE LoadA6(mnr:INTEGER);

PROCEDURE IsByte(l{6}:LONGINT):BOOLEAN;
PROCEDURE IsWord(l{6}:LONGINT):BOOLEAN;

(* konvertiert LR-Const to FFP oder Real-Const
   Dies darf aber nur direkt in CAST aufgerufen werden,
   weil sonst alles in die Hose geht!
   Vielen Dank an die Genies, die das vebockt haben!
 *)
PROCEDURE ConvLRConstTo(VAR x:Item; frm:StrForm);

END M2XM.
