1050 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1050 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
static char *sccsid =
 | 
						||
   "@(#) dishand.c, Ver. 2.1 created 00:00:00 87/09/01";
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  *  Copyright (C) 1987 G. M. Harding, all rights reserved  *
 | 
						||
  *                                                         *
 | 
						||
  * Permission to copy and  redistribute is hereby granted, *
 | 
						||
  * provided full source code,  with all copyright notices, *
 | 
						||
  * accompanies any redistribution.                         *
 | 
						||
  *                                                         *
 | 
						||
  * This file contains the source code for most of the spe- *
 | 
						||
  * cialized handler routines of the disassembler  program. *
 | 
						||
  * (The file disfp.c contains handler routines specific to *
 | 
						||
  * the 8087 numeric  co-processor.)  Each handler  routine *
 | 
						||
  * interprets the opcode byte  (and subsequent data bytes, *
 | 
						||
  * if any)  of a particular family of opcodes,  and is re- *
 | 
						||
  * sponsible for generating appropriate output. All of the *
 | 
						||
  * code in this file is highly MACHINE-SPECIFIC, and would *
 | 
						||
  * have to be rewritten for a different  CPU.  The handler *
 | 
						||
  * routines are accessed  only via pointers in the optab[] *
 | 
						||
  * array, however, so machine dependencies are confined to *
 | 
						||
  * this file, its sister file "disfp.c", and the data file *
 | 
						||
  * "distabs.c".                                            *
 | 
						||
  *                                                         *
 | 
						||
  * All of the code in this file is based on the assumption *
 | 
						||
  * of sixteen-bit integers.                                *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
#include "dis.h"              /* Disassembler declarations  */
 | 
						||
 | 
						||
int segflg;                   /* Segment-override flag      */
 | 
						||
 | 
						||
unsigned char objbuf[OBJMAX]; /* Buffer for object code     */
 | 
						||
 | 
						||
int objptr;                   /* Index into objbuf[]        */
 | 
						||
 | 
						||
unsigned long PC;             /* Current program counter    */
 | 
						||
 | 
						||
 /* * * * * *  MISCELLANEOUS SUPPORTING ROUTINES  * * * * * */
 | 
						||
 | 
						||
 | 
						||
void
 | 
						||
objini(j)                     /* Object code init routine   */
 | 
						||
 | 
						||
   register int j;
 | 
						||
 | 
						||
{
 | 
						||
   if ((segflg == 1) || (segflg == 2))
 | 
						||
      segflg *= 3;
 | 
						||
   else
 | 
						||
      segflg = 0;
 | 
						||
   objptr = 0;
 | 
						||
   objbuf[objptr++] = (unsigned char)(j);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void
 | 
						||
objout()                      /* Object-code output routine */
 | 
						||
 | 
						||
{
 | 
						||
    register int k;
 | 
						||
 | 
						||
   if ( ! objflg )
 | 
						||
      return;
 | 
						||
   else
 | 
						||
      {
 | 
						||
      printf("\t|");
 | 
						||
      if (symptr >= 0)
 | 
						||
         printf(" %05.5lx:",(PC + 1L - (long)(objptr)));
 | 
						||
      for (k = 0; k < objptr; ++k)
 | 
						||
         printf(" %02.2x",objbuf[k]);
 | 
						||
      putchar('\n');
 | 
						||
      }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void
 | 
						||
badseq(j,k)                   /* Invalid-sequence routine   */
 | 
						||
 | 
						||
   register int j, k;
 | 
						||
 | 
						||
{
 | 
						||
   printf("\t.byte\t0x%02.2x\t\t| invalid code sequence\n",j);
 | 
						||
   printf("\t.byte\t0x%02.2x\n",k);
 | 
						||
}
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This  routine  is the first of several  opcode-specific *
 | 
						||
  * handlers,  each of which is  dedicated  to a particular *
 | 
						||
  * opcode family.  A pointer to a handler  routine is con- *
 | 
						||
  * tained in the second field of each optab[]  entry.  The *
 | 
						||
  * dfhand()  routine is the default handler,  invoked when *
 | 
						||
  * no other handler is appropriate (generally, when an in- *
 | 
						||
  * valid opcode is encountered).                           *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
dfhand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF dfhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   segflg = 0;
 | 
						||
 | 
						||
   printf("\t.byte\t0x%02.2x",j);
 | 
						||
 | 
						||
   if (optab[j].min || optab[j].max)
 | 
						||
      putchar('\n');
 | 
						||
   else
 | 
						||
      printf("\t\t| unimplemented opcode\n");
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF dfhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the  single-byte  handler,  invoked  whenever a *
 | 
						||
  * one-byte opcode is encountered.                         *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
sbhand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF sbhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   if (j == 0x2e)                               /* seg cs   */
 | 
						||
      segflg = 1;
 | 
						||
 | 
						||
   if ((j == 0x26)                              /* seg es   */
 | 
						||
    || (j == 0x36)                              /* seg ss   */
 | 
						||
    || (j == 0x3e))                             /* seg ds   */
 | 
						||
      segflg = 2;
 | 
						||
 | 
						||
   printf("%s\n",optab[j].text);
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF sbhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for most of the processor's regular *
 | 
						||
  * arithmetic operations.                                  *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
aohand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF aohand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int k;
 | 
						||
   int m, n;
 | 
						||
   char b[64];
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   switch (j & 7)
 | 
						||
      {
 | 
						||
      case 0 :
 | 
						||
      case 1 :
 | 
						||
      case 2 :
 | 
						||
      case 3 :
 | 
						||
         printf("%s\t",optab[j].text);
 | 
						||
         FETCH(k);
 | 
						||
         printf("%s\n",mtrans(j,k,TR_STD));
 | 
						||
         break;
 | 
						||
      case 4 :
 | 
						||
         FETCH(k);
 | 
						||
         printf("%s\tal,*0x%02.2x\n",optab[j].text,k);
 | 
						||
         break;
 | 
						||
      case 5 :
 | 
						||
         FETCH(m);
 | 
						||
         FETCH(n);
 | 
						||
         k = (n << 8) | m;
 | 
						||
         if (lookext((long)(k),(PC - 1),b))
 | 
						||
            printf("%s\tax,#%s\n",optab[j].text,b);
 | 
						||
         else
 | 
						||
            printf("%s\tax,#0x%04.4x\n",optab[j].text,k);
 | 
						||
         break;
 | 
						||
      default :
 | 
						||
         dfhand(j);
 | 
						||
         break;
 | 
						||
      }
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF aohand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the  handler for opcodes  which  perform  short *
 | 
						||
  * (eight-bit) relative jumps.                             *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
sjhand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF sjhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int k;
 | 
						||
   int m;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(m);
 | 
						||
 | 
						||
   if (m & 0x80)
 | 
						||
      k = 0xff00;
 | 
						||
   else
 | 
						||
      k = 0;
 | 
						||
 | 
						||
   k |= m;
 | 
						||
 | 
						||
   printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text,
 | 
						||
    lookup((PC + k + 1L),N_TEXT,LOOK_REL,-1L),
 | 
						||
    (PC + k + 1L));
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF sjhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the  handler for a  loosely-knit  family of op- *
 | 
						||
  * codes which perform  arithmetic and logical operations, *
 | 
						||
  * and which take immediate  data.  The routine's logic is *
 | 
						||
  * rather complex,  so,  in an effort to avoid  additional *
 | 
						||
  * complexity,  the search for external  references in the *
 | 
						||
  * relocation table has been dispensed with. Eager hackers *
 | 
						||
  * can try their hand at coding such a search.             *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
imhand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF imhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   unsigned long pc;
 | 
						||
   register int k;
 | 
						||
   int offset, oflag, immed, iflag, mod, opi, w, rm;
 | 
						||
   int m, n;
 | 
						||
   static char a[100], b[30];
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   pc = PC + 1;
 | 
						||
 | 
						||
   offset = 0;
 | 
						||
   mod = (k & 0xc0) >> 6;
 | 
						||
   opi = (k & 0x38) >> 3;
 | 
						||
   w = j & 1;
 | 
						||
   rm = k & 7;
 | 
						||
 | 
						||
   if ((j & 2)
 | 
						||
    && ((opi == 1)
 | 
						||
     || (opi == 4)
 | 
						||
     || (opi == 6)))
 | 
						||
      {
 | 
						||
      badseq(j,k);
 | 
						||
      return;
 | 
						||
      }
 | 
						||
 | 
						||
   strcpy(a,OPFAM[opi]);
 | 
						||
 | 
						||
   if ( ! w )
 | 
						||
      strcat(a,"b");
 | 
						||
 | 
						||
   if ((oflag = mod) > 2)
 | 
						||
      oflag = 0;
 | 
						||
 | 
						||
   if ((mod == 0) && (rm == 6))
 | 
						||
      {
 | 
						||
      FETCH(m);
 | 
						||
      FETCH(n);
 | 
						||
      offset = (n << 8) | m;
 | 
						||
      }
 | 
						||
   else if (oflag)
 | 
						||
      if (oflag == 2)
 | 
						||
         {
 | 
						||
         FETCH(m);
 | 
						||
         FETCH(n);
 | 
						||
         offset = (n << 8) | m;
 | 
						||
         }
 | 
						||
      else
 | 
						||
         {
 | 
						||
         FETCH(m);
 | 
						||
         if (m & 0x80)
 | 
						||
            n = 0xff00;
 | 
						||
         else
 | 
						||
            n = 0;
 | 
						||
         offset = n | m;
 | 
						||
         }
 | 
						||
 | 
						||
   switch (j & 3)
 | 
						||
      {
 | 
						||
      case 0 :
 | 
						||
      case 2 :
 | 
						||
         FETCH(immed);
 | 
						||
         iflag = 0;
 | 
						||
         break;
 | 
						||
      case 1 :
 | 
						||
         FETCH(m);
 | 
						||
         FETCH(n);
 | 
						||
         immed = (n << 8) | m;
 | 
						||
         iflag = 1;
 | 
						||
         break;
 | 
						||
      case 3 :
 | 
						||
         FETCH(immed);
 | 
						||
         if (immed & 0x80)
 | 
						||
            immed &= 0xff00;
 | 
						||
         iflag = 0;
 | 
						||
         break;
 | 
						||
      }
 | 
						||
 | 
						||
   strcat(a,"\t");
 | 
						||
 | 
						||
   switch (mod)
 | 
						||
      {
 | 
						||
      case 0 :
 | 
						||
         if (rm == 6)
 | 
						||
            strcat(a,
 | 
						||
             lookup((long)(offset),N_DATA,LOOK_ABS,pc));
 | 
						||
         else
 | 
						||
            {
 | 
						||
            sprintf(b,"(%s)",REGS0[rm]);
 | 
						||
            strcat(a,b);
 | 
						||
            }
 | 
						||
         break;
 | 
						||
      case 1 :
 | 
						||
      case 2 :
 | 
						||
         if (mod == 1)
 | 
						||
            strcat(a,"*");
 | 
						||
         else
 | 
						||
            strcat(a,"#");
 | 
						||
         sprintf(b,"%d(",offset);
 | 
						||
         strcat(a,b);
 | 
						||
         strcat(a,REGS1[rm]);
 | 
						||
         strcat(a,")");
 | 
						||
         break;
 | 
						||
      case 3 :
 | 
						||
         strcat(a,REGS[(w << 3) | rm]);
 | 
						||
         break;
 | 
						||
      }
 | 
						||
 | 
						||
   strcat(a,",");
 | 
						||
   if (iflag)
 | 
						||
      strcat(a,"#");
 | 
						||
   else
 | 
						||
      strcat(a,"*");
 | 
						||
   sprintf(b,"%d",immed);
 | 
						||
   strcat(a,b);
 | 
						||
 | 
						||
   printf("%s\n",a);
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF imhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the  handler  for  various  "mov"-type  opcodes *
 | 
						||
  * which use the mod,  reg,  and r/m  fields of the second *
 | 
						||
  * code byte in a standard, straightforward way.           *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
mvhand(j)
 | 
						||
 | 
						||
   int j;                     /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF mvhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int k, m = j;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   if ((m == 0x84) || (m == 0x85)      /* Kind of kludgey   */
 | 
						||
    || (m == 0xc4) || (m == 0xc5)
 | 
						||
    || (m == 0x8d))
 | 
						||
      if (m & 0x40)
 | 
						||
         m |= 0x03;
 | 
						||
      else
 | 
						||
         m |= 0x02;
 | 
						||
 | 
						||
   printf("%s\t%s\n",optab[j].text,mtrans(m,k,TR_STD));
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF mvhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for segment-register "mov" opcodes. *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
mshand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF mshand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int k;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   if (k & 0x20)
 | 
						||
      {
 | 
						||
      badseq(j,k);
 | 
						||
      return;
 | 
						||
      }
 | 
						||
 | 
						||
   printf("%s\t%s\n",optab[j].text,mtrans(j,k,TR_SEG));
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF mshand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the  handler for pops,  other than  single-byte *
 | 
						||
  * pops.  (The 8088 allows  popping into any register,  or *
 | 
						||
  * directly into memory,  accessed  either  immediately or *
 | 
						||
  * through a register and an index.)                       *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
pohand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF pohand()  * * * * * * * * * */
 | 
						||
 | 
						||
   char *a;
 | 
						||
   register int k;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   if (k & 0x38)
 | 
						||
      {
 | 
						||
      badseq(j,k);
 | 
						||
      return;
 | 
						||
      }
 | 
						||
 | 
						||
   printf("%s\t",optab[j].text);
 | 
						||
 | 
						||
   a = mtrans((j & 0xfd),k,TR_STD);
 | 
						||
 | 
						||
   mtrunc(a);
 | 
						||
 | 
						||
   printf("%s\n",a);
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF pohand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler routine for intersegment  calls and *
 | 
						||
  * jumps.  Its output is never symbolic,  because the host *
 | 
						||
  * linker  does not allow  symbolic  intersegment  address *
 | 
						||
  * references except by means of symbolic  constants,  and *
 | 
						||
  * any such  constants in the symbol  table,  even if they *
 | 
						||
  * are of the  appropriate  value,  may be misleading.  In *
 | 
						||
  * compiled code,  intersegment  references  should not be *
 | 
						||
  * encountered,  and even in assembled  code,  they should *
 | 
						||
  * occur infrequently. If and when they do occur, however, *
 | 
						||
  * they will be disassembled in absolute form.             *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
cihand(j)
 | 
						||
 | 
						||
   int j;                     /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF cihand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int m, n;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   printf("%s\t",optab[j].text);
 | 
						||
 | 
						||
   FETCH(m);
 | 
						||
   FETCH(n);
 | 
						||
 | 
						||
   printf("#0x%04.4x,",((n << 8) | m));
 | 
						||
 | 
						||
   FETCH(m);
 | 
						||
   FETCH(n);
 | 
						||
 | 
						||
   printf("#0x%04.4x\n",((n << 8) | m));
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF cihand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for  "mov"  opcodes with  immediate *
 | 
						||
  * data.                                                   *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
mihand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF mihand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int k;
 | 
						||
   int m, n;
 | 
						||
   char b[64];
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   printf("%s",optab[j].text);
 | 
						||
 | 
						||
   if (j & 8)
 | 
						||
      {
 | 
						||
      FETCH(m);
 | 
						||
      FETCH(n);
 | 
						||
      k = ((n << 8) | m);
 | 
						||
      if (lookext((long)(k),(PC - 1),b))
 | 
						||
         printf("#%s\n",b);
 | 
						||
      else
 | 
						||
         printf("#%d\n",k);
 | 
						||
      }
 | 
						||
   else
 | 
						||
      {
 | 
						||
      FETCH(m);
 | 
						||
      printf("*%d\n",m);
 | 
						||
      }
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF mihand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for a family of quick-move opcodes. *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
mqhand(j)
 | 
						||
 | 
						||
   int j;                     /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF mqhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   unsigned long pc;
 | 
						||
   register int m, n;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   pc = PC + 1;
 | 
						||
 | 
						||
   FETCH(m);
 | 
						||
   FETCH(n);
 | 
						||
 | 
						||
   m = (n << 8) | m;
 | 
						||
 | 
						||
   printf("%s\t",optab[j].text);
 | 
						||
 | 
						||
   if (j & 2)
 | 
						||
      printf("%s,%s\n",
 | 
						||
       lookup((long)(m),N_DATA,LOOK_ABS,pc),
 | 
						||
       REGS[(j & 1) << 3]);
 | 
						||
   else
 | 
						||
      printf("%s,%s\n",
 | 
						||
       REGS[(j & 1) << 3],
 | 
						||
       lookup((long)(m),N_DATA,LOOK_ABS,pc));
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF mqhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for a family of quick-test opcodes. *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
tqhand(j)
 | 
						||
 | 
						||
   int j;                     /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF tqhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int m, n;
 | 
						||
   int k;
 | 
						||
   char b[64];
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   printf("%s\t%s,",optab[j].text,REGS[(j & 1) << 3]);
 | 
						||
 | 
						||
   FETCH(m);
 | 
						||
 | 
						||
   if (j & 1)
 | 
						||
      {
 | 
						||
      FETCH(n);
 | 
						||
      k = ((n << 8) | m);
 | 
						||
      if (lookext((long)(k),(PC - 1),b))
 | 
						||
         printf("#%s\n",b);
 | 
						||
      else
 | 
						||
         printf("#%d\n",k);
 | 
						||
      }
 | 
						||
   else
 | 
						||
      {
 | 
						||
      if (m & 80)
 | 
						||
         m |= 0xff00;
 | 
						||
      printf("*%d\n",m);
 | 
						||
      }
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF tqhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for multiple-byte "return" opcodes. *
 | 
						||
  * The 8088 allows returns to take an optional  16-bit ar- *
 | 
						||
  * gument,  which  reflects  the  amount to be added to SP *
 | 
						||
  * after  the pop of the  return  address.  The idea is to *
 | 
						||
  * facilitate  the use of local  parameters  on the stack. *
 | 
						||
  * After some  rumination,  it was decided to  disassemble *
 | 
						||
  * any such arguments as absolute quantities,  rather than *
 | 
						||
  * rummaging  through the symbol table for possible corre- *
 | 
						||
  * sponding constants.                                     *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
rehand(j)
 | 
						||
 | 
						||
   int j;                     /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF rehand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int m, n;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(m);
 | 
						||
   FETCH(n);
 | 
						||
 | 
						||
   m = (n << 8) | m;
 | 
						||
 | 
						||
   printf("%s\t#0x%04.4x\n",optab[j].text,m);
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF rehand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for "mov"  opcodes involving memory *
 | 
						||
  * and immediate data.                                     *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
mmhand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF mmhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   char *a;
 | 
						||
   register int k;
 | 
						||
   char b[64];
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   if (k & 0x38)
 | 
						||
      {
 | 
						||
      badseq(j,k);
 | 
						||
      return;
 | 
						||
      }
 | 
						||
 | 
						||
   printf("%s",optab[j].text);
 | 
						||
 | 
						||
   if ( ! (j & 1) )
 | 
						||
      putchar('b');
 | 
						||
 | 
						||
   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
 | 
						||
 | 
						||
   mtrunc(a);
 | 
						||
 | 
						||
   printf("\t%s,",a);
 | 
						||
 | 
						||
   if (j & 1)
 | 
						||
      {
 | 
						||
      FETCH(j);
 | 
						||
      FETCH(k);
 | 
						||
      k = (k << 8) | j;
 | 
						||
      if (lookext((long)(k),(PC - 1),b))
 | 
						||
         printf("#%s\n",b);
 | 
						||
      else
 | 
						||
         printf("#%d\n",k);
 | 
						||
      }
 | 
						||
   else
 | 
						||
      {
 | 
						||
      FETCH(k);
 | 
						||
      printf("*%d\n",k);
 | 
						||
      }
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF mmhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the  handler  for the 8088  family of shift and *
 | 
						||
  * rotate instructions.                                    *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
srhand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF srhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   char *a;
 | 
						||
   register int k;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   if ((k & 0x38) == 0x30)
 | 
						||
      {
 | 
						||
      badseq(j,k);
 | 
						||
      return;
 | 
						||
      }
 | 
						||
 | 
						||
   printf("%s",OPFAM[((k & 0x38) >> 3) + 16]);
 | 
						||
 | 
						||
   if ( ! (j & 1) )
 | 
						||
      putchar('b');
 | 
						||
 | 
						||
   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
 | 
						||
 | 
						||
   mtrunc(a);
 | 
						||
 | 
						||
   printf("\t%s",a);
 | 
						||
 | 
						||
   if (j & 2)
 | 
						||
      printf(",cl\n");
 | 
						||
   else
 | 
						||
      printf(",*1\n");
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF srhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for the ASCII-adjust opcodes.       *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
aahand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF aahand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int k;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   if (k != 0x0a)
 | 
						||
      {
 | 
						||
      badseq(j,k);
 | 
						||
      return;
 | 
						||
      }
 | 
						||
 | 
						||
   printf("%s\n",optab[j].text);
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF aahand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for port I/O opcodes  which specify *
 | 
						||
  * the port address as an immediate operand.               *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
iohand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF iohand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int k;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   printf("%s\t0x%02.2x\n",optab[j].text,k);
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF iohand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the  handler  for opcodes  which  perform  long *
 | 
						||
  * (sixteen-bit) relative jumps and calls.                 *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
ljhand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF ljhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   register int k;
 | 
						||
   int m, n;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(m);
 | 
						||
   FETCH(n);
 | 
						||
 | 
						||
   k = (n << 8) | m;
 | 
						||
 | 
						||
   printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text,
 | 
						||
    lookup((PC + k + 1L),N_TEXT,LOOK_LNG,(PC - 1L)),
 | 
						||
    (PC + k + 1L));
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF ljhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for a pair of oddball opcodes (0xf6 *
 | 
						||
  * and 0xf7) which perform miscellaneous arithmetic opera- *
 | 
						||
  * tions not dealt with elsewhere.                         *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
