/***************************************************************************
**
**  Name:  emulib.c
**
**  Description:
**     Michelle library routines.
**
**  Status:  preliminary
**
**  $Log:   S:/tbird/arcppc/fw/603e/emulib.c_v  $
** 
**    Rev 1.0   11 Feb 1997 16:16:52   kevin
** Initial revision.
** 
**    Rev 1.2   17 Dec 1996 15:07:56   gene
** 
**    Rev 1.1   17 Dec 1996 10:02:56   gene
** added ExchangeHighLow2/ExchangeHighLow4
** 
**    Rev 1.0   03 Jun 1996 14:18:56   gene
** Initial revision.
** 
** Copyright (C) 1992 Microtek International, Inc.
**
****************************************************************************/

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

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

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

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

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

#include <string.h>
#include <dos.h>
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/
STATIC U32 baseRegBuf[MAX_BASE_REG_NO];
STATIC U16 lfwFlagArray[MAX_LLFW_FLAG_NO];
STATIC U16 signals;
STATIC U16 statusFlag[MAX_STATUS_FLAG_NO];
U16 iceFlagArray[MAX_ICE_FLAG_NO];

                        /****************************
                         *                          *
                         *    EXTERNAL VARIABLES    *
                         *                          *
                         ****************************/

                        /****************************
                         *                          *
                         *     LOCAL PROTOTYPES     *
                         *                          *
                         ****************************/

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

/****************************************************************************
**
**  OutData
**
**  Description:
**
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
VOID OutData(U8 dataLen, VOID *data, BOOLEAN lenFlag) {
   if (lenFlag) outputStream[outputStreamLen++] = dataLen;
   memcpy(&outputStream[outputStreamLen],data,dataLen);
   outputStreamLen += dataLen;
}

/****************************************************************************
**
**  OutMultipleData
**
**  Description:
**
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
VOID OutMultipleData(U8 dataLen, VOID *data, U8 times) {
   outputStream[outputStreamLen++] = dataLen;
   memcpy(&outputStream[outputStreamLen],data,dataLen*times);
   outputStreamLen += dataLen*times;
}

/****************************************************************************
**
**  CheckViolation
**
**  Description:
**
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
STATUS CheckViolation(VOID) {
STATUS status;
U16 memBreak;

   status = GOOD;
//   memBreak = (RdViolFlg() & 3);
   switch (memBreak) {
     case 0 :
        status = VIOL_HALT;break;
     case 1 :
        status = MEM_GUARD; break;
     case 2 :
        status = MEM_PROTECT; break;
     case 3 :
        status = GOOD;
   }
   return(status);
}
/****************************************************************************
**
**  StopRun
**
**  Description:
**
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
VOID StopRun(VOID) {
//   U8 emOnstatus;
   U16 flyFlag;  //,cnt0,cnt1;
//   U16 traceing;
   U32 baseReg[MAX_BASE_REG_NO];
   //U32 tmpCnt;

   if (!EPstatus(baseReg)) { // gene
      StopEP(baseReg); /* llfw */
      AccessIceFlag(WRITE_ONE,RUNNING,&C_OFF);
      AccessIceFlag(READ_ONE,FLYING,&flyFlag);
//      Exbp1Disable(); // 11/8/93
//      Exbp2Disable(); // 11/8/93
//     AccessIceFlag(READ_ONE,TRACEING,&traceing);
/*
      if (traceing && mtatExist && (flyFlag == OFF)) {
         ProgramTMANStatic(&traceBufNo,&tmpCnt);
         AccessIceFlag(WRITE_ONE,TRACEING,&C_OFF);
         cnt1 = HighWord(tmpCnt);
         cnt0 = LowWord(tmpCnt);
         AccessIceFlag(WRITE_ONE,TRACED_BUFF_NO,&traceBufNo);
         AccessIceFlag(WRITE_ONE,COUNTER1,&cnt1);
         AccessIceFlag(WRITE_ONE,COUNTER0,&cnt0);
      }
*/
   }

}

