Adjusting top-level emulation logic, integrating breakpoints
This commit is contained in:
+106
-102
@@ -116,8 +116,8 @@ static vbool cpuFloatReserved(Vue *vue, vbool left) {
|
||||
)) continue;
|
||||
|
||||
/* The value is a reserved operand */
|
||||
vue->cpu.exception.code = 0xFF60;
|
||||
vue->cpu.psw_fro = 1;
|
||||
vue->cpu.exception = 0xFF60;
|
||||
vue->cpu.psw_fro = 1;
|
||||
return VUE_TRUE;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ static void cpuFloatConvert(Vue *vue, vbool round) {
|
||||
|
||||
/* Invalid operation (word overflow) */
|
||||
else if (bits >= 8) {
|
||||
vue->cpu.exception.code = 0xFF70;
|
||||
vue->cpu.exception = 0xFF70;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -193,8 +193,8 @@ static void cpuFloatResult(Vue *vue, vbool compare, double full) {
|
||||
|
||||
/* Overflow */
|
||||
if (full > result || full < -result) {
|
||||
vue->cpu.exception.code = 0xFF64;
|
||||
vue->cpu.psw_fov = 1;
|
||||
vue->cpu.exception = 0xFF64;
|
||||
vue->cpu.psw_fov = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -578,7 +578,7 @@ static void cpuDIV(Vue *vue) {
|
||||
|
||||
/* Zero division */
|
||||
if (right == 0) {
|
||||
vue->cpu.exception.code = 0xFF80;
|
||||
vue->cpu.exception = 0xFF80;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -612,7 +612,7 @@ static void cpuDIVF_S(Vue *vue) {
|
||||
|
||||
/* An exception has occurred */
|
||||
if (!right) {
|
||||
vue->cpu.exception.code = left ? 0xFF68 : 0xFF70;
|
||||
vue->cpu.exception = left ? 0xFF68 : 0xFF70;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -628,7 +628,7 @@ static void cpuDIVU(Vue *vue) {
|
||||
|
||||
/* Zero division */
|
||||
if (right == 0) {
|
||||
vue->cpu.exception.code = 0xFF80;
|
||||
vue->cpu.exception = 0xFF80;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -848,7 +848,7 @@ static void cpuREV(Vue *vue) {
|
||||
|
||||
/* Trap */
|
||||
#define cpuTRAP(vue) \
|
||||
vue->cpu.exception.code = 0xFFA0 | (vue->cpu.inst.imm & 15), \
|
||||
vue->cpu.exception = 0xFFA0 | (vue->cpu.inst.imm & 15), \
|
||||
vue->cpu.pc += 2
|
||||
|
||||
/* Truncate Short Floating to Word */
|
||||
@@ -908,8 +908,12 @@ static void cpuDecode(VueInstruction *inst) {
|
||||
x = inst->bits >> 16 & 31;
|
||||
inst->reg2 = inst->bits >> 21 & 31;
|
||||
inst->imm = extend < 0 ? SIGN_EXTEND(5, x) : x;
|
||||
if (inst->id == BITSTRING)
|
||||
if (inst->id == BITSTRING) {
|
||||
inst->id = x >= 16 ? VUE_ILLEGAL : LOOKUP_BITSTRING[x];
|
||||
inst->subopcode = x;
|
||||
}
|
||||
if (inst->id == VUE_SETF)
|
||||
inst->cond = x & 15;
|
||||
break;
|
||||
case 3:
|
||||
x = inst->bits >> 16 & 0x1FF;
|
||||
@@ -944,21 +948,84 @@ static void cpuDecode(VueInstruction *inst) {
|
||||
|
||||
}
|
||||
|
||||
/* Operations for exception stage */
|
||||
static vbool cpuException(Vue *vue) {
|
||||
vbool isIRQ; /* The exception is an interrupt */
|
||||
int32_t psw; /* Current value of PSW */
|
||||
|
||||
/* Application callback */
|
||||
if (vue->onException != NULL) {
|
||||
vue->breakCode = vue->onException(vue, vue->cpu.exception);
|
||||
if (vue->breakCode != 0)
|
||||
return VUE_TRUE;
|
||||
}
|
||||
|
||||
/* Configure working variables */
|
||||
vue->cpu.exception &= 0xFFFF;
|
||||
isIRQ = (vue->cpu.exception & 0xFF00) == 0xFE00;
|
||||
psw = cpuGetSystemRegister(vue, VUE_PSW);
|
||||
|
||||
/* Fatal exception */
|
||||
if (vue->cpu.psw_np != 0) {
|
||||
vueWrite(vue, 0x00000000, VUE_S32, 0xFFFF0000 | vue->cpu.exception);
|
||||
vueWrite(vue, 0x00000004, VUE_S32, psw);
|
||||
vueWrite(vue, 0x00000008, VUE_S32, vue->cpu.pc);
|
||||
vue->cpu.stage = CPU_FATAL;
|
||||
return VUE_TRUE;
|
||||
}
|
||||
|
||||
/* Duplexed exception */
|
||||
if (vue->cpu.psw_ep != 0) {
|
||||
vue->cpu.ecr_fecc = vue->cpu.exception;
|
||||
vue->cpu.fepc = vue->cpu.pc;
|
||||
vue->cpu.fepsw = psw;
|
||||
vue->cpu.psw_np = 1;
|
||||
vue->cpu.pc = 0xFFFFFFD0;
|
||||
}
|
||||
|
||||
/* Regular exception */
|
||||
else {
|
||||
vue->cpu.ecr_eicc = vue->cpu.exception;
|
||||
vue->cpu.eipc = vue->cpu.pc;
|
||||
vue->cpu.eipsw = psw;
|
||||
vue->cpu.psw_ep = 1;
|
||||
vue->cpu.pc = 0xFFFF0000 | (vue->cpu.exception & 0xFFF0);
|
||||
if (vue->cpu.pc == (int32_t) 0xFFFFFF70) /* FIV */
|
||||
vue->cpu.pc = 0xFFFFFF60;
|
||||
}
|
||||
|
||||
/* Interrupt */
|
||||
if (isIRQ) {
|
||||
psw = vue->cpu.exception >> 4 & 15;
|
||||
vue->cpu.psw_i = psw < 15 ? psw : 15;
|
||||
if (vue->cpu.stage == CPU_HALT)
|
||||
vue->cpu.pc += 2;
|
||||
}
|
||||
|
||||
/* Common processing */
|
||||
vue->cpu.cycles = 0; /* TODO: Determine the actual number */
|
||||
vue->cpu.exception = 0;
|
||||
vue->cpu.psw_ae = 0;
|
||||
vue->cpu.psw_id = 1;
|
||||
vue->cpu.stage = CPU_FETCH;
|
||||
return VUE_FALSE;
|
||||
}
|
||||
|
||||
/* Check for an exception or interrupt */
|
||||
static vbool cpuTestException(Vue *vue) {
|
||||
int32_t level; /* Interrupt level */
|
||||
|
||||
/* Check for an interrupt */
|
||||
if (vue->cpu.irq != 0 && (vue->cpu.exception.code |
|
||||
if (vue->cpu.irq != 0 && (vue->cpu.exception |
|
||||
vue->cpu.psw_id | vue->cpu.psw_ep | vue->cpu.psw_np) == 0) {
|
||||
for (level = 4; level >= 0; level--)
|
||||
if ((vue->cpu.irq >> level & 1) != 0)
|
||||
break;
|
||||
vue->cpu.exception.code = 0xFE00 | level << 4;
|
||||
vue->cpu.exception = 0xFE00 | level << 4;
|
||||
}
|
||||
|
||||
/* There is no exception */
|
||||
if (vue->cpu.exception.code == 0) /* No further processing */
|
||||
if (vue->cpu.exception == 0) /* No further processing */
|
||||
return vue->cpu.stage == CPU_HALT && vue->cpu.cycles == 0;
|
||||
|
||||
/* An exception has occurred */
|
||||
@@ -975,8 +1042,6 @@ static vbool cpuExecute(Vue *vue) {
|
||||
vue->breakCode = vue->onExecute(vue, &vue->cpu.inst);
|
||||
if (vue->breakCode != 0)
|
||||
return VUE_TRUE;
|
||||
vue->cpu.inst.reg1 &= 31;
|
||||
vue->cpu.inst.reg2 &= 31;
|
||||
}
|
||||
|
||||
/* Processing by instruction ID */
|
||||
@@ -1058,11 +1123,11 @@ static vbool cpuExecute(Vue *vue) {
|
||||
case VUE_XORI : cpuXORI (vue); break;
|
||||
/*case VUE_XORNBSU: cpuXORNBSU(vue); break;*/
|
||||
default: /* Invalid instruction */
|
||||
vue->cpu.exception.code = 0xFF90;
|
||||
vue->cpu.exception = 0xFF90;
|
||||
}
|
||||
|
||||
/* Common processing */
|
||||
if (vue->cpu.exception.code == 0) {
|
||||
if (vue->cpu.exception == 0) {
|
||||
vue->cpu.cycles += CYCLES[vue->cpu.inst.id];
|
||||
vue->cpu.pc += vue->cpu.inst.size;
|
||||
}
|
||||
@@ -1082,10 +1147,15 @@ static int32_t cpuSize(int32_t opcode) {
|
||||
/* Operations for fetch stage */
|
||||
static vbool cpuFetch(Vue *vue) {
|
||||
|
||||
/* Entering the fetch stage */
|
||||
if (vue->cpu.fetch == -1)
|
||||
vue->cpu.fetch = 0;
|
||||
|
||||
/* Read the bits from the bus */
|
||||
if (cpuRead(vue, vue->cpu.pc + (vue->cpu.fetch << 1),
|
||||
VUE_U16, vue->cpu.fetch))
|
||||
return VUE_TRUE;
|
||||
/* TODO: Determine how many cycles this takes */
|
||||
|
||||
/* First unit */
|
||||
if (vue->cpu.fetch == 0) {
|
||||
@@ -1099,7 +1169,7 @@ static vbool cpuFetch(Vue *vue) {
|
||||
/* Second unit */
|
||||
else {
|
||||
vue->cpu.inst.bits |= vue->cpu.access.value & 0xFFFF;
|
||||
vue->cpu.fetch = 0;
|
||||
vue->cpu.fetch = -1;
|
||||
}
|
||||
|
||||
/* Decode the instruction and advance to execute stage */
|
||||
@@ -1108,94 +1178,30 @@ static vbool cpuFetch(Vue *vue) {
|
||||
return VUE_FALSE;
|
||||
}
|
||||
|
||||
/* Operations for exception stage */
|
||||
static vbool cpuException(Vue *vue) {
|
||||
vbool isIRQ; /* The exception is an interrupt */
|
||||
int32_t psw; /* Current value of PSW */
|
||||
|
||||
/* Application callback */
|
||||
if (vue->onException != NULL) {
|
||||
vue->breakCode = vue->onException(vue, &vue->cpu.exception);
|
||||
if (vue->breakCode != 0)
|
||||
return VUE_TRUE;
|
||||
}
|
||||
|
||||
/* Configure working variables */
|
||||
vue->cpu.exception.code &= 0xFFFF;
|
||||
isIRQ = (vue->cpu.exception.code & 0xFF00) == 0xFE00;
|
||||
psw = cpuGetSystemRegister(vue, VUE_PSW);
|
||||
|
||||
/* Fatal exception */
|
||||
if (vue->cpu.psw_np != 0) {
|
||||
vueWrite(vue, 0x00000000, VUE_S32, 0xFFFF0000|vue->cpu.exception.code);
|
||||
vueWrite(vue, 0x00000004, VUE_S32, psw);
|
||||
vueWrite(vue, 0x00000008, VUE_S32, vue->cpu.pc);
|
||||
vue->cpu.stage = CPU_FATAL;
|
||||
return VUE_TRUE;
|
||||
}
|
||||
|
||||
/* Duplexed exception */
|
||||
if (vue->cpu.psw_ep != 0) {
|
||||
vue->cpu.ecr_fecc = vue->cpu.exception.code;
|
||||
vue->cpu.fepc = vue->cpu.pc;
|
||||
vue->cpu.fepsw = psw;
|
||||
vue->cpu.psw_np = 1;
|
||||
vue->cpu.pc = 0xFFFFFFD0;
|
||||
}
|
||||
|
||||
/* Regular exception */
|
||||
else {
|
||||
vue->cpu.ecr_eicc = vue->cpu.exception.code;
|
||||
vue->cpu.eipc = vue->cpu.pc;
|
||||
vue->cpu.eipsw = psw;
|
||||
vue->cpu.psw_ep = 1;
|
||||
vue->cpu.pc = 0xFFFF0000 | (vue->cpu.exception.code & 0xFFF0);
|
||||
if (vue->cpu.pc == (int32_t) 0xFFFFFF70) /* FIV */
|
||||
vue->cpu.pc = 0xFFFFFF60;
|
||||
}
|
||||
|
||||
/* Interrupt */
|
||||
if (isIRQ) {
|
||||
psw = vue->cpu.exception.code >> 4 & 15;
|
||||
vue->cpu.psw_i = psw < 15 ? psw : 15;
|
||||
if (vue->cpu.stage == CPU_HALT)
|
||||
vue->cpu.pc += 2;
|
||||
}
|
||||
|
||||
/* Common processing */
|
||||
vue->cpu.cycles = 0; /* TODO: Determine the actual number */
|
||||
vue->cpu.exception.code = 0;
|
||||
vue->cpu.psw_ae = 0;
|
||||
vue->cpu.psw_id = 1;
|
||||
vue->cpu.stage = CPU_FETCH;
|
||||
return VUE_FALSE;
|
||||
}
|
||||
|
||||
/* Process the simulation */
|
||||
static void cpuEmulate(Vue *vue, int32_t cycles) {
|
||||
static void cpuEmulate(Vue *vue, uint32_t cycles) {
|
||||
|
||||
/* The CPU is halting */
|
||||
if (vue->cpu.stage == CPU_FATAL || vue->cpu.stage == CPU_HALT)
|
||||
/* The CPU is in fatal halt status */
|
||||
if (vue->cpu.stage == CPU_FATAL)
|
||||
return;
|
||||
|
||||
vue->cpu.cycles = 0; /* DEBUG: Stop processing after execute */
|
||||
|
||||
/* Process for the given number of cycles */
|
||||
for (;;) {
|
||||
|
||||
/* The next event occurs after the given number of cycles */
|
||||
/* The next stage occurs after the given number of cycles */
|
||||
if (vue->cpu.cycles > cycles) {
|
||||
vue->cpu.cycles -= cycles;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Processing by stage */
|
||||
cycles -= vue->cpu.cycles;
|
||||
vue->cpu.cycles = 0;
|
||||
switch (vue->cpu.stage) {
|
||||
case CPU_EXCEPTION: if (cpuException (vue)) return; break;
|
||||
case CPU_EXECUTE : if (cpuExecute (vue)) return; break;
|
||||
case CPU_FETCH : if (cpuFetch (vue)) return; break;
|
||||
case CPU_HALT : if (cpuTestException(vue)) return; break;
|
||||
case CPU_EXCEPTION: if (cpuException(vue)) return; break;
|
||||
case CPU_EXECUTE : if (cpuExecute (vue)) return; break;
|
||||
case CPU_FETCH : if (cpuFetch (vue)) return; break;
|
||||
case CPU_HALT : cpuTestException(vue); return;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1207,11 +1213,11 @@ static void cpuReset(Vue *vue) {
|
||||
int32_t x;
|
||||
|
||||
/* Configure instance fields */
|
||||
vue->cpu.cycles = 0;
|
||||
vue->cpu.exception.code = 0;
|
||||
vue->cpu.fetch = 0;
|
||||
vue->cpu.irq = 0;
|
||||
vue->cpu.stage = CPU_FETCH;
|
||||
vue->cpu.cycles = 0;
|
||||
vue->cpu.exception = 0;
|
||||
vue->cpu.fetch = -1;
|
||||
vue->cpu.irq = 0;
|
||||
vue->cpu.stage = CPU_FETCH;
|
||||
|
||||
/* Clear all registers (hardware only sets ECR, PC and PSW) */
|
||||
for (x = 0; x < 32; x++) {
|
||||
@@ -1229,12 +1235,10 @@ static void cpuReset(Vue *vue) {
|
||||
vue->cpu.psw_np = 1;
|
||||
}
|
||||
|
||||
/* Determine the number of CPU cycles until something can happen */
|
||||
static int32_t cpuUntil(Vue *vue, int32_t cycles) {
|
||||
if (vue->cpu.stage == CPU_FATAL || vue->cpu.stage == CPU_HALT)
|
||||
return cycles;
|
||||
return cycles < 0 ? vue->cpu.cycles :
|
||||
cycles < vue->cpu.cycles ? cycles : vue->cpu.cycles;
|
||||
/* Determine the number of CPU cycles until a breakpoint could trigger */
|
||||
static uint32_t cpuUntil(Vue *vue, uint32_t cycles) {
|
||||
return vue->cpu.stage == CPU_FATAL || vue->cpu.stage == CPU_HALT ?
|
||||
cycles : cycles < vue->cpu.cycles ? cycles : vue->cpu.cycles;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+27
-29
@@ -154,11 +154,6 @@ typedef struct {
|
||||
int8_t type; /* Data type */
|
||||
} VueAccess;
|
||||
|
||||
/* Exception state */
|
||||
typedef struct {
|
||||
uint16_t code; /* Exception code */
|
||||
} VueException;
|
||||
|
||||
/* Instruction state */
|
||||
typedef struct {
|
||||
int32_t bits; /* Binary encoding */
|
||||
@@ -174,31 +169,32 @@ typedef struct {
|
||||
uint8_t subopcode; /* Instruction subopcode */
|
||||
} VueInstruction;
|
||||
|
||||
/* Callbacks */
|
||||
typedef int32_t (*VueOnException)(Vue *, VueException *);
|
||||
/* Breakpoint handler callbacks */
|
||||
typedef int32_t (*VueOnAccess )(Vue *, VueAccess *);
|
||||
typedef int32_t (*VueOnException)(Vue *, uint16_t );
|
||||
typedef int32_t (*VueOnExecute )(Vue *, VueInstruction *);
|
||||
typedef int32_t (*VueOnRead )(Vue *, VueAccess *);
|
||||
typedef int32_t (*VueOnWrite )(Vue *, VueAccess *);
|
||||
typedef int32_t (*VueOnFrame )(Vue * );
|
||||
|
||||
/* Emulation state */
|
||||
struct Vue {
|
||||
int32_t breakCode; /* Application break code */
|
||||
uint8_t wram[0x10000]; /* System memory */
|
||||
|
||||
/* Callback handlers */
|
||||
/* Breakpoint handlers */
|
||||
VueOnException onException;
|
||||
VueOnExecute onExecute;
|
||||
VueOnRead onRead;
|
||||
VueOnWrite onWrite;
|
||||
VueOnFrame onFrame;
|
||||
VueOnAccess onRead;
|
||||
VueOnAccess onWrite;
|
||||
|
||||
/* CPU state */
|
||||
struct {
|
||||
VueAccess access; /* Access state */
|
||||
VueException exception; /* Exception state */
|
||||
VueInstruction inst; /* Instruction state */
|
||||
int32_t cycles; /* Cycles until next stage */
|
||||
uint32_t cycles; /* Cycles until next stage */
|
||||
int32_t jumpFrom[3]; /* Source PCs of most recent jumps */
|
||||
int32_t jumpTo [3]; /* Destination PCs of most recent jumps */
|
||||
uint16_t exception; /* Exception code */
|
||||
uint16_t irq; /* Interrupt lines */
|
||||
int fetch; /* Fetch unit index */
|
||||
int stage; /* Current processing stage */
|
||||
@@ -265,21 +261,23 @@ struct Vue {
|
||||
* Function Prototypes *
|
||||
*****************************************************************************/
|
||||
|
||||
VUEAPI int32_t vueEmulate (Vue *vue, int32_t maxCycles);
|
||||
VUEAPI int32_t vueGetBreakCode(Vue *vue);
|
||||
VUEAPI int32_t vueGetRegister (Vue *vue, int32_t index, vbool system);
|
||||
VUEAPI void vueInitialize (Vue *vue);
|
||||
VUEAPI int32_t vueRead (Vue *vue, uint32_t address, int32_t type);
|
||||
VUEAPI vbool vueReadBytes (Vue *vue, uint32_t address, uint8_t *dest, uint32_t length);
|
||||
VUEAPI void vueReset (Vue *vue);
|
||||
VUEAPI void vueSetException(Vue *vue, VueOnException callback);
|
||||
VUEAPI void vueSetExecute (Vue *vue, VueOnExecute callback);
|
||||
VUEAPI void vueSetRead (Vue *vue, VueOnRead callback);
|
||||
VUEAPI int32_t vueSetRegister (Vue *vue, int32_t index, vbool system, int32_t value);
|
||||
VUEAPI vbool vueSetROM (Vue *vue, uint8_t *rom, uint32_t size);
|
||||
VUEAPI void vueSetWrite (Vue *vue, VueOnWrite callback);
|
||||
VUEAPI void vueWrite (Vue *vue, uint32_t address, int32_t type, int32_t value);
|
||||
VUEAPI vbool vueWriteBytes (Vue *vue, uint32_t address, uint8_t *src, uint32_t length);
|
||||
VUEAPI uint32_t vueEmulate (Vue *vue, uint32_t maxCycles);
|
||||
VUEAPI int32_t vueGetBreakCode (Vue *vue);
|
||||
VUEAPI uint16_t vueGetExceptionCode (Vue *vue);
|
||||
VUEAPI int32_t vueGetRegister (Vue *vue, int32_t index, vbool system);
|
||||
VUEAPI void vueInitialize (Vue *vue);
|
||||
VUEAPI VueOnException vueOnException (Vue *vue, VueOnException callback);
|
||||
VUEAPI VueOnExecute vueOnExecute (Vue *vue, VueOnExecute callback);
|
||||
VUEAPI VueOnFrame vueOnFrame (Vue *vue, VueOnFrame callback);
|
||||
VUEAPI VueOnAccess vueOnRead (Vue *vue, VueOnAccess callback);
|
||||
VUEAPI VueOnAccess vueOnWrite (Vue *vue, VueOnAccess callback);
|
||||
VUEAPI int32_t vueRead (Vue *vue, uint32_t address, int32_t type);
|
||||
VUEAPI vbool vueReadBytes (Vue *vue, uint32_t address, uint8_t *dest, uint32_t length);
|
||||
VUEAPI void vueReset (Vue *vue);
|
||||
VUEAPI int32_t vueSetRegister (Vue *vue, int32_t index, vbool system, int32_t value);
|
||||
VUEAPI vbool vueSetROM (Vue *vue, uint8_t *rom, uint32_t size);
|
||||
VUEAPI void vueWrite (Vue *vue, uint32_t address, int32_t type, int32_t value);
|
||||
VUEAPI vbool vueWriteBytes (Vue *vue, uint32_t address, uint8_t *src, uint32_t length);
|
||||
|
||||
|
||||
|
||||
|
||||
+68
-49
@@ -155,55 +155,46 @@ static void writeBytes(uint8_t *data, uint32_t datlen, uint32_t address,
|
||||
*****************************************************************************/
|
||||
|
||||
/* Process the simulation */
|
||||
int32_t vueEmulate(Vue *vue, int32_t maxCycles) {
|
||||
int32_t cycles; /* Number of cycles to process */
|
||||
uint32_t vueEmulate(Vue *vue, uint32_t maxCycles) {
|
||||
uint32_t cycles; /* Number of cycles to process */
|
||||
|
||||
/* Process up to the given number of cycles */
|
||||
do {
|
||||
|
||||
/* Determine the number of cycles during which nothing will happen */
|
||||
cycles = -1;
|
||||
/* Determine the number of cycles where no breakpoint will occur */
|
||||
cycles = maxCycles; /* min(maxCycles, nextFrameCycles) */
|
||||
cycles = cpuUntil (vue, cycles);
|
||||
/*cycles = padUntil (vue, cycles);*/
|
||||
/*cycles = linkUntil (vue, cycles);*/
|
||||
/*cycles = timerUntil(vue, cycles);*/
|
||||
/*cycles = vipUntil (vue, cycles);*/
|
||||
/*cycles = vsuUntil (vue, cycles);*/
|
||||
cycles = cpuUntil (vue, cycles);
|
||||
|
||||
/* Range checking */
|
||||
if (cycles == -1) /* No activity on any component */
|
||||
break;
|
||||
if (maxCycles >= 0) /* Restrict to given number of cycles */
|
||||
cycles = cycles < maxCycles ? cycles : maxCycles;
|
||||
|
||||
/* Process all system components */
|
||||
vue->breakCode = 0;
|
||||
cpuEmulate (vue, cycles);
|
||||
/*padEmulate (vue, cycles);*/
|
||||
/*pakEmulate (vue, cycles);*/
|
||||
/*linkEmulate (vue, cycles);*/
|
||||
/*timerEmulate(vue, cycles);*/
|
||||
/*vipEmulate (vue, cycles);*/
|
||||
/*vsuEmulate (vue, cycles);*/
|
||||
cpuEmulate (vue, cycles);
|
||||
|
||||
/* An application break was requested */
|
||||
if (vue->breakCode != 0)
|
||||
break;
|
||||
|
||||
/* Update the number of cycles remaining */
|
||||
if (maxCycles >= 0)
|
||||
maxCycles -= cycles;
|
||||
} while (maxCycles != 0);
|
||||
maxCycles -= cycles;
|
||||
} while (vue->breakCode == 0 && maxCycles != 0);
|
||||
|
||||
/* A break condition has occurred */
|
||||
return maxCycles;
|
||||
}
|
||||
|
||||
/* Retrieve the application break code */
|
||||
/* Retrieve the most recent applicaiton break code */
|
||||
int32_t vueGetBreakCode(Vue *vue) {
|
||||
return vue == NULL ? 0 : vue->breakCode;
|
||||
}
|
||||
|
||||
/* Retrieve the most recent exception code */
|
||||
uint16_t vueGetExceptionCode(Vue *vue) {
|
||||
return vue == NULL ? 0 : vue->cpu.exception;
|
||||
}
|
||||
|
||||
/* Retrieve the value of a register */
|
||||
int32_t vueGetRegister(Vue *vue, int32_t index, vbool system) {
|
||||
|
||||
@@ -234,17 +225,69 @@ void vueInitialize(Vue *vue) {
|
||||
return;
|
||||
vue->onException = NULL;
|
||||
vue->onExecute = NULL;
|
||||
vue->onFrame = NULL;
|
||||
vue->onRead = NULL;
|
||||
vue->onWrite = NULL;
|
||||
vue->pak.ram = NULL;
|
||||
vue->pak.rom = NULL;
|
||||
vueReset(vue);
|
||||
}
|
||||
|
||||
/* Specify an exception breakpoint callback */
|
||||
VueOnException vueOnException(Vue *vue, VueOnException callback) {
|
||||
VueOnException ret;
|
||||
if (vue == NULL)
|
||||
return NULL;
|
||||
ret = vue->onException;
|
||||
vue->onException = callback;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Specify an execute breakpoint callback */
|
||||
VueOnExecute vueOnExecute(Vue *vue, VueOnExecute callback) {
|
||||
VueOnExecute ret;
|
||||
if (vue == NULL)
|
||||
return NULL;
|
||||
ret = vue->onExecute;
|
||||
vue->onExecute = callback;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Specify a frame breakpoint callback */
|
||||
VueOnFrame vueOnFrame(Vue *vue, VueOnFrame callback) {
|
||||
VueOnFrame ret;
|
||||
if (vue == NULL)
|
||||
return NULL;
|
||||
ret = vue->onFrame;
|
||||
vue->onFrame = callback;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Specify a read breakpoint callback */
|
||||
VueOnAccess vueSetRead(Vue *vue, VueOnAccess callback) {
|
||||
VueOnAccess ret;
|
||||
if (vue == NULL)
|
||||
return NULL;
|
||||
ret = vue->onRead;
|
||||
vue->onRead = callback;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Specify a write breakpoint callback */
|
||||
VueOnAccess vueOnWrite(Vue *vue, VueOnAccess callback) {
|
||||
VueOnAccess ret;
|
||||
if (vue == NULL)
|
||||
return NULL;
|
||||
ret = vue->onWrite;
|
||||
vue->onWrite = callback;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read a value from the CPU bus */
|
||||
int32_t vueRead(Vue *vue, uint32_t address, int32_t type) {
|
||||
|
||||
/* Error checking */
|
||||
if (vue == NULL)
|
||||
if (vue == NULL || type < 0 || type > 4)
|
||||
return 0;
|
||||
|
||||
/* Perform the operation */
|
||||
@@ -299,28 +342,10 @@ void vueReset(Vue *vue) {
|
||||
/* Reset state */
|
||||
cpuReset(vue);
|
||||
pakReset(vue);
|
||||
for (x = 0; x < 0x1000; x++)
|
||||
for (x = 0; x < 0x10000; x++)
|
||||
vue->wram[x] = 0;
|
||||
}
|
||||
|
||||
/* Specify an exception breakpoint callback */
|
||||
void vueSetException(Vue *vue, VueOnException callback) {
|
||||
if (vue != NULL)
|
||||
vue->onException = callback;
|
||||
}
|
||||
|
||||
/* Specify an execute breakpoint callback */
|
||||
void vueSetExecute(Vue *vue, VueOnExecute callback) {
|
||||
if (vue != NULL)
|
||||
vue->onExecute = callback;
|
||||
}
|
||||
|
||||
/* Specify a read breakpoint callback */
|
||||
void vueSetRead(Vue *vue, VueOnRead callback) {
|
||||
if (vue != NULL)
|
||||
vue->onRead = callback;
|
||||
}
|
||||
|
||||
/* Specify a value for a register */
|
||||
int32_t vueSetRegister(Vue *vue, int32_t index, vbool system, int32_t value) {
|
||||
return vue == NULL ? 0 :
|
||||
@@ -348,12 +373,6 @@ vbool vueSetROM(Vue *vue, uint8_t *rom, uint32_t size) {
|
||||
return VUE_TRUE;
|
||||
}
|
||||
|
||||
/* Specify a write breakpoint callback */
|
||||
void vueSetWrite(Vue *vue, VueOnRead callback) {
|
||||
if (vue != NULL)
|
||||
vue->onWrite = callback;
|
||||
}
|
||||
|
||||
/* Write a value to the CPU bus */
|
||||
void vueWrite(Vue *vue, uint32_t address, int32_t type, int32_t value) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user