/****************************************************************************
**
**  Name:  dasmppc.c
**
**  Description:
**     This is a disassembler
**
**  Status:  REVIEWED
**
**  $Log:   S:/tbird/arcppc/dasm/dasmppc.c_v  $
** 
**    Rev 1.9   08 Apr 1998 10:56:04   hera
** for ppc821
** 
**    Rev 1.8   26 Feb 1998 14:24:52   kevin
** Treat floating-point instructions as illegal code
** 
**    Rev 1.7   11 Feb 1998 09:34:50   kevin
** In PPC860 case, floating-point instructions are treated as illegal code.
** 
**    Rev 1.6   19 Sep 1997 16:12:44   kevin
** in some cases, ProcessXXX always return GOOD. The return code should go with
** ProcessOperand
** 
**    Rev 1.5   19 Sep 1997 16:09:34   kevin
** DisassembleOpcode didn't handle error cases and return directly.
** 
**    Rev 1.4   19 Aug 1997 16:01:30   cjchen
** 
**    Rev 1.3   18 Jul 1997 17:57:22   cjchen
** 
**    Rev 1.2   31 Mar 1997 13:40:56   cjchen
**
**  $Header:   S:/tbird/arcppc/dasm/dasmppc.c_v   1.9   08 Apr 1998 10:56:04   hera  $
**
**  Copyright (C) 1991 Microtek International.  All rights reserved.
**
*****************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <io.h>
#include <string.h>
//#include "dadtable.h"

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

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

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

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

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

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



#include "603e.tbl"

#define INST_NO 225
#define I_NO    4
#define SC_NO   1
#define M_NO    6
#define XS_NO   2
#define MD_NO   8
#define MDS_NO  4
#define XFX_NO  4
#define XFL_NO  1
#define DS_NO   5
#define A_NO    42
#define XL_NO   15
#define B_NO    4
#define D_NO    42
#define XO_NO   76
#define X_NO    141


#define PAGESIZE 240
#define HALFPAGE 120

const U8 endOfBuffer[] = "\0";
const U8 endOfLine[] = "\r\n";

extern PROBE_TYPE specProc;
extern BOOLEAN dummyDasm;

const LPSTR space[] = {""," ","  ","   ","    ","     ","      ","       ",

                      "        ","         ","          ","           "};
static U32 pageCache = 0;
static LPU8 memCacheBuf = NULL;

U16 ProcessM(U32,  int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessMD(U32, int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessMDS(U32,int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessXFX(U32,int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessA(U32 , int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessXFL(U32,int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessXL(U32, int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessXS(U32, int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessI(U32 , int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessB(U32 , int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessSC(U32, int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessXO(U32, int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessD(U32 , int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessDS(U32, int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessX(U32 , int , OPERATOR* ,U32,BOOLEAN);
U16 ProcessOperand(U32 , OPERATOR*, U32,BOOLEAN);
//U16 DisassembleOpcode(U32 , OPERATOR *);
U16 DisassembleOpcode(U32 OpWord, U32 addrOffset, BOOLEAN symbols,
                          OPERATOR FAR *opSet, DASM_INFO FAR *dasmInfo);
U32 GetBits(U32, U8, U8);
RETCODE InitOpSet(OPERATOR FAR *opSet,BOOLEAN symbols);
RETCODE TraceBufInst(U32 addrOffset, BOOLEAN DadSymbol,
                     U8 FAR *inst, DASM_INFO FAR *dasmInfo,ADDR_SPACE addrSpace);
RETCODE DasmInst(U16 FAR *OpWord, DESCRIPTOR startAddr,U8 FAR *inst,
                 U8 FAR *InstLen, BOOLEAN DadSymbol);
RETCODE GetIntData(DESCRIPTOR address, LPU8 dataBuf);
RETCODE GetDasmInstNoAlloc(DESCRIPTOR startAddr, LPSTR buffer,
                    BOOLEAN DasmSymbol);
RETCODE GetDasmInstByLine(DESCRIPTOR startAddr, U16 FAR *lines, LPSTR *buffer,
                          BOOLEAN DasmSymbol);
RETCODE GetDasmInst(DESCRIPTOR startAddr, U16 numInst, LPSTR *buffer,
                    BOOLEAN DasmSymbol);
RETCODE EXPORT CheckDasmInst(DESCRIPTOR startAddr,BOOLEAN DasmSymbol,
                      U8 FAR *instLen, BOOLEAN FAR *instValid);
RETCODE EXPORT IsTransfer(DESCRIPTOR startAddr, DESCRIPTOR transferAddr,
      TRANSFER_TYPE *transfer);
RETCODE IsCallOrRTS(DESCRIPTOR startAddr, DESCRIPTOR calledAddr,
                    CALL_TYPE FAR *type);

RETCODE TraceBufInst(U32 addrOffset, BOOLEAN DadSymbol,
                     U8 FAR *inst, DASM_INFO FAR *dasmInfo,ADDR_SPACE addrSpace) {
    return GOOD;
}

/*****************************************************************************
**
**    InitOpSet
**
*****************************************************************************/
RETCODE InitOpSet(OPERATOR FAR *opSet,BOOLEAN symbols) {
   return(GOOD);
}

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

   RETCODE err;

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

   return GOOD;
}

