rii: Many updates

- Identify CPU type used by vreadere as ePG3231
- Add preliminary port I/O handlers and callbacks
- Add stub handlers and state variables for interrupt controller, timers, synthesizer, UART and SPI
- Fix TBRD addressing of external data memory
- Fix calculation of carry flag for normal additive operations
- Implement multi-byte carry/borrow for applicable registers
- Implement signed multiplication option
- Add internal stack buffer for saving PCH during calls/interrupts
This commit is contained in:
AJR 2019-09-25 11:48:22 -04:00
parent a73d55f52e
commit a24caaede8
6 changed files with 1043 additions and 77 deletions

View File

@ -16,8 +16,8 @@ using osd::u32;
using util::BIT; using util::BIT;
using offs_t = u32; using offs_t = u32;
// FIXME: this set is an amalgam of ePG3231-EM202, EPD3332 and EPD3338 // TODO: add register sets for other models
const char *const riscii_disassembler::s_regs[0x60] = const char *const epg3231_disassembler::s_regs[0x60] =
{ {
"INDF0", "FSR0", "PCL", "PCM", "PCH", "BSR", "STKPTR", "BSR1", "INDF0", "FSR0", "PCL", "PCM", "PCH", "BSR", "STKPTR", "BSR1",
"INDF1", "FSR1", "ACC", "TABPTRL", "TABPTRM", "TABPTRH", "CPUCON", "STATUS", "INDF1", "FSR1", "ACC", "TABPTRL", "TABPTRM", "TABPTRH", "CPUCON", "STATUS",
@ -27,8 +27,8 @@ const char *const riscii_disassembler::s_regs[0x60] =
"TR2CON", "TRLIR", nullptr, "POST_ID", "ADCON", "PAINTEN", "PAINTSTA", "PAWAKE", "TR2CON", "TRLIR", nullptr, "POST_ID", "ADCON", "PAINTEN", "PAINTSTA", "PAWAKE",
"UARTCON", "UARTSTA", "PORTJ", "PORTK", "DCRB", "DCRC", "DCRDE", "DCRFG", "UARTCON", "UARTSTA", "PORTJ", "PORTK", "DCRB", "DCRC", "DCRDE", "DCRFG",
"DCRHI", "DCRJK", "PBCON", "PCCON", "PLLF", "T0CL", "T0CH", "SPICON", "DCRHI", "DCRJK", "PBCON", "PCCON", "PLLF", "T0CL", "T0CH", "SPICON",
"SPISTA", "SPRL", "SPRM", "SPRH", "SFCR", "ADDL1~ADDL4", "ADDM1~ADDM4", "ADDH1~ADDH4", "SPISTA", "SPRL", "SPRM", "SPRH", "SFCR", "ADDL", "ADDM", "ADDH",
"ENV1~4/SPHDR", "MTCON1~4/SPHTCON", "MTRL1~4/SPHTRL", "VOCON", "TR1C", "TR2C", "ADCF", nullptr, "ENV/SPHDR", "MTCON/SPHTCON", "MTRL/SPHTRL", "VOCON", "TR1C", "TR2C", "ADCF", nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
}; };

View File

@ -8,9 +8,6 @@
class riscii_disassembler : public util::disasm_interface class riscii_disassembler : public util::disasm_interface
{ {
public:
riscii_disassembler() : riscii_disassembler(s_regs) { }
protected: protected:
// construction/destruction // construction/destruction
riscii_disassembler(const char *const regs[]); riscii_disassembler(const char *const regs[]);
@ -31,4 +28,13 @@ private:
const char *const *m_regs; const char *const *m_regs;
}; };
class epg3231_disassembler : public riscii_disassembler
{
public:
epg3231_disassembler() : riscii_disassembler(s_regs) { }
private:
static const char *const s_regs[0x60];
};
#endif // MAME_CPU_RII_RIIDASM_H #endif // MAME_CPU_RII_RIIDASM_H

File diff suppressed because it is too large Load Diff

View File

