/*
 ** Copyright 2003-2010, VisualOn, Inc.
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
/*******************************************************************************
	File:		basicop2.h

	Content:	Constants , Globals and Basic arithmetic operators.

*******************************************************************************/

#ifndef __BASIC_OP_H
#define __BASIC_OP_H

#include "typedef.h"

#define MAX_32 (Word32)0x7fffffffL
#define MIN_32 (Word32)0x80000000L

#define MAX_16 (Word16)0x7fff
#define MIN_16 (Word16)0x8000
#define ABS(a)	((a) >= 0) ? (a) : (-(a))

/* Short abs,           1   */
#define abs_s(x)       ((Word16)(((x) != MIN_16) ? (((x) >= 0) ? (x) : (-(x))) : MAX_16))

/* 16 bit var1 -> MSB,     2 */
#define L_deposit_h(x) (((Word32)(x)) << 16)


/* 16 bit var1 -> LSB,     2 */
#define L_deposit_l(x) ((Word32)(x))


/* Long abs,              3  */
#define L_abs(x) (((x) != MIN_32) ? (((x) >= 0) ? (x) : (-(x))) : MAX_32)


/* Short negate,        1   */
#define negate(var1) ((Word16)(((var1) == MIN_16) ? MAX_16 : (-(var1))))


/* Long negate,     2 */
#define L_negate(L_var1) (((L_var1) == (MIN_32)) ? (MAX_32) : (-(L_var1)))


#define MULHIGH(A,B) (int)(((Word64)(A)*(Word64)(B)) >> 32)
#define fixmul(a, b) (int)((((Word64)(a)*(Word64)(b)) >> 32) << 1)


#if  (SATRUATE_IS_INLINE)
__inline Word16 saturate(Word32 L_var1);
#else
Word16 saturate(Word32 L_var1);
#endif

/* Short shift left,    1   */
#if (SHL_IS_INLINE)
__inline Word16 shl (Word16 var1, Word16 var2);
#else
Word16 shl (Word16 var1, Word16 var2);
#endif

/* Short shift right,   1   */
#if (SHR_IS_INLINE)
__inline Word16 shr (Word16 var1, Word16 var2);
#else
Word16 shr (Word16 var1, Word16 var2);
#endif

#if (L_MULT_IS_INLINE)
__inline Word32 L_mult(Word16 var1, Word16 var2);
#else
Word32 L_mult(Word16 var1, Word16 var2);
#endif

/* Msu,  1  */
#if (L_MSU_IS_INLINE)
__inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2);
#else
Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2);
#endif

/* Long sub,        2 */
#if (L_SUB_IS_INLINE)
__inline Word32 L_sub(Word32 L_var1, Word32 L_var2);
#else
Word32 L_sub(Word32 L_var1, Word32 L_var2);
#endif

/* Long shift left, 2 */
#if (L_SHL_IS_INLINE)
__inline Word32 L_shl (Word32 L_var1, Word16 var2);
#else
Word32 L_shl (Word32 L_var1, Word16 var2);
#endif

/* Long shift right, 2*/
#if (L_SHR_IS_INLINE)
__inline Word32 L_shr (Word32 L_var1, Word16 var2);
#else
Word32 L_shr (Word32 L_var1, Word16 var2);
#endif

/* Short add,           1   */
#if (ADD_IS_INLINE)
__inline Word16 add (Word16 var1, Word16 var2);
#else
Word16 add (Word16 var1, Word16 var2);
#endif

/* Short sub,           1   */
#if (SUB_IS_INLINE)
__inline Word16 sub(Word16 var1, Word16 var2);
#else
Word16 sub(Word16 var1, Word16 var2);
#endif

/* Short division,       18  */
#if (DIV_S_IS_INLINE)
__inline Word16 div_s (Word16 var1, Word16 var2);
#else
Word16 div_s (Word16 var1, Word16 var2);
#endif

/* Short mult,          1   */
#if (MULT_IS_INLINE)
__inline Word16 mult (Word16 var1, Word16 var2);
#else
Word16 mult (Word16 var1, Word16 var2);
#endif

