/***************************************************************************
**
**  Name:  asm030.c
**
**  Description:
**     This is a Assembler for Motorola 68030
**
**
**  Status:  REVIEW
**
**  $Log:   S:/tbird/mt2_68k/dad32/asm030.c_v  $
** 
**    Rev 1.0   13 Feb 1997 08:45:04   gene
** Initial revision.
** 
**    Rev 1.2   11 Sep 1996 11:16:02   kevin
** fixed EA type check bug => data.l/data.w condition
** 
**    Rev 1.1   12 Mar 1996 10:04:30   gene
** changed to large model and added EA check
** 
**    Rev 1.0   07 Sep 1995 10:16:38   gene
** Initial revision.
** 
**    Rev 1.13   03 Dec 1992 10:15:04   john
** fixed assembly of (xxx).w effective addresses
** 
**    Rev 1.12   02 Dec 1992 16:57:46   john
** changed display of asm addr to be 24 bit
** 
**    Rev 1.11   05 Nov 1992 17:14:44   john
** Used a sledge hammer to prevent immediate data values from being used
** in "UNSIZED" opcodes.  cpRestore and PLOAD can both use immediate
** data, but both are technically 030/851 instructions only.  However,
** this reports an error correctly for JSR, JMP, etc...
** 
**    Rev 1.10   29 Oct 1992 14:29:12   john
** fixed bug with coprocessor condition codes
** 
**    Rev 1.9   23 Oct 1992 16:34:38   john
** fixed case sensitivity bugs, and a signed conv. bug
** 
**    Rev 1.8   23 Oct 1992 13:45:24   john
** fixed assembly when 0x prepended to hex numbers
** 
**    Rev 1.7   16 Oct 1992 15:11:40   john
** Added code to handle DC.W
** 
**    Rev 1.6   15 Oct 1992 16:34:42   john
** Removed many compiler warnings.
** Fixed return sequence for asminst.  Now when an error is encountered
** it does not attempt to continue as if no error occured.
** 
**    Rev 1.5   14 Sep 1992 09:52:28   marilyn
** Tracked down memory leaks.
** 
**    Rev 1.4   17 Jul 1992 09:36:34   marilyn
** Updated interface to AsmInst.
** 
**    Rev 1.3   23 Jun 1992 16:30:40   marilyn
** Fixed bugs and added support for 68332.
** 
**    Rev 1.2   13 Mar 1992 09:03:20   mindy
** fixed the assembler bugs as directed by Allen.
** 
**    Rev 1.1   03 Mar 1992 10:39:22   mindy
** Cleaned up documentation format and some local routine interfaces.
**
**    Rev 1.0   14 Jan 1992 13:05:08   tom
** Initial revision.
**
**  $Header:   S:/tbird/mt2_68k/dad32/asm030.c_v   1.0   13 Feb 1997 08:45:04   gene  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/

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

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

#ifndef _CLISRV_
#include "clisrv.h"
#endif

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

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

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

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

#ifndef __STDIO_H_
#include <stdio.h>
#endif

#ifndef __STDLIB_H_
#include <stdlib.h>
#endif

#define ODD_DISP   0x0010

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

extern PROBE_TYPE cpuType;
                       /****************************
                        *                          *
                        *     LOCAL DEFINITIONS    *
                        *                          *
                        ****************************/

#define  NUM_BRANCH_COND   16
#define  NUM_ADDR_REGS     8
#define  NUM_DATA_REGS     8
#define  MOVE_2ND_EA_TYPE  6

typedef enum {EMPTY,PC,AREG,XREG,ZPC} EA_COM;

typedef struct eacomponent {
   EA_COM  type;
   U16     value;
}EACOMPONENT;

U8   *PcClass[] = {"PC","ZPC"};
U8   *AddrReg[] = {"A0","A1","A2","A3","A4","A5","A6","A7"};
U8   *DataReg[] = {"D0","D1","D2","D3","D4","D5","D6","D7"};
U8   *AddrReg2[] = {"(A0)","(A1)","(A2)","(A3)","(A4)","(A5)","(A6)","(A7)"};
U8   *CoReg[] = {"FP0","FP1","FP2","FP3","FP4","FP5","FP6","FP7"};
U8   *CoCntlReg[] = {"FPIAR","FPSR","FPCR"};
U8   *SpecialReg[] = {"CCR","SR","USP"};


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

/*
** #define DEBUG_MEM_LEAKS 1
*/

extern U32 memAlloced;
extern U32 memFreed;


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

RETCODE fReadStr(U16 hFile, VOID FAR *lBuf);
RETCODE FreeLocalMemory();
RETCODE BitNo(U8 SizeNo);
RETCODE CatchAsmData(OPERATOR FAR *opSet,U16 InstNo,U16 PosNo,U8 RotateFlag);
U8      SizeType(U8 FAR *SizeChar);
RETCODE SetSize(OPERATOR FAR *opSet);
RETCODE SetCoSize(OPERATOR FAR *opSet);
RETCODE GetDigit(U8 FAR *bdString,U32 FAR *Disp,U8 FAR *length);
RETCODE SetLData(U16 FAR *AsmObjCode,U32 lData);
RETCODE ProcessBd(U8 FAR *length,U16 FAR *ExtWord);
RETCODE SetBd(U32 lData,U16 length,U16 ExtWord,OPERATOR FAR *opSet);
RETCODE ProcessBs(U8 BsFlag, U16 FAR *ExtWord);
RETCODE ProcessIs(U8 IsFlag, U16 FAR *ExtWord);
RETCODE ProcessIIs(U8 FAR *length, U16 FAR *ExtWord);
RETCODE SetBdOd(U32 lData,U16 length,OPERATOR FAR *opSet);
RETCODE ProcessXn(U8 FAR *XnString,U16 FAR *ExtWord);
VOID    TokenString(LPU8 token,LPU8 FAR *string,LPU8 slite,BOOLEAN Skip);
RETCODE FilterSpace(OPERATOR FAR *opSet);
RETCODE SearchSize(U8 FAR *SizeChar,U8 FAR *Mnemonic);
RETCODE GetToken(OPERATOR FAR *opSet, U8 FAR *inst);
RETCODE SubEaType(U8 FAR *SubEa, EACOMPONENT FAR *EaCpt);
RETCODE ComplexEa(U8 FAR *EaString,OPERATOR FAR *opSet,U8 EaID);
RETCODE AsmEa(OPERATOR FAR *opSet,U8 FAR *EaString,U8 EaID);
RETCODE IdentifyInst(OPERATOR FAR *opSet, U16 FAR *InstNo,
                     U8 FAR *length, U8 FAR *dFlag, U16 FAR *PosNo);
RETCODE DCDataOperand(OPERATOR FAR *opSet, U8 **opStr);

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


/****************************************************************************
*
*  PreMnemonic
*
*****************************************************************************/
RETCODE PreMnemonic(U16 FAR *TypeCode,U8 FAR *mneBuf,U8 FAR *dFlag)
{
   U8 *ccCode[] = {
   /* 0 */   "B",
   /* 1 */   "DB",
   /* 2 */   "S",
   /* 3 */   "TRAP",
   /* 4 */   "FB",
   /* 5 */   "FDB",
   /* 6 */   "FS",
   /* 7 */   "FTRAP"
   };
   U8 *dCode[] = {
   /* 0 */   "AS",
   /* 1 */   "LS",
   /* 3 */   "ROX",
   /* 2 */   "RO"
   };
   register LOOP_VAR  loop;
   U8  ccFlag;
   S8  PosNo;
   U16 Len, opcodeVal;

   loop = 0;
   ccFlag = *dFlag = OFF;
   while ((loop < 8) && (ccFlag == OFF)) {
      Len = lstrlen(ccCode[loop]);
      if (_fstrnicmp(mneBuf,ccCode[loop],Len) == 0) {
         switch (loop) {
            case  0 :
            case  1 :
            case  2 :
            case  3 :
               if((PosNo=FindString(16,Condition,&mneBuf[Len]))>=0) {
                  if ((loop == 0) && (PosNo < 2)) {
                     *TypeCode = 0;
                     return(ER_DAD_ASM_ERROR);
                  }
                  else {
                     mneBuf[Len] = 0x00;
                     lstrcat(mneBuf,"cc");
                     opcodeVal = (U16)PosNo << 8;
                     ccFlag = ON;
                  }
               }
               else {
                  *TypeCode = 0;
                  return(ER_DAD_ASM_ERROR);
               }
               break;
            case  4 :
            case  5 :
            case  6 :
            case  7 :
               if ((PosNo = FindString(32,CoCondition,&mneBuf[Len])) >= 0) {
                  mneBuf[Len] = 0x00;
                  opcodeVal = (U16)PosNo;
                  lstrcat(mneBuf,"cc");
                  ccFlag = ON;
               }
               else {
                  *TypeCode = 0;
                  return(ER_DAD_STRING_NOT_FOUND);
               }
               break;
         }
      }
      loop++;
   }
   if (ccFlag == OFF) {
      loop = 0;
      while ((loop < 4) && (*dFlag == OFF)) {
         Len = lstrlen(dCode[loop]);
         if ((_fstrnicmp(mneBuf,dCode[loop],Len) == 0) &&
             ((PosNo = FindString(2,ShiftType,&mneBuf[Len])) >= 0)) {
            mneBuf[Len] = 0x00;
            lstrcat(mneBuf,"d");
            opcodeVal = (U16)PosNo << 8;
            *dFlag = ON;
         }
      loop++;
      }
   }
   if ((ccFlag == ON) || (*dFlag == ON))
      *TypeCode = opcodeVal;
   else
      *TypeCode = 0;
   return(GOOD);
}


/****************************************************************************
*
*  FindString
*
*****************************************************************************/
S8 FindString(U8 Count, U8 **Source, U8 *Search) {
   U8   idx;
   idx = 0;

   while ((idx < Count) && (_fstricmp(Search,Source[idx]) != 0)) idx++;
   if( idx == Count ) return(-1);
   return(idx);
}

/****************************************************************************
*
*     SizeType
*
*****************************************************************************/
U8 SizeType(U8 *SizeChar) {
   S8 sizeNo;
   U8 bit = 0x01;
   if((sizeNo = FindString(9,SizeString,SizeChar)) >= 0 )
      return(bit << (sizeNo-1));
   return(0);
}

/****************************************************************************
*
*  SetSize
*
*****************************************************************************/
RETCODE SetSize(OPERATOR FAR *opSet)
{
   switch(opSet->size[0]) {
      case 'B' :
      case 'b' :
         opSet->objCode[0] += 00;
         break;
      case 'W' :
      case 'w' :
         opSet->objCode[0] += 0x40;
         break;
      case 'L' :
      case 'l' :
         opSet->objCode[0] += 0x80;
         break;
      case 'Q' :
      case 'q' :
         break;
      default :
         break;
   }
   return(GOOD);
}

/****************************************************************************
*
*  SetCoSize
*
*****************************************************************************/
RETCODE SetCoSize(OPERATOR FAR *opSet)
{
   switch(opSet->size[0]) {
      case 'B' :
      case 'b' :
         opSet->objCode[1] += 0X1800;
         break;
      case 'W' :
      case 'w' :
         opSet->objCode[1] += 0X1000;
         break;
      case 'L' :
      case 'l' :
         opSet->objCode[1] += 0X0000;
         break;
      case 'S' :
      case 's' :
         opSet->objCode[1] += 0X0400;
         break;
      case 'D' :
      case 'd' :
         opSet->objCode[1] += 0X1400;
         break;
      case 'X' :
      case 'x' :
         opSet->objCode[1] += 0X0800;
         break;
      case 'P' :
      case 'p' :
         opSet->objCode[1] += 0X0C00;
         break;
      default :
         break;
   }
   return(GOOD);
}

/****************************************************************************
*
*  GetDigit
*
*****************************************************************************/
RETCODE GetDigit(U8 FAR *bdString,U32 FAR *disp,U8 FAR *length)
{

   U8 *endString;
   
   /* make sure the pointer is null */
   endString = NULL;

   if ((*disp = (U32)strtoul(bdString,&endString,16)) == 0L) {
      if (lstrlen(endString) != 0) {
         *length = 0;
         return(ER_DAD_ASM_ERROR);
      }
   }
   if (endString[0] != 0x00) {
      *length = 0;
      return(ER_DAD_ASM_ERROR);
   }
   if (bdString[0] == '-')
      *length = lstrlen(bdString)  - 1;
   else
      *length = lstrlen(bdString) /*(lstrlen(bdString) % 2) */;

   /* remove leading 0x from length consideration */
   if (!_fstrnicmp(bdString, "0x", 2)) *length -= 2;
   return(GOOD);
}

/****************************************************************************
*
*  SetLData
*
*****************************************************************************/
RETCODE SetLData(U16 FAR *AsmObjCode,U32 lData)
{
   *AsmObjCode = (lData >> 16);
   *(AsmObjCode+1) = (U16)(lData);
   return(GOOD);
}

/****************************************************************************
*
*  ProcessBd
*
*****************************************************************************/
RETCODE ProcessBd(U8 FAR *length,U16 FAR *ExtWord)
{
   switch (*length) {
      case 0 :
         *ExtWord +=0x10;
         *length = 0;
         break;
      case 1 :
      case 2 :
      case 3 :
      case 4 :
         *ExtWord +=0x20;
         *length = 1;
         break;
      case 5 :
      case 6 :
      case 7 :
      case 8 :
         *ExtWord +=0x30;
         *length = 2;
         break;
      default :
         return(ER_DAD_ASM_ERROR);
   }
   return(GOOD);
}

/****************************************************************************
*
*  SetBd
*
*****************************************************************************/
RETCODE SetBd(U32 lData,U16 length,U16 ExtWord,OPERATOR FAR *opSet)
{
   switch (length) {
      case 0 :
         opSet->objCode[opSet->opLength] = ExtWord;
         opSet->opLength++;
         break;
      case 1 :
         opSet->objCode[opSet->opLength] = ExtWord;
         opSet->objCode[opSet->opLength+1] = (U16)lData;
         opSet->opLength+=2;
         break;
      case 2:
         opSet->objCode[opSet->opLength] = ExtWord;
         SetLData(&(opSet->objCode[opSet->opLength+1]),lData);
         opSet->opLength+=3;
         break;
   }
   return(GOOD);
}

/****************************************************************************
*
*  ProcessBs
*
*****************************************************************************/
RETCODE ProcessBs(U8 BsFlag, U16 FAR *ExtWord)
{
   switch (BsFlag) {
      case ON :
         break;
      case OFF :
         *ExtWord += 0x0080;
         break;
   }
   return(GOOD);
}

/****************************************************************************
*
*  ProcessIs
*
*****************************************************************************/
RETCODE ProcessIs(U8 IsFlag, U16 FAR *ExtWord)
{
   switch (IsFlag) {
      case ON :
         break;
      case OFF :
         *ExtWord += 0x0040;
         break;
   }
   return(GOOD);
}

/****************************************************************************
*
*  ProcessIIs
*
*****************************************************************************/
RETCODE ProcessIIs(U8 FAR *length, U16 FAR *ExtWord)
{
   switch (*length) {
      case 0 :
         *ExtWord += 0x0001;
         *length = 0;
         break;
      case 1 :
      case 2 :
      case 3 :
      case 4 :
         *ExtWord += 0x0002;
         *length = 1;
         break;
      case 5 :
      case 6 :
      case 7 :
      case 8 :
         *ExtWord += 0x0003;
         *length = 2;
         break;
      default :
         return(ER_DAD_ASM_ERROR);
   }
   return(GOOD);

}

/****************************************************************************
*
*  SetBdOd
*
*****************************************************************************/
RETCODE SetBdOd(U32 lData,U16 length,OPERATOR FAR *opSet)
{
   switch (length) {
      case 0 :
         break;
      case 1 :
         opSet->objCode[opSet->opLength] = (U16)lData;
         opSet->opLength+=1;
         break;
      case 2:
         SetLData(&(opSet->objCode[opSet->opLength]),lData);
         opSet->opLength+=2;
         break;
   }
   return(GOOD);
}

/****************************************************************************
*
*  SetAddrData
*
*****************************************************************************/
RETCODE SetAddrData(OPERATOR FAR *opSet,U32 EaData,U8 EaLen)
{
   switch (EaLen) {
      case 0 :
      case 1 :
      case 2 :
      case 3 :
      case 4 :
         opSet->objCode[opSet->opLength] = (U16)EaData;
         opSet->opLength+=1;
         break;
      case 5 :
      case 6 :
      case 7 :
      case 8 :
         SetLData(&(opSet->objCode[opSet->opLength]),EaData);
         opSet->opLength+=2;
         break;
      default :
         return(ER_DAD_ASM_ERROR);
   }
   return(GOOD);
}


/****************************************************************************
*
*  ProcessXn
*
*****************************************************************************/
RETCODE ProcessXn(U8 FAR *XnString,U16 FAR *ExtWord)
{
   U16 RegNo;

   *ExtWord = 0;
   switch (XnString[0]) {
      case 0x00 :
         *ExtWord = 1; /* set bit 1 = 1 to check NULL */
         break;
      case 'D' :
      case 'A' :
      case 'a' :
      case 'd' :
         if (XnString[0] == 'A') (*ExtWord += 0x8000);
         if (((RegNo = XnString[1] - '0') & 0xfff8) > 0)
            return(ER_DAD_ASM_ERROR);
         *ExtWord = *ExtWord + (RegNo << 12);
         switch (XnString[2]) {
            case '.' :
               switch (XnString[3]) {
                  case 'W' :
                  case 'w' :
                     break;
                  case 'L' :
                  case 'l' :
                     *ExtWord += 0x0800;
                     break;
                  default :
                  return(ER_DAD_ASM_ERROR);
               }
               if (XnString[4] != '*') return(ER_DAD_ASM_ERROR);
               switch (XnString[5]) {     /* Set bit 9,10 */
                   case '1' :
                      break;                   /* 00 */
                   case '2' :
                      *ExtWord += 0x0200;      /* 01 */
                      break;
                   case '4' :
                      *ExtWord += 0x0400;      /* 10 */
                      break;
                   case '8' :
                      *ExtWord += 0x0600;      /* 11 */
                      break;
                   default :
                      return(ER_DAD_ASM_ERROR);
               }
               break;
            case '*' :
               switch (XnString[3]) {     /* Set bit 9,10 */
                  case '1' :
                     break;                  /* 00 */
                  case '2' :
                     *ExtWord += 0x0200;      /* 01 */
                     break;
                  case '4' :
                     *ExtWord += 0x0400;      /* 10 */
                     break;
                  case '8' :
                     *ExtWord += 0x0600;      /* 11 */
                     break;
                  default :
                     return(ER_DAD_ASM_ERROR);
               }
               break;
            default :
               return(ER_DAD_ASM_ERROR);
         }
         break;
      default :
         return(ER_DAD_ASM_ERROR);
   }
   return(GOOD);
}



/****************************************************************************
*
*  TokenString
*
*****************************************************************************/
VOID TokenString(LPU8 token,LPU8 *string,LPU8 slite, BOOLEAN Skip) {
   U8 buf;
   LPSTR nextToken;

   if((nextToken = _fstrpbrk(*string,slite)) != NULL) {
      buf = *nextToken;
      *nextToken = 0x00;
      lstrcpy(token,*string);
      *nextToken = buf;
      *string = nextToken;
   }
   else {
      lstrcpy(token,*string);
      *string += lstrlen(token);
   }
   if ((**string != 0x00) && Skip)
      (*string)++;
}

/****************************************************************************
*
*  FilterSpace
*
*****************************************************************************/
RETCODE FilterSpace(OPERATOR FAR *opSet)
{
   U16 Len;
   register LOOP_VAR lp1,lp2;

   Len = lstrlen(opSet->mnemonic);
   for (lp1 = 0; lp1 < Len; lp1++) {
      if (opSet->mnemonic[lp1] == ' ') {
         for (lp2 = lp1; lp2 < Len; lp2++)
            opSet->mnemonic[lp2] = opSet->mnemonic[lp2+1];
         Len--;
         lp1--;
      }
   }

   Len = lstrlen(opSet->opString);
   for (lp1 = 0; lp1 < Len; lp1++) {
      if (opSet->opString[lp1] == ' ') {
         for (lp2 = lp1; lp2 < Len; lp2++)
            opSet->opString[lp2] = opSet->opString[lp2+1];
         Len--;
         lp1--;
      }
   }
   return(GOOD);
}

/****************************************************************************
*
*  SearchSize
*
*****************************************************************************/
RETCODE SearchSize(U8 FAR *SizeChar,U8 FAR *Mnemonic)
{
   LOOP_VAR idx;

   idx = 0;
   while ((_fstricmp(Mnemonic,InstructionSet[idx].Mnemonic) != 0) &&
          (idx < MAX_NUM_INST)) {
      idx++;
   }
   if (idx < MAX_NUM_INST)
      lstrcpy(SizeChar,SizeString[(U16)BitNo(InstructionSet[idx].OpSize)]);
   else {
      lstrcpy(SizeChar,"N"); /* Search No Match */
      return ER_DAD_INST_SIZE_UNDETERMINED;
   }

   return(GOOD);
}

/****************************************************************************
*
*  GetToken
*
*****************************************************************************/
RETCODE GetToken(OPERATOR FAR *opSet, U8 FAR *inst)
{
   RETCODE err = GOOD;

   TokenString(opSet->mnemonic,&inst,". ",FALSE);
   if (*inst == '.') {
      inst++;
      opSet->size[0] = *inst;
      inst+=2;
   }
   else {
      err = SearchSize(opSet->size,opSet->mnemonic);
      if (*inst != NULL) inst++;
   }
   lstrcpy(opSet->opString,inst);
   FilterSpace(opSet);
   return(err);
}

/****************************************************************************
*
*  SubEaType
*  checks EA component - PC, An, Xn, NULL
*  TypeWord  :  FEDCBA9| 8 | 765 | 4 | 3 | 2 | 1 | 0 |
*
*****************************************************************************/
RETCODE SubEaType(U8 FAR *SubEa, EACOMPONENT FAR *EaCpt)
{
   S8 RegNo;
   RETCODE err;
   if ((RegNo = FindString(NUM_ADDR_REGS,AddrReg,SubEa)) >= 0) {
      EaCpt->type = AREG;
      EaCpt->value = RegNo;
   }
   else if ((RegNo = FindString(2,PcClass,SubEa)) >= 0) {
           if (RegNo == 0) EaCpt->type = PC;
           else if (RegNo == 1) EaCpt->type = ZPC;
           EaCpt->value = 0;
        }
        else {
           if((err = ProcessXn(SubEa,&EaCpt->value)) != GOOD) 
              return(err);
           EaCpt->type = XREG;
           if (EaCpt->value == 1) EaCpt->type = EMPTY;
        }
   return(GOOD);
}


/****************************************************************************
*
*  ComplexEa
*
*****************************************************************************/
RETCODE ComplexEa(U8 FAR *EaString,OPERATOR FAR *opSet,U8 EaID)
{
   U8 *SubEaStrPtr,*SubEaPtr,*SubBufPtr;
   U8 *SubEaStr,*SubEa,*SubBuf,*EaPtr;
   U8 length,ExtPos,EaChar,XnFlag;
   U16 ExtWord,OdWord;
   U32 lData;
   EACOMPONENT EaCpt = {0};
   RETCODE err,ret;

   ret = GOOD;

   if ((SubEaStrPtr = (U8 *)TMalloc(MAX_LINE_LENGTH)) == NULL)
      return ER_OUT_OF_MEMORY;
   SubEaStr = SubEaStrPtr;
   if ((SubEaPtr = (U8 *)TMalloc(MAX_LINE_LENGTH)) == NULL)
      return ER_OUT_OF_MEMORY;
   SubEa = SubEaPtr;
   if ((SubBufPtr = (U8 *)TMalloc(MAX_LINE_LENGTH)) == NULL)
      return ER_OUT_OF_MEMORY;
   SubBuf = SubBufPtr;
   lData   = 0;
   length  = 0;
   ExtWord = 0;
   XnFlag  = OFF;
   ExtPos  = opSet->opLength;
   EaChar  = *EaString;
   switch (EaChar) {
      case '[' :
         TokenString(SubEaStr,&EaString,"]",TRUE);
         SubEaStr++;
         break;
      default :
         lstrcpy(SubEaStr,EaString);
   }
   TokenString(SubEa,&SubEaStr,",",TRUE);
   if ((FindString(NUM_ADDR_REGS,AddrReg,SubEa) >= 0) ||
       (FindString(NUM_DATA_REGS,DataReg,SubEa) >= 0)) {
      EaPtr = SubEaStr;
      TokenString(SubBuf,&SubEaStr,",",TRUE);
      if (ProcessXn(SubBuf,&EaCpt.value) == GOOD) SubEaStr = EaPtr;
   }
   else if ((ret = GetDigit(SubEa,&lData,&length)) == GOOD)
           TokenString(SubEa,&SubEaStr,",",TRUE);
   if ((ret = SubEaType(SubEa,&EaCpt)) == GOOD) {
      switch (EaCpt.type) {
         case EMPTY : /* () or (digital) */
            opSet->objCode[0] += (0x30 << EaID);
            ExtWord += FULL_EXTENSION;
            ProcessBd(&length,&ExtWord);
            ProcessBs(OFF,&ExtWord);
            if (EaChar != '[')  ProcessIs(OFF,&ExtWord);
            opSet->objCode[ExtPos] = ExtWord;
            opSet->opLength++;
            SetBdOd(lData,length,opSet);
            break;
         case ZPC :
            opSet->objCode[0] += (0x3b << EaID);
            TokenString(SubEa,&SubEaStr,",",TRUE);
            if ((ret = ProcessXn(SubEa,&EaCpt.value)) == GOOD) {
               ExtWord = FULL_EXTENSION;
               ProcessBd(&length,&ExtWord);
               ProcessBs(OFF,&ExtWord);
               if (EaCpt.value == 1) {      /* (..ZPC) */
                  if (EaChar != '[')  ProcessIs(OFF,&ExtWord);
                  opSet->objCode[ExtPos] = ExtWord;
               }
               else {  /* (..ZPC,Xn) */
                  opSet->objCode[ExtPos] = ExtWord + EaCpt.value;
                  XnFlag = ON;
               }
               opSet->opLength++;
               SetBdOd(lData,length,opSet);
            }
            break;
         case PC :
         case AREG :
            if (EaCpt.type == AREG)
               opSet->objCode[0] += ((0x30+EaCpt.value) << EaID);
            else
               opSet->objCode[0] += (0x3b << EaID);
            TokenString(SubEa,&SubEaStr,",",TRUE);
            if((ret = ProcessXn(SubEa,&EaCpt.value)) == GOOD) {
               if (EaCpt.value == 1) {      /* (..PC) */
                  if (((length > 0) && (length < 5)) && (EaChar != '[')) {  /* (d16,PC) */
                     opSet->objCode[ExtPos] = (U16)lData;
                     if (EaCpt.type == AREG) {
                        opSet->objCode[0] -= (0x08 << EaID);
                        opSet->eaType = 6;   /* (d16,An) */
                     }
                     else {
                        opSet->objCode[0] -= (0x01 << EaID);
                        opSet->eaType = 14;   /* (d16,PC) */
                     }
                     opSet->opLength++;
                  }
                  else {  /* (bd,PC) */
                     ExtWord = FULL_EXTENSION;
                     ProcessBd(&length,&ExtWord);
                     if (EaChar != '[')  
                        ProcessIs(OFF,&ExtWord);
                     else {
                        if (EaCpt.type == AREG) 
                           opSet->eaType = 10;   /* ([bd,An],Xn,od) */
                        else
                           opSet->eaType = 18;   /* ([bd,PC],Xn,od) */
                     }
                     opSet->objCode[ExtPos] = ExtWord;
                     opSet->opLength++;
                     SetBdOd(lData,length,opSet);
                  }
               }
               else {
                  XnFlag = ON;
                  if (length == 0){       /* (PC,Xn) */
                     ExtWord = FULL_EXTENSION;
                     ProcessBd(&length,&ExtWord);
                     opSet->objCode[ExtPos] = ExtWord + EaCpt.value;
                     opSet->opLength++;
                     SetBdOd(lData,length,opSet);
                  }
                  else {
                     if (((length > 0) && (length < 3)) && (EaChar != '[')){  /* (d8,PC,Xn) */
                        ExtWord = BRIEF_EXTENSION;
                        ExtWord += EaCpt.value;
                        opSet->objCode[ExtPos] = ExtWord + (U8)lData;
                        opSet->opLength++;
                        if (EaCpt.type == AREG)
                           opSet->eaType = 7;   /* (d8,An,Xn) */
                        else
                           opSet->eaType = 15;   /* (d8,PC,Xn) */
                     }
                     else {  /* (bd,PC,Xn) */
                        ExtWord = FULL_EXTENSION;
                        ProcessBd(&length,&ExtWord);
                        opSet->objCode[ExtPos] = ExtWord + EaCpt.value;
                        opSet->opLength++;
                        SetBdOd(lData,length,opSet);
                        if (EaChar == '[') {
                           if (EaCpt.type == AREG)
                              opSet->eaType = 9;   /* ([bd,An,Xn],od) */
                           else
                              opSet->eaType = 17;   /* ([bd,PC,Xn],od) */
                        }
                     }
                  }
               }
            }
            break;
         case XREG :
            XnFlag = ON;
            ExtWord = FULL_EXTENSION;
            ProcessBd(&length,&ExtWord);
            ProcessBs(OFF,&ExtWord);
            if (EaChar != '[')  ProcessIs(ON,&ExtWord);
            opSet->objCode[0] += (0x30 << EaID);
            opSet->objCode[ExtPos] = ExtWord + EaCpt.value;
            opSet->opLength++;
            SetBdOd(lData,length,opSet);
            break;
      }
   }

   if (EaChar == '[') {
      switch (*EaString) {
        case 0x00 :  /* ([]) */
        case ','  :
          if (*EaString == ',') EaString++;
          OdWord = 0;
          if (XnFlag == OFF) {
             EaPtr = EaString;
             TokenString(SubEa,&EaString,",",TRUE);
             if ((ret = ProcessXn(SubEa,&EaCpt.value)) == GOOD ) {
                if (EaCpt.value != 1) {
                   XnFlag = ON;
                   OdWord += 0x04;
                   opSet->objCode[ExtPos] += EaCpt.value;
                }
             }
             else EaString = EaPtr;
          }
          if (*EaString != 0x00) {
             ret  = GetDigit(EaString,&lData,&length);
          }
          else length = 0;
          if (XnFlag == OFF)  ProcessIs(OFF,&OdWord);
          ProcessIIs(&length,&OdWord);
          opSet->objCode[ExtPos] += OdWord;
          if (length != 0) SetBdOd(lData,length,opSet);
          break;
        default :
           ret = ER_DAD_ASM_ERROR;
      }
   }
   if ((err = TFree(SubEaPtr)) != GOOD)
      return err;
   if ((err = TFree(SubEaStrPtr)) != GOOD)
      return err;
   if ((err = TFree(SubBufPtr)) != GOOD)
      return err;
   return(ret);
}

