pvbemu/core/vb.c

227 lines
6.9 KiB
C

#define VBAPI
/* Header includes */
#include <vb.h>
/********************************* Constants *********************************/
/* Type sizes */
static const uint8_t TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
/********************************** Macros ***********************************/
/* Sign-extend a value of some number of bits to 32 bits */
#define SignExtend(v,b) ( (v) | (((v) & 1 << b - 1) ? ~(int32_t)0 << b : 0) )
/*************************** Subsystem Components ****************************/
/* Component includes */
#include "bus.c"
/******************************* API Functions *******************************/
/* Retrieve the value of PC */
uint32_t vbGetProgramCounter(VB *emu, int type) {
switch (type) {
case VB_PC : return emu->cpu.pc;
case VB_PC_FROM: return emu->cpu.pcFrom;
case VB_PC_TO : return emu->cpu.pcTo;
}
return 0;
}
/* Retrieve the value of a program register */
int32_t vbGetProgramRegister(VB *emu, int id) {
return id < 1 || id > 31 ? 0 : emu->cpu.program[id];
}
/* Retrieve the ROM buffer */
void* vbGetROM(VB *emu, uint32_t *size) {
if (size != NULL)
*size = emu->cart.romSize;
return emu->cart.rom;
}
/* Retrieve the SRAM buffer */
void* vbGetSRAM(VB *emu, uint32_t *size) {
if (size != NULL)
*size = emu->cart.sramSize;
return emu->cart.sram;
}
/* Retrieve the value of a system register */
uint32_t vbGetSystemRegister(VB *emu, int id) {
switch (id) {
case VB_ADTRE: return emu->cpu.adtre;
case VB_CHCW : return emu->cpu.chcw.ice << 1;
case VB_EIPC : return emu->cpu.eipc;
case VB_EIPSW: return emu->cpu.eipsw;
case VB_FEPC : return emu->cpu.fepc;
case VB_FEPSW: return emu->cpu.fepsw;
case VB_PIR : return 0x00005346;
case VB_TKCW : return 0x000000E0;
case 29 : return emu->cpu.sr29;
case 30 : return 0x00000004;
case 31 : return emu->cpu.sr31;
case VB_ECR : return
(uint32_t) emu->cpu.ecr.fecc << 16 | emu->cpu.ecr.eicc;
case VB_PSW : return
(uint32_t) emu->cpu.psw.i << 16 |
(uint32_t) emu->cpu.psw.np << 15 |
(uint32_t) emu->cpu.psw.ep << 14 |
(uint32_t) emu->cpu.psw.ae << 13 |
(uint32_t) emu->cpu.psw.id << 12 |
(uint32_t) emu->cpu.psw.fro << 9 |
(uint32_t) emu->cpu.psw.fiv << 8 |
(uint32_t) emu->cpu.psw.fzd << 7 |
(uint32_t) emu->cpu.psw.fov << 6 |
(uint32_t) emu->cpu.psw.fud << 5 |
(uint32_t) emu->cpu.psw.fpr << 4 |
(uint32_t) emu->cpu.psw.cy << 3 |
(uint32_t) emu->cpu.psw.ov << 2 |
(uint32_t) emu->cpu.psw.s << 1 |
(uint32_t) emu->cpu.psw.z
;
}
return 0;
}
/* Prepare a simulation state instance for use */
void vbInit(VB *emu) {
/* Cartridge */
emu->cart.rom = NULL;
emu->cart.romSize = 0;
emu->cart.sram = NULL;
emu->cart.sramSize = 0;
/* All others */
vbReset(emu);
}
/* Read a data unit from the bus */
int32_t vbRead(VB *emu, uint32_t address, int type, int debug) {
return type < 0 || type >= (int) sizeof TYPE_SIZES ? 0 :
busRead(emu, address, type, debug);
}
/* Simulate a hardware reset */
void vbReset(VB *emu) {
uint32_t x; /* Iterator */
/* CPU registers */
emu->cpu.pc = 0xFFFFFFF0;
vbSetSystemRegister(emu, VB_ECR, 0x0000FFF0);
vbSetSystemRegister(emu, VB_PSW, 0x00008000);
/* Extra CPU registers (the hardware does not do this) */
for (x = 0; x < 32; x++)
emu->cpu.program[x] = 0x00000000;
emu->cpu.adtre = 0x00000000;
emu->cpu.eipc = 0x00000000;
emu->cpu.eipsw = 0x00000000;
emu->cpu.fepc = 0x00000000;
emu->cpu.fepsw = 0x00000000;
emu->cpu.sr29 = 0x00000000;
emu->cpu.sr31 = 0x00000000;
emu->cpu.pcFrom = 0xFFFFFFF0;
emu->cpu.pcTo = 0xFFFFFFF0;
/* WRAM (the hardware does not do this) */
for (x = 0; x < 0x10000; x++)
emu->wram[x] = 0x00;
}
/* Specify a new value for PC */
uint32_t vbSetProgramCounter(VB *emu, uint32_t value) {
value &= 0xFFFFFFFE;
emu->cpu.pc = value;
/* Set stage to fecth=0 */
return value;
}
/* Specify a new value for a program register */
int32_t vbSetProgramRegister(VB *emu, int id, int32_t value) {
return id < 1 || id > 31 ? 0 : (emu->cpu.program[id] = value);
}
/* Supply a ROM buffer */
int vbSetROM(VB *emu, void *rom, uint32_t size) {
/* Check the buffer size */
if (size < 1024 || size > 0x1000000 || ((size - 1) & size) != 0)
return 0;
/* Configure the ROM buffer */
emu->cart.rom = (uint8_t *) rom;
emu->cart.romSize = size;
return 1;
}
/* Supply an SRAM buffer */
int vbSetSRAM(VB *emu, void *sram, uint32_t size) {
/* Check the buffer size */
if (size == 0 || ((size - 1) & size) != 0)
return 0;
/* Configure the SRAM buffer */
emu->cart.sram = (uint8_t *) sram;
emu->cart.sramSize = size;
return 1;
}
/* Specify a new value for a system register */
uint32_t vbSetSystemRegister(VB *emu, int id, uint32_t value) {
switch (id) {
case VB_ADTRE: return emu->cpu.adtre = value & 0xFFFFFFFE;
case VB_EIPC : return emu->cpu.eipc = value & 0xFFFFFFFE;
case VB_EIPSW: return emu->cpu.eipsw = value & 0x000FF3FF;
case VB_FEPC : return emu->cpu.fepc = value & 0xFFFFFFFE;
case VB_FEPSW: return emu->cpu.fepsw = value & 0x000FF3FF;
case VB_PIR : return 0x00005346;
case VB_TKCW : return 0x000000E0;
case 29 : return emu->cpu.sr29 = value & 0x00000001;
case 31 : return emu->cpu.sr31 = value;
case VB_CHCW :
emu->cpu.chcw.ice = value >> 1 & 1;
return value & 0x00000002;
case VB_ECR :
emu->cpu.ecr.fecc = value >> 16;
emu->cpu.ecr.eicc = value;
return value;
case VB_PSW :
emu->cpu.psw.i = value >> 16 & 15;
emu->cpu.psw.np = value >> 15 & 1;
emu->cpu.psw.ep = value >> 14 & 1;
emu->cpu.psw.ae = value >> 13 & 1;
emu->cpu.psw.id = value >> 12 & 1;
emu->cpu.psw.fro = value >> 9 & 1;
emu->cpu.psw.fiv = value >> 8 & 1;
emu->cpu.psw.fzd = value >> 7 & 1;
emu->cpu.psw.fov = value >> 6 & 1;
emu->cpu.psw.fud = value >> 5 & 1;
emu->cpu.psw.fpr = value >> 4 & 1;
emu->cpu.psw.cy = value >> 3 & 1;
emu->cpu.psw.ov = value >> 2 & 1;
emu->cpu.psw.s = value >> 1 & 1;
emu->cpu.psw.z = value & 1;
return value & 0x000FF3FF;
}
return 0;
}
/* Write a data unit to the bus */
void vbWrite(VB *emu, uint32_t address, int type, int32_t value, int debug) {
if (type < 0 || type >= (int32_t) sizeof TYPE_SIZES)
busWrite(emu, address, type, value, debug);
}