/* Short norm,           15  */
#if (NORM_S_IS_INLINE)
__inline Word16 norm_s (Word16 var1);
#else
Word16 norm_s (Word16 var1);
#endif

/* Long norm,            30  */
#if (NORM_L_IS_INLINE)
__inline Word16 norm_l (Word32 L_var1);
#else
Word16 norm_l (Word32 L_var1);
#endif

/* Round,               1   */
#if (ROUND_IS_INLINE)
__inline Word16 round16(Word32 L_var1);
#else
Word16 round16(Word32 L_var1);
#endif

/* Mac,  1  */
#if (L_MAC_IS_INLINE)
__inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2);
#else
Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2);
#endif

#if (L_ADD_IS_INLINE)
__inline Word32 L_add (Word32 L_var1, Word32 L_var2);
#else
Word32 L_add (Word32 L_var1, Word32 L_var2);
#endif

/* Extract high,        1   */
#if (EXTRACT_H_IS_INLINE)
__inline Word16 extract_h (Word32 L_var1);
#else
Word16 extract_h (Word32 L_var1);
#endif

/* Extract low,         1   */
#if (EXTRACT_L_IS_INLINE)
__inline Word16 extract_l(Word32 L_var1);
#else
Word16 extract_l(Word32 L_var1);
#endif

/* Mult with round, 2 */
#if (MULT_R_IS_INLINE)
__inline Word16 mult_r(Word16 var1, Word16 var2);
#else
Word16 mult_r(Word16 var1, Word16 var2);
#endif

/* Shift right with round, 2           */
#if (SHR_R_IS_INLINE)
__inline Word16 shr_r (Word16 var1, Word16 var2);
#else
Word16 shr_r (Word16 var1, Word16 var2);
#endif

/* Mac with rounding,2 */
#if (MAC_R_IS_INLINE)
__inline Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2);
#else
Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2);
#endif

/* Msu with rounding,2 */
#if (MSU_R_IS_INLINE)
__inline Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2);
#else
Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2);
#endif

/* Long shift right with round,  3             */
#if (L_SHR_R_IS_INLINE)
__inline Word32 L_shr_r (Word32 L_var1, Word16 var2);
#else
Word32 L_shr_r (Word32 L_var1, Word16 var2);
#endif

#if ARMV4_INASM
__inline Word32 ASM_L_shr(Word32 L_var1, Word16 var2)
{
	return L_var1 >> var2;
}

__inline Word32 ASM_L_shl(Word32 L_var1, Word16 var2)
{
	Word32 result;
	asm (
		"MOV	%[result], %[L_var1], ASL %[var2] \n"
		"TEQ	%[L_var1], %[result], ASR %[var2]\n"
		"EORNE  %[result], %[mask], %[L_var1], ASR #31\n"
		:[result]"=&r"(result)
		:[L_var1]"r"(L_var1), [var2]"r"(var2), [mask]"r"(0x7fffffff)
		);
	return result;
}

__inline Word32 ASM_shr(Word32 L_var1, Word16 var2)
{
	Word32 result;
	asm (
		"CMP	%[var2], #15\n"
		"MOVLT	%[result], %[L_var1], ASR %[var2]\n"
		"MOVGE	%[result], %[L_var1], ASR #15\n"
		:[result]"=r"(result)
		:[L_var1]"r"(L_var1), [var2]"r"(var2)
		);
	return result;
}

__inline Word32 ASM_shl(Word32 L_var1, Word16 var2)
{
#if ARMV6_SAT
	Word32 result;
	asm (
		"CMP	%[var2], #16\n"
		"MOVLT  %[result], %[L_var1], ASL %[var2]\n"
		"MOVGE  %[result], %[L_var1], ASL #16\n"
		"SSAT   %[result], #16, %[result]\n"
		:[result]"=r"(result)
		:[L_var1]"r"(L_var1), [var2]"r"(var2)
		);
	return result;
#else
	Word32 result;
	Word32 tmp;
	asm (
		"CMP	%[var2], #16\n"
		"MOVLT  %[result], %[L_var1], ASL %[var2]\n"
		"MOVGE  %[result], %[L_var1], ASL #16\n"
        "MOV    %[tmp], %[result], ASR #15\n"
        "TEQ    %[tmp], %[result], ASR #31 \n"
        "EORNE  %[result], %[mask], %[result],ASR #31"
		:[result]"=&r"(result), [tmp]"=&r"(tmp)
		:[L_var1]"r"(L_var1), [var2]"r"(var2), [mask]"r"(0x7fff)
		);
	return result;
#endif
}
#endif

