/****************************************************************************
**
**  Name:  dasm030.c
**
**  Description:
**     This is a disassembler for Motorola 68030
**
**
**  Status:  REVIEW
**
**  $Log:   S:/tbird/mt2_186/dad186/dasm030.c_v  $
** 
**    Rev 1.0   16 Dec 1996 15:13:42   Judy
** Initial revision.
** 
**    Rev 1.49   14 Jun 1994 08:50:40   nghia
** Fixed typo for AdrAddToAddressOverflow().
** 
**    Rev 1.48   10 Jun 1994 17:06:24   nghia
** Revised to use the AddToAddressOverFlow().  Caller will handle the overflow
** condition.
** 
**    Rev 1.47   15 Apr 1994 18:52:48   brucea
** In IsCallOrRTS:
**    Added recognition of CALLM for step into instruction
**    Added all RT? instructions (RTE, RTD, RTR, RTS RTM) for step until return
**       recognition
** 
**    Rev 1.46   28 Feb 1994 17:13:10   marilyn
** Moved maxOutput routines to the address server. Updated interfaces.
** 
**    Rev 1.45   29 Jul 1993 15:20:58   nghia
** Refixed PPR 8078 - disassemble JSR 0x##### -> DC.W ####
** 
**    Rev 1.44   26 Jul 1993 12:21:30   paul
** Replace CHECK_ABORT with TskCheckAbort from PVTASK DLL
** 
**    Rev 1.43   13 Jul 1993 09:25:44   ernie
** Streamlined DadDasmGetRangeOfInst() to improve mixed mode performance
** 
**    Rev 1.42   09 Jun 1993 08:57:12   ernie
** Added IsTransfer and fixed the code setting the corresponding dasminfo
** 
**    Rev 1.41   25 May 1993 11:52:52   ernie
** Changed interface to MemReadSized()
** 
**    Rev 1.40   22 Apr 1993 17:44:10   nghia
** Fixed ppr8078 - cannot disassemble JSR 0x????.
** 
**    Rev 1.39   23 Mar 1993 09:35:30   doug
** merged John's generic 340 change
** 
**    Rev 1.38.1.1   01 Mar 1993 13:18:04   john
** Changed dasm output to use use address descriptors and 
** ConvertAddressToTextWithParams to display jump targets, etc...
** 
** Changed dasmInstByLine to return an error when the address overflows
** past the U32 limit.
** 
**    Rev 1.38.1.0   12 Feb 1993 10:12:02   john
** No change.
** 
**    Rev 1.38   14 Jan 1993 14:56:18   brucea
** Changed: AddrSymbol to only call symbol lookup if the instruction type is
**    a transfer (jsr) type.  This filters out calls for all other effective
**    addresses and will therefore speed up disassembly.
**    Also, the symbol call was changed to simply get the symbol name rather
**    than require that it be a function.  This way, all JSR effective addresses
**    will be looked up, including library calls.
** 
**    Rev 1.37   11 Jan 1993 17:01:08   john
** processor #def's were modified, changes made to match
** 
**    Rev 1.36   06 Jan 1993 17:38:50   marilyn
** In GetDasmInst now check to make sure that the requested number of
** instructions will fit in a 64K buffer. 
** 
**    Rev 1.35   15 Dec 1992 13:03:42   ernie
** Converted to new MemReadSized call and now use WORD_SIZE for code memory
** 
**    Rev 1.34   09 Dec 1992 10:05:02   john
** Added code to handle the simple case of pc relative jsr's.  It can
** only calculate offsets in the (bd,PC) format.
** 
**    Rev 1.33   02 Dec 1992 16:55:06   john
** modified target address printout to be 24 bit
** 
**    Rev 1.32   23 Nov 1992 16:21:48   john
** All function calls inside DisassembleOpcode that could possibly cause
** an opcode to be deemed invalid now call a general cleanup function.
** This cleanup function forces the invalid opcode to be reported as a
** DC.W.
** 
**    Rev 1.31   06 Nov 1992 14:01:46   john
** fixed memory leaks
** 
**    Rev 1.30   02 Nov 1992 13:05:44   ernie
** In TraceBufInst(), added support for a NULL text output pointer.
** When this argument is NULL, TraceBufInst() just returns dasmInfo,
** and does not fill in memory with the textual representation of the
** instruction.
** 
**    Rev 1.29   30 Oct 1992 18:17:54   john
** removed tfree's for buffers freed by callers
** 
**    Rev 1.28   20 Oct 1992 11:09:38   john
** Removed unnecessary heapdump calls in a routine that doesn't do any
** dynamic allocation.
** Removed a cleanup routine because the dynamic var. being created was
** turned into a stack var.
** 
**    Rev 1.27   15 Oct 1992 10:37:46   john
** Fixed a dasm error in effective address full format extension words.
** A reserved bit combination was not being checked for.
** Also added return code checking to the EA parsing routine.  The
** subfuncs that were being called all returned RETCODES, but the
** parsing routine ignored them.  Now a returned error forces the
** disassembler to return DC.W.
** Made minor formatting changes.
** 
**    Rev 1.26   14 Oct 1992 17:28:28   john
** fixed dasm input address > physical addr
** 
**    Rev 1.25   14 Oct 1992 15:12:38   john
** 
** Removed more code that unnecessarily tmalloc'd memory.
** There are a couple of calls that malloc memory for other higher and
** lower routines to use.  The upper routines are expected to clear the
** buff.  The lower routines fill the buffer in, and expect the buffer
** to be in a known good state.  Code has been added to make sure the
** newly created buffer is in a known good state for use by the lower
** routines.  This helps to fix heap corrupt errors.
** 
**    Rev 1.24   13 Oct 1992 14:21:06   john
** Fixed UAE caused by Bcc style opcodes.  The disassembler was not
** checking to make sure the encoded cc bytes were in range.
** Modified code that manually did mallocs/frees for variables that were
** of a known size.  Now these are stack resident.
** Fixed the DC.W display to only show one word of data. (part of
** malloc/free fix above)
** 
**    Rev 1.23   09 Oct 1992 12:24:40   marilyn
** Fixed memory leak.
** 
**    Rev 1.22   25 Sep 1992 16:06:18   marilyn
** Found another memory leak and fixed it.
** 
**    Rev 1.21   18 Sep 1992 09:59:44   marilyn
** Fixed memory leaks.
** 
**    Rev 1.20   14 Sep 1992 09:54:00   marilyn
** Fixed some memory leaks.
** 
**    Rev 1.19   31 Aug 1992 09:22:28   marilyn
** Fixed bug where return codes from symbol server were not checked and
** causing UAE in subsequent calls to the symbol server. Also misc
** compiler warnings were fixed.
** 
**    Rev 1.18   27 Aug 1992 15:22:46   marilyn
** Eliminated compiler warnings.
** 
**    Rev 1.17   19 Aug 1992 09:23:28   marilyn
** Fixed assorted PPRs.  Checks instruction against current processor.
** Never returns invalid instruction error just puts out DC.W.  Uses
** address server routines.
** 
**    Rev 1.16   31 Jul 1992 09:40:16   marilyn
** Removed internal error defines.  Now use the ones in daddef.h.
** Added some error checking for CheckEa routine.
** 
**    Rev 1.15   22 Jul 1992 09:25:04   marilyn
** Fixed bug in FreeDasmCache.
** 
**    Rev 1.14   17 Jul 1992 09:39:32   marilyn
** Added FreeDasmCache.
**
**    Rev 1.13   10 Jul 1992 17:22:06   marilyn
** Added memory read caching.
** 
**    Rev 1.12   23 Jun 1992 16:34:02   marilyn
** Bug fixes and 68332 support.
** 
**    Rev 1.11   04 May 1992 10:10:12   mindy
** a) added address output for each line of disassembley - see ppr5371
**    for more details.
** b) dasminfo bytesused wasn't being filled in for Iscall... routine.
**
**    Rev 1.10   28 Apr 1992 08:45:40   mindy
** a) added checks for bad memory allocation.
** b) cleaned up some exits from GetDasmInst
** c) added abort support.
**
**    Rev 1.9   15 Apr 1992 10:01:26   mindy
** initialize the dasmInfo structure before Identify call incase we error
** out.
**
**    Rev 1.8   31 Mar 1992 14:19:38   mindy
** used dasm_info instead of unparsing text
** 
**    Rev 1.7   30 Mar 1992 13:33:54   mindy
** a) in ProcessOperand that was an infinite loop that occurs if we were
**    processing the "caches" case.
** b) Fixed the symbol getting portion.
** c) added ReturnType to DASM_INFO structure.
** d) Fixed up IsCall... routine to return the address following the
**    current instruction.
** e) GetDasmInt now returns DC.W XXXX if we can't disassemble memory.
** 
**    Rev 1.6   13 Mar 1992 09:05:58   mindy
** added DASM_INFO support: the hook between the disassembler and dequeuer.
**
**    Rev 1.5   06 Mar 1992 06:19:14   mindy
** allen's fix for MULS/MULU problem
** 
**    Rev 1.4   05 Mar 1992 11:37:44   mindy
** added debug switch around MemRead call (see dasm.c note)
**
**    Rev 1.3   03 Mar 1992 14:53:50   mindy
** a) ProcessMne. had a logic problem.
** b) changed dummy read interface to match memread
**
**    Rev 1.2   03 Mar 1992 11:55:40   mindy
** a) memory allocation is done by the memory server now.
** b) changed local memory allocation to all use TMalloc.
** c) removed multi instruction stuff if is now handled by the
**    GetDasmInst routine.
**
**    Rev 1.1   03 Mar 1992 10:11:00   mindy
** Made interface changes to support standard document format and new
** memory server interface.  Also general clean up.
** 
**    Rev 1.0   14 Jan 1992 13:06:08   tom
** Initial revision.
**
**  $Header:   S:/tbird/mt2_186/dad186/dasm030.c_v   1.0   16 Dec 1996 15:13:42   Judy  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/
#ifndef _BASEWIND_
#include "basewind.h"
#endif

#ifndef _ADDR_
#include "addr.h"
#endif

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

#ifndef _TBIRDMEM_
#include "tbirdmem.h"
#endif

#ifndef _DAD_SERVER_
#include "dasm.h"
#endif

#ifndef _SYMBLSVR_
#include "symblsvr.h"
#endif

#ifndef _DAD_DEFINE_
#include "daddef.h"
#endif

#ifndef _DAD_EXT_DEFINE_
#include "dadext.h"
#endif

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

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

                        /***************************
                        *                          *
                        *  DEFINITIONS             *
                        *                          *
                        ***************************/



#define EA_ERR          0x7fff

#define NUM_FP_COND_CODES 32
#define NUM_PROC_COND_CODES 16

#define PAGESIZE 256
#define HALFPAGE 128

#define TwoComplement(Data) (~Data + 1)

#define EA_EXT_FRMT_BD_RESERVED 0
#define EA_EXT_FRMT_BD_NULL     1
#define EA_EXT_FRMT_BD_WORD     2
#define EA_EXT_FRMT_BD_LONG     3


const U8 endOfBuffer[] = "\0";
const U8 endOfLine[] = "\r\n";
const U8 dot[] = ".";
const U8 space39[] = "                                         ";
          /* space 0 - space 11 */
const LPSTR space[] = {""," ","  ","   ","    ","     ","      ","       ",

                      "        ","         ","          ","           "};

static U32 pageCache = 0;
static LPU8 memCacheBuf = NULL;


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

extern BOOLEAN dummyDasm;
extern PROBE_TYPE cpuType;

/*
** #define DEBUG_MEM_LEAKS 1
*/

extern U32 memAlloced;
extern U32 memFreed;

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

RETCODE AddrSymbol(LPSTR OpString, U16 *Code, U8 *opIndex, U8 size,
                   BOOLEAN DadSymbol, DASM_INFO FAR *dasmInfo);
