Implement most CPU instructions
This commit is contained in:
parent
d4ae5f3909
commit
2e0af6b109
1105
core/cpu.c
1105
core/cpu.c
File diff suppressed because it is too large
Load Diff
110
core/vb.c
110
core/vb.c
|
@ -73,6 +73,7 @@ struct VB {
|
||||||
/* Other state */
|
/* Other state */
|
||||||
uint32_t clocks; /* Master clocks to wait */
|
uint32_t clocks; /* Master clocks to wait */
|
||||||
uint16_t code[2]; /* Instruction code units */
|
uint16_t code[2]; /* Instruction code units */
|
||||||
|
uint16_t exception; /* Exception cause code */
|
||||||
uint16_t irq; /* Interrupt request lines */
|
uint16_t irq; /* Interrupt request lines */
|
||||||
int length; /* Instruction code length */
|
int length; /* Instruction code length */
|
||||||
uint32_t nextPC; /* Address of next instruction */
|
uint32_t nextPC; /* Address of next instruction */
|
||||||
|
@ -83,27 +84,27 @@ struct VB {
|
||||||
/* Other system state */
|
/* Other system state */
|
||||||
uint8_t wram[0x10000]; /* System RAM */
|
uint8_t wram[0x10000]; /* System RAM */
|
||||||
|
|
||||||
/* Application callbacks */
|
/* Application data */
|
||||||
vbOnExecute onExecute; /* CPU instruction execute */
|
vbOnExecute onExecute; /* CPU instruction execute */
|
||||||
vbOnFetch onFetch; /* CPU instruction fetch */
|
vbOnFetch onFetch; /* CPU instruction fetch */
|
||||||
vbOnRead onRead; /* CPU instruction read */
|
vbOnRead onRead; /* CPU instruction read */
|
||||||
vbOnWrite onWrite; /* CPU instruction write */
|
vbOnWrite onWrite; /* CPU instruction write */
|
||||||
|
void *tag; /* User data */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************** Library Functions *****************************/
|
/***************************** Library Functions *****************************/
|
||||||
|
|
||||||
/* Determine the lesser of two clocks figures */
|
|
||||||
static uint32_t MinClocks(uint32_t a, uint32_t b) {
|
|
||||||
return a < b ? a : b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sign-extend an integer of variable width */
|
/* Sign-extend an integer of variable width */
|
||||||
static int32_t SignExtend(int32_t value, int32_t bits) {
|
static int32_t SignExtend(int32_t value, int32_t bits) {
|
||||||
|
#ifndef VB_SIGNED_PROPAGATE
|
||||||
value &= ~((uint32_t) 0xFFFFFFFF << bits);
|
value &= ~((uint32_t) 0xFFFFFFFF << bits);
|
||||||
bits = (int32_t) 1 << (bits - (int32_t) 1);
|
bits = (int32_t) 1 << (bits - (int32_t) 1);
|
||||||
return (value ^ bits) - bits;
|
return (value ^ bits) - bits;
|
||||||
|
#else
|
||||||
|
return value << (32 - bits) >> (32 - bits);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -169,19 +170,6 @@ VBAPI int vbEmulateEx(VB **sims, int count, uint32_t *clocks) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retrieve a callback handler */
|
|
||||||
VBAPI void* vbGetCallback(VB *sim, int id) {
|
|
||||||
switch (id) {
|
|
||||||
/*case VB_EXCEPTION: return *(void **) &sim->onException;*/
|
|
||||||
case VB_EXECUTE : return *(void **) &sim->onExecute;
|
|
||||||
case VB_FETCH : return *(void **) &sim->onFetch;
|
|
||||||
/*case VB_FRAME : return *(void **) &sim->onFrame;*/
|
|
||||||
case VB_READ : return *(void **) &sim->onRead;
|
|
||||||
case VB_WRITE : return *(void **) &sim->onWrite;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve the game pack RAM buffer */
|
/* Retrieve the game pack RAM buffer */
|
||||||
VBAPI void* vbGetCartRAM(VB *sim, uint32_t *size) {
|
VBAPI void* vbGetCartRAM(VB *sim, uint32_t *size) {
|
||||||
if (size != NULL)
|
if (size != NULL)
|
||||||
|
@ -196,6 +184,16 @@ VBAPI void* vbGetCartROM(VB *sim, uint32_t *size) {
|
||||||
return sim->cart.rom;
|
return sim->cart.rom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Retrieve the execute callback handle */
|
||||||
|
VBAPI vbOnExecute vbGetExecuteCallback(VB *sim) {
|
||||||
|
return sim->onExecute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the fetch callback handle */
|
||||||
|
VBAPI vbOnFetch vbGetFetchCallback(VB *sim) {
|
||||||
|
return sim->onFetch;
|
||||||
|
}
|
||||||
|
|
||||||
/* Retrieve the value of the program counter */
|
/* Retrieve the value of the program counter */
|
||||||
VBAPI uint32_t vbGetProgramCounter(VB *sim) {
|
VBAPI uint32_t vbGetProgramCounter(VB *sim) {
|
||||||
return sim->cpu.pc;
|
return sim->cpu.pc;
|
||||||
|
@ -206,11 +204,26 @@ VBAPI int32_t vbGetProgramRegister(VB *sim, int index) {
|
||||||
return index < 1 || index > 31 ? 0 : sim->cpu.program[index];
|
return index < 1 || index > 31 ? 0 : sim->cpu.program[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Retrieve the read callback handle */
|
||||||
|
VBAPI vbOnRead vbGetReadCallback(VB *sim) {
|
||||||
|
return sim->onRead;
|
||||||
|
}
|
||||||
|
|
||||||
/* Retrieve the value in a system register */
|
/* Retrieve the value in a system register */
|
||||||
VBAPI uint32_t vbGetSystemRegister(VB *sim, int index) {
|
VBAPI uint32_t vbGetSystemRegister(VB *sim, int index) {
|
||||||
return index < 0 || index > 31 ? 0 : cpuGetSystemRegister(sim, index);
|
return index < 0 || index > 31 ? 0 : cpuGetSystemRegister(sim, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Retrieve a simulation's userdata pointer */
|
||||||
|
VBAPI void* vbGetUserData(VB *sim) {
|
||||||
|
return sim->tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve the write callback handle */
|
||||||
|
VBAPI vbOnWrite vbGetWriteCallback(VB *sim) {
|
||||||
|
return sim->onWrite;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize a simulation instance */
|
/* Initialize a simulation instance */
|
||||||
VBAPI VB* vbInit(VB *sim) {
|
VBAPI VB* vbInit(VB *sim) {
|
||||||
sim->cart.ram = NULL;
|
sim->cart.ram = NULL;
|
||||||
|
@ -241,6 +254,7 @@ VBAPI VB* vbReset(VB *sim) {
|
||||||
sim->wram[x] = 0x00;
|
sim->wram[x] = 0x00;
|
||||||
|
|
||||||
/* CPU (normal) */
|
/* CPU (normal) */
|
||||||
|
sim->cpu.exception = 0;
|
||||||
sim->cpu.irq = 0;
|
sim->cpu.irq = 0;
|
||||||
sim->cpu.pc = 0xFFFFFFF0;
|
sim->cpu.pc = 0xFFFFFFF0;
|
||||||
cpuSetSystemRegister(sim, VB_ECR, 0x0000FFF0, 1);
|
cpuSetSystemRegister(sim, VB_ECR, 0x0000FFF0, 1);
|
||||||
|
@ -267,29 +281,6 @@ VBAPI VB* vbReset(VB *sim) {
|
||||||
return sim;
|
return sim;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Specify a new callback handler */
|
|
||||||
VBAPI void* vbSetCallback(VB *sim, int id, void *callback) {
|
|
||||||
void *prev = NULL;
|
|
||||||
void **target = NULL;
|
|
||||||
|
|
||||||
/* Select callback by ID */
|
|
||||||
switch (id) {
|
|
||||||
/*case VB_EXCEPTION: target = (void **) &sim->onException; break;*/
|
|
||||||
case VB_EXECUTE : target = (void **) &sim->onExecute ; break;
|
|
||||||
case VB_FETCH : target = (void **) &sim->onFetch ; break;
|
|
||||||
/*case VB_FRAME : target = (void **) &sim->onFrame ; break;*/
|
|
||||||
case VB_READ : target = (void **) &sim->onRead ; break;
|
|
||||||
case VB_WRITE : target = (void **) &sim->onWrite ; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve current state and update new state */
|
|
||||||
if (target != NULL) {
|
|
||||||
prev = *target;
|
|
||||||
*target = callback;
|
|
||||||
}
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Specify a game pak RAM buffer */
|
/* Specify a game pak RAM buffer */
|
||||||
VBAPI int vbSetCartRAM(VB *sim, void *sram, uint32_t size) {
|
VBAPI int vbSetCartRAM(VB *sim, void *sram, uint32_t size) {
|
||||||
if (sram != NULL) {
|
if (sram != NULL) {
|
||||||
|
@ -312,6 +303,20 @@ VBAPI int vbSetCartROM(VB *sim, void *rom, uint32_t size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specify a new execute callback handle */
|
||||||
|
VBAPI vbOnExecute vbSetExecuteCallback(VB *sim, vbOnExecute callback) {
|
||||||
|
vbOnExecute prev = sim->onExecute;
|
||||||
|
sim->onExecute = callback;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Specify a new fetch callback handle */
|
||||||
|
VBAPI vbOnFetch vbSetFetchCallback(VB *sim, vbOnFetch callback) {
|
||||||
|
vbOnFetch prev = sim->onFetch;
|
||||||
|
sim->onFetch = callback;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
/* Specify a new value for the program counter */
|
/* Specify a new value for the program counter */
|
||||||
VBAPI uint32_t vbSetProgramCounter(VB *sim, uint32_t value) {
|
VBAPI uint32_t vbSetProgramCounter(VB *sim, uint32_t value) {
|
||||||
sim->cpu.operation = CPU_FETCH;
|
sim->cpu.operation = CPU_FETCH;
|
||||||
|
@ -325,17 +330,38 @@ VBAPI int32_t vbSetProgramRegister(VB *sim, int index, int32_t value) {
|
||||||
return index < 1 || index > 31 ? 0 : (sim->cpu.program[index] = value);
|
return index < 1 || index > 31 ? 0 : (sim->cpu.program[index] = value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specify a new read callback handle */
|
||||||
|
VBAPI vbOnRead vbSetReadCallback(VB *sim, vbOnRead callback) {
|
||||||
|
vbOnRead prev = sim->onRead;
|
||||||
|
sim->onRead = callback;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
/* Specify a new value for a system register */
|
/* Specify a new value for a system register */
|
||||||
VBAPI uint32_t vbSetSystemRegister(VB *sim, int index, uint32_t value) {
|
VBAPI uint32_t vbSetSystemRegister(VB *sim, int index, uint32_t value) {
|
||||||
return index < 0 || index > 31 ? 0 :
|
return index < 0 || index > 31 ? 0 :
|
||||||
cpuSetSystemRegister(sim, index, value, 1);
|
cpuSetSystemRegister(sim, index, value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specify a new write callback handle */
|
||||||
|
VBAPI vbOnWrite vbSetWriteCallback(VB *sim, vbOnWrite callback) {
|
||||||
|
vbOnWrite prev = sim->onWrite;
|
||||||
|
sim->onWrite = callback;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine the size of a simulation instance */
|
/* Determine the size of a simulation instance */
|
||||||
VBAPI size_t vbSizeOf() {
|
VBAPI size_t vbSizeOf() {
|
||||||
return sizeof (VB);
|
return sizeof (VB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specify a simulation's userdata pointer */
|
||||||
|
VBAPI void* vbSetUserData(VB *sim, void *tag) {
|
||||||
|
void *prev = sim->tag;
|
||||||
|
sim->tag = tag;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write a value to the memory bus */
|
/* Write a value to the memory bus */
|
||||||
VBAPI int32_t vbWrite(VB *sim, uint32_t address, int type, int32_t value) {
|
VBAPI int32_t vbWrite(VB *sim, uint32_t address, int type, int32_t value) {
|
||||||
if (type < 0 || type > 4)
|
if (type < 0 || type > 4)
|
||||||
|
|
16
core/vb.h
16
core/vb.h
|
@ -44,11 +44,6 @@ extern "C" {
|
||||||
#define VB_U16 3
|
#define VB_U16 3
|
||||||
#define VB_S32 4
|
#define VB_S32 4
|
||||||
|
|
||||||
/* CPU modes */
|
|
||||||
#define VB_ACCURACY 0
|
|
||||||
#define VB_DEBUG 1
|
|
||||||
#define VB_WHOLE 2
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************** Types ***********************************/
|
/*********************************** Types ***********************************/
|
||||||
|
@ -72,18 +67,27 @@ VBAPI int vbEmulateEx (VB **sims, int count, uint32_t *clocks);
|
||||||
VBAPI void* vbGetCallback (VB *sim, int id);
|
VBAPI void* vbGetCallback (VB *sim, int id);
|
||||||
VBAPI void* vbGetCartRAM (VB *sim, uint32_t *size);
|
VBAPI void* vbGetCartRAM (VB *sim, uint32_t *size);
|
||||||
VBAPI void* vbGetCartROM (VB *sim, uint32_t *size);
|
VBAPI void* vbGetCartROM (VB *sim, uint32_t *size);
|
||||||
|
VBAPI vbOnExecute vbGetExecuteCallback(VB *sim);
|
||||||
|
VBAPI vbOnFetch vbGetFetchCallback (VB *sim);
|
||||||
VBAPI uint32_t vbGetProgramCounter (VB *sim);
|
VBAPI uint32_t vbGetProgramCounter (VB *sim);
|
||||||
VBAPI int32_t vbGetProgramRegister(VB *sim, int index);
|
VBAPI int32_t vbGetProgramRegister(VB *sim, int index);
|
||||||
|
VBAPI vbOnRead vbGetReadCallback (VB *sim);
|
||||||
VBAPI uint32_t vbGetSystemRegister (VB *sim, int index);
|
VBAPI uint32_t vbGetSystemRegister (VB *sim, int index);
|
||||||
|
VBAPI void* vbGetUserData (VB *sim);
|
||||||
|
VBAPI vbOnWrite vbGetWriteCallback (VB *sim);
|
||||||
VBAPI VB* vbInit (VB *sim);
|
VBAPI VB* vbInit (VB *sim);
|
||||||
VBAPI int32_t vbRead (VB *sim, uint32_t address, int type);
|
VBAPI int32_t vbRead (VB *sim, uint32_t address, int type);
|
||||||
VBAPI VB* vbReset (VB *sim);
|
VBAPI VB* vbReset (VB *sim);
|
||||||
VBAPI void* vbSetCallback (VB *sim, int index, void *callback);
|
|
||||||
VBAPI int vbSetCartRAM (VB *sim, void *sram, uint32_t size);
|
VBAPI int vbSetCartRAM (VB *sim, void *sram, uint32_t size);
|
||||||
VBAPI int vbSetCartROM (VB *sim, void *rom, uint32_t size);
|
VBAPI int vbSetCartROM (VB *sim, void *rom, uint32_t size);
|
||||||
|
VBAPI vbOnExecute vbSetExecuteCallback(VB *sim, vbOnExecute callback);
|
||||||
|
VBAPI vbOnFetch vbSetFetchCallback (VB *sim, vbOnFetch callback);
|
||||||
VBAPI uint32_t vbSetProgramCounter (VB *sim, uint32_t value);
|
VBAPI uint32_t vbSetProgramCounter (VB *sim, uint32_t value);
|
||||||
VBAPI int32_t vbSetProgramRegister(VB *sim, int index, int32_t value);
|
VBAPI int32_t vbSetProgramRegister(VB *sim, int index, int32_t value);
|
||||||
|
VBAPI vbOnRead vbSetReadCallback (VB *sim, vbOnRead callback);
|
||||||
VBAPI uint32_t vbSetSystemRegister (VB *sim, int index, uint32_t value);
|
VBAPI uint32_t vbSetSystemRegister (VB *sim, int index, uint32_t value);
|
||||||
|
VBAPI void* vbSetUserData (VB *sim, void *tag);
|
||||||
|
VBAPI vbOnWrite vbSetWriteCallback (VB *sim, vbOnWrite callback);
|
||||||
VBAPI size_t vbSizeOf ();
|
VBAPI size_t vbSizeOf ();
|
||||||
VBAPI int32_t vbWrite (VB *sim, uint32_t address, int type, int32_t value);
|
VBAPI int32_t vbWrite (VB *sim, uint32_t address, int type, int32_t value);
|
||||||
|
|
||||||
|
|
4
makefile
4
makefile
|
@ -41,14 +41,14 @@ core:
|
||||||
# GCC compilation control
|
# GCC compilation control
|
||||||
@gcc core/vb.c -I core -c -o /dev/null \
|
@gcc core/vb.c -I core -c -o /dev/null \
|
||||||
-Werror -std=c90 -Wall -Wextra -Wpedantic \
|
-Werror -std=c90 -Wall -Wextra -Wpedantic \
|
||||||
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE
|
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC
|
||||||
# Clang generic
|
# Clang generic
|
||||||
@emcc core/vb.c -I core -c -o /dev/null \
|
@emcc core/vb.c -I core -c -o /dev/null \
|
||||||
-Werror -std=c90 -Wall -Wextra -Wpedantic
|
-Werror -std=c90 -Wall -Wextra -Wpedantic
|
||||||
# Clang compilation control
|
# Clang compilation control
|
||||||
@emcc core/vb.c -I core -c -o /dev/null \
|
@emcc core/vb.c -I core -c -o /dev/null \
|
||||||
-Werror -std=c90 -Wall -Wextra -Wpedantic \
|
-Werror -std=c90 -Wall -Wextra -Wpedantic \
|
||||||
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE
|
-D VB_LITTLE_ENDIAN -D VB_SIGNED_PROPAGATE -D VB_DIV_GENERIC
|
||||||
|
|
||||||
.PHONY: wasm
|
.PHONY: wasm
|
||||||
wasm:
|
wasm:
|
||||||
|
|
Loading…
Reference in New Issue