Coherent4.2.10/include/common/_gregset.h

/* (-lgl
 *	Coherent 386 release 4.2
 *	Copyright (c) 1982, 1993 by Mark Williams Company.
 *	All rights reserved. May not be copied without permission.
 *	For copying permission and licensing info, write licensing@mwc.com
 -lgl) */

#ifndef	__COMMON__GREGSET_H__
#define	__COMMON__GREGSET_H__

/*
 * This file defines a "register set" type along the lines of the "gregset_t"
 * type defined for the process file-system in System V, Release 4.  This
 * subsumes the function of the <sys/reg.h> header in the iBCS2 specification,
 * which describes the layout of data on the signal stack and also within the
 * kernel (in COHERENT, via the "u.u_regl" pointer, and in SCO via "u.u_ar0")
 * in terms of an array of "int".  With the introduction of this type, the U
 * area structure has been removed as an anachronism.
 *
 * This file defines the structure layout; an incomplete type declaration is
 * present in another file for use by code that has no need to know the
 * internal structure of such items.
 */

#include <common/__types.h>
#include <common/gregset.h>

/*
 * Definitions for dealing with the flag register.  The flag register should
 * only be accessed by the following macros; for public use we declare a
 * non-arithmetic type.  For the 286 part of the structure, we define a
 * suitable non-arithmetic type, but no macros; such elements may be copied,
 * but not manipulated.
 */

/*
 * Codes for I/O privelege levels.  This level specifies a cut-off processor
 * privelege level (as given by the CPL, the privelege level of the currently
 * executing code segment) above which certain instructions require special
 * privelege.
 */

enum __iopl {
	_IOPL_0, _IOPL_1, _IOPL_2, _IOPL_3,
	__FLAG_IOPL_MASK = _IOPL_3
};
typedef	enum __iopl	__iopl_t;


typedef	struct __flag_reg     *	__flag_reg_t;
typedef	__ulong_t		__flag_arith_t;
typedef	struct {
	__ushort_t	__286;
} __286_flags_t;


enum {
	__CARRY_FLAG_SHIFT,
	__PARITY_FLAG_SHIFT = 2,
	__AUXCARRY_FLAG_SHIFT = 4,
	__ZERO_FLAG_SHIFT = 6,
	__SIGN_FLAG_SHIFT,
	__TRAP_FLAG_SHIFT,
	__INTERRUPT_FLAG_SHIFT,
	__DIRECTION_FLAG_SHIFT,
	__OVERFLOW_FLAG_SHIFT,
	__IOPL_SHIFT,
	__NESTED_FLAG_SHIFT = 14,
	__RESUME_FLAG_SHIFT = 16,
	__V8086_FLAG_SHIFT,
	__ALIGNCHECK_FLAG_SHIFT
};


/*
 * Except for the IOPL field, all the currently defined members of the flag
 * word are single bits; here we simply define a general framework for dealing
 * with them and the shift positions for the most common flags.
 */

#define	__FLAG_MASK(value, shift) \
		((__flag_arith_t) (value) << \
		 (__CONCAT (shift, _FLAG_SHIFT) + 0U))

#define	__FLAG_GET_FLAG(flags, shift) \
		((__flag_arith_t) (flags) >> \
		 (__CONCAT (shift, _FLAG_SHIFT) & 1) != 0)
#define	__FLAG_SET_FLAG_TO(flags, value, shift) \
		((__flag_reg_t) \
		 (((__flag_arith_t) (flags) & ~ __FLAG_MASK (1, shift)) | \
		  __FLAG_MASK (value, shift)))
#define	__FLAG_SET_FLAG(flags, shift)	__FLAG_SET_FLAG_TO (flags, 1, shift)
#define	__FLAG_CLEAR_FLAG(flags, shift)	__FLAG_SET_FLAG_TO (flags, 0, shift)

#define	__FLAG_GET_IOPL(flags) \
		((__iopl_t) ((__flag_arith_t) (flags) >> __IOPL_SHIFT) & \
		 __IOPL_MASK)

/*
 * Special case for clearing all the status (i.e., user-modifiable) flags to
 * a known state.
 */

#define	__FLAG_STATUS_MASK	(__FLAG_MASK (1, __OVERFLOW) | \
			         __FLAG_MASK (1, __SIGN) | \
				 __FLAG_MASK (1, __ZERO) | \
				 __FLAG_MASK (1, __AUXCARRY) | \
				 __FLAG_MASK (1, __PARITY) | \
				 __FLAG_MASK (1, __CARRY))
#define	__FLAG_CLEAR_STATUS(flags) \
		((__flag_reg_t) ((__flag_arith_t) (flags) & \
				 ~ __FLAG_STATUS_MASK))

/*
 * Type for describing an Intel-style selector. We have few choices as to how
 * to define this type, because the size of a selector does not match that of
 * a pointer for the usual pointer-to-incomplete-type technique.
 *
 * However, because selector access relates only to the i386 processor family,
 * this is actually desirable as we do not want access to these items to be
 * made directly in portable code anyway.
 */

typedef	__ushort_t	__sel_arith_t;
typedef	struct {
	__sel_arith_t	__selector;
} __selector_t;

#define	__SELECTOR_ARITH(selp)	((selp).__selector)

/*
 * Describe privilege rings verbosely.
 */

enum {
	_PRIVILEGE_RING_0,
	_PRIVILEGE_RING_1,
	_PRIVILEGE_RING_2,
	_PRIVILEGE_RING_3,
	_USER_PRIVILEGE = _PRIVILEGE_RING_3,
	__PRIVILEGE_RING_MASK = _PRIVILEGE_RING_3
};

/*
 * A bit in the selector selects whether the selector refers to a descriptor
 * in the local descriptor table or the global descriptor table.
 */

enum {
	_GLOBAL_DESCRIPTOR,
	_LOCAL_DESCRIPTOR,
	__DESCRIPTOR_TABLE_MASK = _LOCAL_DESCRIPTOR
};

/*
 * A part of the selector forms an index into one of the selected descriptor
 * tables.  Here, we only deal with the generic aspect of this; index values
 * for particular segments are described elsewhere.
 */

enum {
	__DESCRIPTOR_INDEX_MASK = 0x1FFF
};

/*
 * Shift values for the various components of a selector.
 */

#define	__SELECTOR_PRIVILEGE_SHIFT	0U
#define	__SELECTOR_TABLE_SHIFT		2U
#define	__SELECTOR_INDEX_SHIFT		3U

#define	__SELECTOR_PRIVILEGE(selp) \
		((__SELECTOR_ARITH (selp) >> __SELECTOR_PRIVILEGE_SHIFT) & \
		 __PRIVILEGE_RING_MASK)
#define	__SELECTOR_TABLE(selp) \
		((__SELECTOR_ARITH (selp) >> __SELECTOR_TABLE_SHIFT) & \
		 __DESCRIPTOR_TABLE_MASK)
#define	__SELECTOR_DESCRIPTOR(selp) \
		((__SELECTOR_ARITH (selp) >> __SELECTOR_INDEX_SHIFT) & \
		 __DESCRIPTOR_INDEX_MASK)
#define	__MAKE_SELECTOR_ARITH(index,table,privelege) \
		(((index) << __SELECTOR_INDEX_SHIFT) | \
		 ((table) << __SELECTOR_TABLE_SHIFT) | \
		 ((privelege) << __SELECTOR_PRIVILEGE_SHIFT))
#define	__SET_SELECTOR(selp,arith) \
		((void) (__SELECTOR_ARITH (selp) = (arith)))

/*
 * General register-set description structure, without padding.
 */

union __gregset {
	/*
	 * Frame for i386 task.
	 */
	struct {
		/*
		 * Pushed by the trap handler.
		 */
		__selector_t	_gs;
		__ushort_t	_pad1;
		__selector_t	_fs;
		__ushort_t	_pad2;
		__selector_t	_es;
		__ushort_t	_pad3;
		__selector_t	_ds;
		__ushort_t	_pad4;
		/*
		 * Pushed by the trap handler with a "pusha" intruction.
		 */
		__ulong_t	_edi;
		__ulong_t	_esi;
		__ulong_t	_ebp;
		__ulong_t	_esp;
		__ulong_t	_ebx;
		__ulong_t	_edx;
		__ulong_t	_ecx;
		__ulong_t	_eax;
		/*
		 * Created by the i386 when handling exceptions, or by the
		 * trap code when handling software/hardware interrupts.
		 */
		__ulong_t	_trapno;
		__ulong_t	_err;
		/*
		 * General i386 inter-level interrupt return frame.
		 */
		__ulong_t	_eip;
		__selector_t	_cs;
		__ushort_t	_pad5;
		__flag_reg_t	_eflags;
		__ulong_t	_uesp;
		__selector_t	_ss;
		__ushort_t	_pad6;
	} _i386;
	/*
	 * Frame for i286 task, created from the same code as above but with
	 * only the low 16 bits of general registers containing valid data.
	 */
	struct {
		/*
		 * Pushed by the trap handler.
		 */
		__selector_t	_gs;
		__ushort_t	_pad1;
		__selector_t	_fs;
		__ushort_t	_pad2;
		__selector_t	_es;
		__ushort_t	_pad3;
		__selector_t	_ds;
		__ushort_t	_pad4;
		/*
		 * Pushed by the trap handler with a "pusha" intruction.
		 */
		__ushort_t	_di;
		__ushort_t	_pad6;
		__ushort_t	_si;
		__ushort_t	_pad7;
		__ushort_t	_bp;
		__ushort_t	_pad8;
		__ulong_t	_esp;		/* kernel %esp */
		__ushort_t	_bx;
		__ushort_t	_pad9;
		__ushort_t	_dx;
		__ushort_t	_pad10;
		__ushort_t	_cx;
		__ushort_t	_pad11;
		__ushort_t	_ax;
		__ushort_t	_pad12;

		/*
		 * Created by the i386 when handling exceptions, or by the
		 * trap code when handling software/hardware interrupts.
		 */
		__ulong_t	_trapno;
		__ulong_t	_err;

		/*
		 * General i386 inter-level interrupt return frame.
		 */
		__ushort_t	_ip;
		__ushort_t	_pad13;
		__selector_t	_cs;
		__ushort_t	_pad14;
		__286_flags_t	_flags;
		__ushort_t	_pad15;
		__ushort_t	_usp;
		__ushort_t	_pad16;
		__selector_t	_ss;
		__ushort_t	_pad17;
	} _i286;
};

/*
 * The notion of "flags" and "program counter" are fairly universal, although
 * details vary wildly.  The notion of a "flags" register encompasses condition
 * codes on CISC-style processors, but is more oriented towards processor
 * control functions such as endianness on RISC processors.
 *
 * Program counters are fairly universal, though. We also provide a predicate
 * for testing whether a context is a saved user context or system context.
 */

#define	__FLAG_REG(rp)		((rp)->_i386._eflags)
#define	__PC_REG(rp)		((rp)->_i386._eip)
#define	__IS_USER_REGS(rp)	(__SELECTOR_PRIVILEGE ((rp)->_i386._cs) \
				 == _USER_PRIVILEGE)

#endif	/* ! defined (__COMMON__GREGSET_H__) */