RETCODE BitNo(U8 SizeNo);
RETCODE BitCnt(U16 Code);
VOID    CatchData(U16 InstructionNo,U16 SizeNo,U16 *OpWord,OPERATOR *opSet);
RETCODE GetIntData(DESCRIPTOR address, LPU8 dataBuf);
RETCODE CleanInst(U16 *InstNo,U8 *lp2,U16 *OpWord);
RETCODE Coprocessor(U16 *InstructionNo, U16 *SizeNo, U16 *OpWord);
RETCODE Identify(U16 *InstructionNo, U16 *SizeNo, U16 *OpWord);
RETCODE RegisterList (OPERATOR *opSet, U8 *opIndex);
RETCODE CoRegisterList (OPERATOR *opSet, U8 *opIndex);
RETCODE CoControlReg (OPERATOR *opSet, U8 *opIndex);
RETCODE ProcessEffective(OPERATOR *opSet, U8 *opIndex, BOOLEAN DadSymbol,
                         DASM_INFO FAR *dasmInfo, U32 addrOffset);
RETCODE ProcessMnemonic(OPERATOR *opSet);
RETCODE ProcessOperand(OPERATOR *opSet, U32 addrOffset, BOOLEAN DadSymbol,
                       DASM_INFO FAR *dasmInfo);
RETCODE GetIntString(LPSTR OpString, U16 *Code, U8 *opIndex, U8 Len);
RETCODE DisassembleOpcode(U16 FAR *OpWord, U32 addrOffset, BOOLEAN symbols,
                          OPERATOR FAR *opSet, DASM_INFO FAR *dasmInfo);
RETCODE DasmInst(U16 FAR *OpWord, DESCRIPTOR startAddr, U8 *inst,
                 U8 *InstLen,BOOLEAN DadSymbol);
RETCODE FreeDasmCache(VOID);
RETCODE CreateDCWord(OPERATOR *opSet);

/* dummy to test dasm!!! */
RETCODE DummyMemRead(DESCRIPTOR source, U32 length, LPU8 *buffer);

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


/*****************************************************************************
**
**    CreateDCWord
**
**    When an error is returned from ProcessOperand the data that 
**    was processed and found to be invalid is turned into a DC.W
**    string.  No error is returned the data is just converted.
**
*****************************************************************************/
RETCODE CreateDCWord(OPERATOR *opSet) {
   strcpy((LPSTR)opSet->mnemonic,"DC");
   opSet->size[0] = 'W';
   sprintf((LPSTR)opSet->opString,"%4.4X",opSet->objCode[0]);
   opSet->opLength=1;
   return(GOOD);
}


/*****************************************************************************
**
**    GetBits
**
*****************************************************************************/
RETCODE GetBits(U16 value, U8 bitStart,U8 length) {
   U16 buffer, mask;
   buffer = value >> bitStart;
   mask = 0xffff;
   mask = (mask >> (16-length));
   buffer &= mask;
   return (buffer);
}

/*****************************************************************************
**
**    BitNo
**
*****************************************************************************/
RETCODE BitNo(U8 sizeNo)
{
   LOOP_VAR loop,bit = 0x01;

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

}


/*****************************************************************************
**
**    CatchData
**
*****************************************************************************/
VOID CatchData(U16 instructionNo,U16 sizeNo,U16 *opWord,OPERATOR *opSet) {
/* Catch INSTRUCTION & relational data, Check the operator size. */
   U16 loop;

   if (GetBits(opWord[0],9,7) == 0x79) { /* 68881 */
      strcpy((LPSTR)opSet->mnemonic,
            (LPSTR)CoInstructionSet[instructionNo].Mnemonic);
      strcpy((LPSTR)opSet->operand,
            (LPSTR)OperandType[CoInstructionSet[instructionNo].OpType]);
      opSet->eaType = CoInstructionSet[instructionNo].EaType;
      opSet->cpuType = CoInstructionSet[instructionNo].CpuType;
      opSet->eaPos = CoInstructionSet[instructionNo].EaPos;
   }
   else {
      strcpy((LPSTR)opSet->mnemonic,
            (LPSTR)InstructionSet[instructionNo].Mnemonic);
      strcpy((LPSTR)opSet->operand,
            (LPSTR)OperandType[InstructionSet[instructionNo].OpType]);
      opSet->eaType = InstructionSet[instructionNo].EaType;
      opSet->cpuType = InstructionSet[instructionNo].CpuType;
      opSet->eaPos = InstructionSet[instructionNo].EaPos;
   }
   strcpy((LPSTR)opSet->size,(LPSTR)SizeString[(U16)BitNo(sizeNo)]);
   for(loop = 0; loop < MAX_CODE_LENGTH; loop++)
      opSet->objCode[loop] = opWord[loop];
}

/*****************************************************************************
**
**   FreeDasmCache
**
*****************************************************************************/
RETCODE FreeDasmCache(VOID) {

   RETCODE err;

   if (pageCache && (memCacheBuf != NULL)) {
      if ((err = TFree((LPSTR)memCacheBuf)) != GOOD)
         return err;
      pageCache = 0;
      memCacheBuf = NULL;
   }

   return GOOD;
}

/*****************************************************************************
**
**    GetIntData
**
**    This routine keeps a cache of one page (256 bytes) to help improve
**    performance.  When a caching system is implemented inside the memory
**    server, this caching would be redundant.
**
*****************************************************************************/
RETCODE GetIntData(DESCRIPTOR address, LPU8 dataBuf) {

   U16  *dataPtr, temp1,temp2;
   U32 offset;
   U16 cacheOffset;
   LOOP_VAR  loop;
   RETCODE err;

   if ((err = AdrGetAddrOffset(address,&offset)) != GOOD)
      return err;
   if (!pageCache) {
      if (dummyDasm) {
         if ((err = DummyMemRead(address,PAGESIZE,&memCacheBuf)) != GOOD)
            return(err);
      }
      else {
         if ((err = MemReadSized(address,PAGESIZE,&memCacheBuf,WORD_SIZE,
               CACHE_USE)) != GOOD) {
            TFree(memCacheBuf);
            memCacheBuf = NULL;
            return err;
         }
      }
      dataPtr = (U16 FAR *)memCacheBuf;
      for (loop = 0; loop < HALFPAGE; loop++) {
        temp1 = dataPtr[loop];
        temp2 = dataPtr[loop];
        dataPtr[loop] = (temp1 >> 8) + (temp2 << 8);
      }
      pageCache = offset;
   }
   /*
   ** we have a page already, check if the requested data is
   ** in the page
   */
   if ((offset >= pageCache) && ((offset+MAX_CODE_LENGTH*2) <= (pageCache
         +PAGESIZE-1))) {
      cacheOffset = (U16) (offset - pageCache);
      memmove(dataBuf,memCacheBuf+cacheOffset,MAX_CODE_LENGTH*2);
   }
   else {
      /*
      ** our requested data is not completely in the memory cache,
      ** so get a new cache.
      */
      if ((err = FreeDasmCache()) != GOOD)
         return err;
      if (dummyDasm) {
         if ((err = DummyMemRead(address,PAGESIZE,&memCacheBuf)) != GOOD)
            return(err);
      }
      else {
         if ((err = MemReadSized(address,PAGESIZE,&memCacheBuf,WORD_SIZE,
               CACHE_USE)) != GOOD) {
            TFree(memCacheBuf);
            memCacheBuf = NULL;
            return err;
         }
      }
      dataPtr = (U16 FAR *)memCacheBuf;
      for (loop = 0; loop < HALFPAGE; loop++) {
        temp1 = dataPtr[loop];
        temp2 = dataPtr[loop];
        dataPtr[loop] = (temp1 >> 8) + (temp2 << 8);
      }
      pageCache = offset;
      memmove(dataBuf,memCacheBuf,MAX_CODE_LENGTH*2);
   }


   return(GOOD);
}


/*****************************************************************************
**
**    GetIntString
**
*****************************************************************************/
RETCODE GetIntString(LPSTR OpString, U16 *Code, U8 *opIndex, U8 Len)
{
   U32 lData;
   U16 wData;
   U8  digBuf[10];

   switch (Len) {
      case 1 :
         wData = GetBits(Code[0],0,8);
         sprintf((LPSTR)digBuf,"%2.2X",wData);
         break;
      case 2 :
         wData = Code[0];
         sprintf((LPSTR)digBuf,"%4.4X",wData);
         break;
      case 4 :
         lData = Code[0];
         wData = Code[1];
         lData = (lData << 16) + wData;
         sprintf((LPSTR)digBuf,"%8.8lX",lData);
         break;
   }
   strcat((LPSTR)OpString,(LPSTR)digBuf);
   (*opIndex)+=strlen((LPSTR)digBuf);
   return(GOOD);
}

/*****************************************************************************
**
**    GetTwoCompIntString
**
*****************************************************************************/
RETCODE GetTwoCompIntString(LPSTR OpString, U16 *Code, U8 *opIndex, U8 Len) {
   S32 lData;
   U16 wData;
   U8  bData,checkBit;
   U8  digBuf[10];
   switch (Len) {
      case 1 :
         bData = GetBits(Code[0],0,8);
         if (GetBits(bData,7,1) == 1) {
            bData = TwoComplement(bData);
            sprintf((LPSTR)digBuf,"-%2.2X",bData);
         }
         else
            sprintf((LPSTR)digBuf,"%2.2X",bData);
         break;
      case 2 :
         wData = Code[0];
         if (GetBits(wData,15,1) == 1) {
            wData = TwoComplement(wData);
            sprintf((LPSTR)digBuf,"-%4.4X",wData);
         }
         else
            sprintf((LPSTR)digBuf,"%4.4X",wData);
         break;
      case 6 :
         lData = Code[0];
         if (GetBits(lData,15,1) == 1) {
            lData += 0xffff0000L;
            sprintf((LPSTR)digBuf,"%8.8lX",lData);
         }
         else
            sprintf((LPSTR)digBuf,"%4.4X",lData);
         break;
      case 4 :
         lData = Code[0];
         wData = Code[1];
         checkBit = GetBits(lData,15,1);
         lData = (lData << 16) + wData;
         if (checkBit == 1) {
            lData = TwoComplement(lData);
            sprintf((LPSTR)digBuf,"-%8.8lX",lData);
         }
         else
            sprintf((LPSTR)digBuf,"%8.8lX",lData);
         break;
   }
   strcat((LPSTR)OpString ,(LPSTR)digBuf);
   (*opIndex)+=strlen((LPSTR)digBuf);
   return(GOOD);
}

/*****************************************************************************
**
**    CheckEa
**
*****************************************************************************/
U16 CheckEa(U16 OpWord, U16 Extword) {

   U16 AddrMode;
   U16 TypeNo = EA_ERR;

   AddrMode = GetBits(OpWord,3,3);
   switch (AddrMode) {
      case 0 :
      case 1 :
      case 2 :
      case 3 :
      case 4 :
      case 5 :
         TypeNo = AddrMode + 1; /* Dn,An,(An),(An)+,-(An),(d16,An) */
         break;
      case 6 :
         if (GetBits(Extword,8,1)==0) {/* identify extword is brief or full */
            TypeNo = 7; /* (d8,An,Xn) */
         }
         else {
            if (GetBits(Extword,6,1) == 0) {   /* IS */
               switch (GetBits(Extword,0,3)) {
                  case 0 :
                     TypeNo = 8; /*    (bd,An,Xn)     */
                     break;
                  case 1 :
                  case 2 :
                  case 3 :
                     TypeNo = 9; /*  ([bd,An,Xn],od)  */
                     break;
                  case 4 :
                     return(EA_ERR);
                  case 5 :
                  case 6 :
                  case 7 :
                     TypeNo = 10; /*  ([bd,An],Xn,od)  */
                     break;
               }
            }
            else {
               switch (GetBits(Extword,0,3)) {
                  case 0 :
                     TypeNo = 8; /*    (bd,An)     */
                     break;
                  case 1 :
                  case 2 :
                  case 3 :
                     TypeNo = 10; /*  ([bd,An],od)  */
                     break;
                  default :
                     return(EA_ERR);
               }
            }
         }
         break;
      case 7 :
         switch (GetBits(OpWord,0,3)) { /* register */
            case 0 :
               TypeNo = 11;    /* (xxx).W */
               break;
            case 1 :
               TypeNo = 12;    /* (xxx).L */
               break;
            case 2 :
               TypeNo = 14;    /* (d16,PC) */
               break;
            case 3 :
               if (GetBits(Extword,8,1) == 0) {
                  TypeNo = 15; /* (d8,PC,Xn) */
               }
               else {
                  if (GetBits(Extword,6,1) == 0) {   /* IS */
                     switch (GetBits(Extword,0,3)) {
                        case 0 :
                           TypeNo = 16; /*    (bd,PC,Xn)     */
                           break;
                        case 1 :
                        case 2 :
                        case 3 :
                           TypeNo = 17; /*  ([bd,PC,Xn],od)  */
                           break;
                        case 4 :
                           return(EA_ERR);
                               case 5 :
                        case 6 :
                        case 7 :
                           TypeNo = 18; /*  ([bd,PC],Xn,od)  */
                           break;
                     }
                  }
                  else {
                     switch (GetBits(Extword,0,3)) {
                        case 0 :
                           TypeNo = 16; /*    (bd,PC)     */
                           break;
                        case 1 :
                        case 2 :
                        case 3 :
                           TypeNo = 18; /*  ([bd,PC],od)  */
                           break;
                        default :
                           return(EA_ERR);
                     }
                  }
               }
               break;
            case 4 :
               TypeNo = 13;       /* #<data> */
               break;
         }
         break;
      default:
         return (EA_ERR);
   }
   return(TypeNo);
}

