1 /* Software floating-point emulation. 2 Basic eight-word fraction declaration and manipulation. 3 Copyright (C) 1997-2022 Free Software Foundation, Inc. 4 This file is part of the GNU C Library. 5 6 The GNU C Library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 In addition to the permissions in the GNU Lesser General Public 12 License, the Free Software Foundation gives you unlimited 13 permission to link the compiled version of this file into 14 combinations with other programs, and to distribute those 15 combinations without any restriction coming from the use of this 16 file. (The Lesser General Public License restrictions do apply in 17 other respects; for example, they cover modification of the file, 18 and distribution when not linked into a combine executable.) 19 20 The GNU C Library is distributed in the hope that it will be useful, 21 but WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 Lesser General Public License for more details. 24 25 You should have received a copy of the GNU Lesser General Public 26 License along with the GNU C Library; if not, see 27 <https://www.gnu.org/licenses/>. */ 28 29 #ifndef SOFT_FP_OP_8_H 30 #define SOFT_FP_OP_8_H 1 31 32 /* We need just a few things from here for op-4, if we ever need some 33 other macros, they can be added. */ 34 #define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8] 35 #define _FP_FRAC_SET_8(X, I) __FP_FRAC_SET_8 (X, I) 36 #define _FP_FRAC_HIGH_8(X) (X##_f[7]) 37 #define _FP_FRAC_LOW_8(X) (X##_f[0]) 38 #define _FP_FRAC_WORD_8(X, w) (X##_f[w]) 39 40 #define _FP_FRAC_SLL_8(X, N) \ 41 do \ 42 { \ 43 _FP_I_TYPE _FP_FRAC_SLL_8_up, _FP_FRAC_SLL_8_down; \ 44 _FP_I_TYPE _FP_FRAC_SLL_8_skip, _FP_FRAC_SLL_8_i; \ 45 _FP_FRAC_SLL_8_skip = (N) / _FP_W_TYPE_SIZE; \ 46 _FP_FRAC_SLL_8_up = (N) % _FP_W_TYPE_SIZE; \ 47 _FP_FRAC_SLL_8_down = _FP_W_TYPE_SIZE - _FP_FRAC_SLL_8_up; \ 48 if (!_FP_FRAC_SLL_8_up) \ 49 for (_FP_FRAC_SLL_8_i = 7; \ 50 _FP_FRAC_SLL_8_i >= _FP_FRAC_SLL_8_skip; \ 51 --_FP_FRAC_SLL_8_i) \ 52 X##_f[_FP_FRAC_SLL_8_i] \ 53 = X##_f[_FP_FRAC_SLL_8_i-_FP_FRAC_SLL_8_skip]; \ 54 else \ 55 { \ 56 for (_FP_FRAC_SLL_8_i = 7; \ 57 _FP_FRAC_SLL_8_i > _FP_FRAC_SLL_8_skip; \ 58 --_FP_FRAC_SLL_8_i) \ 59 X##_f[_FP_FRAC_SLL_8_i] \ 60 = ((X##_f[_FP_FRAC_SLL_8_i-_FP_FRAC_SLL_8_skip] \ 61 << _FP_FRAC_SLL_8_up) \ 62 | (X##_f[_FP_FRAC_SLL_8_i-_FP_FRAC_SLL_8_skip-1] \ 63 >> _FP_FRAC_SLL_8_down)); \ 64 X##_f[_FP_FRAC_SLL_8_i--] = X##_f[0] << _FP_FRAC_SLL_8_up; \ 65 } \ 66 for (; _FP_FRAC_SLL_8_i >= 0; --_FP_FRAC_SLL_8_i) \ 67 X##_f[_FP_FRAC_SLL_8_i] = 0; \ 68 } \ 69 while (0) 70 71 #define _FP_FRAC_SRL_8(X, N) \ 72 do \ 73 { \ 74 _FP_I_TYPE _FP_FRAC_SRL_8_up, _FP_FRAC_SRL_8_down; \ 75 _FP_I_TYPE _FP_FRAC_SRL_8_skip, _FP_FRAC_SRL_8_i; \ 76 _FP_FRAC_SRL_8_skip = (N) / _FP_W_TYPE_SIZE; \ 77 _FP_FRAC_SRL_8_down = (N) % _FP_W_TYPE_SIZE; \ 78 _FP_FRAC_SRL_8_up = _FP_W_TYPE_SIZE - _FP_FRAC_SRL_8_down; \ 79 if (!_FP_FRAC_SRL_8_down) \ 80 for (_FP_FRAC_SRL_8_i = 0; \ 81 _FP_FRAC_SRL_8_i <= 7-_FP_FRAC_SRL_8_skip; \ 82 ++_FP_FRAC_SRL_8_i) \ 83 X##_f[_FP_FRAC_SRL_8_i] \ 84 = X##_f[_FP_FRAC_SRL_8_i+_FP_FRAC_SRL_8_skip]; \ 85 else \ 86 { \ 87 for (_FP_FRAC_SRL_8_i = 0; \ 88 _FP_FRAC_SRL_8_i < 7-_FP_FRAC_SRL_8_skip; \ 89 ++_FP_FRAC_SRL_8_i) \ 90 X##_f[_FP_FRAC_SRL_8_i] \ 91 = ((X##_f[_FP_FRAC_SRL_8_i+_FP_FRAC_SRL_8_skip] \ 92 >> _FP_FRAC_SRL_8_down) \ 93 | (X##_f[_FP_FRAC_SRL_8_i+_FP_FRAC_SRL_8_skip+1] \ 94 << _FP_FRAC_SRL_8_up)); \ 95 X##_f[_FP_FRAC_SRL_8_i++] = X##_f[7] >> _FP_FRAC_SRL_8_down; \ 96 } \ 97 for (; _FP_FRAC_SRL_8_i < 8; ++_FP_FRAC_SRL_8_i) \ 98 X##_f[_FP_FRAC_SRL_8_i] = 0; \ 99 } \ 100 while (0) 101 102 103 /* Right shift with sticky-lsb. 104 What this actually means is that we do a standard right-shift, 105 but that if any of the bits that fall off the right hand side 106 were one then we always set the LSbit. */ 107 #define _FP_FRAC_SRS_8(X, N, size) \ 108 do \ 109 { \ 110 _FP_I_TYPE _FP_FRAC_SRS_8_up, _FP_FRAC_SRS_8_down; \ 111 _FP_I_TYPE _FP_FRAC_SRS_8_skip, _FP_FRAC_SRS_8_i; \ 112 _FP_W_TYPE _FP_FRAC_SRS_8_s; \ 113 _FP_FRAC_SRS_8_skip = (N) / _FP_W_TYPE_SIZE; \ 114 _FP_FRAC_SRS_8_down = (N) % _FP_W_TYPE_SIZE; \ 115 _FP_FRAC_SRS_8_up = _FP_W_TYPE_SIZE - _FP_FRAC_SRS_8_down; \ 116 for (_FP_FRAC_SRS_8_s = _FP_FRAC_SRS_8_i = 0; \ 117 _FP_FRAC_SRS_8_i < _FP_FRAC_SRS_8_skip; \ 118 ++_FP_FRAC_SRS_8_i) \ 119 _FP_FRAC_SRS_8_s |= X##_f[_FP_FRAC_SRS_8_i]; \ 120 if (!_FP_FRAC_SRS_8_down) \ 121 for (_FP_FRAC_SRS_8_i = 0; \ 122 _FP_FRAC_SRS_8_i <= 7-_FP_FRAC_SRS_8_skip; \ 123 ++_FP_FRAC_SRS_8_i) \ 124 X##_f[_FP_FRAC_SRS_8_i] \ 125 = X##_f[_FP_FRAC_SRS_8_i+_FP_FRAC_SRS_8_skip]; \ 126 else \ 127 { \ 128 _FP_FRAC_SRS_8_s \ 129 |= X##_f[_FP_FRAC_SRS_8_i] << _FP_FRAC_SRS_8_up; \ 130 for (_FP_FRAC_SRS_8_i = 0; \ 131 _FP_FRAC_SRS_8_i < 7-_FP_FRAC_SRS_8_skip; \ 132 ++_FP_FRAC_SRS_8_i) \ 133 X##_f[_FP_FRAC_SRS_8_i] \ 134 = ((X##_f[_FP_FRAC_SRS_8_i+_FP_FRAC_SRS_8_skip] \ 135 >> _FP_FRAC_SRS_8_down) \ 136 | (X##_f[_FP_FRAC_SRS_8_i+_FP_FRAC_SRS_8_skip+1] \ 137 << _FP_FRAC_SRS_8_up)); \ 138 X##_f[_FP_FRAC_SRS_8_i++] = X##_f[7] >> _FP_FRAC_SRS_8_down; \ 139 } \ 140 for (; _FP_FRAC_SRS_8_i < 8; ++_FP_FRAC_SRS_8_i) \ 141 X##_f[_FP_FRAC_SRS_8_i] = 0; \ 142 /* Don't fix the LSB until the very end when we're sure f[0] is \ 143 stable. */ \ 144 X##_f[0] |= (_FP_FRAC_SRS_8_s != 0); \ 145 } \ 146 while (0) 147 148 #define _FP_FRAC_ADD_8(R, X, Y) \ 149 do \ 150 { \ 151 _FP_W_TYPE _FP_FRAC_ADD_8_c = 0; \ 152 _FP_I_TYPE _FP_FRAC_ADD_8_i; \ 153 for (_FP_FRAC_ADD_8_i = 0; _FP_FRAC_ADD_8_i < 8; ++_FP_FRAC_ADD_8_i) \ 154 { \ 155 R##_f[_FP_FRAC_ADD_8_i] \ 156 = (X##_f[_FP_FRAC_ADD_8_i] + Y##_f[_FP_FRAC_ADD_8_i] \ 157 + _FP_FRAC_ADD_8_c); \ 158 _FP_FRAC_ADD_8_c \ 159 = (_FP_FRAC_ADD_8_c \ 160 ? R##_f[_FP_FRAC_ADD_8_i] <= X##_f[_FP_FRAC_ADD_8_i] \ 161 : R##_f[_FP_FRAC_ADD_8_i] < X##_f[_FP_FRAC_ADD_8_i]); \ 162 } \ 163 } \ 164 while (0) 165 166 #define _FP_FRAC_SUB_8(R, X, Y) \ 167 do \ 168 { \ 169 _FP_W_TYPE _FP_FRAC_SUB_8_tmp[8]; \ 170 _FP_W_TYPE _FP_FRAC_SUB_8_c = 0; \ 171 _FP_I_TYPE _FP_FRAC_SUB_8_i; \ 172 for (_FP_FRAC_SUB_8_i = 0; _FP_FRAC_SUB_8_i < 8; ++_FP_FRAC_SUB_8_i) \ 173 { \ 174 _FP_FRAC_SUB_8_tmp[_FP_FRAC_SUB_8_i] \ 175 = (X##_f[_FP_FRAC_SUB_8_i] - Y##_f[_FP_FRAC_SUB_8_i] \ 176 - _FP_FRAC_SUB_8_c); \ 177 _FP_FRAC_SUB_8_c \ 178 = (_FP_FRAC_SUB_8_c \ 179 ? (_FP_FRAC_SUB_8_tmp[_FP_FRAC_SUB_8_i] \ 180 >= X##_f[_FP_FRAC_SUB_8_i]) \ 181 : (_FP_FRAC_SUB_8_tmp[_FP_FRAC_SUB_8_i] \ 182 > X##_f[_FP_FRAC_SUB_8_i])); \ 183 } \ 184 for (_FP_FRAC_SUB_8_i = 0; _FP_FRAC_SUB_8_i < 8; ++_FP_FRAC_SUB_8_i) \ 185 R##_f[_FP_FRAC_SUB_8_i] = _FP_FRAC_SUB_8_tmp[_FP_FRAC_SUB_8_i]; \ 186 } \ 187 while (0) 188 189 #define _FP_FRAC_CLZ_8(R, X) \ 190 do \ 191 { \ 192 _FP_I_TYPE _FP_FRAC_CLZ_8_i; \ 193 for (_FP_FRAC_CLZ_8_i = 7; _FP_FRAC_CLZ_8_i > 0; _FP_FRAC_CLZ_8_i--) \ 194 if (X##_f[_FP_FRAC_CLZ_8_i]) \ 195 break; \ 196 __FP_CLZ ((R), X##_f[_FP_FRAC_CLZ_8_i]); \ 197 (R) += _FP_W_TYPE_SIZE * (7 - _FP_FRAC_CLZ_8_i); \ 198 } \ 199 while (0) 200 201 #define _FP_MINFRAC_8 0, 0, 0, 0, 0, 0, 0, 1 202 203 #define _FP_FRAC_NEGP_8(X) ((_FP_WS_TYPE) X##_f[7] < 0) 204 #define _FP_FRAC_ZEROP_8(X) \ 205 ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3] \ 206 | X##_f[4] | X##_f[5] | X##_f[6] | X##_f[7]) == 0) 207 #define _FP_FRAC_HIGHBIT_DW_8(fs, X) \ 208 (_FP_FRAC_HIGH_DW_##fs (X) & _FP_HIGHBIT_DW_##fs) 209 210 #define _FP_FRAC_COPY_4_8(D, S) \ 211 do \ 212 { \ 213 D##_f[0] = S##_f[0]; \ 214 D##_f[1] = S##_f[1]; \ 215 D##_f[2] = S##_f[2]; \ 216 D##_f[3] = S##_f[3]; \ 217 } \ 218 while (0) 219 220 #define _FP_FRAC_COPY_8_4(D, S) \ 221 do \ 222 { \ 223 D##_f[0] = S##_f[0]; \ 224 D##_f[1] = S##_f[1]; \ 225 D##_f[2] = S##_f[2]; \ 226 D##_f[3] = S##_f[3]; \ 227 D##_f[4] = D##_f[5] = D##_f[6] = D##_f[7]= 0; \ 228 } \ 229 while (0) 230 231 #define __FP_FRAC_SET_8(X, I7, I6, I5, I4, I3, I2, I1, I0) \ 232 (X##_f[7] = I7, X##_f[6] = I6, X##_f[5] = I5, X##_f[4] = I4, \ 233 X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0) 234 235 #endif /* !SOFT_FP_OP_8_H */ 236