From: Wilbert Pol [mailto:wilbert@jdg.info]

Subject: uPD7801, uPD78C05, and uPD78C06 cpu cores added to the uPD7810
cpu core

This patch adds basic support for the NEC uPD7801, uPD78C05, and  
uPD78C06 cpus to the uPD7810 cpu core.
This commit is contained in:
Aaron Giles 2008-02-28 03:22:38 +00:00
parent 34781e5f4c
commit 0104d6ff63
8 changed files with 8899 additions and 3408 deletions

View File

@ -1225,8 +1225,9 @@ $(CPUOBJ)/v810/v810.o: $(CPUSRC)/v810/v810.c \
CPUDEFS += -DHAS_UPD7810=$(if $(filter UPD7810,$(CPUS)),1,0)
CPUDEFS += -DHAS_UPD7807=$(if $(filter UPD7807,$(CPUS)),1,0)
CPUDEFS += -DHAS_UPD7801=$(if $(filter UPD7801,$(CPUS)),1,0)
ifneq ($(filter UPD7810 UPD7807,$(CPUS)),)
ifneq ($(filter UPD7810 UPD7807 UPD7801,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/upd7810
CPUOBJS += $(CPUOBJ)/upd7810/upd7810.o
DBGOBJS += $(CPUOBJ)/upd7810/7810dasm.o

File diff suppressed because it is too large Load Diff

View File

@ -291,7 +291,7 @@ static void HALT(void)
{
int cycles = (upd7810_icount / 4) * 4;
upd7810_icount -= cycles;
upd7810_timers(cycles);
upd7810.handle_timers(cycles);
PC -= 1; /* continue executing HALT */
}
@ -816,7 +816,7 @@ static void STOP(void)
{
int cycles = (upd7810_icount / 4) * 4;
upd7810_icount -= cycles;
upd7810_timers(cycles);
upd7810.handle_timers(cycles);
PC -= 1;
}
@ -8397,9 +8397,9 @@ static void ONIW_wa_xx(void)
static void PRE_48(void)
{
RDOP(OP2);
upd7810_icount -= op48[OP2].cycles;
upd7810_timers(op48[OP2].cycles);
(*op48[OP2].opfunc)();
upd7810_icount -= upd7810.op48[OP2].cycles;
upd7810.handle_timers(upd7810.op48[OP2].cycles);
(*upd7810.op48[OP2].opfunc)();
}
/* 49: 0100 1001 xxxx xxxx */
@ -8430,18 +8430,18 @@ static void MVIX_HL_xx(void)
static void PRE_4C(void)
{
RDOP(OP2);
upd7810_icount -= op4C[OP2].cycles;
upd7810_timers(op4C[OP2].cycles);
(*op4C[OP2].opfunc)();
upd7810_icount -= upd7810.op4C[OP2].cycles;
upd7810.handle_timers(upd7810.op4C[OP2].cycles);
(*upd7810.op4C[OP2].opfunc)();
}
/* 4d: prefix */
static void PRE_4D(void)
{
RDOP(OP2);
upd7810_icount -= op4D[OP2].cycles;
upd7810_timers(op4D[OP2].cycles);
(*op4D[OP2].opfunc)();
upd7810_icount -= upd7810.op4D[OP2].cycles;
upd7810.handle_timers(upd7810.op4D[OP2].cycles);
(*upd7810.op4D[OP2].opfunc)();
}
/* 4e: 0100 111d dddd dddd */
@ -8820,9 +8820,9 @@ static void SK_bit(void)
static void PRE_60(void)
{
RDOP(OP2);
upd7810_icount -= op60[OP2].cycles;
upd7810_timers(op60[OP2].cycles);
(*op60[OP2].opfunc)();
upd7810_icount -= upd7810.op60[OP2].cycles;
upd7810.handle_timers(upd7810.op60[OP2].cycles);
(*upd7810.op60[OP2].opfunc)();
}
/* 61: 0110 0001 */
@ -8883,9 +8883,9 @@ static void STAW_wa(void)
static void PRE_64(void)
{
RDOP(OP2);
upd7810_icount -= op64[OP2].cycles;
upd7810_timers(op64[OP2].cycles);
(*op64[OP2].opfunc)();
upd7810_icount -= upd7810.op64[OP2].cycles;
upd7810.handle_timers(upd7810.op64[OP2].cycles);
(*upd7810.op64[OP2].opfunc)();
}
/* 65: 0110 0101 oooo oooo xxxx xxxx */
@ -8970,9 +8970,9 @@ static void MVI_L_xx(void)
static void PRE_70(void)
{
RDOP(OP2);
upd7810_icount -= op70[OP2].cycles;
upd7810_timers(op70[OP2].cycles);
(*op70[OP2].opfunc)();
upd7810_icount -= upd7810.op70[OP2].cycles;
upd7810.handle_timers(upd7810.op70[OP2].cycles);
(*upd7810.op70[OP2].opfunc)();
}
/* 71: 0111 0001 oooo oooo xxxx xxxx */
@ -9005,9 +9005,9 @@ static void SOFTI(void)
static void PRE_74(void)
{
RDOP(OP2);
upd7810_icount -= op74[OP2].cycles;
upd7810_timers(op74[OP2].cycles);
(*op74[OP2].opfunc)();
upd7810_icount -= upd7810.op74[OP2].cycles;
upd7810.handle_timers(upd7810.op74[OP2].cycles);
(*upd7810.op74[OP2].opfunc)();
}
/* 75: 0111 0101 oooo oooo xxxx xxxx */
@ -9072,7 +9072,6 @@ static void CALT(void)
PCH=RM(w.w.l+1);
change_pc( PCD );
logerror ("!!!!!!!%.4x calt %.2x %.4x; game master table position not known\n",PPC, OP, PCD);
}
}
@ -9339,3 +9338,138 @@ static void JR(void)
change_pc(PCD);
}
/*********************/
/* */
/* 7801 instructions */
/* */
/*********************/
static void CALT_7801(void)
{
PAIR w;
w.d = 0;
w.w.l = 0x80 + 2 * (OP & 0x3f);
SP--;
WM( SPD, PCH );
SP--;
WM( SPD, PCL );
PCL=RM(w.w.l);
PCH=RM(w.w.l+1);
change_pc( PCD );
}
/* DCR(W) and INR(W) instructions do not modify the CY register on at least 78c05 and 78c06 */
static void DCR_A_7801(void)
{
UINT32 old_CY = PSW & CY;
DCR_A();
PSW = ( PSW & ~CY ) | old_CY;
}
static void DCR_B_7801(void)
{
UINT32 old_CY = PSW & CY;
DCR_B();
PSW = ( PSW & ~CY ) | old_CY;
}
static void DCR_C_7801(void)
{
UINT32 old_CY = PSW & CY;
DCR_C();
PSW = ( PSW & ~CY ) | old_CY;
}
static void DCRW_wa_7801(void)
{
UINT32 old_CY = PSW & CY;
DCRW_wa();
PSW = ( PSW & ~CY ) | old_CY;
}
static void INR_A_7801(void)
{
UINT32 old_CY = PSW & CY;
INR_A();
PSW = ( PSW & ~CY ) | old_CY;
}
static void INR_B_7801(void)
{
UINT32 old_CY = PSW & CY;
INR_B();
PSW = ( PSW & ~CY ) | old_CY;
}
static void INR_C_7801(void)
{
UINT32 old_CY = PSW & CY;
INR_C();
PSW = ( PSW & ~CY ) | old_CY;
}
static void INRW_wa_7801(void)
{
UINT32 old_CY = PSW & CY;
INRW_wa();
PSW = ( PSW & ~CY ) | old_CY;
}
static void IN(void)
{
logerror("unimplemented instruction: IN\n");
}
static void OUT(void)
{
logerror("unimplemented instruction: OUT\n");
}
static void MOV_A_S(void)
{
logerror("unimplemented instruction: MOV_A_S\n");
}
static void MOV_S_A(void)
{
logerror("unimplemented instruction: MOV_A_S\n");
}
static void PEN(void)
{
logerror("unimplemented instruction: PEN\n");
}
static void PER(void)
{
logerror("unimplemented instruction: PER\n");
}
static void PEX(void)
{
logerror("unimplemented instruction: PEX\n");
}
static void SIO(void)
{
logerror("unimplemented instruction: SIO\n");
}
static void SKIT_F0(void)
{
logerror("unimplemented instruction: SKIT_F0\n");
}
static void SKNIT_F0(void)
{
logerror("unimplemented instruction: SKNIT_F0\n");
}
static void STM(void)
{
upd7810.ovc0 = ( ( TMM & 0x04 ) ? 16 * 8 : 8 ) * TM0;
}

