/*

 *      Interactive disassembler (IDA).
 *      Version 3.05
 *      Copyright (c) 1990-95 by Ilfak Guilfanov.
 *      ALL RIGHTS RESERVED.
 *                              FIDO:   2:5020/209
 *                              E-mail: ig@estar.msk.su
 *
 */

#include "78k_0s.hpp"
/*

00001010 1111R2R1R01          mov r,#byte
11110101 Saddr-offset  Data   mov saddr,#byte
11110111 Sfr-offset Data      mov sfr,#byte
00001010 0010R2R1R0           mov A,r
00001010 1110R2R1R0           mov r,A
00100101 Saddr-offset         mov A,saddr
11100101 Saddr-offset         mov saddr,A
00100111 sfr-offset           mov A,sfr
11100111 sfr-offset           mov sfr,A
00101001 Low High             mov A,!addr16
11101001 Low High             mov !addr16,A
11110101 00011110 Data        mov PSW, #byte
00100101 00011110             mov A,PSW
11100101 00011110             mov PSW,A
00101011                      mov A,[DE]
11101011                      mov [DE],A
00101111                      mov A,[HL]
11101111                      mov [HL],A
00101101 Data                 mov A,[HL+byte]
11101101 Data                 mov [HL+byte],A

11000000                      xch A,X
00001010 0000R2R1R01          xch A,r
00000101 Saddr-offset         xch A,saddr
00000111 Sfr-offset           xch Sfr-offset
00001011                      xch A,[DE]
00001111                      xch A,[HL]
00001101 Data                 xch A,[HL+byte]

1111P1P000 Low High           movw rp,#word
11010110 Saddr-offset         movw AX,Saddr-offset
11100110 Saddr-offset         movw saddr,AX
1101P1P000                    movw AX,rp
1110P1P000                    movw rp,AX

1100P1P000                    xchw AX,rp

10000011 Data                 add A,#byte
10000001 Saddr-offse Data     add saddr,#byte
00001010 1000R2R1R01          add A,r
10000101 Saddr-offset         add A,saddr
10001001 Low High             add A,!addr16
10001111                      add A,[HL]
10001101  Data                add A,[HL+byte]

10100011 Data                 addc A,#byte
10100001 Saddr-offse Data     addc saddr,#byte
00001010 1000R2R1R01          addc A,r
10100101 Saddr-offset         addc A,saddr
10101001 Low High             addc A,!addr16
10101111                      addc A,[HL]
10101101  Data                addc A,[HL+byte]

10010011 Data                 sub A,#byte
10010001 Saddr-offse Data     sub saddr,#byte
00001010 1000R2R1R01          sub A,r
10010101 Saddr-offset         sub A,saddr
10011001 Low High             sub A,!addr16
10011111                      sub A,[HL]
10011101  Data                sub A,[HL+byte]

10110011 Data                 subc A,#byte
10110001 Saddr-offse Data     subc saddr,#byte
00001010 1000R2R1R01          subc A,r
10110101 Saddr-offset         subc A,saddr
10111001 Low High             subc A,!addr16
10111111                      subc A,[HL]
10111101  Data                subc A,[HL+byte]

01100011 Data                 and A,#byte
01100001 Saddr-offse Data     and saddr,#byte
00001010 1000R2R1R01          and A,r
01100101 Saddr-offset         and A,saddr
01101001 Low High             and A,!addr16
01101111                      and A,[HL]
01101101  Data                and A,[HL+byte]

01110011 Data                 or A,#byte
01110001 Saddr-offse Data     or saddr,#byte
00001010 1000R2R1R01          or A,r
01110101 Saddr-offset         or A,saddr
01111001 Low High             or A,!addr16
01111111                      or A,[HL]
01111101  Data                or A,[HL+byte]

01000011 Data                 xor A,#byte
01000001 Saddr-offse Data     xor saddr,#byte
00001010 1000R2R1R01          xor A,r
01000101 Saddr-offset         xor A,saddr
01001001 Low High             xor A,!addr16
01001111                      xor A,[HL]
01001101  Data                xor A,[HL+byte]

00010011 Data                 cmp A,#byte
00010001 Saddr-offse Data     cmp saddr,#byte
00001010 1000R2R1R01          cmp A,r
00010101 Saddr-offset         cmp A,saddr
00011001 Low High             cmp A,!addr16
00011111                      cmp A,[HL]
00011101  Data                cmp A,[HL+byte]

11010010 Low High             addw AX,#word
11000010 Low High             subw AX,#word
11100010 Low High             cmpw AX,#word

00001010 1100R2R1R01          inc r
11000101 Saddr-offset         inc saddr

00001010 1101R2R1R01          dec r
11010101 Saddr-offset         dec saddr

1000P1P000                    incw rp
1001P1P000                    decw rp

00000000                      ror A,1
00010000                      rol A,1
00000010                      rorc A,1
00010010                      rolc A,1

00001010 0B2B1B01010 Saddr-offset    set1 saddr.bit
00001010 0B2B1B00110 Sfr-offset      set1 sfr.bit
00001010 0B2B1B00010                 set1 A.bit
00001010 0B2B1B01010 00011110        set1 PSW.bit
00001010 0B2B1B01110                 set1 [HL].bit

00001010 0B2B1B01010 Saddr-offset    clr1 saddr.bit
00001010 0B2B1B00110 Sfr-offset      clr1 sfr.bit
00001010 0B2B1B00010                 clr1 A.bit
00001010 0B2B1B01010 00011110        clr1 PSW.bit
00001010 0B2B1B01110                 clr1 [HL].bit

00010100                     set1 CY
00000100                     clr1 CY
00000110                     not1 CY

00100010 Low High            call !addr16
01ta40                       callt addr5

00100000                     ret
00100100                     reti

00101110                     push PSW
1010P1P010                   push rp

00101100                     pop PSW
1010P1P000                   pop rp

11100110 00011100           movw SP,AX
11010110 00011100           movw AX,SP

10110010 Low High           br !addr16
00110000 jdisp              br $addr16
10110000                    br AX

00111000 jdisp              bc $addr16

00111010 jdisp              bnc $addr16

00111100 jdisp              bz $addr16

00111110 jdisp              bnz $addr16

00001010 1B2B1B01000 Saddr-offset jdisp   bt saddr.bit,$addr16
00001010 1B2B1B00100 Sfr-offset jdisp     bt sfr.bit,$addr16
00001010 1B2B1B00000 jdisp                bt A.bit,$addr16
00001010 1B2B1B01000 00011110 jdisp       bt PSW.bit,$addr16

00001010 0B2B1B01000 Saddr-offset jdisp   bf saddr.bit,$addr16
00001010 0B2B1B00100 Sfr-offset jdisp     bf sfr.bit,$addr16
00001010 0B2B1B00000 jdisp                bf A.bit,$addr16
00001010 0B2B1B01000 00011110 jdisp       bf PSW.bit,$addr16

00110110 jdisp                dbnz B,$addr16
00110100 jdisp                dbnz C,$addr16
00110010 Saddr-offset jdisp   dbnz saddr,$addr16

00001000                      nop

00001010 01111010 00011110    ei

00001010 11111010 00011110    di

00001100                      halt

00001110                      stop
*/

