; PREncrypt.mu -- Microcode source for Packet Radio encryption instruction.
;
Last modified September 18, 1978 12:07 PM


;
PREncrypt: PROCEDURE
; [from, to: POINTER, count: CARDINAL, gray1, gray2: WORD] =
; BEGIN
; DO
; IF count=0 THEN EXIT;
; count ← count-1;
; (to+count)↑ ← InlineDefs.BITXOR[(from+count)↑,gray1];
; IF count=0 THEN EXIT;
; count ← count-1;
; (to+count)↑ ← InlineDefs.BITXOR[(from+count)↑,gray2];
; ENDLOOP;
; END;
;
; gray1: XOR’s with even address words
; gray2: XOR’s with odd address words
; from: address of source block.
; to: address of destination block.
; count: length of block (words)
; Entry point is Ram address XXX.
; Timing is 5 cycles + 12 cycles per word
; Mesa emulator conventions

$temp
$R35;Emulator-level temporaries
$temp2
$R36;
$mpc
$R15;Mesa PC
$ib
$R10;Leftover instruction byte (0 if none)
$wdc
$R70;Wakeup disable counter
$stkp
$R16;Stack pointer (0 = empty, 10 = full)
$stk0
$R60;Stack (bottom)
$stk1
$R61;
$stk2
$R62;
$stk3
$R63;
$stk4
$R64;
$from
$R60;My names for registers
$to
$R61;
$count
$R62;
$gray1
$R63;
$gray2
$R64;
$NWW
$R4;

!1,2,ECLoop,ECDon1;
!1,2,ECMore,ECDon2;
!1,2,ECMayI,ECNoI;
!1,2,ECJunk,ECDoI;
!1,1,ECDn1;

PREncrypt:
L← T← count-1, BUS=0;Test completion
count← L, :ECLoop;[ECLoop, ECDon1]
ECLoop:
MAR← from+T;
L← to+T;Compute address for Store
temp← L;Save address for Store
T← gray1;
L← MD XOR T;Compute Encrypted word
MAR← temp;Start Store of result
temp2← L;
NOP, TASK;
MD← temp2;Store Encrypted word

L← T← count-1, BUS=0;Test for completion
count← L, :ECMore;[ECMore,ECDon2], Save new count
ECMore:
MAR← from+T;
L← to+T;Compute address for Store
temp← L;Save address for Store
T← gray2;
L← MD XOR T;Compute Encrypted word
MAR← temp;Start Store of result
temp2← L;
NOP, TASK;Update count
MD← temp2;Store Encrypted word

SINK← NWW, BUS=0;Test interrupts
NOP, :ECMayI;[ECMayI, ECNoI]
ECNoI:
NOP, :ECJunk;[ECJunk, ECDoI]
ECJunk:
NOP, :PREncrypt;

ECDon2:
L← 0, :ECDn1;
ECDon1:
L← 0, :ECDn1;
ECDn1:
stkp← L, TASK;
NOP, :Emulator;

; Here when possible interrupt pending.
ECMayI:
SINK← wdc, BUS=0, :ECNoI;Let it take only if wdc=0

; Here when interrupt definitely pending.
; Assume that the JRAM was the A-byte, so back up mpc and set ib to zero
; to force the interpreter to re-fetch the current word and also test again
; for the interrupt we know is pending.
ECDoI:
L← mpc-1;Back up mpc, squash BUS=0
mpc← L, L← 0, TASK;
ib← L;ib← 0
L← stkp+1, :ECDn1;Push Ram address back onto stack