diff options
Diffstat (limited to 'src/devices/cpu/es5510/es5510.cpp')
-rw-r--r-- | src/devices/cpu/es5510/es5510.cpp | 364 |
1 files changed, 173 insertions, 191 deletions
diff --git a/src/devices/cpu/es5510/es5510.cpp b/src/devices/cpu/es5510/es5510.cpp index 2349b789646..03cea0595a7 100644 --- a/src/devices/cpu/es5510/es5510.cpp +++ b/src/devices/cpu/es5510/es5510.cpp @@ -2,11 +2,11 @@ // copyright-holders:Christian Brunschen /*************************************************************************************** * - * es5510.c - Ensoniq ES5510 (ESP) emulation + * es5510.cpp - Ensoniq ES5510 (ESP) emulation * by Christian Brunschen * - * TODO - * ridingf, ringrage and clones: Exception after logo is displayed (MT #06894) + * TODO: + * gunlock and clones: Glitch sound after game over once (MT #07861) * DRAM Size isn't verified, differs per machines? * ***************************************************************************************/ @@ -16,49 +16,28 @@ #include "es5510d.h" #include "cpu/m68000/m68000.h" -#include "debugger.h" +#include "corestr.h" + +#include <cstdarg> #include <cstdio> #include <algorithm> -static constexpr int32_t MIN_24 = -(1 << 23); -static constexpr int32_t MAX_24 = (1 << 23) - 1; - -static constexpr int64_t MIN_48 = -(s64(1) << 47); -static constexpr int64_t MAX_48 = (s64(1) << 47) - 1; - -#define SIGN_BIT_24 (0x00800000) -#define GET_SIGN_BIT_24(x) ((x) & SIGN_BIT_24) -#define IS_NEGATIVE(x) (((x) & SIGN_BIT_24) != 0) - -#define CARRY_OUT_24 (0x01000000) - -constexpr int32_t SX(int32_t x) { return IS_NEGATIVE(x) ? x | 0xff000000 : x & 0x00ffffff; } -constexpr int32_t SC(int32_t x) { return x & 0x00ffffff; } -constexpr int64_t SX64(int64_t x) { return (x & s64(0x0000800000000000U)) ? x | s64(0xffff000000000000U) : x & s64(0x0000ffffffffffffU); } -//constexpr int64_t SC64(int64_t x) { return x & s64(0x0000ffffffffffffU); } - -#define VERBOSE 0 #define VERBOSE_EXEC 0 -static inline void ATTR_PRINTF(1,2) log_to_stderr(const char *format, ...) { - va_list ap; - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); -} - -#define LOG(...) do { if (VERBOSE) log_to_stderr(__VA_ARGS__); } while(0) - +#define LOG_EXECUTION (1U << 1) #if VERBOSE_EXEC static int exec_cc = 0; -#define LOG_EXEC(x) do { if (!exec_cc) LOG x; } while(0) +#define VERBOSE (LOG_EXECUTION) #else -#define LOG_EXEC(x) +#define VERBOSE (0) #endif +#include "logmacro.h" -DEFINE_DEVICE_TYPE(ES5510, es5510_device, "es5510", "ES5510") +#define LOG_EXEC(...) LOGMASKED(LOG_EXECUTION, __VA_ARGS__) + +DEFINE_DEVICE_TYPE(ES5510, es5510_device, "es5510", "Ensoniq ES5510") #define FLAG_N (1 << 7) #define FLAG_C (1 << 6) @@ -92,26 +71,27 @@ inline static bool isFlagSet(uint8_t ccr, uint8_t flag) { } inline static int32_t add(int32_t a, int32_t b, uint8_t &flags) { - int32_t aSign = a & SIGN_BIT_24; - int32_t bSign = b & SIGN_BIT_24; + int32_t aSign = a & 0x00800000; + int32_t bSign = b & 0x00800000; int32_t result = a + b; - int32_t resultSign = result & SIGN_BIT_24; + int32_t resultSign = result & 0x00800000; bool overflow = (aSign == bSign) && (aSign != resultSign); - bool carry = result & CARRY_OUT_24; + bool carry = result & 0x01000000; bool negative = resultSign != 0; bool lessThan = (overflow && !negative) || (!overflow && negative); flags = setFlagTo(flags, FLAG_C, carry); flags = setFlagTo(flags, FLAG_N, negative); - flags = setFlagTo(flags, FLAG_Z, result == 0); + flags = setFlagTo(flags, FLAG_Z, (result & 0x00ffffff) == 0); flags = setFlagTo(flags, FLAG_V, overflow); flags = setFlagTo(flags, FLAG_LT, lessThan); - return SC(result); + return result & 0x00ffffff; } inline static int32_t saturate(int32_t value, uint8_t &flags, bool negative) { if (isFlagSet(flags, FLAG_V)) { - setFlagTo(flags, FLAG_N, negative); - return negative ? MIN_24 : MAX_24; + flags = setFlagTo(flags, FLAG_N, negative); + flags = clearFlag(flags, FLAG_Z); + return negative ? 0x00800000 : 0x007fffff; } else { return value; } @@ -122,10 +102,11 @@ inline static int32_t negate(int32_t value) { } inline static int32_t asl(int32_t value, int shift, uint8_t &flags) { - int32_t signBefore = value & SIGN_BIT_24; + int32_t signBefore = value & 0x00800000; int32_t result = value << shift; - int32_t signAfter = result & SIGN_BIT_24; + int32_t signAfter = result & 0x00800000; bool overflow = signBefore != signAfter; + flags = setFlagTo(flags, FLAG_Z, (result & 0x00ffffff) == 0); flags = setFlagTo(flags, FLAG_V, overflow); return saturate(result, flags, signBefore != 0); } @@ -170,6 +151,7 @@ es5510_device::es5510_device(const machine_config &mconfig, const char *tag, dev , instr_latch(0) , ram_sel(0) , host_control(0) + , host_serial(0) { dol[0] = dol[1] = 0; memset(&alu, 0, sizeof(alu)); @@ -288,7 +270,7 @@ const es5510_device::ram_control_t es5510_device::RAM_CONTROL[8] = { }; static inline char * DESCRIBE_RAM(char *s, uint8_t ramControl, uint32_t gprContents) { - return s + sprintf(s, es5510_device::RAM_CONTROL[ramControl].description, SC(gprContents)); + return s + sprintf(s, es5510_device::RAM_CONTROL[ramControl].description, gprContents & 0x00ffffff); } static inline char * DESCRIBE_ALU(char *s, uint8_t opcode, uint8_t aReg, const char *aName, uint8_t bReg, const char *bName, const op_select_t &opSelect) { @@ -355,19 +337,9 @@ static inline char * DESCRIBE_INSTR(char *s, uint64_t instr, uint32_t gpr, const } -READ8_MEMBER(es5510_device::host_r) +uint8_t es5510_device::host_r(address_space &space, offs_t offset) { // printf("%06x: DSP read offset %04x (data is %04x)\n",pc(),offset,dsp_ram[offset]); - - // VFX hack - if (core_stricmp(machine().system().name, "vfx") == 0) - { - if (pc == 0xc091f0) - { - return space.device().state().state_int(M68K_D2); - } - } - switch(offset) { case 0x00: LOG("ES5510: Host Read GPR latch[2]: %02x\n", (gpr_latch >> 16) & 0xff); return (gpr_latch >> 16) & 0xff; @@ -402,7 +374,7 @@ READ8_MEMBER(es5510_device::host_r) return 0x00; } -WRITE8_MEMBER(es5510_device::host_w) +void es5510_device::host_w(offs_t offset, uint8_t data) { #if VERBOSE static char buf[1024]; @@ -410,30 +382,39 @@ WRITE8_MEMBER(es5510_device::host_w) switch (offset) { case 0x00: gpr_latch = (gpr_latch&0x00ffff) | ((data&0xff)<<16); - LOG("ES5510: Host Write GPR latch[2] = %02x -> %06x (%d)\n", data, gpr_latch, SX(gpr_latch)); + LOG("ES5510: Host Write GPR latch[2] = %02x -> %06x (%d)\n", data, gpr_latch, util::sext(gpr_latch, 24)); break; case 0x01: gpr_latch = (gpr_latch&0xff00ff) | ((data&0xff)<< 8); - LOG("ES5510: Host Write GPR latch[1] = %02x -> %06x (%d)\n", data, gpr_latch, SX(gpr_latch)); + LOG("ES5510: Host Write GPR latch[1] = %02x -> %06x (%d)\n", data, gpr_latch, util::sext(gpr_latch, 24)); break; case 0x02: gpr_latch = (gpr_latch&0xffff00) | ((data&0xff)<< 0); - LOG("ES5510: Host Write GPR latch[0] = %02x -> %06x (%d)\n", data, gpr_latch, SX(gpr_latch)); + LOG("ES5510: Host Write GPR latch[0] = %02x -> %06x (%d)\n", data, gpr_latch, util::sext(gpr_latch, 24)); break; /* 0x03 to 0x08 INSTR Register */ - case 0x03: instr_latch = ((instr_latch&0x00ffffffffffU) | (int64_t(data)&0xff)<<40); LOG("%s",string_format("ES5510: Host Write INSTR latch[5] = %02x -> %012x\n", data, instr_latch).c_str()); break; - case 0x04: instr_latch = ((instr_latch&0xff00ffffffffU) | (int64_t(data)&0xff)<<32); LOG("%s",string_format("ES5510: Host Write INSTR latch[4] = %02x -> %012x\n", data, instr_latch).c_str()); break; - case 0x05: instr_latch = ((instr_latch&0xffff00ffffffU) | (int64_t(data)&0xff)<<24); LOG("%s",string_format("ES5510: Host Write INSTR latch[3] = %02x -> %012x\n", data, instr_latch).c_str()); break; - case 0x06: instr_latch = ((instr_latch&0xffffff00ffffU) | (int64_t(data)&0xff)<<16); LOG("%s",string_format("ES5510: Host Write INSTR latch[2] = %02x -> %012x\n", data, instr_latch).c_str()); break; - case 0x07: instr_latch = ((instr_latch&0xffffffff00ffU) | (int64_t(data)&0xff)<< 8); LOG("%s",string_format("ES5510: Host Write INSTR latch[1] = %02x -> %012x\n", data, instr_latch).c_str()); break; - case 0x08: instr_latch = ((instr_latch&0xffffffffff00U) | (int64_t(data)&0xff)<< 0); LOG("%s",string_format("ES5510: Host Write INSTR latch[0] = %02x -> %012x\n", data, instr_latch).c_str()); break; + case 0x03: instr_latch = ((instr_latch & 0x00ffffffffffULL) | (int64_t(data)&0xff)<<40); LOG("%s",string_format("ES5510: Host Write INSTR latch[5] = %02x -> %012x\n", data, instr_latch).c_str()); break; + case 0x04: instr_latch = ((instr_latch & 0xff00ffffffffULL) | (int64_t(data)&0xff)<<32); LOG("%s",string_format("ES5510: Host Write INSTR latch[4] = %02x -> %012x\n", data, instr_latch).c_str()); break; + case 0x05: instr_latch = ((instr_latch & 0xffff00ffffffULL) | (int64_t(data)&0xff)<<24); LOG("%s",string_format("ES5510: Host Write INSTR latch[3] = %02x -> %012x\n", data, instr_latch).c_str()); break; + case 0x06: instr_latch = ((instr_latch & 0xffffff00ffffULL) | (int64_t(data)&0xff)<<16); LOG("%s",string_format("ES5510: Host Write INSTR latch[2] = %02x -> %012x\n", data, instr_latch).c_str()); break; + case 0x07: instr_latch = ((instr_latch & 0xffffffff00ffULL) | (int64_t(data)&0xff)<< 8); LOG("%s",string_format("ES5510: Host Write INSTR latch[1] = %02x -> %012x\n", data, instr_latch).c_str()); break; + case 0x08: instr_latch = ((instr_latch & 0xffffffffff00ULL) | (int64_t(data)&0xff)<< 0); LOG("%s",string_format("ES5510: Host Write INSTR latch[0] = %02x -> %012x\n", data, instr_latch).c_str()); break; /* 0x09 to 0x0b DIL Register (r/o) */ - case 0x0c: dol_latch = (dol_latch&0x00ffff) | ((data&0xff)<<16); LOG("ES5510: Host Write DOL latch[2] = %02x -> %06x (%d)\n", data, dol_latch, SX(dol_latch)); break; - case 0x0d: dol_latch = (dol_latch&0xff00ff) | ((data&0xff)<< 8); LOG("ES5510: Host Write DOL latch[1] = %02x -> %06x (%d)\n", data, dol_latch, SX(dol_latch)); break; - case 0x0e: dol_latch = (dol_latch&0xffff00) | ((data&0xff)<< 0); LOG("ES5510: Host Write DOL latch[0] = %02x -> %06x (%d)\n", data, dol_latch, SX(dol_latch)); break; //TODO: docs says that this always returns 0xff + case 0x0c: + dol_latch = (dol_latch&0x00ffff) | ((data&0xff)<<16); + LOG("ES5510: Host Write DOL latch[2] = %02x -> %06x (%d)\n", data, dol_latch, util::sext(dol_latch, 24)); + break; + case 0x0d: + dol_latch = (dol_latch&0xff00ff) | ((data&0xff)<< 8); + LOG("ES5510: Host Write DOL latch[1] = %02x -> %06x (%d)\n", data, dol_latch, util::sext(dol_latch, 24)); + break; + case 0x0e: + dol_latch = (dol_latch&0xffff00) | ((data&0xff)<< 0); + LOG("ES5510: Host Write DOL latch[0] = %02x -> %06x (%d)\n", data, dol_latch, util::sext(dol_latch, 24)); + break; //TODO: docs says that this always returns 0xff case 0x0f: dadr_latch = (dadr_latch&0x00ffff) | ((data&0xff)<<16); @@ -451,6 +432,20 @@ WRITE8_MEMBER(es5510_device::host_w) case 0x11: dadr_latch = (dadr_latch&0xffff00) | ((data&0xff)<< 0); break; /* 0x12 Host Control */ + case 0x12: + host_control = (host_control & 0x4) | (data & 0x3); + if (BIT(host_control, 1)) // RAM clear + { + // TODO: Timing, MEMSIZ and DLENGTH behavior + if (state == STATE_HALTED) // only in halted + { + for (int i = 0; i < DRAM_SIZE; i++) + dram[i] = 0; + } + host_control &= ~0x2; + } + // bit 0 is RAM refresh disable flag + break; case 0x14: ram_sel = data & 0x80; /* bit 6 is i/o select, everything else is undefined */break; @@ -465,10 +460,11 @@ WRITE8_MEMBER(es5510_device::host_w) data & 0x10 ? "Out" : "In", data & 0x08 ? "Out" : "In", data & 0x04 ? "Out" : "In"); + host_serial = data; break; /* 0x1f Halt enable (w) / Frame Counter (r) */ - case 0x1F: + case 0x1f: LOG("ES5510: Host Write Halt Enable %02x; HALT line is %d\n", data, halt_asserted); if (halt_asserted) { LOG("ES5510: Host Write to Halt Enable while HALT line is asserted: Halting!\n"); @@ -477,7 +473,7 @@ WRITE8_MEMBER(es5510_device::host_w) break; case 0x80: /* Read select - GPR + INSTR */ - LOG("%s",string_format("ES5510: Host Read INSTR+GPR %02x (%s): %012x %06x (%d)\n", data, REGNAME(data & 0xff), instr[data] & 0xffffffffffffU, gpr[data] & 0xffffff, gpr[data]).c_str()); + LOG("%s",string_format("ES5510: Host Read INSTR+GPR %02x (%s): %012x %06x (%d)\n", data, REGNAME(data & 0xff), instr[data] & 0xffffffffffffULL, gpr[data] & 0xffffff, gpr[data]).c_str()); /* Check if an INSTR address is selected */ if (data < 0xa0) { @@ -491,24 +487,24 @@ WRITE8_MEMBER(es5510_device::host_w) break; case 0xa0: /* Write select - GPR */ - LOG("ES5510: Host Write GPR %02x (%s): %06x (%d)\n", data, REGNAME(data&0xff), gpr_latch, SX(gpr_latch)); + LOG("ES5510: Host Write GPR %02x (%s): %06x (%d)\n", data, REGNAME(data&0xff), gpr_latch, util::sext(gpr_latch, 24)); write_reg(data, gpr_latch); break; case 0xc0: /* Write select - INSTR */ #if VERBOSE DESCRIBE_INSTR(buf, instr_latch, gpr[data], nullptr, nullptr, nullptr, nullptr); - LOG("%s",string_format("ES5510: Host Write INSTR %02x %012x: %s\n", data, instr_latch&0xffffffffffffU, buf).c_str()); + LOG("%s",string_format("ES5510: Host Write INSTR %02x %012x: %s\n", data, instr_latch & 0xffffffffffffULL, buf).c_str()); #endif if (data < 0xa0) { - instr[data] = instr_latch&0xffffffffffffU; + instr[data] = instr_latch & 0xffffffffffffULL; } break; case 0xe0: /* Write select - GPR + INSTR */ #if VERBOSE DESCRIBE_INSTR(buf, instr_latch, gpr_latch, nullptr, nullptr, nullptr, nullptr); - LOG("%s",string_format("ES5510: Host Write INSTR+GPR %02x (%s): %012x %06x (%d): %s\n", data, REGNAME(data&0xff), instr_latch, gpr_latch, SX(gpr_latch), buf).c_str()); + LOG("%s",string_format("ES5510: Host Write INSTR+GPR %02x (%s): %012x %06x (%d): %s\n", data, REGNAME(data&0xff), instr_latch, gpr_latch, util::sext(gpr_latch, 24), buf).c_str()); #endif if (data < 0xa0) { instr[data] = instr_latch; @@ -597,6 +593,7 @@ void es5510_device::device_start() { save_item(NAME(instr_latch)); save_item(NAME(ram_sel)); save_item(NAME(host_control)); + save_item(NAME(host_serial)); save_item(NAME(alu.aReg)); save_item(NAME(alu.bReg)); @@ -635,7 +632,8 @@ void es5510_device::device_reset() { dil_latch = dol_latch = dadr_latch = gpr_latch = 0; instr_latch = uint64_t(0); ram_sel = 0; - host_control = 0; + host_control = 0x04; // Signal Host Access not OK + host_serial = 0; memset(&ram, 0, sizeof(ram_t)); memset(&ram_p, 0, sizeof(ram_t)); memset(&ram_pp, 0, sizeof(ram_t)); @@ -643,27 +641,22 @@ void es5510_device::device_reset() { device_memory_interface::space_config_vector es5510_device::memory_space_config() const { - return space_config_vector { - }; + return space_config_vector { }; } -uint64_t es5510_device::execute_clocks_to_cycles(uint64_t clocks) const { +uint64_t es5510_device::execute_clocks_to_cycles(uint64_t clocks) const noexcept { return clocks / 3; } -uint64_t es5510_device::execute_cycles_to_clocks(uint64_t cycles) const { +uint64_t es5510_device::execute_cycles_to_clocks(uint64_t cycles) const noexcept { return cycles * 3; } -uint32_t es5510_device::execute_min_cycles() const { - return 1; -} - -uint32_t es5510_device::execute_max_cycles() const { +uint32_t es5510_device::execute_min_cycles() const noexcept { return 1; } -uint32_t es5510_device::execute_input_lines() const { +uint32_t es5510_device::execute_max_cycles() const noexcept { return 1; } @@ -749,10 +742,10 @@ void es5510_device::list_program(void(p)(const char *, ...)) { uint8_t cReg = (uint8_t)((instr[addr] >> 32) & 0xff); uint8_t dReg = (uint8_t)((instr[addr] >> 40) & 0xff); DESCRIBE_INSTR(buf, instr[addr], gpr[addr], name[aReg], name[bReg], name[cReg], name[dReg]); - p("%s",string_format("%02x: %012x %06x (%8d) %s\n", addr, instr[addr], gpr[addr]&0xffffff, SX(gpr[addr]&0xffffff), buf).c_str()); + p("%s",string_format("%02x: %012x %06x (%8d) %s\n", addr, instr[addr], gpr[addr]&0xffffff, util::sext(gpr[addr], 24), buf).c_str()); } for (; addr < 0xc0; addr++) { - p("%02x: %06x (%d)\n", addr, gpr[addr]&0xffffff, SX(gpr[addr]&0xffffff)); + p("%02x: %06x (%d)\n", addr, gpr[addr]&0xffffff, util::sext(gpr[addr], 24)); } } @@ -762,26 +755,27 @@ void es5510_device::execute_run() { // Currently halted, sample the HALT line if (halt_asserted) { // remain halted - host_control |= 0x04; // Signal Host Access OK + host_control &= ~0x04; // Signal Host Access OK } else { // start from the beginning at PC 0 state = STATE_RUNNING; - host_control &= ~0x04; // Signal Host Access not OK + host_control |= 0x04; // Signal Host Access not OK pc = 0; } } else { // currently running, execute one instruction. -#if VERBOSE_EXEC - char buf[1024]; - DESCRIBE_INSTR(buf, instr[pc], gpr[pc], nullptr, nullptr, nullptr, nullptr); - LOG_EXEC(("%s",string_format("EXECUTING %02x: %012x %06x %s\n", pc, instr[pc], gpr[pc]&0xffffff, buf).c_str())); -#endif + if (VERBOSE & LOG_EXECUTION) + { + char buf[1024]; + DESCRIBE_INSTR(buf, instr[pc], gpr[pc], nullptr, nullptr, nullptr, nullptr); + LOG_EXEC("EXECUTING %02x: %012x %06x %s\n", pc, instr[pc], gpr[pc]&0xffffff, buf); + } ram_pp = ram_p; ram_p = ram; - LOG_EXEC(("- T0\n")); + LOG_EXEC("- T0\n"); // *** T0, clock high // --- nothing to do! @@ -793,10 +787,10 @@ void es5510_device::execute_run() { // --- RAM cycle N-2 (if a Read cycle): data read from bus is stored in DIL if (ram_pp.cycle != RAM_CYCLE_WRITE) { if (ram_pp.io) { // read from I/O and store into DIL - dil = 0; // read_io(ram_pp.address);; + dil = 0; // read_io(ram_pp.address); } else { // read from DRAM and store into DIL dil = dram_r(ram_pp.address) << 8; - LOG_EXEC((" . RAM: read %x (%d) from address %x\n", dil, dil, ram_pp.address)); + LOG_EXEC(" . RAM: read %x (%d) from address %x\n", dil, dil, ram_pp.address); } } @@ -810,19 +804,19 @@ void es5510_device::execute_run() { switch(ramControl.access) { case RAM_CONTROL_DELAY: ram.address = (((dbase + offset) % (dlength + memincrement)) & memmask) >> memshift; - LOG_EXEC((". Ram Control: Delay, base=%x, offset=%x, length=%x => address=%x\n", dbase >> memshift, offset >> memshift, (dlength + memincrement) >> memshift, ram.address)); + LOG_EXEC(". Ram Control: Delay, base=%x, offset=%x, length=%x => address=%x\n", dbase >> memshift, offset >> memshift, (dlength + memincrement) >> memshift, ram.address); break; case RAM_CONTROL_TABLE_A: ram.address = ((abase + offset) & memmask) >> memshift; - LOG_EXEC((". Ram Control: table A = %x, offset=%x => address=%x\n", abase >> memshift, offset >> memshift, ram.address)); + LOG_EXEC(". Ram Control: table A = %x, offset=%x => address=%x\n", abase >> memshift, offset >> memshift, ram.address); break; case RAM_CONTROL_TABLE_B: ram.address = ((bbase + offset) & memmask) >> memshift; - LOG_EXEC((". Ram Control: table B = %x, offset=%x => address=%x\n", bbase >> memshift, offset >> memshift, ram.address)); + LOG_EXEC(". Ram Control: table B = %x, offset=%x => address=%x\n", bbase >> memshift, offset >> memshift, ram.address); break; case RAM_CONTROL_IO: ram.address = offset & 0x00fffff0; // mask off the low 4 bits - LOG_EXEC((". Ram Control: I/O at address=%x\n", ram.address)); + LOG_EXEC(". Ram Control: I/O at address=%x\n", ram.address); break; } @@ -830,7 +824,7 @@ void es5510_device::execute_run() { // --- Decode instruction N; // we will do this both here and in stages as the different parts of the instruction complete & recommence. - LOG_EXEC(("- T1.1\n")); + LOG_EXEC("- T1.1\n"); uint8_t operandSelect = (uint8_t)((instr >> 8) & 0x0f); const op_select_t &opSelect = OPERAND_SELECT[operandSelect]; @@ -842,40 +836,38 @@ void es5510_device::execute_run() { skipConditionSatisfied = !skipConditionSatisfied; } skip = skipConditionSatisfied; - LOG_EXEC((". skippable: %x vs %x => skippable = %d\n", ccr, cmr, skip)); + LOG_EXEC(". skippable: %x vs %x => skippable = %d\n", ccr, cmr, skip); } else { skip = false; } // --- Write Multiplier result N-1 - LOG_EXEC((". write mulacc:\n")); + LOG_EXEC(". write mulacc:\n"); if (mulacc.write_result) { - mulacc.product = ((int64_t)SX(mulacc.cValue) * (int64_t)SX(mulacc.dValue)) << mulshift; + mulacc.product = mul_32x32(util::sext(mulacc.cValue, 24), util::sext(mulacc.dValue, 24)) << mulshift; if (mulacc.accumulate) { mulacc.result = mulacc.product + machl; } else { mulacc.result = mulacc.product; } - if (mulacc.result < MIN_48 || mulacc.result > MAX_48) { + if (mulacc.result < -(s64(1) << 47) || mulacc.result >= (s64(1) << 47)) { mac_overflow = true; } else { mac_overflow = false; } -#if VERBOSE_EXEC if (mulacc.cValue || mulacc.dValue || (mulacc.accumulate && machl)) { - LOG_EXEC((". mulacc: %x (%d) * %x (%d) << %d", SX(mulacc.cValue), SX(mulacc.cValue), SX(mulacc.dValue), SX(mulacc.dValue), mulshift)); - if (mulacc.accumulate) LOG_EXEC((" + %llx (%lld) ", machl, machl)); - LOG_EXEC((" = %llx (%lld)", mulacc.result, mulacc.result)); + LOG_EXEC(". mulacc: %x (%d) * %x (%d) << %d", (mulacc.cValue & 0x00ffffff), util::sext(mulacc.cValue, 24), (mulacc.dValue & 0x00ffffff), util::sext(mulacc.dValue, 24), mulshift); + if (mulacc.accumulate) LOG_EXEC(" + %llx (%lld) ", machl, machl); + LOG_EXEC(" = %llx (%lld)", mulacc.result, mulacc.result); if (mac_overflow) { - LOG_EXEC((" overflow!\n")); + LOG_EXEC(" overflow!\n"); } else { - LOG_EXEC(("\n")); + LOG_EXEC("\n"); } } -#endif machl = mulacc.result; - int32_t tmp = mac_overflow ? (machl < 0 ? MIN_24 : MAX_24) : (mulacc.result & 0x0000ffffff000000U) >> 24; + int32_t tmp = mac_overflow ? (machl < 0 ? 0x00800000 : 0x007fffff) : (mulacc.result & 0x0000ffffff000000ULL) >> 24; if (mulacc.dst & SRC_DST_REG) { write_reg(mulacc.cReg, tmp); } @@ -886,10 +878,10 @@ void es5510_device::execute_run() { // *** T1, clock low - LOG_EXEC(("- T1.0\n")); + LOG_EXEC("- T1.0\n"); // --- Start of multiplier cycle N - LOG_EXEC((". start mulacc:\n")); + LOG_EXEC(". start mulacc:\n"); mulacc.cReg = (uint8_t)((instr >> 32) & 0xff); mulacc.dReg = (uint8_t)((instr >> 40) & 0xff); mulacc.src = opSelect.mac_src; @@ -901,17 +893,17 @@ void es5510_device::execute_run() { if (mulacc.src == SRC_DST_REG) { mulacc.cValue = read_reg(mulacc.cReg); } else { // must be SRC_DST_DELAY - LOG_EXEC((" . reading %x (%d) from dil\n", dil, SX(dil))); + LOG_EXEC(" . reading %x (%d) from dil\n", dil, util::sext(dil, 24)); mulacc.cValue = dil; } mulacc.dValue = read_reg(mulacc.dReg); // *** T2, clock high - LOG_EXEC(("- T2.1\n")); + LOG_EXEC("- T2.1\n"); // --- Write ALU Result N-1 - LOG_EXEC((". write ALU:\n")); + LOG_EXEC(". write ALU:\n"); if (alu.write_result) { uint8_t flags = ccr; alu.result = alu_operation(alu.op, alu.aValue, alu.bValue, flags); @@ -928,10 +920,10 @@ void es5510_device::execute_run() { // *** T2, clock low - LOG_EXEC(("- T2.0\n")); + LOG_EXEC("- T2.0\n"); // --- Start of ALU cycle N - LOG_EXEC((". start ALU:\n")); + LOG_EXEC(". start ALU:\n"); alu.aReg = (instr >> 16) & 0xff; alu.bReg = (instr >> 24) & 0xff; alu.op = (instr >> 12) & 0x0f; @@ -940,7 +932,7 @@ void es5510_device::execute_run() { alu.write_result = !skip; alu.update_ccr = !skippable || (alu.op == OP_CMP); - if (alu.op == 0xF) { + if (alu.op == 0xf) { alu_operation_end(); } else { // --- Read ALU Operands N @@ -969,25 +961,23 @@ void es5510_device::execute_run() { // write_io(ram_p.io, dol[0]); } else { dram_w(ram_p.address, dol[0] >> 8); - LOG_EXEC((" . RAM: writing %x (%d) [of %x (%d)] to address %x\n", dol[0]&0xffff00, SX(dol[0]&0xffff00), dol[0], SX(dol[0]), ram_p.address)); + LOG_EXEC(" . RAM: writing %x (%d) [of %x (%d)] to address %x\n", dol[0]&0xffff00, util::sext(dol[0] & 0xffff00, 24), dol[0], util::sext(dol[0], 24), ram_p.address); } } // If this is a Write or Dump cycle, eject the frontmost DL value. -#if VERBOSE_EXEC - LOG_EXEC((" . ejecting from DOL: [ ")); - if (dol_count >= 1) LOG_EXEC(("{ %x (%d) }", dol[0], SX(dol[0]))); - if (dol_count == 2) LOG_EXEC((", { %x (%d) }", dol[1], SX(dol[1]))); - LOG_EXEC((" ] -> [ ")); -#endif + LOG_EXEC(" . ejecting from DOL: [ "); + if (dol_count >= 1) LOG_EXEC("{ %x (%d) }", dol[0], util::sext(dol[0], 24)); + if (dol_count == 2) LOG_EXEC(", { %x (%d) }", dol[1], util::sext(dol[1], 24)); + LOG_EXEC(" ] -> [ "); + dol[0] = dol[1]; if (dol_count > 0) { --dol_count; } -#if VERBOSE_EXEC - if (dol_count >= 1) LOG_EXEC(("{ %x (%d) }", dol[0], SX(dol[0]))); - if (dol_count == 2) LOG_EXEC((", { %x (%d) }", dol[1], SX(dol[1]))); - LOG_EXEC((" ]\n")); -#endif + + if (dol_count >= 1) LOG_EXEC("{ %x (%d) }", dol[0], util::sext(dol[0], 24)); + if (dol_count == 2) LOG_EXEC(", { %x (%d) }", dol[1], util::sext(dol[1], 24)); + LOG_EXEC(" ]\n"); } ++pc; @@ -1002,9 +992,9 @@ std::unique_ptr<util::disasm_interface> es5510_device::create_disassembler() } #if VERBOSE_EXEC -#define RETURN_GPR(r, x) do { int32_t v = (x); LOG_EXEC((" . reading %x (%d) from gpr_%02x\n", v, SX(v), r)); return v; } while(0) -#define RETURN(r, x) do { int32_t v = (x); LOG_EXEC((" . reading %x (%d) from " #r "\n", v, SX(v))); return v; } while(0) -#define RETURN16(r, x) do { int16_t vv = (x); int32_t v = vv << 8; LOG_EXEC((" . reading %x (%d) as %x (%d) from " #r "\n", vv, vv, v, SX(v))); return v; } while(0) +#define RETURN_GPR(r, x) do { int32_t v = (x); LOG_EXEC(" . reading %x (%d) from gpr_%02x\n", v, util::sext(v, 24), r); return v; } while(0) +#define RETURN(r, x) do { int32_t v = (x); LOG_EXEC(" . reading %x (%d) from " #r "\n", v, util::sext(v, 24)); return v; } while(0) +#define RETURN16(r, x) do { int16_t vv = (x); int32_t v = vv << 8; LOG_EXEC(" . reading %x (%d) as %x (%d) from " #r "\n", vv, vv, v, util::sext(v, 24)); return v; } while(0) #else #define RETURN_GPR(r, x) return x #define RETURN(r, x) return x @@ -1026,8 +1016,8 @@ int32_t es5510_device::read_reg(uint8_t reg) case 239: RETURN16(ser2l, ser2l); case 240: RETURN16(ser3r, ser3r); case 241: RETURN16(ser3l, ser3l); - case 242: /* macl */ RETURN(macl, mac_overflow ? (machl < 0 ? 0x00ffffff : 0x00000000) : (machl >> 0) & 0x00ffffff); - case 243: /* mach */ RETURN(mach, mac_overflow ? (machl < 0 ? MIN_24 : MAX_24) : (machl >> 24) & 0x00ffffff); + case 242: RETURN(macl, mac_overflow ? (machl < 0 ? 0x00000000 : 0x00ffffff) : (machl >> 0) & 0x00ffffff); + case 243: RETURN(mach, mac_overflow ? (machl < 0 ? 0x00800000 : 0x007fffff) : (machl >> 24) & 0x00ffffff); case 244: RETURN(dil, dil); // DIL when reading case 245: RETURN(dlength, dlength); case 246: RETURN(abase, abase); @@ -1037,8 +1027,8 @@ int32_t es5510_device::read_reg(uint8_t reg) case 250: RETURN(ccr, ccr); case 251: RETURN(cmr, cmr); case 252: RETURN(minus_one, 0x00ffffff); - case 253: RETURN(min, MIN_24); - case 254: RETURN(max, MAX_24); + case 253: RETURN(min, 0x00800000); + case 254: RETURN(max, 0x007fffff); case 255: RETURN(zero, 0); default: // unknown SPR @@ -1076,8 +1066,8 @@ int8_t countLowOnes(int32_t x) { } #if VERBOSE_EXEC -#define WRITE_REG(r, x) do { r = value; LOG_EXEC((" . writing %x (%d) to " #r "\n", r, SX(r))); } while(0) -#define WRITE_REG16(r, x) do { r = ((value >> 8) & 0xffff); LOG_EXEC((" . writing %x (%d) as %x (%d) to " #r "\n", value, SX(value), r, r)); } while(0) +#define WRITE_REG(r, x) do { r = value; LOG_EXEC(" . writing %x (%d) to " #r "\n", r, util::sext(r, 24)); } while(0) +#define WRITE_REG16(r, x) do { r = ((value >> 8) & 0xffff); LOG_EXEC(" . writing %x (%d) as %x (%d) to " #r "\n", value, util::sext(value, 24), r, r); } while(0) #else #define WRITE_REG(r, x) do { r = value; } while(0) #define WRITE_REG16(r, x) do { r = ((value >> 8) & 0xffff); } while(0) @@ -1085,12 +1075,10 @@ int8_t countLowOnes(int32_t x) { void es5510_device::write_reg(uint8_t reg, int32_t value) { - #if VERBOSE_EXEC int64_t old; - #endif value &= 0x00ffffff; if (reg < 0xc0) { - LOG_EXEC((" . writing %x (%d) to gpr_%02x\n", value, SX(value), reg)); + LOG_EXEC(" . writing %x (%d) to gpr_%02x\n", value, util::sext(value, 24), reg); gpr[reg] = value; } else { switch(reg) @@ -1112,28 +1100,20 @@ void es5510_device::write_reg(uint8_t reg, int32_t value) case 241: WRITE_REG16(ser3l, value); break; case 242: /* macl */ { - #if VERBOSE_EXEC old = machl; - #endif int64_t masked = machl & (s64(0x00ffffffU) << 24); int64_t shifted = (int64_t)(value & 0x00ffffff) << 0; - machl = SX64(masked | shifted); - #if VERBOSE_EXEC - LOG_EXEC((" . writing machl: l -> %06x => %llx -> %llx\n", value, old, machl)); - #endif + machl = util::sext(masked | shifted, 48); + LOG_EXEC(" . writing machl: l -> %06x => %llx -> %llx\n", value, old, machl); break; } case 243: /* mach */ { - #if VERBOSE_EXEC old = machl; - #endif int64_t masked = machl & (s64(0x00ffffffU) << 0); int64_t shifted = (int64_t)(value & 0x00ffffff) << 24; - machl = SX64(masked | shifted); + machl = util::sext(masked | shifted, 48); mac_overflow = false; - #if VERBOSE_EXEC - LOG_EXEC((" . writing machl: h -> %06x => %llx -> %llx\n", value, old, machl)); - #endif + LOG_EXEC(" . writing machl: h -> %06x => %llx -> %llx\n", value, old, machl); break; } case 244: /* MEMSIZ when writing */ @@ -1141,7 +1121,7 @@ void es5510_device::write_reg(uint8_t reg, int32_t value) memsiz = 0x00ffffff >> (24 - memshift); memmask = 0x00ffffff & ~memsiz; memincrement = 1 << memshift; - LOG_EXEC((" . writing %x (%d) to memsiz => memsiz=%x, shift=%d, mask=%x, increment=%x\n", value, SX(value), memsiz, memshift, memmask, memincrement)); + LOG_EXEC(" . writing %x (%d) to memsiz => memsiz=%x, shift=%d, mask=%x, increment=%x\n", value, util::sext(value, 24), memsiz, memshift, memmask, memincrement); break; case 245: WRITE_REG(dlength, value); break; @@ -1157,13 +1137,13 @@ void es5510_device::write_reg(uint8_t reg, int32_t value) break; case 251: WRITE_REG(cmr, (value >> 16) & (FLAG_MASK | FLAG_NOT)); break; - case 252: LOG_EXEC((". not writing %x (%d) to minus_one\n", value, SX(value))); // no-op + case 252: LOG_EXEC(". not writing %x (%d) to minus_one\n", value, util::sext(value, 24)); // no-op break; - case 253: LOG_EXEC((". not writing %x (%d) to min\n", value, SX(value))); // no-op + case 253: LOG_EXEC(". not writing %x (%d) to min\n", value, util::sext(value, 24)); // no-op break; - case 254: LOG_EXEC((". not writing %x (%d) to max\n", value, SX(value))); // no-op + case 254: LOG_EXEC(". not writing %x (%d) to max\n", value, util::sext(value, 24)); // no-op break; - case 255: LOG_EXEC((". not writing %x (%d) to zero\n", value, SX(value))); // no-op + case 255: LOG_EXEC(". not writing %x (%d) to zero\n", value, util::sext(value, 24)); // no-op break; default: // unknown register break; @@ -1172,33 +1152,31 @@ void es5510_device::write_reg(uint8_t reg, int32_t value) } void es5510_device::write_to_dol(int32_t value) { -#if VERBOSE_EXEC - LOG_EXEC((". writing %x (%d) to DOL: [ ", value, value)); - if (dol_count >= 1) LOG_EXEC(("{ %x (%d) }", dol[0], SX(dol[0]))); - if (dol_count == 2) LOG_EXEC((", { %x (%d) }", dol[1], SX(dol[1]))); - LOG_EXEC((" ] -> [ ")); -#endif + LOG_EXEC(". writing %x (%d) to DOL: [ ", value, value); + if (dol_count >= 1) LOG_EXEC("{ %x (%d) }", dol[0], util::sext(dol[0], 24)); + if (dol_count == 2) LOG_EXEC(", { %x (%d) }", dol[1], util::sext(dol[1], 24)); + LOG_EXEC(" ] -> [ "); + if (dol_count >= 2) { dol[0] = dol[1]; dol[1] = value; } else { dol[dol_count++] = value; } -#if VERBOSE_EXEC - LOG_EXEC(("{%x (%d)}", dol[0], SX(dol[0]))); - if (dol_count == 2) LOG_EXEC((", {%x (%d)}", dol[1], SX(dol[1]))); - LOG_EXEC((" ]\n")); -#endif + + LOG_EXEC("{%x (%d)}", dol[0], util::sext(dol[0], 24)); + if (dol_count == 2) LOG_EXEC(", {%x (%d)}", dol[1], util::sext(dol[1], 24)); + LOG_EXEC(" ]\n"); } void es5510_device::alu_operation_end() { // Handle the END instruction separately - LOG_EXEC(("ES5510: END\n")); + LOG_EXEC("ES5510: END\n"); // sample the HALT line if (halt_asserted) { // halt state = STATE_HALTED; - host_control |= 0x04; // Signal Host Access OK + host_control &= ~0x04; // Signal Host Access OK } // update the delay line base pointer dbase -= memincrement; @@ -1240,27 +1218,27 @@ int32_t es5510_device::alu_operation(uint8_t op, int32_t a, int32_t b, uint8_t & case 0x5: // AND a &= b; - setFlagTo(flags, FLAG_N, (a & 0x0080000000) != 0); - setFlagTo(flags, FLAG_Z, a == 0); + flags = setFlagTo(flags, FLAG_N, (a & 0x00800000) != 0); + flags = setFlagTo(flags, FLAG_Z, a == 0); return a; case 0x6: // OR a |= b; - setFlagTo(flags, FLAG_N, (a & 0x0080000000) != 0); - setFlagTo(flags, FLAG_Z, a == 0); + flags = setFlagTo(flags, FLAG_N, (a & 0x00800000) != 0); + flags = setFlagTo(flags, FLAG_Z, a == 0); return a; case 0x7: // XOR a ^= b; - setFlagTo(flags, FLAG_N, (a & 0x0080000000) != 0); - setFlagTo(flags, FLAG_Z, a == 0); + flags = setFlagTo(flags, FLAG_N, (a & 0x00800000) != 0); + flags = setFlagTo(flags, FLAG_Z, a == 0); return a; case 0x8: // ABS { - clearFlag(flags, FLAG_N); + flags = clearFlag(flags, FLAG_N); bool isNegative = (a & 0x00800000) != 0; - setFlagTo(flags, FLAG_C, isNegative); + flags = setFlagTo(flags, FLAG_C, isNegative); // Note: the absolute value is calculated by one's complement! return isNegative ? (0x00ffffff ^ a) : a; } @@ -1268,22 +1246,26 @@ int32_t es5510_device::alu_operation(uint8_t op, int32_t a, int32_t b, uint8_t & case 0x9: // MOV return b; - case 0xA: // ASL2 + case 0xa: // ASL2 return asl(b, 2, flags); - case 0xB: // ASL8 + case 0xb: // ASL8 return asl(b, 8, flags); - case 0xC: // LS15 + case 0xc: // LS15 + flags = clearFlag(flags, FLAG_N); + flags = setFlagTo(flags, FLAG_C, (b & 0x00800000) != 0); return (b << 15) & 0x007fffff; - case 0xD: // DIFF + case 0xd: // DIFF return add(0x007fffff, negate(b), flags); - case 0xE: // ASR + case 0xe: // ASR + flags = setFlagTo(flags, FLAG_N, (b & 0x00800000) != 0); + flags = setFlagTo(flags, FLAG_C, (b & 1) != 0); return (b >> 1) | (b & 0x00800000); - case 0xF: // END - handled separately in alu_operation_end() + case 0xf: // END - handled separately in alu_operation_end() default: return 0; } |