diff options
author | 2018-08-12 02:11:58 -0400 | |
---|---|---|
committer | 2018-08-12 02:11:58 -0400 | |
commit | a459faa90fceb95cdd6af60276d48f949f115fb3 (patch) | |
tree | fda7d121d3507de079511da07cea68686fe57077 /src/devices/cpu/nec | |
parent | 33983bf43e60e26361a07bd8922860bbf311fda5 (diff) |
Emulate V33/V53 expanded addressing mode, including BRKXA and RETXA instructions
Mask address expressions correctly in debug memory view when using physical addresses beyond logical limits
Diffstat (limited to 'src/devices/cpu/nec')
-rw-r--r-- | src/devices/cpu/nec/nec.cpp | 69 | ||||
-rw-r--r-- | src/devices/cpu/nec/nec.h | 16 | ||||
-rw-r--r-- | src/devices/cpu/nec/necinstr.hxx | 4 | ||||
-rw-r--r-- | src/devices/cpu/nec/necpriv.h | 10 | ||||
-rw-r--r-- | src/devices/cpu/nec/v25priv.h | 2 | ||||
-rw-r--r-- | src/devices/cpu/nec/v53.cpp | 11 | ||||
-rw-r--r-- | src/devices/cpu/nec/v53.h | 4 |
7 files changed, 86 insertions, 30 deletions
diff --git a/src/devices/cpu/nec/nec.cpp b/src/devices/cpu/nec/nec.cpp index 9296d952ba5..b4205b54a2c 100644 --- a/src/devices/cpu/nec/nec.cpp +++ b/src/devices/cpu/nec/nec.cpp @@ -122,14 +122,14 @@ DEFINE_DEVICE_TYPE(V33, v33_device, "v33", "NEC V33") DEFINE_DEVICE_TYPE(V33A, v33a_device, "v33a", "NEC V33A") - -nec_common_device::nec_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) +nec_common_device::nec_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, address_map_constructor internal_port_map) : cpu_device(mconfig, type, tag, owner, clock) - , m_program_config("program", ENDIANNESS_LITTLE, is_16bit ? 16 : 8, 20, 0) - , m_io_config("io", ENDIANNESS_LITTLE, is_16bit ? 16 : 8, 16, 0) + , m_program_config("program", ENDIANNESS_LITTLE, is_16bit ? 16 : 8, chip_type == V33_TYPE ? 24 : 20, 0, chip_type == V33_TYPE ? 20 : 0, chip_type == V33_TYPE ? 14 : 0) + , m_io_config("io", ENDIANNESS_LITTLE, is_16bit ? 16 : 8, 16, 0, internal_port_map) , m_prefetch_size(prefetch_size) , m_prefetch_cycles(prefetch_cycles) , m_chip_type(chip_type) + , m_v33_transtable(*this, "v33_transtable") { } @@ -158,14 +158,43 @@ device_memory_interface::space_config_vector nec_common_device::memory_space_con * complete guess below, nbbatman will not work * properly without. */ v33_device::v33_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nec_common_device(mconfig, V33, tag, owner, clock, true, 6, 1, V33_TYPE) + : nec_common_device(mconfig, V33, tag, owner, clock, true, 6, 1, V33_TYPE, address_map_constructor(FUNC(v33_device::v33_internal_port_map), this)) { } v33a_device::v33a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : nec_common_device(mconfig, V33A, tag, owner, clock, true, 6, 1, V33_TYPE) + : nec_common_device(mconfig, V33A, tag, owner, clock, true, 6, 1, V33_TYPE, address_map_constructor(FUNC(v33a_device::v33_internal_port_map), this)) +{ +} + + +uint16_t nec_common_device::aex_r() +{ + return m_aex ? 1 : 0; +} + +void nec_common_device::v33_internal_port_map(address_map &map) { + map(0xff00, 0xff7f).ram().share("v33_transtable"); + map(0xff80, 0xff81).r(FUNC(nec_common_device::aex_r)).unmapw(); + map(0xff82, 0xffff).unmaprw(); +} + + +offs_t nec_common_device::v33_translate(offs_t addr) +{ + if (m_aex) + return uint32_t(m_v33_transtable[(addr >> 14) & 63]) << 14 | (addr & 0x03fff); + else + return addr & 0xfffff; +} + +bool nec_common_device::memory_translate(int spacenum, int intention, offs_t &address) +{ + if (m_chip_type == V33_TYPE && spacenum == AS_PROGRAM) + address = v33_translate(address); + return true; } @@ -265,6 +294,9 @@ void nec_common_device::device_reset() m_poll_state = 1; m_halted = 0; + if (m_chip_type == V33_TYPE) + m_aex = false; + Sreg(PS) = 0xffff; Sreg(SS) = 0; Sreg(DS0) = 0; @@ -300,6 +332,13 @@ void nec_common_device::nec_trap() nec_interrupt(NEC_TRAP_VECTOR, BRK); } +void nec_common_device::nec_brk(unsigned int_num) +{ + m_ip = read_mem_word(int_num*4); + Sreg(PS) = read_mem_word(int_num*4+2); + CHANGE_PC; +} + void nec_common_device::external_int() { if (m_pending_irq & NMI_IRQ) @@ -418,10 +457,19 @@ void nec_common_device::device_start() save_item(NAME(m_prefetch_reset)); m_program = &space(AS_PROGRAM); - if(m_program->data_width() == 8) { + if (m_program->data_width() == 8) + { auto cache = m_program->cache<0, 0, ENDIANNESS_LITTLE>(); m_dr8 = [cache](offs_t address) -> u8 { return cache->read_byte(address); }; - } else { + } + else if (m_chip_type == V33_TYPE) + { + save_item(NAME(m_aex)); + auto cache = m_program->cache<1, 0, ENDIANNESS_LITTLE>(); + m_dr8 = [cache, this](offs_t address) -> u8 { return cache->read_byte(v33_translate(address)); }; + } + else + { auto cache = m_program->cache<1, 0, ENDIANNESS_LITTLE>(); m_dr8 = [cache](offs_t address) -> u8 { return cache->read_byte(address); }; } @@ -444,6 +492,9 @@ void nec_common_device::device_start() state_add( NEC_SS, "SS", Sreg(SS)).formatstr("%04X"); state_add( NEC_DS, "DS0", Sreg(DS0)).formatstr("%04X"); + if (m_chip_type == V33_TYPE) + state_add(NEC_AEX, "AEX", m_aex); + state_add( STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow(); state_add( STATE_GENPCBASE, "CURPC", m_debugger_temp).callexport().noshow(); state_add( STATE_GENSP, "GENSP", m_debugger_temp).callimport().callexport().noshow(); @@ -485,7 +536,7 @@ void nec_common_device::state_import(const device_state_entry &entry) switch (entry.index()) { case NEC_PC: - if( m_debugger_temp - (Sreg(PS)<<4) < 0x10000 ) + if (m_debugger_temp - (Sreg(PS)<<4) < 0x10000) { m_ip = m_debugger_temp - (Sreg(PS)<<4); } diff --git a/src/devices/cpu/nec/nec.h b/src/devices/cpu/nec/nec.h index 5d8e2ad3338..243fbfb5a7e 100644 --- a/src/devices/cpu/nec/nec.h +++ b/src/devices/cpu/nec/nec.h @@ -14,6 +14,7 @@ enum NEC_PC=0, NEC_IP, NEC_AW, NEC_CW, NEC_DW, NEC_BW, NEC_SP, NEC_BP, NEC_IX, NEC_IY, NEC_FLAGS, NEC_ES, NEC_CS, NEC_SS, NEC_DS, + NEC_AEX, NEC_PENDING }; @@ -22,7 +23,7 @@ class nec_common_device : public cpu_device { protected: // construction/destruction - nec_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); + nec_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, address_map_constructor internal_port_map = address_map_constructor()); // device-level overrides virtual void device_start() override; @@ -39,6 +40,7 @@ protected: // device_memory_interface overrides virtual space_config_vector memory_space_config() const override; + virtual bool memory_translate(int spacenum, int intention, offs_t &address) override; // device_state_interface overrides virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; @@ -93,11 +95,14 @@ private: uint8_t m_prefetch_cycles; int8_t m_prefetch_count; uint8_t m_prefetch_reset; - uint32_t m_chip_type; + const uint32_t m_chip_type; uint32_t m_prefix_base; /* base address of the latest prefix segment */ uint8_t m_seg_prefix; /* prefix segment indicator */ + bool m_aex; + optional_shared_ptr<uint16_t> m_v33_transtable; + uint32_t m_EA; uint16_t m_EO; uint16_t m_E16; @@ -109,6 +114,12 @@ private: static const nec_ophandler s_nec_instruction[256]; static const nec_eahandler s_GetEA[192]; +protected: + void v33_internal_port_map(address_map &map); + uint16_t aex_r(); + offs_t v33_translate(offs_t addr); + +private: inline void prefetch(); void do_prefetch(int previous_ICount); inline uint8_t fetch(); @@ -116,6 +127,7 @@ private: uint8_t fetchop(); void nec_interrupt(unsigned int_num, int source); void nec_trap(); + void nec_brk(unsigned int_num); void external_int(); void i_add_br8(); diff --git a/src/devices/cpu/nec/necinstr.hxx b/src/devices/cpu/nec/necinstr.hxx index 0499c49c65b..f1209d675a9 100644 --- a/src/devices/cpu/nec/necinstr.hxx +++ b/src/devices/cpu/nec/necinstr.hxx @@ -45,8 +45,8 @@ OP( 0x0f, i_pre_nec ) { uint32_t ModRM, tmp, tmp2; case 0x2a : ModRM = fetch(); tmp = GetRMByte(ModRM); tmp2 = (Breg(AL) & 0xf)<<4; Breg(AL) = (Breg(AL) & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break; case 0x31 : ModRM = fetch(); ModRM=0; logerror("%06x: Unimplemented bitfield INS\n",PC()); break; case 0x33 : ModRM = fetch(); ModRM=0; logerror("%06x: Unimplemented bitfield EXT\n",PC()); break; - case 0xe0 : ModRM = fetch(); ModRM=0; logerror("%06x: V33 unimplemented BRKXA (break to expansion address)\n",PC()); break; - case 0xf0 : ModRM = fetch(); ModRM=0; logerror("%06x: V33 unimplemented RETXA (return from expansion address)\n",PC()); break; + case 0xe0 : BRKXA(true); CLK(12); break; + case 0xf0 : BRKXA(false); CLK(12); break; case 0xff : ModRM = fetch(); ModRM=0; logerror("%06x: unimplemented BRKEM (break to 8080 emulation mode)\n",PC()); break; default: logerror("%06x: Unknown V20 instruction\n",PC()); break; } diff --git a/src/devices/cpu/nec/necpriv.h b/src/devices/cpu/nec/necpriv.h index 459fa5017b4..08ce013f891 100644 --- a/src/devices/cpu/nec/necpriv.h +++ b/src/devices/cpu/nec/necpriv.h @@ -52,10 +52,10 @@ enum BREGS { /************************************************************************/ -#define read_mem_byte(a) m_program->read_byte(a) -#define read_mem_word(a) m_program->read_word_unaligned(a) -#define write_mem_byte(a,d) m_program->write_byte((a),(d)) -#define write_mem_word(a,d) m_program->write_word_unaligned((a),(d)) +#define read_mem_byte(a) m_program->read_byte(m_chip_type == V33_TYPE ? v33_translate(a) : (a)) +#define read_mem_word(a) m_program->read_word_unaligned(m_chip_type == V33_TYPE ? v33_translate(a) : (a)) +#define write_mem_byte(a,d) m_program->write_byte(m_chip_type == V33_TYPE ? v33_translate(a) : (a), (d)) +#define write_mem_word(a,d) m_program->write_word_unaligned(m_chip_type == V33_TYPE ? v33_translate(a) : (a), (d)) #define read_port_byte(a) m_io->read_byte(a) #define read_port_word(a) m_io->read_word_unaligned(a) @@ -84,6 +84,8 @@ enum BREGS { #define PUSH(val) { Wreg(SP) -= 2; write_mem_word(((Sreg(SS)<<4)+Wreg(SP)), val); } #define POP(var) { Wreg(SP) += 2; var = read_mem_word(((Sreg(SS)<<4) + ((Wreg(SP)-2) & 0xffff))); } +#define BRKXA(aex) { if (m_chip_type == V33_TYPE) { nec_brk(fetch()); m_aex = aex; } else logerror("%06x: %sXA instruction is V33 exclusive\n", PC(), aex ? "BRK" : "RET"); } + #define GetModRM uint32_t ModRM=fetch() /* Cycle count macros: diff --git a/src/devices/cpu/nec/v25priv.h b/src/devices/cpu/nec/v25priv.h index eb60c8f041d..ee885142dd5 100644 --- a/src/devices/cpu/nec/v25priv.h +++ b/src/devices/cpu/nec/v25priv.h @@ -141,6 +141,8 @@ enum BREGS { #define PUSH(val) { Wreg(SP) -= 2; write_mem_word(((Sreg(SS)<<4)+Wreg(SP)), val); } #define POP(var) { Wreg(SP) += 2; var = read_mem_word(((Sreg(SS)<<4) + ((Wreg(SP)-2) & 0xffff))); } +#define BRKXA(aex) { logerror("%06x: %sXA instruction is V33 exclusive\n", PC(), aex ? "BRK" : "RET"); } + #define GetModRM uint32_t ModRM=fetch() /* Cycle count macros: diff --git a/src/devices/cpu/nec/v53.cpp b/src/devices/cpu/nec/v53.cpp index 410867e804e..697d12d461f 100644 --- a/src/devices/cpu/nec/v53.cpp +++ b/src/devices/cpu/nec/v53.cpp @@ -172,13 +172,6 @@ m_DST = 0x00; m_DMK = 0x0f; */ -device_memory_interface::space_config_vector v53_base_device::memory_space_config() const -{ - auto r = nec_common_device::memory_space_config(); - r.emplace_back(std::make_pair(AS_IO, &m_io_space_config)); - return r; -} - void v53_base_device::device_reset() { nec_common_device::device_reset(); @@ -416,6 +409,7 @@ WRITE_LINE_MEMBER(v53_base_device::hack_w) void v53_base_device::v53_internal_port_map(address_map &map) { + v33_internal_port_map(map); map(0xffe0, 0xffe0).w(FUNC(v53_base_device::BSEL_w)); // 0xffe0 // uPD71037 DMA mode bank selection register map(0xffe1, 0xffe1).w(FUNC(v53_base_device::BADR_w)); // 0xffe1 // uPD71037 DMA mode bank register peripheral mapping (also uses OPHA) // AM_RANGE(0xffe2, 0xffe3) // (reserved , 0x00ff) // 0xffe2 @@ -532,8 +526,7 @@ MACHINE_CONFIG_END v53_base_device::v53_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t prefetch_size, uint8_t prefetch_cycles, uint32_t chip_type) : - nec_common_device(mconfig, type, tag, owner, clock, true, prefetch_size, prefetch_cycles, chip_type), - m_io_space_config( "io", ENDIANNESS_LITTLE, 16, 16, 0, address_map_constructor(FUNC(v53_base_device::v53_internal_port_map), this) ), + nec_common_device(mconfig, type, tag, owner, clock, true, prefetch_size, prefetch_cycles, chip_type, address_map_constructor(FUNC(v53_base_device::v53_internal_port_map), this)), m_v53tcu(*this, "pit"), m_v53dmau(*this, "upd71071dma"), m_v53icu(*this, "upd71059pic"), diff --git a/src/devices/cpu/nec/v53.h b/src/devices/cpu/nec/v53.h index c5f695a5dd0..c91a264bbf6 100644 --- a/src/devices/cpu/nec/v53.h +++ b/src/devices/cpu/nec/v53.h @@ -201,10 +201,6 @@ protected: void install_peripheral_io(); - const address_space_config m_io_space_config; - - virtual space_config_vector memory_space_config() const override; - uint8_t m_SCTL; uint8_t m_OPSEL; |