/*============================================================================

This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.

Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California.  All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 1. Redistributions of source code must retain the above copyright notice,
    this list of conditions, and the following disclaimer.

 2. Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions, and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

 3. Neither the name of the University nor the names of its contributors may
    be used to endorse or promote products derived from this software without
    specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=============================================================================*/

#ifndef _INTERNALS_H_
#define _INTERNALS_H_

#include <stdbool.h>
#include <stdint.h>
//#include "primitives.h"
#include "softfloat_types.h"

struct softfloat_status_t;

#ifdef __cplusplus
extern "C" {
#endif

/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
uint32_t softfloat_roundToUI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *);
uint64_t softfloat_roundToUI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *);

int32_t softfloat_roundToI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *);
int64_t softfloat_roundToI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *);

/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/


#define signF16UI(a) ((bool) ((uint16_t) (a)>>15))
#define expF16UI(a) ((int8_t) ((a)>>10) & 0x1F)
#define fracF16UI(a) ((a) & 0x03FF)
#define packToF16UI(sign, exp, sig) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig))

#define isNaNF16UI(a) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF))

struct exp8_sig16 { int8_t exp; uint16_t sig; };
struct exp8_sig16 softfloat_normSubnormalF16Sig(uint16_t);

float16 softfloat_roundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *);
float16 softfloat_normRoundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *);

/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signF32UI(a) ((bool) ((uint32_t) (a)>>31))
#define expF32UI(a) ((int16_t) ((a)>>23) & 0xFF)
#define fracF32UI(a) ((a) & 0x007FFFFF)
#define packToF32UI(sign, exp, sig) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig))

#define isNaNF32UI(a) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF))

struct exp16_sig32 { int16_t exp; uint32_t sig; };
struct exp16_sig32 softfloat_normSubnormalF32Sig(uint32_t);

float32 softfloat_roundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *);
float32 softfloat_normRoundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *);

/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signF64UI(a) ((bool) ((uint64_t) (a)>>63))
#define expF64UI(a) ((int16_t) ((a)>>52) & 0x7FF)
#define fracF64UI(a) ((a) & UINT64_C(0x000FFFFFFFFFFFFF))
#define packToF64UI(sign, exp, sig) ((uint64_t) (((uint64_t) (sign)<<63) + ((uint64_t) (exp)<<52) + (sig)))

#define isNaNF64UI(a) (((~(a) & UINT64_C(0x7FF0000000000000)) == 0) && ((a) & UINT64_C(0x000FFFFFFFFFFFFF)))

struct exp16_sig64 { int16_t exp; uint64_t sig; };
struct exp16_sig64 softfloat_normSubnormalF64Sig(uint64_t);

float64 softfloat_roundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *);
float64 softfloat_normRoundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *);

/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/

extFloat80_t softfloat_addMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status);
extFloat80_t softfloat_subMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status);

#define signExtF80UI64(a64) ((bool) ((uint16_t) (a64)>>15))
#define expExtF80UI64(a64) ((a64) & 0x7FFF)
#define packToExtF80UI64(sign, exp) ((uint16_t) (sign)<<15 | (exp))

#define isNaNExtF80UI(a64, a0) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C(0x7FFFFFFFFFFFFFFF)))

extFloat80_t packToExtF80(bool, uint16_t, uint64_t);
extFloat80_t packToExtF80_twoargs(uint16_t, uint64_t);
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/

struct exp32_sig64 { int32_t exp; uint64_t sig; };
struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint64_t);

extFloat80_t
 softfloat_roundPackToExtF80(bool, int32_t, uint64_t, uint64_t, uint8_t, struct softfloat_status_t *);
extFloat80_t
 softfloat_normRoundPackToExtF80(bool, int32_t, uint64_t, uint64_t, uint8_t, struct softfloat_status_t *);

/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signF128UI64(a64) ((bool) ((uint64_t) (a64)>>63))
#define expF128UI64(a64) ((int32_t) ((a64)>>48) & 0x7FFF)
#define fracF128UI64(a64) ((a64) & UINT64_C(0x0000FFFFFFFFFFFF))
#define packToF128UI64(sign, exp, sig64) (((uint64_t) (sign)<<63) + ((uint64_t) (exp)<<48) + (sig64))

#define isNaNF128UI(a64, a0) (((~(a64) & UINT64_C(0x7FFF000000000000)) == 0) && (a0 || ((a64) & UINT64_C(0x0000FFFFFFFFFFFF))))

struct exp32_sig128 { int32_t exp; struct uint128 sig; };
struct exp32_sig128 softfloat_normSubnormalF128Sig(uint64_t, uint64_t);

float128_t
 softfloat_roundPackToF128(bool, int32_t, uint64_t, uint64_t, uint64_t, struct softfloat_status_t *);
float128_t
 softfloat_normRoundPackToF128(bool, int32_t, uint64_t, uint64_t, struct softfloat_status_t *);
#ifdef __cplusplus
}
#endif

#endif
