Add quotes missing from previous patch.
[qemu/mini2440.git] / target-ppc / translate_init.c
blob012c34f73dbbebb0d619ee1daa2cf174861a23d4
1 /*
2 * PowerPC CPU initialization for qemu.
3 *
4 * Copyright (c) 2003-2005 Jocelyn Mayer
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.
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.
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
21 /* A lot of PowerPC definition have been included here.
22 * Most of them are not usable for now but have been kept
23 * inside "#if defined(TODO) ... #endif" statements to make tests easier.
26 //#define PPC_DUMP_CPU
27 //#define PPC_DEBUG_SPR
29 struct ppc_def_t {
30 const unsigned char *name;
31 uint32_t pvr;
32 uint32_t pvr_mask;
33 uint32_t insns_flags;
34 uint32_t flags;
35 uint64_t msr_mask;
38 /* Generic callbacks:
39 * do nothing but store/retrieve spr value
41 static void spr_read_generic (void *opaque, int sprn)
43 gen_op_load_spr(sprn);
46 static void spr_write_generic (void *opaque, int sprn)
48 gen_op_store_spr(sprn);
51 /* SPR common to all PPC */
52 /* XER */
53 static void spr_read_xer (void *opaque, int sprn)
55 gen_op_load_xer();
58 static void spr_write_xer (void *opaque, int sprn)
60 gen_op_store_xer();
63 /* LR */
64 static void spr_read_lr (void *opaque, int sprn)
66 gen_op_load_lr();
69 static void spr_write_lr (void *opaque, int sprn)
71 gen_op_store_lr();
74 /* CTR */
75 static void spr_read_ctr (void *opaque, int sprn)
77 gen_op_load_ctr();
80 static void spr_write_ctr (void *opaque, int sprn)
82 gen_op_store_ctr();
85 /* User read access to SPR */
86 /* USPRx */
87 /* UMMCRx */
88 /* UPMCx */
89 /* USIA */
90 /* UDECR */
91 static void spr_read_ureg (void *opaque, int sprn)
93 gen_op_load_spr(sprn + 0x10);
96 /* SPR common to all non-embedded PPC (ie not 4xx) */
97 /* DECR */
98 static void spr_read_decr (void *opaque, int sprn)
100 gen_op_load_decr();
103 static void spr_write_decr (void *opaque, int sprn)
105 gen_op_store_decr();
108 /* SPR common to all non-embedded PPC, except 601 */
109 /* Time base */
110 static void spr_read_tbl (void *opaque, int sprn)
112 gen_op_load_tbl();
115 static void spr_write_tbl (void *opaque, int sprn)
117 gen_op_store_tbl();
120 static void spr_read_tbu (void *opaque, int sprn)
122 gen_op_load_tbu();
125 static void spr_write_tbu (void *opaque, int sprn)
127 gen_op_store_tbu();
130 /* IBAT0U...IBAT0U */
131 /* IBAT0L...IBAT7L */
132 static void spr_read_ibat (void *opaque, int sprn)
134 gen_op_load_ibat(sprn & 1, (sprn - SPR_IBAT0U) / 2);
137 static void spr_read_ibat_h (void *opaque, int sprn)
139 gen_op_load_ibat(sprn & 1, (sprn - SPR_IBAT4U) / 2);
142 static void spr_write_ibatu (void *opaque, int sprn)
144 DisasContext *ctx = opaque;
146 gen_op_store_ibatu((sprn - SPR_IBAT0U) / 2);
147 RET_STOP(ctx);
150 static void spr_write_ibatu_h (void *opaque, int sprn)
152 DisasContext *ctx = opaque;
154 gen_op_store_ibatu((sprn - SPR_IBAT4U) / 2);
155 RET_STOP(ctx);
158 static void spr_write_ibatl (void *opaque, int sprn)
160 DisasContext *ctx = opaque;
162 gen_op_store_ibatl((sprn - SPR_IBAT0L) / 2);
163 RET_STOP(ctx);
166 static void spr_write_ibatl_h (void *opaque, int sprn)
168 DisasContext *ctx = opaque;
170 gen_op_store_ibatl((sprn - SPR_IBAT4L) / 2);
171 RET_STOP(ctx);
174 /* DBAT0U...DBAT7U */
175 /* DBAT0L...DBAT7L */
176 static void spr_read_dbat (void *opaque, int sprn)
178 gen_op_load_dbat(sprn & 1, (sprn - SPR_DBAT0U) / 2);
181 static void spr_read_dbat_h (void *opaque, int sprn)
183 gen_op_load_dbat(sprn & 1, (sprn - SPR_DBAT4U) / 2);
186 static void spr_write_dbatu (void *opaque, int sprn)
188 DisasContext *ctx = opaque;
190 gen_op_store_dbatu((sprn - SPR_DBAT0U) / 2);
191 RET_STOP(ctx);
194 static void spr_write_dbatu_h (void *opaque, int sprn)
196 DisasContext *ctx = opaque;
198 gen_op_store_dbatu((sprn - SPR_DBAT4U) / 2);
199 RET_STOP(ctx);
202 static void spr_write_dbatl (void *opaque, int sprn)
204 DisasContext *ctx = opaque;
206 gen_op_store_dbatl((sprn - SPR_DBAT0L) / 2);
207 RET_STOP(ctx);
210 static void spr_write_dbatl_h (void *opaque, int sprn)
212 DisasContext *ctx = opaque;
214 gen_op_store_dbatl((sprn - SPR_DBAT4L) / 2);
215 RET_STOP(ctx);
218 /* SDR1 */
219 static void spr_read_sdr1 (void *opaque, int sprn)
221 gen_op_load_sdr1();
224 static void spr_write_sdr1 (void *opaque, int sprn)
226 DisasContext *ctx = opaque;
228 gen_op_store_sdr1();
229 RET_STOP(ctx);
232 static void spr_write_pir (void *opaque, int sprn)
234 gen_op_store_pir();
237 static inline void spr_register (CPUPPCState *env, int num,
238 const unsigned char *name,
239 void (*uea_read)(void *opaque, int sprn),
240 void (*uea_write)(void *opaque, int sprn),
241 void (*oea_read)(void *opaque, int sprn),
242 void (*oea_write)(void *opaque, int sprn),
243 target_ulong initial_value)
245 ppc_spr_t *spr;
247 spr = &env->spr_cb[num];
248 if (spr->name != NULL ||env-> spr[num] != 0x00000000 ||
249 spr->uea_read != NULL || spr->uea_write != NULL ||
250 spr->oea_read != NULL || spr->oea_write != NULL) {
251 printf("Error: Trying to register SPR %d (%03x) twice !\n", num, num);
252 exit(1);
254 #if defined(PPC_DEBUG_SPR)
255 printf("*** register spr %d (%03x) %s val %08llx\n", num, num, name,
256 (unsigned long long)initial_value);
257 #endif
258 spr->name = name;
259 spr->uea_read = uea_read;
260 spr->uea_write = uea_write;
261 spr->oea_read = oea_read;
262 spr->oea_write = oea_write;
263 env->spr[num] = initial_value;
266 /* Generic PowerPC SPRs */
267 static void gen_spr_generic (CPUPPCState *env)
269 /* Integer processing */
270 spr_register(env, SPR_XER, "XER",
271 &spr_read_xer, &spr_write_xer,
272 &spr_read_xer, &spr_write_xer,
273 0x00000000);
274 /* Branch contol */
275 spr_register(env, SPR_LR, "LR",
276 &spr_read_lr, &spr_write_lr,
277 &spr_read_lr, &spr_write_lr,
278 0x00000000);
279 spr_register(env, SPR_CTR, "CTR",
280 &spr_read_ctr, &spr_write_ctr,
281 &spr_read_ctr, &spr_write_ctr,
282 0x00000000);
283 /* Interrupt processing */
284 spr_register(env, SPR_SRR0, "SRR0",
285 SPR_NOACCESS, SPR_NOACCESS,
286 &spr_read_generic, &spr_write_generic,
287 0x00000000);
288 spr_register(env, SPR_SRR1, "SRR1",
289 SPR_NOACCESS, SPR_NOACCESS,
290 &spr_read_generic, &spr_write_generic,
291 0x00000000);
292 /* Processor control */
293 spr_register(env, SPR_SPRG0, "SPRG0",
294 SPR_NOACCESS, SPR_NOACCESS,
295 &spr_read_generic, &spr_write_generic,
296 0x00000000);
297 spr_register(env, SPR_SPRG1, "SPRG1",
298 SPR_NOACCESS, SPR_NOACCESS,
299 &spr_read_generic, &spr_write_generic,
300 0x00000000);
301 spr_register(env, SPR_SPRG2, "SPRG2",
302 SPR_NOACCESS, SPR_NOACCESS,
303 &spr_read_generic, &spr_write_generic,
304 0x00000000);
305 spr_register(env, SPR_SPRG3, "SPRG3",
306 SPR_NOACCESS, SPR_NOACCESS,
307 &spr_read_generic, &spr_write_generic,
308 0x00000000);
311 /* SPR common to all non-embedded PowerPC, including 601 */
312 static void gen_spr_ne_601 (CPUPPCState *env)
314 /* Exception processing */
315 spr_register(env, SPR_DSISR, "DSISR",
316 SPR_NOACCESS, SPR_NOACCESS,
317 &spr_read_generic, &spr_write_generic,
318 0x00000000);
319 spr_register(env, SPR_DAR, "DAR",
320 SPR_NOACCESS, SPR_NOACCESS,
321 &spr_read_generic, &spr_write_generic,
322 0x00000000);
323 /* Timer */
324 spr_register(env, SPR_DECR, "DECR",
325 SPR_NOACCESS, SPR_NOACCESS,
326 &spr_read_decr, &spr_write_decr,
327 0x00000000);
328 /* Memory management */
329 spr_register(env, SPR_SDR1, "SDR1",
330 SPR_NOACCESS, SPR_NOACCESS,
331 &spr_read_sdr1, &spr_write_sdr1,
332 0x00000000);
335 /* BATs 0-3 */
336 static void gen_low_BATs (CPUPPCState *env)
338 spr_register(env, SPR_IBAT0U, "IBAT0U",
339 SPR_NOACCESS, SPR_NOACCESS,
340 &spr_read_ibat, &spr_write_ibatu,
341 0x00000000);
342 spr_register(env, SPR_IBAT0L, "IBAT0L",
343 SPR_NOACCESS, SPR_NOACCESS,
344 &spr_read_ibat, &spr_write_ibatl,
345 0x00000000);
346 spr_register(env, SPR_IBAT1U, "IBAT1U",
347 SPR_NOACCESS, SPR_NOACCESS,
348 &spr_read_ibat, &spr_write_ibatu,
349 0x00000000);
350 spr_register(env, SPR_IBAT1L, "IBAT1L",
351 SPR_NOACCESS, SPR_NOACCESS,
352 &spr_read_ibat, &spr_write_ibatl,
353 0x00000000);
354 spr_register(env, SPR_IBAT2U, "IBAT2U",
355 SPR_NOACCESS, SPR_NOACCESS,
356 &spr_read_ibat, &spr_write_ibatu,
357 0x00000000);
358 spr_register(env, SPR_IBAT2L, "IBAT2L",
359 SPR_NOACCESS, SPR_NOACCESS,
360 &spr_read_ibat, &spr_write_ibatl,
361 0x00000000);
362 spr_register(env, SPR_IBAT3U, "IBAT3U",
363 SPR_NOACCESS, SPR_NOACCESS,
364 &spr_read_ibat, &spr_write_ibatu,
365 0x00000000);
366 spr_register(env, SPR_IBAT3L, "IBAT3L",
367 SPR_NOACCESS, SPR_NOACCESS,
368 &spr_read_ibat, &spr_write_ibatl,
369 0x00000000);
370 spr_register(env, SPR_DBAT0U, "DBAT0U",
371 SPR_NOACCESS, SPR_NOACCESS,
372 &spr_read_dbat, &spr_write_dbatu,
373 0x00000000);
374 spr_register(env, SPR_DBAT0L, "DBAT0L",
375 SPR_NOACCESS, SPR_NOACCESS,
376 &spr_read_dbat, &spr_write_dbatl,
377 0x00000000);
378 spr_register(env, SPR_DBAT1U, "DBAT1U",
379 SPR_NOACCESS, SPR_NOACCESS,
380 &spr_read_dbat, &spr_write_dbatu,
381 0x00000000);
382 spr_register(env, SPR_DBAT1L, "DBAT1L",
383 SPR_NOACCESS, SPR_NOACCESS,
384 &spr_read_dbat, &spr_write_dbatl,
385 0x00000000);
386 spr_register(env, SPR_DBAT2U, "DBAT2U",
387 SPR_NOACCESS, SPR_NOACCESS,
388 &spr_read_dbat, &spr_write_dbatu,
389 0x00000000);
390 spr_register(env, SPR_DBAT2L, "DBAT2L",
391 SPR_NOACCESS, SPR_NOACCESS,
392 &spr_read_dbat, &spr_write_dbatl,
393 0x00000000);
394 spr_register(env, SPR_DBAT3U, "DBAT3U",
395 SPR_NOACCESS, SPR_NOACCESS,
396 &spr_read_dbat, &spr_write_dbatu,
397 0x00000000);
398 spr_register(env, SPR_DBAT3L, "DBAT3L",
399 SPR_NOACCESS, SPR_NOACCESS,
400 &spr_read_dbat, &spr_write_dbatl,
401 0x00000000);
402 env->nb_BATs = 4;
405 /* BATs 4-7 */
406 static void gen_high_BATs (CPUPPCState *env)
408 spr_register(env, SPR_IBAT4U, "IBAT4U",
409 SPR_NOACCESS, SPR_NOACCESS,
410 &spr_read_ibat_h, &spr_write_ibatu_h,
411 0x00000000);
412 spr_register(env, SPR_IBAT4L, "IBAT4L",
413 SPR_NOACCESS, SPR_NOACCESS,
414 &spr_read_ibat_h, &spr_write_ibatl_h,
415 0x00000000);
416 spr_register(env, SPR_IBAT5U, "IBAT5U",
417 SPR_NOACCESS, SPR_NOACCESS,
418 &spr_read_ibat_h, &spr_write_ibatu_h,
419 0x00000000);
420 spr_register(env, SPR_IBAT5L, "IBAT5L",
421 SPR_NOACCESS, SPR_NOACCESS,
422 &spr_read_ibat_h, &spr_write_ibatl_h,
423 0x00000000);
424 spr_register(env, SPR_IBAT6U, "IBAT6U",
425 SPR_NOACCESS, SPR_NOACCESS,
426 &spr_read_ibat_h, &spr_write_ibatu_h,
427 0x00000000);
428 spr_register(env, SPR_IBAT6L, "IBAT6L",
429 SPR_NOACCESS, SPR_NOACCESS,
430 &spr_read_ibat_h, &spr_write_ibatl_h,
431 0x00000000);
432 spr_register(env, SPR_IBAT7U, "IBAT7U",
433 SPR_NOACCESS, SPR_NOACCESS,
434 &spr_read_ibat_h, &spr_write_ibatu_h,
435 0x00000000);
436 spr_register(env, SPR_IBAT7L, "IBAT7L",
437 SPR_NOACCESS, SPR_NOACCESS,
438 &spr_read_ibat_h, &spr_write_ibatl_h,
439 0x00000000);
440 spr_register(env, SPR_DBAT4U, "DBAT4U",
441 SPR_NOACCESS, SPR_NOACCESS,
442 &spr_read_dbat_h, &spr_write_dbatu_h,
443 0x00000000);
444 spr_register(env, SPR_DBAT4L, "DBAT4L",
445 SPR_NOACCESS, SPR_NOACCESS,
446 &spr_read_dbat_h, &spr_write_dbatl_h,
447 0x00000000);
448 spr_register(env, SPR_DBAT5U, "DBAT5U",
449 SPR_NOACCESS, SPR_NOACCESS,
450 &spr_read_dbat_h, &spr_write_dbatu_h,
451 0x00000000);
452 spr_register(env, SPR_DBAT5L, "DBAT5L",
453 SPR_NOACCESS, SPR_NOACCESS,
454 &spr_read_dbat_h, &spr_write_dbatl_h,
455 0x00000000);
456 spr_register(env, SPR_DBAT6U, "DBAT6U",
457 SPR_NOACCESS, SPR_NOACCESS,
458 &spr_read_dbat_h, &spr_write_dbatu_h,
459 0x00000000);
460 spr_register(env, SPR_DBAT6L, "DBAT6L",
461 SPR_NOACCESS, SPR_NOACCESS,
462 &spr_read_dbat_h, &spr_write_dbatl_h,
463 0x00000000);
464 spr_register(env, SPR_DBAT7U, "DBAT7U",
465 SPR_NOACCESS, SPR_NOACCESS,
466 &spr_read_dbat_h, &spr_write_dbatu_h,
467 0x00000000);
468 spr_register(env, SPR_DBAT7L, "DBAT7L",
469 SPR_NOACCESS, SPR_NOACCESS,
470 &spr_read_dbat_h, &spr_write_dbatl_h,
471 0x00000000);
472 env->nb_BATs = 8;
475 /* Generic PowerPC time base */
476 static void gen_tbl (CPUPPCState *env)
478 spr_register(env, SPR_VTBL, "TBL",
479 &spr_read_tbl, SPR_NOACCESS,
480 &spr_read_tbl, SPR_NOACCESS,
481 0x00000000);
482 spr_register(env, SPR_TBL, "TBL",
483 SPR_NOACCESS, SPR_NOACCESS,
484 SPR_NOACCESS, &spr_write_tbl,
485 0x00000000);
486 spr_register(env, SPR_VTBU, "TBU",
487 &spr_read_tbu, SPR_NOACCESS,
488 &spr_read_tbu, SPR_NOACCESS,
489 0x00000000);
490 spr_register(env, SPR_TBU, "TBU",
491 SPR_NOACCESS, SPR_NOACCESS,
492 SPR_NOACCESS, &spr_write_tbu,
493 0x00000000);
496 /* SPR common to all 7xx PowerPC implementations */
497 static void gen_spr_7xx (CPUPPCState *env)
499 /* Breakpoints */
500 /* XXX : not implemented */
501 spr_register(env, SPR_DABR, "DABR",
502 SPR_NOACCESS, SPR_NOACCESS,
503 &spr_read_generic, &spr_write_generic,
504 0x00000000);
505 /* XXX : not implemented */
506 spr_register(env, SPR_IABR, "IABR",
507 SPR_NOACCESS, SPR_NOACCESS,
508 &spr_read_generic, &spr_write_generic,
509 0x00000000);
510 /* Cache management */
511 /* XXX : not implemented */
512 spr_register(env, SPR_ICTC, "ICTC",
513 SPR_NOACCESS, SPR_NOACCESS,
514 &spr_read_generic, &spr_write_generic,
515 0x00000000);
516 /* Performance monitors */
517 /* XXX : not implemented */
518 spr_register(env, SPR_MMCR0, "MMCR0",
519 SPR_NOACCESS, SPR_NOACCESS,
520 &spr_read_generic, &spr_write_generic,
521 0x00000000);
522 /* XXX : not implemented */
523 spr_register(env, SPR_MMCR1, "MMCR1",
524 SPR_NOACCESS, SPR_NOACCESS,
525 &spr_read_generic, &spr_write_generic,
526 0x00000000);
527 /* XXX : not implemented */
528 spr_register(env, SPR_PMC1, "PMC1",
529 SPR_NOACCESS, SPR_NOACCESS,
530 &spr_read_generic, &spr_write_generic,
531 0x00000000);
532 /* XXX : not implemented */
533 spr_register(env, SPR_PMC2, "PMC2",
534 SPR_NOACCESS, SPR_NOACCESS,
535 &spr_read_generic, &spr_write_generic,
536 0x00000000);
537 /* XXX : not implemented */
538 spr_register(env, SPR_PMC3, "PMC3",
539 SPR_NOACCESS, SPR_NOACCESS,
540 &spr_read_generic, &spr_write_generic,
541 0x00000000);
542 /* XXX : not implemented */
543 spr_register(env, SPR_PMC4, "PMC4",
544 SPR_NOACCESS, SPR_NOACCESS,
545 &spr_read_generic, &spr_write_generic,
546 0x00000000);
547 /* XXX : not implemented */
548 spr_register(env, SPR_SIA, "SIA",
549 SPR_NOACCESS, SPR_NOACCESS,
550 &spr_read_generic, SPR_NOACCESS,
551 0x00000000);
552 spr_register(env, SPR_UMMCR0, "UMMCR0",
553 &spr_read_ureg, SPR_NOACCESS,
554 &spr_read_ureg, SPR_NOACCESS,
555 0x00000000);
556 spr_register(env, SPR_UMMCR1, "UMMCR1",
557 &spr_read_ureg, SPR_NOACCESS,
558 &spr_read_ureg, SPR_NOACCESS,
559 0x00000000);
560 spr_register(env, SPR_UPMC1, "UPMC1",
561 &spr_read_ureg, SPR_NOACCESS,
562 &spr_read_ureg, SPR_NOACCESS,
563 0x00000000);
564 spr_register(env, SPR_UPMC2, "UPMC2",
565 &spr_read_ureg, SPR_NOACCESS,
566 &spr_read_ureg, SPR_NOACCESS,
567 0x00000000);
568 spr_register(env, SPR_UPMC3, "UPMC3",
569 &spr_read_ureg, SPR_NOACCESS,
570 &spr_read_ureg, SPR_NOACCESS,
571 0x00000000);
572 spr_register(env, SPR_UPMC4, "UPMC4",
573 &spr_read_ureg, SPR_NOACCESS,
574 &spr_read_ureg, SPR_NOACCESS,
575 0x00000000);
576 spr_register(env, SPR_USIA, "USIA",
577 &spr_read_ureg, SPR_NOACCESS,
578 &spr_read_ureg, SPR_NOACCESS,
579 0x00000000);
580 /* Thermal management */
581 /* XXX : not implemented */
582 spr_register(env, SPR_THRM1, "THRM1",
583 SPR_NOACCESS, SPR_NOACCESS,
584 &spr_read_generic, &spr_write_generic,
585 0x00000000);
586 /* XXX : not implemented */
587 spr_register(env, SPR_THRM2, "THRM2",
588 SPR_NOACCESS, SPR_NOACCESS,
589 &spr_read_generic, &spr_write_generic,
590 0x00000000);
591 /* XXX : not implemented */
592 spr_register(env, SPR_THRM3, "THRM3",
593 SPR_NOACCESS, SPR_NOACCESS,
594 &spr_read_generic, &spr_write_generic,
595 0x00000000);
596 /* External access control */
597 /* XXX : not implemented */
598 spr_register(env, SPR_EAR, "EAR",
599 SPR_NOACCESS, SPR_NOACCESS,
600 &spr_read_generic, &spr_write_generic,
601 0x00000000);
604 /* SPR specific to PowerPC 604 implementation */
605 static void gen_spr_604 (CPUPPCState *env)
607 /* Processor identification */
608 spr_register(env, SPR_PIR, "PIR",
609 SPR_NOACCESS, SPR_NOACCESS,
610 &spr_read_generic, &spr_write_pir,
611 0x00000000);
612 /* Breakpoints */
613 /* XXX : not implemented */
614 spr_register(env, SPR_IABR, "IABR",
615 SPR_NOACCESS, SPR_NOACCESS,
616 &spr_read_generic, &spr_write_generic,
617 0x00000000);
618 /* XXX : not implemented */
619 spr_register(env, SPR_DABR, "DABR",
620 SPR_NOACCESS, SPR_NOACCESS,
621 &spr_read_generic, &spr_write_generic,
622 0x00000000);
623 /* Performance counters */
624 /* XXX : not implemented */
625 spr_register(env, SPR_MMCR0, "MMCR0",
626 SPR_NOACCESS, SPR_NOACCESS,
627 &spr_read_generic, &spr_write_generic,
628 0x00000000);
629 /* XXX : not implemented */
630 spr_register(env, SPR_MMCR1, "MMCR1",
631 SPR_NOACCESS, SPR_NOACCESS,
632 &spr_read_generic, &spr_write_generic,
633 0x00000000);
634 /* XXX : not implemented */
635 spr_register(env, SPR_PMC1, "PMC1",
636 SPR_NOACCESS, SPR_NOACCESS,
637 &spr_read_generic, &spr_write_generic,
638 0x00000000);
639 /* XXX : not implemented */
640 spr_register(env, SPR_PMC2, "PMC2",
641 SPR_NOACCESS, SPR_NOACCESS,
642 &spr_read_generic, &spr_write_generic,
643 0x00000000);
644 /* XXX : not implemented */
645 spr_register(env, SPR_PMC3, "PMC3",
646 SPR_NOACCESS, SPR_NOACCESS,
647 &spr_read_generic, &spr_write_generic,
648 0x00000000);
649 /* XXX : not implemented */
650 spr_register(env, SPR_PMC4, "PMC4",
651 SPR_NOACCESS, SPR_NOACCESS,
652 &spr_read_generic, &spr_write_generic,
653 0x00000000);
654 /* XXX : not implemented */
655 spr_register(env, SPR_SIA, "SIA",
656 SPR_NOACCESS, SPR_NOACCESS,
657 &spr_read_generic, SPR_NOACCESS,
658 0x00000000);
659 /* XXX : not implemented */
660 spr_register(env, SPR_SDA, "SDA",
661 SPR_NOACCESS, SPR_NOACCESS,
662 &spr_read_generic, SPR_NOACCESS,
663 0x00000000);
664 /* External access control */
665 /* XXX : not implemented */
666 spr_register(env, SPR_EAR, "EAR",
667 SPR_NOACCESS, SPR_NOACCESS,
668 &spr_read_generic, &spr_write_generic,
669 0x00000000);
672 // XXX: TODO (64 bits PPC sprs)
674 * ASR => SPR 280 (64 bits)
675 * FPECR => SPR 1022 (?)
676 * VRSAVE => SPR 256 (Altivec)
677 * SCOMC => SPR 276 (64 bits ?)
678 * SCOMD => SPR 277 (64 bits ?)
679 * HSPRG0 => SPR 304 (hypervisor)
680 * HSPRG1 => SPR 305 (hypervisor)
681 * HDEC => SPR 310 (hypervisor)
682 * HIOR => SPR 311 (hypervisor)
683 * RMOR => SPR 312 (970)
684 * HRMOR => SPR 313 (hypervisor)
685 * HSRR0 => SPR 314 (hypervisor)
686 * HSRR1 => SPR 315 (hypervisor)
687 * LPCR => SPR 316 (970)
688 * LPIDR => SPR 317 (970)
689 * ... and more (thermal management, performance counters, ...)
692 static void init_ppc_proc (CPUPPCState *env, ppc_def_t *def)
694 /* Default MMU definitions */
695 env->nb_BATs = -1;
696 env->nb_tlb = 0;
697 env->nb_ways = 0;
698 /* XXX: missing:
699 * 32 bits PPC:
700 * - MPC5xx(x)
701 * - MPC8xx(x)
702 * - RCPU (MPC5xx)
704 spr_register(env, SPR_PVR, "PVR",
705 SPR_NOACCESS, SPR_NOACCESS,
706 &spr_read_generic, SPR_NOACCESS,
707 def->pvr);
708 switch (def->pvr & def->pvr_mask) {
709 case CPU_PPC_604: /* PPC 604 */
710 case CPU_PPC_604E: /* PPC 604e */
711 case CPU_PPC_604R: /* PPC 604r */
712 gen_spr_generic(env);
713 gen_spr_ne_601(env);
714 /* Memory management */
715 gen_low_BATs(env);
716 /* Time base */
717 gen_tbl(env);
718 gen_spr_604(env);
719 /* Hardware implementation registers */
720 /* XXX : not implemented */
721 spr_register(env, SPR_HID0, "HID0",
722 SPR_NOACCESS, SPR_NOACCESS,
723 &spr_read_generic, &spr_write_generic,
724 0x00000000);
725 /* XXX : not implemented */
726 spr_register(env, SPR_HID1, "HID1",
727 SPR_NOACCESS, SPR_NOACCESS,
728 &spr_read_generic, &spr_write_generic,
729 0x00000000);
730 break;
732 case CPU_PPC_74x: /* PPC 740 / 750 */
733 case CPU_PPC_74xP: /* PPC 740P / 750P */
734 case CPU_PPC_750CXE: /* IBM PPC 750cxe */
735 gen_spr_generic(env);
736 gen_spr_ne_601(env);
737 /* Memory management */
738 gen_low_BATs(env);
739 /* Time base */
740 gen_tbl(env);
741 gen_spr_7xx(env);
742 /* XXX : not implemented */
743 spr_register(env, SPR_L2CR, "L2CR",
744 SPR_NOACCESS, SPR_NOACCESS,
745 &spr_read_generic, &spr_write_generic,
746 0x00000000);
747 /* Hardware implementation registers */
748 /* XXX : not implemented */
749 spr_register(env, SPR_HID0, "HID0",
750 SPR_NOACCESS, SPR_NOACCESS,
751 &spr_read_generic, &spr_write_generic,
752 0x00000000);
753 /* XXX : not implemented */
754 spr_register(env, SPR_HID1, "HID1",
755 SPR_NOACCESS, SPR_NOACCESS,
756 &spr_read_generic, &spr_write_generic,
757 0x00000000);
758 break;
760 case CPU_PPC_750FX: /* IBM PPC 750 FX */
761 case CPU_PPC_750GX: /* IBM PPC 750 GX */
762 gen_spr_generic(env);
763 gen_spr_ne_601(env);
764 /* Memory management */
765 gen_low_BATs(env);
766 /* PowerPC 750fx & 750gx has 8 DBATs and 8 IBATs */
767 gen_high_BATs(env);
768 /* Time base */
769 gen_tbl(env);
770 gen_spr_7xx(env);
771 /* XXX : not implemented */
772 spr_register(env, SPR_L2CR, "L2CR",
773 SPR_NOACCESS, SPR_NOACCESS,
774 &spr_read_generic, &spr_write_generic,
775 0x00000000);
776 /* Hardware implementation registers */
777 /* XXX : not implemented */
778 spr_register(env, SPR_HID0, "HID0",
779 SPR_NOACCESS, SPR_NOACCESS,
780 &spr_read_generic, &spr_write_generic,
781 0x00000000);
782 /* XXX : not implemented */
783 spr_register(env, SPR_HID1, "HID1",
784 SPR_NOACCESS, SPR_NOACCESS,
785 &spr_read_generic, &spr_write_generic,
786 0x00000000);
787 /* XXX : not implemented */
788 spr_register(env, SPR_750_HID2, "HID2",
789 SPR_NOACCESS, SPR_NOACCESS,
790 &spr_read_generic, &spr_write_generic,
791 0x00000000);
792 break;
794 default:
795 gen_spr_generic(env);
796 break;
798 if (env->nb_BATs == -1)
799 env->nb_BATs = 4;
802 #if defined(PPC_DUMP_CPU)
803 static void dump_sprs (CPUPPCState *env)
805 ppc_spr_t *spr;
806 uint32_t pvr = env->spr[SPR_PVR];
807 uint32_t sr, sw, ur, uw;
808 int i, j, n;
810 printf("* SPRs for PVR=%08x\n", pvr);
811 for (i = 0; i < 32; i++) {
812 for (j = 0; j < 32; j++) {
813 n = (i << 5) | j;
814 spr = &env->spr_cb[n];
815 sw = spr->oea_write != NULL && spr->oea_write != SPR_NOACCESS;
816 sr = spr->oea_read != NULL && spr->oea_read != SPR_NOACCESS;
817 uw = spr->uea_write != NULL && spr->uea_write != SPR_NOACCESS;
818 ur = spr->uea_read != NULL && spr->uea_read != SPR_NOACCESS;
819 if (sw || sr || uw || ur) {
820 printf("%4d (%03x) %8s s%c%c u%c%c\n",
821 (i << 5) | j, (i << 5) | j, spr->name,
822 sw ? 'w' : '-', sr ? 'r' : '-',
823 uw ? 'w' : '-', ur ? 'r' : '-');
827 fflush(stdout);
828 fflush(stderr);
830 #endif
832 /*****************************************************************************/
833 #include <stdlib.h>
834 #include <string.h>
836 int fflush (FILE *stream);
838 /* Opcode types */
839 enum {
840 PPC_DIRECT = 0, /* Opcode routine */
841 PPC_INDIRECT = 1, /* Indirect opcode table */
844 static inline int is_indirect_opcode (void *handler)
846 return ((unsigned long)handler & 0x03) == PPC_INDIRECT;
849 static inline opc_handler_t **ind_table(void *handler)
851 return (opc_handler_t **)((unsigned long)handler & ~3);
854 /* Instruction table creation */
855 /* Opcodes tables creation */
856 static void fill_new_table (opc_handler_t **table, int len)
858 int i;
860 for (i = 0; i < len; i++)
861 table[i] = &invalid_handler;
864 static int create_new_table (opc_handler_t **table, unsigned char idx)
866 opc_handler_t **tmp;
868 tmp = malloc(0x20 * sizeof(opc_handler_t));
869 if (tmp == NULL)
870 return -1;
871 fill_new_table(tmp, 0x20);
872 table[idx] = (opc_handler_t *)((unsigned long)tmp | PPC_INDIRECT);
874 return 0;
877 static int insert_in_table (opc_handler_t **table, unsigned char idx,
878 opc_handler_t *handler)
880 if (table[idx] != &invalid_handler)
881 return -1;
882 table[idx] = handler;
884 return 0;
887 static int register_direct_insn (opc_handler_t **ppc_opcodes,
888 unsigned char idx, opc_handler_t *handler)
890 if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
891 printf("*** ERROR: opcode %02x already assigned in main "
892 "opcode table\n", idx);
893 return -1;
896 return 0;
899 static int register_ind_in_table (opc_handler_t **table,
900 unsigned char idx1, unsigned char idx2,
901 opc_handler_t *handler)
903 if (table[idx1] == &invalid_handler) {
904 if (create_new_table(table, idx1) < 0) {
905 printf("*** ERROR: unable to create indirect table "
906 "idx=%02x\n", idx1);
907 return -1;
909 } else {
910 if (!is_indirect_opcode(table[idx1])) {
911 printf("*** ERROR: idx %02x already assigned to a direct "
912 "opcode\n", idx1);
913 return -1;
916 if (handler != NULL &&
917 insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
918 printf("*** ERROR: opcode %02x already assigned in "
919 "opcode table %02x\n", idx2, idx1);
920 return -1;
923 return 0;
926 static int register_ind_insn (opc_handler_t **ppc_opcodes,
927 unsigned char idx1, unsigned char idx2,
928 opc_handler_t *handler)
930 int ret;
932 ret = register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
934 return ret;
937 static int register_dblind_insn (opc_handler_t **ppc_opcodes,
938 unsigned char idx1, unsigned char idx2,
939 unsigned char idx3, opc_handler_t *handler)
941 if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
942 printf("*** ERROR: unable to join indirect table idx "
943 "[%02x-%02x]\n", idx1, idx2);
944 return -1;
946 if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
947 handler) < 0) {
948 printf("*** ERROR: unable to insert opcode "
949 "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
950 return -1;
953 return 0;
956 static int register_insn (opc_handler_t **ppc_opcodes, opcode_t *insn)
958 if (insn->opc2 != 0xFF) {
959 if (insn->opc3 != 0xFF) {
960 if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
961 insn->opc3, &insn->handler) < 0)
962 return -1;
963 } else {
964 if (register_ind_insn(ppc_opcodes, insn->opc1,
965 insn->opc2, &insn->handler) < 0)
966 return -1;
968 } else {
969 if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0)
970 return -1;
973 return 0;
976 static int test_opcode_table (opc_handler_t **table, int len)
978 int i, count, tmp;
980 for (i = 0, count = 0; i < len; i++) {
981 /* Consistency fixup */
982 if (table[i] == NULL)
983 table[i] = &invalid_handler;
984 if (table[i] != &invalid_handler) {
985 if (is_indirect_opcode(table[i])) {
986 tmp = test_opcode_table(ind_table(table[i]), 0x20);
987 if (tmp == 0) {
988 free(table[i]);
989 table[i] = &invalid_handler;
990 } else {
991 count++;
993 } else {
994 count++;
999 return count;
1002 static void fix_opcode_tables (opc_handler_t **ppc_opcodes)
1004 if (test_opcode_table(ppc_opcodes, 0x40) == 0)
1005 printf("*** WARNING: no opcode defined !\n");
1008 /*****************************************************************************/
1009 static int create_ppc_opcodes (CPUPPCState *env, ppc_def_t *def)
1011 opcode_t *opc, *start, *end;
1013 fill_new_table(env->opcodes, 0x40);
1014 #if defined(PPC_DUMP_CPU)
1015 printf("* PPC instructions for PVR %08x: %s\n", def->pvr, def->name);
1016 #endif
1017 if (&opc_start < &opc_end) {
1018 start = &opc_start;
1019 end = &opc_end;
1020 } else {
1021 start = &opc_end;
1022 end = &opc_start;
1024 for (opc = start + 1; opc != end; opc++) {
1025 if ((opc->handler.type & def->insns_flags) != 0) {
1026 if (register_insn(env->opcodes, opc) < 0) {
1027 printf("*** ERROR initializing PPC instruction "
1028 "0x%02x 0x%02x 0x%02x\n", opc->opc1, opc->opc2,
1029 opc->opc3);
1030 return -1;
1032 #if defined(PPC_DUMP_CPU)
1033 if (opc1 != 0x00) {
1034 if (opc->opc3 == 0xFF) {
1035 if (opc->opc2 == 0xFF) {
1036 printf(" %02x -- -- (%2d ----) : %s\n",
1037 opc->opc1, opc->opc1, opc->oname);
1038 } else {
1039 printf(" %02x %02x -- (%2d %4d) : %s\n",
1040 opc->opc1, opc->opc2, opc->opc1, opc->opc2,
1041 opc->oname);
1043 } else {
1044 printf(" %02x %02x %02x (%2d %4d) : %s\n",
1045 opc->opc1, opc->opc2, opc->opc3,
1046 opc->opc1, (opc->opc3 << 5) | opc->opc2,
1047 opc->oname);
1050 #endif
1053 fix_opcode_tables(env->opcodes);
1054 fflush(stdout);
1055 fflush(stderr);
1057 return 0;
1060 int cpu_ppc_register (CPUPPCState *env, ppc_def_t *def)
1062 env->msr_mask = def->msr_mask;
1063 env->flags = def->flags;
1064 if (create_ppc_opcodes(env, def) < 0) {
1065 printf("Error creating opcodes table\n");
1066 fflush(stdout);
1067 fflush(stderr);
1068 return -1;
1070 init_ppc_proc(env, def);
1071 #if defined(PPC_DUMP_CPU)
1072 dump_sprs(env);
1073 #endif
1074 fflush(stdout);
1075 fflush(stderr);
1077 return 0;
1080 CPUPPCState *cpu_ppc_init(void)
1082 CPUPPCState *env;
1084 env = qemu_mallocz(sizeof(CPUPPCState));
1085 if (!env)
1086 return NULL;
1087 cpu_exec_init(env);
1088 tlb_flush(env, 1);
1089 #if defined (DO_SINGLE_STEP) && 0
1090 /* Single step trace mode */
1091 msr_se = 1;
1092 msr_be = 1;
1093 #endif
1094 msr_fp = 1; /* Allow floating point exceptions */
1095 msr_me = 1; /* Allow machine check exceptions */
1096 #if defined(CONFIG_USER_ONLY)
1097 msr_pr = 1;
1098 #else
1099 env->nip = 0xFFFFFFFC;
1100 #endif
1101 do_compute_hflags(env);
1102 env->reserve = -1;
1103 return env;
1106 void cpu_ppc_close(CPUPPCState *env)
1108 /* Should also remove all opcode tables... */
1109 free(env);
1112 /*****************************************************************************/
1113 /* PowerPC CPU definitions */
1114 static ppc_def_t ppc_defs[] =
1116 /* Embedded PPC */
1117 #if defined (TODO)
1118 /* PPC 401 */
1120 .name = "401",
1121 .pvr = CPU_PPC_401,
1122 .pvr_mask = 0xFFFF0000,
1123 .insns_flags = PPC_INSNS_401,
1124 .flags = PPC_FLAGS_401,
1125 .msr_mask = xxx,
1127 #endif
1128 #if defined (TODO)
1129 /* IOP480 (401 microcontroler) */
1131 .name = "iop480",
1132 .pvr = CPU_PPC_IOP480,
1133 .pvr_mask = 0xFFFF0000,
1134 .insns_flags = PPC_INSNS_401,
1135 .flags = PPC_FLAGS_401,
1136 .msr_mask = xxx,
1138 #endif
1139 #if defined (TODO)
1140 /* PPC 403 GA */
1142 .name = "403ga",
1143 .pvr = CPU_PPC_403GA,
1144 .pvr_mask = 0xFFFFFF00,
1145 .insns_flags = PPC_INSNS_403,
1146 .flags = PPC_FLAGS_403,
1147 .msr_mask = 0x000000000007D23D,
1149 #endif
1150 #if defined (TODO)
1151 /* PPC 403 GB */
1153 .name = "403gb",
1154 .pvr = CPU_PPC_403GB,
1155 .pvr_mask = 0xFFFFFF00,
1156 .insns_flags = PPC_INSNS_403,
1157 .flags = PPC_FLAGS_403,
1158 .msr_mask = 0x000000000007D23D,
1160 #endif
1161 #if defined (TODO)
1162 /* PPC 403 GC */
1164 .name = "403gc",
1165 .pvr = CPU_PPC_403GC,
1166 .pvr_mask = 0xFFFFFF00,
1167 .insns_flags = PPC_INSNS_403,
1168 .flags = PPC_FLAGS_403,
1169 .msr_mask = 0x000000000007D23D,
1171 #endif
1172 #if defined (TODO)
1173 /* PPC 403 GCX */
1175 .name = "403gcx",
1176 .pvr = CPU_PPC_403GCX,
1177 .pvr_mask = 0xFFFFFF00,
1178 .insns_flags = PPC_INSNS_403,
1179 .flags = PPC_FLAGS_403,
1180 .msr_mask = 0x000000000007D23D,
1182 #endif
1183 #if defined (TODO)
1184 /* PPC 405 CR */
1186 .name = "405cr",
1187 .pvr = CPU_PPC_405,
1188 .pvr_mask = 0xFFFF0000,
1189 .insns_flags = PPC_INSNS_405,
1190 .flags = PPC_FLAGS_405,
1191 .msr_mask = 0x00000000020EFF30,
1193 #endif
1194 #if defined (TODO)
1195 /* PPC 405 GP */
1197 .name = "405gp",
1198 .pvr = CPU_PPC_405,
1199 .pvr_mask = 0xFFFF0000,
1200 .insns_flags = PPC_INSNS_405,
1201 .flags = PPC_FLAGS_405,
1202 .msr_mask = 0x00000000020EFF30,
1204 #endif
1205 #if defined (TODO)
1206 /* PPC 405 EP */
1208 .name = "405ep",
1209 .pvr = CPU_PPC_405EP,
1210 .pvr_mask = 0xFFFF0000,
1211 .insns_flags = PPC_INSNS_405,
1212 .flags = PPC_FLAGS_405,
1213 .msr_mask = 0x00000000020EFF30,
1215 #endif
1216 #if defined (TODO)
1217 /* PPC 405 GPR */
1219 .name = "405gpr",
1220 .pvr = CPU_PPC_405GPR,
1221 .pvr_mask = 0xFFFF0000,
1222 .insns_flags = PPC_INSNS_405,
1223 .flags = PPC_FLAGS_405,
1224 .msr_mask = 0x00000000020EFF30,
1226 #endif
1227 #if defined (TODO)
1228 /* PPC 405 D2 */
1230 .name = "405d2",
1231 .pvr = CPU_PPC_405D2,
1232 .pvr_mask = 0xFFFF0000,
1233 .insns_flags = PPC_INSNS_405,
1234 .flags = PPC_FLAGS_405,
1235 .msr_mask = 0x00000000020EFF30,
1237 #endif
1238 #if defined (TODO)
1239 /* PPC 405 D4 */
1241 .name = "405d4",
1242 .pvr = CPU_PPC_405D4,
1243 .pvr_mask = 0xFFFF0000,
1244 .insns_flags = PPC_INSNS_405,
1245 .flags = PPC_FLAGS_405,
1246 .msr_mask = 0x00000000020EFF30,
1248 #endif
1249 #if defined (TODO)
1250 /* Npe405 H */
1252 .name = "Npe405H",
1253 .pvr = CPU_PPC_NPE405H,
1254 .pvr_mask = 0xFFFF0000,
1255 .insns_flags = PPC_INSNS_405,
1256 .flags = PPC_FLAGS_405,
1257 .msr_mask = 0x00000000020EFF30,
1259 #endif
1260 #if defined (TODO)
1261 /* Npe405 L */
1263 .name = "Npe405L",
1264 .pvr = CPU_PPC_NPE405L,
1265 .pvr_mask = 0xFFFF0000,
1266 .insns_flags = PPC_INSNS_405,
1267 .flags = PPC_FLAGS_405,
1268 .msr_mask = 0x00000000020EFF30,
1270 #endif
1271 #if defined (TODO)
1272 /* STB03xx */
1274 .name = "STB03",
1275 .pvr = CPU_PPC_STB03,
1276 .pvr_mask = 0xFFFF0000,
1277 .insns_flags = PPC_INSNS_405,
1278 .flags = PPC_FLAGS_405,
1279 .msr_mask = 0x00000000020EFF30,
1281 #endif
1282 #if defined (TODO)
1283 /* STB04xx */
1285 .name = "STB04",
1286 .pvr = CPU_PPC_STB04,
1287 .pvr_mask = 0xFFFF0000,
1288 .insns_flags = PPC_INSNS_405,
1289 .flags = PPC_FLAGS_405,
1290 .msr_mask = 0x00000000020EFF30,
1292 #endif
1293 #if defined (TODO)
1294 /* STB25xx */
1296 .name = "STB25",
1297 .pvr = CPU_PPC_STB25,
1298 .pvr_mask = 0xFFFF0000,
1299 .insns_flags = PPC_INSNS_405,
1300 .flags = PPC_FLAGS_405,
1301 .msr_mask = 0x00000000020EFF30,
1303 #endif
1304 #if defined (TODO)
1305 /* PPC 440 EP */
1307 .name = "440ep",
1308 .pvr = CPU_PPC_440EP,
1309 .pvr_mask = 0xFFFF0000,
1310 .insns_flags = PPC_INSNS_440,
1311 .flags = PPC_FLAGS_440,
1312 .msr_mask = 0x000000000006D630,
1314 #endif
1315 #if defined (TODO)
1316 /* PPC 440 GP */
1318 .name = "440gp",
1319 .pvr = CPU_PPC_440GP,
1320 .pvr_mask = 0xFFFFFF00,
1321 .insns_flags = PPC_INSNS_440,
1322 .flags = PPC_FLAGS_440,
1323 .msr_mask = 0x000000000006D630,
1325 #endif
1326 #if defined (TODO)
1327 /* PPC 440 GX */
1329 .name = "440gx",
1330 .pvr = CPU_PPC_440GX,
1331 .pvr_mask = 0xFFFF0000,
1332 .insns_flags = PPC_INSNS_405,
1333 .flags = PPC_FLAGS_440,
1334 .msr_mask = 0x000000000006D630,
1336 #endif
1338 /* 32 bits "classic" powerpc */
1339 #if defined (TODO)
1340 /* PPC 601 */
1342 .name = "601",
1343 .pvr = CPU_PPC_601,
1344 .pvr_mask = 0xFFFF0000,
1345 .insns_flags = PPC_INSNS_601,
1346 .flags = PPC_FLAGS_601,
1347 .msr_mask = 0x000000000000FD70,
1349 #endif
1350 #if defined (TODO)
1351 /* PPC 602 */
1353 .name = "602",
1354 .pvr = CPU_PPC_602,
1355 .pvr_mask = 0xFFFF0000,
1356 .insns_flags = PPC_INSNS_602,
1357 .flags = PPC_FLAGS_602,
1358 .msr_mask = 0x0000000000C7FF73,
1360 #endif
1361 #if defined (TODO)
1362 /* PPC 603 */
1364 .name = "603",
1365 .pvr = CPU_PPC_603,
1366 .pvr_mask = 0xFFFF0000,
1367 .insns_flags = PPC_INSNS_603,
1368 .flags = PPC_FLAGS_603,
1369 .msr_mask = 0x000000000007FF73,
1371 #endif
1372 #if defined (TODO)
1373 /* PPC 603e */
1375 .name = "603e",
1376 .pvr = CPU_PPC_603E,
1377 .pvr_mask = 0xFFFF0000,
1378 .insns_flags = PPC_INSNS_603,
1379 .flags = PPC_FLAGS_603,
1380 .msr_mask = 0x000000000007FF73,
1383 .name = "Stretch",
1384 .pvr = CPU_PPC_603E,
1385 .pvr_mask = 0xFFFF0000,
1386 .insns_flags = PPC_INSNS_603,
1387 .flags = PPC_FLAGS_603,
1388 .msr_mask = 0x000000000007FF73,
1390 #endif
1391 #if defined (TODO)
1392 /* PPC 603ev */
1394 .name = "603ev",
1395 .pvr = CPU_PPC_603EV,
1396 .pvr_mask = 0xFFFFF000,
1397 .insns_flags = PPC_INSNS_603,
1398 .flags = PPC_FLAGS_603,
1399 .msr_mask = 0x000000000007FF73,
1401 #endif
1402 #if defined (TODO)
1403 /* PPC 603r */
1405 .name = "603r",
1406 .pvr = CPU_PPC_603R,
1407 .pvr_mask = 0xFFFFF000,
1408 .insns_flags = PPC_INSNS_603,
1409 .flags = PPC_FLAGS_603,
1410 .msr_mask = 0x000000000007FF73,
1413 .name = "Goldeneye",
1414 .pvr = CPU_PPC_603R,
1415 .pvr_mask = 0xFFFFF000,
1416 .insns_flags = PPC_INSNS_603,
1417 .flags = PPC_FLAGS_603,
1418 .msr_mask = 0x000000000007FF73,
1420 #endif
1421 #if defined (TODO)
1422 /* XXX: TODO: according to Motorola UM, this is a derivative to 603e */
1424 .name = "G2",
1425 .pvr = CPU_PPC_G2,
1426 .pvr_mask = 0xFFFF0000,
1427 .insns_flags = PPC_INSNS_G2,
1428 .flags = PPC_FLAGS_G2,
1429 .msr_mask = 0x000000000006FFF2,
1431 { /* Same as G2, with LE mode support */
1432 .name = "G2le",
1433 .pvr = CPU_PPC_G2LE,
1434 .pvr_mask = 0xFFFF0000,
1435 .insns_flags = PPC_INSNS_G2,
1436 .flags = PPC_FLAGS_G2,
1437 .msr_mask = 0x000000000007FFF3,
1439 #endif
1440 /* PPC 604 */
1442 .name = "604",
1443 .pvr = CPU_PPC_604,
1444 .pvr_mask = 0xFFFF0000,
1445 .insns_flags = PPC_INSNS_604,
1446 .flags = PPC_FLAGS_604,
1447 .msr_mask = 0x000000000005FF77,
1449 /* PPC 604e */
1451 .name = "604e",
1452 .pvr = CPU_PPC_604E,
1453 .pvr_mask = 0xFFFF0000,
1454 .insns_flags = PPC_INSNS_604,
1455 .flags = PPC_FLAGS_604,
1456 .msr_mask = 0x000000000005FF77,
1458 /* PPC 604r */
1460 .name = "604r",
1461 .pvr = CPU_PPC_604R,
1462 .pvr_mask = 0xFFFF0000,
1463 .insns_flags = PPC_INSNS_604,
1464 .flags = PPC_FLAGS_604,
1465 .msr_mask = 0x000000000005FF77,
1467 /* generic G3 */
1469 .name = "G3",
1470 .pvr = CPU_PPC_74x,
1471 .pvr_mask = 0xFFFFF000,
1472 .insns_flags = PPC_INSNS_7x0,
1473 .flags = PPC_FLAGS_7x0,
1474 .msr_mask = 0x000000000007FF77,
1476 #if defined (TODO)
1477 /* MPC740 (G3) */
1479 .name = "740",
1480 .pvr = CPU_PPC_74x,
1481 .pvr_mask = 0xFFFFF000,
1482 .insns_flags = PPC_INSNS_7x0,
1483 .flags = PPC_FLAGS_7x0,
1484 .msr_mask = 0x000000000007FF77,
1487 .name = "Arthur",
1488 .pvr = CPU_PPC_74x,
1489 .pvr_mask = 0xFFFFF000,
1490 .insns_flags = PPC_INSNS_7x0,
1491 .flags = PPC_FLAGS_7x0,
1492 .msr_mask = 0x000000000007FF77,
1494 #endif
1495 #if defined (TODO)
1496 /* MPC745 (G3) */
1498 .name = "745",
1499 .pvr = CPU_PPC_74x,
1500 .pvr_mask = 0xFFFFF000,
1501 .insns_flags = PPC_INSNS_7x5,
1502 .flags = PPC_FLAGS_7x5,
1503 .msr_mask = 0x000000000007FF77,
1506 .name = "Goldfinger",
1507 .pvr = CPU_PPC_74x,
1508 .pvr_mask = 0xFFFFF000,
1509 .insns_flags = PPC_INSNS_7x5,
1510 .flags = PPC_FLAGS_7x5,
1511 .msr_mask = 0x000000000007FF77,
1513 #endif
1514 /* MPC750 (G3) */
1516 .name = "750",
1517 .pvr = CPU_PPC_74x,
1518 .pvr_mask = 0xFFFFF000,
1519 .insns_flags = PPC_INSNS_7x0,
1520 .flags = PPC_FLAGS_7x0,
1521 .msr_mask = 0x000000000007FF77,
1523 #if defined (TODO)
1524 /* MPC755 (G3) */
1526 .name = "755",
1527 .pvr = CPU_PPC_755,
1528 .pvr_mask = 0xFFFFF000,
1529 .insns_flags = PPC_INSNS_7x5,
1530 .flags = PPC_FLAGS_7x5,
1531 .msr_mask = 0x000000000007FF77,
1533 #endif
1534 #if defined (TODO)
1535 /* MPC740P (G3) */
1537 .name = "740p",
1538 .pvr = CPU_PPC_74xP,
1539 .pvr_mask = 0xFFFFF000,
1540 .insns_flags = PPC_INSNS_7x0,
1541 .flags = PPC_FLAGS_7x0,
1542 .msr_mask = 0x000000000007FF77,
1545 .name = "Conan/Doyle",
1546 .pvr = CPU_PPC_74xP,
1547 .pvr_mask = 0xFFFFF000,
1548 .insns_flags = PPC_INSNS_7x0,
1549 .flags = PPC_FLAGS_7x0,
1550 .msr_mask = 0x000000000007FF77,
1552 #endif
1553 #if defined (TODO)
1554 /* MPC745P (G3) */
1556 .name = "745p",
1557 .pvr = CPU_PPC_74xP,
1558 .pvr_mask = 0xFFFFF000,
1559 .insns_flags = PPC_INSNS_7x5,
1560 .flags = PPC_FLAGS_7x5,
1561 .msr_mask = 0x000000000007FF77,
1563 #endif
1564 /* MPC750P (G3) */
1566 .name = "750p",
1567 .pvr = CPU_PPC_74xP,
1568 .pvr_mask = 0xFFFFF000,
1569 .insns_flags = PPC_INSNS_7x0,
1570 .flags = PPC_FLAGS_7x0,
1571 .msr_mask = 0x000000000007FF77,
1573 #if defined (TODO)
1574 /* MPC755P (G3) */
1576 .name = "755p",
1577 .pvr = CPU_PPC_74xP,
1578 .pvr_mask = 0xFFFFF000,
1579 .insns_flags = PPC_INSNS_7x5,
1580 .flags = PPC_FLAGS_7x5,
1581 .msr_mask = 0x000000000007FF77,
1583 #endif
1584 /* IBM 750CXe (G3 embedded) */
1586 .name = "750cxe",
1587 .pvr = CPU_PPC_750CXE,
1588 .pvr_mask = 0xFFFFF000,
1589 .insns_flags = PPC_INSNS_7x0,
1590 .flags = PPC_FLAGS_7x0,
1591 .msr_mask = 0x000000000007FF77,
1593 /* IBM 750FX (G3 embedded) */
1595 .name = "750fx",
1596 .pvr = CPU_PPC_750FX,
1597 .pvr_mask = 0xFFFF0000,
1598 .insns_flags = PPC_INSNS_7x0,
1599 .flags = PPC_FLAGS_7x0,
1600 .msr_mask = 0x000000000007FF77,
1602 /* IBM 750GX (G3 embedded) */
1604 .name = "750gx",
1605 .pvr = CPU_PPC_750GX,
1606 .pvr_mask = 0xFFFF0000,
1607 .insns_flags = PPC_INSNS_7x0,
1608 .flags = PPC_FLAGS_7x0,
1609 .msr_mask = 0x000000000007FF77,
1611 #if defined (TODO)
1612 /* generic G4 */
1614 .name = "G4",
1615 .pvr = CPU_PPC_7400,
1616 .pvr_mask = 0xFFFF0000,
1617 .insns_flags = PPC_INSNS_74xx,
1618 .flags = PPC_FLAGS_74xx,
1619 .msr_mask = 0x000000000205FF77,
1621 #endif
1622 #if defined (TODO)
1623 /* PPC 7400 (G4) */
1625 .name = "7400",
1626 .pvr = CPU_PPC_7400,
1627 .pvr_mask = 0xFFFF0000,
1628 .insns_flags = PPC_INSNS_74xx,
1629 .flags = PPC_FLAGS_74xx,
1630 .msr_mask = 0x000000000205FF77,
1633 .name = "Max",
1634 .pvr = CPU_PPC_7400,
1635 .pvr_mask = 0xFFFF0000,
1636 .insns_flags = PPC_INSNS_74xx,
1637 .flags = PPC_FLAGS_74xx,
1638 .msr_mask = 0x000000000205FF77,
1640 #endif
1641 #if defined (TODO)
1642 /* PPC 7410 (G4) */
1644 .name = "7410",
1645 .pvr = CPU_PPC_7410,
1646 .pvr_mask = 0xFFFF0000,
1647 .insns_flags = PPC_INSNS_74xx,
1648 .flags = PPC_FLAGS_74xx,
1649 .msr_mask = 0x000000000205FF77,
1652 .name = "Nitro",
1653 .pvr = CPU_PPC_7410,
1654 .pvr_mask = 0xFFFF0000,
1655 .insns_flags = PPC_INSNS_74xx,
1656 .flags = PPC_FLAGS_74xx,
1657 .msr_mask = 0x000000000205FF77,
1659 #endif
1660 /* XXX: 7441 */
1661 /* XXX: 7445 */
1662 /* XXX: 7447 */
1663 /* XXX: 7447A */
1664 #if defined (TODO)
1665 /* PPC 7450 (G4) */
1667 .name = "7450",
1668 .pvr = CPU_PPC_7450,
1669 .pvr_mask = 0xFFFF0000,
1670 .insns_flags = PPC_INSNS_74xx,
1671 .flags = PPC_FLAGS_74xx,
1672 .msr_mask = 0x000000000205FF77,
1675 .name = "Vger",
1676 .pvr = CPU_PPC_7450,
1677 .pvr_mask = 0xFFFF0000,
1678 .insns_flags = PPC_INSNS_74xx,
1679 .flags = PPC_FLAGS_74xx,
1680 .msr_mask = 0x000000000205FF77,
1682 #endif
1683 /* XXX: 7451 */
1684 #if defined (TODO)
1685 /* PPC 7455 (G4) */
1687 .name = "7455",
1688 .pvr = CPU_PPC_7455,
1689 .pvr_mask = 0xFFFF0000,
1690 .insns_flags = PPC_INSNS_74xx,
1691 .flags = PPC_FLAGS_74xx,
1692 .msr_mask = 0x000000000205FF77,
1695 .name = "Apollo 6",
1696 .pvr = CPU_PPC_7455,
1697 .pvr_mask = 0xFFFF0000,
1698 .insns_flags = PPC_INSNS_74xx,
1699 .flags = PPC_FLAGS_74xx,
1700 .msr_mask = 0x000000000205FF77,
1702 #endif
1703 #if defined (TODO)
1704 /* PPC 7457 (G4) */
1706 .name = "7457",
1707 .pvr = CPU_PPC_7457,
1708 .pvr_mask = 0xFFFF0000,
1709 .insns_flags = PPC_INSNS_74xx,
1710 .flags = PPC_FLAGS_74xx,
1711 .msr_mask = 0x000000000205FF77,
1714 .name = "Apollo 7",
1715 .pvr = CPU_PPC_7457,
1716 .pvr_mask = 0xFFFF0000,
1717 .insns_flags = PPC_INSNS_74xx,
1718 .flags = PPC_FLAGS_74xx,
1719 .msr_mask = 0x000000000205FF77,
1721 #endif
1722 #if defined (TODO)
1723 /* PPC 7457A (G4) */
1725 .name = "7457A",
1726 .pvr = CPU_PPC_7457A,
1727 .pvr_mask = 0xFFFF0000,
1728 .insns_flags = PPC_INSNS_74xx,
1729 .flags = PPC_FLAGS_74xx,
1730 .msr_mask = 0x000000000205FF77,
1733 .name = "Apollo 7 PM",
1734 .pvr = CPU_PPC_7457A,
1735 .pvr_mask = 0xFFFF0000,
1736 .insns_flags = PPC_INSNS_74xx,
1737 .flags = PPC_FLAGS_74xx,
1738 .msr_mask = 0x000000000205FF77,
1740 #endif
1741 /* 64 bits PPC */
1742 #if defined (TODO)
1743 /* PPC 620 */
1745 .name = "620",
1746 .pvr = CPU_PPC_620,
1747 .pvr_mask = 0xFFFF0000,
1748 .insns_flags = PPC_INSNS_620,
1749 .flags = PPC_FLAGS_620,
1750 .msr_mask = 0x800000000005FF73,
1752 #endif
1753 #if defined (TODO)
1754 /* PPC 630 (POWER3) */
1756 .name = "630",
1757 .pvr = CPU_PPC_630,
1758 .pvr_mask = 0xFFFF0000,
1759 .insns_flags = PPC_INSNS_630,
1760 .flags = PPC_FLAGS_630,
1761 .msr_mask = xxx,
1764 .name = "POWER3",
1765 .pvr = CPU_PPC_630,
1766 .pvr_mask = 0xFFFF0000,
1767 .insns_flags = PPC_INSNS_630,
1768 .flags = PPC_FLAGS_630,
1769 .msr_mask = xxx,
1771 #endif
1772 #if defined (TODO)
1773 /* PPC 631 (Power 3+)*/
1775 .name = "631",
1776 .pvr = CPU_PPC_631,
1777 .pvr_mask = 0xFFFF0000,
1778 .insns_flags = PPC_INSNS_631,
1779 .flags = PPC_FLAGS_631,
1780 .msr_mask = xxx,
1783 .name = "POWER3+",
1784 .pvr = CPU_PPC_631,
1785 .pvr_mask = 0xFFFF0000,
1786 .insns_flags = PPC_INSNS_631,
1787 .flags = PPC_FLAGS_631,
1788 .msr_mask = xxx,
1790 #endif
1791 #if defined (TODO)
1792 /* POWER4 */
1794 .name = "POWER4",
1795 .pvr = CPU_PPC_POWER4,
1796 .pvr_mask = 0xFFFF0000,
1797 .insns_flags = PPC_INSNS_POWER4,
1798 .flags = PPC_FLAGS_POWER4,
1799 .msr_mask = xxx,
1801 #endif
1802 #if defined (TODO)
1803 /* POWER4p */
1805 .name = "POWER4+",
1806 .pvr = CPU_PPC_POWER4P,
1807 .pvr_mask = 0xFFFF0000,
1808 .insns_flags = PPC_INSNS_POWER4,
1809 .flags = PPC_FLAGS_POWER4,
1810 .msr_mask = xxx,
1812 #endif
1813 #if defined (TODO)
1814 /* POWER5 */
1816 .name = "POWER5",
1817 .pvr = CPU_PPC_POWER5,
1818 .pvr_mask = 0xFFFF0000,
1819 .insns_flags = PPC_INSNS_POWER5,
1820 .flags = PPC_FLAGS_POWER5,
1821 .msr_mask = xxx,
1823 #endif
1824 #if defined (TODO)
1825 /* POWER5+ */
1827 .name = "POWER5+",
1828 .pvr = CPU_PPC_POWER5P,
1829 .pvr_mask = 0xFFFF0000,
1830 .insns_flags = PPC_INSNS_POWER5,
1831 .flags = PPC_FLAGS_POWER5,
1832 .msr_mask = xxx,
1834 #endif
1835 #if defined (TODO)
1836 /* PPC 970 */
1838 .name = "970",
1839 .pvr = CPU_PPC_970,
1840 .pvr_mask = 0xFFFF0000,
1841 .insns_flags = PPC_INSNS_970,
1842 .flags = PPC_FLAGS_970,
1843 .msr_mask = 0x900000000204FF36,
1845 #endif
1846 #if defined (TODO)
1847 /* PPC 970FX (G5) */
1849 .name = "970fx",
1850 .pvr = CPU_PPC_970FX,
1851 .pvr_mask = 0xFFFF0000,
1852 .insns_flags = PPC_INSNS_970FX,
1853 .flags = PPC_FLAGS_970FX,
1854 .msr_mask = 0x800000000204FF36,
1856 #endif
1857 #if defined (TODO)
1858 /* RS64 (Apache/A35) */
1859 /* This one seems to support the whole POWER2 instruction set
1860 * and the PowerPC 64 one.
1863 .name = "RS64",
1864 .pvr = CPU_PPC_RS64,
1865 .pvr_mask = 0xFFFF0000,
1866 .insns_flags = PPC_INSNS_RS64,
1867 .flags = PPC_FLAGS_RS64,
1868 .msr_mask = xxx,
1871 .name = "Apache",
1872 .pvr = CPU_PPC_RS64,
1873 .pvr_mask = 0xFFFF0000,
1874 .insns_flags = PPC_INSNS_RS64,
1875 .flags = PPC_FLAGS_RS64,
1876 .msr_mask = xxx,
1879 .name = "A35",
1880 .pvr = CPU_PPC_RS64,
1881 .pvr_mask = 0xFFFF0000,
1882 .insns_flags = PPC_INSNS_RS64,
1883 .flags = PPC_FLAGS_RS64,
1884 .msr_mask = xxx,
1886 #endif
1887 #if defined (TODO)
1888 /* RS64-II (NorthStar/A50) */
1890 .name = "RS64-II",
1891 .pvr = CPU_PPC_RS64II,
1892 .pvr_mask = 0xFFFF0000,
1893 .insns_flags = PPC_INSNS_RS64,
1894 .flags = PPC_FLAGS_RS64,
1895 .msr_mask = xxx,
1898 .name = "NortStar",
1899 .pvr = CPU_PPC_RS64II,
1900 .pvr_mask = 0xFFFF0000,
1901 .insns_flags = PPC_INSNS_RS64,
1902 .flags = PPC_FLAGS_RS64,
1903 .msr_mask = xxx,
1906 .name = "A50",
1907 .pvr = CPU_PPC_RS64II,
1908 .pvr_mask = 0xFFFF0000,
1909 .insns_flags = PPC_INSNS_RS64,
1910 .flags = PPC_FLAGS_RS64,
1911 .msr_mask = xxx,
1913 #endif
1914 #if defined (TODO)
1915 /* RS64-III (Pulsar) */
1917 .name = "RS64-III",
1918 .pvr = CPU_PPC_RS64III,
1919 .pvr_mask = 0xFFFF0000,
1920 .insns_flags = PPC_INSNS_RS64,
1921 .flags = PPC_FLAGS_RS64,
1922 .msr_mask = xxx,
1925 .name = "Pulsar",
1926 .pvr = CPU_PPC_RS64III,
1927 .pvr_mask = 0xFFFF0000,
1928 .insns_flags = PPC_INSNS_RS64,
1929 .flags = PPC_FLAGS_RS64,
1930 .msr_mask = xxx,
1932 #endif
1933 #if defined (TODO)
1934 /* RS64-IV (IceStar/IStar/SStar) */
1936 .name = "RS64-IV",
1937 .pvr = CPU_PPC_RS64IV,
1938 .pvr_mask = 0xFFFF0000,
1939 .insns_flags = PPC_INSNS_RS64,
1940 .flags = PPC_FLAGS_RS64,
1941 .msr_mask = xxx,
1944 .name = "IceStar",
1945 .pvr = CPU_PPC_RS64IV,
1946 .pvr_mask = 0xFFFF0000,
1947 .insns_flags = PPC_INSNS_RS64,
1948 .flags = PPC_FLAGS_RS64,
1949 .msr_mask = xxx,
1952 .name = "IStar",
1953 .pvr = CPU_PPC_RS64IV,
1954 .pvr_mask = 0xFFFF0000,
1955 .insns_flags = PPC_INSNS_RS64,
1956 .flags = PPC_FLAGS_RS64,
1957 .msr_mask = xxx,
1960 .name = "SStar",
1961 .pvr = CPU_PPC_RS64IV,
1962 .pvr_mask = 0xFFFF0000,
1963 .insns_flags = PPC_INSNS_RS64,
1964 .flags = PPC_FLAGS_RS64,
1965 .msr_mask = xxx,
1967 #endif
1968 /* POWER */
1969 #if defined (TODO)
1970 /* Original POWER */
1972 .name = "POWER",
1973 .pvr = CPU_POWER,
1974 .pvr_mask = 0xFFFF0000,
1975 .insns_flags = PPC_INSNS_POWER,
1976 .flags = PPC_FLAGS_POWER,
1977 .msr_mask = xxx,
1979 #endif
1980 #if defined (TODO)
1981 /* POWER2 */
1983 .name = "POWER2",
1984 .pvr = CPU_POWER2,
1985 .pvr_mask = 0xFFFF0000,
1986 .insns_flags = PPC_INSNS_POWER,
1987 .flags = PPC_FLAGS_POWER,
1988 .msr_mask = xxx,
1990 #endif
1991 /* Generic PowerPCs */
1992 #if defined (TODO)
1994 .name = "ppc64",
1995 .pvr = CPU_PPC_970,
1996 .pvr_mask = 0xFFFF0000,
1997 .insns_flags = PPC_INSNS_PPC64,
1998 .flags = PPC_FLAGS_PPC64,
1999 .msr_mask = 0xA00000000204FF36,
2001 #endif
2003 .name = "ppc32",
2004 .pvr = CPU_PPC_604,
2005 .pvr_mask = 0xFFFF0000,
2006 .insns_flags = PPC_INSNS_PPC32,
2007 .flags = PPC_FLAGS_PPC32,
2008 .msr_mask = 0x000000000005FF77,
2010 /* Fallback */
2012 .name = "ppc",
2013 .pvr = CPU_PPC_604,
2014 .pvr_mask = 0xFFFF0000,
2015 .insns_flags = PPC_INSNS_PPC32,
2016 .flags = PPC_FLAGS_PPC32,
2017 .msr_mask = 0x000000000005FF77,
2021 int ppc_find_by_name (const unsigned char *name, ppc_def_t **def)
2023 int i, ret;
2025 ret = -1;
2026 *def = NULL;
2027 for (i = 0; strcmp(ppc_defs[i].name, "ppc") != 0; i++) {
2028 if (strcasecmp(name, ppc_defs[i].name) == 0) {
2029 *def = &ppc_defs[i];
2030 ret = 0;
2031 break;
2035 return ret;
2038 int ppc_find_by_pvr (uint32_t pvr, ppc_def_t **def)
2040 int i, ret;
2042 ret = -1;
2043 *def = NULL;
2044 for (i = 0; ppc_defs[i].name != NULL; i++) {
2045 if ((pvr & ppc_defs[i].pvr_mask) ==
2046 (ppc_defs[i].pvr & ppc_defs[i].pvr_mask)) {
2047 *def = &ppc_defs[i];
2048 ret = 0;
2049 break;
2053 return ret;
2056 void ppc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
2058 int i;
2060 for (i = 0; ; i++) {
2061 (*cpu_fprintf)(f, "PowerPC '%s' PVR %08x mask %08x\n",
2062 ppc_defs[i].name,
2063 ppc_defs[i].pvr, ppc_defs[i].pvr_mask);
2064 if (strcmp(ppc_defs[i].name, "ppc") == 0)
2065 break;