mirror of
https://github.com/Z3Prover/z3
synced 2025-05-06 23:35:46 +00:00
165 lines
4.6 KiB
C
165 lines
4.6 KiB
C
/* Copyright (c) INRIA and Microsoft Corporation. All rights reserved.
|
|
Licensed under the Apache 2.0 License. */
|
|
|
|
/******************************************************************************/
|
|
/* Machine integers (128-bit arithmetic) */
|
|
/******************************************************************************/
|
|
|
|
/* This header contains two things.
|
|
*
|
|
* First, an implementation of 128-bit arithmetic suitable for 64-bit GCC and
|
|
* Clang, i.e. all the operations from FStar.UInt128.
|
|
*
|
|
* Second, 128-bit operations from C.Endianness (or LowStar.Endianness),
|
|
* suitable for any compiler and platform (via a series of ifdefs). This second
|
|
* part is unfortunate, and should be fixed by moving {load,store}128_{be,le} to
|
|
* FStar.UInt128 to avoid a maze of preprocessor guards and hand-written code.
|
|
* */
|
|
|
|
/* This file is used for both the minimal and generic kremlib distributions. As
|
|
* such, it assumes that the machine integers have been bundled the exact same
|
|
* way in both cases. */
|
|
|
|
#ifndef FSTAR_UINT128_GCC64
|
|
#define FSTAR_UINT128_GCC64
|
|
|
|
#include "math/bigfix/FStar_UInt128.h"
|
|
#include "math/bigfix/FStar_UInt_8_16_32_64.h"
|
|
#include "math/bigfix/LowStar_Endianness.h"
|
|
|
|
/* GCC + using native unsigned __int128 support */
|
|
|
|
inline static uint128_t load128_le(uint8_t *b) {
|
|
uint128_t l = (uint128_t)load64_le(b);
|
|
uint128_t h = (uint128_t)load64_le(b + 8);
|
|
return (h << 64 | l);
|
|
}
|
|
|
|
inline static void store128_le(uint8_t *b, uint128_t n) {
|
|
store64_le(b, (uint64_t)n);
|
|
store64_le(b + 8, (uint64_t)(n >> 64));
|
|
}
|
|
|
|
inline static uint128_t load128_be(uint8_t *b) {
|
|
uint128_t h = (uint128_t)load64_be(b);
|
|
uint128_t l = (uint128_t)load64_be(b + 8);
|
|
return (h << 64 | l);
|
|
}
|
|
|
|
inline static void store128_be(uint8_t *b, uint128_t n) {
|
|
store64_be(b, (uint64_t)(n >> 64));
|
|
store64_be(b + 8, (uint64_t)n);
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_add(uint128_t x, uint128_t y) {
|
|
return x + y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_mul(uint128_t x, uint128_t y) {
|
|
return x * y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_add_mod(uint128_t x, uint128_t y) {
|
|
return x + y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_sub(uint128_t x, uint128_t y) {
|
|
return x - y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_sub_mod(uint128_t x, uint128_t y) {
|
|
return x - y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_logand(uint128_t x, uint128_t y) {
|
|
return x & y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_logor(uint128_t x, uint128_t y) {
|
|
return x | y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_logxor(uint128_t x, uint128_t y) {
|
|
return x ^ y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_lognot(uint128_t x) {
|
|
return ~x;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_shift_left(uint128_t x, uint32_t y) {
|
|
return x << y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_shift_right(uint128_t x, uint32_t y) {
|
|
return x >> y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_uint64_to_uint128(uint64_t x) {
|
|
return (uint128_t)x;
|
|
}
|
|
|
|
inline static uint64_t FStar_UInt128_uint128_to_uint64(uint128_t x) {
|
|
return (uint64_t)x;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_mul_wide(uint64_t x, uint64_t y) {
|
|
return ((uint128_t) x) * y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_eq_mask(uint128_t x, uint128_t y) {
|
|
uint64_t mask =
|
|
FStar_UInt64_eq_mask((uint64_t)(x >> 64), (uint64_t)(y >> 64)) &
|
|
FStar_UInt64_eq_mask(x, y);
|
|
return ((uint128_t)mask) << 64 | mask;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_gte_mask(uint128_t x, uint128_t y) {
|
|
uint64_t mask =
|
|
(FStar_UInt64_gte_mask(x >> 64, y >> 64) &
|
|
~(FStar_UInt64_eq_mask(x >> 64, y >> 64))) |
|
|
(FStar_UInt64_eq_mask(x >> 64, y >> 64) & FStar_UInt64_gte_mask(x, y));
|
|
return ((uint128_t)mask) << 64 | mask;
|
|
}
|
|
|
|
inline static uint64_t FStar_UInt128___proj__Mkuint128__item__low(uint128_t x) {
|
|
return (uint64_t) x;
|
|
}
|
|
|
|
inline static uint64_t FStar_UInt128___proj__Mkuint128__item__high(uint128_t x) {
|
|
return (uint64_t) (x >> 64);
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_add_underspec(uint128_t x, uint128_t y) {
|
|
return x + y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_sub_underspec(uint128_t x, uint128_t y) {
|
|
return x - y;
|
|
}
|
|
|
|
inline static bool FStar_UInt128_eq(uint128_t x, uint128_t y) {
|
|
return x == y;
|
|
}
|
|
|
|
inline static bool FStar_UInt128_gt(uint128_t x, uint128_t y) {
|
|
return x > y;
|
|
}
|
|
|
|
inline static bool FStar_UInt128_lt(uint128_t x, uint128_t y) {
|
|
return x < y;
|
|
}
|
|
|
|
inline static bool FStar_UInt128_gte(uint128_t x, uint128_t y) {
|
|
return x >= y;
|
|
}
|
|
|
|
inline static bool FStar_UInt128_lte(uint128_t x, uint128_t y) {
|
|
return x <= y;
|
|
}
|
|
|
|
inline static uint128_t FStar_UInt128_mul32(uint64_t x, uint32_t y) {
|
|
return (uint128_t) x * (uint128_t) y;
|
|
}
|
|
|
|
#endif
|