Improved Z180 timer and HALT processing. This fixes MT03852. [Couriersud]

This commit is contained in:
Couriersud 2010-05-17 21:45:17 +00:00
parent 5c5b6e2cb4
commit 8deddc4cf6

View File

@ -43,6 +43,16 @@
* *
*****************************************************************************/ *****************************************************************************/
/*****************************************************************************
TODO:
- HALT processing is not yet perfect. The manual states that
during HALT, all dma and internal i/o incl. timers continue to
work. Currently, only timers are implemented. Ideally, the
burn_cycles routine would go away and halt processing be
implemented in cpu_execute.
*****************************************************************************/
/***************************************************************************** /*****************************************************************************
Z180 Info: Z180 Info:
@ -122,6 +132,7 @@ struct _z180_state
UINT8 rtemp; UINT8 rtemp;
UINT32 ioltemp; UINT32 ioltemp;
int icount; int icount;
int old_icount; /* for burning cycles */
UINT8 *cc[6]; UINT8 *cc[6];
}; };
@ -1447,7 +1458,16 @@ static void z180_writecontrol(z180_state *cpustate, offs_t port, UINT8 data)
case Z180_TCR: case Z180_TCR:
LOG(("Z180 '%s' TCR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TCR_WMASK)); LOG(("Z180 '%s' TCR wr $%02x ($%02x)\n", cpustate->device->tag(), data, data & Z180_TCR_WMASK));
{
UINT16 old = cpustate->IO_TCR;
/* Force reload on state change */
cpustate->IO_TCR = (cpustate->IO_TCR & ~Z180_TCR_WMASK) | (data & Z180_TCR_WMASK); cpustate->IO_TCR = (cpustate->IO_TCR & ~Z180_TCR_WMASK) | (data & Z180_TCR_WMASK);
if (!(old & Z180_TCR_TDE0) && (cpustate->IO_TCR & Z180_TCR_TDE0))
cpustate->tmdr_value[0] = 0; //cpustate->IO_RLDR0L | (cpustate->IO_RLDR0H << 8);
if (!(old & Z180_TCR_TDE1) && (cpustate->IO_TCR & Z180_TCR_TDE1))
cpustate->tmdr_value[1] = 0; //cpustate->IO_RLDR1L | (cpustate->IO_RLDR1H << 8);
}
break; break;
case Z180_IO11: case Z180_IO11:
@ -2230,6 +2250,9 @@ static CPU_RESET( z180 )
cpustate->IO_OMCR = Z180_OMCR_RESET; cpustate->IO_OMCR = Z180_OMCR_RESET;
cpustate->IO_IOCR = Z180_IOCR_RESET; cpustate->IO_IOCR = Z180_IOCR_RESET;
/* reset old_icount */
cpustate->old_icount = 0;
if (cpustate->daisy) if (cpustate->daisy)
z80daisy_reset(cpustate->daisy); z80daisy_reset(cpustate->daisy);
z180_mmu(cpustate); z180_mmu(cpustate);
@ -2246,23 +2269,25 @@ static int handle_timers(z180_state *cpustate, int current_icount, int previous_
/* Programmable Reload Timer 0 */ /* Programmable Reload Timer 0 */
if(cpustate->IO_TCR & Z180_TCR_TDE0) if(cpustate->IO_TCR & Z180_TCR_TDE0)
{ {
cpustate->tmdr_value[0]--;
if(cpustate->tmdr_value[0] == 0) if(cpustate->tmdr_value[0] == 0)
{ {
cpustate->tmdr_value[0] = cpustate->IO_RLDR0L | (cpustate->IO_RLDR0H << 8); cpustate->tmdr_value[0] = cpustate->IO_RLDR0L | (cpustate->IO_RLDR0H << 8);
cpustate->tif[0] = 1; cpustate->tif[0] = 1;
} }
else
cpustate->tmdr_value[0]--;
} }
/* Programmable Reload Timer 1 */ /* Programmable Reload Timer 1 */
if(cpustate->IO_TCR & Z180_TCR_TDE1) if(cpustate->IO_TCR & Z180_TCR_TDE1)
{ {
cpustate->tmdr_value[1]--;
if(cpustate->tmdr_value[1] == 0) if(cpustate->tmdr_value[1] == 0)
{ {
cpustate->tmdr_value[1] = cpustate->IO_RLDR1L | (cpustate->IO_RLDR1H << 8); cpustate->tmdr_value[1] = cpustate->IO_RLDR1L | (cpustate->IO_RLDR1H << 8);
cpustate->tif[1] = 1; cpustate->tif[1] = 1;
} }
else
cpustate->tmdr_value[1]--;
} }
if((cpustate->IO_TCR & Z180_TCR_TIE0) && cpustate->tif[0]) if((cpustate->IO_TCR & Z180_TCR_TIE0) && cpustate->tif[0])
@ -2312,7 +2337,9 @@ static void check_interrupts(z180_state *cpustate)
static CPU_EXECUTE( z180 ) static CPU_EXECUTE( z180 )
{ {
z180_state *cpustate = get_safe_token(device); z180_state *cpustate = get_safe_token(device);
int old_icount = cycles;
cpustate->old_icount = cycles;
cpustate->icount = cycles; cpustate->icount = cycles;
/* check for NMIs on the way in; they can only be set externally */ /* check for NMIs on the way in; they can only be set externally */
@ -2346,7 +2373,7 @@ again:
debugger_instruction_hook(device, cpustate->_PCD); debugger_instruction_hook(device, cpustate->_PCD);
z180_dma0(cpustate); z180_dma0(cpustate);
old_icount = handle_timers(cpustate, cpustate->icount, old_icount); cpustate->old_icount = handle_timers(cpustate, cpustate->icount, cpustate->old_icount);
} }
else else
{ {
@ -2360,13 +2387,13 @@ again:
cpustate->R++; cpustate->R++;
EXEC_INLINE(op,ROP(cpustate)); EXEC_INLINE(op,ROP(cpustate));
old_icount = handle_timers(cpustate, cpustate->icount, old_icount); cpustate->old_icount = handle_timers(cpustate, cpustate->icount, cpustate->old_icount);
z180_dma0(cpustate); z180_dma0(cpustate);
old_icount = handle_timers(cpustate, cpustate->icount, old_icount); cpustate->old_icount = handle_timers(cpustate, cpustate->icount, cpustate->old_icount);
z180_dma1(cpustate); z180_dma1(cpustate);
old_icount = handle_timers(cpustate, cpustate->icount, old_icount); cpustate->old_icount = handle_timers(cpustate, cpustate->icount, cpustate->old_icount);
/* If DMA is done break out to the faster loop */ /* If DMA is done break out to the faster loop */
if ((cpustate->IO_DSTAT & Z180_DSTAT_DME) != Z180_DSTAT_DME) if ((cpustate->IO_DSTAT & Z180_DSTAT_DME) != Z180_DSTAT_DME)
@ -2386,7 +2413,7 @@ again:
debugger_instruction_hook(device, cpustate->_PCD); debugger_instruction_hook(device, cpustate->_PCD);
cpustate->R++; cpustate->R++;
EXEC_INLINE(op,ROP(cpustate)); EXEC_INLINE(op,ROP(cpustate));
old_icount = handle_timers(cpustate, cpustate->icount, old_icount); cpustate->old_icount = handle_timers(cpustate, cpustate->icount, cpustate->old_icount);
/* If DMA is started go to check the mode */ /* If DMA is started go to check the mode */
if ((cpustate->IO_DSTAT & Z180_DSTAT_DME) == Z180_DSTAT_DME) if ((cpustate->IO_DSTAT & Z180_DSTAT_DME) == Z180_DSTAT_DME)
@ -2394,6 +2421,7 @@ again:
} while( cpustate->icount > 0 ); } while( cpustate->icount > 0 );
} }
//cpustate->old_icount -= cpustate->icount;
return cycles - cpustate->icount; return cycles - cpustate->icount;
} }
@ -2403,12 +2431,13 @@ again:
static CPU_BURN( z180 ) static CPU_BURN( z180 )
{ {
z180_state *cpustate = get_safe_token(device); z180_state *cpustate = get_safe_token(device);
if( cycles > 0 ) while ( (cycles > 0) && cpustate->HALT )
{ {
cpustate->old_icount = handle_timers(cpustate, cpustate->icount, cpustate->old_icount);
/* NOP takes 3 cycles per instruction */ /* NOP takes 3 cycles per instruction */
int n = (cycles + 2) / 3; cpustate->R += 1;
cpustate->R += n; cpustate->icount -= 3;
cpustate->icount -= 3 * n; cycles -= 3;
} }
} }