/****************************************************************************
|
/****************************************************************************
|
*
|
*
|
* mcs48 disassembler
|
* mcs48 disassembler
|
*
|
*
|
* This file is Copyright 1996 Michael Cuddy, Fen's Ende Sofware.
|
* This file is Copyright 1996 Michael Cuddy, Fen's Ende Sofware.
|
* Redistribution is allowed in source and binary form as long as both
|
* Redistribution is allowed in source and binary form as long as both
|
* forms are distributed together with the file 'README'. This copyright
|
* forms are distributed together with the file 'README'. This copyright
|
* notice must also accompany the files.
|
* notice must also accompany the files.
|
*
|
*
|
* This software should be considered a small token to all of the
|
* This software should be considered a small token to all of the
|
* emulator authors for thier dilligence in preserving our Arcade and
|
* emulator authors for thier dilligence in preserving our Arcade and
|
* Computer history.
|
* Computer history.
|
*
|
*
|
* Michael Cuddy, Fen's Ende Software.
|
* Michael Cuddy, Fen's Ende Software.
|
* 11/25/1996
|
* 11/25/1996
|
*
|
*
|
* Adapted by Andrea Mazzoleni for use with MAME
|
* Adapted by Andrea Mazzoleni for use with MAME
|
*
|
*
|
***************************************************************************/
|
***************************************************************************/
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
#include <ctype.h>
|
#include <ctype.h>
|
|
|
#include "memory.h"
|
#include "memory.h"
|
|
|
typedef unsigned char byte;
|
typedef unsigned char byte;
|
|
|
#define FMT(a,b) a, b
|
#define FMT(a,b) a, b
|
#define PTRS_PER_FORMAT 2
|
#define PTRS_PER_FORMAT 2
|
|
|
const char *Formats[] = {
|
const char *Formats[] = {
|
FMT("00000011dddddddd", "add a, #%X"),
|
FMT("00000011dddddddd", "add a, #%X"),
|
FMT("01101rrr", "add a, %R"),
|
FMT("01101rrr", "add a, %R"),
|
FMT("0110000r", "add a, @%R"),
|
FMT("0110000r", "add a, @%R"),
|
FMT("00010011dddddddd", "adc a, #%X"),
|
FMT("00010011dddddddd", "adc a, #%X"),
|
FMT("01111rrr", "adc a, %R"),
|
FMT("01111rrr", "adc a, %R"),
|
FMT("0111000r", "adc a, @%R"),
|
FMT("0111000r", "adc a, @%R"),
|
FMT("01010011dddddddd", "anl a, #%X"),
|
FMT("01010011dddddddd", "anl a, #%X"),
|
FMT("01011rrr", "anl a, %R"),
|
FMT("01011rrr", "anl a, %R"),
|
FMT("0101000r", "anl a, @%R"),
|
FMT("0101000r", "anl a, @%R"),
|
FMT("10011000dddddddd", "anl bus, #%X"),
|
FMT("10011000dddddddd", "anl bus, #%X"),
|
FMT("10011001dddddddd", "anl p1, #%X"),
|
FMT("10011001dddddddd", "anl p1, #%X"),
|
FMT("10011010dddddddd", "anl p2, #%X"),
|
FMT("10011010dddddddd", "anl p2, #%X"),
|
FMT("100111pp", "anld %P, a"),
|
FMT("100111pp", "anld %P, a"),
|
FMT("aaa10100aaaaaaaa", "call %A"),
|
FMT("aaa10100aaaaaaaa", "call %A"),
|
FMT("00100111", "clr a"),
|
FMT("00100111", "clr a"),
|
FMT("10010111", "clr c"),
|
FMT("10010111", "clr c"),
|
FMT("10100101", "clr f1"),
|
FMT("10100101", "clr f1"),
|
FMT("10000101", "clr f0"),
|
FMT("10000101", "clr f0"),
|
FMT("00110111", "cpl a"),
|
FMT("00110111", "cpl a"),
|
FMT("10100111", "cpl c"),
|
FMT("10100111", "cpl c"),
|
FMT("10010101", "cpl f0"),
|
FMT("10010101", "cpl f0"),
|
FMT("10110101", "cpl f1"),
|
FMT("10110101", "cpl f1"),
|
FMT("01010111", "da a"),
|
FMT("01010111", "da a"),
|
FMT("00000111", "dec a"),
|
FMT("00000111", "dec a"),
|
FMT("11001rrr", "dec %R"),
|
FMT("11001rrr", "dec %R"),
|
FMT("00010101", "dis i"),
|
FMT("00010101", "dis i"),
|
FMT("00110101", "dis tcnti"),
|
FMT("00110101", "dis tcnti"),
|
FMT("11101rrraaaaaaaa", "djnz %R, %J"),
|
FMT("11101rrraaaaaaaa", "djnz %R, %J"),
|
FMT("00000101", "en i"),
|
FMT("00000101", "en i"),
|
FMT("00100101", "en tcnti"),
|
FMT("00100101", "en tcnti"),
|
FMT("01110101", "ent0 clk"),
|
FMT("01110101", "ent0 clk"),
|
FMT("00001001", "in a, p1"),
|
FMT("00001001", "in a, p1"),
|
FMT("00001010", "in a, p2"),
|
FMT("00001010", "in a, p2"),
|
FMT("00010111", "inc a"),
|
FMT("00010111", "inc a"),
|
FMT("00011rrr", "inc %R"),
|
FMT("00011rrr", "inc %R"),
|
FMT("0001000r", "inc @%R"),
|
FMT("0001000r", "inc @%R"),
|
FMT("00001000", "ins a,bus"),
|
FMT("00001000", "ins a,bus"),
|
FMT("0001 0110aaaaaaaa", "jtf %J"),
|
FMT("0001 0110aaaaaaaa", "jtf %J"),
|
FMT("0010 0110aaaaaaaa", "jnt0 %J"),
|
FMT("0010 0110aaaaaaaa", "jnt0 %J"),
|
FMT("0011 0110aaaaaaaa", "jt0 %J"),
|
FMT("0011 0110aaaaaaaa", "jt0 %J"),
|
FMT("0100 0110aaaaaaaa", "jnt1 %J"),
|
FMT("0100 0110aaaaaaaa", "jnt1 %J"),
|
FMT("0101 0110aaaaaaaa", "jt1 %J"),
|
FMT("0101 0110aaaaaaaa", "jt1 %J"),
|
FMT("0111 0110aaaaaaaa", "jf1 %J"),
|
FMT("0111 0110aaaaaaaa", "jf1 %J"),
|
FMT("1000 0110aaaaaaaa", "jni %J"),
|
FMT("1000 0110aaaaaaaa", "jni %J"),
|
FMT("1001 0110aaaaaaaa", "jnz %J"),
|
FMT("1001 0110aaaaaaaa", "jnz %J"),
|
FMT("1011 0110aaaaaaaa", "jf0 %J"),
|
FMT("1011 0110aaaaaaaa", "jf0 %J"),
|
FMT("1100 0110aaaaaaaa", "jz %J"),
|
FMT("1100 0110aaaaaaaa", "jz %J"),
|
FMT("1110 0110aaaaaaaa", "jnc %J"),
|
FMT("1110 0110aaaaaaaa", "jnc %J"),
|
FMT("1111 0110aaaaaaaa", "jc %J"),
|
FMT("1111 0110aaaaaaaa", "jc %J"),
|
FMT("bbb10010aaaaaaaa", "jb%B %J"),
|
FMT("bbb10010aaaaaaaa", "jb%B %J"),
|
FMT("aaa00100aaaaaaaa", "jmp %A"),
|
FMT("aaa00100aaaaaaaa", "jmp %A"),
|
FMT("10110011", "jmpp @a"),
|
FMT("10110011", "jmpp @a"),
|
FMT("00100011dddddddd", "mov a, #%X"),
|
FMT("00100011dddddddd", "mov a, #%X"),
|
FMT("11111rrr", "mov a, %R"),
|
FMT("11111rrr", "mov a, %R"),
|
FMT("1111000r", "mov a, @%R"),
|
FMT("1111000r", "mov a, @%R"),
|
FMT("11000111", "mov a, psw"),
|
FMT("11000111", "mov a, psw"),
|
FMT("10111rrrdddddddd", "mov %R, #%X"),
|
FMT("10111rrrdddddddd", "mov %R, #%X"),
|
FMT("10101rrr", "mov %R, a"),
|
FMT("10101rrr", "mov %R, a"),
|
FMT("1010000r", "mov @%R, a"),
|
FMT("1010000r", "mov @%R, a"),
|
FMT("1011000rdddddddd", "mov @%R, #%X"),
|
FMT("1011000rdddddddd", "mov @%R, #%X"),
|
FMT("11010111", "mov psw, a"),
|
FMT("11010111", "mov psw, a"),
|
FMT("000011pp", "movd a, %P"),
|
FMT("000011pp", "movd a, %P"),
|
FMT("001111pp", "movd %P, a"),
|
FMT("001111pp", "movd %P, a"),
|
FMT("01000010", "mov a, t"),
|
FMT("01000010", "mov a, t"),
|
FMT("01100010", "mov t, a"),
|
FMT("01100010", "mov t, a"),
|
FMT("11100011", "movp3 a, @a"),
|
FMT("11100011", "movp3 a, @a"),
|
FMT("10100011", "movp a, @a"),
|
FMT("10100011", "movp a, @a"),
|
FMT("1000000r", "movx a, @%R"),
|
FMT("1000000r", "movx a, @%R"),
|
FMT("1001000r", "movx @%R, a"),
|
FMT("1001000r", "movx @%R, a"),
|
FMT("0100 1rrr", "orl a, %R"),
|
FMT("0100 1rrr", "orl a, %R"),
|
FMT("0100 000r", "orl a, @%R"),
|
FMT("0100 000r", "orl a, @%R"),
|
FMT("0100 0011dddddddd", "orl a, #%X"),
|
FMT("0100 0011dddddddd", "orl a, #%X"),
|
FMT("1000 1000dddddddd", "orl bus, #%X"),
|
FMT("1000 1000dddddddd", "orl bus, #%X"),
|
FMT("1000 1001dddddddd", "orl p1, #%X"),
|
FMT("1000 1001dddddddd", "orl p1, #%X"),
|
FMT("1000 1010dddddddd", "orl p2, #%X"),
|
FMT("1000 1010dddddddd", "orl p2, #%X"),
|
FMT("1000 11pp", "orld %P, a"),
|
FMT("1000 11pp", "orld %P, a"),
|
FMT("00000010", "outl bus, a"),
|
FMT("00000010", "outl bus, a"),
|
FMT("001110pp", "outl %P, a"),
|
FMT("001110pp", "outl %P, a"),
|
FMT("10000011", "ret"),
|
FMT("10000011", "ret"),
|
FMT("10010011", "retr"),
|
FMT("10010011", "retr"),
|
FMT("11100111", "rl a"),
|
FMT("11100111", "rl a"),
|
FMT("11110111", "rlc a"),
|
FMT("11110111", "rlc a"),
|
FMT("01110111", "rr a"),
|
FMT("01110111", "rr a"),
|
FMT("01100111", "rrc a"),
|
FMT("01100111", "rrc a"),
|
FMT("11100101", "sel mb0"),
|
FMT("11100101", "sel mb0"),
|
FMT("11110101", "sel mb1"),
|
FMT("11110101", "sel mb1"),
|
FMT("11000101", "sel rb0"),
|
FMT("11000101", "sel rb0"),
|
FMT("11010101", "sel rb1"),
|
FMT("11010101", "sel rb1"),
|
FMT("01100101", "stop tcnt"),
|
FMT("01100101", "stop tcnt"),
|
FMT("01000101", "strt cnt"),
|
FMT("01000101", "strt cnt"),
|
FMT("01010101", "strt t"),
|
FMT("01010101", "strt t"),
|
FMT("01000111", "swap a"),
|
FMT("01000111", "swap a"),
|
FMT("00101rrr", "xch a, %R"),
|
FMT("00101rrr", "xch a, %R"),
|
FMT("0010000r", "xch a, @%R"),
|
FMT("0010000r", "xch a, @%R"),
|
FMT("0011000r", "xchd a, @%R"),
|
FMT("0011000r", "xchd a, @%R"),
|
FMT("1101 0011dddddddd", "xrl a, #%X"),
|
FMT("1101 0011dddddddd", "xrl a, #%X"),
|
FMT("1101 1rrr", "xrl a, %R"),
|
FMT("1101 1rrr", "xrl a, %R"),
|
FMT("1101 000r", "xrl a, @%R"),
|
FMT("1101 000r", "xrl a, @%R"),
|
FMT("00000000", "nop"),
|
FMT("00000000", "nop"),
|
NULL
|
NULL
|
};
|
};
|
|
|
#define MAX_OPS (((sizeof(Formats) / sizeof(Formats[0])) - 1) / PTRS_PER_FORMAT)
|
#define MAX_OPS (((sizeof(Formats) / sizeof(Formats[0])) - 1) / PTRS_PER_FORMAT)
|
|
|
typedef struct opcode {
|
typedef struct opcode {
|
byte mask; /* instruction mask */
|
byte mask; /* instruction mask */
|
byte bits; /* constant bits */
|
byte bits; /* constant bits */
|
char extcode; /* value that gets extension code */
|
char extcode; /* value that gets extension code */
|
const char *parse; /* how to parse bits */
|
const char *parse; /* how to parse bits */
|
const char *fmt; /* instruction format */
|
const char *fmt; /* instruction format */
|
} M48Opcode;
|
} M48Opcode;
|
|
|
static M48Opcode Op[MAX_OPS+1];
|
static M48Opcode Op[MAX_OPS+1];
|
static int OpInizialized = 0;
|
static int OpInizialized = 0;
|
|
|
static void InitDasm8039(void)
|
static void InitDasm8039(void)
|
{
|
{
|
const char *p, **ops;
|
const char *p, **ops;
|
byte mask, bits;
|
byte mask, bits;
|
int bit;
|
int bit;
|
int i;
|
int i;
|
|
|
ops = Formats; i = 0;
|
ops = Formats; i = 0;
|
while (*ops) {
|
while (*ops) {
|
p = *ops;
|
p = *ops;
|
mask = 0; bits = 0; bit = 7;
|
mask = 0; bits = 0; bit = 7;
|
while (*p && bit >= 0) {
|
while (*p && bit >= 0) {
|
switch (*p++) {
|
switch (*p++) {
|
case '1': mask |= 1<<bit; bits |= 1<<bit; bit--; break;
|
case '1': mask |= 1<<bit; bits |= 1<<bit; bit--; break;
|
case '0': mask |= 1<<bit; bit--; break;
|
case '0': mask |= 1<<bit; bit--; break;
|
case ' ': break;
|
case ' ': break;
|
case 'b':
|
case 'b':
|
case 'a': case 'r': case 'd': case 'p':
|
case 'a': case 'r': case 'd': case 'p':
|
bit --;
|
bit --;
|
break;
|
break;
|
default:
|
default:
|
printf("Invalid instruction encoding '%s %s'\n", ops[0],ops[1]);
|
printf("Invalid instruction encoding '%s %s'\n", ops[0],ops[1]);
|
exit(1);
|
exit(1);
|
}
|
}
|
}
|
}
|
if (bit != -1 ) {
|
if (bit != -1 ) {
|
printf("not enough bits in encoding '%s %s' %d\n", ops[0],ops[1],bit);
|
printf("not enough bits in encoding '%s %s' %d\n", ops[0],ops[1],bit);
|
exit(1);
|
exit(1);
|
}
|
}
|
while (isspace(*p)) p++;
|
while (isspace(*p)) p++;
|
if (*p) Op[i].extcode = *p;
|
if (*p) Op[i].extcode = *p;
|
Op[i].bits = bits;
|
Op[i].bits = bits;
|
Op[i].mask = mask;
|
Op[i].mask = mask;
|
Op[i].fmt = ops[1];
|
Op[i].fmt = ops[1];
|
Op[i].parse = ops[0];
|
Op[i].parse = ops[0];
|
|
|
ops += PTRS_PER_FORMAT;
|
ops += PTRS_PER_FORMAT;
|
i++;
|
i++;
|
}
|
}
|
|
|
OpInizialized = 1;
|
OpInizialized = 1;
|
}
|
}
|
|
|
int Dasm8039(char *buffer, unsigned pc)
|
int Dasm8039(char *buffer, unsigned pc)
|
{
|
{
|
int b, a, d, r, p; /* these can all be filled in by parsing an instruction */
|
int b, a, d, r, p; /* these can all be filled in by parsing an instruction */
|
int i;
|
int i;
|
int op;
|
int op;
|
int cnt = 1;
|
int cnt = 1;
|
int code, bit;
|
int code, bit;
|
const char *cp;
|
const char *cp;
|
|
|
if (!OpInizialized) InitDasm8039();
|
if (!OpInizialized) InitDasm8039();
|
|
|
code = cpu_readop(pc);
|
code = cpu_readop(pc);
|
op = -1; /* no matching opcode */
|
op = -1; /* no matching opcode */
|
for ( i = 0; i < MAX_OPS; i++)
|
for ( i = 0; i < MAX_OPS; i++)
|
{
|
{
|
if( (code & Op[i].mask) == Op[i].bits )
|
if( (code & Op[i].mask) == Op[i].bits )
|
{
|
{
|
if (op != -1)
|
if (op != -1)
|
{
|
{
|
fprintf(stderr, "Error: opcode %02X matches %d (%s) and %d (%s)\n",
|
fprintf(stderr, "Error: opcode %02X matches %d (%s) and %d (%s)\n",
|
code,i,Op[i].fmt,op,Op[op].fmt);
|
code,i,Op[i].fmt,op,Op[op].fmt);
|
}
|
}
|
op = i;
|
op = i;
|
}
|
}
|
}
|
}
|
|
|
if (op == -1)
|
if (op == -1)
|
{
|
{
|
sprintf(buffer,"db %2.2x",code);
|
sprintf(buffer,"db %2.2x",code);
|
return cnt;
|
return cnt;
|
}
|
}
|
|
|
if (Op[op].extcode)
|
if (Op[op].extcode)
|
{
|
{
|
cnt++;
|
cnt++;
|
code <<= 8;
|
code <<= 8;
|
code |= cpu_readop_arg((pc+1)&0xffff);
|
code |= cpu_readop_arg((pc+1)&0xffff);
|
bit = 15;
|
bit = 15;
|
}
|
}
|
else
|
else
|
{
|
{
|
bit = 7;
|
bit = 7;
|
}
|
}
|
|
|
/* shift out operands */
|
/* shift out operands */
|
cp = Op[op].parse;
|
cp = Op[op].parse;
|
b = a = d = r = p = 0;
|
b = a = d = r = p = 0;
|
|
|
while (bit >= 0)
|
while (bit >= 0)
|
{
|
{
|
/* printf("{%c/%d}",*cp,bit); */
|
/* printf("{%c/%d}",*cp,bit); */
|
switch(*cp)
|
switch(*cp)
|
{
|
{
|
case 'a': a <<=1; a |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case 'a': a <<=1; a |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case 'b': b <<=1; b |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case 'b': b <<=1; b |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case 'd': d <<=1; d |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case 'd': d <<=1; d |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case 'r': r <<=1; r |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case 'r': r <<=1; r |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case 'p': p <<=1; p |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case 'p': p <<=1; p |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
|
case ' ': break;
|
case ' ': break;
|
case '1': case '0': bit--; break;
|
case '1': case '0': bit--; break;
|
case '\0': printf("premature end of parse string, opcode %x, bit = %d\n",code,bit); exit(1);
|
case '\0': printf("premature end of parse string, opcode %x, bit = %d\n",code,bit); exit(1);
|
}
|
}
|
cp++;
|
cp++;
|
}
|
}
|
|
|
/* now traverse format string */
|
/* now traverse format string */
|
cp = Op[op].fmt;
|
cp = Op[op].fmt;
|
while (*cp)
|
while (*cp)
|
{
|
{
|
if (*cp == '%')
|
if (*cp == '%')
|
{
|
{
|
char num[10], *q;
|
char num[10], *q;
|
cp++;
|
cp++;
|
switch (*cp++)
|
switch (*cp++)
|
{
|
{
|
case 'A': sprintf(num,"0%04XH",a); break;
|
case 'A': sprintf(num,"0%04XH",a); break;
|
case 'J': sprintf(num,"0%04XH",((pc+1) & 0xf00) | a); break;
|
case 'J': sprintf(num,"0%04XH",((pc+1) & 0xf00) | a); break;
|
case 'B': sprintf(num,"%d",b); break;
|
case 'B': sprintf(num,"%d",b); break;
|
case 'D': sprintf(num,"%d",d); break;
|
case 'D': sprintf(num,"%d",d); break;
|
case 'X': sprintf(num,"0%02XH",d); break;
|
case 'X': sprintf(num,"0%02XH",d); break;
|
case 'R': sprintf(num,"r%d",r); break;
|
case 'R': sprintf(num,"r%d",r); break;
|
case 'P': sprintf(num,"p%d",p); break;
|
case 'P': sprintf(num,"p%d",p); break;
|
default:
|
default:
|
printf("illegal escape character in format '%s'\n",Op[op].fmt);
|
printf("illegal escape character in format '%s'\n",Op[op].fmt);
|
exit(1);
|
exit(1);
|
}
|
}
|
q = num; while (*q) *buffer++ = *q++;
|
q = num; while (*q) *buffer++ = *q++;
|
*buffer = '\0';
|
*buffer = '\0';
|
}
|
}
|
else
|
else
|
{
|
{
|
*buffer++ = *cp++;
|
*buffer++ = *cp++;
|
*buffer = '\0';
|
*buffer = '\0';
|
}
|
}
|
}
|
}
|
|
|
return cnt;
|
return cnt;
|
}
|
}
|
|
|