/* !!! Windows */
#define _WINDOWS_

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

#ifndef _BASEWIND_
#include "basewind.h"
#endif

#ifndef _HEAP_
#include "heap.h"
#endif

#ifndef _HOSTERRS_
#include "hosterrs.h"
#endif

#ifndef _PROC_
#include "proc.h"
#endif

#ifndef _PVTASK_
#include "pvtask.h"
#endif

#ifndef _SDPROBE_
#include "sdprobe.h"
#endif

#ifndef _SDPROC_
#include "sdproc.h"
#endif

#ifndef _SSHARED_
#include "sshared.h"
#endif

#ifndef _SHAREDAT_
#include "sharedat.h"
#endif

#ifndef _WSCOM_
#include "wscom.h"
#endif

#ifndef __TIME_H
#include "time.h"
#endif

#ifndef _VERSIONS_
#include "versions.h"
#endif

#ifndef  _SDS2ABI_
#include "sds2abi.h"
#endif

#define INI_FILENAME "mp186.ini"
#define ICE_EP_PENDING -51

RETCODE reset(VOID);
RETCODE step(VOID);
RETCODE abortEmulation(VOID);
U32 SwapDwordOrder(U32 input);
U16 SwapWordOrder(U16 input);
VOID Sds2AbiInputAvailable(VOID);
BOOLEAN SimIRET(VOID);

RETCODE status;

typedef enum {
   BKPT_UNLOADED, BKPT_XBRK, BKPT_SWB, BKPT_STATUS_END=0x7fff
} BKPT_STATUS;

U32 int3Handler;
BOOLEAN hasSWBkpt=FALSE;

typedef struct BKPT_ENTRY_TAG {
   struct BKPT_ENTRY_TAG *next;
   struct BKPT_ENTRY_TAG *prev;
   U16 id;
   U16 opcode;
   U32 addr;
   ADDR_SPACE space;
   BKPT_STATUS status;
} BKPT_ENTRY;

BAD_MEMORY  badAddr1, badAddr2;
U8 fwVersion;
extern   BOOLEAN bkptHitFlag;  /* Set by bkpt handler when emul stops */
extern   U16   emulationState;
U16   MPBreakCause;
extern   U32   probeVersion;
extern   BKPT_ENTRY *bkptHead;
extern   BKPT_ENTRY *bkptTail;
extern   BKPT_ENTRY *bkptFree;
extern   U16 SRSave;           /* Saved value of SR register */

static U16 MP_MAX_XBRKS;   /* Determined by MICEPack hardware */
                           /* note that this value can't exceed MAX_XBRKS */
extern   U16 numXbrks;   /* Number of execution breakpoints currently active */
extern   U32 xbrkAddr[];
extern   BOOLEAN SRModified;   /* Has SR been patched? */
extern   BOOLEAN bkptEnable;   /* Enables bkpt handler to run when emul stops*/

VOID InitializeSWBkpt(VOID);

RETCODE Sds2AbiFwInit(VOID)
{
   MP_MAX_XBRKS = 1;    // MICEPack can handle up to 1 hardware execution breakpoint
   Sds2AbiClearTrig(0);
   Sds2AbiClearEvent(0);
   return(GOOD);
}
////////////////////////////////////////////////////////////////////////////
// Sds2AbiFwGetBreakCause
//
// Description: get the cause break the emulation
//
// Parameters:
//    Input:   <none>
//    Output:  <cause> cause which break the emulation
////////////////////////////////////////////////////////////////////////////
RETCODE EXPORT Sds2AbiFwGetBreakCause(BREAK_CAUSE *cause)
{
   *cause = MPBreakCause;
   return(GOOD);
}

