Fixing a Gitsplosion
This commit is contained in:
parent
17277bb354
commit
133a5e7e82
BIN
core/bus.c
BIN
core/bus.c
Binary file not shown.
3177
core/cpu.c
3177
core/cpu.c
File diff suppressed because it is too large
Load Diff
441
core/vb.c
441
core/vb.c
|
@ -1,34 +1,35 @@
|
||||||
#ifdef VB_EXPORT
|
#ifndef VBAPI
|
||||||
#define VBAPI VB_EXPORT
|
#define VBAPI
|
||||||
#else
|
|
||||||
#define VBAPI
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Header includes */
|
|
||||||
#include <float.h>
|
|
||||||
#include <vb.h>
|
#include <vb.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************************* Constants *********************************/
|
/***************************** Utility Functions *****************************/
|
||||||
|
|
||||||
/* Type sizes */
|
/* Select the lesser of two unsigned numbers */
|
||||||
static const uint8_t TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
|
static uint32_t Min(uint32_t a, uint32_t b) {
|
||||||
|
return a < b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sign-extend an integer, masking upper bits if positive */
|
||||||
|
#ifndef VB_SIGNED_PROPAGATE
|
||||||
|
/* Generic implementation */
|
||||||
|
static int32_t SignExtend(int32_t value, int bits) {
|
||||||
|
return value & 1 << (bits - 1) ?
|
||||||
|
value | ~0 << bits :
|
||||||
|
value & ((1 << bits) - 1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Sign-propagating implementation */
|
||||||
|
#define SignExtend(v, b) ((int32_t) (v) << (32 - (b)) >> (32 - (b)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************************** Macros ***********************************/
|
/**************************** Sub-Module Imports *****************************/
|
||||||
|
|
||||||
/* Sign-extend a value of some number of bits to 32 bits */
|
|
||||||
#define SignExtend(v,b) \
|
|
||||||
((v) | (((v) & (1 << ((b) - 1))) ? (uint32_t) 0xFFFFFFFF << (b) : 0))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************** Subsystem Components ****************************/
|
|
||||||
|
|
||||||
/* Component includes */
|
|
||||||
#include "bus.c"
|
#include "bus.c"
|
||||||
#include "cpu.c"
|
#include "cpu.c"
|
||||||
|
|
||||||
|
@ -36,252 +37,246 @@ static const uint8_t TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
|
||||||
|
|
||||||
/***************************** Module Functions ******************************/
|
/***************************** Module Functions ******************************/
|
||||||
|
|
||||||
/* Process a simulation for some number of clocks */
|
/* Process a simulation for a given number of clocks */
|
||||||
static int sysEmulate(VB *sim, uint32_t clocks) {
|
static int sysEmulate(VB *vb, uint32_t clocks) {
|
||||||
int broke;
|
return
|
||||||
broke = cpuEmulate(sim, clocks);
|
cpuEmulate(vb, clocks)
|
||||||
return broke;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine the number of clocks before a break condititon could occur */
|
/* Determine how many clocks can be simulated without a breakpoint */
|
||||||
static uint32_t sysUntil(VB *sim, uint32_t clocks) {
|
static uint32_t sysUntil(VB *vb, uint32_t clocks) {
|
||||||
clocks = cpuUntil(sim, clocks);
|
clocks = cpuUntil(vb, clocks);
|
||||||
return clocks;
|
return clocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/******************************* API Functions *******************************/
|
/************************************ API ************************************/
|
||||||
|
|
||||||
/* Associate two simulations as peers, or remove an association */
|
/* Process a simulation */
|
||||||
void vbConnect(VB *sim1, VB *sim2) {
|
int vbEmulate(VB *vb, uint32_t *clocks) {
|
||||||
|
int brk; /* A break was requested */
|
||||||
|
uint32_t until; /* Number of clocks during which no break will occur */
|
||||||
|
|
||||||
/* Disconnect */
|
/* Process all clocks */
|
||||||
if (sim2 == NULL) {
|
for (brk = 0; *clocks != 0 && !brk; *clocks -= until) {
|
||||||
if (sim1->peer != NULL)
|
until = sysUntil (vb, *clocks);
|
||||||
sim1->peer->peer = NULL;
|
brk = sysEmulate(vb, until );
|
||||||
sim1->peer = NULL;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disconnect any existing link associations */
|
return brk;
|
||||||
if (sim1->peer != NULL && sim1->peer != sim2)
|
|
||||||
sim1->peer->peer = NULL;
|
|
||||||
if (sim2->peer != NULL && sim2->peer != sim1)
|
|
||||||
sim2->peer->peer = NULL;
|
|
||||||
|
|
||||||
/* Link the two simulations */
|
|
||||||
sim1->peer = sim2;
|
|
||||||
sim2->peer = sim1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process one simulation */
|
|
||||||
int vbEmulate(VB *sim, uint32_t *clocks) {
|
|
||||||
int broke; /* The simulation requested an application break */
|
|
||||||
uint32_t until; /* Maximum clocks before a break could happen */
|
|
||||||
|
|
||||||
/* Process the simulation until a break condition occurs */
|
|
||||||
do {
|
|
||||||
until = *clocks;
|
|
||||||
until = sysUntil (sim, until);
|
|
||||||
broke = sysEmulate(sim, until);
|
|
||||||
*clocks -= until;
|
|
||||||
} while (!broke && *clocks > 0);
|
|
||||||
|
|
||||||
return broke;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process multiple simulations */
|
/* Process multiple simulations */
|
||||||
int vbEmulateMulti(VB **sims, int count, uint32_t *clocks) {
|
int vbEmulateEx(VB **vbs, int count, uint32_t *clocks) {
|
||||||
int broke; /* The simulation requested an application break */
|
int brk; /* A break was requested */
|
||||||
uint32_t until; /* Maximum clocks before a break could happen */
|
uint32_t until; /* Number of clocks during which no break will occur */
|
||||||
int x; /* Iterator */
|
int x; /* Iterator */
|
||||||
|
|
||||||
/* Process simulations until a break condition occurs */
|
/* Process all clocks */
|
||||||
do {
|
for (brk = 0; *clocks != 0 && !brk; *clocks -= until) {
|
||||||
broke = 0;
|
|
||||||
until = *clocks;
|
until = *clocks;
|
||||||
for (x = 0; x < count; x++)
|
for (x = 0; x < count; x++)
|
||||||
until = sysUntil (sims[x], until);
|
until = sysUntil (vbs[x], until);
|
||||||
for (x = 0; x < count; x++)
|
for (x = 0; x < count; x++)
|
||||||
broke |= sysEmulate(sims[x], until);
|
brk |= sysEmulate(vbs[x], until);
|
||||||
*clocks -= until;
|
|
||||||
} while (!broke && *clocks > 0);
|
|
||||||
|
|
||||||
return broke;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve a current breakpoint callback */
|
|
||||||
void* vbGetCallback(VB *sim, int type) {
|
|
||||||
void **field; /* Pointer to field within simulation */
|
|
||||||
|
|
||||||
/* Select the field to update */
|
|
||||||
switch (type) {
|
|
||||||
case VB_ONEXCEPTION: field = (void *) &sim->onException; break;
|
|
||||||
case VB_ONEXECUTE : field = (void *) &sim->onExecute ; break;
|
|
||||||
case VB_ONFETCH : field = (void *) &sim->onFetch ; break;
|
|
||||||
case VB_ONREAD : field = (void *) &sim->onRead ; break;
|
|
||||||
case VB_ONWRITE : field = (void *) &sim->onWrite ; break;
|
|
||||||
default: return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve the simulation field */
|
return brk;
|
||||||
return *field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve the value of PC */
|
/* Retrieve a current breakpoint handler */
|
||||||
uint32_t vbGetProgramCounter(VB *sim) {
|
void* vbGetCallback(VB *vb, int id) {
|
||||||
return sim->cpu.pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve the value of a program register */
|
|
||||||
int32_t vbGetProgramRegister(VB *sim, int id) {
|
|
||||||
return id < 1 || id > 31 ? 0 : sim->cpu.program[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve the ROM buffer */
|
|
||||||
void* vbGetROM(VB *sim, uint32_t *size) {
|
|
||||||
if (size != NULL)
|
|
||||||
*size = sim->cart.romSize;
|
|
||||||
return sim->cart.rom;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve the SRAM buffer */
|
|
||||||
void* vbGetSRAM(VB *sim, uint32_t *size) {
|
|
||||||
if (size != NULL)
|
|
||||||
*size = sim->cart.sramSize;
|
|
||||||
return sim->cart.sram;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve the value of a system register */
|
|
||||||
uint32_t vbGetSystemRegister(VB *sim, int id) {
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case VB_ADTRE: return sim->cpu.adtre;
|
case VB_ONEXCEPTION: return *(void **)&vb->onException;
|
||||||
case VB_CHCW : return sim->cpu.chcw.ice << 1;
|
case VB_ONEXECUTE : return *(void **)&vb->onExecute;
|
||||||
case VB_EIPC : return sim->cpu.eipc;
|
case VB_ONFETCH : return *(void **)&vb->onFetch;
|
||||||
case VB_EIPSW: return sim->cpu.eipsw;
|
case VB_ONREAD : return *(void **)&vb->onRead;
|
||||||
case VB_FEPC : return sim->cpu.fepc;
|
case VB_ONWRITE : return *(void **)&vb->onWrite;
|
||||||
case VB_FEPSW: return sim->cpu.fepsw;
|
|
||||||
case VB_PIR : return 0x00005346;
|
|
||||||
case VB_TKCW : return 0x000000E0;
|
|
||||||
case 29 : return sim->cpu.sr29;
|
|
||||||
case 30 : return 0x00000004;
|
|
||||||
case 31 : return sim->cpu.sr31;
|
|
||||||
case VB_ECR : return
|
|
||||||
(uint32_t) sim->cpu.ecr.fecc << 16 | sim->cpu.ecr.eicc;
|
|
||||||
case VB_PSW : return
|
|
||||||
(uint32_t) sim->cpu.psw.i << 16 |
|
|
||||||
(uint32_t) sim->cpu.psw.np << 15 |
|
|
||||||
(uint32_t) sim->cpu.psw.ep << 14 |
|
|
||||||
(uint32_t) sim->cpu.psw.ae << 13 |
|
|
||||||
(uint32_t) sim->cpu.psw.id << 12 |
|
|
||||||
(uint32_t) sim->cpu.psw.fro << 9 |
|
|
||||||
(uint32_t) sim->cpu.psw.fiv << 8 |
|
|
||||||
(uint32_t) sim->cpu.psw.fzd << 7 |
|
|
||||||
(uint32_t) sim->cpu.psw.fov << 6 |
|
|
||||||
(uint32_t) sim->cpu.psw.fud << 5 |
|
|
||||||
(uint32_t) sim->cpu.psw.fpr << 4 |
|
|
||||||
(uint32_t) sim->cpu.psw.cy << 3 |
|
|
||||||
(uint32_t) sim->cpu.psw.ov << 2 |
|
|
||||||
(uint32_t) sim->cpu.psw.s << 1 |
|
|
||||||
(uint32_t) sim->cpu.psw.z
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare a simulation state instance for use */
|
/* Retrieve the value of a register */
|
||||||
void vbInit(VB *sim) {
|
int32_t vbGetRegister(VB *vb, int type, int id) {
|
||||||
|
switch (type) {
|
||||||
/* Breakpoint callbacks */
|
case VB_PROGRAM:
|
||||||
sim->onException = NULL;
|
return id < 0 || id > 31 ? 0 : vb->cpu.program[id];
|
||||||
sim->onExecute = NULL;
|
case VB_SYSTEM:
|
||||||
sim->onFetch = NULL;
|
return cpuGetSystemRegister(vb, id);
|
||||||
sim->onRead = NULL;
|
case VB_OTHER:
|
||||||
sim->onWrite = NULL;
|
switch (id) {
|
||||||
|
case VB_PC: return vb->cpu.pc;
|
||||||
/* System */
|
}
|
||||||
sim->peer = NULL;
|
}
|
||||||
|
return 0; /* Invalid type */
|
||||||
/* Cartridge */
|
|
||||||
sim->cart.rom = NULL;
|
|
||||||
sim->cart.romSize = 0;
|
|
||||||
sim->cart.sram = NULL;
|
|
||||||
sim->cart.sramSize = 0;
|
|
||||||
|
|
||||||
/* Everything else */
|
|
||||||
vbReset(sim);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read a data unit from the bus */
|
/* Retrieve a handle to the current cartridge ROM data */
|
||||||
int32_t vbRead(VB *sim, uint32_t address, int type, int debug) {
|
uint8_t* vbGetROM(VB *vb, uint32_t *size) {
|
||||||
return type < 0 || type >= (int) sizeof TYPE_SIZES ? 0 :
|
if (size != NULL)
|
||||||
busRead(sim, address, type, debug);
|
*size = vb->cart.romSize;
|
||||||
|
return vb->cart.rom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve a handle to the current cartridge RAM data */
|
||||||
|
uint8_t* vbGetSRAM(VB *vb, uint32_t *size) {
|
||||||
|
if (size != NULL)
|
||||||
|
*size = vb->cart.ramSize;
|
||||||
|
return vb->cart.ram;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prepare a simulation instance for use */
|
||||||
|
void vbInit(VB *vb) {
|
||||||
|
|
||||||
|
/* Breakpoint handlers */
|
||||||
|
vb->onException = NULL;
|
||||||
|
vb->onExecute = NULL;
|
||||||
|
vb->onFetch = NULL;
|
||||||
|
vb->onRead = NULL;
|
||||||
|
vb->onWrite = NULL;
|
||||||
|
|
||||||
|
/* Game pak */
|
||||||
|
vb->cart.ram = NULL;
|
||||||
|
vb->cart.ramSize = 0;
|
||||||
|
vb->cart.rom = NULL;
|
||||||
|
vb->cart.romSize = 0;
|
||||||
|
|
||||||
|
/* Hardware reset */
|
||||||
|
vbReset(vb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a value from memory */
|
||||||
|
int32_t vbRead(VB *vb, uint32_t address, int type) {
|
||||||
|
return busRead(vb, address, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read multiple bytes from memory */
|
||||||
|
void vbReadEx(VB *vb, uint32_t address, uint8_t *buffer, uint32_t length) {
|
||||||
|
while (length--) *buffer++ = busRead(vb, address++, VB_U8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simulate a hardware reset */
|
/* Simulate a hardware reset */
|
||||||
void vbReset(VB *sim) {
|
void vbReset(VB *vb) {
|
||||||
uint32_t x; /* Iterator */
|
int x; /* Iterator */
|
||||||
|
|
||||||
/* Subsystem components */
|
/* Reset WRAM (the hardware does not do this) */
|
||||||
cpuReset(sim);
|
|
||||||
|
|
||||||
/* WRAM (the hardware does not do this) */
|
|
||||||
for (x = 0; x < 0x10000; x++)
|
for (x = 0; x < 0x10000; x++)
|
||||||
sim->wram[x] = 0x00;
|
vb->wram[x] = 0x00;
|
||||||
|
|
||||||
|
/* CPU (normal) */
|
||||||
|
vb->cpu.pc = 0xFFFFFFF0;
|
||||||
|
cpuSetSystemRegister(vb, VB_ECR, 0x0000FFF0, 1);
|
||||||
|
cpuSetSystemRegister(vb, VB_PSW, 0x00008000, 1);
|
||||||
|
for (x = 0; x < 5; x++)
|
||||||
|
vb->cpu.irq[x] = 0;
|
||||||
|
|
||||||
|
/* CPU (extra, hardware doesn't do this) */
|
||||||
|
vb->cpu.adtre = 0x00000000;
|
||||||
|
vb->cpu.eipc = 0x00000000;
|
||||||
|
vb->cpu.eipsw = 0x00000000;
|
||||||
|
vb->cpu.fepc = 0x00000000;
|
||||||
|
vb->cpu.fepsw = 0x00000000;
|
||||||
|
vb->cpu.sr29 = 0x00000000;
|
||||||
|
vb->cpu.sr31 = 0x00000000;
|
||||||
|
cpuSetSystemRegister(vb, VB_CHCW, 0x00000000, 1);
|
||||||
|
for (x = 0; x < 32; x++)
|
||||||
|
vb->cpu.program[x] = 0x00000000;
|
||||||
|
|
||||||
|
/* CPU (internal) */
|
||||||
|
vb->cpu.bitstring = 0;
|
||||||
|
vb->cpu.clocks = 0;
|
||||||
|
vb->cpu.exception = 0;
|
||||||
|
vb->cpu.stage = CPU_FETCH;
|
||||||
|
vb->cpu.step = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Specify a breakpoint callback */
|
/* Specify a breakpoint handler */
|
||||||
void* vbSetCallback(VB *sim, int type, void *callback) {
|
void* vbSetCallback(VB *vb, int id, void *proc) {
|
||||||
void **field; /* Pointer to field within simulation */
|
void *prev = vbGetCallback(vb, id);
|
||||||
void *prev; /* Previous value within field */
|
switch (id) {
|
||||||
|
case VB_ONEXCEPTION: *(void **)&vb->onException = proc; break;
|
||||||
/* Select the field to update */
|
case VB_ONEXECUTE : *(void **)&vb->onExecute = proc; break;
|
||||||
switch (type) {
|
case VB_ONFETCH : *(void **)&vb->onFetch = proc; break;
|
||||||
case VB_ONEXCEPTION: field = (void *) &sim->onException; break;
|
case VB_ONREAD : *(void **)&vb->onRead = proc; break;
|
||||||
case VB_ONEXECUTE : field = (void *) &sim->onExecute ; break;
|
case VB_ONWRITE : *(void **)&vb->onWrite = proc; break;
|
||||||
case VB_ONFETCH : field = (void *) &sim->onFetch ; break;
|
|
||||||
case VB_ONREAD : field = (void *) &sim->onRead ; break;
|
|
||||||
case VB_ONWRITE : field = (void *) &sim->onWrite ; break;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the simulation field */
|
|
||||||
prev = *field;
|
|
||||||
*field = callback;
|
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Specify a new value for PC */
|
/* Specify a value for a register */
|
||||||
uint32_t vbSetProgramCounter(VB *sim, uint32_t value) {
|
int32_t vbSetRegister(VB *vb, int type, int id, int32_t value) {
|
||||||
value &= 0xFFFFFFFE;
|
switch (type) {
|
||||||
sim->cpu.busWait = 0;
|
case VB_PROGRAM:
|
||||||
sim->cpu.causeCode = 0;
|
return id < 1 || id > 31 ? 0 : (vb->cpu.program[id] = value);
|
||||||
sim->cpu.clocks = 0;
|
case VB_SYSTEM:
|
||||||
sim->cpu.fetch = 0;
|
return cpuSetSystemRegister(vb, id, value, 1);
|
||||||
sim->cpu.pc = value;
|
case VB_OTHER:
|
||||||
sim->cpu.state = CPU_FETCH;
|
switch (id) {
|
||||||
sim->cpu.substring = 0;
|
case VB_PC:
|
||||||
return value;
|
vb->cpu.bitstring = 0;
|
||||||
|
vb->cpu.clocks = 0;
|
||||||
|
vb->cpu.exception = 0;
|
||||||
|
vb->cpu.stage = CPU_FETCH;
|
||||||
|
return vb->cpu.pc = value & 0xFFFFFFFE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0; /* Invalid type or ID */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Specify a new value for a program register */
|
/* Specify a cartridge ROM buffer */
|
||||||
int32_t vbSetProgramRegister(VB *sim, int id, int32_t value) {
|
int vbSetROM(VB *vb, uint8_t *data, uint32_t size) {
|
||||||
return id < 1 || id > 31 ? 0 : (sim->cpu.program[id] = value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Supply a ROM buffer */
|
/* Specifying no ROM */
|
||||||
int vbSetROM(VB *sim, void *rom, uint32_t size) {
|
if (data == NULL) {
|
||||||
|
vb->cart.rom = NULL;
|
||||||
/* Check the buffer size */
|
vb->cart.romSize = 0;
|
||||||
if (size < 1024 || size > 0x1000000 || ((size - 1) & size) != 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Configure the ROM buffer */
|
/* Error checking */
|
||||||
sim->cart.rom = (uint8_t *) rom;
|
if (
|
||||||
sim->cart.romSize = size;
|
size < 4 ||
|
||||||
return 1;
|
size > 0x1000000 ||
|
||||||
|
(size & (size - 1)) /* Power of 2 */
|
||||||
|
) return 1;
|
||||||
|
|
||||||
|
/* Register the ROM data */
|
||||||
|
vb->cart.rom = data;
|
||||||
|
vb->cart.romSize = size;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Supply an SRAM buffer */
|
/* Specify a cartridge RAM buffer */
|
||||||
int vbSetSRAM(VB *sim, void *sram, uint32_t size)
|
int vbSetSRAM(VB *vb, uint8_t *data, uint32_t size) {
|
||||||
|
|
||||||
|
/* Specifying no SRAM */
|
||||||
|
if (data == NULL) {
|
||||||
|
vb->cart.ram = NULL;
|
||||||
|
vb->cart.ramSize = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error checking */
|
||||||
|
if (
|
||||||
|
size < 4 ||
|
||||||
|
size > 0x1000000 ||
|
||||||
|
(size & (size - 1)) /* Power of 2 */
|
||||||
|
) return 1;
|
||||||
|
|
||||||
|
/* Register the SRAM data */
|
||||||
|
vb->cart.ram = data;
|
||||||
|
vb->cart.ramSize = size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a value to memory */
|
||||||
|
void vbWrite(VB *vb, uint32_t address, int type, int32_t value) {
|
||||||
|
busWrite(vb, address, type, value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write multiple values to memory */
|
||||||
|
void vbWriteEx(VB *vb, uint32_t address, uint8_t *buffer, uint32_t length) {
|
||||||
|
while (length--) busWrite(vb, address++, VB_U8, *buffer++, 1);
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (C) 2022 Guy Perfect
|
Copyright (C) 2023 Guy Perfect
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
warranty. In no event will the authors be held liable for any damages
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
|
|
@ -146,6 +146,15 @@ class Core {
|
||||||
}, [], options);
|
}, [], options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieve the value of a program register
|
||||||
|
getSystemRegister(sim, id, options) {
|
||||||
|
return this.message({
|
||||||
|
command: "getProgramRegister",
|
||||||
|
id : id,
|
||||||
|
sim : sim.pointer
|
||||||
|
}, [], options);
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve the value of a system register
|
// Retrieve the value of a system register
|
||||||
getSystemRegister(sim, id, options) {
|
getSystemRegister(sim, id, options) {
|
||||||
return this.message({
|
return this.message({
|
||||||
|
@ -200,10 +209,10 @@ class Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specify a value for a program register
|
// Specify a value for a program register
|
||||||
setProgramRegister(sim, index, value, options) {
|
setProgramRegister(sim, id, value, options) {
|
||||||
return this.message({
|
return this.message({
|
||||||
command: "setProgramRegister",
|
command: "setProgramRegister",
|
||||||
index : index,
|
id : id,
|
||||||
sim : sim.pointer,
|
sim : sim.pointer,
|
||||||
value : value
|
value : value
|
||||||
}, [], options);
|
}, [], options);
|
||||||
|
|
|
@ -119,11 +119,11 @@ class CoreThread {
|
||||||
let program = new Int32Array (32);
|
let program = new Int32Array (32);
|
||||||
let system = new Uint32Array(32);
|
let system = new Uint32Array(32);
|
||||||
for (let x = 0; x < 32; x++) {
|
for (let x = 0; x < 32; x++) {
|
||||||
program[x] = this.vbGetProgramRegister(msg.sim, x);
|
program[x] = this.vbGetRegister(msg.sim, 0, x);
|
||||||
system [x] = this.vbGetSystemRegister (msg.sim, x);
|
system [x] = this.vbGetRegister(msg.sim, 1, x);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
pc : this.vbGetProgramCounter(msg.sim) >>> 0,
|
pc : this.vbGetRegister(msg.sim, 2, 0) >>> 0,
|
||||||
program : program,
|
program : program,
|
||||||
system : system,
|
system : system,
|
||||||
transfers: [ program.buffer, system.buffer ]
|
transfers: [ program.buffer, system.buffer ]
|
||||||
|
@ -132,12 +132,17 @@ class CoreThread {
|
||||||
|
|
||||||
// Retrieve the value of PC
|
// Retrieve the value of PC
|
||||||
getProgramCounter(msg) {
|
getProgramCounter(msg) {
|
||||||
return { value: this.vbGetProgramCounter(msg.sim) >>> 0 };
|
return { value: this.vbGetRegister(msg.sim, 2, 0) >>> 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the value of a program register
|
||||||
|
getProgramRegister(msg) {
|
||||||
|
return { value: this.vbGetRegister(msg.sim, 0, msg.id) };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the value of a system register
|
// Retrieve the value of a system register
|
||||||
getSystemRegister(msg) {
|
getSystemRegister(msg) {
|
||||||
return { value: this.vbGetSystemRegister(msg.sim, msg.id) >>> 0 };
|
return { value: this.vbGetRegister(msg.sim, 1, msg.id) >>> 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read multiple bytes from memory
|
// Read multiple bytes from memory
|
||||||
|
@ -214,19 +219,19 @@ class CoreThread {
|
||||||
|
|
||||||
let pcs = new Array(msg.sims.length);
|
let pcs = new Array(msg.sims.length);
|
||||||
for (let x = 0; x < msg.sims.length; x++)
|
for (let x = 0; x < msg.sims.length; x++)
|
||||||
pcs[x] = this.vbGetProgramCounter(msg.sims[x]) >>> 0;
|
pcs[x] = this.vbGetRegister(msg.sims[x], 2, 0) >>> 0;
|
||||||
|
|
||||||
return { pcs: pcs };
|
return { pcs: pcs };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specify a value for the program counter
|
// Specify a value for the program counter
|
||||||
setProgramCounter(msg) {
|
setProgramCounter(msg) {
|
||||||
return { value: this.vbSetProgramCounter(msg.sim, msg.value) >>> 0 };
|
return { value: this.vbSetRegister(msg.sim, 2, 0, msg.value) >>> 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specify a value for a program register
|
// Specify a value for a program register
|
||||||
setProgramRegister(msg) {
|
setProgramRegister(msg) {
|
||||||
return {value:this.vbSetProgramRegister(msg.sim,msg.index,msg.value)};
|
return { value: this.vbSetRegister(msg.sim, 0, msg.id, msg.value) };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specify a cartridge ROM buffer
|
// Specify a cartridge ROM buffer
|
||||||
|
@ -258,7 +263,7 @@ class CoreThread {
|
||||||
|
|
||||||
// Specify a value for a system register
|
// Specify a value for a system register
|
||||||
setSystemRegister(msg) {
|
setSystemRegister(msg) {
|
||||||
return {value:this.vbSetSystemRegister(msg.sim,msg.id,msg.value)>>>0};
|
return {value:this.vbSetRegister(msg.sim, 1, msg.id, msg.value)>>>0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the current instruction
|
// Execute the current instruction
|
||||||
|
@ -271,7 +276,7 @@ class CoreThread {
|
||||||
|
|
||||||
let pcs = new Array(msg.sims.length);
|
let pcs = new Array(msg.sims.length);
|
||||||
for (let x = 0; x < msg.sims.length; x++)
|
for (let x = 0; x < msg.sims.length; x++)
|
||||||
pcs[x] = this.vbGetProgramCounter(msg.sims[x]) >>> 0;
|
pcs[x] = this.vbGetRegister(msg.sims[x], 2, 0) >>> 0;
|
||||||
|
|
||||||
return { pcs: pcs };
|
return { pcs: pcs };
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,22 +41,22 @@ EMSCRIPTEN_KEEPALIVE int PointerSize() {
|
||||||
////////////////////////////// Debugger Commands //////////////////////////////
|
////////////////////////////// Debugger Commands //////////////////////////////
|
||||||
|
|
||||||
// Execute until the following instruction
|
// Execute until the following instruction
|
||||||
uint32_t RunNextAddress;
|
static uint32_t RunNextAddress;
|
||||||
static int RunNextFetch(VB *vb, int fetch, VBAccess *access) {
|
static int RunNextFetch(VB *vb, int fetch, VBAccess *access) {
|
||||||
return access->address == RunNextAddress;
|
return access->address == RunNextAddress;
|
||||||
}
|
}
|
||||||
static int RunNextExecute(VB *vb, VBInstruction *inst) {
|
static int RunNextExecute(VB *vb, VBInstruction *inst) {
|
||||||
RunNextAddress = inst->address + inst->size;
|
RunNextAddress = inst->address + inst->size;
|
||||||
vbSetOnExecute(vb, NULL);
|
vbSetCallback(vb, VB_ONEXECUTE, NULL);
|
||||||
vbSetOnFetch(vb, &RunNextFetch);
|
vbSetCallback(vb, VB_ONFETCH, &RunNextFetch);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EMSCRIPTEN_KEEPALIVE void RunNext(VB **vbs, int count) {
|
EMSCRIPTEN_KEEPALIVE void RunNext(VB **vbs, int count) {
|
||||||
uint32_t clocks = 20000000; // 1s
|
uint32_t clocks = 20000000; // 1s
|
||||||
vbSetOnExecute(vbs[0], &RunNextExecute);
|
vbSetCallback(vbs[0], VB_ONEXECUTE, &RunNextExecute);
|
||||||
vbEmulateEx (vbs, count, &clocks);
|
vbEmulateEx (vbs, count, &clocks);
|
||||||
vbSetOnExecute(vbs[0], NULL);
|
vbSetCallback(vbs[0], VB_ONEXECUTE, NULL);
|
||||||
vbSetOnFetch (vbs[0], NULL);
|
vbSetCallback(vbs[0], VB_ONFETCH , NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the current instruction
|
// Execute the current instruction
|
||||||
|
@ -72,7 +72,8 @@ static int SingleStepFetch(VB *vb, int fetch, VBAccess *access) {
|
||||||
EMSCRIPTEN_KEEPALIVE void SingleStep(VB **vbs, int count) {
|
EMSCRIPTEN_KEEPALIVE void SingleStep(VB **vbs, int count) {
|
||||||
uint32_t clocks = 20000000; // 1s
|
uint32_t clocks = 20000000; // 1s
|
||||||
SingleStepBreak = vbs[0]->cpu.stage == 0 ? 0 : 1;
|
SingleStepBreak = vbs[0]->cpu.stage == 0 ? 0 : 1;
|
||||||
vbSetOnFetch(vbs[0], &SingleStepFetch);
|
vbSetCallback(vbs[0], VB_ONFETCH, &SingleStepFetch);
|
||||||
vbEmulateEx (vbs, count, &clocks);
|
vbEmulateEx (vbs, count, &clocks);
|
||||||
vbSetOnFetch(vbs[0], NULL);
|
vbSetCallback(vbs[0], VB_ONEXECUTE, NULL);
|
||||||
|
vbSetCallback(vbs[0], VB_ONFETCH , NULL);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue