mirror of
https://github.com/livingcomputermuseum/Darkstar.git
synced 2026-02-28 17:39:41 +00:00
39 lines
25 KiB
Plaintext
39 lines
25 KiB
Plaintext
head 1.1;
|
||
branch 1.1.1;
|
||
access ;
|
||
symbols start:1.1.1.1 Xerox:1.1.1;
|
||
locks ; strict;
|
||
comment @# @;
|
||
|
||
|
||
1.1
|
||
date 2001.08.12.22.22.18; author freier; state Exp;
|
||
branches 1.1.1.1;
|
||
next ;
|
||
|
||
1.1.1.1
|
||
date 2001.08.12.22.22.18; author freier; state Exp;
|
||
branches ;
|
||
next ;
|
||
|
||
|
||
desc
|
||
@@
|
||
|
||
|
||
|
||
1.1
|
||
log
|
||
@Initial revision
|
||
@
|
||
text
|
||
@{File name Block.mc
|
||
Description: Mesa Block Transfer op-codes
|
||
Author: Jim JXF
|
||
Created: January 30, 1981
|
||
Last edited by Dennis DEG : 1-Sep-84 19:26:09: Add copyright notice.
|
||
Last edited by AeF AEF : 11-Nov-83 14:31:58: Delete ClrIntErr at blGoDisabled
|
||
Last edited by AXD : 15-Jun-83 17:24:43: New instruction set
|
||
Last edited by AeF AEF : 12-Jan-83 17:32:20: Move ClrIntErr away from stack instructions
|
||
Last edited by AeF AEF : 22-Dec-82 10:29:02: Add BLTLR
|
||
Last edited by Jim JXF : January 13, 1982 3:42 PM: Fix Checksum to decrement stack when count is zero.
|
||
JGS : November 2, 1981 2:30 PM: Integrate into new instruction set.
|
||
Last edited by AeF AEF : July 7, 1981 8:22 AM: Revision to provide for the BlockEqual parameters to be in the same order as the BlockTransfer parameters.
|
||
Last edited by Jim JXF : March 23, 1981 2:46 PM: Update comments and try out new coding conventions.
|
||
Last edited by Jim JXF : March 16, 1981 11:42 AM: Add code to handle Checksum Misc opcode.
|
||
Last edited by Jim JXF : February 25, 1981 3:02 PM: Major rewrite. The goddamn BlockEqual instructions are not at all like the BlockTransfer instructions. The code offset is on the top of the stack.
|
||
Last edited by Jim JXF : February 24, 1981 10:50 PM: Fix the Zero Byte Page Carry Gotcha.
|
||
Last edited by Jim JXF : February 21, 1981 3:23 AM: Major rewrite. BlockEqual is a two-byte opcode.
|
||
Last edited by Jim JXF : February 17, 1981 11:10 PM: Change to check for zero count BEFORE we do any maps. Unfortunately, we get address fault otherwise.
|
||
}
|
||
|
||
{ Copyright (C) 1982, 1983 by Xerox Corporation. All rights reserved.}
|
||
|
||
{This module handles BlockTransfer and BlockEqual instructions.
|
||
For the Block instructions, L2 is used to call SaveBlockRegs. It is also used
|
||
to distinguish the opcodes as follows:
|
||
|
||
Inst. L2 code long Block Transfer
|
||
|
||
BLT 3 0 0 1 1
|
||
BLTC B 1 0 1 1
|
||
BLTCL F 1 1 1 1
|
||
BLTL 7 0 1 1 1
|
||
BLEL 6 0 1 1 0
|
||
BLECL E 1 1 1 0
|
||
CKSUM 4 0 1 0 0
|
||
BLTLR 5 0 1 0 1
|
||
|
||
After L2Disp:
|
||
|
||
BRANCH[NotBlockTransferInstruction, BlockTransferInstruction, 0E],
|
||
BRANCH[ChecksumInstruction, BlockInstruction, 0D],
|
||
BRANCH[ShortInstruction, LongInstruction, 0B],
|
||
BRANCH[ZeroBase, CodeBase, 7], }
|
||
|
||
Set[Transfer,0E];
|
||
Set[Block,0D];
|
||
Set[Long,0B];
|
||
Set[CodeBase,7];
|
||
Set[L1.Forward, 0];
|
||
Set[L1.Reverse, 0F];
|
||
|
||
{ SUBROUTINES }
|
||
|
||
{******************************************************************************************
|
||
PopCount subroutine
|
||
L2Disp is pending on call.
|
||
******************************************************************************************}
|
||
MacroDef[PopCountRet,at[#1,10,PopCountRet]];
|
||
{Return depending on the two middle bits of L2:}
|
||
Set[PopShortBlock,0B]; {x01x = 0B = short Block}
|
||
Set[PopLongBlock,0F]; {x11x = 0F = long Block}
|
||
Set[PopChecksum,0D]; {x10x = 0D = checksum}
|
||
Set[PopBLEQC,9]; {x00x = 9 = BLEQC (called with no disp)}
|
||
PopCount:
|
||
TOS ¬ STK, pop, DISP4[PopCountRet,9], c*;
|
||
|
||
|
||
{******************************************************************************************
|
||
Checksum
|
||
TOS = uStack5 = sourceHi
|
||
STK = uStack4 = = sourceLow
|
||
STK-1 = uStack3 = count
|
||
STK-2 = uStack2 = sum
|
||
We set up source and dest to be the same thing because this works out easiest when mapping.
|
||
******************************************************************************************}
|
||
@@CKSUM:
|
||
at[0A,10,ESC2n]
|
||
L ¬ ~ErrnIBnStkp, ULsave ¬ L, L2 ¬ CKSUM, c1;
|
||
rhT {destHi} ¬ uStack5 {sourceHi}, CALL[SaveBlockRegs], c2;
|
||
{SaveBlockRegs subroutine here c3-c3}
|
||
at[CKSUM,10,SavebbRegsRet]
|
||
Rx {sourceLow} ¬ uStack4 {sourceLow}, c1;
|
||
TOS ¬ uStack3 {count}, ZeroBr, L0 ¬ BLEQfini, c2;
|
||
TT ¬ rhTT {sourceHi} ¬ uStack5 {sourceHi}, {Next line}
|
||
BRANCH[$, blNullChecksum], c3;
|
||
|
||
T ¬ STK{destLow}, pop{count}, GOTO[blTestCount], c1;
|
||
|
||
blNullChecksum:
|
||
TOS ¬ uStack2 {return sum in TOS}, c1;
|
||
stackP ¬ 1 {one thing (sum) left on the stack}, CALL[RestoreBlockRegsC2], c2;
|
||
{RestoreBlockRegs here. Return to blChecksumDone c3-c1};
|
||
|
||
|
||
{ BLOCK EQUAL INSTRUCTIONS }
|
||
|
||
{******************************************************************************************
|
||
BLEL Block Equal Long
|
||
TOS = destHi
|
||
STK = destLow
|
||
STK-1 = count
|
||
STK-2 = srcHi
|
||
STK-3 = srcLow
|
||
******************************************************************************************}
|
||
@@BLEL:
|
||
at[8,10,ESC2n]
|
||
L ¬ ~ErrnIBnStkp, ULsave ¬ L, L2 ¬ BLEL, c1;
|
||
rhT ¬ TOS {destHi} LRot0, CALL[SaveBlockRegs], c2;
|
||
{SaveBlockRegs subroutine here c3-c3}
|
||
at[BLEL,10,SavebbRegsRet]
|
||
T ¬ STK {destLow}, pop {count}, L2Disp, CALL[PopCount], c1;
|
||
{TOS ¬ STK, pop {srcHi}, GOTO[BLongSourceCommon], c2;}
|
||
|
||
{******************************************************************************************
|
||
BLECL Block Equal Code Long
|
||
TOS = destHi
|
||
STK = destLow
|
||
STK-1 = count
|
||
STK-2 = srcLow
|
||
******************************************************************************************}
|
||
@@BLECL:
|
||
at[9,10,ESC2n]
|
||
L ¬ ~ErrnIBnStkp, ULsave ¬ L, L2 ¬ BLECL, c1;
|
||
rhT ¬ TOS {destHi} LRot0, CALL[SaveBlockRegs], c2;
|
||
{SaveBlockRegs subroutine here c3-c3}
|
||
at[BLECL,10,SavebbRegsRet]
|
||
TT ¬ rhTT ¬ UvChigh {srcHi}, c1;
|
||
blBlockEqualCodeCommon:
|
||
T ¬ STK {count}, pop {count}, c2;
|
||
TOS ¬ STK {count}, pop {offset}, GOTO[blPopSourceLow], c3;
|
||
|
||
|
||
{ BLOCK TRANSFER INSTRUCTIONS }
|
||
|
||
{******************************************************************************************
|
||
BLTLR Block Transfer Long Reverse
|
||
TOS = destHi
|
||
STK = destLow
|
||
STK-1 = count
|
||
STK-2 = srcHi
|
||
STK-3 = srcLow
|
||
******************************************************************************************}
|
||
|
||
@@BLTLR:
|
||
at[7,10,ESC2n]
|
||
L ¬ ~ErrnIBnStkp, ULsave ¬ L, L2 ¬ BLTLR, c1;
|
||
rhT ¬ TOS LRot0 {destHi}, CALL[SaveBlockRegs], c2;
|
||
{SaveBlockRegs subroutine here c3-c3}
|
||
at[BLTLR,10,SavebbRegsRet]
|
||
G ¬ STK {destLow}, pop {count}, L2Disp, CALL[PopCount], c1;
|
||
|
||
PopCountRet[PopChecksum]
|
||
rhTT ¬ TT ¬ STK {srcHi}, pop {srcLow}, c3;
|
||
|
||
Rx ¬ STK {srcLow}, pop {next}, c1;
|
||
uStackPSave ¬ L, c2;
|
||
uDestLowSave ¬ G, c3;
|
||
|
||
blAdjustRHRegs:
|
||
Q ¬ TOS - 1, {count - 1} c1;
|
||
[] ¬ Rx + Q, CarryBr, L2 ¬ BLTLR, c2;
|
||
G ¬ uDestLowSave, BRANCH[blNoBankSrcCross, blBankSrcCross], c3;
|
||
|
||
blNoBankSrcCross:
|
||
uSourceHighSave ¬ TT, GOTO[blTestDestCross], c1;
|
||
blBankSrcCross:
|
||
uSourceHighSave ¬ TT, TT ¬ TT + 1, c1;
|
||
blTestDestCross:
|
||
G ¬ G + Q, CarryBr, L1 ¬ L1.Restore, c2;
|
||
T ¬ rhT, BRANCH[blNoBankDestCross, blBankDestCross], c3;
|
||
|
||
blNoBankDestCross:
|
||
uDestHighSave ¬ T, GOTO[blSetSrcHiRev], c1;
|
||
blBankDestCross:
|
||
uDestHighSave ¬ T, T ¬ T + 1, c1;
|
||
blSetSrcHiRev:
|
||
[] ¬ TOS, ZeroBr, L0 ¬ BLEQfini, c2;
|
||
rhT ¬ T LRot0, BRANCH[$, RestoreBlockRegsC1], c3;
|
||
|
||
T ¬ G, c1;
|
||
rhTT ¬ TT LRot0, GOTO[blSaveOffset], c2;
|
||
|
||
{******************************************************************************************
|
||
BLTL Block Transfer Long
|
||
TOS = destHi
|
||
STK = destLow
|
||
STK-1 = count
|
||
STK-2 = srcHi
|
||
STK-3 = srcLow
|
||
******************************************************************************************}
|
||
@@BLTL:
|
||
opcode[364'b]
|
||
L ¬ ~ErrnIBnStkp, ULsave ¬ L, L2 ¬ BLTL, c1;
|
||
rhT ¬ TOS {destHi} LRot0, push, CALL[SaveBLTRegs], c2;
|
||
{SaveBlockRegs subroutine here c3-c3}
|
||
at[BLTL,10,SavebbRegsRet]
|
||
T ¬ STK {destLow}, pop {count}, L2Disp, CALL[PopCount], c1;
|
||
{TOS ¬ STK {count}, pop{srcHi}, c2;}
|
||
|
||
blLongSourceCommon:
|
||
PopCountRet[PopLongBlock]
|
||
TT ¬ rhTT ¬ STK {srcHi}, pop {srcLow}, GOTO[blPopSourceLow] c3;
|
||
|
||
{******************************************************************************************
|
||
BLTC Block Transfer Code
|
||
TOS = destLow
|
||
STK = count
|
||
STK-1 = offset of source from codebase
|
||
******************************************************************************************}
|
||
@@BLTC:
|
||
opcode[365'b]
|
||
L ¬ ~ErrnIBnStkp, ULsave ¬ L, L2 ¬ BLTC, c1;
|
||
TT ¬ rhTT {srcHi} ¬ UvChigh {dstHi}, push, CALL[SaveBLTRegs], c2;
|
||
{SaveBlockRegs subroutine here c3-c3}
|
||
rhT ¬ UvMDS {dstHi}, {continue next line}
|
||
at[BLTC,10,SavebbRegsRet]
|
||
push {destLow, now in stack}, GOTO[blShortSourceCommon], c1;
|
||
|
||
{******************************************************************************************
|
||
BLTCL Block Transfer Code Long
|
||
TOS = destHi
|
||
STK = destLow
|
||
STK-1 = count
|
||
STK-2 = offset of source from codebase
|
||
******************************************************************************************}
|
||
@@BLTCL:
|
||
opcode[366'b]
|
||
L ¬ ~ErrnIBnStkp, ULsave ¬ L, L2 ¬ BLTCL, c1;
|
||
rhT ¬ TOS {destHi} LRot0, push, CALL[SaveBLTRegs], c2;
|
||
{SaveBlockRegs subroutine here c3-c3}
|
||
at[BLTCL,10,SavebbRegsRet]
|
||
TT ¬ rhTT ¬ UvChigh {srcHi}, GOTO[blBlockEqualCodeCommon], c1;
|
||
|
||
{******************************************************************************************
|
||
BLT Block Transfer
|
||
TOS = destLow
|
||
STK = count
|
||
STK-1 = srcLow
|
||
******************************************************************************************}
|
||
@@BLT:
|
||
opcode[363'b]
|
||
L ¬ ~ErrnIBnStkp, ULsave ¬ L, L2 ¬ BLT, c1;
|
||
TT ¬ rhTT {srcHi} ¬ UvMDS, push, CALL[SaveBLTRegs], c2;
|
||
SaveBLTRegs:
|
||
STK ¬ TOS, pop, CALL[SaveBlockRegsx], c3;
|
||
{SaveBlockRegsx subroutine here c1-c3}
|
||
at[BLT,10,SavebbRegsRet]
|
||
rhT ¬ UvMDS {dstHi}, push {destLow, now in stack}, c1;
|
||
blShortSourceCommon:
|
||
T ¬ STK {destLow}, pop {count}, L2Disp, CALL[PopCount], c2;
|
||
|
||
{TOS ¬ STK {count}, pop {srcLow}, c3;}
|
||
blPopSourceLow:
|
||
PopCountRet[PopShortBlock]
|
||
Rx ¬ STK {srcLow}, pop {next}, c1;
|
||
blTestCount:
|
||
[] ¬ TOS {count}, ZeroBr, CANCELBR[$,1], c2;
|
||
blTestOffset:
|
||
L2Disp, BRANCH[$,blNullCount], c3;
|
||
|
||
blSaveStackP:
|
||
uStackPSave ¬ L, BRANCH[blZeroOffset,blCodeOffset, CodeBase], c1;
|
||
blZeroOffset:
|
||
Q ¬ 0, GOTO[blSaveOffset], c2;
|
||
blCodeOffset:
|
||
Q ¬ UvC, c2;
|
||
blSaveOffset:
|
||
uSourceOffset ¬ Q, GOTO[blMapSource], c3;
|
||
|
||
blNullCount:
|
||
{L2Disp is pending. Load L0 to return to BLTransferDone or BLCompareDone.
|
||
Put one in TOS for TRUE in case this is BlockEqual. It doesn't matter which Restore
|
||
entry we use so long as it is 3 cycles and we don't try to restore rhL. }
|
||
TOS ¬ 1 {TRUE}, L0 ¬ BLEQfini, {continue next line}
|
||
BRANCH[RestoreBlockRegsC3, RestoreBlockRegsC3Initial, Transfer], c1;
|
||
{Restore here c2-c1};
|
||
blTransferDone:
|
||
at[BLTfini,10,RestoreCallers]
|
||
TOS ¬ STK, pop, GOTO[blDone], c2;
|
||
blCompareDone: {1 (TRUE) or 0 (FALSE) is in TOS.}
|
||
blChecksumDone: {sum is in TOS.}
|
||
blReverseTransferDone: {need to pop stack for transfer}
|
||
at[BLEQfini,10,RestoreCallers]
|
||
{BlockCompare, BLTLR, and Checksum are two-byte instructions.}
|
||
PC ¬ PC + PC16, L2Disp, c2;
|
||
blDone: Xbus ¬ uPCCross, XRefBr, BRANCH[$, blReverseDone, Transfer], c3;
|
||
|
||
Noop, BRANCH[blNoInt, blSetInt], c1;
|
||
blReverseDone:
|
||
TOS ¬ STK, pop, BRANCH[blNoInt, blSetInt] c1;
|
||
blSetInt: PC ¬ PC + PC16, MesaIntRq, GOTO[NoWakeups {in Refill}], c2;
|
||
blNoInt: PC ¬ PC + PC16, GOTO[NoWakeups {in Refill}], c2;
|
||
|
||
{NoWakeups:
|
||
GOTO[IgnoreInt] ,c3;}
|
||
{IgnoreInt:
|
||
Noop ,c1;}
|
||
{IBDispOnly:
|
||
IBDisp, GOTO[DISPNIonly] ,c2;}
|
||
|
||
{******************************************************************************************
|
||
Map source and dest virtual addresses
|
||
Entry State:
|
||
Registers have been saved by SaveBlockRegs and must be restored.
|
||
All arguments have been removed from the stack except for the case of Checksum.
|
||
In the case of Checksum, we must set Stack pointer to 1 before we exit.
|
||
L1 = L1.Restore: return address from RLMapFix or WLMapFix in case of trap.
|
||
TT = source virtual address high
|
||
Rx = source virtual address low
|
||
rhT = dest virtual address high
|
||
T = dest virtual address low (dest virt addr low + Q if BLTLR)
|
||
Q = source offset (UvC if Code operation, TOS-1 if reverse transfer, else 0)
|
||
TOS = count
|
||
uDestHighSave = dest virt addr high of start of block for BLTLR only
|
||
uDestLowSave = dest virt addr low of start of block for BLTLR only
|
||
uSourceHighSave = source virt addr high of start of block for BLTLR only
|
||
|
||
******************************************************************************************}
|
||
|
||
blMapSource:
|
||
{Map source real address into rhG, G.
|
||
Test map for referenced. If not referenced, update the map since we are about to read it.
|
||
We want to end up with the source virtual address in rhTT,,Q in case of a trap on source.
|
||
Save rhTT (source high) and Rx (source low) so that we can restore it later.
|
||
Set up L0 to return to BLMapDest if we call RLMapFix.}
|
||
|
||
Map ¬ Q ¬ [rhTT, Rx + Q], L1 ¬ L1.Restore, c1;
|
||
blMapSourcex:
|
||
uSourceHighSaveTemp ¬ TT, PC ¬ Q, L0 ¬ L0.BLSource, c2;
|
||
G ¬ rhG ¬ MD, XRefBr, uSourceLowSave ¬ Rx, c3;
|
||
|
||
|
||
blMapDest:
|
||
RLMFRet[L0.BLSource]
|
||
{Map dest real address into rhRx, Rx.
|
||
We want to end up with the source virtual address in rhTT,,Q in case of a trap on dest.
|
||
Return here from RLMapFix if we needed to set the referenced bit.
|
||
Set up L0 to return to BLTestDestDirty if BlockTransfer or BLTestDestReferenced if BlockEqual.}
|
||
|
||
Map ¬ [rhT, T], L2Disp, BRANCH[blSetSourceReferenced, blSourceMapOK, 0E], c1;
|
||
blSourceMapOK:
|
||
Q ¬ rhT, L0 ¬ L0.BLDestR, {Continue next line}
|
||
BRANCH[blMapDestRead, blMapDestWrite, Transfer], c2;
|
||
blMapDestWrite:
|
||
{Come here for BlockTransfer to map the dest address for write.
|
||
If not dirty, we will have to fix the map since we are about to write it.}
|
||
rhRx ¬ Rx ¬ MD, XDirtyDisp, c3;
|
||
|
||
blTestDestDirty:
|
||
WLMFRet[L0.BLDest]
|
||
{Return here from WLMapFix after we set dirty bit.}
|
||
rhTT ¬ Q LRot0, BRANCH[blSetDestDirty, blDestDirty, 1], c1;
|
||
|
||
blSetSourceReferenced:
|
||
{Come here if source map must be fixed for referenced.
|
||
Q = virtual sourceLow. rhTT = virtual sourceHi. Set Rx to map data.
|
||
L0 = L0.BLSource to return to BLMapDest above after we set referenced bit.
|
||
L1 = L1.Restore to return to BLReadTrap in case of trap.}
|
||
Rx ¬ G, CANCELBR[RLMapFix,0F], c2;
|
||
|
||
blSetDestDirty:
|
||
{Come here if dest map must be fixed for dirty.
|
||
Rx = map data. rhTT = virtual destHi. Set Q to virtual destLow.
|
||
L0 = L0.BLDest for return to BLTestDestDirty after we set dirty bit.
|
||
L1 = L1w.restore = L1r.restore to return to BLWriteTrap in case of trap.}
|
||
Q ¬ T, CALL[WLMapFix], c2;
|
||
|
||
blDestDirty:
|
||
{Restore while we have a spare cycle in case we get to Update.}
|
||
TT ¬ uSourceHighSaveTemp, L1 ¬ L1.Forward, GOTO[blStart], c2;
|
||
|
||
blMapDestRead:
|
||
{Come here if Block Equal. Test dest for referenced.
|
||
If not referenced, we will have to fix the map since we are about to read it. }
|
||
rhRx ¬ Rx ¬ MD, XRefBr, c3;
|
||
blTestDestReferenced:
|
||
RLMFRet[L0.BLDestR]
|
||
{Return here from RLMapFix after we set dest referenced.}
|
||
rhTT ¬ Q LRot0, {Continue next line}
|
||
BRANCH[blSetDestReferenced, blDestReferenced], c1;
|
||
blSetDestReferenced:
|
||
{Come here if dest map must be fixed for referenced.
|
||
Rx = map data. rhTT = virtual destHi. Set Q to virtual destLow.
|
||
L0 = L0.BLDest for return to blTestDestReferenced after we set dirty bit.
|
||
L1 = L1.Restore to return to blWriteTrap in case of trap.}
|
||
Q ¬ T, CALL[RLMapFix], c2;
|
||
blDestReferenced:
|
||
{Restore while we have a spare cycle in case we get to Update.}
|
||
TT ¬ uSourceHighSaveTemp, L1 ¬ L1.Forward, GOTO[blStart], c2;
|
||
|
||
blReadTrap:
|
||
at[L1.Restore,10,RLTrapFix]
|
||
{Return here from RLMapFix in case of trap on either source or dest (if Block Equal).}
|
||
stackP ¬ uStackPSave, {Continue next line}
|
||
L0 ¬ restore.trap, GOTO[blRestoreBlockRegs], c1;
|
||
|
||
blWriteTrap:
|
||
at[L1.Restore,10,WTrapFix]
|
||
{Return here from WLMapFix in case of trap on dest.}
|
||
stackP ¬ uStackPSave, L0 ¬ restore.trap, c1;
|
||
blRestoreBlockRegs:
|
||
{StackP has been restored from uStackPSave. Restore all other registers.
|
||
Q = virtual address low. TT = virtual address high.}
|
||
uFaultParm0 ¬ Q, push, CALL[RestoreBlockRegsC1], c2;
|
||
{Restore here. c3-c3}
|
||
at[restore.trap,10,RestoreCallers]
|
||
{Restore TOS so HiTT can save it again}
|
||
TOS ¬ STK, GOTO[HiTT], c1;
|
||
|
||
|
||
{******************************************************************************************
|
||
Block inner loop
|
||
Entry State:
|
||
L1 = L1.Restore: return address from RLMapFix or WLMapFix in case of trap.
|
||
rhTT = source virtual address high
|
||
uSourceHighSaveTemp = source virtual address High
|
||
PC = source virtual address low
|
||
uSourceLowSave = source virtual address low
|
||
rhG,,G = source real address high
|
||
rhT = dest virtual address high
|
||
T = dest virtual address low
|
||
rhRx,,Rx = dest real address high
|
||
TOS = count
|
||
Registers used:
|
||
Q = words transferred
|
||
L = source word read
|
||
******************************************************************************************}
|
||
blStart:
|
||
L {words transferred} ¬ 0, L0 ¬ BLEQfini, {this is reset later if Transfer} c3;
|
||
|
||
{Note that it is necessary to do the first memory reference separately.
|
||
Unfortunately, we cannot use Q to add to the virtual address each time through the loop.
|
||
When the low byte of the virtual address is zero, we will never get a page cross branch.
|
||
This is the Zero Byte Page Cross Gotcha. }
|
||
|
||
MAR ¬ G ¬ [rhG, PC+0], L2Disp, c1;
|
||
L2Disp, BRANCH[blFirstCksmOrRev, blFirstForward, Block], c2;
|
||
blFirstForward:
|
||
PC ¬ MD {source}, L2Disp, CANCELBR[blFirstDest, 0F], c3;
|
||
|
||
blFirstCksmOrRev:
|
||
PC ¬ MD {source}, BRANCH[blFirstChecksumWord, $, Transfer], c3;
|
||
|
||
blFirstDestReverse:
|
||
MAR ¬ Rx ¬ [rhRx, T + 0], L1 ¬ L1.Reverse, GOTO[blWriteNextDest], c1;
|
||
|
||
blFirstDest:
|
||
{Set L0 to return from RestoreCallers}
|
||
MAR ¬ Rx ¬ [rhRx, T + 0], L0 ¬ BLEQfini, BRANCH[blReadNextDest, blWriteNextDest, Transfer], c1;
|
||
|
||
{Read next source word: high 10 bits from rhG,,G, low 8 bits from G + 1.}
|
||
blReadSourceRev:
|
||
MAR ¬ G ¬ [rhG, G - 1], MesaIntBr, BRANCH[blCheckSource, blCountZero], c1;
|
||
|
||
blReadSource:
|
||
MAR ¬ G ¬ [rhG, G + 1], MesaIntBr, BRANCH[blCheckSource, blCountZero], c1;
|
||
blCheckSource:
|
||
L2Disp, DISP2[blSourceCheck], c2;
|
||
PC ¬ MD {source}, DISP4[ChksumOrRevOrOther, 0C], c3, at[0,4,blSourceCheck];
|
||
L1Disp, CANCELBR[blUpdate,0F], {source page cross} c3, at[2,4,blSourceCheck];
|
||
L1Disp, CANCELBR[blUpdate,0F], {interrupt} c3, at[1,4,blSourceCheck];
|
||
L1Disp, CANCELBR[blUpdate,0F], {source page cross and interrupt} c3, at[3,4,blSourceCheck];
|
||
|
||
{Send real address of dest: high 10 bits from rhRx,,Rx, low 8 bits from Rx + 1.}
|
||
MAR ¬ Rx ¬ [rhRx, Rx - 1], GOTO[blWriteNextDest], {reverse transfer} c1, at[0D, 10, ChksumOrRevOrOther];
|
||
|
||
MAR ¬ Rx ¬ [rhRx, Rx + 1], GOTO[blReadNextDest], c1, at[0E, 10, ChksumOrRevOrOther];
|
||
MAR ¬ Rx ¬ [rhRx, Rx + 1], GOTO[blWriteNextDest], {forward transfer} c1, at[0F, 10, ChksumOrRevOrOther];
|
||
|
||
blWriteNextDest:
|
||
{Come here if BlockTransfer to store the source word in the dest address.}
|
||
MDR {dest} ¬ PC {source}, L2Disp, L ¬ L + 1, BRANCH[blNoDestWriteCross, blDestWriteCross, 1], c2;
|
||
blNoDestWriteCross:
|
||
TOS ¬ TOS - 1, ZeroBr, BRANCH[blReadSourceRev, blReadSource, Block] c3;
|
||
blDestWriteCross:
|
||
L ¬ L - 1, L1Disp, CANCELBR[blUpdate, 0F], c3;
|
||
blReadNextDest:
|
||
{Come here if BlockEqual to compare the source word to the dest word.}
|
||
Noop, BRANCH[blNoDestReadPageCross, blDestReadPageCross,1], c2;
|
||
blDestReadPageCross:
|
||
L1Disp, GOTO[blUpdate], {Dest page cross} c3;
|
||
blNoDestReadPageCross:
|
||
PC ¬ MD {source} xor PC {dest}, c3;
|
||
|
||
[] ¬ PC, NZeroBr, c1;
|
||
blChecksumReturn:
|
||
L ¬ L + 1, BRANCH[blDecCount, blFalse], c2;
|
||
blFalse:
|
||
TOS ¬ 0 {false}, CALL[RestoreBlockRegsC1], c3;
|
||
{RestoreBlockRegs here. Return to blCompareDone. c1-c1}
|
||
|
||
blDecCount:
|
||
TOS ¬ TOS - 1, ZeroBr, GOTO[blReadSource], c3;
|
||
|
||
blCountZero:
|
||
TOS ¬ 1 {TRUE}, L2Disp, CANCELBR[$, 3], c2;
|
||
L2Disp, BRANCH[blChecksumCountZero, RestoreBlockRegsC1, Block], c3;
|
||
|
||
blChecksumCountZero:
|
||
[] ¬ Rx xor ~0, NZeroBr, BRANCH[$, RestoreRegs, Transfer], c1;
|
||
stackP ¬ TOS {1}, TOS ¬ uStack2 {sum}, BRANCH[blChecksumAllOnes, RestoreBlockRegsC2], c2;
|
||
RestoreRegs:
|
||
CANCELBR[RestoreBlockRegsC2, 1], c2;
|
||
|
||
blChecksumAllOnes:
|
||
TOS {sum} ¬ 0, CALL[RestoreBlockRegsC1], c3;
|
||
{Restore here. Return to blChecksumDone. c1-c1}
|
||
|
||
{******************************************************************************************
|
||
ChecksumWord
|
||
|
||
The Pup checksum is a 16-bit, one's complement, add-and-cycle checksum computed over
|
||
the 16-bit words in the block. The checksum is initialized to zero and computed by repeated
|
||
one's complement addition and left cycle. If the result is the ones-complement value
|
||
"minus one" (177777B), it is converted to zero. 177777B is specifically defined to mean
|
||
that the Pup carries no checksum.
|
||
******************************************************************************************}
|
||
blFirstChecksumWord:
|
||
PC {next word to add to sum} ¬ PC LRot1, GOTO[blChecksum], c1;
|
||
blNextChecksumWord:
|
||
PC {next word to add to sum} ¬ PC LRot1, CANCELBR[blChecksum,0F], c1, at[0C, 10, ChksumOrRevOrOther];
|
||
blChecksum:
|
||
Rx {sum} ¬ uStack2 LRot1, L0 ¬ BLEQfini, c2;
|
||
Rx {sum} ¬ Rx + PC {next word}, CarryBr, c3;
|
||
|
||
blTestChecksumCarry:
|
||
uStack2 ¬ Rx {sum}, BRANCH[blChecksumReturn, blChecksumCarry], c1;
|
||
blChecksumCarry:
|
||
Rx {sum} ¬ Rx + 1, c2;
|
||
Noop, GOTO[blTestChecksumCarry], c3;
|
||
|
||
{******************************************************************************************
|
||
blUpdate
|
||
Come here if we got a source or dest page cross or an interrupt request.
|
||
L1 = L1.Restore: return address from RLMapFix or WLMapFix in case of trap.
|
||
TT = uSourceHighSaveTemp source virtual address high
|
||
uSourceLowSave = source virtual address low
|
||
uSourceOffset = 0 if not code, UvC if code operation
|
||
rhT = dest virtual address high
|
||
T = dest virtual address low
|
||
TOS = count
|
||
L = number of words transferred
|
||
uStackPSave = stack pointer at beginning of operation.
|
||
******************************************************************************************}
|
||
blUpdate:
|
||
Rx ¬ uSourceLowSave, BRANCH[blUpdateForward, blUpdateReverse, 0E], c1;
|
||
blUpdateForward:
|
||
T {destLow} ¬ T {destLow} + L {words transferred}, CarryBr, c2;
|
||
|
||
blTestDestCarry:
|
||
rhTT ¬ TT LRot0, BRANCH[blNoDestCarry, blDestCarry], c3;
|
||
blDestCarry:
|
||
Q ¬ rhT {destHi} + 1, LOOPHOLE[byteTiming], c1;
|
||
|
||
rhT ¬ Q LRot0, GOTO[blTestDestCarry], {delay 1 cycle} c2;
|
||
|
||
blNoDestCarry:
|
||
Rx {srcLow} ¬ Rx {srcLow} + L {words transferred}, CarryBr, c1;
|
||
|
||
blTestSourceCarry:
|
||
L ¬ ~ErrnIBnStkp, L2Disp, BRANCH[blUpdateStack, blSourceCarry], c2;
|
||
|
||
blSourceCarry:
|
||
TT ¬ TT {sourceHigh} + 1, CANCELBR[$,0F], c3;
|
||
|
||
blSetHiSource:
|
||
rhTT ¬ TT LRot0, GOTO[blTestSourceCarry], {delay 1 cycle} c1;
|
||
|
||
blUpdateReverse:
|
||
rhTT ¬ TT ¬ uSourceHighSave, c2;
|
||
rhT ¬ uDestHighSave, c3;
|
||
|
||
{From now on we pretend that this is BLTL. L1 will tell us otherwise.}
|
||
T ¬ uDestLowSave, L2 ¬ BLTL, GOTO[blTestSourceCarry], c1;
|
||
|
||
|
||
{******************************************************************************************
|
||
If we must interrupt, we must save the state in the stack.
|
||
Current State:
|
||
TT = rhTT = source virtual address high
|
||
Rx = source virtual address low
|
||
rhT = dest virtual address high
|
||
T = dest virtual address low
|
||
TOS = count
|
||
Stack pointer points to next.
|
||
This is the way the stack should look when we are done:
|
||
|
||
BLTL and BLEL BLTC, and BLT
|
||
TOS = destHi TOS = destLow
|
||
STK = destLow STK = count
|
||
STK-1 = count STK-1 = srcLow
|
||
STK-2 = srcHi
|
||
STK-3 = srcLow
|
||
|
||
Checksum BLECL, and BLTCL
|
||
TOS = srcHi TOS = destHi
|
||
STK = srcLow STK = destLow
|
||
STK-1 = count STK-1 = count
|
||
STK-2 = sum STK-2 = srcLow
|
||
|
||
|
||
******************************************************************************************}
|
||
|
||
blUpdateStack:
|
||
Q ¬ rhT {destHi}, push {srcLow}, L2Disp, {Continue next line}
|
||
DISP4[blStackFormat,9], c3;
|
||
at[0D,10,blStackFormat] {Checksum}
|
||
stackP ¬ 3 {count}, L2Disp, CANCELBR[blStoreCountWait,0F], c1;
|
||
at[0B,10,blStackFormat] {Short}
|
||
STK ¬ Rx {srcLow}, push {count}, L2Disp, {Continue next line}
|
||
CANCELBR[blStoreCountWait,0F], c1;
|
||
at[0F,10,blStackFormat] {Long}
|
||
STK ¬ Rx {srcLow}, push {srcHi/count}, {Continue next line}
|
||
BRANCH[blStoreSourceHigh,blStoreCountWait,CodeBase], c1;
|
||
|
||
blStoreSourceHigh:
|
||
STK ¬ TT {srcHi}, push {count/next}, L2Disp, c2;
|
||
blStoreCount:
|
||
STK ¬ TOS {count}, push {destLow/srcLow}, L2Disp, {Continue}
|
||
BRANCH[blChecksumSourceLow,blStoreDestLow,Block], c3;
|
||
blStoreDestLow:
|
||
STK ¬ T {destLow}, push{destHi/next},BRANCH[blShortDone,blStoreDestHi,Long], c1;
|
||
|
||
blStoreCountWait:
|
||
L2Disp,CANCELBR[blStoreCount,0F], c2;
|
||
|
||
blStoreDestHi:
|
||
STK ¬ Q {destHi}, GOTO[blCheckInterrupts], c2;
|
||
blShortDone:
|
||
GOTO[blCheckInterrupts], c2;
|
||
|
||
blChecksumSourceLow:
|
||
STK ¬ Rx {srcLow}, push {srcHi}, CANCELBR[$,0F], c1;
|
||
STK ¬ TT {srcHi}, c2;
|
||
|
||
blCheckInterrupts:
|
||
[] ¬ uWDC, ZeroBr, c3;
|
||
blDisableBranch:
|
||
BRANCH[blDisabled, blNotDisabled], c1;
|
||
|
||
blDisabled:
|
||
Q ¬ uSourceOffset, L1Disp, c2;
|
||
stackP ¬ L, BRANCH[blMapSource, blAdjustRHRegs, 0D], c3;
|
||
|
||
blNotDisabled: {We must wait another click until we can do ClrIntErr}
|
||
CANCELBR[$, 0F], c2;
|
||
L0 ¬ restore.int, c3;
|
||
|
||
MesaIntBr, c1;
|
||
[] ¬ uWP, ZeroBr, BRANCH[$, blInterrupt], c2;
|
||
blGoDisabled:
|
||
CANCELBR[blDisableBranch, 1], c3;
|
||
blInterrupt:
|
||
ClrIntErr, BRANCH[$, blDisableBranch], c3;
|
||
|
||
stackP ¬ uStackPSave, CALL[RestoreBlockRegsC1], c1;
|
||
|
||
{This call to RestoreBlockRegs does not use the commented cycle numbers in BBSubs};
|
||
{RestoreBlockRegs here. Return to bbInit: c2-c2};
|
||
{RestoreRRegsAndRhG here. Return to bbInit: c1-c2};
|
||
|
||
{Rx ¬ pInt, push, c3, at[restore.int,10,RestoreCallers]};
|
||
|
||
{TOS ¬ STK, pop, GOTO[SaveRegs], c1;}
|
||
|
||
|
||
@
|
||
|
||
|
||
1.1.1.1
|
||
log
|
||
@first add
|
||
@
|
||
text
|
||
@@
|