Rewrite of the Motorola DSP56k CPU core. (Andrew Gardner)

* Fixed flag calculation and sign extension for numerous ops.
* Added rnd, mpysuuu, and dmac ops.
* Fixed do loop behavior to skip empty loops.
* Added stack underflow exception handling.
This commit is contained in:
Andrew Gardner 2008-12-21 19:07:44 +00:00
parent 6bd48dad88
commit 44a99ed738
5 changed files with 263 additions and 89 deletions

View File

@ -308,37 +308,37 @@ CPU_DISASSEMBLE( dsp56k )
int parallelType = -1;
/* Note: it's important that NPDM comes before RtRDM here */
/* No Parallel Data Move : 0100 1010 ---- ---- : A-131 */
/* No Parallel Data Move : 0100 1010 .... .... : A-131 */
if ((op & 0xff00) == 0x4a00)
{
op_byte = op & 0x00ff;
parallelType = kNoParallelDataMove;
}
/* Register to Register Data Move : 0100 IIII ---- ---- : A-133 */
/* Register to Register Data Move : 0100 IIII .... .... : A-133 */
else if ((op & 0xf000) == 0x4000)
{
op_byte = op & 0x00ff;
parallelType = kRegisterToRegister;
}
/* Address Register Update : 0011 0zRR ---- ---- : A-135 */
/* Address Register Update : 0011 0zRR .... .... : A-135 */
else if ((op & 0xf800) == 0x3000)
{
op_byte = op & 0x00ff;
parallelType = kAddressRegister;
}
/* X Memory Data Move : 1mRR HHHW ---- ---- : A-137 */
/* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
else if ((op & 0x8000) == 0x8000)
{
op_byte = op & 0x00ff;
parallelType = kXMemoryDataMove;
}
/* X Memory Data Move : 0101 HHHW ---- ---- : A-137 */
/* X Memory Data Move : 0101 HHHW .... .... : A-137 */
else if ((op & 0xf000) == 0x5000)
{
op_byte = op & 0x00ff;
parallelType = kXMemoryDataMove2;
}
/* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW ---- ---- : A-139 */
/* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */
else if ((op & 0xff00) == 0x0500)
{
/* Now check it against all the other potential collisions */

View File

@ -242,7 +242,7 @@ static CPU_RESET( dsp56k )
agu_reset(cpustate);
alu_reset(cpustate);
/* HACK - Put a jump to 0x0000 at 0x0000 - this keeps the CPU put in MAME */
/* HACK - Put a jump to 0x0000 at 0x0000 - this keeps the CPU locked to the instruction at address 0x0000 */
memory_write_word_16le(cpustate->program, 0x0000, 0x0124);
}

View File

