emu48-mirror/sources/Emu48/DISASM.C

1924 lines
41 KiB
C
Raw Normal View History

2024-03-19 22:24:30 +01:00
/*
* Disasm.c
*
* This file is part of Emu48, a ported version of x48
*
* Copyright (C) 1994 Eddie C. Dost
* Copyright (C) 1998 Christoph Gie<EFBFBD>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)
{
2024-03-19 22:25:45 +01:00
BYTE *pbyVal;
2024-03-19 22:24:30 +01:00
DWORD d = *p;
2024-03-19 22:25:45 +01:00
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);
2024-03-19 22:24:30 +01:00
2024-03-19 22:25:45 +01:00
_ASSERT(d < ((dwPort2Mask + 1) << 18));
pbyVal = pbyPort2;
}
return *(pbyVal + d);
2024-03-19 22:24:30 +01:00
}
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;
}
2024-03-19 22:25:45 +01:00
static char *append_pc_comment (char *buf, DWORD pc, BOOL view)
2024-03-19 22:24:30 +01:00
{
char *p = buf;
2024-03-19 22:25:45 +01:00
if (view == VIEW_LONG) // output of address in remarks
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:25:45 +01:00
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");
2024-03-19 22:24:30 +01:00
break;
2024-03-19 22:25:45 +01:00
}
}
else // output of address in brackets
{
while (*p) ++p;
p = append_str (p, " [");
p = append_addr (p, pc);
p = append_str (p, "]");
2024-03-19 22:24:30 +01:00
}
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;
}
2024-03-19 22:25:45 +01:00
static char *disasm_8 (DWORD *addr, char *out, BOOL view)
2024-03-19 22:24:30 +01:00
{
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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
{
2024-03-19 22:25:45 +01:00
// 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");
}
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
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
2024-03-19 22:25:45 +01:00
DWORD disassemble (DWORD addr, LPSTR out, BOOL view)
2024-03-19 22:24:30 +01:00
{
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
break;
case CLASS_MNEMONICS:
p = append_str (out, "bsr.3");
p = append_tab (out);
p = append_r_addr (p, &pc, disp, 3, 4);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
break;
default:
p = append_str (out, "Unknown disassembler mode");
break;
}
break;
case 8:
fn = read_nibble (&addr); /* PEEK */
--addr;
if (fn != 0xa && fn != 0xb)
{
2024-03-19 22:25:45 +01:00
p = disasm_8 (&addr, out, view);
2024-03-19 22:24:30 +01:00
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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);
2024-03-19 22:25:45 +01:00
p = append_pc_comment (out, pc, view);
2024-03-19 22:24:30 +01:00
}
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;
}