{
File name TextBlt.mc
Description: Mesa TextBlt op-code
Last edited by JAC 17-Aug-87 10:49:34: get notInFont exit in correct cycle
Last edited by JGS 7-Jan-85 17:33:08: New font format, long resolve buffer. 
Last edited by JPM 4-Oct-84 11:21:26: Change TextBlt to @TextBlt for consistency. 
Last edited by DEG 1-Sep-84 19:52:38: Add copyright notice. 
Last edited by AXD 14-Nov-83 15:43:44: undo previous change. 
Last edited by AXD 16-Aug-83 14:03:25: RRot1 uPMask2 due to new PSB format. 
Last edited by JXF February 12, 1982  12:39 PM: Nothing on the Xbus when calling CycleMask; Set L2 ← sd.spec for call to SrcMapSpec. 
Last edited by JXF February 10, 1982  2:31 AM: fix exit bug. 
Last edited by JXF January 7, 1982  1:02 PM: Change to new FontBits format. 
Last edited by JGS October 5, 1981  3:51 PM: Added JXF's fixes. 
Last edited by JGS  8-Sep-81  7:49:04: New Instruction Set. 
Last edited by JXF August 20, 1981  2:20 PM: Margin is a CARDINAL; Update MicaPos after call to BitBlt in case of page fault. 
Last edited by JXF August 20, 1981  2:20 PM: Fix for new assembler. 
Last edited by JXF: July 21, 1981  10:50 AM: Test for Resolve before testing for Stop char. 
Last edited by JXF: July 7, 1981  11:06 AM: General rewrite to make it small and wonderful. 
Last edited by JXF: March 17, 1981  4:09 PM: Fix label bug: change tbFunction to tbFunction. Put one on XBus when calling CycleMask. Return with uStack6 in TOS.
Last edited by JXF: March 16, 1981  2:14 PM: Bug fix: save MicaWidth instead of MicaPos at TestMargin. Change to call TextBltToBitBltEntry instead of LSEPNormEntry.
Last edited by JXF: March 15, 1981  5:35 PM: Move definitions from Dandelion into TextBlt.
Last edited by JXF: February 17, 1981  2:55 PM: Change to check for margin before function.
Last edited by JXF: February 11, 1981  11:04 AM: use symbol to call SavebbRegs.
Author: JXF     
Created: December, 1980
}

{ 	Copyright (C) 1980, 1981, 1982, 1983, 1984, 1985 by Xerox Corporation.  All rights reserved.}

{REGISTER USAGE:


Number	Name

0	VS	holds the Virtual Address when calling SrcMapSpec in BitBlt.
	TOS	used by CycleMask to return cycled result.
1	T	temporary used by CycleMask.
	VD	temporary used by DstVAMod subroutine
2	TT	temporary
		Used to hold Index parameter
3	L	temporary
		Used to hold Last parameter.
	TempBpl	used to hold BitPos when calling DstVAMod subroutine
4	G	temporary
	SrcA	Used by SrcMapSpec to return real address
5	PC	Used by ExtractByte to return value
6	TempB	temporary used by DstVAMod subroutine
	Rx	used to hold character MicaPos
}

{SUBROUTINES }
{*****************************************************************************
	Subroutine FetchVS
Fetch word pointed to by Virtual Address in VS and rhVS, offset by T.
Timing: 5 clicks
Called from cycle 3, returns to cycle 1
Returns thru L0

	Input:
VS	(TOS) virtual address
rhVS	(rhMDS) virtual address (high order)
T	offset of virtual address

	Output:
T	word pointed to by Virtual Address
SrcA	(G) real address page and word
rhSrcA	(rhG) real address rh
USrcValoSav
	used to save VS
Q	real page and word
rhRet	tbMap (used to call SrcMapSpec)

	Side Effects:
	UDstBit ← 0;
	UHeight ← UtbHeight, TOS ← UtbHeight
*****************************************************************************}


	MacroDef[FetchVSRet,at[#1,10,FetchVSRtn]];

	{Return values for FetchVS and ExtractByte Subroutines}
	{0 = restore.int is reserved for use at tbFaultOrInt}
	Set[FetchFlags, 1], {fetch RgFlags}
	{2 = restore.pf is reserved for use at tbFaultOrInt}
	Set[FetchPrinterWidth, 3], {fetch PrinterWidth}
	Set[StoreCoord,4], {get address of Coord[Index]}
	Set[FetchWidth, 5], {fetch width of character}
	Set[FetchChar, 6], {fetch next character}
	Set[FetchInfo, 7], {fetch raster info}
	Set[FetchEntry, 8], {fetch raster info}

FetchVS:
	VS ← VS + T, CarryBr, L2 ← sd.spec {in case of fault in SrcMapSpec},	c1;
tbFetch:	UDstBit ← 0, BRANCH[$, tbCarry],	c2;
	rhRet ← Fetch, CALL[SrcMapSpec],	c3;

	{SrcMapSpec subroutine here  for 2 Clicks,	c1-c3;}
	{On return, SrcA and rhSrcA contain real address.}

SrcMapSpecRet[Fetch]
	MAR ← [rhSrcA, SrcA + 0],	c1;
	TOS ← UtbHeight, L0Disp,	c2;
	T ← MD, UHeight ← TOS, RET[FetchVSRtn],	c3;

tbCarry:	Q ← rhVS + 1 {Increment rh portion of VA}, LOOPHOLE[byteTiming],	c3;
	rhVS ← Q LRot0, GOTO[tbFetch],	c1;

{*****************************************************************************
	Subroutine ExtractByte
Extract byte from T depending on Index:
	Index even => extract left byte
	index odd => extract right byte
Timing: 2 cycles
Calling Sequence:
	...L0 ← ,...
	[] ← UtbIndex, XDisp, CALL[ExtractByte],	c*;
Returns thru L0

	Input:
T	word contains 2 bytes

	Output:
PC	word contains left byte or right byte
*****************************************************************************}

	MacroDef[ExtractByteRet,at[#1,8,ExtractByteRet]];
ExtractByte:
	TT ← T LRot8, L0Disp, BRANCH[tbEvenChar, tbOddChar,0E],	c*;

tbOddChar:
	PC ← T and 0FF, DISP3[ExtractByteRet],	c*;
tbEvenChar:
	PC ← TT and 0FF, DISP3[ExtractByteRet],	c*;

{*****************************************************************************
Subroutine GgetsBitPos
	Disp is pending for return
*****************************************************************************}

	Set[Kern,1];
	Set[Update,0];
	MacroDef[GgetsBitPosRet,at[#1,4,GgetsBitPosRet]];
GgetsBitPos:
	G ← UtbBitPos, DISP2[GgetsBitPosRet],	c*;

{*****************************************************************************
Subroutine TTgetsSTK
	Pop stack into TT and set rhType for TextBlt
	Disp on Stack pointer is pending for return
*****************************************************************************}

	MacroDef[TTgetsSTKRet,at[#1,10,TTgetsSTKRet]];
TTgetsSTK:
SavebbRegsRet[Savebb.TXTBLT]
	TT ← STK, pop, RET[TTgetsSTKRet],	c*;

{*****************************************************************************
Begin TextBlt. 
Come here from ESC on a Misc 15 opcode. 
PC points to the byte code because BitBlt counts on this in case of a page fault. 
Save R and RH registers. Move the parameters passed in the stack to other U registers.
If we need to call BitBlt, BitBlt will need to use the stack.
Input:
	stackP = 5
	uStack6 = ArgPtr => UtbArgPtr
	uStack5 = Count => UtbCount
	uStack4 = MicaPos => UtbMicaPos
	uStack3 = BitPos => UtbBitPos
	uStack2 = Index => UtbIndex
*****************************************************************************}

@TextBlt:	
at[0C,10,ESC2n]
	ULsave ← L, L2 ← Savebb.TXTBLT,	c1;
	T ← uStack6 {ArgPtr}, CALL[SavebbRegs],	c2;

	{SavebbRegs subroutine here for 2 2/3 Clicks,	c3-c1;}
	{Return to TTgetsSTK}

	{TT ← STK {Count}, pop {MicaPos: stackP ← 4},	c2;}
TTgetsSTKRet[0]
	UtbCount ← TT {Count}, Xbus ← ErrnIBnStkp, XDisp, CALL[TTgetsSTK],	c3;

	{TT ← STK {MicaPos}, pop {BitPos stackP ← 3},	c1;}
TTgetsSTKRet[0B] {1011 is one's complement of stackP = 4}
	UtbMicaPos ← TT {MicaPos}, {next line}
	Xbus ← ErrnIBnStkp, XDisp, CALL[TTgetsSTK],	c2;
	{TT ← STK {BitPos}, pop {Index: stackP ← 2},	c3;}
TTgetsSTKRet[0C] {1100 is one's complement of stackP = 3}

	UtbBitPos ← TT {BitPos}, {next line}
	Xbus ← ErrnIBnStkp, XDisp, CALL[TTgetsSTK],	c1;
	{TT ← STK {Index}, pop {next: stackP ← 1},	c2;}
TTgetsSTKRet[0D] {1101 is one's complement of stackP = 2}
	{Set L2 for SrcMapSpec subroutine in case of a page fault.}
	UtbIndex ← TT {Index}, L2 ← sd.spec,	c3;

{*****************************************************************************
Move TextBlt arguments pointed to by ArgPtr to U registers. The following loop loads U registers as follows:
	60   junk
	61   not touched
	62   saved and restored
	63   UtbFunction: arg word 0 = function
	64   UtbLast: arg word 1 = Last
	65   UtbTextLo: arg word 2 = TextLo
	66   UtbTextHi: arg word 3 = TextHi
	67   UtbFontLo: arg word 4 = FontLo
	68   UtbFontHi: arg word 5 = FontHi
	69   UtbDstLow: arg word 6 = DestLow
	6A   UtbDstHigh: arg word 7 = DestHigh
	6B   UtbDstBpl: arg word 8 = DestBpl
	6C   UtbMargin: arg word 9 = Margin
	6D   UtbSpace: arg word A = Space
	6E   UtbCoordLo: arg word B = CoordLo
	6F   UtbCoordHigh: arg word B = CoordHigh
In case of a page fault, we must be able to restore the stack and the registers. 
Set rhType to return to us in case of a page fault or interrupt.  
rhVS = MDS, so we don't need to load it.
*****************************************************************************}

	VS ← UtbArgPtr ← T {ArgPtr},	c1;
	rhType ← Type.TextBlt,	c2;
	rhRet ← MapArg, CALL[SrcMapSpec],	c3;

	{SrcMapSpec subroutine here  for 2 Clicks,	c1-c3;}
	{On return, SrcA (G) and rhSrcA contain real address of TextBltArg.}

SrcMapSpecRet[MapArg]
	L ← UtbFlags ,	c1; 
	UFlags ← L {UtbFlags -- Set up for BitBlt},	c2;
	Rx ← uPMask2 {save u62, which will be wiped out},	c3;

tbFetchArgLoop:
	MAR ← [rhSrcA,SrcA ], SrcA ← SrcA + 1, NibCarryBr,	c1;
	Ybus ← SrcA+1, AltUaddr,  BRANCH[$, tbFetchFontRecord, 2],	c2;
	tbParmBlock ← Rx, Rx ← MD, GOTO[tbFetchArgLoop],	c3;

{*****************************************************************************
Fetch FontRecord data pointed to by FontLo,,FontHi into U registers. 
NOTE: for this to work, FontRecord must be hex aligned.
The following loop loads U registers as follows:
	50   UtbHeight: FontRecord word 10 = Height
	51   UtbRasterLo: FontRecord word 0 = RasterLo
	52   UtbRasterHi: FontRecord word 1 = RasterLHi
	53   UtbSpacingWidthLo: FontRecord word 2 = SpacingWidthLo
	54   UtbSpacingWidthHi: FontRecord word 3 = SpacingWidthHi
	55   UtbPrinterWidthLo: FontRecord word 4 = PrinterWidthLo 
	56   UtbPrinterWidthHi: FontRecord word 5 = PrinterWidthHi
	57   UtbFlagsLo: FontRecord word 6 = FlagsLo
	58   UtbFlagsHi: FontRecord word 7 = FlagsHi
	59   UtbRasterInfoLo: FontRecord word 8 = RasterInfoLo
	5A   UtbRasterInfoHi: FontRecord word 9 = RasterInfoHi
	5B   not touched
	5C   not touched
	5D   not touched
	5E   not touched
	5F   not touched
*****************************************************************************}

tbFetchFontRecord:
	rhRet ← MapFont {NOTE: this instruction follows AltUaddr, so beware of
	any instruction with a U address here!},	c3;

	VS ← UtbFontLo, 	c1;
	rhVS ← UtbFontHi,	c2;
	CALL[SrcMapSpec],	c3;

	{SrcMapSpec subroutine here  for 2 Clicks,	c1-c3;}
	{On return SrcA and rhSrcA point to FontRecord.} 

SrcMapSpecRet[MapFont]
tbFetchFontDataLoop:
	MAR ← [rhSrcA,SrcA+0],  	c1;
	Ybus ← SrcA, SrcA ← SrcA+1, YDisp, AltUaddr, 	c2;
	UtbFontData ← PC, PC ← MD, {next line}
	BRANCH[tbFetchFontDataLoop,$,7],	c3;

	{We have just stored UtbFlagsHi, and PC = RasterInfoLo}

	MAR ← [rhSrcA,SrcA+0],  	c1;
	Rx ← UtbDstBpl, 	c2;
	UtbRasterInfoLo ← PC, PC ← MD,	c3;

	MAR ← [rhSrcA,SrcA+1],  	c1;
	UDstBpl ← Rx {Prepare for BitBlt}, CANCELBR[$,0], 	c2;
	UtbRasterInfoHi ← PC, PC ← MD,	c3;
	
	UtbHeight ← PC, GOTO[tbLoop],		c1;

{*****************************************************************************
Begin TextBlt loop. 
We come through here for each character. 
Subtract Index of current character from index of Last character. 
If carry, then I'm done.
*****************************************************************************}

tbLoop:	L {Last} ← UtbLast,	c2;
	L ← L {Last} - TT {Index}, UtbIndex ← TT {Index}, CarryBr,	c3;

	Xbus ← UtbFunction {test for resolve}, XDisp, BRANCH[tbFinished,$],	c1;
	Q ← UtbCoordLo, BRANCH[tbFetchChar, tbResolve, 1],	c2;

{*****************************************************************************
Come here if function is Resolve. 
*****************************************************************************}
tbResolve:
	rhVD ← UtbCoordHigh,	c3;
 
	VD ← Q + TT, CarryBr,	c1;
	L ← UtbBitPos,	BRANCH[tbR, $],	c2;
	Q ← rhVD + 1, LOOPHOLE[byteTiming],	c3;
	
	rhVD ← Q LRot0,	c1;
	Noop,	c2;
tbR:	rhRet ← argMap, CALL[DstMapSpec],	c3;

	{DstMapSpec subroutine here  for 2 Clicks,	c1-c3;}
	{On return, DstA and rhDstA contain real address.}

	MAR ← [rhDstA, DstA + 0],	c1, at[argMap,4,DstMapRet];
	MDR ← L,	c2;
tbFetchChar:
	TT ← UtbIndex,	c3;

	{FetchText[Index]: word that contains next character.}
	VS ← UtbTextLo, L0 ← FetchChar,	c1;
	rhVS ← UtbTextHi,	c2;
	T {offset} ← RShift1 TT {Index}, CALL[FetchVS],	c3;

	{FetchVS subroutine here for 5 clicks,	c1-c3}
	{On return, T contains word that contains next character.}

FetchVSRet[FetchChar]
	Xbus ← UtbIndex, XDisp, CALL[ExtractByte],	c1;

	{ExtractByte subroutine here	c2-c3}
	{On return, PC contains next character}

ExtractByteRet[FetchChar]
	Rx ← UtbMicaPos {Prepare for tbTestMargin},	c1;

tbFetchFlags:   {Fetch RgFlags[char/8]. }
	VS ← UtbFlagsLo, L0 ← FetchFlags,	c2;
	rhVS ← UtbFlagsHi,	c3;

	T ← LShift1 (PC {next char} and 0F8) {mask off low 3 bits},	c1;
	T ← T LRot12 {Char/8},	c2;
	{Prepare L for CycleMask below.}
	L ← LShift1 (PC {next char} and 7), CALL[FetchVS],	c3;

	{FetchVS subroutine here for 5 clicks,	c1-c3}

{*****************************************************************************
On return, T contains RgFlags[char/8]. Call CycleMask to right justify RgFlags. 
We rotate RgFlags 2*(n+1), where n is the low 3 bits of Char. If n = 7, our Disp4 will cause a zero rotation. 
Calling sequence to CycleMask:
	T = data to be rotated (RgFlags)
	TT = pre-rotated version of T
	We must set INIA.11.
*****************************************************************************}

FetchVSRet[FetchFlags]
	Ybus ← L {LShift1 (nextChar and 7)} + 2, YDisp, L2 ← maskRet.flags,	c1;
	TT ← LRot1 T {RgFlags}, DISP4[CycleMask],	c2;

	{CycleMask subroutine here for 1 click,	c3-c2}
	{On return, TOS contains RgFlags right justified. }

tbTestStop:    {Dispatch on low order bit to test for Stop character.}	at[maskRet.flags,10,MaskRet]
	UtbRgFlags ← TOS, L0 ← FetchPrinterWidth, YDisp,	c3;

	L {Margin} ← UtbMargin, BRANCH[$,tbStopChar,0E],	c1;
	VS ← UtbPrinterWidthLo,	c2;
	rhVS ← UtbPrinterWidthHi,	c3;

	VS ← VS + PC, CarryBr, L2 ← sd.spec, CALL[tbFetch],	c1;
	{FetchVS subroutine here for 4-2/3 clicks,	c2-c3}
	{On return, T contains word that contains printer width of character. }

      {
      IF printerWidth = CARDINAL.LAST THEN GOTO NotInFont;
      IF micaPos + printerWidth > ptr.margin THEN GOTO Margin;
      }
      
FetchVSRet[FetchPrinterWidth]
	Q ← 0-T-1, ZeroBr,	c1;
	Rx ← Rx - Q - 1 , BRANCH[$, tbNotInFont], 	c2;
	[] ← L - Rx, CarryBr, 	c3;

tbTestMargin:
	T ← RShift1 PC, BRANCH[tbMargin,$],	c1;
	VS ← UtbSpacingWidthLo, L0 ← FetchWidth,	c2;
	rhVS ← UtbSpacingWidthHi, CALL[FetchVS],	c3;

	{FetchVS subroutine here for 5 clicks,	c2-c3}
	{On return, T contains word that contains width of character. }

FetchVSRet[FetchWidth]
	Ybus ← Q ← PC {nextChar}, YDisp, CALL[ExtractByte],	c1;
	{ExtractByte subroutine here,	c2-c3}
	{On return, PC contains width of Char, Q contains char}

ExtractByteRet[FetchWidth]
	UtbWidth ← PC,		c1;
	UtbNewMicaPos ← Rx	c2;
	L {Src} ← UtbRasterLo,	c3;

	Xbus ← UtbFunction, T ← Q, XDisp, L0 ← FetchEntry,	c1;
	VS ← UtbRasterInfoLo, DISP2[tbFunction],	c2;

{*****************************************************************************
Come here if function is Display. 
	L2 = OffsetPlus256
	PC = UtbWidth = width of character
	T = character.

Set up parameters for BitBlt:
	L2 = sd.spec
	UDstBpl contains dstBpl 
	UWidth contains width of Char
	UFlags contains flags
	USrcBpl contains srcBpl (width of character)
	UHeight contains height (from FontRecord)
	UDstValo contains low order of dest BitAddress
	UDstBit contains bit portion of dest BitAddress
	USrcValo contains low order of source BitAddress
	USrcBit contains bit portion of source BitAddress (Zero)
	UrhVS and rhVS contain high order of source BitAddress
	UrhVD and rhVD contain high order of dest BitAddress
*****************************************************************************}

tbDisplay:
at[0,4,tbFunction]
	rhVS ← UtbRasterInfoHi, CALL[FetchVS],	c3;
	
	{FetchVS subroutine here for 5 clicks,	c1-c3}

{*****************************************************************************
On return, T contains RasterInfo[Char]. 
This contains the left and right kern bits and the offset of the character in the rasters. 
*****************************************************************************}
FetchVSRet[FetchEntry]
	{Calculate source address for BitBlt. Extract offset to FontTable  from low 14 bits of first word of CharEntry. 
	Calculate address of entry for this Char in FontTable: FontChar + offset.}

	Q ← UtbDstLo,	c1;
	UDstVALo ← Q,	c2;
	TT {offset} ← T {CharEntry} and u3FFF, {nextLine},	c3;

	TOS {SrcHi} ← rhVS ← UtbRasterHi,	c1;
	L {Src} ← L {Src} + TT {offset}, CarryBr,	c2;
tbTestFontCarry:
	USrcVALo ← L {Src}, BRANCH[tbNoFontCarry, tbFontCarry],	c3;
tbFontCarry:
	TOS {SrcHi} ← TOS + 1,	c1;
	rhVS {SrcHi} ← TOS LRot0, GOTO[tbTestFontCarry],	c2;

tbNoFontCarry:
	UrhVS ← TOS {SrcHi}, TOS ← 0,	c1;
	USrcBit ← TOS {0}, TOS ← {8000} RShift1 TOS, SE ← 1,	c2;

	{Extract left kern and right kern bits.}
	L {LKern} ← LRot1 T {Left kern in low order bit},	c3;

	TOS {RKern} ← (L LRot1) and TOS {8000},	c1;
	L {LKern} ← L {LKern} and 1 ,	c2;

	{Calculate Width as Width + left kern + right kern.}
	PC {Width} ← PC {Width}  + L {LKern},	c3;

	TOS {Width} ← PC {Width} + TOS {RKern}, L0 ← Kern,	c1;
	USrcBpl ← TOS {Width}, 	c2;
	UWidth ← TOS {Width}, L0Disp, CALL[GgetsBitPos],	c3;

	{Calculate bitPos as bitPos - left kern.}
	{G ← UtbBitPos,	c1;}
GgetsBitPosRet[Kern]
	L {BitPos} ← G {UtbBitPos} - L {LKern}, rhWho ← Dest, 	c2;

{*****************************************************************************

Calculate Dst address for BitBlt. Call DstVAMod to add BitPos to Dst address. Parameters must be set up as follows:
	rhWho	caller
	TempBpl	increment for the destination address (L)
	UDstValo	virtual destination page and word,
		set from UtbDstLo by FetchVA
	UDstBit	virtual destination bit (set to 0)
	UrhVD	virtual destination rh
*****************************************************************************}

	T ← UtbDstHi, rhVD ← UtbDstHi,	c3;

tbCalculateDst:
	UrhVD ← T, CALL[DstVAMod],	c1;

	{DstVAMod subroutine here for 4 clicks,	c2 - c1}
	{On return, uDstValo has been updated by the number of words in BitPos. 
	TempB and UDstBit contain BitPos. 
	We must mask off the high order bits of BitPos from UDstBit.}

DstVAModRet[Dest]
	TempB {BitPos} ← TempB and 0F, L2 ← sd.spec,	c2;
	UDstBit ← TempB, CALL[TextBltToBitBltEntry],	c3;

	{BitBlt runs here for lots of clicks.,	c1 - c2}

{*****************************************************************************
Return here from BitBlt. L0 = restore.term.
Increment BitPos.
*****************************************************************************}
tbNextChar:
at[6,8,LSEPReturn]
	T ← UtbWidth {width}, {0 disp}, CALL[GgetsBitPos],	c3;

	{G ← UtbBitPos GOTO[tbNextCharx],	c1;}

{*****************************************************************************
Come here if function is Resolve. 
*****************************************************************************}
at[2,4,tbFunction]
	T ← UtbWidth {width}, {0 disp}, CALL[GgetsBitPos],	c3;

	{G ← UtbBitPos GOTO[tbNextCharx],	c1;}

tbNextCharx:
GgetsBitPosRet[Update]
	G {BitPos} ← G {BitPos} + T {Width}, {next line}
	Xbus ← UtbRgFlags, XDisp, {Test for pad character (2 bit of RgFlags).}	c2;
tbTestPad:
	{Come here from tbCountPos or tbCountNotPos to delay 1 cycle.}	
	TT {Count} ← UtbCount, BRANCH[tbNoPad,tbPad,0D],	c3;

tbPad:
	T {Count} ← TT {Count} + 1,	c1;
	Xbus ← UtbFunction, XLDisp, {test low order bit: 1 if format}	c2;

	{Test for function = format. 0 => display, 1 => format, 2=> resolve.}
	UtbCount ← T {Count}, TT ← TT {count-1}, NegBr, {next line}
	BRANCH[$,tbNoPad],	c3;

	{Continue if function is not Format. 
	Increment BitPos by Space. If count <= 0, increment BitPos by one more.}

	T ← UtbSpace, BRANCH[tbCountPos, tbCountNotPos],	c1;
tbCountPos:
	G {BitPos} ← G {BitPos} + T {Space}, GOTO[tbTestPad],	c2;
tbCountNotPos:
	G {BitPos} ← G {BitPos} + T {Space} + 1, GOTO[tbTestPad],	c2;

tbNoPad:
	TT {Index} ← UtbIndex, CANCELBR[$,1],	c1;
	UtbBitPos ← G {BitPos}, TT {Index} ← TT {Index} + 1,	c2;
	L ← UtbNewMicaPos,	c3;

	UtbMicaPos ← L, GOTO[tbLoop],	c1;
	
{*****************************************************************************
Come here if function is Format.
*****************************************************************************}
tbFormat:
at[1,4,tbFunction]
	T ← UtbWidth {width}, {0 disp}, CALL[GgetsBitPos],	c3;
	{G ← UtbBitPos, GOTO[tbNextCharx],	c1;}

tbFinished:
	TOS ← 0 {normal}, CANCELBR[tbDone,3], L0 ← restore.term,	c2;
tbMargin:
	TOS ← 1 {margin}, CANCELBR[tbDone,3], L0 ← restore.term,	c2;

tbStopChar:
	TOS ← 2 {stop}, L0 ← restore.term, GOTO[tbDone],	c2;

tbNotInFont:
	TOS ← 3 {notInFont}, L0 ← restore.term, GOTO[tbWait],	c3;

{*****************************************************************************
Come here from BitBlt if we get a page fault (L0 = restore.pf) or a request for an interrupt (L0 = restore.int). 
Restore the Stack so that it will be set up when our opcode gets executed again. 
Then go to RestoreRandRHRegs subroutine, which will return to the appropriate place in BitBlt.
*****************************************************************************}
at[7,8,MoverhVToStkandRestore]

	TOS ← UtbArgPtr, 	c2;
tbWait:
	Noop, 	c*;	{c1, c3}
tbFault:
	Noop, 	c*;	{c2, c1}

{*****************************************************************************
	Subroutine RestoreStack
Timing: 3 2/3 cycles
	Input:
T	value to place in Stack6
Restore the Stack with TextBlt parameters. We do this at completion, to process an interrupt, or to process a page fault. 
We then exit to RestoreRandRHRegs, which will return to the appropriate place in BitBlt.
On completion, we must come here on c3.
On interrupt or page fault, we must come here on c2.
*****************************************************************************}
		     {fin	int}
tbDone:	
	uStack6 ← TOS, TT ← 0,  	c*; {c3	c2}
tbRestoreStack:	
	stackP ← TT {0}, T ← UtbIndex,	c*; {c1	c3}
 	uStack2 ← T,	c*; {c2	c1}
	T ←UtbBitPos, push {stackP ← 1},	c*; {c3	c2}

	uStack3 ← T, push {stackP ← 2},	c*; {c1	c3}
	T ← UtbMicaPos, push {stackP ← 3},	c*; {c2	c1}
	uStack4 ← T, push {stackP ← 4},	c*; {c3	c2}

	T ← UtbCount, push {stackP ← 5},	c*; {c1	c3}
	uStack5 ← T, GOTO[RestoreRandRHRegs],	c*; {c2	c1}

	{RestoreRandRHRegs here 2 1/3 cycles}	{c3 - c3 c2 - c2}
	{Continue at BBExit on c1 if finished (L0 = restore.term)}
	{Continue at restore.pf on c3 if page fault (L0 = restore.pf)}
	{Continue at restore.int on c3 if interrupt (L0 = restore.int)}

	{END}