//U16 DisassembleOpcode(U32 OpWord, OPERATOR *OpSet)
U16 DisassembleOpcode(U32 OpWord, U32 addrOffset, BOOLEAN symbols,
                          OPERATOR FAR *OpSet, DASM_INFO FAR *dasmInfo)
{
   U8 OpCode,ret;
   U16 OpXO;
   int i;
   BOOLEAN bFlag=FALSE;

   /* initialize all fields to FALSE */
   dasmInfo->transfer = dasmInfo->conditional = dasmInfo->knowAddr = FALSE;
   dasmInfo->call = dasmInfo->returnType = FALSE;
   dasmInfo->readCycle = dasmInfo->writeCycle = dasmInfo->instCycle = 0;
   dasmInfo->bytesUsed = 4;
   dasmInfo->target = 0;

   OpSet->ObjCode = OpWord;
   OpCode = GetBits(OpWord,5,6);

   // the following dirty code is to get rid of floating-point instructions
   // in PPC860 case
   if (specProc == PPC860_MP || specProc == PPC821_MP) {
      if (OpCode == 63 || OpCode == 59 ||   // general instructions
          (OpCode >= 48 && OpCode <= 55)) { // load/store instructions
         strcpy(OpSet->Mnemonic,"DW");
         sprintf(OpSet->Operand1," %lX",OpWord);
         OpSet->Operand2[0]=OpSet->Operand3[0]='\0';
         OpSet->Operand4[0]=OpSet->Operand5[0]='\0';
         return(GOOD);
      }
      else if (OpCode == 31) {
         OpXO = GetBits(OpWord,30,10);
         switch (OpXO) {
            case 535:   // lfsx
            case 567:   // lfsux
            case 599:   // lfdx
            case 631:   // lfdux
            case 663:   // stfsx
            case 695:   // stfsux
            case 711:   // mtfsfx
            case 727:   // stfdx
            case 759:   // stfdux
            case 983:   // stfiwx
               strcpy(OpSet->Mnemonic,"DW");
               sprintf(OpSet->Operand1," %lX",OpWord);
               OpSet->Operand2[0]=OpSet->Operand3[0]='\0';
               OpSet->Operand4[0]=OpSet->Operand5[0]='\0';
               return(GOOD);
         }
      }
   }

   for(i = 0; i < INST_NO; i++)
     if(OpCode == InstructionSet[i].OpCode)
     {
       dasmInfo->transfer=InstructionSet[i].Transfer;
       dasmInfo->conditional=InstructionSet[i].Conditional;
       dasmInfo->knowAddr=InstructionSet[i].KnowAddr;

       switch(InstructionSet[i].Formate)
       {
	 case I:
	   ret = ProcessI(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols);
	   if(ret == 0)
	   {
	     OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	     OpSet->SuperLevel = InstructionSet[i].SuperLevel;
	     i = INST_NO;
             bFlag=TRUE;
             dasmInfo->target=OpSet->targetAddr;
	   }
	   break;

	 case B:
	   if((ret = ProcessB(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	   {
	     OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	     OpSet->SuperLevel = InstructionSet[i].SuperLevel;
	     i = INST_NO;
             bFlag=TRUE;
             dasmInfo->target=OpSet->targetAddr;
	   }
          break;

	 case SC:
	   if(GetBits(OpWord,30,10) != 0x01)
              break;
	   if((ret = ProcessSC(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	   {
	     OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	     OpSet->SuperLevel = InstructionSet[i].SuperLevel;
             i = INST_NO;
             bFlag=TRUE;
           }
	   break;

	 case D:
	   if((ret = ProcessD(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	   {
	     OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	     OpSet->SuperLevel = InstructionSet[i].SuperLevel;
	     i = INST_NO;
             bFlag=TRUE;
	   }
	   break;

	 case DS:
	   OpXO = GetBits(OpWord,31,2);
	   if(OpXO == InstructionSet[i].Xo)
	   { 
	     if((ret = ProcessDS(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	     {
	       OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	       OpSet->SuperLevel = InstructionSet[i].SuperLevel;
	       i = INST_NO;
               bFlag=TRUE;
	     }
//!!             break;    //!!!??? is it a typo?
//!!           }           //!!!???
            }      //!! added
            break; //!! added
         case XO:
           OpXO = GetBits(OpWord,30,9);
	   if(OpXO == InstructionSet[i].Xo)
           {
	      ret = ProcessXO(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols);
	      if(ret == 0)
	      {
		OpSet->ArchLevel = InstructionSet[i].ArchLevel;
		OpSet->SuperLevel = InstructionSet[i].SuperLevel;
		i = INST_NO;
                bFlag=TRUE;
	      }
	    }	  
	    break;

	 case X:
	 case XL:
         case XFL:
	   OpXO = GetBits(OpWord,30,10);
	   if(OpXO == InstructionSet[i].Xo)
	   {
	      U8 Formate = InstructionSet[i].Formate;
	      if(Formate == X)
		 ret = ProcessX(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols);
	      else if(Formate == XL)
		 ret = ProcessXL(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols);
	      else if(Formate == XFL)
                 ret = ProcessXFL(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols);

	      if(ret == 0)
	      {
		OpSet->ArchLevel = InstructionSet[i].ArchLevel;
		OpSet->SuperLevel = InstructionSet[i].SuperLevel;
		i = INST_NO;
                bFlag=TRUE;
              }
	   }
	   break;

	case XFX:
	  OpXO = GetBits(OpWord,30,10);
	  if(OpXO == InstructionSet[i].Xo)
	  {
	    if((ret = ProcessXFX(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	    {
	      OpSet->ArchLevel = OpSet->ArchLevel & InstructionSet[i].ArchLevel;
	      OpSet->SuperLevel = OpSet->SuperLevel & InstructionSet[i].SuperLevel;
	      i = INST_NO;
              bFlag=TRUE;
	    }
	  }
	  break;

       case XS:
	  if(GetBits(OpWord,29,9) == InstructionSet[i].Xo)
	  {
	    if((ret = ProcessXS(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	    {
	      OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	      OpSet->SuperLevel = InstructionSet[i].SuperLevel;
	      i = INST_NO;
              bFlag=TRUE;
	    }
	  }
          break;
       case A:
	  if(GetBits(OpWord,30,5) == InstructionSet[i].Xo)
	  {
	    if((ret = ProcessA(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	    {
	      OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	      OpSet->SuperLevel = InstructionSet[i].SuperLevel;
	      i = INST_NO;
              bFlag=TRUE;
	    }
	  }
	  break;

       case M:
	  if((ret = ProcessM(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	  {
	    OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	    OpSet->SuperLevel = InstructionSet[i].SuperLevel;
	    i = INST_NO;
            bFlag=TRUE;
          }
	  break;

       case MD:
	  if(GetBits(OpWord,29,3) == InstructionSet[i].Xo)
	  {
	     if((ret = ProcessMD(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	     {
	       OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	       OpSet->SuperLevel = InstructionSet[i].SuperLevel;
               bFlag=TRUE;
	     }
	  }
          break;
       case MDS:
	  if(GetBits(OpWord,30,4) == InstructionSet[i].Xo)
	  {
	     if((ret = ProcessMDS(OpWord,InstructionSet[i].Index,OpSet,addrOffset,symbols)) == 0)
	     {
	       OpSet->ArchLevel = InstructionSet[i].ArchLevel;
	       OpSet->SuperLevel = InstructionSet[i].SuperLevel;
               bFlag=TRUE;
	     }
	  }
          break;
        }//*switch(InstructionSet[i].OpSet);
     }
     if( (_fstricmp((LPSTR)OpSet->Mnemonic,"bl") == 0)
        || (_fstricmp((LPSTR)OpSet->Mnemonic,"bla") == 0)
        || (_fstricmp((LPSTR)OpSet->Mnemonic,"bcl") == 0)
        || (_fstricmp((LPSTR)OpSet->Mnemonic,"bcla") == 0)
        || (_fstricmp((LPSTR)OpSet->Mnemonic,"bcctrl") == 0)
        || (_fstricmp((LPSTR)OpSet->Mnemonic,"bclrl") == 0) ){
        dasmInfo->call=1;
     }
     if (!bFlag || ret) {
        strcpy(OpSet->Mnemonic,"DW");
        sprintf(OpSet->Operand1," %lX",OpWord);
        OpSet->Operand2[0]=OpSet->Operand3[0]='\0';
        OpSet->Operand4[0]=OpSet->Operand5[0]='\0';
     }
     else
        for (i=0;i<strlen(OpSet->Mnemonic);i++)
           OpSet->Mnemonic[i]=tolower(OpSet->Mnemonic[i]);

   return GOOD;
}

U16 ProcessMD(U32 OpWord, int index,OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  index = index+(int)GetBits(OpWord,31,1);
  strcpy(OpSet->Mnemonic,MDForm[index].Mnemonic);
  OpSet->OpType = MDForm[index].OpType;
  OpSet->CpuType = MDForm[index].CpuType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}

U16 ProcessMDS(U32 OpWord, int index,OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  index = index+(int)GetBits(OpWord,31,1);
  strcpy(OpSet->Mnemonic,MDSForm[index].Mnemonic);
  OpSet->OpType = MDSForm[index].OpType;
  OpSet->CpuType = MDSForm[index].CpuType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}

U16 ProcessM(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  index = index+(int)GetBits(OpWord,31,1);
  strcpy(OpSet->Mnemonic,MForm[index].Mnemonic);
  OpSet->OpType = MForm[index].OpType;
  OpSet->CpuType = MForm[index].CpuType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}

U16 ProcessA(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  index = index+(int)GetBits(OpWord,31,1);
  if(AForm[index].OpType == 25 && GetBits(OpWord,25,5) != 0)
     return(!GOOD);
  strcpy(OpSet->Mnemonic,AForm[index].Mnemonic);
  OpSet->OpType = AForm[index].OpType;
  OpSet->CpuType =AForm[index].CpuType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}

U16 ProcessXS(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  index = index+(int)GetBits(OpWord,31,1);
  strcpy(OpSet->Mnemonic,SXForm[index].Mnemonic);
  OpSet->OpType = SXForm[index].OpType;
  OpSet->CpuType = SXForm[index].CpuType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}

U16 ProcessXFL(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  if(GetBits(OpWord,6,1) != 0 || GetBits(OpWord,15,1) != 0)
    return(!GOOD);

  index = index + (int)GetBits(OpWord,31,1);
  strcpy(OpSet->Mnemonic,XFLForm[index].Mnemonic);
  OpSet->OpType = XFLForm[index].OpType;
  OpSet->CpuType = XFLForm[index].CpuType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}

U16 ProcessXL(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  U32 temp;
  temp = GetBits(OpWord,30,10);
  if(temp == 0x210 || temp == 0x10)
    index = index+ (int)GetBits(OpWord,31,1);
  else if(GetBits(OpWord,31,1) != 0)
    return(!GOOD);

  strcpy(OpSet->Mnemonic,XLForm[index].Mnemonic);
  OpSet->OpType = XLForm[index].OpType;
  OpSet->CpuType = XLForm[index].CpuType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}
    

U16 ProcessXFX(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  if(GetBits(OpWord,31,1) != (U32) 0)
    return(!GOOD);

  strcpy(OpSet->Mnemonic,XFXForm[index].Mnemonic);
  OpSet->OpType = XFXForm[index].OpType;
  OpSet->CpuType = XFXForm[index].CpuType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}

U16 ProcessI(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  int i;

  for(i = index; i < I_NO; i++)
   if(GetBits(OpWord,31,2) == (U32)IForm[i].AA_LK)
   {
     strcpy(OpSet->Mnemonic,IForm[i].Mnemonic);
     OpSet->OpType = IForm[i].OpType;
     OpSet->CpuType = IForm[i].CpuType;
     return(ProcessOperand(OpWord, OpSet,addrOffset,symbols));
   }
  return(!GOOD);
}

U16 ProcessB(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  int i;

  for(i = index; i< B_NO; i++)
   if(GetBits(OpWord,31,2) == (U32)BForm[i].AA_LK)
   {
     strcpy(OpSet->Mnemonic,BForm[i].Mnemonic);
     OpSet->OpType = BForm[i].OpType;
     OpSet->CpuType = BForm[i].CpuType;
     return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
   }
  return(!GOOD);
}

U16 ProcessSC(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  int i;

  for(i = index; i < SC_NO; i++)
   if(GetBits(OpWord,31,1) == (U32)SCForm[i].RC)
   {
     strcpy(OpSet->Mnemonic,SCForm[i].Mnemonic);
     OpSet->OpType = SCForm[i].OpType;
     OpSet->CpuType = SCForm[i].CpuType;
     return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
   }
  return(!GOOD);
}

U16 ProcessD(U32 OpWord, int index,OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  
  strcpy(OpSet->Mnemonic,DForm[index].Mnemonic);
  OpSet->OpType = DForm[index].OpType;

  if(DForm[index].OpType != 16 && DForm[index].OpType != 17) /*(crfD,L,rA,SIMM) and (crfD,L,rA,UIMM)*/
    OpSet->CpuType = DForm[index].CpuType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}

U16 ProcessDS(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  strcpy(OpSet->Mnemonic,DSForm[index].Mnemonic);
  OpSet->OpType = DSForm[index].OpType;
  return(ProcessOperand(OpWord,OpSet,addrOffset,symbols));
}

U16 ProcessXO(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  int i;
  
  for(i = index; i < XO_NO; i++)
   if((OpWord & 0x00000401) == XOForm[i].OE_RC)
   {
     strcpy(OpSet->Mnemonic,XOForm[i].Mnemonic);
     OpSet->OpType = XOForm[i].OpType;
     OpSet->CpuType = XOForm[i].CpuType;
     return(ProcessOperand(OpWord, OpSet,addrOffset,symbols));
   }
  return(!GOOD);
}

U16 ProcessX(U32 OpWord, int index, OPERATOR* OpSet,U32 addrOffset,BOOLEAN symbols)
{
  int i;
  
  for(i = index; i < X_NO; i++)
   if(GetBits(OpWord,31,1) == (U32)XForm[i].RC)
   {
     strcpy(OpSet->Mnemonic,XForm[i].Mnemonic);
     OpSet->OpType = XForm[i].OpType;
     if(OpSet->OpType != 11) /*(crfD,L,rA,rB) = 11*/
       OpSet->CpuType = XForm[i].CpuType;
     return(ProcessOperand(OpWord, OpSet,addrOffset,symbols));
   }
  return(!GOOD);
}

U16 ProcessOperand(U32 OpWord, OPERATOR *OpSet,U32 addrOffset,BOOLEAN symbols)
{
  U32 temp,aaBit;
  U32 Split_Field;
  U32 Mask1,Mask2;
  DESCRIPTOR dadAddr,symNameDesc;
  MEM_ADDR_CLASS memoryClass;
  SYM_TYPE_TYPE  symbolType;
  U32            offset;
  SYM_DESCRIPTOR outputSymbol;
  SYM_DESCRIPTOR funcDescriptor;
  SYM_DESCRIPTOR moduleDescriptor;

  Mask1 = 0x1 | 0x8 | 0x9;
  Mask2 = 0x12 | 0x13 | 0x16 | 0x19 | 0x1A | 0x1B | 0x110 | 0x111;
  Mask2 = Mask2 | 0x112 | 0x113 | 0x118 | 0x11A | 0x11F | 0x210;
  Mask2 = Mask2 | 0x211 | 0x212 | 0x213 | 0x214 | 0x215 | 0x216;
  Mask2 = Mask2 | 0x217 | 0x218 | 0x219 | 0x21A | 0x21B | 0x21C;
  Mask2 = Mask2 | 0x21D | 0x21E | 0x21F | 0x3F5;


  switch(OpSet->OpType)
  {

   case 6: /*RS,rA,NB*/
   case 1: /*rD,rA,NB*/
	/*rD,RS*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
        /*rA*/
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand2,"r%u,",(U16)temp);
	/*NB*/
	temp = GetBits(OpWord,20,5);
	sprintf(OpSet->Operand3,"%u",(U16)temp);
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 2: /*rD,rB*/
	if(GetBits(OpWord,15,5) != 0)
          return(!GOOD);
        /*rD*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
        /*rB*/
	temp = GetBits(OpWord,20,5);
	sprintf(OpSet->Operand2,"r%u",(U16)temp);
	OpSet->Operand3[0] = '\0';
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 27:/*frD*/
   case 8: /*rS*/
   case 3: /*rD*/
    if(GetBits(OpWord,20,10) != 0)
           return(!GOOD);

	temp = GetBits(OpWord,10,5);
	if(OpSet->OpType == 27)
	  sprintf(OpSet->Operand1," fr%u",(U16)temp);
        else
	  sprintf(OpSet->Operand1," r%u",(U16)temp);
	OpSet->Operand2[0] = OpSet->Operand3[0] = '\0';
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 4: /*rD,SR*/
	if(GetBits(OpWord,11,1) != 0 || GetBits(OpWord,20,5) != 0)
           return(!GOOD);
        /*rD*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
        /*SR*/
	temp = GetBits(OpWord,15,4);
	sprintf(OpSet->Operand2,"%u",(U16)temp);
	OpSet->Operand3[0] = OpSet->Operand4[0] = '\0';
        OpSet->Operand5[0] = '\0';
        break;

   case 5: /*rS,rA,rB*/
        /*rS*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand2,"r%u,",(U16)temp);
	/*rA*/
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
	/*rB*/
	temp = GetBits(OpWord,20,5);
	sprintf(OpSet->Operand3,"r%u",(U16)temp);
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 7: /*rA,rS*/
	if(GetBits(OpWord,20,5) != 0)
          return(!GOOD);
	/*rS*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand2,"r%u",(U16)temp);
        /*rA*/
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
        OpSet->Operand3[0] = '\0';
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 9: /*SR,rS*/
	if(GetBits(OpWord,11,1) != 0 || GetBits(OpWord,20,5) != 0)
           return(!GOOD);
        /*rS*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand2,"r%u",(U16)temp);
        /*SR*/
	temp = GetBits(OpWord,15,4);
	sprintf(OpSet->Operand1," %u,",(U16)temp);
	OpSet->Operand3[0] = OpSet->Operand4[0] = '\0';
        OpSet->Operand5[0] = '\0';
        break;

   case 10: /*rA,rS,SH*/
	/*rS*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand2,"r%u,",(U16)temp);
        /*rA*/
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
	/*SH*/
	temp = GetBits(OpWord,20,5);
	sprintf(OpSet->Operand3,"%u",(U16)temp);
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 11: /*crfD,L,rA,rB*/
        /*L*/
	if(GetBits(OpWord,9,1) != 0)
          return(!GOOD);
	if(GetBits(OpWord,10,1))
        {
	  OpSet->CpuType = 0x00;
	  sprintf(OpSet->Operand2,"1,");
	}
	else
	{
	  OpSet->CpuType = 0x01;
	  sprintf(OpSet->Operand2,"0,");
	}
        /*crfD*/
	temp = GetBits(OpWord,8,3);
	sprintf(OpSet->Operand1," %u,",(U16)temp);
        /*rA*/
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand3,"r%u,",(U16)temp);
	/*rB*/
	temp = GetBits(OpWord,20,5);
	sprintf(OpSet->Operand4,"r%u",(U16)temp);
	OpSet->Operand5[0] = '\0';
	break;

   case 12: /*crfD,rA,rB*/
   case 28: /*crfD,frA,frB*/
	if(GetBits(OpWord,10,2) != 0)
          return(!GOOD);
        /*crfD*/
	temp = GetBits(OpWord,8,3);
	sprintf(OpSet->Operand1," %u,",(U16)temp);
	/*rA,frA*/
	temp = GetBits(OpWord,15,5);
        if(OpSet->OpType == 12)
	   sprintf(OpSet->Operand2,"r%u,",(U16)temp);
	else
           sprintf(OpSet->Operand2,"fr%u,",(U16)temp);
	/*rB,frB*/
	temp = GetBits(OpWord,20,5);
        if(OpSet->OpType == 12)
	  sprintf(OpSet->Operand3,"r%u",(U16)temp);
	else
          sprintf(OpSet->Operand3,"fr%u",(U16)temp);
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 13: /*rA,rB*/
	if(GetBits(OpWord,10,5) != 0)
           return(!GOOD);
        /*rA*/
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
	/*rB*/
	temp = GetBits(OpWord,20,5);
	sprintf(OpSet->Operand2," r%u",(U16)temp);
	OpSet->Operand3[0] = '\0';
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 14: /*rD,rA,SIMM*/
   case 34: /*TO,rA,SIMM*/
	temp = GetBits(OpWord,10,5);
	if(OpSet->OpType == 34)
	 sprintf(OpSet->Operand1," %u,",(U16)temp);
        else
	 sprintf(OpSet->Operand1," r%u,",(U16)temp);

	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand2,"r%u,",(U16)temp);
	temp = GetBits(OpWord,31,16);
	sprintf(OpSet->Operand3,"%d",(int)temp);
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 15: /*rA,rS,UIMM*/
        /*rS*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand2,"r%u,",(U16)temp);
        /*rA*/
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
        /*UIMM*/
	temp = GetBits(OpWord,31,16);
	sprintf(OpSet->Operand3,"%u",(U16)temp);
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 16: /*crfD,L,rA,SIMM*/
   case 17: /*crfD,L,rA,UIMM*/
	if(GetBits(OpWord,10,1))
        {
	  OpSet->CpuType = 0x00;
	  sprintf(OpSet->Operand2,"1,");
        }
	else
        {
	  OpSet->CpuType = 0x01;
	  sprintf(OpSet->Operand2,"0,");
        }
	temp = GetBits(OpWord,8,3);
	sprintf(OpSet->Operand1," %u,",(U16)temp);
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand3,"r%u,",(U16)temp);
	temp = GetBits(OpWord,31,16);
        if(OpSet->OpType == 16)
	  sprintf(OpSet->Operand4,"%d",(int)temp);
	else if(OpSet->OpType == 17)
	  sprintf(OpSet->Operand4,"%u",(U16)temp);
	OpSet->Operand5[0]='\0';
	break;

   case 18: /*BO,BI,BD*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand1," %u,",(U16)temp);
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand2,"%u,",(U16)temp);
	temp = GetBits(OpWord,29,14);
 aaBit = GetBits(OpWord,30,1);
 if (temp > 0x2000) { // minus
 	  temp = (temp ^ 0x3fff)+1;
    if (aaBit)
       temp = -(temp<<2) ;
    else
       temp=-(temp<<2)+addrOffset;
 	  sprintf(OpSet->Operand3,"0x%lX",temp);
 }
 else {
 	  if (aaBit)
    	  temp = (temp<<2) ;
    else
       temp=(temp<<2)+addrOffset;
    sprintf(OpSet->Operand3,"0x%lX",temp);
 }
 OpSet->targetAddr=temp;
 if (symbols) {
    AdrCreateAddress(&dadAddr);
    AdrSetAddrOffset(dadAddr,temp);
    SymMapAddr2Symbol(dadAddr,&memoryClass,&symbolType,&offset,
       &outputSymbol,&funcDescriptor,&moduleDescriptor);
    if (offset == 0)
       if ((SymGetSymbolName(outputSymbol, &symNameDesc)) == GOOD)
          wsprintf(OpSet->Operand1," %s",(LPSTR)symNameDesc);
 }
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

   case 19: /*LI*/
	temp = GetBits(OpWord,29,24);
 aaBit= GetBits(OpWord,30,1);
 if (temp > 0x800000) { //minus
 	  temp = (temp ^ 0xffffff) +1;
    if (aaBit)
       temp = -(temp<<2) ;
    else
       temp = -(temp<<2) + addrOffset;
    sprintf(OpSet->Operand1," 0x%lX",temp);
 }
 else {
    if (aaBit)
       temp = temp<<2;
    else
       temp = (temp <<2) + addrOffset;
	   sprintf(OpSet->Operand1," 0x%lX",temp);
 }
 OpSet->targetAddr=temp;
 if (symbols) {
    AdrCreateAddress(&dadAddr);
    AdrSetAddrOffset(dadAddr,temp);
    SymMapAddr2Symbol(dadAddr,&memoryClass,&symbolType,&offset,
       &outputSymbol,&funcDescriptor,&moduleDescriptor);
    if (offset == 0)
       if ((SymGetSymbolName(outputSymbol, &symNameDesc)) == GOOD)
          wsprintf(OpSet->Operand1," %s",(LPSTR)symNameDesc);
 }
	OpSet->Operand2[0] = OpSet->Operand3[0] = '\0';
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

  case 20: /*BO,BI*/
	if(GetBits(OpWord,20,5) != 0)
          return(!GOOD);
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand1," %u,",(U16)temp);
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand2,"%u",(U16)temp);
	OpSet->Operand3[0] = '\0';
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

  case 21: /*crbD,crbA,crbB*/
	/*crbD*/
	temp = GetBits(OpWord,10,5);
	sprintf(OpSet->Operand1," %u,",(U16)temp);
        /*crbA*/
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand2,"%u,",(U16)temp);
	/*crbB*/
	temp = GetBits(OpWord,20,5);
	sprintf(OpSet->Operand3,"%u",(U16)temp);
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

  case 22: /*crfD,crfS*/
       if(GetBits(OpWord,20,5)!=0 || GetBits(OpWord,15,2)!=0 || GetBits(OpWord,10,2)!=0)
          return(!GOOD);
       /*crfD*/
       temp = GetBits(OpWord,8,3);
       sprintf(OpSet->Operand1," %u,",(U16)temp);
       /*crfS*/
       temp = GetBits(OpWord,13,3);
       sprintf(OpSet->Operand2,"%u",(U16)temp);
       break;

  case 23: /*  */
	if(GetBits(OpWord,20,15)!=0)
          return(!GOOD);
	OpSet->Operand1[0] = '\0';
       	OpSet->Operand2[0] = OpSet->Operand3[0] = '\0';
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

  case 24: /*rD,rA*/
       if(GetBits(OpWord,20,5)!=0)
          return(!GOOD);
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," r%u,",(U16)temp);
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand2,"r%u",(U16)temp);
       OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 25:/*frD,frB*/
       if (GetBits(OpWord,15,5) != 0)
          return(!GOOD);
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," fr%u,",(U16)temp);
       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand2,"fr%u",(U16)temp);
       OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 60:/*frD,frB*/
       if(GetBits(OpWord,25,5) != 0 || GetBits(OpWord,15,5) != 0)
          return(!GOOD);
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," fr%u,",(U16)temp);
       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand2,"fr%u",(U16)temp);
       OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 26:/*frD,frA,frB*/
       if(GetBits(OpWord,25,5) != 0)
          return(!GOOD);
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," fr%u,",(U16)temp);
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand2,"fr%u,",(U16)temp);
       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand3,"fr%u",(U16)temp);
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 29:/*frD,frA,frC,frB*/
       /*frD*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," fr%u,",(U16)temp);
       /*frA*/
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand2,"fr%u,",(U16)temp);
       /*frC*/
       temp = GetBits(OpWord,25,5);
       sprintf(OpSet->Operand3,"fr%u,",(U16)temp);
       /*frB*/
       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand4,"fr%u",(U16)temp);
       OpSet->Operand5[0] = '\0';
       break;

  case 30:/*rD,Dis(rA)*/
  case 31:/*rS,Dis(rA)*/
  case 33:/*fRS,Dis(rA)*/
  case 49:/*frD,Dis(rA)*/
       /* rD or rS or frD*/
       temp = GetBits(OpWord,10,5);
       if(OpSet->OpType == 49 || OpSet->OpType == 33)
	sprintf(OpSet->Operand1," fr%u,",(U16)temp);
       else
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
       /*rA*/
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand3,"(r%u)",(U16)temp);
       /*Dis*/
       temp = GetBits(OpWord,31,16);
       if (temp >= 0x8000) { // minus
          temp = (temp ^ 0xffff) + 1;
          sprintf(OpSet->Operand2,"-0x%X",temp);
       }
       else
          sprintf(OpSet->Operand2,"0x%X",temp);
       strcat(OpSet->Operand2,OpSet->Operand3);
       OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 59: /*rS,rA,rB*/
  case 32: /*rD,rA,rB*/
	temp = GetBits(OpWord,10,5);        
	sprintf(OpSet->Operand1," r%u,",(U16)temp);
	temp = GetBits(OpWord,15,5);
	sprintf(OpSet->Operand2,"r%u,",(U16)temp);
	temp = GetBits(OpWord,20,5);
	sprintf(OpSet->Operand3,"r%u",(U16)temp);
	OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
	break;

  case 35: /*rS,Ds(rA)*/
  case 36: /*rD,Ds(rA)*/
       /* rD or rS*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," r%u,",(U16)temp);
       /*rA*/
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand3,"(r%u)",(U16)temp);
       /*Dis*/
       temp = GetBits(OpWord,29,14);
       if (temp > 0x2000) { //minus
       	   temp = (temp ^ 0x3fff) +1;
           sprintf(OpSet->Operand2,"-0x%X",temp);
       }
       else
          sprintf(OpSet->Operand2,"0x%X",temp);
       strcat(OpSet->Operand2,OpSet->Operand3);
       OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 37: /*rD,SPR*/       
       temp = (GetBits(OpWord,20,5) << 5) | GetBits(OpWord,15,5);  /*spr[5-9]spr[0-4]*/     
       Split_Field = temp;
       if((Split_Field & Mask1) == Split_Field)
       {
         OpSet->ArchLevel = UISA_OEA;
         OpSet->SuperLevel = 0x01; /*user Mode*/
       }
       else if((Split_Field & Mask2) == Split_Field)
       {
         OpSet->ArchLevel = OEA;
         OpSet->SuperLevel = 0x02; /*supervisor Mode*/
       }
       else
         return(!GOOD);

       /*SPR*/
       sprintf(OpSet->Operand2,"%u",(U16)temp);
       /*rD*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," r%u,",(U16)temp);
       OpSet->Operand3[0] = OpSet->Operand4[0] = '\0';
       OpSet->Operand5[0] = '\0';
       break;

  case 38: /*CRM,rS*/
       if(GetBits(OpWord,11,1) != 0 || GetBits(OpWord,20,1) != 0)
          return(!GOOD);
       /*rS*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand2,"r%u",(U16)temp);
       /*CRM*/
       temp = GetBits(OpWord,19,8);
       sprintf(OpSet->Operand1," 0x%X,",(U16)temp);
       OpSet->Operand3[0] = OpSet->Operand4[0] = '\0';
       OpSet->Operand5[0] = '\0';
       break;

  case 39: /*rD,TBR*/
       temp = (GetBits(OpWord,20,5) << 5) | GetBits(OpWord,15,5);  /*TBR[5-9]TBR[0-4]*/
       Split_Field = temp;
       if((Split_Field & (0x10C|0x10D)) == Split_Field)
       {
         OpSet->ArchLevel = VEA;
         OpSet->SuperLevel = 0x01; /*user Mode*/
       }
       else
         return(!GOOD);

       /*TBR*/       
       sprintf(OpSet->Operand2,"%u",(U16)temp);

       /*rD*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," r%u,",(U16)temp);
       OpSet->Operand3[0] = OpSet->Operand4[0] = '\0';
       OpSet->Operand5[0] = '\0';
       break;

  case 40: /*FM frB*/
       temp = GetBits(OpWord,14,8);
       sprintf(OpSet->Operand1," 0x%X,",(U16)temp);
       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand2,"fr%u",(U16)temp);
       OpSet->Operand3[0] = OpSet->Operand4[0] = '\0';
       OpSet->Operand5[0] = '\0';
       break;

  case 41: /*To,rA,rB*/
      /*TO*/
      temp = GetBits(OpWord,10,5);
      sprintf(OpSet->Operand1," %u,",(U16)temp);
      /*rA*/
      temp = GetBits(OpWord,15,5);
      sprintf(OpSet->Operand2,"r%u,",(U16)temp);
      /*rB*/
      temp = GetBits(OpWord,20,5);
      sprintf(OpSet->Operand3,"r%u",(U16)temp);
      OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
      break;

  case 42: /*rA,rS,SH,MB,ME*/
       /*rS*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand2,"r%u,",(U16)temp);
       /*rA*/
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand1," r%u,",(U16)temp);
       /*SH*/
       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand3,"%u,",(U16)temp);
       /*MB*/
       temp = GetBits(OpWord,25,5);
       sprintf(OpSet->Operand4,"%u,",(U16)temp);
       /*ME*/
       temp = GetBits(OpWord,30,5);
       sprintf(OpSet->Operand5,"%u",(U16)temp);
       break;

  case 43: /*rA,rS,rB,MB,ME*/
       /*rS*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand2,"r%u,",(U16)temp);
       /*rA*/
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand1," r%u,",(U16)temp);
       /*rB*/
       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand3,"r%u,",(U16)temp);
       /*MB*/
       temp = GetBits(OpWord,25,5);
       sprintf(OpSet->Operand4,"%u,",(U16)temp);
       /*ME*/
       temp = GetBits(OpWord,30,5);
       sprintf(OpSet->Operand5,"%u",(U16)temp);
       break;

  case 44: /*rS,rA,SH,mb*/  
  case 45: /*rS,rA,SH,me*/
       /*rS*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand2,"r%u,",(U16)temp);
       /*rA*/
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand1," r%u,",(U16)temp);
       /*SH (this is a split field*/
       temp = GetBits(OpWord,30,1) << 5 | GetBits(OpWord,20,5);
       sprintf(OpSet->Operand3,"%u,",(U16)temp);
       /*me,mb*/
       temp = GetBits(OpWord,26,1) << 5 | GetBits(OpWord,25,5);
       sprintf(OpSet->Operand4,"%u",(U16)temp);
       OpSet->Operand5[0] = '\0';
       break;

  case 46: /*rA,rS,rB,mb*/
  case 47: /*rA,rS,rB,me*/
       /*rS*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand2,"r%u,",(U16)temp);
       /*rA*/
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand1," r%u,",(U16)temp);
       /*rB*/
       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand3," r%u,",(U16)temp);
       /*me,mb*/
       temp = GetBits(OpWord,26,1) << 5 | GetBits(OpWord,25,5);
       sprintf(OpSet->Operand4,"%u",(U16)temp);
       OpSet->Operand5[0] = '\0';
       break;

  case 50: /*frD,frA,frC*/
       if(GetBits(OpWord,20,5) != 0)
          return(!GOOD);

       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," fr%u,",(U16)temp);
       temp = GetBits(OpWord,15,5);
       sprintf(OpSet->Operand2,"fr%u,",(U16)temp);
       temp = GetBits(OpWord,25,5);
       sprintf(OpSet->Operand3,"fr%u",(U16)temp);
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 51: /*crfD*/
       if(GetBits(OpWord,20,12) != 0)
          return(!GOOD);
       temp = GetBits(OpWord,8,3);
       sprintf(OpSet->Operand1," %u",(U16)temp);
       OpSet->Operand2[0] = OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 52: /*crbD*/
       if(GetBits(OpWord,15,10) != 0)
          return(!GOOD);

       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," %u",(U16)temp);
       OpSet->Operand2[0] = OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 53: /*crfD,IMM*/
       if(GetBits(OpWord,15,7) != 0 || GetBits(OpWord,20,1) !=0)
          return(!GOOD);
       /*crfD*/
       temp = GetBits(OpWord,8,3);
       sprintf(OpSet->Operand1," %u,",(U16)temp);
       /*IMM*/
       temp = GetBits(OpWord,19,4);
       sprintf(OpSet->Operand2,"0x%X",(U16)temp);
       OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 54: /*SPR,rS*/
       temp = (GetBits(OpWord,20,5) << 5) | GetBits(OpWord,15,5);  /*spr[5-9]spr[0-4]*/     
       Split_Field = temp;
       if((Split_Field & Mask1) == Split_Field)
       {
         OpSet->ArchLevel = UISA_OEA;
         OpSet->SuperLevel = 0x01; /*user Mode*/
       }
       else if((Split_Field & Mask2) == Split_Field)
       {
         OpSet->ArchLevel = OEA;
         OpSet->SuperLevel = 0x02; /*supervisor Mode*/
       }
       else
         return(!GOOD);

       /*SPR*/
       sprintf(OpSet->Operand1," %u,",(U16)temp);
       /*rS*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand2," r%u",(U16)temp);
       OpSet->Operand3[0] = OpSet->Operand4[0] = '\0';
       OpSet->Operand5[0] = '\0';
       break;

  case 55: /*rS,rB*/
       if(GetBits(OpWord,15,5) != 0)
          return(!GOOD);
       /*rS*/
       temp = GetBits(OpWord,10,5);
       sprintf(OpSet->Operand1," r%u,",(U16)temp);
       /*rB*/
       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand2,"r%u",(U16)temp);
       OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 56: /*rB*/
       if(GetBits(OpWord,10,5) != 0 || GetBits(OpWord,15,5) != 0)
           return(!GOOD);

       temp = GetBits(OpWord,20,5);
       sprintf(OpSet->Operand1," r%u",(U16)temp);
       OpSet->Operand2[0] = OpSet->Operand3[0] = '\0';
       OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
       break;

  case 57: /*rA,rS,SH (sh is a split field)*/
      /*rS*/
      temp = GetBits(OpWord,10,5);
      sprintf(OpSet->Operand2,"r%u,",(U16)temp);
      /*rA*/
      temp = GetBits(OpWord,15,5);
      sprintf(OpSet->Operand1," r%u,",(U16)temp);
      /*SH*/
      temp = GetBits(OpWord,30,1) << 5 | GetBits(OpWord,20,5);
      sprintf(OpSet->Operand3,"%u",(U16)temp);
      OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
      break;

  case 48: /*frD,rA,rB*/
  case 58: /*frS,rA,rB*/
      temp = GetBits(OpWord,10,5);
      sprintf(OpSet->Operand1," fr%u,",(U16)temp);
      temp = GetBits(OpWord,15,5);
      sprintf(OpSet->Operand2,"r%u,",(U16)temp);
      temp = GetBits(OpWord,20,5);
      sprintf(OpSet->Operand3,"r%u",(U16)temp);
      OpSet->Operand4[0] = OpSet->Operand5[0] = '\0';
      break;

  }
 return GOOD;
}

