📄 rmmacros.h
字号:
static inline RMuint32 RMbeBufToUint24(const RMuint8 *buf){ return (((RMuint32) buf[0] << 16) + \ ((RMuint32) buf[1] << 8) + \ (RMuint32) buf[2]);}/** @param buf 6 bytes-long buffer. @return a RMuint48 from 6 bytes of a bigendian buffer*/static inline RMuint64 RMbeBufToUint48(const RMuint8 *buf){ return (((RMuint64) buf[0] << 40) + \ ((RMuint64) buf[1] << 32) + \ ((RMuint64) buf[2] << 24) + \ ((RMuint64) buf[3] << 16) + \ ((RMuint64) buf[4] << 8) + \ (RMuint64) buf[5]);}/** @param buf 3 bytes-long buffer. @return a RMuint24 from 4 bytes of a littleendian buffer*/static inline RMuint32 RMleBufToUint24(const RMuint8 *buf){ return (((RMuint32) buf[2] << 16) + \ ((RMuint32) buf[1] << 8) + \ (RMuint32) buf[0]);}/** Transform a 24 bits integer (stored in a RMuint32) into 3 bytes in big endian order @param val @param buf*/static inline void RMuint24ToBeBuf(RMuint32 val, RMuint8 *buf){ buf[0] = (RMuint8)(val >> 16); buf[1] = (RMuint8)(val >> 8); buf[2] = (RMuint8)val;}/** Transfroms a 24 bits integer into 2 bytes in little endian order @param val @param buf */static inline void RMuint24ToLeBuf(RMuint32 val, RMuint8 *buf){ buf[2] = (RMuint8)(val >> 16); buf[1] = (RMuint8)(val >> 8); buf[0] = (RMuint8)val;}/** @param buf 2 bytes-long buffer. @return a RMuint16 from 2 bytes of a bigendian buffer*/static inline RMuint16 RMbeBufToUint16(const RMuint8 *buf){ return (((RMuint16) buf[0] << 8) + \ (RMuint16) buf[1]);}/** @param buf 2 bytes-long buffer. @return a RMuint16 from 2 bytes of a littleendian buffer*/static inline RMuint16 RMleBufToUint16(RMuint8 *buf){ return (((RMuint16) buf[1] << 8) + \ (RMuint16) buf[0]);}/** Transfroms a 16 bits integer into 2 bytes in big endian order @param val @param buf */static inline void RMuint16ToBeBuf(RMuint16 val, RMuint8 *buf){ buf[0] = (RMuint8)(val >> 8); buf[1] = (RMuint8)val;}/** Transfroms a 16 bits integer into 2 bytes in little endian order @param val @param buf */static inline void RMuint16ToLeBuf(RMuint16 val, RMuint8 *buf){ buf[1] = (RMuint8)(val >> 8); buf[0] = (RMuint8)val;}// sometimes RMMemset is remapped on a complex operation. Rather use this to zero memory at location:#define clearmemory(location,size) \do { \ RMuint32 i; \ for (i=0;i<(RMuint32)(size);i++) *((RMuint8 *)(location)+i)=0; \} while (0)#define copymemory(dest, src, size) \do { \ RMuint32 i; \ for (i=0;i<(RMuint32)(size);i++) *((RMuint8 *)(dest)+i)=*((RMuint8 *)(src)+i); \} while (0)// integer division a * b / c#define RM64mult32div32(a,b,c) ( (RMuint64)(a) * (RMuint32)(b) / (RMuint32)(c) )// rounded integer division a * b / c#define RM64mult32divrnd32(a,b,c) ( ((RMuint64)(a) * (RMuint32)(b) + ((RMuint32)(c) >> 1)) / (RMuint32)(c) )/* Example RMALIGNTO(0x12345600,2) = 0x12345600 (prev 32bit word align) RMALIGNTO(0x12345601,2) = 0x12345600 (prev 32bit word align) RMALIGNTO(0x12345609,4) = 0x12345600 (prev 128bit word align) With the current implementation, the `Var' form is not different.*/#define RMALIGNTOVar(x,nbits) ((((RMuint32)(x))>>(nbits))<<(nbits))#define RMALIGNTO(x,nbits) RMALIGNTOVar(x,nbits)/* process x as a 32bit integer, align it to next 2^nbits byte boundary. Example RMALIGNTONEXT(0x12345600,2) = 0x12345600 (next 32bit word align) RMALIGNTONEXT(0x12345601,2) = 0x12345604 (next 32bit word align) RMALIGNTONEXT(0x12345601,4) = 0x12345610 (next 128bit word align)*/#define RMALIGNTONEXT(x,nbits) RMALIGNTO( (RMuint32)(x) + ((1<<(nbits))-1) , nbits )#define RMALIGNTONEXTVar(x,nbits) RMALIGNTOVar( (RMuint32)(x) + ((1<<(nbits))-1) , nbits )/* check if [p, p+size[ crosses a 2^nbits boundary. [0x803,0x803 + 0x20[ does cross a 2^5 boundary. [0x800,0x800 + 0x20[ does not cross a 2^5 boundary. [0x800,0x800 + 0[ does not cross a 2^5 boundary. The alternate with ((RMALIGNTONEXT(p+size,nbits)-RMALIGNTO(p,nbits))>>nbits)<=1 is too much calculus. */#define RMCROSSES(p,size,nbits) (RMALIGNTO(p,nbits)!=RMALIGNTO((RMuint32)(p)+(RMuint32)(size)-1,nbits))/// /** Returns the largest page aligned address <= x. @param x @return -ReturnValue-*/#define LOG2_RM_PAGE_SIZE 12#define RM_PAGE_SIZE (1<<LOG2_RM_PAGE_SIZE)#define RM_PAGE_ALIGN(x) RMALIGNTO(x,LOG2_RM_PAGE_SIZE)/// /** Classic variant of the above, not to be mismatched Typically: p=RMMalloc(size+RM_PAGE_SIZE-1); Give out RM_NEXT_PAGE_ALIGN(p). @param x @return -ReturnValue-*/#define RM_NEXT_PAGE_ALIGN(x) RMALIGNTONEXT(x,LOG2_RM_PAGE_SIZE)/* returns the number of the highest bit set log2 0xffffffff = 31 log2 0x1003 = 12 log2 0x1000 = 12 log2 0x1 = 0 log2 (nil) = -1 */#if RMCOMPILERID==RMCOMPILERID_MIPSEL_GCC && !defined(XOS_COMPACT)#define RMlog2(a) \({ \ RMint32 __hidden_rv; \ \ __asm__ __volatile__( \ "clz %0, %1\n" \ "neg %0, %0\n" \ "addu %0, 31\n" \ : "=r" (__hidden_rv) \ : "r" (a)); \ \ __hidden_rv; \})#elsestatic inline RMint32 RMlog2(RMuint32 a){ RMint32 rv = -1; while (a) { rv++; a >>= 1; } return rv;}#endif/* returns the number of the lowest bit set 0: -1 1: 0 4: 2 0x8C: 2 0x8000: 15 */static inline RMint32 RMlbs(RMuint32 a){ return RMlog2(a - (a & (a - 1)));}/* Is a power of two? 0: FALSE 1: TRUE 8: TRUE 0x1000: TRUE 0x1003: FALSE */static inline RMbool RMisPot(RMuint32 a) { return (!(a & (a - 1)) && a); // check if non-zero after removing least significant set bit}/* Count the number of set bits 0: 0 1: 1 8: 1 0x5A5A5A5A: 16 0xFFFFFFFF: 32 */static inline RMuint32 RMcountBits(RMuint32 x){ RMuint32 i; for (i = 0; x; i++) { x &= x - 1; // remove least significant set bit } return i;}/* only for 32bit; mips assembly small if log2im is immediate (resolved at compile time) */#define RMHASIMBIT(x,log2im) ((int)( ((RMuint32)(x)<<(31-(log2im))) )<0)#if (EM86XX_CHIP>=EM86XX_CHIPID_TANGO3)#define RM_DRAM_CONTROLLER_ID(x) NOTCOMPILABLE#else#define RM_DRAM_CONTROLLER_ID(x) (((x)>>28) - 1)#endif/*It divides two RMuint64 and returns quotient = a / b and reminder */static inline RMuint64 RM64div64rem64(RMuint64 a, RMuint64 b, RMuint64 *rem){ RMuint64 remainder = 0, quotient = 0; RMuint32 r32, d, b_low; RMint32 i; RMuint8 nbits = sizeof(RMuint64) * 8; if(rem) *rem = 0; if (! b) { /* RMDBGLOG((ENABLE, "RM64div64() DIVIDE BY 0!\n" )); */ return a; } if (a == b) { return 1; } if (((b >> 32) == 0) && ((a >> 32) == 0)) { /* Simplest Case, 32 bits division */ quotient = (RMuint64)((RMuint32)a / (RMuint32)b); if(rem) *rem = a - quotient * (RMuint32)b; return quotient; } if ((b >> 28) == 0) { /* Divisor is less than 28bit length */ b_low = (RMuint32)b; d = (RMuint32)(a >> 32); quotient = (d / b_low); for (i = 0; i < 8; i++) { r32 = d % b_low; d = (RMuint32)((r32 << 4) | ((a >> (7 - i) * 4) & 0xf)); quotient = (quotient << 4) | (d / b_low); } if(rem) *rem = d % b_low; return quotient; } /* Skip first zeros */ quotient = (((RMuint64)1) << (nbits - 1)); while (quotient && ((a & quotient) == 0)) { nbits--; quotient >>= 1; } /* Compute, simple 2-radix */ quotient = 0; for (i = (nbits - 1); i >= 0; i--) { remainder = remainder << 1 | ((a >> i) & 1); quotient <<= 1; if (remainder >= b) { remainder -= b; quotient |= 1; } } if(rem) *rem = remainder; return quotient;}static inline RMuint64 RM64div64(RMuint64 a, RMuint64 b){ return RM64div64rem64(a, b, (RMuint64 *)NULL );}/* DEPRECATED. See #5142. em2007apr17 This funtion divides two signed 64 bit integer, and writes the resulting integer quotient, the remainder and the first 64 bits of the fractional part into 3 64 bit integer, whose references are passed to the function. Each of the references can be NULL, if the result is not desired.*/static inline RMstatus RM64divfrac64rem64( RMint64 numer, /* enumerator */ RMint64 denom, /* denominator */ RMint64 *pQuot, /* result of integer division */ RMint64 *pRem, /* remainder of division */ RMint64 *pFrac) /* fractional part of division */{ RMint64 quot; RMint64 frac; RMint32 shift; RMint64 sign = 1; /* division by zero? */ if (!denom) return RM_ERROR; /* remove and remember sign */ if (numer < 0) { numer = -numer; sign = -sign; } if (denom < 0) { denom = -denom; sign = -sign; } /* align denom with numer */ quot = frac = 0; shift = 0; while ((denom < numer) && ((denom & 0x8000000000000000ll) == 0)) { denom <<= 1; shift++; } /* divide numer by denom */ while (1) { if (numer >= denom) { numer -= denom; quot |= 1; } if (! shift) break; denom >>= 1; quot <<= 1; shift--; } /* write results and check if fractional part is needed */ if (pQuot) *pQuot = quot * sign; if (pRem) *pRem = numer * sign; if (!pFrac) return RM_OK; /* keep dividing remainder for fractional part */ while (1) { if (numer & 0x8000000000000000ll) { if ( ((numer == (denom >> 1)) && (!(denom & 1))) || (numer > (denom >> 1))) { numer -= (denom >> 1); frac |= 1; } numer <<= 1; if (denom & 1) numer -= 1; } else { numer <<= 1; if (numer >= denom) { numer -= denom; frac |= 1; } } if (shift <= -63) break; frac <<= 1; shift--; } /* write fractional part and return */ *pFrac = frac * sign; return RM_OK;}RM_EXTERN_C_BLOCKEND#endif // __RMMACROS_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -