summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/cpu/v60/v60.cpp
blob: 46220d8637eeea03db2fa7c8602a0486f1690cd6 (plain) (tree)
1
2
3
4
5
6
7
8
9
                       
                                           


                                        
                                  


                                                               
 
































































                                                                            
                
                
                 
                     
 

                                                     

 

                                                              
                                                                                                       
                                                                         
 


 


                                                                                                                                                                   
                                                         

                                
                        

 

                                                                
                                                                                                       
                                                                         


 
                                                                                    
 
                                    




                                                              
 
                                                                         
 
                                                    


 
                   


                              







                                                   


                                                                                   
 


                                                                                    
 

                                                             
                                                                           
 

                                      
 


                                                                                         
 


                                                                           
 


                                                                           
 


                                                                           
 


                                                                                                                                                                
 


                                                                                                                                                                 
 

                                                                  
 
 

                                                                            
                                                                            




                                                                              



                          


                                 


































                         

                       









                         
                













                         

                
             
                          
   



                              

 
 
                               
 

                             
            
                                                   

 
                                 
 

                             
            
                                                   

 
                                 
 


                                                           

 
                                             
 
                                                               


                                                                              
                                        


                                                                                            
                                                                      



                                           
                               

                                                    
                     



                                 


                                       
                                 


 
                                                                                     
 

                                       

                                      
                                            
                                                         




                                            
                         


                                                  




                      
                                                                                              
                                                                     


                                     
                 

                   






                   
 
                                  
 
                                                                                
                                                                


                    
                      
 
                               
 


                                
 







                                                                                                             
 





























                                       

                                          



                                                                                                           


            



                                                                                                           

         






































































                                                                                                      
                                                              
                                                                                                       
 
                                

 
 







                                                              

 











                                                                                                                     

                                                              
 





                                                       

 

                               
 










                           

 

                        
 
                       

 

                                       
 
                                                             
 




                                                     

                                            
                                

 
                              
 
                                    
                       
                                    
                           

                                                
 
                                                  
 
                                          
         

 
                                                          



                                       


                                                         


                                
                                                
                              

                 

                                   


         
                                         
 
                              
 

                                     
 
                            
         
                             
                           
                                              




                                                                       

         
// license:BSD-3-Clause
// copyright-holders:Farfetch'd, R. Belmont
// V60.C
// Undiscover the beast!
// Main hacking and coding by Farfetch'd
// Portability fixes by R. Belmont
//
// Emulation for the NEC V60 (uPD70615) and V70 (uPD70632) CPUs
//

/*
Taken from the NEC Semiconductor Selection Guide Guide Book (Oct. 1995):

uPD70615 (V60)
Features:
- Virtual memory (paging method)
- Level protection architecture - 4-level hierarchical protection function
    for system multi-programming.
- Abundant general registers - Thirty two 32-bit general registers for
    optimizing compiler
- Refined instruction set - 2-address method: Arbitrary addressing mode
    can be used independently for source operand and destination operand.
- Abundant address modes and data types - Auto increment/decrement mode
    for string process, and memory indirect addressing for pointer operation
- High cost-to performance chip
- No multiprocessor system - no FRM function for increasing system
    reliability using two or more processors.
- No V20/V30 simulation mode
Address bus: 24 bits
Data bus: 16 bits
Memory space: 4G bytes
Operating frequency: 16 MHz
Package: 120-pin QFP

uPD70616 (V60)
Features:
- Virtual memory (paging method)
- Level protection architecture - 4-level hierarchical protection function
    for system multi-programming.
- Abundant general registers - Thirty two 32-bit general registers for
    optimizing compiler
- Refined instruction set - 2-address method: Arbitrary addressing mode
    can be used independently for source operand and destination operand.
- Abundant address modes and data types - Auto increment/decrement mode
    for string process, and memory indirect addressing for pointer operation
- Multiprocessor system - FRM function for increasing system reliability
    using two or more processors.
- V20/V30 simulation mode
Address bus: 24 bits
Data bus: 16 bits
Memory space: 4G bytes
Operating frequency: 16 MHz
Package: 68-pin PGA

uPD70632 (V70)
Features:
- Virtual memory (paging method)
- Level protection architecture - 4-level hierarchical protection function
    for system multi-programming.
- Abundant general registers - Thirty two 32-bit general registers for
    optimizing compiler
- Refined instruction set - 2-address method: Arbitrary addressing mode
    can be used independently for source operand and destination operand.
- Abundant address modes and data types - Auto increment/decrement mode
    for string process, and memory indirect addressing for pointer operation
- Multiprocessor system - FRM function for increasing system reliability
    using two or more processors.
- V20/V30 simulation mode
Address bus: 32 bits
Data bus: 32 bits
Memory space: 4G bytes
Operating frequency: 20 MHz
Package: 132-pin PGA, 200-pin QFP
*/

#include "emu.h"
#include "v60.h"
#include "v60d.h"
#include "debugger.h"

DEFINE_DEVICE_TYPE(V60, v60_device, "v60", "NEC V60")
DEFINE_DEVICE_TYPE(V70, v70_device, "v70", "NEC V70")


// Set m_PIR (Processor ID) for NEC m_ LSB is reserved to NEC,
// so I don't know what it contains.
v60_device::v60_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: v60_device(mconfig, V60, tag, owner, clock, 16, 24, 0x00006000)
{
}


v60_device::v60_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int databits, int addrbits, uint32_t pir)
	: cpu_device(mconfig, type, tag, owner, clock)
	, m_program_config("program", ENDIANNESS_LITTLE, databits, addrbits, 0)
	, m_io_config("io", ENDIANNESS_LITTLE, 16, 24, 0)
	, m_start_pc(0xfffffff0)
{
	m_reg[45] = pir;
}

// Set m_PIR (Processor ID) for NEC v70. LSB is reserved to NEC,
// so I don't know what it contains.
v70_device::v70_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: v60_device(mconfig, V70, tag, owner, clock, 32, 32, 0x00007000)
{
}

device_memory_interface::space_config_vector v60_device::memory_space_config() const
{
	return space_config_vector {
		std::make_pair(AS_PROGRAM, &m_program_config),
		std::make_pair(AS_IO,      &m_io_config)
	};
}


std::unique_ptr<util::disasm_interface> v60_device::create_disassembler()
{
	return std::make_unique<v60_disassembler>();
}


// memory accessors
#define OpRead8(a)   m_pr8(a)
#define OpRead16(a)  m_pr16(a)
#define OpRead32(a)  m_pr32(a)


// macros stolen from MAME for flags calc
// note that these types are in x86 naming:
// byte = 8 bit, word = 16 bit, long = 32 bit

// parameter x = result, y = source 1, z = source 2

#define SetOFL_Add(x, y,z)  (_OV = (((x) ^ (y)) & ((x) ^ (z)) & 0x80000000) ? 1: 0)
#define SetOFW_Add(x, y,z)  (_OV = (((x) ^ (y)) & ((x) ^ (z)) & 0x8000) ? 1 : 0)
#define SetOFB_Add(x, y,z)  (_OV = (((x) ^ (y)) & ((x) ^ (z)) & 0x80) ? 1 : 0)

#define SetOFL_Sub(x, y,z)  (_OV = (((z) ^ (y)) & ((z) ^ (x)) & 0x80000000) ? 1 : 0)
#define SetOFW_Sub(x, y,z)  (_OV = (((z) ^ (y)) & ((z) ^ (x)) & 0x8000) ? 1 : 0)
#define SetOFB_Sub(x, y,z)  (_OV = (((z) ^ (y)) & ((z) ^ (x)) & 0x80) ? 1 : 0)

#define SetCFB(x)           {_CY = ((x) & 0x100) ? 1 : 0; }
#define SetCFW(x)           {_CY = ((x) & 0x10000) ? 1 : 0; }
#define SetCFL(x)           {_CY = ((x) & (((uint64_t)1) << 32)) ? 1 : 0; }