U32 GetBits(U32 value, U8 endBits, U8 length)
{
   U32 buffer, mask;
   buffer = value >> (31-endBits);
   mask = 0xffffffff;
   mask = (mask >> (32-length));
   buffer &= mask;
   return (buffer);
}

/*****************************************************************************
**
**    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;
   STATIC ADDR_SPACE preSpace = SPACE_SP;
   ADDR_SPACE curSpace;

   if ((err = AdrGetAddrOffset(address,&offset)) != GOOD)
      return err;
   if ((err = AdrGetAddrSpace(address,&curSpace)) != 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)) && (curSpace == preSpace)) {
      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);
   }                    
   preSpace = curSpace ;
   return(GOOD);
}

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

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


   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);
   }

   OpCode = ((U32)OpWord[0] << 16) | OpWord[1]; // Hera 2/25/97
   err=DisassembleOpcode(OpCode,addrOffset,DadSymbol,&opSet,&dasmInfo);

   /******** Start Output inst ********/
   if ((err = AdrConvAddressToTextWithParams(dupAddr,FALSE,TRUE,
              (LPSTR)WordBuf)) != GOOD) {
      AdrDestroyAddress(dupAddr);
      return(err);
   }
   lstrcat((LPSTR)inst,(LPSTR)WordBuf);
   lstrcat((LPSTR)inst,(LPSTR)space[2]);
   for (loop2 = 1; loop2 >= 0; loop2--) {
      wsprintf((LPSTR)WordBuf,"%4.4X",(U16)(opSet.ObjCode >> (16*loop2))); //Hera 2/26/97
      lstrcat((LPSTR)inst,(LPSTR)WordBuf);
      lstrcat((LPSTR)inst,(LPSTR)space[1]);
   }
   lstrcat((LPSTR)inst,(LPSTR)space[1]);
   lstrcat((LPSTR)inst,(LPSTR)opSet.Mnemonic);
   nLength=strlen(opSet.Mnemonic);
   lstrcat((LPSTR)inst,(LPSTR)space[10-nLength]);
   lstrcat((LPSTR)inst,(LPSTR)opSet.Operand1);
   lstrcat((LPSTR)inst,(LPSTR)opSet.Operand2);
   lstrcat((LPSTR)inst,(LPSTR)opSet.Operand3);
   lstrcat((LPSTR)inst,(LPSTR)opSet.Operand4);
   lstrcat((LPSTR)inst,(LPSTR)opSet.Operand5);
   lstrcat((LPSTR)inst,(LPSTR)space[1]);
   /******** End Output inst ********/
   *InstLen = 4;

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

   return(GOOD);
}