/****************************************************************************
*
*  ComplexDigital
*
*****************************************************************************/
RETCODE ComplexDigital(OPERATOR FAR *opSet,U8 FAR *DigString)
{
   S8 SizeNo;
   U8 DigLen;
   U8 DigStr1[10],DigStr2[10];
   U32 Digital[3];


   if ((SizeNo = FindString(9,SizeString,opSet->size)) < 0)
      return(ER_DAD_STRING_NOT_FOUND);
   DigLen = lstrlen(DigString);
   /* find out if there is a leading 0x in digstring.  If there is remove */
   /* it's consideration from the string length */
   if (!_fstrnicmp(DigString, "0x", 2)) DigLen -= 2;
   
   switch(SizeNo) {
      case 0 :  /* Unsized */
         return(ER_DAD_ASM_ERROR);
      case 1 :  /* Byte */
         if (GetDigit(DigString,&Digital[0],&DigLen) == ER_DAD_ASM_ERROR)
            return(ER_DAD_ASM_ERROR);
         if (Digital[0] > 0xff) return(ER_DAD_ASM_ERROR);
         SetAddrData(opSet,Digital[0],DigLen);
         break;
      case 2 :  /* Word */
         if (GetDigit(DigString,&Digital[0],&DigLen) == ER_DAD_ASM_ERROR)
            return(ER_DAD_ASM_ERROR);
         if (Digital[0] > 0xffff) return(ER_DAD_ASM_ERROR);
         SetAddrData(opSet,Digital[0],DigLen);
         break;
      case 3 :  /* Long */
      case 5 :  /* Single */
         if (GetDigit(DigString,&Digital[0],&DigLen) == ER_DAD_ASM_ERROR)
            return(ER_DAD_ASM_ERROR);
         SetAddrData(opSet,Digital[0],8);
         break;
      case 4 :  /* Quad */
         break;
      case 6 :  /* Double */
         if (DigLen > 16) return(ER_DAD_ASM_ERROR);
         if (DigLen > 8) {
            _fstrncpy(DigStr1,DigString,DigLen-8);
            DigStr1[DigLen-8] = 0x00;
            DigString += (DigLen-8);
            if ((GetDigit(DigStr1,&Digital[0],&DigLen) == ER_DAD_ASM_ERROR) ||
                (GetDigit(DigString,&Digital[1],&DigLen) == ER_DAD_ASM_ERROR))
               return(ER_DAD_ASM_ERROR);
         }
         else {
            Digital[0] = 0;
            if (GetDigit(DigString,&Digital[1],&DigLen) == ER_DAD_ASM_ERROR)
               return(ER_DAD_ASM_ERROR);
         }
         SetAddrData(opSet,Digital[0],8);
         SetAddrData(opSet,Digital[1],8);
         break;
      case 7 :  /* Extended */
      case 8 :  /* Packed */
         if (DigLen > 24) return(ER_DAD_ASM_ERROR);
         if (DigLen > 16) {
            _fstrncpy(DigStr1,DigString,DigLen - 16);
            DigStr1[DigLen-16] = 0x00;
            DigString += (DigLen-16);
            _fstrncpy(DigStr2,DigString,8);
            DigStr2[8] = 0x00;
            DigString += (DigLen-8);
            if ((GetDigit(DigStr1,&Digital[0],&DigLen) == ER_DAD_ASM_ERROR) ||
                (GetDigit(DigStr2,&Digital[1],&DigLen) == ER_DAD_ASM_ERROR) ||
                (GetDigit(DigString,&Digital[2],&DigLen) == ER_DAD_ASM_ERROR))
               return(ER_DAD_ASM_ERROR);
         }
         else if (DigLen > 8) {
                 _fstrncpy(DigStr1,DigString,DigLen - 8);
                 DigStr1[DigLen-8] = 0x00;
                 DigString += (DigLen-8);
                 Digital[0] = 0;
                 if ((GetDigit(DigStr1,&Digital[1],&DigLen) == ER_DAD_ASM_ERROR) ||
                     (GetDigit(DigString,&Digital[2],&DigLen) == ER_DAD_ASM_ERROR))
                    return(ER_DAD_ASM_ERROR);
              }
              else {
                 Digital[0] = 0;
                 Digital[1] = 0;
                 if (GetDigit(DigString,&Digital[2],&DigLen) 
                    == ER_DAD_ASM_ERROR) return(ER_DAD_ASM_ERROR);
              }
         SetAddrData(opSet,Digital[0],8);
         SetAddrData(opSet,Digital[1],8);
         SetAddrData(opSet,Digital[2],8);
         break;
   }
   return(GOOD);
}
/****************************************************************************
*
*  AsmEa
*
*****************************************************************************/
RETCODE AsmEa(OPERATOR FAR *opSet,U8 FAR *EaString,U8 EaID)
{
   U32 EaData;
   S8  EaMode;
   U8  EaLen;

   /* OpLen = opSet->opLength; */
   switch (EaString[0]) {
      case '(' :
         if (ComplexEa(EaString+1,opSet,EaID) != GOOD)                
            return(ER_DAD_EA_INVALID);
         break;
      case '-' :
         if ((EaMode = FindString(NUM_ADDR_REGS,AddrReg2,&EaString[1])) < 0)
            return(ER_DAD_EA_INVALID);        
         EaMode += 0x20;
         opSet->objCode[0] += (EaMode << EaID);
         opSet->eaType = 5;   /* -(An) */
         break;
      case '#' :
         EaString++;
         if (ComplexDigital(opSet,EaString) != GOOD)              
            return(ER_DAD_EA_INVALID);
         else {
            EaMode = 0x3c;
            opSet->objCode[0] += (EaMode << EaID);
            opSet->eaType = 13;   /* #<data> */
         }
         break;
      default :
         if ((EaMode = FindString(NUM_DATA_REGS,DataReg,EaString)) >= 0) {
             opSet->objCode[0] += (EaMode << EaID);
             opSet->eaType = 1;   /* Dn */
         }
         else if((EaMode=FindString(NUM_ADDR_REGS,AddrReg,&EaString[0]))>=0){
                 opSet->objCode[0] += ((EaMode + 8) << EaID);
                 opSet->eaType = 2; /* An */
              }
              else if (GetDigit(EaString,&EaData,&EaLen) !=ER_DAD_ASM_ERROR) {
                      if (EaLen > 4) {
                         EaMode = 0x39;
                         opSet->objCode[0] += (EaMode << EaID);
                         SetLData(&(opSet->objCode[opSet->opLength]),EaData);
                         opSet->opLength +=2;
                         opSet->eaType = 12;  /* data.l */
                      } else if (EaData < 0x8000) {
                         /* target can be accomodated by the signed word */
                         EaMode = 0x38;
                         opSet->objCode[0] += (EaMode << EaID);
                         opSet->objCode[opSet->opLength] = (U16)(EaData);
                         opSet->opLength++;
                         opSet->eaType = 11;  /* data.w */
                      } else {
                         /* need to create long data since the word */
                         /* addressing mode is a signed value and the */
                         /* processor sign extends the word value */
                         EaMode = 0x39;
                         opSet->objCode[0] += (EaMode << EaID);
                         SetLData(&(opSet->objCode[opSet->opLength]),EaData);
                         opSet->opLength += 2;
                         opSet->eaType = 12;  /* data.l */
                      }
                   }
                   else return(ER_DAD_EA_INVALID);
         /* Dn, An, data.W, data.L */
         break;
   }
   return(GOOD);
}


