/*
 * 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 _TYPES_H
#define _TYPES_H

#include "configure.h"
#include "platform_config.h"
#include "exit_trace.h"

typedef byte boolean;
typedef uint16_t nvm_array_size_t;
typedef uint32_t nvm_binary_size_t;
typedef uint16_t nvm_class_index_t;
typedef uint16_t nvm_method_index_t;

/*
 * The following types must be defined in platform_config.h:
 * JBYTE
 * JSHORT
 * JINT
 * uint16_t
 * uint32_t
 */

typedef float       JFLOAT;
typedef JBYTE       JBOOLEAN;
typedef uint16_t    JCHAR;
//typedef uint32_t    REFERENCE;
typedef struct {
    uint32_t refval;
} REFERENCE;
typedef uint32_t    STACKWORD;
typedef volatile uint64_t TIMESTAMP;
#define APOCALYPSE (~((TIMESTAMP) 0))
typedef int64_t    LLONG;
typedef uint64_t   ULLONG;
typedef LLONG JLONG;
typedef double JDOUBLE;

// Representation punning via memcpy
static inline STACKWORD jfloat2word(JFLOAT f)
{
    STACKWORD t;
    memcpy(&t, &f, sizeof(STACKWORD));
    return t;
}

static inline JFLOAT word2jfloat(STACKWORD s)
{
    JFLOAT f;
    memcpy(&f, &s, sizeof(JFLOAT));
    return f;
}

#define byte2jint(BYTE_)    ((JINT) (signed char) (BYTE_))
#define word2jint(WORD_)    ((JINT) (WORD_))
#define word2jshort(WORD_)  ((JSHORT) (WORD_))
#define obj2ref(OBJ_)       ptr2ref(OBJ_)
#define obj2ptr(OBJ_)       ((void *) (OBJ_))

#if RELATIVE_REFERENCES

static inline uint32_t adjust_ptr2ref(void* pState, const void* ptr)
{
    if (ptr == NULL) {
        return UINT32_C(0);
    } else {
        return ((uint32_t) (((byte*) ptr) - ((byte*) pState)));
    }
}

static inline void* adjust_ref2ptr(void* pState, uint32_t val)
{
    if (val == UINT32_C(0)) {
        return NULL;
    } else {
        return (void*) (((byte*) pState) + val);
    }
}

#define ptr2ref(PTR_)       ((REFERENCE) { .refval = adjust_ptr2ref(pState, PTR_) })
#define ref2ptr(REF_)       (adjust_ref2ptr(pState, (REF_).refval))

#else

#define ptr2ref(PTR_)       ((REFERENCE) { .refval = (uint32_t) (uintptr_t) (PTR_) })
#define ref2ptr(REF_)       ((void*) (uintptr_t) ((REF_).refval))

#endif

#define stackword2ref(WORD_) ((REFERENCE) { .refval = WORD_ })
#define ref2stackword(REF_) ((REF_).refval)
#define ref2obj(REF_)       ((Object *) ref2ptr(REF_))
#define word2obj(WORD_)     ref2obj(stackword2ref(WORD_))

#define ref_null_p(REF_)    (ref2ptr(REF_) == NULL)

#endif