/*****************************************************************************
**
**    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 lstrcat 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);
   if ((err = AdrAddToAddress(startAddr,InstLen)) != GOOD) {
      if (err == ER_ADR_RESULT_OVERFLOW) return(GOOD);
      return(err);
   }
   return(GOOD);
}

/*****************************************************************************
**
**    GetDasmInstByLine
**
*****************************************************************************/
RETCODE GetDasmInstByLine(DESCRIPTOR startAddr, U16 FAR *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 lstrcat is being used by dasminst */
   _fmemset(tmpPtr,'\0', 1);

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

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

   lstrcat(*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);

   if ((err = AdrAddToAddress(startAddr,instLen)) != GOOD) return(err);

   return(err);
}

/*****************************************************************************
**
**    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 lstrcat is being used by dasminst */
   _fmemset(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);
         lstrcat((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) {
            lstrcat(*buffer,(LPSTR)endOfBuffer);
            err = GOOD;
            break;
         }
         return(err);
      }
         
      if (instCnt < numInst - 1)
         lstrcat(*buffer,(LPSTR)endOfLine);
      else
         lstrcat(*buffer,(LPSTR)endOfBuffer);
   }
   return(err);
}

/*****************************************************************************
**
**    IsTransfer
**
*****************************************************************************/
RETCODE EXPORT IsTransfer(DESCRIPTOR startAddr, DESCRIPTOR transferAddr,
      TRANSFER_TYPE *transfer) {
   OPERATOR opSet;
   U32 addrOffset,OpCode;
   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);


   OpCode = ((U32)OpWord[0] << 16) | OpWord[1]; // Hera 2/25/97
   if((err=DisassembleOpcode(OpCode,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);
}

/*****************************************************************************
**
**    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 EXPORT CheckDasmInst(DESCRIPTOR startAddr,BOOLEAN DasmSymbol,
                      U8 FAR *instLen, BOOLEAN FAR *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 = 4;
   } else {
      *instLen = 4;
   }

   return(err);
}

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

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

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

   OpCode = ((U32)OpWord[0] << 16) | OpWord[1]; // Hera 2/25/97
   if((err=DisassembleOpcode(OpCode,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);
   // cjchen 1997.7.16
   if( (_fstricmp((LPSTR)opSet.Mnemonic,"bl") == 0)
      || (_fstricmp((LPSTR)opSet.Mnemonic,"bla") == 0)
      || (_fstricmp((LPSTR)opSet.Mnemonic,"bcl") == 0)
      || (_fstricmp((LPSTR)opSet.Mnemonic,"bcla") == 0)
      || (_fstricmp((LPSTR)opSet.Mnemonic,"bcctrl") == 0)
      || (_fstricmp((LPSTR)opSet.Mnemonic,"bclrl") == 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 */
   else if( (_fstricmp((LPSTR)opSet.Mnemonic,"bclr") == 0)
           || (_fstricmp((LPSTR)opSet.Mnemonic,"bclrl") == 0) )
      *type = INST_RETURN;
   else
      *type = INST_NONE;

   return(err);
}
