1923 lines
41 KiB
C
1923 lines
41 KiB
C
/*
|
|
* Disasm.c
|
|
*
|
|
* This file is part of Emu48, a ported version of x48
|
|
*
|
|
* Copyright (C) 1994 Eddie C. Dost
|
|
* Copyright (C) 1998 Christoph Gießelink
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
#include "Emu48.h"
|
|
|
|
#define TAB_SKIP 8
|
|
|
|
BOOL disassembler_mode = HP_MNEMONICS;
|
|
WORD disassembler_map = MEM_MAP;
|
|
|
|
static char *hex[] =
|
|
{
|
|
"0123456789ABCDEF",
|
|
"0123456789abcdef",
|
|
};
|
|
|
|
static char *opcode_0_tbl[32] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"RTNSXM", "RTN", "RTNSC", "RTNCC",
|
|
"SETHEX", "SETDEC", "RSTK=C", "C=RSTK",
|
|
"CLRST", "C=ST", "ST=C", "CSTEX",
|
|
"P=P+1", "P=P-1", "(NULL)", "RTI",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"rtnsxm", "rtn", "rtnsc", "rtncc",
|
|
"sethex", "setdec", "push", "pop",
|
|
"clr.3 st", "move.3 st, c", "move.3 c, st", "exg.3 c, st",
|
|
"inc.1 p", "dec.1 p", "(null)", "rti"
|
|
};
|
|
|
|
static char *op_str_0[16] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"A=A%cB", "B=B%cC", "C=C%cA", "D=D%cC",
|
|
"B=B%cA", "C=C%cB", "A=A%cC", "C=C%cD",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"b, a", "c, b", "a, c", "c, d",
|
|
"a, b", "b, c", "c, a", "d, c"
|
|
};
|
|
|
|
static char *op_str_1[16] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"DAT0=A", "DAT1=A", "A=DAT0", "A=DAT1",
|
|
"DAT0=C", "DAT1=C", "C=DAT0", "C=DAT1",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"a, (d0)", "a, (d1)", "(d0), a", "(d1), a",
|
|
"c, (d0)", "c, (d1)", "(d0), c", "(d1), c"
|
|
};
|
|
|
|
static char *in_str_80[32] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"OUT=CS", "OUT=C", "A=IN", "C=IN",
|
|
"UNCNFG", "CONFIG", "C=ID", "SHUTDN",
|
|
NULL, "C+P+1", "RESET", "BUSCC",
|
|
NULL, NULL, "SREQ?", NULL,
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"move.s c, out", "move.3 c, out", "move.4 in, a", "move.4 in, c",
|
|
"uncnfg", "config", "c=id", "shutdn",
|
|
NULL, "add.a p+1, c", "reset", "buscc",
|
|
NULL, NULL, "sreq?", NULL
|
|
};
|
|
|
|
static char *in_str_808[32] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"INTON", NULL, NULL, "BUSCB",
|
|
NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL,
|
|
"PC=(A)", "BUSCD", "PC=(C)", "INTOFF",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"inton", NULL, NULL, "buscb",
|
|
NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL,
|
|
"jmp (a)", "buscd", "jmp (c)", "intoff"
|
|
};
|
|
|
|
static char *op_str_81[8] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"A", "B", "C", "D",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"a", "b", "c", "d",
|
|
};
|
|
|
|
static char *in_str_81b[32] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
NULL, NULL, "PC=A", "PC=C",
|
|
"A=PC", "C=PC", "APCEX", "CPCEX",
|
|
NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL,
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
NULL, NULL, "jmp a", "jmp c",
|
|
"move.a pc, a", "move.a pc, c", "exg.a a, pc", "exg.a c, pc",
|
|
NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL,
|
|
};
|
|
|
|
static char *in_str_9[16] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"=", "#", "=", "#",
|
|
">", "<", ">=", "<=",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"eq", "ne", "eq", "ne",
|
|
"gt", "lt", "ge", "le"
|
|
};
|
|
|
|
static char *op_str_9[16] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"?A%sB", "?B%sC", "?C%sA", "?D%sC",
|
|
"?A%s0", "?B%s0", "?C%s0", "?D%s0",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"a, b", "b, c", "c, a", "d, c",
|
|
"a, 0", "b, 0", "c, 0", "d, 0"
|
|
};
|
|
|
|
static char *op_str_af[32] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"A=A%sB", "B=B%sC", "C=C%sA", "D=D%sC",
|
|
"A=A%sA", "B=B%sB", "C=C%sC", "D=D%sD",
|
|
"B=B%sA", "C=C%sB", "A=A%sC", "C=C%sD",
|
|
"A=B%sA", "B=C%sB", "C=A%sC", "D=C%sD",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"b, a", "c, b", "a, c", "c, d",
|
|
"a, a", "b, b", "c, c", "d, d",
|
|
"a, b", "b, c", "c, a", "d, c",
|
|
"b, a", "c, b", "a, c", "c, d"
|
|
};
|
|
|
|
static char hp_reg_1_af[] = "ABCDABCDBCACABAC";
|
|
static char hp_reg_2_af[] = "0000BCACABCDBCCD";
|
|
|
|
static char *field_tbl[32] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"P", "WP", "XS", "X",
|
|
"S", "M", "B", "W",
|
|
"P", "WP", "XS", "X",
|
|
"S", "M", "B", "A",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
".p", ".wp", ".xs", ".x",
|
|
".s", ".m", ".b", ".w",
|
|
".p", ".wp", ".xs", ".x",
|
|
".s", ".m", ".b", ".a",
|
|
};
|
|
|
|
static char *hst_bits[8] =
|
|
{
|
|
/*
|
|
* HP Mnemonics
|
|
*/
|
|
"XM", "SB", "SR", "MP",
|
|
/*
|
|
* Class Mnemonics
|
|
*/
|
|
"xm", "sb", "sr", "mp",
|
|
};
|
|
|
|
|
|
// static functions
|
|
|
|
static BYTE rn_map (DWORD *p)
|
|
{
|
|
DWORD d = *p;
|
|
|
|
*p = ++(*p) & 0xFFFFF;
|
|
|
|
_ASSERT(d < 0x100000);
|
|
return *(RMap[d>>12]+(d&0xFFF));
|
|
}
|
|
|
|
static BYTE rn_rom (DWORD *p)
|
|
{
|
|
DWORD d = *p;
|
|
|
|
*p = ++(*p) & (dwRomSize - 1);
|
|
|
|
_ASSERT(d < dwRomSize);
|
|
return *(pbyRom + d);
|
|
}
|
|
|
|
static BYTE rn_ram (DWORD *p)
|
|
{
|
|
DWORD d = *p;
|
|
|
|
*p = ++(*p) & (Chipset.Port0Size * 2048 - 1);
|
|
|
|
_ASSERT(d < Chipset.Port0Size * 2048);
|
|
return *(Chipset.Port0 + d);
|
|
}
|
|
|
|
static BYTE rn_port1 (DWORD *p)
|
|
{
|
|
DWORD d = *p;
|
|
|
|
*p = ++(*p) & (Chipset.Port1Size * 2048 - 1);
|
|
|
|
_ASSERT(d < Chipset.Port1Size * 2048);
|
|
return *(Chipset.Port1 + d);
|
|
}
|
|
|
|
static BYTE rn_port2 (DWORD *p)
|
|
{
|
|
BYTE *pbyVal;
|
|
DWORD d = *p;
|
|
|
|
if (cCurrentRomType=='X') // HP49G
|
|
{
|
|
*p = ++(*p) & (Chipset.Port2Size * 2048 - 1);
|
|
|
|
_ASSERT(d < Chipset.Port2Size * 2048);
|
|
pbyVal = Chipset.Port2;
|
|
}
|
|
else // HP48SX/GX
|
|
{
|
|
*p = ++(*p) & (((dwPort2Mask + 1) << 18) - 1);
|
|
|
|
_ASSERT(d < ((dwPort2Mask + 1) << 18));
|
|
pbyVal = pbyPort2;
|
|
}
|
|
return *(pbyVal + d);
|
|
}
|
|
|
|
static BYTE read_nibble (DWORD *p)
|
|
{
|
|
BYTE (*pnread[])(DWORD *) = { rn_map, rn_rom, rn_ram, rn_port1, rn_port2 };
|
|
|
|
_ASSERT(disassembler_map < sizeof(pnread) / sizeof(pnread[0]));
|
|
return pnread[disassembler_map](p);
|
|
}
|
|
|
|
// general functions
|
|
|
|
static int read_int (DWORD *addr, int n)
|
|
{
|
|
int i, t;
|
|
|
|
for (i = 0, t = 0; i < n; i++)
|
|
t |= read_nibble (addr) << (i * 4);
|
|
|
|
return t;
|
|
}
|
|
|
|
static char *append_str (char *buf, char *str)
|
|
{
|
|
while ((*buf = *str++))
|
|
buf++;
|
|
return buf;
|
|
}
|
|
|
|
static char *append_tab (char *buf)
|
|
{
|
|
int n;
|
|
char *p;
|
|
|
|
n = TAB_SKIP - (strlen (buf) % TAB_SKIP);
|
|
p = &buf[strlen (buf)];
|
|
while (n--)
|
|
*p++ = ' ';
|
|
*p = 0;
|
|
return p;
|
|
}
|
|
|
|
static char *append_field (char *buf, BYTE fn)
|
|
{
|
|
buf = append_str (buf, field_tbl[fn + 16 * disassembler_mode]);
|
|
return buf;
|
|
}
|
|
|
|
static char *append_imm_nibble (char *buf, DWORD *addr, int n)
|
|
{
|
|
int i;
|
|
char t[16];
|
|
|
|
if (disassembler_mode == CLASS_MNEMONICS)
|
|
{
|
|
*buf++ = '#';
|
|
if (n > 1)
|
|
*buf++ = '$';
|
|
}
|
|
else // HP Mnemonics
|
|
{
|
|
if (n > 1) // hex mode
|
|
*buf++ = '#'; // insert hex header
|
|
}
|
|
if (n > 1)
|
|
{
|
|
for (i = 0; i < n; i++)
|
|
t[i] = hex[disassembler_mode][read_nibble (addr)];
|
|
for (i = n - 1; i >= 0; i--)
|
|
{
|
|
*buf++ = t[i];
|
|
}
|
|
*buf = 0;
|
|
}
|
|
else
|
|
{
|
|
wsprintf (t, "%d", read_nibble (addr));
|
|
buf = append_str (buf, t);
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
static char *append_addr (char *buf, DWORD addr)
|
|
{
|
|
int shift;
|
|
long mask;
|
|
|
|
if (disassembler_mode == CLASS_MNEMONICS)
|
|
{
|
|
*buf++ = '$';
|
|
}
|
|
for (mask = 0xf0000, shift = 16; mask != 0; mask >>= 4, shift -= 4)
|
|
*buf++ = hex[disassembler_mode][(addr & mask) >> shift];
|
|
*buf = 0;
|
|
return buf;
|
|
}
|
|
|
|
static char *append_r_addr (char *buf, DWORD * pc, long disp, int n, int offset)
|
|
{
|
|
long sign;
|
|
|
|
sign = 1 << (n * 4 - 1);
|
|
if (disp & sign)
|
|
disp |= ~(sign - 1);
|
|
*pc += disp;
|
|
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (disp < 0)
|
|
{
|
|
buf = append_str(buf, "-");
|
|
disp = -disp - offset;
|
|
}
|
|
else
|
|
{
|
|
buf = append_str(buf, "+");
|
|
disp += offset;
|
|
}
|
|
buf = append_addr(buf, disp);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
if (disp < 0)
|
|
{
|
|
buf = append_str(buf, "-");
|
|
disp = -disp - offset;
|
|
}
|
|
else
|
|
{
|
|
buf = append_str(buf, "+");
|
|
disp += offset;
|
|
}
|
|
buf = append_addr (buf, disp);
|
|
break;
|
|
default:
|
|
buf = append_str (buf, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
static char *append_pc_comment (char *buf, DWORD pc, BOOL view)
|
|
{
|
|
char *p = buf;
|
|
|
|
if (view == VIEW_LONG) // output of address in remarks
|
|
{
|
|
while (strlen (buf) < 4 * TAB_SKIP)
|
|
p = append_tab (buf);
|
|
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
p = append_str (p, "# Address: ");
|
|
p = append_addr (p, pc);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (p, "; address: ");
|
|
p = append_addr (p, pc);
|
|
break;
|
|
default:
|
|
p = append_str (p, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
}
|
|
else // output of address in brackets
|
|
{
|
|
while (*p) ++p;
|
|
p = append_str (p, " [");
|
|
p = append_addr (p, pc);
|
|
p = append_str (p, "]");
|
|
}
|
|
return p;
|
|
}
|
|
|
|
static char *append_hst_bits (char *buf, int n)
|
|
{
|
|
int i;
|
|
char *p = buf;
|
|
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
for (i = 0; i < 4; i++)
|
|
if (n & (1 << i))
|
|
{
|
|
p = append_str (p, hst_bits[i + 4 * disassembler_mode]);
|
|
}
|
|
break;
|
|
|
|
case CLASS_MNEMONICS:
|
|
while (strlen (buf) < 4 * TAB_SKIP)
|
|
p = append_tab (buf);
|
|
p = &buf[strlen (buf)];
|
|
p = append_str (p, "; hst bits: ");
|
|
|
|
for (buf = p, i = 0; i < 4; i++)
|
|
if (n & (1 << i))
|
|
{
|
|
if (p != buf)
|
|
p = append_str (p, ", ");
|
|
p = append_str (p, hst_bits[i + 4 * disassembler_mode]);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
p = append_str (p, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
static char *disasm_1 (DWORD *addr, char *out)
|
|
{
|
|
BYTE n;
|
|
BYTE fn;
|
|
char *p;
|
|
char buf[20];
|
|
char c;
|
|
|
|
p = out;
|
|
switch (n = read_nibble (addr))
|
|
{
|
|
case 0:
|
|
case 1:
|
|
fn = read_nibble (addr);
|
|
fn = (fn & 7);
|
|
if (fn > 4)
|
|
fn -= 4;
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
c = (char) ((fn < 8) ? 'A' : 'C');
|
|
if (n == 0)
|
|
wsprintf (buf, "R%d=%c", fn, c);
|
|
else
|
|
wsprintf (buf, "%c=R%d", c, fn);
|
|
p = append_str (out, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "move.w");
|
|
p = append_tab (out);
|
|
c = (char) ((fn < 8) ? 'a' : 'c');
|
|
if (n == 0)
|
|
wsprintf (buf, "%c, r%d", c, fn);
|
|
else
|
|
wsprintf (buf, "r%d, %c", fn, c);
|
|
p = append_str (p, buf);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
fn = read_nibble (addr);
|
|
fn = (fn & 7);
|
|
if (fn > 4)
|
|
fn -= 4;
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
c = (char) ((fn < 8) ? 'A' : 'C');
|
|
wsprintf (buf, "%cR%dEX", c, fn);
|
|
p = append_str (out, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "exg.w");
|
|
p = append_tab (out);
|
|
c = (char) ((fn < 8) ? 'a' : 'c');
|
|
wsprintf (buf, "%c, r%d", c, fn);
|
|
p = append_str (p, buf);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
n = read_nibble (addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
c = (n & 4) ? 'C' : 'A';
|
|
if (n & 2)
|
|
{
|
|
if (n < 8)
|
|
{
|
|
wsprintf (buf, "%cD%dEX", c, (n & 1));
|
|
}
|
|
else
|
|
{
|
|
wsprintf (buf, "%cD%dXS", c, (n & 1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (n < 8)
|
|
{
|
|
wsprintf (buf, "D%d=%c", (n & 1), c);
|
|
}
|
|
else
|
|
{
|
|
wsprintf (buf, "D%d=%cS", (n & 1), c);
|
|
}
|
|
}
|
|
p = append_str (out, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (n & 2) ? "exg." : "move.");
|
|
p = append_str (p, (n < 8) ? "a" : "4");
|
|
p = append_tab (out);
|
|
c = (n & 4) ? 'c' : 'a';
|
|
wsprintf (buf, "%c, d%d", c, (n & 1));
|
|
p = append_str (p, buf);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
case 5:
|
|
fn = read_nibble (addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
p = append_str (out, op_str_1[(fn & 7) + 8 * disassembler_mode]);
|
|
p = append_tab (out);
|
|
if (n == 4)
|
|
{
|
|
p = append_str (p, (fn < 8) ? "A" : "B");
|
|
}
|
|
else
|
|
{
|
|
n = read_nibble (addr);
|
|
if (fn < 8)
|
|
{
|
|
p = append_field (p, n);
|
|
}
|
|
else
|
|
{
|
|
wsprintf (buf, "%d", n + 1);
|
|
p = append_str (p, buf);
|
|
}
|
|
}
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "move");
|
|
if (n == 4)
|
|
{
|
|
p = append_str (p, ".");
|
|
p = append_str (p, (fn < 8) ? "a" : "b");
|
|
}
|
|
else
|
|
{
|
|
n = read_nibble (addr);
|
|
if (fn < 8)
|
|
{
|
|
p = append_field (p, n);
|
|
}
|
|
else
|
|
{
|
|
wsprintf (buf, ".%d", n + 1);
|
|
p = append_str (p, buf);
|
|
}
|
|
}
|
|
p = append_tab (out);
|
|
p = append_str (p, op_str_1[(fn & 7) + 8 * disassembler_mode]);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 0xc:
|
|
fn = read_nibble (addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (n == 6 || n == 8)
|
|
p = append_str (out, "D0=D0");
|
|
else
|
|
p = append_str (out, "D1=D1");
|
|
if (n < 8)
|
|
p = append_str (p, "+");
|
|
else
|
|
p = append_str (p, "-");
|
|
p = append_tab (out);
|
|
wsprintf (buf, "%d", fn + 1);
|
|
p = append_str (p, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
if (n < 8)
|
|
p = append_str (out, "add.a");
|
|
else
|
|
p = append_str (out, "sub.a");
|
|
p = append_tab (out);
|
|
wsprintf (buf, "#%d, ", fn + 1);
|
|
p = append_str (p, buf);
|
|
if (n == 6 || n == 8)
|
|
p = append_str (p, "d0");
|
|
else
|
|
p = append_str (p, "d1");
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 9:
|
|
case 0xa:
|
|
case 0xb:
|
|
case 0xd:
|
|
case 0xe:
|
|
case 0xf:
|
|
c = (char) ((n < 0xd) ? '0' : '1');
|
|
switch (n & 3)
|
|
{
|
|
case 1:
|
|
n = 2;
|
|
break;
|
|
case 2:
|
|
n = 4;
|
|
break;
|
|
case 3:
|
|
n = 5;
|
|
break;
|
|
}
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "D%c=(%d)", c, n);
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, addr, n);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
if (n == 5)
|
|
{
|
|
wsprintf (buf, "move.a");
|
|
}
|
|
else
|
|
if (n == 4)
|
|
{
|
|
wsprintf (buf, "move.as");
|
|
}
|
|
else
|
|
{
|
|
wsprintf (buf, "move.b");
|
|
}
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, addr, n);
|
|
wsprintf (buf, ", d%c", c);
|
|
p = append_str (p, buf);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
static char *disasm_8 (DWORD *addr, char *out, BOOL view)
|
|
{
|
|
BYTE n;
|
|
BYTE fn;
|
|
char *p = out;
|
|
char c;
|
|
char buf[20];
|
|
DWORD disp, pc;
|
|
|
|
fn = read_nibble (addr);
|
|
switch (fn)
|
|
{
|
|
case 0:
|
|
n = read_nibble (addr);
|
|
if (NULL != (p = in_str_80[n + 16 * disassembler_mode]))
|
|
{
|
|
p = append_str (out, p);
|
|
return p;
|
|
}
|
|
switch (n)
|
|
{
|
|
case 8:
|
|
fn = read_nibble (addr);
|
|
if (NULL != (p = in_str_808[fn + 16 * disassembler_mode]))
|
|
{
|
|
p = append_str (out, p);
|
|
return p;
|
|
}
|
|
switch (fn)
|
|
{
|
|
case 1:
|
|
n = read_nibble (addr);
|
|
if (n == 0)
|
|
{
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
p = append_str (out, "RSI");
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "rsi");
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
n = read_nibble (addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (n < 5)
|
|
{
|
|
wsprintf (buf, "LA(%d)", n + 1);
|
|
}
|
|
else
|
|
{
|
|
wsprintf (buf, "LAHEX");
|
|
}
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, addr, n + 1);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
wsprintf (buf, "move.%d", n + 1);
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, addr, n + 1);
|
|
wsprintf (buf, ", a.p");
|
|
p = append_str (p, buf);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
case 5:
|
|
case 8:
|
|
case 9:
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "%cBIT=%d", (fn & 8) ? 'C' : 'A',
|
|
(fn & 1) ? 1 : 0);
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, addr, 1);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (fn & 1) ? "bset" : "bclr");
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, addr, 1);
|
|
p = append_str (p, (fn & 8) ? ", c" : ", a");
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
case 7:
|
|
case 0xa:
|
|
case 0xb:
|
|
n = read_nibble (addr);
|
|
pc = *addr;
|
|
disp = read_int (addr, 2);
|
|
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
c = (char) ((fn < 0xa) ? 'A' : 'C');
|
|
wsprintf (buf, "?%cBIT=%d", c, (fn & 1) ? 1 : 0);
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
wsprintf (buf, "%d", n);
|
|
p = append_str (p, buf);
|
|
if (disp != 0)
|
|
{
|
|
p = append_str (p, ", GOYES ");
|
|
p = append_r_addr (p, &pc, disp, 2, 5);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
else
|
|
p = append_str (p, ", RTNYES");
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
c = (char) ((fn < 0xa) ? 'a' : 'c');
|
|
p = append_str (out, (disp == 0) ? "rt" : "b");
|
|
p = append_str (p, (fn & 1) ? "bs" : "bc");
|
|
p = append_tab (out);
|
|
wsprintf (buf, "#%d, %c", n, c);
|
|
p = append_str (p, buf);
|
|
if (disp != 0)
|
|
{
|
|
p = append_str (p, ", ");
|
|
p = append_r_addr (p, &pc, disp, 2, 5);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0xc:
|
|
case 0xd:
|
|
case 0xf:
|
|
fn = read_nibble (addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, (n == 0xf) ? "%c%cEX" : "%c=%c",
|
|
(n == 0xd) ? 'P' : 'C', (n == 0xd) ? 'C' : 'P');
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
wsprintf (buf, "%d", fn);
|
|
p = append_str (p, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (n == 0xf) ? "exg.1" : "move.1");
|
|
p = append_tab (out);
|
|
wsprintf (buf, (n == 0xd) ? "p, c.%d" : "c.%d, p", fn);
|
|
p = append_str (p, buf);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
switch (n = read_nibble (addr))
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "%sSLC", op_str_81[(n & 3) + 4 * disassembler_mode]);
|
|
p = append_str (out, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "rol.w");
|
|
p = append_tab (out);
|
|
p = append_str (p, "#4, ");
|
|
p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "%sSRC", op_str_81[(n & 3) + 4 * disassembler_mode]);
|
|
p = append_str (out, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "ror.w");
|
|
p = append_tab (out);
|
|
p = append_str (p, "#4, ");
|
|
p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
fn = read_nibble (addr);
|
|
n = read_nibble (addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "%s=%s%cCON",
|
|
op_str_81[(n & 3) + 4 * disassembler_mode],
|
|
op_str_81[(n & 3) + 4 * disassembler_mode],
|
|
(n < 8) ? '+' : '-');
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_field (p, fn);
|
|
fn = read_nibble (addr);
|
|
wsprintf (buf, ", %d", fn + 1);
|
|
p = append_str (p, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (n < 8) ? "add" : "sub");
|
|
p = append_field (p, fn);
|
|
p = append_tab (out);
|
|
fn = read_nibble (addr);
|
|
wsprintf (buf, "#%d, ", fn + 1);
|
|
p = append_str (p, buf);
|
|
p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 9:
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "%sSRB.F",
|
|
op_str_81[(n & 3) + 4 * disassembler_mode]);
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_field (p, read_nibble (addr));
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "lsr");
|
|
p = append_field (p, read_nibble (addr));
|
|
p = append_tab (out);
|
|
p = append_str (p, "#1, ");
|
|
p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0xa:
|
|
fn = read_nibble (addr);
|
|
n = read_nibble (addr);
|
|
if (n > 2)
|
|
break;
|
|
c = (char) read_nibble (addr);
|
|
if (((int) c & 7) > 4)
|
|
break;
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (n == 2)
|
|
{
|
|
wsprintf (buf, "%cR%dEX.F", ((int) c < 8) ? 'A' : 'C',
|
|
(int) c & 7);
|
|
}
|
|
else
|
|
if (n == 1)
|
|
{
|
|
wsprintf (buf, "%c=R%d.F", ((int) c < 8) ? 'A' : 'C',
|
|
(int) c & 7);
|
|
}
|
|
else
|
|
{
|
|
wsprintf (buf, "R%d=%c.F", (int) c & 7,
|
|
((int) c < 8) ? 'A' : 'C');
|
|
}
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_field (p, fn);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (n == 2) ? "exg" : "move");
|
|
p = append_field (p, fn);
|
|
p = append_tab (out);
|
|
if (n == 1)
|
|
{
|
|
wsprintf (buf, "r%d", (int) c & 7);
|
|
p = append_str (p, buf);
|
|
}
|
|
else
|
|
p = append_str (p, ((int) c < 8) ? "a" : "c");
|
|
p = append_str (p, ", ");
|
|
if (n == 1)
|
|
p = append_str (p, ((int) c < 8) ? "a" : "c");
|
|
else
|
|
{
|
|
wsprintf (buf, "r%d", (int) c & 7);
|
|
p = append_str (p, buf);
|
|
}
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0xb:
|
|
n = read_nibble (addr);
|
|
if ((n < 2) || (n > 7))
|
|
break;
|
|
|
|
p = append_str (out, in_str_81b[n + 16 * disassembler_mode]);
|
|
break;
|
|
|
|
case 0xc:
|
|
case 0xd:
|
|
case 0xe:
|
|
case 0xf:
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "%sSRB", op_str_81[(n & 3) + 4 * disassembler_mode]);
|
|
p = append_str (out, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "lsr.w");
|
|
p = append_tab (out);
|
|
p = append_str (p, "#1, ");
|
|
p = append_str (p, op_str_81[(n & 3) + 4 * disassembler_mode]);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
n = read_nibble (addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (n == 0xf)
|
|
{
|
|
p = append_str (out, "CLRHST");
|
|
}
|
|
else
|
|
{
|
|
// when not only one bit is set the HS=0 opcode is used
|
|
if (n != 1 && n != 2 && n != 4 && n != 8)
|
|
{
|
|
p = append_str (out, "HS=0");
|
|
p = append_tab (out);
|
|
wsprintf (buf, "%d", n);
|
|
p = append_str (p, buf);
|
|
}
|
|
else
|
|
{
|
|
p = append_hst_bits (out, n);
|
|
p = append_str (p, "=0");
|
|
}
|
|
}
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "clr.1");
|
|
p = append_tab (out);
|
|
wsprintf (buf, "#%d, hst", n);
|
|
p = append_str (p, buf);
|
|
p = append_hst_bits (out, n);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
n = read_nibble (addr);
|
|
pc = *addr;
|
|
disp = read_int (addr, 2);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
p = append_str (out, "?");
|
|
p = append_hst_bits (p, n);
|
|
p = append_str (p, "=0");
|
|
p = append_tab (out);
|
|
if (disp != 0)
|
|
{
|
|
p = append_str (p, "GOYES ");
|
|
p = append_r_addr (p, &pc, disp, 2, 3);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
else
|
|
p = append_str (p, "RTNYES");
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (disp == 0) ? "rt" : "b");
|
|
p = append_str (p, "eq.1");
|
|
p = append_tab (out);
|
|
wsprintf (buf, "#%d, hst", n);
|
|
p = append_str (p, buf);
|
|
if (disp != 0)
|
|
{
|
|
p = append_str (p, ", ");
|
|
p = append_r_addr (p, &pc, disp, 2, 3);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
p = append_hst_bits (out, n);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
case 5:
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "ST=%d", (fn == 4) ? 0 : 1);
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, addr, 1);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (fn == 4) ? "bclr" : "bset");
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, addr, 1);
|
|
p = append_str (p, ", st");
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
case 7:
|
|
n = read_nibble (addr);
|
|
pc = *addr;
|
|
disp = read_int (addr, 2);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "?ST=%d", (fn == 6) ? 0 : 1);
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
wsprintf (buf, "%d", n);
|
|
p = append_str (p, buf);
|
|
if (disp != 0)
|
|
{
|
|
p = append_str (p, ", GOYES ");
|
|
p = append_r_addr (p, &pc, disp, 2, 3);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
else
|
|
p = append_str (p, ", RTNYES");
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (disp == 0) ? "rt" : "b");
|
|
p = append_str (p, (fn == 6) ? "bc" : "bs");
|
|
p = append_tab (out);
|
|
wsprintf (buf, "#%d, st", n);
|
|
p = append_str (p, buf);
|
|
if (disp != 0)
|
|
{
|
|
p = append_str (p, ", ");
|
|
p = append_r_addr (p, &pc, disp, 2, 3);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
case 9:
|
|
n = read_nibble (addr);
|
|
pc = *addr;
|
|
disp = read_int (addr, 2);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, "?P%c", (fn == 8) ? '#' : '=');
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
wsprintf (buf, "%d", n);
|
|
p = append_str (p, buf);
|
|
if (disp != 0)
|
|
{
|
|
p = append_str (p, ", GOYES ");
|
|
p = append_r_addr (p, &pc, disp, 2, 3);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
else
|
|
p = append_str (p, ", RTNYES");
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (disp == 0) ? "rt" : "b");
|
|
p = append_str (p, (fn == 8) ? "ne.1" : "eq.1");
|
|
p = append_tab (out);
|
|
wsprintf (buf, "#%d, p", n);
|
|
p = append_str (p, buf);
|
|
if (disp != 0)
|
|
{
|
|
p = append_str (p, ", ");
|
|
p = append_r_addr (p, &pc, disp, 2, 3);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0xc:
|
|
case 0xe:
|
|
pc = *addr;
|
|
if (fn == 0xe)
|
|
pc += 4;
|
|
disp = read_int (addr, 4);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
p = append_str (out, (fn == 0xc) ? "GOLONG" : "GOSUBL");
|
|
p = append_tab (out);
|
|
p = append_r_addr (p, &pc, disp, 4, (fn == 0xc) ? 2 : 6);
|
|
p = append_pc_comment (out, pc, view);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (fn == 0xc) ? "bra.4" : "bsr.4");
|
|
p = append_tab (out);
|
|
p = append_r_addr (p, &pc, disp, 4, (fn == 0xc) ? 2 : 6);
|
|
p = append_pc_comment (out, pc, view);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0xd:
|
|
case 0xf:
|
|
pc = read_int (addr, 5);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
p = append_str (out, (fn == 0xd) ? "GOVLNG" : "GOSBVL");
|
|
p = append_tab (out);
|
|
p = append_addr (p, pc);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (fn == 0xd) ? "jmp" : "jsr");
|
|
p = append_tab (out);
|
|
p = append_addr (p, pc);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
|
|
// public functions
|
|
|
|
DWORD disassemble (DWORD addr, LPSTR out, BOOL view)
|
|
{
|
|
BYTE n;
|
|
BYTE fn;
|
|
char *p = out;
|
|
char c;
|
|
char buf[20];
|
|
DWORD disp, pc;
|
|
|
|
switch (n = read_nibble (&addr))
|
|
{
|
|
case 0:
|
|
if ((n = read_nibble (&addr)) != 0xe)
|
|
{
|
|
p = append_str (out, opcode_0_tbl[n + 16 * disassembler_mode]);
|
|
break;
|
|
}
|
|
fn = read_nibble (&addr);
|
|
n = read_nibble (&addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
wsprintf (buf, op_str_0[(n & 7) + 8 * HP_MNEMONICS],
|
|
(n < 8) ? '&' : '!');
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_field (p, fn);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (n < 8) ? "and" : "or");
|
|
p = append_field (p, fn);
|
|
p = append_tab (out);
|
|
p = append_str (p, op_str_0[(n & 7) + 8 * CLASS_MNEMONICS]);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
p = disasm_1 (&addr, out);
|
|
break;
|
|
|
|
case 2:
|
|
n = read_nibble (&addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
p = append_str (out, "P=");
|
|
p = append_tab (out);
|
|
wsprintf (buf, "%d", n);
|
|
p = append_str (p, buf);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
wsprintf (buf, "move.1 #%d, p", n);
|
|
p = append_str (out, buf);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
fn = read_nibble (&addr);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (fn < 5)
|
|
{
|
|
wsprintf (buf, "LC(%d)", fn + 1);
|
|
}
|
|
else
|
|
{
|
|
wsprintf (buf, "LCHEX");
|
|
}
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, &addr, fn + 1);
|
|
break;
|
|
case CLASS_MNEMONICS:
|
|
wsprintf (buf, "move.%d", fn + 1);
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_imm_nibble (p, &addr, fn + 1);
|
|
wsprintf (buf, ", c.p");
|
|
p = append_str (p, buf);
|
|
break;
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
case 5:
|
|
pc = addr;
|
|
disp = read_int (&addr, 2);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (disp == 2)
|
|
{
|
|
p = append_str (out, "NOP3");
|
|
break;
|
|
}
|
|
wsprintf (buf, (disp == 0) ? "RTN%sC" : "GO%sC", (n == 4) ? "" : "N");
|
|
p = append_str (out, buf);
|
|
if (disp != 0)
|
|
{
|
|
p = append_tab (out);
|
|
p = append_r_addr (p, &pc, disp, 2, 1);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
break;
|
|
|
|
case CLASS_MNEMONICS:
|
|
if (disp == 2)
|
|
{
|
|
p = append_str (out, "nop3");
|
|
break;
|
|
}
|
|
p = append_str (out, (disp == 0) ? "rtc" : "bc");
|
|
p = append_str (p, (n == 4) ? "s" : "c");
|
|
if (disp != 0)
|
|
{
|
|
p = append_tab (out);
|
|
p = append_r_addr (p, &pc, disp, 2, 1);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
pc = addr;
|
|
disp = read_int (&addr, 3);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (disp == 3)
|
|
{
|
|
p = append_str (out, "NOP4");
|
|
break;
|
|
}
|
|
if (disp == 4)
|
|
{
|
|
p = append_str (out, "NOP5");
|
|
break;
|
|
}
|
|
p = append_str (out, "GOTO");
|
|
p = append_tab (out);
|
|
p = append_r_addr (p, &pc, disp, 3, 1);
|
|
p = append_pc_comment (out, pc, view);
|
|
break;
|
|
|
|
case CLASS_MNEMONICS:
|
|
if (disp == 3)
|
|
{
|
|
p = append_str (out, "nop4");
|
|
break;
|
|
}
|
|
if (disp == 4)
|
|
{
|
|
p = append_str (out, "nop5");
|
|
break;
|
|
}
|
|
p = append_str (out, "bra.3");
|
|
p = append_tab (out);
|
|
p = append_r_addr (p, &pc, disp, 3, 1);
|
|
p = append_pc_comment (out, pc, view);
|
|
break;
|
|
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 7:
|
|
pc = addr + 3;
|
|
disp = read_int (&addr, 3);
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
p = append_str (out, "GOSUB");
|
|
p = append_tab (out);
|
|
p = append_r_addr (p, &pc, disp, 3, 4);
|
|
p = append_pc_comment (out, pc, view);
|
|
break;
|
|
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, "bsr.3");
|
|
p = append_tab (out);
|
|
p = append_r_addr (p, &pc, disp, 3, 4);
|
|
p = append_pc_comment (out, pc, view);
|
|
break;
|
|
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
fn = read_nibble (&addr); /* PEEK */
|
|
--addr;
|
|
if (fn != 0xa && fn != 0xb)
|
|
{
|
|
p = disasm_8 (&addr, out, view);
|
|
break;
|
|
}
|
|
/* Fall through */
|
|
|
|
case 9:
|
|
fn = read_nibble (&addr);
|
|
if (n == 8)
|
|
{
|
|
c = (char) ((fn == 0xa) ? 0 : 1);
|
|
fn = 0xf;
|
|
}
|
|
else
|
|
{
|
|
c = (char) ((fn < 8) ? 0 : 1);
|
|
fn &= 7;
|
|
}
|
|
|
|
n = read_nibble (&addr);
|
|
pc = addr;
|
|
disp = read_int (&addr, 2);
|
|
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if ((c == 0) && (n >= 8))
|
|
wsprintf (buf, op_str_9[(n & 3) + 8 * HP_MNEMONICS + 4],
|
|
in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]);
|
|
else
|
|
wsprintf (buf, op_str_9[(n & 3) + 8 * HP_MNEMONICS],
|
|
in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]);
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_field (p, fn);
|
|
p = append_str (p, ", ");
|
|
p = append_str (p, (disp == 0) ? "RTNYES" : "GOYES ");
|
|
if (disp != 0)
|
|
{
|
|
p = append_r_addr (p, &pc, disp, 2, 3);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
break;
|
|
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, (disp == 0) ? "rt" : "b");
|
|
p = append_str (p, in_str_9[((n >> 2) & 3) + 4 * c + 8 * CLASS_MNEMONICS]);
|
|
p = append_field (p, fn);
|
|
p = append_tab (out);
|
|
if ((c == 0) && (n >= 8))
|
|
p = append_str (p, op_str_9[(n & 3) + 8 * CLASS_MNEMONICS + 4]);
|
|
else
|
|
p = append_str (p, op_str_9[(n & 3) + 8 * CLASS_MNEMONICS]);
|
|
if (disp != 0)
|
|
{
|
|
p = append_str (p, ", ");
|
|
p = append_r_addr (p, &pc, disp, 2, 3);
|
|
p = append_pc_comment (out, pc, view);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
switch (n)
|
|
{
|
|
case 0xa:
|
|
fn = read_nibble (&addr);
|
|
c = (char) ((fn < 8) ? 0 : 1);
|
|
fn &= 7;
|
|
disp = 0xa;
|
|
break;
|
|
case 0xb:
|
|
fn = read_nibble (&addr);
|
|
c = (char) ((fn < 8) ? 0 : 1);
|
|
fn &= 7;
|
|
disp = 0xb;
|
|
break;
|
|
case 0xc:
|
|
case 0xd:
|
|
fn = 0xf;
|
|
c = (char) (n & 1);
|
|
disp = 0xa;
|
|
break;
|
|
case 0xe:
|
|
case 0xf:
|
|
fn = 0xf;
|
|
c = (char) (n & 1);
|
|
disp = 0xb;
|
|
break;
|
|
default:
|
|
fn = 0;
|
|
disp = 0;
|
|
c = 0;
|
|
break;
|
|
}
|
|
|
|
n = read_nibble (&addr);
|
|
pc = 0;
|
|
|
|
switch (disp)
|
|
{
|
|
case 0xa:
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (c == 0)
|
|
{
|
|
if (n < 0xc)
|
|
{
|
|
p = "+";
|
|
}
|
|
else
|
|
{
|
|
p = "%c=%c-1";
|
|
pc = 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (n < 4)
|
|
{
|
|
p = "%c=0";
|
|
pc = 1;
|
|
}
|
|
else
|
|
if (n >= 0xc)
|
|
{
|
|
p = "%c%cEX";
|
|
pc = 3;
|
|
}
|
|
else
|
|
{
|
|
p = "%c=%c";
|
|
pc = 3;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CLASS_MNEMONICS:
|
|
if (c == 0)
|
|
{
|
|
if (n < 0xc)
|
|
{
|
|
p = "add";
|
|
}
|
|
else
|
|
{
|
|
p = "dec";
|
|
pc = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (n < 4)
|
|
{
|
|
p = "clr";
|
|
pc = 1;
|
|
}
|
|
else
|
|
if (n >= 0xc)
|
|
{
|
|
p = "exg";
|
|
}
|
|
else
|
|
{
|
|
p = "move";
|
|
if (n < 8)
|
|
n -= 4;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
return addr;
|
|
}
|
|
break;
|
|
|
|
case 0xb:
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (c == 0)
|
|
{
|
|
if (n >= 0xc)
|
|
{
|
|
p = "-";
|
|
}
|
|
else
|
|
if ((n >= 4) && (n <= 7))
|
|
{
|
|
p = "%c=%c+1";
|
|
pc = 2;
|
|
n -= 4;
|
|
}
|
|
else
|
|
{
|
|
p = "-";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (n < 4)
|
|
{
|
|
p = "%cSL";
|
|
pc = 1;
|
|
}
|
|
else
|
|
if (n < 8)
|
|
{
|
|
p = "%cSR";
|
|
pc = 1;
|
|
}
|
|
else
|
|
if (n < 0xc)
|
|
{
|
|
p = "%c=%c-1";
|
|
pc = 2;
|
|
}
|
|
else
|
|
{
|
|
p = "%c=-%c-1";
|
|
pc = 2;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CLASS_MNEMONICS:
|
|
if (c == 0)
|
|
{
|
|
if (n >= 0xc)
|
|
{
|
|
p = "subr";
|
|
}
|
|
else
|
|
if ((n >= 4) && (n <= 7))
|
|
{
|
|
p = "inc";
|
|
pc = 1;
|
|
n -= 4;
|
|
}
|
|
else
|
|
{
|
|
p = "sub";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pc = 1;
|
|
if (n < 4)
|
|
{
|
|
p = "lsl";
|
|
}
|
|
else
|
|
if (n < 8)
|
|
{
|
|
p = "lsr";
|
|
}
|
|
else
|
|
if (n < 0xc)
|
|
{
|
|
p = "neg";
|
|
}
|
|
else
|
|
{
|
|
p = "not";
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
p = append_str (out, "Unknown disassembler mode");
|
|
return addr;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
switch (disassembler_mode)
|
|
{
|
|
case HP_MNEMONICS:
|
|
if (pc == 0)
|
|
{
|
|
wsprintf (buf, op_str_af[n + 16 * HP_MNEMONICS], p);
|
|
}
|
|
else
|
|
if (pc == 1)
|
|
{
|
|
wsprintf (buf, p, (n & 3) + 'A');
|
|
}
|
|
else
|
|
if (pc == 2)
|
|
{
|
|
wsprintf (buf, p, (n & 3) + 'A', (n & 3) + 'A');
|
|
}
|
|
else
|
|
{
|
|
wsprintf (buf, p, hp_reg_1_af[n], hp_reg_2_af[n]);
|
|
}
|
|
p = append_str (out, buf);
|
|
p = append_tab (out);
|
|
p = append_field (p, fn);
|
|
break;
|
|
|
|
case CLASS_MNEMONICS:
|
|
p = append_str (out, p);
|
|
p = append_field (p, fn);
|
|
p = append_tab (out);
|
|
if (pc == 1)
|
|
{
|
|
wsprintf (buf, "%c", (n & 3) + 'a');
|
|
p = append_str (p, buf);
|
|
}
|
|
else
|
|
{
|
|
p = append_str (p, op_str_af[n + 16 * CLASS_MNEMONICS]);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
p = append_str (p, "Unknown disassembler mode");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
*p = 0;
|
|
|
|
return addr;
|
|
}
|
|
|