#define SetSF(x)            (_S = (x))
#define SetZF(x)            (_Z = (x))

#define SetSZPF_Byte(x)     {_Z = ((uint8_t)(x) == 0);  _S = ((x)&0x80) ? 1 : 0; }
#define SetSZPF_Word(x)     {_Z = ((uint16_t)(x) == 0);  _S = ((x)&0x8000) ? 1 : 0; }
#define SetSZPF_Long(x)     {_Z = ((uint32_t)(x) == 0);  _S = ((x)&0x80000000) ? 1 : 0; }

#define ORB(dst, src)       { (dst) |= (src); _OV = 0; SetSZPF_Byte(dst); }
#define ORW(dst, src)       { (dst) |= (src); _OV = 0; SetSZPF_Word(dst); }
#define ORL(dst, src)       { (dst) |= (src); _OV = 0; SetSZPF_Long(dst); }

#define ANDB(dst, src)      { (dst) &= (src); _OV = 0; SetSZPF_Byte(dst); }
#define ANDW(dst, src)      { (dst) &= (src); _OV = 0; SetSZPF_Word(dst); }
#define ANDL(dst, src)      { (dst) &= (src); _OV = 0; SetSZPF_Long(dst); }

#define XORB(dst, src)      { (dst) ^= (src); _OV = 0; SetSZPF_Byte(dst); }
#define XORW(dst, src)      { (dst) ^= (src); _OV = 0; SetSZPF_Word(dst); }
#define XORL(dst, src)      { (dst) ^= (src); _OV = 0; SetSZPF_Long(dst); }

#define SUBB(dst, src)      { unsigned res = (dst) - (src); SetCFB(res); SetOFB_Sub(res, src, dst); SetSZPF_Byte(res); dst = (uint8_t)res; }
#define SUBW(dst, src)      { unsigned res = (dst) - (src); SetCFW(res); SetOFW_Sub(res, src, dst); SetSZPF_Word(res); dst = (uint16_t)res; }
#define SUBL(dst, src)      { uint64_t res = (uint64_t)(dst) - (int64_t)(src); SetCFL(res); SetOFL_Sub(res, src, dst); SetSZPF_Long(res); dst = (uint32_t)res; }

#define ADDB(dst, src)      { unsigned res = (dst) + (src); SetCFB(res); SetOFB_Add(res, src, dst); SetSZPF_Byte(res); dst = (uint8_t)res; }
#define ADDW(dst, src)      { unsigned res = (dst) + (src); SetCFW(res); SetOFW_Add(res, src, dst); SetSZPF_Word(res); dst = (uint16_t)res; }
#define ADDL(dst, src)      { uint64_t res = (uint64_t)(dst) + (uint64_t)(src); SetCFL(res); SetOFL_Add(res, src, dst); SetSZPF_Long(res); dst = (uint32_t)res; }

#define SETREG8(a, b)       (a) = ((a) & ~0xff) | ((b) & 0xff)
#define SETREG16(a, b)      (a) = ((a) & ~0xffff) | ((b) & 0xffff)


/*
 * Prevent warnings on NetBSD.  All identifiers beginning with an underscore
 * followed by an uppercase letter are reserved by the C standard (ISO / IEC
 * 9899:1999, 7.1.3) to be used by the implementation.  It'd be best to rename
 * all such instances, but this is less intrusive and error-prone.
 */
#undef _S

#define _CY     m_flags.CY
#define _OV     m_flags.OV
#define _S      m_flags.S
#define _Z      m_flags.Z


