custom_float.c (4116B)
1/* 2 * Copyright 2017 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25#include "dm_services.h" 26#include "custom_float.h" 27 28 29static bool build_custom_float( 30 struct fixed31_32 value, 31 const struct custom_float_format *format, 32 bool *negative, 33 uint32_t *mantissa, 34 uint32_t *exponenta) 35{ 36 uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1; 37 38 const struct fixed31_32 mantissa_constant_plus_max_fraction = 39 dc_fixpt_from_fraction( 40 (1LL << (format->mantissa_bits + 1)) - 1, 41 1LL << format->mantissa_bits); 42 43 struct fixed31_32 mantiss; 44 45 if (dc_fixpt_eq( 46 value, 47 dc_fixpt_zero)) { 48 *negative = false; 49 *mantissa = 0; 50 *exponenta = 0; 51 return true; 52 } 53 54 if (dc_fixpt_lt( 55 value, 56 dc_fixpt_zero)) { 57 *negative = format->sign; 58 value = dc_fixpt_neg(value); 59 } else { 60 *negative = false; 61 } 62 63 if (dc_fixpt_lt( 64 value, 65 dc_fixpt_one)) { 66 uint32_t i = 1; 67 68 do { 69 value = dc_fixpt_shl(value, 1); 70 ++i; 71 } while (dc_fixpt_lt( 72 value, 73 dc_fixpt_one)); 74 75 --i; 76 77 if (exp_offset <= i) { 78 *mantissa = 0; 79 *exponenta = 0; 80 return true; 81 } 82 83 *exponenta = exp_offset - i; 84 } else if (dc_fixpt_le( 85 mantissa_constant_plus_max_fraction, 86 value)) { 87 uint32_t i = 1; 88 89 do { 90 value = dc_fixpt_shr(value, 1); 91 ++i; 92 } while (dc_fixpt_lt( 93 mantissa_constant_plus_max_fraction, 94 value)); 95 96 *exponenta = exp_offset + i - 1; 97 } else { 98 *exponenta = exp_offset; 99 } 100 101 mantiss = dc_fixpt_sub( 102 value, 103 dc_fixpt_one); 104 105 if (dc_fixpt_lt( 106 mantiss, 107 dc_fixpt_zero) || 108 dc_fixpt_lt( 109 dc_fixpt_one, 110 mantiss)) 111 mantiss = dc_fixpt_zero; 112 else 113 mantiss = dc_fixpt_shl( 114 mantiss, 115 format->mantissa_bits); 116 117 *mantissa = dc_fixpt_floor(mantiss); 118 119 return true; 120} 121 122static bool setup_custom_float( 123 const struct custom_float_format *format, 124 bool negative, 125 uint32_t mantissa, 126 uint32_t exponenta, 127 uint32_t *result) 128{ 129 uint32_t i = 0; 130 uint32_t j = 0; 131 132 uint32_t value = 0; 133 134 /* verification code: 135 * once calculation is ok we can remove it 136 */ 137 138 const uint32_t mantissa_mask = 139 (1 << (format->mantissa_bits + 1)) - 1; 140 141 const uint32_t exponenta_mask = 142 (1 << (format->exponenta_bits + 1)) - 1; 143 144 if (mantissa & ~mantissa_mask) { 145 BREAK_TO_DEBUGGER(); 146 mantissa = mantissa_mask; 147 } 148 149 if (exponenta & ~exponenta_mask) { 150 BREAK_TO_DEBUGGER(); 151 exponenta = exponenta_mask; 152 } 153 154 /* end of verification code */ 155 156 while (i < format->mantissa_bits) { 157 uint32_t mask = 1 << i; 158 159 if (mantissa & mask) 160 value |= mask; 161 162 ++i; 163 } 164 165 while (j < format->exponenta_bits) { 166 uint32_t mask = 1 << j; 167 168 if (exponenta & mask) 169 value |= mask << i; 170 171 ++j; 172 } 173 174 if (negative && format->sign) 175 value |= 1 << (i + j); 176 177 *result = value; 178 179 return true; 180} 181 182bool convert_to_custom_float_format( 183 struct fixed31_32 value, 184 const struct custom_float_format *format, 185 uint32_t *result) 186{ 187 uint32_t mantissa; 188 uint32_t exponenta; 189 bool negative; 190 191 return build_custom_float( 192 value, format, &negative, &mantissa, &exponenta) && 193 setup_custom_float( 194 format, negative, mantissa, exponenta, result); 195} 196 197