/*___________________________________________________________________________
 |                                                                           |
 |   definitions for inline basic arithmetic operators                       |
 |___________________________________________________________________________|
*/
#if (SATRUATE_IS_INLINE)
__inline Word16 saturate(Word32 L_var1)
{
#if ARMV6_SAT
    Word16 result;
	asm (
		"SSAT %[result], #16, %[L_var1]"
		: [result]"=r"(result)
		: [L_var1]"r"(L_var1)
		);
	return result;
#elif ARMV5TE_SAT
	Word16 result;
	Word32 tmp;
	asm volatile (
		"MOV	%[tmp], %[L_var1],ASR#15\n"
		"TEQ	%[tmp], %[L_var1],ASR#31\n"
		"EORNE	%[result], %[mask],%[L_var1],ASR#31\n"
		"MOVEQ	%[result], %[L_var1]\n"
		:[result]"=&r"(result), [tmp]"=&r"(tmp)
		:[L_var1]"r"(L_var1), [mask]"r"(0x7fff)
	);

	return result;
#else
    Word16 var_out;

    //var_out = (L_var1 > (Word32)0X00007fffL) ? (MAX_16) : ((L_var1 < (Word32)0xffff8000L) ? (MIN_16) : ((Word16)L_var1));

    if (L_var1 > 0X00007fffL)
    {
        var_out = MAX_16;
    }
    else if (L_var1 < (Word32) 0xffff8000L)
    {
        var_out = MIN_16;
    }
    else
    {
        var_out = extract_l(L_var1);
    }

    return (var_out);
#endif
}
#endif

/* Short shift left,    1   */
#if (SHL_IS_INLINE)
__inline Word16 shl (Word16 var1, Word16 var2)
{
#if ARMV5TE_SHL
	if(var2>=0)
	{
		return ASM_shl( var1, var2);
	}
	else
	{
		return ASM_shr( var1, -var2);
	}
#else
    Word16 var_out;
    Word32 result;

    if (var2 < 0)
    {
        var_out = shr (var1, (Word16)-var2);
    }
    else
    {
        result = (Word32) var1 *((Word32) 1 << var2);

        if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))
        {
            var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);
        }
        else
        {
            var_out = extract_l(result);
        }
    }
    return (var_out);
#endif
}
#endif

/* Short shift right,   1   */
#if (SHR_IS_INLINE)
__inline Word16 shr (Word16 var1, Word16 var2)
{
#if ARMV5TE_SHR
	if(var2>=0)
	{
		return  ASM_shr( var1, var2);
	}
	else
	{
		return  ASM_shl( var1, -var2);
	}
#else
    Word16 var_out;

    if (var2 < 0)
    {
        var_out = shl (var1, (Word16)-var2);
    }
    else
    {
        if (var2 >= 15)
        {
            var_out = (Word16)((var1 < 0) ? -1 : 0);
        }
        else
        {
            if (var1 < 0)
            {
                var_out = (Word16)(~((~var1) >> var2));
            }
            else
            {
                var_out = (Word16)(var1 >> var2);
            }
        }
    }

    return (var_out);
#endif
}
#endif


#if (L_MULT_IS_INLINE)
__inline Word32 L_mult(Word16 var1, Word16 var2)
{
#if ARMV5TE_L_MULT
	Word32 result;
	asm (
		"SMULBB %[result], %[var1], %[var2] \n"
		"QADD %[result], %[result], %[result] \n"
		:[result]"=r"(result)
		:[var1]"r"(var1), [var2]"r"(var2)
		);
	return result;
#else
    Word32 L_var_out;

    L_var_out = (Word32) var1 *(Word32) var2;

    if (L_var_out != (Word32) 0x40000000L)
    {
        L_var_out <<= 1;
    }
    else
    {
        L_var_out = MAX_32;
    }
    return (L_var_out);
#endif
}
#endif