/*****************************************************************************
**
**    BitCnt
**
*****************************************************************************/
RETCODE BitCnt(U16 Code) {
   LOOP_VAR loop;
   const U16 MaskBit = 0x01;
   RETCODE cnt;
   for (cnt = 0, loop = 0; loop < 16; loop++) {
      if( Code & (MaskBit << loop) ) cnt++;
   }
   return(cnt);
}

/*****************************************************************************
**
**    CleanInst
**
*****************************************************************************/
RETCODE CleanInst(U16 *InstNo,U8 *lp2,U16 *OpWord) {
   U16 MaxBit,BitCount,Buf[5] = {0};
   LOOP_VAR loop,loop2;
   MaxBit = 0;
   for (loop = 0; loop < *lp2; loop++) {
      if ((BitCount = BitCnt(ObjCode[InstNo[loop]][3]) +
                             BitCnt(ObjCode[InstNo[loop]][4])) > MaxBit)
        MaxBit = BitCount;
   }
   if (((InstNo[0] == 173) && (InstNo[1] == 175)) ||
       ((InstNo[0] == 174) && (InstNo[1] == 176))) /* Special for PLOADW/R */
      if (GetBits(OpWord[1],13,2) == 1) {
    *lp2 = 1;
         return(GOOD);
      }
   if (((InstNo[0] == 211) && (InstNo[1] == 213)) ||
       ((InstNo[0] ==   5) && (InstNo[1] ==   7)))
      if (GetBits(OpWord[0],6,2) == 3) { /* Special for SUBA/ADDA */
    InstNo[0] = InstNo[1];
    *lp2 = 1;
         return(GOOD);
      }
   loop2 = 0;
   for (loop = 0; loop < *lp2; loop++) {
      if ((BitCount = BitCnt(ObjCode[InstNo[loop]][3]) +
                      BitCnt(ObjCode[InstNo[loop]][4])) == MaxBit) {
        Buf[loop2] = InstNo[loop];
        loop2++;
      }
   }

   for (loop = 0; loop < loop2; loop++)
        InstNo[loop] = Buf[loop];
   *lp2 = loop2;
   return(GOOD);
}

/*****************************************************************************
**
**    CoCleanInst
**
*****************************************************************************/
RETCODE CoCleanInst(U16 *InstNo,U8 *lp2)
{
   U16 MaxBit,BitCount,Buf[5] = {0};
   LOOP_VAR loop,loop2;

   MaxBit = 0;
   for (loop = 0; loop < *lp2; loop++) {
      if ((BitCount = BitCnt(CoObjCode[InstNo[loop]][3]) +
                             BitCnt(CoObjCode[InstNo[loop]][4])) > MaxBit)
               MaxBit = BitCount;
   }

   loop2 = 0;
   for (loop = 0; loop < *lp2; loop++) {
      if ((BitCount = BitCnt(CoObjCode[InstNo[loop]][3]) +
                      BitCnt(CoObjCode[InstNo[loop]][4])) == MaxBit) {
        Buf[loop2] = InstNo[loop];
        loop2++;
      }
   }

   for (loop = 0; loop < loop2; loop++)
        InstNo[loop] = Buf[loop];
   *lp2 = loop2;
   return(GOOD);
}

/*****************************************************************************
**
**    Coprocessor
**
*****************************************************************************/
RETCODE Coprocessor(U16 *InstructionNo, U16 *SizeNo, U16 *OpWord)
{
   LOOP_VAR lp1,lp3;
   U8   lp2;
   U16  InstNo[5],EaNo;
   U32  CheckBit = 0x01;

   for (lp1 = 0; lp1 < 5; lp1++)
      InstNo[lp1] = 0;
   lp1 = 1;
   lp2 = 0;
   while (lp1 < MAX_NUM_CO_INST) {
      if ( ((OpWord[0] & CoObjCode[lp1][3]) == CoObjCode[lp1][0]) &&
      ((OpWord[1] & CoObjCode[lp1][4]) == CoObjCode[lp1][1]) ){
    InstNo[lp2] = lp1;
    lp2++;
      }
   lp1++;
   }
   *InstructionNo = 0;
   switch (lp2) {
      case 0 :
      *InstructionNo = 0; /* No any instruction match */
      return(ER_DAD_INST_NOT_FOUND);
      case 1 :
    *InstructionNo = InstNo[0];
    break;
      default : /* Mutli Instruction match */
    if ((InstNo[0] == 89) && (InstNo[1] == 116)) {
       lp2 = 1;                          /* FScc   */
       if (GetBits(OpWord[0],0,3) > 1)   /* FTRAPcc*/
          InstNo[0] = InstNo[1];
    }
         else if ((InstNo[0] == 68) || (InstNo[0] == 69)) {
                 lp2 = 1;                          /* FMOVE  */
                 if ((GetBits(OpWord[1],10,3) != 1) &&
                     (GetBits(OpWord[1],10,3) != 2) &&
                     (GetBits(OpWord[1],10,3) != 4))
                    InstNo[0] = InstNo[1];
              }
              else
                 CoCleanInst(InstNo,&lp2);
    if ((InstNo[0] + 1) == InstNo[1]) {
            lp2 = 1;
            if (GetBits(OpWord[1],7,3) == GetBits(OpWord[1],10,3))
               InstNo[0] = InstNo[1];
         }
         if (lp2 == 1) {
            *InstructionNo = InstNo[0];
         }
         else {
            switch (InstNo[0]) {
               case 0 :
               default :
                  for (lp3 = 0; lp3 < lp2; lp3++) {
                     if ((EaNo = CheckEa(*OpWord,OpWord[CoInstructionSet
                           [InstNo[lp3]].EaPos])) == EA_ERR)
                        return ER_DAD_EA_INVALID;
                     if (((EaClass[CoInstructionSet[InstNo[lp3]].EaType]) &
                        (CheckBit << (EaNo - 1))) != 0) {
                        *InstructionNo = InstNo[lp3];
                        break;
                     }
                  }
                  break;
            }
         }
         break;
   }
   *SizeNo = CoInstructionSet[*InstructionNo].OpSize;
   if ((*SizeNo == TBWLSDXP)) {
      switch (GetBits(OpWord[1],10,3)) {
        case 0 :
           *SizeNo = TL;
           break;
        case 1 :
           *SizeNo = TS;
           break;
        case 2 :
           *SizeNo = TX;
           break;
        case 3 :
           *SizeNo = TP;
           break;
        case 4 :
           *SizeNo = TW;
           break;
        case 5 :
           *SizeNo = TD;
           break;
        case 6 :
           *SizeNo = TB;
           break;
        default :
           return(ER_DAD_INST_SIZE_UNDETERMINED);
      }
   }
   return(GOOD);
}


/*****************************************************************************
**
**    Processor
**
*****************************************************************************/
RETCODE Processor(U16 *InstructionNo, U16 *SizeNo, U16 *OpWord) {
   LOOP_VAR lp1,lp3;
   U8   lp2;
   U16  InstNo[5],EaNo;
   U32  CheckBit = 0x01;

   for (lp1 = 0; lp1 < 5; lp1++) InstNo[lp1] = 0;
   lp1 = 1;
   lp2 = 0;
   while (lp1 < MAX_NUM_INST) {
       if ( ((OpWord[0] & ObjCode[lp1][3]) == ObjCode[lp1][0]) &&
       ((OpWord[1] & ObjCode[lp1][4]) == ObjCode[lp1][1]) ){
          InstNo[lp2] = lp1;
          lp2++;
       }
      lp1++;
   }
   *InstructionNo = 0;
   switch (lp2) {
      case 0 :
         *InstructionNo = 0; /* No any instruction match */
         return(ER_DAD_INST_NOT_FOUND);
      case 1 :
         *InstructionNo = InstNo[0];
         break;
      default : /* Mutli Instruction match */
         CleanInst(InstNo,&lp2,OpWord);
         *InstructionNo = InstNo[0];
         if (lp2 > 1) {
            switch (InstNo[0]) {
               case 64 : /* special case for CHK2, CMP2 */
               case 65 :
               case 66 :
                  (GetBits(OpWord[1],11,1) == 1) ? 
                     (*InstructionNo = InstNo[0])/* CHK2 */
                   : (*InstructionNo = InstNo[0]+9);/* CMP2 */
                  break;
               case 94 : /* special case for DIVS,DIVSL,DIVU,DIVUL  */
               case 97 :
                  if (GetBits(OpWord[1],0,3) == GetBits(OpWord[1],12,3))
                     *InstructionNo = InstNo[0] + 1;
                  else
                     *InstructionNo = InstNo[0];
                  break;
               case 145 : /* special case for MULS, MULU */
               case 147 :
                  if (GetBits(OpWord[1],10,1) == 1) /* Check Dh:Dl/Dl */
                     *InstructionNo = InstNo[0] + 1; /* Dh:Dl */
                  else
                     *InstructionNo = InstNo[0];
                  break;
               default :
                  for (lp3 = 0; lp3 < lp2; lp3++) {
                     if ((EaNo = CheckEa(*OpWord,OpWord[InstructionSet
                           [InstNo[lp3]].EaPos])) == EA_ERR)
                        return ER_DAD_EA_INVALID;
                     if (((EaClass[InstructionSet[InstNo[lp3]].EaType]) &
                        (CheckBit << (EaNo - 1))) != 0) {
                        *InstructionNo = InstNo[lp3];
                        break;
                     }
                  }
                  break;
            }
         }
         break;
   }
   *SizeNo = InstructionSet[*InstructionNo].OpSize;
   if ((*SizeNo == TBW) || (*SizeNo == TWL) || (*SizeNo == TBWL)) {
      switch (GetBits(OpWord[0],6,2)) {
        case 0 :
           *SizeNo = TB;
           break;
        case 1 :
           *SizeNo = TW;
           break;
        case 2 :
           *SizeNo = TL;
           break;
        default :
           return(ER_DAD_INST_SIZE_UNDETERMINED);
      }
   }
   return(GOOD);
}


/*****************************************************************************
**
**    Identify
**
*****************************************************************************/
RETCODE Identify(U16 *InstructionNo, U16 *SizeNo, U16 *OpWord) {
/* Through the object code to identify which instruction */
   RETCODE ret;

   *SizeNo = 0xFF;
   ret = GOOD;
   if ((GetBits(OpWord[0],12,4) == 15) && (GetBits(OpWord[0],9,3) == 1))
      ret = Coprocessor(InstructionNo,SizeNo,OpWord);
   else
      ret = Processor(InstructionNo,SizeNo,OpWord);

   return(ret);
}

