/***************************************************************************
**  Name:  emumem.c
**
**  Description:
**     Michelle memory-group routines.
**     include:
**        "Read N bytes memory from Michelle -- emuReadMemN()"
**        "Write N bytes memory to Michelle  -- emuSetMemN()"
**        "Memory data comparing             -- emuCompare()"
**        "Memory data coping                -- emuCopy()"
**        "Memory data filling               -- emuFill()"
**        "Memory data testing               -- emuTest()"
**        "Memory data searching             -- emuSearch()"
**        "Memory data checksum             -- emuChecksum()"
**
**  Status:  preliminary
**
**  $Log:   S:/tbird/arcppc/fw/860/emumem.c_v  $
** 
**    Rev 1.6   19 Mar 1998 13:26:06   hera
** For ID239
** 
**    Rev 1.5   20 Nov 1997 11:13:26   kevin
** Fixed EmuTest()
** 
**    Rev 1.4   29 Oct 1997 14:03:38   kevin
** warning-free version
** 
**    Rev 1.3   28 Aug 1997 10:22:50   cjchen
** 
**    Rev 1.2   19 Aug 1997 16:02:22   cjchen
** 
**    Rev 1.1   28 Jul 1997 10:09:00   cjchen
** 
**    Rev 1.0   18 Jul 1997 15:12:56   cjchen
** Initial revision.
** 
**    Rev 1.0   11 Feb 1997 16:16:54   kevin
** Initial revision.
** 
**    Rev 1.3   25 Jun 1996 11:12:22   gene
** 
**    Rev 1.2   11 Jun 1996 17:38:36   gene
** 
**    Rev 1.1   11 Jun 1996 09:48:42   gene
** changed BDMTemp -> BDMTempB
** 
**    Rev 1.0   03 Jun 1996 14:19:04   gene
** Initial revision.
**
** Copyright (C) 1992 Microtek International, Inc.
**
****************************************************************************/

                   /****************************
                   *                           *
                   *       INCLUDE FILES       *
                   *                           *
                   ****************************/

#ifndef _EMU_MEM_
#include "emumem.h"
#endif

#ifndef _EMU_BASE_TYPES_
#include "emutypes.h"
#endif

#ifndef _EMU_LIB_
#include "emulib.h"
#endif

#ifndef _LLFW_
#include "emullfw.h"
#endif

#ifndef _EMU_EXTERNAL_
#include "emuext.h"
#endif

#include <string.h>
#include <stdio.h>

                   /****************************
                   *                           *
                   *     LOCAL DEFINITIONS     *
                   *                           *
                   ****************************/
#define RET_ADDR_LEN     8
#define DATA_BUFFER_LEN  0x400
U32 gMemAddr;
U32 gSDMemAddr[2];
extern U32 brokeReason;
extern U8 brokeResult;
                   /****************************
                   *                           *
                   *    EXTERNAL VARIABLES     *
                   *                           *
                   ****************************/

                   /****************************
                   *                           *
                   *     LOCAL PROTOTYPES     *
                   *                           *
                   ****************************/
STATUS ReadMem(ADDR *addr, U8 *buff, U16 len);
STATUS WriteMem(ADDR *addr, U16 dataLen, U8 *buff);
STATUS FillMem(ADDR *addr, U32 addrLen, U8 *buff, U16 len, U16 size, U16 verifyFlag);

                   /***************************
                   *                          *
                   *      EXECUTABLE CODE     *
                   *                          *
                   ****************************/