/****************************************************************************
*
*  CatchAsmData
*
*****************************************************************************/
RETCODE CatchAsmData(OPERATOR FAR *opSet,U16 InstNo,U16 PosNo,U8 RotateFlag) {
   LOOP_VAR idx;
   if ((opSet->mnemonic[0] == 'F') || (opSet->mnemonic[0] == 'f')) {
      opSet->opLength = CoInstructionSet[InstNo].EaPos;
      for (idx = 0; idx < CoInstructionSet[InstNo].EaPos; idx++)
           opSet->objCode[idx] = CoObjCode[InstNo][idx];
      if ((_fstrnicmp(opSet->mnemonic,"FDB",3) == 0)   ||
          (_fstrnicmp(opSet->mnemonic,"FS",2) == 0)    ||
          (_fstrnicmp(opSet->mnemonic,"FTRAP",4) == 0))
         opSet->objCode[1] += PosNo;
      else
         opSet->objCode[0] += PosNo;
      lstrcpy(opSet->operand,OperandType[CoInstructionSet[InstNo].OpType]);
      if (!((RotateFlag == ON) && (lstrcmp(opSet->operand,"ea") == 0)))
         if (CoInstructionSet[InstNo].OpSize != SizeType(opSet->size))
            SetCoSize(opSet);
   }
   else {
      opSet->opLength = InstructionSet[InstNo].EaPos;
      for (idx = 0; idx < InstructionSet[InstNo].EaPos; idx++)
         opSet->objCode[idx] = ObjCode[InstNo][idx];
      opSet->objCode[0] += PosNo;
      lstrcpy(opSet->operand,OperandType[InstructionSet[InstNo].OpType]);
      if (!((RotateFlag == ON) && (lstrcmp(opSet->operand,"ea") == 0)))
         if (InstructionSet[InstNo].OpSize != SizeType(opSet->size))
            SetSize(opSet);
   }
   return(GOOD);
}

/****************************************************************************
*
*  CoRegisterCode
*
*****************************************************************************/
RETCODE CoRegisterCode(OPERATOR FAR *opSet, U8 **opStr)
{
   S8 regNo,regNo2;
   U8 temp,opToken[10],regArray[80],*regList;
   LOOP_VAR lp1;

   regList = regArray;
   TokenString(regList,opStr,",",FALSE);
   TokenString(opToken,&regList,"/-",FALSE);
   while (*regList != NULL) {
      switch (*regList) {
         case '/' :
            regList++;
            if ((regNo = FindString(8,CoReg,opToken)) >= 0)
               opSet->objCode[1] += (0x01 << regNo);
            else
               return(ER_DAD_STRING_NOT_FOUND);
            break;
         case '-' :
            regList++;
            if ((regNo = FindString(8,CoReg,opToken)) >= 0) {
               TokenString(opToken,&regList,"/",TRUE);
               if ((regNo2 = FindString(8,CoReg,opToken)) < 0)
                  return(ER_DAD_STRING_NOT_FOUND);
               else {
                   if (regNo > regNo2) {
                        temp = regNo;
                        regNo = regNo2;
                        regNo2 = temp;
                   }
                   for (lp1 = regNo; lp1 <= regNo2; lp1++)
                       opSet->objCode[1] += (0x01 << lp1);
               }
            }
            else
               return(ER_DAD_ASM_ERROR);
            break;
         default :
            return(ER_DAD_ASM_ERROR);
      }
      TokenString(opToken,&regList,"/-",FALSE);
   }
   if (*opToken != NULL) {
      if ((regNo = FindString(8,CoReg,opToken)) >= 0)
         opSet->objCode[1] += (0x01 << regNo);
      else
         return(ER_DAD_STRING_NOT_FOUND);
   }
   opSet->operand+=4;
   return(GOOD);
}

/****************************************************************************
*
*  MMURegisterCode
*
*****************************************************************************/
RETCODE MMURegisterCode(OPERATOR FAR *opSet, U8 **opStr)
{
   U8 opToken[80];
   S8 codeVal;

   TokenString(opToken,opStr,",",FALSE);
   codeVal = FindString(6,MMUReg,opToken);
   switch (codeVal) {
      case 0 :
      case 2 :
      case 3 :
         opSet->objCode[1] += (0x4000 + (codeVal << 10));
         break;
      case 1 : /* MMUSR */
         opSet->objCode[1] += 0x6000;
         break;
      case 4 :
      case 5 :
         opSet->objCode[1] += ((codeVal - 2) << 10);
         break;
      default :
         return(ER_DAD_ASM_ERROR);
   }
   (opSet->operand)+=3;
   return(GOOD);
}

/****************************************************************************
*
*  ControlRegOperand
*
*****************************************************************************/
RETCODE ControlRegOperand(OPERATOR FAR *opSet,U8 **opStr)
{
   S8 regNo;
   U8 opToken[80];

   TokenString(opToken,opStr,",",FALSE);
   if ((regNo = FindString(3,ControlReg0,opToken)) >= 0)
      opSet->objCode[1] += regNo;
   else if ((regNo = FindString(5,ControlReg8,opToken)) >= 0)
           opSet->objCode[1] += regNo + 0x800;
        else
           return(ER_DAD_STRING_NOT_FOUND);
   (opSet->operand)+=2;
   return(GOOD);
}

/****************************************************************************
*
*  CoControlRegCode
*
*****************************************************************************/
RETCODE CoControlRegCode(OPERATOR FAR *opSet,U8 **opStr)
{
   S8 regNo;
   U8 opToken[10],regArray[80],*regList;
/*
   TokenString(opToken,opStr,",/",FALSE);
   if (**opStr == NULL)
      return(ER_DAD_ASM_ERROR);
   while ((**opStr != NULL) && (**opStr != ',')) {
      if (**opStr == '/') {
         (*opStr)++;
         if ((regNo = FindString(3,SpecialReg,opToken)) >= 0)
            opSet->objCode[1] += (0x0001 << (regNo+9));
         else
            return(ER_DAD_STRING_NOT_FOUND);
      }
   TokenString(opToken,opStr,&endToken,",/",FALSE);
   *opStr = endToken;
   }
   (opSet->operand)+=4;
*/
   regList = regArray;
   TokenString(regList,opStr,",",FALSE);
   TokenString(opToken,&regList,"/",FALSE);
   while (*regList != NULL) {
      switch (*regList) {
         case '/' :
            regList++;
            if ((regNo = FindString(3,CoCntlReg,opToken)) < 0)
               return(ER_DAD_STRING_NOT_FOUND);
            else
               opSet->objCode[1] += (0x01 << (regNo+10));
            break;
         default :
            return(ER_DAD_ASM_ERROR);
      }
      TokenString(opToken,&regList,"/",FALSE);
   }
   if (*opToken != NULL) {
      if ((regNo = FindString(3,CoCntlReg,opToken)) < 0)
         return(ER_DAD_STRING_NOT_FOUND);
      else
         opSet->objCode[1] += (0x01 << (regNo+10));
   }
   opSet->operand+=4;
   return(GOOD);
}

/****************************************************************************
*
*  FcOperand
*
*****************************************************************************/
RETCODE FcOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   S8 fcData;
   U8 opToken[80];

   TokenString(opToken,opStr,",",FALSE);
   if ((fcData = FindString(2,ControlReg0,opToken)) >= 0)
      opSet->objCode[1] += fcData;
   else if ((fcData = FindString(8,DataReg,opToken)) >= 0)
           opSet->objCode[1] += (8+ fcData);
        else if ((fcData = atoi(opToken)) < 8)
                 opSet->objCode[1] += (16+ fcData);
             else
                return(ER_DAD_ASM_ERROR);
   opSet->operand+=2;
   return(GOOD);
}

/****************************************************************************
*
*  CoRegOperand
*
*****************************************************************************/
RETCODE CoRegOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   S8 codeVal;
   U8 wordPos,codePos,opToken[80];

   TokenString(opToken,opStr,",:",FALSE);
   if( (codeVal = FindString(8,CoReg,opToken)) < 0)
      return(ER_DAD_STRING_NOT_FOUND);
   codePos = ctoi(*(opSet->operand+2));
   wordPos = ctoi(*(opSet->operand+3));
   opSet->objCode[codePos] += (codeVal << wordPos);
   opSet->operand+=4;
   return(GOOD);
}

/****************************************************************************
*
*  EaOperand
*
*****************************************************************************/
RETCODE EaOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   S8 eaMode;
   U8 eaToken[80],SourceEa = 0;
   RETCODE ret = GOOD;

   switch (**opStr) {
      case '(' :
         TokenString(eaToken,opStr,")",TRUE);
         if ((eaMode = FindString(8,AddrReg,eaToken+1)) >= 0) {
            TokenString(eaToken,opStr,",{",FALSE);
            if ((*eaToken == '+') && (*(eaToken+1) == 0x00)) { 
               opSet->eaType = 4;   /* (An)+ */
               opSet->objCode[0] += (0x18 + eaMode);
            }
            else if (*eaToken == 0x00) {     
                    opSet->eaType = 3;   /* (An) */
                    opSet->objCode[0] += (0x10 + eaMode);
                 }
                 else return(ER_DAD_ASM_ERROR);
         }
         else {
            ret = AsmEa(opSet,eaToken,SourceEa);
         }
         break;
      default :
         TokenString(eaToken,opStr,",{",FALSE);
         ret = AsmEa(opSet,eaToken,SourceEa);
         break;
   }
   opSet->operand += 2;
   opSet->ea1Type = opSet->eaType;
   return(ret);
}

/****************************************************************************
*
*  SecondEaOperand
*
*****************************************************************************/
RETCODE SecondEaOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   S8 eaMode;
   U8 eaToken[80],DestEa = 6;
   U16 Code0;
   RETCODE ret = GOOD;

