/* 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 */