//Прочитать 2 байта  с указанного адресса
const ulong Get_Addr_Call(uchar Addr )
{
   ulong low = get_byte( Addr+1 );
   ulong high  = get_byte(Addr );
   ulong res = high | (low<<8);

   return res;
}

// Определяем oпреранд CALL
// Заполняем структуру op_t, описывая операнд типа - near
//     Addr - смещение относительно 0х40
//      0x40 - 0x3E
inline void Operand_Call5( op_t &x, ulong Addr)
{
   x.type = o_near;
   x.addr = Get_Addr_Call( 0x40+ Addr );
   ++x.form;
}



//Для операции !addr
inline void Operation_16bits( op_t &x )
{
	x.offb = cmd.size;
	ulong high = ua_next_byte();
	ulong low  = ua_next_byte();
	ulong res = high | (low<<8);

	x.type = o_imm;
	x.value = res;
	x.dtyp  = dt_word;
        ++x.addr16;
}


//Вычитываем 2 байта(данные) и заполняем структуру op_t,
//описывая операнд типа - imm
inline void Data_16bits( op_t &x )
{
   x.offb = cmd.size;
   x.type = o_imm;
   x.value = Get_Data_16bits();
   x.dtyp  = dt_word;
}

const ulong Get_Data_16bits( )
{
   ulong high = ua_next_byte();
   ulong low  = ua_next_byte();
   ulong res = high | (low<<8);
   return res;
}

//Запоняем структуру op_t, описывая операнд типа - near
inline void Near(op_t &x, uchar addr, int del)
{
    x.type = o_near;
    x.addr = cmd.ip + (signed char)addr + del;
    x.offb = cmd.size - 1;
}

//Определяем операнд для SFR(0xFF00 - 0xFFFF)
//Длина адресса 2 байта
//Запоняем структуру op_t, описывая операнд типа - mem
inline void Sfr(op_t &x, uchar addr)
{
	x.type = o_mem;
        x.offb = cmd.size - 1;

	if( (0xFF00+addr)>0xFFFF)
		x.addr = addr ;
        else
		x.addr = 0xFF00+addr ;
}

//Определяем операнд для адресса(0xFE00 - 0xFF1F)
//Длина адресса 2 байта
//Запоняем структуру op_t, описывая операнд типа - mem
inline void Saddr(op_t &x, uchar addr)
{
	if(addr<0x20)
	{
	   Sfr(x, addr);
	   return;
	}

        x.type = o_mem;
        x.offb = cmd.size - 1;
	if( (0xFE00+addr)>0xFF1F)
		x.addr = addr ;
        else
		x.addr = 0xFE00+addr ;
}

