summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/68307.cpp
blob: 58865272653fa7bc5d6ee20b98183fe89b6db06d (plain) (tree)
1
2
3
4
5
6
7

                                  

           
                

                  












                                                                                  
 












                                                                          




                                                                                                     















                                                                                                      
                                                                                                                   






                                                                                                                                          
 


                              



                             












                                            





























                                                                                 
                                                                          

                                                     
                                            

 
                                                          




                                                     
                                                           




                                                     
                                                            




                                                     
                                                                      




                                                     
                                                                       




                                                     
                                                                        













                                                          






                                                                                                      



 
                                                                                                                                                                                           
 



                                   

 



 
                                                 
 
                                                         
 
                                




                            
                                                           
 
                                                            

 
                                         
 


                                                               

 
                                         
 


                                                               

 
 
                                                   
 

                                                            

 



                                                             
                                                            


         
                                       
 


                                                               

 
                                        
 


                                                               

 
                                             








                                                     
 



                                         





                                          






                                            





                                     
                                                                                                                                                  




























                                                                                                
                 









































                                                                                                                                                                                                                                                     
// license:BSD-3-Clause
// copyright-holders:David Haywood
/* 68307 */

#include "emu.h"
#include "68307.h"

/* 68307 SERIAL Module */
/* all ports on this are 8-bit? */

/* this is a 68681 'compatible' chip but with only a single channel implemented
  (writes to the other channel have no effects)

  for now at least we piggyback on the existing 68307 emulation rather than having
  a custom verson here, that may change later if subtle differences exist.

*/
READ8_MEMBER( m68307cpu_device::m68307_internal_serial_r )
{
	m68307cpu_device *m68k = this;

	if (offset&1) return m_duart->read(*m68k->program, offset>>1);
	return 0x0000;
}

WRITE8_MEMBER(m68307cpu_device::m68307_internal_serial_w)
{
	m68307cpu_device *m68k = this;

	if (offset & 1) m_duart->write(*m68k->program, offset >> 1, data);
}



static ADDRESS_MAP_START( m68307_internal_map, AS_PROGRAM, 16, m68307cpu_device )
	AM_RANGE(0x000000f0, 0x000000ff) AM_READWRITE(m68307_internal_base_r, m68307_internal_base_w)
ADDRESS_MAP_END



static MACHINE_CONFIG_FRAGMENT( 68307fragment )
	MCFG_MC68681_ADD("internal68681", 16000000/4) // ?? Mhz - should be specified in inline config
	MCFG_MC68681_IRQ_CALLBACK(WRITELINE(m68307cpu_device, m68307_duart_irq_handler))
	MCFG_MC68681_A_TX_CALLBACK(WRITELINE(m68307cpu_device, m68307_duart_txa))
	MCFG_MC68681_B_TX_CALLBACK(WRITELINE(m68307cpu_device, m68307_duart_txb))
	MCFG_MC68681_INPORT_CALLBACK(READ8(m68307cpu_device, m68307_duart_input_r))
	MCFG_MC68681_OUTPORT_CALLBACK(WRITE8(m68307cpu_device, m68307_duart_output_w))
MACHINE_CONFIG_END

machine_config_constructor m68307cpu_device::device_mconfig_additions() const
{
	return MACHINE_CONFIG_NAME( 68307fragment );
}


m68307cpu_device::m68307cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: m68000_device(mconfig, "MC68307", tag, owner, clock, M68307, 16,24, ADDRESS_MAP_NAME(m68307_internal_map), "mc68307", __FILE__),
	write_irq(*this),
	write_a_tx(*this),
	write_b_tx(*this),
	read_inport(*this),
	write_outport(*this),
	m_duart(*this, "internal68681")
{
	m68307SIM = nullptr;
	m68307MBUS = nullptr;
	m68307TIMER = nullptr;
	m68307_base = 0;
	m68307_scrhigh = 0;
	m68307_scrlow = 0;
	m68307_currentcs = 0;
}






void m68307cpu_device::device_reset()
{
	m68000_device::device_reset();

	if (m68307SIM) m68307SIM->reset();
	if (m68307MBUS) m68307MBUS->reset();
	if (m68307TIMER) m68307TIMER->reset();

	m68307_base = 0xbfff;
	m68307_scrhigh = 0x0007;
	m68307_scrlow = 0xf010;

}


/* todo: is it possible to calculate the address map based on CS when they change
   and install handlers?  Going through this logic for every memory access is
   very slow */

