-- file: PeepholeZ.mesa
-- last edited by Sweet on July 24, 1980  9:33 AM
-- last edited by Satterthwaite on June 1, 1982 9:13 am

DIRECTORY
  Alloc: TYPE USING [Notifier],
  Code: TYPE USING [bodyFileIndex],
  CodeDefs: TYPE USING [Base, CCIndex, CCNull, CodeCCIndex, codeType, JumpCCIndex],
  ComData: TYPE USING [textIndex, switches],
  FOpCodes: TYPE USING [
    qADD, qALLOC, qAMUL, qAND, qBCAST, qBCASTL, qBITBLT, qBLT, qBLTC, qBLTCL, 
    qBLTL, qBLZL, qBNDCK, qBRK, qCATCH, qDADD, qDBL, qDCOMP, qDDIV, qDESCB,
    qDESCBS, qDIV, qDST, qDSUB, qDMOD, qDMUL, qDUP, qDUCOMP, qDUDIV, qDUMOD,
    qDWDC, qEFC, qEXCH, qFADD, qFCOMP, qFDIV, qFLOAT, qFMUL, qFREE, qFSC,
    qFSUB, qGADRB, qGCRT, qICDL, qINC, qIWDC, qKFCB, qLADRB, qLCO, qLDIV,
    qLFC, qLG, qLGD, qLI, qLINKB, qLL, qLLD, qLLK, qLP, qLST, qLSTF, qME, qMEL,
    qMRE, qMREL, qMUL, qMXD, qMXDL, qMXW, qMXWL, qNEG, qNILCK, qNILCKL,
    qNOTIFY, qNOTIFYL, qOR, qPL, qPOP, qPORTI, qPORTO, qPS, qPSD, qPSF, qPUSH,
    qR, qRD, qRDL, qREQUEUE, qREQUEUEL, qRET, qRF, qRFC, qRFL, qRFS, qRFSL,
    qRIG, qRIGL, qRIL, qRILL, qRL, qRR, qRSTR, qRSTRL, qRXGL, qRXL, qRXLL,
    qSFC, qSG, qSGD, qSHIFT, qSL, qSLD, qSTARTIO, qSTOP, qSUB, qW, qWCDL,
    qWD, qWDL, qWF, qWFL, qWFS, qWFSL, qWIGL, qWIL, qWILL, qWL, qWR,
    qWS, qWSD, qWSF, qWSTR, qWSTRL, qWXGL, qWXL, qWXLL, qXOR],
  Log: TYPE USING [Error],
  MiscAlpha: TYPE USING [aFADD, aFCOMP, aFDIV, aFLOAT, aFMUL, aFSUB],
  Mopcodes: TYPE USING [
    zADD, zALLOC, zAND, zBCAST, zBITBLT, zBLT, zBLTC, zBLTCL, zBLTL, 
    zBNDCK, zBRK, zCATCH, zDADD, zDBL, zDCOMP, zDESCB, zDESCBS, zDIV, zDST, 
    zDSUB, zDUP, zDUCOMP, zDWDC, zEFCB, zEXCH, zFREE, zGADRB, zICDBL, zINC,
    zIWDC, zKFCB, zLADRB, zLCO, zLDIV, zLFCB, zLGB, zLGDB, zLINKB, zLLB, 
    zLLDB, zLLKB, zLP, zLST, zLSTF, zME, zMISC, zMRE, zMUL, zMXD, zMXW, zNEG, 
    zNILCK, zNILCKL, zNOTIFY, zOR, zPOP, zPORTI, zPORTO, zPUSH, zR0, zRB, zRBL, 
    zRD0, zRDB, zRDBL, zREQUEUE, zRET, zRF, zRFC, zRFL, zRFS, zRFSL, zRIGP, zRIGPL, 
    zRILP, zRILPL, zRR, zRSTR, zRSTRL, zRXGPL, zRXLP, zRXLPL, zSFC, zSGB, zSGDB, 
    zSHIFT, zSLB, zSLDB, zSTARTIO, zSTOP, zSUB, zW0, zWB, zWBL, zWCDBL, zWD0, 
    zWDB, zWDBL, zWF, zWFL, zWFS, zWFSL, zWIGPL, zWILP, zWILPL, zWR, zWS0, 
    zWSB, zWSDB, zWSF, zWSTR, zWSTRL, zWXGPL, zWXLP, zWXLPL, zXOR],
  OpCodeParams: TYPE USING [
    Byte, DstarLocalProcSlots, ExternalProcBase, ExternalProcSlots, 
    GlobalBase, GlobalLoadSlots, GlobalStoreSlots, LocalBase, LocalLoadSlots, 
    LocalProcBase, LocalPutSlots, LocalStoreSlots, ReadSlots, RILSlots, WriteSlots,
    zEFCn, zLFCn, zLGn, zLLn, zPLn, zRILn, zRn, zSGn, zSLn, zWn],
  OpTableDefs: TYPE USING [InstLength],
  P5: TYPE USING [NumberOfParams, P5Error, C0, C1, C1W, C2, LoadConstant],
  PeepholeDefs: TYPE USING [InitParameters, PackPair, PeepState],
  P5U: TYPE USING [DeleteCell],
  RTSD: TYPE USING [sAssignRefTrap, sAssignRefNewTrap, sGetCanonicalReferentType],
  SDDefs: TYPE USING [
    sFADD, sFCOMP, sFDIV, sFLOAT, sFMUL, sFSUB, sLongDiv, sLongMod, sLongMul, 
    sULongDiv, sULongMod];

PeepholeZ: PROGRAM
    IMPORTS CPtr: Code, MPtr: ComData, Log, OpTableDefs, P5, P5U, PeepholeDefs
    EXPORTS PeepholeDefs =
  BEGIN OPEN PeepholeDefs, OpCodeParams, CodeDefs;

  -- imported definitions

  Byte: TYPE = OpCodeParams.Byte;
  CodeCCIndex: TYPE = CodeDefs.CodeCCIndex;
  JumpCCIndex: TYPE = CodeDefs.JumpCCIndex;


  cb: CodeDefs.Base;		-- code base (local copy)

  PeepholeZNotify: PUBLIC Alloc.Notifier =
    BEGIN  -- called by allocator whenever table area is repacked
    cb ← base[codeType];
    END;

  dummy: PRIVATE PROC =
    BEGIN
    state: PeepState;
    IF FALSE THEN [] ← state;
    END;
  
  UnconvertedInstruction: SIGNAL [opcode: WORD] = CODE;

  PeepZ: PUBLIC PROC [start: CodeCCIndex] =
    BEGIN -- convert to real instructions (ie from qXXX to zXXX)
    OPEN Mopcodes, FOpCodes;
    next, ci: CCIndex;
    state: PeepState;
    recentSource: CARDINAL ← 0;
    next ← start;
    UNTIL (ci ← next) = CCNull DO
      next ← cb[ci].flink;
      WITH cc: cb[ci] SELECT FROM
	code =>
	 IF ~cc.realinst THEN
	  BEGIN OPEN state;
	  InitParameters[@state, LOOPHOLE[ci], c];
	  SELECT cInst FROM
	    qLG => {MoveVar[global, load, single, cP[1]]; P5U.DeleteCell[c]};
	    qSG => {MoveVar[global, store, single, cP[1]]; P5U.DeleteCell[c]};
	    qLL => {MoveVar[local, load, single, cP[1]]; P5U.DeleteCell[c]};
	    qSL => {MoveVar[local, store, single, cP[1]]; P5U.DeleteCell[c]};
	    qPL => {MoveVar[local, put, single, cP[1]]; P5U.DeleteCell[c]};
	    qLI => {P5.LoadConstant[cP[1]]; P5U.DeleteCell[c]};
	    qLCO => {P5.C1W[zLCO, cP[1]]; P5U.DeleteCell[c]};
	    qLGD => {MoveVar[global, load, double, cP[1]]; P5U.DeleteCell[c]};
	    qSGD => {MoveVar[global, store, double, cP[1]]; P5U.DeleteCell[c]};
	    qLLD => {MoveVar[local, load, double, cP[1]]; P5U.DeleteCell[c]};
	    qSLD => {MoveVar[local, store, double, cP[1]]; P5U.DeleteCell[c]};
	    qR => {Move[read, single, cP[1], 0]; P5U.DeleteCell[c]};
	    qW => {Move[write, single, cP[1], 0]; P5U.DeleteCell[c]};
	    qRL => {Move[readlong, single, cP[1], 0]; P5U.DeleteCell[c]};
	    qWL => {Move[writelong, single, cP[1], 0]; P5U.DeleteCell[c]};
	    qRF => {Move[read, partial, cP[1], cP[2]]; P5U.DeleteCell[c]};
	    qWF => {Move[write, partial, cP[1], cP[2]]; P5U.DeleteCell[c]};
	    qRFL => {Move[readlong, partial, cP[1], cP[2]]; P5U.DeleteCell[c]};
	    qWFL => {Move[writelong, partial, cP[1], cP[2]]; P5U.DeleteCell[c]};
	    qRFC => MakeReal[ zRFC, c];
	    qRFS => MakeReal[ zRFS, c];
	    qWFS => MakeReal[ zWFS, c];
	    qRFSL => MakeReal[ zRFSL, c];
	    qWFSL => MakeReal[ zWFSL, c];
	    qRD => {Move[read, double, cP[1], 0]; P5U.DeleteCell[c]};
	    qWD => {Move[write, double, cP[1], 0]; P5U.DeleteCell[c]};
	    qRSTR => MakeReal[ zRSTR, c];
	    qWSTR => MakeReal[ zWSTR, c];
	    qRXL => MakeLPReal[zRXLP, c];
	    qWXL => MakeLPReal[zWXLP, c];
	    qRIG => MakeGPReal[zRIGP, c];
	    qRIL => IF cP[1] = LocalBase AND cP[2] IN RILSlots
	      THEN {P5.C0[zRILn+cP[2]]; P5U.DeleteCell[c]}
	      ELSE MakeLPReal[zRILP, c];
	    qWIL => MakeLPReal[zWILP, c];
	    qRDL => {Move[readlong, double, cP[1], 0]; P5U.DeleteCell[c]};
	    qWDL => {Move[writelong, double, cP[1], 0]; P5U.DeleteCell[c]};
	    qRSTRL => MakeReal[ zRSTRL, c];
	    qWSTRL => MakeReal[ zWSTRL, c];
	    qRXGL => MakeGPReal[zRXGPL, c];
	    qWXGL => MakeGPReal[zWXGPL, c];
	    qRXLL => MakeLPReal[zRXLPL, c];
	    qWXLL => MakeLPReal[zWXLPL, c];
	    qRIGL => MakeGPReal[zRIGPL, c];
	    qWIGL => MakeGPReal[zWIGPL, c];
	    qRILL => MakeLPReal[zRILPL, c];
	    qWILL => MakeLPReal[zWILPL, c];
	    qWS => {Move[swrite, single, cP[1], 0]; P5U.DeleteCell[c]};
	    qWSF => {Move[swrite, partial, cP[1], cP[2]]; P5U.DeleteCell[c]};
	    qWSD => {Move[swrite, double, cP[1], 0]; P5U.DeleteCell[c]};
	    qPS => {Move[sput, single, cP[1], 0]; P5U.DeleteCell[c]};
	    qPSF => {Move[sput, partial, cP[1], cP[2]]; P5U.DeleteCell[c]};
	    qPSD => {Move[sput, double, cP[1], 0]; P5U.DeleteCell[c]};
	    qADD => MakeReal[ zADD, c];
	    qSUB => MakeReal[ zSUB, c];
	    qDADD => MakeReal[ zDADD, c];
	    qDSUB => MakeReal[ zDSUB, c];
	    qDCOMP => MakeReal[ zDCOMP, c];
	    qDUCOMP => MakeReal[ zDUCOMP, c];
	    qMUL, qAMUL => MakeReal[ zMUL, c];
	    qDIV => MakeReal[ zDIV, c];
	    qLDIV => MakeReal[ zLDIV, c];
	    qNEG => MakeReal[ zNEG, c];
	    qAND => MakeReal[ zAND, c];
	    qOR => MakeReal[ zOR, c];
	    qXOR => MakeReal[ zXOR, c];
	    qSHIFT => MakeReal[ zSHIFT, c];
	    qPUSH => MakeReal[ zPUSH, c];
	    qPOP => MakeReal[ zPOP, c];
	    qEXCH => MakeReal[ zEXCH, c];
	    qCATCH => MakeReal[ zCATCH, c];
	    qEFC =>
		IF cP[1] IN ExternalProcSlots THEN
		  {P5.C0[zEFCn+cP[1]-ExternalProcBase]; P5U.DeleteCell[c]}
		ELSE MakeReal[ zEFCB, c];
	    qLLK => MakeReal[ zLLKB, c];
	    qLFC =>
		IF cP[1] IN DstarLocalProcSlots THEN
		  {P5.C0[zLFCn+cP[1]-LocalProcBase]; P5U.DeleteCell[c]}
		ELSE MakeReal[ zLFCB, c];
	    qSFC => MakeReal[ zSFC, c];
	    qRET => MakeReal[ zRET, c];
	    qPORTO => MakeReal[ zPORTO, c];
	    qPORTI => MakeReal[ zPORTI, c];
	    qKFCB => IF MPtr.switches['y] THEN
	        {MPtr.textIndex ← recentSource; Log.Error[implicitCall]}
	      ELSE MakeReal[ zKFCB, c];
	    qBLT => MakeReal[ zBLT, c];
	    qBLTL => MakeReal[ zBLTL, c];
	    qBLTC => MakeReal[ zBLTC, c];
	    qBLTCL => MakeReal[ zBLTCL, c];
	    qALLOC => MakeReal[ zALLOC, c];
	    qFREE => MakeReal[ zFREE, c];
	    qSTOP => MakeReal[ zSTOP, c];
	    qBITBLT => MakeReal[ zBITBLT, c];
	    qSTARTIO => MakeReal[ zSTARTIO, c];
	    qDST => MakeReal[ zDST, c];
	    qLST => MakeReal[ zLST, c];
	    qLSTF => MakeReal[ zLSTF, c];
	    qWR => MakeReal[ zWR, c];
	    qRR => MakeReal[ zRR, c];
	    qBRK => MakeReal[ zBRK, c];
	    qLINKB => MakeReal[ zLINKB, c];
	    qLADRB => MakeReal[ zLADRB, c];
	    qGADRB => MakeReal[ zGADRB, c];
	    qINC => MakeReal[ zINC, c];
	    qDUP => MakeReal[ zDUP, c];
	    qDBL => MakeReal[ zDBL, c];
	    qDWDC => MakeReal[ zDWDC, c];
	    qIWDC => MakeReal[ zIWDC, c];
	    qDESCB => MakeReal[ zDESCB, c];
	    qDESCBS => MakeReal[ zDESCBS, c];
	    qFADD => MakeFloatReal[MiscAlpha.aFADD, SDDefs.sFADD, c];
	    qFSUB => MakeFloatReal[MiscAlpha.aFSUB, SDDefs.sFSUB, c];
	    qFMUL => MakeFloatReal[MiscAlpha.aFMUL, SDDefs.sFMUL, c];
	    qFDIV => MakeFloatReal[MiscAlpha.aFDIV, SDDefs.sFDIV, c];
	    qFSC => MakeFloatReal[37b--MiscAlpha.aFSC--, 147b--SDDefs.sFSC--, c];
	    qFLOAT => MakeFloatReal[MiscAlpha.aFLOAT, SDDefs.sFLOAT, c];
	    qFCOMP => MakeFloatReal[MiscAlpha.aFCOMP, SDDefs.sFCOMP, c];
	    qDMUL => {P5.C1[zKFCB, SDDefs.sLongMul]; P5U.DeleteCell[c]};
	    qDDIV => {P5.C1[zKFCB, SDDefs.sLongDiv]; P5U.DeleteCell[c]};
	    qDUDIV => {P5.C1[zKFCB, SDDefs.sULongDiv]; P5U.DeleteCell[c]};
	    qDMOD => {P5.C1[zKFCB, SDDefs.sLongMod]; P5U.DeleteCell[c]};
	    qDUMOD => {P5.C1[zKFCB, SDDefs.sULongMod]; P5U.DeleteCell[c]};
	    qLP => MakeReal[ zLP, c];
	    qNILCK => MakeReal[ zNILCK, c];
	    qNILCKL => MakeReal[ zNILCKL, c];
	    qBNDCK => MakeReal[ zBNDCK, c];
	    qME, qMEL => MakeReal[ zME, c];
	    qMRE, qMREL => MakeReal[ zMRE, c];
	    qMXW, qMXWL => MakeReal[ zMXW, c];
	    qMXD, qMXDL => MakeReal[ zMXD, c];
	    qNOTIFY, qNOTIFYL => MakeReal[ zNOTIFY, c];
	    qBCAST, qBCASTL => MakeReal[ zBCAST, c];
	    qREQUEUE, qREQUEUEL => MakeReal[ zREQUEUE, c];
	    qWCDL => {StoreCounted[cP[1], FALSE]; P5U.DeleteCell[c]};
	    qICDL => {StoreCounted[cP[1], TRUE]; P5U.DeleteCell[c]};
	    qGCRT =>
	      MakeMiscReal[72b--CedarAlpha.?--, RTSD.sGetCanonicalReferentType, c];
	    qBLZL => {P5.C1[zMISC, 102b--CedarAlpha.?--]; P5U.DeleteCell[c]};
	    ENDCASE => {SIGNAL UnconvertedInstruction[cInst]; P5U.DeleteCell[c]};
	  END;
	other => WITH cc SELECT FROM
	  absSource => recentSource ← index;
	  relSource => recentSource ← CPtr.bodyFileIndex + relIndex;
	  ENDCASE => NULL;
	ENDCASE => NULL;
      ENDLOOP;
    END;

  MakeReal: PROC [i: Byte, c: CodeCCIndex] =
    BEGIN
    IF cb[c].realinst OR P5.NumberOfParams[cb[c].inst] # OpTableDefs.InstLength[i]-1
      THEN P5.P5Error[1025];
    cb[c].inst ← i;
    cb[c].realinst ← TRUE;
    END;

  MakeLPReal: PROC [i: Byte, c: CodeCCIndex] =
    BEGIN
    IF cb[c].realinst OR P5.NumberOfParams[cb[c].inst] # OpTableDefs.InstLength[i]-1+1
      THEN P5.P5Error[1027];
    P5.C1[i, PackPair[cb[c].parameters[1]-LocalBase, cb[c].parameters[2]]];
    P5U.DeleteCell[c];
    END;

  MakeGPReal: PROC [i: Byte, c: CodeCCIndex] =
    BEGIN
    IF cb[c].realinst OR P5.NumberOfParams[cb[c].inst] # OpTableDefs.InstLength[i]-1+1
      THEN P5.P5Error[1028];
    P5.C1[i, PackPair[cb[c].parameters[1]-GlobalBase, cb[c].parameters[2]]];
    P5U.DeleteCell[c];
    END;

  MakeFloatReal: PROC [alpha, sdOffset: Byte, c: CodeCCIndex] =
    BEGIN OPEN Mopcodes;
    IF MPtr.switches['f] THEN P5.C1[zMISC, alpha] ELSE P5.C1[zKFCB, sdOffset];
    P5U.DeleteCell[c];
    END;


  cpeep9: PROC =
    BEGIN -- find 2-instruction sequences
    RETURN
    END;

  cpeep10: PROC =
    BEGIN -- find bit-testing jumps
    RETURN
    END;


  Mdirection: TYPE = {read, write, swrite, sput, readlong, writelong};
  Mtype: TYPE = {single, double, partial};
  MVdirection: TYPE = {load, store, put};
  MVtype: TYPE = {single, double};
  MVclass: TYPE = {global, local};

  MoveVar: PROC [c: MVclass, d: MVdirection, t: MVtype, offset: WORD] =
    BEGIN -- handles LG, SG, LL, SL, LGD, SGD, LLD, SLD, PL class instructions
    OPEN Mopcodes;
    IF t = single THEN
      IF c = local THEN
	SELECT d FROM
	  load =>
	    IF offset IN LocalLoadSlots THEN {P5.C0[zLLn+offset-LocalBase]; RETURN};
	  store =>
	    IF offset IN LocalStoreSlots THEN {P5.C0[zSLn+offset-LocalBase]; RETURN};
	  put =>
	    IF offset IN LocalPutSlots THEN {P5.C0[zPLn+offset-LocalBase]; RETURN};
	  ENDCASE
      ELSE
	SELECT d FROM
	  load =>
	    IF offset IN GlobalLoadSlots THEN {P5.C0[zLGn+offset-GlobalBase]; RETURN};
	  store =>
	    IF offset IN GlobalStoreSlots THEN {P5.C0[zSGn+offset-GlobalBase]; RETURN};
	  ENDCASE;
    IF offset IN Byte THEN
      BEGIN
      MoveB: ARRAY MVclass OF ARRAY MVtype OF
	ARRAY MVdirection [load..store] OF Byte = [
	  [[Mopcodes.zLGB, Mopcodes.zSGB], [Mopcodes.zLGDB, Mopcodes.zSGDB]],
	  [[Mopcodes.zLLB, Mopcodes.zSLB], [Mopcodes.zLLDB, Mopcodes.zSLDB]]];
      P5.C1[MoveB[c][t][d], offset];
      END
    ELSE
      BEGIN
      RWB: ARRAY MVdirection [load..store] OF ARRAY MVtype [single..double] OF Byte = [
	[Mopcodes.zRB, Mopcodes.zRDB], [Mopcodes.zWB, Mopcodes.zWDB]];
      RW0: ARRAY MVdirection [load..store] OF ARRAY MVtype [single..double] OF Byte = [
	[Mopcodes.zR0, Mopcodes.zRD0], [Mopcodes.zW0, Mopcodes.zWD0]];
      P5.C1[IF c = global THEN zGADRB ELSE zLADRB, LAST[Byte]];
      offset ← offset - LAST[Byte];
      IF offset IN Byte THEN P5.C1[RWB[d][t], offset]
      ELSE {P5.LoadConstant[offset]; P5.C0[zADD]; P5.C0[RW0[d][t]]};
      END;
    END;


  Move: PROC [d: Mdirection, t: Mtype, offset, field: WORD] =
    BEGIN -- handles R, W, RF, WF, WS, WSF, PS, PSF class instructions
    OPEN Mopcodes;
    IF d = read AND t = single AND offset IN ReadSlots THEN
      {P5.C0[zRn+offset]; RETURN};
    IF d = write AND t = single AND offset IN WriteSlots THEN
      {P5.C0[zWn+offset]; RETURN};
    IF offset NOT IN Byte THEN
      BEGIN
      P5.LoadConstant[offset];
      IF d >= readlong THEN
	BEGIN
	P5.LoadConstant[IF LOOPHOLE[offset, INTEGER]>0 THEN 0 ELSE 177777B];
	P5.C0[zDADD]
	END
      ELSE P5.C0[zADD];
      offset ← 0;
      END;
    IF offset = 0 AND d < readlong THEN
      SELECT d FROM
	read => SELECT t FROM
	  single => P5.C0[zR0];
	  double => P5.C0[zRD0];
	  partial => P5.C2[zRF, 0, field];
	  ENDCASE;
	write => SELECT t FROM
	  single => P5.C0[zW0];
	  double => P5.C0[zWD0];
	  partial => P5.C2[zWF, 0, field];
	  ENDCASE;
	swrite, sput => SELECT t FROM
	  single => P5.C0[zWS0];
	  double => P5.C1[zWSDB, 0];
	  partial => P5.C2[zWSF, 0, field];
	  ENDCASE;
	ENDCASE
    ELSE
      SELECT d FROM
	read => SELECT t FROM
	  single => P5.C1[zRB, offset];
	  double => P5.C1[zRDB, offset];
	  partial => P5.C2[zRF, offset, field];
	  ENDCASE;
	write => SELECT t FROM
	  single => P5.C1[zWB, offset];
	  double => P5.C1[zWDB, offset];
	  partial => P5.C2[zWF, offset, field];
	  ENDCASE;
	swrite, sput => SELECT t FROM
	  single => P5.C1[zWSB, offset];
	  double => P5.C1[zWSDB, offset];
	  partial => P5.C2[zWSF, offset, field];
	  ENDCASE;
	readlong => SELECT t FROM
	  single => P5.C1[zRBL, offset];
	  double => P5.C1[zRDBL, offset];
	  partial => P5.C2[zRFL, offset, field];
	  ENDCASE;
	writelong => SELECT t FROM
	  single => P5.C1[zWBL, offset];
	  double => P5.C1[zWDBL, offset];
	  partial => P5.C2[zWFL, offset, field];
	  ENDCASE;
	ENDCASE;
    IF d = sput THEN P5.C0[zPUSH];
    END;


  StoreCounted: PROC [offset: WORD, init: BOOLEAN] =
    BEGIN
    OPEN Mopcodes;
    IF offset NOT IN Byte OR (~MPtr.switches['m] AND offset # 0) THEN
      BEGIN
      P5.LoadConstant[offset];
      P5.LoadConstant[IF LOOPHOLE[offset, INTEGER]>=0 THEN 0 ELSE 177777B];
      P5.C0[zDADD];
      offset ← 0;
      END;
    IF MPtr.switches['m] THEN P5.C1[IF init THEN zICDBL ELSE zWCDBL, offset]
    ELSE P5.C1[zKFCB, IF init THEN RTSD.sAssignRefNewTrap ELSE RTSD.sAssignRefTrap];
    END;

  MakeMiscReal: PROC [alpha, sdOffset: Byte, c: CodeCCIndex] =
    BEGIN OPEN Mopcodes;
    IF MPtr.switches['m] THEN P5.C1[zMISC, alpha] ELSE P5.C1[zKFCB, sdOffset];
    P5U.DeleteCell[c];
    END;

  END.