////////////////////////////////////////////////////////////////////////////
// Sds2AbiFwGetEmuState
//
// Description: get current emulation state
//
// Parameters:
//    Input:   <none>
//    Output:  <state> emulation state
////////////////////////////////////////////////////////////////////////////
RETCODE EXPORT Sds2AbiFwGetEmuState(EMULATION_STATE *iceState)
{
RETCODE  err;

   err=SdnReadMember(SDN_EMULATION_STATE,(U8 *)iceState);
   return(err);
}

/*****************************************************************************
**
** Sds2AbiFwReset
**
** description:
**    Reset target processor and enter emulation mode.
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwReset(CPU_RESET typeOfReset) {
   RETCODE err,err2;
   EMULATION_STATE iceState;
   U32 sim;
   BOOLEAN simValid = FALSE;
   PROC_CPU  cpuType;

   bkptEnable = FALSE;
   SRModified = FALSE;
   err = reset();
   err2 = Sds2AbiFwUnloadRegisters(TRUE);
   if (!err) err = err2;
   err2 = Sds2AbiFwUnloadBreakpoints();
   if (!err) err = err2;
   err2 = SdnReadMember(SDN_EMULATION_STATE,(U8*)&iceState);
   if (!err) err = err2;

/*
   ProcReturnCpu(&cpuType);
   if (cpuType == PROC_CPU_80186) {
         sim = 0xffffful;
         simValid = TRUE;
         err2 = SdnWriteMember(SDN_SIM_VALID,(U8*)&simValid,GOOD);
         err2 = SdnWriteMember(SDN_SIM_ADDRESS,(U8*)&sim,GOOD);
   }
 */
   if (iceState!=EM_HALTED) {       /* Update cause if we were emulating */
      BREAK_CAUSE cause = CAUSE_RESET;
      err2 = SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD);
      if (!err) err = err2;
   }
   if (typeOfReset==RESET_CPU_AND_UPDATE_STATUS) {
      iceState = EM_HALTED;
      err2 = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
      if (!err) err = err2;
      err2 = SdnWriteMember(SDN_EMULATION_RESULT,(U8*)&err,err);
      if (!err) err = err2;
   }
   return(err);
}

/*****************************************************************************
**
** Sds2AbiFwCpuReset
**
** description:
**    Reset the processor.  Does not update any registers or unload
**    breakpoints; therefore should be used only during initialization.
**
** parameters:
**    none
*****************************************************************************/
RETCODE EXPORT Sds2AbiFwCpuReset(VOID) {
   return(reset());
}