@ -30,16 +30,60 @@ public:
RII_CPUCON, RII_CPUCON,
RII_STATUS, RII_STATUS,
RII_PROD, RII_PROD,
RII_POST_ID RII_PFS,
RII_INTCON,
RII_INTSTA,
RII_POST_ID,
RII_PORTB, RII_PORTC, RII_PORTD, RII_PORTE, RII_PORTF, RII_PORTG, RII_PORTH, RII_PORTI, RII_PORTJ, RII_PORTK,
RII_STBCON,
RII_PAINTEN, RII_PAINTSTA, RII_PAWAKE,
RII_DCRB, RII_DCRC, RII_DCRDE, RII_DCRFG, RII_DCRHI, RII_DCRJK,
RII_PBCON, RII_PCCON,
RII_UARTCON, RII_UARTSTA,
RII_SPICON, RII_SPISTA,
RII_TRL0, RII_TRL1, RII_TRL2,
RII_TR01CON,
RII_TR2CON,
RII_TRLIR,
RII_SFCR,
RII_ADD1, RII_ADD2, RII_ADD3, RII_ADD4,
RII_ENV1, RII_ENV2, RII_ENV3, RII_ENV4,
RII_MTCON1, RII_MTCON2, RII_MTCON3, RII_MTCON4,
RII_MTRL1, RII_MTRL2, RII_MTRL3, RII_MTRL4,
RII_SPHDR,
RII_SPHTCON,
RII_SPHTRL,
RII_VOCON
}; };
// construction/destruction // callback configuration
riscii_series_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); auto in_porta_cb() { return m_porta_in_cb.bind(); }
auto in_portb_cb() { return m_port_in_cb[0].bind(); }
auto out_portb_cb() { return m_port_out_cb[0].bind(); }
auto in_portc_cb() { return m_port_in_cb[1].bind(); }
auto out_portc_cb() { return m_port_out_cb[1].bind(); }
auto in_portd_cb() { return m_port_in_cb[2].bind(); }
auto out_portd_cb() { return m_port_out_cb[2].bind(); }
auto in_porte_cb() { return m_port_in_cb[3].bind(); }
auto out_porte_cb() { return m_port_out_cb[3].bind(); }
auto in_portf_cb() { return m_port_in_cb[4].bind(); }
auto out_portf_cb() { return m_port_out_cb[4].bind(); }
auto in_portg_cb() { return m_port_in_cb[5].bind(); }
auto out_portg_cb() { return m_port_out_cb[5].bind(); }
auto in_porth_cb() { return m_port_in_cb[6].bind(); }
auto out_porth_cb() { return m_port_out_cb[6].bind(); }
auto in_porti_cb() { return m_port_in_cb[7].bind(); }
auto out_porti_cb() { return m_port_out_cb[7].bind(); }
auto in_portj_cb() { return m_port_in_cb[8].bind(); }
auto out_portj_cb() { return m_port_out_cb[8].bind(); }
auto in_portk_cb() { return m_port_in_cb[9].bind(); }
auto out_portk_cb() { return m_port_out_cb[9].bind(); }
protected: protected:
riscii_series_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, unsigned prgbits, unsigned bankbits, uint8_t maxbank); riscii_series_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, unsigned addrbits, unsigned pcbits, u32 datastart, unsigned bankbits, u8 maxbank, u8 post_id_mask, address_map_constructor regs);
// device-level overrides // device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override; virtual void device_start() override;
virtual void device_reset() override; virtual void device_reset() override;
@ -47,16 +91,14 @@ protected:
virtual void execute_run() override; virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override; virtual void execute_set_input(int inputnum, int state) override;
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
// device_memory_interface overrides // device_memory_interface overrides
virtual space_config_vector memory_space_config() const override; virtual space_config_vector memory_space_config() const override;
// device_state_interface overrides // device_state_interface overrides
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
private: void core_regs_map(address_map &map);
// register handlers // register handlers
u8 fsr0_r(); u8 fsr0_r();
void fsr0_w(u8 data); void fsr0_w(u8 data);
@ -90,12 +132,92 @@ private:
void prodl_w(u8 data); void prodl_w(u8 data);
u8 prodh_r(); u8 prodh_r();
void prodh_w(u8 data); void prodh_w(u8 data);
u8 pfs_r();
void pfs_w(u8 data);
u8 intcon_r();
void intcon_w(u8 data);
u8 intsta_r();
void intsta_w(u8 data);
u8 post_id_r(); u8 post_id_r();
void post_id_w(u8 data); void post_id_w(u8 data);
u8 porta_r();
u8 port_r(offs_t offset);
void port_w(offs_t offset, u8 data);
u8 stbcon_r();
void stbcon_w(u8 data);
u8 painten_r();
void painten_w(u8 data);
u8 paintsta_r();
void paintsta_w(u8 data);
u8 pawake_r();
void pawake_w(u8 data);
u8 portjk_r(offs_t offset);
void portjk_w(offs_t offset, u8 data);
u8 dcr_r(offs_t offset);
void dcr_w(offs_t offset, u8 data);
u8 pcon_r(offs_t offset);
void pcon_w(offs_t offset, u8 data);
void uarttx_w(u8 data);
u8 uartrx_r();
u8 uartcon_r();
void uartcon_w(u8 data);
u8 uartsta_r();
void uartsta_w(u8 data);
u8 spicon_r();
void spicon_w(u8 data);
u8 spista_r();
void spista_w(u8 data);
u8 sprl_r();
void sprl_w(u8 data);
u8 sprm_r();
void sprm_w(u8 data);
u8 sprh_r();
void sprh_w(u8 data);
u8 trl0l_r();
void trl0l_w(u8 data);
u8 trl0h_r();
void trl0h_w(u8 data);
u8 trl1_r();
void trl1_w(u8 data);
u8 trl2_r();
void trl2_w(u8 data);
u8 tr01con_r();
void tr01con_w(u8 data);
u8 tr2con_r();
void tr2con_w(u8 data);
u8 trlir_r();
void trlir_w(u8 data);
u8 t0cl_r();
u8 t0ch_r();
u8 tr1c_r();
u8 tr2c_r();
u8 sfcr_r();
void sfcr_w(u8 data);
u8 addl_r();
void addl_w(u8 data);
u8 addm_r();
void addm_w(u8 data);
u8 addh_r();
void addh_w(u8 data);
u8 env_sphdr_r();
void env_sphdr_w(u8 data);
u8 mtcon_sphtcon_r();
void mtcon_sphtcon_w(u8 data);
u8 mtrl_sphtrl_r();
void mtrl_sphtrl_w(u8 data);
u8 vocon_r();
void vocon_w(u8 data);
private:
// debugging helpers
void debug_set_pc(u32 pc);
// memory helpers // memory helpers
u16 fetch_program_word();
u16 get_banked_address(u8 reg); u16 get_banked_address(u8 reg);
u32 tabptr_offset(int offset) const; u32 tabptr_offset(int offset) const;
void multi_byte_carry(u16 addr, bool cy);
void multi_byte_borrow(u16 addr, bool cy);
// execution // execution
void execute_move(u8 dstreg, u8 srcreg); void execute_move(u8 dstreg, u8 srcreg);
@ -143,6 +265,7 @@ private:
enum exec_state : u8 { enum exec_state : u8 {
EXEC_CYCLE1, EXEC_CYCLE1,
EXEC_ADCPCM, EXEC_SBCPCM,
EXEC_TBRD0, EXEC_TBRD1, EXEC_TBRD2, EXEC_TBRDA, EXEC_TBRD0, EXEC_TBRD1, EXEC_TBRD2, EXEC_TBRDA,
EXEC_NOJMP, EXEC_NOJMP,
EXEC_L0JMP, EXEC_L1JMP, EXEC_L2JMP, EXEC_L3JMP, EXEC_L0JMP, EXEC_L1JMP, EXEC_L2JMP, EXEC_L3JMP,
@ -155,8 +278,6 @@ private:
EXEC_LCCALL, EXEC_LDCALL, EXEC_LECALL, EXEC_LFCALL EXEC_LCCALL, EXEC_LDCALL, EXEC_LECALL, EXEC_LFCALL
}; };
void regs_map(address_map &map);
// address spaces // address spaces
address_space_config m_program_config; address_space_config m_program_config;
address_space_config m_regs_config; address_space_config m_regs_config;
@ -164,10 +285,18 @@ private:
address_space *m_regs; address_space *m_regs;
memory_access_cache<1, -1, ENDIANNESS_LITTLE> *m_cache; memory_access_cache<1, -1, ENDIANNESS_LITTLE> *m_cache;
// device callbacks
devcb_read8 m_porta_in_cb;
devcb_read8 m_port_in_cb[10];
devcb_write8 m_port_out_cb[10];
// model-specific parameters // model-specific parameters
const unsigned m_prgbits; const u32 m_pcmask;
const uint8_t m_bankmask; const u32 m_datastart;
const uint8_t m_maxbank; const u32 m_tbptmask;
const u8 m_bankmask;
const u8 m_maxbank;
const u8 m_post_id_mask;
// internal state // internal state
u32 m_pc; u32 m_pc;
@ -177,11 +306,51 @@ private:
u8 m_bsr[2]; u8 m_bsr[2];
u32 m_tabptr; u32 m_tabptr;
u8 m_stkptr; u8 m_stkptr;
std::unique_ptr<u8[]> m_pchstack;
u8 m_cpucon; u8 m_cpucon;
u8 m_status; u8 m_status;
u16 m_prod; u16 m_prod;
u8 m_pfs;
u8 m_intcon;
u8 m_intsta;
u8 m_post_id; u8 m_post_id;
// port state
u8 m_port_data[10];
u8 m_port_dcr[6];
u8 m_port_control[2];
u8 m_stbcon;
u8 m_painten;
u8 m_paintsta;
u8 m_pawake;
// UART state
u8 m_uartcon;
u8 m_uartsta;
// SPI state
u8 m_spicon;
u8 m_spista;
// timer state
u16 m_trl0;
u8 m_trl1;
u8 m_trl2;
u8 m_tr01con;
u8 m_tr2con;
u8 m_trlir;
u8 m_sfcr;
// synthesizer state
u32 m_add[4];
u8 m_env[4];
u8 m_mtcon[4];
u8 m_mtrl[4];
u8 m_sphdr;
u8 m_sphtcon;
u8 m_sphtrl;
u8 m_vocon;
// execution sequencing // execution sequencing
s32 m_icount; s32 m_icount;
exec_state m_exec_state; exec_state m_exec_state;
@ -189,6 +358,20 @@ private:
u8 m_curreg; u8 m_curreg;
}; };
DECLARE_DEVICE_TYPE(RISCII, riscii_series_device) class epg3231_device : public riscii_series_device
{
public:
// construction/destruction
epg3231_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
private:
void regs_map(address_map &map);
};
DECLARE_DEVICE_TYPE(EPG3231, epg3231_device)
#endif // MAME_CPU_RII_RISCII_H #endif // MAME_CPU_RII_RISCII_H

