ftp.nice.ch/pub/next/developer/nextsources/cctools.s.tar.gz#/cctools/include/architecture/m98k/basic_regs.h

This is basic_regs.h in view mode; [Download] [Up]

/* Copyright (c) 1992 NeXT Computer, Inc.  All rights reserved.
 *
 *	File:	architecture/m98k/basic_regs.h
 *	Author:	Doug Mitchell, NeXT Computer, Inc.
 *
 *	Basic m98k registers.
 *
 * HISTORY
 * 05-Nov-92  Doug Mitchell at NeXT
 *	Created.
 */

#ifndef _ARCH_M98K_BASIC_REGS_H_
#define _ARCH_M98K_BASIC_REGS_H_

#import <architecture/m98k/reg_help.h>
#import <architecture/nrw/macro_help.h>

/*
 * Number of General Purpose registers.
 */
#define M98K_NGP_REGS	32

/*
 * Common half-word used in Machine State Register and in 
 * various exception frames. Defined as a macro because the compiler
 * will align a struct to a word boundary when used inside another struct.
 */
#define MSR_BITS							   \
	unsigned	ee:BIT_WIDTH(15),	/* external intr enable */ \
			pr:BIT_WIDTH(14),	/* problem state	*/ \
			fp:BIT_WIDTH(13),	/* floating point avail	*/ \
			me:BIT_WIDTH(12),	/* machine check enable	*/ \
			fe0:BIT_WIDTH(11),	/* fp exception mode 0	*/ \
			se:BIT_WIDTH(10),	/* single step enable	*/ \
			be:BIT_WIDTH(9),	/* branch trace enable	*/ \
			fe1:BIT_WIDTH(8),	/* fp exception mode 0	*/ \
			rsvd1:BIT_WIDTH(7),	/* reserved		*/ \
			ip:BIT_WIDTH(6),	/* interrupt prefix	*/ \
			ir:BIT_WIDTH(5),	/* instruction relocate	*/ \
			dr:BIT_WIDTH(4),	/* data relocate	*/ \
			rsvd2:BITS_WIDTH(3,1),	/* reserved		*/ \
			psfr:BIT_WIDTH(0)	/* 64 bit mode		*/

/*
 * Machine state register.
 * Read and written via get_msr() and set_msr() inlines, below.
 */
typedef struct {
	unsigned	rsvd3:BITS_WIDTH(31,16);	// reserved
			MSR_BITS;			// see above
} msr_t;

/*
 * Data Storage Interrupt Status Register (DSISR)
 */
typedef struct {
	unsigned	dse:BIT_WIDTH(31);	// direct-store error
	unsigned	tnf:BIT_WIDTH(30);	// translation not found
	unsigned	:BITS_WIDTH(29,28);
	unsigned	pe:BIT_WIDTH(27);	// protection error
	unsigned	dsr:BIT_WIDTH(26);	// lwarx/stwcx to direct-store
	unsigned	rw:BIT_WIDTH(25);	// 1 => store, 0 => load
	unsigned	:BITS_WIDTH(24,23);
	unsigned	dab:BIT_WIDTH(22);	// data address bkpt (601)
	unsigned	ssf:BIT_WIDTH(21);	// seg table search failed
	unsigned	:BITS_WIDTH(20,0);
} dsisr_t;

/*
 * Instruction Storage Interrupt Status Register (really SRR1)
 */
typedef struct {
	unsigned	:BIT_WIDTH(31);
	unsigned	tnf:BIT_WIDTH(30);	// translation not found
	unsigned	:BIT_WIDTH(29);
	unsigned	dse:BIT_WIDTH(28);	// direct-store fetch error
	unsigned	pe:BIT_WIDTH(27);	// protection error
	unsigned	:BITS_WIDTH(26,22);
	unsigned	ssf:BIT_WIDTH(21);	// seg table search failed
	unsigned	:BITS_WIDTH(20,16);
	MSR_BITS;
} isisr_t;

/*
 * Alignment Interrupt Status Register (really DSISR)
 * NOTE: bit numbers in field *names* are in IBM'ese (0 is MSB).
 * FIXME: Yuck!!! Double Yuck!!!
 */
typedef struct {
	unsigned	:BITS_WIDTH(31,20);
	unsigned	ds3031:BITS_WIDTH(19,18);// bits 30:31 if DS form
	unsigned	:BIT_WIDTH(17);
	unsigned	x2930:BITS_WIDTH(16,15); // bits 29:30 if X form
	unsigned	x25:BIT_WIDTH(14);	 // bit 25 if X form or
						 // bit 5 if D or DS form
	unsigned	x2124:BITS_WIDTH(13,10); // bits 21:24 if X form or
						 // bits 1:4 if D or DS form
	unsigned	all615:BITS_WIDTH(9,0);	 // bits 6:15 of instr
	MSR_BITS;
} aisr_t;

/*
 * Program Interrupt Status Register (really SRR1)
 */
typedef struct {
	unsigned	:BITS_WIDTH(31,21);
	unsigned	fpee:BIT_WIDTH(20);	// floating pt enable exception
	unsigned	ill:BIT_WIDTH(19);	// illegal instruction
	unsigned	priv:BIT_WIDTH(18);	// privileged instruction
	unsigned	trap:BIT_WIDTH(17);	// trap program interrupt
	unsigned	subseq:BIT_WIDTH(16);	// 1 => SRR0 points to
						// subsequent instruction
	MSR_BITS;
} pisr_t;

/*
 * Condition register. May not be useful in C, let's see...
 */
