home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
messroms.de
/
2007-01-13_www.messroms.de.zip
/
VZ200
/
TOOLS
/
DZ80.ZIP
/
dis.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-12-07
|
52KB
|
2,420 lines
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "z80.h"
#include "dis.h"
#include "table.h"
#define COLUMN_OPCODE 32
#define COLUMN_ARGUMENT 38
#define COLUMN_COMMENT 56
MEMOPT memopt[0x10000]; // memory flags and options
SYM * symbols = NULL;
COM * comments = NULL;
DIS dis = {{0,}, };
Z80 z80 = {{{0,},}, };
//****************************************************************************
// print a value as 2 or 3 digit hexadecimal with trailing 'h'
//******************************************************************----------
char * hexb(int val)
{
static int hexb_indx=0;
static char hexb_buff[6*16];
char * dst = hexb_buff + 6 * (++hexb_indx & 15);
if (val > 0x9F)
sprintf(dst, "%03XH", val & 255);
else
if (val < 10)
sprintf(dst, "%d", val);
else
sprintf(dst, "%02XH", val);
return dst;
}
//****************************************************************************
// print a value as 4 or 5 digit hexadecimal with trailing 'h'
//******************************************************************----------
char * hexw(int val)
{
static int hexw_indx=0;
static char hexw_buff[8*16];
char *dst = hexw_buff + 8 * (++hexw_indx & 15);
if (val > 0x9FFF)
sprintf(dst, "%05XH", val & 65535);
else
sprintf(dst, "%04XH", val);
return dst;
}
//****************************************************************************
// convert hexadecimal digit sequence into a WORD
//******************************************************************----------
WORD hextoi(char * src)
{
WORD rc = 0;
while (*src)
{
if ((*src >= '0') && (*src <= '9'))
rc = rc * 16 + *src - '0';
else
if ((*src >= 'A') && (*src <= 'F'))
rc = rc * 16 + *src - 'A' + 10;
else
if ((*src >= 'a') && (*src <= 'f'))
rc = rc * 16 + *src - 'a' + 10;
else
return rc;
src++;
}
return rc;
}
//****************************************************************************
// define an option for a memory location
//******************************************************************----------
void OPT_def(WORD addr, unsigned mode, unsigned size, unsigned opt)
{
memopt[addr].mode = mode;
memopt[addr].size = size;
memopt[addr].opt = opt;
}
//****************************************************************************
// add a symbol to our table
//******************************************************************----------
void SYM_add(WORD addr, SYMTYPE type, char * name)
{
SYM *sym, * sym0, * sym1;
for (sym0 = NULL, sym1 = symbols; (sym1); sym0 = sym1, sym1 = sym1->next)
if (addr <= sym1->addr)
break;
sym = (SYM *) malloc(sizeof(SYM) + strlen(name));
if (!sym)
return;
sym->next = sym1;
sym->type = type;
sym->addr = addr;
strcpy(sym->name, name);
if (sym0)
sym0->next = sym;
else
symbols = sym;
memopt[addr].symbol = 1;
}
//****************************************************************************
// add a comment to our table
//******************************************************************----------
void COM_add(WORD addr, COMTYPE type, char * text)
{
COM * com, * com0, * com1;
for (com0 = NULL, com1 = comments; (com1); com0 = com1, com1 = com1->next)
if (addr <= com1->addr)
break;
if( com1 && // found an entry
com1->addr == addr && // address is equal ?
com1->type == type && // address is equal ?
strncmp(com1->text,text,strlen(text)) ) // and text not yet found ?
{
com = (COM *) realloc(com1, sizeof(COM) + strlen(com1->text) + 3 + strlen(text) + 1);
if (!com)
return;
strcat(com->text, "\n; ");
strcat(com->text, text);
if (com0)
com0->next = com;
else
comments = com;
return;
}
com = (COM *) malloc(sizeof(COM) + strlen(text));
if (!com)
return;
com->next = com1;
com->type = type;
com->addr = addr;
strcpy(com->text, text);
if (com0)
com0->next = com;
else
comments = com;
memopt[addr].comment = 1;
}
//****************************************************************************
// get a symbol name for the given address and of the given type
//******************************************************************----------
char * SYM_get(WORD addr, SYMTYPE type)
{
static char sym_buff[128];
SYM *sym;
if( memopt[addr].symbol )
{
for( sym = symbols; (sym); sym = sym->next )
{
if( addr != sym->addr )
continue;
if( type == SYM_NONE || type == sym->type )
return sym->name;
}
}
if( addr > 0 && memopt[addr-1].symbol )
{
for (sym = symbols; (sym); sym = sym->next)
{
if (addr != sym->addr+1)
continue;
if( type == SYM_NONE || type == sym->type )
{
sprintf(sym_buff, "%s+1", sym->name);
return sym_buff;
}
}
if( addr > 1 && memopt[addr-2].symbol )
{
for (sym = symbols; (sym); sym = sym->next)
{
if (addr != sym->addr+2)
continue;
if( type == SYM_NONE || type == sym->type )
{
sprintf(sym_buff, "%s+2", sym->name);
return sym_buff;
}
}
if( addr > 2 && memopt[addr-3].symbol )
{
for( sym = symbols; (sym); sym = sym->next )
{
if( addr != sym->addr+3 )
continue;
if( type == SYM_NONE || type == sym->type )
{
sprintf(sym_buff, "%s+3", sym->name);
return sym_buff;
}
}
}
}
}
return hexw(addr);
}
//****************************************************************************
// get a comment for the given address
//******************************************************************----------
char * COM_get(WORD addr, COMTYPE type)
{
COM *com;
if( memopt[addr].comment )
{
for( com = comments; (com); com = com->next )
{
if( addr != com->addr )
continue;
if( type == COM_NONE || type == com->type )
return com->text;
}
}
return "";
}
//****************************************************************************
// read a symbol, flags and options definitions file
//******************************************************************----------
void DEF_file_read(char *filename)
{
FILE *filp;
char *line;
char buff[64];
char *src;
WORD addr;
WORD offs;
if (NULL == (line = alloca(1024)))
return;
filp = fopen(filename, "r");
if (!filp)
return;
while (!feof(filp))
{
fgets(line, 1024, filp);
src = strtok(line, "\t \n\x1A");
if (!src)
continue;
addr = hextoi(src);
src = strtok(NULL, "\t \n\x1A");
if (!src)
continue;
switch (*src)
{
case '+':
src = strtok(NULL, "\n\x1A");
if (src)
COM_add(addr, COM_APPEND, src);
break;
case ';':
src = strtok(NULL, "\n\x1A");
if (src)
COM_add(addr, COM_BLOCK, src);
break;
case '=':
src = strtok(NULL, "\n\x1A");
if (src)
SYM_add(addr, SYM_NONE, src);
break;
case 'c': case 'C':
OPT_def(addr, MEM_CODE, 0, 0);
src = strtok(NULL, "\t \n\x1A");
if (src)
SYM_add(addr, SYM_CODE, src);
break;
case 'b': case 'B':
OPT_def(addr, MEM_DATA, 0, OPT_BYTES);
memopt[addr].opt = OPT_BYTES;
src = strtok(NULL, "\t \n\x1A");
if (src)
SYM_add(addr, SYM_DATA, src);
break;
case '7':
OPT_def(addr, MEM_DATA, 0, OPT_7BIT);
src = strtok(NULL, "\t \n\x1A");
if (src)
SYM_add(addr, SYM_DATA, src);
break;
case 'a': case 'A':
OPT_def(addr, MEM_DATA, 0, OPT_ASCII);
memopt[addr].opt = OPT_ASCII;
src = strtok(NULL, "\t \n\x1A");
if (src)
SYM_add(addr, SYM_DATA, src);
break;
case 'w': case 'W':
OPT_def(addr, MEM_DATA, 1, OPT_WORDS);
src = strtok(NULL, "\t \n\x1A");
if (src)
SYM_add(addr, SYM_DATA, src);
break;
case 'e': case 'E':
OPT_def(addr, MEM_DATA, 1, OPT_ENTRY);
src = strtok(NULL, "\t \n\x1A");
if (src)
SYM_add(addr, SYM_DATA, src);
break;
case 's': case 'S':
OPT_def(addr, MEM_DATA, 2, OPT_FSNG);
src = strtok(NULL, "\t \n\x1A");
if (src)
SYM_add(addr, SYM_DATA, src);
break;
case 'd': case 'D':
OPT_def(addr, MEM_DATA, 3, OPT_FDBL);
src = strtok(NULL, "\t \n\x1A");
if (src)
SYM_add(addr, SYM_DATA, src);
break;
case 'o': case 'O':
offs = *(WORD*)&mem[addr];
switch (src[1])
{
case 'c': case 'C':
OPT_def(addr, MEM_DATA, 1, OPT_OC);
memopt[addr].opt = OPT_OC;
if (memopt[offs].mode == MEM_UNKNOWN)
{
OPT_def(offs, MEM_CODE, 0, OPT_NONE);
if (memopt[offs].comment == 0)
{
sprintf(buff, "CODE xref [%04Xh]", addr);
COM_add(offs, COM_APPEND, buff);
}
}
break;
case '7':
OPT_def(addr, MEM_DATA, 1, OPT_OD7);
if (memopt[offs].mode == MEM_UNKNOWN)
{
OPT_def(offs, MEM_DATA, 0, OPT_7BIT);
if (memopt[offs].comment == 0)
{
sprintf(buff, "7BIT xref [%04Xh]", addr);
COM_add(offs, COM_APPEND, buff);
}
}
break;
case 'a': case 'A':
OPT_def(addr, MEM_DATA, 1, OPT_ODA);
if (memopt[offs].mode == MEM_UNKNOWN)
{
OPT_def(offs, MEM_DATA, 0, OPT_ASCII);
if (memopt[offs].comment == 0)
{
sprintf(buff, "ASCII xref [%04Xh]", addr);
COM_add(offs, COM_APPEND, buff);
}
}
break;
case 'b': case 'B':
OPT_def(addr, MEM_DATA, 1, OPT_ODB);
if (memopt[offs].mode == MEM_UNKNOWN)
{
OPT_def(offs, MEM_DATA, 0, OPT_BYTES);
if (memopt[offs].comment == 0)
{
sprintf(buff, "BYTES xref [%04Xh]", addr);
COM_add(offs, COM_APPEND, buff);
}
}
break;
case 'w': case 'W':
OPT_def(addr, MEM_DATA, 1, OPT_ODW);
if (memopt[offs].mode == MEM_UNKNOWN)
{
OPT_def(offs, MEM_DATA, 1, OPT_WORDS);
if (memopt[offs].comment == 0)
{
sprintf(buff, "WORDS xref [%04Xh]", addr);
COM_add(offs, COM_APPEND, buff);
}
}
break;
case 'e': case 'E':
OPT_def(addr, MEM_DATA, 1, OPT_ODE);
if (memopt[offs].mode == MEM_UNKNOWN)
{
OPT_def(offs, MEM_DATA, 1, OPT_ENTRY);
if (memopt[offs].comment == 0)
{
sprintf(buff, "ENTRY xref [%04Xh]", addr);
COM_add(offs, COM_APPEND, buff);
}
}
break;
default:
OPT_def(addr, MEM_DATA, 1, OPT_ODB);
if (memopt[offs].mode == MEM_UNKNOWN)
{
OPT_def(offs, MEM_DATA, 0, OPT_BYTES);
}
break;
}
src = strtok(NULL, "\t \n\x1A");
if (src)
SYM_add(addr, SYM_DATA, src);
break;
}
}
fclose(filp);
}
//****************************************************************************
// pad the output buffer with blanks and output an opcode
//******************************************************************----------
int pad_opcode(char * fmt, ...)
{
va_list arg;
int len;
while( dis.dst < dis.buff + COLUMN_OPCODE )
*dis.dst++ = ' ';
va_start(arg, fmt);
len = vsprintf(dis.dst, fmt, arg);
va_end(arg);
return len;
}
//****************************************************************************
// pad the output buffer with blanks and output an argument
//******************************************************************----------
int pad_argument(char * fmt, ...)
{
va_list arg;
int len;
while( dis.dst < dis.buff + COLUMN_ARGUMENT )
*dis.dst++ = ' ';
va_start(arg, fmt);
len = vsprintf(dis.dst, fmt, arg);
va_end(arg);
return len;
}
//****************************************************************************
// pad the output buffer with blanks and output a comment
//******************************************************************----------
int pad_comment(char * fmt, ...)
{
va_list arg;
int len;
while (dis.dst < dis.buff + COLUMN_COMMENT)
*dis.dst++ = ' ';
if (!dis.padcom)
{
dis.padcom = 1;
*dis.dst++ = ';';
}
va_start(arg, fmt);
len = vsprintf(dis.dst, fmt, arg);
va_end(arg);
return len;
}
//****************************************************************************
// disassemble an destination operand from the given table entry
//******************************************************************----------
int dis_dst(TABLE * ptab, BOOL comma)
{
int len = 0;
switch (ptab->dst)
{
case _d0:
return 0;
case _dB:
len = pad_argument("B");
break;
case _dC:
len = pad_argument("C");
break;
case _dD:
len = pad_argument("D");
break;
case _dE:
len = pad_argument("E");
break;
case _dH:
len = pad_argument("H");
break;
case _dL:
len = pad_argument("L");
break;
case _dM:
dis.flag.dst_mem8 = 1;
dis.flag.dst_addr = 1;
dis.addr = z80.hl.r16;
dis.mem8 = mem[dis.addr];
len = pad_argument("(HL)");
break;
case _dA:
len = pad_argument("A");
break;
case _dHIX:
len = pad_argument("HX");
break;
case _dLIX:
len = pad_argument("LX");
break;
case _dHIY:
len = pad_argument("HY");
break;
case _dLIY:
len = pad_argument("LY");
break;
case _dI:
len = pad_argument("I");
break;
case _dR:
len = pad_argument("R");
break;
case _dF:
len = pad_argument("F");
break;
case _dMBC:
dis.flag.dst_mem8 = 1;
dis.flag.dst_addr = 1;
dis.addr = z80.bc.r16;
dis.mem8 = mem[dis.addr];
len = pad_argument("(BC)");
break;
case _dMDE:
dis.flag.dst_mem8 = 1;
dis.flag.dst_addr = 1;
dis.addr = z80.de.r16;
dis.mem8 = mem[dis.addr];
len = pad_argument("(DE)");
break;
case _dMSP:
dis.flag.dst_mem16 = 1;
dis.flag.dst_addr = 1;
dis.addr = z80.sp.r16;
dis.mem16 = mem[dis.addr] + 256 * mem[dis.addr+1];
len = pad_argument("(SP)");
break;
case _dMIX:
if (!(dis.flag.has_ofs8))
{
dis.flag.has_ofs8 = 1;
dis.ofs8 = (OFS8) mem[dis.pc++];
}
dis.flag.dst_mem8 = 1;
dis.flag.dst_addr = 1;
dis.addr = z80.ix.r16 + dis.ofs8;
dis.mem8 = mem[dis.addr];
if (dis.ofs8)
len = pad_argument("(IX%+d)", dis.ofs8);
else
len = pad_argument("(IX)");
break;
case _dMIY:
if (!dis.flag.has_ofs8)
{
dis.flag.has_ofs8 = 1;
dis.ofs8 = (OFS8) mem[dis.pc++];
}
dis.flag.dst_mem8 = 1;
dis.flag.dst_addr = 1;
dis.addr = z80.iy.r16 + dis.ofs8;
dis.mem8 = mem[dis.addr];
if (dis.ofs8)
len = pad_argument("(IY%+d)", dis.ofs8);
else
len = pad_argument("(IY)");
break;
case _dIND8:
if (!(dis.flag.has_ind))
{
dis.flag.has_ind = 1;
dis.ind16 = mem[dis.pc++];
dis.ind16 += mem[dis.pc++] << 8;
}
dis.flag.dst_mem8 = 1;
dis.addr = dis.ind16;
dis.mem8 = mem[dis.addr];
len = pad_argument("(%s)", SYM_get(dis.ind16, SYM_NONE));
break;
case _dIMM8:
if (!(dis.flag.has_imm8))
{
dis.flag.has_imm8 = 1;
dis.imm8 = mem[dis.pc++];
}
len = pad_argument("%s", hexb(dis.imm8));
break;
case _dPORT8:
if (!(dis.flag.has_port))
{
dis.flag.has_port = 1;
dis.port = mem[dis.pc++];
}
dis.flag.dst_port = 1;
len = pad_argument("(%s)", hexb(dis.port));
break;
case _dPORTC:
dis.flag.dst_port = 1;
dis.port = z80.bc.r16;
len = pad_argument("(C)");
break;
case _dBC:
len = pad_argument("BC");
break;
case _dDE:
len = pad_argument("DE");
break;
case _dHL:
len = pad_argument("HL");
break;
case _dSP:
len = pad_argument("SP");
break;
case _dAF:
len = pad_argument("AF");
break;
case _dPC:
len = pad_argument("$");
break;
case _dIX:
len = pad_argument("IX");
break;
case _dIY:
len = pad_argument("IY");
break;
case _dPCHL:
dis.flag.dst_addr = 1;
dis.addr = z80.hl.r16;
len = pad_argument("(HL)");
break;
case _dPCIX:
dis.flag.dst_addr = 1;
dis.addr = z80.ix.r16;
len = pad_argument("(IX)");
break;
case _dPCIY:
dis.flag.dst_addr = 1;
dis.addr = z80.iy.r16;
len = pad_argument("(IY)");
break;
case _dREG1:
len = pad_argument("BC,DE,HL");
break;
case _dREG2:
len = pad_argument("BC',DE',HL'");
break;
case _dAF2:
len = pad_argument("AF'");
break;
case _dIND16:
if (!(dis.flag.has_ind))
{
dis.flag.has_ind = 1;
dis.ind16 = mem[dis.pc++];
dis.ind16 += mem[dis.pc++] << 8;
}
dis.flag.dst_mem16 = 1;
dis.addr = dis.ind16;
dis.mem16 = mem[dis.addr] + 256 * mem[dis.addr + 1];
len = pad_argument("(%s)", SYM_get(dis.ind16, SYM_NONE));
break;
case _dIMPL:
dis.flag.dst_addr = 1;
dis.addr = dis.cmd0 & 0x0038;
len = pad_argument("%s", hexb(dis.addr));
break;
}
if (comma)
len += sprintf(dis.dst + len, ",");
return len;
}
//****************************************************************************
// disassemble a source operand from the given table entry
//******************************************************************----------
int dis_src(TABLE * ptab)
{
int len = 0;
switch (ptab->src)
{
case _s0:
return 0;
case _sB:
len = pad_argument("B");
dis.val8 = z80.bc.r8[1];
break;
case _sC:
len = pad_argument("C");
dis.val8 = z80.bc.r8[0];
break;
case _sD:
len = pad_argument("D");
dis.val8 = z80.de.r8[1];
break;
case _sE:
len = pad_argument("E");
dis.val8 = z80.de.r8[0];
break;
case _sH:
len = pad_argument("H");
dis.val8 = z80.hl.r8[1];
break;
case _sL:
len = pad_argument("L");
dis.val8 = z80.hl.r8[0];
break;
case _sM:
dis.flag.src_mem8 = 1;
dis.flag.src_addr = 1;
dis.addr = z80.hl.r16;
dis.mem8 = dis.val8 = mem[dis.addr];
len = pad_argument("(HL)");
break;
case _sA:
len = pad_argument("A");
dis.val8 = z80.af.r8[1];
break;
case _sHIX:
len = pad_argument("HX");
dis.val8 = z80.ix.r8[1];
break;
case _sLIX:
len = pad_argument("LX");
dis.val8 = z80.ix.r8[0];
break;
case _sHIY:
len = pad_argument("HY");
dis.val8 = z80.iy.r8[1];
break;
case _sLIY:
len = pad_argument("LY");
dis.val8 = z80.iy.r8[0];
break;
case _sI:
len = pad_argument("I");
dis.val8 = z80.ri.r8[0];
break;
case _sR:
len = pad_argument("R");
dis.val8 = z80.ri.r8[1];
break;
case _sF:
len = pad_argument("F");
dis.val8 = z80.af.r8[0];
break;
case _sMBC:
dis.flag.src_mem8 = 1;
dis.flag.src_addr = 1;
dis.addr = z80.bc.r16;
dis.mem8 = dis.val8 = mem[dis.addr];
len = pad_argument("(BC)");
break;
case _sMDE:
dis.flag.src_mem8 = 1;
dis.flag.src_addr = 1;
dis.addr = z80.de.r16;
dis.mem8 = dis.val8 = mem[dis.addr];
len = pad_argument("(DE)");
break;
case _sMSP:
dis.flag.src_mem16 = 1;
dis.flag.src_addr = 1;
dis.addr = z80.sp.r16;
dis.mem16 = mem[dis.addr] + 256 * mem[dis.addr + 1];
len = pad_argument("(SP)");
break;
case _sMIX:
if (!(dis.flag.has_ofs8))
{
dis.flag.has_ofs8 = 1;
dis.ofs8 = (OFS8) mem[dis.pc++];
}
dis.flag.src_mem8 = 1;
dis.flag.src_addr = 1;
dis.addr = z80.ix.r16 + dis.ofs8;
dis.mem8 = dis.val8 = mem[dis.addr];
if (dis.ofs8)
len = pad_argument("(IX%+d)", dis.ofs8);
else
len = pad_argument("(IX)");
break;
case _sMIY:
if (!(dis.flag.has_ofs8))
{
dis.flag.has_ofs8 = 1;
dis.ofs8 = (OFS8) mem[dis.pc++];
}
dis.flag.src_mem8 = 1;
dis.flag.src_addr = 1;
dis.addr = z80.iy.r16 + dis.ofs8;
dis.mem8 = dis.val8 = mem[dis.addr];
if (dis.ofs8)
len = pad_argument("(IY%+d)", dis.ofs8);
else
len = pad_argument("(IY)");
break;
case _sIND8:
if (!(dis.flag.has_ind))
{
dis.flag.has_ind = 1;
dis.ind16 = mem[dis.pc++];
dis.ind16 += mem[dis.pc++] << 8;
}
dis.flag.src_mem8 = 1;
dis.addr = dis.ind16;
dis.mem8 = dis.val8 = mem[dis.addr];
len = pad_argument("(%s)", SYM_get(dis.ind16, SYM_NONE));
break;
case _sIMM8:
if (!(dis.flag.has_imm8))
{
dis.flag.has_imm8 = 1;
dis.imm8 = mem[dis.pc++];
}
dis.val8 = dis.imm8;
len = pad_argument("%s", hexb(dis.imm8));
break;
case _sIMM8A:
if (!(dis.flag.has_imm8))
{
dis.flag.has_imm8 = 1;
dis.imm8 = mem[dis.pc++];
}
dis.val8 = dis.imm8;
switch (dis.imm8)
{
case 0 ... 31:
len = pad_argument("%d", dis.imm8);
break;
case 32 ... 127:
len = pad_argument("\"%c\"", dis.imm8);
break;
case 255:
len = pad_argument("-1");
break;
default:
len = pad_argument("%s", hexb(dis.imm8));
break;
}
break;
case _sPORT8:
if (!(dis.flag.has_port))
{
dis.flag.has_port = 1;
dis.port = mem[dis.pc++];
}
dis.flag.src_port = 1;
dis.val8 = dis.port;
len = pad_argument("(%s)", hexb(dis.port));
break;
case _sPORTC:
dis.flag.src_port = 1;
dis.port = z80.bc.r16;
len = pad_argument("(C)");
break;
case _sBC:
len = pad_argument("BC");
dis.val16 = z80.bc.r16;
break;
case _sDE:
len = pad_argument("DE");
dis.val16 = z80.de.r16;
break;
case _sHL:
len = pad_argument("HL");
dis.val16 = z80.hl.r16;
break;
case _sSP:
len = pad_argument("SP");
dis.val16 = z80.sp.r16;
break;
case _sAF:
len = pad_argument("AF");
dis.val16 = z80.af.r16;
break;
case _sPC:
len = pad_argument("$");
break;
case _sIX:
len = pad_argument("IX");
dis.val16 = z80.ix.r16;
break;
case _sIY:
len = pad_argument("IY");
dis.val16 = z80.iy.r16;
break;
case _sPCHL:
dis.flag.src_addr = 1;
dis.addr = dis.val16 = z80.hl.r16;
len = pad_argument("(HL)");
break;
case _sPCIX:
dis.flag.src_addr = 1;
dis.addr = dis.val16 = z80.ix.r16;
len = pad_argument("(IX)");
break;
case _sPCIY:
dis.flag.src_addr = 1;
dis.addr = dis.val16 = z80.iy.r16;
len = pad_argument("(IY)");
break;
case _sREL8:
if (!(dis.flag.has_rel8))
{
dis.flag.has_rel8 = 1;
dis.rel8 = (OFS8) mem[dis.pc++];
}
dis.flag.src_addr = 1;
dis.addr = dis.pc + dis.rel8;
len = pad_argument("%s", SYM_get(dis.addr, SYM_CODE));
break;
case _sREG1:
len = pad_argument("BC,DE,HL");
break;
case _sREG2:
len = pad_argument("BC',DE',HL'");
break;
case _sAF2:
len = pad_argument("AF'");
dis.val16 = z80.af2.r16;
break;
case _sIMM16:
if (!(dis.flag.has_imm16))
{
dis.flag.has_imm16 = 1;
dis.imm16 = mem[dis.pc++];
dis.imm16 += mem[dis.pc++] << 8;
}
dis.val16 = dis.imm16;
len = pad_argument("%s", SYM_get(dis.imm16, SYM_NONE));
break;
case _sADR16:
if (!(dis.flag.has_adr16))
{
dis.flag.has_adr16 = 1;
dis.adr16 = mem[dis.pc++];
dis.adr16 += mem[dis.pc++] << 8;
}
dis.flag.jmp_addr = 1;
dis.addr = dis.val16 = dis.adr16;
len = pad_argument("%s", SYM_get(dis.adr16, SYM_NONE));
break;
case _sIND16:
if (!(dis.flag.has_ind))
{
dis.flag.has_ind = 1;
dis.ind16 = mem[dis.pc++];
dis.ind16 += mem[dis.pc++] << 8;
}
dis.flag.src_mem16 = 1;
dis.addr = dis.ind16;
dis.mem16 = dis.val16 = mem[dis.addr] + 256 * mem[dis.addr + 1];
len = pad_argument("(%s)", SYM_get(dis.ind16, SYM_NONE));
break;
case _sIMPL:
dis.flag.jmp_addr = 1;
dis.addr = dis.cmd0 & 0x0038;
len = pad_argument("%s", hexb(dis.addr));
break;
}
return len;
}
//****************************************************************************
// disassemble a secondary destination from the given table entry
//******************************************************************----------
int dis_dst_2(TABLE * ptab)
{
int len = 0;
if (ptab->dst != ptab->src) // DD CB and FD CB commands
{
len = dis_dst(ptab, 0);
len += pad_argument("=");
}
return len;
}
//****************************************************************************
// disassemble a bit number from the given table entry
//******************************************************************----------
int dis_bit(TABLE * ptab)
{
int len = 0;
switch (ptab->spec)
{
case _xBIT0:
len = pad_argument("0");
break;
case _xBIT1:
len = pad_argument("1");
break;
case _xBIT2:
len = pad_argument("2");
break;
case _xBIT3:
len = pad_argument("3");
break;
case _xBIT4:
len = pad_argument("4");
break;
case _xBIT5:
len = pad_argument("5");
break;
case _xBIT6:
len = pad_argument("6");
break;
case _xBIT7:
len = pad_argument("7");
break;
default:
len = pad_argument("?");
break;
}
len += sprintf(dis.dst + len, ",");
return len;
}
//****************************************************************************
// disassemble a condition code from the given table entry
//******************************************************************----------
int dis_cond(TABLE * ptab, int comma)
{
int len = 0;
switch (ptab->cond)
{
case _c0:
return len;
case _cNZ:
len = pad_argument("NZ");
break;
case _cZ:
len = pad_argument("Z");
break;
case _cNC:
len = pad_argument("NC");
break;
case _cC:
len = pad_argument("C");
break;
case _cPO:
len = pad_argument("PO");
break;
case _cPE:
len = pad_argument("PE");
break;
case _cP:
len = pad_argument("P");
break;
case _cM:
len = pad_argument("M");
break;
}
if (comma)
len += sprintf(dis.dst + len, ",");
return len;
}
//****************************************************************************
// disassemble one instruction from the given table entry
//******************************************************************----------
void dis_instr(TABLE * ptab)
{
switch (ptab->oper)
{
case _t0:
dis.dst += pad_opcode("???");
break;
case _tADC:
dis.dst += pad_opcode("ADC");
dis.dst += dis_dst(ptab, 1);
dis.dst += dis_src(ptab);
if (ptab->dst == _dA)
dis.val8 += z80.af.r8[1] + z80.af.f.c;
else
if (ptab->dst == _dHL)
dis.val16 += z80.hl.r16 + z80.af.f.c;
break;
case _tADD:
dis.dst += pad_opcode("ADD");
dis.dst += dis_dst(ptab, 1);
dis.dst += dis_src(ptab);
if (ptab->dst == _dA)
dis.val8 += z80.af.r8[1];
else
if (ptab->dst == _dHL)
dis.val16 += z80.hl.r16;
else
if (ptab->dst == _dIX)
dis.val16 += z80.ix.r16;
else
if (ptab->dst == _dIY)
dis.val16 += z80.iy.r16;
break;
case _tAND:
dis.dst += pad_opcode("AND");
dis.dst += dis_src(ptab);
dis.val8 = (z80.af.r8[1] & dis.val8);
break;
case _tBIT:
dis.dst += pad_opcode("BIT");
dis.dst += dis_bit(ptab);
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
break;
case _tCALL:
dis.dst += pad_opcode("CALL");
dis.dst += dis_cond(ptab, 1);
dis.dst += dis_src(ptab);
break;
case _tCCF:
dis.dst += pad_opcode("CCF");
z80.af.f.c = ~z80.af.f.c;
break;
case _tCP:
dis.dst += pad_opcode("CP");
dis.dst += dis_src(ptab);
break;
case _tCPD:
dis.dst += pad_opcode("CPD");
break;
case _tCPDR:
dis.dst += pad_opcode("CPDR");
break;
case _tCPI:
dis.dst += pad_opcode("CPI");
break;
case _tCPIR:
dis.dst += pad_opcode("CPIR");
break;
case _tCPL:
dis.dst += pad_opcode("CPL");
dis.val8 = ~z80.af.r8[1];
break;
case _tDAA:
dis.dst += pad_opcode("DAA");
break;
case _tDEC:
dis.dst += pad_opcode("DEC");
dis.dst += dis_src(ptab);
dis.val8 -= 1;
dis.val16 -= 1;
break;
case _tDI:
dis.dst += pad_opcode("DI");
break;
case _tDJNZ:
dis.dst += pad_opcode("DJNZ");
dis.dst += dis_src(ptab);
z80.bc.r8[1] = 0;
break;
case _tEI:
dis.dst += pad_opcode("EI");
break;
case _tEX:
dis.dst += pad_opcode("EX");
dis.dst += dis_dst(ptab, 1);
dis.dst += dis_src(ptab);
break;
case _tEXX:
dis.dst += pad_opcode("EXX");
dis.val16 = z80.bc2.r16; z80.bc2.r16 = z80.bc.r16; z80.bc.r16 = dis.val16;
dis.val16 = z80.de2.r16; z80.de2.r16 = z80.de.r16; z80.de.r16 = dis.val16;
dis.val16 = z80.hl2.r16; z80.hl2.r16 = z80.hl.r16; z80.hl.r16 = dis.val16;
break;
case _tHALT:
dis.dst += pad_opcode("HALT");
break;
case _tIM0:
dis.dst += pad_opcode("IM");
pad_argument("0");
break;
case _tIM1:
dis.dst += pad_opcode("IM");
pad_argument("1");
break;
case _tIM2:
dis.dst += pad_opcode("IM");
pad_argument("2");
break;
case _tIN:
dis.dst += pad_opcode("IN");
dis.dst += dis_dst(ptab, 1);
dis.dst += dis_src(ptab);
break;
case _tINC:
dis.dst += pad_opcode("INC");
dis.dst += dis_src(ptab);
dis.val8 += 1;
dis.val16 += 1;
break;
case _tIND:
dis.dst += pad_opcode("IND");
break;
case _tINDR:
dis.dst += pad_opcode("INDR");
break;
case _tINI:
dis.dst += pad_opcode("INI");
break;
case _tINIR:
dis.dst += pad_opcode("INIR");
break;
case _tJP:
dis.dst += pad_opcode("JP");
dis.dst += dis_cond(ptab, 1);
dis.dst += dis_src(ptab);
dis.flag.end_mode = (ptab->cond == _c0) ? 1 : 0;
break;
case _tJR:
dis.dst += pad_opcode("JR");
dis.dst += dis_cond(ptab, 1);
dis.dst += dis_src(ptab);
dis.flag.end_mode = (ptab->cond == _c0) ? 1 : 0;
break;
case _tLD:
dis.dst += pad_opcode("LD");
dis.dst += dis_dst(ptab, 1);
dis.dst += dis_src(ptab);
break;
case _tLDD:
dis.dst += pad_opcode("LDD");
z80.hl.r16 += 1;
z80.de.r16 += 1;
z80.bc.r16 -= 1;
break;
case _tLDDR:
dis.dst += pad_opcode("LDDR");
z80.hl.r16 -= z80.bc.r16;
z80.de.r16 -= z80.bc.r16;
z80.bc.r16 = 0;
break;
case _tLDI:
dis.dst += pad_opcode("LDI");
z80.hl.r16 += 1;
z80.de.r16 += 1;
z80.bc.r16 -= 1;
break;
case _tLDIR:
dis.dst += pad_opcode("LDIR");
z80.hl.r16 += z80.bc.r16;
z80.de.r16 += z80.bc.r16;
z80.bc.r16 = 0;
break;
case _tNEG:
dis.dst += pad_opcode("NEG");
dis.val8 = 0 - z80.af.r8[1];
break;
case _tNOP:
dis.dst += pad_opcode("NOP");
break;
case _tOR:
dis.dst += pad_opcode("OR");
dis.dst += dis_src(ptab);
dis.val8 |= z80.af.r8[1];
break;
case _tOTDR:
dis.dst += pad_opcode("OTDR");
break;
case _tOTIR:
dis.dst += pad_opcode("OTIR");
break;
case _tOUTD:
dis.dst += pad_opcode("OUTD");
break;
case _tOUTI:
dis.dst += pad_opcode("OUTI");
break;
case _tOUT:
dis.dst += pad_opcode("OUT");
dis.dst += dis_dst(ptab, 1);
dis.dst += dis_src(ptab);
break;
case _tPOP:
dis.dst += pad_opcode("POP");
dis.dst += dis_dst(ptab, 0);
break;
case _tPUSH:
dis.dst += pad_opcode("PUSH");
dis.dst += dis_src(ptab);
break;
case _tRES:
dis.dst += pad_opcode("RES");
dis.dst += dis_bit(ptab);
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
switch (ptab->spec)
{
case _x0:
case _xPC: break;
case _xBIT0: dis.val8 &= 0xFE; break;
case _xBIT1: dis.val8 &= 0xFD; break;
case _xBIT2: dis.val8 &= 0xFB; break;
case _xBIT3: dis.val8 &= 0xF7; break;
case _xBIT4: dis.val8 &= 0xEF; break;
case _xBIT5: dis.val8 &= 0xDF; break;
case _xBIT6: dis.val8 &= 0xBF; break;
case _xBIT7: dis.val8 &= 0x7F; break;
}
break;
case _tRETN:
dis.dst += pad_opcode("RETN");
dis.flag.end_mode = 1;
break;
case _tRETI:
dis.dst += pad_opcode("RETI");
dis.flag.end_mode = 1;
break;
case _tRET:
dis.dst += pad_opcode("RET");
dis.dst += dis_cond(ptab, 0);
dis.flag.end_mode = (ptab->cond == _c0) ? 1 : 0;
break;
case _tRL:
dis.dst += pad_opcode("RL");
dis.dst += dis_src(ptab);
dis.val8 = (dis.val8 << 1) | (z80.af.f.c);
break;
case _tRLA:
dis.dst += pad_opcode("RLA");
dis.val8 = (z80.af.r8[1] << 1) | (z80.af.f.c);
break;
case _tRLC:
dis.dst += pad_opcode("RLC");
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
dis.val8 = (dis.val8 << 1) | (dis.val8 >> 7);
break;
case _tRLCA:
dis.dst += pad_opcode("RLCA");
dis.val8 = (z80.af.r8[1] << 1) | (z80.af.r8[1] >> 7);
break;
case _tRLD:
dis.dst += pad_opcode("RLD");
dis.dst += dis_src(ptab);
break;
case _tRR:
dis.dst += pad_opcode("RR");
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
dis.val8 = (dis.val8 >> 1) | (z80.af.f.c << 7);
break;
case _tRRA:
dis.dst += pad_opcode("RRA");
dis.val8 = (z80.af.r8[1] >> 1) | (z80.af.f.c << 7);
break;
case _tRRC:
dis.dst += pad_opcode("RRC");
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
dis.val8 = (dis.val8 >> 1) | (dis.val8 << 7);
break;
case _tRRCA:
dis.dst += pad_opcode("RRCA");
dis.val8 = (z80.af.r8[1] >> 1) | (z80.af.r8[1] << 7);
break;
case _tRRD:
dis.dst += pad_opcode("RRD");
dis.dst += dis_src(ptab);
break;
case _tRST:
dis.dst += pad_opcode("RST");
dis.dst += dis_src(ptab);
break;
case _tSBC:
dis.dst += pad_opcode("SBC");
dis.dst += dis_dst(ptab, 1);
dis.dst += dis_src(ptab);
if (ptab->dst == _dA)
dis.val8 = (z80.af.r8[1] - dis.val8 - z80.af.f.c);
else
if (ptab->dst == _dHL)
dis.val16 = (z80.hl.r16 - dis.val16 - z80.af.f.c);
break;
case _tSCF:
dis.dst += pad_opcode("SCF");
z80.af.f.c = 1;
break;
case _tSET:
dis.dst += pad_opcode("SET");
dis.dst += dis_bit(ptab);
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
switch (ptab->spec)
{
case _x0:
case _xPC:
break;
case _xBIT0: dis.val8 |= 0x01; break;
case _xBIT1: dis.val8 |= 0x02; break;
case _xBIT2: dis.val8 |= 0x04; break;
case _xBIT3: dis.val8 |= 0x08; break;
case _xBIT4: dis.val8 |= 0x10; break;
case _xBIT5: dis.val8 |= 0x20; break;
case _xBIT6: dis.val8 |= 0x40; break;
case _xBIT7: dis.val8 |= 0x80; break;
}
break;
case _tSHL:
dis.dst += pad_opcode("SHL");
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
dis.val8 = dis.val8 * 2;
break;
case _tSHR:
dis.dst += pad_opcode("SHR");
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
dis.val8 = dis.val8 / 2;
break;
case _tSLI:
dis.dst += pad_opcode("SLI");
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
dis.val8 = dis.val8 * 2 + 1;
break;
case _tSRL:
dis.dst += pad_opcode("SRL");
dis.dst += dis_dst_2(ptab);
dis.dst += dis_src(ptab);
dis.val8 = (dis.val8 & 0x80) + (dis.val8 / 2);
break;
case _tSUB:
dis.dst += pad_opcode("SUB");
dis.dst += dis_src(ptab);
dis.val8 = (z80.af.r8[1] - dis.val8);
break;
case _tXOR:
dis.dst += pad_opcode("XOR");
dis.dst += dis_src(ptab);
dis.val8 = (z80.af.r8[1] ^ dis.val8);
break;
case _tEXT:
break;
}
}
char * dis_code(WORD * addr)
{
TABLE *ptab;
dis.pc = *addr;
dis.cmd0 = mem[dis.pc++];
dis.dst = dis.buff + COLUMN_OPCODE;
switch (dis.cmd0)
{
case 0xCB:
dis.cmd1 = mem[dis.pc++];
ptab = dis_cb + dis.cmd1;
dis.flag.has_cmd1 = 1;
dis_instr(ptab);
break;
case 0xDD:
dis.cmd1 = mem[dis.pc];
ptab = dis_dd + dis.cmd1;
if (ptab->oper)
{
dis.flag.has_cmd1 = 1;
dis.pc++;
if (ptab->oper == _tEXT)
{
dis.ofs8 = mem[dis.pc++];
dis.flag.has_ofs8 = 1;
dis.cmd3 = mem[dis.pc++];
dis.flag.has_cmd3 = 1;
ptab = dis_ddcb + dis.cmd3;
dis_instr(ptab);
break;
}
dis_instr(ptab);
}
break;
case 0xED:
dis.cmd1 = mem[dis.pc];
ptab = dis_ed + dis.cmd1;
if (ptab->oper)
{
dis.flag.has_cmd1 = 1;
dis.pc++;
dis_instr(ptab);
}
break;
case 0xFD:
dis.cmd1 = mem[dis.pc];
ptab = dis_fd + dis.cmd1;
if (ptab->oper)
{
dis.flag.has_cmd1 = 1;
dis.pc++;
if (ptab->oper == _tEXT)
{
dis.ofs8 = mem[dis.pc++];
dis.flag.has_ofs8 = 1;
dis.cmd3 = mem[dis.pc++];
dis.flag.has_cmd3 = 1;
ptab = dis_fdcb + dis.cmd3;
dis_instr(ptab);
break;
}
dis_instr(ptab);
}
break;
default:
ptab = dis_xx + dis.cmd0;
dis_instr(ptab);
break;
}
if (!ptab->oper)
dis.dst += pad_opcode("??? %02X", dis.cmd0);
*dis.dst = '\0';
if (dis.prtcom)
{
dis.prtcom = 0;
dis.dst += pad_comment(" %s", COM_get(*addr, COM_APPEND));
}
else
{
if (dis.flag.has_rel8)
{
dis.dst += pad_comment(" $%+d", dis.rel8);
}
if (dis.flag.src_mem8)
{
dis.dst += pad_comment(" [%04X] {%02X}", dis.addr, dis.mem8);
dis.flag.src_addr = 0;
}
else
if (dis.flag.dst_mem8)
{
dis.dst += pad_comment(" [%04X] {%02X}", dis.addr, dis.mem8);
dis.flag.dst_addr = 0;
}
if (dis.flag.src_mem16)
{
dis.dst += pad_comment(" [%04X] {%s}", dis.addr, SYM_get(dis.mem16, SYM_NONE));
dis.flag.src_addr = 0;
}
else
if (dis.flag.dst_mem16)
{
dis.dst += pad_comment(" [%04X] {%s}", dis.addr, SYM_get(dis.mem16, SYM_NONE));
dis.flag.dst_addr = 0;
}
if (dis.flag.src_port)
{
dis.dst += pad_comment(" (%04X)", dis.port);
}
if (dis.flag.dst_port)
{
dis.dst += pad_comment(" (%04X)", dis.port);
}
if (dis.flag.src_addr)
{
dis.dst += pad_comment(" %04X", dis.addr);
}
else
if (dis.flag.dst_addr)
{
dis.dst += pad_comment(" %04X", dis.addr);
}
else
if (dis.flag.jmp_addr)
{
dis.dst += pad_comment(" %04X", dis.addr);
}
}
sprintf(dis.buff, "%04X:%02X ", *addr, dis.cmd0);
dis.dst = dis.buff + 8;
*addr += 1;
if (dis.flag.has_cmd1)
{
dis.dst += sprintf(dis.dst, "%02X ", dis.cmd1);
*addr += 1;
}
if (dis.flag.has_port)
{
dis.dst += sprintf(dis.dst, "%02X ", dis.port);
*addr += 1;
}
if (dis.flag.has_imm8)
{
dis.dst += sprintf(dis.dst, "%02X ", dis.imm8);
*addr += 1;
}
if (dis.flag.has_ofs8)
{
dis.dst += sprintf(dis.dst, "%02X ", (BYTE)dis.ofs8);
*addr += 1;
}
if (dis.flag.has_rel8)
{
dis.dst += sprintf(dis.dst, "%02X ", (BYTE)dis.rel8);
*addr += 1;
}
if (dis.flag.has_imm16)
{
dis.dst += sprintf(dis.dst, "%04X ", dis.imm16);
*addr += 2;
}
if (dis.flag.has_adr16)
{
dis.dst += sprintf(dis.dst, "%04X ", dis.adr16);
*addr += 2;
}
if (dis.flag.has_ind)
{
dis.dst += sprintf(dis.dst, "%04X ", dis.ind16);
*addr += 2;
}
if (dis.flag.has_cmd3)
{
dis.dst += sprintf(dis.dst, "%02X ", dis.cmd3);
*addr += 1;
}
while (dis.dst < dis.buff + COLUMN_OPCODE)
*dis.dst++ = ' ';
switch (ptab->dst)
{
case _d0:
case _dM:
case _dMBC:
case _dMDE:
case _dMSP:
case _dMIX:
case _dMIY:
case _dIMM8:
case _dIND8:
case _dPC:
case _dREG1:
case _dREG2:
case _dIND16:
case _dIMPL:
break;
case _dB:
z80.bc.r8[1] = dis.val8;
break;
case _dC:
z80.bc.r8[0] = dis.val8;
break;
case _dD:
z80.de.r8[1] = dis.val8;
break;
case _dE:
z80.de.r8[0] = dis.val8;
break;
case _dH:
z80.hl.r8[1] = dis.val8;
break;
case _dL:
z80.hl.r8[0] = dis.val8;
break;
case _dA:
z80.af.r8[1] = dis.val8;
break;
case _dHIX:
z80.ix.r8[1] = dis.val8;
break;
case _dLIX:
z80.ix.r8[0] = dis.val8;
break;
case _dHIY:
z80.iy.r8[1] = dis.val8;
break;
case _dLIY:
z80.iy.r8[0] = dis.val8;
break;
case _dI:
z80.ri.r8[0] = dis.val8;
break;
case _dR:
z80.ri.r8[1] = dis.val8;
break;
case _dF:
z80.af.r8[0] = dis.val8;
break;
case _dPORT8:
break;
case _dPORTC:
break;
case _dBC:
z80.bc.r16 = dis.val16;
break;
case _dDE:
z80.de.r16 = dis.val16;
break;
case _dHL:
z80.hl.r16 = dis.val16;
break;
case _dSP:
z80.sp.r16 = dis.val16;
break;
case _dAF:
z80.af.r16 = dis.val16;
break;
case _dIX:
z80.ix.r16 = dis.val16;
break;
case _dIY:
z80.iy.r16 = dis.val16;
break;
case _dPCHL:
case _dPCIX:
case _dPCIY:
z80.pc.r16 = dis.val16;
break;
case _dAF2:
z80.af2.r16 = dis.val16;
break;
}
if (dis.flag.end_mode)
memset(&z80, 0, sizeof(z80));
return dis.buff;
}
int dis_bytes(void)
{
int i;
dis.dst += pad_opcode("DEFB");
for (i = 0; i < 8; i++)
{
if (i > 0)
{
if (memopt[dis.pc].symbol)
break;
if (memopt[dis.pc].comment)
break;
if (NEWOPT(dis.pc))
break;
dis.dst += pad_argument(",");
}
dis.val8 = mem[dis.pc++];
dis.dst += pad_argument("%s", hexb(dis.val8));
}
return i;
}
int dis_ascii(void)
{
BYTE str = 0;
BYTE old = 0;
int i;
dis.dst += pad_opcode("DEFM");
for (i = 0; i < 8; i++)
{
if (i > 0)
{
if ((dis.val8 == 0x00) && (old != 0x00))
break;
if (memopt[dis.pc].symbol)
break;
if (memopt[dis.pc].comment)
break;
if (NEWOPT(dis.pc))
break;
if (!str)
dis.dst += pad_argument(",");
}
old = dis.val8;
dis.val8 = mem[dis.pc++];
switch (dis.val8)
{
case 0x00 ... 0x1F:
case 0x22:
if (str)
dis.dst += pad_argument("\",");
dis.dst += pad_argument("%s", hexb(dis.val8));
str = 0;
break;
default:
if (!str)
dis.dst += pad_argument("\"");
dis.dst += pad_argument("%c", dis.val8);
str = 1;
break;
}
}
if (str)
dis.dst += pad_argument("\"");
return i;
}
int dis_7bit(void)
{
int first_bit8;
BYTE str = 0;
int i;
dis.dst += pad_opcode("DEFM");
first_bit8 = (mem[dis.pc] & 0x80) ? 1 : 0;
for (i = 0; i < 8; i++)
{
if (i > 0)
{
if (mem[dis.pc] == 0x80)
{
dis.flag.end_mode = 1;
break;
}
if (first_bit8 && (mem[dis.pc] & 0x80))
break;
if (!first_bit8 && (dis.val8 & 0x80))
break;
if (memopt[dis.pc].symbol)
break;
if (memopt[dis.pc].comment)
break;
if (NEWOPT(dis.pc))
break;
if (!str)
dis.dst += pad_argument(",");
}
dis.val8 = mem[dis.pc++];
switch (dis.val8)
{
case 0x00 ... 0x1F:
case 0x22:
case 0x80 ... 0x9F:
case 0xA7:
if (str)
dis.dst += pad_argument("\",");
dis.dst += pad_argument("%s", hexb(dis.val8));
str = 0;
break;
case 0xA0 ... 0xA6:
case 0xA8 ... 0xFF:
if (str)
dis.dst += pad_argument("\",");
dis.dst += pad_argument("'%c'+80h", dis.val8 & 0x7F);
str = 0;
break;
default:
if (!str)
dis.dst += pad_argument("\"");
dis.dst += pad_argument("%c", dis.val8);
str = 1;
break;
}
}
if (str)
dis.dst += pad_argument("\"");
return i;
}
int dis_words(void)
{
int i;
dis.dst += pad_opcode("DEFW");
for (i = 0; i < 4; i++)
{
if (i > 0)
{
if (memopt[dis.pc].symbol)
break;
if (memopt[dis.pc].comment)
break;
if (NEWOPT(dis.pc))
break;
dis.dst += pad_argument(",");
}
dis.val16 = mem[dis.pc++];
dis.val16 += mem[dis.pc++] << 8;
dis.dst += pad_argument("%s", hexw(dis.val16));
}
return i;
}
int dis_entry(void)
{
dis.dst += pad_opcode("DEFW");
dis.val16 = mem[dis.pc++];
dis.val16 += mem[dis.pc++] << 8;
dis.dst += pad_argument("%s", SYM_get(dis.val16, SYM_NONE));
return 1;
}
double frac2[56] = {
0.5,
0.25,
0.125,
0.0625,
0.03125,
0.015625,
0.0078125,
0.00390625,
0.001953125,
0.0009765625,
0.00048828125,
0.000244140625,
0.0001220703125,
0.00006103515625,
0.000030517578125,
0.0000152587890625,
0.00000762939453125,
0.000003814697265625,
0.0000019073486328125,
0.00000095367431640625,
0.000000476837158203125,
0.0000002384185791015625,
0.00000011920928955078125,
0.000000059604644775390625,
0.0000000298023223876953125,
0.00000001490116119384765625,
0.000000007450580596923828125,
0.0000000037252902984619140625,
0.00000000186264514923095703125,
0.000000000931322574615478515625,
0.0000000004656612873077392578125,
0.00000000023283064365386962890625,
0.000000000116415321826934814453125,
0.0000000000582076609134674072265625,
0.00000000002910383045673370361328125,
0.000000000014551915228366851806640625,
0.0000000000072759576141834259033203125,
0.00000000000363797880709171295166015625,
0.000000000001818989403545856475830078125,
0.0000000000009094947017729282379150390625,
0.00000000000045474735088646411895751953125,
0.000000000000227373675443232059478759765625,
0.0000000000001136868377216160297393798828125,
0.00000000000005684341886080801486968994140625,
0.000000000000028421709430404007434844970703125,
0.0000000000000142108547152020037174224853515625,
0.00000000000000710542735760100185871124267578125,
0.000000000000003552713678800500929355621337890625,
0.0000000000000017763568394002504646778106689453125,
0.00000000000000088817841970012523233890533447265625,
0.000000000000000444089209850062616169452667236328125,
0.0000000000000002220446049250313080847263336181640625,
0.00000000000000011102230246251565404236316680908203125,
0.000000000000000055511151231257827021181583404541015625,
0.0000000000000000277555756156289135105907917022705078125,
0.00000000000000001387778780781445675529539585113525390625,
};
int dis_float_single(void)
{
BYTE b[4];
int i;
double df;
b[0] = mem[dis.pc++];
b[1] = mem[dis.pc++];
b[2] = mem[dis.pc++];
b[3] = mem[dis.pc++];
dis.fsng.man = b[0];
dis.fsng.man += b[1] << 8;
dis.fsng.man += b[2] << 16;
dis.fsng.exp = b[3] - 128;
dis.dst += pad_opcode("DEFB");
dis.dst += pad_argument("%s,%s,%s,%s", hexb(b[0]), hexb(b[1]), hexb(b[2]), hexb(b[3]));
if (dis.prtcom)
return 1;
df = frac2[0];
for (i = 1; i < 24; i++)
if (dis.fsng.man & (0x800000 >> i))
df += frac2[i];
if (dis.fsng.exp > 0)
df *= 1 << dis.fsng.exp;
else
df /= 1 << -dis.fsng.exp;
if (dis.fsng.man & 0x800000)
df = -df;
dis.dst += pad_comment(" %g", df);
return 1;
}
int dis_float_double(void)
{
BYTE b[8];
int i;
double df;
b[0] = mem[dis.pc++];
b[1] = mem[dis.pc++];
b[2] = mem[dis.pc++];
b[3] = mem[dis.pc++];
b[4] = mem[dis.pc++];
b[5] = mem[dis.pc++];
b[6] = mem[dis.pc++];
b[7] = mem[dis.pc++];
dis.fdbl.manl = b[0];
dis.fdbl.manl += b[1] << 8;
dis.fdbl.manl += b[2] << 16;
dis.fdbl.manl += b[3] << 24;
dis.fdbl.manh = b[4];
dis.fdbl.manh += b[5] << 8;
dis.fdbl.manh += b[6] << 16;
dis.fdbl.exp = b[7] - 128;
dis.dst += pad_opcode("DEFB");
dis.dst += pad_argument("%s,%s,%s,%s,%s,%s,%s,%s", hexb(b[0]), hexb(b[1]), hexb(b[2]), hexb(b[3]), hexb(b[4]), hexb(b[5]), hexb(b[6]), hexb(b[7]));
if (dis.prtcom)
return 1;
df = frac2[0];
for (i = 1; i < 32; i++)
if (dis.fdbl.manl & (0x80000000 >> i))
df += frac2[i];
for (i = 0; i < 24; i++)
if (dis.fdbl.manh & (0x800000 >> i))
df += frac2[32+i];
if (dis.fdbl.exp > 0)
df *= 1 << dis.fdbl.exp;
else
df /= 1 << -dis.fdbl.exp;
if (dis.fdbl.manh & 0x800000)
df = -df;
dis.dst += pad_comment(" %g", df);
return 1;
}
char * dis_data(WORD * addr)
{
char * phex;
int cnt;
dis.pc = *addr;
dis.dst = dis.buff + sprintf(dis.buff, "%04X:", dis.pc);
phex = dis.dst;
switch (dis.curopt.opt)
{
case OPT_BYTES:
cnt = dis_bytes();
break;
case OPT_ASCII:
cnt = dis_ascii();
break;
case OPT_7BIT:
cnt = dis_7bit();
break;
case OPT_WORDS:
cnt = dis_words();
break;
case OPT_ENTRY:
cnt = dis_entry();
break;
case OPT_FSNG:
cnt = dis_float_single();
break;
case OPT_FDBL:
cnt = dis_float_double();
break;
default:
cnt = dis_bytes();
break;
}
dis.pc = *addr;
while (cnt--)
{
switch (dis.curopt.size)
{
case 0:
dis.val8 = mem[dis.pc++];
phex += sprintf(phex, "%02X ", dis.val8);
break;
case 1:
dis.val16 = mem[dis.pc++];
dis.val16 += mem[dis.pc++] << 8;
phex += sprintf(phex, "%04X ", dis.val16);
break;
case 2:
dis.fsng.man = mem[dis.pc++];
dis.fsng.man += mem[dis.pc++] << 8;
dis.fsng.man += mem[dis.pc++] << 16;
dis.fsng.exp = mem[dis.pc++];
phex += sprintf(phex, "%06X %02X", dis.fsng.man, (unsigned) dis.fsng.exp);
break;
case 3:
dis.fdbl.manl = mem[dis.pc++];
dis.fdbl.manl+= mem[dis.pc++] << 8;
dis.fdbl.manl+= mem[dis.pc++] << 16;
dis.fdbl.manl+= mem[dis.pc++] << 24;
dis.fdbl.manh = mem[dis.pc++];
dis.fdbl.manh+= mem[dis.pc++] << 8;
dis.fdbl.manh+= mem[dis.pc++] << 16;
dis.fdbl.exp = mem[dis.pc++] - 128;
phex += sprintf(phex, "%06X%08X %02X ", dis.fdbl.manh, dis.fdbl.manl, (unsigned) dis.fdbl.exp);
break;
}
}
*phex = ' ';
if (dis.prtcom)
{
dis.prtcom = 0;
dis.dst += pad_comment(" %s", COM_get(*addr, COM_APPEND));
}
*addr = dis.pc;
return dis.buff;
}
void disasm_init(WORD addr)
{
memset(&z80, 0, sizeof(z80));
dis.curopt = memopt[addr];
if (dis.curopt.comment)
{
dis.curopt.comment = 0;
dis.prtcom = 1;
}
if (dis.curopt.symbol)
{
dis.curopt.symbol = 0;
dis.prtsym = 1;
}
}
char * disasm(WORD * addr, BOOL flg_dump)
{
char * src;
char * dst = "";
WORD addr_cmd;
addr_cmd = *addr;
memset(&dis.flag, 0, sizeof(dis.flag));
dis.padcom = 0;
if (dis.prtcom)
{
dis.prtcom = 0;
src = COM_get(*addr, COM_BLOCK);
if (src && strlen(src))
{
dst = dis.buff;
sprintf(dst, ";****** %s", COM_get(addr_cmd, COM_BLOCK));
return dst;
}
}
if (flg_dump)
{
if (dis.prtsym)
{
dis.prtsym = 0;
dst = dis.buff;
if (dis.curopt.mode == MEM_CODE)
sprintf(dst, "%s:", SYM_get(addr_cmd, SYM_NONE));
else
sprintf(dst, "%-*sEQU $", COLUMN_OPCODE, SYM_get(addr_cmd, SYM_NONE));
return dst;
}
}
switch (dis.curopt.mode)
{
case MEM_UNKNOWN:
dst = dis_data(addr);
break;
case MEM_CODE:
dst = dis_code(addr);
break;
case MEM_DATA:
dst = dis_data(addr);
break;
case MEM_IO:
dst = dis_data(addr);
break;
}
if (!flg_dump)
{
if (dis.prtsym)
{
dis.prtsym = 0;
dst[sprintf(dst, "%-*s ", COLUMN_OPCODE-2, SYM_get(addr_cmd, SYM_NONE))] = ' ';
}
else
{
dst[sprintf(dst, "%-*s", COLUMN_OPCODE-1, "")] = ' ';
}
}
if (NEWOPT(*addr))
{
BYTE old_mode = dis.curopt.mode;
BYTE old_opt = dis.curopt.opt;
dis.curopt = memopt[*addr];
if (dis.curopt.mode == MEM_UNKNOWN)
{
dis.curopt.mode = old_mode;
if (dis.curopt.opt == OPT_NONE)
dis.curopt.opt = old_opt;
}
if (dis.curopt.comment)
{
dis.curopt.comment = 0;
dis.prtcom = 1;
}
if (dis.curopt.symbol)
{
dis.curopt.symbol = 0;
dis.prtsym = 1;
}
}
if (dis.prtsym || dis.flag.end_mode)
strcat(dst, "\n");
return dst;
}