[comp.os.cpm] Z80/Z280 disassembler in C

root@kunivv1.sci.kun.nl (Privileged Account) (12/27/89)

In article <592@kunivv1.sci.kun.nl> lwj@cs.kun.nl (Luc Rooijakkers) writes:
>
>So, does anyone want it posted ?
>

Since several people have asked me to post it, here it is. It compiles
without problems on SunOs 4.0.3 cc (Z80 only) and also under gcc (Z80
and Z280 versions).

This package comprises a universal Z80/Z280 (compile-time selectable)
disassembler module, together with three front-ends using it: a simple
disassembler for CP/M .COM files, an opcode table producing program and
an opcode list producing program.

The package was originally written in TurboC 2.0. It has been cleaned up
to the point that it *should* be portable C now. Prototypes are included and
used if the preprocessor symbol PROTO is defined (see the Makefile). The
Z80 version works with SunOs 4.0.3 cc; both Z280 and Z80 work with gcc.
The Z280 version can be made to work with cc using a sed script; see the
README.

Have fun, and a Happy New Year to you all.

--
Luc Rooijakkers                                 Internet: lwj@cs.kun.nl
Faculty of Mathematics and Computer Science     UUCP: uunet!cs.kun.nl!lwj
University of Nijmegen, the Netherlands         tel. +3180612271

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  MANIFEST Makefile README beep.com.uue dis.c dis.h disas.c
#   oplist.c optab.c outdebug.c outhex.c outsym.c stdlib.h
# Wrapped by lwj@cs.kun.nl on Wed Dec 27 13:30:02 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f MANIFEST -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MANIFEST\"
else
echo shar: Extracting \"MANIFEST\" \(850 characters\)
sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                  1	This file
X Makefile                  1	Makefile for the package
X README                    1	Read this first
X beep.com.uue              1	Uuencoded beep.com; use with disas
X dis.c                     1	Universal Z80/Z280 disassembly module
X dis.h                     1	Declarations for disassembly module
X disas.c                   1	Simple disassembler program
X oplist.c                  1	Opcode list program
X optab.c                   1	Opcode table program
X outdebug.c                1	Debugging output function for module
X outhex.c                  1	Hexadecimal output function for module
X outsym.c                  1	Symbolic output function for module
X stdlib.h                  1	Dummy <stdlib.h> for dumb compilers
END_OF_MANIFEST
if test 850 -ne `wc -c <MANIFEST`; then
    echo shar: \"MANIFEST\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(1084 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# @(#) Makefile - makefile for Z80/Z280 disassembler package
