z80 disassembler subroutine
Duane Morse
duane at anasazi.UUCP
Thu Nov 21 06:58:08 AEST 1985
Here's a routine which will disassemble one instruction into z80
mnemonics. It will also indicate whether the instruction references
something which might be in a symbol table, so the calling program
can display the nearest symbol name on the same line.
Note: z80dis.c uses Fred Fish's Debug package, though the current
z80dis.o is compiled with -DDBUG_OFF. If you don't have the debug
package, delete "DBUG_3" and "DBUG_ENTER" statements, change "DBUG_VOID_RETURN"
to "return", and change "DBUG_RETURN(x)" to "return(x)".
-----------------------------Cut here ------------------------------
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by duane on Wed Nov 20 13:50:30 MST 1985
# Contents: z80dis.3 z80dis.c
echo x - z80dis.3
sed 's/^@//' > "z80dis.3" <<'@//E*O*F z80dis.3//'
@.TH Z80DIS 3 "Anasazi Programmer's Manual"
@.SH NAME
z80dis \- disassemble memory into Z80 instructions
@.SH SYNOPSIS
@.nf
int z80dis(op_buf, outbuf, b_addr, lblflag)
unsigned char *op_buf;
char *outbuf;
unsigned short b_addr;
long *lblflag;
@.SH RETURNS
Length of the disassembled instruction in bytes (1 to 4).
@.SH DESCRIPTION
z80dis disassembles one Z80 instruction into an uppercase ASCII string.
The instruction to be disassembled starts at
@.B op_buf
and should be at least 4 bytes long (the longest Z80 instruction uses
4 bytes). The null-terminated ASCII string is returned in
@.B outbuf.
The program counter corresponding to the start of the instruction
is in
@.B b_addr.
On return, lblflag is -1 unless the disassembled instruction contained
a full-word address, in which case lblflag contains that address. (If
the caller has access to a symbol table, lblflag can be used to indicate
the nearest symbol name referenced by the instruction.)
@.SH EXAMPLE
instrlen = z80dis(mem_buf, dumpbuf, baseaddr, &z80addr);
@.SH "BUGS AND CAUTIONS"
If z80dis doesn't understand the instruction, it returns a length of
1 and the string is "??".
@//E*O*F z80dis.3//
chmod u=rw,g=r,o=r z80dis.3
echo x - z80dis.c
sed 's/^@//' > "z80dis.c" <<'@//E*O*F z80dis.c//'
/*TITLE z80dis.c - disassemble into Z80 mnemonics - 11/20/85 10:03:34 */
/*SUBTTL Includes, defines, data storage, and declarations */
static char *version = "@(#)z80dis.c 1.1 11/20/85 10:03:34";
/*
** This file contains routine z80dis, which disassembles one z80 instruction.
*/
#include <stdio.h>
#include <dbug.h>
#define STATIC static
#define FAKEHLIDX 0x20 /* Needed for some IX/IY translation */
struct codestring {
unsigned short simplecode; /* Op code */
char *simplestring; /* String that corresponds to simplecode */
} ;
/* Main variables */
/* Points to next byte to disassemble */
STATIC unsigned char *dis_addr;
/* Points to where to put the output byte */
STATIC char *outptr;
/* Points to start of ASCII output buffer */
STATIC char *org_buf;
/* Length of the current instruction in bytes */
STATIC int instr_len;
/* If not -1, addr of "label" in instruction. Caller may have symbol table. */
STATIC long labeladdr;
/* address of the current byte being disassembled */
STATIC unsigned short curaddr;
/* 'X' or 'Y' if current instruction uses IX or IY */
STATIC char ixiyop;
/* Current op code */
STATIC unsigned char this_op;
/* Count of characters displayed before the op code string */
STATIC int count;
/*PAGE*/
/* Register names in order by Z80 convention */
STATIC char *rtbl[] = {
"B", "C", "D", "E", "H", "L", "(HL)", "A"
} ;
/* Register pair names (ends with SP) */
STATIC char *rptbl[] = {
"BC", "DE", "HL", "SP"
} ;
/* Alternate table of register pair names (ends with afF) */
STATIC char *rptbla[] = {
"BC", "DE", "HL", "AF"
} ;
/* Condition code strings */
STATIC char *cctbl[] = {
"NZ", "Z", "NC", "C", "PO", "PE", "P", "M"
} ;
/* String address for STRN routine and for op codes 80 to BF */
STATIC char *strntb[] = {
"ADD A,", "ADC A,", "SUB ", "SBC A,", "AND ", "XOR ", "OR ", "CP "
} ;
/* String addresses for shft00 */
STATIC char *shfttb[] = {
"RLC ", "RRC ", "RL ", "RR ", "SLA ", "SRA ", NULL, "SRL "
} ;
/*PAGE*/
/* Allowed IX and IY op codes other than CB xx */
STATIC unsigned char ixytb[] = {
0x09, 0x19, 0x21, 0x22, 0x23, 0x29, 0x2a,
0x2b, 0x34, 0x35, 0x36, 0x39, 0x46, 0x4e,
0x56, 0x5e, 0x66, 0x6e, 0x70, 0x71, 0x72,
0x73, 0x74, 0x75, 0x77, 0x7e, 0x86, 0x8e,
0x96, 0x9e, 0xa6, 0xae, 0xb6, 0xbe, 0xe1,
0xe3, 0xe5, 0xe9, 0xf9
} ;
/* Op code and string tables */
/*
** The following tables contain pairs of op codes and string addresses.
** If an op code can be handled entirely by displaying a string, it
** appears in one of these tables.
*/
/* Op codes 00 to FF, excluding ED combinations. */
STATIC struct codestring strtb1[] = {
{0x00, "NOP"},
{0x02, "LD (BC),A"},
{0x07, "RLCA"},
{0x08, "EX AF,AF'"},
{0x0a, "LD A,(BC)"},
{0x0f, "RRCA"},
{0x12, "LD (DE),A"},
{0x17, "RLA"},
{0x1a, "LD A,(DE)"},
{0x1f, "RRA"},
{0x27, "DAA"},
{0x2f, "CPL"},
{0x37, "SCF"},
{0x3f, "CCF"},
{0x76, "HALT"},
{0xc9, "RET"},
{0xd9, "EXX"},
{0xeb, "EX DE,HL"},
{0xf3, "DI"},
{0xfb, "EI"}
} ;
/*PAGE*/
/* Op codes ED 40 through ED BF */
STATIC struct codestring strtb2[] = {
{0x44, "NEG"},
{0x45, "RETN"},
{0x46, "IM 0"},
{0x47, "LD I,A"},
{0x4d, "RETI"},
{0x4f, "LD R,A"},
{0x56, "IM 1"},
{0x57, "LD A,I"},
{0x5e, "IM 2"},
{0x5f, "LD A,R"},
{0x67, "RRD"},
{0x6f, "RLD"},
{0xa0, "LDI"},
{0xa1, "CPI"},
{0xa2, "INI"},
{0xa3, "OUTI"},
{0xa8, "LDD"},
{0xa9, "CPD"},
{0xaa, "IND"},
{0xab, "OUTD"},
{0xb0, "LDIR"},
{0xb1, "CPIR"},
{0xb2, "INIR"},
{0xb3, "OTIR"},
{0xb8, "LDDR"},
{0xb9, "CPDR"},
{0xba, "INDR"},
{0xbb, "OTDR"}
} ;
/*PAGE*/
/* Declaractions */
STATIC unsigned char nxtbyt();
STATIC int disasm(), doed(), shifts(), exmtbl(), exmstr(), outrpc();
STATIC void jrcom(), dorela(), outchr(), oct1(), hex1(), hex2();
STATIC void outrs0(), outrs3(), outr(), sout(), badop();
STATIC void doixiy(), outrp4(), outrpa(), doaddr(), donpar(), doadrp();
/*SUBTTL z80dis - disassemble an instruction */
/*
** int z80dis(op_buf, outbuf, b_addr, lblflag)
**
** Disassemble one Z80 instruction.
**
** Parameters:
** op_buf = points to where object code to be disassembled is found.
** outbuf = points to where z80dis sends the ASCII output.
** b_addr = address of the instruction pointed at by op_buf.
** lblflag = if not -1, address of a possible label in the instruction
** (e.g. in a jump instruction, call, etc.).
**
** Returns:
** Length of the instruction disassembled.
*/
int z80dis(op_buf, outbuf, b_addr, lblflag)
unsigned char *op_buf;
char *outbuf;
unsigned short b_addr;
long *lblflag;
{
DBUG_ENTER("z80dis");
/* Set up the globals */
dis_addr = op_buf;
org_buf = outptr = outbuf;
curaddr = b_addr;
labeladdr = -1;
instr_len = 0;
count = 5;
ixiyop = '\0';
/* Do the work */
if (disasm())
badop();
else if (ixiyop) {
if (disasm())
badop();
}
*outptr = '\0';
*lblflag = labeladdr;
DBUG_RETURN(instr_len);
}
/*SUBTTL disasm - disassemble */
/*
** int disasm()
**
** Disassemble an instruction. If an IX/IY instruction is encountered,
** this routine will be called twice.
**
** Parameters:
**
** ixiyop = null if not an IX or IY instruction, 'X' or 'Y' otherwise.
**
** Returns:
** 0 if successful, -1 if the instruction is invalid.
*/
STATIC int disasm()
{
unsigned char op;
DBUG_ENTER("disasm");
/* Get the next byte in the message */
this_op = nxtbyt();
/* Am I in the middle of an IX or IY instruction? */
if (ixiyop) {
/* Yes - handle illegal values */
if (this_op == 0xdd || this_op == 0xfd || this_op == 0xed)
DBUG_RETURN(-1);
if (this_op == 0xcb) {
op = *(dis_addr + 1);
if (op == 0x36)
DBUG_RETURN(-1);
op &= 0xf;
if (op != 6 && op != 0xe)
DBUG_RETURN(-1);
DBUG_RETURN(shifts());
}
/* See if op code makes sense with IX/IY */
if (exmtbl(ixytb, sizeof(ixytb)))
DBUG_RETURN(-1);
}
/*PAGE*/
/* See if a simple string will do */
if (exmstr(strtb1, sizeof(strtb1) / sizeof(struct codestring)) == 0)
DBUG_RETURN(0);
/* Try miscellaneous instructions */
switch (this_op) {
case 0x10: /* DJNZ */
dorela("DJNZ ");
DBUG_RETURN(0);
case 0x18: /* JR */
jrcom(NULL);
DBUG_RETURN(0);
case 0x20: /* JR NZ */
jrcom("NZ");
DBUG_RETURN(0);
case 0x22: /* LD (addr),HL */
sout("LD ");
doadrp();
this_op = FAKEHLIDX;
outrp4(",");
DBUG_RETURN(0);
case 0x28: /* JR Z */
jrcom("Z");
DBUG_RETURN(0);
case 0x2a: /* LD HL,(addr) */
this_op = FAKEHLIDX;
outrp4("LD ");
outchr(',');
doadrp();
DBUG_RETURN(0);
case 0x30: /* JR NC */
jrcom("NC");
DBUG_RETURN(0);
case 0x32: /* LD (addr),A */
sout("LD ");
doadrp();
sout(",A");
DBUG_RETURN(0);
case 0x38: /* JR C */
jrcom("C");
DBUG_RETURN(0);
case 0x3a: /* LD A,(addr) */
sout("LD A,");
doadrp();
DBUG_RETURN(0);
case 0xc3: /* JP addr */
sout("JP ");
doaddr();
DBUG_RETURN(0);
case 0xcb: /* shift */
DBUG_RETURN(shifts());
case 0xcd: /* CALL */
sout("CALL ");
doaddr();
DBUG_RETURN(0);
case 0xd3: /* OUT (nn),A */
sout("OUT ");
donpar();
sout(",A");
DBUG_RETURN(0);
case 0xdb: /* IN A,(nn) */
sout("IN A,");
donpar();
DBUG_RETURN(0);
case 0xdd: /* IX instruction */
ixiyop = 'X';
DBUG_RETURN(0);
case 0xe3: /* EX (SP),HL */
this_op = FAKEHLIDX;
outrp4("EX (SP),");
DBUG_RETURN(0);
case 0xe9: /* JP (HL) */
this_op = FAKEHLIDX;
outrp4("JP (");
outchr(')');
DBUG_RETURN(0);
case 0xed: /* various */
DBUG_RETURN(doed());
case 0xf9: /* LD SP,HL */
this_op = FAKEHLIDX;
outrp4("LD SP,");
DBUG_RETURN(0);
case 0xfd: /* IY instruction */
ixiyop = 'Y';
DBUG_RETURN(0);
default:
break;
}
/*PAGE*/
/* Handle op codes from 00 to 3f */
if (this_op < 0x40) {
switch (this_op & 0x0f) {
case 1: /* ld rp,nnnn */
outrp4("LD ");
outchr(',');
doaddr();
DBUG_RETURN(0);
case 3: /* inc rp */
outrp4("INC ");
DBUG_RETURN(0);
case 4: case 0xc: /* inc r */
outrs3("INC ");
DBUG_RETURN(0);
case 5: case 0xd: /* dec r */
outrs3("DEC ");
DBUG_RETURN(0);
case 6: case 0xe: /* ld r,nn */
outrs3("LD ");
outchr(',');
hex2((int) nxtbyt());
DBUG_RETURN(0);
case 9: /* add hl,rp */
if (ixiyop) {
sout("ADD ");
doixiy();
outrp4(",");
}
else
outrp4("ADD HL,");
DBUG_RETURN(0);
case 0xb: /* DEC rp */
outrp4("DEC ");
DBUG_RETURN(0);
default:
DBUG_RETURN(-1);
}
}
/* Handle op codes from 40 to 7f */
if (this_op < 0x80) {
/* Instruction is LD r,r' */
outrs3("LD ");
outchr(',');
outrs0();
DBUG_RETURN(0);
}
/* Handle op codes from 80 to bf */
if (this_op < 0xc0) {
sout(strntb[(this_op >> 3) & 0x7]);
outrs0();
DBUG_RETURN(0);
}
/*PAGE*/
/* Op code is from c0 to ff */
switch (this_op & 0xf) {
case 0: case 8: /* RET cc */
sout("RET ");
sout(cctbl[(this_op >> 3) & 0x7]);
DBUG_RETURN(0);
case 1: /* pop rp */
outrpa("POP ");
DBUG_RETURN(0);
case 2: case 0xa: /* JP cc,addr */
sout("JP ");
sout(cctbl[(this_op >> 3) & 0x7]);
outchr(',');
doaddr();
DBUG_RETURN(0);
case 4: case 0xc: /* CALL cc,addr */
sout("CALL ");
sout(cctbl[(this_op >> 3) & 0x7]);
outchr(',');
doaddr();
DBUG_RETURN(0);
case 5: /* PUSH rp */
outrpa("PUSH ");
DBUG_RETURN(0);
case 6: case 0xe: /* Various */
sout(strntb[((this_op - 0xc6) >> 3) & 0xf]);
hex2(nxtbyt());
DBUG_RETURN(0);
case 7: case 0xf: /* rst p */
sout("RST ");
hex2(this_op & 0x38);
DBUG_RETURN(0);
default:
break;
}
DBUG_RETURN(-1);
}
/*SUBTTL Functions for putting addresses and registers together */
/*
** void jrcom(s)
**
** Handle jr xx,e or jr e instructions.
**
** Parameters:
** s = NULL or string pointer for condition code.
**
** Returns:
** Nothing.
*/
STATIC void jrcom(s)
char *s;
{
DBUG_ENTER("jrcom");
sout("JR ");
if (s != NULL) {
sout(s);
outchr(',');
}
dorela();
DBUG_VOID_RETURN;
}
/*
** void dorela(s)
**
** Compute a relative address and save the absolute address for
** a relative jump.
**
** Parameters:
** s = string to display before doing other stuff.
**
** Returns:
** Nothing.
*/
STATIC void dorela(s)
char *s;
{
unsigned char op;
int offset;
sout(s);
op = nxtbyt();
offset = (char) op;
labeladdr = curaddr + offset;
if (offset < 0) {
offset = -offset;
sout(".-");
}
else
sout(".+");
hex2(offset);
}
/*SUBTTL Handle ED op codes */
/*
** int doed()
**
** Handle op codes beginning with ED.
**
** Parameters:
** None.
**
** Returns:
** 0 if successful, -1 otherwise.
*/
STATIC int doed()
{
DBUG_ENTER("doed");
this_op = nxtbyt();
if (exmstr(strtb2, sizeof(strtb2) / sizeof(struct codestring)) == 0)
DBUG_RETURN(0);
if (this_op < 0x40 || this_op >= 0x80)
DBUG_RETURN(-1);
switch (this_op & 0xf) {
case 0: case 8: /* IN r,(C) */
if (this_op == 0x70)
DBUG_RETURN(-1);
outrs3("IN ");
sout(",(C)");
DBUG_RETURN(0);
case 1: case 9: /* OUT (C),r */
if (this_op == 0x71)
DBUG_RETURN(-1);
outrs3("OUT (C),");
DBUG_RETURN(0);
case 2: /* SBC HL,rp */
outrp4("SBC HL,");
DBUG_RETURN(0);
case 3: /* LD (addr),rp */
sout("LD ");
doadrp();
outrp4(",");
DBUG_RETURN(0);
case 0xa: /* ADC HL,rp */
outrp4("ADC HL,");
DBUG_RETURN(0);
case 0xb: /* LD rp,(addr) */
outrp4("LD ");
outchr(',');
doadrp();
DBUG_RETURN(0);
default:
break;
}
DBUG_RETURN(-1);
}
/*SUBTTL Handle CB op codes - shifts */
/*
** int shifts()
**
** Handle shift instructions.
**
** Parameters:
** None.
**
** Returns:
** 0 if the instruction is valid, -1 otherwise.
*/
STATIC int shifts()
{
int k;
DBUG_ENTER("shifts");
this_op = ixiyop ? *(dis_addr + 1) : nxtbyt();
if (this_op < 0x40) {
k = (this_op >> 3) & 0x7;
if (k == 6)
DBUG_RETURN(-1);
sout(shfttb[k]);
outrs0();
if (ixiyop)
nxtbyt();
DBUG_RETURN(0);
}
if (this_op < 0x80)
sout("BIT ");
else if (this_op < 0xc0)
sout("RES ");
else
sout("SET ");
k = (this_op >> 3) & 7;
outchr('0' + k);
outchr(',');
outrs0();
if (ixiyop)
nxtbyt();
DBUG_RETURN(0);
}
/*SUBTTL exmtbl & exmstr - see if op code found in table */
/*
** int exmtbl(s, n)
**
** See of this_op is found in the op code table pointed at by s.
**
** Parameters:
** s = points to table of op codes.
** n = number of entries in the table.
**
** this_op = op code to seek.
**
** Returns:
** 0 if found, -1 otherwise.
*/
STATIC int exmtbl(s, n)
register unsigned char *s;
register int n;
{
register unsigned char c;
DBUG_ENTER("exmtbl");
for (c = this_op; n--; )
if (*s++ == c)
DBUG_RETURN(0);
DBUG_RETURN(-1);
}
/*PAGE*/
/*
** int exmstr(ptr, n)
**
** Look for this_op in a table of op code & strings. If the op code is
** found, display the associated string.
**
** Parameters:
** ptr = points to the op code/string table.
** n = number of entries in the table.
**
** this_op = op code to seek.
**
** Returns:
** 0 if successful, -1 otherwise.
*/
STATIC int exmstr(ptr, n)
register struct codestring *ptr;
register int n;
{
register short c;
DBUG_ENTER("exmstr");
for (c = this_op; n--; ptr++)
if (ptr->simplecode == c) {
sout(ptr->simplestring);
DBUG_RETURN(0);
}
DBUG_RETURN(-1);
}
/*SUBTTL String-oriented subroutines */
/*
** outchr(c)
**
** Display the character in c, making sure that there are always
** 5 characters before the operand.
**
** Parameters:
** c = character to display.
**
** Returns;
** Nothing.
*/
STATIC void outchr(c)
{
count--;
if (c != ' ') {
*outptr++ = c;
return;
}
while (count-- > 0)
*outptr++ = ' ';
*outptr++ = ' ';
}
/*PAGE*/
/*
** void hex1(k)
**
** Display a value as one hex digit.
**
** Parameters:
** k = value to convert to hex.
**
** Returns:
** Nothing.
*/
STATIC void hex1(k)
int k;
{
k &= 0xf;
if (k < 10)
outchr('0' + k);
else
outchr('A' + k - 10);
}
/*
** void hex2(k)
**
** Display a value as 2 hex digits.
**
** Parameters:
** k = value to display.
**
** Returns:
** Nothing.
*/
STATIC void hex2(k)
int k;
{
hex1(k >> 4);
hex1(k);
}
/*PAGE*/
/*
** void outrs0()
**
** Output the name of a register using the last 3 bits of this_op.
**
** Parameters:
**
** this_op = current op code.
**
** Returns:
** Nothing.
*/
STATIC void outrs0()
{
outr(this_op & 0x7);
}
/*
** void outrs3(s)
**
** Display the name of a register using bits 2-4 of this_op.
**
** Parameters:
** s = points to string to display first.
**
** this_op = current op code.
**
** Returns:
** Nothing.
*/
STATIC void outrs3(s)
char *s;
{
sout(s);
outr((this_op >> 3) & 0x7);
}
/*PAGE*/
/*
** void outr(k)
**
** Display a register based on an index.
**
** Parameters:
** k = register's index.
**
** Returns:
** Nothing.
*/
STATIC void outr(k)
int k;
{
int offset;
if (k == 6 && ixiyop) {
/* It's (IX+d) or (IY+d) */
sout("(I");
outchr(ixiyop);
offset = (char) nxtbyt();
if (offset < 0) {
outchr('-');
offset = -offset;
}
else
outchr('+');
hex2(offset);
outchr(')');
return;
}
sout(rtbl[k]);
}
/*PAGE*/
/*
** void sout(s)
**
** Display a string.
**
** Parameters:
** s = points to string to display.
**
** Returns:
** Nothing.
*/
STATIC void sout(s)
register char *s;
{
while (*s)
outchr(*s++);
}
/*
** int outrpc()
**
** Compute register pair index and handle IX/IY if necessary.
**
** Parameters:
**
** this_op = current op code.
**
** Returns:
** -1 if an IX/IY register pair was displayed, 0 otherwise.
*/
STATIC int outrpc()
{
int k;
DBUG_ENTER("outrpc");
k = (this_op >> 4) & 0x3;
if (k != 2 || ixiyop == '\0')
DBUG_RETURN(0);
doixiy();
DBUG_RETURN(-1);
}
/*PAGE*/
/*
** void doixiy()
**
** Display IX or IY.
**
** Parameters:
**
** ixiyop = 'X' or 'Y'.
**
** Returns:
** Nothing.
*/
STATIC void doixiy()
{
outchr('I');
outchr(ixiyop);
}
/*
** void outrp4(s)
**
** Output a register pair name. Bits 2-3 of this_op contain the index.
**
** Parameters:
** s = points to string to display first.
**
** this_op = current op code.
**
** Returns:
** Nothing.
*/
STATIC void outrp4(s)
char *s;
{
DBUG_ENTER("outrp4");
sout(s);
if (outrpc())
DBUG_VOID_RETURN;
sout(rptbl[(this_op >> 4) & 0x3]);
}
/*PAGE*/
/*
** void outrpa(s)
**
** Output a register pair name. Bits 2-3 of this_op contain the index.
** (This is like outrp4 except register pair SP is replaced with AF.
**
** Parameters:
** s = points to string to display first.
**
** this_op = current op code.
**
** Returns:
** Nothing.
*/
STATIC void outrpa(s)
char *s;
{
DBUG_ENTER("outrpa");
sout(s);
if (outrpc())
DBUG_VOID_RETURN;
sout(rptbla[(this_op >> 4) & 0x3]);
}
/*PAGE*/
/*
** void doaddr()
**
** Display the address pointed at by dis_addr.
**
** Parameters:
**
** dis_addr = points to first byte of address.
**
** Returns:
** Nothing.
*/
STATIC void doaddr()
{
unsigned short addr;
addr = nxtbyt();
addr |= ((nxtbyt() << 8) & 0xff00);
hex2(addr >> 8);
hex2(addr);
labeladdr = addr;
}
/*
** void donpar()
**
** Display the next byte in hex surrounded by parentheses.
**
** Parameters:
**
** dis_addr = points to the byte to fetch.
**
** Returns:
** Nothing.
*/
STATIC void donpar()
{
outchr('(');
hex2((int) nxtbyt());
outchr(')');
}
/*PAGE*/
/*
** void doadrp()
**
** Display the address pointed at by dis_addr surrounded by parentheses.
**
** Parameters:
**
** dis_addr = points to first byte of address.
**
** Returns:
** Nothing.
*/
STATIC void doadrp()
{
outchr('(');
doaddr();
outchr(')');
}
/*SUBTTL nxtbyt - get next byte to examine */
/*
** unsigned char nxtbyt()
**
** Return the next byte of the instruction and advance pointers and
** counters.
**
** Parameters:
**
** dis_addr = points to the next byte to fetch.
** instr_len = current instruction length.
** curaddr = address of the current byte.
**
** Returns:
** The next byte.
**
** Side effects:
** dis_addr, instr_len, and curaddr are advanced.
*/
STATIC unsigned char nxtbyt()
{
DBUG_ENTER("nxtbyt");
curaddr++;
instr_len++;
DBUG_3("nxtbyt", "returning %x", *dis_addr);
DBUG_RETURN(*dis_addr++);
}
/*SUBTTL badop - handle unknown instruction */
/*
** void badop()
**
** Replace whatever was being worked on with generic bad operand info.
**
** Parameters:
** None.
**
** Returns:
** Nothing.
*/
STATIC void badop()
{
outptr = org_buf;
sout("??");
labeladdr = -1;
instr_len = 1;
}
@//E*O*F z80dis.c//
chmod u=rw,g=rw,o=rw z80dis.c
exit 0
--
Duane Morse ...!noao!{terak|mot}!anasazi!duane
(602) 870-3330
More information about the Comp.sources.unix
mailing list