#if (L_MSU_IS_INLINE)
__inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)
{
#if ARMV5TE_L_MSU
	Word32 result;
	asm (
		"SMULBB %[result], %[var1], %[var2] \n"
		"QDSUB %[result], %[L_var3], %[result]\n"
		:[result]"=&r"(result)
		:[L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2)
		);
	return result;
#else
    Word32 L_var_out;
    Word32 L_product;

    L_product = L_mult(var1, var2);
    L_var_out = L_sub(L_var3, L_product);
    return (L_var_out);
#endif
}
#endif

#if (L_SUB_IS_INLINE)
__inline Word32 L_sub(Word32 L_var1, Word32 L_var2)
{
#if ARMV5TE_L_SUB
	Word32 result;
	asm (
		"QSUB %[result], %[L_var1], %[L_var2]\n"
		:[result]"=r"(result)
		:[L_var1]"r"(L_var1), [L_var2]"r"(L_var2)
		);
	return result;
#else
    Word32 L_var_out;

    L_var_out = L_var1 - L_var2;

    if (((L_var1 ^ L_var2) & MIN_32) != 0)
    {
        if ((L_var_out ^ L_var1) & MIN_32)
        {
            L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
        }
    }

    return (L_var_out);
#endif
}
#endif

#if (L_SHL_IS_INLINE)
__inline Word32 L_shl(Word32 L_var1, Word16 var2)
{
#if ARMV5TE_L_SHL
    if(var2>=0)
    {
        return  ASM_L_shl( L_var1, var2);
    }
    else
    {
        return  ASM_L_shr( L_var1, -var2);
    }
#else
    if (var2 <= 0)
    {
        L_var1 = L_shr(L_var1, (Word16)-var2);
    }
    else
    {
        for (; var2 > 0; var2--)
        {
            if (L_var1 > (Word32) 0X3fffffffL)
            {
                return MAX_32;
            }
            else
            {
                if (L_var1 < (Word32) 0xc0000000L)
                {
                    return MIN_32;
                }
            }
            L_var1 <<= 1;
        }
    }
    return (L_var1);
#endif
}
#endif

#if (L_SHR_IS_INLINE)
__inline Word32 L_shr (Word32 L_var1, Word16 var2)
{
#if ARMV5TE_L_SHR
	if(var2>=0)
	{
		return ASM_L_shr( L_var1, var2);
	}
	else
	{
		return ASM_L_shl( L_var1, -var2);
	}
#else
    Word32 L_var_out;

    if (var2 < 0)
    {
        L_var_out = L_shl (L_var1, (Word16)-var2);
    }
    else
    {
        if (var2 >= 31)
        {
            L_var_out = (L_var1 < 0L) ? -1 : 0;
        }
        else
        {
            if (L_var1 < 0)
            {
                L_var_out = ~((~L_var1) >> var2);
            }
            else
            {
                L_var_out = L_var1 >> var2;
            }
        }
    }
    return (L_var_out);
#endif
}
#endif

/* Short add,           1   */
#if (ADD_IS_INLINE)
__inline Word16 add (Word16 var1, Word16 var2)
{
#if ARMV5TE_ADD
	Word32 result;
	Word32 tmp;
	asm (
		"ADD  %[result], %[var1], %[var2] \n"
		"MOV  %[tmp], %[result], ASR #15 \n"
		"TEQ  %[tmp], %[result], ASR #31 \n"
		"EORNE %[result], %[mask], %[result], ASR #31"
		:[result]"=&r"(result), [tmp]"=&r"(tmp)
		:[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff)
		);
	return result;
#else
    Word16 var_out;
    Word32 L_sum;

    L_sum = (Word32) var1 + var2;
    var_out = saturate(L_sum);

    return (var_out);
#endif
}
#endif

