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