summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/apexc/apexcdsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/apexc/apexcdsm.c')
-rw-r--r--trunk/src/emu/cpu/apexc/apexcdsm.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/apexc/apexcdsm.c b/trunk/src/emu/cpu/apexc/apexcdsm.c
new file mode 100644
index 00000000000..61752703f74
--- /dev/null
+++ b/trunk/src/emu/cpu/apexc/apexcdsm.c
@@ -0,0 +1,183 @@
+/*
+ cpu/apexc/apexcsm.c : APE(X)C CPU disassembler
+
+ By Raphael Nabet
+
+ see cpu/apexc.c for background and tech info
+*/
+
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "apexc.h"
+
+/*
+ Here is the format used for debugger output.
+
+ Since the only assembler for the APEXC that I know of uses numerical data
+ (yes, mnemonics are numbers), I do not know if there is an official way of writing
+ APEXC assembly on a text terminal. The format I chose is closely inspired by
+ the assembly format found in Booth, but was slightly adapted to accommodate
+ the lack of subscripts and of a 'greater or equal' character.
+
+ Printed format Name
+ 0 1 2
+ 012345678901234567890123456
+ Stop (##/##) one_address
+ I (##/##) one_address
+ P (##/##) one_address
+ B <(##/##) >=(##/##) branch
+ l (##) (##/##) shiftl
+ r (##) (##/##) shiftr
+ Illegal (##/##) one_address
+ X (##) (##) (##/##) multiply
+ X (##) (##/##) multiply
+ +c (##/##) (##/##) two_address
+ -c (##/##) (##/##) two_address
+ + (##/##) (##/##) two_address
+ - (##/##) (##/##) two_address
+ T (##/##) (##/##) two_address
+ R (1-##) (##/##) (##/##) store
+ R (##-32) (##/##) (##/##) store
+ R (##/##) (##/##) store
+ A (1-##) (##/##) (##/##) store
+ A (##-32) (##/##) (##/##) store
+ A (##/##) (##/##) store
+ S (##) (##/##) swap
+ +--------++--------++-----+
+ mnemonic X field Y field
+ field
+
+ For vector instructions, replace the first space on the right of the mnemonic
+ with a 'v'.
+
+ 01-Feb-2010 (Robbbert):
+ I've added the actual address, (as shown in the extreme left of the debugger
+ output), so that you can see much easier how the program will flow. Example:
+
+ +C XXX(##/##) XXX(##/##)
+
+ The X value shows where the data word is located, and the Y value is the
+ address of the next instruction.
+*/
+enum _format_type {branch, shiftl, shiftr, multiply, store, swap, one_address, two_address};
+typedef enum _format_type format_type;
+
+typedef struct instr_desc
+{
+ const char *mnemonic;
+ format_type format; /* -> X and Y are format */
+} instr_desc;
+
+static const instr_desc instructions[16] =
+{
+ { "Stop", one_address }, { "I", one_address },
+ { "P", one_address }, { "B", branch },
+ { "l", shiftl }, { "r", shiftr },
+ { "Illegal",one_address }, { "X", multiply },
+ { "+c", two_address }, { "-c", two_address },
+ { "+", two_address }, { "-", two_address },
+ { "T", two_address }, { "R", store },
+ { "A", store }, { "S", swap }
+};
+
+CPU_DISASSEMBLE( apexc )
+{
+ UINT32 instruction; /* 32-bit machine instruction */
+ int x, y, function, c6, vector; /* instruction fields */
+ int n; /* 'friendly', instruction-dependant interpretation of C6 */
+ const instr_desc *the_desc; /* pointer to the revelant entry in the instructions array */
+ char mnemonic[9]; /* storage for generated mnemonic */
+
+ /* read the instruction to disassemble */
+ instruction = oprom[0] << 24 | oprom[1] << 16 | oprom[2] << 8 | oprom[3];
+
+ /* isolate the instruction fields */
+ x = (instruction >> 22) & 0x3FF;
+ y = (instruction >> 12) & 0x3FF;
+ function = (instruction >> 7) & 0x1F;
+ c6 = (instruction >> 1) & 0x3F;
+ vector = instruction & 1;
+
+ /* get the revelant entry in instructions */
+ the_desc = & instructions[function >> 1];
+
+ /* generate mnemonic : append a 'v' to the basic mnemonic if it is a vector instruction */
+ sprintf(mnemonic, "%.*s%c", (int)sizeof(mnemonic)-2, the_desc->mnemonic, vector ? 'v' : ' ');
+
+ /* print mnemonic and n immediate */
+ switch (the_desc->format)
+ {
+ case one_address:
+ case two_address:
+ case branch:
+ case swap:
+ buffer += sprintf(buffer, " %-10s", mnemonic); /* 10 chars*/
+ break;
+
+ case shiftl:
+ case shiftr:
+ if (the_desc->format == shiftl)
+ n = c6;
+ else
+ n = 64-c6;
+ buffer += sprintf(buffer, " %-2s(%2d) ", mnemonic, n); /* 10 chars */
+ break;
+
+ case multiply:
+ n = 33-c6;
+ if (n == 32)
+ /* case "32" : do not show bit specifier */
+ buffer += sprintf(buffer, " %-10s", mnemonic); /* 10 chars */
+ else
+ buffer += sprintf(buffer, " %-2s(%2d) ", mnemonic, n); /* 10 chars */
+ break;
+
+ case store:
+ if (c6 == 0)
+ { /* case "1-32" : do not show bit specifier */
+ buffer += sprintf(buffer, " %-10s", mnemonic); /* 10 chars*/
+ }
+ else if (c6 & 0x20)
+ { /* case "1-n" */
+ n = c6-32;
+ buffer += sprintf(buffer, " %-2s (1-%02d) ", mnemonic, n); /* 10 chars */
+ }
+ else
+ { /* case "n-32" */
+ n = c6+1;
+ buffer += sprintf(buffer, " %-2s(%02d-32) ", mnemonic, n); /* 8 chars */
+ }
+ }
+
+ /* print X address */
+ switch (the_desc->format)
+ {
+ case branch:
+ buffer--; /* eat last char */
+ buffer += sprintf(buffer, "<%03X(%02d/%02d) >=", x<<2, (x >> 5) & 0x1f, x & 0x1f); /* 10+1 chars */
+ break;
+
+ case multiply:
+ case swap:
+ buffer += sprintf(buffer, " (%02d) ", (x >> 5) & 0x1f); /* 10 chars */
+ break;
+
+ case one_address:
+ case shiftl:
+ case shiftr:
+ buffer += sprintf(buffer, " "); /* 10 chars */
+ break;
+
+ case two_address:
+ case store:
+ buffer += sprintf(buffer, "%03X(%02d/%02d) ", x<<2, (x >> 5) & 0x1f, x & 0x1f); /* 10 chars */
+ break;
+ }
+
+ /* print Y address */
+ buffer += sprintf(buffer, "%03X(%02d/%02d)", y<<2, (y >> 5) & 0x1f, y & 0x1f); /* 7 chars */
+
+ return 4;
+}