]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
8f6c56a5 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
8f6c56a5 A |
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 | |
8ad349bb | 24 | * limitations under the License. |
8f6c56a5 A |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
1c79356b A |
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 | */ | |
83 | typedef 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 | */ | |
95 | typedef 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 | */ | |
111 | typedef 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 | */ | |
128 | typedef 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 | */ | |
144 | typedef 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 | */ | |
158 | typedef 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 | */ | |
175 | typedef 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 | */ | |
190 | typedef 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 | */ | |
198 | typedef 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 | */ | |
213 | static __inline__ msr_t | |
214 | get_msr() | |
215 | { | |
216 | msr_t __msr_tmp; | |
217 | __asm__ volatile ("mfmsr %0 /* mfmsr */" : "=r" (__msr_tmp)); | |
218 | return __msr_tmp; | |
219 | } | |
220 | ||
221 | static __inline__ void | |
222 | set_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 | */ | |
230 | static __inline__ fp_exc_mode_t | |
231 | get_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) \ | |
289 | MACRO_BEGIN \ | |
290 | __typeof__ (val) __spr_tmp = (val); \ | |
291 | __asm__ volatile ("mtspr "STRINGIFY(spr) ", %0" : : "r" (__spr_tmp)); \ | |
292 | MACRO_END | |
293 | ||
294 | /* | |
295 | * Fully synchronize instruction stream. | |
296 | */ | |
297 | static __inline__ void | |
298 | ppc_sync() | |
299 | { | |
300 | __asm__ volatile ("sync /* sync */" : : ); | |
301 | } | |
302 | ||
303 | #endif /* ! __ASSEMBLER__ */ | |
304 | ||
305 | #endif /* _ARCH_PPC_BASIC_REGS_H_ */ | |
306 |