summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/dsp56k/dsp56ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/dsp56k/dsp56ops.c')
-rw-r--r--src/emu/cpu/dsp56k/dsp56ops.c2599
1 files changed, 2599 insertions, 0 deletions
diff --git a/src/emu/cpu/dsp56k/dsp56ops.c b/src/emu/cpu/dsp56k/dsp56ops.c
new file mode 100644
index 00000000000..a6907f20b58
--- /dev/null
+++ b/src/emu/cpu/dsp56k/dsp56ops.c
@@ -0,0 +1,2599 @@
+/***************************************************************************
+
+ dsp56kops.c
+ Core implementation for the portable Motorola/Freescale DSP56k emulator.
+ Written by Andrew Gardner
+
+***************************************************************************/
+
+// Helper functions and macros
+#define BITS(CUR,MASK) (Dsp56kOpMask(CUR,MASK))
+static UINT16 Dsp56kOpMask(UINT16 op, UINT16 mask) ;
+
+enum dataType { DT_BYTE, DT_WORD, DT_DOUBLE_WORD, DT_LONG_WORD } ;
+
+// This function's areguments are written source->destination to fall in line with the processor's paradigm...
+static void SetDestinationValue(void *sourcePointer, unsigned char sourceType,
+ void *destinationPointer, unsigned char destinationType) ;
+
+static void SetDataMemoryValue (void *sourcePointer, unsigned char sourceType, UINT32 destinationAddr) ;
+static void SetProgramMemoryValue(void *sourcePointer, unsigned char sourceType, UINT32 destinationAddr) ;
+
+
+// Main opcode categories
+static unsigned ExecuteDataALUOpcode(int parallelType) ;
+static unsigned ExecuteDXMDROpcode(void) ;
+static unsigned ExecuteNPMOpcode(void) ;
+static unsigned ExecuteMisfitOpcode(void) ;
+static unsigned ExecuteSpecialOpcode(void) ;
+
+
+// Actual opcode implementations
+
+// Data ALU Ops
+static int ClrOperation(void **wd, UINT64 *pa) ;
+static int AddOperation(void **wd, UINT64 *pa) ;
+static int NotOperation(void **wd, UINT64 *pa) ;
+static int LsrOperation(void **wd, UINT64 *pa) ;
+static int AsrOperation(void **wd, UINT64 *pa) ;
+static int TfrDataALUOperation(void **wd, UINT64 *pa) ;
+static int EorOperation(void **wd, UINT64 *pa) ;
+static int CmpOperation(void **wd, UINT64 *pa) ;
+static int Dec24Operation(void **wd, UINT64 *pa) ;
+static int AndOperation(void **wd, UINT64 *pa) ;
+static int OrOperation(void **wd, UINT64 *pa) ;
+static int TstOperation(void **wd, UINT64 *pa) ;
+
+static int MoveCOperation(void) ;
+static int MoveMOperation(void) ;
+static int MoveIOperation(void) ;
+static int MovePOperation(void) ;
+
+static int AndiOperation(void) ;
+//static int OriOperation(void) ;
+
+static int BitfieldOperation(void) ;
+static int JmpOperation(void) ;
+static int BsrOperation(void) ;
+static int JsrOperation(void) ;
+static int DoOperation(void) ;
+static int TccOperation(void) ;
+static int BraOperation(void) ;
+static int BsccOperation(void) ;
+static int BccOperation(void) ;
+static int Tst2Operation(void) ;
+static int MACsuuuOperation(void) ;
+static int RepOperation(void) ;
+
+static void EndOfLoopProcessing(void) ;
+static void EndOfRepProcessing(void) ;
+
+// Parallel memory data moves
+static void XMDMOperation(UINT16 parameters, void *working, UINT64 *pa) ;
+static void XMDMSpecialOperation(UINT16 parameters, void *working) ;
+static void ARUOperation(UINT16 parameters) ;
+static void RRDMOperation(UINT16 parameters, void *working, UINT64 *pa) ;
+
+// For decoding the different types of tables...
+static void *DecodeDDDDDTable(UINT16 DDDDD, unsigned char *dt) ;
+static void *DecodeRRTable(UINT16 RR, unsigned char *dt) ;
+static void *DecodeDDTable(UINT16 DD, unsigned char *dt) ;
+static void *DecodeHHHTable(UINT16 HHH, unsigned char *dt) ;
+static void *DecodeHHTable(UINT16 HH, unsigned char *dt) ;
+static void *DecodeZTable(UINT16 Z, unsigned char *dt) ;
+static UINT16 DecodeBBBBitMask(UINT16 BBB, UINT16 *iVal) ;
+static int DecodeccccTable(UINT16 cccc) ;
+static void Decodeh0hFTable(UINT16 h0h, UINT16 F, void **source, unsigned char *st, void **dest, unsigned char *dt) ;
+static void *DecodeFTable(UINT16 F, unsigned char *dt) ;
+static void DecodeJJJFTable(UINT16 JJJ, UINT16 F, void **source, unsigned char *st, void **dest, unsigned char *dt) ;
+static void DecodeJJFTable(UINT16 JJ, UINT16 F, void **source, unsigned char *st, void **dest, unsigned char *dt) ;
+static void DecodeQQFTableSp(UINT16 QQ, UINT16 F, void **S1, void **S2, void **D) ;
+static void DecodeIIIITable(UINT16 IIII, void **source, unsigned char *st, void **dest, unsigned char *dt, void *working) ;
+
+static void ExecuteMMTable(int x, UINT16 MM) ;
+static void ExecutemTable(int x, UINT16 m) ;
+static void ExecutezTable(int x, UINT16 z) ;
+static UINT16 ExecuteqTable(int x, UINT16 q) ;
+
+static UINT16 AssembleDFromPTable(UINT16 P, UINT16 ppppp) ;
+
+static UINT16 AssembleAddressFromIOShortAddress(UINT16 pp) ;
+static UINT16 AssembleAddressFrom6BitSignedRelativeShortAddress(UINT16 srs) ;
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+#ifdef UNUSED_FUNCTION
+static void unimplemented(void)
+{
+ fatalerror("Unimplemented OP @ %04X: %04X", PC-2, OP) ;
+}
+#endif
+
+
+static void execute_one(void)
+{
+ unsigned size = 666 ;
+
+ CALL_MAME_DEBUG;
+ OP = ROPCODE(PC<<1);
+
+ if (BITS(OP,0x8000)) // First, the parallel data move instructions
+ {
+ size = ExecuteDataALUOpcode(PARALLEL_TYPE_XMDM) ;
+ }
+ else if (BITS(OP,0xf000) == 0x5)
+ {
+ size = ExecuteDataALUOpcode(PARALLEL_TYPE_XMDM_SPECIAL) ;
+ }
+ else if (BITS(OP,0xff00) == 0x4a)
+ {
+ size = ExecuteDataALUOpcode(PARALLEL_TYPE_NODM) ;
+ }
+ else if (BITS(OP,0xf000) == 0x04)
+ {
+ size = ExecuteDataALUOpcode(PARALLEL_TYPE_RRDM) ;
+ }
+ else if (BITS(OP,0xf800) == 0x06)
+ {
+ size = ExecuteDataALUOpcode(PARALLEL_TYPE_ARU) ;
+ }
+
+
+ else if (BITS(OP,0x4000))
+ {
+ size = ExecuteDXMDROpcode() ;
+ }
+ else if (BITS(OP,0xf000) == 0x1)
+ {
+ size = ExecuteNPMOpcode() ;
+ }
+ else if (BITS(OP,0x2000))
+ {
+ size = ExecuteMisfitOpcode() ;
+ }
+ else if (BITS(OP,0xf000) == 0x0)
+ {
+ size = ExecuteSpecialOpcode();
+ }
+
+ if (size == 666)
+ {
+ mame_printf_debug("unimplemented at %04x\n", PC) ;
+ size = 1 ; // Just to get the debugger past the bad opcode
+ }
+
+
+ PC += size ;
+ change_pc(PC) ;
+
+ // Loop processing
+ if (lfBIT)
+ {
+ if (PC == LA)
+ {
+ // You're on the last instruction of the loop...
+ if (LC != 1) // Strange, the == 1 thing...
+ {
+ LC-- ;
+ PC = SSH ;
+ change_pc(PC) ;
+ }
+ else
+ {
+ EndOfLoopProcessing() ;
+ }
+ }
+ }
+
+ // Rep processing
+ if (dsp56k.repFlag)
+ {
+ if (PC == dsp56k.repAddr)
+ {
+ if (LC != 1)
+ {
+ LC-- ;
+ PC -= size ; // Eh, seems reasonable :)
+ change_pc(PC) ;
+ }
+ else
+ {
+ EndOfRepProcessing() ;
+ }
+ }
+ }
+
+ dsp56k_icount -= 4; /* Temporarily hard-coded at 4 clocks per opcode */
+}
+
+
+static unsigned ExecuteDataALUOpcode(int parallelType)
+{
+ unsigned retSize = 666 ;
+
+ void *workingDest = 0x00 ;
+
+ // Whenever an instruction uses an accumulator as both a destination operand for a Data ALU operation and
+ // as a source for a parallel move operation, the parallel move operation will use the value in the accumulator
+ // prior to execution of any Data ALU operation.
+ UINT64 previousAccum = 0 ;
+
+ switch(BITS(OP,0x0070))
+ {
+
+ case 0x0:
+ if (BITS(OP,0x0007) == 0x1)
+ {
+ // CLR - 1mRR HHHW 0000 F001
+ retSize = ClrOperation(&workingDest, &previousAccum) ;
+ }
+ else
+ {
+ // ADD - 1mRR HHHW 0000 FJJJ
+ retSize = AddOperation(&workingDest, &previousAccum) ;
+ }
+ break ;
+
+ case 0x1:
+ if (BITS(OP,0x000f) == 0x1)
+ {
+ // MOVE - 1mRR HHHW 0001 0001
+ retSize = 1 ;
+ }
+ else
+ {
+ // TFR - 1mRR HHHW 0001 FJJJ
+ retSize = TfrDataALUOperation(&workingDest, &previousAccum) ;
+ }
+ break ;
+
+ case 0x2:
+ if (BITS(OP,0x0007) == 0x0)
+ {
+ // RND - 1mRR HHHW 0010 F000
+ }
+ else if (BITS(OP,0x0007) == 0x1)
+ {
+ // TST - 1mRR HHHW 0010 F001
+ retSize = TstOperation(&workingDest, &previousAccum);
+ }
+ else if (BITS(OP,0x0007) == 0x2)
+ {
+ // INC - 1mRR HHHW 0010 F010
+ }
+ else if (BITS(OP,0x0007) == 0x3)
+ {
+ // INC24 - 1mRR HHHW 0010 F011
+ }
+ else
+ {
+ // OR - 1mRR HHHW 0010 F1JJ
+ retSize = OrOperation(&workingDest, &previousAccum) ;
+ }
+ break ;
+
+ case 0x3:
+ if (BITS(OP,0x0007) == 0x0)
+ {
+ // ASR - 1mRR HHHW 0011 F000
+ retSize = AsrOperation(&workingDest, &previousAccum) ;
+ }
+ else if (BITS(OP,0x0007) == 0x1)
+ {
+ // ASL - 1mRR HHHW 0011 F001
+ }
+ else if (BITS(OP,0x0007) == 0x2)
+ {
+ // LSR - 1mRR HHHW 0011 F010
+ retSize = LsrOperation(&workingDest, &previousAccum) ;
+ }
+ else if (BITS(OP,0x0007) == 0x3)
+ {
+ // LSL - 1mRR HHHW 0011 F011
+ }
+ else
+ {
+ // EOR - 1mRR HHHW 0011 F1JJ
+ retSize = EorOperation(&workingDest, &previousAccum) ;
+ }
+ break ;
+/*
+ case 0x4:
+ if (BITS(op,0x0007) == 0x1)
+ {
+ // SUBL - 1mRR HHHW 0100 F001
+ }
+ else
+ {
+ // SUB - 1mRR HHHW 0100 FJJJ
+ }
+ break ;
+*/
+ case 0x5:
+ if (BITS(OP,0x0007) == 0x1)
+ {
+ // CLR24 - 1mRR HHHW 0101 F001
+ }
+ else if (BITS(OP,0x0006) == 0x1)
+ {
+ // SBC - 1mRR HHHW 0101 F01J
+ }
+ else
+ {
+ // CMP - 1mRR HHHW 0101 FJJJ
+ retSize = CmpOperation(&workingDest, &previousAccum) ;
+ }
+ break ;
+
+ case 0x6:
+ if (BITS(OP,0x0007) == 0x0)
+ {
+ // NEG - 1mRR HHHW 0110 F000
+ }
+ else if (BITS(OP,0x0007) == 0x1)
+ {
+ // NOT - 1mRR HHHW 0110 F001
+ retSize = NotOperation(&workingDest, &previousAccum) ;
+ }
+ else if (BITS(OP,0x0007) == 0x2)
+ {
+ // DEC - 1mRR HHHW 0110 F010
+ }
+ else if (BITS(OP,0x0007) == 0x3)
+ {
+ // DEC24 - 1mRR HHHW 0110 F011
+ retSize = Dec24Operation(&workingDest, &previousAccum) ;
+ }
+ else
+ {
+ // AND - 1mRR HHHW 0110 F1JJ
+ retSize = AndOperation(&workingDest, &previousAccum) ;
+ }
+ break ;
+/*
+ case 0x7:
+ if (BITS(op,0x0007) == 0x1)
+ {
+ // ABS - 1mRR HHHW 0111 F001
+ }
+ if (BITS(op,0x0007) == 0x2)
+ {
+ // ROR - 1mRR HHHW 0111 F010
+ }
+ if (BITS(op,0x0007) == 0x3)
+ {
+ // ROL - 1mRR HHHW 0111 F011
+ }
+ else
+ {
+ // CMPM - 1mRR HHHW 0111 FJJJ
+ }
+
+ break ;
+*/
+ }
+
+/*
+ // Otherwise you're looking at a MPY/MAC operation...
+ if (BITS(op,0x0080)) // Maybe i should un-consolidate here?
+ {
+ DecodeQQQFTable(BITS(op,0x0007), BITS(op,0x0008), S1, S2, D) ;
+ DecodekSignTable(BITS(op,0x0040), sign) ;
+
+ switch(BITS(op,0x00b0))
+ {
+ // MPY - 1mRR HHHH 1k00 FQQQ
+ case 0x4: sprintf(buffer, "mpy (%s)%s,%s,%s", sign, S2, S1, D) ; break ;
+
+ // MPYR - 1mRR HHHH 1k01 FQQQ
+ case 0x5: sprintf(buffer, "mpyr (%s)%s,%s,%s", sign, S2, S1, D) ; break ;
+
+ // MAC - 1mRR HHHH 1k10 FQQQ
+ case 0x6: sprintf(buffer, "mac (%s)%s,%s,%s", sign, S2, S1, D) ; break ;
+
+ // MACR - 1mRR HHHH 1k11 FQQQ
+ case 0x7: sprintf(buffer, "macr (%s)%s,%s,%s", sign, S1, S2, D) ; break ;
+ // !! It's a little odd that macr is S1,S2 while everyone else is S2,S1 !!
+ }
+
+ retSize = 1 ;
+ }
+*/
+
+ // Do the parallel move parallel'y :)
+ // Someday we may have to check against the special cases to throw exceptions !!
+ switch (parallelType)
+ {
+ case PARALLEL_TYPE_XMDM:
+ XMDMOperation(BITS(OP,0xff00), workingDest, &previousAccum) ;
+ break ;
+
+ case PARALLEL_TYPE_RRDM:
+ RRDMOperation(BITS(OP,0xff00), workingDest, &previousAccum) ;
+ break ;
+
+ case PARALLEL_TYPE_XMDM_SPECIAL:
+ // pa is not needed because the XMDM dest is always the .opposite. of the regular dest.
+ XMDMSpecialOperation(BITS(OP,0xff00), workingDest) ;
+ break ;
+
+ case PARALLEL_TYPE_NODM:
+ // do nothing
+ break ;
+
+ case PARALLEL_TYPE_ARU:
+ ARUOperation(BITS(OP,0xff00)) ;
+ break ;
+ }
+
+ return retSize ;
+}
+
+static unsigned ExecuteDXMDROpcode(void)
+{
+ unsigned retSize = 666 ;
+
+ return retSize ;
+}
+
+static unsigned ExecuteNPMOpcode(void)
+{
+ unsigned retSize = 666 ;
+
+ if (BITS(OP,0x0f00) == 0x4)
+ {
+ retSize = BitfieldOperation() ;
+ }
+ else if (BITS(OP,0x0f00) == 0x5)
+ {
+ switch(BITS(OP,0x0074))
+ {
+ case 0x0:
+ if (BITS(OP,0x0006) == 0x0)
+ {
+ // TFR(2) - 0001 0101 0000 F00J
+ retSize = 1 ;
+ }
+ else if (BITS(OP,0x0006) == 0x1)
+ {
+ // ADC - 0001 0101 0000 F01J
+ retSize = 1 ;
+ }
+ break ;
+
+ case 0x3:
+ // TST(2) - 0001 0101 0001 -1DD
+ retSize = Tst2Operation() ; break ;
+
+ case 0x4:
+ // NORM - 0001 0101 0010 F0RR
+ retSize = 1 ; break ;
+
+ case 0x6:
+ if (BITS(OP,0x0003) == 0x0)
+ {
+ // ASR4 - 0001 0101 0011 F000
+ retSize = 1 ;
+ }
+ else if (BITS(OP,0x0003) == 0x1)
+ {
+ // ASL4 - 0001 0101 0011 F001
+ retSize = 1 ;
+ }
+ break ;
+
+ case 0x1: case 0x5: case 0x9: case 0xd:
+ // DIV - 0001 0101 0--0 F1DD
+ retSize = 1 ; break ;
+
+ case 0xa:
+ if (BITS(OP,0x0003) == 0x0)
+ {
+ // ZERO - 0001 0101 0101 F000
+ retSize = 1 ;
+ }
+ else if (BITS(OP,0x0003) == 0x2)
+ {
+ // EXT - 0001 0101 0101 F010
+ retSize = 1 ;
+ }
+ break ;
+
+ case 0xc:
+ if (BITS(OP,0x0003) == 0x0)
+ {
+ // NEGC - 0001 0101 0110 F000
+ retSize = 1 ;
+ }
+ break ;
+
+ case 0xe:
+ if (BITS(OP,0x0003) == 0x0)
+ {
+ // ASR16 - 0001 0101 0111 F000
+ retSize = 1 ;
+ }
+ else if (BITS(OP,0x0003) == 0x1)
+ {
+ // SWAP - 0001 0101 0111 F001
+ retSize = 1 ;
+ }
+ break ;
+ }
+
+ switch(BITS(OP,0x00f0))
+ {
+ case 0x8:
+ // IMPY - 0001 0101 1000 FQQQ
+ retSize = 1 ; break ;
+ case 0xa:
+ // IMAC - 0001 0101 1010 FQQQ
+ retSize = 1 ; break ;
+ case 0x9: case 0xb:
+ // DMAC(ss,su,uu) - 0001 0101 10s1 FsQQ
+ retSize = 1 ; break ;
+ case 0xc:
+ // MPY(su,uu) - 0001 0101 1100 FsQQ
+ retSize = 1 ; break ;
+ case 0xe:
+ // MAC(su,uu) - 0001 0101 1110 FsQQ
+ retSize = MACsuuuOperation() ; break ;
+ }
+ }
+ else if ((BITS(OP,0x0f00) == 0x6))
+ {
+ retSize = 1 ;
+ }
+ else if ((BITS(OP,0x0f00) == 0x7))
+ {
+ retSize = 1 ;
+ }
+ else if ((BITS(OP,0x0800) == 0x1))
+ {
+ if (BITS(OP,0x0600))
+ {
+ if (!BITS(OP,0x0100))
+ {
+ // ANDI - 0001 1EE0 iiii iiii
+ retSize = AndiOperation() ;
+ }
+ else
+ {
+ // ORI - 0001 1EE1 iiii iiii
+ }
+ }
+ else
+ {
+ if (!BITS(OP,0x0020))
+ {
+ // MOVE(S) - 0001 100W HH0a aaaa
+ }
+ else
+ {
+ // MOVE(P) - 0001 100W HH1p pppp
+ retSize = MovePOperation() ;
+ }
+ }
+ }
+ else if ((BITS(OP,0x0c00) == 0x0))
+ {
+ retSize = TccOperation() ;
+ }
+
+ return retSize ;
+}
+
+static unsigned ExecuteMisfitOpcode(void)
+{
+ unsigned retSize = 666 ;
+
+ if (BITS(OP,0x1000)== 0x0)
+ {
+ switch(BITS(OP,0x0c00))
+ {
+ // MOVE(I) - 0010 00DD BBBB BBBB
+ case 0x0:
+ retSize = MoveIOperation() ;
+ break ;
+
+/*
+ case 0x1:
+ // TFR(3) - 0010 01mW RRDD FHHH
+ break ;
+*/
+ case 0x2:
+ // MOVE(C) - 0010 10dd dddD DDDD
+ retSize = MoveCOperation() ;
+ break ;
+
+ case 0x3:
+ // B.cc - 0010 11cc ccee eeee
+ retSize = BccOperation() ;
+ break ;
+ }
+ }
+ else
+ {
+ // MOVE(C) - 0011 1WDD DDD0 MMRR
+ // MOVE(C) - 0011 1WDD DDD1 q0RR
+ // MOVE(C) - 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx
+ // MOVE(C) - 0011 1WDD DDD1 Z11-
+ retSize = MoveCOperation() ;
+ }
+
+ return retSize ;
+}
+
+static unsigned ExecuteSpecialOpcode(void)
+{
+ unsigned retSize = 666 ;
+
+ if (BITS(OP,0x0ff0) == 0x0)
+ {
+ switch (BITS(OP,0x000f))
+ {
+ // NOP - 0000 0000 0000 0000
+ case 0x0:
+ retSize = 1 ;
+ break ;
+
+ // DO FOREVER - 0000 0000 0000 0010 xxxx xxxx xxxx xxxx
+ case 0x2:
+ // !!! IMPLEMENT ME NEXT;
+ retSize = 0;
+ break;
+
+ // RTS - 0000 0000 0000 0110
+ case 0x6:
+ PC = SSH ;
+ SR = SSL ;
+ SP-- ;
+ retSize = 0 ;
+ change_pc(PC) ;
+ break ;
+
+ // RTI - 0000 0000 0000 0111
+ case 0x7:
+ PC = SSH;
+ SR = SSL;
+ SP--;
+ retSize = 0;
+ change_pc(PC);
+ break;
+ }
+ }
+ else if (BITS(OP,0x0f00) == 0x0)
+ {
+ retSize = 1 ;
+ }
+ else if (BITS(OP,0x0f00) == 0x1)
+ {
+ if (BITS(OP,0x00f0) == 0x1)
+ {
+ retSize = 1 ;
+ }
+ else if (BITS(OP,0x00f0) == 0x2)
+ {
+ switch(BITS(OP,0x000c)) // Consolidation can happen here
+ {
+ // JSR - 0000 0001 0010 00RR
+ // JMP - 0000 0001 0010 01RR
+ case 0x1: retSize = JmpOperation(); break;
+ // BSR - 0000 0001 0010 10RR
+ // BRA - 0000 0001 0010 11RR
+ default: retSize = 1;
+ }
+ }
+ else if (BITS(OP,0x00f0) == 0x3)
+ {
+ switch(BITS(OP,0x000c))
+ {
+ // JSR - 0000 0001 0011 00-- xxxx xxxx xxxx xxxx
+ case 0x0: retSize = JsrOperation() ; break ;
+ // JMP - 0000 0001 0011 01-- xxxx xxxx xxxx xxxx
+ case 0x1: retSize = JmpOperation() ; break ;
+ // BSR - 0000 0001 0011 10-- xxxx xxxx xxxx xxxx
+ case 0x2: retSize = BsrOperation() ; break ;
+ }
+ }
+ else if (BITS(OP,0x00f0) == 0x5)
+ {
+ retSize = 1 ;
+ }
+ else if (BITS(OP,0x0080) == 0x1)
+ {
+ retSize = 1 ;
+ }
+ }
+ else if (BITS(OP,0x0e00) == 0x1)
+ {
+ if (BITS(OP,0x0020) == 0x0)
+ {
+ // MOVE(M) - 0000 001W RR0M MHHH
+ retSize = MoveMOperation() ;
+ }
+ }
+ else if (BITS(OP,0x0f00) == 0x4)
+ {
+ if (BITS(OP,0x0020) == 0x0)
+ {
+ // DO - 0000 0100 000D DDDD xxxx xxxx xxxx xxxx
+ retSize = DoOperation() ;
+ }
+ else
+ {
+ // REP - 0000 0100 001D DDDD
+ retSize = RepOperation() ;
+ }
+ }
+ else if (BITS(OP,0x0f00) == 0x5)
+ {
+ UINT16 op2 = ROPCODE((PC<<1)+2) ;
+
+ if (BITS(op2,0xfe20) == 0x02)
+ {
+ // MOVE(M) - 0000 0101 BBBB BBBB | 0000 001W --0- -HHH
+ retSize = MoveMOperation() ;
+ }
+ else if (BITS(op2,0xf810) == 0x0e)
+ {
+ // MOVE(C) - 0000 0101 BBBB BBBB | 0011 1WDD DDD0 ----
+ }
+ else if (BITS(op2,0x00ff) == 0x11)
+ {
+ // MOVE - 0000 0101 BBBB BBBB | ---- HHHW 0001 0001
+ }
+ }
+ else if (BITS(OP,0x0f00) == 0x6)
+ {
+ retSize = 1 ;
+ }
+ else if (BITS(OP,0x0f00) == 0x7)
+ {
+ switch(BITS(OP,0x0030))
+ {
+ // BS.cc - 0000 0111 RR00 cccc
+ case 0x0: retSize = 1 ; break ;
+
+ // BS.cc - 0000 0111 --01 cccc xxxx xxxx xxxx xxxx
+ case 0x1: retSize = BsccOperation() ; break ;
+
+ // B.cc - 0000 0111 RR10 cccc
+ case 0x2: retSize = 1 ; break ;
+
+ // B.cc - 0000 0111 --11 cccc xxxx xxxx xxxx xxxx
+ case 0x3: retSize = BccOperation() ; break ;
+ }
+ }
+ else if (BITS(OP,0x0800))
+ {
+ switch (BITS(OP,0x0700))
+ {
+ // BRA - 0000 1011 aaaa aaaa
+ case 0x3: retSize = BraOperation() ; break ;
+
+ // MOVE(P) - 0000 110W RRmp pppp
+ case 0x4: case 0x5: retSize = MovePOperation() ; break ;
+
+ // DO - 0000 1110 iiii iiii xxxx xxxx xxxx xxxx
+ case 0x6: retSize = DoOperation() ; break ;
+
+ // REP - 0000 1111 iiii iiii
+ case 0x7: retSize = RepOperation() ; break ;
+ }
+ }
+
+ return retSize ;
+}
+
+/*
+IMPLEMENTATIONS
+*/
+
+static int BitfieldOperation(void)
+{
+ int retSize = 0 ;
+
+ // BITFIELD OPERATIONS
+ // ONLY PARTIALLY IMPLEMENTED !!!
+
+ // Get the next part of the opcode...
+ UINT16 op2 = ROPCODE((PC<<1)+2) ;
+
+ unsigned char dt = 0x00 ;
+ void *destinationReg = 0x00 ;
+ void *rReg = 0x00 ;
+
+ UINT16 destAddr = 0x00 ;
+
+ UINT16 opVal ;
+
+ // Get the universal immediate value and its proper mask...
+ UINT16 iVal = op2 & 0x00ff ;
+ DecodeBBBBitMask(BITS(op2,0xe000), &iVal) ;
+
+ // Figure out where data you'll be dealing with comes from...
+ switch(BITS(OP,0x00e0))
+ {
+ case 0x6: case 0x7: case 0x2: case 0x3:
+ destAddr = AssembleDFromPTable(BITS(OP,0x0020), BITS(OP,0x001f)) ;
+ break ;
+
+ case 0x5: case 0x1:
+ rReg = DecodeRRTable(BITS(OP,0x0003), &dt) ;
+ destAddr = *((UINT16*)rReg) ;
+ break ;
+
+ case 0x4: case 0x0:
+ destinationReg = DecodeDDDDDTable(BITS(OP,0x001f), &dt) ;
+ break ;
+ }
+
+ // Grab the value to operate on...
+ if (destinationReg)
+ {
+ if (dt == DT_LONG_WORD)
+ opVal = (*((PAIR64*)destinationReg)).w.h ;
+ else
+ opVal = *((UINT16*)destinationReg) ;
+ }
+ else
+ opVal = data_read_word_16le(destAddr<<1) ;
+
+ // Do the necessary bitfield operation...
+ switch(BITS(op2,0x1f00))
+ {
+ // bfchg
+ case 0x12:
+ if ((iVal & opVal) == iVal) SET_cBIT() ; // test
+ else CLEAR_cBIT() ;
+
+ opVal ^= iVal ; // and change
+ break ;
+
+ // bfclr
+ case 0x04:
+ opVal &= (~iVal) ;
+ break ;
+
+ // bfset
+ case 0x18:
+ opVal |= iVal ;
+ break ;
+
+ // bfsth
+ case 0x10:
+ mame_printf_debug("BFSTH - not here yet") ;
+ break ;
+
+ // bftstl
+ case 0x00:
+ if ((iVal & opVal) == 0) SET_cBIT() ;
+ else CLEAR_cBIT() ;
+ retSize = 2; return retSize; /* It's just a test - no need to go on */
+ break ;
+ }
+
+ // Put the data back where it belongs
+ // !!! When setting A and B, I'm pretty sure if it's supposed to pass through the normal 'setDestValue' pipe but not entirely !!!
+ // (in other words, does clearing ff.ffff.ffff with 001c really result in ff.ffe3.0000 or ff.ffe3.ffff) ???
+ if (destinationReg)
+ SetDestinationValue(&opVal, DT_WORD, destinationReg, dt) ;
+ else
+ SetDataMemoryValue(&opVal, DT_WORD, destAddr<<1) ;
+
+ retSize = 2 ;
+ return retSize ;
+}
+
+static int MoveCOperation(void)
+{
+ int retSize = 0 ;
+
+ unsigned char W = 0x00 ;
+
+ unsigned char sdt = 0x00 ;
+ void *SD ;
+
+ // ONLY PARTIALLY IMPLEMENTED !!!
+
+ SD = DecodeDDDDDTable(BITS(OP,0x03e0), &sdt) ;
+ W = BITS(OP,0x0400) ;
+
+ if (BITS(OP,0x1000))
+ {
+ // Single source/destination move(c)
+ if (!BITS(OP,0x0010))
+ {
+ // MM in move(c)
+
+ // Get the r register...
+ unsigned char rt = 0x00 ;
+ void *R ;
+
+ R = DecodeRRTable(BITS(OP,0x0003), &rt) ;
+
+ if (W)
+ {
+ // !!! does this work ???
+ UINT16 data = data_read_word_16le((*((UINT16*)R))<<1) ;
+ SetDestinationValue(&data, DT_WORD, SD, sdt) ;
+ }
+ else
+ {
+ SetDataMemoryValue(SD, sdt, (*((UINT16*)R))<<1) ;
+ }
+
+ ExecuteMMTable(BITS(OP,0x0003), BITS(OP,0x000c)) ;
+ retSize = 1 ;
+ }
+ else
+ {
+ if (!BITS(OP,0x0004))
+ {
+ // q in move(c)
+
+ // Figure out the true addr...
+ UINT16 addr = ExecuteqTable(BITS(OP,0x0003), BITS(OP,0x0008));
+
+ if (W)
+ {
+ // !!! does this work ???
+ UINT16 data = data_read_word_16le(addr<<1) ;
+ SetDestinationValue(&data, DT_WORD, SD, sdt) ;
+ }
+ else
+ {
+ SetDataMemoryValue(SD, sdt, addr<<1);
+ }
+
+ retSize = 1 ;
+ }
+ else
+ {
+ if (BITS(OP,0x0002))
+ {
+ // Z in move(c)
+ unsigned char rt = 0x00;
+ void *Z;
+
+ Z = DecodeZTable(BITS(OP,0x0008), &rt);
+
+ if (W)
+ {
+ // Unimplemented
+ retSize = 666 ;
+ }
+ else
+ {
+ SetDataMemoryValue(SD, sdt, (*((UINT16*)Z))<<1);
+ retSize = 1;
+ }
+ }
+ else
+ {
+ // 2-word move(c)
+ UINT16 nextWord = ROPCODE((PC<<1)+2) ;
+
+ if (BITS(OP,0x0008))
+ {
+ // #xxxx - value read directly out of the opcode
+ SetDestinationValue(&nextWord, DT_WORD, SD, sdt) ;
+ }
+ else
+ {
+ // X:xxxx = value resides in X memory...
+ if (W)
+ {
+ // Read from X-data memory...
+ // !!! Does this work ???
+ UINT16 data = data_read_word_16le(nextWord<<1) ;
+ SetDestinationValue(&data, DT_WORD, SD, sdt) ;
+ }
+ else
+ {
+ // Write to X-data memory...
+ SetDataMemoryValue(SD, sdt, nextWord<<1) ;
+ }
+ }
+
+ retSize = 2 ;
+ }
+ }
+ }
+ }
+ else if (BITS(OP,0x2000))
+ {
+ // Source and Destination explicit
+ unsigned char dt = 0x00 ;
+ void *D ;
+
+ D = DecodeDDDDDTable(BITS(OP,0x001f), &dt) ;
+ SetDestinationValue(SD, sdt, D, dt) ;
+
+ retSize = 1 ;
+ }
+ else
+ {
+ // Double source/destination move(c)
+
+ retSize = 666 ;
+ }
+
+ return retSize ;
+}
+
+static int MoveMOperation(void)
+{
+ int retSize = 0 ;
+
+ // ONLY PARTIALLY IMPLEMENTED !!!
+
+ if (BITS(OP,0x0400))
+ {
+ // The double word MoveM operation...
+ UINT16 nextWord = ROPCODE((PC<<1)+2) ;
+
+ UINT8 increment = BITS(OP,0x00ff) ;
+
+ int W = BITS(nextWord, 0x0100) ;
+
+ unsigned char sdt = 0x00 ;
+ void *sdReg = 0x00 ;
+ sdReg = DecodeHHHTable(BITS(nextWord,0x0007), &sdt) ;
+
+ if (W)
+ {
+ // Read from Program Memory...
+ UINT16 data = program_read_word_16le((R2<<1)+(increment<<1)) ;
+ SetDestinationValue(&data, DT_WORD, sdReg, sdt) ;
+ }
+ else
+ {
+ // Write to Program Memory...
+ // !!! Does this work ???
+ // SetMemoryValue(sdReg, sdt, ((R2<<1)+(increment<<1))) ;
+ }
+
+ retSize = 2 ;
+ }
+ else
+ {
+ // The single word MoveM operation...
+
+ // Decode which way the data is going...
+ int W = BITS(OP,0x0100) ;
+
+ // Decode which R Register we're working with...
+ unsigned char rt = 0x00 ;
+ void *rReg = 0x00 ;
+ rReg = DecodeRRTable(BITS(OP,0x00c0), &rt) ;
+
+ if (BITS(OP,0x0020))
+ {
+ // R and R operation
+ retSize = 666 ;
+ }
+ else
+ {
+ // R and SD operation
+ // Decode the SD register...
+ unsigned char sdt = 0x00 ;
+ void *sdReg = 0x00 ;
+ sdReg = DecodeHHHTable(BITS(OP,0x0007), &sdt) ;
+
+ if (W)
+ {
+ // Read from Program Memory...
+ UINT16 data = program_read_word_16le( (*((UINT16*)rReg)) << 1 ) ;
+ SetDestinationValue(&data, DT_WORD, sdReg, sdt) ;
+ }
+ else
+ {
+ // Write to Program Memory...
+ SetProgramMemoryValue(sdReg, sdt, (*((UINT16*)rReg)) << 1 ) ;
+ }
+
+ // Execute the increment part of the opcode...
+ ExecuteMMTable(BITS(OP,0x00c0), BITS(OP,0x0018)) ;
+
+ retSize = 1 ;
+ }
+ }
+
+ return retSize ;
+}
+
+static int MoveIOperation(void)
+{
+ int retSize = 1 ;
+
+ // The 8-bit signed immediate operand is stored in the low byte of destination
+ // register D after having been sign extended.
+
+ INT8 immediateVal = OP & 0x00ff ;
+ UINT16 immediateWord ;
+
+ unsigned char dt = 0x00 ;
+ void *destinationReg = 0x00 ;
+
+ destinationReg = DecodeDDTable(BITS(OP,0x0300), &dt) ;
+
+ // Sign extend the immediate value...
+ // !!! On Intel architecture this works correctly, does it work everywhere ???
+ immediateWord = (INT16)immediateVal ;
+
+ SetDestinationValue(&immediateWord, DT_WORD, destinationReg, dt) ;
+
+ return retSize ;
+}
+
+static int MovePOperation(void)
+{
+ int retSize = 1 ;
+
+ if (BITS(OP,0x1000))
+ {
+ // X:<pp> and SD
+ UINT16 pp ;
+ UINT16 W ;
+
+ unsigned char sdt = 0x00 ;
+ void *SD = 0x00 ;
+
+ SD = DecodeHHTable(BITS(OP,0x00c0), &sdt) ;
+
+ pp = BITS(OP,0x001f) ;
+ pp = AssembleAddressFromIOShortAddress(pp) ;
+
+ W = BITS(OP,0x0100) ;
+
+ if (W)
+ {
+ UINT16 data = data_read_word_16le(pp<<1) ;
+ SetDestinationValue(&data, DT_WORD, SD, sdt) ;
+ }
+ else
+ {
+ SetDataMemoryValue(SD, sdt, pp<<1) ;
+ }
+ }
+ else
+ {
+ // X:<Rx> and X:<pp>
+ UINT16 pp ;
+ UINT16 W ;
+
+ unsigned char sdrt = 0x00 ;
+ void *sdrReg = 0x00 ;
+ sdrReg = DecodeRRTable(BITS(OP,0x00c0), &sdrt) ;
+
+ pp = BITS(OP,0x001f) ;
+ pp = AssembleAddressFromIOShortAddress(pp) ;
+
+ W = BITS(OP,0x0100) ;
+
+ // A little different than most W if's - opposite read and write thingies...
+ if (W)
+ {
+ UINT16 data = data_read_word_16le( (*((UINT16*)sdrReg))<<1 ) ; // read the word out
+ SetDataMemoryValue(&data, DT_WORD, pp<<1) ;
+ }
+ else
+ {
+ mame_printf_debug("NOTHING HERE (yet)\n") ;
+ }
+
+ // Postincrement
+ ExecutemTable(BITS(OP,0x00c0), BITS(OP,0x0020)) ;
+ }
+
+ return retSize ;
+}
+
+
+static int JmpOperation(void)
+{
+ int retSize = 0 ;
+
+ dsp56k.ppc = PC;
+
+ if (BITS(OP,0x0010))
+ {
+ PC = (ROPCODE((PC<<1)+2)) ; // Can this offset by 2 bytes be handled better? Say, for example, by moving "1 word"?
+ change_pc(PC) ;
+ }
+ else
+ {
+ unsigned char rt = 0x00 ;
+ void *R = 0x00 ;
+
+ R = DecodeRRTable(BITS(OP,0x0003), &rt);
+
+ PC = *((UINT16*)R);
+ change_pc(PC);
+ }
+
+ retSize = 0 ; // Jump with no offset.
+
+ return retSize ;
+}
+
+static int BsrOperation(void)
+{
+ int retSize = 0 ;
+
+ INT16 branchOffset = (ROPCODE((PC<<1)+2)) ; // Can this offset by 2 bytes be handled better? Say, for example, by moving "1 word"?
+
+ // "The PC Contains the address of the next instruction"
+ PC += 2 ;
+ dsp56k.ppc = PC ;
+
+ // Push the PC to the stack...
+ SP++ ; // !!! I'm not so sure about this 'pre-increment'
+ // The reason it might be there is that SSH and SSL are supposed to point to the top of the
+ // stack (and the docs seem to imply this behaviour). But it wastes the first stack entry ???
+ // !!! I think i've read somewhere that PC == 1 when the stack is empty ???
+ // !!! I also .know. there are only 15 stack entries - could this be why ???
+ SSH = PC ;
+ SSL = SR ;
+
+ PC += branchOffset ;
+
+ retSize = 0 ; // Branch and then no offset.
+
+ change_pc(PC) ;
+
+ return retSize ;
+}
+
+static int JsrOperation(void)
+{
+ int retSize = 0;
+
+ // Handle other JSR types!
+ INT16 branchOffset = (ROPCODE((PC<<1)+2)) ; // Can this offset by 2 bytes be handled better? Say, for example, by moving "1 word"?
+
+ // The docs say nothing of this, but I swear it *must* be true
+ PC += 2 ;
+ dsp56k.ppc = PC ;
+
+ // See bsr operation
+ SP++;
+ SSH = PC;
+ SSL = SR;
+
+ PC = branchOffset;
+
+ return retSize;
+}
+
+static int BraOperation(void)
+{
+ int retSize = 0 ;
+
+ // Branch to the location in program memory at location PC+displacement.
+ INT16 branchOffset = 0x00;
+
+ if (BITS(OP,0x0800))
+ {
+ // 8 bit immediate (relative) offset
+ branchOffset = (INT8)BITS(OP,0x00ff) ;
+
+ // "The PC Contains the address of the next instruction"
+ PC += 1 ;
+ }
+ else if (BITS(OP,0x0010))
+ {
+ // 16 bit immediate (relative) offset
+ retSize = 666 ;
+ }
+ else if (!BITS(OP,0x0010))
+ {
+ // 16 bit Rx offset
+ retSize = 666 ;
+ }
+
+ dsp56k.ppc = PC ;
+ PC += branchOffset ;
+
+ change_pc(PC) ;
+
+ return retSize ;
+}
+
+
+static int DoOperation(void)
+{
+ int retSize = 0 ;
+
+ UINT16 offset ;
+
+ // First instruction cycle
+ SP++ ;
+ SSH = LA ;
+ SSL = LC ;
+
+ if (BITS(OP,0x0800))
+ {
+ // #xx,expr
+ LC = BITS(OP,0x00ff) ;
+ retSize = 2 ;
+ }
+ else if (BITS(OP,0x0400))
+ {
+ // S,expr
+ unsigned char sdt = 0x00 ;
+ void *SD ;
+
+ // !!! Watch out for the special cases (FamilyManual page 276) !!!
+ SD = DecodeDDDDDTable(BITS(OP,0x001f), &sdt) ;
+ SetDestinationValue(SD, sdt, &LC, DT_WORD) ;
+ retSize = 2 ;
+ }
+ else
+ {
+ // X:(Rn),expr
+ retSize = 666 ;
+ }
+
+
+ // Second instruction cycle
+ SP++ ;
+ SSH = PC+2 ; // The value in the Program Counter (PC) register pushed onto the system stack is the address of the first instruction following the DO instruction
+ SSL = SR ;
+
+ offset = 0x00 ; // The offset is the same for all DO instructions...
+ offset = (ROPCODE((PC<<1)+2)) ;
+ offset += PC+2 ;
+ LA = offset ;
+
+
+ // Third instruction cycle
+ SET_lfBIT() ;
+
+ return retSize ;
+}
+
+static void EndOfLoopProcessing(void)
+{
+ SR = SSL ;
+ SP-- ;
+ LA = SSH ;
+ LC = SSL ;
+ SP-- ;
+}
+
+static int Dec24Operation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ UINT64 decMe ;
+
+ unsigned char drt = 0x00 ;
+ void *D = 0x00 ;
+ D = DecodeFTable(BITS(OP,0x0008), &drt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value
+
+ // !! I wonder if this should be a signed int instead !!
+ decMe = (*((UINT64*)D) & (UINT64)U64(0xffffff0000)) >> 16 ;
+ decMe-- ;
+ decMe &= (UINT64)U64(0x0000000000ffffff) ; // For wraparound - Make sure no bits get set improperly in A/B
+
+// UINT8 carryBit = (*((UINT64*)D) & 0x0000008000000000) >> 39 ; // For determinating carry status...
+
+ *((UINT64*)D) &= (UINT64)U64(0x000000000000ffff) ; // Prepare the destination to be set...
+ *((UINT64*)D) |= (decMe << 16) ; // Set the top 24 bits accordingly...
+
+ // Carry flag (C) - HACK
+// if (decMe == 0x0000000000ff7fff)
+// SET_cBIT() ;
+// else
+// CLEAR_cBIT() ;
+
+ // Carry flag (C)
+// UINT8 postCarryBit = (*((UINT64*)D) & 0x0000008000000000) >> 39 ;
+// if (postCarryBit != carryBit) SET_cBIT() ;
+// else CLEAR_cBIT() ;
+
+ *wd = D ;
+
+/*
+ UINT32 decMe = ((*((PAIR64*)D)).b.h4 << 16) | (*((PAIR64*)D)).w.h ;
+
+ int fflag = 0 ;
+ if (decMe == 0x00007fff) fflag = 1 ;
+
+ if (fflag) mame_printf_debug("%08x\n", decMe) ;
+
+ decMe-- ;
+
+ if (fflag) mame_printf_debug("%08x\n", decMe) ;
+
+ decMe &= 0x00ffffff ;
+
+ if (fflag) mame_printf_debug("%08x\n", decMe) ;
+
+ UINT8 carryBit = ((*((PAIR64*)D)).b.h4 & 0x80) >> 7 ;
+
+ (*((PAIR64*)D)).b.h4 = (decMe & 0x00ff0000) >> 16 ;
+ (*((PAIR64*)D)).w.h = (decMe & 0x0000ffff) ;
+
+ if (fflag) mame_printf_debug("%2x\n", (*((PAIR64*)D)).b.h4) ;
+ if (fflag) mame_printf_debug("%4x\n", (*((PAIR64*)D)).w.h) ;
+
+ // Carry flag (C)
+ UINT8 postCarryBit = ((*((PAIR64*)D)).b.h4 & 0x80) >> 7 ;
+ if (postCarryBit != carryBit) SET_cBIT() ;
+ else CLEAR_cBIT() ;
+
+ *wd = D ;
+*/
+ return retSize ;
+}
+
+static int AddOperation(void **wd, UINT64 *pa)
+{
+ UINT64 addVal = 0x00;
+
+ unsigned char st = 0x00, dt = 0x00 ;
+ void *S = 0x00, *D = 0x00;
+
+ DecodeJJJFTable(BITS(OP,0x0007),BITS(OP,0x0008), &S, &st, &D, &dt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value
+
+ switch(st)
+ {
+ case DT_WORD: addVal = (UINT64)*((UINT16*)S) << 16 ; break ;
+ case DT_DOUBLE_WORD: addVal = (UINT64)*((UINT32*)S) ; break ;
+ case DT_LONG_WORD: addVal = (UINT64)*((UINT64*)S) ; break ;
+ }
+
+ *((UINT64*)D) += addVal ;
+
+ *wd = D ;
+
+ return 1 ;
+}
+
+static int LsrOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ UINT16 result ;
+
+ unsigned char dt = 0x00 ;
+ void *D = 0x00 ;
+
+ D = DecodeFTable(BITS(OP,0x0008), &dt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value
+
+ // !!! Make sure to hold the MS bit and shift the LS bit properly !!!
+
+ result = (*((PAIR64*)D)).w.h >> 1 ;
+ (*((PAIR64*)D)).w.h = result ;
+
+ *wd = D ;
+ return retSize ;
+}
+
+static int AsrOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ unsigned char dt = 0x00 ;
+ void *D = 0x00 ;
+
+ D = DecodeFTable(BITS(OP,0x0008), &dt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value
+
+ // !!! Make sure to hold the MS bit and shift the LS bit properly !!!
+
+ *((UINT64*)D) = (*((UINT64*)D)) >> 1 ;
+
+ *wd = D ;
+ return retSize ;
+}
+
+static int NotOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ unsigned char dt = 0x00 ;
+ void *D = 0x00 ;
+
+ D = DecodeFTable(BITS(OP,0x0008), &dt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value
+
+ (*((PAIR64*)D)).w.h ^= 0xffff ;
+
+ *wd = D ;
+ return retSize ;
+}
+
+
+static int EorOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ UINT16 result ;
+
+ unsigned char st = 0x00, dt = 0x00 ;
+ void *S = 0x00, *D = 0x00;
+
+ DecodeJJFTable(BITS(OP,0x0003),BITS(OP,0x0008), &S, &st, &D, &dt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value
+
+ // This operation does an XOR of a word of S with A1/B1...
+ result = *((UINT16*)S) ^ (*((PAIR64*)D)).w.h ;
+ (*((PAIR64*)D)).w.h = result ;
+
+ *wd = D ;
+ return retSize ;
+}
+
+static int TfrDataALUOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ unsigned char st = 0x00, dt = 0x00 ;
+ void *S = 0x00, *D = 0x00;
+
+ DecodeJJJFTable(BITS(OP,0x0007),BITS(OP,0x0008), &S, &st, &D, &dt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value
+
+ SetDestinationValue(S, st, D, dt) ;
+
+ *wd = D ;
+ return retSize ;
+}
+
+static int AndOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ UINT16 result ;
+
+ unsigned char st = 0x00, dt = 0x00 ;
+ void *S = 0x00, *D = 0x00;
+
+ DecodeJJFTable(BITS(OP,0x0003),BITS(OP,0x0008), &S, &st, &D, &dt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value
+
+ // This operation does an AND of a word of S with A1/B1...
+ result = *((UINT16*)S) & (*((PAIR64*)D)).w.h ;
+ (*((PAIR64*)D)).w.h = result ;
+
+ *wd = D ;
+ return retSize ;
+}
+
+static int OrOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ UINT16 result ;
+
+ unsigned char st = 0x00, dt = 0x00 ;
+ void *S = 0x00, *D = 0x00;
+
+ DecodeJJFTable(BITS(OP,0x0003),BITS(OP,0x0008), &S, &st, &D, &dt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value
+
+ // This operation does an OR of a word of S with A1/B1...
+ result = *((UINT16*)S) | (*((PAIR64*)D)).w.h ;
+ (*((PAIR64*)D)).w.h = result ;
+
+ *wd = D ;
+ return retSize ;
+}
+
+
+static int TccOperation(void)
+{
+ int retSize = 1 ;
+
+ int transfer = DecodeccccTable(BITS(OP,0x03c0)) ;
+
+ // !!! WARNING === TESTING !!!
+ // transfer = 1 ;
+
+ if (transfer)
+ {
+ unsigned char st = 0x00, dt = 0x00 ;
+ void *S = 0x00, *D = 0x00;
+
+ unsigned char drt = 0x00 ;
+ void *destinationReg = 0x00 ;
+
+ Decodeh0hFTable(BITS(OP,0x0007),BITS(OP,0x0008), &S, &st, &D, &dt) ;
+
+ SetDestinationValue(S, st, D, dt) ;
+
+ // !!! What's up with that A,A* thing in the docs? Does that mean "do not transfer R0 to Rn ???
+ destinationReg = DecodeRRTable(BITS(OP,0x0030), &drt) ; // Actually a TT table, but it's the same
+
+ SetDestinationValue(&R0, DT_WORD, destinationReg, drt) ;
+ }
+
+ // Otherwise it's a NOP
+
+ return retSize ;
+}
+
+static int ClrOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ UINT64 clearValue = 0 ;
+
+ unsigned char drt = 0x00 ;
+ void *destinationReg = 0x00 ;
+
+ destinationReg = DecodeFTable(BITS(OP,0x0008), &drt) ;
+
+ *pa = *((UINT64*)destinationReg) ; // backup the previous value
+
+ SetDestinationValue(&clearValue, DT_LONG_WORD, destinationReg, drt) ;
+
+ *wd = destinationReg ;
+ return retSize ;
+}
+
+static int TstOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ unsigned char drt = 0x00 ;
+ void *destinationReg = 0x00 ;
+ destinationReg = DecodeFTable(BITS(OP,0x0008), &drt) ;
+
+ // S - "computed according to the standard definition (section A.4)"
+ // L - can't be done until after data move
+ // E - set if signed integer portion is in use
+ // U - set according to the standard definition of the U bit
+ // N - set if bit 39 is set
+ if (*((UINT64*)destinationReg) & (UINT64)U64(0x8000000000)) SET_nBIT();
+ else CLEAR_nBIT();
+
+ // Z - set if == 0
+ if (*((UINT64*)destinationReg) == 0) SET_zBIT();
+ else CLEAR_zBIT();
+
+ // V&C - always cleared
+ CLEAR_vBIT();
+ CLEAR_cBIT();
+
+ *pa = *((UINT64*)destinationReg) ; // backup the previous value (no change here)
+ *wd = destinationReg;
+
+ return retSize ;
+}
+
+static int AndiOperation(void)
+{
+ int retSize = 1 ;
+
+ UINT16 andMe = BITS(OP,0x00ff) ;
+
+ // Because I don't have a good way to access MR and CCR right now, i'm going to
+ // hard-code decoding EE here and in the OriOperation as well...
+ switch(BITS(OP,0x0600))
+ {
+ // MR
+ case 0x01:
+ SR &= ((andMe << 8) | 0x00ff) ;
+ break ;
+
+ // CCR
+ case 0x03:
+ SR &= ((andMe) | 0xff00) ;
+ break ;
+
+ // OMR
+ case 0x02:
+ OMR &= (UINT8)(andMe) ;
+ break ;
+
+ default:
+ fatalerror("DSP56k - BAD EE value in andi operation") ;
+ }
+
+
+ return retSize ;
+}
+
+#ifdef UNUSED_FUNCTION
+// !!! NOT IMPLEMENTED YET - JUST PUT HERE TO BE NEXT TO ANDI SOMEDAY !!!
+static int OriOperation(void)
+{
+ int retSize = 1 ;
+
+ return retSize ;
+}
+#endif
+
+static int CmpOperation(void **wd, UINT64 *pa)
+{
+ int retSize = 1 ;
+
+ UINT64 cmpVal ;
+ UINT64 result ;
+
+ unsigned char st = 0x00, dt = 0x00 ;
+ void *S = 0x00, *D = 0x00;
+
+ DecodeJJJFTable(BITS(OP,0x0007),BITS(OP,0x0008), &S, &st, &D, &dt) ;
+
+ *pa = *((UINT64*)D) ; // backup the previous value - not necessary for cmp :)
+
+ switch(st)
+ {
+ default:
+ case DT_WORD: cmpVal = (UINT64)*((UINT16*)S) ; break ;
+ case DT_DOUBLE_WORD: cmpVal = (UINT64)*((UINT32*)S) ; break ;
+ case DT_LONG_WORD: cmpVal = (UINT64)*((UINT64*)S) ; break ;
+ }
+
+ result = *((UINT64*)D) - cmpVal ;
+
+ if (result == 0)
+ SET_zBIT() ;
+ else
+ CLEAR_zBIT() ;
+
+ *wd = D ;
+ return retSize ;
+}
+
+static int BsccOperation(void)
+{
+ int retSize = 0 ;
+
+ // Decode the condition
+ int transfer = DecodeccccTable(BITS(OP,0x000f)) ;
+
+ // TESTING !!!
+ // transfer = 0 ;
+
+ // 1 or 2 word operation...
+ if (transfer)
+ {
+ if (BITS(OP,0x0010))
+ {
+ // 2 word immediate offset...
+ INT16 branchOffset = (INT16)ROPCODE((PC<<1)+2) ;
+
+ // "The PC Contains the address of the next instruction"
+ PC += 2 ;
+ dsp56k.ppc = PC ;
+
+ SP++ ;
+ SSH = PC ;
+ SSL = SR ;
+
+ PC += branchOffset ;
+
+ change_pc(PC) ;
+ }
+ else
+ {
+ // 1 word Rx offset...
+ }
+
+ retSize = 0 ;
+ }
+ else
+ {
+ if (BITS(OP,0x0010))
+ retSize = 2 ;
+ else
+ retSize = 1 ;
+ }
+
+ return retSize ;
+}
+
+static int BccOperation(void)
+{
+ int retSize = 0 ;
+
+ if (!BITS(OP,0x2000))
+ {
+ int branch = DecodeccccTable(BITS(OP,0x000f)) ;
+
+ if (branch)
+ {
+ if (BITS(OP,0x0010))
+ {
+ // B.cc xxxx
+ INT16 op2 = ROPCODE((PC<<1)+2) ;
+
+ // The PC contains the address of the next instruction
+ PC += 2 ;
+ dsp56k.ppc = PC ;
+ PC += op2 ;
+
+ change_pc(PC) ;
+ }
+ else
+ {
+ // B.cc Rn
+ }
+ }
+ else
+ {
+ if (BITS(OP,0x0010))
+ retSize = 2 ;
+ else
+ retSize = 1 ;
+ }
+ }
+ else
+ {
+ // B.cc aa
+ int branch = DecodeccccTable(BITS(OP,0x03c0)) ;
+
+ if (branch)
+ {
+ INT16 offset = (INT16)AssembleAddressFrom6BitSignedRelativeShortAddress(BITS(OP,0x003f)) ;
+
+ PC += 1 ;
+ dsp56k.ppc = PC ;
+ PC += offset ;
+
+ change_pc(PC) ;
+ }
+ else
+ {
+ retSize = 1 ;
+ }
+ }
+
+ return retSize ;
+}
+
+static int Tst2Operation(void)
+{
+ int retSize = 1 ;
+
+ unsigned char dt = 0x00 ;
+ void *destinationReg = 0x00 ;
+
+ destinationReg = DecodeDDTable(BITS(OP,0x0003), &dt) ;
+
+ // unnormalized
+
+ // negative
+ // bit 31 of A or B ???
+
+ // zero
+ if ( (*((UINT16*)destinationReg)) == 0)
+ SET_zBIT() ;
+ else
+ CLEAR_zBIT() ;
+
+ // always clear C flag
+ CLEAR_cBIT() ;
+
+ return retSize ;
+}
+
+static int MACsuuuOperation(void)
+{
+ int retSize = 1 ;
+
+ INT64 result = 0 ;
+
+ int s ;
+ void *S1 = 0x00, *S2 = 0x00, *D = 0x00 ;
+
+ DecodeQQFTableSp(BITS(OP,0x0003), BITS(OP,0x0008), &S1, &S2, &D) ;
+
+ s = BITS(OP,0x0004) ;
+
+ // !!! There is no way this is right - wtf is EXT:MSP:LSP format ???
+ if (!s)
+ {
+ // su
+ result = ( (INT32)(*((UINT16*)S1)) * (UINT32)(*((UINT16*)S2)) ) << 1 ;
+ }
+ else
+ {
+ // uu
+ result = ( (UINT32)(*((UINT16*)S1)) * (UINT32)(*((UINT16*)S2)) ) << 1 ;
+ }
+
+ (*((UINT64*)D)) += result ;
+
+ return retSize ;
+}
+
+static int RepOperation(void)
+{
+ int retSize = 1 ;
+
+ UINT16 count = 0x0000 ;
+
+ if (BITS(OP,0x0f00) == 0xf)
+ {
+ // immediate
+ count = BITS(OP,0x00ff) ;
+ }
+ else if (BITS(OP,0x0f00) == 0x4)
+ {
+ // SD
+ unsigned char st = 0x00 ;
+ void *S ;
+
+ S = DecodeDDDDDTable(BITS(OP,0x001f), &st) ;
+ SetDestinationValue(S, st, &count, DT_WORD);
+ }
+ else
+ {
+ // X:(Rn)
+ }
+
+ TEMP = LC ;
+ LC = count ;
+
+ dsp56k.repFlag = 1 ;
+ dsp56k.repAddr = PC + (retSize<<1) ;
+
+ return retSize ;
+}
+
+static void EndOfRepProcessing(void)
+{
+ LC = TEMP ;
+
+ dsp56k.repFlag = 0 ;
+ dsp56k.repAddr = 0x0000 ;
+}
+
+
+/*
+DECODERS
+*/
+static void *DecodeDDDDDTable(UINT16 DDDDD, unsigned char *dt)
+{
+ void *retAddress = 0x00 ;
+
+ switch(DDDDD)
+ {
+ case 0x00: retAddress = &X0 ; *dt = DT_WORD ; break ;
+ case 0x01: retAddress = &Y0 ; *dt = DT_WORD ; break ;
+ case 0x02: retAddress = &X1 ; *dt = DT_WORD ; break ;
+ case 0x03: retAddress = &Y1 ; *dt = DT_WORD ; break ;
+ case 0x04: retAddress = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x05: retAddress = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x06: retAddress = &A0 ; *dt = DT_WORD ; break ;
+ case 0x07: retAddress = &B0 ; *dt = DT_WORD ; break ;
+ case 0x08: retAddress = &LC ; *dt = DT_WORD ; break ;
+ case 0x09: retAddress = &SR ; *dt = DT_WORD ; break ;
+ case 0x0a: retAddress = &OMR ; *dt = DT_BYTE ; break ;
+ case 0x0b: retAddress = &SP ; *dt = DT_BYTE ; break ;
+ case 0x0c: retAddress = &A1 ; *dt = DT_WORD ; break ;
+ case 0x0d: retAddress = &B1 ; *dt = DT_WORD ; break ;
+ case 0x0e: retAddress = &A2 ; *dt = DT_BYTE ; break ;
+ case 0x0f: retAddress = &B2 ; *dt = DT_BYTE ; break ;
+
+ case 0x10: retAddress = &R0 ; *dt = DT_WORD ; break ;
+ case 0x11: retAddress = &R1 ; *dt = DT_WORD ; break ;
+ case 0x12: retAddress = &R2 ; *dt = DT_WORD ; break ;
+ case 0x13: retAddress = &R3 ; *dt = DT_WORD ; break ;
+ case 0x14: retAddress = &M0 ; *dt = DT_WORD ; break ;
+ case 0x15: retAddress = &M1 ; *dt = DT_WORD ; break ;
+ case 0x16: retAddress = &M2 ; *dt = DT_WORD ; break ;
+ case 0x17: retAddress = &M3 ; *dt = DT_WORD ; break ;
+ case 0x18: retAddress = &SSH ; *dt = DT_WORD ; break ;
+ case 0x19: retAddress = &SSL ; *dt = DT_WORD ; break ;
+ case 0x1a: retAddress = &LA ; *dt = DT_WORD ; break ;
+ //no 0x1b
+ case 0x1c: retAddress = &N0 ; *dt = DT_WORD ; break ;
+ case 0x1d: retAddress = &N1 ; *dt = DT_WORD ; break ;
+ case 0x1e: retAddress = &N2 ; *dt = DT_WORD ; break ;
+ case 0x1f: retAddress = &N3 ; *dt = DT_WORD ; break ;
+ }
+
+ return retAddress ;
+}
+
+static void *DecodeRRTable(UINT16 RR, unsigned char *dt)
+{
+ void *retAddress = 0x00 ;
+
+ switch(RR)
+ {
+ case 0x00: retAddress = &R0 ; *dt = DT_WORD ; break ;
+ case 0x01: retAddress = &R1 ; *dt = DT_WORD ; break ;
+ case 0x02: retAddress = &R2 ; *dt = DT_WORD ; break ;
+ case 0x03: retAddress = &R3 ; *dt = DT_WORD ; break ;
+ }
+
+ return retAddress ;
+}
+
+static void *DecodeDDTable(UINT16 DD, unsigned char *dt)
+{
+ void *retAddress = 0x00 ;
+
+ switch(DD)
+ {
+ case 0x00: retAddress = &X0 ; *dt = DT_WORD ; break ;
+ case 0x01: retAddress = &Y0 ; *dt = DT_WORD ; break ;
+ case 0x02: retAddress = &X1 ; *dt = DT_WORD ; break ;
+ case 0x03: retAddress = &Y1 ; *dt = DT_WORD ; break ;
+ }
+
+ return retAddress ;
+}
+
+static void *DecodeHHHTable(UINT16 HHH, unsigned char *dt)
+{
+ void *retAddress = 0x00 ;
+
+ switch(HHH)
+ {
+ case 0x0: retAddress = &X0 ; *dt = DT_WORD ; break ;
+ case 0x1: retAddress = &Y0 ; *dt = DT_WORD ; break ;
+ case 0x2: retAddress = &X1 ; *dt = DT_WORD ; break ;
+ case 0x3: retAddress = &Y1 ; *dt = DT_WORD ; break ;
+ case 0x4: retAddress = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x5: retAddress = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x6: retAddress = &A0 ; *dt = DT_WORD ; break ;
+ case 0x7: retAddress = &B0 ; *dt = DT_WORD ; break ;
+ }
+
+ return retAddress ;
+}
+
+static void *DecodeHHTable(UINT16 HH, unsigned char *dt)
+{
+ void *retAddress = 0x00 ;
+
+ switch(HH)
+ {
+ case 0x0: retAddress = &X0 ; *dt = DT_WORD ; break ;
+ case 0x1: retAddress = &Y0 ; *dt = DT_WORD ; break ;
+ case 0x2: retAddress = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x3: retAddress = &B ; *dt = DT_LONG_WORD ; break ;
+ }
+
+ return retAddress ;
+}
+
+static void *DecodeZTable(UINT16 Z, unsigned char *dt)
+{
+ void *retAddress = 0x00 ;
+
+ switch(Z)
+ {
+ // Fixed as per the Family Manual addendum
+ case 0x01: retAddress = &A1 ; *dt = DT_WORD ; break ;
+ case 0x00: retAddress = &B1 ; *dt = DT_WORD ; break ;
+ }
+
+ return retAddress ;
+}
+
+
+static UINT16 DecodeBBBBitMask(UINT16 BBB, UINT16 *iVal)
+{
+ UINT16 retVal = 0x00 ;
+
+ switch(BBB)
+ {
+ case 0x4: retVal = 0xff00 ; *iVal <<= 8 ; break ;
+ case 0x2: retVal = 0x0ff0 ; *iVal <<= 4 ; break ;
+ case 0x1: retVal = 0x00ff ; *iVal <<= 0 ; break ;
+ }
+
+ return retVal ;
+}
+
+static void ExecuteMMTable(int x, UINT16 MM)
+{
+ UINT16 *rX = 0x00 ;
+ UINT16 *nX = 0x00 ;
+
+ switch(x)
+ {
+ case 0x0: rX = &R0 ; nX = &N0 ; break ;
+ case 0x1: rX = &R1 ; nX = &N1 ; break ;
+ case 0x2: rX = &R2 ; nX = &N2 ; break ;
+ case 0x3: rX = &R3 ; nX = &N3 ; break ;
+ }
+
+ switch(MM)
+ {
+ case 0x0: /* do nothing */ break ;
+ case 0x1: (*rX)++ ; break ;
+ case 0x2: (*rX)-- ; break ;
+ case 0x3: (*rX) = (*rX)+(*nX) ; break ;
+ }
+}
+
+static void ExecutemTable(int x, UINT16 m)
+{
+ UINT16 *rX = 0x00 ;
+ UINT16 *nX = 0x00 ;
+
+ switch(x)
+ {
+ case 0x0: rX = &R0 ; nX = &N0 ; break ;
+ case 0x1: rX = &R1 ; nX = &N1 ; break ;
+ case 0x2: rX = &R2 ; nX = &N2 ; break ;
+ case 0x3: rX = &R3 ; nX = &N3 ; break ;
+ }
+
+ switch(m)
+ {
+ case 0x0: (*rX)++ ; break ;
+ case 0x1: (*rX) = (*rX)+(*nX) ; break ;
+ }
+}
+
+static void ExecutezTable(int x, UINT16 z)
+{
+ UINT16 *rX = 0x00 ;
+ UINT16 *nX = 0x00 ;
+
+ switch(x)
+ {
+ case 0x0: rX = &R0 ; nX = &N0 ; break ;
+ case 0x1: rX = &R1 ; nX = &N1 ; break ;
+ case 0x2: rX = &R2 ; nX = &N2 ; break ;
+ case 0x3: rX = &R3 ; nX = &N3 ; break ;
+ }
+
+ if (!z)
+ {
+ (*rX)-- ;
+ }
+ else
+ {
+ (*rX) = (*rX)+(*nX) ;
+ }
+}
+
+// Returns R address
+static UINT16 ExecuteqTable(int x, UINT16 q)
+{
+ UINT16 *rX = 0x00 ;
+ UINT16 *nX = 0x00 ;
+
+ switch(x)
+ {
+ case 0x0: rX = &R0 ; nX = &N0 ; break ;
+ case 0x1: rX = &R1 ; nX = &N1 ; break ;
+ case 0x2: rX = &R2 ; nX = &N2 ; break ;
+ case 0x3: rX = &R3 ; nX = &N3 ; break ;
+ }
+
+ switch(q)
+ {
+ case 0x0: /* No permanent changes */ ; return (*rX)+(*nX); break;
+ case 0x1: (*rX)--; return (*rX); break; // This one is special - it's a *PRE-decrement*!
+ }
+
+ exit(1);
+ return 0x00;
+}
+
+static UINT16 AssembleDFromPTable(UINT16 P, UINT16 ppppp)
+{
+ UINT16 destAddr = 0x00 ;
+
+ switch (P)
+ {
+ case 0x0: destAddr = ppppp ; break ;
+ case 0x1: destAddr = AssembleAddressFromIOShortAddress(ppppp) ; break ;
+ }
+
+ return destAddr ;
+}
+
+
+static UINT16 AssembleAddressFromIOShortAddress(UINT16 pp)
+{
+ UINT16 fullAddy = 0xffe0 ;
+ fullAddy |= pp ;
+ return fullAddy ;
+}
+
+static UINT16 AssembleAddressFrom6BitSignedRelativeShortAddress(UINT16 srs)
+{
+ UINT16 fullAddy = srs ;
+ if (fullAddy & 0x0020) fullAddy |= 0xffc0 ;
+
+ return fullAddy ;
+}
+
+static int DecodeccccTable(UINT16 cccc)
+{
+ int retVal = 0 ;
+
+ // !!! go back and check me again someday - potential bugs !!!
+ switch (cccc)
+ {
+ // Arranged according to mnemonic table - not decoding table...
+ case 0x0: if( cBIT == 0) retVal = 1 ; break ; // cc(hs)
+ case 0x8: if( cBIT == 1) retVal = 1 ; break ; // cs(lo)
+ case 0x5: if( eBIT == 0) retVal = 1 ; break ; // ec
+ case 0xa: if( zBIT == 1) retVal = 1 ; break ; // eq
+ case 0xd: if( eBIT == 1) retVal = 1 ; break ; // es
+ case 0x1: if((nBIT ^ vBIT) == 0) retVal = 1 ; break ; // ge
+ case 0x7: if((zBIT + (nBIT ^ vBIT)) == 0) retVal = 1 ; break ; // gt
+ case 0x6: if( lBIT == 0) retVal = 1 ; break ; // lc
+ case 0xf: if((zBIT + (nBIT ^ vBIT)) == 1) retVal = 1 ; break ; // le
+ case 0xe: if( lBIT == 1) retVal = 1 ; break ; // ls
+ case 0x9: if((nBIT ^ vBIT) == 1) retVal = 1 ; break ; // lt
+ case 0xb: if( nBIT == 1) retVal = 1 ; break ; // mi
+ case 0x2: if( zBIT == 0) retVal = 1 ; break ; // ne
+ case 0xc: if((zBIT + ((!uBIT) & (!eBIT))) == 1) retVal = 1 ; break ; // nr
+ case 0x3: if( nBIT == 0) retVal = 1 ; break ; // pl
+ case 0x4: if((zBIT + ((!uBIT) & (!eBIT))) == 0) retVal = 1 ; break ; // nn
+ }
+
+ return retVal ;
+}
+
+static void Decodeh0hFTable(UINT16 h0h, UINT16 F,
+ void **source, unsigned char *st,
+ void **dest, unsigned char *dt)
+{
+ UINT16 switchVal = (h0h << 1) | F ;
+
+ switch (switchVal)
+ {
+ case 0x8: *source = &X0 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x9: *source = &X0 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0xa: *source = &Y0 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0xb: *source = &Y0 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x2: *source = &A ; *st = DT_LONG_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x1: *source = &A ; *st = DT_LONG_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x0: *source = &B ; *st = DT_LONG_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x3: *source = &B ; *st = DT_LONG_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ }
+}
+
+static void *DecodeFTable(UINT16 F, unsigned char *dt)
+{
+ void *retAddress = 0x00 ;
+
+ switch(F)
+ {
+ case 0x0: retAddress = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x1: retAddress = &B ; *dt = DT_LONG_WORD ; break ;
+ }
+
+ return retAddress ;
+}
+
+static void DecodeJJJFTable(UINT16 JJJ, UINT16 F,
+ void **source, unsigned char *st,
+ void **dest, unsigned char *dt)
+{
+ UINT16 switchVal = (JJJ << 1) | F ;
+
+ switch(switchVal)
+ {
+ case 0x0: *source = &B ; *st = DT_LONG_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x1: *source = &A ; *st = DT_LONG_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x4: *source = &X ; *st = DT_DOUBLE_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x5: *source = &X ; *st = DT_DOUBLE_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x6: *source = &Y ; *st = DT_DOUBLE_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x7: *source = &Y ; *st = DT_DOUBLE_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x8: *source = &X0 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x9: *source = &X0 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0xa: *source = &Y0 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0xb: *source = &Y0 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0xc: *source = &X1 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0xd: *source = &X1 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0xe: *source = &Y1 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0xf: *source = &Y1 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ }
+}
+
+static void DecodeJJFTable(UINT16 JJ, UINT16 F,
+ void **source, unsigned char *st,
+ void **dest, unsigned char *dt)
+{
+ UINT16 switchVal = (JJ << 1) | F ;
+
+ switch (switchVal)
+ {
+ case 0x0: *source = &X0 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x1: *source = &X0 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x2: *source = &Y0 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x3: *source = &Y0 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x4: *source = &X1 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x5: *source = &X1 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ case 0x6: *source = &Y1 ; *st = DT_WORD ; *dest = &A ; *dt = DT_LONG_WORD ; break ;
+ case 0x7: *source = &Y1 ; *st = DT_WORD ; *dest = &B ; *dt = DT_LONG_WORD ; break ;
+ }
+}
+
+// Types not necessary - we know what we are...
+static void DecodeQQFTableSp(UINT16 QQ, UINT16 F, void **S1, void **S2, void **D)
+{
+ UINT16 switchVal = (QQ << 1) | F ;
+
+ switch(switchVal)
+ {
+ case 0x0: *S1 = &Y0 ; *S2 = &X0 ; *D = &A ; break ;
+ case 0x1: *S1 = &Y0 ; *S2 = &X0 ; *D = &B ; break ;
+ case 0x2: *S1 = &Y1 ; *S2 = &X0 ; *D = &A ; break ;
+ case 0x3: *S1 = &Y1 ; *S2 = &X0 ; *D = &B ; break ;
+ case 0x4: *S1 = &X1 ; *S2 = &Y0 ; *D = &A ; break ;
+ case 0x5: *S1 = &X1 ; *S2 = &Y0 ; *D = &B ; break ;
+ case 0x6: *S1 = &X1 ; *S2 = &Y1 ; *D = &A ; break ;
+ case 0x7: *S1 = &X1 ; *S2 = &Y1 ; *D = &B ; break ;
+ }
+}
+
+static void DecodeIIIITable(UINT16 IIII,
+ void **source, unsigned char *st,
+ void **dest, unsigned char *dt,
+ void *working)
+{
+ void *opposite = 0x00 ;
+
+ if (working == &A) opposite = &B ;
+ else opposite = &A ;
+
+ switch(IIII)
+ {
+ case 0x0: *source = &X0 ; *st = DT_WORD ; *dest = opposite ; *dt = DT_LONG_WORD ; break ;
+ case 0x1: *source = &Y0 ; *st = DT_WORD ; *dest = opposite ; *dt = DT_LONG_WORD ; break ;
+ case 0x2: *source = &X1 ; *st = DT_WORD ; *dest = opposite ; *dt = DT_LONG_WORD ; break ;
+ case 0x3: *source = &Y1 ; *st = DT_WORD ; *dest = opposite ; *dt = DT_LONG_WORD ; break ;
+ case 0x4: *source = &A ; *st = DT_LONG_WORD ; *dest = &X0 ; *dt = DT_WORD ; break ;
+ case 0x5: *source = &B ; *st = DT_LONG_WORD ; *dest = &Y0 ; *dt = DT_WORD ; break ;
+ case 0x6: *source = &A0 ; *st = DT_WORD ; *dest = &X0 ; *dt = DT_WORD ; break ;
+ case 0x7: *source = &B0 ; *st = DT_WORD ; *dest = &Y0 ; *dt = DT_WORD ; break ;
+ case 0x8: *source = working ; *st = DT_LONG_WORD ; *dest = opposite ; *dt = DT_LONG_WORD ; break ;
+ case 0x9: *source = working ; *st = DT_LONG_WORD ; *dest = opposite ; *dt = DT_LONG_WORD ; break ;
+ case 0xc: *source = &A ; *st = DT_LONG_WORD ; *dest = &X1 ; *dt = DT_WORD ; break ;
+ case 0xd: *source = &B ; *st = DT_LONG_WORD ; *dest = &Y1 ; *dt = DT_WORD ; break ;
+ case 0xe: *source = &A0 ; *st = DT_WORD ; *dest = &X1 ; *dt = DT_WORD ; break ;
+ case 0xf: *source = &B0 ; *st = DT_WORD ; *dest = &Y1 ; *dt = DT_WORD ; break ;
+ }
+}
+
+/*
+MEMORY OPS
+*/
+
+static void XMDMOperation(UINT16 parameters, void *working, UINT64 *pa)
+{
+ UINT16 W ;
+ unsigned char rdt = 0x00 ;
+ void *R = 0x00 ;
+
+ unsigned char sdt = 0x00 ;
+ void *SD = 0x00 ;
+
+ // Get the source
+ SD = DecodeHHHTable(BITS(parameters,0x000e), &sdt) ;
+
+ // Get the destination
+ R = DecodeRRTable(BITS(parameters,0x0030), &rdt) ;
+
+ // Move the data
+ W = BITS(parameters,0x0001) ;
+
+ if (W)
+ {
+ // from X:<ea> to SD...
+ // !!! TODO : Fill in similar comments for other "if (W)'s" !!!
+ UINT16 data = data_read_word_16le((*((UINT16*)R))<<1) ; // read the word out
+ SetDestinationValue(&data, DT_WORD, SD, sdt) ;
+ }
+ else
+ {
+ // from SD to X:<ea>...
+
+ // If the source is the same as the ALU destination, use the Previous Accumulator value
+ if (working == SD)
+ {
+ // the value before the ALU operation was executed...
+ SetDataMemoryValue(pa, DT_LONG_WORD, (*((UINT16*)R))<<1) ;
+ }
+ else
+ {
+ // Expected memory move
+ SetDataMemoryValue(SD, sdt, (*((UINT16*)R))<<1) ;
+ }
+ }
+
+ // Postincrement
+ ExecutemTable(BITS(parameters,0x0030), BITS(parameters,0x0040)) ;
+}
+
+static void RRDMOperation(UINT16 parameters, void *working, UINT64 *pa)
+{
+ unsigned char st = 0x00, dt = 0x00 ;
+ void *S = 0x00, *D = 0x00;
+
+ DecodeIIIITable(BITS(parameters,0x000f), &S, &st, &D, &dt, working) ;
+
+ // If the source is what we're working with, use the old value
+ if (S == working)
+ SetDestinationValue(pa, DT_LONG_WORD, D, dt) ;
+ else
+ SetDestinationValue(S, st, D, dt) ;
+}
+
+
+static void XMDMSpecialOperation(UINT16 parameters, void *working)
+{
+ UINT16 W ;
+ UINT16 *dest = 0x00 ;
+
+ // Get the source/destination
+ unsigned char sdt = 0x00 ;
+ void *SD = 0x00 ;
+ SD = DecodeHHHTable(BITS(parameters,0x000e), &sdt) ;
+
+ // Get the opposite A/B depending on what was used before
+ if (working == &A)
+ dest = &B1 ;
+ else if (working == &B)
+ dest = &A1 ;
+ else
+ {
+ mame_printf_debug("WTF MF\n") ;
+ return ;
+ }
+
+ // Move the data
+ W = BITS(parameters,0x0001) ;
+
+ if (W)
+ {
+ // from X:<ea> to SD...
+ // !!! DOES THIS WORK ???
+ UINT16 data = data_read_word_16le((*dest)<<1) ; // read the word out
+ SetDestinationValue(&data, DT_WORD, SD, sdt) ;
+ }
+ else
+ {
+ // Normal memory move
+ SetDataMemoryValue(SD, sdt, (*dest)<<1) ;
+ }
+}
+
+static void ARUOperation(UINT16 parameters)
+{
+ ExecutezTable(BITS(parameters, 0x0003), BITS(parameters, 0x0004)) ;
+}
+
+
+/*
+HELPERS
+*/
+static UINT16 Dsp56kOpMask(UINT16 cur, UINT16 mask)
+{
+ int i ;
+
+ UINT16 retVal = (cur & mask) ;
+ UINT16 temp = 0x0000 ;
+ int offsetCount = 0 ;
+
+ // Shift everything right, eliminating 'whitespace'...
+ for (i = 0; i < 16; i++)
+ {
+ if (mask & (0x1<<i)) // If mask bit is non-zero
+ {
+ temp |= (((retVal >> i) & 0x1) << offsetCount) ;
+ offsetCount++ ;
+ }
+ }
+
+ return temp ;
+}
+
+
+static void SetDestinationValue(void *sourcePointer, unsigned char sourceType,
+ void *destinationPointer, unsigned char destinationType)
+{
+ UINT64 destinationValue = 0 ;
+
+ switch(destinationType)
+ {
+ case DT_BYTE:
+ switch(sourceType)
+ {
+ case DT_BYTE: *((UINT8*)destinationPointer) = *((UINT8*) sourcePointer) ; break ;
+ case DT_WORD: *((UINT8*)destinationPointer) = *((UINT16*)sourcePointer) ; break ;
+ case DT_DOUBLE_WORD: *((UINT8*)destinationPointer) = *((UINT32*)sourcePointer) ; break ;
+ case DT_LONG_WORD: *((UINT8*)destinationPointer) = *((UINT64*)sourcePointer) ; break ;
+ }
+ break ;
+
+ case DT_WORD:
+ switch(sourceType)
+ {
+ case DT_BYTE: *((UINT16*)destinationPointer) = *((UINT8*) sourcePointer) ; break ;
+ case DT_WORD: *((UINT16*)destinationPointer) = *((UINT16*)sourcePointer) ; break ;
+ case DT_DOUBLE_WORD: *((UINT16*)destinationPointer) = *((UINT32*)sourcePointer) ; break ;
+ // !!! This one is interesting too - shifter limiter action !!!
+ case DT_LONG_WORD: *((UINT16*)destinationPointer) = *((UINT64*)sourcePointer) ; break ;
+ }
+ break ;
+
+ case DT_DOUBLE_WORD:
+ switch(sourceType)
+ {
+ case DT_BYTE: *((UINT32*)destinationPointer) = *((UINT8*) sourcePointer) ; break ;
+ case DT_WORD: *((UINT32*)destinationPointer) = *((UINT16*)sourcePointer) ; break ;
+ case DT_DOUBLE_WORD: *((UINT32*)destinationPointer) = *((UINT32*)sourcePointer) ; break ;
+ case DT_LONG_WORD: *((UINT32*)destinationPointer) = *((UINT64*)sourcePointer) ; break ;
+ }
+ break ;
+
+ case DT_LONG_WORD:
+ switch(sourceType)
+ {
+ case DT_BYTE: *((UINT64*)destinationPointer) = *((UINT8*) sourcePointer) ; break ;
+
+ // !!! sign extending works on intel, others ???
+ // !!! Need to check the shift limiter here too !!!
+ case DT_WORD: destinationValue = (*((INT16*)sourcePointer)) << 16 ; // Insure sign extending
+ destinationValue &= (UINT64)U64(0x000000ffffff0000) ;
+ *((UINT64*)destinationPointer) = destinationValue ; break ;
+
+ case DT_DOUBLE_WORD: *((UINT64*)destinationPointer) = *((UINT32*)sourcePointer) ; break ;
+ case DT_LONG_WORD: *((UINT64*)destinationPointer) = *((UINT64*)sourcePointer) ; break ;
+ }
+ break ;
+ }
+}
+
+// !! redundant functions (data and memory) can be handled with function pointers !!
+static void SetDataMemoryValue(void *sourcePointer, unsigned char sourceType, UINT32 destinationAddr)
+{
+ // mame_printf_debug("%d %x\n", sourceType, destinationAddr) ;
+
+ // I wonder if this is how this should be done???
+ switch(sourceType)
+ {
+ case DT_BYTE: data_write_word_16le(destinationAddr, (UINT16)( (*((UINT8*) sourcePointer) & 0xff) ) ) ; break ;
+ case DT_WORD: data_write_word_16le(destinationAddr, (UINT16)( (*((UINT16*)sourcePointer) & 0xffff) ) ) ; break ;
+ case DT_DOUBLE_WORD: data_write_word_16le(destinationAddr, (UINT16)( (*((UINT32*)sourcePointer) & 0x0000ffff) ) ) ; break ;
+
+ // !!! Is this universal ???
+ // !!! Forget not, yon shift-limiter !!!
+ case DT_LONG_WORD: data_write_word_16le(destinationAddr, (UINT16)( ((*((UINT64*)sourcePointer)) & (UINT64)U64(0x00000000ffff0000)) >> 16) ) ; break ;
+ }
+}
+
+static void SetProgramMemoryValue(void *sourcePointer, unsigned char sourceType, UINT32 destinationAddr)
+{
+ // I wonder if this is how this should be done???
+ switch(sourceType)
+ {
+ case DT_BYTE: program_write_word_16le(destinationAddr, (UINT16)( (*((UINT8*) sourcePointer) & 0xff) ) ) ; break ;
+ case DT_WORD: program_write_word_16le(destinationAddr, (UINT16)( (*((UINT16*)sourcePointer) & 0xffff) ) ) ; break ;
+ case DT_DOUBLE_WORD: program_write_word_16le(destinationAddr, (UINT16)( (*((UINT32*)sourcePointer) & 0x0000ffff) ) ) ; break ;
+
+ // !!! Is this universal ???
+ // !!! Forget not, yon shift-limiter !!!
+ case DT_LONG_WORD: program_write_word_16le(destinationAddr, (UINT16)( ((*((UINT64*)sourcePointer)) & (UINT64)U64(0x00000000ffff0000)) >> 16) ) ; break ;
+ }
+}
+