Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10 Apollo 4/24/84; site apollo.uucp Path: utzoo!linus!decvax!wivax!apollo!rees From: rees@apollo.UUCP Newsgroups: net.sources Subject: Z-80 disassembler Message-ID: <207831a1.1147@apollo.uucp> Date: Tue, 10-Jul-84 15:20:18 EDT Article-I.D.: apollo.207831a1.1147 Posted: Tue Jul 10 15:20:18 1984 Date-Received: Thu, 12-Jul-84 01:10:44 EDT Organization: Apollo Computer, Chelmsford, Mass. Lines: 394 # The rest of this file is a shell script which will extract: # Readme dis.c distab.c echo x - Readme cat >Readme <<'Godfather_Of_Soul' This is an el-cheapo Z-80 disassembler, written in C. I wrote it myself. No comments - tough. It expects to see an input file containing records of the form where and are two byte integers, least significant first, and there are bytes of data. There can be an arbitrary number of these records. There is some cruft in here for TRS-80 start addresses, in getbyte(). You can probably ignore it, but may want to take it out. If you give it a "-a" flag, it produces output suitable for input to a Z-80 assembler. Some of the Z-80 instructions are not supported. A special prize for anyone who adds these. Let me know if you find any use for this. Godfather_Of_Soul echo x - dis.c cat >dis.c <<'Godfather_Of_Soul' #include extern struct optab { short op_mask, op_val; char *op_op; } optab[], toptab[], ddoptab[], edoptab[], fdoptab[]; struct optab *xopt[] = { toptab, ddoptab, edoptab, fdoptab, }; char *f1_op[] = { "add\ta,", "adc\ta,", "sub\t", "sbc\ta,", "and\t", "xor\t", "or\t", "cp\t" }; char *rnam[] = { "b", "c", "d", "e", "h", "l", "(hl)", "a" }; char *ssnam[] = { "bc", "de", "hl", "sp" }; char *qqnam[] = { "bc", "de", "hl", "af" }; char *cctab[] = { "nz", "z", "nc", "c", "po", "pe", "p", "m" }; int adr; char text[64]; int hexcol; int startadr= -1; int aflg; main(ac,av) int ac; char *av[]; { FILE *in; int c,i; int f0,f1,f2; struct optab *opp; char sbuf[32]; while (ac > 1 && av[1][0] == '-') { switch (av[1][1]) { case 'a': aflg = 1; break; } ac--; av++; } if (ac > 1) { if ((in = fopen(av[1], "r")) == NULL) { perror(av[1]); exit(1); } } else in = stdin; while ((c = getbyte(in)) != EOF) { if (aflg) strcpy(text, "\t"); else { sprintf(text, "%.4x \t", adr-1); hexcol = 5; addhex(c); } docode(c, optab, in, text); printf("%s\n", text); } if (!aflg) printf("%.4x ", adr); printf("\tend", adr); if (startadr != -1) { sphexno(sbuf, "\t%s", startadr); printf(sbuf); } printf("\n"); exit(0); } docode(c, opp, in, text) int c; struct optab *opp; FILE *in; char *text; { for (; opp->op_mask != 0; opp++) if ((c&opp->op_mask) == opp->op_val) break; expand(c, opp->op_op, in, text); } expand(c, op, in, text) int c; char *op, *text; FILE *in; { int i,j; char *s,sbuf[32]; for (s=op; *s; s++) { sbuf[0] = '\0'; switch (*s) { case 'B': i = getbyte(in); addhex(i); sphexno(sbuf, "%s", i); break; case '-': /* Relative jump */ i = getbyte(in); addhex(i); if (i > 127) i -= 256; i += adr; sphexno(sbuf, "%s", i); break; case 'W': addhex(i = getbyte(in)); addhex(j = getbyte(in)); i = i | (j << 8); sphexno(sbuf, "%s", i); break; case 'S': sprintf(sbuf, "%s", ssnam[(c>>4)&0x3]); break; case 'Q': sprintf(sbuf, "%s", qqnam[(c>>4)&0x3]); break; case 'P': sprintf(sbuf, "%s", rnam[(c>>3)&0x7]); break; case 'R': sprintf(sbuf, "%s", rnam[c&0x7]); break; case 'F': sprintf(sbuf, "%s", f1_op[(c>>3)&0x7]); break; case 'T': sprintf(sbuf, "%d", (c>>3)&0x7); break; case 'X': c = getbyte(in); addhex(c); docode(c, xopt[*(++s)-'0'], in, text); break; case 'K': strcpy(sbuf, (c&0x8) ? "d" : "i"); if (c & 0x10) strcat(sbuf, "r"); break; case 'C': sprintf(sbuf, "%s", cctab[(c>>3)&07]); break; default: sbuf[0] = *s; sbuf[1] = '\0'; break; } strcat(text, sbuf); } } addhex(x) int x; { if (aflg) return; addnib(x >> 4); addnib(x & 0xf); } addnib(x) int x; { x += '0'; if (x > '9') x += 'a' - '9' - 1; text[hexcol++] = x; } getbyte(f) FILE *f; { static int count; int i,oadr; char sbuf[32]; while (count == 0) { oadr = adr; if ((i = getint(f)) == EOF) return(EOF); adr = i; count = getint(f); if (adr == 0x40df && count == 2) { if ((startadr = getint(f)) == EOF) return(EOF); count = 0; adr = oadr; } else if (adr != oadr) { sphexno(sbuf, "%s", adr); if (!aflg) printf("%.4x ", oadr); printf("\torg\t%s\n", sbuf); } } adr++; count--; if ((i = getc(f)) == EOF) { printf("Premature EOF\n"); exit(1); } return(i); } getint(f) FILE *f; { int c,i; i = getc(f); if ((c = getc(f)) == EOF) return(EOF); else return(i | (c << 8)); } sphexno(s, sform, n) char *s, *sform; int n; { char sbuf[32], *xform; if (n < 0 || n > 0xffff) { fprintf(stderr, "sphexno(%d)\n", n); exit(1); } if (n <= 9) xform = "%d"; else if ((n > 0x10 && n <= 0x9f) || (n > 0x100 && n <= 0x9ff) || (n > 0x1000 && n <= 0x9fff)) xform = "%xh"; else xform = "0%xh"; sprintf(sbuf, xform, n); sprintf(s, sform, sbuf); } Godfather_Of_Soul echo x - distab.c cat >distab.c <<'Godfather_Of_Soul' struct optab { short op_mask, op_val; char *op_op; }; struct optab optab[] = { 0xff, 0, "nop", 0xc0, 0x40, "ld\tP,R", 0xc0, 0x80, "FR", 0xc7, 0x04, "inc\tP", 0xc7, 0x05, "dec\tP", 0xc7, 0x06, "ld\tP,B", 0xc7, 0xc0, "ret\tC", 0xc7, 0xc2, "jp\tC,W", 0xc7, 0xc4, "call\tC,W", 0xc7, 0xc6, "FB", 0xc7, 0xc7, "rst\tT", 0xcf, 0x01, "ld\tS,W", 0xef, 0x02, "ld\t(S),a", 0xef, 0x0a, "ld\ta,(S)", 0xcf, 0x03, "inc\tS", 0xcf, 0x09, "add\thl,S", 0xcf, 0x0b, "dec\tS", 0xff, 0x7, "rlca", 0xff, 0x8, "ex\taf,af'", 0xff, 0x0f, "rrca", 0xff, 0x10, "djnz\t-", 0xff, 0x17, "rla", 0xff, 0x18, "jr\t-", 0xff, 0x1f, "rra", 0xff, 0x20, "jr\tnz,-", 0xff, 0x27, "daa", 0xff, 0x28, "jr\tz,-", 0xff, 0x2f, "cpl", 0xff, 0x30, "jr\tnc,-", 0xff, 0x37, "scf", 0xff, 0x38, "jr\tc,-", 0xff, 0x22, "ld\t(W),hl", 0xff, 0x2a, "ld\thl,(W)", 0xff, 0x32, "ld\t(W),a", 0xff, 0x3a, "ld\ta,(W)", 0xff, 0x3f, "ccf", 0xcf, 0xc1, "pop\tQ", 0xff, 0xc3, "jp\tW", 0xcf, 0xc5, "push\tQ", 0xff, 0xc9, "ret", 0xff, 0xcb, "X0", 0xff, 0xcd, "call\tW", 0xff, 0xd3, "out\t(B),a", 0xff, 0xd9, "exx", 0xff, 0xdb, "in\ta,(B)", /* 0xff, 0xdd, "X1", */ 0xff, 0xe3, "ex\t(sp),hl", 0xff, 0xe9, "jp\t(hl)", 0xff, 0xeb, "ex\tde,hl", 0xff, 0xed, "X2", 0xff, 0xf3, "di", 0xff, 0xfb, "ei", /* 0xff, 0xfd, "X3", */ 0xff, 0xf9, "ld\tsp,hl", 0, 0, "???", }; struct optab toptab[] = { 0xf8, 0, "rlc\tR", 0xf8, 0x8, "rrc\tR", 0xf8, 0x10, "rl\tR", 0xf8, 0x18, "rr\tR", 0xf8, 0x20, "sla\tR", 0xf8, 0x28, "sra\tR", 0xf8, 0x38, "srl\tR", 0xc0, 0x40, "bit\tT,R", 0xc0, 0x80, "res\tT,R", 0xc0, 0xc0, "set\tT,R", 0, 0, "???", }; struct optab ddoptab[] = { 0, 0, "???", }; struct optab edoptab[] = { 0xcf, 0x42, "sbc\thl,S", 0xcf, 0x43, "ld\t(W),S", 0xcf, 0x4a, "adc\thl,S", 0xcf, 0x4b, "ld\tS,(W)", 0xe7, 0xa0, "ldK", 0xe7, 0xa1, "cpK", 0xe7, 0xa2, "inK", 0xff, 0x2b, "dec\tix", 0xff, 0x35, "dec\t(ix+B)", 0xff, 0x44, "neg", 0xff, 0x46, "im\t0", 0xff, 0x4b, "ld\tbc,(W)", 0xff, 0x4d, "reti", 0xff, 0x56, "im\t1", 0xff, 0x5b, "ld\tde,(W)", 0xff, 0x66, "im\t2", 0xff, 0x67, "rrd", 0xff, 0x6f, "rld", 0xff, 0x73, "ld\t(W),sp", 0xff, 0x7b, "ld\tsp,(W)", 0, 0, "???", }; struct optab fdoptab[] = { 0, 0, "???", }; Godfather_Of_Soul