View File

@ -1,7 +1,7 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:Sandro Ronco // copyright-holders:Sandro Ronco
// CPU die is an Elan EU3A12 (Elan "RISC II Series" quasi-PIC with 16-bit opcodes) // CPU die (epoxy blob) is an Elan EU3A12 (Elan "RISC II Series" quasi-PIC with 16-bit opcodes)
#include "emu.h" #include "emu.h"
#include "cpu/rii/riscii.h" #include "cpu/rii/riscii.h"
@ -22,7 +22,7 @@ private:
void prog_map(address_map &map); void prog_map(address_map &map);
required_device<cpu_device> m_maincpu; required_device<riscii_series_device> m_maincpu;
}; };
uint32_t vreadere_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) uint32_t vreadere_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -32,7 +32,7 @@ uint32_t vreadere_state::screen_update(screen_device &screen, bitmap_rgb32 &bitm
void vreadere_state::prog_map(address_map &map) void vreadere_state::prog_map(address_map &map)
{ {
map(0x00000, 0x3ffff).rom().region("maincpu", 0); map(0x000000, 0x1fffff).rom().region("maincpu", 0);
} }
static INPUT_PORTS_START( vreadere ) static INPUT_PORTS_START( vreadere )
@ -40,7 +40,7 @@ INPUT_PORTS_END
void vreadere_state::vreadere(machine_config &config) void vreadere_state::vreadere(machine_config &config)
{ {
RISCII(config, m_maincpu, 10'000'000); // CPU type is unknown, epoxy blob EPG3231(config, m_maincpu, 10'000'000);
m_maincpu->set_addrmap(AS_PROGRAM, &vreadere_state::prog_map); m_maincpu->set_addrmap(AS_PROGRAM, &vreadere_state::prog_map);
/* video hardware */ /* video hardware */

View File

@ -354,6 +354,7 @@ static const dasm_table_entry dasm_table[] =
{ "dsp32c", le, 0, []() -> util::disasm_interface * { return new dsp32c_disassembler; } }, { "dsp32c", le, 0, []() -> util::disasm_interface * { return new dsp32c_disassembler; } },
{ "dsp56156", le, -1, []() -> util::disasm_interface * { return new dsp56156_disassembler; } }, { "dsp56156", le, -1, []() -> util::disasm_interface * { return new dsp56156_disassembler; } },
{ "e0c6200", be, -1, []() -> util::disasm_interface * { return new e0c6200_disassembler; } }, { "e0c6200", be, -1, []() -> util::disasm_interface * { return new e0c6200_disassembler; } },
{ "epg3231", le, -1, []() -> util::disasm_interface * { return new epg3231_disassembler; } },
// { "es5510", be, 0, []() -> util::disasm_interface * { return new es5510_disassembler; } }, // Currently does nothing // { "es5510", be, 0, []() -> util::disasm_interface * { return new es5510_disassembler; } }, // Currently does nothing
{ "esrip", be, 0, []() -> util::disasm_interface * { return new esrip_disassembler; } }, { "esrip", be, 0, []() -> util::disasm_interface * { return new esrip_disassembler; } },
{ "f2mc16", le, 0, []() -> util::disasm_interface * { return new f2mc16_disassembler; } }, { "f2mc16", le, 0, []() -> util::disasm_interface * { return new f2mc16_disassembler; } },
@ -448,7 +449,6 @@ static const dasm_table_entry dasm_table[] =
{ "pps4", le, 0, []() -> util::disasm_interface * { return new pps4_disassembler; } }, { "pps4", le, 0, []() -> util::disasm_interface * { return new pps4_disassembler; } },
{ "psxcpu", le, 0, []() -> util::disasm_interface * { return new psxcpu_disassembler; } }, { "psxcpu", le, 0, []() -> util::disasm_interface * { return new psxcpu_disassembler; } },
{ "r65c02", le, 0, []() -> util::disasm_interface * { return new r65c02_disassembler; } }, { "r65c02", le, 0, []() -> util::disasm_interface * { return new r65c02_disassembler; } },
{ "rii", le, -1, []() -> util::disasm_interface * { return new riscii_disassembler; } },
{ "rsp", le, 0, []() -> util::disasm_interface * { return new rsp_disassembler; } }, { "rsp", le, 0, []() -> util::disasm_interface * { return new rsp_disassembler; } },
{ "s2650", le, 0, []() -> util::disasm_interface * { return new s2650_disassembler(&s2650_unidasm); } }, { "s2650", le, 0, []() -> util::disasm_interface * { return new s2650_disassembler(&s2650_unidasm); } },
{ "saturn", le, 0, []() -> util::disasm_interface * { return new saturn_disassembler(&saturn_unidasm); } }, { "saturn", le, 0, []() -> util::disasm_interface * { return new saturn_disassembler(&saturn_unidasm); } },