{DESTest.mc, HGM,  4-Nov-84  2:29:40

 Simple tests for DES chip on Dicentra Misc board.
 
 Each tick of the MP represents 256 good encryption blocks and 254 good decryption blocks.
 
 NB: This program assumes that Burdock loads
  the Key, Data, and Cipher U Regs with valid data.

}


	Reserve[0F5F, 0FFF]; {section used by the CP Kernel }
	SetTask[0]; StartAddress[Go];

RegDef[address,		R, 1]; {9000 => DES Chip}
RegDef[rhAddr,		RH, 1]; {6 => Byte mode, 7=> Word mode}

RegDef[out1,		R, 3];
RegDef[out2,		R, 4];
RegDef[out3,		R, 5];
RegDef[out4,		R, 6];

RegDef[passCount,	R, 0D];
RegDef[temp,		R, 0E];

RegDef[uKey1,		U, 21];
RegDef[uKey2,		U, 22];
RegDef[uKey3,		U, 23];
RegDef[uKey4,		U, 24];

RegDef[uData1,		U, 31];
RegDef[uData2,		U, 32];
RegDef[uData3,		U, 33];
RegDef[uData4,		U, 34];

RegDef[uCipher1,	U, 41];
RegDef[uCipher2,	U, 42];
RegDef[uCipher3,	U, 43];
RegDef[uCipher4,	U, 44];

Set[L0.ResetForEncryption, 1];
Set[L0.ResetForDecryption, 2];
Set[L0.SetEncryptMode, 3];
Set[L0.SetDecryptMode, 4];
Set[L0.LoadEnKey, 5];
Set[L0.LoadDeKey, 6];
Set[L0.StartEncryption, 7];
Set[L0.StartDecryption, 8];


Trap:	temp ← RRot1 ErrnIBnStkp, ClrIntErr,		c1, at[0];
	Xbus ← temp LRot0, XwdDisp,			c2;
	DISP2[TrapType],				c3;
	
Parity:	GOTO[GoToGo],					c1, at[0,4,TrapType];
Init:	GOTO[GoToGo],					c1, at[1,4,TrapType];
Stack:	GOTO[GoToGo],					c1, at[2,4,TrapType];
IB:	GOTO[GoToGo],					c1, at[3,4,TrapType];

GoToGo:
	Noop,						c2;
	GOTO[Go],					c3;

Go:	address ← 90,					c1;
	address ← address LRot8, {9000}			c2;
	Noop,						c3;
	
	Noop,						c1;
	passCount ← 0,					c2;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}		c3;
	
MainLoop:
	Noop,						c1;
	Noop,						c2;
	Noop,						c3;
	
ResetTheChip:
	temp ← 00, L0 ← L0.ResetForEncryption,		c1;
	CALL[StuffCommand],				c2;

SetEncryptionMode:
	temp ← 18, L0 ← L0.SetEncryptMode,		c1, at[L0.ResetForEncryption, 10, StuffRet];
	CALL[StuffMode], {ECB, Encrypt via Master Port}	c2;

	
LoadEncryptionKey:
	temp ← 11, L0 ← L0.LoadEnKey,			c1, at[L0.SetEncryptMode, 10, StuffRet];
	CALL[StuffCommand],				c2;

	Noop,						c1, at[L0.LoadEnKey, 10, StuffRet];
	Noop,						c2;
	Noop,						c3;
	
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uKey1,					c2;
	Noop,						c3;
	
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uKey2,					c2;
	Noop,						c3;
	
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uKey3,					c2;
	Noop,						c3;
	
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uKey4,					c2;
	Noop,						c3;
	
StartEncryption:
	temp ← 0C0, L0 ← L0.StartEncryption,		c1;
	CALL[StuffCommand],				c2;
	
	Noop,						c1, at[L0.StartEncryption, 10, StuffRet];
	Noop,						c2;
	Noop,						c3;
	
LoadData:
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uData1,					c2;
	Noop,						c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uData2,					c2;
	Noop,						c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uData3,					c2;
	Noop,						c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uData4,					c2;
	Noop,						c3;

	Noop,						c1;
	Noop,						c2;
	temp ← 20,					c3;
	
{Wait for the chip to crunch the bits.  No pipelining.}
DataDally:
	Noop,						c1;
	temp ← temp - 1, ZeroBr,			c2;
	BRANCH[DataDally, $],				c3;

GetEncryption:
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	Noop,						c2;
	out1 ← MD,					c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	Noop,						c2;
	out2 ← MD,					c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	Noop,						c2;
	out3 ← MD,					c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	Noop,						c2;
	out4 ← MD,					c3;

CheckEncryption:
	temp ← uCipher1,				c1;
	[] ← out1 xor temp, NZeroBr,			c2;
	BRANCH[$, Encr1Bad],				c3;
	
	temp ← uCipher2,				c1;
	[] ← out2 xor temp, NZeroBr,			c2;
	BRANCH[$, Encr2Bad],				c3;
	
	temp ← uCipher3,				c1;
	[] ← out3 xor temp, NZeroBr,			c2;
	BRANCH[$, Encr3Bad],				c3;
	
	temp ← uCipher4,				c1;
	[] ← out4 xor temp, NZeroBr,			c2;
	BRANCH[$, Encr4Bad],				c3;
	
GoodEncryption:
	Noop,						c1;
	passCount ← passCount + 1, PgCarryBr,		c2;
	BRANCH[LoadData, $],				c3;


ResetForDecryption:
	temp ← 00, L0 ← L0.ResetForDecryption,		c1;
	CALL[StuffCommand],				c2;

SetDecryptionMode:
	temp ← 08, L0 ← L0.SetDecryptMode,		c1, at[L0.ResetForDecryption, 10, StuffRet];
	CALL[StuffMode], {ECB, Decrypt via Master Port}	c2;

LoadDecryptionKey:
	temp ← 12, L0 ← L0.LoadDeKey,			c1, at[L0.SetDecryptMode, 10, StuffRet];
	CALL[StuffCommand],				c2;

	Noop,						c1, at[L0.LoadDeKey, 10, StuffRet];
	Noop,						c2;
	Noop,						c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uKey1,					c2;
	Noop,						c3;
	
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uKey2,					c2;
	Noop,						c3;
	
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uKey3,					c2;
	Noop,						c3;
	
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uKey4,					c2;
	Noop,						c3;

StartDecryption:
	temp ← 0C0, L0 ← L0.StartDecryption,		c1;
	CALL[StuffCommand],				c2;
	
	Noop,						c1, at[L0.StartDecryption, 10, StuffRet];
	Noop,						c2;
	Noop,						c3;
	
LoadCipher:
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uCipher1,					c2;
	Noop,						c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uCipher2,					c2;
	Noop,						c3;
	
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uCipher3,					c2;
	Noop,						c3;
	
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	MDR ← uCipher4,					c2;
	Noop,						c3;

{A slight delay seems to be necessary at 16MHZ.}
	Noop,						c1;
	Noop,						c2;
	Noop,						c3;
	
FillDecryptionPipeTest:
	temp ← passCount and 0FE,			c1;
	[] ← temp, ZeroBr,				c2;
	BRANCH[GetDecryption, $],			c3;

	Noop, {passCount is 0 or 1}			c1;
	passCount ← passCount + 1,			c2;
	GOTO[LoadCipher],				c3;

GetDecryption:
	IO ← [rhAddr, address + 0], {DES Data}		c1;
	Noop,						c2;
	out1 ← MD,					c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	Noop,						c2;
	out2 ← MD,					c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	Noop,						c2;
	out3 ← MD,					c3;

	IO ← [rhAddr, address + 0], {DES Data}		c1;
	Noop,						c2;
	out4 ← MD,					c3;
	
CheckDecryption:
	temp ← uData1,					c1;
	[] ← out1 xor temp, NZeroBr,			c2;
	BRANCH[$, Decr1Bad],				c3;
	
	temp ← uData2,					c1;
	[] ← out2 xor temp, NZeroBr,			c2;
	BRANCH[$, Decr2Bad],				c3;
	
	temp ← uData3,					c1;
	[] ← out3 xor temp, NZeroBr,			c2;
	BRANCH[$, Decr3Bad],				c3;
	
	temp ← uData4,					c1;
	[] ← out4 xor temp, NZeroBr,			c2;
	temp ← passCount + 1, BRANCH[$, Decr4Bad],	c3;
	
GoodDecryption:
	temp ← temp and 0FE,				c1;
	passCount ← passCount + 1, PgCarryBr,		c2;
	BRANCH[$, NextPass],				c3;

	temp ← temp xor 0FE,				c1;
	[] ← temp, ZeroBr,				c2;
	BRANCH[LoadCipher, $],				c3;

	Noop, {passCount = 0FD or 0FE}			c1;
	Noop,						c2;
	GOTO[GetDecryption],				c3;

NextPass:
	Noop,						c1;
	ExtCtrl ← 3, {Gets Bumped on rising edge},	c2;
	ExtCtrl ← 7, GOTO[MainLoop],			c3;
	
	
{------------------------------------------------------------------------------------}

Encr1Bad: GOTO[ErrorInEncryption],			c1;
Encr2Bad: GOTO[ErrorInEncryption],			c1;
Encr3Bad: GOTO[ErrorInEncryption],			c1;
Encr4Bad: GOTO[ErrorInEncryption],			c1;

ErrorInEncryption:
	Noop,						c2;
	GOTO[Go],					c3;

Decr1Bad: GOTO[ErrorInDecryption],			c1;
Decr2Bad: GOTO[ErrorInDecryption],			c1;
Decr3Bad: GOTO[ErrorInDecryption],			c1;
Decr4Bad: GOTO[ErrorInDecryption],			c1;

ErrorInDecryption:
	Noop,						c2;
	GOTO[Go],					c3;


{------------------------------------------------------------------------------------}

StuffCommand:
	rhAddr ← 6,					c3;
	
	IO ← [rhAddr, address + 1], {DES Command}	c1;
	MDR ← temp, L0Disp,				c2;
	rhAddr ← 7, DISP4[StuffRet],			c3;
	
StuffMode:
	rhAddr ← 6,					c3;
	
	IO ← [rhAddr, address + 3], {DES Mode}		c1;
	MDR ← temp, L0Disp,				c2;
	rhAddr ← 7, DISP4[StuffRet],			c3;
	
{
  BEWARE: You have to wait 6 des clock after storing a command or mode.
  This code assumes that the hardware provides that delay.
  }
  
  
{------------------------------------------------------------------------------------}

{Scope loops: Let normal stuff run a while to initialize things..}

ScopeWriteLoopIO:
	IO ← [rhAddr, address + 0],			c1;
	MDR ← temp,					c2;
	Noop,						c3;

{Dally a while to let AddressStrobe happen.}
	Noop,						c1;
	Noop,						c2;
	Noop,						c3;

	Noop,						c1;
	Noop,						c2;
	Noop,						c3;

	Noop,						c1;
	Noop,						c2;
	Noop,						c3;

	Noop,						c1;
	Noop,						c2;
	GOTO[ScopeWriteLoopIO],				c3;
	
ScopeReadLoopIO:
	IO ← [rhAddr, address + 0],			c1;
	Noop,						c2;
	temp ← MD,					c3;

{Dally a while to let AddressStrobe happen.}
	Noop,						c1;
	Noop,						c2;
	Noop,						c3;

	Noop,						c1;
	Noop,						c2;
	Noop,						c3;

	Noop,						c1;
	Noop,						c2;
	Noop,						c3;

	Noop,						c1;
	Noop,						c2;
	Noop, GOTO[ScopeReadLoopIO],			c3;