typedef struct {
	unsigned	lt:BIT_WIDTH(31),	// negative
			gt:BIT_WIDTH(30),	// positive
			eq:BIT_WIDTH(29),	// equal to zero
			so:BIT_WIDTH(28),	// summary overflow
			fx:BIT_WIDTH(27),	// floating point exception
			fex:BIT_WIDTH(26),	// fp enabled exception
			vx:BIT_WIDTH(25),	// fp invalid operation
						//    exception
			ox:BIT_WIDTH(24),	// fp overflow exception
			rsvd:BITS_WIDTH(23,0);	// reserved
} cr_t;

/*
 * Program mode register.
 * Read and written via get_prog_mode() and set_prog_mode() inlines, below.
 *
 * NOT SUPPORTED ON M98601
 */
typedef struct {
	unsigned	rsvd1:BITS_WIDTH(31,12),
			fe0:BIT_WIDTH(11),
			rsvd2:BITS_WIDTH(10,9),
			fe1:BIT_WIDTH(8),
			rsvd3:BITS_WIDTH(7,1),
			sf:BIT_WIDTH(0);	// 64 bit mode
} prog_mode_t;

/*
 * Abstract values representing fe0:fe1.
 * See get_fp_exc_mode(), below.
 */
typedef enum {
	FEM_IGNORE_EXCEP,	// ignore exceptions
	FEM_IMPR_NONREC,	// imprecise nonrecoverable
	FEM_IMPR_RECOV,		// imprecise recoverable
	FEM_PRECISE,
} fp_exc_mode_t;


/*
 * Special purpose registers.
 */
 
/*
 * Processor version register (special purpose register pvr).
 */
typedef struct {
	unsigned	version:BITS_WIDTH(31,16),	
			revision:BITS_WIDTH(15,0);
} pvr_t;

/*
 * Fixed point exception register (special purpose register xer)
 */
typedef struct {
	unsigned	so:BIT_WIDTH(31),	// summary overflow
			ov:BIT_WIDTH(30),	// overflow
			ca:BIT_WIDTH(29),	// carry
			rsvd1:BITS_WIDTH(28,16),// reserved
			byte:BITS_WIDTH(15,8),	// byte to be compared
			rsvd2:BIT_WIDTH(7),	// reserved
			byte_count:BITS_WIDTH(6,0);	
} xer_t;

/*
 * Inlines and macros to manipulate the above registers.
 */
 
/*
 * Get/set machine state register.
 */
static __inline__ msr_t
get_msr()
{
	msr_t	__msr_tmp;	
	
	__asm__ volatile ("mfmsr %0  /* mfmsr */"  \
	  	: "=r" (__msr_tmp));
	return __msr_tmp;
}

static __inline__ void
set_msr(msr_t msr)
{
	__asm__ volatile ("mtmsr %0 /* mtmsr */ "	\
	  : : "r" (msr));	
}

/*
 * Read/write program mode register.
 *
 * NOT SUPPORTED ON M98601
 */
static __inline__ prog_mode_t 
get_prog_mode()
{
	prog_mode_t	__pm_tmp;	
	__asm__ volatile ("mfpmr %0  /* mfpmr */"	\
	  	: "=r" (__pm_tmp));
	return __pm_tmp;		
}

static __inline__ void 
set_prog_mode(prog_mode_t prog_mode)
{
	__asm__ volatile ("mtpmr %0; /* mtpmr */ "	\
	  : : "r" (prog_mode));	
}


/* 
 * Determine current fp_exc_mode_t given prog_mode.
 */
static __inline__ fp_exc_mode_t
get_fp_exc_mode(prog_mode_t prog_mode)
{
	if(prog_mode.fe0) {
		return prog_mode.fe1 ? FEM_PRECISE : FEM_IMPR_RECOV;
	}
	else {
		return prog_mode.fe1 ? FEM_IMPR_NONREC : FEM_IGNORE_EXCEP;
	}
}

/*
 * Software definitions for special purpose registers.
 * The same register is used as per_cpu data pointer and
 * vector base register. This requires that the vector
 * table be the first item in the per_cpu table.
 */
#define SR_EXCEPTION_TMP_LR	sprg0
#define SR_EXCEPTION_TMP_CR	sprg1
#define SR_EXCEPTION_TMP_AT	sprg2
#define SR_PER_CPU_DATA		sprg3
#define SR_VBR			sprg3

/*
 * Get/set special purpose registers.
 *
 * GET_SPR - get SPR by name.
 *
 * Example usage:
 *
 *   {
 *	xer_t	some_xer;
 *
 *	some_xer = GET_SPR(xer_t, xer);
 *	...
 *   }
 *
 * This is a strange one. We're creating a list of C expressions within
 * a set of curlies; the last expression ("__spr_tmp;") is the return value
 * of the statement created by the curlies.
 *
 * WARNING: The m88k version of this did not compile with -O2. Let's hope
 * the 2.2.2 compiler fixes this.
 */
 
#define GET_SPR(type, spr)					\
({								\
	unsigned	__spr_tmp;				\
	__asm__ volatile ("mfspr %0, "  STRINGIFY(spr)		\
	 	 : "=r" (__spr_tmp));				\
	*(type *)&__spr_tmp;					\
})

/* 
 * Example usage of SET_SPR:
 *
 *   {
 *	xer_t some_xer;
 *
 *	...set up some_xer...
 *	SET_SPR(xer, some_xer);
 *   }
 */
#define	SET_SPR(spr, val)					\
MACRO_BEGIN							\
	__typeof__ (val) __spr_tmp = (val);			\
	__asm__ volatile ("mtspr "STRINGIFY(spr) ", %0"		\
	  : : "r" (__spr_tmp));					\
MACRO_END

/*
 * Fully synchronize instruction stream.
 */
static __inline__ void
m98k_sync()
{
	__asm__ volatile ("sync         /* sync */"	\
		: : );
}

#endif	_ARCH_M98K_BASIC_REGS_H_

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.