X#
X
X# Change this if you want prototype support
X
XPROTO=
X#PROTO=-DPROTO
X
X# Change this if you want a Z280 version. You then need ANSI string
X# concatenation or you must edit dis.c (see the README)
X
XFLAVOR=-DZ80
X#FLAVOR=-DZ280
X
X# You might change this if you have gcc
X
XCC=cc
X#CC=gcc
X
XLINT=lint
X
X# The -I. is there in case your compiler doesn't have <stdlib.h>
X
XCFLAGS=$(PROTO) $(FLAVOR) -I.
X
XLINTFLAGS=$(FLAVOR) -I.
X
X# Rules
X
Xall: disas optab oplist
X
Xdisas: disas.o outhex.o dis.o
X	$(CC) $(CFLAGS) disas.o outhex.o dis.o -o disas
X
Xoptab: optab.o outsym.o outdebug.o dis.o
X	$(CC) $(CFLAGS) optab.o outsym.o outdebug.o dis.o -o optab
X
Xoplist: oplist.o outsym.o outdebug.o dis.o
X	$(CC) $(CFLAGS) oplist.o outsym.o outdebug.o dis.o -o oplist
X
Xdisas.o optab.o oplist.o dis.o outsym.o outdebug.o outhex.o: dis.h Makefile
X
Xclean:
X	rm -f disas optab oplist *.o core
X
Xlint:
X	$(LINT) $(LINTFLAGS) disas.c outhex.c dis.c
X	$(LINT) $(LINTFLAGS) optab.c outsym.c outdebug.c dis.c
X	$(LINT) $(LINTFLAGS) oplist.c outsym.c outdebug.c dis.c
X
END_OF_Makefile
if test 1084 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(7040 characters\)
sed "s/^X//" >README <<'END_OF_README'
XREADME - readme file for Z80/Z280 disassembler package
X------------------------------------------------------
X
XOverview
X--------
X
XThis package comprises a universal Z80/Z280 (compile-time selectable)
Xdisassembler module, together with three front-ends using it: a simple
Xdisassembler for CP/M .COM files, an opcode table producing program and
Xan opcode list producing program.
X
XThe package was originally written in TurboC 2.0. It has been cleaned up
Xto the point that it *should* be portable C now. Prototypes are included and
Xused if the preprocessor symbol PROTO is defined (see the Makefile). The
XZ80 version works with SunOs 4.0.3 cc; both Z280 and Z80 work with gcc.
X
XPortability
X-----------
X
XOnly #ifdef and #ifndef are used, and no use is made of any ANSI-ness
Xexcept the following:
X
X- In the file dis.c ANSI string concatenation is used in the form "LD"W where
X  W is a preprocessor macro. It is defined to be "W" if Z280 is defined, and
X  empty otherwise. This is done to modify certain mnemonics when compiling a
X  Z280 disassembler. If needed, it can be gotten rid of with
X
X	mv dis.c dis.old
X	sed 's/"W/W"/g' dis.old >dis.c
X
X  since it is only used in this form.
X
X- The file <stdlib.h> is included in disas.c, optab.c and oplist.c. Non-ANSI
X  compilers and even gcc don't usually have it, so I've included a dummy
X  stdlib.h that is used automatically (with gcc at least) if the standard one
X  is not available (by -I. in the Makefile).
X
X- The functions memset, strchr and various other SysV/ANSI functions are used,
X  that might not be on a BSD system (they *are* on SunOs).
X
XByte order is not (should not) be a problem, since I've tried to insure
Xthat it isn't exploited anywhere now (in the original version, it was).
X
XThe types word and byte (declared in dis.h) really *must* be unsigned. It
Xwould be most convenient if you could do ``typedef unsigned short word'' and
X``typedef unsigned char byte'', but this gives problems if you use function
Xprototypes, since all function *definitions* are still old-style and hence
Xsuffer argument promotion. This would give a mismatch between the promoted
Xtype (``unsigned int'' in both cases) and the type used in the function
Xprototypes (TurboC 2.0 seems to allow this however; maybe this is a bug?)
XHowever, the type byte not being a char flavor is a bit inconvenient; see
Xfor example the function get() in disas.c.
X
XThe code passes lint; all messages generated are spurious or arise from
Xomitting declarationof things like sprintf, memset etc.
X
XStructure
X---------
X
XThe disassembler module itself consists of the files dis.c and dis.h.
XIt contains a function dis() that takes an array of sufficient ``byte''s
Xas argument and produces (via the functions outs() and outval()) it's
Xdisassembled form, returning the length of the instruction. Opcode and
Xoperands are separated by a tab. This module compiles a Z280 assembler if
Xthe preprocessor constant Z280 is defined, otherwise as Z80. It's flexibility
Xis due to the use of the function outval() that is called for any value to
Xbe output. Example's of such a function can be found in outsym.c, outdebug.c
Xand outhex.c. The outval() function should direct all it's output via outs()
Xin order to interoperate properly with the disassembler.
X
XThe Z280 instruction set is almost a superset of the (legal) Z80 instruction
Xset, even LD IXH,A is now legal. The only instruction changed is IN F,(C)
Xwhich is now spelled TSTI (C) (probably more clearly). Also, a considerable
Xsyntax weakening has been done: one may now write AND A,B and NEG A also.
XLots of opcodes now have multiple mnemonics, usually one with and one without
Xa trailing "W" (e.g. LD HL,0 == LDW HL,0 == LDA HL,(0)). Since a disassembler
Xcan only produce one form, I've chose for the most elaborate one (that is,
Xinclude the "W" and the optional "A" or "A," if allowed), e.g. write NEG A and
Xnot NEG (there's now also a NEG HL), write AND A,B not AND B and LDW HL,0 not
XLD HL,0. Note that there is one nasty case: ADD HL,BC != ADDW HL,BC (the
Xlatter sets *all* flags, while the former only sets the carry flag). In the
XZ280 version I also chose NV and V instead of PO and PE as condition codes.
XFinally, the illegal Z80 instruction SLIA (shift left filling with 1-bits)
Xthat fills the gap in the Z80 CB opcodes is now called TSET (test and set) and
Xworks totally different. In fact, it's the instruction Zilog recommends using
Xto differentiate the two chips.
X
XThe disassembler consists mainly of several large switch statements. Despite
Xits apparent chaos, there *is* a method (or maybe several methods :-) to the
XZ80 instruction set, and even more so to the Z280 instruction set. This can
Xbe seen most clearly by the opcode tables produced by optab, and also in the
Xstructure of the disassembler itself.
X
XThree front-end programs using the module are included:
X
X- The program disas is a simple disassembler for CP/M .COM files. It is
X  included merely as a demonstration of the function outhex(). It's
X  stucture reflects the fact that it was actually cut from a larger program
X  that was too messy to include here. More elaborate versions, including a
X  symbolic one, are easily written. Use it on the file beep.com (included
X  as beep.com.uue) to see a sample of it's use.
X
X- The program optab produces opcode tables of 160 characters wide (this is
X  the maximum width my PC printer can support). The tables are organized as
X  8 columns by 32 rows. The program takes a few bytes as arguments, and
X  produces a table of all 256 extensions of these bytes. The following
X  invocations are useful:
X
X	optab [-] [dd|fd]
X	optab [-] [dd|fd] cb
X	optab [-] [dd|fd] ed
X
X  (opcodes dd ed and fd ed are meaningful for the Z280 only).
X
X  If the minus is included, the outdebug() function is used instead of the
X  outsym() function, producing things like "JP jp" and "IN A,(in)" to show
X  what values the "out" parameter of the outval() function gets for the
X  different instructions. See the files dis.c, dis.h and the discussion above.
X
X  For the Z280 EPU ("extended processing unit", read "floating point unit")
X  instructions, the four byte operands are printed as "epu,epu,epu,epu", but
X  this can easily be changed inside the outval() function, see for example
X  outval() in optab.c.
X
X- The program oplist works just like optab, except that it produces a list
X  of instructions instead of a table. Instruction bytes containing operands
X  are displayed **, e.g. ``21****  LD  HL,nn''.
X
XInstallation
X------------
X
XInstallation should be as simple as typing ``make''. This will build the
XZ80 version of the package. If you want the Z280 version, you must edit
Xthe Makefile and use a C compiler that supports ANSI string concatenation,
Xor use the sed script given above.
X
XComments
X--------
X
XAlthough I believe that the disassembler is correct and complete, I might
Xhave overlooked some things. If you find any bugs or omissions, please
Xreport them to me, Luc Rooijakkers <lwj@cs.kun.nl>. Note that I am *not*
Xinterested in mnemonic changes, except to correct mistakes.
X
XHave Fun !
X
X
END_OF_README
if test 7040 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f beep.com.uue -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"beep.com.uue\"
else
echo shar: Extracting \"beep.com.uue\" \(555 characters\)
sed "s/^X//" >beep.com.uue <<'END_OF_beep.com.uue'
Xbegin 644 beep.com
XM$=4!S7 !'@<. LT%  : Q0X+S04 MR %P1#T&.G!#@'-!0#^ \PI <G-;0'-
XM=0'^_\@1PP'-< '-: %?YE_^62@2_DXH''O^ \QM 1&G <UP 1C>$:(!S7 !
XM#A,1?@'#!0 1I0'#< $. <,% !&? 0X)PP4 $7X!#A'-!0#) 20D)" @(" @
XM4U5"                            7D,D97,D;R0-"E!L96%S92!S<&5C
XM:69Y(%EE<R!O<B!.;R$D#0I497)M:6YA=&4@4W5B/R D4W1R:6ME(&%N>2!K
XM97D@=VAE;B!R96%D>2XN+B1 *",I($)%15 @,C@P-S@X('1H92!!8VED)R!3
XM;V9T=V%R92!7;W)K<P                                          
XM                                                            
X8                                
X 
Xend
END_OF_beep.com.uue
if test 555 -ne `wc -c <beep.com.uue`; then
    echo shar: \"beep.com.uue\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dis.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dis.c\"
else
echo shar: Extracting \"dis.c\" \(18930 characters\)
sed "s/^X//" >dis.c <<'END_OF_dis.c'
X/*
X * dis - generic Z80/Z280 disassembler
X *
X * Copyright 1989 by Luc Rooijakkers <lwj@cs.kun.nl>
X * Permission is hereby granted to use and modify this code for
X * non-commercial use, provided this copyright is retained.
X *
X */
X
X#include <stdio.h>
X#include <string.h>
X
X#include "dis.h"
X
X/*
X * Use compiler options to define either Z80 or Z280.
X * If none is defined, Z80 is the default.
X *
X */
X
X#ifndef Z80
X#ifndef Z280
X#define	Z80
X#endif
X#endif
X
X/*
X * change log
X *
X * ../../88	Created as symbolic Z280 disassembler
X * ../../88	Extended to non-symbolic Z280 disassembler
X * ../../88	Added #if's for Z80 disassembler
X * 07/07/88	First final version
X * 12/08/89	Split off output routines
X * 01/10/89	Split OUT_IO into OUT_INP,OUT_OUTP
X * 23/12/89	Split off more output routines
X * 24/12/89	Cleaned up for public release
X * 27/12/89	Use strchr() instead of strstr()
X *
X */
X
X#ifdef Z280
X	char DisId[] = "@(#) DIS (Z280) 27/12/89";
X#else
X	char DisId[] = "@(#) DIS (Z80) 27/12/89";
X#endif
X
X/*
X * prototypes
X *
X */
X
X#ifdef PROTO
X
Xstatic void outsp(char *s,char *sp);
Xstatic void outjrt(int len);
Xstatic void outjpt(int out);
Xstatic void expand(char *s);
Xstatic void dis_CB(void);
Xstatic void dis_ED(void);
X
X#else /* !PROTO */
X
Xstatic void outsp();
Xstatic void outjrt();
Xstatic void outjpt();
Xstatic void expand();
Xstatic void dis_CB();
Xstatic void dis_ED();
X
X#endif /* PROTO */
X
X/*
X * byte/word get routines
X *
X */
X
Xstatic byte *getptr;
X
X#define	onebyte(disp)	( (word) ( (unsigned)getptr[disp]&0xFF ) )
X
X#define	getbyte()	( getptr+=1, onebyte(-1) )
X
X#define	getword()	( getptr+=2, onebyte(-2)+(onebyte(-1)<<8) )
X
X/*
X * disassembler output routines
X *
X */
X
Xstatic int am_code;	/* addressing mode code */
X
X#define	AM_NULL		0
X#define	AM_DD		1
X#define	AM_FD		2
X
X#define outop(s)	( outs(s), outs("\t") )
X
X#define	outn(out)	outval(getbyte(),out)
X
X#define	outnn(out)	outval(getword(),out)
X
Xstatic void outsp(s,sp)
Xchar *s;
Xchar *sp;
X{
X	char buf[5];	/* "(RR+" is the longest */
X	char *bp;
X
X	for(bp=buf;s<sp;)
X		*bp++=*s++;
X
X	*bp='\0';
X
X	outs(buf);
X}
X
X#define	outepu(s)	( \
X	outs(s), \
X	outn(OUT_EPU), \
X	outs(","), \
X	outn(OUT_EPU), \
X	outs(","), \
X	outn(OUT_EPU), \
X	outs(","), \
X	outn(OUT_EPU) \
X)
X
Xstatic char *tab_xr[]={
X
X/* AM_NULL */
X	"B",		"C",		"D",		"E",
X	"H",		"L",		"(HL)",		"A",
X
X/* AM_DD */
X	"(SP+dd)",	"(HL+IX)",	"(HL+IY)",	"(IX+IY)",
X	"IXH",		"IXL",		"(IX+d)",	"(nn)",
X
X/* AM_FD */
X	"(PC+dd)",	"(IX+dd)",	"(IY+dd)",	"(HL+dd)",
X	"IYH",		"IYL",		"(IY+d)",	"n"
X
X};
X
X#define outxr(xr)	expand(tab_xr[am_code*8+(xr)])
X#define outr(r)		outs(tab_xr[(r)])
X#define outir(ir)	( (4<=(ir) && (ir)<=6) ? outxr(ir) : outr(ir) )
X#define outim()		outxr(6)
X
Xstatic char *tab_xrp[]={
X
X/* AM_NULL */
X	"BC",		"DE",		"HL",		"SP",
X
X/* AM_DD*/
X	"(HL)",		"(nn)",		"IX",		"(PC+dd)",
X
X/* AM_FD */
X	"(IX+dd)",	"(IY+dd)",	"IY",		"nn"
X
X};
X
X#define outxrp(xrp)	expand(tab_xrp[am_code*4+(xrp)])
X
X#define outprp(prp)	( (am_code==AM_NULL && (prp)==3) ? outs("AF") \
X							 : outxrp(prp) \
X			)
X
X#define outrp(rp)	outs(tab_xrp[(rp)])
X
Xstatic char *tab_irp[]={
X
X/* AM_NULL */
X	"BC",		"DE",		"HL",		"SP",
X
X/* AM_DD */
X	"BC",		"DE",		"IX",		"SP",
X
X/* AM_FD */
X	"BC",		"DE",		"IY",		"SP"
X
X};
X
X#define outirp(irp)	outs(tab_irp[am_code*4+(irp)])
X#define outihl()	outirp(2)
X
X#ifdef Z280
X
Xstatic char *tab_ea[]={
X	"(SP+dd)",	"(HL+IX)",	"(HL+IY)",	"(IX+IY)",
X	"(PC+dd)",	"(IX+dd)",	"(IY+dd)",	"(HL+dd)"
X};
X
X#define	outea(ea)	expand(tab_ea[(ea)])
X
X#endif
X
Xstatic char *tab_cc[]={
X#ifdef Z280
X	"NZ",	"Z",	"NC",	"C",	"NV",	"V",	"P",	"M"
X#else
X	"NZ",	"Z",	"NC",	"C",	"PO",	"PE",	"P",	"M"
X#endif
X};
X
X#define	outcc(cc)	outs(tab_cc[(cc)])
X
X#ifdef Z280
X#define	W	"W"
X#else
X#define	W	/*empty*/
X#endif
X
Xstatic char *tab_op1[]={
X	"ADD",	"ADC",	"SUB",	"SBC",	"AND",	"XOR",	"OR",	"CP"
X};
X
X#define	outop1(op)	outop(tab_op1[((op)>>3)&0x07])
X
X#ifdef Z80
X
Xstatic char *tab_a[]={
X	"A,",	"A,",	"",	"A,",	"",	"",	"",	""
X};
X
X#define outa(op)	outs(tab_a[((op)>>3)&0x07])
X
X#else /* Z280 */
X
X#define	outa(op)	outs("A,")
X
X#endif /* Z80 */
X
Xstatic char *tab_op2[]={
X	"RLCA",	"RRCA",	"RLA",	"RRA",	"DAA",	"CPL",	"SCF",	"CCF"
X};
X
X#define	outop2(op)	outop(tab_op2[((op)>>3)&0x07])
X
Xstatic void outjrt(len)
Xint len;
X{
X	word disp = getbyte();
X
X	if(disp>=0x80)
X		disp+=-0x100;	/* cryptic but portable */
X
X	outval(len+disp,OUT_JR);
X}
X
Xstatic void outjpt(out)
Xint out;
X{
X	switch(am_code) {
X
X	case AM_NULL:
X		outnn(out);
X		break;
X
X	case AM_DD:
X		outs("(HL)");
X		break;
X
X	case AM_FD:
X		outnn(OUT_PC);
X		break;
X
X	}
X}
X
Xstatic void expand(s)
Xchar *s;
X{
X	char *sp;
X
X	if (strcmp(s,"(PC+dd)")==0) {
X		outnn(OUT_PC);
X	} else if ((sp=strchr(s,'n'))!=NULL) {
X		if(sp[1]=='n') { /* nn */
X			outsp(s,sp);
X			outnn(OUT_NN);
X			outs(sp+2);
X		} else { /* n */
X			outsp(s,sp);
X			outn(OUT_N);
X			outs(sp+1);
X		}
X	} else if ((sp=strchr(s,'+'))!=NULL && sp[1]=='d') {
X		if(sp[2]=='d') { /* +dd */
X			outsp(s,sp);
X			outnn(OUT_DD);
X			outs(sp+3);
X		} else { /* +d */
X			outsp(s,sp);
X			outn(OUT_D);
X			outs(sp+2);
X		}
X	} else
X		outs(s);
X}
X
X/*
X * disassembler functions
X *
X */
X
Xint jumped;	/* unconditional JR, JP, RET flag */
X
Xint dis(bytes)
Xbyte *bytes;
X{
X	word op;
X
X	getptr=bytes;
X	am_code=AM_NULL;
X	jumped=0;
X
Xdis_op:
X	op=getbyte();
X
X	switch (op&0xC0) {
X
X	case 0x00:
X		switch (op&0xC7) {
X
X		case 0x00:
X			switch (am_code) {
X
X			case AM_NULL:
X				if (op==0x00)
X					outs("NOP");
X				else if (op==0x08) {
X					outop("EX");
X					outs("AF,AF'");
X				} else {
X					outop( (op==0x10) ? "DJNZ" : "JR" );
X					if( op>=0x20 ) {
X						outcc((op>>3)&0x03);
X						outs(",");
X					}
X					outjrt(2);
X					if(op==0x18)
X						jumped=1;
X				}
X				break;
X
X			case AM_DD:
X#ifdef Z280
X				if ((op&0x37)==0x20) {
X					outop( (op==0x20) ? "JAR" : "JAF" );
X					outjrt(3);
X					break;
X				}
X#endif
X				/* fall-trough */
X
X			case AM_FD:
X				outs("?");
X
X			}
X			break;
X
X		case 0x01:
X			if (op&0x08) {
X				outop("ADD");
X				outihl();
X				outs(",");
X				outirp((op>>4)&0x03);
X#ifdef Z280
X			} else if(am_code!=AM_FD || op==0x21) {
X#else
X			} else if(am_code==AM_NULL || op==0x21) {
X#endif
X				outop("LD"W);
X				outxrp((op>>4)&0x03);
X				outs(",");
X				outnn(OUT_NN);
X			} else
X				outs("?");
X			break;
X
X		case 0x02:
X			if ((op&0x37)==0x22) {
X				outop("LD"W);
X				if (op==0x22) {
X					outs("(");
X					outnn(OUT_NN);
X					outs("),");
X					outihl();
X				} else {
X					outihl();
X					outs(",(");
X					outnn(OUT_NN);
X					outs(")");
X				}
X			} else if (am_code==AM_NULL) {
X				static char *tab[]={
X					"(BC),A",	"A,(BC)",
X					"(DE),A",	"A,(DE)",
X					NULL,		NULL,
X					"(nn),A",	"A,(nn)"
X				};
X				outop("LD");
X				expand(tab[(op>>3)&0x07]);
X			} else
X				outs("?");
X			break;
X
X		case 0x03:
X#ifdef Z280
X			if(am_code!=AM_FD || op<0x30) {
X#else
X			if(am_code==AM_NULL || (op&0x37)==0x23) {
X#endif
X				outop( (op&0x08) ? "DEC"W : "INC"W );
X				outxrp((op>>4)&0x03);
X			} else
X				outs("?");
X			break;
X
X		case 0x04:
X#ifdef Z280
X			if(am_code!=AM_FD || op!=0x3C) {
X#else
X			if(am_code==AM_NULL || op==0x34) {
X#endif
X				outop("INC");
X				outxr((op>>3)&0x07);
X			} else
X				outs("?");
X			break;
X
X		case 0x05:
X#ifdef Z280
X			if(am_code!=AM_FD || op!=0x3D) {
X#else
X			if(am_code==AM_NULL || op==0x35) {
X#endif
X				outop("DEC");
X				outxr((op>>3)&0x07);
X			} else
X				outs("?");
X			break;
X
X		case 0x06:
X#ifdef Z280
X			if(am_code!=AM_FD || op!=0x3E) {
X#else
X			if(am_code==AM_NULL || op==0x36) {
X#endif
X				outop("LD");
X				outxr((op>>3)&0x07);
X				outs(",");
X				outn(OUT_N);
X			} else
X				outs("?");
X			break;
X
X		case 0x07:
X			if (am_code==AM_NULL) {
X				outop2(op);
X#ifdef Z280
X				if(op==0x2F)
X					outs("A");
X#endif
X			} else
X				outs("?");
X			break;
X		}
X		break;
X
X	case 0x40:
X		if ( op==0x76 )
X			if (am_code==AM_NULL)
X				outs("HALT");
X			else
X				outs("?");
X#ifdef Z280
X		else if ( am_code==AM_NULL || op>=0x60 && op!=0x7F ||
X			0x04<=(op&0x07) && (op&0x07)<=0x06 )
X#else
X		else if ( am_code==AM_NULL || (op&0xF8)==0x70 ||
X				(op&0x07)==0x06 )
X#endif
X		{
X			outop("LD");
X			if (op==0x66 || op==0x6E)
X				outr((op>>3)&0x07);
X			else
X				outir((op>>3)&0x07);
X			outs(",");
X			if (op==0x74 || op==0x75 )
X				outr(op&0x07);
X			else if (op>=0x78)
X				outxr(op&0x07);
X			else
X				outir(op&0x07);
X		} else
X			outs("?");
X		break;
X
X	case 0x80:
X#ifdef Z280
X		if(am_code!=AM_FD || (op&0x07)!=0x07) {
X#else
X		if(am_code==AM_NULL || (op&0x07)==0x06) {
X#endif
X			outop1(op);
X			outa(op);
X			outxr(op&0x07);
X		} else
X			outs("?");
X		break;
X
X	case 0xC0:
X		switch (op&0xC7) {
X
X		case 0xC0:
X			if (am_code==AM_NULL) {
X				outop("RET");
X				outcc((op>>3)&0x07);
X			} else
X				outs("?");
X			break;
X
X		case 0xC1:
X			if ((op&0xEF)!=0xC9 || am_code==AM_NULL) {
X				if (op&0x08) {
X        				if (op==0xC9) {
X						outs("RET");
X        					jumped=1;
X        				} else if (op==0xD9)
X        					outop("EXX");
X	        			else if (op==0xE9) {
X        					outop("JP");
X						outs("(");
X        					outihl();
X						outs(")");
X						jumped=1;
X	        			} else {
X        					outop("LD"W);
X        					outs("SP,");
X        					outihl();
X        				}
X#ifdef Z280
X				} else if(am_code!=AM_FD || op==0xE1) {
X#else
X				} else if(am_code==AM_NULL || op==0xE1) {
X#endif
X					outop("POP");
X					outprp((op>>4)&0x03);
X				} else
X					outs("?");
X			} else
X				outs("?");
X			break;
X
X		case 0xC2:
X#ifdef Z80
X			if(am_code==AM_NULL) {
X#endif
X				outop("JP");
X				outcc((op>>3)&0x07);
X				outs(",");
X				outjpt(OUT_JP);
X#ifdef Z80
X			} else
X				outs("?");
X#endif
X			break;
X
X		case 0xC3:
X			switch (op) {
X
X			case 0xC3:
X#ifdef Z280
X				if(am_code!=AM_DD) {
X#else
X				if(am_code==NULL) {
X#endif
X					outop("JP");
X					outjpt(OUT_JP);
X					jumped=1;
X				} else
X					outs("?");
X				break;
X
X			case 0xCB:
X				dis_CB();
X				break;
X
X			case 0xD3:
X				if (am_code==AM_NULL) {
X					outop("OUT");
X					outs("(");
X					outn(OUT_OUTP);
X					outs("),A");
X				} else
X					outs("?");
X				break;
X
X			case 0xDB:
X				if (am_code==AM_NULL) {
X					outop("IN");
X					outs("A,(");
X					outn(OUT_INP);
X					outs(")");
X				} else
X					outs("?");
X				break;
X
X
X			case 0xE3:
X				outop("EX");
X				outs("(SP),");
X				outihl();
X				break;
X
X			case 0xEB:
X#ifdef Z280
X				outop("EX");
X				if (am_code==AM_NULL)
X					outs("DE");
X				else
X					outihl();
X				outs(",HL");
X#else /* Z80 */
X				if(am_code==AM_NULL) {
X					outop("EX");
X					outs("DE,HL");
X				} else
X					outs("?");
X#endif /* Z280 */
X				break;
X
X			case 0xF3:
X				if (am_code==AM_NULL)
X					outs("DI");
X				else
X					outs("?");
X				break;
X
X			case 0xFB:
X				if (am_code==AM_NULL)
X					outs("EI");
X				else
X					outs("?");
X				break;
X
X			}
X			break;
X
X		case 0xC4:
X#ifdef Z80
X			if(am_code==NULL) {
X#endif
X				outop("CALL");
X				outcc((op>>3)&0x07);
X				outs(",");
X				outjpt(OUT_CALL);
X#ifdef Z80
X			} else
X				outs("?");
X#endif
X			break;
X
X		case 0xC5:
X#ifdef Z280
X			if (op&0x08) {
X#else
X			if ((op&0x08) && am_code==AM_NULL) {
X#endif
X				if (op==0xCD) {
X					outop("CALL");
X					outjpt(OUT_CALL);
X				} else if (op==0xED) {
X					dis_ED();
X				} else {
X					if(am_code==AM_NULL) {
X						if (op==0xDD)
X							am_code=AM_DD;
X						else
X							am_code=AM_FD;
X						goto dis_op;
X					} else
X						outs("?");
X				}
X#ifdef Z280
X			} else if (am_code!=AM_FD || op>=0xE0) {
X#else
X			} else if (am_code==AM_NULL || op==0xE5) {
X#endif
X				outop("PUSH");
X				outprp((op>>4)&0x03);
X			} else
X				outs("?");
X			break;
X
X		case 0xC6:
X			if (am_code==AM_NULL) {
X				outop1(op);
X				outa(op);
X				outn(OUT_N);
X			} else
X				outs("?");
X			break;
X
X		case 0xC7:
X			if (am_code==AM_NULL) {
X				outop("RST");
X				outval(op&0x38,OUT_RST);
X			} else
X				outs("?");
X			break;
X
X		}
X		break;
X
X	}
X	return(getptr-bytes);
X}
X
Xstatic char *tab_CB1[]={
X	"RLC",	"RRC",	"RL",	"RR",	"SLA",	"SRA",	"TSET",	"SRL"
X};
X
Xstatic char *tab_CB2[]={
X	NULL,	"BIT",	"RES",	"SET"
X};
X
Xstatic void dis_CB()
X{
X	word op, off;
X	char bit[2];
X
X	if (am_code==AM_NULL)
X		op=getbyte();
X	else {
X		off=getbyte();
X		op=getbyte();
X		if ((op&0x07)!=6) {
X			outs("?");
X			return;
X		}
X	}
X
X#ifdef Z80
X	if ((op&0xF8)==0x30) {
X		outs("?");
X		return;
X	}
X#endif
X
X	if ((op&0xC0)==0x00)
X		outop(tab_CB1[op>>3]);
X	else {
X		outop(tab_CB2[op>>6]);
X		bit[0]='0'+((op>>3)&0x07);
X		bit[1]='\0';
X		outs(bit);
X		outs(",");
X	}
X
X	if (am_code==AM_NULL)
X		outr(op&0x07);
X	else {
X		outs("(");
X		outihl();
X		outval(off,OUT_D);
X		outs(")");
X	}
X}
X
Xstatic void dis_ED()
X{
X	word op;
X
X	op=getbyte();
X
X	switch (op&0xC7) {
X
X#ifdef Z280
X
X	case 0x02:
X		outop("LDA");
X		outihl();
X		outs(",");
X		outea((op>>3)&0x07);
X		break;
X
X	case 0x03:
X		if (am_code==AM_NULL) {
X			outop("LD");
X			outea((op>>3)&0x07);
X			outs(",A");
X		} else
X			outs("?");
X		break;
X
X	case 0x04:
X		outop("LD"W);
X		outihl();
X		outs(",");
X		outea((op>>3)&0x07);
X		break;
X
X	case 0x05:
X		outop("LD"W);
X		outea((op>>3)&0x07);
X		outs(",");
X		outihl();
X		break;
X
X	case 0x06:
X		if (op&0x08) {
X			outop("LD"W);
X			outrp((op>>4)&0x03);
X			outs(",");
X			outim();
X		} else {
X			outop("LD"W);
X			outim();
X			outs(",");
X			outrp((op>>4)&0x03);
X		}
X		break;
X
X	case 0x07:
X		if(am_code!=AM_FD || op!=0x3F) {
X			outop("EX");
X			outs("A,");
X			outxr((op>>3)&0x07);
X		} else
X			outs("?");
X		break;
X
X#endif /* Z280 */
X
X	case 0x40:
X		if (op==0x70) {
X			if (am_code==AM_NULL) {
X#ifdef Z280
X				outop("TSTI");
X				outs("(C)");
X#else /* Z80 */
X				outop("IN");
X				outs("F,(C)");
X#endif /* Z280 */
X			} else
X				outs("?");
X		} else if (am_code!=AM_FD || op!=0x78) {
X			outop("IN");
X			outxr((op>>3)&0x07);
X			outs(",(C)");
X		} else
X			outs("?");
X		break;
X
X	case 0x41:
X#ifdef Z280
X		if (op==0x71) {
X			if (am_code==AM_NULL) {
X				outop("SC");
X				outnn(OUT_NN);
X			} else
X				outs("?");
X		} else if (am_code!=AM_FD || op!=0x79) {
X#else /* Z80 */
X		if (am_code==AM_NULL && op!=0x71) {
X#endif /* Z280 */
X			outop("OUT");
X			outs("(C),");
X			outxr((op>>3)&0x07);
X		} else
X			outs("?");
X		break;
X
X	case 0x42:
X		outop( (op&0x08) ? "ADC" : "SBC" );
X		outihl();
X		outs(",");
X		outirp((op>>4)&0x03);
X		break;
X
X	case 0x43:
X		if (am_code==AM_NULL && (op&0xF7)!=0x63) {
X			if (op&0x08) {
X				outop("LD"W);
X				outrp((op>>4)&0x03);
X				outs(",(");
X				outnn(OUT_NN);
X				outs(")");
X			} else {
X  				outop("LD"W);
X				outs("(");
X				outnn(OUT_NN);
X				outs("),");
X				outrp((op>>4)&0x03);
X			}
X		} else
X			outs("?");
X		break;
X
X	case 0x44:
X#ifdef Z280
X		if (am_code==AM_NULL) {
X			switch (op) {
X
X			case 0x44:
X				outop("NEG");
X				outs("A");
X				break;
X
X			case 0x4C:
X				outop("NEG");
X				outs("HL");
X				break;
X
X			case 0x64:
X				outop("EXTS");
X				outs("A");
X				break;
X
X			case 0x6C:
X				outop("EXTS");
X				outs("HL");
X				break;
X
X			default:
X				outs("?");
X				break;
X			
X			}
X#else /* Z80 */
X		if (am_code==AM_NULL && op==0x44) {
X			outs("NEG");
X#endif /* Z280 */
X		} else
X			outs("?");
X		break;
X
X	case 0x45:
X#ifdef Z280
X		if (op==0x6D) {
X			outop("ADD");
X			outihl();
X			outs(",A");
X		} else {
X			if (am_code==AM_NULL) {
X				static char *tab[]={
X					"RETN",		"RETI",
X					"RETIL",	"?",
X					"PCACHE",	NULL,
X					"?",		"?"
X				};
X				outop(tab[(op>>3)&0x07]);
X			} else
X				outs("?");
X		}
X#else /* Z80 */
X		if (am_code==AM_NULL && op==0x45)
X			outs("RETN");
X		else if (am_code==AM_NULL && op==0x4D)
X			outs("RETI");
X		else
X			outs("?");
X#endif /* Z280 */
X		break;
X
X	case 0x46:
X#ifdef Z280
X		if (am_code==AM_NULL && op<0x60 ) {
X#else
X		if (am_code==AM_NULL && op<0x60 && op!=0x4E) {
X#endif
X			static char *tab[]={
X				"0",	"3",	"1",	"2"
X			};
X			outop("IM");
X			outs(tab[(op>>3)&0x07]);
X#ifdef Z280
X		} else if (op==0x66) {
X			outop("LDCTL");
X			outihl();
X			outs(",(C)");
X		} else if (op==0x6E) {
X			outop("LDCTL");
X			outs("(C),");
X			outihl();
X#endif /* Z280 */
X		} else
X			outs("?");
X		break;
X
X	case 0x47:
X#ifdef Z280
X		if (am_code==AM_NULL) {
X#else
X		if (am_code==AM_NULL && op<0x70) {
X#endif
X			static char *tab1[]={
X				"LD",	"LD",	"LD",	"LD",
X				"RRD",	"RLD",	"DI",	"EI"
X			};
X			static char *tab2[]={
X				"I,A",	"R,A",	"A,I",	"A,R",
X				"",	"",	"n",	"n"
X			};
X			outop(tab1[(op>>3)&0x07]);
X			expand(tab2[(op>>3)&0x07]);
X		} else
X			outs("?");
X		break;
X
X	case 0x80:
X		if (am_code==AM_NULL) {
X			static char *tab[]={
X				"?",	"?",	"?",	"?",
X				"LDI",	"LDD",	"LDIR",	"LDDR"
X			};
X			outop(tab[(op>>3)&0x07]);
X		} else
X			outs("?");
X		break;
X
X	case 0x81:
X		if (am_code==AM_NULL) {
X			static char *tab[]={
X				"?",	"?",	"?",	"?",
X				"CPI",	"CPD",	"CPIR",	"CPDR"
X			};
X			outop(tab[(op>>3)&0x07]);
X		} else
X			outs("?");
X		break;
X
X	case 0x82:
X		if (am_code==AM_NULL) {
X			static char *tab[]={
X#ifdef Z280
X				"INIW",		"INDW",
X				"INIRW",	"INDRW",
X#else
X				"?",		"?",
X				"?",		"?",
X#endif
X				"INI",		"IND",
X				"INIR",		"INDR"
X			};
X			outop(tab[(op>>3)&0x07]);
X		} else
X			outs("?");
X		break;
X
X	case 0x83:
X		if (am_code==AM_NULL) {
X			static char *tab[]={
X#ifdef Z280
X				"OUTIW",	"OUTDW",
X				"OTIRW",	"OTDRW",
X#else
X				"?",		"?",
X				"?",		"?",
X#endif
X				"OUTI",		"OUTD",
X				"OTIR",		"OTDR"
X			};
X			outop(tab[(op>>3)&0x07]);
X		} else
X			outs("?");
X		break;
X
X#ifdef Z280
X
X	case 0x84:
X	case 0x85:
X		if (am_code==AM_NULL) {
X			outop( ((op&0xC7)==0x84) ? "EPUM" : "MEPU" );
X			outea((op>>3)&0x07);
X			outepu(",");
X		} else
X			outs("?");
X		break;
X
X	case 0x86:
X		if (op<0xA0) {
X			outop( (op<0x90) ? "LDUD" : "LDUP" );
X			if (op&0x08) {
X				outim();
X				outs(",A");
X			} else {
X				outs("A,");
X				outim();
X			}
X		} else if (am_code==AM_NULL && (op&0xF7)==0xA6) {
X			outop( (op&0x08) ? "MEPU" : "EPUM" );
X			outs("(HL)");
X			outepu(",");
X		} else
X			outs("?");
X		break;
X
X	case 0x87:
X		switch (op) {
X
X		case 0x87:
X			outop("LDCTL");
X			outihl();
X			outs(",USP");
X			break;
X
X		case 0x8F:
X			outop("LDCTL");
X			outs("USP,");
X			outihl();
X			break;
X
X		case 0x97:
X		case 0x9F:
X			if (am_code==NULL) {
X				outop( (op==0x97) ? "EPUF" : "EPUI" );
X				outepu("");
X			} else
X				outs("?");
X			break;
X
X		case 0xA7:
X		case 0xAF:
X			if (am_code==NULL) {
X				outop( (op==0xA7) ? "EPUM" : "MEPU" );
X				outs("(");
X				outnn(OUT_NN);
X				outs(")");
X				outepu(",");
X			} else
X				outs("?");
X			break;
X
X		case 0xB7:
X			if (am_code==NULL) {
X				outop("INW");
X				outs("HL,(C)");
X			} else
X				outs("?");
X			break;
X
X		case 0xBF:
X			if (am_code==NULL) {
X				outop("OUTW");
X				outs("(C),HL");
X			} else
X				outs("?");
X			break;
X
X		}
X		break;
X
X	case 0xC0:
X		outop("MULT");
X		outs("A,");
X		outxr((op>>3)&0x07);
X		break;
X			
X	case 0xC1:
X		outop("MULTU");
X		outs("A,");
X		outxr((op>>3)&0x07);
X		break;
X
X	case 0xC2:
X		if (op&0x08) {
X			outop("DIVW");
X			outs("DEHL,");
X		} else {
X			outop("MULTW");
X			outs("HL,");
X		}
X		outxrp((op>>4)&0x03);
X		break;
X			
X	case 0xC3:
X		if (op&0x08) {
X			outop("DIVUW");
X			outs("DEHL,");
X		} else {
X			outop("MULTUW");
X			outs("HL,");
X		}
X		outxrp((op>>4)&0x03);
X		break;
X			
X	case 0xC4:
X		outop("DIV");
X		outs("HL,");
X		outxr((op>>3)&0x07);
X		break;
X			
X	case 0xC5:
X		outop("DIVU");
X		outs("HL,");
X		outxr((op>>3)&0x07);
X		break;
X			
X	case 0xC6:
X		outop( (op&0x08) ? "SUBW" : "ADDW" );
X		outs("HL,");
X		outxrp((op>>4)&0x03);
X		break;
X
X	case 0xC7:
X		if (am_code==AM_NULL && op==0xEF) {
X			outop("EX");
X			outs("H,L");
X		} else if (op&0x08)
X			outs("?");
X		else {
X			outop("CPW");
X			outs("HL,");
X			outxrp((op>>4)&0x03);
X		}
X		break;
X
X#endif /* Z280 */
X
X	default:
X		outs("?");
X		break;
X
X	}
X}
X
END_OF_dis.c
if test 18930 -ne `wc -c <dis.c`; then
    echo shar: \"dis.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dis.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dis.h\"
else
echo shar: Extracting \"dis.h\" \(1443 characters\)
sed "s/^X//" >dis.h <<'END_OF_dis.h'
X/*
X * dis.h - header file for generic Z80/Z280 disassembler
X *
X * Copyright 1989 by Luc Rooijakkers <lwj@cs.kun.nl>
X * Permission is hereby granted to use and modify this code for
X * non-commercial use, provided this copyright is retained.
X *
X */
X
X/*
X * type definitions
X *
X * word should be at least 16 bits unsigned,
X * byte should be at least 8 bits unsigned
X *
X */
X
Xtypedef unsigned int word;
Xtypedef unsigned int byte;
X
X/*
X * declarations
X *
X */
X
X#ifdef PROTO
X
Xextern int dis(byte *bytes);
Xextern int jumped;
X
Xextern void outs(char *s);
Xextern void outval(word value,int out);
X
Xextern void outsym(word value,int out);
Xextern void outhex(word value,int out,word addr);
Xextern void outdebug(word value,int out);
X
X#else /* !PROTO */
X
Xextern int dis();
Xextern int jumped;
X
Xextern void outs();
Xextern void outval();
X
Xextern void outsym();
Xextern void outhex();
Xextern void outdebug();
X
X#endif /* PROTO */
X
X/*
X * output kinds
X *
X */
X
X#define OUT_N		0	/* 8-bit operand */
X#define OUT_NN		1	/* 16-bit operand */
X#define OUT_D		2	/* 8-bit IX/IY offset */
X#define OUT_DD		3	/* 16-bit HL/SP/IX/IY offset */
X#define OUT_PC		4	/* 16-bit PC offset */
X#define OUT_INP		5	/* 8-bit input port */
X#define OUT_OUTP 	6	/* 8-bit output port */
X#define OUT_EPU		7	/* 8-bit EPU operand */
X#define OUT_JR		8	/* 16-bit JR offset */
X#define OUT_JP		9	/* 16-bit JP target */
X#define OUT_CALL	10	/* 16-bit CALL target */
X#define OUT_RST		11	/* 16-bit RST target */
X
END_OF_dis.h
if test 1443 -ne `wc -c <dis.h`; then
    echo shar: \"dis.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f disas.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"disas.c\"
else
echo shar: Extracting \"disas.c\" \(3384 characters\)
sed "s/^X//" >disas.c <<'END_OF_disas.c'
X/*
X * disas - simple Z80/Z280 disassembler
X *
X * Copyright 1989 by Luc Rooijakkers <lwj@cs.kun.nl>
X * Permission is hereby granted to use and modify this code for
X * non-commercial use, provided this copyright is retained.
X *
X * usage: disas file
X *
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <ctype.h>
X
X#include "dis.h"
X
X/*
X * change log
X *
X * ../../88	Created
X * 16/12/89	Fixed JR/JP address bug
X * 26/12/89	Cut down for public release
X *
X */
X
Xchar DisasId[] = "@(#) DISAS 26/12/89";
X
X/*
X *	0	0	1	2	3	4	4	5
X * 	0.......8.......6.......4.......2.......0.......8.......6
X *
X * 	XXXX xxxxxxxx+	CALL	(IX+XXH),XXH		....
X *
X */
X
X#define	OPCODE	16
X#define	OPERAND	24
X#define	ASCII	48
X
X/*
X * prototypes
X *
X */
X
X#ifdef PROTO
X
Xvoid main(int argc,char **argv);
Xint instr(word addr,byte *buf,int len);
Xvoid leader(word addr,byte *buf,int len);
Xvoid trailer(byte *buf,int len);
Xint get(byte *buf,int size,word addr);
Xvoid clear(void);
Xvoid outs(char *s);
Xvoid flush(void);
Xvoid tab(int pos);
Xvoid outval(word value,int out);
X
X#else /* !PROTO */
X
Xvoid main();
Xint instr();
Xvoid leader();
Xvoid trailer();
Xint get();
Xvoid clear();
Xvoid outs();
Xvoid flush();
Xvoid tab();
Xvoid outval();
X
X#endif /* PROTO */
X
X/*
X * variables
X *
X */
X
XFILE *file;
Xchar *name;
Xword address;
X
Xint col;
X
Xchar line[80];
Xchar *linep;
X
X/*
X * main function
X *
X */
X
Xvoid main(argc,argv)
Xint argc;
Xchar **argv;
X{
X	word addr;
X	int len;
X	byte buf[16];
X
X	if(argc!=2) {
X		fprintf(stderr,"Usage: disas file\n");
X		exit(1);
X	}
X
X	name=argv[1];
X
X	if((file=fopen(name,"rb"))==NULL) {
X		perror(name);
X		exit(1);
X	}
X
X	for(addr=0x100;(len=get(buf,16,addr))>0;addr+=len) {
X		jumped=0;
X		len=instr(addr,buf,len);
X		if(jumped)
X			putchar('\n');
X	}
X
X	fclose(file);
X
X	exit(0);
X}
X
Xint instr(addr,buf,size)
Xword addr;
Xbyte *buf;
Xint size;
X{
X	int len;
X	char linebuf[80], *sep;
X
X	if(size<=0)
X		return(0);
X
X	linep=linebuf;
X	col=OPCODE;
X	address=addr;
X
X	len=dis(buf);
X
X	*linep='\0';
X
X	if(len>size) {
X		linep=linebuf;
X		col=OPCODE;
X
X		outs("DEFB\t");
X		for(sep="",len=0;len<size;len++) {
X			outs(sep);
X			outval(buf[len],OUT_N);
X			sep=",";
X		}
X
X		*linep='\0';
X	}
X
X	leader(addr,buf,len);
X	outs(linebuf);
X	trailer(buf,len);
X
X	return(len);
X}
X
Xvoid leader(addr,buf,len)
Xword addr;
Xbyte *buf;
Xint len;
X{
X	col=0;
X
X	col+=printf("%04X ",addr);
X
X	for(;len>0 && col+3<OPCODE;len--,buf++)
X		col+=printf("%02X",*buf);
X
X	if(len>0)
X		col+=printf("+");
X
X	clear();
X	tab(OPCODE);
X	flush();
X}
X
Xvoid trailer(buf,len)
Xbyte *buf;
Xint len;
X{
X	tab(ASCII);
X	flush();
X
X	for(;len>0;len--,buf++) {
X		if(isascii(*buf) && isprint(*buf))
X			putchar((char)(*buf));
X		else
X			putchar('.');
X		col++;
X	}
X
X	putchar('\n');
X}
X
Xint get(buf,size,addr)
Xbyte *buf;
Xint size;
Xword addr;
X{
X	char getbuf[16];
X	int len,i;
X
X	if(fseek(file,(long)addr-0x100,0)!=0) {
X		fprintf(stderr,"%s: Can't seek to address %04X\n",name,addr);
X		exit(1);
X	}
X
X	len=fread(getbuf,1,size,file);
X
X	for(i=0;i<len;i++)
X		buf[i]=(getbuf[i]&0xFF);
X
X	return(len);
X}
X
Xvoid clear()
X{
X	linep=line;
X}
X
Xvoid outs(s)
Xchar *s;
X{
X	while(*s) {
X		if(*s=='\t')
X			col=(col+8)&~7;
X		else
X			col++;
X		*linep++=*s++;
X	}
X}
X
Xvoid flush()
X{
X	*linep='\0';
X	fputs(line,stdout);
X	linep=line;
X}
X
Xvoid tab(pos)
Xint pos;
X{
X	while(((col+8)&~7)<=pos) {
X		*linep++='\t';
X		col=(col+8)&~7;
X	}
X
X	while(col<pos) {
X		*linep++=' ';
X		col++;
X	}
X}
X
Xvoid outval(value,out)
Xword value;
Xint out;
X{
X	outhex(value,out,address);
X}
X
END_OF_disas.c
if test 3384 -ne `wc -c <disas.c`; then
    echo shar: \"disas.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f oplist.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"oplist.c\"
else
echo shar: Extracting \"oplist.c\" \(2465 characters\)
sed "s/^X//" >oplist.c <<'END_OF_oplist.c'
X/*
X * oplist - generate opcode list for Z80/Z280 disassembler
X *
X * Copyright 1989 by Luc Rooijakkers <lwj@cs.kun.nl>
X * Permission is hereby granted to use and modify this code for
X * non-commercial use, provided this copyright is retained.
X *
X * Usage: oplist [-] [byte...]
X *
X */
X
X#include <stdio.h>
X#include <string.h>
X#include <stdlib.h>
X
X#include "dis.h"
X
X/*
X * change log
X *
X * 23/12/89	Split off from dis.c
X * 26/12/89	Added debugging option
X *
X */
X
Xchar OpListId[] = "@(#) OPLIST 26/12/89";
X
X/*
X * prototypes
X *
X */
X
X#ifdef PROTO
X
Xvoid list(int nbytes,byte *bytes);
Xint outins(int nbytes,byte *bytes);
X
X#else /* !PROTO*/
X
Xvoid list();
Xint outins();
X
X#endif /* PROTO */
X
X/*
X * variables
X *
X */
X
Xint debug;
Xchar outbuf[50];
Xchar *outbufp;
X
X/*
X * main program
X *
X */
X
Xvoid main(argc,argv)
Xint argc;
Xchar **argv;
X{
X	byte bytes[10];
X	int i,arg,nbytes = 0;
X
X	for(i=1;i<argc;i++) {
X		if(strcmp(argv[i],"-")==0) {
X			debug=1;
X			continue;
X		}
X		if(sscanf(argv[i],"%x",&arg)!=1 || arg<0 || arg>255) {
X			fprintf(stderr,"\nUsage: oplist [-] [byte...]\n");
X			exit(1);
X		}
X		bytes[nbytes++]=arg;
X	}
X
X	list(nbytes,bytes);
X
X	exit(0);
X}
X
X/*
X * generate opcode list
X *
X */
X
Xvoid list(nbytes,bytes)
Xint nbytes;
Xbyte *bytes;
X{
X	int special,len,i;
X	word op;
X
X	for(i=0;i<nbytes;i++)
X		printf("%02X ",bytes[i]);
X
X	printf("XX opcodes\n\n");
X
X	special=(nbytes==2 && (bytes[0]==0xDD || bytes[0]==0xFD)
X			   && bytes[1]==0xCB
X		);
X
X	for(op=0x00;op<=0xFF;op++) {
X
X		bytes[nbytes+special]=op;
X
X		outbufp=outbuf;
X		len=outins(nbytes,bytes);
X		*outbufp='\0';
X
X		for(i=0;i<len && i<7;i++) {
X			if(i<nbytes || i==nbytes+special)
X				printf("%02X",bytes[i]);
X			else
X				printf("**");
X		}
X
X		if(len>7) {
X			printf("+ ");
X			i++;
X		}
X
X		for(;i<8;i++)
X			printf("  ");
X
X		printf("%s\n",outbuf);
X        }
X}
X
X/*
X * output an instruction
X *
X */
X
Xint outins(nbytes,bytes)
Xint nbytes;
Xbyte *bytes;
X{
X	/* make sure things like "CB" and "DD ED" do not come out funny */
X
X	if ( nbytes==0 || ( bytes[0]==0xDD || bytes[0]==0xFD ) ) {
X		if ( nbytes<2 &&
X		     ( bytes[nbytes]==0xCB || bytes[nbytes]==0xDD ||
X		       bytes[nbytes]==0xED || bytes[nbytes]==0xFD ) )
X		{
X			outs("?");
X			return(nbytes+1);
X		}
X	}
X
X	return(dis(bytes));
X}
X
X/*
X * output a string
X *
X */
X
Xvoid outs(s)
Xchar *s;
X{
X	while(*s)
X		*outbufp++=*s++;
X}
X
X/*
X * output a value
X *
X */
X
Xvoid outval(value,out)
Xword value;
Xint out;
X{
X	if(debug)
X		outdebug(value,out);
X	else if(out==OUT_EPU)
X		outbufp--;
X	else
X		outsym(value,out);
X}
X
END_OF_oplist.c
if test 2465 -ne `wc -c <oplist.c`; then
    echo shar: \"oplist.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f optab.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"optab.c\"
else
echo shar: Extracting \"optab.c\" \(3694 characters\)
sed "s/^X//" >optab.c <<'END_OF_optab.c'
X/*
X * optab - generate opcode table for Z80/Z280 disassembler
X *
X * Copyright 1989 by Luc Rooijakkers <lwj@cs.kun.nl>
X * Permission is hereby granted to use and modify this code for
X * non-commercial use, provided this copyright is retained.
X *
X * Usage: optab [-] [byte...]
X *
X */
X
X#include <stdio.h>
X#include <string.h>
X#include <stdlib.h>
X
X#include "dis.h"
X
X/*
X * change log
X *
X * 23/12/89	Split off from dis.c
X * 26/12/89	Added debugging option
X *
X */
X
Xchar OpTabId[] = "@(#) OPTAB 26/12/89";
X
X/*
X * graphic characters
X *
X */
X
X#ifdef __MSDOS__
X
X/* Only MS-DOS has those nice graphic characters... */
X
X#define CH_B3		0xB3
X#define CH_B6		0xB6
X#define CH_BA		0xBA
X#define CH_BB		0xBB
X#define CH_BC		0xBC
X#define CH_C4		0xC4
X#define CH_C5		0xC5
X#define CH_C7		0xC7
X#define CH_C8		0xC8
X#define CH_C9		0xC9
X#define CH_CD		0xCD
X#define CH_CF		0xCF
X#define CH_D1		0xD1
X
X#else /* !__MSDOS__ */
X
X#define CH_B3		'|'
X#define CH_B6		'+'
X#define CH_BA		'|'
X#define CH_BB		'+'
X#define CH_BC		'+'
X#define CH_C4		'-'
X#define CH_C5		'+'
X#define CH_C7		'+'
X#define CH_C8		'+'
X#define CH_C9		'+'
X#define CH_CD		'-'
X#define CH_CF		'+'
X#define CH_D1		'+'
X
X#endif /* __MSDOS__ */
X
X/*
X * prototypes
X *
X */
X
X#ifdef PROTO
X
Xvoid tab(int nbytes,byte *bytes);
Xint outins(int nbytes,byte *bytes);
X
X#else /* !PROTO*/
X
Xvoid tab();
Xint outins();
X
X#endif /* PROTO */
X
X/*
X * variables
X *
X */
X
Xint debug;
Xchar outbuf[50];
Xchar *outbufp;
X
X/*
X * main program
X *
X */
X
Xvoid main(argc,argv)
Xint argc;
Xchar **argv;
X{
X	byte bytes[10];
X	int i,arg,nbytes = 0;
X
X	for(i=1;i<argc;i++) {
X		if(strcmp(argv[i],"-")==0) {
X			debug=1;
X			continue;
X		}
X		if(sscanf(argv[i],"%x",&arg)!=1 || arg<0 || arg>255) {
X			fprintf(stderr,"\nUsage: optab [-] [byte...]\n");
X			exit(1);
X		}
X		bytes[nbytes++]=arg;
X	}
X
X	tab(nbytes,bytes);
X
X	exit(0);
X}
X
X/*
X * generate opcode table
X *
X */
X
Xvoid tab(nbytes,bytes)
Xint nbytes;
Xbyte *bytes;
X{
X	char line[200],dline[200];
X	int special,i,row,col;
X	word op;
X
X	for(i=0;i<nbytes;i++)
X		printf("%02X ",bytes[i]);
X
X	printf("XX opcodes\n\n");
X
X	special=(nbytes==2 && (bytes[0]==0xDD || bytes[0]==0xFD)
X			   && bytes[1]==0xCB
X		);
X
X	memset(line,CH_C4,200);
X	memset(dline,CH_CD,200);
X
X	printf("%c%.6s",CH_C9,dline);
X	for(col=0;col<=7;col++)
X		printf("%c%.18s",CH_D1,dline);
X	printf("%c\n",CH_BB);
X
X	printf("%c%6s",CH_BA,"");
X	for(col=0;col<=7;col++)
X		printf("%c%7s%X/%X%8s",CH_B3,"",col,col+0x08,"");
X	printf("%c\n",CH_BA);
X
X	printf("%c%.6s",CH_C7,line);
X	for(col=0;col<=7;col++)
X		printf("%c%.18s",CH_C5,line);
X	printf("%c\n",CH_B6);
X
X	for(row=0x00;row<=0xF8;row+=0x08) {
X
X		if ((row&0x08)==0)
X			printf("%c%2s%02X%2s",CH_BA,"",row,"");
X		else
X			printf("%c%6s",CH_BA,"");
X
X		for(col=0;col<=7;col++) {
X			op=row|col;
X
X			bytes[nbytes+special]=op;
X
X			outbufp=outbuf;
X			outins(nbytes,bytes);
X			*outbufp='\0';
X
X			printf("%c %-17.17s",CH_B3,outbuf);
X        	}
X		printf("%c\n",CH_BA);
X        }
X
X	printf("%c%.6s",CH_C8,dline);
X	for(col=0;col<=7;col++)
X		printf("%c%.18s",CH_CF,dline);
X	printf("%c\n",CH_BC);
X}
X
X/*
X * output an instruction
X *
X */
X
Xint outins(nbytes,bytes)
Xint nbytes;
Xbyte *bytes;
X{
X	/* make sure things like "CB" and "DD ED" do not come out funny */
X
X	if ( nbytes==0 || ( bytes[0]==0xDD || bytes[0]==0xFD ) ) {
X		if ( nbytes<2 &&
X		     ( bytes[nbytes]==0xCB || bytes[nbytes]==0xDD ||
X		       bytes[nbytes]==0xED || bytes[nbytes]==0xFD ) )
X		{
X			outs("?");
X			return(nbytes+1);
X		}
X	}
X
X	return(dis(bytes));
X}
X
X/*
X * output a string
X *
X */
X
Xvoid outs(s)
Xchar *s;
X{
X	for(;*s!='\0';s++)
X		*outbufp++= (*s=='\t') ? ' ' : *s;
X}
X
X/*
X * output a value
X *
X */
X
Xvoid outval(value,out)
Xword value;
Xint out;
X{
X	if(debug)
X		outdebug(value,out);
X	else if(out==OUT_EPU)
X		outbufp--;
X	else
X		outsym(value,out);
X}
X
END_OF_optab.c
if test 3694 -ne `wc -c <optab.c`; then
    echo shar: \"optab.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f outdebug.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"outdebug.c\"
else
echo shar: Extracting \"outdebug.c\" \(1130 characters\)
sed "s/^X//" >outdebug.c <<'END_OF_outdebug.c'
X/*
X * outdebug - debugging output routine for Z80/Z280 disassembler
X *
X * Copyright 1989 by Luc Rooijakkers <lwj@cs.kun.nl>
X * Permission is hereby granted to use and modify this code for
X * non-commercial use, provided this copyright is retained.
X *
X */
X
X#include <stdio.h>
X
X#include "dis.h"
X
X/*
X * change log
X *
X * 23/12/89	Split off from dis.c
X *
X */
X
Xchar OutDebugId[] = "@(#) OUTDEBUG 23/12/89";
X
X/*
X * debugging output routine
X *
X */
X
Xvoid outdebug(value,out)
Xword value;
Xint out;
X{
X	char buf[4]; /* xxH is the longest */
X	char *str;
X
X	switch(out) {
X
X	case OUT_N:
X		str="n";
X		break;
X
X	case OUT_NN:
X		str="nn";
X		break;
X
X	case OUT_D:
X		str="+d";
X		break;
X
X	case OUT_DD:
X		str="+dd";
X		break;
X
X	case OUT_PC:
X		str="pc";
X		break;
X
X	case OUT_INP:
X		str="in";
X		break;
X
X	case OUT_OUTP:
X		str="out";
X		break;
X
X	case OUT_EPU:
X		str="epu";
X		break;
X
X	case OUT_JR:
X		str="jr";
X		break;
X
X	case OUT_JP:
X		str="jp";
X		break;
X
X	case OUT_CALL:
X		str="call";
X		break;
X
X	case OUT_RST:
X		if(value<0x10)
X			sprintf(buf,"%X",value);
X		else
X			sprintf(buf,"%02XH",value);
X		str=buf;
X		break;
X
X	default:
X		str="?";
X		break;
X	}
X
X	outs(str);
X}
X
X
END_OF_outdebug.c
if test 1130 -ne `wc -c <outdebug.c`; then
    echo shar: \"outdebug.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f outhex.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"outhex.c\"
else
echo shar: Extracting \"outhex.c\" \(1478 characters\)
sed "s/^X//" >outhex.c <<'END_OF_outhex.c'
X/*
X * outhex - hexadecimal output routine for Z80/Z280 disassembler
X *
X * Copyright 1989 by Luc Rooijakkers <lwj@cs.kun.nl>
X * Permission is hereby granted to use and modify this code for
X * non-commercial use, provided this copyright is retained.
X *
X */
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "dis.h"
X
X/*
X * change log
X *
X * 12/08/89	Split off from dis.c
X * 01/10/89	Split OUT_IO into OUT_INP, OUT_OUTP
X * 23/12/89	Cleaned up for public release
X *
X */
X
Xchar OutHexId[] = "@(#) OUTHEX 23/12/89";
X
X/*
X * hexadecimal output routine
X *
X */
X
Xvoid outhex(value,out,addr)
Xword value;
Xint out;
Xword addr;
X{
X	char buf[11]; /* (PC+xxxxH) is the longest */
X
X	switch(out) {
X
X	case OUT_N:
X	case OUT_INP:
X	case OUT_OUTP:
X	case OUT_EPU:
X		sprintf(buf,"%02XH",value);
X		break;
X
X	case OUT_NN:
X	case OUT_JP:
X	case OUT_CALL:
X		sprintf(buf,"%04XH",value);
X		break;
X
X	case OUT_D:
X		if(value<0x80)
X			sprintf(buf,"+%02XH",value);
X		else
X			sprintf(buf,"-%02XH",0x100-value);
X		break;
X
X	case OUT_DD:
X		if(value<0x8000)
X			sprintf(buf,"+%04XH",value);
X		else
X			sprintf(buf,"-%04XH",-value);
X		break;
X
X	case OUT_PC:
X		if(value<0x8000)
X			sprintf(buf,"(PC+%04XH)",value);
X		else
X			sprintf(buf,"(PC-%04XH)",-value);
X		break;
X
X	case OUT_JR:
X		sprintf(buf,"%04XH",addr+value);
X		break;
X
X	case OUT_RST:
X		if(value<0x10)
X			sprintf(buf,"%X",value);
X		else
X			sprintf(buf,"%02XH",value);
X		break;
X
X	default:
X		sprintf(buf,"?",value);
X		break;
X	}
X
X	if(isalpha(buf[0]))
X		outs("0");
X
X	outs(buf);
X}
X
END_OF_outhex.c
if test 1478 -ne `wc -c <outhex.c`; then
    echo shar: \"outhex.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f outsym.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"outsym.c\"
else
echo shar: Extracting \"outsym.c\" \(1011 characters\)
sed "s/^X//" >outsym.c <<'END_OF_outsym.c'
X/*
X * outsym - symbolic output routine for Z80/Z280 disassembler
X *
X * Copyright 1989 by Luc Rooijakkers <lwj@cs.kun.nl>
X * Permission is hereby granted to use and modify this code for
X * non-commercial use, provided this copyright is retained.
X *
X */
X
X#include <stdio.h>
X
X#include "dis.h"
X
X/*
X * change log
X *
X * 23/12/89	Split off from dis.c
X *
X */
X
Xchar OutSymId[] = "@(#) OUTSYM 23/12/89";
X
X/*
X * symbolic output routine
X *
X */
X
Xvoid outsym(value,out)
Xword value;
Xint out;
X{
X	char buf[4]; /* xxH is the longest */
X	char *str;
X
X	switch(out) {
X
X	case OUT_N:
X	case OUT_INP:
X	case OUT_OUTP:
X	case OUT_EPU:
X		str="n";
X		break;
X
X	case OUT_NN:
X	case OUT_JP:
X	case OUT_CALL:
X		str="nn";
X		break;
X
X	case OUT_D:
X		str="+d";
X		break;
X
X	case OUT_DD:
X		str="+dd";
X		break;
X
X	case OUT_PC:
X		str="(PC+dd)";
X		break;
X
X	case OUT_JR:
X		str="$+d";
X		break;
X
X	case OUT_RST:
X		if(value<0x10)
X			sprintf(buf,"%X",value);
X		else
X			sprintf(buf,"%02XH",value);
X		str=buf;
X		break;
X
X	default:
X		str="?";
X		break;
X	}
X
X	outs(str);
X}
X
END_OF_outsym.c
if test 1011 -ne `wc -c <outsym.c`; then
    echo shar: \"outsym.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f stdlib.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"stdlib.h\"
else
echo shar: Extracting \"stdlib.h\" \(89 characters\)
sed "s/^X//" >stdlib.h <<'END_OF_stdlib.h'
X/*
X * stdlib.h - dummy <stdlib.h> to satisfy non-ANSI compilers
X *
X */
X
Xchar *strstr();
X
END_OF_stdlib.h
if test 89 -ne `wc -c <stdlib.h`; then
    echo shar: \"stdlib.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 1 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--
Luc Rooijakkers                                 Internet: lwj@cs.kun.nl
Faculty of Mathematics and Computer Science     UUCP: uunet!cs.kun.nl!lwj
University of Nijmegen, the Netherlands         tel. +3180612271