mame/src/emu/cpu/cubeqcpu/cubeqcpu.c
Aaron Giles 98c40f06db Made CPUs into proper devices. CPUs are now added in the
machine configuration just as any other device, and the
standard CPU configuration is performed via the inline
configuration macros.

Change cpu_type from an enumeration into a pointer to the
CPU's get_info function, very similar to device behavior.
For now all CPUs are declared in cpuintrf.h, but 
eventually they should be declared in the CPU's header
file, and the driver should #include that header.

Added function cpu_get_type() to return the CPU type.

Changed several cpu_* functions into macros that call
through to the equivalent device_* function.

The device system now maintains a parallel list of devices
based on type, for faster iteration through all devices
of a given type.

Cleaned up code that looped over CPUs via the machine->cpu
array to now loop using the type-based device list.

Removed start/stop/reset/nvram functions from the 
device_config in favor of grabbing them as needed.

Cleaned up the generic interrupt_enable code to work with
CPU devices instead of numbers.

Mapped the devtag_* functions to device_* functions via
macros instead of parallel implementations.
2008-12-16 15:02:15 +00:00

2166 lines
67 KiB
C

/***************************************************************************
cubeqcpu.c
Implementation of the Cube Quest AM2901-based CPUs
TODO:
* Tidy up diassembly (split into different files?)
***************************************************************************/
#include "debugger.h"
#include "cubeqcpu.h"
#include "driver.h"
/***************************************************************************
CONSTANTS
***************************************************************************/
/* Am2901 Instruction Fields */
static const char *const ins[] =
{
"ADD ",
"SUBR ",
"SUBS ",
"OR ",
"AND ",
"NOTRS",
"EXOR ",
"EXNOR",
};
static const char *const src[] =
{
"A,Q",
"A,B",
"0,Q",
"0,B",
"0,A",
"D,A",
"D,Q",
"D,0",
};
static const char *const dst[] =
{
"QREG ",
"NOP ",
"RAMA ",
"RAMF ",
"RAMQD",
"RAMD ",
"RAMQU",
"RAMU ",
};
enum alu_src
{
AQ = 0,
AB = 1,
ZQ = 2,
ZB = 3,
ZA = 4,
DA = 5,
DQ = 6,
DZ = 7,
};
enum alu_ins
{
ADD = 0,
SUBR = 1,
SUBS = 2,
OR = 3,
AND = 4,
NOTRS = 5,
EXOR = 6,
EXNOR = 7,
};
enum alu_dst
{
QREG = 0,
NOP = 1,
RAMA = 2,
RAMF = 3,
RAMQD = 4,
RAMD = 5,
RAMQU = 6,
RAMU = 7,
};
/***************************************************************************
MACROS
***************************************************************************/
#define _BIT(x, n) ((x) & (1 << (n)))
/***************************************************************************
STRUCTURES & TYPEDEFS
***************************************************************************/
typedef struct
{
/* AM2901 internals */
UINT16 ram[16];
UINT16 q;
UINT16 f;
UINT16 y;
UINT32 cflag;
UINT32 vflag;
UINT8 pc; /* 2 x LS161 @ 6E, 6F */
UINT16 platch;
UINT8 rtnlatch; /* LS374 @ 5F */
UINT8 adrcntr; /* 2 x LS161 */
UINT16 adrlatch;
UINT16 dinlatch;
UINT16 ramwlatch;
UINT16 *sram;
int prev_ipram;
int prev_ipwrt;
cubeqst_dac_w_func dac_w;
UINT16 *sound_data;
const device_config *device;
const address_space *program;
int icount;
} cquestsnd_state;
typedef struct
{
/* AM2901 internals */
UINT16 ram[16];
UINT16 q;
UINT16 f;
UINT16 y;
UINT32 cflag;
UINT32 vflag;
UINT16 pc; /* 12-bit, but only 9 used */
UINT8 seqcnt; /* 4-bit counter */
UINT8 dsrclatch;
UINT8 rsrclatch;
UINT16 dynaddr; /* LS374 at 2D, 8D */
UINT16 dyndata; /* LS374 at 10B, 9B */
UINT16 yrlatch; /* LS374 at 9D, 10D */
UINT16 ydlatch; /* LS374 at 9C, 10C */
UINT16 dinlatch;
UINT8 divreg; /* LS74 at ? */
UINT16 linedata;
UINT16 lineaddr;
UINT16 *dram;
UINT16 *sram;
UINT8 prev_dred;
UINT8 prev_dwrt;
UINT8 wc;
UINT8 rc;
UINT8 clkcnt;
const device_config *device;
const device_config *lindevice;
const address_space *program;
int icount;
} cquestrot_state;
typedef struct
{
/* 12-bit AM2901 internals */
UINT16 ram[16];
UINT16 q;
UINT16 f;
UINT16 y;
UINT32 cflag;
UINT32 vflag;
UINT8 pc[2]; /* Two program counters; one for FG, other for BG */
UINT16 seqcnt; /* 12-bit */
UINT16 clatch; /* LS374 at 9E and 1-bit FF */
UINT8 zlatch; /* LS374 at 4H */
UINT16 xcnt;
UINT16 ycnt;
UINT8 sreg;
UINT16 fadlatch;
UINT16 badlatch;
UINT16 sramdlatch;
UINT8 fglatch;
UINT8 bglatch;
UINT8 gt0reg;
UINT8 fdxreg;
UINT32 field;
UINT32 clkcnt;
/* RAM */
UINT16 *sram;
UINT8 *ptr_ram;
UINT32 *e_stack;
UINT32 *o_stack;
const device_config *device;
const device_config *rotdevice;
const address_space *program;
int icount;
} cquestlin_state;
/***************************************************************************
MEMORY ACCESSORS FOR 68000
***************************************************************************/
WRITE16_DEVICE_HANDLER( cubeqcpu_sndram_w )
{
cquestsnd_state *cpustate = device->token;
COMBINE_DATA(&cpustate->sram[offset]);
}
READ16_DEVICE_HANDLER( cubeqcpu_sndram_r )
{
cquestsnd_state *cpustate = device->token;
return cpustate->sram[offset];
}
WRITE16_DEVICE_HANDLER( cubeqcpu_rotram_w )
{
cquestrot_state *cpustate = device->token;
COMBINE_DATA(&cpustate->dram[offset]);
}
READ16_DEVICE_HANDLER( cubeqcpu_rotram_r )
{
cquestrot_state *cpustate = device->token;
return cpustate->dram[offset];
}
/***************************************************************************
SOUND INITIALIZATION AND SHUTDOWN
***************************************************************************/
static STATE_POSTLOAD( cquestsnd_postload )
{
}
static void cquestsnd_state_register(const device_config *device)
{
cquestsnd_state *cpustate = device->token;
state_save_register_device_item_array(device, 0, cpustate->ram);
state_save_register_device_item(device, 0, cpustate->q);
state_save_register_device_item(device, 0, cpustate->f);
state_save_register_device_item(device, 0, cpustate->y);
state_save_register_device_item(device, 0, cpustate->cflag);
state_save_register_device_item(device, 0, cpustate->vflag);
state_save_register_device_item(device, 0, cpustate->pc);
state_save_register_device_item(device, 0, cpustate->platch);
state_save_register_device_item(device, 0, cpustate->rtnlatch);
state_save_register_device_item(device, 0, cpustate->adrcntr);
state_save_register_device_item(device, 0, cpustate->adrlatch);
state_save_register_device_item(device, 0, cpustate->dinlatch);
state_save_register_device_item(device, 0, cpustate->ramwlatch);
state_save_register_device_item(device, 0, cpustate->prev_ipram);
state_save_register_device_item(device, 0, cpustate->prev_ipwrt);
state_save_register_postload(device->machine, cquestsnd_postload, (void *)device);
}
static CPU_INIT( cquestsnd )
{
cquestsnd_state *cpustate = device->token;
cubeqst_snd_config* _config = (cubeqst_snd_config*)device->static_config;
memset(cpustate, 0, sizeof(*cpustate));
cpustate->dac_w = _config->dac_w;
cpustate->sound_data = (UINT16*)memory_region(device->machine, _config->sound_data_region);
cpustate->device = device;
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
/* Allocate RAM shared with 68000 */
cpustate->sram = auto_malloc(4096);
cquestsnd_state_register(device);
}
static CPU_RESET( cquestsnd )
{
cquestsnd_state *cpustate = device->token;
cpustate->pc = 0;
}
static CPU_EXIT( cquestsnd )
{
}
/***************************************************************************
ROTATE INITIALIZATION AND SHUTDOWN
***************************************************************************/
static STATE_POSTLOAD( cquestrot_postload )
{
}
static void cquestrot_state_register(const device_config *device)
{
cquestrot_state *cpustate = device->token;
state_save_register_device_item_array(device, 0, cpustate->ram);
state_save_register_device_item(device, 0, cpustate->q);
state_save_register_device_item(device, 0, cpustate->f);
state_save_register_device_item(device, 0, cpustate->y);
state_save_register_device_item(device, 0, cpustate->cflag);
state_save_register_device_item(device, 0, cpustate->vflag);
state_save_register_device_item(device, 0, cpustate->pc);
state_save_register_device_item(device, 0, cpustate->seqcnt);
state_save_register_device_item(device, 0, cpustate->dsrclatch);
state_save_register_device_item(device, 0, cpustate->rsrclatch);
state_save_register_device_item(device, 0, cpustate->dynaddr);
state_save_register_device_item(device, 0, cpustate->dyndata);
state_save_register_device_item(device, 0, cpustate->yrlatch);
state_save_register_device_item(device, 0, cpustate->ydlatch);
state_save_register_device_item(device, 0, cpustate->dinlatch);
state_save_register_device_item(device, 0, cpustate->divreg);
state_save_register_device_item(device, 0, cpustate->linedata);
state_save_register_device_item(device, 0, cpustate->lineaddr);
state_save_register_device_item(device, 0, cpustate->prev_dred);
state_save_register_device_item(device, 0, cpustate->prev_dwrt);
state_save_register_device_item(device, 0, cpustate->wc);
state_save_register_device_item_pointer(device, 0, cpustate->dram, 16384);
state_save_register_device_item_pointer(device, 0, cpustate->sram, 2048);
state_save_register_postload(device->machine, cquestrot_postload, (void *)device);
}
static CPU_INIT( cquestrot )
{
const cubeqst_rot_config *rotconfig = device->static_config;
cquestrot_state *cpustate = device->token;
memset(cpustate, 0, sizeof(*cpustate));
/* Allocate RAM */
cpustate->dram = auto_malloc(16384 * sizeof(UINT16)); /* Shared with 68000 */
cpustate->sram = auto_malloc(2048 * sizeof(UINT16)); /* Private */
cpustate->device = device;
cpustate->lindevice = cputag_get_cpu(device->machine, rotconfig->lin_cpu_tag);
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
cquestrot_state_register(device);
}
static CPU_RESET( cquestrot )
{
cquestrot_state *cpustate = device->token;
cpustate->pc = 0;
cpustate->wc = 0;
cpustate->prev_dred = 1;
cpustate->prev_dwrt = 1;
}
static CPU_EXIT( cquestrot )
{
}
/***************************************************************************
LINE DRAWER INITIALIZATION AND SHUTDOWN
***************************************************************************/
#define FOREGROUND 0
#define BACKGROUND 1
#define ODD_FIELD 0
#define EVEN_FIELD 1
static STATE_POSTLOAD( cquestlin_postload )
{
}
static void cquestlin_state_register(const device_config *device)
{
cquestlin_state *cpustate = device->token;
state_save_register_device_item_array(device, 0, cpustate->ram);
state_save_register_device_item(device, 0, cpustate->q);
state_save_register_device_item(device, 0, cpustate->f);
state_save_register_device_item(device, 0, cpustate->y);
state_save_register_device_item(device, 0, cpustate->cflag);
state_save_register_device_item(device, 0, cpustate->vflag);
state_save_register_device_item(device, 0, cpustate->pc[0]);
state_save_register_device_item(device, 0, cpustate->pc[1]);
state_save_register_device_item(device, 0, cpustate->seqcnt);
state_save_register_device_item(device, 0, cpustate->clatch);
state_save_register_device_item(device, 0, cpustate->zlatch);
state_save_register_device_item(device, 0, cpustate->xcnt);
state_save_register_device_item(device, 0, cpustate->ycnt);
state_save_register_device_item(device, 0, cpustate->sreg);
state_save_register_device_item(device, 0, cpustate->fadlatch);
state_save_register_device_item(device, 0, cpustate->badlatch);
state_save_register_device_item(device, 0, cpustate->sramdlatch);
state_save_register_device_item(device, 0, cpustate->fglatch);
state_save_register_device_item(device, 0, cpustate->bglatch);
state_save_register_device_item(device, 0, cpustate->gt0reg);
state_save_register_device_item(device, 0, cpustate->fdxreg);
state_save_register_device_item(device, 0, cpustate->field);
state_save_register_device_item(device, 0, cpustate->clkcnt);
state_save_register_device_item_pointer(device, 0, cpustate->sram, 4096);
state_save_register_device_item_pointer(device, 0, cpustate->ptr_ram, 1024);
state_save_register_device_item_pointer(device, 0, cpustate->e_stack, 32768);
state_save_register_device_item_pointer(device, 0, cpustate->o_stack, 32768);
state_save_register_postload(device->machine, cquestlin_postload, (void *)device);
}
static CPU_INIT( cquestlin )
{
const cubeqst_lin_config *linconfig = device->static_config;
cquestlin_state *cpustate = device->token;
memset(cpustate, 0, sizeof(*cpustate));
/* Allocate RAM */
cpustate->sram = auto_malloc(4096 * sizeof(UINT16)); /* Shared with rotate CPU */
cpustate->ptr_ram = auto_malloc(1024); /* Pointer RAM */
cpustate->e_stack = auto_malloc(32768 * sizeof(UINT32)); /* Stack DRAM: 32kx20 */
cpustate->o_stack = auto_malloc(32768 * sizeof(UINT32)); /* Stack DRAM: 32kx20 */
cpustate->device = device;
cpustate->rotdevice = cputag_get_cpu(device->machine, linconfig->rot_cpu_tag);
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
cquestlin_state_register(device);
}
static CPU_RESET( cquestlin )
{
cquestlin_state *cpustate = device->token;
cpustate->clkcnt = 0;
cpustate->pc[FOREGROUND] = 0;
cpustate->pc[BACKGROUND] = 0x80;
}
static CPU_EXIT( cquestlin )
{
}
/***************************************************************************
SOUND CORE EXECUTION LOOP
***************************************************************************/
#define SND_PC (cpustate->pc)
#define SND_DATA_IN (_ramen ? cpustate->sound_data[cpustate->platch] : cpustate->dinlatch)
enum snd_latch_type
{
PLTCH = 0,
DAC = 1,
ADLATCH = 2,
};
static int do_sndjmp(cquestsnd_state *cpustate, int jmp)
{
switch (jmp)
{
/* JUMP */ case 0: return 1;
/* MSB */ case 2: return cpustate->f & 0x8000 ? 0 : 1;
/* !MSB */ case 3: return cpustate->f & 0x8000 ? 1 : 0;
/* ZERO */ case 5: return cpustate->f == 0 ? 0 : 1;
/* OVR */ case 6: return cpustate->vflag ? 0 : 1;
/* LOOP */ case 7: return cpustate->adrcntr & 0x80 ? 0: 1;
}
return 0;
}
static CPU_EXECUTE( cquestsnd )
{
cquestsnd_state *cpustate = device->token;
int calldebugger = ((device->machine->debug_flags & DEBUG_FLAG_ENABLED) != 0);
cpustate->icount = cycles;
/* Core execution loop */
do
{
/* Decode the instruction */
UINT64 inst = memory_decrypted_read_qword(cpustate->program, SND_PC << 3);
UINT32 inslow = inst & 0xffffffff;
UINT32 inshig = inst >> 32;
int t = (inshig >> 24) & 0xff;
int b = (inshig >> 20) & 0xf;
int a = (inshig >> 16) & 0xf;
int ci = (inshig >> 15) & 1;
int i5_3 = (inshig >> 12) & 7;
int _ramen = (inshig >> 11) & 1;
int i2_0 = (inshig >> 8) & 7;
int rtnltch = (inshig >> 7) & 1;
int jmp = (inshig >> 4) & 7;
int inca = (inshig >> 3) & 1;
int i8_6 = (inshig >> 0) & 7;
int _ipram = (inslow >> 31) & 1;
int _ipwrt = (inslow >> 30) & 1;
int latch = (inslow >> 28) & 3;
int rtn = (inslow >> 27) & 1;
int _rin = (inslow >> 26) & 1;
if (calldebugger)
debugger_instruction_hook(device, cpustate->pc);
/* Don't think this matters, but just in case */
if (rtn)
t = cpustate->rtnlatch;
/* Handle the AM2901 ALU instruction */
{
UINT16 r = 0;
UINT16 s = 0;
UINT32 res = 0;
UINT32 cflag = 0;
UINT32 vflag = 0;
/* Determine the ALU sources */
switch (i2_0)
{
case AQ: r = cpustate->ram[a]; s = cpustate->q; break;
case AB: r = cpustate->ram[a]; s = cpustate->ram[b]; break;
case ZQ: r = 0; s = cpustate->q; break;
case ZB: r = 0; s = cpustate->ram[b]; break;
case ZA: r = 0; s = cpustate->ram[a]; break;
case DA: r = SND_DATA_IN; s = cpustate->ram[a]; break;
case DQ: r = SND_DATA_IN; s = cpustate->q; break;
case DZ: r = SND_DATA_IN; s = 0; break;
}
/* Perform the ALU operation */
switch (i5_3)
{
case ADD:
res = r + s + ci;
cflag = (res >> 16) & 1;
vflag = (((r & 0x7fff) + (s & 0x7fff) + ci) >> 15) ^ cflag;
break;
case SUBR:
res = ~r + s + ci;
cflag = (res >> 16) & 1;
vflag = (((s & 0x7fff) + (~r & 0x7fff) + ci) >> 15) ^ cflag;
break;
case SUBS:
res = r + ~s + ci;
cflag = (res >> 16) & 1;
vflag = (((r & 0x7fff) + (~s & 0x7fff) + ci) >> 15) ^ cflag;
break;
case OR:
res = r | s;
break;
case AND:
res = r & s;
break;
case NOTRS:
res = ~r & s;
break;
case EXOR:
res = r ^ s;
break;
case EXNOR:
res = ~(r ^ s);
break;
}
cpustate->f = res;
cpustate->cflag = cflag;
cpustate->vflag = vflag;
switch (i8_6)
{
case QREG:
cpustate->q = cpustate->f;
cpustate->y = cpustate->f;
break;
case NOP:
cpustate->y = cpustate->f;
break;
case RAMA:
cpustate->y = cpustate->ram[a];
cpustate->ram[b] = cpustate->f;
break;
case RAMF:
cpustate->ram[b] = cpustate->f;
cpustate->y = cpustate->f;
break;
case RAMQD:
{
UINT16 qin;
cpustate->ram[b] = (_rin ? 0 : 0x8000) | (cpustate->f >> 1);
cpustate->q >>= 1;
cpustate->y = cpustate->f;
/* When right shifting Q, we need to OR in a value */
qin = (((cpustate->y >> 15) ^ (cpustate->y >> 1)) & 1) ? 0 : 0x8000;
cpustate->q |= qin;
break;
}
case RAMD:
cpustate->ram[b] = (_rin ? 0 : 0x8000) | (cpustate->f >> 1);
cpustate->y = cpustate->f;
break;
case RAMQU:
cpustate->ram[b] = (cpustate->f << 1) | (_rin ? 0 : 0x0001);
cpustate->q <<= 1;
cpustate->y = cpustate->f;
break;
case RAMU:
cpustate->ram[b] = (cpustate->f << 1) | (_rin ? 0 : 0x0001);
cpustate->y = cpustate->f;
break;
}
}
/* Now handle any SRAM accesses from the previous cycle */
if (!cpustate->prev_ipram)
{
UINT16 addr = cpustate->adrlatch | (cpustate->adrcntr & 0x7f);
if (!cpustate->prev_ipwrt)
cpustate->sram[addr] = cpustate->ramwlatch;
else
cpustate->dinlatch = cpustate->sram[addr];
}
/* Handle latches */
if (latch == PLTCH)
{
cpustate->platch = ((t & 3) << 9) | ((cpustate->y >> 6) & 0x1ff);
}
else if (latch == DAC)
{
cpustate->dac_w(cpustate->device, (cpustate->y & 0xfff0) | ((cpustate->adrcntr >> 3) & 0xf));
}
else if (latch == ADLATCH)
{
/* Load the SRAM address counter - this value is instantly loaded */
cpustate->adrcntr = cpustate->y & 0x7f;
/* Also load the SRAM address latch */
cpustate->adrlatch = cpustate->y & 0x780;
}
/* Check for jump/return */
if ( do_sndjmp(cpustate, jmp) )
cpustate->pc = rtn ? cpustate->rtnlatch : t;
else
cpustate->pc++;
/* Load the return latch? (Obviously a load and a ret in the same cycle are invalid) */
if (rtnltch)
cpustate->rtnlatch = t;
/* Only increment the sound counter if not loading */
if (inca && latch != ADLATCH)
cpustate->adrcntr++;
/* Latch data for a RAM write (do actual write on the next cycle) */
if (!_ipwrt)
cpustate->ramwlatch = cpustate->y;
/* Save level sensitive bits */
cpustate->prev_ipram = _ipram;
cpustate->prev_ipwrt = _ipwrt;
cpustate->icount--;
} while (cpustate->icount > 0);
return cycles - cpustate->icount;
}
/***************************************************************************
SOUND DISASSEMBLY HOOK
***************************************************************************/
static CPU_DISASSEMBLE( cquestsnd )
{
static const char *const jmps[] =
{
"JUMP ",
" ",
"JMSB ",
"JNMSB",
" ",
"JZERO",
"JOVR ",
"JLOOP",
};
static const char *const latches[] =
{
"PLTCH ",
"DAC ",
"ADLATCH",
" ",
};
UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom);
UINT32 inslow = inst & 0xffffffff;
UINT32 inshig = inst >> 32;
int t = (inshig >> 24) & 0xff;
int b = (inshig >> 20) & 0xf;
int a = (inshig >> 16) & 0xf;
int ci = (inshig >> 15) & 1;
int i5_3 = (inshig >> 12) & 7;
int _ramen = (inshig >> 11) & 1;
int i2_0 = (inshig >> 8) & 7;
int rtnltch = (inshig >> 7) & 1;
int jmp = (inshig >> 4) & 7;
int inca = (inshig >> 3) & 1;
int i8_6 = (inshig >> 0) & 7;
int _ipram = (inslow >> 31) & 1;
int _ipwrt = (inslow >> 30) & 1;
int latch = (inslow >> 28) & 3;
int rtn = (inslow >> 27) & 1;
int _rin = (inslow >> 26) & 1;
sprintf(buffer, "%s %s %s %x,%x,%c %.2x %s %s %.2x %s %s %s %c %c %c\n",
ins[i5_3],
src[i2_0],
dst[i8_6],
a,
b,
ci ? 'C' : ' ',
_rin,
jmps[jmp],
rtn ? "RET" : " ",
t,
latches[latch],
rtnltch ? "RTLATCH" : " ",
_ramen ? "PROM" : "RAM ",
_ipram ? ' ' : 'R',
_ipwrt ? ' ' : 'W',
inca ? 'I' : ' ');
return 1 | DASMFLAG_SUPPORTED;
}
/***************************************************************************
ROTATE CORE EXECUTION LOOP
***************************************************************************/
#define ROT_PC (cpustate->pc & 0x1ff)
enum rot_spf
{
SPF_UNUSED0 = 0,
SPF_UNUSED1 = 1,
SPF_OP = 2,
SPF_RET = 3,
SPF_SQLTCH = 4,
SPF_SWRT = 5,
SPF_DIV = 6,
SPF_MULT = 7,
SPF_DRED = 8,
SPF_DWRT = 9,
};
enum rot_yout
{
YOUT_UNUSED0 = 0,
YOUT_UNUSED1 = 1,
YOUT_Y2LDA = 2,
YOUT_Y2LDD = 3,
YOUT_Y2DAD = 4,
YOUT_Y2DYN = 5,
YOUT_Y2R = 6,
YOUT_Y2D = 7,
};
/* Sync is asserted for the duration of every fourth cycle */
/* The Dynamic RAM latch clocks in a value at the end of this cycle */
/* So CPU waits for sync before reading from DRAM */
INLINE int do_rotjmp(cquestrot_state *cpustate, int jmp)
{
int ret = 0;
switch (jmp & 7)
{
/* */ case 0: ret = 0; break;
/* SEQ */ case 1: ret = (cpustate->seqcnt == 0xf); break;
/* CAROUT */ case 2: ret = cpustate->cflag; break;
/* SYNC */ case 3: ret = !(cpustate->clkcnt & 0x3); break;
/* LDWAIT */ case 4: ret = 0; break;
/* MSB */ case 5: ret = BIT(cpustate->f, 15); break;
/* >=1 */ case 6: ret = (!_BIT(cpustate->f, 15) && !(cpustate->f == 0)); break;
/* ZERO */ case 7: ret = (cpustate->f == 0); break;
}
return !(!ret ^ BIT(jmp, 3));
}
#define ROT_SRAM_ADDRESS ((cpustate->dsrclatch & 2) ? cpustate->yrlatch : (cpustate->rsrclatch | 0x700))
static CPU_EXECUTE( cquestrot )
{
cquestrot_state *cpustate = device->token;
cquestlin_state *lincpustate = cpustate->lindevice->token;
int calldebugger = ((device->machine->debug_flags & DEBUG_FLAG_ENABLED) != 0);
cpustate->icount = cycles;
/* Core execution loop */
do
{
/* Decode the instruction */
UINT64 inst = memory_decrypted_read_qword(cpustate->program, ROT_PC << 3);
UINT32 inslow = inst & 0xffffffff;
UINT32 inshig = inst >> 32;
int t = (inshig >> 20) & 0xfff;
int jmp = (inshig >> 16) & 0xf;
int spf = (inshig >> 12) & 0xf;
int rsrc = (inshig >> 11) & 0x1;
int yout = (inshig >> 8) & 0x7;
int sel = (inshig >> 6) & 0x3;
int dsrc = (inshig >> 4) & 0x3;
int b = (inshig >> 0) & 0xf;
int a = (inslow >> 28) & 0xf;
int i8_6 = (inslow >> 24) & 0x7;
int ci = (inslow >> 23) & 0x1;
int i5_3 = (inslow >> 20) & 0x7;
int _sex = (inslow >> 19) & 0x1;
int i2_0 = (inslow >> 16) & 0x7;
int dsrclatch;
UINT16 data_in = 0xffff;
if (calldebugger)
debugger_instruction_hook(device, ROT_PC);
/* Handle DRAM accesses - I ought to check this... */
if (!(cpustate->clkcnt & 3))
{
if (cpustate->wc)
{
cpustate->wc = 0;
cpustate->dram[cpustate->dynaddr & 0x3fff] = cpustate->dyndata;
}
if (cpustate->rc)
{
cpustate->rc = 0;
cpustate->dinlatch = cpustate->dram[cpustate->dynaddr & 0x3fff];
}
}
/* Flag pending DRAM accesses */
if (!cpustate->prev_dwrt)
cpustate->wc = 1;
else if (!cpustate->prev_dred)
cpustate->rc = 1;
/* What's on the D-Bus? */
if (~cpustate->dsrclatch & 0x10)
data_in = cpustate->dinlatch;
else if (~cpustate->dsrclatch & 0x20)
data_in = cpustate->sram[ROT_SRAM_ADDRESS];
else if (~cpustate->dsrclatch & 0x40)
data_in = cpustate->ydlatch;
else if (~cpustate->dsrclatch & 0x80)
data_in = t & 0xfff;
/* What's on the T-Bus? */
if ((spf == SPF_RET) && (cpustate->dsrclatch & 0x80))
t = data_in;
else if (spf == SPF_OP)
t = (t & ~0xf) | (data_in >> 12);
if (~cpustate->dsrclatch & 1)
cpustate->sram[ROT_SRAM_ADDRESS] = data_in;
/* Sign extend ALU input? */
if (!_sex)
data_in = (data_in & ~0xf000) | ((data_in & 0x800) ? 0xf000 : 0);
/* No do the ALU operation */
{
UINT16 r = 0;
UINT16 s = 0;
UINT32 res = 0;
UINT32 cflag = 0;
UINT32 vflag = 0;
/* First, determine correct I1 bit */
if ((spf == SPF_MULT) && !_BIT(cpustate->q, 0))
i2_0 |= 2;
/* Determine the ALU sources */
switch (i2_0)
{
case 0: r = cpustate->ram[a]; s = cpustate->q; break;
case 1: r = cpustate->ram[a]; s = cpustate->ram[b]; break;
case 2: r = 0; s = cpustate->q; break;
case 3: r = 0; s = cpustate->ram[b]; break;
case 4: r = 0; s = cpustate->ram[a]; break;
case 5: r = data_in; s = cpustate->ram[a]; break;
case 6: r = data_in; s = cpustate->q; break;
case 7: r = data_in; s = 0; break;
}
/* Next, determine the I3 and carry bits */
if ((spf == SPF_DIV) && cpustate->divreg)
{
i5_3 |= 1;
ci = 1;
}
/* Perform the ALU operation */
switch (i5_3)
{
case ADD:
res = r + s + ci;
cflag = (res >> 16) & 1;
vflag = (((r & 0x7fff) + (s & 0x7fff) + ci) >> 15) ^ cflag;
break;
case SUBR:
res = ~r + s + ci;
cflag = (res >> 16) & 1;
vflag = (((s & 0x7fff) + (~r & 0x7fff) + ci) >> 15) ^ cflag;
break;
case SUBS:
res = r + ~s + ci;
cflag = (res >> 16) & 1;
vflag = (((r & 0x7fff) + (~s & 0x7fff) + ci) >> 15) ^ cflag;
break;
case OR:
res = r | s;
break;
case AND:
res = r & s;
break;
case NOTRS:
res = ~r & s;
break;
case EXOR:
res = r ^ s;
break;
case EXNOR:
res = ~(r ^ s);
break;
}
cpustate->f = res;
cpustate->cflag = cflag;
cpustate->vflag = vflag;
switch (i8_6)
{
case QREG:
cpustate->q = cpustate->f;
cpustate->y = cpustate->f;
break;
case NOP:
cpustate->y = cpustate->f;
break;
case RAMA:
cpustate->y = cpustate->ram[a];
cpustate->ram[b] = cpustate->f;
break;
case RAMF:
cpustate->ram[b] = cpustate->f;
cpustate->y = cpustate->f;
break;
case RAMQD:
{
UINT16 q0 = cpustate->q & 1;
UINT16 r0 = cpustate->f & 1;
UINT16 q15 = 0;
UINT16 r15 = 0;
/* Determine Q15 and RAM15 */
switch (sel)
{
case 0: q15 = r15 = 0;
break;
case 1: q15 = r15 = 0x8000;
break;
case 2: q15 = q0 << 15;
r15 = r0 << 15;
break;
case 3: q15 = r0 << 15;
r15 = (cpustate->vflag ^ BIT(cpustate->f, 15)) << 15;
break;
}
cpustate->ram[b] = r15 | (cpustate->f >> 1);
cpustate->q = q15 | (cpustate->q >> 1);
cpustate->y = cpustate->f;
break;
}
case RAMD:
{
UINT16 r0 = cpustate->f & 1;
UINT16 r15 = 0;
switch (sel)
{
case 0: r15 = 0; break;
case 1: r15 = 0x8000; break;
case 2: r15 = r0 << 15; break;
case 3:
r15 = (cpustate->vflag ^ BIT(cpustate->f, 15)) << 15;
break;
}
cpustate->ram[b] = r15 | (cpustate->f >> 1);
cpustate->y = cpustate->f;
break;
}
case RAMQU:
{
UINT16 q15 = BIT(cpustate->q, 15);
UINT16 r15 = BIT(cpustate->f, 15);
UINT16 q0 = 0;
UINT16 r0 = 0;
switch (sel)
{
case 0: q0 = 0; r0 = 0; break;
case 1: q0 = 1; r0 = 1; break;
case 2: q0 = q15; r0 = r15; break;
case 3:
{
q0 = (spf == SPF_DIV) && !BIT(cpustate->f, 15);
r0 = q15;
break;
}
}
cpustate->ram[b] = (cpustate->f << 1) | r0;
cpustate->q = (cpustate->q << 1) | q0;
cpustate->y = cpustate->f;
break;
}
case RAMU:
{
UINT16 q15 = BIT(cpustate->q, 15);
UINT16 r15 = BIT(cpustate->f, 15);
UINT16 r0 = 0;
switch (sel)
{
case 0: r0 = 0; break;
case 1: r0 = 1; break;
case 2: r0 = r15; break;
case 3: r0 = q15; break;
}
cpustate->ram[b] = (cpustate->f << 1) | r0;
cpustate->y = cpustate->f;
break;
}
}
}
/* Check for jump */
if ( do_rotjmp(cpustate, jmp) )
cpustate->pc = t;
else
cpustate->pc = (cpustate->pc + 1) & 0xfff;
/* Rising edge; update the sequence counter */
if (spf == SPF_SQLTCH)
cpustate->seqcnt = t & 0xf;
else if ( (spf == SPF_MULT) || (spf == SPF_DIV) )
cpustate->seqcnt = (cpustate->seqcnt + 1) & 0xf;
/* Rising edge; write data source reg */
dsrclatch =
(~(0x10 << dsrc) & 0xf0)
| (rsrc ? 0x04 : 0x02)
| !(spf == SPF_SWRT);
/* R-latch is written on rising edge of dsrclatch bit 2 */
if (!_BIT(cpustate->dsrclatch, 2) && _BIT(dsrclatch, 2))
cpustate->rsrclatch = t & 0xff;
cpustate->dsrclatch = dsrclatch;
/* Handle latching on rising edge */
switch (yout)
{
case YOUT_Y2LDA:
{
cpustate->lineaddr = cpustate->y & 0xfff;
break;
}
case YOUT_Y2LDD:
{
cpustate->linedata = ((t & 0xf) << 12) | (cpustate->y & 0xfff);
lincpustate->sram[cpustate->lineaddr] = cpustate->linedata;
break;
}
case YOUT_Y2DAD: cpustate->dynaddr = cpustate->y & 0x3fff; break;
case YOUT_Y2DYN: cpustate->dyndata = cpustate->y & 0xffff; break;
case YOUT_Y2R: cpustate->yrlatch = cpustate->y & 0x7ff; break;
case YOUT_Y2D: cpustate->ydlatch = cpustate->y; break;
}
/* Clock in the divide register */
cpustate->divreg = (spf == SPF_DIV) && !_BIT(cpustate->f, 15);
/* DRAM accessing */
cpustate->prev_dred = !(spf == SPF_DRED);
cpustate->prev_dwrt = !(spf == SPF_DWRT);
cpustate->clkcnt++;
cpustate->icount--;
} while (cpustate->icount > 0);
return cycles - cpustate->icount;
}
/***************************************************************************
ROTATE DISASSEMBLY HOOK
***************************************************************************/
static CPU_DISASSEMBLE( cquestrot )
{
static const char *const jmps[] =
{
" ",
"JSEQ ",
"JC ",
"JSYNC ",
"JLDWAIT",
"JMSB ",
"JGEONE ",
"JZERO ",
"JUMP ",
"JNSEQ ",
"JNC ",
"JNSYNC ",
"JNLDWAI",
"JNMSB ",
"JLTONE ",
"JNZERO ",
};
static const char *const youts[] =
{
" ",
" ",
"Y2LDA",
"Y2LDD",
"Y2DAD",
"Y2DIN",
"Y2R ",
"Y2D ",
};
static const char *const spfs[] =
{
" ",
" ",
"OP ",
"RET ",
"SQLTCH",
"SWRT ",
"DIV ",
"MULT ",
"DRED ",
"DWRT ",
"??? ",
"??? ",
"??? ",
"??? ",
"??? ",
"??? "
};
UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom);
UINT32 inslow = inst & 0xffffffff;
UINT32 inshig = inst >> 32;
int t = (inshig >> 20) & 0xfff;
int jmp = (inshig >> 16) & 0xf;
int spf = (inshig >> 12) & 0xf;
// int rsrc = (inshig >> 11) & 0x1;
int yout = (inshig >> 8) & 0x7;
int sel = (inshig >> 6) & 0x3;
// int dsrc = (inshig >> 4) & 0x3;
int b = (inshig >> 0) & 0xf;
int a = (inslow >> 28) & 0xf;
int i8_6 = (inslow >> 24) & 0x7;
int ci = (inslow >> 23) & 0x1;
int i5_3 = (inslow >> 20) & 0x7;
// int _sex = (inslow >> 19) & 0x1;
int i2_0 = (inslow >> 16) & 0x7;
sprintf(buffer, "%s %s,%s %x,%x,%c %d %s %s %s %.2x\n",
ins[i5_3],
src[i2_0],
dst[i8_6],
a,
b,
ci ? 'C' : ' ',
sel,
jmps[jmp],
youts[yout],
spfs[spf],
t);
return 1 | DASMFLAG_SUPPORTED;
}
/***************************************************************************
LINE DRAWER CORE EXECUTION LOOP
***************************************************************************/
#define VISIBLE_FIELD !cpustate->field
enum line_spf
{
LSPF_UNUSUED = 0,
LSPF_FSTOP = 1,
LSPF_SREG = 2,
LSPF_FSTRT = 3,
LSPF_PWRT = 4,
LSPF_MULT = 5,
LSPF_LSTOP = 6,
LSPF_BRES = 7,
};
enum line_latch
{
LLATCH_UNUSED = 0,
LLATCH_SEQLATCH = 1,
LLATCH_XLATCH = 2,
LLATCH_YLATCH = 3,
LLATCH_BADLATCH = 4,
LLATCH_FADLATCH = 5,
LLATCH_CLATCH = 6,
LLATCH_ZLATCH = 7,
};
enum sreg_bits
{
SREG_E0 = 0,
SREG_DX_DY = 1,
SREG_DY = 2,
SREG_DX = 3,
SREG_LE0 = 4,
SREG_LDX_DY = 5,
SREG_LDY = 6,
SREG_LDX = 7,
};
INLINE int do_linjmp(cquestlin_state *cpustate, int jmp)
{
int ret = 0;
switch (jmp & 7)
{
/* */ case 0: ret = 0; break;
/* MSB */ case 1: ret = BIT(cpustate->f, 11); break;
/* SEQ */ case 2: ret = (cpustate->seqcnt == 0xfff); break;
/* >0 */ case 3: ret = !(cpustate->f == 0) && !_BIT(cpustate->f, 11); break;
/* CAROUT */ case 4: ret = (cpustate->cflag); break;
/* ZERO */ case 5: ret = (cpustate->f == 0); break;
}
return !(!ret ^ BIT(jmp, 3));
}
void cubeqcpu_swap_line_banks(const device_config *device)
{
cquestlin_state *cpustate = device->token;
cpustate->field = cpustate->field ^ 1;
}
void cubeqcpu_clear_stack(const device_config *device)
{
cquestlin_state *cpustate = device->token;
memset(&cpustate->ptr_ram[cpustate->field * 256], 0, 256);
}
UINT8 cubeqcpu_get_ptr_ram_val(const device_config *device, int i)
{
cquestlin_state *cpustate = device->token;
return cpustate->ptr_ram[(VISIBLE_FIELD * 256) + i];
}
UINT32* cubeqcpu_get_stack_ram(const device_config *device)
{
cquestlin_state *cpustate = device->token;
if (VISIBLE_FIELD == ODD_FIELD)
return cpustate->o_stack;
else
return cpustate->e_stack;
}
static CPU_EXECUTE( cquestlin )
{
#define LINE_PC ((cpustate->pc[prog] & 0x7f) | ((prog == BACKGROUND) ? 0x80 : 0))
cquestlin_state *cpustate = device->token;
cquestrot_state *rotcpustate = cpustate->rotdevice->token;
int calldebugger = ((device->machine->debug_flags & DEBUG_FLAG_ENABLED) != 0);
UINT32 *stack_ram;
UINT8 *ptr_ram;
/* Check the field and set the stack/pointer RAM pointers appropriately */
if (cpustate->field == ODD_FIELD)
{
stack_ram = cpustate->o_stack;
ptr_ram = &cpustate->ptr_ram[0];
}
else
{
stack_ram = cpustate->e_stack;
ptr_ram = &cpustate->ptr_ram[0x100];
}
cpustate->icount = cycles;
/* Core execution loop */
do
{
/* Are we executing the foreground or backgroud program? */
int prog = (cpustate->clkcnt & 3) ? BACKGROUND : FOREGROUND;
UINT64 inst = memory_decrypted_read_qword(cpustate->program, LINE_PC << 3);
UINT32 inslow = inst & 0xffffffff;
UINT32 inshig = inst >> 32;
int t = (inshig >> 24) & 0xff;
int jmp = (inshig >> 20) & 0xf;
int latch = (inshig >> 16) & 0x7;
int op = (inshig >> 15) & 0x1;
int spf = (inshig >> 12) & 0x7;
int b = (inshig >> 8) & 0xf;
int a = (inshig >> 4) & 0xf;
int i8_6 = (inshig >> 0) & 0x7;
int ci = (inslow >> 31) & 0x1;
int i5_3 = (inslow >> 28) & 0x7;
int _pbcs = (inslow >> 27) & 0x1;
int i2_0 = (inslow >> 24) & 0x7;
UINT16 data_in = 0;
if (calldebugger)
debugger_instruction_hook(device, cpustate->pc[prog]);
/* Handle accesses to and from shared SRAM */
if (prog == FOREGROUND)
{
if (!_BIT(cpustate->fglatch, 5))
data_in = cpustate->sram[cpustate->fadlatch];
else
data_in = rotcpustate->linedata;
}
else
{
if (!_BIT(cpustate->bglatch, 4))
cpustate->sram[cpustate->badlatch] = cpustate->sramdlatch;
else if (_BIT(cpustate->bglatch, 2))
data_in = cpustate->sram[cpustate->badlatch];
else
data_in = rotcpustate->linedata;
}
/* Handle a write to stack RAM (/DOWRT) */
if ((cpustate->clkcnt & 3) == 1)
{
if (_BIT(cpustate->fglatch, 4) && (cpustate->ycnt < 256))
{
/* 20-bit words */
UINT32 data;
UINT16 h = cpustate->xcnt;
UINT8 v = cpustate->ycnt & 0xff;
/* Clamp H between 0 and 319 */
if (h >= 320)
h = (h & 0x800) ? 0 : 319;
/* Stack word type depends on STOP/#START bit */
if ( _BIT(cpustate->fglatch, 3) )
data = (0 << 19) | (h << 8) | cpustate->zlatch;
else
data = (1 << 19) | ((cpustate->clatch & 0x100) << 9) | (h << 8) | (cpustate->clatch & 0xff);
stack_ram[(v << 7) | (ptr_ram[v] & 0x7f)] = data;
/* Also increment the pointer RAM entry. Note that it cannot exceed 128 */
ptr_ram[v] = (ptr_ram[v] + 1) & 0x7f;
}
}
/* Override T3-0? */
if (op)
t = (t & ~0xf) | (data_in >> 12);
/* Determine the correct I1 bit */
if ((spf == LSPF_MULT) && !_BIT(cpustate->q, 0))
i2_0 |= 2;
/* Determine A0 (BRESA0) */
if ((prog == FOREGROUND) && !_BIT(cpustate->fglatch, 2))
a |= cpustate->gt0reg;
/* Now do the ALU operation */
{
UINT16 r = 0;
UINT16 s = 0;
UINT16 res = 0;
UINT32 cflag = 0;
UINT32 vflag = 0;
/* Determine the ALU sources */
switch (i2_0)
{
case 0: r = cpustate->ram[a]; s = cpustate->q; break;
case 1: r = cpustate->ram[a]; s = cpustate->ram[b]; break;
case 2: r = 0; s = cpustate->q; break;
case 3: r = 0; s = cpustate->ram[b]; break;
case 4: r = 0; s = cpustate->ram[a]; break;
case 5: r = data_in; s = cpustate->ram[a]; break;
case 6: r = data_in; s = cpustate->q; break;
case 7: r = data_in; s = 0; break;
}
/* 12-bits */
r &= 0xfff;
s &= 0xfff;
/* Perform the 12-bit ALU operation */
switch (i5_3)
{
case ADD:
res = r + s + ci;
cflag = (res >> 12) & 1;
vflag = (((r & 0x7ff) + (s & 0x7ff) + ci) >> 11) ^ cflag;
break;
case SUBR:
res = (r ^ 0x0FFF) + s + ci;
cflag = (res >> 12) & 1;
vflag = (((s & 0x7ff) + (~r & 0x7ff) + ci) >> 11) ^ cflag;
break;
case SUBS:
res = r + (s ^ 0x0FFF) + ci;
cflag = (res >> 12) & 1;
vflag = (((r & 0x7ff) + (~s & 0x7ff) + ci) >> 11) ^ cflag;
break;
case OR:
res = r | s;
break;
case AND:
res = r & s;
break;
case NOTRS:
res = ~r & s;
break;
case EXOR:
res = r ^ s;
break;
case EXNOR:
res = ~(r ^ s);
break;
}
cpustate->f = res & 0xfff;
cpustate->cflag = cflag;
cpustate->vflag = vflag;
switch (i8_6)
{
case QREG:
cpustate->q = cpustate->f;
cpustate->y = cpustate->f;
break;
case NOP:
cpustate->y = cpustate->f;
break;
case RAMA:
cpustate->y = cpustate->ram[a];
cpustate->ram[b] = cpustate->f;
break;
case RAMF:
cpustate->ram[b] = cpustate->f;
cpustate->y = cpustate->f;
break;
case RAMQD:
{
UINT16 r11 = (BIT(cpustate->f, 11) ^ cpustate->vflag) ? 0x800 : 0;
UINT16 q11 = (prog == BACKGROUND) ? 0x800 : 0;
cpustate->ram[b] = r11 | (cpustate->f >> 1);
cpustate->q = q11 | (cpustate->q >> 1);
cpustate->y = cpustate->f;
break;
}
case RAMD:
{
UINT16 r11 = (BIT(cpustate->f, 11) ^ cpustate->vflag) ? 0x800 : 0;
cpustate->ram[b] = r11 | (cpustate->f >> 1);
cpustate->y = cpustate->f;
break;
}
case RAMQU:
{
/* Determine shift inputs */
UINT16 r0 = (prog == BACKGROUND);
/* This should never happen - Q0 will be invalid */
cpustate->ram[b] = (cpustate->f << 1) | r0;
cpustate->q = (cpustate->q << 1) | 0;
cpustate->y = cpustate->f;
break;
}
case RAMU:
{
UINT16 r0 = (prog == BACKGROUND);
cpustate->ram[b] = (cpustate->f << 1) | r0;
cpustate->y = cpustate->f;
break;
}
}
}
/* Adjust program counter */
if ( do_linjmp(cpustate, jmp) )
cpustate->pc[prog] = t & 0x7f;
else
cpustate->pc[prog] = (cpustate->pc[prog] + 1) & 0x7f;
if (prog == BACKGROUND)
cpustate->pc[prog] |= 0x80;
else
{
/* Handle events that happen during FG execution */
if (latch == LLATCH_XLATCH)
cpustate->xcnt = cpustate->y & 0xfff;
else
{
int _xcet;
int mux_sel = (BIT(cpustate->sreg, SREG_DX_DY) << 1) | (BIT(cpustate->sreg, SREG_DX) ^ BIT(cpustate->sreg, SREG_DY));
if (mux_sel == 0)
_xcet = !(spf == LSPF_BRES);
else if (mux_sel == 1)
_xcet = _BIT(cpustate->fglatch, 1);
else if (mux_sel == 2)
_xcet = !(cpustate->gt0reg && (spf == LSPF_BRES));
else
_xcet = _BIT(cpustate->fglatch, 0);
if (!_xcet)
cpustate->xcnt = (cpustate->xcnt + (_BIT(cpustate->sreg, SREG_DX) ? 1 : -1)) & 0xfff;
}
if (latch == LLATCH_YLATCH)
cpustate->ycnt = cpustate->y & 0xfff;
else
{
int _ycet;
int mux_sel = (BIT(cpustate->sreg, SREG_DX_DY) << 1) | (BIT(cpustate->sreg, SREG_DX) ^ BIT(cpustate->sreg, SREG_DY));
if (mux_sel == 0)
_ycet = !(cpustate->gt0reg && (spf == LSPF_BRES));
else if (mux_sel == 1)
_ycet = _BIT(cpustate->fglatch, 0);
else if (mux_sel == 2)
_ycet = !(spf == LSPF_BRES);
else
_ycet = _BIT(cpustate->fglatch, 1);
if (!_ycet)
cpustate->ycnt = (cpustate->ycnt + (_BIT(cpustate->sreg, SREG_DY) ? 1 : -1)) & 0xfff;
}
}
if (latch == LLATCH_CLATCH)
cpustate->clatch = cpustate->y & 0x1ff;
else if (latch == LLATCH_ZLATCH)
cpustate->zlatch = cpustate->y & 0xff;
else if (latch == LLATCH_FADLATCH)
cpustate->fadlatch = cpustate->y & 0xfff;
else if (latch == LLATCH_BADLATCH)
cpustate->badlatch = cpustate->y & 0xfff;
/* What about the SRAM dlatch? */
if ( !_BIT(cpustate->bglatch, 5) )
cpustate->sramdlatch = ((t & 0xf) << 12) | (cpustate->y & 0x0fff);
/* BG and FG latches */
if (prog == FOREGROUND)
{
int mux_sel = (!(spf == LSPF_FSTOP) << 1) | !(spf == LSPF_LSTOP);
int dowrt;
int start_stop;
/* Handle the stack write and start/stop mux */
if (mux_sel == 0)
{
dowrt = 0;
start_stop = 0;
}
else if (mux_sel == 1)
{
dowrt = cpustate->fdxreg ^ BIT(cpustate->sreg, SREG_DX);
start_stop = cpustate->fdxreg;
}
else if (mux_sel == 2)
{
dowrt = BIT(cpustate->sreg, SREG_LDX) ^ BIT(cpustate->sreg, SREG_DX);
start_stop = BIT(cpustate->sreg, SREG_DX);
}
else
{
dowrt = (spf == LSPF_BRES) && (_BIT(cpustate->sreg, SREG_DX_DY) || cpustate->gt0reg);
start_stop = BIT(cpustate->sreg, SREG_DY);
}
cpustate->fglatch =
(!(latch == LLATCH_FADLATCH) << 5)
| (dowrt << 4)
| (start_stop << 3)
| (_pbcs << 2)
| (!(spf == LSPF_BRES) << 1)
| !(cpustate->gt0reg && (spf == LSPF_BRES));
}
else
{
int _lpwrt = BIT(cpustate->bglatch, 5);
cpustate->bglatch =
(!(spf == LSPF_PWRT) << 5)
| (_lpwrt << 4)
| ((!_lpwrt || (!(spf == LSPF_PWRT) && (latch == LLATCH_BADLATCH))) << 2);
}
/* Clock-in another bit into the sign bit shifter? */
if (spf == LSPF_SREG)
{
/* The sign bit is inverted */
cpustate->sreg = (cpustate->sreg << 1) | !BIT(cpustate->f, 11);
/* Also latch the >0 reg */
cpustate->gt0reg = !(cpustate->f == 0) && !_BIT(cpustate->f, 11);
}
else if (spf == LSPF_FSTRT)
{
cpustate->fdxreg = BIT(cpustate->sreg, 3);
}
/* Load or increment sequence counter? */
if (latch == LLATCH_SEQLATCH)
{
cpustate->seqcnt = cpustate->y & 0xfff;
}
else if (spf == LSPF_BRES)
{
cpustate->seqcnt = (cpustate->seqcnt + 1) & 0xfff;
/* Also latch the >0 reg */
cpustate->gt0reg = !(cpustate->f == 0) && !_BIT(cpustate->f, 11);
}
cpustate->icount--;
cpustate->clkcnt++;
} while (cpustate->icount > 0);
return cycles - cpustate->icount;
}
/***************************************************************************
LINE DRAWER DISASSEMBLY HOOK
***************************************************************************/
static CPU_DISASSEMBLE( cquestlin )
{
static const char *const jmps[] =
{
" ",
"JMSB ",
"JSEQ ",
"JGTZ ",
"JC ",
"JZ ",
"?????",
"?????",
"JUMP ",
"JNMSB",
"JNSEQ",
"JLEZ ",
"JNC ",
"JNZ ",
"?????",
"?????",
};
static const char *const latches[] =
{
" ",
"SEQLTCH",
"XLTCH ",
"YLTCH ",
"BGLTCH ",
"FGLTCH ",
"CLTCH ",
"ZLTCH ",
};
static const char *const spfs[] =
{
" ",
"FSTOP ",
"FREG ",
"FSTART",
"PWRT ",
"MULT ",
"LSTOP ",
"BRES ",
};
UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom);
UINT32 inslow = inst & 0xffffffff;
UINT32 inshig = inst >> 32;
int t = (inshig >> 24) & 0xff;
int jmp = (inshig >> 20) & 0xf;
int latch = (inshig >> 16) & 0x7;
int op = (inshig >> 15) & 0x1;
int spf = (inshig >> 12) & 0x7;
int b = (inshig >> 8) & 0xf;
int a = (inshig >> 4) & 0xf;
int i8_6 = (inshig >> 0) & 0x7;
int ci = (inslow >> 31) & 0x1;
int i5_3 = (inslow >> 28) & 0x7;
int _pbcs = (inslow >> 27) & 0x1;
int i2_0 = (inslow >> 24) & 0x7;
sprintf(buffer, "%s %s,%s %x,%x %c %s %.2x %s %s %s %s\n",
ins[i5_3],
src[i2_0],
dst[i8_6],
a,
b,
ci ? 'C' : ' ',
jmps[jmp],
t,
latches[latch],
op ? "OP" : " ",
_pbcs ? " " : "PB",
spfs[spf]);
return 1 | DASMFLAG_SUPPORTED;
}
/**************************************************************************
* Sound set_info
**************************************************************************/
static CPU_SET_INFO( cquestsnd )
{
cquestsnd_state *cpustate = device->token;
switch (state)
{
/* --- the following bits of info are set as 64-bit signed integers --- */
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + CQUESTSND_PC: cpustate->pc = info->i; break;
case CPUINFO_INT_REGISTER + CQUESTSND_Q: cpustate->q = info->i; break;
case CPUINFO_INT_REGISTER + CQUESTSND_RTNLATCH: cpustate->rtnlatch = info->i; break;
case CPUINFO_INT_REGISTER + CQUESTSND_ADRCNTR: cpustate->adrcntr = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_DINLATCH: cpustate->dinlatch = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM0: cpustate->ram[0x0] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM1: cpustate->ram[0x1] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM2: cpustate->ram[0x2] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM3: cpustate->ram[0x3] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM4: cpustate->ram[0x4] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM5: cpustate->ram[0x5] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM6: cpustate->ram[0x6] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM7: cpustate->ram[0x7] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM8: cpustate->ram[0x8] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM9: cpustate->ram[0x9] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMA: cpustate->ram[0xa] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMB: cpustate->ram[0xb] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMC: cpustate->ram[0xc] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMD: cpustate->ram[0xd] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAME: cpustate->ram[0xe] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMF: cpustate->ram[0xf] = info->i; break;
}
}
/**************************************************************************
* Sound get_info
**************************************************************************/
CPU_GET_INFO( cquestsnd )
{
cquestsnd_state *cpustate = (device != NULL) ? device->token : NULL;
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cquestsnd_state); break;
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
case CPUINFO_INT_MAX_CYCLES: info->i = 1; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -3; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + CQUESTSND_PC: info->i = cpustate->pc; break;
case CPUINFO_INT_REGISTER + CQUESTSND_RTNLATCH: info->i = cpustate->rtnlatch; break;
case CPUINFO_INT_REGISTER + CQUESTSND_ADRCNTR: info->i = cpustate->adrcntr; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestsnd); break;
case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(cquestsnd); break;
case CPUINFO_PTR_RESET: info->reset = CPU_RESET_NAME(cquestsnd); break;
case CPUINFO_PTR_EXIT: info->exit = CPU_EXIT_NAME(cquestsnd); break;
case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestsnd); break;
case CPUINFO_PTR_BURN: info->burn = NULL; break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cquestsnd); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "Sound CPU");break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Cube Quest"); break;
case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break;
case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break;
case CPUINFO_STR_FLAGS: sprintf(info->s, "......."); break;
case CPUINFO_STR_REGISTER + CQUESTSND_PC: sprintf(info->s, "PC: %02X", cpustate->pc); break;
case CPUINFO_STR_REGISTER + CQUESTSND_Q: sprintf(info->s, "Q: %04X", cpustate->q); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RTNLATCH: sprintf(info->s, "RTN: %02X", cpustate->rtnlatch); break;
case CPUINFO_STR_REGISTER + CQUESTSND_ADRCNTR: sprintf(info->s, "CNT: %02X", cpustate->adrcntr); break;
case CPUINFO_STR_REGISTER + CQUESTSND_DINLATCH: sprintf(info->s, "DIN: %04X", cpustate->dinlatch); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM0: sprintf(info->s, "RAM[0]: %04X", cpustate->ram[0x0]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM1: sprintf(info->s, "RAM[1]: %04X", cpustate->ram[0x1]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM2: sprintf(info->s, "RAM[2]: %04X", cpustate->ram[0x2]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM3: sprintf(info->s, "RAM[3]: %04X", cpustate->ram[0x3]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM4: sprintf(info->s, "RAM[4]: %04X", cpustate->ram[0x4]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM5: sprintf(info->s, "RAM[5]: %04X", cpustate->ram[0x5]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM6: sprintf(info->s, "RAM[6]: %04X", cpustate->ram[0x6]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM7: sprintf(info->s, "RAM[7]: %04X", cpustate->ram[0x7]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM8: sprintf(info->s, "RAM[8]: %04X", cpustate->ram[0x8]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAM9: sprintf(info->s, "RAM[9]: %04X", cpustate->ram[0x9]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMA: sprintf(info->s, "RAM[A]: %04X", cpustate->ram[0xa]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMB: sprintf(info->s, "RAM[B]: %04X", cpustate->ram[0xb]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMC: sprintf(info->s, "RAM[C]: %04X", cpustate->ram[0xc]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMD: sprintf(info->s, "RAM[D]: %04X", cpustate->ram[0xd]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAME: sprintf(info->s, "RAM[E]: %04X", cpustate->ram[0xe]); break;
case CPUINFO_STR_REGISTER + CQUESTSND_RAMF: sprintf(info->s, "RAM[F]: %04X", cpustate->ram[0xf]); break;
}
}
/**************************************************************************
* Rotate set_info
**************************************************************************/
static CPU_SET_INFO( cquestrot )
{
cquestrot_state *cpustate = device->token;
switch (state)
{
/* --- the following bits of info are set as 64-bit signed integers --- */
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + CQUESTROT_PC: cpustate->pc = info->i; break;
case CPUINFO_INT_REGISTER + CQUESTROT_Q: cpustate->q = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM0: cpustate->ram[0x0] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM1: cpustate->ram[0x1] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM2: cpustate->ram[0x2] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM3: cpustate->ram[0x3] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM4: cpustate->ram[0x4] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM5: cpustate->ram[0x5] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM6: cpustate->ram[0x6] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM7: cpustate->ram[0x7] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM8: cpustate->ram[0x8] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM9: cpustate->ram[0x9] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMA: cpustate->ram[0xa] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMB: cpustate->ram[0xb] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMC: cpustate->ram[0xc] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMD: cpustate->ram[0xd] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAME: cpustate->ram[0xe] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMF: cpustate->ram[0xf] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_SEQCNT: cpustate->seqcnt = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_DYNADDR: cpustate->dynaddr = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_DYNDATA: cpustate->dyndata = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_YRLATCH: cpustate->yrlatch = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_YDLATCH: cpustate->ydlatch = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_DINLATCH: cpustate->dinlatch = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_DSRCLATCH:cpustate->dsrclatch = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTROT_RSRCLATCH:cpustate->rsrclatch = info->i; break;
}
}
/**************************************************************************
* Rotate get_info
**************************************************************************/
CPU_GET_INFO( cquestrot )
{
cquestrot_state *cpustate = (device != NULL) ? device->token : NULL;
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cquestrot_state); break;
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
case CPUINFO_INT_MAX_CYCLES: info->i = 1; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 9; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -3; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + CQUESTROT_PC: info->i = cpustate->pc; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestrot); break;
case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(cquestrot); break;
case CPUINFO_PTR_RESET: info->reset = CPU_RESET_NAME(cquestrot); break;
case CPUINFO_PTR_EXIT: info->exit = CPU_EXIT_NAME(cquestrot); break;
case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestrot); break;
case CPUINFO_PTR_BURN: info->burn = NULL; break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cquestrot); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "Rotate CPU");break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Cube Quest"); break;
case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break;
case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break;
case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c%c", cpustate->cflag ? 'C' : '.',
cpustate->vflag ? 'V' : '.',
cpustate->f ? '.' : 'Z'); break;
case CPUINFO_STR_REGISTER + CQUESTROT_PC: sprintf(info->s, "PC: %02X", cpustate->pc); break;
case CPUINFO_STR_REGISTER + CQUESTROT_Q: sprintf(info->s, "Q: %04X", cpustate->q); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM0: sprintf(info->s, "RAM[0]: %04X", cpustate->ram[0x0]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM1: sprintf(info->s, "RAM[1]: %04X", cpustate->ram[0x1]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM2: sprintf(info->s, "RAM[2]: %04X", cpustate->ram[0x2]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM3: sprintf(info->s, "RAM[3]: %04X", cpustate->ram[0x3]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM4: sprintf(info->s, "RAM[4]: %04X", cpustate->ram[0x4]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM5: sprintf(info->s, "RAM[5]: %04X", cpustate->ram[0x5]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM6: sprintf(info->s, "RAM[6]: %04X", cpustate->ram[0x6]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM7: sprintf(info->s, "RAM[7]: %04X", cpustate->ram[0x7]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM8: sprintf(info->s, "RAM[8]: %04X", cpustate->ram[0x8]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAM9: sprintf(info->s, "RAM[9]: %04X", cpustate->ram[0x9]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMA: sprintf(info->s, "RAM[A]: %04X", cpustate->ram[0xa]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMB: sprintf(info->s, "RAM[B]: %04X", cpustate->ram[0xb]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMC: sprintf(info->s, "RAM[C]: %04X", cpustate->ram[0xc]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMD: sprintf(info->s, "RAM[D]: %04X", cpustate->ram[0xd]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAME: sprintf(info->s, "RAM[E]: %04X", cpustate->ram[0xe]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RAMF: sprintf(info->s, "RAM[F]: %04X", cpustate->ram[0xf]); break;
case CPUINFO_STR_REGISTER + CQUESTROT_SEQCNT: sprintf(info->s, "SEQCNT: %01X", cpustate->seqcnt); break;
case CPUINFO_STR_REGISTER + CQUESTROT_DYNADDR: sprintf(info->s, "DYNADDR: %04X", cpustate->dynaddr); break;
case CPUINFO_STR_REGISTER + CQUESTROT_DYNDATA: sprintf(info->s, "DYNDATA: %04X", cpustate->dyndata); break;
case CPUINFO_STR_REGISTER + CQUESTROT_YRLATCH: sprintf(info->s, "YRLATCH: %04X", cpustate->yrlatch); break;
case CPUINFO_STR_REGISTER + CQUESTROT_YDLATCH: sprintf(info->s, "YDLATCH: %04X", cpustate->ydlatch); break;
case CPUINFO_STR_REGISTER + CQUESTROT_DINLATCH: sprintf(info->s, "DINLATCH: %04X", cpustate->dinlatch); break;
case CPUINFO_STR_REGISTER + CQUESTROT_DSRCLATCH:sprintf(info->s, "DSRCLATCH: %04X", cpustate->dsrclatch); break;
case CPUINFO_STR_REGISTER + CQUESTROT_RSRCLATCH:sprintf(info->s, "RSRCLATCH: %04X", cpustate->rsrclatch); break;
case CPUINFO_STR_REGISTER + CQUESTROT_LDADDR: sprintf(info->s, "LDADDR : %04X", cpustate->lineaddr); break;
case CPUINFO_STR_REGISTER + CQUESTROT_LDDATA: sprintf(info->s, "LDDATA : %04X", cpustate->linedata); break;
}
}
/**************************************************************************
* Line drawer set_info
**************************************************************************/
static CPU_SET_INFO( cquestlin )
{
cquestlin_state *cpustate = device->token;
switch (state)
{
/* --- the following bits of info are set as 64-bit signed integers --- */
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + CQUESTLIN_FGPC: cpustate->pc[FOREGROUND] = info->i; break;
case CPUINFO_INT_REGISTER + CQUESTLIN_BGPC: cpustate->pc[BACKGROUND] = info->i; break;
case CPUINFO_INT_REGISTER + CQUESTLIN_Q: cpustate->q = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM0: cpustate->ram[0x0] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM1: cpustate->ram[0x1] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM2: cpustate->ram[0x2] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM3: cpustate->ram[0x3] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM4: cpustate->ram[0x4] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM5: cpustate->ram[0x5] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM6: cpustate->ram[0x6] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM7: cpustate->ram[0x7] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM8: cpustate->ram[0x8] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM9: cpustate->ram[0x9] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMA: cpustate->ram[0xa] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMB: cpustate->ram[0xb] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMC: cpustate->ram[0xc] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMD: cpustate->ram[0xd] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAME: cpustate->ram[0xe] = info->i; break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMF: cpustate->ram[0xf] = info->i; break;
}
}
/**************************************************************************
* Line drawer get_info
**************************************************************************/
CPU_GET_INFO( cquestlin )
{
cquestlin_state *cpustate = (device != NULL) ? device->token : NULL;
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cquestlin_state); break;
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
case CPUINFO_INT_MAX_CYCLES: info->i = 1; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -3; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + CQUESTLIN_FGPC: info->i = cpustate->pc[cpustate->clkcnt & 3 ? BACKGROUND : FOREGROUND]; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_PTR_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestlin); break;
case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(cquestlin); break;
case CPUINFO_PTR_RESET: info->reset = CPU_RESET_NAME(cquestlin); break;
case CPUINFO_PTR_EXIT: info->exit = CPU_EXIT_NAME(cquestlin); break;
case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestlin); break;
case CPUINFO_PTR_BURN: info->burn = NULL; break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cquestlin); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "Line CPU"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Cube Quest"); break;
case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break;
case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break;
case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c%c|%cG", cpustate->cflag ? 'C' : '.',
cpustate->vflag ? 'V' : '.',
cpustate->f ? '.' : 'Z',
cpustate->clkcnt & 3 ? 'B' : 'F'); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_FGPC: sprintf(info->s, "FPC: %02X", cpustate->pc[FOREGROUND]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_BGPC: sprintf(info->s, "BPC: %02X", cpustate->pc[BACKGROUND]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_Q: sprintf(info->s, "Q: %04X", cpustate->q); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM0: sprintf(info->s, "RAM[0]: %04X", cpustate->ram[0x0]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM1: sprintf(info->s, "RAM[1]: %04X", cpustate->ram[0x1]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM2: sprintf(info->s, "RAM[2]: %04X", cpustate->ram[0x2]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM3: sprintf(info->s, "RAM[3]: %04X", cpustate->ram[0x3]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM4: sprintf(info->s, "RAM[4]: %04X", cpustate->ram[0x4]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM5: sprintf(info->s, "RAM[5]: %04X", cpustate->ram[0x5]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM6: sprintf(info->s, "RAM[6]: %04X", cpustate->ram[0x6]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM7: sprintf(info->s, "RAM[7]: %04X", cpustate->ram[0x7]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM8: sprintf(info->s, "RAM[8]: %04X", cpustate->ram[0x8]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAM9: sprintf(info->s, "RAM[9]: %04X", cpustate->ram[0x9]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMA: sprintf(info->s, "RAM[A]: %04X", cpustate->ram[0xa]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMB: sprintf(info->s, "RAM[B]: %04X", cpustate->ram[0xb]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMC: sprintf(info->s, "RAM[C]: %04X", cpustate->ram[0xc]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMD: sprintf(info->s, "RAM[D]: %04X", cpustate->ram[0xd]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAME: sprintf(info->s, "RAM[E]: %04X", cpustate->ram[0xe]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_RAMF: sprintf(info->s, "RAM[F]: %04X", cpustate->ram[0xf]); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_FADLATCH: sprintf(info->s, "FADDR: %04X", cpustate->fadlatch); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_BADLATCH: sprintf(info->s, "BADDR: %04X", cpustate->badlatch); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_SREG: sprintf(info->s, "SREG: %04X", cpustate->sreg); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_XCNT: sprintf(info->s, "XCNT: %03X", cpustate->xcnt); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_YCNT: sprintf(info->s, "YCNT: %03X", cpustate->ycnt); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_CLATCH: sprintf(info->s, "CLATCH: %04X", cpustate->clatch); break;
case CPUINFO_STR_REGISTER + CQUESTLIN_ZLATCH: sprintf(info->s, "ZLATCH: %04X", cpustate->zlatch); break;
}
}