File diff suppressed because it is too large Load Diff

View File

@ -59,6 +59,16 @@
* 5B xx (CLR)
* 5D xx (SK bit)
*
* 2008-02-24 (Wilbert Pol):
* - Added preliminary support for uPD7801
* For the uPD7801 only the basic instruction set was added. The current timer
* and serial i/o implementations are most likely incorrect.
* - Added basic support for uPD78C05 and uPD78C06
* Documentation of the actual instruction set layout is missing, so we took
* the uPD7801 instruction set and only kept the instructions mentioned in
* the little documentation available on the uPD78c05A/06A. The serial i/o
* implementation has not been tested and is probably incorrect.
*
*****************************************************************************/
/* Hau around 23 May 2004
gta, gti, dgt fixed
@ -1496,6 +1506,30 @@ static void upd7810_timers(int cycles)
}
}
//static void upd7801_timers(int cycles)
//{
//}
static void upd78c05_timers(int cycles)
{
if ( upd7810.ovc0 ) {
upd7810.ovc0 -= cycles;
if ( upd7810.ovc0 <= 0 ) {
IRR |= INTFT0;
if (0x00 == (TMM & 0x03)) {
TO ^= 1;
if (upd7810.config.io_callback)
(*upd7810.config.io_callback)(UPD7810_TO,TO);
}
while ( upd7810.ovc0 <= 0 ) {
upd7810.ovc0 += ( ( TMM & 0x04 ) ? 16 * 8 : 8 ) * TM0;
}
}
}
}
static void upd7810_init(int index, int clock, const void *config, int (*irqcallback)(int))
{
upd7810.config = *(const UPD7810_CONFIG*) config;
@ -1580,6 +1614,13 @@ static void upd7810_reset (void)
upd7810.irq_callback = save_irqcallback;
upd7810.opXX = opXX_7810;
upd7810.op48 = op48;
upd7810.op4C = op4C;
upd7810.op4D = op4D;
upd7810.op60 = op60;
upd7810.op64 = op64;
upd7810.op70 = op70;
upd7810.op74 = op74;
ETMM = 0xff;
TMM = 0xff;
MA = 0xff;
@ -1599,6 +1640,7 @@ static void upd7810_reset (void)
// gamemaster falling block "and"s to enable interrupts
MKL = 0xff;
MKH = 0xff; //?
upd7810.handle_timers = upd7810_timers;
}
static void upd7807_reset (void)
@ -1607,14 +1649,54 @@ static void upd7807_reset (void)
upd7810.opXX = opXX_7807;
}
static void upd7801_reset( void ) {
upd7810_reset();
upd7810.op48 = op48_7801;
upd7810.op4C = op4C_7801;
upd7810.op4D = op4D_7801;
upd7810.op60 = op60_7801;
upd7810.op64 = op64_7801;
upd7810.op70 = op70_7801;
upd7810.op74 = op74_7801;
upd7810.opXX = opXX_7801;
}
static void upd78c05_reset( void ) {
upd7810_reset();
upd7810.op48 = op48_78c05;
upd7810.op4C = op4C_78c05;
upd7810.op4D = op4D_78c05;
upd7810.op60 = op60_78c05;
upd7810.op64 = op64_78c05;
upd7810.op70 = op70_78c05;
upd7810.op74 = op74_78c05;
upd7810.opXX = opXX_78c05;
MA = 0; /* All outputs */
MC = 0xFF; /* All inputs */
V = 0xFF; /* The vector register is always pointing to FF00 */
upd7810.handle_timers = upd78c05_timers;
TM0 = 0xFF; /* Timer seems to be running from boot */
upd7810.ovc0 = ( ( TMM & 0x04 ) ? 16 * 8 : 8 ) * TM0;
}
static void upd78c06_reset( void ) {
upd78c05_reset();
upd7810.op48 = op48_78c06;
upd7810.op4C = op4C_78c06;
upd7810.op4D = op4D_78c06;
upd7810.op60 = op60_78c06;
upd7810.op64 = op64_78c06;
upd7810.op70 = op70_78c06;
upd7810.op74 = op74_78c06;
upd7810.opXX = opXX_78c06;
}
static void upd7810_exit (void)
{
}
static int upd7810_execute (int cycles)
{
const struct opcode_s *opXX = upd7810.opXX;
upd7810_icount = cycles;
do
@ -1631,15 +1713,15 @@ static int upd7810_execute (int cycles)
* L0 for "MVI L,xx" or "LXI H,xxxx"
* L1 for "MVI A,xx"
*/
PSW &= ~opXX[OP].mask_l0_l1;
PSW &= ~upd7810.opXX[OP].mask_l0_l1;
/* skip flag set and not SOFTI opcode? */
if ((PSW & SK) && (OP != 0x72))
{
if (opXX[OP].cycles)
if (upd7810.opXX[OP].cycles)
{
cc = opXX[OP].cycles_skip;
PC += opXX[OP].oplen - 1;
cc = upd7810.opXX[OP].cycles_skip;
PC += upd7810.opXX[OP].oplen - 1;
}
else
{
@ -1647,46 +1729,46 @@ static int upd7810_execute (int cycles)
switch (OP)
{
case 0x48:
cc = op48[OP2].cycles_skip;
PC += op48[OP2].oplen - 2;
cc = upd7810.op48[OP2].cycles_skip;
PC += upd7810.op48[OP2].oplen - 2;
break;
case 0x4c:
cc = op4C[OP2].cycles_skip;
PC += op4C[OP2].oplen - 2;
cc = upd7810.op4C[OP2].cycles_skip;
PC += upd7810.op4C[OP2].oplen - 2;
break;
case 0x4d:
cc = op4D[OP2].cycles_skip;
PC += op4D[OP2].oplen - 2;
cc = upd7810.op4D[OP2].cycles_skip;
PC += upd7810.op4D[OP2].oplen - 2;
break;
case 0x60:
cc = op60[OP2].cycles_skip;
PC += op60[OP2].oplen - 2;
cc = upd7810.op60[OP2].cycles_skip;
PC += upd7810.op60[OP2].oplen - 2;
break;
case 0x64:
cc = op64[OP2].cycles_skip;
PC += op64[OP2].oplen - 2;
cc = upd7810.op64[OP2].cycles_skip;
PC += upd7810.op64[OP2].oplen - 2;
break;
case 0x70:
cc = op70[OP2].cycles_skip;
PC += op70[OP2].oplen - 2;
cc = upd7810.op70[OP2].cycles_skip;
PC += upd7810.op70[OP2].oplen - 2;
break;
case 0x74:
cc = op74[OP2].cycles_skip;
PC += op74[OP2].oplen - 2;
cc = upd7810.op74[OP2].cycles_skip;
PC += upd7810.op74[OP2].oplen - 2;
break;
default:
fatalerror("uPD7810 internal error: check cycle counts for main");
}
}
PSW &= ~SK;
upd7810_timers( cc );
upd7810.handle_timers( cc );
change_pc( PCD );
}
else
{
cc = opXX[OP].cycles;
upd7810_timers( cc );
(*opXX[OP].opfunc)();
cc = upd7810.opXX[OP].cycles;
upd7810.handle_timers( cc );
(*upd7810.opXX[OP].opfunc)();
}
upd7810_icount -= cc;
upd7810_take_irq();
@ -2017,3 +2099,75 @@ void upd7807_get_info(UINT32 state, cpuinfo *info)
default: upd7810_get_info(state, info); break;
}
}
void upd7801_get_info(UINT32 state, cpuinfo *info) {
switch( state ) {
case CPUINFO_PTR_RESET: info->reset = upd7801_reset; break;
#ifdef ENABLE_DEBUGGER
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = upd7801_dasm; break;
#endif /* ENABLE_DEBUGGER */
case CPUINFO_STR_NAME: strcpy(info->s, "uPD7801"); break;
default: upd7810_get_info(state, info); break;
}
}
void upd78c05_get_info(UINT32 state, cpuinfo *info ) {
switch ( state ) {
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
case CPUINFO_PTR_RESET: info->reset = upd78c05_reset; break;
#ifdef ENABLE_DEBUGGER
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = upd78c05_dasm; break;
#endif /* ENABLE_DEBUGGER */
case CPUINFO_STR_NAME: strcpy(info->s, "uPD78C05"); break;
/* These registers are not present in the uPD78C05 cpu */
case CPUINFO_STR_REGISTER + UPD7810_A2:
case CPUINFO_STR_REGISTER + UPD7810_V2:
case CPUINFO_STR_REGISTER + UPD7810_EA2:
case CPUINFO_STR_REGISTER + UPD7810_BC2:
case CPUINFO_STR_REGISTER + UPD7810_DE2:
case CPUINFO_STR_REGISTER + UPD7810_HL2:
case CPUINFO_STR_REGISTER + UPD7810_MA:
case CPUINFO_STR_REGISTER + UPD7810_MCC:
case CPUINFO_STR_REGISTER + UPD7810_MC:
case CPUINFO_STR_REGISTER + UPD7810_MM:
case CPUINFO_STR_REGISTER + UPD7810_MF:
case CPUINFO_STR_REGISTER + UPD7810_ETMM:
case CPUINFO_STR_REGISTER + UPD7810_EOM:
case CPUINFO_STR_REGISTER + UPD7810_SML:
case CPUINFO_STR_REGISTER + UPD7810_SMH:
case CPUINFO_STR_REGISTER + UPD7810_ANM:
case CPUINFO_STR_REGISTER + UPD7810_MKH:
case CPUINFO_STR_REGISTER + UPD7810_ZCM:
case CPUINFO_STR_REGISTER + UPD7810_CR0:
case CPUINFO_STR_REGISTER + UPD7810_CR1:
case CPUINFO_STR_REGISTER + UPD7810_CR2:
case CPUINFO_STR_REGISTER + UPD7810_CR3:
case CPUINFO_STR_REGISTER + UPD7810_RXB:
case CPUINFO_STR_REGISTER + UPD7810_TXB:
case CPUINFO_STR_REGISTER + UPD7810_TXD:
case CPUINFO_STR_REGISTER + UPD7810_RXD:
case CPUINFO_STR_REGISTER + UPD7810_SCK:
case CPUINFO_STR_REGISTER + UPD7810_TI:
case CPUINFO_STR_REGISTER + UPD7810_TO:
case CPUINFO_STR_REGISTER + UPD7810_CI:
case CPUINFO_STR_REGISTER + UPD7810_CO0:
case CPUINFO_STR_REGISTER + UPD7810_CO1: break;
default: upd7801_get_info(state, info); break;
}
}
void upd78c06_get_info(UINT32 state, cpuinfo *info ) {
switch ( state ) {
case CPUINFO_PTR_RESET: info->reset = upd78c06_reset; break;
case CPUINFO_STR_NAME: strcpy(info->s, "uPD78C06"); break;
default: upd78c05_get_info(state, info); break;
}
}

View File

@ -11,6 +11,9 @@
// unfortunatly memory configuration differs with internal rom size
typedef enum {
TYPE_7801,
TYPE_78C05,
TYPE_78C06,
TYPE_7810,
TYPE_7810_GAMEMASTER, // a few modifications until internal rom dumped
TYPE_7807
@ -62,8 +65,11 @@ enum {
#define UPD7810_INTF2 1
#define UPD7810_INTFE1 4
extern void upd7810_get_info(UINT32 state, cpuinfo *info);
extern void upd7807_get_info(UINT32 state, cpuinfo *info);
void upd7810_get_info(UINT32 state, cpuinfo *info);
void upd7807_get_info(UINT32 state, cpuinfo *info);
void upd7801_get_info(UINT32 state, cpuinfo *info);
void upd78c05_get_info(UINT32 state, cpuinfo *info);
void upd78c06_get_info(UINT32 state, cpuinfo *info);
typedef struct {
PAIR ppc; /* previous program counter */
@ -144,6 +150,12 @@ typedef struct {
const struct opcode_s *opXX; /* opcode table */
const struct opcode_s *op48;
const struct opcode_s *op4C;
const struct opcode_s *op4D;
const struct opcode_s *op60;
const struct opcode_s *op64;
const struct opcode_s *op70;
const struct opcode_s *op74;
void (*handle_timers)(int cycles);
UPD7810_CONFIG config;
int (*irq_callback)(int irqline);
} UPD7810;
@ -151,6 +163,8 @@ typedef struct {
#ifdef ENABLE_DEBUGGER
offs_t upd7810_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
offs_t upd7807_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
offs_t upd7801_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
offs_t upd78c05_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
#endif
#endif

View File

@ -141,6 +141,9 @@ enum _cpu_type
CPU_ASAP,
CPU_UPD7810,
CPU_UPD7807,
CPU_UPD7801,
CPU_UPD78C05,
CPU_UPD78C06,
CPU_JAGUARGPU,
CPU_JAGUARDSP,
CPU_R3000BE,

View File

@ -113,6 +113,9 @@ void psxcpu_get_info(UINT32 state, cpuinfo *info);
void asap_get_info(UINT32 state, cpuinfo *info);
void upd7810_get_info(UINT32 state, cpuinfo *info);
void upd7807_get_info(UINT32 state, cpuinfo *info);
void upd7801_get_info(UINT32 state, cpuinfo *info);
void upd78c05_get_info(UINT32 state, cpuinfo *info);
void upd78c06_get_info(UINT32 state, cpuinfo *info);
void jaguargpu_get_info(UINT32 state, cpuinfo *info);
void jaguardsp_get_info(UINT32 state, cpuinfo *info);
void r3000be_get_info(UINT32 state, cpuinfo *info);
@ -553,6 +556,11 @@ static const struct
#if (HAS_UPD7807)
{ CPU_UPD7807, upd7807_get_info },
#endif
#if (HAS_UPD7801)
{ CPU_UPD7801, upd7801_get_info },
{ CPU_UPD78C05, upd78c05_get_info },
{ CPU_UPD78C06, upd78c06_get_info },
#endif
#if (HAS_JAGUAR)
{ CPU_JAGUARGPU, jaguargpu_get_info },
{ CPU_JAGUARDSP, jaguardsp_get_info },