{******************************************************************}
{***************** 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;