Coherent4.2.10/include/common/_dregset.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__DREGSET_H__
#define __COMMON__DREGSET_H__
/*
* This file defines a structure for the debugging facilities made available
* by the kernel for debugger use. In COHERENT, this means the raw debug
* registers.
*
* This file defines the structure layout. Another file contains a incomplete
* type declaration, for use by code that has no need to know the internal
* structure of such items.
*/
#include <common/__types.h>
#include <common/dregset.h>
#include <common/__linear.h>
#if ! _I386
# error You must be compiling for the _I386 to use this header!
#endif
/*
* Definitions for the internal structure of the debug registers.
*/
/*
* Codes for the types of fetches that a breakpoint can match.
*/
enum __break_match {
_BREAK_EXECUTE, /* break on execute, len must == 0 */
_BREAK_WRITE, /* break on write */
_BREAK_RESERVED_DO_NOT_USE,
_BREAK_READ_WRITE, /* break on read or write */
__BREAK_MATCH_MASK = _BREAK_READ_WRITE
};
typedef enum __break_match __break_match_t;
/*
* Codes for the length of the region matched by a breakpoint; note that the
* address must be correspondingly aligned on a byte, word, or double-word
* boundary.
*/
enum __break_len {
_BREAK_LEN_BYTE,
_BREAK_LEN_WORD,
_BREAK_LEN_RESERVED_DO_NOT_USE,
_BREAK_LEN_DWORD,
__BREAK_LEN_MASK = _BREAK_LEN_DWORD
};
typedef enum __break_len __break_len_t;
/*
* Codes for the level at which the breakpoints are enabled. If the
* breakpoint is enabled locally, it will be disabled by the first hardware
* task-switch to occur.
*
* Note that the effect of this at user-level within the COHERENT system may
* not match your expectation ...
*/
enum __break_level {
_BREAK_NONE,
_BREAK_LOCAL,
_BREAK_GLOBAL,
_BREAK_BOTH,
__BREAK_LEVEL_MASK = _BREAK_BOTH
};
typedef enum __break_level __break_level_t;
/*
* Codes for controlling whether pipelining in the i386 execution unit should
* be reduced to a level that allows breakpoint matches to be able to report
* the precise instruction address that caused the breakpoint match. On the
* i486, these bits are ignored and the same effect happens automatically.
*/
enum __break_exact {
_BREAK_NORMAL,
_BREAK_SLOW_LOCAL,
_BREAK_SLOW_GLOBAL,
_BREAK_SLOW_BOTH,
__BREAK_EXACT_MASK = _BREAK_SLOW_BOTH
};
typedef enum __break_exact __break_exact_t;
/*
* Codes to control global breakpoint enabling.
*/
enum __break_enab {
_BREAK_DISABLED,
_BREAK_ENABLED,
__BREAK_ENABLE_MASK = _BREAK_ENABLED
};
typedef enum __break_enab __break_enab_t;
/*
* Miscellaneous info about the breakpoints detected.
*/
#define __BREAK_0_MATCH 0x0001U /* breakpoint set 0 match */
#define __BREAK_1_MATCH 0x0002U /* breakpoint set 1 match */
#define __BREAK_2_MATCH 0x0004U /* breakpoint set 2 match */
#define __BREAK_3_MATCH 0x0008U /* breakpoint set 3 match */
#define __BREAK_DEBUG 0x2000U /* breakpoint contention */
#define __BREAK_STEP 0x4000U /* break on single-step */
#define __BREAK_TASK 0x8000U /* break on task-switch */
/*
* The contents of DR6/DR7 are an unsigned long in the _I386 architecture, but
* we declare the externally-visible type as an incomplete structure pointer
* to prevent accidental misuse as a scalar type. DR6 should be treated as a
* read-only object; we only allow construction of an empty version.
*/
typedef struct __break_stat * __break_stat_t;
#define _MAKE_DEBUG_STATUS() ((__break_stat_t) 0)
#define __IS_BREAK(stat,mask) (((__break_arith_t) (stat) & (mask)) != 0)
#define _IS_BREAK_0_MATCH(stat) __IS_BREAK (stat, __BREAK_0_MATCH)
#define _IS_BREAK_1_MATCH(stat) __IS_BREAK (stat, __BREAK_1_MATCH)
#define _IS_BREAK_2_MATCH(stat) __IS_BREAK (stat, __BREAK_2_MATCH)
#define _IS_BREAK_3_MATCH(stat) __IS_BREAK (stat, __BREAK_3_MATCH)
#define _IS_BREAK_DEBUG(stat) __IS_BREAK (stat, __BREAK_DEBUG)
#define _IS_BREAK_STEP(stat) __IS_BREAK (stat, __BREAK_STEP)
#define _IS_BREAK_TASK(stat) __IS_BREAK (stat, __break_point_tASK)
#define __CLEAR_BREAK(stat,mask) ((__stat_t) ((__ulong_t) (stat) & ~ (mask)))
#define _CLEAR_BREAK_0_MATCH(stat) __CLEAR_BREAK (stat, __BREAK_0_MATCH)
#define _CLEAR_BREAK_1_MATCH(stat) __CLEAR_BREAK (stat, __BREAK_1_MATCH)
#define _CLEAR_BREAK_2_MATCH(stat) __CLEAR_BREAK (stat, __BREAK_2_MATCH)
#define _CLEAR_BREAK_3_MATCH(stat) __CLEAR_BREAK (stat, __BREAK_3_MATCH)
#define _CLEAR_BREAK_DEBUG(stat) __CLEAR_BREAK (stat, __BREAK_DEBUG)
#define _CLEAR_BREAK_STEP(stat) __CLEAR_BREAK (stat, __BREAK_STEP)
#define _CLEAR_BREAK_TASK(stat) __CLEAR_BREAK (stat, __break_point_tASK)
typedef struct __break_cntl * __break_cntl_t;
typedef struct __break_point * __break_point_t;
typedef __ulong_t __break_arith_t;
enum {
__BREAK_LEVEL_SHIFT,
__BREAK_EXACT_SHIFT = 8,
__BREAK_ENABLE_SHIFT = 13,
__BREAK_MATCH_SHIFT = 16,
__BREAK_LEN_SHIFT = 18
};
/*
* The following macros wrap up basic shifting and masking such that we don't
* have to worry about casting (or signedness) below. Note that we use the
* "+ 0U" trick because we know the bounds of the shift count, but we perform
* an actual cast of the LHS because it will often have a nonarithmetic
* operand.
*/
#define __BREAK_SHIFT_LEFT(x, y) ((__break_arith_t) (x) << ((y) + 0U))
#define __BREAK_SHIFT_RIGHT(x, y) ((__break_arith_t) (x) >> ((y) + 0U))
#define __BREAK_MASK(x, y) ((__break_arith_t) (x) & (y))
#define __BREAK_SHIFT_AND_MASK(x,direction,name) \
(__BREAK_SHIFT_RIGHT (x, \
__CONCAT3 (__BREAK_, name, _SHIFT)) & \
__CONCAT3 (__BREAK_, name, _MASK))
#define __BREAK_SHIFTED_MASK(name) \
__BREAK_SHIFT_LEFT (__CONCAT3 (__BREAK_, name, _MASK), \
__CONCAT3 (__BREAK_, name, _SHIFT))
#define __BREAK_BREAK_MASK(n) \
((__break_arith_t) \
_MAKE_BREAK (__BREAK_MATCH_MASK, __BREAK_LEN_MASK, \
__BREAK_LEVEL_MASK))
#define __BREAK_SHIFT_MASK(n) __BREAK_SHIFT_LEFT (__BREAK_BREAK_MASK (n), \
2 * (n))
#define _MAKE_BREAK(match,len,level) \
((__break_point_t) \
(__BREAK_SHIFT_LEFT (match, __BREAK_MATCH_SHIFT) | \
__BREAK_SHIFT_LEFT (len, __BREAK_LEN_SHIFT) | \
__BREAK_SHIFT_LEFT (level, __BREAK_LEVEL_SHIFT)))
#define _GET_BREAK_MATCH(break) \
((__break_match_t) __BREAK_SHIFT_AND_MASK (break, MATCH))
#define _GET_BREAK_LEN(break) \
((__break_match_t) __BREAK_SHIFT_AND_MASK (break, LEN))
#define _GET_BREAK_LEVEL(break) \
((__break_match_t) __BREAK_SHIFT_AND_MASK (break, LEVEL))
#define _MAKE_DEBUG_CONTROL(br0,br1,br2,br3,exact) \
((__break_cntl_t) \
(__BREAK_SHIFT_LEFT (br0, 0) | \
__BREAK_SHIFT_LEFT (br1, 2) | \
__BREAK_SHIFT_LEFT (br2, 4) | \
__BREAK_SHIFT_LEFT (br3, 6) | \
__BREAK_SHIFT_LEFT (exact, __BREAK_EXACT_SHIFT) | \
__BREAK_SHIFT_LEFT (__BREAK_ENABLED, __BREAK_ENABLE_SHIFT)))
#define _MAKE_DEBUG_DISABLED() \
((__break_cntl_t) \
__BREAK_SHIFT_LEFT (__BREAK_DISABLED, __BREAK_ENABLE_SHIFT))
#define _IS_BREAK_ENABLED(cntl) \
(((__break_arith_t) (cntl) & \
__BREAK_SHIFT_LEFT (__BREAK_ENABLE_MASK, \
__BREAK_ENABLE_SHIFT)) != \
_BREAK_DISABLED)
#define _SET_BREAK_ENABLE(cntl, flag) \
((__break_cntl_t) \
(__BREAK_MASK (cntl, __BREAK_SHIFTED_MASK (ENABLE)) | \
__BREAK_SHIFT_LEFT (flag, __BREAK_ENABLE_SHIFT))
#define _BREAK_SET_BREAK(cntl,n,break) \
((__break_cntl_t) \
(__BREAK_MASK (cntl, ~ __BREAK_SHIFT_MASK (n)) | \
__BREAK_SHIFT_LEFT (break, 2 * n)))
#define _BREAK_SET_EXACT(cntl, exact) \
((__break_cntl_t) \
(__BREAK_MASK (cntl, __BREAK_SHIFTED_MASK (EXACT)) | \
__BREAK_SHIFT_LEFT (exact, __BREAK_EXACT_SHIFT)))
#define _BREAK_GET_BREAK(cntl,n) \
((__break_point_t) (__BREAK_SHIFT_RIGHT (cntl, 2 * n) & \
__BREAK_BREAK_MASK (n)))
#define _BREAK_GET_EXACT(cntl) \
((__break_exact_t) __BREAK_SHIFT_AND_MASK (cntl, EXACT))
struct __dregset {
__linear_t _break_address [4]; /* DR0-DR3 */
__ulong_t _break_reserved [2]; /* DR4-DR5 */
__break_stat_t _break_status; /* DR6 */
__break_cntl_t _break_control; /* DR7 */
};
#endif /* ! defined (__COMMON__DREGSET_H__) */