summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/es5510/es5510.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/es5510/es5510.cpp')
-rw-r--r--src/devices/cpu/es5510/es5510.cpp364
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;
}