/*****************************************************************************
**
** Sds2AbiFwLoadBreakpoints
**
** description:
**    Replace user opcodes at breakpoint addresses by BGND instructions
**
** parameters:
**    none
*****************************************************************************/
RETCODE  Sds2AbiFwLoadBreakpoints(BOOLEAN loadNow) {
RETCODE err;
BKPT_ENTRY *entry;
U8 bkptOp[2], temp[2];
BOOLEAN enable;
PROC_CPU cpuType;

   hasSWBkpt = FALSE;
   ProcReturnCpu(&cpuType);
   if (cpuType == PROC_CPU_80186) {
         bkptOp[0] = 0xcc;
   }
   if ((err = SdnReadMember(SDN_BKPT_ENABLE, (U8*)&enable)) != GOOD)
      return(err);
   if (enable || loadNow) {
      numXbrks = 0; /* first breakpoint always H/W execution bkpt*/
      entry=bkptHead;
      if (!entry) return(GOOD);
      iceSetBP(numXbrks+10,entry->addr);
      xbrkAddr[numXbrks++] = entry->addr;
      entry->status = BKPT_XBRK;
      entry=entry->next;
      if (!entry) return(GOOD);
      if (entry->next) { /* more than 2 breakpoints are set */
         for (; entry; entry=entry->next) {
            hasSWBkpt = TRUE;
            err = Sds2AbiFwReadMem(entry->addr, entry->space, 2, BYTE_SIZE,
               (U8*)&entry->opcode);
            bkptOp[1] = (U8) (entry->opcode >> 8) & 0xff;
            if (!err) err=Sds2AbiFillMemAction(entry->addr,entry->space,2,2,BYTE_SIZE,
               TRUE, NULL, bkptOp);
            if (!err) entry->status = BKPT_SWB;
            Sds2AbiReadMemAction(entry->addr,entry->space,1,BYTE_SIZE,temp);
            if (temp[0] != bkptOp[0]) {
               err = ER_TOO_MANY_XBRKS;
               break;
            }
         }
      } else {
         iceSetBP(numXbrks+10,entry->addr);
         xbrkAddr[numXbrks++] = entry->addr;
         entry->status = BKPT_XBRK;
         err = GOOD;
      }
   }
   return(err);
}
/*****************************************************************************
**
** Sds2AbiFwUnloadBreakpoints
**
** description:
**    Restore user memory contents at all breakpoint addresses
**
** parameters:
**    none
*****************************************************************************/
RETCODE  Sds2AbiFwUnloadBreakpoints(VOID) {
   RETCODE err=GOOD, err2;
   BKPT_ENTRY *entry;
   RETCODE hwbp = FALSE;

   for (entry=bkptTail; entry; entry=entry->prev) {
      if (entry->status == BKPT_SWB) {
         err2 = Sds2AbiFillMemAction(entry->addr, entry->space,2,2,BYTE_SIZE,FALSE,
            NULL, (U8*)&entry->opcode);
         if (!err) err = err2;
         }
      else {
         hwbp = TRUE;
         }
      entry->status = BKPT_UNLOADED;
   }
   if (hwbp) {
      iceClearEvent(10);
      iceClearEvent(11);
      }
   return(GOOD);
}

RETCODE  EXPORT FindBreakpointAddr(U32 addr) {
   BKPT_ENTRY *entry;

   for (entry=bkptTail; entry; entry=entry->prev) {
         if (entry->addr == addr) break;
   }
   if (!entry) return(FALSE);
   else return(TRUE);
}

/*****************************************************************************
**
** Sds2AbiFwBkptHit
**
** description:
**    Called when the probe stops emulation.  Unloads registers into shared
**    data members, updates SD_BREAK_CAUSE, and sets SD_EMULATION_STATE.
**
** parameters:
**    byte  comm byte received from probe (one of PCOM_BKPTHIT, PCOM_STEPBKPT,
**          or PCOM_STEPFAIL).
*****************************************************************************/
RETCODE  Sds2AbiFwBkptHit()
{
   RETCODE err=GOOD,err2; 
   EMULATION_STATE iceState;
   BREAK_CAUSE cause=CAUSE_NONE;

   err = SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,err);
   if (hasSWBkpt) {
      if (SimIRET() == FALSE) return(ICE_USER_CC);
   }
   err2 = Sds2AbiFwUnloadRegisters(FALSE);
   if (!err) err = err2;
   err2 = Sds2AbiFwUnloadBreakpoints();
   if (!err) err = err2;
   iceState=EM_HALTED;
   err2 = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
   if (!err) err = err2;
   err = SdnWriteMember(SDN_EMULATION_RESULT,(U8*)&err,err);
   return(err);
}
/*   Mathew
RETCODE  Sds2AbiFwStep(U32 count) {
   RETCODE err;
   BOOLEAN  abortFromEsc;
   BREAK_CAUSE cause = CAUSE_STEP;

   bkptEnable=FALSE;

   while (count--) {
      bkptHitFlag=FALSE;
      if ((err = step()) != GOOD) return(err);
      if ((err = TskCheckAbort(&abortFromEsc)) != GOOD) return(err);
      if (abortFromEsc!=0) break;
   }
   if ((err = SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD)) != GOOD)
      return(err);
   return(GOOD);
}
*/
RETCODE  Sds2AbiFwStep(U32 count) {
   RETCODE err, err2;
   BOOLEAN  abortFromEsc;
   BREAK_CAUSE cause = CAUSE_STEP;

   bkptEnable=FALSE;

   while (count--) {
      bkptHitFlag=FALSE;
      err = step();
      if (err != ICE_MEM_GUARD && err != ICE_MEM_PROTECT && err != GOOD) return(err);
      if ((err2 = TskCheckAbort(&abortFromEsc)) != GOOD) return(err2);
      if (abortFromEsc!=0) break;
   }

   if (err == GOOD) {
      if ((err = SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD)) != GOOD)
         return(err);
   }
   return(GOOD);
}

