mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
i186: Peripheral register refinements
- Emulate strange but documented behavior of unaligned accesses and byte writes to internal peripheral registers - Use more official register mnemonics
This commit is contained in:
parent
0fc2e7e152
commit
354656e55b
@ -524,6 +524,16 @@ void i80186_cpu_device::execute_run()
|
||||
m_regs.w[AX] = 0xffff; // FPU not present
|
||||
break;
|
||||
|
||||
case 0xe6: // i_outal
|
||||
write_port_byte_al(fetch());
|
||||
CLK(OUT_IMM8);
|
||||
break;
|
||||
|
||||
case 0xee: // i_outdxal
|
||||
write_port_byte_al(m_regs.w[DX]);
|
||||
CLK(OUT_DX8);
|
||||
break;
|
||||
|
||||
case 0xf2: // i_repne
|
||||
case 0xf3:
|
||||
{
|
||||
@ -577,44 +587,46 @@ void i80186_cpu_device::device_start()
|
||||
state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%05X").noshow();
|
||||
state_add( I8086_HALT, "HALT", m_halt ).mask(1);
|
||||
|
||||
// Most of these mnemonics are not official and only chosen as convenient shorthand.
|
||||
state_add( I80186_RELOC, "RELOC", m_reloc ).formatstr("%04X");
|
||||
// Most of these mnemonics are borrowed from the Intel 80C186EB/80C188EB Microprocessor User's Manual.
|
||||
// (The 80C186EB/80C188EB's peripheral block is mapped incompatibly but mostly functionally analogous.)
|
||||
// The DMA register mnemonics are not official and only chosen as convenient shorthand.
|
||||
state_add( I80186_RELREG, "RELREG", m_reloc ).formatstr("%04X");
|
||||
state_add( I80186_UMCS, "UMCS", m_mem.upper ).formatstr("%04X");
|
||||
state_add( I80186_LMCS, "LMCS", m_mem.lower ).formatstr("%04X");
|
||||
state_add( I80186_PACS, "PACS", m_mem.peripheral ).formatstr("%04X");
|
||||
state_add( I80186_MMCS, "MMCS", m_mem.middle ).formatstr("%04X");
|
||||
state_add( I80186_MPCS, "MPCS", m_mem.middle_size ).formatstr("%04X");
|
||||
state_add( I80186_DMA_SP + 0, "DMA0_SP", m_dma[0].source ).formatstr("%05X").mask(0xfffff);
|
||||
state_add( I80186_DMA_DP + 0, "DMA0_DP", m_dma[0].dest ).formatstr("%05X").mask(0xfffff);
|
||||
state_add( I80186_DMA_TC + 0, "DMA0_TC", m_dma[0].count ).formatstr("%04X");
|
||||
state_add( I80186_DMA_CR + 0, "DMA0_CR", m_dma[0].control ).formatstr("%04X");
|
||||
state_add( I80186_DMA_SP + 1, "DMA1_SP", m_dma[1].source ).formatstr("%05X").mask(0xfffff);
|
||||
state_add( I80186_DMA_DP + 1, "DMA1_DP", m_dma[1].dest ).formatstr("%05X").mask(0xfffff);
|
||||
state_add( I80186_DMA_TC + 1, "DMA1_TC", m_dma[1].count ).formatstr("%04X");
|
||||
state_add( I80186_DMA_CR + 1, "DMA1_CR", m_dma[1].control ).formatstr("%04X");
|
||||
state_add( I80186_T_COUNT + 0, "T0_COUNT", m_timer[0].count ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_A + 0, "T0_MAX_A", m_timer[0].maxA ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_B + 0, "T0_MAX_B", m_timer[0].maxB ).formatstr("%04X");
|
||||
state_add( I80186_T_CONTROL + 0, "T0_CONTROL", m_timer[0].control ).formatstr("%04X");
|
||||
state_add( I80186_T_COUNT + 1, "T1_COUNT", m_timer[1].count ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_A + 1, "T1_MAX_A", m_timer[1].maxA ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_B + 1, "T1_MAX_B", m_timer[1].maxB ).formatstr("%04X");
|
||||
state_add( I80186_T_CONTROL + 1, "T1_CONTROL", m_timer[1].control ).formatstr("%04X");
|
||||
state_add( I80186_T_COUNT + 2, "T2_COUNT", m_timer[2].count ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_A + 2, "T2_MAX", m_timer[2].maxA ).formatstr("%04X");
|
||||
state_add( I80186_T_CONTROL + 2, "T2_CONTROL", m_timer[2].control ).formatstr("%04X");
|
||||
state_add( I80186_ISR, "ISR", m_intr.in_service ).formatstr("%04X");
|
||||
state_add( I80186_IRR, "IRR", m_intr.request ).formatstr("%04X");
|
||||
state_add( I80186_PMR, "PMR", m_intr.priority_mask ).formatstr("%04X");
|
||||
state_add( I80186_ICSR, "ICSR", m_intr.status ).formatstr("%04X");
|
||||
state_add( I80186_TMRCR, "TMRCR", m_intr.timer ).formatstr("%04X");
|
||||
state_add( I80186_D0CR, "D0CR", m_intr.dma[0] ).formatstr("%04X");
|
||||
state_add( I80186_D1CR, "D1CR", m_intr.dma[1] ).formatstr("%04X");
|
||||
state_add( I80186_I0CR, "I0CR", m_intr.ext[0] ).formatstr("%04X");
|
||||
state_add( I80186_I1CR, "I1CR", m_intr.ext[1] ).formatstr("%04X");
|
||||
state_add( I80186_I2CR, "I2CR", m_intr.ext[2] ).formatstr("%04X");
|
||||
state_add( I80186_I3CR, "I3CR", m_intr.ext[3] ).formatstr("%04X");
|
||||
state_add( I80186_POLL, "POLL", m_intr.poll_status ).formatstr("%04X");
|
||||
state_add( I80186_DMA_SP + 0, "DMA0SP", m_dma[0].source ).formatstr("%05X").mask(0xfffff);
|
||||
state_add( I80186_DMA_DP + 0, "DMA0DP", m_dma[0].dest ).formatstr("%05X").mask(0xfffff);
|
||||
state_add( I80186_DMA_TC + 0, "DMA0TC", m_dma[0].count ).formatstr("%04X");
|
||||
state_add( I80186_DMA_CR + 0, "DMA0CR", m_dma[0].control ).formatstr("%04X");
|
||||
state_add( I80186_DMA_SP + 1, "DMA1SP", m_dma[1].source ).formatstr("%05X").mask(0xfffff);
|
||||
state_add( I80186_DMA_DP + 1, "DMA1DP", m_dma[1].dest ).formatstr("%05X").mask(0xfffff);
|
||||
state_add( I80186_DMA_TC + 1, "DMA1TC", m_dma[1].count ).formatstr("%04X");
|
||||
state_add( I80186_DMA_CR + 1, "DMA1CR", m_dma[1].control ).formatstr("%04X");
|
||||
state_add( I80186_T_COUNT + 0, "T0CNT", m_timer[0].count ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_A + 0, "T0CMPA", m_timer[0].maxA ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_B + 0, "T0CMPB", m_timer[0].maxB ).formatstr("%04X");
|
||||
state_add( I80186_T_CONTROL + 0, "T0CON", m_timer[0].control ).formatstr("%04X");
|
||||
state_add( I80186_T_COUNT + 1, "T1CNT", m_timer[1].count ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_A + 1, "T1CMPA", m_timer[1].maxA ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_B + 1, "T1CMPB", m_timer[1].maxB ).formatstr("%04X");
|
||||
state_add( I80186_T_CONTROL + 1, "T1CON", m_timer[1].control ).formatstr("%04X");
|
||||
state_add( I80186_T_COUNT + 2, "T2CNT", m_timer[2].count ).formatstr("%04X");
|
||||
state_add( I80186_T_MAX_A + 2, "T2CMPA", m_timer[2].maxA ).formatstr("%04X");
|
||||
state_add( I80186_T_CONTROL + 2, "T2CON", m_timer[2].control ).formatstr("%04X");
|
||||
state_add( I80186_INSERV, "INSERV", m_intr.in_service ).formatstr("%04X");
|
||||
state_add( I80186_REQST, "REQST", m_intr.request ).formatstr("%04X");
|
||||
state_add( I80186_PRIMSK, "PRIMSK", m_intr.priority_mask ).formatstr("%04X");
|
||||
state_add( I80186_INTSTS, "INTSTS", m_intr.status ).formatstr("%04X");
|
||||
state_add( I80186_TCUCON, "TCUCON", m_intr.timer ).formatstr("%04X");
|
||||
state_add( I80186_D0CON, "D0CON", m_intr.dma[0] ).formatstr("%04X");
|
||||
state_add( I80186_D1CON, "D1CON", m_intr.dma[1] ).formatstr("%04X");
|
||||
state_add( I80186_I0CON, "I0CON", m_intr.ext[0] ).formatstr("%04X");
|
||||
state_add( I80186_I1CON, "I1CON", m_intr.ext[1] ).formatstr("%04X");
|
||||
state_add( I80186_I2CON, "I2CON", m_intr.ext[2] ).formatstr("%04X");
|
||||
state_add( I80186_I3CON, "I3CON", m_intr.ext[3] ).formatstr("%04X");
|
||||
state_add( I80186_POLLSTS, "POLLSTS", m_intr.poll_status ).formatstr("%04X");
|
||||
|
||||
// register for savestates
|
||||
save_item(NAME(m_timer[0].control));
|
||||
@ -718,8 +730,10 @@ uint8_t i80186_cpu_device::read_port_byte(uint16_t port)
|
||||
{
|
||||
if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff))
|
||||
{
|
||||
uint16_t ret = internal_port_r(*m_io, (port >> 1) & 0x7f, (port & 1) ? 0xff00 : 0x00ff);
|
||||
return (port & 1) ? (ret >> 8) : (ret & 0xff);
|
||||
if(port & 1)
|
||||
return internal_port_r(*m_io, (port >> 1) & 0x7f, 0xff00) >> 8;
|
||||
else
|
||||
return internal_port_r(*m_io, (port >> 1) & 0x7f, 0x00ff) & 0xff;
|
||||
}
|
||||
return m_io->read_byte(port);
|
||||
}
|
||||
@ -728,12 +742,11 @@ uint16_t i80186_cpu_device::read_port_word(uint16_t port)
|
||||
{
|
||||
if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff))
|
||||
{
|
||||
// Unaligned reads from the internal bus are swapped rather than split
|
||||
if(port & 1)
|
||||
{
|
||||
uint8_t low = read_port_byte(port);
|
||||
return read_port_byte(port + 1) << 8 | low;
|
||||
}
|
||||
return internal_port_r(*m_io, (port >> 1) & 0x7f);
|
||||
return swapendian_int16(internal_port_r(*m_io, (port >> 1) & 0x7f));
|
||||
else
|
||||
return internal_port_r(*m_io, (port >> 1) & 0x7f);
|
||||
}
|
||||
return m_io->read_word_unaligned(port);
|
||||
}
|
||||
@ -741,20 +754,37 @@ uint16_t i80186_cpu_device::read_port_word(uint16_t port)
|
||||
void i80186_cpu_device::write_port_byte(uint16_t port, uint8_t data)
|
||||
{
|
||||
if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff))
|
||||
internal_port_w(*m_io, (port >> 1) & 0x7f, (port & 1) ? (data << 8) : data, (port & 1) ? 0xff00 : 0x00ff);
|
||||
{
|
||||
if(port & 1)
|
||||
internal_port_w(*m_io, (port >> 1) & 0x7f, data << 8, 0xff00);
|
||||
else
|
||||
internal_port_w(*m_io, (port >> 1) & 0x7f, data, 0x00ff);
|
||||
}
|
||||
else
|
||||
m_io->write_byte(port, data);
|
||||
}
|
||||
|
||||
void i80186_cpu_device::write_port_byte_al(uint16_t port)
|
||||
{
|
||||
if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff))
|
||||
{
|
||||
// Both AH and AL are written onto the internal bus
|
||||
if(port & 1)
|
||||
internal_port_w(*m_io, (port >> 1) & 0x7f, swapendian_int16(m_regs.w[AX]), 0xff00);
|
||||
else
|
||||
internal_port_w(*m_io, (port >> 1) & 0x7f, m_regs.w[AX], 0x00ff);
|
||||
}
|
||||
else
|
||||
m_io->write_byte(port, m_regs.w[AL]);
|
||||
}
|
||||
|
||||
void i80186_cpu_device::write_port_word(uint16_t port, uint16_t data)
|
||||
{
|
||||
if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff))
|
||||
{
|
||||
// Unaligned writes to the internal bus are swapped rather than split
|
||||
if(port & 1)
|
||||
{
|
||||
write_port_byte(port, data & 0xff);
|
||||
write_port_byte(port + 1, data >> 8);
|
||||
}
|
||||
internal_port_w(*m_io, (port >> 1) & 0x7f, swapendian_int16(data));
|
||||
else
|
||||
internal_port_w(*m_io, (port >> 1) & 0x7f, data);
|
||||
}
|
||||
@ -776,12 +806,11 @@ uint16_t i80186_cpu_device::read_word(uint32_t addr)
|
||||
{
|
||||
if((m_reloc & 0x1000) && (addr >> 8) == (m_reloc & 0xfff))
|
||||
{
|
||||
// Unaligned reads from the internal bus are swapped rather than split
|
||||
if(addr & 1)
|
||||
{
|
||||
uint8_t low = read_byte(addr);
|
||||
return read_byte(addr + 1) << 8 | low;
|
||||
}
|
||||
return internal_port_r(*m_program, (addr >> 1) & 0x7f);
|
||||
return swapendian_int16(internal_port_r(*m_program, (addr >> 1) & 0x7f));
|
||||
else
|
||||
return internal_port_r(*m_program, (addr >> 1) & 0x7f);
|
||||
}
|
||||
return m_program->read_word_unaligned(addr);
|
||||
}
|
||||
@ -798,11 +827,9 @@ void i80186_cpu_device::write_word(uint32_t addr, uint16_t data)
|
||||
{
|
||||
if((m_reloc & 0x1000) && (addr >> 8) == (m_reloc & 0xfff))
|
||||
{
|
||||
// Unaligned writes from the internal bus are swapped rather than split
|
||||
if(addr & 1)
|
||||
{
|
||||
write_byte(addr, data & 0xff);
|
||||
write_byte(addr + 1, data >> 8);
|
||||
}
|
||||
internal_port_w(*m_program, (addr >> 1) & 0x7f, swapendian_int16(data));
|
||||
else
|
||||
internal_port_w(*m_program, (addr >> 1) & 0x7f, data);
|
||||
}
|
||||
@ -1809,9 +1836,9 @@ WRITE16_MEMBER(i80186_cpu_device::internal_port_w)
|
||||
break;
|
||||
|
||||
case 0x7f:
|
||||
// 80188 byte output to this port is *not* masked!
|
||||
if (LOG_PORTS) logerror("%05X:80186 relocation register = %04X\n", m_pc, data);
|
||||
m_reloc = data;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
I80186_RELOC = I8086_HALT + 1,
|
||||
I80186_RELREG = I8086_HALT + 1,
|
||||
I80186_UMCS, I80186_LMCS, I80186_PACS, I80186_MMCS, I80186_MPCS,
|
||||
I80186_DMA_SP,
|
||||
I80186_DMA_DP = I80186_DMA_SP + 2,
|
||||
@ -47,11 +47,11 @@ protected:
|
||||
I80186_T_MAX_A = I80186_T_COUNT + 3,
|
||||
I80186_T_MAX_B = I80186_T_MAX_A + 3,
|
||||
I80186_T_CONTROL = I80186_T_MAX_B + 2,
|
||||
I80186_ISR = I80186_T_CONTROL + 3,
|
||||
I80186_IRR, I80186_PMR, I80186_ICSR,
|
||||
I80186_TMRCR, I80186_D0CR, I80186_D1CR,
|
||||
I80186_I0CR, I80186_I1CR, I80186_I2CR, I80186_I3CR,
|
||||
I80186_POLL
|
||||
I80186_INSERV = I80186_T_CONTROL + 3,
|
||||
I80186_REQST, I80186_PRIMSK, I80186_INTSTS,
|
||||
I80186_TCUCON, I80186_D0CON, I80186_D1CON,
|
||||
I80186_I0CON, I80186_I1CON, I80186_I2CON, I80186_I3CON,
|
||||
I80186_POLLSTS
|
||||
};
|
||||
|
||||
i80186_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int data_bus_size);
|
||||
@ -70,6 +70,7 @@ protected:
|
||||
virtual uint8_t read_port_byte(uint16_t port) override;
|
||||
virtual uint16_t read_port_word(uint16_t port) override;
|
||||
virtual void write_port_byte(uint16_t port, uint8_t data) override;
|
||||
void write_port_byte_al(uint16_t port);
|
||||
virtual void write_port_word(uint16_t port, uint16_t data) override;
|
||||
virtual uint8_t read_byte(uint32_t addr) override;
|
||||
virtual uint16_t read_word(uint32_t addr) override;
|
||||
|
@ -3,14 +3,13 @@
|
||||
/* BGT Fruit Machines
|
||||
BGT (British Gaming Technology) were a small Spanish company
|
||||
|
||||
x86 based, not sure exactly what CPU tho
|
||||
x86 based (186/188 or equivalent)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/nec/nec.h"
|
||||
#include "cpu/i86/i86.h"
|
||||
#include "cpu/i86/i186.h"
|
||||
|
||||
|
||||
class bgt_state : public driver_device
|
||||
@ -51,7 +50,7 @@ INPUT_PORTS_END
|
||||
|
||||
void bgt_state::bgt(machine_config &config)
|
||||
{
|
||||
V30(config, m_maincpu, 12000000); // ? unknown CPU.. definitely x86 based tho
|
||||
I80186(config, m_maincpu, 12000000); // ?
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &bgt_state::bgt_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &bgt_state::bgt_io);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user