162306a36Sopenharmony_ci/* Software floating-point emulation. 262306a36Sopenharmony_ci Basic four-word fraction declaration and manipulation. 362306a36Sopenharmony_ci Copyright (C) 1997,1998,1999 Free Software Foundation, Inc. 462306a36Sopenharmony_ci This file is part of the GNU C Library. 562306a36Sopenharmony_ci Contributed by Richard Henderson (rth@cygnus.com), 662306a36Sopenharmony_ci Jakub Jelinek (jj@ultra.linux.cz), 762306a36Sopenharmony_ci David S. Miller (davem@redhat.com) and 862306a36Sopenharmony_ci Peter Maydell (pmaydell@chiark.greenend.org.uk). 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci The GNU C Library is free software; you can redistribute it and/or 1162306a36Sopenharmony_ci modify it under the terms of the GNU Library General Public License as 1262306a36Sopenharmony_ci published by the Free Software Foundation; either version 2 of the 1362306a36Sopenharmony_ci License, or (at your option) any later version. 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci The GNU C Library is distributed in the hope that it will be useful, 1662306a36Sopenharmony_ci but WITHOUT ANY WARRANTY; without even the implied warranty of 1762306a36Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1862306a36Sopenharmony_ci Library General Public License for more details. 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci You should have received a copy of the GNU Library General Public 2162306a36Sopenharmony_ci License along with the GNU C Library; see the file COPYING.LIB. If 2262306a36Sopenharmony_ci not, write to the Free Software Foundation, Inc., 2362306a36Sopenharmony_ci 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#ifndef __MATH_EMU_OP_4_H__ 2662306a36Sopenharmony_ci#define __MATH_EMU_OP_4_H__ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4] 2962306a36Sopenharmony_ci#define _FP_FRAC_COPY_4(D,S) \ 3062306a36Sopenharmony_ci (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \ 3162306a36Sopenharmony_ci D##_f[2] = S##_f[2], D##_f[3] = S##_f[3]) 3262306a36Sopenharmony_ci#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I) 3362306a36Sopenharmony_ci#define _FP_FRAC_HIGH_4(X) (X##_f[3]) 3462306a36Sopenharmony_ci#define _FP_FRAC_LOW_4(X) (X##_f[0]) 3562306a36Sopenharmony_ci#define _FP_FRAC_WORD_4(X,w) (X##_f[w]) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define _FP_FRAC_SLL_4(X,N) \ 3862306a36Sopenharmony_ci do { \ 3962306a36Sopenharmony_ci _FP_I_TYPE _up, _down, _skip, _i; \ 4062306a36Sopenharmony_ci _skip = (N) / _FP_W_TYPE_SIZE; \ 4162306a36Sopenharmony_ci _up = (N) % _FP_W_TYPE_SIZE; \ 4262306a36Sopenharmony_ci _down = _FP_W_TYPE_SIZE - _up; \ 4362306a36Sopenharmony_ci if (!_up) \ 4462306a36Sopenharmony_ci for (_i = 3; _i >= _skip; --_i) \ 4562306a36Sopenharmony_ci X##_f[_i] = X##_f[_i-_skip]; \ 4662306a36Sopenharmony_ci else \ 4762306a36Sopenharmony_ci { \ 4862306a36Sopenharmony_ci for (_i = 3; _i > _skip; --_i) \ 4962306a36Sopenharmony_ci X##_f[_i] = X##_f[_i-_skip] << _up \ 5062306a36Sopenharmony_ci | X##_f[_i-_skip-1] >> _down; \ 5162306a36Sopenharmony_ci X##_f[_i--] = X##_f[0] << _up; \ 5262306a36Sopenharmony_ci } \ 5362306a36Sopenharmony_ci for (; _i >= 0; --_i) \ 5462306a36Sopenharmony_ci X##_f[_i] = 0; \ 5562306a36Sopenharmony_ci } while (0) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* This one was broken too */ 5862306a36Sopenharmony_ci#define _FP_FRAC_SRL_4(X,N) \ 5962306a36Sopenharmony_ci do { \ 6062306a36Sopenharmony_ci _FP_I_TYPE _up, _down, _skip, _i; \ 6162306a36Sopenharmony_ci _skip = (N) / _FP_W_TYPE_SIZE; \ 6262306a36Sopenharmony_ci _down = (N) % _FP_W_TYPE_SIZE; \ 6362306a36Sopenharmony_ci _up = _FP_W_TYPE_SIZE - _down; \ 6462306a36Sopenharmony_ci if (!_down) \ 6562306a36Sopenharmony_ci for (_i = 0; _i <= 3-_skip; ++_i) \ 6662306a36Sopenharmony_ci X##_f[_i] = X##_f[_i+_skip]; \ 6762306a36Sopenharmony_ci else \ 6862306a36Sopenharmony_ci { \ 6962306a36Sopenharmony_ci for (_i = 0; _i < 3-_skip; ++_i) \ 7062306a36Sopenharmony_ci X##_f[_i] = X##_f[_i+_skip] >> _down \ 7162306a36Sopenharmony_ci | X##_f[_i+_skip+1] << _up; \ 7262306a36Sopenharmony_ci X##_f[_i++] = X##_f[3] >> _down; \ 7362306a36Sopenharmony_ci } \ 7462306a36Sopenharmony_ci for (; _i < 4; ++_i) \ 7562306a36Sopenharmony_ci X##_f[_i] = 0; \ 7662306a36Sopenharmony_ci } while (0) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* Right shift with sticky-lsb. 8062306a36Sopenharmony_ci * What this actually means is that we do a standard right-shift, 8162306a36Sopenharmony_ci * but that if any of the bits that fall off the right hand side 8262306a36Sopenharmony_ci * were one then we always set the LSbit. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci#define _FP_FRAC_SRS_4(X,N,size) \ 8562306a36Sopenharmony_ci do { \ 8662306a36Sopenharmony_ci _FP_I_TYPE _up, _down, _skip, _i; \ 8762306a36Sopenharmony_ci _FP_W_TYPE _s; \ 8862306a36Sopenharmony_ci _skip = (N) / _FP_W_TYPE_SIZE; \ 8962306a36Sopenharmony_ci _down = (N) % _FP_W_TYPE_SIZE; \ 9062306a36Sopenharmony_ci _up = _FP_W_TYPE_SIZE - _down; \ 9162306a36Sopenharmony_ci for (_s = _i = 0; _i < _skip; ++_i) \ 9262306a36Sopenharmony_ci _s |= X##_f[_i]; \ 9362306a36Sopenharmony_ci _s |= X##_f[_i] << _up; \ 9462306a36Sopenharmony_ci/* s is now != 0 if we want to set the LSbit */ \ 9562306a36Sopenharmony_ci if (!_down) \ 9662306a36Sopenharmony_ci for (_i = 0; _i <= 3-_skip; ++_i) \ 9762306a36Sopenharmony_ci X##_f[_i] = X##_f[_i+_skip]; \ 9862306a36Sopenharmony_ci else \ 9962306a36Sopenharmony_ci { \ 10062306a36Sopenharmony_ci for (_i = 0; _i < 3-_skip; ++_i) \ 10162306a36Sopenharmony_ci X##_f[_i] = X##_f[_i+_skip] >> _down \ 10262306a36Sopenharmony_ci | X##_f[_i+_skip+1] << _up; \ 10362306a36Sopenharmony_ci X##_f[_i++] = X##_f[3] >> _down; \ 10462306a36Sopenharmony_ci } \ 10562306a36Sopenharmony_ci for (; _i < 4; ++_i) \ 10662306a36Sopenharmony_ci X##_f[_i] = 0; \ 10762306a36Sopenharmony_ci /* don't fix the LSB until the very end when we're sure f[0] is stable */ \ 10862306a36Sopenharmony_ci X##_f[0] |= (_s != 0); \ 10962306a36Sopenharmony_ci } while (0) 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci#define _FP_FRAC_ADD_4(R,X,Y) \ 11262306a36Sopenharmony_ci __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ 11362306a36Sopenharmony_ci X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ 11462306a36Sopenharmony_ci Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci#define _FP_FRAC_SUB_4(R,X,Y) \ 11762306a36Sopenharmony_ci __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ 11862306a36Sopenharmony_ci X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ 11962306a36Sopenharmony_ci Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci#define _FP_FRAC_DEC_4(X,Y) \ 12262306a36Sopenharmony_ci __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ 12362306a36Sopenharmony_ci Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#define _FP_FRAC_ADDI_4(X,I) \ 12662306a36Sopenharmony_ci __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I) 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#define _FP_ZEROFRAC_4 0,0,0,0 12962306a36Sopenharmony_ci#define _FP_MINFRAC_4 0,0,0,1 13062306a36Sopenharmony_ci#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0) 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0) 13362306a36Sopenharmony_ci#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0) 13462306a36Sopenharmony_ci#define _FP_FRAC_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs) 13562306a36Sopenharmony_ci#define _FP_FRAC_CLEAR_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs) 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#define _FP_FRAC_EQ_4(X,Y) \ 13862306a36Sopenharmony_ci (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \ 13962306a36Sopenharmony_ci && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3]) 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci#define _FP_FRAC_GT_4(X,Y) \ 14262306a36Sopenharmony_ci (X##_f[3] > Y##_f[3] || \ 14362306a36Sopenharmony_ci (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ 14462306a36Sopenharmony_ci (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ 14562306a36Sopenharmony_ci (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \ 14662306a36Sopenharmony_ci )) \ 14762306a36Sopenharmony_ci )) \ 14862306a36Sopenharmony_ci ) 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci#define _FP_FRAC_GE_4(X,Y) \ 15162306a36Sopenharmony_ci (X##_f[3] > Y##_f[3] || \ 15262306a36Sopenharmony_ci (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ 15362306a36Sopenharmony_ci (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ 15462306a36Sopenharmony_ci (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \ 15562306a36Sopenharmony_ci )) \ 15662306a36Sopenharmony_ci )) \ 15762306a36Sopenharmony_ci ) 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci#define _FP_FRAC_CLZ_4(R,X) \ 16162306a36Sopenharmony_ci do { \ 16262306a36Sopenharmony_ci if (X##_f[3]) \ 16362306a36Sopenharmony_ci { \ 16462306a36Sopenharmony_ci __FP_CLZ(R,X##_f[3]); \ 16562306a36Sopenharmony_ci } \ 16662306a36Sopenharmony_ci else if (X##_f[2]) \ 16762306a36Sopenharmony_ci { \ 16862306a36Sopenharmony_ci __FP_CLZ(R,X##_f[2]); \ 16962306a36Sopenharmony_ci R += _FP_W_TYPE_SIZE; \ 17062306a36Sopenharmony_ci } \ 17162306a36Sopenharmony_ci else if (X##_f[1]) \ 17262306a36Sopenharmony_ci { \ 17362306a36Sopenharmony_ci __FP_CLZ(R,X##_f[2]); \ 17462306a36Sopenharmony_ci R += _FP_W_TYPE_SIZE*2; \ 17562306a36Sopenharmony_ci } \ 17662306a36Sopenharmony_ci else \ 17762306a36Sopenharmony_ci { \ 17862306a36Sopenharmony_ci __FP_CLZ(R,X##_f[0]); \ 17962306a36Sopenharmony_ci R += _FP_W_TYPE_SIZE*3; \ 18062306a36Sopenharmony_ci } \ 18162306a36Sopenharmony_ci } while(0) 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#define _FP_UNPACK_RAW_4(fs, X, val) \ 18562306a36Sopenharmony_ci do { \ 18662306a36Sopenharmony_ci union _FP_UNION_##fs _flo; _flo.flt = (val); \ 18762306a36Sopenharmony_ci X##_f[0] = _flo.bits.frac0; \ 18862306a36Sopenharmony_ci X##_f[1] = _flo.bits.frac1; \ 18962306a36Sopenharmony_ci X##_f[2] = _flo.bits.frac2; \ 19062306a36Sopenharmony_ci X##_f[3] = _flo.bits.frac3; \ 19162306a36Sopenharmony_ci X##_e = _flo.bits.exp; \ 19262306a36Sopenharmony_ci X##_s = _flo.bits.sign; \ 19362306a36Sopenharmony_ci } while (0) 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci#define _FP_UNPACK_RAW_4_P(fs, X, val) \ 19662306a36Sopenharmony_ci do { \ 19762306a36Sopenharmony_ci union _FP_UNION_##fs *_flo = \ 19862306a36Sopenharmony_ci (union _FP_UNION_##fs *)(val); \ 19962306a36Sopenharmony_ci \ 20062306a36Sopenharmony_ci X##_f[0] = _flo->bits.frac0; \ 20162306a36Sopenharmony_ci X##_f[1] = _flo->bits.frac1; \ 20262306a36Sopenharmony_ci X##_f[2] = _flo->bits.frac2; \ 20362306a36Sopenharmony_ci X##_f[3] = _flo->bits.frac3; \ 20462306a36Sopenharmony_ci X##_e = _flo->bits.exp; \ 20562306a36Sopenharmony_ci X##_s = _flo->bits.sign; \ 20662306a36Sopenharmony_ci } while (0) 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci#define _FP_PACK_RAW_4(fs, val, X) \ 20962306a36Sopenharmony_ci do { \ 21062306a36Sopenharmony_ci union _FP_UNION_##fs _flo; \ 21162306a36Sopenharmony_ci _flo.bits.frac0 = X##_f[0]; \ 21262306a36Sopenharmony_ci _flo.bits.frac1 = X##_f[1]; \ 21362306a36Sopenharmony_ci _flo.bits.frac2 = X##_f[2]; \ 21462306a36Sopenharmony_ci _flo.bits.frac3 = X##_f[3]; \ 21562306a36Sopenharmony_ci _flo.bits.exp = X##_e; \ 21662306a36Sopenharmony_ci _flo.bits.sign = X##_s; \ 21762306a36Sopenharmony_ci (val) = _flo.flt; \ 21862306a36Sopenharmony_ci } while (0) 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci#define _FP_PACK_RAW_4_P(fs, val, X) \ 22162306a36Sopenharmony_ci do { \ 22262306a36Sopenharmony_ci union _FP_UNION_##fs *_flo = \ 22362306a36Sopenharmony_ci (union _FP_UNION_##fs *)(val); \ 22462306a36Sopenharmony_ci \ 22562306a36Sopenharmony_ci _flo->bits.frac0 = X##_f[0]; \ 22662306a36Sopenharmony_ci _flo->bits.frac1 = X##_f[1]; \ 22762306a36Sopenharmony_ci _flo->bits.frac2 = X##_f[2]; \ 22862306a36Sopenharmony_ci _flo->bits.frac3 = X##_f[3]; \ 22962306a36Sopenharmony_ci _flo->bits.exp = X##_e; \ 23062306a36Sopenharmony_ci _flo->bits.sign = X##_s; \ 23162306a36Sopenharmony_ci } while (0) 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/* 23462306a36Sopenharmony_ci * Multiplication algorithms: 23562306a36Sopenharmony_ci */ 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \ 24062306a36Sopenharmony_ci do { \ 24162306a36Sopenharmony_ci _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ 24262306a36Sopenharmony_ci _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f); \ 24362306a36Sopenharmony_ci \ 24462306a36Sopenharmony_ci doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \ 24562306a36Sopenharmony_ci doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]); \ 24662306a36Sopenharmony_ci doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]); \ 24762306a36Sopenharmony_ci doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]); \ 24862306a36Sopenharmony_ci doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]); \ 24962306a36Sopenharmony_ci doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]); \ 25062306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \ 25162306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0, \ 25262306a36Sopenharmony_ci 0,0,_FP_FRAC_WORD_8(_z,1)); \ 25362306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \ 25462306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0, \ 25562306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \ 25662306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,1)); \ 25762306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ 25862306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0, \ 25962306a36Sopenharmony_ci 0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2)); \ 26062306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ 26162306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0, \ 26262306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ 26362306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,2)); \ 26462306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ 26562306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0, \ 26662306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ 26762306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,2)); \ 26862306a36Sopenharmony_ci doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]); \ 26962306a36Sopenharmony_ci doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]); \ 27062306a36Sopenharmony_ci doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]); \ 27162306a36Sopenharmony_ci doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]); \ 27262306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ 27362306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0, \ 27462306a36Sopenharmony_ci 0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3)); \ 27562306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ 27662306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0, \ 27762306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ 27862306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,3)); \ 27962306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ 28062306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0, \ 28162306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ 28262306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,3)); \ 28362306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ 28462306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0, \ 28562306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ 28662306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,3)); \ 28762306a36Sopenharmony_ci doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]); \ 28862306a36Sopenharmony_ci doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]); \ 28962306a36Sopenharmony_ci doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]); \ 29062306a36Sopenharmony_ci doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]); \ 29162306a36Sopenharmony_ci doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]); \ 29262306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ 29362306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0, \ 29462306a36Sopenharmony_ci 0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4)); \ 29562306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ 29662306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0, \ 29762306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ 29862306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,4)); \ 29962306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ 30062306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0, \ 30162306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ 30262306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,4)); \ 30362306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ 30462306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0, \ 30562306a36Sopenharmony_ci 0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5)); \ 30662306a36Sopenharmony_ci __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ 30762306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0, \ 30862306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ 30962306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,5)); \ 31062306a36Sopenharmony_ci doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]); \ 31162306a36Sopenharmony_ci __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ 31262306a36Sopenharmony_ci _b_f1,_b_f0, \ 31362306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6)); \ 31462306a36Sopenharmony_ci \ 31562306a36Sopenharmony_ci /* Normalize since we know where the msb of the multiplicands \ 31662306a36Sopenharmony_ci were (bit B), we know that the msb of the of the product is \ 31762306a36Sopenharmony_ci at either 2B or 2B-1. */ \ 31862306a36Sopenharmony_ci _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \ 31962306a36Sopenharmony_ci __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \ 32062306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \ 32162306a36Sopenharmony_ci } while (0) 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \ 32462306a36Sopenharmony_ci do { \ 32562306a36Sopenharmony_ci _FP_FRAC_DECL_8(_z); \ 32662306a36Sopenharmony_ci \ 32762306a36Sopenharmony_ci mpn_mul_n(_z_f, _x_f, _y_f, 4); \ 32862306a36Sopenharmony_ci \ 32962306a36Sopenharmony_ci /* Normalize since we know where the msb of the multiplicands \ 33062306a36Sopenharmony_ci were (bit B), we know that the msb of the of the product is \ 33162306a36Sopenharmony_ci at either 2B or 2B-1. */ \ 33262306a36Sopenharmony_ci _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \ 33362306a36Sopenharmony_ci __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \ 33462306a36Sopenharmony_ci _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \ 33562306a36Sopenharmony_ci } while (0) 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/* 33862306a36Sopenharmony_ci * Helper utility for _FP_DIV_MEAT_4_udiv: 33962306a36Sopenharmony_ci * pppp = m * nnn 34062306a36Sopenharmony_ci */ 34162306a36Sopenharmony_ci#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0) \ 34262306a36Sopenharmony_ci do { \ 34362306a36Sopenharmony_ci UWtype _t; \ 34462306a36Sopenharmony_ci umul_ppmm(p1,p0,m,n0); \ 34562306a36Sopenharmony_ci umul_ppmm(p2,_t,m,n1); \ 34662306a36Sopenharmony_ci __FP_FRAC_ADDI_2(p2,p1,_t); \ 34762306a36Sopenharmony_ci umul_ppmm(p3,_t,m,n2); \ 34862306a36Sopenharmony_ci __FP_FRAC_ADDI_2(p3,p2,_t); \ 34962306a36Sopenharmony_ci } while (0) 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/* 35262306a36Sopenharmony_ci * Division algorithms: 35362306a36Sopenharmony_ci */ 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \ 35662306a36Sopenharmony_ci do { \ 35762306a36Sopenharmony_ci int _i; \ 35862306a36Sopenharmony_ci _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m); \ 35962306a36Sopenharmony_ci _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4); \ 36062306a36Sopenharmony_ci if (_FP_FRAC_GT_4(X, Y)) \ 36162306a36Sopenharmony_ci { \ 36262306a36Sopenharmony_ci _n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \ 36362306a36Sopenharmony_ci _FP_FRAC_SRL_4(X, 1); \ 36462306a36Sopenharmony_ci } \ 36562306a36Sopenharmony_ci else \ 36662306a36Sopenharmony_ci R##_e--; \ 36762306a36Sopenharmony_ci \ 36862306a36Sopenharmony_ci /* Normalize, i.e. make the most significant bit of the \ 36962306a36Sopenharmony_ci denominator set. */ \ 37062306a36Sopenharmony_ci _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs); \ 37162306a36Sopenharmony_ci \ 37262306a36Sopenharmony_ci for (_i = 3; ; _i--) \ 37362306a36Sopenharmony_ci { \ 37462306a36Sopenharmony_ci if (X##_f[3] == Y##_f[3]) \ 37562306a36Sopenharmony_ci { \ 37662306a36Sopenharmony_ci /* This is a special case, not an optimization \ 37762306a36Sopenharmony_ci (X##_f[3]/Y##_f[3] would not fit into UWtype). \ 37862306a36Sopenharmony_ci As X## is guaranteed to be < Y, R##_f[_i] can be either \ 37962306a36Sopenharmony_ci (UWtype)-1 or (UWtype)-2. */ \ 38062306a36Sopenharmony_ci R##_f[_i] = -1; \ 38162306a36Sopenharmony_ci if (!_i) \ 38262306a36Sopenharmony_ci break; \ 38362306a36Sopenharmony_ci __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ 38462306a36Sopenharmony_ci Y##_f[2], Y##_f[1], Y##_f[0], 0, \ 38562306a36Sopenharmony_ci X##_f[2], X##_f[1], X##_f[0], _n_f[_i]); \ 38662306a36Sopenharmony_ci _FP_FRAC_SUB_4(X, Y, X); \ 38762306a36Sopenharmony_ci if (X##_f[3] > Y##_f[3]) \ 38862306a36Sopenharmony_ci { \ 38962306a36Sopenharmony_ci R##_f[_i] = -2; \ 39062306a36Sopenharmony_ci _FP_FRAC_ADD_4(X, Y, X); \ 39162306a36Sopenharmony_ci } \ 39262306a36Sopenharmony_ci } \ 39362306a36Sopenharmony_ci else \ 39462306a36Sopenharmony_ci { \ 39562306a36Sopenharmony_ci udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \ 39662306a36Sopenharmony_ci umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0], \ 39762306a36Sopenharmony_ci R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]); \ 39862306a36Sopenharmony_ci X##_f[2] = X##_f[1]; \ 39962306a36Sopenharmony_ci X##_f[1] = X##_f[0]; \ 40062306a36Sopenharmony_ci X##_f[0] = _n_f[_i]; \ 40162306a36Sopenharmony_ci if (_FP_FRAC_GT_4(_m, X)) \ 40262306a36Sopenharmony_ci { \ 40362306a36Sopenharmony_ci R##_f[_i]--; \ 40462306a36Sopenharmony_ci _FP_FRAC_ADD_4(X, Y, X); \ 40562306a36Sopenharmony_ci if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X)) \ 40662306a36Sopenharmony_ci { \ 40762306a36Sopenharmony_ci R##_f[_i]--; \ 40862306a36Sopenharmony_ci _FP_FRAC_ADD_4(X, Y, X); \ 40962306a36Sopenharmony_ci } \ 41062306a36Sopenharmony_ci } \ 41162306a36Sopenharmony_ci _FP_FRAC_DEC_4(X, _m); \ 41262306a36Sopenharmony_ci if (!_i) \ 41362306a36Sopenharmony_ci { \ 41462306a36Sopenharmony_ci if (!_FP_FRAC_EQ_4(X, _m)) \ 41562306a36Sopenharmony_ci R##_f[0] |= _FP_WORK_STICKY; \ 41662306a36Sopenharmony_ci break; \ 41762306a36Sopenharmony_ci } \ 41862306a36Sopenharmony_ci } \ 41962306a36Sopenharmony_ci } \ 42062306a36Sopenharmony_ci } while (0) 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci/* 42462306a36Sopenharmony_ci * Square root algorithms: 42562306a36Sopenharmony_ci * We have just one right now, maybe Newton approximation 42662306a36Sopenharmony_ci * should be added for those machines where division is fast. 42762306a36Sopenharmony_ci */ 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci#define _FP_SQRT_MEAT_4(R, S, T, X, q) \ 43062306a36Sopenharmony_ci do { \ 43162306a36Sopenharmony_ci while (q) \ 43262306a36Sopenharmony_ci { \ 43362306a36Sopenharmony_ci T##_f[3] = S##_f[3] + q; \ 43462306a36Sopenharmony_ci if (T##_f[3] <= X##_f[3]) \ 43562306a36Sopenharmony_ci { \ 43662306a36Sopenharmony_ci S##_f[3] = T##_f[3] + q; \ 43762306a36Sopenharmony_ci X##_f[3] -= T##_f[3]; \ 43862306a36Sopenharmony_ci R##_f[3] += q; \ 43962306a36Sopenharmony_ci } \ 44062306a36Sopenharmony_ci _FP_FRAC_SLL_4(X, 1); \ 44162306a36Sopenharmony_ci q >>= 1; \ 44262306a36Sopenharmony_ci } \ 44362306a36Sopenharmony_ci q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ 44462306a36Sopenharmony_ci while (q) \ 44562306a36Sopenharmony_ci { \ 44662306a36Sopenharmony_ci T##_f[2] = S##_f[2] + q; \ 44762306a36Sopenharmony_ci T##_f[3] = S##_f[3]; \ 44862306a36Sopenharmony_ci if (T##_f[3] < X##_f[3] || \ 44962306a36Sopenharmony_ci (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \ 45062306a36Sopenharmony_ci { \ 45162306a36Sopenharmony_ci S##_f[2] = T##_f[2] + q; \ 45262306a36Sopenharmony_ci S##_f[3] += (T##_f[2] > S##_f[2]); \ 45362306a36Sopenharmony_ci __FP_FRAC_DEC_2(X##_f[3], X##_f[2], \ 45462306a36Sopenharmony_ci T##_f[3], T##_f[2]); \ 45562306a36Sopenharmony_ci R##_f[2] += q; \ 45662306a36Sopenharmony_ci } \ 45762306a36Sopenharmony_ci _FP_FRAC_SLL_4(X, 1); \ 45862306a36Sopenharmony_ci q >>= 1; \ 45962306a36Sopenharmony_ci } \ 46062306a36Sopenharmony_ci q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ 46162306a36Sopenharmony_ci while (q) \ 46262306a36Sopenharmony_ci { \ 46362306a36Sopenharmony_ci T##_f[1] = S##_f[1] + q; \ 46462306a36Sopenharmony_ci T##_f[2] = S##_f[2]; \ 46562306a36Sopenharmony_ci T##_f[3] = S##_f[3]; \ 46662306a36Sopenharmony_ci if (T##_f[3] < X##_f[3] || \ 46762306a36Sopenharmony_ci (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] || \ 46862306a36Sopenharmony_ci (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1])))) \ 46962306a36Sopenharmony_ci { \ 47062306a36Sopenharmony_ci S##_f[1] = T##_f[1] + q; \ 47162306a36Sopenharmony_ci S##_f[2] += (T##_f[1] > S##_f[1]); \ 47262306a36Sopenharmony_ci S##_f[3] += (T##_f[2] > S##_f[2]); \ 47362306a36Sopenharmony_ci __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1], \ 47462306a36Sopenharmony_ci T##_f[3], T##_f[2], T##_f[1]); \ 47562306a36Sopenharmony_ci R##_f[1] += q; \ 47662306a36Sopenharmony_ci } \ 47762306a36Sopenharmony_ci _FP_FRAC_SLL_4(X, 1); \ 47862306a36Sopenharmony_ci q >>= 1; \ 47962306a36Sopenharmony_ci } \ 48062306a36Sopenharmony_ci q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ 48162306a36Sopenharmony_ci while (q != _FP_WORK_ROUND) \ 48262306a36Sopenharmony_ci { \ 48362306a36Sopenharmony_ci T##_f[0] = S##_f[0] + q; \ 48462306a36Sopenharmony_ci T##_f[1] = S##_f[1]; \ 48562306a36Sopenharmony_ci T##_f[2] = S##_f[2]; \ 48662306a36Sopenharmony_ci T##_f[3] = S##_f[3]; \ 48762306a36Sopenharmony_ci if (_FP_FRAC_GE_4(X,T)) \ 48862306a36Sopenharmony_ci { \ 48962306a36Sopenharmony_ci S##_f[0] = T##_f[0] + q; \ 49062306a36Sopenharmony_ci S##_f[1] += (T##_f[0] > S##_f[0]); \ 49162306a36Sopenharmony_ci S##_f[2] += (T##_f[1] > S##_f[1]); \ 49262306a36Sopenharmony_ci S##_f[3] += (T##_f[2] > S##_f[2]); \ 49362306a36Sopenharmony_ci _FP_FRAC_DEC_4(X, T); \ 49462306a36Sopenharmony_ci R##_f[0] += q; \ 49562306a36Sopenharmony_ci } \ 49662306a36Sopenharmony_ci _FP_FRAC_SLL_4(X, 1); \ 49762306a36Sopenharmony_ci q >>= 1; \ 49862306a36Sopenharmony_ci } \ 49962306a36Sopenharmony_ci if (!_FP_FRAC_ZEROP_4(X)) \ 50062306a36Sopenharmony_ci { \ 50162306a36Sopenharmony_ci if (_FP_FRAC_GT_4(X,S)) \ 50262306a36Sopenharmony_ci R##_f[0] |= _FP_WORK_ROUND; \ 50362306a36Sopenharmony_ci R##_f[0] |= _FP_WORK_STICKY; \ 50462306a36Sopenharmony_ci } \ 50562306a36Sopenharmony_ci } while (0) 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci/* 50962306a36Sopenharmony_ci * Internals 51062306a36Sopenharmony_ci */ 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \ 51362306a36Sopenharmony_ci (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0) 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci#ifndef __FP_FRAC_ADD_3 51662306a36Sopenharmony_ci#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ 51762306a36Sopenharmony_ci do { \ 51862306a36Sopenharmony_ci int _c1, _c2; \ 51962306a36Sopenharmony_ci r0 = x0 + y0; \ 52062306a36Sopenharmony_ci _c1 = r0 < x0; \ 52162306a36Sopenharmony_ci r1 = x1 + y1; \ 52262306a36Sopenharmony_ci _c2 = r1 < x1; \ 52362306a36Sopenharmony_ci r1 += _c1; \ 52462306a36Sopenharmony_ci _c2 |= r1 < _c1; \ 52562306a36Sopenharmony_ci r2 = x2 + y2 + _c2; \ 52662306a36Sopenharmony_ci } while (0) 52762306a36Sopenharmony_ci#endif 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci#ifndef __FP_FRAC_ADD_4 53062306a36Sopenharmony_ci#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ 53162306a36Sopenharmony_ci do { \ 53262306a36Sopenharmony_ci int _c1, _c2, _c3; \ 53362306a36Sopenharmony_ci r0 = x0 + y0; \ 53462306a36Sopenharmony_ci _c1 = r0 < x0; \ 53562306a36Sopenharmony_ci r1 = x1 + y1; \ 53662306a36Sopenharmony_ci _c2 = r1 < x1; \ 53762306a36Sopenharmony_ci r1 += _c1; \ 53862306a36Sopenharmony_ci _c2 |= r1 < _c1; \ 53962306a36Sopenharmony_ci r2 = x2 + y2; \ 54062306a36Sopenharmony_ci _c3 = r2 < x2; \ 54162306a36Sopenharmony_ci r2 += _c2; \ 54262306a36Sopenharmony_ci _c3 |= r2 < _c2; \ 54362306a36Sopenharmony_ci r3 = x3 + y3 + _c3; \ 54462306a36Sopenharmony_ci } while (0) 54562306a36Sopenharmony_ci#endif 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci#ifndef __FP_FRAC_SUB_3 54862306a36Sopenharmony_ci#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ 54962306a36Sopenharmony_ci do { \ 55062306a36Sopenharmony_ci int _c1, _c2; \ 55162306a36Sopenharmony_ci r0 = x0 - y0; \ 55262306a36Sopenharmony_ci _c1 = r0 > x0; \ 55362306a36Sopenharmony_ci r1 = x1 - y1; \ 55462306a36Sopenharmony_ci _c2 = r1 > x1; \ 55562306a36Sopenharmony_ci r1 -= _c1; \ 55662306a36Sopenharmony_ci _c2 |= r1 > _c1; \ 55762306a36Sopenharmony_ci r2 = x2 - y2 - _c2; \ 55862306a36Sopenharmony_ci } while (0) 55962306a36Sopenharmony_ci#endif 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci#ifndef __FP_FRAC_SUB_4 56262306a36Sopenharmony_ci#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ 56362306a36Sopenharmony_ci do { \ 56462306a36Sopenharmony_ci int _c1, _c2, _c3; \ 56562306a36Sopenharmony_ci r0 = x0 - y0; \ 56662306a36Sopenharmony_ci _c1 = r0 > x0; \ 56762306a36Sopenharmony_ci r1 = x1 - y1; \ 56862306a36Sopenharmony_ci _c2 = r1 > x1; \ 56962306a36Sopenharmony_ci r1 -= _c1; \ 57062306a36Sopenharmony_ci _c2 |= r1 > _c1; \ 57162306a36Sopenharmony_ci r2 = x2 - y2; \ 57262306a36Sopenharmony_ci _c3 = r2 > x2; \ 57362306a36Sopenharmony_ci r2 -= _c2; \ 57462306a36Sopenharmony_ci _c3 |= r2 > _c2; \ 57562306a36Sopenharmony_ci r3 = x3 - y3 - _c3; \ 57662306a36Sopenharmony_ci } while (0) 57762306a36Sopenharmony_ci#endif 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci#ifndef __FP_FRAC_DEC_3 58062306a36Sopenharmony_ci#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) \ 58162306a36Sopenharmony_ci do { \ 58262306a36Sopenharmony_ci UWtype _t0, _t1, _t2; \ 58362306a36Sopenharmony_ci _t0 = x0, _t1 = x1, _t2 = x2; \ 58462306a36Sopenharmony_ci __FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0); \ 58562306a36Sopenharmony_ci } while (0) 58662306a36Sopenharmony_ci#endif 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci#ifndef __FP_FRAC_DEC_4 58962306a36Sopenharmony_ci#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) \ 59062306a36Sopenharmony_ci do { \ 59162306a36Sopenharmony_ci UWtype _t0, _t1, _t2, _t3; \ 59262306a36Sopenharmony_ci _t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3; \ 59362306a36Sopenharmony_ci __FP_FRAC_SUB_4 (x3,x2,x1,x0,_t3,_t2,_t1,_t0, y3,y2,y1,y0); \ 59462306a36Sopenharmony_ci } while (0) 59562306a36Sopenharmony_ci#endif 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci#ifndef __FP_FRAC_ADDI_4 59862306a36Sopenharmony_ci#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \ 59962306a36Sopenharmony_ci do { \ 60062306a36Sopenharmony_ci UWtype _t; \ 60162306a36Sopenharmony_ci _t = ((x0 += i) < i); \ 60262306a36Sopenharmony_ci x1 += _t; _t = (x1 < _t); \ 60362306a36Sopenharmony_ci x2 += _t; _t = (x2 < _t); \ 60462306a36Sopenharmony_ci x3 += _t; \ 60562306a36Sopenharmony_ci } while (0) 60662306a36Sopenharmony_ci#endif 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci/* Convert FP values between word sizes. This appears to be more 60962306a36Sopenharmony_ci * complicated than I'd have expected it to be, so these might be 61062306a36Sopenharmony_ci * wrong... These macros are in any case somewhat bogus because they 61162306a36Sopenharmony_ci * use information about what various FRAC_n variables look like 61262306a36Sopenharmony_ci * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do 61362306a36Sopenharmony_ci * the ones in op-2.h and op-1.h. 61462306a36Sopenharmony_ci */ 61562306a36Sopenharmony_ci#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S) \ 61662306a36Sopenharmony_ci do { \ 61762306a36Sopenharmony_ci if (S##_c != FP_CLS_NAN) \ 61862306a36Sopenharmony_ci _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \ 61962306a36Sopenharmony_ci _FP_WFRACBITS_##sfs); \ 62062306a36Sopenharmony_ci else \ 62162306a36Sopenharmony_ci _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs)); \ 62262306a36Sopenharmony_ci D##_f = S##_f[0]; \ 62362306a36Sopenharmony_ci } while (0) 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S) \ 62662306a36Sopenharmony_ci do { \ 62762306a36Sopenharmony_ci if (S##_c != FP_CLS_NAN) \ 62862306a36Sopenharmony_ci _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \ 62962306a36Sopenharmony_ci _FP_WFRACBITS_##sfs); \ 63062306a36Sopenharmony_ci else \ 63162306a36Sopenharmony_ci _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs)); \ 63262306a36Sopenharmony_ci D##_f0 = S##_f[0]; \ 63362306a36Sopenharmony_ci D##_f1 = S##_f[1]; \ 63462306a36Sopenharmony_ci } while (0) 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci/* Assembly/disassembly for converting to/from integral types. 63762306a36Sopenharmony_ci * No shifting or overflow handled here. 63862306a36Sopenharmony_ci */ 63962306a36Sopenharmony_ci/* Put the FP value X into r, which is an integer of size rsize. */ 64062306a36Sopenharmony_ci#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \ 64162306a36Sopenharmony_ci do { \ 64262306a36Sopenharmony_ci if (rsize <= _FP_W_TYPE_SIZE) \ 64362306a36Sopenharmony_ci r = X##_f[0]; \ 64462306a36Sopenharmony_ci else if (rsize <= 2*_FP_W_TYPE_SIZE) \ 64562306a36Sopenharmony_ci { \ 64662306a36Sopenharmony_ci r = X##_f[1]; \ 64762306a36Sopenharmony_ci r <<= _FP_W_TYPE_SIZE; \ 64862306a36Sopenharmony_ci r += X##_f[0]; \ 64962306a36Sopenharmony_ci } \ 65062306a36Sopenharmony_ci else \ 65162306a36Sopenharmony_ci { \ 65262306a36Sopenharmony_ci /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \ 65362306a36Sopenharmony_ci /* and int == 4words as a single case. */ \ 65462306a36Sopenharmony_ci r = X##_f[3]; \ 65562306a36Sopenharmony_ci r <<= _FP_W_TYPE_SIZE; \ 65662306a36Sopenharmony_ci r += X##_f[2]; \ 65762306a36Sopenharmony_ci r <<= _FP_W_TYPE_SIZE; \ 65862306a36Sopenharmony_ci r += X##_f[1]; \ 65962306a36Sopenharmony_ci r <<= _FP_W_TYPE_SIZE; \ 66062306a36Sopenharmony_ci r += X##_f[0]; \ 66162306a36Sopenharmony_ci } \ 66262306a36Sopenharmony_ci } while (0) 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci/* "No disassemble Number Five!" */ 66562306a36Sopenharmony_ci/* move an integer of size rsize into X's fractional part. We rely on 66662306a36Sopenharmony_ci * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid 66762306a36Sopenharmony_ci * having to mask the values we store into it. 66862306a36Sopenharmony_ci */ 66962306a36Sopenharmony_ci#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \ 67062306a36Sopenharmony_ci do { \ 67162306a36Sopenharmony_ci X##_f[0] = r; \ 67262306a36Sopenharmony_ci X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \ 67362306a36Sopenharmony_ci X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \ 67462306a36Sopenharmony_ci X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \ 67562306a36Sopenharmony_ci } while (0) 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S) \ 67862306a36Sopenharmony_ci do { \ 67962306a36Sopenharmony_ci D##_f[0] = S##_f; \ 68062306a36Sopenharmony_ci D##_f[1] = D##_f[2] = D##_f[3] = 0; \ 68162306a36Sopenharmony_ci _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ 68262306a36Sopenharmony_ci } while (0) 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S) \ 68562306a36Sopenharmony_ci do { \ 68662306a36Sopenharmony_ci D##_f[0] = S##_f0; \ 68762306a36Sopenharmony_ci D##_f[1] = S##_f1; \ 68862306a36Sopenharmony_ci D##_f[2] = D##_f[3] = 0; \ 68962306a36Sopenharmony_ci _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ 69062306a36Sopenharmony_ci } while (0) 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci#endif 693