RETCODE  Sds2AbiFwGo(EMULATION_STATE *iceState) {
RETCODE err, err2;
BOOLEAN bool=TRUE;
S16 status;

   bkptEnable=TRUE;
   *iceState = EM_HALTED;
   if ((err = SdnWriteMember(SDN_TRIC_DIAGNOSTIC_MODE,&bool,&err)) != GOOD) 
       return(err);
   InitializeSWBkpt();
   status = iceGo(0);
   if (status == ICE_EP_PENDING) {
//      *iceState = EM_HUNG;
//      err = ERR_PROGRAM_NOT_RUNNING; 
   } else {
      err = iceMapError(status);
      if (err != GOOD) return(err);
   }
   *iceState = EM_RUNNING;
   if ((err=SdnWriteMember(SDN_FW_TRACING_STATUS, &bool, err)) != GOOD) return(err);
   if ((err=SdnWriteMember(SDN_TRACING, &bool, err)) != GOOD) return(err);
   return(GOOD);
}

RETCODE EXPORT Sds2AbiFwGr(EMULATION_STATE *iceState) {
   return(Sds2AbiFwGo(iceState));
}

RETCODE  Sds2AbiFwHalt(VOID) {
   abortEmulation();
   return(GOOD);
}

RETCODE EXPORT Sds2AbiRunaccStart(EMULATION_STATE *iceState, U32 *regs) {
   RETCODE err;

   err = SdnReadMember(SDN_EMULATION_STATE,(U8*)iceState);
   if ((!err) && (*iceState != EM_HALTED)) {
      bkptEnable=FALSE;
      abortEmulation();
   }
   return(err);
}

RETCODE EXPORT Sds2AbiRunaccFinish(EMULATION_STATE iceState, U32 *regs) {
   RETCODE err=GOOD;
   if (iceState != EM_HALTED) {
//      err = Sds2AbiFwGo(&iceState);
//      if (err) return(err);
      iceGo(0);
      return (SdnWriteMember(SDN_EMULATION_STATE, (U8 *)&iceState, GOOD));
   }
   return(err);
}

RETCODE reset(VOID)
{
   status = iceReset();
   return(iceMapError(status));
}

RETCODE step(VOID)
{
   status = iceStepRange(0, 0);
   if (status != ICE_OK) return(iceMapError(status));
   return(GOOD);
}

RETCODE abortEmulation(VOID)
{
   status = iceAbort();
   return(iceMapError(status));
}