// Defines of all v60 register...
#define R0      m_reg[0]
#define R1      m_reg[1]
#define R2      m_reg[2]
#define R3      m_reg[3]
#define R4      m_reg[4]
#define R5      m_reg[5]
#define R6      m_reg[6]
#define R7      m_reg[7]
#define R8      m_reg[8]
#define R9      m_reg[9]
#define R10     m_reg[10]
#define R11     m_reg[11]
#define R12     m_reg[12]
#define R13     m_reg[13]
#define R14     m_reg[14]
#define R15     m_reg[15]
#define R16     m_reg[16]
#define R17     m_reg[17]
#define R18     m_reg[18]
#define R19     m_reg[19]
#define R20     m_reg[20]
#define R21     m_reg[21]
#define R22     m_reg[22]
#define R23     m_reg[23]
#define R24     m_reg[24]
#define R25     m_reg[25]
#define R26     m_reg[26]
#define R27     m_reg[27]
#define R28     m_reg[28]
#define AP      m_reg[29]
#define FP      m_reg[30]
#define SP      m_reg[31]

#define PC      m_reg[32]
#define PSW     m_reg[33]

// Privileged registers
#define ISP     m_reg[36]
#define L0SP    m_reg[37]
#define L1SP    m_reg[38]
#define L2SP    m_reg[39]
#define L3SP    m_reg[40]
#define SBR     m_reg[41]
#define TR      m_reg[42]
#define SYCW    m_reg[43]
#define TKCW    m_reg[44]
#define PIR     m_reg[45]
//10-14 reserved
#define PSW2    m_reg[51]
#define ATBR0   m_reg[52]
#define ATLR0   m_reg[53]
#define ATBR1   m_reg[54]
#define ATLR1   m_reg[55]
#define ATBR2   m_reg[56]
#define ATLR2   m_reg[57]
#define ATBR3   m_reg[58]
#define ATLR3   m_reg[59]
#define TRMODE  m_reg[60]
#define ADTR0   m_reg[61]
#define ADTR1   m_reg[62]
#define ADTMR0  m_reg[63]
#define ADTMR1  m_reg[64]
//29-31 reserved

// Defines...
#define NORMALIZEFLAGS() \
{ \
	_S    = _S  ? 1 : 0; \
	_OV   = _OV ? 1 : 0; \
	_Z    = _Z  ? 1 : 0; \
	_CY   = _CY ? 1 : 0; \
}


void v60_device::v60SaveStack()
{
	if (PSW & 0x10000000)
		ISP = SP;
	else
		m_reg[37 + ((PSW >> 24) & 3)] = SP;
}

void v60_device::v60ReloadStack()
{
	if (PSW & 0x10000000)
		SP = ISP;
	else
		SP = m_reg[37 + ((PSW >> 24) & 3)];
}

uint32_t v60_device::v60ReadPSW()
{
	PSW &= 0xfffffff0;
	PSW |= (_Z?1:0) | (_S?2:0) | (_OV?4:0) | (_CY?8:0);
	return PSW;
}

void v60_device::v60WritePSW(uint32_t newval)
{
	/* determine if we need to save / restore the stacks */
	int updateStack = 0;

	/* if the interrupt state is changing, we definitely need to update */
	if ((newval ^ PSW) & 0x10000000)
		updateStack = 1;

	/* if we are not in interrupt mode and the level is changing, we also must update */
	else if (!(PSW & 0x10000000) && ((newval ^ PSW) & 0x03000000))
		updateStack = 1;

	/* save the previous stack value */
	if (updateStack)
		v60SaveStack();

	/* set the new value and update the flags */
	PSW = newval;
	_Z =  (uint8_t)(PSW & 1);
	_S =  (uint8_t)(PSW & 2);
	_OV = (uint8_t)(PSW & 4);
	_CY = (uint8_t)(PSW & 8);

	/* fetch the new stack value */
	if (updateStack)
		v60ReloadStack();
}


