📄 rmmacros.h
字号:
/***************************************** Copyright (c) 2001-2003 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//** @file rmmacros.h @brief This file defines static inline function and macros. Macros may suffer name collision (in this case we use __hidden_rv for rv). Some macros have a good optimization in MIPS assembly. These optimizations are specific to 4KE (MIPS32 release 2) and little endian (tango2). The assembly optimizations are valid for mipsel-linux-gcc and sde-gcc, some of them only for little endian (e.g. tangox), and only for 32bit mode. Since constrained __asm__ syntax is only for gcc, it makes sense there to also use ({ ... }) http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_4.html#SEC62 (see RMALIGNTO/RMALIGNTOVar). All other cases implement static inline functions, or macros without ({ ... }), that are safe with Microsoft compiler. See test suite in llad_xtest/example.c @author Emmanuel Michon @date 2002-10-17*/#ifndef __RMMACROS_H__#define __RMMACROS_H__RM_EXTERN_C_BLOCKSTART/** Standard min macro.*/#define RMmin(x,y) (((x) < (y)) ? (x) : (y))/** Standard max macro.*/#define RMmax(x,y) (((x) < (y)) ? (y) : (x))/** Standard abs macro. */#define RMabs(x) (((x) >= 0) ? (x) : (-(x)))/// /** @param l 64 bit unsigned integer. @return the lowest 32 bits from a 64 bits long unsigned integer.*/#define RMuint32LSBfromRMuint64(l) ( (RMuint32) (l) )/// /** @param l 64 bit unsigned integer. @return the highest 32 bits from a 64 bits long unsigned integer.*/#define RMuint32MSBfromRMuint64(l) ( (RMuint32) ( ((l)>>32) & 0xffffffff ) )/// /** @param MSB high-order 32 bits. @param LSB low-order 32 bits. @return the 64 bits unsigned integer such that its 32 high-order bits are MSB and its 32 low-order bits are LSB.*/#define RMuint64from2RMuint32(MSB,LSB) ( (RMuint64) ( (((RMuint64)(MSB))<<32) + ((RMuint64)(LSB)) ) )/// /** @param l 32 bit unsigned integer. @param n 32 bit unsigned integer. @return 64 bits unsigned integer resulting from left shift of l.*/#define RMuint64fromRMuint32ShiftLeft(l,n) ( ((RMuint64)(l))<<(n) )/// /** @param l 64 bit unsigned integer. @param n 32 bit unsigned integer. @return 32 bits unsigned integer resulting from right shift of l.*/#define RMuint32fromRMuint64ShiftRight(l,n) ( (RMuint32) ((RMuint64)(l)>>(n)) )/** --------------- e.m. use this one! -------------------- Insert the bits 0..bits-1 from data starting at bit number `shift' in *ptr, replacing whatever was there. In the (rare) cases where bits or shift are variable arguments (not known at compile time), use RMinsShiftBitsVar. @param ptr: pointer to RMuint32 to be manipulated @param data: source data @param bits: number of bits to use from data @param shift: number of bits to shift data by to the left @return the new value of *ptr*/#define RMinsShiftBits(ptr, data, bits, shift) RMsetConsecutiveBits(ptr,shift,(shift)+(bits)-1,data)#define RMinsShiftBitsVar(ptr, data, bits, shift) RMsetConsecutiveBitsVar(ptr,shift,(shift)+(bits)-1,data)// e.m. deprecated --- use RMinsShiftBitsVar()#define RMsetConsecutiveBitsVar(target,begin,end,value) \ *(target)=( \ ( \ (*(target)) \ & \ (~( \ ( ( 1 << ((end)-(begin)+1) ) - 1 ) \ << \ (begin) \ ) \ ) \ ) \ | \ ( \ ( (RMuint32)(value) & ( ( 1 << ((end)-(begin)+1) ) - 1 ) ) \ << \ (begin) \ ) \ )#ifndef STR#define __STR(x) #x#define STR(x) __STR(x)#endif /* STR */// e.m. deprecated --- use RMinsShiftBits()#if RMCOMPILERID==RMCOMPILERID_MIPSEL_GCC & !defined(XOS_COMPACT)#define RMsetConsecutiveBits(target,begin,end,value) \do __asm__ __volatile__( \ "ins %0, %1, " STR(begin) ", (" STR(end) "-(" STR(begin) ")+1)" \ : "=r" (*(target)) /* may be same reg */ \ : "r" (value), "0" (*(target))); while (0)#define RMclearBits(ptr, bits, shift) \do __asm__ __volatile__( \ "ins %0, $0, " STR(shift) ", " STR(bits) \ : "=r" (*(ptr)) /* may be same reg */ \ : "0" (*(ptr))); while (0)#else#define RMsetConsecutiveBits RMsetConsecutiveBitsVar#define RMclearBits(ptr, bits, shift) RMsetConsecutiveBits(ptr,shift,(shift)+(bits)-1,0)#endif// e.m. deprecated --- use RMinsShiftBits()#define RMshiftBits(data, bits, shift) ( \ (((RMuint32)(data)) & ((1 << (bits)) - 1)) << (shift) )// e.m. deprecated --- use RMinsShiftBits()#define RMinsShiftBool(ptr, val, shift) RMinsShiftBits(ptr,(val)?1:0,1,shift)// e.m. deprecated --- use RMinsShiftBits()#define RMshiftBool(data, shift) ( \ (RMuint32)((data) ? (1 << (shift)) : 0) )/** --------------- e.m. use this one! -------------------- Bit manipulation operation. [RMunshiftBits(data, 3, 9) maps directly in mips to `ext $y, $x, 9, 3'] In the (rare) cases where bits or shift are variable arguments (not known at compile time), use RMinsShiftBitsVar. Use of __hidden_rv is to make very unlikely one of the provided variables has the same name. This is a trick, but Linux kernel headers do no better for this (see uaccess.h). @param data source data. @param bits: number of bits to use from data @param shift: number bits to shift data by to the right @return 'bits' bits from position 'shift' of 'data'. @remark for example, if 'data' is '00110100', RMunshiftBits(data, 3, 2) returns '101'*/#if RMCOMPILERID==RMCOMPILERID_MIPSEL_GCC & !defined(XOS_COMPACT)#define RMunshiftBits(data, bits, shift) \({ \ RMuint32 __hidden_rv; \ \ __asm__ __volatile__( \ "ext %0, %1, (" STR(shift) "), (" STR(bits)")" \ : "=r" (__hidden_rv) /* may be same reg */ \ : "r" (data)); \ \ __hidden_rv; \})#else#define RMunshiftBits RMunshiftBitsVar#endif#define RMunshiftBitsVar(data, bits, shift) ( \ (((RMuint32)(data)) >> (shift)) & ((1 << (bits)) - 1) )// e.m. deprecated --- use RMunshiftBits()#define RMunshiftBool(data, shift) RMunshiftBits(data, 1, shift)// e.m. deprecated --- use RMunshiftBits()#define RMgetConsecutiveBits(target,begin,end) RMunshiftBits(target, (end)-(begin)+1, begin)/* 0x10111213 -> 0x13121110 */#if RMCOMPILERID==RMCOMPILERID_MIPSEL_GCC & !defined(XOS_COMPACT)#define RMswapBytesUint32(a) \({ \ RMuint32 __hidden_rv; \ \ __asm__ __volatile__( \ "wsbh %0, %1\n" \ "rotr %0, %0, 16\n" \ : "=r" (__hidden_rv) /* may be same reg */ \ : "r" (a)); \ \ __hidden_rv; \})#elsestatic inline RMuint32 RMswapBytesUint32(RMuint32 a) { RMuint32 tmp=a; tmp = (((tmp >> 8) & 0x00ff00ff) | ((tmp & 0x00ff00ff) << 8)); tmp = ((tmp >> 16) | (tmp << 16)); return tmp; }#endif/* 0x10111213 -> 0xc8488808 */static inline RMuint32 RMswapBitsUint32(RMuint32 x){ RMuint32 y = 0x55555555; x = (((x >> 1) & y) | ((x & y) << 1)); y = 0x33333333; x = (((x >> 2) & y) | ((x & y) << 2)); y = 0x0f0f0f0f; x = (((x >> 4) & y) | ((x & y) << 4)); return RMswapBytesUint32(x);}/** @param buf 4 bytes-long buffer. @return a RMuint32 from 4 bytes of a bigendian buffer*/static inline RMuint32 RMbeBufToUint32(const RMuint8 *buf){#if RMCOMPILERID==RMCOMPILERID_MIPSEL_GCC & !defined(XOS_COMPACT) && RMENDIANNESS==RMLITTLEENDIAN RMuint32 rv; __asm__ __volatile__( "ulw %0, 0(%1)" : "=&r" (rv) /* may NOT be the same reg because ulw expands to two insn. Thanks Bertrand */ : "r" (buf)); return RMswapBytesUint32(rv);#else return (((RMuint32) buf[0] << 24) + \ ((RMuint32) buf[1] << 16) + \ ((RMuint32) buf[2] << 8) + \ (RMuint32) buf[3]);#endif}/** @param buf 4 bytes-long buffer. @return a RMuint32 from 4 bytes of a littleendian buffer*/static inline RMuint32 RMleBufToUint32(const RMuint8 *buf){#if RMCOMPILERID==RMCOMPILERID_MIPSEL_GCC & !defined(XOS_COMPACT) && RMENDIANNESS==RMLITTLEENDIAN RMuint32 rv; __asm__ __volatile__( "ulw %0, 0(%1)" : "=&r" (rv) /* may NOT be the same reg */ : "r" (buf)); return rv;#else return (((RMuint32) buf[3] << 24) + \ ((RMuint32) buf[2] << 16) + \ ((RMuint32) buf[1] << 8) + \ (RMuint32) buf[0]);#endif}/** @param buf 8 bytes-long buffer. @return a RMuint64 from 8 bytes of a littleendian buffer*/static inline RMuint64 RMbeBufToUint64(const RMuint8 *buf){#if RMCOMPILERID==RMCOMPILERID_MIPSEL_GCC & !defined(XOS_COMPACT) && RMENDIANNESS==RMLITTLEENDIAN RMuint32 rvhi,rvlo; __asm__ __volatile__( "ulw %0, 0(%2)\n" "ulw %1, 4(%2)\n" : "=&r" (rvhi), "=&r" (rvlo) : "r" (buf)); rvhi=RMswapBytesUint32(rvhi); rvlo=RMswapBytesUint32(rvlo); return ((RMuint64)rvhi<<32)+(RMuint64)rvlo;#else return (((RMuint64) buf[0] << 56) + \ ((RMuint64) buf[1] << 48) + \ ((RMuint64) buf[2] << 40) + \ ((RMuint64) buf[3] << 32) + \ ((RMuint64) buf[4] << 24) + \ ((RMuint64) buf[5] << 16) + \ ((RMuint64) buf[6] << 8) + \ (RMuint64) buf[7]);#endif}/** @param buf 8 bytes-long buffer. @return a RMuint64 from 8 bytes of a littleendian buffer*/static inline RMuint64 RMleBufToUint64(const RMuint8 *buf){#if RMCOMPILERID==RMCOMPILERID_MIPSEL_GCC & !defined(XOS_COMPACT) && RMENDIANNESS==RMLITTLEENDIAN RMuint32 rvhi,rvlo; __asm__ __volatile__( "ulw %0, 0(%2)\n" "ulw %1, 4(%2)\n" : "=&r" (rvlo), "=&r" (rvhi) : "r" (buf)); return ((RMuint64)rvhi<<32)+(RMuint64)rvlo;#else return (((RMuint64) buf[7] << 56) + \ ((RMuint64) buf[6] << 48) + \ ((RMuint64) buf[5] << 40) + \ ((RMuint64) buf[4] << 32) + \ ((RMuint64) buf[3] << 24) + \ ((RMuint64) buf[2] << 16) + \ ((RMuint64) buf[1] << 8) + \ (RMuint64) buf[0]);#endif}/** Transfroms a 32 bits integer into 4 bytes in big endian order @param val @param buf */static inline void RMuint32ToBeBuf(RMuint32 val, RMuint8 *buf){#if (defined WITH_32BIT_BUF_ALIGNMENT) && (RMPLATFORMID == RMPLATFORMID_JASPERMAMBO) /* Standalone ARM platform : optimized swapping - as WMAPro lib uses this intensively now... */ *(RMuint32 *) buf = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); #else /* default other platforms */ buf[0] = (RMuint8)(val >> 24) & 0xff; buf[1] = (RMuint8)(val >> 16) & 0xff; buf[2] = (RMuint8)(val >> 8) & 0xff; buf[3] = (RMuint8)val & 0xff;#endif /* WITH_32BIT_BUF_ALIGNMENT && RMPLATFORMID == */ }/** Transfroms a 32 bits integer int o 4 bytes in little endian order @param val @param buf */static inline void RMuint32ToLeBuf(RMuint32 val, RMuint8 *buf){#if (defined WITH_32BIT_BUF_ALIGNMENT) && (RMPLATFORMID == RMPLATFORMID_JASPERMAMBO) /* Standalone platform : optimized swapping - as WMAPro lib uses this intensively now... */ *(RMuint32 *) buf = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24); #else /* default other platforms */ buf[3] = (RMuint8)(val >> 24); buf[2] = (RMuint8)(val >> 16); buf[1] = (RMuint8)(val >> 8); buf[0] = (RMuint8)val;#endif /* WITH_32BIT_BUF_ALIGNMENT && RMPLATFORMID == */ }/** Transfroms a 64 bits integer int to 8 bytes in little endian order @param val @param buf */static inline void RMuint64ToLeBuf(RMuint64 val, RMuint8 *buf){ buf[7] = (RMuint8)(val >> 56); buf[6] = (RMuint8)(val >> 48); buf[5] = (RMuint8)(val >> 40); buf[4] = (RMuint8)(val >> 32); buf[3] = (RMuint8)(val >> 24); buf[2] = (RMuint8)(val >> 16); buf[1] = (RMuint8)(val >> 8); buf[0] = (RMuint8)val;}/** Transfroms a 64 bits integer int to 8 bytes in big endian order @param val @param buf */static inline void RMuint64ToBeBuf(RMuint64 val, RMuint8 *buf){ buf[0] = (RMuint8)(val >> 56) & 0xff; buf[1] = (RMuint8)(val >> 48) & 0xff; buf[2] = (RMuint8)(val >> 40) & 0xff; buf[3] = (RMuint8)(val >> 32) & 0xff; buf[4] = (RMuint8)(val >> 24) & 0xff; buf[5] = (RMuint8)(val >> 16) & 0xff; buf[6] = (RMuint8)(val >> 8) & 0xff; buf[7] = (RMuint8)val & 0xff;}/** @param buf 3 bytes-long buffer. @return a RMuint24 from 3 bytes of a bigendian buffer*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -