// CoreMark porting layer for W65816.  See core_portme.h for config.
#include "coremark.h"
#include "core_portme.h"
#include <time.h>
#include <stdio.h>

#if VALIDATION_RUN
volatile ee_s32 seed1_volatile = 0x3415;
volatile ee_s32 seed2_volatile = 0x3415;
volatile ee_s32 seed3_volatile = 0x66;
#endif
#if PERFORMANCE_RUN
volatile ee_s32 seed1_volatile = 0x0;
volatile ee_s32 seed2_volatile = 0x0;
volatile ee_s32 seed3_volatile = 0x66;
#endif
#if PROFILE_RUN
volatile ee_s32 seed1_volatile = 0x8;
volatile ee_s32 seed2_volatile = 0x8;
volatile ee_s32 seed3_volatile = 0x8;
#endif
volatile ee_s32 seed4_volatile = ITERATIONS;
volatile ee_s32 seed5_volatile = 0;

// Timing — uses libc's clock() (VBL counter at 60 Hz).
#define GETMYTIME(_t)              (*_t = (CORETIMETYPE)clock())
#define MYTIMEDIFF(fin, ini)       ((fin) - (ini))
#define TIMER_RES_DIVIDER          1
#define SAMPLE_TIME_IMPLEMENTATION 1
#define EE_TICKS_PER_SEC           (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)

static CORETIMETYPE start_time_val;
static CORETIMETYPE stop_time_val;

void start_time(void) {
    GETMYTIME(&start_time_val);
}


void stop_time(void) {
    GETMYTIME(&stop_time_val);
}


CORE_TICKS get_time(void) {
    return (CORE_TICKS)MYTIMEDIFF(stop_time_val, start_time_val);
}


secs_ret time_in_secs(CORE_TICKS ticks) {
    return ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
}


ee_u32 default_num_contexts = 1;


void portable_init(core_portable *p, int *argc, char *argv[]) {
    (void)argc;
    (void)argv;
    // Sentinel BEFORE benchmark: 0xBEEF.  MAME can confirm we got here
    // even if CoreMark hangs mid-iteration.
    *(volatile unsigned short *)0x025000 = 0xBEEF;
    p->portable_id = 1;
}


void portable_fini(core_portable *p) {
    p->portable_id = 0;
    // Final sentinel + elapsed-tick snapshot.  CoreMark called
    // stop_time() then computed total_time before printing — we
    // pick up its captured stop_time_val.
    CORE_TICKS elapsed = get_time();
    *(volatile unsigned short *)0x025002 = (unsigned short)(elapsed & 0xFFFF);
    *(volatile unsigned short *)0x025004 = (unsigned short)((elapsed >> 16) & 0xFFFF);
    // 0xC0DE = "CoreMark completed without aborting".
    *(volatile unsigned short *)0x025000 = 0xC0DE;
}


// ee_printf is referenced from core_main.c; bridge to printf.
int ee_printf(const char *fmt, ...) {
    extern int vprintf(const char *, __builtin_va_list);
    __builtin_va_list ap;
    __builtin_va_start(ap, fmt);
    int r = vprintf(fmt, ap);
    __builtin_va_end(ap);
    return r;
}