mahand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF mahand()  * * * * * * * * * */
 | 
						||
 | 
						||
   char *a;
 | 
						||
   register int k;
 | 
						||
   char b[64];
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
 | 
						||
 | 
						||
   mtrunc(a);
 | 
						||
 | 
						||
   switch (((k = objbuf[1]) & 0x38) >> 3)
 | 
						||
      {
 | 
						||
      case 0 :
 | 
						||
         printf("\ttest");
 | 
						||
         break;
 | 
						||
      case 1 :
 | 
						||
         badseq(j,k);
 | 
						||
         return;
 | 
						||
      case 2 :
 | 
						||
         printf("\tnot");
 | 
						||
         break;
 | 
						||
      case 3 :
 | 
						||
         printf("\tneg");
 | 
						||
         break;
 | 
						||
      case 4 :
 | 
						||
         printf("\tmul");
 | 
						||
         break;
 | 
						||
      case 5 :
 | 
						||
         printf("\timul");
 | 
						||
         break;
 | 
						||
      case 6 :
 | 
						||
         printf("\tdiv");
 | 
						||
         break;
 | 
						||
      case 7 :
 | 
						||
         printf("\tidiv");
 | 
						||
         break;
 | 
						||
      }
 | 
						||
 | 
						||
   if ( ! (j & 1) )
 | 
						||
      putchar('b');
 | 
						||
 | 
						||
   printf("\t%s",a);
 | 
						||
 | 
						||
   if (k & 0x38)
 | 
						||
      putchar('\n');
 | 
						||
   else
 | 
						||
      if (j & 1)
 | 
						||
         {
 | 
						||
         FETCH(j);
 | 
						||
         FETCH(k);
 | 
						||
         k = (k << 8) | j;
 | 
						||
         if (lookext((long)(k),(PC - 1),b))
 | 
						||
            printf(",#%s\n",b);
 | 
						||
         else
 | 
						||
            printf(",#%d\n",k);
 | 
						||
         }
 | 
						||
      else
 | 
						||
         {
 | 
						||
         FETCH(k);
 | 
						||
         printf(",*%d\n",k);
 | 
						||
         }
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF mahand() * * * * * * * * * * */
 | 
						||
 | 
						||
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 | 
						||
  *                                                         *
 | 
						||
  * This is the handler for miscellaneous jump, call, push, *
 | 
						||
  * and increment/decrement opcodes  (0xfe and 0xff)  which *
 | 
						||
  * are not dealt with elsewhere.                           *
 | 
						||
  *                                                         *
 | 
						||
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 | 
						||
 | 
						||
