1 | /* Software floating-point emulation. |
---|---|

2 | Basic eight-word fraction declaration and manipulation. |

3 | Copyright (C) 1997-2019 Free Software Foundation, Inc. |

4 | This file is part of the GNU C Library. |

5 | Contributed by Richard Henderson (rth@cygnus.com), |

6 | Jakub Jelinek (jj@ultra.linux.cz) and |

7 | Peter Maydell (pmaydell@chiark.greenend.org.uk). |

8 | |

9 | The GNU C Library is free software; you can redistribute it and/or |

10 | modify it under the terms of the GNU Lesser General Public |

11 | License as published by the Free Software Foundation; either |

12 | version 2.1 of the License, or (at your option) any later version. |

13 | |

14 | In addition to the permissions in the GNU Lesser General Public |

15 | License, the Free Software Foundation gives you unlimited |

16 | permission to link the compiled version of this file into |

17 | combinations with other programs, and to distribute those |

18 | combinations without any restriction coming from the use of this |

19 | file. (The Lesser General Public License restrictions do apply in |

20 | other respects; for example, they cover modification of the file, |

21 | and distribution when not linked into a combine executable.) |

22 | |

23 | The GNU C Library is distributed in the hope that it will be useful, |

24 | but WITHOUT ANY WARRANTY; without even the implied warranty of |

25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |

26 | Lesser General Public License for more details. |

27 | |

28 | You should have received a copy of the GNU Lesser General Public |

29 | License along with the GNU C Library; if not, see |

30 | <http://www.gnu.org/licenses/>. */ |

31 | |

32 | #ifndef SOFT_FP_OP_8_H |

33 | #define SOFT_FP_OP_8_H 1 |

34 | |

35 | /* We need just a few things from here for op-4, if we ever need some |

36 | other macros, they can be added. */ |

37 | #define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8] |

38 | #define _FP_FRAC_SET_8(X, I) __FP_FRAC_SET_8 (X, I) |

39 | #define _FP_FRAC_HIGH_8(X) (X##_f[7]) |

40 | #define _FP_FRAC_LOW_8(X) (X##_f[0]) |

41 | #define _FP_FRAC_WORD_8(X, w) (X##_f[w]) |

42 | |

43 | #define _FP_FRAC_SLL_8(X, N) \ |

44 | do \ |

45 | { \ |

46 | _FP_I_TYPE _FP_FRAC_SLL_8_up, _FP_FRAC_SLL_8_down; \ |

47 | _FP_I_TYPE _FP_FRAC_SLL_8_skip, _FP_FRAC_SLL_8_i; \ |

48 | _FP_FRAC_SLL_8_skip = (N) / _FP_W_TYPE_SIZE; \ |

49 | _FP_FRAC_SLL_8_up = (N) % _FP_W_TYPE_SIZE; \ |

50 | _FP_FRAC_SLL_8_down = _FP_W_TYPE_SIZE - _FP_FRAC_SLL_8_up; \ |

51 | if (!_FP_FRAC_SLL_8_up) \ |

52 | for (_FP_FRAC_SLL_8_i = 7; \ |

53 | _FP_FRAC_SLL_8_i >= _FP_FRAC_SLL_8_skip; \ |

54 | --_FP_FRAC_SLL_8_i) \ |

55 | X##_f[_FP_FRAC_SLL_8_i] \ |

56 | = X##_f[_FP_FRAC_SLL_8_i-_FP_FRAC_SLL_8_skip]; \ |

57 | else \ |

58 | { \ |

59 | for (_FP_FRAC_SLL_8_i = 7; \ |

60 | _FP_FRAC_SLL_8_i > _FP_FRAC_SLL_8_skip; \ |

61 | --_FP_FRAC_SLL_8_i) \ |

62 | X##_f[_FP_FRAC_SLL_8_i] \ |

63 | = ((X##_f[_FP_FRAC_SLL_8_i-_FP_FRAC_SLL_8_skip] \ |

64 | << _FP_FRAC_SLL_8_up) \ |

65 | | (X##_f[_FP_FRAC_SLL_8_i-_FP_FRAC_SLL_8_skip-1] \ |

66 | >> _FP_FRAC_SLL_8_down)); \ |

67 | X##_f[_FP_FRAC_SLL_8_i--] = X##_f[0] << _FP_FRAC_SLL_8_up; \ |

68 | } \ |

69 | for (; _FP_FRAC_SLL_8_i >= 0; --_FP_FRAC_SLL_8_i) \ |

70 | X##_f[_FP_FRAC_SLL_8_i] = 0; \ |

71 | } \ |

72 | while (0) |

73 | |

74 | #define _FP_FRAC_SRL_8(X, N) \ |

75 | do \ |

76 | { \ |

77 | _FP_I_TYPE _FP_FRAC_SRL_8_up, _FP_FRAC_SRL_8_down; \ |

78 | _FP_I_TYPE _FP_FRAC_SRL_8_skip, _FP_FRAC_SRL_8_i; \ |

79 | _FP_FRAC_SRL_8_skip = (N) / _FP_W_TYPE_SIZE; \ |

80 | _FP_FRAC_SRL_8_down = (N) % _FP_W_TYPE_SIZE; \ |

81 | _FP_FRAC_SRL_8_up = _FP_W_TYPE_SIZE - _FP_FRAC_SRL_8_down; \ |

82 | if (!_FP_FRAC_SRL_8_down) \ |

83 | for (_FP_FRAC_SRL_8_i = 0; \ |

84 | _FP_FRAC_SRL_8_i <= 7-_FP_FRAC_SRL_8_skip; \ |

85 | ++_FP_FRAC_SRL_8_i) \ |

86 | X##_f[_FP_FRAC_SRL_8_i] \ |

87 | = X##_f[_FP_FRAC_SRL_8_i+_FP_FRAC_SRL_8_skip]; \ |

88 | else \ |

89 | { \ |

90 | for (_FP_FRAC_SRL_8_i = 0; \ |

91 | _FP_FRAC_SRL_8_i < 7-_FP_FRAC_SRL_8_skip; \ |

92 | ++_FP_FRAC_SRL_8_i) \ |

93 | X##_f[_FP_FRAC_SRL_8_i] \ |

94 | = ((X##_f[_FP_FRAC_SRL_8_i+_FP_FRAC_SRL_8_skip] \ |

95 | >> _FP_FRAC_SRL_8_down) \ |

96 | | (X##_f[_FP_FRAC_SRL_8_i+_FP_FRAC_SRL_8_skip+1] \ |

97 | << _FP_FRAC_SRL_8_up)); \ |

98 | X##_f[_FP_FRAC_SRL_8_i++] = X##_f[7] >> _FP_FRAC_SRL_8_down; \ |

99 | } \ |

100 | for (; _FP_FRAC_SRL_8_i < 8; ++_FP_FRAC_SRL_8_i) \ |

101 | X##_f[_FP_FRAC_SRL_8_i] = 0; \ |

102 | } \ |

103 | while (0) |

104 | |

105 | |

106 | /* Right shift with sticky-lsb. |

107 | What this actually means is that we do a standard right-shift, |

108 | but that if any of the bits that fall off the right hand side |

109 | were one then we always set the LSbit. */ |

110 | #define _FP_FRAC_SRS_8(X, N, size) \ |

111 | do \ |