/* Short sub,           1   */
#if (SUB_IS_INLINE)
__inline Word16 sub(Word16 var1, Word16 var2)
{
#if ARMV5TE_SUB
	Word32 result;
	Word32 tmp;
	asm (
		"SUB   %[result], %[var1], %[var2] \n"
		"MOV   %[tmp], %[var1], ASR #15 \n"
		"TEQ   %[tmp], %[var1], ASR #31 \n"
		"EORNE %[result], %[mask], %[result], ASR #31 \n"
		:[result]"=&r"(result), [tmp]"=&r"(tmp)
		:[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff)
		);
	return result;
#else
    Word16 var_out;
    Word32 L_diff;

    L_diff = (Word32) var1 - var2;
    var_out = saturate(L_diff);

    return (var_out);
#endif
}
#endif

/* Short division,       18  */
#if (DIV_S_IS_INLINE)
__inline Word16 div_s (Word16 var1, Word16 var2)
{
    Word16 var_out = 0;
    Word16 iteration;
    Word32 L_num;
    Word32 L_denom;

    var_out = MAX_16;
    if (var1!= var2)//var1!= var2
    {
    	var_out = 0;
    	L_num = (Word32) var1;

    	L_denom = (Word32) var2;

		//return (L_num<<15)/var2;

    	for (iteration = 0; iteration < 15; iteration++)
    	{
    		var_out <<= 1;
    		L_num <<= 1;

    		if (L_num >= L_denom)
    		{
    			L_num -= L_denom;
    			var_out++;
    		}
    	}
    }
    return (var_out);
}
#endif

/* Short mult,          1   */
#if (MULT_IS_INLINE)
__inline Word16 mult (Word16 var1, Word16 var2)
{
#if ARMV5TE_MULT && ARMV6_SAT
	Word32 result;
	asm (
		"SMULBB %[result], %[var1], %[var2] \n"
		"SSAT   %[result], #16, %[result], ASR #15 \n"
		:[result]"=r"(result)
		:[var1]"r"(var1), [var2]"r"(var2)
		);
	return result;
#elif ARMV5TE_MULT
	Word32 result, tmp;
	asm (
		"SMULBB %[tmp], %[var1], %[var2] \n"
		"MOV	%[result], %[tmp], ASR #15\n"
		"MOV	%[tmp], %[result], ASR #15\n"
		"TEQ	%[tmp], %[result], ASR #31\n"
		"EORNE  %[result], %[mask], %[result], ASR #31 \n"
		:[result]"=&r"(result), [tmp]"=&r"(tmp)
		:[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff)
		);
	return result;
#else
    Word16 var_out;
    Word32 L_product;

    L_product = (Word32) var1 *(Word32) var2;
    L_product = (L_product & (Word32) 0xffff8000L) >> 15;
    if (L_product & (Word32) 0x00010000L)
        L_product = L_product | (Word32) 0xffff0000L;
    var_out = saturate(L_product);

    return (var_out);
#endif
}
#endif


/* Short norm,           15  */
#if (NORM_S_IS_INLINE)
__inline Word16 norm_s (Word16 var1)
{
#if ARMV5TE_NORM_S
	Word16 result;
	Word32 tmp;
	asm (
		"RSBS  %[tmp], %[var1], #0 \n"
		"CLZLT %[result], %[var1]\n"
		"CLZGT %[result], %[tmp]\n"
		"SUBNE %[result], %[result], #17\n"
		"MOVEQ %[result], #0\n"
		"CMP   %[var1], #-1\n"
		"MOVEQ %[result], #15\n"
		:[result]"=&r"(result), [tmp]"=&r"(tmp)
		:[var1]"r"(var1)
		);
	return result;
#else
    Word16 var_out;

    if (var1 == 0)
    {
        var_out = 0;
    }
    else
    {
        if (var1 == -1)
        {
            var_out = 15;
        }
        else
        {
            if (var1 < 0)
            {
                var1 = (Word16)~var1;
            }
            for (var_out = 0; var1 < 0x4000; var_out++)
            {
                var1 <<= 1;
            }
        }
    }
    return (var_out);
#endif
}
#endif

