Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2017 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 #include "dm_services.h"
0026 #include "custom_float.h"
0027 
0028 
0029 static bool build_custom_float(
0030     struct fixed31_32 value,
0031     const struct custom_float_format *format,
0032     bool *negative,
0033     uint32_t *mantissa,
0034     uint32_t *exponenta)
0035 {
0036     uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
0037 
0038     const struct fixed31_32 mantissa_constant_plus_max_fraction =
0039         dc_fixpt_from_fraction(
0040             (1LL << (format->mantissa_bits + 1)) - 1,
0041             1LL << format->mantissa_bits);
0042 
0043     struct fixed31_32 mantiss;
0044 
0045     if (dc_fixpt_eq(
0046         value,
0047         dc_fixpt_zero)) {
0048         *negative = false;
0049         *mantissa = 0;
0050         *exponenta = 0;
0051         return true;
0052     }
0053 
0054     if (dc_fixpt_lt(
0055         value,
0056         dc_fixpt_zero)) {
0057         *negative = format->sign;
0058         value = dc_fixpt_neg(value);
0059     } else {
0060         *negative = false;
0061     }
0062 
0063     if (dc_fixpt_lt(
0064         value,
0065         dc_fixpt_one)) {
0066         uint32_t i = 1;
0067 
0068         do {
0069             value = dc_fixpt_shl(value, 1);
0070             ++i;
0071         } while (dc_fixpt_lt(
0072             value,
0073             dc_fixpt_one));
0074 
0075         --i;
0076 
0077         if (exp_offset <= i) {
0078             *mantissa = 0;
0079             *exponenta = 0;
0080             return true;
0081         }
0082 
0083         *exponenta = exp_offset - i;
0084     } else if (dc_fixpt_le(
0085         mantissa_constant_plus_max_fraction,
0086         value)) {
0087         uint32_t i = 1;
0088 
0089         do {
0090             value = dc_fixpt_shr(value, 1);
0091             ++i;
0092         } while (dc_fixpt_lt(
0093             mantissa_constant_plus_max_fraction,
0094             value));
0095 
0096         *exponenta = exp_offset + i - 1;
0097     } else {
0098         *exponenta = exp_offset;
0099     }
0100 
0101     mantiss = dc_fixpt_sub(
0102         value,
0103         dc_fixpt_one);
0104 
0105     if (dc_fixpt_lt(
0106             mantiss,
0107             dc_fixpt_zero) ||
0108         dc_fixpt_lt(
0109             dc_fixpt_one,
0110             mantiss))
0111         mantiss = dc_fixpt_zero;
0112     else
0113         mantiss = dc_fixpt_shl(
0114             mantiss,
0115             format->mantissa_bits);
0116 
0117     *mantissa = dc_fixpt_floor(mantiss);
0118 
0119     return true;
0120 }
0121 
0122 static bool setup_custom_float(
0123     const struct custom_float_format *format,
0124     bool negative,
0125     uint32_t mantissa,
0126     uint32_t exponenta,
0127     uint32_t *result)
0128 {
0129     uint32_t i = 0;
0130     uint32_t j = 0;
0131 
0132     uint32_t value = 0;
0133 
0134     /* verification code:
0135      * once calculation is ok we can remove it
0136      */
0137 
0138     const uint32_t mantissa_mask =
0139         (1 << (format->mantissa_bits + 1)) - 1;
0140 
0141     const uint32_t exponenta_mask =
0142         (1 << (format->exponenta_bits + 1)) - 1;
0143 
0144     if (mantissa & ~mantissa_mask) {
0145         BREAK_TO_DEBUGGER();
0146         mantissa = mantissa_mask;
0147     }
0148 
0149     if (exponenta & ~exponenta_mask) {
0150         BREAK_TO_DEBUGGER();
0151         exponenta = exponenta_mask;
0152     }
0153 
0154     /* end of verification code */
0155 
0156     while (i < format->mantissa_bits) {
0157         uint32_t mask = 1 << i;
0158 
0159         if (mantissa & mask)
0160             value |= mask;
0161 
0162         ++i;
0163     }
0164 
0165     while (j < format->exponenta_bits) {
0166         uint32_t mask = 1 << j;
0167 
0168         if (exponenta & mask)
0169             value |= mask << i;
0170 
0171         ++j;
0172     }
0173 
0174     if (negative && format->sign)
0175         value |= 1 << (i + j);
0176 
0177     *result = value;
0178 
0179     return true;
0180 }
0181 
0182 bool convert_to_custom_float_format(
0183     struct fixed31_32 value,
0184     const struct custom_float_format *format,
0185     uint32_t *result)
0186 {
0187     uint32_t mantissa;
0188     uint32_t exponenta;
0189     bool negative;
0190 
0191     return build_custom_float(
0192         value, format, &negative, &mantissa, &exponenta) &&
0193     setup_custom_float(
0194         format, negative, mantissa, exponenta, result);
0195 }
0196 
0197