{ File Name: FlipX.mc
Description: Get mirror image for 1 bit or 8 bits data.
Author: MYT
Created: Nov 24, 1986
Last edited: Dec 18, 1986 *after code review*
Last edited by JPM: Jan 15, 1987 *bug fix at fmcont (bad L0 value)*
Jan 28, 1987 *bug fix near fvrcom (width = 1 case didn't work)*
}
{ Copyright (C) 1986 by XEROX corporation. All rights reserved.}
{ FlipX.mc includes 2 opcodes - FlipXBits and FlipXGray,
L0 is caller for MapSrc and MapDst, L0=L0.FlipXRight for 1st right word, L0=L0.FlipXLast for other right words(MapSrc) and left words(MapDst)
L2 is used to indicate bits or gray, L2=0 for FlipXBits, L2=1 for FlipXGray.
L4 is used to indicate if 1st word to process, L4=0 for 1st word(either left or right),otherwise, L4=1.
L7 is used to specify left ,right or middle word when page cross happened, L7=0 for left, L7=1 for right, L7=2 for middle.
Globol subroutines called - ComMapWord (in ComMapSub) to bring in pages needed,
MapSrc (in GrayBltSubs) to map real address for 1st right word and remap right word for page cross cases, L0 = L0.FlipXRight for 1st right word, L0 = L0.FlipXLast for remapping.
MapDst (in GrayBltSubs) to map real address for the left and middle word remap for page cross cases, L0 = L0.FlipXLast for left or middle word remapping.
}
@FlipXBits:
at [0B,10,ESCAn]
{****************************************************************************************
POP Parameters from stack for FlipXBits
****************************************************************************************}
{ Set L2 = 0 for FlipXBits }
L2←0,bitWidth ← TOS,ZeroBr, c1;{L2=0, TOS=width, bitWidth=r2 for commapsub }
rhVirtualH ← Urhleft,BRANCH[flipxcommon,fnodataB], c2;{rhleft}
@FlipXGray:
at [0C,10,ESCAn]
{****************************************************************************************
POP Parameters from stack for FlipXGray
****************************************************************************************}
{ Set L2 = 1 for FlipXGray }
L2←1,bitWidth ← TOS,ZeroBr, c1;{L2=1, TOS=width, bitWidth=r2 for commapsub }
rhVirtualH ← Urhleft,BRANCH[$,fnodataB], c2;
flipxcommon:
rVirtualL ← Urleft, c3;{rleft}
{**************************************************************************************** Save arguments and call ComMapWord to get left real address
****************************************************************************************}
Uworkrleft ← rVirtualL, c1;{ save rleft virtual address to some working U-reeg}
Q ← rhVirtualH, c2;{ save rhleft virtual address to some working U-reeg}
Uworkrhleft ← Q, c3;
VD ← rVirtualL, c1;{ set up parameters for left to call commapword}
Q ← rhVirtualH,L1←1, c2;
rhVD ← Q LRot0, c3;
DBit←0, c1;
L3 ← L3.FlipX, c2;{ L3 is caller for commapsub }
CALL[ComMapWord], c3;{ rcount=r2 }
{ rC and rhC contains left real address after ComMapWord }
BRANCH[$,FlipXPageFault], c2,at [L3.FlipX,10,ComMapRet];
rleftreal←BARealALo, c3;{set up left real address from rC to r6(rleftreal)}
Q ← BARealAHi, c1;
rhleftreal ← Q LRot0, c2;
{ restore registers }
width ← Uwidth, c3;
rVirtualL ← Urleft, c1;
rhVirtualH ← Urhleft, c2;
{****************************************************************************************
virtual and real address process for the 1st left and right word
****************************************************************************************}
bitWidth ← bitWidth - 1,L4 ← 0, c3;
{ caculate right virtual address and save in U-register }
rVirtualL ← rVirtualL + bitWidth,CarryBr, c1;{right = left + width - 1}
Q ← rhVirtualH,BRANCH[$,fvrcarry], c2;
GOTO[fvrcom], c3;
fvrcarry:
Q ← Q + 1, c3;{ if carry }
fvrcom: Urright ← rVirtualL,L0 ← L0.FlipXRight, c1;{ save right virtual address }
rhVirtualH ← Q LRot0, c2;{ rVirtualL=r0B the virtual address to call MapSrc }
Urhright ← Q,CALL[MapSrc], c3;{ save rhright into U-reg, caller-rB, retrurned-r2 }
width ← width DRShift1, c3,MapSrcRet[L0.FlipXRight];{ width/2 = word count, bit inversed after DRShift1 }
[] ← width,ZeroBr, c1;
USavecheck ← Q,BRANCH[$,fonlyone], c2;{ bit15 of Q is flag for middle case, 0 is middle case, 1 is not. }
Noop, c3;
{**************************************************************************************** Read left or right data and branch to reverse
****************************************************************************************}
fleft: MAR ← [rhleftreal,rleftreal+0],L7←0,GOTO[fleftc2], c1;{ 1st left word entry }
fleftloop:
MAR ← rleftreal ← [rhleftreal,rleftreal+1],L7←0, c1;
fleftc2:
rcount ← 11,L2Disp,BRANCH[$,flpagecross,1], c2;{ L2Disp checks if bits or gray }
rwork ← MD,BRANCH[LReverseBits,$,2], c3;{ read left data, branch to reverse left data }
frhtchk:
ftoright:
rwork ← rwork LRot8,L7 ← 1, c1;{ rotate left data for gray}
rcount ← 11,L4Disp, c2;{ L4Disp checks if 1st entry for right word }
BRANCH [fright,frightloop,2], c3;
fright: MAR ← [rhrightreal,rrightreal+0],L4 ← 1,GOTO[frightc2], c1;{ 1st right word entry, reset L4=1 for not first read}
frightloop:
MAR ← rrightreal ← [rhrightreal,rrightreal-1], c1;
frightc2:
rtemp ← rwork,L2Disp,BRANCH[$,frpagecross,1], c2;{ store left reversed data }
rwork ← MD,BRANCH[RReverseBits,$,2], c3;{ read right data, branch to reverse right data }
fwrite:
MAR ← [rhrightreal,rrightreal+0], c1;
MDR ← rtemp, c2;{ write left reversed data to right }
fbrk0: rwork ← rwork LRot8, c3;{ rotate right data }
flpwrt: MAR ← [rhleftreal,rleftreal+0], c1;
MDR ← rwork, width ← width - 1,ZeroBr, c2;{ write right reversed data to left }
{updata word counter for next pair of words to flip}
BRANCH [fleftloop,chkodd,2], c3;
{**************************************************************************************** Reverse bits or byte
****************************************************************************************}
RReverseBits:{ right word }
rwork ← rwork LRot8,GOTO[ReverseBits], c1;{rotate rwork back, process reverse bits}
LReverseBits:{ left word }
rwork ← rwork LRot8,GOTO[ReverseBits], c1;{rotate rwork back, process reverse bits}
MReverseBits:{ middle word }
rwork ← rwork LRot8, c1;{rotate rwork back, process reverse bits}
ReverseBits:
rcount ← rcount-1,ZeroBr, c2;
rwork ← rwork DRShift1,BRANCH[$,RevRet], c3;
rworkR ← rworkR DLShift1,GOTO [ReverseBits], c1;
RevRet: rwork ← ~rworkR,L7Disp, c1;{invert result from Q}
DISP2[fLRM], c2;
fmto: GOTO[fmrotate], c3,at[2,4,fLRM];
flto: GOTO[ftoright], c3,at[0,4,fLRM];
frto: GOTO[fwrite], c3,at[1,4,fLRM];
{**************************************************************************************** FlipX Page Cross Handler
****************************************************************************************}
flpagecross:{ page cross from left word }
rVirtualL ← Uworkrleft,CANCELBR[fpcross,1], c3;{ left word, same as fmpagecross }
frpagecross:{ page cross from right word }
rVirtualL ← Urright,CANCELBR[$,1], c3;{ restore previous right virtual address }
frnxt: rhVirtualH ← Urhright, c1;{rhright}
rVirtualL ← rVirtualL or 0FF,L0 ← L0.FlipXLast, c2;{ mask out low order 8 bits }
rVirtualL ← rVirtualL - r0100, CarryBr, c3;{ new page number }
Q ← rhVirtualH - 1,LOOPHOLE[byteTiming],BRANCH[$,frpno], c1;
rhVirtualH ← Q LRot0,GOTO[frpcom], c2;
frpno: Noop, c2;
frpcom: Urright ← rVirtualL, c3;{resave new right virtual address into working U-register}
Q ← rhVirtualH, c1;
Urhright ← Q, c2;{remap real address for right}
CALL[MapSrc], c3;{remap new page and get new real address}
rwork ← MD,L7Disp,GOTO[fDisp], c3,MapSrcRet[L0.FlipXLast];
fmpagecross:{ page cross from middle word }
rVirtualL ← Uworkrleft,CANCELBR[$,1], c3;{ use left process for middle word, restore the 1st left virtual address,L7=0 for left, L7=1 for right }
fpcross:
rhVirtualH ← Uworkrhleft, c1;{rhleft}
rVirtualL ← rVirtualL and ~0FF,L0 ← L0.FlipXLast, c2;{ mask out low order 8 bits }
rVirtualL ← rVirtualL + r0100, CarryBr, c3;{ new page number for left }
Q ← rhVirtualH + 1, LOOPHOLE[byteTiming],BRANCH[fmcont,$], c1;
rhVirtualH ← Q LRot0,GOTO[fmpcom], c2;
fmcont: Noop, c2;
fmpcom: Uworkrleft ← rVirtualL, c3;{update new virtual address into left working U-register*17*}
Q ← rhVirtualH, c1;
Uworkrhleft ← Q, c2;
CALL[MapDst], c3;{remap new page and get new real address}
rwork ← MD,L7Disp, c3,MapDstRet[L0.FlipXLast];
fDisp: DISP2[fLRMpc], c1;
pcleft: L2Disp, c2,at[0,4,fLRMpc];
BRANCH[LReverseBits,ftoright,2], c3;{*17*}
pcmiddle:
L2Disp, c2,at[2,4,fLRMpc];
BRANCH[MReverseBits,fmrotate,2], c3;{*17*}
pcright:
L2Disp, c2,at[1,4,fLRMpc];
BRANCH[RReverseBits,fwrite,2], c3;{*17*}
{**************************************************************************************** FlipX Page Fault Handler
****************************************************************************************}
{{page fault from 1st right word mapping}
GOTO[fpfRest], c3,MapSrcF[L0.FlipXRight];
{page fault from right word pagecross remap}
GOTO[fpfRest], c3,MapSrcF[L0.FlipXLast];
{page fault from left or middle word remap}
GOTO[fpfRest], c3,MapDstF[L0.FlipXLast];}
FlipXPageFault:{page fault from commapsub for 1st left word}
uFaultParm0 ← VD, c3;
T ← Q, c1;
Q ← rhVD, c2;
uFaultParm1 ← Q, c3;
fpfRest:
Noop, c1;
GOTO[Bank1Fault], c2;
{**************************************************************************************** odd case
****************************************************************************************}
fonlyone:{ only one word to process }
rcount ← 11, c3;
MAR ← [rhleftreal,rleftreal+0],GOTO[fmiddlec2], c1;{ 1st left word entry }
chkodd: rcount ← USavecheck, c1;
[] ← rcount+0,NegBr, c2;
rcount ← 11,BRANCH[foddnot1st,ftoexit], c3;
foddnot1st:
MAR ← rleftreal ← [rhleftreal,rleftreal+1],L7 ← 2{Flip.Middle}, c1;{ update L7 caller}
fmiddlec2:
L2Disp,BRANCH[$,fmpagecross,1], c2;
rwork ← MD,BRANCH[MReverseBits,$,2], c3;{ read middle data }
fmrotate:
rwork ← rwork LRot8, c1;
Noop, c2;
Noop, c3;
fmtowrite:
MAR ← [rhleftreal,rleftreal+0], c1;{rotate data, set up write address, branch bits or gray}
fmwrite:
MDR ← rwork , c2;{ write right data to left }
fnodataB:
stackP ← 0,GOTO[Bank1NxtInstc1], c3;
ftoexit:Noop, c1;
GOTO[fnodataB], c2;