From 3c6ffd84b0ae8c7138ea7199ebc8d74e77be0f3e Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 5 Mar 2026 03:43:49 +1100 Subject: -cpu/e132xs: Log analysed instructions in UML log when using recompiler. -cpu/powerpc: Modernised recompiler front-end code, improved instruction analysis logging. -cpu/sh: Cleaned up instruction analysis logging a little -util/client_ws.hpp, util/server_ws_impl.hpp, capcom/cps2comm.cpp: Updated some use of deprecation ASIO APIs. -nakajima/nakajies.cpp: Use range-based loops. --- scripts/src/cpu.lua | 11 +- src/devices/cpu/e132xs/32xsdasm.cpp | 1104 ----------------------------- src/devices/cpu/e132xs/32xsdasm.h | 46 -- src/devices/cpu/e132xs/32xsdefs.h | 247 ------- src/devices/cpu/e132xs/e132xs.cpp | 7 +- src/devices/cpu/e132xs/e132xs.h | 4 +- src/devices/cpu/e132xs/e132xsdrc.cpp | 68 +- src/devices/cpu/e132xs/e132xsdrc_ops.hxx | 1 - src/devices/cpu/e132xs/e132xsfe.cpp | 1027 --------------------------- src/devices/cpu/e132xs/e132xsfe.h | 210 ------ src/devices/cpu/e132xs/e1dasm.cpp | 1132 +++++++++++++++++++++++++++++ src/devices/cpu/e132xs/e1dasm.h | 51 ++ src/devices/cpu/e132xs/e1defs.h | 247 +++++++ src/devices/cpu/e132xs/e1fe.cpp | 1136 ++++++++++++++++++++++++++++++ src/devices/cpu/e132xs/e1fe.h | 215 ++++++ src/devices/cpu/powerpc/ppc.h | 4 - src/devices/cpu/powerpc/ppcdrc.cpp | 227 +----- src/devices/cpu/powerpc/ppcfe.cpp | 994 ++++++++++++++------------ src/devices/cpu/powerpc/ppcfe.h | 104 ++- src/devices/cpu/sh/sh.cpp | 86 +-- src/devices/cpu/sh/sh.h | 1 - src/devices/cpu/sh/sh_fe.cpp | 50 ++ src/devices/cpu/sh/sh_fe.h | 5 + src/lib/util/client_ws.hpp | 16 +- src/lib/util/server_ws_impl.hpp | 12 +- src/mame/capcom/cps2comm.cpp | 12 +- src/mame/nakajima/nakajies.cpp | 43 +- src/tools/unidasm.cpp | 14 +- 28 files changed, 3649 insertions(+), 3425 deletions(-) delete mode 100644 src/devices/cpu/e132xs/32xsdasm.cpp delete mode 100644 src/devices/cpu/e132xs/32xsdasm.h delete mode 100644 src/devices/cpu/e132xs/32xsdefs.h delete mode 100644 src/devices/cpu/e132xs/e132xsfe.cpp delete mode 100644 src/devices/cpu/e132xs/e132xsfe.h create mode 100644 src/devices/cpu/e132xs/e1dasm.cpp create mode 100644 src/devices/cpu/e132xs/e1dasm.h create mode 100644 src/devices/cpu/e132xs/e1defs.h create mode 100644 src/devices/cpu/e132xs/e1fe.cpp create mode 100644 src/devices/cpu/e132xs/e1fe.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 9bf32fcaf66..3490ca9d4f9 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1046,17 +1046,18 @@ if CPUS["E1"] then files { MAME_DIR .. "src/devices/cpu/e132xs/e132xs.cpp", MAME_DIR .. "src/devices/cpu/e132xs/e132xs.h", - MAME_DIR .. "src/devices/cpu/e132xs/32xsdefs.h", - MAME_DIR .. "src/devices/cpu/e132xs/e132xsop.hxx", - MAME_DIR .. "src/devices/cpu/e132xs/e132xsfe.cpp", MAME_DIR .. "src/devices/cpu/e132xs/e132xsdrc.cpp", MAME_DIR .. "src/devices/cpu/e132xs/e132xsdrc_ops.hxx", + MAME_DIR .. "src/devices/cpu/e132xs/e132xsop.hxx", + MAME_DIR .. "src/devices/cpu/e132xs/e1defs.h", + MAME_DIR .. "src/devices/cpu/e132xs/e1fe.cpp", + MAME_DIR .. "src/devices/cpu/e132xs/e1fe.h", } end if opt_tool(CPUS, "E1") then - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/e132xs/32xsdasm.cpp") - table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/e132xs/32xsdasm.h") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/e132xs/e1dasm.cpp") + table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/e132xs/e1dasm.h") end -------------------------------------------------- diff --git a/src/devices/cpu/e132xs/32xsdasm.cpp b/src/devices/cpu/e132xs/32xsdasm.cpp deleted file mode 100644 index 286ef747dde..00000000000 --- a/src/devices/cpu/e132xs/32xsdasm.cpp +++ /dev/null @@ -1,1104 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Pierpaolo Prazzoli -/* - - Hyperstone disassembler - written by Pierpaolo Prazzoli - -*/ - -#include "emu.h" -#include "32xsdasm.h" -#include "32xsdefs.h" - - -namespace { - -const char *const L_REG[] = -{ - "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7", - "L8", "L9", "L10", "L11", "L12", "L13", "L14", "L15" -}; - -const char *const G_REG[] = -{ - "PC", "SR", "FER", "G03", "G04", "G05", "G06", "G07", - "G08", "G09", "G10", "G11", "G12", "G13", "G14", "G15", - "G16", "G17", "SP", "UB", "BCR", "TPR", "TCR", "TR", - "WCR", "ISR", "FCR", "MCR", "G28", "G29", "G30", "G31" -}; - -const char *const SETxx[] = -{ - "SETADR", nullptr, "SET1", "SET0", "SETLE", "SETGT", "SETLT", "SETGE", - "SETSE", "SETHT", "SETST", "SETHE", "SETE", "SETNE", "SETV", "SETNV", - nullptr, nullptr, "SET1M", nullptr, "SETLEM", "SETGTM", "SETLTM", "SETGEM", - "SETSEM", "SETTHM", "SETSTM", "SETHEM", "SETEM", "SETNEM", "SETVM", "SETNVM" -}; - -const char *const Fxxx[] = -{ - "FADD", "FADDD", "FSUB", "FSUBD", "FMUL", "FMULD", "FDIV", "FDIVD", - "FCMP", "FCMPD", "FCMPU", "FCMPUD", "FCVT", "FCVTD" -}; - -const char *const Bxx[] = -{ - "BV", "BNV", "BE", "BNE", "BC", "BNC", "BSE", "BHT", - "BN", "BNN", "BLE", "BGT", "BR" -}; - -const char *const TRAPxx[] = -{ - nullptr, nullptr, nullptr, nullptr, "TRAPLE", "TRAPGT", "TRAPLT", "TRAPGE", - "TRAPSE", "TRAPHT", "TRAPST", "TRAPHE", "TRAPE", "TRAPNE", "TRAPV", "TRAP" -}; - -#define DESTCODE(op) ((op & 0x00f0) >> 4) -#define SOURCECODE(op) (op & 0x000f) - -#define SOURCEBIT(op) ((op & 0x100) >> 8) -#define DESTBIT(op) ((op & 0x200) >> 9) - -#define DASM_N_VALUE(op) ((((op & 0x100) >> 8) << 4 ) | (op & 0x0f)) - - -void LL_format(std::string_view &source, std::string_view &dest, uint16_t op) -{ - source = L_REG[SOURCECODE(op)]; - dest = L_REG[DESTCODE(op)]; -} - -void LR_format(std::string_view &source, std::string_view &dest, uint16_t op) -{ - if (SOURCEBIT(op)) - source = L_REG[SOURCECODE(op)]; - else - source = G_REG[SOURCECODE(op)]; - - dest = L_REG[DESTCODE(op)]; -} - -void RR_format(std::string_view &source, std::string_view &dest, uint16_t op, unsigned h_flag) -{ - if (SOURCEBIT(op)) - source = L_REG[SOURCECODE(op)]; - else - source = G_REG[SOURCECODE(op) + h_flag * 16]; - - if (DESTBIT(op)) - dest = L_REG[DESTCODE(op)]; - else - dest = G_REG[DESTCODE(op) + h_flag * 16]; -} - -uint8_t Ln_format(std::string_view &dest, uint16_t op) -{ - dest = L_REG[DESTCODE(op)]; - - return DASM_N_VALUE(op); -} - -uint8_t Rn_format(std::string_view &dest, uint16_t op) -{ - if (DESTBIT(op)) - dest = L_REG[DESTCODE(op)]; - else - dest = G_REG[DESTCODE(op)]; - - return DASM_N_VALUE(op); -} - - -void format_addsub( - std::ostream &stream, - std::string_view inst, - std::string_view dest, - std::string_view source, - uint8_t source_bit, - uint8_t source_code) -{ - util::stream_format(stream, "%-7s %s, %s", - inst, - dest, - (!source_bit && (source_code == SR_REGISTER)) ? "C" : source); -} - -} // anonymous namespace - - - -uint32_t hyperstone_disassembler::LRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, const data_buffer &opcodes) -{ - uint16_t next_op; - uint32_t const_val; - - if (SOURCEBIT(op)) - source = L_REG[SOURCECODE(op)]; - else - source = G_REG[SOURCECODE(op)]; - - dest = L_REG[DESTCODE(op)]; - - size = 4; - - pc += 2; - next_op = opcodes.r16(pc); - - if (E_BIT(next_op)) - { - uint16_t next_op2; - - size = 6; - - pc += 2; - next_op2 = opcodes.r16(pc); - const_val = next_op2; - const_val |= ((next_op & 0x3fff) << 16 ); - - if (S_BIT_CONST(next_op)) - const_val |= 0xc0000000; - } - else - { - const_val = next_op & 0x3fff; - - if (S_BIT_CONST(next_op)) - const_val |= 0xffffc000; - } - - return const_val; -} - -uint32_t hyperstone_disassembler::RRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, const data_buffer &opcodes) -{ - uint16_t next_op; - uint32_t const_val; - - if (SOURCEBIT(op)) - source = L_REG[SOURCECODE(op)]; - else - source = G_REG[SOURCECODE(op)]; - - if (DESTBIT(op)) - dest = L_REG[DESTCODE(op)]; - else - dest = G_REG[DESTCODE(op)]; - - size = 4; - - pc += 2; - next_op = opcodes.r16(pc); - - if (E_BIT(next_op)) - { - uint16_t next_op2; - - size = 6; - - pc += 2; - next_op2 = opcodes.r16(pc); - const_val = next_op2; - const_val |= ((next_op & 0x3fff) << 16 ); - - if (S_BIT_CONST(next_op)) - { - const_val |= 0xc0000000; - } - } - else - { - const_val = next_op & 0x3fff; - - if (S_BIT_CONST(next_op)) - const_val |= 0xffffc000; - } - - return const_val; -} - -int32_t hyperstone_disassembler::Rimm_format(std::string_view &dest, uint16_t op, offs_t pc, const data_buffer &opcodes, unsigned h_flag) -{ - uint16_t imm1, imm2; - int32_t ret; - - int n = DASM_N_VALUE(op); - - if (DESTBIT(op)) - dest = L_REG[DESTCODE(op)]; - else - dest = G_REG[DESTCODE(op) + h_flag * 16]; - - switch (n) - { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: - case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: - return n; - - case 17: - pc += 2; - imm1 = opcodes.r16(pc); - pc += 2; - imm2 = opcodes.r16(pc); - ret = (imm1 << 16) | imm2; - - size = 6; - return ret; - - - case 18: - pc += 2; - ret = opcodes.r16(pc); - - size = 4; - return ret; - - case 19: - pc += 2; - ret = (int32_t) (0xffff0000 | opcodes.r16(pc)); - - size = 4; - return ret; - - case 20: - return 32; //bit 5 = 1, others = 0 - - case 21: - return 64; //bit 6 = 1, others = 0 - - case 22: - return 128; //bit 7 = 1, others = 0 - - case 23: - return 0x80000000; //bit 31 = 1, others = 0 (2 at the power of 31) - - case 24: - return -8; - - case 25: - return -7; - - case 26: - return -6; - - case 27: - return -5; - - case 28: - return -4; - - case 29: - return -3; - - case 30: - return -2; - - case 31: - return -1; - - default: - return 0; //should never goes here - } -} - -int32_t hyperstone_disassembler::PCrel_format(uint16_t op, offs_t pc, const data_buffer &opcodes) -{ - int32_t ret; - - if( op & 0x80 ) //bit 7 = 1 - { - uint16_t next; - - size = 4; - - pc += 2; - - next = opcodes.r16(pc); - - ret = (op & 0x7f) << 16; - - ret |= (next & 0xfffe); - - if( next & 1 ) - ret |= 0xff800000; //ok? - } - else - { - ret = op & 0x7e; - - if( op & 1 ) - ret |= 0xffffff80; //ok? - } - - return (pc + ret); -} - -uint32_t hyperstone_disassembler::RRdis_format(std::string_view &source, std::string_view &dest, uint16_t op, uint16_t next_op, offs_t pc, const data_buffer &opcodes) -{ - uint32_t ret; - - if (SOURCEBIT(op)) - source = L_REG[SOURCECODE(op)]; - else - source = G_REG[SOURCECODE(op)]; - - if (DESTBIT(op)) - dest = L_REG[DESTCODE(op)]; - else - dest = G_REG[DESTCODE(op)]; - - if (E_BIT(next_op)) - { - uint16_t next; - - size = 6; - - next = opcodes.r16(pc + 4); - - ret = next; - ret |= ( ( next_op & 0xfff ) << 16 ); - - if( S_BIT_CONST(next_op) ) - { - ret |= 0xf0000000; - } - } - else - { - ret = next_op & 0xfff; - if( S_BIT_CONST(next_op) ) - { - ret |= 0xfffff000; - } - } - - return ret; -} - -u32 hyperstone_disassembler::opcode_alignment() const -{ - return 2; -} - -hyperstone_disassembler::hyperstone_disassembler(config *conf) : m_config(conf) -{ -} - -/*****************************/ -/* Main disassembly function */ -/*****************************/ -offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) -{ - std::string_view source, dest; - uint32_t flags = 0; - - const uint16_t op = opcodes.r16(pc); - - size = 2; - - const uint8_t source_code = SOURCECODE(op); - const uint8_t dest_code = DESTCODE(op); - const uint8_t source_bit = SOURCEBIT(op); - const uint8_t dest_bit = DESTBIT(op); - - const int h_flag = m_config->get_h(); - - const uint8_t op_num = (op & 0xff00) >> 8; - - switch (op_num) - { - // CHK - CHKZ - NOP - case 0x00: case 0x01: case 0x02: case 0x03: - if (source_bit && dest_bit && !source_code && !dest_code) - { - util::stream_format(stream, "NOP"); - } - else - { - RR_format(source, dest, op, 0); - if (!source_bit && (source_code == SR_REGISTER)) - util::stream_format(stream, "CHKZ %s, 0", dest); - else - util::stream_format(stream, "CHK %s, %s", dest, source); - } - break; - - // MOVD - RET - case 0x04: case 0x05: case 0x06: case 0x07: - RR_format(source, dest, op, 0); - - if (!dest_bit && (dest_code == PC_REGISTER)) - { - if (!source_bit && ((source_code == PC_REGISTER) || (source_code == SR_REGISTER))) - { - // RET with PC or SR as source is reserved for future expansion - util::stream_format(stream, "D.HU $%04x", op); - } - else - { - RR_format(source, dest, op, 0); - util::stream_format(stream, "RET PC, %s", source); - flags = STEP_OUT; - } - } - else if (!source_bit && (source_code == SR_REGISTER)) - { - util::stream_format(stream, "MOVD %s, 0", dest); - } - else - { - util::stream_format(stream, "MOVD %s, %s", dest, source); - } - break; - - case 0x08: case 0x09: case 0x0a: case 0x0b: // DIVU - case 0x0c: case 0x0d: case 0x0e: case 0x0f: // DIVS - RR_format(source, dest, op, 0); - util::stream_format(stream, "DIV%c %s, %s", (op_num & 0x4) ? 'S' : 'U', dest, source); - break; - - // XMx - XXx - case 0x10: case 0x11: case 0x12: case 0x13: - { - RR_format(source, dest, op, 0); - - size = 4; - - pc += 2; - const uint16_t ilm1 = opcodes.r16(pc); - - const int xcode = X_CODE(ilm1); - - if (xcode < 4) - { - uint16_t lim; - - if (E_BIT(ilm1)) - { - size = 6; - - pc += 2; - const uint16_t ilm2 = opcodes.r16(pc); - - lim = ((ilm1 & 0xfff) << 16) | ilm2; - } - else - { - lim = ilm1 & 0xfff; - } - - util::stream_format(stream, "XM%x %s, %s, $%x", 1 << xcode, dest, source, lim); - } - else - { - util::stream_format(stream, "XX%x %s, %s, 0", 1 << (xcode & 0x3), dest, source); - } - } - break; - - // MASK - case 0x14: case 0x15: case 0x16: case 0x17: - { - const uint32_t const_val = RRconst_format(source, dest, op, pc, opcodes); - util::stream_format(stream, "MASK %s, %s, $%x", dest, source, const_val); - if (!source_bit && (source_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t((pc + size) & const_val)); - } - break; - - case 0x18: case 0x19: case 0x1a: case 0x1b: // SUM - case 0x1c: case 0x1d: case 0x1e: case 0x1f: // SUMS - { - const uint32_t const_val = RRconst_format(source, dest, op, pc, opcodes); - util::stream_format(stream, "SUM%c %s, %s, $%x", - (op_num & 0x4) ? 'S' : ' ', - dest, - (!source_bit && (source_code == SR_REGISTER)) ? "C" : source, - const_val); - if (!source_bit && (source_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + const_val)); - } - break; - - // CMP - case 0x20: case 0x21: case 0x22: case 0x23: - RR_format(source, dest, op, 0); - format_addsub(stream, "CMP", dest, source, source_bit, source_code); - break; - - // MOV - case 0x24: case 0x25: case 0x26: case 0x27: - RR_format(source, dest, op, h_flag); - util::stream_format(stream, "MOV %s, %s", dest, source); - break; - - case 0x28: case 0x29: case 0x2a: case 0x2b: // ADD - case 0x2c: case 0x2d: case 0x2e: case 0x2f: // ADDS - RR_format(source, dest, op, 0); - format_addsub(stream, (op_num & 0x4) ? "ADDS" : "ADD", dest, source, source_bit, source_code); - break; - - // CMPB - case 0x30: case 0x31: case 0x32: case 0x33: - RR_format(source, dest, op, 0); - util::stream_format(stream, "CMPB %s, %s", dest, source); - break; - - // ANDN - case 0x34: case 0x35: case 0x36: case 0x37: - RR_format(source, dest, op, 0); - util::stream_format(stream, "ANDN %s, %s", dest, source); - break; - - // OR - case 0x38: case 0x39: case 0x3a: case 0x3b: - RR_format(source, dest, op, 0); - util::stream_format(stream, "OR %s, %s", dest, source); - break; - - // XOR - case 0x3c: case 0x3d: case 0x3e: case 0x3f: - RR_format(source, dest, op, 0); - util::stream_format(stream, "XOR %s, %s", dest, source); - break; - - // SUBC - case 0x40: case 0x41: case 0x42: case 0x43: - RR_format(source, dest, op, 0); - format_addsub(stream, "SUBC", dest, source, source_bit, source_code); - break; - - // NOT - case 0x44: case 0x45: case 0x46: case 0x47: - RR_format(source, dest, op, 0); - util::stream_format(stream, "NOT %s, %s", dest, source); - break; - - case 0x48: case 0x49: case 0x4a: case 0x4b: // SUB - case 0x4c: case 0x4d: case 0x4e: case 0x4f: // SUBS - RR_format(source, dest, op, 0); - format_addsub(stream, (op_num & 0x4) ? "SUBS" : "SUB", dest, source, source_bit, source_code); - break; - - // ADDC - case 0x50: case 0x51: case 0x52: case 0x53: - RR_format(source, dest, op, 0); - format_addsub(stream, "ADDC", dest, source, source_bit, source_code); - break; - - // AND - case 0x54: case 0x55: case 0x56: case 0x57: - RR_format(source, dest, op, 0); - util::stream_format(stream, "AND %s, %s", dest, source); - break; - - case 0x58: case 0x59: case 0x5a: case 0x5b: // NEG - case 0x5c: case 0x5d: case 0x5e: case 0x5f: // NEGS - RR_format(source, dest, op, 0); - format_addsub(stream, (op_num & 0x4) ? "NEGS" : "NEG", dest, source, source_bit, source_code); - break; - - // CMPI - case 0x60: case 0x61: case 0x62: case 0x63: - { - const uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0); - util::stream_format(stream, "CMPI %s, $%x", dest, imm); - } - break; - - // MOVI - case 0x64: case 0x65: case 0x66: case 0x67: - { - const uint32_t imm = Rimm_format(dest, op, pc, opcodes, h_flag); - util::stream_format(stream, "MOVI %s, $%x", dest, imm); - } - break; - - case 0x68: case 0x69: case 0x6a: case 0x6b: // ADDI - case 0x6c: case 0x6d: case 0x6e: case 0x6f: // ADDSI - if (!DASM_N_VALUE(op)) - { - util::stream_format(stream, "%-7s %s, CZ", (op_num & 0x4) ? "ADDSI" : "ADDI", dest); - } - else - { - const uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0); - util::stream_format(stream, "%-7s %s, $%x", (op_num & 0x4) ? "ADDSI" : "ADDI", dest, imm); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + imm)); - } - break; - - // CMPBI - case 0x70: case 0x71: case 0x72: case 0x73: - if (!DASM_N_VALUE(op)) - { - util::stream_format(stream, "CMPBI %s, ANYBZ", dest); - } - else - { - uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0); - if (DASM_N_VALUE(op) == 31) - imm = 0x7fffffff; //bit 31 = 0, others = 1 - - util::stream_format(stream, "CMPBI %s, $%x", dest, imm); - } - break; - - // ANDNI - case 0x74: case 0x75: case 0x76: case 0x77: - { - uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0); - if (DASM_N_VALUE(op) == 31) - imm = 0x7fffffff; //bit 31 = 0, others = 1 - - util::stream_format(stream, "ANDNI %s, $%x", dest, imm); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t((pc + size) & ~imm)); - } - break; - - // ORI - case 0x78: case 0x79: case 0x7a: case 0x7b: - { - const uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0); - - util::stream_format(stream, "ORI %s, $%x", dest, imm); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t((pc + size) | imm)); - } - break; - - // XORI - case 0x7c: case 0x7d: case 0x7e: case 0x7f: - { - const uint32_t imm = Rimm_format(dest, op, pc, opcodes, 0); - - util::stream_format(stream, "XORI %s, $%x", dest, imm); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t((pc + size) ^ imm)); - } - break; - - case 0x80: case 0x81: // SHRDI - case 0x84: case 0x85: // SARDI - { - const uint8_t n = Ln_format(dest, op); - util::stream_format(stream, "S%cRDI %s, $%x", (op_num & 0x4) ? 'A' : 'H', dest, n); - } - break; - - case 0x82: // SHRD - case 0x83: // SHR - case 0x86: // SARD - case 0x87: // SAR - LL_format(source, dest, op); - util::stream_format(stream, "S%cR%c %s, %s", - (op_num & 0x4) ? 'A' : 'H', - (op_num & 0x1) ? ' ' : 'D', - dest, - source); - break; - - // SHLDI - case 0x88: case 0x89: - { - const uint8_t n = Ln_format(dest, op); - util::stream_format(stream, "SHLDI %s, $%x", dest, n); - } - break; - - case 0x8a: // SHLD - case 0x8b: // SHL - LL_format(source, dest, op); - util::stream_format(stream, "SHL%c %s, %s", (op_num & 0x1) ? ' ' : 'D', dest, source); - break; - - // RESERVED - case 0x8c: case 0x8d: - case 0xac: case 0xad: case 0xae: case 0xaf: - util::stream_format(stream, "D.HU $%04x", op); - break; - - // TESTLZ - case 0x8e: - LL_format(source, dest, op); - util::stream_format(stream, "TESTLZ %s, %s", dest, source); - break; - - // ROL - case 0x8f: - LL_format(source, dest, op); - util::stream_format(stream, "ROL %s, %s", dest, source); - break; - - case 0x90: case 0x91: case 0x92: case 0x93: // LDxx.D/A/IOD/IOA - case 0x98: case 0x99: case 0x9a: case 0x9b: // STxx.D/A/IOD/IOA - { - const uint16_t next_op = opcodes.r16(pc + 2); - const uint32_t dis = RRdis_format(source, dest, op, next_op, pc, opcodes); - - if (size == 2) - size = 4; - - if ((op_num & 0x8) && !source_bit && (source_code == SR_REGISTER)) - source = "0"; - - if (!dest_bit && (dest_code == SR_REGISTER)) - dest = "0"; - - const std::string_view inst = (op_num & 0x8) ? "ST" : "LD"; - const char mode = (!dest_bit && (dest_code == SR_REGISTER)) ? 'A' : 'D'; - - switch (DD(next_op)) - { - case 0: - // LD/STBS.D/A - util::stream_format(stream, "%sBS.%c %s, %s, $%x", inst, mode, dest, source, dis); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + dis)); - break; - - case 1: - // LD/STBU.D/A - util::stream_format(stream, "%sBU.%c %s, %s, $%x", inst, mode, dest, source, dis); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + dis)); - break; - - case 2: - // LD/STHU.D/A - // LD/STHS.D/A - util::stream_format(stream, "%sH%c.%c %s, %s, $%x", inst, (dis & 1) ? 'S' : 'U', mode, dest, source, dis & ~1); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~1)) & ~1); - break; - - case 3: - if (dis & 2) - { - // LD/STW.IOD/A - // LD/STD.IOD/A - util::stream_format(stream, "%s%c.IO%c %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', mode, dest, source, dis & ~3); - } - else - { - // LD/STW.D/A - // LD/STD.D/A - util::stream_format(stream, "%s%c.%c %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', mode, dest, source, dis & ~3); - } - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~3)) & ~3); - break; - } - } - break; - - case 0x94: case 0x95: case 0x96: case 0x97: // LDxx.N/S - case 0x9c: case 0x9d: case 0x9e: case 0x9f: // STxx.N/S - { - const uint16_t next_op = opcodes.r16(pc + 2); - const uint32_t dis = RRdis_format(source, dest, op, next_op, pc, opcodes); - - if (size == 2) - size = 4; - - if (!dest_bit && ((dest_code == PC_REGISTER) || (dest_code == SR_REGISTER))) - { - util::stream_format(stream, "Reserved"); - break; - } - - if ((op_num & 0x8) && !source_bit && (source_code == SR_REGISTER)) - source = "0"; - - const std::string_view inst = (op_num & 0x8) ? "ST" : "LD"; - - switch (DD(next_op)) - { - case 0: - // LD/STBS.N - util::stream_format(stream, "%sBS.N %s, %s, $%x", inst, dest, source, dis); - break; - - case 1: - // LD/STBU.N - util::stream_format(stream, "%sBU.N %s, %s, $%x", inst, dest, source, dis); - break; - - case 2: - // LD/STHU.N - // LD/STHS.N - util::stream_format(stream, "%sH%c.N %s, %s, $%x", inst, (dis & 1) ? 'S' : 'U', dest, source, dis & ~1); - break; - - case 3: - if ((dis & 3) == 3) - { - // LD/STW.S - util::stream_format(stream, "%sW.S %s, %s, $%x", inst, dest, source, dis & ~3); - } - else if ((dis & 3) == 2) - { - // Reserved - util::stream_format(stream, "Reserved"); - } - else - { - // LD/STW.N - // LD/STD.N - util::stream_format(stream, "%s%c.N %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', dest, source, dis & ~3); - } - break; - } - } - break; - - case 0xa0: case 0xa1: case 0xa2: case 0xa3: // SHRI - case 0xa4: case 0xa5: case 0xa6: case 0xa7: // SARI - { - const uint8_t n = Rn_format(dest, op); - util::stream_format(stream, "S%cRI %s, $%x", (op_num & 0x4) ? 'A' : 'H', dest, n); - } - break; - - // SHLI - case 0xa8: case 0xa9: case 0xaa: case 0xab: - { - const uint8_t n = Rn_format(dest, op); - util::stream_format(stream, "SHLI %s, $%x", dest, n); - } - break; - - case 0xb0: case 0xb1: case 0xb2: case 0xb3: // MULU - case 0xb4: case 0xb5: case 0xb6: case 0xb7: // MULS - RR_format(source, dest, op, 0); - util::stream_format(stream, "MUL%c %s, %s", (op_num & 0x4) ? 'S' : 'U', dest, source); - break; - - // SETxx - SETADR - FETCH - case 0xb8: case 0xb9: case 0xba: case 0xbb: - { - const uint8_t n = Rn_format(dest, op); - - if (!dest_bit && (dest_code == PC_REGISTER)) - { - // SETxx with PC as destination is reserved for future use - util::stream_format(stream, "D.HU $%04x", op); - } - else if (!dest_bit && (dest_code == SR_REGISTER)) - { - util::stream_format(stream, "FETCH $%x", (n / 2) + 1); - } - else - { - char const *const inst = SETxx[n]; - if (inst) - util::stream_format(stream, "%-7s %s", inst, dest); - else - util::stream_format(stream, "D.HU $%04x", op); - } - } - break; - - // MUL - case 0xbc: case 0xbd: case 0xbe: case 0xbf: - RR_format(source, dest, op, 0); - util::stream_format(stream, "MUL %s, %s", dest, source); - break; - - case 0xc0: // FADD - case 0xc1: // FADDD - case 0xc2: // FSUB - case 0xc3: // FSUBD - case 0xc4: // FMUL - case 0xc5: // FMULD - case 0xc6: // FDIV - case 0xc7: // FDIVD - case 0xc8: // FCMP - case 0xc9: // FCMPD - case 0xca: // FCMPU - case 0xcb: // FCMPUD - case 0xcc: // FCVT - case 0xcd: // FCVTD - LL_format(source, dest, op); - util::stream_format(stream, "%-7s %s, %s", Fxxx[op_num & 0xf], dest, source); - break; - - // EXTEND - case 0xce: - { - LL_format(source, dest, op); - - pc += 2; - const uint16_t extended_op = opcodes.r16(pc); - - size = 4; - - switch (extended_op) - { - case 0x100: - case EMUL: - util::stream_format(stream, "EMUL %s, %s", dest, source); - break; - - case EMULU: - util::stream_format(stream, "EMULU %s, %s", dest, source); - break; - - case EMULS: - util::stream_format(stream, "EMULS %s, %s", dest, source); - break; - - case EMAC: - util::stream_format(stream, "EMAC %s, %s", dest, source); - break; - - case EMACD: - util::stream_format(stream, "EMACD %s, %s", dest, source); - break; - - case EMSUB: - util::stream_format(stream, "EMSUB %s, %s", dest, source); - break; - - case EMSUBD: - util::stream_format(stream, "EMSUBD %s, %s", dest, source); - break; - - case EHMAC: - util::stream_format(stream, "EHMAC %s, %s", dest, source); - break; - - case EHMACD: - util::stream_format(stream, "EHMACD %s, %s", dest, source); - break; - - case EHCMULD: - util::stream_format(stream, "EHCMULD %s, %s", dest, source); - break; - - case EHCMACD: - util::stream_format(stream, "EHCMACD %s, %s", dest, source); - break; - - case EHCSUMD: - util::stream_format(stream, "EHCSUMD %s, %s", dest, source); - break; - - case EHCFFTD: - util::stream_format(stream, "EHCFFTD %s, %s", dest, source); - break; - - case EHCFFTSD: - util::stream_format(stream, "EHCFFTSD %s, %s", dest, source); - break; - - default: - util::stream_format(stream, "Ext. OP $%X @ %X", extended_op, pc); - osd_printf_verbose("Illegal Extended Opcode: %X @ %X\n", extended_op, pc); - break; - } - } - break; - - // DO - case 0xcf: - LL_format(source, dest, op); - util::stream_format(stream, "DO %s, %s", dest, source); - break; - - case 0xd0: case 0xd1: // LDW.R - case 0xd2: case 0xd3: // LDD.R - case 0xd4: case 0xd5: // LDW.P - case 0xd6: case 0xd7: // LDD.P - case 0xd8: case 0xd9: // STW.R - case 0xda: case 0xdb: // STD.R - case 0xdc: case 0xdd: // STW.P - case 0xde: case 0xdf: // STD.P - LR_format(source, dest, op); - util::stream_format(stream, "%s%c.%c %s, %s", - (op_num & 0x8) ? "ST" : "LD", - (op_num & 0x2) ? 'D' : 'W', - (op_num & 0x4) ? 'P' : 'R', - dest, - ((op_num & 0x8) && !source_bit && (source_code == SR_REGISTER)) ? "0" : source); - break; - - case 0xe0: // DBV - case 0xe1: // DBNV - case 0xe2: // DBE - case 0xe3: // DBNE - case 0xe4: // DBC - case 0xe5: // DBNC - case 0xe6: // DBSE - case 0xe7: // DBHT - case 0xe8: // DBN - case 0xe9: // DBNN - case 0xea: // DBLE - case 0xeb: // DBGT - case 0xec: // DBR - { - const int32_t rel = PCrel_format(op, pc, opcodes) + 2; - util::stream_format(stream, "D%-6s $%x", Bxx[op_num & 0xf], rel); - if (op_num != 0xec) - flags = STEP_COND | step_over_extra(1); - } - break; - - // FRAME - case 0xed: - LL_format(source, dest, op); - util::stream_format(stream, "FRAME %s, %s", dest, source); - break; - - // CALL - case 0xee: case 0xef: - { - const uint32_t const_val = LRconst_format(source, dest, op, pc, opcodes); - - util::stream_format(stream, "CALL %s, %s, $%x", dest, (!source_bit && (source_code == SR_REGISTER)) ? "0" : source, const_val); - if (!source_bit && (source_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + const_val)); - flags = STEP_OVER; - } - break; - - case 0xf0: // BV - case 0xf1: // BNV - case 0xf2: // BE - case 0xf3: // BNE - case 0xf4: // BC - case 0xf5: // BNC - case 0xf6: // BSE - case 0xf7: // BHT - case 0xf8: // BN - case 0xf9: // BNN - case 0xfa: // BLE - case 0xfb: // BGT - case 0xfc: // BR - { - const int32_t rel = PCrel_format(op, pc, opcodes) + 2; - util::stream_format(stream, "%-7s $%x", Bxx[op_num & 0xf], rel); - if (op_num != 0xfc) - flags = STEP_COND; - } - break; - - // TRAPxx - TRAP - case 0xfd: case 0xfe: case 0xff: - { - const uint8_t code = ((op & 0x300) >> 6) | (op & 0x03); - const uint8_t trapno = (op & 0xfc) >> 2; - - util::stream_format(stream, "%-7s %d", TRAPxx[code], trapno); - if (code == TRAP) - flags = STEP_OVER; - else - flags = STEP_OVER | STEP_COND; - } - break; - } - - return size | flags | SUPPORTED; -} diff --git a/src/devices/cpu/e132xs/32xsdasm.h b/src/devices/cpu/e132xs/32xsdasm.h deleted file mode 100644 index 32f9c6df587..00000000000 --- a/src/devices/cpu/e132xs/32xsdasm.h +++ /dev/null @@ -1,46 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Pierpaolo Prazzoli -/* - - Hyperstone disassembler - written by Pierpaolo Prazzoli - -*/ - -#ifndef MAME_CPU_E132XS_32XSDASM_H -#define MAME_CPU_E132XS_32XSDASM_H - -#pragma once - -#include - - -class hyperstone_disassembler : public util::disasm_interface -{ -public: - struct config - { - virtual ~config() = default; - - virtual bool get_h() const = 0; - }; - - hyperstone_disassembler(config *conf); - virtual ~hyperstone_disassembler() = default; - - virtual u32 opcode_alignment() const override; - virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; - -private: - config *m_config; - - int size; - - uint32_t LRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, const data_buffer &opcodes); - uint32_t RRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, const data_buffer &opcodes); - int32_t Rimm_format(std::string_view &dest, uint16_t op, offs_t pc, const data_buffer &opcodes, unsigned h_flag); - int32_t PCrel_format(uint16_t op, offs_t pc, const data_buffer &opcodes); - uint32_t RRdis_format(std::string_view &source, std::string_view &dest, uint16_t op, uint16_t next_op, offs_t pc, const data_buffer &opcodes); -}; - -#endif diff --git a/src/devices/cpu/e132xs/32xsdefs.h b/src/devices/cpu/e132xs/32xsdefs.h deleted file mode 100644 index 9dad4d780c5..00000000000 --- a/src/devices/cpu/e132xs/32xsdefs.h +++ /dev/null @@ -1,247 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Pierpaolo Prazzoli -#ifndef MAME_CPU_E132XS_32XSDEFS_H -#define MAME_CPU_E132XS_32XSDEFS_H - -#pragma once - -/*************************************************************************** - COMPILE-TIME DEFINITIONS -***************************************************************************/ - -// compilation boundaries -- how far back/forward does the analysis extend? -enum : u32 -{ - COMPILE_BACKWARDS_BYTES = 128, - COMPILE_FORWARDS_BYTES = 512, - COMPILE_MAX_INSTRUCTIONS = (COMPILE_BACKWARDS_BYTES / 2) + (COMPILE_FORWARDS_BYTES / 2), - COMPILE_MAX_SEQUENCE = 64 -}; - -enum -{ - PC_REGISTER = 0, - SR_REGISTER = 1, - FER_REGISTER = 2, - SP_REGISTER = 18, - UB_REGISTER = 19, - BCR_REGISTER = 20, - TPR_REGISTER = 21, - TCR_REGISTER = 22, - TR_REGISTER = 23, - WCR_REGISTER = 24, - ISR_REGISTER = 25, - FCR_REGISTER = 26, - MCR_REGISTER = 27 -}; - -#define X_CODE(val) ((val & 0x7000) >> 12) -#define E_BIT(val) ((val & 0x8000) >> 15) -#define S_BIT_CONST(val) ((val & 0x4000) >> 14) -#define DD(val) ((val & 0x3000) >> 12) - -#define S_BIT ((OP & 0x100) >> 8) -#define D_BIT ((OP & 0x200) >> 9) -#define N_VALUE (((OP & 0x100) >> 4) | (OP & 0x0f)) -#define HI_N_VALUE (0x10 | (OP & 0x0f)) -#define LO_N_VALUE (OP & 0x0f) -#define N_OP_MASK (m_op & 0x10f) -#define DRC_HI_N_VALUE (0x10 | (op & 0x0f)) -#define DRC_LO_N_VALUE (op & 0x0f) -#define DRC_N_OP_MASK (op & 0x10f) -#define DST_CODE ((OP & 0xf0) >> 4) -#define SRC_CODE (OP & 0x0f) -#define SIGN_BIT(val) ((val & 0x80000000) >> 31) -#define SIGN_TO_N(val) ((val & 0x80000000) >> 29) -#define SIGN64_TO_N(val) ((val & 0x8000000000000000ULL) >> 61) - -/* Extended DSP instructions */ -#define EHMAC 0x02a -#define EHMACD 0x02e -#define EHCMULD 0x046 -#define EHCMACD 0x04e -#define EHCSUMD 0x086 -#define EHCFFTD 0x096 -#define EMUL_N 0x100 -#define EMUL 0x102 -#define EMULU 0x104 -#define EMULS 0x106 -#define EMAC 0x10a -#define EMACD 0x10e -#define EMSUB 0x11a -#define EMSUBD 0x11e -#define EHCFFTSD 0x296 - -// IRQ numbers -enum -{ - IRQ_INT1 = 0, - IRQ_INT2 = 1, - IRQ_INT3 = 2, - IRQ_INT4 = 3, - IRQ_IO1 = 4, - IRQ_IO2 = 5, - IRQ_IO3 = 6 -}; - -// Trap numbers -enum -{ - TRAPNO_IO2 = 48, - TRAPNO_IO1 = 49, - TRAPNO_INT4 = 50, - TRAPNO_INT3 = 51, - TRAPNO_INT2 = 52, - TRAPNO_INT1 = 53, - TRAPNO_IO3 = 54, - TRAPNO_TIMER = 55, - TRAPNO_RESERVED1 = 56, - TRAPNO_TRACE_EXCEPTION = 57, - TRAPNO_PARITY_ERROR = 58, - TRAPNO_EXTENDED_OVERFLOW = 59, - TRAPNO_RANGE_ERROR = 60, - TRAPNO_POINTER_ERROR = TRAPNO_RANGE_ERROR, - TRAPNO_PRIVILEGE_ERROR = TRAPNO_RANGE_ERROR, - TRAPNO_FRAME_ERROR = TRAPNO_RANGE_ERROR, - TRAPNO_RESERVED2 = 61, - TRAPNO_RESET = 62, // reserved if not mapped @ MEM3 - TRAPNO_ERROR_ENTRY = 63 // for instruction code of all ones -}; - -/* Trap codes */ -#define TRAPLE 4 -#define TRAPGT 5 -#define TRAPLT 6 -#define TRAPGE 7 -#define TRAPSE 8 -#define TRAPHT 9 -#define TRAPST 10 -#define TRAPHE 11 -#define TRAPE 12 -#define TRAPNE 13 -#define TRAPV 14 -#define TRAP 15 - -/* Entry point to get trap locations or emulated code associated */ -#define E132XS_ENTRY_MEM0 0 -#define E132XS_ENTRY_MEM1 1 -#define E132XS_ENTRY_MEM2 2 -#define E132XS_ENTRY_IRAM 3 -#define E132XS_ENTRY_MEM3 7 - -/* Memory access */ -#define READ_B(addr) m_read_byte(addr) -#define READ_HW(addr) m_read_halfword(addr) -#define READ_W(addr) m_read_word(addr) - -#define WRITE_B(addr, data) m_write_byte(addr, data) -#define WRITE_HW(addr, data) m_write_halfword(addr, data) -#define WRITE_W(addr, data) m_write_word(addr, data) - - -/* I/O access */ -#define IO_READ_W(addr) m_read_io(addr) -#define IO_WRITE_W(addr, data) m_write_io(addr, data) - -// set C in adds/addsi/subs/sums -#define SETCARRYS 0 - -/* Registers */ - -/* Internal registers */ - -#define OP m_op -#define PC m_core->global_regs[0] //Program Counter -#define SR m_core->global_regs[1] //Status Register -#define FER m_core->global_regs[2] //Floating-Point Exception Register -// 03 - 15 General Purpose Registers -// 16 - 17 Reserved -#define SP m_core->global_regs[18] //Stack Pointer -#define UB m_core->global_regs[19] //Upper Stack Bound -#define BCR m_core->global_regs[20] //Bus Control Register -#define TPR m_core->global_regs[21] //Timer Prescaler Register -#define TCR m_core->global_regs[22] //Timer Compare Register -#define TR compute_tr() //Timer Register -#define WCR m_core->global_regs[24] //Watchdog Compare Register -#define ISR m_core->global_regs[25] //Input Status Register -#define FCR m_core->global_regs[26] //Function Control Register -#define MCR m_core->global_regs[27] //Memory Control Register -// 28 - 31 Reserved - -constexpr uint32_t C_MASK = 0x00000001; -constexpr uint32_t Z_MASK = 0x00000002; -constexpr uint32_t N_MASK = 0x00000004; -constexpr uint32_t V_MASK = 0x00000008; -constexpr uint32_t M_MASK = 0x00000010; -constexpr uint32_t H_MASK = 0x00000020; -constexpr uint32_t I_MASK = 0x00000080; -constexpr uint32_t L_MASK = 0x00008000; -constexpr uint32_t T_MASK = 0x00010000; -constexpr uint32_t P_MASK = 0x00020000; -constexpr uint32_t S_MASK = 0x00040000; -constexpr uint32_t ILC_MASK = 0x00180000; -constexpr uint32_t FL_MASK = 0x01e00000; -constexpr uint32_t FP_MASK = 0xfe000000; - -constexpr int C_SHIFT = 0; -constexpr int Z_SHIFT = 1; -constexpr int N_SHIFT = 2; -constexpr int V_SHIFT = 3; -constexpr int L_SHIFT = 15; -constexpr int T_SHIFT = 16; -constexpr int S_SHIFT = 18; -constexpr int ILC_SHIFT = 19; -constexpr int FL_SHIFT = 21; -constexpr int FP_SHIFT = 25; - -/* SR flags */ -#define GET_C ( SR & C_MASK) // bit 0 //CARRY -#define GET_Z ((SR & Z_MASK)>>1) // bit 1 //ZERO -#define GET_N ((SR & N_MASK)>>2) // bit 2 //NEGATIVE -#define GET_V ((SR & V_MASK)>>3) // bit 3 //OVERFLOW -#define GET_M ((SR & M_MASK)>>4) // bit 4 //CACHE-MODE -#define GET_H ((SR & H_MASK)>>5) // bit 5 //HIGHGLOBAL -// bit 6 RESERVED (always 0) -#define GET_I ((SR & I_MASK)>>7) // bit 7 //INTERRUPT-MODE -#define GET_FTE ((SR & 0x00001f00)>>8) // bits 12 - 8 //Floating-Point Trap Enable -#define GET_FRM ((SR & 0x00006000)>>13) // bits 14 - 13 //Floating-Point Rounding Mode -#define GET_L ((SR & L_MASK)>>15) // bit 15 //INTERRUPT-LOCK -#define GET_T ((SR & T_MASK)>>16) // bit 16 //TRACE-MODE -#define GET_P ((SR & P_MASK)>>17) // bit 17 //TRACE PENDING -#define GET_S ((SR & S_MASK)>>18) // bit 18 //SUPERVISOR STATE -#define GET_ILC ((SR & 0x00180000)>>19) // bits 20 - 19 //INSTRUCTION-LENGTH -/* if FL is zero it is always interpreted as 16 */ -#define GET_FL m_core->fl_lut[((SR >> 21) & 0xf)] // bits 24 - 21 //FRAME LENGTH -#define GET_FP ((SR & 0xfe000000)>>25) // bits 31 - 25 //FRAME POINTER - -#define SET_C(val) (SR = (SR & ~C_MASK) | (val)) -#define SET_Z(val) (SR = (SR & ~Z_MASK) | ((val) << 1)) -#define SET_N(val) (SR = (SR & ~N_MASK) | ((val) << 2)) -#define SET_V(val) (SR = (SR & ~V_MASK) | ((val) << 3)) -#define SET_M(val) (SR = (SR & ~M_MASK) | ((val) << 4)) -#define SET_H(val) (SR = (SR & ~H_MASK) | ((val) << 5)) -#define SET_I(val) (SR = (SR & ~I_MASK) | ((val) << 7)) -#define SET_FTE(val) (SR = (SR & ~0x00001f00) | ((val) << 8)) -#define SET_FRM(val) (SR = (SR & ~0x00006000) | ((val) << 13)) -#define SET_L(val) (SR = (SR & ~L_MASK) | ((val) << 15)) -#define SET_T(val) (SR = (SR & ~T_MASK) | ((val) << 16)) -#define SET_P(val) (SR = (SR & ~P_MASK) | ((val) << 17)) -#define SET_S(val) (SR = (SR & ~S_MASK) | ((val) << 18)) -#define SET_ILC(val) (SR = (SR & 0xffe7ffff) | (val)) -#define SET_FL(val) (SR = (SR & ~0x01e00000) | ((val) << 21)) -#define SET_FP(val) (SR = (SR & ~0xfe000000) | ((val) << 25)) - -#define SET_PC(val) PC = ((val) & 0xfffffffe) //PC(0) = 0 -#define SET_SP(val) SP = ((val) & 0xfffffffc) //SP(0) = SP(1) = 0 -#define SET_UB(val) UB = ((val) & 0xfffffffc) //UB(0) = UB(1) = 0 - -#define SET_LOW_SR(val) (SR = (SR & 0xffff0000) | ((val) & 0x0000ffff)) // when SR is addressed, only low 16 bits can be changed - - -/* FER flags */ -#define GET_ACCRUED (FER & 0x0000001f) //bits 4 - 0 //Floating-Point Accrued Exceptions -#define GET_ACTUAL (FER & 0x00001f00) //bits 12 - 8 //Floating-Point Actual Exceptions -//other bits are reversed, in particular 7 - 5 for the operating system. -//the user program can only change the above 2 flags - -#endif // MAME_CPU_E132XS_32XSDEFS_H diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp index 6d4b1792552..34117a70486 100644 --- a/src/devices/cpu/e132xs/e132xs.cpp +++ b/src/devices/cpu/e132xs/e132xs.cpp @@ -1,7 +1,7 @@ // license:BSD-3-Clause // copyright-holders:Pierpaolo Prazzoli /******************************************************************** - Hyperstone cpu emulator + Hyperstone E1 CPU emulator written by Pierpaolo Prazzoli Hyperstone models: @@ -91,9 +91,9 @@ #include "emu.h" #include "e132xs.h" -#include "e132xsfe.h" -#include "32xsdefs.h" +#include "e1defs.h" +#include "e1fe.h" #include "emuopts.h" @@ -160,6 +160,7 @@ hyperstone_device::hyperstone_device( : cpu_device(mconfig, type, tag, owner, clock) , m_program_config("program", ENDIANNESS_BIG, prg_data_width, 32, 0, internal_map) , m_io_config("io", ENDIANNESS_BIG, io_data_width, io_addr_bits, (io_data_width == 16) ? -1 : -2) + , m_disassembler(nullptr) // for logging - pass nullptr so output doesn't depend on state , m_cache(CACHE_SIZE + sizeof(internal_hyperstone_state)) , m_drcuml(nullptr) , m_drcfe(nullptr) diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index 55bf264f8ac..ba78ff17272 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -5,7 +5,7 @@ #pragma once -#include "32xsdasm.h" +#include "e1dasm.h" #include "cpu/drcuml.h" @@ -439,6 +439,7 @@ private: FILE *m_trace_log; #endif + hyperstone_disassembler m_disassembler; drc_cache m_cache; std::unique_ptr m_drcuml; std::unique_ptr m_drcfe; @@ -477,6 +478,7 @@ private: void flush_drc_cache(); void generate_invariant(); void code_compile_block(uint8_t mode, offs_t pc); + void log_descriptions(const opcode_desc *desc_list, unsigned indent); //void load_fast_iregs(drcuml_block &block); //void save_fast_iregs(drcuml_block &block); void static_generate_helpers(drcuml_block &block, uml::code_label &label); diff --git a/src/devices/cpu/e132xs/e132xsdrc.cpp b/src/devices/cpu/e132xs/e132xsdrc.cpp index 88b7bdc11fa..c3bb9fb22d2 100644 --- a/src/devices/cpu/e132xs/e132xsdrc.cpp +++ b/src/devices/cpu/e132xs/e132xsdrc.cpp @@ -4,13 +4,17 @@ #include "emu.h" #include "e132xs.h" -#include "32xsdefs.h" -#include "e132xsfe.h" +#include "e1defs.h" +#include "e1fe.h" #include "cpu/drcumlsh.h" +#include "util/vecstream.h" -/* map variables */ +#include + + +// map variables #define MAPVAR_PC M0 #define MAPVAR_CYCLES M1 @@ -266,8 +270,10 @@ void hyperstone_device::code_compile_block(uint8_t mode, offs_t pc) auto profile = g_profiler.start(PROFILER_DRC_COMPILE); - /* get a description of this sequence */ + // describe a sequence of instructions const opcode_desc *desclist = m_drcfe->describe_code(pc); + if (m_drcuml->logging()) + log_descriptions(desclist, 0); bool succeeded = false; while (!succeeded) @@ -352,6 +358,60 @@ void hyperstone_device::code_compile_block(uint8_t mode, offs_t pc) } } +void hyperstone_device::log_descriptions(const opcode_desc *desc_list, unsigned indent) +{ + util::ovectorstream buffer; + buffer.imbue(std::locale::classic()); + + // assume no indent is the start of a sequence and needs a heading + if (!indent) + m_drcuml->log_printf("\nDescriptor list @ %08X\n", desc_list->pc); + + for ( ; desc_list; desc_list = desc_list->next()) + { + buffer.clear(); + buffer.seekp(0); + desc_list->log_flags(buffer); + buffer.put('\0'); + + m_drcuml->log_printf("%08X t:%08X f:%s: ", desc_list->pc, desc_list->targetpc, &buffer.vec()[0]); + + // disassemble the current instruction and output it to the log + buffer.clear(); + buffer.seekp(0); + util::stream_format(buffer, "%*s", 4 * indent, ""); + if (desc_list->virtual_noop()) + buffer << ""; + else + m_disassembler.disassemble_one(buffer, desc_list->pc, desc_list->opptr); + buffer.put('\0'); + m_drcuml->log_printf("%-36s", &buffer.vec()[0]); + + // output register dependencies + buffer.clear(); + buffer.seekp(0); + if (!desc_list->regin.none()) + { + desc_list->log_registers_used(buffer); + if (!desc_list->regout.none()) + buffer << ' '; + } + if (!desc_list->regout.none()) + desc_list->log_registers_modified(buffer); + buffer.put('\0'); + m_drcuml->log_printf("%s\n", &buffer.vec()[0]); + + // if we have a delay slot, output it recursively + if (desc_list->delay.first()) + log_descriptions(desc_list->delay.first(), indent + 1); + + // at the end of a sequence add a dividing line + if (desc_list->end_sequence()) + m_drcuml->log_printf("-----\n"); + } +} + + /*************************************************************************** STATIC CODEGEN ***************************************************************************/ diff --git a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx index 7131bdba505..af0795bea2b 100644 --- a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx +++ b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx @@ -3873,7 +3873,6 @@ void hyperstone_device::generate_call(drcuml_block &block, compiler_state &compi dst_code = 16; UML_BFXU(block, I3, DRC_SR, FP_SHIFT, 7); - UML_MOV(block, I1, desc->imm); if (SrcGlobal) { diff --git a/src/devices/cpu/e132xs/e132xsfe.cpp b/src/devices/cpu/e132xs/e132xsfe.cpp deleted file mode 100644 index 1eb0de91382..00000000000 --- a/src/devices/cpu/e132xs/e132xsfe.cpp +++ /dev/null @@ -1,1027 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Vas Crabb -/*************************************************************************** - - e132xsfe.cpp - - Hyperstone E1 instruction decoder - -***************************************************************************/ - -#include "emu.h" -#include "e132xsfe.h" - -#include "32xsdefs.h" - -#include "cpu/drcfe.ipp" - - - -hyperstone_device::frontend::frontend(hyperstone_device &cpu, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend_base(cpu.space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) - , m_cpu(cpu) -{ -} - -hyperstone_device::frontend::~frontend() -{ -} - -hyperstone_device::opcode_desc const *hyperstone_device::frontend::describe_code(offs_t startpc) -{ - return do_describe_code( - [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, - startpc); -} - - -inline void hyperstone_device::frontend::read_op(opcode_desc &desc) -{ - desc.opptr[0] = m_cpu.m_pr16(desc.pc); -} - -inline void hyperstone_device::frontend::read_imm1(opcode_desc &desc) -{ - desc.opptr[1] = m_cpu.m_pr16(desc.pc + 2); -} - -inline void hyperstone_device::frontend::read_imm2(opcode_desc &desc) -{ - desc.opptr[2] = m_cpu.m_pr16(desc.pc + 4); -} - -inline void hyperstone_device::frontend::decode_const(opcode_desc &desc) -{ - read_imm1(desc); - int32_t const const1 = util::sext(desc.opptr[1], 15); - if (!E_BIT(desc.opptr[1])) - { - desc.length = 4; - desc.imm = uint32_t(const1); - } - else - { - read_imm2(desc); - desc.length = 6; - desc.imm = uint32_t(const1 << 16) | desc.opptr[2]; - } -} - - -inline void hyperstone_device::frontend::decode_ll(opcode_desc &desc) -{ - uint16_t const op = desc.opptr[0]; - desc.dst_code = BIT(op, 4, 4); - desc.src_code = BIT(op, 0, 4); - desc.dst_local = true; - desc.src_local = true; -} - -inline void hyperstone_device::frontend::decode_llext(opcode_desc &desc) -{ - decode_ll(desc); - read_imm1(desc); - desc.length = 4; -} - -inline void hyperstone_device::frontend::decode_lr(opcode_desc &desc) -{ - uint16_t const op = desc.opptr[0]; - desc.dst_code = BIT(op, 4, 4); - desc.src_code = BIT(op, 0, 4); - desc.dst_local = true; - desc.src_local = BIT(op, 8); -} - -inline void hyperstone_device::frontend::decode_rr(opcode_desc &desc) -{ - uint16_t const op = desc.opptr[0]; - desc.dst_code = BIT(op, 4, 4); - desc.src_code = BIT(op, 0, 4); - desc.dst_local = BIT(op, 9); - desc.src_local = BIT(op, 8); -} - -inline void hyperstone_device::frontend::decode_ln(opcode_desc &desc) -{ - uint16_t const op = desc.opptr[0]; - desc.dst_code = BIT(op, 4, 4); - desc.dst_local = true; - desc.imm = (BIT(op, 8) << 4) | BIT(op, 0, 4); -} - -inline void hyperstone_device::frontend::decode_rn(opcode_desc &desc) -{ - uint16_t const op = desc.opptr[0]; - desc.dst_code = BIT(op, 4, 4); - desc.dst_local = BIT(op, 9); - desc.imm = (BIT(op, 8) << 4) | BIT(op, 0, 4); -} - -inline void hyperstone_device::frontend::decode_pcrel(opcode_desc &desc) -{ - if (!BIT(desc.opptr[0], 7)) - { - uint32_t const low_rel = BIT(desc.opptr[0], 1, 6); - int32_t const s = util::sext(desc.opptr[0], 1); - desc.imm = uint32_t(s << 7) | (low_rel << 1); - } - else - { - read_imm1(desc); - desc.length = 4; - uint32_t const high_rel = BIT(desc.opptr[0], 0, 7); - uint32_t const low_rel = BIT(desc.opptr[1], 1, 15); - int32_t const s = util::sext(desc.opptr[1], 1); - desc.imm = uint32_t(s << 23) | (high_rel << 16) | (low_rel << 1); - } -} - -inline void hyperstone_device::frontend::decode_lrconst(opcode_desc &desc) -{ - decode_lr(desc); - decode_const(desc); -} - -inline void hyperstone_device::frontend::decode_rrconst(opcode_desc &desc) -{ - decode_rr(desc); - decode_const(desc); -} - -inline void hyperstone_device::frontend::decode_rrdis(opcode_desc &desc) -{ - decode_rr(desc); - read_imm1(desc); - int32_t const dis1 = util::sext((BIT(desc.opptr[1], 14) << 12) | BIT(desc.opptr[1], 0, 12), 13); - if (!E_BIT(desc.opptr[1])) - { - desc.length = 4; - desc.imm = uint32_t(dis1); - } - else - { - read_imm2(desc); - desc.length = 6; - desc.imm = uint32_t(dis1 << 16) | desc.opptr[2]; - } -} - -inline void hyperstone_device::frontend::decode_rimm(opcode_desc &desc, bool cmpbi_andni) -{ - constexpr int32_t table[32] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, -1, -1, -1, 32, 64, 128, int32_t(uint32_t(0x80000000)), - -8, -7, -6, -5, -4, -3, -2, -1 }; - - uint16_t const op = desc.opptr[0]; - desc.dst_code = BIT(op, 4, 4); - desc.dst_local = BIT(op, 9); - - uint16_t const n = (BIT(op, 8) << 4) | BIT(op, 0, 4); - switch (n) - { - case 17: - read_imm1(desc); - read_imm2(desc); - desc.length = 6; - desc.imm = (uint32_t(desc.opptr[1]) << 16) | desc.opptr[2]; - break; - case 18: - case 19: - read_imm1(desc); - desc.length = 4; - desc.imm = (BIT(n, 0) ? 0xffff0000U : 0U) | desc.opptr[1]; - break; - case 31: - desc.imm = cmpbi_andni ? 0x7fffffff : uint32_t(table[n]); - break; - default: - desc.imm = uint32_t(table[n]); - } -} - -inline void hyperstone_device::frontend::decode_rrlim(opcode_desc &desc) -{ - decode_rr(desc); - read_imm1(desc); - uint32_t const lim1 = BIT(desc.opptr[1], 0, 12); - if (!E_BIT(desc.opptr[1])) - { - desc.length = 4; - desc.imm = lim1; - } - else - { - read_imm2(desc); - desc.length = 6; - desc.imm = (lim1 << 16) | desc.opptr[2]; - } -} - - -/*------------------------------------------------- - describe - build a description of a single - instruction --------------------------------------------------*/ - -bool hyperstone_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) -{ - read_op(desc); - uint16_t const op = desc.opptr[0]; - - // most instructions are 2 bytes and a single cycle - desc.length = 2; - desc.delayslots = 0; - - switch (op >> 8) - { - case 0x00: // chk global,global - case 0x01: // chk global,local - case 0x02: // chk local,global - case 0x03: // chk local,local - decode_rr(desc); - if (!desc.dst_is_src() || desc.src_is_sr()) - { - desc.set_can_cause_exception(); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.dst_local) - desc.set_g_used(desc.dst_code); - if (!desc.src_local && (desc.src_code != SR_REGISTER)) - desc.set_g_used(desc.src_code); - } - else if (desc.dst_is_pc()) - { - desc.set_will_cause_exception(); - desc.set_end_sequence(); - } - break; - case 0x04: // movd global,global - case 0x05: // movd global,local - case 0x06: // movd local,global - case 0x07: // movd local,local - decode_rr(desc); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.src_local && (desc.dst_is_pc() || !desc.src_is_sr())) - { - desc.set_g_used(desc.src_code); - desc.set_g_used(desc.src_code + 1); - } - if (!desc.dst_local) - { - desc.set_g_modified(desc.dst_code); - desc.set_g_modified(desc.dst_code + 1); - } - desc.set_znv_modified(); - if (desc.dst_is_pc()) - { - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.set_g_used(SP_REGISTER); - desc.set_g_modified(SP_REGISTER); - desc.set_fp_modified(); - desc.set_is_unconditional_branch(); - desc.set_can_cause_exception(); - desc.set_end_sequence(); - desc.set_can_change_modes(); - desc.set_reads_memory(); - } - break; - case 0x08: // divu global,global - case 0x09: // divu global,local - case 0x0a: // divu local,global - case 0x0b: // divu local,local - case 0x0c: // divs global,global - case 0x0d: // divs global,local - case 0x0e: // divs local,global - case 0x0f: // divs local,local - decode_rr(desc); - desc.set_can_cause_exception(); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.src_local) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - { - desc.set_g_used(desc.dst_code); - desc.set_g_used(desc.dst_code + 1); - desc.set_g_modified(desc.dst_code); - desc.set_g_modified(desc.dst_code + 1); - } - desc.set_znv_modified(); - break; - case 0x10: // xm global,global - case 0x11: // xm global,local - case 0x12: // xm local,global - case 0x13: // xm local,local - decode_rrlim(desc); - if (desc.imm != 0U) - desc.set_can_cause_exception(); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.src_local) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - desc.set_g_modified(desc.dst_code); - break; - case 0x14: // mask global,global - case 0x15: // mask global,local - case 0x16: // mask local,global - case 0x17: // mask local,local - decode_rrconst(desc); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.src_local) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - desc.set_g_modified(desc.dst_code); - desc.set_z_modified(); - if (desc.dst_is_pc()) - { - if (!desc.src_is_pc()) - desc.targetpc = BRANCH_TARGET_DYNAMIC; - else - desc.targetpc = (desc.pc + desc.length) & desc.imm; - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - } - break; - case 0x18: // sum global,global - case 0x19: // sum global,local - case 0x1a: // sum local,global - case 0x1b: // sum local,local - case 0x1c: // sums global,global - case 0x1d: // sums global,local - case 0x1e: // sums local,global - case 0x1f: // sums local,local - decode_rrconst(desc); - if ((op & 0x0400) && !desc.src_is_sr()) - desc.set_can_cause_exception(); // sums - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (desc.src_is_sr()) - desc.set_c_used(); - else if (!desc.src_local) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - desc.set_g_modified(desc.dst_code); - if (op & 0x0400) - desc.set_znv_modified(); // sums - else - desc.set_cznv_modified(); // sum - if (desc.dst_is_pc()) - { - if (!desc.src_is_pc()) - desc.targetpc = BRANCH_TARGET_DYNAMIC; - else - desc.targetpc = ((desc.pc + desc.length) + desc.imm) & ~uint32_t(1); - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - } - break; - case 0x20: // cmp global,global - case 0x21: // cmp global,local - case 0x22: // cmp local,global - case 0x30: // cmpb global,global - case 0x31: // cmpb global,local - case 0x32: // cmpb local,global - decode_rr(desc); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!(op & 0x1000) && desc.src_is_sr()) - desc.set_c_used(); - else if (!desc.src_local) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - desc.set_g_used(desc.dst_code); - if (op & 0x1000) - desc.set_z_modified(); // cmpb - else - desc.set_cznv_modified(); // cmp - break; - case 0x24: // mov global,global - case 0x25: // mov global,local - case 0x26: // mov local,global - case 0x27: // mov local,local - decode_rr(desc); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.dst_local || !desc.src_local) - desc.regin.set(SR_REGISTER); // only the H bit is used - if (!desc.src_local) - { - desc.set_g_used(desc.src_code); - desc.set_g_used(desc.src_code + 16); - } - if (!desc.dst_local) - { - desc.set_can_cause_exception(); - desc.set_g_modified(desc.dst_code); - desc.set_g_modified(desc.dst_code + 16); - if (desc.dst_code == PC_REGISTER) - { - if (!desc.src_is_pc()) - desc.targetpc = BRANCH_TARGET_DYNAMIC; - else - desc.targetpc = desc.pc + desc.length; - desc.set_is_conditional_branch(); // technically it won't branch if H is clear - desc.set_end_sequence(); - } - else if (desc.dst_code == 5) // TPR_REGISTER & 0xf - { - desc.set_end_sequence(); - } - } - desc.set_znv_modified(); - break; - case 0x28: // add global,global - case 0x29: // add global,local - case 0x2a: // add local,global - case 0x2b: // add local,local - case 0x2c: // adds global,global - case 0x2d: // adds global,local - case 0x2e: // adds local,global - case 0x2f: // adds local,local - case 0x48: // sub global,global - case 0x49: // sub global,local - case 0x4a: // sub local,global - case 0x4b: // sub local,local - case 0x4c: // subs global,global - case 0x4d: // subs global,local - case 0x4e: // subs local,global - case 0x4f: // subs local,local - decode_rr(desc); - if (op & 0x0400) - desc.set_can_cause_exception(); // adds, subs - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (desc.src_is_sr()) - desc.set_c_used(); - else if (!desc.src_local) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - { - desc.set_g_used(desc.dst_code); - desc.set_g_modified(desc.dst_code); - if (desc.dst_code == PC_REGISTER) - { - if (!desc.src_is_pc()) - desc.targetpc = BRANCH_TARGET_DYNAMIC; - else if ((op & 0xf800) == 0x2800) - desc.targetpc = (desc.pc + desc.length) << 1; // add, adds - else - desc.targetpc = 0; // sub, subs - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - } - } - if (op & 0x0400) - desc.set_znv_modified(); // adds, subs - else - desc.set_cznv_modified(); // add, sub - break; - case 0x34: // andn global,global - case 0x35: // andn global,local - case 0x36: // andn local,global - case 0x37: // andn local,local - case 0x38: // or global,global - case 0x39: // or global,local - case 0x3a: // or local,global - case 0x3b: // or local,local - case 0x3c: // xor global,global - case 0x3d: // xor global,local - case 0x3e: // xor local,global - case 0x3f: // xor local,local - case 0x54: // and global,global - case 0x55: // and global,local - case 0x56: // and local,global - case 0x57: // and local,local - decode_rr(desc); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.src_local) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - { - desc.set_g_used(desc.dst_code); - desc.set_g_modified(desc.dst_code); - if (desc.dst_code == PC_REGISTER) - { - if (!desc.src_is_pc()) - desc.targetpc = BRANCH_TARGET_DYNAMIC; - else if ((op & 0xf400) == 0x3400) - desc.targetpc = 0; // andn, xor - else - desc.targetpc = desc.pc + desc.length; // or, and - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - } - } - desc.set_z_modified(); - break; - case 0x40: // subc global,global - case 0x41: // subc global,local - case 0x42: // subc local,global - case 0x43: // subc local,local - case 0x50: // addc global,global - case 0x51: // addc global,local - case 0x52: // addc local,global - case 0x53: // addc local,local - decode_rr(desc); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - desc.set_cz_used(); - if (!desc.src_local && !desc.src_is_sr()) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - { - desc.set_g_used(desc.dst_code); - desc.set_g_modified(desc.dst_code); - if (desc.dst_code == PC_REGISTER) - { - if (!desc.src_is_sr() || ((op & 0xfc00) == 0x4000)) - desc.targetpc = BRANCH_TARGET_DYNAMIC; - else - desc.targetpc = desc.pc + desc.length; - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - } - } - desc.set_cznv_modified(); - break; - case 0x44: // not global,global - case 0x45: // not global,local - case 0x46: // not local,global - case 0x47: // not local,local - case 0x58: // neg global,global - case 0x59: // neg global,local - case 0x5a: // neg local,global - case 0x5b: // neg local,local - case 0x5c: // negs global,global - case 0x5d: // negs global,local - case 0x5e: // negs local,global - case 0x5f: // negs local,local - decode_rr(desc); - if (((op & 0xfc00) == 0x5c00) && !desc.src_is_sr()) - desc.set_can_cause_exception(); // negs - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (((op & 0xf800) == 0x5800) & desc.src_is_sr()) - desc.set_c_used(); - else if (!desc.src_local) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - { - desc.set_g_modified(desc.dst_code); - if (desc.dst_code == PC_REGISTER) - { - if (!desc.src_is_pc()) - desc.targetpc = BRANCH_TARGET_DYNAMIC; - else if ((op & 0xfc00) == 0x4400) - desc.targetpc = ~(desc.pc + desc.length) & ~uint32_t(1); // not - else - desc.targetpc = uint32_t(-int32_t(desc.pc + desc.length)) & ~uint32_t(1); // neg, negs - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - } - } - if (!(op & 0x1000)) - desc.set_z_modified(); // not - else if (!(op & 0x0400)) - desc.set_cznv_modified(); // neg - else - desc.set_znv_modified(); // negs - break; - case 0x60: // cmpi global,imm - case 0x61: // cmpi global,imm - case 0x62: // cmpi local,imm - case 0x63: // cmpi local,imm - case 0x70: // cmpbi global,imm - case 0x71: // cmpbi global,imm - case 0x72: // cmpbi local,imm - case 0x73: // cmpbi local,imm - decode_rimm(desc, op & 0x1000); - if (desc.dst_local) - desc.set_fp_used(); - else - desc.set_g_used(desc.dst_code); - if (op & 0x1000) - desc.set_z_modified(); // cmpbi - else - desc.set_cznv_modified(); // cmpi - break; - case 0x64: // movi global,imm - case 0x65: // movi global,imm - decode_rimm(desc, false); - desc.set_can_cause_exception(); - desc.regin.set(SR_REGISTER); // only the H bit is used - desc.set_g_modified(desc.dst_code); - desc.set_g_modified(desc.dst_code + 16); - if (desc.dst_code == PC_REGISTER) - { - desc.targetpc = desc.imm & ~uint32_t(1); - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - } - else if (desc.dst_code == 5) // TPR_REGISTER & 0xf - { - desc.set_end_sequence(); - } - break; - case 0x66: // movi local,imm - case 0x67: // movi local,imm - decode_rimm(desc, false); - desc.set_fp_used(); - desc.set_znv_modified(); - break; - case 0x68: // addi global,imm - case 0x69: // addi global,imm - case 0x6a: // addi local,imm - case 0x6b: // addi local,imm - case 0x6c: // addsi global,imm - case 0x6d: // addsi global,imm - case 0x6e: // addsi local,imm - case 0x6f: // addsi local,imm - decode_rimm(desc, false); - if (op & 0x0400) - desc.set_can_cause_exception(); // addsi - if (desc.dst_local) - desc.set_fp_used(); - if (!(op & 0x010f)) - desc.set_cz_used(); - if (!desc.dst_local) - { - desc.set_g_used(desc.dst_code); - desc.set_g_modified(desc.dst_code); - if (desc.dst_code == PC_REGISTER) - { - desc.targetpc = (desc.pc + desc.length + desc.imm) & ~uint32_t(1); - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - } - } - if (op & 0x0400) - desc.set_znv_modified(); // addsi - else - desc.set_cznv_modified(); // addi - break; - case 0x74: // andni global,imm - case 0x75: // andni global,imm - case 0x78: // ori global,imm - case 0x79: // ori global,imm - case 0x7c: // xori global,imm - case 0x7d: // xori global,imm - decode_rimm(desc, !(op & 0x0800)); - desc.set_g_used(desc.dst_code); - desc.set_g_modified(desc.dst_code); - if (desc.dst_code == PC_REGISTER) - { - if (!(op & 0x0800)) - desc.targetpc = (desc.pc + desc.length) & ~desc.imm; // andni - else if (!(op & 0x0400)) - desc.targetpc = ((desc.pc + desc.length) | desc.imm) & ~uint32_t(1); // ori - else - desc.targetpc = ((desc.pc + desc.length) ^ desc.imm) & ~uint32_t(1); // xori - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - } - desc.set_z_modified(); - break; - case 0x76: // andni local,imm - case 0x77: // andni local,imm - case 0x7a: // ori local,imm - case 0x7b: // ori local,imm - case 0x7e: // xori local,imm - case 0x7f: // xori local,imm - decode_rimm(desc, !(op & 0x0800)); - desc.set_fp_used(); - desc.set_z_modified(); - break; - case 0x80: case 0x81: // shrdi - case 0x84: case 0x85: // sardi - case 0x88: case 0x89: // shldi - decode_ln(desc); - desc.set_fp_used(); - if (op & 0x0800) - desc.set_cznv_modified(); // shldi - else - desc.set_czn_modified(); // shrdi, sardi - break; - case 0x82: // shrd - case 0x83: // shr - case 0x86: // sard - case 0x87: // sar - case 0x8a: // shld - case 0x8b: // shl - case 0x8f: // rol - decode_ll(desc); - desc.set_fp_used(); - if (op & 0x0800) - desc.set_cznv_modified(); // shld, shl, rol - else - desc.set_czn_modified(); // shrd, shr, sard, sar - break; - case 0x8c: case 0x8d: // reserved - return false; - case 0x8e: // testlz - decode_ll(desc); - desc.set_fp_used(); - break; - case 0x90: // ldxx.d/a global,global - case 0x91: // ldxx.d/a global,local - case 0x92: // ldxx.d/a local,global - case 0x93: // ldxx.d/a local,local - case 0x94: // ldxx.n/s global,global - case 0x95: // ldxx.n/s global,local - case 0x96: // ldxx.n/s local,global - case 0x97: // ldxx.n/s local,local - decode_rrdis(desc); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.dst_local && !desc.dst_is_sr()) - desc.set_g_used(desc.dst_code); - if ((op & 0x0400) && !desc.dst_local) - desc.set_g_modified(desc.dst_code); - if (!desc.src_local) - { - desc.set_g_modified(desc.src_code); - if ((desc.opptr[1] & 0x3000) == 0x3000) - { - if ((desc.imm & ((op & 0x0400) ? 0x3 : 0x1)) == 0x1) - desc.set_g_modified(desc.src_code + 1); - } - } - desc.set_reads_memory(); - break; - case 0x98: // stxx.d/a global,global - case 0x99: // stxx.d/a global,local - case 0x9a: // stxx.d/a local,global - case 0x9b: // stxx.d/a local,local - case 0x9c: // stxx.n/s global,global - case 0x9d: // stxx.n/s global,local - case 0x9e: // stxx.n/s local,global - case 0x9f: // stxx.n/s local,local - decode_rrdis(desc); - if (((desc.opptr[1] & 0x3000) == 0x0000) || (((desc.opptr[1] & 0x3000) == 0x0000) && (desc.imm & 0x1))) - desc.set_can_cause_exception(); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.dst_local && !desc.dst_is_sr()) - desc.set_g_used(desc.dst_code); - if (!desc.src_local) - { - desc.set_g_used(desc.src_code); - if ((desc.opptr[1] & 0x3000) == 0x3000) - { - if ((desc.imm & ((op & 0x0400) ? 0x3 : 0x1)) == 0x1) - desc.set_g_used(desc.src_code + 1); - } - } - if ((op & 0x0400) && !desc.dst_local) - desc.set_g_modified(desc.dst_code); - desc.set_writes_memory(); - break; - case 0xa0: // shri global - case 0xa1: // shri global - case 0xa2: // shri local - case 0xa3: // shri local - case 0xa4: // sari global - case 0xa5: // sari global - case 0xa6: // sari local - case 0xa7: // sari local - case 0xa8: // shli global - case 0xa9: // shli global - case 0xaa: // shli local - case 0xab: // shli local - decode_rn(desc); - if (desc.dst_local) - desc.set_fp_used(); - if (!desc.dst_local) - { - desc.set_g_used(desc.dst_code); - desc.set_g_modified(desc.dst_code); - } - if (op & 0x0800) - desc.set_cznv_modified(); // shli - else - desc.set_czn_modified(); // shri, sari - break; - case 0xac: case 0xad: case 0xae: case 0xaf: // reserved - return false; - case 0xb0: // mulu global,global - case 0xb1: // mulu global,local - case 0xb2: // mulu local,global - case 0xb3: // mulu local,local - case 0xb4: // muls global,global - case 0xb5: // muls global,local - case 0xb6: // muls local,global - case 0xb7: // muls local,local - case 0xbc: // mul global,global - case 0xbd: // mul global,local - case 0xbe: // mul local,global - case 0xbf: // mul local,local - decode_rr(desc); - if (desc.dst_local || desc.src_local) - desc.set_fp_used(); - if (!desc.src_local) - desc.set_g_used(desc.src_code); - if (!desc.dst_local) - { - desc.set_g_used(desc.dst_code); - desc.set_g_modified(desc.dst_code); - if (!(op & 0x0800)) - desc.set_g_modified(desc.dst_code + 1); // mulu, muls - } - desc.set_cznv_modified(); - break; - case 0xb8: // set global - case 0xb9: // set global - case 0xba: // set local - case 0xbb: // set local - decode_rn(desc); - if (desc.dst_local) - desc.set_fp_used(); - switch (desc.imm) - { - case 4: case 5: case 20: case 21: // le, gt, lem, gtm - desc.set_z_used(); - desc.set_n_used(); - break; - case 6: case 7: case 22: case 23: // lt/n, ge/nn, ltm/nm, gem/nnm - desc.set_n_used(); - break; - case 8: case 9: case 24: case 25: // se, ht, sem, htm - desc.set_cz_used(); - break; - case 10: case 11: case 26: case 27: // st/c, he/nc, stm/cm, hem/ncm - desc.set_c_used(); - break; - case 12: case 13: case 28: case 29: // e/z, ne/nz, em/zm, nem/nzm - desc.set_z_used(); - break; - case 14: case 15: case 30: case 31: // v, nv, vm, nvm - desc.set_v_used(); - break; - } - if (!desc.dst_local) - desc.set_g_modified(desc.dst_code); - break; - case 0xc0: case 0xc1: case 0xc2: case 0xc3: // software - case 0xc4: case 0xc5: case 0xc6: case 0xc7: // software - case 0xc8: case 0xc9: case 0xca: case 0xcb: // software - case 0xcc: case 0xcd: // software - case 0xcf: // do - decode_ll(desc); - desc.set_fp_used(); - desc.set_g_used(PC_REGISTER); - desc.set_g_used(SR_REGISTER); - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - desc.set_can_change_modes(); - break; - case 0xce: // extend - decode_llext(desc); - desc.set_fp_used(); - desc.set_g_used(14); - desc.set_g_used(15); - desc.set_g_modified(14); - desc.set_g_modified(15); - break; - case 0xd0: // ldwr global - case 0xd1: // ldwr local - case 0xd2: // lddr global - case 0xd3: // lddr local - case 0xd4: // ldwp global - case 0xd5: // ldwp local - case 0xd6: // lddp global - case 0xd7: // lddp local - decode_lr(desc); - desc.set_fp_used(); - if (!desc.src_local) - { - desc.set_g_modified(desc.src_code); - if (op & 0x0200) - desc.set_g_modified(desc.src_code + 1); - } - desc.set_reads_memory(); - break; - case 0xd8: // stwr global - case 0xd9: // stwr local - case 0xda: // stdr global - case 0xdb: // stdr local - case 0xdc: // stwp global - case 0xdd: // stwp local - case 0xde: // stdp global - case 0xdf: // stdp local - decode_lr(desc); - desc.set_fp_used(); - if (!desc.src_local) - { - desc.set_g_used(desc.src_code); - if (op & 0x0200) - desc.set_g_used(desc.src_code + 1); - } - desc.set_writes_memory(); - break; - case 0xe0: case 0xe1: case 0xe2: case 0xe3: // dbv, dbnv, dbe, dbne - case 0xe4: case 0xe5: case 0xe6: case 0xe7: // dbc, dbnc, dbse, dbht - case 0xe8: case 0xe9: case 0xea: case 0xeb: // dbn, dbnn, dble, dbgt - case 0xec: // dbr - case 0xf0: case 0xf1: case 0xf2: case 0xf3: // bv, bnv, be, bne - case 0xf4: case 0xf5: case 0xf6: case 0xf7: // bc, bnc, bse, bht - case 0xf8: case 0xf9: case 0xfa: case 0xfb: // bn, bnn, ble, bgt - case 0xfc: // br - decode_pcrel(desc); - switch (op & 0x0f00) - { - case 0x0000: case 0x0100: // bv, bnv - desc.set_v_used(); - break; - case 0x0200: case 0x0300: // be/bz, bne/bnz - desc.set_z_used(); - break; - case 0x0400: case 0x0500: // bst/bc, bhe/bnc - desc.set_c_used(); - break; - case 0x0600: case 0x0700: // bse, bht - desc.set_cz_used(); - break; - case 0x0800: case 0x0900: // blt/bn, bge/bnn - desc.set_n_used(); - break; - case 0x0a00: case 0x0b00: // ble, bgt - desc.set_z_used(); - desc.set_n_used(); - break; - case 0x0c00: // br - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - break; - } - if ((op & 0x0f00) != 0x0c00) - desc.set_is_conditional_branch(); - desc.delayslots = (op & 0x1000) ? 0 : 1; - desc.targetpc = desc.pc + desc.length + desc.imm; - break; - case 0xed: // frame - desc.set_can_cause_exception(); - desc.set_fp_used(); - desc.regin.set(SR_REGISTER); // uses FL - desc.set_g_used(SP_REGISTER); - desc.set_g_used(UB_REGISTER); - desc.set_g_modified(SP_REGISTER); - desc.set_fp_modified(); - desc.set_writes_memory(); - break; - case 0xee: // call global - case 0xef: // call local - decode_lrconst(desc); - if (!desc.src_local && !desc.src_is_sr()) - desc.set_g_used(desc.src_code); - desc.set_g_used(PC_REGISTER); - desc.set_g_used(SR_REGISTER); - if (desc.src_is_pc()) - desc.targetpc = (desc.pc + desc.length + desc.imm) & ~uint32_t(1); - else if (desc.src_is_sr()) - desc.targetpc = desc.imm & ~uint32_t(1); - else - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.set_is_unconditional_branch(); - desc.set_end_sequence(); - break; - case 0xfd: case 0xfe: case 0xff: // trap - switch (bitswap<4>(op, 9, 8, 1, 0)) - { - case 4: case 5: // traple, trapgt - desc.set_z_used(); - desc.set_n_used(); - break; - case 6: case 7: // traplt, trapge - desc.set_n_used(); - break; - case 8: case 9: // trapse, trapht - desc.set_cz_used(); - break; - case 10: case 11: // trapst, traphe - desc.set_c_used(); - break; - case 12: case 13: // trape, trapne - desc.set_z_used(); - break; - case 14: // trapv - desc.set_z_used(); - break; - case 15: // trap - desc.set_will_cause_exception(); - desc.set_end_sequence(); - break; - } - if (bitswap<4>(op, 9, 8, 1, 0) != 15) - desc.set_can_cause_exception(); - break; - } - return true; -} diff --git a/src/devices/cpu/e132xs/e132xsfe.h b/src/devices/cpu/e132xs/e132xsfe.h deleted file mode 100644 index f3075a415c8..00000000000 --- a/src/devices/cpu/e132xs/e132xsfe.h +++ /dev/null @@ -1,210 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Vas Crabb -/*************************************************************************** - - e132xsfe.h - - Hyperstone E1 instruction decoder - -***************************************************************************/ -#ifndef MAME_CPU_E132XS_E132XSFE_H -#define MAME_CPU_E132XS_E132XSFE_H - -#pragma once - -#include "e132xs.h" - -#include "cpu/drcfe.h" - -#include -#include -#include - - -class hyperstone_device::opcode_desc : public opcode_desc_base -{ -public: - uint16_t opptr[3]; - uint8_t dst_code; - uint8_t src_code; - bool dst_local; - bool src_local; - uint32_t imm; - - void set_g_used(unsigned n) - { - regin.set(REG_G0 + n); - if (n == 1) // SR - { - regin.set(REG_C); - regin.set(REG_Z); - regin.set(REG_N); - regin.set(REG_V); - regin.set(REG_FP); - } - } - - void set_c_used() { regin.set(REG_C); } - void set_z_used() { regin.set(REG_Z); } - void set_n_used() { regin.set(REG_N); } - void set_v_used() { regin.set(REG_V); } - void set_fp_used() { regin.set(REG_FP); } - - void set_cz_used() - { - set_c_used(); - set_z_used(); - } - - void set_g_modified(unsigned n) - { - regout.set(REG_G0 + n); - if (n == 1) // SR - { - regout.set(REG_C); - regout.set(REG_Z); - regout.set(REG_N); - regout.set(REG_V); - } - } - - void set_z_modified() - { - regout.set(REG_SR); - regout.set(REG_Z); - } - - void set_znv_modified() - { - regout.set(REG_SR); - regout.set(REG_Z); - regout.set(REG_N); - regout.set(REG_V); - } - - void set_czn_modified() - { - regout.set(REG_SR); - regout.set(REG_C); - regout.set(REG_Z); - regout.set(REG_N); - } - - void set_cznv_modified() - { - regout.set(REG_SR); - regout.set(REG_C); - regout.set(REG_Z); - regout.set(REG_N); - regout.set(REG_V); - } - - void set_fp_modified() - { - regout.set(REG_SR); - regout.set(REG_FP); - } - - bool c_calc_required() const { return regreq[REG_C] || in_delay_slot(); } - bool z_calc_required() const { return regreq[REG_Z] || in_delay_slot(); } - bool n_calc_required() const { return regreq[REG_N] || in_delay_slot(); } - bool v_calc_required() const { return regreq[REG_V] || in_delay_slot(); } - bool condition_calc_required() const { return regreq[REG_C] || regreq[REG_Z] || regreq[REG_N] || regreq[REG_V] || in_delay_slot(); } - - void set_can_change_modes() { m_extra_flags.set(CAN_CHANGE_MODES); } - void set_reads_memory() { m_extra_flags.set(READS_MEMORY); } - void set_writes_memory() { m_extra_flags.set(WRITES_MEMORY); } - - bool can_change_modes() const { return m_extra_flags[CAN_CHANGE_MODES]; } - bool reads_memory() const { return m_extra_flags[READS_MEMORY]; } - bool writes_memory() const { return m_extra_flags[WRITES_MEMORY]; } - - bool dst_is_src() const { return (dst_local == src_local) && (dst_code == src_code); } - bool dst_is_pc() const { return !dst_local && (dst_code == 0); } - bool dst_is_sr() const { return !dst_local && (dst_code == 1); } - bool src_is_pc() const { return !src_local && (src_code == 0); } - bool src_is_sr() const { return !src_local && (src_code == 1); } - - // epc - compute the exception PC - uint32_t epc() const - { - return in_delay_slot() ? branch->pc : pc; - } - - void reset(offs_t curpc, bool in_delay_slot) - { - static_assert(REG_COUNT <= 40); - - opcode_desc_base::reset(curpc, in_delay_slot); - - std::fill(std::begin(opptr), std::end(opptr), 0); - dst_code = ~uint8_t(0); - src_code = ~uint8_t(0); - dst_local = false; - src_local = false; - imm = 0x80000000; - m_extra_flags.reset(); - } - -protected: - enum - { - REG_G0 = 0, - REG_PC = REG_G0, - REG_SR = REG_G0 + 1, - - REG_C = REG_G0 + 32, - REG_Z, - REG_N, - REG_V, - REG_FP, - - REG_COUNT - }; - - enum - { - CAN_CHANGE_MODES = 0, - READS_MEMORY, - WRITES_MEMORY, - - EXTRA_FLAG_COUNT - }; - - std::bitset m_extra_flags; -}; - - -class hyperstone_device::frontend : public drc_frontend_base -{ -public: - frontend(hyperstone_device &cpu, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - ~frontend(); - - opcode_desc const *describe_code(offs_t startpc); - -private: - bool describe(opcode_desc &desc, opcode_desc const *prev); - - void read_op(opcode_desc &desc); - void read_imm1(opcode_desc &desc); - void read_imm2(opcode_desc &desc); - void decode_const(opcode_desc &desc); - - void decode_ll(opcode_desc &desc); - void decode_llext(opcode_desc &desc); - void decode_lr(opcode_desc &desc); - void decode_rr(opcode_desc &desc); - void decode_ln(opcode_desc &desc); - void decode_rn(opcode_desc &desc); - void decode_pcrel(opcode_desc &desc); - void decode_lrconst(opcode_desc &desc); - void decode_rrconst(opcode_desc &desc); - void decode_rrdis(opcode_desc &desc); - void decode_rimm(opcode_desc &desc, bool cmpbi_andni); - void decode_rrlim(opcode_desc &desc); - - hyperstone_device &m_cpu; -}; - -#endif // MAME_CPU_E132XS_E132XSFE_H diff --git a/src/devices/cpu/e132xs/e1dasm.cpp b/src/devices/cpu/e132xs/e1dasm.cpp new file mode 100644 index 00000000000..fe8e64b4d9e --- /dev/null +++ b/src/devices/cpu/e132xs/e1dasm.cpp @@ -0,0 +1,1132 @@ +// license:BSD-3-Clause +// copyright-holders:Pierpaolo Prazzoli +/* + + Hyperstone E1 disassembler + written by Pierpaolo Prazzoli + +*/ + +#include "emu.h" +#include "e1dasm.h" + +#include "e1defs.h" + +#include + + +namespace { + +const char *const L_REG[] = +{ + "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7", + "L8", "L9", "L10", "L11", "L12", "L13", "L14", "L15" +}; + +const char *const G_REG[] = +{ + "PC", "SR", "FER", "G03", "G04", "G05", "G06", "G07", + "G08", "G09", "G10", "G11", "G12", "G13", "G14", "G15", + "G16", "G17", "SP", "UB", "BCR", "TPR", "TCR", "TR", + "WCR", "ISR", "FCR", "MCR", "G28", "G29", "G30", "G31" +}; + +const char *const SETxx[] = +{ + "SETADR", nullptr, "SET1", "SET0", "SETLE", "SETGT", "SETLT", "SETGE", + "SETSE", "SETHT", "SETST", "SETHE", "SETE", "SETNE", "SETV", "SETNV", + nullptr, nullptr, "SET1M", nullptr, "SETLEM", "SETGTM", "SETLTM", "SETGEM", + "SETSEM", "SETTHM", "SETSTM", "SETHEM", "SETEM", "SETNEM", "SETVM", "SETNVM" +}; + +const char *const Fxxx[] = +{ + "FADD", "FADDD", "FSUB", "FSUBD", "FMUL", "FMULD", "FDIV", "FDIVD", + "FCMP", "FCMPD", "FCMPU", "FCMPUD", "FCVT", "FCVTD" +}; + +const char *const Bxx[] = +{ + "BV", "BNV", "BE", "BNE", "BC", "BNC", "BSE", "BHT", + "BN", "BNN", "BLE", "BGT", "BR" +}; + +const char *const TRAPxx[] = +{ + nullptr, nullptr, nullptr, nullptr, "TRAPLE", "TRAPGT", "TRAPLT", "TRAPGE", + "TRAPSE", "TRAPHT", "TRAPST", "TRAPHE", "TRAPE", "TRAPNE", "TRAPV", "TRAP" +}; + +#define DESTCODE(op) ((op & 0x00f0) >> 4) +#define SOURCECODE(op) (op & 0x000f) + +#define SOURCEBIT(op) ((op & 0x100) >> 8) +#define DESTBIT(op) ((op & 0x200) >> 9) + +#define DASM_N_VALUE(op) ((((op & 0x100) >> 8) << 4 ) | (op & 0x0f)) + + +void LL_format(std::string_view &source, std::string_view &dest, uint16_t op) +{ + source = L_REG[SOURCECODE(op)]; + dest = L_REG[DESTCODE(op)]; +} + +void LR_format(std::string_view &source, std::string_view &dest, uint16_t op) +{ + if (SOURCEBIT(op)) + source = L_REG[SOURCECODE(op)]; + else + source = G_REG[SOURCECODE(op)]; + + dest = L_REG[DESTCODE(op)]; +} + +void RR_format(std::string_view &source, std::string_view &dest, uint16_t op, unsigned h_flag) +{ + if (SOURCEBIT(op)) + source = L_REG[SOURCECODE(op)]; + else + source = G_REG[SOURCECODE(op) + h_flag * 16]; + + if (DESTBIT(op)) + dest = L_REG[DESTCODE(op)]; + else + dest = G_REG[DESTCODE(op) + h_flag * 16]; +} + +uint8_t Ln_format(std::string_view &dest, uint16_t op) +{ + dest = L_REG[DESTCODE(op)]; + + return DASM_N_VALUE(op); +} + +uint8_t Rn_format(std::string_view &dest, uint16_t op) +{ + if (DESTBIT(op)) + dest = L_REG[DESTCODE(op)]; + else + dest = G_REG[DESTCODE(op)]; + + return DASM_N_VALUE(op); +} + + +void format_addsub( + std::ostream &stream, + std::string_view inst, + std::string_view dest, + std::string_view source, + uint8_t source_bit, + uint8_t source_code) +{ + util::stream_format(stream, "%-7s %s, %s", + inst, + dest, + (!source_bit && (source_code == SR_REGISTER)) ? "C" : source); +} + +} // anonymous namespace + + + +template +uint32_t hyperstone_disassembler::LRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, T &&read_hw) +{ + uint16_t next_op; + uint32_t const_val; + + if (SOURCEBIT(op)) + source = L_REG[SOURCECODE(op)]; + else + source = G_REG[SOURCECODE(op)]; + + dest = L_REG[DESTCODE(op)]; + + size = 4; + + pc += 2; + next_op = read_hw(pc); + + if (E_BIT(next_op)) + { + uint16_t next_op2; + + size = 6; + + pc += 2; + next_op2 = read_hw(pc); + const_val = next_op2; + const_val |= ((next_op & 0x3fff) << 16 ); + + if (S_BIT_CONST(next_op)) + const_val |= 0xc0000000; + } + else + { + const_val = next_op & 0x3fff; + + if (S_BIT_CONST(next_op)) + const_val |= 0xffffc000; + } + + return const_val; +} + +template +uint32_t hyperstone_disassembler::RRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, T &&read_hw) +{ + uint16_t next_op; + uint32_t const_val; + + if (SOURCEBIT(op)) + source = L_REG[SOURCECODE(op)]; + else + source = G_REG[SOURCECODE(op)]; + + if (DESTBIT(op)) + dest = L_REG[DESTCODE(op)]; + else + dest = G_REG[DESTCODE(op)]; + + size = 4; + + pc += 2; + next_op = read_hw(pc); + + if (E_BIT(next_op)) + { + uint16_t next_op2; + + size = 6; + + pc += 2; + next_op2 = read_hw(pc); + const_val = next_op2; + const_val |= ((next_op & 0x3fff) << 16 ); + + if (S_BIT_CONST(next_op)) + { + const_val |= 0xc0000000; + } + } + else + { + const_val = next_op & 0x3fff; + + if (S_BIT_CONST(next_op)) + const_val |= 0xffffc000; + } + + return const_val; +} + +template +int32_t hyperstone_disassembler::Rimm_format(std::string_view &dest, uint16_t op, offs_t pc, T &&read_hw, unsigned h_flag) +{ + uint16_t imm1, imm2; + int32_t ret; + + int n = DASM_N_VALUE(op); + + if (DESTBIT(op)) + dest = L_REG[DESTCODE(op)]; + else + dest = G_REG[DESTCODE(op) + h_flag * 16]; + + switch (n) + { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: + case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: + return n; + + case 17: + pc += 2; + imm1 = read_hw(pc); + pc += 2; + imm2 = read_hw(pc); + ret = (imm1 << 16) | imm2; + + size = 6; + return ret; + + + case 18: + pc += 2; + ret = read_hw(pc); + + size = 4; + return ret; + + case 19: + pc += 2; + ret = (int32_t) (0xffff0000 | read_hw(pc)); + + size = 4; + return ret; + + case 20: + return 32; //bit 5 = 1, others = 0 + + case 21: + return 64; //bit 6 = 1, others = 0 + + case 22: + return 128; //bit 7 = 1, others = 0 + + case 23: + return 0x80000000; //bit 31 = 1, others = 0 (2 at the power of 31) + + case 24: + return -8; + + case 25: + return -7; + + case 26: + return -6; + + case 27: + return -5; + + case 28: + return -4; + + case 29: + return -3; + + case 30: + return -2; + + case 31: + return -1; + + default: + return 0; //should never goes here + } +} + +template +int32_t hyperstone_disassembler::PCrel_format(uint16_t op, offs_t pc, T &&read_hw) +{ + int32_t ret; + + if( op & 0x80 ) //bit 7 = 1 + { + uint16_t next; + + size = 4; + + pc += 2; + + next = read_hw(pc); + + ret = (op & 0x7f) << 16; + + ret |= (next & 0xfffe); + + if( next & 1 ) + ret |= 0xff800000; //ok? + } + else + { + ret = op & 0x7e; + + if( op & 1 ) + ret |= 0xffffff80; //ok? + } + + return (pc + ret); +} + +template +uint32_t hyperstone_disassembler::RRdis_format(std::string_view &source, std::string_view &dest, uint16_t op, uint16_t next_op, offs_t pc, T &&read_hw) +{ + uint32_t ret; + + if (SOURCEBIT(op)) + source = L_REG[SOURCECODE(op)]; + else + source = G_REG[SOURCECODE(op)]; + + if (DESTBIT(op)) + dest = L_REG[DESTCODE(op)]; + else + dest = G_REG[DESTCODE(op)]; + + if (E_BIT(next_op)) + { + uint16_t next; + + size = 6; + + next = read_hw(pc + 4); + + ret = next; + ret |= ( ( next_op & 0xfff ) << 16 ); + + if( S_BIT_CONST(next_op) ) + { + ret |= 0xf0000000; + } + } + else + { + ret = next_op & 0xfff; + if( S_BIT_CONST(next_op) ) + { + ret |= 0xfffff000; + } + } + + return ret; +} + +u32 hyperstone_disassembler::opcode_alignment() const +{ + return 2; +} + +hyperstone_disassembler::hyperstone_disassembler(config *conf) : m_config(conf) +{ +} + +offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + return do_disassemble(stream, pc, [&opcodes] (offs_t addr) { return opcodes.r16(addr); }); +} + +offs_t hyperstone_disassembler::disassemble_one(std::ostream &stream, offs_t pc, const uint16_t *opptr) +{ + return do_disassemble( + stream, + pc, + [pc, opptr] (offs_t addr) + { + assert(addr >= pc); + assert(addr < (pc + 6)); + return opptr[(addr - pc) >> 1]; + }); +} + + +/*****************************/ +/* Main disassembly function */ +/*****************************/ +template +offs_t hyperstone_disassembler::do_disassemble(std::ostream &stream, offs_t pc, T &&read_hw) +{ + std::string_view source, dest; + uint32_t flags = 0; + + const uint16_t op = read_hw(pc); + + size = 2; + + const uint8_t source_code = SOURCECODE(op); + const uint8_t dest_code = DESTCODE(op); + const uint8_t source_bit = SOURCEBIT(op); + const uint8_t dest_bit = DESTBIT(op); + + const int h_flag = m_config ? m_config->get_h() : 0; + + const uint8_t op_num = (op & 0xff00) >> 8; + + switch (op_num) + { + // CHK - CHKZ - NOP + case 0x00: case 0x01: case 0x02: case 0x03: + if (source_bit && dest_bit && !source_code && !dest_code) + { + util::stream_format(stream, "NOP"); + } + else + { + RR_format(source, dest, op, 0); + if (!source_bit && (source_code == SR_REGISTER)) + util::stream_format(stream, "CHKZ %s, 0", dest); + else + util::stream_format(stream, "CHK %s, %s", dest, source); + } + break; + + // MOVD - RET + case 0x04: case 0x05: case 0x06: case 0x07: + RR_format(source, dest, op, 0); + + if (!dest_bit && (dest_code == PC_REGISTER)) + { + if (!source_bit && ((source_code == PC_REGISTER) || (source_code == SR_REGISTER))) + { + // RET with PC or SR as source is reserved for future expansion + util::stream_format(stream, "D.HU $%04x", op); + } + else + { + RR_format(source, dest, op, 0); + util::stream_format(stream, "RET PC, %s", source); + flags = STEP_OUT; + } + } + else if (!source_bit && (source_code == SR_REGISTER)) + { + util::stream_format(stream, "MOVD %s, 0", dest); + } + else + { + util::stream_format(stream, "MOVD %s, %s", dest, source); + } + break; + + case 0x08: case 0x09: case 0x0a: case 0x0b: // DIVU + case 0x0c: case 0x0d: case 0x0e: case 0x0f: // DIVS + RR_format(source, dest, op, 0); + util::stream_format(stream, "DIV%c %s, %s", (op_num & 0x4) ? 'S' : 'U', dest, source); + break; + + // XMx - XXx + case 0x10: case 0x11: case 0x12: case 0x13: + { + RR_format(source, dest, op, 0); + + size = 4; + + pc += 2; + const uint16_t ilm1 = read_hw(pc); + + const int xcode = X_CODE(ilm1); + + if (xcode < 4) + { + uint16_t lim; + + if (E_BIT(ilm1)) + { + size = 6; + + pc += 2; + const uint16_t ilm2 = read_hw(pc); + + lim = ((ilm1 & 0xfff) << 16) | ilm2; + } + else + { + lim = ilm1 & 0xfff; + } + + util::stream_format(stream, "XM%x %s, %s, $%x", 1 << xcode, dest, source, lim); + } + else + { + util::stream_format(stream, "XX%x %s, %s, 0", 1 << (xcode & 0x3), dest, source); + } + } + break; + + // MASK + case 0x14: case 0x15: case 0x16: case 0x17: + { + const uint32_t const_val = RRconst_format(source, dest, op, pc, read_hw); + util::stream_format(stream, "MASK %s, %s, $%x", dest, source, const_val); + if (!source_bit && (source_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t((pc + size) & const_val)); + } + break; + + case 0x18: case 0x19: case 0x1a: case 0x1b: // SUM + case 0x1c: case 0x1d: case 0x1e: case 0x1f: // SUMS + { + const uint32_t const_val = RRconst_format(source, dest, op, pc, read_hw); + util::stream_format(stream, "SUM%c %s, %s, $%x", + (op_num & 0x4) ? 'S' : ' ', + dest, + (!source_bit && (source_code == SR_REGISTER)) ? "C" : source, + const_val); + if (!source_bit && (source_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t(pc + size + const_val)); + } + break; + + // CMP + case 0x20: case 0x21: case 0x22: case 0x23: + RR_format(source, dest, op, 0); + format_addsub(stream, "CMP", dest, source, source_bit, source_code); + break; + + // MOV + case 0x24: case 0x25: case 0x26: case 0x27: + RR_format(source, dest, op, h_flag); + util::stream_format(stream, "MOV %s, %s", dest, source); + break; + + case 0x28: case 0x29: case 0x2a: case 0x2b: // ADD + case 0x2c: case 0x2d: case 0x2e: case 0x2f: // ADDS + RR_format(source, dest, op, 0); + format_addsub(stream, (op_num & 0x4) ? "ADDS" : "ADD", dest, source, source_bit, source_code); + break; + + // CMPB + case 0x30: case 0x31: case 0x32: case 0x33: + RR_format(source, dest, op, 0); + util::stream_format(stream, "CMPB %s, %s", dest, source); + break; + + // ANDN + case 0x34: case 0x35: case 0x36: case 0x37: + RR_format(source, dest, op, 0); + util::stream_format(stream, "ANDN %s, %s", dest, source); + break; + + // OR + case 0x38: case 0x39: case 0x3a: case 0x3b: + RR_format(source, dest, op, 0); + util::stream_format(stream, "OR %s, %s", dest, source); + break; + + // XOR + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + RR_format(source, dest, op, 0); + util::stream_format(stream, "XOR %s, %s", dest, source); + break; + + // SUBC + case 0x40: case 0x41: case 0x42: case 0x43: + RR_format(source, dest, op, 0); + format_addsub(stream, "SUBC", dest, source, source_bit, source_code); + break; + + // NOT + case 0x44: case 0x45: case 0x46: case 0x47: + RR_format(source, dest, op, 0); + util::stream_format(stream, "NOT %s, %s", dest, source); + break; + + case 0x48: case 0x49: case 0x4a: case 0x4b: // SUB + case 0x4c: case 0x4d: case 0x4e: case 0x4f: // SUBS + RR_format(source, dest, op, 0); + format_addsub(stream, (op_num & 0x4) ? "SUBS" : "SUB", dest, source, source_bit, source_code); + break; + + // ADDC + case 0x50: case 0x51: case 0x52: case 0x53: + RR_format(source, dest, op, 0); + format_addsub(stream, "ADDC", dest, source, source_bit, source_code); + break; + + // AND + case 0x54: case 0x55: case 0x56: case 0x57: + RR_format(source, dest, op, 0); + util::stream_format(stream, "AND %s, %s", dest, source); + break; + + case 0x58: case 0x59: case 0x5a: case 0x5b: // NEG + case 0x5c: case 0x5d: case 0x5e: case 0x5f: // NEGS + RR_format(source, dest, op, 0); + format_addsub(stream, (op_num & 0x4) ? "NEGS" : "NEG", dest, source, source_bit, source_code); + break; + + // CMPI + case 0x60: case 0x61: case 0x62: case 0x63: + { + const uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0); + util::stream_format(stream, "CMPI %s, $%x", dest, imm); + } + break; + + // MOVI + case 0x64: case 0x65: case 0x66: case 0x67: + { + const uint32_t imm = Rimm_format(dest, op, pc, read_hw, h_flag); + util::stream_format(stream, "MOVI %s, $%x", dest, imm); + } + break; + + case 0x68: case 0x69: case 0x6a: case 0x6b: // ADDI + case 0x6c: case 0x6d: case 0x6e: case 0x6f: // ADDSI + if (!DASM_N_VALUE(op)) + { + util::stream_format(stream, "%-7s %s, CZ", (op_num & 0x4) ? "ADDSI" : "ADDI", dest); + } + else + { + const uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0); + util::stream_format(stream, "%-7s %s, $%x", (op_num & 0x4) ? "ADDSI" : "ADDI", dest, imm); + if (!dest_bit && (dest_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t(pc + size + imm)); + } + break; + + // CMPBI + case 0x70: case 0x71: case 0x72: case 0x73: + if (!DASM_N_VALUE(op)) + { + util::stream_format(stream, "CMPBI %s, ANYBZ", dest); + } + else + { + uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0); + if (DASM_N_VALUE(op) == 31) + imm = 0x7fffffff; //bit 31 = 0, others = 1 + + util::stream_format(stream, "CMPBI %s, $%x", dest, imm); + } + break; + + // ANDNI + case 0x74: case 0x75: case 0x76: case 0x77: + { + uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0); + if (DASM_N_VALUE(op) == 31) + imm = 0x7fffffff; //bit 31 = 0, others = 1 + + util::stream_format(stream, "ANDNI %s, $%x", dest, imm); + if (!dest_bit && (dest_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t((pc + size) & ~imm)); + } + break; + + // ORI + case 0x78: case 0x79: case 0x7a: case 0x7b: + { + const uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0); + + util::stream_format(stream, "ORI %s, $%x", dest, imm); + if (!dest_bit && (dest_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t((pc + size) | imm)); + } + break; + + // XORI + case 0x7c: case 0x7d: case 0x7e: case 0x7f: + { + const uint32_t imm = Rimm_format(dest, op, pc, read_hw, 0); + + util::stream_format(stream, "XORI %s, $%x", dest, imm); + if (!dest_bit && (dest_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t((pc + size) ^ imm)); + } + break; + + case 0x80: case 0x81: // SHRDI + case 0x84: case 0x85: // SARDI + { + const uint8_t n = Ln_format(dest, op); + util::stream_format(stream, "S%cRDI %s, $%x", (op_num & 0x4) ? 'A' : 'H', dest, n); + } + break; + + case 0x82: // SHRD + case 0x83: // SHR + case 0x86: // SARD + case 0x87: // SAR + LL_format(source, dest, op); + util::stream_format(stream, "S%cR%c %s, %s", + (op_num & 0x4) ? 'A' : 'H', + (op_num & 0x1) ? ' ' : 'D', + dest, + source); + break; + + // SHLDI + case 0x88: case 0x89: + { + const uint8_t n = Ln_format(dest, op); + util::stream_format(stream, "SHLDI %s, $%x", dest, n); + } + break; + + case 0x8a: // SHLD + case 0x8b: // SHL + LL_format(source, dest, op); + util::stream_format(stream, "SHL%c %s, %s", (op_num & 0x1) ? ' ' : 'D', dest, source); + break; + + // RESERVED + case 0x8c: case 0x8d: + case 0xac: case 0xad: case 0xae: case 0xaf: + util::stream_format(stream, "D.HU $%04x", op); + break; + + // TESTLZ + case 0x8e: + LL_format(source, dest, op); + util::stream_format(stream, "TESTLZ %s, %s", dest, source); + break; + + // ROL + case 0x8f: + LL_format(source, dest, op); + util::stream_format(stream, "ROL %s, %s", dest, source); + break; + + case 0x90: case 0x91: case 0x92: case 0x93: // LDxx.D/A/IOD/IOA + case 0x98: case 0x99: case 0x9a: case 0x9b: // STxx.D/A/IOD/IOA + { + const uint16_t next_op = read_hw(pc + 2); + const uint32_t dis = RRdis_format(source, dest, op, next_op, pc, read_hw); + + if (size == 2) + size = 4; + + if ((op_num & 0x8) && !source_bit && (source_code == SR_REGISTER)) + source = "0"; + + if (!dest_bit && (dest_code == SR_REGISTER)) + dest = "0"; + + const std::string_view inst = (op_num & 0x8) ? "ST" : "LD"; + const char mode = (!dest_bit && (dest_code == SR_REGISTER)) ? 'A' : 'D'; + + switch (DD(next_op)) + { + case 0: + // LD/STBS.D/A + util::stream_format(stream, "%sBS.%c %s, %s, $%x", inst, mode, dest, source, dis); + if (!dest_bit && (dest_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t(pc + size + dis)); + break; + + case 1: + // LD/STBU.D/A + util::stream_format(stream, "%sBU.%c %s, %s, $%x", inst, mode, dest, source, dis); + if (!dest_bit && (dest_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t(pc + size + dis)); + break; + + case 2: + // LD/STHU.D/A + // LD/STHS.D/A + util::stream_format(stream, "%sH%c.%c %s, %s, $%x", inst, (dis & 1) ? 'S' : 'U', mode, dest, source, dis & ~1); + if (!dest_bit && (dest_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~1)) & ~1); + break; + + case 3: + if (dis & 2) + { + // LD/STW.IOD/A + // LD/STD.IOD/A + util::stream_format(stream, "%s%c.IO%c %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', mode, dest, source, dis & ~3); + } + else + { + // LD/STW.D/A + // LD/STD.D/A + util::stream_format(stream, "%s%c.%c %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', mode, dest, source, dis & ~3); + } + if (!dest_bit && (dest_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~3)) & ~3); + break; + } + } + break; + + case 0x94: case 0x95: case 0x96: case 0x97: // LDxx.N/S + case 0x9c: case 0x9d: case 0x9e: case 0x9f: // STxx.N/S + { + const uint16_t next_op = read_hw(pc + 2); + const uint32_t dis = RRdis_format(source, dest, op, next_op, pc, read_hw); + + if (size == 2) + size = 4; + + if (!dest_bit && ((dest_code == PC_REGISTER) || (dest_code == SR_REGISTER))) + { + util::stream_format(stream, "Reserved"); + break; + } + + if ((op_num & 0x8) && !source_bit && (source_code == SR_REGISTER)) + source = "0"; + + const std::string_view inst = (op_num & 0x8) ? "ST" : "LD"; + + switch (DD(next_op)) + { + case 0: + // LD/STBS.N + util::stream_format(stream, "%sBS.N %s, %s, $%x", inst, dest, source, dis); + break; + + case 1: + // LD/STBU.N + util::stream_format(stream, "%sBU.N %s, %s, $%x", inst, dest, source, dis); + break; + + case 2: + // LD/STHU.N + // LD/STHS.N + util::stream_format(stream, "%sH%c.N %s, %s, $%x", inst, (dis & 1) ? 'S' : 'U', dest, source, dis & ~1); + break; + + case 3: + if ((dis & 3) == 3) + { + // LD/STW.S + util::stream_format(stream, "%sW.S %s, %s, $%x", inst, dest, source, dis & ~3); + } + else if ((dis & 3) == 2) + { + // Reserved + util::stream_format(stream, "Reserved"); + } + else + { + // LD/STW.N + // LD/STD.N + util::stream_format(stream, "%s%c.N %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', dest, source, dis & ~3); + } + break; + } + } + break; + + case 0xa0: case 0xa1: case 0xa2: case 0xa3: // SHRI + case 0xa4: case 0xa5: case 0xa6: case 0xa7: // SARI + { + const uint8_t n = Rn_format(dest, op); + util::stream_format(stream, "S%cRI %s, $%x", (op_num & 0x4) ? 'A' : 'H', dest, n); + } + break; + + // SHLI + case 0xa8: case 0xa9: case 0xaa: case 0xab: + { + const uint8_t n = Rn_format(dest, op); + util::stream_format(stream, "SHLI %s, $%x", dest, n); + } + break; + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: // MULU + case 0xb4: case 0xb5: case 0xb6: case 0xb7: // MULS + RR_format(source, dest, op, 0); + util::stream_format(stream, "MUL%c %s, %s", (op_num & 0x4) ? 'S' : 'U', dest, source); + break; + + // SETxx - SETADR - FETCH + case 0xb8: case 0xb9: case 0xba: case 0xbb: + { + const uint8_t n = Rn_format(dest, op); + + if (!dest_bit && (dest_code == PC_REGISTER)) + { + // SETxx with PC as destination is reserved for future use + util::stream_format(stream, "D.HU $%04x", op); + } + else if (!dest_bit && (dest_code == SR_REGISTER)) + { + util::stream_format(stream, "FETCH $%x", (n / 2) + 1); + } + else + { + char const *const inst = SETxx[n]; + if (inst) + util::stream_format(stream, "%-7s %s", inst, dest); + else + util::stream_format(stream, "D.HU $%04x", op); + } + } + break; + + // MUL + case 0xbc: case 0xbd: case 0xbe: case 0xbf: + RR_format(source, dest, op, 0); + util::stream_format(stream, "MUL %s, %s", dest, source); + break; + + case 0xc0: // FADD + case 0xc1: // FADDD + case 0xc2: // FSUB + case 0xc3: // FSUBD + case 0xc4: // FMUL + case 0xc5: // FMULD + case 0xc6: // FDIV + case 0xc7: // FDIVD + case 0xc8: // FCMP + case 0xc9: // FCMPD + case 0xca: // FCMPU + case 0xcb: // FCMPUD + case 0xcc: // FCVT + case 0xcd: // FCVTD + LL_format(source, dest, op); + util::stream_format(stream, "%-7s %s, %s", Fxxx[op_num & 0xf], dest, source); + break; + + // EXTEND + case 0xce: + { + LL_format(source, dest, op); + + pc += 2; + const uint16_t extended_op = read_hw(pc); + + size = 4; + + switch (extended_op) + { + case 0x100: + case EMUL: + util::stream_format(stream, "EMUL %s, %s", dest, source); + break; + + case EMULU: + util::stream_format(stream, "EMULU %s, %s", dest, source); + break; + + case EMULS: + util::stream_format(stream, "EMULS %s, %s", dest, source); + break; + + case EMAC: + util::stream_format(stream, "EMAC %s, %s", dest, source); + break; + + case EMACD: + util::stream_format(stream, "EMACD %s, %s", dest, source); + break; + + case EMSUB: + util::stream_format(stream, "EMSUB %s, %s", dest, source); + break; + + case EMSUBD: + util::stream_format(stream, "EMSUBD %s, %s", dest, source); + break; + + case EHMAC: + util::stream_format(stream, "EHMAC %s, %s", dest, source); + break; + + case EHMACD: + util::stream_format(stream, "EHMACD %s, %s", dest, source); + break; + + case EHCMULD: + util::stream_format(stream, "EHCMULD %s, %s", dest, source); + break; + + case EHCMACD: + util::stream_format(stream, "EHCMACD %s, %s", dest, source); + break; + + case EHCSUMD: + util::stream_format(stream, "EHCSUMD %s, %s", dest, source); + break; + + case EHCFFTD: + util::stream_format(stream, "EHCFFTD %s, %s", dest, source); + break; + + case EHCFFTSD: + util::stream_format(stream, "EHCFFTSD %s, %s", dest, source); + break; + + default: + util::stream_format(stream, "Ext. OP $%X @ %X", extended_op, pc); + osd_printf_verbose("Illegal Extended Opcode: %X @ %X\n", extended_op, pc); + break; + } + } + break; + + // DO + case 0xcf: + LL_format(source, dest, op); + util::stream_format(stream, "DO %s, %s", dest, source); + break; + + case 0xd0: case 0xd1: // LDW.R + case 0xd2: case 0xd3: // LDD.R + case 0xd4: case 0xd5: // LDW.P + case 0xd6: case 0xd7: // LDD.P + case 0xd8: case 0xd9: // STW.R + case 0xda: case 0xdb: // STD.R + case 0xdc: case 0xdd: // STW.P + case 0xde: case 0xdf: // STD.P + LR_format(source, dest, op); + util::stream_format(stream, "%s%c.%c %s, %s", + (op_num & 0x8) ? "ST" : "LD", + (op_num & 0x2) ? 'D' : 'W', + (op_num & 0x4) ? 'P' : 'R', + dest, + ((op_num & 0x8) && !source_bit && (source_code == SR_REGISTER)) ? "0" : source); + break; + + case 0xe0: // DBV + case 0xe1: // DBNV + case 0xe2: // DBE + case 0xe3: // DBNE + case 0xe4: // DBC + case 0xe5: // DBNC + case 0xe6: // DBSE + case 0xe7: // DBHT + case 0xe8: // DBN + case 0xe9: // DBNN + case 0xea: // DBLE + case 0xeb: // DBGT + case 0xec: // DBR + { + const int32_t rel = PCrel_format(op, pc, read_hw) + 2; + util::stream_format(stream, "D%-6s $%x", Bxx[op_num & 0xf], rel); + if (op_num != 0xec) + flags = STEP_COND | step_over_extra(1); + } + break; + + // FRAME + case 0xed: + LL_format(source, dest, op); + util::stream_format(stream, "FRAME %s, %s", dest, source); + break; + + // CALL + case 0xee: case 0xef: + { + const uint32_t const_val = LRconst_format(source, dest, op, pc, read_hw); + + util::stream_format(stream, "CALL %s, %s, $%x", dest, (!source_bit && (source_code == SR_REGISTER)) ? "0" : source, const_val); + if (!source_bit && (source_code == PC_REGISTER)) + util::stream_format(stream, " ; $%x", uint32_t(pc + size + const_val)); + flags = STEP_OVER; + } + break; + + case 0xf0: // BV + case 0xf1: // BNV + case 0xf2: // BE + case 0xf3: // BNE + case 0xf4: // BC + case 0xf5: // BNC + case 0xf6: // BSE + case 0xf7: // BHT + case 0xf8: // BN + case 0xf9: // BNN + case 0xfa: // BLE + case 0xfb: // BGT + case 0xfc: // BR + { + const int32_t rel = PCrel_format(op, pc, read_hw) + 2; + util::stream_format(stream, "%-7s $%x", Bxx[op_num & 0xf], rel); + if (op_num != 0xfc) + flags = STEP_COND; + } + break; + + // TRAPxx - TRAP + case 0xfd: case 0xfe: case 0xff: + { + const uint8_t code = ((op & 0x300) >> 6) | (op & 0x03); + const uint8_t trapno = (op & 0xfc) >> 2; + + util::stream_format(stream, "%-7s %d", TRAPxx[code], trapno); + if (code == TRAP) + flags = STEP_OVER; + else + flags = STEP_OVER | STEP_COND; + } + break; + } + + return size | flags | SUPPORTED; +} diff --git a/src/devices/cpu/e132xs/e1dasm.h b/src/devices/cpu/e132xs/e1dasm.h new file mode 100644 index 00000000000..4a3803cc513 --- /dev/null +++ b/src/devices/cpu/e132xs/e1dasm.h @@ -0,0 +1,51 @@ +// license:BSD-3-Clause +// copyright-holders:Pierpaolo Prazzoli +/* + + Hyperstone E1 disassembler + written by Pierpaolo Prazzoli + +*/ + +#ifndef MAME_CPU_E132XS_E1DASM_H +#define MAME_CPU_E132XS_E1DASM_H + +#pragma once + +#include +#include + + +class hyperstone_disassembler : public util::disasm_interface +{ +public: + struct config + { + virtual ~config() = default; + + virtual bool get_h() const = 0; + }; + + hyperstone_disassembler(config *conf); + virtual ~hyperstone_disassembler() = default; + + virtual u32 opcode_alignment() const override; + virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; + + offs_t disassemble_one(std::ostream &stream, offs_t pc, const uint16_t *opptr); + +private: + config *m_config; + + int size; // FIXME: not concurrency-safe + + template offs_t do_disassemble(std::ostream &stream, offs_t pc, T &&read_hw); + + template uint32_t LRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, T &&read_hw); + template uint32_t RRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, T &&read_hw); + template int32_t Rimm_format(std::string_view &dest, uint16_t op, offs_t pc, T &&read_hw, unsigned h_flag); + template int32_t PCrel_format(uint16_t op, offs_t pc, T &&read_hw); + template uint32_t RRdis_format(std::string_view &source, std::string_view &dest, uint16_t op, uint16_t next_op, offs_t pc, T &&read_hw); +}; + +#endif // MAME_CPU_E132XS_E1DASM_H diff --git a/src/devices/cpu/e132xs/e1defs.h b/src/devices/cpu/e132xs/e1defs.h new file mode 100644 index 00000000000..860d04bbb2e --- /dev/null +++ b/src/devices/cpu/e132xs/e1defs.h @@ -0,0 +1,247 @@ +// license:BSD-3-Clause +// copyright-holders:Pierpaolo Prazzoli +#ifndef MAME_CPU_E132XS_E1DEFS_H +#define MAME_CPU_E132XS_E1DEFS_H + +#pragma once + +/*************************************************************************** + COMPILE-TIME DEFINITIONS +***************************************************************************/ + +// compilation boundaries -- how far back/forward does the analysis extend? +enum : u32 +{ + COMPILE_BACKWARDS_BYTES = 128, + COMPILE_FORWARDS_BYTES = 512, + COMPILE_MAX_INSTRUCTIONS = (COMPILE_BACKWARDS_BYTES / 2) + (COMPILE_FORWARDS_BYTES / 2), + COMPILE_MAX_SEQUENCE = 64 +}; + +enum +{ + PC_REGISTER = 0, + SR_REGISTER = 1, + FER_REGISTER = 2, + SP_REGISTER = 18, + UB_REGISTER = 19, + BCR_REGISTER = 20, + TPR_REGISTER = 21, + TCR_REGISTER = 22, + TR_REGISTER = 23, + WCR_REGISTER = 24, + ISR_REGISTER = 25, + FCR_REGISTER = 26, + MCR_REGISTER = 27 +}; + +#define X_CODE(val) ((val & 0x7000) >> 12) +#define E_BIT(val) ((val & 0x8000) >> 15) +#define S_BIT_CONST(val) ((val & 0x4000) >> 14) +#define DD(val) ((val & 0x3000) >> 12) + +#define S_BIT ((OP & 0x100) >> 8) +#define D_BIT ((OP & 0x200) >> 9) +#define N_VALUE (((OP & 0x100) >> 4) | (OP & 0x0f)) +#define HI_N_VALUE (0x10 | (OP & 0x0f)) +#define LO_N_VALUE (OP & 0x0f) +#define N_OP_MASK (m_op & 0x10f) +#define DRC_HI_N_VALUE (0x10 | (op & 0x0f)) +#define DRC_LO_N_VALUE (op & 0x0f) +#define DRC_N_OP_MASK (op & 0x10f) +#define DST_CODE ((OP & 0xf0) >> 4) +#define SRC_CODE (OP & 0x0f) +#define SIGN_BIT(val) ((val & 0x80000000) >> 31) +#define SIGN_TO_N(val) ((val & 0x80000000) >> 29) +#define SIGN64_TO_N(val) ((val & 0x8000000000000000ULL) >> 61) + +/* Extended DSP instructions */ +#define EHMAC 0x02a +#define EHMACD 0x02e +#define EHCMULD 0x046 +#define EHCMACD 0x04e +#define EHCSUMD 0x086 +#define EHCFFTD 0x096 +#define EMUL_N 0x100 +#define EMUL 0x102 +#define EMULU 0x104 +#define EMULS 0x106 +#define EMAC 0x10a +#define EMACD 0x10e +#define EMSUB 0x11a +#define EMSUBD 0x11e +#define EHCFFTSD 0x296 + +// IRQ numbers +enum +{ + IRQ_INT1 = 0, + IRQ_INT2 = 1, + IRQ_INT3 = 2, + IRQ_INT4 = 3, + IRQ_IO1 = 4, + IRQ_IO2 = 5, + IRQ_IO3 = 6 +}; + +// Trap numbers +enum +{ + TRAPNO_IO2 = 48, + TRAPNO_IO1 = 49, + TRAPNO_INT4 = 50, + TRAPNO_INT3 = 51, + TRAPNO_INT2 = 52, + TRAPNO_INT1 = 53, + TRAPNO_IO3 = 54, + TRAPNO_TIMER = 55, + TRAPNO_RESERVED1 = 56, + TRAPNO_TRACE_EXCEPTION = 57, + TRAPNO_PARITY_ERROR = 58, + TRAPNO_EXTENDED_OVERFLOW = 59, + TRAPNO_RANGE_ERROR = 60, + TRAPNO_POINTER_ERROR = TRAPNO_RANGE_ERROR, + TRAPNO_PRIVILEGE_ERROR = TRAPNO_RANGE_ERROR, + TRAPNO_FRAME_ERROR = TRAPNO_RANGE_ERROR, + TRAPNO_RESERVED2 = 61, + TRAPNO_RESET = 62, // reserved if not mapped @ MEM3 + TRAPNO_ERROR_ENTRY = 63 // for instruction code of all ones +}; + +/* Trap codes */ +#define TRAPLE 4 +#define TRAPGT 5 +#define TRAPLT 6 +#define TRAPGE 7 +#define TRAPSE 8 +#define TRAPHT 9 +#define TRAPST 10 +#define TRAPHE 11 +#define TRAPE 12 +#define TRAPNE 13 +#define TRAPV 14 +#define TRAP 15 + +/* Entry point to get trap locations or emulated code associated */ +#define E132XS_ENTRY_MEM0 0 +#define E132XS_ENTRY_MEM1 1 +#define E132XS_ENTRY_MEM2 2 +#define E132XS_ENTRY_IRAM 3 +#define E132XS_ENTRY_MEM3 7 + +/* Memory access */ +#define READ_B(addr) m_read_byte(addr) +#define READ_HW(addr) m_read_halfword(addr) +#define READ_W(addr) m_read_word(addr) + +#define WRITE_B(addr, data) m_write_byte(addr, data) +#define WRITE_HW(addr, data) m_write_halfword(addr, data) +#define WRITE_W(addr, data) m_write_word(addr, data) + + +/* I/O access */ +#define IO_READ_W(addr) m_read_io(addr) +#define IO_WRITE_W(addr, data) m_write_io(addr, data) + +// set C in adds/addsi/subs/sums +#define SETCARRYS 0 + +/* Registers */ + +/* Internal registers */ + +#define OP m_op +#define PC m_core->global_regs[0] //Program Counter +#define SR m_core->global_regs[1] //Status Register +#define FER m_core->global_regs[2] //Floating-Point Exception Register +// 03 - 15 General Purpose Registers +// 16 - 17 Reserved +#define SP m_core->global_regs[18] //Stack Pointer +#define UB m_core->global_regs[19] //Upper Stack Bound +#define BCR m_core->global_regs[20] //Bus Control Register +#define TPR m_core->global_regs[21] //Timer Prescaler Register +#define TCR m_core->global_regs[22] //Timer Compare Register +#define TR compute_tr() //Timer Register +#define WCR m_core->global_regs[24] //Watchdog Compare Register +#define ISR m_core->global_regs[25] //Input Status Register +#define FCR m_core->global_regs[26] //Function Control Register +#define MCR m_core->global_regs[27] //Memory Control Register +// 28 - 31 Reserved + +constexpr uint32_t C_MASK = 0x00000001; +constexpr uint32_t Z_MASK = 0x00000002; +constexpr uint32_t N_MASK = 0x00000004; +constexpr uint32_t V_MASK = 0x00000008; +constexpr uint32_t M_MASK = 0x00000010; +constexpr uint32_t H_MASK = 0x00000020; +constexpr uint32_t I_MASK = 0x00000080; +constexpr uint32_t L_MASK = 0x00008000; +constexpr uint32_t T_MASK = 0x00010000; +constexpr uint32_t P_MASK = 0x00020000; +constexpr uint32_t S_MASK = 0x00040000; +constexpr uint32_t ILC_MASK = 0x00180000; +constexpr uint32_t FL_MASK = 0x01e00000; +constexpr uint32_t FP_MASK = 0xfe000000; + +constexpr int C_SHIFT = 0; +constexpr int Z_SHIFT = 1; +constexpr int N_SHIFT = 2; +constexpr int V_SHIFT = 3; +constexpr int L_SHIFT = 15; +constexpr int T_SHIFT = 16; +constexpr int S_SHIFT = 18; +constexpr int ILC_SHIFT = 19; +constexpr int FL_SHIFT = 21; +constexpr int FP_SHIFT = 25; + +/* SR flags */ +#define GET_C ( SR & C_MASK) // bit 0 //CARRY +#define GET_Z ((SR & Z_MASK)>>1) // bit 1 //ZERO +#define GET_N ((SR & N_MASK)>>2) // bit 2 //NEGATIVE +#define GET_V ((SR & V_MASK)>>3) // bit 3 //OVERFLOW +#define GET_M ((SR & M_MASK)>>4) // bit 4 //CACHE-MODE +#define GET_H ((SR & H_MASK)>>5) // bit 5 //HIGHGLOBAL +// bit 6 RESERVED (always 0) +#define GET_I ((SR & I_MASK)>>7) // bit 7 //INTERRUPT-MODE +#define GET_FTE ((SR & 0x00001f00)>>8) // bits 12 - 8 //Floating-Point Trap Enable +#define GET_FRM ((SR & 0x00006000)>>13) // bits 14 - 13 //Floating-Point Rounding Mode +#define GET_L ((SR & L_MASK)>>15) // bit 15 //INTERRUPT-LOCK +#define GET_T ((SR & T_MASK)>>16) // bit 16 //TRACE-MODE +#define GET_P ((SR & P_MASK)>>17) // bit 17 //TRACE PENDING +#define GET_S ((SR & S_MASK)>>18) // bit 18 //SUPERVISOR STATE +#define GET_ILC ((SR & 0x00180000)>>19) // bits 20 - 19 //INSTRUCTION-LENGTH +/* if FL is zero it is always interpreted as 16 */ +#define GET_FL m_core->fl_lut[((SR >> 21) & 0xf)] // bits 24 - 21 //FRAME LENGTH +#define GET_FP ((SR & 0xfe000000)>>25) // bits 31 - 25 //FRAME POINTER + +#define SET_C(val) (SR = (SR & ~C_MASK) | (val)) +#define SET_Z(val) (SR = (SR & ~Z_MASK) | ((val) << 1)) +#define SET_N(val) (SR = (SR & ~N_MASK) | ((val) << 2)) +#define SET_V(val) (SR = (SR & ~V_MASK) | ((val) << 3)) +#define SET_M(val) (SR = (SR & ~M_MASK) | ((val) << 4)) +#define SET_H(val) (SR = (SR & ~H_MASK) | ((val) << 5)) +#define SET_I(val) (SR = (SR & ~I_MASK) | ((val) << 7)) +#define SET_FTE(val) (SR = (SR & ~0x00001f00) | ((val) << 8)) +#define SET_FRM(val) (SR = (SR & ~0x00006000) | ((val) << 13)) +#define SET_L(val) (SR = (SR & ~L_MASK) | ((val) << 15)) +#define SET_T(val) (SR = (SR & ~T_MASK) | ((val) << 16)) +#define SET_P(val) (SR = (SR & ~P_MASK) | ((val) << 17)) +#define SET_S(val) (SR = (SR & ~S_MASK) | ((val) << 18)) +#define SET_ILC(val) (SR = (SR & 0xffe7ffff) | (val)) +#define SET_FL(val) (SR = (SR & ~0x01e00000) | ((val) << 21)) +#define SET_FP(val) (SR = (SR & ~0xfe000000) | ((val) << 25)) + +#define SET_PC(val) PC = ((val) & 0xfffffffe) //PC(0) = 0 +#define SET_SP(val) SP = ((val) & 0xfffffffc) //SP(0) = SP(1) = 0 +#define SET_UB(val) UB = ((val) & 0xfffffffc) //UB(0) = UB(1) = 0 + +#define SET_LOW_SR(val) (SR = (SR & 0xffff0000) | ((val) & 0x0000ffff)) // when SR is addressed, only low 16 bits can be changed + + +/* FER flags */ +#define GET_ACCRUED (FER & 0x0000001f) //bits 4 - 0 //Floating-Point Accrued Exceptions +#define GET_ACTUAL (FER & 0x00001f00) //bits 12 - 8 //Floating-Point Actual Exceptions +//other bits are reversed, in particular 7 - 5 for the operating system. +//the user program can only change the above 2 flags + +#endif // MAME_CPU_E132XS_E1DEFS_H diff --git a/src/devices/cpu/e132xs/e1fe.cpp b/src/devices/cpu/e132xs/e1fe.cpp new file mode 100644 index 00000000000..6b8852a0f6c --- /dev/null +++ b/src/devices/cpu/e132xs/e1fe.cpp @@ -0,0 +1,1136 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + e1fe.cpp + + Hyperstone E1 instruction decoder + +***************************************************************************/ + +#include "emu.h" +#include "e1fe.h" + +#include "e1defs.h" + +#include "cpu/drcfe.ipp" + + + +void hyperstone_device::opcode_desc::log_flags(std::ostream &stream) const +{ + // branches + if (is_unconditional_branch()) + stream << 'U'; + else if (is_conditional_branch()) + stream << 'C'; + else + stream << '.'; + + // intrablock branches + stream << (intrablock_branch() ? 'i' : '.'); + + // branch targets + stream << (is_branch_target() ? 'B' : '.'); + + // delay slots + stream << (in_delay_slot() ? 'D' : '.'); + + // check H flag + stream << (check_h() ? 'H' : '.'); + + // modes + stream << (can_change_modes() ? 'M' : '.'); + + // exceptions + if (will_cause_exception()) + stream << 'E'; + else if (can_cause_exception()) + stream << 'e'; + else + stream << '.'; + + // read/write + if (reads_memory()) + stream << 'R'; + else if (writes_memory()) + stream << 'W'; + else + stream << '.'; + + // TLB validation + stream << (validate_tlb() ? 'V' : '.'); + + // redispatch + stream << (redispatch() ? 'R' : '.'); +} + +void hyperstone_device::opcode_desc::log_registers_used(std::ostream &stream) const +{ + stream << "[use:"; + log_register_list(stream, regin, nullptr); + stream << ']'; +} + +void hyperstone_device::opcode_desc::log_registers_modified(std::ostream &stream) const +{ + stream << "[mod:"; + log_register_list(stream, regout, ®req); + stream << ']'; +} + +void hyperstone_device::opcode_desc::log_register_list(std::ostream &stream, const regmask ®list, const regmask *regnostarlist) +{ + int count = 0; + + for (int regnum = 0; regnum < 32; regnum++) + { + if (reglist[REG_G0 + regnum]) + { + if (count++) + stream << ','; + stream << 'G' << regnum; + if (regnostarlist && !(*regnostarlist)[REG_G0 + regnum]) + stream << '*'; + } + } + + const auto log_bit = + [&stream, &count, ®list, ®nostarlist] (size_t bit, const char *name) + { + if (reglist[bit]) + { + if (count++) + stream << ','; + stream << name; + if (regnostarlist && !(*regnostarlist)[bit]) + stream << '*'; + } + }; + + log_bit(REG_C, "C"); + log_bit(REG_Z, "Z"); + log_bit(REG_N, "N"); + log_bit(REG_V, "V"); + log_bit(REG_FP, "FP"); +} + + +hyperstone_device::frontend::frontend(hyperstone_device &cpu, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : drc_frontend_base(cpu.space_config(AS_PROGRAM)->page_shift(), window_start, window_end, max_sequence) + , m_cpu(cpu) +{ +} + +hyperstone_device::frontend::~frontend() +{ +} + +hyperstone_device::opcode_desc const *hyperstone_device::frontend::describe_code(offs_t startpc) +{ + return do_describe_code( + [this] (opcode_desc &desc, opcode_desc const *prev) { return describe(desc, prev); }, + startpc); +} + + +inline void hyperstone_device::frontend::read_op(opcode_desc &desc) +{ + desc.opptr[0] = m_cpu.m_pr16(desc.pc); +} + +inline void hyperstone_device::frontend::read_imm1(opcode_desc &desc) +{ + desc.opptr[1] = m_cpu.m_pr16(desc.pc + 2); +} + +inline void hyperstone_device::frontend::read_imm2(opcode_desc &desc) +{ + desc.opptr[2] = m_cpu.m_pr16(desc.pc + 4); +} + +inline void hyperstone_device::frontend::decode_const(opcode_desc &desc) +{ + read_imm1(desc); + int32_t const const1 = util::sext(desc.opptr[1], 15); + if (!E_BIT(desc.opptr[1])) + { + desc.length = 4; + desc.imm = uint32_t(const1); + } + else + { + read_imm2(desc); + desc.length = 6; + desc.imm = uint32_t(const1 << 16) | desc.opptr[2]; + } +} + + +inline void hyperstone_device::frontend::decode_ll(opcode_desc &desc) +{ + uint16_t const op = desc.opptr[0]; + desc.dst_code = BIT(op, 4, 4); + desc.src_code = BIT(op, 0, 4); + desc.dst_local = true; + desc.src_local = true; +} + +inline void hyperstone_device::frontend::decode_llext(opcode_desc &desc) +{ + decode_ll(desc); + read_imm1(desc); + desc.length = 4; +} + +inline void hyperstone_device::frontend::decode_lr(opcode_desc &desc) +{ + uint16_t const op = desc.opptr[0]; + desc.dst_code = BIT(op, 4, 4); + desc.src_code = BIT(op, 0, 4); + desc.dst_local = true; + desc.src_local = BIT(op, 8); +} + +inline void hyperstone_device::frontend::decode_rr(opcode_desc &desc) +{ + uint16_t const op = desc.opptr[0]; + desc.dst_code = BIT(op, 4, 4); + desc.src_code = BIT(op, 0, 4); + desc.dst_local = BIT(op, 9); + desc.src_local = BIT(op, 8); +} + +inline void hyperstone_device::frontend::decode_ln(opcode_desc &desc) +{ + uint16_t const op = desc.opptr[0]; + desc.dst_code = BIT(op, 4, 4); + desc.dst_local = true; + desc.imm = (BIT(op, 8) << 4) | BIT(op, 0, 4); +} + +inline void hyperstone_device::frontend::decode_rn(opcode_desc &desc) +{ + uint16_t const op = desc.opptr[0]; + desc.dst_code = BIT(op, 4, 4); + desc.dst_local = BIT(op, 9); + desc.imm = (BIT(op, 8) << 4) | BIT(op, 0, 4); +} + +inline void hyperstone_device::frontend::decode_pcrel(opcode_desc &desc) +{ + if (!BIT(desc.opptr[0], 7)) + { + uint32_t const low_rel = BIT(desc.opptr[0], 1, 6); + int32_t const s = util::sext(desc.opptr[0], 1); + desc.imm = uint32_t(s << 7) | (low_rel << 1); + } + else + { + read_imm1(desc); + desc.length = 4; + uint32_t const high_rel = BIT(desc.opptr[0], 0, 7); + uint32_t const low_rel = BIT(desc.opptr[1], 1, 15); + int32_t const s = util::sext(desc.opptr[1], 1); + desc.imm = uint32_t(s << 23) | (high_rel << 16) | (low_rel << 1); + } +} + +inline void hyperstone_device::frontend::decode_lrconst(opcode_desc &desc) +{ + decode_lr(desc); + decode_const(desc); +} + +inline void hyperstone_device::frontend::decode_rrconst(opcode_desc &desc) +{ + decode_rr(desc); + decode_const(desc); +} + +inline void hyperstone_device::frontend::decode_rrdis(opcode_desc &desc) +{ + decode_rr(desc); + read_imm1(desc); + int32_t const dis1 = util::sext((BIT(desc.opptr[1], 14) << 12) | BIT(desc.opptr[1], 0, 12), 13); + if (!E_BIT(desc.opptr[1])) + { + desc.length = 4; + desc.imm = uint32_t(dis1); + } + else + { + read_imm2(desc); + desc.length = 6; + desc.imm = uint32_t(dis1 << 16) | desc.opptr[2]; + } +} + +inline void hyperstone_device::frontend::decode_rimm(opcode_desc &desc, bool cmpbi_andni) +{ + constexpr int32_t table[32] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, -1, -1, -1, 32, 64, 128, int32_t(uint32_t(0x80000000)), + -8, -7, -6, -5, -4, -3, -2, -1 }; + + uint16_t const op = desc.opptr[0]; + desc.dst_code = BIT(op, 4, 4); + desc.dst_local = BIT(op, 9); + + uint16_t const n = (BIT(op, 8) << 4) | BIT(op, 0, 4); + switch (n) + { + case 17: + read_imm1(desc); + read_imm2(desc); + desc.length = 6; + desc.imm = (uint32_t(desc.opptr[1]) << 16) | desc.opptr[2]; + break; + case 18: + case 19: + read_imm1(desc); + desc.length = 4; + desc.imm = (BIT(n, 0) ? 0xffff0000U : 0U) | desc.opptr[1]; + break; + case 31: + desc.imm = cmpbi_andni ? 0x7fffffff : uint32_t(table[n]); + break; + default: + desc.imm = uint32_t(table[n]); + } +} + +inline void hyperstone_device::frontend::decode_rrlim(opcode_desc &desc) +{ + decode_rr(desc); + read_imm1(desc); + uint32_t const lim1 = BIT(desc.opptr[1], 0, 12); + if (!E_BIT(desc.opptr[1])) + { + desc.length = 4; + desc.imm = lim1; + } + else + { + read_imm2(desc); + desc.length = 6; + desc.imm = (lim1 << 16) | desc.opptr[2]; + } +} + + +/*------------------------------------------------- + describe - build a description of a single + instruction +-------------------------------------------------*/ + +bool hyperstone_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) +{ + read_op(desc); + uint16_t const op = desc.opptr[0]; + + // most instructions are 2 bytes and a single cycle + desc.length = 2; + desc.delayslots = 0; + + switch (op >> 8) + { + case 0x00: // chk global,global + case 0x01: // chk global,local + case 0x02: // chk local,global + case 0x03: // chk local,local + decode_rr(desc); + if (!desc.dst_is_src() || desc.src_is_sr()) + { + desc.set_can_cause_exception(); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.dst_local) + desc.set_g_used(desc.dst_code); + if (!desc.src_local && (desc.src_code != SR_REGISTER)) + desc.set_g_used(desc.src_code); + } + else if (desc.dst_is_pc()) + { + desc.set_will_cause_exception(); + desc.set_end_sequence(); + } + break; + case 0x04: // movd global,global + case 0x05: // movd global,local + case 0x06: // movd local,global + case 0x07: // movd local,local + decode_rr(desc); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.src_local && (desc.dst_is_pc() || !desc.src_is_sr())) + { + desc.set_g_used(desc.src_code); + desc.set_g_used(desc.src_code + 1); + } + if (!desc.dst_local) + { + desc.set_g_modified(desc.dst_code); + desc.set_g_modified(desc.dst_code + 1); + } + desc.set_znv_modified(); + if (desc.dst_is_pc()) + { + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.set_g_used(SP_REGISTER); + desc.set_g_modified(SP_REGISTER); + desc.set_fp_modified(); + desc.set_is_unconditional_branch(); + desc.set_can_cause_exception(); + desc.set_end_sequence(); + desc.set_can_change_modes(); + desc.set_reads_memory(); + } + break; + case 0x08: // divu global,global + case 0x09: // divu global,local + case 0x0a: // divu local,global + case 0x0b: // divu local,local + case 0x0c: // divs global,global + case 0x0d: // divs global,local + case 0x0e: // divs local,global + case 0x0f: // divs local,local + decode_rr(desc); + desc.set_can_cause_exception(); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.src_local) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + { + desc.set_g_used(desc.dst_code); + desc.set_g_used(desc.dst_code + 1); + desc.set_g_modified(desc.dst_code); + desc.set_g_modified(desc.dst_code + 1); + } + desc.set_znv_modified(); + break; + case 0x10: // xm global,global + case 0x11: // xm global,local + case 0x12: // xm local,global + case 0x13: // xm local,local + decode_rrlim(desc); + if (desc.imm != 0U) + desc.set_can_cause_exception(); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.src_local) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + desc.set_g_modified(desc.dst_code); + break; + case 0x14: // mask global,global + case 0x15: // mask global,local + case 0x16: // mask local,global + case 0x17: // mask local,local + decode_rrconst(desc); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.src_local) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + desc.set_g_modified(desc.dst_code); + desc.set_z_modified(); + if (desc.dst_is_pc()) + { + if (!desc.src_is_pc()) + desc.targetpc = BRANCH_TARGET_DYNAMIC; + else + desc.targetpc = (desc.pc + desc.length) & desc.imm; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } + break; + case 0x18: // sum global,global + case 0x19: // sum global,local + case 0x1a: // sum local,global + case 0x1b: // sum local,local + case 0x1c: // sums global,global + case 0x1d: // sums global,local + case 0x1e: // sums local,global + case 0x1f: // sums local,local + decode_rrconst(desc); + if ((op & 0x0400) && !desc.src_is_sr()) + desc.set_can_cause_exception(); // sums + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (desc.src_is_sr()) + desc.set_c_used(); + else if (!desc.src_local) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + desc.set_g_modified(desc.dst_code); + if (op & 0x0400) + desc.set_znv_modified(); // sums + else + desc.set_cznv_modified(); // sum + if (desc.dst_is_pc()) + { + if (!desc.src_is_pc()) + desc.targetpc = BRANCH_TARGET_DYNAMIC; + else + desc.targetpc = ((desc.pc + desc.length) + desc.imm) & ~uint32_t(1); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } + break; + case 0x20: // cmp global,global + case 0x21: // cmp global,local + case 0x22: // cmp local,global + case 0x30: // cmpb global,global + case 0x31: // cmpb global,local + case 0x32: // cmpb local,global + decode_rr(desc); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!(op & 0x1000) && desc.src_is_sr()) + desc.set_c_used(); + else if (!desc.src_local) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + desc.set_g_used(desc.dst_code); + if (op & 0x1000) + desc.set_z_modified(); // cmpb + else + desc.set_cznv_modified(); // cmp + break; + case 0x24: // mov global,global + case 0x25: // mov global,local + case 0x26: // mov local,global + case 0x27: // mov local,local + decode_rr(desc); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.dst_local || !desc.src_local) + { + if (!prev || prev->regout[SR_REGISTER]) + desc.set_check_h(); + desc.regin.set(SR_REGISTER); // only the H bit is used + } + if (!desc.src_local) + { + desc.set_g_used(desc.src_code); + desc.set_g_used(desc.src_code + 16); + } + if (!desc.dst_local) + { + desc.set_can_cause_exception(); + desc.set_g_used(desc.dst_code); + desc.set_g_used(desc.dst_code + 16); + desc.set_g_modified(desc.dst_code); + desc.set_g_modified(desc.dst_code + 16); + if (desc.dst_code == PC_REGISTER) + { + if (!desc.src_is_pc()) + desc.targetpc = BRANCH_TARGET_DYNAMIC; + else + desc.targetpc = desc.pc + desc.length; + desc.set_is_conditional_branch(); // technically it won't branch if H is clear + desc.set_end_sequence(); + } + else if (desc.dst_code == 5) // TPR_REGISTER & 0xf + { + desc.set_end_sequence(); + } + } + desc.set_znv_modified(); + break; + case 0x28: // add global,global + case 0x29: // add global,local + case 0x2a: // add local,global + case 0x2b: // add local,local + case 0x2c: // adds global,global + case 0x2d: // adds global,local + case 0x2e: // adds local,global + case 0x2f: // adds local,local + case 0x48: // sub global,global + case 0x49: // sub global,local + case 0x4a: // sub local,global + case 0x4b: // sub local,local + case 0x4c: // subs global,global + case 0x4d: // subs global,local + case 0x4e: // subs local,global + case 0x4f: // subs local,local + decode_rr(desc); + if (op & 0x0400) + desc.set_can_cause_exception(); // adds, subs + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (desc.src_is_sr()) + desc.set_c_used(); + else if (!desc.src_local) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + { + desc.set_g_used(desc.dst_code); + desc.set_g_modified(desc.dst_code); + if (desc.dst_code == PC_REGISTER) + { + if (!desc.src_is_pc()) + desc.targetpc = BRANCH_TARGET_DYNAMIC; + else if ((op & 0xf800) == 0x2800) + desc.targetpc = (desc.pc + desc.length) << 1; // add, adds + else + desc.targetpc = 0; // sub, subs + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } + } + if (op & 0x0400) + desc.set_znv_modified(); // adds, subs + else + desc.set_cznv_modified(); // add, sub + break; + case 0x34: // andn global,global + case 0x35: // andn global,local + case 0x36: // andn local,global + case 0x37: // andn local,local + case 0x38: // or global,global + case 0x39: // or global,local + case 0x3a: // or local,global + case 0x3b: // or local,local + case 0x3c: // xor global,global + case 0x3d: // xor global,local + case 0x3e: // xor local,global + case 0x3f: // xor local,local + case 0x54: // and global,global + case 0x55: // and global,local + case 0x56: // and local,global + case 0x57: // and local,local + decode_rr(desc); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.src_local) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + { + desc.set_g_used(desc.dst_code); + desc.set_g_modified(desc.dst_code); + if (desc.dst_code == PC_REGISTER) + { + if (!desc.src_is_pc()) + desc.targetpc = BRANCH_TARGET_DYNAMIC; + else if ((op & 0xf400) == 0x3400) + desc.targetpc = 0; // andn, xor + else + desc.targetpc = desc.pc + desc.length; // or, and + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } + } + desc.set_z_modified(); + break; + case 0x40: // subc global,global + case 0x41: // subc global,local + case 0x42: // subc local,global + case 0x43: // subc local,local + case 0x50: // addc global,global + case 0x51: // addc global,local + case 0x52: // addc local,global + case 0x53: // addc local,local + decode_rr(desc); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + desc.set_cz_used(); + if (!desc.src_local && !desc.src_is_sr()) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + { + desc.set_g_used(desc.dst_code); + desc.set_g_modified(desc.dst_code); + if (desc.dst_code == PC_REGISTER) + { + if (!desc.src_is_sr() || ((op & 0xfc00) == 0x4000)) + desc.targetpc = BRANCH_TARGET_DYNAMIC; + else + desc.targetpc = desc.pc + desc.length; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } + } + desc.set_cznv_modified(); + break; + case 0x44: // not global,global + case 0x45: // not global,local + case 0x46: // not local,global + case 0x47: // not local,local + case 0x58: // neg global,global + case 0x59: // neg global,local + case 0x5a: // neg local,global + case 0x5b: // neg local,local + case 0x5c: // negs global,global + case 0x5d: // negs global,local + case 0x5e: // negs local,global + case 0x5f: // negs local,local + decode_rr(desc); + if (((op & 0xfc00) == 0x5c00) && !desc.src_is_sr()) + desc.set_can_cause_exception(); // negs + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (((op & 0xf800) == 0x5800) & desc.src_is_sr()) + desc.set_c_used(); + else if (!desc.src_local) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + { + desc.set_g_modified(desc.dst_code); + if (desc.dst_code == PC_REGISTER) + { + if (!desc.src_is_pc()) + desc.targetpc = BRANCH_TARGET_DYNAMIC; + else if ((op & 0xfc00) == 0x4400) + desc.targetpc = ~(desc.pc + desc.length) & ~uint32_t(1); // not + else + desc.targetpc = uint32_t(-int32_t(desc.pc + desc.length)) & ~uint32_t(1); // neg, negs + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } + } + if (!(op & 0x1000)) + desc.set_z_modified(); // not + else if (!(op & 0x0400)) + desc.set_cznv_modified(); // neg + else + desc.set_znv_modified(); // negs + break; + case 0x60: // cmpi global + case 0x61: // cmpi global + case 0x62: // cmpi local + case 0x63: // cmpi local + case 0x70: // cmpbi global + case 0x71: // cmpbi global + case 0x72: // cmpbi local + case 0x73: // cmpbi local + decode_rimm(desc, op & 0x1000); + if (desc.dst_local) + desc.set_fp_used(); + else + desc.set_g_used(desc.dst_code); + if (op & 0x1000) + desc.set_z_modified(); // cmpbi + else + desc.set_cznv_modified(); // cmpi + break; + case 0x64: // movi global + case 0x65: // movi global + decode_rimm(desc, false); + desc.set_can_cause_exception(); + if (!prev || prev->regout[SR_REGISTER]) + desc.set_check_h(); + desc.set_g_used(desc.dst_code); + desc.set_g_used(desc.dst_code + 16); + desc.regin.set(SR_REGISTER); // only the H bit is used + desc.set_g_modified(desc.dst_code); + desc.set_g_modified(desc.dst_code + 16); + if (desc.dst_code == PC_REGISTER) + { + desc.targetpc = desc.imm & ~uint32_t(1); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } + else if (desc.dst_code == 5) // TPR_REGISTER & 0xf + { + desc.set_end_sequence(); + } + break; + case 0x66: // movi local + case 0x67: // movi local + decode_rimm(desc, false); + desc.set_fp_used(); + desc.set_znv_modified(); + break; + case 0x68: // addi global + case 0x69: // addi global + case 0x6a: // addi local + case 0x6b: // addi local + case 0x6c: // addsi global + case 0x6d: // addsi global + case 0x6e: // addsi local + case 0x6f: // addsi local + decode_rimm(desc, false); + if (op & 0x0400) + desc.set_can_cause_exception(); // addsi + if (desc.dst_local) + desc.set_fp_used(); + if (!(op & 0x010f)) + desc.set_cz_used(); + if (!desc.dst_local) + { + desc.set_g_used(desc.dst_code); + desc.set_g_modified(desc.dst_code); + if (desc.dst_code == PC_REGISTER) + { + desc.targetpc = (desc.pc + desc.length + desc.imm) & ~uint32_t(1); + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } + } + if (op & 0x0400) + desc.set_znv_modified(); // addsi + else + desc.set_cznv_modified(); // addi + break; + case 0x74: // andni global + case 0x75: // andni global + case 0x78: // ori global + case 0x79: // ori global + case 0x7c: // xori global + case 0x7d: // xori global + decode_rimm(desc, !(op & 0x0800)); + desc.set_g_used(desc.dst_code); + desc.set_g_modified(desc.dst_code); + if (desc.dst_code == PC_REGISTER) + { + if (!(op & 0x0800)) + desc.targetpc = (desc.pc + desc.length) & ~desc.imm; // andni + else if (!(op & 0x0400)) + desc.targetpc = ((desc.pc + desc.length) | desc.imm) & ~uint32_t(1); // ori + else + desc.targetpc = ((desc.pc + desc.length) ^ desc.imm) & ~uint32_t(1); // xori + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + } + desc.set_z_modified(); + break; + case 0x76: // andni local + case 0x77: // andni local + case 0x7a: // ori local + case 0x7b: // ori local + case 0x7e: // xori local + case 0x7f: // xori local + decode_rimm(desc, !(op & 0x0800)); + desc.set_fp_used(); + desc.set_z_modified(); + break; + case 0x80: case 0x81: // shrdi + case 0x84: case 0x85: // sardi + case 0x88: case 0x89: // shldi + decode_ln(desc); + desc.set_fp_used(); + if (op & 0x0800) + desc.set_cznv_modified(); // shldi + else + desc.set_czn_modified(); // shrdi, sardi + break; + case 0x82: // shrd + case 0x83: // shr + case 0x86: // sard + case 0x87: // sar + case 0x8a: // shld + case 0x8b: // shl + case 0x8f: // rol + decode_ll(desc); + desc.set_fp_used(); + if (op & 0x0800) + desc.set_cznv_modified(); // shld, shl, rol + else + desc.set_czn_modified(); // shrd, shr, sard, sar + break; + case 0x8c: case 0x8d: // reserved + return false; + case 0x8e: // testlz + decode_ll(desc); + desc.set_fp_used(); + break; + case 0x90: // ldxx.d/a global,global + case 0x91: // ldxx.d/a global,local + case 0x92: // ldxx.d/a local,global + case 0x93: // ldxx.d/a local,local + case 0x94: // ldxx.n/s global,global + case 0x95: // ldxx.n/s global,local + case 0x96: // ldxx.n/s local,global + case 0x97: // ldxx.n/s local,local + decode_rrdis(desc); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.dst_local && !desc.dst_is_sr()) + desc.set_g_used(desc.dst_code); + if ((op & 0x0400) && !desc.dst_local) + desc.set_g_modified(desc.dst_code); + if (!desc.src_local) + { + desc.set_g_modified(desc.src_code); + if ((desc.opptr[1] & 0x3000) == 0x3000) + { + if ((desc.imm & ((op & 0x0400) ? 0x3 : 0x1)) == 0x1) + desc.set_g_modified(desc.src_code + 1); + } + } + desc.set_reads_memory(); + break; + case 0x98: // stxx.d/a global,global + case 0x99: // stxx.d/a global,local + case 0x9a: // stxx.d/a local,global + case 0x9b: // stxx.d/a local,local + case 0x9c: // stxx.n/s global,global + case 0x9d: // stxx.n/s global,local + case 0x9e: // stxx.n/s local,global + case 0x9f: // stxx.n/s local,local + decode_rrdis(desc); + if (((desc.opptr[1] & 0x3000) == 0x0000) || (((desc.opptr[1] & 0x3000) == 0x0000) && (desc.imm & 0x1))) + desc.set_can_cause_exception(); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.dst_local && !desc.dst_is_sr()) + desc.set_g_used(desc.dst_code); + if (!desc.src_local) + { + desc.set_g_used(desc.src_code); + if ((desc.opptr[1] & 0x3000) == 0x3000) + { + if ((desc.imm & ((op & 0x0400) ? 0x3 : 0x1)) == 0x1) + desc.set_g_used(desc.src_code + 1); + } + } + if ((op & 0x0400) && !desc.dst_local) + desc.set_g_modified(desc.dst_code); + desc.set_writes_memory(); + break; + case 0xa0: // shri global + case 0xa1: // shri global + case 0xa2: // shri local + case 0xa3: // shri local + case 0xa4: // sari global + case 0xa5: // sari global + case 0xa6: // sari local + case 0xa7: // sari local + case 0xa8: // shli global + case 0xa9: // shli global + case 0xaa: // shli local + case 0xab: // shli local + decode_rn(desc); + if (desc.dst_local) + desc.set_fp_used(); + if (!desc.dst_local) + { + desc.set_g_used(desc.dst_code); + desc.set_g_modified(desc.dst_code); + } + if (op & 0x0800) + desc.set_cznv_modified(); // shli + else + desc.set_czn_modified(); // shri, sari + break; + case 0xac: case 0xad: case 0xae: case 0xaf: // reserved + return false; + case 0xb0: // mulu global,global + case 0xb1: // mulu global,local + case 0xb2: // mulu local,global + case 0xb3: // mulu local,local + case 0xb4: // muls global,global + case 0xb5: // muls global,local + case 0xb6: // muls local,global + case 0xb7: // muls local,local + case 0xbc: // mul global,global + case 0xbd: // mul global,local + case 0xbe: // mul local,global + case 0xbf: // mul local,local + decode_rr(desc); + if (desc.dst_local || desc.src_local) + desc.set_fp_used(); + if (!desc.src_local) + desc.set_g_used(desc.src_code); + if (!desc.dst_local) + { + desc.set_g_used(desc.dst_code); + desc.set_g_modified(desc.dst_code); + if (!(op & 0x0800)) + desc.set_g_modified(desc.dst_code + 1); // mulu, muls + } + desc.set_cznv_modified(); + break; + case 0xb8: // set global + case 0xb9: // set global + case 0xba: // set local + case 0xbb: // set local + decode_rn(desc); + if (desc.dst_local) + desc.set_fp_used(); + switch (desc.imm) + { + case 4: case 5: case 20: case 21: // le, gt, lem, gtm + desc.set_z_used(); + desc.set_n_used(); + break; + case 6: case 7: case 22: case 23: // lt/n, ge/nn, ltm/nm, gem/nnm + desc.set_n_used(); + break; + case 8: case 9: case 24: case 25: // se, ht, sem, htm + desc.set_cz_used(); + break; + case 10: case 11: case 26: case 27: // st/c, he/nc, stm/cm, hem/ncm + desc.set_c_used(); + break; + case 12: case 13: case 28: case 29: // e/z, ne/nz, em/zm, nem/nzm + desc.set_z_used(); + break; + case 14: case 15: case 30: case 31: // v, nv, vm, nvm + desc.set_v_used(); + break; + } + if (!desc.dst_local) + desc.set_g_modified(desc.dst_code); + break; + case 0xc0: case 0xc1: case 0xc2: case 0xc3: // software + case 0xc4: case 0xc5: case 0xc6: case 0xc7: // software + case 0xc8: case 0xc9: case 0xca: case 0xcb: // software + case 0xcc: case 0xcd: // software + case 0xcf: // do + decode_ll(desc); + desc.set_fp_used(); + desc.set_g_used(PC_REGISTER); + desc.set_g_used(SR_REGISTER); + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + desc.set_can_change_modes(); + break; + case 0xce: // extend + decode_llext(desc); + desc.set_fp_used(); + desc.set_g_used(14); + desc.set_g_used(15); + desc.set_g_modified(14); + desc.set_g_modified(15); + break; + case 0xd0: // ldwr global + case 0xd1: // ldwr local + case 0xd2: // lddr global + case 0xd3: // lddr local + case 0xd4: // ldwp global + case 0xd5: // ldwp local + case 0xd6: // lddp global + case 0xd7: // lddp local + decode_lr(desc); + desc.set_fp_used(); + if (!desc.src_local) + { + desc.set_g_modified(desc.src_code); + if (op & 0x0200) + desc.set_g_modified(desc.src_code + 1); + } + desc.set_reads_memory(); + break; + case 0xd8: // stwr global + case 0xd9: // stwr local + case 0xda: // stdr global + case 0xdb: // stdr local + case 0xdc: // stwp global + case 0xdd: // stwp local + case 0xde: // stdp global + case 0xdf: // stdp local + decode_lr(desc); + desc.set_fp_used(); + if (!desc.src_local) + { + desc.set_g_used(desc.src_code); + if (op & 0x0200) + desc.set_g_used(desc.src_code + 1); + } + desc.set_writes_memory(); + break; + case 0xe0: case 0xe1: case 0xe2: case 0xe3: // dbv, dbnv, dbe, dbne + case 0xe4: case 0xe5: case 0xe6: case 0xe7: // dbc, dbnc, dbse, dbht + case 0xe8: case 0xe9: case 0xea: case 0xeb: // dbn, dbnn, dble, dbgt + case 0xec: // dbr + case 0xf0: case 0xf1: case 0xf2: case 0xf3: // bv, bnv, be, bne + case 0xf4: case 0xf5: case 0xf6: case 0xf7: // bc, bnc, bse, bht + case 0xf8: case 0xf9: case 0xfa: case 0xfb: // bn, bnn, ble, bgt + case 0xfc: // br + decode_pcrel(desc); + switch (op & 0x0f00) + { + case 0x0000: case 0x0100: // bv, bnv + desc.set_v_used(); + break; + case 0x0200: case 0x0300: // be/bz, bne/bnz + desc.set_z_used(); + break; + case 0x0400: case 0x0500: // bst/bc, bhe/bnc + desc.set_c_used(); + break; + case 0x0600: case 0x0700: // bse, bht + desc.set_cz_used(); + break; + case 0x0800: case 0x0900: // blt/bn, bge/bnn + desc.set_n_used(); + break; + case 0x0a00: case 0x0b00: // ble, bgt + desc.set_z_used(); + desc.set_n_used(); + break; + case 0x0c00: // br + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + break; + } + if ((op & 0x0f00) != 0x0c00) + desc.set_is_conditional_branch(); + desc.delayslots = (op & 0x1000) ? 0 : 1; + desc.targetpc = desc.pc + desc.length + desc.imm; + break; + case 0xed: // frame + desc.set_can_cause_exception(); + desc.set_fp_used(); + desc.regin.set(SR_REGISTER); // uses FL + desc.set_g_used(SP_REGISTER); + desc.set_g_used(UB_REGISTER); + desc.set_g_modified(SP_REGISTER); + desc.set_fp_modified(); + desc.set_writes_memory(); + break; + case 0xee: // call global + case 0xef: // call local + decode_lrconst(desc); + if (!desc.src_local && !desc.src_is_sr()) + desc.set_g_used(desc.src_code); + desc.set_g_used(PC_REGISTER); + desc.set_g_used(SR_REGISTER); + if (desc.src_is_pc()) + desc.targetpc = (desc.pc + desc.length + desc.imm) & ~uint32_t(1); + else if (desc.src_is_sr()) + desc.targetpc = desc.imm & ~uint32_t(1); + else + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.set_is_unconditional_branch(); + desc.set_end_sequence(); + break; + case 0xfd: case 0xfe: case 0xff: // trap + switch (bitswap<4>(op, 9, 8, 1, 0)) + { + case 4: case 5: // traple, trapgt + desc.set_z_used(); + desc.set_n_used(); + break; + case 6: case 7: // traplt, trapge + desc.set_n_used(); + break; + case 8: case 9: // trapse, trapht + desc.set_cz_used(); + break; + case 10: case 11: // trapst, traphe + desc.set_c_used(); + break; + case 12: case 13: // trape, trapne + desc.set_z_used(); + break; + case 14: // trapv + desc.set_z_used(); + break; + case 15: // trap + desc.set_will_cause_exception(); + desc.set_end_sequence(); + break; + } + if (bitswap<4>(op, 9, 8, 1, 0) != 15) + desc.set_can_cause_exception(); + break; + } + return true; +} diff --git a/src/devices/cpu/e132xs/e1fe.h b/src/devices/cpu/e132xs/e1fe.h new file mode 100644 index 00000000000..97354a950f2 --- /dev/null +++ b/src/devices/cpu/e132xs/e1fe.h @@ -0,0 +1,215 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + e1fe.h + + Hyperstone E1 instruction decoder + +***************************************************************************/ +#ifndef MAME_CPU_E132XS_E1FE_H +#define MAME_CPU_E132XS_E1FE_H + +#pragma once + +#include "e132xs.h" + +#include "cpu/drcfe.h" + +#include +#include +#include +#include + + +class hyperstone_device::opcode_desc : public opcode_desc_base +{ +public: + uint16_t opptr[3]; + uint8_t dst_code; + uint8_t src_code; + bool dst_local; + bool src_local; + uint32_t imm; + + void set_g_used(unsigned n) + { + regin.set(REG_G0 + n); + if (n == 1) // SR + { + regin.set(REG_C); + regin.set(REG_Z); + regin.set(REG_N); + regin.set(REG_V); + regin.set(REG_FP); + } + } + + void set_c_used() { regin.set(REG_C); } + void set_z_used() { regin.set(REG_Z); } + void set_n_used() { regin.set(REG_N); } + void set_v_used() { regin.set(REG_V); } + void set_fp_used() { regin.set(REG_FP); } + + void set_cz_used() + { + set_c_used(); + set_z_used(); + } + + void set_g_modified(unsigned n) + { + regout.set(REG_G0 + n); + if (n == 1) // SR + { + regout.set(REG_C); + regout.set(REG_Z); + regout.set(REG_N); + regout.set(REG_V); + } + } + + void set_z_modified() + { + regout.set(REG_Z); + } + + void set_znv_modified() + { + regout.set(REG_Z); + regout.set(REG_N); + regout.set(REG_V); + } + + void set_czn_modified() + { + regout.set(REG_C); + regout.set(REG_Z); + regout.set(REG_N); + } + + void set_cznv_modified() + { + regout.set(REG_C); + regout.set(REG_Z); + regout.set(REG_N); + regout.set(REG_V); + } + + void set_fp_modified() + { + regout.set(REG_FP); + } + + bool c_calc_required() const { return regreq[REG_C] || in_delay_slot(); } + bool z_calc_required() const { return regreq[REG_Z] || in_delay_slot(); } + bool n_calc_required() const { return regreq[REG_N] || in_delay_slot(); } + bool v_calc_required() const { return regreq[REG_V] || in_delay_slot(); } + bool condition_calc_required() const { return regreq[REG_C] || regreq[REG_Z] || regreq[REG_N] || regreq[REG_V] || in_delay_slot(); } + + void set_check_h() { m_extra_flags.set(CHECK_H); } + void set_can_change_modes() { m_extra_flags.set(CAN_CHANGE_MODES); } + void set_reads_memory() { m_extra_flags.set(READS_MEMORY); } + void set_writes_memory() { m_extra_flags.set(WRITES_MEMORY); } + + bool check_h() const { return m_extra_flags[CHECK_H]; } + bool can_change_modes() const { return m_extra_flags[CAN_CHANGE_MODES]; } + bool reads_memory() const { return m_extra_flags[READS_MEMORY]; } + bool writes_memory() const { return m_extra_flags[WRITES_MEMORY]; } + + bool dst_is_src() const { return (dst_local == src_local) && (dst_code == src_code); } + bool dst_is_pc() const { return !dst_local && (dst_code == 0); } + bool dst_is_sr() const { return !dst_local && (dst_code == 1); } + bool src_is_pc() const { return !src_local && (src_code == 0); } + bool src_is_sr() const { return !src_local && (src_code == 1); } + + // epc - compute the exception PC + uint32_t epc() const + { + return in_delay_slot() ? branch->pc : pc; + } + + void reset(offs_t curpc, bool in_delay_slot) + { + static_assert(REG_COUNT <= 40); + + opcode_desc_base::reset(curpc, in_delay_slot); + + std::fill(std::begin(opptr), std::end(opptr), 0); + dst_code = ~uint8_t(0); + src_code = ~uint8_t(0); + dst_local = false; + src_local = false; + imm = 0x80000000; + m_extra_flags.reset(); + } + + void log_flags(std::ostream &stream) const; + void log_registers_used(std::ostream &stream) const; + void log_registers_modified(std::ostream &stream) const; + +protected: + enum + { + REG_G0 = 0, + REG_PC = REG_G0, + REG_SR = REG_G0 + 1, + + REG_C = REG_G0 + 32, + REG_Z, + REG_N, + REG_V, + REG_FP, + + REG_COUNT + }; + + enum + { + CHECK_H = 0, + CAN_CHANGE_MODES, + READS_MEMORY, + WRITES_MEMORY, + + EXTRA_FLAG_COUNT + }; + + static void log_register_list(std::ostream &stream, const regmask ®list, const regmask *regnostarlist); + + std::bitset m_extra_flags; +}; + + +class hyperstone_device::frontend : public drc_frontend_base +{ +public: + frontend(hyperstone_device &cpu, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + ~frontend(); + + opcode_desc const *describe_code(offs_t startpc); + +private: + bool describe(opcode_desc &desc, opcode_desc const *prev); + + void read_op(opcode_desc &desc); + void read_imm1(opcode_desc &desc); + void read_imm2(opcode_desc &desc); + void decode_const(opcode_desc &desc); + + void decode_ll(opcode_desc &desc); + void decode_llext(opcode_desc &desc); + void decode_lr(opcode_desc &desc); + void decode_rr(opcode_desc &desc); + void decode_ln(opcode_desc &desc); + void decode_rn(opcode_desc &desc); + void decode_pcrel(opcode_desc &desc); + void decode_lrconst(opcode_desc &desc); + void decode_rrconst(opcode_desc &desc); + void decode_rrdis(opcode_desc &desc); + void decode_rimm(opcode_desc &desc, bool cmpbi_andni); + void decode_rrlim(opcode_desc &desc); + + hyperstone_device &m_cpu; +}; + +#endif // MAME_CPU_E132XS_E1FE_H diff --git a/src/devices/cpu/powerpc/ppc.h b/src/devices/cpu/powerpc/ppc.h index d00bcac10a1..86292a1dba5 100644 --- a/src/devices/cpu/powerpc/ppc.h +++ b/src/devices/cpu/powerpc/ppc.h @@ -16,12 +16,10 @@ #include "ppc_dasm.h" #include "cpu/drcuml.h" -#include "cpu/drcumlsh.h" #include "divtlb.h" #include -#include /*************************************************************************** @@ -700,8 +698,6 @@ protected: bool generate_instruction_3b(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc); bool generate_instruction_3f(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc); void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op); - const char *log_desc_flags_to_string(const opcode_desc &desc); - void log_register_list(const char *string, const std::bitset<128> ®list, const std::bitset<128> *regnostarlist); void log_opcode_desc(const opcode_desc *desclist, int indent); private: diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp index 1ced08d9dc5..ee0c9b664bc 100644 --- a/src/devices/cpu/powerpc/ppcdrc.cpp +++ b/src/devices/cpu/powerpc/ppcdrc.cpp @@ -23,6 +23,10 @@ #include "cpu/drcuml.h" #include "cpu/drcumlsh.h" +#include "util/vecstream.h" + +#include + /*************************************************************************** @@ -1764,9 +1768,9 @@ void ppc_device::generate_compute_flags(drcuml_block &block, const opcode_desc * /* modify inputs based on required flags */ if (!DISABLE_FLAG_OPTIMIZATIONS) { - if (!frontend::REGFLAG_XER_CA(desc->regreq)) + if (!desc->xer_ca_required()) xermask &= ~XER_CA; - if (!frontend::REGFLAG_CR(desc->regreq, 0)) + if (!desc->cr_required(0)) updatecr = 0; } const uint32_t xerflags = ((xermask & XER_OV) ? uml::FLAG_V : 0) | ((xermask & XER_CA) ? uml::FLAG_C : 0); @@ -2969,7 +2973,7 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co UML_CMP(block, I2, 0x00000020); // cmp rb,0x20 UML_JMPc(block, COND_S, compiler->labelnum); // bs 1: - if (DISABLE_FLAG_OPTIMIZATIONS || frontend::REGFLAG_XER_CA(desc->regreq)) + if (DISABLE_FLAG_OPTIMIZATIONS || desc->xer_ca_required()) { // for shift amt > 32, carry flag is the sign bit of Rs and the sign bit fills all bit positions UML_TEST(block, R32(G_RS(op)), 0x80000000); @@ -2980,7 +2984,7 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co UML_JMP(block, compiler->labelnum+1); // bra 2: UML_LABEL(block, compiler->labelnum++); // 1: - if (DISABLE_FLAG_OPTIMIZATIONS || frontend::REGFLAG_XER_CA(desc->regreq)) + if (DISABLE_FLAG_OPTIMIZATIONS || desc->xer_ca_required()) { UML_SHL(block, I1, 0xffffffff, I2); // shl i1,0xffffffff,i2 UML_XOR(block, I1, I1, ~0); // xor i1,i1,~0 @@ -3001,7 +3005,7 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co return true; case 0x338: /* SRAWIx */ - if (DISABLE_FLAG_OPTIMIZATIONS || frontend::REGFLAG_XER_CA(desc->regreq)) + if (DISABLE_FLAG_OPTIMIZATIONS || desc->xer_ca_required()) { UML_AND(block, I0, R32(G_RS(op)), ~(0xffffffff << (G_SH(op) & 31)));// and i0,rs,~(0xffffffff << (sh & 31)) UML_SAR(block, I1, R32(G_RS(op)), 31); // sar i1,rs,31 @@ -3916,172 +3920,6 @@ void ppc_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32 } -/*------------------------------------------------- - log_desc_flags_to_string - generate a string - representing the instruction description - flags --------------------------------------------------*/ - -const char *ppc_device::log_desc_flags_to_string(const opcode_desc &desc) -{ - static char tempbuf[30]; - char *dest = tempbuf; - - /* branches */ - if (desc.is_unconditional_branch()) - *dest++ = 'U'; - else if (desc.is_conditional_branch()) - *dest++ = 'C'; - else - *dest++ = '.'; - - /* intrablock branches */ - *dest++ = desc.intrablock_branch() ? 'i' : '.'; - - /* branch targets */ - *dest++ = desc.is_branch_target() ? 'B' : '.'; - - /* delay slots */ - *dest++ = desc.in_delay_slot() ? 'D' : '.'; - - /* exceptions */ - if (desc.will_cause_exception()) - *dest++ = 'E'; - else if (desc.can_cause_exception()) - *dest++ = 'e'; - else - *dest++ = '.'; - - /* read/write */ - if (desc.reads_memory()) - *dest++ = 'R'; - else if (desc.writes_memory()) - *dest++ = 'W'; - else - *dest++ = '.'; - - /* TLB validation */ - *dest++ = desc.validate_tlb() ? 'V' : '.'; - - /* redispatch */ - *dest++ = desc.redispatch() ? 'R' : '.'; - return tempbuf; -} - - -/*------------------------------------------------- - log_register_list - log a list of GPR registers --------------------------------------------------*/ - -void ppc_device::log_register_list(const char *string, const std::bitset<128> ®list, const std::bitset<128> *regnostarlist) -{ - static const char *const crtext[4] = { "lt", "gt", "eq", "so" }; - int count = 0; - int regnum; - int crnum; - - /* skip if nothing */ - if (reglist.none()) - return; - - m_drcuml->log_printf("[%s:", string); - - for (regnum = 0; regnum < 32; regnum++) - { - if (frontend::REGFLAG_R(reglist, regnum)) - { - m_drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist && !frontend::REGFLAG_R(*regnostarlist, regnum)) - m_drcuml->log_printf("*"); - } - } - - for (regnum = 0; regnum < 32; regnum++) - { - if (frontend::REGFLAG_FR(reglist, regnum)) - { - m_drcuml->log_printf("%sfr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist && !frontend::REGFLAG_FR(*regnostarlist, regnum)) - m_drcuml->log_printf("*"); - } - } - - for (regnum = 0; regnum < 8; regnum++) - { - if (frontend::REGFLAG_CR(reglist, regnum)) - { - if ((frontend::REGFLAG_CR(reglist, regnum) == 0x0f) && (!regnostarlist || (frontend::REGFLAG_CR(*regnostarlist, regnum) == 0x0f))) - { - m_drcuml->log_printf("%scr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist && !frontend::REGFLAG_CR(*regnostarlist, regnum)) - m_drcuml->log_printf("*"); - } - else - { - for (crnum = 0; crnum < 4; crnum++) - { - if (frontend::REGFLAG_CR_BIT(reglist, regnum * 4 + crnum)) - { - m_drcuml->log_printf("%scr%d[%s]", (count++ == 0) ? "" : ",", regnum, crtext[crnum]); - if (regnostarlist && !frontend::REGFLAG_CR_BIT(*regnostarlist, regnum * 4 + crnum)) - m_drcuml->log_printf("*"); - } - } - } - } - } - - if (frontend::REGFLAG_XER_CA(reglist)) - { - m_drcuml->log_printf("%sxer_ca", (count++ == 0) ? "" : ","); - if (regnostarlist && !frontend::REGFLAG_XER_CA(*regnostarlist)) - m_drcuml->log_printf("*"); - } - if (frontend::REGFLAG_XER_OV(reglist)) - { - m_drcuml->log_printf("%sxer_ov", (count++ == 0) ? "" : ","); - if (regnostarlist && !frontend::REGFLAG_XER_OV(*regnostarlist)) - m_drcuml->log_printf("*"); - } - if (frontend::REGFLAG_XER_SO(reglist)) - { - m_drcuml->log_printf("%sxer_so", (count++ == 0) ? "" : ","); - if (regnostarlist && !frontend::REGFLAG_XER_SO(*regnostarlist)) - m_drcuml->log_printf("*"); - } - if (frontend::REGFLAG_XER_COUNT(reglist)) - { - m_drcuml->log_printf("%sxer_count", (count++ == 0) ? "" : ","); - if (regnostarlist && !frontend::REGFLAG_XER_COUNT(*regnostarlist)) - m_drcuml->log_printf("*"); - } - if (frontend::REGFLAG_CTR(reglist)) - { - m_drcuml->log_printf("%sctr", (count++ == 0) ? "" : ","); - if (regnostarlist && !frontend::REGFLAG_CTR(*regnostarlist)) - m_drcuml->log_printf("*"); - } - if (frontend::REGFLAG_LR(reglist)) - { - m_drcuml->log_printf("%slr", (count++ == 0) ? "" : ","); - if (regnostarlist && !frontend::REGFLAG_LR(*regnostarlist)) - m_drcuml->log_printf("*"); - } - - for (regnum = 0; regnum < 8; regnum++) - { - if (frontend::REGFLAG_FPSCR(reglist, regnum)) - { - m_drcuml->log_printf("%sfpscr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist && !frontend::REGFLAG_FPSCR(*regnostarlist, regnum)) - m_drcuml->log_printf("*"); - } - } - - m_drcuml->log_printf("] "); -} - - /*------------------------------------------------- log_opcode_desc - log a list of descriptions -------------------------------------------------*/ @@ -4089,41 +3927,50 @@ void ppc_device::log_register_list(const char *string, const std::bitset<128> &r void ppc_device::log_opcode_desc(const opcode_desc *desclist, int indent) { util::ovectorstream buffer; + buffer.imbue(std::locale::classic()); - /* open the file, creating it if necessary */ + // assume no indent is the start of a sequence and needs a heading if (indent == 0) m_drcuml->log_printf("\nDescriptor list @ %08X\n", desclist->pc); - /* output each descriptor */ + // output each description for ( ; desclist != nullptr; desclist = desclist->next()) { buffer.clear(); buffer.seekp(0); + desclist->log_flags(buffer); + buffer.put('\0'); + m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: ", desclist->pc, desclist->physpc, desclist->targetpc, &buffer.vec()[0]); - /* disassemble the current instruction and output it to the log */ - if (m_drcuml->logging() || m_drcuml->logging_native()) - { - if (desclist->virtual_noop()) - buffer << ""; - else - m_dasm.dasm_one(buffer, desclist->pc, desclist->opptr); - } + // disassemble the current instruction and output it to the log + buffer.clear(); + buffer.seekp(0); + if (desclist->virtual_noop()) + buffer << ""; else - buffer << "???"; - + m_dasm.dasm_one(buffer, desclist->pc, desclist->opptr); buffer.put('\0'); - m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(*desclist), &buffer.vec()[0]); + m_drcuml->log_printf("%-30s", &buffer.vec()[0]); - /* output register states */ - log_register_list("use", desclist->regin, nullptr); - log_register_list("mod", desclist->regout, &desclist->regreq); - m_drcuml->log_printf("\n"); + // output register dependencies + buffer.clear(); + buffer.seekp(0); + if (!desclist->regin.none()) + { + desclist->log_registers_used(buffer); + if (!desclist->regout.none()) + buffer << ' '; + } + if (!desclist->regout.none()) + desclist->log_registers_modified(buffer); + buffer.put('\0'); + m_drcuml->log_printf("%s\n", &buffer.vec()[0]); - /* if we have a delay slot, output it recursively */ + // if we have a delay slot, output it recursively if (desclist->delay.first() != nullptr) log_opcode_desc(desclist->delay.first(), indent + 1); - /* at the end of a sequence add a dividing line */ + // at the end of a sequence add a dividing line if (desclist->end_sequence()) m_drcuml->log_printf("-----\n"); } diff --git a/src/devices/cpu/powerpc/ppcfe.cpp b/src/devices/cpu/powerpc/ppcfe.cpp index 6b8be8061fe..e970e6706f8 100644 --- a/src/devices/cpu/powerpc/ppcfe.cpp +++ b/src/devices/cpu/powerpc/ppcfe.cpp @@ -16,38 +16,166 @@ #include "cpu/drcfe.ipp" -//************************************************************************** -// MACROS -//************************************************************************** -#define GPR_USED(desc, x) do { (desc).regin.set(REG_BIT_R0 + x); } while (0) -#define GPR_USED_OR_ZERO(desc, x) do { if (x) GPR_USED((desc), x); } while (0) -#define GPR_MODIFIED(desc, x) do { (desc).regout.set(REG_BIT_R0 + x); } while (0) +/*------------------------------------------------- + log_flags - write a string representing the + instruction description flags to a stream +-------------------------------------------------*/ + +void ppc_device::opcode_desc::log_flags(std::ostream &stream) const +{ + // branches + if (is_unconditional_branch()) + stream << 'U'; + else if (is_conditional_branch()) + stream << 'C'; + else + stream << '.'; + + // intrablock branches + stream << (intrablock_branch() ? 'i' : '.'); + + // branch targets + stream << (is_branch_target() ? 'B' : '.'); + + // delay slots + stream << (in_delay_slot() ? 'D' : '.'); + + // exceptions + if (will_cause_exception()) + stream << 'E'; + else if (can_cause_exception()) + stream << 'e'; + else + stream << '.'; + + // read/write + if (reads_memory()) + stream << 'R'; + else if (writes_memory()) + stream << 'W'; + else + stream << '.'; -#define FPR_USED(desc, x) do { (desc).regin.set(REG_BIT_FR0 + x); } while (0) -#define FPR_MODIFIED(desc, x) do { (desc).regout.set(REG_BIT_FR0 + x); } while (0) + // TLB validation + stream << (validate_tlb() ? 'V' : '.'); -#define CR_USED(desc, x) do { CR_BIT_USED((desc), (x * 4) + 0); CR_BIT_USED((desc), (x * 4) + 1); CR_BIT_USED((desc), (x * 4) + 2); CR_BIT_USED((desc), (x * 4) + 3); } while (0) -#define CR_BIT_USED(desc, x) do { (desc).regin.set(64 + 31 - x); } while (0) -#define CR_MODIFIED(desc, x) do { CR_BIT_MODIFIED((desc), (x * 4) + 0); CR_BIT_MODIFIED((desc), (x * 4) + 1); CR_BIT_MODIFIED((desc), (x * 4) + 2); CR_BIT_MODIFIED((desc), (x * 4) + 3); } while (0) -#define CR_BIT_MODIFIED(desc, x) do { (desc).regout.set(64 + 31 - x); } while (0) + // redispatch + stream << (redispatch() ? 'R' : '.'); +} -#define XER_CA_USED(desc) do { (desc).regin.set(REG_BIT_XER_CA); } while (0) -#define XER_OV_USED(desc) do { (desc).regin.set(REG_BIT_XER_OV); } while (0) -#define XER_SO_USED(desc) do { (desc).regin.set(REG_BIT_XER_SO); } while (0) -#define XER_COUNT_USED(desc) do { (desc).regin.set(REG_BIT_XER_COUNT); } while (0) -#define XER_CA_MODIFIED(desc) do { (desc).regout.set(REG_BIT_XER_CA); } while (0) -#define XER_OV_MODIFIED(desc) do { (desc).regout.set(REG_BIT_XER_OV); } while (0) -#define XER_SO_MODIFIED(desc) do { (desc).regout.set(REG_BIT_XER_SO); } while (0) -#define XER_COUNT_MODIFIED(desc) do { (desc).regout.set(REG_BIT_XER_COUNT); } while (0) -#define CTR_USED(desc) do { (desc).regin.set(REG_BIT_CTR); } while (0) -#define CTR_MODIFIED(desc) do { (desc).regout.set(REG_BIT_CTR); } while (0) -#define LR_USED(desc) do { (desc).regin.set(REG_BIT_LR); } while (0) -#define LR_MODIFIED(desc) do { (desc).regout.set(REG_BIT_LR); } while (0) +/*------------------------------------------------- + log_register_list - log a list of registers +-------------------------------------------------*/ + +void ppc_device::opcode_desc::log_registers_used(std::ostream &stream) const +{ + stream << "[use:"; + log_register_list(stream, regin, nullptr); + stream << ']'; +} -#define FPSCR_USED(desc, x) do { (desc).regin.set(REG_BIT_FPSCR0 + x); } while (0) -#define FPSCR_MODIFIED(desc, x) do { (desc).regout.set(REG_BIT_FPSCR0 + x); } while (0) +void ppc_device::opcode_desc::log_registers_modified(std::ostream &stream) const +{ + stream << "[mod:"; + log_register_list(stream, regout, ®req); + stream << ']'; +} + +void ppc_device::opcode_desc::log_register_list(std::ostream &stream, const regmask ®list, const regmask *regnostarlist) +{ + static const char *const crtext[4] = { "lt", "gt", "eq", "so" }; + int count = 0; + + for (int regnum = 0; regnum < 32; regnum++) + { + if (reglist[REG_BIT_R0 + regnum]) + { + if (count++) + stream << ','; + stream << 'r' << regnum; + if (regnostarlist && !(*regnostarlist)[REG_BIT_R0 + regnum]) + stream << '*'; + } + } + + for (int regnum = 0; regnum < 32; regnum++) + { + if (reglist[REG_BIT_FR0 + regnum]) + { + if (count++) + stream << ','; + stream << "fr" << regnum; + if (regnostarlist && !(*regnostarlist)[REG_BIT_FR0 + regnum]) + stream << '*'; + } + } + + for (int regnum = 0; regnum < 8; regnum++) + { + if (!reg_cr(reglist, regnum)) + continue; + + if (count++) + stream << ','; + stream << "cr" << regnum; + if ((reg_cr(reglist, regnum) == 0x0f) && (!regnostarlist || (reg_cr(*regnostarlist, regnum) == 0x0f) || !reg_cr(*regnostarlist, regnum))) + { + if (regnostarlist && !reg_cr(*regnostarlist, regnum)) + stream << '*'; + } + else + { + int crcount = 0; + stream << '['; + for (int crnum = 0; crnum < 4; crnum++) + { + if (reg_cr_bit(reglist, (regnum * 4) + crnum)) + { + if (crcount++) + stream << ','; + stream << crtext[crnum]; + if (regnostarlist && !reg_cr_bit(*regnostarlist, (regnum * 4) + crnum)) + stream << '*'; + } + } + stream << ']'; + } + } + + const auto log_bit = + [&stream, &count, ®list, ®nostarlist] (size_t bit, const char *name) + { + if (reglist[bit]) + { + if (count++) + stream << ','; + stream << name; + if (regnostarlist && !(*regnostarlist)[bit]) + stream << '*'; + } + }; + + log_bit(REG_BIT_XER_CA, "xer_ca"); + log_bit(REG_BIT_XER_OV, "xer_ov"); + log_bit(REG_BIT_XER_SO, "xer_so"); + log_bit(REG_BIT_XER_COUNT, "xer_count"); + log_bit(REG_BIT_CTR, "ctr"); + log_bit(REG_BIT_LR, "lr"); + + for (int regnum = 0; regnum < 8; regnum++) + { + if (reglist[REG_BIT_FPSCR0 + regnum]) + { + if (count++) + stream << ','; + stream << "fpscr" << regnum; + if (regnostarlist && !(*regnostarlist)[REG_BIT_FPSCR0 + regnum]) + stream << '*'; + } + } +} @@ -117,15 +245,15 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; case 0x03: // TWI - GPR_USED(desc, G_RA(op)); + desc.set_gpr_used(G_RA(op)); desc.set_can_cause_exception(); if (is_603_class()) desc.cycles = 2; // 603 return true; case 0x07: // MULLI - GPR_USED(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_modified(G_RD(op)); if (is_403_class()) desc.cycles = 4; // 4XX else if (is_601_class()) @@ -142,53 +270,53 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; } - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_modified(G_RD(op)); return true; case 0x0e: // ADDI case 0x0f: // ADDIS - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_modified(G_RD(op)); return true; case 0x0a: // CMPLI case 0x0b: // CMPI - GPR_USED(desc, G_RA(op)); - XER_SO_USED(desc); - CR_MODIFIED(desc, G_CRFD(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_xer_so_used(); + desc.set_cr_modified(G_CRFD(op)); return true; case 0x08: // SUBFIC case 0x0c: // ADDIC - GPR_USED(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_CA_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ca_modified(); return true; case 0x0d: // ADDIC. - GPR_USED(desc, G_RA(op)); - XER_SO_USED(desc); - GPR_MODIFIED(desc, G_RT(op)); - XER_CA_MODIFIED(desc); - CR_MODIFIED(desc, 0); + desc.set_gpr_used(G_RA(op)); + desc.set_xer_so_used(); + desc.set_gpr_modified(G_RT(op)); + desc.set_xer_ca_modified(); + desc.set_cr_modified(0); return true; case 0x10: // BCx if (!(G_BO(op) & 0x10)) { - CR_BIT_USED(desc, G_BI(op)); + desc.set_cr_bit_used(G_BI(op)); // branch folding - if (prev == nullptr || REGFLAG_CR(prev->regout) == 0) + if (!prev || (prev->cr_modified() == 0)) desc.cycles = 0; } if (!(G_BO(op) & 0x04)) { - CTR_USED(desc); - CTR_MODIFIED(desc); + desc.set_ctr_used(); + desc.set_ctr_modified(); } if (op & M_LK) - LR_MODIFIED(desc); + desc.set_lr_modified(); if ((G_BO(op) & 0x14) == 0x14) { desc.set_is_unconditional_branch(); @@ -218,7 +346,7 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x12: // Bx if (op & M_LK) - LR_MODIFIED(desc); + desc.set_lr_modified(); desc.set_is_unconditional_branch(); desc.set_end_sequence(); desc.targetpc = ((int32_t)(G_LI(op) << 8) >> 6) + ((op & M_AA) ? 0 : desc.pc); @@ -231,34 +359,34 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) return describe_13(op, desc, prev); case 0x14: // RLWIMIx - GPR_USED(desc, G_RS(op)); - GPR_USED(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_modified(G_RA(op)); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; case 0x15: // RLWINMx - GPR_USED(desc, G_RS(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_modified(G_RA(op)); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; case 0x17: // RLWNMx - GPR_USED(desc, G_RS(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RA(op)); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; @@ -266,16 +394,16 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x19: // ORIS case 0x1a: // XORI case 0x1b: // XORIS - GPR_USED(desc, G_RS(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_modified(G_RA(op)); return true; case 0x1c: // ANDI. case 0x1d: // ANDIS. - GPR_USED(desc, G_RS(op)); - XER_SO_USED(desc); - GPR_MODIFIED(desc, G_RA(op)); - CR_MODIFIED(desc, 0); + desc.set_gpr_used(G_RS(op)); + desc.set_xer_so_used(); + desc.set_gpr_modified(G_RA(op)); + desc.set_cr_modified(0); return true; case 0x1f: // 0x1f group @@ -285,8 +413,8 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x22: // LBZ case 0x28: // LHZ case 0x2a: // LHA - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_modified(G_RD(op)); desc.set_reads_memory(); return true; @@ -296,17 +424,17 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x2b: // LHAU if (G_RA(op) == 0 || G_RA(op) == G_RD(op)) return false; - GPR_USED(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RD(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_gpr_modified(G_RA(op)); desc.set_reads_memory(); return true; case 0x24: // STW case 0x26: // STB case 0x2c: // STH - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RS(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RS(op)); desc.set_writes_memory(); return true; @@ -315,28 +443,28 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x2d: // STHU if (G_RA(op) == 0) return false; - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RS(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_modified(G_RA(op)); desc.set_writes_memory(); return true; case 0x2e: // LMW - GPR_USED_OR_ZERO(desc, G_RA(op)); + desc.set_gpr_used_or_zero(G_RA(op)); for (regnum = G_RD(op); regnum < 32; regnum++) { if (regnum != G_RA(op) || ((m_ppc.m_cap & PPCCAP_4XX) && regnum == 31)) - GPR_MODIFIED(desc, regnum); + desc.set_gpr_modified(regnum); } desc.set_reads_memory(); desc.cycles = 32 - G_RD(op); return true; case 0x2f: // STMW - GPR_USED_OR_ZERO(desc, G_RA(op)); + desc.set_gpr_used_or_zero(G_RA(op)); for (regnum = G_RS(op); regnum < 32; regnum++) - GPR_USED(desc, regnum); + desc.set_gpr_used(regnum); desc.set_writes_memory(); desc.cycles = 32 - G_RS(op); return true; @@ -345,8 +473,8 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x32: // LFD if (!(m_ppc.m_cap & PPCCAP_FPU)) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_fpr_modified(G_RD(op)); desc.set_reads_memory(); return true; @@ -356,9 +484,9 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; if (G_RA(op) == 0) return false; - GPR_USED(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RA(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_modified(G_RA(op)); + desc.set_fpr_modified(G_RD(op)); desc.set_reads_memory(); return true; @@ -366,8 +494,8 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) case 0x36: // STFD if (!(m_ppc.m_cap & PPCCAP_FPU)) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - FPR_USED(desc, G_RS(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_fpr_used(G_RS(op)); desc.set_writes_memory(); return true; @@ -377,9 +505,9 @@ bool ppc_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) return false; if (G_RA(op) == 0) return false; - GPR_USED(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RA(op)); - FPR_USED(desc, G_RS(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_modified(G_RA(op)); + desc.set_fpr_used(G_RS(op)); desc.set_writes_memory(); return true; @@ -407,24 +535,24 @@ bool ppc_device::frontend::describe_13(uint32_t op, opcode_desc &desc, const opc switch (opswitch) { case 0x000: // MTCRF - CR_USED(desc, G_CRFS(op)); - CR_MODIFIED(desc, G_CRFD(op)); + desc.set_cr_used(G_CRFS(op)); + desc.set_cr_modified(G_CRFD(op)); // CR logical folding - if (prev == nullptr || REGFLAG_CR(prev->regout) == 0) + if (!prev || (prev->cr_modified() == 0)) desc.cycles = 0; return true; case 0x010: // BCLRx - LR_USED(desc); + desc.set_lr_used(); if (!(G_BO(op) & 0x10)) - CR_BIT_USED(desc, G_BI(op)); + desc.set_cr_bit_used(G_BI(op)); if (!(G_BO(op) & 0x04)) { - CTR_USED(desc); - CTR_MODIFIED(desc); + desc.set_ctr_used(); + desc.set_ctr_modified(); } if (op & M_LK) - LR_MODIFIED(desc); + desc.set_lr_modified(); if ((G_BO(op) & 0x14) == 0x14) { desc.set_is_unconditional_branch(); @@ -445,11 +573,11 @@ bool ppc_device::frontend::describe_13(uint32_t op, opcode_desc &desc, const opc case 0x121: // CREQV case 0x1a1: // CRORC case 0x1c1: // CROR - CR_BIT_USED(desc, G_CRBA(op)); - CR_BIT_USED(desc, G_CRBB(op)); - CR_BIT_MODIFIED(desc, G_CRBD(op)); + desc.set_cr_bit_used(G_CRBA(op)); + desc.set_cr_bit_used(G_CRBB(op)); + desc.set_cr_bit_modified(G_CRBD(op)); // CR logical folding - if (prev == nullptr || REGFLAG_CR(prev->regout) == 0) + if (!prev || (prev->cr_modified() == 0)) desc.cycles = 0; return true; @@ -489,13 +617,13 @@ bool ppc_device::frontend::describe_13(uint32_t op, opcode_desc &desc, const opc return true; case 0x210: // BCCTRx - CTR_USED(desc); + desc.set_ctr_used(); if (!(G_BO(op) & 0x10)) - CR_BIT_USED(desc, G_BI(op)); + desc.set_cr_bit_used(G_BI(op)); if (!(G_BO(op) & 0x04)) return false; if (op & M_LK) - LR_MODIFIED(desc); + desc.set_lr_modified(); if ((G_BO(op) & 0x14) == 0x14) { desc.set_is_unconditional_branch(); @@ -556,15 +684,15 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x000: // CMP case 0x020: // CMPL - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - XER_SO_USED(desc); - CR_MODIFIED(desc, G_CRFD(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_xer_so_used(); + desc.set_cr_modified(G_CRFD(op)); return true; case 0x004: // TW - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); desc.set_can_cause_exception(); if (is_603_class()) desc.cycles = 2; // 603 @@ -572,28 +700,28 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x008: // SUBFCx case 0x00a: // ADDCx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_CA_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ca_modified(); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; case 0x088: // SUBFEx case 0x08a: // ADDEx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - XER_CA_USED(desc); - GPR_MODIFIED(desc, G_RD(op)); - XER_CA_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_xer_ca_used(); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ca_modified(); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; @@ -601,27 +729,27 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x0ca: // ADDZEx case 0x0e8: // SUBFMEx case 0x0ea: // ADDMEx - GPR_USED(desc, G_RA(op)); - XER_CA_USED(desc); - GPR_MODIFIED(desc, G_RD(op)); - XER_CA_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_xer_ca_used(); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ca_modified(); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; case 0x00b: // MULHWUx case 0x04b: // MULHWx case 0x0eb: // MULLWx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } if (is_403_class()) desc.cycles = 4; // 4XX @@ -635,13 +763,13 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x1cb: // DIVWUx case 0x1eb: // DIVWx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } if (is_403_class()) desc.cycles = 33; // 4XX @@ -655,63 +783,63 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x028: // SUBFx case 0x10a: // ADDx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; case 0x208: // SUBFCOx case 0x20a: // ADDCOx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); - XER_CA_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); + desc.set_xer_ca_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; case 0x288: // SUBFEOx case 0x28a: // ADDEOx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - XER_CA_USED(desc); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); - XER_CA_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_xer_ca_used(); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); + desc.set_xer_ca_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; case 0x2c8: // SUBFZEOx case 0x2ca: // ADDZEOx case 0x2e8: // SUBFMEOx case 0x2ea: // ADDMEOx - GPR_USED(desc, G_RA(op)); - XER_CA_USED(desc); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); - XER_CA_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_xer_ca_used(); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); + desc.set_xer_ca_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; case 0x2eb: // MULLWOx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); if (is_403_class()) desc.cycles = 4; // 4XX else if (is_601_class()) @@ -724,13 +852,13 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x3cb: // DIVWUOx case 0x3eb: // DIVWOx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); if (is_403_class()) desc.cycles = 33; // 4XX else if (is_601_class()) @@ -743,25 +871,25 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x228: // SUBFOx case 0x30a: // ADDOx - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; case 0x013: // MFCR - CR_USED(desc, 0); - CR_USED(desc, 1); - CR_USED(desc, 2); - CR_USED(desc, 3); - CR_USED(desc, 4); - CR_USED(desc, 5); - CR_USED(desc, 6); - CR_USED(desc, 7); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_cr_used(0); + desc.set_cr_used(1); + desc.set_cr_used(2); + desc.set_cr_used(3); + desc.set_cr_used(4); + desc.set_cr_used(5); + desc.set_cr_used(6); + desc.set_cr_used(7); + desc.set_gpr_modified(G_RD(op)); return true; case 0x136: // ECIWX @@ -775,9 +903,9 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x157: // LHAX case 0x216: // LWBRX case 0x316: // LHBRX - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); desc.set_reads_memory(); return true; @@ -790,38 +918,38 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x19c: // ORCx case 0x1bc: // ORx case 0x1dc: // NANDx - GPR_USED(desc, G_RS(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RA(op)); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; case 0x218: // SRWx case 0x318: // SRAWx - GPR_USED(desc, G_RS(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RA(op)); - XER_CA_MODIFIED(desc); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RA(op)); + desc.set_xer_ca_modified(); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; case 0x01a: // CNTLZWx case 0x39a: // EXTSHx case 0x3ba: // EXTSBx - GPR_USED(desc, G_RS(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_modified(G_RA(op)); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; @@ -833,15 +961,15 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x3d6: // ICBI if (!(m_ppc.m_cap & (PPCCAP_VEA | PPCCAP_4XX))) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); return true; case 0x1d6: // DCBI if (!(m_ppc.m_cap & (PPCCAP_OEA | PPCCAP_4XX))) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); desc.set_can_cause_exception(); desc.set_privileged(); return true; @@ -852,26 +980,26 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x177: // LHAUX if (G_RA(op) == 0 || G_RA(op) == G_RD(op)) return false; - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_gpr_modified(G_RA(op)); desc.set_reads_memory(); return true; case 0x153: // MFSPR - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_modified(G_RD(op)); spr = compute_spr(G_SPR(op)); if (spr == SPR_LR) - LR_USED(desc); + desc.set_lr_used(); if (spr == SPR_CTR) - CTR_USED(desc); + desc.set_ctr_used(); if (spr == SPR_XER) { - XER_COUNT_USED(desc); - XER_CA_USED(desc); - XER_OV_USED(desc); - XER_SO_USED(desc); + desc.set_xer_count_used(); + desc.set_xer_ca_used(); + desc.set_xer_ov_used(); + desc.set_xer_so_used(); } if (spr & 0x010) { @@ -887,7 +1015,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return true; case 0x053: // MFMSR - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_modified(G_RD(op)); desc.set_can_cause_exception(); desc.set_can_expose_external_int(); desc.set_privileged(); @@ -896,14 +1024,14 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return true; case 0x253: // MFSR - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_modified(G_RD(op)); desc.set_can_cause_exception(); desc.set_privileged(); return true; case 0x293: // MFSRIN - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); desc.set_can_cause_exception(); desc.set_privileged(); return true; @@ -911,45 +1039,45 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x173: // MFTB if (!(m_ppc.m_cap & PPCCAP_VEA)) return false; - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_modified(G_RD(op)); spr = compute_spr(G_SPR(op)); if (spr == SPRVEA_TBL_R) desc.cycles = POWERPC_COUNT_READ_TBL; return true; case 0x068: // NEGx - GPR_USED(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_modified(G_RD(op)); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; case 0x268: // NEGOx - GPR_USED(desc, G_RA(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; case 0x090: // MTCRF - GPR_USED(desc, G_RS(op)); - if (G_CRM(op) & 0x80) CR_MODIFIED(desc, 0); - if (G_CRM(op) & 0x40) CR_MODIFIED(desc, 1); - if (G_CRM(op) & 0x20) CR_MODIFIED(desc, 2); - if (G_CRM(op) & 0x10) CR_MODIFIED(desc, 3); - if (G_CRM(op) & 0x08) CR_MODIFIED(desc, 4); - if (G_CRM(op) & 0x04) CR_MODIFIED(desc, 5); - if (G_CRM(op) & 0x02) CR_MODIFIED(desc, 6); - if (G_CRM(op) & 0x01) CR_MODIFIED(desc, 7); + desc.set_gpr_used(G_RS(op)); + if (G_CRM(op) & 0x80) desc.set_cr_modified(0); + if (G_CRM(op) & 0x40) desc.set_cr_modified(1); + if (G_CRM(op) & 0x20) desc.set_cr_modified(2); + if (G_CRM(op) & 0x10) desc.set_cr_modified(3); + if (G_CRM(op) & 0x08) desc.set_cr_modified(4); + if (G_CRM(op) & 0x04) desc.set_cr_modified(5); + if (G_CRM(op) & 0x02) desc.set_cr_modified(6); + if (G_CRM(op) & 0x01) desc.set_cr_modified(7); return true; case 0x092: // MTMSR - GPR_USED(desc, G_RS(op)); + desc.set_gpr_used(G_RS(op)); desc.set_can_cause_exception(); desc.set_end_sequence(); desc.set_privileged(); @@ -963,24 +1091,24 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x0d2: // MTSR if (!(m_ppc.m_cap & PPCCAP_OEA)) return false; - GPR_USED(desc, G_RS(op)); + desc.set_gpr_used(G_RS(op)); desc.set_can_cause_exception(); desc.set_privileged(); return true; case 0x1d3: // MTSPR - GPR_USED(desc, G_RS(op)); + desc.set_gpr_used(G_RS(op)); spr = compute_spr(G_SPR(op)); if (spr == SPR_LR) - LR_MODIFIED(desc); + desc.set_lr_modified(); if (spr == SPR_CTR) - CTR_MODIFIED(desc); + desc.set_ctr_modified(); if (spr == SPR_XER) { - XER_COUNT_MODIFIED(desc); - XER_CA_MODIFIED(desc); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_xer_count_modified(); + desc.set_xer_ca_modified(); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); } if (spr & 0x010) { @@ -999,9 +1127,9 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x197: // STHX case 0x296: // STWBRX case 0x396: // STHBRX - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_USED(desc, G_RS(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_used(G_RS(op)); desc.set_writes_memory(); return true; @@ -1010,18 +1138,18 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x1b7: // STHUX if (G_RA(op) == 0) return false; - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_USED(desc, G_RS(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_modified(G_RA(op)); desc.set_writes_memory(); return true; case 0x0f2: // MTSRIN if (!(m_ppc.m_cap & PPCCAP_OEA)) return false; - GPR_USED(desc, G_RS(op)); - GPR_USED(desc, G_RB(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_used(G_RB(op)); desc.set_can_cause_exception(); desc.set_privileged(); return true; @@ -1029,7 +1157,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x132: // TLBIE if (!(m_ppc.m_cap & PPCCAP_OEA)) return false; - GPR_USED(desc, G_RB(op)); + desc.set_gpr_used(G_RB(op)); desc.set_can_cause_exception(); desc.set_privileged(); return true; @@ -1050,21 +1178,21 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return true; case 0x200: // MCRXR - XER_CA_USED(desc); - XER_OV_USED(desc); - XER_SO_USED(desc); - CR_MODIFIED(desc, G_CRFD(op)); - XER_CA_MODIFIED(desc); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_xer_ca_used(); + desc.set_xer_ov_used(); + desc.set_xer_so_used(); + desc.set_cr_modified(G_CRFD(op)); + desc.set_xer_ca_modified(); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); return true; case 0x215: // LSWX - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - XER_COUNT_USED(desc); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_xer_count_used(); for (regnum = 0; regnum < 32; regnum++) - GPR_MODIFIED(desc, regnum); + desc.set_gpr_modified(regnum); desc.set_reads_memory(); return true; @@ -1072,9 +1200,9 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x257: // LFDX if (!(m_ppc.m_cap & PPCCAP_FPU)) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_fpr_modified(G_RD(op)); desc.set_reads_memory(); return true; @@ -1099,34 +1227,34 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; if (G_RA(op) == 0) return false; - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RA(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RA(op)); + desc.set_fpr_modified(G_RD(op)); desc.set_reads_memory(); return true; case 0x255: // LSWI - GPR_USED_OR_ZERO(desc, G_RA(op)); + desc.set_gpr_used_or_zero(G_RA(op)); for (regnum = 0; regnum < ((G_NB(op) - 1) & 0x1f) + 1; regnum += 4) - GPR_MODIFIED(desc, (G_RD(op) + regnum / 4) % 32); + desc.set_gpr_modified((G_RD(op) + regnum / 4) % 32); desc.set_reads_memory(); desc.cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4; return true; case 0x295: // STSWX - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - XER_COUNT_USED(desc); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_xer_count_used(); for (regnum = 0; regnum < 32; regnum++) - GPR_USED(desc, regnum); + desc.set_gpr_used(regnum); desc.set_writes_memory(); return true; case 0x2d5: // STSWI - GPR_USED_OR_ZERO(desc, G_RA(op)); + desc.set_gpr_used_or_zero(G_RA(op)); for (regnum = 0; regnum < ((G_NB(op) - 1) & 0x1f) + 1; regnum += 4) - GPR_USED(desc, (G_RD(op) + regnum / 4) % 32); + desc.set_gpr_used((G_RD(op) + regnum / 4) % 32); desc.set_writes_memory(); desc.cycles = (((G_NB(op) - 1) & 0x1f) + 1 + 3) / 4; return true; @@ -1136,9 +1264,9 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x3d7: // STFIWX if (!(m_ppc.m_cap & PPCCAP_FPU)) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - FPR_USED(desc, G_RS(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_fpr_used(G_RS(op)); desc.set_writes_memory(); return true; @@ -1148,29 +1276,29 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; if (G_RA(op) == 0) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RA(op)); - FPR_USED(desc, G_RS(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RA(op)); + desc.set_fpr_used(G_RS(op)); desc.set_writes_memory(); return true; case 0x338: // SRAWIx - GPR_USED(desc, G_RS(op)); - GPR_MODIFIED(desc, G_RA(op)); - XER_CA_MODIFIED(desc); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_modified(G_RA(op)); + desc.set_xer_ca_modified(); if (op & M_RC) { - XER_SO_USED(desc); - CR_MODIFIED(desc, 0); + desc.set_xer_so_used(); + desc.set_cr_modified(0); } return true; case 0x3f6: // DCBZ if (!(m_ppc.m_cap & (PPCCAP_VEA | PPCCAP_4XX))) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); desc.set_writes_memory(); return true; @@ -1179,8 +1307,8 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x3c6: // ICCCI if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); desc.set_can_cause_exception(); desc.set_privileged(); return true; @@ -1189,9 +1317,9 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x3e6: // ICREAD if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; - GPR_USED_OR_ZERO(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RT(op)); + desc.set_gpr_used_or_zero(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RT(op)); desc.set_can_cause_exception(); desc.set_privileged(); return true; @@ -1199,7 +1327,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x143: // MFDCR if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; - GPR_MODIFIED(desc, G_RD(op)); + desc.set_gpr_modified(G_RD(op)); desc.set_can_cause_exception(); desc.set_privileged(); return true; @@ -1207,7 +1335,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x1c3: // MTDCR if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; - GPR_USED(desc, G_RS(op)); + desc.set_gpr_used(G_RS(op)); desc.set_can_cause_exception(); desc.set_can_expose_external_int(); desc.set_privileged(); @@ -1216,7 +1344,7 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc case 0x083: // WRTEE if (!(m_ppc.m_cap & PPCCAP_4XX)) return false; - GPR_USED(desc, G_RS(op)); + desc.set_gpr_used(G_RS(op)); desc.set_can_expose_external_int(); return true; @@ -1243,13 +1371,13 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; } - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; case 0x6b: // MUL (POWER) @@ -1258,13 +1386,13 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; } - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; case 0x108: // DOZ (POWER) @@ -1273,13 +1401,13 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; } - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; case 0x168: // ABS (POWER) @@ -1289,13 +1417,13 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; } - GPR_USED(desc, G_RA(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RD(op)); - XER_OV_MODIFIED(desc); - XER_SO_MODIFIED(desc); + desc.set_gpr_used(G_RA(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RD(op)); + desc.set_xer_ov_modified(); + desc.set_xer_so_modified(); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; case 0x21d: // MASKIR (POWER) @@ -1304,11 +1432,11 @@ bool ppc_device::frontend::describe_1f(uint32_t op, opcode_desc &desc, const opc return false; } - GPR_USED(desc, G_RS(op)); - GPR_USED(desc, G_RB(op)); - GPR_MODIFIED(desc, G_RA(op)); + desc.set_gpr_used(G_RS(op)); + desc.set_gpr_used(G_RB(op)); + desc.set_gpr_modified(G_RA(op)); if (op & M_RC) - CR_MODIFIED(desc, 0); + desc.set_cr_modified(0); return true; } @@ -1332,59 +1460,59 @@ bool ppc_device::frontend::describe_3b(uint32_t op, opcode_desc &desc, const opc switch (opswitch) { case 0x12: // FDIVSx - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_RB(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); + desc.set_cr_modified(1); if (is_601_class()) desc.cycles = 17; // 601 else if (is_603_class()) desc.cycles = 18; // 603 else desc.cycles = 17; // ??? - FPSCR_MODIFIED(desc, 4); + desc.set_fpscr_modified(4); return true; case 0x14: // FSUBSx case 0x15: // FADDSx - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_RB(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); - FPSCR_MODIFIED(desc, 4); + desc.set_cr_modified(1); + desc.set_fpscr_modified(4); return true; case 0x19: // FMULSx - not the same form as FSUB/FADD! - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_REGC(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_REGC(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); - FPSCR_MODIFIED(desc, 4); + desc.set_cr_modified(1); + desc.set_fpscr_modified(4); return true; case 0x16: // FSQRTSx case 0x18: // FRESx - FPR_USED(desc, G_RB(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); - FPSCR_MODIFIED(desc, 4); + desc.set_cr_modified(1); + desc.set_fpscr_modified(4); return true; case 0x1c: // FMSUBSx case 0x1d: // FMADDSx case 0x1e: // FNMSUBSx case 0x1f: // FNMADDSx - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_RB(op)); - FPR_USED(desc, G_REGC(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_used(G_REGC(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); - FPSCR_MODIFIED(desc, 4); + desc.set_cr_modified(1); + desc.set_fpscr_modified(4); return true; } @@ -1411,56 +1539,56 @@ bool ppc_device::frontend::describe_3f(uint32_t op, opcode_desc &desc, const opc switch (opswitch) { case 0x12: // FDIVx - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_RB(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); + desc.set_cr_modified(1); if (is_601_class()) desc.cycles = 31; // 601 else if (is_603_class()) desc.cycles = 33; // 603 else desc.cycles = 31; // ??? - FPSCR_MODIFIED(desc, 4); + desc.set_fpscr_modified(4); return true; case 0x19: // FMULx - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_REGC(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_REGC(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); + desc.set_cr_modified(1); desc.cycles = 2; // 601/603 - FPSCR_MODIFIED(desc, 4); + desc.set_fpscr_modified(4); return true; case 0x14: // FSUBx case 0x15: // FADDx - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_RB(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); - FPSCR_MODIFIED(desc, 4); + desc.set_cr_modified(1); + desc.set_fpscr_modified(4); return true; case 0x16: // FSQRTx case 0x1a: // FSQRTEx - FPR_USED(desc, G_RB(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); - FPSCR_MODIFIED(desc, 4); + desc.set_cr_modified(1); + desc.set_fpscr_modified(4); return true; case 0x17: // FSELx - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_RB(op)); - FPR_USED(desc, G_REGC(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_used(G_REGC(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); + desc.set_cr_modified(1); desc.cycles = 2; // 601/603 return true; @@ -1468,14 +1596,14 @@ bool ppc_device::frontend::describe_3f(uint32_t op, opcode_desc &desc, const opc case 0x1d: // FMADDx case 0x1e: // FNMSUBx case 0x1f: // FNMADDx - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_RB(op)); - FPR_USED(desc, G_REGC(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_used(G_REGC(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); + desc.set_cr_modified(1); desc.cycles = 2; // 601/603 - FPSCR_MODIFIED(desc, 4); + desc.set_fpscr_modified(4); return true; } } @@ -1490,62 +1618,62 @@ bool ppc_device::frontend::describe_3f(uint32_t op, opcode_desc &desc, const opc case 0x000: // FCMPU case 0x020: // FCMPO - FPR_USED(desc, G_RA(op)); - FPR_USED(desc, G_RB(op)); - CR_MODIFIED(desc, G_CRFD(op)); + desc.set_fpr_used(G_RA(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_cr_modified(G_CRFD(op)); return true; case 0x00c: // FRSPx case 0x00e: // FCTIWx case 0x00f: // FCTIWZx - FPSCR_MODIFIED(desc, 4); + desc.set_fpscr_modified(4); [[fallthrough]]; case 0x028: // FNEGx case 0x048: // FMRx case 0x088: // FNABSx case 0x108: // FABSx - FPR_USED(desc, G_RB(op)); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpr_used(G_RB(op)); + desc.set_fpr_modified(G_RD(op)); if (op & M_RC) - CR_MODIFIED(desc, 1); + desc.set_cr_modified(1); return true; case 0x026: // MTFSB1x case 0x046: // MTFSB0x - FPSCR_MODIFIED(desc, G_CRBD(op) / 4); + desc.set_fpscr_modified(G_CRBD(op) / 4); return true; case 0x040: // MCRFS - FPSCR_USED(desc, G_CRFS(op)); - CR_MODIFIED(desc, G_CRFD(op)); + desc.set_fpscr_used(G_CRFS(op)); + desc.set_cr_modified(G_CRFD(op)); return true; case 0x086: // MTFSFIx - FPSCR_MODIFIED(desc, G_CRFD(op)); + desc.set_fpscr_modified(G_CRFD(op)); return true; case 0x247: // MFFSx - FPSCR_USED(desc, 0); - FPSCR_USED(desc, 1); - FPSCR_USED(desc, 2); - FPSCR_USED(desc, 3); - FPSCR_USED(desc, 4); - FPSCR_USED(desc, 5); - FPSCR_USED(desc, 6); - FPSCR_USED(desc, 7); - FPR_MODIFIED(desc, G_RD(op)); + desc.set_fpscr_used(0); + desc.set_fpscr_used(1); + desc.set_fpscr_used(2); + desc.set_fpscr_used(3); + desc.set_fpscr_used(4); + desc.set_fpscr_used(5); + desc.set_fpscr_used(6); + desc.set_fpscr_used(7); + desc.set_fpr_modified(G_RD(op)); return true; case 0x2c7: // MTFSFx - FPR_USED(desc, G_RB(op)); - if (G_CRM(op) & 0x80) FPSCR_MODIFIED(desc, 0); - if (G_CRM(op) & 0x40) FPSCR_MODIFIED(desc, 1); - if (G_CRM(op) & 0x20) FPSCR_MODIFIED(desc, 2); - if (G_CRM(op) & 0x10) FPSCR_MODIFIED(desc, 3); - if (G_CRM(op) & 0x08) FPSCR_MODIFIED(desc, 4); - if (G_CRM(op) & 0x04) FPSCR_MODIFIED(desc, 5); - if (G_CRM(op) & 0x02) FPSCR_MODIFIED(desc, 6); - if (G_CRM(op) & 0x01) FPSCR_MODIFIED(desc, 7); + desc.set_fpr_used(G_RB(op)); + if (G_CRM(op) & 0x80) desc.set_fpscr_modified(0); + if (G_CRM(op) & 0x40) desc.set_fpscr_modified(1); + if (G_CRM(op) & 0x20) desc.set_fpscr_modified(2); + if (G_CRM(op) & 0x10) desc.set_fpscr_modified(3); + if (G_CRM(op) & 0x08) desc.set_fpscr_modified(4); + if (G_CRM(op) & 0x04) desc.set_fpscr_modified(5); + if (G_CRM(op) & 0x02) desc.set_fpscr_modified(6); + if (G_CRM(op) & 0x01) desc.set_fpscr_modified(7); return true; } } diff --git a/src/devices/cpu/powerpc/ppcfe.h b/src/devices/cpu/powerpc/ppcfe.h index b72f9256fb9..c3483db3dd7 100644 --- a/src/devices/cpu/powerpc/ppcfe.h +++ b/src/devices/cpu/powerpc/ppcfe.h @@ -17,6 +17,8 @@ #include "cpu/drcfe.h" #include +#include +#include //************************************************************************** @@ -32,6 +34,45 @@ public: u32 cycles; // number of cycles needed to execute + void set_gpr_used(unsigned n) { regin.set(REG_BIT_R0 + n); } + void set_gpr_used_or_zero(unsigned n) { if (n) set_gpr_used(n); } + void set_gpr_modified(unsigned n) { regout.set(REG_BIT_R0 + n); } + + void set_fpr_used(unsigned n) { regin.set(REG_BIT_FR0 + n); } + void set_fpr_modified(unsigned n) { regout.set(REG_BIT_FR0 + n); } + + void set_cr_used(unsigned n) { set_cr_bit_used((n * 4) + 0); set_cr_bit_used((n * 4) + 1); set_cr_bit_used((n * 4) + 2); set_cr_bit_used((n * 4) + 3); } + void set_cr_bit_used(unsigned n) { regin.set(64 + 31 - n); } + void set_cr_modified(unsigned n) { set_cr_bit_modified((n * 4) + 0); set_cr_bit_modified((n * 4) + 1); set_cr_bit_modified((n * 4) + 2); set_cr_bit_modified((n * 4) + 3); } + void set_cr_bit_modified(unsigned n) { regout.set(64 + 31 - n); } + + void set_xer_ca_used() { regin.set(REG_BIT_XER_CA); } + void set_xer_ov_used() { regin.set(REG_BIT_XER_OV); } + void set_xer_so_used() { regin.set(REG_BIT_XER_SO); } + void set_xer_count_used() { regin.set(REG_BIT_XER_COUNT); } + void set_xer_ca_modified() { regout.set(REG_BIT_XER_CA); } + void set_xer_ov_modified() { regout.set(REG_BIT_XER_OV); } + void set_xer_so_modified() { regout.set(REG_BIT_XER_SO); } + void set_xer_count_modified() { regout.set(REG_BIT_XER_COUNT); } + + void set_ctr_used() { regin.set(REG_BIT_CTR); } + void set_lr_used() { regin.set(REG_BIT_LR); } + void set_ctr_modified() { regout.set(REG_BIT_CTR); } + void set_lr_modified() { regout.set(REG_BIT_LR); } + + void set_fpscr_used(unsigned n) { regin.set(REG_BIT_FPSCR0 + n); } + void set_fpscr_modified(unsigned n) { regout.set(REG_BIT_FPSCR0 + n); } + + uint32_t cr_modified() const { return regmask_field<64, 32>(regout); } + uint8_t cr_modified(unsigned n) const { return reg_cr(regout, n); } + uint32_t cr_required() const { return regmask_field<64, 32>(regreq); } + uint8_t cr_required(unsigned n) const { return reg_cr(regreq, n); } + + bool xer_ca_required() const { return regreq[REG_BIT_XER_CA]; } + bool xer_ov_required() const { return regreq[REG_BIT_XER_OV]; } + bool xer_so_required() const { return regreq[REG_BIT_XER_SO]; } + bool xer_count_required() const { return regreq[REG_BIT_XER_COUNT]; } + void set_can_expose_external_int() { m_extra_flags.set(CAN_EXPOSE_EXTERNAL_INT); } void set_privileged() { m_extra_flags.set(PRIVILEGED); } void set_compiler_unmapped() { m_extra_flags.set(COMPILER_UNMAPPED); } @@ -48,6 +89,8 @@ public: void reset(offs_t curpc, bool in_delay_slot) { + static_assert(REG_BIT_COUNT <= 128); + opcode_desc_base::reset(curpc, in_delay_slot); physpc = curpc; @@ -56,7 +99,26 @@ public: m_extra_flags.reset(); } + void log_flags(std::ostream &stream) const; + void log_registers_used(std::ostream &stream) const; + void log_registers_modified(std::ostream &stream) const; + protected: + enum + { + REG_BIT_R0 = 0, + REG_BIT_FR0 = 32, + REG_BIT_XER_CA = 96, + REG_BIT_XER_OV, + REG_BIT_XER_SO, + REG_BIT_XER_COUNT, + REG_BIT_CTR, + REG_BIT_LR, + REG_BIT_FPSCR0, + + REG_BIT_COUNT = REG_BIT_FPSCR0 + 8 + }; + enum { CAN_EXPOSE_EXTERNAL_INT = 0, @@ -69,27 +131,24 @@ protected: EXTRA_FLAG_COUNT }; + // TODO: uncomment constexpr when GCC/GNU libstdc++ catch up + static /*constexpr*/ bool reg_cr_bit(const regmask &r, unsigned n) + { + return r[64 + 31 - n]; + } + static /*constexpr*/ uint8_t reg_cr(const regmask &r, unsigned n) + { + return uint8_t(((r << ((4 * n) + 32)) >> (128 - 4)).to_ulong()); + } + + static void log_register_list(std::ostream &stream, const regmask ®list, const regmask *regnostarlist); + std::bitset m_extra_flags; }; class ppc_device::frontend : public drc_frontend_base { public: - // TODO: uncomment constexpr when GCC/GNU libstdc++ catch up - static constexpr bool REGFLAG_R(const opcode_desc::regmask &r, unsigned n) { return r[REG_BIT_R0 + n]; } - static constexpr bool REGFLAG_RZ(const opcode_desc::regmask &r, unsigned n) { return n && REGFLAG_R(r, n); } - static constexpr bool REGFLAG_FR(const opcode_desc::regmask &r, unsigned n) { return r[REG_BIT_FR0 + n]; } - static /*constexpr*/ uint32_t REGFLAG_CR(const opcode_desc::regmask &r) { return uint32_t(((r << 32) >> (128 - 32)).to_ulong()); } - static /*constexpr*/ uint8_t REGFLAG_CR(const opcode_desc::regmask &r, unsigned n) { return uint8_t(((r << ((4 * n) + 32)) >> (128 - 4)).to_ulong()); } - static constexpr bool REGFLAG_CR_BIT(const opcode_desc::regmask &r, unsigned n) { return r[64 + 31 - n]; } - static constexpr bool REGFLAG_XER_CA(const opcode_desc::regmask &r) { return r[REG_BIT_XER_CA]; } - static constexpr bool REGFLAG_XER_OV(const opcode_desc::regmask &r) { return r[REG_BIT_XER_OV]; } - static constexpr bool REGFLAG_XER_SO(const opcode_desc::regmask &r) { return r[REG_BIT_XER_SO]; } - static constexpr bool REGFLAG_XER_COUNT(const opcode_desc::regmask &r) { return r[REG_BIT_XER_COUNT]; } - static constexpr bool REGFLAG_CTR(const opcode_desc::regmask &r) { return r[REG_BIT_CTR]; } - static constexpr bool REGFLAG_LR(const opcode_desc::regmask &r) { return r[REG_BIT_LR]; } - static constexpr bool REGFLAG_FPSCR(const opcode_desc::regmask &r, unsigned n) { return r[REG_BIT_FPSCR0 + n]; } - // construction/destruction frontend(ppc_device &ppc, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); ~frontend(); @@ -97,23 +156,10 @@ public: opcode_desc const *describe_code(offs_t startpc); protected: - enum - { - REG_BIT_R0 = 0, - REG_BIT_FR0 = 32, - REG_BIT_XER_CA = 96, - REG_BIT_XER_OV, - REG_BIT_XER_SO, - REG_BIT_XER_COUNT, - REG_BIT_CTR, - REG_BIT_LR, - REG_BIT_FPSCR0 - }; - bool describe(opcode_desc &desc, const opcode_desc *prev); // inlines - uint32_t compute_spr(uint32_t spr) const { return ((spr >> 5) | (spr << 5)) & 0x3ff; } + static constexpr uint32_t compute_spr(uint32_t spr) { return ((spr >> 5) | (spr << 5)) & 0x3ff; } bool is_403_class() const { return (m_ppc.m_flavor == ppc_device::PPC_MODEL_403GA || m_ppc.m_flavor == ppc_device::PPC_MODEL_403GB || m_ppc.m_flavor == ppc_device::PPC_MODEL_403GC || m_ppc.m_flavor == ppc_device::PPC_MODEL_403GCX || m_ppc.m_flavor == ppc_device::PPC_MODEL_405GP); } bool is_601_class() const { return (m_ppc.m_flavor == ppc_device::PPC_MODEL_601); } bool is_602_class() const { return (m_ppc.m_flavor == ppc_device::PPC_MODEL_602); } diff --git a/src/devices/cpu/sh/sh.cpp b/src/devices/cpu/sh/sh.cpp index c507410d759..72945b2e364 100644 --- a/src/devices/cpu/sh/sh.cpp +++ b/src/devices/cpu/sh/sh.cpp @@ -11,6 +11,10 @@ #include "emuopts.h" +#include "util/vecstream.h" + +#include + sh_common_execution::sh_common_execution(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal) : cpu_device(mconfig, type, tag, owner, clock) @@ -2028,59 +2032,6 @@ void sh_common_execution::save_fast_iregs(drcuml_block &block) } -/*------------------------------------------------- - log_desc_flags_to_string - generate a string - representing the instruction description - flags --------------------------------------------------*/ - -const char *sh_common_execution::log_desc_flags_to_string(const opcode_desc &desc) -{ - static char tempbuf[30]; - char *dest = tempbuf; - - /* branches */ - if (desc.is_unconditional_branch()) - *dest++ = 'U'; - else if (desc.is_conditional_branch()) - *dest++ = 'C'; - else - *dest++ = '.'; - - /* intrablock branches */ - *dest++ = desc.intrablock_branch() ? 'i' : '.'; - - /* branch targets */ - *dest++ = desc.is_branch_target() ? 'B' : '.'; - - /* delay slots */ - *dest++ = desc.in_delay_slot() ? 'D' : '.'; - - /* exceptions */ - if (desc.will_cause_exception()) - *dest++ = 'E'; - else if (desc.can_cause_exception()) - *dest++ = 'e'; - else - *dest++ = '.'; - - /* read/write */ - if (desc.reads_memory()) - *dest++ = 'R'; - else if (desc.writes_memory()) - *dest++ = 'W'; - else - *dest++ = '.'; - - /* TLB validation */ - *dest++ = desc.validate_tlb() ? 'V' : '.'; - - /* redispatch */ - *dest++ = desc.redispatch() ? 'R' : '.'; - return tempbuf; -} - - /*------------------------------------------------- log_register_list - log a list of GPR registers -------------------------------------------------*/ @@ -2156,6 +2107,10 @@ void sh_common_execution::log_register_list(const char *string, const std::bitse void sh_common_execution::log_opcode_desc(const opcode_desc *desclist, int indent) { + sh_disassembler sh2d(false); + util::ovectorstream buffer; + buffer.imbue(std::locale::classic()); + /* open the file, creating it if necessary */ if (indent == 0) m_drcuml->log_printf("\nDescriptor list @ %08X\n", desclist->pc); @@ -2163,22 +2118,21 @@ void sh_common_execution::log_opcode_desc(const opcode_desc *desclist, int inden /* output each descriptor */ for ( ; desclist != nullptr; desclist = desclist->next()) { - std::ostringstream stream; + buffer.clear(); + buffer.seekp(0); + desclist->log_flags(buffer); + buffer.put('\0'); + m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: ", desclist->pc, desclist->physpc, desclist->targetpc, &buffer.vec()[0]); /* disassemle the current instruction and output it to the log */ - if (m_drcuml->logging() || m_drcuml->logging_native()) - { - if (desclist->virtual_noop()) - stream << ""; - else - { - sh_disassembler sh2d(false); - sh2d.dasm_one(stream, desclist->pc, desclist->opptr); - } - } + buffer.clear(); + buffer.seekp(0); + if (desclist->virtual_noop()) + buffer << ""; else - stream << "???"; - m_drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(*desclist), stream.str()); + sh2d.dasm_one(buffer, desclist->pc, desclist->opptr); + buffer.put('\0'); + m_drcuml->log_printf("%-36s", &buffer.vec()[0]); /* output register states */ log_register_list("use", desclist->regin, nullptr); diff --git a/src/devices/cpu/sh/sh.h b/src/devices/cpu/sh/sh.h index 3d726db11bd..c06fbeddf10 100644 --- a/src/devices/cpu/sh/sh.h +++ b/src/devices/cpu/sh/sh.h @@ -443,7 +443,6 @@ public: void alloc_handle(uml::code_handle *&handleptr, const char *name); void load_fast_iregs(drcuml_block &block); void save_fast_iregs(drcuml_block &block); - const char *log_desc_flags_to_string(const opcode_desc &flags); void log_register_list(const char *string, const std::bitset<32> ®list, const std::bitset<32> *regnostarlist); void log_opcode_desc(const opcode_desc *desclist, int indent); void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op); diff --git a/src/devices/cpu/sh/sh_fe.cpp b/src/devices/cpu/sh/sh_fe.cpp index f62ecf110fb..0716231aef7 100644 --- a/src/devices/cpu/sh/sh_fe.cpp +++ b/src/devices/cpu/sh/sh_fe.cpp @@ -14,6 +14,56 @@ #include "cpu/drcfe.ipp" + +/*------------------------------------------------- + log_flags - log the instruction description to + a stream +-------------------------------------------------*/ + +void sh_common_execution::opcode_desc::log_flags(std::ostream &stream) const +{ + // branches + if (is_unconditional_branch()) + stream << 'U'; + else if (is_conditional_branch()) + stream << 'C'; + else + stream << '.'; + + // intrablock branches + stream << (intrablock_branch() ? 'i' : '.'); + + // branch targets + stream << (is_branch_target() ? 'B' : '.'); + + // delay slots + stream << (in_delay_slot() ? 'D' : '.'); + + // exceptions + if (will_cause_exception()) + stream << 'E'; + else if (can_cause_exception()) + stream << 'e'; + else + stream << '.'; + + // read/write + if (reads_memory()) + stream << (writes_memory() ? '+' : 'R'); + else if (writes_memory()) + stream << 'W'; + else + stream << '.'; + + // TLB validation + stream << (validate_tlb() ? 'V' : '.'); + + // redispatch + stream << (redispatch() ? 'R' : '.'); +} + + + /*************************************************************************** INSTRUCTION PARSERS ***************************************************************************/ diff --git a/src/devices/cpu/sh/sh_fe.h b/src/devices/cpu/sh/sh_fe.h index 26439f8af8d..ba63138e3eb 100644 --- a/src/devices/cpu/sh/sh_fe.h +++ b/src/devices/cpu/sh/sh_fe.h @@ -16,6 +16,9 @@ #include "cpu/drcfe.h" +#include +#include + class sh_common_execution::opcode_desc : public opcode_desc_base { @@ -83,6 +86,8 @@ public: m_can_expose_external_int = false; } + void log_flags(std::ostream &stream) const; + private: bool m_reads_memory; bool m_writes_memory; diff --git a/src/lib/util/client_ws.hpp b/src/lib/util/client_ws.hpp index 04af5026014..01540907843 100644 --- a/src/lib/util/client_ws.hpp +++ b/src/lib/util/client_ws.hpp @@ -99,7 +99,7 @@ namespace webpp { std::list send_queue; void send_from_queue() { - strand.post([this]() { + asio::post(strand, [this]() { asio::async_write(*socket, send_queue.begin()->send_stream->streambuf, strand.wrap([this](const std::error_code& ec, size_t /*bytes_transferred*/) { auto send_queued=send_queue.begin(); @@ -175,7 +175,7 @@ namespace webpp { } if(io_context->stopped()) - io_context->reset(); + io_context->restart(); if(!resolver) resolver= std::make_unique(*io_context); @@ -237,7 +237,7 @@ namespace webpp { send_stream->put(message_stream->get()^mask[c%4]); } - connection->strand.post([this, send_stream, callback]() { + asio::post(connection->strand, [this, send_stream, callback]() { connection->send_queue.emplace_back(send_stream, callback); if(connection->send_queue.size()==1) connection->send_from_queue(); @@ -516,15 +516,13 @@ namespace webpp { protected: void connect() override { - asio::ip::tcp::resolver::query query(host, std::to_string(port)); - - resolver->async_resolve(query, [this] - (const std::error_code &ec, asio::ip::tcp::resolver::iterator it){ + resolver->async_resolve(host, std::to_string(port), [this] + (const std::error_code &ec, asio::ip::tcp::resolver::results_type results){ if(!ec) { connection=std::shared_ptr(new Connection(*io_context, new WS(*io_context))); - asio::async_connect(*connection->socket, it, [this] - (const std::error_code &ec, asio::ip::tcp::resolver::iterator /*it*/){ + asio::async_connect(*connection->socket, results, [this] + (const std::error_code &ec, const asio::ip::tcp::endpoint &/*endpoint*/){ if(!ec) { asio::ip::tcp::no_delay option(true); connection->socket->set_option(option); diff --git a/src/lib/util/server_ws_impl.hpp b/src/lib/util/server_ws_impl.hpp index c1ba9f1a392..4f7468232c3 100644 --- a/src/lib/util/server_ws_impl.hpp +++ b/src/lib/util/server_ws_impl.hpp @@ -96,7 +96,7 @@ namespace webpp { std::list send_queue; void send_from_queue(const std::shared_ptr &connection) { - strand.post([this, connection]() { + asio::post(strand, [this, connection]() { asio::async_write(*socket, send_queue.begin()->header_stream->streambuf, strand.wrap([this, connection](const std::error_code& ec, size_t /*bytes_transferred*/) { if(!ec) { @@ -219,11 +219,11 @@ namespace webpp { io_context=std::make_shared(); if(io_context->stopped()) - io_context->reset(); + io_context->restart(); asio::ip::tcp::endpoint endpoint; if(config.address.size()>0) - endpoint=asio::ip::tcp::endpoint(asio::ip::address::from_string(config.address), config.port); + endpoint=asio::ip::tcp::endpoint(asio::ip::make_address(config.address), config.port); else endpoint=asio::ip::tcp::endpoint(asio::ip::tcp::v4(), config.port); @@ -283,7 +283,7 @@ namespace webpp { else header_stream->put(static_cast(length)); - connection->strand.post([connection, header_stream, message_stream, callback]() { + asio::post(connection->strand, [connection, header_stream, message_stream, callback]() { connection->send_queue.emplace_back(header_stream, message_stream, callback); if(connection->send_queue.size()==1) connection->send_from_queue(connection); @@ -653,12 +653,12 @@ namespace webpp { void timer_idle_init(const std::shared_ptr &connection) { if(config.timeout_idle>0) { connection->timer_idle= std::make_unique(connection->socket->get_executor()); - connection->timer_idle->expires_from_now(std::chrono::seconds(static_cast(config.timeout_idle))); + connection->timer_idle->expires_after(std::chrono::seconds(static_cast(config.timeout_idle))); timer_idle_expired_function(connection); } } void timer_idle_reset(const std::shared_ptr &connection) const { - if(config.timeout_idle>0 && connection->timer_idle->expires_from_now(std::chrono::seconds(static_cast(config.timeout_idle)))>0) + if(config.timeout_idle>0 && connection->timer_idle->expires_after(std::chrono::seconds(static_cast(config.timeout_idle)))>0) timer_idle_expired_function(connection); } void timer_idle_cancel(const std::shared_ptr &connection) const { diff --git a/src/mame/capcom/cps2comm.cpp b/src/mame/capcom/cps2comm.cpp index 95701ef264d..2dac7035b1c 100644 --- a/src/mame/capcom/cps2comm.cpp +++ b/src/mame/capcom/cps2comm.cpp @@ -173,7 +173,8 @@ public: void stop() { - m_ioctx.post( + asio::post( + m_ioctx, [this] () { m_stopping = true; @@ -191,7 +192,8 @@ public: void set_routing(u8 val) { - m_ioctx.post( + asio::post( + m_ioctx, [this, val] () { if (BIT(val, 0, 2) == 0U) @@ -216,7 +218,8 @@ public: void send_in(u8 data) { - m_ioctx.post( + asio::post( + m_ioctx, [this, data] () { if (m_in_connected) @@ -231,7 +234,8 @@ public: void send_out(u8 data) { - m_ioctx.post( + asio::post( + m_ioctx, [this, data] () { if (m_out_sock.is_open()) diff --git a/src/mame/nakajima/nakajies.cpp b/src/mame/nakajima/nakajies.cpp index 4506c368d4b..3fc10647388 100644 --- a/src/mame/nakajima/nakajies.cpp +++ b/src/mame/nakajima/nakajies.cpp @@ -302,8 +302,7 @@ public: , m_rtc(*this, "rtc") , m_view{ {*this, "view_0"}, {*this, "view_1"}, {*this, "view_2"}, {*this, "view_3"}, - {*this, "view_4"}, {*this, "view_5"}, {*this, "view_6"}, {*this, "view_7"} - } + {*this, "view_4"}, {*this, "view_5"}, {*this, "view_6"}, {*this, "view_7"} } , m_port_row(*this, "ROW%u", 0U) , m_port_debug(*this, "debug") , m_rombank(*this, "rombank%u", 0U) @@ -312,11 +311,11 @@ public: { } - void nakajies210(machine_config &config); - void nakajies220(machine_config &config); - void nakajies220_256(machine_config &config); - void nakajies250(machine_config &config); - void dator3k(machine_config &config); + void nakajies210(machine_config &config) ATTR_COLD; + void nakajies220(machine_config &config) ATTR_COLD; + void nakajies220_256(machine_config &config) ATTR_COLD; + void nakajies250(machine_config &config) ATTR_COLD; + void dator3k(machine_config &config) ATTR_COLD; DECLARE_INPUT_CHANGED_MEMBER(trigger_irq); @@ -621,16 +620,14 @@ void nakajies_state::machine_reset() m_lcd_memory_start = 0; m_matrix = 0; - for (int i = 0; i < 8; i++) - { - m_view[i].select(0); - } + for (auto &view : m_view) + view.select(0); - for (int i = 0; i < 8; i++) - { - m_rombank[i]->set_entry(0x0f); - m_rambank[i]->set_entry(0x0f); - } + for (auto &bank : m_rombank) + bank->set_entry(0x0f); + + for (auto &bank : m_rambank) + bank->set_entry(0x0f); } u32 nakajies_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) @@ -826,11 +823,11 @@ ROM_END } // anonymous namespace -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 199?, wales210, 0, 0, nakajies210, nakajies, nakajies_state, empty_init, "Walther", "ES-210", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // German, 128KB RAM -COMP( 199?, dator3k, wales210, 0, dator3k, nakajies, nakajies_state, empty_init, "Dator", "Dator 3000", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // Spanish, 128KB RAM -COMP( 199?, es210_es, wales210, 0, nakajies210, nakajies, nakajies_state, empty_init, "Nakajima", "ES-210 (Spain)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // Spanish, 128KB RAM -COMP( 199?, drwrt100, wales210, 0, nakajies220, nakajies, nakajies_state, empty_init, "NTS", "DreamWriter T100", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // English, 128KB RAM +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 199?, wales210, 0, 0, nakajies210, nakajies, nakajies_state, empty_init, "Walther", "ES-210", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // German, 128KB RAM +COMP( 199?, dator3k, wales210, 0, dator3k, nakajies, nakajies_state, empty_init, "Dator", "Dator 3000", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // Spanish, 128KB RAM +COMP( 199?, es210_es, wales210, 0, nakajies210, nakajies, nakajies_state, empty_init, "Nakajima", "ES-210 (Spain)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // Spanish, 128KB RAM +COMP( 199?, drwrt100, wales210, 0, nakajies220, nakajies, nakajies_state, empty_init, "NTS", "DreamWriter T100", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // English, 128KB RAM COMP( 1996, drwrt400, wales210, 0, nakajies220_256, nakajies, nakajies_state, empty_init, "NTS", "DreamWriter T400", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // English, 256KB RAM, also found a machine with 160KB RAM -COMP( 199?, drwrt450, wales210, 0, nakajies220, nakajies, nakajies_state, empty_init, "NTS", "DreamWriter 450", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // English, 128KB RAM -COMP( 199?, drwrt200, wales210, 0, nakajies250, nakajies, nakajies_state, empty_init, "NTS", "DreamWriter T200", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // English, 256KB? RAM +COMP( 199?, drwrt450, wales210, 0, nakajies220, nakajies, nakajies_state, empty_init, "NTS", "DreamWriter 450", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // English, 128KB RAM +COMP( 199?, drwrt200, wales210, 0, nakajies250, nakajies, nakajies_state, empty_init, "NTS", "DreamWriter T200", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // English, 256KB? RAM diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index ded12f49f09..b479313119b 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -51,7 +51,7 @@ using util::BIT; #include "cpu/dsp563xx/dsp563xxd.h" #include "cpu/dspp/dsppdasm.h" #include "cpu/e0c6200/e0c6200d.h" -#include "cpu/e132xs/32xsdasm.h" +#include "cpu/e132xs/e1dasm.h" #include "cpu/es5510/es5510d.h" #include "cpu/esrip/esripdsm.h" #include "cpu/f2mc16/f2mc16d.h" @@ -347,16 +347,6 @@ struct z8000_unidasm_t : z8000_disassembler::config virtual bool get_segmented_mode() const override { return segmented_mode; } } z8000_unidasm; -// Configuration missing -struct hyperstone_unidasm_t : hyperstone_disassembler::config -{ - bool h; - hyperstone_unidasm_t() { h = false; } - virtual ~hyperstone_unidasm_t() = default; - - virtual bool get_h() const { return h; } -} hyperstone_unidasm; - // Configuration missing struct nec_unidasm_t : nec_disassembler::config { @@ -491,7 +481,7 @@ static const dasm_table_entry dasm_table[] = { "hp_09825_67907", be, -1, []() -> util::disasm_interface * { return new hp_09825_67907_disassembler; } }, { "hpc16083", le, 0, []() -> util::disasm_interface * { return new hpc16083_disassembler; } }, { "hpc16164", le, 0, []() -> util::disasm_interface * { return new hpc16164_disassembler; } }, - { "hyperstone", be, 0, []() -> util::disasm_interface * { return new hyperstone_disassembler(&hyperstone_unidasm); } }, + { "hyperstone", be, 0, []() -> util::disasm_interface * { return new hyperstone_disassembler(nullptr); } }, { "ht1130", le, 0, []() -> util::disasm_interface * { return new ht1130_disassembler; } }, { "i4004", le, 0, []() -> util::disasm_interface * { return new i4004_disassembler; } }, { "i4040", le, 0, []() -> util::disasm_interface * { return new i4040_disassembler; } }, -- cgit v1.2.3