www.pudn.com > SMV_Code.rar > basic_op.c
/*=========================================================================*/ /* Each of the companies; Ericsson, Lucent, Mindspeed, Motorola, Nokia, */ /* Nortel Networks, and Qualcomm (hereinafter referred to individually as */ /* “Source” or collectively as “Sources”) do hereby state: */ /* */ /* To the extent to which the Source(s) may legally and freely do so, */ /* the Source(s), upon submission of a Contribution, grant(s) a free, */ /* irrevocable, non-exclusive, license to the Third Generation Partnership */ /* Project 2 (3GPP2) and its Organizational Partners: ARIB, CCSA, TIA, */ /* TTA, and TTC, under the Source’s copyright or copyright license rights */ /* in the Contribution, to, in whole or in part, copy, make derivative */ /* works, perform, display and distribute the Contribution and derivative */ /* works thereof consistent with 3GPP2’s and each Organizational Partner’s */ /* policies and procedures, with the right to (i) sublicense the foregoing */ /* rights consistent with 3GPP2’s and each Organizational Partner’s */ /* policies and procedures and (ii) copyright and sell, if applicable) in */ /* 3GPP2's name or each Organizational Partner’s name any 3GPP2 or */ /* transposed Publication even though this Publication may contain the */ /* Contribution or a derivative work thereof. The Contribution shall */ /* disclose any known limitations on the Source’s rights to license as */ /* herein provided. */ /* */ /* When a Contribution is submitted by the Source(s) to assist the */ /* formulating groups of 3GPP2 or any of its Organizational Partners, */ /* it is proposed to the Committee as a basis for discussion and is not */ /* to be construed as a binding proposal on the Source(s). The Source(s) */ /* specifically reserve(s) the right to amend or modify the material */ /* contained in the Contribution. Nothing contained in the Contribution */ /* shall, except as herein expressly provided, be construed as conferring */ /* by implication, estoppel or otherwise, any license or right under */ /* (i) any existing or later issuing patent, whether or not the use of */ /* information in the document necessarily employs an invention of any */ /* existing or later issued patent, (ii) any copyright, (iii) any */ /* trademark, or (iv) any other intellectual property right. */ /* */ /* With respect to the Software necessary for the practice of any or all */ /* Normative portions of the Selectable Mode Vocoder (SMV) as it exists on */ /* the date of submittal of this form, should the SMV be approved as a */ /* Specification or Report by 3GPP2, or as a transposed Standard by any of */ /* the 3GPP2’s Organizational Partners, the Source(s) state(s) that a */ /* worldwide license to reproduce, use and distribute the Software, the */ /* license rights to which are held by the Source(s), will be made */ /* available to applicants under terms and conditions that are reasonable */ /* and non-discriminatory, which may include monetary compensation, */ /* and only to the extent necessary for the practice of any or all of the */ /* Normative portions of the SMV or the field of use of practice of the */ /* SMV Specification, Report, or Standard. The statement contained above */ /* is irrevocable and shall be binding upon the Source(s). In the event */ /* the rights of the Source(s) in and to copyright or copyright license */ /* rights subject to such commitment are assigned or transferred, */ /* the Source(s) shall notify the assignee or transferee of the existence */ /* of such commitments. */ /*=========================================================================*/ /* */ /*-------------------------------------------------------------------*/ /*===================================================================*/ /*************************************************************************** * * File Name: basic_op.c (mathevrc.c with op counting added) * * Purpose: Contains functions which implement the primitive * arithmetic operations. * * The functions in this file are listed below. Some of them are * defined in terms of other basic operations. One of the * routines, saturate() is static. This is not a basic * operation, and is not referenced outside the scope of this * file. * * * abs_s() * add() * clearOverflow() * divide_s() * extract_h() * extract_l() * isOverflow() * L_abs() * L_add() * L_add_c() * L_deposit_h() * L_deposit_l() * L_mac() * L_msu() * L_mult() * L_negate() * L_shift_r() * L_shl() * L_shr() * L_sub() * L_sub_c() * L_saturate() * mac_r() * msu_r() * mult() * mult_r() * negate() * norm_l() * norm_s() * popOverflow() * round32_16() * saturate() * setOverflow() * shift_r() * shl() * shr() * sub() * **************************************************************************/ /*_________________________________________________________________________ | | | Include Files | |_________________________________________________________________________| */ #include#include "basic_op.h" #ifdef WMOPS_FX #include "typedef_fx.h" #include "main_fx.h" #include "const_fx.h" #include "ext_var_fx.h" #include "lib_wmp_fx.h" #endif int giOverflow = 0; int giOldOverflow = 0; // local function: /*************************************************************************** * * FUNCTION NAME: saturate * * PURPOSE: * * Limit the 32 bit input to the range of a 16 bit word. * * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * KEYWORDS: saturation, limiting, limit, saturate, 16 bits * *************************************************************************/ static Word16 saturate(Word32 L_var1) { Word16 swOut; if (L_var1 > SW_MAX) { swOut = SW_MAX; giOverflow = 1; } else if (L_var1 < SW_MIN) { swOut = SW_MIN; giOverflow = 1; } else swOut = (Word16) L_var1; /* automatic type conversion */ return (swOut); } /***************************************************************************/ /***************************************************************************/ /*------------------------------ Public Functions -------------------------*/ /***************************************************************************/ /***************************************************************************/ /*************************************************************************** * * FUNCTION NAME: L_saturate * * PURPOSE: * * Limit the input double (possibly exceeding 32 bit dynamic * range) having to the 32 output wordsize. * * INPUTS: * * dVar1 * A double whose range is * 0x8 0000 0000 <= L_var1 <= 0x7 ffff ffff. * i.e. a 33 bit number. Not modified. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long integer (Word32) where the DSP's * rules of saturation are followed: * for: 0x8000 0000 <= dVal1 <= 0x7fff ffff * input == output, no saturation * for: 0x8000 0000 > dVal1 output 0x8000 0000 * for: dVal1 > 0x7fff ffff output 0x7fff ffff * * KEYWORDS: saturation, limiting, limit, saturate, 32 bits * *************************************************************************/ static Word32 L_saturate(double dVar1) { if (dVar1 > (double) LW_MAX) { dVar1 = (double) LW_MAX; giOverflow = 1; } else if (dVar1 < (double) LW_MIN) { dVar1 = (double) LW_MIN; giOverflow = 1; } #ifdef WMOPS_FX counter_fx.L_saturate++; #endif return ((long) dVar1); } /*************************************************************************** * * FUNCTION NAME: abs_s * * PURPOSE: * * Take the absolute value of the 16 bit input. An input of * -0x8000 results in a return value of 0x7fff. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0x0000 0000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * Take the absolute value of the 16 bit input. An input of * -0x8000 results in a return value of 0x7fff. * * KEYWORDS: absolute value, abs * *************************************************************************/ Word16 abs_s(Word16 var1) { Word16 swOut; if (var1 == SW_MIN) { swOut = SW_MAX; giOverflow = 1; } else { if (var1 < 0) swOut = -var1; else swOut = var1; } #ifdef WMOPS_FX counter_fx.abs_s++; #endif return (swOut); } /*************************************************************************** * * FUNCTION NAME: add * * PURPOSE: * * Perform the addition of the two 16 bit input variable with * saturation. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * Perform the addition of the two 16 bit input variable with * saturation. * * swOut = var1 + var2 * * swOut is set to 0x7fff if the operation results in an * overflow. swOut is set to 0x8000 if the operation results * in an underflow. * * KEYWORDS: add, addition * *************************************************************************/ Word16 add(Word16 var1, Word16 var2) { Word32 L_sum; Word16 swOut; L_sum = (Word32) var1 + var2; swOut = saturate(L_sum); #ifdef WMOPS_FX counter_fx.add++; #endif return (swOut); } /**************************************************************************** * * FUNCTION NAME: clearOverflow * * PURPOSE: * * Clear the overflow flag * * INPUTS: * * none * * * OUTPUTS: global overflow flag is cleared * previous value stored in giOldOverflow * * RETURN VALUE: previous value of overflow * * * KEYWORDS: saturation, limit, overflow * ***************************************************************************/ int clearOverflow(void) { giOldOverflow = giOverflow; giOverflow = 0; #ifdef WMOPS_FX counter_fx.clearOverflow++; #endif return (giOldOverflow); } /*************************************************************************** * * FUNCTION NAME: divide_s * * PURPOSE: * * Divide var1 by var2. Note that both must be positive, and * var1 >= var2. The output is set to 0 if invalid input is * provided. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * In the case where var1==var2 the function returns 0x7fff. The output * is undefined for invalid inputs. This implementation returns zero * and issues a warning via stdio if invalid input is presented. * * KEYWORDS: divide * *************************************************************************/ Word16 divide_s(Word16 var1, Word16 var2) { Word32 L_div; Word16 swOut; #ifdef WMOPS_FX counter_fx.divide_s++; #endif if (var1 < 0 || var2 < 0 || var1 > var2) { /* undefined output for invalid input into divide_s */ return (0); } if (var1 == var2) { giOverflow = 1; return (0x7fff); } L_div = ((0x00008000L * (Word32) var1) / (Word32) var2); swOut = saturate(L_div); return (swOut); } /*************************************************************************** * * FUNCTION NAME: extract_h * * PURPOSE: * * Extract the 16 MS bits of a 32 bit Word32. Return the 16 bit * number as a Word16. This is used as a "truncation" of a fractional * number. * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * KEYWORDS: assign, truncate * *************************************************************************/ Word16 extract_h(Word32 L_var1) { Word16 var2; var2 = (Word16) (0x0000ffffL & (L_var1 >> 16)); #ifdef WMOPS_FX counter_fx.extract_h++; #endif return (var2); } /*************************************************************************** * * FUNCTION NAME: extract_l * * PURPOSE: * * Extract the 16 LS bits of a 32 bit Word32. Return the 16 bit * number as a Word16. The upper portion of the input Word32 * has no impact whatsoever on the output. * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * * KEYWORDS: extract, assign * *************************************************************************/ Word16 extract_l(Word32 L_var1) { Word16 var2; var2 = (Word16) (0x0000ffffL & L_var1); #ifdef WMOPS_FX counter_fx.extract_l++; #endif return (var2); } /**************************************************************************** * * FUNCTION NAME: isOverflow * * PURPOSE: * * Check to see whether an overflow/saturation/limiting has occurred * * INPUTS: * * none * * * OUTPUTS: none * * RETURN VALUE: 1 if overflow has been flagged * 0 otherwise * * KEYWORDS: saturation, limit, overflow * ***************************************************************************/ int isOverflow(void) { return (giOverflow); } /*************************************************************************** * * FUNCTION NAME: L_abs * * PURPOSE: * * Take the absolute value of the 32 bit input. An input of * -0x8000 0000 results in a return value of 0x7fff ffff. * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * * * KEYWORDS: absolute value, abs * *************************************************************************/ Word32 L_abs(Word32 L_var1) { Word32 L_Out; if (L_var1 == LW_MIN) { L_Out = LW_MAX; giOverflow = 1; } else { if (L_var1 < 0) L_Out = -L_var1; else L_Out = L_var1; } #ifdef WMOPS_FX counter_fx.L_abs++; #endif return (L_Out); } /*************************************************************************** * * FUNCTION NAME: L_add * * PURPOSE: * * Perform the addition of the two 32 bit input variables with * saturation. * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * L_var2 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var2 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * IMPLEMENTATION: * * Perform the addition of the two 32 bit input variables with * saturation. * * L_Out = L_var1 + L_var2 * * L_Out is set to 0x7fff ffff if the operation results in an * overflow. L_Out is set to 0x8000 0000 if the operation * results in an underflow. * * KEYWORDS: add, addition * *************************************************************************/ Word32 L_add(Word32 L_var1, Word32 L_var2) { Word32 L_Sum; double dSum; dSum = (double) L_var1 + (double) L_var2; L_Sum = L_var1 + L_var2; if (dSum != (double) L_Sum) { /* overflow occurred */ L_Sum = L_saturate(dSum); // OP_COUNT(-4); #ifdef WMOPS_FX counter_fx.L_saturate--; #endif } #ifdef WMOPS_FX counter_fx.L_add++; #endif return (L_Sum); } /*************************************************************************** * * FUNCTION NAME: L_deposit_h * * PURPOSE: * * Put the 16 bit input into the 16 MSB's of the output Word32. The * LS 16 bits are zeroed. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff 0000. * * * KEYWORDS: deposit, assign, fractional assign * *************************************************************************/ Word32 L_deposit_h(Word16 var1) { Word32 L_var2; L_var2 = (Word32) var1 << 16; #ifdef WMOPS_FX counter_fx.L_deposit_h++; #endif return (L_var2); } /*************************************************************************** * * FUNCTION NAME: L_deposit_l * * PURPOSE: * * Put the 16 bit input into the 16 LSB's of the output Word32 with * sign extension i.e. the top 16 bits are set to either 0 or 0xffff. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0xffff 8000 <= L_var1 <= 0x0000 7fff. * * KEYWORDS: deposit, assign * *************************************************************************/ Word32 L_deposit_l(Word16 var1) { Word32 L_Out; L_Out = var1; #ifdef WMOPS_FX counter_fx.L_deposit_l++; #endif return (L_Out); } /*************************************************************************** * * FUNCTION NAME: L_mac * * PURPOSE: * * Multiply accumulate. Fractionally multiply two 16 bit * numbers together with saturation. Add that result to the * 32 bit input with saturation. Return the 32 bit result. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * L_var3 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var2 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * IMPLEMENTATION: * * Fractionally multiply two 16 bit numbers together with * saturation. The only numbers which will cause saturation on * the multiply are 0x8000 * 0x8000. * * Add that result to the 32 bit input with saturation. * Return the 32 bit result. * * Please note that this is not a true multiply accumulate as * most processors would implement it. The 0x8000*0x8000 * causes and overflow for this instruction. On most * processors this would cause an overflow only if the 32 bit * input added to it were positive or zero. * * KEYWORDS: mac, multiply accumulate * *************************************************************************/ Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2) { Word32 L_product; L_product = (Word32) var1 *var2; /* integer multiply */ if (L_product == (Word32) 0x40000000) { /* the event 0x8000 * 0x8000, the only possible saturation * in the multiply */ L_product = L_saturate(2147483647.0 + (double) L_var3); #ifdef WMOPS_FX counter_fx.L_saturate--; #endif } else { /* no overflow possible in mult */ L_product = L_product << 1; L_product = L_add(L_var3, L_product); // OP_COUNT(-2); #ifdef WMOPS_FX counter_fx.L_add--; #endif } #ifdef WMOPS_FX counter_fx.L_mac++; #endif return (L_product); } /*************************************************************************** * * FUNCTION NAME: L_msu * * PURPOSE: * * Multiply and subtract. Fractionally multiply two 16 bit * numbers together with saturation. Subtract that result from * the 32 bit input with saturation. Return the 32 bit result. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * L_var3 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var2 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * IMPLEMENTATION: * * Fractionally multiply two 16 bit numbers together with * saturation. The only numbers which will cause saturation on * the multiply are 0x8000 * 0x8000. * * Subtract that result from the 32 bit input with saturation. * Return the 32 bit result. * * Please note that this is not a true multiply accumulate as * most processors would implement it. The 0x8000*0x8000 * causes and overflow for this instruction. On most * processors this would cause an overflow only if the 32 bit * input added to it were negative or zero. * * KEYWORDS: mac, multiply accumulate, msu * *************************************************************************/ Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2) { Word32 L_product; L_product = (Word32) var1 *var2; /* integer multiply */ if (L_product == (Word32) 0x40000000) { /* the event 0x8000 * 0x8000, the only possible saturation * in the multiply */ L_product = L_saturate((double) L_var3 - 2147483647.0); // OP_COUNT(-4); #ifdef WMOPS_FX counter_fx.L_saturate--; #endif } else { /* no overflow possible in mult */ L_product <<= 1; L_product = L_sub(L_var3, L_product); // OP_COUNT(-2); /* LT 6/96 */ #ifdef WMOPS_FX counter_fx.L_sub--; #endif } #ifdef WMOPS_FX counter_fx.L_msu++; #endif return (L_product); } /*************************************************************************** * * FUNCTION NAME: L_mult * * PURPOSE: * * Perform a fractional multipy of the two 16 bit input numbers * with saturation. Output a 32 bit number. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * IMPLEMENTATION: * * Multiply the two the two 16 bit input numbers. If the * result is within this range, left shift the result by one * and output the 32 bit number. The only possible overflow * occurs when var1==var2==-0x8000. In this case output * 0x7fff ffff. * * KEYWORDS: multiply, mult, mpy * *************************************************************************/ Word32 L_mult(Word16 var1, Word16 var2) { Word32 L_product; if (var1 == SW_MIN && var2 == SW_MIN) { L_product = LW_MAX; /* overflow */ giOverflow = 1; } else { L_product = (Word32) var1 *var2; /* integer multiply */ L_product = L_product << 1; } #ifdef WMOPS_FX counter_fx.L_mult++; #endif return (L_product); } /*************************************************************************** * * FUNCTION NAME: L_negate * * PURPOSE: * * Negate the 32 bit input. 0x8000 0000's negated value is * 0x7fff ffff. * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0001 <= L_var1 <= 0x7fff ffff. * * KEYWORDS: negate, negative * *************************************************************************/ Word32 L_negate(Word32 L_var1) { Word32 L_Out; if (L_var1 == LW_MIN) { L_Out = LW_MAX; giOverflow = 1; } else L_Out = -L_var1; #ifdef WMOPS_FX counter_fx.L_negate++; #endif return (L_Out); } /*************************************************************************** * * FUNCTION NAME: L_shift_r * * PURPOSE: * * Shift and round. Perform a shift right. After shifting, use * the last bit shifted out of the LSB to round the result up * or down. * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * * IMPLEMENTATION: * * Shift and round. Perform a shift right. After shifting, use * the last bit shifted out of the LSB to round the result up * or down. This is just like shift_r above except that the * input/output is 32 bits as opposed to 16. * * if var2 is positve perform a arithmetic left shift * with saturation (see L_shl() above). * * If var2 is zero simply return L_var1. * * If var2 is negative perform a arithmetic right shift (L_shr) * of L_var1 by (-var2)+1. Add the LS bit of the result to * L_var1 shifted right (L_shr) by -var2. * * Note that there is no constraint on var2, so if var2 is * -0xffff 8000 then -var2 is 0x0000 8000, not 0x0000 7fff. * This is the reason the L_shl function is used. * * * KEYWORDS: * *************************************************************************/ Word32 L_shift_r(Word32 L_var1, Word16 var2) { Word32 L_Out, L_rnd; if (var2 < -31) { L_Out = 0; } else if (var2 < 0) { /* right shift */ L_rnd = L_shl(L_var1, (Word16)(var2 + 1)) & 0x1; L_Out = L_add(L_shl(L_var1, var2), L_rnd); #ifdef WMOPS_FX counter_fx.L_shl-=2; counter_fx.L_add--; #endif } else { L_Out = L_shl(L_var1, var2); #ifdef WMOPS_FX counter_fx.L_shl--; #endif } #ifdef WMOPS_FX counter_fx.L_shift_r++; #endif return (L_Out); } /*************************************************************************** * * FUNCTION NAME: L_shl * * PURPOSE: * * Arithmetic shift left (or right). * Arithmetically shift the input left by var2. If var2 is * negative then an arithmetic shift right (L_shr) of L_var1 by * -var2 is performed. * * INPUTS: * * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * * IMPLEMENTATION: * * Arithmetically shift the 32 bit input left by var2. This * operation maintains the sign of the input number. If var2 is * negative then an arithmetic shift right (L_shr) of L_var1 by * -var2 is performed. See description of L_shr for details. * * Equivalent to the Full-Rate GSM ">> n" operation. Note that * ANSI-C does not guarantee operation of the C ">>" or "<<" * operator for negative numbers. * * KEYWORDS: shift, arithmetic shift left, * *************************************************************************/ Word32 L_shl(Word32 L_var1, Word16 var2) { Word32 L_Mask, L_Out = 0; int i, iOverflow = 0; if (var2 == 0 || L_var1 == 0) { L_Out = L_var1; } else if (var2 < 0) { if (var2 <= -31) { if (L_var1 > 0) L_Out = 0; else L_Out = 0xffffffffL; } else { L_Out = L_shr(L_var1, (Word16)(-var2)); #ifdef WMOPS_FX counter_fx.L_shr--; #endif } } else { if (var2 >= 31) iOverflow = 1; else { if (L_var1 < 0) L_Mask = LW_SIGN; /* sign bit mask */ else L_Mask = 0x0; L_Out = L_var1; for (i = 0; i < var2 && !iOverflow; i++) { /* check the sign bit */ L_Out = (L_Out & 0x7fffffffL) << 1; if ((L_Mask ^ L_Out) & LW_SIGN) iOverflow = 1; } } if (iOverflow) { /* saturate */ if (L_var1 > 0) L_Out = LW_MAX; else L_Out = LW_MIN; giOverflow = 1; } } #ifdef WMOPS_FX counter_fx.L_shl++; #endif return (L_Out); } /*************************************************************************** * * FUNCTION NAME: L_shr * * PURPOSE: * * Arithmetic shift right (or left). * Arithmetically shift the input right by var2. If var2 is * negative then an arithmetic shift left (shl) of var1 by * -var2 is performed. * * INPUTS: * * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * * IMPLEMENTATION: * * Arithmetically shift the input right by var2. This * operation maintains the sign of the input number. If var2 is * negative then an arithmetic shift left (shl) of L_var1 by * -var2 is performed. See description of L_shl for details. * * The input is a 32 bit number, as is the output. * * Equivalent to the Full-Rate GSM ">> n" operation. Note that * ANSI-C does not guarantee operation of the C ">>" or "<<" * operator for negative numbers. * * KEYWORDS: shift, arithmetic shift right, * *************************************************************************/ Word32 L_shr(Word32 L_var1, Word16 var2) { Word32 L_Mask, L_Out; if (var2 == 0 || L_var1 == 0) { L_Out = L_var1; } else if (var2 < 0) { /* perform a left shift */ /*----------------------*/ if (var2 <= -31) { /* saturate */ if (L_var1 > 0) { L_Out = LW_MAX; giOverflow = 1; } else { L_Out = LW_MIN; giOverflow = 1; } } else { L_Out = L_shl(L_var1, (Word16)(-var2)); // OP_COUNT(-2); #ifdef WMOPS_FX counter_fx.L_shl--; #endif } } else { if (var2 >= 31) { if (L_var1 > 0) L_Out = 0; else L_Out = 0xffffffffL; } else { L_Mask = 0; if (L_var1 < 0) { L_Mask = ~L_Mask << (32 - var2); } L_var1 >>= var2; L_Out = L_Mask | L_var1; } } #ifdef WMOPS_FX counter_fx.L_shr++; #endif return (L_Out); } /*************************************************************************** * * FUNCTION NAME: L_sub * * PURPOSE: * * Perform the subtraction of the two 32 bit input variables with * saturation. * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * L_var2 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var2 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * L_Out * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * IMPLEMENTATION: * * Perform the subtraction of the two 32 bit input variables with * saturation. * * L_Out = L_var1 - L_var2 * * L_Out is set to 0x7fff ffff if the operation results in an * overflow. L_Out is set to 0x8000 0000 if the operation * results in an underflow. * * KEYWORDS: sub, subtraction * *************************************************************************/ Word32 L_sub(Word32 L_var1, Word32 L_var2) { Word32 L_Sum; double dSum; dSum = (double) L_var1 - (double) L_var2; L_Sum = L_var1 - L_var2; if (dSum != L_Sum) { /* overflow occurred */ L_Sum = L_saturate(dSum); #ifdef WMOPS_FX counter_fx.L_saturate--; #endif } #ifdef WMOPS_FX counter_fx.L_sub++; #endif return (L_Sum); } /*************************************************************************** * * FUNCTION NAME:mac_r * * PURPOSE: * * Multiply accumulate and round. Fractionally multiply two 16 * bit numbers together with saturation. Add that result to * the 32 bit input with saturation. Finally round the result * into a 16 bit number. * * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * L_var3 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var2 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * Fractionally multiply two 16 bit numbers together with * saturation. The only numbers which will cause saturation on * the multiply are 0x8000 * 0x8000. * * Add that result to the 32 bit input with saturation. * Round the 32 bit result by adding 0x0000 8000 to the input. * The result may overflow due to the add. If so, the result * is saturated. The 32 bit rounded number is then shifted * down 16 bits and returned as a Word16. * * Please note that this is not a true multiply accumulate as * most processors would implement it. The 0x8000*0x8000 * causes and overflow for this instruction. On most * processors this would cause an overflow only if the 32 bit * input added to it were positive or zero. * * KEYWORDS: mac, multiply accumulate, macr * *************************************************************************/ Word16 mac_r(Word32 L_var3, Word16 var1, Word16 var2) { return (round32_16(L_mac(L_var3, var1, var2))); } /*************************************************************************** * * FUNCTION NAME: msu_r * * PURPOSE: * * Multiply subtract and round. Fractionally multiply two 16 * bit numbers together with saturation. Subtract that result from * the 32 bit input with saturation. Finally round the result * into a 16 bit number. * * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * L_var3 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var2 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * Fractionally multiply two 16 bit numbers together with * saturation. The only numbers which will cause saturation on * the multiply are 0x8000 * 0x8000. * * Subtract that result from the 32 bit input with saturation. * Round the 32 bit result by adding 0x0000 8000 to the input. * The result may overflow due to the add. If so, the result * is saturated. The 32 bit rounded number is then shifted * down 16 bits and returned as a Word16. * * Please note that this is not a true multiply accumulate as * most processors would implement it. The 0x8000*0x8000 * causes and overflow for this instruction. On most * processors this would cause an overflow only if the 32 bit * input added to it were positive or zero. * * KEYWORDS: mac, multiply accumulate, macr * *************************************************************************/ Word16 msu_r(Word32 L_var3, Word16 var1, Word16 var2) { return (round32_16(L_msu(L_var3, var1, var2))); } /*************************************************************************** * * FUNCTION NAME: mult * * PURPOSE: * * Perform a fractional multipy of the two 16 bit input numbers * with saturation and truncation. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * Perform a fractional multipy of the two 16 bit input * numbers. If var1 == var2 == -0x8000, output 0x7fff. * Otherwise output var1*var2 >> 15. The output is a * 16 bit number. * * KEYWORDS: mult, mulitply, mpy * *************************************************************************/ Word16 mult(Word16 var1, Word16 var2) { Word32 L_product; Word16 swOut; L_product = L_mult(var1, var2); swOut = extract_h(L_product); #ifdef WMOPS_FX counter_fx.mult++; counter_fx.L_mult--; counter_fx.extract_h--; #endif return (swOut); } /*************************************************************************** * * FUNCTION NAME: mult_r * * PURPOSE: * * Perform a fractional multipy and round of the two 16 bit * input numbers with saturation. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * This routine is defined as the concatenation of the multiply * operation and the round operation. * * The fractional multiply (L_mult) produces a saturated 32 bit * output. This is followed by a an add of 0x0000 8000 to the * 32 bit result. The result may overflow due to the add. If * so, the result is saturated. The 32 bit rounded number is * then shifted down 16 bits and returned as a Word16. * * * KEYWORDS: multiply and round, round, mult_r, mpyr * *************************************************************************/ Word16 mult_r(Word16 var1, Word16 var2) { Word16 swOut; swOut = round32_16(L_mult(var1, var2)); #ifdef WMOPS_FX counter_fx.mult_r++; counter_fx.L_mult--; counter_fx.round--; #endif return (swOut); } /*************************************************************************** * * FUNCTION NAME: negate * * PURPOSE: * * Negate the 16 bit input. 0x8000's negated value is 0x7fff. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8001 <= swOut <= 0x0000 7fff. * * KEYWORDS: negate, negative, invert * *************************************************************************/ Word16 negate(Word16 var1) { Word16 swOut; if (var1 == SW_MIN) { swOut = SW_MAX; giOverflow = 1; } else swOut = -var1; #ifdef WMOPS_FX counter_fx.negate++; #endif return (swOut); } /*************************************************************************** * * FUNCTION NAME: norm_l * * PURPOSE: * * Get normalize shift count: * * A 32 bit number is input (possiblly unnormalized). Output * the positive (or zero) shift count required to normalize the * input. * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0 <= swOut <= 31 * * * * IMPLEMENTATION: * * Get normalize shift count: * * A 32 bit number is input (possiblly unnormalized). Output * the positive (or zero) shift count required to normalize the * input. * * If zero in input, return 0 as the shift count. * * For non-zero numbers, count the number of left shift * required to get the number to fall into the range: * * 0x4000 0000 >= normlzd number >= 0x7fff ffff (positive number) * or * 0x8000 0000 <= normlzd number < 0xc000 0000 (negative number) * * Return the number of shifts. * * This instruction corresponds exactly to the Full-Rate "norm" * instruction. * * KEYWORDS: norm, normalization * *************************************************************************/ Word16 norm_l(Word32 L_var1) { Word16 swShiftCnt; if (L_var1 != 0) { if (!(L_var1 & LW_SIGN)) { /* positive input */ for (swShiftCnt = 0; !(L_var1 <= LW_MAX && L_var1 >= 0x40000000L); swShiftCnt++) { L_var1 = L_var1 << 1; } } else { /* negative input */ for (swShiftCnt = 0; !(L_var1 >= LW_MIN && L_var1 < (Word32) 0xc0000000L); swShiftCnt++) { L_var1 = L_var1 << 1; } } } else { swShiftCnt = 0; } #ifdef WMOPS_FX counter_fx.norm_l++; #endif return (swShiftCnt); } /*************************************************************************** * * FUNCTION NAME: norm_s * * PURPOSE: * * Get normalize shift count: * * A 16 bit number is input (possiblly unnormalized). Output * the positive (or zero) shift count required to normalize the * input. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0 <= swOut <= 15 * * * * IMPLEMENTATION: * * Get normalize shift count: * * A 16 bit number is input (possiblly unnormalized). Output * the positive (or zero) shift count required to normalize the * input. * * If zero in input, return 0 as the shift count. * * For non-zero numbers, count the number of left shift * required to get the number to fall into the range: * * 0x4000 >= normlzd number >= 0x7fff (positive number) * or * 0x8000 <= normlzd number < 0xc000 (negative number) * * Return the number of shifts. * * This instruction corresponds exactly to the Full-Rate "norm" * instruction. * * KEYWORDS: norm, normalization * *************************************************************************/ Word16 norm_s(Word16 var1) { short swShiftCnt; Word32 L_var1; L_var1 = L_deposit_h(var1); swShiftCnt = norm_l(L_var1); #ifdef WMOPS_FX counter_fx.norm_s++; counter_fx.L_deposit_h--; counter_fx.norm_l--; #endif return (swShiftCnt); } /**************************************************************************** * * FUNCTION NAME: popOverflow * * PURPOSE: * * Pull the old overflow state from the "stack". Replace the current * overflow status with its predecessor. * * INPUTS: * * none * * * OUTPUTS: none * * RETURN VALUE: value of datum about the be lost (usually the * temporary saturation state) * * KEYWORDS: saturation, limit, overflow * ***************************************************************************/ int popOverflow(void) { int i; i = giOverflow; giOverflow = giOldOverflow; return (i); } /*************************************************************************** * * FUNCTION NAME: round32_16 * * PURPOSE: * * Round the 32 bit Word32 into a 16 bit shortword with saturation. * * INPUTS: * * L_var1 * 32 bit long signed integer (Word32) whose value * falls in the range * 0x8000 0000 <= L_var1 <= 0x7fff ffff. * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * Perform a two's complement round on the input Word32 with * saturation. * * This is equivalent to adding 0x0000 8000 to the input. The * result may overflow due to the add. If so, the result is * saturated. The 32 bit rounded number is then shifted down * 16 bits and returned as a Word16. * * * KEYWORDS: round * *************************************************************************/ Word16 round32_16(Word32 L_var1) { Word32 L_Prod; L_Prod = L_add(L_var1, 0x00008000L); /* round MSP */ #ifdef WMOPS_FX counter_fx.round++; counter_fx.L_add--; #endif return (extract_h(L_Prod)); } /**************************************************************************** * * FUNCTION NAME: set overflow * * PURPOSE: * * Clear the overflow flag * * INPUTS: * * none * * * OUTPUTS: global overflow flag is cleared * previous value stored in giOldOverflow * * RETURN VALUE: previous value of overflow * * * KEYWORDS: saturation, limit, overflow * ***************************************************************************/ int setOverflow(void) { giOldOverflow = giOverflow; giOverflow = 1; return (giOldOverflow); } /*************************************************************************** * * FUNCTION NAME: shift_r * * PURPOSE: * * Shift and round. Perform a shift right. After shifting, use * the last bit shifted out of the LSB to round the result up * or down. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * * IMPLEMENTATION: * * Shift and round. Perform a shift right. After shifting, use * the last bit shifted out of the LSB to round the result up * or down. * * If var2 is positive perform a arithmetic left shift * with saturation (see shl() above). * * If var2 is zero simply return var1. * * If var2 is negative perform a arithmetic right shift (shr) * of var1 by (-var2)+1. Add the LS bit of the result to var1 * shifted right (shr) by -var2. * * Note that there is no constraint on var2, so if var2 is * -0xffff 8000 then -var2 is 0x0000 8000, not 0x0000 7fff. * This is the reason the shl function is used. * * * KEYWORDS: * *************************************************************************/ Word16 shift_r(Word16 var1, Word16 var2) { Word16 swOut, swRnd; if (var2 >= 0) { swOut = shl(var1, var2); // OP_COUNT(-1); #ifdef WMOPS_FX counter_fx.shl--; #endif } else { /* right shift */ if (var2 < -15) { swOut = 0; } else { swRnd = shl(var1, (Word16)(var2 + 1)) & 0x1; swOut = add(shl(var1, var2), swRnd); #ifdef WMOPS_FX counter_fx.shl-=2; counter_fx.add--; #endif } } #ifdef WMOPS_FX counter_fx.shift_r++; #endif return (swOut); } /*************************************************************************** * * FUNCTION NAME: shl * * PURPOSE: * * Arithmetically shift the input left by var2. * * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * If Arithmetically shift the input left by var2. If var2 is * negative then an arithmetic shift right (shr) of var1 by * -var2 is performed. See description of shr for details. * When an arithmetic shift left is performed the var2 LS bits * are zero filled. * * The only exception is if the left shift causes an overflow * or underflow. In this case the LS bits are not modified. * The number returned is 0x8000 in the case of an underflow or * 0x7fff in the case of an overflow. * * The shl is equivalent to the Full-Rate GSM "<< n" operation. * Note that ANSI-C does not guarantee operation of the C ">>" * or "<<" operator for negative numbers - it is not specified * whether this shift is an arithmetic or logical shift. * * KEYWORDS: asl, arithmetic shift left, shift * *************************************************************************/ Word16 shl(Word16 var1, Word16 var2) { Word16 swOut; Word32 L_Out; if (var2 == 0 || var1 == 0) { swOut = var1; } else if (var2 < 0) { /* perform a right shift */ /*-----------------------*/ if (var2 <= -15) { if (var1 < 0) swOut = (Word16) 0xffff; else swOut = 0x0; } else { swOut = shr(var1, (Word16)(-var2)); #ifdef WMOPS_FX counter_fx.shr--; #endif } } else { /* var2 > 0 */ if (var2 >= 15) { /* saturate */ if (var1 > 0) swOut = SW_MAX; else swOut = SW_MIN; giOverflow = 1; } else { L_Out = (Word32) var1 *(1 << var2); swOut = (Word16) L_Out; /* copy low portion to swOut, overflow * could have hpnd */ if (swOut != L_Out) { /* overflow */ if (var1 > 0) swOut = SW_MAX; /* saturate */ else swOut = SW_MIN; /* saturate */ giOverflow = 1; } } } #ifdef WMOPS_FX counter_fx.shl++; #endif return (swOut); } /*************************************************************************** * * FUNCTION NAME: shr * * PURPOSE: * * Arithmetic shift right (or left). * Arithmetically shift the input right by var2. If var2 is * negative then an arithmetic shift left (shl) of var1 by * -var2 is performed. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * Arithmetically shift the input right by var2. This * operation maintains the sign of the input number. If var2 is * negative then an arithmetic shift left (shl) of var1 by * -var2 is performed. See description of shl for details. * * Equivalent to the Full-Rate GSM ">> n" operation. Note that * ANSI-C does not guarantee operation of the C ">>" or "<<" * operator for negative numbers. * * KEYWORDS: shift, arithmetic shift right, * *************************************************************************/ Word16 shr(Word16 var1, Word16 var2) { Word16 swMask, swOut; if (var2 == 0 || var1 == 0) swOut = var1; else if (var2 < 0) { /* perform an arithmetic left shift */ /*----------------------------------*/ if (var2 <= -15) { /* saturate */ if (var1 > 0) swOut = SW_MAX; else swOut = SW_MIN; giOverflow = 1; } else { swOut = shl(var1, (Word16)(-var2)); // OP_COUNT(-1); #ifdef WMOPS_FX counter_fx.shl--; #endif } } else { /* positive shift count */ /*----------------------*/ if (var2 >= 15) { if (var1 < 0) swOut = (Word16) 0xffff; else swOut = 0x0; } else { /* take care of sign extension */ /*-----------------------------*/ swMask = 0; if (var1 < 0) { swMask = ~swMask << (16 - var2); } var1 >>= var2; swOut = swMask | var1; } } #ifdef WMOPS_FX counter_fx.shr++; #endif return (swOut); } /*************************************************************************** * * FUNCTION NAME: sub * * PURPOSE: * * Perform the subtraction of the two 16 bit input variable with * saturation. * * INPUTS: * * var1 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. * var2 * 16 bit short signed integer (Word16) whose value * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. * * OUTPUTS: * * none * * RETURN VALUE: * * swOut * 16 bit short signed integer (Word16) whose value * falls in the range * 0xffff 8000 <= swOut <= 0x0000 7fff. * * IMPLEMENTATION: * * Perform the subtraction of the two 16 bit input variable with * saturation. * * swOut = var1 - var2 * * swOut is set to 0x7fff if the operation results in an * overflow. swOut is set to 0x8000 if the operation results * in an underflow. * * KEYWORDS: sub, subtraction * *************************************************************************/ Word16 sub(Word16 var1, Word16 var2) { Word32 L_diff; Word16 swOut; L_diff = (Word32) var1 - var2; swOut = saturate(L_diff); #ifdef WMOPS_FX counter_fx.sub++; #endif return (swOut); }