/* Long norm,            30  */
#if (NORM_L_IS_INLINE)
__inline Word16 norm_l (Word32 L_var1)
{
#if ARMV5TE_NORM_L
	Word16 result;
	asm volatile(
		"CMP    %[L_var1], #0\n"
		"CLZNE  %[result], %[L_var1]\n"
		"SUBNE  %[result], %[result], #1\n"
		"MOVEQ  %[result], #0\n"
		:[result]"=r"(result)
		:[L_var1]"r"(L_var1)
		);
	return result;
#else
    //Word16 var_out;

    //if (L_var1 == 0)
    //{
    //    var_out = 0;
    //}
    //else
    //{
    //    if (L_var1 == (Word32) 0xffffffffL)
    //    {
    //        var_out = 31;
    //    }
    //    else
    //    {
    //        if (L_var1 < 0)
    //        {
    //            L_var1 = ~L_var1;
    //        }
    //        for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)
    //        {
    //            L_var1 <<= 1;
    //        }
    //    }
    //}
    //return (var_out);
  Word16 a16;
  Word16 r = 0 ;


  if ( L_var1 < 0 ) {
    L_var1 = ~L_var1;
  }

  if (0 == (L_var1 & 0x7fff8000)) {
    a16 = extract_l(L_var1);
    r += 16;

    if (0 == (a16 & 0x7f80)) {
      r += 8;

      if (0 == (a16 & 0x0078)) {
        r += 4;

        if (0 == (a16 & 0x0006)) {
          r += 2;

          if (0 == (a16 & 0x0001)) {
            r += 1;
          }
        }
        else {

          if (0 == (a16 & 0x0004)) {
            r += 1;
          }
        }
      }
      else {

        if (0 == (a16 & 0x0060)) {
          r += 2;

          if (0 == (a16 & 0x0010)) {
            r += 1;
          }
        }
        else {

          if (0 == (a16 & 0x0040)) {
            r += 1;
          }
        }
      }
    }
    else {

      if (0 == (a16 & 0x7800)) {
        r += 4;

        if (0 == (a16 & 0x0600)) {
          r += 2;

          if (0 == (a16 & 0x0100)) {
            r += 1;
          }
        }
        else {

          if (0 == (a16 & 0x0400)) {
            r += 1;
          }
        }
      }
      else {

        if (0 == (a16 & 0x6000)) {
          r += 2;

          if (0 == (a16 & 0x1000)) {
            r += 1;
          }
        }
        else {

          if (0 == (a16 & 0x4000)) {
            r += 1;
          }
        }
      }
    }
  }
  else {
    a16 = extract_h(L_var1);

    if (0 == (a16 & 0x7f80)) {
      r += 8;

      if (0 == (a16 & 0x0078)) {
        r += 4 ;

        if (0 == (a16 & 0x0006)) {
          r += 2;

          if (0 == (a16 & 0x0001)) {
            r += 1;
          }
        }
        else {

          if (0 == (a16 & 0x0004)) {
            r += 1;
          }
        }
      }
      else {

        if (0 == (a16 & 0x0060)) {
          r += 2;

          if (0 == (a16 & 0x0010)) {
            r += 1;
          }
        }
        else {

          if (0 == (a16 & 0x0040)) {
            r += 1;
          }
        }
      }
    }
    else {

      if (0 == (a16 & 0x7800)) {
        r += 4;

        if (0 == (a16 & 0x0600)) {
          r += 2;

          if (0 == (a16 & 0x0100)) {
            r += 1;
          }
        }
        else {

          if (0 == (a16 & 0x0400)) {
            r += 1;
          }
        }
      }
      else {

        if (0 == (a16 & 0x6000)) {
          r += 2;

          if (0 == (a16 & 0x1000)) {
            r += 1;
          }
        }
        else {

          if (0 == (a16 & 0x4000)) {
            return 1;
          }
        }
      }
    }
  }

  return r ;
#endif
}
#endif

