;; Press Microcode -- "Scan Microcode" (Scan conversion pass) ; last modified by Butterfield, September 29, 1980 4:22 PM ; - change TRP10 and TRP11 end tests to be SH=0 - 9/29 ; - ScanPutChar(TRP1), don't mask down BELOChar.Bit - 8/8 ; - add TRP10 and TRP11 dispatches - 3/18 ; - include DispatchMc.mu inline and start to re-work it - 3/18 ; - get lastMask using rightMask1 - 3/7 ; - bum a word at TRP2 - 3/5/80 %0, 1777, 23, LOC23; Used by RdRAM %0, 1777, 24, LOC24; and WriteRam in ScanConvert %0, 1777, 37, TRAP1; RAM trap location $LREG $R40; #TriConMc.Mu; ; Additional emulator definitions $AC2 $R1; $AC3 $R0; $PC $R6; $XREG $R7; $TEMP $R5; Shared with SAD $400 $400; ;R register availability: ; R10 ; (R14 used by disk) ; R15-R17 ; R35-R36 ; ;S register availability: ; (R40 = last L in RAM) ; R41-R56 -- used by Slot, but can be re-used if Slot off. ; (R71-R76 used by disk) ; (R77 unusable) ; Notation: ; ** means TASK break may happen after this instruction ; Note that an instruction line with ** may NOT have ; branch conditions or BUS (i.e., anything that alters NEXT) ; !a,b means the label a (which is the goto of this instruction) ; is in a branch table with b. ; ;******************************************************************** ; Trap handling stuff (copied from Ingalls) ; If trap is 70000 + disp field, this is a trap for us; dispatch ; on low order 3 bits to TRP0-TRP7. Otherwise, return the trap ; to the Emulator. !637,1,TRAPX10; X10 microcode locn of TRAP !645,1,TRAPX13; X13 location ;TRAP1; X21 location !1,2,RETRAP,TRPDISP; TRAPX10: T_ 37, :TRPX; TRAPX13: T_ 37, :TRPX; TRAP1: T_ 37, :TRPX; TRPX: L_ T_ XREG.T; Look for trap # 70000 TEMP_ L; T_ 20; L_ LREG-T; SH=0, TASK; :RETRAP; ** !RETRAP, TRPDISP RETRAP: MAR_ TRAPPC; T_ TEMP; MD_ PC; MAR_ TRAPPC+T+1; NOP; L_ MD, TASK, :PCL; ; Trap dispatch to the various functions !17,20,TRP0,TRP1,TRP2,TRP3,TRP4,TRP5,TRP6,TRP7,TRP10,TRP11; TRPDISP: SINK_ DISP, BUS; No out-of-range protection :TRP0; ;******************************************************************** ; BCPLRETL -- Do a "Bcpl return" with L as value of the function. ; BCPLRET -- Simply do a "Bcpl return" BCPLRETL: AC0_ L; BCPLRET: L_ AC3+1, TASK; PCL: PC_ L; ** SWRET: SWMODE; :START; ;******************************************************************** ; Definitions for Press scan conversion microcode ; ; ; G L O B A L ; $ScanBitWc $R70; Number of words/scan line $mpSBuf $R67; ScanLineIndex!s = pointer to scan-line buffer ; already offset for any margin effects $177770 $177770; $177774 $177774; $177776 $177776; $170000 $170000; ; ScanPutChar $ShiftCnt $R66; $nS $R65; $Fw $R64; $Fadr $R63; $Badr $R62; $FCNT $R61; $WLEFT $R60; $SubRet $R57; $Fb $R56; $FracPart $R55; $lastMask $R54; $leftMask $R53; $rightMask $R52; $leftMask1 $R51; $rightMask1 $R50; $initialFadr $R47; $thisW $R46; $inputShiftAmt $R45; $nextW $R15; Must be an R register $Badr0 $R16; Must be an R register ;TEMP $R5; shared with SAD ; ScanPutDots (also ScanPutHalf) $INADR $R66; $BIT $R65; $BBIT $R64; $BINCR $R63; $BBITINIT $R62; $BDIM $R61; $BSTATUS $R60; $BDELTA $R57; $INBIT $R56; $WORDOUT $R55; $BCOUNT $R54; $WORDIN $R53; ; ScanPutHalf $screenAddr $R52; $screenMod $R51; $screenCount $R50; $screen $R47; $cascadeDiag $R46; $black $R45; $white $R44; $range $R43; $threshold $R42; $errorBuff $R41; $error $R36; R register for shifts $error1 $R35; R register for shifts $sample $R17; R register for shifts $MASK $R3; ; ;ScanLoadVars(v) ; v!0 = mpSBuf ; v!1 = ScanBitWc TRP0: MAR_ AC0; NOP; L_MD; MAR_ AC0+1; mpSBuf_ L; L_MD, TASK; ScanBitWc_ L, :BCPLRET; ** ; ;******************************************************************** ; ScanPutChar(Soff, v) -- scan convert a character ; v=> structure BELOChar describing character to do: ; Cbit bit 1 =1 ; spare bit 3 ; hw bit 12 ;-Number of bits/sl ; ; orbitX bit 4 ;scan line in band to start on (=Soff) ; Bit bit 12 ;Address on scan line ; ; bitOffset bit 4 ;offset of char start in word of font ; orbitS bit 12 ;nscanlines-1 left to do ; ; Fadr word ;Address of next font word ; returns 0 if no left-overs ; returns 4 (size BELOChar/16) if leftovers ; also ns and Fadr ; fields of v are updated. !17,20,CYCL0,CYCL1,CYCL2,CYCL3,CYCL4,CYCL5,CYCL6,CYCL7,CYCL8,CYCR7,CYCR6,CYCR5,CYCR4,CYCR3,CYCR2,CYCR1; !17,20,wCycR0,wCycR1,wCycR2,wCycR3,wCycR4,wCycR5,wCycR6,wCycR7,wCycL8,wCycL7,wCycL6,wCycL5,wCycL4,wCycL3,wCycL2,wCycL1; !17,20,PCleftMask0,PCleftMask1,PCleftMask2,PCleftMask3,PCleftMask4,PCleftMask5,PCleftMask6,PCleftMask7,PCleftMask10,PCleftMask11,PCleftMask12,PCleftMask13,PCleftMask14,PCleftMask15,PCleftMask16,PCleftMask17; ;3/7 !17,20,PClastMask0,PClastMask1,PClastMask2,PClastMask3,PClastMask4, ;3/7 PClastMask5,PClastMask6,PClastMask7,PClastMask10,PClastMask11, ;3/7 PClastMask12,PClastMask13,PClastMask14,PClastMask15,PClastMask16, ;3/7 PClastMask17; !1,2,PCGOT1Mask,PCGOTlastMask; ;3/7 !1,2,PCGOTlastMask2,PCGOTlastMask1; ;3/7 !17,20,PC1Mask0,PC1Mask1,PC1Mask2,PC1Mask3,PC1Mask4,PC1Mask5,PC1Mask6,PC1Mask7,PC1Mask10,PC1Mask11,PC1Mask12,PC1Mask13,PC1Mask14,PC1Mask15,PC1Mask16,PC1Mask17; !1,2,PCH2,PCH3; !1,2,PCH0,PCH5; !1,2,CHARL1,CHARL2; !1,2,CHARLmore,CHARLlast; !1,2,cycleThisW,ZthisW; !1,2,CHARL5,CHARL6; !1,2,CHARL,CHARL8; !1,2,CHARL9,PCH1; !1,2,CYRET0,CycleRet2; ;Note: Badr0 must be R reg for shifts TRP1: MAR_L_AC1+1; v AC1_L; ;8/8 T_ 7777; ;8/8 L_ MD AND T; //let Bit=v>>BELOChar.Bit L_ MD; //let Bit=v>>BELOChar.Bit ;8/8 Badr0_ L RSH 1; 1 shift T_ 17; L_LREG AND T,TASK; Compute skew ShiftCnt_L; ** //let ShiftCnt=(Bit) T_ 170000; MAR_L_AC1-1; hw word L_ Badr0; Badr0_ L RSH 1; 2 shifts T_MD OR T; T_-hw L_0-T; Fb_L; //let Fb=-(#170000+v>>BELOChar.orbitW) T_17; L_Fb AND T; FracPart_L; //let FracPart=Fb SINK_ FracPart, BUS; ;3/7 T_ 170000, :PClastMask0; !PClastMask0,1,2,.... ;3/7 PCGOTlastMask: lastMask_L; //let lastMask=masks!(16-FracPart) T_ 0, BUS=0, :PC1Mask0; !PC1Mask0,1,2,.... ;3/7 PCGOTlastMask: ;3/7 T_ ALLONES, SH<0; ;3/7 L_ LREG XOR T, :PCGOTlastMask2; !PCGOTlastMask2,PCGOTlastMask1 ;3/7 PCGOTlastMask1: ;3/7 L_ ALLONES; ;3/7 PCGOTlastMask2: ;3/7 lastMask_L; //let lastMask=masks!(16-FracPart) ;3/7 T_17; L_Fb+T; T_177760; L_LREG AND T; Fw_L; //let Fw=(Fb+15)/16 MAR_L_AC1+1; AC1_L; T_7777; L_T_MD AND T; T_bitOffset,nS;L_nS L_LREG+1; was nScanLines-1 nS_L,L_T; //let nS=v>>BELOChar.orbitS+1 T_170000; L_T_LREG.T; TEMP_L MLSH 1; L_T_TEMP; TEMP_L MLSH 1; L_T_TEMP; TEMP_L MLSH 1; L_T_TEMP; TEMP_L MLSH 1; L_TEMP,TASK; inputShiftAmt_L; //let inputShiftAmt=v>>BELOChar.bitOffset SINK_ShiftCnt, BUS; ;3/7 T_ALLONES,:PC1Mask0;!PC1Mask0,... T_ ALLONES, BUS=0, :PC1Mask0; !PC1Mask0,... ;3/7 PCGOT1Mask: rightMask1_L; //let rightMask1=-1 rshift ShiftCnt L_rightMask1 XOR T; leftMask1_L; //let leftMask1=not rightMask1 MAR_ AC1+1; Fadr word L_ Badr0; Badr0_ L RSH 1; 3 shifts L_MD, TASK; initialFadr_L; ** initialFadr= first font address L_Badr0; Badr0_ L RSH 1; 4 th shift T_AC0; Scan line number (0-15 decimal) MAR_ mpSBuf+T; L_ 20-T; AC0_L; AC0= number of scan-lines to go to run out T_MD-1; //let Badr=mpSBuf!Soff+(Bit rshift 4) ;Prepare to call CHARL to do one scan-line of the character PCH0: L_Badr0+T; L=first band address-1 Badr0_L, TASK; Badr_L; ** SINK_inputShiftAmt,BUS; T_ALLONES,:PCleftMask0;!PCleftMask0,PCleftMask1,... PCGOTleftMask: leftMask_L; //let leftMask=masks!inputShiftAmt L_leftMask XOR T,TASK; rightMask_L; //let rightMask=not leftMask LOC23: XMAR_L_initialFadr; Fadr_L; T_MD,:CycleInit; //let nextW=Cycle(Fadr!0,inputShiftAmt) CycleRet1: L_0; WLEFT_L; //let WLEFT=0 T_20; L_ Fw-T, TASK; FCNT_ L, :CHARL; ** FCNT = 20*(Fw-1) PCH1: L_ nS-1; nS_L, SH=0; L_AC0-1, :PCH2; !PCH2,PCH3 ;nS has not expired; more to do. PCH2: AC0_L, SH=0; T_ScanBitWc, :PCH0; !PCH0,PCH5 ;nS=0 -- character is completed PCH3: L_0, :BCPLRETL; No leftovers ;S=0 -- run out of band. Update BELOChar structure PCH5: L_T_inputShiftAmt; move to leftmost 4 bits TEMP_L MRSH 1; L_T_TEMP; TEMP_L MRSH 1; L_T_TEMP; TEMP_L MRSH 1; L_T_TEMP; TEMP_L MRSH 1; T_TEMP; MAR_AC1; L_ nS-1; L_LREG OR T, TASK; //v>>BELOChar.bitOffset=inputShiftAmt MD_ LREG; ** //v>>BELOChar.orbitS=nS-1 MAR_AC1+1; Now restore Fadr to structure L_4; MD_initialFadr,:BCPLRETL; //v>>BELOChar.CoreAdr=Fadr ; //resultis size BELOChar/16 ; Mask tables here to make above code somewhat more readable ;3/7 PClastMask0: L_ ALLONES, :PCGOTlastMask; ;3/7 PClastMask1: L_ 100000, :PCGOTlastMask; ;3/7 PClastMask2: L_ 140000, :PCGOTlastMask; ;3/7 PClastMask3: L_ 160000, :PCGOTlastMask; ;3/7 PClastMask4: L_ 170000, :PCGOTlastMask; ;3/7 PClastMask5: L_ 174000, :PCGOTlastMask; ;3/7 PClastMask6: L_ 176000, :PCGOTlastMask; ;3/7 PClastMask7: L_ 177000, :PCGOTlastMask; ;3/7 PClastMask10: L_ 177400, :PCGOTlastMask; ;3/7 PClastMask11: L_ 177600, :PCGOTlastMask; ;3/7 PClastMask12: L_ 177700, :PCGOTlastMask; ;3/7 PClastMask13: L_ 177740, :PCGOTlastMask; ;3/7 PClastMask14: L_ 177760, :PCGOTlastMask; ;3/7 PClastMask15: L_ 177770, :PCGOTlastMask; ;3/7 PClastMask16: L_ 177774, :PCGOTlastMask; ;3/7 PClastMask17: L_ 177776, :PCGOTlastMask; PC1Mask0: L_ ALLONES, :PCGOT1Mask; PC1Mask1: L_ 77777, :PCGOT1Mask; PC1Mask2: L_ 37777, :PCGOT1Mask; PC1Mask3: L_ 17777, :PCGOT1Mask; PC1Mask4: L_ 7777, :PCGOT1Mask; PC1Mask5: L_ 3777, :PCGOT1Mask; PC1Mask6: L_ 1777, :PCGOT1Mask; PC1Mask7: L_ 777, :PCGOT1Mask; PC1Mask10: L_ 377, :PCGOT1Mask; PC1Mask11: L_ 177, :PCGOT1Mask; PC1Mask12: L_ 77, :PCGOT1Mask; PC1Mask13: L_ 37, :PCGOT1Mask; PC1Mask14: L_ 17, :PCGOT1Mask; PC1Mask15: L_ 7, :PCGOT1Mask; PC1Mask16: L_ 3, :PCGOT1Mask; PC1Mask17: L_ ONE, :PCGOT1Mask; PCleftMask0: L_ ALLONES, :PCGOTleftMask; PCleftMask1: L_ 177776, :PCGOTleftMask; PCleftMask2: L_ 177774, :PCGOTleftMask; PCleftMask3: L_ 177770, :PCGOTleftMask; PCleftMask4: L_ 177760, :PCGOTleftMask; PCleftMask5: L_ 177740, :PCGOTleftMask; PCleftMask6: L_ 177700, :PCGOTleftMask; PCleftMask7: L_ 177600, :PCGOTleftMask; PCleftMask10: L_ 177400, :PCGOTleftMask; PCleftMask11: L_ 177000, :PCGOTleftMask; PCleftMask12: L_ 176000, :PCGOTleftMask; PCleftMask13: L_ 174000, :PCGOTleftMask; PCleftMask14: L_ 170000, :PCGOTleftMask; PCleftMask15: L_ 160000, :PCGOTleftMask; PCleftMask16: L_ 140000, :PCGOTleftMask; PCleftMask17: L_ 100000, :PCGOTleftMask; ; ;Character loop for one scan-line. ; Enter at CHARL with: ; initialFadr+1 => next word of font to fetch ; Badr+1 => next word to store in the band ; ShiftCnt = shift amount for each font word (to the right) ; FCNT+20 = 20* number of font words/scanline ; MASK = -1 rshift ShiftCnt ; Exit to PCH1 with: ; Fadr+1 => next word of font to fetch ; ShiftCnt,MASK unchanged ;let thisW=nextW&leftMask ;nextW=Cycle(Fadr!j,inputShiftAmt) ;thisW=thisW+(rightMask&nextW) CHARL: T_leftMask; L_nextW AND T; thisW_L; //let thisW=nextW&leftMask LOC24: XMAR_L_Fadr+1; Fadr_L; L_MD, BUS=0, TASK; nextW_L, :CHARL1; ** !CHARL1,CHARL2 ;Left cycle the non-zero font word by inputShiftAmt, and pick out some low bits ; (governed by MASK) to put in this band word. CHARL1: T_nextW, :Cycle; //nextW=Cycle(Fadr!j,inputShiftAmt) CycleRet2: T_rightMask,:CHARL3; CHARL2: T_rightMask; CHARL3: L_nextW AND T; T_thisW; L_LREG+T; thisW_L; //thisW=thisW+(rightMask&nextW) ;if j eq Fw then //update shiftAmt, mask w ; [ thisW=thisW&lastMask ; inputShiftAmt=inputShiftAmt+Fb ; initialFadr=initialFadr+inputShiftAmt/16 ; inputShiftAmt=inputShiftAmt ; ] SINK_FCNT,BUS=0; L_T_thisW,:CHARLmore; !1,2,CHARLmore,CHARLlast; CHARLlast: L_lastMask AND T,TASK; thisW_L; //thisW=thisW&lastMask T_Fb; L_inputShiftAmt+T; inputShiftAmt_L; //inputShiftAmt=inputShiftAmt+Fb TEMP_L RSH 1; L_TEMP; TEMP_L RSH 1; L_TEMP; TEMP_L RSH 1; L_TEMP; TEMP_L RSH 1; T_initialFadr; L_TEMP+T,TASK; initialFadr_L; //initialFadr=initialFadr+inputShiftAmt/16 T_17; L_inputShiftAmt AND T; inputShiftAmt_L; //inputShiftAmt=inputShiftAmt L_T_thisW,:CHARLmore; ;if thisW then //Play only if non-zero ; [ thisW=Cycle(thisW,16-ShiftCnt) ; WLEFT=(thisW&rightMask1)%WLEFT ; ] CHARLmore: L_T_thisW,BUS=0; NOP,:cycleThisW; !1,2,cycleThisW,ZthisW; cycleWRet: T_rightMask1; L_thisW AND T; T_WLEFT; L_LREG OR T; WLEFT_L; ;if WLEFT then ; Badr!0=(Badr!0 % WLEFT) ZthisW: SINK_WLEFT,BUS=0; NOP, :CHARL5; !CHARL5,CHARL6 ;Because bits to "or" (W1) non-zero, must store CHARL5: MAR_Badr+1; T_WLEFT; L_ MD OR T; MAR_T_Badr+1; WLEFT_L,L_T; Badr_ L, TASK; Bump Badr MD_ WLEFT, :CHARL7; ** ;WLEFT=thisW&leftMask1 ;Badr=Badr+1 CHARL6: L_Badr+1, TASK; Badr_L; ** ;Compute WLEFT, the bits left over for next band word. CHARL7: T_ leftMask1; L_ thisW AND T,TASK; Bits left over for next time WLEFT_ L; ** ;If FCNT=0, we are done with the scan-line. Else FCNT_FCNT-20 L_T_ FCNT; L_177760 +T, SH=0; Test FCNT=0 FCNT_L, :CHARL; !CHARL,CHARL8 ;End of loop, need to store final band word with any remaining bits ; Badr!0=(Badr!0 % WLEFT) CHARL8: MAR_Badr+1; L_T_ WLEFT,BUS=0; L_MD OR T, :CHARL9; !CHARL9,PCH1 CHARL9: MAR_Badr+1; NOP, TASK; MD_ LREG, :PCH1; ** ; ;Cycle left. ; Enter at CYCLE with: ; inputShiftAmt = count of places to cycle ; T = bits ; Exit to CHARL2 with ; nextW= cycled bits ; Note: nextW must be R register for shifts CycleInit: L_0; SubRet_L,:Cycle; Cycle: SINK_ inputShiftAmt, BUS; L_ T, TASK, :CYCL0; CYCL0: nextW_ L, :CYRET; CYCR4: nextW_L MRSH 1; CYCY3: T_L_nextW, TASK; CYCR3: nextW_L MRSH 1; CYCY2: T_L_nextW, TASK; CYCR2: nextW_L MRSH 1; CYCY1: T_L_nextW; TASK; CYCR1: nextW_L MRSH 1, :CYRET; CYCL4: nextW_L MLSH 1; CYCZ3: T_L_nextW, TASK; CYCL3: nextW_L MLSH 1; CYCZ2: T_L_nextW, TASK; CYCL2: nextW_L MLSH 1; CYCZ1: T_L_nextW, TASK; CYCL1: nextW_L MLSH 1, :CYRET; CYCL8: nextW_ L LCY 8, :CYRET; CYCL7: nextW_ L LCY 8, :CYCY1; CYCL6: nextW_ L LCY 8, :CYCY2; CYCL5: nextW_ L LCY 8, :CYCY3; CYCR7: nextW_ L LCY 8, :CYCZ1; CYCR6: nextW_ L LCY 8, :CYCZ2; CYCR5: nextW_ L LCY 8, :CYCZ3; CYRET: SINK_SubRet,BUS; L_ONE,:CYRET0; !1,2,CYRET0,CycleRet2 CYRET0: SubRet_L,:CycleRet1; ;thisW_thisW rCycle ShiftCnt cycleThisW: SINK_ ShiftCnt, BUS; L_ T, TASK, :wCycR0; wCycR0: thisW_ L, :cycleWRet; wCycR4: TEMP_L MRSH 1; wCycY3: T_L_TEMP, TASK; wCycR3: TEMP_L MRSH 1; wCycY2: T_L_TEMP, TASK; wCycR2: TEMP_L MRSH 1; wCycY1: T_L_TEMP; TASK; wCycR1: TEMP_L MRSH 1, :wCycRET; wCycL4: TEMP_L MLSH 1; wCycZ3: T_L_TEMP, TASK; wCycL3: TEMP_L MLSH 1; wCycZ2: T_L_TEMP, TASK; wCycL2: TEMP_L MLSH 1; wCycZ1: T_L_TEMP, TASK; wCycL1: TEMP_L MLSH 1, :wCycRET; wCycL8: TEMP_ L LCY 8, :wCycRET; wCycL7: TEMP_ L LCY 8, :wCycY1; wCycL6: TEMP_ L LCY 8, :wCycY2; wCycL5: TEMP_ L LCY 8, :wCycY3; wCycR7: TEMP_ L LCY 8, :wCycZ1; wCycR6: TEMP_ L LCY 8, :wCycZ2; wCycR5: TEMP_ L LCY 8, :wCycZ3; wCycRET: L_TEMP; thisW_L,:cycleWRet; ; ;******************************************************************** ;ScanPutDots(Soff, v) ; Blows up a 1-bit bit map, and spits it out. ; Soff = scan-line number within band (0-15 decimal) ; v => BEDots entry: ; H word ;;ignore ; Bstart word -- starting bit position on scan-line ; Bincr word -- =+1 if bit position increases, else -1 ; Bdim word -- -# of bits to output on the scan-line ; Opaque bit ; Smagnify bit ; Bmagnify bit -- 20000 bit =1 => magnify on output ; Code bit 13 ; Bdelta word -- decrement for DDA ; BitBuf word -- pointer to first word of input data ; BitPhase word -- bit position in word of first input sample ; ;DotsDeltaConst=#37777 ; $DOTSDELTACOnST $37777; !17,20,SPDORM0,SPDORM1,SPDORM2,SPDORM3,SPDORM4,SPDORM5,SPDORM6,SPDORM7,SPDORM10,SPDORM11,SPDORM12,SPDORM13,SPDORM14,SPDORM15,SPDORM16,SPDORM17; !17,20,SPDMASK0,SPDMASK1,SPDMASK2,SPDMASK3,SPDMASK4,SPDMASK5,SPDMASK6,SPDMASK7,SPDMASK10,SPDMASK11,SPDMASK12,SPDMASK13,SPDMASK14,SPDMASK15,SPDMASK16,SPDMASK17; !1,2,SPD2,SPD1; !1,2,SPD6,SPD4; !1,2,SPD20,SPD8; !1,2,SPD3,SPD9; !1,2,SPD21,SPD23; !1,2,SPD26,SPD28; !1,2,SPD29,SPD40; !1,2,SPD27,SPD41; !1,2,SPD30,SPD3a; !1,2,SPD20a,SPD31; !1,2,SPHREE,SPDREE; ;TRP2: MAR_AC1+1; Fetch Bstart ; T_3; ; L_AC1+T; TRP2: T_ MAR_ AC1 +1; Fetch Bstart L_ 2 +T; AC1_L; L_MD; MAR_AC1-1; Fetch Bincr Badr0_L RSH 1; 1 shift T_17; L_LREG AND T; T_MD; BBIT_L, L_T, TASK; Bit offset in the word to begin output BINCR_L; ** L_BINCR; MAR_AC1, SH<0; L_0, :SPD2; !SPD2,SPD1 -- branch if Bincr<0 SPD1: L_17; Bincr<0 SPD2: BBITINIT_L; L_MD, TASK; BDIM_L; ** MAR_L_AC1+1; Fetch word with Bmagnify in it; AC1_L; L_Badr0; Badr0_L RSH 1; 2nd shift L_MD, TASK; BSTATUS_L; ** MAR_L_AC1+1; Fetch Bdelta AC1_L; L_Badr0; Badr0_L RSH 1; 3rd shift L_MD, TASK; BDELTA_L; ** MAR_L_AC1+1; Fetch address of input bits AC1_L; L_MD-1, TASK; INADR_L; ** INADR=address of next word to get -1 MAR_L_AC1+1; Fetch bit position in word AC1_L; L_Badr0; Badr0_L RSH 1; 4th shift T_MD; L_17-T, TASK; INBIT_L; ** T_AC0; MAR_mpSBuf+T; Fetch scan-buffer L_0; WORDOUT_L; T_Badr0; L_MD+T, TASK; Badr0_L; ** Badr0 = band address ;Test for halftoning here T_37; L_BSTATUS AND T; L_DOTSDELTACOnST,SH=0; BCOUNT_L, :SPHREE; !SPHREE,SPDREE ;Get a Bit SPD3: L_INBIT-1, :SPD3z; Duplicated in order to address it SPD3a: L_INBIT-1; SPD3z: INBIT_L, SH<0; L_17, :SPD6; !SPD6,SPD4 SPD4: INBIT_L; Ran out of input word SPDREE: MAR_L_INADR+1; Fetch next input word INADR_L; L_MD, TASK; WORDIN_L; ** SPD6: SINK_INBIT,BUS; T_WORDIN, :SPDMASK0; !SPDMASK0,1,2,... SPD7: BIT_L; ** ;Get DDA T_20000; L_BSTATUS AND T; T_BDELTA, SH=0; Test Bmagnify L_BCOUNT-T, :SPD20; !SPD20,SPD8 SPD8: BCOUNT_L, SH<0; Not magnifying -- do DDA T_DOTSDELTACOnST, :SPD3; !SPD3,SPD9 SPD9: L_BCOUNT+T, TASK; BCOUNT_L; ** ;Put a bit SPD20: L_BIT, :SPD20z; Duplicated in order to address it SPD20a: L_BIT; SPD20z: T_BBIT, SH=0; L_BINCR+T, :SPD21; !SPD21,SPD23 SPD21: BBIT_L, L_T; Must or a bit in SINK_LREG, BUS; T_WORDOUT, :SPDORM0; !SPDORM0,1,2,... SPD22: WORDOUT_L, :SPD24; ** SPD23: BBIT_L; SPD24: T_177760; L_BBIT AND T; L_BDIM+1, SH=0; BDIM_L, SH=0, :SPD26; !SPD26,SPD28 ;Bbit has run below 0 or above 17, so must store a word. SPD26: MAR_Badr0, :SPD27; !SPD27,SPD41 -- to SPD41 if Bdim=0 SPD27: L_BBITINIT; BBIT_L; T_WORDOUT; L_MD OR T,TASK; WORDOUT_L; ** T_BINCR; MAR_Badr0; L_Badr0+T; Badr0_L, T_0; Badr0 R register => T_0 MD_WORDOUT, L_T, TASK; WORDOUT_L; ** SPD28: T_20000, :SPD29; !SPD29,SPD40 -- to SPD40 if Bdim=0 SPD29: L_BSTATUS AND T; T_BDELTA, SH=0; L_BCOUNT-T, :SPD30; !SPD30,SPD3a -- if no magnify, goto getabit SPD30: BCOUNT_L, SH<0; T_DOTSDELTACOnST, :SPD20a; !SPD20a,SPD31 -- if overflow, SPD31: L_BCOUNT+T, TASK; Add the constant BCOUNT_L, :SPD3; ** ; Finish out by storing the last word. Do not bother to update ; any variables in v as they dont matter SPD40: MAR_Badr0; SPD41: T_WORDOUT; L_MD OR T; MAR_Badr0; T_0; MD_LREG, L_T, :BCPLRETL; Return 0 ;Mask table here to make above more readable. SPDORM0: L_100000 OR T, TASK, :SPD22; SPDORM1: L_40000 OR T, TASK, :SPD22; SPDORM2: L_20000 OR T, TASK, :SPD22; SPDORM3: L_10000 OR T, TASK, :SPD22; SPDORM4: L_4000 OR T, TASK, :SPD22; SPDORM5: L_2000 OR T, TASK, :SPD22; SPDORM6: L_1000 OR T, TASK, :SPD22; SPDORM7: L_400 OR T, TASK, :SPD22; SPDORM10: L_200 OR T, TASK, :SPD22; SPDORM11: L_100 OR T, TASK, :SPD22; SPDORM12: L_40 OR T, TASK, :SPD22; SPDORM13: L_20 OR T, TASK, :SPD22; SPDORM14: L_10 OR T, TASK, :SPD22; SPDORM15: L_4 OR T, TASK, :SPD22; SPDORM16: L_2 OR T, TASK, :SPD22; SPDORM17: L_ONE OR T, TASK, :SPD22; SPDMASK0: L_ONE AND T, TASK, :SPD7; SPDMASK1: L_2 AND T, TASK, :SPD7; SPDMASK2: L_4 AND T, TASK, :SPD7; SPDMASK3: L_10 AND T, TASK, :SPD7; SPDMASK4: L_20 AND T, TASK, :SPD7; SPDMASK5: L_40 AND T, TASK, :SPD7; SPDMASK6: L_100 AND T, TASK, :SPD7; SPDMASK7: L_200 AND T, TASK, :SPD7; SPDMASK10: L_400 AND T, TASK, :SPD7; SPDMASK11: L_1000 AND T, TASK, :SPD7; SPDMASK12: L_2000 AND T, TASK, :SPD7; SPDMASK13: L_4000 AND T, TASK, :SPD7; SPDMASK14: L_10000 AND T, TASK, :SPD7; SPDMASK15: L_20000 AND T, TASK, :SPD7; SPDMASK16: L_40000 AND T, TASK, :SPD7; SPDMASK17: L_100000 AND T, TASK, :SPD7; ; ;*************************************** ;ScanPutHalf (finish initialization, and spit out the bits) !17,20,hCYCR0,hCYCR1,hCYCR2,hCYCR3,hCYCR4,hCYCR5,hCYCR6,hCYCR7,hCYCL8,hCYCL7,hCYCL6,hCYCL5,hCYCL4,hCYCL3,hCYCL2,hCYCL1; !17,20,SPHOrM0,SPHOrM1,SPHOrM2,SPHOrM3,SPHOrM4,SPHOrM5,SPHOrM6,SPHOrM7,SPHOrM10,SPHOrM11,SPHOrM12,SPHOrM13,SPHOrM14,SPHOrM15,SPHOrM16,SPHOrM17; !17,20,SPHMask0,SPHMask1,SPHMask2,SPHMask3,SPHMask4,SPHMask5,SPHMask6,SPHMask7,SPHMask10,SPHMask11,SPHMask12,SPHMask13,SPHMask14,SPHMask15,SPHMask16,SPHMask17; !1,2,SPH6,SPH4; !1,2,SPH20,SPH8; !1,2,SPH3,SPH9; !1,2,SPH21,SPH23; !1,2,SPH26,SPH28; !1,2,SPH29,SPH40; !1,2,SPH27,SPH41; !1,2,SPH30,SPH3a; !1,2,SPH20a,SPH31; !1,2,SPHScreen,SPHNoScreen; !1,2,NoRem,Rem; SPHREE: T_17; fix INBIT (20-bit-sampleSize instead of 17-bit) T_BSTATUS.T; L_INBIT+1; L_LREG-T; INBIT_L; ;!!NO ERROR DISTRIBUTION!!!MAR_L_AC1+1; pick up Error Vec for error distribution ;!!NO ERROR DISTRIBUTION!!!AC1_L; ;!!NO ERROR DISTRIBUTION!!!T_BDIM; ;!!NO ERROR DISTRIBUTION!!!L_MD-T,TASK; ;!!NO ERROR DISTRIBUTION!!!errorBuff_L; ** L_AC1+1;!!NO ERROR DISTRIBUTION!!! MAR_L_LREG+1; pick up Screen Modulus AC1_L; L_0; cascadeDiag_L; L_MD,TASK; screenMod_L; ** MAR_L_AC1+1; pick up screen address AC1_L; L_MD,TASK; screenAddr_L; ** MAR_L_AC1+1; pick up IMin AC1_L; L_MD,TASK; black_L; ** MAR_AC1+1; pick up IMax L_0; screenCount_L; screen_L; L_MD,TASK; white_L; ** T_black; L_white-T,TASK; nextW_L LSH 1; ** T_nextW-1; !!FIX!! L_0-T; !!FIX!! threshold_L; !!FIX!! L_nextW; nextW_L LSH 1; L_nextW,TASK; range_L; ** range=(white-black)*4 T_37; L_BSTATUS AND T; L_LREG-1; SINK_LREG,BUS; NOP,:SPHMask0; SPH2: MASK_L; ** ; !!BUG: threshold*2 is what's needed !! T_white; ; !!BUG !! L_black-T,TASK; ; !!BUG !! threshold_L; ** L_threshold-1; error_L,:SPHRE; ** ;Get a sample point SPH3: T_17, :SPH3z; Duplicated in order to address it SPH3a: T_17; SPH3z: T_BSTATUS.T; sampleSize L_INBIT-T; INBIT_L, SH<0; L_20-T, :SPH6; !SPH6,SPH4 SPH4: INBIT_L; Ran out of input word SPHRE: MAR_L_INADR+1; Fetch next input word INADR_L; L_MD, TASK; WORDIN_L; ** SPH6: T_WORDIN,:hCYCLE; SPH7: T_MASK; L_nextW AND T; T_black; L_LREG-T; sample_L LSH 1; L_sample; sample_L LSH 1; *4 to avoid errors on 25% calculation ;Get DDA T_20000; L_BSTATUS AND T; T_BDELTA, SH=0; Test Bmagnify L_BCOUNT-T, :SPH20; !SPH20,SPH8 SPH8: BCOUNT_L, SH<0; Not magnifying -- do DDA T_DOTSDELTACOnST, :SPH3; !SPH3,SPH9 SPH9: L_BCOUNT+T, TASK; BCOUNT_L; ** ;Put a bit ;add screen frequency, if called for SPH20: L_screenAddr,BUS=0,:SPH20z; Duplicated in order to address it SPH20a: L_screenAddr,BUS=0; SPH20z: T_screenCount,:SPHScreen; !SPHScreen,SPHNoScreen SPHScreen: MAR_screenAddr+T; L_screenCount+1; screenCount_L; L_MD,TASK; screen_L; ** T_screenMod; L_screenCount XOR T; NOP,SH=0; L_0,:NoRem; !NoRem,Rem Rem: screenCount_L; NoRem: T_screen-1,:SPHyyy; ;!!NO ERROR DISTRIBUTION!!!SPHNoScreen:T_BDIM; ;!!NO ERROR DISTRIBUTION!!! MAR_errorBuff+T; ;!!NO ERROR DISTRIBUTION!!! T_sample-1; ;!!NO ERROR DISTRIBUTION!!! T_screen+T+1; screen+sample screen+sample ;!!NO ERROR DISTRIBUTION!!! L_error-T; error-(screen+sample) ;!!NO ERROR DISTRIBUTION!!! T_MD; errorBuff!BDIM ;!!NO ERROR DISTRIBUTION!!! L_LREG+T; errorBuff!BDIM+error-(screen+sample) SPHNoScreen: T_screen-1; !!NO ERROR DISTRIBUTION!! SPHyyy: T_sample+T+1; !!NO ERROR DISTRIBUTION!! L_0-T; !!NO ERROR DISTRIBUTION!! ;!!NO ERROR DISTRIBUTION!! error_L; ;test error ge threshold then SetBit() or error=error+range T_threshold; L_LREG-T; T_BBIT,SH<0; L_BINCR+T,:SPH21; !SPH21,SPH23 (SetBit,SetBitReturn) SPH21: BBIT_L, L_T; Must or a bit in SINK_LREG, BUS; T_WORDOUT, :SPHOrM0; !SPHOrM0,1,2,... SPH22: WORDOUT_L; ** ;!!NO ERROR DISTRIBUTION!!! L_error, :SPH24; ;!!NO ERROR DISTRIBUTION!!!SPH23: BBIT_L; ;!!NO ERROR DISTRIBUTION!!!T_range; ;!!NO ERROR DISTRIBUTION!!!L_error+T; ;!!NO ERROR DISTRIBUTION!!!error_L; ;now, compute cascading error ;distribution is : Down 25%, Diag 25%, Right 25% ;!!NO ERROR DISTRIBUTION!!!SPH24: SH<0; put sign bit in low order of T for MAGIC ;!!NO ERROR DISTRIBUTION!!!T_0,:pos; !pos,neg ;!!NO ERROR DISTRIBUTION!!!neg: T_ONE; ;!!NO ERROR DISTRIBUTION!!!pos: error_L MRSH 1; error=error/2 (error is signed number) ;!!NO ERROR DISTRIBUTION!!! L_error,TASK; ;!!NO ERROR DISTRIBUTION!!! error1_L MRSH 1; ** error1=error/2 (error is signed number) ;errorBuff!BDIM=cascadeDiag+error1 //prev diag error + new down error ;!!NO ERROR DISTRIBUTION!!! T_BDIM; ;!!NO ERROR DISTRIBUTION!!! MAR_errorBuff+T; ;!!NO ERROR DISTRIBUTION!!! T_error1; ;!!NO ERROR DISTRIBUTION!!! L_cascadeDiag+T,TASK; ;!!NO ERROR DISTRIBUTION!!! MD_LREG; ** ;cascadeDiag=error1 ;!!NO ERROR DISTRIBUTION!!! L_error1,TASK; ;!!NO ERROR DISTRIBUTION!!! cascadeDiag_L; ** SPH24: T_177760,:SPHxxx; ;!!NO ERROR DISTRIBUTION111 SPH23: BBIT_L; ;!!NO ERROR DISTRIBUTION111 T_177760; SPHxxx: L_BBIT AND T; L_BDIM+1, SH=0; BDIM_L, SH=0, :SPH26; !SPH26,SPH28 ;Bbit has run below 0 or above 17, so must store a word. SPH26: MAR_Badr0, :SPH27; !SPH27,SPH41 -- to SPH41 if Bdim=0 SPH27: L_BBITINIT; BBIT_L; T_WORDOUT; L_MD OR T,TASK; WORDOUT_L; ** T_BINCR; MAR_Badr0; L_Badr0+T; Badr0_L, T_0; Badr0 R register => T_0 MD_WORDOUT, L_T, TASK; WORDOUT_L; ** SPH28: T_20000, :SPH29; !SPH29,SPH40 -- to SPH40 if Bdim=0 SPH29: L_BSTATUS AND T; T_BDELTA, SH=0; L_BCOUNT-T, :SPH30; !SPH30,SPH3a -- if no magnify, goto getabit SPH30: BCOUNT_L, SH<0; T_DOTSDELTACOnST, :SPH20a; !SPH20a,SPH31 -- if overflow, SPH31: L_BCOUNT+T, TASK; Add the constant BCOUNT_L, :SPH3; ** ; Finish out by storing the last word. Do not bother to update ; any variables in v as they dont matter SPH40: MAR_Badr0; SPH41: T_WORDOUT; L_MD OR T; MAR_Badr0; T_0; MD_LREG, L_T, :BCPLRETL; Return 0 ;Mask table here to make above more readable. SPHOrM0: L_100000 OR T, TASK, :SPH22; SPHOrM1: L_40000 OR T, TASK, :SPH22; SPHOrM2: L_20000 OR T, TASK, :SPH22; SPHOrM3: L_10000 OR T, TASK, :SPH22; SPHOrM4: L_4000 OR T, TASK, :SPH22; SPHOrM5: L_2000 OR T, TASK, :SPH22; SPHOrM6: L_1000 OR T, TASK, :SPH22; SPHOrM7: L_400 OR T, TASK, :SPH22; SPHOrM10: L_200 OR T, TASK, :SPH22; SPHOrM11: L_100 OR T, TASK, :SPH22; SPHOrM12: L_40 OR T, TASK, :SPH22; SPHOrM13: L_20 OR T, TASK, :SPH22; SPHOrM14: L_10 OR T, TASK, :SPH22; SPHOrM15: L_4 OR T, TASK, :SPH22; SPHOrM16: L_2 OR T, TASK, :SPH22; SPHOrM17: L_ONE OR T, TASK, :SPH22; SPHMask0: L_ONE, TASK, :SPH2; SPHMask1: L_3 , TASK, :SPH2; SPHMask2: L_7 , TASK, :SPH2; SPHMask3: L_17 , TASK, :SPH2; SPHMask4: L_37 , TASK, :SPH2; SPHMask5: L_77 , TASK, :SPH2; SPHMask6: L_177 , TASK, :SPH2; SPHMask7: L_377 , TASK, :SPH2; SPHMask10: L_ 777 , TASK, :SPH2; SPHMask11: L_ 1777 , TASK, :SPH2; SPHMask12: L_ 3777 , TASK, :SPH2; SPHMask13: L_ 7777 , TASK, :SPH2; SPHMask14: L_ 17777 , TASK, :SPH2; SPHMask15: L_ 37777 , TASK, :SPH2; SPHMask16: L_ 77777 , TASK, :SPH2; SPHMask17: L_177777 , TASK, :SPH2; ;Cycle right. ; Enter at CYCLE with: ; INBIT = count of places to cycle ; T = bits ; Exit to SPH7 with ; nextW= cycled bits ; Note: nextW must be R register for shifts hCYCLE: SINK_ INBIT, BUS; L_ T, TASK, :hCYCR0; hCYCR0: nextW_ L, :SPH7; hCYCR4: nextW_L MRSH 1; hCYCY3: T_L_nextW, TASK; hCYCR3: nextW_L MRSH 1; hCYCY2: T_L_nextW, TASK; hCYCR2: nextW_L MRSH 1; hCYCY1: T_L_nextW; TASK; hCYCR1: nextW_L MRSH 1, :SPH7; hCYCL4: nextW_L MLSH 1; hCYCZ3: T_L_nextW, TASK; hCYCL3: nextW_L MLSH 1; hCYCZ2: T_L_nextW, TASK; hCYCL2: nextW_L MLSH 1; hCYCZ1: T_L_nextW, TASK; hCYCL1: nextW_L MLSH 1, :SPH7; hCYCL8: nextW_ L LCY 8, :SPH7; hCYCL7: nextW_ L LCY 8, :hCYCY1; hCYCL6: nextW_ L LCY 8, :hCYCY2; hCYCL5: nextW_ L LCY 8, :hCYCY3; hCYCR7: nextW_ L LCY 8, :hCYCZ1; hCYCR6: nextW_ L LCY 8, :hCYCZ2; hCYCR5: nextW_ L LCY 8, :hCYCZ3; ;---------------------------------------------------------------------- ; DoubleAdd (returns integer part) ;---------------------------------------------------------------------- !1,2,DPADNoCarry,DPADCarry; TRP3: MAR_AC0; destination AC NOP; L_MD; MAR_AC0+1; sample_L; high order of first term L_MD; MAR_AC1; TEMP_L; low order of first term L_MD; MAR_AC1+1; AC1_L; high order of second term L_MD; MAR_AC0+1; T_TEMP; L_LREG+T; LREG has low order of second term MD_LREG; T_sample,ALUCY; MAR_AC0,:DPADNoCarry; DPADCarry: L_AC1+T+1,:DPADStore; DPADNoCarry: L_AC1+T,:DPADStore; DPADStore: MD_LREG,:BCPLRETL; ;---------------------------------------------------------------------- ; DoubleSub ;---------------------------------------------------------------------- !1,2,DPSBNoCarry,DPSBCarry; TRP4: MAR_AC0; destination AC NOP; L_MD; MAR_AC0+1; sample_L; sample has high order word 1 L_MD; MAR_AC1; TEMP_L; TEMP has low order word 1 T_ALLONES; L_MD XOR T; store complement of AC1 MAR_AC1+1; AC1_L; AC1 has (NOT high order word 1) L_MD; MAR_AC0+1; T_LREG; L_TEMP-T; MD_LREG; store low order=lowOrder1-lowOrder2 T_sample,ALUCY; MAR_AC0,:DPSBNoCarry; DPSBCarry: L_AC1+T+1,:DPSBStore; DPSBNoCarry: L_AC1+T,:DPSBStore; DPSBStore: MD_LREG,:BCPLRETL; ;---------------------------------------------------------------------- ; DoubleShr ;---------------------------------------------------------------------- !1,2,DSHRpos,DSHRneg; TRP5: MAR_AC0; NOP; L_MD; MAR_AC0+1,SH<0; AC1_L,T_0,:DSHRpos; !1,2,DSHRpos,DSHRneg; DSHRneg: T_ALLONES; DSHRpos: TEMP_L MRSH 1; L_MD; MAR_AC0; T_AC1; unshifted high order (for carry) AC1_L MRSH 1; MD_TEMP; shifted high order MAR_AC0+1; L_TEMP; return integer part MD_AC1,:BCPLRETL;(635)\7637b27B3387b22B ; ;Read(adr) returns contents of bank1 adr TRP6: XMAR_AC0; NOP; L_MD,:BCPLRETL; ;Write(adr,val) writes val into bank1 adr TRP7: XMAR_AC0; NOP; MD_AC1,:BCPLRET; ;BLT from bank1 to bank1 MoveBlock(dest1,src1,nwords) !1,2,more10,done10; TRP10: T_3; MAR_AC2+T; NOP; L_MD; loop10: range_L,SH=0; XMAR_AC1,:more10; !1,2,more10,done10; more10: L_AC1+1; AC1_L; L_MD; TEMP_L; XMAR_AC0; L_AC0+1; AC0_L,TASK; MD_TEMP; L_range-1,:loop10; done10: NOP,:BCPLRET; ;BLT from bank0 to bank1 MoveBlock(dest1,src0,nwords) !1,2,more11,done11; TRP11: T_3; MAR_AC2+T; NOP; L_MD; loop11: range_L,SH=0; MAR_AC1,:more11; !1,2,more11,done11; more11: L_AC1+1; AC1_L; L_MD; TEMP_L; XMAR_AC0; L_AC0+1; AC0_L,TASK; MD_TEMP; L_range-1,:loop11; done11: NOP,:BCPLRET; ; ;******************************************************************** $FOO $R41 ;TestExit -- store various values in low core, and exit ;TESTEXIT: MAR_20000; ; NOP, TASK; ; MD_ LREG; ; MAR_L_20000+1; ; FOO_L,TASK; ; MD_ ShiftCnt; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ MASK; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ nS; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ Fw; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ Fadr; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ Badr; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ FCNT; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ WLEFT; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ W1; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ W2; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ nextW; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ Badr0; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ BCOUNT; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ WORDIN; ; MAR_L_FOO+1; ; FOO_L,TASK; ; MD_ PC; ; :BCPLRET; ; (1270)