offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) { unsigned startpc = pc; uint16_t opcode = opcodes.r16(pc); uint8_t inst = opcode >> 13; pc+=1; // determine instruction switch (inst) { case 0x00: stream << "MOVE " << reg_names[SRC]; if(is_rot(opcode)) util::stream_format(stream, "(%i),", ROTLEN); else util::stream_format(stream, ",%i,", ROTLEN); stream << reg_names[DST]; break; case 0x01: stream << "ADD " << reg_names[SRC]; if(is_rot(opcode)) util::stream_format(stream, "(%i),", ROTLEN); else util::stream_format(stream, ",%i,", ROTLEN); stream << reg_names[DST]; break; case 0x02: stream << "AND " << reg_names[SRC]; if(is_rot(opcode)) util::stream_format(stream, "(%i),", ROTLEN); else util::stream_format(stream, ",%i,", ROTLEN); stream << reg_names[DST]; break; case 0x03: stream << "XOR " << reg_names[SRC]; if(is_rot(opcode)) util::stream_format(stream, "(%i),", ROTLEN); else util::stream_format(stream, ",%i,", ROTLEN); stream << reg_names[DST]; break; case 0x04: stream << "XEC " << reg_names[SRC]; if(is_src_rot(opcode)) { util::stream_format(stream, ",%02XH", IMM8); } else { util::stream_format(stream, ",%i", ROTLEN); util::stream_format(stream, ",%02XH", IMM5); } break; case 0x05: stream << "NZT " << reg_names[SRC]; if(is_src_rot(opcode)) { util::stream_format(stream, ",%02XH", IMM8); } else { util::stream_format(stream, ",%i", ROTLEN); util::stream_format(stream, ",%02XH", IMM5); } break; case 0x06: stream << "XMIT "; if(is_src_rot(opcode)) { util::stream_format(stream, "%02XH,", IMM8); stream << reg_names[SRC]; } else { util::stream_format(stream, "%02XH,", IMM5); stream << reg_names[SRC]; util::stream_format(stream, ",%i", ROTLEN); } break; case 0x07: util::stream_format(stream, "JMP %04XH", (opcode & 0x1fff)); break; } return (pc - startpc); }
void n8x300_cpu_device::execute_run() { do { UINT16 opcode; UINT8 src = 0; UINT8 dst; UINT8 rotlen; // rotate amount or I/O field length UINT8 mask; UINT16 result; /* fetch the opcode */ debugger_instruction_hook(this, m_genPC); opcode = FETCHOP(m_genPC); m_PC++; m_PC &= 0x1fff; m_AR = m_PC; m_IR = opcode; m_genPC = m_PC << 1; switch (OP) { case 0x00: // MOVE rotlen = ROTLEN; if(is_rot(opcode)) // MOVE reg,reg { src = get_reg(SRC); dst = rotate(src,rotlen); set_reg(DST,dst); } else { if(rotlen == 0) rotlen = 8; // 0 = 8-bit I/O field length if(is_src_reg(opcode) && !(is_dst_reg(opcode))) { // MOVE reg,IV DST_LATCH; mask = ((1 << rotlen)-1); src = (get_reg(SRC)) << (7-DST_LSB); mask <<= (7-DST_LSB); if(DST_IS_RIGHT_BANK) { dst = (m_right_IV & ~mask) | (src & mask); m_right_IV = dst; WRITEPORT(m_IVR+0x100,m_right_IV); } else { dst = (m_left_IV & ~mask) | (src & mask); m_left_IV = dst; WRITEPORT(m_IVL,m_left_IV); } } else if(!(is_src_reg(opcode)) && is_dst_reg(opcode)) { // MOVE IV,reg SRC_LATCH; if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB); else src = rotate(m_left_IV,7-SRC_LSB); mask = ((1 << rotlen)-1); dst = src & mask; set_reg(DST,dst); } else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode))) { // MOVE IV,IV SRC_LATCH; if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB); else src = rotate(m_left_IV,7-SRC_LSB); mask = ((1 << rotlen)-1); dst = src & mask; dst <<= (7-DST_LSB); mask <<= (7-DST_LSB); if(SRC_IS_RIGHT_BANK) // untouched source IV bits are preserved and sent to destination IV { dst = (m_right_IV & ~mask) | (dst & mask); m_right_IV = dst; WRITEPORT(m_IVR+0x100,m_right_IV); } else { dst = (m_left_IV & ~mask) | (dst & mask); m_left_IV = dst; WRITEPORT(m_IVL,m_left_IV); } } } break; case 0x01: // ADD rotlen = ROTLEN; if(is_rot(opcode)) { // ADD reg,reg src = rotate(get_reg(SRC),rotlen); result = src + m_AUX; set_reg(DST,result & 0xff); SET_OVF; } else { if(rotlen == 0) rotlen = 8; // 0 = 8-bit I/O field length if(is_src_reg(opcode) && !(is_dst_reg(opcode))) { // ADD reg,IV DST_LATCH; result = get_reg(SRC) + m_AUX; mask = ((1 << rotlen)-1); dst = (result & 0xff) << DST_LSB; mask <<= DST_LSB; SET_OVF; if(DST_IS_RIGHT_BANK) { dst = (m_right_IV & ~mask) | (dst & mask); m_right_IV = dst; WRITEPORT(m_IVR+0x100,m_right_IV); } else { dst = (m_left_IV & ~mask) | (dst & mask); m_left_IV = dst; WRITEPORT(m_IVL,m_left_IV); } } else if(!(is_src_reg(opcode)) && is_dst_reg(opcode)) { // ADD IV,reg SRC_LATCH; mask = ((1 << rotlen)-1); if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB) & mask; else src = rotate(m_left_IV,7-SRC_LSB) & mask; result = src + m_AUX; SET_OVF; set_reg(DST,result & 0xff); } else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode))) { // ADD IV,IV SRC_LATCH; DST_LATCH; mask = ((1 << rotlen)-1); if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB) & mask; else src = rotate(m_left_IV,7-SRC_LSB) & mask; result = src + m_AUX; SET_OVF; dst = (result << (7-DST_LSB)) & 0xff; mask <<= (7-DST_LSB); if(SRC_IS_RIGHT_BANK) // unused destination IV data is not preserved, is merged with input IV data { dst = (m_right_IV & ~mask) | (dst & mask); m_right_IV = dst; WRITEPORT(m_IVR+0x100,m_right_IV); } else { dst = (m_left_IV & ~mask) | (dst & mask); m_left_IV = dst; WRITEPORT(m_IVL,m_left_IV); } } } break; case 0x02: // AND rotlen = ROTLEN; if(is_rot(opcode)) { // AND reg,reg src = rotate(get_reg(SRC),rotlen); dst = src & m_AUX; set_reg(DST,dst); } else { if(rotlen == 0) rotlen = 8; // 0 = 8-bit I/O field length if(is_src_reg(opcode) && !(is_dst_reg(opcode))) { // AND reg,IV DST_LATCH; src = get_reg(SRC) & m_AUX; mask = ((1 << rotlen)-1); src <<= (7-DST_LSB); mask <<= (7-DST_LSB); if(DST_IS_RIGHT_BANK) { dst = (m_right_IV & ~mask) | (src & mask); m_right_IV = dst; WRITEPORT(m_IVR+0x100,m_right_IV); } else { dst = (m_left_IV & ~mask) | (src & mask); m_left_IV = dst; WRITEPORT(m_IVL,m_left_IV); } } else if(!(is_src_reg(opcode)) && is_dst_reg(opcode)) { // AND IV,reg SRC_LATCH; mask = ((1 << rotlen)-1); if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB) & mask; else src = rotate(m_left_IV,7-SRC_LSB) & mask; src &= mask; dst = src & m_AUX; set_reg(DST,dst); } else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode))) { // AND IV,IV SRC_LATCH; DST_LATCH; mask = ((1 << rotlen)-1); if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB) & mask; else src = rotate(m_left_IV,7-SRC_LSB) & mask; src &= mask; dst = src & m_AUX; dst <<= (7-DST_LSB); mask <<= (7-DST_LSB); if(SRC_IS_RIGHT_BANK) { dst = (m_right_IV & ~mask) | (src & mask); m_right_IV = dst; WRITEPORT(m_IVR+0x100,m_right_IV); } else { dst = (m_left_IV & ~mask) | (src & mask); m_left_IV = dst; WRITEPORT(m_IVL,m_left_IV); } } } break; case 0x03: // XOR rotlen = ROTLEN; if(is_rot(opcode)) { // AND reg,reg src = rotate(get_reg(SRC),rotlen); dst = src ^ m_AUX; set_reg(DST,dst); } else { if(rotlen == 0) rotlen = 8; // 0 = 8-bit I/O field length if(is_src_reg(opcode) && !(is_dst_reg(opcode))) { // AND reg,IV DST_LATCH; src = get_reg(SRC) ^ m_AUX; mask = ((1 << rotlen)-1); src <<= (7-DST_LSB); mask <<= (7-DST_LSB); if(DST_IS_RIGHT_BANK) { dst = (m_right_IV & ~mask) | (src & mask); m_right_IV = dst; WRITEPORT(m_IVR+0x100,m_right_IV); } else { dst = (m_left_IV & ~mask) | (src & mask); m_left_IV = dst; WRITEPORT(m_IVL,m_left_IV); } } else if(!(is_src_reg(opcode)) && is_dst_reg(opcode)) { // AND IV,reg SRC_LATCH; mask = ((1 << rotlen)-1); if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB) & mask; else src = rotate(m_left_IV,7-SRC_LSB) & mask; src &= mask; dst = src ^ m_AUX; set_reg(DST,dst); } else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode))) { // AND IV,IV SRC_LATCH; DST_LATCH; mask = ((1 << rotlen)-1); if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB) & mask; else src = rotate(m_left_IV,7-SRC_LSB) & mask; src &= mask; dst = src ^ m_AUX; dst <<= (7-DST_LSB); mask <<= (7-DST_LSB); if(SRC_IS_RIGHT_BANK) { dst = (m_right_IV & ~mask) | (src & mask); m_right_IV = dst; WRITEPORT(m_IVR+0x100,m_right_IV); } else { dst = (m_left_IV & ~mask) | (src & mask); m_left_IV = dst; WRITEPORT(m_IVL,m_left_IV); } } } break; case 0x04: // XEC (Execute) if(is_src_reg(opcode)) { src = get_reg(SRC); src += IMM8; SET_AR((m_AR & 0x1f00) | src); } else { SRC_LATCH; rotlen = ROTLEN; if(rotlen == 0) rotlen = 8; // 0 = 8-bit I/O field length mask = ((1 << rotlen)-1); if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB); else src = rotate(m_left_IV,7-SRC_LSB); src &= mask; src += IMM5; SET_AR((m_AR & 0x1fe0) | (src & 0x1f)); } break; case 0x05: // NZT (Non-zero transfer) if(is_src_reg(opcode)) { src = get_reg(SRC); if(src != 0) SET_PC((m_PC & 0x1f00) | IMM8); } else { SRC_LATCH; rotlen = ROTLEN; if(rotlen == 0) rotlen = 8; // 0 = 8-bit I/O field length mask = ((1 << rotlen)-1); if(SRC_IS_RIGHT_BANK) src = rotate(m_right_IV,7-SRC_LSB); else src = rotate(m_left_IV,7-SRC_LSB); rotate(src,SRC_LSB); src &= mask; if(src != 0) SET_PC((m_PC & 0x1fe0) | IMM5); } break; case 0x06: // XMIT (Transmit) // the source is actually the destination for this instruction if(is_src_reg(opcode)) set_reg(SRC,IMM8); else { SRC_LATCH; rotlen = ROTLEN; if(rotlen == 0) rotlen = 8; // 0 = 8-bit I/O field length mask = ((1 << rotlen)-1); dst = IMM5; mask <<= (7-SRC_LSB); dst <<= (7-SRC_LSB); if(SRC_IS_RIGHT_BANK) { m_right_IV = (m_right_IV & ~mask) | (dst & mask); WRITEPORT(m_IVR+0x100,m_right_IV); } else { m_left_IV = (m_left_IV & ~mask) | (dst & mask); WRITEPORT(m_IVL,m_left_IV); } } break; case 0x07: // JMP SET_PC(ADDR); break; } CYCLES(1); // all instructions take 1 cycle (250ns) } while (m_icount > 0); }