1049 lines
25 KiB
C
1049 lines
25 KiB
C
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() * * * * * * * * * * */
|
||
|
||
|