//   opSet->eaType = 6;
   opSet->eaPos = opSet->opLength;
   switch (**opStr) {
      case '(' :
         TokenString(eaToken,opStr,")",TRUE);
         if ((eaMode = FindString(8,AddrReg,eaToken+1)) >= 0) {
            TokenString(eaToken,opStr,",{",FALSE);
            if ((*eaToken == '+') && (*(eaToken+1) == 0x00)) { 
               opSet->objCode[0] += ((0x18 + eaMode) << DestEa);
               opSet->eaType = 5;   /* (An)+ */
            }
            else if (*eaToken == 0x00) {
                    opSet->objCode[0] += ((0x10 + eaMode) << DestEa);
                    opSet->eaType = 3;   /* (An) */
                 }
                 else return(ER_DAD_ASM_ERROR);
         }
         else {
            ret = AsmEa(opSet,eaToken,DestEa);
         }
         break;
      default :
         TokenString(eaToken,opStr,",{",FALSE);
         ret = AsmEa(opSet,eaToken,DestEa);
         break;
   }
   Code0 = opSet->objCode[0];
   Code0  = (GetBits(Code0,6,3) << 9) +
            (GetBits(Code0,9,3) << 6) + (Code0 & 0xf03f);
   opSet->objCode[0] = Code0;
   opSet->operand += 2;
   opSet->ea2Type = opSet->eaType;
   return(ret);
}

/****************************************************************************
*
*  RegOperand
*
*****************************************************************************/
RETCODE RegOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   U8 wordPos,codePos,opToken[80];
   S8 codeVal;

   TokenString(opToken,opStr,",:",FALSE);
   if (*(opSet->operand) == 'D')
      codeVal = FindString(NUM_DATA_REGS,DataReg,opToken);
   else
      codeVal = FindString(NUM_ADDR_REGS,AddrReg,opToken);
   if(codeVal < 0) return(ER_DAD_ASM_ERROR);
   codePos = ctoi(*(opSet->operand+1));
   wordPos = ctoi(*(opSet->operand+2));
   opSet->objCode[codePos] += (codeVal << wordPos);
   opSet->operand+=3;
   return(GOOD);
}

/****************************************************************************
*
*  Reg2Operand
*
*****************************************************************************/
RETCODE Reg2Operand(OPERATOR FAR *opSet, U8 **opStr)
{
   U8 regID,wordPos,codePos,opToken[80];
   S8 codeVal;
   U16 regAD;

   TokenString(opToken,opStr,")",FALSE);
   if (*(opSet->operand) == 'A') {
      if( (codeVal = FindString(NUM_ADDR_REGS,AddrReg,opToken)) < 0)
         return(ER_DAD_STRING_NOT_FOUND);
      codePos = ctoi(*(opSet->operand+1));
      wordPos = ctoi(*(opSet->operand+2));
      opSet->objCode[codePos] += (U16)(codeVal << wordPos);
      opSet->operand+=3;
   }
   else {
      (*opStr)++;
      switch (*opToken) {
         case 'D' :
            codeVal = FindString(NUM_DATA_REGS,DataReg,opToken);
            regAD = 0;
            break;
         case 'A' :
            codeVal = FindString(NUM_ADDR_REGS,AddrReg,opToken);
            regAD = 1;
            break;
         default :
            return(ER_DAD_ASM_ERROR);
      }
      if (codeVal < 0) return(ER_DAD_ASM_ERROR);
      codePos = ctoi(*(opSet->operand+1));
      wordPos = ctoi(*(opSet->operand+2));
      regID   = ctoi(*(opSet->operand+3));
      opSet->objCode[codePos] += (codeVal << wordPos);
      opSet->objCode[codePos] += (regAD << regID);
      opSet->operand+=5;
   }
   return(GOOD);
}

/****************************************************************************
*
*  SROperand
*
*****************************************************************************/
RETCODE SROperand(OPERATOR FAR *opSet, U8 **opStr)
{
   U8 opToken[80];

   TokenString(opToken,opStr,",",FALSE);
   if (_fstricmp(opToken,"SR") == 0) opSet->operand+=2;
   else return(ER_DAD_ASM_ERROR);
   return(GOOD);
}

/****************************************************************************
*
*  CCROperand
*
*****************************************************************************/
RETCODE CCROperand(OPERATOR FAR *opSet, U8 **opStr)
{
   U8 opToken[80];

   TokenString(opToken,opStr,",",FALSE);
   if (_fstricmp(opToken,"CCR") == 0) opSet->operand+=3;
   else return(ER_DAD_ASM_ERROR);
   return(GOOD);
}

/****************************************************************************
*
*  USPOperand
*
*****************************************************************************/
RETCODE USPOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   U8 opToken[80];

   TokenString(opToken,opStr,",",FALSE);
   if (_fstricmp(opToken,"USP") == 0) opSet->operand+=3;
   else return(ER_DAD_ASM_ERROR);
   return(GOOD);
}

/****************************************************************************
*
*  MMUSROperand
*
*****************************************************************************/
RETCODE MMUSROperand(OPERATOR FAR *opSet, U8 **opStr)
{
   U8 opToken[80];

   TokenString(opToken,opStr,",",FALSE);
   if (_fstricmp(opToken,"MMUSR") == 0)
      opSet->operand+=5;
   else return(ER_DAD_ASM_ERROR);
   return(GOOD);
}

/****************************************************************************
*
*  XRegOperand
*
*****************************************************************************/
RETCODE XRegOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   U8 regID,wordPos,codePos,opToken[80];
   S8 codeVal;
   U16 regAD;

   TokenString(opToken,opStr,",",FALSE);
   switch (*opToken) {
      case 'D' :
      case 'd' :
         codeVal = FindString(NUM_DATA_REGS,DataReg,opToken);
         regAD = 0;
         break;
      case 'A' :
      case 'a' :
         codeVal = FindString(NUM_ADDR_REGS,AddrReg,opToken);
         regAD = 1;
         break;
      default :
         return(ER_DAD_REG_INVALID);
   }
   if (codeVal >= 0) {
      codePos = ctoi(*(opSet->operand+1));
      wordPos = ctoi(*(opSet->operand+2));
      regID   = ctoi(*(opSet->operand+3));
      opSet->objCode[codePos] += (codeVal << wordPos);
      opSet->objCode[codePos] += (regAD << regID);
      opSet->operand+=4;
   }
   return(GOOD);
}

/****************************************************************************
*
*  RegListOperand
*
*****************************************************************************/
RETCODE RegListOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   S8 regNo, regNo2;
   U8 temp,opToken[10],regArray[80],*regList;
   LOOP_VAR lp1;

   regList = regArray;
   TokenString(regList,opStr,",",FALSE);
   TokenString(opToken,&regList,"/-",FALSE);
   while (*regList != NULL)  {
      switch (*regList) {
         case '/' :
            (regList)++;
            if ((regNo = FindString(NUM_ADDR_REGS,AddrReg,opToken)) >= 0)
               opSet->objCode[1] += (0x01 << (regNo+8));
            else if ((regNo = FindString(NUM_DATA_REGS,DataReg,opToken)) >= 0)
               opSet->objCode[1] += (0x01 << regNo);
                 else
                    return(ER_DAD_REG_INVALID);
            break;
         case '-' :
            regList++;
            if ((regNo = FindString(NUM_ADDR_REGS,AddrReg,opToken)) >= 0) {
               TokenString(opToken,&regList,"/",TRUE);
               if ((regNo2 = FindString(NUM_ADDR_REGS,AddrReg,opToken)) < 0)
                  return(ER_DAD_REG_INVALID);
               else {
                   if (regNo > regNo2) {
                      temp = regNo;
                      regNo = regNo2;
                      regNo2 = temp;
                   }
                   for (lp1 = regNo; lp1 <= regNo2; lp1++)
                       opSet->objCode[1] += (0x01 << (lp1+8));
               }
            }
            else if ((regNo = FindString(NUM_DATA_REGS,DataReg,opToken))>=0) {
                    TokenString(opToken,&regList,"/",TRUE);
                    if((regNo2=FindString(NUM_DATA_REGS,DataReg,opToken))<0)
                       return(ER_DAD_REG_INVALID);
                    else {
                       if (regNo > regNo2) {
                            temp = regNo;
                            regNo = regNo2;
                            regNo2 = temp;
                       }
                       for (lp1 = regNo; lp1 <= regNo2; lp1++)
                           opSet->objCode[1] += (0x01 << lp1);
                    }
                 }
                 else
                    return(ER_DAD_REG_INVALID);
            break;
         default :
            return(ER_DAD_REG_INVALID);
      }
      TokenString(opToken,&regList,"/-",FALSE);
   }
   if (*opToken != NULL) {
      if ((regNo = FindString(NUM_ADDR_REGS,AddrReg,opToken)) >= 0)
         opSet->objCode[1] += (0x01 << (regNo+8));
      else if ((regNo = FindString(NUM_DATA_REGS,DataReg,opToken))>=0)
         opSet->objCode[1] += (0x01 << regNo);
           else
              return(ER_DAD_REG_INVALID);
   }
   opSet->operand+=5;
   return(GOOD);
}

/****************************************************************************
*
*  BDataOperand
*
*****************************************************************************/
RETCODE BDataOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   RETCODE err;
   U8 length,opToken[80];
   U32 lData;

   TokenString(opToken,opStr,",",FALSE);
   if ((err = GetDigit(opToken,&lData,&length)) != GOOD)
      return(err);
   switch (atoi(opSet->operand+1)) {
      case 8 :
         if (lData <= 0xff)
            opSet->objCode[1] += (U8)lData;
         else
            return(ER_DAD_ASM_ERROR);
         break;
      case 10 :
         if (lData <= 0xffff)
            opSet->objCode[1] += (U16)lData;
         else
            return(ER_DAD_ASM_ERROR);
         break;
      case 20 :
         SetLData(&(opSet->objCode[1]),lData);
         break;
   }
   opSet->operand +=3;
   return(GOOD);
}

