1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/* Copyright (c) 1996 NeXT Software, Inc.  All rights reserved.
29 *
30 *	File:	architecture/ppc/basic_regs.h
31 *	Author:	Doug Mitchell, NeXT Software, Inc.
32 *
33 *	Basic ppc registers.
34 *
35 * HISTORY
36 * 22-May-97  Umesh Vaishampayan  (umeshv@apple.com)
37 	Updated to match MPCFPE32B/AD 1/97 REV. 1
38 * 29-Dec-96  Umesh Vaishampayan  (umeshv@NeXT.com)
39 *	Ported from m98k.
40 * 05-Nov-92  Doug Mitchell at NeXT
41 *	Created.
42 */
43
44#ifndef _ARCH_PPC_BASIC_REGS_H_
45#define _ARCH_PPC_BASIC_REGS_H_
46
47#include <architecture/ppc/reg_help.h>
48#include <architecture/ppc/macro_help.h>
49
50#if !defined(__ASSEMBLER__)
51
52/*
53 * Number of General Purpose registers.
54 */
55#define PPC_NGP_REGS	32
56
57/*
58 * Common half-word used in Machine State Register and in
59 * various exception frames. Defined as a macro because the compiler
60 * will align a struct to a word boundary when used inside another struct.
61 */
62#define MSR_BITS							   \
63	unsigned	ee:BIT_WIDTH(15),	/* external intr enable    */ \
64			pr:BIT_WIDTH(14),	/* problem state	   */ \
65			fp:BIT_WIDTH(13),	/* floating point avail	   */ \
66			me:BIT_WIDTH(12),	/* machine check enable	   */ \
67			fe0:BIT_WIDTH(11),	/* fp exception mode 0	   */ \
68			se:BIT_WIDTH(10),	/* single step enable	   */ \
69			be:BIT_WIDTH(9),	/* branch trace enable	   */ \
70			fe1:BIT_WIDTH(8),	/* fp exception mode 0	   */ \
71			rsvd1:BIT_WIDTH(7),	/* reserved		   */ \
72			ip:BIT_WIDTH(6),	/* interrupt prefix	   */ \
73			ir:BIT_WIDTH(5),	/* instruction relocate	   */ \
74			dr:BIT_WIDTH(4),	/* data relocate	   */ \
75			rsvd2:BITS_WIDTH(3,2),	/* reserved		   */ \
76			ri:BIT_WIDTH(1),	/* recoverable exception   */ \
77			le:BIT_WIDTH(0)		/* Little-endian mode	   */
78
79/*
80 * Machine state register.
81 * Read and written via get_msr() and set_msr() inlines, below.
82 */
83typedef struct {
84	unsigned	rsvd3:BITS_WIDTH(31,19),	// reserved
85			pow:BIT_WIDTH(18),	// Power management enable
86			rsvd0: BIT_WIDTH(17),	// reserved
87			ile: BIT_WIDTH(16);	// exception little endian
88
89			MSR_BITS;			// see above
90} msr_t;
91
92/*
93 * Data Storage Interrupt Status Register (DSISR)
94 */
95typedef struct {
96	unsigned	dse:BIT_WIDTH(31);	// direct-store error
97	unsigned	tnf:BIT_WIDTH(30);	// translation not found
98	unsigned	:BITS_WIDTH(29,28);
99	unsigned	pe:BIT_WIDTH(27);	// protection error
100	unsigned	dsr:BIT_WIDTH(26);	// lwarx/stwcx to direct-store
101	unsigned	rw:BIT_WIDTH(25);	// 1 => store, 0 => load
102	unsigned	:BITS_WIDTH(24,23);
103	unsigned	dab:BIT_WIDTH(22);	// data address bkpt (601)
104	unsigned	ssf:BIT_WIDTH(21);	// seg table search failed
105	unsigned	:BITS_WIDTH(20,0);
106} dsisr_t;
107
108/*
109 * Instruction Storage Interrupt Status Register (really SRR1)
110 */
111typedef struct {
112	unsigned	:BIT_WIDTH(31);
113	unsigned	tnf:BIT_WIDTH(30);	// translation not found
114	unsigned	:BIT_WIDTH(29);
115	unsigned	dse:BIT_WIDTH(28);	// direct-store fetch error
116	unsigned	pe:BIT_WIDTH(27);	// protection error
117	unsigned	:BITS_WIDTH(26,22);
118	unsigned	ssf:BIT_WIDTH(21);	// seg table search failed
119	unsigned	:BITS_WIDTH(20,16);
120	MSR_BITS;
121} isisr_t;
122
123/*
124 * Alignment Interrupt Status Register (really DSISR)
125 * NOTE: bit numbers in field *names* are in IBM'ese (0 is MSB).
126 * FIXME: Yuck!!! Double Yuck!!!
127 */
128typedef struct {
129	unsigned	:BITS_WIDTH(31,20);
130	unsigned	ds3031:BITS_WIDTH(19,18);// bits 30:31 if DS form
131	unsigned	:BIT_WIDTH(17);
132	unsigned	x2930:BITS_WIDTH(16,15); // bits 29:30 if X form
133	unsigned	x25:BIT_WIDTH(14);	 // bit 25 if X form or
134						 // bit 5 if D or DS form
135	unsigned	x2124:BITS_WIDTH(13,10); // bits 21:24 if X form or
136						 // bits 1:4 if D or DS form
137	unsigned	all615:BITS_WIDTH(9,0);	 // bits 6:15 of instr
138	MSR_BITS;
139} aisr_t;
140
141/*
142 * Program Interrupt Status Register (really SRR1)
143 */
144typedef struct {
145	unsigned	:BITS_WIDTH(31,21);
146	unsigned	fpee:BIT_WIDTH(20);	// floating pt enable exception
147	unsigned	ill:BIT_WIDTH(19);	// illegal instruction
148	unsigned	priv:BIT_WIDTH(18);	// privileged instruction
149	unsigned	trap:BIT_WIDTH(17);	// trap program interrupt
150	unsigned	subseq:BIT_WIDTH(16);	// 1 => SRR0 points to
151						// subsequent instruction
152	MSR_BITS;
153} pisr_t;
154
155/*
156 * Condition register. May not be useful in C, let's see...
157 */
158typedef struct {
159	unsigned	lt:BIT_WIDTH(31),	// negative
160			gt:BIT_WIDTH(30),	// positive
161			eq:BIT_WIDTH(29),	// equal to zero
162			so:BIT_WIDTH(28),	// summary overflow
163			fx:BIT_WIDTH(27),	// floating point exception
164			fex:BIT_WIDTH(26),	// fp enabled exception
165			vx:BIT_WIDTH(25),	// fp invalid operation
166						//    exception
167			ox:BIT_WIDTH(24),	// fp overflow exception
168			rsvd:BITS_WIDTH(23,0);	// reserved
169} cr_t;
170
171/*
172 * Abstract values representing fe0:fe1.
173 * See get_fp_exc_mode(), below.
174 */
175typedef enum {
176	FEM_IGNORE_EXCEP,	// ignore exceptions
177	FEM_IMPR_NONREC,	// imprecise nonrecoverable
178	FEM_IMPR_RECOV,		// imprecise recoverable
179	FEM_PRECISE
180} fp_exc_mode_t;
181
182
183/*
184 * Special purpose registers.
185 */
186
187/*
188 * Processor version register (special purpose register pvr).
189 */
190typedef struct {
191	unsigned	version:BITS_WIDTH(31,16),
192			revision:BITS_WIDTH(15,0);
193} pvr_t;
194
195/*
196 * Fixed point exception register (special purpose register xer)
197 */
198typedef struct {
199	unsigned	so:BIT_WIDTH(31),	// summary overflow
200			ov:BIT_WIDTH(30),	// overflow
201			ca:BIT_WIDTH(29),	// carry
202			rsvd1:BITS_WIDTH(28,7), // reserved
203			byte_count:BITS_WIDTH(6,0);
204} xer_t;
205
206/*
207 * Inlines and macros to manipulate the above registers.
208 */
209
210/*
211 * Get/set machine state register.
212 */
213static __inline__ msr_t
214get_msr()
215{
216	msr_t	__msr_tmp;
217	__asm__ volatile ("mfmsr %0  /* mfmsr */" : "=r" (__msr_tmp));
218	return __msr_tmp;
219}
220
221static __inline__ void
222set_msr(msr_t msr)
223{
224	__asm__ volatile ("mtmsr %0 /* mtmsr */ " : : "r" (msr));
225}
226
227/*
228 * Determine current fp_exc_mode_t given prog_mode.
229 */
230static __inline__ fp_exc_mode_t
231get_fp_exc_mode(pmr_t pmr)
232{
233	if(pmr.fe0)
234		return pmr.fe1 ? FEM_PRECISE : FEM_IMPR_RECOV;
235	else
236		return pmr.fe1 ? FEM_IMPR_NONREC : FEM_IGNORE_EXCEP;
237}
238
239/*
240 * Software definitions for special purpose registers.
241 * The same register is used as per_cpu data pointer and
242 * vector base register. This requires that the vector
243 * table be the first item in the per_cpu table.
244 */
245#define SR_EXCEPTION_TMP_LR	sprg0
246#define SR_EXCEPTION_TMP_CR	sprg1
247#define SR_EXCEPTION_TMP_AT	sprg2
248#define SR_PER_CPU_DATA		sprg3
249#define SR_VBR			sprg3
250
251/*
252 * Get/set special purpose registers.
253 *
254 * GET_SPR - get SPR by name.
255 *
256 * Example usage:
257 *
258 *   {
259 *	xer_t	some_xer;
260 *
261 *	some_xer = GET_SPR(xer_t, xer);
262 *	...
263 *   }
264 *
265 * This is a strange one. We're creating a list of C expressions within
266 * a set of curlies; the last expression ("__spr_tmp;") is the return value
267 * of the statement created by the curlies.
268 *
269 */
270
271#define GET_SPR(type, spr)					\
272({								\
273	unsigned	__spr_tmp;				\
274	__asm__ volatile ("mfspr %0, " STRINGIFY(spr) : "=r" (__spr_tmp));				\
275	*(type *)&__spr_tmp;					\
276})
277
278/*
279 * Example usage of SET_SPR:
280 *
281 *   {
282 *	xer_t some_xer;
283 *
284 *	...set up some_xer...
285 *	SET_SPR(xer, some_xer);
286 *   }
287 */
288#define	SET_SPR(spr, val)					\
289MACRO_BEGIN							\
290	__typeof__ (val) __spr_tmp = (val);			\
291	__asm__ volatile ("mtspr "STRINGIFY(spr) ", %0" : : "r" (__spr_tmp));					\
292MACRO_END
293
294/*
295 * Fully synchronize instruction stream.
296 */
297static __inline__ void
298ppc_sync()
299{
300	__asm__ volatile ("sync         /* sync */" : : );
301}
302
303#endif /* ! __ASSEMBLER__ */
304
305#endif /* _ARCH_PPC_BASIC_REGS_H_ */
306
307