1*8ec969ceSTreehugger Robot /* 2*8ec969ceSTreehugger Robot * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische 3*8ec969ceSTreehugger Robot * Universitaet Berlin. See the accompanying file "COPYRIGHT" for 4*8ec969ceSTreehugger Robot * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. 5*8ec969ceSTreehugger Robot */ 6*8ec969ceSTreehugger Robot 7*8ec969ceSTreehugger Robot /* $Header: /tmp_amd/presto/export/kbs/jutta/src/gsm/RCS/add.c,v 1.6 1996/07/02 09:57:33 jutta Exp $ */ 8*8ec969ceSTreehugger Robot 9*8ec969ceSTreehugger Robot /* 10*8ec969ceSTreehugger Robot * See private.h for the more commonly used macro versions. 11*8ec969ceSTreehugger Robot */ 12*8ec969ceSTreehugger Robot 13*8ec969ceSTreehugger Robot #include <stdio.h> 14*8ec969ceSTreehugger Robot #include <assert.h> 15*8ec969ceSTreehugger Robot 16*8ec969ceSTreehugger Robot #include "private.h" 17*8ec969ceSTreehugger Robot #include "gsm.h" 18*8ec969ceSTreehugger Robot #include "proto.h" 19*8ec969ceSTreehugger Robot 20*8ec969ceSTreehugger Robot #define saturate(x) \ 21*8ec969ceSTreehugger Robot ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) 22*8ec969ceSTreehugger Robot 23*8ec969ceSTreehugger Robot word gsm_add P2((a,b), word a, word b) 24*8ec969ceSTreehugger Robot { 25*8ec969ceSTreehugger Robot longword sum = (longword)a + (longword)b; 26*8ec969ceSTreehugger Robot return saturate(sum); 27*8ec969ceSTreehugger Robot } 28*8ec969ceSTreehugger Robot 29*8ec969ceSTreehugger Robot word gsm_sub P2((a,b), word a, word b) 30*8ec969ceSTreehugger Robot { 31*8ec969ceSTreehugger Robot longword diff = (longword)a - (longword)b; 32*8ec969ceSTreehugger Robot return saturate(diff); 33*8ec969ceSTreehugger Robot } 34*8ec969ceSTreehugger Robot 35*8ec969ceSTreehugger Robot word gsm_mult P2((a,b), word a, word b) 36*8ec969ceSTreehugger Robot { 37*8ec969ceSTreehugger Robot if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; 38*8ec969ceSTreehugger Robot else return SASR( (longword)a * (longword)b, 15 ); 39*8ec969ceSTreehugger Robot } 40*8ec969ceSTreehugger Robot 41*8ec969ceSTreehugger Robot word gsm_mult_r P2((a,b), word a, word b) 42*8ec969ceSTreehugger Robot { 43*8ec969ceSTreehugger Robot if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; 44*8ec969ceSTreehugger Robot else { 45*8ec969ceSTreehugger Robot longword prod = (longword)a * (longword)b + 16384; 46*8ec969ceSTreehugger Robot prod >>= 15; 47*8ec969ceSTreehugger Robot return prod & 0xFFFF; 48*8ec969ceSTreehugger Robot } 49*8ec969ceSTreehugger Robot } 50*8ec969ceSTreehugger Robot 51*8ec969ceSTreehugger Robot word gsm_abs P1((a), word a) 52*8ec969ceSTreehugger Robot { 53*8ec969ceSTreehugger Robot return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; 54*8ec969ceSTreehugger Robot } 55*8ec969ceSTreehugger Robot 56*8ec969ceSTreehugger Robot longword gsm_L_mult P2((a,b),word a, word b) 57*8ec969ceSTreehugger Robot { 58*8ec969ceSTreehugger Robot assert( a != MIN_WORD || b != MIN_WORD ); 59*8ec969ceSTreehugger Robot return ((longword)a * (longword)b) << 1; 60*8ec969ceSTreehugger Robot } 61*8ec969ceSTreehugger Robot 62*8ec969ceSTreehugger Robot longword gsm_L_add P2((a,b), longword a, longword b) 63*8ec969ceSTreehugger Robot { 64*8ec969ceSTreehugger Robot if (a < 0) { 65*8ec969ceSTreehugger Robot if (b >= 0) return a + b; 66*8ec969ceSTreehugger Robot else { 67*8ec969ceSTreehugger Robot ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); 68*8ec969ceSTreehugger Robot return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; 69*8ec969ceSTreehugger Robot } 70*8ec969ceSTreehugger Robot } 71*8ec969ceSTreehugger Robot else if (b <= 0) return a + b; 72*8ec969ceSTreehugger Robot else { 73*8ec969ceSTreehugger Robot ulongword A = (ulongword)a + (ulongword)b; 74*8ec969ceSTreehugger Robot return A > MAX_LONGWORD ? MAX_LONGWORD : A; 75*8ec969ceSTreehugger Robot } 76*8ec969ceSTreehugger Robot } 77*8ec969ceSTreehugger Robot 78*8ec969ceSTreehugger Robot longword gsm_L_sub P2((a,b), longword a, longword b) 79*8ec969ceSTreehugger Robot { 80*8ec969ceSTreehugger Robot if (a >= 0) { 81*8ec969ceSTreehugger Robot if (b >= 0) return a - b; 82*8ec969ceSTreehugger Robot else { 83*8ec969ceSTreehugger Robot /* a>=0, b<0 */ 84*8ec969ceSTreehugger Robot 85*8ec969ceSTreehugger Robot ulongword A = (ulongword)a + -(b + 1); 86*8ec969ceSTreehugger Robot return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); 87*8ec969ceSTreehugger Robot } 88*8ec969ceSTreehugger Robot } 89*8ec969ceSTreehugger Robot else if (b <= 0) return a - b; 90*8ec969ceSTreehugger Robot else { 91*8ec969ceSTreehugger Robot /* a<0, b>0 */ 92*8ec969ceSTreehugger Robot 93*8ec969ceSTreehugger Robot ulongword A = (ulongword)-(a + 1) + b; 94*8ec969ceSTreehugger Robot return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; 95*8ec969ceSTreehugger Robot } 96*8ec969ceSTreehugger Robot } 97*8ec969ceSTreehugger Robot 98*8ec969ceSTreehugger Robot static unsigned char const bitoff[ 256 ] = { 99*8ec969ceSTreehugger Robot 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 100*8ec969ceSTreehugger Robot 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 101*8ec969ceSTreehugger Robot 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 102*8ec969ceSTreehugger Robot 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 103*8ec969ceSTreehugger Robot 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 104*8ec969ceSTreehugger Robot 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 105*8ec969ceSTreehugger Robot 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 106*8ec969ceSTreehugger Robot 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 107*8ec969ceSTreehugger Robot 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108*8ec969ceSTreehugger Robot 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109*8ec969ceSTreehugger Robot 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110*8ec969ceSTreehugger Robot 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111*8ec969ceSTreehugger Robot 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112*8ec969ceSTreehugger Robot 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 113*8ec969ceSTreehugger Robot 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114*8ec969ceSTreehugger Robot 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 115*8ec969ceSTreehugger Robot }; 116*8ec969ceSTreehugger Robot 117*8ec969ceSTreehugger Robot word gsm_norm P1((a), longword a ) 118*8ec969ceSTreehugger Robot /* 119*8ec969ceSTreehugger Robot * the number of left shifts needed to normalize the 32 bit 120*8ec969ceSTreehugger Robot * variable L_var1 for positive values on the interval 121*8ec969ceSTreehugger Robot * 122*8ec969ceSTreehugger Robot * with minimum of 123*8ec969ceSTreehugger Robot * minimum of 1073741824 (01000000000000000000000000000000) and 124*8ec969ceSTreehugger Robot * maximum of 2147483647 (01111111111111111111111111111111) 125*8ec969ceSTreehugger Robot * 126*8ec969ceSTreehugger Robot * 127*8ec969ceSTreehugger Robot * and for negative values on the interval with 128*8ec969ceSTreehugger Robot * minimum of -2147483648 (-10000000000000000000000000000000) and 129*8ec969ceSTreehugger Robot * maximum of -1073741824 ( -1000000000000000000000000000000). 130*8ec969ceSTreehugger Robot * 131*8ec969ceSTreehugger Robot * in order to normalize the result, the following 132*8ec969ceSTreehugger Robot * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); 133*8ec969ceSTreehugger Robot * 134*8ec969ceSTreehugger Robot * (That's 'ffs', only from the left, not the right..) 135*8ec969ceSTreehugger Robot */ 136*8ec969ceSTreehugger Robot { 137*8ec969ceSTreehugger Robot assert(a != 0); 138*8ec969ceSTreehugger Robot 139*8ec969ceSTreehugger Robot if (a < 0) { 140*8ec969ceSTreehugger Robot if (a <= -1073741824) return 0; 141*8ec969ceSTreehugger Robot a = ~a; 142*8ec969ceSTreehugger Robot } 143*8ec969ceSTreehugger Robot 144*8ec969ceSTreehugger Robot return a & 0xffff0000 145*8ec969ceSTreehugger Robot ? ( a & 0xff000000 146*8ec969ceSTreehugger Robot ? -1 + bitoff[ 0xFF & (a >> 24) ] 147*8ec969ceSTreehugger Robot : 7 + bitoff[ 0xFF & (a >> 16) ] ) 148*8ec969ceSTreehugger Robot : ( a & 0xff00 149*8ec969ceSTreehugger Robot ? 15 + bitoff[ 0xFF & (a >> 8) ] 150*8ec969ceSTreehugger Robot : 23 + bitoff[ 0xFF & a ] ); 151*8ec969ceSTreehugger Robot } 152*8ec969ceSTreehugger Robot 153*8ec969ceSTreehugger Robot longword gsm_L_asl P2((a,n), longword a, int n) 154*8ec969ceSTreehugger Robot { 155*8ec969ceSTreehugger Robot if (n >= 32) return 0; 156*8ec969ceSTreehugger Robot if (n <= -32) return -(a < 0); 157*8ec969ceSTreehugger Robot if (n < 0) return gsm_L_asr(a, -n); 158*8ec969ceSTreehugger Robot return a << n; 159*8ec969ceSTreehugger Robot } 160*8ec969ceSTreehugger Robot 161*8ec969ceSTreehugger Robot word gsm_asl P2((a,n), word a, int n) 162*8ec969ceSTreehugger Robot { 163*8ec969ceSTreehugger Robot if (n >= 16) return 0; 164*8ec969ceSTreehugger Robot if (n <= -16) return -(a < 0); 165*8ec969ceSTreehugger Robot if (n < 0) return gsm_asr(a, -n); 166*8ec969ceSTreehugger Robot return a << n; 167*8ec969ceSTreehugger Robot } 168*8ec969ceSTreehugger Robot 169*8ec969ceSTreehugger Robot longword gsm_L_asr P2((a,n), longword a, int n) 170*8ec969ceSTreehugger Robot { 171*8ec969ceSTreehugger Robot if (n >= 32) return -(a < 0); 172*8ec969ceSTreehugger Robot if (n <= -32) return 0; 173*8ec969ceSTreehugger Robot if (n < 0) return a << -n; 174*8ec969ceSTreehugger Robot 175*8ec969ceSTreehugger Robot # ifdef SASR 176*8ec969ceSTreehugger Robot return a >> n; 177*8ec969ceSTreehugger Robot # else 178*8ec969ceSTreehugger Robot if (a >= 0) return a >> n; 179*8ec969ceSTreehugger Robot else return -(longword)( -(ulongword)a >> n ); 180*8ec969ceSTreehugger Robot # endif 181*8ec969ceSTreehugger Robot } 182*8ec969ceSTreehugger Robot 183*8ec969ceSTreehugger Robot word gsm_asr P2((a,n), word a, int n) 184*8ec969ceSTreehugger Robot { 185*8ec969ceSTreehugger Robot if (n >= 16) return -(a < 0); 186*8ec969ceSTreehugger Robot if (n <= -16) return 0; 187*8ec969ceSTreehugger Robot if (n < 0) return a << -n; 188*8ec969ceSTreehugger Robot 189*8ec969ceSTreehugger Robot # ifdef SASR 190*8ec969ceSTreehugger Robot return a >> n; 191*8ec969ceSTreehugger Robot # else 192*8ec969ceSTreehugger Robot if (a >= 0) return a >> n; 193*8ec969ceSTreehugger Robot else return -(word)( -(uword)a >> n ); 194*8ec969ceSTreehugger Robot # endif 195*8ec969ceSTreehugger Robot } 196*8ec969ceSTreehugger Robot 197*8ec969ceSTreehugger Robot /* 198*8ec969ceSTreehugger Robot * (From p. 46, end of section 4.2.5) 199*8ec969ceSTreehugger Robot * 200*8ec969ceSTreehugger Robot * NOTE: The following lines gives [sic] one correct implementation 201*8ec969ceSTreehugger Robot * of the div(num, denum) arithmetic operation. Compute div 202*8ec969ceSTreehugger Robot * which is the integer division of num by denum: with denum 203*8ec969ceSTreehugger Robot * >= num > 0 204*8ec969ceSTreehugger Robot */ 205*8ec969ceSTreehugger Robot 206*8ec969ceSTreehugger Robot word gsm_div P2((num,denum), word num, word denum) 207*8ec969ceSTreehugger Robot { 208*8ec969ceSTreehugger Robot longword L_num = num; 209*8ec969ceSTreehugger Robot longword L_denum = denum; 210*8ec969ceSTreehugger Robot word div = 0; 211*8ec969ceSTreehugger Robot int k = 15; 212*8ec969ceSTreehugger Robot 213*8ec969ceSTreehugger Robot /* The parameter num sometimes becomes zero. 214*8ec969ceSTreehugger Robot * Although this is explicitly guarded against in 4.2.5, 215*8ec969ceSTreehugger Robot * we assume that the result should then be zero as well. 216*8ec969ceSTreehugger Robot */ 217*8ec969ceSTreehugger Robot 218*8ec969ceSTreehugger Robot /* assert(num != 0); */ 219*8ec969ceSTreehugger Robot 220*8ec969ceSTreehugger Robot assert(num >= 0 && denum >= num); 221*8ec969ceSTreehugger Robot if (num == 0) 222*8ec969ceSTreehugger Robot return 0; 223*8ec969ceSTreehugger Robot 224*8ec969ceSTreehugger Robot while (k--) { 225*8ec969ceSTreehugger Robot div <<= 1; 226*8ec969ceSTreehugger Robot L_num <<= 1; 227*8ec969ceSTreehugger Robot 228*8ec969ceSTreehugger Robot if (L_num >= L_denum) { 229*8ec969ceSTreehugger Robot L_num -= L_denum; 230*8ec969ceSTreehugger Robot div++; 231*8ec969ceSTreehugger Robot } 232*8ec969ceSTreehugger Robot } 233*8ec969ceSTreehugger Robot 234*8ec969ceSTreehugger Robot return div; 235*8ec969ceSTreehugger Robot } 236