; 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 (1792)\126b9B