1
0
mirror of https://github.com/rkujawa/rk65c02.git synced 2026-03-11 03:16:11 +00:00
Files
rk65c02/examples/idle_wait.c
Radosław Kujawa 1b4e7fe598 MMU/JIT: extended bus, examples (mmu_mpu, mmu_pae), tests, doc
- src: bus extended phys API, MMU/JIT hooks, rk65c02 MMU/tick/stop APIs
- examples: mmu_mpu and mmu_pae, Makefile targets; idle_wait, mmu_cart,
  mmu_multitasking updates
- test: test_mmu, test_bus, test_debug, Makefile
- doc: jit-design.md

Made-with: Cursor
2026-03-07 13:49:52 +01:00

94 lines
2.2 KiB
C

/*
* Idle-wait example — WAI and rk65c02_idle_wait_set.
*
* Build: make idle_wait idle_wait.rom
* Run: ./idle_wait
* Expected: guest runs WAI; host sleeps in idle_wait callback; IRQ wakes; STP.
*/
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include "bus.h"
#include "rk65c02.h"
static const uint16_t load_addr = 0xC000;
static const uint16_t counter_addr = 0x0200;
struct idle_wait_host_state {
uint32_t wait_calls;
uint64_t total_wait_ns;
};
static uint64_t
mono_ns_now(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint64_t)ts.tv_sec * 1000000000ULL + (uint64_t)ts.tv_nsec;
}
static void
on_idle_wait(rk65c02emu_t *e, void *ctx)
{
struct idle_wait_host_state *hs;
struct timespec req;
uint64_t t0, t1;
hs = (struct idle_wait_host_state *)ctx;
req.tv_sec = 0;
req.tv_nsec = 5 * 1000 * 1000; /* 5 ms */
t0 = mono_ns_now();
(void)nanosleep(&req, NULL);
/* Wake CPU from WAI (IRQ delivery can be handled by guest logic). */
rk65c02_assert_irq(e);
t1 = mono_ns_now();
hs->wait_calls++;
hs->total_wait_ns += (t1 - t0);
}
int
main(void)
{
rk65c02emu_t e;
struct idle_wait_host_state host;
uint8_t counter;
host.wait_calls = 0;
host.total_wait_ns = 0;
e = rk65c02_load_rom("idle_wait.rom", load_addr, NULL);
e.regs.SP = 0xFF;
e.regs.PC = load_addr;
/* Keep default throughput mode unless guest is in WAI. */
rk65c02_jit_enable(&e, true);
rk65c02_idle_wait_set(&e, on_idle_wait, &host);
rk65c02_start(&e);
counter = bus_read_1(e.bus, counter_addr);
printf("Stop reason: %s\n", rk65c02_stop_reason_string(e.stopreason));
printf("Counter at $%04x: %u\n", counter_addr, counter);
printf("Idle wait callbacks: %" PRIu32 "\n", host.wait_calls);
printf("Approx idle wait time: %" PRIu64 " us\n",
(uint64_t)(host.total_wait_ns / 1000ULL));
if (e.stopreason != STP) {
fprintf(stderr, "FAIL: expected STP, got %s\n",
rk65c02_stop_reason_string(e.stopreason));
return 1;
}
if (host.wait_calls == 0) {
fprintf(stderr, "FAIL: idle_wait callback was never invoked\n");
return 1;
}
printf("PASS: WAI drove idle_wait callbacks, then STP.\n");
return 0;
}