-- file: PeepholeZ.mesa, edited by Sweet on November 29, 1979 11:23 PM DIRECTORY Code: FROM "code" USING [dStar], CodeDefs: FROM "codedefs" USING [CCIndex, CCNull, CodeCCIndex, JumpCCIndex], ComData: FROM "comdata" USING [switches], FOpCodes: FROM "fopcodes" USING [ qADD, qALLOC, qAMUL, qAND, qBCAST, qBCASTL, qBITBLT, qBLT, qBLTC, qBLTCL, qBLTL, 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, qFSUB, qGADRB, 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, qNOOP, 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, qWD, qWDL, qWF, qWFL, qWFS, qWFSL, qWIGL, qWIL, qWILL, qWL, qWR, qWS, qWSD, qWSF, qWSTR, qWSTRL, qWXGL, qWXL, qWXLL, qXOR], Mopcodes: FROM "mopcodes" USING [ zADD, zADD01, 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, zINC, zIWDC, zKFCB, zLADRB, zLDIV, zLFCB, zLGB, zLGDB, zLI0, zLINKB, zLLB, zLLDB, zLLKB, zLP, zLST, zLSTF, zME, 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, zWD0, zWDB, zWDBL, zWF, zWFL, zWFS, zWFSL, zWIGPL, zWILP, zWILPL, zWR, zWS0, zWSB, zWSDB, zWSF, zWSTR, zWSTRL, zWXGPL, zWXLP, zWXLPL, zXOR], OpCodeParams: FROM "opcodeparams" USING [ BYTE, DstarLocalProcSlots, ExternalProcBase, ExternalProcSlots, GlobalBase, GlobalLoadSlots, GlobalStoreSlots, LocalBase, LocalLoadSlots, LocalProcBase, LocalProcSlots, LocalPutSlots, LocalStoreSlots, ReadSlots, RILSlots, WriteSlots, zEFCn, zLFCn, zLGn, zLLn, zPLn, zRILn, zRn, zSGn, zSLn, zWn], OpTableDefs: FROM "optabledefs" USING [instlength], P5: FROM "p5" USING [NumberOfParams, P5Error, C0, C1, C2, LoadConstant], PeepholeDefs: FROM "peepholedefs" USING [ InitParametersC, PackPair, PeepState], P5U: FROM "p5u" USING [DeleteCell], SDDefs: FROM "sddefs" USING [ sFADD, sFCOMP, sFDIV, sFLOAT, sFMUL, sFSUB, sLongDiv, sLongMod, sLongMul, sULongDiv, sULongMod], Table: FROM "table" USING [Base, Notifier], Tree: FROM "tree" USING [treeType]; PeepholeZ: PROGRAM IMPORTS CPtr: Code, MPtr: ComData, P5U, OpTableDefs, P5, PeepholeDefs EXPORTS CodeDefs, PeepholeDefs = BEGIN OPEN PeepholeDefs, OpCodeParams, CodeDefs; -- imported definitions BYTE: TYPE = OpCodeParams.BYTE; CodeCCIndex: TYPE = CodeDefs.CodeCCIndex; JumpCCIndex: TYPE = CodeDefs.JumpCCIndex; cb: Table.Base; -- code base (local copy) PeepholeZNotify: PUBLIC Table.Notifier = BEGIN -- called by allocator whenever table area is repacked cb ← base[Tree.treeType]; RETURN END; dummy: PRIVATE PROCEDURE = BEGIN state: PeepState; IF FALSE THEN [] ← state; END; UnconvertedInstruction: SIGNAL [opcode: WORD] = CODE; PeepZ: PUBLIC PROCEDURE [start: CodeCCIndex] = BEGIN -- convert to real instructions (ie from qXXX to zXXX) OPEN Mopcodes, FOpCodes; next: CodeCCIndex; state: PeepState; next ← start; BEGIN OPEN state; UNTIL (c ← next) = CCNull DO next ← LOOPHOLE[cb[c].flink]; WITH cb[LOOPHOLE[c,CCIndex]] SELECT FROM code => IF ~cb[c].realinst THEN BEGIN InitParametersC[@state]; SELECT cInst FROM qLG => BEGIN MoveVar[global, load, single, cP[1]]; P5U.DeleteCell[c] END; qSG => BEGIN MoveVar[global, store, single, cP[1]]; P5U.DeleteCell[c] END; qLL => BEGIN MoveVar[local, load, single, cP[1]]; P5U.DeleteCell[c] END; qSL => BEGIN MoveVar[local, store, single, cP[1]]; P5U.DeleteCell[c] END; qPL => BEGIN MoveVar[local, put, single, cP[1]]; P5U.DeleteCell[c] END; qLI, qLCO => BEGIN P5.LoadConstant[cP[1]]; P5U.DeleteCell[c] END; qLGD => BEGIN MoveVar[global, load, double, cP[1]]; P5U.DeleteCell[c] END; qSGD => BEGIN MoveVar[global, store, double, cP[1]]; P5U.DeleteCell[c] END; qLLD => BEGIN MoveVar[local, load, double, cP[1]]; P5U.DeleteCell[c] END; qSLD => BEGIN MoveVar[local, store, double, cP[1]]; P5U.DeleteCell[c] END; qR => BEGIN Move[read, single, cP[1], 0]; P5U.DeleteCell[c] END; qW => BEGIN Move[write, single, cP[1], 0]; P5U.DeleteCell[c] END; qRL => BEGIN Move[readlong, single, cP[1], 0]; P5U.DeleteCell[c] END; qWL => BEGIN Move[writelong, single, cP[1], 0]; P5U.DeleteCell[c] END; qRF => BEGIN Move[read, partial, cP[1], cP[2]]; P5U.DeleteCell[c] END; qWF => BEGIN Move[write, partial, cP[1], cP[2]]; P5U.DeleteCell[c] END; qRFL => BEGIN Move[readlong, partial, cP[1], cP[2]]; P5U.DeleteCell[c] END; qWFL => BEGIN Move[writelong, partial, cP[1], cP[2]]; P5U.DeleteCell[c] END; qRFC => MakeReal[ zRFC, c]; qRFS => MakeReal[ zRFS, c]; qWFS => MakeReal[ zWFS, c]; qRFSL => MakeReal[ zRFSL, c]; qWFSL => MakeReal[ zWFSL, c]; qRD => BEGIN Move[read, double, cP[1], 0]; P5U.DeleteCell[c] END; qWD => BEGIN Move[write, double, cP[1], 0]; P5U.DeleteCell[c] END; 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 BEGIN P5.C0[zRILn+cP[2]]; P5U.DeleteCell[c] END ELSE MakeLPReal[zRILP, c]; qWIL => MakeLPReal[zWILP, c]; qRDL => BEGIN Move[readlong, double, cP[1], 0]; P5U.DeleteCell[c] END; qWDL => BEGIN Move[writelong, double, cP[1], 0]; P5U.DeleteCell[c] END; 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 => BEGIN Move[swrite, single, cP[1], 0]; P5U.DeleteCell[c] END; qWSF => BEGIN Move[swrite, partial, cP[1], cP[2]]; P5U.DeleteCell[c] END; qWSD => BEGIN Move[swrite, double, cP[1], 0]; P5U.DeleteCell[c] END; qPS => BEGIN Move[sput, single, cP[1], 0]; P5U.DeleteCell[c] END; qPSF => BEGIN Move[sput, partial, cP[1], cP[2]]; P5U.DeleteCell[c] END; qPSD => BEGIN Move[sput, double, cP[1], 0]; P5U.DeleteCell[c] END; qADD => MakeRealFast[c:c, slow:zADD, fast:zADD01]; 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 BEGIN P5.C0[zEFCn+cP[1]-ExternalProcBase]; P5U.DeleteCell[c] END ELSE MakeReal[ zEFCB, c]; qLLK => MakeReal[ zLLKB, c]; qLFC => IF ~CPtr.dStar AND cP[1] IN LocalProcSlots OR CPtr.dStar AND cP[1] IN DstarLocalProcSlots THEN BEGIN P5.C0[zLFCn+cP[1]-LocalProcBase]; P5U.DeleteCell[c] END ELSE MakeReal[ zLFCB, c]; qSFC => MakeReal[ zSFC, c]; qRET => MakeReal[ zRET, c]; qPORTO => MakeReal[ zPORTO, c]; qPORTI => MakeReal[ zPORTI, c]; qKFCB => 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 => BEGIN P5.C1[zKFCB, SDDefs.sFADD]; P5U.DeleteCell[c]; END; qFSUB => BEGIN P5.C1[zKFCB, SDDefs.sFSUB]; P5U.DeleteCell[c]; END; qFMUL => BEGIN P5.C1[zKFCB, SDDefs.sFMUL]; P5U.DeleteCell[c]; END; qFDIV => BEGIN P5.C1[zKFCB, SDDefs.sFDIV]; P5U.DeleteCell[c]; END; qFLOAT => BEGIN P5.C1[zKFCB, SDDefs.sFLOAT]; P5U.DeleteCell[c]; END; qFCOMP => BEGIN P5.C1[zKFCB, SDDefs.sFCOMP]; P5U.DeleteCell[c]; END; qDMUL => BEGIN P5.C1[zKFCB, SDDefs.sLongMul]; P5U.DeleteCell[c]; END; qDDIV => BEGIN P5.C1[zKFCB, SDDefs.sLongDiv]; P5U.DeleteCell[c]; END; qDUDIV => BEGIN P5.C1[zKFCB, SDDefs.sULongDiv]; P5U.DeleteCell[c]; END; qDMOD => BEGIN P5.C1[zKFCB, SDDefs.sLongMod]; P5U.DeleteCell[c]; END; qDUMOD => BEGIN P5.C1[zKFCB, SDDefs.sULongMod]; P5U.DeleteCell[c]; END; qLP => MakeReal[ IF (CPtr.dStar OR MPtr.switches['l]) THEN zLP ELSE zLI0, c]; qNILCK => MakeReal[ zNILCK, c]; qNILCKL => IF (CPtr.dStar OR MPtr.switches['l]) THEN MakeReal[ zNILCKL, c] ELSE BEGIN P5.C0[zEXCH]; P5.C0[zNILCK]; P5.C0[zEXCH]; P5U.DeleteCell[c]; END; 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]; qNOOP => NULL; -- pass on unconverted to OutBinary ENDCASE => BEGIN SIGNAL UnconvertedInstruction[cInst]; P5U.DeleteCell[c] END; END; ENDCASE; -- of WITH ENDLOOP; END; -- of OPEN state RETURN END; MakeReal: PROCEDURE [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; RETURN END; MakeRealFast: PROCEDURE [slow, fast: BYTE, c: CodeCCIndex] = BEGIN IF cb[c].realinst OR P5.NumberOfParams[cb[c].inst] # OpTableDefs.instlength[slow]-1 THEN P5.P5Error[1026]; cb[c].inst ← IF cb[c].minimalStack THEN fast ELSE slow; cb[c].realinst ← TRUE; RETURN END; MakeLPReal: PROCEDURE [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]; RETURN END; MakeGPReal: PROCEDURE [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]; RETURN END; cpeep9: PROCEDURE = BEGIN -- find 2-instruction sequences RETURN END; cpeep10: PROCEDURE = 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}; MoveB: ARRAY MVclass OF ARRAY MVtype OF PACKED ARRAY MVdirection[load..store] OF BYTE ← [ [[Mopcodes.zLGB, Mopcodes.zSGB], [Mopcodes.zLGDB, Mopcodes.zSGDB]], [[Mopcodes.zLLB, Mopcodes.zSLB], [Mopcodes.zLLDB, Mopcodes.zSLDB]]]; MoveVar: PROCEDURE [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 BEGIN P5.C0[zLLn+offset-LocalBase]; RETURN END; store => IF offset IN LocalStoreSlots THEN BEGIN P5.C0[zSLn+offset-LocalBase]; RETURN END; put => IF offset IN LocalPutSlots THEN BEGIN P5.C0[zPLn+offset-LocalBase]; RETURN END; ENDCASE ELSE SELECT d FROM load => IF offset IN GlobalLoadSlots THEN BEGIN P5.C0[zLGn+offset-GlobalBase]; RETURN END; store => IF offset IN GlobalStoreSlots THEN BEGIN P5.C0[zSGn+offset-GlobalBase]; RETURN END; ENDCASE; IF offset ~IN BYTE THEN BEGIN P5.C1[IF c = global THEN zGADRB ELSE zLADRB, LAST[BYTE]]; P5.LoadConstant[offset - LAST[BYTE]]; P5.C0[zADD]; IF t = single THEN IF d = load THEN P5.C0[zR0] ELSE P5.C0[zW0] ELSE IF d = load THEN P5.C0[zRD0] ELSE P5.C0[zWD0]; RETURN END; P5.C1[MoveB[c][t][d], offset]; RETURN END; Move: PROCEDURE [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 BEGIN P5.C0[zRn+offset]; RETURN END; IF d = write AND t = single AND offset IN WriteSlots THEN BEGIN P5.C0[zWn+offset]; RETURN END; IF offset ~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]; RETURN END; END...