/*
#ident "@(#)smail/src:RELEASE-3_2_0_121:smailarch.h,v 1.3 2004/07/24 16:17:24 woods Exp"
*/
/*
* Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
* Copyright (C) 1992 Ronald S. Karr
*
* See the file COPYING, distributed with smail, for restriction
* and warranty information.
*/
/*
* arch:
* deal with hardware/architectural issues
*
* Architecure-independent aspects of architecture configuration.
* To specify a new architecture, create a file under the smail
* conf/arch directory, and refer to the new architecture in the
* conf/EDIT_ME file.
*/
#ifdef CHAR_BIT /* <limits.h> */
# if (BITS_PER_CHAR != CHAR_BIT)
# include "ERROR: BITS_PER_CHAR does not match platform CHAR_BIT value!"
# endif
#endif
/*
* This trick will count char bits at runtime
*
* We assume a char cannot be as wide as 0xffffffffUL
*/
#define CHAR_BITCOUNT (((_CHAR_BX((char) -1) + (_CHAR_BX((char) -1) >> 4)) & (char) 0x0f0f0f0fL) % 255)
#define _CHAR_BX(x) ((x) - (((x) >> 1) & (unsigned char) 0x77777777UL) \
- (((x) >> 2) & (unsigned char) 0x33333333UL) \
- (((x) >> 3) & (unsigned char) 0x11111111UL))
/*
* Derive bit counts extended to other types
*
* If BITS_PER_LONG < 32 be careful! Along with other things, the hash_str()
* function in hash.c will need to be changed.
*/
#define BITS_PER_LONG (sizeof(long) * BITS_PER_CHAR)
#define BITS_PER_INT (sizeof(int) * BITS_PER_CHAR)
#define BITS_PER_SHORT (sizeof(short) * BITS_PER_CHAR)
/*
* pointer - same size as a pointer to a structure
*
* Setup the typedef so that `pointer' is the same size as a pointer to a
* structure. On most machines, this is a long. On some machines where long
* is larger than an int, `pointer' is an unsigned int. Woe to machines with
* hardware addresses < 19 bits. (smail might not even fit in that case!)
*
* Assume:
* typedef long pointer_t;
* struct foo *p; <-- some j-random pointer
* long v; <-- same type as the typedef
* union offptr {
* struct foo *ptr;
* pointer_t addr;
* } x; <-- union of a pointer and the typedef
*
* then the following must be true:
* x.addr = v; implies v == (pointer_t) (x.ptr)
* x.addr = (pointer_t) p; implies p == x.ptr
* x.addr == (pointer_t) (x.ptr)
* x.ptr = p; implies p == (struct foo *) (x.addr)
* x.ptr = (struct foo *) v; implies v == x.addr
* x.ptr == (struct foo *) (x.addr)
*/
typedef POINTER_TYPE pointer_t;
/*
* BYTES_PER_ALIGN - what byte-resolution should be used for alignment
*
* Typically BYTES_PER_ALIGN should be equal to the width of the path to memory
* for a machine, as this is the smallest alignment for which there no
* performance penalty in accessing an object of any size.
*
* In general though sizeof(ALIGNED_TYPE) suffices, unless that's less than the
* size of pointer_t.
*
* Note Smail itself never stores float, double, or long double values in
* allocated storage so max(sizeof(pointer_t), sizeof(long long)) is the
* largest alignment value we have to worry about in terms of protecting
* ourselves from triggering SIGBUS.
*/
#define BYTES_PER_ALIGN (sizeof(ALIGNED_TYPE))
/*
* even bytes and odd bytes
*
* The hash system used by hash.c (on disk and in memory) relies on the fact
* that BYTES_PER_ALIGN (see above) will align things to an even byte boundary.
*
* Any hash `pointer' that refers to an odd value (2n+1) is taken to mean an
* offset rather than a real address. Note that odd valued pointers are never
* dereferenced.
*
* We need to be able to distinguish between even and odd addresses, and to
* convert to/from even/odd addresseses. On most machines this is a trivial
* macro. Brain damaged machines with brain damaged segment addressing may
* have to form their own creative macros.
*
* Assume:
* #define NULL 0 <-- for the sake of this example
* struct foobar *ptr; <-- ptr points to a BYTES_PER_ALIGN object
* pointer addr; <-- addr is of a BYTES_PER_ALIGN object
*
* Then these conversion macros must perform the following:
* to_odd() and to_even() do not distroy data:
* addr = to_odd(ptr) ==> ptr == to_even(addr)
* addr = to_even(ptr) ==> ptr == to_odd(addr)
* is_even() and is_odd() are reflexive:
* is_odd(addr) != 0 ==> is_even(to_even(addr)) == 0
* is_odd(ptr) != 0 ==> is_even(to_even(ptr)) == 0
* is_even(addr) != 0 ==> is_odd(to_odd(addr)) == 0
* is_even(ptr) != 0 ==> is_odd(to_odd(ptr)) == 0
* NULL is an even pointer:
* is_even(NULL) != 0
*/
#define is_odd(addr) ((pointer_t) (addr) & 0x1) /* non-zero if odd pointer */
#define is_even(addr) (! is_odd(addr)) /* non-zero if even pointer */
#define to_odd(addr) ((pointer_t) (addr) | 0x1) /* from even or odd to odd */
#define to_even(addr) ((pointer_t) (addr) & ~0x1) /* from even or odd to even */
/*
* set_ptr(ptr,addr) places the numeric value of `addr' into the pointer `ptr'.
* That is, we borrow the pointer `ptr' to store numeric data.
*
* get_ptr(ptr) converts a pointer `ptr' back into the value which was stored
* into it by set_ptr().
*/
#define get_ptr(ptr) (*(pointer_t *) &(ptr))
#define set_ptr(ptr,addr) (get_ptr(ptr) = (pointer_t) (addr))
/*
* Local Variables:
* c-file-style: "smail"
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1