VOID Sds2AbiInputAvailable(VOID) {
EMULATION_STATE iceState;
BREAK_CAUSE cause;
U8 goStatus;
BOOLEAN  bool, value;
RETCODE  err;
S16 status;
U32 pc, myCS;
STATIC BOOLEAN isPending = FALSE;

   status = iceGetCpuStatus(&goStatus);
   if ((goStatus & 0x01) == 0 && status != ICE_EP_PENDING) { // Judy 5/30/97
      if (isPending) {
         isPending = FALSE;
         iceState = EM_RUNNING;
         err = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
      }
   /* <Judy 5/30/97> */
      if ((goStatus & 0x02) !=0) {
         bool=0;
         SdnWriteMember(SDN_TRACING, &bool, GOOD);
      }
   /* eof <Judy 5/30/97> */
      return;
   }
   switch (status)
      {
      case ICE_BKPT2_HALT:
      case ICE_USER_CC:
      case ICE_SW_BKPT_HIT:
         if (bkptEnable) {
            if (Sds2AbiFwBkptHit() == ICE_USER_CC) {
               iceStepOne();
               iceGo(0);
               return;
            }
         }
         bkptHitFlag = TRUE;
         bool = FALSE;
         SdnWriteMember(SDN_FW_TRACING_STATUS, &bool, GOOD);
         SdnWriteMember(SDN_TRACING, &bool, GOOD);
         cause = CAUSE_BKPT;
         SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD);
         return;
      case ICE_BKPT1_HALT:
      case ICE_TRIG_HALT:
         FwUnloadRegisters();
         SdnReadMember(SDN_CS, (U8*)&myCS);
         SdnReadMember(SDN_EIP, (U8*)&pc);
         pc += myCS*16;
         if (pc == int3Handler) Sds2AbiFwBkptHit(); 
         if (status == ICE_BKPT1_HALT) cause = CAUSE_BKPT;
         else cause=CAUSE_BUSBRK;
         break;
      case ICE_HALT_USER:
         cause = CAUSE_HALT;
         break;
      case ICE_EP_PENDING:
         if (!isPending) {
            isPending = TRUE;
            iceState = EM_RUNNING;
            err = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
         }
         cause = CAUSE_PENDING;
         SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD);
         return;
      case ICE_MEM_PROTECT:      // Using 
         cause=CAUSE_DR_ACCESS;
         break;
      case ICE_MEM_GUARD:      // Using 
         cause=CAUSE_OVERLAY_ACCESS;
         break;
      case ICE_BROKE:
      default:
         cause=CAUSE_NONE;
         break;
//      default:
//         break;
      }
   SdnWriteMember(SDN_BREAK_CAUSE,(U8*)&cause,GOOD);
   Sds2AbiFwUnloadRegisters(FALSE);
   if (bkptEnable) Sds2AbiFwUnloadBreakpoints();
   iceState = EM_HALTED;
   err = SdnWriteMember(SDN_EMULATION_STATE,(U8*)&iceState,GOOD);
   SdnWriteMember(SDN_EMULATION_RESULT,(U8*)&err,GOOD);
   bool = FALSE;
   SdnWriteMember(SDN_FW_TRACING_STATUS, &bool, GOOD);
   SdnWriteMember(SDN_TRACING, &bool, GOOD);
}
RETCODE EXPORT GetID(PROBE_TYPE *probeType, BOOLEAN *slotPresent)
{
U8 ID_Info[40];
   status = ~ICE_OK;
   while (status != ICE_OK) status = iceGetID(ID_Info);
   switch (ID_Info[2]) {
   case 1: 
      *probeType = I80C188XL_MP; break;
   case 2: 
      *probeType = I80C188EA_MP; break;
   case 3: 
      *probeType = I80C188EB_MP; break;
   case 4: 
      *probeType = I80C188EC_MP; break;
   case 5: 
      *probeType = I80C186XL_MP; break;
   case 6: 
      *probeType = I80C186EA_MP; break;
   case 7: 
      *probeType = I80C186EB_MP; break;
   case 8: 
      *probeType = I80C186EC_MP; break;
   case 9:
      *probeType = A80188EM_MP; break;
   case 10:
      *probeType = A80188ES_MP; break;
   case 11:
      *probeType = A80188ER_MP; break;
   case 12:
      *probeType = A80186EM_MP; break;
   case 13:
      *probeType = A80186ES_MP; break;
   case 14:
      *probeType = A80186ER_MP; break;
   case 15:
      *probeType = A80186ED_MP; break;
   }
   fwVersion = ID_Info[1];
   if (ID_Info[4]) *slotPresent = TRUE;
   else *slotPresent = FALSE;
   return(GOOD);
}

