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\t$%02.2x\t\t| invalid code sequence\n",j);
   printf("\t.byte\t$%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\t$%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[80];

   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);
	 if( k < 16 )
            printf("%s\tal,*%d\n",optab[j].text,k);
	 else
            printf("%s\tal,*$%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
	    {
	    if( k < 100 || k > 65436 )
	       printf("%s\tax,#%d\n",optab[j].text, (short)k);
	    else
	       printf("%s\tax,#$%04x\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;
   unsigned short dest;

   objini(j);

   FETCH(m);

   if (m & 0x80)
      k = 0xff00;
   else
      k = 0;

   k |= m;
   dest = (PC + k + 1);

   printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text,
    lookup((long) dest,N_TEXT,LOOK_REL,-1L),
    (long) dest);

   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 = -0xFF;
         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,"*");
            sprintf(b,"%d(", (short)offset);
	 }
         else
	 {
            strcat(a,"#");
	    if( offset < 100 || offset > 65436 )
               sprintf(b,"%d(", (short)offset);
	    else
               sprintf(b,"$%04x(",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,"#");
      if( immed < 100 || immed > 65436 )
         sprintf(b,"%d", (short)immed);
      else
         sprintf(b,"$%04x",immed);
   }
   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("#$%04.4x,",((n << 8) | m));

   FETCH(m);
   FETCH(n);

   printf("#$%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[80];

   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
         {
         if( k < 100 || k > 65436 )
            printf("#%d\n",(short)k);
	 else
            printf("#$%04x\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[80];

   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
         {
         if( k < 100 || k > 65436 )
            printf("#%d\n",(short)k);
	 else
            printf("#$%04x\n",k);
         }
      }
   else
      {
      if (m & 80)
         m |= -0xFF;
      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[80];

   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
         {
         if( k < 100 || k > 65436 )
            printf("#%d\n",(short)k);
	 else
            printf("#$%04x\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\t$%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;
   unsigned short dest;

   objini(j);

   FETCH(m);
   FETCH(n);

   k = (n << 8) | m;
   dest = PC + k + 1;

   printf("%s\t%s\t\t| loc %05.5lx\n",optab[j].text,
          lookup((long)dest,N_TEXT,LOOK_LNG,(PC - 1L)),
          (long)dest);

   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[80];

   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(",#$%04x\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() * * * * * * * * * * */


