/* sqMemoryAccess.h -- memory accessors (and associated type definitions)
*
* Author: Ian.Piumarta@squeakland.org
*
* Last edited: 2007-06-10 19:16:03 by piumarta on vps2.piumarta.com
*/
/* Systematic use of the macros defined in this file within the
* Interpreter, ObjectMemory and plugins will permit all four
* combinations of 32/64-bit image and 32/64-bit host to compile and
* run correctly. (Code that uses explicit casts and/or integer
* constants in arithmetic on object pointers will invariably fail in
* at least one of the four possible combinations.)
*/
#ifndef __sqMemoryAccess_h
#define __sqMemoryAccess_h
#include "config.h"
#if defined(HAVE_INTERP_H)
# include "interp.h"
#else
# define SQ_VI_BYTES_PER_WORD 4 /* build a 32-bit VM */
# warning
# warning ***************************************************
# warning *
# warning * interp.h not found -- defaulting to a 32-bit VM
# warning *
# warning * update your image-side VM sources to the latest
# warning * version to avoid this message
# warning *
# warning ***************************************************
# warning
#endif
#if (SQ_VI_BYTES_PER_WORD == 4)
# define SQ_IMAGE32 1
#else
# define SQ_IMAGE64 1
#endif
#if (SIZEOF_VOID_P == 4)
# define SQ_HOST32 1
#elif (SIZEOF_VOID_P == 8)
# define SQ_HOST64 1
#else
# error host is neither 32- nor 64-bit?
#endif
#if defined(SQ_IMAGE32)
typedef int sqInt;
typedef unsigned int usqInt;
#elif defined(SQ_HOST64)
typedef long sqInt;
typedef unsigned long usqInt;
#else
# if (SIZEOF_LONG_LONG != 8)
# error long long integers are not 64-bits wide?
# endif
typedef long long sqInt;
typedef unsigned long long usqInt;
#endif
#if defined(SQ_HOST64) && defined(SQ_IMAGE32)
extern char *sqMemoryBase;
# define SQ_FAKE_MEMORY_OFFSET 16 // (1*1024*1024) /* nonzero to debug addr xlation */
#else
# define sqMemoryBase ((char *)0)
#endif
#ifdef USE_INLINE_MEMORY_ACCESSORS
/* Use static inline functions when the compiler produces efficient code for small accessors.
These are preferred because static type checking will prevent inadvertent confusion of pointers and oops. */
static inline sqInt byteAtPointer(char *ptr) { return (sqInt)(*((unsigned char *)ptr)); }
static inline sqInt byteAtPointerput(char *ptr, int val) { return (sqInt)(*((unsigned char *)ptr)= (unsigned char)val); }
static inline sqInt shortAtPointer(char *ptr) { return (sqInt)(*((short *)ptr)); }
static inline sqInt shortAtPointerput(char *ptr, int val) { return (sqInt)(*((short *)ptr)= (short)val); }
static inline sqInt intAtPointer(char *ptr) { return (sqInt)(*((unsigned int *)ptr)); }
static inline sqInt intAtPointerput(char *ptr, int val) { return (sqInt)(*((unsigned int *)ptr)= (int)val); }
static inline sqInt longAtPointer(char *ptr) { return (sqInt)(*((sqInt *)ptr)); }
static inline sqInt longAtPointerput(char *ptr, sqInt val) { return (sqInt)(*((sqInt *)ptr)= (sqInt)val); }
static inline sqInt oopAtPointer(char *ptr) { return (sqInt)(*((sqInt *)ptr)); }
static inline sqInt oopAtPointerput(char *ptr, sqInt val) { return (sqInt)(*((sqInt *)ptr)= (sqInt)val); }
static inline char *pointerForOop(usqInt oop) { return sqMemoryBase + oop; }
static inline sqInt oopForPointer(char *ptr) { return (sqInt)(ptr - sqMemoryBase); }
static inline sqInt byteAt(sqInt oop) { return byteAtPointer(pointerForOop(oop)); }
static inline sqInt byteAtput(sqInt oop, int val) { return byteAtPointerput(pointerForOop(oop), val); }
static inline sqInt shortAt(sqInt oop) { return shortAtPointer(pointerForOop(oop)); }
static inline sqInt shortAtput(sqInt oop, int val) { return shortAtPointerput(pointerForOop(oop), val); }
static inline sqInt intAt(sqInt oop) { return intAtPointer(pointerForOop(oop)); }
static inline sqInt intAtput(sqInt oop, int val) { return intAtPointerput(pointerForOop(oop), val); }
static inline sqInt longAt(sqInt oop) { return longAtPointer(pointerForOop(oop)); }
static inline sqInt longAtput(sqInt oop, sqInt val) { return longAtPointerput(pointerForOop(oop), val); }
static inline sqInt oopAt(sqInt oop) { return oopAtPointer(pointerForOop(oop)); }
static inline sqInt oopAtput(sqInt oop, sqInt val) { return oopAtPointerput(pointerForOop(oop), val); }
#else
/* Use macros when static inline functions aren't efficient. */
# define byteAtPointer(ptr) ((sqInt)(*((unsigned char *)(ptr))))
# define byteAtPointerput(ptr, val) ((sqInt)(*((unsigned char *)(ptr))= (unsigned char)(val)))
# define shortAtPointer(ptr) ((sqInt)(*((short *)(ptr))))
# define shortAtPointerput(ptr, val) ((sqInt)(*((short *)(ptr))= (short)(val)))
# define intAtPointer(ptr) ((sqInt)(*((unsigned int *)(ptr))))
# define intAtPointerput(ptr, val) ((sqInt)(*((unsigned int *)(ptr))= (int)(val)))
# define longAtPointer(ptr) ((sqInt)(*((sqInt *)(ptr))))
# define longAtPointerput(ptr, val) ((sqInt)(*((sqInt *)(ptr))= (sqInt)(val)))
# define oopAtPointer(ptr) (sqInt)(*((sqInt *)ptr))
# define oopAtPointerput(ptr, val) (sqInt)(*((sqInt *)ptr)= (sqInt)val)
# define pointerForOop(oop) ((char *)(sqMemoryBase + ((usqInt)(oop))))
# define oopForPointer(ptr) ((sqInt)(((char *)(ptr)) - (sqMemoryBase)))
# define byteAt(oop) byteAtPointer(pointerForOop(oop))
# define byteAtput(oop, val) byteAtPointerput(pointerForOop(oop), (val))
# define shortAt(oop) shortAtPointer(pointerForOop(oop))
# define shortAtput(oop, val) shortAtPointerput(pointerForOop(oop), (val))
# define longAt(oop) longAtPointer(pointerForOop(oop))
# define longAtput(oop, val) longAtPointerput(pointerForOop(oop), (val))
# define intAt(oop) intAtPointer(pointerForOop(oop))
# define intAtput(oop, val) intAtPointerput(pointerForOop(oop), (val))
# define oopAt(oop) oopAtPointer(pointerForOop(oop))
# define oopAtput(oop, val) oopAtPointerput(pointerForOop(oop), (val))
#endif
#define long32At intAt
#define long32Atput intAtput
/* platform-dependent float conversion macros */
/* Note: Second argument must be a variable name, not an expression! */
/* Note: Floats in image are always in PowerPC word order; change
these macros to swap words if necessary. This costs no extra and
obviates sometimes having to word-swap floats when reading an image.
*/
#if defined(DOUBLE_WORD_ALIGNMENT) || defined(DOUBLE_WORD_ORDER)
/* this is to allow strict aliasing assumption in the optimizer */
typedef union { double d; int i[sizeof(double) / sizeof(int)]; } _swapper;
# ifdef DOUBLE_WORD_ORDER
/* word-based copy with swapping for non-PowerPC order */
# define storeFloatAtPointerfrom(intPointerToFloat, floatVarName) \
*((int *)(intPointerToFloat) + 0) = ((_swapper *)(&floatVarName))->i[1]; \
*((int *)(intPointerToFloat) + 1) = ((_swapper *)(&floatVarName))->i[0];
# define fetchFloatAtPointerinto(intPointerToFloat, floatVarName) \
((_swapper *)(&floatVarName))->i[1] = *((int *)(intPointerToFloat) + 0); \
((_swapper *)(&floatVarName))->i[0] = *((int *)(intPointerToFloat) + 1);
# else /*!DOUBLE_WORD_ORDER*/
/* word-based copy for machines with alignment restrictions */
# define storeFloatAtPointerfrom(intPointerToFloat, floatVarName) \
*((int *)(intPointerToFloat) + 0) = ((_swapper *)(&floatVarName))->i[0]; \
*((int *)(intPointerToFloat) + 1) = ((_swapper *)(&floatVarName))->i[1];
# define fetchFloatAtPointerinto(intPointerToFloat, floatVarName) \
((_swapper *)(&floatVarName))->i[0] = *((int *)(intPointerToFloat) + 0); \
((_swapper *)(&floatVarName))->i[1] = *((int *)(intPointerToFloat) + 1);
# endif /*!DOUBLE_WORD_ORDER*/
#else /*!(DOUBLE_WORD_ORDER||DOUBLE_WORD_ALIGNMENT)*/
/* for machines that allow doubles to be on any word boundary */
# define storeFloatAtPointerfrom(i, floatVarName) \
*((double *) (i)) = (floatVarName);
# define fetchFloatAtPointerinto(i, floatVarName) \
(floatVarName) = *((double *) (i));
#endif
#define storeFloatAtfrom(i, floatVarName) storeFloatAtPointerfrom(pointerForOop(i), floatVarName)
#define fetchFloatAtinto(i, floatVarName) fetchFloatAtPointerinto(pointerForOop(i), floatVarName)
/* This doesn't belong here, but neither do 'self flag: ...'s belong in the image. */
static inline void flag(char *ignored)
{
(void)ignored;
}
#endif /* __sqMemoryAccess_h */
|