@ -15,6 +15,15 @@
//
//
/*
TODO:
- 0x01ee: should this move sign extend? otherwise the test-against-minus means nothing.
- Restore only the proper bits upon loop termination!
- BFCLR has some errata in the docs that may need to be applied.
- *_bit_set(0) is difficult to read. maybe make it *_bit_chg(0).
- Potentially "better" reporting for unimplemented opcodes.
*/
/************************/
/* Datatypes and macros */
/************************/
@ -175,6 +184,7 @@ static UINT16 decode_BBB_bitmask(dsp56k_core* cpustate, UINT16 BBB, UINT16 *iVal
static int decode_cccc_table(dsp56k_core* cpustate, UINT16 cccc);
static void decode_DDDDD_table(dsp56k_core* cpustate, UINT16 DDDDD, typed_pointer* ret);
static void decode_DD_table(dsp56k_core* cpustate, UINT16 DD, typed_pointer* ret);
static void decode_DDF_table(dsp56k_core* cpustate, UINT16 DD, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
static void decode_F_table(dsp56k_core* cpustate, UINT16 F, typed_pointer* ret);
static void decode_h0hF_table(dsp56k_core* cpustate, UINT16 h0h, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
static void decode_HH_table(dsp56k_core* cpustate, UINT16 HH, typed_pointer* ret);
@ -1125,9 +1135,9 @@ static size_t dsp56k_op_addsub_2(dsp56k_core* cpustate, const UINT16 op_byte, ty
case DT_LONG_WORD: useVal = (UINT64)*((UINT64*)S.addr); break;
}
/* TODO: Verify : Sign-extend everyone for proper add/sub op */
if (useVal & U64(0x0000000080000000))
useVal |= U64(0xffffffff00000000);
/* Sign-extend word for proper add/sub op */
if ((S.data_type == DT_WORD) && useVal & U64(0x0000000080000000))
useVal |= U64(0x000000ff00000000);
/* Operate*/
if (op_type == OP_ADD)
@ -1141,8 +1151,8 @@ static size_t dsp56k_op_addsub_2(dsp56k_core* cpustate, const UINT16 op_byte, ty
/* S L E U N Z V C */
/* * * * * * * * * */
/* TODO S, L, E, U, V, C */
if (*((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if (*((UINT64*)D.addr) == 0) Z_bit_set(cpustate, 1);
if (*((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if (*((UINT64*)D.addr) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator cycles */
return 1;
@ -1192,8 +1202,8 @@ static size_t dsp56k_op_mac_1(dsp56k_core* cpustate, const UINT16 op_byte, typed
/* S L E U N Z V C */
/* * * * * * * * - */
/* TODO: S, L, E, V */
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: +mv oscillator cycles */
return 1;
@ -1246,8 +1256,8 @@ static size_t dsp56k_op_mpy_1(dsp56k_core* cpustate, const UINT16 op_byte, typed
/* S L E U N Z V C */
/* * * * * * * * - */
/* TODO: S, L, E, V */
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: +mv oscillator cycles */
return 1;
@ -1334,9 +1344,9 @@ static size_t dsp56k_op_add(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
case DT_LONG_WORD: addVal = (UINT64)*((UINT64*)S.addr); break;
}
/* TODO: Verify : Sign-extend everyone for proper addition op */
if (addVal & U64(0x0000000080000000))
addVal |= U64(0xffffffff00000000);
/* Sign-extend word for proper add/sub op */
if ((S.data_type == DT_WORD) && addVal & U64(0x0000000080000000))
addVal |= U64(0x000000ff00000000);
/* Operate*/
*((UINT64*)D.addr) += addVal;
@ -1347,8 +1357,8 @@ static size_t dsp56k_op_add(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_bit_set(cpustate, 1);
if (*((UINT64*)D.addr) == 0) Z_bit_set(cpustate, 1);
if (*((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if (*((UINT64*)D.addr) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator cycles */
return 1;
@ -1395,9 +1405,29 @@ static size_t dsp56k_op_tfr(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* RND : .... .... 0010 F000 : A-188 */
static size_t dsp56k_op_rnd(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
{
typed_pointer D = {NULL, DT_BYTE};
decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
*p_accum = *((UINT64*)D.addr);
/* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */
if ((*((UINT64*)D.addr) & U64(0x000000000000ffff)) >= 0x8000)
*((UINT64*)D.addr) += U64(0x0000000000010000);
*((UINT64*)D.addr) = *((UINT64*)D.addr) & U64(0x000000ffffff0000);
d_register->addr = D.addr;
d_register->data_type = D.data_type;
/* S L E U N Z V C */
/* * * * * * * * - */
return 0;
/* TODO: S, L, E, U, V */
if ((*((UINT64*)D.addr)) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D.addr)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator clock cycles */
return 1;
}
/* TST : .... .... 0010 F001 : A-218 */
@ -1445,8 +1475,8 @@ static size_t dsp56k_op_inc(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_bit_set(cpustate, 1);
if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: +mv oscillator cycles */
return 1;
@ -1478,8 +1508,8 @@ 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 */
if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator clock cycles */
return 1;
@ -1536,10 +1566,10 @@ static size_t dsp56k_op_asr(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* S L E U N Z V C */
/* * * * * * * 0 ? */
/* TODO: S, L, E, U */
if (*((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if (*((UINT64*)D.addr) == 0) Z_bit_set(cpustate, 1);
if (*((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if (*((UINT64*)D.addr) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
V_bit_set(cpustate, 0);
if (*p_accum & U64(0x0000000000000001)) C_bit_set(cpustate, 1);
if (*p_accum & U64(0x0000000000000001)) C_bit_set(cpustate, 1); else C_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator cycles */
return 1;
@ -1577,9 +1607,9 @@ static size_t dsp56k_op_lsr(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* * * - - ? ? 0 ? */
/* TODO: S, L */
N_bit_set(cpustate, 0);
if (((PAIR64*)D.addr)->w.h == 0) Z_bit_set(cpustate, 1);
if (((PAIR64*)D.addr)->w.h == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
V_bit_set(cpustate, 0);
if (*p_accum & U64(0x0000000000010000)) C_bit_set(cpustate, 1);
if (*p_accum & U64(0x0000000000010000)) C_bit_set(cpustate, 1); else C_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator cycles */
return 1;
@ -1656,11 +1686,20 @@ static size_t dsp56k_op_cmp(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
switch(S.data_type)
{
case DT_WORD: cmpVal = (UINT64)*((UINT16*)S.addr); break;
case DT_WORD: cmpVal = (UINT64)*((UINT16*)S.addr) << 16; break;
case DT_DOUBLE_WORD: cmpVal = (UINT64)*((UINT32*)S.addr); break;
case DT_LONG_WORD: cmpVal = (UINT64)*((UINT64*)S.addr); break;
}
/* Sign-extend word for proper subtraction op */
if ((S.data_type == DT_WORD) && cmpVal & U64(0x0000000080000000))
cmpVal |= U64(0x000000ff00000000);
/* Make sure they're both real 40-bit values */
cmpVal &= U64(0x000000ffffffffff);
*((UINT64*)D.addr) &= U64(0x000000ffffffffff);
/* Operate */
result = *((UINT64*)D.addr) - cmpVal;
d_register->addr = D.addr;
@ -1669,7 +1708,7 @@ 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_bit_set(cpustate, 1); /* TODO: Do you clear it if this isn't true? */
if (result == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator clock cycles */
@ -1701,8 +1740,8 @@ static size_t dsp56k_op_not(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* S L E U N Z V C */
/* * * - - ? ? 0 - */
/* TODO: S?, L */
if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
V_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator cycles */
@ -1743,8 +1782,8 @@ static size_t dsp56k_op_dec24(dsp56k_core* cpustate, const UINT16 op_byte, typed
/* S L E U N Z V C */
/* * * * * * ? * * */
/* TODO: S, L, E, U, V, C */
if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator clock cycles */
return 1;
@ -1770,8 +1809,8 @@ static size_t dsp56k_op_and(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* S L E U N Z V C */
/* * * - - ? ? 0 - */
/* TODO: S, L */
if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
V_bit_set(cpustate, 0);
cycles += 2; /* TODO: + mv oscillator cycles */
@ -1901,8 +1940,8 @@ static size_t dsp56k_op_mpy(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* S L E U N Z V C */
/* * * * * * * * - */
/* TODO: S, L, E, V */
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: +mv oscillator cycles */
return 1;
@ -1967,8 +2006,8 @@ static size_t dsp56k_op_mac(dsp56k_core* cpustate, const UINT16 op_byte, typed_p
/* S L E U N Z V C */
/* * * * * * * * - */
/* TODO: S, L, E, V */
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: +mv oscillator cycles */
return 1;
@ -2015,6 +2054,9 @@ static size_t dsp56k_op_macr(dsp56k_core* cpustate, const UINT16 op_byte, typed_
/* Round the result */
/* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */
if ((opD & U64(0x000000000000ffff)) >= 0x8000)
opD += U64(0x0000000000010000);
opD &= U64(0x000000ffffff0000);
/* And out the bits that don't live in the register */
@ -2030,8 +2072,8 @@ static size_t dsp56k_op_macr(dsp56k_core* cpustate, const UINT16 op_byte, typed_
/* S L E U N Z V C */
/* * * * * * * * - */
/* TODO: S, L, E, V */
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2; /* TODO: +mv oscillator cycles */
return 1;
@ -2184,7 +2226,7 @@ static size_t dsp56k_op_bfop(dsp56k_core* cpustate, const UINT16 op, const UINT1
UINT16 iVal = op2 & 0x00ff;
decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal);
workAddr = assemble_address_from_Pppppp_table(cpustate, BITS(OP,0x0020), BITS(OP,0x001f));
workAddr = assemble_address_from_Pppppp_table(cpustate, BITS(op,0x0020), BITS(op,0x001f));
previousValue = memory_read_word_16le(cpustate->data, WORD(workAddr));
workingWord = previousValue;
@ -2596,20 +2638,71 @@ static size_t dsp56k_op_debugcc(dsp56k_core* cpustate, const UINT16 op, UINT8* c
/* WARNING : DOCS SAY THERE IS A PARALLEL MOVE HERE !!! */
static size_t dsp56k_op_div(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
{
/* WARNING : THIS DOES NOT WORK. IT DOESN'T EVEN TRY !!! */
typed_pointer S = {NULL, DT_BYTE};
typed_pointer D = {NULL, DT_BYTE};
decode_DDF_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S, &D);
/* S L E U N Z V C */
/* - * - - - - ? ? */
/* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst
bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */
/* C - Set if bit 39 of the result is cleared. Cleared otherwise. */
return 0;
cycles += 2;
return 1;
}
/* DMAC : 0001 0101 10s1 FsQQ : A-80 */
static size_t dsp56k_op_dmac(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
{
UINT8 ss = 0;
INT64 result = 0;
void* D = NULL;
void* S1 = NULL;
void* S2 = NULL;
decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D);
ss = BITS(op,0x0024);
/* Fixed-point 2's complement multiplication requires a shift */
if (ss == 0x00 || ss == 0x01)
{
/* Signed * Signed */
INT32 s1 = ((INT32)(*((UINT16*)S1)));
INT32 s2 = ((INT32)(*((UINT16*)S2)));
result = ( s1 * s2 ) << 1;
}
else if (ss == 0x2)
{
/* Signed * Unsigned */
/* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
INT32 s1 = ((INT32)(*((UINT16*)S1)));
INT32 s2 = (UINT32)(*((UINT16*)S2));
result = ( s1 * s2 ) << 1;
}
else if (ss == 0x3)
{
/* Unsigned * Unsigned */
UINT32 s1 = (UINT32)(*((UINT16*)S1));
UINT32 s2 = (UINT32)(*((UINT16*)S2));
result = ( s1 * s2 ) << 1;
}
/* Shift right, then accumulate */
(*((UINT64*)D)) = (*((UINT64*)D)) >> 16;
(*((UINT64*)D)) += result;
/* S L E U N Z V C */
/* - * * * * * * - */
return 0;
/* TODO: L, E, U, V */
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2;
return 1;
}
/* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */
@ -2623,6 +2716,7 @@ static size_t dsp56k_op_do(dsp56k_core* cpustate, const UINT16 op, const UINT16
/* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */
static size_t dsp56k_op_do_1(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
{
UINT8 retSize = 0;
UINT8 iValue = BITS(op,0x00ff);
/* Don't execute if the loop counter == 0 */
@ -2645,24 +2739,34 @@ static size_t dsp56k_op_do_1(dsp56k_core* cpustate, const UINT16 op, const UINT1
/* Third instruction cycle */
LF_bit_set(cpustate, 1);
/* Undocumented, but it must be true to nest Dos in DoForevers */
FV_bit_set(cpustate, 0);
/* S L E U N Z V C */
/* - * - - - - - - */
/* TODO : L */
cycles += 6; /* TODO: + mv oscillator cycles */
retSize = 2;
}
else
{
/* Skip over the contents of the loop */
cpustate->ppc = PC;
PC = PC + 2 + op2;
cycles += 10; /* TODO: + mv oscillator cycles */
retSize = 0;
}
return 2;
return retSize;
}
/* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */
static size_t dsp56k_op_do_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
{
UINT8 retSize = 0;
UINT16 lValue = 0x0000;
typed_pointer S = {NULL, DT_BYTE};
decode_DDDDD_table(cpustate, BITS(op,0x001f), &S);
@ -2704,13 +2808,19 @@ static size_t dsp56k_op_do_2(dsp56k_core* cpustate, const UINT16 op, const UINT1
/* TODO : L */
cycles += 6; /* TODO: + mv oscillator cycles */
retSize = 2;
}
else
{
/* Skip over the contents of the loop */
cpustate->ppc = PC;
PC = PC + 2 + op2;
cycles += 10; /* TODO: + mv oscillator cycles */
retSize = 0;
}
return 2;
return retSize;
}
/* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */
@ -2977,19 +3087,22 @@ static size_t dsp56k_op_macsuuu(dsp56k_core* cpustate, const UINT16 op, UINT8* c
else
{
/* Signed * Unsigned */
/* TODO: THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
UINT32 s1 = (UINT32)((INT32)(*((UINT16*)S1)));
UINT32 s2 = (UINT32)(*((UINT16*)S2));
/* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
INT32 s1 = ((INT32)(*((UINT16*)S1)));
INT32 s2 = (UINT32)(*((UINT16*)S2));
result = ( s1 * s2 ) << 1;
}
(*((UINT64*)D)) += result;
/* And out the bits that don't live in the register */
(*((UINT64*)D)) &= U64(0x000000ffffffffff);
/* S L E U N Z V C */
/* - * * * * * * - */
/* TODO: L, E, U, V */
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1);
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2;
return 1;
@ -3383,7 +3496,7 @@ static size_t dsp56k_op_movep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* c
pp = op & 0x001f;
pp = assemble_address_from_IO_short_address(cpustate, pp);
W = BITS(OP,0x0100);
W = BITS(op,0x0100);
/* A little different than most W if's - opposite read and write */
if (W)
@ -3403,7 +3516,7 @@ static size_t dsp56k_op_movep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* c
}
// Postincrement
execute_m_table(cpustate, BITS(OP,0x00c0), BITS(OP,0x0020));
execute_m_table(cpustate, BITS(op,0x00c0), BITS(op,0x0020));
/* S L E U N Z V C */
/* * * - - - - - - */
@ -3423,9 +3536,47 @@ static size_t dsp56k_op_moves(dsp56k_core* cpustate, const UINT16 op, UINT8* cyc
/* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */
static size_t dsp56k_op_mpysuuu(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
{
UINT8 s = 0;
INT64 result = 0;
void* D = NULL;
void* S1 = NULL;
void* S2 = NULL;
decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D);
s = BITS(op,0x0004);
/* Fixed-point 2's complement multiplication requires a shift */
if (s)
{
/* Unsigned * Unsigned */
UINT32 s1 = (UINT32)(*((UINT16*)S1));
UINT32 s2 = (UINT32)(*((UINT16*)S2));
result = ( s1 * s2 ) << 1;
}
else
{
/* Signed * Unsigned */
/* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
INT32 s1 = ((INT32)(*((UINT16*)S1)));
INT32 s2 = (UINT32)(*((UINT16*)S2));
result = ( s1 * s2 ) << 1;
}
(*((UINT64*)D)) = result;
/* And out the bits that don't live in the register */
(*((UINT64*)D)) &= U64(0x000000ffffffffff);
/* S L E U N Z V C */
/* - * * * * * * - */
return 0;
/* TODO: L, E, U, V */
if ( *((UINT64*)D) & U64(0x0000008000000000)) N_bit_set(cpustate, 1); else N_bit_set(cpustate, 0);
if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) Z_bit_set(cpustate, 1); else Z_bit_set(cpustate, 0);
cycles += 2;
return 1;
}
/* NEGC : 0001 0101 0110 F000 : A-168 */
@ -3554,6 +3705,13 @@ static size_t dsp56k_op_reset(dsp56k_core* cpustate, const UINT16 op, UINT8* cyc
/* RTI : 0000 0000 0000 0111 : A-194 */
static size_t dsp56k_op_rti(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
{
/* WARNING : THERE SHOULD BE A MORE GENERAL HANDLING OF STACK ERRORS. */
if (SP == 0)
{
dsp56k_add_pending_interrupt(cpustate, "Stack Error");
return 0;
}
cpustate->ppc = PC;
PC = SSH;
@ -3786,6 +3944,23 @@ static void decode_DD_table(dsp56k_core* cpustate, UINT16 DD, typed_pointer* ret
}
}
static void decode_DDF_table(dsp56k_core* cpustate, UINT16 DD, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret)
{
UINT16 switchVal = (DD << 1) | F;
switch (switchVal)
{
case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
}
}
static void decode_F_table(dsp56k_core* cpustate, UINT16 F, typed_pointer* ret)
{
switch(F)
@ -4250,7 +4425,7 @@ static void dsp56k_process_loop(dsp56k_core* cpustate)
if (LC == 1)
{
/* End of loop processing */
SR = SSL; /* TODO: A-83. I believe only the Loop Flag comes back here. */
SR = SSL; /* TODO: A-83. I believe only the Loop Flag comes back here. And maybe the do forever bit too. */
SP--;
LA = SSH;
@ -4531,9 +4706,10 @@ static void SetDestinationValue(typed_pointer source, typed_pointer dest)
{
case DT_BYTE: *((UINT64*)dest.addr) = (*((UINT8*)source.addr)) & 0xff; break;
case DT_WORD: destinationValue = (*((INT16*)source.addr)) << 16; /* Sign extend */
destinationValue &= U64(0x000000ffffff0000);
*((UINT64*)dest.addr) = destinationValue; break; /* Forget not, yon shift register */
case DT_WORD: destinationValue = (*((UINT16*)source.addr)) << 16;
if (destinationValue & U64(0x0000000080000000))
destinationValue |= U64(0x000000ff00000000);
*((UINT64*)dest.addr) = (UINT64)destinationValue; break; /* Forget not, yon shift register */
case DT_DOUBLE_WORD: *((UINT64*)dest.addr) = (*((UINT32*)source.addr)) & 0xffffffff; break;
case DT_LONG_WORD: *((UINT64*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x000000ffffffffff); break;

View File

@ -142,7 +142,7 @@ static void pcu_reset(dsp56k_core* cpustate)
// This, in actuality, is handled with the internal boot ROM.
for (i = 0; i < 0x800; i++)
{
UINT32 mem_offset = (0xc0000<<1) + (i<<1); /* TODO: TEST */
UINT32 mem_offset = (0xc000<<1) + (i<<1); /* TODO: TEST */
// TODO - DO I HAVE TO FLIP THIS WORD?
// P:$c000 -> Internal P:$0000 low byte

View File

@ -189,14 +189,12 @@ static READ32_HANDLER( psac_rom_r )
/* irq 3 is network. don't generate if you don't emulate the network h/w! */
/* irq 5 is vblank */
/* irq 7 does nothing (it jsrs to a rts and then rte) */
static INTERRUPT_GEN(polygonet_interrupt)
{
cpu_set_input_line(device, M68K_IRQ_5, HOLD_LINE);
}
/* sound CPU communications */
static READ32_HANDLER( sound_r )
{
int latch = soundlatch3_r(space, 0);
@ -286,8 +284,7 @@ static WRITE32_HANDLER( dsp_w_lines )
cputag_set_input_line(space->machine, "dsp", DSP56K_IRQ_MODB, CLEAR_LINE);
}
/* 0x04000000 is the ??? line */
/* 0x04000000 is the COMBNK line - it switches who has access to the shared RAM - the dsp or the 68020 */
}
static WRITE32_HANDLER( dsp_host_interface_w )
@ -311,6 +308,21 @@ static READ32_HANDLER( network_r )
return 0x08000000;
}
WRITE32_HANDLER( plygonet_palette_w )
{
int r,g,b;
COMBINE_DATA(&paletteram32[offset]);
r = (paletteram32[offset] >>16) & 0xff;
g = (paletteram32[offset] >> 8) & 0xff;
b = (paletteram32[offset] >> 0) & 0xff;
palette_set_color(space->machine,offset,MAKE_RGB(r,g,b));
}
/**********************************************************************************/
/******* DSP56k maps *******/
/**********************************************************************************/
@ -506,20 +518,6 @@ static WRITE16_HANDLER( dsp56k_ram_bank04_write )
}
WRITE32_HANDLER( plygonet_palette_w )
{
int r,g,b;
COMBINE_DATA(&paletteram32[offset]);
r = (paletteram32[offset] >>16) & 0xff;
g = (paletteram32[offset] >> 8) & 0xff;
b = (paletteram32[offset] >> 0) & 0xff;
palette_set_color(space->machine,offset,MAKE_RGB(r,g,b));
}
/**********************************************************************************/
static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 32 )