/*****************************************************************************
**
** Sds2AbiFwUpdateProbeVersion
**
** description:
**    Send version packet to probe and write results to shared data members
**
** parameters:
**    none
*****************************************************************************/
RETCODE Sds2AbiFwUpdateProbeVersion(VOID) {
   RETCODE err;
   PROBE_TYPE probeType = PROBE_NONE;
   BOOLEAN slotPresent;

   if ((err = Sds2AbiFwCpuReset()) != GOOD) return(err);

   /* find out which processor is installed...tests must be in this order */
   if ((err = GetID(&probeType, &slotPresent)) != GOOD) return(err);

   Sds2AbiFwReset(ONLY_RESET_CPU);  /* Clear possible error from above memory reads */
   if((err=SdnWriteMember(SDN_PROBE_TYPE,(U8*)&probeType,GOOD)) != GOOD)
      return(err);

   // a section of version update code might need to be added here

   return(GOOD);
}

RETCODE EXPORT SdsCliSync(LPSTR cmdString, U32 argc, U32 argv[])
{
U16   sync, mask;
S8    buf[64];
RETCODE  err;

   switch (argc)
      {
      case 1:
         err = iceMapError(iceGetSync(&sync));
         if (err != GOOD) return(err);
         wsprintf(buf, "Sync start in %s", (sync & 0x01) ? "on" : "off");
         if ((err = SendMessageToCli(buf)) != GOOD) return(err);
         wsprintf(buf, "Sync slave out %s", (sync & 0x02) ? "on" : "off");
         if ((err = SendMessageToCli(buf)) != GOOD) return(err);
         break;
      case 2:
         if (stricmp(&cmdString[(int)argv[1]], "input") == 0)
            {
            err = iceMapError(iceGetSync(&sync));
            if (err != GOOD) return(err);
            wsprintf(buf, "Sync start in %s", (sync & 0x01) ? "on" : "off");
            if ((err = SendMessageToCli(buf)) != GOOD) return(err);
            }
         else if (stricmp(&cmdString[(int)argv[1]], "output") == 0)
            {
            err = iceMapError(iceGetSync(&sync));
            if (err != GOOD) return(err);
            wsprintf(buf, "Sync slave out %s", (sync & 0x02) ? "on" : "off");
            if ((err = SendMessageToCli(buf)) != GOOD) return(err);
            }
         else return(ER_CLI_SYNTAX);
         break;
      case 3:
         if ((status = iceGetSync(&sync)) != ICE_OK) return(iceMapError(status));
         if (!stricmp(&cmdString[(int)argv[1]], "input")) mask = 0x01;
         else if (!stricmp(&cmdString[(int)argv[1]], "output")) mask = 0x02;
               else return(ER_CLI_SYNTAX);
         if (!stricmp(&cmdString[(int)argv[2]], "on")) sync |= mask;
         else if (!stricmp(&cmdString[(int)argv[2]], "off")) sync &= (~mask);
               else return(ER_CLI_SYNTAX);
         if ((status = iceSetSync(sync)) != ICE_OK) return(iceMapError(status));
         wsprintf(buf, "Sync start in %s", (sync & 0x01) ? "on" : "off");
         if ((err = SendMessageToCli(buf)) != GOOD) return(err);
         wsprintf(buf, "Sync slave out %s", (sync & 0x02) ? "on" : "off");
         if ((err = SendMessageToCli(buf)) != GOOD) return(err);
         break;
      default:
         return (ER_CLI_SYNTAX);
      }
   return(GOOD);
}

