mirror of
https://github.com/holub/mame
synced 2025-04-23 08:49:55 +03:00
v25: Add address space for internal data area and SFRs
This commit is contained in:
parent
a2e7f4f5f6
commit
6141cf5b7a
@ -50,11 +50,12 @@ DEFINE_DEVICE_TYPE(V25, v25_device, "v25", "NEC V25")
|
||||
DEFINE_DEVICE_TYPE(V35, v35_device, "v35", "NEC V35")
|
||||
|
||||
|
||||
v25_common_device::v25_common_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is_16bit, offs_t fetch_xor, uint8_t prefetch_size, uint8_t prefetch_cycles, uint32_t chip_type)
|
||||
v25_common_device::v25_common_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is_16bit, uint8_t prefetch_size, uint8_t prefetch_cycles, uint32_t chip_type)
|
||||
: cpu_device(mconfig, type, tag, owner, clock)
|
||||
, m_program_config("program", ENDIANNESS_LITTLE, is_16bit ? 16 : 8, 20, 0)
|
||||
, m_data_config("data", ENDIANNESS_LITTLE, 16, 9, 0, address_map_constructor(FUNC(v25_common_device::ida_sfr_map), this))
|
||||
, m_io_config("io", ENDIANNESS_LITTLE, is_16bit ? 16 : 8, 16, 0)
|
||||
, m_fetch_xor(fetch_xor)
|
||||
, m_internal_ram(*this, "internal_ram")
|
||||
, m_PCK(8)
|
||||
, m_pt_in(*this)
|
||||
, m_p0_in(*this)
|
||||
@ -72,13 +73,13 @@ v25_common_device::v25_common_device(const machine_config &mconfig, device_type
|
||||
|
||||
|
||||
v25_device::v25_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: v25_common_device(mconfig, V25, tag, owner, clock, false, 0, 4, 4, V20_TYPE)
|
||||
: v25_common_device(mconfig, V25, tag, owner, clock, false, 4, 4, V20_TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
v35_device::v35_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: v25_common_device(mconfig, V35, tag, owner, clock, true, BYTE_XOR_LE(0), 6, 2, V30_TYPE)
|
||||
: v25_common_device(mconfig, V35, tag, owner, clock, true, 6, 2, V30_TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
@ -86,6 +87,7 @@ device_memory_interface::space_config_vector v25_common_device::memory_space_con
|
||||
{
|
||||
return space_config_vector {
|
||||
std::make_pair(AS_PROGRAM, &m_program_config),
|
||||
std::make_pair(AS_DATA, &m_data_config),
|
||||
std::make_pair(AS_IO, &m_io_config)
|
||||
};
|
||||
}
|
||||
@ -177,8 +179,6 @@ uint8_t v25_common_device::fetchop()
|
||||
|
||||
void v25_common_device::device_reset()
|
||||
{
|
||||
attotime time;
|
||||
|
||||
m_ip = 0;
|
||||
m_IBRK = 1;
|
||||
m_F0 = 0;
|
||||
@ -216,10 +216,12 @@ void v25_common_device::device_reset()
|
||||
m_RAMEN = 1;
|
||||
m_TB = 20;
|
||||
m_PCK = 8;
|
||||
m_IDB = 0xFFE00;
|
||||
m_RFM = 0xfc;
|
||||
m_WTC = 0xffff;
|
||||
m_IDB = 0xffe00;
|
||||
|
||||
int tmp = m_PCK << m_TB;
|
||||
time = attotime::from_hz(unscaled_clock()) * tmp;
|
||||
unsigned tmp = m_PCK << m_TB;
|
||||
attotime time = clocks_to_attotime(tmp);
|
||||
m_timers[3]->adjust(time, INTTB, time);
|
||||
|
||||
m_timers[0]->adjust(attotime::never);
|
||||
@ -462,7 +464,6 @@ void v25_common_device::device_start()
|
||||
for (i = 0; i < 4; i++)
|
||||
m_timers[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(v25_common_device::v25_timer_callback),this));
|
||||
|
||||
save_item(NAME(m_ram.w));
|
||||
save_item(NAME(m_intp_state));
|
||||
|
||||
save_item(NAME(m_ip));
|
||||
@ -506,6 +507,8 @@ void v25_common_device::device_start()
|
||||
save_item(NAME(m_RAMEN));
|
||||
save_item(NAME(m_TB));
|
||||
save_item(NAME(m_PCK));
|
||||
save_item(NAME(m_RFM));
|
||||
save_item(NAME(m_WTC));
|
||||
save_item(NAME(m_IDB));
|
||||
save_item(NAME(m_prefetch_count));
|
||||
save_item(NAME(m_prefetch_reset));
|
||||
@ -518,6 +521,7 @@ void v25_common_device::device_start()
|
||||
auto cache = m_program->cache<1, 0, ENDIANNESS_LITTLE>();
|
||||
m_dr8 = [cache](offs_t address) -> u8 { return cache->read_byte(address); };
|
||||
}
|
||||
m_data = &space(AS_DATA);
|
||||
m_io = &space(AS_IO);
|
||||
|
||||
m_pt_in.resolve_safe(0xff);
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
|
||||
protected:
|
||||
// construction/destruction
|
||||
v25_common_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is_16bit, offs_t fetch_xor, uint8_t prefetch_size, uint8_t prefetch_cycles, uint32_t chip_type);
|
||||
v25_common_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is_16bit, uint8_t prefetch_size, uint8_t prefetch_cycles, uint32_t chip_type);
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
@ -105,17 +105,11 @@ protected:
|
||||
|
||||
private:
|
||||
address_space_config m_program_config;
|
||||
address_space_config m_data_config;
|
||||
address_space_config m_io_config;
|
||||
|
||||
/* internal RAM and register banks */
|
||||
union internalram
|
||||
{
|
||||
uint16_t w[128];
|
||||
uint8_t b[256];
|
||||
};
|
||||
|
||||
internalram m_ram;
|
||||
offs_t m_fetch_xor;
|
||||
required_shared_ptr<uint16_t> m_internal_ram;
|
||||
|
||||
uint16_t m_ip;
|
||||
|
||||
@ -146,10 +140,13 @@ private:
|
||||
|
||||
/* system control */
|
||||
uint8_t m_RAMEN, m_TB, m_PCK; /* PRC register */
|
||||
uint8_t m_RFM;
|
||||
uint16_t m_WTC;
|
||||
uint32_t m_IDB;
|
||||
|
||||
address_space *m_program;
|
||||
std::function<u8 (offs_t address)> m_dr8;
|
||||
address_space *m_data;
|
||||
address_space *m_io;
|
||||
int m_icount;
|
||||
|
||||
@ -194,12 +191,60 @@ private:
|
||||
void nec_bankswitch(unsigned bank_num);
|
||||
void nec_trap();
|
||||
void external_int();
|
||||
|
||||
void ida_sfr_map(address_map &map);
|
||||
uint8_t read_irqcontrol(int /*INTSOURCES*/ source, uint8_t priority);
|
||||
uint8_t read_sfr(unsigned o);
|
||||
uint16_t read_sfr_word(unsigned o);
|
||||
void write_irqcontrol(int /*INTSOURCES*/ source, uint8_t d);
|
||||
void write_sfr(unsigned o, uint8_t d);
|
||||
void write_sfr_word(unsigned o, uint16_t d);
|
||||
uint8_t p0_r();
|
||||
void p0_w(uint8_t d);
|
||||
void pm0_w(uint8_t d);
|
||||
void pmc0_w(uint8_t d);
|
||||
uint8_t p1_r();
|
||||
void p1_w(uint8_t d);
|
||||
void pm1_w(uint8_t d);
|
||||
void pmc1_w(uint8_t d);
|
||||
uint8_t p2_r();
|
||||
void p2_w(uint8_t d);
|
||||
void pm2_w(uint8_t d);
|
||||
void pmc2_w(uint8_t d);
|
||||
uint8_t pt_r();
|
||||
void pmt_w(uint8_t d);
|
||||
uint8_t exic0_r();
|
||||
void exic0_w(uint8_t d);
|
||||
uint8_t exic1_r();
|
||||
void exic1_w(uint8_t d);
|
||||
uint8_t exic2_r();
|
||||
void exic2_w(uint8_t d);
|
||||
uint16_t tm0_r();
|
||||
void tm0_w(uint16_t d);
|
||||
uint16_t md0_r();
|
||||
void md0_w(uint16_t d);
|
||||
uint16_t tm1_r();
|
||||
void tm1_w(uint16_t d);
|
||||
uint16_t md1_r();
|
||||
void md1_w(uint16_t d);
|
||||
void tmc0_w(uint8_t d);
|
||||
void tmc1_w(uint8_t d);
|
||||
uint8_t tmic0_r();
|
||||
void tmic0_w(uint8_t d);
|
||||
uint8_t tmic1_r();
|
||||
void tmic1_w(uint8_t d);
|
||||
uint8_t tmic2_r();
|
||||
void tmic2_w(uint8_t d);
|
||||
uint8_t rfm_r();
|
||||
void rfm_w(uint8_t d);
|
||||
uint16_t wtc_r();
|
||||
void wtc_w(offs_t a, uint16_t d, uint16_t m);
|
||||
uint8_t flag_r();
|
||||
void flag_w(uint8_t d);
|
||||
uint8_t prc_r();
|
||||
void prc_w(uint8_t d);
|
||||
uint8_t tbic_r();
|
||||
void tbic_w(uint8_t d);
|
||||
uint8_t irqs_r();
|
||||
uint8_t ispr_r();
|
||||
uint8_t idb_r();
|
||||
void idb_w(uint8_t d);
|
||||
uint8_t v25_read_byte(unsigned a);
|
||||
uint16_t v25_read_word(unsigned a);
|
||||
void v25_write_byte(unsigned a, uint8_t d);
|
||||
|
@ -26,13 +26,13 @@
|
||||
|
||||
#define MOVSPA \
|
||||
tmp = (Wreg(PSW_SAVE) & 0x7000) >> 8; \
|
||||
Sreg(SS) = m_ram.w[tmp+SS]; \
|
||||
Wreg(SP) = m_ram.w[tmp+SP]
|
||||
Sreg(SS) = m_internal_ram[tmp+SS]; \
|
||||
Wreg(SP) = m_internal_ram[tmp+SP]
|
||||
|
||||
#define MOVSPB \
|
||||
tmp <<= 4; \
|
||||
m_ram.w[tmp+SS] = Sreg(SS); \
|
||||
m_ram.w[tmp+SP] = Wreg(SP)
|
||||
m_internal_ram[tmp+SS] = Sreg(SS); \
|
||||
m_internal_ram[tmp+SP] = Wreg(SP)
|
||||
|
||||
#define FINT \
|
||||
for(tmp = 1; tmp < 0x100; tmp <<= 1) { \
|
||||
|
@ -93,9 +93,9 @@ enum BREGS {
|
||||
|
||||
#define SetRB(x) do { m_RBW = (x) << 4; m_RBB = (x) << 5; } while (0)
|
||||
|
||||
#define Sreg(x) m_ram.w[m_RBW + (x)]
|
||||
#define Wreg(x) m_ram.w[m_RBW + (x)]
|
||||
#define Breg(x) m_ram.b[m_RBB + (x)]
|
||||
#define Sreg(x) m_internal_ram[m_RBW + (x)]
|
||||
#define Wreg(x) m_internal_ram[m_RBW + (x)]
|
||||
#define Breg(x) reinterpret_cast<uint8_t *>(&m_internal_ram[0])[m_RBB + (x)]
|
||||
|
||||
#define PC() ((Sreg(PS)<<4)+m_ip)
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
// copyright-holders:Bryan McPhail, Alex W. Jackson
|
||||
/****************************************************************************
|
||||
|
||||
NEC V25/V35 special function registers and internal ram access
|
||||
NEC V25/V35 special function registers and internal data area access
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
@ -10,6 +10,42 @@
|
||||
#include "v25.h"
|
||||
#include "v25priv.h"
|
||||
|
||||
void v25_common_device::ida_sfr_map(address_map &map)
|
||||
{
|
||||
map(0x000, 0x0ff).ram().share("internal_ram");
|
||||
map(0x100, 0x100).rw(FUNC(v25_common_device::p0_r), FUNC(v25_common_device::p0_w));
|
||||
map(0x101, 0x101).w(FUNC(v25_common_device::pm0_w));
|
||||
map(0x102, 0x102).w(FUNC(v25_common_device::pmc0_w));
|
||||
map(0x108, 0x108).rw(FUNC(v25_common_device::p1_r), FUNC(v25_common_device::p1_w));
|
||||
map(0x109, 0x109).w(FUNC(v25_common_device::pm1_w));
|
||||
map(0x10a, 0x10a).w(FUNC(v25_common_device::pmc1_w));
|
||||
map(0x110, 0x110).rw(FUNC(v25_common_device::p2_r), FUNC(v25_common_device::p2_w));
|
||||
map(0x111, 0x111).w(FUNC(v25_common_device::pm2_w));
|
||||
map(0x112, 0x112).w(FUNC(v25_common_device::pmc2_w));
|
||||
map(0x138, 0x138).r(FUNC(v25_common_device::pt_r));
|
||||
map(0x13b, 0x13b).w(FUNC(v25_common_device::pmt_w));
|
||||
map(0x14c, 0x14c).rw(FUNC(v25_common_device::exic0_r), FUNC(v25_common_device::exic0_w));
|
||||
map(0x14d, 0x14d).rw(FUNC(v25_common_device::exic1_r), FUNC(v25_common_device::exic1_w));
|
||||
map(0x14e, 0x14e).rw(FUNC(v25_common_device::exic2_r), FUNC(v25_common_device::exic2_w));
|
||||
map(0x180, 0x181).rw(FUNC(v25_common_device::tm0_r), FUNC(v25_common_device::tm0_w));
|
||||
map(0x182, 0x183).rw(FUNC(v25_common_device::md0_r), FUNC(v25_common_device::md0_w));
|
||||
map(0x188, 0x189).rw(FUNC(v25_common_device::tm1_r), FUNC(v25_common_device::tm1_w));
|
||||
map(0x18a, 0x18b).rw(FUNC(v25_common_device::md1_r), FUNC(v25_common_device::md1_w));
|
||||
map(0x190, 0x190).w(FUNC(v25_common_device::tmc0_w));
|
||||
map(0x191, 0x191).w(FUNC(v25_common_device::tmc1_w));
|
||||
map(0x19c, 0x19c).rw(FUNC(v25_common_device::tmic0_r), FUNC(v25_common_device::tmic0_w));
|
||||
map(0x19d, 0x19d).rw(FUNC(v25_common_device::tmic1_r), FUNC(v25_common_device::tmic1_w));
|
||||
map(0x19e, 0x19e).rw(FUNC(v25_common_device::tmic2_r), FUNC(v25_common_device::tmic2_w));
|
||||
map(0x1e1, 0x1e1).rw(FUNC(v25_common_device::rfm_r), FUNC(v25_common_device::rfm_w));
|
||||
map(0x1e8, 0x1e9).rw(FUNC(v25_common_device::wtc_r), FUNC(v25_common_device::wtc_w));
|
||||
map(0x1ea, 0x1ea).rw(FUNC(v25_common_device::flag_r), FUNC(v25_common_device::flag_w));
|
||||
map(0x1eb, 0x1eb).rw(FUNC(v25_common_device::prc_r), FUNC(v25_common_device::prc_w));
|
||||
map(0x1ec, 0x1ec).rw(FUNC(v25_common_device::tbic_r), FUNC(v25_common_device::tbic_w));
|
||||
map(0x1ef, 0x1ef).r(FUNC(v25_common_device::irqs_r));
|
||||
map(0x1fc, 0x1fc).r(FUNC(v25_common_device::ispr_r));
|
||||
map(0x1ff, 0x1ff).rw(FUNC(v25_common_device::idb_r), FUNC(v25_common_device::idb_w));
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::read_irqcontrol(int /*INTSOURCES*/ source, uint8_t priority)
|
||||
{
|
||||
return (((m_pending_irq & source) ? 0x80 : 0x00)
|
||||
@ -18,386 +54,436 @@ uint8_t v25_common_device::read_irqcontrol(int /*INTSOURCES*/ source, uint8_t pr
|
||||
| priority);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::read_sfr(unsigned o)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
switch(o)
|
||||
{
|
||||
case 0x00: /* P0 */
|
||||
ret = m_p0_in();
|
||||
break;
|
||||
case 0x08: /* P1 */
|
||||
/* P1 is combined with the interrupt lines */
|
||||
ret = ((m_p1_in() & 0xF0)
|
||||
| (m_nmi_state ? 0x00 : 0x01)
|
||||
| (m_intp_state[0] ? 0x00 : 0x02)
|
||||
| (m_intp_state[1] ? 0x00 : 0x04)
|
||||
| (m_intp_state[2] ? 0x00 : 0x08));
|
||||
break;
|
||||
case 0x10: /* P2 */
|
||||
ret = m_p2_in();
|
||||
break;
|
||||
case 0x38: /* PT */
|
||||
ret = m_pt_in();
|
||||
break;
|
||||
case 0x4C: /* EXIC0 */
|
||||
ret = read_irqcontrol(INTP0, m_priority_intp);
|
||||
break;
|
||||
case 0x4D: /* EXIC1 */
|
||||
ret = read_irqcontrol(INTP1, 7);
|
||||
break;
|
||||
case 0x4E: /* EXIC2 */
|
||||
ret = read_irqcontrol(INTP2, 7);
|
||||
break;
|
||||
case 0x9C: /* TMIC0 */
|
||||
ret = read_irqcontrol(INTTU0, m_priority_inttu);
|
||||
break;
|
||||
case 0x9D: /* TMIC1 */
|
||||
ret = read_irqcontrol(INTTU1, 7);
|
||||
break;
|
||||
case 0x9E: /* TMIC2 */
|
||||
ret = read_irqcontrol(INTTU2, 7);
|
||||
break;
|
||||
case 0xEA: /* FLAG */
|
||||
ret = ((m_F0 << 3) | (m_F1 << 5));
|
||||
break;
|
||||
case 0xEB: /* PRC */
|
||||
ret = (m_RAMEN ? 0x40 : 0);
|
||||
switch (m_TB)
|
||||
{
|
||||
case 10:
|
||||
break;
|
||||
case 13:
|
||||
ret |= 0x04;
|
||||
break;
|
||||
case 16:
|
||||
ret |= 0x08;
|
||||
break;
|
||||
case 20:
|
||||
ret |= 0x0C;
|
||||
break;
|
||||
}
|
||||
switch (m_PCK)
|
||||
{
|
||||
case 2:
|
||||
break;
|
||||
case 4:
|
||||
ret |= 0x01;
|
||||
break;
|
||||
case 8:
|
||||
ret |= 0x02;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xEC: /* TBIC */
|
||||
ret = read_irqcontrol(INTTB, 7);
|
||||
break;
|
||||
case 0xEF: /* IRQS */
|
||||
ret = m_IRQS;
|
||||
break;
|
||||
case 0xFC: /* ISPR */
|
||||
ret = m_ISPR;
|
||||
break;
|
||||
case 0xFF: /* IDB */
|
||||
ret = (m_IDB >> 12);
|
||||
break;
|
||||
default:
|
||||
logerror("%06x: Read from special function register %02x\n",PC(),o);
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t v25_common_device::read_sfr_word(unsigned o)
|
||||
{
|
||||
uint16_t ret;
|
||||
|
||||
switch(o)
|
||||
{
|
||||
case 0x80: /* TM0 */
|
||||
logerror("%06x: Warning: read back TM0\n",PC());
|
||||
ret = m_TM0;
|
||||
break;
|
||||
case 0x82: /* MD0 */
|
||||
logerror("%06x: Warning: read back MD0\n",PC());
|
||||
ret = m_MD0;
|
||||
break;
|
||||
case 0x88: /* TM1 */
|
||||
logerror("%06x: Warning: read back TM1\n",PC());
|
||||
ret = m_TM1;
|
||||
break;
|
||||
case 0x8A: /* MD1 */
|
||||
logerror("%06x: Warning: read back MD1\n",PC());
|
||||
ret = m_MD1;
|
||||
break;
|
||||
default:
|
||||
ret = (read_sfr(o) | (read_sfr(o+1) << 8));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void v25_common_device::write_irqcontrol(int /*INTSOURCES*/ source, uint8_t d)
|
||||
{
|
||||
if(d & 0x80)
|
||||
if (BIT(d, 7))
|
||||
m_pending_irq |= source;
|
||||
else
|
||||
m_pending_irq &= ~source;
|
||||
|
||||
if(d & 0x40)
|
||||
if (BIT(d, 6))
|
||||
m_unmasked_irq &= ~source;
|
||||
else
|
||||
m_unmasked_irq |= source;
|
||||
|
||||
if(d & 0x20)
|
||||
if (BIT(d, 5))
|
||||
logerror("%06x: Warning: macro service function not implemented\n",PC());
|
||||
|
||||
if(d & 0x10)
|
||||
if (BIT(d, 4))
|
||||
m_bankswitch_irq |= source;
|
||||
else
|
||||
m_bankswitch_irq &= ~source;
|
||||
}
|
||||
|
||||
void v25_common_device::write_sfr(unsigned o, uint8_t d)
|
||||
uint8_t v25_common_device::p0_r()
|
||||
{
|
||||
int tmp;
|
||||
attotime time;
|
||||
return m_p0_in();
|
||||
}
|
||||
|
||||
static const int timebases[4] = { 10, 13, 16, 20 };
|
||||
static const int clocks[4] = { 2, 4, 8, 0 };
|
||||
void v25_common_device::p0_w(uint8_t d)
|
||||
{
|
||||
m_p0_out(d);
|
||||
}
|
||||
|
||||
switch(o)
|
||||
void v25_common_device::pm0_w(uint8_t d)
|
||||
{
|
||||
logerror("%06x: PM0 set to %02x\n", PC(), d);
|
||||
}
|
||||
|
||||
void v25_common_device::pmc0_w(uint8_t d)
|
||||
{
|
||||
logerror("%06x: PMC0 set to %02x\n", PC(), d);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::p1_r()
|
||||
{
|
||||
// P1 is combined with the interrupt lines
|
||||
return ((m_p1_in() & 0xf0)
|
||||
| (m_nmi_state ? 0x00 : 0x01)
|
||||
| (m_intp_state[0] ? 0x00 : 0x02)
|
||||
| (m_intp_state[1] ? 0x00 : 0x04)
|
||||
| (m_intp_state[2] ? 0x00 : 0x08));
|
||||
}
|
||||
|
||||
void v25_common_device::p1_w(uint8_t d)
|
||||
{
|
||||
// only the upper four bits of P1 can be used as output
|
||||
m_p1_out(d & 0xf0);
|
||||
}
|
||||
|
||||
void v25_common_device::pm1_w(uint8_t d)
|
||||
{
|
||||
logerror("%06x: PM1 set to %02x\n", PC(), d);
|
||||
}
|
||||
|
||||
void v25_common_device::pmc1_w(uint8_t d)
|
||||
{
|
||||
logerror("%06x: PMC1 set to %02x\n", PC(), d);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::p2_r()
|
||||
{
|
||||
return m_p2_in();
|
||||
}
|
||||
|
||||
void v25_common_device::p2_w(uint8_t d)
|
||||
{
|
||||
m_p2_out(d);
|
||||
}
|
||||
|
||||
void v25_common_device::pm2_w(uint8_t d)
|
||||
{
|
||||
logerror("%06x: PM2 set to %02x\n", PC(), d);
|
||||
}
|
||||
|
||||
void v25_common_device::pmc2_w(uint8_t d)
|
||||
{
|
||||
logerror("%06x: PMC2 set to %02x\n", PC(), d);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::pt_r()
|
||||
{
|
||||
return m_pt_in();
|
||||
}
|
||||
|
||||
void v25_common_device::pmt_w(uint8_t d)
|
||||
{
|
||||
logerror("%06x: PMT set to %02x\n", PC(), d);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::exic0_r()
|
||||
{
|
||||
return read_irqcontrol(INTP0, m_priority_intp);
|
||||
}
|
||||
|
||||
void v25_common_device::exic0_w(uint8_t d)
|
||||
{
|
||||
write_irqcontrol(INTP0, d);
|
||||
m_priority_intp = d & 0x7;
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::exic1_r()
|
||||
{
|
||||
return read_irqcontrol(INTP1, 7);
|
||||
}
|
||||
|
||||
void v25_common_device::exic1_w(uint8_t d)
|
||||
{
|
||||
write_irqcontrol(INTP1, d);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::exic2_r()
|
||||
{
|
||||
return read_irqcontrol(INTP2, 7);
|
||||
}
|
||||
|
||||
void v25_common_device::exic2_w(uint8_t d)
|
||||
{
|
||||
write_irqcontrol(INTP2, d);
|
||||
}
|
||||
|
||||
uint16_t v25_common_device::tm0_r()
|
||||
{
|
||||
if (!machine().side_effects_disabled())
|
||||
logerror("%06x: Warning: read back TM0\n",PC());
|
||||
return m_TM0;
|
||||
}
|
||||
|
||||
void v25_common_device::tm0_w(uint16_t d)
|
||||
{
|
||||
m_TM0 = d;
|
||||
}
|
||||
|
||||
uint16_t v25_common_device::md0_r()
|
||||
{
|
||||
if (!machine().side_effects_disabled())
|
||||
logerror("%06x: Warning: read back MD0\n",PC());
|
||||
return m_MD0;
|
||||
}
|
||||
|
||||
void v25_common_device::md0_w(uint16_t d)
|
||||
{
|
||||
m_MD0 = d;
|
||||
}
|
||||
|
||||
uint16_t v25_common_device::tm1_r()
|
||||
{
|
||||
if (!machine().side_effects_disabled())
|
||||
logerror("%06x: Warning: read back TM1\n",PC());
|
||||
return m_TM1;
|
||||
}
|
||||
|
||||
void v25_common_device::tm1_w(uint16_t d)
|
||||
{
|
||||
m_TM1 = d;
|
||||
}
|
||||
|
||||
uint16_t v25_common_device::md1_r()
|
||||
{
|
||||
if (!machine().side_effects_disabled())
|
||||
logerror("%06x: Warning: read back MD1\n",PC());
|
||||
return m_MD1;
|
||||
}
|
||||
|
||||
void v25_common_device::md1_w(uint16_t d)
|
||||
{
|
||||
m_MD1 = d;
|
||||
}
|
||||
|
||||
void v25_common_device::tmc0_w(uint8_t d)
|
||||
{
|
||||
m_TMC0 = d;
|
||||
if (BIT(d, 0)) // oneshot mode
|
||||
{
|
||||
case 0x00: /* P0 */
|
||||
m_p0_out(d);
|
||||
break;
|
||||
case 0x08: /* P1 */
|
||||
/* only the upper four bits of P1 can be used as output */
|
||||
m_p1_out(d & 0xF0);
|
||||
break;
|
||||
case 0x10: /* P2 */
|
||||
m_p2_out(d);
|
||||
break;
|
||||
case 0x4C: /* EXIC0 */
|
||||
write_irqcontrol(INTP0, d);
|
||||
m_priority_intp = d & 0x7;
|
||||
break;
|
||||
case 0x4D: /* EXIC1 */
|
||||
write_irqcontrol(INTP1, d);
|
||||
break;
|
||||
case 0x4E: /* EXIC2 */
|
||||
write_irqcontrol(INTP2, d);
|
||||
break;
|
||||
case 0x90: /* TMC0 */
|
||||
m_TMC0 = d;
|
||||
if(d & 1) /* oneshot mode */
|
||||
{
|
||||
if(d & 0x80)
|
||||
{
|
||||
tmp = m_PCK * m_TM0 * ((d & 0x40) ? 128 : 12 );
|
||||
time = attotime::from_hz(unscaled_clock()) * tmp;
|
||||
m_timers[0]->adjust(time, INTTU0);
|
||||
}
|
||||
else
|
||||
m_timers[0]->adjust(attotime::never);
|
||||
if (BIT(d, 7))
|
||||
{
|
||||
unsigned tmp = m_PCK * m_TM0 * (BIT(d, 6) ? 128 : 12);
|
||||
attotime time = clocks_to_attotime(tmp);
|
||||
m_timers[0]->adjust(time, INTTU0);
|
||||
}
|
||||
else
|
||||
m_timers[0]->adjust(attotime::never);
|
||||
|
||||
if(d & 0x20)
|
||||
{
|
||||
tmp = m_PCK * m_MD0 * ((d & 0x10) ? 128 : 12 );
|
||||
time = attotime::from_hz(unscaled_clock()) * tmp;
|
||||
m_timers[1]->adjust(time, INTTU1);
|
||||
}
|
||||
else
|
||||
m_timers[1]->adjust(attotime::never);
|
||||
}
|
||||
else /* interval mode */
|
||||
{
|
||||
if(d & 0x80)
|
||||
{
|
||||
tmp = m_PCK * m_MD0 * ((d & 0x40) ? 128 : 6 );
|
||||
time = attotime::from_hz(unscaled_clock()) * tmp;
|
||||
m_timers[0]->adjust(time, INTTU0, time);
|
||||
m_timers[1]->adjust(attotime::never);
|
||||
m_TM0 = m_MD0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_timers[0]->adjust(attotime::never);
|
||||
m_timers[1]->adjust(attotime::never);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x91: /* TMC1 */
|
||||
m_TMC1 = d & 0xC0;
|
||||
if(d & 0x80)
|
||||
{
|
||||
tmp = m_PCK * m_MD1 * ((d & 0x40) ? 128 : 6 );
|
||||
time = attotime::from_hz(unscaled_clock()) * tmp;
|
||||
m_timers[2]->adjust(time, INTTU2, time);
|
||||
m_TM1 = m_MD1;
|
||||
}
|
||||
else
|
||||
m_timers[2]->adjust(attotime::never);
|
||||
break;
|
||||
case 0x9C: /* TMIC0 */
|
||||
write_irqcontrol(INTTU0, d);
|
||||
m_priority_inttu = d & 0x7;
|
||||
break;
|
||||
case 0x9D: /* TMIC1 */
|
||||
write_irqcontrol(INTTU1, d);
|
||||
break;
|
||||
case 0x9E: /* TMIC2 */
|
||||
write_irqcontrol(INTTU2, d);
|
||||
break;
|
||||
case 0xEA: /* FLAG */
|
||||
m_F0 = ((d & 0x08) == 0x08);
|
||||
m_F1 = ((d & 0x20) == 0x20);
|
||||
break;
|
||||
case 0xEB: /* PRC */
|
||||
logerror("%06x: PRC set to %02x\n", PC(), d);
|
||||
m_RAMEN = ((d & 0x40) == 0x40);
|
||||
m_TB = timebases[(d & 0x0C) >> 2];
|
||||
m_PCK = clocks[d & 0x03];
|
||||
if (m_PCK == 0)
|
||||
{
|
||||
logerror(" Warning: invalid clock divider\n");
|
||||
m_PCK = 8;
|
||||
}
|
||||
tmp = m_PCK << m_TB;
|
||||
time = attotime::from_hz(unscaled_clock()) * tmp;
|
||||
m_timers[3]->adjust(time, INTTB, time);
|
||||
notify_clock_changed(); /* make device_execute_interface pick up the new clocks_to_cycles() */
|
||||
logerror(" Internal RAM %sabled\n", (m_RAMEN ? "en" : "dis"));
|
||||
logerror(" Time base set to 2^%d\n", m_TB);
|
||||
logerror(" Clock divider set to %d\n", m_PCK);
|
||||
break;
|
||||
case 0xEC: /* TBIC */
|
||||
/* time base interrupt doesn't support macro service, bank switching or priority control */
|
||||
write_irqcontrol(INTTB, d & 0xC0);
|
||||
break;
|
||||
case 0xFF: /* IDB */
|
||||
m_IDB = (d << 12) | 0xE00;
|
||||
logerror("%06x: IDB set to %02x\n",PC(),d);
|
||||
break;
|
||||
default:
|
||||
logerror("%06x: Wrote %02x to special function register %02x\n",PC(),d,o);
|
||||
if (BIT(d, 5))
|
||||
{
|
||||
unsigned tmp = m_PCK * m_MD0 * (BIT(d, 4) ? 128 : 12);
|
||||
attotime time = clocks_to_attotime(tmp);
|
||||
m_timers[1]->adjust(time, INTTU1);
|
||||
}
|
||||
else
|
||||
m_timers[1]->adjust(attotime::never);
|
||||
}
|
||||
else // interval mode
|
||||
{
|
||||
if (BIT(d, 7))
|
||||
{
|
||||
unsigned tmp = m_PCK * m_MD0 * (BIT(d, 6) ? 128 : 6);
|
||||
attotime time = clocks_to_attotime(tmp);
|
||||
m_timers[0]->adjust(time, INTTU0, time);
|
||||
m_timers[1]->adjust(attotime::never);
|
||||
m_TM0 = m_MD0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_timers[0]->adjust(attotime::never);
|
||||
m_timers[1]->adjust(attotime::never);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void v25_common_device::write_sfr_word(unsigned o, uint16_t d)
|
||||
void v25_common_device::tmc1_w(uint8_t d)
|
||||
{
|
||||
switch(o)
|
||||
m_TMC1 = d & 0xC0;
|
||||
if (BIT(d, 7))
|
||||
{
|
||||
case 0x80: /* TM0 */
|
||||
m_TM0 = d;
|
||||
break;
|
||||
case 0x82: /* MD0 */
|
||||
m_MD0 = d;
|
||||
break;
|
||||
case 0x88: /* TM1 */
|
||||
m_TM1 = d;
|
||||
break;
|
||||
case 0x8A: /* MD1 */
|
||||
m_MD1 = d;
|
||||
break;
|
||||
default:
|
||||
write_sfr(o, d);
|
||||
write_sfr(o+1, d >> 8);
|
||||
unsigned tmp = m_PCK * m_MD1 * (BIT(d, 6) ? 128 : 6);
|
||||
attotime time = clocks_to_attotime(tmp);
|
||||
m_timers[2]->adjust(time, INTTU2, time);
|
||||
m_TM1 = m_MD1;
|
||||
}
|
||||
else
|
||||
m_timers[2]->adjust(attotime::never);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::tmic0_r()
|
||||
{
|
||||
return read_irqcontrol(INTTU0, m_priority_inttu);
|
||||
}
|
||||
|
||||
void v25_common_device::tmic0_w(uint8_t d)
|
||||
{
|
||||
write_irqcontrol(INTTU0, d);
|
||||
m_priority_inttu = d & 0x7;
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::tmic1_r()
|
||||
{
|
||||
return read_irqcontrol(INTTU1, 7);
|
||||
}
|
||||
|
||||
void v25_common_device::tmic1_w(uint8_t d)
|
||||
{
|
||||
write_irqcontrol(INTTU1, d);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::tmic2_r()
|
||||
{
|
||||
return read_irqcontrol(INTTU2, 7);
|
||||
}
|
||||
|
||||
void v25_common_device::tmic2_w(uint8_t d)
|
||||
{
|
||||
write_irqcontrol(INTTU2, d);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::rfm_r()
|
||||
{
|
||||
return m_RFM;
|
||||
}
|
||||
|
||||
void v25_common_device::rfm_w(uint8_t d)
|
||||
{
|
||||
m_RFM = d;
|
||||
}
|
||||
|
||||
uint16_t v25_common_device::wtc_r()
|
||||
{
|
||||
return m_WTC;
|
||||
}
|
||||
|
||||
void v25_common_device::wtc_w(offs_t a, uint16_t d, uint16_t m)
|
||||
{
|
||||
m_WTC = (m_WTC & ~m) | (d & m);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::flag_r()
|
||||
{
|
||||
return (m_F0 << 3) | (m_F1 << 5);
|
||||
}
|
||||
|
||||
void v25_common_device::flag_w(uint8_t d)
|
||||
{
|
||||
m_F0 = BIT(d, 3);
|
||||
m_F1 = BIT(d, 5);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::prc_r()
|
||||
{
|
||||
uint8_t ret = m_RAMEN ? 0x40 : 0;
|
||||
|
||||
switch (m_TB)
|
||||
{
|
||||
case 10:
|
||||
break;
|
||||
case 13:
|
||||
ret |= 0x04;
|
||||
break;
|
||||
case 16:
|
||||
ret |= 0x08;
|
||||
break;
|
||||
case 20:
|
||||
ret |= 0x0C;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (m_PCK)
|
||||
{
|
||||
case 2:
|
||||
break;
|
||||
case 4:
|
||||
ret |= 0x01;
|
||||
break;
|
||||
case 8:
|
||||
ret |= 0x02;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void v25_common_device::prc_w(uint8_t d)
|
||||
{
|
||||
static const int timebases[4] = { 10, 13, 16, 20 };
|
||||
static const int clocks[4] = { 2, 4, 8, 0 };
|
||||
|
||||
logerror("%06x: PRC set to %02x\n", PC(), d);
|
||||
m_RAMEN = ((d & 0x40) == 0x40);
|
||||
m_TB = timebases[(d & 0x0C) >> 2];
|
||||
m_PCK = clocks[d & 0x03];
|
||||
if (m_PCK == 0)
|
||||
{
|
||||
logerror(" Warning: invalid clock divider\n");
|
||||
m_PCK = 8;
|
||||
}
|
||||
|
||||
unsigned tmp = m_PCK << m_TB;
|
||||
attotime time = clocks_to_attotime(tmp);
|
||||
m_timers[3]->adjust(time, INTTB, time);
|
||||
notify_clock_changed(); // make device_execute_interface pick up the new clocks_to_cycles()
|
||||
|
||||
logerror(" Internal RAM %sabled\n", (m_RAMEN ? "en" : "dis"));
|
||||
logerror(" Time base set to 2^%d\n", m_TB);
|
||||
logerror(" Clock divider set to %d\n", m_PCK);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::tbic_r()
|
||||
{
|
||||
return read_irqcontrol(INTTB, 7);
|
||||
}
|
||||
|
||||
void v25_common_device::tbic_w(uint8_t d)
|
||||
{
|
||||
// time base interrupt doesn't support macro service, bank switching or priority control
|
||||
write_irqcontrol(INTTB, d & 0xC0);
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::irqs_r()
|
||||
{
|
||||
return m_IRQS;
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::ispr_r()
|
||||
{
|
||||
return m_ISPR;
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::idb_r()
|
||||
{
|
||||
return m_IDB >> 12;
|
||||
}
|
||||
|
||||
void v25_common_device::idb_w(uint8_t d)
|
||||
{
|
||||
m_IDB = (d << 12) | 0xe00;
|
||||
}
|
||||
|
||||
uint8_t v25_common_device::v25_read_byte(unsigned a)
|
||||
{
|
||||
if((a & 0xFFE00) == m_IDB || a == 0xFFFFF)
|
||||
{
|
||||
unsigned o = a & 0x1FF;
|
||||
|
||||
if(m_RAMEN && o < 0x100)
|
||||
return m_ram.b[BYTE_XOR_LE(o)];
|
||||
|
||||
if(o >= 0x100)
|
||||
return read_sfr(o-0x100);
|
||||
}
|
||||
|
||||
return m_program->read_byte(a);
|
||||
if (((a & 0xffe00) == m_IDB && (m_RAMEN || BIT(a, 8))) || a == 0xfffff)
|
||||
return m_data->read_byte(a & 0x1ff);
|
||||
else
|
||||
return m_program->read_byte(a);
|
||||
}
|
||||
|
||||
uint16_t v25_common_device::v25_read_word(unsigned a)
|
||||
{
|
||||
if( a & 1 )
|
||||
if (BIT(a, 0))
|
||||
return (v25_read_byte(a) | (v25_read_byte(a + 1) << 8));
|
||||
|
||||
if((a & 0xFFE00) == m_IDB)
|
||||
{
|
||||
unsigned o = a & 0x1FF;
|
||||
|
||||
if(m_RAMEN && o < 0x100)
|
||||
return m_ram.w[o/2];
|
||||
|
||||
if(o >= 0x100)
|
||||
return read_sfr_word(o-0x100);
|
||||
}
|
||||
|
||||
if(a == 0xFFFFE) /* not sure about this - manual says FFFFC-FFFFE are "reserved" */
|
||||
return (m_program->read_byte(a) | (read_sfr(0xFF) << 8));
|
||||
|
||||
return m_program->read_word(a);
|
||||
// not sure about this - manual says FFFFC-FFFFE are "reserved"
|
||||
if (a == 0xffffe)
|
||||
return (m_program->read_byte(a) | (m_data->read_byte(0x1ff) << 8));
|
||||
else if ((a & 0xffe00) == m_IDB && (m_RAMEN || BIT(a, 8)))
|
||||
return m_data->read_word(a & 0x1ff);
|
||||
else
|
||||
return m_program->read_word(a);
|
||||
}
|
||||
|
||||
void v25_common_device::v25_write_byte(unsigned a, uint8_t d)
|
||||
{
|
||||
if((a & 0xFFE00) == m_IDB || a == 0xFFFFF)
|
||||
{
|
||||
unsigned o = a & 0x1FF;
|
||||
|
||||
if(m_RAMEN && o < 0x100)
|
||||
{
|
||||
m_ram.b[BYTE_XOR_LE(o)] = d;
|
||||
return;
|
||||
}
|
||||
|
||||
if(o >= 0x100)
|
||||
{
|
||||
write_sfr(o-0x100, d);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_program->write_byte(a, d);
|
||||
if (((a & 0xffe00) == m_IDB && (m_RAMEN || BIT(a, 8))) || a == 0xfffff)
|
||||
m_data->write_byte(a & 0x1ff, d);
|
||||
else
|
||||
m_program->write_byte(a, d);
|
||||
}
|
||||
|
||||
void v25_common_device::v25_write_word(unsigned a, uint16_t d)
|
||||
{
|
||||
if( a & 1 )
|
||||
if (BIT(a, 0))
|
||||
{
|
||||
v25_write_byte(a, d);
|
||||
v25_write_byte(a + 1, d >> 8);
|
||||
return;
|
||||
}
|
||||
|
||||
if((a & 0xFFE00) == m_IDB)
|
||||
{
|
||||
unsigned o = a & 0x1FF;
|
||||
|
||||
if(m_RAMEN && o < 0x100)
|
||||
{
|
||||
m_ram.w[o/2] = d;
|
||||
return;
|
||||
}
|
||||
|
||||
if(o >= 0x100)
|
||||
{
|
||||
write_sfr_word(o-0x100, d);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(a == 0xFFFFE) /* not sure about this - manual says FFFFC-FFFFE are "reserved" */
|
||||
// not sure about this - manual says FFFFC-FFFFE are "reserved"
|
||||
if (a == 0xffffe)
|
||||
{
|
||||
m_program->write_byte(a, d);
|
||||
write_sfr(0xFF, d >> 8);
|
||||
return;
|
||||
m_data->write_byte(0x1ff, d >> 8);
|
||||
}
|
||||
|
||||
m_program->write_word(a, d);
|
||||
else if ((a & 0xffe00) == m_IDB && (m_RAMEN || BIT(a, 8)))
|
||||
m_data->write_word(a & 0x1ff, d);
|
||||
else
|
||||
m_program->write_word(a, d);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user