Files
psxrecomp/runtime/include/timers.h
Matthew Stanley 2d915c3fa9 wip(tomba2): precise-IRQ-slicing groundwork — cycles_to_next_event + design spec
Phase 1 of the cycle-budgeted precise interrupt-take-point fix (root cause:
compiled blocks take IRQs only at block edges; HW + the dirty-RAM interpreter
take them at the exact instruction — oracle-confirmed at the Tomba 2 logo
Timer1 debounce). Design validated with ChatGPT; full spec in PRECISE_IRQ_SLICE.md.

This commit lands the additive, no-behavior-change foundation (Task #2) plus the
prior session's diagnostic take-PC capture, and a build-hygiene dedup:

- cycles_to_next_event() (interrupts.c): single source of truth — min guest-cycle
  distance to the next DELIVERABLE interrupt (source raises its I_STAT bit AND
  that bit is unmasked in i_mask). Aggregates VBLANK + per-peripheral queries.
- timers/cdrom/dma/sio _cycles_to_irq(i_mask): each peripheral owns its own
  next-IRQ-distance query; all conservative under-estimates (smaller => slice
  more => never run past an event).
- debug_server: cycles_to_next_event command for live validation.
- interrupts.c: take-PC capture into the IRQ_DELIVER event-ring aux (prior
  session's diagnostic; records the architectural take-PC for cross-backend diff).
- overlay_loader.c: remove duplicate psx_native_bad_entry definition (HEAD had it
  twice; would not link cleanly).

Live-validated at the logo: returns the VBLANK distance, correctly excludes the
three free-running (unarmed/masked) timers and idle CD/DMA/SIO. Runtime-only,
no regen. The two-tier executor (Task #3) that consumes this is next.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 15:04:25 -07:00

40 lines
1.2 KiB
C

#ifndef PSXRECOMP_TIMERS_H
#define PSXRECOMP_TIMERS_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define TIMER_BASE 0x1F801100
void timers_init(void);
void timers_get_snapshot(uint16_t counter[3], uint32_t mode[3],
uint16_t target[3], int32_t irq_line[3],
uint32_t frac[3]);
void timers_set_snapshot(const uint16_t counter[3], const uint32_t mode[3],
const uint16_t target[3], const int32_t irq_line[3],
const uint32_t frac[3]);
/* MMIO read/write for 0x1F801100..0x1F80112F.
* Accepts 16-bit or 32-bit access (caller zero-extends). */
uint32_t timers_read(uint32_t addr);
void timers_write(uint32_t addr, uint32_t value);
/* Advance all timers by guest CPU cycles. Used by native block-cycle builds. */
void timers_advance(uint32_t cycles);
/* Cycle-budgeted precise event slicing: guest CPU cycles until a timer raises a
* DELIVERABLE IRQ (unmasked in i_mask + mode-armed). UINT32_MAX if none. */
uint32_t timers_cycles_to_irq(uint32_t i_mask);
/* Legacy coarse tick used by interpreter/oracle builds. */
void timers_tick(int cycles);
#ifdef __cplusplus
}
#endif
#endif /* PSXRECOMP_TIMERS_H */