RETCODE EXPORT SdsCliWait(LPSTR cmdString, U32 argc, U32 argv[])
{
LPSTR   lpParam;
S8    buf[64];
RETCODE  err;
U16 waitState;

   switch (argc)
   {
   case 1:
      err = iceMapError(iceGetWait(&waitState));
      if (err != GOOD) return(err);
      break;
   case 2:
      lpParam = &(cmdString[(U16)argv[1]]);
      if(isdigit((S16) lpParam[0])) { /* isdigit returns nonzero if 0-9 */
         char *endptr;
         waitState = strtoul(&lpParam[0], &endptr, 0);
         if (waitState > 3 || *endptr != '\0') return(ER_CLI_SYNTAX);
         err = iceMapError(iceSetWait(waitState));
         if (err != GOOD) return(err);
         break;
      } 
   default:
      return (ER_CLI_SYNTAX);
   }
   wsprintf(buf, "%d wait states is inserted", waitState);
   if ((err = SendMessageToCli(buf)) != GOOD) return(err);
   return(GOOD);
}

RETCODE EXPORT SdsCliReady(LPSTR cmdString, U32 argc, U32 argv[])
{
S8    buf[64];
RETCODE  err;
U16 readyState;

   switch (argc)
   {
   case 1:
      if ((err=iceMapError(iceGetReady(&readyState))) != GOOD) return(err);
      break;
   case 2:
      if (stricmp(&cmdString[(int)argv[1]], "external") == 0) 
         readyState = 1;
      else if (stricmp(&cmdString[(int)argv[1]], "internal") == 0)
         readyState = 0;
      else return(ER_CLI_SYNTAX);
      if ((err=iceMapError(iceSetReady(readyState))) != GOOD) return(err);
      break;
   default:
      return (ER_CLI_SYNTAX);
   }
   wsprintf(buf, "Emulation memory RAEDY signal generated from %s", 
      (readyState & 0x01) ? "external" : "internal");
   if ((err = SendMessageToCli(buf)) != GOOD) return(err);
   return(GOOD);
}

VOID InitializeSWBkpt(VOID)
{
U8 newVect[4];
U32 vectLoc = 0xc;
U32 trapHandler;

    if (hasSWBkpt == TRUE) {
       Sds2AbiReadMemAction(vectLoc,0,4,BYTE_SIZE,newVect);
       trapHandler = *((U32 *)&newVect[0]); /* get CS:IP of trap vector */
//       Sds2AbiFillMemAction(vectLoc,0,4,4,BYTE_SIZE,FALSE,
//            NULL, (U8*)&newVect);
       iceSetBP(11, trapHandler);
       int3Handler = 
        (((trapHandler&0xffff0000L)>>12)+(trapHandler&0xffffL))&0xfffffL;
    }
}

BOOLEAN SimIRET(VOID)
{
U32 spPtr, retSR, retIP, retCS, curSS, tmpAddr;
U8 tmpBuff[2];

    Sds2AbiFwUnloadRegisters(TRUE);
    SdnReadMember(SDN_SS, (U8*)&curSS);
    SdnReadMember(SDN_SP, (U8*)&spPtr);
    spPtr += curSS << 16; 
    iceGetMemN(spPtr, tmpBuff, 2);
    retIP = *(U16 *)tmpBuff;
    spPtr += 2;
    iceGetMemN(spPtr, tmpBuff, 2);
    retCS = *(U16 *)tmpBuff;
    spPtr += 2;
    iceGetMemN(spPtr, tmpBuff, 2);
    retSR = *(U16 *)tmpBuff;
    spPtr += 2;
    retIP--;
    tmpAddr = (retCS << 16) + retIP; /* address in breakpoint table is cs:ip form */
    if (FindBreakpointAddr(tmpAddr) == FALSE) return (FALSE);
    SdnWriteMemberNoCallback(SDN_EIP,(U8*)&retIP,GOOD);
    SdnWriteMemberNoCallback(SDN_CS, (U8*)&retCS,GOOD);
    SdnWriteMemberNoCallback(SDN_EFLAGS,(U8*)&retSR,GOOD);
    spPtr &= 0xffffL;
    SdnWriteMemberNoCallback(SDN_SP,(U8*)&spPtr,GOOD);
    Sds2AbiFwLoadRegisters();
    return (TRUE);
 }

