droid48/jni/disasm.c
2010-09-18 01:13:52 +02:00

1965 lines
38 KiB
C

/*
* This file is part of x48, an emulator of the HP-48sx Calculator.
* Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Log: disasm.c,v $
* Revision 1.6 1995/01/11 18:20:01 ecd
* major update to support HP48 G/GX
*
* Revision 1.5 1994/12/07 20:20:50 ecd
* some minor fixes
*
* Revision 1.5 1994/12/07 20:20:50 ecd
* some minor fixes
*
* Revision 1.4 1994/11/28 02:00:51 ecd
* enlarged field_tbl further
*
* Revision 1.3 1994/11/04 03:42:34 ecd
* fixed bug in field_tbl
*
* Revision 1.2 1994/11/02 14:40:38 ecd
* completed disassembler
*
* Revision 1.1 1994/10/09 20:29:47 ecd
* Initial revision
*
*
* $Id: disasm.c,v 1.6 1995/01/11 18:20:01 ecd Exp ecd $
*/
#include "global.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "hp48.h"
#include "disasm.h"
#define TAB_SKIP 8
int disassembler_mode = CLASS_MNEMONICS;
char *mode_name[] =
{
"HP",
"class"
};
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",
};
int
#ifdef __FunctionProto__
read_int (word_20 * addr, int n)
#else
read_int (addr, n)
word_20 *addr;
int n;
#endif
{
int i, t;
for (i = 0, t = 0; i < n; i++)
t |= read_nibble ((*addr)++) << (i * 4);
return t;
}
char *
#ifdef __FunctionProto__
append_str (char *buf, char *str)
#else
append_str (buf, str)
char *buf;
char *str;
#endif
{
while ((*buf = *str++))
buf++;
return buf;
}
char *
#ifdef __FunctionProto__
append_tab_16 (char *buf)
#else
append_tab_16 (buf)
char *buf;
#endif
{
int n;
char *p;
n = 16 - (strlen (buf) % 16);
p = &buf[strlen (buf)];
while (n--)
*p++ = ' ';
*p = '\0';
return p;
}
char *
#ifdef __FunctionProto__
append_tab (char *buf)
#else
append_tab (buf)
char *buf;
#endif
{
int n;
char *p;
n = TAB_SKIP - (strlen (buf) % TAB_SKIP);
p = &buf[strlen (buf)];
while (n--)
*p++ = ' ';
*p = '\0';
return p;
}
char *
#ifdef __FunctionProto__
append_field (char *buf, word_4 fn)
#else
append_field (buf, fn)
char *buf;
word_4 fn;
#endif
{
buf = append_str (buf, field_tbl[fn + 16 * disassembler_mode]);
return buf;
}
char *
#ifdef __FunctionProto__
append_imm_nibble (char *buf, word_20 * addr, int n)
#else
append_imm_nibble (buf, addr, n)
char *buf;
word_20 *addr;
int n;
#endif
{
int i;
char t[16];
if (disassembler_mode == CLASS_MNEMONICS)
{
*buf++ = '#';
if (n > 1)
*buf++ = '$';
}
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
{
sprintf (t, "%d", read_nibble ((*addr)++));
buf = append_str (buf, t);
}
return buf;
}
char *
#ifdef __FunctionProto__
append_addr (char *buf, word_20 addr)
#else
append_addr (buf, addr)
char *buf;
word_20 addr;
#endif
{
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;
}
char *
#ifdef __FunctionProto__
append_r_addr (char *buf, word_20 * pc, long disp, int n, int offset)
#else
append_r_addr (buf, pc, disp, n, offset)
char *buf;
word_20 *pc;
long disp;
int n;
int offset;
#endif
{
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;
}
char *
#ifdef __FunctionProto__
append_pc_comment (char *buf, word_20 pc)
#else
append_pc_comment (buf, pc)
char *buf;
word_20 pc;
#endif
{
char *p = buf;
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;
}
return p;
}
char *
#ifdef __FunctionProto__
append_hst_bits (char *buf, int n)
#else
append_hst_bits (buf, n)
char *buf;
int n;
#endif
{
int i;
char *p = buf;
switch (disassembler_mode)
{
case HP_MNEMONICS:
for (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;
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;
}
char *
#ifdef __FunctionProto__
disasm_1 (word_20 * addr, char *out)
#else
disasm_1 (addr, out)
word_20 *addr;
char *out;
#endif
{
word_4 n;
word_4 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)
sprintf (buf, "R%d=%c", fn, c);
else
sprintf (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)
sprintf (buf, "%c, r%d", c, fn);
else
sprintf (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');
sprintf (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');
sprintf (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)
{
sprintf (buf, "%cD%dEX", c, (n & 1));
}
else
{
sprintf (buf, "%cD%dXS", c, (n & 1));
}
}
else
{
if (n < 8)
{
sprintf (buf, "D%d=%c", (n & 1), c);
}
else
{
sprintf (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';
sprintf (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
{
sprintf (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
{
sprintf (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);
sprintf (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);
sprintf (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:
sprintf (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)
{
sprintf (buf, "move.a");
}
else if (n == 4)
{
sprintf (buf, "move.as");
}
else
{
sprintf (buf, "move.b");
}
p = append_str (out, buf);
p = append_tab (out);
p = append_imm_nibble (p, addr, n);
sprintf (buf, ", d%c", c);
p = append_str (p, buf);
break;
default:
p = append_str (out, "Unknown disassembler mode");
break;
}
break;
default:
break;
}
return p;
}
char *
#ifdef __FunctionProto__
disasm_8 (word_20 * addr, char *out)
#else
disasm_8 (addr, out)
word_20 *addr;
char *out;
#endif
{
word_4 n;
word_4 fn;
char *p = out;
char c;
char buf[20];
word_20 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)
{
sprintf (buf, "LA(%d)", n + 1);
}
else
{
sprintf (buf, "LAHEX");
}
p = append_str (out, buf);
p = append_tab (out);
p = append_imm_nibble (p, addr, n + 1);
break;
case CLASS_MNEMONICS:
sprintf (buf, "move.%d", n + 1);
p = append_str (out, buf);
p = append_tab (out);
p = append_imm_nibble (p, addr, n + 1);
sprintf (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:
sprintf (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');
sprintf (buf, "?%cBIT=%d", c, (fn & 1) ? 1 : 0);
p = append_str (out, buf);
p = append_tab (out);
sprintf (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);
}
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);
sprintf (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);
}
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:
sprintf (buf, (n == 0xf) ? "%c%cEX" : "%c=%c",
(n == 0xd) ? 'P' : 'C', (n == 0xd) ? 'C' : 'P');
p = append_str (out, buf);
p = append_tab (out);
sprintf (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);
sprintf (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:
sprintf (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:
sprintf (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:
sprintf (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)++);
sprintf (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)++);
sprintf (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:
sprintf (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)
{
sprintf (buf, "%cR%dEX.F", ((int) c < 8) ? 'A' : 'C',
(int) c & 7);
}
else if (n == 1)
{
sprintf (buf, "%c=R%d.F", ((int) c < 8) ? 'A' : 'C',
(int) c & 7);
}
else
{
sprintf (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)
{
sprintf (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
{
sprintf (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:
sprintf (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
{
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);
sprintf (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);
}
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);
sprintf (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);
}
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:
sprintf (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:
sprintf (buf, "?ST=%d", (fn == 6) ? 0 : 1);
p = append_str (out, buf);
p = append_tab (out);
sprintf (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);
}
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);
sprintf (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);
}
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:
sprintf (buf, "?P%c", (fn == 8) ? '#' : '=');
p = append_str (out, buf);
p = append_tab (out);
sprintf (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);
}
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);
sprintf (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);
}
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);
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);
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 == 0xc) ? "GOVLNG" : "GOSBVL");
p = append_tab (out);
p = append_addr (p, pc);
break;
case CLASS_MNEMONICS:
p = append_str (out, (fn == 0xc) ? "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;
}
word_20
#ifdef __FunctionProto__
disassemble (word_20 addr, char *out)
#else
disassemble (addr, out)
word_20 addr;
char *out;
#endif
{
word_4 n;
word_4 fn;
char *p = out;
char c;
char buf[20];
word_20 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:
sprintf (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:
sprintf (buf, "P=%d", n);
p = append_str (out, buf);
break;
case CLASS_MNEMONICS:
sprintf (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)
{
sprintf (buf, "LC(%d)", fn + 1);
}
else
{
sprintf (buf, "LCHEX");
}
p = append_str (out, buf);
p = append_tab (out);
p = append_imm_nibble (p, &addr, fn + 1);
break;
case CLASS_MNEMONICS:
sprintf (buf, "move.%d", fn + 1);
p = append_str (out, buf);
p = append_tab (out);
p = append_imm_nibble (p, &addr, fn + 1);
sprintf (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;
}
sprintf (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);
}
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);
}
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);
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);
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);
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);
break;
default:
p = append_str (out, "Unknown disassembler mode");
break;
}
break;
case 8:
fn = read_nibble (addr); /* PEEK */
if (fn != 0xa && fn != 0xb)
{
p = disasm_8 (&addr, out);
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))
sprintf (buf, op_str_9[(n & 3) + 8 * HP_MNEMONICS + 4],
in_str_9[((n >> 2) & 3) + 4 * c + 8 * HP_MNEMONICS]);
else
sprintf (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);
}
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);
}
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)
{
sprintf (buf, op_str_af[n + 16 * HP_MNEMONICS], p);
}
else if (pc == 1)
{
sprintf (buf, p, (n & 3) + 'A');
}
else if (pc == 2)
{
sprintf (buf, p, (n & 3) + 'A', (n & 3) + 'A');
}
else
{
sprintf (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)
{
sprintf (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;
}