-- 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...