/*****************************************************************************
**
**    RegisterList
**
*****************************************************************************/
RETCODE RegisterList (OPERATOR *opSet, U8 *opIndex)
{
   LOOP_VAR   loop,loop1,loop2,loop3;
   BOOLEAN    rever;

   rever = OFF;
   if (GetBits(opSet->objCode[0],3,3) == 4)
      rever = ON;
   /* display A0-A7,D0-D7 */
   for (loop3 = 0; loop3 < 2; loop3++) {
      for (loop = 0; loop < 8; loop++) {
         loop1 = loop;
         while((GetBits(opSet->objCode[1],loop1+loop3*8,1) != 1) &&
               (loop1 < 8)) {
            loop1++;
         }
         loop  = loop1;
         loop2 = loop1;
         while((GetBits(opSet->objCode[1],loop2+loop3*8,1) != 0) &&
               (loop2 < 8)) {
            loop2++;
         }
         if (rever == OFF) {
            loop  = loop2;
            if (loop1 != loop2) {
               if ((loop2-loop1) == 1) {
                  opSet->opString [*opIndex] = RegType[loop3];
                  (*opIndex)++;
                  opSet->opString [*opIndex] = (U8)('0' + loop1);
                  (*opIndex)++;
                  opSet->opString [*opIndex] = '/';
                  (*opIndex)++;
               }
               else {
                  opSet->opString [*opIndex] = RegType[loop3];
                  (*opIndex)++;
                  opSet->opString [*opIndex] = (U8)('0' + loop1);
                  (*opIndex)++;
                  opSet->opString [*opIndex] = '-';
                  (*opIndex)++;
                  opSet->opString [*opIndex] = RegType[loop3];
                  (*opIndex)++;
                  opSet->opString [*opIndex] = (U8)('0' + loop2-1);
                  (*opIndex)++;
                  opSet->opString [*opIndex] = '/';
                  (*opIndex)++;
               }
            }
        }
        else {
            loop  = loop2;
            if (loop1 != loop2) {
               if ((loop2-loop1) == 1) {
                  opSet->opString [*opIndex] = RegType[1 - loop3];
                  (*opIndex)++;
                  opSet->opString [*opIndex] = (U8)('0' + 7 -loop1);
                  (*opIndex)++;
                  opSet->opString [*opIndex] = '/';
                  (*opIndex)++;
               }
               else {
                  opSet->opString [*opIndex] = RegType[1 - loop3];
                  (*opIndex)++;
                  opSet->opString [*opIndex] = (U8)('0' + 7 -loop1);
                  (*opIndex)++;
                  opSet->opString [*opIndex] = '-';
                  (*opIndex)++;
                  opSet->opString [*opIndex] = RegType[1 - loop3];
                  (*opIndex)++;
                  opSet->opString [*opIndex] = (U8)('0' + 7 - (loop2-1));
                  (*opIndex)++;
                  opSet->opString [*opIndex] = '/';
                  (*opIndex)++;
               }
            }
        }
      }
   }

   if (*opIndex == 0)
      return(ER_DAD_REG_INVALID);
   if (opSet->opString[(*opIndex)-1] == '/') {
      (*opIndex)--; /* delete '/' */
      opSet->opString[*opIndex] = 0x00;
   }
   return(GOOD);
}

/*****************************************************************************
**
**    CoRegisterList
**
*****************************************************************************/
RETCODE CoRegisterList (OPERATOR *opSet, U8 *opIndex)
{
   LOOP_VAR   loop,loop1,loop2;

   /* display FP0-FP7 */
      for (loop = 0; loop < 8; loop++) {
         loop1 = loop;
         while((GetBits(opSet->objCode[1],loop1,1) != 1) &&
               (loop1 < 8)) {
            loop1++;
         }
         loop  = loop1;
         loop2 = loop1;
         while((GetBits(opSet->objCode[1],loop2,1) != 0) &&
               (loop2 < 8)) {
            loop2++;
         }
         loop  = loop2;
         if (loop1 != loop2) {
            if ((loop2-loop1) == 1) {
                      strcat((LPSTR)&opSet->opString[*opIndex],"FP");
                      (*opIndex)+=2;
                      opSet->opString [*opIndex] = (U8)('0' + loop1);
                      (*opIndex)++;
                      opSet->opString [*opIndex] = '/';
                      (*opIndex)++;
                   }
                   else {
                      strcat((LPSTR)&opSet->opString[*opIndex],"FP");
                      (*opIndex)+=2;
                      opSet->opString [*opIndex] = (U8)('0' + loop1);
                      (*opIndex)++;
                      opSet->opString [*opIndex] = '-';
                      (*opIndex)++;
                      strcat((LPSTR)&opSet->opString[*opIndex],"FP");
                      (*opIndex)+=2;
                      opSet->opString [*opIndex] = (U8)('0' + loop2-1);
                      (*opIndex)++;
               opSet->opString [*opIndex] = '/';
               (*opIndex)++;
            }
         }
      }
   if (opSet->opString[(*opIndex)-1] == '/') {
      (*opIndex)--; /* delete '/' */
      opSet->opString[*opIndex] = 0x00;
   }
   return(GOOD);
}

/*****************************************************************************
**
**    CoControlReg
**
*****************************************************************************/
RETCODE CoControlReg (OPERATOR *opSet, U8 *opIndex)
{
   LOOP_VAR   loop;
   U8         Pos,base;
   LPSTR ControlReg81[] = {
                 "FPIAR",
                 "FPSR",
                 "FPCR"
   };

   /* display FPCR/FPSR/FPIAR */
   base = ctoi(*(opSet->operand+1));
   Pos  = ctoi(*(opSet->operand+2));
   for (loop = 0; loop < 3; loop++) {
      if (GetBits(opSet->objCode[base],Pos+loop,1) > 0) {
         strcat((LPSTR)&opSet->opString[*opIndex],ControlReg81[loop]);
                (*opIndex)+=strlen((LPSTR)ControlReg81[loop]);
         opSet->opString [*opIndex] = '/';
         (*opIndex)++;
      }
   }
   (*opIndex)--;
   opSet->opString [*opIndex] = 0x00;
   return(GOOD);
}


/*****************************************************************************
**
**    EAFieldX
**
*****************************************************************************/
RETCODE EAFieldX(OPERATOR *opSet, U8 *opIndex, LPSTR *eaPtr,
                 BOOLEAN SuppressFlag)
{
   if ((SuppressFlag == ON) &&
       (GetBits(opSet->objCode[opSet->eaPos],6,1) == 1)) {
      if (opSet->opString[*opIndex-1] == ',') {
    (*opIndex)--;
    opSet->opString[*opIndex] = '\0';
      }
      (*eaPtr)+=2;
   }
   else {
      switch (GetBits(opSet->objCode[opSet->eaPos],15,1)) {
    case 0 :
       opSet->opString [*opIndex] = 'D';
       break;
    case 1 :
       opSet->opString [*opIndex] = 'A';
       break;
      }
      (*opIndex)++;
      opSet->opString [*opIndex] = GetBits(opSet->objCode[opSet->eaPos],12,3) + '0';
      (*opIndex)++;
      opSet->opString [*opIndex] = '.';
      (*opIndex)++;
      switch (GetBits(opSet->objCode[opSet->eaPos],11,1)) {
    case 0 :
       opSet->opString [*opIndex] = 'W';
       break;
    case 1 :
       opSet->opString [*opIndex] = 'L';
       break;
      };
      (*opIndex)++;
      opSet->opString [*opIndex] = '*';
      (*opIndex)++;
      switch (GetBits(opSet->objCode[opSet->eaPos],9,2)) {
    case 0 :
       opSet->opString [*opIndex] = '1';
       break;
    case 1 :
       opSet->opString [*opIndex] = '2';
       break;
    case 2 :
       opSet->opString [*opIndex] = '4';
       break;
    case 3 :
       opSet->opString [*opIndex] = '8';
            break;
      };
      (*opIndex)++;
      (*eaPtr)+=2;
   }
   return(GOOD);
}


/*****************************************************************************
**
**    EAFieldPC
**
*****************************************************************************/
RETCODE EAFieldPC(OPERATOR *opSet, U8 *opIndex, LPSTR *eaPtr,
                  BOOLEAN SuppressFlag, S32 disp, DASM_INFO *dasmInfo,
                  U32 addrOffset) {
   
   U32 disp2;

   dasmInfo->knowAddr = TRUE;
   if ((SuppressFlag == ON) &&
       (GetBits(opSet->objCode[opSet->eaPos],7,1) == 1)) {
      strcat((LPSTR)opSet->opString,"ZPC");
      (*opIndex)+=3;
      dasmInfo->target = disp;
      
   }
   else {
      strcat((LPSTR)opSet->opString,"PC");
      (*opIndex)+=2;
      if (disp > 0) {
         dasmInfo->target = addrOffset + (U32) disp + 2L;
      } else {
         /* subtract the negative displacement from the */
         /* current disassembly address.  The pc is currently */
         /* two bytes past the disassembly address so we must */
         /* compensate. */
         disp2 = (U32) disp;
         dasmInfo->target = addrOffset - ( (~disp2) + 1) + 2L;
      }
   }
   (*eaPtr)+=2;
   return(GOOD);
}

/*****************************************************************************
**
**    EAFieldRegAD
**
*****************************************************************************/
RETCODE EAFieldRegAD(OPERATOR *opSet, U8 *opIndex, LPSTR *eaPtr,
                     BOOLEAN SuppressFlag,BOOLEAN nullFlag)
{

   if ((SuppressFlag == ON) &&
       (GetBits(opSet->objCode[opSet->eaPos],7,1) == 1)) {
      if (opSet->opString[*opIndex-1] == ',') {
         (*opIndex)--;
         opSet->opString[*opIndex] = '\0';
      }
      if ((*(*eaPtr+2) == ',') && (nullFlag == ON))
         (*eaPtr)++;

   }
   else {
      opSet->opString [*opIndex] = **eaPtr;
      (*opIndex)++;
      opSet->opString [*opIndex] = GetBits(opSet->objCode[0],0,3) + '0';
             (*opIndex)++;
   }
   (*eaPtr)+=2;
   return(GOOD);
}


/*****************************************************************************
**
**    EAFieldData
**
*****************************************************************************/
RETCODE EAFieldData(OPERATOR *opSet, U8 *opIndex, LPSTR *eaPtr)
{
   opSet->opString [*opIndex] = **eaPtr;
   (*opIndex)++;
   (*eaPtr)+=4;
   switch (opSet->size[0]) {
      case ' ' :
         break;
      case 'B' :
         GetIntString((LPSTR)opSet->opString, 
            (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,1);
         opSet->opLength++;
         break;
      case 'W' :
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,2);
         opSet->opLength++;
         break;
      case 'L' :
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,4);
    opSet->opLength+=2;
         break;
      case 'Q' :
         break;
      case 'S' :
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,4);
         opSet->opLength+=2;
         break;
      case 'D' :
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,4);
         opSet->opLength+=2;
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos+2]),opIndex,4);
                opSet->opLength+=2;
    break;
      case 'X' :
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,4);
         opSet->opLength+=2;
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos+2]),opIndex,4);
         opSet->opLength+=2;
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos+4]),opIndex,4);
         opSet->opLength+=2;
         break;
      case 'P' :
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,4);
         opSet->opLength+=2;
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos+2]),opIndex,4);
         opSet->opLength+=2;
         GetIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos+4]),opIndex,4);
         opSet->opLength+=2;
         break;
   }
   return(GOOD);
}


