mirror of
https://github.com/holub/mame
synced 2025-06-14 16:37:00 +03:00
es5510: improved debug capabilities, better disassembly, bugfixed many opcodes. Most effects programs now produce correct results. [Christian Brunschen]
This commit is contained in:
parent
e318ca7149
commit
b8f66ce559
@ -14,11 +14,27 @@
|
||||
#define VERBOSE 0
|
||||
|
||||
#if VERBOSE
|
||||
#define LOG(x) do { logerror x; } while(0)
|
||||
void log_to_stderr(const char *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#define LOG(x) do { log_to_stderr x; } while(0)
|
||||
#else
|
||||
#define LOG(x)
|
||||
#endif
|
||||
|
||||
#define VERBOSE_EXEC 0
|
||||
|
||||
#if VERBOSE_EXEC
|
||||
static int exec_cc = 0;
|
||||
#define LOG_EXEC(x) do { if (!exec_cc) LOG(x); } while(0)
|
||||
#else
|
||||
#define LOG_EXEC(x)
|
||||
#endif
|
||||
|
||||
const device_type ES5510 = &device_creator<es5510_device>;
|
||||
|
||||
#define FLAG_N (1 << 7)
|
||||
@ -54,7 +70,7 @@ inline static bool isFlagSet(UINT8 ccr, UINT8 flag) {
|
||||
|
||||
inline static INT32 add(INT32 a, INT32 b, UINT8 &flags) {
|
||||
INT32 aSign = a & 0x00800000;
|
||||
INT32 bSign = (b & 0x00800000) == 0;
|
||||
INT32 bSign = b & 0x00800000;
|
||||
INT32 result = a + b;
|
||||
INT32 resultSign = result & 0x00800000;
|
||||
bool overflow = (aSign == bSign) && (aSign != resultSign);
|
||||
@ -90,7 +106,6 @@ inline static INT32 asl(INT32 value, int shift, UINT8 &flags) {
|
||||
return saturate(result, flags);
|
||||
}
|
||||
|
||||
|
||||
es5510_device::es5510_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: cpu_device(mconfig, ES5510, "ES5510", tag, owner, clock, "es5510", __FILE__)
|
||||
{
|
||||
@ -135,7 +150,8 @@ es5510_device::es5510_device(const machine_config &mconfig, const char *tag, dev
|
||||
instr_latch = 0;
|
||||
ram_sel = 0;
|
||||
host_control = 0;
|
||||
|
||||
|
||||
pc = 0;
|
||||
memset(&alu, 0, sizeof(alu));
|
||||
memset(&mulacc, 0, sizeof(mulacc));
|
||||
}
|
||||
@ -146,8 +162,8 @@ typedef es5510_device::op_src_dst_t op_src_dst_t;
|
||||
|
||||
static inline INT32 SX(INT32 x) { return (x & 0x00800000) ? x | 0xff000000 : x & 0x00ffffff; }
|
||||
static inline INT32 SC(INT32 x) { return x & 0x00ffffff; }
|
||||
static inline INT64 SX64(INT64 x) { return (x & U64(0x0000800000000000)) ? x | U64(0xffff000000000000) : x & U64(0x0000ffffffffffff); }
|
||||
static inline INT64 SC64(INT64 x) { return x & U64(0x0000ffffffffffff); }
|
||||
static inline INT64 SX64(INT64 x) { return (x & S64(0x0000800000000000)) ? x | S64(0xffff000000000000) : x & S64(0x0000ffffffffffff); }
|
||||
static inline INT64 SC64(INT64 x) { return x & S64(0x0000ffffffffffff); }
|
||||
|
||||
static inline const char * const REGNAME(UINT8 r) {
|
||||
static char rn[8];
|
||||
@ -179,8 +195,12 @@ static inline const char * const REGNAME(UINT8 r) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline char * DESCRIBE_REG(char *s, UINT8 r) {
|
||||
return stpcpy_int(s, REGNAME(r));
|
||||
static inline char * DESCRIBE_REG(char *s, UINT8 r, const char *name) {
|
||||
if (name) {
|
||||
return s + sprintf(s, "%s/%s", REGNAME(r), name);
|
||||
} else {
|
||||
return stpcpy_int(s, REGNAME(r));
|
||||
}
|
||||
}
|
||||
|
||||
const alu_op_t es5510_device::ALU_OPS[16] = {
|
||||
@ -224,14 +244,14 @@ const op_select_t es5510_device::OPERAND_SELECT[16] = {
|
||||
{ es5510_device::SRC_DST_DELAY, es5510_device::SRC_DST_BOTH, es5510_device::SRC_DST_DELAY, es5510_device::SRC_DST_REG },
|
||||
};
|
||||
|
||||
static inline char * DESCRIBE_SRC_DST(char *s, UINT8 reg, op_src_dst_t src_dst) {
|
||||
static inline char * DESCRIBE_SRC_DST(char *s, UINT8 reg, const char *regname, op_src_dst_t src_dst) {
|
||||
switch (src_dst) {
|
||||
case es5510_device::SRC_DST_REG:
|
||||
return DESCRIBE_REG(s, reg);
|
||||
return DESCRIBE_REG(s, reg, regname);
|
||||
case es5510_device::SRC_DST_DELAY:
|
||||
return stpcpy_int(s, "Delay");
|
||||
case es5510_device::SRC_DST_BOTH:
|
||||
s = DESCRIBE_REG(s, reg);
|
||||
s = DESCRIBE_REG(s, reg, regname);
|
||||
return stpcpy_int(s, ",Delay");
|
||||
}
|
||||
// should never happen!
|
||||
@ -245,15 +265,15 @@ const es5510_device::ram_control_t es5510_device::RAM_CONTROL[8] = {
|
||||
{ es5510_device::RAM_CYCLE_WRITE, es5510_device::RAM_CONTROL_TABLE_A, "Write Table A+%06x" },
|
||||
{ es5510_device::RAM_CYCLE_READ, es5510_device::RAM_CONTROL_TABLE_B, "Read Table B+%06x" },
|
||||
{ es5510_device::RAM_CYCLE_DUMP_FIFO, es5510_device::RAM_CONTROL_DELAY, "Read Delay+%06x and Dump FIFO" },
|
||||
{ es5510_device::RAM_CYCLE_READ, es5510_device::RAM_CONTROL_IO, "Read I/O at %06x" },
|
||||
{ es5510_device::RAM_CYCLE_WRITE, es5510_device::RAM_CONTROL_IO, "Write I/o %06x" },
|
||||
{ es5510_device::RAM_CYCLE_READ, es5510_device::RAM_CONTROL_IO, "Read from I/O at %06x" },
|
||||
{ es5510_device::RAM_CYCLE_WRITE, es5510_device::RAM_CONTROL_IO, "Write to I/O at %06x" },
|
||||
};
|
||||
|
||||
static inline char * DESCRIBE_RAM(char *s, UINT8 ramControl, UINT32 gprContents) {
|
||||
return s + sprintf(s, es5510_device::RAM_CONTROL[ramControl].description, SC(gprContents));
|
||||
}
|
||||
|
||||
static inline char * DESCRIBE_ALU(char *s, UINT8 opcode, UINT8 aReg, UINT8 bReg, const op_select_t &opSelect) {
|
||||
static inline char * DESCRIBE_ALU(char *s, UINT8 opcode, UINT8 aReg, const char *aName, UINT8 bReg, const char *bName, const op_select_t &opSelect) {
|
||||
const alu_op_t &op = es5510_device::ALU_OPS[opcode];
|
||||
|
||||
switch (op.operands) {
|
||||
@ -261,32 +281,36 @@ static inline char * DESCRIBE_ALU(char *s, UINT8 opcode, UINT8 aReg, UINT8 bReg,
|
||||
return stpcpy_int(s, op.opcode);
|
||||
|
||||
case 1:
|
||||
s += sprintf(s, "%s %s >", op.opcode, REGNAME(bReg));
|
||||
return DESCRIBE_SRC_DST(s, aReg, opSelect.alu_dst);
|
||||
s += sprintf(s, "%s ", op.opcode);
|
||||
s = DESCRIBE_SRC_DST(s, bReg, bName, opSelect.alu_src);
|
||||
s += sprintf(s, " >");
|
||||
return DESCRIBE_SRC_DST(s, aReg, aName, opSelect.alu_dst);
|
||||
|
||||
case 2:
|
||||
s += sprintf(s, "%s %s,", op.opcode, REGNAME(bReg));
|
||||
s = DESCRIBE_SRC_DST(s, aReg, opSelect.alu_src);
|
||||
s += sprintf(s, "%s ", op.opcode);
|
||||
s = DESCRIBE_REG(s, bReg, bName);
|
||||
s += sprintf(s, " ");
|
||||
s = DESCRIBE_SRC_DST(s, aReg, aName, opSelect.alu_src);
|
||||
s += sprintf(s, " >");
|
||||
return DESCRIBE_SRC_DST(s, aReg, opSelect.alu_dst);
|
||||
return DESCRIBE_SRC_DST(s, aReg, aName, opSelect.alu_dst);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline char * DESCRIBE_MAC(char *s, UINT8 mac, UINT8 cReg, UINT8 dReg, const op_select_t &opSelect)
|
||||
static inline char * DESCRIBE_MAC(char *s, UINT8 mac, UINT8 cReg, const char *cName, UINT8 dReg, const char *dName, const op_select_t &opSelect)
|
||||
{
|
||||
if (mac)
|
||||
{
|
||||
s += sprintf(s, "MAC + ");
|
||||
}
|
||||
s = DESCRIBE_REG(s, dReg);
|
||||
s = DESCRIBE_REG(s, dReg, dName);
|
||||
s += sprintf(s, " * ");
|
||||
s = DESCRIBE_SRC_DST(s, cReg, opSelect.mac_src);
|
||||
s = DESCRIBE_SRC_DST(s, cReg, cName, opSelect.mac_src);
|
||||
s += sprintf(s, " >");
|
||||
return DESCRIBE_SRC_DST(s, cReg, opSelect.mac_dst);
|
||||
return DESCRIBE_SRC_DST(s, cReg, cName, opSelect.mac_dst);
|
||||
}
|
||||
|
||||
static inline char * DESCRIBE_INSTR(char *s, UINT64 instr, UINT32 gpr)
|
||||
static inline char * DESCRIBE_INSTR(char *s, UINT64 instr, UINT32 gpr, const char *aName, const char *bName, const char *cName, const char *dName)
|
||||
{
|
||||
UINT8 dReg = (UINT8)((instr >> 40) & 0xff);
|
||||
UINT8 cReg = (UINT8)((instr >> 32) & 0xff);
|
||||
@ -300,9 +324,9 @@ static inline char * DESCRIBE_INSTR(char *s, UINT64 instr, UINT32 gpr)
|
||||
|
||||
const op_select_t &opSelect = es5510_device::OPERAND_SELECT[operandSelect];
|
||||
|
||||
s = DESCRIBE_ALU(s, aluOpcode, aReg, bReg, opSelect);
|
||||
s = DESCRIBE_ALU(s, aluOpcode, aReg, aName, bReg, bName, opSelect);
|
||||
s += sprintf(s, "; ");
|
||||
s = DESCRIBE_MAC(s, mac, cReg, dReg, opSelect);
|
||||
s = DESCRIBE_MAC(s, mac, cReg, cName, dReg, dName, opSelect);
|
||||
s += sprintf(s, "; ");
|
||||
s = DESCRIBE_RAM(s, ramControl, gpr);
|
||||
if (skip) {
|
||||
@ -341,11 +365,11 @@ READ8_MEMBER(es5510_device::host_r)
|
||||
|
||||
case 0x09: LOG(("ES5510: Host Read DIL latch[2]: %02x\n", (dil_latch >> 16) & 0xff)); return (dil_latch >> 16) & 0xff;
|
||||
case 0x0a: LOG(("ES5510: Host Read DIL latch[1]: %02x\n", (dil_latch >> 8) & 0xff)); return (dil_latch >> 8) & 0xff;
|
||||
case 0x0b: LOG(("ES5510: Host Read DIL latch[0]: %02x\n", (dil_latch >> 0) & 0xff)); return (dil_latch >> 0) & 0xff; //TODO: docs says that this always returns 0
|
||||
case 0x0b: LOG(("ES5510: Host Read DIL latch[0]: %02x\n", 0)); return 0;
|
||||
|
||||
case 0x0c: LOG(("ES5510: Host Read DOL latch[2]: %02x\n", (dol_latch >> 16) & 0xff)); return (dol_latch >> 16) & 0xff;
|
||||
case 0x0d: LOG(("ES5510: Host Read DOL latch[1]: %02x\n", (dol_latch >> 8) & 0xff)); return (dol_latch >> 8) & 0xff;
|
||||
case 0x0e: LOG(("ES5510: Host Read DOL latch[0]: %02x\n", (dol_latch >> 0) & 0xff)); return (dol_latch >> 0) & 0xff; //TODO: docs says that this always returns 0
|
||||
case 0x0e: LOG(("ES5510: Host Read DOL latch[0]: %02x\n", 0xff)); return 0xff;
|
||||
|
||||
case 0x0f: LOG(("ES5510: Host Read DADR latch[2]: %02x\n", (dadr_latch >> 16) & 0xff)); return (dadr_latch >> 16) & 0xff;
|
||||
case 0x10: LOG(("ES5510: Host Read DADR latch[1]: %02x\n", (dadr_latch >> 8) & 0xff)); return (dadr_latch >> 8) & 0xff;
|
||||
@ -397,11 +421,11 @@ WRITE8_MEMBER(es5510_device::host_w)
|
||||
dadr_latch = (dadr_latch&0x00ffff) | ((data&0xff)<<16);
|
||||
if (ram_sel)
|
||||
{
|
||||
dil_latch = dram[dadr_latch];
|
||||
dil_latch = dram[dadr_latch] << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
dram[dadr_latch] = dol_latch;
|
||||
dram[dadr_latch] = dol_latch >> 8;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -455,7 +479,7 @@ WRITE8_MEMBER(es5510_device::host_w)
|
||||
|
||||
case 0xc0: /* Write select - INSTR */
|
||||
#if VERBOSE
|
||||
DESCRIBE_INSTR(buf, instr_latch, gpr[data]);
|
||||
DESCRIBE_INSTR(buf, instr_latch, gpr[data], NULL, NULL, NULL, NULL);
|
||||
LOG(("ES5510: Host Write INSTR %02x %012" I64FMT "x: %s\n", data, instr_latch&U64(0xffffffffffff), buf));
|
||||
#endif
|
||||
if (data < 0xa0) {
|
||||
@ -465,7 +489,7 @@ WRITE8_MEMBER(es5510_device::host_w)
|
||||
|
||||
case 0xe0: /* Write select - GPR + INSTR */
|
||||
#if VERBOSE
|
||||
DESCRIBE_INSTR(buf, instr_latch, gpr_latch);
|
||||
DESCRIBE_INSTR(buf, instr_latch, gpr_latch, NULL, NULL, NULL, NULL);
|
||||
LOG(("ES5510: Host Write INSTR+GPR %02x (%s): %012" I64FMT "x %06x (%d): %s\n", data, REGNAME(data&0xff), instr_latch, gpr_latch, SX(gpr_latch), buf));
|
||||
#endif
|
||||
if (data < 0xa0) {
|
||||
@ -560,14 +584,83 @@ void es5510_device::execute_set_input(int linenum, int state) {
|
||||
void es5510_device::list_program(void(p)(const char *, ...)) {
|
||||
LOG(("ES5501: Starting!\n"));
|
||||
|
||||
UINT8 addr;
|
||||
char buf[1024];
|
||||
bool is_written[0xff], is_read[0xff];
|
||||
char name[0xff][16];
|
||||
int addr;
|
||||
|
||||
for (int i = 0; i < 0x100; i++) {
|
||||
is_written[i] = is_read[i] = false;
|
||||
name[i][0] = '\0';
|
||||
}
|
||||
|
||||
for (addr = 0; addr < 0xa0; addr++) {
|
||||
DESCRIBE_INSTR(buf, instr[addr], gpr[addr]);
|
||||
p("%02x: %012" I64FMT "x %06x %s\n", addr, instr[addr], gpr[addr]&0xffffff, buf);
|
||||
DESCRIBE_INSTR(buf, instr[addr], gpr[addr], NULL, NULL, NULL, NULL);
|
||||
UINT64 inst = instr[addr];
|
||||
UINT8 aReg = (UINT8)((inst >> 16) & 0xff);
|
||||
UINT8 bReg = (UINT8)((inst >> 24) & 0xff);
|
||||
UINT8 cReg = (UINT8)((inst >> 32) & 0xff);
|
||||
UINT8 dReg = (UINT8)((inst >> 40) & 0xff);
|
||||
UINT8 alu_op = (inst >> 12) & 0x0f;
|
||||
if (alu_op == 0x0f) {
|
||||
// END!
|
||||
break;
|
||||
}
|
||||
|
||||
UINT8 operandSelect = (UINT8)((inst >> 8) & 0x0f);
|
||||
const op_select_t &opSelect = OPERAND_SELECT[operandSelect];
|
||||
|
||||
if (opSelect.mac_src == SRC_DST_REG) {
|
||||
is_read[cReg] = true;
|
||||
}
|
||||
is_read[dReg] = true;
|
||||
if (opSelect.mac_dst != SRC_DST_DELAY) { // either REG or BOTH
|
||||
is_written[cReg] = true;
|
||||
}
|
||||
|
||||
alu_op_t aluOp = ALU_OPS[alu_op];
|
||||
if (aluOp.operands == 1) {
|
||||
if (opSelect.alu_src == SRC_DST_REG) {
|
||||
is_read[bReg] = true;
|
||||
}
|
||||
} else if (aluOp.operands == 2) {
|
||||
if (opSelect.alu_src == SRC_DST_REG) {
|
||||
is_read[aReg] = true;
|
||||
}
|
||||
is_read[bReg] = true;
|
||||
}
|
||||
if (opSelect.mac_dst != SRC_DST_DELAY) { // either REG or BOTH
|
||||
is_written[aReg] = true;
|
||||
}
|
||||
}
|
||||
|
||||
int varIndex = 1;
|
||||
int constIndex = 1;
|
||||
for (int i = 0; i < 0xc0; i++) {
|
||||
if (is_written[i]) {
|
||||
// this is a variable
|
||||
sprintf(name[i], "v_%03d", varIndex++);
|
||||
} else if (is_read[i]) {
|
||||
// this is only read, so a constant - or possibly something updated by the CPU
|
||||
sprintf(name[i], "c_%03d", constIndex++);
|
||||
} else {
|
||||
name[i][0] = 0;
|
||||
}
|
||||
}
|
||||
for (int i = 0xc0; i < 0x100; i++) {
|
||||
name[i][0] = 0;
|
||||
}
|
||||
|
||||
for (addr = 0; addr < 0xa0; addr++) {
|
||||
UINT8 aReg = (UINT8)((instr[addr] >> 16) & 0xff);
|
||||
UINT8 bReg = (UINT8)((instr[addr] >> 24) & 0xff);
|
||||
UINT8 cReg = (UINT8)((instr[addr] >> 32) & 0xff);
|
||||
UINT8 dReg = (UINT8)((instr[addr] >> 40) & 0xff);
|
||||
DESCRIBE_INSTR(buf, instr[addr], gpr[addr], name[aReg], name[bReg], name[cReg], name[dReg]);
|
||||
p("%02x: %012" I64FMT "x %06x (%8d) %s\n", addr, instr[addr], gpr[addr]&0xffffff, SX(gpr[addr]&0xffffff), buf);
|
||||
}
|
||||
for (; addr < 0xc0; addr++) {
|
||||
p("%02x: %06x (%d)\n", addr, gpr[addr]&0xffffff, gpr[addr]);
|
||||
p("%02x: %06x (%d)\n", addr, gpr[addr]&0xffffff, SX(gpr[addr]&0xffffff));
|
||||
}
|
||||
}
|
||||
|
||||
@ -587,15 +680,17 @@ void es5510_device::execute_run() {
|
||||
} else {
|
||||
// currently running, execute one instruction.
|
||||
|
||||
#if VERBOSE
|
||||
#if VERBOSE_EXEC
|
||||
char buf[1024];
|
||||
DESCRIBE_INSTR(buf, instr[pc], gpr[pc]);
|
||||
LOG(("%02x: %012" I64FMT "x %06x %s\n", pc, instr[pc], gpr[pc]&0xffffff, buf));
|
||||
DESCRIBE_INSTR(buf, instr[pc], gpr[pc], NULL, NULL, NULL, NULL);
|
||||
LOG_EXEC(("EXECUTING %02x: %012" I64FMT "x %06x %s\n", pc, instr[pc], gpr[pc]&0xffffff, buf));
|
||||
#endif
|
||||
|
||||
ram_pp = ram_p;
|
||||
ram_p = ram;
|
||||
|
||||
LOG_EXEC(("- T0\n"));
|
||||
|
||||
// *** T0, clock high
|
||||
// --- nothing to do!
|
||||
|
||||
@ -608,7 +703,8 @@ void es5510_device::execute_run() {
|
||||
if (ram_pp.io) { // read from I/O and store into DIL
|
||||
dil = 0; // read_io(ram_pp.address);;
|
||||
} else { // read from DRAM and store into DIL
|
||||
dil = dram[ram_pp.address];
|
||||
dil = dram[ram_pp.address] << 8;
|
||||
LOG_EXEC((" . RAM: read %x (%d) from address %x\n", dil, dil, ram_pp.address));
|
||||
}
|
||||
}
|
||||
|
||||
@ -621,16 +717,20 @@ void es5510_device::execute_run() {
|
||||
INT32 offset = gpr[pc];
|
||||
switch(ramControl.access) {
|
||||
case RAM_CONTROL_DELAY:
|
||||
ram.address = (((dbase + offset) % (dlength + 1)) & memmask) >> memshift;
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
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));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -638,25 +738,56 @@ 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"));
|
||||
|
||||
UINT8 operandSelect = (UINT8)((instr >> 8) & 0x0f);
|
||||
const op_select_t &opSelect = OPERAND_SELECT[operandSelect];
|
||||
bool skip = false;
|
||||
bool skippable = ((instr >> 7) & 0x01) != 0; // aka the 'SKIP' bit in the instruction word
|
||||
bool skip;
|
||||
bool skippable = (instr & (0x01 << 7)) != 0; // aka the 'SKIP' bit in the instruction word
|
||||
if (skippable) {
|
||||
bool skipConditionSatisfied = (ccr & cmr & FLAG_MASK) != 0;
|
||||
if (isFlagSet(cmr, FLAG_NOT)) {
|
||||
skipConditionSatisfied = !skipConditionSatisfied;
|
||||
}
|
||||
skip = skipConditionSatisfied;
|
||||
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"));
|
||||
if (mulacc.write_result) {
|
||||
mulacc.product = (mulacc.cValue * mulacc.dValue) << mulshift;
|
||||
mulacc.result = (mulacc.accumulate ? machl : 0) + mulacc.product;
|
||||
INT32 tmp = (mulacc.result & U64(0x0000ffffff000000)) >> 24;
|
||||
mulacc.product = ((INT64)SX(mulacc.cValue) * (INT64)SX(mulacc.dValue)) << mulshift;
|
||||
if (mulacc.accumulate) {
|
||||
mulacc.result = mulacc.product + machl;
|
||||
} else {
|
||||
mulacc.result = mulacc.product;
|
||||
}
|
||||
|
||||
INT64 result_min = ~0LL << 47;
|
||||
INT64 result_max = (1LL << 48) - 1;
|
||||
|
||||
if (mulacc.result < result_min || mulacc.result > result_max) {
|
||||
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));
|
||||
if (mac_overflow) {
|
||||
LOG_EXEC((" overflow!\n"));
|
||||
} else {
|
||||
LOG_EXEC(("\n"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
machl = mulacc.result;
|
||||
INT32 tmp = mac_overflow ? (machl < 0 ? 0x00800000 : 0x007fffff) : (mulacc.result & U64(0x0000ffffff000000)) >> 24;
|
||||
if (mulacc.dst & SRC_DST_REG) {
|
||||
machl = mulacc.result;
|
||||
write_reg(mulacc.cReg, tmp);
|
||||
}
|
||||
if (mulacc.dst & SRC_DST_DELAY) {
|
||||
@ -665,7 +796,11 @@ void es5510_device::execute_run() {
|
||||
}
|
||||
|
||||
// *** T1, clock low
|
||||
|
||||
LOG_EXEC(("- T1.0\n"));
|
||||
|
||||
// --- Start of multiplier cycle N
|
||||
LOG_EXEC((". start mulacc:\n"));
|
||||
mulacc.cReg = (UINT8)((instr >> 32) & 0xff);
|
||||
mulacc.dReg = (UINT8)((instr >> 40) & 0xff);
|
||||
mulacc.src = opSelect.mac_src;
|
||||
@ -677,12 +812,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)));
|
||||
mulacc.cValue = dil;
|
||||
}
|
||||
mulacc.dValue = read_reg(mulacc.dReg);
|
||||
|
||||
// *** T2, clock high
|
||||
|
||||
LOG_EXEC(("- T2.1\n"));
|
||||
|
||||
// --- Write ALU Result N-1
|
||||
LOG_EXEC((". write ALU:\n"));
|
||||
if (alu.write_result) {
|
||||
UINT8 flags = ccr;
|
||||
alu.result = alu_operation(alu.op, alu.aValue, alu.bValue, flags);
|
||||
@ -698,7 +838,11 @@ void es5510_device::execute_run() {
|
||||
}
|
||||
|
||||
// *** T2, clock low
|
||||
|
||||
LOG_EXEC(("- T2.0\n"));
|
||||
|
||||
// --- Start of ALU cycle N
|
||||
LOG_EXEC((". start ALU:\n"));
|
||||
alu.aReg = (instr >> 16) & 0xff;
|
||||
alu.bReg = (instr >> 24) & 0xff;
|
||||
alu.op = (instr >> 12) & 0x0f;
|
||||
@ -712,14 +856,18 @@ void es5510_device::execute_run() {
|
||||
} else {
|
||||
// --- Read ALU Operands N
|
||||
alu_op_t aluOp = ALU_OPS[alu.op];
|
||||
if (aluOp.operands == 2) {
|
||||
if (aluOp.operands == 1) {
|
||||
if (alu.src == SRC_DST_REG) {
|
||||
alu.bValue = read_reg(alu.bReg);
|
||||
} else { // must be SRC_DST_DELAY
|
||||
alu.bValue = dil;
|
||||
}
|
||||
} else {
|
||||
if (alu.src == SRC_DST_REG) {
|
||||
alu.aValue = read_reg(alu.aReg);
|
||||
} else { // must be SRC_DST_DELAY
|
||||
alu.aValue = dil;
|
||||
}
|
||||
}
|
||||
if (aluOp.operands >= 1) {
|
||||
alu.bValue = read_reg(alu.bReg);
|
||||
}
|
||||
}
|
||||
@ -731,14 +879,26 @@ void es5510_device::execute_run() {
|
||||
if (ram_p.io) {
|
||||
// write_io(ram_p.io, dol[0]);
|
||||
} else {
|
||||
dram[ram_p.address] = dol[0];
|
||||
dram[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));
|
||||
}
|
||||
}
|
||||
// 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
|
||||
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
|
||||
}
|
||||
|
||||
++pc;
|
||||
@ -762,38 +922,48 @@ offs_t es5510_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *o
|
||||
return pc;
|
||||
}
|
||||
|
||||
#if VERBOSE_EXEC
|
||||
#define RETURN_GPR(r, x) do { INT32 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 v = (x); LOG_EXEC((" . reading %x (%d) from " #r "\n", v, SX(v))); return v; } while(0)
|
||||
#define RETURN16(r, x) do { INT16 vv = (x); INT32 v = vv << 8; LOG_EXEC((" . reading %x (%d) as %x (%d) from " #r "\n", vv, vv, v, SX(v))); return v; } while(0)
|
||||
#else
|
||||
#define RETURN_GPR(r, x) return x
|
||||
#define RETURN(r, x) return x
|
||||
#define RETURN16(r, x) return (x) << 8
|
||||
#endif
|
||||
|
||||
INT32 es5510_device::read_reg(UINT8 reg)
|
||||
{
|
||||
if (reg < 0xc0) {
|
||||
return gpr[reg];
|
||||
RETURN_GPR(reg, gpr[reg]);
|
||||
} else {
|
||||
switch(reg)
|
||||
{
|
||||
case 234: return ser0r;
|
||||
case 235: return ser0l;
|
||||
case 236: return ser1r;
|
||||
case 237: return ser1l;
|
||||
case 238: return ser2r;
|
||||
case 239: return ser2l;
|
||||
case 240: return ser3r;
|
||||
case 241: return ser3l;
|
||||
case 242: return (machl >> 0) & 0x00ffffff;
|
||||
case 243: return (machl >> 24) & 0x00ffffff;
|
||||
case 244: return dil; // DIL when reading
|
||||
case 245: return dlength;
|
||||
case 246: return abase;
|
||||
case 247: return bbase;
|
||||
case 248: return dbase;
|
||||
case 249: return sigreg;
|
||||
case 250: return ccr;
|
||||
case 251: return cmr;
|
||||
case 252: return 0x00ffffff;
|
||||
case 253: return 0x00800000;
|
||||
case 254: return 0x007fffff;
|
||||
case 255: return 0x00000000;
|
||||
case 234: RETURN16(ser0r, ser0r);
|
||||
case 235: RETURN16(ser0l, ser0l);
|
||||
case 236: RETURN16(ser1r, ser1r);
|
||||
case 237: RETURN16(ser1l, ser1l);
|
||||
case 238: RETURN16(ser2r, ser2r);
|
||||
case 239: RETURN16(ser2l, ser2l);
|
||||
case 240: RETURN16(ser3r, ser3r);
|
||||
case 241: RETURN16(ser3l, ser3l);
|
||||
case 242: /* macl */ RETURN(macl, mac_overflow ? (machl < 0 ? 0x00fffffe : 0x00000000) : (machl >> 0) & 0x00ffffff);
|
||||
case 243: /* mach */ RETURN(mach, mac_overflow ? (machl < 0 ? 0x007fffff : 0x00800000) : (machl >> 24) & 0x00ffffff);
|
||||
case 244: RETURN(dil, dil); // DIL when reading
|
||||
case 245: RETURN(dlength, dlength);
|
||||
case 246: RETURN(abase, abase);
|
||||
case 247: RETURN(bbase, bbase);
|
||||
case 248: RETURN(dbase, dbase);
|
||||
case 249: RETURN(sigreg, sigreg);
|
||||
case 250: RETURN(ccr, ccr);
|
||||
case 251: RETURN(cmr, cmr);
|
||||
case 252: RETURN(minus_one, 0x00ffffff);
|
||||
case 253: RETURN(min, 0x00800000);
|
||||
case 254: RETURN(max, 0x007fffff);
|
||||
case 255: RETURN(zero, 0x00000000);
|
||||
default:
|
||||
// unknown SPR
|
||||
return 0;
|
||||
RETURN(unknown, 0);;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -826,61 +996,95 @@ INT8 countLowOnes(INT32 x) {
|
||||
return n;
|
||||
}
|
||||
|
||||
#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)
|
||||
#else
|
||||
#define WRITE_REG(r, x) do { r = value; } while(0)
|
||||
#define WRITE_REG16(r, x) do { r = ((value >> 8) & 0xffff); } while(0)
|
||||
#endif
|
||||
|
||||
void es5510_device::write_reg(UINT8 reg, INT32 value)
|
||||
{
|
||||
#if VERBOSE_EXEC
|
||||
INT64 old;
|
||||
#endif
|
||||
value &= 0x00ffffff;
|
||||
if (reg < 0xc0) {
|
||||
LOG_EXEC((" . writing %x (%d) to gpr_%02x\n", value, SX(value), reg));
|
||||
gpr[reg] = value;
|
||||
} else {
|
||||
switch(reg)
|
||||
{
|
||||
case 234: ser0r = value;
|
||||
case 234: WRITE_REG16(ser0r, value);
|
||||
break;
|
||||
case 235: ser0l = value;
|
||||
case 235: WRITE_REG16(ser0l, value);
|
||||
break;
|
||||
case 236: ser1r = value;
|
||||
case 236: WRITE_REG16(ser1r, value);
|
||||
break;
|
||||
case 237: ser1l = value;
|
||||
case 237: WRITE_REG16(ser1l, value);
|
||||
break;
|
||||
case 238: ser2r = value;
|
||||
case 238: WRITE_REG16(ser2r, value);
|
||||
break;
|
||||
case 239: ser2l = value;
|
||||
case 239: WRITE_REG16(ser2l, value);
|
||||
break;
|
||||
case 240: ser3r = value;
|
||||
case 240: WRITE_REG16(ser3r, value);
|
||||
break;
|
||||
case 241: ser3l = value;
|
||||
case 241: WRITE_REG16(ser3l, value);
|
||||
break;
|
||||
case 242: machl = (machl & ~((INT64)0x00ffffff << 0)) | (value << 0);
|
||||
case 242: /* macl */ {
|
||||
#if VERBOSE_EXEC
|
||||
old = machl;
|
||||
#endif
|
||||
INT64 masked = machl & (S64(0x00ffffff) << 24);
|
||||
INT64 shifted = (INT64)(value & 0x00ffffff) << 0;
|
||||
machl = SX64(masked | shifted);
|
||||
#if VERBOSE_EXEC
|
||||
LOG_EXEC((" . writing machl: l -> %06x => %llx -> %llx\n", value, old, machl));
|
||||
#endif
|
||||
break;
|
||||
case 243: machl = (machl & ~((INT64)0x00ffffff << 24)) | (value << 24);
|
||||
}
|
||||
case 243: /* mach */ {
|
||||
#if VERBOSE_EXEC
|
||||
old = machl;
|
||||
#endif
|
||||
INT64 masked = machl & (S64(0x00ffffff) << 0);
|
||||
INT64 shifted = (INT64)(value & 0x00ffffff) << 24;
|
||||
machl = SX64(masked | shifted);
|
||||
mac_overflow = false;
|
||||
#if VERBOSE_EXEC
|
||||
LOG_EXEC((" . writing machl: h -> %06x => %llx -> %llx\n", value, old, machl));
|
||||
#endif
|
||||
break;
|
||||
case 244:
|
||||
}
|
||||
case 244: /* MEMSIZ when writing */
|
||||
memshift = countLowOnes(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));
|
||||
break;
|
||||
case 245: dlength = value;
|
||||
case 245: WRITE_REG(dlength, value);
|
||||
break;
|
||||
case 246: abase = value;
|
||||
case 246: WRITE_REG(abase, value);
|
||||
break;
|
||||
case 247: bbase = value;
|
||||
case 247: WRITE_REG(bbase, value);
|
||||
break;
|
||||
case 248: dbase = value;
|
||||
case 248: WRITE_REG(dbase, value);
|
||||
break;
|
||||
case 249: sigreg = (value != 0);
|
||||
case 249: WRITE_REG(sigreg, (value != 0));
|
||||
break;
|
||||
case 250: ccr = (value >> 16) & FLAG_MASK;
|
||||
case 250: WRITE_REG(ccr, (value >> 16) & FLAG_MASK);
|
||||
break;
|
||||
case 251: cmr = (value >> 16) & (FLAG_MASK | FLAG_NOT);
|
||||
case 251: WRITE_REG(cmr, (value >> 16) & (FLAG_MASK | FLAG_NOT));
|
||||
break;
|
||||
case 252: // no-op
|
||||
case 252: LOG_EXEC((". not writing %x (%d) to minus_one\n", value, SX(value))); // no-op
|
||||
break;
|
||||
case 253: // no-op
|
||||
case 253: LOG_EXEC((". not writing %x (%d) to min\n", value, SX(value))); // no-op
|
||||
break;
|
||||
case 254: // no-op
|
||||
case 254: LOG_EXEC((". not writing %x (%d) to max\n", value, SX(value))); // no-op
|
||||
break;
|
||||
case 255: // no-op
|
||||
case 255: LOG_EXEC((". not writing %x (%d) to zero\n", value, SX(value))); // no-op
|
||||
break;
|
||||
default: // unknown register
|
||||
break;
|
||||
@ -889,17 +1093,28 @@ void es5510_device::write_reg(UINT8 reg, INT32 value)
|
||||
}
|
||||
|
||||
void es5510_device::write_to_dol(INT32 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
|
||||
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
|
||||
}
|
||||
|
||||
void es5510_device::alu_operation_end() {
|
||||
// Handle the END instruction separately
|
||||
LOG(("ES5510: END\n"));
|
||||
LOG_EXEC(("ES5510: END\n"));
|
||||
// sample the HALT line
|
||||
if (halt_asserted) {
|
||||
// halt
|
||||
@ -911,15 +1126,27 @@ void es5510_device::alu_operation_end() {
|
||||
if (dbase < 0) {
|
||||
dbase = dlength;
|
||||
}
|
||||
// Possibly reset the PC
|
||||
if (state == STATE_RUNNING) {
|
||||
pc = 0;
|
||||
}
|
||||
|
||||
#if VERBOSE_EXEC
|
||||
// update the verbose-execution counter.
|
||||
exec_cc = (exec_cc + 1) % 10000;
|
||||
#endif
|
||||
}
|
||||
|
||||
INT32 es5510_device::alu_operation(UINT8 op, INT32 a, INT32 b, UINT8 &flags) {
|
||||
INT32 tmp;
|
||||
switch(op) {
|
||||
case 0x0: // ADD
|
||||
return saturate(add(a, b, flags), flags);
|
||||
tmp = add(a, b, flags);
|
||||
return saturate(tmp, flags);
|
||||
|
||||
case 0x1: // SUB
|
||||
return saturate(add(a, negate(b), flags), flags);
|
||||
tmp = add(a, negate(b), flags);
|
||||
return saturate(tmp, flags);
|
||||
|
||||
case 0x2: // ADDU
|
||||
return add(a, b, flags);
|
||||
@ -954,10 +1181,7 @@ INT32 es5510_device::alu_operation(UINT8 op, INT32 a, INT32 b, UINT8 &flags) {
|
||||
clearFlag(flags, FLAG_N);
|
||||
bool isNegative = (a & 0x00800000) != 0;
|
||||
setFlagTo(flags, FLAG_C, isNegative);
|
||||
if (isNegative) {
|
||||
a = (a ^ 0x00ffffff) + 1;
|
||||
}
|
||||
return a;
|
||||
return isNegative ? negate(a) : a;
|
||||
}
|
||||
|
||||
case 0x9: // MOV
|
||||
|
@ -91,8 +91,8 @@ public:
|
||||
op_src_dst_t src;
|
||||
op_src_dst_t dst;
|
||||
bool accumulate;
|
||||
INT64 cValue;
|
||||
INT64 dValue;
|
||||
INT32 cValue;
|
||||
INT32 dValue;
|
||||
INT64 product;
|
||||
INT64 result;
|
||||
bool write_result;
|
||||
@ -111,6 +111,15 @@ public:
|
||||
void run_once();
|
||||
void list_program(void(p)(const char *, ...));
|
||||
|
||||
// for testing purposes
|
||||
UINT64 &_instr(int pc) { return instr[pc % 160]; }
|
||||
INT16 &_dram(int addr) { return dram[addr & 0xfffff]; }
|
||||
|
||||
// publicly visible for testing purposes
|
||||
INT32 read_reg(UINT8 reg);
|
||||
void write_reg(UINT8 reg, INT32 value);
|
||||
void write_to_dol(INT32 value);
|
||||
|
||||
protected:
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
@ -126,10 +135,6 @@ protected:
|
||||
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
|
||||
virtual void execute_set_input(int linenum, int state);
|
||||
|
||||
INT32 read_reg(UINT8 reg);
|
||||
void write_reg(UINT8 reg, INT32 value);
|
||||
void write_to_dol(INT32 value);
|
||||
|
||||
INT32 alu_operation(UINT8 op, INT32 aValue, INT32 bValue, UINT8 &flags);
|
||||
void alu_operation_end();
|
||||
|
||||
@ -138,16 +143,17 @@ private:
|
||||
bool halt_asserted;
|
||||
UINT8 pc;
|
||||
state_t state;
|
||||
INT32 gpr[0xc0]; // 24 bits, right justified and sign extended
|
||||
INT32 ser0r;
|
||||
INT32 ser0l;
|
||||
INT32 ser1r;
|
||||
INT32 ser1l;
|
||||
INT32 ser2r;
|
||||
INT32 ser2l;
|
||||
INT32 ser3r;
|
||||
INT32 ser3l;
|
||||
INT64 machl; // 48 bits, right justified and sign extended
|
||||
INT32 gpr[0xc0]; // 24 bits, right justified
|
||||
INT16 ser0r;
|
||||
INT16 ser0l;
|
||||
INT16 ser1r;
|
||||
INT16 ser1l;
|
||||
INT16 ser2r;
|
||||
INT16 ser2l;
|
||||
INT16 ser3r;
|
||||
INT16 ser3l;
|
||||
INT64 machl; // 48 bits, right justified and sign extended
|
||||
bool mac_overflow; // whether reading the MAC register should return a saturated replacement value
|
||||
INT32 dil;
|
||||
INT32 memsiz;
|
||||
INT32 memmask;
|
||||
@ -159,13 +165,13 @@ private:
|
||||
INT32 dbase;
|
||||
INT32 sigreg;
|
||||
int mulshift;
|
||||
INT8 ccr; // really, 5 bits, left justified
|
||||
INT8 cmr; // really, 6 bits, left justified
|
||||
INT8 ccr; // really, 5 bits, left justified
|
||||
INT8 cmr; // really, 6 bits, left justified
|
||||
INT32 dol[2];
|
||||
int dol_count;
|
||||
|
||||
UINT64 instr[160]; // 48 bits, right justified
|
||||
UINT16 dram[1<<20]; // there are up to 20 address bits (at least 16 expected), left justified within the 24 bits of a gpr or dadr; we preallocate all of it.
|
||||
INT16 dram[1<<20]; // there are up to 20 address bits (at least 16 expected), left justified within the 24 bits of a gpr or dadr; we preallocate all of it.
|
||||
|
||||
// latch registers for host interaction
|
||||
INT32 dol_latch; // 24 bits
|
||||
|
@ -143,9 +143,11 @@ void print_to_stderr(const char *format, ...)
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
#define PUMP_DETECT_SILENCE 1
|
||||
#define PUMP_DETECT_SILENCE 0
|
||||
#define PUMP_TRACK_SAMPLES 0
|
||||
#define PUMP_FAKE_ESP_PROCESSING 1
|
||||
#define PUMP_FAKE_ESP_PROCESSING 0
|
||||
#define PUMP_REPLACE_ESP_PROGRAM 0
|
||||
|
||||
class esq_5505_5510_pump : public device_t,
|
||||
public device_sound_interface
|
||||
{
|
||||
@ -158,7 +160,43 @@ public:
|
||||
m_esp_halted = esp_halted;
|
||||
logerror("ESP-halted -> %d\n", m_esp_halted);
|
||||
if (!esp_halted) {
|
||||
m_esp->list_program(print_to_stderr);
|
||||
|
||||
#if PUMP_REPLACE_ESP_PROGRAM
|
||||
m_esp->write_reg(245, 0x1d0f << 8); // dlength = 0x3fff, 16-sample delay
|
||||
|
||||
int pc = 0;
|
||||
for (pc = 0; pc < 0xc0; pc++) {
|
||||
m_esp->write_reg(pc, 0);
|
||||
}
|
||||
pc = 0;
|
||||
// replace the ESP program with a simple summing & single-sample delay
|
||||
m_esp->_instr(pc++) = 0xffffeaa09000; // MOV SER0R > grp_a0
|
||||
m_esp->_instr(pc++) = 0xffffeba00000; // ADD SER0L, gpr_a0 > gpr_a0
|
||||
m_esp->_instr(pc++) = 0xffffeca00000; // ADD SER1R, gpr_a0 > gpr_a0
|
||||
m_esp->_instr(pc++) = 0xffffeda00000; // ADD SER1L, gpr_a0 > gpr_a0
|
||||
m_esp->_instr(pc++) = 0xffffeea00000; // ADD SER2R, gpr_a0 > gpr_a0
|
||||
|
||||
m_esp->_instr(pc ) = 0xffffefa00000; // ADD SER2L, gpr_a0 > gpr_a0; prepare to read from delay 2 instructions from now, offset = 0
|
||||
m_esp->write_reg(pc++, 0); //offset into delay
|
||||
|
||||
m_esp->_instr(pc ) = 0xffffa0a09508; // MOV gpr_a0 > delay + offset
|
||||
m_esp->write_reg(pc++, 1 << 8); // offset into delay - -1 samples
|
||||
|
||||
m_esp->_instr(pc++) = 0xffff00a19928; // MOV DIL > gpr_a1; read Delay and dump FIFO (so that the value gets written)
|
||||
|
||||
m_esp->_instr(pc++) = 0xffffa1f09000; // MOV gpr_a1 > SER3R
|
||||
m_esp->_instr(pc++) = 0xffffa1f19000; // MOV gpr_a1 > SER3L
|
||||
|
||||
m_esp->_instr(pc++) = 0xffffffff0000; // NO-OP
|
||||
m_esp->_instr(pc++) = 0xffffffff0000; // NO-OP
|
||||
m_esp->_instr(pc++) = 0xfffffffff000; // END
|
||||
|
||||
while (pc < 160) {
|
||||
m_esp->_instr(pc++) = 0xffffffffffff; // no-op
|
||||
}
|
||||
#endif
|
||||
|
||||
// m_esp->list_program(print_to_stderr);
|
||||
}
|
||||
}
|
||||
bool get_esp_halted() {
|
||||
@ -174,7 +212,7 @@ protected:
|
||||
// sound stream update overrides
|
||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||
|
||||
// timer callback overridea
|
||||
// timer callback overrides
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
private:
|
||||
@ -209,6 +247,11 @@ private:
|
||||
osd_ticks_t last_ticks;
|
||||
osd_ticks_t next_report_ticks;
|
||||
#endif
|
||||
|
||||
#if !PUMP_FAKE_ESP_PROCESSING && PUMP_REPLACE_ESP_PROGRAM
|
||||
INT16 e[0x4000];
|
||||
int ei;
|
||||
#endif
|
||||
};
|
||||
|
||||
const device_type ESQ_5505_5510_PUMP = &device_creator<esq_5505_5510_pump>;
|
||||
@ -222,14 +265,11 @@ esq_5505_5510_pump::esq_5505_5510_pump(const machine_config &mconfig, const char
|
||||
|
||||
void esq_5505_5510_pump::device_start()
|
||||
{
|
||||
INT64 nsec_per_sample = 100 * 16 * 21;
|
||||
attotime sample_time(0, 1000000000 * nsec_per_sample);
|
||||
attotime initial_delay(0, 0);
|
||||
logerror("Clock = %d\n", clock());
|
||||
|
||||
m_stream = machine().sound().stream_alloc(*this, 8, 2, clock(), this);
|
||||
m_timer = timer_alloc(0);
|
||||
m_timer->adjust(initial_delay, 0, sample_time);
|
||||
m_timer->enable(true);
|
||||
m_timer->enable(false);
|
||||
|
||||
#if PUMP_DETECT_SILENCE
|
||||
silent_for = 500;
|
||||
@ -244,6 +284,11 @@ void esq_5505_5510_pump::device_start()
|
||||
last_ticks = osd_ticks();
|
||||
next_report_ticks = last_ticks + osd_ticks_per_second();
|
||||
#endif
|
||||
|
||||
#if !PUMP_FAKE_ESP_PROCESSING && PUMP_REPLACE_ESP_PROGRAM
|
||||
memset(e, 0, 0x4000 * sizeof(e[0]));
|
||||
ei = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void esq_5505_5510_pump::device_stop()
|
||||
@ -253,6 +298,12 @@ void esq_5505_5510_pump::device_stop()
|
||||
|
||||
void esq_5505_5510_pump::device_reset()
|
||||
{
|
||||
INT64 nsec_per_sample = 100 * 16 * 21;
|
||||
attotime sample_time(0, 1000000000 * nsec_per_sample);
|
||||
attotime initial_delay(0, 0);
|
||||
|
||||
m_timer->adjust(initial_delay, 0, sample_time);
|
||||
m_timer->enable(true);
|
||||
}
|
||||
|
||||
void esq_5505_5510_pump::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
@ -264,9 +315,9 @@ void esq_5505_5510_pump::sound_stream_update(sound_stream &stream, stream_sample
|
||||
stream_sample_t *left = outputs[0], *right = outputs[1];
|
||||
for (int i = 0; i < samples; i++)
|
||||
{
|
||||
// anything for the 'aux' output?
|
||||
INT32 l = inputs[0][i] >> 4;
|
||||
INT32 r = inputs[1][i] >> 4;
|
||||
// anything for the 'aux' output?
|
||||
INT16 l = inputs[0][i] >> 4;
|
||||
INT16 r = inputs[1][i] >> 4;
|
||||
|
||||
// push the samples into the ESP
|
||||
m_esp->ser_w(0, inputs[2][i] >> 4);
|
||||
@ -276,9 +327,6 @@ void esq_5505_5510_pump::sound_stream_update(sound_stream &stream, stream_sample
|
||||
m_esp->ser_w(4, inputs[6][i] >> 4);
|
||||
m_esp->ser_w(5, inputs[7][i] >> 4);
|
||||
|
||||
m_esp->ser_w(6, 0);
|
||||
m_esp->ser_w(7, 0);
|
||||
|
||||
#if PUMP_FAKE_ESP_PROCESSING
|
||||
m_esp->ser_w(6, m_esp->ser_r(0) + m_esp->ser_r(2) + m_esp->ser_r(4));
|
||||
m_esp->ser_w(7, m_esp->ser_r(1) + m_esp->ser_r(3) + m_esp->ser_r(5));
|
||||
@ -294,8 +342,23 @@ void esq_5505_5510_pump::sound_stream_update(sound_stream &stream, stream_sample
|
||||
#endif
|
||||
|
||||
// read the processed result from the ESP and add to the saved AUX data
|
||||
l += m_esp->ser_r(6);
|
||||
r += m_esp->ser_r(7);
|
||||
INT16 ll = m_esp->ser_r(6);
|
||||
INT16 rr = m_esp->ser_r(7);
|
||||
l += ll;
|
||||
r += rr;
|
||||
|
||||
#if !PUMP_FAKE_ESP_PROCESSING && PUMP_REPLACE_ESP_PROGRAM
|
||||
// if we're processing the fake program through the ESP, the result should just be that of adding the inputs
|
||||
INT32 el = (inputs[2][i]) + (inputs[4][i]) + (inputs[6][i]);
|
||||
INT32 er = (inputs[3][i]) + (inputs[5][i]) + (inputs[7][i]);
|
||||
INT32 e_next = el + er;
|
||||
e[(ei + 0x1d0f) % 0x4000] = e_next;
|
||||
|
||||
if (l != e[ei]) {
|
||||
fprintf(stderr, "expected (%d) but have (%d)\n", e[ei], l);
|
||||
}
|
||||
ei = (ei + 1) % 0x4000;
|
||||
#endif
|
||||
|
||||
// write the combined data to the output
|
||||
*left++ = l;
|
||||
@ -876,8 +939,8 @@ static MACHINE_CONFIG_START( vfx, esq5505_state )
|
||||
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
||||
|
||||
MCFG_SOUND_ADD("pump", ESQ_5505_5510_PUMP, XTAL_10MHz / (16 * 21))
|
||||
MCFG_SOUND_ROUTE(0, "lspeaker", 2.0)
|
||||
MCFG_SOUND_ROUTE(1, "rspeaker", 2.0)
|
||||
MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
|
||||
MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
|
||||
|
||||
MCFG_SOUND_ADD("otis", ES5505, XTAL_10MHz)
|
||||
MCFG_SOUND_CONFIG(es5505_config)
|
||||
@ -930,8 +993,8 @@ static MACHINE_CONFIG_START(vfx32, esq5505_state)
|
||||
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
||||
|
||||
MCFG_SOUND_ADD("pump", ESQ_5505_5510_PUMP, XTAL_30_4761MHz / (2 * 16 * 32))
|
||||
MCFG_SOUND_ROUTE(0, "lspeaker", 2.0)
|
||||
MCFG_SOUND_ROUTE(1, "rspeaker", 2.0)
|
||||
MCFG_SOUND_ROUTE(0, "lspeaker", 1.0)
|
||||
MCFG_SOUND_ROUTE(1, "rspeaker", 1.0)
|
||||
|
||||
MCFG_SOUND_ADD("otis", ES5505, XTAL_30_4761MHz / 2)
|
||||
MCFG_SOUND_CONFIG(es5505_config)
|
||||
|
Loading…
Reference in New Issue
Block a user