|
|
1.1 root 1: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
2: *
3: * File: architecture/m98k/basic_regs.h
4: * Author: Doug Mitchell, NeXT Computer, Inc.
5: *
6: * Basic m98k registers.
7: *
8: * HISTORY
9: * 05-Nov-92 Doug Mitchell at NeXT
10: * Created.
11: */
12:
13: #ifndef _ARCH_M98K_BASIC_REGS_H_
14: #define _ARCH_M98K_BASIC_REGS_H_
15:
16: #import <architecture/m98k/reg_help.h>
17: #import <architecture/nrw/macro_help.h>
18:
19: /*
20: * Number of General Purpose registers.
21: */
22: #define M98K_NGP_REGS 32
23:
24: /*
25: * Common half-word used in Machine State Register and in
26: * various exception frames. Defined as a macro because the compiler
27: * will align a struct to a word boundary when used inside another struct.
28: */
29: #define MSR_BITS \
30: unsigned ee:BIT_WIDTH(15), /* external intr enable */ \
31: pr:BIT_WIDTH(14), /* problem state */ \
32: fp:BIT_WIDTH(13), /* floating point avail */ \
33: me:BIT_WIDTH(12), /* machine check enable */ \
34: fe0:BIT_WIDTH(11), /* fp exception mode 0 */ \
35: se:BIT_WIDTH(10), /* single step enable */ \
36: be:BIT_WIDTH(9), /* branch trace enable */ \
37: fe1:BIT_WIDTH(8), /* fp exception mode 0 */ \
38: rsvd1:BIT_WIDTH(7), /* reserved */ \
39: ip:BIT_WIDTH(6), /* interrupt prefix */ \
40: ir:BIT_WIDTH(5), /* instruction relocate */ \
41: dr:BIT_WIDTH(4), /* data relocate */ \
42: rsvd2:BITS_WIDTH(3,1), /* reserved */ \
43: psfr:BIT_WIDTH(0) /* 64 bit mode */
44:
45: /*
46: * Machine state register.
47: * Read and written via get_msr() and set_msr() inlines, below.
48: */
49: typedef struct {
50: unsigned rsvd3:BITS_WIDTH(31,16); // reserved
51: MSR_BITS; // see above
52: } msr_t;
53:
54: /*
55: * Data Storage Interrupt Status Register (DSISR)
56: */
57: typedef struct {
58: unsigned dse:BIT_WIDTH(31); // direct-store error
59: unsigned tnf:BIT_WIDTH(30); // translation not found
60: unsigned :BITS_WIDTH(29,28);
61: unsigned pe:BIT_WIDTH(27); // protection error
62: unsigned dsr:BIT_WIDTH(26); // lwarx/stwcx to direct-store
63: unsigned rw:BIT_WIDTH(25); // 1 => store, 0 => load
64: unsigned :BITS_WIDTH(24,23);
65: unsigned dab:BIT_WIDTH(22); // data address bkpt (601)
66: unsigned ssf:BIT_WIDTH(21); // seg table search failed
67: unsigned :BITS_WIDTH(20,0);
68: } dsisr_t;
69:
70: /*
71: * Instruction Storage Interrupt Status Register (really SRR1)
72: */
73: typedef struct {
74: unsigned :BIT_WIDTH(31);
75: unsigned tnf:BIT_WIDTH(30); // translation not found
76: unsigned :BIT_WIDTH(29);
77: unsigned dse:BIT_WIDTH(28); // direct-store fetch error
78: unsigned pe:BIT_WIDTH(27); // protection error
79: unsigned :BITS_WIDTH(26,22);
80: unsigned ssf:BIT_WIDTH(21); // seg table search failed
81: unsigned :BITS_WIDTH(20,16);
82: MSR_BITS;
83: } isisr_t;
84:
85: /*
86: * Alignment Interrupt Status Register (really DSISR)
87: * NOTE: bit numbers in field *names* are in IBM'ese (0 is MSB).
88: * FIXME: Yuck!!! Double Yuck!!!
89: */
90: typedef struct {
91: unsigned :BITS_WIDTH(31,20);
92: unsigned ds3031:BITS_WIDTH(19,18);// bits 30:31 if DS form
93: unsigned :BIT_WIDTH(17);
94: unsigned x2930:BITS_WIDTH(16,15); // bits 29:30 if X form
95: unsigned x25:BIT_WIDTH(14); // bit 25 if X form or
96: // bit 5 if D or DS form
97: unsigned x2124:BITS_WIDTH(13,10); // bits 21:24 if X form or
98: // bits 1:4 if D or DS form
99: unsigned all615:BITS_WIDTH(9,0); // bits 6:15 of instr
100: MSR_BITS;
101: } aisr_t;
102:
103: /*
104: * Program Interrupt Status Register (really SRR1)
105: */
106: typedef struct {
107: unsigned :BITS_WIDTH(31,21);
108: unsigned fpee:BIT_WIDTH(20); // floating pt enable exception
109: unsigned ill:BIT_WIDTH(19); // illegal instruction
110: unsigned priv:BIT_WIDTH(18); // privileged instruction
111: unsigned trap:BIT_WIDTH(17); // trap program interrupt
112: unsigned subseq:BIT_WIDTH(16); // 1 => SRR0 points to
113: // subsequent instruction
114: MSR_BITS;
115: } pisr_t;
116:
117: /*
118: * Condition register. May not be useful in C, let's see...
119: */
120: typedef struct {
121: unsigned lt:BIT_WIDTH(31), // negative
122: gt:BIT_WIDTH(30), // positive
123: eq:BIT_WIDTH(29), // equal to zero
124: so:BIT_WIDTH(28), // summary overflow
125: fx:BIT_WIDTH(27), // floating point exception
126: fex:BIT_WIDTH(26), // fp enabled exception
127: vx:BIT_WIDTH(25), // fp invalid operation
128: // exception
129: ox:BIT_WIDTH(24), // fp overflow exception
130: rsvd:BITS_WIDTH(23,0); // reserved
131: } cr_t;
132:
133: /*
134: * Program mode register.
135: * Read and written via get_prog_mode() and set_prog_mode() inlines, below.
136: *
137: * NOT SUPPORTED ON M98601
138: */
139: typedef struct {
140: unsigned rsvd1:BITS_WIDTH(31,12),
141: fe0:BIT_WIDTH(11),
142: rsvd2:BITS_WIDTH(10,9),
143: fe1:BIT_WIDTH(8),
144: rsvd3:BITS_WIDTH(7,1),
145: sf:BIT_WIDTH(0); // 64 bit mode
146: } prog_mode_t;
147:
148: /*
149: * Abstract values representing fe0:fe1.
150: * See get_fp_exc_mode(), below.
151: */
152: typedef enum {
153: FEM_IGNORE_EXCEP, // ignore exceptions
154: FEM_IMPR_NONREC, // imprecise nonrecoverable
155: FEM_IMPR_RECOV, // imprecise recoverable
156: FEM_PRECISE,
157: } fp_exc_mode_t;
158:
159:
160: /*
161: * Special purpose registers.
162: */
163:
164: /*
165: * Processor version register (special purpose register pvr).
166: */
167: typedef struct {
168: unsigned version:BITS_WIDTH(31,16),
169: revision:BITS_WIDTH(15,0);
170: } pvr_t;
171:
172: /*
173: * Fixed point exception register (special purpose register xer)
174: */
175: typedef struct {
176: unsigned so:BIT_WIDTH(31), // summary overflow
177: ov:BIT_WIDTH(30), // overflow
178: ca:BIT_WIDTH(29), // carry
179: rsvd1:BITS_WIDTH(28,16),// reserved
180: byte:BITS_WIDTH(15,8), // byte to be compared
181: rsvd2:BIT_WIDTH(7), // reserved
182: byte_count:BITS_WIDTH(6,0);
183: } xer_t;
184:
185: /*
186: * Inlines and macros to manipulate the above registers.
187: */
188:
189: /*
190: * Get/set machine state register.
191: */
192: static __inline__ msr_t
193: get_msr()
194: {
195: msr_t __msr_tmp;
196:
197: __asm__ volatile ("mfmsr %0 /* mfmsr */" \
198: : "=r" (__msr_tmp));
199: return __msr_tmp;
200: }
201:
202: static __inline__ void
203: set_msr(msr_t msr)
204: {
205: __asm__ volatile ("mtmsr %0 /* mtmsr */ " \
206: : : "r" (msr));
207: }
208:
209: /*
210: * Read/write program mode register.
211: *
212: * NOT SUPPORTED ON M98601
213: */
214: static __inline__ prog_mode_t
215: get_prog_mode()
216: {
217: prog_mode_t __pm_tmp;
218: __asm__ volatile ("mfpmr %0 /* mfpmr */" \
219: : "=r" (__pm_tmp));
220: return __pm_tmp;
221: }
222:
223: static __inline__ void
224: set_prog_mode(prog_mode_t prog_mode)
225: {
226: __asm__ volatile ("mtpmr %0; /* mtpmr */ " \
227: : : "r" (prog_mode));
228: }
229:
230:
231: /*
232: * Determine current fp_exc_mode_t given prog_mode.
233: */
234: static __inline__ fp_exc_mode_t
235: get_fp_exc_mode(prog_mode_t prog_mode)
236: {
237: if(prog_mode.fe0) {
238: return prog_mode.fe1 ? FEM_PRECISE : FEM_IMPR_RECOV;
239: }
240: else {
241: return prog_mode.fe1 ? FEM_IMPR_NONREC : FEM_IGNORE_EXCEP;
242: }
243: }
244:
245: /*
246: * Software definitions for special purpose registers.
247: * The same register is used as per_cpu data pointer and
248: * vector base register. This requires that the vector
249: * table be the first item in the per_cpu table.
250: */
251: #define SR_EXCEPTION_TMP_LR sprg0
252: #define SR_EXCEPTION_TMP_CR sprg1
253: #define SR_EXCEPTION_TMP_AT sprg2
254: #define SR_PER_CPU_DATA sprg3
255: #define SR_VBR sprg3
256:
257: /*
258: * Get/set special purpose registers.
259: *
260: * GET_SPR - get SPR by name.
261: *
262: * Example usage:
263: *
264: * {
265: * xer_t some_xer;
266: *
267: * some_xer = GET_SPR(xer_t, xer);
268: * ...
269: * }
270: *
271: * This is a strange one. We're creating a list of C expressions within
272: * a set of curlies; the last expression ("__spr_tmp;") is the return value
273: * of the statement created by the curlies.
274: *
275: * WARNING: The m88k version of this did not compile with -O2. Let's hope
276: * the 2.2.2 compiler fixes this.
277: */
278:
279: #define GET_SPR(type, spr) \
280: ({ \
281: unsigned __spr_tmp; \
282: __asm__ volatile ("mfspr %0, " STRINGIFY(spr) \
283: : "=r" (__spr_tmp)); \
284: *(type *)&__spr_tmp; \
285: })
286:
287: /*
288: * Example usage of SET_SPR:
289: *
290: * {
291: * xer_t some_xer;
292: *
293: * ...set up some_xer...
294: * SET_SPR(xer, some_xer);
295: * }
296: */
297: #define SET_SPR(spr, val) \
298: MACRO_BEGIN \
299: __typeof__ (val) __spr_tmp = (val); \
300: __asm__ volatile ("mtspr "STRINGIFY(spr) ", %0" \
301: : : "r" (__spr_tmp)); \
302: MACRO_END
303:
304: /*
305: * Fully synchronize instruction stream.
306: */
307: static __inline__ void
308: m98k_sync()
309: {
310: __asm__ volatile ("sync /* sync */" \
311: : : );
312: }
313:
314: #endif _ARCH_M98K_BASIC_REGS_H_
315:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.