diff options
Diffstat (limited to 'src/devices/cpu')
-rw-r--r-- | src/devices/cpu/mb86233/mb86233.cpp | 2356 | ||||
-rw-r--r-- | src/devices/cpu/mb86233/mb86233.h | 206 | ||||
-rw-r--r-- | src/devices/cpu/mb86233/mb86233d.cpp | 168 | ||||
-rw-r--r-- | src/devices/cpu/mb86233/mb86233d.h | 2 | ||||
-rw-r--r-- | src/devices/cpu/mb86235/mb86235.cpp | 55 | ||||
-rw-r--r-- | src/devices/cpu/mb86235/mb86235.h | 61 | ||||
-rw-r--r-- | src/devices/cpu/mb86235/mb86235drc.cpp | 192 | ||||
-rw-r--r-- | src/devices/cpu/mb86235/mb86235ops.cpp | 58 |
8 files changed, 1297 insertions, 1801 deletions
diff --git a/src/devices/cpu/mb86233/mb86233.cpp b/src/devices/cpu/mb86233/mb86233.cpp index 68cf6a8fe6f..7244e0d5d04 100644 --- a/src/devices/cpu/mb86233/mb86233.cpp +++ b/src/devices/cpu/mb86233/mb86233.cpp @@ -1,1666 +1,1200 @@ // license:BSD-3-Clause -// copyright-holders:Ernesto Corvi -/*************************************************************************** - - mb86233.c - Core implementation for the portable Fujitsu MB86233 series DSP emulator. - - Written by ElSemi - MAME version by Ernesto Corvi - - TODO: - - Properly emulate the TGP Tables from the ROM (See GETEXTERNAL) - - Many unknown opcodes and addressing modes - - Interrupts? - -***************************************************************************/ +// copyright-holders:Olivier Galibert #include "emu.h" #include "debugger.h" #include "mb86233.h" #include "mb86233d.h" +/* + Driver based on the initial reverse-engineering of Elsemi, extended, + generalized and made to look more like a cpu since then thanks in + part to a "manual" that barely deserves the name. + + The 86232 has 512 32-bits dwords of triple-port memory (1 write, 2 + read). The 86233/86234 have instead two normal (1 read, 1 write, + non-simultaneous) independant ram banks, one of 256 dwords and one + of 512. + + The ram banks are mapped at 0x000-0x0ff and 0x200-0x3ff (proven by + geometrizer code that clears the ram at startup). Move and load + instructions kind of target a specific ram, but do it by adding + 0x200 to the address on one side of the other, which can then end up + anywhere. In particular model1 coprocessor has the output fifo at + 0x400, which is sometimes hit by having x1 at 0x200 and using the + automatic 0x200 adder. Theorically external accesses to 100-1ff and + 400+ seem to be routed externally, since they're used for the fifo + in model 1. + + The cpu can theorically work in either floating point (32-bits ieee + flots) or fixed point (32/36/48 bits registers) modes. All sega + programs start by activating floating point and staying there, so + fixed point is not implemented. + + An interrupt is used to update the rf0 (status? leds?) registers in + the coprocessor programs. It's on bit 1 of the mask (irq3?) and + vector 0x004. It's probably periodic, maybe on vblank. Note that + the copro programs never initialize the stack pointer. Interrupts + are not implemented at this point. + + The 86233 and 86234 dies are slightly different in the die shots, + but there's no known programming-level difference at this point. + It's unclear whether some register-file linked functionality is + internal or external though (fifos, banking in model2/86234), so + there may lie the actual differences. +*/ + + +DEFINE_DEVICE_TYPE(MB86233, mb86233_device, "mb86233", "Fujitsu MB86233 (TGP)") +DEFINE_DEVICE_TYPE(MB86234, mb86234_device, "mb86234", "Fujitsu MB86234 (TGP)") + + +mb86233_device::mb86233_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : cpu_device(mconfig, type, tag, owner, clock) + , m_program_config("program", ENDIANNESS_LITTLE, 32, 16, -2) + , m_data_config("data", ENDIANNESS_LITTLE, 32, 16, -2) + , m_io_config("io", ENDIANNESS_LITTLE, 32, 16, -2) + , m_rf_config("rf", ENDIANNESS_LITTLE, 32, 4, -2) +{ +} -DEFINE_DEVICE_TYPE(MB86233, mb86233_cpu_device, "mb86233", "Fujitsu MB86233 \"TGP\"") - +mb86233_device::mb86233_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mb86233_device(mconfig, MB86233, tag, owner, clock) +{ +} -mb86233_cpu_device::mb86233_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : cpu_device(mconfig, MB86233, tag, owner, clock) - , m_program_config("program", ENDIANNESS_LITTLE, 32, 32, -2) - , m_data_config("data", ENDIANNESS_LITTLE, 32, 32, 0) - , m_pc(0), m_reps(0), m_pcsp(0), m_eb(0), m_shift(0), m_repcnt(0), m_sr(0) - , m_fpucontrol(0), m_program(nullptr), m_direct(nullptr), m_icount(0), m_fifo_wait(0) - , m_fifo_read_cb(*this) - , m_fifo_read_ok_cb(*this) - , m_fifo_write_cb(*this) - , m_tablergn(nullptr), m_ARAM(nullptr), m_BRAM(nullptr) - , m_Tables(nullptr) +mb86234_device::mb86234_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : mb86233_device(mconfig, MB86234, tag, owner, clock) { } -device_memory_interface::space_config_vector mb86233_cpu_device::memory_space_config() const +device_memory_interface::space_config_vector mb86233_device::memory_space_config() const { return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_config), - std::make_pair(AS_DATA, &m_data_config) + std::make_pair(AS_PROGRAM, &m_program_config), + std::make_pair(AS_DATA, &m_data_config), + std::make_pair(AS_IO, &m_io_config), + std::make_pair(AS_RF, &m_rf_config) }; } -std::unique_ptr<util::disasm_interface> mb86233_cpu_device::create_disassembler() +std::unique_ptr<util::disasm_interface> mb86233_device::create_disassembler() { return std::make_unique<mb86233_disassembler>(); } -/*************************************************************************** - MACROS -***************************************************************************/ - -#define ZERO_FLAG (1 << 0) -#define SIGN_FLAG (1 << 1) -#define EXTERNAL_FLAG (1 << 2) //This seems to be a flag coming from some external circuit?? - -#define GETPC() m_pc -#define GETA() m_a -#define GETB() m_b -#define GETD() m_d -#define GETP() m_p -#define GETSR() m_sr -#define GETGPR(a) m_gpr[a] -#define GETSHIFT() m_shift -#define GETPCS() m_pcs -#define GETPCSP() m_pcsp -#define GETEB() m_eb -#define GETREPS() m_reps -#define GETEXTPORT() m_extport -#define GETFIFOWAIT() m_fifo_wait -#define GETARAM() m_ARAM -#define GETBRAM() m_BRAM -#define GETREPCNT() m_repcnt - -#define ROPCODE(a) m_direct->read_dword(a) -#define RDMEM(a) m_program->read_dword(a) -#define WRMEM(a,v) m_program->write_dword((a), v) - -/*************************************************************************** - Initialization and Shutdown -***************************************************************************/ - -void mb86233_cpu_device::device_start() -{ - m_pc = 0; - m_a.u = 0; - m_b.u = 0; - m_d.u = 0; - m_p.u = 0; - m_reps = 0; - m_pcs[0] = m_pcs[1] = m_pcs[2] = m_pcs[3] = 0; - m_pcsp = 0; - m_eb = 0; - m_shift = 0; - m_repcnt = 0; - m_sr = 0; - memset(m_gpr, 0, sizeof(m_gpr)); - memset(m_extport, 0, sizeof(m_extport)); - m_fifo_wait = 0; - - m_fifo_read_cb.resolve_safe(0); - m_fifo_read_ok_cb.resolve_safe(0); - m_fifo_write_cb.resolve_safe(); +void mb86233_device::device_start() +{ m_program = &space(AS_PROGRAM); - m_direct = m_program->direct<-2>(); - - if ( m_tablergn ) - { - m_Tables = (uint32_t*) machine().root_device().memregion(m_tablergn)->base(); - } - - memset( m_RAM, 0, 2 * 0x200 * sizeof(uint32_t) ); - m_ARAM = &m_RAM[0]; - m_BRAM = &m_RAM[0x200]; - + m_direct = m_program->direct<-2>(); + + m_data = &space(AS_DATA); + m_io = &space(AS_IO); + m_rf = &space(AS_RF); + + state_add(STATE_GENPC, "GENPC", m_pc); + state_add(STATE_GENPCBASE, "PC", m_ppc).noshow(); + state_add(STATE_GENSP, "SP", m_sp); + state_add(STATE_GENFLAGS, "ST", m_st); + + state_add(REG_A, "A", m_a); + state_add(REG_B, "B", m_b); + state_add(REG_D, "D", m_d); + state_add(REG_P, "P", m_p); + state_add(REG_R, "R", m_r); + state_add(REG_R, "RPC", m_rpc); + state_add(REG_C0, "C0", m_c0); + state_add(REG_C1, "C1", m_c1); + state_add(REG_B0, "B0", m_b0); + state_add(REG_B1, "B1", m_b1); + state_add(REG_X0, "X0", m_x0); + state_add(REG_X1, "X1", m_x1); + state_add(REG_I0, "I0", m_i0); + state_add(REG_I1, "I1", m_i1); + state_add(REG_SFT, "SFT", m_sft); + state_add(REG_VSM, "VSM", m_vsm); + state_add(REG_PCS0, "PCS0", m_pcs[0]); + state_add(REG_PCS1, "PCS1", m_pcs[1]); + state_add(REG_PCS2, "PCS2", m_pcs[2]); + state_add(REG_PCS3, "PCS3", m_pcs[3]); + state_add(REG_MASK, "MASK", m_mask); + state_add(REG_M, "M", m_m); + + save_item(NAME(m_ppc)); save_item(NAME(m_pc)); - save_item(NAME(m_a.u)); - save_item(NAME(m_b.u)); - save_item(NAME(m_d.u)); - save_item(NAME(m_p.u)); - save_item(NAME(m_reps)); + save_item(NAME(m_st)); + save_item(NAME(m_sp)); + save_item(NAME(m_a)); + save_item(NAME(m_b)); + save_item(NAME(m_d)); + save_item(NAME(m_p)); + save_item(NAME(m_r)); + save_item(NAME(m_rpc)); + save_item(NAME(m_c0)); + save_item(NAME(m_c1)); + save_item(NAME(m_b0)); + save_item(NAME(m_b1)); + save_item(NAME(m_x0)); + save_item(NAME(m_x1)); + save_item(NAME(m_i0)); + save_item(NAME(m_i1)); + save_item(NAME(m_sft)); + save_item(NAME(m_vsm)); + save_item(NAME(m_vsmr)); save_item(NAME(m_pcs)); - save_item(NAME(m_pcsp)); - save_item(NAME(m_eb)); - save_item(NAME(m_shift)); - save_item(NAME(m_repcnt)); - save_item(NAME(m_sr)); - save_item(NAME(m_gpr)); - save_item(NAME(m_extport)); - save_item(NAME(m_RAM)); - - state_add( MB86233_PC, "PC", m_pc).formatstr("%04X"); - state_add( MB86233_A, "PA", m_a.u).formatstr("%08X"); - state_add( MB86233_B, "PB", m_b.u).formatstr("%08X"); - state_add( MB86233_P, "PP", m_p.u).formatstr("%08X"); - state_add( MB86233_D, "PD", m_d.u).formatstr("%08X"); - state_add( MB86233_REP, "REPS", m_reps).formatstr("%08X"); - state_add( MB86233_SP, "PCSP", m_pcsp).mask(0xf).formatstr("%01X"); - state_add( MB86233_EB, "EB", m_eb).formatstr("%08X"); - state_add( MB86233_SHIFT, "SHIFT", m_shift).formatstr("%08X"); - state_add( MB86233_R0, "R0", m_gpr[0]).formatstr("%08X"); - state_add( MB86233_R1, "R1", m_gpr[1]).formatstr("%08X"); - state_add( MB86233_R2, "R2", m_gpr[2]).formatstr("%08X"); - state_add( MB86233_R3, "R3", m_gpr[3]).formatstr("%08X"); - state_add( MB86233_R4, "R4", m_gpr[4]).formatstr("%08X"); - state_add( MB86233_R5, "R5", m_gpr[5]).formatstr("%08X"); - state_add( MB86233_R6, "R6", m_gpr[6]).formatstr("%08X"); - state_add( MB86233_R7, "R7", m_gpr[7]).formatstr("%08X"); - state_add( MB86233_R8, "R8", m_gpr[8]).formatstr("%08X"); - state_add( MB86233_R9, "R9", m_gpr[9]).formatstr("%08X"); - state_add( MB86233_R10, "R10", m_gpr[10]).formatstr("%08X"); - state_add( MB86233_R11, "R11", m_gpr[11]).formatstr("%08X"); - state_add( MB86233_R12, "R12", m_gpr[12]).formatstr("%08X"); - state_add( MB86233_R13, "R13", m_gpr[13]).formatstr("%08X"); - state_add( MB86233_R14, "R14", m_gpr[14]).formatstr("%08X"); - state_add( MB86233_R15, "R15", m_gpr[15]).formatstr("%08X"); - - state_add( STATE_GENPC, "GENPC", m_pc).noshow(); - state_add( STATE_GENPCBASE, "CURPC", m_pc).noshow(); - state_add( STATE_GENFLAGS, "GENFLAGS", m_sr).formatstr("%2s").noshow(); + save_item(NAME(m_mask)); + save_item(NAME(m_m)); + save_item(NAME(m_gpio0)); + save_item(NAME(m_gpio1)); + save_item(NAME(m_gpio2)); + save_item(NAME(m_gpio3)); + + save_item(NAME(m_alu_stmask)); + save_item(NAME(m_alu_stset)); + save_item(NAME(m_alu_r1)); + save_item(NAME(m_alu_r2)); + + m_gpio0 = m_gpio1 = m_gpio2 = m_gpio3 = false; set_icountptr(m_icount); } -void mb86233_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const +void mb86233_device::state_string_export(const device_state_entry &entry, std::string &str) const { - switch (entry.index()) - { - case STATE_GENFLAGS: - str = string_format("%c%c", (m_sr & SIGN_FLAG) ? 'N' : 'n', (m_sr & ZERO_FLAG) ? 'Z' : 'z'); - break; - } } - -void mb86233_cpu_device::device_reset() +WRITE_LINE_MEMBER(mb86233_device::gpio0_w) { - /* zero registers and flags */ - m_pc = 0; - m_sr = 0; - m_pcsp = 0; - m_eb = 0; - m_shift = 0; - m_fifo_wait = 0; + m_gpio0 = state; } +WRITE_LINE_MEMBER(mb86233_device::gpio1_w) +{ + m_gpio1 = state; +} +WRITE_LINE_MEMBER(mb86233_device::gpio2_w) +{ + m_gpio2 = state; +} -/*************************************************************************** - Status Register -***************************************************************************/ - -#define ZERO_FLAG (1 << 0) -#define SIGN_FLAG (1 << 1) -#define EXTERNAL_FLAG (1 << 2) //This seems to be a flag coming from some external circuit?? - -void mb86233_cpu_device::FLAGSF( float v ) +WRITE_LINE_MEMBER(mb86233_device::gpio3_w) { - GETSR() &= ~(ZERO_FLAG|SIGN_FLAG); + m_gpio3 = state; +} - if ( v == 0 ) - GETSR() |= ZERO_FLAG; +void mb86233_device::device_reset() +{ + m_pc = 0; + m_ppc = 0; + m_st = F_ZRC|F_ZRD|F_ZX0|F_ZX1|F_ZX2|F_ZC0|F_ZC1; + m_sp = 0; + + m_a = 0; + m_b = 0; + m_d = 0; + m_p = 0; + m_r = 1; + m_rpc = 1; + m_c0 = 1; + m_c1 = 1; + m_b0 = 0; + m_b1 = 0; + m_x0 = 0; + m_x1 = 0; + m_i0 = 0; + m_i1 = 0; + m_sft = 0; + m_vsm = 0; + m_vsmr = 7; + m_mask = 0; + m_m = 1; + + m_alu_stmask = 0; + m_alu_stset = 0; + m_alu_r1 = 0; + m_alu_r2 = 0; + + std::fill(std::begin(m_pcs), std::end(m_pcs), 0); + + m_stall = false; +} - if ( v < 0 ) - GETSR() |= SIGN_FLAG; +s32 mb86233_device::s24_32(u32 val) +{ + if(val & 0x00800000) + return val | 0xff000000; + else + return val & 0x00ffffff; } -void mb86233_cpu_device::FLAGSI( uint32_t v ) +u32 mb86233_device::set_exp(u32 val, u32 exp) { - GETSR() &= ~(ZERO_FLAG|SIGN_FLAG); + return (val & 0x807fffff) | ((exp & 0xff) << 23); +} - if ( v == 0 ) - GETSR() |= ZERO_FLAG; +u32 mb86233_device::set_mant(u32 val, u32 mant) +{ + return (val & 0x07f800000) | ((mant & 0x00800000) << 8) | (mant & 0x007fffff); +} - if ( v & 0x80000000 ) - GETSR() |= SIGN_FLAG; +u32 mb86233_device::get_exp(u32 val) +{ + return (val >> 23) & 0xff; } +u32 mb86233_device::get_mant(u32 val) +{ + return val & 0x80000000 ? val | 0x7f800000 : val & 0x807fffff; +} +void mb86233_device::pcs_push() +{ + for(unsigned int i=3; i; i--) + m_pcs[i] = m_pcs[i-1]; + m_pcs[0] = m_pc; +} -/*************************************************************************** - Condition Codes -***************************************************************************/ +void mb86233_device::pcs_pop() +{ + m_pc = m_pcs[0]; + for(unsigned int i=0; i != 3; i++) + m_pcs[i] = m_pcs[i+1]; +} -int mb86233_cpu_device::COND( uint32_t cond ) +void mb86233_device::testdz() { - switch( cond ) - { - case 0x00: /* eq */ - if ( (GETSR() & ZERO_FLAG) ) return 1; - break; + if(m_d) + m_st &= ~F_ZRD; + else + m_st |= F_ZRD; + if(m_d & 0x80000000) + m_st |= F_SGD; + else + m_st &= ~F_SGD; +} - case 0x01: /* ge */ - if ( (GETSR() & ZERO_FLAG) || ((GETSR() & SIGN_FLAG)==0) ) return 1; +void mb86233_device::alu_pre(u32 alu) +{ + switch(alu) { + case 0x00: break; // no alu + + case 0x01: { + // andd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_d & m_a; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x02: /* le */ - if ( (GETSR() & ZERO_FLAG) || (GETSR() & SIGN_FLAG) ) return 1; + case 0x02: { + // orad + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_d | m_a; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x06: /* never */ + case 0x03: { + // eord + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_d ^ m_a; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x0a: - if(GETSR() & EXTERNAL_FLAG) return 1; + case 0x05: { + // fcpd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + u32 r = f2u(u2f(m_d) - u2f(m_a)); + m_alu_stset = r ? r & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x10: /* --r12 != 0 */ - GETGPR(12)--; - if ( GETGPR(12) != 0 ) return 1; + case 0x06: { + // fmad + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = f2u(u2f(m_d) + u2f(m_a)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x11: /* --r13 != 0 */ - GETGPR(13)--; - if ( GETGPR(13) != 0 ) return 1; + case 0x07: { + // fsbd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = f2u(u2f(m_d) - u2f(m_a)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x16: /* always */ - return 1; - - default: - logerror( "TGP: Unknown condition code (cc=%d) at PC:%x\n", cond, GETPC()); + case 0x08: { + // fml + m_alu_stmask = 0; + m_alu_r1 = f2u(u2f(m_a) * u2f(m_b)); + m_alu_stset = 0; break; } - return 0; -} - - - -/*************************************************************************** - ALU -***************************************************************************/ - -void mb86233_cpu_device::ALU( uint32_t alu) -{ - float ftmp; - - switch(alu) - { - case 0x00: /* NOP */ + case 0x09: { + // fmsd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = f2u(u2f(m_d) + u2f(m_p)); + m_alu_r2 = f2u(u2f(m_a) * u2f(m_b)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x01: /* D = D & A */ - GETD().u &= GETA().u; - FLAGSI( GETD().u); + case 0x0a: { + // fmrd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = f2u(u2f(m_d) - u2f(m_p)); + m_alu_r2 = f2u(u2f(m_a) * u2f(m_b)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x02: /* D = D | A */ - GETD().u |= GETA().u; - FLAGSI( GETD().u); + case 0x0b: { + // fabd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_d & 0x7fffffff; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x03: /* D = D ^ A */ - GETD().u ^= GETA().u; - FLAGSI( GETD().u); + case 0x0c: { + // fsmd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = f2u(u2f(m_d) + u2f(m_p)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x04: /* D = D ~ A */ - GETD().u = ~GETA().u; - FLAGSI( GETD().u); + case 0x0d: { + // fspd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_p; + m_alu_r2 = f2u(u2f(m_a) * u2f(m_b)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x05: /* CMP D,A */ - ftmp = GETD().f - GETA().f; - FLAGSF( ftmp); - m_icount--; + case 0x0e: { + // cxfd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = f2u(s32(m_d)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x06: /* D = D + A */ - GETD().f += GETA().f; - FLAGSF( GETD().f); - m_icount--; + case 0x0f: { + // cfxd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + switch((m_m >> 1) & 3) { + case 0: m_alu_r1 = s32(roundf(u2f(m_d))); break; + case 1: m_alu_r1 = s32(ceilf(u2f(m_d))); break; + case 2: m_alu_r1 = s32(floorf(u2f(m_d))); break; + case 3: m_alu_r1 = s32(u2f(m_d)); break; + } + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x07: /* D = D - A */ - GETD().f -= GETA().f; - FLAGSF( GETD().f); - m_icount--; + case 0x10: { + // fdvd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = f2u(u2f(m_d) / u2f(m_a)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x08: /* P = A * B */ - GETP().f = GETA().f * GETB().f; - m_icount--; + case 0x11: { + // fned + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_d ? m_d ^ 0x80000000 : 0; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x09: /* D = D + P; P = A * B */ - GETD().f += GETP().f; - GETP().f = GETA().f * GETB().f; - FLAGSF( GETD().f); - m_icount--; + case 0x13: { + // d = b + a + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = f2u(u2f(m_b) + u2f(m_a)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x0A: /* D = D - P; P = A * B */ - GETD().f -= GETP().f; - GETP().f = GETA().f * GETB().f; - FLAGSF( GETD().f); - m_icount--; + case 0x14: { + // d = b - a + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = f2u(u2f(m_b) - u2f(m_a)); + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x0B: /* D = fabs(D) */ - GETD().f = fabs( GETD().f ); - FLAGSF( GETD().f); - m_icount--; + case 0x16: { + // lsrd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_d >> m_sft; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x0C: /* D = D + P */ - GETD().f += GETP().f; - FLAGSF( GETD().f); - m_icount--; + case 0x17: { + // lsld + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_d << m_sft; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x0D: /* D = P; P = A * B */ - GETD().f = GETP().f; - GETP().f = GETA().f * GETB().f; - FLAGSF( GETD().f); - m_icount--; + case 0x18: { + // asrd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = s32(m_d) >> m_sft; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x0E: /* D = float(D) */ - GETD().f = (float)GETD().i; - FLAGSF( GETD().f); - m_icount--; + case 0x19: { + // asld + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = s32(m_d) << m_sft; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x0F: /* D = int(D) */ - switch((m_fpucontrol>>1)&3) - { - //case 0: GETD().i = floorf(GETD().f+0.5f); break; - //case 1: GETD().i = ceilf(GETD().f); break; - case 2: GETD().i = floorf(GETD().f); break; // Manx TT - case 3: GETD().i = (int32_t)GETD().f; break; - default: popmessage("TGP uses D = int(D) with FPU control = %02x, contact MAMEdev",m_fpucontrol>>1); break; - } - - FLAGSI( GETD().i); + case 0x1a: { + // addd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_d + m_a; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x10: /* D = D / A */ - if ( GETA().u != 0 ) - GETD().f = GETD().f / GETA().f; - FLAGSF( GETD().f); - m_icount--; + case 0x1b: { + // subd + m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD; + m_alu_r1 = m_d - m_a; + m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD; break; + } - case 0x11: /* D = -D */ - GETD().f = -GETD().f; - FLAGSF( GETD().f); - m_icount--; + default: + logerror("unhandled alu pre %02x\n", alu); break; + } +} - case 0x13: /* D = A + B */ - GETD().f = GETA().f + GETB().f; - FLAGSF( GETD().f); - m_icount--; - break; +void mb86233_device::alu_update_st() +{ + m_st = (m_st & ~m_alu_stmask) | m_alu_stset; +} - case 0x14: /* D = B - A */ - GETD().f = GETB().f - GETA().f; - FLAGSF( GETD().f); - m_icount--; - break; +void mb86233_device::alu_post(u32 alu) +{ + switch(alu) { + case 0x00: break; // no alu - case 0x16: /* LSR D, SHIFT */ - GETD().u >>= GETSHIFT(); - FLAGSI( GETD().u); + case 0x05: + // flags only + alu_update_st(); break; - case 0x17: /* LSL D, SHIFT */ - GETD().u <<= GETSHIFT(); - FLAGSI( GETD().u); + case 0x01: case 0x02: case 0x03: case 0x06: + case 0x07: case 0x0b: case 0x0c: case 0x0e: + case 0x0f: case 0x10: case 0x11: case 0x13: + case 0x14: case 0x16: case 0x17: case 0x18: + case 0x19: case 0x1a: case 0x1b: + // d update + m_d = m_alu_r1; + alu_update_st(); break; - case 0x18: /* ASR D, SHIFT */ -// GETD().u = (GETD().u & 0x80000000) | (GETD().u >> GETSHIFT()); - GETD().i >>= GETSHIFT(); - FLAGSI( GETD().u); + case 0x08: + // p update + m_p = m_alu_r1; break; - case 0x1A: /* D = D + A */ - GETD().i += GETA().i; - FLAGSI( GETD().u); + case 0x09: case 0x0a: case 0xd: + // d, p update + m_d = m_alu_r1; + m_p = m_alu_r2; + alu_update_st(); break; - case 0x1B: /* D = D - A */ - GETD().i -= GETA().i; - FLAGSI( GETD().u); + default: + logerror("unhandled alu post %02x\n", alu); break; - - default: - fatalerror( "TGP: Unknown ALU op %x at PC:%04x\n", alu, GETPC() ); } } - - -/*************************************************************************** - Memory Access -***************************************************************************/ - -uint32_t mb86233_cpu_device::ScaleExp(unsigned int v,int scale) -{ - int exp=(v>>23)&0xff; - exp+=scale; - v&=~0x7f800000; - return v|(exp<<23); -} - - -uint32_t mb86233_cpu_device::GETEXTERNAL( uint32_t EB, uint32_t offset ) +u16 mb86233_device::ea_pre_0(u32 r) { - uint32_t addr; - - if ( EB == 0 && offset >= 0x20 && offset <= 0x2f ) /* TGP Tables in ROM - FIXME - */ - { - if(offset>=0x20 && offset<=0x23) //SIN from value at RAM(0x20) in 0x4000/PI steps - { - uint32_t r; - uint32_t value=GETEXTPORT()[0x20]; - uint32_t off; - value+=(offset-0x20)<<14; - off=value&0x3fff; - if((value&0x7fff)==0) - r=0; - else if((value&0x7fff)==0x4000) - r=0x3f800000; - else - { - if(value&0x4000) - off=0x4000-off; - r=m_Tables[off]; - } - if(value&0x8000) - r|=1<<31; - return r; + switch(r & 0x180) { + case 0x000: return r & 0x7f; + case 0x080: case 0x100: return (r & 0x7f) + m_b0 + m_x0; + case 0x180: { + switch(r & 0x60) { + case 0x00: return m_b0 + m_x0; + case 0x20: return m_x0; + case 0x40: return m_b0 + (m_x0 & m_vsmr); + case 0x60: return m_x0 & m_vsmr; } - - if(offset==0x27) - { - unsigned int value=GETEXTPORT()[0x27]; - int exp=(value>>23)&0xff; - unsigned int res; - unsigned int sign=0; - MB86233_REG a,b; - int index; - - a.u=GETEXTPORT()[0x24]; - b.u=GETEXTPORT()[0x25]; - - - if(!exp) - { - if((a.u&0x7fffffff)<=(b.u&0x7fffffff)) - { - if(b.u&0x80000000) - res=0xc000; - else - res=0x4000; - } - else - { - if(a.u&0x80000000) - res=0x8000; - else - res=0x0000; - } - return res; - } - - if((a.u^b.u)&0x80000000) - sign=16; //the negative values are in the high word - - if((exp&0x70)!=0x70) - index=0; - else if(exp<0x70 || exp>0x7e) - index=0x3fff; - else - { - int expdif=exp-0x71; - int base; - int mask; - int shift; - - - if(expdif<0) - expdif=0; - base=1<<expdif; - mask=base-1; - shift=23-expdif; - - index=base+((value>>shift)&mask); - - } - - res=(m_Tables[index+0x10000/4]>>sign)&0xffff; - - if((a.u&0x7fffffff)<=(b.u&0x7fffffff)) - res=0x4000-res; - - - if((a.u&0x80000000) && (b.u&0x80000000)) //3rd quadrant - { - res=0x8000|res; - } - else if((a.u&0x80000000) && !(b.u&0x80000000)) //2nd quadrant - { - res=res&0x7fff; - } - else if(!(a.u&0x80000000) && (b.u&0x80000000)) //2nd quadrant - { - res=0x8000|res; - } - - return res; - - } - - if(offset==0x28) - { - uint32_t offset=(GETEXTPORT()[0x28]>>10)&0x1fff; - uint32_t value=m_Tables[offset*2+0x20000/4]; - uint32_t srcexp=(GETEXTPORT()[0x28]>>23)&0xff; - - value&=0x7FFFFFFF; - - return ScaleExp(value,0x7f-srcexp); - } - if(offset==0x29) - { - uint32_t offset=(GETEXTPORT()[0x28]>>10)&0x1fff; - uint32_t value=m_Tables[offset*2+(0x20000/4)+1]; - uint32_t srcexp=(GETEXTPORT()[0x28]>>23)&0xff; - - value&=0x7FFFFFFF; - if(GETEXTPORT()[0x28]&(1<<31)) - value|=1<<31; - - return ScaleExp(value,0x7f-srcexp); - } - if(offset==0x2a) - { - uint32_t offset=((GETEXTPORT()[0x2a]>>11)&0x1fff)^0x1000; - uint32_t value=m_Tables[offset*2+0x30000/4]; - uint32_t srcexp=(GETEXTPORT()[0x2a]>>24)&0x7f; - - value&=0x7FFFFFFF; - - return ScaleExp(value,0x3f-srcexp); - } - if(offset==0x2b) - { - uint32_t offset=((GETEXTPORT()[0x2a]>>11)&0x1fff)^0x1000; - uint32_t value=m_Tables[offset*2+(0x30000/4)+1]; - uint32_t srcexp=(GETEXTPORT()[0x2a]>>24)&0x7f; - - value&=0x7FFFFFFF; - if(GETEXTPORT()[0x2a]&(1<<31)) - value|=1<<31; - - return ScaleExp(value,0x3f-srcexp); - } - - return GETEXTPORT()[offset]; } - - addr = ( EB & 0xFFFF0000 ) | ( offset & 0xFFFF ); - - return RDMEM(addr); + } + return 0; } -void mb86233_cpu_device::SETEXTERNAL( uint32_t EB, uint32_t offset, uint32_t value ) +void mb86233_device::ea_post_0(u32 r) { - uint32_t addr; - - if ( EB == 0 && offset >= 0x20 && offset <= 0x2f ) /* TGP Tables in ROM - FIXME - */ - { - GETEXTPORT()[offset] = value; - - if(offset==0x25 || offset==0x24) - { - if((GETEXTPORT()[0x24]&0x7fffffff)<=(GETEXTPORT()[0x25]&0x7fffffff)) - { - GETSR()|=EXTERNAL_FLAG; - } - else - { - GETSR()&=~EXTERNAL_FLAG; - } - } + if(!(r & 0x100)) return; + if(!(r & 0x080)) + m_x0 += m_i0; + else { + if(r & 0x10) + m_x0 += (r & 0xf) - 0x10; + else + m_x0 += r & 0xf; } - - addr = ( EB & 0xFFFF0000 ) | ( offset & 0xFFFF ); - - WRMEM( addr, value ); } - - -/*************************************************************************** - Register Access -***************************************************************************/ - -uint32_t mb86233_cpu_device::GETREGS( uint32_t reg, int source ) +u16 mb86233_device::ea_pre_1(u32 r) { - uint32_t mode = ( reg >> 6 ) & 0x07; - - reg &= 0x3f; - - if ( mode == 0 || mode == 1 || mode == 3 ) - { - if ( reg < 0x10 ) - { - return GETGPR(reg); - } - - switch( reg ) - { - case 0x10: /* A */ - return GETA().u; - - case 0x11: /* A.e */ - return (GETA().u >> 23) & 0xff; - - case 0x12: /* A.m */ - return (GETA().u & 0x7fffff) | ((GETA().u&0x80000000) >> 8); - - case 0x13: /* B */ - return GETB().u; - - case 0x14: /* B.e */ - return (GETB().u >> 23) & 0xff; - - case 0x15: /* B.m */ - return (GETB().u & 0x7fffff) | ((GETB().u&0x80000000) >> 8); - - case 0x19: /* D */ - return GETD().u; - - case 0x1A: /* D.e */ - return (GETD().u >> 23) & 0xff; - - case 0x1B: /* D.m */ - return (GETD().u & 0x7fffff) | ((GETD().u&0x80000000) >> 8); - - case 0x1C: /* P */ - return GETP().u; - - case 0x1D: /* P.e */ - return (GETP().u >> 23) & 0xff; - - case 0x1E: /* P.m */ - return (GETP().u & 0x7fffff) | ((GETP().u&0x80000000) >> 8); - - case 0x1F: /* Shift */ - return GETSHIFT(); - - case 0x20: /* Parallel Port */ - logerror( "TGP: Parallel port read at PC:%04x\n", GETPC() ); - return 0; - - case 0x21: /* FIn */ - { - if ( m_fifo_read_ok_cb() == ASSERT_LINE ) - { - return m_fifo_read_cb(); - } - - GETFIFOWAIT() = 1; - return 0; - } - - case 0x22: /* FOut */ - return 0; - - case 0x23: /* EB */ - return GETEB(); - - case 0x34: - return GETREPCNT(); - - default: - fatalerror( "TGP: Unknown GETREG (%d) at PC=%04x\n", reg, GETPC() ); + switch(r & 0x180) { + case 0x000: return r & 0x7f; + case 0x080: case 0x100: return (r & 0x7f) + m_b1 + m_x1; + case 0x180: { + switch(r & 0x60) { + case 0x00: return m_b1 + m_x1; + case 0x20: return m_x1; + case 0x40: return m_b1 + (m_x1 & m_vsmr); + case 0x60: return m_x1 & m_vsmr; } } - else if ( mode == 2 ) /* Indexed */ - { - uint32_t addr = reg & 0x1f; - - if ( source ) - { - if( !( reg & 0x20 ) ) - addr += GETGPR(0); - - addr += GETGPR(2); - } - else - { - if( !( reg & 0x20 ) ) - addr += GETGPR(1); - - addr += GETGPR(3); - } - - return addr; } - else if( mode == 6 ) /* Indexed with postop */ - { - uint32_t addr = 0; - - if ( source ) - { - if( !( reg & 0x20 ) ) - addr += GETGPR(0); - - addr += GETGPR(2); - } - else - { - if( !( reg & 0x20 ) ) - addr += GETGPR(1); - - addr += GETGPR(3); - } + return 0; +} - if ( reg & 0x10 ) - { - if ( source ) - GETGPR(2) -= 0x20 - ( reg & 0x1f ); - else - GETGPR(3) -= 0x20 - ( reg & 0x1f ); - } +void mb86233_device::ea_post_1(u32 r) +{ + if(!(r & 0x100)) + return; + if(!(r & 0x080)) + m_x1 += m_i1; + else { + if(r & 0x10) + m_x1 += (r & 0xf) - 0x10; else - { - if ( source ) - GETGPR(2) += ( reg & 0x1f ); - else - GETGPR(3) += ( reg & 0x1f ); - } - - return addr; - } - else - { - fatalerror( "TGP: Unknown GETREG mode %d at PC:%04x\n", mode, GETPC() ); + m_x1 += r & 0xf; } - - // never executed - //return 0; } -void mb86233_cpu_device::SETREGS( uint32_t reg, uint32_t val ) +u32 mb86233_device::read_reg(u32 r) { - int mode = ( reg >> 6) & 0x07; - - reg &= 0x3f; - - if( mode == 0 || mode == 1 || mode == 3 ) - { - if(reg==12 || reg==13) // counter regs seem to be 8 bit only - val&=0xff; - - if ( reg < 0x10 ) - { - GETGPR(reg) = val; - return; - } - - switch( reg ) - { - case 0x10: /* A */ - GETA().u = val; - break; - - case 0x11: /* A.e */ - GETA().u &= ~((0x0000007f) << 23); - GETA().u |= (( val & 0xff ) << 23 ); - break; - - case 0x12: /* A.m */ - GETA().u &= ~( 0x807fffff ); - GETA().u |= ( val & 0x7fffff ); - GETA().u |= ( val & 0x800000 ) << 8; - break; - - case 0x13: /* B */ - GETB().u = val; - break; - - case 0x14: /* B.e */ - GETB().u &= ~((0x0000007f) << 23); - GETB().u |= (( val & 0xff ) << 23 ); - break; - - case 0x15: /* B.m */ - GETB().u &= ~( 0x807fffff ); - GETB().u |= ( val & 0x7fffff ); - GETB().u |= ( val & 0x800000 ) << 8; - break; - - case 0x19: /* D */ - GETD().u = val; - break; - - case 0x1A: /* D.e */ - GETD().u &= ~((0x0000007f) << 23); - GETD().u |= (( val & 0xff ) << 23 ); - break; - - case 0x1B: /* B.m */ - GETD().u &= ~( 0x807fffff ); - GETD().u |= ( val & 0x7fffff ); - GETD().u |= ( val & 0x800000 ) << 8; - break; - - case 0x1C: /* P */ - GETP().u = val; - break; - - case 0x1D: /* P.e */ - GETP().u &= ~((0x000000ff) << 23); - GETP().u |= (( val & 0xff ) << 23 ); - break; - - case 0x1E: /* P.m */ - GETP().u &= ~( 0x807fffff ); - GETP().u |= ( val & 0x7fffff ); - GETP().u |= ( val & 0x800000 ) << 8; - break; - - case 0x1F: - GETSHIFT() = val; - break; - - case 0x20: /* Parallel Port */ - logerror( "TGP: Parallel port write: %08x at PC:%04x\n", val, GETPC() ); - break; - - case 0x22: /* FOut */ - m_fifo_write_cb( val ); - break; - - case 0x23: - GETEB() = val; - break; - - case 0x34: - GETREPCNT() = val; - break; - - default: - fatalerror( "TGP: Unknown register write (r:%d, mode:%d) at PC:%04x\n", reg, mode, GETPC()); - } - } - else - { - fatalerror( "TGP: Unknown register write (r:%d, mode:%d) at PC:%04x\n", reg, mode, GETPC()); + r &= 0x3f; + if(r >= 0x20 && r < 0x30) + return m_rf->read_dword(r & 0x1f); + switch(r) { + case 0x00: return m_b0; + case 0x01: return m_b1; + case 0x02: return m_x0; + case 0x03: return m_x1; + + case 0x0c: return m_c0; + case 0x0d: return m_c1; + + case 0x10: return m_a; + case 0x11: return get_exp(m_a); + case 0x12: return get_mant(m_a); + case 0x13: return m_b; + case 0x14: return get_exp(m_b); + case 0x15: return get_mant(m_b); + case 0x19: return m_d; + /* c */ + case 0x1a: return get_exp(m_d); + case 0x1b: return get_mant(m_d); + case 0x1c: return m_p; + case 0x1d: return get_exp(m_p); + case 0x1e: return get_mant(m_p); + case 0x1f: return m_sft; + + case 0x34: return m_rpc; + + default: + logerror("unimplemented read_reg(%02x)\n", r); + return 0; } } - -/*************************************************************************** - Addressing Modes -***************************************************************************/ - -uint32_t mb86233_cpu_device::INDIRECT( uint32_t reg, int source ) +void mb86233_device::write_reg(u32 r, u32 v) { - uint32_t mode = ( reg >> 6 ) & 0x07; - - if ( mode == 0 || mode == 1 || mode == 3 ) - { - return reg; + r &= 0x3f; + if(r >= 0x20 && r < 0x30) { + m_rf->write_dword(r & 0x1f, v); + return; } - else if ( mode == 2 ) - { - uint32_t addr = reg & 0x3f; - - if ( source ) - { - if( !(reg & 0x20) ) - addr += GETGPR(0); + switch(r) { + case 0x00: m_b0 = v; break; + case 0x01: m_b1 = v; break; + case 0x02: m_x0 = v; break; + case 0x03: m_x1 = v; break; - addr += GETGPR(2); - } - else - { - if( !(reg & 0x20) ) - addr += GETGPR(1); + case 0x05: m_i0 = v; break; + case 0x06: m_i1 = v; break; - addr += GETGPR(3); - } + case 0x08: m_sp = v; break; - return addr; - } - else if ( mode == 6 || mode == 7 ) - { - uint32_t addr = 0; + case 0x0a: m_vsm = v & 7; m_vsmr = (8 << m_vsm) - 1; break; - if ( source ) - { - if ( !( reg & 0x20 ) ) - addr += GETGPR(0); - - addr += GETGPR(2); - } + case 0x0c: + m_c0 = v; + if(m_c0 == 1) + m_st |= F_ZC0; else - { - if ( !( reg & 0x20 ) ) - addr += GETGPR(1); - - addr += GETGPR(3); - } + m_st &= ~F_ZC0; + break; - if ( reg & 0x10 ) - { - if ( source ) - GETGPR(2) -= 0x20 - ( reg & 0x1f ); - else - GETGPR(3) -= 0x20 - ( reg & 0x1f ); - } + case 0x0d: + m_c1 = v; + if(m_c1 == 1) + m_st |= F_ZC1; else - { - if ( source ) - GETGPR(2) += ( reg & 0x1f ); - else - GETGPR(3) += ( reg & 0x1f ); - } - if( mode == 7) - { - if ( source ) - GETGPR(2)&=0x3f; - else - GETGPR(3)&=0x3f; - } + m_st &= ~F_ZC1; + break; - return addr; - } - else - { - fatalerror( "TGP: Unknown INDIRECT mode %d at PC:%04x\n", mode, GETPC() ); + case 0x0f: break; + + case 0x10: m_a = v; break; + case 0x11: m_a = set_exp(m_a, v); break; + case 0x12: m_a = set_mant(m_a, v); break; + case 0x13: m_b = v; break; + case 0x14: m_b = set_exp(m_b, v); break; + case 0x15: m_b = set_mant(m_b, v); break; + /* c */ + case 0x19: m_d = v; testdz(); break; + case 0x1a: m_d = set_exp(m_d, v); testdz(); break; + case 0x1b: m_d = set_mant(m_d, v); testdz(); break; + case 0x1c: m_p = v; break; + case 0x1d: m_p = set_exp(m_p, v); break; + case 0x1e: m_p = set_mant(m_p, v); break; + case 0x1f: m_sft = v; break; + + case 0x34: m_rpc = v; break; + case 0x3c: m_mask = v; break; + + default: + logerror("unimplemented write_reg(%02x, %08x)\n", r, v); + break; } - - // never executed - //return 0; } -/*************************************************************************** - Core Execution Loop -***************************************************************************/ +void mb86233_device::write_mem_internal_1(u32 r, u32 v, bool bank) +{ + u16 ea = ea_pre_1(r); + if(bank) + ea += 0x200; + m_data->write_dword(ea, v); + ea_post_1(r); +} -void mb86233_cpu_device::execute_run() +void mb86233_device::write_mem_io_1(u32 r, u32 v) { - while( m_icount > 0 ) - { - uint32_t val; - uint32_t opcode; + u16 ea = ea_pre_1(r); + m_io->write_dword(ea, v); + ea_post_1(r); +} - debugger_instruction_hook(GETPC()); +void mb86233_device::execute_run() +{ + while(m_icount > 0) { + m_ppc = m_pc; + debugger_instruction_hook(m_ppc); + u32 opcode = m_direct->read_dword(m_pc++); + + switch((opcode >> 26) & 0x3f) { + case 0x00: { + // lab + u32 r1 = opcode & 0x1ff; + u32 r2 = (opcode >> 9) & 0x1ff; + u32 alu = (opcode >> 21) & 0x1f; + u32 op = (opcode >> 18) & 0x7; + + alu_pre(alu); + + switch(op) { + case 0: { + // lab mem, mem (e) + + u32 ea1 = ea_pre_0(r1); + u32 v1 = m_data->read_dword(ea1); + if(m_stall) goto do_stall; + + u32 ea2 = ea_pre_1(r2); + u32 v2 = m_io->read_dword(ea2); + if(m_stall) goto do_stall; + + ea_post_0(r1); + ea_post_1(r2); + + m_a = v1; + m_b = v2; + break; + } - opcode = ROPCODE(GETPC()); + case 3: { + // lab mem, mem + 0x200 - GETFIFOWAIT() = 0; + u32 ea1 = ea_pre_0(r1); + u32 v1 = m_data->read_dword(ea1); + if(m_stall) goto do_stall; - switch( (opcode >> 26) & 0x3f ) - { - case 0x00: /* dual move */ - { - uint32_t r1 = opcode & 0x1ff; - uint32_t r2 = ( opcode >> 9 ) & 0x7f; - uint32_t alu = ( opcode >> 21 ) & 0x1f; - uint32_t op = ( opcode >> 16 ) & 0x1f; + u32 ea2 = ea_pre_1(r2) + 0x200; + u32 v2 = m_data->read_dword(ea2); + if(m_stall) goto do_stall; - ALU( alu ); + ea_post_0(r1); + ea_post_1(r2); - switch( op ) - { - case 0x01: - GETA().u = GETARAM()[INDIRECT(r1,1)]; - GETB().u = GETEXTERNAL( GETEB(),INDIRECT(r2|(2<<6), 0)); - break; + m_a = v1; + m_b = v2; + break; + } - case 0x04: // ? - GETA().u = GETARAM()[r1]; - GETB().u = GETEXTERNAL( GETEB(),r2); - break; + case 4: { + // lab mem + 0x200, mem - case 0x0C: - GETA().u = GETARAM()[INDIRECT(r1,1)]; - GETB().u = GETBRAM()[r2]; - break; + u32 ea1 = ea_pre_0(r1) + 0x200; + u32 v1 = m_data->read_dword(ea1); + if(m_stall) goto do_stall; - case 0x0D: // VF2 shadows - GETA().u = GETARAM()[INDIRECT(r1,1)]; - GETB().u = GETBRAM()[INDIRECT(r2|2<<6,0)]; - break; + u32 ea2 = ea_pre_1(r2); + u32 v2 = m_data->read_dword(ea2); + if(m_stall) goto do_stall; - case 0x0F: - GETA().u = GETARAM()[r1]; - GETB().u = GETBRAM()[INDIRECT(r2|6<<6,0)]; - break; + ea_post_0(r1); + ea_post_1(r2); - case 0x10: - GETA().u = GETBRAM()[INDIRECT(r1,1)]; - GETB().u = GETARAM()[r2]; - break; + m_a = v1; + m_b = v2; + break; + } - case 0x11: - GETA().u = GETBRAM()[INDIRECT(r1,1)]; - GETB().u = GETARAM()[INDIRECT(r2|(2<<6),0)]; - break; + default: + logerror("unhandler lab subop %x\n", op); + break; - default: - logerror( "TGP: Unknown TGP double move (op=%d) at PC:%x\n", op, GETPC()); - break; - } } - break; - - case 0x7: /* LD/MOV */ - { - uint32_t r1 = opcode & 0x1ff; - uint32_t r2 = ( opcode >> 9 ) & 0x7f; - uint32_t alu = ( opcode >> 21 ) & 0x1f; - uint32_t op = ( opcode >> 16 ) & 0x1f; - - switch( op ) - { - case 0x04: /* MOV RAM->External */ - { - SETEXTERNAL( GETEB(), r2, GETARAM()[r1]); - ALU(alu); - } - break; - case 0x0c: /* MOV RAM->BRAM */ - { - GETBRAM()[r2] = GETARAM()[r1]; - ALU(alu); - } - break; + alu_post(alu); + break; + } - case 0x0d: /* Move RAM->BRAM indirect? */ - { - val = GETARAM()[r1]; - ALU(alu); - GETBRAM()[INDIRECT(r2|(2<<6),0)] = val; - } - break; - case 0x1d: /* MOV RAM->Reg */ - { - if ( r1 & 0x180 ) - { - val = GETARAM()[GETREGS(r1,0)]; - } - else - { - val = GETARAM()[r1]; - } - - /* if we're waiting for data, don't complete the instruction */ - if ( GETFIFOWAIT() ) - break; - - ALU(alu); - SETREGS(r2,val); - } - break; + case 0x07: { + // ld / mov + u32 r1 = opcode & 0x1ff; + u32 r2 = (opcode >> 9) & 0x1ff; + u32 alu = (opcode >> 21) & 0x1f; + u32 op = (opcode >> 18) & 0x7; - case 0x1c: /* MOV Reg->RAMInd */ - { - val = GETREGS(r2,1); + alu_pre(alu); - /* if we're waiting for data, don't complete the instruction */ - if ( GETFIFOWAIT() ) - break; + switch(op) { + case 0: { + // mov mem, mem (e) + u32 ea = ea_pre_0(r1); + u32 v = m_data->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(r1); + write_mem_io_1(r2, v); + break; + } - ALU(alu); + case 1: { + // mov mem + 0x200, mem (e) + u32 ea = ea_pre_0(r1) + 0x200*0; + u32 v = m_data->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(r1); + write_mem_io_1(r2, v); + break; + } - if ( ( r2 >> 6 ) & 0x01) - { - SETEXTERNAL( GETEB(),INDIRECT(r1,0),val); - } - else - { - GETARAM()[INDIRECT(r1,0)] = val; - } - } - break; + case 2: { + // mov mem (e), mem + u32 ea = ea_pre_0(r1); + u32 v = m_io->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(r1); + write_mem_internal_1(r2, v, false); + break; + } - case 0x1f: /* MOV Reg->Reg */ - { - if ( r1 == 0x10 && r2 == 0xf ) - { - /* NOP */ - ALU( alu); - } - else - { - val = GETREGS(r1,1); - - /* if we're waiting for data, don't complete the instruction */ - if ( GETFIFOWAIT() ) - break; - - ALU(alu); - SETREGS(r2, val); - } - } - break; + case 3: { + // mov mem, mem + 0x200 + u32 ea = ea_pre_0(r1); + u32 v = m_data->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(r1); + write_mem_internal_1(r2, v, true); + break; + } - case 0x0f: /* MOV RAMInd->BRAMInd */ - { - val = GETARAM()[INDIRECT(r1,1)]; - ALU(alu); - GETBRAM()[INDIRECT(r2|(6<<6),0)] = val; - } - break; + case 4: { + // mov mem + 0x200, mem + u32 ea = ea_pre_0(r1) + 0x200; + u32 v = m_data->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(r1); + write_mem_internal_1(r2, v, false); + break; + } - case 0x13: /* MOV BRAMInd->RAMInd */ - { - val = GETBRAM()[INDIRECT(r1,1)]; - ALU(alu); - GETARAM()[INDIRECT(r2|(6<<6),0)] = val; - } - break; + case 5: { + // mov mem (o), mem + u32 ea = ea_pre_0(r1); + u32 v = m_program->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(r1); + write_mem_internal_1(r2, v, false); + break; + } - case 0x10: /* MOV RAMInd->RAM */ - { - val = GETBRAM()[INDIRECT(r1,1)]; - ALU(alu); - GETARAM()[r2] = val; - } + case 7: { + switch(r2 >> 6) { + case 0: { + // mov reg, mem + u32 v = read_reg(r2); + if(m_stall) goto do_stall; + write_mem_internal_1(r1, v, false); break; + } - case 0x1e: /* External->Reg */ - { - uint32_t offset; - - if ( (( r2 >> 6 ) & 7) == 1 ) - { - offset = INDIRECT(r1,1); - val = GETEXTERNAL(0,offset); - } - else - { - offset = INDIRECT(r1,0); - val = GETEXTERNAL(GETEB(),offset); - } - - ALU(alu); - SETREGS(r2,val); - } + case 1: { + // mov reg, mem (e) + u32 v = read_reg(r2); + if(m_stall) goto do_stall; + write_mem_io_1(r1, v); break; + } - case 0x03: /* RAM->External Ind */ - { - val = GETARAM()[r1]; - ALU(alu); - SETEXTERNAL(GETEB(),INDIRECT(r2|(6<<6),0),val); - } + case 2: { + // mov mem + 0x200, reg + u32 ea = ea_pre_1(r1) + 0x200; + u32 v = m_data->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_1(r1); + write_reg(r2, v); break; + } - case 0x07: /* RAMInd->External */ - { - val = GETARAM()[INDIRECT(r1,1)]; - ALU(alu); - SETEXTERNAL( GETEB(),INDIRECT(r2|(6<<6),0),val); - } + case 3: { + // mov mem, reg + u32 ea = ea_pre_1(r1); + u32 v = m_data->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_1(r1); + write_reg(r2, v); break; + } - case 0x08: /* External->RAM */ - { - val = GETEXTERNAL( GETEB(),INDIRECT(r1,1)); - ALU(alu); - GETARAM()[r2] = val; - } + case 4: { + // mov mem (e), reg + u32 ea = ea_pre_1(r1); + u32 v = m_io->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_1(r1); + write_reg(r2, v); break; + } - case 0x0b: /* External->RAMInd */ - { - val = GETEXTERNAL( GETEB(),INDIRECT(r1,1)); - ALU( alu); - GETARAM()[INDIRECT(r2|(6<<6),0)] = val; - } + case 5: { + // mov mem (o), reg + u32 ea = ea_pre_0(r1); + u32 v = m_program->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(r1); + write_reg(r2, v); break; + } - case 0x17: /* External r2-> RAMInd r3 */ - { - uint32_t offset; - - offset = INDIRECT(r1,1); - - val = GETEXTERNAL( GETEB(), offset); - ALU(alu); - GETARAM()[INDIRECT(r2|(6<<6),0)] = val; - } + case 6: { + // mov reg, reg + u32 v = read_reg(r1); + if(m_stall) goto do_stall; + write_reg(r2, v); break; - case 0x14: - { - uint32_t offset; - - offset = INDIRECT(r1,1); + } - val = GETEXTERNAL( 0, offset); - ALU(alu); - GETARAM()[r2] = val; - } + default: + logerror("unhandler ld/mov subop 7/%x\n", r2 >> 6); break; - - default: - fatalerror( "TGP: Unknown TGP move (op=%02x) at PC:%x\n", op, GETPC()); } + break; } - break; - - case 0x0d: /* CONTROL? */ - { - uint32_t sub = (opcode>>16) & 0xff; - - switch(sub) - { - case 0x0a: // FPU Round Control opcode - m_fpucontrol = opcode & 0xff; - logerror( "TGP: FPU Round CONTROL sets %02x at PC:%x\n", m_fpucontrol, GETPC()); - break; - default: - logerror( "TGP: Unknown CONTROL sub-type %02x at PC:%x\n", sub, GETPC()); - break; - } + default: + logerror("unhandler ld/mov subop %x\n", op); break; } - case 0x0e: /* LDIMM24 */ - { - uint32_t sub = (opcode>>24) & 0x03; - uint32_t imm = opcode & 0xffffff; - - /* sign extend 24->32 */ - if ( imm & 0x800000 ) - imm |= 0xFF000000; + alu_post(alu); + break; + } - switch( sub ) - { - case 0x00: /* P */ - GETP().u = imm; - break; + case 0x0d: { + // stm/clm + u32 sub2 = (opcode >> 17) & 7; - case 0x01: /* A */ - GETA().u = imm; - break; + // Theorically has restricted alu too - case 0x02: /* B */ - GETB().u = imm; - break; + switch(sub2) { + case 5: + // stmh + // bit 0 = floating point + // bit 1-2 = rounding mode + m_m = opcode; + break; - case 0x03: /* D */ - GETD().u = imm; - break; - } + default: + logerror("unimplemented opcode 0d/%x\n", sub2); + break; } break; + } - case 0x0f: /* REP/CLEAR/FLAGS */ - { - uint32_t alu = ( opcode >> 20 ) & 0x1f; - uint32_t sub2 = ( opcode >> 16 ) & 0x0f; - - ALU(alu); - - if( sub2 == 0x00 ) /* CLEAR reg */ - { - uint32_t reg = opcode & 0x1f; - - switch( reg ) - { - case 0x10: - GETD().u = 0; - break; - - case 0x08: - GETB().u = 0; - break; - - case 0x04: - GETA().u = 0; - break; - } - } - else if ( sub2 == 0x04 ) /* REP xxx */ - { - uint32_t sub3 = ( opcode >> 12 ) & 0x0f; - - if ( sub3 == 0 ) - { - GETREPS() = opcode & 0xfff; - - if ( GETREPS() == 0 ) - GETREPS() = 0x100; - - GETPC()++; - } - else if ( sub3 == 8 ) - { - GETREPS() = GETREGS( opcode & 0xfff, 0 ); - GETPC()++; - } - } - else if ( sub2 == 0x02 ) /* CLRFLAGS */ - { - GETSR() &= ~(opcode&0xfff); - } - else if ( sub2 == 0x06 ) /* SETFLAGS */ - { - GETSR() |= (opcode&0xfff); - } + case 0x0e: { + // lipl / lia / lib / lid + switch((opcode >> 24) & 0x3) { + case 0: + m_p = (m_p & 0xffffff000000) | (opcode & 0xffffff); + break; + case 1: + m_a = s24_32(opcode); + break; + case 2: + m_b = s24_32(opcode); + break; + case 3: + m_d = s24_32(opcode); + testdz(); + break; } break; + } - case 0x10: /* LDIMM rx */ - { - uint32_t sub = (opcode>>24) & 0x03; - uint32_t imm = opcode & 0xffff; + case 0x0f: { + // rep/clr0/clr1/set + u32 alu = (opcode >> 20) & 0x1f; + u32 sub2 = (opcode >> 17) & 7; + + alu_pre(alu); + + switch(sub2) { + case 0: + // clr0 + if(opcode & 0x0004) m_a = 0; + if(opcode & 0x0008) m_b = 0; + if(opcode & 0x0010) m_d = 0; + break; - GETGPR(sub) = imm; - } - break; + case 1: + // clr1 - flags mapping unknown + break; - case 0x13: /* LDIMM r1x */ - { - uint32_t sub = (opcode>>24) & 0x03; - uint32_t imm = opcode & 0xffffff; - - if ( sub == 0 ) /* R12 */ - GETGPR(12) = imm; - else if ( sub == 1 ) /* R13 */ - GETGPR(13) = imm; - else - logerror( "TGP: Unknown LDIMM r12 (sub=%d) at PC:%04x\n", sub, GETPC() ); + case 2: { + // rep + u8 r = opcode & 0x8000 ? read_reg(opcode) : opcode; + if(m_stall) goto do_stall; + m_r = r; + goto rep_start; } - break; - case 0x14: /* LDIMM m,e */ - { - uint32_t sub = (opcode>>24) & 0x03; - uint32_t imm = opcode & 0xffffff; + case 3: + // set - flags mapping unknown + // 0800 = enable interrupt flag + break; - if ( sub == 0 ) /* A */ - { - GETA().u = imm; - } - else if ( sub == 1 ) /* A.e */ - { - GETA().u &= ~0x7f800000; - GETA().u |= (imm & 0xff) << 23; - } - else if ( sub == 2 ) /* A.m */ - { - GETA().u &= 0x7f800000; - GETA().u |= (imm & 0x7fffff ) | ((imm & 0x800000) << 8); - } - else - { - fatalerror( "TGP: Unknown LDIMM m,e (sub=%d) at PC:%04x\n", sub, GETPC() ); - } + default: + logerror("unimplemented opcode 0f/%x\n", sub2); + break; } + + alu_post(alu); break; + } - case 0x15: /* LDIMM m,e */ - { - uint32_t sub = (opcode>>24) & 0x03; - uint32_t imm = opcode & 0xffffff; - - if ( sub == 0 ) /* B.e again? */ - { - //GETB().u = ((imm & 0x7f) << 23) | ((imm & 0xff) << 8) | ( imm & 0xff ); - GETB().u &= ~0x7f800000; - GETB().u |= (imm & 0xff) << 23; - } - else if ( sub == 1 ) /* B.e */ - { - GETB().u &= ~0x7f800000; - GETB().u |= (imm & 0xff) << 23; - } - else if ( sub == 2 ) /* B.m */ - { - GETB().u &= 0x7f800000; - GETB().u |= (imm & 0x7fffff ) | ((imm & 0x800000) << 8); - } - else - { - fatalerror( "TGP: Unknown LDIMM m,e (sub=%d) at PC:%04x\n", sub, GETPC() ); - } - } + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: { + // ldi + write_reg(opcode >> 24, s24_32(opcode)); break; + } - case 0x16: /* LDIMM m,e */ - { - uint32_t sub = (opcode>>24) & 0x03; - uint32_t imm = opcode & 0xffffff; + case 0x2f: case 0x3f: { + // Conditional branch of every kind + u32 cond = ( opcode >> 20 ) & 0x1f; + u32 subtype = ( opcode >> 17 ) & 7; + u32 data = opcode & 0xffff; + bool invert = opcode & 0x40000000; - if ( sub == 1 ) /* clear + D.m */ - { - GETD().u = (imm & 0x7fffff ) | ((imm & 0x800000) << 8); - } - else if ( sub == 2 ) /* D.e */ - { - GETD().u &= ~0x7f800000; - GETD().u |= (imm & 0xff) << 23; - } - else if ( sub == 3 ) /* D.m */ - { - GETD().u &= 0x7f800000; - GETD().u |= (imm & 0x7fffff ) | ((imm & 0x800000) << 8); - } - else - { - fatalerror( "TGP: Unknown LDIMM m,e (sub=%d) at PC:%04x\n", sub, GETPC() ); - } - } - break; + bool cond_passed = false; - case 0x17: /* LDIMM special reg */ - { - uint32_t sub = (opcode>>24) & 0x03; - uint32_t imm = opcode & 0xffffff; + switch(cond) { + case 0x00: // zrd - d zero + cond_passed = m_st & F_ZRD; + break; - if ( sub == 0x03 ) - { - GETSHIFT() = imm; - } - else - { - logerror( "TGP: Unknown LDIMM special reg (sub=%d) at PC:%04x\n", sub, GETPC() ); - } - } - break; + case 0x01: // ged - d >= 0 + cond_passed = !(m_st & F_SGD); + break; - case 0x18: /* LDIMM external reg */ - { - uint32_t sub = (opcode>>24) & 0x03; - uint32_t imm = opcode & 0xffffff; + case 0x02: // led - d <= 0 + cond_passed = m_st & (F_ZRD | F_SGD); + break; - if ( sub == 0x03 ) - { - GETEB() = imm; - } - else - { - fatalerror( "TGP: Unknown LDIMM external reg (sub=%d) at PC:%04x\n", sub, GETPC() ); - } - } - break; + case 0x0a: // gpio0 + cond_passed = m_gpio0; + break; - case 0x1d: //LDIMM to Rep regs - { - uint32_t sub = (opcode>>24)&0x3; - uint32_t imm = opcode&0xffffff; - if(sub == 0x00) - { - GETREPCNT() = imm; - } - else - { - fatalerror( "TGP: Unknown LDIMM REPCnt (sub=%d) at PC:%04x\n", sub, GETPC() ); - } - } - break; + case 0x0b: // gpio1 + cond_passed = m_gpio1; + break; - case 0x2f: /* Conditional Branches */ - { - uint32_t cond = ( opcode >> 20 ) & 0x1f; - uint32_t subtype = ( opcode >> 16 ) & 0x0f; - uint32_t data = opcode & 0xffff; - - if( COND( cond) ) - { - switch( subtype ) - { - case 0x00: /* BRIF <addr> */ - GETPC() = data - 1; - break; - - case 0x02: /* BRIF indirect */ - data = GETREGS(data&0x7f,0) - 1; - - /* if we're waiting for data, don't complete the instruction */ - if ( GETFIFOWAIT() ) - break; - - GETPC() = data; - break; - - case 0x04: /* BSIF <addr> */ - GETPCS()[GETPCSP()] = GETPC(); - GETPCSP()++; - GETPC() = data - 1; - break; - - case 0x06: /* BSIF indirect */ - GETPCS()[GETPCSP()] = GETPC(); - GETPCSP()++; - if ( data & 0x4000 ) - data = GETREGS(data&0x7f,0) - 1; - else - data = ((GETARAM()[data&0x3ff])&0xffff)-1; - - /* if we're waiting for data, don't complete the instruction */ - if ( GETFIFOWAIT() ) - break; - - GETPC() = data; - break; - - case 0x0a: /* RTIF */ - --GETPCSP(); - GETPC() = GETPCS()[GETPCSP()]; - break; - - case 0x0c: /* LDIF */ - SETREGS(((data>>9)&0x7f), GETARAM()[data&0x1FF] ); - break; - - case 0x0e: /* RIIF */ - fatalerror( "TGP: RIIF unimplemented at PC:%04x\n", GETPC() ); - - default: - fatalerror( "TGP: Unknown Branch opcode (subtype=%d) at PC:%04x\n", subtype, GETPC() ); - } - } - } - break; + case 0x0c: // gpio2 + cond_passed = m_gpio2; + break; - case 0x3f: /* Inverse Conditional Branches */ - { - uint32_t cond = ( opcode >> 20 ) & 0x1f; - uint32_t subtype = ( opcode >> 16 ) & 0x0f; - uint32_t data = opcode & 0xffff; + case 0x10: // zc0 - c0 == 1 + cond_passed = !(m_st & F_ZC0); + break; - if( !COND( cond) ) - { - switch( subtype ) - { - case 0x00: /* BRUL <addr> */ - GETPC() = data - 1; - break; + case 0x11: // zc1 - c1 == 1 + cond_passed = !(m_st & F_ZC1); + break; - case 0x02: /* BRUL indirect */ - data = GETREGS(data&0x7f,0) - 1; + case 0x12: // gpio3 + cond_passed = m_gpio3; + break; - /* if we're waiting for data, don't complete the instruction */ - if ( GETFIFOWAIT() ) - break; + case 0x16: // alw - always + cond_passed = true; + break; - GETPC() = data; - break; + default: + logerror("unimplemented condition %x\n", cond); + break; + } + if(invert) + cond_passed = !cond_passed; - case 0x04: /* BSUL <addr> */ - GETPCS()[GETPCSP()] = GETPC(); - GETPCSP()++; - GETPC() = data - 1; - break; + if(cond_passed) { + switch(subtype) { + case 0: // brif #adr + m_pc = data; + break; - case 0x06: /* BSUL indirect */ - data = GETARAM()[data] - 1; + case 1: // brul + if(opcode & 0x4000) { + // brul reg + u32 v = read_reg(opcode); + if(m_stall) goto do_stall; + m_pc = v; + } else { + // brul adr + u32 ea = ea_pre_0(opcode); + u32 v = m_data->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(opcode); + m_pc = v; + } + break; - /* if we're waiting for data, don't complete the instruction */ - if ( GETFIFOWAIT() ) - break; + case 2: // bsif #adr + pcs_push(); + m_pc = data; + break; - GETPC() = data; - break; + case 3: // bsul + if(opcode & 0x4000) { + // bsul reg + u32 v = read_reg(opcode); + if(m_stall) goto do_stall; + pcs_push(); + m_pc = v; + } else { + // bsul adr + u32 ea = ea_pre_0(opcode); + u32 v = m_data->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(opcode); + pcs_push(); + m_pc = v; + } + break; - case 0x0a: /* RTUL */ - --GETPCSP(); - GETPC() = GETPCS()[GETPCSP()]; - break; + case 5: // rtif #adr + pcs_pop(); + break; - case 0x0c: /* LDUL */ - SETREGS(((data>>9)&0x7f), GETARAM()[data&0x1FF] ); - break; + case 6: { // ldif adr, rn + u32 ea = ea_pre_0(opcode); + u32 v = m_data->read_dword(ea); + if(m_stall) goto do_stall; + ea_post_0(opcode); + write_reg(opcode >> 9, v); + break; + } - case 0x0e: /* RIUL */ - fatalerror( "TGP: RIUL unimplemented at PC:%04x\n", GETPC() ); + default: + logerror("unimplemented branch subtype %x\n", subtype); + break; + } + } - default: - fatalerror( "TGP: Unknown Branch opcode (subtype=%d) at PC:%04x\n", subtype, GETPC() ); + if(subtype < 2) + switch(cond) { + case 0x10: + if(m_c0 != 1) { + m_c0 --; + if(m_c0 == 1) + m_st |= F_ZC0; } + break; + + case 0x11: + if(m_c1 != 1) { + m_c1 --; + if(m_c1 == 1) + m_st |= F_ZC1; + } + break; } - } + break; + } - case 0x1f: - case 0x12: - logerror( "TGP: unknown opcode %08x at PC:%04x (%02x)\n", opcode, GETPC(),(opcode >> 26) & 0x3f ); + default: + logerror("unimplemented opcode type %02x\n", (opcode >> 26) & 0x3f); break; - - default: - fatalerror( "TGP: unknown opcode %08x at PC:%04x (%02x)\n", opcode, GETPC(),(opcode >> 26) & 0x3f ); } - if ( GETFIFOWAIT() == 0 ) - { - if( GETREPS() == 0 ) - GETPC()++; - else - --GETREPS(); - - m_icount--; + if(m_r != 1) { + m_pc = m_ppc; + m_r --; } - else - { - m_icount = 0; + + rep_start: + if(0) { + do_stall: + m_pc = m_ppc; + m_stall = false; } + m_icount--; } } diff --git a/src/devices/cpu/mb86233/mb86233.h b/src/devices/cpu/mb86233/mb86233.h index 1d25be5eae4..255b16d16e4 100644 --- a/src/devices/cpu/mb86233/mb86233.h +++ b/src/devices/cpu/mb86233/mb86233.h @@ -1,143 +1,137 @@ // license:BSD-3-Clause -// copyright-holders:Ernesto Corvi +// copyright-holders:Olivier Galibert + #ifndef MAME_CPU_MB86233_MB86233_H #define MAME_CPU_MB86233_MB86233_H #pragma once +class mb86233_device : public cpu_device +{ +public: + enum address_space_ids { + AS_RF = 4, + AS_EXTERNAL = 5 + }; -#define MCFG_MB86233_FIFO_READ_CB(_devcb) \ - devcb = &downcast<mb86233_cpu_device &>(*device).set_fifo_read_cb(DEVCB_##_devcb); -#define MCFG_MB86233_FIFO_READ_OK_CB(_devcb) \ - devcb = &downcast<mb86233_cpu_device &>(*device).set_fifo_read_ok_cb(DEVCB_##_devcb); -#define MCFG_MB86233_FIFO_WRITE_CB(_devcb) \ - devcb = &downcast<mb86233_cpu_device &>(*device).set_fifo_write_cb(DEVCB_##_devcb); -#define MCFG_MB86233_TABLE_REGION(_region) \ - downcast<mb86233_cpu_device &>(*device).set_tablergn(_region); + enum regs_ids { + REG_A, REG_B, REG_D, REG_P, + REG_R, REG_C0, REG_C1, + REG_B0, REG_B1, REG_X0, REG_X1, REG_I0, REG_I1, + REG_SFT, REG_VSM, REG_MASK, REG_M, + REG_PCS0, REG_PCS1, REG_PCS2, REG_PCS3 + }; + enum st_flags { + F_ZRC = 0x00000001, + F_ZRD = 0x00000002, + F_SGC = 0x00000004, + F_SGD = 0x00000008, + F_CPC = 0x00000010, + F_CPD = 0x00000020, + F_OVC = 0x00000040, + F_OVD = 0x00000080, + F_UNC = 0x00000100, + F_UND = 0x00000200, + F_DVZC = 0x00000400, + F_DVZD = 0x00000800, + F_CA = 0x00001000, + F_CPP = 0x00002000, + F_OVM = 0x00004000, + F_UNM = 0x00008000, + F_SIF0 = 0x00010000, + F_SIF1 = 0x00020000, + F_SOF0 = 0x00040000, + + F_PIF = 0x00100000, + F_POF = 0x00200000, + F_PAIF = 0x00400000, + F_PAOF = 0x00800000, + F_F0S = 0x01000000, + F_F1S = 0x02000000, + F_IT = 0x04000000, + F_ZX0 = 0x08000000, + F_ZX1 = 0x10000000, + F_ZX2 = 0x20000000, + F_ZC0 = 0x40000000, + F_ZC1 = 0x80000000 + }; -class mb86233_cpu_device : public cpu_device -{ -public: - // construction/destruction - mb86233_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + mb86233_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - // configuration helpers - template <class Object> devcb_base &set_fifo_read_cb(Object &&cb) { return m_fifo_read_cb.set_callback(std::forward<Object>(cb)); } - template <class Object> devcb_base &set_fifo_read_ok_cb(Object &&cb) { return m_fifo_read_ok_cb.set_callback(std::forward<Object>(cb)); } - template <class Object> devcb_base &set_fifo_write_cb(Object &&cb) { return m_fifo_write_cb.set_callback(std::forward<Object>(cb)); } - void set_tablergn(const char *tablergn) { m_tablergn = tablergn; } + void stall() { m_stall = true; } + + DECLARE_WRITE_LINE_MEMBER(gpio0_w); + DECLARE_WRITE_LINE_MEMBER(gpio1_w); + DECLARE_WRITE_LINE_MEMBER(gpio2_w); + DECLARE_WRITE_LINE_MEMBER(gpio3_w); protected: - // register enumeration - enum - { - MB86233_PC=1, - MB86233_A, - MB86233_B, - MB86233_D, - MB86233_P, - MB86233_REP, - MB86233_SP, - MB86233_EB, - MB86233_SHIFT, - MB86233_FLAGS, - MB86233_R0, - MB86233_R1, - MB86233_R2, - MB86233_R3, - MB86233_R4, - MB86233_R5, - MB86233_R6, - MB86233_R7, - MB86233_R8, - MB86233_R9, - MB86233_R10, - MB86233_R11, - MB86233_R12, - MB86233_R13, - MB86233_R14, - MB86233_R15 - }; + mb86233_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - // device-level overrides virtual void device_start() override; virtual void device_reset() override; - // device_execute_interface overrides virtual uint32_t execute_min_cycles() const override { return 1; } - virtual uint32_t execute_max_cycles() const override { return 2; } - virtual uint32_t execute_input_lines() const override { return 0; } + virtual uint32_t execute_max_cycles() const override { return 1; } + virtual uint32_t execute_input_lines() const override { return 4; } virtual void execute_run() override; - // device_memory_interface overrides virtual space_config_vector memory_space_config() const override; - - // device_state_interface overrides virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - // device_disasm_interface overrides virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; private: address_space_config m_program_config; address_space_config m_data_config; + address_space_config m_io_config; + address_space_config m_rf_config; - union MB86233_REG - { - int32_t i; - uint32_t u; - float f; - }; - - uint16_t m_pc; - MB86233_REG m_a; - MB86233_REG m_b; - MB86233_REG m_d; - MB86233_REG m_p; - - uint16_t m_reps; - uint16_t m_pcs[4]; - uint8_t m_pcsp; - uint32_t m_eb; - uint32_t m_shift; - uint32_t m_repcnt; - uint16_t m_sr; - uint8_t m_fpucontrol; - - uint32_t m_gpr[16]; - uint32_t m_extport[0x30]; - - address_space *m_program; + address_space *m_program, *m_data, *m_io, *m_rf; direct_read_data<-2> *m_direct; int m_icount; - /* FIFO */ - int m_fifo_wait; - devcb_read32 m_fifo_read_cb; - devcb_read_line m_fifo_read_ok_cb; - devcb_write32 m_fifo_write_cb; - const char *m_tablergn; - - /* internal RAM */ - uint32_t m_RAM[2 * 0x200]; - uint32_t *m_ARAM, *m_BRAM; - uint32_t *m_Tables; - - void FLAGSF( float v ); - void FLAGSI( uint32_t v ); - int COND( uint32_t cond ); - void ALU( uint32_t alu); - uint32_t ScaleExp(unsigned int v,int scale); - uint32_t GETEXTERNAL( uint32_t EB, uint32_t offset ); - void SETEXTERNAL( uint32_t EB, uint32_t offset, uint32_t value ); - uint32_t GETREGS( uint32_t reg, int source ); - void SETREGS( uint32_t reg, uint32_t val ); - uint32_t INDIRECT( uint32_t reg, int source ); + u32 m_st, m_a, m_b, m_d, m_p; + u32 m_alu_stmask, m_alu_stset, m_alu_r1, m_alu_r2; + u16 m_ppc, m_pc, m_sp, m_b0, m_b1, m_x0, m_x1, m_i0, m_i1, m_vsmr, m_pcs[4], m_mask, m_m; + u8 m_r, m_rpc, m_c0, m_c1, m_sft, m_vsm; + bool m_gpio0, m_gpio1, m_gpio2, m_gpio3; + + bool m_stall; + + static s32 s24_32(u32 val); + static u32 set_exp(u32 val, u32 exp); + static u32 set_mant(u32 val, u32 mant); + static u32 get_exp(u32 val); + static u32 get_mant(u32 val); + + void testdz(); + void alu_update_st(); + void alu_pre(u32 alu); + void alu_post(u32 alu); + u16 ea_pre_0(u32 r); + void ea_post_0(u32 r); + u16 ea_pre_1(u32 r); + void ea_post_1(u32 r); + void pcs_push(); + void pcs_pop(); + + u32 read_reg(u32 r); + void write_reg(u32 r, u32 v); + void write_mem_internal_1(u32 r, u32 v, bool bank); + void write_mem_external_1(u32 r, u32 v); + void write_mem_io_1(u32 r, u32 v); +}; +class mb86234_device : public mb86233_device +{ +public: + mb86234_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; -DECLARE_DEVICE_TYPE(MB86233, mb86233_cpu_device) +DECLARE_DEVICE_TYPE(MB86233, mb86233_device) +DECLARE_DEVICE_TYPE(MB86234, mb86234_device) #endif // MAME_CPU_MB86233_MB86233_H diff --git a/src/devices/cpu/mb86233/mb86233d.cpp b/src/devices/cpu/mb86233/mb86233d.cpp index 8433247dbc7..c49f01c3bba 100644 --- a/src/devices/cpu/mb86233/mb86233d.cpp +++ b/src/devices/cpu/mb86233/mb86233d.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Ernesto Corvi +// copyright-holders:Olivier Galibert #include "emu.h" #include "mb86233d.h" @@ -15,47 +15,54 @@ 2 <register file> 3 sio0 si1 pio pioa rpc - - - pad mod ear st mask tim cx dx + In the 86233/86234 the C, page, serial, parallel, timer registers + don't seem to exist. The register file is turned into i/o ports. + Of the second bank part '3', only "mask" is actually used. - Address encoding: + Address encoding (adx uses x0/b0, ady uses x1/b1): 0 0aaa aaaa $a 0 1aaa aaaa $a(xn) 1 0aaa aaaa $a(xn+) - 1 100b bbbb (xn+$b) - 1 101b bbbb (bxn+$b) - 1 110b bbbb [xn+$b] - 1 111b bbbb [bxn+$b] + 1 100b bbbb (bxn+$b) + 1 101b bbbb (xn+$b) + 1 110b bbbb [bxn+$b] + 1 111b bbbb [xn+$b] 3322 2222 2222 1111 1111 1100 0000 0000 1098 7654 3210 9876 5432 1098 7654 3210 - 0000 00aa aaao ooyy yyyy yyyx xxxx xxxx lab + 0000 00aa aaa0 00yy yyyy yyyx xxxx xxxx lab adx, ady (e) + 0000 00aa aaa0 11yy yyyy yyyx xxxx xxxx lab adx, ady + 0x200 + 0000 00aa aaa1 00yy yyyy yyyx xxxx xxxx lab adx + 0x200, ady - 0000 00aa aaa0 11yy yyyy yyyx xxxx xxxx lab adx (e), ady - 0000 00aa aaa1 00yy yyyy yyyx xxxx xxxx lab adx, ady (e) - - 0001 11aa aaa0 10yy yyyy yyyx xxxx xxxx mov adx, ady - 0001 11aa aaa0 11yy yyyy yyyx xxxx xxxx mov adx (e), ady - 0001 11aa aaa1 00yy yyyy yyyx xxxx xxxx mov adx, ady (e) + 0001 11aa aaa0 0?yy yyyy yyyx xxxx xxxx mov adx, ady (e) (the ? is not a + 0x200 select, cf. VR copro code) + 0001 11aa aaa0 10yy yyyy yyyx xxxx xxxx mov adx (e), ady + 0001 11aa aaa0 11yy yyyy yyyx xxxx xxxx mov adx, ady + 0x200 + 0001 11aa aaa1 00yy yyyy yyyx xxxx xxxx mov adx + 0x200, ady 0001 11aa aaa1 01yy yyyy yyyx xxxx xxxx mov adx (o), ady - 0001 11aa aaa1 1100 0rrr rrry yyyy yyyy mov r, ady (e) - 0001 11aa aaa1 1100 1rrr rrry yyyy yyyy mov r, ady - 0001 11aa aaa1 1101 1rrr rrrx xxxx xxxx mov adx (e), r - 0001 11aa aaa1 1110 0rrr rrrx xxxx xxxx mov adx, r + + 0001 11aa aaa1 1100 0rrr rrry yyyy yyyy mov r, ady + 0001 11aa aaa1 1100 1rrr rrry yyyy yyyy mov r, ady (e) + 0001 11aa aaa1 1101 0rrr rrry yyyy yyyy mov ady + 0x200, r + 0001 11aa aaa1 1101 1rrr rrry yyyy yyyy mov ady, r + 0001 11aa aaa1 1110 0rrr rrry yyyy yyyy mov ady (e), r 0001 11aa aaa1 1110 1rrr rrrx xxxx xxxx mov adx (o), r 0001 11aa aaa1 1111 0rrr rrr. ..ss ssss mov s, r + 0011 011. .... 101. vvvv vvvv vvvv vvvv stmh (bit0 = fp, bit 1-2 = rounding mode, rest unused) + 0011 10rr vvvv vvvv vvvv vvvv vvvv vvvv lipl/lia/lib/lid #v - 0011 11aa aaa. 000. rrrr rrrr rrrr rrrr clr0 <reglist> - 0011 11aa aaa. 001. ffff ffff ffff ffff clr1 flags - 0011 11aa aaa. 010. 0... .... nnnn nnnn rep #n - 0011 11aa aaa. 010. 1... .... ..11 0100 rep rpc - 0011 11aa aaa. 011. ffff ffff ffff ffff set flags + 0011 11.a aaaa 000. rrrr rrrr rrrr rrrr clr0 <reglist> + 0011 11.a aaaa 001. ffff ffff ffff ffff clr1 flags + 0011 11.a aaaa 010. 0... .... nnnn nnnn rep #n (0 = 0x100) + 0011 11.a aaaa 010. 1... .... ..11 0100 rep rpc + 0011 11.a aaaa 011. ffff ffff ffff ffff set flags - 010r rrrr .... .... vvvv vvvv vvvv vvvv ldi #v, b0/.../- (bank 0/1) (h/l is special and targets exponent/mantissa size 8/24) + 01rr rrrr vvvv vvvv vvvv vvvv vvvv vvvv ldi #v, r (actual v size varies 3-24 depending on register) 1i11 11.c cccc 0000 aaaa aaaa aaaa aaaa brif cond #a 1i11 11.c cccc 0010 .0.. ...x xxxx xxxx brul cond (adx) @@ -65,10 +72,17 @@ 1i11 11.c cccc 0110 .1.. .... ...r rrrr bsul cond r 1i11 11.c cccc 1010 .... .... .... .... rtif cond 1i11 11.c cccc 1100 .rrr rrrx xxxx xxxx ldif cond adx, r - 1011 11.c 0110 1110 .... .... .... .... iret + 1011 11.1 0110 1110 .... .... .... .... iret Top 3 bits = instruction group, except when it isn't. + + Conditions are 5 bits, but only a subset is known, see condition() + + Alu can theorically be on C or D registers, but since C doesn't + exist, we don't know how C access is encoded. The operation + itself is 5-bits for the "full" alu range. + */ @@ -109,24 +123,28 @@ std::string mb86233_disassembler::regs(u32 reg) return regnames[reg & 0x3f]; } -std::string mb86233_disassembler::memory(u32 reg, bool x1) +std::string mb86233_disassembler::memory(u32 reg, bool x1, bool bank) { std::ostringstream stream; switch(reg & 0x180) { case 0x000: - if((reg & 0x7f) < 10) - util::stream_format(stream, "$%d", reg & 0x7f ); + if(bank) + util::stream_format(stream, "$0x%x", 0x200 | (reg & 0x7f)); + else if((reg & 0x7f) < 10) + util::stream_format(stream, "$%d", reg & 0x7f); else - util::stream_format(stream, "$0x%x", reg & 0x7f ); + util::stream_format(stream, "$0x%x", reg & 0x7f); break; case 0x080: - if(reg & 0x7f) { - if((reg & 0x7f) < 10) - util::stream_format(stream, "$%d", reg & 0x7f ); + if(bank || (reg & 0x7f)) { + if(bank) + util::stream_format(stream, "$0x%x", 0x200 | (reg & 0x7f)); + else if((reg & 0x7f) < 10) + util::stream_format(stream, "$%d", reg & 0x7f); else - util::stream_format(stream, "$0x%x", reg & 0x7f ); + util::stream_format(stream, "$0x%x", reg & 0x7f); } stream << '('; @@ -139,8 +157,14 @@ std::string mb86233_disassembler::memory(u32 reg, bool x1) break; case 0x100: - if(reg & 0x7f) - util::stream_format(stream, "$0x%x", reg & 0x7f ); + if(bank || (reg & 0x7f)) { + if(bank) + util::stream_format(stream, "$0x%x", 0x200 | (reg & 0x7f)); + else if((reg & 0x7f) < 10) + util::stream_format(stream, "$%d", reg & 0x7f); + else + util::stream_format(stream, "$0x%x", reg & 0x7f); + } stream << '('; @@ -152,7 +176,7 @@ std::string mb86233_disassembler::memory(u32 reg, bool x1) break; case 0x180: - stream << (reg & 0x40 ? "$[" : "$("); + stream << (reg & 0x40 ? "[" : "("); if(x1) { if(!(reg & 0x20)) util::stream_format(stream, "bx1"); @@ -179,6 +203,10 @@ std::string mb86233_disassembler::memory(u32 reg, bool x1) } stream << (reg & 0x40 ? ']' : ')'); + + if(bank) + stream << "+0x200"; + break; } @@ -204,13 +232,14 @@ std::string mb86233_disassembler::alu0_func(u32 alu) case 0x0b: util::stream_format(stream, "fabd"); break; case 0x0c: util::stream_format(stream, "fsmd"); break; case 0x0d: util::stream_format(stream, "fspd"); break; - case 0x0e: util::stream_format(stream, "cifd"); break; - case 0x0f: util::stream_format(stream, "cfid"); break; + case 0x0e: util::stream_format(stream, "cxfd"); break; + case 0x0f: util::stream_format(stream, "cfxd"); break; case 0x10: util::stream_format(stream, "fdvd"); break; case 0x11: util::stream_format(stream, "fned"); break; // 12 case 0x13: util::stream_format(stream, "d=b+a"); break; case 0x14: util::stream_format(stream, "d=b-a"); break; + // 15 case 0x16: util::stream_format(stream, "lsrd"); break; case 0x17: util::stream_format(stream, "lsld"); break; case 0x18: util::stream_format(stream, "asrd"); break; @@ -243,19 +272,19 @@ offs_t mb86233_disassembler::disassemble(std::ostream &stream, offs_t pc, const switch(op) { case 0: - util::stream_format(stream, "lab %s, %s (io)", memory(r1, false), memory(r2, true)); + util::stream_format(stream, "lab %s, %s (e)", memory(r1, false, false), memory(r2, true, false)); break; case 3: - util::stream_format(stream, "lab %s, %s", memory(r1, false), memory(r2, true)); + util::stream_format(stream, "lab %s, %s", memory(r1, false, false), memory(r2, true, true)); break; case 4: - util::stream_format(stream, "lab %s, %s (e)", memory(r1, false), memory(r2, true)); + util::stream_format(stream, "lab %s, %s", memory(r1, false, true), memory(r2, true, false)); break; default: - util::stream_format(stream, "lab {%d} %s, %s", op, memory(r1, false), memory(r2, true)); + util::stream_format(stream, "lab {%d} %s, %s", op, memory(r1, false, false), memory(r2, true, false)); break; } break; @@ -278,53 +307,53 @@ offs_t mb86233_disassembler::disassemble(std::ostream &stream, offs_t pc, const switch(op) { case 0: - util::stream_format(stream, "mov %s, %s", memory(r1, false), memory(r2, true)); + util::stream_format(stream, "mov {0} %s, %s (e)", memory(r1, false, false), memory(r2, true, false)); break; case 1: - util::stream_format(stream, "mov %s, %s (io)", memory(r1, false), memory(r2, true)); + util::stream_format(stream, "mov {1} %s, %s (e)", memory(r1, false, false), memory(r2, true, false)); break; case 2: - util::stream_format(stream, "mov %s (io), %s", memory(r1, false), memory(r2, true)); + util::stream_format(stream, "mov %s (e), %s", memory(r1, false, false), memory(r2, true, false)); break; case 3: - util::stream_format(stream, "mov %s, %s (e)", memory(r1, false), memory(r2, true)); + util::stream_format(stream, "mov %s, %s", memory(r1, false, false), memory(r2, true, true)); break; case 4: - util::stream_format(stream, "mov %s (e), %s", memory(r1, false), memory(r2, true)); + util::stream_format(stream, "mov %s, %s", memory(r1, false, true), memory(r2, true, false)); break; case 5: - util::stream_format(stream, "mov %s (o), %s", memory(r1, false), memory(r2, true)); + util::stream_format(stream, "mov %s (o), %s", memory(r1, false, false), memory(r2, true, false)); break; case 7: { switch(r2 >> 6) { case 0: - util::stream_format(stream, "mov %s, %s", regs(r2 & 0x3f), memory(r1, true)); + util::stream_format(stream, "mov %s, %s", regs(r2 & 0x3f), memory(r1, true, false)); break; case 1: - util::stream_format(stream, "mov %s, %s (io)", regs(r2 & 0x3f), memory(r1, true)); + util::stream_format(stream, "mov %s, %s (e)", regs(r2 & 0x3f), memory(r1, true, false)); break; case 2: - util::stream_format(stream, "mov %s (e), %s", memory(r1, false), regs(r2 & 0x3f)); + util::stream_format(stream, "mov %s, %s", memory(r1, true, true), regs(r2 & 0x3f)); break; case 3: - util::stream_format(stream, "mov %s, %s", memory(r1, false), regs(r2 & 0x3f)); + util::stream_format(stream, "mov %s, %s", memory(r1, true, false), regs(r2 & 0x3f)); break; case 4: - util::stream_format(stream, "mov %s (io), %s", memory(r1, false), regs(r2 & 0x3f)); + util::stream_format(stream, "mov %s (e), %s", memory(r1, true, false), regs(r2 & 0x3f)); break; case 5: - util::stream_format(stream, "mov %s (o), %s", memory(r1, false), regs(r2 & 0x3f)); + util::stream_format(stream, "mov %s (o), %s", memory(r1, false, false), regs(r2 & 0x3f)); break; case 6: @@ -335,13 +364,33 @@ offs_t mb86233_disassembler::disassemble(std::ostream &stream, offs_t pc, const break; default: - util::stream_format(stream, "mov {r2 %d} %s, %s", r2 >> 6, memory(r1, true), regs(r2 & 0x3f)); + util::stream_format(stream, "mov {r2 %d} %s, %s", r2 >> 6, memory(r1, false, false), regs(r2 & 0x3f)); break; } break; } default: - util::stream_format(stream, "mov {%d} %s, %s", op, memory(r1, false), memory(r2, true)); + util::stream_format(stream, "mov {%d} %s, %s", op, memory(r1, false, false), memory(r2, true, false)); + break; + } + break; + } + + case 0x0d: { // stm/clm + u32 sub2 = (opcode >> 17) & 7; + + switch(sub2) { + case 5: { + util::stream_format(stream, "stmh"); + if(opcode & 0x0001) + util::stream_format(stream, " fp"); + static const char *const round_mode[4] = { "rn", "rp", "rm", "rz" }; + util::stream_format(stream, " %s", round_mode[(opcode >> 1) & 3]); + break; + } + + default: + util::stream_format(stream, "unk %02x.%x", opcode >> 26, sub2); break; } break; @@ -354,7 +403,7 @@ offs_t mb86233_disassembler::disassemble(std::ostream &stream, offs_t pc, const } case 0x0f: { // rep/clr0/clr1/set - u32 alu = (opcode >> 21) & 0x1f; + u32 alu = (opcode >> 20) & 0x1f; u32 sub2 = (opcode >> 17) & 7; if(alu) @@ -405,6 +454,7 @@ offs_t mb86233_disassembler::disassemble(std::ostream &stream, offs_t pc, const } case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: util::stream_format(stream, "ldi #0x%x, %s", opcode & 0xffffff, regnames[(opcode >> 24) & 0x3f]); break; break; @@ -424,7 +474,7 @@ offs_t mb86233_disassembler::disassemble(std::ostream &stream, offs_t pc, const if(opcode & 0x4000) util::stream_format(stream, "%s", regs(opcode & 0x1f)); else - util::stream_format(stream, "(%s)", memory(opcode & 0x1ff, false)); + util::stream_format(stream, "(%s)", memory(opcode & 0x1ff, false, false)); break; case 2: @@ -436,7 +486,7 @@ offs_t mb86233_disassembler::disassemble(std::ostream &stream, offs_t pc, const if(opcode & 0x4000) util::stream_format(stream, "%s", regs(opcode & 0x1f)); else - util::stream_format(stream, "(%s)", memory(opcode & 0x1ff, false)); + util::stream_format(stream, "(%s)", memory(opcode & 0x1ff, false, false)); break; case 5: @@ -444,7 +494,7 @@ offs_t mb86233_disassembler::disassemble(std::ostream &stream, offs_t pc, const break; case 6: - util::stream_format(stream, "ldif %s %s, %s", condition(cond, invert), memory(data & 0x1ff, false), regs((data >> 9) & 0x3f)); + util::stream_format(stream, "ldif %s %s, %s", condition(cond, invert), memory(data & 0x1ff, false, false), regs((data >> 9) & 0x3f)); break; case 7: diff --git a/src/devices/cpu/mb86233/mb86233d.h b/src/devices/cpu/mb86233/mb86233d.h index 50a48a6f0a9..bd475e061b6 100644 --- a/src/devices/cpu/mb86233/mb86233d.h +++ b/src/devices/cpu/mb86233/mb86233d.h @@ -19,7 +19,7 @@ private: static const char *const regnames[0x40]; static std::string condition(unsigned int cond, bool invert); static std::string regs(u32 reg); - static std::string memory(u32 reg, bool x1); + static std::string memory(u32 reg, bool x1, bool bank); static std::string alu0_func(u32 alu); }; diff --git a/src/devices/cpu/mb86235/mb86235.cpp b/src/devices/cpu/mb86235/mb86235.cpp index 0987b1e1b20..670571e6fce 100644 --- a/src/devices/cpu/mb86235/mb86235.cpp +++ b/src/devices/cpu/mb86235/mb86235.cpp @@ -263,6 +263,9 @@ mb86235_device::mb86235_device(const machine_config &mconfig, const char *tag, d , m_program_config("program", ENDIANNESS_LITTLE, 64, 32, -3) , m_dataa_config("data_a", ENDIANNESS_LITTLE, 32, 24, -2, address_map_constructor(FUNC(mb86235_device::internal_abus), this)) , m_datab_config("data_b", ENDIANNESS_LITTLE, 32, 10, -2, address_map_constructor(FUNC(mb86235_device::internal_bbus), this)) + , m_fifoin(*this, finder_base::DUMMY_TAG) + , m_fifoout0(*this, finder_base::DUMMY_TAG) + , m_fifoout1(*this, finder_base::DUMMY_TAG) , m_cache(CACHE_SIZE + sizeof(mb86235_internal_state)) , m_drcuml(nullptr) , m_drcfe(nullptr) @@ -292,55 +295,3 @@ std::unique_ptr<util::disasm_interface> mb86235_device::create_disassembler() { return std::make_unique<mb86235_disassembler>(); } - - -void mb86235_device::fifoin_w(uint32_t data) -{ - if (m_core->fifoin.num >= FIFOIN_SIZE) - { - fatalerror("fifoin_w: pushing to full fifo"); - } - - //printf("FIFOIN push %08X\n", data); - - m_core->fifoin.data[m_core->fifoin.wpos] = data; - - m_core->fifoin.wpos++; - m_core->fifoin.wpos &= FIFOIN_SIZE-1; - m_core->fifoin.num++; -} - -bool mb86235_device::is_fifoin_empty() -{ - return m_core->fifoin.num == 0; -} - -bool mb86235_device::is_fifoin_full() -{ - return m_core->fifoin.num >= FIFOIN_SIZE; -} - -uint32_t mb86235_device::fifoout0_r() -{ - if (m_core->fifoout0.num == 0) - { - fatalerror("fifoout0_r: reading from empty fifo"); - } - - uint32_t data = m_core->fifoout0.data[m_core->fifoout0.rpos]; - - m_core->fifoout0.rpos++; - m_core->fifoout0.rpos &= FIFOOUT0_SIZE - 1; - m_core->fifoout0.num--; - return data; -} - -bool mb86235_device::is_fifoout0_full() -{ - return m_core->fifoout0.num >= FIFOOUT0_SIZE; -} - -bool mb86235_device::is_fifoout0_empty() -{ - return m_core->fifoout0.num == 0; -} diff --git a/src/devices/cpu/mb86235/mb86235.h b/src/devices/cpu/mb86235/mb86235.h index 73ee7fcb07f..dc583dd9b84 100644 --- a/src/devices/cpu/mb86235/mb86235.h +++ b/src/devices/cpu/mb86235/mb86235.h @@ -13,10 +13,21 @@ #include "cpu/drcfe.h" #include "cpu/drcuml.h" +#include "machine/gen_fifo.h" + +#define MCFG_MB86235_FIFOIN(tag) \ + downcast<mb86235_device &>(*device).set_fifoin_tag(tag); + +#define MCFG_MB86235_FIFOOUT0(tag) \ + downcast<mb86235_device &>(*device).set_fifoout0_tag(tag); + +#define MCFG_MB86235_FIFOOUT1(tag) \ + downcast<mb86235_device &>(*device).set_fifoout1_tag(tag); class mb86235_frontend; + class mb86235_device : public cpu_device { friend class mb86235_frontend; @@ -25,6 +36,10 @@ public: // construction/destruction mb86235_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t clock); + void set_fifoin_tag(const char *tag) { m_fifoin.set_tag(tag); } + void set_fifoout0_tag(const char *tag) { m_fifoout0.set_tag(tag); } + void set_fifoout1_tag(const char *tag) { m_fifoout1.set_tag(tag); } + void unimplemented_op(); void unimplemented_alu(); void unimplemented_control(); @@ -33,13 +48,6 @@ public: void pcs_overflow(); void pcs_underflow(); - void fifoin_w(uint32_t data); - bool is_fifoin_full(); - bool is_fifoin_empty(); - uint32_t fifoout0_r(); - bool is_fifoout0_empty(); - bool is_fifoout0_full(); - enum { MB86235_PC = 1, @@ -53,10 +61,6 @@ public: MB86235_ST }; - static constexpr int FIFOIN_SIZE = 16; - static constexpr int FIFOOUT0_SIZE = 16; - static constexpr int FIFOOUT1_SIZE = 16; - void internal_abus(address_map &map); void internal_bbus(address_map &map); protected: @@ -102,14 +106,6 @@ private: uint32_t md; }; - struct fifo - { - int rpos; - int wpos; - int num; - uint32_t data[16]; - }; - struct fifo_state { uint32_t pc; @@ -164,9 +160,6 @@ private: float fp0; bool delay_slot; - fifo fifoin; - fifo fifoout0; - fifo fifoout1; fifo_state cur_fifo_state; }; @@ -177,18 +170,16 @@ private: uml::code_handle *m_entry; /* entry point */ uml::code_handle *m_nocode; /* nocode exception handler */ uml::code_handle *m_out_of_cycles; /* out of cycles exception handler */ - uml::code_handle *m_clear_fifo_in; - uml::code_handle *m_clear_fifo_out0; - uml::code_handle *m_clear_fifo_out1; - uml::code_handle *m_read_fifo_in; - uml::code_handle *m_write_fifo_out0; - uml::code_handle *m_write_fifo_out1; uml::code_handle *m_read_abus; uml::code_handle *m_write_abus; address_space_config m_program_config; address_space_config m_dataa_config; address_space_config m_datab_config; + optional_device<generic_fifo_u32_device> m_fifoin; + optional_device<generic_fifo_u32_device> m_fifoout0; + optional_device<generic_fifo_u32_device> m_fifoout1; + drc_cache m_cache; std::unique_ptr<drcuml_state> m_drcuml; std::unique_ptr<mb86235_frontend> m_drcfe; @@ -216,7 +207,6 @@ private: void static_generate_entry_point(); void static_generate_nocode_handler(); void static_generate_out_of_cycles(); - void static_generate_fifo(); void static_generate_memory_accessors(); void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); void generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception); @@ -244,6 +234,19 @@ private: bool aluop_has_result(int aluop); bool check_previous_op_stall(); + // UML is sad... + u32 m_cur_value; + + static void clear_fifoin(void *param); + static void clear_fifoout0(void *param); + static void clear_fifoout1(void *param); + static void read_fifoin(void *param); + static void write_fifoout0(void *param); + static void write_fifoout1(void *param); + static void empty_fifoin(void *param); + static void full_fifoout0(void *param); + static void full_fifoout1(void *param); + // interpreter void execute_op(uint32_t h, uint32_t l); void do_alu1(uint32_t h, uint32_t l); diff --git a/src/devices/cpu/mb86235/mb86235drc.cpp b/src/devices/cpu/mb86235/mb86235drc.cpp index d1682d0e024..12e0ab60650 100644 --- a/src/devices/cpu/mb86235/mb86235drc.cpp +++ b/src/devices/cpu/mb86235/mb86235drc.cpp @@ -78,17 +78,6 @@ #define MU_CALC_REQUIRED ((desc->regreq[1] & 0x1000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define MD_CALC_REQUIRED ((desc->regreq[1] & 0x2000) || desc->flags & OPFLAG_IN_DELAY_SLOT) -#define FIFOIN_RPOS uml::mem(&m_core->fifoin.rpos) -#define FIFOIN_WPOS uml::mem(&m_core->fifoin.wpos) -#define FIFOIN_NUM uml::mem(&m_core->fifoin.num) -#define FIFOOUT0_RPOS uml::mem(&m_core->fifoout0.rpos) -#define FIFOOUT0_WPOS uml::mem(&m_core->fifoout0.wpos) -#define FIFOOUT0_NUM uml::mem(&m_core->fifoout0.num) -#define FIFOOUT1_RPOS uml::mem(&m_core->fifoout1.rpos) -#define FIFOOUT1_WPOS uml::mem(&m_core->fifoout1.wpos) -#define FIFOOUT1_NUM uml::mem(&m_core->fifoout1.num) - - inline void mb86235_device::alloc_handle(uml::code_handle *&handleptr, const char *name) { if (!handleptr) @@ -390,89 +379,58 @@ void mb86235_device::static_generate_out_of_cycles() block.end(); } -void mb86235_device::static_generate_fifo() +void mb86235_device::clear_fifoin(void *param) { - { - // clear fifo in - drcuml_block &block(m_drcuml->begin_block(20)); - - alloc_handle(m_clear_fifo_in, "clear_fifo_in"); - UML_HANDLE(block, *m_clear_fifo_in); - UML_MOV(block, FIFOIN_NUM, 0); - UML_MOV(block, FIFOIN_RPOS, 0); - UML_MOV(block, FIFOIN_WPOS, 0); - UML_RET(block); + mb86235_device *cpu = (mb86235_device *)param; + cpu->m_fifoin->clear(); +} - block.end(); - } - { - // clear fifo out0 - drcuml_block &block(m_drcuml->begin_block(20)); - - alloc_handle(m_clear_fifo_out0, "clear_fifo_out0"); - UML_HANDLE(block, *m_clear_fifo_out0); - UML_MOV(block, FIFOOUT0_NUM, 0); - UML_MOV(block, FIFOOUT0_RPOS, 0); - UML_MOV(block, FIFOOUT0_WPOS, 0); - UML_RET(block); +void mb86235_device::clear_fifoout0(void *param) +{ + mb86235_device *cpu = (mb86235_device *)param; + cpu->m_fifoout0->clear(); +} - block.end(); - } - { - // clear fifo out1 - drcuml_block &block(m_drcuml->begin_block(20)); - - alloc_handle(m_clear_fifo_out1, "clear_fifo_out1"); - UML_HANDLE(block, *m_clear_fifo_out1); - UML_MOV(block, FIFOOUT1_NUM, 0); - UML_MOV(block, FIFOOUT1_RPOS, 0); - UML_MOV(block, FIFOOUT1_WPOS, 0); - UML_RET(block); +void mb86235_device::clear_fifoout1(void *param) +{ + mb86235_device *cpu = (mb86235_device *)param; + cpu->m_fifoout1->clear(); +} - block.end(); - } - { - // read fifo in - // I0 = return value - drcuml_block &block(m_drcuml->begin_block(32)); - alloc_handle(m_read_fifo_in, "read_fifo_in"); - UML_HANDLE(block, *m_read_fifo_in); - UML_MOV(block, I1, FIFOIN_RPOS); - UML_LOAD(block, I0, m_core->fifoin.data, I1, SIZE_QWORD, SCALE_x8); - UML_ADD(block, I1, I1, 1); - UML_AND(block, I1, I1, FIFOIN_SIZE-1); - UML_MOV(block, FIFOIN_RPOS, I1); - UML_SUB(block, FIFOIN_NUM, FIFOIN_NUM, 1); - UML_RET(block); +void mb86235_device::read_fifoin(void *param) +{ + mb86235_device *cpu = (mb86235_device *)param; + cpu->m_cur_value = cpu->m_fifoin->pop(); +} - block.end(); - } - { - // write fifo out0 - // I0 = input value - drcuml_block &block(m_drcuml->begin_block(32)); - alloc_handle(m_write_fifo_out0, "write_fifo_out0"); - UML_HANDLE(block, *m_write_fifo_out0); - UML_MOV(block, I1, FIFOOUT0_WPOS); - UML_STORE(block, m_core->fifoout0.data, I1, I0, SIZE_QWORD, SCALE_x8); - UML_ADD(block, I1, I1, 1); - UML_AND(block, I1, I1, FIFOOUT0_SIZE - 1); - UML_MOV(block, FIFOOUT0_WPOS, I1); - UML_ADD(block, FIFOOUT0_NUM, FIFOOUT0_NUM, 1); - UML_RET(block); +void mb86235_device::write_fifoout0(void *param) +{ + mb86235_device *cpu = (mb86235_device *)param; + cpu->m_fifoout0->push(u32(cpu->m_cur_value)); +} - block.end(); - } - { - // write fifo out1 - drcuml_block &block(m_drcuml->begin_block(32)); - alloc_handle(m_write_fifo_out1, "write_fifo_out1"); - UML_HANDLE(block, *m_write_fifo_out1); - // TODO - UML_RET(block); +void mb86235_device::write_fifoout1(void *param) +{ + mb86235_device *cpu = (mb86235_device *)param; + cpu->m_fifoout1->push(u32(cpu->m_cur_value)); +} - block.end(); - } +void mb86235_device::empty_fifoin(void *param) +{ + mb86235_device *cpu = (mb86235_device *)param; + cpu->m_cur_value = cpu->m_fifoin->is_empty(); +} + +void mb86235_device::full_fifoout0(void *param) +{ + mb86235_device *cpu = (mb86235_device *)param; + cpu->m_cur_value = cpu->m_fifoout0->is_full(); +} + +void mb86235_device::full_fifoout1(void *param) +{ + mb86235_device *cpu = (mb86235_device *)param; + cpu->m_cur_value = cpu->m_fifoout1->is_full(); } void mb86235_device::static_generate_memory_accessors() @@ -542,9 +500,6 @@ void mb86235_device::flush_cache() static_generate_nocode_handler(); static_generate_out_of_cycles(); - // generate utility functions - static_generate_fifo(); - // generate exception handlers // generate memory accessors @@ -690,8 +645,13 @@ void mb86235_device::generate_reg_read(drcuml_block &block, compiler_state &comp break; case 0x31: // FI - UML_CALLH(block, *m_read_fifo_in); - UML_MOV(block, dst, I0); + if (m_fifoin) + { + UML_CALLC(block, read_fifoin, this); + UML_MOV(block, dst, mem(&m_cur_value)); + } + else + UML_MOV(block, dst, 0); break; default: @@ -747,8 +707,11 @@ void mb86235_device::generate_reg_write(drcuml_block &block, compiler_state &com break; case 0x32: // FO0 - UML_MOV(block, I0, src); - UML_CALLH(block, *m_write_fifo_out0); + if (m_fifoout0) + { + UML_MOV(block, mem(&m_cur_value), src); + UML_CALLC(block, write_fifoout0, this); + } break; case 0x34: // PDR @@ -850,11 +813,12 @@ bool mb86235_device::generate_opcode(drcuml_block &block, compiler_state &compil } // insert FIFO IN check if needed - if (fifoin_check) + if (fifoin_check && m_fifoin) { uml::code_label const not_empty = compiler.labelnum++; - UML_CMP(block, FIFOIN_NUM, 0); - UML_JMPc(block, COND_G, not_empty); + UML_CALLC(block, empty_fifoin, this); + UML_CMP(block, mem(&m_cur_value), 1); + UML_JMPc(block, COND_NE, not_empty); UML_MOV(block, mem(&m_core->icount), 0); UML_EXH(block, *m_out_of_cycles, desc->pc); @@ -863,11 +827,12 @@ bool mb86235_device::generate_opcode(drcuml_block &block, compiler_state &compil } // insert FIFO OUT0 check if needed - if (fifoout0_check) + if (fifoout0_check && m_fifoout0) { uml::code_label const not_full = compiler.labelnum++; - UML_CMP(block, FIFOOUT0_NUM, FIFOOUT0_SIZE - 1); - UML_JMPc(block, COND_L, not_full); + UML_CALLC(block, full_fifoout0, this); + UML_CMP(block, mem(&m_cur_value), 1); + UML_JMPc(block, COND_NE, not_full); UML_MOV(block, mem(&m_core->icount), 0); UML_EXH(block, *m_out_of_cycles, desc->pc); @@ -876,11 +841,12 @@ bool mb86235_device::generate_opcode(drcuml_block &block, compiler_state &compil } // insert FIFO OUT1 check if needed - if (fifoout1_check) + if (fifoout1_check && m_fifoout1) { uml::code_label const not_full = compiler.labelnum++; - UML_CMP(block, FIFOOUT1_NUM, FIFOOUT1_SIZE - 1); - UML_JMPc(block, COND_L, not_full); + UML_CALLC(block, full_fifoout1, this); + UML_CMP(block, mem(&m_cur_value), 1); + UML_JMPc(block, COND_NE, not_full); UML_MOV(block, mem(&m_core->icount), 0); UML_EXH(block, *m_out_of_cycles, desc->pc); @@ -1573,17 +1539,25 @@ void mb86235_device::generate_control(drcuml_block &block, compiler_state &compi case 0x03: // if (ef1 == 1) // CLRFI - UML_CALLH(block, *m_clear_fifo_in); + { + if (m_fifoin) + UML_CALLC(block, clear_fifoin, this); + } else if (ef1 == 2) // CLRFO { - UML_CALLH(block, *m_clear_fifo_out0); - UML_CALLH(block, *m_clear_fifo_out1); + if (m_fifoout0) + UML_CALLC(block, clear_fifoout0, this); + if (m_fifoout1) + UML_CALLC(block, clear_fifoout1, this); } else if (ef1 == 3) // CLRF { - UML_CALLH(block, *m_clear_fifo_in); - UML_CALLH(block, *m_clear_fifo_out0); - UML_CALLH(block, *m_clear_fifo_out1); + if (m_fifoin) + UML_CALLC(block, clear_fifoin, this); + if (m_fifoout0) + UML_CALLC(block, clear_fifoout0, this); + if (m_fifoout1) + UML_CALLC(block, clear_fifoout1, this); } break; diff --git a/src/devices/cpu/mb86235/mb86235ops.cpp b/src/devices/cpu/mb86235/mb86235ops.cpp index 024437c506a..fc8d667fc35 100644 --- a/src/devices/cpu/mb86235/mb86235ops.cpp +++ b/src/devices/cpu/mb86235/mb86235ops.cpp @@ -752,7 +752,7 @@ inline uint32_t mb86235_device::get_transfer_reg(uint8_t which) case 1: // FI { FCLR(IFE); - if(is_fifoin_empty() == true) + if(m_fifoin->is_empty()) { FSET(IFE); m_core->cur_fifo_state.has_stalled = true; @@ -765,13 +765,7 @@ inline uint32_t mb86235_device::get_transfer_reg(uint8_t which) } m_core->cur_fifo_state.has_stalled = false; - uint32_t res = (uint32_t)m_core->fifoin.data[m_core->fifoin.rpos]; - - m_core->fifoin.rpos++; - m_core->fifoin.rpos &= FIFOIN_SIZE-1; - m_core->fifoin.num--; - - return res; + return m_fifoin->pop(); } } } @@ -827,24 +821,23 @@ inline void mb86235_device::set_transfer_reg(uint8_t which, uint32_t value) break; case 2: // FO0 FCLR(OFF); - if(is_fifoout0_full() == true) + if(m_fifoout0) { - FSET(OFF); - m_core->cur_fifo_state.has_stalled = true; - if((m_core->st & RP) == 0) - m_core->cur_fifo_state.pc = m_core->ppc; - - //else - // fatalerror("check me (writes)"); - return; - } - - m_core->cur_fifo_state.has_stalled = false; - m_core->fifoout0.data[m_core->fifoin.wpos] = value; - - m_core->fifoout0.wpos++; - m_core->fifoout0.wpos &= FIFOIN_SIZE-1; - m_core->fifoout0.num++; + if(m_fifoout0->is_full()) + { + FSET(OFF); + m_core->cur_fifo_state.has_stalled = true; + if((m_core->st & RP) == 0) + m_core->cur_fifo_state.pc = m_core->ppc; + + //else + // fatalerror("check me (writes)"); + return; + } + + m_core->cur_fifo_state.has_stalled = false; + m_fifoout0->push(u32(value)); + } break; case 4: m_core->pdr = value; break; case 5: m_core->ddr = value; break; @@ -1193,21 +1186,18 @@ void mb86235_device::do_control(uint32_t h, uint32_t l) case 0x03: // CLRF if(ef1 & 1) // clear fifo in (CLRFI) { - m_core->fifoin.wpos = 0; - m_core->fifoin.rpos = 0; - m_core->fifoin.num = 0; + if(m_fifoin) + m_fifoin->clear(); FSET(IFE); FCLR(IFF); m_core->cur_fifo_state.has_stalled = false; } if(ef1 & 2) // clear fifo0/1 out (CLRFO) { - m_core->fifoout0.wpos = 0; - m_core->fifoout0.rpos = 0; - m_core->fifoout0.num = 0; - m_core->fifoout1.wpos = 0; - m_core->fifoout1.rpos = 0; - m_core->fifoout1.num = 0; + if(m_fifoout0) + m_fifoout0->clear(); + if(m_fifoout1) + m_fifoout1->clear(); FSET(OFE); FCLR(OFF); m_core->cur_fifo_state.has_stalled = false; |