/*************************************************************************** tokenize.h Common definitions and macros for tokenizing definitions. Copyright Nicola Salmoria and the MAME Team. Visit http://mamedev.org for licensing and usage restrictions. ***************************************************************************/ #pragma once #ifndef __TOKENIZE_H__ #define __TOKENIZE_H__ /*************************************************************************** CONSTANTS ***************************************************************************/ /* tokens per item */ #define TOKENS_PER_PTR (1) #define TOKENS_PER_UINT32 (1) #define TOKENS_PER_UINT64 (8 / sizeof(FPTR)) #define TOKENS_PER_ATTOTIME (TOKENS_PER_UINT32 + TOKENS_PER_UINT64) /*************************************************************************** MACROS ***************************************************************************/ /* include this at the top of your union to get the standard fields */ #define TOKEN_COMMON_FIELDS \ FPTR i; \ const char * stringptr; \ const void * voidptr; \ const UINT8 * ui8ptr; \ const INT8 * i8ptr; \ const UINT16 * ui16ptr; \ const INT16 * i16ptr; \ const UINT32 * ui32ptr; \ const INT32 * i32ptr; \ const UINT64 * ui64ptr; \ const INT64 * i64ptr; \ /* ----- compile-time token generation macros ----- */ /* GCC and C99 compilers can use designated initializers for type safety */ #if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(_STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) #define TOKEN_VALUE(field,a) { .field = (a) } #else #define TOKEN_VALUE(field,a) { (FPTR)(a) } #endif /* token output primitives */ /* note that regardless of the endianness, UINT64s are packed LSW first */ #define TOKEN_PTR(field,p) TOKEN_VALUE(field, p) #define TOKEN_STRING(p) TOKEN_VALUE(stringptr, p) #define TOKEN_UINT32(a) TOKEN_VALUE(i, a) #ifdef PTR64 #define TOKEN_UINT64(a) TOKEN_VALUE(i, a) #else #define TOKEN_UINT64(a) TOKEN_VALUE(i, (UINT32)(a)), TOKEN_VALUE(i, (UINT32)((a) >> 32)) #endif /* mask a value to a fixed number of bits and then shift it */ #define SHIFT_AND_MASK32(val, bits, shift) (((UINT32)(val) & ((1 << (bits)) - 1)) << (shift)) #define SHIFT_AND_MASK64(val, bits, shift) (((UINT64)(val) & (((UINT64)1 << (bits)) - 1)) << (shift)) /* 32-bit integer packing */ #define TOKEN_UINT32_PACK1(val1, bits1) \ TOKEN_UINT32(SHIFT_AND_MASK32((val1), (bits1), 0)) #define TOKEN_UINT32_PACK2(val1, bits1, val2, bits2) \ TOKEN_UINT32(SHIFT_AND_MASK32((val1), (bits1), 0) | \ SHIFT_AND_MASK32((val2), (bits2), (bits1))) #define TOKEN_UINT32_PACK3(val1, bits1, val2, bits2, val3, bits3) \ TOKEN_UINT32(SHIFT_AND_MASK32((val1), (bits1), 0) | \ SHIFT_AND_MASK32((val2), (bits2), (bits1)) | \ SHIFT_AND_MASK32((val3), (bits3), (bits1)+(bits2))) #define TOKEN_UINT32_PACK4(val1, bits1, val2, bits2, val3, bits3, val4, bits4) \ TOKEN_UINT32(SHIFT_AND_MASK32((val1), (bits1), 0) | \ SHIFT_AND_MASK32((val2), (bits2), (bits1)) | \ SHIFT_AND_MASK32((val3), (bits3), (bits1)+(bits2)) | \ SHIFT_AND_MASK32((val4), (bits4), (bits1)+(bits2)+(bits3))) /* 64-bit integer packing */ #define TOKEN_UINT64_PACK1(val1, bits1) \ TOKEN_UINT64(SHIFT_AND_MASK64((val1), (bits1), 0)) #define TOKEN_UINT64_PACK2(val1, bits1, val2, bits2) \ TOKEN_UINT64(SHIFT_AND_MASK64((val1), (bits1), 0) | \ SHIFT_AND_MASK64((val2), (bits2), (bits1))) #define TOKEN_UINT64_PACK3(val1, bits1, val2, bits2, val3, bits3) \ TOKEN_UINT64(SHIFT_AND_MASK64((val1), (bits1), 0) | \ SHIFT_AND_MASK64((val2), (bits2), (bits1)) | \ SHIFT_AND_MASK64((val3), (bits3), (bits1)+(bits2))) #define TOKEN_UINT64_PACK4(val1, bits1, val2, bits2, val3, bits3, val4, bits4) \ TOKEN_UINT64(SHIFT_AND_MASK64((val1), (bits1), 0) | \ SHIFT_AND_MASK64((val2), (bits2), (bits1)) | \ SHIFT_AND_MASK64((val3), (bits3), (bits1)+(bits2)) | \ SHIFT_AND_MASK64((val4), (bits4), (bits1)+(bits2)+(bits3))) /* ----- run-time token extraction macros ----- */ /* token fetch and advance primitives */ #define TOKEN_GET_PTR(tp,field) (((tp)++)->field) #define TOKEN_GET_STRING(tp) (((tp)++)->stringptr) #define TOKEN_GET_UINT32(tp) (((tp)++)->i) #ifdef PTR64 #define TOKEN_EXTRACT_UINT64(tp,a) do { (a) = (tp)->i; (tp)++; } while (0) #else #define TOKEN_EXTRACT_UINT64(tp,a) do { (a) = (tp)[0].i | ((UINT64)(tp)[1].i << 32); (tp) += 2; } while (0) #endif /* token unfetch primitives */ #define TOKEN_UNGET_PTR(tp) ((tp)--) #define TOKEN_UNGET_STRING(tp) ((tp)--) #define TOKEN_UNGET_UINT32(tp) ((tp)--) #define TOKEN_UNGET_UINT64(tp) ((tp) -= 8 / sizeof(FPTR)) /* token skip primitives */ #define TOKEN_SKIP_PTR(tp) ((tp)++) #define TOKEN_SKIP_STRING(tp) ((tp)++) #define TOKEN_SKIP_UINT32(tp) ((tp)++) #define TOKEN_SKIP_UINT64(tp) ((tp) += 8 / sizeof(FPTR)) /* extract a value from a fixed number of bits; if bits is negative, treat it as a signed value */ #define UNSHIFT_AND_MASK32(src, val, bits, shift) do { \ if ((bits) < 0) \ (val) = token_sign_extend32((src) >> (shift), -(bits)); \ else \ (val) = token_zero_extend32((src) >> (shift), (bits)); \ } while (0) #define UNSHIFT_AND_MASK64(src, val, bits, shift) do { \ if ((bits) < 0) \ (val) = token_sign_extend64((src) >> (shift), -(bits)); \ else \ (val) = token_zero_extend64((src) >> (shift), (bits)); \ } while (0) /* cheesy inline absolute value */ #define TOKENABS(v) (((v) < 0) ? -(v) : (v)) /* 32-bit integer unpacking */ #define TOKEN_GET_UINT32_UNPACK1(tp, val1, bits1) do { \ UINT32 token32 = TOKEN_GET_UINT32(tp); \ UNSHIFT_AND_MASK32(token32, val1, (bits1), 0); \ } while (0) #define TOKEN_GET_UINT32_UNPACK2(tp, val1, bits1, val2, bits2) do { \ UINT32 token32 = TOKEN_GET_UINT32(tp); \ UINT8 shift = 0; \ UNSHIFT_AND_MASK32(token32, val1, (bits1), shift); shift += TOKENABS(bits1); \ UNSHIFT_AND_MASK32(token32, val2, (bits2), shift); \ } while (0) #define TOKEN_GET_UINT32_UNPACK3(tp, val1, bits1, val2, bits2, val3, bits3) do { \ UINT32 token32 = TOKEN_GET_UINT32(tp); \ UINT8 shift = 0; \ UNSHIFT_AND_MASK32(token32, val1, (bits1), shift); shift += TOKENABS(bits1); \ UNSHIFT_AND_MASK32(token32, val2, (bits2), shift); shift += TOKENABS(bits2); \ UNSHIFT_AND_MASK32(token32, val3, (bits3), shift); \ } while (0) #define TOKEN_GET_UINT32_UNPACK4(tp, val1, bits1, val2, bits2, val3, bits3, val4, bits4) do { \ UINT32 token32 = TOKEN_GET_UINT32(tp); \ UINT8 shift = 0; \ UNSHIFT_AND_MASK32(token32, val1, (bits1), shift); shift += TOKENABS(bits1); \ UNSHIFT_AND_MASK32(token32, val2, (bits2), shift); shift += TOKENABS(bits2); \ UNSHIFT_AND_MASK32(token32, val3, (bits3), shift); shift += TOKENABS(bits3); \ UNSHIFT_AND_MASK32(token32, val4, (bits4), shift); \ } while (0) /* 64-bit integer unpacking */ #define TOKEN_GET_UINT64_UNPACK1(tp, val1, bits1) do { \ UINT64 token64; \ TOKEN_EXTRACT_UINT64(tp, token64); \ UNSHIFT_AND_MASK64(token64, val1, (bits1), 0); \ } while (0) #define TOKEN_GET_UINT64_UNPACK2(tp, val1, bits1, val2, bits2) do { \ UINT64 token64; \ UINT8 shift = 0; \ TOKEN_EXTRACT_UINT64(tp, token64); \ UNSHIFT_AND_MASK64(token64, val1, (bits1), shift); shift += TOKENABS(bits1); \ UNSHIFT_AND_MASK64(token64, val2, (bits2), shift); \ } while (0) #define TOKEN_GET_UINT64_UNPACK3(tp, val1, bits1, val2, bits2, val3, bits3) do { \ UINT64 token64; \ UINT8 shift = 0; \ TOKEN_EXTRACT_UINT64(tp, token64); \ UNSHIFT_AND_MASK64(token64, val1, (bits1), shift); shift += TOKENABS(bits1); \ UNSHIFT_AND_MASK64(token64, val2, (bits2), shift); shift += TOKENABS(bits2); \ UNSHIFT_AND_MASK64(token64, val3, (bits3), shift); \ } while (0) #define TOKEN_GET_UINT64_UNPACK4(tp, val1, bits1, val2, bits2, val3, bits3, val4, bits4) do { \ UINT64 token64; \ UINT8 shift = 0; \ TOKEN_EXTRACT_UINT64(tp, token64); \ UNSHIFT_AND_MASK64(token64, val1, (bits1), shift); shift += TOKENABS(bits1); \ UNSHIFT_AND_MASK64(token64, val2, (bits2), shift); shift += TOKENABS(bits2); \ UNSHIFT_AND_MASK64(token64, val3, (bits3), shift); shift += TOKENABS(bits3); \ UNSHIFT_AND_MASK64(token64, val4, (bits4), shift); \ } while (0) /*************************************************************************** INLINE FUNCTIONS ***************************************************************************/ INLINE UINT32 token_zero_extend32(UINT32 val, UINT8 bits) { return val & (((UINT32)1 << bits) - 1); } INLINE INT32 token_sign_extend32(UINT32 val, UINT8 bits) { return (INT32)(val << (32 - bits)) >> (32 - bits); } INLINE UINT64 token_zero_extend64(UINT64 val, UINT8 bits) { return val & (((UINT64)1 << bits) - 1); } INLINE INT64 token_sign_extend64(UINT64 val, UINT8 bits) { return (INT64)(val << (64 - bits)) >> (64 - bits); } #endif