/****************************************************************************
*
*  DCDataOperand
*
*****************************************************************************/
RETCODE DCDataOperand(OPERATOR FAR *opSet, U8 **opStr)
{  RETCODE err;
   U8 length,opToken[80];
   U32 lData;

   /* check to see if an # is used to signify immediate data */
   if(_fstrpbrk(*opStr,"#") != NULL) lstrcpy(opToken, *opStr+1);
   else lstrcpy(opToken, *opStr);

   /* convert the string into a number */
   if ((err=GetDigit(opToken,&lData,&length)) != GOOD)
      return(err);
   /* store the number as the first opcode word in opset */
   opSet->objCode[0] = (U16)lData;
   
   /* increment the operand pointer to the \0 */
   opSet->operand += 1;
   return(GOOD);
}

/****************************************************************************
*
*  DDispOperand
*
*****************************************************************************/
RETCODE DDispOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   RETCODE err;
   U8 length,opToken[80];
   U32 lData;

   TokenString(opToken,opStr,",(",FALSE);
   if((err=GetDigit(opToken,&lData,&length)) != GOOD)
      return(err);
   switch (atoi(opSet->operand+1)) {
      case 8 :
         if ((lData <= 0xffL) || (lData >= 0xffffff00L))
            opSet->objCode[1] += (U8)lData;
         else
            return(ER_DAD_OPERAND_INVALID);
         break;
      case 10 :
         if ((lData <= 0xffffL) || (lData >= 0xffff0000L))
            opSet->objCode[1] += (U16)lData;
         else
            return(ER_DAD_OPERAND_INVALID);
         break;
      case 20 :
         SetLData(&(opSet->objCode[1]),lData);
         break;
   }
   opSet->operand +=3;
   return(GOOD);
}

/****************************************************************************
*
*  JDataOperand
*
*****************************************************************************/
RETCODE JDataOperand(OPERATOR FAR *opSet, U8 **opStr,U32 startOffset) {
   U8 length,opToken[80];
   U32 lData;
   RETCODE err;

   TokenString(opToken,opStr,",",FALSE);
   if((err= GetDigit(opToken,&lData,&length)) != GOOD )
      return(err);
   if ((lData/2)*2 != lData)
      return(ER_DAD_DISPLACEMENT_INVALID);
   switch (atoi(opSet->operand+1)) {
      case 8 :
         lData -= startOffset;
         /* find out if branch address < current pc */
         if (lData & 0x80000000L) {
            /* find out if negative displacement is too large */
            if ( (lData + 0x80) & 0x80000000L) 
               return(ER_DAD_DISPLACEMENT_INVALID);
            lData = lData & 0xff;
         } else if (lData > 0x7e)
            return(ER_DAD_DISPLACEMENT_INVALID);
         opSet->objCode[0] += (U8)lData;
         break;
      case 10 :
         lData -= startOffset;
         if (lData & 0x80000000L) {
            if( (lData + 0x8000) & 0x80000000L)
               return(ER_DAD_DISPLACEMENT_INVALID);
            lData = lData & 0xffff;
         } else if (lData > 0x7ffe)
            return(ER_DAD_DISPLACEMENT_INVALID);
         opSet->objCode[1] += (U16)lData;
         break;
      case 20 :
         lData -= startOffset;
         SetLData(&(opSet->objCode[1]),lData) ;
         break;
   }
   opSet->operand +=3;
   return(GOOD);
}

/****************************************************************************
*
*  ODataOperand
*
*****************************************************************************/
RETCODE ODataOperand(OPERATOR FAR *opSet, U8 **opStr)
{
   RETCODE err;
   U8 length,opToken[80];
   U32 lData;

   TokenString(opToken,opStr,",",FALSE);
   if((err=GetDigit(opToken,&lData,&length))!=GOOD)
      return(err);
   switch (atoi(opSet->operand+1)) {
      case 8 :
         if ((lData <= 0xffL) || (lData >= 0xffffff00L))
            opSet->objCode[0] += (U8)lData;
         else
            return(ER_DAD_ASM_ERROR);
         break;
      case 10 :
         if ((lData <= 0xffffL) || (lData >= 0xffff0000L))
            opSet->objCode[1] += (U16)lData;
         else
            return(ER_DAD_ASM_ERROR);
         break;
      case 30 :
         if ((lData <= 0xffffL) || (lData >= 0xffff0000L))
            opSet->objCode[2] += (U16)lData;
         else
            return(ER_DAD_ASM_ERROR);
         break;
      case 40 :
         SetLData(&(opSet->objCode[2]),lData);
         break;
   }
   opSet->operand +=3;
   return(GOOD);
}

/****************************************************************************
*
*  VDataOperand
*
*****************************************************************************/
RETCODE VDataOperand(OPERATOR FAR *opSet, U8 **opStr)
{  RETCODE err;
   U8 codePos,length,opToken[80];
   U32 lData;

   TokenString(opToken,opStr,",",FALSE);
   if ((err= GetDigit(opToken,&lData,&length)) != GOOD)
      return(err);
    switch (atoi(opSet->operand+1)) {
      case 3 :
         if (lData > 7) return(ER_DAD_ASM_ERROR);
         break;
      case 4 :
         if (lData > 0x0f) return(ER_DAD_ASM_ERROR);
         break;
   }
   codePos = ctoi(*(opSet->operand+1));
   opSet->objCode[codePos] += (U16)lData;
   opSet->operand +=3;
   return(GOOD);
}

/****************************************************************************
*
*  SDataOperand
*
*****************************************************************************/
RETCODE SDataOperand(OPERATOR FAR *opSet, U8 **opStr)
{  RETCODE err;
   U8 length,opToken[80];
   U32 lData;

   TokenString(opToken,opStr,",}",FALSE);
   if ((err=GetDigit(opToken,&lData,&length)) != GOOD)
      return(err);
   switch (atoi(opSet->operand+1)) {
      case 7 :
         if (lData > 0x3f) return(ER_DAD_ASM_ERROR);
         break;
      default :
         return(ER_DAD_ASM_ERROR);
   }
   opSet->objCode[1] += (U16)lData;
   opSet->operand +=3;
   return(GOOD);
}

/****************************************************************************
*
*  PDataOperand
*
*****************************************************************************/
RETCODE PDataOperand(OPERATOR FAR *opSet, U8 **opStr)
{  RETCODE err;
   U8 codePos,wordPos,length,opToken[80];
   U32 lData;

   TokenString(opToken,opStr,",",FALSE);
   if((err=GetDigit(opToken,&lData,&length)) != GOOD)
      return(err);
   if (lData > 8) return(ER_DAD_ASM_ERROR);
   if (lData == 8) lData = 0;
   codePos = ctoi(*(opSet->operand+1));
   wordPos = ctoi(*(opSet->operand+2));
   opSet->objCode[codePos] += (U16)(lData << wordPos);
   opSet->operand +=3;
   return(GOOD);
}

/****************************************************************************
*
*  WDataOperand
*
*****************************************************************************/
RETCODE WDataOperand(OPERATOR FAR *opSet, U8 **opStr)
{  RETCODE err;
   S8  dataReg;
   U8  codePos,wordPos,length,opToken[80],detId = 0x20;
   U32 lData;

   TokenString(opToken,opStr,":}",FALSE);
   if ((dataReg = FindString(NUM_DATA_REGS,DataReg,opToken))<0) {
      if((err=GetDigit(opToken,&lData,&length)) != GOOD)
         return(err);
      if (lData > 32) return(ER_DAD_ASM_ERROR);
   }
   if (lData == 32) lData = 0;
   if( dataReg >= 0) lData = detId + dataReg; /* recover condition check */
   codePos = ctoi(*(opSet->operand+1));
   wordPos = ctoi(*(opSet->operand+2));
   opSet->objCode[codePos] += (U16)(lData << wordPos);
   opSet->operand +=3;
   return(GOOD);
}

