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