]>
Commit | Line | Data |
---|---|---|
79aceca5 FB |
1 | /* |
2 | * PPC emulation cpu definitions for qemu. | |
3 | * | |
4 | * Copyright (c) 2003 Jocelyn Mayer | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2 of the License, or (at your option) any later version. | |
10 | * | |
11 | * This library is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with this library; if not, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | */ | |
20 | #if !defined (__CPU_PPC_H__) | |
21 | #define __CPU_PPC_H__ | |
22 | ||
23 | #include <endian.h> | |
24 | #include <asm/byteorder.h> | |
25 | ||
26 | #include "cpu-defs.h" | |
27 | ||
28 | /*** Sign extend constants ***/ | |
29 | /* 8 to 32 bits */ | |
30 | static inline int32_t s_ext8 (uint8_t value) | |
31 | { | |
32 | int8_t *tmp = &value; | |
33 | ||
34 | return *tmp; | |
35 | } | |
36 | ||
37 | /* 16 to 32 bits */ | |
38 | static inline int32_t s_ext16 (uint16_t value) | |
39 | { | |
40 | int16_t *tmp = &value; | |
41 | ||
42 | return *tmp; | |
43 | } | |
44 | ||
45 | /* 24 to 32 bits */ | |
46 | static inline int32_t s_ext24 (uint32_t value) | |
47 | { | |
48 | uint16_t utmp = (value >> 8) & 0xFFFF; | |
49 | int16_t *tmp = &utmp; | |
50 | ||
51 | return (*tmp << 8) | (value & 0xFF); | |
52 | } | |
53 | ||
54 | #include "config.h" | |
55 | #include <setjmp.h> | |
56 | ||
57 | /* Floting point status and control register */ | |
58 | #define FPSCR_FX 31 | |
59 | #define FPSCR_FEX 30 | |
60 | #define FPSCR_VX 29 | |
61 | #define FPSCR_OX 28 | |
62 | #define FPSCR_UX 27 | |
63 | #define FPSCR_ZX 26 | |
64 | #define FPSCR_XX 25 | |
65 | #define FPSCR_VXSNAN 24 | |
66 | #define FPSCR_VXISI 26 | |
67 | #define FPSCR_VXIDI 25 | |
68 | #define FPSCR_VXZDZ 21 | |
69 | #define FPSCR_VXIMZ 20 | |
70 | ||
71 | #define FPSCR_VXVC 18 | |
72 | #define FPSCR_FR 17 | |
73 | #define FPSCR_FI 16 | |
74 | #define FPSCR_FPRF 11 | |
75 | #define FPSCR_VXSOFT 9 | |
76 | #define FPSCR_VXSQRT 8 | |
77 | #define FPSCR_VXCVI 7 | |
78 | #define FPSCR_OE 6 | |
79 | #define FPSCR_UE 5 | |
80 | #define FPSCR_ZE 4 | |
81 | #define FPSCR_XE 3 | |
82 | #define FPSCR_NI 2 | |
83 | #define FPSCR_RN 0 | |
84 | #define fpscr_fx env->fpscr[FPSCR_FX] | |
85 | #define fpscr_fex env->fpscr[FPSCR_FEX] | |
86 | #define fpscr_vx env->fpscr[FPSCR_VX] | |
87 | #define fpscr_ox env->fpscr[FPSCR_OX] | |
88 | #define fpscr_ux env->fpscr[FPSCR_UX] | |
89 | #define fpscr_zx env->fpscr[FPSCR_ZX] | |
90 | #define fpscr_xx env->fpscr[FPSCR_XX] | |
91 | #define fpscr_vsxnan env->fpscr[FPSCR_VXSNAN] | |
92 | #define fpscr_vxisi env->fpscr[FPSCR_VXISI] | |
93 | #define fpscr_vxidi env->fpscr[FPSCR_VXIDI] | |
94 | #define fpscr_vxzdz env->fpscr[FPSCR_VXZDZ] | |
95 | #define fpscr_vximz env->fpscr[FPSCR_VXIMZ] | |
96 | #define fpscr_fr env->fpscr[FPSCR_FR] | |
97 | #define fpscr_fi env->fpscr[FPSCR_FI] | |
98 | #define fpscr_fprf env->fpscr[FPSCR_FPRF] | |
99 | #define fpscr_vxsoft env->fpscr[FPSCR_VXSOFT] | |
100 | #define fpscr_vxsqrt env->fpscr[FPSCR_VXSQRT] | |
101 | #define fpscr_oe env->fpscr[FPSCR_OE] | |
102 | #define fpscr_ue env->fpscr[FPSCR_UE] | |
103 | #define fpscr_ze env->fpscr[FPSCR_ZE] | |
104 | #define fpscr_xe env->fpscr[FPSCR_XE] | |
105 | #define fpscr_ni env->fpscr[FPSCR_NI] | |
106 | #define fpscr_rn env->fpscr[FPSCR_RN] | |
107 | ||
108 | /* Supervisor mode registers */ | |
109 | /* Machine state register */ | |
110 | #define MSR_POW 18 | |
111 | #define MSR_ILE 16 | |
112 | #define MSR_EE 15 | |
113 | #define MSR_PR 14 | |
114 | #define MSR_FP 13 | |
115 | #define MSR_ME 12 | |
116 | #define MSR_FE0 11 | |
117 | #define MSR_SE 10 | |
118 | #define MSR_BE 9 | |
119 | #define MSR_FE1 8 | |
120 | #define MSR_IP 6 | |
121 | #define MSR_IR 5 | |
122 | #define MSR_DR 4 | |
123 | #define MSR_RI 1 | |
124 | #define MSR_LE 0 | |
125 | #define msr_pow env->msr[MSR_POW] | |
126 | #define msr_ile env->msr[MSR_ILE] | |
127 | #define msr_ee env->msr[MSR_EE] | |
128 | #define msr_pr env->msr[MSR_PR] | |
129 | #define msr_fp env->msr[MSR_FP] | |
130 | #define msr_me env->msr[MSR_ME] | |
131 | #define msr_fe0 env->msr[MSR_FE0] | |
132 | #define msr_se env->msr[MSR_SE] | |
133 | #define msr_be env->msr[MSR_BE] | |
134 | #define msr_fe1 env->msr[MSR_FE1] | |
135 | #define msr_ip env->msr[MSR_IP] | |
136 | #define msr_ir env->msr[MSR_IR] | |
137 | #define msr_dr env->msr[MSR_DR] | |
138 | #define msr_ri env->msr[MSR_RI] | |
139 | #define msr_le env->msr[MSR_LE] | |
140 | ||
141 | /* Segment registers */ | |
142 | typedef struct ppc_sr_t { | |
143 | uint32_t t:1; | |
144 | uint32_t ks:1; | |
145 | uint32_t kp:1; | |
146 | uint32_t n:1; | |
147 | uint32_t res:4; | |
148 | uint32_t vsid:24; | |
149 | } ppc_sr_t; | |
150 | ||
151 | typedef struct CPUPPCState { | |
152 | /* general purpose registers */ | |
153 | uint32_t gpr[32]; | |
154 | /* floating point registers */ | |
155 | uint64_t fpr[32]; | |
156 | /* segment registers */ | |
157 | ppc_sr_t sr[16]; | |
158 | /* special purpose registers */ | |
159 | uint32_t spr[1024]; | |
160 | /* XER */ | |
161 | uint8_t xer[32]; | |
162 | /* Reservation address */ | |
163 | uint32_t reserve; | |
164 | /* machine state register */ | |
165 | uint8_t msr[32]; | |
166 | /* condition register */ | |
167 | uint8_t crf[8]; | |
168 | /* floating point status and control register */ | |
169 | uint8_t fpscr[32]; | |
170 | uint32_t nip; | |
171 | /* CPU exception code */ | |
172 | uint32_t exception; | |
173 | ||
174 | /* qemu dedicated */ | |
175 | int interrupt_request; | |
176 | jmp_buf jmp_env; | |
177 | int exception_index; | |
178 | int error_code; | |
179 | int user_mode_only; /* user mode only simulation */ | |
180 | struct TranslationBlock *current_tb; /* currently executing TB */ | |
181 | ||
182 | /* user data */ | |
183 | void *opaque; | |
184 | } CPUPPCState; | |
185 | ||
186 | CPUPPCState *cpu_ppc_init(void); | |
187 | int cpu_ppc_exec(CPUPPCState *s); | |
188 | void cpu_ppc_close(CPUPPCState *s); | |
189 | /* you can call this signal handler from your SIGBUS and SIGSEGV | |
190 | signal handlers to inform the virtual CPU of exceptions. non zero | |
191 | is returned if the signal was handled by the virtual CPU. */ | |
192 | struct siginfo; | |
193 | int cpu_ppc_signal_handler(int host_signum, struct siginfo *info, | |
194 | void *puc); | |
195 | ||
196 | void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags); | |
197 | ||
198 | #define TARGET_PAGE_BITS 12 | |
199 | #include "cpu-all.h" | |
200 | ||
201 | #define ugpr(n) (env->gpr[n]) | |
202 | #define fpr(n) (env->fpr[n]) | |
203 | ||
204 | #define SPR_ENCODE(sprn) \ | |
205 | (((sprn) >> 5) | (((sprn) & 0x1F) << 5)) | |
206 | ||
207 | /* User mode SPR */ | |
208 | #define spr(n) env->spr[n] | |
209 | //#define XER spr[1] | |
210 | #define XER env->xer | |
211 | #define XER_SO 31 | |
212 | #define XER_OV 30 | |
213 | #define XER_CA 29 | |
214 | #define XER_BC 0 | |
215 | #define xer_so env->xer[XER_SO] | |
216 | #define xer_ov env->xer[XER_OV] | |
217 | #define xer_ca env->xer[XER_CA] | |
218 | #define xer_bc env->xer[XER_BC] | |
219 | ||
220 | #define LR spr[SPR_ENCODE(8)] | |
221 | #define CTR spr[SPR_ENCODE(9)] | |
222 | /* VEA mode SPR */ | |
223 | #define V_TBL spr[SPR_ENCODE(268)] | |
224 | #define V_TBU spr[SPR_ENCODE(269)] | |
225 | /* supervisor mode SPR */ | |
226 | #define DSISR spr[SPR_ENCODE(18)] | |
227 | #define DAR spr[SPR_ENCODE(19)] | |
228 | #define DEC spr[SPR_ENCODE(22)] | |
229 | #define SDR1 spr[SPR_ENCODE(25)] | |
230 | typedef struct ppc_sdr1_t { | |
231 | uint32_t htaborg:16; | |
232 | uint32_t res:7; | |
233 | uint32_t htabmask:9; | |
234 | } ppc_sdr1_t; | |
235 | #define SRR0 spr[SPR_ENCODE(26)] | |
236 | #define SRR0_MASK 0xFFFFFFFC | |
237 | #define SRR1 spr[SPR_ENCODE(27)] | |
238 | #define SPRG0 spr[SPR_ENCODE(272)] | |
239 | #define SPRG1 spr[SPR_ENCODE(273)] | |
240 | #define SPRG2 spr[SPR_ENCODE(274)] | |
241 | #define SPRG3 spr[SPR_ENCODE(275)] | |
242 | #define EAR spr[SPR_ENCODE(282)] | |
243 | typedef struct ppc_ear_t { | |
244 | uint32_t e:1; | |
245 | uint32_t res:25; | |
246 | uint32_t rid:6; | |
247 | } ppc_ear_t; | |
248 | #define TBL spr[SPR_ENCODE(284)] | |
249 | #define TBU spr[SPR_ENCODE(285)] | |
250 | #define PVR spr[SPR_ENCODE(287)] | |
251 | typedef struct ppc_pvr_t { | |
252 | uint32_t version:16; | |
253 | uint32_t revision:16; | |
254 | } ppc_pvr_t; | |
255 | #define IBAT0U spr[SPR_ENCODE(528)] | |
256 | #define IBAT0L spr[SPR_ENCODE(529)] | |
257 | #define IBAT1U spr[SPR_ENCODE(530)] | |
258 | #define IBAT1L spr[SPR_ENCODE(531)] | |
259 | #define IBAT2U spr[SPR_ENCODE(532)] | |
260 | #define IBAT2L spr[SPR_ENCODE(533)] | |
261 | #define IBAT3U spr[SPR_ENCODE(534)] | |
262 | #define IBAT3L spr[SPR_ENCODE(535)] | |
263 | #define DBAT0U spr[SPR_ENCODE(536)] | |
264 | #define DBAT0L spr[SPR_ENCODE(537)] | |
265 | #define DBAT1U spr[SPR_ENCODE(538)] | |
266 | #define DBAT1L spr[SPR_ENCODE(539)] | |
267 | #define DBAT2U spr[SPR_ENCODE(540)] | |
268 | #define DBAT2L spr[SPR_ENCODE(541)] | |
269 | #define DBAT3U spr[SPR_ENCODE(542)] | |
270 | #define DBAT3L spr[SPR_ENCODE(543)] | |
271 | typedef struct ppc_ubat_t { | |
272 | uint32_t bepi:15; | |
273 | uint32_t res:4; | |
274 | uint32_t bl:11; | |
275 | uint32_t vs:1; | |
276 | uint32_t vp:1; | |
277 | } ppc_ubat_t; | |
278 | typedef struct ppc_lbat_t { | |
279 | uint32_t brpn:15; | |
280 | uint32_t res0:10; | |
281 | uint32_t w:1; | |
282 | uint32_t i:1; | |
283 | uint32_t m:1; | |
284 | uint32_t g:1; | |
285 | uint32_t res1:1; | |
286 | uint32_t pp:2; | |
287 | } ppc_lbat_t; | |
288 | #define DABR spr[SPR_ENCODE(1013)] | |
289 | #define DABR_MASK 0xFFFFFFF8 | |
290 | typedef struct ppc_dabr_t { | |
291 | uint32_t dab:29; | |
292 | uint32_t bt:1; | |
293 | uint32_t dw:1; | |
294 | uint32_t dr:1; | |
295 | } ppc_dabr_t; | |
296 | #define FPECR spr[SPR_ENCODE(1022)] | |
297 | #define PIR spr[SPR_ENCODE(1023)] | |
298 | ||
299 | #define TARGET_PAGE_BITS 12 | |
300 | #include "cpu-all.h" | |
301 | ||
302 | CPUPPCState *cpu_ppc_init(void); | |
303 | int cpu_ppc_exec(CPUPPCState *s); | |
304 | void cpu_ppc_close(CPUPPCState *s); | |
305 | void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags); | |
306 | ||
307 | /* Exeptions */ | |
308 | enum { | |
309 | EXCP_NONE = 0x00, | |
310 | /* PPC hardware exceptions : exception vector / 0x100 */ | |
311 | EXCP_RESET = 0x01, /* System reset */ | |
312 | EXCP_MACHINE_CHECK = 0x02, /* Machine check exception */ | |
313 | EXCP_DSI = 0x03, /* Impossible memory access */ | |
314 | EXCP_ISI = 0x04, /* Impossible instruction fetch */ | |
315 | EXCP_EXTERNAL = 0x05, /* External interruption */ | |
316 | EXCP_ALIGN = 0x06, /* Alignment exception */ | |
317 | EXCP_PROGRAM = 0x07, /* Program exception */ | |
318 | EXCP_NO_FP = 0x08, /* No floating point */ | |
319 | EXCP_DECR = 0x09, /* Decrementer exception */ | |
320 | EXCP_RESA = 0x0A, /* Implementation specific */ | |
321 | EXCP_RESB = 0x0B, /* Implementation specific */ | |
322 | EXCP_SYSCALL = 0x0C, /* System call */ | |
323 | EXCP_TRACE = 0x0D, /* Trace exception (optional) */ | |
324 | EXCP_FP_ASSIST = 0x0E, /* Floating-point assist (optional) */ | |
325 | #if 0 | |
326 | /* Exeption subtypes for EXCP_DSI */ | |
327 | EXCP_DSI_TRANSLATE = 0x10301, /* Data address can't be translated */ | |
328 | EXCP_DSI_NOTSUP = 0x10302, /* Access type not supported */ | |
329 | EXCP_DSI_PROT = 0x10303, /* Memory protection violation */ | |
330 | EXCP_DSI_EXTERNAL = 0x10304, /* External access disabled */ | |
331 | EXCP_DSI_DABR = 0x10305, /* Data address breakpoint */ | |
332 | /* Exeption subtypes for EXCP_ISI */ | |
333 | EXCP_ISI_TRANSLATE = 0x10401, /* Code address can't be translated */ | |
334 | EXCP_ISI_NOTSUP = 0x10402, /* Access type not supported */ | |
335 | EXCP_ISI_PROT = 0x10403, /* Memory protection violation */ | |
336 | EXCP_ISI_GUARD = 0x10404, /* Fetch into guarded memory */ | |
337 | /* Exeption subtypes for EXCP_ALIGN */ | |
338 | EXCP_ALIGN_FP = 0x10601, /* FP alignment exception */ | |
339 | EXCP_ALIGN_LST = 0x10602, /* Unaligned memory load/store */ | |
340 | EXCP_ALIGN_LE = 0x10603, /* Unaligned little-endian access */ | |
341 | EXCP_ALIGN_PROT = 0x10604, /* Access cross protection boundary */ | |
342 | EXCP_ALIGN_BAT = 0x10605, /* Access cross a BAT/seg boundary */ | |
343 | EXCP_ALIGN_CACHE = 0x10606, /* Impossible dcbz access */ | |
344 | /* Exeption subtypes for EXCP_PROGRAM */ | |
345 | /* FP exceptions */ | |
346 | EXCP_FP_OX = 0x10701, /* FP overflow */ | |
347 | EXCP_FP_UX = 0x10702, /* FP underflow */ | |
348 | EXCP_FP_ZX = 0x10703, /* FP divide by zero */ | |
349 | EXCP_FP_XX = 0x10704, /* FP inexact */ | |
350 | EXCP_FP_VXNAN = 0x10705, /* FP invalid SNaN op */ | |
351 | EXCP_FP_VXISI = 0x10706, /* FP invalid infinite substraction */ | |
352 | EXCP_FP_VXIDI = 0x10707, /* FP invalid infinite divide */ | |
353 | EXCP_FP_VXZDZ = 0x10708, /* FP invalid zero divide */ | |
354 | EXCP_FP_VXIMZ = 0x10709, /* FP invalid infinite * zero */ | |
355 | EXCP_FP_VXVC = 0x1070A, /* FP invalid compare */ | |
356 | EXCP_FP_VXSOFT = 0x1070B, /* FP invalid operation */ | |
357 | EXCP_FP_VXSQRT = 0x1070C, /* FP invalid square root */ | |
358 | EXCP_FP_VXCVI = 0x1070D, /* FP invalid integer conversion */ | |
359 | /* Invalid instruction */ | |
360 | EXCP_INVAL_INVAL = 0x10711, /* Invalid instruction */ | |
361 | EXCP_INVAL_LSWX = 0x10712, /* Invalid lswx instruction */ | |
362 | EXCP_INVAL_SPR = 0x10713, /* Invalid SPR access */ | |
363 | EXCP_INVAL_FP = 0x10714, /* Unimplemented mandatory fp instr */ | |
364 | #endif | |
365 | EXCP_INVAL = 0x70, /* Invalid instruction */ | |
366 | /* Privileged instruction */ | |
367 | EXCP_PRIV = 0x71, /* Privileged instruction */ | |
368 | /* Trap */ | |
369 | EXCP_TRAP = 0x72, /* Trap */ | |
370 | /* Special cases where we want to stop translation */ | |
371 | EXCP_MTMSR = 0x103, /* mtmsr instruction: */ | |
372 | /* may change privilege level */ | |
373 | EXCP_BRANCH = 0x104, /* branch instruction */ | |
374 | }; | |
375 | ||
376 | /* | |
377 | * We need to put in some extra aux table entries to tell glibc what | |
378 | * the cache block size is, so it can use the dcbz instruction safely. | |
379 | */ | |
380 | #define AT_DCACHEBSIZE 19 | |
381 | #define AT_ICACHEBSIZE 20 | |
382 | #define AT_UCACHEBSIZE 21 | |
383 | /* A special ignored type value for PPC, for glibc compatibility. */ | |
384 | #define AT_IGNOREPPC 22 | |
385 | /* | |
386 | * The requirements here are: | |
387 | * - keep the final alignment of sp (sp & 0xf) | |
388 | * - make sure the 32-bit value at the first 16 byte aligned position of | |
389 | * AUXV is greater than 16 for glibc compatibility. | |
390 | * AT_IGNOREPPC is used for that. | |
391 | * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, | |
392 | * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. | |
393 | */ | |
394 | #define DLINFO_ARCH_ITEMS 3 | |
395 | #define ARCH_DLINFO \ | |
396 | do { \ | |
397 | /* \ | |
398 | * Now handle glibc compatibility. \ | |
399 | */ \ | |
400 | NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ | |
401 | NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ | |
402 | \ | |
403 | NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \ | |
404 | NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \ | |
405 | NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ | |
406 | } while (0) | |
407 | #endif /* !defined (__CPU_PPC_H__) */ |