uint32_t v60_device::v60_update_psw_for_exception(int is_interrupt, int target_level)
{
	uint32_t oldPSW = v60ReadPSW();
	uint32_t newPSW = oldPSW;

	// Change to interrupt context
	newPSW &= ~(3 << 24);  // PSW.EL = 0
	newPSW |= target_level << 24; // set target level
	newPSW &= ~(1 << 18);  // PSW.IE = 0
	newPSW &= ~(1 << 16);  // PSW.TE = 0
	newPSW &= ~(1 << 27);  // PSW.TP = 0
	newPSW &= ~(1 << 17);  // PSW.AE = 0
	newPSW &= ~(1 << 29);  // PSW.EM = 0
	if (is_interrupt)
		newPSW |=  (1 << 28);// PSW.IS = 1
	newPSW |=  (1 << 31);  // PSW.ASA = 1
	v60WritePSW(newPSW);

	return oldPSW;
}


#define GETINTVECT(nint)                    m_program->read_dword((SBR & ~0xfff) + (nint) * 4)
#define EXCEPTION_CODE_AND_SIZE(code, size) (((code) << 16) | (size))


// Addressing mode decoding functions
#include "am.hxx"

// Opcode functions
#include "op12.hxx"
#include "op2.hxx"
#include "op3.hxx"
#include "op4.hxx"
#include "op5.hxx"
#include "op6.hxx"
#include "op7a.hxx"

uint32_t v60_device::opUNHANDLED()
{
	fatalerror("Unhandled OpCode found : %02x at %08x\n", OpRead16(PC), PC);
	//return 0; /* never reached, fatalerror won't return */
}

// Opcode jump table
#include "optable.hxx"

