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

* Implemented tst, or, jsr, rti, tst2, and 2 new movec ops.
* Added opbase handler to plygonet.c
This commit is contained in:
Andrew Gardner 2008-10-22 04:15:30 +00:00
parent a30f534c52
commit 40a5d0c543
2 changed files with 213 additions and 30 deletions

View File

@ -181,13 +181,11 @@ static void decode_JJJF_table(UINT16 JJJ, UINT16 F, typed_pointer* src_ret, type
static void decode_JJF_table(UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
static void decode_QQF_special_table(UINT16 QQ, UINT16 F, void **S1, void **S2, void **D);
static void decode_RR_table(UINT16 RR, typed_pointer* ret);
#ifdef UNUSED_FUNCTION
static void decode_Z_table(UINT16 Z, typed_pointer* ret);
#endif
static void execute_m_table(int x, UINT16 m);
static void execute_MM_table(UINT16 rnum, UINT16 MM);
#ifdef UNUSED_FUNCTION
static UINT16 execute_q_table(int x, UINT16 q);
#ifdef UNUSED_FUNCTION
static void execute_z_table(int x, UINT16 z);
#endif
static UINT16 assemble_address_from_Pppppp_table(UINT16 P, UINT16 ppppp);
@ -1258,9 +1256,25 @@ static size_t dsp56k_op_rnd(const UINT16 op_byte, typed_pointer* d_register, UIN
/* TST : .... .... 0010 F001 : A-218 */
static size_t dsp56k_op_tst(const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
{
typed_pointer D = {NULL, DT_LONG_WORD};
decode_F_table(BITS(op_byte,0x0008), &D);
*p_accum = *((UINT64*)D.addr);
d_register->addr = D.addr;
d_register->data_type = D.data_type;
/* S L E U N Z V C */
/* 0 * * * * * 0 0 */
return 0;
/* TODO: S, L, E, U */
if ((*((UINT64*)D.addr)) & U64(0x0000008000000000)) N_bit_set(1); else N_bit_set(0);
if ((*((UINT64*)D.addr)) == 0) Z_bit_set(1); else Z_bit_set(0);
V_bit_set(0);
C_bit_set(0);
cycles += 2; /* TODO: + mv oscillator clock cycles */
return 1;
}
/* INC : .... .... 0010 F010 : A-104 */
@ -1283,11 +1297,29 @@ static size_t dsp56k_op_inc24(const UINT16 op_byte, typed_pointer* d_register, U
/* OR : .... .... 0010 F1JJ : A-176 */
static size_t dsp56k_op_or(const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
{
typed_pointer S = {NULL, DT_BYTE};
typed_pointer D = {NULL, DT_BYTE};
decode_JJF_table(BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D);
/* Save some data for the parallel move */
*p_accum = *((UINT64*)D.addr);
/* OR a word of S with A1|B1 */
((PAIR64*)D.addr)->w.h = *((UINT16*)S.addr) | ((PAIR64*)D.addr)->w.h;
d_register->addr = D.addr;
d_register->data_type = D.data_type;
/* S L E U N Z V C */
/* * * - - ? ? 0 - */
/* N - Set if bit 31 of the result is set. Cleared otherwise. */
/* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */
return 0;
/* TODO: S, L */
if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) N_bit_set(1); else N_bit_set(0);
if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) Z_bit_set(1); else Z_bit_set(0);
V_bit_set(0);
cycles += 2; /* TODO: + mv oscillator cycles */
return 1;
}
/* ASR : .... .... 0011 F000 : A-32 */
@ -1540,7 +1572,10 @@ static size_t dsp56k_op_and(const UINT16 op_byte, typed_pointer* d_register, UIN
/* AND a word of S with A1|B1 */
((PAIR64*)D.addr)->w.h = *((UINT16*)S.addr) & ((PAIR64*)D.addr)->w.h;
d_register->addr = D.addr;
d_register->data_type = D.data_type;
/* S L E U N Z V C */
/* * * - - ? ? 0 - */
/* TODO: S, L */
@ -1913,9 +1948,9 @@ static size_t dsp56k_op_bcc_1(const UINT16 op, UINT8* cycles)
INT16 offset = (INT16)assemble_address_from_6bit_signed_relative_short_address(BITS(op,0x003f));
PC += 1;
core.ppc = PC;
PC += offset;
change_pc(PC) ;
cycles += 4;
@ -2320,8 +2355,23 @@ static size_t dsp56k_op_jscc_1(const UINT16 op, UINT8* cycles)
/* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */
static size_t dsp56k_op_jsr(const UINT16 op, const UINT16 op2, UINT8* cycles)
{
/* TODO: It says "signed" absolute offset. Weird. */
UINT16 branchOffset = op2;
/* TODO: Verify, since it's not in the docs, but it must be true */
PC += 2;
SP++;
SSH = PC;
SSL = SR;
core.ppc = PC;
PC = branchOffset;
change_pc(PC);
/* S L E U N Z V C */
/* - - - - - - - - */
cycles += 4; /* TODO: + jx oscillator cycles */
return 0;
}
@ -2452,23 +2502,87 @@ static size_t dsp56k_op_movec(const UINT16 op, UINT8* cycles)
/* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */
static size_t dsp56k_op_movec_1(const UINT16 op, UINT8* cycles)
{
UINT8 W;
UINT16 memOffset;
typed_pointer SD = {NULL, DT_BYTE};
W = BITS(op,0x0400);
decode_DDDDD_table(BITS(op,0x03e0), &SD);
memOffset = execute_q_table(BITS(op,0x0003), BITS(op,0x0008));
if (W)
{
/* Write D */
UINT16 tempData = data_read_word_16le(WORD(memOffset));
typed_pointer temp_src = { (void*)&tempData, DT_WORD };
SetDestinationValue(temp_src, SD);
}
else
{
/* Read S */
UINT16 tempData = *((UINT16*)SD.addr);
typed_pointer temp_src = { (void*)&tempData, DT_WORD };
SetDataMemoryValue(temp_src, WORD(memOffset));
}
/* S L E U N Z V C */
/* * ? ? ? ? ? ? ? */
/* All ? bits - If SR is specified as a destination operand, set according to the corresponding
bit of the source operand. If SR is not specified as a destination operand, L is set if data
limiting occurred. All ? bits are not affected otherwise.*/
return 0;
if (W && (SD.addr != &SR))
{
/* If you're writing to something other than the SR */
/* TODO */
}
cycles += 2; /* + mvc oscillator clock cycles */
return 1;
}
/* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */
static size_t dsp56k_op_movec_2(const UINT16 op, UINT8* cycles)
{
UINT8 W;
UINT16 memOffset;
typed_pointer SD = {NULL, DT_BYTE};
typed_pointer XMemOffset = {NULL, DT_BYTE};
W = BITS(op,0x0400);
decode_Z_table(BITS(op,0x0008), &XMemOffset);
decode_DDDDD_table(BITS(op,0x03e0), &SD);
memOffset = *((UINT16*)XMemOffset.addr);
if (W)
{
/* Write D */
UINT16 tempData = data_read_word_16le(WORD(memOffset));
typed_pointer temp_src = { (void*)&tempData, DT_WORD };
SetDestinationValue(temp_src, SD);
}
else
{
/* Read S */
UINT16 tempData = *((UINT16*)SD.addr);
typed_pointer temp_src = { (void*)&tempData, DT_WORD };
SetDataMemoryValue(temp_src, WORD(memOffset));
}
/* S L E U N Z V C */
/* * ? ? ? ? ? ? ? */
/* All ? bits - If SR is specified as a destination operand, set according to the corresponding
bit of the source operand. If SR is not specified as a destination operand, L is set if data
limiting occurred. All ? bits are not affected otherwise.*/
return 0;
if (W && (SD.addr != &SR))
{
/* If you're writing to something other than the SR */
/* TODO */
}
cycles += 2; /* + mvc oscillator clock cycles */
return 1;
}
/* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */
@ -2803,16 +2917,43 @@ static size_t dsp56k_op_rep_1(const UINT16 op, UINT8* cycles)
/* S L E U N Z V C */
/* - * - - - - - - */
/* TODO */
/* TODO: L */
return 1;
}
/* REP : 0000 0100 001D DDDD : A-180 */
static size_t dsp56k_op_rep_2(const UINT16 op, UINT8* cycles)
{
/* TODO: This is non-interruptable, probably have to turn off interrupts here */
UINT16 repValue;
typed_pointer D = {NULL, DT_BYTE};
decode_DDDDD_table(BITS(op,0x001f), &D);
/* TODO: handle special A&B source cases */
if (D.addr == &A || D.addr == &B)
logerror("DSP56k ERROR : Rep with A or B instruction not implemented yet!\n");
repValue = *((UINT16*)D.addr);
if (repValue != 0)
{
TEMP = LC;
LC = repValue;
core.repFlag = 1;
core.repAddr = PC + WORD(1);
cycles += 4; /* TODO: + mv oscillator clock cycles */
}
else
{
cycles += 6; /* TODO: + mv oscillator clock cycles */
}
/* S L E U N Z V C */
/* - * - - - - - - */
return 0;
/* TODO: L */
return 1;
}
/* REPcc : 0000 0001 0101 cccc : A-184 */
@ -2834,9 +2975,17 @@ static size_t dsp56k_op_reset(const UINT16 op, UINT8* cycles)
/* RTI : 0000 0000 0000 0111 : A-194 */
static size_t dsp56k_op_rti(const UINT16 op, UINT8* cycles)
{
core.ppc = PC;
PC = SSH;
change_pc(PC);
SR = SSL;
SP = SP - 1;
/* S L E U N Z V C */
/* - ? ? ? ? ? ? ? */
/* ? ? ? ? ? ? ? ? */
/* All ? bits - Set according to value pulled from the stack. */
cycles += 4; /* TODO: + rx oscillator clock cycles */
return 0;
}
@ -2927,10 +3076,22 @@ static size_t dsp56k_op_tfr3(const UINT16 op, UINT8* cycles)
/* TST(2) : 0001 0101 0001 -1DD : A-220 */
static size_t dsp56k_op_tst2(const UINT16 op, UINT8* cycles)
{
typed_pointer D = {NULL, DT_BYTE};
decode_DD_table(BITS(op,0x0003), &D);
/* S L E U N Z V C */
/* - * * * * * 0 0 */
/* (L,E,U should be set to 0) */
return 0;
L_bit_set(0);
E_bit_set(0);
// U_bit_set(0); /* TODO: Conflicting opinions? "Set if unnormalized." Documentation is weird (A&B?) */
if ((*((UINT16*)D.addr)) & 0x8000) N_bit_set(1); else N_bit_set(0);
if ((*((UINT16*)D.addr)) == 0x0000) Z_bit_set(1); else Z_bit_set(0);
// V_bit_set(0); /* TODO: Verify as well! */
C_bit_set(0);
cycles += 2;
return 1;
}
/* WAIT : 0000 0000 0000 1011 : A-222 */
@ -3193,7 +3354,7 @@ static void decode_RR_table(UINT16 RR, typed_pointer* ret)
case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break;
}
}
#ifdef UNUSED_FUNCTION
static void decode_Z_table(UINT16 Z, typed_pointer* ret)
{
switch(Z)
@ -3203,7 +3364,7 @@ static void decode_Z_table(UINT16 Z, typed_pointer* ret)
case 0x00: ret->addr = &B1; ret->data_type = DT_WORD; break;
}
}
#endif
static void execute_m_table(int x, UINT16 m)
{
UINT16 *rX = 0x00 ;
@ -3245,19 +3406,19 @@ static void execute_MM_table(UINT16 rnum, UINT16 MM)
case 0x3: (*rX) = (*rX)+(*nX) ; break;
}
}
#ifdef UNUSED_FUNCTION
// Returns R address
/* Returns R value */
static UINT16 execute_q_table(int x, UINT16 q)
{
UINT16 *rX = 0x00 ;
UINT16 *nX = 0x00 ;
UINT16 *rX = 0x0000;
UINT16 *nX = 0x0000;
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 ;
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)
@ -3266,10 +3427,12 @@ static UINT16 execute_q_table(int x, UINT16 q)
case 0x1: (*rX)--; return (*rX); break; // This one is special - it's a *PRE-decrement*!
}
/* Should not get here */
exit(1);
return 0x00;
}
#ifdef UNUSED_FUNCTION
static void execute_z_table(int x, UINT16 z)
{
UINT16 *rX = 0x00 ;

View File

@ -64,6 +64,7 @@ static int init_eeprom_count;
static UINT32* shared_ram;
static UINT16* dsp56k_p_mirror;
static UINT16* dsp56k_p_8000;
static const UINT16 dsp56k_bank00_size = 0x1000; static UINT16* dsp56k_bank00_ram;
static const UINT16 dsp56k_bank01_size = 0x1000; static UINT16* dsp56k_bank01_ram;
static const UINT16 dsp56k_bank02_size = 0x4000; static UINT16* dsp56k_bank02_ram;
@ -286,6 +287,21 @@ static READ16_HANDLER( dsp56k_bootload_r )
return 0x7fff;
}
static OPBASE_HANDLER( plygonet_dsp56k_opbase_handler )
{
if (address >= 0x7000 && address <= 0x7fff)
{
opbase->rom = opbase->ram = (void*)(dsp56k_p_mirror - 0x7000);
return ~0;
}
else if (address >= 0x8000 && address <= 0x87ff)
{
opbase->rom = opbase->ram = (void*)(dsp56k_p_8000 - 0x8000);
return ~0;
}
return address;
}
/* The dsp56k's Port C Data register (0xffe3) :
Program code (function 4e) configures it as general purpose output I/O pins (ffc1 = 0000 & ffc3 = 0fff).
@ -465,6 +481,7 @@ static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x580000, 0x5807ff) AM_RAM
AM_RANGE(0x580800, 0x580803) AM_READWRITE(network_r, SMH_NOP)
AM_RANGE(0x580800, 0x580803) AM_RAM /* network RAM | registers? */
// AM_RANGE(0x600000, 0x600000)
AM_RANGE(0x600004, 0x600007) AM_WRITE(sound_w)
AM_RANGE(0x600008, 0x60000b) AM_READ(sound_r)
AM_RANGE(0x640000, 0x640003) AM_WRITE(sound_irq_w)
@ -477,15 +494,15 @@ ADDRESS_MAP_END
/**********************************************************************************/
static ADDRESS_MAP_START( dsp_program_map, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x7000, 0x7fff) AM_RAM AM_BASE(&dsp56k_p_mirror) /* Unsure of size, but this corresponds to bank01 */
AM_RANGE(0x8000, 0x87ff) AM_RAM
AM_RANGE(0x7000, 0x7fff) AM_RAM AM_BASE(&dsp56k_p_mirror) /* Unsure of size, but 0x1000 matches bank01 */
AM_RANGE(0x8000, 0x87ff) AM_RAM AM_BASE(&dsp56k_p_8000)
AM_RANGE(0xc000, 0xc000) AM_READ(dsp56k_bootload_r)
ADDRESS_MAP_END
static ADDRESS_MAP_START( dsp_data_map, ADDRESS_SPACE_DATA, 16 )
AM_RANGE(0x0800, 0x5fff) AM_RAM /* Appears to not be affected by banking? */
AM_RANGE(0x0800, 0x5fff) AM_RAM /* Appears to not be affected by banking? */
AM_RANGE(0x6000, 0x6fff) AM_READWRITE(dsp56k_ram_bank00_read, dsp56k_ram_bank00_write)
AM_RANGE(0x7000, 0x7fff) AM_READWRITE(dsp56k_ram_bank01_read, dsp56k_ram_bank01_write)
AM_RANGE(0x7000, 0x7fff) AM_READWRITE(dsp56k_ram_bank01_read, dsp56k_ram_bank01_write) /* Mirrored in program space @ 0x8000 */
AM_RANGE(0x8000, 0xbfff) AM_READWRITE(dsp56k_ram_bank02_read, dsp56k_ram_bank02_write)
AM_RANGE(0xc000, 0xdfff) AM_READWRITE(dsp56k_shared_ram_read, dsp56k_shared_ram_write)
AM_RANGE(0xe000, 0xffbf) AM_READWRITE(dsp56k_ram_bank04_read, dsp56k_ram_bank04_write)
@ -569,7 +586,7 @@ static MACHINE_DRIVER_START( plygonet )
MDRV_CPU_PROGRAM_MAP(main_map, 0)
MDRV_CPU_VBLANK_INT_HACK(polygonet_interrupt, 2)
MDRV_CPU_ADD("dsp", DSP56156, 10000000) /* should be 40.0 MHz/? */
MDRV_CPU_ADD("dsp", DSP56156, 10000000) /* xtal is 40.0 MHz */
MDRV_CPU_PROGRAM_MAP(dsp_program_map, 0)
MDRV_CPU_DATA_MAP(dsp_data_map, 0)
@ -643,6 +660,9 @@ static DRIVER_INIT(polygonet)
memset(dsp56k_bank02_ram, 0, 2 * 8 * dsp56k_bank02_size * sizeof(UINT16));
memset(dsp56k_shared_ram_16, 0, 2 * 8 * dsp56k_shared_ram_16_size * sizeof(UINT16));
memset(dsp56k_bank04_ram, 0, 2 * 8 * dsp56k_bank04_size * sizeof(UINT16));
/* The dsp56k occasionally executes out of mapped memory */
memory_set_opbase_handler(1, plygonet_dsp56k_opbase_handler);
}
ROM_START( plygonet )