112 | { \ |

113 | _FP_I_TYPE _FP_FRAC_SRS_8_up, _FP_FRAC_SRS_8_down; \ |

114 | _FP_I_TYPE _FP_FRAC_SRS_8_skip, _FP_FRAC_SRS_8_i; \ |

115 | _FP_W_TYPE _FP_FRAC_SRS_8_s; \ |

116 | _FP_FRAC_SRS_8_skip = (N) / _FP_W_TYPE_SIZE; \ |

117 | _FP_FRAC_SRS_8_down = (N) % _FP_W_TYPE_SIZE; \ |

118 | _FP_FRAC_SRS_8_up = _FP_W_TYPE_SIZE - _FP_FRAC_SRS_8_down; \ |

119 | for (_FP_FRAC_SRS_8_s = _FP_FRAC_SRS_8_i = 0; \ |

120 | _FP_FRAC_SRS_8_i < _FP_FRAC_SRS_8_skip; \ |

121 | ++_FP_FRAC_SRS_8_i) \ |

122 | _FP_FRAC_SRS_8_s |= X##_f[_FP_FRAC_SRS_8_i]; \ |

123 | if (!_FP_FRAC_SRS_8_down) \ |

124 | for (_FP_FRAC_SRS_8_i = 0; \ |

125 | _FP_FRAC_SRS_8_i <= 7-_FP_FRAC_SRS_8_skip; \ |

126 | ++_FP_FRAC_SRS_8_i) \ |

127 | X##_f[_FP_FRAC_SRS_8_i] \ |

128 | = X##_f[_FP_FRAC_SRS_8_i+_FP_FRAC_SRS_8_skip]; \ |

129 | else \ |

130 | { \ |

131 | _FP_FRAC_SRS_8_s \ |

132 | |= X##_f[_FP_FRAC_SRS_8_i] << _FP_FRAC_SRS_8_up; \ |

133 | for (_FP_FRAC_SRS_8_i = 0; \ |

134 | _FP_FRAC_SRS_8_i < 7-_FP_FRAC_SRS_8_skip; \ |

135 | ++_FP_FRAC_SRS_8_i) \ |

136 | X##_f[_FP_FRAC_SRS_8_i] \ |

137 | = ((X##_f[_FP_FRAC_SRS_8_i+_FP_FRAC_SRS_8_skip] \ |

138 | >> _FP_FRAC_SRS_8_down) \ |

139 | | (X##_f[_FP_FRAC_SRS_8_i+_FP_FRAC_SRS_8_skip+1] \ |

140 | << _FP_FRAC_SRS_8_up)); \ |

141 | X##_f[_FP_FRAC_SRS_8_i++] = X##_f[7] >> _FP_FRAC_SRS_8_down; \ |

142 | } \ |

143 | for (; _FP_FRAC_SRS_8_i < 8; ++_FP_FRAC_SRS_8_i) \ |

144 | X##_f[_FP_FRAC_SRS_8_i] = 0; \ |

145 | /* Don't fix the LSB until the very end when we're sure f[0] is \ |

146 | stable. */ \ |

147 | X##_f[0] |= (_FP_FRAC_SRS_8_s != 0); \ |

148 | } \ |

149 | while (0) |

150 | |

151 | #define _FP_FRAC_ADD_8(R, X, Y) \ |

152 | do \ |