//Определяем операнд для адресса(0xFE00 - 0xFF1E)
//Длина адресса 2 байта
//Запоняем структуру op_t, описывая операнд типа - mem
inline void Saddrp(op_t &x, uchar addr)
{
	x.type = o_mem;
        x.offb = cmd.size - 1;

	if( (0xFE00+addr)>0xFF1E)
		x.addr = addr ;
        else
		x.addr = 0xFE00+addr ;
}


//Возвращает значение запрашиваемого бита и байта
inline int GETBIT(uchar Data, int bit)
{
	uchar TempByte;
	TempByte = Data;
	return (((TempByte >> bit) & 0x01));
}


inline void Command_SET1_CLR1( op_t &x, uchar bt, int nib )
{
    x.regmode = SADDR;
    Saddr(x, bt );
    x.type = o_bit;
    x.value = nib & 0x7;
}


//----------------------------------------------------------------------
int ana(void) {


  //получить один байт
  uchar cd, cdEx, code = ua_next_byte();

  if( code == 0x0A)
  {
    //Если первый байт 0x0A
    code = ua_next_byte();

    int SW = GETBIT(code, 0);
    //Проверяем 0 бит в следующем байте
    if(SW==1)
    {
      static uchar code0A[16]=
       {  NEC_78K_0S_xch, NEC_78K_0S_cmp, NEC_78K_0S_mov, 0,
          NEC_78K_0S_xor, 0, NEC_78K_0S_and, NEC_78K_0S_or,
          NEC_78K_0S_add, NEC_78K_0S_sub, NEC_78K_0S_addc, NEC_78K_0S_subc,
          NEC_78K_0S_inc, NEC_78K_0S_dec, NEC_78K_0S_mov, NEC_78K_0S_mov};

       //получаем старшую часть байта
       uchar nib  = (code >> 4) & 0xF;
       cd = code;
       cd &= 0xF;
       cdEx = cd >> 1;


      //00001010 xxxxx смотри дополнительные данные по команде 0x0A
      switch(nib)
       {
         case 0x0:
         case 0x2:
         case 0x8:
         case 0xA:
         case 0x9:
         case 0xB:
         case 0x6:
         case 0x7:
         case 0x4:
         case 0x1:
            cmd.itype = code0A[nib];

            cmd.Op2.type = o_reg;
            cmd.Op2.reg = cdEx;

            cmd.Op1.type = o_reg;
            cmd.Op1.reg = rA;
         break;

        case 0xC:
        case 0xD:
            cmd.itype = code0A[nib];

            cmd.Op1.type = o_reg;
            cmd.Op1.reg = cdEx;
          break;



        case 0xF:
            cmd.itype = code0A[nib];

            cmd.Op2.type = o_imm;
            cmd.Op2.value = ua_next_byte();

            cmd.Op1.type = o_reg;
            cmd.Op1.reg = cdEx;
          break;

        case 0xE:
             cmd.itype = code0A[nib];

             cmd.Op1.type = o_reg;
             cmd.Op1.reg = cdEx;

             cmd.Op2.type = o_reg;
             cmd.Op2.reg = rA;
           break;

       }

     }//end if
    else //0 бит = 0
    {
       //получаем старшую часть байта
       uchar nib  = (code >> 4) & 0xF;
       cd = code;
       cd &= 0xF;

       //У нас при разборе возникает ситуация неправильного интерпритирования
       // 0x7A или 0xFA. 0x7A(0xFA) также встречается в командах set1 and clr1
       if(code == 0xFA || code == 0x7A)
       {
         uchar bt = ua_next_byte();
         if( bt == 0x1E)
         {
	// 00001010 11111010 00011110    di
	// 00001010 01111010 00011110    ei

	 switch(code)
            {
              case 0xFA: cmd.itype = NEC_78K_0S_DI; return( cmd.size );
              case 0x7A: cmd.itype = NEC_78K_0S_EI; return( cmd.size );
            }
         } //предпологаем что это set1 или clr1
         else  if(code == 0x7A)
             {
              cmd.itype = NEC_78K_0S_set1;
              Command_SET1_CLR1( cmd.Op1, bt, nib );
              return( cmd.size);
             }
          else  if(code == 0xFA)
             {
              cmd.itype = NEC_78K_0S_clr1;
              Command_SET1_CLR1( cmd.Op1, bt, nib );
              return( cmd.size);
             }

       }


      //работа с битовыми полями SET1, CLR1, BF, BT
      //проверяем в старшем бите 1
      if(code != 0xFA || cd == 0x6 || cd == 0x2 || cd == 0xE)
      {
         if( GETBIT(code, 7) == 0)//SET1
              cmd.itype = NEC_78K_0S_set1;
          else // CLR1
              cmd.itype = NEC_78K_0S_clr1;


        switch(cd)
         {
          //00001010 1B2B1B00000 jdisp                bt A.bit,$addr16
	      //A.bit, $saddr  0A 10 FC  BT A.0, 0FF10h
          case 0x0:
                cmd.itype = GETBIT(code, 7) ? NEC_78K_0S_bt :  NEC_78K_0S_bf;

                cmd.Op1.type = o_bit;
                cmd.Op1.offb = cmd.size;
                cmd.Op1.regmode = A;
                cmd.Op1.value = nib & 0x07;

		Near( cmd.Op2, ua_next_byte(), 3);
             break;

          case 0x2:
                cmd.Op1.type = o_bit;
                cmd.Op1.offb = cmd.size;
                cmd.Op1.regmode = A;
                cmd.Op1.value = nib & 0x07;
             break;

	 //00001010 1B2B1B00100 Sfr-offset jdisp     bt sfr.bit,$addr16
          case 0x4: //sfr.bit, $addr16    (0A 84 D0 FB)  BT 0FFD0.0, $LOC
                cmd.itype = GETBIT(code, 7) ? NEC_78K_0S_bt :  NEC_78K_0S_bf;

                cmd.Op1.regmode = SFR;
		Sfr( cmd.Op1, ua_next_byte() );
		cmd.Op1.type = o_bit;
                cmd.Op1.value = nib & 0x7;

                Near( cmd.Op2, ua_next_byte(), 4);

             break;


           case 0x6:
                cmd.Op1.regmode = SFR;
		Sfr( cmd.Op1, ua_next_byte() );
		cmd.Op1.type = o_bit;
                cmd.Op1.value = nib & 0x7;

             break;

          //00001010 1B2B1B01000 00011110 jdisp       bt PSW.bit,$addr16
          //saddr.bit, $addr16    (0A 84 D0 FB)  BT 0FFD0.0, $LOC
          //PSW.bit, $addr16      (0A 84 D0 FB)  BT PSW.0, $LOC
          case 0x8:
                {
                 cmd.itype = GETBIT(code, 7) ? NEC_78K_0S_bt :  NEC_78K_0S_bf;
                 uchar tst = ua_next_byte();
                 if(tst == 0x1E)
                    cmd.Op1.regmode = PSW;
                 else
                  {
                    cmd.Op1.regmode = SADDR;
                    Saddr(cmd.Op1,  tst );
                  }

                 cmd.Op1.type = o_bit;
                 cmd.Op1.value = nib & 0x7;

                 Near( cmd.Op2, ua_next_byte(), 4);

                }
             break;


          case 0xA:
                {
                 uchar tst = ua_next_byte();
                 if(tst == 0x1E)
                      cmd.Op1.regmode = PSW;
		 else
	         {
		   cmd.Op1.regmode = SADDR;
		   Saddr(cmd.Op1,  tst );
	         }

		cmd.Op1.type = o_bit;
		cmd.Op1.value = nib & 0x7;
               }
             break;

           case 0xE:
               {
                cmd.Op1.type = o_bit;
                cmd.Op1.offb = cmd.size;
                cmd.Op1.regmode = HL;
                cmd.Op1.value = nib & 0x07;
               }
             break;

         }//end switch
      }//
    }//end else


    return( cmd.size);

   }


  //получаем старшую часть байта
  uchar nibble  = (code >> 4) & 0xF;
  cd = code;
  cd &= 0xF;

  //проверяем на "интерестные" байты
   if( (nibble>>2) == 0x1 )
   {
         cmd.itype = NEC_78K_0S_callt;
         Operand_Call5(cmd.Op1, code & 0x3E );
         return (cmd.size);
   }

   if(nibble == 0x08)
   {
        //incw rp
        cmd.itype = NEC_78K_0S_incw;

        cmd.Op1.type = o_reg;
        cmd.Op1.reg = rAX + (cd>>2);
   }

   if(nibble == 0x09)
   {
        //incw rp
        cmd.itype = NEC_78K_0S_decw;

        cmd.Op1.type = o_reg;
        cmd.Op1.reg = rAX + (cd>>2);
   }

   if(nibble == 0x0F)
   {
     if(code != 0xF5 && code != 0xF7)
     {
        //movw rp, #word
        cmd.itype = NEC_78K_0S_movw;

        cmd.Op1.type = o_reg;
        cmd.Op1.reg = rAX + (cd>>2);

        Data_16bits(	cmd.Op2 );

     }
   }


   if(nibble == 0x0D)
   {
     if(code != 0xD6 && code !=0xD5)
     {
        //movw AX, rp
        cmd.itype = NEC_78K_0S_movw;

        cmd.Op1.type = o_reg;
        cmd.Op1.reg = rAX;
        cmd.Op1.dtyp = dt_word;

        cmd.Op2.type = o_reg;
        cmd.Op2.reg = rAX + (cd>>2);
        cmd.Op2.dtyp = dt_word;
     }
   }

   //
   if(nibble == 0x0E && ((cd & 0x03)==0))
   {
        //movw rp, AX
        cmd.itype = NEC_78K_0S_movw;

        cmd.Op2.type = o_reg;
        cmd.Op2.reg = rAX;
        cmd.Op2.dtyp = dt_word;

        cmd.Op1.type = o_reg;
        cmd.Op1.reg = rAX + (cd>>2);
        cmd.Op1.dtyp = dt_word;

   }

   if(nibble == 0xC)
   {
     if(code != 0xC0 && code != 0xC2 && code != 0xC5)
     {
        //xchw AX, rp
        cmd.itype = NEC_78K_0S_xchw;

        cmd.Op1.type = o_reg;
        cmd.Op1.reg = rAX;

        cmd.Op2.type = o_reg;
        cmd.Op2.reg = rAX + (cd>>2);
     }
   }


  // 8-bit Operation Instruction
  static uchar icode[15]={ 0, NEC_78K_0S_cmp,0, 0, NEC_78K_0S_xor,0, NEC_78K_0S_and,  NEC_78K_0S_or,
                          NEC_78K_0S_add, NEC_78K_0S_sub, NEC_78K_0S_addc, NEC_78K_0S_subc,
                          NEC_78K_0S_subw, NEC_78K_0S_addw, NEC_78K_0S_cmpw};



  switch(code)
  {
	  //10000001 Saddr-offse Data     add saddr,#byte
	  //10100001 Saddr-offse Data     addc saddr,#byte
	  //10010001 Saddr-offse Data     sub saddr,#byte
	  //10110001 Saddr-offse Data     subc saddr,#byte
	  //01100001 Saddr-offse Data     and saddr,#byte
	  //01110001 Saddr-offse Data     or saddr,#byte
	  //01000001 Saddr-offse Data     xor saddr,#byte
	  //00010001 Saddr-offse Data     cmp saddr,#byte
	  case 0x11:
	  case 0x41:
	  case 0x61:
	  case 0x71:
	  case 0x81:
	  case 0x91:
	  case 0xA1:
	  case 0xB1:
         // saadr,#byte
         cmd.itype = icode[nibble];

	 Saddr(cmd.Op1, ua_next_byte());

         cmd.Op2.type = o_imm;
         cmd.Op2.value = ua_next_byte();

        break;

	//10000011 Data                 add A,#byte
	//10100011 Data                 addc A,#byte
	//10010011 Data                 sub A,#byte
	//10110011 Data                 subc A,#byte
	//01100011 Data                 and A,#byte
	//01110011 Data                 or A,#byte
	//01000011 Data                 xor A,#byte
	//00010011 Data                 cmp A,#byte
	 case 0x13:
	 case 0x43:
	 case 0x63:
	 case 0x73:
	 case 0x83:
	 case 0x93:
	 case 0xA3:
	 case 0xB3:
         //A,#byte;
         cmd.itype = icode[nibble];

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;


         cmd.Op2.type = o_imm;
         cmd.Op2.value = ua_next_byte();

        break;

	//10000101 Saddr-offset         add A,saddr
	//10100101 Saddr-offset         addc A,saddr
	//10010101 Saddr-offset         sub A,saddr
	//10110101 Saddr-offset         subc A,saddr
	//01100101 Saddr-offset         and A,saddr
	//01110101 Saddr-offset         or A,saddr
	//01000101 Saddr-offset         xor A,saddr
	//00010101 Saddr-offset         cmp A,saddr
	case 0x15:
	case 0x45:
        case 0x65:
        case 0x75:
        case 0x85:
        case 0x95:
        case 0xA5:
        case 0xB5:
         // A, saddr
         cmd.itype = icode[nibble];
	     cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

		 Saddr( cmd.Op2, ua_next_byte() );
        break;

	//10001001 Low High             add A,!addr16
	//10101001 Low High             addc A,!addr16
	//10011001 Low High             sub A,!addr16
	//10111001 Low High             subc A,!addr16
	//01101001 Low High             and A,!addr16
	//01111001 Low High             or A,!addr16
	//01001001 Low High             xor A,!addr16
	//00011001 Low High             cmp A,!addr16
       case 0x19:
       case 0x49:
       case 0x69:
       case 0x79:
       case 0x89:
       case 0x99:
       case 0xA9:
       case 0xB9:
         // A, !saddr16
         cmd.itype = icode[nibble];
	 cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         Operation_16bits(cmd.Op2);
         //cmd.Op2.offb = cmd.size;
         //cmd.Op2.addr = ua_next_word();
         //cmd.Op2.type = o_mem;
         //cmd.Op2.addr16 = 1;
        break;

	//10001111                      add A,[HL]
	//10101111                      addc A,[HL]
	//10011111                      sub A,[HL]
	//10111111                      subc A,[HL]
	//01101111                      and A,[HL]
	//01111111                      or A,[HL]
	//01001111                      xor A,[HL]
	//00011111                      cmp A,[HL]
       case 0x1F:
       case 0x4F:
       case 0x6F:
       case 0x7F:
       case 0x8F:
       case 0x9F:
       case 0xAF:
       case 0xBF:
         // A, [HL]
         cmd.itype = icode[nibble];
	 cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rHL;
         ++cmd.Op2.prepost;
        break;

	//10001101  Data                add A,[HL+byte]
	//10101101  Data                addc A,[HL+byte]
	//10011101  Data                sub A,[HL+byte]
	//10111101  Data                subc A,[HL+byte]
	//01101101  Data                and A,[HL+byte]
	//01111101  Data                or A,[HL+byte]
	//01001101  Data                xor A,[HL+byte]
	//00011101  Data                cmp A,[HL+byte]
        case 0x1D:
        case 0x4D:
        case 0x6D:
        case 0x7D:
        case 0x8D:
        case 0x9D:
        case 0xAD:
        case 0xBD:
         // A, [HL+#byte]
         cmd.itype = icode[nibble];
	 cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rHL;
         cmd.Op2.addr = ua_next_byte();
         ++cmd.Op2.prepost;
         ++cmd.Op2.xmode;

        break;
  }

  // 16-bit Operation Instruction
  //11010010 Low High             addw AX,#word
  //11000010 Low High             subw AX,#word
  //11100010 Low High             cmpw AX,#word
   switch(code)
   {
    case 0xE2:
    case 0xD2:
    case 0xC2:
         // AX,#word
         cmd.itype = icode[ nibble ];

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rAX;

         Data_16bits( cmd.Op2 );
         break;

   }

  // Incriment/Decriment Instruction
  static uchar idcode[2]={ NEC_78K_0S_inc, NEC_78K_0S_dec};

  //11010101 Saddr-offset         dec saddr
  //11000101 Saddr-offset         inc saddr
   switch(code)
   {
    case 0xD5:
    case 0xC5:
         // saddr
         cmd.itype = idcode[ nibble & 0x1 ];
         Saddr( cmd.Op1, ua_next_byte() );
         return( cmd.size );
   }

 //Rotate Instructions
   //00000000                      ror A,1
   //00010000                      rol A,1
   //00000010                      rorc A,1
   //00010010                      rolc A,1
    switch(code)
   {
    case 0x0:
         //ror A,1
         cmd.itype = NEC_78K_0S_ror;
         goto mem;

    case 0x10:
         // rol A,1
         cmd.itype = NEC_78K_0S_rol;
         goto mem;

    case 0x2:
         // rorc A,1
         cmd.itype = NEC_78K_0S_rorc;
         goto mem;

    case 0x12:
         // rolc A,1
         cmd.itype = NEC_78K_0S_rolc;

mem:
         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_imm;
         cmd.Op2.value = 1;
       break;
   }


  switch(code)
  {
    //00100010 Low High            call !addr16
    case 0x22:
         // call
         cmd.itype = NEC_78K_0S_call;
         cmd.Op1.offb = cmd.size;
         cmd.Op1.type = o_near;
         cmd.Op1.addr = Get_Data_16bits();


       break;

    //00100000                     ret
    case 0x20:
         // ret
         cmd.itype = NEC_78K_0S_ret;
       break;

    //00100100                     reti
    case 0x24:
         // reti
         cmd.itype = NEC_78K_0S_reti;
       break;
  }


  switch(code)
  {
    //00010100                     set1 CY
    case 0x14:
         // set1 CY
         cmd.itype = NEC_78K_0S_set1;
         cmd.Op1.type = o_phrase;
         cmd.Op1.reg = bCY;


       break;

    //00000100                     clr1 CY
    case 0x04:
         // clr1 CY
         cmd.itype = NEC_78K_0S_clr1;
         cmd.Op1.type = o_phrase;
         cmd.Op1.reg = bCY;

       break;

    //00000110                     not1 CY
    case 0x06:
         // not1 CY
         cmd.itype = NEC_78K_0S_not1;
         cmd.Op1.type = o_phrase;
         cmd.Op1.reg = bCY;

       break;
  }


  switch(code)
  {
    //00101110                     push PSW
    case 0x2E:
          // push PSW
          cmd.itype = NEC_78K_0S_push;

          cmd.Op1.type = o_phrase;
          cmd.Op1.reg = rPSW;
        break;

    //00101100                     pop PSW
    case 0x2C:
          // pop PSW
          cmd.itype = NEC_78K_0S_pop;

          cmd.Op1.type = o_phrase;
          cmd.Op1.reg = rPSW;

         break;




    case 0xE6:
          {
      	    //11100110 00011100           movw SP,AX
            cmd.itype = NEC_78K_0S_movw;

            uchar tst =  ua_next_byte();
            if(tst == 0x1C)
            {
             // movw SP,AX
             cmd.Op1.type = o_reg;
             cmd.Op1.reg = rSP;
             cmd.Op1.dtyp = dt_word;

             cmd.Op2.type = o_reg;
             cmd.Op2.reg = rAX;
             cmd.Op2.dtyp = dt_word;
            }
            else
            {
             // movw saddrrp,AX
             cmd.Op2.type = o_reg;
             cmd.Op2.reg = rAX;
             cmd.Op2.dtyp = dt_word;

	     Saddr(cmd.Op1, tst );
             cmd.Op1.dtyp = dt_word;
            }
          }
         break;


    case 0xD6:
         {
           cmd.itype = NEC_78K_0S_movw;

          uchar tst =  ua_next_byte();
          if(tst == 0x1C)
          {
            //11010110 00011100           movw AX,SP
            // movw AX,SP
            cmd.Op2.type = o_reg;
            cmd.Op2.reg = rSP;
            cmd.Op2.dtyp = dt_word;

            cmd.Op1.type = o_reg;
            cmd.Op1.reg = rAX;
            cmd.Op1.dtyp = dt_word;
           }
           else
           {
            // movw AX,saddrp
            cmd.Op1.type = o_reg;
            cmd.Op1.reg = rAX;
            cmd.Op1.dtyp = dt_word;

	    Saddrp(cmd.Op2, tst );
            cmd.Op2.dtyp = dt_word;
           }
         }
         break;

     //00001100                      halt
     case 0xE:
          // STOP
          cmd.itype = NEC_78K_0S_STOP;
         break;

     //00001100                      halt
     case 0xC:
          // HALT
          cmd.itype = NEC_78K_0S_HALT;
         break;

     //00001000                      nop
     case 0x08:
          // nop
          cmd.itype = NEC_78K_0S_nop;
         break;


     //00110010 Saddr-offset jdisp   dbnz saddr,$addr16
     case 0x32:
         // dbnz saddr,$addr
         cmd.itype = NEC_78K_0S_dbnz;

         //cmd.Op1.type = o_mem;
         // cmd.Op1.value = ua_next_byte();

	 Saddr(cmd.Op1, ua_next_byte());

	 Near(cmd.Op2, ua_next_byte(), 3 );

        break;


     //00110100 jdisp                dbnz C,$addr16
     case 0x34:
         //dbnzC,$addr
         cmd.itype = NEC_78K_0S_dbnz;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rC;

	 Near( cmd.Op2, ua_next_byte(), 2);
        break;

     //00110110 jdisp                dbnz B,$addr16
     case 0x36:
         //dbnz B,$addr
         cmd.itype = NEC_78K_0S_dbnz;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rB;

	 Near( cmd.Op2, ua_next_byte(), 2);
        break;

     //00111000 jdisp              bc $addr16
     case 0x38:
         //bc $addr16
         cmd.itype = NEC_78K_0S_bc;

	 Near( cmd.Op1, ua_next_byte(), 2);
        break;

     //00111010 jdisp              bnc $addr16
     case 0x3A:
         //bnc $addr16
         cmd.itype = NEC_78K_0S_bnc;

	 Near( cmd.Op1, ua_next_byte(), 2);
        break;


     //00111100 jdisp              bz $addr16
     case 0x3C:
         //bz $addr16
         cmd.itype = NEC_78K_0S_bz;

	 Near( cmd.Op1, ua_next_byte(), 2);
        break;


     //00111110 jdisp              bnz $addr16
     case 0x3E:
         //bnz $addr16
         cmd.itype = NEC_78K_0S_bnz;

	 Near( cmd.Op1, ua_next_byte(), 2);
        break;


    //00110000 jdisp              br $addr16
     case 0xB2:
         //br !addr16
         cmd.itype = NEC_78K_0S_br;

         cmd.Op1.offb = cmd.size;
         cmd.Op1.addr = Get_Data_16bits();
         cmd.Op1.type = o_mem;
         cmd.Op1.addr16 = 1;
        break;


     //00110000 jdisp              br $addr16
     case 0x30:
         //br $addr16
         cmd.itype = NEC_78K_0S_br;

	 Near( cmd.Op1, ua_next_byte(), 2);
        break;


     //10110000                    br AX
     case 0xB0:
         //br AX
         cmd.itype = NEC_78K_0S_br;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rAX;
        break;

    //MOV
     case 0xF5:
        {
  	 //00001010 1111R2R1R01          mov r,#byte
         //  mov saddr,#byte
         cmd.itype = NEC_78K_0S_mov;

         uchar tst = ua_next_byte();
         if(tst != 0x1E)
          {
	    Saddr(cmd.Op1, tst);
          }
          else
          {
            cmd.Op1.type = o_reg;
            cmd.Op1.reg = rPSW;
          }


         cmd.Op2.type = o_imm;
         cmd.Op2.offb = cmd.size;
         cmd.Op2.value = ua_next_byte();
        }
        break;

     case 0xF7:
	 //11110111 Sfr-offset Data      mov sfr,#byte
         //mov sfr,#byte
         cmd.itype = NEC_78K_0S_mov;

	 Sfr( cmd.Op1, ua_next_byte() );

         cmd.Op2.type = o_imm;
         cmd.Op2.offb = cmd.size;
         cmd.Op2.value = ua_next_byte();
        break;

     case 0x25:
         {
	 //00100101 Saddr-offset         mov A,saddr
         //mov A,saddr
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         uchar tst = ua_next_byte();
         if(tst == 0x1E)
         {
           cmd.Op2.type = o_reg;
           cmd.Op2.reg = rPSW;
         }
         else
	  Saddr(cmd.Op2, tst);

         }
        break;

     case 0xE5:
        {
	 //11100101 Saddr-offset         mov saddr,A
         //mov saddr,A
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rA;

         uchar tst = ua_next_byte();
         if(tst == 0x1E)
          {
           cmd.Op1.type = o_reg;
           cmd.Op1.reg = rPSW;
          }
         else
          {
           cmd.Op1.type = o_mem;
           cmd.Op1.addr = tst;
           cmd.Op1.offb = cmd.size;
          }
         }
        break;


     case 0x27:
	 //00100111 sfr-offset           mov A,sfr
         //mov A,sfr
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_mem;
         cmd.Op2.offb = cmd.size;
         cmd.Op2.addr = ua_next_byte();
        break;

      case 0xE7:
	 //11100111 sfr-offset           mov sfr,A
         //mov sfr,A
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rA;

         Sfr( cmd.Op1,  ua_next_byte());
        break;

     case 0x29:
	 //
         //movx A,!saddr
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

	 Data_16bits( cmd.Op2 );
        break;

     case 0xE9:
	 //11101001 Low High             mov !addr16,A
         //mov !saddr,A
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rA;

	 Data_16bits( cmd.Op1 );
        break;



     case 0x2B:
	 //00101011                      mov A,[DE]
         //mov A,[DE]
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rDE;
         ++cmd.Op2.prepost;
       break;



     case 0xEB:
	 //11101011                      mov [DE],A
         //mov [DE], A
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rA;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rDE;
         ++cmd.Op1.prepost;
       break;



     case 0x2F:
	 //00101111                      mov A,[HL]
         //mov A,[HL]
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;


         cmd.Op2.type = o_reg;
	 cmd.Op2.reg = rHL;
         ++cmd.Op2.prepost;

       break;


     case 0xEF:
	 //11101111                      mov [HL],A
         //mov [HL],A
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rA;

	 cmd.Op1.type = o_reg;
	 cmd.Op1.reg = rHL;
         ++cmd.Op1.prepost;

       break;

     case 0x2D:
	 //00101101 Data                 mov A,[HL+byte]
         //mov A,[HL+byte]
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rHL;
	 cmd.Op2.addr = ua_next_byte();
         ++cmd.Op2.prepost;
         ++cmd.Op2.xmode;
       break;


     case 0xED:
	 //11101101 Data                 mov [HL+byte],A
         //mov [HL+byte],A
         cmd.itype = NEC_78K_0S_mov;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rA;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rHL;
	 cmd.Op1.value = ua_next_byte();
         ++cmd.Op1.prepost;
         ++cmd.Op1.xmode;

       break;

    //XCH
     case 0xC0:
	 //11000000                      xch A,X
         //xch A,X
         cmd.itype = NEC_78K_0S_xch;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rX;
       break;

     case 0x05:
	 //00000101 Saddr-offset         xch A,saddr
         //xch A,saddr
         cmd.itype = NEC_78K_0S_xch;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

	 Saddr(cmd.Op2, ua_next_byte() );
       break;


     case 0x07:
	 //00000111 Sfr-offset           xch Sfr-offset
         //xch A,sfr
         cmd.itype = NEC_78K_0S_xch;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_mem;
         cmd.Op2.offb = cmd.size;
         cmd.Op2.addr = ua_next_byte();
       break;



     case 0x0B:
	 //00001011                      xch A,[DE]
         //xch A,[DE]
         cmd.itype = NEC_78K_0S_xch;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rDE;
         ++cmd.Op2.prepost;
       break;

     case 0x0F:
	 //00001111                      xch A,[HL]
         //xch A,[HL]
         cmd.itype = NEC_78K_0S_xch;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rHL;
         ++cmd.Op2.prepost;
       break;


     case 0x0D:
	 //
         //xch A,[HL+#byte]
         cmd.itype = NEC_78K_0S_xch;

         cmd.Op1.type = o_reg;
         cmd.Op1.reg = rA;

         cmd.Op2.type = o_reg;
         cmd.Op2.reg = rHL;
         cmd.Op2.addr = ua_next_byte();
         ++cmd.Op2.prepost;
         ++cmd.Op2.xmode;
       break;

     }


     switch(code)
     {
       //pop
       case 0xA0:
       case 0xA4:
       case 0xA8:
       case 0xAC:
            cmd.itype = NEC_78K_0S_pop;
            goto frase;

       //push
       case 0xA2:
       case 0xA6:
       case 0xAA:
       case 0xAE:
            cmd.itype = NEC_78K_0S_push;
frase:

        cmd.Op1.type = o_reg;
        cmd.Op1.reg = rAX + (cd>>2);
          break;

     }

  return( cmd.size );

}
