Additional work on emulation/CPU logic, implementing in C code

This commit is contained in:
2020-08-11 13:38:31 -05:00
parent d1b8e293c3
commit e31a5080c4
11 changed files with 635 additions and 107 deletions
+339 -33
View File
@@ -8,14 +8,14 @@
*****************************************************************************/
/* Stages */
#define CPU_FETCH 0
#define CPU_EXECUTE 1
#define CPU_HALT 2
#define CPU_EXCEPTION 3
#define CPU_FATAL 4
#define CPU_CLEAR 5
#define CPU_DUMP 6
#define CPU_RESTORE 7
#define CPU_FATAL -1
#define CPU_FETCH 0
#define CPU_EXECUTE 1
#define CPU_EXCEPTION 2
#define CPU_HALT 3
#define CPU_CLEAR 4
#define CPU_DUMP 5
#define CPU_RESTORE 6
/* Intermediate instruction IDs */
#define BITSTRING -2
@@ -57,20 +57,51 @@ static const int8_t LOOKUP_FLOATENDO[] = {
VUE_MPYHW , VUE_ILLEGAL, VUE_ILLEGAL, VUE_ILLEGAL
};
/* Instruction cycle counts */
static const int8_t CYCLES[] = {
1, 1, 28, 1, 1, 1, 1, 1, 1, 26, 12, 1, 1, 10, 14, 16,
38, 44, 36, 1, 5, 5, 5, 3, 3, 3, 5, 5, 5, 8, 1, 1,
1, 1, 1, 9, 13, 30, 13, 1, 1, 1, 1, 1, 1, 4, 4, 4,
10, 22, 1, 1, 1, 1, 1, 1, 12, 1, 1, 1, 1, 1, 4, 4,
4, 8, 1, 28, 15, 14, 6, 1, 1, 1, 1, 1
};
/*****************************************************************************
* Module Functions *
* Instruction Functions *
*****************************************************************************/
/* JMP */
static void cpuJMP(VUE *vue) {
vue->cpu.pc = vue->cpu.program[vue->cpu.inst.reg1] - 2;
}
/* MOVEA */
static void cpuMOVEA(VUE *vue) {
vue->cpu.program[vue->cpu.inst.reg2] =
vue->cpu.program[vue->cpu.inst.reg1] + vue->cpu.inst.imm;
}
/* MOVHI */
static void cpuMOVHI(VUE *vue) {
vue->cpu.program[vue->cpu.inst.reg2] =
vue->cpu.program[vue->cpu.inst.reg1] + (vue->cpu.inst.imm << 16);
}
/*****************************************************************************
* Stage Functions *
*****************************************************************************/
/* Decode an instruction from its binary encoding */
static void cpuDecode(VUE_INST *inst, int32_t bits) {
static void cpuDecode(VUE_INSTRUCTION *inst) {
int8_t extend; /* Sign-extend the immediate operand */
int32_t x; /* Working variable */
/* Configure instance fields */
inst->bits = bits;
inst->opcode = bits >> 26 & 63;
inst->opcode = inst->bits >> 26 & 63;
x = inst->opcode << 1;
inst->id = LOOKUP_OPCODE[x ];
extend = LOOKUP_OPCODE[x + 1];
@@ -80,42 +111,42 @@ static void cpuDecode(VUE_INST *inst, int32_t bits) {
/* Decode by format */
switch (inst->format) {
case 1:
inst->reg2 = bits >> 21 & 31;
inst->reg1 = bits >> 16 & 31;
inst->reg2 = inst->bits >> 21 & 31;
inst->reg1 = inst->bits >> 16 & 31;
break;
case 2:
x = bits >> 16 & 31;
inst->reg2 = bits >> 21 & 31;
x = inst->bits >> 16 & 31;
inst->reg2 = inst->bits >> 21 & 31;
inst->imm = extend < 0 ? SIGN_EXTEND(5, x) : x;
if (inst->id == BITSTRING)
inst->id = x >= 16 ? VUE_ILLEGAL : LOOKUP_BITSTRING[x];
break;
case 3:
x = bits >> 16 & 0x1FF;
x = inst->bits >> 16 & 0x1FF;
inst->opcode = 0x20;
inst->cond = bits >> 25 & 15;
inst->cond = inst->bits >> 25 & 15;
inst->disp = SIGN_EXTEND(9, x);
break;
case 4:
x = bits & 0x3FFFFFF;
x = inst->bits & 0x3FFFFFF;
inst->disp = SIGN_EXTEND(26, x);
break;
case 5:
x = bits & 0xFFFF;
inst->reg2 = bits >> 21 & 31;
inst->reg1 = bits >> 16 & 31;
x = inst->bits & 0xFFFF;
inst->reg2 = inst->bits >> 21 & 31;
inst->reg1 = inst->bits >> 16 & 31;
inst->imm = extend < 0 ? SIGN_EXTEND(16, x) : x;
break;
case 6:
x = bits & 0xFFFF;
inst->reg2 = bits >> 21 & 31;
inst->reg1 = bits >> 16 & 31;
x = inst->bits & 0xFFFF;
inst->reg2 = inst->bits >> 21 & 31;
inst->reg1 = inst->bits >> 16 & 31;
inst->disp = SIGN_EXTEND(16, x);
break;
case 7:
inst->reg2 = bits >> 21 & 31;
inst->reg1 = bits >> 16 & 31;
inst->subopcode = bits >> 10 & 63;
inst->reg2 = inst->bits >> 21 & 31;
inst->reg1 = inst->bits >> 16 & 31;
inst->subopcode = inst->bits >> 10 & 63;
inst->id = inst->subopcode >= 16 ? VUE_ILLEGAL :
LOOKUP_FLOATENDO[inst->subopcode];
break;
@@ -123,6 +154,178 @@ static void cpuDecode(VUE_INST *inst, int32_t bits) {
}
/* 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 |
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;
}
/* There is no exception */
if (vue->cpu.exception.code == 0) /* No further processing */
return vue->cpu.stage == CPU_HALT && vue->cpu.cycles == 0;
/* An exception has occurred */
vue->cpu.cycles = 0;
vue->cpu.stage = CPU_EXCEPTION;
return VUE_FALSE;
}
/* Operations for execute stage */
static vbool cpuExecute(VUE *vue) {
/* Application callback */
if (vue->onExecute != NULL) {
vue->breakCode = vue->onExecute(vue, &vue->cpu.inst);
if (vue->breakCode != 0)
return VUE_TRUE;
}
/* Determine the default number of cycles for the instruction */
if (vue->cpu.inst.id >= 0 && vue->cpu.inst.id <= 75)
vue->cpu.cycles = CYCLES[vue->cpu.inst.id];
/* Processing by instruction ID */
switch (vue->cpu.inst.id) {
/*case VUE_ADD_IMM: cpuADD_IMM(vue); break;*/
/*case VUE_ADD_REG: cpuADD_REG(vue); break;*/
/*case VUE_ADDF_S : cpuADDF_S (vue); break;*/
/*case VUE_ADDI : cpuADDI (vue); break;*/
/*case VUE_AND : cpuAND (vue); break;*/
/*case VUE_ANDBSU : cpuANDBSU (vue); break;*/
/*case VUE_ANDI : cpuANDI (vue); break;*/
/*case VUE_ANDNBSU: cpuANDNBSU(vue); break;*/
/*case VUE_BCOND : cpuBCOND (vue); break;*/
/*case VUE_CAXI : cpuCAXI (vue); break;*/
/*case VUE_CLI : cpuCLI (vue); break;*/
/*case VUE_CMP_IMM: cpuCMP_IMM(vue); break;*/
/*case VUE_CMP_REG: cpuCMP_REG(vue); break;*/
/*case VUE_CMPF_S : cpuCMPF_S (vue); break;*/
/*case VUE_CVT_SW : cpuCVT_SW (vue); break;*/
/*case VUE_CVT_WS : cpuCVT_WS (vue); break;*/
/*case VUE_DIV : cpuDIV (vue); break;*/
/*case VUE_DIVF_S : cpuDIVF_S (vue); break;*/
/*case VUE_DIVU : cpuDIVU (vue); break;*/
/*case VUE_HALT : cpuHALT (vue); break;*/
/*case VUE_IN_B : cpuIN_B (vue); break;*/
/*case VUE_IN_H : cpuIN_H (vue); break;*/
/*case VUE_IN_W : cpuIN_W (vue); break;*/
/*case VUE_JAL : cpuJAL (vue); break;*/
case VUE_JMP : cpuJMP (vue); break;
/*case VUE.JR : cpuJR (vue); break;*/
/*case VUE.LD_B : cpuLD_B (vue); break;*/
/*case VUE.LD_H : cpuLD_H (vue); break;*/
/*case VUE.LD_W : cpuLD_W (vue); break;*/
/*case VUE.LDSR : cpuLDSR (vue); break;*/
/*case VUE.MOV_IMM: cpuMOV_IMM(vue); break;*/
/*case VUE.MOV_REG: cpuMOV_REG(vue); break;*/
/*case VUE.MOVBSU : cpuMOVBSU (vue); break;*/
case VUE_MOVEA : cpuMOVEA (vue); break;
case VUE_MOVHI : cpuMOVHI (vue); break;
/*case VUE.MPYHW : cpuMPYHW (vue); break;*/
/*case VUE.MUL : cpuMUL (vue); break;*/
/*case VUE.MULF_S : cpuMULF_S (vue); break;*/
/*case VUE.MULU : cpuMULU (vue); break;*/
/*case VUE.NOT : cpuNOT (vue); break;*/
/*case VUE.NOTBSU : cpuNOTBSU (vue); break;*/
/*case VUE.OR : cpuOR (vue); break;*/
/*case VUE.ORBSU : cpuORBSU (vue); break;*/
/*case VUE.ORI : cpuORI (vue); break;*/
/*case VUE.ORNBSU : cpuORNBSU (vue); break;*/
/*case VUE.OUT_B : cpuOUT_B (vue); break;*/
/*case VUE.OUT_H : cpuOUT_H (vue); break;*/
/*case VUE.OUT_W : cpuOUT_W (vue); break;*/
/*case VUE.RETI : cpuRETI (vue); break;*/
/*case VUE.REV : cpuREV (vue); break;*/
/*case VUE.SAR_IMM: cpuSAR_IMM(vue); break;*/
/*case VUE.SAR_REG: cpuSAR_REG(vue); break;*/
/*case VUE.SCH0BSD: cpuSCH0BSD(vue); break;*/
/*case VUE.SCH0BSU: cpuSCH0BSU(vue); break;*/
/*case VUE.SCH1BSD: cpuSCH1BSD(vue); break;*/
/*case VUE.SCH1BSU: cpuSCH1BSU(vue); break;*/
/*case VUE.SEI : cpuSEI (vue); break;*/
/*case VUE.SETF : cpuSETF (vue); break;*/
/*case VUE.SHL_IMM: cpuSHL_IMM(vue); break;*/
/*case VUE.SHL_REG: cpuSHL_REG(vue); break;*/
/*case VUE.SHR_IMM: cpuSHR_IMM(vue); break;*/
/*case VUE.SHR_REG: cpuSHR_REG(vue); break;*/
/*case VUE.ST_B : cpuST_B (vue); break;*/
/*case VUE.ST_H : cpuST_H (vue); break;*/
/*case VUE.ST_W : cpuST_W (vue); break;*/
/*case VUE.STSR : cpuSTSR (vue); break;*/
/*case VUE.SUB : cpuSUB (vue); break;*/
/*case VUE.SUBF_S : cpuSUBF_S (vue); break;*/
/*case VUE.TRAP : cpuTRAP (vue); break;*/
/*case VUE.TRNC_SW: cpuTRNC_SW(vue); break;*/
/*case VUE.XB : cpuXB (vue); break;*/
/*case VUE.XH : cpuXH (vue); break;*/
/*case VUE.XOR : cpuXOR (vue); break;*/
/*case VUE.XORBSU : cpuXORBSU (vue); break;*/
/*case VUE.XORI : cpuXORI (vue); break;*/
/*case VUE.XORNBSU: cpuXORNBSU(vue); break;*/
default: /* Invalid instruction */
vue->cpu.exception.code = 0xFF90;
vue->cpu.inst.size = 0;
}
/* Common processing */
vue->cpu.pc += vue->cpu.inst.size;
vue->cpu.program[0] = 0;
cpuTestException(vue);
if (vue->cpu.stage == CPU_EXECUTE)
vue->cpu.stage = CPU_FETCH;
return VUE_FALSE;
}
/* Determine the size of an instruction given its opcode */
static int32_t cpuSize(int32_t opcode) {
int32_t ret = LOOKUP_OPCODE[opcode << 1 | 1];
return (ret < 0 ? -ret : ret) < 4 ? 2 : 4;
}
/* Operations for fetch stage */
static vbool cpuFetch(VUE *vue) {
/* Read the bits from the bus */
vue->cpu.access.address = vue->cpu.pc + (vue->cpu.fetch << 1);
vue->cpu.access.fetch = vue->cpu.fetch;
vue->cpu.access.type = VUE_U16;
vue->cpu.access.value = vueRead(vue, vue->cpu.access.address, VUE_U16);
/* Application callback */
if (vue->onRead != NULL) {
vue->breakCode = vue->onRead(vue, &vue->cpu.access);
if (vue->breakCode != 0)
return VUE_TRUE;
}
/* First unit */
if (vue->cpu.fetch == 0) {
vue->cpu.inst.bits = vue->cpu.access.value << 16;
if (cpuSize(vue->cpu.access.value >> 10 & 0x3F) == 4) {
vue->cpu.fetch = 1;
return VUE_FALSE;
}
}
/* Second unit */
else {
vue->cpu.inst.bits |= vue->cpu.access.value & 0xFFFF;
vue->cpu.fetch = 0;
}
/* Decode the instruction and advance to execute stage */
cpuDecode(&vue->cpu.inst);
vue->cpu.stage = CPU_EXECUTE;
return VUE_FALSE;
}
/* Read a system register */
static int32_t cpuGetSystemRegister(VUE *vue, int32_t index) {
switch (index) {
@@ -158,6 +361,97 @@ static int32_t cpuGetSystemRegister(VUE *vue, int32_t index) {
return 1; /* Unreachable */
}
/* 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;
}
/* 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) {
/* The CPU is in permanent halt */
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 */
if (vue->cpu.cycles > cycles) {
vue->cpu.cycles -= cycles;
return;
}
/* Processing by stage */
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;
}
}
}
/* Write a system register */
static int32_t cpuSetSystemRegister(VUE *vue, int32_t index, int32_t value,
vbool debug) {
@@ -230,9 +524,11 @@ static void cpuReset(VUE *vue) {
int32_t x;
/* Configure instance fields */
vue->cpu.cycles = 0; /* Duration of first fetch */
vue->cpu.fetch = 0;
vue->cpu.stage = CPU_FETCH;
vue->cpu.cycles = 0;
vue->cpu.exception.code = 0;
vue->cpu.fetch = 0;
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++) {
@@ -251,7 +547,7 @@ static void cpuReset(VUE *vue) {
}
/* Test a condition */
static int8_t cpuTest(VUE *vue, int32_t condition) {
static int8_t cpuTestCondition(VUE *vue, int32_t condition) {
switch (condition) {
case 0: return vue->cpu.psw_ov;
case 1: return vue->cpu.psw_cy;
@@ -262,7 +558,17 @@ static int8_t cpuTest(VUE *vue, int32_t condition) {
case 6: return vue->cpu.psw_ov | vue->cpu.psw_s;
case 7: return (vue->cpu.psw_ov ^ vue->cpu.psw_s) | vue->cpu.psw_z;
}
return cpuTest(vue, condition & 7) ^ 1;
return cpuTestCondition(vue, condition & 7) ^ 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;
}
#endif
+44 -9
View File
@@ -139,9 +139,25 @@ extern "C" {
* Types *
*****************************************************************************/
/* Forward references */
typedef struct VUE VUE;
/* Boolean */
typedef int vbool;
/* Access state */
typedef struct {
uint32_t address; /* CPU bus address */
int32_t value; /* Value read/to write */
int8_t fetch; /* Index of machine code unit */
int8_t type; /* Data type */
} VUE_ACCESS;
/* Exception state */
typedef struct {
uint16_t code; /* Exception code */
} VUE_EXCEPTION;
/* Instruction state */
typedef struct {
int32_t bits; /* Binary encoding */
@@ -155,21 +171,36 @@ typedef struct {
uint8_t reg2; /* Destination/left register */
uint8_t size; /* Number of bytes in encoding */
uint8_t subopcode; /* Instruction subopcode */
} VUE_INST;
} VUE_INSTRUCTION;
/* Callbacks */
typedef int32_t (*VUE_ONEXCEPTION)(VUE *, VUE_EXCEPTION *);
typedef int32_t (*VUE_ONEXECUTE )(VUE *, VUE_INSTRUCTION *);
typedef int32_t (*VUE_ONREAD )(VUE *, VUE_ACCESS *);
typedef int32_t (*VUE_ONWRITE )(VUE *, VUE_ACCESS *);
/* Emulation state */
typedef struct {
struct VUE {
int32_t breakCode; /* Application break code */
uint8_t wram[0x10000]; /* System memory */
/* Callback handlers */
VUE_ONEXCEPTION onException;
VUE_ONEXECUTE onExecute;
VUE_ONREAD onRead;
VUE_ONWRITE onWrite;
/* CPU state */
struct {
VUE_INST inst; /* Instruction state */
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 */
int fetch; /* Fetch unit index */
int stage; /* Current processing stage */
VUE_ACCESS access; /* Access state */
VUE_EXCEPTION exception; /* Exception state */
VUE_INSTRUCTION inst; /* Instruction state */
int32_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 irq; /* Interrupt lines */
int fetch; /* Fetch unit index */
int stage; /* Current processing stage */
/* Program registers */
int32_t program[32];
@@ -225,7 +256,7 @@ typedef struct {
int8_t wcr_rom1w; /* ROM one-wait mode */
} pak;
} VUE;
};
@@ -240,8 +271,12 @@ 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, VUE_ONEXCEPTION callback);
VUEAPI void vueSetExecute (VUE *vue, VUE_ONEXECUTE callback);
VUEAPI void vueSetRead (VUE *vue, VUE_ONREAD 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, VUE_ONWRITE 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);
+59 -12
View File
@@ -75,7 +75,7 @@ static int32_t readBuffer(uint8_t *data, uint32_t datlen, uint32_t address,
}
/* Sign-extend the value if appropriate */
if (type & 1) {
if ((type & 1) == 0) {
size <<= 3;
value = SIGN_EXTEND(size, value);
}
@@ -167,23 +167,29 @@ int32_t vueEmulate(VUE *vue, int32_t maxCycles) {
do {
/* Determine the number of cycles during which nothing will happen */
cycles = maxCycles;
/*cycles = cpuUntil (vue, cycles);*/
cycles = -1;
/*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;
/*gamePad.emulate(cycles);*/
/*gamePak.emulate(cycles);*/
/*link .emulate(cycles);*/
/*timer .emulate(cycles);*/
/*vip .emulate(cycles);*/
/*vsu .emulate(cycles);*/
/*cpu .emulate(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)
@@ -231,12 +237,22 @@ int32_t vueGetRegister(VUE *vue, int32_t index, vbool system) {
void vueInitialize(VUE *vue) {
if (vue == NULL)
return;
vue->pak.ram = NULL;
vue->pak.rom = NULL;
vue->onException = NULL;
vue->onExecute = NULL;
vue->onRead = NULL;
vue->onWrite = NULL;
vue->pak.ram = NULL;
vue->pak.rom = NULL;
}
/* Read a value from the CPU bus */
int32_t vueRead(VUE *vue, uint32_t address, int32_t type) {
/* Error checking */
if (vue == NULL)
return 0;
/* Perform the operation */
switch (address >> 24 & 7) {
case 5: return readBuffer(vue->wram , 0x10000,address,type);
case 6: return readBuffer(vue->pak.ram,vue->pak.ramSize,address,type);
@@ -292,6 +308,24 @@ void vueReset(VUE *vue) {
vue->wram[x] = 0;
}
/* Specify an exception breakpoint callback */
void vueSetException(VUE *vue, VUE_ONEXCEPTION callback) {
if (vue != NULL)
vue->onException = callback;
}
/* Specify an execute breakpoint callback */
void vueSetExecute(VUE *vue, VUE_ONEXECUTE callback) {
if (vue != NULL)
vue->onExecute = callback;
}
/* Specify a read breakpoint callback */
void vueSetRead(VUE *vue, VUE_ONREAD 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 :
@@ -319,8 +353,20 @@ vbool vueSetROM(VUE *vue, uint8_t *rom, uint32_t size) {
return VUE_TRUE;
}
/* Specify a write breakpoint callback */
void vueSetWrite(VUE *vue, VUE_ONREAD 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) {
/* Error checking */
if (vue == NULL)
return;
/* Perform the operation */
switch (address >> 24 & 7) {
case 5: writeBuffer(vue->wram , 0x1000,
address, type, value); break;
@@ -329,6 +375,7 @@ void vueWrite(VUE *vue, uint32_t address, int32_t type, int32_t value) {
case 7: writeBuffer(vue->pak.rom, vue->pak.romSize,
address, type, value); break;
}
}
/* Write bytes to the CPU bus */