//
// inasm.hxx
//
// generates the core of an i386+ assembly implementation of the
// SHA (Secure Hash Algorithm)
// Copyright (C) 1996-7 by Leonard Janke (janke@unixg.ubc.ca)
//
// I beleive the circular buffer optimization is due to Colin Plumb. 
// The optimized versions of the round functions are mentioned in
// _Can_D.S.A._be_Improved?_ 
// _Complexity_Trade-Offs_with_the_Digital_Signature_Standard_
// by D. Naccache, D. M'Raihi, S. Vaudenay, and D. Raphaeli
// appearing in Eurocrypt '94

#include <iostream.h>
#include <iomanip.h>
#include <cstring>

const  int newSHA=1;

typedef unsigned long u32;
static char* alias[5];
static char* t;

void Initialize()
{
  alias[0]=new char[6];
  alias[1]=new char[6];
  alias[2]=new char[6];
  alias[3]=new char[6];
  alias[4]=new char[6];
  t=new char[6];

  strcpy(alias[0],"%eax");
  strcpy(alias[1],"%ebx");
  strcpy(alias[2],"%ecx");
  strcpy(alias[3],"%edx");
  strcpy(alias[4],"%edi");
  strcpy(t,"%eqx");
}

void CirculateAlias()
{
  strcpy(t,alias[4]);
  strcpy(alias[4],alias[3]);
  strcpy(alias[3],alias[2]);
  strcpy(alias[2],alias[1]);
  strcpy(alias[1],alias[0]);
  strcpy(alias[0],t);
}

void main(int argc,char** argv)
{
  Initialize();


  if ( argc==2 && !strcmp("sha1",argv[1]) )
    newSHA=1;

  for (int i=0; i<20; i++)
    {
      cout <<"\t// i="<<dec<<i<<endl;
      cout <<"\tmovl "<<alias[2]<<", %ebp"<<endl;
      cout <<"\txorl "<<alias[3]<<", %ebp"<<endl;
      cout <<"\tandl "<<alias[1]<<", %ebp"<<endl;
      cout <<"\txorl "<<alias[3]<<", %ebp"<<endl;
      cout <<"\tmovl %ebp, (%esp) "<<endl;
      cout <<endl;
      if ( i>=16 )
	{
	  cout <<"\tmovl "<<4*((i-16)%16)<<"(%esi), %ebp"<<endl;
	  cout <<"\txorl "<<4*((i-14)%16)<<"(%esi), %ebp"<<endl;
	  cout <<"\txorl "<<4*((i-8)%16)<<"(%esi), %ebp"<<endl;
	  cout <<"\txorl "<<4*((i-3)%16)<<"(%esi), %ebp"<<endl;
	  if ( newSHA )
	    cout <<"\troll $1, %ebp"<<endl;
	  cout <<"\tmovl %ebp, "<<4*((i-16)%16)<<"(%esi)"<<endl;
	  cout <<endl;
	}
      cout <<"\tmovl "<<alias[0]<<", %ebp"<<endl;
      cout <<"\troll $5, %ebp"<<endl;
      cout <<"\taddl (%esp), %ebp"<<endl;
      cout <<"\taddl "<<alias[4]<<", %ebp"<<endl;
      if ( i>=16 )
	cout <<"\taddl "<<4*((i-16)%16)<<"(%esi), %ebp"<<endl;
      else
	cout <<"\taddl "<<4*i<<"(%esi), %ebp"<<endl;
      cout <<"\taddl $"<<int(0x5a827999)<<", %ebp"<<endl;
      cout <<"\tmovl %ebp, "<<alias[4]<<endl;
      cout <<endl;
      cout <<"\troll $30, "<<alias[1]<<endl;
      cout <<endl;
     CirculateAlias();
    }
   for (int i=20; i<40; i++)
    {
      cout <<"\t// i="<<dec<<i<<endl;
      cout <<"\tmovl "<<alias[1]<<", %ebp"<<endl;
      cout <<"\txorl "<<alias[2]<<", %ebp"<<endl;
      cout <<"\txorl "<<alias[3]<<", %ebp"<<endl;
      cout <<"\tmovl %ebp, (%esp)"<<endl;
      cout <<endl;
      cout <<"\tmovl "<<4*((i-16)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\txorl "<<4*((i-14)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\txorl "<<4*((i-8)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\txorl "<<4*((i-3)%16)<<"(%esi), %ebp"<<endl;
      if ( newSHA )
	cout <<"\troll $1, %ebp"<<endl;
      cout <<"\tmovl %ebp, "<<4*((i-16)%16)<<"(%esi)"<<endl;
      cout <<endl;
      cout <<"\tmovl "<<alias[0]<<", %ebp"<<endl;
      cout <<"\troll $5, %ebp"<<endl;
      cout <<"\taddl (%esp), %ebp"<<endl;
      cout <<"\taddl "<<alias[4]<<", %ebp"<<endl;
      cout <<"\taddl "<<4*((i-16)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\taddl $"<<int(0x6ed9eba1)<<", %ebp"<<endl;
      cout <<"\tmovl %ebp, "<<alias[4]<<endl;
      cout <<endl;
      cout <<"\troll $30, "<<alias[1]<<endl;
      cout <<endl;
     CirculateAlias();
    }

   for (int i=40; i<60; i++)
    {
      cout <<"\t// i="<<dec<<i<<endl;
      cout <<"\tmovl "<<alias[1]<<", %ebp"<<endl;
      cout <<"\torl "<<alias[2]<<", %ebp"<<endl;
      cout <<"\tandl "<<alias[3]<<", %ebp"<<endl;
      cout <<"\tmovl %ebp, (%esp)"<<endl;
      cout <<"\tmovl "<<alias[1]<<", %ebp"<<endl;
      cout <<"\tandl "<<alias[2]<<", %ebp"<<endl;
      cout <<"\torl (%esp), %ebp"<<endl;
      cout <<"\tmovl %ebp, (%esp)"<<endl;
      cout <<endl;
      cout <<"\tmovl "<<4*((i-16)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\txorl "<<4*((i-14)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\txorl "<<4*((i-8)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\txorl "<<4*((i-3)%16)<<"(%esi), %ebp"<<endl;
      if ( newSHA )
	cout <<"\troll $1, %ebp"<<endl;
      cout <<"\tmovl %ebp, "<<4*((i-16)%16)<<"(%esi)"<<endl;
      cout <<endl;
      cout <<"\tmovl "<<alias[0]<<", %ebp"<<endl;
      cout <<"\troll $5, %ebp"<<endl;
      cout <<"\taddl (%esp), %ebp"<<endl;
      cout <<"\taddl "<<alias[4]<<", %ebp"<<endl;
      cout <<"\taddl "<<4*((i-16)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\taddl $"<<int(0x8f1bbcdc)<<", %ebp"<<endl;
      cout <<"\tmovl %ebp, "<<alias[4]<<endl;
      cout <<endl;
      cout <<"\troll $30, "<<alias[1]<<endl;
      cout <<endl;
     CirculateAlias();
 }
 
    for (int i=60; i<80; i++)
    {
      cout <<"\t// i="<<dec<<i<<endl;
      cout <<"\tmovl "<<alias[1]<<", %ebp"<<endl;
      cout <<"\txorl "<<alias[2]<<", %ebp"<<endl;
      cout <<"\txorl "<<alias[3]<<", %ebp"<<endl;
      cout <<"\tmovl %ebp, (%esp)"<<endl;
      cout <<endl;
      cout <<"\tmovl "<<4*((i-16)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\txorl "<<4*((i-14)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\txorl "<<4*((i-8)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\txorl "<<4*((i-3)%16)<<"(%esi), %ebp"<<endl;
      if ( newSHA )
	cout <<"\troll $1, %ebp"<<endl;
      cout <<"\tmovl %ebp, "<<4*((i-16)%16)<<"(%esi)"<<endl;
      cout <<endl;
      cout <<"\tmovl "<<alias[0]<<", %ebp"<<endl;
      cout <<"\troll $5, %ebp"<<endl;
      cout <<"\taddl (%esp), %ebp"<<endl;
      cout <<"\taddl "<<alias[4]<<", %ebp"<<endl;
      cout <<"\taddl "<<4*((i-16)%16)<<"(%esi), %ebp"<<endl;
      cout <<"\taddl $"<<int(0xca62c1d6)<<", %ebp"<<endl;
      cout <<"\tmovl %ebp, "<<alias[4]<<endl;
      cout <<endl;
      cout <<"\troll $30, "<<alias[1]<<endl;
      cout <<endl;
      CirculateAlias();
    }

 delete[] alias[0];
 delete[] alias[1];
 delete[] alias[2];
 delete[] alias[3];
 delete[] alias[4];
 delete[] t;
}