153 | { \ |

154 | _FP_W_TYPE _FP_FRAC_ADD_8_c = 0; \ |

155 | _FP_I_TYPE _FP_FRAC_ADD_8_i; \ |

156 | for (_FP_FRAC_ADD_8_i = 0; _FP_FRAC_ADD_8_i < 8; ++_FP_FRAC_ADD_8_i) \ |

157 | { \ |

158 | R##_f[_FP_FRAC_ADD_8_i] \ |

159 | = (X##_f[_FP_FRAC_ADD_8_i] + Y##_f[_FP_FRAC_ADD_8_i] \ |

160 | + _FP_FRAC_ADD_8_c); \ |

161 | _FP_FRAC_ADD_8_c \ |

162 | = (_FP_FRAC_ADD_8_c \ |

163 | ? R##_f[_FP_FRAC_ADD_8_i] <= X##_f[_FP_FRAC_ADD_8_i] \ |

164 | : R##_f[_FP_FRAC_ADD_8_i] < X##_f[_FP_FRAC_ADD_8_i]); \ |

165 | } \ |

166 | } \ |

167 | while (0) |

168 | |

169 | #define _FP_FRAC_SUB_8(R, X, Y) \ |

170 | do \ |

171 | { \ |

172 | _FP_W_TYPE _FP_FRAC_SUB_8_tmp[8]; \ |

173 | _FP_W_TYPE _FP_FRAC_SUB_8_c = 0; \ |

174 | _FP_I_TYPE _FP_FRAC_SUB_8_i; \ |

175 | for (_FP_FRAC_SUB_8_i = 0; _FP_FRAC_SUB_8_i < 8; ++_FP_FRAC_SUB_8_i) \ |

176 | { \ |

177 | _FP_FRAC_SUB_8_tmp[_FP_FRAC_SUB_8_i] \ |

178 | = (X##_f[_FP_FRAC_SUB_8_i] - Y##_f[_FP_FRAC_SUB_8_i] \ |

179 | - _FP_FRAC_SUB_8_c); \ |

180 | _FP_FRAC_SUB_8_c \ |

181 | = (_FP_FRAC_SUB_8_c \ |

182 | ? (_FP_FRAC_SUB_8_tmp[_FP_FRAC_SUB_8_i] \ |

183 | >= X##_f[_FP_FRAC_SUB_8_i]) \ |

184 | : (_FP_FRAC_SUB_8_tmp[_FP_FRAC_SUB_8_i] \ |

185 | > X##_f[_FP_FRAC_SUB_8_i])); \ |

186 | } \ |

187 | for (_FP_FRAC_SUB_8_i = 0; _FP_FRAC_SUB_8_i < 8; ++_FP_FRAC_SUB_8_i) \ |

188 | R##_f[_FP_FRAC_SUB_8_i] = _FP_FRAC_SUB_8_tmp[_FP_FRAC_SUB_8_i]; \ |

189 | } \ |

190 | while (0) |

191 | |

192 | #define _FP_FRAC_CLZ_8(R, X) \ |

193 | do \ |

194 | { \ |

195 | _FP_I_TYPE _FP_FRAC_CLZ_8_i; \ |

196 | for (_FP_FRAC_CLZ_8_i = 7; _FP_FRAC_CLZ_8_i > 0; _FP_FRAC_CLZ_8_i--) \ |

197 | if (X##_f[_FP_FRAC_CLZ_8_i]) \ |

198 | break; \ |

199 | __FP_CLZ ((R), X##_f[_FP_FRAC_CLZ_8_i]); \ |

200 | (R) += _FP_W_TYPE_SIZE * (7 - _FP_FRAC_CLZ_8_i); \ |

201 | } \ |

202 | while (0) |

203 | |

204 | #define _FP_MINFRAC_8 0, 0, 0, 0, 0, 0, 0, 1 |

205 | |

206 | #define _FP_FRAC_NEGP_8(X) ((_FP_WS_TYPE) X##_f[7] < 0) |

207 | #define _FP_FRAC_ZEROP_8(X) \ |

208 | ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3] \ |

209 | | X##_f[4] | X##_f[5] | X##_f[6] | X##_f[7]) == 0) |

210 | #define _FP_FRAC_HIGHBIT_DW_8(fs, X) \ |

211 | (_FP_FRAC_HIGH_DW_##fs (X) & _FP_HIGHBIT_DW_##fs) |

212 | |

213 | #define _FP_FRAC_COPY_4_8(D, S) \ |

214 | do \ |

215 | { \ |

216 | D##_f[0] = S##_f[0]; \ |

217 | D##_f[1] = S##_f[1]; \ |

218 | D##_f[2] = S##_f[2]; \ |

219 | D##_f[3] = S##_f[3]; \ |

220 | } \ |

221 | while (0) |

222 | |

223 | #define _FP_FRAC_COPY_8_4(D, S) \ |

224 | do \ |

225 | { \ |

226 | D##_f[0] = S##_f[0]; \ |

227 | D##_f[1] = S##_f[1]; \ |

228 | D##_f[2] = S##_f[2]; \ |

229 | D##_f[3] = S##_f[3]; \ |

230 | D##_f[4] = D##_f[5] = D##_f[6] = D##_f[7]= 0; \ |

231 | } \ |

232 | while (0) |

233 | |

234 | #define __FP_FRAC_SET_8(X, I7, I6, I5, I4, I3, I2, I1, I0) \ |

235 | (X##_f[7] = I7, X##_f[6] = I6, X##_f[5] = I5, X##_f[4] = I4, \ |

236 | X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0) |

237 | |

238 | #endif /* !SOFT_FP_OP_8_H */ |

239 |