mirror of
https://github.com/holub/mame
synced 2025-05-22 13:48:55 +03:00
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:
parent
a30f534c52
commit
40a5d0c543
@ -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 ;
|
||||
|
@ -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 )
|
||||
|
Loading…
Reference in New Issue
Block a user