int m68307_calc_cs(m68307cpu_device *m68k, offs_t address)
{
	m68307_sim* sim = m68k->m68307SIM;

	for (int i=0;i<4;i++)
	{
		int br,amask,bra;
		br = sim->m_br[i] & 1;
		amask = ((sim->m_or[i]&0x1ffc)<<11);
		bra = ((sim->m_br[i] & 0x1ffc)<<11);
		if ((br) && ((address & amask) == bra)) return i+1;
	}
	return 0;
}



uint16_t m68307cpu_device::simple_read_immediate_16_m68307(offs_t address)
{
//  m68307_currentcs = m68307_calc_cs(this, address);
	return m_direct->read_word(address);
}

uint8_t m68307cpu_device::read_byte_m68307(offs_t address)
{
//  m68307_currentcs = m68307_calc_cs(this, address);
	return m_space->read_byte(address);
}

uint16_t m68307cpu_device::read_word_m68307(offs_t address)
{
//  m68307_currentcs = m68307_calc_cs(this, address);
	return m_space->read_word(address);
}

uint32_t m68307cpu_device::read_dword_m68307(offs_t address)
{
//  m68307_currentcs = m68307_calc_cs(this, address);
	return m_space->read_dword(address);
}

void m68307cpu_device::write_byte_m68307(offs_t address, uint8_t data)
{
//  m68307_currentcs = m68307_calc_cs(this, address);
	m_space->write_byte(address, data);
}

void m68307cpu_device::write_word_m68307(offs_t address, uint16_t data)
{
//  m68307_currentcs = m68307_calc_cs(this, address);
	m_space->write_word(address, data);
}

void m68307cpu_device::write_dword_m68307(offs_t address, uint32_t data)
{
//  m68307_currentcs = m68307_calc_cs(this, address);
	m_space->write_dword(address, data);
}




void m68307cpu_device::init16_m68307(address_space &space)
{
	m_space = &space;
	m_direct = &space.direct();
	opcode_xor = 0;

	readimm16 = m68k_readimm16_delegate(&m68307cpu_device::simple_read_immediate_16_m68307, this);
	read8 = m68k_read8_delegate(&m68307cpu_device::read_byte_m68307, this);
	read16 = m68k_read16_delegate(&m68307cpu_device::read_word_m68307, this);
	read32 = m68k_read32_delegate(&m68307cpu_device::read_dword_m68307, this);
	write8 = m68k_write8_delegate(&m68307cpu_device::write_byte_m68307, this);
	write16 = m68k_write16_delegate(&m68307cpu_device::write_word_m68307, this);
	write32 = m68k_write32_delegate(&m68307cpu_device::write_dword_m68307, this);
}



void m68307cpu_device::set_port_callbacks(m68307_porta_read_delegate porta_r, m68307_porta_write_delegate porta_w, m68307_portb_read_delegate portb_r, m68307_portb_write_delegate portb_w)
{
	m_m68307_porta_r = porta_r;
	m_m68307_porta_w = porta_w;
	m_m68307_portb_r = portb_r;
	m_m68307_portb_w = portb_w;
}





uint16_t m68307cpu_device::get_cs(offs_t address)
{
	m68307_currentcs = m68307_calc_cs(this, address);

	return m68307_currentcs;
}


/* 68307 specifics - MOVE */

void m68307cpu_device::set_interrupt(int level, int vector)
{
	set_input_line_and_vector(level, HOLD_LINE, vector);
}

void m68307cpu_device::timer0_interrupt()
{
	int prioritylevel = (m68307SIM->m_picr & 0x7000)>>12;
	int vector        = (m68307SIM->m_pivr & 0x00f0) | 0xa;
	set_interrupt(prioritylevel, vector);
}

void m68307cpu_device::timer1_interrupt()
{
	int prioritylevel = (m68307SIM->m_picr & 0x0700)>>8;
	int vector        = (m68307SIM->m_pivr & 0x00f0) | 0xb;
	set_interrupt(prioritylevel, vector);
}


void m68307cpu_device::serial_interrupt(int vector)
{
	int prioritylevel = (m68307SIM->m_picr & 0x0070)>>4;
	set_interrupt(prioritylevel, vector);
}

WRITE_LINE_MEMBER(m68307cpu_device::m68307_duart_irq_handler)
{
	if (state == ASSERT_LINE)
	{
		serial_interrupt(m_duart->get_irq_vector());
	}
}

void m68307cpu_device::mbus_interrupt()
{
	int prioritylevel = (m68307SIM->m_picr & 0x0007)>>0;
	int vector        = (m68307SIM->m_pivr & 0x00f0) | 0xd;
	set_interrupt(prioritylevel, vector);
}