/*****************************************************************************
**
**    AddrSymbol
**
*****************************************************************************/
RETCODE AddrSymbol(LPSTR OpString, U16 *Code, U8 *opIndex, U8 size,
                   BOOLEAN DadSymbol, DASM_INFO FAR *dasmInfo) {
   U32 lData;
   U16 wData;
   DESCRIPTOR  dadAddr;
   U8 operandName[MAX_SYMNAME_LENGTH];
   RETCODE err = GOOD;

   if((err=AdrCreateAddress(&dadAddr))!=GOOD)
      return(err);
   switch (size) {
      case 1 :
         lData = Code[0];
         if (GetBits(lData,15,1) == 1)
            lData += 0xffff0000L;
         break;
      case 2 :
         lData = Code[0];
         wData = Code[1];
         lData = (lData << 16) +wData;
         break;
   }
   if((err=AdrSetAddrOffset(dadAddr, lData))!= GOOD ) {
      AdrDestroyAddress(dadAddr);
      return(err);
   }
   dasmInfo->knowAddr = TRUE;
   dasmInfo->target = lData;

   if ((err = AdrConvAddressToTextWithParams(dadAddr,FALSE,TRUE,
         operandName)) != GOOD)
      return err;
   if( DadSymbol && dasmInfo->transfer) {
      // filter only control transfer instructions
      MEM_ADDR_CLASS memoryClass;
      SYM_TYPE_TYPE symbolType;
      SYM_DESCRIPTOR outputSymbol,funcDescriptor,moduleDescriptor;
      U32 offset;
      DESCRIPTOR symNameDesc;
      LPSTR strPtr;

      if ((SymMapAddr2Symbol(dadAddr,&memoryClass,&symbolType,
          &offset,&outputSymbol,&funcDescriptor,&moduleDescriptor)) == GOOD) {
         if( outputSymbol != NULL_SYMBOL ) {
            if ((SymGetSymbolName(outputSymbol, &symNameDesc)) == GOOD) {
               strPtr = stpcpy(operandName, (LPSTR)symNameDesc);
               if(offset) {
                  wsprintf(strPtr," + %ld",offset);
               }
               TFree((LPSTR)symNameDesc);
            }
         }
      }
   }
   strcat((LPSTR)OpString,operandName);
   (*opIndex)+=strlen((LPSTR)operandName);

   /* Notes: 04/22/93 - Nghia
   ** Address symbol look up failed is a very usual case. Therefore, only
   ** need to report error from other component other than symbol table
   ** Fixed ppr8078
   ** 07/29/93 - Nghia - Revised to reflect new error code changes.
   ** Since error code no longer has COMPONENT_ID, checking for error
   ** from the symbol server is imposssible.  Beside, no need to report
   ** error any way.
   */
   return(AdrDestroyAddress(dadAddr));
}

/*****************************************************************************
**
**    EAFieldAddr
**
*****************************************************************************/
RETCODE EAFieldAddr(OPERATOR *opSet, U8 *opIndex, LPSTR *eaPtr,
                    BOOLEAN DadSymbol, DASM_INFO FAR *dasmInfo) {

   RETCODE err;

   (*eaPtr)++;
   switch (**eaPtr) {
      case '0' :   /* !!! I don't ever see this case happening??? */
         GetTwoCompIntString((LPSTR)opSet->opString,
              (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,1);
        opSet->opLength++;
        break;
      case '1' :
         if ((err = AddrSymbol((LPSTR)opSet->opString,
              (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,1,
              DadSymbol,dasmInfo)) != GOOD)
            return err;
         opSet->opLength++;
         break;
      case '2' :
         if ((err = AddrSymbol((LPSTR)opSet->opString,
              (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,2,
              DadSymbol,dasmInfo)) != GOOD)
            return err;
         opSet->opLength+=2;
         break;
   }
   (*eaPtr)+=2;
   return(GOOD);
}

/*****************************************************************************
**
**    EAFieldOuter
**
*****************************************************************************/
RETCODE EAFieldOuter(OPERATOR *opSet, U8 *opIndex, LPSTR *eaPtr) {

   (*eaPtr)++;
   switch (**eaPtr) {
      case '2' :
         switch (GetBits(opSet->objCode[opSet->eaPos],6,1)) {   /* IS */
            case 0 :
               switch (GetBits(opSet->objCode[opSet->eaPos],0,3)) { /* I/IS */
                  case 0 :  /* No memory indirection */
                     break;
                  case 4 :  /* Reserved */
                     return(EA_ERR);
                  case 1 :  /* Null Displacement */
                  case 5 :
                     (*opIndex)--;
                     break;
                  case 2 :  /* Word Displacement */
                  case 6 :
                     GetTwoCompIntString((LPSTR)opSet->opString,
                        (U16 *)&(opSet->objCode[opSet->opLength]),opIndex,2);
                     opSet->opLength++;
                     break;
                  case 3 :  /* Long  Displacement */
                  case 7 :
                     GetTwoCompIntString((LPSTR)opSet->opString,
                        (U16 *)&(opSet->objCode[opSet->opLength]),opIndex,4);
                     opSet->opLength+=2;
                     break;
               }
               break;
            case 1 :
               switch (GetBits(opSet->objCode[opSet->eaPos],0,3)) { /* I/IS */
                  case 0 :  /* No memory indirection */
                     break;
                  case 1 :  /* Null Displacement */
                     (*opIndex)--;
                     break;
                  case 2 :  /* Word Displacement */
                     GetTwoCompIntString((LPSTR)opSet->opString,
                        (U16 *)&(opSet->objCode[opSet->opLength]),opIndex,2);
                     opSet->opLength++;
                     break;
                  case 3 :  /* Long  Displacement */
                     GetTwoCompIntString((LPSTR)opSet->opString,
                        (U16 *)&(opSet->objCode[opSet->opLength]),opIndex,4);
                     opSet->opLength+=2;
                     break;
                  case 4 :  /* Reserved */
                  case 5 :  /* Reserved */
                  case 6 :  /* Reserved */
                  case 7 :  /* Reserved */
                     return(EA_ERR);
                      }
               break;
         }
         break;
      default :
         return(EA_ERR);
   }
   (*eaPtr)+=2;
   return(GOOD);
}

/*****************************************************************************
**
**    EAFieldBDisp
**
*****************************************************************************/
RETCODE EAFieldBDisp(OPERATOR *opSet, U8 *opIndex, LPSTR *eaPtr,
                     BOOLEAN *SuppressFlag, BOOLEAN *nullFlag, S32 *disp) {
   (*eaPtr)++;
   switch (**eaPtr) {
      case '0' :
         GetTwoCompIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,1);
         *disp = (S32) GetBits(opSet->objCode[opSet->eaPos],0,8);
         if ( *disp & 0x80L ) *disp |= 0xffffff00L;
         opSet->opLength++;
         break;
      case '1' :
         GetTwoCompIntString((LPSTR)opSet->opString,
            (U16 *)&(opSet->objCode[opSet->eaPos]),opIndex,2);
         *disp = (S32) opSet->objCode[opSet->eaPos];
         if (*disp & 0x8000L) *disp |= 0xffff0000L;
         opSet->opLength++;
         break;
      case '2' :
         *SuppressFlag = ON;
         switch (GetBits(opSet->objCode[opSet->eaPos],4,2)) { /* BD SIZE */
            case EA_EXT_FRMT_BD_NULL  :  /* Null Base Displacement */
               *nullFlag = ON;
               *disp = 0L;
               opSet->opLength++;
               (*eaPtr)++;
               break;
            case EA_EXT_FRMT_BD_WORD :  /* Word Base Displacement */
               opSet->opLength++;
               GetTwoCompIntString((LPSTR)opSet->opString,
                  (U16 *)&(opSet->objCode[opSet->opLength]),opIndex,2);
               *disp = (S32) opSet->objCode[opSet->opLength];
               if (*disp & 0x8000L) *disp |= 0xffff0000L;
               opSet->opLength++;
               break;
            case EA_EXT_FRMT_BD_LONG :  /* Long Base Displacement */
               opSet->opLength++;
               GetTwoCompIntString((LPSTR)opSet->opString,
                  (U16 *)&(opSet->objCode[opSet->opLength]),opIndex,4);
               *disp = (S32) opSet->objCode[((opSet->opLength) + 1)];
               *disp |= ((S32) opSet->objCode[opSet->opLength] << 16);
               opSet->opLength+=2;
               break;
            case EA_EXT_FRMT_BD_RESERVED : /* reserved opcode */
               *disp = 0L;
               return(EA_ERR);
         }
         break;
      default :
         return(EA_ERR);
   }
   (*eaPtr)+=2;
   return(GOOD);
}

/*****************************************************************************
**
**    ProcessEffective
**
*****************************************************************************/
RETCODE ProcessEffective(OPERATOR *opSet, U8 *opIndex, BOOLEAN DadSymbol,
                         DASM_INFO FAR *dasmInfo, U32 addrOffset) {
   U32    CheckBit = 0x01;
   U16    EaNo;
   LPSTR  eaPtr;
   BOOLEAN SuppressFlag,nullFlag;
   RETCODE err;
   S32 disp;

   SuppressFlag = OFF;
   nullFlag = OFF;
   if ((EaNo = CheckEa(*opSet->objCode,
         opSet->objCode[opSet->eaPos])) == EA_ERR)
      return ER_DAD_EA_INVALID;
   if ((EaClass[opSet->eaType] & (CheckBit << (EaNo - 1))) == 0) {
      return(ER_DAD_EA_INVALID); /* the Instruction can't use this EA type */
   }
   else {
      eaPtr = (LPSTR)EaSet[EaNo];
      while (*eaPtr!='\0') {
         switch (*eaPtr) {
            case '[' :
            case ']' :
            case '(' :
            case ')' :
            case '-' :
            case '+' :
            case ',' :
               opSet->opString [*opIndex] = *eaPtr;
               (*opIndex)++;
               eaPtr++;
               break;
            case 'X' :
               if ((err = EAFieldX(opSet,opIndex,&eaPtr,SuppressFlag))
                  != GOOD) return(err);
               /* can't generate a known target address with an index */
               /* register.  The register is only valid at one location */
               if (dasmInfo->knowAddr == TRUE) dasmInfo->knowAddr = FALSE;
               break;
            case 'b' :
               if ((err = EAFieldBDisp(opSet, opIndex, &eaPtr, &SuppressFlag,
                  &nullFlag, &disp)) != GOOD) return(err);
               break;
            case 'P' :
               if ((err = EAFieldPC(opSet, opIndex, &eaPtr, SuppressFlag,
                                    disp, dasmInfo, addrOffset)) 
                  != GOOD) return(err);
               break;
            case 'A' :
            case 'D' :
               if ((err = EAFieldRegAD(opSet, opIndex, &eaPtr, SuppressFlag,
                  nullFlag)) != GOOD) return(err);
               break;
            case '#' :
               if ((err = EAFieldData(opSet, opIndex, &eaPtr)) != GOOD)
                  return(err);
               break;
            case 'd' : 
               if ((err = EAFieldAddr(opSet, opIndex, &eaPtr, DadSymbol,
                  dasmInfo)) != GOOD) return(err);
               break;
            case 'o' :
               if ((err = EAFieldOuter(opSet, opIndex, &eaPtr)) != GOOD)
                  return(err);
               break;
         }
      }
   }
   return(GOOD);
}


/*****************************************************************************
**
**    ProcessMnemonic
**
*****************************************************************************/
RETCODE ProcessMnemonic(OPERATOR *opSet) {
   U8      ccType;
   U8 FAR *charPtr, FAR **condTblPtr;
   condTblPtr = Condition;
   if ((charPtr = (U8 FAR *)strstr((LPSTR)opSet->mnemonic,(LPSTR)"cc")) != NULL) {
      switch (opSet->mnemonic[0]) {
         case 'B' :  /* Bcc */
            ccType = GetBits(opSet->objCode[0],8,4);
            if ((ccType == 0) || (ccType == 1))
               return(ER_DAD_INST_NOT_FOUND);
            else if (ccType > NUM_PROC_COND_CODES)
               return(ER_DAD_INST_NOT_FOUND);
            break;
         case 'D' :  /* DBcc */
         case 'S' : /* Scc */
         case 'T' : /* TRAPcc */
            ccType = GetBits(opSet->objCode[0],8,4);
            if (ccType > NUM_PROC_COND_CODES)
               return(ER_DAD_INST_NOT_FOUND);
            break;
         case 'F' :
            condTblPtr = CoCondition;
            switch (opSet->mnemonic[1]) {
               case 'B' :  /* FBcc */
                  ccType = GetBits(opSet->objCode[0],0,6);
                  if (ccType >= NUM_FP_COND_CODES)
                     return(ER_DAD_INST_NOT_FOUND);
                  break;
               case 'D' : /* FDBcc */
               case 'S' : /* FScc */
               case 'T' : /* FTRAPcc */
                  ccType = GetBits(opSet->objCode[1],0,6);
                  if (ccType >= NUM_FP_COND_CODES) 
                     return(ER_DAD_INST_NOT_FOUND);
                  break;
            }
      }
      charPtr[0] = 0x00; /* \0 */
      strcat((LPSTR)opSet->mnemonic,(LPSTR)condTblPtr[ccType]);
   }
   if ((charPtr = (U8 FAR *)strstr((LPSTR)opSet->mnemonic,(LPSTR)"d")) != NULL) {
      ccType = GetBits(opSet->objCode[0],8,1);
      charPtr[0] = 0x00; /* \0 */
      strcat((LPSTR)opSet->mnemonic,(LPSTR)ShiftType[ccType]);
   }
   return(GOOD);
}

/*****************************************************************************
**
**    VDataParameter
**
*****************************************************************************/
RETCODE VDataParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8         base,digBuf[10];
   U16        wData;

   (opSet->operand)+=2;
   base   = ctoi(*(opSet->operand));
   switch (base) {
      case 3 :     /* v03 */
      case 4 :     /* v04 */
         wData = GetBits(opSet->objCode[0],0,base);
         sprintf((LPSTR)digBuf,"%X",wData);
         strcat((LPSTR)opSet->opString ,(LPSTR)digBuf);
         (*opIndex)+=strlen((LPSTR)digBuf);
         break;
   }
   (opSet->operand)++;
   return(GOOD);
}

/*****************************************************************************
**
**    BDataParameter
**
*****************************************************************************/
RETCODE BDataParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8  base;

   (opSet->operand)++;
   base   = ctoi(*(opSet->operand));
   switch (base) {
      case 0 :     /* b08 */
         GetIntString((LPSTR)opSet->opString,(U16 *)&(opSet->objCode[1]),opIndex,1);
         break;
      case 1 :     /* b10 */
         GetIntString((LPSTR)opSet->opString,(U16 *)&(opSet->objCode[1]),opIndex,2);
         break;
      case 2 :     /* b20 */
         GetIntString((LPSTR)opSet->opString,(U16 *)&(opSet->objCode[1]),opIndex,4);
         break;
   }
   (opSet->operand)+=2;
   return(GOOD);
}

/*****************************************************************************
**
**    dDispParameter
**
*****************************************************************************/
RETCODE dDispParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8  base;

   (opSet->operand)++;
   base   = ctoi(*(opSet->operand));
   switch (base) {
      case 1 :     /* d10 */
         GetTwoCompIntString((LPSTR)opSet->opString,
               (U16 *)&(opSet->objCode[1]),opIndex,2);
         break;
      case 2 :     /* d20 */
         GetTwoCompIntString((LPSTR)opSet->opString,
               (U16 *)&(opSet->objCode[1]),opIndex,4);
         break;
   }
   (opSet->operand)+=2;
   return(GOOD);
}

/*****************************************************************************
**
**    JDataParameter
**
*****************************************************************************/
RETCODE JDataParameter(OPERATOR *opSet, U8 *opIndex, U32 addrOffset, 
                       DASM_INFO FAR *dasmInfo) {
   U8         digBuf[10];
   U16        wData;
   U32        lData;
   DESCRIPTOR address;
   RETCODE err;
   
   (opSet->operand)++;
   switch (*(opSet->operand)) {
      case '0':     /* j08 */
         lData = GetBits(opSet->objCode[0],0,8);
         if (GetBits(lData,7,1) == 1) 
            lData += (addrOffset + 2 + 0xffffff00L);
         else
            lData = (lData + addrOffset+2);
         break;
      case '1':     /* j10 */
         lData = GetBits(opSet->objCode[1],0,16);
         if (GetBits(lData,15,1) == 1) 
            lData += (addrOffset + 2 + 0xffff0000L);
         else lData += (addrOffset+2) ;
         break;
      case '2':     /* j20 */
         lData = GetBits(opSet->objCode[1],0,16);
         wData = GetBits(opSet->objCode[2],0,16);
         lData = (lData << 16) + wData;
         if (GetBits(lData,31,1) == 1) {
            lData = TwoComplement(lData);
            lData =  (-lData) + (addrOffset+2);
         }
         else
            lData += (addrOffset+2);
         break;
   }
   if ((err = AdrCreateAddress(&address)) != GOOD) return(err);
   if ((err = AdrSetAddrOffset(address, lData)) != GOOD) {
      AdrDestroyAddress(address);
      return(err);
   }
   if ((err = AdrConvAddressToTextWithParams(address, FALSE, TRUE, digBuf))
       != GOOD) {
      AdrDestroyAddress(address);
      return(err);
   }
   strcat((LPSTR)opSet->opString ,(LPSTR)digBuf);
   if ((err = AdrDestroyAddress(address)) != GOOD) return(err);
   (*opIndex)+=strlen((LPSTR)digBuf);
   (opSet->operand)+=2;
   dasmInfo->knowAddr = TRUE;
   dasmInfo->target = lData;
   return(GOOD);
}

/*****************************************************************************
**
**    ODataParameter
**
*****************************************************************************/
RETCODE ODataParameter(OPERATOR *opSet, U8 *opIndex)
{
   (opSet->operand)++;
   switch (*(opSet->operand)) {
      case '0':     /* o08 */
         GetTwoCompIntString((LPSTR)opSet->opString,
               (U16 *)&(opSet->objCode[0]),opIndex,1);
         break;
      case '1':     /* o10 */
         GetIntString((LPSTR)opSet->opString,
               (U16 *)&(opSet->objCode[2]),opIndex,2);
         break;
      case '3':     /* o30 */
         GetIntString((LPSTR)opSet->opString,
               (U16 *)&(opSet->objCode[2]),opIndex,2);
         break;
      case '4':     /* o40 */
         GetIntString((LPSTR)opSet->opString,(U16 *)&(opSet->objCode[2]),opIndex,4);
         break;
   }
   (opSet->operand)+=2;
   return(GOOD);
}

/*****************************************************************************
**
**    PDataParameter
**
*****************************************************************************/
RETCODE PDataParameter(OPERATOR *opSet, U8 *opIndex){
   U8         pos,base,digBuf[10];
   U16        wData;
   (opSet->operand)++;
   base   = ctoi(*(opSet->operand));
   (opSet->operand)++;
   pos    = ctoi(*(opSet->operand));
   wData = GetBits(opSet->objCode[base],pos,3);
   if ((wData == 0) && (base == 0))
      wData = 8;
   sprintf((LPSTR)digBuf,"%X",wData);
   strcat((LPSTR)opSet->opString ,(LPSTR)digBuf);
   (*opIndex)+=strlen((LPSTR)digBuf);
   (opSet->operand)++;
   return(GOOD);
}

/*****************************************************************************
**
**    WDataParameter
**
*****************************************************************************/
RETCODE WDataParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8         pos,base,digBuf[10];
   U16        wData;


   (opSet->operand)++;
   base   = ctoi(*(opSet->operand));
   (opSet->operand)++;
   pos    = ctoi(*(opSet->operand));
   wData = GetBits(opSet->objCode[base],pos,5);
   if(GetBits(opSet->objCode[base],pos+5,1) == 1) {
      wData = (wData & 0x07);
      sprintf((LPSTR)digBuf,"D%d",wData);
   }
   else {
      if ((pos == 0) && (wData == 0))
         wData = 0x20;
      sprintf((LPSTR)digBuf,"%2.2X",wData);
   }
   strcat((LPSTR)opSet->opString ,(LPSTR)digBuf);
   (*opIndex)+=strlen((LPSTR)digBuf);
   (opSet->operand)++;
   return(GOOD);
}

/*****************************************************************************
**
**    SDataParameter
**
*****************************************************************************/
RETCODE SDataParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8         length,pos,digBuf[10];
   U16        wData;

   (opSet->operand)++;
   pos   = ctoi(*(opSet->operand));
   (opSet->operand)++;
   length    = ctoi(*(opSet->operand));
   wData = GetBits(opSet->objCode[1],pos,length);
   sprintf((LPSTR)digBuf,"%2.2X",wData);
   strcat((LPSTR)opSet->opString ,(LPSTR)digBuf);
   (*opIndex)+=strlen((LPSTR)digBuf);
   (opSet->operand)++;
   return(GOOD);
}

/*****************************************************************************
**
**    SecondEAParameter
**
*****************************************************************************/
RETCODE SecondEAParameter(OPERATOR *opSet, U8 *opIndex,BOOLEAN DadSymbol) {
   U16        wData,temp;
   RETCODE    ret;
   DASM_INFO dasmInfo;
   ret = GOOD;
   opSet->eaType = 6;
   opSet->eaPos = opSet->opLength;
   wData = opSet->objCode[0];  /* Store first op code */
   temp = (GetBits(opSet->objCode[0],6,3) << 3) +
           GetBits(opSet->objCode[0],9,3);    /* Get Dest EA */
   opSet->objCode[0] = (opSet->objCode[0] & 0xffc0) +temp;  /* copy Dest EA to Source EA */
   ret = ProcessEffective(opSet,opIndex,DadSymbol,&dasmInfo, 0L); /* ea */
   opSet->objCode[0] = wData;  /* Restore first op code */
   (opSet->operand)+=2;
   return(ret);
}

/*****************************************************************************
**
**    ADRegParameter
**
*****************************************************************************/
RETCODE ADRegParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8         tempNo,pos,base;

   opSet->opString [*opIndex] = *(opSet->operand);
   (*opIndex)++;
   (opSet->operand)++;
   base = ctoi(*(opSet->operand));
   (opSet->operand)++;
   pos = ctoi(*(opSet->operand));
   tempNo = GetBits(opSet->objCode[base],pos,3) + '0';
   opSet->opString [*opIndex] = tempNo;
   (opSet->operand)++;
   (*opIndex)++;
   return(GOOD);
}

/*****************************************************************************
**
**    XRegParameter
**
*****************************************************************************/
RETCODE XRegParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8         tempNo,base,pos,RegAD,RegPos;

   (opSet->operand)++;
   base = ctoi(*(opSet->operand));
   (opSet->operand)++;
   pos = ctoi(*(opSet->operand));
   (opSet->operand)++;
   RegPos = ctoi(*(opSet->operand));
   RegAD = GetBits(opSet->objCode[base],RegPos,1);
   opSet->opString [*opIndex] = RegType[RegAD];
   (*opIndex)++;
   tempNo = GetBits(opSet->objCode[base],pos,3) + '0';
   opSet->opString [*opIndex] = tempNo;
   (opSet->operand)++;
   (*opIndex)++;
   return(GOOD);
}

/*****************************************************************************
**
**    MRegParameter
**
*****************************************************************************/
RETCODE MRegParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8         tempNo,base,pos;

   (opSet->operand)++;
   base = ctoi(*(opSet->operand));
   (opSet->operand)++;
   pos = ctoi(*(opSet->operand));
   (opSet->operand)++;
   tempNo = GetBits(opSet->objCode[base],pos,3);
   switch (GetBits(opSet->objCode[base],13,3)) {
      case 0 :   /* TT */
    strcat((LPSTR)opSet->opString ,(LPSTR)MMUReg[tempNo+2]);
    (*opIndex)+=strlen((LPSTR)MMUReg[tempNo+2]);
    break;
      case 2 :  /* TC,SRP,CRP */
    strcat((LPSTR)opSet->opString ,(LPSTR)MMUReg[tempNo]);
    (*opIndex)+=strlen((LPSTR)MMUReg[tempNo]);
    break;
      case 3 :   /* MMUSR */
    strcat((LPSTR)opSet->opString ,(LPSTR)MMUReg[1]);
    (*opIndex)+=strlen((LPSTR)MMUReg[1]);
    break;
   }
   return(GOOD);
}


/*****************************************************************************
**
**    CORegParameter
**
*****************************************************************************/
RETCODE CORegParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8         tempNo,base,pos;
   RETCODE    ret;

   ret = GOOD;
   (opSet->operand)++;
   switch (*(opSet->operand)) {
      case 'c' :
         switch (GetBits(opSet->objCode[1],3,2)) {
            case 0 :
               switch (GetBits(opSet->objCode[1],0,3)) {
                  case 0 :
                  case 1 :
           tempNo = (GetBits(opSet->objCode[1],0,3));
                     strcat((LPSTR)opSet->opString ,(LPSTR)ControlReg0[tempNo]);
                     (*opIndex)+=strlen((LPSTR)ControlReg0[tempNo]);
                     break;
                  default :
                     return(ER_DAD_REG_INVALID);
               }
               break;
            case 1 :
               opSet->opString [*opIndex] = 'D';
               opSet->opString [(*opIndex)+1] =
                          GetBits(opSet->objCode[1],0,3) + '0';
               (*opIndex)+=2;
               break;
            case 2 :
               opSet->opString [*opIndex] =
                          GetBits(opSet->objCode[1],0,3) + '0';
               (*opIndex)++;
               break;
         }
         (opSet->operand)++;
         break;
      case 'p' : /* FP            */
         strcat((LPSTR)opSet->opString,"FP");
         (*opIndex)+=2;
         (opSet->operand)++;
         base = ctoi(*(opSet->operand));
         (opSet->operand)++;
         pos = ctoi(*(opSet->operand));
         tempNo = GetBits(opSet->objCode[base],pos,3) + '0';
    opSet->opString [*opIndex] = tempNo;
         (opSet->operand)++;
         (*opIndex)++;
         break;
      case 'l' : /* FP List       */
         ret = CoRegisterList(opSet,opIndex);
         (opSet->operand)+=3;
         break;
      case 'r' : /* FP List       */
         ret = CoControlReg(opSet,opIndex);
         (opSet->operand)+=3;
         break;
   }
   return(ret);
}

/*****************************************************************************
**
**    RegLstParameter
**
*****************************************************************************/
RETCODE RegLstParameter(OPERATOR *opSet, U8 *opIndex)
{
   U8         tempNo;
   RETCODE    ret;

   ret = GOOD;
   (opSet->operand)++;
   switch (*(opSet->operand)) {
      case 'c' :
         switch (GetBits(opSet->objCode[1],8,4)) {
            case 0 :
               tempNo = (GetBits(opSet->objCode[1],0,8));
               strcat((LPSTR)opSet->opString ,(LPSTR)ControlReg0[tempNo]);
               (*opIndex) += strlen((LPSTR)ControlReg0[tempNo]);
               break;
            case 8 :
               tempNo = (GetBits(opSet->objCode[1],0,8));
               strcat((LPSTR)opSet->opString ,(LPSTR)ControlReg8[tempNo]);
               (*opIndex) += strlen((LPSTR)ControlReg8[tempNo]);
               break;
         }
         break;
      case 'l' :
         ret = RegisterList(opSet,opIndex);
         (opSet->operand)+=3;
         break;
   }
   (opSet->operand)++;
   return(ret);
}

/*****************************************************************************
**
**    ProcessOperand
**
*****************************************************************************/
RETCODE ProcessOperand(OPERATOR *opSet, U32 addrOffset, BOOLEAN DadSymbol,
                       DASM_INFO FAR *dasmInfo) {
   U8         opIndex;
   RETCODE    ret;

   ret = GOOD;
   opIndex = 0;
   opSet->opLength = opSet->eaPos;
   while ( (*(opSet->operand) != '\0') && (ret == GOOD) ) {
      switch (*(opSet->operand)) {
         case ',' :
         case '#' :
         case '(' :
         case ')' :
         case '+' :
         case '-' :
         case ':' :
         case 'C' :
         case 'S' :
         case 'R' :
         case 'U' :
         case 'M' :
         case 'P' :
         case '{' :
         case '}' : /* reserved word */
            opSet->opString [opIndex] = *(opSet->operand);
            (opSet->operand)++;
            opIndex++;
            break;
         case 'v' : /*               */
            ret = VDataParameter(opSet,&opIndex);
            break;
         case 'b' : /*               */
            ret = BDataParameter(opSet,&opIndex);
            break;
         case 'd' : /*               */
            ret = dDispParameter(opSet,&opIndex);
            break;
         case 'j' :
            ret = JDataParameter(opSet,&opIndex,addrOffset,dasmInfo);
            break;
         case 'o' : /*               */
            ret = ODataParameter(opSet,&opIndex);
            break;
         case 'p' : /*               */
            ret = PDataParameter(opSet,&opIndex);
            break;
         case 'w' : /*               */
            ret = WDataParameter(opSet,&opIndex);
            break;
         case 's' : /*               */
            ret = SDataParameter(opSet,&opIndex);
            break;
         case 'e' :
            ret = ProcessEffective(opSet, &opIndex, DadSymbol,
                                   dasmInfo, addrOffset);/* ea */
            (opSet->operand)+=2;
            break;
         case 'E' :  /* Special case for move ea,ea */
            ret = SecondEAParameter(opSet,&opIndex,DadSymbol);
            break;
         case 'A' : /* reserved word */
         case 'D' : /* reserved word */
            ret = ADRegParameter(opSet,&opIndex);
            break;
         case 'T' : /* reserved word */
            opSet->operand++;
            ret = ADRegParameter(opSet,&opIndex);
            if (GetBits(opSet->objCode[1],12,3)
               != GetBits(opSet->objCode[1],0,3))
               ret = 0xff;
            break;
         case 'x' : /* reserved word */
            ret = XRegParameter(opSet,&opIndex);
            break;
         case 'm' : /* reserved word */
            ret = MRegParameter(opSet,&opIndex);
            break;
         case 'f' : /* fc            */
            ret = CORegParameter(opSet,&opIndex);
            break;
         case 'F' : /* FPIAR       */
            strcat((LPSTR)opSet->opString,"FPIAR");
            opIndex+=5;
            (opSet->operand)+=5;
            break;
         case 'r' : /* rc & rlist    */
            ret = RegLstParameter(opSet,&opIndex);
            break;
         case 'c' : /* caches        */
            (opSet->operand)+=5; /* !!! doesn't do anything - just inc past
                        operand so we don't get into an infinite loop */
            break;
         case 'z' : /* dc.w */
            /* force an error so the CreateDCWord below can correctly */
            /* fill in the data */
            ret = ER_DAD_INST_NOT_FOUND;
            break;
      }
   }
   /* make sure the processor understands the opcode just disassebled */
   /* if it doesn't then turn it into a DC.W string */
   if (((opSet->cpuType & cpuMask[cpuType]) != cpuMask[cpuType]) || ret)
      ret = CreateDCWord(opSet);

   return(ret);
}


/*****************************************************************************
**
**    TraceBufInst
**
*****************************************************************************/
RETCODE TraceBufInst(U16 FAR *OpWord, U32 addrOffset, BOOLEAN DadSymbol,
                  U8 *inst, DASM_INFO FAR *dasmInfo) {
   OPERATOR  opSet;
   RETCODE   err;

   if((err=DisassembleOpcode(OpWord,addrOffset,DadSymbol,&opSet,dasmInfo))
      != GOOD) return(err);
   if (inst != NULL) {
      strcat((LPSTR)inst,(LPSTR)space[2]);
      strcat((LPSTR)inst,(LPSTR)opSet.mnemonic);
      if (opSet.size[0] != ' ') {
         strcat((LPSTR)inst,(LPSTR)dot);
         strcat((LPSTR)inst,(LPSTR)opSet.size);
         strcat((LPSTR)inst,(LPSTR)space[MAX_MNEMONIC_SIZE - 
            (strlen((LPSTR)opSet.mnemonic)+2)]);
      }
      else {
         strcat((LPSTR)inst,(LPSTR)space[MAX_MNEMONIC_SIZE - 
            (strlen((LPSTR)opSet.mnemonic))]);
      }
      strcat((LPSTR)inst,(LPSTR)space[2]);
      strcat((LPSTR)inst,(LPSTR)opSet.opString);
   }
   /******** End Output inst ********/
   return(err);
}

/*****************************************************************************
**
**    IsCallOrRTS
**
*****************************************************************************/
RETCODE IsCallOrRTS(DESCRIPTOR startAddr, DESCRIPTOR calledAddr,
                    CALL_TYPE *type) {
   OPERATOR opSet;
   U32 addrOffset;
   U16  OpWord[MAX_CODE_LENGTH];
   RETCODE err = GOOD;
   DASM_INFO dasmInfo;

   if((err=AdrGetAddrOffset(startAddr,&addrOffset))!= GOOD) return(err);

   if((err=GetIntData(startAddr,(LPU8)OpWord))!=GOOD) return(err);

   if((err=DisassembleOpcode(OpWord,addrOffset,FALSE,&opSet,&dasmInfo))!=GOOD)
      return(err);
   addrOffset += dasmInfo.bytesUsed;

   if((err=AdrSetAddrOffset(startAddr,addrOffset))!= GOOD)
      return(err);
   if((err=AdrSetAddrOffset(calledAddr,addrOffset))!= GOOD)
      return(err);
   if( (strcmpi((LPSTR)opSet.mnemonic,"BSR") == 0)
      || (strcmpi((LPSTR)opSet.mnemonic,"JSR") == 0)
      || (strcmpi((LPSTR)opSet.mnemonic,"CALLM") == 0) ){
      *type = INST_CALL;
      if((err=AdrSetAddrOffset(calledAddr,dasmInfo.target)) != GOOD)
         return(err);
   }
   else if (strncmpi((LPSTR)opSet.mnemonic,"RT",2) == 0)
   /* compare all RT? instructions - RTM, D, E, R, and S */
      *type = INST_RETURN;
   else
      *type = INST_NONE;

   return(err);
}

/*****************************************************************************
**
**    IsTransfer
**
*****************************************************************************/
RETCODE IsTransfer(DESCRIPTOR startAddr, DESCRIPTOR transferAddr,
      TRANSFER_TYPE *transfer) {
   OPERATOR opSet;
   U32 addrOffset;
   U16  OpWord[MAX_CODE_LENGTH];
   RETCODE err = GOOD;
   DASM_INFO dasmInfo;

   if((err=AdrGetAddrOffset(startAddr,&addrOffset))!= GOOD) return(err);

   if((err=GetIntData(startAddr,(LPU8)OpWord))!=GOOD) return(err);

   if((err=DisassembleOpcode(OpWord,addrOffset,FALSE,&opSet,&dasmInfo))!=GOOD)
      return(err);
   addrOffset += dasmInfo.bytesUsed;

   if((err=AdrSetAddrOffset(startAddr,addrOffset))!= GOOD)
      return(err);

   transfer->transfer = dasmInfo.transfer;
   transfer->call = dasmInfo.call;
   transfer->destKnown = dasmInfo.knowAddr;
   if (dasmInfo.knowAddr) {
      if ((err = AdrSetAddrOffset(transferAddr, dasmInfo.target)) != GOOD)
         return(err);
   }

   return(GOOD);
}

/*****************************************************************************
**
**    DisassembleOpcode
**
*****************************************************************************/
RETCODE DisassembleOpcode(U16 FAR *OpWord, U32 addrOffset, BOOLEAN symbols,
                          OPERATOR FAR *opSet, DASM_INFO FAR *dasmInfo) {
   U16       InstructionNo,SizeNo;
   RETCODE   err = GOOD;

   InitOpSet(opSet,symbols);
   dasmInfo->flushableInst = FALSE;
   dasmInfo->conditional = FALSE;
   dasmInfo->call = FALSE;
   dasmInfo->bkptInst = FALSE;
   dasmInfo->transfer = FALSE;
   dasmInfo->returnType = FALSE;
   dasmInfo->knowAddr = FALSE;
   if((err=Identify(&InstructionNo,&SizeNo,OpWord)) != GOOD) {
      /* the failing opcode must be moved into the first location of 
         objcode.  This is done below by CatchData. */
      opSet->objCode[0] = OpWord[0];
      return(CreateDCWord(opSet));
   }
   switch(InstructionNo) {
      case 189 :  /* RTM     */  /* Return */
      case 190 :  /* RTD     */
      case 191 :  /* RTE     */
      case 192 :  /* RTR     */
      case 193 :  /* RTS     */
         dasmInfo->transfer = TRUE;
         dasmInfo->returnType = TRUE;
         break;
      case  53 :  /* BSR     */
      case  54 :  /* BSR     */
      case  55 :  /* BSR     */
      case 114 :  /* ILLEGAL */  /* Take Illegal Instruction Trap */
      case 116 :  /* JSR     */
      case 226 :  /* TRAP    */  /* InstTrap */
         dasmInfo->transfer = TRUE;
         dasmInfo->call = TRUE;
         break;
      case  50 :  /* BRA     */  /* Branches */
      case  51 :  /* BRA     */
      case  52 :  /* BRA     */
      case 115 :  /* JMP     */  /* Jumps */
         dasmInfo->transfer = TRUE;
         break;
      case  22 :  /* Bcc     */  /* Branches Conditionally */
      case  23 :  /* Bcc     */
      case  24 :  /* Bcc     */
      case  92 :  /* DBcc    */  /* Branches Conditionally */
         dasmInfo->transfer = TRUE;
         dasmInfo->conditional = TRUE;
         break;
      case 227 :  /* TRAPcc  */  /* Trap on Condition */
      case 228 :  /* TRAPcc  */
      case 229 :  /* TRAPcc  */
      case 230 :  /* TRAPV   */
         dasmInfo->transfer = TRUE;
         dasmInfo->call = TRUE;
         dasmInfo->conditional = TRUE;
         break;
      case 164 :  /* ORI     */  /* ManipluationSR */
      case 130 :  /* MOVE    */
      case 106 :  /* EORI    */
      case  21 :  /* ANDI    */
      case 177 :  /* PMOVE   */
      case 178 :  /* PMOVE   */
      case 179 :  /* PMOVEFD */
      case 180 :  /* PMOVE   */
      case 181 :  /* PMOVE   */
         dasmInfo->flushableInst = TRUE;
         break;
      case  49 :  /* BKPT    */  /* BreakPoint */
         dasmInfo->transfer = TRUE;
         dasmInfo->call = TRUE;
         dasmInfo->bkptInst = TRUE;
         break;
   }
   CatchData(InstructionNo,SizeNo,OpWord,opSet);
   if((err=ProcessMnemonic(opSet))!=GOOD) 
      return(CreateDCWord(opSet));
   if ((err=ProcessOperand(opSet,addrOffset,symbols,dasmInfo)) != GOOD)
      /* this branch should never be taken since the Create.. call has */
      /* already been performed in the ProcessOperand fcn. */
      return(CreateDCWord(opSet));
   dasmInfo->bytesUsed = (opSet->opLength*2);
   return(err);
}

/*****************************************************************************
**
**    DasmInst
**
*****************************************************************************/
RETCODE DasmInst(U16 FAR *OpWord, DESCRIPTOR startAddr,U8 *inst,
                 U8 *InstLen, BOOLEAN DadSymbol) {

   OPERATOR  opSet;
   LOOP_VAR  loop2,loop1;
   DASM_INFO dasmInfo;
   RETCODE   err;
   DESCRIPTOR dupAddr;
   U32 addrOffset;
   U32 maxAddrOffset;
   U8        WordBuf[ADDR_BUFF_SZ];

   if ((err = AdrDuplicateAddress(startAddr,&dupAddr)) != GOOD)
      return err;
   if ((err = AdrGetAddrOffset(startAddr,&addrOffset)) != GOOD) {
      AdrDestroyAddress(dupAddr);
      return err;
   }
   if ((err = AdrGetMaxOutputAddrOffset(startAddr,&maxAddrOffset)) != GOOD)
      return err;

   addrOffset &= maxAddrOffset;
   if ((err = AdrSetAddrOffset(dupAddr, addrOffset)) != GOOD) {
      AdrDestroyAddress(dupAddr);
      return(err);
   }
   err=DisassembleOpcode(OpWord,addrOffset,DadSymbol,&opSet,&dasmInfo);
   opSet.symbol = DadSymbol;

   /******** Start Output inst ********/
   for (loop1 = 0; loop1 <= ((opSet.opLength-1)/3); loop1++) {
      if (loop1 != 0) strcat((LPSTR)inst,(LPSTR)endOfLine);
   /*
   **     take it out to fix ppr 5575
   **      strcat((LPSTR)inst,(LPSTR)space[1]);
   **
   */
      if ((err = AdrConvAddressToTextWithParams(dupAddr,FALSE,TRUE,
                 (LPSTR)WordBuf)) != GOOD) {
         AdrDestroyAddress(dupAddr);
         return(err);
      }
      strcat((LPSTR)inst,(LPSTR)WordBuf);
      strcat((LPSTR)inst,(LPSTR)space[2]);
      for (loop2 = 0; (loop2 < 3); loop2++) {
         if (loop2 < (opSet.opLength-3*loop1)) {
            addrOffset += 2;
            if ((err = AdrSetAddrOffset(dupAddr,addrOffset)) != GOOD) {
               AdrDestroyAddress(dupAddr);
               return err;
            }
            sprintf((LPSTR)WordBuf,"%4.4X",opSet.objCode[loop1*3+loop2]);
            strcat((LPSTR)inst,(LPSTR)WordBuf);
         }
         else {
            strcat((LPSTR)inst,(LPSTR)space[4]);
         }
         strcat((LPSTR)inst,(LPSTR)space[1]);
      }
      strcat((LPSTR)inst,(LPSTR)space[1]);
      if (loop1 == 0) {
         strcat((LPSTR)inst,(LPSTR)opSet.mnemonic);
         if (opSet.size[0] != ' ') {
            strcat((LPSTR)inst,(LPSTR)dot);
            strcat((LPSTR)inst,(LPSTR)opSet.size);
            strcat((LPSTR)inst,(LPSTR)space[MAX_MNEMONIC_SIZE-
               (strlen((LPSTR)opSet.mnemonic)+2)]);
         }
         else {
            strcat((LPSTR)inst,(LPSTR)space[MAX_MNEMONIC_SIZE-
               (strlen((LPSTR)opSet.mnemonic))]);
         }
         strcat((LPSTR)inst,(LPSTR)space[1]);
      }
      else {
         strcat((LPSTR)inst,(LPSTR)space[10]);
         strcat((LPSTR)inst,(LPSTR)space[2]);
      }
      strcat((LPSTR)inst,(LPSTR)opSet.opString);
      opSet.opString+=strlen((LPSTR)opSet.opString);
   }
   while (strlen((LPSTR)opSet.opString) > 0) {
      strcat((LPSTR)inst,(LPSTR)endOfLine);
      strcat((LPSTR)inst,(LPSTR)space39);
      strncat((LPSTR)inst,(LPSTR)opSet.opString,38);
      if (strlen((LPSTR)opSet.opString) >=38)
         opSet.opString+=38;
      else
         opSet.opString+=strlen((LPSTR)opSet.opString);
   }
   /******** End Output inst ********/
   *InstLen = (opSet.opLength*2);

   if ((err = AdrDestroyAddress(dupAddr)) != GOOD)
      return err;

   return(GOOD);
}

/*****************************************************************************
**
**    InitOpSet
**
*****************************************************************************/
RETCODE InitOpSet(OPERATOR *opSet,BOOLEAN symbols) {

   memset(opSet,'\0',sizeof(OPERATOR));
   opSet->opString = &opSet->opStringStorage[0];
   opSet->operand = &opSet->operandStorage[0];
   opSet->symbol = symbols;
   return(GOOD);
}

/*****************************************************************************
**
**    GetDasmInst
**
*****************************************************************************/
RETCODE GetDasmInst(DESCRIPTOR startAddr, U16 numInst, LPSTR *buffer,
                    BOOLEAN DasmSymbol) {

   U16  OpWord[MAX_CODE_LENGTH];
   U8  InstLen;
   LOOP_VAR instCnt;
   RETCODE err;
   BOOLEAN  abortFromEsc;
   LPSTR tmpPtr;

   /* allocate the memory for the data to be sent back */
   /* max size buffer is 64k and max line length is 256, which
   ** means the maximum number of instructions per buffer is 250
   */
   if (numInst > MAX_INST_PER_BUFFER)
      numInst = MAX_INST_PER_BUFFER;
   if( (tmpPtr= TMalloc(numInst*MAX_LINE_LENGTH)) == NULL ) 
      return(ER_OUT_OF_MEMORY);
   *buffer = tmpPtr;
   /* make sure the first byte is \0 since strcat is being used by dasminst */
   memset(tmpPtr,'\0', 1);

   for( instCnt = 0; instCnt < numInst; instCnt++ ) {
      err = TskCheckAbort(&abortFromEsc);
      if(err!=GOOD) return err;
      if (abortFromEsc!=0) {
         return(ER_ABORT_FROM_ESC);
      }


      if((err=GetIntData(startAddr,(LPU8)OpWord)) != GOOD) {
         if( !instCnt ) return(err);
         strcat((LPSTR) *buffer,(LPSTR)endOfBuffer);
         err = GOOD;   /* we've found one instruction so return GOOD */
         return(err);
      }

      if((err=DasmInst(OpWord,startAddr,*buffer,&InstLen,DasmSymbol))
         !=GOOD) return(err);

      if ((err = AdrAddToAddress(startAddr,InstLen)) != GOOD) {
         if (err == ER_ADR_RESULT_OVERFLOW) {
            strcat(*buffer,(LPSTR)endOfBuffer);
            err = GOOD;
            break;
         }
         return(err);
      }
         
      if (instCnt < numInst - 1)
         strcat(*buffer,(LPSTR)endOfLine);
      else
         strcat(*buffer,(LPSTR)endOfBuffer);
   }
   return(err);
}

/*****************************************************************************
**
**    GetDasmInstNoAlloc
**
*****************************************************************************/
RETCODE GetDasmInstNoAlloc(DESCRIPTOR startAddr, LPSTR buffer,
                    BOOLEAN DasmSymbol) {

   U16  OpWord[MAX_CODE_LENGTH];
   U8  InstLen;
   RETCODE err;

   /* make sure the first byte is \0 since strcat is being used by dasminst */
   buffer[0] = '\0';
   if((err=GetIntData(startAddr,(LPU8)OpWord)) != GOOD) return(err);
   if((err=DasmInst(OpWord,startAddr,buffer,&InstLen,DasmSymbol)) != GOOD)
       return(err);
   return AdrAddToAddressOverflow(startAddr,InstLen);
}

/*****************************************************************************
**
**    GetDasmInstByLine
**
*****************************************************************************/
RETCODE GetDasmInstByLine(DESCRIPTOR startAddr, U16 *lines, LPSTR *buffer,
                          BOOLEAN DasmSymbol) {
   U16  OpWord[MAX_CODE_LENGTH];
   U8  instLen;
   RETCODE err;
   LPSTR tmpPtr;

   *lines = 0;
   if( (tmpPtr = TMalloc(MAX_LINE_LENGTH)) == NULL ) {
      return(ER_OUT_OF_MEMORY);
   }
   *buffer = tmpPtr;
   /* make sure the first byte is \0 since strcat is being used by dasminst */
   memset(tmpPtr,'\0', 1);

   if ((err=GetIntData(startAddr,(LPU8)OpWord))!=GOOD) return(err);

   if ((err=DasmInst(OpWord, startAddr, *buffer, &instLen, DasmSymbol)) 
      != GOOD) return(err);

   strcat(*buffer,(LPSTR)endOfBuffer);
   if (instLen <= MAX_INST_PER_LINE)
      (*lines)++;
   else
      *lines = (instLen/MAX_INST_PER_LINE) +
               ((instLen%MAX_INST_PER_LINE > 0)?1:0);

   return AdrAddToAddressOverflow(startAddr,instLen);
}

/*****************************************************************************
**
**    CheckDasmInst
**
**    This routine only returns an error due to catastophic conditions.
**    Like being out of memory, unable to converse with address server etc,
**    This routine never returns an error because it is unable to
**    dissasemble.  The instValid parameter returns whether the
**    dissasembly was successful.
**
**
*****************************************************************************/
RETCODE CheckDasmInst(DESCRIPTOR startAddr,BOOLEAN DasmSymbol,
                      U8 *instLen, BOOLEAN *instValid) {

   U32 addrOffset;
   U16  OpWord[MAX_CODE_LENGTH];
   OPERATOR  opSet;
   DASM_INFO dasmInfo;
   RETCODE err;

   *instValid = FALSE;
   *instLen = 0;
   if((err=AdrGetAddrOffset(startAddr,&addrOffset))!= GOOD)
      return(err);

   if((err=GetIntData(startAddr,(LPU8)OpWord))!=GOOD)
      return(err);

   err=DisassembleOpcode(OpWord,addrOffset,DasmSymbol,&opSet,&dasmInfo);

   if (!err) {
      *instValid = TRUE;
      *instLen = (opSet.opLength*2);
   } else {
      *instLen = sizeof(opSet.objCode[0]);
   }

   return(err);
}

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