:IF[WithTextBlt]; **********************************
TITLE[TextBlt];
%
Edit by HGM November 27, 1981 12:22 PM: Return to P4Tail rather than MesaBBRet.
Edit by Ed Fiala 18 September 1981: MIPend call change; use DispTable rather than At one place; eliminate MP code def.
Edit by Ed Fiala 5 May 1981: Move dispatch table defs to GlobalDefs; eliminate register def comment; add WithTextBlt conditional.
Edit by Ed Fiala 28 April 1981: IntPending instead of NWW.
Edit by Ev Neely March 16, 1981 12:43 PM Allow cross of 64k.
Edit by Ev Neely February 5, 1981 12:54 PM Margin change.
Edit by Ev Neely February 3, 1981 10:34 AM Fix and trim.
Edit by Ev Neely January 21, 1981 5:35 PM Allow for contiguous source scanlines.
Edit by Ron Joiner December 8, 1980 9:07 AM move dispatch locs
Edit by Ev Neely November 12, 1980 3:29 PM Fix bug in TxInitResolve: interlock needed for txrCoordLo.
Edit by Ev Neely October 21, 1980 12:14 PM Fix bug in TxSourceRefill: and back up of Mesa PC.
Edit by Jim Frandeen October 20, 1980 3:28 PM Check for minimal stack.
Edit by Ev Neely October 6, 1980 2:45 PM
Edit by Jim Frandeen July 15, 1980 3:32 PM
%
*TextBltArg format. This is aligned on a sixteen word boundary in the MDS.
Set[txcFunction,0];*0 => display, 1 => format, 2 => resolve.
Set[txcLast,1];*When index > last, we are done.
Set[txcTextLPtrLo,2];*Long pointer to array of BytePair.
Set[txcTextLPtrHi,3];
Set[txcFontLPtrLo,4];*Long pointer to font.
Set[txcFontLPtrHi,5];
Set[txcDestLPtrLo,6];*Long pointer to dest bit map.
Set[txcDestLPtrHi,7];
Set[txcDestBpl,10];*Destination bits per line.
Set[txcMargin,11];*Right margin in micas.
Set[txcSpace,12];*Number to add to the width of pad characters
Set[txcCoordSPtr,13];*Short Pointer to array of cardinal. Used by the Resolve function to save the bitPos value for each character.
*Function values.
MC[txcFuncDisplay,0];*0 => display.
MC[txcFuncFormat,1];*1 => Format.
MC[txcFuncResolve,2];*2 => Resolve.
*Result values.
MC[txcResultNormal,0];*0 => Normal.
MC[txcResultMargin,1];*1 => Margin.
MC[txcResultStop,2];*2 => Stop.
*Font table format.
Set[txcFontBodyLPtrLo,0];*Long pointer to FontBody.
Set[txcFontBodyLPtrHi,1];
Set[txcFlagLPtrLo,2];*Long pointer to array of BytePair containing a flag byte for each character.
Set[txcFlagLPtrHi,3];
Set[txcHeight,4];*Font height.
*Offsets to start of FontBody subtables.
MC[txcBitWidthSubtable,1000];*Offset to start of FontBody BitWidth subtable.
MC[txcLenghtBWS,200];*Lenght of BitWidth Subtable. Used in computing the starting address of the FontBody Image subtable.
*Constants for dealing with the Kern flags in txrSrcImageWO.
Set[txcLeftKernField,0];*Left kern flag is in bit 0.
Set[txcRightKernField,1];*Right kern flag is in bit 1.
MC[txcLeftKern,100000];
MC[txcRightKern,40000];
MC[txcKernMask,140000];
*Flag constants.
Set[txcPadField,0];*Pad flag is in bit 0.
MC[txcPad,100000];*Identifies character as a pad character.
MC[txcStop,40000];*Identifies character as a Stop character.
* DISPATCH VALUES FOR BBFA:
Set[ItemRefill,3];
Set[SourceDestRefill,4];
Set[SourceRefill,5];
Set[DestRefill,6];
Set[NoRefill,7];
%
REGISTER USAGE:
ArgLo(Hi)This base register pair points to the TextBltArg table. This is initialized from ArgSPtr (below) and MDShi.
ArgSPtrShortPointer to the (hex aligned) TextBltArg table. This is Stack4.
BitPosBit position of the left edge of the next character. This is Stack1.
BitWidthBit width of current character from FontBody table.
CharacterThe current character.
CoordLo(Hi)his base register pair to array of cardinal. Used by the Resolve function to save the bitPos value for each character. This is initialized from TextBltArg table and MdsHi.
CountThe first Count characters encountered get arg.space+1 added to their widths. This is Stack3.
DestBitOffsetThis is the offset in bits to the current destination scanline from the current value of DestLo(Hi).
DestBplContains destination bits per line. This is initialized from the TextBltArg table. After each item, we add DestBpl to DestBitOffset.
DestBufThis is a quad register buffer that contains the current four words of destination data during Display function transfers.
DestQWOThe word offset to current Dest quadword from DestLo(Hi). Initialized from DestBitOffset for each scanline; it is incremented by 4 each time another DestBuf is fetched.
DestLo(Hi)This base register pair points to the destination bitmap. It is initialized from the TextBltArg table. During scanline transfers it is modified to point to the first quadword of the current scanline. It is restored after the bits are transfered.
FlagLo(Hi)Base register pair points to a byte table of flags. This pointer is initialized from the Font table. The table contains - for each character - the Pad and Stop flags.
FlagContains the Pad and Stop flags from the table of flags..
FontBodyLo(Hi)Base register pair points to FontBody table. This pointer is initialized from the Font table. For the Display function, during the actual transfer of bits, it is modified to point to the word containing the current scan line. It is restored after the bits are transfered.
FontLo(Hi)Base register pair points to Font table. This pointer is initialized from TextBltArg table. The Font table consists of two long pointers (one to the FontBody and one to a byte table of Flags) and the font height.
FunctionContains function loaded from TextBltArg table.
HeightIt is loaded from Font table for each character(because we don’t have enough registers to do it only once). It is used to specify the number of scan lines to be processed. It is decremented by one each time we go through ItemRefill. When we get to zero, we are done.
IndexIndex of next character of text. This is Stack0.
LastContains index of last text character. This is initialized from TextBltArg table.
MarginContains the right margin in micas. This is initialized from TextBltArg table.
MicaPosMica position of the left edge of the next character. This is Stack2.
MicaWidthMica width of current character from FontBody table.
NegItemWidthThe negative of bit width adjusted for kerning. The negative of actual source scanline width.
SpaceNumber to add to the width of pad characters. This is initialized from TextBltArg table.
SrcBitOffsetThe bit offset to the first bit of the current souce scanline from the current value of FontBodyLO(Hi).
SrcBufThis is a quad register buffer that contains the current four words of source data during Display function transfers.
SrcImageWOThe first word of an even-odd pair which is loaded from doubleWord subtable in the FondBody. When loaded from FontBody this word contains two kern flags and a 14D bit field providing the word offset from the beginning of the font’s scanImage subtable to the current characters first scanline.
SrcQWOThe word offset to current source quadword from FontBodyLO(Hi). Initialized from SrcBitOffset for each scanline; it is incremented by 4 each time another SrcBuf is fetched.
TextLo(Hi)Base register pair points to array of BytePair to be processed. This is initialized from TextBltArg table.
%
OnPage[TxP1];
TextBlt:
%
Start here from MesaX. We also come here to resume after an interrupt or a page fault. Resuming after an interrupt does not require special handling because we constrain interrupts to character boundaries. Resuming after a page fault does not require special handling because we don’t update the contents of stack registers untill after all actions that might trigger a page fault have occurred.
On entry:
Stack0 is txrIndex:Index of next character of text.
Stack1 is txrBitPos:Bit position of the left edge of the next character.
Stack2 is txrMicaPos:Mica position of the left edge of the next character.
Stack3 is txrCount:The first Count characters encountered get arg.space+1 added to their widths.
Stack4 is txrArgSPtr:Short Pointer to the (hex aligned) TextBltArg table.
txrArgLo(the even Base Register for the TextBltArg table) has been set to txrArgSPtr.
%
*Test to be sure there are only 5 words on the stack.
T ← 372C;*T ← complement of 5
LU ← (nStkP) XOR T;*Check for minimal stack.
T ← MDShi, GoTo[TxStackOK,ALU=0];*IF stack is OK
TxStackError:
LoadPageExternal[FaultPage];
GoToExternal[StackErrorLoc];
TxStackOK:
*Establish txrArgHi for base register accessing of the TextBlt argument table.
txrArgHi ← T;
T ← txrIndex;*Wait for write of txrArgHi. Avoids Gotcha8.
*Load txrFunction, txrLast and txrTextLo(Hi) from the argument table.
PFetch4[txrArgLo,txrFunction,txcFunction],
Call[TxTask];*Time available and allows write of T which avoids a Gotcha11 below.
*Load txrFontLo(Hi) from the argument table.
PFetch2[txrArgLo,txrFontLo,txcFontLPtrLo];
*Check for nothing to do: Index > Last.
LU ← (txrLast)-T;
*Load txrSpace from the argument table.
PFetch1[txrArgLo,txrSpace,txcSpace],
GOTO[TxNothingToDo,ALU<0];*Go if Index > Last.
*Convert txrFontHi to base register format.
T ← (RHMask[txrFontHi]);
txrFontHi ← (LSH[txrFontHi,10]) + T + 1;*Note: Something must be between this insturction and the following PFetch4 to avoid gotcha #11.
*Convert txrTextHi to base register format.
T ← (RHMask[txrTextHi]);
txrTextHi ← (LSH[txrTextHi,10]) + T + 1;
*Load txrFontBodyLo(Hi) and txrFlagLo(Hi) from the Font table.
PFetch4[txrFontLo,txrFontBodyLo,txcFontBodyLPtrLo],
Call[TxTask];*Time available while awaiting load of txrFontBodyHi.
*Convert txrFontBodyHi to base register format.
T ← (RHMask[txrFontBodyHi]);
txrFontBodyHi ← (LSH[txrFontBodyHi,10]) + T + 1;
*Load txrDestBpl(bits per line) and txrMargin from the argument table.
PFetch2[txrArgLo,txrDestBpl,txcDestBpl];
*Convert txrFlagHi to base register format.
T ← (RHMask[txrFlagHi]);
*Function specific initialization.
TxFuncDispInit:
DISPATCH[txrFunction,16,2];
txrFlagHi ← (LSH[txrFlagHi,10]) + T + 1,
DISP[.+1];
PFetch2[txrArgLo,txrDestLo,txcDestLPtrLo],
GoTo[TxInitDisplay],AT[TxInitFuncDisp,txcFuncDisplay!];
T ← RSH[txrIndex,1],*Word index into character string.
GoTo[TxGetCharacter1],AT[TxInitFuncDisp,txcFuncFormat!];
PFetch1[txrArgLo,txrCoordLo,txcCoordSPtr],
GoTo[TxInitResolve],AT[TxInitFuncDisp,txcFuncResolve!];
TxInitDisplay:
*Come here with PFetch2 of txcDestLPtrLo(Hi) in progress. There’s no way to merge tasking with another instruction at this point so ...
Task;
*Convert txrDestHi to base register format.
T ← (RHMask[txrDestHi]);
txrDestHi ← (LSH[txrDestHi,10]) + T + 1,
GoTo[TxGetCharacter];
TxInitResolve:
*Come here with PFetch1 of txcCoordSPtr (a short pointer) in progress.
*Establish base register format.
T ← MDShi;
txrCoordHi ← T;
txrCoordLo ← (txrCoordLo);*Interlock to avoid gotcha #27.
T ← (txrIndex),
Goto[TxStoreCoord];
TxCharacterLoop:
DISPATCH[txrFunction,16,2];
TxCharacterLoop1:
T ← (txrIndex),*Used in Resolve path.
DISP[.+1];
PFetch4[txrFontLo,txrFontBodyLo,txcFontBodyLPtrLo],*Load txrFontBodyLo(Hi) and txrFlagLo(Hi).
GoTo[TxRestoreRegs],AT[TxLoopFuncDisp,txcFuncDisplay!];
T ← RSH[txrIndex,1],*Word index into character string.
GoTo[TxGetCharacter1],AT[TxLoopFuncDisp,txcFuncFormat!];
TxStoreCoord:
PStore1[txrCoordLo,txrBitPos],*Store txrBitPos in table pointed at by txrCoordLo as indexed by txrIndex.
GoTo[TxGetCharacter],AT[TxLoopFuncDisp,txcFuncResolve!];
TxRestoreRegs:
*Restore the Registers "borrowed" during Display transfer. Only needed when there is another character to be processed.
*Come here with the load of txrFontBodyLo(Hi) and txrFlagLo(Hi) in progress.
*Load txrDestLo.
PFetch1[txrArgLo,txrDestLo,txcDestLPtrLo], Task;
*Convert txrFontBodyHi to base register format.
T ← (RHMask[txrFontBodyHi]);
txrFontBodyHi ← (LSH[txrFontBodyHi,10]) + T + 1;
*Convert txrFlagHi to base register format.
T ← (RHMask[txrFlagHi]);
txrFlagHi ← (LSH[txrFlagHi,10]) + T + 1;
TxGetCharacter:
*Get word containing character.
T ← RSH[txrIndex,1];*Word index into character string.
TxGetCharacter1:
PFetch1[txrTextLo,txrCharacter],*Word containing character.
CALL[TxTask];*Will have to wait for txrCharacter to be loaded anyway.
*Extract character.
T ← (txrIndex),
Skip[R Odd];
txrCharacter ← RSH[txrCharacter,10],Skip;
txrCharacter ← RHMASK[txrCharacter];
TxGetFontInfo:
*Load txrFlag from the table of flags packed 8 pairs(Pad and Stop) per word.
T ← RSH[txrCharacter,3];*Word index into table of flags.
PFetch1[txrFlagLo,txrFlag],*txrFlag = word containing 8 flag pairs.
Call[TxTask];
*Load txrBitWidth from a byte table of BitWidths and left justify the current character’s flag pair.
T ← txcBitWidthSubtable;
T ← (RSH[txrCharacter,1]) + T,*Word index into byte table of bitWidths.
Skip[R Even];*Begin left justify of flag pair.
txrFlag ← LSH[txrFlag,2];
DISPATCH[txrCharacter,15,2];
PFetch1[txrFontBodyLo,txrBitWidth],*txrBitWidth = word containing two bitWidth bytes.
DISP[.+1];
GoTo[TxTestStop], DispTable[4];
txrFlag ← LSH[txrFlag,4], GoTo[TxTestStop];
txrFlag ← LSH[txrFlag,10], GoTo[TxTestStop];
txrFlag ← LSH[txrFlag,14], GoTo[TxTestStop];
TxTestStop:
* Test for stop-character termination.
LU ← (txrFlag) AND (txcStop);
*Load txrSrcImageWO and txrMicaWidth from the dbl word portion of FontBody table. The word loaded into txrSrcImageWO contains a pointer to the character "image bits" and two "kern" flags.
T ← LSH[txrCharacter,1],*Use character as index into Dblword portion of Font.
Goto[TxDoneStop,ALU#0];*Done if stop char.
PFetch2[txrFontBodyLo,txrSrcImageWO];
TxTestMargin:
*Test for margin termination (i.e. if MicaPos + MicaWidth > Margin).
T ← (txrMicaPos);
T ← (txrMicaWidth)+T, CALL[TxTask];
LU ← (txrMargin) - T;
T ← (txrSrcImageWO) AND NOT (txcKernMask),*Used in display path.
Goto[TxDoneMargin,ALU<0];*Quit if margin will be exceeded.
*Get BitWidth from even or odd byte.
LU ← (txrCharacter),
Skip[R Odd];*Skip if character odd
txrBitWidth ← RSH[txrBitWidth,10];
DISPATCH[txrFunction,16,2];
txrBitWidth ← RHMASK[txrBitWidth],
DISP[.+1];
*Function specific character processing.
txrSrcBitOffset ← T,*txrSrcBitOffset used as a temporary
GoTo[TxDisplayChar], AT[TxCharFuncDisp,txcFuncDisplay!];
LU ← (txrFlag),*Bit0 is Pad Flag.
DblGoTo[TxIncrCount,TxUpdate,R<0], AT[TxCharFuncDisp,txcFuncFormat!];
T ← (txrBitWidth),
GoTo[TxTestPad], AT[TxCharFuncDisp,txcFuncResolve!];
TxDisplayChar:
*Set txrFontBodyLo(Hi) to address the word containing the first source scanline of the current character. It will be restored at TxRestoreRegisters. txrSrcBitOffset is used as a temporary because it will soon be set to a new value. Came here with txrSrcBitOffset = (txrSrcImageWO) AND NOT (txcKernMask).
txrSrcBitOffset ← (txrSrcBitOffset) + (txcBitWidthSubtable),
Task;*Let high priority tasks run.
T ← (txrSrcBitOffset) + (txcLenghtBWS);
txrFontBodyLo ← (txrFontBodyLo) + T;
T ← 60C, Skip[No Carry];*Check 64k boundary cross.
txrFontBodyHi ← (txrFontBodyHi) + (400C) + 1;
*Set txrSrcBitOffset to the bit offset within the source quadword. Come here with T = 60C.
T ← (LSH[txrFontBodyLo,4]) AND T;*16 times the sub quadword portion of txrFontBodyLo.
txrSrcBitOffset ← T;
*Set txrFontBodyLo to the source quadword address.
txrFontBodyLo ← (txrFontBodyLo) AND NOT (3C);
*Set DestBitOffset to the bit offset from the beginning of the quadword addressed by txrDestLo to the first destination scanline for the current character. txrDestLo will be modified during the actual transfer and restored at TxRestoreRegisters.
T ← 60C;
T ← (LSH[txrDestLo,4]) AND T;*16 times the sub quadword portion of txrDestLo.
T ← (txrBitPos) + T;
txrDestBitOffset ← T;
*Now that txrDestLo’s sub quadword portion is represented in txrDestBitOffset make txrDestLo a quadword address.
txrDestLo ← (txrDestLo) AND NOT (3C);
*Load txrHeight from the Font table.
PFetch1[txrFontLo,txrHeight,txcHeight],
Task;*Let high priority tasks run.
*Adjust txrDestBitOffset for left kerning. Make txrNegItemWidth the negative of txrBitWidth adjusted for left & right kerning.
T ← (LDF[txrSrcImageWO,txcLeftKernField,1]);
txrDestBitOffset ← (txrDestBitOffset) - T;
T ← (LDF[txrSrcImageWO,txcRightKernField,1]) + T;
T ← (txrBitWidth) + T;
txrNegItemWidth ← (zero) - T,
GoTo[TxWidth0,ALU=0];*Zero width character
*Load Saluf for a "Code 2: Source OR Dest Type 0" block transfer.
T←204C;
Saluf←T,
GoTo[TxItemSetup];
TxItemRefill:
*Come here when the current item is exhausted. Store the last dest quadword. T already set to txrDestQWO.
PStore4[txrDestLo,txrDestBuf];
*Check for last item (scanline) this character.
txrHeight ← (txrHeight) - 1;
*Set txrDestBitOffset to the bit offset from the beginning of the first quadword of the just-completed-destination-scanline to the first bit of the next scanline. txrDestBitOffset’s old high order bits have already been incorporated into txrDestLo. The new high order bits produced here will be incorporated into txrDestLo below.
T ← txrDestBpl,
GoTo[TxCharDispDone,ALU = 0];*Display of this character is done if all scanlines used.
txrDestBitOffset ← (LDF[txrDestBitOffset,12,6]) + T;
*Add the source-bits-per-item to txrSrcBitOffset making it the bit offset from the beginning of the first quadword of the first-source-scanline to the first bit of the next scanline.
T ← (txrNegItemWidth);
txrSrcBitOffset ← (txrSrcBitOffset) - T;* -- = +
TxItemSetup:
*Set txrSrcQWO to the word offset from that first quadword to the quadword containing the first bit of the current scanline. Load the source quadregister buffer.Note: At this point txrFontBodyLo is always the address of the quadword containing the first bit of the first source scanline and txrSrcBitOffset is the bit offset from the beginning of that first quadword to first bit of the current scanline.
T ← (3C),
Task;*Let high priority tasks run.
T ← (RSH[txrSrcBitOffset,4]) AND NOT T;
txrSrcQWO ← T;
PFetch4[txrFontBodyLo,txrSrcBuf];
*Load SB with the bit offset of the current souce item(scanline) within the current source quadword.
SB ← (txrSrcBitOffset);*SB set to the 6 low order bits of txrSrcBitOffset.
*Load DB with the bit offset of the current destination item(scanline) within the current destination quadword.
DB ← (txrDestBitOffset);*DB set to the 6 low order bits of txrSrcBitOffset.
*Load MNBR with the negative item (scanline) width.
MNBR ← (txrNegItemWidth);
*Set txrDestLo(Hi) to address the quadword containing the first bit of the current destination scanline.
T ← (3C);
T ← (RSH[txrDestBitOffset,4]) AND NOT T;
txrDestLo ← (txrDestLo) + T;
Skip[No Carry];*Check 64k boundary cross.
txrDestHi ← (txrDestHi) + (400C) + 1;
*Initialize txrDestQWO and set T for Dest fetch.
T ← txrDestQWO ← (0C),*Initialize txrDestQWO and set T for Dest fetch.
GoTo[TxInnerLoopType0];
TxStartInnerLoop:
BBFBX,
RETURN;
TxInnerLoopType0:
*This is the inner loop for Source OR Dest.
PFetch4[txrDestLo,txrDestBuf],*Load destination quadregister buffer.
Call[TxStartInnerLoop];
%The following is the first instruction of the inner loop. The Source Mask is used to mask the source word after it has been aligned with the destination. This instruction does four operations:
(1) The T input on the right side is disabled by special logic. Instead, H2 input is loaded in bit positions not covered by the Source Mask. If MA=1, these bits are filled with ones; if MA=0, these bit positions are filled with zeroes.
(2) The word placed in T will contain the source bits correctly aligned with the destination, filled with ones if MA=1, or with zeroes if MA=0.
(3) APC is set with a dispatch value for loop control.
(4) SB, DB, and MNBR are updated by the number of bits to be transferred by this iteration.
%
TxInnerLoopType0A:
T ← BBFA[SB[txrSrcBuf]] OR T;
%The following is the second instruction of the inner loop. This instruction does three operations:
(1) It combines the destination bits with the source bits in T depending on the operation previously loaded into SalufOp.
(2) It updates SBX from SB, DBX from DB, and it calculates MWX for the next iteration.
(3) It dispatches to the next instruction depending on the value loaded into APC by the previous BBFA instruction:
ItemRefill if MNBR is about to become zero.
SourcDestRefill if SB and DB are exhausted
SourceRefill if SB is exhausted
DestRefill if DB is exhausted
Continue if another loop can be performed
%
TxInnerLoopType0B:
DB[txrDestBuf] ← BBFBX[DB[txrDestBuf]] SalufOp T,
Disp[.+1];*See next page
T ← txrDestQWO,
GoTo[TxItemRefill],AT[BBFAType0Disp,ItemRefill]; *TxItemRefill is two pages back.
TxSourceDestRefill:
T ← txrDestQWO,
AT[BBFAType0Disp,SourceDestRefill];
*Note: Doing PStore4 first allows both PFetch4s to be launched before transport for either occurs. If the PFetch4 for the source were done first, the PFetch4 for the dest could not be launched before transport for both preceding references had finished.
PStore4[txrDestLo,txrDestBuf];
T ← txrSrcQWO ← (txrSrcQWO) + (4C);
PFetch4[txrFontBodyLo,txrSrcBuf];
TxFetchDest:
T ← txrDestQWO ← (txrDestQWO) + (4C);
PFetch4[txrDestLo,txrDestBuf],
RETURN;*Return to the first instruction (BBFA) of the inner loop.
TxSourceRefill:
T ← txrSrcQWO ← (txrSrcQWO) + (4C),
AT[BBFAType0Disp,SourceRefill];
PFetch4[txrFontBodyLo,txrSrcBuf],
RETURN;*Return to the first instruction (BBFA) of the inner loop.
TxDestRefill:
T ← txrDestQWO,
AT[BBFAType0Disp,DestRefill];
PStore4[txrDestLo,txrDestBuf],
GoTo[TxFetchDest];
TxContinue:
T ← BBFA[SB[txrSrcBuf]] OR T,
GoTo[TxInnerLoopType0B],
AT[BBFAType0Disp,NoRefill];
TxWidth0:*Alternate TxCharDispDone:
PFetch1[txrArgLo,txrSpace,txcSpace], Goto[TxCDD1];
TxCharDispDone:
*Reload txrSpace from the argument table. Display path only.
PFetch1[txrArgLo,txrSpace,txcSpace];
TxCDD1:
*If 4 more registers must be freed sometime (e.g. to implement Local caching), one could share quad registers between txrDestBuf and txrFunction-txrLast-txrTextLo(Hi). Then one could PFetch4 txrFunction-etc. here and adjust txrTextHi in TxRestoreRegs.
T ← (txrBitWidth);*Needed at TxUpdate1.
TxTestPad:
LU ←(txrFlag),*bit 0 is pad flag
GoTo[TxUpdate1,R>=0];*Go if No Pad
T ← (LDF[txrCount,0,1]), Task;*T = 1 if count was negative.
T ← (txrSpace) + T;
txrBitPos ← (txrBitPos)+T;
TxIncrCount:
txrCount ← (txrCount)+1;
TxUpdate:
T ←(txrBitWidth);
TxUpdate1:
txrBitPos ← (txrBitPos)+T;
T ←(txrMicaWidth);
txrMicaPos ← (txrMicaPos)+T,
Task;*Let high priority tasks run.
T ←(txrIndex)+1;
LU ← (txrLast)-T;
txrIndex ← T,
Goto[TxDoneNormal,ALU<0];*Done if new Index > Last
TxTestNWW:
LU ← xfWDC, GoTo[TxCharacterLoop,IntPending’];
DISPATCH[txrFunction,16,2],
GoTo[TxCharacterLoop1,ALU#0];*Go if interrupts disabled.
*Here if xfWDC .eq. 0 and IntPending. Control will return by restarting the opcode.
LoadPage[OpPage0];
T ← 2C, GoToP[MIPend];*back up the Mesa PC by 2 because MISC Mopp is a two byte opcode.
TxDoneStop:
txrResult ← TxcResultStop, GoTo[TxDone];
TxDoneMargin:
txrResult ← TxcResultMargin, GoTo[TxDone];
TxNothingToDo:
txrResult ← TxcResultNormal, GoTo[TxDone];
TxDoneNormal:
txrResult ← TxcResultNormal;
TxDone:
LoadPage[OpPage0];
GoToP[P4Tail];
TxTask:
RETURN;
END[TextBlt];
:ELSE; *********************************************
TITLE[TextBlt.microcode.not.assembled];
:ENDIF; ********************************************