/****************************************************************************
**
**  AddSegAddr
**
**  Description:
**
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
U32 AddSegAddr(U32 addr, U32 len) {
U32 segment,offset,modLen,count,segLen = 0xffff;

   count = len / segLen;
   modLen = len % segLen;
   segment = addr & 0xffff0000;
   segment += 0x10000000 * count;
   offset =  (addr & 0x0000ffff) + modLen;
   addr = segment + (offset & 0x0000ffff);
   if (offset >= 0x10000) addr += 0x10000000;
   return(addr);
}


U32 AddSegAddr2(U32 addr, U16 len) {
U32 segment,offset;

   segment = addr & 0xffff0000;
   offset =  (addr & 0x0000ffff) + len;
   addr = segment + (offset & 0x0000ffff);
   if (offset >= 0x10000) addr += 0x10000000;
   return(addr);
}
/****************************************************************************
**
**  AccessIceFlag
**
**  Description:
**
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
STATUS AccessIceFlag(ACCESS_MODE accessMode, ICE_FLAG flagName, U16 *value) {
register lp;
   switch (accessMode) {
      case READ_ONE :
         *value = iceFlagArray[flagName];
         break;
      case WRITE_ONE :
         iceFlagArray[flagName] = *value;
         break;
      case CLEAR_ONE :
         iceFlagArray[flagName] = 0;
         break;
      case CLEAR_ALL :
         for (lp = 0;lp < MAX_ICE_FLAG_NO; lp++)
            iceFlagArray[lp] = 0;
         break;
      default :
         return(ACCESS_ERROR);
   }
   return(GOOD);
}

/****************************************************************************
**
**  AccesstatusFlag
**
**  Description:
**
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
STATUS AccessStatusFlag
      (ACCESS_MODE accessMode, STATUS_FLAG statusName, U16 *flagNo) {
U16 lp;

   switch (accessMode) {
      case READ_ONE :
         *flagNo = (statusFlag[statusName] >> *flagNo) & maskBit;
         break;
      case WRITE_ONE :
         statusFlag[statusName] = statusFlag[statusName] | (maskBit << *flagNo);
         break;
      case CLEAR_ONE :
         statusFlag[statusName] = statusFlag[statusName] & ~(maskBit << *flagNo);
         break;
      case CLEAR_ALL :
         for (lp = 0; lp < MAX_STATUS_FLAG_NO; lp++)
            statusFlag[lp] = 0;
         break;
      default :
         return(ACCESS_ERROR);
   }
   return(GOOD);
}

/****************************************************************************
**
**  AccessBaseReg
**
**  Description: Access register : SS,CS,IP,FS and Timer 0,1,2 from buffer.
**               Note : Before Access, it must check hardware data to save in
**                      buffer.
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
STATUS AccessBaseReg
       (ACCESS_MODE accessMode, BASE_REG regName, U32 *value) {
   STATUS status = GOOD;

   switch (accessMode) {
      case READ_ONE :
         *value = baseRegBuf[regName];
         break;
      case READ_ALL :
         memcpy(value,baseRegBuf,sizeof(baseRegBuf)); // SP,PC
         break;
      case WRITE_ONE :
         baseRegBuf[regName] = *value;
         if (regName == BREG_SP)
            status = WriteReg(R_A7,*value);
         else
            status = WriteReg(R_PC,*value);
         break;
      case WRITE_ALL :
         memcpy(baseRegBuf,value,sizeof(baseRegBuf));
         status = WriteReg(R_A7,baseRegBuf[BREG_SP]);
         status |= WriteReg(R_PC,baseRegBuf[BREG_PC]);
         break;
      case FW_WRITE_ALL :
         memcpy(baseRegBuf,value,sizeof(baseRegBuf));
         break;
      default :
         return(ACCESS_ERROR);
   }
   if (status) status = ACCESS_ERROR;
   return(status);
}

/****************************************************************************
**
**  AccessCpuReg
**
**  Description: Access register from CPU.
**
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
STATUS AccessCpuReg
       (ACCESS_MODE accessMode, CPU_REG regName, U32 *value) {
//   U16 reg_num;
   STATUS status = GOOD;

   if (regName >= MAX_CPU_REG_NO) return(UNKNOWN_TYPE);
   switch (accessMode) {
      case READ_ALL :
         GetReg(value);   // A6..A0/D7..D0,SP,PC,SR,VBR
         break;
      case WRITE_ALL :
         SetReg(value);   // A6..A0/D7..D0,SP,PC,SR,VBR
         break;
      case READ_ONE :
         status = ReadReg(regName,value);
         break;
      case WRITE_ONE :
         status = WriteReg(regName,*value);
         break;
      default :
         return(ACCESS_ERROR);
   }
   if (status) status = ACCESS_ERROR;
   return(status);
}

/****************************************************************************
**
**  OutputStatus
**
**  Description: output the status of executive FW to outputStream
**
**  Parameters:
**     input:
**
**     output:
**
**        return data --
**
****************************************************************************/
VOID OutputStatus(STATUS status,U8 endData) {

   outputStreamLen = sizeof(status);
   memcpy (&outputStream[0],&status,outputStreamLen);
   if (endData == ON)
      outputStream[outputStreamLen++] = 0x00;/* Output stream length */
}

/****************************************************************************
*
*  GetBits
*
*  Description:
*
*  Parameters:
*    input:
*      value     :
*      bitStart  :
*      length    :
*    output:
*      return value :
*
*****************************************************************************/
U16 GetBits(U16 value, U8 bitStart,U8 length)
{
   U16 buffer, mask;

   buffer = value >> bitStart;
   mask = 0xffff;
   mask = (mask >> (16-length));
   buffer &= mask;
   return (buffer);
}

/****************************************************************************
*
*  BitNo
*
*  Description:
*
*  Parameters:
*    input:
*      sizeNo:
*    output:
*      return:
*
*****************************************************************************/
U8 BitNo(U8 sizeNo) {
U8 bitPos,loop,bit = 0x01;

   loop = 0;
   while ((loop < 8) && ((sizeNo & (bit << loop)) <= 0)) {
      loop++;
   }
   if (loop >= 8) bitPos = 0;
   else bitPos = ++loop;
   return(bitPos);
}

/****************************************************************************
*
*  ExchangeHighLow2 / ExchangeHighLow4
*
*  Description:
*
*  Parameters:
*    input:
*      sizeNo:
*    output:
*      return:
*
*****************************************************************************/
U16 ExchangeHighLow2(U16 changeData) {
   U8 highByte,lowByte;

   highByte = (U8)changeData;
   lowByte = (U8)(changeData >> 8);
   return(((U16)highByte << 8) + (U16)lowByte);

}

U32 ExchangeHighLow4(U32 changeData) {
   U16 highWord,lowWord;

   lowWord = ExchangeHighLow2((U16)(changeData & 0x0FFFFl));
   highWord = ExchangeHighLow2((U16)(changeData >> 16));
   
   return((U32)highWord + ((U32)lowWord << 16));

}

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

