/* See LICENSE file for copyright and license details. */ #include "common.h" enum libsyscalls_error libsyscalls_make_signed_integer(unsigned long long int value_in, int negative, enum libsyscalls_datatype_sign_representation representation, size_t bits, unsigned long long int *value_out) { unsigned long long int value = value_in, mask, highbit; if (!bits || bits > sizeof(value) / sizeof(char) * CHAR_BIT) return LIBSYSCALLS_E_INVAL; switch (representation) { case LIBSYSCALLS_SIGN_UNDETERMINED: break; case LIBSYSCALLS_SIGN_TWOS_COMPLEMENT: if (negative && value) { highbit = 1ULL << (bits - 1U); mask = highbit - 1ULL; value = ~(value - 1) & mask; value |= highbit; } break; case LIBSYSCALLS_SIGN_ONES_COMPLEMENT: if (negative) { highbit = 1ULL << (bits - 1U); mask = highbit - 1ULL; value = ~value & mask; value |= highbit; } break; case LIBSYSCALLS_SIGN_SIGN_MAGNITUDE: if (negative) value ^= 1ULL << (bits - 1); break; case LIBSYSCALLS_SIGN_EXCESS_HALF: if (!negative) value ^= 1ULL << (bits - 1); else value = (1ULL << (bits - 1)) - value; break; default: return LIBSYSCALLS_E_INVAL; } if (value_out) *value_out = value; return LIBSYSCALLS_E_OK; }