summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/pic16c5x/16c5xdsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/pic16c5x/16c5xdsm.c')
-rw-r--r--trunk/src/emu/cpu/pic16c5x/16c5xdsm.c254
1 files changed, 254 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/pic16c5x/16c5xdsm.c b/trunk/src/emu/cpu/pic16c5x/16c5xdsm.c
new file mode 100644
index 00000000000..3b2f997f42d
--- /dev/null
+++ b/trunk/src/emu/cpu/pic16c5x/16c5xdsm.c
@@ -0,0 +1,254 @@
+ /**************************************************************************\
+ * Microchip PIC16C5x Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ * Addressing architecture is based on the Harvard addressing scheme. *
+ * *
+ * Many thanks to those involved in the i8039 Disassembler *
+ * as this was based on it. *
+ * *
+ * *
+ * *
+ * A Address to jump to. *
+ * B Bit address within an 8-bit file register. *
+ * D Destination select (0 = store result in W (accumulator)) *
+ * (1 = store result in file register) *
+ * F Register file address (00-1F). *
+ * K Literal field, constant data. *
+ * *
+ \**************************************************************************/
+
+#include "emu.h"
+#include <ctype.h>
+
+static const UINT8 *rombase;
+static const UINT8 *rambase;
+static offs_t pcbase;
+#define READOP16(A) (rombase[(A) - pcbase] | (rombase[(A) + 1 - pcbase] << 8))
+#define READARG16(A) (rambase[(A) - pcbase] | (rambase[(A) + 1 - pcbase] << 8))
+
+
+
+typedef unsigned char byte;
+typedef unsigned short int word;
+
+#define FMT(a,b) a, b
+#define PTRS_PER_FORMAT 2
+
+static const char *const regfile[32] = { "Reg$00 (IND)", "Reg$01 (TMR)", "Reg$02 (PCL)", "Reg$03 (ST)", "Reg$04 (FSR)", "Reg$05 (PTA)", "Reg$06 (PTB)", "Reg$07 (PTC)",
+ "Reg$08", "Reg$09", "Reg$0A", "Reg$0B", "Reg$0C", "Reg$0D", "Reg$0E", "Reg$0F",
+ "Reg$10", "Reg$11", "Reg$12", "Reg$13", "Reg$14", "Reg$15", "Reg$16", "Reg$17",
+ "Reg$18", "Reg$19", "Reg$1A", "Reg$1B", "Reg$1C", "Reg$1D", "Reg$1E", "Reg$1F" };
+
+static const char *const dest[2] = { "W", "Reg" };
+
+static const char *const PIC16C5xFormats[] = {
+ FMT("000000000000", "nop"),
+ FMT("000000000010", "option"),
+ FMT("000000000011", "sleep"),
+ FMT("000000000100", "clrwdt"),
+ FMT("000000000101", "tris Port A"),
+ FMT("000000000110", "tris Port B"),
+ FMT("000000000111", "tris Port C"),
+ FMT("0000001fffff", "movwf %F"),
+ FMT("000001000000", "clrw"),
+ FMT("0000011fffff", "clrf %F"),
+ FMT("000010dfffff", "subwf %F,%D"),
+ FMT("000011dfffff", "decf %F,%D"),
+ FMT("000100dfffff", "iorwf %F,%D"),
+ FMT("000101dfffff", "andwf %F,%D"),
+ FMT("000110dfffff", "xorwf %F,%D"),
+ FMT("000111dfffff", "addwf %F,%D"),
+ FMT("001000dfffff", "movf %F,%D"),
+ FMT("001001dfffff", "comf %F,%D"),
+ FMT("001010dfffff", "incf %F,%D"),
+ FMT("001011dfffff", "decfsz %F,%D"),
+ FMT("001100dfffff", "rrf %F,%D"),
+ FMT("001101dfffff", "rlf %F,%D"),
+ FMT("001110dfffff", "swapf %F,%D"),
+ FMT("001111dfffff", "incfsz %F,%D"),
+ FMT("0100bbbfffff", "bcf %F,%B"),
+ FMT("0101bbbfffff", "bsf %F,%B"),
+ FMT("0110bbbfffff", "btfsc %F,%B"),
+ FMT("0111bbbfffff", "btfss %F,%B"),
+ FMT("1000kkkkkkkk", "retlw %K"),
+ FMT("1001aaaaaaaa", "call %A"),
+ FMT("101aaaaaaaaa", "goto %A"),
+ FMT("1100kkkkkkkk", "movlw %K"),
+ FMT("1101kkkkkkkk", "iorlw %K"),
+ FMT("1110kkkkkkkk", "andlw %K"),
+ FMT("1111kkkkkkkk", "xorlw %K"),
+ NULL
+};
+
+#define MAX_OPS (((sizeof(PIC16C5xFormats) / sizeof(PIC16C5xFormats[0])) - 1) / PTRS_PER_FORMAT)
+
+typedef struct opcode {
+ word mask; /* instruction mask */
+ word bits; /* constant bits */
+ word extcode; /* value that gets extension code */
+ const char *parse; /* how to parse bits */
+ const char *fmt; /* instruction format */
+} PIC16C5xOpcode;
+
+static PIC16C5xOpcode Op[MAX_OPS+1];
+static int OpInizialized = 0;
+
+static void InitDasm16C5x(void)
+{
+ const char *p;
+ const char *const *ops;
+ word mask, bits;
+ int bit;
+ int i;
+
+ ops = PIC16C5xFormats; i = 0;
+ while (*ops)
+ {
+ p = *ops;
+ mask = 0; bits = 0; bit = 11;
+ while (*p && bit >= 0)
+ {
+ switch (*p++)
+ {
+ case '1': mask |= 1<<bit; bits |= 1<<bit; bit--; break;
+ case '0': mask |= 1<<bit; bit--; break;
+ case ' ': break;
+ case 'a':
+ case 'b':
+ case 'd':
+ case 'f':
+ case 'k':
+ bit --;
+ break;
+ default: fatalerror("Invalid instruction encoding '%s %s'",
+ ops[0],ops[1]);
+ }
+ }
+ if (bit != -1 )
+ {
+ fatalerror("not enough bits in encoding '%s %s' %d",
+ ops[0],ops[1],bit);
+ }
+ while (isspace((UINT8)*p)) p++;
+ if (*p) Op[i].extcode = *p;
+ Op[i].bits = bits;
+ Op[i].mask = mask;
+ Op[i].fmt = ops[1];
+ Op[i].parse = ops[0];
+
+ ops += PTRS_PER_FORMAT;
+ i++;
+ }
+
+ OpInizialized = 1;
+}
+
+CPU_DISASSEMBLE( pic16c5x )
+{
+ int a, b, d, f, k; /* these can all be filled in by parsing an instruction */
+ int i;
+ int op;
+ int cnt = 1;
+ int code;
+ int bit;
+ //char *buffertmp;
+ const char *cp; /* character pointer in OpFormats */
+ UINT32 flags = 0;
+
+ rombase = oprom;
+ rambase = opram;
+ pcbase = 2*pc;
+
+ if (!OpInizialized) InitDasm16C5x();
+
+ op = -1; /* no matching opcode */
+ code = READOP16(2*pc);
+ for ( i = 0; i < MAX_OPS; i++)
+ {
+ if ((code & Op[i].mask) == Op[i].bits)
+ {
+ if (op != -1)
+ {
+ mame_printf_debug("Error: opcode %04Xh matches %d (%s) and %d (%s)\n",
+ code,i,Op[i].fmt,op,Op[op].fmt);
+ }
+ op = i;
+ }
+ }
+ if (op == -1)
+ {
+ sprintf(buffer,"???? dw %04Xh",code);
+ return cnt;
+ }
+ //buffertmp = buffer;
+ if (Op[op].extcode) /* Actually, theres no double length opcodes */
+ {
+ bit = 27;
+ code <<= 16;
+ code |= READARG16(2*(pc+cnt));
+ cnt++;
+ }
+ else
+ {
+ bit = 11;
+ }
+
+ /* shift out operands */
+ cp = Op[op].parse;
+ a = b = d = f = k = 0;
+
+ while (bit >= 0)
+ {
+ /* mame_printf_debug("{%c/%d}",*cp,bit); */
+ switch(*cp)
+ {
+ 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 'd': d <<=1; d |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'f': f <<=1; f |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'k': k <<=1; k |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case ' ': break;
+ case '1': case '0': bit--; break;
+ case '\0': fatalerror("premature end of parse string, opcode %x, bit = %d",code,bit);
+ }
+ cp++;
+ }
+
+ /* now traverse format string */
+ cp = Op[op].fmt;
+ if (!strncmp(cp, "call", 4))
+ flags = DASMFLAG_STEP_OVER;
+ else if (!strncmp(cp, "ret", 3))
+ flags = DASMFLAG_STEP_OUT;
+
+ while (*cp)
+ {
+ if (*cp == '%')
+ {
+ char num[30], *q;
+ cp++;
+ switch (*cp++)
+ {
+ case 'A': sprintf(num,"$%03X",a); break;
+ case 'B': sprintf(num,"%d",b); break;
+ case 'D': sprintf(num,"%s",dest[d]); break;
+ case 'F': sprintf(num,"%s",regfile[f]); break;
+ case 'K': sprintf(num,"%02Xh",k); break;
+ default:
+ fatalerror("illegal escape character in format '%s'",Op[op].fmt);
+ }
+ q = num; while (*q) *buffer++ = *q++;
+ *buffer = '\0';
+ }
+ else
+ {
+ *buffer++ = *cp++;
+ *buffer = '\0';
+ }
+ }
+ return cnt | flags | DASMFLAG_SUPPORTED;
+}