/************************************************************************

         D-code Disassembler V1.0 - special opcode handler
         -------------------------------------------------

Author : David Allison
Issue  : 1.0
Date   : 11 August 1987

(C) 1987 Beebug Limited

This file contains the second part of the D-code disassembler.  The first file
is called C.DASM.

***************************************************************************/

# include <h.stdio>

/* only need unsigned int and bitfield */

# define UINT 1
# define BIT_FIELD 6

extern int get_byte (void) ;     /* is c.dasm, get a byte */

struct op_list
   {
   unsigned short opcode ;
   char *string ;
   unsigned short num_bytes ;
   } ;


/* this is the main function.  It disassembles one opcode.  All those opcodes
   whose 'num_bytes' field is 255 are handled here */

disassemble_special(struct op_list *code)
   {
   switch (code -> opcode)
      {
      case 0xe4 :
      case 0xe5 :
      case 0xe6 :
      case 0xec :
      case 0xea :
      case 0xfb :
      case 0xe2 : read_symbol() ;
                  break ;
      case 0xe1 : def_bytes() ;
                  break ;
      case 0x80 : read_name() ;
                  break ;
      case 0x83 : reset_line_func() ;
                  break ;
      case 0xeb : load_mem() ;
                  break ;
      case 0xa0 :
      case 0xa3 :
      case 0xd0 :
      case 0xd3 : inc_dec() ;
                  break ;
      case 0xf8 : dasm_call() ;
                  break ;
      case 0xe9 : switch_list() ;
                  break ;
      case 0x8a : def_stat_offset() ;
                  break ;
      case 0x8b : read_symbol() ;
      }
   }


/* read a symbol from the input file */

read_symbol(void)
   {
   int type ;
            
   switch (type=get_byte())             /* get the symbol type */ 
      {
      case 2 : read_external() ;        /* external */
               break ;
      case 1 : read_static() ;          /* static symbol */
               break ;
      case 4 : read_internal() ;        /* internal */
               break ;
      case 3 : read_func_stat() ;       /* funcion static symbol */
               break ;
      case 0xd8 : read_label() ;        /* label */
                  break ;
      default : fprintf (stderr,"\nUnknown symbol type %d\n",type) ;
      }
   }

/* output the next byte from the file in hex */

out_byte(void)
   {
   unsigned short i ;

   i = get_byte() ;
   printf ("%02X ",i & 0xff) ;
   }

read_name(void)
   {
   int i ;
   putchar ('"') ;
   while ((i=get_byte()) != '\r')
      putchar (i) ;
   putchar ('"') ;
   }

read_external(void)
   {
   printf ("external  ") ;
   read_name() ;
   }

read_static(void)
   {
   printf ("static  ") ;
   read_name() ;
   }

read_internal(void)
   {
   int lo,hi ;

   printf ("internal  ") ;
   lo = get_byte() ;
   hi = get_byte() ;
   printf (" %X",hi * 256 + lo) ;
   }

read_label(void)
   {
   int lo,hi ;

   printf ("label  ") ;
   lo = get_byte() ;
   hi = get_byte() ;
   printf (" %X",hi * 256 + lo) ;
   read_name() ;
   }

read_func_stat(void)
   {
   int lo,hi ;

   printf ("int-static  ") ;
   lo = get_byte() ;
   hi = get_byte() ;
   printf (" %X",hi * 256 + lo) ;
   putchar (' ') ;
   out_byte() ;
   out_byte() ;
   }

def_bytes(void)
   {
   int lo,hi,num ;
   
   lo = get_byte() ;
   hi = get_byte() ;
   num = hi*256+lo ;
   for (lo=0 ; lo < num ; lo++)
      out_byte() ;
   }

reset_line_func(void)
   {
   read_symbol() ;
   putchar (' ') ;
   out_byte() ;
   out_byte();
   }
 

load_mem(void)
   {
   unsigned short i ;
          
   print_type (i = get_byte()) ;
   if (i==BIT_FIELD)
      {
      out_byte() ;
      out_byte();
      }
   read_symbol() ;
   }

inc_dec(void)
   {
   unsigned short i ;
          
   print_type (i = get_byte()) ;
   if (i==UINT)
      {
      out_byte() ;
      out_byte();
      }
   }

dasm_call(void)
   {
   out_byte() ;
   read_symbol() ;
   }

switch_list(void)
   {
   out_byte() ;
   out_byte() ;
   read_symbol() ;
   }

def_stat_offset(void)
   {
   read_symbol() ;
   putchar (' ') ;
   out_byte() ;
   out_byte() ;
   }


