shrooms-vb-core/core/pseudo-halt.c

178 lines
4.9 KiB
C
Raw Normal View History

2024-10-23 21:29:11 +00:00
/* This file is included into vb.c and cannot be compiled on its own. */
#ifdef VBAPI
/********************************* Constants *********************************/
/* Pseudo-halt operations */
#define PH_NEVER 0 /* Must be zero */
#define PH_XPSTTS 1
/***************************** Module Functions ******************************/
/* Activate pseudo-halt */
static void phActivate(VB *sim, uint32_t address, int type) {
int range; /* Memory address range by component */
(void) type;
/* Working variables */
address = 0x07FFFFFF;
range = address >> 24;
/* Configure CPU */
sim->cpu.operation = CPU_PHALT;
sim->ph.operation = PH_NEVER;
/* VIP */
if (range == 0) {
address &= 0x0007FFFF;
/* I/O register */
switch (address) {
case 0x5F840: /* XPSTTS */
if (sim->vip.dp.disp && sim->vip.xp.xpen)
sim->ph.operation = PH_XPSTTS;
break;
}
}
/* Configure CPU */
sim->cpu.clocks = phUntil(sim);
}
/* Test whether the current memory access matches the monitored access */
static int phMatches(VB *sim, uint32_t address, int type, int32_t value) {
int match; /* Parameter match */
int x; /* Iterator */
/* New memory access */
if (sim->ph.step == 0)
return 0;
/* Check memory access parameters */
match =
address == sim->ph.address &&
sim->cpu.pc == sim->ph.pc &&
type == sim->ph.type &&
value == sim->ph.value
;
if (!match || sim->ph.step != 3)
return match;
/* Check full CPU state */
for (x = 1; x < 32; x++) {
if (sim->ph.program[x - 1] != sim->cpu.program[x])
return 0;
}
return
sim->ph.adtre == sim->cpu.adtre &&
sim->ph.chcw == cpuGetSystemRegister(sim, VB_CHCW) &&
sim->ph.eipc == sim->cpu.eipc &&
sim->ph.eipsw == sim->cpu.eipsw &&
sim->ph.fepc == sim->cpu.fepc &&
sim->ph.fepsw == sim->cpu.fepsw &&
sim->ph.psw == cpuGetSystemRegister(sim, VB_PSW)
;
}
/****************************** Clock Measurers ******************************/
/* XPSTTS */
static uint32_t phXPSTTS(VB *sim) {
uint32_t clocks; /* Return value */
uint16_t *halfwords; /* Drawing clocks this SBCOUNT */
uint32_t x; /* Iterator */
/* Drawing is underway */
if (sim->vip.xp.f0bsy || sim->vip.xp.f1bsy) {
clocks = 0;
halfwords = &sim->vip.halfwords[
(uint32_t) sim->vip.xp.sbcount * 384 + sim->vip.xp.column];
for (x = sim->vip.xp.column; x < 384; x++, halfwords++)
clocks += *halfwords;
return clocks;
}
/* Drawing is idle */
switch (sim->vip.dp.step) {
case 0: /* 0ms - FCLK rising edge */
return sim->vip.dp.until;
case 1: /* 3ms - L*BSY rising edge */
case 2: /* 3ms-8ms - Display left frame buffer */
case 3: /* 8ms - L*BSY falling edge */
return sim->vip.dp.until + vipClocksMs(12);
}
/* case 4: 10ms - FCLK falling edge */
/* case 5: 13ms - R*BSY rising edge */
/* case 6: 13ms-18ms - Display right frame buffer */
/* case 7: 18ms - R*BSY falling edge */
return sim->vip.dp.until + vipClocksMs(2);
}
/***************************** Library Functions *****************************/
/* Test whether to activate pseudo-halt */
static int phAssess(VB *sim, uint32_t address, int type, int32_t value) {
int x; /* Iterator */
/* Memory access does not match last time */
if (!phMatches(sim, address, type, value))
sim->ph.step = 0;
/* New memory access */
if (sim->ph.step == 0) {
sim->ph.address = address;
sim->ph.pc = sim->cpu.pc;
sim->ph.step = 1;
sim->ph.type = type;
sim->ph.value = value;
return 0;
}
/* Repeated memory access, not checking full CPU state */
if (sim->ph.step < 2) {
sim->ph.step++;
return 0;
}
/* Take a snapshot of the full CPU state */
if (sim->ph.step == 2) {
for (x = 1; x < 32; x++)
sim->ph.program[x - 1] = sim->cpu.program[x];
sim->ph.adtre = sim->cpu.adtre;
sim->ph.chcw = cpuGetSystemRegister(sim, VB_CHCW);
sim->ph.eipc = sim->cpu.eipc;
sim->ph.eipsw = sim->cpu.eipsw;
sim->ph.fepc = sim->cpu.fepc;
sim->ph.fepsw = sim->cpu.fepsw;
sim->ph.psw = cpuGetSystemRegister(sim, VB_PSW);
sim->ph.step = 3;
return 0;
}
/* Activate pseudo-halt */
phActivate(sim, address, type);
return 1;
}
/* Determine how long the CPU should wait before checking the monitor value */
static uint32_t phUntil(VB *sim) {
switch (sim->ph.operation) {
case PH_XPSTTS: return phXPSTTS(sim);
}
return 0; /* PH_NEVER */
}
#endif /* VBAPI */