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