diff options
Diffstat (limited to 'src/devices/cpu/esrip/esrip.c')
-rw-r--r-- | src/devices/cpu/esrip/esrip.c | 1985 |
1 files changed, 1985 insertions, 0 deletions
diff --git a/src/devices/cpu/esrip/esrip.c b/src/devices/cpu/esrip/esrip.c new file mode 100644 index 00000000000..fa7ab139b08 --- /dev/null +++ b/src/devices/cpu/esrip/esrip.c @@ -0,0 +1,1985 @@ +// license:BSD-3-Clause +// copyright-holders:Philip Bennett +/*************************************************************************** + + esrip.c + + Implementation of the Entertainment Sciences + AM29116-based Real Time Image Processor + +***************************************************************************/ + +#include "emu.h" +#include "debugger.h" +#include "esrip.h" + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define IPT_RAM_SIZE (8192 * sizeof(UINT16)) + + +/*************************************************************************** + MACROS +***************************************************************************/ + +#define RIP_PC (m_pc | ((m_status_out & 1) << 8)) +#define _BIT(x, n) ((x) & (1 << (n))) +#define RISING_EDGE(old_val, new_val, bit) (!(old_val & (1 << bit)) && (new_val & (1 << bit))) + +#define UNHANDLED do {printf("%s:UNHANDLED (%x)\n", __FUNCTION__, inst); assert(0);} while (0) +#define INVALID do {printf("%s:INVALID (%x)\n", __FUNCTION__, inst); assert(0);} while (0) + +#define RAM_ADDR (inst & 0x1f) +#define MODE (inst & 0x8000) +#define WORD_MODE (inst & 0x8000) +#define BYTE_MODE (!WORD_MODE) +#define N ((inst >> 9) & 0xf) +#define OPCODE ((inst >> 5) & 0xf) +#define SRC ((inst >> 9) & 0xf) +#define DST (inst & 0x1f) // TEST + +#define BW_WORD (1 << 15) +#define BW_BYTE (0 << 15) + +#define FLAG_3 (1 << 7) +#define FLAG_2 (1 << 6) +#define FLAG_1 (1 << 5) +#define L_FLAG (1 << 4) +#define V_FLAG (1 << 3) +#define N_FLAG (1 << 2) +#define C_FLAG (1 << 1) +#define Z_FLAG (1 << 0) + +#define CLEAR_FLAGS(a) (m_new_status &= ~(a)) +#define SET_FLAGS(a) (m_new_status |= (a)) + + +/*************************************************************************** + STRUCTURES & TYPEDEFS +***************************************************************************/ + +/*************************************************************************** + PUBLIC FUNCTIONS +***************************************************************************/ + +UINT8 esrip_device::get_rip_status() +{ + return m_status_out; +} + + +/*************************************************************************** + INITIALIZATION AND SHUTDOWN +***************************************************************************/ + +enum ops +{ + ROTR1, TOR1, ROTR2, ROTC, ROTM, BOR2, CRCF, CRCR, + SVSTR, PRT, SOR, TOR2, SHFTR, TEST, NOP, SETST, RSTST, + ROTNR, BONR, BOR1, SONR, SHFTNR, PRTNR, TONR +}; + +void esrip_device::make_ops() +{ + int inst; + + for (inst = 0; inst < 65536; ++inst) + { + int quad = (inst >> 13) & 3; + + if (quad == 0) + { + if (((inst >> 5) & 0xc) == 0xc) + m_optable[inst] = ROTR1; + else + m_optable[inst] = TOR1; + } + else if (quad == 1) + { + if (OPCODE < 2) + m_optable[inst] = ROTR2; + else if (OPCODE < 6) + m_optable[inst] = ROTC; + else + m_optable[inst] = ROTM; + } + else if (quad == 2) + { + if (OPCODE > 11) + m_optable[inst] = BOR2; + else + { + int tmp = (inst >> 5) & 0xff; + + if (tmp == 0x63) + m_optable[inst] = CRCF; + else if (tmp == 0x69) + m_optable[inst] = CRCR; + else if (tmp == 0x7a) + m_optable[inst] = SVSTR; + else + { + if ((SRC > 7) && (SRC < 12)) + m_optable[inst] = PRT; + else if (SRC > 11) + m_optable[inst] = SOR; + else if (SRC < 6) + m_optable[inst] = TOR2; + else + m_optable[inst] = SHFTR; + } + } + } + else + { + if (inst == 0x7140) + m_optable[inst] = NOP; + else + { + int x = (inst & 0xffe0); + if (x == 0x7340) + m_optable[inst] = TEST; + else if (x == 0x7740) + m_optable[inst] = SETST; + else if (x == 0x7540) + m_optable[inst] = RSTST; + else + { + int op = OPCODE; + if (op == 0xc) + { + if ((inst & 0x18) == 0x18) + m_optable[inst] = ROTNR; + else + m_optable[inst] = BONR; + } + else if ((op & 0xc) == 0xc) + m_optable[inst] = BOR1; + else + { + int src = SRC; + + if ((src & 0xc) == 0xc) + m_optable[inst] = SONR; + else if ((src & 0x6) == 0x6) + m_optable[inst] = SHFTNR; + else if (src & 0x8) + m_optable[inst] = PRTNR; + else + m_optable[inst] = TONR; + } + } + } + } + } +} + +void esrip_device::device_start() +{ + /* Register configuration structure callbacks */ + m_fdt_r.resolve_safe(0); + m_fdt_w.resolve_safe(); + m_lbrm = (UINT8*)machine().root_device().memregion(m_lbrm_prom)->base(); + m_status_in.resolve_safe(0); + m_draw.bind_relative_to(*owner()); + + /* Allocate image pointer table RAM */ + m_ipt_ram.resize(IPT_RAM_SIZE/2); + + m_program = &space(AS_PROGRAM); + m_direct = &m_program->direct(); + + // register our state for the debugger + std::string tempstr; + state_add(STATE_GENPC, "GENPC", m_rip_pc).noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_status).callimport().callexport().formatstr("%8s").noshow(); + state_add(ESRIP_PC, "PC:", m_rip_pc).mask(0xffff); + state_add(ESRIP_ACC, "ACC:", m_acc).mask(0xffff); + state_add(ESRIP_DLATCH, "DLATCH:", m_d_latch).mask(0xff); + state_add(ESRIP_ILATCH, "ILATCH:", m_i_latch).mask(0xffff); + state_add(ESRIP_RAM00, "RAM[00]:", m_ram[0x00]).mask(0xffff); + state_add(ESRIP_RAM01, "RAM[01]:", m_ram[0x01]).mask(0xffff); + state_add(ESRIP_RAM02, "RAM[02]:", m_ram[0x02]).mask(0xffff); + state_add(ESRIP_RAM03, "RAM[03]:", m_ram[0x03]).mask(0xffff); + state_add(ESRIP_RAM04, "RAM[04]:", m_ram[0x04]).mask(0xffff); + state_add(ESRIP_RAM05, "RAM[05]:", m_ram[0x05]).mask(0xffff); + state_add(ESRIP_RAM06, "RAM[06]:", m_ram[0x06]).mask(0xffff); + state_add(ESRIP_RAM07, "RAM[07]:", m_ram[0x07]).mask(0xffff); + state_add(ESRIP_RAM08, "RAM[08]:", m_ram[0x08]).mask(0xffff); + state_add(ESRIP_RAM09, "RAM[09]:", m_ram[0x09]).mask(0xffff); + state_add(ESRIP_RAM0A, "RAM[0A]:", m_ram[0x0a]).mask(0xffff); + state_add(ESRIP_RAM0B, "RAM[0B]:", m_ram[0x0b]).mask(0xffff); + state_add(ESRIP_RAM0C, "RAM[0C]:", m_ram[0x0c]).mask(0xffff); + state_add(ESRIP_RAM0D, "RAM[0D]:", m_ram[0x0d]).mask(0xffff); + state_add(ESRIP_RAM0E, "RAM[0E]:", m_ram[0x0e]).mask(0xffff); + state_add(ESRIP_RAM0F, "RAM[0F]:", m_ram[0x0f]).mask(0xffff); + state_add(ESRIP_RAM10, "RAM[10]:", m_ram[0x10]).mask(0xffff); + state_add(ESRIP_RAM11, "RAM[11]:", m_ram[0x11]).mask(0xffff); + state_add(ESRIP_RAM12, "RAM[12]:", m_ram[0x12]).mask(0xffff); + state_add(ESRIP_RAM13, "RAM[13]:", m_ram[0x13]).mask(0xffff); + state_add(ESRIP_RAM14, "RAM[14]:", m_ram[0x14]).mask(0xffff); + state_add(ESRIP_RAM15, "RAM[15]:", m_ram[0x15]).mask(0xffff); + state_add(ESRIP_RAM16, "RAM[16]:", m_ram[0x16]).mask(0xffff); + state_add(ESRIP_RAM17, "RAM[17]:", m_ram[0x17]).mask(0xffff); + state_add(ESRIP_RAM18, "RAM[18]:", m_ram[0x18]).mask(0xffff); + state_add(ESRIP_RAM19, "RAM[19]:", m_ram[0x19]).mask(0xffff); + state_add(ESRIP_RAM1A, "RAM[1A]:", m_ram[0x1a]).mask(0xffff); + state_add(ESRIP_RAM1B, "RAM[1B]:", m_ram[0x1b]).mask(0xffff); + state_add(ESRIP_RAM1C, "RAM[1C]:", m_ram[0x1c]).mask(0xffff); + state_add(ESRIP_RAM1D, "RAM[1D]:", m_ram[0x1d]).mask(0xffff); + state_add(ESRIP_RAM1E, "RAM[1E]:", m_ram[0x1e]).mask(0xffff); + state_add(ESRIP_RAM1F, "RAM[1F]:", m_ram[0x1f]).mask(0xffff); + state_add(ESRIP_STATW, "STAT:", m_status_out).mask(0xffff); + state_add(ESRIP_FDTC, "FDTC:", m_fdt_cnt).mask(0xffff); + state_add(ESRIP_IPTC, "IPTC:", m_ipt_cnt).mask(0xffff); + state_add(ESRIP_XSCALE, "XSCL:", m_x_scale).mask(0xffff); + state_add(ESRIP_YSCALE, "YSCL:", m_y_scale).mask(0xffff); + state_add(ESRIP_BANK, "BANK:", m_img_bank).mask(0xffff); + state_add(ESRIP_LINE, "LINE:", m_line_latch).mask(0xffff); + state_add(ESRIP_FIG, "FIG:", m_fig_latch).mask(0xffff); + state_add(ESRIP_ATTR, "ATTR:", m_attr_latch).mask(0xffff); + state_add(ESRIP_ADRL, "ADRL:", m_adl_latch).mask(0xffff); + state_add(ESRIP_ADRR, "ADRR:", m_adr_latch).mask(0xffff); + state_add(ESRIP_COLR, "COLR:", m_c_latch).mask(0xffff); + state_add(ESRIP_IADDR, "IADR:", m_iaddr_latch).mask(0xffff); + + /* Create the instruction decode lookup table */ + make_ops(); + + /* Register stuff for state saving */ + save_item(NAME(m_acc)); + save_item(NAME(m_ram)); + save_item(NAME(m_d_latch)); + save_item(NAME(m_i_latch)); + save_item(NAME(m_result)); + save_item(NAME(m_new_status)); + save_item(NAME(m_status)); + save_item(NAME(m_inst)); + save_item(NAME(m_immflag)); + save_item(NAME(m_ct)); + save_item(NAME(m_t)); + save_item(NAME(m_l1)); + save_item(NAME(m_l2)); + save_item(NAME(m_l3)); + save_item(NAME(m_l4)); + save_item(NAME(m_l5)); + save_item(NAME(m_l6)); + save_item(NAME(m_l7)); + save_item(NAME(m_pl1)); + save_item(NAME(m_pl2)); + save_item(NAME(m_pl3)); + save_item(NAME(m_pl4)); + save_item(NAME(m_pl5)); + save_item(NAME(m_pl6)); + save_item(NAME(m_pl7)); + save_item(NAME(m_pc)); + save_item(NAME(m_status_out)); + save_item(NAME(m_x_scale)); + save_item(NAME(m_y_scale)); + save_item(NAME(m_img_bank)); + save_item(NAME(m_line_latch)); + save_item(NAME(m_fig_latch)); + save_item(NAME(m_attr_latch)); + save_item(NAME(m_adl_latch)); + save_item(NAME(m_adr_latch)); + save_item(NAME(m_iaddr_latch)); + save_item(NAME(m_c_latch)); + save_item(NAME(m_fdt_cnt)); + save_item(NAME(m_ipt_cnt)); + save_item(NAME(m_fig)); + save_item(NAME(m_fig_cycles)); + save_item(NAME(m_ipt_ram)); + + // set our instruction counter + m_icountptr = &m_icount; + m_icount = 0; +} + + +void esrip_device::device_reset() +{ + m_pc = 0; + + m_pl1 = 0xff; + m_pl2 = 0xff; + m_pl3 = 0xff; + m_pl4 = 0xff; + m_pl5 = 0xff; + m_pl6 = 0xff; + m_pl7 = 0xff; + + m_l1 = 0xff; + m_l2 = 0xff; + m_l3 = 0xff; + m_l4 = 0xff; + m_l5 = 0xff; + m_l6 = 0xff; + m_l7 = 0xff; + + m_status_out = 0; + m_immflag = 0; + + m_rip_pc = (m_pc | ((m_status_out & 1) << 8)); +} + +void esrip_device::device_stop() +{ +} + + +//------------------------------------------------- +// memory_space_config - return the configuration +// of the specified address space, or NULL if +// the space doesn't exist +//------------------------------------------------- + +const address_space_config *esrip_device::memory_space_config(address_spacenum spacenum) const +{ + if (spacenum == AS_PROGRAM) + { + return &m_program_config; + } + return NULL; +} + + +//------------------------------------------------- +// state_string_export - export state as a string +// for the debugger +//------------------------------------------------- + +void esrip_device::state_string_export(const device_state_entry &entry, std::string &str) +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + strprintf(str, "%c%c%c%c%c%c%c%c%c", + (m_status & 0x80) ? '3' : '.', + (m_status & 0x40) ? '2' : '.', + (m_status & 0x20) ? '1' : '.', + (m_status & 0x10) ? 'L' : '.', + (m_status & 0x08) ? 'V' : '.', + (m_status & 0x04) ? 'N' : '.', + (m_status & 0x02) ? 'C' : '.', + (m_status & 0x01) ? 'Z' : '.', + get_hblank() ? 'H' : '.'); + break; + } +} + + +//------------------------------------------------- +// disasm_min_opcode_bytes - return the length +// of the shortest instruction, in bytes +//------------------------------------------------- + +UINT32 esrip_device::disasm_min_opcode_bytes() const +{ + return 8; +} + + +//------------------------------------------------- +// disasm_max_opcode_bytes - return the length +// of the longest instruction, in bytes +//------------------------------------------------- + +UINT32 esrip_device::disasm_max_opcode_bytes() const +{ + return 8; +} + + +//------------------------------------------------- +// disasm_disassemble - call the disassembly +// helper function +//------------------------------------------------- + +offs_t esrip_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) +{ + extern CPU_DISASSEMBLE( esrip ); + return CPU_DISASSEMBLE_NAME(esrip)(this, buffer, pc, oprom, opram, options); +} + + +/*************************************************************************** + PRIVATE FUNCTIONS +***************************************************************************/ + +int esrip_device::get_hblank() +{ + return machine().first_screen()->hblank(); +} + +/* Return the state of the LBRM line (Y-scaling related) */ +int esrip_device::get_lbrm() +{ + int addr = ((m_y_scale & 0x3f) << 3) | ((m_line_latch >> 3) & 7); + int sel = (m_line_latch & 7); + + UINT8 val = m_lbrm[addr]; + + return (val >> sel) & 1; +} + +int esrip_device::check_jmp(UINT8 jmp_ctrl) +{ + int ret = 0; + + if (~jmp_ctrl & 0x10) + { + switch (jmp_ctrl & 7) + { + /* CT */ case 0: ret = m_ct; break; + /* T1 */ case 4: ret = BIT(m_t, 0); break; + /* T2 */ case 2: ret = BIT(m_t, 1); break; + /* T3 */ case 6: ret = BIT(m_t, 2); break; + /* T4 */ case 1: ret = BIT(m_t, 3); break; + /* /LBRM */ case 5: ret = !get_lbrm(); break; + /* /HBLANK */ case 3: ret = !get_hblank(); break; + /* JMP */ case 7: ret = 0; break; + } + + ret ^= 1; + } + else if (~jmp_ctrl & 0x08) + { + switch (jmp_ctrl & 7) + { + /* CT */ case 0: ret = m_ct; break; + /* T1 */ case 4: ret = BIT(m_t, 0); break; + /* T2 */ case 2: ret = BIT(m_t, 1); break; + /* T3 */ case 6: ret = BIT(m_t, 2); break; + /* T4 */ case 1: ret = BIT(m_t, 3); break; + /* /LBRM */ case 5: ret = !get_lbrm(); break; + /* /FIG */ case 3: ret = !m_fig; break; + /* JMP */ case 7: ret = 1; break; + } + } + else + { + assert(!"RIP: Invalid jump control"); + } + + return ret; +} + + +void esrip_device::calc_z_flag(UINT16 res) +{ + m_new_status &= ~Z_FLAG; + m_new_status |= (res == 0); +} + +void esrip_device::calc_c_flag_add(UINT16 a, UINT16 b) +{ + m_new_status &= ~C_FLAG; + m_new_status |= ((UINT16)(b) > (UINT16)(~(a))) ? 2 : 0; +} + +void esrip_device::calc_c_flag_sub(UINT16 a, UINT16 b) +{ + m_new_status &= ~C_FLAG; + m_new_status |= ((UINT16)(b) <= (UINT16)(a)) ? 2 : 0; +} + +void esrip_device::calc_n_flag(UINT16 res) +{ + m_new_status &= ~N_FLAG; + m_new_status |= (res & 0x8000) ? 4 : 0; +} + +void esrip_device::calc_v_flag_add(UINT16 a, UINT16 b, UINT32 r) +{ + m_new_status &= ~V_FLAG; + m_new_status |= ((a ^ r) & (b ^ r) & 0x8000) ? 8 : 0; +} + +void esrip_device::calc_v_flag_sub(UINT16 a, UINT16 b, UINT32 r) +{ + m_new_status &= ~V_FLAG; + m_new_status |= ((a ^ b) & (r ^ b) & 0x8000) ? 8 : 0; +} + + +/*************************************************************************** + INSTRUCTIONS +***************************************************************************/ + +enum +{ + ACC, + Y_BUS, + STATUS, + RAM +}; + +/************************************* + * + * Single operand + * + *************************************/ + +enum +{ + MOVE = 0xc, + COMP = 0xd, + INC = 0xe, + NEG = 0xf +}; + +enum +{ + SORA = 0x0, + SORY = 0x2, + SORS = 0x3, + SOAR = 0x4, + SODR = 0x6, + SOIR = 0x7, + SOZR = 0x8, + SOZER = 0x9, + SOSER = 0xa, + SORR = 0xb +}; + +UINT16 esrip_device::sor_op(UINT16 r, UINT16 opcode) +{ + UINT32 res = 0; + + switch (opcode) + { + case MOVE: + { + res = r; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case COMP: + { + res = r ^ 0xffff; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case INC: + { + res = r + 1; + calc_v_flag_add(r, 1, res); + calc_n_flag(res); + calc_c_flag_add(r, 1); + calc_z_flag(res); + break; + } + case NEG: + { + res = (r ^ 0xffff) + 1; + calc_v_flag_sub(0, r, res); + calc_n_flag(res); + calc_c_flag_sub(0, r); + calc_z_flag(res); + break; + } + default: assert(0); + } + + return res & 0xffff; +} + +void esrip_device::sor(UINT16 inst) +{ + UINT16 r = 0; + UINT16 dst = 0; + UINT16 res = 0; + + if (BYTE_MODE) + { + printf("Byte Mode! %.4x\n", inst); + UNHANDLED; + } + + switch ((inst >> 5) & 0xf) + { + case SORA: r = m_ram[RAM_ADDR]; dst = ACC; break; + case SORY: r = m_ram[RAM_ADDR]; dst = Y_BUS; break; + case SORS: r = m_ram[RAM_ADDR]; dst = STATUS; break; + case SOAR: r = m_acc; dst = RAM; break; + case SODR: r = m_d_latch; dst = RAM; break; + case SOIR: + { + if (m_immflag == 0) // Macrofiy this? + { + m_i_latch = inst; + m_immflag = 1; + return; + } + else + { + r = m_inst; + dst = RAM; + m_immflag = 0; + } + break; + } + case SOZR: r = 0; dst = RAM; break; + case SORR: r = m_ram[RAM_ADDR]; dst = RAM; break; + default: UNHANDLED; + } + + /* Operation */ + res = sor_op(r, (inst >> 9) & 0xf); + + switch (dst) + { + case Y_BUS: break; + case ACC: m_acc = res; break; + case RAM: m_ram[RAM_ADDR] = res; break; + default: UNHANDLED; + } + + m_result = res; +} + +enum +{ + SOA = 0x4, + SOD = 0x6, + SOI = 0x7, + SOZ = 0x8, + SOZE = 0x9, + SOSE = 0xa +}; + +enum +{ + NRY = 0, + NRA = 1, + NRS = 4, + NRAS = 5 +}; + +void esrip_device::sonr(UINT16 inst) +{ + UINT16 r = 0; + UINT16 res = 0; + + switch ((inst >> 5) & 0xf) + { + case SOA: r = m_acc; break; + case SOD: r = m_d_latch; break; + case SOI: + { + if (m_immflag == 0) + { + m_i_latch = inst; + m_immflag = 1; + return; + } + else + { + r = m_inst; + m_immflag = 0; + } + break; + } + case SOZ: r = 0; break; + default: INVALID; + } + + /* Operation */ + res = sor_op(r, (inst >> 9) & 0xf); + + /* Destination */ + switch (inst & 0x1f) + { + case NRY: break; + case NRA: m_acc = res; break; + default: UNHANDLED; + } + + m_result = res; +} + +/************************************* + * + * Two operand + * + *************************************/ + +enum +{ + SUBR = 0x0, + SUBRC = 0x1, + SUBS = 0x2, + SUBSC = 0x3, + ADD = 0x4, + ADDC = 0x5, + AND = 0x6, + NAND = 0x7, + EXOR = 0x8, + NOR = 0x9, + OR = 0xa, + EXNOR = 0xb +}; + +UINT16 esrip_device::tor_op(UINT16 r, UINT16 s, int opcode) +{ + UINT32 res = 0; + + switch (opcode) + { + case SUBR: + { + res = s - r; + calc_v_flag_sub(s, r, res); + calc_n_flag(res); + calc_c_flag_sub(s, r); + calc_z_flag(res); + break; + } + case SUBRC: assert(0); break; + case SUBS: + { + res = r - s; + calc_v_flag_sub(r, s, res); + calc_n_flag(res); + calc_c_flag_sub(r, s); + calc_z_flag(res); + break; + } + case SUBSC: assert(0); break; + case ADD: + { + res = r + s; + calc_v_flag_add(r, s, res); + calc_n_flag(res); + calc_c_flag_add(r, s); + calc_z_flag(res); + break; + } + case ADDC: + { + // TODO TODO CHECK ME ETC + res = r + s + ((m_status >> 1) & 1); + calc_v_flag_add(r, s, res); + calc_n_flag(res); + calc_c_flag_add(r, s); + calc_z_flag(res); + break; + } + case AND: + { + res = r & s; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case NAND: + { + res = (r & s) ^ 0xffff; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case EXOR: + { + res = r ^ s; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case NOR: + { + res = (r | s) ^ 0xffff; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case OR: + { + res = r | s; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case EXNOR: + { + res = (r ^ s) ^ 0xffff; + CLEAR_FLAGS(V_FLAG | N_FLAG | C_FLAG); + calc_z_flag(res); + break; + } + default: assert(0); + } + + return res & 0xffff; +} + +void esrip_device::tor1(UINT16 inst) +{ + UINT16 r = 0; + UINT16 s = 0; + UINT16 dst = 0; + UINT16 res = 0; + + enum + { + TORAA = 0x0, + TORIA = 0x2, + TODRA = 0x3, + TORAY = 0x8, + TORIY = 0xa, + TODRY = 0xb, + TORAR = 0xc, + TORIR = 0xe, + TODRR = 0xf + }; + + switch (SRC) + { + case TORAA: r = m_ram[RAM_ADDR]; s = m_acc; dst = ACC; break; + case TORIA: + { + if (m_immflag == 0) + { + m_i_latch = inst; + m_immflag = 1; + return; + } + else + { + r = m_ram[RAM_ADDR]; + s = m_inst; + dst = ACC; + m_immflag = 0; + } + break; + } + case TODRA: r = m_d_latch; s = m_ram[RAM_ADDR]; dst = ACC; break; + case TORAY: r = m_ram[RAM_ADDR]; s = m_acc; dst = Y_BUS;break; + case TORIY: + { + if (m_immflag == 0) + { + m_i_latch = inst; + m_immflag = 1; + return; + } + else + { + r = m_ram[RAM_ADDR]; + s = m_inst; + dst = Y_BUS; + m_immflag = 0; + } + break; + } + case TODRY: r = m_d_latch; s = m_ram[RAM_ADDR]; dst = Y_BUS;break; + case TORAR: r = m_ram[RAM_ADDR]; s = m_acc; dst = RAM; break; + case TORIR: + { + if (m_immflag == 0) + { + m_i_latch = inst; + m_immflag = 1; + return; + } + else + { + r = m_ram[RAM_ADDR]; + s = m_inst; + dst = RAM; + m_immflag = 0; + } + break; + } + case TODRR: r = m_d_latch; s = m_ram[RAM_ADDR]; dst = RAM; break; + default: INVALID; + } + + /* Operation */ + res = tor_op(r, s, (inst >> 5) & 0xf); + + /* Destination */ + switch (dst) + { + case ACC: m_acc = res; break; + case Y_BUS: break; + case RAM: m_ram[RAM_ADDR] = res; break; + default: INVALID; + } + + m_result = res; +} + +void esrip_device::tor2(UINT16 inst) +{ + UINT16 r = 0; + UINT16 s = 0; + UINT32 res = 0; + + enum + { + TODAR = 0x1, + TOAIR = 0x2, + TODIR = 0x5 + }; + + switch (SRC) + { + case TODAR: r = m_d_latch; s = m_acc; break; + case TOAIR: + { + if (m_immflag == 0) + { + m_i_latch = inst; + m_immflag = 1; + return; + } + else + { + r = m_acc; + s = m_inst; + m_immflag = 0; + } + break; + } + case TODIR: + { + if (m_immflag == 0) + { + m_i_latch = inst; + m_immflag = 1; + return; + } + else + { + r = m_d_latch; + s = m_inst; + m_immflag = 0; + } + break; + } + default: INVALID; + } + + /* Operation */ + res = tor_op(r, s, (inst >> 5) & 0xf); + + /* Destination is always RAM */ + m_ram[RAM_ADDR] = res; + + m_result = res; +} + +void esrip_device::tonr(UINT16 inst) +{ + enum + { + TODA = 0x1, + TOAI = 0x2, + TODI = 0x5 + }; + + UINT16 r = 0; + UINT16 s = 0; + UINT16 res = 0; + + switch (SRC) + { + case TODA: + { + r = m_d_latch; + s = m_acc; + break; + } + case TOAI: + { + break; + } + case TODI: + { + if (m_immflag == 0) + { + m_i_latch = inst; + m_immflag = 1; + return; + } + else + { + r = m_d_latch; + s = m_inst; + m_immflag = 0; + } + break; + } + default: INVALID; + } + + /* Operation */ + res = tor_op(r, s, (inst >> 5) & 0xf); + + /* Destination */ + switch (DST) + { + case NRY: + break; + case NRA: + m_acc = res; + break; + case NRS: + UNHANDLED; + break; + case NRAS: + UNHANDLED; + break; + default: + INVALID; + } + m_result = res; +} + +/************************************* + * + * Bit operation + * + *************************************/ + +void esrip_device::bonr(UINT16 inst) +{ + enum + { + TSTNA = 0x00, + RSTNA = 0x01, + SETNA = 0x02, + A2NA = 0x04, + S2NA = 0x05, + LD2NA = 0x06, + LDC2NA = 0x07, + TSTND = 0x10, + RSTND = 0x11, + SETND = 0x12, + A2NDY = 0x14, + S2NDY = 0x15, + LD2NY = 0x16, + LDC2NY = 0x17 + }; + + UINT16 res = 0; + + switch (inst & 0x1f) + { + case TSTNA: + { + res = m_acc & (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case RSTNA: + { + res = m_acc & ~(1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + m_acc = res; + break; + } + case SETNA: + { + res = m_acc | (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(res); + m_acc = res; + break; + } + case A2NA: + { + UINT16 r = m_acc; + UINT16 s = 1 << N; + res = r + s; + calc_z_flag(res); + calc_n_flag(res); + calc_c_flag_add(r, s); + calc_v_flag_add(r, s, res); + m_acc = res; + break; + } + case S2NA: + { + UINT16 r = m_acc; + UINT16 s = 1 << N; + res = r - s; + calc_z_flag(res); + calc_n_flag(res); + calc_c_flag_sub(r, s); + calc_v_flag_sub(r, s, res); + m_acc = res; + break; + } + + case TSTND: + { + res = m_d_latch & (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + + case SETND: + { + UINT16 r = m_d_latch; + res = r | (1 << N); + m_d_latch = res; + + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(res); + break; + } + case LD2NY: + { + res = (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(res); + break; + } + case LDC2NY: + { + res = (1 << N) ^ 0xffff; + CLEAR_FLAGS(Z_FLAG | C_FLAG | V_FLAG); + calc_n_flag(res); + break; + } + + case A2NDY: + { + UINT16 r = m_d_latch; + UINT16 s = 1 << N; + res = r + s; + + calc_z_flag(res); + calc_n_flag(res); + calc_c_flag_add(r, s); + calc_v_flag_add(r, s, res); + break; + } + + default: + UNHANDLED; + } + + m_result = res; +} + +void esrip_device::bor1(UINT16 inst) +{ + enum + { + SETNR = 0xd, + RSTNR = 0xe, + TSTNR = 0xf + }; + + UINT16 res = 0; + + switch ((inst >> 5) & 0xf) + { + case SETNR: + { + res = m_ram[RAM_ADDR] | (1 << N); + m_ram[RAM_ADDR] = res; + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(res); + break; + } + case RSTNR: + { + res = m_ram[RAM_ADDR] & ~(1 << N); + m_ram[RAM_ADDR] = res; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case TSTNR: + { + res = m_ram[RAM_ADDR] & (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + default: INVALID; + } + + m_result = res; +} + +void esrip_device::bor2(UINT16 inst) +{ + enum + { + LD2NR = 0xc, + LDC2NR = 0xd, + A2NR = 0xe, + S2NR = 0xf + }; + + UINT32 res = 0; + + switch ((inst >> 5) & 0xf) + { + case LD2NR: + { + res = 1 << N; + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(res); + break; + } + case LDC2NR: + { + res = (1 << N) ^ 0xffff; + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(res); + break; + } + case A2NR: + { + UINT16 r = m_ram[RAM_ADDR]; + UINT16 s = 1 << N; + + res = r + s; + calc_v_flag_add(r, s, res); + calc_n_flag(res); + calc_c_flag_add(r, s); + calc_z_flag(res); + break; + } + case S2NR: + { + UINT16 r = m_ram[RAM_ADDR]; + UINT16 s = 1 << N; + + res = r - s; + calc_v_flag_sub(r, s, res); + calc_n_flag(res); + calc_c_flag_sub(r, s); + calc_z_flag(res); + break; + } + default: INVALID; + } + + /* Destination is RAM */ + m_ram[RAM_ADDR] = res; + m_result = res; +} + +/************************************* + * + * Rotate + * + *************************************/ + +/* TODO Combine these */ +void esrip_device::rotr1(UINT16 inst) +{ + enum + { + RTRA = 0xc, + RTRY = 0xd, + RTRR = 0xf + }; + + UINT16 u = 0; + UINT16 dst = 0; + UINT16 res = 0; + int n = N; + + switch ((inst >> 5) & 0xf) + { + case RTRA: u = m_ram[RAM_ADDR]; dst = ACC; break; + case RTRY: u = m_ram[RAM_ADDR]; dst = Y_BUS; break; + case RTRR: u = m_ram[RAM_ADDR]; dst = RAM; break; + default: INVALID; + } + + res = (u << n) | (u >> (16 - n)); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + + switch (dst) + { + case ACC: m_acc = res; break; + case RAM: m_ram[RAM_ADDR] = res; break; + } + + m_result = res; +} + +void esrip_device::rotr2(UINT16 inst) +{ + enum + { + RTAR = 0, + RTDR = 1 + }; + + UINT16 u = 0; + UINT16 res = 0; + + switch ((inst >> 5) & 0xf) + { + case RTAR: u = m_acc; break; + case RTDR: u = m_d_latch; break; + default: INVALID; + } + + res = (u << N) | (u >> (16 - N)); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + m_ram[RAM_ADDR] = res; + + m_result = res; +} + +void esrip_device::rotnr(UINT16 inst) +{ + enum + { + RTDY = 0x18, + RTDA = 0x19, + RTAY = 0x1c, + RTAA = 0x1d + }; + + UINT16 u = 0; + UINT16 res = 0; + UINT16 dst = 0; + + switch (inst & 0x1f) + { + case RTDY: u = m_d_latch; dst = Y_BUS; break; + case RTDA: u = m_d_latch; dst = ACC; break; + case RTAY: u = m_acc; dst = Y_BUS; break; + case RTAA: u = m_acc; dst = ACC; break; + default: INVALID; + } + + res = (u << N) | (u >> (16 - N)); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + + switch (dst) + { + case Y_BUS: break; + case ACC: m_acc = res; break; + case RAM: m_ram[RAM_ADDR] = res; break; + default: UNHANDLED; + } + + m_result = res; +} + +/************************************* + * + * Rotate and compare + * + *************************************/ + +void esrip_device::rotc(UINT16 inst) +{ + UNHANDLED; +} + +/************************************* + * + * Rotate and merge + * + *************************************/ + +void esrip_device::rotm(UINT16 inst) +{ + UNHANDLED; +} + +/************************************* + * + * Prioritize + * + *************************************/ + +void esrip_device::prt(UINT16 inst) +{ + UNHANDLED; +} + +void esrip_device::prtnr(UINT16 inst) +{ + UNHANDLED; +} + + +/************************************* + * + * CRC + * + *************************************/ + +void esrip_device::crcf(UINT16 inst) +{ + UNHANDLED; +} + +void esrip_device::crcr(UINT16 inst) +{ + UNHANDLED; +} + +/************************************* + * + * Single bit shift + * + *************************************/ + +enum +{ + SHUPZ = 0, + SHUP1 = 1, + SHUPL = 2, + SHDNZ = 4, + SHDN1 = 5, + SHDNL = 6, + SHDNC = 7, + SHDNOV = 8 +}; + +#define SET_LINK_flag(x) (m_new_status &= ~L_FLAG); \ + (m_new_status |= x ? L_FLAG : 0) + +UINT16 esrip_device::shift_op(UINT16 u, int opcode) +{ + UINT32 res = 0; + + switch (opcode) + { + case SHUPZ: + { + res = (u << 1); + SET_LINK_flag(u & 0x8000); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case SHUP1: + { + res = (u << 1) | 1; + SET_LINK_flag(u & 0x8000); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + case SHUPL: + { + res = (u << 1) | ((m_status & L_FLAG) ? 1 : 0); + SET_LINK_flag(u & 0x8000); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(res); + calc_z_flag(res); + break; + } + + case SHDNZ: + case SHDN1: + case SHDNL: + case SHDNC: + case SHDNOV: + default: assert(0); + } + + return res; +} + +void esrip_device::shftr(UINT16 inst) +{ + enum + { + SHRR = 6, + SHDR = 7 + }; + + UINT16 u = 0; + UINT16 res = 0; + + switch ((inst >> 9) & 0xf) + { + case SHRR: u = m_ram[RAM_ADDR]; break; + case SHDR: u = m_d_latch; break; + default: INVALID; + } + + res = shift_op(u, (inst >> 5) & 0xf); + + /* Destination is always RAM */ + m_ram[RAM_ADDR] = res; + m_result = res; +} + +void esrip_device::shftnr(UINT16 inst) +{ + enum + { + SHA = 6, + SHD = 7 + }; + + UINT16 u = 0; + UINT16 res = 0; + + switch ((inst >> 9) & 0xf) + { + case SHA: u = m_acc; break; + case SHD: u = m_d_latch; break; + default: INVALID; + } + + res = shift_op(u, (inst >> 5) & 0xf); + + switch (DST) + { + case NRY: break; + case NRA: m_acc = res; break; + default: INVALID; + } + m_result = res; +} + + +/************************************* + * + * Status + * + *************************************/ + +void esrip_device::svstr(UINT16 inst) +{ + UNHANDLED; +} + +void esrip_device::rstst(UINT16 inst) +{ + enum + { + RONCZ = 0x3, + RL = 0x5, + RF1 = 0x6, + RF2 = 0x9, + RF3 = 0xa + }; + + switch (inst & 0x1f) + { + case RONCZ: CLEAR_FLAGS(V_FLAG | N_FLAG | C_FLAG | Z_FLAG); break; + case RL: CLEAR_FLAGS(L_FLAG); break; + case RF1: CLEAR_FLAGS(FLAG_1); break; + case RF2: CLEAR_FLAGS(FLAG_2); break; + case RF3: CLEAR_FLAGS(FLAG_3); break; + } + + m_result = 0; +} + +void esrip_device::setst(UINT16 inst) +{ + enum + { + SONCZ = 0x3, + SL = 0x5, + SF1 = 0x6, + SF2 = 0x9, + SF3 = 0xa + }; + + switch (inst & 0x1f) + { + case SONCZ: SET_FLAGS(V_FLAG | N_FLAG | C_FLAG | Z_FLAG); break; + case SL: SET_FLAGS(L_FLAG); break; + case SF1: SET_FLAGS(FLAG_1); break; + case SF2: SET_FLAGS(FLAG_2); break; + case SF3: SET_FLAGS(FLAG_3); break; + } + + m_result = 0xffff; +} + +void esrip_device::test(UINT16 inst) +{ + enum + { + TNOZ = 0x00, + TNO = 0x02, + TZ = 0x04, + TOVR = 0x06, + TLOW = 0x08, + TC = 0x0a, + TZC = 0x0c, + TN = 0x0e, + TL = 0x10, + TF1 = 0x12, + TF2 = 0x14, + TF3 = 0x16 + }; + + UINT32 res = 0; + + switch (inst & 0x1f) + { + case TNOZ: UNHANDLED; break; + case TNO: UNHANDLED; break; + case TZ: res = m_status & (Z_FLAG); break; + case TOVR: res = m_status & (V_FLAG); break; + case TLOW: UNHANDLED; break; + case TC: res = m_status & (C_FLAG); break; + case TZC: UNHANDLED; break; + case TN: res = m_status & (N_FLAG); break; + case TL: res = m_status & (L_FLAG); break; + case TF1: res = m_status & (FLAG_1); break; + case TF2: res = m_status & (FLAG_2); break; + case TF3: res = m_status & (FLAG_3); break; + default: INVALID; + } + + m_ct = res ? 1 : 0; +} + + +/************************************* + * + * No operation + * + *************************************/ + +void esrip_device::nop(UINT16 inst) +{ + m_result = 0xff; // Undefined +} + +//************************************************************************** +// DEVICE INTERFACE +//************************************************************************** + +const device_type ESRIP = &device_creator<esrip_device>; + +//------------------------------------------------- +// esrip_device - constructor +//------------------------------------------------- + +esrip_device::esrip_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : cpu_device(mconfig, ESRIP, "ESRIP", tag, owner, clock, "esrip", __FILE__), + m_program_config("program", ENDIANNESS_BIG, 64, 9, -3), + m_fdt_r(*this), + m_fdt_w(*this), + m_status_in(*this), + m_lbrm_prom(NULL) +{ + // build the opcode table + for (int op = 0; op < 24; op++) + m_opcode[op] = s_opcodetable[op]; +} + + +//************************************************************************** +// STATIC OPCODE TABLES +//************************************************************************** + +const esrip_device::ophandler esrip_device::s_opcodetable[24] = +{ + &esrip_device::rotr1, &esrip_device::tor1, &esrip_device::rotr2, &esrip_device::rotc, + &esrip_device::rotm, &esrip_device::bor2, &esrip_device::crcf, &esrip_device::crcr, + &esrip_device::svstr, &esrip_device::prt, &esrip_device::sor, &esrip_device::tor2, + &esrip_device::shftr, &esrip_device::test, &esrip_device::nop, &esrip_device::setst, + &esrip_device::rstst, &esrip_device::rotnr, &esrip_device::bonr, &esrip_device::bor1, + &esrip_device::sonr, &esrip_device::shftnr, &esrip_device::prtnr, &esrip_device::tonr +}; + + +void esrip_device::am29116_execute(UINT16 inst, int _sre) +{ + /* Status register shadow */ + m_new_status = m_status; + + /* Required for immediate source instructions */ + m_inst = inst; + + if (m_immflag == 1) + inst = m_i_latch; + + (this->*m_opcode[m_optable[inst]])(inst); + + if (!_sre) + { + m_status = m_new_status; + m_t = m_status; + } +} + + +//------------------------------------------------- +// execute_min_cycles - return minimum number of +// cycles it takes for one instruction to execute +//------------------------------------------------- + +UINT32 esrip_device::execute_min_cycles() const +{ + return 1; +} + + +//------------------------------------------------- +// execute_max_cycles - return maximum number of +// cycles it takes for one instruction to execute +//------------------------------------------------- + +UINT32 esrip_device::execute_max_cycles() const +{ + return 1; +} + + +//------------------------------------------------- +// execute_input_lines - return the number of +// input/interrupt lines +//------------------------------------------------- + +UINT32 esrip_device::execute_input_lines() const +{ + return 0; +} + + +//------------------------------------------------- +// execute_set_input - act on a changed input/ +// interrupt line +//------------------------------------------------- + +void esrip_device::execute_set_input(int inputnum, int state) +{ +} + + +void esrip_device::execute_run() +{ + int calldebugger = (machine().debug_flags & DEBUG_FLAG_ENABLED) != 0; + UINT8 status; + + /* I think we can get away with placing this outside of the loop */ + status = m_status_in(*m_program, 0); + + /* Core execution loop */ + do + { + UINT64 inst; + UINT8 next_pc; + UINT16 x_bus = 0; + UINT16 ipt_bus = 0; + UINT16 y_bus = 0; + + int yoe = _BIT(m_l5, 1); + int bl46 = BIT(m_l4, 6); + int bl44 = BIT(m_l4, 4); + + UINT32 in_h; + UINT32 in_l; + + if (m_fig_cycles) + { + if (--m_fig_cycles == 0) + m_fig = 0; + } + + /* /OEY = 1 : Y-bus is high imped */ + if (yoe) + { + /* Status In */ + if (!_BIT(m_l2, 0)) + y_bus = status | (!m_fig << 3); + + /* FDT RAM: /Enable, Direction and /RAM OE */ + else if (!bl44 && !_BIT(m_l2, 3) && bl46) + y_bus = m_fdt_r(*m_program, m_fdt_cnt, 0xffff); + + /* IPT RAM: /Enable and /READ */ + else if (!_BIT(m_l2, 6) && !_BIT(m_l4, 5)) + y_bus = m_ipt_ram[m_ipt_cnt]; + + /* DLE - latch the value on the Y-BUS into the data latch */ + if (_BIT(m_l5, 0)) + m_d_latch = y_bus; + + /* Now execute the AM29116 instruction */ + am29116_execute((m_l7 << 8) | m_l6, BIT(m_l5, 2)); + } + else + { + am29116_execute((m_l7 << 8) | m_l6, BIT(m_l5, 2)); + + y_bus = m_result; + + if (BIT(m_l5, 0)) + m_d_latch = y_bus; + } + + /* Determine what value is on the X-Bus */ + + /* FDT RAM */ + if (!bl44) + x_bus = m_fdt_r(*m_program, m_fdt_cnt, 0xffff); + + /* Buffer is enabled - write direction */ + else if (!BIT(m_l2, 3) && !bl46) + { + if (!yoe) + x_bus = y_bus; + else if ( !BIT(m_l2, 6) && !BIT(m_l4, 5) ) + x_bus = m_ipt_ram[m_ipt_cnt]; + } + + /* IPT BUS */ + if (!BIT(m_l2, 6)) + ipt_bus = m_ipt_ram[m_ipt_cnt]; + else if (!BIT(m_l4, 5)) + { + if (!BIT(m_l5, 1)) + ipt_bus = y_bus; + else + ipt_bus = x_bus; + } + + + /* Write FDT RAM: /Enable, Direction and WRITE */ + if (!BIT(m_l2, 3) && !bl46 && !BIT(m_l4, 3)) + m_fdt_w(*m_program, m_fdt_cnt, x_bus, 0xffff); + + /* Write IPT RAM: /Enable and /WR */ + if (!BIT(m_l2, 7) && !BIT(m_l4, 5)) + m_ipt_ram[m_ipt_cnt] = ipt_bus; + + + if ((((m_l5 >> 3) & 0x1f) & 0x18) != 0x18) + { + if ( check_jmp((m_l5 >> 3) & 0x1f) ) + next_pc = m_l1; + else + next_pc = m_pc + 1; + } + else + next_pc = m_pc + 1; + + m_pl1 = m_l1; + m_pl2 = m_l2; + m_pl3 = m_l3; + m_pl4 = m_l4; + m_pl5 = m_l5; + m_pl6 = m_l6; + m_pl7 = m_l7; + + /* Latch instruction */ + inst = m_direct->read_qword(RIP_PC << 3); + + in_h = inst >> 32; + in_l = inst & 0xffffffff; + + m_l1 = (in_l >> 8); + m_l2 = (in_l >> 16); + m_l3 = (in_l >> 24); + + m_l4 = (in_h >> 0); + m_l5 = (in_h >> 8); + m_l6 = (in_h >> 16); + m_l7 = (in_h >> 24); + + /* Colour latch */ + if (RISING_EDGE(m_pl3, m_l3, 0)) + m_c_latch = (x_bus >> 12) & 0xf; + + /* Right pixel line buffer address */ + if (RISING_EDGE(m_pl3, m_l3, 1)) + m_adr_latch = x_bus & 0xfff; + + /* Left pixel line buffer address */ + if (RISING_EDGE(m_pl3, m_l3, 2)) + m_adl_latch = x_bus & 0xfff; + + /* FIGLD: Start the DMA */ + if (RISING_EDGE(m_pl3, m_l3, 3)) + { + m_attr_latch = x_bus; + + m_fig = 1; + m_fig_cycles = m_draw(m_adl_latch, m_adr_latch, m_fig_latch, m_attr_latch, m_iaddr_latch, m_c_latch, m_x_scale, m_img_bank); + } + + /* X-scale */ + if (RISING_EDGE(m_pl3, m_l3, 4)) + m_x_scale = x_bus >> 8; + + /* Y-scale and image bank */ + if (RISING_EDGE(m_pl4, m_l4, 2)) + { + m_y_scale = x_bus & 0xff; + m_img_bank = (y_bus >> 14) & 3; + } + + /* Image ROM address */ + if (RISING_EDGE(m_pl3, m_l3, 5)) + m_iaddr_latch = y_bus; + + /* IXLLD */ + if (RISING_EDGE(m_pl3, m_l3, 6)) + { + m_line_latch = ipt_bus >> 10; + m_fig_latch = ipt_bus & 0x3ff; + } + + /* Status write */ + if (RISING_EDGE(m_pl3, m_l3, 7)) + m_status_out = y_bus & 0xff; + + /* FDT address counter */ + if (!BIT(m_pl2, 1)) + m_fdt_cnt = y_bus & 0xfff; + else if (BIT(m_pl2, 2)) + m_fdt_cnt = (m_fdt_cnt + 1) & 0xfff; + + /* Now we can alter the IPT address counter */ + if (!BIT(m_pl2, 4)) + m_ipt_cnt = y_bus & 0x1fff; + else if (BIT(m_pl2, 5)) + m_ipt_cnt = (m_ipt_cnt + 1) & 0x1fff; + + if (calldebugger) + debugger_instruction_hook(this, RIP_PC); + + m_pc = next_pc; + m_rip_pc = (m_pc | ((m_status_out & 1) << 8)); + + m_icount--; + } while (m_icount > 0); +} |