/* Round,               1   */
#if (ROUND_IS_INLINE)
__inline Word16 round16(Word32 L_var1)
{
#if ARMV5TE_ROUND
	Word16 result;
	asm (
		"QADD  %[result], %[L_var1], %[bias]\n"
		"MOV   %[result], %[result], ASR #16 \n"
		:[result]"=r"(result)
		:[L_var1]"r"(L_var1), [bias]"r"(0x8000)
		);
	return result;
#else
    Word16 var_out;
    Word32 L_rounded;

    L_rounded = L_add (L_var1, (Word32) 0x00008000L);
    var_out = extract_h (L_rounded);
    return (var_out);
#endif
}
#endif

/* Mac,  1  */
#if (L_MAC_IS_INLINE)
__inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)
{
#if ARMV5TE_L_MAC
	Word32 result;
	asm (
		"SMULBB %[result], %[var1], %[var2]\n"
		"QDADD  %[result], %[L_var3], %[result]\n"
		:[result]"=&r"(result)
		: [L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2)
		);
	return result;
#else
    Word32 L_var_out;
    Word32 L_product;

    L_product = L_mult(var1, var2);
    L_var_out = L_add (L_var3, L_product);
    return (L_var_out);
#endif
}
#endif

#if (L_ADD_IS_INLINE)
__inline Word32 L_add (Word32 L_var1, Word32 L_var2)
{
#if ARMV5TE_L_ADD
	Word32 result;
	asm (
		"QADD %[result], %[L_var1], %[L_var2]\n"
		:[result]"=r"(result)
		:[L_var1]"r"(L_var1), [L_var2]"r"(L_var2)
		);
	return result;
#else
    Word32 L_var_out;

    L_var_out = L_var1 + L_var2;
    if (((L_var1 ^ L_var2) & MIN_32) == 0)
    {
        if ((L_var_out ^ L_var1) & MIN_32)
        {
            L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
        }
    }
    return (L_var_out);
#endif
}
#endif



#if (MULT_R_IS_INLINE)
__inline Word16 mult_r (Word16 var1, Word16 var2)
{
    Word16 var_out;
    Word32 L_product_arr;

    L_product_arr = (Word32)var1 *(Word32)var2;       /* product */
    L_product_arr += (Word32)0x00004000L;      /* round */
    L_product_arr >>= 15;       /* shift */

    var_out = saturate(L_product_arr);

    return (var_out);
}
#endif

#if (SHR_R_IS_INLINE)
__inline Word16 shr_r (Word16 var1, Word16 var2)
{
    Word16 var_out;

    if (var2 > 15)
    {
        var_out = 0;
    }
    else
    {
        var_out = shr(var1, var2);

        if (var2 > 0)
        {
            if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
            {
                var_out++;
            }
        }
    }

    return (var_out);
}
#endif

#if (MAC_R_IS_INLINE)
__inline Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2)
{
    Word16 var_out;

    L_var3 = L_mac (L_var3, var1, var2);
    var_out = (Word16)((L_var3 + 0x8000L) >> 16);

    return (var_out);
}
#endif

#if (MSU_R_IS_INLINE)
__inline Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2)
{
    Word16 var_out;

    L_var3 = L_msu (L_var3, var1, var2);
    var_out = (Word16)((L_var3 + 0x8000L) >> 16);

    return (var_out);
}
#endif

#if (L_SHR_R_IS_INLINE)
__inline Word32 L_shr_r (Word32 L_var1, Word16 var2)
{
    Word32 L_var_out;

    if (var2 > 31)
    {
        L_var_out = 0;
    }
    else
    {
        L_var_out = L_shr(L_var1, var2);

        if (var2 > 0)
        {
            if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
            {
                L_var_out++;
            }
        }
    }

    return (L_var_out);
}
#endif

#if (EXTRACT_H_IS_INLINE)
__inline Word16 extract_h (Word32 L_var1)
{
    Word16 var_out;

    var_out = (Word16) (L_var1 >> 16);

    return (var_out);
}
#endif

#if (EXTRACT_L_IS_INLINE)
__inline Word16 extract_l(Word32 L_var1)
{
	return (Word16) L_var1;
}
#endif

#endif
