; PREncrypt.mu -- Microcode source for Packet Radio encryption instruction.
;Last modified October 17, 1978 12:58 PM, HGM
;change count to words because of conflict with XM mesa
;Last modified September 18, 1978 12:07 PM
; PREncrypt: PROCEDURE
; [from, to: POINTER, words: CARDINAL, gray1, gray2: WORD] =
; BEGIN
; DO
; IF words=0 THEN EXIT;
; words ← words-1;
; (to+words)↑ ← InlineDefs.BITXOR[(from+words)↑,gray1];
; IF words=0 THEN EXIT;
; words ← words-1;
; (to+words)↑ ← InlineDefs.BITXOR[(from+words)↑,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;
$words$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← words-1, BUS=0;Test completion
words← 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← words-1, BUS=0;Test for completion
words← 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