void
 | 
						||
mjhand(j)
 | 
						||
 | 
						||
   register int j;            /* Pointer to optab[] entry   */
 | 
						||
 | 
						||
{/* * * * * * * * * *  START OF mjhand()  * * * * * * * * * */
 | 
						||
 | 
						||
   char *a;
 | 
						||
   register int k;
 | 
						||
 | 
						||
   objini(j);
 | 
						||
 | 
						||
   FETCH(k);
 | 
						||
 | 
						||
   a = mtrans((j & 0xfd),(k & 0xc7),TR_STD);
 | 
						||
 | 
						||
   mtrunc(a);
 | 
						||
 | 
						||
   switch (((k = objbuf[1]) & 0x38) >> 3)
 | 
						||
      {
 | 
						||
      case 0 :
 | 
						||
         printf("\tinc");
 | 
						||
         if ( ! (j & 1) )
 | 
						||
            putchar('b');
 | 
						||
         putchar('\t');
 | 
						||
         break;
 | 
						||
      case 1 :
 | 
						||
         printf("\tdec");
 | 
						||
         if ( ! (j & 1) )
 | 
						||
            putchar('b');
 | 
						||
         putchar('\t');
 | 
						||
         break;
 | 
						||
      case 2 :
 | 
						||
         if (j & 1)
 | 
						||
            printf("\tcall\t@");
 | 
						||
         else
 | 
						||
            goto BAD;
 | 
						||
         break;
 | 
						||
      case 3 :
 | 
						||
         if (j & 1)
 | 
						||
            printf("\tcalli\t@");
 | 
						||
         else
 | 
						||
            goto BAD;
 | 
						||
         break;
 | 
						||
      case 4 :
 | 
						||
         if (j & 1)
 | 
						||
            printf("\tjmp\t@");
 | 
						||
         else
 | 
						||
            goto BAD;
 | 
						||
         break;
 | 
						||
      case 5 :
 | 
						||
         if (j & 1)
 | 
						||
            printf("\tjmpi\t@");
 | 
						||
         else
 | 
						||
            goto BAD;
 | 
						||
         break;
 | 
						||
      case 6 :
 | 
						||
         if (j & 1)
 | 
						||
            printf("\tpush\t");
 | 
						||
         else
 | 
						||
            goto BAD;
 | 
						||
         break;
 | 
						||
      case 7 :
 | 
						||
 BAD :
 | 
						||
         badseq(j,k);
 | 
						||
         return;
 | 
						||
      }
 | 
						||
 | 
						||
   printf("%s\n",a);
 | 
						||
 | 
						||
   objout();
 | 
						||
 | 
						||
}/* * * * * * * * * * * END OF mjhand() * * * * * * * * * * */
 | 
						||
 | 
						||
 |