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