/***************************************************************************
**
**  ReadMem
**
**  Description: Read a chunk memory from "addr" location.
**         Note: The data length maximum - 0x100
**
**  Parameters:
**     input:
**        addr -- unsigned long
**        len  --
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on emulator" -- Fatal HW error; check status-code
**
**        return data -- "length" + "N bytes data string"
**
****************************************************************************/
STATUS ReadMem(ADDR *addr, U8 *buff, U16 dataLen) {
   U16 size;
   STATUS status;
   BOOLEAN procTail = FALSE;
   U8  *buffPtr;
   U16 len,mod;
   U32 swapAddr;

   swapAddr=addr->pos;
   Swap((U8*)&swapAddr,4);
   if ((status = AccessIceFlag(READ_ONE,SIZE_FLAG,&size)) != GOOD)
      return status;

   if (size == S_BYTE)
      status = DumpByteMem(swapAddr,dataLen,buff);
   else {
      if (size == S_HALFWORD)
         len = 2;
      else
         len = 4;

      buffPtr = buff;
      mod = (U16)addr->pos % len;
      if ((len-mod) > dataLen)
         len = dataLen + mod;  // Let dataLen==len-mod
      if (mod) {
         status = DumpByteMem(swapAddr,len-mod,buffPtr);
         dataLen=dataLen-(len-mod);
         buffPtr=buffPtr-mod+len;
         addr->pos=addr->pos-mod+len;
      }

      mod = dataLen % len;
      if (mod)
         dataLen=dataLen-mod;

      if (!status && dataLen != 0) {
         swapAddr=addr->pos;
         Swap((U8*)&swapAddr,4);
         if (size == S_HALFWORD)
            status = DumpHalfWordMem(swapAddr,dataLen,buffPtr);
         else
            status = DumpWordMem(swapAddr,dataLen,buffPtr);
         buffPtr += dataLen;
         addr->pos += dataLen;
      }
      if ( mod && !status)
         status = DumpByteMem(addr->pos,mod,buffPtr);
   }
   return(status);
}

STATUS processHeadPos(ADDR *addr, U16 *dataLen, U8 **buff,U16 verifyFlag,
          BOOLEAN *processTail,U32 *ptr) {
   STATUS status = GOOD;
   U8     tmpBuff[4];
   U16    size,len,mod,i;
   U32    swapAddr;

   AccessIceFlag(READ_ONE,SIZE_FLAG,&size);
   if (size == S_BYTE) // should not happen
      len=1;
   else if (size == S_HALFWORD)
      len=2;
   else
      len=4; //S_WORD

   mod=(U16)addr->pos % len;
   if (mod) { // process head, len!=1
      swapAddr=addr->pos-mod;
      Swap((U8*)&swapAddr,4);
      DumpByteMem(swapAddr,mod,tmpBuff);
      for (i=mod;i<len;i++)
          tmpBuff[i]=(*buff)[i-mod];
      if (len==2)
         status = FillHalfWordMem(swapAddr,len,len,tmpBuff,verifyFlag,ptr) & 0xff;
      else
         status = FillWordMem(swapAddr,len,len,tmpBuff,verifyFlag,ptr) & 0xff;
      addr->pos=addr->pos-mod+len;
      if (*dataLen > (len-mod))
         (*dataLen) -= (len-mod);
      else
         (*dataLen) = 0;
      //(*buff)=(*buff)-(len-mod);
      (*buff) = (*buff)+(len-mod); //Hera 3/19/98
   }

   return(status);
}

STATUS processTailPos(ADDR *addr,U8 *buff,U8 mod,U16 verifyFlag,U32 *ptr) {
   STATUS status = GOOD;
   U8     tmpBuff[4];
   U16    size,len,i;
   U32    swapAddr;

   if (mod == 0)
      return(GOOD);

   AccessIceFlag(READ_ONE,SIZE_FLAG,&size);
   if (size == S_BYTE)
      len=1;  // it should not be happened
   else if (size == S_HALFWORD)
      len=2;
   else
      len=4; //S_WORD

   swapAddr=addr->pos+mod;
   Swap((U8*)&swapAddr,4);
   DumpByteMem(swapAddr,len-mod,&tmpBuff[mod]);
   for (i=0;i<mod;i++)
      tmpBuff[i] = buff[i];
   swapAddr=addr->pos;
   Swap((U8*)&swapAddr,4);
   if (len == 2)
      status = FillHalfWordMem(swapAddr,len,len,tmpBuff,verifyFlag,ptr) & 0xff;
   else  // S_WORD
      status = FillWordMem(swapAddr,len,len,tmpBuff,verifyFlag,ptr) & 0xff;

   return(status);
}

