mcs48: fix possible missed timer overflow if burn_cycles is larger than 2

This commit is contained in:
hap 2020-08-11 16:02:07 +02:00
parent 96403e68f0
commit 03ea613fd8
4 changed files with 30 additions and 29 deletions

View File

@ -430,7 +430,7 @@ void mcs48_cpu_device::pull_pc_psw()
uint8_t sp = (m_psw - 1) & 0x07;
m_pc = ram_r(8 + 2*sp);
m_pc |= ram_r(9 + 2*sp) << 8;
m_psw = ((m_pc >> 8) & 0xf0) | 0x08 | sp;
m_psw = ((m_pc >> 8) & 0xf0) | sp;
m_pc &= 0xfff;
update_regptr();
}
@ -447,7 +447,7 @@ void mcs48_cpu_device::pull_pc()
m_pc = ram_r(8 + 2*sp);
m_pc |= ram_r(9 + 2*sp) << 8;
m_pc &= 0xfff;
m_psw = (m_psw & 0xf0) | 0x08 | sp;
m_psw = (m_psw & 0xf0) | sp;
}
@ -768,7 +768,7 @@ OPHANDLER( jmp_7 ) { burn_cycles(2); execute_jmp(argument_fetch() | 0x7
OPHANDLER( jmpp_xa ) { burn_cycles(2); m_pc &= 0xf00; m_pc |= program_r(m_pc | m_a); }
OPHANDLER( mov_a_n ) { burn_cycles(2); m_a = argument_fetch(); }
OPHANDLER( mov_a_psw ) { burn_cycles(1); m_a = m_psw; }
OPHANDLER( mov_a_psw ) { burn_cycles(1); m_a = m_psw | 0x08; }
OPHANDLER( mov_a_r0 ) { burn_cycles(1); m_a = R0; }
OPHANDLER( mov_a_r1 ) { burn_cycles(1); m_a = R1; }
OPHANDLER( mov_a_r2 ) { burn_cycles(1); m_a = R2; }
@ -1187,7 +1187,7 @@ void mcs48_cpu_device::device_reset()
{
/* confirmed from reset description */
m_pc = 0;
m_psw = (m_psw & (C_FLAG | A_FLAG)) | 0x08;
m_psw = m_psw & (C_FLAG | A_FLAG);
m_a11 = 0x000;
m_dbbo = 0xff;
bus_w(0xff);
@ -1219,15 +1219,16 @@ void mcs48_cpu_device::device_reset()
check_irqs - check for and process IRQs
-------------------------------------------------*/
int mcs48_cpu_device::check_irqs()
void mcs48_cpu_device::check_irqs()
{
/* if something is in progress, we do nothing */
if (m_irq_in_progress)
return 0;
return;
/* external interrupts take priority */
if ((m_irq_state || (m_sts & STS_IBF) != 0) && m_xirq_enabled)
else if ((m_irq_state || (m_sts & STS_IBF) != 0) && m_xirq_enabled)
{
burn_cycles(2);
m_irq_in_progress = true;
/* transfer to location 0x03 */
@ -1236,12 +1237,12 @@ int mcs48_cpu_device::check_irqs()
/* indicate we took the external IRQ */
standard_irq_callback(0);
return 2;
}
/* timer overflow interrupts follow */
if (m_timer_overflow && m_tirq_enabled)
else if (m_timer_overflow && m_tirq_enabled)
{
burn_cycles(2);
m_irq_in_progress = true;
/* transfer to location 0x07 */
@ -1250,9 +1251,7 @@ int mcs48_cpu_device::check_irqs()
/* timer overflow flip-flop is reset once taken */
m_timer_overflow = false;
return 2;
}
return 0;
}
@ -1266,7 +1265,7 @@ void mcs48_cpu_device::burn_cycles(int count)
if (count == 0)
return;
int timerover = false;
bool timerover = false;
/* if the timer is enabled, accumulate prescaler cycles */
if (m_timecount_enabled & TIMER_ENABLED)
@ -1284,7 +1283,10 @@ void mcs48_cpu_device::burn_cycles(int count)
{
m_t1_history = (m_t1_history << 1) | (test_r(1) & 1);
if ((m_t1_history & 3) == 2)
timerover = (++m_timer == 0);
{
if (++m_timer == 0)
timerover = true;
}
}
/* if timer counter was disabled, adjust icount here (otherwise count is 0) */
@ -1322,7 +1324,7 @@ void mcs48_cpu_device::execute_run()
(this->*m_opcode_table[opcode])();
// check interrupts
burn_cycles(check_irqs());
check_irqs();
} while (m_icount > 0);
}

View File

@ -260,7 +260,7 @@ protected:
void execute_jcc(uint8_t result);
uint8_t p2_mask();
void expander_operation(expander_op operation, uint8_t port);
int check_irqs();
void check_irqs();
void burn_cycles(int count);
void illegal();

View File

@ -17,12 +17,6 @@
DEFINE_DEVICE_TYPE(EF9340_1, ef9340_1_device, "ef9340_1", "Thomson EF9340+EF9341")
static constexpr uint8_t bgr2rgb[8] =
{
0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07
};
ef9340_1_device::ef9340_1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, EF9340_1, tag, owner, clock)
, device_video_interface(mconfig, *this)
@ -64,9 +58,10 @@ void ef9340_1_device::device_start()
save_item(NAME(m_ef9340.Y0));
save_item(NAME(m_ef9340.R));
save_item(NAME(m_ef9340.M));
save_pointer(NAME(m_ef934x_ram_a), 1024);
save_pointer(NAME(m_ef934x_ram_b), 1024);
save_pointer(NAME(m_ef934x_ext_char_ram), 1024);
save_item(NAME(m_ef934x_ram_a));
save_item(NAME(m_ef934x_ram_b));
save_item(NAME(m_ef934x_ext_char_ram));
}
@ -279,6 +274,11 @@ uint8_t ef9340_1_device::ef9341_read( uint8_t command, uint8_t b )
void ef9340_1_device::ef9340_scanline(int vpos)
{
static const uint8_t bgr2rgb[8] =
{
0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07
};
if ( vpos < m_ef9340.max_vpos )
{
int y = vpos - 0;
@ -287,18 +287,15 @@ void ef9340_1_device::ef9340_scanline(int vpos)
if ( y < 10 )
{
// Service row
if ( m_ef9340.R & 0x08 )
{
// Service row is enabled
y_row = 31;
slice = y;
}
else
{
// Service row is disabled
for ( int i = 0; i < 40 * 8; i++ )
{
m_tmp_bitmap.pix16(vpos, 0 + i ) = 24;

View File

@ -264,8 +264,10 @@ const double XTAL::known_xtals[] = {
17'430'000, /* 17.43_MHz_XTAL Videx Videoterm */
17'550'000, /* 17.55_MHz_XTAL HP 264x display clock (50 Hz configuration) */
17'600'000, /* 17.6_MHz_XTAL LSI Octopus */
17'734'470, /* 17.73447_MHz_XTAL (~4x PAL subcarrier) */
17'734'472, /* 17.734472_MHz_XTAL actually ~4x PAL subcarrier */
17'734'470, /* 17.73447_MHz_XTAL 4x PAL subcarrier */
17'734'472, /* 17.734472_MHz_XTAL 4x PAL subcarrier - All of these exist, exact 4x PAL is actually 17'734'475 */
17'734'475, /* 17.734475_MHz_XTAL 4x PAL subcarrier - " */
17'734'476, /* 17.734476_MHz_XTAL 4x PAL subcarrier - " */
17'812'000, /* 17.812_MHz_XTAL Videopac C52 */
17'971'200, /* 17.9712_MHz_XTAL Compucolor II, Hazeltine Esprit III */
18'000'000, /* 18_MHz_XTAL S.A.R, Ikari Warriors 3 */