void m68307cpu_device::licr2_interrupt()
{
	int prioritylevel = (m68307SIM->m_licr2 & 0x0007)>>0;
	int vector        = (m68307SIM->m_pivr & 0x00f0) | 0x9;
	m68307SIM->m_licr2 |= 0x8;


	set_interrupt(prioritylevel, vector);
}

void m68307cpu_device::device_start()
{
	init_cpu_m68000();

	/* basic CS logic, timers, mbus, serial logic
	   set via remappable register
	*/

	init16_m68307(*program);

	m68307SIM    = new m68307_sim();
	m68307MBUS   = new m68307_mbus();
	m68307TIMER  = new m68307_timer();

	m68307TIMER->init(this);

	m68307SIM->reset();
	m68307MBUS->reset();
	m68307TIMER->reset();

	internal = &this->space(AS_PROGRAM);
	m68307_base = 0xbfff;
	m68307_scrhigh = 0x0007;
	m68307_scrlow = 0xf010;

	write_irq.resolve_safe();
	write_a_tx.resolve_safe();
	write_b_tx.resolve_safe();
	read_inport.resolve();
	write_outport.resolve_safe();

	set_port_callbacks(m68307_porta_read_delegate(),m68307_porta_write_delegate(),m68307_portb_read_delegate(),m68307_portb_write_delegate());
}



READ16_MEMBER( m68307cpu_device::m68307_internal_base_r )
{
	m68307cpu_device *m68k = this;

	int pc = space.device().safe_pc();
	logerror("%08x m68307_internal_base_r %08x, (%04x)\n", pc, offset*2,mem_mask);

	switch (offset<<1)
	{
		case 0x2: return m68k->m68307_base;
		case 0x4: return m68k->m68307_scrhigh;
		case 0x6: return m68k->m68307_scrlow;
	}

	logerror("(read was illegal?)\n");

	return 0x0000;
}

WRITE16_MEMBER( m68307cpu_device::m68307_internal_base_w )
{
	m68307cpu_device *m68k = this;

	int pc = space.device().safe_pc();
	logerror("%08x m68307_internal_base_w %08x, %04x (%04x)\n", pc, offset*2,data,mem_mask);
	int base;
	//int mask = 0;

	switch (offset<<1)
	{
		case 0x2:
			/* remove old internal handler */
			base = (m68k->m68307_base & 0x0fff) << 12;
			//mask = (m68k->m68307_base & 0xe000) >> 13;
			//if ( m68k->m68307_base & 0x1000 ) mask |= 7;
			m68k->internal->unmap_readwrite(base+0x000, base+0x04f);
			m68k->internal->unmap_readwrite(base+0x100, base+0x11f);
			m68k->internal->unmap_readwrite(base+0x120, base+0x13f);
			m68k->internal->unmap_readwrite(base+0x140, base+0x149);

			/* store new base address */
			COMBINE_DATA(&m68k->m68307_base);

			/* install new internal handler */
			base = (m68k->m68307_base & 0x0fff) << 12;
			//mask = (m68k->m68307_base & 0xe000) >> 13;
			//if ( m68k->m68307_base & 0x1000 ) mask |= 7;
			m68k->internal->install_readwrite_handler(base + 0x000, base + 0x04f, read16_delegate(FUNC(m68307cpu_device::m68307_internal_sim_r),this),    write16_delegate(FUNC(m68307cpu_device::m68307_internal_sim_w),this));
			m68k->internal->install_readwrite_handler(base + 0x100, base + 0x11f, read8_delegate(FUNC(m68307cpu_device::m68307_internal_serial_r),this), write8_delegate(FUNC(m68307cpu_device::m68307_internal_serial_w),this), 0xffff);
			m68k->internal->install_readwrite_handler(base + 0x120, base + 0x13f, read16_delegate(FUNC(m68307cpu_device::m68307_internal_timer_r),this),  write16_delegate(FUNC(m68307cpu_device::m68307_internal_timer_w),this));
			m68k->internal->install_readwrite_handler(base + 0x140, base + 0x149, read8_delegate(FUNC(m68307cpu_device::m68307_internal_mbus_r),this),   write8_delegate(FUNC(m68307cpu_device::m68307_internal_mbus_w),this), 0xffff);


			break;

		case 0x4:
			COMBINE_DATA(&m68k->m68307_scrhigh);
			break;

		case 0x6:
			COMBINE_DATA(&m68k->m68307_scrlow);
			break;

		default:
			logerror("(write was illegal?)\n");
			break;
	}
}