/***************************************************************************
**
** WriteMem
**
**  Description: Read a chunk memory from "addr" location.
**         Note: The data length maximum - 0x100
**
**  Parameters:
**     input:
**        addr -- unsigned long
**        len  --
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on emulator" -- Fatal HW error; check status-code
**
**        return data -- "length" + "N bytes data string"
**
**  NOTE: if interFlag is on, it will not check verifyFlag at all.
****************************************************************************/
STATUS WriteMem(ADDR *addr, U16 dataLen, U8 *buff) {
   U16 verifyFlag, size;
   //U16 lp;
   STATUS status;
   U32 length,swapAddr,infoPtr[4];
   BOOLEAN processTail = FALSE;
   U16 tempDataLen, mod, len;

   status = GOOD;
   length = (U32)dataLen;
   AccessIceFlag(READ_ONE,VERIFY_FLAG,&verifyFlag);
   AccessIceFlag(READ_ONE,SIZE_FLAG,&size);
   tempDataLen=dataLen;
   swapAddr=addr->pos;
   Swap((U8*)&swapAddr,4);

   if (size == S_BYTE)
      status = FillByteMem(swapAddr,dataLen,dataLen,
                  buff,verifyFlag,infoPtr) & 0xff;
   else {
      if (size == S_HALFWORD)
         len = 2;
      else
         len = 4;

      status = processHeadPos(addr,&dataLen,&buff,verifyFlag,&processTail,infoPtr);
      mod = dataLen % len;
      dataLen = dataLen - mod;
      if (!status && dataLen != 0) {
         swapAddr=addr->pos;
         Swap((U8*)&swapAddr,4);
         if (size == S_HALFWORD)
            status = FillHalfWordMem(swapAddr,dataLen,
                    dataLen,buff,verifyFlag,infoPtr) & 0xff;
         else
            status = FillWordMem(swapAddr,dataLen,
                    dataLen,buff,verifyFlag,infoPtr) & 0xff;
      }
      addr->pos += dataLen;
      if ( mod && !status)
         status = processTailPos(addr,buff+dataLen,(U8)mod,verifyFlag,infoPtr);
   }

   if (status==1) { // has some problem
      gMemAddr=infoPtr[0];
      gSDMemAddr[0]=infoPtr[1];
      gSDMemAddr[1]=infoPtr[2];
      Swap((U8*)&gMemAddr,4);
      Swap((U8*)&gSDMemAddr[0],4);
      Swap((U8*)&gSDMemAddr[1],4);
   }
   return(status);
}

/***************************************************************************
**
**  EmuReadMemN
**
**  Description: Michelle memory-group routine, to read a chunk memory
**               from "addr" location.
**         Note: The data length maximum - 0x100
**
**  Parameters:
**     input:
**        addr -- unsigned long
**        len  --
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on emulator" -- Fatal HW error; check status-code
**
**        return data -- "length" + "N bytes data string"
**
****************************************************************************/
VOID EmuReadMemN(ADDR *addr, U16 addrLen) {
   STATUS status;
   U8 dataLen,memBuff[MAX_STREAM_LEN];
   //U32 m68Reg[MAX_CPU_REG_NO];

   status = GOOD;
   if (addrLen > MAX_STREAM_LEN-4) {
      OutputStatus(LEN_TOO_LONG,ON);
      return;
   }
   status = ReadMem(addr,memBuff,(U16)addrLen);

//     return al --> 0:ok/1:access fail
   if (status==1) {
      brokeResult = EPStatus(&brokeReason);
      OutputExceptReason(OFF);
      OutEnd();
   } else {
      OutputStatus(status,OFF);
      dataLen = (U8)(addrLen & 0xFF);
      OutData(dataLen,memBuff,ON);
      OutEnd();
   }
}
/****************************************************************************
**
**  EmuSetMemN
**
**  Description: Michelle memory-group routine, to write a chunk data
**               from "buff" to "addr" location. The driver program can
**               use this function to implement to download code from a
**               file.
**               The length should be limitted up to 1024 bytes(1KB).
**         Note: if the set area is not in the internal register area
**               then do: ModifyRegister();
**                          set memory
**                        RestoreRegister();
**               else set memory only.
**
**  Parameters:
**     input:
**        addr  -- unsigned long,
**        *buff -- unsigned char,
**        len   -- int
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on emulator" -- Fatal HW error; check status-code
**
**
****************************************************************************/
VOID EmuSetMemN(ADDR *addr, U8 *buff, U16 len) {
   STATUS status;
   //ADDR addr2;
   //U16 Len1, Len2;

   status = GOOD;
   if (len > MAX_STREAM_LEN-4) {
      OutputStatus(LEN_TOO_LONG,ON);
      return;
   }
   else if (len == 0) {
      OutputStatus(LEN_EQUAL_ZERO,ON);
      return;
   }

   status = WriteMem(addr,len,buff);

//    return al --> 0:ok
//                  1:verfy not ok ,    fail addr -> Info[0]
//                                 expected data -> Info[1]
//                                 actual   data -> Info[2]
//                  2:access fail

   if (status==1) {
      OutputStatus(ERROR_WRITE,OFF);
      OutData(4,&gMemAddr,ON);
      OutData(RET_ADDR_LEN,gSDMemAddr,ON);
      OutEnd();
   }
   else if (status==2) {
      brokeResult = EPStatus(&brokeReason);
      OutputExceptReason(OFF);
      OutEnd();
   } else {
      OutputStatus(GOOD,ON);
      OutEnd();
   }
}

/***************************************************************************
**
** EmuCompare
**
**  Description: Michelle memory-group routine, to compare two memory
**               blocks.
**               Return the locations and its contents, if there has
**               difference.
**               The "addr1" is the start addres of the first block.
**               The "addrLen" is the addres length of the first block.
**               The "addr2" is the start address of the second block.
**
**  Parameters:
**     input:
**        addr1 -- unsigned long,
**        addrLen -- unsigned long,
**        addr2 -- unsigned long
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on emulator" -- Fatal HW error; check status-code
**
**        return data -- "length" + "location" + "contents"
**
****************************************************************************/
VOID EmuCompare(ADDR *addr1, U32 addrLen, ADDR *addr2) {
   STATUS status;
   U16 size;
   U32 infoPtr[4];
   U32 swapAddr1, swapAddr2;
   U32 tempAddr[4];

   AccessIceFlag(READ_ONE,SIZE_FLAG,&size);
   switch ((SIZE)size) {
      case S_HALFWORD :
         ReduceEven(addr1->pos);
         IncreaseEven(addrLen);
         ReduceEven(addr2->pos);
         break;
      case S_WORD :
         ReduceQuad(addr1->pos);
         IncreaseQuad(addrLen);
         ReduceQuad(addr2->pos);
         break;
   }
   swapAddr1=addr1->pos;
   Swap((U8*)&swapAddr1,4);
   swapAddr2=addr2->pos;
   Swap((U8*)&swapAddr2,4);
   status = CompareMem(swapAddr1,addrLen,
           swapAddr2,size,infoPtr) & 0xff;

//            0  --- OK, Match
//            1  --- Not Match & put not matching
//                   addr1 -> Info[0] ,data1 -> Info[1]
//                   addr2 -> Info[2] ,data2 -> Info[4]
//            2  --- Block 1 Not Ready ( check ep_status r1 )
//            3  --- Block 2 Not Ready ( check ep_status r30 )

   switch (status) {
      case 0 :
         OutputStatus(NO_DIFF,ON);
         break;
      case 1 :
         OutputStatus(GOOD,OFF);
         tempAddr[0]=infoPtr[0];
         tempAddr[1]=infoPtr[1];
         tempAddr[2]=infoPtr[2];
         tempAddr[3]=infoPtr[3];
         Swap((U8*)&tempAddr[0],4);
         Swap((U8*)&tempAddr[1],4);
         Swap((U8*)&tempAddr[2],4);
         Swap((U8*)&tempAddr[3],4);
         OutData(RET_ADDR_LEN*2,tempAddr,ON);
         break;
      case 2 :
      case 3 :
         brokeResult = EPStatus(&brokeReason);
         OutputExceptReason(OFF);
         break;
      default :
         OutputExceptReason(ON);
   }
   OutEnd();
}

/***************************************************************************
**
**  EmuCopy
**
**  Description: Michelle memory-group routine, to copy a memory block
**               data to another block's.
**               The "addr1" and "addr2" is the addres range of the
**               first block.
**               The "addr3" is the start address of the destination
**               block.
**
**         Note: If the range is partial in the internal register area
**               then reduce the length and do:
**                     ModifyRegisterCS()
**                     copy command
**                     RestoreRegisterCS()
**               If one of the source area or destination area is all in the
**               internal register area then don't do copy.
**  Parameters:
**     input:
**        addr1 -- unsigned long,
**        addr2 -- unsigned long,
**        addr3 -- unsigned long
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on Emulator" -- Fatal HW error; check status-code
**
**
****************************************************************************/
VOID EmuCopy(ADDR *addr1, U32 addrLen, ADDR *addr2) {
   STATUS status;
   U16 size,verifyFlag;
   U32 *ptr;
   U32 swapAddr1,swapAddr2;
//   U32 tempAddr[2];
   
   status = GOOD;
   AccessIceFlag(READ_ONE,SIZE_FLAG,&size);
   AccessIceFlag(READ_ONE,VERIFY_FLAG,&verifyFlag);
   switch ((SIZE)size) {
      case S_HALFWORD :
         ReduceEven(addr1->pos);
         IncreaseEven(addrLen);
         ReduceEven(addr2->pos);
         break;
      case S_WORD :
         ReduceQuad(addr1->pos);
         IncreaseQuad(addrLen);
         ReduceQuad(addr2->pos);
         break;
   }

   swapAddr1=addr1->pos;
   Swap((U8*)&swapAddr1,4);
   swapAddr2=addr2->pos;
   Swap((U8*)&swapAddr2,4);
   status = CopyMem(swapAddr1,addrLen,
       swapAddr2,size,ptr) & 0xff;

//        0  --- OK,
//        1  --- Block 1 fail
//        2  --- Block 2 fail
   if (status!=0) {
      brokeResult = EPStatus(&brokeReason);
      OutputExceptReason(OFF);
      OutEnd();
   } else {
      OutputStatus(GOOD,OFF);
      OutEnd();
   }
}

/***************************************************************************
**
**  FillMem
**
**  Description: Fill a memory range with a specified pattern.
**               Data pattern is specified in "buff" array.
**               The lengh of the data pattern is "len".
**
**  Parameters:
**     input:
**        addr -- unsigned long(address), int (space)
**        addrLen -- unsigned long,
**        *buff -- unsigned char, Max 16 bytes;
**        len   -- int
**        size --int
**        verifyFlag -- int
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on Emulator" -- Fatal HW error; check status-code
**
**
****************************************************************************/
STATUS FillMem(ADDR *addr, U32 addrLen, U8 *buff, U16 len, U16 size, U16 verifyFlag) {
STATUS status=GOOD;
U16 accessSize,mod1,mod2;
//U16 pos;
U32 swapAddr;
U32 infoPtr[4];
   //switch ((SIZE)size) {
   //   case S_BYTE :
   //      status = FillByteMem(addr->pos,addrLen,len,buff,verifyFlag) & 0xff;
   //      break;
   //   case S_HALFWORD :
   //      status = FillHalfWordMem(addr->pos,addrLen,len,buff,verifyFlag) & 0xff;
   //      break;
   //   case S_WORD :
   //      status = FillWordMem(addr->pos,addrLen,len,buff,verifyFlag) & 0xff;
   //      break;

   if (size == S_BYTE) {
      swapAddr=addr->pos;
      Swap((U8*)&swapAddr,4);
      status = FillByteMem(swapAddr,addrLen,len,
                  buff,verifyFlag,infoPtr) & 0xff;
   } else {
         if (size == S_HALFWORD)
            accessSize = 2;
         else
            accessSize = 4;
         mod1 = (U16)addrLen % accessSize;
         if (addrLen != 0) {
            swapAddr=addr->pos;
            Swap((U8*)&swapAddr,4);
            if (size == S_HALFWORD)
                status = FillHalfWordMem(swapAddr,addrLen-mod1,
                            len,buff,verifyFlag,infoPtr) & 0xff;
            else
                status = FillWordMem(swapAddr,addrLen-mod1,
                            len,buff,verifyFlag,infoPtr) & 0xff;
         }
         if (mod1) {
            mod2 = ((U16)addrLen-mod1) % len;
            while ((mod1>0) && (status==GOOD)) {
               swapAddr=addr->pos+addrLen-mod1;
               Swap((U8*)&swapAddr,4);
               status = FillByteMem(swapAddr,1,1,
                           &buff[mod2],verifyFlag,infoPtr) & 0xff;
               mod1--;
               //addrLen--;
               mod2++;
               if (mod2==len)
                  mod2=0;
            }
         }
     }
         //if (addrLen != 0)
         //   status = FillWordMem(addr->pos,addrLen,
         //               len,buff,verifyFlag) & 0xff;
         //break;
//      default :
//         status = FillByteMem(addr->pos,addrLen,len,buff,verifyFlag) & 0xff;
//         break;
//   }

   if (status==1) {
      gMemAddr=infoPtr[0];
      gSDMemAddr[0]=infoPtr[2];
      gSDMemAddr[1]=infoPtr[1];
      Swap((U8*)&gMemAddr,4);
      Swap((U8*)&gSDMemAddr[0],4);
      Swap((U8*)&gSDMemAddr[1],4);
   }

   return(status);
}
/***************************************************************************
**
**  EmuFill
**
**  Description: Michelle memory-group routine, to fill a memory range
**               with a specified pattern.
**               Fill a memory range with a specified pattern.
**               Data pattern is specified in "buff" array.
**               The lengh of the data pattern is "len".
**
**  Parameters:
**     input:
**        addr1 -- unsigned long,
**        addr2 -- unsigned long,
**        *buff -- unsigned char, Max 16 bytes;
**        len   -- int
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on Emulator" -- Fatal HW error; check status-code
**
** 
****************************************************************************/
VOID EmuFill(ADDR *addr, U32 addrLen, U8 *buff, U16 len) {
   STATUS status;
   U16 size;
   //U32 m68Reg[MAX_CPU_REG_NO];
   U16 verifyFlag;

   status = GOOD;
   AccessIceFlag(READ_ONE,SIZE_FLAG,&size);
   AccessIceFlag(READ_ONE,VERIFY_FLAG,&verifyFlag);

   status = FillMem(addr,addrLen,buff,len,size,verifyFlag);

//     return al --> 0:ok
//                   1:verfy not ok ,    fail addr -> Info[0]
//                                  expected data -> Info[1]
//                                  actual   data -> Info[2]
//                   2:access fail

   if (status==1) {
      OutputStatus(ERROR_WRITE,ON);
      OutData(4,&gMemAddr,OFF);
      OutData(RET_ADDR_LEN,gSDMemAddr,OFF);
      OutEnd();
   }
   else if (status==2) {
      brokeResult = EPStatus(&brokeReason);
      OutputExceptReason(OFF);
      OutEnd();
   } else
      OutputStatus(GOOD,OFF);
}

