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.c227
1 files changed, 172 insertions, 55 deletions
diff --git a/src/emu/cpu/dsp56k/dsp56ops.c b/src/emu/cpu/dsp56k/dsp56ops.c
index b21b521bfc4..8f8efea29f0 100644
--- a/src/emu/cpu/dsp56k/dsp56ops.c
+++ b/src/emu/cpu/dsp56k/dsp56ops.c
@@ -6,14 +6,14 @@
***************************************************************************/
-// NOTES For register setting:
-// FM.3-4 : When A2 or B2 is read, the register contents occupy the low-order portion
-// (bits 7-0) of the word; the high-order portion (bits 16-8) is sign-extended. When A2 or B2
-// is written, the register receives the low-order portion of the word; the high-order portion is not used
-// : ...much more!
-// : ...shifter/limiter/overflow notes too.
-//
-//
+/* NOTES For register setting:
+ FM.3-4 : When A2 or B2 is read, the register contents occupy the low-order portion
+ (bits 7-0) of the word; the high-order portion (bits 16-8) is sign-extended. When A2 or B2
+ is written, the register receives the low-order portion of the word; the high-order portion is not used
+ : ...much more!
+ : ...shifter/limiter/overflow notes too.
+
+*/
/*
TODO:
@@ -190,6 +190,7 @@ static void decode_HHH_table(dsp56k_core* cpustate, UINT16 HHH, typed_pointer*
static void decode_IIII_table(dsp56k_core* cpustate, UINT16 IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void* working);
static void decode_JJJF_table(dsp56k_core* cpustate, UINT16 JJJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
static void decode_JJF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_JF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
static void decode_KKK_table(dsp56k_core* cpustate, UINT16 KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working);
static void decode_QQF_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D);
static void decode_QQF_special_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D);
@@ -321,7 +322,7 @@ static void execute_one(dsp56k_core* cpustate)
}
/* Now evaluate the parallel data move */
- // TODO // decode_x_memory_data_write_and_register_data_move(op, parallel_move_str, parallel_move_str2);
+ /* TODO // decode_x_memory_data_write_and_register_data_move(op, parallel_move_str, parallel_move_str2); */
logerror("DSP56k: Unemulated Dual X Memory Data And Register Data Move @ 0x%x\n", PC);
}
@@ -1088,7 +1089,7 @@ static void execute_one(dsp56k_core* cpustate)
if (size == 0x1337)
{
logerror("DSP56k: Unimplemented opcode at 0x%04x : %04x\n", PC, op);
- size = 1 ; // Just to get the debugger past the bad opcode
+ size = 1 ; /* Just to get the debugger past the bad opcode */
}
/* Must have been a good opcode */
@@ -1467,20 +1468,22 @@ static size_t dsp56k_op_inc(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* Save some data for the parallel move */
*p_accum = *((UINT64*)D.addr);
+ /* Make sure the destination is a real 40-bit value */
+ *((UINT64*)D.addr) &= U64(0x000000ffffffffff);
+
/* Increment */
*((UINT64*)D.addr) = *((UINT64*)D.addr) + 1;
- /* And out the bits that don't live in the register */
- *((UINT64*)D.addr) &= U64(0x000000ffffffffff);
-
d_register->addr = D.addr;
d_register->data_type = D.data_type;
/* S L E U N Z V C */
/* * * * * * * * * */
- /* TODO: S, L, E, U, V, C */
+ /* TODO: S, L, E, U */
if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) N_SET(); else N_CLEAR();
if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) Z_SET(); else Z_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) V_SET(); else V_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) C_SET(); else C_CLEAR();
cycles += 2; /* TODO: +mv oscillator cycles */
return 1;
@@ -1500,7 +1503,7 @@ static size_t dsp56k_op_inc24(dsp56k_core* cpustate, const UINT16 op_byte, typed
/* TODO: I wonder if workBits24 should be signed? */
workBits24 = ((*((UINT64*)D.addr)) & U64(0x000000ffffff0000)) >> 16;
workBits24++;
- workBits24 &= 0x00ffffff; /* Solves -x issues */
+ //workBits24 &= 0x00ffffff; /* Solves -x issues - TODO: huh? */
/* Set the D bits with the dec result */
*((UINT64*)D.addr) &= U64(0x000000000000ffff);
@@ -1511,9 +1514,11 @@ static size_t dsp56k_op_inc24(dsp56k_core* cpustate, const UINT16 op_byte, typed
/* S L E U N Z V C */
/* * * * * * ? * * */
- /* TODO: S, L, E, U, V, C */
+ /* TODO: S, L, E, U */
if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) N_SET(); else N_CLEAR();
if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) Z_SET(); else Z_CLEAR();
+ if ((workBits24 & 0xff000000) != 0) V_SET(); else V_CLEAR();
+ if ((workBits24 & 0xff000000) != 0) C_SET(); else C_CLEAR();
cycles += 2; /* TODO: + mv oscillator clock cycles */
return 1;
@@ -1671,6 +1676,10 @@ static size_t dsp56k_op_sub(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
if ((S.data_type == DT_WORD) && useVal & U64(0x0000000080000000))
useVal |= U64(0x000000ff00000000);
+ /* Make sure they're both real 40-bit values */
+ useVal &= U64(0x000000ffffffffff);
+ *((UINT64*)D.addr) &= U64(0x000000ffffffffff);
+
/* Operate*/
*((UINT64*)D.addr) -= useVal;
@@ -1679,9 +1688,11 @@ static size_t dsp56k_op_sub(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* S L E U N Z V C */
/* * * * * * * * * */
- /* TODO S, L, E, U, V, C */
- if (*((UINT64*)D.addr) & U64(0x0000008000000000)) N_SET(); else N_CLEAR();
- if (*((UINT64*)D.addr) == 0) Z_SET(); else Z_CLEAR();
+ /* TODO S, L, E, U */
+ if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) N_SET(); else N_CLEAR();
+ if ( *((UINT64*)D.addr) == 0) Z_SET(); else Z_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) V_SET(); else V_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) C_SET(); else C_CLEAR();
cycles += 2; /* TODO: + mv oscillator cycles */
return 1;
@@ -1740,8 +1751,11 @@ static size_t dsp56k_op_cmp(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* S L E U N Z V C */
/* * * * * * * * * */
- /* TODO: S, L, E, U, N, V, C */
- if (result == 0) Z_SET(); else Z_CLEAR();
+ /* TODO: S, L, E, U */
+ if ( result & U64(0x0000008000000000)) N_SET(); else N_CLEAR();
+ if ( result == 0) Z_SET(); else Z_CLEAR();
+ if ((result & U64(0xffffff0000000000)) != 0) V_SET(); else V_CLEAR();
+ if ((result & U64(0xffffff0000000000)) != 0) C_SET(); else C_CLEAR();
cycles += 2; /* TODO: + mv oscillator clock cycles */
@@ -1853,9 +1867,40 @@ static size_t dsp56k_op_and(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* ABS : .... .... 0111 F001 : A-18 */
static size_t dsp56k_op_abs(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
{
+ INT64 opD = 0;
+ typed_pointer D = {NULL, DT_LONG_WORD};
+
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ /* Sign extend D into a temp variable */
+ opD = *p_accum;
+ if (opD & U64(0x0000008000000000))
+ opD |= U64(0xffffff0000000000);
+ else
+ opD &= U64(0x000000ffffffffff);
+
+ /* Take the absolute value and clean up */
+ opD = abs(opD);
+ opD &= U64(0x000000ffffffffff);
+
+ /* Reassign */
+ *((UINT64*)D.addr) = opD;
+
+ /* Special overflow case */
+ if ((*p_accum) == U64(0x0000008000000000))
+ *((UINT64*)D.addr) = U64(0x0000007fffffffff);
+
/* S L E U N Z V C */
/* * * * * * * * - */
- return 0;
+ /* TODO: S, L, E, U */
+ if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) N_SET(); else N_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0x000000ffffffffff)) == 0) Z_SET(); else Z_CLEAR();
+ if ((*p_accum) == U64(0x0000008000000000)) V_SET(); else V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
}
/* ROR : .... .... 0111 F010 : A-192 */
@@ -1932,9 +1977,11 @@ static size_t dsp56k_op_cmpm(dsp56k_core* cpustate, const UINT16 op_byte, typed_
/* S L E U N Z V C */
/* * * * * * * * * */
- /* TODO: S, L, E, U, V, C */
+ /* TODO: S, L, E, U */
if ( (absResult) & U64(0x0000008000000000)) N_SET(); else N_CLEAR();
if (((absResult) & U64(0x000000ffffffffff)) == 0) Z_SET(); else Z_CLEAR();
+ if ( (absResult & U64(0xffffff0000000000)) != 0) V_SET(); else V_CLEAR();
+ if ( (absResult & U64(0xffffff0000000000)) != 0) C_SET(); else C_CLEAR();
cycles += 2; /* TODO: +mv oscillator cycles */
return 1;
@@ -2815,6 +2862,13 @@ static size_t dsp56k_op_do_2(dsp56k_core* cpustate, const UINT16 op, const UINT1
else if (S.addr == &B) lValue = *((UINT16*)(&B1));
else lValue = *((UINT16*)S.addr);
+ /* HACK */
+ if (lValue >= 0xfff0)
+ {
+ lValue = 0x0000;
+ logerror("Dsp56k : DO_2 operation changed %04x to 0000.\n", lValue);
+ }
+
/* TODO: Fix for special cased SP S */
if (S.addr == &SP)
logerror("DSP56k: do with SP as the source not properly implemented yet.\n");
@@ -2915,12 +2969,53 @@ static size_t dsp56k_op_illegal(dsp56k_core* cpustate, const UINT16 op, UINT8* c
/* IMAC : 0001 0101 1010 FQQQ : A-100 */
static size_t dsp56k_op_imac(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
{
+ INT64 opD = 0;
+ INT64 result = 0;
+
+ INT32 s1 = 0;
+ INT32 s2 = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQQF_table(cpustate, BITS(op,0x0007), BITS(op,0x0008), &S1, &S2, &D);
+
+ /* Cast both values as being signed */
+ s1 = *((INT16*)S1);
+ s2 = *((INT16*)S2);
+
+ /* Integral multiply doesn't require the shift */
+ result = (s1 * s2);
+
+ /* Shift result 16 bits to the left before adding to destination */
+ result = (result << 16) & 0xffff0000;
+
+ /* Sign extend D into a temp variable */
+ opD = (*((UINT64*)D));
+ if (opD & U64(0x0000008000000000))
+ opD |= U64(0xffffff0000000000);
+ else
+ opD &= U64(0x000000ffffffffff);
+
+ /* Accumulate */
+ opD += result;
+
+ /* And out the bits that don't live in the register */
+ opD &= U64(0x000000ffffffffff);
+
+ (*((UINT64*)D)) = (UINT64)opD;
+
/* S L E U N Z V C */
/* - * ? ? * ? ? - */
- /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */
+ /* TODO: L */
/* U,E - Will not be set correctly by this instruction*/
- /* V - Set to zero regardless of the overflow */
- return 0;
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) N_SET(); else N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffff0000)) == 0) Z_SET(); else Z_CLEAR();
+ V_CLEAR();
+
+ cycles += 2;
+ return 1;
}
/* IMPY : 0001 0101 1000 FQQQ : A-102 */
@@ -3542,7 +3637,7 @@ static size_t dsp56k_op_movep(dsp56k_core* cpustate, const UINT16 op, UINT8* cyc
/* MOVE(P) : 0000 110W RRmp pppp : A-156 */
static size_t dsp56k_op_movep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
{
- // X:<Rx> and X:<pp>
+ /* X:<Rx> and X:<pp> */
UINT16 W;
UINT16 pp;
@@ -3571,7 +3666,7 @@ static size_t dsp56k_op_movep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* c
fatalerror("dsp56k : move(p) NOTHING HERE (yet)\n") ;
}
- // Postincrement
+ /* Postincrement */
execute_m_table(cpustate, BITS(op,0x00c0), BITS(op,0x0020));
/* S L E U N Z V C */
@@ -3851,9 +3946,18 @@ static size_t dsp56k_op_tcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycle
/* TFR(2) : 0001 0101 0000 F00J : A-214 */
static size_t dsp56k_op_tfr2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
{
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_JF_table(cpustate, BITS(op,0x0001), BITS(op,0x0008), &S, &D);
+
+ SetDestinationValue(S, D);
+
/* S L E U N Z V C */
/* - * - - - - - - */
- return 0;
+ /* TODO: L */
+ cycles += 2;
+ return 1;
}
/* TFR(3) : 0010 01mW RRDD FHHH : A-216 */
@@ -3875,10 +3979,10 @@ static size_t dsp56k_op_tst2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycl
/* (L,E,U should be set to 0) */
L_CLEAR();
E_CLEAR();
- // U_CLEAR(); /* TODO: Conflicting opinions? "Set if unnormalized." Documentation is weird (A&B?) */
+ /* U_CLEAR(); */ /* TODO: Conflicting opinions? "Set if unnormalized." Documentation is weird (A&B?) */
if ((*((UINT16*)D.addr)) & 0x8000) N_SET(); else N_CLEAR();
if ((*((UINT16*)D.addr)) == 0x0000) Z_SET(); else Z_CLEAR();
- // V_CLEAR(); /* Unaffected */
+ /* V_CLEAR(); */ /* Unaffected */
C_CLEAR();
cycles += 2;
@@ -3928,22 +4032,22 @@ static int decode_cccc_table(dsp56k_core* cpustate, UINT16 cccc)
switch (cccc)
{
/* Arranged according to mnemonic table - not decoding table */
- case 0x0: if( C() == 0) retVal = 1; break; // cc(hs)
- case 0x8: if( C() == 1) retVal = 1; break; // cs(lo)
- case 0x5: if( E() == 0) retVal = 1; break; // ec
- case 0xa: if( Z() == 1) retVal = 1; break; // eq
- case 0xd: if( E() == 1) retVal = 1; break; // es
- case 0x1: if((N() ^ V()) == 0) retVal = 1; break; // ge
- case 0x7: if((Z() | (N() ^ V())) == 0) retVal = 1; break; // gt
- case 0x6: if( L() == 0) retVal = 1; break; // lc
- case 0xf: if((Z() | (N() ^ V())) == 1) retVal = 1; break; // le
- case 0xe: if( L() == 1) retVal = 1; break; // ls
- case 0x9: if((N() ^ V()) == 1) retVal = 1; break; // lt
- case 0xb: if( N() == 1) retVal = 1; break; // mi
- case 0x2: if( Z() == 0) retVal = 1; break; // ne
- case 0xc: if((Z() | ((!U()) & (!E()))) == 1) retVal = 1; break; // nr
- case 0x3: if( N() == 0) retVal = 1; break; // pl
- case 0x4: if((Z() | ((!U()) & (!E()))) == 0) retVal = 1; break; // nn
+ case 0x0: if( C() == 0) retVal = 1; break; /* cc(hs) */
+ case 0x8: if( C() == 1) retVal = 1; break; /* cs(lo) */
+ case 0x5: if( E() == 0) retVal = 1; break; /* ec */
+ case 0xa: if( Z() == 1) retVal = 1; break; /* eq */
+ case 0xd: if( E() == 1) retVal = 1; break; /* es */
+ case 0x1: if((N() ^ V()) == 0) retVal = 1; break; /* ge */
+ case 0x7: if((Z() | (N() ^ V())) == 0) retVal = 1; break; /* gt */
+ case 0x6: if( L() == 0) retVal = 1; break; /* lc */
+ case 0xf: if((Z() | (N() ^ V())) == 1) retVal = 1; break; /* le */
+ case 0xe: if( L() == 1) retVal = 1; break; /* ls */
+ case 0x9: if((N() ^ V()) == 1) retVal = 1; break; /* lt */
+ case 0xb: if( N() == 1) retVal = 1; break; /* mi */
+ case 0x2: if( Z() == 0) retVal = 1; break; /* ne */
+ case 0xc: if((Z() | ((!U()) & (!E()))) == 1) retVal = 1; break; /* nr */
+ case 0x3: if( N() == 0) retVal = 1; break; /* pl */
+ case 0x4: if((Z() | ((!U()) & (!E()))) == 0) retVal = 1; break; /* nn */
}
return retVal;
@@ -3981,7 +4085,7 @@ static void decode_DDDDD_table(dsp56k_core* cpustate, UINT16 DDDDD, typed_pointe
case 0x18: ret->addr = &SSH; ret->data_type = DT_WORD; break;
case 0x19: ret->addr = &SSL; ret->data_type = DT_WORD; break;
case 0x1a: ret->addr = &LA; ret->data_type = DT_WORD; break;
- //no 0x1b
+ /*no 0x1b */
case 0x1c: ret->addr = &N0; ret->data_type = DT_WORD; break;
case 0x1d: ret->addr = &N1; ret->data_type = DT_WORD; break;
case 0x1e: ret->addr = &N2; ret->data_type = DT_WORD; break;
@@ -4135,6 +4239,19 @@ static void decode_JJF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_p
}
}
+static void decode_JF_table(dsp56k_core* cpustate, UINT16 J, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ UINT16 switchVal = (J << 1) | F ;
+
+ switch (switchVal)
+ {
+ case 0x0: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ case 0x1: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ }
+}
+
static void decode_KKK_table(dsp56k_core* cpustate, UINT16 KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working)
{
void *opposite = 0x00 ;
@@ -4402,7 +4519,7 @@ static UINT16 execute_q_table(dsp56k_core* cpustate, int RR, UINT16 q)
switch(q)
{
case 0x0: /* No permanent changes */ ; return (*rX)+(*nX);
- case 0x1: (*rX)--; return (*rX); // This one is special - it's a *PRE-decrement*!
+ case 0x1: (*rX)--; return (*rX); /* This one is special - it's a *PRE-decrement*! */
}
/* Should not get here */
@@ -4703,10 +4820,10 @@ static UINT16 Dsp56kOpMask(UINT16 cur, UINT16 mask)
UINT16 temp = 0x0000 ;
int offsetCount = 0 ;
- // Shift everything right, eliminating 'whitespace'...
+ /* Shift everything right, eliminating 'whitespace' */
for (i = 0; i < 16; i++)
{
- if (mask & (0x1<<i)) // If mask bit is non-zero
+ if (mask & (0x1<<i)) /* If mask bit is non-zero */
{
temp |= (((retVal >> i) & 0x1) << offsetCount) ;
offsetCount++ ;
@@ -4783,8 +4900,8 @@ static void SetDataMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT
case DT_WORD: memory_write_word_16le(cpustate->data, destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ;
case DT_DOUBLE_WORD: memory_write_word_16le(cpustate->data, destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ;
- // !!! Is this universal ???
- // !!! Forget not, yon shift-limiter !!!
+ /* !!! Is this universal ??? */
+ /* !!! Forget not, yon shift-limiter !!! */
case DT_LONG_WORD: memory_write_word_16le(cpustate->data, destinationAddr, (UINT16)( ((*((UINT64*)source.addr)) & U64(0x00000000ffff0000)) >> 16) ) ; break ;
}
}
@@ -4798,8 +4915,8 @@ static void SetProgramMemoryValue(dsp56k_core* cpustate, typed_pointer source, U
case DT_WORD: memory_write_word_16le(cpustate->program, destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ;
case DT_DOUBLE_WORD: memory_write_word_16le(cpustate->program, destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ;
- // !!! Is this universal ???
- // !!! Forget not, yon shift-limiter !!!
+ /* !!! Is this universal ??? */
+ /* !!! Forget not, yon shift-limiter !!! */
case DT_LONG_WORD: memory_write_word_16le(cpustate->program, destinationAddr, (UINT16)( ((*((UINT64*)source.addr)) & U64(0x00000000ffff0000)) >> 16) ) ; break ;
}
}