246 lines
8.6 KiB
C
246 lines
8.6 KiB
C
/***************************************************************************
|
|
|
|
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
|