/****************************************************************************
*
*  CreateObjCode
*
*****************************************************************************/
RETCODE CreateObjCode(OPERATOR FAR *opSet, U32 startOffset)
{
   U8 *opStr,*opStrPtr;
   RETCODE ret,err;
   ret = GOOD;

   if ((opStrPtr = (U8 *)TMalloc(MAX_LINE_LENGTH)) == NULL)
      return ER_OUT_OF_MEMORY;
   opStr = opStrPtr;
   lstrcpy(opStr,opSet->opString);
   while ((*(opSet->operand) != NULL) && (ret == GOOD)) {
      switch (*(opSet->operand)) {
         case ',' :
         case '#' :
         case '+' :
         case '-' :
         case ')' :
         case '{' :
         case '}' :
         case ':' :            /* reserved word */
            if (*(opSet->operand) == *opStr) {
               opStr++;
               opSet->operand++;
            }
            else
               return(ER_DAD_ASM_ERROR);
            break;
         case '(' :
            if (*(opSet->operand) == *opStr) {
               opStr++;
               opSet->operand++;
            }
            else
               return(ER_DAD_ASM_ERROR);
            ret = Reg2Operand(opSet,&opStr);
            break;
         case 'e' : /* ea */
            ret = EaOperand(opSet,&opStr);
            break;
         case 'E' :  /* Special case for move ea,ea */
            ret = SecondEaOperand(opSet,&opStr);
            break;
         case 'T' :
            opSet->operand++;
            ret = RegOperand(opSet,&opStr);
            opSet->objCode[1] += GetBits(opSet->objCode[1],12,3); /* Dr = Dq */
            break;
         case 'D' :
         case 'A' :
            ret = RegOperand(opSet,&opStr);
            break;
         case 'C' : /* CCR */
            ret = CCROperand(opSet,&opStr);
            break;
         case 'S' : /* SR  */
            ret = SROperand(opSet,&opStr);
            break;
         case 'U' : /* USP */
            ret = USPOperand(opSet,&opStr);
            break;
         case 'M' : /* MMUSR */
            ret = MMUSROperand(opSet,&opStr);
            break;
         case 'b':
            ret = BDataOperand(opSet,&opStr);
            break;
         case 'd':
            ret = DDispOperand(opSet,&opStr);
            break;
         case 'j':
            ret = JDataOperand(opSet,&opStr,startOffset+2);
            break;
         case 'o' : /*               */
            ret = ODataOperand(opSet,&opStr);
            break;
         case 'v' : /*               */
            ret = VDataOperand(opSet,&opStr);
            break;
         case 'p' : /*               */
            ret = PDataOperand(opSet,&opStr);
            break;
         case 'w' : /*               */
            ret = WDataOperand(opSet,&opStr);
            break;
         case 'x' : /* reserved word */
            ret = XRegOperand(opSet,&opStr);
            break;
         case 'f' : /* fc            */
            switch (*(opSet->operand+1)) {
               case 'c' :
                  ret = FcOperand(opSet,&opStr);
                  break;
               case 'p' :  /* FP */
                  ret = CoRegOperand(opSet,&opStr);
                  break;
               case 'l' : /* FP List       */
                  ret = CoRegisterCode(opSet,&opStr);
                  break;
               case 'r' : /* FPCR/FPSR/FPIAR */
                  ret = CoControlRegCode(opSet,&opStr);
                  break;
            }
            break;
         case 'r' :
            switch (*(opSet->operand+1)) {
               case 'l' :  /* Register List */
                  ret = RegListOperand(opSet,&opStr);
                  break;
               case 'c' : /* Control Register */
                  ret = ControlRegOperand(opSet,&opStr);
                  break;
            }
            break;
         case 'm' : /* MMU Register */
            ret = MMURegisterCode(opSet,&opStr);
            break;
         case 's' : /* reserved word */
            ret = SDataOperand(opSet,&opStr);
            break;
         case 'z' : /* DC mnemonic word */
            ret = DCDataOperand(opSet,&opStr);
            break;
         case 'c' : /* caches        */
            break;
      }
   }

   if ((err = TFree(opStrPtr)) != GOOD)
      return err;
   return(ret);
}

/****************************************************************************
*
*  CheckSpecialReg
*
*****************************************************************************/
RETCODE CheckSpecialReg(U8 FAR *OpString, U8 FAR *specialRegNo)
{
   LOOP_VAR lp1;

   *specialRegNo = 0xff;
   for (lp1 = 0; lp1 < 3; lp1++) {
      if (_fstrstr(OpString,SpecialReg[lp1]) != NULL) {
         *specialRegNo = lp1;
         break;
      }
   }
   return(GOOD);
}

/****************************************************************************
*
*  IdentifyInst
*
*****************************************************************************/
RETCODE IdentifyInst(OPERATOR FAR *opSet, U16 FAR *InstNo,
                     U8 FAR *length, U8 FAR *dFlag, U16 FAR *PosNo)
{
   register LOOP_VAR  lp1,lp2;
   U8  specialRegNo,mneBuf[12];
   U8 instSize;

   mneBuf[0] = 0x00;
   lstrcpy(mneBuf,opSet->mnemonic);

   PreMnemonic(PosNo,mneBuf,dFlag);
   if (opSet->size[0] == 'N') SearchSize(opSet->size,mneBuf);
   specialRegNo = 0xff;
   if (_fstricmp(opSet->mnemonic,"MOVE") == 0)
      CheckSpecialReg(opSet->opString,&specialRegNo);
   lp1 = 1;
   lp2 = 0;
   if ((mneBuf[0] == 'F') || (mneBuf[0] == 'f')) {
      while (lp1 < MAX_NUM_CO_INST) {
         instSize = SizeType(opSet->size);
         if ((_fstricmp(mneBuf,CoInstructionSet[lp1].Mnemonic) == 0) &&
             (((CoInstructionSet[lp1].OpSize & instSize) != 0) ||
              (CoInstructionSet[lp1].OpSize == instSize))) {
            InstNo[lp2] = lp1;
            lp2++;
         }
         lp1++;
      }
   }
   else {
      while (lp1 < MAX_NUM_INST) {
         instSize = SizeType(opSet->size);
         if ((_fstricmp(mneBuf,InstructionSet[lp1].Mnemonic) == 0) &&
            (((InstructionSet[lp1].OpSize & instSize) != 0) ||
            (InstructionSet[lp1].OpSize == instSize))) {
            if(specialRegNo == 0xff) {
               InstNo[lp2] = lp1;
               lp2++;
            }
            else {
               if (_fstrstr(OperandType[InstructionSet[lp1].OpType],
                  SpecialReg[specialRegNo]) != NULL) {
                  InstNo[lp2] = lp1;
                  lp2++;
               }
            }
         }
         lp1++;
      }
   }
   *length = (U8)lp2;
   if (*length == 0)
      return ER_DAD_INST_NOT_FOUND;
   return(GOOD);
}

/****************************************************************************
*
*  AsmInst
*
*****************************************************************************/
RETCODE AsmInst(OPERATOR FAR *opSet, LPSTR inInst, LPSTR *outInst,
                LPWORD numBytes, DESCRIPTOR StartAddr) {

   U32       startOffset, checkBit = 1;
   U16       tempData,InstNo[5],PosNo;
   LOOP_VAR  lp1,lp2,lp3;
   U8        length,dFlag,WordBuf[10];
   RETCODE   err;
   U8        validEaType;

#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   if (((err = GetToken(opSet,inInst)) != GOOD) && 
      (err != ER_DAD_INST_SIZE_UNDETERMINED)) return(err);
#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   if ((err = IdentifyInst(opSet,InstNo,&length,&dFlag,&PosNo)) != GOOD)
      return err;
#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   if ((*outInst = (LPSTR)TMalloc(lstrlen(inInst) +
         MAX_LINE_PER_INST*MAX_LINE_LENGTH)) == NULL)
      return ER_OUT_OF_MEMORY;
#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   if ((err = AdrGetAddrOffset(StartAddr,&startOffset)) != GOOD)
      return err;
#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif
   switch (length) {
      case 0 :
         return(ER_DAD_INST_NOT_FOUND);
      case 1 :
         CatchAsmData(opSet,InstNo[0],PosNo,dFlag);
         err = CreateObjCode(opSet,startOffset);
         opSet->cpuType = InstructionSet[InstNo[0]].CpuType;
         validEaType = InstructionSet[InstNo[0]].EaType;
         break;
      default :
         lp1 = 0;
         do {
            CatchAsmData(opSet,InstNo[lp1],PosNo,dFlag);
            err = CreateObjCode(opSet,startOffset);
            lp1++;
         } while ((lp1 < length) && (err != GOOD));
         opSet->cpuType = InstructionSet[InstNo[lp1-1]].CpuType;
         validEaType = InstructionSet[InstNo[lp1-1]].EaType;
   }
   if ((opSet->cpuType & cpuMask[cpuType]) != cpuMask[cpuType])
      err = ER_DAD_ASM_ERROR;

   if (opSet->ea1Type != 0) {
      if (opSet->ea2Type != 0) {   /* special for move <ea>,<ea> */
         if (!(EaClass[validEaType] & (checkBit << (opSet->ea1Type-1))))
            return ER_DAD_EA_INVALID;
         if (!(EaClass[MOVE_2ND_EA_TYPE] & (checkBit << (opSet->ea2Type-1))))
            return ER_DAD_EA_INVALID;
      } else if (!(EaClass[validEaType] & (checkBit << (opSet->ea1Type-1))))
         return ER_DAD_EA_INVALID;
   }
   

#ifdef DEBUG_MEM_LEAKS
   HeapDump(&memAlloced,&memFreed);
#endif

   if (err == GOOD) {
      if (_fstricmp(opSet->mnemonic,"MOVEM") == 0) {
         if (GetBits(opSet->objCode[0],3,3) == 4) {
            tempData = opSet->objCode[1];
            opSet->objCode[1] = 0;
            for (lp1 = 0; lp1 < 16; lp1++)
               opSet->objCode[1] += (GetBits(tempData,lp1,1) << (15 - lp1));
         }
      }
      **outInst = WordBuf[0] = 0x00;
      wsprintf(*outInst," %6.6lX  ",startOffset);

      for (lp1 = 0; lp1 < 3; lp1++) {
         if (opSet->opLength > lp1)
            wsprintf(WordBuf,"%4.4X",opSet->objCode[lp1]);
         else
            wsprintf(WordBuf,"    ");
         lstrcat(*outInst,WordBuf);
         lstrcat(*outInst," ");
      }
      lstrcat(*outInst," ");
      lstrcat(*outInst,inInst);
      *numBytes = opSet->opLength * 2;
      if (opSet->opLength > 3) {
         for (lp1 = 0; lp1 < (opSet->opLength-1)/3; lp1++) {
            lstrcat(*outInst,"\r\n           ");
            lp2 = (lp1+1)*3;
            for (lp3 = 0; lp3 < 3; lp3++) {
               if ((opSet->opLength- (lp1+1)*3) > lp3)
                  wsprintf(WordBuf,"%4.4X",opSet->objCode[lp2+lp3]);
               else
                  wsprintf(WordBuf,"    ");
               lstrcat(*outInst,WordBuf);
               lstrcat(*outInst," ");
            }
            lstrcat(*outInst,"      ");
         }
      }
   } else {
      lstrcat(*outInst,"   *** Error ***     ");
      lstrcat(*outInst,inInst);
      *numBytes = 0;
   }
   return(err);
}

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

