/*****************************************************************************
 * ARM Loader - Main Loop                                                    *
 *                                                                           *
 * Copyright (c) 2003 Rowley Associates Limited.                             *
 *                                                                           *
 * This file may be distributed under the terms of the License Agreement     *
 * provided with this software.                                              *
 *                                                                           *
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE   *
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
 *****************************************************************************/

#include "__armcps.h"
#include "__armlib.h"
#include "loader.h"

static int
loaderPeek(unsigned char *address, unsigned int length)
{
  unsigned int data;
  while(length)
    { 
      int i;             
      for(i = 4; i; --i)
        {
          data >>= 8;
          if(length)
            {
              data |= *address++ << 24;
              --length;
            }                      
        }
      loaderWriteWord(data);
    }
  return 1;
}

#ifdef VERIFY_USE_MEMCMP

static int
loaderVerify(unsigned char *address, unsigned int length)
{
  int result = 1;
  while(length)
    {
      unsigned int data = loaderReadWord();
      int i;
      for(i = 4; i && length; --i)
        {
          if (*address++ != (unsigned char)data)
            result = 0;
          data >>= 8;
          length--;
        }
    }
  return result;
}

#endif

void
C_Entry(void)
{
  loaderBegin();
  for(;;)
    {
      unsigned int ctrl, length;
      loaderWaitForCommand();                   
      ctrl = loaderReadWord(); 
      length = ctrl >> __CPS_CTRL_LENGTH_OFFSET;
      switch(ctrl & __CPS_CTRL_TAG_MASK)
        {
          case __CPS_TAG_POKE:
            loaderWriteWord(loaderPoke((unsigned char *)loaderReadWord(), length));
            break;
          case __CPS_TAG_PEEK:
#ifdef LOADER_FLUSH_WRITES
            loaderFlushWrites();
#endif
            loaderWriteWord(loaderPeek((unsigned char *)loaderReadWord(), length));
            break;
#ifdef VERIFY_USE_MEMCMP
          case __CPS_TAG_VERIFY:
#ifdef LOADER_FLUSH_WRITES
            loaderFlushWrites();
#endif
            loaderWriteWord(loaderVerify((unsigned char *)loaderReadWord(), length));
            break;
#endif
          case __CPS_TAG_MEMSET:
            loaderWriteWord(loaderMemset((unsigned char *)loaderReadWord(), length, (unsigned char)loaderReadWord()));
            break;
          case __CPS_TAG_ERASE:
            loaderWriteWord(loaderErase((unsigned char *)loaderReadWord(), length));
            break;
          case __CPS_TAG_ERASE_ALL:
            loaderWriteWord(loaderEraseAll());
            break;
          case __CPS_TAG_SET_PARAM:
            loaderWriteWord(loaderSetParameter(loaderReadWord(), loaderReadWord()));
            break;
          case __CPS_TAG_CRC32:
#ifdef LOADER_FLUSH_WRITES
            loaderFlushWrites();
#endif
            loaderWriteWord(__ARMLIB_crc32((const unsigned char *)loaderReadWord(), length));
            break;
          case __CPS_TAG_TERMINATE:
#ifdef LOADER_FLUSH_WRITES
            loaderFlushWrites();
#endif
            loaderEnd();
            loaderWriteWord(1);
            loaderWaitForCommand();
            return;
        }
    }
}

