/*
 * Copyright (C) 2018-2020 Western Digital Corporation or its affiliates
 * Copyright (C) 2017-2018 Wearable, Inc.
 * Copyright (C) 2000-2012 leJOS Contributors
 * Copyright (C) 2000 Jose H. Solorzano and TinyVM Contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 * 
 * This Source Code Form is “Incompatible With Secondary Licenses”,
 * as defined by the Mozilla Public License, v. 2.0.
 */

#ifndef _PLATFORM_HOOKS_H
#define _PLATFORM_HOOKS_H

// Methods declared here must be implemented by
// each platform.

#include "types.h"
#include "classes.h"
#include "language.h"
#include "interpreter.h"
#include "poll.h"

// In math.c
int dcmp(double f1, double f2);
int fcmp(JFLOAT f1, JFLOAT f2);

// standard library functions
extern float fmodf(float x, float y);
extern double fmod(double x, double y);

#ifdef PLATFORM_HAS_INSTRUCTION_HOOK
void instruction_hook(nvm_state_t* pState);
#else
#define instruction_hook(state) do { } while (0)
#endif
void event_hook(nvm_state_t* pState);
void exit_hook(nvm_state_t* pState);
void idle_hook(nvm_state_t* pState);

void oom_hook(nvm_state_t* pState);
void gc_start_hook(nvm_state_t* pState);
void gc_end_hook(nvm_state_t* pState);

static inline void switch_thread_hook()
{
}

JINT platform_check_event(JINT type);

void platform_wait_events(TIMESTAMP until);

/**
 * Called when thread is about to die due to an uncaught exception.
 */
void handle_uncaught_exception (nvm_state_t* pState,
                                Object *exception,
                                const Thread *thread,
                                const MethodRecord *methodRecord,
                                const MethodRecord *rootMethod,
                                byte *pc);

extern void firmware_exception_handler(Throwable *exception, STACKWORD method, STACKWORD pc);

void init_time(nvm_state_t* pState);

/**
 * Called to atomically read a timestamp value
 */

TIMESTAMP atomic_time_get(TIMESTAMP* val);

void get_nanotime(TIMESTAMP* sec, TIMESTAMP* nsec);

/**
 * Dispatch native and platform methods
 */
int dispatch_native  (nvm_state_t* pState, uint16_t signature, STACKWORD* paramBase);
int dispatch_platform(nvm_state_t* pState, uint16_t signature, STACKWORD* paramBase);
int dispatch_platform_crypt(nvm_state_t* state, uint16_t signature, STACKWORD argv[], _Bool* taken);

int dispatch_platform_hardware(nvm_state_t* state, uint16_t signature, STACKWORD argv[], _Bool* taken);
int check_platform_hardware_event(const uint8_t type);
void trigger_hardware_event_check();

extern void bridge_open(void);
extern void realFlush(void);

#endif
