{******************************************************************} {***************** FLOYD ALGORITHM SUBROUTINES *****************} {******************************************************************} { File: FloydSubs.mc Create by: Martin J. Shramo, June 1986 Last Edited: 19-Dec-86 13:46:54 } { to list use: print gacha8/f /-a FloydSubs.mc } {****************************************************************** fSaveState SUBROUTINE (Saves the state of the instruction for interrupt or page fault handling) first Cycle = c2, last cycle = c3 This routine save the current state of the instruction on the stack. Only the following state variables need to be updated: uSTKMisc, uInPtrVL, uOutPtrVL, uErrPtrVL and uErrPtrVH. The rest of the state variables are updated as they are changed. CALLING ARGUMENTS L0 caller uRtnReason interrupt or page fault flag (UA4) uByte byte of pixel pair being used (UA1) uPolarity invert flag (UA0) rSrcLow gray input real low address pointer (R03) rDstLow output real low address pointer (R04) rErrLow error buffer real low address pointer (R05) ALWAYS UPDATES uSTKMisc misc data for interrupt/page fault returns (U0F) uInPtrVL gray input low virtual address pointer (U06) uOutPtrVL output low virtual address pointer (U08) uErrorPtrVL error buffer low virtual address pointer (U0A) uErrorPtrVH error buffer high virtual address pointer (U09) USES rTT temp register (R06) rTT2 temp register (R00) rTT3 temp register (R09) rTT4 temp register (R0B) RETURNS THROUGH fSaveStateRet } fSaveState: { update uSTKMisc } rTT ← uByte LShift1,SE ← 0 ,c2; rTT2 ← uPolarity ,c3; rTT ← rTT or rTT2 ,c1; rTT2 ← uRtnReason ,c2; uSTKMisc ← rTT or rTT2 ,c3; rTT2 ← rTT2 + 0,ZeroBr ,c1; pRet0,BRANCH[$,fNoUpdateVPs] ,c2;{0:PFReturn, ~0:INTReturn} { update the virtual pointers } rTT ← rSrcLow and 0FF,CANCELBR[$,0F] ,c3;{source virt addr} rTT2 ← uInPtrVL ,c1; rTT2 ← rTT2 and ~0FF ,c2; uInPtrVL ← rTT2 or rTT ,c3; rTT ← rDstLow and 0FF ,c1;{dest virt addr} rTT2 ← uOutPtrVL ,c2; rTT2 ← rTT2 and ~0FF ,c3; uOutPtrVL ← rTT2 or rTT ,c1; rTT ← rErrLow and 0FF ,c2;{error virt addr} rTT2 ← uErrorPtrVL ,c3; rTT2 ← rTT2 and ~0FF ,c1; rTT2 ← rTT2 or rTT ,c2; rTT2 ← rTT2 - 1,CarryBr ,c3; {get the error buff addr to write to} uErrorPtrVL ← rTT2,BRANCH[$,fRHVaddrOK] ,c1; { need to decr RH virt addr } rTT ← uErrorPtrVH ,c2; rTT ← rTT - 1 ,c3; uErrorPtrVH ← rTT ,c1; fRHVaddrOK: { the RH virt addr does not need to be decr. } pRet0 ,c2; fNoUpdateVPs: { no update of the virtual pointers } RET[fSaveStateRet] ,c3; {****************************************************************** fGetState SUBROUTINE (Gets the state of the instruction after interrupt or page fault handling) first Cycle = c1, last cycle = c3 This routine retrieves the current state of the instruction from the stack. The state variables that are retrieved are uByte, uRtnReason, uPolarity, uThreshold, and uMaxValue. Three of these values are incoded into uSTKMisc, two into uThreshAndMax. The rest of the state variables are used from the stack. CALLING ARGUMENTS uThreshAndMax threshold and max value (U03) uSTKMisc misc data for interrupt/page fault returns (U0F) ALWAYS UPDATES uPolarity invert flag (UE0) uByte byte of pixel pair being used (UE1) uRtnReason interrupt or page fault flag (UE2) uThreshold threshold value (UE3) uMaxValue max pixel value (UE4) USES rTT temp register (R06) RETURNS TO fGetStateRet } fGetState: Xbus ← uSTKMisc,XDisp ,c1; rTT ← 1,BRANCH[fNoInvert,fYesInvert,0E] ,c2; {used as constant} fNoInvert: uPolarity ← 0,GOTO[fSetPolarityDone] ,c3; fYesInvert: uPolarity ← rTT ,c3; fSetPolarityDone: Xbus ← uSTKMisc,XDisp ,c1; BRANCH[fZeroByte,fOneByte,0D] ,c2; fZeroByte: uByte ← 0,GOTO[fSetByteDone] ,c3; fOneByte: uByte ← rTT ,c3; fSetByteDone: Xbus ← uSTKMisc,XDisp ,c1; rTT ← INTRtn,BRANCH[fPFrtn,fINTrtn,0B] ,c2; fPFrtn: uRtnReason ← PFRtn,GOTO[fGetThreshAndMax],c3; fINTrtn: uRtnReason ← rTT ,c3; fGetThreshAndMax: rTT ← uThreshAndMax ,c1; Q ← rTT and 0FF ,c2; uMaxValue ← Q ,c3; rTT ← rTT LRot8 ,c1; rTT ← rTT and 0FF ,c2; uThreshold ← rTT, GOTO[fGetStateRet] ,c3; {****************************************************************** fGetAllPages SUBROUTINE (Gets all pages into real memory) first Cycle = c3, last cycle = c2 This routine pulls all source, destination and error buffer pages into real memory. The R register pointers for the real addresses are updated. The includes the locations that are read and the locations that are written in the error buffer. If a page fault occurs, code is transferred to that will save the state of the instruction and goto the page fault handler. CALLING ARGUMENTS uCount number of input pixels (U02) uInPtrVH source data virt address (U05) uInPtrVL source data virt address (U06) uOutPtrVH destination data virt address (U07) uOutPtrVL destination data virt address (U08) uErrorPtrVH error data virt address (U09) uErrorPtrVL error data virt address (U0A) uBit Bit-address of output pixel (U0B) L2 caller ALWAYS UPDATES rSrcLow source real address (R03) rhSrcHi source real address (RH03) rDstLow destination real address (R04) rhDstHi destination real address (RH04) rErrLow write error real address (R05) rhErrHi write error real address (RH05) rOldErrorLow read error real address (R07) rhOldErrorHi read error real address (RH07) USES rTT temp (R06) rTT3 temp (R09) rTT4 temp (R0B) Q temp rDstReal interface to MapGrDst (R06) rhDstReal interface to MapGrDst (RH06) rVirtualL interface to MapGrDst (R0B) rhVirtualH interface to MapGrDst (RH06) bitWidth interface to ComMap (R02) byteWidth interface to ComMap (R02) wordWidth interface to ComMap (R02) DBit interface to ComMap (R09) DByte interface to ComMap (R09) VD interface to ComMap (R01) rhVD interface to ComMap (RH01) BARealALo interface to ComMap (R0C) BARealAHi interface to ComMap (RH0C) L0 interface to MapGrDst L1 interface to ComMap L3 interface to ComMap Q used by ComMap Regb used by ComMap (R0B) Reg6 used by ComMap (R06) Reg0 used by ComMap (R00) rhRegD used by ComMap (RH0D) Rege used by ComMap (RH0E) RETURNS THROUGH fGetAllPagesRet Success case, via L2 fScrFlt source page fault, via GOTO fDstFlt destination page fault, via GOTO fErrFlt error page fault, via GOTO } fGetAllPages: { Source Data case } VD ← uInPtrVL,L3 ← L3.FloydSrc ,c3;{return for ComMap} rhVD ← uInPtrVH ,c1; DByte ← uByte,L1 ← 0 ,c2; {want to look at src case} byteWidth ← uCount,CALL[ComMapByte] ,c3; { save real address } rSrcLow ← BARealALo,BRANCH[$,fSrcFlt] ,c2,at[L3.FloydSrc,10,ComMapRet]; Q ← BARealAHi ,c3; rhSrcHi ← Q LRot0 ,c1; { Destination Data case} bitWidth ← uCount,L3 ← L3.FloydDst ,c2; {return for ComMap} VD ← uOutPtrVL ,c3; rhVD ← uOutPtrVH ,c1; DBit ← uBit,L1 ← 1 ,c2; {want to look at dst case} CALL[ComMap] ,c3; { save real addresses } rDstLow ← BARealALo,BRANCH[$,fDstFlt] ,c2,at[L3.FloydDst,10,ComMapRet]; Q ← BARealAHi,L1 ← 1 ,c3; {want to look at dst case} rhDstHi ← Q LRot0 ,c1; { Error Data Case } VD ← uErrorPtrVL,L3 ← L3.FloydErrBuf ,c2; {return for ComMap} rhVD ← uErrorPtrVH ,c3; wordWidth ← uCount ,c1; wordWidth ← wordWidth + 1 ,c2; {error buffer is 1 longer than others} CALL[ComMapWord] ,c3; { save real addresses } rOldErrorLow ← BARealALo,BRANCH[$,fErrFlt] ,c2,at[L3.FloydErrBuf,10,ComMapRet]; Q ← BARealAHi ,c3; { error buff address to write to } rhOldErrorHi ← Q LRot0 ,c1; { get the error buffer address to read from } rErrLow ← BARealALo + 1,PgCarryBr ,c2; rVirtualL ← uErrorPtrVL,BRANCH[fErrNoCarry,$] ,c3; { we have a page cross on the error address, update the virt. address } rTT3 ← 0FF + 1,L0 ← L0.FloydErrBuf ,c1;{return for MapDst} rVirtualL ← rVirtualL and ~(0FF) ,c2; rVirtualL ← rVirtualL + rTT3,CarryBr,c3; uErrorPtrVL ← rVirtualL,BRANCH[fErrNoTopCarry,$] ,c1; { need to carry into the rh register } Q ← uErrorPtrVH ,c2; Q ← Q + 1 ,c3; uErrorPtrVH ← Q ,c1; fErrNoTopCarry: rhVirtualH ← uErrorPtrVH ,c2; CALL[MapDst] ,c3; { can't get a page fault, already checked pages } rErrLow ← rDstReal ,c3,MapDstRet[L0.FloydErrBuf]; Q ← rhDstReal,pRet2,GOTO[fGetDone] ,c1; fErrNoCarry: Q ← BARealAHi,pRet2 ,c1; fGetDone: rhErrHi ← Q LRot0,RET[fGetAllPagesRet] ,c2; {****************************************************************** fSaveRegs SUBROUTINE (Save system registers before Floyd uses them.) first Cycle = c2, last cycle = c1 This subroutine is used to save system regs in U. Note that the caller MUST save L before calling. CALLING ARGUMENTS L2 caller ALWAYS UPDATES G -> UGsave rhG -> UrhGsave PC -> UPCsave rhPC -> UrhPCsave L -> UrhLsave rhL -> UrhLsave USES RETURNS THROUGH fSaveRegsRet } fSaveRegs: L ← rhL ,c2, at[0,10,fSaveRegs]; UPCsave ← PC ,c3; UGsave ← G ,c1; {the following Uregs are at "xB" to allow "← rh"} UrhLsave ← L, G ← rhG ,c2; UrhGsave ← G, PC ← rhPC, pRet2 ,c3; UrhPCsave ← PC, RET[fSaveRegsRet], ,c1; {****************************************************************** fRestoreRegs SUBROUTINE (Restore system registers after Floyd uses them.) first Cycle = c1, last cycle = c1 This subroutine is used to restore system regs from U. CALLING ARGUMENTS L0 caller ALWAYS UPDATES r0100 ← 0FF + 1 G ← UGsave rhG ← UrhGsave PC ← UPCsave rhPC ← UrhPCsave L ← UrhLsave rhL ← UrhLsave USES RETURNS THROUGH fRestoreRegsRet } fRestoreRegs: rhL ← UrhLsave ,c1,at[1,10,fSaveStateRet]; rhPC ← UrhPCsave ,c2; rhG ← UrhGsave ,c3; PC ← UPCsave ,c1; r0100 ← 0FF + 1 ,c2; G ← UGsave,pRet0 ,c3; L ← ULsave, RET[fRestoreRegsRet] ,c1;