tms99xx: Change setaddress method signature to (address,buslines); treating an address as a value to be written does not work with memory maps. Also fix 99/4p regression with wrong cru address access to peribox/evpc.

This commit is contained in:
Michael Zapf 2019-04-17 22:39:50 +02:00
parent cdd6766fe4
commit 0c70ab3079
12 changed files with 110 additions and 90 deletions

View File

@ -33,10 +33,6 @@ public:
static constexpr unsigned TOTAL_HORZ = 342;
static constexpr unsigned TOTAL_VERT_NTSC = 262;
template <class Object> devcb_base &set_readmem_callback(Object &&cb) { return m_mem_read_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_hold_callback(Object &&cb) { return m_hold_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_int_callback(Object &&cb) { return m_int_cb.set_callback(std::forward<Object>(cb)); }
// Delay(2) + ColorBurst(14) + Delay(8) + LeftBorder(13)
static constexpr unsigned HORZ_DISPLAY_START = 2 + 14 + 8 + 13;
// RightBorder(15) + Delay(8) + HorizSync(26)

View File

@ -367,10 +367,10 @@ void mainboard8_device::cruwrite(offs_t offset, uint8_t data)
// =============== Memory bus access ==================
void mainboard8_device::setaddress(offs_t mode, uint16_t offset)
void mainboard8_device::setaddress(offs_t offset, uint8_t busctrl)
{
m_dbin_level = ((busctrl & TMS99xx_BUS_DBIN)!=0);
LOGMASKED(LOG_ADDRESS, "set %s %04x\n", (m_dbin_level==ASSERT_LINE)? "R" : "W", offset);
m_dbin_level = ((mode & TMS99xx_BUS_DBIN)!=0);
// No data is waiting on the data bus
m_pending_write = false;

View File

@ -541,7 +541,7 @@ public:
// Memory space
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
void setaddress(offs_t mode, uint16_t address);
void setaddress(offs_t offset, uint8_t busctrl);
// Memory space for debugger access
uint8_t debugger_read(offs_t offset);

View File

@ -98,6 +98,9 @@ datamux_device::datamux_device(const machine_config &mconfig, const char *tag, d
m_ram16b(*owner, TI99_EXPRAM_TAG),
m_padram(*owner, TI99_PADRAM_TAG),
m_cpu(*owner, "maincpu"),
m_grom0(*owner, TI99_GROM0_TAG),
m_grom1(*owner, TI99_GROM1_TAG),
m_grom2(*owner, TI99_GROM2_TAG),
m_ready(*this),
m_addr_buf(0),
m_dbin(CLEAR_LINE),
@ -130,10 +133,9 @@ void datamux_device::read_all(uint16_t addr, uint8_t *value)
{
if (m_console_groms_present)
{
for (int i=0; i < 3; i++)
{
m_grom[i]->readz(value);
}
m_grom0->readz(value);
m_grom1->readz(value);
m_grom2->readz(value);
}
// GROMport (GROMs)
m_gromport->readz(addr, value);
@ -164,8 +166,9 @@ void datamux_device::write_all(uint16_t addr, uint8_t value)
{
if (m_console_groms_present)
{
for (int i=0; i < 3; i++)
m_grom[i]->write(value);
m_grom0->write(value);
m_grom1->write(value);
m_grom2->write(value);
}
// GROMport
m_gromport->write(addr, value);
@ -212,8 +215,11 @@ void datamux_device::setaddress_all(uint16_t addr)
if (isgrom) m_grom_idle = false;
if (m_console_groms_present)
for (int i=0; i < 3; i++)
m_grom[i]->set_lines((line_state)m_dbin, a14, gsq);
{
m_grom0->set_lines((line_state)m_dbin, a14, gsq);
m_grom1->set_lines((line_state)m_dbin, a14, gsq);
m_grom2->set_lines((line_state)m_dbin, a14, gsq);
}
// GROMport (GROMs)
m_gromport->set_gromlines((line_state)m_dbin, a14, gsq);
@ -428,11 +434,11 @@ void datamux_device::write(offs_t offset, uint16_t data)
Called when the memory access starts by setting the address bus. From that
point on, we suspend the CPU until all operations are done.
*/
void datamux_device::setaddress(offs_t mode, uint16_t addr)
void datamux_device::setaddress(offs_t offset, uint16_t busctrl)
{
m_addr_buf = addr;
m_addr_buf = offset << 1;
m_waitcount = 0;
m_dbin = ((mode & TMS99xx_BUS_DBIN)!=0);
m_dbin = ((busctrl & TMS99xx_BUS_DBIN)!=0);
LOGMASKED(LOG_ADDRESS, "Set address %04x\n", m_addr_buf);
@ -558,8 +564,10 @@ WRITE_LINE_MEMBER( datamux_device::gromclk_in )
// Propagate to the GROMs
if (m_console_groms_present)
{
for (int i=0; i < 3; i++) m_grom[i]->gclock_in(state);
m_grom_idle = m_grom[0]->idle();
m_grom0->gclock_in(state);
m_grom1->gclock_in(state);
m_grom2->gclock_in(state);
m_grom_idle = m_grom0->idle();
}
m_gromport->gclock_in(state);
@ -610,14 +618,6 @@ void datamux_device::device_reset(void)
m_dbin = CLEAR_LINE;
}
void datamux_device::device_config_complete()
{
m_grom[0] = downcast<tmc0430_device*>(owner()->subdevice(TI99_GROM0_TAG));
m_grom[1] = downcast<tmc0430_device*>(owner()->subdevice(TI99_GROM1_TAG));
m_grom[2] = downcast<tmc0430_device*>(owner()->subdevice(TI99_GROM2_TAG));
}
INPUT_PORTS_START( datamux )
PORT_START( "RAM" ) /* config */
PORT_CONFNAME( 0x01, 0x00, "Console 32 KiB RAM upgrade (16 bit)" )

View File

@ -35,7 +35,7 @@ public:
datamux_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
uint16_t read(offs_t offset);
void write(offs_t offset, uint16_t data);
void setaddress(offs_t mode, uint16_t address);
void setaddress(offs_t offset, uint16_t busctrl);
DECLARE_WRITE_LINE_MEMBER( clock_in );
DECLARE_WRITE_LINE_MEMBER( dbin_in );
@ -50,7 +50,6 @@ protected:
void device_start() override;
void device_stop() override;
void device_reset() override;
void device_config_complete() override;
ioport_constructor device_input_ports() const override;
private:
@ -79,7 +78,9 @@ private:
uint16_t* m_consolerom;
// Console GROMs
tmc0430_device* m_grom[3];
required_device<tmc0430_device> m_grom0;
required_device<tmc0430_device> m_grom1;
required_device<tmc0430_device> m_grom2;
// Common read routine
void read_all(uint16_t addr, uint8_t *target);

View File

@ -907,13 +907,13 @@ void geneve_mapper_device::write_to_pfm(offs_t offset, uint8_t data)
This decoding will later be used in the READ/WRITE member functions. Also,
we initiate wait state creation here.
*/
void geneve_mapper_device::setaddress(offs_t mode, uint16_t address)
void geneve_mapper_device::setaddress(offs_t address, uint8_t busctrl)
{
LOGMASKED(LOG_DETAIL, "setaddress = %04x\n", address);
m_debug_no_ws = false;
m_decoded.offset = address;
m_read_mode = ((mode & TMS99xx_BUS_DBIN)!=0);
m_read_mode = ((busctrl & TMS99xx_BUS_DBIN)!=0);
decode_logical(m_read_mode, &m_decoded);
if (m_decoded.function == MUNDEF)

View File

@ -123,7 +123,7 @@ public:
uint8_t readm(offs_t offset);
void writem(offs_t offset, uint8_t data);
void setaddress(offs_t mode, uint16_t address);
void setaddress(offs_t offset, uint8_t busctrl);
DECLARE_INPUT_CHANGED_MEMBER( settings_changed );

View File

@ -321,11 +321,13 @@ READ8Z_MEMBER(snug_enhanced_video_device::crureadz)
{
if ((offset & 0xff00)==EVPC_CRU_BASE)
{
if ((offset & 0x00f0)==0) // offset 0 delivers bits 0-7 (address 00-0f)
switch ((offset>>1) & 7)
{
uint8_t p = ~(ioport("EVPC-SW1")->read() | (ioport("EVPC-SW3")->read()<<2)
| (ioport("EVPC-SW4")->read()<<3) | (ioport("EVPC-SW8")->read()<<7));
*value = BIT(p, (offset >> 1) & 7);
case 0: *value = ~(ioport("EVPC-SW1")->read()); break;
case 2: *value = ~(ioport("EVPC-SW3")->read()); break;
case 3: *value = ~(ioport("EVPC-SW4")->read()); break;
case 7: *value = ~(ioport("EVPC-SW8")->read()); break;
default: *value = ~0; break;
}
}
}

View File

@ -159,12 +159,12 @@ enum
tms99xx_device::tms99xx_device(const machine_config &mconfig, device_type type, const char *tag, int data_width, int prg_addr_bits, int cru_addr_bits, device_t *owner, uint32_t clock)
: cpu_device(mconfig, type, tag, owner, clock),
m_program_config("program", ENDIANNESS_BIG, data_width, prg_addr_bits),
m_setaddress_config("setaddress", ENDIANNESS_BIG, prg_addr_bits, prg_addr_bits), // data = address
m_setaddress_config("setaddress", ENDIANNESS_BIG, data_width, prg_addr_bits), // choose the same width as the program space
m_io_config("cru", ENDIANNESS_LITTLE, 8, cru_addr_bits + 1, 1),
m_prgspace(nullptr),
m_cru(nullptr),
m_prgaddr_mask((1<<prg_addr_bits)-1),
m_cruaddr_mask((2<<cru_addr_bits)-2),
m_prgaddr_mask((1<<prg_addr_bits)-2), // fffe for 16 bits, 3ffe for 14 bits (only even addresses)
m_cruaddr_mask((2<<cru_addr_bits)-2), // Address is shifted left by one
m_iaq(false),
m_clock_out_line(*this),
m_wait_line(*this),
@ -328,10 +328,10 @@ void tms99xx_device::state_import(const device_state_entry &entry)
// bits of the STATUS register
break;
case TMS9900_PC:
PC = (uint16_t)(m_state_any & m_prgaddr_mask & 0xfffe);
PC = (uint16_t)(m_state_any & m_prgaddr_mask);
break;
case TMS9900_WP:
WP = (uint16_t)(m_state_any & m_prgaddr_mask & 0xfffe);
WP = (uint16_t)(m_state_any & m_prgaddr_mask);
break;
case TMS9900_STATUS:
ST = (uint16_t)m_state_any;
@ -404,7 +404,7 @@ uint16_t tms99xx_device::read_workspace_register_debug(int reg)
{
int temp = m_icount;
auto dis = machine().disable_side_effects();
uint16_t value = m_prgspace->read_word((WP+(reg<<1)) & m_prgaddr_mask & 0xfffe);
uint16_t value = m_prgspace->read_word((WP+(reg<<1)) & m_prgaddr_mask);
m_icount = temp;
return value;
}
@ -413,10 +413,26 @@ void tms99xx_device::write_workspace_register_debug(int reg, uint16_t data)
{
int temp = m_icount;
auto dis = machine().disable_side_effects();
m_prgspace->write_word((WP+(reg<<1)) & m_prgaddr_mask & 0xfffe, data);
m_prgspace->write_word((WP+(reg<<1)) & m_prgaddr_mask, data);
m_icount = temp;
}
/*
The setaddress space is used to implement a split-phase memory access
where the address bus is first set, then the CPU samples the READY line,
(when low, enters wait states,) then the CPU reads the address bus. For
writing, setting the address and setting the data bus is done in direct
succession.
It is an optional feature, where drivers may connect to this space to
make use of it, or to completely ignore it when there is no need for
waitstate control.
In order to allow for using address maps, the setaddress space shows the
same widths as the normal program space. Its values are the levels of
certains lines that are set or reset during the memory access, in
particular DBIN and IAQ.
*/
device_memory_interface::space_config_vector tms99xx_device::memory_space_config() const
{
if (has_configured_map(AS_SETADDRESS))
@ -1511,7 +1527,7 @@ void tms99xx_device::acquire_instruction()
LOGMASKED(LOG_EXEC, "%04x\n", PC);
debugger_instruction_hook(PC);
PC = (PC + 2) & 0xfffe & m_prgaddr_mask;
PC = (PC + 2) & m_prgaddr_mask;
// IAQ will be cleared in the main loop
}
}
@ -1530,8 +1546,7 @@ void tms99xx_device::mem_read()
{
LOGMASKED(LOG_ADDRESSBUS, "set address (r) %04x\n", m_address);
if (m_setaddr)
// Note that the bus lines form a pseudo address that is shifted right by one in the handler
m_setaddr->write_word((TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0))<<1, m_address & m_prgaddr_mask & 0xfffe);
m_setaddr->write_word(m_address & m_prgaddr_mask, (TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0)));
m_check_ready = true;
m_mem_phase = 2;
m_pass = 2;
@ -1541,7 +1556,7 @@ void tms99xx_device::mem_read()
else
{
// Second phase (after READY was raised again)
m_current_value = m_prgspace->read_word(m_address & m_prgaddr_mask & 0xfffe);
m_current_value = m_prgspace->read_word(m_address & m_prgaddr_mask);
pulse_clock(1);
m_mem_phase = 1; // reset to phase 1
LOGMASKED(LOG_MEM, "mem r %04x -> %04x\n", m_address, m_current_value);
@ -1555,9 +1570,9 @@ void tms99xx_device::mem_write()
LOGMASKED(LOG_ADDRESSBUS, "set address (w) %04x\n", m_address);
// When writing, the data bus is asserted immediately after the address bus
if (m_setaddr)
m_setaddr->write_word(TMS99xx_BUS_WRITE, m_address & m_prgaddr_mask & 0xfffe);
m_setaddr->write_word(m_address & m_prgaddr_mask, TMS99xx_BUS_WRITE);
LOGMASKED(LOG_MEM, "mem w %04x <- %04x\n", m_address, m_current_value);
m_prgspace->write_word(m_address & m_prgaddr_mask & 0xfffe, m_current_value);
m_prgspace->write_word(m_address & m_prgaddr_mask, m_current_value);
m_check_ready = true;
m_mem_phase = 2;
m_pass = 2;
@ -1595,7 +1610,7 @@ void tms99xx_device::register_write()
{
// This will be called twice; m_pass is set by the embedded mem_write
uint16_t addr_save = m_address;
m_address = (WP + (m_regnumber<<1)) & m_prgaddr_mask & 0xfffe;
m_address = (WP + (m_regnumber<<1)) & m_prgaddr_mask;
mem_write();
m_address = addr_save;
}
@ -1820,7 +1835,7 @@ void tms99xx_device::alu_pcaddr_advance()
{
// Set PC as new read address, increase by 2
m_address = PC;
PC = (PC + 2) & 0xfffe & m_prgaddr_mask;
PC = (PC + 2) & m_prgaddr_mask;
pulse_clock(2);
}
@ -1836,7 +1851,7 @@ void tms99xx_device::alu_imm()
m_value_copy = m_current_value;
m_address_copy = m_address;
m_address = PC;
PC = (PC + 2) & 0xfffe & m_prgaddr_mask;
PC = (PC + 2) & m_prgaddr_mask;
pulse_clock(2);
}
@ -2118,7 +2133,7 @@ void tms99xx_device::alu_xop()
break;
case 1:
m_value_copy = WP; // save the old WP
WP = m_current_value & m_prgaddr_mask & 0xfffe; // the new WP has been read in the previous microoperation
WP = m_current_value & m_prgaddr_mask; // the new WP has been read in the previous microoperation
m_current_value = m_address_saved; // we saved the address of the source operand; retrieve it
m_address = WP + 0x0016; // Next register is R11
break;
@ -2139,7 +2154,7 @@ void tms99xx_device::alu_xop()
set_status_bit(ST_X, true);
break;
case 6:
PC = m_current_value & m_prgaddr_mask & 0xfffe;
PC = m_current_value & m_prgaddr_mask;
break;
}
pulse_clock(2);
@ -2264,7 +2279,7 @@ void tms99xx_device::alu_b()
// retrieves the value at 0xa000, but in fact it will load the PC
// with the address 0xa000
m_current_value = PC;
PC = m_address & m_prgaddr_mask & 0xfffe;
PC = m_address & m_prgaddr_mask;
m_address = WP + 22;
pulse_clock(2);
}
@ -2275,7 +2290,7 @@ void tms99xx_device::alu_blwp()
{
case 0:
m_value_copy = WP;
WP = m_current_value & m_prgaddr_mask & 0xfffe; // set new WP (*m_destination)
WP = m_current_value & m_prgaddr_mask; // set new WP (*m_destination)
m_address_saved = (m_address + 2) & m_prgaddr_mask; // Save the location of the WP
m_address = WP + 30;
m_current_value = ST; // get status register
@ -2292,7 +2307,7 @@ void tms99xx_device::alu_blwp()
m_address = m_address_saved; // point to PC component of branch vector
break;
case 4:
PC = m_current_value & m_prgaddr_mask & 0xfffe;
PC = m_current_value & m_prgaddr_mask;
LOGMASKED(LOG_CONTEXT, "Context switch (blwp): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
break;
}
@ -2492,7 +2507,7 @@ void tms99xx_device::alu_jmp()
else
{
displacement = (IR & 0xff);
PC = (PC + (displacement<<1)) & m_prgaddr_mask & 0xfffe;
PC = (PC + (displacement<<1)) & m_prgaddr_mask;
}
m_state++;
pulse_clock(2);
@ -2623,7 +2638,7 @@ void tms99xx_device::alu_li()
void tms99xx_device::alu_lwpi()
{
WP = m_current_value & m_prgaddr_mask & 0xfffe;
WP = m_current_value & m_prgaddr_mask;
pulse_clock(2);
}
@ -2672,11 +2687,11 @@ void tms99xx_device::alu_rtwp()
m_address -= 2; // R14
break;
case 2:
PC = m_current_value & m_prgaddr_mask & 0xfffe;
PC = m_current_value & m_prgaddr_mask;
m_address -= 2; // R13
break;
case 3:
WP = m_current_value & m_prgaddr_mask & 0xfffe;
WP = m_current_value & m_prgaddr_mask;
pulse_clock(2);
// Just for debugging purposes
m_log_interrupt = false;
@ -2710,7 +2725,7 @@ void tms99xx_device::alu_int()
case 1:
m_address_copy = m_address;
m_value_copy = WP; // old WP
WP = m_current_value & m_prgaddr_mask & 0xfffe; // new WP
WP = m_current_value & m_prgaddr_mask; // new WP
m_current_value = ST;
m_address = (WP + 30) & m_prgaddr_mask;
LOGMASKED(LOG_INTD, "interrupt service (1): Read new WP = %04x, save ST to %04x\n", WP, m_address);
@ -2726,11 +2741,11 @@ void tms99xx_device::alu_int()
LOGMASKED(LOG_INTD, "interrupt service (3): Save WP to %04x\n", m_address);
break;
case 4:
m_address = (m_address_copy + 2) & 0xfffe & m_prgaddr_mask;
m_address = (m_address_copy + 2) & m_prgaddr_mask;
LOGMASKED(LOG_INTD, "interrupt service (4): Read PC from %04x\n", m_address);
break;
case 5:
PC = m_current_value & m_prgaddr_mask & 0xfffe;
PC = m_current_value & m_prgaddr_mask;
if (m_irq_level > 0 )
{
ST = (ST & 0xfff0) | (m_irq_level - 1);

View File

@ -109,7 +109,7 @@ void tms9980a_device::resolve_lines()
uint16_t tms9980a_device::read_workspace_register_debug(int reg)
{
int temp = m_icount;
int addr = (WP+(reg<<1)) & 0xfffe & m_prgaddr_mask;
int addr = (WP+(reg<<1)) & m_prgaddr_mask;
uint16_t value = (m_prgspace->read_byte(addr) << 8) | (m_prgspace->read_byte(addr+1) & 0xff);
m_icount = temp;
return value;
@ -118,7 +118,7 @@ uint16_t tms9980a_device::read_workspace_register_debug(int reg)
void tms9980a_device::write_workspace_register_debug(int reg, uint16_t data)
{
int temp = m_icount;
int addr = (WP+(reg<<1)) & 0xfffe & m_prgaddr_mask;
int addr = (WP+(reg<<1)) & m_prgaddr_mask;
m_prgspace->write_byte(addr, data>>8);
m_prgspace->write_byte(addr+1, data & 0xff);
m_icount = temp;
@ -195,19 +195,19 @@ void tms9980a_device::mem_read()
case 1:
m_pass = 4; // make the CPU visit this method more than once
if (m_setaddr)
m_setaddr->write_word((TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0))<<1, m_address & m_prgaddr_mask & ~1);
LOGMASKED(LOG_ADDRESSBUS, "Set address bus %04x\n", m_address & m_prgaddr_mask & ~1);
m_setaddr->write_byte(m_address & m_prgaddr_mask, (TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0)));
LOGMASKED(LOG_ADDRESSBUS, "Set address bus %04x\n", m_address & m_prgaddr_mask);
m_check_ready = true;
break;
case 2:
// Sample the value on the data bus (high byte)
value = m_prgspace->read_byte(m_address & m_prgaddr_mask & ~1);
LOGMASKED(LOG_MEM, "Memory read high byte %04x -> %02x\n", m_address & m_prgaddr_mask & ~1, value);
value = m_prgspace->read_byte(m_address & m_prgaddr_mask);
LOGMASKED(LOG_MEM, "Memory read high byte %04x -> %02x\n", m_address & m_prgaddr_mask, value);
m_current_value = (value << 8) & 0xff00;
break;
case 3:
if (m_setaddr)
m_setaddr->write_word((TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0))<<1, (m_address & m_prgaddr_mask) | 1);
m_setaddr->write_byte((m_address & m_prgaddr_mask) | 1, (TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0)));
LOGMASKED(LOG_ADDRESSBUS, "Set address bus %04x\n", (m_address & m_prgaddr_mask) | 1);
break;
case 4:
@ -229,10 +229,10 @@ void tms9980a_device::mem_write()
case 1:
m_pass = 4; // make the CPU visit this method once more
if (m_setaddr)
m_setaddr->write_word(TMS99xx_BUS_WRITE, m_address & m_prgaddr_mask & ~1);
LOGMASKED(LOG_ADDRESSBUS, "Set address bus %04x\n", m_address & m_prgaddr_mask & ~1);
m_prgspace->write_byte(m_address & 0x3ffe & ~1, (m_current_value >> 8)&0xff);
LOGMASKED(LOG_MEM, "Memory write high byte %04x <- %02x\n", m_address & m_prgaddr_mask & ~1, (m_current_value >> 8)&0xff);
m_setaddr->write_byte(m_address & m_prgaddr_mask, TMS99xx_BUS_WRITE);
LOGMASKED(LOG_ADDRESSBUS, "Set address bus %04x\n", m_address & m_prgaddr_mask);
m_prgspace->write_byte(m_address & 0x3ffe, (m_current_value >> 8)&0xff);
LOGMASKED(LOG_MEM, "Memory write high byte %04x <- %02x\n", m_address & m_prgaddr_mask, (m_current_value >> 8)&0xff);
m_check_ready = true;
break;
case 2:
@ -240,7 +240,7 @@ void tms9980a_device::mem_write()
break;
case 3:
if (m_setaddr)
m_setaddr->write_word(TMS99xx_BUS_WRITE, (m_address & m_prgaddr_mask) | 1);
m_setaddr->write_byte((m_address & m_prgaddr_mask) | 1, TMS99xx_BUS_WRITE);
LOGMASKED(LOG_ADDRESSBUS, "Set address bus %04x\n", (m_address & m_prgaddr_mask) | 1);
m_prgspace->write_byte((m_address & m_prgaddr_mask) | 1, m_current_value & 0xff);
LOGMASKED(LOG_MEM, "Memory write low byte %04x <- %02x\n", (m_address & m_prgaddr_mask) | 1, m_current_value & 0xff);
@ -268,7 +268,7 @@ void tms9980a_device::acquire_instruction()
decode(m_current_value);
LOGMASKED(LOG_OP, "===== Next operation %04x (%s) at %04x =====\n", IR, opname[m_command], PC);
debugger_instruction_hook(PC);
PC = (PC + 2) & 0xfffe & m_prgaddr_mask;
PC = (PC + 2) & m_prgaddr_mask;
}
// IAQ will be cleared in the main loop
}

View File

@ -170,7 +170,7 @@ tms9995_device::tms9995_device(const machine_config &mconfig, device_type type,
PC_debug(0),
m_iaq(false),
m_program_config("program", ENDIANNESS_BIG, 8, 16),
m_setaddress_config("setaddress", ENDIANNESS_BIG, 16, 16), // data = address
m_setaddress_config("setaddress", ENDIANNESS_BIG, 8, 16), // see tms9900.cpp
m_io_config("cru", ENDIANNESS_LITTLE, 8, 16, 1),
m_prgspace(nullptr),
m_setaddr(nullptr),
@ -438,6 +438,12 @@ void tms9995_device::write_workspace_register_debug(int reg, uint16_t data)
m_icount = temp;
}
/*
The setaddress space is used to implement a split-phase memory access
where the address bus is first set, then the CPU samples the READY line,
(when low, enters wait states,) then the CPU reads the address bus. See
tms9900.cpp for more information.
*/
device_memory_interface::space_config_vector tms9995_device::memory_space_config() const
{
if (has_configured_map(AS_SETADDRESS))
@ -1851,9 +1857,9 @@ void tms9995_device::mem_read()
else m_pass = 2;
m_check_hold = false;
LOGMASKED(LOG_ADDRESSBUS, "set address bus %04x\n", m_address & ~1);
LOGMASKED(LOG_ADDRESSBUS, "set address bus %04x\n", m_address & 0xfffe);
if (m_setaddr)
m_setaddr->write_word((TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0))<<1, address);
m_setaddr->write_byte(address, (TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0)));
m_request_auto_wait_state = m_auto_wait;
pulse_clock(1);
break;
@ -1861,14 +1867,14 @@ void tms9995_device::mem_read()
// Sample the value on the data bus (high byte)
if (m_word_access || !m_byteop) address &= 0xfffe;
value = m_prgspace->read_byte(address);
LOGMASKED(LOG_MEM, "memory read byte %04x -> %02x\n", m_address & ~1, value);
LOGMASKED(LOG_MEM, "memory read byte %04x -> %02x\n", m_address & 0xfffe, value);
m_current_value = (value << 8) & 0xff00;
break;
case 3:
// Set address + 1 (unless byte command)
LOGMASKED(LOG_ADDRESSBUS, "set address bus %04x\n", m_address | 1);
if (m_setaddr)
m_setaddr->write_word((TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0))<<1, m_address | 1);
m_setaddr->write_byte(m_address | 1, (TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0)));
m_request_auto_wait_state = m_auto_wait;
pulse_clock(1);
break;
@ -1985,7 +1991,7 @@ void tms9995_device::mem_write()
m_check_hold = false;
LOGMASKED(LOG_ADDRESSBUS, "set address bus %04x\n", address);
if (m_setaddr)
m_setaddr->write_word(TMS99xx_BUS_WRITE, address);
m_setaddr->write_byte(address, TMS99xx_BUS_WRITE);
LOGMASKED(LOG_MEM, "memory write byte %04x <- %02x\n", address, (m_current_value >> 8)&0xff);
m_prgspace->write_byte(address, (m_current_value >> 8)&0xff);
m_request_auto_wait_state = m_auto_wait;
@ -1999,7 +2005,7 @@ void tms9995_device::mem_write()
// Set address + 1 (unless byte command)
LOGMASKED(LOG_ADDRESSBUS, "set address bus %04x\n", m_address | 1);
if (m_setaddr)
m_setaddr->write_word(TMS99xx_BUS_WRITE, m_address | 1);
m_setaddr->write_byte(m_address | 1, TMS99xx_BUS_WRITE);
LOGMASKED(LOG_MEM, "memory write byte %04x <- %02x\n", m_address | 1, m_current_value & 0xff);
m_prgspace->write_byte(m_address | 1, m_current_value & 0xff);
m_request_auto_wait_state = m_auto_wait;

View File

@ -429,11 +429,11 @@ int ti99_4p_state::decode_address(int address)
Called when the memory access starts by setting the address bus. From that
point on, we suspend the CPU until all operations are done.
*/
void ti99_4p_state::setaddress(offs_t mode, uint16_t address)
void ti99_4p_state::setaddress(offs_t address, uint16_t busctrl)
{
m_addr_buf = address;
m_addr_buf = address << 1;
m_waitcount = 0;
m_dbin = ((mode & TMS99xx_BUS_DBIN)!=0);
m_dbin = ((busctrl & TMS99xx_BUS_DBIN)!=0);
LOGMASKED(LOG_ADDRESS, "set address %04x\n", m_addr_buf);
@ -717,7 +717,7 @@ void ti99_4p_state::cruwrite(offs_t offset, uint8_t data)
uint8_t ti99_4p_state::cruread(offs_t offset)
{
uint8_t value = 0;
m_peribox->crureadz(offset<<4, &value);
m_peribox->crureadz(offset<<1, &value);
return value;
}