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