void v60_device::device_start()
{
	m_stall_io = 0;
	m_irq_line = CLEAR_LINE;
	m_nmi_line = CLEAR_LINE;

	for ( int i = 0; i < 68; i++ )
	{
		// Don't set SP (31), PCi (32), PSW (33), SBR (41), SYCW (43), TKCW (44), PIR (45), PSW2 (51)
		if ( i != 31 && i != 32 && i != 33 && i != 41 && i != 43 && i != 44 && i != 45 && i != 51 )
		{
			m_reg[i] = 0;
		}
	}

	m_flags.CY = 0;
	m_flags.OV = 0;
	m_flags.S = 0;
	m_flags.Z = 0;

	m_op1 = 0;
	m_op2 = 0;
	m_flag1 = 0;
	m_flag2 = 0;
	m_instflags = 0;
	m_lenop1 = 0;
	m_lenop2 = 0;
	m_subop = 0;
	m_bamoffset1 = 0;
	m_bamoffset2 = 0;
	m_amflag = 0;
	m_amout = 0;
	m_bamoffset = 0;
	m_amlength1 = 0;
	m_amlength2 = 0;
	m_modadd = 0;
	m_modm = 0;
	m_modval = 0;
	m_modval2 = 0;
	m_modwritevalb = 0;
	m_modwritevalh = 0;
	m_modwritevalw = 0;
	m_moddim = 0;

	m_program = &space(AS_PROGRAM);
	if (m_program->data_width() == 16)
	{
		m_program->cache(m_cache16);
		m_pr8  = [this](offs_t address) -> u8  { return m_cache16.read_byte(address); };
		m_pr16 = [this](offs_t address) -> u16 { return m_cache16.read_word_unaligned(address); };
		m_pr32 = [this](offs_t address) -> u32 { return m_cache16.read_dword_unaligned(address); };
	}
	else
	{
		m_program->cache(m_cache32);
		m_pr8  = [this](offs_t address) -> u8  { return m_cache32.read_byte(address); };
		m_pr16 = [this](offs_t address) -> u16 { return m_cache32.read_word_unaligned(address); };
		m_pr32 = [this](offs_t address) -> u32 { return m_cache32.read_dword_unaligned(address); };
	}

	m_io = &space(AS_IO);

	save_item(NAME(m_reg));
	save_item(NAME(m_irq_line));
	save_item(NAME(m_nmi_line));
	save_item(NAME(m_PPC));
	save_item(NAME(_CY));
	save_item(NAME(_OV));
	save_item(NAME(_S));
	save_item(NAME(_Z));

	state_add( V60_R0,     "R0",     R0).formatstr("%08X");
	state_add( V60_R1,     "R1",     R1).formatstr("%08X");
	state_add( V60_R2,     "R2",     R2).formatstr("%08X");
	state_add( V60_R3,     "R3",     R3).formatstr("%08X");
	state_add( V60_R4,     "R4",     R4).formatstr("%08X");
	state_add( V60_R5,     "R5",     R5).formatstr("%08X");
	state_add( V60_R6,     "R6",     R6).formatstr("%08X");
	state_add( V60_R7,     "R7",     R7).formatstr("%08X");
	state_add( V60_R8,     "R8",     R8).formatstr("%08X");
	state_add( V60_R9,     "R9",     R9).formatstr("%08X");
	state_add( V60_R10,    "R10",    R10).formatstr("%08X");
	state_add( V60_R11,    "R11",    R11).formatstr("%08X");
	state_add( V60_R12,    "R12",    R12).formatstr("%08X");
	state_add( V60_R13,    "R13",    R13).formatstr("%08X");
	state_add( V60_R14,    "R14",    R14).formatstr("%08X");
	state_add( V60_R15,    "R15",    R15).formatstr("%08X");
	state_add( V60_R16,    "R16",    R16).formatstr("%08X");
	state_add( V60_R17,    "R17",    R17).formatstr("%08X");
	state_add( V60_R18,    "R18",    R18).formatstr("%08X");
	state_add( V60_R19,    "R19",    R19).formatstr("%08X");
	state_add( V60_R20,    "R20",    R20).formatstr("%08X");
	state_add( V60_R21,    "R21",    R21).formatstr("%08X");
	state_add( V60_R22,    "R22",    R22).formatstr("%08X");
	state_add( V60_R23,    "R23",    R23).formatstr("%08X");
	state_add( V60_R24,    "R24",    R24).formatstr("%08X");
	state_add( V60_R25,    "R25",    R25).formatstr("%08X");
	state_add( V60_R26,    "R26",    R26).formatstr("%08X");
	state_add( V60_R27,    "R27",    R27).formatstr("%08X");
	state_add( V60_R28,    "R28",    R28).formatstr("%08X");
	state_add( V60_AP,     "AP",     AP).formatstr("%08X");
	state_add( V60_FP,     "FP",     FP).formatstr("%08X");
	state_add( V60_SP,     "SP",     SP).formatstr("%08X");
	state_add( V60_PC,     "PC",     PC).formatstr("%08X");
	state_add( V60_PSW,    "PSW",    m_debugger_temp).callimport().callexport().formatstr("%08X");
	state_add( V60_ISP,    "ISP",    ISP).formatstr("%08X");
	state_add( V60_L0SP,   "L0SP",   L0SP).formatstr("%08X");
	state_add( V60_L1SP,   "L1SP",   L1SP).formatstr("%08X");
	state_add( V60_L2SP,   "L2SP",   L2SP).formatstr("%08X");
	state_add( V60_L3SP,   "L3SP",   L3SP).formatstr("%08X");
	state_add( V60_SBR,    "SBR",    SBR).formatstr("%08X");
	state_add( V60_TR,     "TR",     TR).formatstr("%08X");
	state_add( V60_SYCW,   "SYCW",   SYCW).formatstr("%08X");
	state_add( V60_TKCW,   "TKCW",   TKCW).formatstr("%08X");
	state_add( V60_PIR,    "PIR",    PIR).formatstr("%08X");
	state_add( V60_PSW2,   "PSW2",   PSW2).formatstr("%08X");
	state_add( V60_ATBR0,  "ATBR0",  ATBR0).formatstr("%08X");
	state_add( V60_ATLR0,  "ATLR0",  ATLR0).formatstr("%08X");
	state_add( V60_ATBR1,  "ATBR1",  ATBR1).formatstr("%08X");
	state_add( V60_ATLR1,  "ATLR1",  ATLR1).formatstr("%08X");
	state_add( V60_ATBR2,  "ATBR2",  ATBR2).formatstr("%08X");
	state_add( V60_ATLR2,  "ATLR2",  ATLR2).formatstr("%08X");
	state_add( V60_ATBR3,  "ATBR3",  ATBR3).formatstr("%08X");
	state_add( V60_ATLR3,  "ATLR3",  ATLR3).formatstr("%08X");
	state_add( V60_TRMODE, "TRMODE", TRMODE).formatstr("%08X");
	state_add( V60_ADTR0,  "ADTR0",  ADTR0).formatstr("%08X");
	state_add( V60_ADTR1,  "ADTR1",  ADTR1).formatstr("%08X");
	state_add( V60_ADTMR0, "ADTMR0", ADTMR0).formatstr("%08X");
	state_add( V60_ADTMR1, "ADTMR1", ADTMR1).formatstr("%08X");

	state_add( STATE_GENPC, "GENPC", PC).noshow();
	state_add( STATE_GENPCBASE, "CURPC", m_PPC ).noshow();
	state_add( STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).callimport().formatstr("%7s").noshow();

	set_icountptr(m_icount);
}


void v60_device::state_export(const device_state_entry &entry)
{
	switch (entry.index())
	{
		case V60_PSW:
			m_debugger_temp = v60ReadPSW();
			break;
	}
}

void v60_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
		switch(entry.index()) {
		case STATE_GENFLAGS:
				str = string_format("%c%c%c%c",
												PSW & 1 ? 'Z' : '.',
												PSW & 2 ? 'S' : '.',
												PSW & 4 ? 'O' : '.',
												PSW & 8 ? 'C' : '.');
				break;
		}
}

void v60_device::state_import(const device_state_entry &entry)
{
	switch (entry.index())
	{
		case V60_PSW:
			v60WritePSW( m_debugger_temp );
			break;
	}
}


void v60_device::device_reset()
{
	PSW   = 0x10000000;
	PC    = m_start_pc;
	SBR   = 0x00000000;
	SYCW  = 0x00000070;
	TKCW  = 0x0000e000;
	PSW2  = 0x0000f002;

	_CY   = 0;
	_OV   = 0;
	_S    = 0;
	_Z    = 0;
}


void v60_device::stall()
{
	m_stall_io = 1;
}


void v60_device::v60_do_irq(int vector)
{
	uint32_t oldPSW = v60_update_psw_for_exception(1, 0);

	// Push PC and PSW onto the stack
	SP-=4;
	m_program->write_dword_unaligned(SP, oldPSW);
	SP-=4;
	m_program->write_dword_unaligned(SP, PC);

	// Jump to vector for user interrupt
	PC = GETINTVECT(vector);
}

void v60_device::v60_try_irq()
{
	if(m_irq_line == CLEAR_LINE)
		return;
	if((PSW & (1 << 18)) != 0) {
		int vector;
		if(m_irq_line != ASSERT_LINE)
			m_irq_line = CLEAR_LINE;

		vector = standard_irq_callback(0);

		v60_do_irq(vector + 0x40);
	}
}

void v60_device::execute_set_input(int irqline, int state)
{
	if(irqline == INPUT_LINE_NMI) {
		switch(state) {
		case ASSERT_LINE:
			if(m_nmi_line == CLEAR_LINE) {
				m_nmi_line = ASSERT_LINE;
				v60_do_irq(2);
			}
			break;
		case CLEAR_LINE:
			m_nmi_line = CLEAR_LINE;
			break;
		}
	} else {
		m_irq_line = state;
		v60_try_irq();
	}
}

// Actual cycles / instruction is unknown

void v60_device::execute_run()
{
	if (m_irq_line != CLEAR_LINE)
		v60_try_irq();

	while (m_icount > 0)
	{
		uint32_t inc;
		m_PPC = PC;
		debugger_instruction_hook(PC);
		m_icount -= 8;  /* fix me -- this is just an average */
		inc = (this->*s_OpCodeTable[OpRead8(PC)])();
		PC += inc;
		if (m_irq_line != CLEAR_LINE)
			v60_try_irq();
	}
}