PeepholeZ.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Sweet on July 24, 1980 9:33 AM
Satterthwaite on October 10, 1985 2:11:19 pm PDT
Maxwell, August 11, 1983 9:21 am
Russ Atkinson (RRA) March 6, 1985 11:24:02 pm PST
DIRECTORY
Alloc USING [Notifier],
Code USING [bodyStartLoc],
CodeDefs USING [Base, CCIndex, CCNull, CodeCCIndex, codeType, JumpCCIndex],
ComData USING [textIndex, switches],
FOpCodes USING [qADD, qALLOC, qAMUL, qAND, qBCAST, qBCASTL, qBLT, qBLTC, qBLTCL, qBLTL, qBLZL, qBNDCK, 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, qRET, qRF, qRFC, qRFL, qRFS, qRFSL, qRIG, qRIGL, qRIL, qRILL, qRL, qRSTR, qRSTRL, qRXGL, qRXL, qRXLL, qSFC, qSG, qSGD, qSHIFT, qSL, qSLD, qSUB, qW, qWCDL, qWD, qWDL, qWF, qWFL, qWFS, qWFSL, qWIGL, qWIL, qWILL, qWL, qWS, qWSD, qWSF, qWSTR, qWSTRL, qWXGL, qWXL, qWXLL, qXOR],
Log USING [Error],
OpCodeParams 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 USING [InstLength],
P5 USING [NumberOfParams, P5Error, C0, C1, C1W, C2, LoadConstant],
PeepholeDefs USING [InitParameters, PackPair, PeepState],
P5U USING [DeleteCell],
PrincOps USING [aFADD, aFCOMP, aFDIV, aFLOAT, aFMUL, aFSUB, sFADD, sFCOMP, sFDIV, sFLOAT, sFMUL, sFSUB, sLongDiv, sLongMod, sLongMul, sULongDiv, sULongMod, zADD, zALLOC, zAND, zBCAST, zBLT, zBLTC, zBLTCL, zBLTL, zBNDCK, 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, zRET, zRF, zRFC, zRFL, zRFS, zRFSL, zRIGP, zRIGPL, zRILP, zRILPL, zRSTR, zRSTRL, zRXGPL, zRXLP, zRXLPL, zSFC, zSGB, zSGDB, zSHIFT, zSLB, zSLDB, zSUB, zW0, zWB, zWBL, zWCDBL, zWD0, zWDB, zWDBL, zWF, zWFL, zWFS, zWFSL, zWIGPL, zWILP, zWILPL, zWS0, zWSB, zWSDB, zWSF, zWSTR, zWSTRL, zWXGPL, zWXLP, zWXLPL, zXOR],
RTSD USING [sAssignRefTrap, sAssignRefNewTrap, sGetCanonicalReferentType],
SourceMap USING [Loc, Cons, Incr];
PeepholeZ: PROGRAM
IMPORTS CPtr: Code, MPtr: ComData, Log, OpTableDefs, P5, P5U, PeepholeDefs, SourceMap
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 PrincOps, FOpCodes;
next, ci: CCIndex;
state: PeepState;
recentSource: SourceMap.Loc ← SourceMap.Cons[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];
qDST => MakeReal[ zDST, c];
qLST => MakeReal[ zLST, c];
qLSTF => MakeReal[ zLSTF, 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[PrincOps.aFADD, PrincOps.sFADD, c];
qFSUB => MakeFloatReal[PrincOps.aFSUB, PrincOps.sFSUB, c];
qFMUL => MakeFloatReal[PrincOps.aFMUL, PrincOps.sFMUL, c];
qFDIV => MakeFloatReal[PrincOps.aFDIV, PrincOps.sFDIV, c];
qFSC => MakeFloatReal[37b--PrincOps.aFSC--, 147b--PrincOps.sFSC--, c];
qFLOAT => MakeFloatReal[PrincOps.aFLOAT, PrincOps.sFLOAT, c];
qFCOMP => MakeFloatReal[PrincOps.aFCOMP, PrincOps.sFCOMP, c];
qDMUL => {P5.C1[zKFCB, PrincOps.sLongMul]; P5U.DeleteCell[c]};
qDDIV => {P5.C1[zKFCB, PrincOps.sLongDiv]; P5U.DeleteCell[c]};
qDUDIV => {P5.C1[zKFCB, PrincOps.sULongDiv]; P5U.DeleteCell[c]};
qDMOD => {P5.C1[zKFCB, PrincOps.sLongMod]; P5U.DeleteCell[c]};
qDUMOD => {P5.C1[zKFCB, PrincOps.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];
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 ← loc;
relSource => recentSource ← CPtr.bodyStartLoc.Incr[relLoc];
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 PrincOps;
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 PrincOps;
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 = [
[[PrincOps.zLGB, PrincOps.zSGB], [PrincOps.zLGDB, PrincOps.zSGDB]],
[[PrincOps.zLLB, PrincOps.zSLB], [PrincOps.zLLDB, PrincOps.zSLDB]]];
P5.C1[MoveB[c][t][d], offset];
END
ELSE
BEGIN
RWB: ARRAY MVdirection [load..store] OF ARRAY MVtype [single..double] OF BYTE = [
[PrincOps.zRB, PrincOps.zRDB], [PrincOps.zWB, PrincOps.zWDB]];
RW0: ARRAY MVdirection [load..store] OF ARRAY MVtype [single..double] OF BYTE = [
[PrincOps.zR0, PrincOps.zRD0], [PrincOps.zW0, PrincOps.zWD0]];
P5.C1[IF c = global THEN zGADRB ELSE zLADRB, BYTE.LAST];
offset ← offset - BYTE.LAST;
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 PrincOps;
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: BOOL] =
BEGIN
OPEN PrincOps;
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 PrincOps;
IF MPtr.switches['m] THEN P5.C1[zMISC, alpha] ELSE P5.C1[zKFCB, sdOffset];
P5U.DeleteCell[c];
END;
END.