brintos

brintos / linux-shallow public Read only

0
0
Text · 3.1 KiB · be2f34d Raw
152 lines · c
1// SPDX-License-Identifier: MIT2//3// Copyright 2024 Advanced Micro Devices, Inc.4 5#include "spl_debug.h"6#include "spl_custom_float.h"7 8static bool spl_build_custom_float(struct spl_fixed31_32 value,9			       const struct spl_custom_float_format *format,10			       bool *negative,11			       uint32_t *mantissa,12			       uint32_t *exponenta)13{14	uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;15 16	const struct spl_fixed31_32 mantissa_constant_plus_max_fraction =17		spl_fixpt_from_fraction((1LL << (format->mantissa_bits + 1)) - 1,18				       1LL << format->mantissa_bits);19 20	struct spl_fixed31_32 mantiss;21 22	if (spl_fixpt_eq(value, spl_fixpt_zero)) {23		*negative = false;24		*mantissa = 0;25		*exponenta = 0;26		return true;27	}28 29	if (spl_fixpt_lt(value, spl_fixpt_zero)) {30		*negative = format->sign;31		value = spl_fixpt_neg(value);32	} else {33		*negative = false;34	}35 36	if (spl_fixpt_lt(value, spl_fixpt_one)) {37		uint32_t i = 1;38 39		do {40			value = spl_fixpt_shl(value, 1);41			++i;42		} while (spl_fixpt_lt(value, spl_fixpt_one));43 44		--i;45 46		if (exp_offset <= i) {47			*mantissa = 0;48			*exponenta = 0;49			return true;50		}51 52		*exponenta = exp_offset - i;53	} else if (spl_fixpt_le(mantissa_constant_plus_max_fraction, value)) {54		uint32_t i = 1;55 56		do {57			value = spl_fixpt_shr(value, 1);58			++i;59		} while (spl_fixpt_lt(mantissa_constant_plus_max_fraction, value));60 61		*exponenta = exp_offset + i - 1;62	} else {63		*exponenta = exp_offset;64	}65 66	mantiss = spl_fixpt_sub(value, spl_fixpt_one);67 68	if (spl_fixpt_lt(mantiss, spl_fixpt_zero) ||69	    spl_fixpt_lt(spl_fixpt_one, mantiss))70		mantiss = spl_fixpt_zero;71	else72		mantiss = spl_fixpt_shl(mantiss, format->mantissa_bits);73 74	*mantissa = spl_fixpt_floor(mantiss);75 76	return true;77}78 79static bool spl_setup_custom_float(const struct spl_custom_float_format *format,80			       bool negative,81			       uint32_t mantissa,82			       uint32_t exponenta,83			       uint32_t *result)84{85	uint32_t i = 0;86	uint32_t j = 0;87	uint32_t value = 0;88 89	/* verification code:90	 * once calculation is ok we can remove it91	 */92 93	const uint32_t mantissa_mask =94		(1 << (format->mantissa_bits + 1)) - 1;95 96	const uint32_t exponenta_mask =97		(1 << (format->exponenta_bits + 1)) - 1;98 99	if (mantissa & ~mantissa_mask) {100		SPL_BREAK_TO_DEBUGGER();101		mantissa = mantissa_mask;102	}103 104	if (exponenta & ~exponenta_mask) {105		SPL_BREAK_TO_DEBUGGER();106		exponenta = exponenta_mask;107	}108 109	/* end of verification code */110 111	while (i < format->mantissa_bits) {112		uint32_t mask = 1 << i;113 114		if (mantissa & mask)115			value |= mask;116 117		++i;118	}119 120	while (j < format->exponenta_bits) {121		uint32_t mask = 1 << j;122 123		if (exponenta & mask)124			value |= mask << i;125 126		++j;127	}128 129	if (negative && format->sign)130		value |= 1 << (i + j);131 132	*result = value;133 134	return true;135}136 137bool spl_convert_to_custom_float_format(struct spl_fixed31_32 value,138				    const struct spl_custom_float_format *format,139				    uint32_t *result)140{141	uint32_t mantissa;142	uint32_t exponenta;143	bool negative;144 145	return spl_build_custom_float(value, format, &negative, &mantissa, &exponenta) &&146				  spl_setup_custom_float(format,147						     negative,148						     mantissa,149						     exponenta,150						     result);151}152