/***************************************************************************
**
**  EmuTest
**
**  Description: Michelle memory-group routine, to test a spcified
**               address range working O.K. or not? Is RAM or not?
**         Note: If the range is partial in the internal register area
**               then reduce the length and do:
**                     ModifyRegisterCS()
**                     copy command
**                     RestoreRegisterCS()
**               If one of the source area or destination area is all in the
**               internal register area then don't do copy (InterFlag=YES).
**
**  Parameters:
**     input:
**        addr1 -- unsigned long,
**        addr2 -- unsigned long,
**
**    *** *pattern[n] -- char ===> optional
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on Emulator" -- Fatal HW error; check status-code
**
**  NOTE: I have three ways to do this testing, you can decide how
**        to implement it by one of these.
**        1. (Read data from specified address location) -->
**           (Write pre-read data back to the same memory location) -->
**           (Compare these result then check it to report the status)
**        2. Write the defined special data pattern to the specified
**           memory loaction, then check the virolation.
**        3. Like method 2, but driver can select the "data pattern"
**           as she like. In this case, to add a parameter to indicate
**           the data pattern is necessary.
**
****************************************************************************/
VOID EmuTest(ADDR *addr, U32 addrLen) {
   STATUS status = GOOD;
   U16 size;
   U32 infoPtr[2], swapAddr;

   AccessIceFlag(READ_ONE,SIZE_FLAG,&size);
   switch ((SIZE)size) {
      case S_HALFWORD :
         ReduceEven(addr->pos);
         IncreaseEven(addrLen);
         break;
      case S_WORD :
         ReduceQuad(addr->pos);
         IncreaseQuad(addrLen);
         break;
   }
   swapAddr = addr->pos;
   Swap((U8*)&swapAddr,4);
   status = TestMem(swapAddr,addrLen,size,infoPtr) & 0xff;

//            0  --- OK,
//            1  --- mem err ( value written isn't same value read ) ;
//                     err addr -> Info[0]
//            2  --- fail

   if (status == 0)
      OutputStatus(GOOD,ON);
   else if (status == 1) {
      OutputStatus(TEST_FAIL,OFF);
      swapAddr = infoPtr[0];
      Swap((U8*)&swapAddr,4);
      OutData(4,&swapAddr,ON);
      OutEnd();
   } else {
      brokeResult = EPStatus(&brokeReason);
      OutputExceptReason(OFF);
      OutEnd();
   }
}

/***************************************************************************
**
**  EmuSearch
**
**  Description: Michelle memory-group routine, to search data pattern
**               in the specified address range.
**               Data pattern is specified in "buff" array.
**               The lengh of the data pattern is "len".
**
**  Parameters:
**     input:
**        addr1 -- unsigned long,
**        addr2 -- unsigned long,
**        *buff -- unsigned char,  Max 32 Bytes;
**        len   -- int
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on Emulator" -- Fatal HW error; check status-code
**
**
****************************************************************************/
VOID EmuSearch(ADDR *addr, U32 addrLen, U8 *buff, U16 len) {
#define MATCH  0xff /* template data, it will redefine. */
   STATUS status = GOOD;
   U32 infoPtr[4];
   U32 swapAddr1;
//   char tempAddr[2][8];

   swapAddr1=addr->pos;
   Swap((U8*)&swapAddr1,4);
   status = SearchMem(swapAddr1,addrLen,len,buff,infoPtr) & 0xff;

//       0  --- OK (found) , found address -> infoPtr
//       1  --- Not found
//       2  --- failure , check EPStatus
   if (status==0) {
      OutputStatus(GOOD,OFF);
      Swap((U8*)infoPtr,4);
      OutData(RET_ADDR_LEN,infoPtr,ON);
      OutEnd();
   }
   else if (status==1)
      OutputStatus(NO_FOUND,ON);
   else {
      brokeResult = EPStatus(&brokeReason);
      OutputExceptReason(OFF);
      OutEnd();
   }
}

/***************************************************************************
**
**  EmuChecksum
**
**  Description: Michelle memory-group routine, to caculate the data
**               sum value of the specified address range.
**               The "addr1" and "addr2" is the address range.
**               The "size" is the sum-width = 0 --> caculate in byte
**                                           = 1 --> caculate in word
**                                           = 2 --> caculate in long word
**
**  Parameters:
**     input:
**        addr1 -- unsigned long,
**        addr2 -- unsigned long,
**        size  -- int
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on Emulator" -- Fatal HW error; check status-code
**
**
****************************************************************************/
VOID EmuChecksum(ADDR *addr, U32 addrLen) {
   U16 size;
//   U16 checksumData;
   STATUS status;
   U32 infoPtr[4];
   U32 swapAddr;
//   char tempAddr[2][8];


   AccessIceFlag(READ_ONE,SIZE_FLAG,&size);
   if (size == S_HALFWORD) {
      ReduceEven(addr->pos);
      IncreaseEven(addrLen);
   }
   if (size == S_WORD) {
      ReduceQuad(addr->pos);
      IncreaseQuad(addrLen);
   }
   swapAddr=addr->pos;
   Swap((U8*)&swapAddr,4);
   status = CheckSum(swapAddr,addrLen,size,infoPtr);

//        0  --- OK, checksum value -> Info[0]
//        1  --- fail ;
   if (status == 0) {
      OutputStatus(GOOD,OFF);
      Swap((U8*)&infoPtr[0],4);
      OutData(4,&infoPtr[0],ON);
      OutEnd();
   }
   else {
      brokeResult = EPStatus(&brokeReason);
      OutputExceptReason(OFF);
      OutEnd();
   }
}
/***************************************************************************
**
**  EmuGetUpm
**
**  Description: Michelle memory-group routine, to caculate the data
**               sum value of the specified address range.
**               The "addr1" and "addr2" is the address range.
**               The "size" is the sum-width = 0 --> caculate in byte
**                                           = 1 --> caculate in word
**                                           = 2 --> caculate in long word
**
**  Parameters:
**     input:
**        addr1 -- unsigned long,
**        addr2 -- unsigned long,
**        size  -- int
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on Emulator" -- Fatal HW error; check status-code
**
**
****************************************************************************/
VOID EmuGetUpm(U16 upmNum, U16 upmAddr, U16 len, U32 *ptrBuff) {
STATUS status;
//U32 dataLen;
U32 buff[35];

   status=DumpUPM(upmNum,upmAddr,len,buff);
//              0  --- OK
//              1  --- fail
   if (status == 0) {
      OutputStatus(GOOD,OFF);
      OutData((U8)(4*len),buff,ON);
      OutEnd();
   }
   else {
      brokeResult = EPStatus(&brokeReason);
      OutputExceptReason(OFF);
      OutEnd();
   }
}

/***************************************************************************
**
**  EmuSetUpm
**
**  Description: Michelle memory-group routine, to caculate the data
**               sum value of the specified address range.
**               The "addr1" and "addr2" is the address range.
**               The "size" is the sum-width = 0 --> caculate in byte
**                                           = 1 --> caculate in word
**                                           = 2 --> caculate in long word
**
**  Parameters:
**     input:
**        addr1 -- unsigned long,
**        addr2 -- unsigned long,
**        size  -- int
**
**     output:
**        return status code(error-code) in to the output processor.
**        "O.K." -- Normal return
**        "Fatal error on Emulator" -- Fatal HW error; check status-code
**
**
****************************************************************************/
VOID EmuSetUpm(U16 upmNum, U16 upmAddr, U32 value) {
STATUS status;

   status=FillUPM(upmNum,upmAddr,value);
//              0  --- OK
//              1  --- fail
   if (status == 0)
      OutputStatus(GOOD,ON);
   else {
      brokeResult = EPStatus(&brokeReason);
      OutputExceptReason(ON);
   }
}

/******************************** E O F ***********************************/

